OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkPaint.h" | 8 #include "SkPaint.h" |
9 #include "SkAutoKern.h" | 9 #include "SkAutoKern.h" |
10 #include "SkChecksum.h" | 10 #include "SkChecksum.h" |
(...skipping 715 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
726 SkTLazy<SkPaint> fLazy; | 726 SkTLazy<SkPaint> fLazy; |
727 }; | 727 }; |
728 | 728 |
729 static void set_bounds(const SkGlyph& g, SkRect* bounds) { | 729 static void set_bounds(const SkGlyph& g, SkRect* bounds) { |
730 bounds->set(SkIntToScalar(g.fLeft), | 730 bounds->set(SkIntToScalar(g.fLeft), |
731 SkIntToScalar(g.fTop), | 731 SkIntToScalar(g.fTop), |
732 SkIntToScalar(g.fLeft + g.fWidth), | 732 SkIntToScalar(g.fLeft + g.fWidth), |
733 SkIntToScalar(g.fTop + g.fHeight)); | 733 SkIntToScalar(g.fTop + g.fHeight)); |
734 } | 734 } |
735 | 735 |
736 static void join_bounds_x(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dx) { | 736 static void join_bounds_x(const SkGlyph& g, SkRect* bounds, SkScalar dx) { |
737 SkScalar sx = Sk48Dot16ToScalar(dx); | 737 bounds->join(SkIntToScalar(g.fLeft) + dx, |
738 bounds->join(SkIntToScalar(g.fLeft) + sx, | |
739 SkIntToScalar(g.fTop), | 738 SkIntToScalar(g.fTop), |
740 SkIntToScalar(g.fLeft + g.fWidth) + sx, | 739 SkIntToScalar(g.fLeft + g.fWidth) + dx, |
741 SkIntToScalar(g.fTop + g.fHeight)); | 740 SkIntToScalar(g.fTop + g.fHeight)); |
742 } | 741 } |
743 | 742 |
744 static void join_bounds_y(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dy) { | 743 static void join_bounds_y(const SkGlyph& g, SkRect* bounds, SkScalar dy) { |
745 SkScalar sy = Sk48Dot16ToScalar(dy); | |
746 bounds->join(SkIntToScalar(g.fLeft), | 744 bounds->join(SkIntToScalar(g.fLeft), |
747 SkIntToScalar(g.fTop) + sy, | 745 SkIntToScalar(g.fTop) + dy, |
748 SkIntToScalar(g.fLeft + g.fWidth), | 746 SkIntToScalar(g.fLeft + g.fWidth), |
749 SkIntToScalar(g.fTop + g.fHeight) + sy); | 747 SkIntToScalar(g.fTop + g.fHeight) + dy); |
750 } | 748 } |
751 | 749 |
752 typedef void (*JoinBoundsProc)(const SkGlyph&, SkRect*, Sk48Dot16); | 750 typedef void (*JoinBoundsProc)(const SkGlyph&, SkRect*, SkScalar); |
753 | 751 |
754 // xyIndex is 0 for fAdvanceX or 1 for fAdvanceY | 752 // xyIndex is 0 for fAdvanceX or 1 for fAdvanceY |
755 static SkFixed advance(const SkGlyph& glyph, int xyIndex) { | 753 static SkScalar advance(const SkGlyph& glyph, int xyIndex) { |
756 SkASSERT(0 == xyIndex || 1 == xyIndex); | 754 SkASSERT(0 == xyIndex || 1 == xyIndex); |
757 return (&glyph.fAdvanceX)[xyIndex]; | 755 return SkFloatToScalar((&glyph.fAdvanceX)[xyIndex]); |
758 } | 756 } |
759 | 757 |
760 SkScalar SkPaint::measure_text(SkGlyphCache* cache, | 758 SkScalar SkPaint::measure_text(SkGlyphCache* cache, |
761 const char* text, size_t byteLength, | 759 const char* text, size_t byteLength, |
762 int* count, SkRect* bounds) const { | 760 int* count, SkRect* bounds) const { |
763 SkASSERT(count); | 761 SkASSERT(count); |
764 if (byteLength == 0) { | 762 if (byteLength == 0) { |
765 *count = 0; | 763 *count = 0; |
766 if (bounds) { | 764 if (bounds) { |
767 bounds->setEmpty(); | 765 bounds->setEmpty(); |
768 } | 766 } |
769 return 0; | 767 return 0; |
770 } | 768 } |
771 | 769 |
772 GlyphCacheProc glyphCacheProc = this->getGlyphCacheProc(nullptr != bounds); | 770 GlyphCacheProc glyphCacheProc = this->getGlyphCacheProc(nullptr != bounds); |
773 | 771 |
774 int xyIndex; | 772 int xyIndex; |
775 JoinBoundsProc joinBoundsProc; | 773 JoinBoundsProc joinBoundsProc; |
776 if (this->isVerticalText()) { | 774 if (this->isVerticalText()) { |
777 xyIndex = 1; | 775 xyIndex = 1; |
778 joinBoundsProc = join_bounds_y; | 776 joinBoundsProc = join_bounds_y; |
779 } else { | 777 } else { |
780 xyIndex = 0; | 778 xyIndex = 0; |
781 joinBoundsProc = join_bounds_x; | 779 joinBoundsProc = join_bounds_x; |
782 } | 780 } |
783 | 781 |
784 int n = 1; | 782 int n = 1; |
785 const char* stop = (const char*)text + byteLength; | 783 const char* stop = (const char*)text + byteLength; |
786 const SkGlyph* g = &glyphCacheProc(cache, &text); | 784 const SkGlyph* g = &glyphCacheProc(cache, &text); |
787 // our accumulated fixed-point advances might overflow 16.16, so we use | 785 SkScalar x = advance(*g, xyIndex); |
788 // a 48.16 (64bit) accumulator, and then convert that to scalar at the | |
789 // very end. | |
790 Sk48Dot16 x = advance(*g, xyIndex); | |
791 | |
792 SkAutoKern autokern; | |
793 | 786 |
794 if (nullptr == bounds) { | 787 if (nullptr == bounds) { |
795 if (this->isDevKernText()) { | 788 if (this->isDevKernText()) { |
796 int rsb; | |
797 for (; text < stop; n++) { | 789 for (; text < stop; n++) { |
798 rsb = g->fRsbDelta; | 790 const int rsb = g->fRsbDelta; |
799 g = &glyphCacheProc(cache, &text); | 791 g = &glyphCacheProc(cache, &text); |
800 x += SkAutoKern_AdjustF(rsb, g->fLsbDelta) + advance(*g, xyIndex
); | 792 x += SkAutoKern_Adjust(rsb, g->fLsbDelta) + advance(*g, xyIndex)
; |
801 } | 793 } |
802 } else { | 794 } else { |
803 for (; text < stop; n++) { | 795 for (; text < stop; n++) { |
804 x += advance(glyphCacheProc(cache, &text), xyIndex); | 796 x += advance(glyphCacheProc(cache, &text), xyIndex); |
805 } | 797 } |
806 } | 798 } |
807 } else { | 799 } else { |
808 set_bounds(*g, bounds); | 800 set_bounds(*g, bounds); |
809 if (this->isDevKernText()) { | 801 if (this->isDevKernText()) { |
810 int rsb; | |
811 for (; text < stop; n++) { | 802 for (; text < stop; n++) { |
812 rsb = g->fRsbDelta; | 803 const int rsb = g->fRsbDelta; |
813 g = &glyphCacheProc(cache, &text); | 804 g = &glyphCacheProc(cache, &text); |
814 x += SkAutoKern_AdjustF(rsb, g->fLsbDelta); | 805 x += SkAutoKern_Adjust(rsb, g->fLsbDelta); |
815 joinBoundsProc(*g, bounds, x); | 806 joinBoundsProc(*g, bounds, x); |
816 x += advance(*g, xyIndex); | 807 x += advance(*g, xyIndex); |
817 } | 808 } |
818 } else { | 809 } else { |
819 for (; text < stop; n++) { | 810 for (; text < stop; n++) { |
820 g = &glyphCacheProc(cache, &text); | 811 g = &glyphCacheProc(cache, &text); |
821 joinBoundsProc(*g, bounds, x); | 812 joinBoundsProc(*g, bounds, x); |
822 x += advance(*g, xyIndex); | 813 x += advance(*g, xyIndex); |
823 } | 814 } |
824 } | 815 } |
825 } | 816 } |
826 SkASSERT(text == stop); | 817 SkASSERT(text == stop); |
827 | 818 |
828 *count = n; | 819 *count = n; |
829 return Sk48Dot16ToScalar(x); | 820 return x; |
830 } | 821 } |
831 | 822 |
832 SkScalar SkPaint::measureText(const void* textData, size_t length, SkRect* bound
s) const { | 823 SkScalar SkPaint::measureText(const void* textData, size_t length, SkRect* bound
s) const { |
833 const char* text = (const char*)textData; | 824 const char* text = (const char*)textData; |
834 SkASSERT(text != nullptr || length == 0); | 825 SkASSERT(text != nullptr || length == 0); |
835 | 826 |
836 SkCanonicalizePaint canon(*this); | 827 SkCanonicalizePaint canon(*this); |
837 const SkPaint& paint = canon.getPaint(); | 828 const SkPaint& paint = canon.getPaint(); |
838 SkScalar scale = canon.getScale(); | 829 SkScalar scale = canon.getScale(); |
839 | 830 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
889 // adjust max in case we changed the textSize in paint | 880 // adjust max in case we changed the textSize in paint |
890 if (scale) { | 881 if (scale) { |
891 maxWidth /= scale; | 882 maxWidth /= scale; |
892 } | 883 } |
893 | 884 |
894 SkAutoGlyphCache autoCache(paint, nullptr, nullptr); | 885 SkAutoGlyphCache autoCache(paint, nullptr, nullptr); |
895 SkGlyphCache* cache = autoCache.getCache(); | 886 SkGlyphCache* cache = autoCache.getCache(); |
896 | 887 |
897 GlyphCacheProc glyphCacheProc = paint.getGlyphCacheProc(false); | 888 GlyphCacheProc glyphCacheProc = paint.getGlyphCacheProc(false); |
898 const int xyIndex = paint.isVerticalText() ? 1 : 0; | 889 const int xyIndex = paint.isVerticalText() ? 1 : 0; |
899 // use 64bits for our accumulator, to avoid overflowing 16.16 | 890 SkScalar width = 0; |
900 Sk48Dot16 max = SkScalarTo48Dot16(maxWidth); | |
901 Sk48Dot16 width = 0; | |
902 | |
903 SkAutoKern autokern; | |
904 | 891 |
905 if (this->isDevKernText()) { | 892 if (this->isDevKernText()) { |
906 int rsb = 0; | 893 int rsb = 0; |
907 while (text < stop) { | 894 while (text < stop) { |
908 const char* curr = text; | 895 const char* curr = text; |
909 const SkGlyph& g = glyphCacheProc(cache, &text); | 896 const SkGlyph& g = glyphCacheProc(cache, &text); |
910 SkFixed x = SkAutoKern_AdjustF(rsb, g.fLsbDelta) + advance(g, xyInde
x); | 897 SkScalar x = SkAutoKern_Adjust(rsb, g.fLsbDelta) + advance(g, xyInde
x); |
911 if ((width += x) > max) { | 898 if ((width += x) > maxWidth) { |
912 width -= x; | 899 width -= x; |
913 text = curr; | 900 text = curr; |
914 break; | 901 break; |
915 } | 902 } |
916 rsb = g.fRsbDelta; | 903 rsb = g.fRsbDelta; |
917 } | 904 } |
918 } else { | 905 } else { |
919 while (text < stop) { | 906 while (text < stop) { |
920 const char* curr = text; | 907 const char* curr = text; |
921 SkFixed x = advance(glyphCacheProc(cache, &text), xyIndex); | 908 SkScalar x = advance(glyphCacheProc(cache, &text), xyIndex); |
922 if ((width += x) > max) { | 909 if ((width += x) > maxWidth) { |
923 width -= x; | 910 width -= x; |
924 text = curr; | 911 text = curr; |
925 break; | 912 break; |
926 } | 913 } |
927 } | 914 } |
928 } | 915 } |
929 | 916 |
930 if (measuredWidth) { | 917 if (measuredWidth) { |
931 SkScalar scalarWidth = Sk48Dot16ToScalar(width); | |
932 if (scale) { | 918 if (scale) { |
933 scalarWidth = SkScalarMul(scalarWidth, scale); | 919 width *= scale; |
934 } | 920 } |
935 *measuredWidth = scalarWidth; | 921 *measuredWidth = width; |
936 } | 922 } |
937 | 923 |
938 // return the number of bytes measured | 924 // return the number of bytes measured |
939 return text - stop + length; | 925 return text - stop + length; |
940 } | 926 } |
941 | 927 |
942 /////////////////////////////////////////////////////////////////////////////// | 928 /////////////////////////////////////////////////////////////////////////////// |
943 | 929 |
944 static bool FontMetricsCacheProc(const SkGlyphCache* cache, void* context) { | 930 static bool FontMetricsCacheProc(const SkGlyphCache* cache, void* context) { |
945 *(SkPaint::FontMetrics*)context = cache->getFontMetrics(); | 931 *(SkPaint::FontMetrics*)context = cache->getFontMetrics(); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1015 GlyphCacheProc glyphCacheProc = paint.getGlyphCacheProc(nullptr != boun
ds); | 1001 GlyphCacheProc glyphCacheProc = paint.getGlyphCacheProc(nullptr != boun
ds); |
1016 | 1002 |
1017 const char* text = (const char*)textData; | 1003 const char* text = (const char*)textData; |
1018 const char* stop = text + byteLength; | 1004 const char* stop = text + byteLength; |
1019 int count = 0; | 1005 int count = 0; |
1020 const int xyIndex = paint.isVerticalText() ? 1 : 0; | 1006 const int xyIndex = paint.isVerticalText() ? 1 : 0; |
1021 | 1007 |
1022 if (this->isDevKernText()) { | 1008 if (this->isDevKernText()) { |
1023 // we adjust the widths returned here through auto-kerning | 1009 // we adjust the widths returned here through auto-kerning |
1024 SkAutoKern autokern; | 1010 SkAutoKern autokern; |
1025 SkFixed prevWidth = 0; | 1011 SkScalar prevWidth = 0; |
1026 | 1012 |
1027 if (scale) { | 1013 if (scale) { |
1028 while (text < stop) { | 1014 while (text < stop) { |
1029 const SkGlyph& g = glyphCacheProc(cache, &text); | 1015 const SkGlyph& g = glyphCacheProc(cache, &text); |
1030 if (widths) { | 1016 if (widths) { |
1031 SkFixed adjust = autokern.adjust(g); | 1017 SkScalar adjust = autokern.adjust(g); |
1032 | 1018 |
1033 if (count > 0) { | 1019 if (count > 0) { |
1034 SkScalar w = SkFixedToScalar(prevWidth + adjust); | 1020 *widths++ = SkScalarMul(prevWidth + adjust, scale); |
1035 *widths++ = SkScalarMul(w, scale); | |
1036 } | 1021 } |
1037 prevWidth = advance(g, xyIndex); | 1022 prevWidth = advance(g, xyIndex); |
1038 } | 1023 } |
1039 if (bounds) { | 1024 if (bounds) { |
1040 set_bounds(g, bounds++, scale); | 1025 set_bounds(g, bounds++, scale); |
1041 } | 1026 } |
1042 ++count; | 1027 ++count; |
1043 } | 1028 } |
1044 if (count > 0 && widths) { | 1029 if (count > 0 && widths) { |
1045 *widths = SkScalarMul(SkFixedToScalar(prevWidth), scale); | 1030 *widths = SkScalarMul(prevWidth, scale); |
1046 } | 1031 } |
1047 } else { | 1032 } else { |
1048 while (text < stop) { | 1033 while (text < stop) { |
1049 const SkGlyph& g = glyphCacheProc(cache, &text); | 1034 const SkGlyph& g = glyphCacheProc(cache, &text); |
1050 if (widths) { | 1035 if (widths) { |
1051 SkFixed adjust = autokern.adjust(g); | 1036 SkScalar adjust = autokern.adjust(g); |
1052 | 1037 |
1053 if (count > 0) { | 1038 if (count > 0) { |
1054 *widths++ = SkFixedToScalar(prevWidth + adjust); | 1039 *widths++ = prevWidth + adjust; |
1055 } | 1040 } |
1056 prevWidth = advance(g, xyIndex); | 1041 prevWidth = advance(g, xyIndex); |
1057 } | 1042 } |
1058 if (bounds) { | 1043 if (bounds) { |
1059 set_bounds(g, bounds++); | 1044 set_bounds(g, bounds++); |
1060 } | 1045 } |
1061 ++count; | 1046 ++count; |
1062 } | 1047 } |
1063 if (count > 0 && widths) { | 1048 if (count > 0 && widths) { |
1064 *widths = SkFixedToScalar(prevWidth); | 1049 *widths = prevWidth; |
1065 } | 1050 } |
1066 } | 1051 } |
1067 } else { // no devkern | 1052 } else { // no devkern |
1068 if (scale) { | 1053 if (scale) { |
1069 while (text < stop) { | 1054 while (text < stop) { |
1070 const SkGlyph& g = glyphCacheProc(cache, &text); | 1055 const SkGlyph& g = glyphCacheProc(cache, &text); |
1071 if (widths) { | 1056 if (widths) { |
1072 *widths++ = SkScalarMul(SkFixedToScalar(advance(g, xyIndex))
, | 1057 *widths++ = SkScalarMul(advance(g, xyIndex), |
1073 scale); | 1058 scale); |
1074 } | 1059 } |
1075 if (bounds) { | 1060 if (bounds) { |
1076 set_bounds(g, bounds++, scale); | 1061 set_bounds(g, bounds++, scale); |
1077 } | 1062 } |
1078 ++count; | 1063 ++count; |
1079 } | 1064 } |
1080 } else { | 1065 } else { |
1081 while (text < stop) { | 1066 while (text < stop) { |
1082 const SkGlyph& g = glyphCacheProc(cache, &text); | 1067 const SkGlyph& g = glyphCacheProc(cache, &text); |
1083 if (widths) { | 1068 if (widths) { |
1084 *widths++ = SkFixedToScalar(advance(g, xyIndex)); | 1069 *widths++ = advance(g, xyIndex); |
1085 } | 1070 } |
1086 if (bounds) { | 1071 if (bounds) { |
1087 set_bounds(g, bounds++); | 1072 set_bounds(g, bounds++); |
1088 } | 1073 } |
1089 ++count; | 1074 ++count; |
1090 } | 1075 } |
1091 } | 1076 } |
1092 } | 1077 } |
1093 | 1078 |
1094 SkASSERT(text == stop); | 1079 SkASSERT(text == stop); |
(...skipping 1195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2290 } | 2275 } |
2291 | 2276 |
2292 SkTextBaseIter::~SkTextBaseIter() { | 2277 SkTextBaseIter::~SkTextBaseIter() { |
2293 SkGlyphCache::AttachCache(fCache); | 2278 SkGlyphCache::AttachCache(fCache); |
2294 } | 2279 } |
2295 | 2280 |
2296 bool SkTextToPathIter::next(const SkPath** path, SkScalar* xpos) { | 2281 bool SkTextToPathIter::next(const SkPath** path, SkScalar* xpos) { |
2297 if (fText < fStop) { | 2282 if (fText < fStop) { |
2298 const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText); | 2283 const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText); |
2299 | 2284 |
2300 fXPos += SkScalarMul(SkFixedToScalar(fPrevAdvance + fAutoKern.adjust(gly
ph)), fScale); | 2285 fXPos += SkScalarMul(fPrevAdvance + fAutoKern.adjust(glyph), fScale); |
2301 fPrevAdvance = advance(glyph, fXYIndex); // + fPaint.getTextTracking()
; | 2286 fPrevAdvance = advance(glyph, fXYIndex); // + fPaint.getTextTracking()
; |
2302 | 2287 |
2303 if (glyph.fWidth) { | 2288 if (glyph.fWidth) { |
2304 if (path) { | 2289 if (path) { |
2305 *path = fCache->findPath(glyph); | 2290 *path = fCache->findPath(glyph); |
2306 } | 2291 } |
2307 } else { | 2292 } else { |
2308 if (path) { | 2293 if (path) { |
2309 *path = nullptr; | 2294 *path = nullptr; |
2310 } | 2295 } |
2311 } | 2296 } |
2312 if (xpos) { | 2297 if (xpos) { |
2313 *xpos = fXPos; | 2298 *xpos = fXPos; |
2314 } | 2299 } |
2315 return true; | 2300 return true; |
2316 } | 2301 } |
2317 return false; | 2302 return false; |
2318 } | 2303 } |
2319 | 2304 |
2320 bool SkTextInterceptsIter::next(SkScalar* array, int* count) { | 2305 bool SkTextInterceptsIter::next(SkScalar* array, int* count) { |
2321 const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText); | 2306 const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText); |
2322 fXPos += SkScalarMul(SkFixedToScalar(fPrevAdvance + fAutoKern.adjust(glyph))
, fScale); | 2307 fXPos += SkScalarMul(fPrevAdvance + fAutoKern.adjust(glyph), fScale); |
2323 fPrevAdvance = advance(glyph, fXYIndex); // + fPaint.getTextTracking(); | 2308 fPrevAdvance = advance(glyph, fXYIndex); // + fPaint.getTextTracking(); |
2324 if (fCache->findPath(glyph)) { | 2309 if (fCache->findPath(glyph)) { |
2325 fCache->findIntercepts(fBounds, fScale, fXPos, SkToBool(fXYIndex), | 2310 fCache->findIntercepts(fBounds, fScale, fXPos, SkToBool(fXYIndex), |
2326 const_cast<SkGlyph*>(&glyph), array, count); | 2311 const_cast<SkGlyph*>(&glyph), array, count); |
2327 } | 2312 } |
2328 return fText < fStop; | 2313 return fText < fStop; |
2329 } | 2314 } |
2330 | 2315 |
2331 /////////////////////////////////////////////////////////////////////////////// | 2316 /////////////////////////////////////////////////////////////////////////////// |
2332 | 2317 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2368 } | 2353 } |
2369 | 2354 |
2370 uint32_t SkPaint::getHash() const { | 2355 uint32_t SkPaint::getHash() const { |
2371 // We're going to hash 10 pointers and 7 32-bit values, finishing up with fB
itfields, | 2356 // We're going to hash 10 pointers and 7 32-bit values, finishing up with fB
itfields, |
2372 // so fBitfields should be 10 pointers and 6 32-bit values from the start. | 2357 // so fBitfields should be 10 pointers and 6 32-bit values from the start. |
2373 static_assert(offsetof(SkPaint, fBitfields) == 9 * sizeof(void*) + 6 * sizeo
f(uint32_t), | 2358 static_assert(offsetof(SkPaint, fBitfields) == 9 * sizeof(void*) + 6 * sizeo
f(uint32_t), |
2374 "SkPaint_notPackedTightly"); | 2359 "SkPaint_notPackedTightly"); |
2375 return SkChecksum::Murmur3(reinterpret_cast<const uint32_t*>(this), | 2360 return SkChecksum::Murmur3(reinterpret_cast<const uint32_t*>(this), |
2376 offsetof(SkPaint, fBitfields) + sizeof(fBitfields
)); | 2361 offsetof(SkPaint, fBitfields) + sizeof(fBitfields
)); |
2377 } | 2362 } |
OLD | NEW |