Chromium Code Reviews| Index: src/ports/SkScalerContext_win_dw.cpp |
| diff --git a/src/ports/SkScalerContext_win_dw.cpp b/src/ports/SkScalerContext_win_dw.cpp |
| index 4609d04851870891c7b60bb32485e62af90255ed..2824ef0285ca70c94498b4c825355a4eea899cc2 100644 |
| --- a/src/ports/SkScalerContext_win_dw.cpp |
| +++ b/src/ports/SkScalerContext_win_dw.cpp |
| @@ -210,6 +210,15 @@ SkScalerContext_DW::SkScalerContext_DW(DWriteFontTypeface* typeface, |
| , fTypeface(SkRef(typeface)) |
| , fGlyphCount(-1) { |
| +#if SK_HAS_DWRITE_2_H |
| + SkTScopedComPtr<IDWriteFactory> factory(SkSafeRefComPtr(sk_get_dwrite_factory())); |
|
bungeman-skia
2016/05/18 14:50:55
You cannot create a factory here, you must use the
Ilya Kulshin
2016/05/18 22:43:38
Done.
|
| + factory->QueryInterface<IDWriteFactory2>(&fFactory2); |
| + |
| + SkTScopedComPtr<IDWriteFontFace2> fontFace2; |
| + fTypeface->fDWriteFontFace->QueryInterface<IDWriteFontFace2>(&fontFace2); |
| + fIsColorFont = fFactory2.get() && fontFace2.get() && fontFace2->IsColorFont(); |
| +#endif |
| + |
| // In general, all glyphs should use CLEARTYPE_NATURAL_SYMMETRIC |
| // except when bi-level rendering is requested or there are embedded |
| // bi-level bitmaps (and the embedded bitmap flag is set and no rotation). |
| @@ -458,6 +467,48 @@ static bool glyph_check_and_set_bounds(SkGlyph* glyph, const RECT& bbox) { |
| return true; |
| } |
| +bool SkScalerContext_DW::isColorGlyph(const SkGlyph& glyph) { |
| +#if SK_HAS_DWRITE_2_H |
| + SkTScopedComPtr<IDWriteColorGlyphRunEnumerator> colorLayer; |
| + if (getColorGlyphRun(glyph, &colorLayer)) { |
| + return true; |
| + } |
| +#endif |
| + return false; |
| +} |
| + |
| +#if SK_HAS_DWRITE_2_H |
| +bool SkScalerContext_DW::getColorGlyphRun(const SkGlyph& glyph, |
| + IDWriteColorGlyphRunEnumerator** colorGlyph) |
| +{ |
| + FLOAT advance = 0; |
| + UINT16 glyphId = glyph.getGlyphID(); |
| + |
| + DWRITE_GLYPH_OFFSET offset; |
| + offset.advanceOffset = 0.0f; |
| + offset.ascenderOffset = 0.0f; |
| + |
| + DWRITE_GLYPH_RUN run; |
| + run.glyphCount = 1; |
| + run.glyphAdvances = &advance; |
| + run.fontFace = fTypeface->fDWriteFontFace.get(); |
| + run.fontEmSize = SkScalarToFloat(fTextSizeRender); |
| + run.bidiLevel = 0; |
| + run.glyphIndices = &glyphId; |
| + run.isSideways = FALSE; |
| + run.glyphOffsets = &offset; |
| + |
| + HRESULT hr = fFactory2->TranslateColorGlyphRun( |
| + 0, 0, &run, nullptr, DWRITE_MEASURING_MODE_NATURAL, nullptr, 0, colorGlyph); |
|
bungeman-skia
2016/05/18 14:50:55
Need to pass in fXform and fMeasuringMode.
Ilya Kulshin
2016/05/18 22:43:38
Done.
|
| + if (SUCCEEDED(hr)) { |
| + return true; |
| + } else { |
| + SkASSERT(hr == DWRITE_E_NOCOLOR); |
| + } |
| + return false; |
|
bungeman-skia
2016/05/18 14:50:55
The return value handling here should be more like
Ilya Kulshin
2016/05/18 22:43:38
Done.
|
| +} |
| +#endif |
| + |
| void SkScalerContext_DW::generateMetrics(SkGlyph* glyph) { |
| glyph->fWidth = 0; |
| glyph->fHeight = 0; |
| @@ -466,6 +517,12 @@ void SkScalerContext_DW::generateMetrics(SkGlyph* glyph) { |
| this->generateAdvance(glyph); |
| +#if SK_HAS_DWRITE_2_H |
| + if (fIsColorFont && isColorGlyph(*glyph)) { |
| + glyph->fMaskFormat = SkMask::kARGB32_Format; |
| + } |
| +#endif |
| + |
| RECT bbox; |
| HRVM(this->getBoundingBox(glyph, fRenderingMode, fTextureType, &bbox), |
| "Requested bounding box could not be determined."); |
| @@ -710,6 +767,71 @@ const void* SkScalerContext_DW::drawDWMask(const SkGlyph& glyph, |
| return fBits.begin(); |
| } |
| +#if SK_HAS_DWRITE_2_H |
| +void SkScalerContext_DW::generateColorGlyphImage(const SkGlyph& glyph) { |
| + SkASSERT(isColorGlyph(glyph)); |
| + HRESULT hr = S_OK; |
|
bungeman-skia
2016/05/18 14:50:55
Remove this.
Ilya Kulshin
2016/05/18 22:43:38
Done.
|
| + |
| + memset(glyph.fImage, 0, glyph.computeImageSize()); |
| + |
| + SkTScopedComPtr<IDWriteColorGlyphRunEnumerator> colorLayers; |
| + getColorGlyphRun(glyph, &colorLayers); |
| + SkASSERT(colorLayers.get()); |
| + |
| + int layerSize = glyph.fWidth * glyph.fHeight; // layers are drawn in monochrome |
| + SkASSERT_RELEASE(layerSize * sizeof(uint32_t) == glyph.computeImageSize()); |
| + fBits.setCount(layerSize); |
| + |
| + RECT bbox; |
| + bbox.left = glyph.fLeft; |
| + bbox.top = glyph.fTop; |
| + bbox.right = glyph.fLeft + glyph.fWidth; |
| + bbox.bottom = glyph.fTop + glyph.fHeight; |
| + |
| + BOOL hasNextRun = FALSE; |
| + while (SUCCEEDED(colorLayers->MoveNext(&hasNextRun)) && hasNextRun) { |
| + const DWRITE_COLOR_GLYPH_RUN* colorGlyph; |
| + if (!SUCCEEDED(colorLayers->GetCurrentRun(&colorGlyph))) { |
|
bungeman-skia
2016/05/18 14:50:55
Use the HRNM macro for proper logging and for cons
Ilya Kulshin
2016/05/18 22:43:38
Done.
|
| + SkASSERT(false); |
| + return; |
| + } |
| + |
| + SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis; |
| + { |
| + Exclusive l(DWriteFactoryMutex); |
| + hr = fTypeface->fFactory->CreateGlyphRunAnalysis(&colorGlyph->glyphRun, |
|
bungeman-skia
2016/05/18 14:50:55
The result is never checked. Use the HRNM macro li
Ilya Kulshin
2016/05/18 22:43:38
Done.
|
| + 1.0f, // pixelsPerDip, |
| + nullptr, |
|
bungeman-skia
2016/05/18 14:50:55
If you don't pass the fXForm, how does this work f
Ilya Kulshin
2016/05/18 22:43:38
Added fXfrom, but I'm not sure when it will be som
bungeman-skia
2016/05/19 18:52:37
Any time there is skew/rotation.
|
| + DWRITE_RENDERING_MODE_ALIASED, |
| + DWRITE_MEASURING_MODE_NATURAL, |
|
bungeman-skia
2016/05/18 14:50:55
fRenderingMode and fMeasuringMode
Ilya Kulshin
2016/05/18 22:43:38
Done.
|
| + colorGlyph->baselineOriginX, |
| + colorGlyph->baselineOriginY, |
| + &glyphRunAnalysis); |
| + } |
| + //NOTE: this assumes that the glyph has already been measured |
| + //with an exact same glyph run analysis. |
| + { |
| + Shared l(DWriteFactoryMutex); |
| + hr = glyphRunAnalysis->CreateAlphaTexture(DWRITE_TEXTURE_ALIASED_1x1, |
|
bungeman-skia
2016/05/18 14:50:55
HRNM, fRenderingMode
Ilya Kulshin
2016/05/18 22:43:38
Done.
|
| + &bbox, |
| + fBits.begin(), |
| + layerSize); |
| + } |
| + |
| + uint32_t* colorPixels = reinterpret_cast<uint32_t*>(glyph.fImage); |
| + SkColor color = SkColorSetARGB(colorGlyph->runColor.a * 255, |
|
bungeman-skia
2016/05/18 14:50:55
Note that if all components of runColor are 0 or (
Ilya Kulshin
2016/05/20 03:41:40
Changed to fRec.getLuminanceColor() and added a co
|
| + colorGlyph->runColor.r * 255, |
|
reed1
2016/05/18 00:42:53
is runColor premultiplied?
Ilya Kulshin
2016/05/18 00:56:46
I'm not actually sure. It's of type D3DCOLORVALUE.
|
| + colorGlyph->runColor.g * 255, |
| + colorGlyph->runColor.b * 255); |
| + for (int pixel = 0; pixel < layerSize; pixel++) { |
| + if (fBits[pixel] != 0) { |
|
bungeman-skia
2016/05/18 14:50:54
This seems like a really bad blend, this should be
Ilya Kulshin
2016/05/18 22:43:38
Originally I thought antialiasing/subpixel renderi
|
| + colorPixels[pixel] = color; |
| + } |
| + } |
| + } |
| +} |
| +#endif |
| + |
| void SkScalerContext_DW::generateImage(const SkGlyph& glyph) { |
| //Create the mask. |
| DWRITE_RENDERING_MODE renderingMode = fRenderingMode; |
| @@ -718,6 +840,14 @@ void SkScalerContext_DW::generateImage(const SkGlyph& glyph) { |
| renderingMode = DWRITE_RENDERING_MODE_ALIASED; |
| textureType = DWRITE_TEXTURE_ALIASED_1x1; |
| } |
| + |
| +#if SK_HAS_DWRITE_2_H |
| + if (SkMask::kARGB32_Format == glyph.fMaskFormat) { |
| + generateColorGlyphImage(glyph); |
| + return; |
| + } |
| +#endif |
| + |
| const void* bits = this->drawDWMask(glyph, renderingMode, textureType); |
| if (!bits) { |
| sk_bzero(glyph.fImage, glyph.computeImageSize()); |