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

Unified Diff: src/ports/SkFontHost_mac.cpp

Issue 15064003: Fix vertical text scaling on Mac. (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Clean-up Created 7 years, 7 months 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 | « samplecode/SampleApp.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
===================================================================
--- 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;
« no previous file with comments | « samplecode/SampleApp.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698