OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "GrAtlasTextBlob.h" | 8 #include "GrAtlasTextBlob.h" |
9 | 9 |
10 #include "GrBatchFlushState.h" | 10 #include "GrBatchFlushState.h" |
11 #include "GrTextUtils.h" | 11 #include "GrTextUtils.h" |
12 | 12 |
13 #include "SkDistanceFieldGen.h" | 13 #include "SkDistanceFieldGen.h" |
14 #include "SkGlyphCache.h" | 14 #include "SkGlyphCache.h" |
15 | 15 |
16 #include "batches/GrAtlasTextBatch.h" | 16 #include "batches/GrAtlasTextBatch.h" |
17 | 17 |
18 ////////////////////////////////////////////////////////////////////////////////
//////////////////// | 18 ////////////////////////////////////////////////////////////////////////////////
//////////////////// |
19 // A large template to handle regenerating the vertices of a textblob with as fe
w branches as | 19 // A large template to handle regenerating the vertices of a textblob with as fe
w branches as |
20 // possible | 20 // possible |
21 template <bool regenPos, bool regenCol, bool regenTexCoords> | 21 template <bool regenPos, bool regenCol, bool regenTexCoords> |
22 inline void regen_vertices(intptr_t vertex, const GrGlyph* glyph, size_t vertexS
tride, | 22 inline void regen_vertices(intptr_t vertex, const GrGlyph* glyph, size_t vertexS
tride, |
23 bool useDistanceFields, SkScalar transX, SkScalar tra
nsY, | 23 bool useDistanceFields, SkScalar transX, SkScalar tra
nsY, |
24 int32_t log2Width, int32_t log2Height, | |
25 GrColor color) { | 24 GrColor color) { |
26 int u0, v0, u1, v1; | 25 int u0, v0, u1, v1; |
27 if (regenTexCoords) { | 26 if (regenTexCoords) { |
28 SkASSERT(glyph); | 27 SkASSERT(glyph); |
29 int width = glyph->fBounds.width(); | 28 int width = glyph->fBounds.width(); |
30 int height = glyph->fBounds.height(); | 29 int height = glyph->fBounds.height(); |
31 | 30 |
32 if (useDistanceFields) { | 31 if (useDistanceFields) { |
33 u0 = glyph->fAtlasLocation.fX + SK_DistanceFieldInset; | 32 u0 = glyph->fAtlasLocation.fX + SK_DistanceFieldInset; |
34 v0 = glyph->fAtlasLocation.fY + SK_DistanceFieldInset; | 33 v0 = glyph->fAtlasLocation.fY + SK_DistanceFieldInset; |
35 u1 = u0 + width - 2 * SK_DistanceFieldInset; | 34 u1 = u0 + width - 2 * SK_DistanceFieldInset; |
36 v1 = v0 + height - 2 * SK_DistanceFieldInset; | 35 v1 = v0 + height - 2 * SK_DistanceFieldInset; |
37 } else { | 36 } else { |
38 u0 = glyph->fAtlasLocation.fX; | 37 u0 = glyph->fAtlasLocation.fX; |
39 v0 = glyph->fAtlasLocation.fY; | 38 v0 = glyph->fAtlasLocation.fY; |
40 u1 = u0 + width; | 39 u1 = u0 + width; |
41 v1 = v0 + height; | 40 v1 = v0 + height; |
42 } | 41 } |
43 | |
44 // normalize | |
45 u0 *= 65535; | |
46 u0 >>= log2Width; | |
47 u1 *= 65535; | |
48 u1 >>= log2Width; | |
49 v0 *= 65535; | |
50 v0 >>= log2Height; | |
51 v1 *= 65535; | |
52 v1 >>= log2Height; | |
53 SkASSERT(u0 >= 0 && u0 <= 65535); | |
54 SkASSERT(u1 >= 0 && u1 <= 65535); | |
55 SkASSERT(v0 >= 0 && v0 <= 65535); | |
56 SkASSERT(v1 >= 0 && v1 <= 65535); | |
57 } | 42 } |
58 | 43 |
59 // This is a bit wonky, but sometimes we have LCD text, in which case we won
't have color | 44 // This is a bit wonky, but sometimes we have LCD text, in which case we won
't have color |
60 // vertices, hence vertexStride - sizeof(SkIPoint16) | 45 // vertices, hence vertexStride - sizeof(SkIPoint16) |
61 intptr_t colorOffset = sizeof(SkPoint); | 46 intptr_t colorOffset = sizeof(SkPoint); |
62 intptr_t texCoordOffset = vertexStride - sizeof(SkIPoint16); | 47 intptr_t texCoordOffset = vertexStride - sizeof(SkIPoint16); |
63 | 48 |
64 // V0 | 49 // V0 |
65 if (regenPos) { | 50 if (regenPos) { |
66 SkPoint* point = reinterpret_cast<SkPoint*>(vertex); | 51 SkPoint* point = reinterpret_cast<SkPoint*>(vertex); |
67 point->fX += transX; | 52 point->fX += transX; |
68 point->fY += transY; | 53 point->fY += transY; |
69 } | 54 } |
70 | 55 |
71 if (regenCol) { | 56 if (regenCol) { |
72 SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset); | 57 SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset); |
73 *vcolor = color; | 58 *vcolor = color; |
74 } | 59 } |
75 | 60 |
76 if (regenTexCoords) { | 61 if (regenTexCoords) { |
77 uint16_t* textureCoords = reinterpret_cast<uint16_t*>(vertex + texCoordO
ffset); | 62 SkIPoint16* textureCoords = reinterpret_cast<SkIPoint16*>(vertex + texCo
ordOffset); |
78 textureCoords[0] = (uint16_t) u0; | 63 textureCoords->set(u0, v0); |
79 textureCoords[1] = (uint16_t) v0; | |
80 } | 64 } |
81 vertex += vertexStride; | 65 vertex += vertexStride; |
82 | 66 |
83 // V1 | 67 // V1 |
84 if (regenPos) { | 68 if (regenPos) { |
85 SkPoint* point = reinterpret_cast<SkPoint*>(vertex); | 69 SkPoint* point = reinterpret_cast<SkPoint*>(vertex); |
86 point->fX += transX; | 70 point->fX += transX; |
87 point->fY += transY; | 71 point->fY += transY; |
88 } | 72 } |
89 | 73 |
90 if (regenCol) { | 74 if (regenCol) { |
91 SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset); | 75 SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset); |
92 *vcolor = color; | 76 *vcolor = color; |
93 } | 77 } |
94 | 78 |
95 if (regenTexCoords) { | 79 if (regenTexCoords) { |
96 uint16_t* textureCoords = reinterpret_cast<uint16_t*>(vertex + texCoordO
ffset); | 80 SkIPoint16* textureCoords = reinterpret_cast<SkIPoint16*>(vertex + texCo
ordOffset); |
97 textureCoords[0] = (uint16_t)u0; | 81 textureCoords->set(u0, v1); |
98 textureCoords[1] = (uint16_t)v1; | |
99 } | 82 } |
100 vertex += vertexStride; | 83 vertex += vertexStride; |
101 | 84 |
102 // V2 | 85 // V2 |
103 if (regenPos) { | 86 if (regenPos) { |
104 SkPoint* point = reinterpret_cast<SkPoint*>(vertex); | 87 SkPoint* point = reinterpret_cast<SkPoint*>(vertex); |
105 point->fX += transX; | 88 point->fX += transX; |
106 point->fY += transY; | 89 point->fY += transY; |
107 } | 90 } |
108 | 91 |
109 if (regenCol) { | 92 if (regenCol) { |
110 SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset); | 93 SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset); |
111 *vcolor = color; | 94 *vcolor = color; |
112 } | 95 } |
113 | 96 |
114 if (regenTexCoords) { | 97 if (regenTexCoords) { |
115 uint16_t* textureCoords = reinterpret_cast<uint16_t*>(vertex + texCoordO
ffset); | 98 SkIPoint16* textureCoords = reinterpret_cast<SkIPoint16*>(vertex + texCo
ordOffset); |
116 textureCoords[0] = (uint16_t)u1; | 99 textureCoords->set(u1, v1); |
117 textureCoords[1] = (uint16_t)v1; | |
118 } | 100 } |
119 vertex += vertexStride; | 101 vertex += vertexStride; |
120 | 102 |
121 // V3 | 103 // V3 |
122 if (regenPos) { | 104 if (regenPos) { |
123 SkPoint* point = reinterpret_cast<SkPoint*>(vertex); | 105 SkPoint* point = reinterpret_cast<SkPoint*>(vertex); |
124 point->fX += transX; | 106 point->fX += transX; |
125 point->fY += transY; | 107 point->fY += transY; |
126 } | 108 } |
127 | 109 |
128 if (regenCol) { | 110 if (regenCol) { |
129 SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset); | 111 SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset); |
130 *vcolor = color; | 112 *vcolor = color; |
131 } | 113 } |
132 | 114 |
133 if (regenTexCoords) { | 115 if (regenTexCoords) { |
134 uint16_t* textureCoords = reinterpret_cast<uint16_t*>(vertex + texCoordO
ffset); | 116 SkIPoint16* textureCoords = reinterpret_cast<SkIPoint16*>(vertex + texCo
ordOffset); |
135 textureCoords[0] = (uint16_t)u1; | 117 textureCoords->set(u1, v0); |
136 textureCoords[1] = (uint16_t)v0; | |
137 } | 118 } |
138 } | 119 } |
139 | 120 |
140 template <bool regenPos, bool regenCol, bool regenTexCoords, bool regenGlyphs> | 121 template <bool regenPos, bool regenCol, bool regenTexCoords, bool regenGlyphs> |
141 void GrAtlasTextBlob::regenInBatch(GrDrawBatch::Target* target, | 122 void GrAtlasTextBlob::regenInBatch(GrDrawBatch::Target* target, |
142 GrBatchFontCache* fontCache, | 123 GrBatchFontCache* fontCache, |
143 GrBlobRegenHelper *helper, | 124 GrBlobRegenHelper *helper, |
144 Run* run, | 125 Run* run, |
145 Run::SubRunInfo* info, SkGlyphCache** cache, | 126 Run::SubRunInfo* info, SkGlyphCache** cache, |
146 SkTypeface** typeface, GrFontScaler** scaler, | 127 SkTypeface** typeface, GrFontScaler** scaler, |
(...skipping 26 matching lines...) Expand all Loading... |
173 if (regenGlyphs) { | 154 if (regenGlyphs) { |
174 strike = fontCache->getStrike(*scaler); | 155 strike = fontCache->getStrike(*scaler); |
175 } else { | 156 } else { |
176 strike = info->strike(); | 157 strike = info->strike(); |
177 } | 158 } |
178 } | 159 } |
179 | 160 |
180 bool brokenRun = false; | 161 bool brokenRun = false; |
181 for (int glyphIdx = 0; glyphIdx < glyphCount; glyphIdx++) { | 162 for (int glyphIdx = 0; glyphIdx < glyphCount; glyphIdx++) { |
182 GrGlyph* glyph = nullptr; | 163 GrGlyph* glyph = nullptr; |
183 int log2Width = 0, log2Height = 0; | |
184 if (regenTexCoords) { | 164 if (regenTexCoords) { |
185 size_t glyphOffset = glyphIdx + info->glyphStartIndex(); | 165 size_t glyphOffset = glyphIdx + info->glyphStartIndex(); |
186 | 166 |
187 if (regenGlyphs) { | 167 if (regenGlyphs) { |
188 // Get the id from the old glyph, and use the new strike to look
up | 168 // Get the id from the old glyph, and use the new strike to look
up |
189 // the glyph. | 169 // the glyph. |
190 GrGlyph::PackedID id = fGlyphs[glyphOffset]->fPackedID; | 170 GrGlyph::PackedID id = fGlyphs[glyphOffset]->fPackedID; |
191 fGlyphs[glyphOffset] = strike->getGlyph(id, info->maskFormat(),
*scaler); | 171 fGlyphs[glyphOffset] = strike->getGlyph(id, info->maskFormat(),
*scaler); |
192 SkASSERT(id == fGlyphs[glyphOffset]->fPackedID); | 172 SkASSERT(id == fGlyphs[glyphOffset]->fPackedID); |
193 } | 173 } |
194 glyph = fGlyphs[glyphOffset]; | 174 glyph = fGlyphs[glyphOffset]; |
195 SkASSERT(glyph && glyph->fMaskFormat == info->maskFormat()); | 175 SkASSERT(glyph && glyph->fMaskFormat == info->maskFormat()); |
196 | 176 |
197 if (!fontCache->hasGlyph(glyph) && | 177 if (!fontCache->hasGlyph(glyph) && |
198 !strike->addGlyphToAtlas(target, glyph, *scaler, info->maskForma
t())) { | 178 !strike->addGlyphToAtlas(target, glyph, *scaler, info->maskForma
t())) { |
199 helper->flush(); | 179 helper->flush(); |
200 brokenRun = glyphIdx > 0; | 180 brokenRun = glyphIdx > 0; |
201 | 181 |
202 SkDEBUGCODE(bool success =) strike->addGlyphToAtlas(target, | 182 SkDEBUGCODE(bool success =) strike->addGlyphToAtlas(target, |
203 glyph, | 183 glyph, |
204 *scaler, | 184 *scaler, |
205 info->maskFo
rmat()); | 185 info->maskFo
rmat()); |
206 SkASSERT(success); | 186 SkASSERT(success); |
207 } | 187 } |
208 fontCache->addGlyphToBulkAndSetUseToken(info->bulkUseToken(), glyph, | 188 fontCache->addGlyphToBulkAndSetUseToken(info->bulkUseToken(), glyph, |
209 target->currentToken()); | 189 target->currentToken()); |
210 log2Width = fontCache->log2Width(info->maskFormat()); | |
211 log2Height = fontCache->log2Height(info->maskFormat()); | |
212 } | 190 } |
213 | 191 |
214 intptr_t vertex = reinterpret_cast<intptr_t>(fVertices); | 192 intptr_t vertex = reinterpret_cast<intptr_t>(fVertices); |
215 vertex += info->vertexStartIndex(); | 193 vertex += info->vertexStartIndex(); |
216 vertex += vertexStride * glyphIdx * GrAtlasTextBatch::kVerticesPerGlyph; | 194 vertex += vertexStride * glyphIdx * GrAtlasTextBatch::kVerticesPerGlyph; |
217 regen_vertices<regenPos, regenCol, regenTexCoords>(vertex, glyph, vertex
Stride, | 195 regen_vertices<regenPos, regenCol, regenTexCoords>(vertex, glyph, vertex
Stride, |
218 info->drawAsDistanceF
ields(), transX, | 196 info->drawAsDistanceF
ields(), transX, |
219 transY, log2Width, lo
g2Height, color); | 197 transY, color); |
220 helper->incGlyphCount(); | 198 helper->incGlyphCount(); |
221 } | 199 } |
222 | 200 |
223 // We may have changed the color so update it here | 201 // We may have changed the color so update it here |
224 info->setColor(color); | 202 info->setColor(color); |
225 if (regenTexCoords) { | 203 if (regenTexCoords) { |
226 if (regenGlyphs) { | 204 if (regenGlyphs) { |
227 info->setStrike(strike); | 205 info->setStrike(strike); |
228 } | 206 } |
229 info->setAtlasGeneration(brokenRun ? GrBatchAtlas::kInvalidAtlasGenerati
on : | 207 info->setAtlasGeneration(brokenRun ? GrBatchAtlas::kInvalidAtlasGenerati
on : |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
308 // set use tokens for all of the glyphs in our subrun. This is only
valid if we | 286 // set use tokens for all of the glyphs in our subrun. This is only
valid if we |
309 // have a valid atlas generation | 287 // have a valid atlas generation |
310 fontCache->setUseTokenBulk(*info.bulkUseToken(), target->currentToke
n(), | 288 fontCache->setUseTokenBulk(*info.bulkUseToken(), target->currentToke
n(), |
311 info.maskFormat()); | 289 info.maskFormat()); |
312 break; | 290 break; |
313 } | 291 } |
314 | 292 |
315 *byteCount = info.byteCount(); | 293 *byteCount = info.byteCount(); |
316 *vertices = fVertices + info.vertexStartIndex(); | 294 *vertices = fVertices + info.vertexStartIndex(); |
317 } | 295 } |
OLD | NEW |