Chromium Code Reviews| 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 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |