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