1ddd22d86455d95941ea21253b210819c1d4a3863joshualitt/*
2ddd22d86455d95941ea21253b210819c1d4a3863joshualitt * Copyright 2016 Google Inc.
3ddd22d86455d95941ea21253b210819c1d4a3863joshualitt *
4ddd22d86455d95941ea21253b210819c1d4a3863joshualitt * Use of this source code is governed by a BSD-style license that can be
5ddd22d86455d95941ea21253b210819c1d4a3863joshualitt * found in the LICENSE file.
6ddd22d86455d95941ea21253b210819c1d4a3863joshualitt */
7ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
8ddd22d86455d95941ea21253b210819c1d4a3863joshualitt#include "GrAtlasTextBlob.h"
9ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
10742e31de1599f3902810aecdf2e2e3eed3b40a09Brian Salomon#include "GrOpFlushState.h"
118e84a1ed07ad5d529d381d43302e597f31723076joshualitt#include "GrTextUtils.h"
12ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
13ddd22d86455d95941ea21253b210819c1d4a3863joshualitt#include "SkDistanceFieldGen.h"
14ddd22d86455d95941ea21253b210819c1d4a3863joshualitt#include "SkGlyphCache.h"
15ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
16895274391db8df7357334aec260edca2e1735626Brian Salomon#include "ops/GrAtlasTextOp.h"
17ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
18ddd22d86455d95941ea21253b210819c1d4a3863joshualitt////////////////////////////////////////////////////////////////////////////////////////////////////
19ddd22d86455d95941ea21253b210819c1d4a3863joshualitt// A large template to handle regenerating the vertices of a textblob with as few branches as
20ddd22d86455d95941ea21253b210819c1d4a3863joshualitt// possible
21ddd22d86455d95941ea21253b210819c1d4a3863joshualitttemplate <bool regenPos, bool regenCol, bool regenTexCoords>
22ddd22d86455d95941ea21253b210819c1d4a3863joshualittinline void regen_vertices(intptr_t vertex, const GrGlyph* glyph, size_t vertexStride,
23ddd22d86455d95941ea21253b210819c1d4a3863joshualitt                           bool useDistanceFields, SkScalar transX, SkScalar transY,
247023a00c35d904e4ccff09c377e9ba26abba6181jvanverth                           int32_t log2Width, int32_t log2Height,
25ddd22d86455d95941ea21253b210819c1d4a3863joshualitt                           GrColor color) {
26ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    int u0, v0, u1, v1;
27ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    if (regenTexCoords) {
28ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        SkASSERT(glyph);
29ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        int width = glyph->fBounds.width();
30ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        int height = glyph->fBounds.height();
31ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
32ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        if (useDistanceFields) {
33ddd22d86455d95941ea21253b210819c1d4a3863joshualitt            u0 = glyph->fAtlasLocation.fX + SK_DistanceFieldInset;
34ddd22d86455d95941ea21253b210819c1d4a3863joshualitt            v0 = glyph->fAtlasLocation.fY + SK_DistanceFieldInset;
35ddd22d86455d95941ea21253b210819c1d4a3863joshualitt            u1 = u0 + width - 2 * SK_DistanceFieldInset;
36ddd22d86455d95941ea21253b210819c1d4a3863joshualitt            v1 = v0 + height - 2 * SK_DistanceFieldInset;
37ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        } else {
38ddd22d86455d95941ea21253b210819c1d4a3863joshualitt            u0 = glyph->fAtlasLocation.fX;
39ddd22d86455d95941ea21253b210819c1d4a3863joshualitt            v0 = glyph->fAtlasLocation.fY;
40ddd22d86455d95941ea21253b210819c1d4a3863joshualitt            u1 = u0 + width;
41ddd22d86455d95941ea21253b210819c1d4a3863joshualitt            v1 = v0 + height;
42ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        }
437023a00c35d904e4ccff09c377e9ba26abba6181jvanverth
447023a00c35d904e4ccff09c377e9ba26abba6181jvanverth        // normalize
457023a00c35d904e4ccff09c377e9ba26abba6181jvanverth        u0 *= 65535;
467023a00c35d904e4ccff09c377e9ba26abba6181jvanverth        u0 >>= log2Width;
477023a00c35d904e4ccff09c377e9ba26abba6181jvanverth        u1 *= 65535;
487023a00c35d904e4ccff09c377e9ba26abba6181jvanverth        u1 >>= log2Width;
497023a00c35d904e4ccff09c377e9ba26abba6181jvanverth        v0 *= 65535;
507023a00c35d904e4ccff09c377e9ba26abba6181jvanverth        v0 >>= log2Height;
517023a00c35d904e4ccff09c377e9ba26abba6181jvanverth        v1 *= 65535;
527023a00c35d904e4ccff09c377e9ba26abba6181jvanverth        v1 >>= log2Height;
537023a00c35d904e4ccff09c377e9ba26abba6181jvanverth        SkASSERT(u0 >= 0 && u0 <= 65535);
547023a00c35d904e4ccff09c377e9ba26abba6181jvanverth        SkASSERT(u1 >= 0 && u1 <= 65535);
557023a00c35d904e4ccff09c377e9ba26abba6181jvanverth        SkASSERT(v0 >= 0 && v0 <= 65535);
567023a00c35d904e4ccff09c377e9ba26abba6181jvanverth        SkASSERT(v1 >= 0 && v1 <= 65535);
57ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    }
58ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
59ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    // This is a bit wonky, but sometimes we have LCD text, in which case we won't have color
60ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    // vertices, hence vertexStride - sizeof(SkIPoint16)
61ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    intptr_t colorOffset = sizeof(SkPoint);
62ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    intptr_t texCoordOffset = vertexStride - sizeof(SkIPoint16);
63ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
64ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    // V0
65ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    if (regenPos) {
66ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        SkPoint* point = reinterpret_cast<SkPoint*>(vertex);
67ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        point->fX += transX;
68ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        point->fY += transY;
69ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    }
70ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
71ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    if (regenCol) {
72ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset);
73ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        *vcolor = color;
74ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    }
75ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
76ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    if (regenTexCoords) {
777023a00c35d904e4ccff09c377e9ba26abba6181jvanverth        uint16_t* textureCoords = reinterpret_cast<uint16_t*>(vertex + texCoordOffset);
787023a00c35d904e4ccff09c377e9ba26abba6181jvanverth        textureCoords[0] = (uint16_t) u0;
797023a00c35d904e4ccff09c377e9ba26abba6181jvanverth        textureCoords[1] = (uint16_t) v0;
80ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    }
81ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    vertex += vertexStride;
82ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
83ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    // V1
84ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    if (regenPos) {
85ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        SkPoint* point = reinterpret_cast<SkPoint*>(vertex);
86ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        point->fX += transX;
87ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        point->fY += transY;
88ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    }
89ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
90ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    if (regenCol) {
91ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset);
92ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        *vcolor = color;
93ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    }
94ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
95ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    if (regenTexCoords) {
967023a00c35d904e4ccff09c377e9ba26abba6181jvanverth        uint16_t* textureCoords = reinterpret_cast<uint16_t*>(vertex + texCoordOffset);
977023a00c35d904e4ccff09c377e9ba26abba6181jvanverth        textureCoords[0] = (uint16_t)u0;
987023a00c35d904e4ccff09c377e9ba26abba6181jvanverth        textureCoords[1] = (uint16_t)v1;
99ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    }
100ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    vertex += vertexStride;
101ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
102ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    // V2
103ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    if (regenPos) {
104ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        SkPoint* point = reinterpret_cast<SkPoint*>(vertex);
105ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        point->fX += transX;
106ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        point->fY += transY;
107ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    }
108ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
109ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    if (regenCol) {
110ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset);
111ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        *vcolor = color;
112ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    }
113ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
114ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    if (regenTexCoords) {
1157023a00c35d904e4ccff09c377e9ba26abba6181jvanverth        uint16_t* textureCoords = reinterpret_cast<uint16_t*>(vertex + texCoordOffset);
1167023a00c35d904e4ccff09c377e9ba26abba6181jvanverth        textureCoords[0] = (uint16_t)u1;
1177023a00c35d904e4ccff09c377e9ba26abba6181jvanverth        textureCoords[1] = (uint16_t)v1;
118ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    }
119ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    vertex += vertexStride;
120ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
121ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    // V3
122ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    if (regenPos) {
123ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        SkPoint* point = reinterpret_cast<SkPoint*>(vertex);
124ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        point->fX += transX;
125ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        point->fY += transY;
126ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    }
127ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
128ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    if (regenCol) {
129ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset);
130ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        *vcolor = color;
131ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    }
132ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
133ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    if (regenTexCoords) {
1347023a00c35d904e4ccff09c377e9ba26abba6181jvanverth        uint16_t* textureCoords = reinterpret_cast<uint16_t*>(vertex + texCoordOffset);
1357023a00c35d904e4ccff09c377e9ba26abba6181jvanverth        textureCoords[0] = (uint16_t)u1;
1367023a00c35d904e4ccff09c377e9ba26abba6181jvanverth        textureCoords[1] = (uint16_t)v0;
137ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    }
138ddd22d86455d95941ea21253b210819c1d4a3863joshualitt}
139ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
140ddd22d86455d95941ea21253b210819c1d4a3863joshualitttemplate <bool regenPos, bool regenCol, bool regenTexCoords, bool regenGlyphs>
141f856fd1ccdd839646159767f6aa9a2f2a1b97f04Brian Salomonvoid GrAtlasTextBlob::regenInOp(GrDrawOp::Target* target, GrAtlasGlyphCache* fontCache,
142344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon                                GrBlobRegenHelper* helper, Run* run, Run::SubRunInfo* info,
143344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon                                SkAutoGlyphCache* lazyCache, int glyphCount, size_t vertexStride,
144344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon                                GrColor color, SkScalar transX, SkScalar transY) const {
145d1c71fd56c293afb986cb5e7546a3a8e4b190d48bsalomon    SkASSERT(lazyCache);
146ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    static_assert(!regenGlyphs || regenTexCoords, "must regenTexCoords along regenGlyphs");
147f856fd1ccdd839646159767f6aa9a2f2a1b97f04Brian Salomon    GrAtlasTextStrike* strike = nullptr;
148ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    if (regenTexCoords) {
149ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        info->resetBulkUseToken();
150ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
151d1c71fd56c293afb986cb5e7546a3a8e4b190d48bsalomon        const SkDescriptor* desc = (run->fOverrideDescriptor && !info->drawAsDistanceFields())
152d1c71fd56c293afb986cb5e7546a3a8e4b190d48bsalomon                                      ? run->fOverrideDescriptor->getDesc()
153d1c71fd56c293afb986cb5e7546a3a8e4b190d48bsalomon                                      : run->fDescriptor.getDesc();
154d1c71fd56c293afb986cb5e7546a3a8e4b190d48bsalomon
155d1c71fd56c293afb986cb5e7546a3a8e4b190d48bsalomon        if (!*lazyCache || (*lazyCache)->getDescriptor() != *desc) {
1568b6fa5e8a9016ebbf3a03009abc3845b71452550bsalomon            SkScalerContextEffects effects;
1578b6fa5e8a9016ebbf3a03009abc3845b71452550bsalomon            effects.fPathEffect = run->fPathEffect.get();
1588b6fa5e8a9016ebbf3a03009abc3845b71452550bsalomon            effects.fRasterizer = run->fRasterizer.get();
1598b6fa5e8a9016ebbf3a03009abc3845b71452550bsalomon            effects.fMaskFilter = run->fMaskFilter.get();
160144caf55ffc692bcda77703a73bb9a894f7d024fHal Canary            lazyCache->reset(SkGlyphCache::DetachCache(run->fTypeface.get(), effects, desc));
161ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        }
162ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
163ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        if (regenGlyphs) {
164d1c71fd56c293afb986cb5e7546a3a8e4b190d48bsalomon            strike = fontCache->getStrike(lazyCache->get());
165ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        } else {
166ddd22d86455d95941ea21253b210819c1d4a3863joshualitt            strike = info->strike();
167ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        }
168ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    }
169ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
170ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    bool brokenRun = false;
171ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    for (int glyphIdx = 0; glyphIdx < glyphCount; glyphIdx++) {
172ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        GrGlyph* glyph = nullptr;
1737023a00c35d904e4ccff09c377e9ba26abba6181jvanverth        int log2Width = 0, log2Height = 0;
174ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        if (regenTexCoords) {
175ddd22d86455d95941ea21253b210819c1d4a3863joshualitt            size_t glyphOffset = glyphIdx + info->glyphStartIndex();
176ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
177ddd22d86455d95941ea21253b210819c1d4a3863joshualitt            if (regenGlyphs) {
178ddd22d86455d95941ea21253b210819c1d4a3863joshualitt                // Get the id from the old glyph, and use the new strike to lookup
179ddd22d86455d95941ea21253b210819c1d4a3863joshualitt                // the glyph.
180ddd22d86455d95941ea21253b210819c1d4a3863joshualitt                GrGlyph::PackedID id = fGlyphs[glyphOffset]->fPackedID;
181d1c71fd56c293afb986cb5e7546a3a8e4b190d48bsalomon                fGlyphs[glyphOffset] = strike->getGlyph(id, info->maskFormat(), lazyCache->get());
182ddd22d86455d95941ea21253b210819c1d4a3863joshualitt                SkASSERT(id == fGlyphs[glyphOffset]->fPackedID);
183ddd22d86455d95941ea21253b210819c1d4a3863joshualitt            }
184ddd22d86455d95941ea21253b210819c1d4a3863joshualitt            glyph = fGlyphs[glyphOffset];
185ddd22d86455d95941ea21253b210819c1d4a3863joshualitt            SkASSERT(glyph && glyph->fMaskFormat == info->maskFormat());
186ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
187ddd22d86455d95941ea21253b210819c1d4a3863joshualitt            if (!fontCache->hasGlyph(glyph) &&
188d1c71fd56c293afb986cb5e7546a3a8e4b190d48bsalomon                !strike->addGlyphToAtlas(target, glyph, lazyCache->get(), info->maskFormat())) {
189ddd22d86455d95941ea21253b210819c1d4a3863joshualitt                helper->flush();
190ddd22d86455d95941ea21253b210819c1d4a3863joshualitt                brokenRun = glyphIdx > 0;
191ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
192ddd22d86455d95941ea21253b210819c1d4a3863joshualitt                SkDEBUGCODE(bool success =) strike->addGlyphToAtlas(target,
193ddd22d86455d95941ea21253b210819c1d4a3863joshualitt                                                                    glyph,
194d1c71fd56c293afb986cb5e7546a3a8e4b190d48bsalomon                                                                    lazyCache->get(),
195ddd22d86455d95941ea21253b210819c1d4a3863joshualitt                                                                    info->maskFormat());
196ddd22d86455d95941ea21253b210819c1d4a3863joshualitt                SkASSERT(success);
197ddd22d86455d95941ea21253b210819c1d4a3863joshualitt            }
198ddd22d86455d95941ea21253b210819c1d4a3863joshualitt            fontCache->addGlyphToBulkAndSetUseToken(info->bulkUseToken(), glyph,
199342bfc25de5b0452b1551bf9db4bf45eac7718b2bsalomon                                                    target->nextDrawToken());
2007023a00c35d904e4ccff09c377e9ba26abba6181jvanverth            log2Width = fontCache->log2Width(info->maskFormat());
2017023a00c35d904e4ccff09c377e9ba26abba6181jvanverth            log2Height = fontCache->log2Height(info->maskFormat());
202ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        }
203ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
204ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        intptr_t vertex = reinterpret_cast<intptr_t>(fVertices);
205ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        vertex += info->vertexStartIndex();
206344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon        vertex += vertexStride * glyphIdx * GrAtlasTextOp::kVerticesPerGlyph;
207ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        regen_vertices<regenPos, regenCol, regenTexCoords>(vertex, glyph, vertexStride,
208ddd22d86455d95941ea21253b210819c1d4a3863joshualitt                                                           info->drawAsDistanceFields(), transX,
2097023a00c35d904e4ccff09c377e9ba26abba6181jvanverth                                                           transY, log2Width, log2Height, color);
210ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        helper->incGlyphCount();
211ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    }
212ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
213ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    // We may have changed the color so update it here
214ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    info->setColor(color);
215ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    if (regenTexCoords) {
216ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        if (regenGlyphs) {
217ddd22d86455d95941ea21253b210819c1d4a3863joshualitt            info->setStrike(strike);
218ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        }
2192ee084e73056b0ad76b721017f576168b7306da3Brian Salomon        info->setAtlasGeneration(brokenRun ? GrDrawOpAtlas::kInvalidAtlasGeneration
2202ee084e73056b0ad76b721017f576168b7306da3Brian Salomon                                           : fontCache->atlasGeneration(info->maskFormat()));
221ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    }
222ddd22d86455d95941ea21253b210819c1d4a3863joshualitt}
223ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
224ddd22d86455d95941ea21253b210819c1d4a3863joshualittenum RegenMask {
225ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    kNoRegen    = 0x0,
226ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    kRegenPos   = 0x1,
227ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    kRegenCol   = 0x2,
228ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    kRegenTex   = 0x4,
229ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    kRegenGlyph = 0x8 | kRegenTex, // we have to regenerate the texture coords when we regen glyphs
230ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
231ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    // combinations
232d1c71fd56c293afb986cb5e7546a3a8e4b190d48bsalomon    kRegenPosCol = kRegenPos | kRegenCol,
233ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    kRegenPosTex = kRegenPos | kRegenTex,
234ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    kRegenPosTexGlyph = kRegenPos | kRegenGlyph,
235ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    kRegenPosColTex = kRegenPos | kRegenCol | kRegenTex,
236ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    kRegenPosColTexGlyph = kRegenPos | kRegenCol | kRegenGlyph,
237ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    kRegenColTex = kRegenCol | kRegenTex,
238ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    kRegenColTexGlyph = kRegenCol | kRegenGlyph,
239ddd22d86455d95941ea21253b210819c1d4a3863joshualitt};
240ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
241d1c71fd56c293afb986cb5e7546a3a8e4b190d48bsalomon#define REGEN_ARGS target, fontCache, helper, &run, &info, lazyCache, \
242ddd22d86455d95941ea21253b210819c1d4a3863joshualitt                   *glyphCount, vertexStride, color, transX, transY
243ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
24409d994ecb30de2e62a31af2c16307af31fe0e0b3Brian Salomonvoid GrAtlasTextBlob::regenInOp(GrDrawOp::Target* target,
24509d994ecb30de2e62a31af2c16307af31fe0e0b3Brian Salomon                                GrAtlasGlyphCache* fontCache,
24609d994ecb30de2e62a31af2c16307af31fe0e0b3Brian Salomon                                GrBlobRegenHelper* helper,
24709d994ecb30de2e62a31af2c16307af31fe0e0b3Brian Salomon                                int runIndex, int subRunIndex, SkAutoGlyphCache* lazyCache,
24809d994ecb30de2e62a31af2c16307af31fe0e0b3Brian Salomon                                size_t vertexStride, const SkMatrix& viewMatrix,
24909d994ecb30de2e62a31af2c16307af31fe0e0b3Brian Salomon                                SkScalar x, SkScalar y, GrColor color,
25009d994ecb30de2e62a31af2c16307af31fe0e0b3Brian Salomon                                void** vertices, size_t* byteCount, int* glyphCount) {
251ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    Run& run = fRuns[runIndex];
252ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    Run::SubRunInfo& info = run.fSubRunInfo[subRunIndex];
253ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
254ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    uint64_t currentAtlasGen = fontCache->atlasGeneration(info.maskFormat());
255ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
2568e0ef294d0fc310432308dc09b8a48a53f7aabc1joshualitt    // Compute translation if any
2578e0ef294d0fc310432308dc09b8a48a53f7aabc1joshualitt    SkScalar transX, transY;
2588e0ef294d0fc310432308dc09b8a48a53f7aabc1joshualitt    info.computeTranslation(viewMatrix, x, y, &transX, &transY);
2598e0ef294d0fc310432308dc09b8a48a53f7aabc1joshualitt
260f856fd1ccdd839646159767f6aa9a2f2a1b97f04Brian Salomon    // Because the GrAtlasGlyphCache may evict the strike a blob depends on using for
261ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    // generating its texture coords, we have to track whether or not the strike has
262ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    // been abandoned.  If it hasn't been abandoned, then we can use the GrGlyph*s as is
263ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    // otherwise we have to get the new strike, and use that to get the correct glyphs.
264ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    // Because we do not have the packed ids, and thus can't look up our glyphs in the
265ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    // new strike, we instead keep our ref to the old strike and use the packed ids from
266ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    // it.  These ids will still be valid as long as we hold the ref.  When we are done
267ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    // updating our cache of the GrGlyph*s, we drop our ref on the old strike
268ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    bool regenerateGlyphs = info.strike()->isAbandoned();
269ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    bool regenerateTextureCoords = info.atlasGeneration() != currentAtlasGen ||
270ddd22d86455d95941ea21253b210819c1d4a3863joshualitt                                   regenerateGlyphs;
271ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    bool regenerateColors = kARGB_GrMaskFormat != info.maskFormat() &&
272ddd22d86455d95941ea21253b210819c1d4a3863joshualitt                            info.color() != color;
273ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    bool regeneratePositions = transX != 0.f || transY != 0.f;
274ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    *glyphCount = info.glyphCount();
275ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
276ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    uint32_t regenMaskBits = kNoRegen;
277ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    regenMaskBits |= regeneratePositions ? kRegenPos : 0;
278ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    regenMaskBits |= regenerateColors ? kRegenCol : 0;
279ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    regenMaskBits |= regenerateTextureCoords ? kRegenTex : 0;
280ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    regenMaskBits |= regenerateGlyphs ? kRegenGlyph : 0;
281ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    RegenMask regenMask = (RegenMask)regenMaskBits;
282ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
283ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    switch (regenMask) {
284344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon        case kRegenPos:
285344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon            this->regenInOp<true, false, false, false>(REGEN_ARGS);
286344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon            break;
287344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon        case kRegenCol:
288344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon            this->regenInOp<false, true, false, false>(REGEN_ARGS);
289344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon            break;
290344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon        case kRegenTex:
291344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon            this->regenInOp<false, false, true, false>(REGEN_ARGS);
292344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon            break;
293344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon        case kRegenGlyph:
294344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon            this->regenInOp<false, false, true, true>(REGEN_ARGS);
295344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon            break;
296344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon
297344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon        // combinations
298344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon        case kRegenPosCol:
299344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon            this->regenInOp<true, true, false, false>(REGEN_ARGS);
300344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon            break;
301344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon        case kRegenPosTex:
302344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon            this->regenInOp<true, false, true, false>(REGEN_ARGS);
303344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon            break;
304344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon        case kRegenPosTexGlyph:
305344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon            this->regenInOp<true, false, true, true>(REGEN_ARGS);
306344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon            break;
307344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon        case kRegenPosColTex:
308344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon            this->regenInOp<true, true, true, false>(REGEN_ARGS);
309344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon            break;
310344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon        case kRegenPosColTexGlyph:
311344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon            this->regenInOp<true, true, true, true>(REGEN_ARGS);
312344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon            break;
313344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon        case kRegenColTex:
314344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon            this->regenInOp<false, true, true, false>(REGEN_ARGS);
315344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon            break;
316344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon        case kRegenColTexGlyph:
317344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon            this->regenInOp<false, true, true, true>(REGEN_ARGS);
318344ec42f60fd9d10f14d4ffaf8e7b7916bb20bccBrian Salomon            break;
319ddd22d86455d95941ea21253b210819c1d4a3863joshualitt        case kNoRegen:
320ddd22d86455d95941ea21253b210819c1d4a3863joshualitt            helper->incGlyphCount(*glyphCount);
321ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
322ddd22d86455d95941ea21253b210819c1d4a3863joshualitt            // set use tokens for all of the glyphs in our subrun.  This is only valid if we
323ddd22d86455d95941ea21253b210819c1d4a3863joshualitt            // have a valid atlas generation
324342bfc25de5b0452b1551bf9db4bf45eac7718b2bsalomon            fontCache->setUseTokenBulk(*info.bulkUseToken(), target->nextDrawToken(),
325ddd22d86455d95941ea21253b210819c1d4a3863joshualitt                                        info.maskFormat());
326ddd22d86455d95941ea21253b210819c1d4a3863joshualitt            break;
327ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    }
328ddd22d86455d95941ea21253b210819c1d4a3863joshualitt
329ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    *byteCount = info.byteCount();
330ddd22d86455d95941ea21253b210819c1d4a3863joshualitt    *vertices = fVertices + info.vertexStartIndex();
331ddd22d86455d95941ea21253b210819c1d4a3863joshualitt}
332