1 /*
2  * Copyright 2018 The Android Open Source Project
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef SkGlyphRunPainter_DEFINED
9 #define SkGlyphRunPainter_DEFINED
10 
11 #include "include/core/SkSurfaceProps.h"
12 #include "src/core/SkDistanceFieldGen.h"
13 #include "src/core/SkGlyphBuffer.h"
14 #include "src/core/SkGlyphRun.h"
15 #include "src/core/SkScalerContext.h"
16 #include "src/core/SkTextBlobPriv.h"
17 
18 #if SK_SUPPORT_GPU
19 #include "src/gpu/text/GrTextContext.h"
20 class GrColorInfo;
21 class GrRenderTargetContext;
22 #endif
23 
24 class SkGlyphRunPainterInterface;
25 class SkStrikeSpec;
26 
27 // round and ignorePositionMask are used to calculate the subpixel position of a glyph.
28 // The per component (x or y) calculation is:
29 //
30 //   subpixelOffset = (floor((viewportPosition + rounding) & mask) >> 14) & 3
31 //
32 // where mask is either 0 or ~0, and rounding is either
33 // 1/2 for non-subpixel or 1/8 for subpixel.
34 struct SkGlyphPositionRoundingSpec {
35     SkGlyphPositionRoundingSpec(bool isSubpixel, SkAxisAlignment axisAlignment);
36     const SkVector halfAxisSampleFreq;
37     const SkIPoint ignorePositionMask;
38 
39 private:
40     static SkVector HalfAxisSampleFreq(bool isSubpixel, SkAxisAlignment axisAlignment);
41     static SkIPoint IgnorePositionMask(bool isSubpixel, SkAxisAlignment axisAlignment);
42 };
43 
44 class SkStrikeCommon {
45 public:
46     // An atlas consists of plots, and plots hold glyphs. The minimum a plot can be is 256x256.
47     // This means that the maximum size a glyph can be is 256x256.
48     static constexpr uint16_t kSkSideTooBigForAtlas = 256;
49 };
50 
51 class SkGlyphRunListPainter {
52 public:
53     // Constructor for SkBitmpapDevice.
54     SkGlyphRunListPainter(const SkSurfaceProps& props,
55                           SkColorType colorType,
56                           SkColorSpace* cs,
57                           SkStrikeForGPUCacheInterface* strikeCache);
58 
59 #if SK_SUPPORT_GPU
60     // The following two ctors are used exclusively by the GPU, and will always use the global
61     // strike cache.
62     SkGlyphRunListPainter(const SkSurfaceProps&, const GrColorInfo&);
63     explicit SkGlyphRunListPainter(const GrRenderTargetContext& renderTargetContext);
64 #endif  // SK_SUPPORT_GPU
65 
66     class BitmapDevicePainter {
67     public:
68         virtual ~BitmapDevicePainter() = default;
69 
70         virtual void paintPaths(
71                 SkDrawableGlyphBuffer* drawables, SkScalar scale, const SkPaint& paint) const = 0;
72 
73         virtual void paintMasks(SkDrawableGlyphBuffer* drawables, const SkPaint& paint) const = 0;
74     };
75 
76     void drawForBitmapDevice(
77             const SkGlyphRunList& glyphRunList, const SkMatrix& deviceMatrix,
78             const BitmapDevicePainter* bitmapDevice);
79 
80 #if SK_SUPPORT_GPU
81     // A nullptr for process means that the calls to the cache will be performed, but none of the
82     // callbacks will be called.
83     void processGlyphRunList(const SkGlyphRunList& glyphRunList,
84                              const SkMatrix& viewMatrix,
85                              const SkSurfaceProps& props,
86                              bool contextSupportsDistanceFieldText,
87                              const GrTextContext::Options& options,
88                              SkGlyphRunPainterInterface* process);
89 #endif  // SK_SUPPORT_GPU
90 
91 private:
92     SkGlyphRunListPainter(const SkSurfaceProps& props, SkColorType colorType,
93                           SkScalerContextFlags flags, SkStrikeForGPUCacheInterface* strikeCache);
94 
95     struct ScopedBuffers {
96         ScopedBuffers(SkGlyphRunListPainter* painter, size_t size);
97         ~ScopedBuffers();
98         SkGlyphRunListPainter* fPainter;
99     };
100 
101     ScopedBuffers SK_WARN_UNUSED_RESULT ensureBuffers(const SkGlyphRunList& glyphRunList);
102 
103     // TODO: Remove once I can hoist ensureBuffers above the list for loop in all cases.
104     ScopedBuffers SK_WARN_UNUSED_RESULT ensureBuffers(const SkGlyphRun& glyphRun);
105 
106     /**
107      *  @param fARGBPositions in source space
108      *  @param fARGBGlyphsIDs the glyphs to process
109      *  @param fGlyphPos used as scratch space
110      *  @param maxSourceGlyphDimension the longest dimension of any glyph as if all fARGBGlyphsIDs
111      *                                 were drawn in source space (as if viewMatrix were identity)
112      */
113     void processARGBFallback(SkScalar maxSourceGlyphDimension,
114                              const SkPaint& runPaint,
115                              const SkFont& runFont,
116                              const SkMatrix& viewMatrix,
117                              SkGlyphRunPainterInterface* process);
118 
119     static SkSpan<const SkPackedGlyphID> DeviceSpacePackedGlyphIDs(
120             const SkGlyphPositionRoundingSpec& roundingSpec,
121             const SkMatrix& viewMatrix,
122             const SkPoint& origin,
123             int n,
124             const SkGlyphID* glyphIDs,
125             const SkPoint* positions,
126             SkPoint* mappedPositions,
127             SkPackedGlyphID* results);
128 
129     static SkSpan<const SkPackedGlyphID> SourceSpacePackedGlyphIDs(
130             const SkPoint& origin,
131             int n,
132             const SkGlyphID* glyphIDs,
133             const SkPoint* positions,
134             SkPoint* mappedPositions,
135             SkPackedGlyphID* results);
136 
137     // The props as on the actual device.
138     const SkSurfaceProps fDeviceProps;
139     // The props for when the bitmap device can't draw LCD text.
140     const SkSurfaceProps fBitmapFallbackProps;
141     const SkColorType fColorType;
142     const SkScalerContextFlags fScalerContextFlags;
143 
144     SkStrikeForGPUCacheInterface* const fStrikeCache;
145 
146     SkDrawableGlyphBuffer fDrawable;
147 
148     size_t fMaxRunSize{0};
149     SkAutoTMalloc<SkPoint> fPositions;
150     SkAutoTMalloc<SkPackedGlyphID> fPackedGlyphIDs;
151     SkAutoTMalloc<SkGlyphPos> fGlyphPos;
152 
153     std::vector<SkGlyphPos> fPaths;
154 
155     // Vectors for tracking ARGB fallback information.
156     std::vector<SkGlyphID> fARGBGlyphsIDs;
157     std::vector<SkPoint>   fARGBPositions;
158 };
159 
160 // SkGlyphRunPainterInterface are all the ways that Ganesh generates glyphs. The first
161 // distinction is between Device and Source.
162 // * Device - the data in the cache is scaled to the device. There is no transformation from the
163 //   cache to the screen.
164 // * Source - the data in the cache needs to be scaled from the cache to source space using the
165 //   factor cacheToSourceScale. When drawn the system must combine cacheToSourceScale and the
166 //   deviceView matrix to transform the cache data onto the screen. This allows zooming and
167 //   simple animation to reuse the same glyph data by just changing the transform.
168 //
169 // In addition to transformation type above, Masks, Paths, SDFT, and Fallback (or really the
170 // rendering method of last resort) are the different
171 // formats of data used from the cache.
172 class SkGlyphRunPainterInterface {
173 public:
174     virtual ~SkGlyphRunPainterInterface() = default;
175 
176     virtual void startRun(const SkGlyphRun& glyphRun, bool useSDFT) = 0;
177 
178     virtual void processDeviceMasks(SkSpan<const SkGlyphPos> masks,
179                                     const SkStrikeSpec& strikeSpec) = 0;
180 
181     virtual void processSourcePaths(SkSpan<const SkGlyphPos> paths,
182                                     const SkStrikeSpec& strikeSpec) = 0;
183 
184     virtual void processDevicePaths(SkSpan<const SkGlyphPos> paths) = 0;
185 
186     virtual void processSourceSDFT(SkSpan<const SkGlyphPos> masks,
187                                    const SkStrikeSpec& strikeSpec,
188                                    const SkFont& runFont,
189                                    SkScalar minScale,
190                                    SkScalar maxScale,
191                                    bool hasWCoord) = 0;
192 
193     virtual void processSourceFallback(SkSpan<const SkGlyphPos> masks,
194                                        const SkStrikeSpec& strikeSpec,
195                                        bool hasW) = 0;
196 
197     virtual void processDeviceFallback(SkSpan<const SkGlyphPos> masks,
198                                        const SkStrikeSpec& strikeSpec) = 0;
199 
200 };
201 
202 #endif  // SkGlyphRunPainter_DEFINED
203