aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Ben Wagner <bungeman@google.com>2014-08-27 19:17:41 -0400
committerGravatar Ben Wagner <bungeman@google.com>2014-08-27 19:17:41 -0400
commitb2f7fce9e034c3b6749e75a129e7836df3529706 (patch)
tree7f5112b38c1cc417234c5f52fcac2f6847351227
parent56fa44250365cd1cef9f57d642b3d6e90749f025 (diff)
DirectWrite to use aliased if ClearType is empty.
Some CJK fonts with some versions of DirectWrite return valid data for bitmaps, but not for cleartype data. For reference, two screenshots. M37 Stable and then with this patch: http://imgur.com/9pf3rB9,EiTb6Li See https://code.google.com/p/chromium/issues/detail?id=396624#c10 for content of test html file. R=eae@chromium.org, reed@google.com, shrikant@chromium.org, bungeman@chromium.org, cpu@chromium.org BUG=chromium:407945 Review URL: https://codereview.chromium.org/504343007
-rw-r--r--src/core/SkGlyph.h2
-rw-r--r--src/ports/SkScalerContext_win_dw.cpp62
-rw-r--r--src/ports/SkScalerContext_win_dw.h9
3 files changed, 58 insertions, 15 deletions
diff --git a/src/core/SkGlyph.h b/src/core/SkGlyph.h
index 5e0ac7ec0b..4290bb889d 100644
--- a/src/core/SkGlyph.h
+++ b/src/core/SkGlyph.h
@@ -32,6 +32,7 @@ struct SkGlyph {
void* fDistanceField;
uint8_t fMaskFormat;
int8_t fRsbDelta, fLsbDelta; // used by auto-kerning
+ int8_t fForceBW;
void init(uint32_t id) {
fID = id;
@@ -39,6 +40,7 @@ struct SkGlyph {
fPath = NULL;
fDistanceField = NULL;
fMaskFormat = MASK_FORMAT_UNKNOWN;
+ fForceBW = 0;
}
/**
diff --git a/src/ports/SkScalerContext_win_dw.cpp b/src/ports/SkScalerContext_win_dw.cpp
index f27497be62..216c7dce2c 100644
--- a/src/ports/SkScalerContext_win_dw.cpp
+++ b/src/ports/SkScalerContext_win_dw.cpp
@@ -398,11 +398,11 @@ void SkScalerContext_DW::generateAdvance(SkGlyph* glyph) {
glyph->fAdvanceY = SkScalarToFixed(vecs[0].fY);
}
-void SkScalerContext_DW::generateMetrics(SkGlyph* glyph) {
- glyph->fWidth = 0;
-
- this->generateAdvance(glyph);
-
+void SkScalerContext_DW::getBoundingBox(SkGlyph* glyph,
+ DWRITE_RENDERING_MODE renderingMode,
+ DWRITE_TEXTURE_TYPE textureType,
+ RECT* bbox)
+{
//Measure raster size.
fXform.dx = SkFixedToFloat(glyph->getSubXFixed());
fXform.dy = SkFixedToFloat(glyph->getSubYFixed());
@@ -430,16 +430,41 @@ void SkScalerContext_DW::generateMetrics(SkGlyph* glyph) {
&run,
1.0f, // pixelsPerDip,
&fXform,
- fRenderingMode,
+ renderingMode,
fMeasuringMode,
0.0f, // baselineOriginX,
0.0f, // baselineOriginY,
&glyphRunAnalysis),
"Could not create glyph run analysis.");
- RECT bbox;
- HRVM(glyphRunAnalysis->GetAlphaTextureBounds(fTextureType, &bbox),
+ HRVM(glyphRunAnalysis->GetAlphaTextureBounds(textureType, bbox),
"Could not get texture bounds.");
+}
+
+void SkScalerContext_DW::generateMetrics(SkGlyph* glyph) {
+ glyph->fWidth = 0;
+
+ this->generateAdvance(glyph);
+
+ RECT bbox;
+ this->getBoundingBox(glyph, fRenderingMode, fTextureType, &bbox);
+
+ // GetAlphaTextureBounds succeeds but returns an empty RECT if there are no
+ // glyphs of the specified texture type. When this happens, try with the
+ // alternate texture type.
+ if (bbox.left == bbox.right || bbox.top == bbox.bottom) {
+ if (DWRITE_TEXTURE_CLEARTYPE_3x1 == fTextureType) {
+ this->getBoundingBox(glyph,
+ DWRITE_RENDERING_MODE_ALIASED,
+ DWRITE_TEXTURE_ALIASED_1x1,
+ &bbox);
+ if (bbox.left != bbox.right && bbox.top != bbox.bottom) {
+ glyph->fForceBW = 1;
+ }
+ }
+ // TODO: handle the case where a request for DWRITE_TEXTURE_ALIASED_1x1
+ // fails, and try DWRITE_TEXTURE_CLEARTYPE_3x1.
+ }
glyph->fWidth = SkToU16(bbox.right - bbox.left);
glyph->fHeight = SkToU16(bbox.bottom - bbox.top);
@@ -602,9 +627,12 @@ static void rgb_to_lcd32(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph,
}
}
-const void* SkScalerContext_DW::drawDWMask(const SkGlyph& glyph) {
+const void* SkScalerContext_DW::drawDWMask(const SkGlyph& glyph,
+ DWRITE_RENDERING_MODE renderingMode,
+ DWRITE_TEXTURE_TYPE textureType)
+{
int sizeNeeded = glyph.fWidth * glyph.fHeight;
- if (DWRITE_RENDERING_MODE_ALIASED != fRenderingMode) {
+ if (DWRITE_RENDERING_MODE_ALIASED != renderingMode) {
sizeNeeded *= 3;
}
if (sizeNeeded > fBits.count()) {
@@ -639,7 +667,7 @@ const void* SkScalerContext_DW::drawDWMask(const SkGlyph& glyph) {
HRNM(fTypeface->fFactory->CreateGlyphRunAnalysis(&run,
1.0f, // pixelsPerDip,
&fXform,
- fRenderingMode,
+ renderingMode,
fMeasuringMode,
0.0f, // baselineOriginX,
0.0f, // baselineOriginY,
@@ -653,7 +681,7 @@ const void* SkScalerContext_DW::drawDWMask(const SkGlyph& glyph) {
bbox.top = glyph.fTop;
bbox.right = glyph.fLeft + glyph.fWidth;
bbox.bottom = glyph.fTop + glyph.fHeight;
- HRNM(glyphRunAnalysis->CreateAlphaTexture(fTextureType,
+ HRNM(glyphRunAnalysis->CreateAlphaTexture(textureType,
&bbox,
fBits.begin(),
sizeNeeded),
@@ -663,7 +691,13 @@ const void* SkScalerContext_DW::drawDWMask(const SkGlyph& glyph) {
void SkScalerContext_DW::generateImage(const SkGlyph& glyph) {
//Create the mask.
- const void* bits = this->drawDWMask(glyph);
+ DWRITE_RENDERING_MODE renderingMode = fRenderingMode;
+ DWRITE_TEXTURE_TYPE textureType = fTextureType;
+ if (glyph.fForceBW) {
+ renderingMode = DWRITE_RENDERING_MODE_ALIASED;
+ textureType = DWRITE_TEXTURE_ALIASED_1x1;
+ }
+ const void* bits = this->drawDWMask(glyph, renderingMode, textureType);
if (!bits) {
sk_bzero(glyph.fImage, glyph.computeImageSize());
return;
@@ -671,7 +705,7 @@ void SkScalerContext_DW::generateImage(const SkGlyph& glyph) {
//Copy the mask into the glyph.
const uint8_t* src = (const uint8_t*)bits;
- if (DWRITE_RENDERING_MODE_ALIASED == fRenderingMode) {
+ if (DWRITE_RENDERING_MODE_ALIASED == renderingMode) {
bilevel_to_bw(src, glyph);
const_cast<SkGlyph&>(glyph).fMaskFormat = SkMask::kBW_Format;
} else if (!isLCD(fRec)) {
diff --git a/src/ports/SkScalerContext_win_dw.h b/src/ports/SkScalerContext_win_dw.h
index e8eff0d6ce..e9eab94de1 100644
--- a/src/ports/SkScalerContext_win_dw.h
+++ b/src/ports/SkScalerContext_win_dw.h
@@ -33,7 +33,14 @@ protected:
virtual void generateFontMetrics(SkPaint::FontMetrics*) SK_OVERRIDE;
private:
- const void* drawDWMask(const SkGlyph& glyph);
+ const void* drawDWMask(const SkGlyph& glyph,
+ DWRITE_RENDERING_MODE renderingMode,
+ DWRITE_TEXTURE_TYPE textureType);
+
+ void getBoundingBox(SkGlyph* glyph,
+ DWRITE_RENDERING_MODE renderingMode,
+ DWRITE_TEXTURE_TYPE textureType,
+ RECT* bbox);
SkTDArray<uint8_t> fBits;
/** The total matrix without the text height scale. */