Bug 1287552 - part 2 - fix transformed bitmaps with Skia and FreeType. r?gw280 draft
authorLee Salzman <lsalzman@mozilla.com>
Mon, 18 Jul 2016 15:27:44 -0400
changeset 389230 a9a8957855f5d7cee90e0a092a6e96d924e1ba1b
parent 389229 b19518a894db6b1bb11e22cd665352833a407cb9
child 389231 e06a9c344ab47d427925833c3fbb64b3721c0dd3
child 390167 7e0dfa9f663a098ef2670c3d363a9b51c856aa96
push id23325
push userbmo:lsalzman@mozilla.com
push dateMon, 18 Jul 2016 19:31:04 +0000
reviewersgw280
bugs1287552
milestone50.0a1
Bug 1287552 - part 2 - fix transformed bitmaps with Skia and FreeType. r?gw280 MozReview-Commit-ID: BqiLfOfZZwR
gfx/skia/skia/src/ports/SkFontHost_FreeType.cpp
gfx/skia/skia/src/ports/SkFontHost_FreeType_common.cpp
--- a/gfx/skia/skia/src/ports/SkFontHost_FreeType.cpp
+++ b/gfx/skia/skia/src/ports/SkFontHost_FreeType.cpp
@@ -1158,29 +1158,36 @@ void SkScalerContext_FreeType::generateM
         }
         break;
 
       case FT_GLYPH_FORMAT_BITMAP:
         if (fRec.fFlags & SkScalerContext::kVertical_Flag) {
             FT_Vector vector;
             vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.horiBearingX;
             vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.horiBearingY;
-            FT_Vector_Transform(&vector, &fMatrix22);
             fFace->glyph->bitmap_left += SkFDot6Floor(vector.x);
             fFace->glyph->bitmap_top  += SkFDot6Floor(vector.y);
         }
 
         if (fFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) {
             glyph->fMaskFormat = SkMask::kARGB32_Format;
         }
 
-        glyph->fWidth   = SkToU16(fFace->glyph->bitmap.width);
-        glyph->fHeight  = SkToU16(fFace->glyph->bitmap.rows);
-        glyph->fTop     = -SkToS16(fFace->glyph->bitmap_top);
-        glyph->fLeft    = SkToS16(fFace->glyph->bitmap_left);
+        SkRect srcRect = SkRect::MakeXYWH(
+            SkIntToScalar(face->glyph->bitmap_left),
+            -SkIntToScalar(face->glyph->bitmap_top),
+            SkIntToScalar(face->glyph->bitmap.width),
+            SkIntToScalar(face->glyph->bitmap.rows));
+        SkRect destRect;
+        fMatrix22Scalar.mapRect(&destRect, srcRect);
+        SkIRect glyphRect = destRect.roundOut();
+        glyph->fWidth  = SkToU16(glyphRect.width());
+        glyph->fHeight = SkToU16(glyphRect.height());
+        glyph->fTop    = SkToS16(SkScalarRoundToInt(destRect.fTop));
+        glyph->fLeft   = SkToS16(SkScalarRoundToInt(destRect.fLeft));
         break;
 
       default:
         SkDEBUGFAIL("unknown glyph format");
         glyph->zeroMetrics();
         return;
     }
 
--- a/gfx/skia/skia/src/ports/SkFontHost_FreeType_common.cpp
+++ b/gfx/skia/skia/src/ports/SkFontHost_FreeType_common.cpp
@@ -397,26 +397,22 @@ void SkScalerContext_FreeType_Base::gene
                      FT_PIXEL_MODE_BGRA == pixel_mode);
 
             // These are the only formats this ScalerContext should request.
             SkASSERT(SkMask::kBW_Format == maskFormat ||
                      SkMask::kA8_Format == maskFormat ||
                      SkMask::kARGB32_Format == maskFormat ||
                      SkMask::kLCD16_Format == maskFormat);
 
-            if (fRec.fFlags & SkScalerContext::kEmbolden_Flag &&
-                !(face->style_flags & FT_STYLE_FLAG_BOLD))
-            {
-                FT_GlyphSlot_Own_Bitmap(face->glyph);
-                FT_Bitmap_Embolden(face->glyph->library, &face->glyph->bitmap,
-                                   kBitmapEmboldenStrength, 0);
-            }
-
-            // If no scaling needed, directly copy glyph bitmap.
-            if (glyph.fWidth == face->glyph->bitmap.width &&
+            // If no skew or scaling needed, directly copy glyph bitmap.
+            bool skewed = fRec.fPreSkewX != 0 ||
+                          fRec.fPost2x2[0][1] != 0 ||
+                          fRec.fPost2x2[1][0] != 0;
+            if (!skewed &&
+                glyph.fWidth == face->glyph->bitmap.width &&
                 glyph.fHeight == face->glyph->bitmap.rows &&
                 glyph.fTop == -face->glyph->bitmap_top &&
                 glyph.fLeft == face->glyph->bitmap_left)
             {
                 SkMask dstMask;
                 glyph.toMask(&dstMask);
                 copyFTBitmap(face->glyph->bitmap, dstMask);
                 break;
@@ -455,18 +451,32 @@ void SkScalerContext_FreeType_Base::gene
                 dstBitmap.allocPixels();
             } else {
                 dstBitmap.setPixels(glyph.fImage);
             }
 
             // Scale unscaledBitmap into dstBitmap.
             SkCanvas canvas(dstBitmap);
             canvas.clear(SK_ColorTRANSPARENT);
-            canvas.scale(SkIntToScalar(glyph.fWidth) / SkIntToScalar(face->glyph->bitmap.width),
-                         SkIntToScalar(glyph.fHeight) / SkIntToScalar(face->glyph->bitmap.rows));
+            if (skewed) {
+                // Apply any transforms with the bitmap placed at (0, 0).
+                SkMatrix matrix;
+                fRec.getSingleMatrix(&matrix);
+                SkRect srcRect = SkRect::MakeIWH(face->glyph->bitmap.width, face->glyph->bitmap.rows);
+                SkRect destRect;
+                matrix.mapRect(&destRect, srcRect);
+                matrix.postTranslate(-destRect.fLeft, -destRect.fTop);
+                // Rescale to the glyph's actual size.
+                matrix.postScale(SkIntToScalar(glyph.fWidth) / destRect.width(),
+                                 SkIntToScalar(glyph.fHeight) / destRect.height());
+                canvas.setMatrix(matrix);
+            } else {
+                canvas.scale(SkIntToScalar(glyph.fWidth) / SkIntToScalar(face->glyph->bitmap.width),
+                             SkIntToScalar(glyph.fHeight) / SkIntToScalar(face->glyph->bitmap.rows));
+            }
             SkPaint paint;
             paint.setFilterQuality(kMedium_SkFilterQuality);
             canvas.drawBitmap(unscaledBitmap, 0, 0, &paint);
 
             // If the destination is BW or LCD, convert from A8.
             if (SkMask::kBW_Format == maskFormat) {
                 // Copy the A8 dstBitmap into the A1 glyph.fImage.
                 SkMask dstMask;