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/GrSDFTOptions.h"
20class GrColorInfo;
21class GrRenderTargetContext;
22#endif
23
24class SkGlyphRunPainterInterface;
25class 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.
34struct SkGlyphPositionRoundingSpec {
35 SkGlyphPositionRoundingSpec(bool isSubpixel, SkAxisAlignment axisAlignment);
36 const SkVector halfAxisSampleFreq;
37 const SkIPoint ignorePositionMask;
38 const SkIPoint ignorePositionFieldMask;
39
40private:
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
46class SkStrikeCommon {
47public:
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 static constexpr uint16_t kSkSideTooBigForAtlas = 256;
51};
52
53class SkGlyphRunListPainter {
54public:
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 GrRenderTargetContext& renderTargetContext);
66#endif // SK_SUPPORT_GPU
67
68 class BitmapDevicePainter {
69 public:
70 virtual ~BitmapDevicePainter() = default;
71
72 virtual void paintPaths(
73 SkDrawableGlyphBuffer* drawables, SkScalar scale, SkPoint origin,
74 const SkPaint& paint) const = 0;
75
76 virtual void paintMasks(SkDrawableGlyphBuffer* drawables, const SkPaint& paint) const = 0;
77 };
78
79 void drawForBitmapDevice(
80 const SkGlyphRunList& glyphRunList, const SkMatrix& deviceMatrix,
81 const BitmapDevicePainter* bitmapDevice);
82
83#if SK_SUPPORT_GPU
84 // A nullptr for process means that the calls to the cache will be performed, but none of the
85 // callbacks will be called.
86 void processGlyphRunList(const SkGlyphRunList& glyphRunList,
87 const SkMatrix& drawMatrix,
88 const SkSurfaceProps& props,
89 bool contextSupportsDistanceFieldText,
90 const GrSDFTOptions& options,
91 SkGlyphRunPainterInterface* process);
92#endif // SK_SUPPORT_GPU
93
94private:
95 SkGlyphRunListPainter(const SkSurfaceProps& props, SkColorType colorType,
96 SkScalerContextFlags flags, SkStrikeForGPUCacheInterface* strikeCache);
97
98 struct ScopedBuffers {
99 ScopedBuffers(SkGlyphRunListPainter* painter, size_t size);
100 ~ScopedBuffers();
101 SkGlyphRunListPainter* fPainter;
102 };
103
104 ScopedBuffers SK_WARN_UNUSED_RESULT ensureBuffers(const SkGlyphRunList& glyphRunList);
105
106 // The props as on the actual device.
107 const SkSurfaceProps fDeviceProps;
108 // The props for when the bitmap device can't draw LCD text.
109 const SkSurfaceProps fBitmapFallbackProps;
110 const SkColorType fColorType;
111 const SkScalerContextFlags fScalerContextFlags;
112
113 SkStrikeForGPUCacheInterface* const fStrikeCache;
114
115 SkDrawableGlyphBuffer fDrawable;
116 SkSourceGlyphBuffer fRejects;
117};
118
119// SkGlyphRunPainterInterface are all the ways that Ganesh generates glyphs. The first
120// distinction is between Device and Source.
121// * Device - the data in the cache is scaled to the device. There is no transformation from the
122// cache to the screen.
123// * Source - the data in the cache needs to be scaled from the cache to source space using the
124// factor cacheToSourceScale. When drawn the system must combine cacheToSourceScale and the
125// deviceView matrix to transform the cache data onto the screen. This allows zooming and
126// simple animation to reuse the same glyph data by just changing the transform.
127//
128// In addition to transformation type above, Masks, Paths, SDFT, and Fallback (or really the
129// rendering method of last resort) are the different
130// formats of data used from the cache.
131class SkGlyphRunPainterInterface {
132public:
133 virtual ~SkGlyphRunPainterInterface() = default;
134
135 virtual void processDeviceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables,
136 const SkStrikeSpec& strikeSpec,
137 SkPoint residual) = 0;
138
139 virtual void processSourceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables,
140 const SkStrikeSpec& strikeSpec) = 0;
141
142 virtual void processSourcePaths(const SkZip<SkGlyphVariant, SkPoint>& drawables,
143 const SkFont& runFont,
144 const SkStrikeSpec& strikeSpec) = 0;
145
146 virtual void processSourceSDFT(const SkZip<SkGlyphVariant, SkPoint>& drawables,
147 const SkStrikeSpec& strikeSpec,
148 const SkFont& runFont,
149 SkScalar minScale,
150 SkScalar maxScale) = 0;
151};
152
153#endif // SkGlyphRunPainter_DEFINED
154