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:
parent
608ea6508a
commit
11ba3199f3
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user