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 "GrAtlas.h" | 9 #include "GrAtlas.h" |
10 #include "GrBatch.h" | 10 #include "GrBatch.h" |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
253 } | 253 } |
254 | 254 |
255 if (blob.fViewMatrix.hasPerspective() != viewMatrix.hasPerspective()) { | 255 if (blob.fViewMatrix.hasPerspective() != viewMatrix.hasPerspective()) { |
256 return true; | 256 return true; |
257 } | 257 } |
258 | 258 |
259 if (blob.fViewMatrix.hasPerspective() && !blob.fViewMatrix.cheapEqualTo(view
Matrix)) { | 259 if (blob.fViewMatrix.hasPerspective() && !blob.fViewMatrix.cheapEqualTo(view
Matrix)) { |
260 return true; | 260 return true; |
261 } | 261 } |
262 | 262 |
263 if (blob.fViewMatrix.getScaleX() != viewMatrix.getScaleX() || | |
264 blob.fViewMatrix.getScaleY() != viewMatrix.getScaleY() || | |
265 blob.fViewMatrix.getSkewX() != viewMatrix.getSkewX() || | |
266 blob.fViewMatrix.getSkewY() != viewMatrix.getSkewY()) { | |
267 return true; | |
268 } | |
269 | |
270 // We only cache one masked version | 263 // We only cache one masked version |
271 if (blob.fKey.fHasBlur && | 264 if (blob.fKey.fHasBlur && |
272 (blob.fBlurRec.fSigma != blurRec.fSigma || | 265 (blob.fBlurRec.fSigma != blurRec.fSigma || |
273 blob.fBlurRec.fStyle != blurRec.fStyle || | 266 blob.fBlurRec.fStyle != blurRec.fStyle || |
274 blob.fBlurRec.fQuality != blurRec.fQuality)) { | 267 blob.fBlurRec.fQuality != blurRec.fQuality)) { |
275 return true; | 268 return true; |
276 } | 269 } |
277 | 270 |
278 // Similarly, we only cache one version for each style | 271 // Similarly, we only cache one version for each style |
279 if (blob.fKey.fStyle != SkPaint::kFill_Style && | 272 if (blob.fKey.fStyle != SkPaint::kFill_Style && |
280 (blob.fStrokeInfo.fFrameWidth != paint.getStrokeWidth() || | 273 (blob.fStrokeInfo.fFrameWidth != paint.getStrokeWidth() || |
281 blob.fStrokeInfo.fMiterLimit != paint.getStrokeMiter() || | 274 blob.fStrokeInfo.fMiterLimit != paint.getStrokeMiter() || |
282 blob.fStrokeInfo.fJoin != paint.getStrokeJoin())) { | 275 blob.fStrokeInfo.fJoin != paint.getStrokeJoin())) { |
283 return true; | 276 return true; |
284 } | 277 } |
285 | 278 |
286 // We can update the positions in the cachedtextblobs without regenerating t
he whole blob, but | 279 // Identical viewmatrices and we can reuse in all cases |
287 // only for integer translations. | 280 if (blob.fViewMatrix.cheapEqualTo(viewMatrix) && x == blob.fX && y == blob.f
Y) { |
288 // This cool bit of math will determine the necessary translation to apply t
o the already | 281 return false; |
289 // generated vertex coordinates to move them to the correct position | 282 } |
290 SkScalar transX = viewMatrix.getTranslateX() + | 283 |
291 viewMatrix.getScaleX() * (x - blob.fX) + | 284 // Mixed blobs must be regenerated. We could probably figure out a way to d
o integer scrolls |
292 viewMatrix.getSkewX() * (y - blob.fY) - | 285 // for mixed blobs if this becomes an issue. |
293 blob.fViewMatrix.getTranslateX(); | 286 if (blob.hasBitmap() && blob.hasDistanceField()) { |
294 SkScalar transY = viewMatrix.getTranslateY() + | |
295 viewMatrix.getSkewY() * (x - blob.fX) + | |
296 viewMatrix.getScaleY() * (y - blob.fY) - | |
297 blob.fViewMatrix.getTranslateY(); | |
298 if (SkScalarFraction(transX) > SK_ScalarNearlyZero || | |
299 SkScalarFraction(transY) > SK_ScalarNearlyZero) { | |
300 return true; | 287 return true; |
301 } | 288 } |
302 | 289 |
| 290 // TODO distance fields can handle many of these conditions |
| 291 if (blob.fViewMatrix.getScaleX() != viewMatrix.getScaleX() || |
| 292 blob.fViewMatrix.getScaleY() != viewMatrix.getScaleY() || |
| 293 blob.fViewMatrix.getSkewX() != viewMatrix.getSkewX() || |
| 294 blob.fViewMatrix.getSkewY() != viewMatrix.getSkewY()) { |
| 295 return true; |
| 296 } |
| 297 |
| 298 if (blob.hasBitmap()) { |
| 299 // We can update the positions in the cachedtextblobs without regenerati
ng the whole blob, |
| 300 // but only for integer translations. |
| 301 // This cool bit of math will determine the necessary translation to app
ly to the already |
| 302 // generated vertex coordinates to move them to the correct position |
| 303 SkScalar transX = viewMatrix.getTranslateX() + |
| 304 viewMatrix.getScaleX() * (x - blob.fX) + |
| 305 viewMatrix.getSkewX() * (y - blob.fY) - |
| 306 blob.fViewMatrix.getTranslateX(); |
| 307 SkScalar transY = viewMatrix.getTranslateY() + |
| 308 viewMatrix.getSkewY() * (x - blob.fX) + |
| 309 viewMatrix.getScaleY() * (y - blob.fY) - |
| 310 blob.fViewMatrix.getTranslateY(); |
| 311 if (SkScalarFraction(transX) > SK_ScalarNearlyZero || |
| 312 SkScalarFraction(transY) > SK_ScalarNearlyZero) { |
| 313 return true; |
| 314 } |
| 315 |
303 #ifdef SK_DEBUG | 316 #ifdef SK_DEBUG |
304 static const SkScalar kMinDiscernableTranslation = 0.0625; | 317 static const SkScalar kMinDiscernableTranslation = 0.0625; |
305 // As a safeguard when debugging, we store the total error across all transl
ations and print if | 318 // As a safeguard when debugging, we store the total error across all tr
anslations and print |
306 // the error becomes discernable. This is pretty unlikely to occur given th
e tight bounds above | 319 // if the error becomes discernable. This is pretty unlikely to occur g
iven the tight |
307 // on translation | 320 // bounds above on translation |
308 blob.fTotalXError += SkScalarAbs(SkScalarFraction(transX)); | 321 blob.fTotalXError += SkScalarAbs(SkScalarFraction(transX)); |
309 blob.fTotalYError += SkScalarAbs(SkScalarFraction(transY)); | 322 blob.fTotalYError += SkScalarAbs(SkScalarFraction(transY)); |
310 if (blob.fTotalXError > kMinDiscernableTranslation || | 323 if (blob.fTotalXError > kMinDiscernableTranslation || |
311 blob.fTotalYError > kMinDiscernableTranslation) { | 324 blob.fTotalYError > kMinDiscernableTranslation) { |
312 SkDebugf("Exceeding error threshold for bitmap text translation"); | 325 SkDebugf("Exceeding error threshold for bitmap text translation"); |
| 326 } |
| 327 #endif |
| 328 (*outTransX) = transX; |
| 329 (*outTransY) = transY; |
| 330 } else { |
| 331 // blob.hasDistanceField() |
| 332 // TODO figure out the regen formula |
| 333 return true; |
313 } | 334 } |
314 #endif | 335 |
315 (*outTransX) = transX; | |
316 (*outTransY) = transY; | |
317 return false; | 336 return false; |
318 } | 337 } |
319 | 338 |
320 | 339 |
321 inline SkGlyphCache* GrAtlasTextContext::setupCache(BitmapTextBlob::Run* run, | 340 inline SkGlyphCache* GrAtlasTextContext::setupCache(BitmapTextBlob::Run* run, |
322 const SkPaint& skPaint, | 341 const SkPaint& skPaint, |
323 const SkMatrix* viewMatrix, | 342 const SkMatrix* viewMatrix, |
324 bool noGamma) { | 343 bool noGamma) { |
325 skPaint.getScalerContextDescriptor(&run->fDescriptor, &fDeviceProperties, vi
ewMatrix, noGamma); | 344 skPaint.getScalerContextDescriptor(&run->fDescriptor, &fDeviceProperties, vi
ewMatrix, noGamma); |
326 run->fTypeface.reset(SkSafeRef(skPaint.getTypeface())); | 345 run->fTypeface.reset(SkSafeRef(skPaint.getTypeface())); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
371 | 390 |
372 if (cacheBlob) { | 391 if (cacheBlob) { |
373 if (MustRegenerateBlob(&transX, &transY, *cacheBlob, skPaint, blurRec, v
iewMatrix, x, y)) { | 392 if (MustRegenerateBlob(&transX, &transY, *cacheBlob, skPaint, blurRec, v
iewMatrix, x, y)) { |
374 // We have to remake the blob because changes may invalidate our mas
ks. | 393 // We have to remake the blob because changes may invalidate our mas
ks. |
375 // TODO we could probably get away reuse most of the time if the poi
nter is unique, | 394 // TODO we could probably get away reuse most of the time if the poi
nter is unique, |
376 // but we'd have to clear the subrun information | 395 // but we'd have to clear the subrun information |
377 fCache->remove(cacheBlob); | 396 fCache->remove(cacheBlob); |
378 cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, key, blurRec, s
kPaint, | 397 cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, key, blurRec, s
kPaint, |
379 kGrayTextVASize))); | 398 kGrayTextVASize))); |
380 this->regenerateTextBlob(cacheBlob, skPaint, grPaint.getColor(), vie
wMatrix, blob, x, y, | 399 this->regenerateTextBlob(cacheBlob, skPaint, grPaint.getColor(), vie
wMatrix, blob, x, y, |
381 drawFilter, clipRect); | 400 drawFilter, clipRect, rt, clip, grPaint); |
382 } else { | 401 } else { |
383 // If we can reuse the blob, then make sure we update the blob's vie
wmatrix, and x/y | 402 // If we can reuse the blob, then make sure we update the blob's vie
wmatrix, and x/y |
384 // offsets | 403 // offsets |
385 cacheBlob->fViewMatrix = viewMatrix; | 404 cacheBlob->fViewMatrix = viewMatrix; |
386 cacheBlob->fX = x; | 405 cacheBlob->fX = x; |
387 cacheBlob->fY = y; | 406 cacheBlob->fY = y; |
388 fCache->makeMRU(cacheBlob); | 407 fCache->makeMRU(cacheBlob); |
389 } | 408 } |
390 } else { | 409 } else { |
391 if (canCache) { | 410 if (canCache) { |
392 cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, key, blurRec, s
kPaint, | 411 cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, key, blurRec, s
kPaint, |
393 kGrayTextVASize))); | 412 kGrayTextVASize))); |
394 } else { | 413 } else { |
395 cacheBlob.reset(fCache->createBlob(blob, kGrayTextVASize)); | 414 cacheBlob.reset(fCache->createBlob(blob, kGrayTextVASize)); |
396 } | 415 } |
397 this->regenerateTextBlob(cacheBlob, skPaint, grPaint.getColor(), viewMat
rix, blob, x, y, | 416 this->regenerateTextBlob(cacheBlob, skPaint, grPaint.getColor(), viewMat
rix, blob, x, y, |
398 drawFilter, clipRect); | 417 drawFilter, clipRect, rt, clip, grPaint); |
399 } | 418 } |
400 | 419 |
401 cacheBlob->fPaintColor = skPaint.getColor(); | 420 cacheBlob->fPaintColor = skPaint.getColor(); |
402 this->flush(fContext->getTextTarget(), blob, cacheBlob, rt, skPaint, grPaint
, drawFilter, | 421 this->flush(fContext->getTextTarget(), blob, cacheBlob, rt, skPaint, grPaint
, drawFilter, |
403 clip, viewMatrix, clipBounds, x, y, transX, transY); | 422 clip, viewMatrix, clipBounds, x, y, transX, transY); |
404 } | 423 } |
405 | 424 |
406 inline bool GrAtlasTextContext::canDrawAsDistanceFields(const SkPaint& skPaint, | 425 inline bool GrAtlasTextContext::canDrawAsDistanceFields(const SkPaint& skPaint, |
407 const SkMatrix& viewMatr
ix) { | 426 const SkMatrix& viewMatr
ix) { |
408 // TODO: support perspective (need getMaxScale replacement) | 427 // TODO: support perspective (need getMaxScale replacement) |
(...skipping 26 matching lines...) Expand all Loading... |
435 return false; | 454 return false; |
436 } | 455 } |
437 | 456 |
438 return true; | 457 return true; |
439 } | 458 } |
440 | 459 |
441 void GrAtlasTextContext::regenerateTextBlob(BitmapTextBlob* cacheBlob, | 460 void GrAtlasTextContext::regenerateTextBlob(BitmapTextBlob* cacheBlob, |
442 const SkPaint& skPaint, GrColor colo
r, | 461 const SkPaint& skPaint, GrColor colo
r, |
443 const SkMatrix& viewMatrix, | 462 const SkMatrix& viewMatrix, |
444 const SkTextBlob* blob, SkScalar x,
SkScalar y, | 463 const SkTextBlob* blob, SkScalar x,
SkScalar y, |
445 SkDrawFilter* drawFilter, const SkIR
ect& clipRect) { | 464 SkDrawFilter* drawFilter, const SkIR
ect& clipRect, |
| 465 GrRenderTarget* rt, const GrClip& cl
ip, |
| 466 const GrPaint& paint) { |
446 cacheBlob->fViewMatrix = viewMatrix; | 467 cacheBlob->fViewMatrix = viewMatrix; |
447 cacheBlob->fX = x; | 468 cacheBlob->fX = x; |
448 cacheBlob->fY = y; | 469 cacheBlob->fY = y; |
449 | 470 |
450 // Regenerate textblob | 471 // Regenerate textblob |
451 SkPaint runPaint = skPaint; | 472 SkPaint runPaint = skPaint; |
452 SkTextBlob::RunIterator it(blob); | 473 SkTextBlob::RunIterator it(blob); |
453 for (int run = 0; !it.done(); it.next(), run++) { | 474 for (int run = 0; !it.done(); it.next(), run++) { |
454 int glyphCount = it.glyphCount(); | 475 int glyphCount = it.glyphCount(); |
455 size_t textLen = glyphCount * sizeof(uint16_t); | 476 size_t textLen = glyphCount * sizeof(uint16_t); |
456 const SkPoint& offset = it.offset(); | 477 const SkPoint& offset = it.offset(); |
457 // applyFontToPaint() always overwrites the exact same attributes, | 478 // applyFontToPaint() always overwrites the exact same attributes, |
458 // so it is safe to not re-seed the paint for this reason. | 479 // so it is safe to not re-seed the paint for this reason. |
459 it.applyFontToPaint(&runPaint); | 480 it.applyFontToPaint(&runPaint); |
460 | 481 |
461 if (drawFilter && !drawFilter->filter(&runPaint, SkDrawFilter::kText_Typ
e)) { | 482 if (drawFilter && !drawFilter->filter(&runPaint, SkDrawFilter::kText_Typ
e)) { |
462 // A false return from filter() means we should abort the current dr
aw. | 483 // A false return from filter() means we should abort the current dr
aw. |
463 runPaint = skPaint; | 484 runPaint = skPaint; |
464 continue; | 485 continue; |
465 } | 486 } |
466 | 487 |
467 runPaint.setFlags(fGpuDevice->filterTextFlags(runPaint)); | 488 runPaint.setFlags(fGpuDevice->filterTextFlags(runPaint)); |
468 | 489 |
469 SkGlyphCache* cache = this->setupCache(&cacheBlob->fRuns[run], runPaint,
&viewMatrix, | |
470 false); | |
471 | |
472 // setup vertex / glyphIndex for the new run | 490 // setup vertex / glyphIndex for the new run |
473 if (run > 0) { | 491 if (run > 0) { |
474 PerSubRunInfo& newRun = cacheBlob->fRuns[run].fSubRunInfo.back(); | 492 PerSubRunInfo& newRun = cacheBlob->fRuns[run].fSubRunInfo.back(); |
475 PerSubRunInfo& lastRun = cacheBlob->fRuns[run - 1].fSubRunInfo.back(
); | 493 PerSubRunInfo& lastRun = cacheBlob->fRuns[run - 1].fSubRunInfo.back(
); |
476 | 494 |
477 newRun.fVertexStartIndex = lastRun.fVertexEndIndex; | 495 newRun.fVertexStartIndex = lastRun.fVertexEndIndex; |
478 newRun.fVertexEndIndex = lastRun.fVertexEndIndex; | 496 newRun.fVertexEndIndex = lastRun.fVertexEndIndex; |
479 | 497 |
480 newRun.fGlyphStartIndex = lastRun.fGlyphEndIndex; | 498 newRun.fGlyphStartIndex = lastRun.fGlyphEndIndex; |
481 newRun.fGlyphEndIndex = lastRun.fGlyphEndIndex; | 499 newRun.fGlyphEndIndex = lastRun.fGlyphEndIndex; |
482 } | 500 } |
483 | 501 |
484 if (SkDraw::ShouldDrawTextAsPaths(runPaint, viewMatrix)) { | 502 if (this->canDrawAsDistanceFields(runPaint, viewMatrix)) { |
| 503 cacheBlob->setHasDistanceField(); |
| 504 SkPaint dfPaint = runPaint; |
| 505 SkScalar textRatio; |
| 506 this->initDistanceFieldPaint(&dfPaint, &textRatio, viewMatrix); |
| 507 Run& runIdx = cacheBlob->fRuns[run]; |
| 508 PerSubRunInfo& subRun = runIdx.fSubRunInfo.back(); |
| 509 subRun.fUseLCDText = runPaint.isLCDRenderText(); |
| 510 subRun.fDrawAsDistanceFields = true; |
| 511 |
| 512 SkGlyphCache* cache = this->setupCache(&cacheBlob->fRuns[run], dfPai
nt, NULL, true); |
| 513 |
| 514 SkTDArray<char> fallbackTxt; |
| 515 SkTDArray<SkScalar> fallbackPos; |
| 516 SkPoint dfOffset; |
| 517 int scalarsPerPosition = 2; |
| 518 switch (it.positioning()) { |
| 519 case SkTextBlob::kDefault_Positioning: { |
| 520 this->internalDrawDFText(cacheBlob, run, cache, dfPaint, col
or, viewMatrix, |
| 521 (const char *)it.glyphs(), textLen, |
| 522 x + offset.x(), y + offset.y(), cli
pRect, textRatio, |
| 523 &fallbackTxt, &fallbackPos, &dfOffs
et, runPaint); |
| 524 break; |
| 525 } |
| 526 case SkTextBlob::kHorizontal_Positioning: { |
| 527 scalarsPerPosition = 1; |
| 528 dfOffset = SkPoint::Make(x, y + offset.y()); |
| 529 this->internalDrawDFPosText(cacheBlob, run, cache, dfPaint,
color, viewMatrix, |
| 530 (const char*)it.glyphs(), textLe
n, it.pos(), |
| 531 scalarsPerPosition, dfOffset, cl
ipRect, textRatio, |
| 532 &fallbackTxt, &fallbackPos); |
| 533 break; |
| 534 } |
| 535 case SkTextBlob::kFull_Positioning: { |
| 536 dfOffset = SkPoint::Make(x, y); |
| 537 this->internalDrawDFPosText(cacheBlob, run, cache, dfPaint,
color, viewMatrix, |
| 538 (const char*)it.glyphs(), textLe
n, it.pos(), |
| 539 scalarsPerPosition, dfOffset, cl
ipRect, textRatio, |
| 540 &fallbackTxt, &fallbackPos); |
| 541 break; |
| 542 } |
| 543 } |
| 544 if (fallbackTxt.count()) { |
| 545 this->fallbackDrawPosText(cacheBlob, run, rt, clip, paint, runPa
int, viewMatrix, |
| 546 fallbackTxt, fallbackPos, scalarsPerPo
sition, dfOffset, |
| 547 clipRect); |
| 548 } |
| 549 |
| 550 SkGlyphCache::AttachCache(cache); |
| 551 } else if (SkDraw::ShouldDrawTextAsPaths(runPaint, viewMatrix)) { |
485 cacheBlob->fRuns[run].fDrawAsPaths = true; | 552 cacheBlob->fRuns[run].fDrawAsPaths = true; |
486 continue; | 553 } else { |
487 } | 554 cacheBlob->setHasBitmap(); |
488 cacheBlob->fRuns[run].fDrawAsPaths = false; | 555 SkGlyphCache* cache = this->setupCache(&cacheBlob->fRuns[run], runPa
int, &viewMatrix, |
489 | 556 false); |
490 switch (it.positioning()) { | 557 switch (it.positioning()) { |
491 case SkTextBlob::kDefault_Positioning: | 558 case SkTextBlob::kDefault_Positioning: |
492 this->internalDrawBMPText(cacheBlob, run, cache, runPaint, color
, viewMatrix, | 559 this->internalDrawBMPText(cacheBlob, run, cache, runPaint, c
olor, viewMatrix, |
493 (const char *)it.glyphs(), textLen, | 560 (const char *)it.glyphs(), textLen
, |
494 x + offset.x(), y + offset.y(), clipRe
ct); | 561 x + offset.x(), y + offset.y(), cl
ipRect); |
495 break; | 562 break; |
496 case SkTextBlob::kHorizontal_Positioning: | 563 case SkTextBlob::kHorizontal_Positioning: |
497 this->internalDrawBMPPosText(cacheBlob, run, cache, runPaint, co
lor, viewMatrix, | 564 this->internalDrawBMPPosText(cacheBlob, run, cache, runPaint
, color, viewMatrix, |
498 (const char*)it.glyphs(), textLen,
it.pos(), 1, | 565 (const char*)it.glyphs(), textL
en, it.pos(), 1, |
499 SkPoint::Make(x, y + offset.y()), c
lipRect); | 566 SkPoint::Make(x, y + offset.y()
), clipRect); |
500 break; | 567 break; |
501 case SkTextBlob::kFull_Positioning: | 568 case SkTextBlob::kFull_Positioning: |
502 this->internalDrawBMPPosText(cacheBlob, run, cache, runPaint, co
lor, viewMatrix, | 569 this->internalDrawBMPPosText(cacheBlob, run, cache, runPaint
, color, viewMatrix, |
503 (const char*)it.glyphs(), textLen,
it.pos(), 2, | 570 (const char*)it.glyphs(), textL
en, it.pos(), 2, |
504 SkPoint::Make(x, y), clipRect); | 571 SkPoint::Make(x, y), clipRect); |
505 break; | 572 break; |
| 573 } |
| 574 SkGlyphCache::AttachCache(cache); |
506 } | 575 } |
507 | 576 |
508 if (drawFilter) { | 577 if (drawFilter) { |
509 // A draw filter may change the paint arbitrarily, so we must re-see
d in this case. | 578 // A draw filter may change the paint arbitrarily, so we must re-see
d in this case. |
510 runPaint = skPaint; | 579 runPaint = skPaint; |
511 } | 580 } |
512 | |
513 SkGlyphCache::AttachCache(cache); | |
514 } | 581 } |
515 } | 582 } |
516 | 583 |
517 inline void GrAtlasTextContext::initDistanceFieldPaint(SkPaint* skPaint, SkScala
r* textRatio, | 584 inline void GrAtlasTextContext::initDistanceFieldPaint(SkPaint* skPaint, SkScala
r* textRatio, |
518 const SkMatrix& viewMatri
x) { | 585 const SkMatrix& viewMatri
x) { |
519 // getMaxScale doesn't support perspective, so neither do we at the moment | 586 // getMaxScale doesn't support perspective, so neither do we at the moment |
520 SkASSERT(!viewMatrix.hasPerspective()); | 587 SkASSERT(!viewMatrix.hasPerspective()); |
521 SkScalar maxScale = viewMatrix.getMaxScale(); | 588 SkScalar maxScale = viewMatrix.getMaxScale(); |
522 SkScalar textSize = skPaint->getTextSize(); | 589 SkScalar textSize = skPaint->getTextSize(); |
523 SkScalar scaledTextSize = textSize; | 590 SkScalar scaledTextSize = textSize; |
(...skipping 15 matching lines...) Expand all Loading... |
539 skPaint->setTextSize(SkIntToScalar(kLargeDFFontSize)); | 606 skPaint->setTextSize(SkIntToScalar(kLargeDFFontSize)); |
540 } | 607 } |
541 | 608 |
542 skPaint->setLCDRenderText(false); | 609 skPaint->setLCDRenderText(false); |
543 skPaint->setAutohinted(false); | 610 skPaint->setAutohinted(false); |
544 skPaint->setHinting(SkPaint::kNormal_Hinting); | 611 skPaint->setHinting(SkPaint::kNormal_Hinting); |
545 skPaint->setSubpixelText(true); | 612 skPaint->setSubpixelText(true); |
546 } | 613 } |
547 | 614 |
548 inline void GrAtlasTextContext::fallbackDrawPosText(BitmapTextBlob* blob, | 615 inline void GrAtlasTextContext::fallbackDrawPosText(BitmapTextBlob* blob, |
| 616 int runIndex, |
549 GrRenderTarget* rt, const Gr
Clip& clip, | 617 GrRenderTarget* rt, const Gr
Clip& clip, |
550 const GrPaint& paint, | 618 const GrPaint& paint, |
551 const SkPaint& skPaint, | 619 const SkPaint& skPaint, |
552 const SkMatrix& viewMatrix, | 620 const SkMatrix& viewMatrix, |
553 const SkTDArray<char>& fallb
ackTxt, | 621 const SkTDArray<char>& fallb
ackTxt, |
554 const SkTDArray<SkScalar>& f
allbackPos, | 622 const SkTDArray<SkScalar>& f
allbackPos, |
555 int scalarsPerPosition, | 623 int scalarsPerPosition, |
556 const SkPoint& offset, | 624 const SkPoint& offset, |
557 const SkIRect& clipRect) { | 625 const SkIRect& clipRect) { |
558 SkASSERT(fallbackTxt.count()); | 626 SkASSERT(fallbackTxt.count()); |
559 Run& run = blob->fRuns[0]; | 627 blob->setHasBitmap(); |
| 628 Run& run = blob->fRuns[runIndex]; |
560 PerSubRunInfo& subRun = run.fSubRunInfo.push_back(); | 629 PerSubRunInfo& subRun = run.fSubRunInfo.push_back(); |
561 subRun.fOverrideDescriptor.reset(SkNEW(SkAutoDescriptor)); | 630 subRun.fOverrideDescriptor.reset(SkNEW(SkAutoDescriptor)); |
562 skPaint.getScalerContextDescriptor(subRun.fOverrideDescriptor, | 631 skPaint.getScalerContextDescriptor(subRun.fOverrideDescriptor, |
563 &fDeviceProperties, &viewMatrix, false); | 632 &fDeviceProperties, &viewMatrix, false); |
564 SkGlyphCache* cache = SkGlyphCache::DetachCache(run.fTypeface, | 633 SkGlyphCache* cache = SkGlyphCache::DetachCache(run.fTypeface, |
565 subRun.fOverrideDescriptor->
getDesc()); | 634 subRun.fOverrideDescriptor->
getDesc()); |
566 this->internalDrawBMPPosText(blob, 0, cache, skPaint, paint.getColor(), view
Matrix, | 635 this->internalDrawBMPPosText(blob, runIndex, cache, skPaint, paint.getColor(
), viewMatrix, |
567 fallbackTxt.begin(), fallbackTxt.count(), | 636 fallbackTxt.begin(), fallbackTxt.count(), |
568 fallbackPos.begin(), scalarsPerPosition, offset
, clipRect); | 637 fallbackPos.begin(), scalarsPerPosition, offset
, clipRect); |
569 SkGlyphCache::AttachCache(cache); | 638 SkGlyphCache::AttachCache(cache); |
570 } | 639 } |
571 | 640 |
572 inline GrAtlasTextContext::BitmapTextBlob* | 641 inline GrAtlasTextContext::BitmapTextBlob* |
573 GrAtlasTextContext::setupDFBlob(int glyphCount, const SkPaint& origPaint, | 642 GrAtlasTextContext::setupDFBlob(int glyphCount, const SkPaint& origPaint, |
574 const SkMatrix& viewMatrix, SkGlyphCache** cache
, | 643 const SkMatrix& viewMatrix, SkGlyphCache** cache
, |
575 SkPaint* dfPaint, SkScalar* textRatio) { | 644 SkPaint* dfPaint, SkScalar* textRatio) { |
576 BitmapTextBlob* blob = fCache->createBlob(glyphCount, 1, kGrayTextVASize); | 645 BitmapTextBlob* blob = fCache->createBlob(glyphCount, 1, kGrayTextVASize); |
577 | 646 |
578 *dfPaint = origPaint; | 647 *dfPaint = origPaint; |
579 this->initDistanceFieldPaint(dfPaint, textRatio, viewMatrix); | 648 this->initDistanceFieldPaint(dfPaint, textRatio, viewMatrix); |
580 blob->fViewMatrix = viewMatrix; | 649 blob->fViewMatrix = viewMatrix; |
581 blob->fRuns[0].fSubRunInfo.back().fUseLCDText = origPaint.isLCDRenderText(); | 650 Run& run = blob->fRuns[0]; |
582 blob->fRuns[0].fSubRunInfo.back().fDrawAsDistanceFields = true; | 651 PerSubRunInfo& subRun = run.fSubRunInfo.back(); |
| 652 subRun.fUseLCDText = origPaint.isLCDRenderText(); |
| 653 subRun.fDrawAsDistanceFields = true; |
583 | 654 |
584 *cache = this->setupCache(&blob->fRuns[0], *dfPaint, NULL, true); | 655 *cache = this->setupCache(&blob->fRuns[0], *dfPaint, NULL, true); |
585 return blob; | 656 return blob; |
586 } | 657 } |
587 | 658 |
588 void GrAtlasTextContext::onDrawText(GrRenderTarget* rt, const GrClip& clip, | 659 void GrAtlasTextContext::onDrawText(GrRenderTarget* rt, const GrClip& clip, |
589 const GrPaint& paint, const SkPaint& skPaint
, | 660 const GrPaint& paint, const SkPaint& skPaint
, |
590 const SkMatrix& viewMatrix, | 661 const SkMatrix& viewMatrix, |
591 const char text[], size_t byteLength, | 662 const char text[], size_t byteLength, |
592 SkScalar x, SkScalar y, const SkIRect& regio
nClipBounds) { | 663 SkScalar x, SkScalar y, const SkIRect& regio
nClipBounds) { |
(...skipping 10 matching lines...) Expand all Loading... |
603 &dfPaint, &textRatio
)); | 674 &dfPaint, &textRatio
)); |
604 | 675 |
605 SkTDArray<char> fallbackTxt; | 676 SkTDArray<char> fallbackTxt; |
606 SkTDArray<SkScalar> fallbackPos; | 677 SkTDArray<SkScalar> fallbackPos; |
607 SkPoint offset; | 678 SkPoint offset; |
608 this->internalDrawDFText(blob, 0, cache, dfPaint, paint.getColor(), view
Matrix, text, | 679 this->internalDrawDFText(blob, 0, cache, dfPaint, paint.getColor(), view
Matrix, text, |
609 byteLength, x, y, clipRect, textRatio, &fallbac
kTxt, &fallbackPos, | 680 byteLength, x, y, clipRect, textRatio, &fallbac
kTxt, &fallbackPos, |
610 &offset, skPaint); | 681 &offset, skPaint); |
611 SkGlyphCache::AttachCache(cache); | 682 SkGlyphCache::AttachCache(cache); |
612 if (fallbackTxt.count()) { | 683 if (fallbackTxt.count()) { |
613 this->fallbackDrawPosText(blob, rt, clip, paint, skPaint, viewMatrix
, fallbackTxt, | 684 this->fallbackDrawPosText(blob, 0, rt, clip, paint, skPaint, viewMat
rix, fallbackTxt, |
614 fallbackPos, 2, offset, clipRect); | 685 fallbackPos, 2, offset, clipRect); |
615 } | 686 } |
616 this->flush(fContext->getTextTarget(), blob, rt, skPaint, paint, clip); | 687 this->flush(fContext->getTextTarget(), blob, rt, skPaint, paint, clip); |
617 } else { | 688 } else { |
618 SkAutoTUnref<BitmapTextBlob> blob(fCache->createBlob(glyphCount, 1, kGra
yTextVASize)); | 689 SkAutoTUnref<BitmapTextBlob> blob(fCache->createBlob(glyphCount, 1, kGra
yTextVASize)); |
619 blob->fViewMatrix = viewMatrix; | 690 blob->fViewMatrix = viewMatrix; |
620 | 691 |
621 SkGlyphCache* cache = this->setupCache(&blob->fRuns[0], skPaint, &viewMa
trix, false); | 692 SkGlyphCache* cache = this->setupCache(&blob->fRuns[0], skPaint, &viewMa
trix, false); |
622 this->internalDrawBMPText(blob, 0, cache, skPaint, paint.getColor(), vie
wMatrix, text, | 693 this->internalDrawBMPText(blob, 0, cache, skPaint, paint.getColor(), vie
wMatrix, text, |
623 byteLength, x, y, clipRect); | 694 byteLength, x, y, clipRect); |
(...skipping 20 matching lines...) Expand all Loading... |
644 SkAutoTUnref<BitmapTextBlob> blob(this->setupDFBlob(glyphCount, skPaint,
viewMatrix, &cache, | 715 SkAutoTUnref<BitmapTextBlob> blob(this->setupDFBlob(glyphCount, skPaint,
viewMatrix, &cache, |
645 &dfPaint, &textRatio
)); | 716 &dfPaint, &textRatio
)); |
646 | 717 |
647 SkTDArray<char> fallbackTxt; | 718 SkTDArray<char> fallbackTxt; |
648 SkTDArray<SkScalar> fallbackPos; | 719 SkTDArray<SkScalar> fallbackPos; |
649 this->internalDrawDFPosText(blob, 0, cache, dfPaint, paint.getColor(), v
iewMatrix, text, | 720 this->internalDrawDFPosText(blob, 0, cache, dfPaint, paint.getColor(), v
iewMatrix, text, |
650 byteLength, pos, scalarsPerPosition, offset,
clipRect, | 721 byteLength, pos, scalarsPerPosition, offset,
clipRect, |
651 textRatio, &fallbackTxt, &fallbackPos); | 722 textRatio, &fallbackTxt, &fallbackPos); |
652 SkGlyphCache::AttachCache(cache); | 723 SkGlyphCache::AttachCache(cache); |
653 if (fallbackTxt.count()) { | 724 if (fallbackTxt.count()) { |
654 this->fallbackDrawPosText(blob, rt, clip, paint, skPaint, viewMatrix
, fallbackTxt, | 725 this->fallbackDrawPosText(blob, 0, rt, clip, paint, skPaint, viewMat
rix, fallbackTxt, |
655 fallbackPos, scalarsPerPosition, offset, c
lipRect); | 726 fallbackPos, scalarsPerPosition, offset, c
lipRect); |
656 } | 727 } |
657 this->flush(fContext->getTextTarget(), blob, rt, skPaint, paint, clip); | 728 this->flush(fContext->getTextTarget(), blob, rt, skPaint, paint, clip); |
658 } else { | 729 } else { |
659 SkAutoTUnref<BitmapTextBlob> blob(fCache->createBlob(glyphCount, 1, kGra
yTextVASize)); | 730 SkAutoTUnref<BitmapTextBlob> blob(fCache->createBlob(glyphCount, 1, kGra
yTextVASize)); |
660 blob->fViewMatrix = viewMatrix; | 731 blob->fViewMatrix = viewMatrix; |
661 SkGlyphCache* cache = this->setupCache(&blob->fRuns[0], skPaint, &viewMa
trix, false); | 732 SkGlyphCache* cache = this->setupCache(&blob->fRuns[0], skPaint, &viewMa
trix, false); |
662 this->internalDrawBMPPosText(blob, 0, cache, skPaint, paint.getColor(),
viewMatrix, text, | 733 this->internalDrawBMPPosText(blob, 0, cache, skPaint, paint.getColor(),
viewMatrix, text, |
663 byteLength, pos, scalarsPerPosition, offset
, clipRect); | 734 byteLength, pos, scalarsPerPosition, offset
, clipRect); |
664 SkGlyphCache::AttachCache(cache); | 735 SkGlyphCache::AttachCache(cache); |
(...skipping 771 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1436 for (int i = 0; i < instanceCount; i++) { | 1507 for (int i = 0; i < instanceCount; i++) { |
1437 Geometry& args = fGeoData[i]; | 1508 Geometry& args = fGeoData[i]; |
1438 Blob* blob = args.fBlob; | 1509 Blob* blob = args.fBlob; |
1439 Run& run = blob->fRuns[args.fRun]; | 1510 Run& run = blob->fRuns[args.fRun]; |
1440 TextInfo& info = run.fSubRunInfo[args.fSubRun]; | 1511 TextInfo& info = run.fSubRunInfo[args.fSubRun]; |
1441 | 1512 |
1442 uint64_t currentAtlasGen = fFontCache->atlasGeneration(fMaskFormat); | 1513 uint64_t currentAtlasGen = fFontCache->atlasGeneration(fMaskFormat); |
1443 bool regenerateTextureCoords = info.fAtlasGeneration != currentAtlas
Gen; | 1514 bool regenerateTextureCoords = info.fAtlasGeneration != currentAtlas
Gen; |
1444 bool regenerateColors; | 1515 bool regenerateColors; |
1445 if (fUseDistanceFields) { | 1516 if (fUseDistanceFields) { |
1446 regenerateColors = fUseLCDText && run.fColor != args.fColor; | 1517 regenerateColors = !fUseLCDText && run.fColor != args.fColor; |
1447 } else { | 1518 } else { |
1448 regenerateColors = kA8_GrMaskFormat == fMaskFormat && run.fColor
!= args.fColor; | 1519 regenerateColors = kA8_GrMaskFormat == fMaskFormat && run.fColor
!= args.fColor; |
1449 } | 1520 } |
1450 bool regeneratePositions = args.fTransX != 0.f || args.fTransY != 0.
f; | 1521 bool regeneratePositions = args.fTransX != 0.f || args.fTransY != 0.
f; |
1451 int glyphCount = info.fGlyphEndIndex - info.fGlyphStartIndex; | 1522 int glyphCount = info.fGlyphEndIndex - info.fGlyphStartIndex; |
1452 | 1523 |
1453 // We regenerate both texture coords and colors in the blob itself,
and update the | 1524 // We regenerate both texture coords and colors in the blob itself,
and update the |
1454 // atlas generation. If we don't end up purging any unused plots, w
e can avoid | 1525 // atlas generation. If we don't end up purging any unused plots, w
e can avoid |
1455 // regenerating the coords. We could take a finer grained approach
to updating texture | 1526 // regenerating the coords. We could take a finer grained approach
to updating texture |
1456 // coords but its not clear if the extra bookkeeping would offset an
y gains. | 1527 // coords but its not clear if the extra bookkeeping would offset an
y gains. |
(...skipping 543 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2000 pipelineBuilder.setFromPaint(grPaint, rt, clip); | 2071 pipelineBuilder.setFromPaint(grPaint, rt, clip); |
2001 | 2072 |
2002 GrColor color = grPaint.getColor(); | 2073 GrColor color = grPaint.getColor(); |
2003 for (int run = 0; run < cacheBlob->fRunCount; run++) { | 2074 for (int run = 0; run < cacheBlob->fRunCount; run++) { |
2004 this->flushRun(target, &pipelineBuilder, cacheBlob, run, color, 0, 0, sk
Paint); | 2075 this->flushRun(target, &pipelineBuilder, cacheBlob, run, color, 0, 0, sk
Paint); |
2005 } | 2076 } |
2006 | 2077 |
2007 // Now flush big glyphs | 2078 // Now flush big glyphs |
2008 this->flushBigGlyphs(cacheBlob, rt, grPaint, clip, 0, 0); | 2079 this->flushBigGlyphs(cacheBlob, rt, grPaint, clip, 0, 0); |
2009 } | 2080 } |
OLD | NEW |