| 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 #undef GetGlyphIndices | 9 #undef GetGlyphIndices |
| 10 | 10 |
| 11 #include "SkAdvancedTypefaceMetrics.h" | 11 #include "SkAdvancedTypefaceMetrics.h" |
| 12 #include "SkColorFilter.h" | 12 #include "SkColorFilter.h" |
| 13 #include "SkDWrite.h" | 13 #include "SkDWrite.h" |
| 14 #include "SkDWriteFontFileStream.h" | 14 #include "SkDWriteFontFileStream.h" |
| 15 #include "SkDWriteGeometrySink.h" | 15 #include "SkDWriteGeometrySink.h" |
| 16 #include "SkDescriptor.h" | 16 #include "SkDescriptor.h" |
| 17 #include "SkEndian.h" | 17 #include "SkEndian.h" |
| 18 #include "SkFontDescriptor.h" | 18 #include "SkFontDescriptor.h" |
| 19 #include "SkFontHost.h" | 19 #include "SkFontHost.h" |
| 20 #include "SkFontMgr.h" | 20 #include "SkFontMgr.h" |
| 21 #include "SkFontStream.h" | 21 #include "SkFontStream.h" |
| 22 #include "SkGlyph.h" | 22 #include "SkGlyph.h" |
| 23 #include "SkHRESULT.h" | 23 #include "SkHRESULT.h" |
| 24 #include "SkMaskGamma.h" | 24 #include "SkMaskGamma.h" |
| 25 #include "SkMatrix22.h" |
| 25 #include "SkOnce.h" | 26 #include "SkOnce.h" |
| 27 #include "SkOTTable_EBLC.h" |
| 28 #include "SkOTTable_EBSC.h" |
| 26 #include "SkOTTable_head.h" | 29 #include "SkOTTable_head.h" |
| 27 #include "SkOTTable_hhea.h" | 30 #include "SkOTTable_hhea.h" |
| 28 #include "SkOTTable_OS_2.h" | 31 #include "SkOTTable_OS_2.h" |
| 29 #include "SkOTTable_post.h" | 32 #include "SkOTTable_post.h" |
| 30 #include "SkPath.h" | 33 #include "SkPath.h" |
| 31 #include "SkStream.h" | 34 #include "SkStream.h" |
| 32 #include "SkString.h" | 35 #include "SkString.h" |
| 33 #include "SkTScopedComPtr.h" | 36 #include "SkTScopedComPtr.h" |
| 34 #include "SkThread.h" | 37 #include "SkThread.h" |
| 35 #include "SkTypeface_win.h" | 38 #include "SkTypeface_win.h" |
| (...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 442 virtual void generateMetrics(SkGlyph* glyph) SK_OVERRIDE; | 445 virtual void generateMetrics(SkGlyph* glyph) SK_OVERRIDE; |
| 443 virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE; | 446 virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE; |
| 444 virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE; | 447 virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE; |
| 445 virtual void generateFontMetrics(SkPaint::FontMetrics* mX, | 448 virtual void generateFontMetrics(SkPaint::FontMetrics* mX, |
| 446 SkPaint::FontMetrics* mY) SK_OVERRIDE; | 449 SkPaint::FontMetrics* mY) SK_OVERRIDE; |
| 447 | 450 |
| 448 private: | 451 private: |
| 449 const void* drawDWMask(const SkGlyph& glyph); | 452 const void* drawDWMask(const SkGlyph& glyph); |
| 450 | 453 |
| 451 SkTDArray<uint8_t> fBits; | 454 SkTDArray<uint8_t> fBits; |
| 455 /** The total matrix without the text height scale. */ |
| 456 SkMatrix fSkXform; |
| 457 /** The total matrix without the text height scale. */ |
| 452 DWRITE_MATRIX fXform; | 458 DWRITE_MATRIX fXform; |
| 459 /** The non-rotational part of total matrix without the text height scale. |
| 460 * This is used to find the magnitude of gdi compatible advances. |
| 461 */ |
| 462 DWRITE_MATRIX fGsA; |
| 463 /** The inverse of the rotational part of the total matrix. |
| 464 * This is used to find the direction of gdi compatible advances. |
| 465 */ |
| 466 SkMatrix fG_inv; |
| 467 /** The text size to render with. */ |
| 468 SkScalar fTextSizeRender; |
| 469 /** The text size to measure with. */ |
| 470 SkScalar fTextSizeMeasure; |
| 453 SkAutoTUnref<DWriteFontTypeface> fTypeface; | 471 SkAutoTUnref<DWriteFontTypeface> fTypeface; |
| 454 int fGlyphCount; | 472 int fGlyphCount; |
| 455 DWRITE_RENDERING_MODE fRenderingMode; | 473 DWRITE_RENDERING_MODE fRenderingMode; |
| 456 DWRITE_TEXTURE_TYPE fTextureType; | 474 DWRITE_TEXTURE_TYPE fTextureType; |
| 457 DWRITE_MEASURING_MODE fMeasuringMode; | 475 DWRITE_MEASURING_MODE fMeasuringMode; |
| 458 }; | 476 }; |
| 459 | 477 |
| 460 static bool are_same(IUnknown* a, IUnknown* b) { | 478 static bool are_same(IUnknown* a, IUnknown* b) { |
| 461 SkTScopedComPtr<IUnknown> iunkA; | 479 SkTScopedComPtr<IUnknown> iunkA; |
| 462 if (FAILED(a->QueryInterface(&iunkA))) { | 480 if (FAILED(a->QueryInterface(&iunkA))) { |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 563 | 581 |
| 564 SkSMallocWCHAR dwFontFamilyNameChar(dwFontFamilyNameLength+1); | 582 SkSMallocWCHAR dwFontFamilyNameChar(dwFontFamilyNameLength+1); |
| 565 SkSMallocWCHAR dwFontNameChar(dwFontNameLength+1); | 583 SkSMallocWCHAR dwFontNameChar(dwFontNameLength+1); |
| 566 HRB(dwFontFamilyNames->GetString(0, dwFontFamilyNameChar.get(), dwFontFamily
NameLength+1)); | 584 HRB(dwFontFamilyNames->GetString(0, dwFontFamilyNameChar.get(), dwFontFamily
NameLength+1)); |
| 567 HRB(dwFontNames->GetString(0, dwFontNameChar.get(), dwFontNameLength+1)); | 585 HRB(dwFontNames->GetString(0, dwFontNameChar.get(), dwFontNameLength+1)); |
| 568 | 586 |
| 569 return wcscmp(dwFaceFontFamilyNameChar.get(), dwFontFamilyNameChar.get()) ==
0 && | 587 return wcscmp(dwFaceFontFamilyNameChar.get(), dwFontFamilyNameChar.get()) ==
0 && |
| 570 wcscmp(dwFaceFontNameChar.get(), dwFontNameChar.get()) == 0; | 588 wcscmp(dwFaceFontNameChar.get(), dwFontNameChar.get()) == 0; |
| 571 } | 589 } |
| 572 | 590 |
| 591 class AutoDWriteTable { |
| 592 public: |
| 593 AutoDWriteTable(IDWriteFontFace* fontFace, UINT32 beTag) : fFontFace(fontFac
e), fExists(FALSE) { |
| 594 // Any errors are ignored, user must check fExists anyway. |
| 595 fontFace->TryGetFontTable(beTag, |
| 596 reinterpret_cast<const void **>(&fData), &fSize, &fLock, &fExists); |
| 597 } |
| 598 ~AutoDWriteTable() { |
| 599 if (fExists) { |
| 600 fFontFace->ReleaseFontTable(fLock); |
| 601 } |
| 602 } |
| 603 |
| 604 const uint8_t* fData; |
| 605 UINT32 fSize; |
| 606 BOOL fExists; |
| 607 private: |
| 608 // Borrowed reference, the user must ensure the fontFace stays alive. |
| 609 IDWriteFontFace* fFontFace; |
| 610 void* fLock; |
| 611 }; |
| 612 template<typename T> class AutoTDWriteTable : public AutoDWriteTable { |
| 613 public: |
| 614 static const UINT32 tag = DWRITE_MAKE_OPENTYPE_TAG(T::TAG0, T::TAG1, T::TAG2
, T::TAG3); |
| 615 AutoTDWriteTable(IDWriteFontFace* fontFace) : AutoDWriteTable(fontFace, tag)
{ } |
| 616 |
| 617 const T* get() const { return reinterpret_cast<const T*>(fData); } |
| 618 const T* operator->() const { return reinterpret_cast<const T*>(fData); } |
| 619 }; |
| 620 |
| 621 static bool hasBitmapStrike(DWriteFontTypeface* typeface, int size) { |
| 622 { |
| 623 AutoTDWriteTable<SkOTTableEmbeddedBitmapLocation> eblc(typeface->fDWrite
FontFace.get()); |
| 624 if (!eblc.fExists) { |
| 625 return false; |
| 626 } |
| 627 if (eblc.fSize < sizeof(SkOTTableEmbeddedBitmapLocation)) { |
| 628 return false; |
| 629 } |
| 630 if (eblc->version != SkOTTableEmbeddedBitmapLocation::version_initial) { |
| 631 return false; |
| 632 } |
| 633 |
| 634 uint32_t numSizes = SkEndianSwap32(eblc->numSizes); |
| 635 if (eblc.fSize < sizeof(SkOTTableEmbeddedBitmapLocation) + |
| 636 sizeof(SkOTTableEmbeddedBitmapLocation::BitmapSizeTable
) * numSizes) |
| 637 { |
| 638 return false; |
| 639 } |
| 640 |
| 641 const SkOTTableEmbeddedBitmapLocation::BitmapSizeTable* sizeTable = |
| 642 SkTAfter<const SkOTTableEmbeddedBitmapLocation::BitmapSizeTable>
(eblc.get()); |
| 643 for (uint32_t i = 0; i < numSizes; ++i, ++sizeTable) { |
| 644 if (sizeTable->ppemX == size && sizeTable->ppemY == size) { |
| 645 // TODO: determine if we should dig through IndexSubTableArray/I
ndexSubTable |
| 646 // to determine the actual number of glyphs with bitmaps. |
| 647 |
| 648 // TODO: Ensure that the bitmaps actually cover a significant po
rtion of the strike. |
| 649 |
| 650 //TODO: Endure that the bitmaps are bi-level. |
| 651 if (sizeTable->endGlyphIndex >= sizeTable->startGlyphIndex + 3)
{ |
| 652 return true; |
| 653 } |
| 654 } |
| 655 } |
| 656 } |
| 657 |
| 658 { |
| 659 AutoTDWriteTable<SkOTTableEmbeddedBitmapScaling> ebsc(typeface->fDWriteF
ontFace.get()); |
| 660 if (!ebsc.fExists) { |
| 661 return false; |
| 662 } |
| 663 if (ebsc.fSize < sizeof(SkOTTableEmbeddedBitmapScaling)) { |
| 664 return false; |
| 665 } |
| 666 if (ebsc->version != SkOTTableEmbeddedBitmapScaling::version_initial) { |
| 667 return false; |
| 668 } |
| 669 |
| 670 uint32_t numSizes = SkEndianSwap32(ebsc->numSizes); |
| 671 if (ebsc.fSize < sizeof(SkOTTableEmbeddedBitmapScaling) + |
| 672 sizeof(SkOTTableEmbeddedBitmapScaling::BitmapScaleTable
) * numSizes) |
| 673 { |
| 674 return false; |
| 675 } |
| 676 |
| 677 const SkOTTableEmbeddedBitmapScaling::BitmapScaleTable* scaleTable = |
| 678 SkTAfter<const SkOTTableEmbeddedBitmapScaling::BitmapScaleTable>
(ebsc.get()); |
| 679 for (uint32_t i = 0; i < numSizes; ++i, ++scaleTable) { |
| 680 if (scaleTable->ppemX == size && scaleTable->ppemY == size) { |
| 681 // EBSC tables are normally only found in bitmap only fonts. |
| 682 return true; |
| 683 } |
| 684 } |
| 685 } |
| 686 |
| 687 return false; |
| 688 } |
| 689 |
| 690 static bool bothZero(SkScalar a, SkScalar b) { |
| 691 return 0 == a && 0 == b; |
| 692 } |
| 693 |
| 694 // returns false if there is any non-90-rotation or skew |
| 695 static bool isAxisAligned(const SkScalerContext::Rec& rec) { |
| 696 return 0 == rec.fPreSkewX && |
| 697 (bothZero(rec.fPost2x2[0][1], rec.fPost2x2[1][0]) || |
| 698 bothZero(rec.fPost2x2[0][0], rec.fPost2x2[1][1])); |
| 699 } |
| 700 |
| 573 SkScalerContext_DW::SkScalerContext_DW(DWriteFontTypeface* typeface, | 701 SkScalerContext_DW::SkScalerContext_DW(DWriteFontTypeface* typeface, |
| 574 const SkDescriptor* desc) | 702 const SkDescriptor* desc) |
| 575 : SkScalerContext(typeface, desc) | 703 : SkScalerContext(typeface, desc) |
| 576 , fTypeface(SkRef(typeface)) | 704 , fTypeface(SkRef(typeface)) |
| 577 , fGlyphCount(-1) { | 705 , fGlyphCount(-1) { |
| 578 | 706 |
| 579 fXform.m11 = SkScalarToFloat(fRec.fPost2x2[0][0]); | 707 // In general, all glyphs should use CLEARTYPE_NATURAL_SYMMETRIC |
| 580 fXform.m12 = SkScalarToFloat(fRec.fPost2x2[1][0]); | 708 // except when bi-level rendering is requested or there are embedded |
| 581 fXform.m21 = SkScalarToFloat(fRec.fPost2x2[0][1]); | 709 // bi-level bitmaps (and the embedded bitmap flag is set and no rotation). |
| 582 fXform.m22 = SkScalarToFloat(fRec.fPost2x2[1][1]); | 710 // |
| 711 // DirectWrite's IDWriteFontFace::GetRecommendedRenderingMode does not do |
| 712 // this. As a result, determine the actual size of the text and then see if |
| 713 // there are any embedded bi-level bitmaps of that size. If there are, then |
| 714 // force bitmaps by requesting bi-level rendering. |
| 715 // |
| 716 // FreeType allows for separate ppemX and ppemY, but DirectWrite assumes |
| 717 // square pixels and only uses ppemY. Therefore the transform must track any |
| 718 // non-uniform x-scale. |
| 719 // |
| 720 // Also, rotated glyphs should have the same absolute advance widths as |
| 721 // horizontal glyphs and the subpixel flag should not affect glyph shapes. |
| 722 |
| 723 // A is the total matrix. |
| 724 SkMatrix A; |
| 725 fRec.getSingleMatrix(&A); |
| 726 |
| 727 // h is where A maps the horizontal baseline. |
| 728 SkPoint h = SkPoint::Make(SK_Scalar1, 0); |
| 729 A.mapPoints(&h, 1); |
| 730 |
| 731 // G is the Givens Matrix for A (rotational matrix where GA[0][1] == 0). |
| 732 SkMatrix G; |
| 733 SkComputeGivensRotation(h, &G); |
| 734 |
| 735 // GA is the matrix A with rotation removed. |
| 736 SkMatrix GA(G); |
| 737 GA.preConcat(A); |
| 738 |
| 739 // realTextSize is the actual device size we want (as opposed to the size th
e user requested). |
| 740 // gdiTextSize is the size we request when GDI compatible. |
| 741 // If the scale is negative, this means the matrix will do the flip anyway. |
| 742 SkScalar realTextSize = SkScalarAbs(GA.get(SkMatrix::kMScaleY)); |
| 743 // Due to floating point math, the lower bits are suspect. Round carefully. |
| 744 SkScalar roundedTextSize = SkScalarRoundToScalar(realTextSize * 64.0f) / 64.
0f; |
| 745 SkScalar gdiTextSize = SkScalarFloorToScalar(roundedTextSize); |
| 746 if (gdiTextSize == 0) { |
| 747 gdiTextSize = SK_Scalar1; |
| 748 } |
| 749 |
| 750 bool hasBitmap = fRec.fFlags & SkScalerContext::kEmbeddedBitmapText_Flag && |
| 751 hasBitmapStrike(typeface, SkScalarTruncToInt(gdiTextSize)); |
| 752 bool axisAligned = isAxisAligned(fRec); |
| 753 bool isBiLevel = SkMask::kBW_Format == fRec.fMaskFormat || (hasBitmap && axi
sAligned); |
| 754 |
| 755 if (isBiLevel) { |
| 756 fTextSizeRender = gdiTextSize; |
| 757 fRenderingMode = DWRITE_RENDERING_MODE_ALIASED; |
| 758 fTextureType = DWRITE_TEXTURE_ALIASED_1x1; |
| 759 fTextSizeMeasure = gdiTextSize; |
| 760 fMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC; |
| 761 } else if (hasBitmap) { |
| 762 // If rotated but the horizontal text would have used a bitmap, |
| 763 // render high quality rotated glyphs using the bitmap metrics. |
| 764 fTextSizeRender = gdiTextSize; |
| 765 fRenderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC; |
| 766 fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1; |
| 767 fTextSizeMeasure = gdiTextSize; |
| 768 fMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC; |
| 769 } else { |
| 770 fTextSizeRender = realTextSize; |
| 771 fRenderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC; |
| 772 fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1; |
| 773 fTextSizeMeasure = realTextSize; |
| 774 fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL; |
| 775 } |
| 776 |
| 777 if (this->isSubpixel()) { |
| 778 fTextSizeMeasure = realTextSize; |
| 779 fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL; |
| 780 } |
| 781 |
| 782 // Remove the realTextSize, as that is the text height scale currently in A. |
| 783 SkScalar scale = SkScalarInvert(realTextSize); |
| 784 |
| 785 // fSkXform is the total matrix A without the text height scale. |
| 786 fSkXform = A; |
| 787 fSkXform.preScale(scale, scale); //remove the text height scale. |
| 788 |
| 789 fXform.m11 = SkScalarToFloat(fSkXform.getScaleX()); |
| 790 fXform.m12 = SkScalarToFloat(fSkXform.getSkewY()); |
| 791 fXform.m21 = SkScalarToFloat(fSkXform.getSkewX()); |
| 792 fXform.m22 = SkScalarToFloat(fSkXform.getScaleY()); |
| 583 fXform.dx = 0; | 793 fXform.dx = 0; |
| 584 fXform.dy = 0; | 794 fXform.dy = 0; |
| 585 | 795 |
| 586 if (SkMask::kBW_Format == fRec.fMaskFormat) { | 796 // GsA is the non-rotational part of A without the text height scale. |
| 587 fRenderingMode = DWRITE_RENDERING_MODE_ALIASED; | 797 SkMatrix GsA(GA); |
| 588 fTextureType = DWRITE_TEXTURE_ALIASED_1x1; | 798 GsA.preScale(scale, scale); //remove text height scale, G is rotational so r
eorders with scale. |
| 589 fMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC; | 799 |
| 590 } else { | 800 fGsA.m11 = SkScalarToFloat(GsA.get(SkMatrix::kMScaleX)); |
| 591 fRenderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC; | 801 fGsA.m12 = SkScalarToFloat(GsA.get(SkMatrix::kMSkewY)); // This should be ~0
. |
| 592 fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1; | 802 fGsA.m21 = SkScalarToFloat(GsA.get(SkMatrix::kMSkewX)); |
| 593 fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL; | 803 fGsA.m22 = SkScalarToFloat(GsA.get(SkMatrix::kMScaleY)); |
| 594 } | 804 |
| 595 | 805 // fG_inv is G inverse, which is fairly simple since G is 2x2 rotational. |
| 596 if (this->isSubpixel()) { | 806 fG_inv.setAll(G.get(SkMatrix::kMScaleX), -G.get(SkMatrix::kMSkewX), G.get(Sk
Matrix::kMTransX), |
| 597 fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL; | 807 -G.get(SkMatrix::kMSkewY), G.get(SkMatrix::kMScaleY), G.get(Sk
Matrix::kMTransY), |
| 598 } | 808 G.get(SkMatrix::kMPersp0), G.get(SkMatrix::kMPersp1), G.get(Sk
Matrix::kMPersp2)); |
| 599 } | 809 } |
| 600 | 810 |
| 601 SkScalerContext_DW::~SkScalerContext_DW() { | 811 SkScalerContext_DW::~SkScalerContext_DW() { |
| 602 } | 812 } |
| 603 | 813 |
| 604 unsigned SkScalerContext_DW::generateGlyphCount() { | 814 unsigned SkScalerContext_DW::generateGlyphCount() { |
| 605 if (fGlyphCount < 0) { | 815 if (fGlyphCount < 0) { |
| 606 fGlyphCount = fTypeface->fDWriteFontFace->GetGlyphCount(); | 816 fGlyphCount = fTypeface->fDWriteFontFace->GetGlyphCount(); |
| 607 } | 817 } |
| 608 return fGlyphCount; | 818 return fGlyphCount; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 624 glyph->fAdvanceX = 0; | 834 glyph->fAdvanceX = 0; |
| 625 glyph->fAdvanceY = 0; | 835 glyph->fAdvanceY = 0; |
| 626 | 836 |
| 627 uint16_t glyphId = glyph->getGlyphID(); | 837 uint16_t glyphId = glyph->getGlyphID(); |
| 628 DWRITE_GLYPH_METRICS gm; | 838 DWRITE_GLYPH_METRICS gm; |
| 629 | 839 |
| 630 if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode || | 840 if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode || |
| 631 DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode) | 841 DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode) |
| 632 { | 842 { |
| 633 HRVM(fTypeface->fDWriteFontFace->GetGdiCompatibleGlyphMetrics( | 843 HRVM(fTypeface->fDWriteFontFace->GetGdiCompatibleGlyphMetrics( |
| 634 fRec.fTextSize, | 844 fTextSizeMeasure, |
| 635 1.0f, // pixelsPerDip | 845 1.0f, // pixelsPerDip |
| 636 &fXform, | 846 &fGsA, |
| 637 DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode, | 847 DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode, |
| 638 &glyphId, 1, | 848 &glyphId, 1, |
| 639 &gm), | 849 &gm), |
| 640 "Could not get gdi compatible glyph metrics."); | 850 "Could not get gdi compatible glyph metrics."); |
| 641 } else { | 851 } else { |
| 642 HRVM(fTypeface->fDWriteFontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm)
, | 852 HRVM(fTypeface->fDWriteFontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm)
, |
| 643 "Could not get design metrics."); | 853 "Could not get design metrics."); |
| 644 } | 854 } |
| 645 | 855 |
| 646 DWRITE_FONT_METRICS dwfm; | 856 DWRITE_FONT_METRICS dwfm; |
| 647 fTypeface->fDWriteFontFace->GetMetrics(&dwfm); | 857 fTypeface->fDWriteFontFace->GetMetrics(&dwfm); |
| 648 SkScalar advanceX = SkScalarMulDiv(fRec.fTextSize, | 858 SkScalar advanceX = SkScalarMulDiv(fTextSizeMeasure, |
| 649 SkIntToScalar(gm.advanceWidth), | 859 SkIntToScalar(gm.advanceWidth), |
| 650 SkIntToScalar(dwfm.designUnitsPerEm)); | 860 SkIntToScalar(dwfm.designUnitsPerEm)); |
| 651 | 861 |
| 652 if (!this->isSubpixel()) { | 862 if (!this->isSubpixel()) { |
| 653 advanceX = SkScalarRoundToScalar(advanceX); | 863 advanceX = SkScalarRoundToScalar(advanceX); |
| 654 } | 864 } |
| 655 | 865 |
| 656 SkVector vecs[1] = { { advanceX, 0 } }; | 866 SkVector vecs[1] = { { advanceX, 0 } }; |
| 657 SkMatrix mat; | 867 if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode || |
| 658 fRec.getMatrixFrom2x2(&mat); | 868 DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode) |
| 659 mat.mapVectors(vecs, SK_ARRAY_COUNT(vecs)); | 869 { |
| 870 fG_inv.mapVectors(vecs, SK_ARRAY_COUNT(vecs)); |
| 871 } else { |
| 872 fSkXform.mapVectors(vecs, SK_ARRAY_COUNT(vecs)); |
| 873 } |
| 660 | 874 |
| 661 glyph->fAdvanceX = SkScalarToFixed(vecs[0].fX); | 875 glyph->fAdvanceX = SkScalarToFixed(vecs[0].fX); |
| 662 glyph->fAdvanceY = SkScalarToFixed(vecs[0].fY); | 876 glyph->fAdvanceY = SkScalarToFixed(vecs[0].fY); |
| 663 } | 877 } |
| 664 | 878 |
| 665 void SkScalerContext_DW::generateMetrics(SkGlyph* glyph) { | 879 void SkScalerContext_DW::generateMetrics(SkGlyph* glyph) { |
| 666 glyph->fWidth = 0; | 880 glyph->fWidth = 0; |
| 667 | 881 |
| 668 this->generateAdvance(glyph); | 882 this->generateAdvance(glyph); |
| 669 | 883 |
| 670 //Measure raster size. | 884 //Measure raster size. |
| 671 fXform.dx = SkFixedToFloat(glyph->getSubXFixed()); | 885 fXform.dx = SkFixedToFloat(glyph->getSubXFixed()); |
| 672 fXform.dy = SkFixedToFloat(glyph->getSubYFixed()); | 886 fXform.dy = SkFixedToFloat(glyph->getSubYFixed()); |
| 673 | 887 |
| 674 FLOAT advance = 0; | 888 FLOAT advance = 0; |
| 675 | 889 |
| 676 UINT16 glyphId = glyph->getGlyphID(); | 890 UINT16 glyphId = glyph->getGlyphID(); |
| 677 | 891 |
| 678 DWRITE_GLYPH_OFFSET offset; | 892 DWRITE_GLYPH_OFFSET offset; |
| 679 offset.advanceOffset = 0.0f; | 893 offset.advanceOffset = 0.0f; |
| 680 offset.ascenderOffset = 0.0f; | 894 offset.ascenderOffset = 0.0f; |
| 681 | 895 |
| 682 DWRITE_GLYPH_RUN run; | 896 DWRITE_GLYPH_RUN run; |
| 683 run.glyphCount = 1; | 897 run.glyphCount = 1; |
| 684 run.glyphAdvances = &advance; | 898 run.glyphAdvances = &advance; |
| 685 run.fontFace = fTypeface->fDWriteFontFace.get(); | 899 run.fontFace = fTypeface->fDWriteFontFace.get(); |
| 686 run.fontEmSize = SkScalarToFloat(fRec.fTextSize); | 900 run.fontEmSize = SkScalarToFloat(fTextSizeRender); |
| 687 run.bidiLevel = 0; | 901 run.bidiLevel = 0; |
| 688 run.glyphIndices = &glyphId; | 902 run.glyphIndices = &glyphId; |
| 689 run.isSideways = FALSE; | 903 run.isSideways = FALSE; |
| 690 run.glyphOffsets = &offset; | 904 run.glyphOffsets = &offset; |
| 691 | 905 |
| 692 SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis; | 906 SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis; |
| 693 HRVM(fTypeface->fFactory->CreateGlyphRunAnalysis( | 907 HRVM(fTypeface->fFactory->CreateGlyphRunAnalysis( |
| 694 &run, | 908 &run, |
| 695 1.0f, // pixelsPerDip, | 909 1.0f, // pixelsPerDip, |
| 696 &fXform, | 910 &fXform, |
| (...skipping 24 matching lines...) Expand all Loading... |
| 721 } | 935 } |
| 722 if (my) { | 936 if (my) { |
| 723 sk_bzero(my, sizeof(*my)); | 937 sk_bzero(my, sizeof(*my)); |
| 724 } | 938 } |
| 725 | 939 |
| 726 DWRITE_FONT_METRICS dwfm; | 940 DWRITE_FONT_METRICS dwfm; |
| 727 if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode || | 941 if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode || |
| 728 DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode) | 942 DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode) |
| 729 { | 943 { |
| 730 fTypeface->fDWriteFontFace->GetGdiCompatibleMetrics( | 944 fTypeface->fDWriteFontFace->GetGdiCompatibleMetrics( |
| 731 fRec.fTextSize, | 945 fTextSizeRender, |
| 732 1.0f, // pixelsPerDip | 946 1.0f, // pixelsPerDip |
| 733 &fXform, | 947 &fXform, |
| 734 &dwfm); | 948 &dwfm); |
| 735 } else { | 949 } else { |
| 736 fTypeface->fDWriteFontFace->GetMetrics(&dwfm); | 950 fTypeface->fDWriteFontFace->GetMetrics(&dwfm); |
| 737 } | 951 } |
| 738 | 952 |
| 739 SkScalar upem = SkIntToScalar(dwfm.designUnitsPerEm); | 953 SkScalar upem = SkIntToScalar(dwfm.designUnitsPerEm); |
| 740 if (mx) { | 954 if (mx) { |
| 741 mx->fTop = -fRec.fTextSize * SkIntToScalar(dwfm.ascent) / upem; | 955 mx->fTop = -fTextSizeRender * SkIntToScalar(dwfm.ascent) / upem; |
| 742 mx->fAscent = mx->fTop; | 956 mx->fAscent = mx->fTop; |
| 743 mx->fDescent = fRec.fTextSize * SkIntToScalar(dwfm.descent) / upem; | 957 mx->fDescent = fTextSizeRender * SkIntToScalar(dwfm.descent) / upem; |
| 744 mx->fBottom = mx->fDescent; | 958 mx->fBottom = mx->fDescent; |
| 745 mx->fLeading = fRec.fTextSize * SkIntToScalar(dwfm.lineGap) / upem; | 959 mx->fLeading = fTextSizeRender * SkIntToScalar(dwfm.lineGap) / upem; |
| 746 mx->fXHeight = fRec.fTextSize * SkIntToScalar(dwfm.xHeight) / upem; | 960 mx->fXHeight = fTextSizeRender * SkIntToScalar(dwfm.xHeight) / upem; |
| 747 mx->fUnderlineThickness = fRec.fTextSize * SkIntToScalar(dwfm.underlineP
osition) / upem; | 961 mx->fUnderlineThickness = fTextSizeRender * SkIntToScalar(dwfm.underline
Position) / upem; |
| 748 mx->fUnderlinePosition = -(fRec.fTextSize * SkIntToScalar(dwfm.underline
Thickness) / upem); | 962 mx->fUnderlinePosition = -(fTextSizeRender * SkIntToScalar(dwfm.underlin
eThickness) / upem); |
| 749 | 963 |
| 750 mx->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag; | 964 mx->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag; |
| 751 mx->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag; | 965 mx->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag; |
| 752 } | 966 } |
| 753 | 967 |
| 754 if (my) { | 968 if (my) { |
| 755 my->fTop = -fRec.fTextSize * SkIntToScalar(dwfm.ascent) / upem; | 969 my->fTop = -fTextSizeRender * SkIntToScalar(dwfm.ascent) / upem; |
| 756 my->fAscent = my->fTop; | 970 my->fAscent = my->fTop; |
| 757 my->fDescent = fRec.fTextSize * SkIntToScalar(dwfm.descent) / upem; | 971 my->fDescent = fTextSizeRender * SkIntToScalar(dwfm.descent) / upem; |
| 758 my->fBottom = my->fDescent; | 972 my->fBottom = my->fDescent; |
| 759 my->fLeading = fRec.fTextSize * SkIntToScalar(dwfm.lineGap) / upem; | 973 my->fLeading = fTextSizeRender * SkIntToScalar(dwfm.lineGap) / upem; |
| 760 my->fXHeight = fRec.fTextSize * SkIntToScalar(dwfm.xHeight) / upem; | 974 my->fXHeight = fTextSizeRender * SkIntToScalar(dwfm.xHeight) / upem; |
| 761 my->fUnderlineThickness = fRec.fTextSize * SkIntToScalar(dwfm.underlineP
osition) / upem; | 975 my->fUnderlineThickness = fTextSizeRender * SkIntToScalar(dwfm.underline
Position) / upem; |
| 762 my->fUnderlinePosition = -(fRec.fTextSize * SkIntToScalar(dwfm.underline
Thickness) / upem); | 976 my->fUnderlinePosition = -(fTextSizeRender * SkIntToScalar(dwfm.underlin
eThickness) / upem); |
| 763 | 977 |
| 764 my->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag; | 978 my->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag; |
| 765 my->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag; | 979 my->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag; |
| 766 } | 980 } |
| 767 } | 981 } |
| 768 | 982 |
| 769 /////////////////////////////////////////////////////////////////////////////// | 983 /////////////////////////////////////////////////////////////////////////////// |
| 770 | 984 |
| 771 #include "SkColorPriv.h" | 985 #include "SkColorPriv.h" |
| 772 | 986 |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 881 UINT16 index = glyph.getGlyphID(); | 1095 UINT16 index = glyph.getGlyphID(); |
| 882 | 1096 |
| 883 DWRITE_GLYPH_OFFSET offset; | 1097 DWRITE_GLYPH_OFFSET offset; |
| 884 offset.advanceOffset = 0.0f; | 1098 offset.advanceOffset = 0.0f; |
| 885 offset.ascenderOffset = 0.0f; | 1099 offset.ascenderOffset = 0.0f; |
| 886 | 1100 |
| 887 DWRITE_GLYPH_RUN run; | 1101 DWRITE_GLYPH_RUN run; |
| 888 run.glyphCount = 1; | 1102 run.glyphCount = 1; |
| 889 run.glyphAdvances = &advance; | 1103 run.glyphAdvances = &advance; |
| 890 run.fontFace = fTypeface->fDWriteFontFace.get(); | 1104 run.fontFace = fTypeface->fDWriteFontFace.get(); |
| 891 run.fontEmSize = SkScalarToFloat(fRec.fTextSize); | 1105 run.fontEmSize = SkScalarToFloat(fTextSizeRender); |
| 892 run.bidiLevel = 0; | 1106 run.bidiLevel = 0; |
| 893 run.glyphIndices = &index; | 1107 run.glyphIndices = &index; |
| 894 run.isSideways = FALSE; | 1108 run.isSideways = FALSE; |
| 895 run.glyphOffsets = &offset; | 1109 run.glyphOffsets = &offset; |
| 896 | 1110 |
| 897 SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis; | 1111 SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis; |
| 898 HRNM(fTypeface->fFactory->CreateGlyphRunAnalysis(&run, | 1112 HRNM(fTypeface->fFactory->CreateGlyphRunAnalysis(&run, |
| 899 1.0f, // pixelsPerDip, | 1113 1.0f, // pixelsPerDip, |
| 900 &fXform, | 1114 &fXform, |
| 901 fRenderingMode, | 1115 fRenderingMode, |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 959 SkASSERT(&glyph && path); | 1173 SkASSERT(&glyph && path); |
| 960 | 1174 |
| 961 path->reset(); | 1175 path->reset(); |
| 962 | 1176 |
| 963 SkTScopedComPtr<IDWriteGeometrySink> geometryToPath; | 1177 SkTScopedComPtr<IDWriteGeometrySink> geometryToPath; |
| 964 HRVM(SkDWriteGeometrySink::Create(path, &geometryToPath), | 1178 HRVM(SkDWriteGeometrySink::Create(path, &geometryToPath), |
| 965 "Could not create geometry to path converter."); | 1179 "Could not create geometry to path converter."); |
| 966 uint16_t glyphId = glyph.getGlyphID(); | 1180 uint16_t glyphId = glyph.getGlyphID(); |
| 967 //TODO: convert to<->from DIUs? This would make a difference if hinting. | 1181 //TODO: convert to<->from DIUs? This would make a difference if hinting. |
| 968 //It may not be needed, it appears that DirectWrite only hints at em size. | 1182 //It may not be needed, it appears that DirectWrite only hints at em size. |
| 969 HRVM(fTypeface->fDWriteFontFace->GetGlyphRunOutline(SkScalarToFloat(fRec.fTe
xtSize), | 1183 HRVM(fTypeface->fDWriteFontFace->GetGlyphRunOutline(SkScalarToFloat(fTextSiz
eRender), |
| 970 &glyphId, | 1184 &glyphId, |
| 971 NULL, //advances | 1185 NULL, //advances |
| 972 NULL, //offsets | 1186 NULL, //offsets |
| 973 1, //num glyphs | 1187 1, //num glyphs |
| 974 FALSE, //sideways | 1188 FALSE, //sideways |
| 975 FALSE, //rtl | 1189 FALSE, //rtl |
| 976 geometryToPath.get()), | 1190 geometryToPath.get()), |
| 977 "Could not create glyph outline."); | 1191 "Could not create glyph outline."); |
| 978 | 1192 |
| 979 SkMatrix mat; | 1193 path->transform(fSkXform); |
| 980 fRec.getMatrixFrom2x2(&mat); | |
| 981 path->transform(mat); | |
| 982 } | 1194 } |
| 983 | 1195 |
| 984 void DWriteFontTypeface::onGetFontDescriptor(SkFontDescriptor* desc, | 1196 void DWriteFontTypeface::onGetFontDescriptor(SkFontDescriptor* desc, |
| 985 bool* isLocalStream) const { | 1197 bool* isLocalStream) const { |
| 986 // Get the family name. | 1198 // Get the family name. |
| 987 SkTScopedComPtr<IDWriteLocalizedStrings> dwFamilyNames; | 1199 SkTScopedComPtr<IDWriteLocalizedStrings> dwFamilyNames; |
| 988 HRV(fDWriteFontFamily->GetFamilyNames(&dwFamilyNames)); | 1200 HRV(fDWriteFontFamily->GetFamilyNames(&dwFamilyNames)); |
| 989 | 1201 |
| 990 UINT32 dwFamilyNamesLength; | 1202 UINT32 dwFamilyNamesLength; |
| 991 HRV(dwFamilyNames->GetStringLength(0, &dwFamilyNamesLength)); | 1203 HRV(dwFamilyNames->GetStringLength(0, &dwFamilyNamesLength)); |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1139 type != DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION) | 1351 type != DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION) |
| 1140 { | 1352 { |
| 1141 return 0; | 1353 return 0; |
| 1142 } | 1354 } |
| 1143 | 1355 |
| 1144 int ttcIndex; | 1356 int ttcIndex; |
| 1145 SkAutoTUnref<SkStream> stream(this->openStream(&ttcIndex)); | 1357 SkAutoTUnref<SkStream> stream(this->openStream(&ttcIndex)); |
| 1146 return stream.get() ? SkFontStream::GetTableTags(stream, ttcIndex, tags) : 0
; | 1358 return stream.get() ? SkFontStream::GetTableTags(stream, ttcIndex, tags) : 0
; |
| 1147 } | 1359 } |
| 1148 | 1360 |
| 1149 class AutoDWriteTable { | |
| 1150 public: | |
| 1151 AutoDWriteTable(IDWriteFontFace* fontFace, UINT32 beTag) : fFontFace(fontFac
e), fExists(FALSE) { | |
| 1152 // Any errors are ignored, user must check fExists anyway. | |
| 1153 fontFace->TryGetFontTable(beTag, | |
| 1154 reinterpret_cast<const void **>(&fData), &fSize, &fLock, &fExists); | |
| 1155 } | |
| 1156 ~AutoDWriteTable() { | |
| 1157 if (fExists) { | |
| 1158 fFontFace->ReleaseFontTable(fLock); | |
| 1159 } | |
| 1160 } | |
| 1161 | |
| 1162 const uint8_t* fData; | |
| 1163 UINT32 fSize; | |
| 1164 BOOL fExists; | |
| 1165 private: | |
| 1166 // Borrowed reference, the user must ensure the fontFace stays alive. | |
| 1167 IDWriteFontFace* fFontFace; | |
| 1168 void* fLock; | |
| 1169 }; | |
| 1170 | |
| 1171 size_t DWriteFontTypeface::onGetTableData(SkFontTableTag tag, size_t offset, | 1361 size_t DWriteFontTypeface::onGetTableData(SkFontTableTag tag, size_t offset, |
| 1172 size_t length, void* data) const | 1362 size_t length, void* data) const |
| 1173 { | 1363 { |
| 1174 AutoDWriteTable table(fDWriteFontFace.get(), SkEndian_SwapBE32(tag)); | 1364 AutoDWriteTable table(fDWriteFontFace.get(), SkEndian_SwapBE32(tag)); |
| 1175 if (!table.fExists) { | 1365 if (!table.fExists) { |
| 1176 return 0; | 1366 return 0; |
| 1177 } | 1367 } |
| 1178 | 1368 |
| 1179 if (offset > table.fSize) { | 1369 if (offset > table.fSize) { |
| 1180 return 0; | 1370 return 0; |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1253 | 1443 |
| 1254 void DWriteFontTypeface::onFilterRec(SkScalerContext::Rec* rec) const { | 1444 void DWriteFontTypeface::onFilterRec(SkScalerContext::Rec* rec) const { |
| 1255 if (rec->fFlags & SkScalerContext::kLCD_BGROrder_Flag || | 1445 if (rec->fFlags & SkScalerContext::kLCD_BGROrder_Flag || |
| 1256 rec->fFlags & SkScalerContext::kLCD_Vertical_Flag) | 1446 rec->fFlags & SkScalerContext::kLCD_Vertical_Flag) |
| 1257 { | 1447 { |
| 1258 rec->fMaskFormat = SkMask::kA8_Format; | 1448 rec->fMaskFormat = SkMask::kA8_Format; |
| 1259 } | 1449 } |
| 1260 | 1450 |
| 1261 unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag | | 1451 unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag | |
| 1262 SkScalerContext::kForceAutohinting_Flag | | 1452 SkScalerContext::kForceAutohinting_Flag | |
| 1263 SkScalerContext::kEmbeddedBitmapText_Flag | | |
| 1264 SkScalerContext::kEmbolden_Flag | | 1453 SkScalerContext::kEmbolden_Flag | |
| 1265 SkScalerContext::kLCD_BGROrder_Flag | | 1454 SkScalerContext::kLCD_BGROrder_Flag | |
| 1266 SkScalerContext::kLCD_Vertical_Flag; | 1455 SkScalerContext::kLCD_Vertical_Flag; |
| 1267 rec->fFlags &= ~flagsWeDontSupport; | 1456 rec->fFlags &= ~flagsWeDontSupport; |
| 1268 | 1457 |
| 1269 SkPaint::Hinting h = rec->getHinting(); | 1458 SkPaint::Hinting h = rec->getHinting(); |
| 1270 // DirectWrite does not provide for hinting hints. | 1459 // DirectWrite does not provide for hinting hints. |
| 1271 h = SkPaint::kSlight_Hinting; | 1460 h = SkPaint::kSlight_Hinting; |
| 1272 rec->setHinting(h); | 1461 rec->setHinting(h); |
| 1273 | 1462 |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1355 | 1544 |
| 1356 if (FAILED(hr)) { | 1545 if (FAILED(hr)) { |
| 1357 *advance = 0; | 1546 *advance = 0; |
| 1358 return false; | 1547 return false; |
| 1359 } | 1548 } |
| 1360 | 1549 |
| 1361 *advance = gm.advanceWidth; | 1550 *advance = gm.advanceWidth; |
| 1362 return true; | 1551 return true; |
| 1363 } | 1552 } |
| 1364 | 1553 |
| 1365 template<typename T> class AutoTDWriteTable : public AutoDWriteTable { | |
| 1366 public: | |
| 1367 static const UINT32 tag = DWRITE_MAKE_OPENTYPE_TAG(T::TAG0, T::TAG1, T::TAG2
, T::TAG3); | |
| 1368 AutoTDWriteTable(IDWriteFontFace* fontFace) : AutoDWriteTable(fontFace, tag)
{ } | |
| 1369 | |
| 1370 const T* operator->() const { return reinterpret_cast<const T*>(fData); } | |
| 1371 }; | |
| 1372 | |
| 1373 SkAdvancedTypefaceMetrics* DWriteFontTypeface::onGetAdvancedTypefaceMetrics( | 1554 SkAdvancedTypefaceMetrics* DWriteFontTypeface::onGetAdvancedTypefaceMetrics( |
| 1374 SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo, | 1555 SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo, |
| 1375 const uint32_t* glyphIDs, | 1556 const uint32_t* glyphIDs, |
| 1376 uint32_t glyphIDsCount) const { | 1557 uint32_t glyphIDsCount) const { |
| 1377 | 1558 |
| 1378 SkAdvancedTypefaceMetrics* info = NULL; | 1559 SkAdvancedTypefaceMetrics* info = NULL; |
| 1379 | 1560 |
| 1380 HRESULT hr = S_OK; | 1561 HRESULT hr = S_OK; |
| 1381 | 1562 |
| 1382 const unsigned glyphCount = fDWriteFontFace->GetGlyphCount(); | 1563 const unsigned glyphCount = fDWriteFontFace->GetGlyphCount(); |
| (...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1821 } | 2002 } |
| 1822 | 2003 |
| 1823 #include "SkFontMgr_indirect.h" | 2004 #include "SkFontMgr_indirect.h" |
| 1824 SkFontMgr* SkFontMgr_New_DirectWriteRenderer(SkRemotableFontMgr* proxy) { | 2005 SkFontMgr* SkFontMgr_New_DirectWriteRenderer(SkRemotableFontMgr* proxy) { |
| 1825 SkAutoTUnref<SkFontMgr> impl(SkFontMgr_New_DirectWrite()); | 2006 SkAutoTUnref<SkFontMgr> impl(SkFontMgr_New_DirectWrite()); |
| 1826 if (impl.get() == NULL) { | 2007 if (impl.get() == NULL) { |
| 1827 return NULL; | 2008 return NULL; |
| 1828 } | 2009 } |
| 1829 return SkNEW_ARGS(SkFontMgr_Indirect, (impl.get(), proxy)); | 2010 return SkNEW_ARGS(SkFontMgr_Indirect, (impl.get(), proxy)); |
| 1830 } | 2011 } |
| OLD | NEW |