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

Side by Side Diff: src/ports/SkFontHost_mac.cpp

Issue 17886002: Remove SK_IGNORE_MAC_TEXT_BOUNDS_FIX workaround. (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 1
2 /* 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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698