| 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 |