| 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..6f1d6fedc324c0d7199674c8a459dff5a1c78325 100644
|
| --- a/src/ports/SkScalerContext_win_dw.cpp
|
| +++ b/src/ports/SkScalerContext_win_dw.cpp
|
| @@ -10,6 +10,7 @@
|
|
|
| #undef GetGlyphIndices
|
|
|
| +#include "SkDraw.h"
|
| #include "SkDWrite.h"
|
| #include "SkDWriteGeometrySink.h"
|
| #include "SkEndian.h"
|
| @@ -23,6 +24,7 @@
|
| #include "SkOTTable_gasp.h"
|
| #include "SkOTTable_maxp.h"
|
| #include "SkPath.h"
|
| +#include "SkRasterClip.h"
|
| #include "SkScalerContext.h"
|
| #include "SkScalerContext_win_dw.h"
|
| #include "SkSharedMutex.h"
|
| @@ -210,6 +212,14 @@ SkScalerContext_DW::SkScalerContext_DW(DWriteFontTypeface* typeface,
|
| , fTypeface(SkRef(typeface))
|
| , fGlyphCount(-1) {
|
|
|
| +#if SK_HAS_DWRITE_2_H
|
| + fTypeface->fFactory->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 +468,47 @@ 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, fMeasuringMode, &fXform, 0, colorGlyph);
|
| + if (hr == DWRITE_E_NOCOLOR) {
|
| + return false;
|
| + }
|
| + HRBM(hr, "Failed to translate color glyph run");
|
| + return true;
|
| +}
|
| +#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,77 @@ 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));
|
| + SkASSERT(glyph.fMaskFormat == SkMask::Format::kARGB32_Format);
|
| +
|
| + memset(glyph.fImage, 0, glyph.computeImageSize());
|
| +
|
| + SkTScopedComPtr<IDWriteColorGlyphRunEnumerator> colorLayers;
|
| + getColorGlyphRun(glyph, &colorLayers);
|
| + SkASSERT(colorLayers.get());
|
| +
|
| + SkMatrix matrix = fSkXform;
|
| + matrix.postTranslate(-SkIntToScalar(glyph.fLeft), -SkIntToScalar(glyph.fTop));
|
| + SkRasterClip rc(SkIRect::MakeWH(glyph.fWidth, glyph.fHeight));
|
| + SkDraw draw;
|
| + draw.fDst = SkPixmap(SkImageInfo::MakeN32(glyph.fWidth, glyph.fHeight, kPremul_SkAlphaType),
|
| + glyph.fImage,
|
| + glyph.ComputeRowBytes(glyph.fWidth, SkMask::Format::kARGB32_Format));
|
| + draw.fMatrix = &matrix;
|
| + draw.fRC = &rc;
|
| +
|
| + SkPaint paint;
|
| + if (fRenderingMode != DWRITE_RENDERING_MODE_ALIASED) {
|
| + paint.setFlags(SkPaint::Flags::kAntiAlias_Flag);
|
| + }
|
| +
|
| + BOOL hasNextRun = FALSE;
|
| + while (SUCCEEDED(colorLayers->MoveNext(&hasNextRun)) && hasNextRun) {
|
| + const DWRITE_COLOR_GLYPH_RUN* colorGlyph;
|
| + HRVM(colorLayers->GetCurrentRun(&colorGlyph), "Could not get current color glyph run");
|
| +
|
| + SkColor color;
|
| + if (colorGlyph->paletteIndex != 0xffff) {
|
| + color = SkColorSetARGB(SkFloatToIntRound(colorGlyph->runColor.a * 255),
|
| + SkFloatToIntRound(colorGlyph->runColor.r * 255),
|
| + SkFloatToIntRound(colorGlyph->runColor.g * 255),
|
| + SkFloatToIntRound(colorGlyph->runColor.b * 255));
|
| + } else {
|
| + // If all components of runColor are 0 or (equivalently) paletteIndex is 0xFFFF then
|
| + // the 'current brush' is used. fRec.getLuminanceColor() is kinda sorta what is wanted
|
| + // here, but not really, it will often be the wrong value because it wan't designed for
|
| + // this.
|
| + // In practice, I've not encountered a color glyph that uses the current brush color.
|
| + // If this assert ever fires, we should verify that the color is rendered properly.
|
| + SkASSERT(false);
|
| + color = fRec.getLuminanceColor();
|
| + }
|
| + paint.setColor(color);
|
| +
|
| + SkPath path;
|
| + SkTScopedComPtr<IDWriteGeometrySink> geometryToPath;
|
| + HRVM(SkDWriteGeometrySink::Create(&path, &geometryToPath),
|
| + "Could not create geometry to path converter.");
|
| + {
|
| + Exclusive l(DWriteFactoryMutex);
|
| + HRVM(colorGlyph->glyphRun.fontFace->GetGlyphRunOutline(
|
| + colorGlyph->glyphRun.fontEmSize,
|
| + colorGlyph->glyphRun.glyphIndices,
|
| + colorGlyph->glyphRun.glyphAdvances,
|
| + colorGlyph->glyphRun.glyphOffsets,
|
| + colorGlyph->glyphRun.glyphCount,
|
| + colorGlyph->glyphRun.isSideways,
|
| + colorGlyph->glyphRun.bidiLevel % 2, //rtl
|
| + geometryToPath.get()),
|
| + "Could not create glyph outline.");
|
| + }
|
| + draw.drawPath(path, paint, nullptr, true /* pathIsMutable */);
|
| + }
|
| +}
|
| +#endif
|
| +
|
| void SkScalerContext_DW::generateImage(const SkGlyph& glyph) {
|
| //Create the mask.
|
| DWRITE_RENDERING_MODE renderingMode = fRenderingMode;
|
| @@ -718,6 +846,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());
|
|
|