| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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) |
| OLD | NEW |