| OLD | NEW |
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2006 The Android Open Source Project | 3 * Copyright 2006 The Android Open Source Project |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 #include <vector> | 9 #include <vector> |
| 10 #ifdef SK_BUILD_FOR_MAC | 10 #ifdef SK_BUILD_FOR_MAC |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 #include "SkPath.h" | 37 #include "SkPath.h" |
| 38 #include "SkString.h" | 38 #include "SkString.h" |
| 39 #include "SkStream.h" | 39 #include "SkStream.h" |
| 40 #include "SkThread.h" | 40 #include "SkThread.h" |
| 41 #include "SkTypeface_mac.h" | 41 #include "SkTypeface_mac.h" |
| 42 #include "SkUtils.h" | 42 #include "SkUtils.h" |
| 43 #include "SkTypefaceCache.h" | 43 #include "SkTypefaceCache.h" |
| 44 #include "SkFontMgr.h" | 44 #include "SkFontMgr.h" |
| 45 | 45 |
| 46 //#define HACK_COLORGLYPHS | 46 //#define HACK_COLORGLYPHS |
| 47 //#define SK_IGNORE_MAC_TEXT_BOUNDS_FIX | |
| 48 | 47 |
| 49 class SkScalerContext_Mac; | 48 class SkScalerContext_Mac; |
| 50 | 49 |
| 51 // CTFontManagerCopyAvailableFontFamilyNames() is not always available, so we | 50 // CTFontManagerCopyAvailableFontFamilyNames() is not always available, so we |
| 52 // provide a wrapper here that will return an empty array if need be. | 51 // provide a wrapper here that will return an empty array if need be. |
| 53 static CFArrayRef SkCTFontManagerCopyAvailableFontFamilyNames() { | 52 static CFArrayRef SkCTFontManagerCopyAvailableFontFamilyNames() { |
| 54 #ifdef SK_BUILD_FOR_IOS | 53 #ifdef SK_BUILD_FOR_IOS |
| 55 return CFArrayCreate(NULL, NULL, 0, NULL); | 54 return CFArrayCreate(NULL, NULL, 0, NULL); |
| 56 #else | 55 #else |
| 57 return CTFontManagerCopyAvailableFontFamilyNames(); | 56 return CTFontManagerCopyAvailableFontFamilyNames(); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 118 public: | 117 public: |
| 119 const T* fData; | 118 const T* fData; |
| 120 }; | 119 }; |
| 121 | 120 |
| 122 // inline versions of these rect helpers | 121 // inline versions of these rect helpers |
| 123 | 122 |
| 124 static bool CGRectIsEmpty_inline(const CGRect& rect) { | 123 static bool CGRectIsEmpty_inline(const CGRect& rect) { |
| 125 return rect.size.width <= 0 || rect.size.height <= 0; | 124 return rect.size.width <= 0 || rect.size.height <= 0; |
| 126 } | 125 } |
| 127 | 126 |
| 128 #if defined(SK_IGNORE_MAC_TEXT_BOUNDS_FIX) | |
| 129 static void CGRectInset_inline(CGRect* rect, CGFloat dx, CGFloat dy) { | |
| 130 rect->origin.x += dx; | |
| 131 rect->origin.y += dy; | |
| 132 rect->size.width -= dx * 2; | |
| 133 rect->size.height -= dy * 2; | |
| 134 } | |
| 135 #endif | |
| 136 | |
| 137 static CGFloat CGRectGetMinX_inline(const CGRect& rect) { | 127 static CGFloat CGRectGetMinX_inline(const CGRect& rect) { |
| 138 return rect.origin.x; | 128 return rect.origin.x; |
| 139 } | 129 } |
| 140 | 130 |
| 141 static CGFloat CGRectGetMaxX_inline(const CGRect& rect) { | 131 static CGFloat CGRectGetMaxX_inline(const CGRect& rect) { |
| 142 return rect.origin.x + rect.size.width; | 132 return rect.origin.x + rect.size.width; |
| 143 } | 133 } |
| 144 | 134 |
| 145 static CGFloat CGRectGetMinY_inline(const CGRect& rect) { | 135 static CGFloat CGRectGetMinY_inline(const CGRect& rect) { |
| 146 return rect.origin.y; | 136 return rect.origin.y; |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 SkScalar sx = SK_Scalar1, | 282 SkScalar sx = SK_Scalar1, |
| 293 SkScalar sy = SK_Scalar1) { | 283 SkScalar sy = SK_Scalar1) { |
| 294 return CGAffineTransformMake( ScalarToCG(matrix[SkMatrix::kMScaleX] * sx), | 284 return CGAffineTransformMake( ScalarToCG(matrix[SkMatrix::kMScaleX] * sx), |
| 295 -ScalarToCG(matrix[SkMatrix::kMSkewY] * sy), | 285 -ScalarToCG(matrix[SkMatrix::kMSkewY] * sy), |
| 296 -ScalarToCG(matrix[SkMatrix::kMSkewX] * sx), | 286 -ScalarToCG(matrix[SkMatrix::kMSkewX] * sx), |
| 297 ScalarToCG(matrix[SkMatrix::kMScaleY] * sy), | 287 ScalarToCG(matrix[SkMatrix::kMScaleY] * sy), |
| 298 ScalarToCG(matrix[SkMatrix::kMTransX] * sx), | 288 ScalarToCG(matrix[SkMatrix::kMTransX] * sx), |
| 299 ScalarToCG(matrix[SkMatrix::kMTransY] * sy)); | 289 ScalarToCG(matrix[SkMatrix::kMTransY] * sy)); |
| 300 } | 290 } |
| 301 | 291 |
| 302 #if defined(SK_IGNORE_MAC_TEXT_BOUNDS_FIX) | |
| 303 static SkScalar getFontScale(CGFontRef cgFont) { | |
| 304 int unitsPerEm = CGFontGetUnitsPerEm(cgFont); | |
| 305 return SkScalarInvert(SkIntToScalar(unitsPerEm)); | |
| 306 } | |
| 307 #endif | |
| 308 | |
| 309 /////////////////////////////////////////////////////////////////////////////// | 292 /////////////////////////////////////////////////////////////////////////////// |
| 310 | 293 |
| 311 #define BITMAP_INFO_RGB (kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host) | 294 #define BITMAP_INFO_RGB (kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host) |
| 312 #define BITMAP_INFO_GRAY (kCGImageAlphaNone) | 295 #define BITMAP_INFO_GRAY (kCGImageAlphaNone) |
| 313 | 296 |
| 314 /** | 297 /** |
| 315 * There does not appear to be a publicly accessable API for determining if lcd | 298 * There does not appear to be a publicly accessable API for determining if lcd |
| 316 * font smoothing will be applied if we request it. The main issue is that if | 299 * font smoothing will be applied if we request it. The main issue is that if |
| 317 * smoothing is applied a gamma of 2.0 will be used, if not a gamma of 1.0. | 300 * smoothing is applied a gamma of 2.0 will be used, if not a gamma of 1.0. |
| 318 */ | 301 */ |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 636 if (face) { | 619 if (face) { |
| 637 SkTypefaceCache::Add(face, style); | 620 SkTypefaceCache::Add(face, style); |
| 638 } else { | 621 } else { |
| 639 face = GetDefaultFace(); | 622 face = GetDefaultFace(); |
| 640 face->ref(); | 623 face->ref(); |
| 641 } | 624 } |
| 642 } | 625 } |
| 643 return face; | 626 return face; |
| 644 } | 627 } |
| 645 | 628 |
| 646 #if defined(SK_IGNORE_MAC_TEXT_BOUNDS_FIX) | |
| 647 static void flip(SkMatrix* matrix) { | |
| 648 matrix->setSkewX(-matrix->getSkewX()); | |
| 649 matrix->setSkewY(-matrix->getSkewY()); | |
| 650 } | |
| 651 #endif | |
| 652 | |
| 653 /////////////////////////////////////////////////////////////////////////////// | 629 /////////////////////////////////////////////////////////////////////////////// |
| 654 | 630 |
| 655 /** GlyphRect is in FUnits (em space, y up). */ | 631 /** GlyphRect is in FUnits (em space, y up). */ |
| 656 struct GlyphRect { | 632 struct GlyphRect { |
| 657 int16_t fMinX; | 633 int16_t fMinX; |
| 658 int16_t fMinY; | 634 int16_t fMinY; |
| 659 int16_t fMaxX; | 635 int16_t fMaxX; |
| 660 int16_t fMaxY; | 636 int16_t fMaxY; |
| 661 }; | 637 }; |
| 662 | 638 |
| 663 class SkScalerContext_Mac : public SkScalerContext { | 639 class SkScalerContext_Mac : public SkScalerContext { |
| 664 public: | 640 public: |
| 665 SkScalerContext_Mac(SkTypeface_Mac*, const SkDescriptor*); | 641 SkScalerContext_Mac(SkTypeface_Mac*, const SkDescriptor*); |
| 666 | 642 |
| 667 protected: | 643 protected: |
| 668 unsigned generateGlyphCount(void) SK_OVERRIDE; | 644 unsigned generateGlyphCount(void) SK_OVERRIDE; |
| 669 uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE; | 645 uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE; |
| 670 void generateAdvance(SkGlyph* glyph) SK_OVERRIDE; | 646 void generateAdvance(SkGlyph* glyph) SK_OVERRIDE; |
| 671 void generateMetrics(SkGlyph* glyph) SK_OVERRIDE; | 647 void generateMetrics(SkGlyph* glyph) SK_OVERRIDE; |
| 672 void generateImage(const SkGlyph& glyph) SK_OVERRIDE; | 648 void generateImage(const SkGlyph& glyph) SK_OVERRIDE; |
| 673 void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE; | 649 void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE; |
| 674 void generateFontMetrics(SkPaint::FontMetrics* mX, SkPaint::FontMetrics* mY)
SK_OVERRIDE; | 650 void generateFontMetrics(SkPaint::FontMetrics* mX, SkPaint::FontMetrics* mY)
SK_OVERRIDE; |
| 675 | 651 |
| 676 private: | 652 private: |
| 677 static void CTPathElement(void *info, const CGPathElement *element); | 653 static void CTPathElement(void *info, const CGPathElement *element); |
| 678 | 654 |
| 679 #if defined(SK_IGNORE_MAC_TEXT_BOUNDS_FIX) | |
| 680 void getVerticalOffset(CGGlyph glyphID, SkIPoint* offset) const; | |
| 681 #else | |
| 682 /** Returns the offset from the horizontal origin to the vertical origin in
SkGlyph units. */ | 655 /** Returns the offset from the horizontal origin to the vertical origin in
SkGlyph units. */ |
| 683 void getVerticalOffset(CGGlyph glyphID, SkPoint* offset) const; | 656 void getVerticalOffset(CGGlyph glyphID, SkPoint* offset) const; |
| 684 #endif | |
| 685 | 657 |
| 686 /** Initializes and returns the value of fFBoundingBoxesGlyphOffset. | 658 /** Initializes and returns the value of fFBoundingBoxesGlyphOffset. |
| 687 * | 659 * |
| 688 * For use with (and must be called before) generateBBoxes. | 660 * For use with (and must be called before) generateBBoxes. |
| 689 */ | 661 */ |
| 690 uint16_t getFBoundingBoxesGlyphOffset(); | 662 uint16_t getFBoundingBoxesGlyphOffset(); |
| 691 | 663 |
| 692 /** Initializes fFBoundingBoxes and returns true on success. | 664 /** Initializes fFBoundingBoxes and returns true on success. |
| 693 * | 665 * |
| 694 * On Lion and Mountain Lion, CTFontGetBoundingRectsForGlyphs has a bug whi
ch causes it to | 666 * On Lion and Mountain Lion, CTFontGetBoundingRectsForGlyphs has a bug whi
ch causes it to |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 727 AutoCFRelease<CTFontRef> fCTVerticalFont; | 699 AutoCFRelease<CTFontRef> fCTVerticalFont; |
| 728 | 700 |
| 729 AutoCFRelease<CGFontRef> fCGFont; | 701 AutoCFRelease<CGFontRef> fCGFont; |
| 730 SkAutoTMalloc<GlyphRect> fFBoundingBoxes; | 702 SkAutoTMalloc<GlyphRect> fFBoundingBoxes; |
| 731 uint16_t fFBoundingBoxesGlyphOffset; | 703 uint16_t fFBoundingBoxesGlyphOffset; |
| 732 uint16_t fGlyphCount; | 704 uint16_t fGlyphCount; |
| 733 bool fGeneratedFBoundingBoxes; | 705 bool fGeneratedFBoundingBoxes; |
| 734 const bool fDoSubPosition; | 706 const bool fDoSubPosition; |
| 735 const bool fVertical; | 707 const bool fVertical; |
| 736 | 708 |
| 737 #if defined(SK_IGNORE_MAC_TEXT_BOUNDS_FIX) | |
| 738 SkMatrix fVerticalMatrix; // unit rotated | |
| 739 SkMatrix fMatrix; // with font size | |
| 740 SkMatrix fFBoundingBoxesMatrix; // lion-specific fix | |
| 741 SkMatrix fUnitMatrix; // without font size | |
| 742 #endif | |
| 743 | |
| 744 friend class Offscreen; | 709 friend class Offscreen; |
| 745 | 710 |
| 746 typedef SkScalerContext INHERITED; | 711 typedef SkScalerContext INHERITED; |
| 747 }; | 712 }; |
| 748 | 713 |
| 749 SkScalerContext_Mac::SkScalerContext_Mac(SkTypeface_Mac* typeface, | 714 SkScalerContext_Mac::SkScalerContext_Mac(SkTypeface_Mac* typeface, |
| 750 const SkDescriptor* desc) | 715 const SkDescriptor* desc) |
| 751 : INHERITED(typeface, desc) | 716 : INHERITED(typeface, desc) |
| 752 , fFBoundingBoxes() | 717 , fFBoundingBoxes() |
| 753 , fFBoundingBoxesGlyphOffset(0) | 718 , fFBoundingBoxesGlyphOffset(0) |
| 754 , fGeneratedFBoundingBoxes(false) | 719 , fGeneratedFBoundingBoxes(false) |
| 755 , fDoSubPosition(SkToBool(fRec.fFlags & kSubpixelPositioning_Flag)) | 720 , fDoSubPosition(SkToBool(fRec.fFlags & kSubpixelPositioning_Flag)) |
| 756 , fVertical(SkToBool(fRec.fFlags & kVertical_Flag)) | 721 , fVertical(SkToBool(fRec.fFlags & kVertical_Flag)) |
| 757 | 722 |
| 758 { | 723 { |
| 759 CTFontRef ctFont = typeface->fFontRef.get(); | 724 CTFontRef ctFont = typeface->fFontRef.get(); |
| 760 CFIndex numGlyphs = CTFontGetGlyphCount(ctFont); | 725 CFIndex numGlyphs = CTFontGetGlyphCount(ctFont); |
| 761 SkASSERT(numGlyphs >= 1 && numGlyphs <= 0xFFFF); | 726 SkASSERT(numGlyphs >= 1 && numGlyphs <= 0xFFFF); |
| 762 fGlyphCount = SkToU16(numGlyphs); | 727 fGlyphCount = SkToU16(numGlyphs); |
| 763 | 728 |
| 764 #if defined(SK_IGNORE_MAC_TEXT_BOUNDS_FIX) | |
| 765 // Get the state we need | |
| 766 fRec.getSingleMatrix(&fMatrix); | |
| 767 CGAffineTransform transform = MatrixToCGAffineTransform(fMatrix); | |
| 768 | |
| 769 // extract the font size out of the matrix, but leave the skewing for italic | |
| 770 SkScalar reciprocal = SkScalarInvert(fRec.fTextSize); | |
| 771 fUnitMatrix = fMatrix; | |
| 772 fUnitMatrix.preScale(reciprocal, reciprocal); | |
| 773 flip(&fUnitMatrix); // flip to fix up bounds later | |
| 774 #else | |
| 775 fRec.getSingleMatrix(&fFUnitMatrix); | 729 fRec.getSingleMatrix(&fFUnitMatrix); |
| 776 CGAffineTransform transform = MatrixToCGAffineTransform(fFUnitMatrix); | 730 CGAffineTransform transform = MatrixToCGAffineTransform(fFUnitMatrix); |
| 777 #endif | |
| 778 | 731 |
| 779 AutoCFRelease<CTFontDescriptorRef> ctFontDesc; | 732 AutoCFRelease<CTFontDescriptorRef> ctFontDesc; |
| 780 if (fVertical) { | 733 if (fVertical) { |
| 781 AutoCFRelease<CFMutableDictionaryRef> cfAttributes(CFDictionaryCreateMut
able( | 734 AutoCFRelease<CFMutableDictionaryRef> cfAttributes(CFDictionaryCreateMut
able( |
| 782 kCFAllocatorDefault, 0, | 735 kCFAllocatorDefault, 0, |
| 783 &kCFTypeDictionaryKeyCallBacks, | 736 &kCFTypeDictionaryKeyCallBacks, |
| 784 &kCFTypeDictionaryValueCallBacks)); | 737 &kCFTypeDictionaryValueCallBacks)); |
| 785 if (cfAttributes) { | 738 if (cfAttributes) { |
| 786 CTFontOrientation ctOrientation = kCTFontVerticalOrientation; | 739 CTFontOrientation ctOrientation = kCTFontVerticalOrientation; |
| 787 AutoCFRelease<CFNumberRef> cfVertical(CFNumberCreate( | 740 AutoCFRelease<CFNumberRef> cfVertical(CFNumberCreate( |
| 788 kCFAllocatorDefault, kCFNumberSInt32Type, &ctOrientation)); | 741 kCFAllocatorDefault, kCFNumberSInt32Type, &ctOrientation)); |
| 789 CFDictionaryAddValue(cfAttributes, kCTFontOrientationAttribute, cfVe
rtical); | 742 CFDictionaryAddValue(cfAttributes, kCTFontOrientationAttribute, cfVe
rtical); |
| 790 ctFontDesc = CTFontDescriptorCreateWithAttributes(cfAttributes); | 743 ctFontDesc = CTFontDescriptorCreateWithAttributes(cfAttributes); |
| 791 } | 744 } |
| 792 } | 745 } |
| 793 // Since our matrix includes everything, we pass 1 for size. | 746 // Since our matrix includes everything, we pass 1 for size. |
| 794 fCTFont = CTFontCreateCopyWithAttributes(ctFont, 1, &transform, ctFontDesc); | 747 fCTFont = CTFontCreateCopyWithAttributes(ctFont, 1, &transform, ctFontDesc); |
| 795 fCGFont = CTFontCopyGraphicsFont(fCTFont, NULL); | 748 fCGFont = CTFontCopyGraphicsFont(fCTFont, NULL); |
| 796 if (fVertical) { | 749 if (fVertical) { |
| 797 CGAffineTransform rotateLeft = CGAffineTransformMake(0, -1, 1, 0, 0, 0); | 750 CGAffineTransform rotateLeft = CGAffineTransformMake(0, -1, 1, 0, 0, 0); |
| 798 transform = CGAffineTransformConcat(rotateLeft, transform); | 751 transform = CGAffineTransformConcat(rotateLeft, transform); |
| 799 fCTVerticalFont = CTFontCreateCopyWithAttributes(ctFont, 1, &transform,
NULL); | 752 fCTVerticalFont = CTFontCreateCopyWithAttributes(ctFont, 1, &transform,
NULL); |
| 800 #if defined(SK_IGNORE_MAC_TEXT_BOUNDS_FIX) | |
| 801 fVerticalMatrix = fUnitMatrix; | |
| 802 if (isSnowLeopard()) { | |
| 803 SkScalar scale = SkScalarMul(fRec.fTextSize, getFontScale(fCGFont)); | |
| 804 fVerticalMatrix.preScale(scale, scale); | |
| 805 } else { | |
| 806 fVerticalMatrix.preRotate(SkIntToScalar(90)); | |
| 807 } | |
| 808 fVerticalMatrix.postScale(SK_Scalar1, -SK_Scalar1); | |
| 809 #endif | |
| 810 } | 753 } |
| 811 #if defined(SK_IGNORE_MAC_TEXT_BOUNDS_FIX) | 754 |
| 812 #else | |
| 813 SkScalar emPerFUnit = SkScalarInvert(SkIntToScalar(CGFontGetUnitsPerEm(fCGFo
nt))); | 755 SkScalar emPerFUnit = SkScalarInvert(SkIntToScalar(CGFontGetUnitsPerEm(fCGFo
nt))); |
| 814 fFUnitMatrix.preScale(emPerFUnit, -emPerFUnit); | 756 fFUnitMatrix.preScale(emPerFUnit, -emPerFUnit); |
| 815 #endif | |
| 816 } | 757 } |
| 817 | 758 |
| 818 CGRGBPixel* Offscreen::getCG(const SkScalerContext_Mac& context, const SkGlyph&
glyph, | 759 CGRGBPixel* Offscreen::getCG(const SkScalerContext_Mac& context, const SkGlyph&
glyph, |
| 819 CGGlyph glyphID, size_t* rowBytesPtr, | 760 CGGlyph glyphID, size_t* rowBytesPtr, |
| 820 bool generateA8FromLCD) { | 761 bool generateA8FromLCD) { |
| 821 if (!fRGBSpace) { | 762 if (!fRGBSpace) { |
| 822 //It doesn't appear to matter what color space is specified. | 763 //It doesn't appear to matter what color space is specified. |
| 823 //Regular blends and antialiased text are always (s*a + d*(1-a)) | 764 //Regular blends and antialiased text are always (s*a + d*(1-a)) |
| 824 //and smoothed text is always g=2.0. | 765 //and smoothed text is always g=2.0. |
| 825 fRGBSpace = CGColorSpaceCreateDeviceRGB(); | 766 fRGBSpace = CGColorSpaceCreateDeviceRGB(); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 857 // skia handles quantization itself, so we disable this for cg to get | 798 // skia handles quantization itself, so we disable this for cg to get |
| 858 // full fractional data from them. | 799 // full fractional data from them. |
| 859 CGContextSetAllowsFontSubpixelQuantization(fCG, false); | 800 CGContextSetAllowsFontSubpixelQuantization(fCG, false); |
| 860 CGContextSetShouldSubpixelQuantizeFonts(fCG, false); | 801 CGContextSetShouldSubpixelQuantizeFonts(fCG, false); |
| 861 | 802 |
| 862 CGContextSetTextDrawingMode(fCG, kCGTextFill); | 803 CGContextSetTextDrawingMode(fCG, kCGTextFill); |
| 863 CGContextSetFont(fCG, context.fCGFont); | 804 CGContextSetFont(fCG, context.fCGFont); |
| 864 CGContextSetFontSize(fCG, 1 /*CTFontGetSize(context.fCTFont)*/); | 805 CGContextSetFontSize(fCG, 1 /*CTFontGetSize(context.fCTFont)*/); |
| 865 CGContextSetTextMatrix(fCG, CTFontGetMatrix(context.fCTFont)); | 806 CGContextSetTextMatrix(fCG, CTFontGetMatrix(context.fCTFont)); |
| 866 | 807 |
| 867 #if defined(SK_IGNORE_MAC_TEXT_BOUNDS_FIX) | |
| 868 CGContextSetAllowsFontSubpixelPositioning(fCG, context.fDoSubPosition); | |
| 869 CGContextSetShouldSubpixelPositionFonts(fCG, context.fDoSubPosition); | |
| 870 #else | |
| 871 // Because CG always draws from the horizontal baseline, | 808 // Because CG always draws from the horizontal baseline, |
| 872 // if there is a non-integral translation from the horizontal origin to
the vertical origin, | 809 // if there is a non-integral translation from the horizontal origin to
the vertical origin, |
| 873 // then CG cannot draw the glyph in the correct location without subpixe
l positioning. | 810 // then CG cannot draw the glyph in the correct location without subpixe
l positioning. |
| 874 CGContextSetAllowsFontSubpixelPositioning(fCG, context.fDoSubPosition ||
context.fVertical); | 811 CGContextSetAllowsFontSubpixelPositioning(fCG, context.fDoSubPosition ||
context.fVertical); |
| 875 CGContextSetShouldSubpixelPositionFonts(fCG, context.fDoSubPosition || c
ontext.fVertical); | 812 CGContextSetShouldSubpixelPositionFonts(fCG, context.fDoSubPosition || c
ontext.fVertical); |
| 876 #endif | |
| 877 | 813 |
| 878 // Draw white on black to create mask. | 814 // Draw white on black to create mask. |
| 879 // TODO: Draw black on white and invert, CG has a special case codepath. | 815 // TODO: Draw black on white and invert, CG has a special case codepath. |
| 880 CGContextSetGrayFillColor(fCG, 1.0f, 1.0f); | 816 CGContextSetGrayFillColor(fCG, 1.0f, 1.0f); |
| 881 | 817 |
| 882 // force our checks below to happen | 818 // force our checks below to happen |
| 883 fDoAA = !doAA; | 819 fDoAA = !doAA; |
| 884 fDoLCD = !doLCD; | 820 fDoLCD = !doLCD; |
| 885 } | 821 } |
| 886 | 822 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 902 | 838 |
| 903 float subX = 0; | 839 float subX = 0; |
| 904 float subY = 0; | 840 float subY = 0; |
| 905 if (context.fDoSubPosition) { | 841 if (context.fDoSubPosition) { |
| 906 subX = SkFixedToFloat(glyph.getSubXFixed()); | 842 subX = SkFixedToFloat(glyph.getSubXFixed()); |
| 907 subY = SkFixedToFloat(glyph.getSubYFixed()); | 843 subY = SkFixedToFloat(glyph.getSubYFixed()); |
| 908 } | 844 } |
| 909 | 845 |
| 910 // CGContextShowGlyphsAtPoint always draws using the horizontal baseline ori
gin. | 846 // CGContextShowGlyphsAtPoint always draws using the horizontal baseline ori
gin. |
| 911 if (context.fVertical) { | 847 if (context.fVertical) { |
| 912 #if defined(SK_IGNORE_MAC_TEXT_BOUNDS_FIX) | |
| 913 SkIPoint offset; | |
| 914 #else | |
| 915 SkPoint offset; | 848 SkPoint offset; |
| 916 #endif | |
| 917 context.getVerticalOffset(glyphID, &offset); | 849 context.getVerticalOffset(glyphID, &offset); |
| 918 subX += offset.fX; | 850 subX += offset.fX; |
| 919 subY += offset.fY; | 851 subY += offset.fY; |
| 920 } | 852 } |
| 921 | 853 |
| 922 CGContextShowGlyphsAtPoint(fCG, -glyph.fLeft + subX, | 854 CGContextShowGlyphsAtPoint(fCG, -glyph.fLeft + subX, |
| 923 glyph.fTop + glyph.fHeight - subY, | 855 glyph.fTop + glyph.fHeight - subY, |
| 924 &glyphID, 1); | 856 &glyphID, 1); |
| 925 | 857 |
| 926 SkASSERT(rowBytesPtr); | 858 SkASSERT(rowBytesPtr); |
| 927 *rowBytesPtr = rowBytes; | 859 *rowBytesPtr = rowBytes; |
| 928 return image; | 860 return image; |
| 929 } | 861 } |
| 930 | 862 |
| 931 #if defined(SK_IGNORE_MAC_TEXT_BOUNDS_FIX) | |
| 932 void SkScalerContext_Mac::getVerticalOffset(CGGlyph glyphID, SkIPoint* offset) c
onst { | |
| 933 CGSize vertOffset; | |
| 934 CTFontGetVerticalTranslationsForGlyphs(fCTVerticalFont, &glyphID, &vertOffse
t, 1); | |
| 935 const SkPoint trans = {CGToScalar(vertOffset.width), | |
| 936 CGToScalar(vertOffset.height)}; | |
| 937 SkPoint floatOffset; | |
| 938 fVerticalMatrix.mapPoints(&floatOffset, &trans, 1); | |
| 939 if (!isSnowLeopard()) { | |
| 940 // SnowLeopard fails to apply the font's matrix to the vertical metrics, | |
| 941 // but Lion and Leopard do. The unit matrix describes the font's matrix at | |
| 942 // point size 1. There may be some way to avoid mapping here by setting up | |
| 943 // fVerticalMatrix differently, but this works for now. | |
| 944 fUnitMatrix.mapPoints(&floatOffset, 1); | |
| 945 } | |
| 946 offset->fX = SkScalarRound(floatOffset.fX); | |
| 947 offset->fY = SkScalarRound(floatOffset.fY); | |
| 948 } | |
| 949 #else | |
| 950 void SkScalerContext_Mac::getVerticalOffset(CGGlyph glyphID, SkPoint* offset) co
nst { | 863 void SkScalerContext_Mac::getVerticalOffset(CGGlyph glyphID, SkPoint* offset) co
nst { |
| 951 // Snow Leopard returns cgVertOffset in completely un-transformed FUnits (em
space, y up). | 864 // Snow Leopard returns cgVertOffset in completely un-transformed FUnits (em
space, y up). |
| 952 // Lion and Leopard return cgVertOffset in CG units (pixels, y up). | 865 // Lion and Leopard return cgVertOffset in CG units (pixels, y up). |
| 953 CGSize cgVertOffset; | 866 CGSize cgVertOffset; |
| 954 CTFontGetVerticalTranslationsForGlyphs(fCTFont, &glyphID, &cgVertOffset, 1); | 867 CTFontGetVerticalTranslationsForGlyphs(fCTFont, &glyphID, &cgVertOffset, 1); |
| 955 | 868 |
| 956 SkPoint skVertOffset = { CGToScalar(cgVertOffset.width), CGToScalar(cgVertOf
fset.height) }; | 869 SkPoint skVertOffset = { CGToScalar(cgVertOffset.width), CGToScalar(cgVertOf
fset.height) }; |
| 957 if (isSnowLeopard()) { | 870 if (isSnowLeopard()) { |
| 958 // From FUnits (em space, y up) to SkGlyph units (pixels, y down). | 871 // From FUnits (em space, y up) to SkGlyph units (pixels, y down). |
| 959 fFUnitMatrix.mapPoints(&skVertOffset, 1); | 872 fFUnitMatrix.mapPoints(&skVertOffset, 1); |
| 960 } else { | 873 } else { |
| 961 // From CG units (pixels, y up) to SkGlyph units (pixels, y down). | 874 // From CG units (pixels, y up) to SkGlyph units (pixels, y down). |
| 962 skVertOffset.fY = -skVertOffset.fY; | 875 skVertOffset.fY = -skVertOffset.fY; |
| 963 } | 876 } |
| 964 | 877 |
| 965 *offset = skVertOffset; | 878 *offset = skVertOffset; |
| 966 } | 879 } |
| 967 #endif | |
| 968 | 880 |
| 969 uint16_t SkScalerContext_Mac::getFBoundingBoxesGlyphOffset() { | 881 uint16_t SkScalerContext_Mac::getFBoundingBoxesGlyphOffset() { |
| 970 if (fFBoundingBoxesGlyphOffset) { | 882 if (fFBoundingBoxesGlyphOffset) { |
| 971 return fFBoundingBoxesGlyphOffset; | 883 return fFBoundingBoxesGlyphOffset; |
| 972 } | 884 } |
| 973 fFBoundingBoxesGlyphOffset = fGlyphCount; // fallback for all fonts | 885 fFBoundingBoxesGlyphOffset = fGlyphCount; // fallback for all fonts |
| 974 AutoCGTable<SkOTTableHorizontalHeader> hheaTable(fCGFont); | 886 AutoCGTable<SkOTTableHorizontalHeader> hheaTable(fCGFont); |
| 975 if (hheaTable.fData) { | 887 if (hheaTable.fData) { |
| 976 fFBoundingBoxesGlyphOffset = SkEndian_SwapBE16(hheaTable->numberOfHMetri
cs); | 888 fFBoundingBoxesGlyphOffset = SkEndian_SwapBE16(hheaTable->numberOfHMetri
cs); |
| 977 } | 889 } |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1006 SkOTTableGlyph::Iterator glyphDataIter(*glyfTable.fData, *locaTable.fData, l
ocaFormat); | 918 SkOTTableGlyph::Iterator glyphDataIter(*glyfTable.fData, *locaTable.fData, l
ocaFormat); |
| 1007 glyphDataIter.advance(fFBoundingBoxesGlyphOffset); | 919 glyphDataIter.advance(fFBoundingBoxesGlyphOffset); |
| 1008 for (uint16_t boundingBoxesIndex = 0; boundingBoxesIndex < entries; ++boundi
ngBoxesIndex) { | 920 for (uint16_t boundingBoxesIndex = 0; boundingBoxesIndex < entries; ++boundi
ngBoxesIndex) { |
| 1009 const SkOTTableGlyphData* glyphData = glyphDataIter.next(); | 921 const SkOTTableGlyphData* glyphData = glyphDataIter.next(); |
| 1010 GlyphRect& rect = fFBoundingBoxes[boundingBoxesIndex]; | 922 GlyphRect& rect = fFBoundingBoxes[boundingBoxesIndex]; |
| 1011 rect.fMinX = SkEndian_SwapBE16(glyphData->xMin); | 923 rect.fMinX = SkEndian_SwapBE16(glyphData->xMin); |
| 1012 rect.fMinY = SkEndian_SwapBE16(glyphData->yMin); | 924 rect.fMinY = SkEndian_SwapBE16(glyphData->yMin); |
| 1013 rect.fMaxX = SkEndian_SwapBE16(glyphData->xMax); | 925 rect.fMaxX = SkEndian_SwapBE16(glyphData->xMax); |
| 1014 rect.fMaxY = SkEndian_SwapBE16(glyphData->yMax); | 926 rect.fMaxY = SkEndian_SwapBE16(glyphData->yMax); |
| 1015 } | 927 } |
| 1016 #if defined(SK_IGNORE_MAC_TEXT_BOUNDS_FIX) | 928 |
| 1017 fFBoundingBoxesMatrix = fMatrix; | |
| 1018 flip(&fFBoundingBoxesMatrix); | |
| 1019 SkScalar fontScale = getFontScale(fCGFont); | |
| 1020 fFBoundingBoxesMatrix.preScale(fontScale, fontScale); | |
| 1021 #endif | |
| 1022 return true; | 929 return true; |
| 1023 } | 930 } |
| 1024 | 931 |
| 1025 unsigned SkScalerContext_Mac::generateGlyphCount(void) { | 932 unsigned SkScalerContext_Mac::generateGlyphCount(void) { |
| 1026 return fGlyphCount; | 933 return fGlyphCount; |
| 1027 } | 934 } |
| 1028 | 935 |
| 1029 uint16_t SkScalerContext_Mac::generateCharToGlyph(SkUnichar uni) { | 936 uint16_t SkScalerContext_Mac::generateCharToGlyph(SkUnichar uni) { |
| 1030 CGGlyph cgGlyph; | 937 CGGlyph cgGlyph; |
| 1031 UniChar theChar; | 938 UniChar theChar; |
| 1032 | 939 |
| 1033 // Validate our parameters and state | 940 // Validate our parameters and state |
| 1034 SkASSERT(uni <= 0x0000FFFF); | 941 SkASSERT(uni <= 0x0000FFFF); |
| 1035 SkASSERT(sizeof(CGGlyph) <= sizeof(uint16_t)); | 942 SkASSERT(sizeof(CGGlyph) <= sizeof(uint16_t)); |
| 1036 | 943 |
| 1037 // Get the glyph | 944 // Get the glyph |
| 1038 theChar = (UniChar) uni; | 945 theChar = (UniChar) uni; |
| 1039 | 946 |
| 1040 if (!CTFontGetGlyphsForCharacters(fCTFont, &theChar, &cgGlyph, 1)) { | 947 if (!CTFontGetGlyphsForCharacters(fCTFont, &theChar, &cgGlyph, 1)) { |
| 1041 cgGlyph = 0; | 948 cgGlyph = 0; |
| 1042 } | 949 } |
| 1043 | 950 |
| 1044 return cgGlyph; | 951 return cgGlyph; |
| 1045 } | 952 } |
| 1046 | 953 |
| 1047 void SkScalerContext_Mac::generateAdvance(SkGlyph* glyph) { | 954 void SkScalerContext_Mac::generateAdvance(SkGlyph* glyph) { |
| 1048 this->generateMetrics(glyph); | 955 this->generateMetrics(glyph); |
| 1049 } | 956 } |
| 1050 | 957 |
| 1051 #if defined(SK_IGNORE_MAC_TEXT_BOUNDS_FIX) | |
| 1052 void SkScalerContext_Mac::generateMetrics(SkGlyph* glyph) { | |
| 1053 CGSize advance; | |
| 1054 CGRect bounds; | |
| 1055 CGGlyph cgGlyph; | |
| 1056 | |
| 1057 // Get the state we need | |
| 1058 cgGlyph = (CGGlyph) glyph->getGlyphID(fBaseGlyphCount); | |
| 1059 | |
| 1060 if (fVertical) { | |
| 1061 if (!isSnowLeopard()) { | |
| 1062 // Lion and Leopard respect the vertical font metrics. | |
| 1063 CTFontGetBoundingRectsForGlyphs(fCTVerticalFont, kCTFontVerticalOrie
ntation, | |
| 1064 &cgGlyph, &bounds, 1); | |
| 1065 } else { | |
| 1066 // Snow Leopard and earlier respect the vertical font metrics for | |
| 1067 // advances, but not bounds, so use the default box and adjust it be
low. | |
| 1068 CTFontGetBoundingRectsForGlyphs(fCTFont, kCTFontDefaultOrientation, | |
| 1069 &cgGlyph, &bounds, 1); | |
| 1070 } | |
| 1071 CTFontGetAdvancesForGlyphs(fCTVerticalFont, kCTFontVerticalOrientation, | |
| 1072 &cgGlyph, &advance, 1); | |
| 1073 } else { | |
| 1074 CTFontGetBoundingRectsForGlyphs(fCTFont, kCTFontDefaultOrientation, | |
| 1075 &cgGlyph, &bounds, 1); | |
| 1076 CTFontGetAdvancesForGlyphs(fCTFont, kCTFontDefaultOrientation, | |
| 1077 &cgGlyph, &advance, 1); | |
| 1078 } | |
| 1079 | |
| 1080 // BUG? | |
| 1081 // 0x200B (zero-advance space) seems to return a huge (garbage) bounds, when | |
| 1082 // it should be empty. So, if we see a zero-advance, we check if it has an | |
| 1083 // empty path or not, and if so, we jam the bounds to 0. Hopefully a zero-ad
vance | |
| 1084 // is rare, so we won't incur a big performance cost for this extra check. | |
| 1085 if (0 == advance.width && 0 == advance.height) { | |
| 1086 AutoCFRelease<CGPathRef> path(CTFontCreatePathForGlyph(fCTFont, cgGlyph,
NULL)); | |
| 1087 if (NULL == path || CGPathIsEmpty(path)) { | |
| 1088 bounds = CGRectMake(0, 0, 0, 0); | |
| 1089 } | |
| 1090 } | |
| 1091 | |
| 1092 glyph->zeroMetrics(); | |
| 1093 glyph->fAdvanceX = SkFloatToFixed_Check(advance.width); | |
| 1094 glyph->fAdvanceY = -SkFloatToFixed_Check(advance.height); | |
| 1095 | |
| 1096 if (CGRectIsEmpty_inline(bounds)) { | |
| 1097 return; | |
| 1098 } | |
| 1099 | |
| 1100 // Adjust the bounds | |
| 1101 // | |
| 1102 // CTFontGetBoundingRectsForGlyphs ignores the font transform, so we need | |
| 1103 // to transform the bounding box ourselves. | |
| 1104 // | |
| 1105 // The bounds are also expanded by 1 pixel, to give CG room for anti-aliasin
g. | |
| 1106 CGRectInset_inline(&bounds, -1, -1); | |
| 1107 | |
| 1108 // Get the metrics | |
| 1109 bool lionAdjustedMetrics = false; | |
| 1110 if (isLion() || isMountainLion()) { | |
| 1111 if (cgGlyph < fGlyphCount && cgGlyph >= getFBoundingBoxesGlyphOffset() &
& generateBBoxes()){ | |
| 1112 lionAdjustedMetrics = true; | |
| 1113 SkRect adjust; | |
| 1114 const GlyphRect& gRect = fFBoundingBoxes[cgGlyph - fFBoundingBoxesGl
yphOffset]; | |
| 1115 adjust.set(gRect.fMinX, gRect.fMinY, gRect.fMaxX, gRect.fMaxY); | |
| 1116 fFBoundingBoxesMatrix.mapRect(&adjust); | |
| 1117 bounds.origin.x = SkScalarToFloat(adjust.fLeft) - 1; | |
| 1118 bounds.origin.y = SkScalarToFloat(adjust.fTop) - 1; | |
| 1119 } | |
| 1120 // Lion returns fractions in the bounds | |
| 1121 glyph->fWidth = SkToU16(sk_float_ceil2int(bounds.size.width)); | |
| 1122 glyph->fHeight = SkToU16(sk_float_ceil2int(bounds.size.height)); | |
| 1123 } else { | |
| 1124 glyph->fWidth = SkToU16(sk_float_round2int(bounds.size.width)); | |
| 1125 glyph->fHeight = SkToU16(sk_float_round2int(bounds.size.height)); | |
| 1126 } | |
| 1127 glyph->fTop = SkToS16(-sk_float_round2int(CGRectGetMaxY_inline(bounds))); | |
| 1128 glyph->fLeft = SkToS16(sk_float_round2int(CGRectGetMinX_inline(bounds))); | |
| 1129 SkIPoint offset; | |
| 1130 if (fVertical && (isSnowLeopard() || lionAdjustedMetrics)) { | |
| 1131 // SnowLeopard doesn't respect vertical metrics, so compute them manuall
y. | |
| 1132 // Also compute them for Lion when the metrics were computed by hand. | |
| 1133 getVerticalOffset(cgGlyph, &offset); | |
| 1134 glyph->fLeft += offset.fX; | |
| 1135 glyph->fTop += offset.fY; | |
| 1136 } | |
| 1137 #ifdef HACK_COLORGLYPHS | |
| 1138 glyph->fMaskFormat = SkMask::kARGB32_Format; | |
| 1139 #endif | |
| 1140 } | |
| 1141 #else | |
| 1142 void SkScalerContext_Mac::generateMetrics(SkGlyph* glyph) { | 958 void SkScalerContext_Mac::generateMetrics(SkGlyph* glyph) { |
| 1143 const CGGlyph cgGlyph = (CGGlyph) glyph->getGlyphID(fBaseGlyphCount); | 959 const CGGlyph cgGlyph = (CGGlyph) glyph->getGlyphID(fBaseGlyphCount); |
| 1144 glyph->zeroMetrics(); | 960 glyph->zeroMetrics(); |
| 1145 | 961 |
| 1146 // The following block produces cgAdvance in CG units (pixels, y up). | 962 // The following block produces cgAdvance in CG units (pixels, y up). |
| 1147 CGSize cgAdvance; | 963 CGSize cgAdvance; |
| 1148 if (fVertical) { | 964 if (fVertical) { |
| 1149 CTFontGetAdvancesForGlyphs(fCTVerticalFont, kCTFontVerticalOrientation, | 965 CTFontGetAdvancesForGlyphs(fCTVerticalFont, kCTFontVerticalOrientation, |
| 1150 &cgGlyph, &cgAdvance, 1); | 966 &cgGlyph, &cgAdvance, 1); |
| 1151 } else { | 967 } else { |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1243 glyph->fLeft = SkToS16(skIBounds.fLeft); | 1059 glyph->fLeft = SkToS16(skIBounds.fLeft); |
| 1244 glyph->fTop = SkToS16(skIBounds.fTop); | 1060 glyph->fTop = SkToS16(skIBounds.fTop); |
| 1245 glyph->fWidth = SkToU16(skIBounds.width()); | 1061 glyph->fWidth = SkToU16(skIBounds.width()); |
| 1246 glyph->fHeight = SkToU16(skIBounds.height()); | 1062 glyph->fHeight = SkToU16(skIBounds.height()); |
| 1247 | 1063 |
| 1248 #ifdef HACK_COLORGLYPHS | 1064 #ifdef HACK_COLORGLYPHS |
| 1249 glyph->fMaskFormat = SkMask::kARGB32_Format; | 1065 glyph->fMaskFormat = SkMask::kARGB32_Format; |
| 1250 #endif | 1066 #endif |
| 1251 } | 1067 } |
| 1252 | 1068 |
| 1253 #endif | |
| 1254 #include "SkColorPriv.h" | 1069 #include "SkColorPriv.h" |
| 1255 | 1070 |
| 1256 static void build_power_table(uint8_t table[], float ee) { | 1071 static void build_power_table(uint8_t table[], float ee) { |
| 1257 for (int i = 0; i < 256; i++) { | 1072 for (int i = 0; i < 256; i++) { |
| 1258 float x = i / 255.f; | 1073 float x = i / 255.f; |
| 1259 x = sk_float_pow(x, ee); | 1074 x = sk_float_pow(x, ee); |
| 1260 int xx = SkScalarRoundToInt(SkFloatToScalar(x * 255)); | 1075 int xx = SkScalarRoundToInt(SkFloatToScalar(x * 255)); |
| 1261 table[i] = SkToU8(xx); | 1076 table[i] = SkToU8(xx); |
| 1262 } | 1077 } |
| 1263 } | 1078 } |
| (...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1534 } | 1349 } |
| 1535 | 1350 |
| 1536 if (fDoSubPosition) { | 1351 if (fDoSubPosition) { |
| 1537 SkMatrix m; | 1352 SkMatrix m; |
| 1538 m.setScale(SkScalarInvert(scaleX), SkScalarInvert(scaleY)); | 1353 m.setScale(SkScalarInvert(scaleX), SkScalarInvert(scaleY)); |
| 1539 path->transform(m); | 1354 path->transform(m); |
| 1540 // balance the call to CTFontCreateCopyWithAttributes | 1355 // balance the call to CTFontCreateCopyWithAttributes |
| 1541 CFSafeRelease(font); | 1356 CFSafeRelease(font); |
| 1542 } | 1357 } |
| 1543 if (fVertical) { | 1358 if (fVertical) { |
| 1544 #if defined(SK_IGNORE_MAC_TEXT_BOUNDS_FIX) | |
| 1545 SkIPoint offset; | |
| 1546 getVerticalOffset(cgGlyph, &offset); | |
| 1547 path->offset(SkIntToScalar(offset.fX), SkIntToScalar(offset.fY)); | |
| 1548 #else | |
| 1549 SkPoint offset; | 1359 SkPoint offset; |
| 1550 getVerticalOffset(cgGlyph, &offset); | 1360 getVerticalOffset(cgGlyph, &offset); |
| 1551 path->offset(offset.fX, offset.fY); | 1361 path->offset(offset.fX, offset.fY); |
| 1552 #endif | |
| 1553 } | 1362 } |
| 1554 } | 1363 } |
| 1555 | 1364 |
| 1556 void SkScalerContext_Mac::generateFontMetrics(SkPaint::FontMetrics* mx, | 1365 void SkScalerContext_Mac::generateFontMetrics(SkPaint::FontMetrics* mx, |
| 1557 SkPaint::FontMetrics* my) { | 1366 SkPaint::FontMetrics* my) { |
| 1558 CGRect theBounds = CTFontGetBoundingBox(fCTFont); | 1367 CGRect theBounds = CTFontGetBoundingBox(fCTFont); |
| 1559 | 1368 |
| 1560 SkPaint::FontMetrics theMetrics; | 1369 SkPaint::FontMetrics theMetrics; |
| 1561 theMetrics.fTop = CGToScalar(-CGRectGetMaxY_inline(theBounds)); | 1370 theMetrics.fTop = CGToScalar(-CGRectGetMaxY_inline(theBounds)); |
| 1562 theMetrics.fAscent = CGToScalar(-CTFontGetAscent(fCTFont)); | 1371 theMetrics.fAscent = CGToScalar(-CTFontGetAscent(fCTFont)); |
| (...skipping 826 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2389 return NULL; | 2198 return NULL; |
| 2390 } | 2199 } |
| 2391 return create_from_dataProvider(pr); | 2200 return create_from_dataProvider(pr); |
| 2392 } | 2201 } |
| 2393 }; | 2202 }; |
| 2394 | 2203 |
| 2395 SkFontMgr* SkFontMgr::Factory() { | 2204 SkFontMgr* SkFontMgr::Factory() { |
| 2396 return SkNEW(SkFontMgr_Mac); | 2205 return SkNEW(SkFontMgr_Mac); |
| 2397 } | 2206 } |
| 2398 #endif | 2207 #endif |
| OLD | NEW |