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
This commit is contained in:
bungeman 2014-06-30 12:19:41 -07:00 committed by Commit bot
parent 26337e9702
commit 761b2509d5

View File

@ -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));