DirectWrite to detect GDI only fonts.
The exist a number of webfonts which have poor hinting which look very
bad with any vertical subsampling. The fonts often rely on drop out
control to avoid zero coverage in the y direction. As a result, any font
with hints but no 'gasp' table is considered to be poorly hinted in this
way, and will not be rendered with vertical subsampling when hinted.
R=eae@chromium.org, reed@google.com, mtklein@google.com
Author: bungeman@google.com
Review URL: https://codereview.chromium.org/363433002
diff --git a/src/ports/SkScalerContext_win_dw.cpp b/src/ports/SkScalerContext_win_dw.cpp
index 99799a5..345cefd 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 @@
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 @@
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 @@
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));