Index: src/ports/SkScalerContext_win_dw.cpp |
diff --git a/src/ports/SkScalerContext_win_dw.cpp b/src/ports/SkScalerContext_win_dw.cpp |
index f27497be62ef7e40fdc88fede12c183624cbb227..216c7dce2c25dfbbcc4f88aaa83fd2c6444c71a3 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)) { |