Snap GDI matrix when snapping height.

When using GDI to render, ensure that the GDI matrix does not attempt to
add subpixel height. This ensures that rotated text is always the same
height as axis aligned text and prevents subpixel drift metrics when they
are unwanted.

R=reed@google.com

Review URL: https://codereview.chromium.org/25739002

git-svn-id: http://skia.googlecode.com/svn/trunk@11592 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
bungeman@google.com 2013-10-03 20:17:51 +00:00
parent 608ea6508a
commit 11ba3199f3

View File

@ -663,17 +663,25 @@ SkScalerContext_GDI::SkScalerContext_GDI(SkTypeface* rawTypeface,
SkMatrix GA(G);
GA.preConcat(A);
// textSize is the actual device size we want (as opposed to the size the user requested).
// realTextSize is the actual device size we want (as opposed to the size the user requested).
// gdiTextSide is the size we request from GDI.
// If the scale is negative, this means the matrix will do the flip anyway.
SkScalar textSize = SkScalarAbs(SkScalarRoundToScalar(GA.get(SkMatrix::kMScaleY)));
if (textSize == 0) {
textSize = SK_Scalar1;
SkScalar realTextSize = SkScalarAbs(GA.get(SkMatrix::kMScaleY));
SkScalar gdiTextSize = SkScalarRoundToScalar(realTextSize);
if (gdiTextSize == 0) {
gdiTextSize = SK_Scalar1;
}
// When not hinting, remove only the gdiTextSize scale which will be applied by GDI.
// When GDI hinting, remove the entire Y scale to prevent 'subpixel' metrics.
SkScalar scale = (fRec.getHinting() == SkPaint::kNo_Hinting ||
fRec.getHinting() == SkPaint::kSlight_Hinting)
? SkScalarInvert(gdiTextSize)
: SkScalarInvert(realTextSize);
// sA is the total matrix A without the textSize (so GDI knows the text size separately).
// When this matrix is used with GetGlyphOutline, no further processing is needed.
SkMatrix sA(A);
SkScalar scale = SkScalarInvert(textSize);
sA.preScale(scale, scale); //remove text size
// GsA is the non-rotational part of A without the text height scale.
@ -692,7 +700,7 @@ SkScalerContext_GDI::SkScalerContext_GDI(SkTypeface* rawTypeface,
G.get(SkMatrix::kMPersp0), G.get(SkMatrix::kMPersp1), G.get(SkMatrix::kMPersp2));
LOGFONT lf = typeface->fLogFont;
lf.lfHeight = -SkScalarTruncToInt(textSize);
lf.lfHeight = -SkScalarTruncToInt(gdiTextSize);
lf.lfQuality = compute_quality(fRec);
fFont = CreateFontIndirect(&lf);
if (!fFont) {
@ -742,7 +750,7 @@ SkScalerContext_GDI::SkScalerContext_GDI(SkTypeface* rawTypeface,
this->forceGenerateImageFromPath();
}
// Create a hires font if we need linear metrics.
// Create a hires matrix if we need linear metrics.
if (this->isSubpixel()) {
OUTLINETEXTMETRIC otm;
UINT success = GetOutlineTextMetrics(fDDC, sizeof(otm), &otm);
@ -751,17 +759,17 @@ SkScalerContext_GDI::SkScalerContext_GDI(SkTypeface* rawTypeface,
success = GetOutlineTextMetrics(fDDC, sizeof(otm), &otm);
}
if (0 != success) {
SkScalar scale = SkIntToScalar(otm.otmEMSquare);
SkScalar upem = SkIntToScalar(otm.otmEMSquare);
SkScalar textScale = scale / textSize;
fHighResMat22.eM11 = float2FIXED(textScale);
SkScalar gdiTextSizeToEMScale = upem / gdiTextSize;
fHighResMat22.eM11 = float2FIXED(gdiTextSizeToEMScale);
fHighResMat22.eM12 = float2FIXED(0);
fHighResMat22.eM21 = float2FIXED(0);
fHighResMat22.eM22 = float2FIXED(textScale);
fHighResMat22.eM22 = float2FIXED(gdiTextSizeToEMScale);
SkScalar invScale = SkScalarInvert(scale);
SkScalar removeEMScale = SkScalarInvert(upem);
fHiResMatrix = A;
fHiResMatrix.preScale(invScale, invScale);
fHiResMatrix.preScale(removeEMScale, removeEMScale);
}
}