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) co nst { | |
1446 // we don't cache hairlines in the cache | |
robertphillips
2013/11/25 20:39:44
line up? or 1 line?
Shouldn't this comment be "//
| |
1447 if (SkPaint::kStroke_Style == paint.getStyle() && | |
1448 0 == paint.getStrokeWidth()) { | |
1449 return true; | |
1450 } | |
1451 | |
1452 // we don't cache perspective | |
1453 if (ctm.hasPerspective()) { | |
1454 return true; | |
1455 } | |
1456 | |
1457 SkMatrix textM; | |
1458 return SkPaint::TooBigToUseCache(ctm, *paint.setTextMatrix(&textM)); | |
1459 } | |
1460 | |
1461 void SkDraw::drawText_asPaths(const char text[], size_t byteLength, | 1461 void SkDraw::drawText_asPaths(const char text[], size_t byteLength, |
1462 SkScalar x, SkScalar y, | 1462 SkScalar x, SkScalar y, |
1463 const SkPaint& paint) const { | 1463 const SkPaint& paint) const { |
1464 SkDEBUGCODE(this->validate();) | 1464 SkDEBUGCODE(this->validate();) |
1465 | 1465 |
1466 SkTextToPathIter iter(text, byteLength, paint, true); | 1466 SkTextToPathIter iter(text, byteLength, paint, true); |
1467 | 1467 |
1468 SkMatrix matrix; | 1468 SkMatrix matrix; |
1469 matrix.setScale(iter.getPathScale(), iter.getPathScale()); | 1469 matrix.setScale(iter.getPathScale(), iter.getPathScale()); |
1470 matrix.postTranslate(x, y); | 1470 matrix.postTranslate(x, y); |
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1701 SkASSERT(byteLength == 0 || text != NULL); | 1701 SkASSERT(byteLength == 0 || text != NULL); |
1702 | 1702 |
1703 SkDEBUGCODE(this->validate();) | 1703 SkDEBUGCODE(this->validate();) |
1704 | 1704 |
1705 // nothing to draw | 1705 // nothing to draw |
1706 if (text == NULL || byteLength == 0 || fRC->isEmpty()) { | 1706 if (text == NULL || byteLength == 0 || fRC->isEmpty()) { |
1707 return; | 1707 return; |
1708 } | 1708 } |
1709 | 1709 |
1710 // SkScalarRec doesn't currently have a way of representing hairline stroke and | 1710 // SkScalarRec doesn't currently have a way of representing hairline stroke and |
1711 // will fill if its frame-width is 0. | 1711 // will fill if its frame-width is 0. |
robertphillips
2013/11/25 20:39:44
this->
| |
1712 if (ShouldDrawTextAsPaths(paint, *fMatrix)) { | 1712 if (shouldDrawTextAsPaths(paint, *fMatrix)) { |
1713 this->drawText_asPaths(text, byteLength, x, y, paint); | 1713 this->drawText_asPaths(text, byteLength, x, y, paint); |
1714 return; | 1714 return; |
1715 } | 1715 } |
1716 | 1716 |
1717 SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc(); | 1717 SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc(); |
1718 | 1718 |
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); | 1719 SkAutoGlyphCache autoCache(paint, &fDevice->fLeakyProperties, fMatrix); |
1736 #endif | |
1737 SkGlyphCache* cache = autoCache.getCache(); | 1720 SkGlyphCache* cache = autoCache.getCache(); |
1738 | 1721 |
1739 // transform our starting point | 1722 // transform our starting point |
1740 #if SK_DISTANCEFIELD_FONTS | |
1741 if (!(procFlags & SkDrawProcs::kSkipBakedGlyphTransform_Flag)) | |
1742 #endif | |
1743 { | 1723 { |
1744 SkPoint loc; | 1724 SkPoint loc; |
1745 fMatrix->mapXY(x, y, &loc); | 1725 fMatrix->mapXY(x, y, &loc); |
1746 x = loc.fX; | 1726 x = loc.fX; |
1747 y = loc.fY; | 1727 y = loc.fY; |
1748 } | 1728 } |
1749 | 1729 |
1750 // need to measure first | 1730 // need to measure first |
1751 if (paint.getTextAlign() != SkPaint::kLeft_Align) { | 1731 if (paint.getTextAlign() != SkPaint::kLeft_Align) { |
1752 SkVector stop; | 1732 SkVector stop; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1791 d1g.fHalfSampleY = SK_FixedHalf; | 1771 d1g.fHalfSampleY = SK_FixedHalf; |
1792 } else if (kY_SkAxisAlignment == baseline) { | 1772 } else if (kY_SkAxisAlignment == baseline) { |
1793 fxMask = 0; | 1773 fxMask = 0; |
1794 d1g.fHalfSampleX = SK_FixedHalf; | 1774 d1g.fHalfSampleX = SK_FixedHalf; |
1795 } | 1775 } |
1796 } | 1776 } |
1797 | 1777 |
1798 SkFixed fx = SkScalarToFixed(x) + d1g.fHalfSampleX; | 1778 SkFixed fx = SkScalarToFixed(x) + d1g.fHalfSampleX; |
1799 SkFixed fy = SkScalarToFixed(y) + d1g.fHalfSampleY; | 1779 SkFixed fy = SkScalarToFixed(y) + d1g.fHalfSampleY; |
1800 | 1780 |
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) { | 1781 while (text < stop) { |
1808 const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fy Mask); | 1782 const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fy Mask); |
1809 | 1783 |
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); | 1784 fx += autokern.adjust(glyph); |
1818 #endif | |
1819 | 1785 |
1820 if (glyph.fWidth) { | 1786 if (glyph.fWidth) { |
1821 proc(d1g, fx, fy, glyph); | 1787 proc(d1g, fx, fy, glyph); |
1822 } | 1788 } |
1823 | 1789 |
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; | 1790 fx += glyph.fAdvanceX; |
1834 fy += glyph.fAdvanceY; | 1791 fy += glyph.fAdvanceY; |
1835 #endif | |
1836 } | 1792 } |
1837 } | 1793 } |
1838 | 1794 |
1839 // last parameter is interpreted as SkFixed [x, y] | 1795 // last parameter is interpreted as SkFixed [x, y] |
1840 // return the fixed position, which may be rounded or not by the caller | 1796 // return the fixed position, which may be rounded or not by the caller |
1841 // e.g. subpixel doesn't round | 1797 // e.g. subpixel doesn't round |
1842 typedef void (*AlignProc)(const SkPoint&, const SkGlyph&, SkIPoint*); | 1798 typedef void (*AlignProc)(const SkPoint&, const SkGlyph&, SkIPoint*); |
1843 | 1799 |
1844 static void leftAlignProc(const SkPoint& loc, const SkGlyph& glyph, | 1800 static void leftAlignProc(const SkPoint& loc, const SkGlyph& glyph, |
1845 SkIPoint* dst) { | 1801 SkIPoint* dst) { |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1975 int scalarsPerPosition, const SkPaint& paint) const { | 1931 int scalarsPerPosition, const SkPaint& paint) const { |
1976 SkASSERT(byteLength == 0 || text != NULL); | 1932 SkASSERT(byteLength == 0 || text != NULL); |
1977 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); | 1933 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); |
1978 | 1934 |
1979 SkDEBUGCODE(this->validate();) | 1935 SkDEBUGCODE(this->validate();) |
1980 | 1936 |
1981 // nothing to draw | 1937 // nothing to draw |
1982 if (text == NULL || byteLength == 0 || fRC->isEmpty()) { | 1938 if (text == NULL || byteLength == 0 || fRC->isEmpty()) { |
1983 return; | 1939 return; |
1984 } | 1940 } |
1985 | 1941 |
robertphillips
2013/11/25 20:39:44
this->
| |
1986 if (ShouldDrawTextAsPaths(paint, *fMatrix)) { | 1942 if (shouldDrawTextAsPaths(paint, *fMatrix)) { |
1987 this->drawPosText_asPaths(text, byteLength, pos, constY, | 1943 this->drawPosText_asPaths(text, byteLength, pos, constY, |
1988 scalarsPerPosition, paint); | 1944 scalarsPerPosition, paint); |
1989 return; | 1945 return; |
1990 } | 1946 } |
1991 | 1947 |
1992 SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc(); | 1948 SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc(); |
1993 #if SK_DISTANCEFIELD_FONTS | |
1994 const SkMatrix* ctm = fMatrix; | |
1995 const SkPaint* paintRef = &paint; | |
1996 SkPaint paintCopy; | |
1997 uint32_t procFlags = fProcs ? fProcs->fFlags : 0; | |
1998 if (procFlags & SkDrawProcs::kUseScaledGlyphs_Flag) { | |
1999 paintCopy = paint; | |
2000 paintCopy.setTextSize(SkDrawProcs::kBaseDFFontSize); | |
2001 paintRef = &paintCopy; | |
2002 } | |
2003 if (procFlags & SkDrawProcs::kSkipBakedGlyphTransform_Flag) { | |
2004 ctm = &SkMatrix::I(); | |
2005 } | |
2006 SkAutoGlyphCache autoCache(*paintRef, &fDevice->fLeakyProperties, ctm); | |
2007 #else | |
2008 SkAutoGlyphCache autoCache(paint, &fDevice->fLeakyProperties, fMatrix); | 1949 SkAutoGlyphCache autoCache(paint, &fDevice->fLeakyProperties, fMatrix); |
2009 #endif | |
2010 SkGlyphCache* cache = autoCache.getCache(); | 1950 SkGlyphCache* cache = autoCache.getCache(); |
2011 | 1951 |
2012 SkAAClipBlitterWrapper wrapper; | 1952 SkAAClipBlitterWrapper wrapper; |
2013 SkAutoBlitterChoose blitterChooser; | 1953 SkAutoBlitterChoose blitterChooser; |
2014 SkBlitter* blitter = NULL; | 1954 SkBlitter* blitter = NULL; |
2015 if (needsRasterTextBlit(*this)) { | 1955 if (needsRasterTextBlit(*this)) { |
2016 blitterChooser.choose(*fBitmap, *fMatrix, paint); | 1956 blitterChooser.choose(*fBitmap, *fMatrix, paint); |
2017 blitter = blitterChooser.get(); | 1957 blitter = blitterChooser.get(); |
2018 if (fRC->isAA()) { | 1958 if (fRC->isAA()) { |
2019 wrapper.init(*fRC, blitter); | 1959 wrapper.init(*fRC, blitter); |
2020 blitter = wrapper.getBlitter(); | 1960 blitter = wrapper.getBlitter(); |
2021 } | 1961 } |
2022 } | 1962 } |
2023 | 1963 |
2024 const char* stop = text + byteLength; | 1964 const char* stop = text + byteLength; |
2025 AlignProc alignProc = pick_align_proc(paint.getTextAlign()); | 1965 AlignProc alignProc = pick_align_proc(paint.getTextAlign()); |
2026 SkDraw1Glyph d1g; | 1966 SkDraw1Glyph d1g; |
2027 SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache, paint); | 1967 SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache, paint); |
2028 #if SK_DISTANCEFIELD_FONTS | |
2029 TextMapState tms(*ctm, constY); | |
2030 #else | |
2031 TextMapState tms(*fMatrix, constY); | 1968 TextMapState tms(*fMatrix, constY); |
2032 #endif | |
2033 TextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition); | 1969 TextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition); |
2034 | 1970 |
2035 if (cache->isSubpixel()) { | 1971 if (cache->isSubpixel()) { |
2036 // maybe we should skip the rounding if linearText is set | 1972 // maybe we should skip the rounding if linearText is set |
2037 SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(*fMatrix); | 1973 SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(*fMatrix); |
2038 | 1974 |
2039 SkFixed fxMask = ~0; | 1975 SkFixed fxMask = ~0; |
2040 SkFixed fyMask = ~0; | 1976 SkFixed fyMask = ~0; |
2041 if (kX_SkAxisAlignment == baseline) { | 1977 if (kX_SkAxisAlignment == baseline) { |
2042 fyMask = 0; | 1978 fyMask = 0; |
2043 #ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX | 1979 #ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX |
2044 d1g.fHalfSampleY = SK_FixedHalf; | 1980 d1g.fHalfSampleY = SK_FixedHalf; |
2045 #endif | 1981 #endif |
2046 } else if (kY_SkAxisAlignment == baseline) { | 1982 } else if (kY_SkAxisAlignment == baseline) { |
2047 fxMask = 0; | 1983 fxMask = 0; |
2048 #ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX | 1984 #ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX |
2049 d1g.fHalfSampleX = SK_FixedHalf; | 1985 d1g.fHalfSampleX = SK_FixedHalf; |
2050 #endif | 1986 #endif |
2051 } | 1987 } |
2052 | 1988 |
2053 if (SkPaint::kLeft_Align == paint.getTextAlign()) { | 1989 if (SkPaint::kLeft_Align == paint.getTextAlign()) { |
2054 while (text < stop) { | 1990 while (text < stop) { |
2055 #if SK_DISTANCEFIELD_FONTS | |
2056 if (procFlags & SkDrawProcs::kSkipBakedGlyphTransform_Flag) { | |
2057 tms.fLoc.fX = *pos; | |
2058 tms.fLoc.fY = *(pos+1); | |
2059 } else { | |
2060 tmsProc(tms, pos); | |
2061 } | |
2062 #else | |
2063 tmsProc(tms, pos); | 1991 tmsProc(tms, pos); |
2064 #endif | |
2065 SkFixed fx = SkScalarToFixed(tms.fLoc.fX) + d1g.fHalfSampleX; | 1992 SkFixed fx = SkScalarToFixed(tms.fLoc.fX) + d1g.fHalfSampleX; |
2066 SkFixed fy = SkScalarToFixed(tms.fLoc.fY) + d1g.fHalfSampleY; | 1993 SkFixed fy = SkScalarToFixed(tms.fLoc.fY) + d1g.fHalfSampleY; |
2067 | 1994 |
2068 const SkGlyph& glyph = glyphCacheProc(cache, &text, | 1995 const SkGlyph& glyph = glyphCacheProc(cache, &text, |
2069 fx & fxMask, fy & fyMask); | 1996 fx & fxMask, fy & fyMask); |
2070 | 1997 |
2071 if (glyph.fWidth) { | 1998 if (glyph.fWidth) { |
2072 proc(d1g, fx, fy, glyph); | 1999 proc(d1g, fx, fy, glyph); |
2073 } | 2000 } |
2074 pos += scalarsPerPosition; | 2001 pos += scalarsPerPosition; |
(...skipping 797 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2872 mask->fImage = SkMask::AllocImage(size); | 2799 mask->fImage = SkMask::AllocImage(size); |
2873 memset(mask->fImage, 0, mask->computeImageSize()); | 2800 memset(mask->fImage, 0, mask->computeImageSize()); |
2874 } | 2801 } |
2875 | 2802 |
2876 if (SkMask::kJustComputeBounds_CreateMode != mode) { | 2803 if (SkMask::kJustComputeBounds_CreateMode != mode) { |
2877 draw_into_mask(*mask, devPath, style); | 2804 draw_into_mask(*mask, devPath, style); |
2878 } | 2805 } |
2879 | 2806 |
2880 return true; | 2807 return true; |
2881 } | 2808 } |
OLD | NEW |