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 "SkDraw.h" | 8 #include "SkDraw.h" |
9 #include "SkBlitter.h" | 9 #include "SkBlitter.h" |
10 #include "SkBounder.h" | 10 #include "SkBounder.h" |
(...skipping 14 matching lines...) Expand all Loading... |
25 #include "SkStroke.h" | 25 #include "SkStroke.h" |
26 #include "SkTemplatesPriv.h" | 26 #include "SkTemplatesPriv.h" |
27 #include "SkTLazy.h" | 27 #include "SkTLazy.h" |
28 #include "SkUtils.h" | 28 #include "SkUtils.h" |
29 | 29 |
30 #include "SkAutoKern.h" | 30 #include "SkAutoKern.h" |
31 #include "SkBitmapProcShader.h" | 31 #include "SkBitmapProcShader.h" |
32 #include "SkDrawProcs.h" | 32 #include "SkDrawProcs.h" |
33 #include "SkMatrixUtils.h" | 33 #include "SkMatrixUtils.h" |
34 | 34 |
35 bool SkDraw::ShouldDrawTextAsPaths(const SkPaint& paint, const SkMatrix& ctm) { | |
36 // we don't cache hairlines in the cache | |
37 if (SkPaint::kStroke_Style == paint.getStyle() && | |
38 0 == paint.getStrokeWidth()) { | |
39 return true; | |
40 } | |
41 | |
42 // we don't cache perspective | |
43 if (ctm.hasPerspective()) { | |
44 return true; | |
45 } | |
46 | |
47 SkMatrix textM; | |
48 return SkPaint::TooBigToUseCache(ctm, *paint.setTextMatrix(&textM)); | |
49 } | |
50 | |
51 //#define TRACE_BITMAP_DRAWS | 35 //#define TRACE_BITMAP_DRAWS |
52 | 36 |
53 #define kBlitterStorageLongCount (sizeof(SkBitmapProcShader) >> 2) | 37 #define kBlitterStorageLongCount (sizeof(SkBitmapProcShader) >> 2) |
54 | 38 |
55 /** Helper for allocating small blitters on the stack. | 39 /** Helper for allocating small blitters on the stack. |
56 */ | 40 */ |
57 class SkAutoBlitterChoose : SkNoncopyable { | 41 class SkAutoBlitterChoose : SkNoncopyable { |
58 public: | 42 public: |
59 SkAutoBlitterChoose() { | 43 SkAutoBlitterChoose() { |
60 fBlitter = NULL; | 44 fBlitter = NULL; |
(...skipping 1390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1451 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); | 1435 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); |
1452 | 1436 |
1453 x += autokern.adjust(glyph) + glyph.fAdvanceX; | 1437 x += autokern.adjust(glyph) + glyph.fAdvanceX; |
1454 y += glyph.fAdvanceY; | 1438 y += glyph.fAdvanceY; |
1455 } | 1439 } |
1456 stopVector->set(SkFixedToScalar(x), SkFixedToScalar(y)); | 1440 stopVector->set(SkFixedToScalar(x), SkFixedToScalar(y)); |
1457 | 1441 |
1458 SkASSERT(text == stop); | 1442 SkASSERT(text == stop); |
1459 } | 1443 } |
1460 | 1444 |
| 1445 bool SkDraw::ShouldDrawTextAsPaths(const SkPaint& paint, const SkMatrix& ctm) { |
| 1446 // hairline glyphs are fast enough so we don't need to cache them |
| 1447 if (SkPaint::kStroke_Style == paint.getStyle() && 0 == paint.getStrokeWidth(
)) { |
| 1448 return true; |
| 1449 } |
| 1450 |
| 1451 // we don't cache perspective |
| 1452 if (ctm.hasPerspective()) { |
| 1453 return true; |
| 1454 } |
| 1455 |
| 1456 SkMatrix textM; |
| 1457 return SkPaint::TooBigToUseCache(ctm, *paint.setTextMatrix(&textM)); |
| 1458 } |
| 1459 |
1461 void SkDraw::drawText_asPaths(const char text[], size_t byteLength, | 1460 void SkDraw::drawText_asPaths(const char text[], size_t byteLength, |
1462 SkScalar x, SkScalar y, | 1461 SkScalar x, SkScalar y, |
1463 const SkPaint& paint) const { | 1462 const SkPaint& paint) const { |
1464 SkDEBUGCODE(this->validate();) | 1463 SkDEBUGCODE(this->validate();) |
1465 | 1464 |
1466 SkTextToPathIter iter(text, byteLength, paint, true); | 1465 SkTextToPathIter iter(text, byteLength, paint, true); |
1467 | 1466 |
1468 SkMatrix matrix; | 1467 SkMatrix matrix; |
1469 matrix.setScale(iter.getPathScale(), iter.getPathScale()); | 1468 matrix.setScale(iter.getPathScale(), iter.getPathScale()); |
1470 matrix.postTranslate(x, y); | 1469 matrix.postTranslate(x, y); |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1709 | 1708 |
1710 // SkScalarRec doesn't currently have a way of representing hairline stroke
and | 1709 // SkScalarRec doesn't currently have a way of representing hairline stroke
and |
1711 // will fill if its frame-width is 0. | 1710 // will fill if its frame-width is 0. |
1712 if (ShouldDrawTextAsPaths(paint, *fMatrix)) { | 1711 if (ShouldDrawTextAsPaths(paint, *fMatrix)) { |
1713 this->drawText_asPaths(text, byteLength, x, y, paint); | 1712 this->drawText_asPaths(text, byteLength, x, y, paint); |
1714 return; | 1713 return; |
1715 } | 1714 } |
1716 | 1715 |
1717 SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc(); | 1716 SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc(); |
1718 | 1717 |
1719 #if SK_DISTANCEFIELD_FONTS | |
1720 const SkMatrix* ctm = fMatrix; | |
1721 const SkPaint* paintRef = &paint; | |
1722 SkPaint paintCopy; | |
1723 uint32_t procFlags = fProcs ? fProcs->fFlags : 0; | |
1724 if (procFlags & SkDrawProcs::kUseScaledGlyphs_Flag) { | |
1725 paintCopy = paint; | |
1726 paintCopy.setTextSize(SkDrawProcs::kBaseDFFontSize); | |
1727 paintCopy.setLCDRenderText(false); | |
1728 paintRef = &paintCopy; | |
1729 } | |
1730 if (procFlags & SkDrawProcs::kSkipBakedGlyphTransform_Flag) { | |
1731 ctm = NULL; | |
1732 } | |
1733 SkAutoGlyphCache autoCache(*paintRef, &fDevice->fLeakyProperties, ctm); | |
1734 #else | |
1735 SkAutoGlyphCache autoCache(paint, &fDevice->fLeakyProperties, fMatrix); | 1718 SkAutoGlyphCache autoCache(paint, &fDevice->fLeakyProperties, fMatrix); |
1736 #endif | |
1737 SkGlyphCache* cache = autoCache.getCache(); | 1719 SkGlyphCache* cache = autoCache.getCache(); |
1738 | 1720 |
1739 // transform our starting point | 1721 // transform our starting point |
1740 #if SK_DISTANCEFIELD_FONTS | |
1741 if (!(procFlags & SkDrawProcs::kSkipBakedGlyphTransform_Flag)) | |
1742 #endif | |
1743 { | 1722 { |
1744 SkPoint loc; | 1723 SkPoint loc; |
1745 fMatrix->mapXY(x, y, &loc); | 1724 fMatrix->mapXY(x, y, &loc); |
1746 x = loc.fX; | 1725 x = loc.fX; |
1747 y = loc.fY; | 1726 y = loc.fY; |
1748 } | 1727 } |
1749 | 1728 |
1750 // need to measure first | 1729 // need to measure first |
1751 if (paint.getTextAlign() != SkPaint::kLeft_Align) { | 1730 if (paint.getTextAlign() != SkPaint::kLeft_Align) { |
1752 SkVector stop; | 1731 SkVector stop; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1791 d1g.fHalfSampleY = SK_FixedHalf; | 1770 d1g.fHalfSampleY = SK_FixedHalf; |
1792 } else if (kY_SkAxisAlignment == baseline) { | 1771 } else if (kY_SkAxisAlignment == baseline) { |
1793 fxMask = 0; | 1772 fxMask = 0; |
1794 d1g.fHalfSampleX = SK_FixedHalf; | 1773 d1g.fHalfSampleX = SK_FixedHalf; |
1795 } | 1774 } |
1796 } | 1775 } |
1797 | 1776 |
1798 SkFixed fx = SkScalarToFixed(x) + d1g.fHalfSampleX; | 1777 SkFixed fx = SkScalarToFixed(x) + d1g.fHalfSampleX; |
1799 SkFixed fy = SkScalarToFixed(y) + d1g.fHalfSampleY; | 1778 SkFixed fy = SkScalarToFixed(y) + d1g.fHalfSampleY; |
1800 | 1779 |
1801 #if SK_DISTANCEFIELD_FONTS | |
1802 SkFixed fixedScale; | |
1803 if (procFlags & SkDrawProcs::kUseScaledGlyphs_Flag) { | |
1804 fixedScale = SkScalarToFixed(paint.getTextSize()/(float)SkDrawProcs::kBa
seDFFontSize); | |
1805 } | |
1806 #endif | |
1807 while (text < stop) { | 1780 while (text < stop) { |
1808 const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fy
Mask); | 1781 const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fy
Mask); |
1809 | 1782 |
1810 #if SK_DISTANCEFIELD_FONTS | |
1811 if (procFlags & SkDrawProcs::kUseScaledGlyphs_Flag) { | |
1812 fx += SkFixedMul_portable(autokern.adjust(glyph), fixedScale); | |
1813 } else { | |
1814 fx += autokern.adjust(glyph); | |
1815 } | |
1816 #else | |
1817 fx += autokern.adjust(glyph); | 1783 fx += autokern.adjust(glyph); |
1818 #endif | |
1819 | 1784 |
1820 if (glyph.fWidth) { | 1785 if (glyph.fWidth) { |
1821 proc(d1g, fx, fy, glyph); | 1786 proc(d1g, fx, fy, glyph); |
1822 } | 1787 } |
1823 | 1788 |
1824 #if SK_DISTANCEFIELD_FONTS | |
1825 if (procFlags & SkDrawProcs::kUseScaledGlyphs_Flag) { | |
1826 fx += SkFixedMul_portable(glyph.fAdvanceX, fixedScale); | |
1827 fy += SkFixedMul_portable(glyph.fAdvanceY, fixedScale); | |
1828 } else { | |
1829 fx += glyph.fAdvanceX; | |
1830 fy += glyph.fAdvanceY; | |
1831 } | |
1832 #else | |
1833 fx += glyph.fAdvanceX; | 1789 fx += glyph.fAdvanceX; |
1834 fy += glyph.fAdvanceY; | 1790 fy += glyph.fAdvanceY; |
1835 #endif | |
1836 } | 1791 } |
1837 } | 1792 } |
1838 | 1793 |
1839 // last parameter is interpreted as SkFixed [x, y] | 1794 // last parameter is interpreted as SkFixed [x, y] |
1840 // return the fixed position, which may be rounded or not by the caller | 1795 // return the fixed position, which may be rounded or not by the caller |
1841 // e.g. subpixel doesn't round | 1796 // e.g. subpixel doesn't round |
1842 typedef void (*AlignProc)(const SkPoint&, const SkGlyph&, SkIPoint*); | 1797 typedef void (*AlignProc)(const SkPoint&, const SkGlyph&, SkIPoint*); |
1843 | 1798 |
1844 static void leftAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* ds
t) { | 1799 static void leftAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* ds
t) { |
1845 dst->set(SkScalarToFixed(loc.fX), SkScalarToFixed(loc.fY)); | 1800 dst->set(SkScalarToFixed(loc.fX), SkScalarToFixed(loc.fY)); |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2006 return; | 1961 return; |
2007 } | 1962 } |
2008 | 1963 |
2009 if (ShouldDrawTextAsPaths(paint, *fMatrix)) { | 1964 if (ShouldDrawTextAsPaths(paint, *fMatrix)) { |
2010 this->drawPosText_asPaths(text, byteLength, pos, constY, | 1965 this->drawPosText_asPaths(text, byteLength, pos, constY, |
2011 scalarsPerPosition, paint); | 1966 scalarsPerPosition, paint); |
2012 return; | 1967 return; |
2013 } | 1968 } |
2014 | 1969 |
2015 SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc(); | 1970 SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc(); |
2016 #if SK_DISTANCEFIELD_FONTS | |
2017 const SkMatrix* ctm = fMatrix; | |
2018 const SkPaint* paintRef = &paint; | |
2019 SkPaint paintCopy; | |
2020 uint32_t procFlags = fProcs ? fProcs->fFlags : 0; | |
2021 if (procFlags & SkDrawProcs::kUseScaledGlyphs_Flag) { | |
2022 paintCopy = paint; | |
2023 paintCopy.setTextSize(SkDrawProcs::kBaseDFFontSize); | |
2024 paintRef = &paintCopy; | |
2025 } | |
2026 if (procFlags & SkDrawProcs::kSkipBakedGlyphTransform_Flag) { | |
2027 ctm = &SkMatrix::I(); | |
2028 } | |
2029 SkAutoGlyphCache autoCache(*paintRef, &fDevice->fLeakyProperties, ctm); | |
2030 #else | |
2031 SkAutoGlyphCache autoCache(paint, &fDevice->fLeakyProperties, fMatrix); | 1971 SkAutoGlyphCache autoCache(paint, &fDevice->fLeakyProperties, fMatrix); |
2032 #endif | |
2033 SkGlyphCache* cache = autoCache.getCache(); | 1972 SkGlyphCache* cache = autoCache.getCache(); |
2034 | 1973 |
2035 SkAAClipBlitterWrapper wrapper; | 1974 SkAAClipBlitterWrapper wrapper; |
2036 SkAutoBlitterChoose blitterChooser; | 1975 SkAutoBlitterChoose blitterChooser; |
2037 SkBlitter* blitter = NULL; | 1976 SkBlitter* blitter = NULL; |
2038 if (needsRasterTextBlit(*this)) { | 1977 if (needsRasterTextBlit(*this)) { |
2039 blitterChooser.choose(*fBitmap, *fMatrix, paint); | 1978 blitterChooser.choose(*fBitmap, *fMatrix, paint); |
2040 blitter = blitterChooser.get(); | 1979 blitter = blitterChooser.get(); |
2041 if (fRC->isAA()) { | 1980 if (fRC->isAA()) { |
2042 wrapper.init(*fRC, blitter); | 1981 wrapper.init(*fRC, blitter); |
2043 blitter = wrapper.getBlitter(); | 1982 blitter = wrapper.getBlitter(); |
2044 } | 1983 } |
2045 } | 1984 } |
2046 | 1985 |
2047 const char* stop = text + byteLength; | 1986 const char* stop = text + byteLength; |
2048 AlignProc alignProc = pick_align_proc(paint.getTextAlign()); | 1987 AlignProc alignProc = pick_align_proc(paint.getTextAlign()); |
2049 SkDraw1Glyph d1g; | 1988 SkDraw1Glyph d1g; |
2050 SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache, paint); | 1989 SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache, paint); |
2051 #if SK_DISTANCEFIELD_FONTS | |
2052 TextMapState tms(*ctm, constY); | |
2053 #else | |
2054 TextMapState tms(*fMatrix, constY); | 1990 TextMapState tms(*fMatrix, constY); |
2055 #endif | |
2056 TextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition); | 1991 TextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition); |
2057 | 1992 |
2058 if (cache->isSubpixel()) { | 1993 if (cache->isSubpixel()) { |
2059 // maybe we should skip the rounding if linearText is set | 1994 // maybe we should skip the rounding if linearText is set |
2060 SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(*fMatrix); | 1995 SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(*fMatrix); |
2061 | 1996 |
2062 SkFixed fxMask = ~0; | 1997 SkFixed fxMask = ~0; |
2063 SkFixed fyMask = ~0; | 1998 SkFixed fyMask = ~0; |
2064 if (kX_SkAxisAlignment == baseline) { | 1999 if (kX_SkAxisAlignment == baseline) { |
2065 fyMask = 0; | 2000 fyMask = 0; |
2066 #ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX | 2001 #ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX |
2067 d1g.fHalfSampleY = SK_FixedHalf; | 2002 d1g.fHalfSampleY = SK_FixedHalf; |
2068 #endif | 2003 #endif |
2069 } else if (kY_SkAxisAlignment == baseline) { | 2004 } else if (kY_SkAxisAlignment == baseline) { |
2070 fxMask = 0; | 2005 fxMask = 0; |
2071 #ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX | 2006 #ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX |
2072 d1g.fHalfSampleX = SK_FixedHalf; | 2007 d1g.fHalfSampleX = SK_FixedHalf; |
2073 #endif | 2008 #endif |
2074 } | 2009 } |
2075 | 2010 |
2076 if (SkPaint::kLeft_Align == paint.getTextAlign()) { | 2011 if (SkPaint::kLeft_Align == paint.getTextAlign()) { |
2077 while (text < stop) { | 2012 while (text < stop) { |
2078 #if SK_DISTANCEFIELD_FONTS | |
2079 if (procFlags & SkDrawProcs::kSkipBakedGlyphTransform_Flag) { | |
2080 tms.fLoc.fX = *pos; | |
2081 tms.fLoc.fY = *(pos+1); | |
2082 } else { | |
2083 tmsProc(tms, pos); | |
2084 } | |
2085 #else | |
2086 tmsProc(tms, pos); | 2013 tmsProc(tms, pos); |
2087 #endif | |
2088 SkFixed fx = SkScalarToFixed(tms.fLoc.fX) + d1g.fHalfSampleX; | 2014 SkFixed fx = SkScalarToFixed(tms.fLoc.fX) + d1g.fHalfSampleX; |
2089 SkFixed fy = SkScalarToFixed(tms.fLoc.fY) + d1g.fHalfSampleY; | 2015 SkFixed fy = SkScalarToFixed(tms.fLoc.fY) + d1g.fHalfSampleY; |
2090 | 2016 |
2091 const SkGlyph& glyph = glyphCacheProc(cache, &text, | 2017 const SkGlyph& glyph = glyphCacheProc(cache, &text, |
2092 fx & fxMask, fy & fyMask); | 2018 fx & fxMask, fy & fyMask); |
2093 | 2019 |
2094 if (glyph.fWidth) { | 2020 if (glyph.fWidth) { |
2095 proc(d1g, fx, fy, glyph); | 2021 proc(d1g, fx, fy, glyph); |
2096 } | 2022 } |
2097 pos += scalarsPerPosition; | 2023 pos += scalarsPerPosition; |
(...skipping 797 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2895 mask->fImage = SkMask::AllocImage(size); | 2821 mask->fImage = SkMask::AllocImage(size); |
2896 memset(mask->fImage, 0, mask->computeImageSize()); | 2822 memset(mask->fImage, 0, mask->computeImageSize()); |
2897 } | 2823 } |
2898 | 2824 |
2899 if (SkMask::kJustComputeBounds_CreateMode != mode) { | 2825 if (SkMask::kJustComputeBounds_CreateMode != mode) { |
2900 draw_into_mask(*mask, devPath, style); | 2826 draw_into_mask(*mask, devPath, style); |
2901 } | 2827 } |
2902 | 2828 |
2903 return true; | 2829 return true; |
2904 } | 2830 } |
OLD | NEW |