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 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 public: | 117 public: |
118 const T* fData; | 118 const T* fData; |
119 }; | 119 }; |
120 | 120 |
121 // inline versions of these rect helpers | 121 // inline versions of these rect helpers |
122 | 122 |
123 static bool CGRectIsEmpty_inline(const CGRect& rect) { | 123 static bool CGRectIsEmpty_inline(const CGRect& rect) { |
124 return rect.size.width <= 0 || rect.size.height <= 0; | 124 return rect.size.width <= 0 || rect.size.height <= 0; |
125 } | 125 } |
126 | 126 |
127 static void CGRectInset_inline(CGRect* rect, CGFloat dx, CGFloat dy) { | |
128 rect->origin.x += dx; | |
129 rect->origin.y += dy; | |
130 rect->size.width -= dx * 2; | |
131 rect->size.height -= dy * 2; | |
132 } | |
133 | |
134 static CGFloat CGRectGetMinX_inline(const CGRect& rect) { | 127 static CGFloat CGRectGetMinX_inline(const CGRect& rect) { |
135 return rect.origin.x; | 128 return rect.origin.x; |
136 } | 129 } |
137 | 130 |
138 static CGFloat CGRectGetMaxX_inline(const CGRect& rect) { | 131 static CGFloat CGRectGetMaxX_inline(const CGRect& rect) { |
139 return rect.origin.x + rect.size.width; | 132 return rect.origin.x + rect.size.width; |
140 } | 133 } |
141 | 134 |
142 static CGFloat CGRectGetMinY_inline(const CGRect& rect) { | 135 static CGFloat CGRectGetMinY_inline(const CGRect& rect) { |
143 return rect.origin.y; | 136 return rect.origin.y; |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
244 SkDebugf("could not parse uname release %s\n", info.release); | 237 SkDebugf("could not parse uname release %s\n", info.release); |
245 } | 238 } |
246 return version; | 239 return version; |
247 } | 240 } |
248 | 241 |
249 static int darwinVersion() { | 242 static int darwinVersion() { |
250 static int darwin_version = readVersion(); | 243 static int darwin_version = readVersion(); |
251 return darwin_version; | 244 return darwin_version; |
252 } | 245 } |
253 | 246 |
254 static bool isLeopard() { | |
255 return darwinVersion() == 9; | |
256 } | |
257 | |
258 static bool isSnowLeopard() { | 247 static bool isSnowLeopard() { |
259 return darwinVersion() == 10; | 248 return darwinVersion() == 10; |
260 } | 249 } |
261 | 250 |
262 static bool isLion() { | 251 static bool isLion() { |
263 return darwinVersion() == 11; | 252 return darwinVersion() == 11; |
264 } | 253 } |
265 | 254 |
266 static bool isMountainLion() { | 255 static bool isMountainLion() { |
267 return darwinVersion() == 12; | 256 return darwinVersion() == 12; |
(...skipping 25 matching lines...) Expand all Loading... |
293 SkScalar sx = SK_Scalar1, | 282 SkScalar sx = SK_Scalar1, |
294 SkScalar sy = SK_Scalar1) { | 283 SkScalar sy = SK_Scalar1) { |
295 return CGAffineTransformMake( ScalarToCG(matrix[SkMatrix::kMScaleX] * sx), | 284 return CGAffineTransformMake( ScalarToCG(matrix[SkMatrix::kMScaleX] * sx), |
296 -ScalarToCG(matrix[SkMatrix::kMSkewY] * sy), | 285 -ScalarToCG(matrix[SkMatrix::kMSkewY] * sy), |
297 -ScalarToCG(matrix[SkMatrix::kMSkewX] * sx), | 286 -ScalarToCG(matrix[SkMatrix::kMSkewX] * sx), |
298 ScalarToCG(matrix[SkMatrix::kMScaleY] * sy), | 287 ScalarToCG(matrix[SkMatrix::kMScaleY] * sy), |
299 ScalarToCG(matrix[SkMatrix::kMTransX] * sx), | 288 ScalarToCG(matrix[SkMatrix::kMTransX] * sx), |
300 ScalarToCG(matrix[SkMatrix::kMTransY] * sy)); | 289 ScalarToCG(matrix[SkMatrix::kMTransY] * sy)); |
301 } | 290 } |
302 | 291 |
303 static SkScalar getFontScale(CGFontRef cgFont) { | |
304 int unitsPerEm = CGFontGetUnitsPerEm(cgFont); | |
305 return SkScalarInvert(SkIntToScalar(unitsPerEm)); | |
306 } | |
307 | |
308 /////////////////////////////////////////////////////////////////////////////// | 292 /////////////////////////////////////////////////////////////////////////////// |
309 | 293 |
310 #define BITMAP_INFO_RGB (kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host) | 294 #define BITMAP_INFO_RGB (kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host) |
311 #define BITMAP_INFO_GRAY (kCGImageAlphaNone) | 295 #define BITMAP_INFO_GRAY (kCGImageAlphaNone) |
312 | 296 |
313 /** | 297 /** |
314 * 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 |
315 * 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 |
316 * 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. |
317 */ | 301 */ |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
523 if (cfFontName != NULL && cfFontTraits != NULL && cfAttributes != NULL && cf
Traits != NULL) { | 507 if (cfFontName != NULL && cfFontTraits != NULL && cfAttributes != NULL && cf
Traits != NULL) { |
524 CFDictionaryAddValue(cfTraits, kCTFontSymbolicTrait, cfFontTraits); | 508 CFDictionaryAddValue(cfTraits, kCTFontSymbolicTrait, cfFontTraits); |
525 | 509 |
526 CFDictionaryAddValue(cfAttributes, kCTFontFamilyNameAttribute, cfFontNam
e); | 510 CFDictionaryAddValue(cfAttributes, kCTFontFamilyNameAttribute, cfFontNam
e); |
527 CFDictionaryAddValue(cfAttributes, kCTFontTraitsAttribute, cfTraits); | 511 CFDictionaryAddValue(cfAttributes, kCTFontTraitsAttribute, cfTraits); |
528 | 512 |
529 AutoCFRelease<CTFontDescriptorRef> ctFontDesc( | 513 AutoCFRelease<CTFontDescriptorRef> ctFontDesc( |
530 CTFontDescriptorCreateWithAttributes(cfAttributes)); | 514 CTFontDescriptorCreateWithAttributes(cfAttributes)); |
531 | 515 |
532 if (ctFontDesc != NULL) { | 516 if (ctFontDesc != NULL) { |
533 if (isLeopard()) { | 517 ctFont = CTFontCreateWithFontDescriptor(ctFontDesc, 0, NULL); |
534 // CTFontCreateWithFontDescriptor on Leopard ignores the name | |
535 AutoCFRelease<CTFontRef> ctNamed(CTFontCreateWithName(cfFontName
, 1, NULL)); | |
536 ctFont = CTFontCreateCopyWithAttributes(ctNamed, 1, NULL, ctFont
Desc); | |
537 } else { | |
538 ctFont = CTFontCreateWithFontDescriptor(ctFontDesc, 0, NULL); | |
539 } | |
540 } | 518 } |
541 } | 519 } |
542 | 520 |
543 return ctFont ? NewFromFontRef(ctFont, familyName) : NULL; | 521 return ctFont ? NewFromFontRef(ctFont, familyName) : NULL; |
544 } | 522 } |
545 | 523 |
546 static SkTypeface* GetDefaultFace() { | 524 static SkTypeface* GetDefaultFace() { |
547 SK_DECLARE_STATIC_MUTEX(gMutex); | 525 SK_DECLARE_STATIC_MUTEX(gMutex); |
548 SkAutoMutexAcquire ma(gMutex); | 526 SkAutoMutexAcquire ma(gMutex); |
549 | 527 |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
641 if (face) { | 619 if (face) { |
642 SkTypefaceCache::Add(face, style); | 620 SkTypefaceCache::Add(face, style); |
643 } else { | 621 } else { |
644 face = GetDefaultFace(); | 622 face = GetDefaultFace(); |
645 face->ref(); | 623 face->ref(); |
646 } | 624 } |
647 } | 625 } |
648 return face; | 626 return face; |
649 } | 627 } |
650 | 628 |
651 static void flip(SkMatrix* matrix) { | |
652 matrix->setSkewX(-matrix->getSkewX()); | |
653 matrix->setSkewY(-matrix->getSkewY()); | |
654 } | |
655 | |
656 /////////////////////////////////////////////////////////////////////////////// | 629 /////////////////////////////////////////////////////////////////////////////// |
657 | 630 |
| 631 /** GlyphRect is in FUnits (em space, y up). */ |
658 struct GlyphRect { | 632 struct GlyphRect { |
659 int16_t fMinX; | 633 int16_t fMinX; |
660 int16_t fMinY; | 634 int16_t fMinY; |
661 int16_t fMaxX; | 635 int16_t fMaxX; |
662 int16_t fMaxY; | 636 int16_t fMaxY; |
663 }; | 637 }; |
664 | 638 |
665 class SkScalerContext_Mac : public SkScalerContext { | 639 class SkScalerContext_Mac : public SkScalerContext { |
666 public: | 640 public: |
667 SkScalerContext_Mac(SkTypeface_Mac*, const SkDescriptor*); | 641 SkScalerContext_Mac(SkTypeface_Mac*, const SkDescriptor*); |
668 virtual ~SkScalerContext_Mac(); | 642 virtual ~SkScalerContext_Mac() { }; |
669 | |
670 | 643 |
671 protected: | 644 protected: |
672 unsigned generateGlyphCount(void) SK_OVERRIDE; | 645 unsigned generateGlyphCount(void) SK_OVERRIDE; |
673 uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE; | 646 uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE; |
674 void generateAdvance(SkGlyph* glyph) SK_OVERRIDE; | 647 void generateAdvance(SkGlyph* glyph) SK_OVERRIDE; |
675 void generateMetrics(SkGlyph* glyph) SK_OVERRIDE; | 648 void generateMetrics(SkGlyph* glyph) SK_OVERRIDE; |
676 void generateImage(const SkGlyph& glyph) SK_OVERRIDE; | 649 void generateImage(const SkGlyph& glyph) SK_OVERRIDE; |
677 void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE; | 650 void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE; |
678 void generateFontMetrics(SkPaint::FontMetrics* mX, SkPaint::FontMetrics* mY)
SK_OVERRIDE; | 651 void generateFontMetrics(SkPaint::FontMetrics* mX, SkPaint::FontMetrics* mY)
SK_OVERRIDE; |
679 | 652 |
680 private: | 653 private: |
681 static void CTPathElement(void *info, const CGPathElement *element); | 654 static void CTPathElement(void *info, const CGPathElement *element); |
682 uint16_t getFBoundingBoxesGlyphOffset(); | 655 uint16_t getFBoundingBoxesGlyphOffset(); |
683 void getVerticalOffset(CGGlyph glyphID, SkIPoint* offset) const; | 656 /** Returns the offset from the horizontal origin to the vertical origin in
SkGlyph units. */ |
| 657 void getVerticalOffset(CGGlyph glyphID, SkPoint* offset) const; |
684 bool generateBBoxes(); | 658 bool generateBBoxes(); |
685 | 659 |
686 CGAffineTransform fTransform; | 660 /** |
687 SkMatrix fUnitMatrix; // without font size | 661 * Converts from FUnits (em space, y up) to SkGlyph units (pixels, y down). |
688 SkMatrix fVerticalMatrix; // unit rotated | 662 * |
689 SkMatrix fMatrix; // with font size | 663 * Used on Snow Leopard to correct CTFontGetVerticalTranslationsForGlyphs. |
690 SkMatrix fFBoundingBoxesMatrix; // lion-specific fix | 664 * Used on Lion to correct CTFontGetBoundingRectsForGlyphs. |
| 665 */ |
| 666 SkMatrix fFUnitMatrix; |
691 Offscreen fOffscreen; | 667 Offscreen fOffscreen; |
692 AutoCFRelease<CTFontRef> fCTFont; | 668 AutoCFRelease<CTFontRef> fCTFont; |
693 AutoCFRelease<CTFontRef> fCTVerticalFont; // for vertical advance | 669 /** CT vertical metrics are pre-rotated (in em space, before transform) 90de
g clock-wise. |
| 670 * This makes kCTFontDefaultOrientation dangerous, because the metrics from |
| 671 * kCTFontHorizontalOrientation are in a different space from kCTFontVertic
alOrientation. |
| 672 * Use fCTVerticalFont with kCTFontVerticalOrientation to get metrics in th
e same space. |
| 673 */ |
| 674 AutoCFRelease<CTFontRef> fCTVerticalFont; |
694 AutoCFRelease<CGFontRef> fCGFont; | 675 AutoCFRelease<CGFontRef> fCGFont; |
695 GlyphRect* fFBoundingBoxes; | 676 SkAutoTMalloc<GlyphRect> fFBoundingBoxes; |
696 uint16_t fFBoundingBoxesGlyphOffset; | 677 uint16_t fFBoundingBoxesGlyphOffset; |
697 uint16_t fGlyphCount; | 678 uint16_t fGlyphCount; |
698 bool fGeneratedFBoundingBoxes; | 679 bool fGeneratedFBoundingBoxes; |
699 bool fDoSubPosition; | 680 const bool fDoSubPosition; |
700 bool fVertical; | 681 const bool fVertical; |
701 | 682 |
702 friend class Offscreen; | 683 friend class Offscreen; |
703 | 684 |
704 typedef SkScalerContext INHERITED; | 685 typedef SkScalerContext INHERITED; |
705 }; | 686 }; |
706 | 687 |
707 SkScalerContext_Mac::SkScalerContext_Mac(SkTypeface_Mac* typeface, | 688 SkScalerContext_Mac::SkScalerContext_Mac(SkTypeface_Mac* typeface, |
708 const SkDescriptor* desc) | 689 const SkDescriptor* desc) |
709 : INHERITED(typeface, desc) | 690 : INHERITED(typeface, desc) |
710 , fFBoundingBoxes(NULL) | 691 , fFBoundingBoxes() |
711 , fFBoundingBoxesGlyphOffset(0) | 692 , fFBoundingBoxesGlyphOffset(0) |
712 , fGeneratedFBoundingBoxes(false) | 693 , fGeneratedFBoundingBoxes(false) |
| 694 , fDoSubPosition(SkToBool(fRec.fFlags & kSubpixelPositioning_Flag)) |
| 695 , fVertical(SkToBool(fRec.fFlags & kVertical_Flag)) |
| 696 |
713 { | 697 { |
| 698 //this->forceGenerateImageFromPath(); |
714 CTFontRef ctFont = typeface->fFontRef.get(); | 699 CTFontRef ctFont = typeface->fFontRef.get(); |
715 CFIndex numGlyphs = CTFontGetGlyphCount(ctFont); | 700 CFIndex numGlyphs = CTFontGetGlyphCount(ctFont); |
716 | |
717 // Get the state we need | |
718 fRec.getSingleMatrix(&fMatrix); | |
719 fUnitMatrix = fMatrix; | |
720 | |
721 // extract the font size out of the matrix, but leave the skewing for italic | |
722 SkScalar reciprocal = SkScalarInvert(fRec.fTextSize); | |
723 fUnitMatrix.preScale(reciprocal, reciprocal); | |
724 | |
725 SkASSERT(numGlyphs >= 1 && numGlyphs <= 0xFFFF); | 701 SkASSERT(numGlyphs >= 1 && numGlyphs <= 0xFFFF); |
726 | 702 fGlyphCount = SkToU16(numGlyphs); |
727 fTransform = MatrixToCGAffineTransform(fMatrix); | 703 |
728 | 704 fRec.getSingleMatrix(&fFUnitMatrix); |
729 CGAffineTransform transform; | 705 CGAffineTransform transform = MatrixToCGAffineTransform(fFUnitMatrix); |
730 CGFloat unitFontSize; | 706 |
731 if (isLeopard()) { | |
732 // passing 1 for pointSize to Leopard sets the font size to 1 pt. | |
733 // pass the CoreText size explicitly | |
734 transform = MatrixToCGAffineTransform(fUnitMatrix); | |
735 unitFontSize = SkScalarToFloat(fRec.fTextSize); | |
736 } else { | |
737 // since our matrix includes everything, we pass 1 for pointSize | |
738 transform = fTransform; | |
739 unitFontSize = 1; | |
740 } | |
741 flip(&fUnitMatrix); // flip to fix up bounds later | |
742 fVertical = SkToBool(fRec.fFlags & kVertical_Flag); | |
743 AutoCFRelease<CTFontDescriptorRef> ctFontDesc; | 707 AutoCFRelease<CTFontDescriptorRef> ctFontDesc; |
744 if (fVertical) { | 708 if (fVertical) { |
745 AutoCFRelease<CFMutableDictionaryRef> cfAttributes(CFDictionaryCreateMut
able( | 709 AutoCFRelease<CFMutableDictionaryRef> cfAttributes(CFDictionaryCreateMut
able( |
746 kCFAllocatorDefault, 0, | 710 kCFAllocatorDefault, 0, |
747 &kCFTypeDictionaryKeyCallBacks, | 711 &kCFTypeDictionaryKeyCallBacks, |
748 &kCFTypeDictionaryValueCallBacks)); | 712 &kCFTypeDictionaryValueCallBacks)); |
749 if (cfAttributes) { | 713 if (cfAttributes) { |
750 CTFontOrientation ctOrientation = kCTFontVerticalOrientation; | 714 CTFontOrientation ctOrientation = kCTFontVerticalOrientation; |
751 AutoCFRelease<CFNumberRef> cfVertical(CFNumberCreate( | 715 AutoCFRelease<CFNumberRef> cfVertical(CFNumberCreate( |
752 kCFAllocatorDefault, kCFNumberSInt32Type, &ctOrientation)); | 716 kCFAllocatorDefault, kCFNumberSInt32Type, &ctOrientation)); |
753 CFDictionaryAddValue(cfAttributes, kCTFontOrientationAttribute, cfVe
rtical); | 717 CFDictionaryAddValue(cfAttributes, kCTFontOrientationAttribute, cfVe
rtical); |
754 ctFontDesc = CTFontDescriptorCreateWithAttributes(cfAttributes); | 718 ctFontDesc = CTFontDescriptorCreateWithAttributes(cfAttributes); |
755 } | 719 } |
756 } | 720 } |
757 fCTFont = CTFontCreateCopyWithAttributes(ctFont, unitFontSize, &transform, c
tFontDesc); | 721 // Since our matrix includes everything, we pass 1 for size. |
| 722 fCTFont = CTFontCreateCopyWithAttributes(ctFont, 1.f, &transform, ctFontDesc
); |
758 fCGFont = CTFontCopyGraphicsFont(fCTFont, NULL); | 723 fCGFont = CTFontCopyGraphicsFont(fCTFont, NULL); |
759 if (fVertical) { | 724 if (fVertical) { |
760 CGAffineTransform rotateLeft = CGAffineTransformMake(0, -1, 1, 0, 0, 0); | 725 CGAffineTransform rotateLeft = CGAffineTransformMake(0, -1, 1, 0, 0, 0); |
761 transform = CGAffineTransformConcat(rotateLeft, transform); | 726 transform = CGAffineTransformConcat(rotateLeft, transform); |
762 fCTVerticalFont = CTFontCreateCopyWithAttributes(ctFont, unitFontSize, &
transform, NULL); | 727 fCTVerticalFont = CTFontCreateCopyWithAttributes(ctFont, 1.f, &transform
, NULL); |
763 fVerticalMatrix = fUnitMatrix; | |
764 if (isSnowLeopard()) { | |
765 SkScalar scale = SkScalarMul(fRec.fTextSize, getFontScale(fCGFont)); | |
766 fVerticalMatrix.preScale(scale, scale); | |
767 } else { | |
768 fVerticalMatrix.preRotate(SkIntToScalar(90)); | |
769 } | |
770 fVerticalMatrix.postScale(SK_Scalar1, -SK_Scalar1); | |
771 } | 728 } |
772 fGlyphCount = SkToU16(numGlyphs); | 729 SkScalar emPerFUnit = SkScalarInvert(SkIntToScalar(CGFontGetUnitsPerEm(fCGFo
nt))); |
773 fDoSubPosition = SkToBool(fRec.fFlags & kSubpixelPositioning_Flag); | 730 fFUnitMatrix.preScale(emPerFUnit, -emPerFUnit); |
774 } | |
775 | |
776 SkScalerContext_Mac::~SkScalerContext_Mac() { | |
777 delete[] fFBoundingBoxes; | |
778 } | 731 } |
779 | 732 |
780 CGRGBPixel* Offscreen::getCG(const SkScalerContext_Mac& context, const SkGlyph&
glyph, | 733 CGRGBPixel* Offscreen::getCG(const SkScalerContext_Mac& context, const SkGlyph&
glyph, |
781 CGGlyph glyphID, size_t* rowBytesPtr, | 734 CGGlyph glyphID, size_t* rowBytesPtr, |
782 bool generateA8FromLCD) { | 735 bool generateA8FromLCD) { |
783 if (!fRGBSpace) { | 736 if (!fRGBSpace) { |
784 //It doesn't appear to matter what color space is specified. | 737 //It doesn't appear to matter what color space is specified. |
785 //Regular blends and antialiased text are always (s*a + d*(1-a)) | 738 //Regular blends and antialiased text are always (s*a + d*(1-a)) |
786 //and smoothed text is always g=2.0. | 739 //and smoothed text is always g=2.0. |
787 fRGBSpace = CGColorSpaceCreateDeviceRGB(); | 740 fRGBSpace = CGColorSpaceCreateDeviceRGB(); |
(...skipping 28 matching lines...) Expand all Loading... |
816 fCG = CGBitmapContextCreate(image, fSize.fWidth, fSize.fHeight, 8, | 769 fCG = CGBitmapContextCreate(image, fSize.fWidth, fSize.fHeight, 8, |
817 rowBytes, fRGBSpace, BITMAP_INFO_RGB); | 770 rowBytes, fRGBSpace, BITMAP_INFO_RGB); |
818 | 771 |
819 // skia handles quantization itself, so we disable this for cg to get | 772 // skia handles quantization itself, so we disable this for cg to get |
820 // full fractional data from them. | 773 // full fractional data from them. |
821 CGContextSetAllowsFontSubpixelQuantization(fCG, false); | 774 CGContextSetAllowsFontSubpixelQuantization(fCG, false); |
822 CGContextSetShouldSubpixelQuantizeFonts(fCG, false); | 775 CGContextSetShouldSubpixelQuantizeFonts(fCG, false); |
823 | 776 |
824 CGContextSetTextDrawingMode(fCG, kCGTextFill); | 777 CGContextSetTextDrawingMode(fCG, kCGTextFill); |
825 CGContextSetFont(fCG, context.fCGFont); | 778 CGContextSetFont(fCG, context.fCGFont); |
826 CGContextSetFontSize(fCG, 1); | 779 CGContextSetFontSize(fCG, 1.0f /*CTFontGetSize(context.fCTFont)*/); |
827 CGContextSetTextMatrix(fCG, context.fTransform); | 780 CGContextSetTextMatrix(fCG, CTFontGetMatrix(context.fCTFont)); |
828 | 781 |
829 CGContextSetAllowsFontSubpixelPositioning(fCG, context.fDoSubPosition); | 782 // Because CG always draws from the horizontal baseline, |
830 CGContextSetShouldSubpixelPositionFonts(fCG, context.fDoSubPosition); | 783 // if there is a non-integral translation from the horizontal origin to
the vertical origin, |
| 784 // then CG cannot draw the glyph in the correct location without subpixe
l positioning. |
| 785 CGContextSetAllowsFontSubpixelPositioning(fCG, context.fDoSubPosition ||
context.fVertical); |
| 786 CGContextSetShouldSubpixelPositionFonts(fCG, context.fDoSubPosition || c
ontext.fVertical); |
831 | 787 |
832 // Draw white on black to create mask. | 788 // Draw white on black to create mask. |
833 // TODO: Draw black on white and invert, CG has a special case codepath. | 789 // TODO: Draw black on white and invert, CG has a special case codepath. |
834 CGContextSetGrayFillColor(fCG, 1.0f, 1.0f); | 790 CGContextSetGrayFillColor(fCG, 1.0f, 1.0f); |
835 | 791 |
836 // force our checks below to happen | 792 // force our checks below to happen |
837 fDoAA = !doAA; | 793 fDoAA = !doAA; |
838 fDoLCD = !doLCD; | 794 fDoLCD = !doLCD; |
839 } | 795 } |
840 | 796 |
(...skipping 12 matching lines...) Expand all Loading... |
853 | 809 |
854 // erase to black | 810 // erase to black |
855 sk_memset_rect32(image, 0, glyph.fWidth, glyph.fHeight, rowBytes); | 811 sk_memset_rect32(image, 0, glyph.fWidth, glyph.fHeight, rowBytes); |
856 | 812 |
857 float subX = 0; | 813 float subX = 0; |
858 float subY = 0; | 814 float subY = 0; |
859 if (context.fDoSubPosition) { | 815 if (context.fDoSubPosition) { |
860 subX = SkFixedToFloat(glyph.getSubXFixed()); | 816 subX = SkFixedToFloat(glyph.getSubXFixed()); |
861 subY = SkFixedToFloat(glyph.getSubYFixed()); | 817 subY = SkFixedToFloat(glyph.getSubYFixed()); |
862 } | 818 } |
| 819 |
| 820 // CGContextShowGlyphsAtPoint always draws using the horizontal baseline ori
gin. |
863 if (context.fVertical) { | 821 if (context.fVertical) { |
864 SkIPoint offset; | 822 SkPoint offset; |
865 context.getVerticalOffset(glyphID, &offset); | 823 context.getVerticalOffset(glyphID, &offset); |
866 subX += offset.fX; | 824 subX += offset.fX; |
867 subY += offset.fY; | 825 subY += offset.fY; |
868 } | 826 } |
| 827 |
869 CGContextShowGlyphsAtPoint(fCG, -glyph.fLeft + subX, | 828 CGContextShowGlyphsAtPoint(fCG, -glyph.fLeft + subX, |
870 glyph.fTop + glyph.fHeight - subY, | 829 glyph.fTop + glyph.fHeight - subY, |
871 &glyphID, 1); | 830 &glyphID, 1); |
872 | 831 |
873 SkASSERT(rowBytesPtr); | 832 SkASSERT(rowBytesPtr); |
874 *rowBytesPtr = rowBytes; | 833 *rowBytesPtr = rowBytes; |
875 return image; | 834 return image; |
876 } | 835 } |
877 | 836 |
878 void SkScalerContext_Mac::getVerticalOffset(CGGlyph glyphID, SkIPoint* offset) c
onst { | 837 void SkScalerContext_Mac::getVerticalOffset(CGGlyph glyphID, SkPoint* offset) co
nst { |
879 CGSize vertOffset; | 838 // SnowLeopard returns cgVertOffset in completely un-transformed FUnits (em
space, y up). |
880 CTFontGetVerticalTranslationsForGlyphs(fCTVerticalFont, &glyphID, &vertOffse
t, 1); | 839 // Lion and Leopard return cgVertOffset in CG units (pixels, y up). |
881 const SkPoint trans = {CGToScalar(vertOffset.width), | 840 CGSize cgVertOffset; |
882 CGToScalar(vertOffset.height)}; | 841 CTFontGetVerticalTranslationsForGlyphs(fCTFont, &glyphID, &cgVertOffset, 1); |
883 SkPoint floatOffset; | 842 |
884 fVerticalMatrix.mapPoints(&floatOffset, &trans, 1); | 843 SkPoint skVertOffset = { CGToScalar(cgVertOffset.width), CGToScalar(cgVertOf
fset.height) }; |
885 if (!isSnowLeopard()) { | 844 if (isSnowLeopard()) { |
886 // SnowLeopard fails to apply the font's matrix to the vertical metrics, | 845 // From FUnits (em space, y up) to SkGlyph units (pixels, y down). |
887 // but Lion and Leopard do. The unit matrix describes the font's matrix at | 846 fFUnitMatrix.mapPoints(&skVertOffset, 1); |
888 // point size 1. There may be some way to avoid mapping here by setting up | 847 } else { |
889 // fVerticalMatrix differently, but this works for now. | 848 skVertOffset.fY = -skVertOffset.fY; |
890 fUnitMatrix.mapPoints(&floatOffset, 1); | |
891 } | 849 } |
892 offset->fX = SkScalarRound(floatOffset.fX); | 850 |
893 offset->fY = SkScalarRound(floatOffset.fY); | 851 *offset = skVertOffset; |
894 } | 852 } |
895 | 853 |
896 uint16_t SkScalerContext_Mac::getFBoundingBoxesGlyphOffset() { | 854 uint16_t SkScalerContext_Mac::getFBoundingBoxesGlyphOffset() { |
897 if (fFBoundingBoxesGlyphOffset) { | 855 if (fFBoundingBoxesGlyphOffset) { |
898 return fFBoundingBoxesGlyphOffset; | 856 return fFBoundingBoxesGlyphOffset; |
899 } | 857 } |
900 fFBoundingBoxesGlyphOffset = fGlyphCount; // fallback for all fonts | 858 fFBoundingBoxesGlyphOffset = fGlyphCount; // fallback for all fonts |
901 AutoCGTable<SkOTTableHorizontalHeader> hheaTable(fCGFont); | 859 AutoCGTable<SkOTTableHorizontalHeader> hheaTable(fCGFont); |
902 if (hheaTable.fData) { | 860 if (hheaTable.fData) { |
903 fFBoundingBoxesGlyphOffset = SkEndian_SwapBE16(hheaTable->numberOfHMetri
cs); | 861 fFBoundingBoxesGlyphOffset = SkEndian_SwapBE16(hheaTable->numberOfHMetri
cs); |
(...skipping 27 matching lines...) Expand all Loading... |
931 if (!locaTable.fData) { | 889 if (!locaTable.fData) { |
932 return false; | 890 return false; |
933 } | 891 } |
934 | 892 |
935 AutoCGTable<SkOTTableGlyph> glyfTable(fCGFont); | 893 AutoCGTable<SkOTTableGlyph> glyfTable(fCGFont); |
936 if (!glyfTable.fData) { | 894 if (!glyfTable.fData) { |
937 return false; | 895 return false; |
938 } | 896 } |
939 | 897 |
940 uint16_t entries = fGlyphCount - fFBoundingBoxesGlyphOffset; | 898 uint16_t entries = fGlyphCount - fFBoundingBoxesGlyphOffset; |
941 fFBoundingBoxes = new GlyphRect[entries]; | 899 fFBoundingBoxes.reset(entries); |
942 | 900 |
943 SkOTTableHead::IndexToLocFormat locaFormat = headTable->indexToLocFormat; | 901 SkOTTableHead::IndexToLocFormat locaFormat = headTable->indexToLocFormat; |
944 SkOTTableGlyph::Iterator glyphDataIter(*glyfTable.fData, *locaTable.fData, l
ocaFormat); | 902 SkOTTableGlyph::Iterator glyphDataIter(*glyfTable.fData, *locaTable.fData, l
ocaFormat); |
945 glyphDataIter.advance(fFBoundingBoxesGlyphOffset); | 903 glyphDataIter.advance(fFBoundingBoxesGlyphOffset); |
946 for (uint16_t boundingBoxesIndex = 0; boundingBoxesIndex < entries; ++boundi
ngBoxesIndex) { | 904 for (uint16_t boundingBoxesIndex = 0; boundingBoxesIndex < entries; ++boundi
ngBoxesIndex) { |
947 const SkOTTableGlyphData* glyphData = glyphDataIter.next(); | 905 const SkOTTableGlyphData* glyphData = glyphDataIter.next(); |
948 GlyphRect& rect = fFBoundingBoxes[boundingBoxesIndex]; | 906 GlyphRect& rect = fFBoundingBoxes[boundingBoxesIndex]; |
949 rect.fMinX = SkEndian_SwapBE16(glyphData->xMin); | 907 rect.fMinX = SkEndian_SwapBE16(glyphData->xMin); |
950 rect.fMinY = SkEndian_SwapBE16(glyphData->yMin); | 908 rect.fMinY = SkEndian_SwapBE16(glyphData->yMin); |
951 rect.fMaxX = SkEndian_SwapBE16(glyphData->xMax); | 909 rect.fMaxX = SkEndian_SwapBE16(glyphData->xMax); |
952 rect.fMaxY = SkEndian_SwapBE16(glyphData->yMax); | 910 rect.fMaxY = SkEndian_SwapBE16(glyphData->yMax); |
953 } | 911 } |
954 fFBoundingBoxesMatrix = fMatrix; | |
955 flip(&fFBoundingBoxesMatrix); | |
956 SkScalar fontScale = getFontScale(fCGFont); | |
957 fFBoundingBoxesMatrix.preScale(fontScale, fontScale); | |
958 return true; | 912 return true; |
959 } | 913 } |
960 | 914 |
961 unsigned SkScalerContext_Mac::generateGlyphCount(void) { | 915 unsigned SkScalerContext_Mac::generateGlyphCount(void) { |
962 return fGlyphCount; | 916 return fGlyphCount; |
963 } | 917 } |
964 | 918 |
965 uint16_t SkScalerContext_Mac::generateCharToGlyph(SkUnichar uni) { | 919 uint16_t SkScalerContext_Mac::generateCharToGlyph(SkUnichar uni) { |
966 CGGlyph cgGlyph; | 920 CGGlyph cgGlyph; |
967 UniChar theChar; | 921 UniChar theChar; |
(...skipping 10 matching lines...) Expand all Loading... |
978 } | 932 } |
979 | 933 |
980 return cgGlyph; | 934 return cgGlyph; |
981 } | 935 } |
982 | 936 |
983 void SkScalerContext_Mac::generateAdvance(SkGlyph* glyph) { | 937 void SkScalerContext_Mac::generateAdvance(SkGlyph* glyph) { |
984 this->generateMetrics(glyph); | 938 this->generateMetrics(glyph); |
985 } | 939 } |
986 | 940 |
987 void SkScalerContext_Mac::generateMetrics(SkGlyph* glyph) { | 941 void SkScalerContext_Mac::generateMetrics(SkGlyph* glyph) { |
988 CGSize advance; | 942 const CGGlyph cgGlyph = (CGGlyph) glyph->getGlyphID(fBaseGlyphCount); |
989 CGRect bounds; | 943 glyph->zeroMetrics(); |
990 CGGlyph cgGlyph; | 944 |
991 | 945 bool wantedVerticalBoundsButGotHorizontalBounds = false; |
992 // Get the state we need | 946 |
993 cgGlyph = (CGGlyph) glyph->getGlyphID(fBaseGlyphCount); | 947 // The following block produces gcAdvance and cgBounds in CG units (pixels,
y up). |
994 | 948 CGSize cgAdvance; |
| 949 CGRect cgBounds; |
995 if (fVertical) { | 950 if (fVertical) { |
996 if (!isSnowLeopard()) { | 951 if (!isSnowLeopard()) { |
997 // Lion and Leopard respect the vertical font metrics. | 952 // Lion and Mountain Lion respect requests for vertical bounds. |
998 CTFontGetBoundingRectsForGlyphs(fCTVerticalFont, kCTFontVerticalOrie
ntation, | 953 CTFontGetBoundingRectsForGlyphs(fCTVerticalFont, kCTFontVerticalOrie
ntation, |
999 &cgGlyph, &bounds, 1); | 954 &cgGlyph, &cgBounds, 1); |
1000 } else { | 955 } else { |
1001 // Snow Leopard and earlier respect the vertical font metrics for | 956 // Snow Leopard does not respect requests for vertical bounds. |
1002 // advances, but not bounds, so use the default box and adjust it be
low. | 957 // Request the horizontal bounds and adjust it below. |
1003 CTFontGetBoundingRectsForGlyphs(fCTFont, kCTFontDefaultOrientation, | 958 CTFontGetBoundingRectsForGlyphs(fCTFont, kCTFontHorizontalOrientatio
n, |
1004 &cgGlyph, &bounds, 1); | 959 &cgGlyph, &cgBounds, 1); |
| 960 wantedVerticalBoundsButGotHorizontalBounds = true; |
1005 } | 961 } |
| 962 // All versions respect requests for vertical advances. |
1006 CTFontGetAdvancesForGlyphs(fCTVerticalFont, kCTFontVerticalOrientation, | 963 CTFontGetAdvancesForGlyphs(fCTVerticalFont, kCTFontVerticalOrientation, |
1007 &cgGlyph, &advance, 1); | 964 &cgGlyph, &cgAdvance, 1); |
1008 } else { | 965 } else { |
1009 CTFontGetBoundingRectsForGlyphs(fCTFont, kCTFontDefaultOrientation, | 966 CTFontGetBoundingRectsForGlyphs(fCTFont, kCTFontHorizontalOrientation, |
1010 &cgGlyph, &bounds, 1); | 967 &cgGlyph, &cgBounds, 1); |
1011 CTFontGetAdvancesForGlyphs(fCTFont, kCTFontDefaultOrientation, | 968 CTFontGetAdvancesForGlyphs(fCTFont, kCTFontHorizontalOrientation, |
1012 &cgGlyph, &advance, 1); | 969 &cgGlyph, &cgAdvance, 1); |
1013 } | 970 } |
| 971 glyph->fAdvanceX = SkFloatToFixed_Check(cgAdvance.width); |
| 972 glyph->fAdvanceY = -SkFloatToFixed_Check(cgAdvance.height); |
| 973 |
| 974 // Now work around all the bounds bugs. |
1014 | 975 |
1015 // BUG? | 976 // BUG? |
1016 // 0x200B (zero-advance space) seems to return a huge (garbage) bounds, when | 977 // 0x200B (zero-advance space) seems to return a huge (garbage) bounds, when |
1017 // it should be empty. So, if we see a zero-advance, we check if it has an | 978 // it should be empty. So, if we see a zero-advance, we check if it has an |
1018 // empty path or not, and if so, we jam the bounds to 0. Hopefully a zero-ad
vance | 979 // empty path or not, and if so, we jam the bounds to 0. Hopefully a zero-ad
vance |
1019 // is rare, so we won't incur a big performance cost for this extra check. | 980 // is rare, so we won't incur a big performance cost for this extra check. |
1020 if (0 == advance.width && 0 == advance.height) { | 981 if (0 == cgAdvance.width && 0 == cgAdvance.height) { |
1021 AutoCFRelease<CGPathRef> path(CTFontCreatePathForGlyph(fCTFont, cgGlyph,
NULL)); | 982 AutoCFRelease<CGPathRef> path(CTFontCreatePathForGlyph(fCTFont, cgGlyph,
NULL)); |
1022 if (NULL == path || CGPathIsEmpty(path)) { | 983 if (NULL == path || CGPathIsEmpty(path)) { |
1023 bounds = CGRectMake(0, 0, 0, 0); | 984 return; |
1024 } | 985 } |
1025 } | 986 } |
1026 | 987 |
1027 glyph->zeroMetrics(); | 988 if (CGRectIsEmpty_inline(cgBounds)) { |
1028 glyph->fAdvanceX = SkFloatToFixed_Check(advance.width); | |
1029 glyph->fAdvanceY = -SkFloatToFixed_Check(advance.height); | |
1030 | |
1031 if (CGRectIsEmpty_inline(bounds)) { | |
1032 return; | 989 return; |
1033 } | 990 } |
1034 | 991 |
1035 if (isLeopard() && !fVertical) { | 992 // Convert bounds to SkGlyph units (pixels, y down). |
1036 // Leopard does not consider the matrix skew in its bounds. | 993 SkRect skBounds = SkRect::MakeXYWH(cgBounds.origin.x, -cgBounds.origin.y - c
gBounds.size.height, |
1037 // Run the bounding rectangle through the skew matrix to determine | 994 cgBounds.size.width, cgBounds.size.height
); |
1038 // the true bounds. However, this doesn't work if the font is vertical. | |
1039 // FIXME (Leopard): If the font has synthetic italic (e.g., matrix skew) | |
1040 // and the font is vertical, the bounds need to be recomputed. | |
1041 SkRect glyphBounds = SkRect::MakeXYWH( | |
1042 bounds.origin.x, bounds.origin.y, | |
1043 bounds.size.width, bounds.size.height); | |
1044 fUnitMatrix.mapRect(&glyphBounds); | |
1045 bounds.origin.x = glyphBounds.fLeft; | |
1046 bounds.origin.y = glyphBounds.fTop; | |
1047 bounds.size.width = glyphBounds.width(); | |
1048 bounds.size.height = glyphBounds.height(); | |
1049 } | |
1050 // Adjust the bounds | |
1051 // | |
1052 // CTFontGetBoundingRectsForGlyphs ignores the font transform, so we need | |
1053 // to transform the bounding box ourselves. | |
1054 // | |
1055 // The bounds are also expanded by 1 pixel, to give CG room for anti-aliasin
g. | |
1056 CGRectInset_inline(&bounds, -1, -1); | |
1057 | |
1058 // Get the metrics | |
1059 bool lionAdjustedMetrics = false; | |
1060 if (isLion() || isMountainLion()) { | 995 if (isLion() || isMountainLion()) { |
1061 if (cgGlyph < fGlyphCount && cgGlyph >= getFBoundingBoxesGlyphOffset() &
& generateBBoxes()){ | 996 if (cgGlyph < fGlyphCount && cgGlyph >= getFBoundingBoxesGlyphOffset() &
& generateBBoxes()){ |
1062 lionAdjustedMetrics = true; | |
1063 SkRect adjust; | |
1064 const GlyphRect& gRect = fFBoundingBoxes[cgGlyph - fFBoundingBoxesGl
yphOffset]; | 997 const GlyphRect& gRect = fFBoundingBoxes[cgGlyph - fFBoundingBoxesGl
yphOffset]; |
1065 adjust.set(gRect.fMinX, gRect.fMinY, gRect.fMaxX, gRect.fMaxY); | 998 skBounds = SkRect::MakeLTRB(gRect.fMinX, gRect.fMinY, gRect.fMaxX, g
Rect.fMaxY); |
1066 fFBoundingBoxesMatrix.mapRect(&adjust); | 999 // From FUnits (em space, y up) to SkGlyph units (pixels, y down). |
1067 bounds.origin.x = SkScalarToFloat(adjust.fLeft) - 1; | 1000 fFUnitMatrix.mapRect(&skBounds); |
1068 bounds.origin.y = SkScalarToFloat(adjust.fTop) - 1; | 1001 wantedVerticalBoundsButGotHorizontalBounds = fVertical; |
1069 } | 1002 } |
1070 // Lion returns fractions in the bounds | |
1071 glyph->fWidth = SkToU16(sk_float_ceil2int(bounds.size.width)); | |
1072 glyph->fHeight = SkToU16(sk_float_ceil2int(bounds.size.height)); | |
1073 } else { | |
1074 glyph->fWidth = SkToU16(sk_float_round2int(bounds.size.width)); | |
1075 glyph->fHeight = SkToU16(sk_float_round2int(bounds.size.height)); | |
1076 } | 1003 } |
1077 glyph->fTop = SkToS16(-sk_float_round2int(CGRectGetMaxY_inline(bounds))); | 1004 if (wantedVerticalBoundsButGotHorizontalBounds) { |
1078 glyph->fLeft = SkToS16(sk_float_round2int(CGRectGetMinX_inline(bounds))); | 1005 // Snow Leopard does not respect requests for vertical bounds. |
1079 SkIPoint offset; | 1006 // Our own fFBoundingBoxes are for horizontal bounds. |
1080 if (fVertical && (isSnowLeopard() || lionAdjustedMetrics)) { | 1007 // Convert these horizontal bounds into vertical bounds. |
1081 // SnowLeopard doesn't respect vertical metrics, so compute them manuall
y. | 1008 SkPoint offset; |
1082 // Also compute them for Lion when the metrics were computed by hand. | |
1083 getVerticalOffset(cgGlyph, &offset); | 1009 getVerticalOffset(cgGlyph, &offset); |
1084 glyph->fLeft += offset.fX; | 1010 skBounds.offset(offset); |
1085 glyph->fTop += offset.fY; | |
1086 } | 1011 } |
| 1012 SkIRect skIBounds; |
| 1013 skBounds.roundOut(&skIBounds); |
| 1014 // Expand the bounds by 1 pixel, to give CG room for anti-aliasing. |
| 1015 // Note that we currently don't know how much room to give subpixel smoothed
glyphs |
| 1016 // as CG dilates the outlines by some amount. |
| 1017 skIBounds.outset(1, 1); |
| 1018 glyph->fTop = SkToS16(skIBounds.fTop); |
| 1019 glyph->fLeft = SkToS16(skIBounds.fLeft); |
| 1020 glyph->fWidth = SkToU16(skIBounds.width()); |
| 1021 glyph->fHeight = SkToU16(skIBounds.height()); |
| 1022 |
1087 #ifdef HACK_COLORGLYPHS | 1023 #ifdef HACK_COLORGLYPHS |
1088 glyph->fMaskFormat = SkMask::kARGB32_Format; | 1024 glyph->fMaskFormat = SkMask::kARGB32_Format; |
1089 #endif | 1025 #endif |
1090 } | 1026 } |
1091 | 1027 |
1092 #include "SkColorPriv.h" | 1028 #include "SkColorPriv.h" |
1093 | 1029 |
1094 static void build_power_table(uint8_t table[], float ee) { | 1030 static void build_power_table(uint8_t table[], float ee) { |
1095 for (int i = 0; i < 256; i++) { | 1031 for (int i = 0; i < 256; i++) { |
1096 float x = i / 255.f; | 1032 float x = i / 255.f; |
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1364 } | 1300 } |
1365 | 1301 |
1366 CGGlyph cgGlyph = (CGGlyph)glyph.getGlyphID(fBaseGlyphCount); | 1302 CGGlyph cgGlyph = (CGGlyph)glyph.getGlyphID(fBaseGlyphCount); |
1367 AutoCFRelease<CGPathRef> cgPath(CTFontCreatePathForGlyph(font, cgGlyph, NULL
)); | 1303 AutoCFRelease<CGPathRef> cgPath(CTFontCreatePathForGlyph(font, cgGlyph, NULL
)); |
1368 | 1304 |
1369 path->reset(); | 1305 path->reset(); |
1370 if (cgPath != NULL) { | 1306 if (cgPath != NULL) { |
1371 CGPathApply(cgPath, path, SkScalerContext_Mac::CTPathElement); | 1307 CGPathApply(cgPath, path, SkScalerContext_Mac::CTPathElement); |
1372 } | 1308 } |
1373 | 1309 |
1374 if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) { | 1310 if (fDoSubPosition) { |
1375 SkMatrix m; | 1311 SkMatrix m; |
1376 m.setScale(SkScalarInvert(scaleX), SkScalarInvert(scaleY)); | 1312 m.setScale(SkScalarInvert(scaleX), SkScalarInvert(scaleY)); |
1377 path->transform(m); | 1313 path->transform(m); |
1378 // balance the call to CTFontCreateCopyWithAttributes | 1314 // balance the call to CTFontCreateCopyWithAttributes |
1379 CFSafeRelease(font); | 1315 CFSafeRelease(font); |
1380 } | 1316 } |
1381 if (fRec.fFlags & SkScalerContext::kVertical_Flag) { | 1317 if (fVertical) { |
1382 SkIPoint offset; | 1318 SkPoint offset; |
1383 getVerticalOffset(cgGlyph, &offset); | 1319 getVerticalOffset(cgGlyph, &offset); |
1384 path->offset(SkIntToScalar(offset.fX), SkIntToScalar(offset.fY)); | 1320 path->offset(offset.fX, offset.fY); |
1385 } | 1321 } |
1386 } | 1322 } |
1387 | 1323 |
1388 void SkScalerContext_Mac::generateFontMetrics(SkPaint::FontMetrics* mx, | 1324 void SkScalerContext_Mac::generateFontMetrics(SkPaint::FontMetrics* mx, |
1389 SkPaint::FontMetrics* my) { | 1325 SkPaint::FontMetrics* my) { |
1390 CGRect theBounds = CTFontGetBoundingBox(fCTFont); | 1326 CGRect theBounds = CTFontGetBoundingBox(fCTFont); |
1391 | 1327 |
1392 SkPaint::FontMetrics theMetrics; | 1328 SkPaint::FontMetrics theMetrics; |
1393 theMetrics.fTop = CGToScalar(-CGRectGetMaxY_inline(theBounds)); | 1329 theMetrics.fTop = CGToScalar(-CGRectGetMaxY_inline(theBounds)); |
1394 theMetrics.fAscent = CGToScalar(-CTFontGetAscent(fCTFont)); | 1330 theMetrics.fAscent = CGToScalar(-CTFontGetAscent(fCTFont)); |
(...skipping 826 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2221 return NULL; | 2157 return NULL; |
2222 } | 2158 } |
2223 return create_from_dataProvider(pr); | 2159 return create_from_dataProvider(pr); |
2224 } | 2160 } |
2225 }; | 2161 }; |
2226 | 2162 |
2227 SkFontMgr* SkFontMgr::Factory() { | 2163 SkFontMgr* SkFontMgr::Factory() { |
2228 return SkNEW(SkFontMgr_Mac); | 2164 return SkNEW(SkFontMgr_Mac); |
2229 } | 2165 } |
2230 #endif | 2166 #endif |
OLD | NEW |