| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 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 #include "GrAtlasTextContext.h" | 7 #include "GrAtlasTextContext.h" |
| 8 | 8 |
| 9 #include "GrBlurUtils.h" | 9 #include "GrBlurUtils.h" |
| 10 #include "GrDrawContext.h" | 10 #include "GrDrawContext.h" |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 181 bool GrAtlasTextContext::HasLCD(const SkTextBlob* blob) { | 181 bool GrAtlasTextContext::HasLCD(const SkTextBlob* blob) { |
| 182 SkTextBlobRunIterator it(blob); | 182 SkTextBlobRunIterator it(blob); |
| 183 for (; !it.done(); it.next()) { | 183 for (; !it.done(); it.next()) { |
| 184 if (it.isLCD()) { | 184 if (it.isLCD()) { |
| 185 return true; | 185 return true; |
| 186 } | 186 } |
| 187 } | 187 } |
| 188 return false; | 188 return false; |
| 189 } | 189 } |
| 190 | 190 |
| 191 bool GrAtlasTextContext::MustRegenerateBlob(SkScalar* outTransX, SkScalar* outTr
ansY, | |
| 192 const GrAtlasTextBlob& blob, const S
kPaint& paint, | |
| 193 GrColor color, const SkMaskFilter::B
lurRec& blurRec, | |
| 194 const SkMatrix& viewMatrix, SkScalar
x, SkScalar y) { | |
| 195 // If we have LCD text then our canonical color will be set to transparent,
in this case we have | |
| 196 // to regenerate the blob on any color change | |
| 197 // We use the grPaint to get any color filter effects | |
| 198 if (blob.fKey.fCanonicalColor == SK_ColorTRANSPARENT && | |
| 199 blob.fPaintColor != color) { | |
| 200 return true; | |
| 201 } | |
| 202 | |
| 203 if (blob.fViewMatrix.hasPerspective() != viewMatrix.hasPerspective()) { | |
| 204 return true; | |
| 205 } | |
| 206 | |
| 207 if (blob.fViewMatrix.hasPerspective() && !blob.fViewMatrix.cheapEqualTo(view
Matrix)) { | |
| 208 return true; | |
| 209 } | |
| 210 | |
| 211 // We only cache one masked version | |
| 212 if (blob.fKey.fHasBlur && | |
| 213 (blob.fBlurRec.fSigma != blurRec.fSigma || | |
| 214 blob.fBlurRec.fStyle != blurRec.fStyle || | |
| 215 blob.fBlurRec.fQuality != blurRec.fQuality)) { | |
| 216 return true; | |
| 217 } | |
| 218 | |
| 219 // Similarly, we only cache one version for each style | |
| 220 if (blob.fKey.fStyle != SkPaint::kFill_Style && | |
| 221 (blob.fStrokeInfo.fFrameWidth != paint.getStrokeWidth() || | |
| 222 blob.fStrokeInfo.fMiterLimit != paint.getStrokeMiter() || | |
| 223 blob.fStrokeInfo.fJoin != paint.getStrokeJoin())) { | |
| 224 return true; | |
| 225 } | |
| 226 | |
| 227 // Mixed blobs must be regenerated. We could probably figure out a way to d
o integer scrolls | |
| 228 // for mixed blobs if this becomes an issue. | |
| 229 if (blob.hasBitmap() && blob.hasDistanceField()) { | |
| 230 // Identical viewmatrices and we can reuse in all cases | |
| 231 if (blob.fViewMatrix.cheapEqualTo(viewMatrix) && x == blob.fX && y == bl
ob.fY) { | |
| 232 return false; | |
| 233 } | |
| 234 return true; | |
| 235 } | |
| 236 | |
| 237 if (blob.hasBitmap()) { | |
| 238 if (blob.fViewMatrix.getScaleX() != viewMatrix.getScaleX() || | |
| 239 blob.fViewMatrix.getScaleY() != viewMatrix.getScaleY() || | |
| 240 blob.fViewMatrix.getSkewX() != viewMatrix.getSkewX() || | |
| 241 blob.fViewMatrix.getSkewY() != viewMatrix.getSkewY()) { | |
| 242 return true; | |
| 243 } | |
| 244 | |
| 245 // We can update the positions in the cachedtextblobs without regenerati
ng the whole blob, | |
| 246 // but only for integer translations. | |
| 247 // This cool bit of math will determine the necessary translation to app
ly to the already | |
| 248 // generated vertex coordinates to move them to the correct position | |
| 249 SkScalar transX = viewMatrix.getTranslateX() + | |
| 250 viewMatrix.getScaleX() * (x - blob.fX) + | |
| 251 viewMatrix.getSkewX() * (y - blob.fY) - | |
| 252 blob.fViewMatrix.getTranslateX(); | |
| 253 SkScalar transY = viewMatrix.getTranslateY() + | |
| 254 viewMatrix.getSkewY() * (x - blob.fX) + | |
| 255 viewMatrix.getScaleY() * (y - blob.fY) - | |
| 256 blob.fViewMatrix.getTranslateY(); | |
| 257 if (!SkScalarIsInt(transX) || !SkScalarIsInt(transY) ) { | |
| 258 return true; | |
| 259 } | |
| 260 | |
| 261 (*outTransX) = transX; | |
| 262 (*outTransY) = transY; | |
| 263 } else if (blob.hasDistanceField()) { | |
| 264 // A scale outside of [blob.fMaxMinScale, blob.fMinMaxScale] would resul
t in a different | |
| 265 // distance field being generated, so we have to regenerate in those cas
es | |
| 266 SkScalar newMaxScale = viewMatrix.getMaxScale(); | |
| 267 SkScalar oldMaxScale = blob.fViewMatrix.getMaxScale(); | |
| 268 SkScalar scaleAdjust = newMaxScale / oldMaxScale; | |
| 269 if (scaleAdjust < blob.fMaxMinScale || scaleAdjust > blob.fMinMaxScale)
{ | |
| 270 return true; | |
| 271 } | |
| 272 | |
| 273 (*outTransX) = x - blob.fX; | |
| 274 (*outTransY) = y - blob.fY; | |
| 275 } | |
| 276 | |
| 277 // It is possible that a blob has neither distanceField nor bitmaptext. Thi
s is in the case | |
| 278 // when all of the runs inside the blob are drawn as paths. In this case, w
e always regenerate | |
| 279 // the blob anyways at flush time, so no need to regenerate explicitly | |
| 280 return false; | |
| 281 } | |
| 282 | |
| 283 | |
| 284 inline SkGlyphCache* GrAtlasTextContext::setupCache(GrAtlasTextBlob::Run* run, | 191 inline SkGlyphCache* GrAtlasTextContext::setupCache(GrAtlasTextBlob::Run* run, |
| 285 const SkPaint& skPaint, | 192 const SkPaint& skPaint, |
| 286 const SkMatrix* viewMatrix, | 193 const SkMatrix* viewMatrix, |
| 287 bool noGamma) { | 194 bool noGamma) { |
| 288 skPaint.getScalerContextDescriptor(&run->fDescriptor, fSurfaceProps, viewMat
rix, noGamma); | 195 skPaint.getScalerContextDescriptor(&run->fDescriptor, fSurfaceProps, viewMat
rix, noGamma); |
| 289 run->fTypeface.reset(SkSafeRef(skPaint.getTypeface())); | 196 run->fTypeface.reset(SkSafeRef(skPaint.getTypeface())); |
| 290 return SkGlyphCache::DetachCache(run->fTypeface, run->fDescriptor.getDesc())
; | 197 return SkGlyphCache::DetachCache(run->fTypeface, run->fDescriptor.getDesc())
; |
| 291 } | 198 } |
| 292 | 199 |
| 293 void GrAtlasTextContext::drawTextBlob(GrDrawContext* dc, | 200 void GrAtlasTextContext::drawTextBlob(GrDrawContext* dc, |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 335 SkScalar transY = 0.f; | 242 SkScalar transY = 0.f; |
| 336 | 243 |
| 337 // Though for the time being runs in the textblob can override the paint, th
ey only touch font | 244 // Though for the time being runs in the textblob can override the paint, th
ey only touch font |
| 338 // info. | 245 // info. |
| 339 GrPaint grPaint; | 246 GrPaint grPaint; |
| 340 if (!SkPaintToGrPaint(fContext, skPaint, viewMatrix, &grPaint)) { | 247 if (!SkPaintToGrPaint(fContext, skPaint, viewMatrix, &grPaint)) { |
| 341 return; | 248 return; |
| 342 } | 249 } |
| 343 | 250 |
| 344 if (cacheBlob) { | 251 if (cacheBlob) { |
| 345 if (MustRegenerateBlob(&transX, &transY, *cacheBlob, skPaint, grPaint.ge
tColor(), blurRec, | 252 if (cacheBlob->mustRegenerate(&transX, &transY, skPaint, grPaint.getColo
r(), blurRec, |
| 346 viewMatrix, x, y)) { | 253 viewMatrix, x, y)) { |
| 347 // We have to remake the blob because changes may invalidate our mas
ks. | 254 // We have to remake the blob because changes may invalidate our mas
ks. |
| 348 // TODO we could probably get away reuse most of the time if the poi
nter is unique, | 255 // TODO we could probably get away reuse most of the time if the poi
nter is unique, |
| 349 // but we'd have to clear the subrun information | 256 // but we'd have to clear the subrun information |
| 350 fCache->remove(cacheBlob); | 257 fCache->remove(cacheBlob); |
| 351 cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, key, blurRec, s
kPaint, | 258 cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, key, blurRec, s
kPaint, |
| 352 GrAtlasTextBlob::kGra
yTextVASize))); | 259 GrAtlasTextBlob::kGra
yTextVASize))); |
| 353 this->regenerateTextBlob(cacheBlob, skPaint, grPaint.getColor(), vie
wMatrix, | 260 this->regenerateTextBlob(cacheBlob, skPaint, grPaint.getColor(), vie
wMatrix, |
| 354 blob, x, y, drawFilter, clip); | 261 blob, x, y, drawFilter, clip); |
| 355 } else { | 262 } else { |
| 356 // If we can reuse the blob, then make sure we update the blob's vie
wmatrix, and x/y | |
| 357 // offsets. Note, we offset the vertex bounds right before flushing | |
| 358 cacheBlob->fViewMatrix = viewMatrix; | |
| 359 cacheBlob->fX = x; | |
| 360 cacheBlob->fY = y; | |
| 361 fCache->makeMRU(cacheBlob); | 263 fCache->makeMRU(cacheBlob); |
| 362 #ifdef CACHE_SANITY_CHECK | 264 #ifdef CACHE_SANITY_CHECK |
| 363 { | 265 { |
| 364 int glyphCount = 0; | 266 int glyphCount = 0; |
| 365 int runCount = 0; | 267 int runCount = 0; |
| 366 GrTextBlobCache::BlobGlyphCount(&glyphCount, &runCount, blob); | 268 GrTextBlobCache::BlobGlyphCount(&glyphCount, &runCount, blob); |
| 367 SkAutoTUnref<GrAtlasTextBlob> sanityBlob(fCache->createBlob(glyp
hCount, runCount, | 269 SkAutoTUnref<GrAtlasTextBlob> sanityBlob(fCache->createBlob(glyp
hCount, runCount, |
| 368 kGra
yTextVASize)); | 270 kGra
yTextVASize)); |
| 369 GrTextBlobCache::SetupCacheBlobKey(sanityBlob, key, blurRec, skP
aint); | 271 GrTextBlobCache::SetupCacheBlobKey(sanityBlob, key, blurRec, skP
aint); |
| 370 this->regenerateTextBlob(sanityBlob, skPaint, grPaint.getColor()
, viewMatrix, | 272 this->regenerateTextBlob(sanityBlob, skPaint, grPaint.getColor()
, viewMatrix, |
| (...skipping 913 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1284 gTextContext->createDrawTextBlob(clip, grPaint, skPaint, viewMatrix,
text, | 1186 gTextContext->createDrawTextBlob(clip, grPaint, skPaint, viewMatrix,
text, |
| 1285 static_cast<size_t>(textLen), 0, 0,
noClip)); | 1187 static_cast<size_t>(textLen), 0, 0,
noClip)); |
| 1286 | 1188 |
| 1287 SkScalar transX = static_cast<SkScalar>(random->nextU()); | 1189 SkScalar transX = static_cast<SkScalar>(random->nextU()); |
| 1288 SkScalar transY = static_cast<SkScalar>(random->nextU()); | 1190 SkScalar transY = static_cast<SkScalar>(random->nextU()); |
| 1289 const GrAtlasTextBlob::Run::SubRunInfo& info = blob->fRuns[0].fSubRunInfo[0]
; | 1191 const GrAtlasTextBlob::Run::SubRunInfo& info = blob->fRuns[0].fSubRunInfo[0]
; |
| 1290 return gTextContext->createBatch(blob, info, textLen, 0, 0, color, transX, t
ransY, skPaint); | 1192 return gTextContext->createBatch(blob, info, textLen, 0, 0, color, transX, t
ransY, skPaint); |
| 1291 } | 1193 } |
| 1292 | 1194 |
| 1293 #endif | 1195 #endif |
| OLD | NEW |