Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1045)

Unified Diff: src/ports/SkScalerContext_win_dw.cpp

Issue 1984943002: Implement support for rendering color emoji on Windows (Closed) Base URL: https://chromium.googlesource.com/skia.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/ports/SkScalerContext_win_dw.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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());
« no previous file with comments | « src/ports/SkScalerContext_win_dw.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698