Chromium Code Reviews| Index: src/ports/SkFontHost_mac.cpp |
| diff --git a/src/ports/SkFontHost_mac.cpp b/src/ports/SkFontHost_mac.cpp |
| index c19df196b3a9a97b1ff4ad667ff550f44f27d56e..e6ece49af3080c8267b230df0588dfc1f3f4843e 100755 |
| --- a/src/ports/SkFontHost_mac.cpp |
| +++ b/src/ports/SkFontHost_mac.cpp |
| @@ -115,6 +115,11 @@ public: |
| const T* fData; |
| }; |
| +static bool CTFontIsAppleColorEmoji(CTFontRef font) { |
| + AutoCFRelease<CFStringRef> name(CTFontCopyFamilyName(font)); |
| + return CFStringCompare(name.get(), CFSTR("Apple Color Emoji"), 0) == kCFCompareEqualTo; |
|
bungeman-skia
2014/12/04 14:47:14
No way we're doing this (testing by name).
|
| +} |
| + |
| // inline versions of these rect helpers |
| static bool CGRectIsEmpty_inline(const CGRect& rect) { |
| @@ -680,6 +685,7 @@ private: |
| bool fGeneratedFBoundingBoxes; |
| const bool fDoSubPosition; |
| const bool fVertical; |
| + bool fIsColorEmoji; |
| friend class Offscreen; |
| @@ -700,6 +706,7 @@ SkScalerContext_Mac::SkScalerContext_Mac(SkTypeface_Mac* typeface, |
| CFIndex numGlyphs = CTFontGetGlyphCount(ctFont); |
| SkASSERT(numGlyphs >= 1 && numGlyphs <= 0xFFFF); |
| fGlyphCount = SkToU16(numGlyphs); |
| + fIsColorEmoji = CTFontIsAppleColorEmoji(ctFont); |
| SkMatrix skTransform; |
| fRec.getSingleMatrixWithoutTextSize(&skTransform); |
| @@ -788,10 +795,12 @@ CGRGBPixel* Offscreen::getCG(const SkScalerContext_Mac& context, const SkGlyph& |
| CGContextSetAllowsFontSubpixelQuantization(fCG, false); |
| CGContextSetShouldSubpixelQuantizeFonts(fCG, false); |
| - CGContextSetTextDrawingMode(fCG, kCGTextFill); |
| - CGContextSetFont(fCG, context.fCGFont); |
| - CGContextSetFontSize(fCG, CTFontGetSize(context.fCTFont)); |
| - CGContextSetTextMatrix(fCG, CTFontGetMatrix(context.fCTFont)); |
| + if (!context.fIsColorEmoji) { |
| + CGContextSetTextDrawingMode(fCG, kCGTextFill); |
| + CGContextSetFont(fCG, context.fCGFont); |
| + CGContextSetFontSize(fCG, CTFontGetSize(context.fCTFont)); |
| + CGContextSetTextMatrix(fCG, CTFontGetMatrix(context.fCTFont)); |
| + } |
| // Because CG always draws from the horizontal baseline, |
| // if there is a non-integral translation from the horizontal origin to the vertical origin, |
| @@ -821,8 +830,8 @@ CGRGBPixel* Offscreen::getCG(const SkScalerContext_Mac& context, const SkGlyph& |
| // skip rows based on the glyph's height |
| image += (fSize.fHeight - glyph.fHeight) * fSize.fWidth; |
| - // erase to black |
| - sk_memset_rect32(image, 0, glyph.fWidth, glyph.fHeight, rowBytes); |
| + // erase to black or white. |
| + sk_memset_rect32(image, context.fIsColorEmoji ? 0xFFFFFFFF : 0, glyph.fWidth, glyph.fHeight, rowBytes); |
|
bungeman-skia
2014/12/04 14:47:13
We cannot make the background opaque.
|
| float subX = 0; |
| float subY = 0; |
| @@ -839,9 +848,19 @@ CGRGBPixel* Offscreen::getCG(const SkScalerContext_Mac& context, const SkGlyph& |
| subY += offset.fY; |
| } |
| - CGContextShowGlyphsAtPoint(fCG, -glyph.fLeft + subX, |
| - glyph.fTop + glyph.fHeight - subY, |
| - &glyphID, 1); |
| + CGPoint pos = CGPointMake(-glyph.fLeft + subX, glyph.fTop + glyph.fHeight - subY); |
| + if (context.fIsColorEmoji) { |
| + CGContextSaveGState(fCG); |
| + // CGContextSetTextMatrix does not work with color glyphs, so we use the |
|
bungeman-skia
2014/12/04 14:47:13
This isn't quite true, what happens is CoreText wo
|
| + // CTM instead. This means we must translate the CTM as well, to set the |
| + // glyph position, instead of using CGContextSetTextPosition. |
| + CGContextConcatCTM(fCG, CTFontGetMatrix(context.fCTFont)); |
| + CGContextTranslateCTM(fCG, pos.x, pos.y); |
| + CTFontDrawGlyphs(context.fCTFont, &glyphID, &CGPointZero, 1, fCG); |
| + CGContextRestoreGState(fCG); |
| + } else { |
| + CGContextShowGlyphsAtPoint(fCG, pos.x, pos.y, &glyphID, 1); |
| + } |
| SkASSERT(rowBytesPtr); |
| *rowBytesPtr = rowBytes; |
| @@ -1140,22 +1159,12 @@ static void rgb_to_lcd16(const CGRGBPixel* SK_RESTRICT cgPixels, size_t cgRowByt |
| } |
| } |
| -#ifdef HACK_COLORGLYPHS |
| -// hack to colorize the output for testing kARGB32_Format |
| -static SkPMColor cgpixels_to_pmcolor(CGRGBPixel rgb, const SkGlyph& glyph, |
| - int x, int y) { |
| +static SkPMColor cgpixels_to_pmcolor(CGRGBPixel rgb) { |
| U8CPU r = (rgb >> 16) & 0xFF; |
| U8CPU g = (rgb >> 8) & 0xFF; |
| U8CPU b = (rgb >> 0) & 0xFF; |
| - unsigned a = SkComputeLuminance(r, g, b); |
| - |
| - // compute gradient from x,y |
| - r = x * 255 / glyph.fWidth; |
| - g = 0; |
| - b = (glyph.fHeight - y) * 255 / glyph.fHeight; |
| - return SkPreMultiplyARGB(a, r, g, b); // red |
| + return SkPreMultiplyARGB(0xFF, r, g, b); // red |
|
bungeman-skia
2014/12/04 14:47:13
We cannot make these opaque, transparency must be
|
| } |
| -#endif |
| template <typename T> T* SkTAddByteOffset(T* ptr, size_t byteOffset) { |
| return (T*)((char*)ptr + byteOffset); |
| @@ -1228,20 +1237,18 @@ void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) { |
| dst += dstRB; |
| } |
| } break; |
| -#ifdef HACK_COLORGLYPHS |
| case SkMask::kARGB32_Format: { |
| const int width = glyph.fWidth; |
| size_t dstRB = glyph.rowBytes(); |
| SkPMColor* dst = (SkPMColor*)glyph.fImage; |
| for (int y = 0; y < glyph.fHeight; y++) { |
| for (int x = 0; x < width; ++x) { |
| - dst[x] = cgpixels_to_pmcolor(cgPixels[x], glyph, x, y); |
| + dst[x] = cgpixels_to_pmcolor(cgPixels[x]); |
| } |
| cgPixels = (CGRGBPixel*)((char*)cgPixels + cgRowBytes); |
| dst = (SkPMColor*)((char*)dst + dstRB); |
| } |
| } break; |
| -#endif |
| default: |
| SkDEBUGFAIL("unexpected mask format"); |
| break; |
| @@ -1828,6 +1835,9 @@ void SkTypeface_Mac::onFilterRec(SkScalerContextRec* rec) const { |
| } |
| } |
| + if (CTFontIsAppleColorEmoji(fFontRef.get())) |
| + rec->fMaskFormat = SkMask::kARGB32_Format; |
| + |
| // Unhinted A8 masks (those not derived from LCD masks) must respect SK_GAMMA_APPLY_TO_A8. |
| // All other masks can use regular gamma. |
| if (SkMask::kA8_Format == rec->fMaskFormat && SkPaint::kNo_Hinting == hinting) { |