Index: src/ports/SkScalerContext_win_dw.cpp |
diff --git a/src/ports/SkScalerContext_win_dw.cpp b/src/ports/SkScalerContext_win_dw.cpp |
index 99799a554a2ffe2c26eb41196373119a8ac8a6c8..345cefd75847548fca3fa3e983703afe916437c3 100644 |
--- a/src/ports/SkScalerContext_win_dw.cpp |
+++ b/src/ports/SkScalerContext_win_dw.cpp |
@@ -18,6 +18,7 @@ |
#include "SkOTTable_EBLC.h" |
#include "SkOTTable_EBSC.h" |
#include "SkOTTable_gasp.h" |
+#include "SkOTTable_maxp.h" |
#include "SkPath.h" |
#include "SkScalerContext.h" |
#include "SkScalerContext_win_dw.h" |
@@ -31,6 +32,27 @@ static bool isLCD(const SkScalerContext::Rec& rec) { |
SkMask::kLCD32_Format == rec.fMaskFormat; |
} |
+static bool is_hinted_without_gasp(DWriteFontTypeface* typeface) { |
+ AutoTDWriteTable<SkOTTableMaximumProfile> maxp(typeface->fDWriteFontFace.get()); |
+ if (!maxp.fExists) { |
+ return false; |
+ } |
+ if (maxp.fSize < sizeof(SkOTTableMaximumProfile::Version::TT)) { |
+ return false; |
+ } |
+ if (maxp->version.version != SkOTTableMaximumProfile::Version::TT::VERSION) { |
+ return false; |
+ } |
+ |
+ if (0 == maxp->version.tt.maxSizeOfInstructions) { |
+ // No hints. |
+ return false; |
+ } |
+ |
+ AutoTDWriteTable<SkOTTableGridAndScanProcedure> gasp(typeface->fDWriteFontFace.get()); |
+ return !gasp.fExists; |
+} |
+ |
/** A PPEMRange is inclusive, [min, max]. */ |
struct PPEMRange { |
int min; |
@@ -254,6 +276,17 @@ SkScalerContext_DW::SkScalerContext_DW(DWriteFontTypeface* typeface, |
fTextSizeMeasure = gdiTextSize; |
fMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC; |
+ // Fonts that have hints but no gasp table get non-symmetric rendering. |
+ // Usually such fonts have low quality hints which were never tested |
+ // with anything but GDI ClearType classic. Such fonts often rely on |
+ // drop out control in the y direction in order to be legible. |
+ } else if (is_hinted_without_gasp(typeface)) { |
+ fTextSizeRender = gdiTextSize; |
+ fRenderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL; |
+ fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1; |
+ fTextSizeMeasure = realTextSize; |
+ fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL; |
+ |
// The normal case is to use natural symmetric rendering and linear metrics. |
} else { |
fTextSizeRender = realTextSize; |
@@ -354,6 +387,9 @@ void SkScalerContext_DW::generateAdvance(SkGlyph* glyph) { |
if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode || |
DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode) |
{ |
+ // DirectWrite produced 'compatible' metrics, but while close, |
+ // the end result is not always an integer as it would be with GDI. |
+ vecs[0].fX = SkScalarRoundToScalar(advanceX); |
fG_inv.mapVectors(vecs, SK_ARRAY_COUNT(vecs)); |
} else { |
fSkXform.mapVectors(vecs, SK_ARRAY_COUNT(vecs)); |