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

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

Issue 15064003: Fix vertical text scaling on Mac. (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Clean-up Created 7 years, 7 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 | « samplecode/SampleApp.cpp ('k') | 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 282 matching lines...) Expand 10 before | Expand all | Expand 10 after
293 SkScalar sx = SK_Scalar1, 293 SkScalar sx = SK_Scalar1,
294 SkScalar sy = SK_Scalar1) { 294 SkScalar sy = SK_Scalar1) {
295 return CGAffineTransformMake( ScalarToCG(matrix[SkMatrix::kMScaleX] * sx), 295 return CGAffineTransformMake( ScalarToCG(matrix[SkMatrix::kMScaleX] * sx),
296 -ScalarToCG(matrix[SkMatrix::kMSkewY] * sy), 296 -ScalarToCG(matrix[SkMatrix::kMSkewY] * sy),
297 -ScalarToCG(matrix[SkMatrix::kMSkewX] * sx), 297 -ScalarToCG(matrix[SkMatrix::kMSkewX] * sx),
298 ScalarToCG(matrix[SkMatrix::kMScaleY] * sy), 298 ScalarToCG(matrix[SkMatrix::kMScaleY] * sy),
299 ScalarToCG(matrix[SkMatrix::kMTransX] * sx), 299 ScalarToCG(matrix[SkMatrix::kMTransX] * sx),
300 ScalarToCG(matrix[SkMatrix::kMTransY] * sy)); 300 ScalarToCG(matrix[SkMatrix::kMTransY] * sy));
301 } 301 }
302 302
303 static SkScalar getFontScale(CGFontRef cgFont) { 303 static SkScalar getFontScale(CGFontRef cgFont) {
bungeman-skia 2013/05/10 17:08:03 This is an ambiguous name, emPerFUnit would be mor
304 int unitsPerEm = CGFontGetUnitsPerEm(cgFont); 304 int unitsPerEm = CGFontGetUnitsPerEm(cgFont);
305 return SkScalarInvert(SkIntToScalar(unitsPerEm)); 305 return SkScalarInvert(SkIntToScalar(unitsPerEm));
306 } 306 }
307 307
308 /////////////////////////////////////////////////////////////////////////////// 308 ///////////////////////////////////////////////////////////////////////////////
309 309
310 #define BITMAP_INFO_RGB (kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host) 310 #define BITMAP_INFO_RGB (kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host)
311 #define BITMAP_INFO_GRAY (kCGImageAlphaNone) 311 #define BITMAP_INFO_GRAY (kCGImageAlphaNone)
312 312
313 /** 313 /**
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after
641 if (face) { 641 if (face) {
642 SkTypefaceCache::Add(face, style); 642 SkTypefaceCache::Add(face, style);
643 } else { 643 } else {
644 face = GetDefaultFace(); 644 face = GetDefaultFace();
645 face->ref(); 645 face->ref();
646 } 646 }
647 } 647 }
648 return face; 648 return face;
649 } 649 }
650 650
651 static void flip(SkMatrix* matrix) {
652 matrix->setSkewX(-matrix->getSkewX());
653 matrix->setSkewY(-matrix->getSkewY());
654 }
655
656 /////////////////////////////////////////////////////////////////////////////// 651 ///////////////////////////////////////////////////////////////////////////////
657 652
658 struct GlyphRect { 653 struct GlyphRect {
659 int16_t fMinX; 654 int16_t fMinX;
660 int16_t fMinY; 655 int16_t fMinY;
661 int16_t fMaxX; 656 int16_t fMaxX;
662 int16_t fMaxY; 657 int16_t fMaxY;
663 }; 658 };
664 659
665 class SkScalerContext_Mac : public SkScalerContext { 660 class SkScalerContext_Mac : public SkScalerContext {
(...skipping 11 matching lines...) Expand all
677 void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE; 672 void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE;
678 void generateFontMetrics(SkPaint::FontMetrics* mX, SkPaint::FontMetrics* mY) SK_OVERRIDE; 673 void generateFontMetrics(SkPaint::FontMetrics* mX, SkPaint::FontMetrics* mY) SK_OVERRIDE;
679 674
680 private: 675 private:
681 static void CTPathElement(void *info, const CGPathElement *element); 676 static void CTPathElement(void *info, const CGPathElement *element);
682 uint16_t getFBoundingBoxesGlyphOffset(); 677 uint16_t getFBoundingBoxesGlyphOffset();
683 void getVerticalOffset(CGGlyph glyphID, SkIPoint* offset) const; 678 void getVerticalOffset(CGGlyph glyphID, SkIPoint* offset) const;
684 bool generateBBoxes(); 679 bool generateBBoxes();
685 680
686 CGAffineTransform fTransform; 681 CGAffineTransform fTransform;
687 SkMatrix fUnitMatrix; // without font size
688 SkMatrix fVerticalMatrix; // unit rotated
689 SkMatrix fMatrix; // with font size 682 SkMatrix fMatrix; // with font size
690 SkMatrix fFBoundingBoxesMatrix; // lion-specific fix 683 SkMatrix fFBoundingBoxesMatrix; // lion-specific fix
691 Offscreen fOffscreen; 684 Offscreen fOffscreen;
692 AutoCFRelease<CTFontRef> fCTFont; 685 AutoCFRelease<CTFontRef> fCTFont;
693 AutoCFRelease<CTFontRef> fCTVerticalFont; // for vertical advance
694 AutoCFRelease<CGFontRef> fCGFont; 686 AutoCFRelease<CGFontRef> fCGFont;
695 GlyphRect* fFBoundingBoxes; 687 GlyphRect* fFBoundingBoxes;
696 uint16_t fFBoundingBoxesGlyphOffset; 688 uint16_t fFBoundingBoxesGlyphOffset;
697 uint16_t fGlyphCount; 689 uint16_t fGlyphCount;
698 bool fGeneratedFBoundingBoxes; 690 bool fGeneratedFBoundingBoxes;
699 bool fDoSubPosition; 691 const bool fDoSubPosition;
700 bool fVertical; 692 const bool fVertical;
701 693
702 friend class Offscreen; 694 friend class Offscreen;
703 695
704 typedef SkScalerContext INHERITED; 696 typedef SkScalerContext INHERITED;
705 }; 697 };
706 698
707 SkScalerContext_Mac::SkScalerContext_Mac(SkTypeface_Mac* typeface, 699 SkScalerContext_Mac::SkScalerContext_Mac(SkTypeface_Mac* typeface,
708 const SkDescriptor* desc) 700 const SkDescriptor* desc)
709 : INHERITED(typeface, desc) 701 : INHERITED(typeface, desc)
710 , fFBoundingBoxes(NULL) 702 , fFBoundingBoxes(NULL)
711 , fFBoundingBoxesGlyphOffset(0) 703 , fFBoundingBoxesGlyphOffset(0)
712 , fGeneratedFBoundingBoxes(false) 704 , fGeneratedFBoundingBoxes(false)
705 , fDoSubPosition(SkToBool(fRec.fFlags & kSubpixelPositioning_Flag))
706 , fVertical(SkToBool(fRec.fFlags & kVertical_Flag))
707
713 { 708 {
714 CTFontRef ctFont = typeface->fFontRef.get(); 709 CTFontRef ctFont = typeface->fFontRef.get();
715 CFIndex numGlyphs = CTFontGetGlyphCount(ctFont); 710 CFIndex numGlyphs = CTFontGetGlyphCount(ctFont);
716 711 SkASSERT(numGlyphs >= 1 && numGlyphs <= 0xFFFF);
717 // Get the state we need 712 fGlyphCount = SkToU16(numGlyphs);
713
718 fRec.getSingleMatrix(&fMatrix); 714 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);
726
727 fTransform = MatrixToCGAffineTransform(fMatrix); 715 fTransform = MatrixToCGAffineTransform(fMatrix);
728 716
729 CGAffineTransform transform;
730 CGFloat unitFontSize;
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; 717 AutoCFRelease<CTFontDescriptorRef> ctFontDesc;
744 if (fVertical) { 718 if (fVertical) {
745 AutoCFRelease<CFMutableDictionaryRef> cfAttributes(CFDictionaryCreateMut able( 719 AutoCFRelease<CFMutableDictionaryRef> cfAttributes(CFDictionaryCreateMut able(
746 kCFAllocatorDefault, 0, 720 kCFAllocatorDefault, 0,
747 &kCFTypeDictionaryKeyCallBacks, 721 &kCFTypeDictionaryKeyCallBacks,
748 &kCFTypeDictionaryValueCallBacks)); 722 &kCFTypeDictionaryValueCallBacks));
749 if (cfAttributes) { 723 if (cfAttributes) {
750 CTFontOrientation ctOrientation = kCTFontVerticalOrientation; 724 CTFontOrientation ctOrientation = kCTFontVerticalOrientation;
751 AutoCFRelease<CFNumberRef> cfVertical(CFNumberCreate( 725 AutoCFRelease<CFNumberRef> cfVertical(CFNumberCreate(
752 kCFAllocatorDefault, kCFNumberSInt32Type, &ctOrientation)); 726 kCFAllocatorDefault, kCFNumberSInt32Type, &ctOrientation));
753 CFDictionaryAddValue(cfAttributes, kCTFontOrientationAttribute, cfVe rtical); 727 CFDictionaryAddValue(cfAttributes, kCTFontOrientationAttribute, cfVe rtical);
754 ctFontDesc = CTFontDescriptorCreateWithAttributes(cfAttributes); 728 ctFontDesc = CTFontDescriptorCreateWithAttributes(cfAttributes);
755 } 729 }
756 } 730 }
757 fCTFont = CTFontCreateCopyWithAttributes(ctFont, unitFontSize, &transform, c tFontDesc); 731 // Since our matrix includes everything, we pass 1 for size.
732 fCTFont = CTFontCreateCopyWithAttributes(ctFont, 1.f, &fTransform, ctFontDes c);
758 fCGFont = CTFontCopyGraphicsFont(fCTFont, NULL); 733 fCGFont = CTFontCopyGraphicsFont(fCTFont, NULL);
759 if (fVertical) {
760 CGAffineTransform rotateLeft = CGAffineTransformMake(0, -1, 1, 0, 0, 0);
761 transform = CGAffineTransformConcat(rotateLeft, transform);
762 fCTVerticalFont = CTFontCreateCopyWithAttributes(ctFont, unitFontSize, & 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 }
772 fGlyphCount = SkToU16(numGlyphs);
773 fDoSubPosition = SkToBool(fRec.fFlags & kSubpixelPositioning_Flag);
774 } 734 }
775 735
776 SkScalerContext_Mac::~SkScalerContext_Mac() { 736 SkScalerContext_Mac::~SkScalerContext_Mac() {
777 delete[] fFBoundingBoxes; 737 delete[] fFBoundingBoxes;
778 } 738 }
779 739
780 CGRGBPixel* Offscreen::getCG(const SkScalerContext_Mac& context, const SkGlyph& glyph, 740 CGRGBPixel* Offscreen::getCG(const SkScalerContext_Mac& context, const SkGlyph& glyph,
781 CGGlyph glyphID, size_t* rowBytesPtr, 741 CGGlyph glyphID, size_t* rowBytesPtr,
782 bool generateA8FromLCD) { 742 bool generateA8FromLCD) {
783 if (!fRGBSpace) { 743 if (!fRGBSpace) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
817 rowBytes, fRGBSpace, BITMAP_INFO_RGB); 777 rowBytes, fRGBSpace, BITMAP_INFO_RGB);
818 778
819 // skia handles quantization itself, so we disable this for cg to get 779 // skia handles quantization itself, so we disable this for cg to get
820 // full fractional data from them. 780 // full fractional data from them.
821 CGContextSetAllowsFontSubpixelQuantization(fCG, false); 781 CGContextSetAllowsFontSubpixelQuantization(fCG, false);
822 CGContextSetShouldSubpixelQuantizeFonts(fCG, false); 782 CGContextSetShouldSubpixelQuantizeFonts(fCG, false);
823 783
824 CGContextSetTextDrawingMode(fCG, kCGTextFill); 784 CGContextSetTextDrawingMode(fCG, kCGTextFill);
825 CGContextSetFont(fCG, context.fCGFont); 785 CGContextSetFont(fCG, context.fCGFont);
826 CGContextSetFontSize(fCG, 1); 786 CGContextSetFontSize(fCG, 1);
827 CGContextSetTextMatrix(fCG, context.fTransform); 787 CGContextSetTextMatrix(fCG, context.fTransform);
bungeman-skia 2013/05/10 17:08:03 Can this just be the transform from the CTFont? If
828 788
829 CGContextSetAllowsFontSubpixelPositioning(fCG, context.fDoSubPosition); 789 CGContextSetAllowsFontSubpixelPositioning(fCG, context.fDoSubPosition);
830 CGContextSetShouldSubpixelPositionFonts(fCG, context.fDoSubPosition); 790 CGContextSetShouldSubpixelPositionFonts(fCG, context.fDoSubPosition);
831 791
832 // Draw white on black to create mask. 792 // Draw white on black to create mask.
833 // TODO: Draw black on white and invert, CG has a special case codepath. 793 // TODO: Draw black on white and invert, CG has a special case codepath.
834 CGContextSetGrayFillColor(fCG, 1.0f, 1.0f); 794 CGContextSetGrayFillColor(fCG, 1.0f, 1.0f);
835 795
836 // force our checks below to happen 796 // force our checks below to happen
837 fDoAA = !doAA; 797 fDoAA = !doAA;
(...skipping 15 matching lines...) Expand all
853 813
854 // erase to black 814 // erase to black
855 sk_memset_rect32(image, 0, glyph.fWidth, glyph.fHeight, rowBytes); 815 sk_memset_rect32(image, 0, glyph.fWidth, glyph.fHeight, rowBytes);
856 816
857 float subX = 0; 817 float subX = 0;
858 float subY = 0; 818 float subY = 0;
859 if (context.fDoSubPosition) { 819 if (context.fDoSubPosition) {
860 subX = SkFixedToFloat(glyph.getSubXFixed()); 820 subX = SkFixedToFloat(glyph.getSubXFixed());
861 subY = SkFixedToFloat(glyph.getSubYFixed()); 821 subY = SkFixedToFloat(glyph.getSubYFixed());
862 } 822 }
823
824 // CGContextShowGlyphsAtPoint always draws using the horizontal baseline ori gin.
825 // Get the offset from the vertical origin to the horizontal origin.
863 if (context.fVertical) { 826 if (context.fVertical) {
864 SkIPoint offset; 827 SkIPoint offset;
865 context.getVerticalOffset(glyphID, &offset); 828 context.getVerticalOffset(glyphID, &offset);
866 subX += offset.fX; 829 subX += offset.fX;
867 subY += offset.fY; 830 subY += offset.fY;
868 } 831 }
832
869 CGContextShowGlyphsAtPoint(fCG, -glyph.fLeft + subX, 833 CGContextShowGlyphsAtPoint(fCG, -glyph.fLeft + subX,
870 glyph.fTop + glyph.fHeight - subY, 834 glyph.fTop + glyph.fHeight - subY,
871 &glyphID, 1); 835 &glyphID, 1);
872 836
873 SkASSERT(rowBytesPtr); 837 SkASSERT(rowBytesPtr);
874 *rowBytesPtr = rowBytes; 838 *rowBytesPtr = rowBytes;
875 return image; 839 return image;
876 } 840 }
877 841
878 void SkScalerContext_Mac::getVerticalOffset(CGGlyph glyphID, SkIPoint* offset) c onst { 842 void SkScalerContext_Mac::getVerticalOffset(CGGlyph glyphID, SkIPoint* offset) c onst {
879 CGSize vertOffset; 843 CGSize vertOffset;
880 CTFontGetVerticalTranslationsForGlyphs(fCTVerticalFont, &glyphID, &vertOffse t, 1); 844 CTFontGetVerticalTranslationsForGlyphs(fCTFont, &glyphID, &vertOffset, 1);
881 const SkPoint trans = {CGToScalar(vertOffset.width), 845
882 CGToScalar(vertOffset.height)}; 846 // SnowLeopard returns vertOffset in completely un-transformed em units.
883 SkPoint floatOffset; 847 // Lion and Leopard return vertOffset in transformed font units.
884 fVerticalMatrix.mapPoints(&floatOffset, &trans, 1); 848 if (isSnowLeopard()) {
885 if (!isSnowLeopard()) { 849 CGFloat emPerUnit = 1.0f / CGFontGetUnitsPerEm(fCGFont);
886 // SnowLeopard fails to apply the font's matrix to the vertical metrics, 850 CGAffineTransform t = CGAffineTransformConcat(fTransform, CGAffineTransf ormMakeScale(emPerUnit, emPerUnit));
887 // but Lion and Leopard do. The unit matrix describes the font's matrix at 851 vertOffset = CGSizeApplyAffineTransform(vertOffset, t);
888 // point size 1. There may be some way to avoid mapping here by setting up
889 // fVerticalMatrix differently, but this works for now.
890 fUnitMatrix.mapPoints(&floatOffset, 1);
891 } 852 }
892 offset->fX = SkScalarRound(floatOffset.fX); 853
893 offset->fY = SkScalarRound(floatOffset.fY); 854 offset->fX = SkScalarRound(vertOffset.width);
855 offset->fY = SkScalarRound(-vertOffset.height);
894 } 856 }
895 857
896 uint16_t SkScalerContext_Mac::getFBoundingBoxesGlyphOffset() { 858 uint16_t SkScalerContext_Mac::getFBoundingBoxesGlyphOffset() {
897 if (fFBoundingBoxesGlyphOffset) { 859 if (fFBoundingBoxesGlyphOffset) {
898 return fFBoundingBoxesGlyphOffset; 860 return fFBoundingBoxesGlyphOffset;
899 } 861 }
900 fFBoundingBoxesGlyphOffset = fGlyphCount; // fallback for all fonts 862 fFBoundingBoxesGlyphOffset = fGlyphCount; // fallback for all fonts
901 AutoCGTable<SkOTTableHorizontalHeader> hheaTable(fCGFont); 863 AutoCGTable<SkOTTableHorizontalHeader> hheaTable(fCGFont);
902 if (hheaTable.fData) { 864 if (hheaTable.fData) {
903 fFBoundingBoxesGlyphOffset = SkEndian_SwapBE16(hheaTable->numberOfHMetri cs); 865 fFBoundingBoxesGlyphOffset = SkEndian_SwapBE16(hheaTable->numberOfHMetri cs);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
940 uint16_t entries = fGlyphCount - fFBoundingBoxesGlyphOffset; 902 uint16_t entries = fGlyphCount - fFBoundingBoxesGlyphOffset;
941 fFBoundingBoxes = new GlyphRect[entries]; 903 fFBoundingBoxes = new GlyphRect[entries];
942 904
943 SkOTTableHead::IndexToLocFormat locaFormat = headTable->indexToLocFormat; 905 SkOTTableHead::IndexToLocFormat locaFormat = headTable->indexToLocFormat;
944 SkOTTableGlyph::Iterator glyphDataIter(*glyfTable.fData, *locaTable.fData, l ocaFormat); 906 SkOTTableGlyph::Iterator glyphDataIter(*glyfTable.fData, *locaTable.fData, l ocaFormat);
945 glyphDataIter.advance(fFBoundingBoxesGlyphOffset); 907 glyphDataIter.advance(fFBoundingBoxesGlyphOffset);
946 for (uint16_t boundingBoxesIndex = 0; boundingBoxesIndex < entries; ++boundi ngBoxesIndex) { 908 for (uint16_t boundingBoxesIndex = 0; boundingBoxesIndex < entries; ++boundi ngBoxesIndex) {
947 const SkOTTableGlyphData* glyphData = glyphDataIter.next(); 909 const SkOTTableGlyphData* glyphData = glyphDataIter.next();
948 GlyphRect& rect = fFBoundingBoxes[boundingBoxesIndex]; 910 GlyphRect& rect = fFBoundingBoxes[boundingBoxesIndex];
949 rect.fMinX = SkEndian_SwapBE16(glyphData->xMin); 911 rect.fMinX = SkEndian_SwapBE16(glyphData->xMin);
950 rect.fMinY = SkEndian_SwapBE16(glyphData->yMin); 912 rect.fMinY = -SkEndian_SwapBE16(glyphData->yMin);
951 rect.fMaxX = SkEndian_SwapBE16(glyphData->xMax); 913 rect.fMaxX = SkEndian_SwapBE16(glyphData->xMax);
952 rect.fMaxY = SkEndian_SwapBE16(glyphData->yMax); 914 rect.fMaxY = -SkEndian_SwapBE16(glyphData->yMax);
953 } 915 }
954 fFBoundingBoxesMatrix = fMatrix; 916 fFBoundingBoxesMatrix = fMatrix;
955 flip(&fFBoundingBoxesMatrix);
956 SkScalar fontScale = getFontScale(fCGFont); 917 SkScalar fontScale = getFontScale(fCGFont);
957 fFBoundingBoxesMatrix.preScale(fontScale, fontScale); 918 fFBoundingBoxesMatrix.preScale(fontScale, fontScale);
bungeman-skia 2013/05/10 17:08:03 The matrix used in getVerticalOffset for SnowLeopa
958 return true; 919 return true;
959 } 920 }
960 921
961 unsigned SkScalerContext_Mac::generateGlyphCount(void) { 922 unsigned SkScalerContext_Mac::generateGlyphCount(void) {
962 return fGlyphCount; 923 return fGlyphCount;
963 } 924 }
964 925
965 uint16_t SkScalerContext_Mac::generateCharToGlyph(SkUnichar uni) { 926 uint16_t SkScalerContext_Mac::generateCharToGlyph(SkUnichar uni) {
966 CGGlyph cgGlyph; 927 CGGlyph cgGlyph;
967 UniChar theChar; 928 UniChar theChar;
(...skipping 12 matching lines...) Expand all
980 return cgGlyph; 941 return cgGlyph;
981 } 942 }
982 943
983 void SkScalerContext_Mac::generateAdvance(SkGlyph* glyph) { 944 void SkScalerContext_Mac::generateAdvance(SkGlyph* glyph) {
984 this->generateMetrics(glyph); 945 this->generateMetrics(glyph);
985 } 946 }
986 947
987 void SkScalerContext_Mac::generateMetrics(SkGlyph* glyph) { 948 void SkScalerContext_Mac::generateMetrics(SkGlyph* glyph) {
988 CGSize advance; 949 CGSize advance;
989 CGRect bounds; 950 CGRect bounds;
990 CGGlyph cgGlyph; 951 CGGlyph const cgGlyph = (CGGlyph) glyph->getGlyphID(fBaseGlyphCount);
991
992 // Get the state we need
993 cgGlyph = (CGGlyph) glyph->getGlyphID(fBaseGlyphCount);
994 952
995 if (fVertical) { 953 if (fVertical) {
996 if (!isSnowLeopard()) { 954 if (!isSnowLeopard()) {
997 // Lion and Leopard respect the vertical font metrics. 955 // Lion and Leopard respect the vertical font metrics.
998 CTFontGetBoundingRectsForGlyphs(fCTVerticalFont, kCTFontVerticalOrie ntation, 956 CTFontGetBoundingRectsForGlyphs(fCTFont, kCTFontVerticalOrientation,
999 &cgGlyph, &bounds, 1); 957 &cgGlyph, &bounds, 1);
958 SkTSwap(bounds.origin.x, bounds.origin.y);
959 SkTSwap(bounds.size.width, bounds.size.height);
1000 } else { 960 } else {
1001 // Snow Leopard and earlier respect the vertical font metrics for 961 // Snow Leopard and earlier respect the vertical font metrics for
1002 // advances, but not bounds, so use the default box and adjust it be low. 962 // advances, but not bounds, so use the default box and adjust it be low.
1003 CTFontGetBoundingRectsForGlyphs(fCTFont, kCTFontDefaultOrientation, 963 CTFontGetBoundingRectsForGlyphs(fCTFont, kCTFontDefaultOrientation,
1004 &cgGlyph, &bounds, 1); 964 &cgGlyph, &bounds, 1);
965 bounds.origin.y = -bounds.origin.y - bounds.size.height;
1005 } 966 }
1006 CTFontGetAdvancesForGlyphs(fCTVerticalFont, kCTFontVerticalOrientation, 967 CTFontGetAdvancesForGlyphs(fCTFont, kCTFontVerticalOrientation,
1007 &cgGlyph, &advance, 1); 968 &cgGlyph, &advance, 1);
969 SkTSwap(advance.height, advance.width);
1008 } else { 970 } else {
1009 CTFontGetBoundingRectsForGlyphs(fCTFont, kCTFontDefaultOrientation, 971 CTFontGetBoundingRectsForGlyphs(fCTFont, kCTFontDefaultOrientation,
1010 &cgGlyph, &bounds, 1); 972 &cgGlyph, &bounds, 1);
973 bounds.origin.y = -bounds.origin.y - bounds.size.height;
1011 CTFontGetAdvancesForGlyphs(fCTFont, kCTFontDefaultOrientation, 974 CTFontGetAdvancesForGlyphs(fCTFont, kCTFontDefaultOrientation,
1012 &cgGlyph, &advance, 1); 975 &cgGlyph, &advance, 1);
976 advance.height = -advance.height;
1013 } 977 }
1014 978
1015 // BUG? 979 // BUG?
1016 // 0x200B (zero-advance space) seems to return a huge (garbage) bounds, when 980 // 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 981 // 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 982 // 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. 983 // is rare, so we won't incur a big performance cost for this extra check.
1020 if (0 == advance.width && 0 == advance.height) { 984 if (0 == advance.width && 0 == advance.height) {
1021 AutoCFRelease<CGPathRef> path(CTFontCreatePathForGlyph(fCTFont, cgGlyph, NULL)); 985 AutoCFRelease<CGPathRef> path(CTFontCreatePathForGlyph(fCTFont, cgGlyph, NULL));
1022 if (NULL == path || CGPathIsEmpty(path)) { 986 if (NULL == path || CGPathIsEmpty(path)) {
1023 bounds = CGRectMake(0, 0, 0, 0); 987 bounds = CGRectMake(0, 0, 0, 0);
1024 } 988 }
1025 } 989 }
1026 990
1027 glyph->zeroMetrics(); 991 glyph->zeroMetrics();
1028 glyph->fAdvanceX = SkFloatToFixed_Check(advance.width); 992 glyph->fAdvanceX = SkFloatToFixed_Check(advance.width);
1029 glyph->fAdvanceY = -SkFloatToFixed_Check(advance.height); 993 glyph->fAdvanceY = SkFloatToFixed_Check(advance.height);
1030 994
1031 if (CGRectIsEmpty_inline(bounds)) { 995 if (CGRectIsEmpty_inline(bounds)) {
1032 return; 996 return;
1033 } 997 }
1034 998
1035 if (isLeopard() && !fVertical) { 999 // Expand the bounds by 1 pixel, to give CG room for anti-aliasing.
1036 // Leopard does not consider the matrix skew in its bounds.
1037 // Run the bounding rectangle through the skew matrix to determine
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); 1000 CGRectInset_inline(&bounds, -1, -1);
1057 1001
1058 // Get the metrics 1002 // Get the metrics
1059 bool lionAdjustedMetrics = false; 1003 bool lionAdjustedMetrics = false;
1060 if (isLion() || isMountainLion()) { 1004 if (isLion() || isMountainLion()) {
1061 if (cgGlyph < fGlyphCount && cgGlyph >= getFBoundingBoxesGlyphOffset() & & generateBBoxes()){ 1005 if (cgGlyph < fGlyphCount && cgGlyph >= getFBoundingBoxesGlyphOffset() & & generateBBoxes()){
1062 lionAdjustedMetrics = true; 1006 lionAdjustedMetrics = true;
1063 SkRect adjust; 1007 SkRect adjust;
1064 const GlyphRect& gRect = fFBoundingBoxes[cgGlyph - fFBoundingBoxesGl yphOffset]; 1008 const GlyphRect& gRect = fFBoundingBoxes[cgGlyph - fFBoundingBoxesGl yphOffset];
1065 adjust.set(gRect.fMinX, gRect.fMinY, gRect.fMaxX, gRect.fMaxY); 1009 adjust.set(gRect.fMinX, gRect.fMinY, gRect.fMaxX, gRect.fMaxY);
1066 fFBoundingBoxesMatrix.mapRect(&adjust); 1010 fFBoundingBoxesMatrix.mapRect(&adjust);
1067 bounds.origin.x = SkScalarToFloat(adjust.fLeft) - 1; 1011 bounds.origin.x = SkScalarToFloat(adjust.fLeft) - 1;
1068 bounds.origin.y = SkScalarToFloat(adjust.fTop) - 1; 1012 bounds.origin.y = SkScalarToFloat(adjust.fTop) - 1;
1069 } 1013 }
1070 // Lion returns fractions in the bounds 1014 // Lion returns fractions in the bounds
1071 glyph->fWidth = SkToU16(sk_float_ceil2int(bounds.size.width)); 1015 glyph->fWidth = SkToU16(sk_float_ceil2int(bounds.size.width));
1072 glyph->fHeight = SkToU16(sk_float_ceil2int(bounds.size.height)); 1016 glyph->fHeight = SkToU16(sk_float_ceil2int(bounds.size.height));
1073 } else { 1017 } else {
1074 glyph->fWidth = SkToU16(sk_float_round2int(bounds.size.width)); 1018 glyph->fWidth = SkToU16(sk_float_round2int(bounds.size.width));
1075 glyph->fHeight = SkToU16(sk_float_round2int(bounds.size.height)); 1019 glyph->fHeight = SkToU16(sk_float_round2int(bounds.size.height));
1076 } 1020 }
1077 glyph->fTop = SkToS16(-sk_float_round2int(CGRectGetMaxY_inline(bounds))); 1021 glyph->fTop = SkToS16(sk_float_round2int(bounds.origin.y));
1078 glyph->fLeft = SkToS16(sk_float_round2int(CGRectGetMinX_inline(bounds))); 1022 glyph->fLeft = SkToS16(sk_float_round2int(bounds.origin.x));
1079 SkIPoint offset;
1080 if (fVertical && (isSnowLeopard() || lionAdjustedMetrics)) { 1023 if (fVertical && (isSnowLeopard() || lionAdjustedMetrics)) {
1081 // SnowLeopard doesn't respect vertical metrics, so compute them manuall y. 1024 // SnowLeopard doesn't respect vertical metrics, so compute them manuall y.
1082 // Also compute them for Lion when the metrics were computed by hand. 1025 // Also compute them for Lion when the metrics were computed by hand.
1026 SkIPoint offset;
1083 getVerticalOffset(cgGlyph, &offset); 1027 getVerticalOffset(cgGlyph, &offset);
1084 glyph->fLeft += offset.fX; 1028 glyph->fLeft += offset.fX;
1085 glyph->fTop += offset.fY; 1029 glyph->fTop += offset.fY;
1086 } 1030 }
1087 #ifdef HACK_COLORGLYPHS 1031 #ifdef HACK_COLORGLYPHS
1088 glyph->fMaskFormat = SkMask::kARGB32_Format; 1032 glyph->fMaskFormat = SkMask::kARGB32_Format;
1089 #endif 1033 #endif
1090 } 1034 }
1091 1035
1092 #include "SkColorPriv.h" 1036 #include "SkColorPriv.h"
(...skipping 1128 matching lines...) Expand 10 before | Expand all | Expand 10 after
2221 return NULL; 2165 return NULL;
2222 } 2166 }
2223 return create_from_dataProvider(pr); 2167 return create_from_dataProvider(pr);
2224 } 2168 }
2225 }; 2169 };
2226 2170
2227 SkFontMgr* SkFontMgr::Factory() { 2171 SkFontMgr* SkFontMgr::Factory() {
2228 return SkNEW(SkFontMgr_Mac); 2172 return SkNEW(SkFontMgr_Mac);
2229 } 2173 }
2230 #endif 2174 #endif
OLDNEW
« no previous file with comments | « samplecode/SampleApp.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698