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

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: 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 unified diff | Download patch
« no previous file with comments | « src/ports/SkScalerContext_win_dw.h ('k') | no next file » | 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
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
203 both_zero(rec.fPost2x2[0][0], rec.fPost2x2[1][1])); 203 both_zero(rec.fPost2x2[0][0], rec.fPost2x2[1][1]));
204 } 204 }
205 205
206 SkScalerContext_DW::SkScalerContext_DW(DWriteFontTypeface* typeface, 206 SkScalerContext_DW::SkScalerContext_DW(DWriteFontTypeface* typeface,
207 const SkScalerContextEffects& effects, 207 const SkScalerContextEffects& effects,
208 const SkDescriptor* desc) 208 const SkDescriptor* desc)
209 : SkScalerContext(typeface, effects, desc) 209 : SkScalerContext(typeface, effects, desc)
210 , fTypeface(SkRef(typeface)) 210 , fTypeface(SkRef(typeface))
211 , fGlyphCount(-1) { 211 , fGlyphCount(-1) {
212 212
213 #if SK_HAS_DWRITE_2_H
214 SkTScopedComPtr<IDWriteFactory> factory(SkSafeRefComPtr(sk_get_dwrite_factor y()));
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.
215 factory->QueryInterface<IDWriteFactory2>(&fFactory2);
216
217 SkTScopedComPtr<IDWriteFontFace2> fontFace2;
218 fTypeface->fDWriteFontFace->QueryInterface<IDWriteFontFace2>(&fontFace2);
219 fIsColorFont = fFactory2.get() && fontFace2.get() && fontFace2->IsColorFont( );
220 #endif
221
213 // In general, all glyphs should use CLEARTYPE_NATURAL_SYMMETRIC 222 // In general, all glyphs should use CLEARTYPE_NATURAL_SYMMETRIC
214 // except when bi-level rendering is requested or there are embedded 223 // 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). 224 // bi-level bitmaps (and the embedded bitmap flag is set and no rotation).
216 // 225 //
217 // DirectWrite's IDWriteFontFace::GetRecommendedRenderingMode does not do 226 // DirectWrite's IDWriteFontFace::GetRecommendedRenderingMode does not do
218 // this. As a result, determine the actual size of the text and then see if 227 // 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 228 // there are any embedded bi-level bitmaps of that size. If there are, then
220 // force bitmaps by requesting bi-level rendering. 229 // force bitmaps by requesting bi-level rendering.
221 // 230 //
222 // FreeType allows for separate ppemX and ppemY, but DirectWrite assumes 231 // 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) { 460 if (bbox.left >= bbox.right || bbox.top >= bbox.bottom) {
452 return false; 461 return false;
453 } 462 }
454 glyph->fWidth = SkToU16(bbox.right - bbox.left); 463 glyph->fWidth = SkToU16(bbox.right - bbox.left);
455 glyph->fHeight = SkToU16(bbox.bottom - bbox.top); 464 glyph->fHeight = SkToU16(bbox.bottom - bbox.top);
456 glyph->fLeft = SkToS16(bbox.left); 465 glyph->fLeft = SkToS16(bbox.left);
457 glyph->fTop = SkToS16(bbox.top); 466 glyph->fTop = SkToS16(bbox.top);
458 return true; 467 return true;
459 } 468 }
460 469
470 bool SkScalerContext_DW::isColorGlyph(const SkGlyph& glyph) {
471 #if SK_HAS_DWRITE_2_H
472 SkTScopedComPtr<IDWriteColorGlyphRunEnumerator> colorLayer;
473 if (getColorGlyphRun(glyph, &colorLayer)) {
474 return true;
475 }
476 #endif
477 return false;
478 }
479
480 #if SK_HAS_DWRITE_2_H
481 bool SkScalerContext_DW::getColorGlyphRun(const SkGlyph& glyph,
482 IDWriteColorGlyphRunEnumerator** color Glyph)
483 {
484 FLOAT advance = 0;
485 UINT16 glyphId = glyph.getGlyphID();
486
487 DWRITE_GLYPH_OFFSET offset;
488 offset.advanceOffset = 0.0f;
489 offset.ascenderOffset = 0.0f;
490
491 DWRITE_GLYPH_RUN run;
492 run.glyphCount = 1;
493 run.glyphAdvances = &advance;
494 run.fontFace = fTypeface->fDWriteFontFace.get();
495 run.fontEmSize = SkScalarToFloat(fTextSizeRender);
496 run.bidiLevel = 0;
497 run.glyphIndices = &glyphId;
498 run.isSideways = FALSE;
499 run.glyphOffsets = &offset;
500
501 HRESULT hr = fFactory2->TranslateColorGlyphRun(
502 0, 0, &run, nullptr, DWRITE_MEASURING_MODE_NATURAL, nullptr, 0, colorGly ph);
bungeman-skia 2016/05/18 14:50:55 Need to pass in fXform and fMeasuringMode.
Ilya Kulshin 2016/05/18 22:43:38 Done.
503 if (SUCCEEDED(hr)) {
504 return true;
505 } else {
506 SkASSERT(hr == DWRITE_E_NOCOLOR);
507 }
508 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.
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 HRESULT hr = S_OK;
bungeman-skia 2016/05/18 14:50:55 Remove this.
Ilya Kulshin 2016/05/18 22:43:38 Done.
774
775 memset(glyph.fImage, 0, glyph.computeImageSize());
776
777 SkTScopedComPtr<IDWriteColorGlyphRunEnumerator> colorLayers;
778 getColorGlyphRun(glyph, &colorLayers);
779 SkASSERT(colorLayers.get());
780
781 int layerSize = glyph.fWidth * glyph.fHeight; // layers are drawn in monochr ome
782 SkASSERT_RELEASE(layerSize * sizeof(uint32_t) == glyph.computeImageSize());
783 fBits.setCount(layerSize);
784
785 RECT bbox;
786 bbox.left = glyph.fLeft;
787 bbox.top = glyph.fTop;
788 bbox.right = glyph.fLeft + glyph.fWidth;
789 bbox.bottom = glyph.fTop + glyph.fHeight;
790
791 BOOL hasNextRun = FALSE;
792 while (SUCCEEDED(colorLayers->MoveNext(&hasNextRun)) && hasNextRun) {
793 const DWRITE_COLOR_GLYPH_RUN* colorGlyph;
794 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.
795 SkASSERT(false);
796 return;
797 }
798
799 SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
800 {
801 Exclusive l(DWriteFactoryMutex);
802 hr = fTypeface->fFactory->CreateGlyphRunAnalysis(&colorGlyph->glyphR un,
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.
803 1.0f, // pixelsPerDip,
804 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.
805 DWRITE_RENDERING_MODE_ALIASED,
806 DWRITE_MEASURING_MODE_NATURAL,
bungeman-skia 2016/05/18 14:50:55 fRenderingMode and fMeasuringMode
Ilya Kulshin 2016/05/18 22:43:38 Done.
807 colorGlyph->baselineOriginX,
808 colorGlyph->baselineOriginY,
809 &glyphRunAnalysis);
810 }
811 //NOTE: this assumes that the glyph has already been measured
812 //with an exact same glyph run analysis.
813 {
814 Shared l(DWriteFactoryMutex);
815 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.
816 &bbox,
817 fBits.begin(),
818 layerSize);
819 }
820
821 uint32_t* colorPixels = reinterpret_cast<uint32_t*>(glyph.fImage);
822 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
823 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.
824 colorGlyph->runColor.g * 255,
825 colorGlyph->runColor.b * 255);
826 for (int pixel = 0; pixel < layerSize; pixel++) {
827 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
828 colorPixels[pixel] = color;
829 }
830 }
831 }
832 }
833 #endif
834
713 void SkScalerContext_DW::generateImage(const SkGlyph& glyph) { 835 void SkScalerContext_DW::generateImage(const SkGlyph& glyph) {
714 //Create the mask. 836 //Create the mask.
715 DWRITE_RENDERING_MODE renderingMode = fRenderingMode; 837 DWRITE_RENDERING_MODE renderingMode = fRenderingMode;
716 DWRITE_TEXTURE_TYPE textureType = fTextureType; 838 DWRITE_TEXTURE_TYPE textureType = fTextureType;
717 if (glyph.fForceBW) { 839 if (glyph.fForceBW) {
718 renderingMode = DWRITE_RENDERING_MODE_ALIASED; 840 renderingMode = DWRITE_RENDERING_MODE_ALIASED;
719 textureType = DWRITE_TEXTURE_ALIASED_1x1; 841 textureType = DWRITE_TEXTURE_ALIASED_1x1;
720 } 842 }
843
844 #if SK_HAS_DWRITE_2_H
845 if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
846 generateColorGlyphImage(glyph);
847 return;
848 }
849 #endif
850
721 const void* bits = this->drawDWMask(glyph, renderingMode, textureType); 851 const void* bits = this->drawDWMask(glyph, renderingMode, textureType);
722 if (!bits) { 852 if (!bits) {
723 sk_bzero(glyph.fImage, glyph.computeImageSize()); 853 sk_bzero(glyph.fImage, glyph.computeImageSize());
724 return; 854 return;
725 } 855 }
726 856
727 //Copy the mask into the glyph. 857 //Copy the mask into the glyph.
728 const uint8_t* src = (const uint8_t*)bits; 858 const uint8_t* src = (const uint8_t*)bits;
729 if (DWRITE_RENDERING_MODE_ALIASED == renderingMode) { 859 if (DWRITE_RENDERING_MODE_ALIASED == renderingMode) {
730 bilevel_to_bw(src, glyph); 860 bilevel_to_bw(src, glyph);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
774 FALSE, //sideways 904 FALSE, //sideways
775 FALSE, //rtl 905 FALSE, //rtl
776 geometryToPath.get()), 906 geometryToPath.get()),
777 "Could not create glyph outline."); 907 "Could not create glyph outline.");
778 } 908 }
779 909
780 path->transform(fSkXform); 910 path->transform(fSkXform);
781 } 911 }
782 912
783 #endif//defined(SK_BUILD_FOR_WIN32) 913 #endif//defined(SK_BUILD_FOR_WIN32)
OLDNEW
« 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