Skip to content

Instantly share code, notes, and snippets.

@jjgod
Last active August 29, 2015 14:10
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jjgod/a955910ed47aee606474 to your computer and use it in GitHub Desktop.
Save jjgod/a955910ed47aee606474 to your computer and use it in GitHub Desktop.
From 96a780135d15645ae56bbfc09599cb0ddc9aea73 Mon Sep 17 00:00:00 2001
From: Jiang Jiang <gzjjgod@gmail.com>
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