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 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 | 190 |
191 static int darwinVersion() { | 191 static int darwinVersion() { |
192 static int darwin_version = readVersion(); | 192 static int darwin_version = readVersion(); |
193 return darwin_version; | 193 return darwin_version; |
194 } | 194 } |
195 | 195 |
196 static bool isLeopard() { | 196 static bool isLeopard() { |
197 return darwinVersion() == 9; | 197 return darwinVersion() == 9; |
198 } | 198 } |
199 | 199 |
| 200 static bool isSnowLeopard() { |
| 201 return darwinVersion() == 10; |
| 202 } |
| 203 |
200 static bool isLion() { | 204 static bool isLion() { |
201 return darwinVersion() == 11; | 205 return darwinVersion() == 11; |
202 } | 206 } |
203 | 207 |
204 static bool isLCDFormat(unsigned format) { | 208 static bool isLCDFormat(unsigned format) { |
205 return SkMask::kLCD16_Format == format || SkMask::kLCD32_Format == format; | 209 return SkMask::kLCD16_Format == format || SkMask::kLCD32_Format == format; |
206 } | 210 } |
207 | 211 |
208 static CGFloat ScalarToCG(SkScalar scalar) { | 212 static CGFloat ScalarToCG(SkScalar scalar) { |
209 if (sizeof(CGFloat) == sizeof(float)) { | 213 if (sizeof(CGFloat) == sizeof(float)) { |
(...skipping 23 matching lines...) Expand all Loading... |
233 ScalarToCG(matrix[SkMatrix::kMTransY]) * sy); | 237 ScalarToCG(matrix[SkMatrix::kMTransY]) * sy); |
234 } | 238 } |
235 | 239 |
236 static void CGAffineTransformToMatrix(const CGAffineTransform& xform, SkMatrix*
matrix) { | 240 static void CGAffineTransformToMatrix(const CGAffineTransform& xform, SkMatrix*
matrix) { |
237 matrix->setAll( | 241 matrix->setAll( |
238 CGToScalar(xform.a), CGToScalar(xform.c), CGToScalar(xform.tx
), | 242 CGToScalar(xform.a), CGToScalar(xform.c), CGToScalar(xform.tx
), |
239 CGToScalar(xform.b), CGToScalar(xform.d), CGToScalar(xform.ty
), | 243 CGToScalar(xform.b), CGToScalar(xform.d), CGToScalar(xform.ty
), |
240 0, 0, SK_Scalar1); | 244 0, 0, SK_Scalar1); |
241 } | 245 } |
242 | 246 |
| 247 static SkScalar getFontScale(CGFontRef cgFont) { |
| 248 int unitsPerEm = CGFontGetUnitsPerEm(cgFont); |
| 249 return SkScalarInvert(SkIntToScalar(unitsPerEm)); |
| 250 } |
| 251 |
243 //============================================================================ | 252 //============================================================================ |
244 // Macros | 253 // Macros |
245 //---------------------------------------------------------------------------- | 254 //---------------------------------------------------------------------------- |
246 // Release a CFTypeRef | 255 // Release a CFTypeRef |
247 #ifndef CFSafeRelease | 256 #ifndef CFSafeRelease |
248 #define CFSafeRelease(_object) \ | 257 #define CFSafeRelease(_object) \ |
249 do \ | 258 do \ |
250 { \ | 259 { \ |
251 if ((_object) != NULL) \ | 260 if ((_object) != NULL) \ |
252 { \ | 261 { \ |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
529 if (face) { | 538 if (face) { |
530 SkTypefaceCache::Add(face, style); | 539 SkTypefaceCache::Add(face, style); |
531 } else { | 540 } else { |
532 face = GetDefaultFace(); | 541 face = GetDefaultFace(); |
533 face->ref(); | 542 face->ref(); |
534 } | 543 } |
535 } | 544 } |
536 return face; | 545 return face; |
537 } | 546 } |
538 | 547 |
| 548 static void flip(SkMatrix* matrix) { |
| 549 matrix->setSkewX(-matrix->getSkewX()); |
| 550 matrix->setSkewY(-matrix->getSkewY()); |
| 551 } |
| 552 |
539 /////////////////////////////////////////////////////////////////////////////// | 553 /////////////////////////////////////////////////////////////////////////////// |
540 | 554 |
541 struct GlyphRect { | 555 struct GlyphRect { |
542 int16_t fMinX; | 556 int16_t fMinX; |
543 int16_t fMinY; | 557 int16_t fMinY; |
544 int16_t fMaxX; | 558 int16_t fMaxX; |
545 int16_t fMaxY; | 559 int16_t fMaxY; |
546 }; | 560 }; |
547 | 561 |
548 class SkScalerContext_Mac : public SkScalerContext { | 562 class SkScalerContext_Mac : public SkScalerContext { |
549 public: | 563 public: |
550 SkScalerContext_Mac(const SkDescriptor*
desc); | 564 SkScalerContext_Mac(const SkDescriptor*
desc); |
551 virtual ~SkScalerContext_Mac(void); | 565 virtual ~SkScalerContext_Mac(void); |
552 | 566 |
553 | 567 |
554 protected: | 568 protected: |
555 unsigned generateGlyphCount(void); | 569 unsigned generateGlyphCount(void); |
556 uint16_t generateCharToGlyph(SkUnichar uni); | 570 uint16_t generateCharToGlyph(SkUnichar uni); |
557 void generateAdvance(SkGlyph* glyph); | 571 void generateAdvance(SkGlyph* glyph); |
558 void generateMetrics(SkGlyph* glyph); | 572 void generateMetrics(SkGlyph* glyph); |
559 void generateImage(const SkGlyph& glyph); | 573 void generateImage(const SkGlyph& glyph); |
560 void generatePath( const SkGlyph& glyph, SkPa
th* path); | 574 void generatePath( const SkGlyph& glyph, SkPa
th* path); |
561 void generateFontMetrics(SkPaint::FontMetrics
* mX, SkPaint::FontMetrics* mY); | 575 void generateFontMetrics(SkPaint::FontMetrics
* mX, SkPaint::FontMetrics* mY); |
562 | 576 |
563 | 577 |
564 private: | 578 private: |
565 static void CTPathElement(void *info, const CGPathEl
ement *element); | 579 static void CTPathElement(void *info, const CGPathEl
ement *element); |
566 uint16_t getAdjustStart(); | 580 uint16_t getAdjustStart(); |
| 581 void getVerticalOffset(CGGlyph glyphID, SkIPo
int* offset) const; |
567 bool generateBBoxes(); | 582 bool generateBBoxes(); |
568 | 583 |
569 | |
570 private: | 584 private: |
571 CGAffineTransform fTransform; | 585 CGAffineTransform fTransform; |
572 SkMatrix fMatrix; | 586 SkMatrix fUnitMatrix; // without font size |
573 SkMatrix fAdjustBadMatrix; | 587 SkMatrix fVerticalMatrix; // unit rotated |
| 588 SkMatrix fMatrix; // with font size |
| 589 SkMatrix fAdjustBadMatrix; // lion-specific fix |
574 Offscreen fOffscreen; | 590 Offscreen fOffscreen; |
575 CTFontRef fCTFont; | 591 CTFontRef fCTFont; |
| 592 CTFontRef fCTVerticalFont; // for vertical advance |
576 CGFontRef fCGFont; | 593 CGFontRef fCGFont; |
577 GlyphRect* fAdjustBad; | 594 GlyphRect* fAdjustBad; |
578 uint16_t fAdjustStart; | 595 uint16_t fAdjustStart; |
579 uint16_t fGlyphCount; | 596 uint16_t fGlyphCount; |
580 bool fGeneratedBBoxes; | 597 bool fGeneratedBBoxes; |
581 bool fDoSubPosition; | 598 bool fDoSubPosition; |
| 599 bool fVertical; |
582 | 600 |
583 friend class Offscreen; | 601 friend class Offscreen; |
584 }; | 602 }; |
585 | 603 |
586 SkScalerContext_Mac::SkScalerContext_Mac(const SkDescriptor* desc) | 604 SkScalerContext_Mac::SkScalerContext_Mac(const SkDescriptor* desc) |
587 : SkScalerContext(desc) | 605 : SkScalerContext(desc) |
| 606 , fCTVerticalFont(NULL) |
588 , fAdjustBad(NULL) | 607 , fAdjustBad(NULL) |
589 , fAdjustStart(0) | 608 , fAdjustStart(0) |
590 , fGeneratedBBoxes(false) | 609 , fGeneratedBBoxes(false) |
591 { | 610 { |
592 CFIndex numGlyphs; | 611 CTFontRef ctFont = GetFontRefFromFontID(fRec.fFontID); |
593 CTFontRef ctFont; | 612 CFIndex numGlyphs = CTFontGetGlyphCount(ctFont); |
594 | 613 |
595 // Get the state we need | 614 // Get the state we need |
596 fRec.getSingleMatrix(&fMatrix); | 615 fRec.getSingleMatrix(&fMatrix); |
| 616 fUnitMatrix = fMatrix; |
597 | 617 |
598 ctFont = GetFontRefFromFontID(fRec.fFontID); | 618 // extract the font size out of the matrix, but leave the skewing for italic |
599 numGlyphs = CTFontGetGlyphCount(ctFont); | 619 SkScalar reciprocal = SkScalarInvert(fRec.fTextSize); |
| 620 fUnitMatrix.preScale(reciprocal, reciprocal); |
| 621 |
600 SkASSERT(numGlyphs >= 1 && numGlyphs <= 0xFFFF); | 622 SkASSERT(numGlyphs >= 1 && numGlyphs <= 0xFFFF); |
601 | 623 |
602 fTransform = MatrixToCGAffineTransform(fMatrix); | 624 fTransform = MatrixToCGAffineTransform(fMatrix); |
603 | 625 |
| 626 CGAffineTransform transform; |
| 627 CGFloat unitFontSize; |
604 if (isLeopard()) { | 628 if (isLeopard()) { |
605 // passing 1 for pointSize to Leopard sets the font size to 1 pt. | 629 // passing 1 for pointSize to Leopard sets the font size to 1 pt. |
606 // pass 0 to use the CoreText size | 630 // pass 0 to use the CoreText size |
607 // extract the font size out of the matrix, but leave the skewing for it
alic | 631 transform = MatrixToCGAffineTransform(fUnitMatrix); |
608 CGFloat fontSize = CTFontGetSize(ctFont); | 632 unitFontSize = 0; |
609 float reciprocal = fontSize ? 1.0f / fontSize : 1.0f; | |
610 fMatrix.preScale(reciprocal, reciprocal); | |
611 CGAffineTransform transform = MatrixToCGAffineTransform(fMatrix); | |
612 fMatrix.setSkewX(-fMatrix.getSkewX()); // flip to fix up bounds later | |
613 fMatrix.setSkewY(-fMatrix.getSkewY()); | |
614 fCTFont = CTFontCreateCopyWithAttributes(ctFont, 0, &transform, NULL); | |
615 } else { | 633 } else { |
616 // since our matrix includes everything, we pass 1 for pointSize | 634 // since our matrix includes everything, we pass 1 for pointSize |
617 fCTFont = CTFontCreateCopyWithAttributes(ctFont, 1, &fTransform, NULL); | 635 transform = fTransform; |
| 636 unitFontSize = 1; |
| 637 } |
| 638 flip(&fUnitMatrix); // flip to fix up bounds later |
| 639 fVertical = SkToBool(fRec.fFlags & kVertical_Flag); |
| 640 CTFontDescriptorRef ctFontDesc = NULL; |
| 641 if (fVertical) { |
| 642 CFMutableDictionaryRef cfAttributes = CFDictionaryCreateMutable( |
| 643 kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, |
| 644 &kCFTypeDictionaryValueCallBacks); |
| 645 if (cfAttributes) { |
| 646 CTFontOrientation ctOrientation = kCTFontVerticalOrientation; |
| 647 CFNumberRef cfVertical = CFNumberCreate(kCFAllocatorDefault, |
| 648 kCFNumberSInt32Type, &ctOrientation); |
| 649 CFDictionaryAddValue(cfAttributes, kCTFontOrientationAttribute, |
| 650 cfVertical); |
| 651 CFSafeRelease(cfVertical); |
| 652 ctFontDesc = CTFontDescriptorCreateWithAttributes(cfAttributes); |
| 653 CFRelease(cfAttributes); |
| 654 } |
| 655 } |
| 656 fCTFont = CTFontCreateCopyWithAttributes(ctFont, unitFontSize, &transform, |
| 657 ctFontDesc); |
| 658 CFSafeRelease(ctFontDesc); |
| 659 fCGFont = CTFontCopyGraphicsFont(fCTFont, NULL); |
| 660 if (fVertical) { |
| 661 CGAffineTransform rotateLeft = CGAffineTransformMake(0, -1, 1, 0, 0, 0); |
| 662 transform = CGAffineTransformConcat(rotateLeft, transform); |
| 663 fCTVerticalFont = CTFontCreateCopyWithAttributes(ctFont, unitFontSize, |
| 664 &transform, NULL); |
| 665 fVerticalMatrix = fUnitMatrix; |
| 666 if (isSnowLeopard()) { |
| 667 SkScalar scale = SkScalarMul(fRec.fTextSize, getFontScale(fCGFont)); |
| 668 fVerticalMatrix.preScale(scale, scale); |
| 669 } else { |
| 670 fVerticalMatrix.preRotate(SkIntToScalar(90)); |
| 671 } |
618 } | 672 } |
619 fGlyphCount = SkToU16(numGlyphs); | 673 fGlyphCount = SkToU16(numGlyphs); |
620 fCGFont = CTFontCopyGraphicsFont(fCTFont, NULL); | |
621 | |
622 fDoSubPosition = SkToBool(fRec.fFlags & kSubpixelPositioning_Flag); | 674 fDoSubPosition = SkToBool(fRec.fFlags & kSubpixelPositioning_Flag); |
623 } | 675 } |
624 | 676 |
625 SkScalerContext_Mac::~SkScalerContext_Mac() { | 677 SkScalerContext_Mac::~SkScalerContext_Mac() { |
626 delete[] fAdjustBad; | 678 delete[] fAdjustBad; |
627 CFSafeRelease(fCTFont); | 679 CFSafeRelease(fCTFont); |
628 if (fCGFont) { | 680 CFSafeRelease(fCTVerticalFont); |
629 CGFontRelease(fCGFont); | 681 CFSafeRelease(fCGFont); |
630 } | |
631 } | 682 } |
632 | 683 |
633 CGRGBPixel* Offscreen::getCG(const SkScalerContext_Mac& context, const SkGlyph&
glyph, | 684 CGRGBPixel* Offscreen::getCG(const SkScalerContext_Mac& context, const SkGlyph&
glyph, |
634 bool fgColorIsWhite, CGGlyph glyphID, size_t* rowBy
tesPtr) { | 685 bool fgColorIsWhite, CGGlyph glyphID, size_t* rowBy
tesPtr) { |
635 if (!fRGBSpace) { | 686 if (!fRGBSpace) { |
636 fRGBSpace = CGColorSpaceCreateDeviceRGB(); | 687 fRGBSpace = CGColorSpaceCreateDeviceRGB(); |
637 } | 688 } |
638 | 689 |
639 // default to kBW_Format | 690 // default to kBW_Format |
640 bool doAA = false; | 691 bool doAA = false; |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
713 #else | 764 #else |
714 sk_memset_rect32(image, erase, glyph.fWidth, glyph.fHeight, rowBytes); | 765 sk_memset_rect32(image, erase, glyph.fWidth, glyph.fHeight, rowBytes); |
715 #endif | 766 #endif |
716 | 767 |
717 float subX = 0; | 768 float subX = 0; |
718 float subY = 0; | 769 float subY = 0; |
719 if (context.fDoSubPosition) { | 770 if (context.fDoSubPosition) { |
720 subX = SkFixedToFloat(glyph.getSubXFixed()); | 771 subX = SkFixedToFloat(glyph.getSubXFixed()); |
721 subY = SkFixedToFloat(glyph.getSubYFixed()); | 772 subY = SkFixedToFloat(glyph.getSubYFixed()); |
722 } | 773 } |
| 774 if (context.fVertical) { |
| 775 SkIPoint offset; |
| 776 context.getVerticalOffset(glyphID, &offset); |
| 777 subX += offset.fX; |
| 778 subY += offset.fY; |
| 779 } |
723 CGContextShowGlyphsAtPoint(fCG, -glyph.fLeft + subX, | 780 CGContextShowGlyphsAtPoint(fCG, -glyph.fLeft + subX, |
724 glyph.fTop + glyph.fHeight - subY, | 781 glyph.fTop + glyph.fHeight - subY, |
725 &glyphID, 1); | 782 &glyphID, 1); |
726 | 783 |
727 SkASSERT(rowBytesPtr); | 784 SkASSERT(rowBytesPtr); |
728 *rowBytesPtr = rowBytes; | 785 *rowBytesPtr = rowBytes; |
729 return image; | 786 return image; |
730 } | 787 } |
731 | 788 |
| 789 void SkScalerContext_Mac::getVerticalOffset(CGGlyph glyphID, SkIPoint* offset) c
onst { |
| 790 CGSize vertOffset; |
| 791 CTFontGetVerticalTranslationsForGlyphs(fCTVerticalFont, &glyphID, &vertOffse
t, 1); |
| 792 const SkPoint trans = {SkFloatToScalar(vertOffset.width), |
| 793 SkFloatToScalar(vertOffset.height)}; |
| 794 SkPoint floatOffset; |
| 795 fVerticalMatrix.mapPoints(&floatOffset, &trans, 1); |
| 796 offset->fX = SkScalarRound(floatOffset.fX); |
| 797 offset->fY = -SkScalarRound(floatOffset.fY); |
| 798 } |
| 799 |
732 /* from http://developer.apple.com/fonts/TTRefMan/RM06/Chap6loca.html | 800 /* from http://developer.apple.com/fonts/TTRefMan/RM06/Chap6loca.html |
733 * There are two versions of this table, the short and the long. The version | 801 * There are two versions of this table, the short and the long. The version |
734 * used is specified in the Font Header ('head') table in the indexToLocFormat | 802 * used is specified in the Font Header ('head') table in the indexToLocFormat |
735 * field. The choice of long or short offsets is dependent on the maximum | 803 * field. The choice of long or short offsets is dependent on the maximum |
736 * possible offset distance. | 804 * possible offset distance. |
737 * | 805 * |
738 * 'loca' short version: The actual local offset divided by 2 is stored.· | 806 * 'loca' short version: The actual local offset divided by 2 is stored.· |
739 * 'loca' long version: The actual local offset is stored. | 807 * 'loca' long version: The actual local offset is stored. |
740 *· | 808 *· |
741 * The result is a offset into a table of 2 byte (16 bit) entries. | 809 * The result is a offset into a table of 2 byte (16 bit) entries. |
(...skipping 11 matching lines...) Expand all Loading... |
753 const int kNumOfLongHorMetrics = 17; | 821 const int kNumOfLongHorMetrics = 17; |
754 return SkEndian_SwapBE16(hheaData[kNumOfLongHorMetrics]); | 822 return SkEndian_SwapBE16(hheaData[kNumOfLongHorMetrics]); |
755 } | 823 } |
756 | 824 |
757 // see http://developer.apple.com/fonts/TTRefMan/RM06/Chap6head.html | 825 // see http://developer.apple.com/fonts/TTRefMan/RM06/Chap6head.html |
758 static int getLocaFormat(const uint16_t* headData) { | 826 static int getLocaFormat(const uint16_t* headData) { |
759 const int kIndexToLocFormat = 25; | 827 const int kIndexToLocFormat = 25; |
760 return SkEndian_SwapBE16(headData[kIndexToLocFormat]); | 828 return SkEndian_SwapBE16(headData[kIndexToLocFormat]); |
761 } | 829 } |
762 | 830 |
763 // see http://developer.apple.com/fonts/TTRefMan/RM06/Chap6head.html | |
764 SkScalar getFontScale(const uint16_t* headData) { | |
765 const int kUnitsPerEm = 9; | |
766 int unitsPerEm = SkEndian_SwapBE16(headData[kUnitsPerEm]); | |
767 return SkScalarInvert(SkIntToScalar(unitsPerEm)); | |
768 } | |
769 | |
770 uint16_t SkScalerContext_Mac::getAdjustStart() { | 831 uint16_t SkScalerContext_Mac::getAdjustStart() { |
771 if (fAdjustStart) { | 832 if (fAdjustStart) { |
772 return fAdjustStart; | 833 return fAdjustStart; |
773 } | 834 } |
774 fAdjustStart = fGlyphCount; // fallback for all fonts | 835 fAdjustStart = fGlyphCount; // fallback for all fonts |
775 AutoCFDataRelease hheaRef(CGFontCopyTableForTag(fCGFont, 'hhea')); | 836 AutoCFDataRelease hheaRef(CGFontCopyTableForTag(fCGFont, 'hhea')); |
776 const uint16_t* hheaData = hheaRef.getShortPtr(); | 837 const uint16_t* hheaData = hheaRef.getShortPtr(); |
777 if (hheaData) { | 838 if (hheaData) { |
778 fAdjustStart = getNumLongMetrics(hheaData); | 839 fAdjustStart = getNumLongMetrics(hheaData); |
779 } | 840 } |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
823 rect.fMinX = SkEndian_SwapBE16(glyfData[last + 1]); | 884 rect.fMinX = SkEndian_SwapBE16(glyfData[last + 1]); |
824 rect.fMinY = SkEndian_SwapBE16(glyfData[last + 2]); | 885 rect.fMinY = SkEndian_SwapBE16(glyfData[last + 2]); |
825 rect.fMaxX = SkEndian_SwapBE16(glyfData[last + 3]); | 886 rect.fMaxX = SkEndian_SwapBE16(glyfData[last + 3]); |
826 rect.fMaxY = SkEndian_SwapBE16(glyfData[last + 4]); | 887 rect.fMaxY = SkEndian_SwapBE16(glyfData[last + 4]); |
827 } else { | 888 } else { |
828 sk_bzero(&rect, sizeof(GlyphRect)); | 889 sk_bzero(&rect, sizeof(GlyphRect)); |
829 } | 890 } |
830 last = offset; | 891 last = offset; |
831 } | 892 } |
832 fAdjustBadMatrix = fMatrix; | 893 fAdjustBadMatrix = fMatrix; |
833 fAdjustBadMatrix.setSkewX(-fMatrix.getSkewX()); | 894 flip(&fAdjustBadMatrix); |
834 fAdjustBadMatrix.setSkewY(-fMatrix.getSkewY()); | 895 SkScalar fontScale = getFontScale(fCGFont); |
835 SkScalar fontScale = getFontScale(headData); | |
836 fAdjustBadMatrix.preScale(fontScale, fontScale); | 896 fAdjustBadMatrix.preScale(fontScale, fontScale); |
837 return true; | 897 return true; |
838 } | 898 } |
839 | 899 |
840 unsigned SkScalerContext_Mac::generateGlyphCount(void) | 900 unsigned SkScalerContext_Mac::generateGlyphCount(void) |
841 { | 901 { |
842 return(fGlyphCount); | 902 return(fGlyphCount); |
843 } | 903 } |
844 | 904 |
845 uint16_t SkScalerContext_Mac::generateCharToGlyph(SkUnichar uni) | 905 uint16_t SkScalerContext_Mac::generateCharToGlyph(SkUnichar uni) |
(...skipping 21 matching lines...) Expand all Loading... |
867 | 927 |
868 void SkScalerContext_Mac::generateMetrics(SkGlyph* glyph) { | 928 void SkScalerContext_Mac::generateMetrics(SkGlyph* glyph) { |
869 CGSize theAdvance; | 929 CGSize theAdvance; |
870 CGRect theBounds; | 930 CGRect theBounds; |
871 CGGlyph cgGlyph; | 931 CGGlyph cgGlyph; |
872 | 932 |
873 // Get the state we need | 933 // Get the state we need |
874 cgGlyph = (CGGlyph) glyph->getGlyphID(fBaseGlyphCount); | 934 cgGlyph = (CGGlyph) glyph->getGlyphID(fBaseGlyphCount); |
875 | 935 |
876 CTFontGetBoundingRectsForGlyphs(fCTFont, kCTFontDefaultOrientation, &cgGlyph
, &theBounds, 1); | 936 CTFontGetBoundingRectsForGlyphs(fCTFont, kCTFontDefaultOrientation, &cgGlyph
, &theBounds, 1); |
877 CTFontGetAdvancesForGlyphs(fCTFont, kCTFontDefaultOrientation, &cgGlyph, &th
eAdvance, 1); | 937 if (fVertical) { |
| 938 CTFontGetAdvancesForGlyphs(fCTVerticalFont, kCTFontVerticalOrientation,
&cgGlyph, &theAdvance, 1); |
| 939 } else { |
| 940 CTFontGetAdvancesForGlyphs(fCTFont, kCTFontDefaultOrientation, &cgGlyph,
&theAdvance, 1); |
| 941 } |
878 | 942 |
879 // BUG? | 943 // BUG? |
880 // 0x200B (zero-advance space) seems to return a huge (garbage) bounds, when | 944 // 0x200B (zero-advance space) seems to return a huge (garbage) bounds, when |
881 // it should be empty. So, if we see a zero-advance, we check if it has an | 945 // it should be empty. So, if we see a zero-advance, we check if it has an |
882 // empty path or not, and if so, we jam the bounds to 0. Hopefully a zero-ad
vance | 946 // empty path or not, and if so, we jam the bounds to 0. Hopefully a zero-ad
vance |
883 // is rare, so we won't incur a big performance cost for this extra check. | 947 // is rare, so we won't incur a big performance cost for this extra check. |
884 if (0 == theAdvance.width && 0 == theAdvance.height) { | 948 if (0 == theAdvance.width && 0 == theAdvance.height) { |
885 CGPathRef path = CTFontCreatePathForGlyph(fCTFont, cgGlyph, NULL); | 949 CGPathRef path = CTFontCreatePathForGlyph(fCTFont, cgGlyph, NULL); |
886 if (NULL == path || CGPathIsEmpty(path)) { | 950 if (NULL == path || CGPathIsEmpty(path)) { |
887 theBounds = CGRectMake(0, 0, 0, 0); | 951 theBounds = CGRectMake(0, 0, 0, 0); |
(...skipping 11 matching lines...) Expand all Loading... |
899 return; | 963 return; |
900 } | 964 } |
901 ···· | 965 ···· |
902 if (isLeopard()) { | 966 if (isLeopard()) { |
903 // Leopard does not consider the matrix skew in its bounds. | 967 // Leopard does not consider the matrix skew in its bounds. |
904 // Run the bounding rectangle through the skew matrix to determine | 968 // Run the bounding rectangle through the skew matrix to determine |
905 // the true bounds. | 969 // the true bounds. |
906 SkRect glyphBounds = SkRect::MakeXYWH( | 970 SkRect glyphBounds = SkRect::MakeXYWH( |
907 theBounds.origin.x, theBounds.origin.y, | 971 theBounds.origin.x, theBounds.origin.y, |
908 theBounds.size.width, theBounds.size.height); | 972 theBounds.size.width, theBounds.size.height); |
909 fMatrix.mapRect(&glyphBounds); | 973 fUnitMatrix.mapRect(&glyphBounds); |
910 theBounds.origin.x = glyphBounds.fLeft; | 974 theBounds.origin.x = glyphBounds.fLeft; |
911 theBounds.origin.y = glyphBounds.fTop; | 975 theBounds.origin.y = glyphBounds.fTop; |
912 theBounds.size.width = glyphBounds.width(); | 976 theBounds.size.width = glyphBounds.width(); |
913 theBounds.size.height = glyphBounds.height(); | 977 theBounds.size.height = glyphBounds.height(); |
914 } | 978 } |
915 // Adjust the bounds | 979 // Adjust the bounds |
916 // | 980 // |
917 // CTFontGetBoundingRectsForGlyphs ignores the font transform, so we need | 981 // CTFontGetBoundingRectsForGlyphs ignores the font transform, so we need |
918 // to transform the bounding box ourselves. | 982 // to transform the bounding box ourselves. |
919 // | 983 // |
(...skipping 13 matching lines...) Expand all Loading... |
933 } | 997 } |
934 // Lion returns fractions in the bounds | 998 // Lion returns fractions in the bounds |
935 glyph->fWidth = sk_float_ceil2int(theBounds.size.width); | 999 glyph->fWidth = sk_float_ceil2int(theBounds.size.width); |
936 glyph->fHeight = sk_float_ceil2int(theBounds.size.height); | 1000 glyph->fHeight = sk_float_ceil2int(theBounds.size.height); |
937 } else { | 1001 } else { |
938 glyph->fWidth = sk_float_round2int(theBounds.size.width); | 1002 glyph->fWidth = sk_float_round2int(theBounds.size.width); |
939 glyph->fHeight = sk_float_round2int(theBounds.size.height); | 1003 glyph->fHeight = sk_float_round2int(theBounds.size.height); |
940 } | 1004 } |
941 glyph->fTop = -sk_float_round2int(CGRectGetMaxY_inline(theBounds)); | 1005 glyph->fTop = -sk_float_round2int(CGRectGetMaxY_inline(theBounds)); |
942 glyph->fLeft = sk_float_round2int(CGRectGetMinX_inline(theBounds)); | 1006 glyph->fLeft = sk_float_round2int(CGRectGetMinX_inline(theBounds)); |
| 1007 SkIPoint offset; |
| 1008 if (fVertical) { |
| 1009 getVerticalOffset(cgGlyph, &offset); |
| 1010 glyph->fLeft += offset.fX; |
| 1011 glyph->fTop += offset.fY; |
| 1012 } |
943 } | 1013 } |
944 | 1014 |
945 #include "SkColorPriv.h" | 1015 #include "SkColorPriv.h" |
946 | 1016 |
947 static void build_power_table(uint8_t table[], float ee) { | 1017 static void build_power_table(uint8_t table[], float ee) { |
948 for (int i = 0; i < 256; i++) { | 1018 for (int i = 0; i < 256; i++) { |
949 float x = i / 255.f; | 1019 float x = i / 255.f; |
950 x = powf(x, ee); | 1020 x = powf(x, ee); |
951 int xx = SkScalarRound(SkFloatToScalar(x * 255)); | 1021 int xx = SkScalarRound(SkFloatToScalar(x * 255)); |
952 table[i] = SkToU8(xx); | 1022 table[i] = SkToU8(xx); |
(...skipping 785 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1738 | 1808 |
1739 if (offset >= theSize) | 1809 if (offset >= theSize) |
1740 return 0; | 1810 return 0; |
1741 | 1811 |
1742 if ((offset + length) > theSize) | 1812 if ((offset + length) > theSize) |
1743 length = theSize - offset; | 1813 length = theSize - offset; |
1744 | 1814 |
1745 memcpy(data, CFDataGetBytePtr(cfData) + offset, length); | 1815 memcpy(data, CFDataGetBytePtr(cfData) + offset, length); |
1746 return(length); | 1816 return(length); |
1747 } | 1817 } |
OLD | NEW |