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