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