Last active
August 29, 2015 14:10
-
-
Save jjgod/a955910ed47aee606474 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 96a780135d15645ae56bbfc09599cb0ddc9aea73 Mon Sep 17 00:00:00 2001 | |
From: Jiang Jiang <[email protected]> | |
Date: Mon, 1 Dec 2014 23:31:55 +0100 | |
Subject: [PATCH] Fix Apple Color Emoji support for OS X 10.7+ | |
BUG=chromium:62435 | |
--- | |
.../Source/platform/fonts/mac/FontCacheMac.mm | 4 -- | |
third_party/skia/src/ports/SkFontHost_mac.cpp | 58 +++++++++++++--------- | |
2 files changed, 34 insertions(+), 28 deletions(-) | |
diff --git a/third_party/WebKit/Source/platform/fonts/mac/FontCacheMac.mm b/third_party/WebKit/Source/platform/fonts/mac/FontCacheMac.mm | |
index 8f8e718..1e5df92 100644 | |
--- a/third_party/WebKit/Source/platform/fonts/mac/FontCacheMac.mm | |
+++ b/third_party/WebKit/Source/platform/fonts/mac/FontCacheMac.mm | |
@@ -129,10 +129,6 @@ PassRefPtr<SimpleFontData> FontCache::fallbackFontForCharacter(const FontDescrip | |
if (!substituteFont) | |
return nullptr; | |
- // Chromium can't render AppleColorEmoji. | |
- if ([[substituteFont familyName] isEqual:@"Apple Color Emoji"]) | |
- return nullptr; | |
- | |
// Use the family name from the AppKit-supplied substitute font, requesting the | |
// traits, weight, and size we want. One way this does better than the original | |
// AppKit request is that it takes synthetic bold and oblique into account. | |
diff --git a/third_party/skia/src/ports/SkFontHost_mac.cpp b/third_party/skia/src/ports/SkFontHost_mac.cpp | |
index dea72c7..c0e1da3 100755 | |
--- a/third_party/skia/src/ports/SkFontHost_mac.cpp | |
+++ b/third_party/skia/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; | |
+} | |
+ | |
// inline versions of these rect helpers | |
static bool CGRectIsEmpty_inline(const CGRect& rect) { | |
@@ -696,6 +701,7 @@ private: | |
bool fGeneratedFBoundingBoxes; | |
const bool fDoSubPosition; | |
const bool fVertical; | |
+ bool fIsColorEmoji; | |
friend class Offscreen; | |
@@ -716,6 +722,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); | |
@@ -804,10 +811,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, | |
@@ -837,8 +846,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); | |
float subX = 0; | |
float subY = 0; | |
@@ -855,9 +864,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 | |
+ // 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; | |
@@ -1156,22 +1175,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 | |
} | |
-#endif | |
template <typename T> T* SkTAddByteOffset(T* ptr, size_t byteOffset) { | |
return (T*)((char*)ptr + byteOffset); | |
@@ -1244,20 +1253,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; | |
@@ -1844,6 +1851,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) { | |
-- | |
2.1.2 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment