blob: 4b7f602e34d799bcc2df5b5a6d2c6414d6a5cc7f [file] [log] [blame]
joshualitt259fbf12015-07-21 11:39:34 -07001/*
2 * Copyright 2015 Google Inc.
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/core/SkColorFilter.h"
Herb Derby4a1f5fc2020-07-10 16:39:28 -04009#include "include/gpu/GrRecordingContext.h"
Herb Derby91fd46a2019-12-26 11:36:30 -050010#include "include/private/SkTemplates.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "src/core/SkMaskFilterBase.h"
Brian Osman449b1152020-04-15 16:43:00 -040012#include "src/core/SkMatrixProvider.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050013#include "src/core/SkPaintPriv.h"
Herb Derbyadd2c392021-11-08 14:42:55 -050014#include "src/core/SkStrikeCache.h"
Herb Derby3e8b57d2020-06-02 10:43:41 -040015#include "src/core/SkStrikeSpec.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050016#include "src/gpu/GrClip.h"
Herb Derbyec98e202021-10-29 16:12:34 -040017#include "src/gpu/GrGlyph.h"
Robert Phillips259b4682021-07-20 09:27:00 -040018#include "src/gpu/GrMeshDrawTarget.h"
Herb Derby4a1f5fc2020-07-10 16:39:28 -040019#include "src/gpu/GrRecordingContextPriv.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050020#include "src/gpu/GrStyle.h"
Herb Derby4a1f5fc2020-07-10 16:39:28 -040021#include "src/gpu/SkGr.h"
22#include "src/gpu/effects/GrDistanceFieldGeoProc.h"
Michael Ludwig2686d692020-04-17 20:21:37 +000023#include "src/gpu/geometry/GrStyledShape.h"
Herb Derbya9047642019-12-06 12:12:11 -050024#include "src/gpu/text/GrAtlasManager.h"
Robert Phillips41bd97d2020-04-07 14:19:37 -040025#include "src/gpu/text/GrStrikeCache.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050026#include "src/gpu/text/GrTextBlob.h"
Robert Phillips46eb3ab2021-08-02 17:09:01 -040027
Robert Phillips06273bc2021-08-11 15:43:50 -040028#include "src/gpu/GrBlurUtils.h"
Robert Phillips31f76312021-08-27 12:35:41 -040029#include "src/gpu/ops/AtlasTextOp.h"
Robert Phillips4dca8312021-07-28 15:13:20 -040030#include "src/gpu/v1/SurfaceDrawContext_v1.h"
Robert Phillips31f76312021-08-27 12:35:41 -040031
Herb Derby1830fb12021-11-23 11:29:58 -050032// Defining SK_EXPERIMENTAL_ADD_ATLAS_PADDING will cause all glyphs in the atlas to have a one
33// pixel border to support bi-lerping on demand.
34// #define SK_EXPERIMENTAL_ADD_ATLAS_PADDING
35
Herb Derbydd7540f2021-11-18 12:00:50 -050036// Naming conventions
37// * drawMatrix - the CTM from the canvas.
38// * drawOrigin - the x, y location of the drawTextBlob call.
39// * positionMatrix - this is the combination of the drawMatrix and the drawOrigin:
40// positionMatrix = drawMatrix * TranslationMatrix(drawOrigin.x, drawOrigin.y);
41
Robert Phillips31f76312021-08-27 12:35:41 -040042using AtlasTextOp = skgpu::v1::AtlasTextOp;
Ben Wagner75d6db72018-09-20 14:39:39 -040043
Herb Derby3d1d6362020-09-01 10:33:37 -040044namespace {
45struct AtlasPt {
46 uint16_t u;
47 uint16_t v;
48};
49
50// Normal text mask, SDFT, or color.
51struct Mask2DVertex {
52 SkPoint devicePos;
53 GrColor color;
54 AtlasPt atlasPos;
55};
56
57struct ARGB2DVertex {
58 ARGB2DVertex(SkPoint d, GrColor, AtlasPt a) : devicePos{d}, atlasPos{a} {}
59
60 SkPoint devicePos;
61 AtlasPt atlasPos;
62};
63
64// Perspective SDFT or SDFT forced to 3D or perspective color.
65struct Mask3DVertex {
66 SkPoint3 devicePos;
67 GrColor color;
68 AtlasPt atlasPos;
69};
70
71struct ARGB3DVertex {
72 ARGB3DVertex(SkPoint3 d, GrColor, AtlasPt a) : devicePos{d}, atlasPos{a} {}
73
74 SkPoint3 devicePos;
75 AtlasPt atlasPos;
76};
77
Robert Phillips31f76312021-08-27 12:35:41 -040078AtlasTextOp::MaskType op_mask_type(GrMaskFormat grMaskFormat) {
Herb Derby3d1d6362020-09-01 10:33:37 -040079 switch (grMaskFormat) {
Robert Phillips31f76312021-08-27 12:35:41 -040080 case kA8_GrMaskFormat: return AtlasTextOp::MaskType::kGrayscaleCoverage;
81 case kA565_GrMaskFormat: return AtlasTextOp::MaskType::kLCDCoverage;
82 case kARGB_GrMaskFormat: return AtlasTextOp::MaskType::kColorBitmap;
Herb Derby3d1d6362020-09-01 10:33:37 -040083 }
Michael Ludwig136d8782020-11-03 11:04:16 -050084 SkUNREACHABLE;
Herb Derby3d1d6362020-09-01 10:33:37 -040085}
86
Herb Derbydd7540f2021-11-18 12:00:50 -050087SkMatrix position_matrix(const SkMatrix& drawMatrix, SkPoint drawOrigin) {
88 SkMatrix position_matrix = drawMatrix;
89 return position_matrix.preTranslate(drawOrigin.x(), drawOrigin.y());
90}
91
Robert Phillips53eaa642021-08-10 13:49:51 -040092SkPMColor4f calculate_colors(skgpu::SurfaceContext* sc,
Herb Derby3d1d6362020-09-01 10:33:37 -040093 const SkPaint& paint,
94 const SkMatrixProvider& matrix,
95 GrMaskFormat grMaskFormat,
96 GrPaint* grPaint) {
Robert Phillips46eb3ab2021-08-02 17:09:01 -040097 GrRecordingContext* rContext = sc->recordingContext();
98 const GrColorInfo& colorInfo = sc->colorInfo();
Herb Derby3d1d6362020-09-01 10:33:37 -040099 if (grMaskFormat == kARGB_GrMaskFormat) {
Brian Salomone00afb02021-11-22 12:22:16 -0500100 SkPaintToGrPaintReplaceShader(rContext, colorInfo, paint, matrix, nullptr, grPaint);
101 float a = grPaint->getColor4f().fA;
102 return {a, a, a, a};
Herb Derby3d1d6362020-09-01 10:33:37 -0400103 }
Brian Salomone00afb02021-11-22 12:22:16 -0500104 SkPaintToGrPaint(rContext, colorInfo, paint, matrix, grPaint);
105 return grPaint->getColor4f();
Herb Derby3d1d6362020-09-01 10:33:37 -0400106}
107
Herb Derby3d1d6362020-09-01 10:33:37 -0400108template<typename Quad, typename VertexData>
109void fill_transformed_vertices_2D(SkZip<Quad, const GrGlyph*, const VertexData> quadData,
110 SkScalar dstPadding,
111 SkScalar strikeToSource,
112 GrColor color,
113 const SkMatrix& matrix) {
114 SkPoint inset = {dstPadding, dstPadding};
115 for (auto[quad, glyph, vertexData] : quadData) {
116 auto[pos, rect] = vertexData;
117 auto[l, t, r, b] = rect;
118 SkPoint sLT = (SkPoint::Make(l, t) + inset) * strikeToSource + pos,
119 sRB = (SkPoint::Make(r, b) - inset) * strikeToSource + pos;
120 SkPoint lt = matrix.mapXY(sLT.x(), sLT.y()),
121 lb = matrix.mapXY(sLT.x(), sRB.y()),
122 rt = matrix.mapXY(sRB.x(), sLT.y()),
123 rb = matrix.mapXY(sRB.x(), sRB.y());
124 auto[al, at, ar, ab] = glyph->fAtlasLocator.getUVs();
125 quad[0] = {lt, color, {al, at}}; // L,T
126 quad[1] = {lb, color, {al, ab}}; // L,B
127 quad[2] = {rt, color, {ar, at}}; // R,T
128 quad[3] = {rb, color, {ar, ab}}; // R,B
129 }
130}
131
132template<typename Quad, typename VertexData>
133void fill_transformed_vertices_3D(SkZip<Quad, const GrGlyph*, const VertexData> quadData,
134 SkScalar dstPadding,
135 SkScalar strikeToSource,
136 GrColor color,
Herb Derby40894182020-12-02 11:39:48 -0500137 const SkMatrix& positionMatrix) {
Herb Derby3d1d6362020-09-01 10:33:37 -0400138 SkPoint inset = {dstPadding, dstPadding};
139 auto mapXYZ = [&](SkScalar x, SkScalar y) {
140 SkPoint pt{x, y};
141 SkPoint3 result;
Herb Derby40894182020-12-02 11:39:48 -0500142 positionMatrix.mapHomogeneousPoints(&result, &pt, 1);
Herb Derby3d1d6362020-09-01 10:33:37 -0400143 return result;
144 };
145 for (auto[quad, glyph, vertexData] : quadData) {
146 auto[pos, rect] = vertexData;
147 auto [l, t, r, b] = rect;
148 SkPoint sLT = (SkPoint::Make(l, t) + inset) * strikeToSource + pos,
149 sRB = (SkPoint::Make(r, b) - inset) * strikeToSource + pos;
150 SkPoint3 lt = mapXYZ(sLT.x(), sLT.y()),
Herb Derby00b2fdb2020-09-03 11:54:01 -0400151 lb = mapXYZ(sLT.x(), sRB.y()),
152 rt = mapXYZ(sRB.x(), sLT.y()),
153 rb = mapXYZ(sRB.x(), sRB.y());
Herb Derby3d1d6362020-09-01 10:33:37 -0400154 auto[al, at, ar, ab] = glyph->fAtlasLocator.getUVs();
155 quad[0] = {lt, color, {al, at}}; // L,T
156 quad[1] = {lb, color, {al, ab}}; // L,B
157 quad[2] = {rt, color, {ar, at}}; // R,T
158 quad[3] = {rb, color, {ar, ab}}; // R,B
159 }
160}
Herb Derby81c6d6e2020-09-03 17:10:45 -0400161
162// Check for integer translate with the same 2x2 matrix.
Herb Derbyfde5b832021-11-19 10:58:57 -0500163// Returns the translation, and true if the change from initial matrix to the position matrix
164// support using direct glyph masks.
165std::tuple<bool, SkVector> can_use_direct(
166 const SkMatrix& initialPositionMatrix, const SkMatrix& positionMatrix) {
167 // The existing direct glyph info can be used if the initialPositionMatrix, and the
168 // positionMatrix have the same 2x2, and the translation between them is integer.
Herb Derby81c6d6e2020-09-03 17:10:45 -0400169 // Calculate the translation in source space to a translation in device space by mapping
Herb Derbyfde5b832021-11-19 10:58:57 -0500170 // (0, 0) through both the initial position matrix and the position matrix; take the difference.
171 SkVector translation = positionMatrix.mapOrigin() - initialPositionMatrix.mapOrigin();
172 return {initialPositionMatrix.getScaleX() == positionMatrix.getScaleX() &&
173 initialPositionMatrix.getScaleY() == positionMatrix.getScaleY() &&
174 initialPositionMatrix.getSkewX() == positionMatrix.getSkewX() &&
175 initialPositionMatrix.getSkewY() == positionMatrix.getSkewY() &&
176 SkScalarIsInt(translation.x()) && SkScalarIsInt(translation.y()),
177 translation};
Herb Derby81c6d6e2020-09-03 17:10:45 -0400178}
Herb Derbya9047642019-12-06 12:12:11 -0500179
Herb Derby7d3886d2020-11-09 09:08:42 -0500180// -- PathSubRun -----------------------------------------------------------------------------------
181class PathSubRun final : public GrSubRun {
Herb Derbye886b8e2020-11-06 10:58:23 -0500182 struct PathGlyph;
183
184public:
Herb Derby7d3886d2020-11-09 09:08:42 -0500185 PathSubRun(bool isAntiAliased,
Herb Derby37afdbc2021-11-02 20:50:19 -0400186 SkScalar strikeToSourceScale,
Herb Derby15264442020-12-16 10:45:50 -0500187 SkSpan<PathGlyph> paths,
188 std::unique_ptr<PathGlyph[], GrSubRunAllocator::ArrayDestroyer> pathData);
Herb Derbye886b8e2020-11-06 10:58:23 -0500189
Robert Phillips643f4812021-08-11 09:31:00 -0400190 void draw(const GrClip*,
Herb Derbye886b8e2020-11-06 10:58:23 -0500191 const SkMatrixProvider& viewMatrix,
Herb Derbye6f2dce2021-11-22 10:34:03 -0500192 SkPoint drawOrigin,
193 const SkPaint& paint,
Robert Phillips643f4812021-08-11 09:31:00 -0400194 skgpu::v1::SurfaceDrawContext*) const override;
Herb Derbye886b8e2020-11-06 10:58:23 -0500195
Herb Derbydd7540f2021-11-18 12:00:50 -0500196 bool canReuse(const SkPaint& paint, const SkMatrix& positionMatrix) const override;
Herb Derbye886b8e2020-11-06 10:58:23 -0500197
Herb Derbyd90024d2020-11-20 10:21:32 -0500198 GrAtlasSubRun* testingOnly_atlasSubRun() override;
199
Herb Derbyc1a06002021-03-11 10:57:16 -0500200 static GrSubRunOwner Make(const SkZip<SkGlyphVariant, SkPoint>& drawables,
201 bool isAntiAliased,
Herb Derby37afdbc2021-11-02 20:50:19 -0400202 SkScalar strikeToSourceScale,
Herb Derbyc1a06002021-03-11 10:57:16 -0500203 GrSubRunAllocator* alloc);
Herb Derbye886b8e2020-11-06 10:58:23 -0500204
205private:
206 struct PathGlyph {
207 PathGlyph(const SkPath& path, SkPoint origin);
208 SkPath fPath;
209 SkPoint fOrigin;
210 };
211
Herb Derbye886b8e2020-11-06 10:58:23 -0500212 const bool fIsAntiAliased;
Herb Derby37afdbc2021-11-02 20:50:19 -0400213 const SkScalar fStrikeToSourceScale;
Herb Derbye886b8e2020-11-06 10:58:23 -0500214 const SkSpan<const PathGlyph> fPaths;
Herb Derby15264442020-12-16 10:45:50 -0500215 const std::unique_ptr<PathGlyph[], GrSubRunAllocator::ArrayDestroyer> fPathData;
Herb Derbye886b8e2020-11-06 10:58:23 -0500216};
217
Herb Derby7d3886d2020-11-09 09:08:42 -0500218PathSubRun::PathSubRun(bool isAntiAliased,
Herb Derby37afdbc2021-11-02 20:50:19 -0400219 SkScalar strikeToSourceScale,
Herb Derby15264442020-12-16 10:45:50 -0500220 SkSpan<PathGlyph> paths,
221 std::unique_ptr<PathGlyph[], GrSubRunAllocator::ArrayDestroyer> pathData)
Herb Derbye4ef35c2021-03-01 11:49:32 -0500222 : fIsAntiAliased{isAntiAliased}
Herb Derby37afdbc2021-11-02 20:50:19 -0400223 , fStrikeToSourceScale{strikeToSourceScale}
Herb Derby15264442020-12-16 10:45:50 -0500224 , fPaths{paths}
Herb Derbyd533add2021-11-04 10:57:09 -0400225 , fPathData{std::move(pathData)} { }
Herb Derbyb2db9792020-07-14 15:39:25 -0400226
Herb Derby7d3886d2020-11-09 09:08:42 -0500227void PathSubRun::draw(const GrClip* clip,
228 const SkMatrixProvider& viewMatrix,
Herb Derbye6f2dce2021-11-22 10:34:03 -0500229 SkPoint drawOrigin,
Herb Derby0da2c142021-03-22 15:28:23 -0400230 const SkPaint& paint,
Robert Phillips4dca8312021-07-28 15:13:20 -0400231 skgpu::v1::SurfaceDrawContext* sdc) const {
Herb Derbyb2db9792020-07-14 15:39:25 -0400232 SkASSERT(!fPaths.empty());
Herb Derby0da2c142021-03-22 15:28:23 -0400233 SkPaint runPaint{paint};
Herb Derbyb2db9792020-07-14 15:39:25 -0400234 runPaint.setAntiAlias(fIsAntiAliased);
235 // If there are shaders, blurs or styles, the path must be scaled into source
236 // space independently of the CTM. This allows the CTM to be correct for the
237 // different effects.
238 GrStyle style(runPaint);
239
240 bool needsExactCTM = runPaint.getShader()
241 || style.applies()
242 || runPaint.getMaskFilter();
243
244 // Calculate the matrix that maps the path glyphs from their size in the strike to
245 // the graphics source space.
Herb Derby37afdbc2021-11-02 20:50:19 -0400246 SkMatrix strikeToSource = SkMatrix::Scale(fStrikeToSourceScale, fStrikeToSourceScale);
Herb Derbyb2db9792020-07-14 15:39:25 -0400247 strikeToSource.postTranslate(drawOrigin.x(), drawOrigin.y());
248 if (!needsExactCTM) {
249 for (const auto& pathPos : fPaths) {
250 const SkPath& path = pathPos.fPath;
251 const SkPoint pos = pathPos.fOrigin; // Transform the glyph to source space.
252 SkMatrix pathMatrix = strikeToSource;
253 pathMatrix.postTranslate(pos.x(), pos.y());
254 SkPreConcatMatrixProvider strikeToDevice(viewMatrix, pathMatrix);
255
Herb Derby0da2c142021-03-22 15:28:23 -0400256 GrStyledShape shape(path, paint);
Herb Derby37afdbc2021-11-02 20:50:19 -0400257 GrBlurUtils::drawShapeWithMaskFilter(
258 sdc->recordingContext(), sdc, clip, runPaint, strikeToDevice, shape);
Herb Derbyb2db9792020-07-14 15:39:25 -0400259 }
260 } else {
261 // Transform the path to device because the deviceMatrix must be unchanged to
262 // draw effect, filter or shader paths.
263 for (const auto& pathPos : fPaths) {
264 const SkPath& path = pathPos.fPath;
265 const SkPoint pos = pathPos.fOrigin;
266 // Transform the glyph to source space.
267 SkMatrix pathMatrix = strikeToSource;
268 pathMatrix.postTranslate(pos.x(), pos.y());
269
270 SkPath deviceOutline;
271 path.transform(pathMatrix, &deviceOutline);
272 deviceOutline.setIsVolatile(true);
Herb Derby0da2c142021-03-22 15:28:23 -0400273 GrStyledShape shape(deviceOutline, paint);
Herb Derby2e0b5bb2020-11-19 11:03:50 -0500274 GrBlurUtils::drawShapeWithMaskFilter(sdc->recordingContext(), sdc, clip, runPaint,
Brian Salomon70fe17e2020-11-30 14:33:58 -0500275 viewMatrix, shape);
Herb Derbyb2db9792020-07-14 15:39:25 -0400276 }
277 }
278}
279
Herb Derbydd7540f2021-11-18 12:00:50 -0500280bool PathSubRun::canReuse(const SkPaint& paint, const SkMatrix& positionMatrix) const {
Herb Derbye4ef35c2021-03-01 11:49:32 -0500281 return true;
Herb Derby81c6d6e2020-09-03 17:10:45 -0400282}
283
Herb Derbyc1a06002021-03-11 10:57:16 -0500284GrSubRunOwner PathSubRun::Make(const SkZip<SkGlyphVariant, SkPoint>& drawables,
285 bool isAntiAliased,
Herb Derby37afdbc2021-11-02 20:50:19 -0400286 SkScalar strikeToSourceScale,
Herb Derbyc1a06002021-03-11 10:57:16 -0500287 GrSubRunAllocator* alloc) {
Herb Derby15264442020-12-16 10:45:50 -0500288 auto pathData = alloc->makeUniqueArray<PathGlyph>(
Herb Derbyb2db9792020-07-14 15:39:25 -0400289 drawables.size(),
Herb Derby15264442020-12-16 10:45:50 -0500290 [&](int i){
Herb Derbyb2db9792020-07-14 15:39:25 -0400291 auto [variant, pos] = drawables[i];
Herb Derby15264442020-12-16 10:45:50 -0500292 return PathGlyph{*variant.path(), pos};
Herb Derbyb2db9792020-07-14 15:39:25 -0400293 });
Herb Derby15264442020-12-16 10:45:50 -0500294 SkSpan<PathGlyph> paths{pathData.get(), drawables.size()};
Herb Derbyb2db9792020-07-14 15:39:25 -0400295
Herb Derby15264442020-12-16 10:45:50 -0500296 return alloc->makeUnique<PathSubRun>(
Herb Derby1d513f02021-11-22 10:16:11 -0500297 isAntiAliased, strikeToSourceScale, paths, std::move(pathData));
Herb Derbyd90024d2020-11-20 10:21:32 -0500298}
299
300GrAtlasSubRun* PathSubRun::testingOnly_atlasSubRun() {
301 return nullptr;
Herb Derbyb2db9792020-07-14 15:39:25 -0400302};
303
Herb Derby7d3886d2020-11-09 09:08:42 -0500304// -- PathSubRun::PathGlyph ------------------------------------------------------------------------
305PathSubRun::PathGlyph::PathGlyph(const SkPath& path, SkPoint origin)
Herb Derbye886b8e2020-11-06 10:58:23 -0500306 : fPath(path)
307 , fOrigin(origin) {}
308
Herb Derby7d3886d2020-11-09 09:08:42 -0500309// -- GlyphVector ----------------------------------------------------------------------------------
Herb Derbyadd2c392021-11-08 14:42:55 -0500310// GlyphVector provides a way to delay the lookup of GrGlyphs until the code is running on the
311// GPU in single threaded mode. The GlyphVector is created in a multi-threaded environment, but
312// the GrStrikeCache is only single threaded (and must be single threaded because of the atlas).
Herb Derby7d3886d2020-11-09 09:08:42 -0500313class GlyphVector {
Herb Derby624f3f72020-10-29 17:56:26 -0400314public:
Herb Derbye886b8e2020-11-06 10:58:23 -0500315 union Variant {
316 // Initially, filled with packed id, but changed to GrGlyph* in the onPrepare stage.
317 SkPackedGlyphID packedGlyphID;
318 GrGlyph* grGlyph;
Herb Derby624f3f72020-10-29 17:56:26 -0400319 // Add ctors to help SkArenaAlloc create arrays.
320 Variant() : grGlyph{nullptr} {}
321 Variant(SkPackedGlyphID id) : packedGlyphID{id} {}
Herb Derbye886b8e2020-11-06 10:58:23 -0500322 };
323
Herb Derbyadd2c392021-11-08 14:42:55 -0500324 GlyphVector(sk_sp<SkStrike>&& strike, SkSpan<Variant> glyphs);
Herb Derby624f3f72020-10-29 17:56:26 -0400325
Herb Derby7d3886d2020-11-09 09:08:42 -0500326 static GlyphVector Make(
Herb Derbyadd2c392021-11-08 14:42:55 -0500327 sk_sp<SkStrike>&& strike, SkSpan<SkGlyphVariant> glyphs, GrSubRunAllocator* alloc);
Herb Derbye886b8e2020-11-06 10:58:23 -0500328 SkSpan<const GrGlyph*> glyphs() const;
329
Herb Derbye886b8e2020-11-06 10:58:23 -0500330 void packedGlyphIDToGrGlyph(GrStrikeCache* cache);
331
332 std::tuple<bool, int> regenerateAtlas(
333 int begin, int end,
334 GrMaskFormat maskFormat,
335 int srcPadding,
Robert Phillips71143952021-06-17 14:55:07 -0400336 GrMeshDrawTarget *,
Herb Derbye886b8e2020-11-06 10:58:23 -0500337 bool bilerpPadding = false);
338
339 static size_t GlyphVectorSize(size_t count) {
340 return sizeof(Variant) * count;
341 }
342
343private:
Herb Derbyadd2c392021-11-08 14:42:55 -0500344 sk_sp<SkStrike> fStrike;
Herb Derbye886b8e2020-11-06 10:58:23 -0500345 SkSpan<Variant> fGlyphs;
Herb Derbyadd2c392021-11-08 14:42:55 -0500346 sk_sp<GrTextStrike> fGrStrike{nullptr};
Herb Derbye886b8e2020-11-06 10:58:23 -0500347 uint64_t fAtlasGeneration{GrDrawOpAtlas::kInvalidAtlasGeneration};
348 GrDrawOpAtlas::BulkUseTokenUpdater fBulkUseToken;
349};
350
Herb Derbyadd2c392021-11-08 14:42:55 -0500351GlyphVector::GlyphVector(sk_sp<SkStrike>&& strike, SkSpan<Variant> glyphs)
352 : fStrike{std::move(strike)}
353 , fGlyphs{glyphs} {
354 SkASSERT(fStrike != nullptr);
355}
Herb Derbyc1cde362020-07-17 14:07:00 -0400356
Herb Derby7d3886d2020-11-09 09:08:42 -0500357GlyphVector GlyphVector::Make(
Herb Derbyadd2c392021-11-08 14:42:55 -0500358 sk_sp<SkStrike>&& strike, SkSpan<SkGlyphVariant> glyphs, GrSubRunAllocator* alloc) {
Herb Derby15264442020-12-16 10:45:50 -0500359 Variant* variants = alloc->makePODArray<Variant>(glyphs.size());
360 for (auto [i, gv] : SkMakeEnumerate(glyphs)) {
361 variants[i] = gv.glyph()->getPackedID();
362 }
Herb Derbyc1cde362020-07-17 14:07:00 -0400363
Herb Derbyadd2c392021-11-08 14:42:55 -0500364 return GlyphVector{std::move(strike), SkMakeSpan(variants, glyphs.size())};
Herb Derbyc1cde362020-07-17 14:07:00 -0400365}
366
Herb Derby7d3886d2020-11-09 09:08:42 -0500367SkSpan<const GrGlyph*> GlyphVector::glyphs() const {
Brian Osmanae87bf12021-05-11 13:36:10 -0400368 return SkMakeSpan(reinterpret_cast<const GrGlyph**>(fGlyphs.data()), fGlyphs.size());
Herb Derbyc1cde362020-07-17 14:07:00 -0400369}
370
Herb Derbyadd2c392021-11-08 14:42:55 -0500371// packedGlyphIDToGrGlyph must be run in single-threaded mode.
372// If fStrike != nullptr then the conversion to GrGlyph* has not happened.
Herb Derby7d3886d2020-11-09 09:08:42 -0500373void GlyphVector::packedGlyphIDToGrGlyph(GrStrikeCache* cache) {
Herb Derbyadd2c392021-11-08 14:42:55 -0500374 if (fStrike != nullptr) {
375 fGrStrike = cache->findOrCreateStrike(fStrike->strikeSpec());
Herb Derbyc27d5352020-08-12 13:58:34 -0400376
377 for (auto& variant : fGlyphs) {
Herb Derbyadd2c392021-11-08 14:42:55 -0500378 variant.grGlyph = fGrStrike->getGlyph(variant.packedGlyphID);
Herb Derbyc27d5352020-08-12 13:58:34 -0400379 }
Herb Derbyadd2c392021-11-08 14:42:55 -0500380
381 // Drop the ref on the strike that was taken in the SkGlyphRunPainter process* methods.
382 fStrike = nullptr;
Herb Derbyc27d5352020-08-12 13:58:34 -0400383 }
384}
385
Herb Derby7d3886d2020-11-09 09:08:42 -0500386std::tuple<bool, int> GlyphVector::regenerateAtlas(int begin, int end,
387 GrMaskFormat maskFormat,
388 int srcPadding,
Robert Phillips71143952021-06-17 14:55:07 -0400389 GrMeshDrawTarget* target,
Herb Derby7d3886d2020-11-09 09:08:42 -0500390 bool bilerpPadding) {
Herb Derbyc1cde362020-07-17 14:07:00 -0400391 GrAtlasManager* atlasManager = target->atlasManager();
392 GrDeferredUploadTarget* uploadTarget = target->deferredUploadTarget();
393
394 uint64_t currentAtlasGen = atlasManager->atlasGeneration(maskFormat);
395
Herb Derbyc27d5352020-08-12 13:58:34 -0400396 this->packedGlyphIDToGrGlyph(target->strikeCache());
Herb Derbyc1cde362020-07-17 14:07:00 -0400397
398 if (fAtlasGeneration != currentAtlasGen) {
399 // Calculate the texture coordinates for the vertexes during first use (fAtlasGeneration
400 // is set to kInvalidAtlasGeneration) or the atlas has changed in subsequent calls..
401 fBulkUseToken.reset();
402
Herb Derbyadd2c392021-11-08 14:42:55 -0500403 SkBulkGlyphMetricsAndImages metricsAndImages{fGrStrike->strikeSpec()};
Herb Derbyc1cde362020-07-17 14:07:00 -0400404
405 // Update the atlas information in the GrStrike.
406 auto tokenTracker = uploadTarget->tokenTracker();
407 auto glyphs = fGlyphs.subspan(begin, end - begin);
408 int glyphsPlacedInAtlas = 0;
409 bool success = true;
410 for (const Variant& variant : glyphs) {
411 GrGlyph* grGlyph = variant.grGlyph;
412 SkASSERT(grGlyph != nullptr);
413
414 if (!atlasManager->hasGlyph(maskFormat, grGlyph)) {
415 const SkGlyph& skGlyph = *metricsAndImages.glyph(grGlyph->fPackedID);
416 auto code = atlasManager->addGlyphToAtlas(
Herb Derby71984a42020-07-31 16:08:41 -0400417 skGlyph, grGlyph, srcPadding, target->resourceProvider(),
Herb Derbya2800c42020-07-31 15:16:55 -0400418 uploadTarget, bilerpPadding);
Herb Derbyc1cde362020-07-17 14:07:00 -0400419 if (code != GrDrawOpAtlas::ErrorCode::kSucceeded) {
420 success = code != GrDrawOpAtlas::ErrorCode::kError;
421 break;
422 }
423 }
424 atlasManager->addGlyphToBulkAndSetUseToken(
425 &fBulkUseToken, maskFormat, grGlyph,
426 tokenTracker->nextDrawToken());
427 glyphsPlacedInAtlas++;
428 }
429
430 // Update atlas generation if there are no more glyphs to put in the atlas.
Brian Osmana3724292021-05-07 17:20:06 -0400431 if (success && begin + glyphsPlacedInAtlas == SkCount(fGlyphs)) {
Herb Derbyc1cde362020-07-17 14:07:00 -0400432 // Need to get the freshest value of the atlas' generation because
433 // updateTextureCoordinates may have changed it.
434 fAtlasGeneration = atlasManager->atlasGeneration(maskFormat);
435 }
436
437 return {success, glyphsPlacedInAtlas};
438 } else {
439 // The atlas hasn't changed, so our texture coordinates are still valid.
Brian Osmana3724292021-05-07 17:20:06 -0400440 if (end == SkCount(fGlyphs)) {
Herb Derbyc1cde362020-07-17 14:07:00 -0400441 // The atlas hasn't changed and the texture coordinates are all still valid. Update
442 // all the plots used to the new use token.
443 atlasManager->setUseTokenBulk(fBulkUseToken,
444 uploadTarget->tokenTracker()->nextDrawToken(),
445 maskFormat);
446 }
447 return {true, end - begin};
448 }
449}
450
Herb Derby7d3886d2020-11-09 09:08:42 -0500451// -- DirectMaskSubRun -----------------------------------------------------------------------------
Herb Derbyd90024d2020-11-20 10:21:32 -0500452class DirectMaskSubRun final : public GrSubRun, public GrAtlasSubRun {
Herb Derbye886b8e2020-11-06 10:58:23 -0500453public:
Herb Derby624f3f72020-10-29 17:56:26 -0400454 using DevicePosition = skvx::Vec<2, int16_t>;
Herb Derbye886b8e2020-11-06 10:58:23 -0500455
Herb Derby7d3886d2020-11-09 09:08:42 -0500456 DirectMaskSubRun(GrMaskFormat format,
Herb Derby7d3886d2020-11-09 09:08:42 -0500457 GrTextBlob* blob,
Herb Derby683f5722020-12-01 10:08:29 -0500458 const SkGlyphRect& deviceBounds,
Herb Derby624f3f72020-10-29 17:56:26 -0400459 SkSpan<const DevicePosition> devicePositions,
Herb Derbya756c622021-11-10 11:05:46 -0500460 GlyphVector&& glyphs,
Herb Derby624f3f72020-10-29 17:56:26 -0400461 bool glyphsOutOfBounds);
Herb Derbye886b8e2020-11-06 10:58:23 -0500462
Herb Derbyc1a06002021-03-11 10:57:16 -0500463 static GrSubRunOwner Make(const SkZip<SkGlyphVariant, SkPoint>& drawables,
Herb Derbyadd2c392021-11-08 14:42:55 -0500464 sk_sp<SkStrike>&& strike,
Herb Derby21f7a9a2021-11-08 10:06:54 -0500465 SkScalar,
Herb Derbyc1a06002021-03-11 10:57:16 -0500466 GrMaskFormat format,
467 GrTextBlob* blob,
468 GrSubRunAllocator* alloc);
Herb Derbye886b8e2020-11-06 10:58:23 -0500469
Robert Phillips4dca8312021-07-28 15:13:20 -0400470 void draw(const GrClip*,
Herb Derbye886b8e2020-11-06 10:58:23 -0500471 const SkMatrixProvider& viewMatrix,
Herb Derbye6f2dce2021-11-22 10:34:03 -0500472 SkPoint drawOrigin,
473 const SkPaint& paint,
Robert Phillips4dca8312021-07-28 15:13:20 -0400474 skgpu::v1::SurfaceDrawContext*) const override;
Herb Derbye886b8e2020-11-06 10:58:23 -0500475
Herb Derbye886b8e2020-11-06 10:58:23 -0500476 std::tuple<const GrClip*, GrOp::Owner>
477 makeAtlasTextOp(const GrClip* clip,
478 const SkMatrixProvider& viewMatrix,
Herb Derbyfe5b1332021-11-15 14:23:57 -0500479 SkPoint drawOrigin,
Herb Derby0da2c142021-03-22 15:28:23 -0400480 const SkPaint& paint,
Robert Phillips4dca8312021-07-28 15:13:20 -0400481 skgpu::v1::SurfaceDrawContext* sdc,
Herb Derby2e0b5bb2020-11-19 11:03:50 -0500482 GrAtlasSubRunOwner) const override;
Robert Phillips46eb3ab2021-08-02 17:09:01 -0400483
Herb Derbydd7540f2021-11-18 12:00:50 -0500484 bool canReuse(const SkPaint& paint, const SkMatrix& positionMatrix) const override;
Robert Phillips46eb3ab2021-08-02 17:09:01 -0400485
486 GrAtlasSubRun* testingOnly_atlasSubRun() override;
487
488 size_t vertexStride(const SkMatrix& drawMatrix) const override;
489
490 int glyphCount() const override;
Herb Derbye886b8e2020-11-06 10:58:23 -0500491
492 void testingOnly_packedGlyphIDToGrGlyph(GrStrikeCache *cache) override;
493
494 std::tuple<bool, int>
Robert Phillips71143952021-06-17 14:55:07 -0400495 regenerateAtlas(int begin, int end, GrMeshDrawTarget*) const override;
Herb Derbye886b8e2020-11-06 10:58:23 -0500496
Herb Derbydd7540f2021-11-18 12:00:50 -0500497 void fillVertexData(void* vertexDst, int offset, int count,
498 GrColor color,
499 const SkMatrix& drawMatrix, SkPoint drawOrigin,
500 SkIRect clip) const override;
Herb Derbye886b8e2020-11-06 10:58:23 -0500501private:
Herb Derbye886b8e2020-11-06 10:58:23 -0500502 // The rectangle that surrounds all the glyph bounding boxes in device space.
503 SkRect deviceRect(const SkMatrix& drawMatrix, SkPoint drawOrigin) const;
504
505 const GrMaskFormat fMaskFormat;
Herb Derbye886b8e2020-11-06 10:58:23 -0500506 GrTextBlob* const fBlob;
Herb Derby683f5722020-12-01 10:08:29 -0500507
508 // The union of all the glyph bounds in device space.
Herb Derby2e0b5bb2020-11-19 11:03:50 -0500509 const SkGlyphRect fGlyphDeviceBounds;
Herb Derby624f3f72020-10-29 17:56:26 -0400510 const SkSpan<const DevicePosition> fLeftTopDevicePos;
511 const bool fSomeGlyphsExcluded;
Herb Derbye886b8e2020-11-06 10:58:23 -0500512
513 // The regenerateAtlas method mutates fGlyphs. It should be called from onPrepare which must
514 // be single threaded.
Herb Derby7d3886d2020-11-09 09:08:42 -0500515 mutable GlyphVector fGlyphs;
Herb Derbye886b8e2020-11-06 10:58:23 -0500516};
517
Herb Derby7d3886d2020-11-09 09:08:42 -0500518DirectMaskSubRun::DirectMaskSubRun(GrMaskFormat format,
Herb Derby7d3886d2020-11-09 09:08:42 -0500519 GrTextBlob* blob,
Herb Derby683f5722020-12-01 10:08:29 -0500520 const SkGlyphRect& deviceBounds,
Herb Derby624f3f72020-10-29 17:56:26 -0400521 SkSpan<const DevicePosition> devicePositions,
Herb Derbya756c622021-11-10 11:05:46 -0500522 GlyphVector&& glyphs,
Herb Derby624f3f72020-10-29 17:56:26 -0400523 bool glyphsOutOfBounds)
Herb Derby09357cc2020-07-20 09:55:48 -0400524 : fMaskFormat{format}
525 , fBlob{blob}
Herb Derby2e0b5bb2020-11-19 11:03:50 -0500526 , fGlyphDeviceBounds{deviceBounds}
Herb Derby624f3f72020-10-29 17:56:26 -0400527 , fLeftTopDevicePos{devicePositions}
528 , fSomeGlyphsExcluded{glyphsOutOfBounds}
Herb Derbya756c622021-11-10 11:05:46 -0500529 , fGlyphs{std::move(glyphs)} {}
Herb Derby09357cc2020-07-20 09:55:48 -0400530
Herb Derbyc1a06002021-03-11 10:57:16 -0500531GrSubRunOwner DirectMaskSubRun::Make(const SkZip<SkGlyphVariant, SkPoint>& drawables,
Herb Derbyadd2c392021-11-08 14:42:55 -0500532 sk_sp<SkStrike>&& strike,
Herb Derby21f7a9a2021-11-08 10:06:54 -0500533 SkScalar,
Herb Derbyc1a06002021-03-11 10:57:16 -0500534 GrMaskFormat format,
535 GrTextBlob* blob,
536 GrSubRunAllocator* alloc) {
Herb Derby15264442020-12-16 10:45:50 -0500537 DevicePosition* glyphLeftTop = alloc->makePODArray<DevicePosition>(drawables.size());
538 GlyphVector::Variant* glyphIDs = alloc->makePODArray<GlyphVector::Variant>(drawables.size());
Herb Derby1fbb3312020-07-30 16:57:22 -0400539
Herb Derby624f3f72020-10-29 17:56:26 -0400540 // Because this is the direct case, the maximum width or height is the size that fits in the
541 // atlas. This boundary is checked below to ensure that the call to SkGlyphRect below will
542 // not overflow.
543 constexpr SkScalar kMaxPos =
544 std::numeric_limits<int16_t>::max() - SkStrikeCommon::kSkSideTooBigForAtlas;
545 SkGlyphRect runBounds = skglyph::empty_rect();
546 size_t goodPosCount = 0;
547 for (auto [variant, pos] : drawables) {
548 auto [x, y] = pos;
549 // Ensure that the .offset() call below does not overflow. And, at this point none of the
550 // rectangles are empty because they were culled before the run was created. Basically,
551 // cull all the glyphs that can't appear on the screen.
Herb Derby4ce110b2020-11-19 16:36:47 +0000552 if (-kMaxPos < x && x < kMaxPos && -kMaxPos < y && y < kMaxPos) {
Herb Derby624f3f72020-10-29 17:56:26 -0400553 const SkGlyph* const skGlyph = variant;
554 const SkGlyphRect deviceBounds =
555 skGlyph->glyphRect().offset(SkScalarRoundToInt(x), SkScalarRoundToInt(y));
556 runBounds = skglyph::rect_union(runBounds, deviceBounds);
557 glyphLeftTop[goodPosCount] = deviceBounds.topLeft();
558 glyphIDs[goodPosCount].packedGlyphID = skGlyph->getPackedID();
559 goodPosCount += 1;
560 }
561 }
Herb Derby09357cc2020-07-20 09:55:48 -0400562
Herb Derby624f3f72020-10-29 17:56:26 -0400563 // Wow! no glyphs are in bounds and had non-empty bounds.
564 if (goodPosCount == 0) {
565 return nullptr;
566 }
Herb Derby09357cc2020-07-20 09:55:48 -0400567
Herb Derby5a136832021-10-28 13:04:53 -0400568 // If some glyphs were excluded by the bounds, then this subrun can't be generally be used
569 // for other draws. Mark the subrun as not general.
Herb Derby624f3f72020-10-29 17:56:26 -0400570 bool glyphsExcluded = goodPosCount != drawables.size();
571 SkSpan<const DevicePosition> leftTop{glyphLeftTop, goodPosCount};
Herb Derby15264442020-12-16 10:45:50 -0500572 return alloc->makeUnique<DirectMaskSubRun>(
Herb Derby683f5722020-12-01 10:08:29 -0500573 format, blob, runBounds, leftTop,
Herb Derbyadd2c392021-11-08 14:42:55 -0500574 GlyphVector{std::move(strike), {glyphIDs, goodPosCount}}, glyphsExcluded);
Herb Derby09357cc2020-07-20 09:55:48 -0400575}
576
Herb Derbydd7540f2021-11-18 12:00:50 -0500577bool DirectMaskSubRun::canReuse(const SkPaint& paint, const SkMatrix& positionMatrix) const {
Herb Derbyfde5b832021-11-19 10:58:57 -0500578 auto [reuse, translation] = can_use_direct(fBlob->initialPositionMatrix(), positionMatrix);
Herb Derby624f3f72020-10-29 17:56:26 -0400579
580 // If glyphs were excluded because of position bounds, then this subrun can only be reused if
581 // there is no change in position.
582 if (fSomeGlyphsExcluded) {
583 return translation.x() == 0 && translation.y() == 0;
584 }
585
586 return reuse;
Herb Derby81c6d6e2020-09-03 17:10:45 -0400587}
588
Herb Derby46d1e9f2020-12-01 14:12:04 -0500589size_t DirectMaskSubRun::vertexStride(const SkMatrix&) const {
Herb Derby09357cc2020-07-20 09:55:48 -0400590 if (fMaskFormat != kARGB_GrMaskFormat) {
591 return sizeof(Mask2DVertex);
592 } else {
593 return sizeof(ARGB2DVertex);
594 }
595}
596
Herb Derby7d3886d2020-11-09 09:08:42 -0500597int DirectMaskSubRun::glyphCount() const {
Brian Osmana3724292021-05-07 17:20:06 -0400598 return SkCount(fGlyphs.glyphs());
Herb Derby09357cc2020-07-20 09:55:48 -0400599}
600
Robert Phillips46eb3ab2021-08-02 17:09:01 -0400601void DirectMaskSubRun::draw(const GrClip* clip,
602 const SkMatrixProvider& viewMatrix,
Herb Derbye6f2dce2021-11-22 10:34:03 -0500603 SkPoint drawOrigin,
Robert Phillips46eb3ab2021-08-02 17:09:01 -0400604 const SkPaint& paint,
605 skgpu::v1::SurfaceDrawContext* sdc) const{
606 auto[drawingClip, op] = this->makeAtlasTextOp(
Herb Derbye6f2dce2021-11-22 10:34:03 -0500607 clip, viewMatrix, drawOrigin, paint, sdc, nullptr);
Robert Phillips46eb3ab2021-08-02 17:09:01 -0400608 if (op != nullptr) {
609 sdc->addDrawOp(drawingClip, std::move(op));
610 }
611}
612
Herb Derbyb34d62b2021-01-19 14:43:33 -0500613namespace {
614enum ClipMethod {
615 kClippedOut,
616 kUnclipped,
617 kGPUClipped,
618 kGeometryClipped
619};
620
621std::tuple<ClipMethod, SkIRect>
622calculate_clip(const GrClip* clip, SkRect deviceBounds, SkRect glyphBounds) {
623 if (clip == nullptr && !deviceBounds.intersects(glyphBounds)) {
624 return {kClippedOut, SkIRect::MakeEmpty()};
625 } else if (clip != nullptr) {
626 switch (auto result = clip->preApply(glyphBounds, GrAA::kNo); result.fEffect) {
627 case GrClip::Effect::kClippedOut:
628 return {kClippedOut, SkIRect::MakeEmpty()};
629 case GrClip::Effect::kUnclipped:
630 return {kUnclipped, SkIRect::MakeEmpty()};
631 case GrClip::Effect::kClipped: {
632 if (result.fIsRRect && result.fRRect.isRect()) {
633 SkRect r = result.fRRect.rect();
634 if (result.fAA == GrAA::kNo || GrClip::IsPixelAligned(r)) {
635 SkIRect clipRect = SkIRect::MakeEmpty();
636 // Clip geometrically during onPrepare using clipRect.
637 r.round(&clipRect);
638 if (clipRect.contains(glyphBounds)) {
639 // If fully within the clip, signal no clipping using the empty rect.
640 return {kUnclipped, SkIRect::MakeEmpty()};
641 }
642 // Use the clipRect to clip the geometry.
643 return {kGeometryClipped, clipRect};
644 }
645 // Partial pixel clipped at this point. Have the GPU handle it.
646 }
647 }
648 break;
649 }
650 }
651 return {kGPUClipped, SkIRect::MakeEmpty()};
652}
653} // namespace
654
Herb Derbyc76d4092020-10-07 16:46:15 -0400655std::tuple<const GrClip*, GrOp::Owner>
Herb Derbyfe5b1332021-11-15 14:23:57 -0500656DirectMaskSubRun::makeAtlasTextOp(const GrClip* clip,
657 const SkMatrixProvider& viewMatrix,
658 SkPoint drawOrigin,
Herb Derby0da2c142021-03-22 15:28:23 -0400659 const SkPaint& paint,
Robert Phillips4dca8312021-07-28 15:13:20 -0400660 skgpu::v1::SurfaceDrawContext* sdc,
Herb Derby2e0b5bb2020-11-19 11:03:50 -0500661 GrAtlasSubRunOwner) const {
Herb Derby09357cc2020-07-20 09:55:48 -0400662 SkASSERT(this->glyphCount() != 0);
663
664 const SkMatrix& drawMatrix = viewMatrix.localToDevice();
Herb Derby09357cc2020-07-20 09:55:48 -0400665
Herb Derbyb34d62b2021-01-19 14:43:33 -0500666 // We can clip geometrically using clipRect and ignore clip when an axis-aligned rectangular
667 // non-AA clip is used. If clipRect is empty, and clip is nullptr, then there is no clipping
668 // needed.
Herb Derby09357cc2020-07-20 09:55:48 -0400669 const SkRect subRunBounds = this->deviceRect(drawMatrix, drawOrigin);
Herb Derby2e0b5bb2020-11-19 11:03:50 -0500670 const SkRect deviceBounds = SkRect::MakeWH(sdc->width(), sdc->height());
Herb Derbyb34d62b2021-01-19 14:43:33 -0500671 auto [clipMethod, clipRect] = calculate_clip(clip, deviceBounds, subRunBounds);
Herb Derby09357cc2020-07-20 09:55:48 -0400672
Herb Derbyb34d62b2021-01-19 14:43:33 -0500673 switch (clipMethod) {
674 case kClippedOut:
675 // Returning nullptr as op means skip this op.
676 return {nullptr, nullptr};
677 case kUnclipped:
678 case kGeometryClipped:
679 // GPU clip is not needed.
680 clip = nullptr;
Herb Derby39697462020-11-16 12:07:01 -0500681 break;
Herb Derbyb34d62b2021-01-19 14:43:33 -0500682 case kGPUClipped:
683 // Use the the GPU clip; clipRect is ignored.
684 break;
Herb Derby09357cc2020-07-20 09:55:48 -0400685 }
686
687 if (!clipRect.isEmpty()) { SkASSERT(clip == nullptr); }
688
689 GrPaint grPaint;
Herb Derby09357cc2020-07-20 09:55:48 -0400690 const SkPMColor4f drawingColor =
Herb Derby0da2c142021-03-22 15:28:23 -0400691 calculate_colors(sdc, paint, viewMatrix, fMaskFormat, &grPaint);
Herb Derby6b748e42020-12-02 17:44:54 -0500692
Robert Phillips31f76312021-08-27 12:35:41 -0400693 auto geometry = AtlasTextOp::Geometry::MakeForBlob(*this,
694 drawMatrix,
695 drawOrigin,
696 clipRect,
697 sk_ref_sp<GrTextBlob>(fBlob),
698 drawingColor,
699 sdc->arenaAlloc());
Herb Derby09357cc2020-07-20 09:55:48 -0400700
Herb Derbybba18802021-03-31 16:45:54 -0400701 GrRecordingContext* const rContext = sdc->recordingContext();
Robert Phillips31f76312021-08-27 12:35:41 -0400702 GrOp::Owner op = GrOp::Make<AtlasTextOp>(rContext,
703 op_mask_type(fMaskFormat),
704 false,
705 this->glyphCount(),
706 subRunBounds,
707 geometry,
708 std::move(grPaint));
Herb Derby09357cc2020-07-20 09:55:48 -0400709
710 return {clip, std::move(op)};
711}
712
Herb Derby7d3886d2020-11-09 09:08:42 -0500713void DirectMaskSubRun::testingOnly_packedGlyphIDToGrGlyph(GrStrikeCache *cache) {
Herb Derbyc27d5352020-08-12 13:58:34 -0400714 fGlyphs.packedGlyphIDToGrGlyph(cache);
715}
716
Herb Derby09357cc2020-07-20 09:55:48 -0400717std::tuple<bool, int>
Robert Phillips71143952021-06-17 14:55:07 -0400718DirectMaskSubRun::regenerateAtlas(int begin, int end, GrMeshDrawTarget* target) const {
Herb Derby1830fb12021-11-23 11:29:58 -0500719 #if defined(SK_EXPERIMENTAL_ADD_ATLAS_PADDING)
720 return fGlyphs.regenerateAtlas(begin, end, fMaskFormat, 1, target, true);
721 #else
722 return fGlyphs.regenerateAtlas(begin, end, fMaskFormat, 0, target, false);
723 #endif
Herb Derby09357cc2020-07-20 09:55:48 -0400724}
Derek Sollenbergerf8431702020-11-05 10:25:40 -0500725
Herb Derby624f3f72020-10-29 17:56:26 -0400726// The 99% case. No clip. Non-color only.
727void direct_2D(SkZip<Mask2DVertex[4],
Herb Derby5a136832021-10-28 13:04:53 -0400728 const GrGlyph*,
729 const DirectMaskSubRun::DevicePosition> quadData,
Herb Derby624f3f72020-10-29 17:56:26 -0400730 GrColor color,
731 SkIPoint integralOriginOffset) {
732 for (auto[quad, glyph, leftTop] : quadData) {
733 auto[al, at, ar, ab] = glyph->fAtlasLocator.getUVs();
734 SkScalar dl = leftTop[0] + integralOriginOffset.x(),
Herb Derbyeeb30ae2021-02-17 11:27:59 -0500735 dt = leftTop[1] + integralOriginOffset.y(),
736 dr = dl + (ar - al),
737 db = dt + (ab - at);
Herb Derby624f3f72020-10-29 17:56:26 -0400738
739 quad[0] = {{dl, dt}, color, {al, at}}; // L,T
740 quad[1] = {{dl, db}, color, {al, ab}}; // L,B
741 quad[2] = {{dr, dt}, color, {ar, at}}; // R,T
742 quad[3] = {{dr, db}, color, {ar, ab}}; // R,B
743 }
744}
745
746template <typename Rect>
747auto ltbr(const Rect& r) {
748 return std::make_tuple(r.left(), r.top(), r.right(), r.bottom());
749}
750
751// Handle any combination of BW or color and clip or no clip.
752template<typename Quad, typename VertexData>
753void generalized_direct_2D(SkZip<Quad, const GrGlyph*, const VertexData> quadData,
754 GrColor color,
755 SkIPoint integralOriginOffset,
756 SkIRect* clip = nullptr) {
757 for (auto[quad, glyph, leftTop] : quadData) {
758 auto[al, at, ar, ab] = glyph->fAtlasLocator.getUVs();
759 uint16_t w = ar - al,
760 h = ab - at;
761 SkScalar l = (SkScalar)leftTop[0] + integralOriginOffset.x(),
762 t = (SkScalar)leftTop[1] + integralOriginOffset.y();
763 if (clip == nullptr) {
764 auto[dl, dt, dr, db] = SkRect::MakeLTRB(l, t, l + w, t + h);
765 quad[0] = {{dl, dt}, color, {al, at}}; // L,T
766 quad[1] = {{dl, db}, color, {al, ab}}; // L,B
767 quad[2] = {{dr, dt}, color, {ar, at}}; // R,T
768 quad[3] = {{dr, db}, color, {ar, ab}}; // R,B
769 } else {
770 SkIRect devIRect = SkIRect::MakeLTRB(l, t, l + w, t + h);
771 SkScalar dl, dt, dr, db;
772 if (!clip->containsNoEmptyCheck(devIRect)) {
773 if (SkIRect clipped; clipped.intersect(devIRect, *clip)) {
774 al += clipped.left() - devIRect.left();
775 at += clipped.top() - devIRect.top();
776 ar += clipped.right() - devIRect.right();
777 ab += clipped.bottom() - devIRect.bottom();
778 std::tie(dl, dt, dr, db) = ltbr(clipped);
779 } else {
780 // TODO: omit generating any vertex data for fully clipped glyphs ?
781 std::tie(dl, dt, dr, db) = std::make_tuple(0, 0, 0, 0);
782 std::tie(al, at, ar, ab) = std::make_tuple(0, 0, 0, 0);
783 }
784 } else {
785 std::tie(dl, dt, dr, db) = ltbr(devIRect);
786 }
787 quad[0] = {{dl, dt}, color, {al, at}}; // L,T
788 quad[1] = {{dl, db}, color, {al, ab}}; // L,B
789 quad[2] = {{dr, dt}, color, {ar, at}}; // R,T
790 quad[3] = {{dr, db}, color, {ar, ab}}; // R,B
791 }
792 }
793}
794
Herb Derbydd7540f2021-11-18 12:00:50 -0500795void DirectMaskSubRun::fillVertexData(void* vertexDst, int offset, int count,
796 GrColor color,
797 const SkMatrix& drawMatrix, SkPoint drawOrigin,
798 SkIRect clip) const {
799 const SkMatrix positionMatrix = position_matrix(drawMatrix, drawOrigin);
Herb Derby43f49b42020-08-14 13:20:11 -0400800 auto quadData = [&](auto dst) {
Herb Derby09357cc2020-07-20 09:55:48 -0400801 return SkMakeZip(dst,
802 fGlyphs.glyphs().subspan(offset, count),
Herb Derby624f3f72020-10-29 17:56:26 -0400803 fLeftTopDevicePos.subspan(offset, count));
Herb Derby09357cc2020-07-20 09:55:48 -0400804 };
805
Herb Derbydd7540f2021-11-18 12:00:50 -0500806 SkPoint originOffset = positionMatrix.mapOrigin() - fBlob->initialPositionMatrix().mapOrigin();
Herb Derby9c81e522020-11-09 10:28:50 -0500807 SkIPoint integralOriginOffset =
808 {SkScalarRoundToInt(originOffset.x()), SkScalarRoundToInt(originOffset.y())};
Herb Derby09357cc2020-07-20 09:55:48 -0400809
810 if (clip.isEmpty()) {
811 if (fMaskFormat != kARGB_GrMaskFormat) {
812 using Quad = Mask2DVertex[4];
Herb Derby40894182020-12-02 11:39:48 -0500813 SkASSERT(sizeof(Quad) == this->vertexStride(positionMatrix) * kVerticesPerGlyph);
Herb Derby9c81e522020-11-09 10:28:50 -0500814 direct_2D(quadData((Quad*)vertexDst), color, integralOriginOffset);
Herb Derby09357cc2020-07-20 09:55:48 -0400815 } else {
816 using Quad = ARGB2DVertex[4];
Herb Derby40894182020-12-02 11:39:48 -0500817 SkASSERT(sizeof(Quad) == this->vertexStride(positionMatrix) * kVerticesPerGlyph);
Herb Derby9c81e522020-11-09 10:28:50 -0500818 generalized_direct_2D(quadData((Quad*)vertexDst), color, integralOriginOffset);
Herb Derby09357cc2020-07-20 09:55:48 -0400819 }
820 } else {
821 if (fMaskFormat != kARGB_GrMaskFormat) {
822 using Quad = Mask2DVertex[4];
Herb Derby40894182020-12-02 11:39:48 -0500823 SkASSERT(sizeof(Quad) == this->vertexStride(positionMatrix) * kVerticesPerGlyph);
Herb Derby9c81e522020-11-09 10:28:50 -0500824 generalized_direct_2D(quadData((Quad*)vertexDst), color, integralOriginOffset, &clip);
Herb Derby09357cc2020-07-20 09:55:48 -0400825 } else {
826 using Quad = ARGB2DVertex[4];
Herb Derby40894182020-12-02 11:39:48 -0500827 SkASSERT(sizeof(Quad) == this->vertexStride(positionMatrix) * kVerticesPerGlyph);
Herb Derby9c81e522020-11-09 10:28:50 -0500828 generalized_direct_2D(quadData((Quad*)vertexDst), color, integralOriginOffset, &clip);
Herb Derby09357cc2020-07-20 09:55:48 -0400829 }
830 }
Herb Derby09357cc2020-07-20 09:55:48 -0400831}
832
Herb Derby7d3886d2020-11-09 09:08:42 -0500833SkRect DirectMaskSubRun::deviceRect(const SkMatrix& drawMatrix, SkPoint drawOrigin) const {
Herb Derby2e0b5bb2020-11-19 11:03:50 -0500834 SkIRect outBounds = fGlyphDeviceBounds.iRect();
Herb Derby09357cc2020-07-20 09:55:48 -0400835
Herb Derby90f211f2020-11-18 11:10:54 -0500836 // Calculate the offset from the initial device origin to the current device origin.
Herb Derbydd7540f2021-11-18 12:00:50 -0500837 SkVector offset = drawMatrix.mapPoint(drawOrigin) - fBlob->initialPositionMatrix().mapOrigin();
Herb Derby09357cc2020-07-20 09:55:48 -0400838
Herb Derby683f5722020-12-01 10:08:29 -0500839 // The offset should be integer, but make sure.
840 SkIVector iOffset = {SkScalarRoundToInt(offset.x()), SkScalarRoundToInt(offset.y())};
Herb Derby09357cc2020-07-20 09:55:48 -0400841
Herb Derby683f5722020-12-01 10:08:29 -0500842 return SkRect::Make(outBounds.makeOffset(iOffset));
Herb Derby09357cc2020-07-20 09:55:48 -0400843}
844
Herb Derbyd90024d2020-11-20 10:21:32 -0500845GrAtlasSubRun* DirectMaskSubRun::testingOnly_atlasSubRun() {
846 return this;
847}
848
Herb Derby7d3886d2020-11-09 09:08:42 -0500849// -- TransformedMaskSubRun ------------------------------------------------------------------------
Herb Derbyd90024d2020-11-20 10:21:32 -0500850class TransformedMaskSubRun final : public GrSubRun, public GrAtlasSubRun {
Herb Derbye886b8e2020-11-06 10:58:23 -0500851public:
852 struct VertexData {
853 const SkPoint pos;
854 // The rectangle of the glyphs in strike space. But, for kDirectMask this also implies a
855 // device space rect.
856 GrIRect16 rect;
857 };
858
Herb Derby7d3886d2020-11-09 09:08:42 -0500859 TransformedMaskSubRun(GrMaskFormat format,
860 GrTextBlob* blob,
Herb Derby21f7a9a2021-11-08 10:06:54 -0500861 SkScalar strikeToSourceScale,
Herb Derby7d3886d2020-11-09 09:08:42 -0500862 const SkRect& bounds,
863 SkSpan<const VertexData> vertexData,
Herb Derbya756c622021-11-10 11:05:46 -0500864 GlyphVector&& glyphs);
Herb Derbye886b8e2020-11-06 10:58:23 -0500865
Herb Derbyc1a06002021-03-11 10:57:16 -0500866 static GrSubRunOwner Make(const SkZip<SkGlyphVariant, SkPoint>& drawables,
Herb Derbyadd2c392021-11-08 14:42:55 -0500867 sk_sp<SkStrike>&& strike,
Herb Derby21f7a9a2021-11-08 10:06:54 -0500868 SkScalar strikeToSourceScale,
Herb Derbyc1a06002021-03-11 10:57:16 -0500869 GrMaskFormat format,
870 GrTextBlob* blob,
871 GrSubRunAllocator* alloc);
Herb Derbye886b8e2020-11-06 10:58:23 -0500872
Robert Phillips4dca8312021-07-28 15:13:20 -0400873 void draw(const GrClip*,
Herb Derbye886b8e2020-11-06 10:58:23 -0500874 const SkMatrixProvider& viewMatrix,
Herb Derbye6f2dce2021-11-22 10:34:03 -0500875 SkPoint drawOrigin,
876 const SkPaint& paint,
Robert Phillips4dca8312021-07-28 15:13:20 -0400877 skgpu::v1::SurfaceDrawContext*) const override;
Herb Derbye886b8e2020-11-06 10:58:23 -0500878
Herb Derbye886b8e2020-11-06 10:58:23 -0500879 std::tuple<const GrClip*, GrOp::Owner>
Robert Phillips4dca8312021-07-28 15:13:20 -0400880 makeAtlasTextOp(const GrClip*,
Herb Derbye886b8e2020-11-06 10:58:23 -0500881 const SkMatrixProvider& viewMatrix,
Herb Derbyfe5b1332021-11-15 14:23:57 -0500882 SkPoint drawOrigin,
Robert Phillips4dca8312021-07-28 15:13:20 -0400883 const SkPaint&,
884 skgpu::v1::SurfaceDrawContext*,
Herb Derby2e0b5bb2020-11-19 11:03:50 -0500885 GrAtlasSubRunOwner) const override;
Robert Phillips46eb3ab2021-08-02 17:09:01 -0400886
Herb Derbydd7540f2021-11-18 12:00:50 -0500887 bool canReuse(const SkPaint& paint, const SkMatrix& positionMatrix) const override;
Robert Phillips46eb3ab2021-08-02 17:09:01 -0400888
889 GrAtlasSubRun* testingOnly_atlasSubRun() override;
Herb Derbye886b8e2020-11-06 10:58:23 -0500890
891 void testingOnly_packedGlyphIDToGrGlyph(GrStrikeCache *cache) override;
892
Robert Phillips71143952021-06-17 14:55:07 -0400893 std::tuple<bool, int> regenerateAtlas(int begin, int end, GrMeshDrawTarget*) const override;
Herb Derbye886b8e2020-11-06 10:58:23 -0500894
895 void fillVertexData(
896 void* vertexDst, int offset, int count,
Herb Derbydd7540f2021-11-18 12:00:50 -0500897 GrColor color,
898 const SkMatrix& drawMatrix, SkPoint drawOrigin,
899 SkIRect clip) const override;
Herb Derbye886b8e2020-11-06 10:58:23 -0500900
Herb Derby46d1e9f2020-12-01 14:12:04 -0500901 size_t vertexStride(const SkMatrix& drawMatrix) const override;
Herb Derbye886b8e2020-11-06 10:58:23 -0500902 int glyphCount() const override;
903
904private:
Herb Derbye886b8e2020-11-06 10:58:23 -0500905 // The rectangle that surrounds all the glyph bounding boxes in device space.
906 SkRect deviceRect(const SkMatrix& drawMatrix, SkPoint drawOrigin) const;
907
908 const GrMaskFormat fMaskFormat;
909 GrTextBlob* fBlob;
910
Herb Derby21f7a9a2021-11-08 10:06:54 -0500911 // The scale factor between the strike size, and the source size.
912 const SkScalar fStrikeToSourceScale;
913
Herb Derbye886b8e2020-11-06 10:58:23 -0500914 // The bounds in source space. The bounds are the joined rectangles of all the glyphs.
915 const SkRect fVertexBounds;
916 const SkSpan<const VertexData> fVertexData;
917
918 // The regenerateAtlas method mutates fGlyphs. It should be called from onPrepare which must
919 // be single threaded.
Herb Derby7d3886d2020-11-09 09:08:42 -0500920 mutable GlyphVector fGlyphs;
Herb Derbye886b8e2020-11-06 10:58:23 -0500921};
922
Herb Derby7d3886d2020-11-09 09:08:42 -0500923TransformedMaskSubRun::TransformedMaskSubRun(GrMaskFormat format,
924 GrTextBlob* blob,
Herb Derby21f7a9a2021-11-08 10:06:54 -0500925 SkScalar strikeToSourceScale,
Herb Derby7d3886d2020-11-09 09:08:42 -0500926 const SkRect& bounds,
927 SkSpan<const VertexData> vertexData,
Herb Derbya756c622021-11-10 11:05:46 -0500928 GlyphVector&& glyphs)
Herb Derby53453f72020-07-24 15:03:54 -0400929 : fMaskFormat{format}
930 , fBlob{blob}
Herb Derby21f7a9a2021-11-08 10:06:54 -0500931 , fStrikeToSourceScale{strikeToSourceScale}
Herb Derby53453f72020-07-24 15:03:54 -0400932 , fVertexBounds{bounds}
933 , fVertexData{vertexData}
Herb Derbya756c622021-11-10 11:05:46 -0500934 , fGlyphs{std::move(glyphs)} { }
Herb Derbya9047642019-12-06 12:12:11 -0500935
Herb Derbyc1a06002021-03-11 10:57:16 -0500936GrSubRunOwner TransformedMaskSubRun::Make(const SkZip<SkGlyphVariant, SkPoint>& drawables,
Herb Derbyadd2c392021-11-08 14:42:55 -0500937 sk_sp<SkStrike>&& strike,
Herb Derby21f7a9a2021-11-08 10:06:54 -0500938 SkScalar strikeToSourceScale,
Herb Derbyc1a06002021-03-11 10:57:16 -0500939 GrMaskFormat format,
940 GrTextBlob* blob,
941 GrSubRunAllocator* alloc) {
Herb Derby53453f72020-07-24 15:03:54 -0400942 SkRect bounds = SkRectPriv::MakeLargestInverted();
Herb Derby53453f72020-07-24 15:03:54 -0400943
Herb Derby15264442020-12-16 10:45:50 -0500944 SkSpan<VertexData> vertexData = alloc->makePODArray<VertexData>(
945 drawables,
946 [&](auto e) {
947 auto [variant, pos] = e;
948 SkGlyph* skGlyph = variant;
949 int16_t l = skGlyph->left(),
950 t = skGlyph->top(),
951 r = l + skGlyph->width(),
952 b = t + skGlyph->height();
Herb Derby21f7a9a2021-11-08 10:06:54 -0500953 SkPoint lt = SkPoint::Make(l, t) * strikeToSourceScale + pos,
954 rb = SkPoint::Make(r, b) * strikeToSourceScale + pos;
Herb Derby53453f72020-07-24 15:03:54 -0400955
Herb Derby15264442020-12-16 10:45:50 -0500956 bounds.joinPossiblyEmptyRect(SkRect::MakeLTRB(lt.x(), lt.y(), rb.x(), rb.y()));
957 return VertexData{pos, {l, t, r, b}};
958 });
Herb Derby53453f72020-07-24 15:03:54 -0400959
Herb Derby15264442020-12-16 10:45:50 -0500960 return alloc->makeUnique<TransformedMaskSubRun>(
Herb Derby21f7a9a2021-11-08 10:06:54 -0500961 format, blob, strikeToSourceScale, bounds, vertexData,
Herb Derbyadd2c392021-11-08 14:42:55 -0500962 GlyphVector::Make(std::move(strike), drawables.get<0>(), alloc));
Herb Derby53453f72020-07-24 15:03:54 -0400963}
964
Herb Derby7d3886d2020-11-09 09:08:42 -0500965void TransformedMaskSubRun::draw(const GrClip* clip,
966 const SkMatrixProvider& viewMatrix,
Herb Derbye6f2dce2021-11-22 10:34:03 -0500967 SkPoint drawOrigin,
Herb Derby0da2c142021-03-22 15:28:23 -0400968 const SkPaint& paint,
Robert Phillips4dca8312021-07-28 15:13:20 -0400969 skgpu::v1::SurfaceDrawContext* sdc) const {
Herb Derby0da2c142021-03-22 15:28:23 -0400970 auto[drawingClip, op] = this->makeAtlasTextOp(
Herb Derbye6f2dce2021-11-22 10:34:03 -0500971 clip, viewMatrix, drawOrigin, paint, sdc, nullptr);
Herb Derby53453f72020-07-24 15:03:54 -0400972 if (op != nullptr) {
Herb Derby2e0b5bb2020-11-19 11:03:50 -0500973 sdc->addDrawOp(drawingClip, std::move(op));
Herb Derby53453f72020-07-24 15:03:54 -0400974 }
975}
976
Herb Derbyc76d4092020-10-07 16:46:15 -0400977std::tuple<const GrClip*, GrOp::Owner>
Herb Derby7d3886d2020-11-09 09:08:42 -0500978TransformedMaskSubRun::makeAtlasTextOp(const GrClip* clip,
979 const SkMatrixProvider& viewMatrix,
Herb Derbyfe5b1332021-11-15 14:23:57 -0500980 SkPoint drawOrigin,
Herb Derby0da2c142021-03-22 15:28:23 -0400981 const SkPaint& paint,
Robert Phillips4dca8312021-07-28 15:13:20 -0400982 skgpu::v1::SurfaceDrawContext* sdc,
Herb Derby2e0b5bb2020-11-19 11:03:50 -0500983 GrAtlasSubRunOwner) const {
Herb Derby4a1f5fc2020-07-10 16:39:28 -0400984 SkASSERT(this->glyphCount() != 0);
985
Herb Derby4a1f5fc2020-07-10 16:39:28 -0400986 const SkMatrix& drawMatrix = viewMatrix.localToDevice();
Herb Derby4a1f5fc2020-07-10 16:39:28 -0400987
Herb Derby4a1f5fc2020-07-10 16:39:28 -0400988 GrPaint grPaint;
Herb Derby0da2c142021-03-22 15:28:23 -0400989 SkPMColor4f drawingColor = calculate_colors(sdc, paint, viewMatrix, fMaskFormat, &grPaint);
Herb Derby4a1f5fc2020-07-10 16:39:28 -0400990
Robert Phillips31f76312021-08-27 12:35:41 -0400991 auto geometry = AtlasTextOp::Geometry::MakeForBlob(*this,
992 drawMatrix,
993 drawOrigin,
994 SkIRect::MakeEmpty(),
995 sk_ref_sp<GrTextBlob>(fBlob),
996 drawingColor,
997 sdc->arenaAlloc());
Herb Derby4a1f5fc2020-07-10 16:39:28 -0400998
Herb Derbybba18802021-03-31 16:45:54 -0400999 GrRecordingContext* const rContext = sdc->recordingContext();
Robert Phillips31f76312021-08-27 12:35:41 -04001000 GrOp::Owner op = GrOp::Make<AtlasTextOp>(rContext,
1001 op_mask_type(fMaskFormat),
1002 true,
1003 this->glyphCount(),
1004 this->deviceRect(drawMatrix, drawOrigin),
1005 geometry,
1006 std::move(grPaint));
Herb Derby4a1f5fc2020-07-10 16:39:28 -04001007 return {clip, std::move(op)};
1008}
Robert Phillips46eb3ab2021-08-02 17:09:01 -04001009
1010// If we are not scaling the cache entry to be larger, than a cache with smaller glyphs may be
1011// better.
Herb Derbydd7540f2021-11-18 12:00:50 -05001012bool TransformedMaskSubRun::canReuse(const SkPaint& paint, const SkMatrix& positionMatrix) const {
1013 if (fBlob->initialPositionMatrix().getMaxScale() < 1) {
Robert Phillips46eb3ab2021-08-02 17:09:01 -04001014 return false;
1015 }
1016 return true;
1017}
Herb Derby4a1f5fc2020-07-10 16:39:28 -04001018
Herb Derby7d3886d2020-11-09 09:08:42 -05001019void TransformedMaskSubRun::testingOnly_packedGlyphIDToGrGlyph(GrStrikeCache *cache) {
Herb Derbyc27d5352020-08-12 13:58:34 -04001020 fGlyphs.packedGlyphIDToGrGlyph(cache);
1021}
1022
Herb Derby7d3886d2020-11-09 09:08:42 -05001023std::tuple<bool, int> TransformedMaskSubRun::regenerateAtlas(int begin, int end,
Robert Phillips71143952021-06-17 14:55:07 -04001024 GrMeshDrawTarget* target) const {
Herb Derby71984a42020-07-31 16:08:41 -04001025 return fGlyphs.regenerateAtlas(begin, end, fMaskFormat, 1, target, true);
Herb Derby53453f72020-07-24 15:03:54 -04001026}
1027
Herb Derbydd7540f2021-11-18 12:00:50 -05001028void TransformedMaskSubRun::fillVertexData(void* vertexDst, int offset, int count,
1029 GrColor color,
1030 const SkMatrix& drawMatrix, SkPoint drawOrigin,
1031 SkIRect clip) const {
1032 const SkMatrix positionMatrix = position_matrix(drawMatrix, drawOrigin);
Herb Derbybad09142020-07-27 11:00:43 -04001033 constexpr SkScalar kDstPadding = 0.f;
Herb Derby53453f72020-07-24 15:03:54 -04001034
Herb Derbybad09142020-07-27 11:00:43 -04001035 auto quadData = [&](auto dst) {
Herb Derby53453f72020-07-24 15:03:54 -04001036 return SkMakeZip(dst,
1037 fGlyphs.glyphs().subspan(offset, count),
1038 fVertexData.subspan(offset, count));
1039 };
1040
Herb Derby40894182020-12-02 11:39:48 -05001041 if (!positionMatrix.hasPerspective()) {
Herb Derby53453f72020-07-24 15:03:54 -04001042 if (fMaskFormat == GrMaskFormat::kARGB_GrMaskFormat) {
1043 using Quad = ARGB2DVertex[4];
Herb Derby40894182020-12-02 11:39:48 -05001044 SkASSERT(sizeof(Quad) == this->vertexStride(positionMatrix) * kVerticesPerGlyph);
Herb Derbybad09142020-07-27 11:00:43 -04001045 fill_transformed_vertices_2D(
1046 quadData((Quad*) vertexDst),
Herb Derby71984a42020-07-31 16:08:41 -04001047 kDstPadding,
Herb Derby21f7a9a2021-11-08 10:06:54 -05001048 fStrikeToSourceScale,
Herb Derbybad09142020-07-27 11:00:43 -04001049 color,
Herb Derby40894182020-12-02 11:39:48 -05001050 positionMatrix);
Herb Derby53453f72020-07-24 15:03:54 -04001051 } else {
1052 using Quad = Mask2DVertex[4];
Herb Derby40894182020-12-02 11:39:48 -05001053 SkASSERT(sizeof(Quad) == this->vertexStride(positionMatrix) * kVerticesPerGlyph);
Herb Derbybad09142020-07-27 11:00:43 -04001054 fill_transformed_vertices_2D(
1055 quadData((Quad*) vertexDst),
Herb Derby71984a42020-07-31 16:08:41 -04001056 kDstPadding,
Herb Derby21f7a9a2021-11-08 10:06:54 -05001057 fStrikeToSourceScale,
Herb Derbybad09142020-07-27 11:00:43 -04001058 color,
Herb Derby40894182020-12-02 11:39:48 -05001059 positionMatrix);
Herb Derby53453f72020-07-24 15:03:54 -04001060 }
1061 } else {
1062 if (fMaskFormat == GrMaskFormat::kARGB_GrMaskFormat) {
1063 using Quad = ARGB3DVertex[4];
Herb Derby40894182020-12-02 11:39:48 -05001064 SkASSERT(sizeof(Quad) == this->vertexStride(positionMatrix) * kVerticesPerGlyph);
Herb Derbybad09142020-07-27 11:00:43 -04001065 fill_transformed_vertices_3D(
1066 quadData((Quad*) vertexDst),
Herb Derby71984a42020-07-31 16:08:41 -04001067 kDstPadding,
Herb Derby21f7a9a2021-11-08 10:06:54 -05001068 fStrikeToSourceScale,
Herb Derbybad09142020-07-27 11:00:43 -04001069 color,
Herb Derby40894182020-12-02 11:39:48 -05001070 positionMatrix);
Herb Derby53453f72020-07-24 15:03:54 -04001071 } else {
1072 using Quad = Mask3DVertex[4];
Herb Derby40894182020-12-02 11:39:48 -05001073 SkASSERT(sizeof(Quad) == this->vertexStride(positionMatrix) * kVerticesPerGlyph);
Herb Derbybad09142020-07-27 11:00:43 -04001074 fill_transformed_vertices_3D(
1075 quadData((Quad*) vertexDst),
Herb Derby71984a42020-07-31 16:08:41 -04001076 kDstPadding,
Herb Derby21f7a9a2021-11-08 10:06:54 -05001077 fStrikeToSourceScale,
Herb Derbybad09142020-07-27 11:00:43 -04001078 color,
Herb Derby40894182020-12-02 11:39:48 -05001079 positionMatrix);
Herb Derby53453f72020-07-24 15:03:54 -04001080 }
Herb Derby2604a892020-07-13 12:13:30 -04001081 }
1082}
1083
Herb Derby46d1e9f2020-12-01 14:12:04 -05001084size_t TransformedMaskSubRun::vertexStride(const SkMatrix& drawMatrix) const {
Herb Derby53453f72020-07-24 15:03:54 -04001085 switch (fMaskFormat) {
Herb Derbya56a1d72019-12-27 12:12:47 -05001086 case kA8_GrMaskFormat:
Herb Derby46d1e9f2020-12-01 14:12:04 -05001087 return drawMatrix.hasPerspective() ? sizeof(Mask3DVertex) : sizeof(Mask2DVertex);
Herb Derbya56a1d72019-12-27 12:12:47 -05001088 case kARGB_GrMaskFormat:
Herb Derby46d1e9f2020-12-01 14:12:04 -05001089 return drawMatrix.hasPerspective() ? sizeof(ARGB3DVertex) : sizeof(ARGB2DVertex);
Herb Derbya56a1d72019-12-27 12:12:47 -05001090 default:
Herb Derby46d1e9f2020-12-01 14:12:04 -05001091 SkASSERT(!drawMatrix.hasPerspective());
Herb Derby64391c42020-05-16 14:32:15 -04001092 return sizeof(Mask2DVertex);
Herb Derbya56a1d72019-12-27 12:12:47 -05001093 }
Herb Derby64391c42020-05-16 14:32:15 -04001094 SkUNREACHABLE;
Herb Derby23f29762020-01-10 16:26:14 -05001095}
1096
Herb Derby7d3886d2020-11-09 09:08:42 -05001097int TransformedMaskSubRun::glyphCount() const {
Brian Osmana3724292021-05-07 17:20:06 -04001098 return SkCount(fVertexData);
Herb Derby53453f72020-07-24 15:03:54 -04001099}
1100
Herb Derby7d3886d2020-11-09 09:08:42 -05001101SkRect TransformedMaskSubRun::deviceRect(const SkMatrix& drawMatrix, SkPoint drawOrigin) const {
Herb Derby53453f72020-07-24 15:03:54 -04001102 SkRect outBounds = fVertexBounds;
1103 outBounds.offset(drawOrigin);
1104 return drawMatrix.mapRect(outBounds);
1105}
1106
Herb Derbyd90024d2020-11-20 10:21:32 -05001107GrAtlasSubRun* TransformedMaskSubRun::testingOnly_atlasSubRun() {
1108 return this;
1109}
1110
Herb Derby7d3886d2020-11-09 09:08:42 -05001111// -- SDFTSubRun -----------------------------------------------------------------------------------
Herb Derbyd90024d2020-11-20 10:21:32 -05001112class SDFTSubRun final : public GrSubRun, public GrAtlasSubRun {
Herb Derbye886b8e2020-11-06 10:58:23 -05001113public:
1114 struct VertexData {
1115 const SkPoint pos;
1116 // The rectangle of the glyphs in strike space.
1117 GrIRect16 rect;
1118 };
1119
Herb Derby7d3886d2020-11-09 09:08:42 -05001120 SDFTSubRun(GrMaskFormat format,
1121 GrTextBlob* blob,
Herb Derby21f7a9a2021-11-08 10:06:54 -05001122 SkScalar strikeToSource,
Herb Derby7d3886d2020-11-09 09:08:42 -05001123 SkRect vertexBounds,
1124 SkSpan<const VertexData> vertexData,
Herb Derbya756c622021-11-10 11:05:46 -05001125 GlyphVector&& glyphs,
Herb Derby7d3886d2020-11-09 09:08:42 -05001126 bool useLCDText,
1127 bool antiAliased);
Herb Derbye886b8e2020-11-06 10:58:23 -05001128
Herb Derbyc1a06002021-03-11 10:57:16 -05001129 static GrSubRunOwner Make(const SkZip<SkGlyphVariant, SkPoint>& drawables,
1130 const SkFont& runFont,
Herb Derbyadd2c392021-11-08 14:42:55 -05001131 sk_sp<SkStrike>&& strike,
Herb Derby21f7a9a2021-11-08 10:06:54 -05001132 SkScalar strikeToSourceScale,
Herb Derbyc1a06002021-03-11 10:57:16 -05001133 GrTextBlob* blob,
1134 GrSubRunAllocator* alloc);
Herb Derbye886b8e2020-11-06 10:58:23 -05001135
Robert Phillips4dca8312021-07-28 15:13:20 -04001136 void draw(const GrClip*,
Herb Derbye886b8e2020-11-06 10:58:23 -05001137 const SkMatrixProvider& viewMatrix,
Herb Derbye6f2dce2021-11-22 10:34:03 -05001138 SkPoint drawOrigin,
Robert Phillips4dca8312021-07-28 15:13:20 -04001139 const SkPaint&,
1140 skgpu::v1::SurfaceDrawContext*) const override;
Herb Derbye886b8e2020-11-06 10:58:23 -05001141
Herb Derbye886b8e2020-11-06 10:58:23 -05001142 std::tuple<const GrClip*, GrOp::Owner>
Robert Phillips4dca8312021-07-28 15:13:20 -04001143 makeAtlasTextOp(const GrClip*,
Herb Derbye886b8e2020-11-06 10:58:23 -05001144 const SkMatrixProvider& viewMatrix,
Herb Derbyfe5b1332021-11-15 14:23:57 -05001145 SkPoint drawOrigin,
Robert Phillips4dca8312021-07-28 15:13:20 -04001146 const SkPaint&,
1147 skgpu::v1::SurfaceDrawContext*,
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001148 GrAtlasSubRunOwner) const override;
Robert Phillips46eb3ab2021-08-02 17:09:01 -04001149
Herb Derbydd7540f2021-11-18 12:00:50 -05001150 bool canReuse(const SkPaint& paint, const SkMatrix& positionMatrix) const override;
Robert Phillips46eb3ab2021-08-02 17:09:01 -04001151
1152 GrAtlasSubRun* testingOnly_atlasSubRun() override;
Herb Derbye886b8e2020-11-06 10:58:23 -05001153
1154 void testingOnly_packedGlyphIDToGrGlyph(GrStrikeCache *cache) override;
1155
Robert Phillips71143952021-06-17 14:55:07 -04001156 std::tuple<bool, int> regenerateAtlas(int begin, int end, GrMeshDrawTarget*) const override;
Herb Derbye886b8e2020-11-06 10:58:23 -05001157
1158 void fillVertexData(
1159 void* vertexDst, int offset, int count,
Herb Derbydd7540f2021-11-18 12:00:50 -05001160 GrColor color,
1161 const SkMatrix& drawMatrix, SkPoint drawOrigin,
1162 SkIRect clip) const override;
Herb Derbye886b8e2020-11-06 10:58:23 -05001163
Herb Derby46d1e9f2020-12-01 14:12:04 -05001164 size_t vertexStride(const SkMatrix& drawMatrix) const override;
Herb Derbye886b8e2020-11-06 10:58:23 -05001165 int glyphCount() const override;
1166
1167private:
Herb Derbye886b8e2020-11-06 10:58:23 -05001168 // The rectangle that surrounds all the glyph bounding boxes in device space.
1169 SkRect deviceRect(const SkMatrix& drawMatrix, SkPoint drawOrigin) const;
1170
1171 const GrMaskFormat fMaskFormat;
1172 GrTextBlob* fBlob;
1173
Herb Derbyd4edc0e2021-11-09 15:32:17 -05001174 // The scale factor between the strike size, and the source size.
Herb Derby21f7a9a2021-11-08 10:06:54 -05001175 const SkScalar fStrikeToSourceScale;
1176
Herb Derbye886b8e2020-11-06 10:58:23 -05001177 // The bounds in source space. The bounds are the joined rectangles of all the glyphs.
1178 const SkRect fVertexBounds;
1179 const SkSpan<const VertexData> fVertexData;
1180
1181 // The regenerateAtlas method mutates fGlyphs. It should be called from onPrepare which must
1182 // be single threaded.
Herb Derby7d3886d2020-11-09 09:08:42 -05001183 mutable GlyphVector fGlyphs;
Herb Derbye886b8e2020-11-06 10:58:23 -05001184
1185 const bool fUseLCDText;
1186 const bool fAntiAliased;
1187};
1188
Herb Derby7d3886d2020-11-09 09:08:42 -05001189SDFTSubRun::SDFTSubRun(GrMaskFormat format,
1190 GrTextBlob* textBlob,
Herb Derby21f7a9a2021-11-08 10:06:54 -05001191 SkScalar strikeToSource,
Herb Derby7d3886d2020-11-09 09:08:42 -05001192 SkRect vertexBounds,
1193 SkSpan<const VertexData> vertexData,
Herb Derbya756c622021-11-10 11:05:46 -05001194 GlyphVector&& glyphs,
Herb Derby7d3886d2020-11-09 09:08:42 -05001195 bool useLCDText,
1196 bool antiAliased)
Herb Derby53453f72020-07-24 15:03:54 -04001197 : fMaskFormat{format}
1198 , fBlob{textBlob}
Herb Derby21f7a9a2021-11-08 10:06:54 -05001199 , fStrikeToSourceScale{strikeToSource}
Herb Derby53453f72020-07-24 15:03:54 -04001200 , fVertexBounds{vertexBounds}
1201 , fVertexData{vertexData}
Herb Derbya756c622021-11-10 11:05:46 -05001202 , fGlyphs{std::move(glyphs)}
Herb Derby53453f72020-07-24 15:03:54 -04001203 , fUseLCDText{useLCDText}
Herb Derbyd533add2021-11-04 10:57:09 -04001204 , fAntiAliased{antiAliased} {}
Herb Derby53453f72020-07-24 15:03:54 -04001205
Herb Derbye886b8e2020-11-06 10:58:23 -05001206bool has_some_antialiasing(const SkFont& font ) {
1207 SkFont::Edging edging = font.getEdging();
1208 return edging == SkFont::Edging::kAntiAlias
1209 || edging == SkFont::Edging::kSubpixelAntiAlias;
1210}
1211
Herb Derbyc1a06002021-03-11 10:57:16 -05001212GrSubRunOwner SDFTSubRun::Make(const SkZip<SkGlyphVariant, SkPoint>& drawables,
1213 const SkFont& runFont,
Herb Derbyadd2c392021-11-08 14:42:55 -05001214 sk_sp<SkStrike>&& strike,
Herb Derby21f7a9a2021-11-08 10:06:54 -05001215 SkScalar strikeToSourceScale,
Herb Derbyc1a06002021-03-11 10:57:16 -05001216 GrTextBlob* blob,
1217 GrSubRunAllocator* alloc) {
Herb Derby53453f72020-07-24 15:03:54 -04001218 SkRect bounds = SkRectPriv::MakeLargestInverted();
Herb Derby21f7a9a2021-11-08 10:06:54 -05001219 auto mapper = [&](const auto& d) {
Herb Derby15264442020-12-16 10:45:50 -05001220 auto& [variant, pos] = d;
Herb Derby53453f72020-07-24 15:03:54 -04001221 SkGlyph* skGlyph = variant;
Herb Derbybd51ac32020-12-01 14:41:18 -05001222 int16_t l = skGlyph->left(),
1223 t = skGlyph->top(),
1224 r = l + skGlyph->width(),
1225 b = t + skGlyph->height();
Herb Derby21f7a9a2021-11-08 10:06:54 -05001226 SkPoint lt = SkPoint::Make(l, t) * strikeToSourceScale + pos,
1227 rb = SkPoint::Make(r, b) * strikeToSourceScale + pos;
Herb Derby53453f72020-07-24 15:03:54 -04001228
1229 bounds.joinPossiblyEmptyRect(SkRect::MakeLTRB(lt.x(), lt.y(), rb.x(), rb.y()));
1230 return VertexData{pos, {l, t, r, b}};
1231 };
1232
Herb Derby15264442020-12-16 10:45:50 -05001233 SkSpan<VertexData> vertexData = alloc->makePODArray<VertexData>(drawables, mapper);
Herb Derby53453f72020-07-24 15:03:54 -04001234
Herb Derby15264442020-12-16 10:45:50 -05001235 return alloc->makeUnique<SDFTSubRun>(
Herb Derby53453f72020-07-24 15:03:54 -04001236 kA8_GrMaskFormat,
1237 blob,
Herb Derby21f7a9a2021-11-08 10:06:54 -05001238 strikeToSourceScale,
Herb Derby53453f72020-07-24 15:03:54 -04001239 bounds,
1240 vertexData,
Herb Derbyadd2c392021-11-08 14:42:55 -05001241 GlyphVector::Make(std::move(strike), drawables.get<0>(), alloc),
Herb Derby53453f72020-07-24 15:03:54 -04001242 runFont.getEdging() == SkFont::Edging::kSubpixelAntiAlias,
Herb Derbye886b8e2020-11-06 10:58:23 -05001243 has_some_antialiasing(runFont));
Herb Derby53453f72020-07-24 15:03:54 -04001244}
1245
Robert Phillips46eb3ab2021-08-02 17:09:01 -04001246void SDFTSubRun::draw(const GrClip* clip,
1247 const SkMatrixProvider& viewMatrix,
Herb Derbye6f2dce2021-11-22 10:34:03 -05001248 SkPoint drawOrigin,
Robert Phillips46eb3ab2021-08-02 17:09:01 -04001249 const SkPaint& paint,
1250 skgpu::v1::SurfaceDrawContext* sdc) const {
1251 auto[drawingClip, op] = this->makeAtlasTextOp(
Herb Derbye6f2dce2021-11-22 10:34:03 -05001252 clip, viewMatrix, drawOrigin, paint, sdc, nullptr);
Robert Phillips46eb3ab2021-08-02 17:09:01 -04001253 if (op != nullptr) {
1254 sdc->addDrawOp(drawingClip, std::move(op));
1255 }
1256}
1257
Robert Phillips31f76312021-08-27 12:35:41 -04001258static std::tuple<AtlasTextOp::MaskType, uint32_t, bool> calculate_sdf_parameters(
Robert Phillips4dca8312021-07-28 15:13:20 -04001259 const skgpu::v1::SurfaceDrawContext& sdc,
Herb Derby215104e2021-02-24 11:33:28 -05001260 const SkMatrix& drawMatrix,
1261 bool useLCDText,
1262 bool isAntiAliased) {
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001263 const GrColorInfo& colorInfo = sdc.colorInfo();
1264 const SkSurfaceProps& props = sdc.surfaceProps();
Herb Derby215104e2021-02-24 11:33:28 -05001265 bool isBGR = SkPixelGeometryIsBGR(props.pixelGeometry());
1266 bool isLCD = useLCDText && SkPixelGeometryIsH(props.pixelGeometry());
Robert Phillips31f76312021-08-27 12:35:41 -04001267 using MT = AtlasTextOp::MaskType;
Herb Derby215104e2021-02-24 11:33:28 -05001268 MT maskType = !isAntiAliased ? MT::kAliasedDistanceField
1269 : isLCD ? (isBGR ? MT::kLCDBGRDistanceField
1270 : MT::kLCDDistanceField)
1271 : MT::kGrayscaleDistanceField;
1272
1273 bool useGammaCorrectDistanceTable = colorInfo.isLinearlyBlended();
1274 uint32_t DFGPFlags = drawMatrix.isSimilarity() ? kSimilarity_DistanceFieldEffectFlag : 0;
1275 DFGPFlags |= drawMatrix.isScaleTranslate() ? kScaleOnly_DistanceFieldEffectFlag : 0;
1276 DFGPFlags |= useGammaCorrectDistanceTable ? kGammaCorrect_DistanceFieldEffectFlag : 0;
1277 DFGPFlags |= MT::kAliasedDistanceField == maskType ? kAliased_DistanceFieldEffectFlag : 0;
1278
1279 if (isLCD) {
1280 DFGPFlags |= kUseLCD_DistanceFieldEffectFlag;
1281 DFGPFlags |= MT::kLCDBGRDistanceField == maskType ? kBGR_DistanceFieldEffectFlag : 0;
1282 }
1283 return {maskType, DFGPFlags, useGammaCorrectDistanceTable};
1284}
1285
Herb Derbyc76d4092020-10-07 16:46:15 -04001286std::tuple<const GrClip*, GrOp::Owner >
Herb Derby7d3886d2020-11-09 09:08:42 -05001287SDFTSubRun::makeAtlasTextOp(const GrClip* clip,
1288 const SkMatrixProvider& viewMatrix,
Herb Derbyfe5b1332021-11-15 14:23:57 -05001289 SkPoint drawOrigin,
Herb Derby0da2c142021-03-22 15:28:23 -04001290 const SkPaint& paint,
Robert Phillips4dca8312021-07-28 15:13:20 -04001291 skgpu::v1::SurfaceDrawContext* sdc,
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001292 GrAtlasSubRunOwner) const {
Herb Derby53453f72020-07-24 15:03:54 -04001293 SkASSERT(this->glyphCount() != 0);
Herb Derbybd51ac32020-12-01 14:41:18 -05001294 SkASSERT(!viewMatrix.localToDevice().hasPerspective());
Herb Derby53453f72020-07-24 15:03:54 -04001295
Herb Derby53453f72020-07-24 15:03:54 -04001296 const SkMatrix& drawMatrix = viewMatrix.localToDevice();
Herb Derby53453f72020-07-24 15:03:54 -04001297
1298 GrPaint grPaint;
Herb Derby0da2c142021-03-22 15:28:23 -04001299 SkPMColor4f drawingColor = calculate_colors(sdc, paint, viewMatrix, fMaskFormat, &grPaint);
Herb Derby53453f72020-07-24 15:03:54 -04001300
Herb Derby215104e2021-02-24 11:33:28 -05001301 auto [maskType, DFGPFlags, useGammaCorrectDistanceTable] =
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001302 calculate_sdf_parameters(*sdc, drawMatrix, fUseLCDText, fAntiAliased);
Herb Derby53453f72020-07-24 15:03:54 -04001303
Robert Phillips31f76312021-08-27 12:35:41 -04001304 auto geometry = AtlasTextOp::Geometry::MakeForBlob(*this,
1305 drawMatrix,
1306 drawOrigin,
1307 SkIRect::MakeEmpty(),
1308 sk_ref_sp<GrTextBlob>(fBlob),
1309 drawingColor,
1310 sdc->arenaAlloc());
Herb Derby53453f72020-07-24 15:03:54 -04001311
Herb Derbybba18802021-03-31 16:45:54 -04001312 GrRecordingContext* const rContext = sdc->recordingContext();
Robert Phillips31f76312021-08-27 12:35:41 -04001313 GrOp::Owner op = GrOp::Make<AtlasTextOp>(rContext,
1314 maskType,
1315 true,
1316 this->glyphCount(),
1317 this->deviceRect(drawMatrix, drawOrigin),
1318 SkPaintPriv::ComputeLuminanceColor(paint),
1319 useGammaCorrectDistanceTable,
1320 DFGPFlags,
1321 geometry,
1322 std::move(grPaint));
Herb Derby53453f72020-07-24 15:03:54 -04001323
1324 return {clip, std::move(op)};
1325}
1326
Herb Derbydd7540f2021-11-18 12:00:50 -05001327bool SDFTSubRun::canReuse(const SkPaint& paint, const SkMatrix& positionMatrix) const {
1328 const SkMatrix& initialPositionMatrix = fBlob->initialPositionMatrix();
Herb Derby81c6d6e2020-09-03 17:10:45 -04001329
1330 // A scale outside of [blob.fMaxMinScale, blob.fMinMaxScale] would result in a different
1331 // distance field being generated, so we have to regenerate in those cases
Herb Derbydd7540f2021-11-18 12:00:50 -05001332 SkScalar newMaxScale = positionMatrix.getMaxScale();
1333 SkScalar oldMaxScale = initialPositionMatrix.getMaxScale();
Herb Derby81c6d6e2020-09-03 17:10:45 -04001334 SkScalar scaleAdjust = newMaxScale / oldMaxScale;
1335 auto [maxMinScale, minMaxScale] = fBlob->scaleBounds();
1336 if (scaleAdjust < maxMinScale || scaleAdjust > minMaxScale) {
1337 return false;
1338 }
1339 return true;
1340}
1341
Herb Derby7d3886d2020-11-09 09:08:42 -05001342void SDFTSubRun::testingOnly_packedGlyphIDToGrGlyph(GrStrikeCache *cache) {
Herb Derbyc27d5352020-08-12 13:58:34 -04001343 fGlyphs.packedGlyphIDToGrGlyph(cache);
1344}
1345
Herb Derby7d3886d2020-11-09 09:08:42 -05001346std::tuple<bool, int> SDFTSubRun::regenerateAtlas(
Robert Phillips71143952021-06-17 14:55:07 -04001347 int begin, int end, GrMeshDrawTarget *target) const {
Herb Derby53453f72020-07-24 15:03:54 -04001348
Herb Derby71984a42020-07-31 16:08:41 -04001349 return fGlyphs.regenerateAtlas(begin, end, fMaskFormat, SK_DistanceFieldInset, target);
Herb Derby53453f72020-07-24 15:03:54 -04001350}
1351
Herb Derby46d1e9f2020-12-01 14:12:04 -05001352size_t SDFTSubRun::vertexStride(const SkMatrix& drawMatrix) const {
Herb Derbybd51ac32020-12-01 14:41:18 -05001353 return sizeof(Mask2DVertex);
Herb Derby53453f72020-07-24 15:03:54 -04001354}
1355
Herb Derby7d3886d2020-11-09 09:08:42 -05001356void SDFTSubRun::fillVertexData(
Herb Derby64391c42020-05-16 14:32:15 -04001357 void *vertexDst, int offset, int count,
Herb Derbydd7540f2021-11-18 12:00:50 -05001358 GrColor color,
1359 const SkMatrix& drawMatrix, SkPoint drawOrigin,
1360 SkIRect clip) const {
1361 const SkMatrix positionMatrix = position_matrix(drawMatrix, drawOrigin);
Herb Derby64391c42020-05-16 14:32:15 -04001362
Herb Derbybd51ac32020-12-01 14:41:18 -05001363 using Quad = Mask2DVertex[4];
Herb Derby40894182020-12-02 11:39:48 -05001364 SkASSERT(sizeof(Quad) == this->vertexStride(positionMatrix) * kVerticesPerGlyph);
Herb Derbybd51ac32020-12-01 14:41:18 -05001365 fill_transformed_vertices_2D(
1366 SkMakeZip((Quad*)vertexDst,
1367 fGlyphs.glyphs().subspan(offset, count),
1368 fVertexData.subspan(offset, count)),
1369 SK_DistanceFieldInset,
Herb Derby21f7a9a2021-11-08 10:06:54 -05001370 fStrikeToSourceScale,
Herb Derbybd51ac32020-12-01 14:41:18 -05001371 color,
Herb Derby40894182020-12-02 11:39:48 -05001372 positionMatrix);
Herb Derby64391c42020-05-16 14:32:15 -04001373}
1374
Herb Derby7d3886d2020-11-09 09:08:42 -05001375int SDFTSubRun::glyphCount() const {
Brian Osmana3724292021-05-07 17:20:06 -04001376 return SkCount(fVertexData);
Herb Derbya9047642019-12-06 12:12:11 -05001377}
1378
Herb Derby7d3886d2020-11-09 09:08:42 -05001379SkRect SDFTSubRun::deviceRect(const SkMatrix& drawMatrix, SkPoint drawOrigin) const {
Herb Derbybe6c7132020-04-28 14:28:04 -04001380 SkRect outBounds = fVertexBounds;
Herb Derby09357cc2020-07-20 09:55:48 -04001381 outBounds.offset(drawOrigin);
1382 return drawMatrix.mapRect(outBounds);
Herb Derbybe6c7132020-04-28 14:28:04 -04001383}
Herb Derbyd90024d2020-11-20 10:21:32 -05001384
1385GrAtlasSubRun* SDFTSubRun::testingOnly_atlasSubRun() {
1386 return this;
1387}
Herb Derbye886b8e2020-11-06 10:58:23 -05001388} // namespace
1389
Herb Derbye886b8e2020-11-06 10:58:23 -05001390// -- GrTextBlob::Key ------------------------------------------------------------------------------
Herb Derby64477842021-03-08 13:47:06 -05001391
1392static SkColor compute_canonical_color(const SkPaint& paint, bool lcd) {
1393 SkColor canonicalColor = SkPaintPriv::ComputeLuminanceColor(paint);
1394 if (lcd) {
1395 // This is the correct computation for canonicalColor, but there are tons of cases where LCD
1396 // can be modified. For now we just regenerate if any run in a textblob has LCD.
1397 // TODO figure out where all of these modifications are and see if we can incorporate that
1398 // logic at a higher level *OR* use sRGB
1399 //canonicalColor = SkMaskGamma::CanonicalColor(canonicalColor);
1400
1401 // TODO we want to figure out a way to be able to use the canonical color on LCD text,
1402 // see the note above. We pick a placeholder value for LCD text to ensure we always match
1403 // the same key
1404 return SK_ColorTRANSPARENT;
1405 } else {
1406 // A8, though can have mixed BMP text but it shouldn't matter because BMP text won't have
1407 // gamma corrected masks anyways, nor color
1408 U8CPU lum = SkComputeLuminance(SkColorGetR(canonicalColor),
1409 SkColorGetG(canonicalColor),
1410 SkColorGetB(canonicalColor));
1411 // reduce to our finite number of bits
1412 canonicalColor = SkMaskGamma::CanonicalColor(SkColorSetRGB(lum, lum, lum));
1413 }
1414 return canonicalColor;
1415}
1416
1417auto GrTextBlob::Key::Make(const SkGlyphRunList& glyphRunList,
Herb Derby0da2c142021-03-22 15:28:23 -04001418 const SkPaint& paint,
Herb Derby64477842021-03-08 13:47:06 -05001419 const SkSurfaceProps& surfaceProps,
1420 const GrColorInfo& colorInfo,
1421 const SkMatrix& drawMatrix,
1422 const GrSDFTControl& control) -> std::tuple<bool, Key> {
Herb Derby64477842021-03-08 13:47:06 -05001423 SkMaskFilterBase::BlurRec blurRec;
1424 // It might be worth caching these things, but its not clear at this time
1425 // TODO for animated mask filters, this will fill up our cache. We need a safeguard here
Herb Derby0da2c142021-03-22 15:28:23 -04001426 const SkMaskFilter* maskFilter = paint.getMaskFilter();
Herb Derby64477842021-03-08 13:47:06 -05001427 bool canCache = glyphRunList.canCache() &&
Herb Derby0da2c142021-03-22 15:28:23 -04001428 !(paint.getPathEffect() ||
Herb Derby64477842021-03-08 13:47:06 -05001429 (maskFilter && !as_MFB(maskFilter)->asABlur(&blurRec)));
1430
1431 // If we're doing linear blending, then we can disable the gamma hacks.
1432 // Otherwise, leave them on. In either case, we still want the contrast boost:
1433 // TODO: Can we be even smarter about mask gamma based on the dest transfer function?
1434 SkScalerContextFlags scalerContextFlags = colorInfo.isLinearlyBlended()
1435 ? SkScalerContextFlags::kBoostContrast
1436 : SkScalerContextFlags::kFakeGammaAndBoostContrast;
1437
1438 GrTextBlob::Key key;
1439 if (canCache) {
1440 bool hasLCD = glyphRunList.anyRunsLCD();
1441
1442 // We canonicalize all non-lcd draws to use kUnknown_SkPixelGeometry
1443 SkPixelGeometry pixelGeometry =
1444 hasLCD ? surfaceProps.pixelGeometry() : kUnknown_SkPixelGeometry;
1445
Herb Derby0da2c142021-03-22 15:28:23 -04001446 GrColor canonicalColor = compute_canonical_color(paint, hasLCD);
Herb Derby64477842021-03-08 13:47:06 -05001447
1448 key.fPixelGeometry = pixelGeometry;
1449 key.fUniqueID = glyphRunList.uniqueID();
Herb Derby0da2c142021-03-22 15:28:23 -04001450 key.fStyle = paint.getStyle();
Herb Derby64477842021-03-08 13:47:06 -05001451 if (key.fStyle != SkPaint::kFill_Style) {
Herb Derby0da2c142021-03-22 15:28:23 -04001452 key.fFrameWidth = paint.getStrokeWidth();
1453 key.fMiterLimit = paint.getStrokeMiter();
1454 key.fJoin = paint.getStrokeJoin();
Herb Derby64477842021-03-08 13:47:06 -05001455 }
1456 key.fHasBlur = maskFilter != nullptr;
1457 if (key.fHasBlur) {
1458 key.fBlurRec = blurRec;
1459 }
1460 key.fCanonicalColor = canonicalColor;
1461 key.fScalerContextFlags = scalerContextFlags;
1462
1463 // Calculate the set of drawing types.
1464 key.fSetOfDrawingTypes = 0;
1465 for (auto& run : glyphRunList) {
Herb Derby0da2c142021-03-22 15:28:23 -04001466 key.fSetOfDrawingTypes |= control.drawingType(run.font(), paint, drawMatrix);
Herb Derby64477842021-03-08 13:47:06 -05001467 }
1468
1469 if (key.fSetOfDrawingTypes & GrSDFTControl::kDirect) {
1470 // Store the fractional offset of the position. We know that the matrix can't be
1471 // perspective at this point.
1472 SkPoint mappedOrigin = drawMatrix.mapOrigin();
Herb Derbydd7540f2021-11-18 12:00:50 -05001473 key.fPositionMatrix = drawMatrix;
1474 key.fPositionMatrix.setTranslateX(
Herb Derby64477842021-03-08 13:47:06 -05001475 mappedOrigin.x() - SkScalarFloorToScalar(mappedOrigin.x()));
Herb Derbydd7540f2021-11-18 12:00:50 -05001476 key.fPositionMatrix.setTranslateY(
Herb Derby64477842021-03-08 13:47:06 -05001477 mappedOrigin.y() - SkScalarFloorToScalar(mappedOrigin.y()));
1478 } else {
1479 // For path and SDFT, the matrix doesn't matter.
Herb Derbydd7540f2021-11-18 12:00:50 -05001480 key.fPositionMatrix = SkMatrix::I();
Herb Derby64477842021-03-08 13:47:06 -05001481 }
1482 }
1483
1484 return {canCache, key};
1485}
Herb Derbye886b8e2020-11-06 10:58:23 -05001486
1487bool GrTextBlob::Key::operator==(const GrTextBlob::Key& that) const {
1488 if (fUniqueID != that.fUniqueID) { return false; }
1489 if (fCanonicalColor != that.fCanonicalColor) { return false; }
1490 if (fStyle != that.fStyle) { return false; }
1491 if (fStyle != SkPaint::kFill_Style) {
1492 if (fFrameWidth != that.fFrameWidth ||
1493 fMiterLimit != that.fMiterLimit ||
1494 fJoin != that.fJoin) {
1495 return false;
1496 }
1497 }
1498 if (fPixelGeometry != that.fPixelGeometry) { return false; }
1499 if (fHasBlur != that.fHasBlur) { return false; }
1500 if (fHasBlur) {
1501 if (fBlurRec.fStyle != that.fBlurRec.fStyle || fBlurRec.fSigma != that.fBlurRec.fSigma) {
1502 return false;
1503 }
1504 }
1505 if (fScalerContextFlags != that.fScalerContextFlags) { return false; }
Herb Derbye4ef35c2021-03-01 11:49:32 -05001506
1507 // Just punt on perspective.
Herb Derbydd7540f2021-11-18 12:00:50 -05001508 if (fPositionMatrix.hasPerspective()) {
Herb Derbye4ef35c2021-03-01 11:49:32 -05001509 return false;
1510 }
1511
1512 if (fSetOfDrawingTypes != that.fSetOfDrawingTypes) {
1513 return false;
1514 }
1515
Herb Derbybf2dd2a2021-03-04 10:13:22 -05001516 if (fSetOfDrawingTypes & GrSDFTControl::kDirect) {
Herb Derbyfde5b832021-11-19 10:58:57 -05001517 auto [compatible, _] = can_use_direct(fPositionMatrix, that.fPositionMatrix);
Herb Derbye4ef35c2021-03-01 11:49:32 -05001518 return compatible;
1519 }
1520
Herb Derbye886b8e2020-11-06 10:58:23 -05001521 return true;
1522}
Herb Derbybe6c7132020-04-28 14:28:04 -04001523
Herb Derbya9047642019-12-06 12:12:11 -05001524// -- GrTextBlob -----------------------------------------------------------------------------------
1525void GrTextBlob::operator delete(void* p) { ::operator delete(p); }
1526void* GrTextBlob::operator new(size_t) { SK_ABORT("All blobs are created by placement new."); }
1527void* GrTextBlob::operator new(size_t, void* p) { return p; }
1528
1529GrTextBlob::~GrTextBlob() = default;
1530
Herb Derby63fe8e52021-03-08 13:22:56 -05001531sk_sp<GrTextBlob> GrTextBlob::Make(const SkGlyphRunList& glyphRunList,
Herb Derby0da2c142021-03-22 15:28:23 -04001532 const SkPaint& paint,
Herb Derbydd7540f2021-11-18 12:00:50 -05001533 const SkMatrix& positionMatrix,
Herb Derby63fe8e52021-03-08 13:22:56 -05001534 const GrSDFTControl& control,
1535 SkGlyphRunListPainter* painter) {
Herb Derbyc59e4482020-11-17 17:40:29 -05001536 // The difference in alignment from the per-glyph data to the SubRun;
1537 constexpr size_t alignDiff =
1538 alignof(DirectMaskSubRun) - alignof(DirectMaskSubRun::DevicePosition);
Herb Derby64391c42020-05-16 14:32:15 -04001539 constexpr size_t vertexDataToSubRunPadding = alignDiff > 0 ? alignDiff : 0;
Herb Derbyb42706c2020-07-23 14:55:38 -04001540 size_t totalGlyphCount = glyphRunList.totalGlyphCount();
Herb Derbyc59e4482020-11-17 17:40:29 -05001541
Herb Derby15264442020-12-16 10:45:50 -05001542 // The neededForSubRun is optimized for DirectMaskSubRun which is by far the most common case.
1543 size_t bytesNeededForSubRun = GrBagOfBytes::PlatformMinimumSizeWithOverhead(
Herb Derbyc59e4482020-11-17 17:40:29 -05001544 totalGlyphCount * sizeof(DirectMaskSubRun::DevicePosition)
Herb Derby7d3886d2020-11-09 09:08:42 -05001545 + GlyphVector::GlyphVectorSize(totalGlyphCount)
Herb Derby15264442020-12-16 10:45:50 -05001546 + glyphRunList.runCount() * (sizeof(DirectMaskSubRun) + vertexDataToSubRunPadding),
1547 alignof(GrTextBlob));
Herb Derbyc514e7d2019-12-11 17:00:31 -05001548
Herb Derby15264442020-12-16 10:45:50 -05001549 size_t allocationSize = sizeof(GrTextBlob) + bytesNeededForSubRun;
Ben Wagner75d6db72018-09-20 14:39:39 -04001550
Herb Derbycb718892019-12-07 00:07:42 -05001551 void* allocation = ::operator new (allocationSize);
Herb Derbyb12175f2018-05-23 16:38:09 -04001552
Herb Derby0da2c142021-03-22 15:28:23 -04001553 SkColor initialLuminance = SkPaintPriv::ComputeLuminanceColor(paint);
Herb Derby15264442020-12-16 10:45:50 -05001554 sk_sp<GrTextBlob> blob{new (allocation)
Herb Derbydd7540f2021-11-18 12:00:50 -05001555 GrTextBlob(bytesNeededForSubRun, positionMatrix, initialLuminance)};
joshualitt92303772016-02-10 11:55:52 -08001556
Herb Derby63fe8e52021-03-08 13:22:56 -05001557 for (auto& glyphRun : glyphRunList) {
1558 painter->processGlyphRun(glyphRun,
Herb Derbydd7540f2021-11-18 12:00:50 -05001559 positionMatrix,
Herb Derby0da2c142021-03-22 15:28:23 -04001560 paint,
Herb Derby63fe8e52021-03-08 13:22:56 -05001561 control,
Herb Derby7b39c3d2021-03-16 17:45:33 -04001562 blob.get(),
1563 "GrTextBlob");
Herb Derby63fe8e52021-03-08 13:22:56 -05001564 }
1565
Herb Derbyf7d5d742018-11-16 13:24:32 -05001566 return blob;
joshualitt92303772016-02-10 11:55:52 -08001567}
1568
Herb Derby00b2fdb2020-09-03 11:54:01 -04001569void GrTextBlob::addKey(const Key& key) {
1570 fKey = key;
1571}
Herb Derby81c6d6e2020-09-03 17:10:45 -04001572
Herb Derbydd7540f2021-11-18 12:00:50 -05001573bool GrTextBlob::hasPerspective() const { return fInitialPositionMatrix.hasPerspective(); }
Herb Derbya9047642019-12-06 12:12:11 -05001574
Herb Derbydd7540f2021-11-18 12:00:50 -05001575bool GrTextBlob::canReuse(const SkPaint& paint, const SkMatrix& positionMatrix) const {
Herb Derbya5b98602020-07-13 11:18:12 -04001576 // A singular matrix will create a GrTextBlob with no SubRuns, but unknown glyphs can
Herb Derby47c88cc2021-04-23 16:21:58 -04001577 // also cause empty runs. If there are no subRuns or some glyphs were excluded or perspective,
1578 // then regenerate when the matrices don't match.
1579 if ((fSubRunList.isEmpty() || fSomeGlyphsExcluded || hasPerspective()) &&
Herb Derbydd7540f2021-11-18 12:00:50 -05001580 fInitialPositionMatrix != positionMatrix)
Herb Derby47c88cc2021-04-23 16:21:58 -04001581 {
Herb Derbyafa90362020-07-08 12:20:11 -04001582 return false;
1583 }
1584
joshualittfd5f6c12015-12-10 07:44:50 -08001585 // If we have LCD text then our canonical color will be set to transparent, in this case we have
1586 // to regenerate the blob on any color change
1587 // We use the grPaint to get any color filter effects
1588 if (fKey.fCanonicalColor == SK_ColorTRANSPARENT &&
Herb Derbyaebc5f82019-12-10 14:07:10 -05001589 fInitialLuminance != SkPaintPriv::ComputeLuminanceColor(paint)) {
Herb Derby64688222020-06-08 14:19:57 -04001590 return false;
joshualittfd5f6c12015-12-10 07:44:50 -08001591 }
1592
Herb Derby743c6972021-02-23 12:57:56 -05001593 for (const GrSubRun& subRun : fSubRunList) {
Herb Derbydd7540f2021-11-18 12:00:50 -05001594 if (!subRun.canReuse(paint, positionMatrix)) {
Herb Derby64688222020-06-08 14:19:57 -04001595 return false;
joshualittfd5f6c12015-12-10 07:44:50 -08001596 }
joshualittfd5f6c12015-12-10 07:44:50 -08001597 }
1598
Herb Derby64688222020-06-08 14:19:57 -04001599 return true;
joshualittfd5f6c12015-12-10 07:44:50 -08001600}
1601
Herb Derbya9047642019-12-06 12:12:11 -05001602const GrTextBlob::Key& GrTextBlob::key() const { return fKey; }
1603size_t GrTextBlob::size() const { return fSize; }
1604
Herb Derby31adbc62020-05-29 12:59:22 -04001605template<typename AddSingleMaskFormat>
Herb Derbya9047642019-12-06 12:12:11 -05001606void GrTextBlob::addMultiMaskFormat(
Herb Derby31adbc62020-05-29 12:59:22 -04001607 AddSingleMaskFormat addSingle,
Herb Derbya9047642019-12-06 12:12:11 -05001608 const SkZip<SkGlyphVariant, SkPoint>& drawables,
Herb Derbyadd2c392021-11-08 14:42:55 -05001609 sk_sp<SkStrike>&& strike,
Herb Derby21f7a9a2021-11-08 10:06:54 -05001610 SkScalar strikeToSourceScale) {
Herb Derbya9047642019-12-06 12:12:11 -05001611 if (drawables.empty()) { return; }
1612
Herb Derbyadd2c392021-11-08 14:42:55 -05001613 auto addSameFormat = [&](const SkZip<SkGlyphVariant, SkPoint>& drawable,
1614 GrMaskFormat format,
1615 sk_sp<SkStrike>&& runStrike) {
Herb Derby21f7a9a2021-11-08 10:06:54 -05001616 GrSubRunOwner subRun = addSingle(
Herb Derbyadd2c392021-11-08 14:42:55 -05001617 drawable, std::move(runStrike), strikeToSourceScale, format, this, &fAlloc);
Herb Derby1c494942020-11-19 13:09:44 -05001618 if (subRun != nullptr) {
Herb Derby15264442020-12-16 10:45:50 -05001619 fSubRunList.append(std::move(subRun));
Herb Derby1c494942020-11-19 13:09:44 -05001620 } else {
1621 fSomeGlyphsExcluded = true;
1622 }
1623 };
1624
Herb Derbya9047642019-12-06 12:12:11 -05001625 auto glyphSpan = drawables.get<0>();
1626 SkGlyph* glyph = glyphSpan[0];
1627 GrMaskFormat format = GrGlyph::FormatFromSkGlyph(glyph->maskFormat());
1628 size_t startIndex = 0;
1629 for (size_t i = 1; i < drawables.size(); i++) {
1630 glyph = glyphSpan[i];
1631 GrMaskFormat nextFormat = GrGlyph::FormatFromSkGlyph(glyph->maskFormat());
1632 if (format != nextFormat) {
1633 auto sameFormat = drawables.subspan(startIndex, i - startIndex);
Herb Derbyadd2c392021-11-08 14:42:55 -05001634 // Take a ref on the strike. This should rarely happen.
1635 addSameFormat(sameFormat, format, sk_sp<SkStrike>(strike));
Herb Derbya9047642019-12-06 12:12:11 -05001636 format = nextFormat;
1637 startIndex = i;
1638 }
1639 }
1640 auto sameFormat = drawables.last(drawables.size() - startIndex);
Herb Derbyadd2c392021-11-08 14:42:55 -05001641 addSameFormat(sameFormat, format, std::move(strike));
Herb Derbye9f691d2019-12-04 12:11:13 -05001642}
1643
Herb Derby15264442020-12-16 10:45:50 -05001644GrTextBlob::GrTextBlob(int allocSize,
Herb Derbydd7540f2021-11-18 12:00:50 -05001645 const SkMatrix& positionMatrix,
Herb Derby692e59d2020-06-05 11:37:16 -04001646 SkColor initialLuminance)
Herb Derby15264442020-12-16 10:45:50 -05001647 : fAlloc{SkTAddOffset<char>(this, sizeof(GrTextBlob)), allocSize, allocSize/2}
1648 , fSize{allocSize}
Herb Derbydd7540f2021-11-18 12:00:50 -05001649 , fInitialPositionMatrix{positionMatrix}
Herb Derby15264442020-12-16 10:45:50 -05001650 , fInitialLuminance{initialLuminance} { }
Herb Derby00ae9592019-12-03 15:55:56 -05001651
Herb Derbya9047642019-12-06 12:12:11 -05001652void GrTextBlob::processDeviceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables,
Herb Derbyadd2c392021-11-08 14:42:55 -05001653 sk_sp<SkStrike>&& strike) {
1654 SkASSERT(strike != nullptr);
1655 this->addMultiMaskFormat(DirectMaskSubRun::Make, drawables, std::move(strike), 1);
Herb Derbya9047642019-12-06 12:12:11 -05001656}
Herb Derbyeba195f2019-12-03 16:44:47 -05001657
Herb Derbya9047642019-12-06 12:12:11 -05001658void GrTextBlob::processSourcePaths(const SkZip<SkGlyphVariant, SkPoint>& drawables,
1659 const SkFont& runFont,
Herb Derby37afdbc2021-11-02 20:50:19 -04001660 SkScalar strikeToSourceScale) {
Herb Derby15264442020-12-16 10:45:50 -05001661 fSubRunList.append(PathSubRun::Make(drawables,
Herb Derby7d3886d2020-11-09 09:08:42 -05001662 has_some_antialiasing(runFont),
Herb Derby37afdbc2021-11-02 20:50:19 -04001663 strikeToSourceScale,
Herb Derby15264442020-12-16 10:45:50 -05001664 &fAlloc));
Herb Derbyeba195f2019-12-03 16:44:47 -05001665}
1666
Herb Derbya9047642019-12-06 12:12:11 -05001667void GrTextBlob::processSourceSDFT(const SkZip<SkGlyphVariant, SkPoint>& drawables,
Herb Derbyadd2c392021-11-08 14:42:55 -05001668 sk_sp<SkStrike>&& strike,
Herb Derby21f7a9a2021-11-08 10:06:54 -05001669 SkScalar strikeToSourceScale,
Herb Derbya9047642019-12-06 12:12:11 -05001670 const SkFont& runFont,
1671 SkScalar minScale,
1672 SkScalar maxScale) {
Herb Derby6d2b7682021-02-23 13:21:37 -05001673
1674 fMaxMinScale = std::max(minScale, fMaxMinScale);
1675 fMinMaxScale = std::min(maxScale, fMinMaxScale);
Herb Derby21f7a9a2021-11-08 10:06:54 -05001676 fSubRunList.append(
Herb Derbyadd2c392021-11-08 14:42:55 -05001677 SDFTSubRun::Make(drawables, runFont, std::move(strike), strikeToSourceScale,this, &fAlloc));
joshualitt8e0ef292016-02-19 14:13:03 -08001678}
Herb Derbya9047642019-12-06 12:12:11 -05001679
1680void GrTextBlob::processSourceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables,
Herb Derbyadd2c392021-11-08 14:42:55 -05001681 sk_sp<SkStrike>&& strike,
Herb Derby21f7a9a2021-11-08 10:06:54 -05001682 SkScalar strikeToSourceScale) {
1683 this->addMultiMaskFormat(
Herb Derbyadd2c392021-11-08 14:42:55 -05001684 TransformedMaskSubRun::Make, drawables, std::move(strike), strikeToSourceScale);
Herb Derbya9047642019-12-06 12:12:11 -05001685}
Herb Derbyb33140a2021-02-08 17:57:03 -05001686
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001687// ----------------------------- Begin no cache implementation -------------------------------------
1688namespace {
1689// -- DirectMaskSubRunNoCache ----------------------------------------------------------------------
1690class DirectMaskSubRunNoCache final : public GrAtlasSubRun {
1691public:
1692 using DevicePosition = skvx::Vec<2, int16_t>;
1693
1694 DirectMaskSubRunNoCache(GrMaskFormat format,
1695 const SkRect& bounds,
1696 SkSpan<const DevicePosition> devicePositions,
Herb Derbya756c622021-11-10 11:05:46 -05001697 GlyphVector&& glyphs);
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001698
1699 static GrAtlasSubRunOwner Make(const SkZip<SkGlyphVariant, SkPoint>& drawables,
Herb Derbyadd2c392021-11-08 14:42:55 -05001700 sk_sp<SkStrike>&& strike,
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001701 GrMaskFormat format,
1702 GrSubRunAllocator* alloc);
1703
1704 size_t vertexStride(const SkMatrix& drawMatrix) const override;
1705
1706 int glyphCount() const override;
1707
1708 std::tuple<const GrClip*, GrOp::Owner>
Robert Phillips4dca8312021-07-28 15:13:20 -04001709 makeAtlasTextOp(const GrClip*,
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001710 const SkMatrixProvider& viewMatrix,
Herb Derbyfe5b1332021-11-15 14:23:57 -05001711 SkPoint,
Robert Phillips4dca8312021-07-28 15:13:20 -04001712 const SkPaint&,
1713 skgpu::v1::SurfaceDrawContext*,
1714 GrAtlasSubRunOwner) const override;
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001715
1716 void testingOnly_packedGlyphIDToGrGlyph(GrStrikeCache *cache) override;
1717
1718 std::tuple<bool, int>
Robert Phillips71143952021-06-17 14:55:07 -04001719 regenerateAtlas(int begin, int end, GrMeshDrawTarget*) const override;
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001720
Herb Derbydd7540f2021-11-18 12:00:50 -05001721 void fillVertexData(void* vertexDst, int offset, int count,
1722 GrColor color,
1723 const SkMatrix& drawMatrix, SkPoint drawOrigin,
1724 SkIRect clip) const override;
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001725
1726private:
1727 const GrMaskFormat fMaskFormat;
Herb Derby21f7a9a2021-11-08 10:06:54 -05001728
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001729 // The vertex bounds in device space. The bounds are the joined rectangles of all the glyphs.
1730 const SkRect fGlyphDeviceBounds;
1731 const SkSpan<const DevicePosition> fLeftTopDevicePos;
1732
1733 // Space for geometry
Robert Phillips31f76312021-08-27 12:35:41 -04001734 alignas(alignof(AtlasTextOp::Geometry)) char fGeom[sizeof(AtlasTextOp::Geometry)];
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001735
1736 // The regenerateAtlas method mutates fGlyphs. It should be called from onPrepare which must
1737 // be single threaded.
1738 mutable GlyphVector fGlyphs;
1739};
1740
1741DirectMaskSubRunNoCache::DirectMaskSubRunNoCache(GrMaskFormat format,
1742 const SkRect& deviceBounds,
1743 SkSpan<const DevicePosition> devicePositions,
Herb Derbya756c622021-11-10 11:05:46 -05001744 GlyphVector&& glyphs)
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001745 : fMaskFormat{format}
1746 , fGlyphDeviceBounds{deviceBounds}
1747 , fLeftTopDevicePos{devicePositions}
Herb Derbya756c622021-11-10 11:05:46 -05001748 , fGlyphs{std::move(glyphs)} { }
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001749
1750GrAtlasSubRunOwner DirectMaskSubRunNoCache::Make(const SkZip<SkGlyphVariant, SkPoint>& drawables,
Herb Derbyadd2c392021-11-08 14:42:55 -05001751 sk_sp<SkStrike>&& strike,
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001752 GrMaskFormat format,
1753 GrSubRunAllocator* alloc) {
1754 DevicePosition* glyphLeftTop = alloc->makePODArray<DevicePosition>(drawables.size());
1755
1756 GlyphVector::Variant* glyphIDs = static_cast<GlyphVector::Variant*>(
1757 alloc->alignedBytes(drawables.size() * sizeof(GlyphVector::Variant),
1758 alignof(GlyphVector::Variant)));
1759
1760 // Because this is the direct case, the maximum width or height is the size that fits in the
1761 // atlas. This boundary is checked below to ensure that the call to SkGlyphRect below will
1762 // not overflow.
1763 constexpr SkScalar kMaxPos =
1764 std::numeric_limits<int16_t>::max() - SkStrikeCommon::kSkSideTooBigForAtlas;
1765 SkGlyphRect runBounds = skglyph::empty_rect();
1766 size_t goodPosCount = 0;
1767 for (auto [variant, pos] : drawables) {
1768 auto [x, y] = pos;
1769 // Ensure that the .offset() call below does not overflow. And, at this point none of the
1770 // rectangles are empty because they were culled before the run was created. Basically,
1771 // cull all the glyphs that can't appear on the screen.
1772 if (-kMaxPos < x && x < kMaxPos && -kMaxPos < y && y < kMaxPos) {
1773 const SkGlyph* const skGlyph = variant;
1774 const SkGlyphRect deviceBounds =
1775 skGlyph->glyphRect().offset(SkScalarRoundToInt(x), SkScalarRoundToInt(y));
1776 runBounds = skglyph::rect_union(runBounds, deviceBounds);
1777 glyphLeftTop[goodPosCount] = deviceBounds.topLeft();
1778 glyphIDs[goodPosCount].packedGlyphID = skGlyph->getPackedID();
1779 goodPosCount += 1;
1780 }
1781 }
1782
1783 // Wow! no glyphs are in bounds and had non-empty bounds.
1784 if (goodPosCount == 0) {
1785 return nullptr;
1786 }
1787
1788 SkSpan<const DevicePosition> leftTop{glyphLeftTop, goodPosCount};
1789 return alloc->makeUnique<DirectMaskSubRunNoCache>(
1790 format, runBounds.rect(), leftTop,
Herb Derbyadd2c392021-11-08 14:42:55 -05001791 GlyphVector{std::move(strike), {glyphIDs, goodPosCount}});
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001792}
1793
1794size_t DirectMaskSubRunNoCache::vertexStride(const SkMatrix&) const {
1795 if (fMaskFormat != kARGB_GrMaskFormat) {
1796 return sizeof(Mask2DVertex);
1797 } else {
1798 return sizeof(ARGB2DVertex);
1799 }
1800}
1801
1802int DirectMaskSubRunNoCache::glyphCount() const {
Brian Osmana3724292021-05-07 17:20:06 -04001803 return SkCount(fGlyphs.glyphs());
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001804}
1805
1806std::tuple<const GrClip*, GrOp::Owner>
1807DirectMaskSubRunNoCache::makeAtlasTextOp(const GrClip* clip,
1808 const SkMatrixProvider& viewMatrix,
Herb Derbyfe5b1332021-11-15 14:23:57 -05001809 SkPoint drawOrigin,
Herb Derby0da2c142021-03-22 15:28:23 -04001810 const SkPaint& paint,
Robert Phillips4dca8312021-07-28 15:13:20 -04001811 skgpu::v1::SurfaceDrawContext* sdc,
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001812 GrAtlasSubRunOwner subRunOwner) const {
1813 SkASSERT(this->glyphCount() != 0);
1814
1815 const SkMatrix& drawMatrix = viewMatrix.localToDevice();
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001816
1817 // We can clip geometrically using clipRect and ignore clip when an axis-aligned rectangular
1818 // non-AA clip is used. If clipRect is empty, and clip is nullptr, then there is no clipping
1819 // needed.
1820 const SkRect deviceBounds = SkRect::MakeWH(sdc->width(), sdc->height());
1821 auto [clipMethod, clipRect] = calculate_clip(clip, deviceBounds, fGlyphDeviceBounds);
1822
1823 switch (clipMethod) {
1824 case kClippedOut:
1825 // Returning nullptr as op means skip this op.
1826 return {nullptr, nullptr};
1827 case kUnclipped:
1828 case kGeometryClipped:
1829 // GPU clip is not needed.
1830 clip = nullptr;
1831 break;
1832 case kGPUClipped:
1833 // Use the the GPU clip; clipRect is ignored.
1834 break;
1835 }
1836
1837 if (!clipRect.isEmpty()) { SkASSERT(clip == nullptr); }
1838
1839 GrPaint grPaint;
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001840 const SkPMColor4f drawingColor =
Herb Derby0da2c142021-03-22 15:28:23 -04001841 calculate_colors(sdc, paint, viewMatrix, fMaskFormat, &grPaint);
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001842
1843 GrRecordingContext* const rContext = sdc->recordingContext();
1844
Robert Phillips31f76312021-08-27 12:35:41 -04001845 auto geometry = new ((void*)fGeom) AtlasTextOp::Geometry{
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001846 *this,
1847 drawMatrix,
1848 drawOrigin,
1849 clipRect,
1850 nullptr,
1851 std::move(subRunOwner),
1852 drawingColor
1853 };
1854
Robert Phillips31f76312021-08-27 12:35:41 -04001855 GrOp::Owner op = GrOp::Make<AtlasTextOp>(rContext,
1856 op_mask_type(fMaskFormat),
1857 false,
1858 this->glyphCount(),
1859 fGlyphDeviceBounds,
1860 geometry,
1861 std::move(grPaint));
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001862
1863 return {clip, std::move(op)};
1864}
1865
1866void DirectMaskSubRunNoCache::testingOnly_packedGlyphIDToGrGlyph(GrStrikeCache *cache) {
1867 fGlyphs.packedGlyphIDToGrGlyph(cache);
1868}
1869
1870std::tuple<bool, int>
Robert Phillips71143952021-06-17 14:55:07 -04001871DirectMaskSubRunNoCache::regenerateAtlas(int begin, int end, GrMeshDrawTarget* target) const {
Herb Derby1830fb12021-11-23 11:29:58 -05001872 #if defined(SK_EXPERIMENTAL_ADD_ATLAS_PADDING)
1873 return fGlyphs.regenerateAtlas(begin, end, fMaskFormat, 1, target, true);
1874 #else
1875 return fGlyphs.regenerateAtlas(begin, end, fMaskFormat, 0, target, false);
1876 #endif
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001877}
1878
1879// The 99% case. No clip. Non-color only.
1880void direct_2D2(SkZip<Mask2DVertex[4],
1881 const GrGlyph*,
1882 const DirectMaskSubRunNoCache::DevicePosition> quadData,
1883 GrColor color) {
1884 for (auto[quad, glyph, leftTop] : quadData) {
1885 auto[al, at, ar, ab] = glyph->fAtlasLocator.getUVs();
1886 SkScalar dl = leftTop[0],
1887 dt = leftTop[1],
1888 dr = dl + (ar - al),
1889 db = dt + (ab - at);
1890
1891 quad[0] = {{dl, dt}, color, {al, at}}; // L,T
1892 quad[1] = {{dl, db}, color, {al, ab}}; // L,B
1893 quad[2] = {{dr, dt}, color, {ar, at}}; // R,T
1894 quad[3] = {{dr, db}, color, {ar, ab}}; // R,B
1895 }
1896}
1897
Herb Derbydd7540f2021-11-18 12:00:50 -05001898void DirectMaskSubRunNoCache::fillVertexData(void* vertexDst, int offset, int count,
1899 GrColor color,
1900 const SkMatrix& drawMatrix, SkPoint drawOrigin,
1901 SkIRect clip) const {
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001902 auto quadData = [&](auto dst) {
1903 return SkMakeZip(dst,
1904 fGlyphs.glyphs().subspan(offset, count),
1905 fLeftTopDevicePos.subspan(offset, count));
1906 };
1907
Herb Derbydd7540f2021-11-18 12:00:50 -05001908 // Notice that no matrix manipulation is needed because all the rectangles are already mapped
1909 // to device space.
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001910 if (clip.isEmpty()) {
1911 if (fMaskFormat != kARGB_GrMaskFormat) {
1912 using Quad = Mask2DVertex[4];
Herb Derbydd7540f2021-11-18 12:00:50 -05001913 SkASSERT(sizeof(Quad) == this->vertexStride(SkMatrix::I()) * kVerticesPerGlyph);
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001914 direct_2D2(quadData((Quad*)vertexDst), color);
1915 } else {
1916 using Quad = ARGB2DVertex[4];
Herb Derbydd7540f2021-11-18 12:00:50 -05001917 SkASSERT(sizeof(Quad) == this->vertexStride(SkMatrix::I()) * kVerticesPerGlyph);
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001918 generalized_direct_2D(quadData((Quad*)vertexDst), color, {0,0});
1919 }
1920 } else {
1921 if (fMaskFormat != kARGB_GrMaskFormat) {
1922 using Quad = Mask2DVertex[4];
Herb Derbydd7540f2021-11-18 12:00:50 -05001923 SkASSERT(sizeof(Quad) == this->vertexStride(SkMatrix::I()) * kVerticesPerGlyph);
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001924 generalized_direct_2D(quadData((Quad*)vertexDst), color, {0,0}, &clip);
1925 } else {
1926 using Quad = ARGB2DVertex[4];
Herb Derbydd7540f2021-11-18 12:00:50 -05001927 SkASSERT(sizeof(Quad) == this->vertexStride(SkMatrix::I()) * kVerticesPerGlyph);
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001928 generalized_direct_2D(quadData((Quad*)vertexDst), color, {0,0}, &clip);
1929 }
1930 }
1931}
1932
1933// -- TransformedMaskSubRunNoCache -----------------------------------------------------------------
1934class TransformedMaskSubRunNoCache final : public GrAtlasSubRun {
1935public:
1936 struct VertexData {
1937 const SkPoint pos;
1938 // The rectangle of the glyphs in strike space. But, for kDirectMask this also implies a
1939 // device space rect.
1940 GrIRect16 rect;
1941 };
1942
1943 TransformedMaskSubRunNoCache(GrMaskFormat format,
Herb Derby21f7a9a2021-11-08 10:06:54 -05001944 SkScalar strikeToSourceScale,
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001945 const SkRect& bounds,
1946 SkSpan<const VertexData> vertexData,
Herb Derbya756c622021-11-10 11:05:46 -05001947 GlyphVector&& glyphs);
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001948
1949 static GrAtlasSubRunOwner Make(const SkZip<SkGlyphVariant, SkPoint>& drawables,
Herb Derbyadd2c392021-11-08 14:42:55 -05001950 sk_sp<SkStrike>&& strike,
Herb Derby21f7a9a2021-11-08 10:06:54 -05001951 SkScalar strikeToSourceScale,
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001952 GrMaskFormat format,
1953 GrSubRunAllocator* alloc);
1954
1955 std::tuple<const GrClip*, GrOp::Owner>
Robert Phillips4dca8312021-07-28 15:13:20 -04001956 makeAtlasTextOp(const GrClip*,
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001957 const SkMatrixProvider& viewMatrix,
Herb Derbyfe5b1332021-11-15 14:23:57 -05001958 SkPoint drawOrigin,
Robert Phillips4dca8312021-07-28 15:13:20 -04001959 const SkPaint&,
1960 skgpu::v1::SurfaceDrawContext*,
1961 GrAtlasSubRunOwner) const override;
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001962
1963 void testingOnly_packedGlyphIDToGrGlyph(GrStrikeCache *cache) override;
1964
Robert Phillips71143952021-06-17 14:55:07 -04001965 std::tuple<bool, int> regenerateAtlas(int begin, int end, GrMeshDrawTarget*) const override;
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001966
1967 void fillVertexData(
1968 void* vertexDst, int offset, int count,
Herb Derbydd7540f2021-11-18 12:00:50 -05001969 GrColor color,
1970 const SkMatrix& drawMatrix, SkPoint drawOrigin,
1971 SkIRect clip) const override;
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001972
1973 size_t vertexStride(const SkMatrix& drawMatrix) const override;
1974 int glyphCount() const override;
1975
1976private:
1977 // The rectangle that surrounds all the glyph bounding boxes in device space.
1978 SkRect deviceRect(const SkMatrix& drawMatrix, SkPoint drawOrigin) const;
1979
1980 const GrMaskFormat fMaskFormat;
1981
Herb Derbyd4edc0e2021-11-09 15:32:17 -05001982 // The scale factor between the strike size, and the source size.
Herb Derby21f7a9a2021-11-08 10:06:54 -05001983 const SkScalar fStrikeToSourceScale;
1984
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001985 // The bounds in source space. The bounds are the joined rectangles of all the glyphs.
1986 const SkRect fVertexBounds;
1987 const SkSpan<const VertexData> fVertexData;
1988
1989 // Space for geometry
Robert Phillips31f76312021-08-27 12:35:41 -04001990 alignas(alignof(AtlasTextOp::Geometry)) char fGeom[sizeof(AtlasTextOp::Geometry)];
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001991
1992 // The regenerateAtlas method mutates fGlyphs. It should be called from onPrepare which must
1993 // be single threaded.
1994 mutable GlyphVector fGlyphs;
1995};
1996
1997TransformedMaskSubRunNoCache::TransformedMaskSubRunNoCache(GrMaskFormat format,
Herb Derby21f7a9a2021-11-08 10:06:54 -05001998 SkScalar strikeToSourceScale,
Herb Derby2e0b5bb2020-11-19 11:03:50 -05001999 const SkRect& bounds,
2000 SkSpan<const VertexData> vertexData,
Herb Derbya756c622021-11-10 11:05:46 -05002001 GlyphVector&& glyphs)
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002002 : fMaskFormat{format}
Herb Derby21f7a9a2021-11-08 10:06:54 -05002003 , fStrikeToSourceScale{strikeToSourceScale}
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002004 , fVertexBounds{bounds}
2005 , fVertexData{vertexData}
Herb Derbya756c622021-11-10 11:05:46 -05002006 , fGlyphs{std::move(glyphs)} {}
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002007
2008GrAtlasSubRunOwner TransformedMaskSubRunNoCache::Make(
2009 const SkZip<SkGlyphVariant, SkPoint>& drawables,
Herb Derbyadd2c392021-11-08 14:42:55 -05002010 sk_sp<SkStrike>&& strike,
Herb Derby21f7a9a2021-11-08 10:06:54 -05002011 SkScalar strikeToSourceScale,
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002012 GrMaskFormat format,
2013 GrSubRunAllocator* alloc) {
2014 SkRect bounds = SkRectPriv::MakeLargestInverted();
Herb Derby21f7a9a2021-11-08 10:06:54 -05002015 auto initializer = [&](auto drawable) {
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002016 auto [variant, pos] = drawable;
2017 SkGlyph* skGlyph = variant;
2018 int16_t l = skGlyph->left(),
2019 t = skGlyph->top(),
2020 r = l + skGlyph->width(),
2021 b = t + skGlyph->height();
Herb Derby21f7a9a2021-11-08 10:06:54 -05002022 SkPoint lt = SkPoint::Make(l, t) * strikeToSourceScale + pos,
2023 rb = SkPoint::Make(r, b) * strikeToSourceScale + pos;
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002024
2025 bounds.joinPossiblyEmptyRect(SkRect::MakeLTRB(lt.x(), lt.y(), rb.x(), rb.y()));
2026 return VertexData{pos, {l, t, r, b}};
2027 };
2028
2029 SkSpan<VertexData> vertexData = alloc->makePODArray<VertexData>(drawables, initializer);
2030
2031 return alloc->makeUnique<TransformedMaskSubRunNoCache>(
Herb Derby21f7a9a2021-11-08 10:06:54 -05002032 format, strikeToSourceScale, bounds, vertexData,
Herb Derbyadd2c392021-11-08 14:42:55 -05002033 GlyphVector::Make(std::move(strike), drawables.get<0>(), alloc));
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002034}
2035
2036std::tuple<const GrClip*, GrOp::Owner>
2037TransformedMaskSubRunNoCache::makeAtlasTextOp(const GrClip* clip,
2038 const SkMatrixProvider& viewMatrix,
Herb Derbyfe5b1332021-11-15 14:23:57 -05002039 SkPoint drawOrigin,
Herb Derby0da2c142021-03-22 15:28:23 -04002040 const SkPaint& paint,
Robert Phillips4dca8312021-07-28 15:13:20 -04002041 skgpu::v1::SurfaceDrawContext* sdc,
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002042 GrAtlasSubRunOwner subRunOwner) const {
2043 SkASSERT(this->glyphCount() != 0);
2044
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002045 const SkMatrix& drawMatrix = viewMatrix.localToDevice();
2046
2047 GrPaint grPaint;
Herb Derby0da2c142021-03-22 15:28:23 -04002048 SkPMColor4f drawingColor = calculate_colors(sdc, paint, viewMatrix, fMaskFormat, &grPaint);
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002049
2050 // We can clip geometrically using clipRect and ignore clip if we're not using SDFs or
2051 // transformed glyphs, and we have an axis-aligned rectangular non-AA clip.
Robert Phillips31f76312021-08-27 12:35:41 -04002052 auto geometry = new ((void*)fGeom) AtlasTextOp::Geometry{
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002053 *this,
2054 drawMatrix,
2055 drawOrigin,
2056 SkIRect::MakeEmpty(),
2057 nullptr,
2058 std::move(subRunOwner),
2059 drawingColor
2060 };
2061
2062 GrRecordingContext* rContext = sdc->recordingContext();
Robert Phillips31f76312021-08-27 12:35:41 -04002063 GrOp::Owner op = GrOp::Make<AtlasTextOp>(rContext,
2064 op_mask_type(fMaskFormat),
2065 true,
2066 this->glyphCount(),
2067 this->deviceRect(drawMatrix, drawOrigin),
2068 geometry,
2069 std::move(grPaint));
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002070 return {clip, std::move(op)};
2071}
2072
2073void TransformedMaskSubRunNoCache::testingOnly_packedGlyphIDToGrGlyph(GrStrikeCache *cache) {
2074 fGlyphs.packedGlyphIDToGrGlyph(cache);
2075}
2076
2077std::tuple<bool, int> TransformedMaskSubRunNoCache::regenerateAtlas(
Robert Phillips71143952021-06-17 14:55:07 -04002078 int begin, int end, GrMeshDrawTarget* target) const {
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002079 return fGlyphs.regenerateAtlas(begin, end, fMaskFormat, 1, target, true);
2080}
2081
2082void TransformedMaskSubRunNoCache::fillVertexData(
Herb Derbydd7540f2021-11-18 12:00:50 -05002083 void* vertexDst, int offset, int count,
2084 GrColor color,
2085 const SkMatrix& drawMatrix, SkPoint drawOrigin,
2086 SkIRect clip) const {
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002087 constexpr SkScalar kDstPadding = 0.f;
Herb Derbydd7540f2021-11-18 12:00:50 -05002088 const SkMatrix positionMatrix = position_matrix(drawMatrix, drawOrigin);
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002089
2090 auto quadData = [&](auto dst) {
2091 return SkMakeZip(dst,
2092 fGlyphs.glyphs().subspan(offset, count),
2093 fVertexData.subspan(offset, count));
2094 };
2095
2096 if (!positionMatrix.hasPerspective()) {
2097 if (fMaskFormat == GrMaskFormat::kARGB_GrMaskFormat) {
2098 using Quad = ARGB2DVertex[4];
2099 SkASSERT(sizeof(Quad) == this->vertexStride(positionMatrix) * kVerticesPerGlyph);
2100 fill_transformed_vertices_2D(
2101 quadData((Quad*) vertexDst),
2102 kDstPadding,
Herb Derby21f7a9a2021-11-08 10:06:54 -05002103 fStrikeToSourceScale,
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002104 color,
2105 positionMatrix);
2106 } else {
2107 using Quad = Mask2DVertex[4];
2108 SkASSERT(sizeof(Quad) == this->vertexStride(positionMatrix) * kVerticesPerGlyph);
2109 fill_transformed_vertices_2D(
2110 quadData((Quad*) vertexDst),
2111 kDstPadding,
Herb Derby21f7a9a2021-11-08 10:06:54 -05002112 fStrikeToSourceScale,
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002113 color,
2114 positionMatrix);
2115 }
2116 } else {
2117 if (fMaskFormat == GrMaskFormat::kARGB_GrMaskFormat) {
2118 using Quad = ARGB3DVertex[4];
2119 SkASSERT(sizeof(Quad) == this->vertexStride(positionMatrix) * kVerticesPerGlyph);
2120 fill_transformed_vertices_3D(
2121 quadData((Quad*) vertexDst),
2122 kDstPadding,
Herb Derby21f7a9a2021-11-08 10:06:54 -05002123 fStrikeToSourceScale,
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002124 color,
2125 positionMatrix);
2126 } else {
2127 using Quad = Mask3DVertex[4];
2128 SkASSERT(sizeof(Quad) == this->vertexStride(positionMatrix) * kVerticesPerGlyph);
2129 fill_transformed_vertices_3D(
2130 quadData((Quad*) vertexDst),
2131 kDstPadding,
Herb Derby21f7a9a2021-11-08 10:06:54 -05002132 fStrikeToSourceScale,
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002133 color,
2134 positionMatrix);
2135 }
2136 }
2137}
2138
2139size_t TransformedMaskSubRunNoCache::vertexStride(const SkMatrix& drawMatrix) const {
2140 switch (fMaskFormat) {
2141 case kA8_GrMaskFormat:
2142 return drawMatrix.hasPerspective() ? sizeof(Mask3DVertex) : sizeof(Mask2DVertex);
2143 case kARGB_GrMaskFormat:
2144 return drawMatrix.hasPerspective() ? sizeof(ARGB3DVertex) : sizeof(ARGB2DVertex);
2145 default:
2146 SkASSERT(!drawMatrix.hasPerspective());
2147 return sizeof(Mask2DVertex);
2148 }
2149 SkUNREACHABLE;
2150}
2151
2152int TransformedMaskSubRunNoCache::glyphCount() const {
Brian Osmana3724292021-05-07 17:20:06 -04002153 return SkCount(fVertexData);
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002154}
2155
2156SkRect TransformedMaskSubRunNoCache::deviceRect(
2157 const SkMatrix& drawMatrix, SkPoint drawOrigin) const {
2158 SkRect outBounds = fVertexBounds;
2159 outBounds.offset(drawOrigin);
2160 return drawMatrix.mapRect(outBounds);
2161}
2162
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002163// -- SDFTSubRunNoCache ----------------------------------------------------------------------------
2164class SDFTSubRunNoCache final : public GrAtlasSubRun {
2165public:
2166 struct VertexData {
2167 const SkPoint pos;
2168 // The rectangle of the glyphs in strike space.
2169 GrIRect16 rect;
2170 };
2171
2172 SDFTSubRunNoCache(GrMaskFormat format,
Herb Derby21f7a9a2021-11-08 10:06:54 -05002173 SkScalar strikeToSourceScale,
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002174 SkRect vertexBounds,
2175 SkSpan<const VertexData> vertexData,
Herb Derbya756c622021-11-10 11:05:46 -05002176 GlyphVector&& glyphs,
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002177 bool useLCDText,
2178 bool antiAliased);
2179
2180 static GrAtlasSubRunOwner Make(const SkZip<SkGlyphVariant, SkPoint>& drawables,
2181 const SkFont& runFont,
Herb Derbyadd2c392021-11-08 14:42:55 -05002182 sk_sp<SkStrike>&& strike,
Herb Derby21f7a9a2021-11-08 10:06:54 -05002183 SkScalar strikeToSourceScale,
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002184 GrSubRunAllocator* alloc);
2185
2186 std::tuple<const GrClip*, GrOp::Owner>
Robert Phillips4dca8312021-07-28 15:13:20 -04002187 makeAtlasTextOp(const GrClip*,
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002188 const SkMatrixProvider& viewMatrix,
Herb Derbyfe5b1332021-11-15 14:23:57 -05002189 SkPoint drawOrigin,
Robert Phillips4dca8312021-07-28 15:13:20 -04002190 const SkPaint&,
2191 skgpu::v1::SurfaceDrawContext*,
2192 GrAtlasSubRunOwner) const override;
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002193
2194 void testingOnly_packedGlyphIDToGrGlyph(GrStrikeCache *cache) override;
2195
Robert Phillips71143952021-06-17 14:55:07 -04002196 std::tuple<bool, int> regenerateAtlas(int begin, int end, GrMeshDrawTarget*) const override;
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002197
2198 void fillVertexData(
2199 void* vertexDst, int offset, int count,
Herb Derbydd7540f2021-11-18 12:00:50 -05002200 GrColor color,
2201 const SkMatrix& drawMatrix, SkPoint drawOrigin,
2202 SkIRect clip) const override;
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002203
2204 size_t vertexStride(const SkMatrix& drawMatrix) const override;
2205 int glyphCount() const override;
2206
2207private:
2208 // The rectangle that surrounds all the glyph bounding boxes in device space.
2209 SkRect deviceRect(const SkMatrix& drawMatrix, SkPoint drawOrigin) const;
2210
2211 const GrMaskFormat fMaskFormat;
2212
Herb Derbyd4edc0e2021-11-09 15:32:17 -05002213 // The scale factor between the strike size, and the source size.
Herb Derby21f7a9a2021-11-08 10:06:54 -05002214 const SkScalar fStrikeToSourceScale;
2215
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002216 // The bounds in source space. The bounds are the joined rectangles of all the glyphs.
2217 const SkRect fVertexBounds;
2218 const SkSpan<const VertexData> fVertexData;
2219
2220 // Space for geometry
Robert Phillips31f76312021-08-27 12:35:41 -04002221 alignas(alignof(AtlasTextOp::Geometry)) char fGeom[sizeof(AtlasTextOp::Geometry)];
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002222
2223 // The regenerateAtlas method mutates fGlyphs. It should be called from onPrepare which must
2224 // be single threaded.
2225 mutable GlyphVector fGlyphs;
2226
2227 const bool fUseLCDText;
2228 const bool fAntiAliased;
2229};
2230
2231SDFTSubRunNoCache::SDFTSubRunNoCache(GrMaskFormat format,
Herb Derby21f7a9a2021-11-08 10:06:54 -05002232 SkScalar strikeToSourceScale,
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002233 SkRect vertexBounds,
2234 SkSpan<const VertexData> vertexData,
Herb Derbya756c622021-11-10 11:05:46 -05002235 GlyphVector&& glyphs,
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002236 bool useLCDText,
2237 bool antiAliased)
2238 : fMaskFormat{format}
Herb Derby21f7a9a2021-11-08 10:06:54 -05002239 , fStrikeToSourceScale{strikeToSourceScale}
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002240 , fVertexBounds{vertexBounds}
2241 , fVertexData{vertexData}
Herb Derbya756c622021-11-10 11:05:46 -05002242 , fGlyphs{std::move(glyphs)}
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002243 , fUseLCDText{useLCDText}
Herb Derbyd533add2021-11-04 10:57:09 -04002244 , fAntiAliased{antiAliased} {}
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002245
2246
2247GrAtlasSubRunOwner SDFTSubRunNoCache::Make(
2248 const SkZip<SkGlyphVariant, SkPoint>& drawables,
2249 const SkFont& runFont,
Herb Derbyadd2c392021-11-08 14:42:55 -05002250 sk_sp<SkStrike>&& strike,
Herb Derby21f7a9a2021-11-08 10:06:54 -05002251 SkScalar strikeToSourceScale,
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002252 GrSubRunAllocator* alloc) {
2253
2254 SkRect bounds = SkRectPriv::MakeLargestInverted();
Herb Derby21f7a9a2021-11-08 10:06:54 -05002255 auto initializer = [&](auto drawable) {
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002256 auto [variant, pos] = drawable;
2257 SkGlyph* skGlyph = variant;
2258 int16_t l = skGlyph->left(),
2259 t = skGlyph->top(),
2260 r = l + skGlyph->width(),
2261 b = t + skGlyph->height();
Herb Derby21f7a9a2021-11-08 10:06:54 -05002262 SkPoint lt = SkPoint::Make(l, t) * strikeToSourceScale + pos,
2263 rb = SkPoint::Make(r, b) * strikeToSourceScale + pos;
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002264
2265 bounds.joinPossiblyEmptyRect(SkRect::MakeLTRB(lt.x(), lt.y(), rb.x(), rb.y()));
2266 return VertexData{pos, {l, t, r, b}};
2267 };
2268
2269 SkSpan<VertexData> vertexData = alloc->makePODArray<VertexData>(drawables, initializer);
2270
2271 return alloc->makeUnique<SDFTSubRunNoCache>(
2272 kA8_GrMaskFormat,
Herb Derby21f7a9a2021-11-08 10:06:54 -05002273 strikeToSourceScale,
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002274 bounds,
2275 vertexData,
Herb Derbyadd2c392021-11-08 14:42:55 -05002276 GlyphVector::Make(std::move(strike), drawables.get<0>(), alloc),
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002277 runFont.getEdging() == SkFont::Edging::kSubpixelAntiAlias,
2278 has_some_antialiasing(runFont));
2279}
2280
2281std::tuple<const GrClip*, GrOp::Owner>
2282SDFTSubRunNoCache::makeAtlasTextOp(const GrClip* clip,
2283 const SkMatrixProvider& viewMatrix,
Herb Derbyfe5b1332021-11-15 14:23:57 -05002284 SkPoint drawOrigin,
Herb Derby0da2c142021-03-22 15:28:23 -04002285 const SkPaint& paint,
Robert Phillips4dca8312021-07-28 15:13:20 -04002286 skgpu::v1::SurfaceDrawContext* sdc,
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002287 GrAtlasSubRunOwner subRunOwner) const {
2288 SkASSERT(this->glyphCount() != 0);
2289
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002290 const SkMatrix& drawMatrix = viewMatrix.localToDevice();
2291
2292 GrPaint grPaint;
Herb Derby0da2c142021-03-22 15:28:23 -04002293 SkPMColor4f drawingColor = calculate_colors(sdc, paint, viewMatrix, fMaskFormat, &grPaint);
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002294
2295 auto [maskType, DFGPFlags, useGammaCorrectDistanceTable] =
2296 calculate_sdf_parameters(*sdc, drawMatrix, fUseLCDText, fAntiAliased);
2297
Robert Phillips31f76312021-08-27 12:35:41 -04002298 auto geometry = new ((void*)fGeom) AtlasTextOp::Geometry {
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002299 *this,
2300 drawMatrix,
2301 drawOrigin,
2302 SkIRect::MakeEmpty(),
2303 nullptr,
2304 std::move(subRunOwner),
2305 drawingColor
2306 };
2307
2308 GrRecordingContext* rContext = sdc->recordingContext();
Robert Phillips31f76312021-08-27 12:35:41 -04002309 GrOp::Owner op = GrOp::Make<AtlasTextOp>(rContext,
2310 maskType,
2311 true,
2312 this->glyphCount(),
2313 this->deviceRect(drawMatrix, drawOrigin),
2314 SkPaintPriv::ComputeLuminanceColor(paint),
2315 useGammaCorrectDistanceTable,
2316 DFGPFlags,
2317 geometry,
2318 std::move(grPaint));
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002319
2320 return {clip, std::move(op)};
2321}
2322
2323void SDFTSubRunNoCache::testingOnly_packedGlyphIDToGrGlyph(GrStrikeCache *cache) {
2324 fGlyphs.packedGlyphIDToGrGlyph(cache);
2325}
2326
2327std::tuple<bool, int> SDFTSubRunNoCache::regenerateAtlas(
Robert Phillips71143952021-06-17 14:55:07 -04002328 int begin, int end, GrMeshDrawTarget *target) const {
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002329
2330 return fGlyphs.regenerateAtlas(begin, end, fMaskFormat, SK_DistanceFieldInset, target);
2331}
2332
2333size_t SDFTSubRunNoCache::vertexStride(const SkMatrix& drawMatrix) const {
2334 return sizeof(Mask2DVertex);
2335}
2336
2337void SDFTSubRunNoCache::fillVertexData(
2338 void *vertexDst, int offset, int count,
Herb Derbydd7540f2021-11-18 12:00:50 -05002339 GrColor color,
2340 const SkMatrix& drawMatrix, SkPoint drawOrigin,
2341 SkIRect clip) const {
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002342 using Quad = Mask2DVertex[4];
Herb Derbydd7540f2021-11-18 12:00:50 -05002343
2344 const SkMatrix positionMatrix = position_matrix(drawMatrix, drawOrigin);
2345
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002346 SkASSERT(sizeof(Quad) == this->vertexStride(positionMatrix) * kVerticesPerGlyph);
2347 fill_transformed_vertices_2D(
2348 SkMakeZip((Quad*)vertexDst,
2349 fGlyphs.glyphs().subspan(offset, count),
2350 fVertexData.subspan(offset, count)),
2351 SK_DistanceFieldInset,
Herb Derby21f7a9a2021-11-08 10:06:54 -05002352 fStrikeToSourceScale,
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002353 color,
2354 positionMatrix);
2355}
2356
2357int SDFTSubRunNoCache::glyphCount() const {
Brian Osmana3724292021-05-07 17:20:06 -04002358 return SkCount(fVertexData);
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002359}
2360
2361SkRect SDFTSubRunNoCache::deviceRect(const SkMatrix& drawMatrix, SkPoint drawOrigin) const {
2362 SkRect outBounds = fVertexBounds;
2363 outBounds.offset(drawOrigin);
2364 return drawMatrix.mapRect(outBounds);
2365}
2366} // namespace
2367
Robert Phillips4dca8312021-07-28 15:13:20 -04002368GrSubRunNoCachePainter::GrSubRunNoCachePainter(skgpu::v1::SurfaceDrawContext* sdc,
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002369 GrSubRunAllocator* alloc,
2370 const GrClip* clip,
2371 const SkMatrixProvider& viewMatrix,
Herb Derby0da2c142021-03-22 15:28:23 -04002372 const SkGlyphRunList& glyphRunList,
2373 const SkPaint& paint)
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002374 : fSDC{sdc}
2375 , fAlloc{alloc}
2376 , fClip{clip}
2377 , fViewMatrix{viewMatrix}
Herb Derby0da2c142021-03-22 15:28:23 -04002378 , fGlyphRunList{glyphRunList}
2379 , fPaint {paint} {}
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002380
2381void GrSubRunNoCachePainter::processDeviceMasks(
Herb Derbyadd2c392021-11-08 14:42:55 -05002382 const SkZip<SkGlyphVariant, SkPoint>& drawables, sk_sp<SkStrike>&& strike) {
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002383 if (drawables.empty()) { return; }
2384
2385 auto glyphSpan = drawables.get<0>();
2386 SkGlyph* glyph = glyphSpan[0];
2387 GrMaskFormat format = GrGlyph::FormatFromSkGlyph(glyph->maskFormat());
2388 size_t startIndex = 0;
2389 for (size_t i = 1; i < drawables.size(); i++) {
2390 glyph = glyphSpan[i];
2391 GrMaskFormat nextFormat = GrGlyph::FormatFromSkGlyph(glyph->maskFormat());
2392 if (format != nextFormat) {
2393 auto sameFormat = drawables.subspan(startIndex, i - startIndex);
Herb Derbyadd2c392021-11-08 14:42:55 -05002394 // Take an extra ref on the strike. This should rarely happen.
2395 this->draw(
2396 DirectMaskSubRunNoCache::Make(sameFormat, sk_sp<SkStrike>(strike), format, fAlloc));
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002397 format = nextFormat;
2398 startIndex = i;
2399 }
2400 }
2401 auto sameFormat = drawables.last(drawables.size() - startIndex);
Herb Derbyadd2c392021-11-08 14:42:55 -05002402 this->draw(DirectMaskSubRunNoCache::Make(sameFormat, std::move(strike), format, fAlloc));
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002403}
2404
Herb Derby21f7a9a2021-11-08 10:06:54 -05002405void GrSubRunNoCachePainter::processSourceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables,
Herb Derbyadd2c392021-11-08 14:42:55 -05002406 sk_sp<SkStrike>&& strike,
Herb Derby21f7a9a2021-11-08 10:06:54 -05002407 SkScalar strikeToSourceScale) {
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002408 if (drawables.empty()) {
2409 return;
2410 }
2411
2412 auto glyphSpan = drawables.get<0>();
2413 SkGlyph* glyph = glyphSpan[0];
2414 GrMaskFormat format = GrGlyph::FormatFromSkGlyph(glyph->maskFormat());
2415 size_t startIndex = 0;
2416 for (size_t i = 1; i < drawables.size(); i++) {
2417 glyph = glyphSpan[i];
2418 GrMaskFormat nextFormat = GrGlyph::FormatFromSkGlyph(glyph->maskFormat());
2419 if (format != nextFormat) {
2420 auto sameFormat = drawables.subspan(startIndex, i - startIndex);
2421 this->draw(
Herb Derbyadd2c392021-11-08 14:42:55 -05002422 // Add an extra ref to the strike. This should rarely happen.
2423 TransformedMaskSubRunNoCache::Make(
2424 sameFormat, sk_sp<SkStrike>(strike), strikeToSourceScale, format, fAlloc));
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002425 format = nextFormat;
2426 startIndex = i;
2427 }
2428 }
2429 auto sameFormat = drawables.last(drawables.size() - startIndex);
2430 this->draw(
Herb Derby21f7a9a2021-11-08 10:06:54 -05002431 TransformedMaskSubRunNoCache::Make(
Herb Derbyadd2c392021-11-08 14:42:55 -05002432 sameFormat, std::move(strike), strikeToSourceScale, format, fAlloc));
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002433}
2434
2435void GrSubRunNoCachePainter::processSourcePaths(const SkZip<SkGlyphVariant, SkPoint>& drawables,
2436 const SkFont& runFont,
Herb Derby37afdbc2021-11-02 20:50:19 -04002437 SkScalar strikeToSourceScale) {
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002438 SkASSERT(!drawables.empty());
2439 SkPoint drawOrigin = fGlyphRunList.origin();
Herb Derby0da2c142021-03-22 15:28:23 -04002440 const SkPaint& drawPaint = fPaint;
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002441 SkPaint runPaint{drawPaint};
2442 runPaint.setAntiAlias(has_some_antialiasing(runFont));
2443 // If there are shaders, blurs or styles, the path must be scaled into source
2444 // space independently of the CTM. This allows the CTM to be correct for the
2445 // different effects.
2446 GrStyle style(runPaint);
2447
2448 bool needsExactCTM = runPaint.getShader()
2449 || style.applies()
2450 || runPaint.getMaskFilter();
2451
2452 // Calculate the matrix that maps the path glyphs from their size in the strike to
2453 // the graphics source space.
Herb Derby37afdbc2021-11-02 20:50:19 -04002454 SkMatrix strikeToSource = SkMatrix::Scale(strikeToSourceScale, strikeToSourceScale);
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002455 strikeToSource.postTranslate(drawOrigin.x(), drawOrigin.y());
2456 if (!needsExactCTM) {
2457 for (auto [variant, pos] : drawables) {
2458 const SkPath& path = *variant.path();
2459 SkMatrix pathMatrix = strikeToSource;
2460 pathMatrix.postTranslate(pos.x(), pos.y());
2461 SkPreConcatMatrixProvider strikeToDevice(fViewMatrix, pathMatrix);
2462
2463 GrStyledShape shape(path, drawPaint);
2464 GrBlurUtils::drawShapeWithMaskFilter(
2465 fSDC->recordingContext(), fSDC, fClip, runPaint,
2466 strikeToDevice, shape);
2467 }
2468 } else {
2469 // Transform the path to device space because the deviceMatrix must be unchanged to
2470 // draw effect, filter or shader paths.
2471 for (auto [variant, pos] : drawables) {
2472 const SkPath& path = *variant.path();
2473 // Transform the glyph to source space.
2474 SkMatrix pathMatrix = strikeToSource;
2475 pathMatrix.postTranslate(pos.x(), pos.y());
2476
2477 SkPath sourceSpacePath;
2478 path.transform(pathMatrix, &sourceSpacePath);
2479 sourceSpacePath.setIsVolatile(true);
2480 GrStyledShape shape(sourceSpacePath, drawPaint);
2481 GrBlurUtils::drawShapeWithMaskFilter(
2482 fSDC->recordingContext(), fSDC, fClip, runPaint, fViewMatrix, shape);
2483 }
2484 }
2485}
2486
2487void GrSubRunNoCachePainter::processSourceSDFT(const SkZip<SkGlyphVariant, SkPoint>& drawables,
Herb Derbyadd2c392021-11-08 14:42:55 -05002488 sk_sp<SkStrike>&& strike,
Herb Derby21f7a9a2021-11-08 10:06:54 -05002489 SkScalar strikeToSourceScale,
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002490 const SkFont& runFont,
2491 SkScalar minScale, SkScalar maxScale) {
2492 if (drawables.empty()) {
2493 return;
2494 }
Herb Derby21f7a9a2021-11-08 10:06:54 -05002495 this->draw(SDFTSubRunNoCache::Make(
Herb Derbyadd2c392021-11-08 14:42:55 -05002496 drawables, runFont, std::move(strike), strikeToSourceScale, fAlloc));
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002497}
2498
2499void GrSubRunNoCachePainter::draw(GrAtlasSubRunOwner subRun) {
Herb Derby9b718cb2021-04-26 18:11:46 -04002500 if (subRun == nullptr) {
2501 return;
2502 }
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002503 GrAtlasSubRun* subRunPtr = subRun.get();
2504 auto [drawingClip, op] = subRunPtr->makeAtlasTextOp(
Herb Derbyfe5b1332021-11-15 14:23:57 -05002505 fClip, fViewMatrix, fGlyphRunList.origin(), fPaint, fSDC, std::move(subRun));
Herb Derby2e0b5bb2020-11-19 11:03:50 -05002506 if (op != nullptr) {
2507 fSDC->addDrawOp(drawingClip, std::move(op));
2508 }
2509}
2510