Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(773)

Unified Diff: src/ports/SkFontHost_mac.cpp

Issue 770383002: Replace use of deprecated CG methods. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Add expectations. Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/core/SkScalerContext.cpp ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/ports/SkFontHost_mac.cpp
diff --git a/src/ports/SkFontHost_mac.cpp b/src/ports/SkFontHost_mac.cpp
index c19df196b3a9a97b1ff4ad667ff550f44f27d56e..0d4bbb73d97a10437547f540091ba017ad006396 100755
--- a/src/ports/SkFontHost_mac.cpp
+++ b/src/ports/SkFontHost_mac.cpp
@@ -25,6 +25,7 @@
#include "SkFontDescriptor.h"
#include "SkFloatingPoint.h"
#include "SkGlyph.h"
+#include "SkLazyFnPtr.h"
#include "SkMaskGamma.h"
#include "SkSFNTHeader.h"
#include "SkOTTable_glyf.h"
@@ -43,7 +44,7 @@
#include "SkFontMgr.h"
#include "SkUtils.h"
-//#define HACK_COLORGLYPHS
+#include <dlfcn.h>
class SkScalerContext_Mac;
@@ -273,7 +274,6 @@ static CGAffineTransform MatrixToCGAffineTransform(const SkMatrix& matrix,
///////////////////////////////////////////////////////////////////////////////
#define BITMAP_INFO_RGB (kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host)
-#define BITMAP_INFO_GRAY (kCGImageAlphaNone)
/**
* There does not appear to be a publicly accessable API for determining if lcd
@@ -304,7 +304,14 @@ static bool supports_LCD() {
class Offscreen {
public:
- Offscreen();
+ Offscreen()
+ : fRGBSpace(NULL)
+ , fCG(NULL)
+ , fDoAA(false)
+ , fDoLCD(false)
+ {
+ fSize.set(0, 0);
+ }
CGRGBPixel* getCG(const SkScalerContext_Mac& context, const SkGlyph& glyph,
CGGlyph glyphID, size_t* rowBytesPtr,
@@ -328,11 +335,6 @@ private:
}
};
-Offscreen::Offscreen() : fRGBSpace(NULL), fCG(NULL),
- fDoAA(false), fDoLCD(false) {
- fSize.set(0, 0);
-}
-
///////////////////////////////////////////////////////////////////////////////
static bool find_dict_float(CFDictionaryRef dict, CFStringRef name, float* value) {
@@ -440,8 +442,21 @@ public:
, fRequestedName(requestedName)
, fFontRef(fontRef) // caller has already called CFRetain for us
, fIsLocalStream(isLocalStream)
+ , fHasSbixTable(false)
{
SkASSERT(fontRef);
+
+ AutoCFRelease<CFArrayRef> tags(CTFontCopyAvailableTables(fFontRef,kCTFontTableOptionNoOptions));
+ if (tags) {
+ int count = SkToInt(CFArrayGetCount(tags));
+ for (int i = 0; i < count; ++i) {
+ uintptr_t tag = reinterpret_cast<uintptr_t>(CFArrayGetValueAtIndex(tags, i));
+ if ('sbix' == tag) {
+ fHasSbixTable = true;
+ break;
+ }
+ }
+ }
}
SkString fRequestedName;
@@ -469,6 +484,7 @@ protected:
private:
bool fIsLocalStream;
+ bool fHasSbixTable;
typedef SkTypeface INHERITED;
};
@@ -663,6 +679,7 @@ private:
Offscreen fOffscreen;
AutoCFRelease<CTFontRef> fCTFont;
+ CGAffineTransform fInvTransform;
/** Vertical variant of fCTFont.
*
@@ -701,9 +718,14 @@ SkScalerContext_Mac::SkScalerContext_Mac(SkTypeface_Mac* typeface,
SkASSERT(numGlyphs >= 1 && numGlyphs <= 0xFFFF);
fGlyphCount = SkToU16(numGlyphs);
+ // CT on (at least) 10.9 will size color glyphs down from the requested size, but not up.
+ // As a result, it is necessary to know the actual device size and request that.
+ SkVector scale;
SkMatrix skTransform;
- fRec.getSingleMatrixWithoutTextSize(&skTransform);
+ fRec.computeMatrices(SkScalerContextRec::kVertical_PreMatrixScale, &scale, &skTransform,
+ NULL, NULL, &fFUnitMatrix);
CGAffineTransform transform = MatrixToCGAffineTransform(skTransform);
+ fInvTransform = CGAffineTransformInvert(transform);
AutoCFRelease<CTFontDescriptorRef> ctFontDesc;
if (fVertical) {
@@ -722,13 +744,7 @@ SkScalerContext_Mac::SkScalerContext_Mac(SkTypeface_Mac* typeface,
// The transform contains everything except the requested text size.
// Some properties, like 'trak', are based on the text size (before applying the matrix).
- CGFloat textSize = ScalarToCG(fRec.fTextSize);
-
- // If a text size of 0 is requested, CoreGraphics will use 12 instead.
- // If the text size is 0, set it to something tiny.
- if (textSize < CGFLOAT_MIN) {
- textSize = CGFLOAT_MIN;
- }
+ CGFloat textSize = ScalarToCG(scale.y());
fCTFont.reset(CTFontCreateCopyWithAttributes(ctFont, textSize, &transform, ctFontDesc));
fCGFont.reset(CTFontCopyGraphicsFont(fCTFont, NULL));
@@ -739,14 +755,39 @@ SkScalerContext_Mac::SkScalerContext_Mac(SkTypeface_Mac* typeface,
}
// The fUnitMatrix includes the text size (and em) as it is used to scale the raw font data.
- fRec.getSingleMatrix(&fFUnitMatrix);
SkScalar emPerFUnit = SkScalarInvert(SkIntToScalar(CGFontGetUnitsPerEm(fCGFont)));
fFUnitMatrix.preScale(emPerFUnit, -emPerFUnit);
}
+extern "C" {
+
+/** CTFontDrawGlyphs was introduced in 10.7. */
+typedef void (*CTFontDrawGlyphsProc)(CTFontRef, const CGGlyph[], const CGPoint[],
+ size_t, CGContextRef);
+
+/** This is an implementation of CTFontDrawGlyphs for 10.6. */
+static void sk_legacy_CTFontDrawGlyphs(CTFontRef, const CGGlyph glyphs[], const CGPoint points[],
+ size_t count, CGContextRef cg)
+{
+ CGContextShowGlyphsAtPositions(cg, glyphs, points, count);
+}
+
+}
+
+CTFontDrawGlyphsProc SkChooseCTFontDrawGlyphs() {
+ CTFontDrawGlyphsProc realCTFontDrawGlyphs;
+ *reinterpret_cast<void**>(&realCTFontDrawGlyphs) = dlsym(RTLD_DEFAULT, "CTFontDrawGlyphs");
+ return realCTFontDrawGlyphs ? realCTFontDrawGlyphs : sk_legacy_CTFontDrawGlyphs;
+};
+
+SK_DECLARE_STATIC_LAZY_FN_PTR(CTFontDrawGlyphsProc, gCTFontDrawGlyphs, SkChooseCTFontDrawGlyphs);
+
CGRGBPixel* Offscreen::getCG(const SkScalerContext_Mac& context, const SkGlyph& glyph,
CGGlyph glyphID, size_t* rowBytesPtr,
- bool generateA8FromLCD) {
+ bool generateA8FromLCD)
+{
+ CTFontDrawGlyphsProc ctFontDrawGlyphs = gCTFontDrawGlyphs.get();
+
if (!fRGBSpace) {
//It doesn't appear to matter what color space is specified.
//Regular blends and antialiased text are always (s*a + d*(1-a))
@@ -769,6 +810,13 @@ CGRGBPixel* Offscreen::getCG(const SkScalerContext_Mac& context, const SkGlyph&
doAA = true;
}
+ // If this font might have color glyphs, disable LCD as there's no way to support it.
+ // CoreText doesn't tell us which format it ended up using, so we can't detect it.
+ // A8 will be ugly too (white on transparent), but TODO: we can detect gray and set to A8.
+ if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
+ doLCD = false;
+ }
+
size_t rowBytes = fSize.fWidth * sizeof(CGRGBPixel);
if (!fCG || fSize.fWidth < glyph.fWidth || fSize.fHeight < glyph.fHeight) {
if (fSize.fWidth < glyph.fWidth) {
@@ -780,24 +828,25 @@ CGRGBPixel* Offscreen::getCG(const SkScalerContext_Mac& context, const SkGlyph&
rowBytes = fSize.fWidth * sizeof(CGRGBPixel);
void* image = fImageStorage.reset(rowBytes * fSize.fHeight);
+ const CGImageAlphaInfo alpha = (SkMask::kARGB32_Format == glyph.fMaskFormat)
+ ? kCGImageAlphaPremultipliedFirst
+ : kCGImageAlphaNoneSkipFirst;
+ const CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host | alpha;
fCG.reset(CGBitmapContextCreate(image, fSize.fWidth, fSize.fHeight, 8,
- rowBytes, fRGBSpace, BITMAP_INFO_RGB));
+ rowBytes, fRGBSpace, bitmapInfo));
- // skia handles quantization itself, so we disable this for cg to get
- // full fractional data from them.
+ // Skia handles quantization and subpixel positioning,
+ // so disable quantization and enabe subpixel positioning in CG.
CGContextSetAllowsFontSubpixelQuantization(fCG, false);
CGContextSetShouldSubpixelQuantizeFonts(fCG, false);
- 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,
// then CG cannot draw the glyph in the correct location without subpixel positioning.
- CGContextSetAllowsFontSubpixelPositioning(fCG, context.fDoSubPosition || context.fVertical);
- CGContextSetShouldSubpixelPositionFonts(fCG, context.fDoSubPosition || context.fVertical);
+ CGContextSetAllowsFontSubpixelPositioning(fCG, true);
+ CGContextSetShouldSubpixelPositionFonts(fCG, true);
+
+ CGContextSetTextDrawingMode(fCG, kCGTextFill);
// Draw white on black to create mask.
// TODO: Draw black on white and invert, CG has a special case codepath.
@@ -806,6 +855,14 @@ CGRGBPixel* Offscreen::getCG(const SkScalerContext_Mac& context, const SkGlyph&
// force our checks below to happen
fDoAA = !doAA;
fDoLCD = !doLCD;
+
+ if (sk_legacy_CTFontDrawGlyphs == ctFontDrawGlyphs) {
+ // CTFontDrawGlyphs will apply the font, font size, and font matrix to the CGContext.
+ // Our 'fake' one does not, so set up the CGContext here.
+ CGContextSetFont(fCG, context.fCGFont);
+ CGContextSetFontSize(fCG, CTFontGetSize(context.fCTFont));
+ CGContextSetTextMatrix(fCG, CTFontGetMatrix(context.fCTFont));
+ }
}
if (fDoAA != doAA) {
@@ -831,7 +888,7 @@ CGRGBPixel* Offscreen::getCG(const SkScalerContext_Mac& context, const SkGlyph&
subY = SkFixedToFloat(glyph.getSubYFixed());
}
- // CGContextShowGlyphsAtPoint always draws using the horizontal baseline origin.
+ // CoreText and CoreGraphics always draw using the horizontal baseline origin.
if (context.fVertical) {
SkPoint offset;
context.getVerticalOffset(glyphID, &offset);
@@ -839,9 +896,12 @@ CGRGBPixel* Offscreen::getCG(const SkScalerContext_Mac& context, const SkGlyph&
subY += offset.fY;
}
- CGContextShowGlyphsAtPoint(fCG, -glyph.fLeft + subX,
- glyph.fTop + glyph.fHeight - subY,
- &glyphID, 1);
+ // CTFontDrawGlyphs and CGContextShowGlyphsAtPositions take 'positions' which are in text space.
+ // The glyph location (in device space) must be mapped into text space, so that CG can convert
+ // it back into device space.
+ CGPoint point = CGPointMake(-glyph.fLeft + subX, glyph.fTop + glyph.fHeight - subY);
+ point = CGPointApplyAffineTransform(point, context.fInvTransform);
+ ctFontDrawGlyphs(context.fCTFont, &glyphID, &point, 1, fCG);
SkASSERT(rowBytesPtr);
*rowBytesPtr = rowBytes;
@@ -1045,10 +1105,6 @@ void SkScalerContext_Mac::generateMetrics(SkGlyph* glyph) {
glyph->fTop = SkToS16(skIBounds.fTop);
glyph->fWidth = SkToU16(skIBounds.width());
glyph->fHeight = SkToU16(skIBounds.height());
-
-#ifdef HACK_COLORGLYPHS
- glyph->fMaskFormat = SkMask::kARGB32_Format;
-#endif
}
#include "SkColorPriv.h"
@@ -1140,22 +1196,14 @@ 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 a = (rgb >> 24) & 0xFF;
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 SkPackARGB32(a, r, g, b);
}
-#endif
template <typename T> T* SkTAddByteOffset(T* ptr, size_t byteOffset) {
return (T*)((char*)ptr + byteOffset);
@@ -1228,20 +1276,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 +1874,13 @@ void SkTypeface_Mac::onFilterRec(SkScalerContextRec* rec) const {
}
}
+ // CoreText provides no information as to whether a glyph will be color or not.
+ // Fonts may mix outlines and bitmaps, so information is needed on a glyph by glyph basis.
+ // If a font contains an 'sbix' table, consider it to be a color font, and disable lcd.
+ if (fHasSbixTable) {
+ 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) {
« no previous file with comments | « src/core/SkScalerContext.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698