diff options
Diffstat (limited to 'src/ports')
-rw-r--r-- | src/ports/SkFontHost_FreeType.cpp | 104 | ||||
-rwxr-xr-x | src/ports/SkFontHost_win.cpp | 30 |
2 files changed, 73 insertions, 61 deletions
diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp index 97caab4b6b..e1d62c027e 100644 --- a/src/ports/SkFontHost_FreeType.cpp +++ b/src/ports/SkFontHost_FreeType.cpp @@ -18,6 +18,7 @@ #include "SkGlyph.h" #include "SkMask.h" #include "SkMaskGamma.h" +#include "SkMatrix22.h" #include "SkOTUtils.h" #include "SkOnce.h" #include "SkScalerContext.h" @@ -43,6 +44,8 @@ #include FT_LCD_FILTER_H #endif +// Defined in FreeType 2.3.8 and later. +// This is a silly build time check, we would need a runtime check if we really cared. #ifdef FT_ADVANCES_H #include FT_ADVANCES_H #endif @@ -693,9 +696,6 @@ SkAdvancedTypefaceMetrics* SkTypeface_FreeType::onGetAdvancedTypefaceMetrics( /////////////////////////////////////////////////////////////////////////// -#define BLACK_LUMINANCE_LIMIT 0x40 -#define WHITE_LUMINANCE_LIMIT 0xA0 - static bool bothZero(SkScalar a, SkScalar b) { return 0 == a && 0 == b; } @@ -849,46 +849,34 @@ SkScalerContext_FreeType::SkScalerContext_FreeType(SkTypeface* typeface, } fFace = fFaceRec->fFace; - // compute our factors from the record - - SkMatrix m; - - fRec.getSingleMatrix(&m); - -#ifdef DUMP_STRIKE_CREATION - SkString keyString; - SkFontHost::GetDescriptorKeyString(desc, &keyString); - printf("========== strike [%g %g %g] [%g %g %g %g] hints %d format %d %s\n", SkScalarToFloat(fRec.fTextSize), - SkScalarToFloat(fRec.fPreScaleX), SkScalarToFloat(fRec.fPreSkewX), - SkScalarToFloat(fRec.fPost2x2[0][0]), SkScalarToFloat(fRec.fPost2x2[0][1]), - SkScalarToFloat(fRec.fPost2x2[1][0]), SkScalarToFloat(fRec.fPost2x2[1][1]), - fRec.getHinting(), fRec.fMaskFormat, keyString.c_str()); -#endif - - // now compute our scale factors - SkScalar sx = m.getScaleX(); - SkScalar sy = m.getScaleY(); + // A is the total matrix. + SkMatrix A; + fRec.getSingleMatrix(&A); + SkScalar sx = A.getScaleX(); + SkScalar sy = A.getScaleY(); fMatrix22Scalar.reset(); - if (m.getSkewX() || m.getSkewY() || sx < 0 || sy < 0) { +//#define SK_IGNORE_FREETYPE_ROTATION_FIX +#ifdef SK_IGNORE_FREETYPE_ROTATION_FIX + if (A.getSkewX() || A.getSkewY() || sx < 0 || sy < 0) { // sort of give up on hinting - sx = SkMaxScalar(SkScalarAbs(sx), SkScalarAbs(m.getSkewX())); - sy = SkMaxScalar(SkScalarAbs(m.getSkewY()), SkScalarAbs(sy)); + sx = SkMaxScalar(SkScalarAbs(sx), SkScalarAbs(A.getSkewX())); + sy = SkMaxScalar(SkScalarAbs(A.getSkewY()), SkScalarAbs(sy)); sx = sy = SkScalarAve(sx, sy); SkScalar inv = SkScalarInvert(sx); // flip the skew elements to go from our Y-down system to FreeType's - fMatrix22.xx = SkScalarToFixed(SkScalarMul(m.getScaleX(), inv)); - fMatrix22.xy = -SkScalarToFixed(SkScalarMul(m.getSkewX(), inv)); - fMatrix22.yx = -SkScalarToFixed(SkScalarMul(m.getSkewY(), inv)); - fMatrix22.yy = SkScalarToFixed(SkScalarMul(m.getScaleY(), inv)); - - fMatrix22Scalar.setScaleX(SkScalarMul(m.getScaleX(), inv)); - fMatrix22Scalar.setSkewX(-SkScalarMul(m.getSkewX(), inv)); - fMatrix22Scalar.setSkewY(-SkScalarMul(m.getSkewY(), inv)); - fMatrix22Scalar.setScaleY(SkScalarMul(m.getScaleY(), inv)); + fMatrix22.xx = SkScalarToFixed(SkScalarMul(A.getScaleX(), inv)); + fMatrix22.xy = -SkScalarToFixed(SkScalarMul(A.getSkewX(), inv)); + fMatrix22.yx = -SkScalarToFixed(SkScalarMul(A.getSkewY(), inv)); + fMatrix22.yy = SkScalarToFixed(SkScalarMul(A.getScaleY(), inv)); + + fMatrix22Scalar.setScaleX(SkScalarMul(A.getScaleX(), inv)); + fMatrix22Scalar.setSkewX(-SkScalarMul(A.getSkewX(), inv)); + fMatrix22Scalar.setSkewY(-SkScalarMul(A.getSkewY(), inv)); + fMatrix22Scalar.setScaleY(SkScalarMul(A.getScaleY(), inv)); } else { fMatrix22.xx = fMatrix22.yy = SK_Fixed1; fMatrix22.xy = fMatrix22.yx = 0; @@ -896,6 +884,54 @@ SkScalerContext_FreeType::SkScalerContext_FreeType(SkTypeface* typeface, fScale.set(sx, sy); fScaleX = SkScalarToFixed(sx); fScaleY = SkScalarToFixed(sy); +#else + // In GDI, the hinter is aware of the current transformation + // (the transform is in some sense applied before/with the hinting). + // The bytecode can then test if it is rotated or stretched and decide + // to apply instructions or not. + // + // FreeType, however, always does the transformation strictly after hinting. + // It just sets 'rotated' and 'stretched' to false and only applies the + // size before hinting. + // + // Also, FreeType respects the head::flags::IntegerScaling flag, + // (although this is patched out on most major distros) + // so it is critical to get the size correct on the request. + // + // This also gets us the actual closest size on bitmap fonts as well. + if (A.getSkewX() || A.getSkewY() || sx < 0 || sy < 0) { + // h is where A maps the horizontal baseline. + SkPoint h = SkPoint::Make(SK_Scalar1, 0); + A.mapPoints(&h, 1); + + // G is the Givens Matrix for A (rotational matrix where GA[0][1] == 0). + SkMatrix G; + SkComputeGivensRotation(h, &G); + + // GA is the matrix A with rotation removed. + SkMatrix GA(G); + GA.preConcat(A); + + sx = SkScalarAbs(GA.get(SkMatrix::kMScaleX)); + sy = SkScalarAbs(GA.get(SkMatrix::kMScaleY)); + + // sA is the total matrix A without the text scale. + SkMatrix sA(A); + sA.preScale(SkScalarInvert(sx), SkScalarInvert(sy)); //remove text size + + fMatrix22Scalar.setScaleX(sA.getScaleX()); + fMatrix22Scalar.setSkewX(-sA.getSkewX()); + fMatrix22Scalar.setSkewY(-sA.getSkewY()); + fMatrix22Scalar.setScaleY(sA.getScaleY()); + } + fScale.set(sx, sy); + fScaleX = SkScalarToFixed(sx); + fScaleY = SkScalarToFixed(sy); + fMatrix22.xx = SkScalarToFixed(fMatrix22Scalar.getScaleX()); + fMatrix22.xy = SkScalarToFixed(fMatrix22Scalar.getSkewX()); + fMatrix22.yx = SkScalarToFixed(fMatrix22Scalar.getSkewY()); + fMatrix22.yy = SkScalarToFixed(fMatrix22Scalar.getScaleY()); +#endif fLCDIsVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag); diff --git a/src/ports/SkFontHost_win.cpp b/src/ports/SkFontHost_win.cpp index 8ed3b666aa..47a29c0024 100755 --- a/src/ports/SkFontHost_win.cpp +++ b/src/ports/SkFontHost_win.cpp @@ -16,6 +16,7 @@ #include "SkGlyph.h" #include "SkHRESULT.h" #include "SkMaskGamma.h" +#include "SkMatrix22.h" #include "SkOTTable_maxp.h" #include "SkOTTable_name.h" #include "SkOTUtils.h" @@ -636,34 +637,9 @@ SkScalerContext_GDI::SkScalerContext_GDI(SkTypeface* rawTypeface, fRec.getSingleMatrix(&A); A.mapPoints(&h, 1); - // Find the Given's matrix [[c, -s],[s, c]] which rotates the baseline vector h - // (where the baseline is mapped to) to the positive horizontal axis. - const SkScalar& a = h.fX; - const SkScalar& b = h.fY; - SkScalar c, s; - if (0 == b) { - c = SkDoubleToScalar(_copysign(SK_Scalar1, a)); - s = 0; - } else if (0 == a) { - c = 0; - s = SkDoubleToScalar(-_copysign(SK_Scalar1, b)); - } else if (SkScalarAbs(b) > SkScalarAbs(a)) { - SkScalar t = a / b; - SkScalar u = SkDoubleToScalar(_copysign(SkScalarSqrt(SK_Scalar1 + t*t), b)); - s = -1 / u; - c = -s * t; - } else { - SkScalar t = b / a; - SkScalar u = SkDoubleToScalar(_copysign(SkScalarSqrt(SK_Scalar1 + t*t), a)); - c = 1 / u; - s = -c * t; - } - - // G is the Given's Matrix for A (rotational matrix such that GA[0][1] == 0). + // G is the Givens Matrix for A (rotational matrix where GA[0][1] == 0). SkMatrix G; - G.setAll(c, -s, 0, - s, c, 0, - 0, 0, SkScalarToPersp(SK_Scalar1)); + SkComputeGivensRotation(h, &G); // GA is the matrix A with rotation removed. SkMatrix GA(G); |