aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Bruce Wang <brucewang@google.com>2018-07-15 17:11:25 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-07-17 21:51:21 +0000
commite3986755dbb1e3d18793ec3508b4e247449b2196 (patch)
treed8a0c0c61c00b1ea0ca162a3389d08d7b5c3d0a9
parentd5148e331436b69e3de1a35d4bfa8492e89b3cce (diff)
Implement scaled color emoji using PNG format fonts.
Change-Id: I8da6258f2a8991231411e84b66b01a5e8fd38e31 Reviewed-on: https://skia-review.googlesource.com/141427 Reviewed-by: Ben Wagner <bungeman@google.com> Commit-Queue: Bruce Wang <brucewang@google.com>
-rw-r--r--src/ports/SkScalerContext_win_dw.cpp139
-rw-r--r--src/ports/SkScalerContext_win_dw.h7
-rw-r--r--src/ports/SkTypeface_win_dw.h4
3 files changed, 149 insertions, 1 deletions
diff --git a/src/ports/SkScalerContext_win_dw.cpp b/src/ports/SkScalerContext_win_dw.cpp
index dac7d0c67e..10153023d3 100644
--- a/src/ports/SkScalerContext_win_dw.cpp
+++ b/src/ports/SkScalerContext_win_dw.cpp
@@ -10,6 +10,7 @@
#undef GetGlyphIndices
+#include "SkCodec.h"
#include "SkDWrite.h"
#include "SkDWriteGeometrySink.h"
#include "SkDraw.h"
@@ -520,6 +521,18 @@ bool SkScalerContext_DW::isColorGlyph(const SkGlyph& glyph) {
return getColorGlyphRun(glyph, &colorLayer);
}
+bool SkScalerContext_DW::isPngGlyph(const SkGlyph& glyph) {
+ if (!this->getDWriteTypeface()->fDWriteFontFace4) {
+ return false;
+ }
+
+ DWRITE_GLYPH_IMAGE_FORMATS f;
+ IDWriteFontFace4* fontFace4 = this->getDWriteTypeface()->fDWriteFontFace4.get();
+ HRBM(fontFace4->GetGlyphImageFormats(glyph.getGlyphID(), 0, UINT32_MAX, &f),
+ "Cannot get glyph image formats.");
+ return f & DWRITE_GLYPH_IMAGE_FORMATS_PNG;
+}
+
bool SkScalerContext_DW::getColorGlyphRun(const SkGlyph& glyph,
IDWriteColorGlyphRunEnumerator** colorGlyph)
{
@@ -589,6 +602,73 @@ void SkScalerContext_DW::generateColorMetrics(SkGlyph* glyph) {
glyph->fTop = ibounds.fTop;
}
+namespace {
+struct Context {
+ SkTScopedComPtr<IDWriteFontFace4> fontFace4;
+ void* glyphDataContext;
+ Context(IDWriteFontFace4* face4, void* context)
+ : fontFace4(SkRefComPtr(face4))
+ , glyphDataContext(context)
+ {}
+};
+
+static void ReleaseProc(const void* ptr, void* context) {
+ Context* ctx = (Context*)context;
+ ctx->fontFace4->ReleaseGlyphImageData(ctx->glyphDataContext);
+ delete ctx;
+}
+}
+
+void SkScalerContext_DW::generatePngMetrics(SkGlyph* glyph) {
+ SkASSERT(isPngGlyph(*glyph));
+ SkASSERT(glyph->fMaskFormat == SkMask::Format::kARGB32_Format);
+ SkASSERT(this->getDWriteTypeface()->fDWriteFontFace4);
+
+ IDWriteFontFace4* fontFace4 = this->getDWriteTypeface()->fDWriteFontFace4.get();
+ DWRITE_GLYPH_IMAGE_DATA glyphData;
+ void* glyphDataContext;
+ HRVM(fontFace4->GetGlyphImageData(glyph->getGlyphID(),
+ fTextSizeRender,
+ DWRITE_GLYPH_IMAGE_FORMATS_PNG,
+ &glyphData,
+ &glyphDataContext),
+ "Glyph image data could not be acquired.");
+
+ Context* context = new Context(fontFace4, glyphDataContext);
+ sk_sp<SkData> data = SkData::MakeWithProc(glyphData.imageData,
+ glyphData.imageDataSize,
+ &ReleaseProc,
+ context);
+
+ std::unique_ptr<SkCodec> codec = SkCodec::MakeFromData(std::move(data));
+ if (!codec) {
+ return;
+ }
+
+ SkImageInfo info = codec->getInfo();
+ SkRect bounds = SkRect::MakeLTRB(SkIntToScalar(info.bounds().fLeft),
+ SkIntToScalar(info.bounds().fTop),
+ SkIntToScalar(info.bounds().fRight),
+ SkIntToScalar(info.bounds().fBottom));
+
+ SkMatrix matrix = fSkXform;
+ SkScalar scale = fTextSizeRender / glyphData.pixelsPerEm;
+ matrix.preScale(scale, scale);
+ matrix.preTranslate(glyphData.horizontalLeftOrigin.x, -glyphData.horizontalLeftOrigin.y);
+ matrix.mapRect(&bounds);
+ if (this->isSubpixel()) {
+ matrix.preTranslate(SkFixedToScalar(glyph->getSubXFixed()),
+ SkFixedToScalar(glyph->getSubYFixed()));
+ }
+ bounds.roundOut();
+
+ glyph->fWidth = bounds.width();
+ glyph->fHeight = bounds.height();
+ glyph->fLeft = bounds.left();
+ glyph->fTop = bounds.top();
+ return;
+}
+
void SkScalerContext_DW::generateMetrics(SkGlyph* glyph) {
glyph->fWidth = 0;
glyph->fHeight = 0;
@@ -603,6 +683,12 @@ void SkScalerContext_DW::generateMetrics(SkGlyph* glyph) {
return;
}
+ if (fIsColorFont && isPngGlyph(*glyph)) {
+ glyph->fMaskFormat = SkMask::kARGB32_Format;
+ generatePngMetrics(glyph);
+ return;
+ }
+
RECT bbox;
HRVM(this->getBoundingBox(glyph, fRenderingMode, fTextureType, &bbox),
"Requested bounding box could not be determined.");
@@ -947,6 +1033,48 @@ void SkScalerContext_DW::generateColorGlyphImage(const SkGlyph& glyph) {
}
}
+void SkScalerContext_DW::generatePngGlyphImage(const SkGlyph& glyph) {
+ SkASSERT(isPngGlyph(glyph));
+ SkASSERT(glyph.fMaskFormat == SkMask::Format::kARGB32_Format);
+ SkASSERT(this->getDWriteTypeface()->fDWriteFontFace4);
+
+ IDWriteFontFace4* fontFace4 = this->getDWriteTypeface()->fDWriteFontFace4.get();
+ DWRITE_GLYPH_IMAGE_DATA glyphData;
+ void* glyphDataContext;
+ HRVM(fontFace4->GetGlyphImageData(glyph.getGlyphID(),
+ fTextSizeRender,
+ DWRITE_GLYPH_IMAGE_FORMATS_PNG,
+ &glyphData,
+ &glyphDataContext),
+ "Glyph image data could not be acquired.");
+ Context* context = new Context(fontFace4, glyphDataContext);
+ sk_sp<SkData> data = SkData::MakeWithProc(glyphData.imageData,
+ glyphData.imageDataSize,
+ &ReleaseProc,
+ context);
+ sk_sp<SkImage> image = SkImage::MakeFromEncoded(std::move(data));
+
+ SkBitmap dstBitmap;
+ dstBitmap.setInfo(SkImageInfo::Make(glyph.fWidth, glyph.fHeight,
+ kN32_SkColorType,
+ kPremul_SkAlphaType),
+ glyph.rowBytes());
+ dstBitmap.setPixels(glyph.fImage);
+
+ SkCanvas canvas(dstBitmap);
+ canvas.clear(SK_ColorTRANSPARENT);
+ canvas.translate(-glyph.fLeft, -glyph.fTop);
+ if (this->isSubpixel()) {
+ canvas.translate(SkFixedToScalar(glyph.getSubXFixed()),
+ SkFixedToScalar(glyph.getSubYFixed()));
+ }
+ canvas.concat(fSkXform);
+ SkScalar ratio = fTextSizeRender / glyphData.pixelsPerEm;
+ canvas.scale(ratio, ratio);
+ canvas.translate(glyphData.horizontalLeftOrigin.x, -glyphData.horizontalLeftOrigin.y);
+ canvas.drawImage(image, 0, 0, nullptr);
+}
+
void SkScalerContext_DW::generateImage(const SkGlyph& glyph) {
//Create the mask.
DWRITE_RENDERING_MODE renderingMode = fRenderingMode;
@@ -957,7 +1085,16 @@ void SkScalerContext_DW::generateImage(const SkGlyph& glyph) {
}
if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
- generateColorGlyphImage(glyph);
+ if (fIsColorFont) {
+ if (isColorGlyph(glyph)) {
+ generateColorGlyphImage(glyph);
+ return;
+ } else if (isPngGlyph(glyph)) {
+ generatePngGlyphImage(glyph);
+ return;
+ }
+ }
+ SkDEBUGFAIL("Could not generate image from the given color font format.");
return;
}
diff --git a/src/ports/SkScalerContext_win_dw.h b/src/ports/SkScalerContext_win_dw.h
index aa36194aa5..2a1f97074d 100644
--- a/src/ports/SkScalerContext_win_dw.h
+++ b/src/ports/SkScalerContext_win_dw.h
@@ -47,6 +47,8 @@ private:
bool isColorGlyph(const SkGlyph& glyph);
+ bool isPngGlyph(const SkGlyph& glyph);
+
DWriteFontTypeface* getDWriteTypeface() {
return static_cast<DWriteFontTypeface*>(this->getTypeface());
}
@@ -57,6 +59,11 @@ private:
void generateColorGlyphImage(const SkGlyph& glyph);
+ void generatePngMetrics(SkGlyph* glyph);
+
+ void generatePngGlyphImage(const SkGlyph& glyph);
+
+
SkTDArray<uint8_t> fBits;
/** The total matrix without the text height scale. */
SkMatrix fSkXform;
diff --git a/src/ports/SkTypeface_win_dw.h b/src/ports/SkTypeface_win_dw.h
index a671eb4855..ce0e753279 100644
--- a/src/ports/SkTypeface_win_dw.h
+++ b/src/ports/SkTypeface_win_dw.h
@@ -62,6 +62,9 @@ private:
if (!SUCCEEDED(fDWriteFontFace->QueryInterface(&fDWriteFontFace2))) {
SkASSERT_RELEASE(nullptr == fDWriteFontFace2.get());
}
+ if (!SUCCEEDED(fDWriteFontFace->QueryInterface(&fDWriteFontFace4))) {
+ SkASSERT_RELEASE(nullptr == fDWriteFontFace4.get());
+ }
if (!SUCCEEDED(fFactory->QueryInterface(&fFactory2))) {
SkASSERT_RELEASE(nullptr == fFactory2.get());
}
@@ -77,6 +80,7 @@ public:
SkTScopedComPtr<IDWriteFontFace> fDWriteFontFace;
SkTScopedComPtr<IDWriteFontFace1> fDWriteFontFace1;
SkTScopedComPtr<IDWriteFontFace2> fDWriteFontFace2;
+ SkTScopedComPtr<IDWriteFontFace4> fDWriteFontFace4;
static DWriteFontTypeface* Create(IDWriteFactory* factory,
IDWriteFontFace* fontFace,