diff options
Diffstat (limited to 'src/ports/SkScalerContext_win_dw.cpp')
-rw-r--r-- | src/ports/SkScalerContext_win_dw.cpp | 62 |
1 files changed, 48 insertions, 14 deletions
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)) { |