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