• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/GrSDFTControl.h"
20 class GrColorInfo;
21 namespace skgpu { namespace v1 { class SurfaceDrawContext; }}
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     const SkIPoint ignorePositionFieldMask;
39 
40 private:
41     static SkVector HalfAxisSampleFreq(bool isSubpixel, SkAxisAlignment axisAlignment);
42     static SkIPoint IgnorePositionMask(bool isSubpixel, SkAxisAlignment axisAlignment);
43     static SkIPoint IgnorePositionFieldMask(bool isSubpixel, SkAxisAlignment axisAlignment);
44 };
45 
46 class SkStrikeCommon {
47 public:
48     // An atlas consists of plots, and plots hold glyphs. The minimum a plot can be is 256x256.
49     // This means that the maximum size a glyph can be is 256x256.
50     inline static constexpr uint16_t kSkSideTooBigForAtlas = 256;
51 };
52 
53 class SkGlyphRunListPainter {
54 public:
55     // Constructor for SkBitmpapDevice.
56     SkGlyphRunListPainter(const SkSurfaceProps& props,
57                           SkColorType colorType,
58                           SkColorSpace* cs,
59                           SkStrikeForGPUCacheInterface* strikeCache);
60 
61 #if SK_SUPPORT_GPU
62     // The following two ctors are used exclusively by the GPU, and will always use the global
63     // strike cache.
64     SkGlyphRunListPainter(const SkSurfaceProps&, const GrColorInfo&);
65     explicit SkGlyphRunListPainter(const skgpu::v1::SurfaceDrawContext&);
66 #endif  // SK_SUPPORT_GPU
67 
68     class BitmapDevicePainter {
69     public:
70         BitmapDevicePainter() = default;
71         BitmapDevicePainter(const BitmapDevicePainter&) = default;
72         virtual ~BitmapDevicePainter() = default;
73 
74         virtual void paintPaths(
75                 SkDrawableGlyphBuffer* drawables, SkScalar scale, SkPoint origin,
76                 const SkPaint& paint) const = 0;
77 
78         virtual void paintMasks(SkDrawableGlyphBuffer* drawables, const SkPaint& paint) const = 0;
79         virtual void drawBitmap(const SkBitmap&, const SkMatrix&, const SkRect* dstOrNull,
80                                 const SkSamplingOptions&, const SkPaint&) const = 0;
81     };
82 
83     void drawForBitmapDevice(
84             const SkGlyphRunList& glyphRunList, const SkPaint& paint, const SkMatrix& deviceMatrix,
85             const BitmapDevicePainter* bitmapDevice);
86 
87 #if SK_SUPPORT_GPU
88     // A nullptr for process means that the calls to the cache will be performed, but none of the
89     // callbacks will be called.
90     void processGlyphRun(const SkGlyphRun& glyphRun,
91                          const SkMatrix& drawMatrix,
92                          const SkPaint& drawPaint,
93                          const GrSDFTControl& control,
94                          SkGlyphRunPainterInterface* process,
95                          const char* tag = nullptr);
96 #endif  // SK_SUPPORT_GPU
97 
98 private:
99     SkGlyphRunListPainter(const SkSurfaceProps& props, SkColorType colorType,
100                           SkScalerContextFlags flags, SkStrikeForGPUCacheInterface* strikeCache);
101 
102     struct ScopedBuffers {
103         ScopedBuffers(SkGlyphRunListPainter* painter, size_t size);
104         // Required until C++17 copy elision
105         ScopedBuffers(const ScopedBuffers&) = default;
106         ~ScopedBuffers();
107         SkGlyphRunListPainter* fPainter;
108     };
109 
110     ScopedBuffers SK_WARN_UNUSED_RESULT ensureBuffers(const SkGlyphRunList& glyphRunList);
111     ScopedBuffers SK_WARN_UNUSED_RESULT ensureBuffers(const SkGlyphRun& glyphRun);
112 
113     // The props as on the actual device.
114     const SkSurfaceProps fDeviceProps;
115     // The props for when the bitmap device can't draw LCD text.
116     const SkSurfaceProps fBitmapFallbackProps;
117     const SkColorType fColorType;
118     const SkScalerContextFlags fScalerContextFlags;
119 
120     SkStrikeForGPUCacheInterface* const fStrikeCache;
121 
122     SkDrawableGlyphBuffer fDrawable;
123     SkSourceGlyphBuffer fRejects;
124 };
125 
126 // SkGlyphRunPainterInterface are all the ways that Ganesh generates glyphs. The first
127 // distinction is between Device and Source.
128 // * Device - the data in the cache is scaled to the device. There is no transformation from the
129 //   cache to the screen.
130 // * Source - the data in the cache needs to be scaled from the cache to source space using the
131 //   factor cacheToSourceScale. When drawn the system must combine cacheToSourceScale and the
132 //   deviceView matrix to transform the cache data onto the screen. This allows zooming and
133 //   simple animation to reuse the same glyph data by just changing the transform.
134 //
135 // In addition to transformation type above, Masks, Paths, SDFT, and Fallback (or really the
136 // rendering method of last resort) are the different
137 // formats of data used from the cache.
138 class SkGlyphRunPainterInterface {
139 public:
140     virtual ~SkGlyphRunPainterInterface() = default;
141 
142     virtual void processDeviceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables,
143                                     sk_sp<SkStrike>&& strike) = 0;
144 
145     virtual void processSourceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables,
146                                     sk_sp<SkStrike>&& strike,
147                                     SkScalar strikeToSourceScale) = 0;
148 
149     virtual void processSourcePaths(const SkZip<SkGlyphVariant, SkPoint>& drawables,
150                                     const SkFont& runFont,
151                                     SkScalar strikeToSourceScale) = 0;
152 
153     virtual void processSourceSDFT(const SkZip<SkGlyphVariant, SkPoint>& drawables,
154                                    sk_sp<SkStrike>&& strike,
155                                    SkScalar strikeToSourceScale,
156                                    const SkFont& runFont,
157                                    SkScalar minScale,
158                                    SkScalar maxScale) = 0;
159 };
160 
161 #endif  // SkGlyphRunPainter_DEFINED
162