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

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

Issue 1409123010: Extract glyph find and position code. (Closed) Base URL: https://skia.googlesource.com/skia.git@extract-glyph-position-code
Patch Set: undef the constant Created 5 years, 1 month 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/SkFindAndPlaceGlyph.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 #define __STDC_LIMIT_MACROS 7 #define __STDC_LIMIT_MACROS
8 8
9 #include "SkDraw.h" 9 #include "SkDraw.h"
10 #include "SkBlitter.h" 10 #include "SkBlitter.h"
11 #include "SkCanvas.h" 11 #include "SkCanvas.h"
12 #include "SkColorPriv.h" 12 #include "SkColorPriv.h"
13 #include "SkDevice.h" 13 #include "SkDevice.h"
14 #include "SkDeviceLooper.h" 14 #include "SkDeviceLooper.h"
15 #include "SkFindAndPlaceGlyph.h"
15 #include "SkFixed.h" 16 #include "SkFixed.h"
16 #include "SkMaskFilter.h" 17 #include "SkMaskFilter.h"
17 #include "SkMatrix.h" 18 #include "SkMatrix.h"
18 #include "SkPaint.h" 19 #include "SkPaint.h"
19 #include "SkPathEffect.h" 20 #include "SkPathEffect.h"
20 #include "SkRasterClip.h" 21 #include "SkRasterClip.h"
21 #include "SkRasterizer.h" 22 #include "SkRasterizer.h"
22 #include "SkRRect.h" 23 #include "SkRRect.h"
23 #include "SkScan.h" 24 #include "SkScan.h"
24 #include "SkShader.h" 25 #include "SkShader.h"
(...skipping 1697 matching lines...) Expand 10 before | Expand all | Expand 10 after
1722 fDevice->drawPath(*this, *path, paint, &matrix, false); 1723 fDevice->drawPath(*this, *path, paint, &matrix, false);
1723 } else { 1724 } else {
1724 this->drawPath(*path, paint, &matrix, false); 1725 this->drawPath(*path, paint, &matrix, false);
1725 } 1726 }
1726 } 1727 }
1727 } 1728 }
1728 pos += scalarsPerPosition; 1729 pos += scalarsPerPosition;
1729 } 1730 }
1730 } 1731 }
1731 1732
1732 //////////////////////////////////////////////////////////////////////////////// ////////////////////
1733 // Calculate a type with the same size as the max of all the Ts.
1734 template <typename... Ts> struct MaxSizeOf;
1735
1736 template <> struct MaxSizeOf<> { static const size_t value = 0; };
1737
1738 template <typename H, typename... Ts> struct MaxSizeOf<H, Ts...> {
1739 static const size_t value =
1740 sizeof(H) >= MaxSizeOf<Ts...>::value ? sizeof(H) : MaxSizeOf<Ts...>::val ue;
1741 };
1742
1743 // UntaggedVariant is a pile of memory that can hold one of the Ts. It provides a way
1744 // to initialize that memory in a typesafe way.
1745 template <typename... Ts>
1746 class UntaggedVariant {
1747 public:
1748 UntaggedVariant() {}
1749 ~UntaggedVariant() {}
1750 UntaggedVariant(const UntaggedVariant&) = delete;
1751 UntaggedVariant& operator=(const UntaggedVariant&) = delete;
1752 UntaggedVariant(UntaggedVariant&&) = delete;
1753 UntaggedVariant& operator=(UntaggedVariant&&) = delete;
1754
1755 template <typename Variant, typename... Args>
1756 void initialize(Args &&... args) {
1757 SkASSERT(sizeof(Variant) <= sizeof(fSpace));
1758 #if defined(_MSC_VER) && _MSC_VER < 1900
1759 #define alignof __alignof
1760 #endif
1761 SkASSERT(alignof(Variant) <= alignof(Space));
1762 new (&fSpace) Variant(skstd::forward<Args>(args)...);
1763 }
1764
1765 private:
1766 typedef SkAlignedSStorage<MaxSizeOf<Ts...>::value> Space;
1767 Space fSpace;
1768 };
1769
1770 // PolymorphicVariant holds subclasses of Base without slicing. Ts must be subcl asses of Base.
1771 template <typename Base, typename... Ts>
1772 class PolymorphicVariant {
1773 public:
1774 typedef UntaggedVariant<Ts...> Variants;
1775 template <typename Initializer>
1776 PolymorphicVariant(Initializer&& initializer) {
1777 initializer(&fVariants);
1778 }
1779 ~PolymorphicVariant() { get()->~Base(); }
1780 Base* get() const { return reinterpret_cast<Base*>(&fVariants); }
1781 Base* operator->() const { return get(); }
1782 Base& operator*() const { return *get(); }
1783
1784 private:
1785 mutable Variants fVariants;
1786 };
1787
1788 // PositionReaderInterface reads a point from the pos vector.
1789 // * HorizontalPositions - assumes a common Y for many X values.
1790 // * ArbitraryPositions - a list of (X,Y) pairs.
1791 class PositionReaderInterface {
1792 public:
1793 virtual ~PositionReaderInterface() { }
1794 virtual SkPoint nextPoint() = 0;
1795 };
1796
1797 class HorizontalPositions final : public PositionReaderInterface {
1798 public:
1799 explicit HorizontalPositions(const SkScalar* positions)
1800 : fPositions(positions) { }
1801
1802 SkPoint nextPoint() override {
1803 SkScalar x = *fPositions++;
1804 return {x, 0};
1805 }
1806 private:
1807 const SkScalar* fPositions;
1808 };
1809
1810 class ArbitraryPositions final : public PositionReaderInterface {
1811 public:
1812 explicit ArbitraryPositions(const SkScalar* positions)
1813 : fPositions(positions) { }
1814 SkPoint nextPoint() override {
1815 SkPoint to_return {fPositions[0], fPositions[1]};
1816 fPositions += 2;
1817 return to_return;
1818 }
1819
1820 private:
1821 const SkScalar* fPositions;
1822 };
1823
1824 typedef PolymorphicVariant<PositionReaderInterface, HorizontalPositions, Arbitra ryPositions>
1825 PositionReader;
1826
1827 // MapperInterface given a point map it through the matrix. There are several sh ortcut variants.
1828 // * TranslationMapper - assumes a translation only matrix.
1829 // * XScaleMapper - assumes an X scaling and a translation.
1830 // * GeneralMapper - Does all other matricies.
1831 class MapperInterface {
1832 public:
1833 virtual ~MapperInterface() {}
1834 virtual SkPoint map(SkPoint position) const = 0;
1835 };
1836
1837 class TranslationMapper final : public MapperInterface {
1838 public:
1839 TranslationMapper(const SkMatrix& matrix, const SkPoint origin)
1840 : fTranslate(matrix.mapXY(origin.fX, origin.fY)) { }
1841 SkPoint map(SkPoint position) const override {
1842 return position + fTranslate;
1843 }
1844
1845 private:
1846 const SkPoint fTranslate;
1847 };
1848
1849 class XScaleMapper final : public MapperInterface {
1850 public:
1851 XScaleMapper(const SkMatrix& matrix, const SkPoint origin)
1852 : fTranslate(matrix.mapXY(origin.fX, origin.fY))
1853 , fXScale(matrix.getScaleX()) { }
1854 SkPoint map(SkPoint position) const override {
1855 return {fXScale * position.fX + fTranslate.fX, fTranslate.fY};
1856 }
1857
1858 private:
1859 const SkPoint fTranslate;
1860 const SkScalar fXScale;
1861 };
1862
1863 // The caller must keep matrix alive while this class is used.
1864 class GeneralMapper final : public MapperInterface {
1865 public:
1866 GeneralMapper(const SkMatrix& matrix, const SkPoint origin)
1867 : fOrigin(origin)
1868 , fMatrix(matrix)
1869 , fMapProc(matrix.getMapXYProc()) { }
1870 SkPoint map(SkPoint position) const override {
1871 SkPoint result;
1872 fMapProc(fMatrix, position.fX + fOrigin.fX, position.fY + fOrigin.fY, &r esult);
1873 return result;
1874 }
1875
1876 private:
1877 const SkPoint fOrigin;
1878 const SkMatrix& fMatrix;
1879 const SkMatrix::MapXYProc fMapProc;
1880 };
1881
1882 typedef PolymorphicVariant<MapperInterface, TranslationMapper, XScaleMapper, Gen eralMapper> Mapper;
1883
1884 //////////////////////////////////////////////////////////////////////////////// ////////////////////
1885 // Text alignment handles shifting the glyph based on its width.
1886 static SkPoint text_alignment_adjustment(SkPaint::Align textAlignment, const SkG lyph& glyph) {
1887 switch (textAlignment) {
1888 case SkPaint::kLeft_Align:
1889 return {0.0f, 0.0f};
1890 break;
1891 case SkPaint::kCenter_Align:
1892 return {SkFixedToScalar(glyph.fAdvanceX >> 1),
1893 SkFixedToScalar(glyph.fAdvanceY >> 1)};
1894 break;
1895 case SkPaint::kRight_Align:
1896 return {SkFixedToScalar(glyph.fAdvanceX),
1897 SkFixedToScalar(glyph.fAdvanceY)};
1898 break;
1899 }
1900 // Even though the entire enum is covered above, MVSC doesn't think so. Make it happy.
1901 SkFAIL("Should never get here.");
1902 return {0.0f, 0.0f};
1903 }
1904
1905 // The "call" to SkFixedToScalar is actually a macro. It's macros all the way do wn.
1906 static const SkScalar kSubpixelRounding = SkFixedToScalar(SkGlyph::kSubpixelRoun d);
1907
1908 //////////////////////////////////////////////////////////////////////////////// ////////////////////
1909 // Functions for handling sub-pixel aligned positions.
1910 // The subpixel_position_rounding function returns a point suitable for rounding a sub-pixel
1911 // positioned glyph.
1912 static SkPoint subpixel_position_rounding(SkAxisAlignment axisAlignment) {
1913 switch (axisAlignment) {
1914 case kX_SkAxisAlignment:
1915 return {SkFixedToScalar(SkGlyph::kSubpixelRound), SK_ScalarHalf};
1916 case kY_SkAxisAlignment:
1917 return {SK_ScalarHalf, kSubpixelRounding};
1918 case kNone_SkAxisAlignment:
1919 return {kSubpixelRounding, kSubpixelRounding};
1920 }
1921 SkFAIL("Should not get here.");
1922 return {0.0f, 0.0f};
1923 }
1924
1925 // The subpixel_position_alignment function produces a suitable position for the glyph cache to
1926 // produce the correct sub-pixel alignment. If a position is aligned with an axi s a shortcut of 0
1927 // is used for the sub-pixel position.
1928 static SkIPoint subpixel_position_alignment(SkAxisAlignment axisAlignment, SkPoi nt position) {
1929 switch (axisAlignment) {
1930 case kX_SkAxisAlignment:
1931 return {SkScalarToFixed(position.fX + kSubpixelRounding), 0};
1932 case kY_SkAxisAlignment:
1933 return {0, SkScalarToFixed(position.fY + kSubpixelRounding)};
1934 case kNone_SkAxisAlignment:
1935 return {SkScalarToFixed(position.fX + kSubpixelRounding),
1936 SkScalarToFixed(position.fY + kSubpixelRounding)};
1937 }
1938 SkFAIL("Should not get here.");
1939 return {0, 0};
1940 }
1941
1942 // GlyphFindAndPlaceInterface given the text and position finds the correct glyp h and does glyph
1943 // specific position adjustment. The findAndPositionGlyph method takes text and position and calls
1944 // processOneGlyph with the correct glyph, final position and rounding terms. Th e final position
1945 // is not rounded yet and is the responsibility of processOneGlyph.
1946 template <typename ProcessOneGlyph>
1947 class GlyphFindAndPlaceInterface : SkNoncopyable {
1948 public:
1949 struct Result {
1950 const SkGlyph* fGlyph;
1951 Sk48Dot16 fX;
1952 Sk48Dot16 fY;
1953 };
1954 virtual ~GlyphFindAndPlaceInterface() { };
1955 // This should be a pure virtual, but some versions of GCC <= 4.8 have a bug that causes a
1956 // compile error.
1957 // See GCC bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60277
1958 virtual void findAndPositionGlyph(const char** text, SkPoint position,
1959 ProcessOneGlyph&& processOneGlyph) {};
1960 };
1961
1962 // GlyphFindAndPlaceForSubpixel handles finding and placing glyphs when sub-pixe l positioning is
1963 // requested. After it has found and placed the glyph it calls the templated fun ction
1964 // ProcessOneGlyph in order to actually perform an action.
1965 template <typename ProcessOneGlyph, SkPaint::Align kTextAlignment, SkAxisAlignme nt kAxisAlignment>
1966 class GlyphFindAndPlaceForSubpixel final : public GlyphFindAndPlaceInterface<Pro cessOneGlyph> {
1967 public:
1968 GlyphFindAndPlaceForSubpixel(SkGlyphCache* cache, SkDrawCacheProc glyphCache Proc)
1969 : fCache(cache)
1970 , fGlyphCacheProc(glyphCacheProc) {
1971 }
1972 void findAndPositionGlyph(const char** text, SkPoint position,
1973 ProcessOneGlyph&& processOneGlyph) override {
1974 SkPoint finalPosition = position;
1975 if (kTextAlignment != SkPaint::kLeft_Align) {
1976 // Get the width of an un-sub-pixel positioned glyph for calculating the alignment.
1977 // This is not needed for kLeftAlign because its adjustment is alway s {0, 0}.
1978 const char* tempText = *text;
1979 const SkGlyph& metricGlyph = fGlyphCacheProc(fCache, &tempText, 0, 0 );
1980
1981 if (metricGlyph.fWidth <= 0) {
1982 return;
1983 }
1984
1985 // Adjust the final position by the alignment adjustment.
1986 finalPosition -= text_alignment_adjustment(kTextAlignment, metricGly ph);
1987 }
1988
1989 // Find the glyph.
1990 SkIPoint lookupPosition = subpixel_position_alignment(kAxisAlignment, fi nalPosition);
1991 const SkGlyph& renderGlyph = fGlyphCacheProc(
1992 fCache, text, lookupPosition.fX, lookupPosition.fY);
1993
1994 // If the glyph has no width (no pixels) then don't bother processing it .
1995 if (renderGlyph.fWidth > 0) {
1996 processOneGlyph(renderGlyph, finalPosition, subpixel_position_roundi ng(kAxisAlignment));
1997 }
1998 }
1999
2000 private:
2001 SkGlyphCache* const fCache;
2002 SkDrawCacheProc fGlyphCacheProc;
2003 };
2004
2005 // GlyphFindAndPlaceForFullPixel handles finding and placing glyphs when no sub- pixel positioning
2006 // is requested.
2007 template <typename ProcessOneGlyph, SkPaint::Align kTextAlignment>
2008 class GlyphFindAndPlaceForFullPixel final : public GlyphFindAndPlaceInterface<Pr ocessOneGlyph> {
2009 public:
2010 GlyphFindAndPlaceForFullPixel(SkGlyphCache* cache, SkDrawCacheProc glyphCach eProc)
2011 : fCache(cache)
2012 , fGlyphCacheProc(glyphCacheProc) { }
2013 void findAndPositionGlyph(const char** text, SkPoint position,
2014 ProcessOneGlyph&& processOneGlyph) override {
2015 SkPoint finalPosition = position;
2016 const SkGlyph& glyph = fGlyphCacheProc(fCache, text, 0, 0);
2017 if (glyph.fWidth <= 0) {
2018 return;
2019 }
2020 finalPosition -= text_alignment_adjustment(kTextAlignment, glyph);
2021 processOneGlyph(glyph, finalPosition, {SK_ScalarHalf, SK_ScalarHalf});
2022 }
2023
2024 private:
2025 SkGlyphCache* const fCache;
2026 SkDrawCacheProc fGlyphCacheProc;
2027 };
2028
2029 // GlyphFindAndPlace is a large variant that encapsulates the multiple types of finding and
2030 // placing a glyph. There are three factors that go into the different factors.
2031 // * Is sub-pixel positioned - a boolean that says whether to use sub-pixel posi tioning.
2032 // * Text alignment - indicates if the glyph should be placed to the right, cent ered or left of a
2033 // given position.
2034 // * Axis alignment - indicates if the glyphs final sub-pixel position should be rounded to a
2035 // whole pixel if the glyph is aligned with an axis. This is only used for sub -pixel positioning
2036 // and allows the baseline to look crisp.
2037 template <typename ProcessOneGlyph>
2038 using GlyphFindAndPlace =
2039 PolymorphicVariant<
2040 GlyphFindAndPlaceInterface<ProcessOneGlyph>,
2041 // Subpixel
2042 GlyphFindAndPlaceForSubpixel<ProcessOneGlyph, SkPaint::kLeft_Align, kN one_SkAxisAlignment>,
2043 GlyphFindAndPlaceForSubpixel<ProcessOneGlyph, SkPaint::kLeft_Align, kX _SkAxisAlignment >,
2044 GlyphFindAndPlaceForSubpixel<ProcessOneGlyph, SkPaint::kLeft_Align, kY _SkAxisAlignment >,
2045 GlyphFindAndPlaceForSubpixel<ProcessOneGlyph, SkPaint::kCenter_Align, kN one_SkAxisAlignment>,
2046 GlyphFindAndPlaceForSubpixel<ProcessOneGlyph, SkPaint::kCenter_Align, kX _SkAxisAlignment >,
2047 GlyphFindAndPlaceForSubpixel<ProcessOneGlyph, SkPaint::kCenter_Align, kY _SkAxisAlignment >,
2048 GlyphFindAndPlaceForSubpixel<ProcessOneGlyph, SkPaint::kRight_Align, kN one_SkAxisAlignment>,
2049 GlyphFindAndPlaceForSubpixel<ProcessOneGlyph, SkPaint::kRight_Align, kX _SkAxisAlignment >,
2050 GlyphFindAndPlaceForSubpixel<ProcessOneGlyph, SkPaint::kRight_Align, kY _SkAxisAlignment >,
2051 // Full pixel
2052 GlyphFindAndPlaceForFullPixel<ProcessOneGlyph, SkPaint::kLeft_Align >,
2053 GlyphFindAndPlaceForFullPixel<ProcessOneGlyph, SkPaint::kCenter_Align>,
2054 GlyphFindAndPlaceForFullPixel<ProcessOneGlyph, SkPaint::kRight_Align >
2055 >;
2056
2057 // init_subpixel is a helper function for initializing all the variants of
2058 // GlyphFindAndPlaceForSubpixel.
2059 template <typename ProcessOneGlyph, SkPaint::Align kTextAlignment>
2060 static void init_subpixel(
2061 typename GlyphFindAndPlace<ProcessOneGlyph>::Variants* to_init,
2062 SkAxisAlignment axisAlignment,
2063 SkGlyphCache* cache,
2064 SkDrawCacheProc glyphCacheProc) {
2065 switch (axisAlignment) {
2066 case kX_SkAxisAlignment:
2067 to_init->template initialize<GlyphFindAndPlaceForSubpixel<
2068 ProcessOneGlyph, kTextAlignment, kX_SkAxisAlignment>>(
2069 cache, glyphCacheProc);
2070 break;
2071 case kNone_SkAxisAlignment:
2072 to_init->template initialize<GlyphFindAndPlaceForSubpixel<
2073 ProcessOneGlyph, kTextAlignment, kNone_SkAxisAlignment>>(
2074 cache, glyphCacheProc);
2075 break;
2076 case kY_SkAxisAlignment:
2077 to_init->template initialize<GlyphFindAndPlaceForSubpixel<
2078 ProcessOneGlyph, kTextAlignment, kY_SkAxisAlignment>>(
2079 cache, glyphCacheProc);
2080 break;
2081 }
2082 }
2083
2084 // specialized_process_pos_text is a version of ProcessPosText that de-virtualiz es the different
2085 // components used. It returns true if it can handle the situation, otherwise it returns false.
2086 // This allows greater inlining freedom to the compiler. Currently, there is onl y one specialized
2087 // variant: sub-pixel position, left-aligned, x-axis-aligned, translation, and o ne scalar per
2088 // position entry.
2089 // * This is by far the most common type of text Blink draws.
2090 template <typename ProcessOneGlyph>
2091 static bool specialized_process_pos_text(const char* const text, size_t byteLeng th,
2092 const SkPoint& offset, const SkMatrix& matrix,
2093 const SkScalar pos[], int scalarsPerPos ition,
2094 SkPaint::Align textAlignment,
2095 SkDrawCacheProc& glyphCacheProc,
2096 SkGlyphCache* cache, ProcessOneGlyph&& processOneGlyph) {
2097 SkAxisAlignment axisAlignment = SkComputeAxisAlignmentForHText(matrix);
2098 uint32_t mtype = matrix.getType();
2099 if (scalarsPerPosition == 1
2100 && textAlignment == SkPaint::kLeft_Align
2101 && axisAlignment == kX_SkAxisAlignment
2102 && cache->isSubpixel()
2103 && mtype <= SkMatrix::kTranslate_Mask) {
2104 typedef GlyphFindAndPlaceForSubpixel<
2105 ProcessOneGlyph, SkPaint::kLeft_Align, kX_SkAxisAlignment> Positione r;
2106 HorizontalPositions positions{pos};
2107 TranslationMapper mapper{matrix, offset};
2108 Positioner positioner(cache, glyphCacheProc);
2109 const char *cursor = text;
2110 const char *stop = text + byteLength;
2111 while (cursor < stop) {
2112 SkPoint mappedPoint = mapper.TranslationMapper::map(
2113 positions.HorizontalPositions::nextPoint());
2114 positioner.Positioner::findAndPositionGlyph(
2115 &cursor, mappedPoint, skstd::forward<ProcessOneGlyph>(processOne Glyph));
2116 }
2117 return true;
2118 }
2119 return false;
2120 }
2121
2122 // ProcessPosText handles all cases for finding and positioning glyphs. It has a very large
2123 // multiplicity. It figures out the glyph, position and rounding and pass those parameters to
2124 // processOneGlyph.
2125 //
2126 // The routine processOneGlyph passed in by the client has the following signatu re:
2127 // void f(const SkGlyph& glyph, SkPoint position, SkPoint rounding);
2128 //
2129 // * Sub-pixel positioning (2) - use sub-pixel positioning.
2130 // * Text alignment (3) - text alignment with respect to the glyph's width.
2131 // * Matrix type (3) - special cases for translation and X-coordinate scaling.
2132 // * Components per position (2) - the positions vector can have a common Y with different Xs, or
2133 // XY-pairs.
2134 // * Axis Alignment (for sub-pixel positioning) (3) - when using sub-pixel posit ioning, round to
2135 // a whole coordinate instead of using sub-pixel positioning.
2136 // The number of variations is 108 for sub-pixel and 36 for full-pixel.
2137 // This routine handles all of them using inline polymorphic variable (no heap a llocation).
2138 template <typename ProcessOneGlyph>
2139 static void process_pos_text(const char text[], size_t byteLength,
2140 const SkPoint& offset, const SkMatrix& matrix,
2141 const SkScalar pos[], int scalarsPerPosition,
2142 SkPaint::Align textAlignment, SkDrawCacheProc& glyp hCacheProc,
2143 SkGlyphCache* cache, ProcessOneGlyph&& processOneGl yph) {
2144
2145 PositionReader positionReader {
2146 [&](PositionReader::Variants* to_init) {
2147 if (2 == scalarsPerPosition) {
2148 to_init->initialize<ArbitraryPositions>(pos);
2149 } else {
2150 to_init->initialize<HorizontalPositions>(pos);
2151 }
2152 }
2153 };
2154
2155 Mapper mapper {
2156 [&] (Mapper::Variants* to_init) {
2157 uint32_t mtype = matrix.getType();
2158 if (mtype & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)
2159 || scalarsPerPosition == 2) {
2160 to_init->initialize<GeneralMapper>(matrix, offset);
2161 } else if (mtype & SkMatrix::kScale_Mask) {
2162 to_init->initialize<XScaleMapper>(matrix, offset);
2163 } else {
2164 to_init->initialize<TranslationMapper>(matrix, offset);
2165 }
2166 }
2167 };
2168
2169 GlyphFindAndPlace<ProcessOneGlyph> findAndPosition{
2170 [&](typename GlyphFindAndPlace<ProcessOneGlyph>::Variants* to_init) {
2171 if (cache->isSubpixel()) {
2172 SkAxisAlignment axisAlignment = SkComputeAxisAlignmentForHText(m atrix);
2173 switch (textAlignment) {
2174 case SkPaint::kLeft_Align:
2175 init_subpixel<ProcessOneGlyph, SkPaint::kLeft_Align>(
2176 to_init, axisAlignment, cache, glyphCacheProc);
2177 break;
2178 case SkPaint::kCenter_Align:
2179 init_subpixel<ProcessOneGlyph, SkPaint::kCenter_Align>(
2180 to_init, axisAlignment, cache, glyphCacheProc);
2181 break;
2182 case SkPaint::kRight_Align:
2183 init_subpixel<ProcessOneGlyph, SkPaint::kRight_Align>(
2184 to_init, axisAlignment, cache, glyphCacheProc);
2185 break;
2186 }
2187 } else {
2188 switch (textAlignment) {
2189 case SkPaint::kLeft_Align:
2190 to_init->template initialize<GlyphFindAndPlaceForFullPix el<ProcessOneGlyph,
2191 SkPaint::kLeft_Align>>(
2192 cache, glyphCacheProc);
2193 break;
2194 case SkPaint::kCenter_Align:
2195 to_init->template initialize<GlyphFindAndPlaceForFullPix el<ProcessOneGlyph,
2196 SkPaint::kCenter_Align>>(
2197 cache, glyphCacheProc);
2198 break;
2199 case SkPaint::kRight_Align:
2200 to_init->template initialize<GlyphFindAndPlaceForFullPix el<ProcessOneGlyph,
2201 SkPaint::kRight_Align>>(
2202 cache, glyphCacheProc);
2203 break;
2204 }
2205 }
2206 }
2207 };
2208
2209 const char* stop = text + byteLength;
2210 while (text < stop) {
2211 SkPoint mappedPoint = mapper->map(positionReader->nextPoint());
2212 findAndPosition->findAndPositionGlyph(
2213 &text, mappedPoint, skstd::forward<ProcessOneGlyph>(processOneGlyph) );
2214 }
2215 }
2216
2217 void SkDraw::drawPosText(const char text[], size_t byteLength, 1733 void SkDraw::drawPosText(const char text[], size_t byteLength,
2218 const SkScalar pos[], int scalarsPerPosition, 1734 const SkScalar pos[], int scalarsPerPosition,
2219 const SkPoint& offset, const SkPaint& paint) const { 1735 const SkPoint& offset, const SkPaint& paint) const {
2220 SkASSERT(byteLength == 0 || text != nullptr); 1736 SkASSERT(byteLength == 0 || text != nullptr);
2221 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); 1737 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
2222 1738
2223 SkDEBUGCODE(this->validate();) 1739 SkDEBUGCODE(this->validate();)
2224 1740
2225 // nothing to draw 1741 // nothing to draw
2226 if (text == nullptr || byteLength == 0 || fRC->isEmpty()) { 1742 if (text == nullptr || byteLength == 0 || fRC->isEmpty()) {
(...skipping 24 matching lines...) Expand all
2251 SkDraw1Glyph d1g; 1767 SkDraw1Glyph d1g;
2252 SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache, paint); 1768 SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache, paint);
2253 1769
2254 auto processOneGlyph = 1770 auto processOneGlyph =
2255 [&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) { 1771 [&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) {
2256 position += rounding; 1772 position += rounding;
2257 proc(d1g, SkScalarToFixed(position.fX), SkScalarToFixed(position.fY) , glyph); 1773 proc(d1g, SkScalarToFixed(position.fX), SkScalarToFixed(position.fY) , glyph);
2258 }; 1774 };
2259 1775
2260 SkPaint::Align textAlignment = paint.getTextAlign(); 1776 SkPaint::Align textAlignment = paint.getTextAlign();
2261 if (!specialized_process_pos_text(text, byteLength, offset, *fMatrix, pos, s calarsPerPosition, 1777 if (!SkFindAndPlaceGlyph::SpecializedProcessPosText(
2262 textAlignment, glyphCacheProc, cache, processOneGlyph)) { 1778 text, byteLength, offset, *fMatrix, pos, scalarsPerPosition,
2263 process_pos_text(text, byteLength, offset, *fMatrix, pos, scalarsPerPosi tion, 1779 textAlignment, glyphCacheProc, cache, processOneGlyph)) {
1780 SkFindAndPlaceGlyph::ProcessPosText(
1781 text, byteLength, offset, *fMatrix, pos, scalarsPerPosition,
2264 textAlignment, glyphCacheProc, cache, processOneGlyph); 1782 textAlignment, glyphCacheProc, cache, processOneGlyph);
2265 } 1783 }
2266 } 1784 }
2267 1785
2268 #if defined _WIN32 && _MSC_VER >= 1300 1786 #if defined _WIN32 && _MSC_VER >= 1300
2269 #pragma warning ( pop ) 1787 #pragma warning ( pop )
2270 #endif 1788 #endif
2271 1789
2272 /////////////////////////////////////////////////////////////////////////////// 1790 ///////////////////////////////////////////////////////////////////////////////
2273 1791
(...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after
2658 mask->fImage = SkMask::AllocImage(size); 2176 mask->fImage = SkMask::AllocImage(size);
2659 memset(mask->fImage, 0, mask->computeImageSize()); 2177 memset(mask->fImage, 0, mask->computeImageSize());
2660 } 2178 }
2661 2179
2662 if (SkMask::kJustComputeBounds_CreateMode != mode) { 2180 if (SkMask::kJustComputeBounds_CreateMode != mode) {
2663 draw_into_mask(*mask, devPath, style); 2181 draw_into_mask(*mask, devPath, style);
2664 } 2182 }
2665 2183
2666 return true; 2184 return true;
2667 } 2185 }
OLDNEW
« no previous file with comments | « gyp/core.gypi ('k') | src/core/SkFindAndPlaceGlyph.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698