Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(304)

Side by Side Diff: src/core/SkDraw.cpp

Issue 335573002: Extract "text align proc" functions as reusable classes (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: address review comments Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « gyp/core.gypi ('k') | src/core/SkDrawProcs.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "SkCanvas.h" 10 #include "SkCanvas.h"
11 #include "SkColorPriv.h" 11 #include "SkColorPriv.h"
12 #include "SkDevice.h" 12 #include "SkDevice.h"
13 #include "SkDeviceLooper.h" 13 #include "SkDeviceLooper.h"
14 #include "SkFixed.h" 14 #include "SkFixed.h"
15 #include "SkMaskFilter.h" 15 #include "SkMaskFilter.h"
16 #include "SkPaint.h" 16 #include "SkPaint.h"
17 #include "SkPathEffect.h" 17 #include "SkPathEffect.h"
18 #include "SkRasterClip.h" 18 #include "SkRasterClip.h"
19 #include "SkRasterizer.h" 19 #include "SkRasterizer.h"
20 #include "SkRRect.h" 20 #include "SkRRect.h"
21 #include "SkScan.h" 21 #include "SkScan.h"
22 #include "SkShader.h" 22 #include "SkShader.h"
23 #include "SkSmallAllocator.h" 23 #include "SkSmallAllocator.h"
24 #include "SkString.h" 24 #include "SkString.h"
25 #include "SkStroke.h" 25 #include "SkStroke.h"
26 #include "SkTextMapStateProc.h"
26 #include "SkTLazy.h" 27 #include "SkTLazy.h"
27 #include "SkUtils.h" 28 #include "SkUtils.h"
28 #include "SkVertState.h" 29 #include "SkVertState.h"
29 30
30 #include "SkAutoKern.h" 31 #include "SkAutoKern.h"
31 #include "SkBitmapProcShader.h" 32 #include "SkBitmapProcShader.h"
32 #include "SkDrawProcs.h" 33 #include "SkDrawProcs.h"
33 #include "SkMatrixUtils.h" 34 #include "SkMatrixUtils.h"
34 35
35 36
(...skipping 1595 matching lines...) Expand 10 before | Expand all | Expand 10 after
1631 1632
1632 if (glyph.fWidth) { 1633 if (glyph.fWidth) {
1633 proc(d1g, fx, fy, glyph); 1634 proc(d1g, fx, fy, glyph);
1634 } 1635 }
1635 1636
1636 fx += glyph.fAdvanceX; 1637 fx += glyph.fAdvanceX;
1637 fy += glyph.fAdvanceY; 1638 fy += glyph.fAdvanceY;
1638 } 1639 }
1639 } 1640 }
1640 1641
1641 // last parameter is interpreted as SkFixed [x, y]
1642 // return the fixed position, which may be rounded or not by the caller
1643 // e.g. subpixel doesn't round
1644 typedef void (*AlignProc)(const SkPoint&, const SkGlyph&, SkIPoint*);
1645
1646 static void leftAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* ds t) {
1647 dst->set(SkScalarToFixed(loc.fX), SkScalarToFixed(loc.fY));
1648 }
1649
1650 static void centerAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* dst) {
1651 dst->set(SkScalarToFixed(loc.fX) - (glyph.fAdvanceX >> 1),
1652 SkScalarToFixed(loc.fY) - (glyph.fAdvanceY >> 1));
1653 }
1654
1655 static void rightAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* d st) {
1656 dst->set(SkScalarToFixed(loc.fX) - glyph.fAdvanceX,
1657 SkScalarToFixed(loc.fY) - glyph.fAdvanceY);
1658 }
1659
1660 static AlignProc pick_align_proc(SkPaint::Align align) {
1661 static const AlignProc gProcs[] = {
1662 leftAlignProc, centerAlignProc, rightAlignProc
1663 };
1664
1665 SkASSERT((unsigned)align < SK_ARRAY_COUNT(gProcs));
1666
1667 return gProcs[align];
1668 }
1669
1670 typedef void (*AlignProc_scalar)(const SkPoint&, const SkGlyph&, SkPoint*);
1671
1672 static void leftAlignProc_scalar(const SkPoint& loc, const SkGlyph& glyph, SkPoi nt* dst) {
1673 dst->set(loc.fX, loc.fY);
1674 }
1675
1676 static void centerAlignProc_scalar(const SkPoint& loc, const SkGlyph& glyph, SkP oint* dst) {
1677 dst->set(loc.fX - SkFixedToScalar(glyph.fAdvanceX >> 1),
1678 loc.fY - SkFixedToScalar(glyph.fAdvanceY >> 1));
1679 }
1680
1681 static void rightAlignProc_scalar(const SkPoint& loc, const SkGlyph& glyph, SkPo int* dst) {
1682 dst->set(loc.fX - SkFixedToScalar(glyph.fAdvanceX),
1683 loc.fY - SkFixedToScalar(glyph.fAdvanceY));
1684 }
1685
1686 static AlignProc_scalar pick_align_proc_scalar(SkPaint::Align align) {
1687 static const AlignProc_scalar gProcs[] = {
1688 leftAlignProc_scalar, centerAlignProc_scalar, rightAlignProc_scalar
1689 };
1690
1691 SkASSERT((unsigned)align < SK_ARRAY_COUNT(gProcs));
1692
1693 return gProcs[align];
1694 }
1695
1696 class TextMapState {
1697 public:
1698 mutable SkPoint fLoc;
1699
1700 TextMapState(const SkMatrix& matrix, SkScalar y)
1701 : fMatrix(matrix), fProc(matrix.getMapXYProc()), fY(y) {}
1702
1703 typedef void (*Proc)(const TextMapState&, const SkScalar pos[]);
1704
1705 Proc pickProc(int scalarsPerPosition);
1706
1707 private:
1708 const SkMatrix& fMatrix;
1709 SkMatrix::MapXYProc fProc;
1710 SkScalar fY; // ignored by MapXYProc
1711 // these are only used by Only... procs
1712 SkScalar fScaleX, fTransX, fTransformedY;
1713
1714 static void MapXProc(const TextMapState& state, const SkScalar pos[]) {
1715 state.fProc(state.fMatrix, *pos, state.fY, &state.fLoc);
1716 }
1717
1718 static void MapXYProc(const TextMapState& state, const SkScalar pos[]) {
1719 state.fProc(state.fMatrix, pos[0], pos[1], &state.fLoc);
1720 }
1721
1722 static void MapOnlyScaleXProc(const TextMapState& state,
1723 const SkScalar pos[]) {
1724 state.fLoc.set(SkScalarMul(state.fScaleX, *pos) + state.fTransX,
1725 state.fTransformedY);
1726 }
1727
1728 static void MapOnlyTransXProc(const TextMapState& state,
1729 const SkScalar pos[]) {
1730 state.fLoc.set(*pos + state.fTransX, state.fTransformedY);
1731 }
1732 };
1733
1734 TextMapState::Proc TextMapState::pickProc(int scalarsPerPosition) {
1735 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
1736
1737 if (1 == scalarsPerPosition) {
1738 unsigned mtype = fMatrix.getType();
1739 if (mtype & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) {
1740 return MapXProc;
1741 } else {
1742 fScaleX = fMatrix.getScaleX();
1743 fTransX = fMatrix.getTranslateX();
1744 fTransformedY = SkScalarMul(fY, fMatrix.getScaleY()) +
1745 fMatrix.getTranslateY();
1746 return (mtype & SkMatrix::kScale_Mask) ?
1747 MapOnlyScaleXProc : MapOnlyTransXProc;
1748 }
1749 } else {
1750 return MapXYProc;
1751 }
1752 }
1753
1754 ////////////////////////////////////////////////////////////////////////////// 1642 //////////////////////////////////////////////////////////////////////////////
1755 1643
1756 void SkDraw::drawPosText_asPaths(const char text[], size_t byteLength, 1644 void SkDraw::drawPosText_asPaths(const char text[], size_t byteLength,
1757 const SkScalar pos[], SkScalar constY, 1645 const SkScalar pos[], SkScalar constY,
1758 int scalarsPerPosition, 1646 int scalarsPerPosition,
1759 const SkPaint& origPaint) const { 1647 const SkPaint& origPaint) const {
1760 // setup our std paint, in hopes of getting hits in the cache 1648 // setup our std paint, in hopes of getting hits in the cache
1761 SkPaint paint(origPaint); 1649 SkPaint paint(origPaint);
1762 SkScalar matrixScale = paint.setupForAsPaths(); 1650 SkScalar matrixScale = paint.setupForAsPaths();
1763 1651
1764 SkMatrix matrix; 1652 SkMatrix matrix;
1765 matrix.setScale(matrixScale, matrixScale); 1653 matrix.setScale(matrixScale, matrixScale);
1766 1654
1767 // Temporarily jam in kFill, so we only ever ask for the raw outline from th e cache. 1655 // Temporarily jam in kFill, so we only ever ask for the raw outline from th e cache.
1768 paint.setStyle(SkPaint::kFill_Style); 1656 paint.setStyle(SkPaint::kFill_Style);
1769 paint.setPathEffect(NULL); 1657 paint.setPathEffect(NULL);
1770 1658
1771 SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc(); 1659 SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc();
1772 SkAutoGlyphCache autoCache(paint, NULL, NULL); 1660 SkAutoGlyphCache autoCache(paint, NULL, NULL);
1773 SkGlyphCache* cache = autoCache.getCache(); 1661 SkGlyphCache* cache = autoCache.getCache();
1774 1662
1775 const char* stop = text + byteLength; 1663 const char* stop = text + byteLength;
1776 AlignProc_scalar alignProc = pick_align_proc_scalar(paint.getTextAlign()); 1664 SkTextAlignProcScalar alignProc(paint.getTextAlign());
1777 TextMapState tms(SkMatrix::I(), constY); 1665 SkTextMapStateProc tmsProc(SkMatrix::I(), constY, scalarsPerPosition);
1778 TextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition);
1779 1666
1780 // Now restore the original settings, so we "draw" with whatever style/strok ing. 1667 // Now restore the original settings, so we "draw" with whatever style/strok ing.
1781 paint.setStyle(origPaint.getStyle()); 1668 paint.setStyle(origPaint.getStyle());
1782 paint.setPathEffect(origPaint.getPathEffect()); 1669 paint.setPathEffect(origPaint.getPathEffect());
1783 1670
1784 while (text < stop) { 1671 while (text < stop) {
1785 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); 1672 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
1786 if (glyph.fWidth) { 1673 if (glyph.fWidth) {
1787 const SkPath* path = cache->findPath(glyph); 1674 const SkPath* path = cache->findPath(glyph);
1788 if (path) { 1675 if (path) {
1789 tmsProc(tms, pos); 1676 SkPoint tmsLoc;
1677 tmsProc(pos, &tmsLoc);
1790 SkPoint loc; 1678 SkPoint loc;
1791 alignProc(tms.fLoc, glyph, &loc); 1679 alignProc(tmsLoc, glyph, &loc);
1792 1680
1793 matrix[SkMatrix::kMTransX] = loc.fX; 1681 matrix[SkMatrix::kMTransX] = loc.fX;
1794 matrix[SkMatrix::kMTransY] = loc.fY; 1682 matrix[SkMatrix::kMTransY] = loc.fY;
1795 if (fDevice) { 1683 if (fDevice) {
1796 fDevice->drawPath(*this, *path, paint, &matrix, false); 1684 fDevice->drawPath(*this, *path, paint, &matrix, false);
1797 } else { 1685 } else {
1798 this->drawPath(*path, paint, &matrix, false); 1686 this->drawPath(*path, paint, &matrix, false);
1799 } 1687 }
1800 } 1688 }
1801 } 1689 }
(...skipping 30 matching lines...) Expand all
1832 if (needsRasterTextBlit(*this)) { 1720 if (needsRasterTextBlit(*this)) {
1833 blitterChooser.choose(*fBitmap, *fMatrix, paint); 1721 blitterChooser.choose(*fBitmap, *fMatrix, paint);
1834 blitter = blitterChooser.get(); 1722 blitter = blitterChooser.get();
1835 if (fRC->isAA()) { 1723 if (fRC->isAA()) {
1836 wrapper.init(*fRC, blitter); 1724 wrapper.init(*fRC, blitter);
1837 blitter = wrapper.getBlitter(); 1725 blitter = wrapper.getBlitter();
1838 } 1726 }
1839 } 1727 }
1840 1728
1841 const char* stop = text + byteLength; 1729 const char* stop = text + byteLength;
1842 AlignProc alignProc = pick_align_proc(paint.getTextAlign()); 1730 SkTextAlignProc alignProc(paint.getTextAlign());
1843 SkDraw1Glyph d1g; 1731 SkDraw1Glyph d1g;
1844 SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache, paint); 1732 SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache, paint);
1845 TextMapState tms(*fMatrix, constY); 1733 SkTextMapStateProc tmsProc(*fMatrix, constY, scalarsPerPosition);
1846 TextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition);
1847 1734
1848 if (cache->isSubpixel()) { 1735 if (cache->isSubpixel()) {
1849 // maybe we should skip the rounding if linearText is set 1736 // maybe we should skip the rounding if linearText is set
1850 SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(*fMatrix); 1737 SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(*fMatrix);
1851 1738
1852 SkFixed fxMask = ~0; 1739 SkFixed fxMask = ~0;
1853 SkFixed fyMask = ~0; 1740 SkFixed fyMask = ~0;
1854 if (kX_SkAxisAlignment == baseline) { 1741 if (kX_SkAxisAlignment == baseline) {
1855 fyMask = 0; 1742 fyMask = 0;
1856 #ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX 1743 #ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX
1857 d1g.fHalfSampleY = SK_FixedHalf; 1744 d1g.fHalfSampleY = SK_FixedHalf;
1858 #endif 1745 #endif
1859 } else if (kY_SkAxisAlignment == baseline) { 1746 } else if (kY_SkAxisAlignment == baseline) {
1860 fxMask = 0; 1747 fxMask = 0;
1861 #ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX 1748 #ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX
1862 d1g.fHalfSampleX = SK_FixedHalf; 1749 d1g.fHalfSampleX = SK_FixedHalf;
1863 #endif 1750 #endif
1864 } 1751 }
1865 1752
1866 if (SkPaint::kLeft_Align == paint.getTextAlign()) { 1753 if (SkPaint::kLeft_Align == paint.getTextAlign()) {
1867 while (text < stop) { 1754 while (text < stop) {
1868 tmsProc(tms, pos); 1755 SkPoint tmsLoc;
1869 SkFixed fx = SkScalarToFixed(tms.fLoc.fX) + d1g.fHalfSampleX; 1756 tmsProc(pos, &tmsLoc);
1870 SkFixed fy = SkScalarToFixed(tms.fLoc.fY) + d1g.fHalfSampleY; 1757 SkFixed fx = SkScalarToFixed(tmsLoc.fX) + d1g.fHalfSampleX;
1758 SkFixed fy = SkScalarToFixed(tmsLoc.fY) + d1g.fHalfSampleY;
1871 1759
1872 const SkGlyph& glyph = glyphCacheProc(cache, &text, 1760 const SkGlyph& glyph = glyphCacheProc(cache, &text,
1873 fx & fxMask, fy & fyMask); 1761 fx & fxMask, fy & fyMask);
1874 1762
1875 if (glyph.fWidth) { 1763 if (glyph.fWidth) {
1876 proc(d1g, fx, fy, glyph); 1764 proc(d1g, fx, fy, glyph);
1877 } 1765 }
1878 pos += scalarsPerPosition; 1766 pos += scalarsPerPosition;
1879 } 1767 }
1880 } else { 1768 } else {
1881 while (text < stop) { 1769 while (text < stop) {
1882 const char* currentText = text; 1770 const char* currentText = text;
1883 const SkGlyph& metricGlyph = glyphCacheProc(cache, &text, 0, 0); 1771 const SkGlyph& metricGlyph = glyphCacheProc(cache, &text, 0, 0);
1884 1772
1885 if (metricGlyph.fWidth) { 1773 if (metricGlyph.fWidth) {
1886 SkDEBUGCODE(SkFixed prevAdvX = metricGlyph.fAdvanceX;) 1774 SkDEBUGCODE(SkFixed prevAdvX = metricGlyph.fAdvanceX;)
1887 SkDEBUGCODE(SkFixed prevAdvY = metricGlyph.fAdvanceY;) 1775 SkDEBUGCODE(SkFixed prevAdvY = metricGlyph.fAdvanceY;)
1888 1776 SkPoint tmsLoc;
1889 tmsProc(tms, pos); 1777 tmsProc(pos, &tmsLoc);
1890 SkIPoint fixedLoc; 1778 SkIPoint fixedLoc;
1891 alignProc(tms.fLoc, metricGlyph, &fixedLoc); 1779 alignProc(tmsLoc, metricGlyph, &fixedLoc);
1892 1780
1893 SkFixed fx = fixedLoc.fX + d1g.fHalfSampleX; 1781 SkFixed fx = fixedLoc.fX + d1g.fHalfSampleX;
1894 SkFixed fy = fixedLoc.fY + d1g.fHalfSampleY; 1782 SkFixed fy = fixedLoc.fY + d1g.fHalfSampleY;
1895 1783
1896 // have to call again, now that we've been "aligned" 1784 // have to call again, now that we've been "aligned"
1897 const SkGlyph& glyph = glyphCacheProc(cache, &currentText, 1785 const SkGlyph& glyph = glyphCacheProc(cache, &currentText,
1898 fx & fxMask, fy & fyMa sk); 1786 fx & fxMask, fy & fyMa sk);
1899 // the assumption is that the metrics haven't changed 1787 // the assumption is that the metrics haven't changed
1900 SkASSERT(prevAdvX == glyph.fAdvanceX); 1788 SkASSERT(prevAdvX == glyph.fAdvanceX);
1901 SkASSERT(prevAdvY == glyph.fAdvanceY); 1789 SkASSERT(prevAdvY == glyph.fAdvanceY);
1902 SkASSERT(glyph.fWidth); 1790 SkASSERT(glyph.fWidth);
1903 1791
1904 proc(d1g, fx, fy, glyph); 1792 proc(d1g, fx, fy, glyph);
1905 } 1793 }
1906 pos += scalarsPerPosition; 1794 pos += scalarsPerPosition;
1907 } 1795 }
1908 } 1796 }
1909 } else { // not subpixel 1797 } else { // not subpixel
1910 if (SkPaint::kLeft_Align == paint.getTextAlign()) { 1798 if (SkPaint::kLeft_Align == paint.getTextAlign()) {
1911 while (text < stop) { 1799 while (text < stop) {
1912 // the last 2 parameters are ignored 1800 // the last 2 parameters are ignored
1913 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); 1801 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
1914 1802
1915 if (glyph.fWidth) { 1803 if (glyph.fWidth) {
1916 tmsProc(tms, pos); 1804 SkPoint tmsLoc;
1805 tmsProc(pos, &tmsLoc);
1917 1806
1918 proc(d1g, 1807 proc(d1g,
1919 SkScalarToFixed(tms.fLoc.fX) + SK_FixedHalf, //d1g.fHal fSampleX, 1808 SkScalarToFixed(tmsLoc.fX) + SK_FixedHalf, //d1g.fHalfS ampleX,
1920 SkScalarToFixed(tms.fLoc.fY) + SK_FixedHalf, //d1g.fHal fSampleY, 1809 SkScalarToFixed(tmsLoc.fY) + SK_FixedHalf, //d1g.fHalfS ampleY,
1921 glyph); 1810 glyph);
1922 } 1811 }
1923 pos += scalarsPerPosition; 1812 pos += scalarsPerPosition;
1924 } 1813 }
1925 } else { 1814 } else {
1926 while (text < stop) { 1815 while (text < stop) {
1927 // the last 2 parameters are ignored 1816 // the last 2 parameters are ignored
1928 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); 1817 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
1929 1818
1930 if (glyph.fWidth) { 1819 if (glyph.fWidth) {
1931 tmsProc(tms, pos); 1820 SkPoint tmsLoc;
1821 tmsProc(pos, &tmsLoc);
1932 1822
1933 SkIPoint fixedLoc; 1823 SkIPoint fixedLoc;
1934 alignProc(tms.fLoc, glyph, &fixedLoc); 1824 alignProc(tmsLoc, glyph, &fixedLoc);
1935 1825
1936 proc(d1g, 1826 proc(d1g,
1937 fixedLoc.fX + SK_FixedHalf, //d1g.fHalfSampleX, 1827 fixedLoc.fX + SK_FixedHalf, //d1g.fHalfSampleX,
1938 fixedLoc.fY + SK_FixedHalf, //d1g.fHalfSampleY, 1828 fixedLoc.fY + SK_FixedHalf, //d1g.fHalfSampleY,
1939 glyph); 1829 glyph);
1940 } 1830 }
1941 pos += scalarsPerPosition; 1831 pos += scalarsPerPosition;
1942 } 1832 }
1943 } 1833 }
1944 } 1834 }
(...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after
2477 mask->fImage = SkMask::AllocImage(size); 2367 mask->fImage = SkMask::AllocImage(size);
2478 memset(mask->fImage, 0, mask->computeImageSize()); 2368 memset(mask->fImage, 0, mask->computeImageSize());
2479 } 2369 }
2480 2370
2481 if (SkMask::kJustComputeBounds_CreateMode != mode) { 2371 if (SkMask::kJustComputeBounds_CreateMode != mode) {
2482 draw_into_mask(*mask, devPath, style); 2372 draw_into_mask(*mask, devPath, style);
2483 } 2373 }
2484 2374
2485 return true; 2375 return true;
2486 } 2376 }
OLDNEW
« no previous file with comments | « gyp/core.gypi ('k') | src/core/SkDrawProcs.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698