Chromium Code Reviews| Index: src/ports/SkFontHost_mac.cpp |
| =================================================================== |
| --- src/ports/SkFontHost_mac.cpp (revision 9039) |
| +++ src/ports/SkFontHost_mac.cpp (working copy) |
| @@ -648,11 +648,6 @@ |
| return face; |
| } |
| -static void flip(SkMatrix* matrix) { |
| - matrix->setSkewX(-matrix->getSkewX()); |
| - matrix->setSkewY(-matrix->getSkewY()); |
| -} |
| - |
| /////////////////////////////////////////////////////////////////////////////// |
| struct GlyphRect { |
| @@ -684,20 +679,17 @@ |
| bool generateBBoxes(); |
| CGAffineTransform fTransform; |
| - SkMatrix fUnitMatrix; // without font size |
| - SkMatrix fVerticalMatrix; // unit rotated |
| SkMatrix fMatrix; // with font size |
| SkMatrix fFBoundingBoxesMatrix; // lion-specific fix |
| Offscreen fOffscreen; |
| AutoCFRelease<CTFontRef> fCTFont; |
| - AutoCFRelease<CTFontRef> fCTVerticalFont; // for vertical advance |
| AutoCFRelease<CGFontRef> fCGFont; |
| GlyphRect* fFBoundingBoxes; |
| uint16_t fFBoundingBoxesGlyphOffset; |
| uint16_t fGlyphCount; |
| bool fGeneratedFBoundingBoxes; |
| - bool fDoSubPosition; |
| - bool fVertical; |
| + const bool fDoSubPosition; |
| + const bool fVertical; |
| friend class Offscreen; |
| @@ -710,36 +702,18 @@ |
| , fFBoundingBoxes(NULL) |
| , 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); |
| - |
| - // Get the state we need |
| + SkASSERT(numGlyphs >= 1 && numGlyphs <= 0xFFFF); |
| + fGlyphCount = SkToU16(numGlyphs); |
| + |
| fRec.getSingleMatrix(&fMatrix); |
| - fUnitMatrix = fMatrix; |
| - |
| - // extract the font size out of the matrix, but leave the skewing for italic |
| - SkScalar reciprocal = SkScalarInvert(fRec.fTextSize); |
| - fUnitMatrix.preScale(reciprocal, reciprocal); |
| - |
| - 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,23 +728,9 @@ |
| ctFontDesc = CTFontDescriptorCreateWithAttributes(cfAttributes); |
| } |
| } |
| - fCTFont = CTFontCreateCopyWithAttributes(ctFont, unitFontSize, &transform, ctFontDesc); |
| + // Since our matrix includes everything, we pass 1 for size. |
| + fCTFont = CTFontCreateCopyWithAttributes(ctFont, 1.f, &fTransform, 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); |
| - fVerticalMatrix = fUnitMatrix; |
| - if (isSnowLeopard()) { |
| - SkScalar scale = SkScalarMul(fRec.fTextSize, getFontScale(fCGFont)); |
| - fVerticalMatrix.preScale(scale, scale); |
| - } else { |
| - fVerticalMatrix.preRotate(SkIntToScalar(90)); |
| - } |
| - fVerticalMatrix.postScale(SK_Scalar1, -SK_Scalar1); |
| - } |
| - fGlyphCount = SkToU16(numGlyphs); |
| - fDoSubPosition = SkToBool(fRec.fFlags & kSubpixelPositioning_Flag); |
| } |
| SkScalerContext_Mac::~SkScalerContext_Mac() { |
| @@ -860,12 +820,16 @@ |
| subX = SkFixedToFloat(glyph.getSubXFixed()); |
| subY = SkFixedToFloat(glyph.getSubYFixed()); |
| } |
| + |
| + // CGContextShowGlyphsAtPoint always draws using the horizontal baseline origin. |
| + // Get the offset from the vertical origin to the horizontal origin. |
| if (context.fVertical) { |
| SkIPoint offset; |
| context.getVerticalOffset(glyphID, &offset); |
| subX += offset.fX; |
| subY += offset.fY; |
| } |
| + |
| CGContextShowGlyphsAtPoint(fCG, -glyph.fLeft + subX, |
| glyph.fTop + glyph.fHeight - subY, |
| &glyphID, 1); |
| @@ -877,20 +841,18 @@ |
| void SkScalerContext_Mac::getVerticalOffset(CGGlyph glyphID, SkIPoint* offset) const { |
| CGSize vertOffset; |
| - CTFontGetVerticalTranslationsForGlyphs(fCTVerticalFont, &glyphID, &vertOffset, 1); |
| - const SkPoint trans = {CGToScalar(vertOffset.width), |
| - CGToScalar(vertOffset.height)}; |
| - SkPoint floatOffset; |
| - fVerticalMatrix.mapPoints(&floatOffset, &trans, 1); |
| - if (!isSnowLeopard()) { |
| - // SnowLeopard fails to apply the font's matrix to the vertical metrics, |
| - // but Lion and Leopard do. The unit matrix describes the font's matrix at |
| - // point size 1. There may be some way to avoid mapping here by setting up |
| - // fVerticalMatrix differently, but this works for now. |
| - fUnitMatrix.mapPoints(&floatOffset, 1); |
| + CTFontGetVerticalTranslationsForGlyphs(fCTFont, &glyphID, &vertOffset, 1); |
| + |
| + // SnowLeopard returns vertOffset in completely un-transformed em units. |
| + // Lion and Leopard return vertOffset in transformed font units. |
| + if (isSnowLeopard()) { |
| + CGFloat emPerUnit = 1.0f / CGFontGetUnitsPerEm(fCGFont); |
| + CGAffineTransform t = CGAffineTransformConcat(fTransform, CGAffineTransformMakeScale(emPerUnit, emPerUnit)); |
| + vertOffset = CGSizeApplyAffineTransform(vertOffset, t); |
| } |
| - offset->fX = SkScalarRound(floatOffset.fX); |
| - offset->fY = SkScalarRound(floatOffset.fY); |
| + |
| + offset->fX = SkScalarRound(vertOffset.width); |
| + offset->fY = SkScalarRound(-vertOffset.height); |
| } |
| uint16_t SkScalerContext_Mac::getFBoundingBoxesGlyphOffset() { |
| @@ -947,12 +909,11 @@ |
| const SkOTTableGlyphData* glyphData = glyphDataIter.next(); |
| GlyphRect& rect = fFBoundingBoxes[boundingBoxesIndex]; |
| rect.fMinX = SkEndian_SwapBE16(glyphData->xMin); |
| - rect.fMinY = SkEndian_SwapBE16(glyphData->yMin); |
| + rect.fMinY = -SkEndian_SwapBE16(glyphData->yMin); |
| rect.fMaxX = SkEndian_SwapBE16(glyphData->xMax); |
| - rect.fMaxY = SkEndian_SwapBE16(glyphData->yMax); |
| + rect.fMaxY = -SkEndian_SwapBE16(glyphData->yMax); |
| } |
| fFBoundingBoxesMatrix = fMatrix; |
| - flip(&fFBoundingBoxesMatrix); |
| SkScalar fontScale = getFontScale(fCGFont); |
| fFBoundingBoxesMatrix.preScale(fontScale, fontScale); |
|
bungeman-skia
2013/05/10 17:08:03
The matrix used in getVerticalOffset for SnowLeopa
|
| return true; |
| @@ -987,29 +948,32 @@ |
| void SkScalerContext_Mac::generateMetrics(SkGlyph* glyph) { |
| CGSize advance; |
| CGRect bounds; |
| - CGGlyph cgGlyph; |
| + CGGlyph const cgGlyph = (CGGlyph) glyph->getGlyphID(fBaseGlyphCount); |
| - // Get the state we need |
| - cgGlyph = (CGGlyph) glyph->getGlyphID(fBaseGlyphCount); |
| - |
| if (fVertical) { |
| if (!isSnowLeopard()) { |
| // Lion and Leopard respect the vertical font metrics. |
| - CTFontGetBoundingRectsForGlyphs(fCTVerticalFont, kCTFontVerticalOrientation, |
| + CTFontGetBoundingRectsForGlyphs(fCTFont, kCTFontVerticalOrientation, |
| &cgGlyph, &bounds, 1); |
| + SkTSwap(bounds.origin.x, bounds.origin.y); |
| + SkTSwap(bounds.size.width, bounds.size.height); |
| } else { |
| // Snow Leopard and earlier respect the vertical font metrics for |
| // advances, but not bounds, so use the default box and adjust it below. |
| CTFontGetBoundingRectsForGlyphs(fCTFont, kCTFontDefaultOrientation, |
| &cgGlyph, &bounds, 1); |
| + bounds.origin.y = -bounds.origin.y - bounds.size.height; |
| } |
| - CTFontGetAdvancesForGlyphs(fCTVerticalFont, kCTFontVerticalOrientation, |
| + CTFontGetAdvancesForGlyphs(fCTFont, kCTFontVerticalOrientation, |
| &cgGlyph, &advance, 1); |
| + SkTSwap(advance.height, advance.width); |
| } else { |
| CTFontGetBoundingRectsForGlyphs(fCTFont, kCTFontDefaultOrientation, |
| &cgGlyph, &bounds, 1); |
| + bounds.origin.y = -bounds.origin.y - bounds.size.height; |
| CTFontGetAdvancesForGlyphs(fCTFont, kCTFontDefaultOrientation, |
| &cgGlyph, &advance, 1); |
| + advance.height = -advance.height; |
| } |
| // BUG? |
| @@ -1025,34 +989,14 @@ |
| } |
| glyph->zeroMetrics(); |
| - glyph->fAdvanceX = SkFloatToFixed_Check(advance.width); |
| - glyph->fAdvanceY = -SkFloatToFixed_Check(advance.height); |
| + glyph->fAdvanceX = SkFloatToFixed_Check(advance.width); |
| + glyph->fAdvanceY = SkFloatToFixed_Check(advance.height); |
| if (CGRectIsEmpty_inline(bounds)) { |
| 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 |
| - // to transform the bounding box ourselves. |
| - // |
| - // The bounds are also expanded by 1 pixel, to give CG room for anti-aliasing. |
| + // Expand the bounds by 1 pixel, to give CG room for anti-aliasing. |
| CGRectInset_inline(&bounds, -1, -1); |
| // Get the metrics |
| @@ -1074,12 +1018,12 @@ |
| glyph->fWidth = SkToU16(sk_float_round2int(bounds.size.width)); |
| glyph->fHeight = SkToU16(sk_float_round2int(bounds.size.height)); |
| } |
| - glyph->fTop = SkToS16(-sk_float_round2int(CGRectGetMaxY_inline(bounds))); |
| - glyph->fLeft = SkToS16(sk_float_round2int(CGRectGetMinX_inline(bounds))); |
| - SkIPoint offset; |
| + glyph->fTop = SkToS16(sk_float_round2int(bounds.origin.y)); |
| + glyph->fLeft = SkToS16(sk_float_round2int(bounds.origin.x)); |
| if (fVertical && (isSnowLeopard() || lionAdjustedMetrics)) { |
| // SnowLeopard doesn't respect vertical metrics, so compute them manually. |
| // Also compute them for Lion when the metrics were computed by hand. |
| + SkIPoint offset; |
| getVerticalOffset(cgGlyph, &offset); |
| glyph->fLeft += offset.fX; |
| glyph->fTop += offset.fY; |