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

Side by Side 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: rebase Created 4 years, 6 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 unified diff | Download patch
« no previous file with comments | « src/ports/SkScalerContext_win_dw.h ('k') | tools/sk_tool_utils.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2011 Google Inc. 2 * Copyright 2011 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkTypes.h" 8 #include "SkTypes.h"
9 #if defined(SK_BUILD_FOR_WIN32) 9 #if defined(SK_BUILD_FOR_WIN32)
10 10
11 #undef GetGlyphIndices 11 #undef GetGlyphIndices
12 12
13 #include "SkDraw.h"
13 #include "SkDWrite.h" 14 #include "SkDWrite.h"
14 #include "SkDWriteGeometrySink.h" 15 #include "SkDWriteGeometrySink.h"
15 #include "SkEndian.h" 16 #include "SkEndian.h"
16 #include "SkGlyph.h" 17 #include "SkGlyph.h"
17 #include "SkHRESULT.h" 18 #include "SkHRESULT.h"
18 #include "SkMaskGamma.h" 19 #include "SkMaskGamma.h"
19 #include "SkMatrix22.h" 20 #include "SkMatrix22.h"
20 #include "SkMutex.h" 21 #include "SkMutex.h"
21 #include "SkOTTable_EBLC.h" 22 #include "SkOTTable_EBLC.h"
22 #include "SkOTTable_EBSC.h" 23 #include "SkOTTable_EBSC.h"
23 #include "SkOTTable_gasp.h" 24 #include "SkOTTable_gasp.h"
24 #include "SkOTTable_maxp.h" 25 #include "SkOTTable_maxp.h"
25 #include "SkPath.h" 26 #include "SkPath.h"
27 #include "SkRasterClip.h"
26 #include "SkScalerContext.h" 28 #include "SkScalerContext.h"
27 #include "SkScalerContext_win_dw.h" 29 #include "SkScalerContext_win_dw.h"
28 #include "SkSharedMutex.h" 30 #include "SkSharedMutex.h"
29 #include "SkTScopedComPtr.h" 31 #include "SkTScopedComPtr.h"
30 #include "SkTypeface_win_dw.h" 32 #include "SkTypeface_win_dw.h"
31 33
32 #include <dwrite.h> 34 #include <dwrite.h>
33 #if SK_HAS_DWRITE_1_H 35 #if SK_HAS_DWRITE_1_H
34 # include <dwrite_1.h> 36 # include <dwrite_1.h>
35 #endif 37 #endif
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
203 both_zero(rec.fPost2x2[0][0], rec.fPost2x2[1][1])); 205 both_zero(rec.fPost2x2[0][0], rec.fPost2x2[1][1]));
204 } 206 }
205 207
206 SkScalerContext_DW::SkScalerContext_DW(DWriteFontTypeface* typeface, 208 SkScalerContext_DW::SkScalerContext_DW(DWriteFontTypeface* typeface,
207 const SkScalerContextEffects& effects, 209 const SkScalerContextEffects& effects,
208 const SkDescriptor* desc) 210 const SkDescriptor* desc)
209 : SkScalerContext(typeface, effects, desc) 211 : SkScalerContext(typeface, effects, desc)
210 , fTypeface(SkRef(typeface)) 212 , fTypeface(SkRef(typeface))
211 , fGlyphCount(-1) { 213 , fGlyphCount(-1) {
212 214
215 #if SK_HAS_DWRITE_2_H
216 fTypeface->fFactory->QueryInterface<IDWriteFactory2>(&fFactory2);
217
218 SkTScopedComPtr<IDWriteFontFace2> fontFace2;
219 fTypeface->fDWriteFontFace->QueryInterface<IDWriteFontFace2>(&fontFace2);
220 fIsColorFont = fFactory2.get() && fontFace2.get() && fontFace2->IsColorFont( );
221 #endif
222
213 // In general, all glyphs should use CLEARTYPE_NATURAL_SYMMETRIC 223 // In general, all glyphs should use CLEARTYPE_NATURAL_SYMMETRIC
214 // except when bi-level rendering is requested or there are embedded 224 // except when bi-level rendering is requested or there are embedded
215 // bi-level bitmaps (and the embedded bitmap flag is set and no rotation). 225 // bi-level bitmaps (and the embedded bitmap flag is set and no rotation).
216 // 226 //
217 // DirectWrite's IDWriteFontFace::GetRecommendedRenderingMode does not do 227 // DirectWrite's IDWriteFontFace::GetRecommendedRenderingMode does not do
218 // this. As a result, determine the actual size of the text and then see if 228 // this. As a result, determine the actual size of the text and then see if
219 // there are any embedded bi-level bitmaps of that size. If there are, then 229 // there are any embedded bi-level bitmaps of that size. If there are, then
220 // force bitmaps by requesting bi-level rendering. 230 // force bitmaps by requesting bi-level rendering.
221 // 231 //
222 // FreeType allows for separate ppemX and ppemY, but DirectWrite assumes 232 // FreeType allows for separate ppemX and ppemY, but DirectWrite assumes
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
451 if (bbox.left >= bbox.right || bbox.top >= bbox.bottom) { 461 if (bbox.left >= bbox.right || bbox.top >= bbox.bottom) {
452 return false; 462 return false;
453 } 463 }
454 glyph->fWidth = SkToU16(bbox.right - bbox.left); 464 glyph->fWidth = SkToU16(bbox.right - bbox.left);
455 glyph->fHeight = SkToU16(bbox.bottom - bbox.top); 465 glyph->fHeight = SkToU16(bbox.bottom - bbox.top);
456 glyph->fLeft = SkToS16(bbox.left); 466 glyph->fLeft = SkToS16(bbox.left);
457 glyph->fTop = SkToS16(bbox.top); 467 glyph->fTop = SkToS16(bbox.top);
458 return true; 468 return true;
459 } 469 }
460 470
471 bool SkScalerContext_DW::isColorGlyph(const SkGlyph& glyph) {
472 #if SK_HAS_DWRITE_2_H
473 SkTScopedComPtr<IDWriteColorGlyphRunEnumerator> colorLayer;
474 if (getColorGlyphRun(glyph, &colorLayer)) {
475 return true;
476 }
477 #endif
478 return false;
479 }
480
481 #if SK_HAS_DWRITE_2_H
482 bool SkScalerContext_DW::getColorGlyphRun(const SkGlyph& glyph,
483 IDWriteColorGlyphRunEnumerator** color Glyph)
484 {
485 FLOAT advance = 0;
486 UINT16 glyphId = glyph.getGlyphID();
487
488 DWRITE_GLYPH_OFFSET offset;
489 offset.advanceOffset = 0.0f;
490 offset.ascenderOffset = 0.0f;
491
492 DWRITE_GLYPH_RUN run;
493 run.glyphCount = 1;
494 run.glyphAdvances = &advance;
495 run.fontFace = fTypeface->fDWriteFontFace.get();
496 run.fontEmSize = SkScalarToFloat(fTextSizeRender);
497 run.bidiLevel = 0;
498 run.glyphIndices = &glyphId;
499 run.isSideways = FALSE;
500 run.glyphOffsets = &offset;
501
502 HRESULT hr = fFactory2->TranslateColorGlyphRun(
503 0, 0, &run, nullptr, fMeasuringMode, &fXform, 0, colorGlyph);
504 if (hr == DWRITE_E_NOCOLOR) {
505 return false;
506 }
507 HRBM(hr, "Failed to translate color glyph run");
508 return true;
509 }
510 #endif
511
461 void SkScalerContext_DW::generateMetrics(SkGlyph* glyph) { 512 void SkScalerContext_DW::generateMetrics(SkGlyph* glyph) {
462 glyph->fWidth = 0; 513 glyph->fWidth = 0;
463 glyph->fHeight = 0; 514 glyph->fHeight = 0;
464 glyph->fLeft = 0; 515 glyph->fLeft = 0;
465 glyph->fTop = 0; 516 glyph->fTop = 0;
466 517
467 this->generateAdvance(glyph); 518 this->generateAdvance(glyph);
468 519
520 #if SK_HAS_DWRITE_2_H
521 if (fIsColorFont && isColorGlyph(*glyph)) {
522 glyph->fMaskFormat = SkMask::kARGB32_Format;
523 }
524 #endif
525
469 RECT bbox; 526 RECT bbox;
470 HRVM(this->getBoundingBox(glyph, fRenderingMode, fTextureType, &bbox), 527 HRVM(this->getBoundingBox(glyph, fRenderingMode, fTextureType, &bbox),
471 "Requested bounding box could not be determined."); 528 "Requested bounding box could not be determined.");
472 529
473 if (glyph_check_and_set_bounds(glyph, bbox)) { 530 if (glyph_check_and_set_bounds(glyph, bbox)) {
474 return; 531 return;
475 } 532 }
476 533
477 // GetAlphaTextureBounds succeeds but returns an empty RECT if there are no 534 // GetAlphaTextureBounds succeeds but returns an empty RECT if there are no
478 // glyphs of the specified texture type. When this happens, try with the 535 // glyphs of the specified texture type. When this happens, try with the
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
703 HRNM(glyphRunAnalysis->CreateAlphaTexture(textureType, 760 HRNM(glyphRunAnalysis->CreateAlphaTexture(textureType,
704 &bbox, 761 &bbox,
705 fBits.begin(), 762 fBits.begin(),
706 sizeNeeded), 763 sizeNeeded),
707 "Could not draw mask."); 764 "Could not draw mask.");
708 } 765 }
709 } 766 }
710 return fBits.begin(); 767 return fBits.begin();
711 } 768 }
712 769
770 #if SK_HAS_DWRITE_2_H
771 void SkScalerContext_DW::generateColorGlyphImage(const SkGlyph& glyph) {
772 SkASSERT(isColorGlyph(glyph));
773 SkASSERT(glyph.fMaskFormat == SkMask::Format::kARGB32_Format);
774
775 memset(glyph.fImage, 0, glyph.computeImageSize());
776
777 SkTScopedComPtr<IDWriteColorGlyphRunEnumerator> colorLayers;
778 getColorGlyphRun(glyph, &colorLayers);
779 SkASSERT(colorLayers.get());
780
781 SkMatrix matrix = fSkXform;
782 matrix.postTranslate(-SkIntToScalar(glyph.fLeft), -SkIntToScalar(glyph.fTop) );
783 SkRasterClip rc(SkIRect::MakeWH(glyph.fWidth, glyph.fHeight));
784 SkDraw draw;
785 draw.fDst = SkPixmap(SkImageInfo::MakeN32(glyph.fWidth, glyph.fHeight, kPrem ul_SkAlphaType),
786 glyph.fImage,
787 glyph.ComputeRowBytes(glyph.fWidth, SkMask::Format::kAR GB32_Format));
788 draw.fMatrix = &matrix;
789 draw.fRC = &rc;
790
791 SkPaint paint;
792 if (fRenderingMode != DWRITE_RENDERING_MODE_ALIASED) {
793 paint.setFlags(SkPaint::Flags::kAntiAlias_Flag);
794 }
795
796 BOOL hasNextRun = FALSE;
797 while (SUCCEEDED(colorLayers->MoveNext(&hasNextRun)) && hasNextRun) {
798 const DWRITE_COLOR_GLYPH_RUN* colorGlyph;
799 HRVM(colorLayers->GetCurrentRun(&colorGlyph), "Could not get current col or glyph run");
800
801 SkColor color;
802 if (colorGlyph->paletteIndex != 0xffff) {
803 color = SkColorSetARGB(SkFloatToIntRound(colorGlyph->runColor.a * 25 5),
804 SkFloatToIntRound(colorGlyph->runColor.r * 25 5),
805 SkFloatToIntRound(colorGlyph->runColor.g * 25 5),
806 SkFloatToIntRound(colorGlyph->runColor.b * 25 5));
807 } else {
808 // If all components of runColor are 0 or (equivalently) paletteInde x is 0xFFFF then
809 // the 'current brush' is used. fRec.getLuminanceColor() is kinda so rta what is wanted
810 // here, but not really, it will often be the wrong value because it wan't designed for
811 // this.
812 // In practice, I've not encountered a color glyph that uses the cur rent brush color.
813 // If this assert ever fires, we should verify that the color is ren dered properly.
814 SkASSERT(false);
815 color = fRec.getLuminanceColor();
816 }
817 paint.setColor(color);
818
819 SkPath path;
820 SkTScopedComPtr<IDWriteGeometrySink> geometryToPath;
821 HRVM(SkDWriteGeometrySink::Create(&path, &geometryToPath),
822 "Could not create geometry to path converter.");
823 {
824 Exclusive l(DWriteFactoryMutex);
825 HRVM(colorGlyph->glyphRun.fontFace->GetGlyphRunOutline(
826 colorGlyph->glyphRun.fontEmSize,
827 colorGlyph->glyphRun.glyphIndices,
828 colorGlyph->glyphRun.glyphAdvances,
829 colorGlyph->glyphRun.glyphOffsets,
830 colorGlyph->glyphRun.glyphCount,
831 colorGlyph->glyphRun.isSideways,
832 colorGlyph->glyphRun.bidiLevel % 2, //rtl
833 geometryToPath.get()),
834 "Could not create glyph outline.");
835 }
836 draw.drawPath(path, paint, nullptr, true /* pathIsMutable */);
837 }
838 }
839 #endif
840
713 void SkScalerContext_DW::generateImage(const SkGlyph& glyph) { 841 void SkScalerContext_DW::generateImage(const SkGlyph& glyph) {
714 //Create the mask. 842 //Create the mask.
715 DWRITE_RENDERING_MODE renderingMode = fRenderingMode; 843 DWRITE_RENDERING_MODE renderingMode = fRenderingMode;
716 DWRITE_TEXTURE_TYPE textureType = fTextureType; 844 DWRITE_TEXTURE_TYPE textureType = fTextureType;
717 if (glyph.fForceBW) { 845 if (glyph.fForceBW) {
718 renderingMode = DWRITE_RENDERING_MODE_ALIASED; 846 renderingMode = DWRITE_RENDERING_MODE_ALIASED;
719 textureType = DWRITE_TEXTURE_ALIASED_1x1; 847 textureType = DWRITE_TEXTURE_ALIASED_1x1;
720 } 848 }
849
850 #if SK_HAS_DWRITE_2_H
851 if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
852 generateColorGlyphImage(glyph);
853 return;
854 }
855 #endif
856
721 const void* bits = this->drawDWMask(glyph, renderingMode, textureType); 857 const void* bits = this->drawDWMask(glyph, renderingMode, textureType);
722 if (!bits) { 858 if (!bits) {
723 sk_bzero(glyph.fImage, glyph.computeImageSize()); 859 sk_bzero(glyph.fImage, glyph.computeImageSize());
724 return; 860 return;
725 } 861 }
726 862
727 //Copy the mask into the glyph. 863 //Copy the mask into the glyph.
728 const uint8_t* src = (const uint8_t*)bits; 864 const uint8_t* src = (const uint8_t*)bits;
729 if (DWRITE_RENDERING_MODE_ALIASED == renderingMode) { 865 if (DWRITE_RENDERING_MODE_ALIASED == renderingMode) {
730 bilevel_to_bw(src, glyph); 866 bilevel_to_bw(src, glyph);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
774 FALSE, //sideways 910 FALSE, //sideways
775 FALSE, //rtl 911 FALSE, //rtl
776 geometryToPath.get()), 912 geometryToPath.get()),
777 "Could not create glyph outline."); 913 "Could not create glyph outline.");
778 } 914 }
779 915
780 path->transform(fSkXform); 916 path->transform(fSkXform);
781 } 917 }
782 918
783 #endif//defined(SK_BUILD_FOR_WIN32) 919 #endif//defined(SK_BUILD_FOR_WIN32)
OLDNEW
« no previous file with comments | « src/ports/SkScalerContext_win_dw.h ('k') | tools/sk_tool_utils.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698