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) { |