| Index: src/ports/SkFontHost_mac.cpp
|
| ===================================================================
|
| --- src/ports/SkFontHost_mac.cpp (revision 9039)
|
| +++ src/ports/SkFontHost_mac.cpp (working copy)
|
| @@ -44,6 +44,7 @@
|
| #include "SkFontMgr.h"
|
|
|
| //#define HACK_COLORGLYPHS
|
| +//#define SK_IGNORE_MAC_TEXT_BOUNDS_FIX
|
|
|
| class SkScalerContext_Mac;
|
|
|
| @@ -124,12 +125,14 @@
|
| return rect.size.width <= 0 || rect.size.height <= 0;
|
| }
|
|
|
| +#if defined(SK_IGNORE_MAC_TEXT_BOUNDS_FIX)
|
| static void CGRectInset_inline(CGRect* rect, CGFloat dx, CGFloat dy) {
|
| rect->origin.x += dx;
|
| rect->origin.y += dy;
|
| rect->size.width -= dx * 2;
|
| rect->size.height -= dy * 2;
|
| }
|
| +#endif
|
|
|
| static CGFloat CGRectGetMinX_inline(const CGRect& rect) {
|
| return rect.origin.x;
|
| @@ -251,10 +254,6 @@
|
| return darwin_version;
|
| }
|
|
|
| -static bool isLeopard() {
|
| - return darwinVersion() == 9;
|
| -}
|
| -
|
| static bool isSnowLeopard() {
|
| return darwinVersion() == 10;
|
| }
|
| @@ -300,10 +299,12 @@
|
| ScalarToCG(matrix[SkMatrix::kMTransY] * sy));
|
| }
|
|
|
| +#if defined(SK_IGNORE_MAC_TEXT_BOUNDS_FIX)
|
| static SkScalar getFontScale(CGFontRef cgFont) {
|
| int unitsPerEm = CGFontGetUnitsPerEm(cgFont);
|
| return SkScalarInvert(SkIntToScalar(unitsPerEm));
|
| }
|
| +#endif
|
|
|
| ///////////////////////////////////////////////////////////////////////////////
|
|
|
| @@ -530,13 +531,7 @@
|
| CTFontDescriptorCreateWithAttributes(cfAttributes));
|
|
|
| if (ctFontDesc != NULL) {
|
| - if (isLeopard()) {
|
| - // CTFontCreateWithFontDescriptor on Leopard ignores the name
|
| - AutoCFRelease<CTFontRef> ctNamed(CTFontCreateWithName(cfFontName, 1, NULL));
|
| - ctFont = CTFontCreateCopyWithAttributes(ctNamed, 1, NULL, ctFontDesc);
|
| - } else {
|
| - ctFont = CTFontCreateWithFontDescriptor(ctFontDesc, 0, NULL);
|
| - }
|
| + ctFont = CTFontCreateWithFontDescriptor(ctFontDesc, 0, NULL);
|
| }
|
| }
|
|
|
| @@ -648,13 +643,16 @@
|
| return face;
|
| }
|
|
|
| +#if defined(SK_IGNORE_MAC_TEXT_BOUNDS_FIX)
|
| static void flip(SkMatrix* matrix) {
|
| matrix->setSkewX(-matrix->getSkewX());
|
| matrix->setSkewY(-matrix->getSkewY());
|
| }
|
| +#endif
|
|
|
| ///////////////////////////////////////////////////////////////////////////////
|
|
|
| +/** GlyphRect is in FUnits (em space, y up). */
|
| struct GlyphRect {
|
| int16_t fMinX;
|
| int16_t fMinY;
|
| @@ -665,9 +663,7 @@
|
| class SkScalerContext_Mac : public SkScalerContext {
|
| public:
|
| SkScalerContext_Mac(SkTypeface_Mac*, const SkDescriptor*);
|
| - virtual ~SkScalerContext_Mac();
|
|
|
| -
|
| protected:
|
| unsigned generateGlyphCount(void) SK_OVERRIDE;
|
| uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE;
|
| @@ -679,26 +675,72 @@
|
|
|
| private:
|
| static void CTPathElement(void *info, const CGPathElement *element);
|
| +
|
| +#if defined(SK_IGNORE_MAC_TEXT_BOUNDS_FIX)
|
| + void getVerticalOffset(CGGlyph glyphID, SkIPoint* offset) const;
|
| +#else
|
| + /** Returns the offset from the horizontal origin to the vertical origin in SkGlyph units. */
|
| + void getVerticalOffset(CGGlyph glyphID, SkPoint* offset) const;
|
| +#endif
|
| +
|
| + /** Initializes and returns the value of fFBoundingBoxesGlyphOffset.
|
| + *
|
| + * For use with (and must be called before) generateBBoxes.
|
| + */
|
| uint16_t getFBoundingBoxesGlyphOffset();
|
| - void getVerticalOffset(CGGlyph glyphID, SkIPoint* offset) const;
|
| +
|
| + /** Initializes fFBoundingBoxes and returns true on success.
|
| + *
|
| + * On Lion and Mountain Lion, CTFontGetBoundingRectsForGlyphs has a bug which causes it to
|
| + * return a bad value in bounds.origin.x for SFNT fonts whose hhea::numberOfHMetrics is
|
| + * less than its maxp::numGlyphs. When this is the case we try to read the bounds from the
|
| + * font directly.
|
| + *
|
| + * This routine initializes fFBoundingBoxes to an array of
|
| + * fGlyphCount - fFBoundingBoxesGlyphOffset GlyphRects which contain the bounds in FUnits
|
| + * (em space, y up) of glyphs with ids in the range [fFBoundingBoxesGlyphOffset, fGlyphCount).
|
| + *
|
| + * Returns true if fFBoundingBoxes is properly initialized. The table can only be properly
|
| + * initialized for a TrueType font with 'head', 'loca', and 'glyf' tables.
|
| + *
|
| + * TODO: A future optimization will compute fFBoundingBoxes once per fCTFont.
|
| + */
|
| bool generateBBoxes();
|
|
|
| - CGAffineTransform fTransform;
|
| - SkMatrix fUnitMatrix; // without font size
|
| - SkMatrix fVerticalMatrix; // unit rotated
|
| - SkMatrix fMatrix; // with font size
|
| - SkMatrix fFBoundingBoxesMatrix; // lion-specific fix
|
| + /** Converts from FUnits (em space, y up) to SkGlyph units (pixels, y down).
|
| + *
|
| + * Used on Snow Leopard to correct CTFontGetVerticalTranslationsForGlyphs.
|
| + * Used on Lion to correct CTFontGetBoundingRectsForGlyphs.
|
| + */
|
| + SkMatrix fFUnitMatrix;
|
| +
|
| Offscreen fOffscreen;
|
| AutoCFRelease<CTFontRef> fCTFont;
|
| - AutoCFRelease<CTFontRef> fCTVerticalFont; // for vertical advance
|
| +
|
| + /** Vertical variant of fCTFont.
|
| + *
|
| + * CT vertical metrics are pre-rotated (in em space, before transform) 90deg clock-wise.
|
| + * This makes kCTFontDefaultOrientation dangerous, because the metrics from
|
| + * kCTFontHorizontalOrientation are in a different space from kCTFontVerticalOrientation.
|
| + * Use fCTVerticalFont with kCTFontVerticalOrientation to get metrics in the same space.
|
| + */
|
| + AutoCFRelease<CTFontRef> fCTVerticalFont;
|
| +
|
| AutoCFRelease<CGFontRef> fCGFont;
|
| - GlyphRect* fFBoundingBoxes;
|
| + SkAutoTMalloc<GlyphRect> fFBoundingBoxes;
|
| uint16_t fFBoundingBoxesGlyphOffset;
|
| uint16_t fGlyphCount;
|
| bool fGeneratedFBoundingBoxes;
|
| - bool fDoSubPosition;
|
| - bool fVertical;
|
| + const bool fDoSubPosition;
|
| + const bool fVertical;
|
|
|
| +#if defined(SK_IGNORE_MAC_TEXT_BOUNDS_FIX)
|
| + SkMatrix fVerticalMatrix; // unit rotated
|
| + SkMatrix fMatrix; // with font size
|
| + SkMatrix fFBoundingBoxesMatrix; // lion-specific fix
|
| + SkMatrix fUnitMatrix; // without font size
|
| +#endif
|
| +
|
| friend class Offscreen;
|
|
|
| typedef SkScalerContext INHERITED;
|
| @@ -707,39 +749,33 @@
|
| SkScalerContext_Mac::SkScalerContext_Mac(SkTypeface_Mac* typeface,
|
| const SkDescriptor* desc)
|
| : INHERITED(typeface, desc)
|
| - , fFBoundingBoxes(NULL)
|
| + , fFBoundingBoxes()
|
| , fFBoundingBoxesGlyphOffset(0)
|
| , fGeneratedFBoundingBoxes(false)
|
| + , fDoSubPosition(SkToBool(fRec.fFlags & kSubpixelPositioning_Flag))
|
| + , fVertical(SkToBool(fRec.fFlags & kVertical_Flag))
|
| +
|
| {
|
| CTFontRef ctFont = typeface->fFontRef.get();
|
| CFIndex numGlyphs = CTFontGetGlyphCount(ctFont);
|
| -
|
| + SkASSERT(numGlyphs >= 1 && numGlyphs <= 0xFFFF);
|
| + fGlyphCount = SkToU16(numGlyphs);
|
| +
|
| +#if defined(SK_IGNORE_MAC_TEXT_BOUNDS_FIX)
|
| // Get the state we need
|
| fRec.getSingleMatrix(&fMatrix);
|
| - fUnitMatrix = fMatrix;
|
| + CGAffineTransform transform = MatrixToCGAffineTransform(fMatrix);
|
|
|
| // extract the font size out of the matrix, but leave the skewing for italic
|
| SkScalar reciprocal = SkScalarInvert(fRec.fTextSize);
|
| + fUnitMatrix = fMatrix;
|
| fUnitMatrix.preScale(reciprocal, reciprocal);
|
| + flip(&fUnitMatrix); // flip to fix up bounds later
|
| +#else
|
| + fRec.getSingleMatrix(&fFUnitMatrix);
|
| + CGAffineTransform transform = MatrixToCGAffineTransform(fFUnitMatrix);
|
| +#endif
|
|
|
| - SkASSERT(numGlyphs >= 1 && numGlyphs <= 0xFFFF);
|
| -
|
| - fTransform = MatrixToCGAffineTransform(fMatrix);
|
| -
|
| - CGAffineTransform transform;
|
| - CGFloat unitFontSize;
|
| - if (isLeopard()) {
|
| - // passing 1 for pointSize to Leopard sets the font size to 1 pt.
|
| - // pass the CoreText size explicitly
|
| - transform = MatrixToCGAffineTransform(fUnitMatrix);
|
| - unitFontSize = SkScalarToFloat(fRec.fTextSize);
|
| - } else {
|
| - // since our matrix includes everything, we pass 1 for pointSize
|
| - transform = fTransform;
|
| - unitFontSize = 1;
|
| - }
|
| - flip(&fUnitMatrix); // flip to fix up bounds later
|
| - fVertical = SkToBool(fRec.fFlags & kVertical_Flag);
|
| AutoCFRelease<CTFontDescriptorRef> ctFontDesc;
|
| if (fVertical) {
|
| AutoCFRelease<CFMutableDictionaryRef> cfAttributes(CFDictionaryCreateMutable(
|
| @@ -754,12 +790,14 @@
|
| ctFontDesc = CTFontDescriptorCreateWithAttributes(cfAttributes);
|
| }
|
| }
|
| - fCTFont = CTFontCreateCopyWithAttributes(ctFont, unitFontSize, &transform, ctFontDesc);
|
| + // Since our matrix includes everything, we pass 1 for size.
|
| + fCTFont = CTFontCreateCopyWithAttributes(ctFont, 1, &transform, ctFontDesc);
|
| fCGFont = CTFontCopyGraphicsFont(fCTFont, NULL);
|
| if (fVertical) {
|
| CGAffineTransform rotateLeft = CGAffineTransformMake(0, -1, 1, 0, 0, 0);
|
| transform = CGAffineTransformConcat(rotateLeft, transform);
|
| - fCTVerticalFont = CTFontCreateCopyWithAttributes(ctFont, unitFontSize, &transform, NULL);
|
| + fCTVerticalFont = CTFontCreateCopyWithAttributes(ctFont, 1, &transform, NULL);
|
| +#if defined(SK_IGNORE_MAC_TEXT_BOUNDS_FIX)
|
| fVerticalMatrix = fUnitMatrix;
|
| if (isSnowLeopard()) {
|
| SkScalar scale = SkScalarMul(fRec.fTextSize, getFontScale(fCGFont));
|
| @@ -768,15 +806,15 @@
|
| fVerticalMatrix.preRotate(SkIntToScalar(90));
|
| }
|
| fVerticalMatrix.postScale(SK_Scalar1, -SK_Scalar1);
|
| +#endif
|
| }
|
| - fGlyphCount = SkToU16(numGlyphs);
|
| - fDoSubPosition = SkToBool(fRec.fFlags & kSubpixelPositioning_Flag);
|
| +#if defined(SK_IGNORE_MAC_TEXT_BOUNDS_FIX)
|
| +#else
|
| + SkScalar emPerFUnit = SkScalarInvert(SkIntToScalar(CGFontGetUnitsPerEm(fCGFont)));
|
| + fFUnitMatrix.preScale(emPerFUnit, -emPerFUnit);
|
| +#endif
|
| }
|
|
|
| -SkScalerContext_Mac::~SkScalerContext_Mac() {
|
| - delete[] fFBoundingBoxes;
|
| -}
|
| -
|
| CGRGBPixel* Offscreen::getCG(const SkScalerContext_Mac& context, const SkGlyph& glyph,
|
| CGGlyph glyphID, size_t* rowBytesPtr,
|
| bool generateA8FromLCD) {
|
| @@ -823,11 +861,19 @@
|
|
|
| CGContextSetTextDrawingMode(fCG, kCGTextFill);
|
| CGContextSetFont(fCG, context.fCGFont);
|
| - CGContextSetFontSize(fCG, 1);
|
| - CGContextSetTextMatrix(fCG, context.fTransform);
|
| + CGContextSetFontSize(fCG, 1 /*CTFontGetSize(context.fCTFont)*/);
|
| + CGContextSetTextMatrix(fCG, CTFontGetMatrix(context.fCTFont));
|
|
|
| +#if defined(SK_IGNORE_MAC_TEXT_BOUNDS_FIX)
|
| CGContextSetAllowsFontSubpixelPositioning(fCG, context.fDoSubPosition);
|
| CGContextSetShouldSubpixelPositionFonts(fCG, context.fDoSubPosition);
|
| +#else
|
| + // 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);
|
| +#endif
|
|
|
| // Draw white on black to create mask.
|
| // TODO: Draw black on white and invert, CG has a special case codepath.
|
| @@ -860,12 +906,19 @@
|
| subX = SkFixedToFloat(glyph.getSubXFixed());
|
| subY = SkFixedToFloat(glyph.getSubYFixed());
|
| }
|
| +
|
| + // CGContextShowGlyphsAtPoint always draws using the horizontal baseline origin.
|
| if (context.fVertical) {
|
| +#if defined(SK_IGNORE_MAC_TEXT_BOUNDS_FIX)
|
| SkIPoint offset;
|
| +#else
|
| + SkPoint offset;
|
| +#endif
|
| context.getVerticalOffset(glyphID, &offset);
|
| subX += offset.fX;
|
| subY += offset.fY;
|
| }
|
| +
|
| CGContextShowGlyphsAtPoint(fCG, -glyph.fLeft + subX,
|
| glyph.fTop + glyph.fHeight - subY,
|
| &glyphID, 1);
|
| @@ -875,6 +928,7 @@
|
| return image;
|
| }
|
|
|
| +#if defined(SK_IGNORE_MAC_TEXT_BOUNDS_FIX)
|
| void SkScalerContext_Mac::getVerticalOffset(CGGlyph glyphID, SkIPoint* offset) const {
|
| CGSize vertOffset;
|
| CTFontGetVerticalTranslationsForGlyphs(fCTVerticalFont, &glyphID, &vertOffset, 1);
|
| @@ -892,7 +946,26 @@
|
| offset->fX = SkScalarRound(floatOffset.fX);
|
| offset->fY = SkScalarRound(floatOffset.fY);
|
| }
|
| +#else
|
| +void SkScalerContext_Mac::getVerticalOffset(CGGlyph glyphID, SkPoint* offset) const {
|
| + // Snow Leopard returns cgVertOffset in completely un-transformed FUnits (em space, y up).
|
| + // Lion and Leopard return cgVertOffset in CG units (pixels, y up).
|
| + CGSize cgVertOffset;
|
| + CTFontGetVerticalTranslationsForGlyphs(fCTFont, &glyphID, &cgVertOffset, 1);
|
|
|
| + SkPoint skVertOffset = { CGToScalar(cgVertOffset.width), CGToScalar(cgVertOffset.height) };
|
| + if (isSnowLeopard()) {
|
| + // From FUnits (em space, y up) to SkGlyph units (pixels, y down).
|
| + fFUnitMatrix.mapPoints(&skVertOffset, 1);
|
| + } else {
|
| + // From CG units (pixels, y up) to SkGlyph units (pixels, y down).
|
| + skVertOffset.fY = -skVertOffset.fY;
|
| + }
|
| +
|
| + *offset = skVertOffset;
|
| +}
|
| +#endif
|
| +
|
| uint16_t SkScalerContext_Mac::getFBoundingBoxesGlyphOffset() {
|
| if (fFBoundingBoxesGlyphOffset) {
|
| return fFBoundingBoxesGlyphOffset;
|
| @@ -905,20 +978,9 @@
|
| return fFBoundingBoxesGlyphOffset;
|
| }
|
|
|
| -/*
|
| - * Lion has a bug in CTFontGetBoundingRectsForGlyphs which returns a bad value
|
| - * in theBounds.origin.x for fonts whose numOfLogHorMetrics is less than its
|
| - * glyph count. This workaround reads the glyph bounds from the font directly.
|
| - *
|
| - * The table is computed only if the font is a TrueType font, if the glyph
|
| - * value is >= fFBoundingBoxesGlyphOffset. (called only if fFBoundingBoxesGlyphOffset < fGlyphCount).
|
| - *
|
| - * TODO: A future optimization will compute fFBoundingBoxes once per CGFont, and
|
| - * compute fFBoundingBoxesMatrix once per font context.
|
| - */
|
| bool SkScalerContext_Mac::generateBBoxes() {
|
| if (fGeneratedFBoundingBoxes) {
|
| - return NULL != fFBoundingBoxes;
|
| + return NULL != fFBoundingBoxes.get();
|
| }
|
| fGeneratedFBoundingBoxes = true;
|
|
|
| @@ -938,7 +1000,7 @@
|
| }
|
|
|
| uint16_t entries = fGlyphCount - fFBoundingBoxesGlyphOffset;
|
| - fFBoundingBoxes = new GlyphRect[entries];
|
| + fFBoundingBoxes.reset(entries);
|
|
|
| SkOTTableHead::IndexToLocFormat locaFormat = headTable->indexToLocFormat;
|
| SkOTTableGlyph::Iterator glyphDataIter(*glyfTable.fData, *locaTable.fData, locaFormat);
|
| @@ -951,10 +1013,12 @@
|
| rect.fMaxX = SkEndian_SwapBE16(glyphData->xMax);
|
| rect.fMaxY = SkEndian_SwapBE16(glyphData->yMax);
|
| }
|
| +#if defined(SK_IGNORE_MAC_TEXT_BOUNDS_FIX)
|
| fFBoundingBoxesMatrix = fMatrix;
|
| flip(&fFBoundingBoxesMatrix);
|
| SkScalar fontScale = getFontScale(fCGFont);
|
| fFBoundingBoxesMatrix.preScale(fontScale, fontScale);
|
| +#endif
|
| return true;
|
| }
|
|
|
| @@ -984,6 +1048,7 @@
|
| this->generateMetrics(glyph);
|
| }
|
|
|
| +#if defined(SK_IGNORE_MAC_TEXT_BOUNDS_FIX)
|
| void SkScalerContext_Mac::generateMetrics(SkGlyph* glyph) {
|
| CGSize advance;
|
| CGRect bounds;
|
| @@ -1032,21 +1097,6 @@
|
| return;
|
| }
|
|
|
| - if (isLeopard() && !fVertical) {
|
| - // Leopard does not consider the matrix skew in its bounds.
|
| - // Run the bounding rectangle through the skew matrix to determine
|
| - // the true bounds. However, this doesn't work if the font is vertical.
|
| - // FIXME (Leopard): If the font has synthetic italic (e.g., matrix skew)
|
| - // and the font is vertical, the bounds need to be recomputed.
|
| - SkRect glyphBounds = SkRect::MakeXYWH(
|
| - bounds.origin.x, bounds.origin.y,
|
| - bounds.size.width, bounds.size.height);
|
| - fUnitMatrix.mapRect(&glyphBounds);
|
| - bounds.origin.x = glyphBounds.fLeft;
|
| - bounds.origin.y = glyphBounds.fTop;
|
| - bounds.size.width = glyphBounds.width();
|
| - bounds.size.height = glyphBounds.height();
|
| - }
|
| // Adjust the bounds
|
| //
|
| // CTFontGetBoundingRectsForGlyphs ignores the font transform, so we need
|
| @@ -1088,7 +1138,119 @@
|
| glyph->fMaskFormat = SkMask::kARGB32_Format;
|
| #endif
|
| }
|
| +#else
|
| +void SkScalerContext_Mac::generateMetrics(SkGlyph* glyph) {
|
| + const CGGlyph cgGlyph = (CGGlyph) glyph->getGlyphID(fBaseGlyphCount);
|
| + glyph->zeroMetrics();
|
| +
|
| + // The following block produces cgAdvance in CG units (pixels, y up).
|
| + CGSize cgAdvance;
|
| + if (fVertical) {
|
| + CTFontGetAdvancesForGlyphs(fCTVerticalFont, kCTFontVerticalOrientation,
|
| + &cgGlyph, &cgAdvance, 1);
|
| + } else {
|
| + CTFontGetAdvancesForGlyphs(fCTFont, kCTFontHorizontalOrientation,
|
| + &cgGlyph, &cgAdvance, 1);
|
| + }
|
| + glyph->fAdvanceX = SkFloatToFixed_Check(cgAdvance.width);
|
| + glyph->fAdvanceY = -SkFloatToFixed_Check(cgAdvance.height);
|
|
|
| + // The following produces skBounds in SkGlyph units (pixels, y down),
|
| + // or returns early if skBounds would be empty.
|
| + SkRect skBounds;
|
| +
|
| + // On Mountain Lion, CTFontGetBoundingRectsForGlyphs with kCTFontVerticalOrientation and
|
| + // CTFontGetVerticalTranslationsForGlyphs do not agree when using OTF CFF fonts.
|
| + // For TTF fonts these two do agree and we can use CTFontGetBoundingRectsForGlyphs to get
|
| + // the bounding box and CTFontGetVerticalTranslationsForGlyphs to then draw the glyph
|
| + // inside that bounding box. However, with OTF CFF fonts this does not work. It appears that
|
| + // CTFontGetBoundingRectsForGlyphs with kCTFontVerticalOrientation on OTF CFF fonts tries
|
| + // to center the glyph along the vertical baseline and also perform some mysterious shift
|
| + // along the baseline. CTFontGetVerticalTranslationsForGlyphs does not appear to perform
|
| + // these steps.
|
| + //
|
| + // It is not known which is correct (or if either is correct). However, we must always draw
|
| + // from the horizontal origin and must use CTFontGetVerticalTranslationsForGlyphs to draw.
|
| + // As a result, we do not call CTFontGetBoundingRectsForGlyphs for vertical glyphs.
|
| +
|
| + // On Snow Leopard, CTFontGetBoundingRectsForGlyphs ignores kCTFontVerticalOrientation and
|
| + // returns horizontal bounds.
|
| +
|
| + // On Lion and Mountain Lion, CTFontGetBoundingRectsForGlyphs has a bug which causes it to
|
| + // return a bad value in cgBounds.origin.x for SFNT fonts whose hhea::numberOfHMetrics is
|
| + // less than its maxp::numGlyphs. When this is the case we try to read the bounds from the
|
| + // font directly.
|
| + if ((isLion() || isMountainLion()) &&
|
| + (cgGlyph < fGlyphCount && cgGlyph >= getFBoundingBoxesGlyphOffset() && generateBBoxes()))
|
| + {
|
| + const GlyphRect& gRect = fFBoundingBoxes[cgGlyph - fFBoundingBoxesGlyphOffset];
|
| + if (gRect.fMinX >= gRect.fMaxX || gRect.fMinY >= gRect.fMaxY) {
|
| + return;
|
| + }
|
| + skBounds = SkRect::MakeLTRB(gRect.fMinX, gRect.fMinY, gRect.fMaxX, gRect.fMaxY);
|
| + // From FUnits (em space, y up) to SkGlyph units (pixels, y down).
|
| + fFUnitMatrix.mapRect(&skBounds);
|
| +
|
| + } else {
|
| + // CTFontGetBoundingRectsForGlyphs produces cgBounds in CG units (pixels, y up).
|
| + CGRect cgBounds;
|
| + CTFontGetBoundingRectsForGlyphs(fCTFont, kCTFontHorizontalOrientation,
|
| + &cgGlyph, &cgBounds, 1);
|
| +
|
| + // BUG?
|
| + // 0x200B (zero-advance space) seems to return a huge (garbage) bounds, when
|
| + // it should be empty. So, if we see a zero-advance, we check if it has an
|
| + // empty path or not, and if so, we jam the bounds to 0. Hopefully a zero-advance
|
| + // is rare, so we won't incur a big performance cost for this extra check.
|
| + if (0 == cgAdvance.width && 0 == cgAdvance.height) {
|
| + AutoCFRelease<CGPathRef> path(CTFontCreatePathForGlyph(fCTFont, cgGlyph, NULL));
|
| + if (NULL == path || CGPathIsEmpty(path)) {
|
| + return;
|
| + }
|
| + }
|
| +
|
| + if (CGRectIsEmpty_inline(cgBounds)) {
|
| + return;
|
| + }
|
| +
|
| + // Convert cgBounds to SkGlyph units (pixels, y down).
|
| + skBounds = SkRect::MakeXYWH(cgBounds.origin.x, -cgBounds.origin.y - cgBounds.size.height,
|
| + cgBounds.size.width, cgBounds.size.height);
|
| + }
|
| +
|
| + if (fVertical) {
|
| + // Due to all of the vertical bounds bugs, skBounds is always the horizontal bounds.
|
| + // Convert these horizontal bounds into vertical bounds.
|
| + SkPoint offset;
|
| + getVerticalOffset(cgGlyph, &offset);
|
| + skBounds.offset(offset);
|
| + }
|
| +
|
| + // Currently the bounds are based on being rendered at (0,0).
|
| + // The top left must not move, since that is the base from which subpixel positioning is offset.
|
| + if (fDoSubPosition) {
|
| + skBounds.fRight += SkFixedToFloat(glyph->getSubXFixed());
|
| + skBounds.fBottom += SkFixedToFloat(glyph->getSubYFixed());
|
| + }
|
| +
|
| + SkIRect skIBounds;
|
| + skBounds.roundOut(&skIBounds);
|
| + // Expand the bounds by 1 pixel, to give CG room for anti-aliasing.
|
| + // Note that this outset is to allow room for LCD smoothed glyphs. However, the correct outset
|
| + // is not currently known, as CG dilates the outlines by some percentage.
|
| + // Note that if this context is A8 and not back-forming from LCD, there is no need to outset.
|
| + skIBounds.outset(1, 1);
|
| + glyph->fLeft = SkToS16(skIBounds.fLeft);
|
| + glyph->fTop = SkToS16(skIBounds.fTop);
|
| + glyph->fWidth = SkToU16(skIBounds.width());
|
| + glyph->fHeight = SkToU16(skIBounds.height());
|
| +
|
| +#ifdef HACK_COLORGLYPHS
|
| + glyph->fMaskFormat = SkMask::kARGB32_Format;
|
| +#endif
|
| +}
|
| +
|
| +#endif
|
| #include "SkColorPriv.h"
|
|
|
| static void build_power_table(uint8_t table[], float ee) {
|
| @@ -1371,17 +1533,23 @@
|
| CGPathApply(cgPath, path, SkScalerContext_Mac::CTPathElement);
|
| }
|
|
|
| - if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) {
|
| + if (fDoSubPosition) {
|
| SkMatrix m;
|
| m.setScale(SkScalarInvert(scaleX), SkScalarInvert(scaleY));
|
| path->transform(m);
|
| // balance the call to CTFontCreateCopyWithAttributes
|
| CFSafeRelease(font);
|
| }
|
| - if (fRec.fFlags & SkScalerContext::kVertical_Flag) {
|
| + if (fVertical) {
|
| +#if defined(SK_IGNORE_MAC_TEXT_BOUNDS_FIX)
|
| SkIPoint offset;
|
| getVerticalOffset(cgGlyph, &offset);
|
| path->offset(SkIntToScalar(offset.fX), SkIntToScalar(offset.fY));
|
| +#else
|
| + SkPoint offset;
|
| + getVerticalOffset(cgGlyph, &offset);
|
| + path->offset(offset.fX, offset.fY);
|
| +#endif
|
| }
|
| }
|
|
|
|
|