OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 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 "GrStencilAndCoverTextContext.h" | 8 #include "GrStencilAndCoverTextContext.h" |
9 #include "GrAtlasTextContext.h" | 9 #include "GrAtlasTextContext.h" |
10 #include "GrDrawContext.h" | 10 #include "GrDrawContext.h" |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
226 } | 226 } |
227 | 227 |
228 fCpuMemorySize += run->computeSizeInCache(); | 228 fCpuMemorySize += run->computeSizeInCache(); |
229 } | 229 } |
230 } | 230 } |
231 | 231 |
232 ////////////////////////////////////////////////////////////////////////////////
//////////////////// | 232 ////////////////////////////////////////////////////////////////////////////////
//////////////////// |
233 | 233 |
234 class GrStencilAndCoverTextContext::FallbackBlobBuilder { | 234 class GrStencilAndCoverTextContext::FallbackBlobBuilder { |
235 public: | 235 public: |
236 FallbackBlobBuilder() : fBuffIdx(0) {} | 236 FallbackBlobBuilder() : fBuffIdx(0), fCount(0) {} |
237 | 237 |
238 bool isInitialized() const { return SkToBool(fBuilder); } | 238 bool isInitialized() const { return SkToBool(fBuilder); } |
239 | 239 |
240 void init(const SkPaint& font, SkScalar textRatio); | 240 void init(const SkPaint& font, SkScalar textRatio); |
241 | 241 |
242 void appendGlyph(uint16_t glyphId, const SkPoint& pos); | 242 void appendGlyph(uint16_t glyphId, const SkPoint& pos); |
243 | 243 |
244 const SkTextBlob* buildIfInitialized(); | 244 const SkTextBlob* buildIfNeeded(int* count); |
245 | 245 |
246 private: | 246 private: |
247 enum { kWriteBufferSize = 1024 }; | 247 enum { kWriteBufferSize = 1024 }; |
248 | 248 |
249 void flush(); | 249 void flush(); |
250 | 250 |
251 SkAutoTDelete<SkTextBlobBuilder> fBuilder; | 251 SkAutoTDelete<SkTextBlobBuilder> fBuilder; |
252 SkPaint fFont; | 252 SkPaint fFont; |
253 int fBuffIdx; | 253 int fBuffIdx; |
| 254 int fCount; |
254 uint16_t fGlyphIds[kWriteBufferSize]; | 255 uint16_t fGlyphIds[kWriteBufferSize]; |
255 SkPoint fPositions[kWriteBufferSize]; | 256 SkPoint fPositions[kWriteBufferSize]; |
256 }; | 257 }; |
257 | 258 |
258 ////////////////////////////////////////////////////////////////////////////////
//////////////////// | 259 ////////////////////////////////////////////////////////////////////////////////
//////////////////// |
259 | 260 |
260 GrStencilAndCoverTextContext::TextRun::TextRun(const SkPaint& fontAndStroke) | 261 GrStencilAndCoverTextContext::TextRun::TextRun(const SkPaint& fontAndStroke) |
261 : fStroke(fontAndStroke), | 262 : fStroke(fontAndStroke), |
262 fFont(fontAndStroke), | 263 fFont(fontAndStroke), |
263 fTotalGlyphCount(0), | 264 fTotalGlyphCount(0), |
| 265 fFallbackGlyphCount(0), |
264 fDetachedGlyphCache(nullptr), | 266 fDetachedGlyphCache(nullptr), |
265 fLastDrawnGlyphsID(SK_InvalidUniqueID) { | 267 fLastDrawnGlyphsID(SK_InvalidUniqueID) { |
266 SkASSERT(!fStroke.isHairlineStyle()); // Hairlines are not supported. | 268 SkASSERT(!fStroke.isHairlineStyle()); // Hairlines are not supported. |
267 | 269 |
268 // Setting to "fill" ensures that no strokes get baked into font outlines. (
We use the GPU path | 270 // Setting to "fill" ensures that no strokes get baked into font outlines. (
We use the GPU path |
269 // rendering API for stroking). | 271 // rendering API for stroking). |
270 fFont.setStyle(SkPaint::kFill_Style); | 272 fFont.setStyle(SkPaint::kFill_Style); |
271 | 273 |
272 if (fFont.isFakeBoldText() && SkStrokeRec::kStroke_Style != fStroke.getStyle
()) { | 274 if (fFont.isFakeBoldText() && SkStrokeRec::kStroke_Style != fStroke.getStyle
()) { |
273 // Instead of letting fake bold get baked into the glyph outlines, do it
with GPU stroke. | 275 // Instead of letting fake bold get baked into the glyph outlines, do it
with GPU stroke. |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
332 const SkDescriptor* desc = &glyphCache->getDescriptor(); | 334 const SkDescriptor* desc = &glyphCache->getDescriptor(); |
333 int descDataCount = (desc->getLength() + 3) / 4; | 335 int descDataCount = (desc->getLength() + 3) / 4; |
334 GrUniqueKey::Builder builder(&fGlyphPathsKey, kPathGlyphDomain, | 336 GrUniqueKey::Builder builder(&fGlyphPathsKey, kPathGlyphDomain, |
335 2 + strokeDataCount + descDataCount); | 337 2 + strokeDataCount + descDataCount); |
336 reinterpret_cast<uint32_t&>(builder[0]) = typeface ? typeface->uniqu
eID() : 0; | 338 reinterpret_cast<uint32_t&>(builder[0]) = typeface ? typeface->uniqu
eID() : 0; |
337 reinterpret_cast<uint32_t&>(builder[1]) = strokeDataCount | (descDat
aCount << 16); | 339 reinterpret_cast<uint32_t&>(builder[1]) = strokeDataCount | (descDat
aCount << 16); |
338 fStroke.asUniqueKeyFragment(&builder[2]); | 340 fStroke.asUniqueKeyFragment(&builder[2]); |
339 memcpy(&builder[2 + strokeDataCount], desc, desc->getLength()); | 341 memcpy(&builder[2 + strokeDataCount], desc, desc->getLength()); |
340 } | 342 } |
341 } | 343 } |
342 | |
343 // When drawing from canonically sized paths, the actual local coords are fT
extRatio * coords. | |
344 fLocalMatrixTemplate.setScale(fTextRatio, fTextRatio); | |
345 } | 344 } |
346 | 345 |
347 GrStencilAndCoverTextContext::TextRun::~TextRun() { | 346 GrStencilAndCoverTextContext::TextRun::~TextRun() { |
348 this->releaseGlyphCache(); | 347 this->releaseGlyphCache(); |
349 } | 348 } |
350 | 349 |
351 void GrStencilAndCoverTextContext::TextRun::setText(const char text[], size_t by
teLength, | 350 void GrStencilAndCoverTextContext::TextRun::setText(const char text[], size_t by
teLength, |
352 SkScalar x, SkScalar y) { | 351 SkScalar x, SkScalar y) { |
353 SkASSERT(byteLength == 0 || text != nullptr); | 352 SkASSERT(byteLength == 0 || text != nullptr); |
354 | 353 |
355 SkGlyphCache* glyphCache = this->getGlyphCache(); | 354 SkGlyphCache* glyphCache = this->getGlyphCache(); |
356 SkDrawCacheProc glyphCacheProc = fFont.getDrawCacheProc(); | 355 SkDrawCacheProc glyphCacheProc = fFont.getDrawCacheProc(); |
357 | 356 |
358 fDraw.reset(GrPathRangeDraw::Create(GrPathRendering::kTranslate_PathTransfor
mType, | 357 fTotalGlyphCount = fFont.countText(text, byteLength); |
359 fTotalGlyphCount = fFont.countText(text,
byteLength))); | 358 fInstanceData.reset(InstanceData::Alloc(GrPathRendering::kTranslate_PathTran
sformType, |
| 359 fTotalGlyphCount)); |
360 | 360 |
361 const char* stop = text + byteLength; | 361 const char* stop = text + byteLength; |
362 | 362 |
363 // Measure first if needed. | 363 // Measure first if needed. |
364 if (fFont.getTextAlign() != SkPaint::kLeft_Align) { | 364 if (fFont.getTextAlign() != SkPaint::kLeft_Align) { |
365 SkFixed stopX = 0; | 365 SkFixed stopX = 0; |
366 SkFixed stopY = 0; | 366 SkFixed stopY = 0; |
367 | 367 |
368 const char* textPtr = text; | 368 const char* textPtr = text; |
369 while (textPtr < stop) { | 369 while (textPtr < stop) { |
(...skipping 30 matching lines...) Expand all Loading... |
400 fx += SkFixedMul(autokern.adjust(glyph), fixedSizeRatio); | 400 fx += SkFixedMul(autokern.adjust(glyph), fixedSizeRatio); |
401 if (glyph.fWidth) { | 401 if (glyph.fWidth) { |
402 this->appendGlyph(glyph, SkPoint::Make(SkFixedToScalar(fx), SkFixedT
oScalar(fy)), | 402 this->appendGlyph(glyph, SkPoint::Make(SkFixedToScalar(fx), SkFixedT
oScalar(fy)), |
403 &fallback); | 403 &fallback); |
404 } | 404 } |
405 | 405 |
406 fx += SkFixedMul(glyph.fAdvanceX, fixedSizeRatio); | 406 fx += SkFixedMul(glyph.fAdvanceX, fixedSizeRatio); |
407 fy += SkFixedMul(glyph.fAdvanceY, fixedSizeRatio); | 407 fy += SkFixedMul(glyph.fAdvanceY, fixedSizeRatio); |
408 } | 408 } |
409 | 409 |
410 fFallbackTextBlob.reset(fallback.buildIfInitialized()); | 410 fFallbackTextBlob.reset(fallback.buildIfNeeded(&fFallbackGlyphCount)); |
411 } | 411 } |
412 | 412 |
413 void GrStencilAndCoverTextContext::TextRun::setPosText(const char text[], size_t
byteLength, | 413 void GrStencilAndCoverTextContext::TextRun::setPosText(const char text[], size_t
byteLength, |
414 const SkScalar pos[], int
scalarsPerPosition, | 414 const SkScalar pos[], int
scalarsPerPosition, |
415 const SkPoint& offset) { | 415 const SkPoint& offset) { |
416 SkASSERT(byteLength == 0 || text != nullptr); | 416 SkASSERT(byteLength == 0 || text != nullptr); |
417 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); | 417 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); |
418 | 418 |
419 SkGlyphCache* glyphCache = this->getGlyphCache(); | 419 SkGlyphCache* glyphCache = this->getGlyphCache(); |
420 SkDrawCacheProc glyphCacheProc = fFont.getDrawCacheProc(); | 420 SkDrawCacheProc glyphCacheProc = fFont.getDrawCacheProc(); |
421 | 421 |
422 fDraw.reset(GrPathRangeDraw::Create(GrPathRendering::kTranslate_PathTransfor
mType, | 422 fTotalGlyphCount = fFont.countText(text, byteLength); |
423 fTotalGlyphCount = fFont.countText(text,
byteLength))); | 423 fInstanceData.reset(InstanceData::Alloc(GrPathRendering::kTranslate_PathTran
sformType, |
| 424 fTotalGlyphCount)); |
424 | 425 |
425 const char* stop = text + byteLength; | 426 const char* stop = text + byteLength; |
426 | 427 |
427 SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition); | 428 SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition); |
428 SkTextAlignProc alignProc(fFont.getTextAlign()); | 429 SkTextAlignProc alignProc(fFont.getTextAlign()); |
429 FallbackBlobBuilder fallback; | 430 FallbackBlobBuilder fallback; |
430 while (text < stop) { | 431 while (text < stop) { |
431 const SkGlyph& glyph = glyphCacheProc(glyphCache, &text, 0, 0); | 432 const SkGlyph& glyph = glyphCacheProc(glyphCache, &text, 0, 0); |
432 if (glyph.fWidth) { | 433 if (glyph.fWidth) { |
433 SkPoint tmsLoc; | 434 SkPoint tmsLoc; |
434 tmsProc(pos, &tmsLoc); | 435 tmsProc(pos, &tmsLoc); |
435 SkPoint loc; | 436 SkPoint loc; |
436 alignProc(tmsLoc, glyph, &loc); | 437 alignProc(tmsLoc, glyph, &loc); |
437 | 438 |
438 this->appendGlyph(glyph, loc, &fallback); | 439 this->appendGlyph(glyph, loc, &fallback); |
439 } | 440 } |
440 pos += scalarsPerPosition; | 441 pos += scalarsPerPosition; |
441 } | 442 } |
442 | 443 |
443 fFallbackTextBlob.reset(fallback.buildIfInitialized()); | 444 fFallbackTextBlob.reset(fallback.buildIfNeeded(&fFallbackGlyphCount)); |
444 } | 445 } |
445 | 446 |
446 GrPathRange* GrStencilAndCoverTextContext::TextRun::createGlyphs(GrContext* ctx)
const { | 447 GrPathRange* GrStencilAndCoverTextContext::TextRun::createGlyphs(GrContext* ctx)
const { |
447 GrPathRange* glyphs = static_cast<GrPathRange*>( | 448 GrPathRange* glyphs = static_cast<GrPathRange*>( |
448 ctx->resourceProvider()->findAndRefResourceByUniqueKey(fGlyphPathsKe
y)); | 449 ctx->resourceProvider()->findAndRefResourceByUniqueKey(fGlyphPathsKe
y)); |
449 if (nullptr == glyphs) { | 450 if (nullptr == glyphs) { |
450 if (fUsingRawGlyphPaths) { | 451 if (fUsingRawGlyphPaths) { |
451 glyphs = ctx->resourceProvider()->createGlyphs(fFont.getTypeface(),
nullptr, fStroke); | 452 glyphs = ctx->resourceProvider()->createGlyphs(fFont.getTypeface(),
nullptr, fStroke); |
452 } else { | 453 } else { |
453 SkGlyphCache* cache = this->getGlyphCache(); | 454 SkGlyphCache* cache = this->getGlyphCache(); |
454 glyphs = ctx->resourceProvider()->createGlyphs(cache->getScalerConte
xt()->getTypeface(), | 455 glyphs = ctx->resourceProvider()->createGlyphs(cache->getScalerConte
xt()->getTypeface(), |
455 &cache->getDescriptor
(), | 456 &cache->getDescriptor
(), |
456 fStroke); | 457 fStroke); |
457 } | 458 } |
458 ctx->resourceProvider()->assignUniqueKeyToResource(fGlyphPathsKey, glyph
s); | 459 ctx->resourceProvider()->assignUniqueKeyToResource(fGlyphPathsKey, glyph
s); |
459 } | 460 } |
460 return glyphs; | 461 return glyphs; |
461 } | 462 } |
462 | 463 |
463 inline void GrStencilAndCoverTextContext::TextRun::appendGlyph(const SkGlyph& gl
yph, | 464 inline void GrStencilAndCoverTextContext::TextRun::appendGlyph(const SkGlyph& gl
yph, |
464 const SkPoint& po
s, | 465 const SkPoint& po
s, |
465 FallbackBlobBuild
er* fallback) { | 466 FallbackBlobBuild
er* fallback) { |
466 // Stick the glyphs we can't draw into the fallback text blob. | 467 // Stick the glyphs we can't draw into the fallback text blob. |
467 if (SkMask::kARGB32_Format == glyph.fMaskFormat) { | 468 if (SkMask::kARGB32_Format == glyph.fMaskFormat) { |
468 if (!fallback->isInitialized()) { | 469 if (!fallback->isInitialized()) { |
469 fallback->init(fFont, fTextRatio); | 470 fallback->init(fFont, fTextRatio); |
470 } | 471 } |
471 fallback->appendGlyph(glyph.getGlyphID(), pos); | 472 fallback->appendGlyph(glyph.getGlyphID(), pos); |
472 } else { | 473 } else { |
473 float translate[] = { fTextInverseRatio * pos.x(), fTextInverseRatio * p
os.y() }; | 474 fInstanceData->append(glyph.getGlyphID(), fTextInverseRatio * pos.x(), |
474 fDraw->append(glyph.getGlyphID(), translate); | 475 fTextInverseRatio * pos.y()); |
475 } | 476 } |
476 } | 477 } |
477 | 478 |
478 void GrStencilAndCoverTextContext::TextRun::draw(GrContext* ctx, | 479 void GrStencilAndCoverTextContext::TextRun::draw(GrContext* ctx, |
479 GrDrawContext* dc, | 480 GrDrawContext* dc, |
480 GrPipelineBuilder* pipelineBuil
der, | 481 GrPipelineBuilder* pipelineBuil
der, |
481 GrColor color, | 482 GrColor color, |
482 const SkMatrix& viewMatrix, | 483 const SkMatrix& viewMatrix, |
483 SkScalar x, SkScalar y, | 484 SkScalar x, SkScalar y, |
484 const SkIRect& clipBounds, | 485 const SkIRect& clipBounds, |
485 GrTextContext* fallbackTextCont
ext, | 486 GrTextContext* fallbackTextCont
ext, |
486 const SkPaint& originalSkPaint)
const { | 487 const SkPaint& originalSkPaint)
const { |
487 SkASSERT(fDraw); | 488 SkASSERT(fInstanceData); |
488 SkASSERT(dc->accessRenderTarget()->isStencilBufferMultisampled() || !fFont.i
sAntiAlias()); | 489 SkASSERT(dc->accessRenderTarget()->isStencilBufferMultisampled() || !fFont.i
sAntiAlias()); |
489 | 490 |
490 if (fDraw->count()) { | 491 if (fInstanceData->count()) { |
491 pipelineBuilder->setState(GrPipelineBuilder::kHWAntialias_Flag, fFont.is
AntiAlias()); | 492 pipelineBuilder->setState(GrPipelineBuilder::kHWAntialias_Flag, fFont.is
AntiAlias()); |
492 | 493 |
493 GR_STATIC_CONST_SAME_STENCIL(kStencilPass, | 494 GR_STATIC_CONST_SAME_STENCIL(kStencilPass, |
494 kZero_StencilOp, | 495 kZero_StencilOp, |
495 kKeep_StencilOp, | 496 kKeep_StencilOp, |
496 kNotEqual_StencilFunc, | 497 kNotEqual_StencilFunc, |
497 0xffff, | 498 0xffff, |
498 0x0000, | 499 0x0000, |
499 0xffff); | 500 0xffff); |
500 | 501 |
501 *pipelineBuilder->stencil() = kStencilPass; | 502 *pipelineBuilder->stencil() = kStencilPass; |
502 | 503 |
503 SkAutoTUnref<GrPathRange> glyphs(this->createGlyphs(ctx)); | 504 SkAutoTUnref<GrPathRange> glyphs(this->createGlyphs(ctx)); |
504 if (fLastDrawnGlyphsID != glyphs->getUniqueID()) { | 505 if (fLastDrawnGlyphsID != glyphs->getUniqueID()) { |
505 // Either this is the first draw or the glyphs object was purged sin
ce last draw. | 506 // Either this is the first draw or the glyphs object was purged sin
ce last draw. |
506 glyphs->loadPathsIfNeeded(fDraw->indices(), fDraw->count()); | 507 glyphs->loadPathsIfNeeded(fInstanceData->indices(), fInstanceData->c
ount()); |
507 fLastDrawnGlyphsID = glyphs->getUniqueID(); | 508 fLastDrawnGlyphsID = glyphs->getUniqueID(); |
508 } | 509 } |
509 | 510 |
510 SkMatrix drawMatrix(viewMatrix); | |
511 drawMatrix.preTranslate(x, y); | |
512 drawMatrix.preScale(fTextRatio, fTextRatio); | |
513 | |
514 SkMatrix& localMatrix = fLocalMatrixTemplate; | |
515 localMatrix.setTranslateX(x); | |
516 localMatrix.setTranslateY(y); | |
517 | |
518 // Don't compute a bounding box. For dst copy texture, we'll opt instead
for it to just copy | 511 // Don't compute a bounding box. For dst copy texture, we'll opt instead
for it to just copy |
519 // the entire dst. Realistically this is a moot point, because any conte
xt that supports | 512 // the entire dst. Realistically this is a moot point, because any conte
xt that supports |
520 // NV_path_rendering will also support NV_blend_equation_advanced. | 513 // NV_path_rendering will also support NV_blend_equation_advanced. |
521 // For clipping we'll just skip any optimizations based on the bounds. T
his does, however, | 514 // For clipping we'll just skip any optimizations based on the bounds. T
his does, however, |
522 // hurt batching. | 515 // hurt batching. |
523 SkRect bounds = SkRect::MakeIWH(pipelineBuilder->getRenderTarget()->widt
h(), | 516 SkRect bounds = SkRect::MakeIWH(pipelineBuilder->getRenderTarget()->widt
h(), |
524 pipelineBuilder->getRenderTarget()->heig
ht()); | 517 pipelineBuilder->getRenderTarget()->heig
ht()); |
525 | 518 |
526 SkAutoTUnref<GrDrawPathBatchBase> batch( | 519 SkAutoTUnref<GrDrawPathBatchBase> batch( |
527 GrDrawPathRangeBatch::Create(drawMatrix, localMatrix, color, | 520 GrDrawPathRangeBatch::Create(viewMatrix, fTextRatio, fTextInverseRat
io * x, |
528 GrPathRendering::kWinding_FillType, gly
phs, fDraw, | 521 fTextInverseRatio * y, color, |
| 522 GrPathRendering::kWinding_FillType, gly
phs, fInstanceData, |
529 bounds)); | 523 bounds)); |
530 | 524 |
531 dc->drawPathBatch(*pipelineBuilder, batch); | 525 dc->drawPathBatch(*pipelineBuilder, batch); |
532 } | 526 } |
533 | 527 |
534 if (fFallbackTextBlob) { | 528 if (fFallbackTextBlob) { |
535 SkPaint fallbackSkPaint(originalSkPaint); | 529 SkPaint fallbackSkPaint(originalSkPaint); |
536 fStroke.applyToPaint(&fallbackSkPaint); | 530 fStroke.applyToPaint(&fallbackSkPaint); |
537 if (!fStroke.isFillStyle()) { | 531 if (!fStroke.isFillStyle()) { |
538 fallbackSkPaint.setStrokeWidth(fStroke.getWidth() * fTextRatio); | 532 fallbackSkPaint.setStrokeWidth(fStroke.getWidth() * fTextRatio); |
(...skipping 13 matching lines...) Expand all Loading... |
552 | 546 |
553 | 547 |
554 void GrStencilAndCoverTextContext::TextRun::releaseGlyphCache() const { | 548 void GrStencilAndCoverTextContext::TextRun::releaseGlyphCache() const { |
555 if (fDetachedGlyphCache) { | 549 if (fDetachedGlyphCache) { |
556 SkGlyphCache::AttachCache(fDetachedGlyphCache); | 550 SkGlyphCache::AttachCache(fDetachedGlyphCache); |
557 fDetachedGlyphCache = nullptr; | 551 fDetachedGlyphCache = nullptr; |
558 } | 552 } |
559 } | 553 } |
560 | 554 |
561 size_t GrStencilAndCoverTextContext::TextRun::computeSizeInCache() const { | 555 size_t GrStencilAndCoverTextContext::TextRun::computeSizeInCache() const { |
562 size_t size = sizeof(TextRun) + | 556 size_t size = sizeof(TextRun) + fGlyphPathsKey.size(); |
563 fGlyphPathsKey.size() + | 557 // The instance data always reserves enough space for every glyph. |
564 fTotalGlyphCount * (sizeof(uint16_t) + 2 * sizeof(float)); | 558 size += (fTotalGlyphCount + fFallbackGlyphCount) * (sizeof(uint16_t) + 2 * s
izeof(float)); |
565 if (fDraw) { | 559 if (fInstanceData) { |
566 size += sizeof(GrPathRangeDraw); | 560 size += sizeof(InstanceData); |
567 } | 561 } |
568 if (fFallbackTextBlob) { | 562 if (fFallbackTextBlob) { |
569 size += sizeof(SkTextBlob); | 563 size += sizeof(SkTextBlob); |
570 } | 564 } |
571 return size; | 565 return size; |
572 } | 566 } |
573 | 567 |
574 ////////////////////////////////////////////////////////////////////////////////
//////////////////// | 568 ////////////////////////////////////////////////////////////////////////////////
//////////////////// |
575 | 569 |
576 void GrStencilAndCoverTextContext::FallbackBlobBuilder::init(const SkPaint& font
, | 570 void GrStencilAndCoverTextContext::FallbackBlobBuilder::init(const SkPaint& font
, |
(...skipping 12 matching lines...) Expand all Loading... |
589 | 583 |
590 void GrStencilAndCoverTextContext::FallbackBlobBuilder::appendGlyph(uint16_t gly
phId, | 584 void GrStencilAndCoverTextContext::FallbackBlobBuilder::appendGlyph(uint16_t gly
phId, |
591 const SkPoin
t& pos) { | 585 const SkPoin
t& pos) { |
592 SkASSERT(this->isInitialized()); | 586 SkASSERT(this->isInitialized()); |
593 if (fBuffIdx >= kWriteBufferSize) { | 587 if (fBuffIdx >= kWriteBufferSize) { |
594 this->flush(); | 588 this->flush(); |
595 } | 589 } |
596 fGlyphIds[fBuffIdx] = glyphId; | 590 fGlyphIds[fBuffIdx] = glyphId; |
597 fPositions[fBuffIdx] = pos; | 591 fPositions[fBuffIdx] = pos; |
598 fBuffIdx++; | 592 fBuffIdx++; |
| 593 fCount++; |
599 } | 594 } |
600 | 595 |
601 void GrStencilAndCoverTextContext::FallbackBlobBuilder::flush() { | 596 void GrStencilAndCoverTextContext::FallbackBlobBuilder::flush() { |
602 SkASSERT(this->isInitialized()); | 597 SkASSERT(this->isInitialized()); |
603 SkASSERT(fBuffIdx <= kWriteBufferSize); | 598 SkASSERT(fBuffIdx <= kWriteBufferSize); |
604 if (!fBuffIdx) { | 599 if (!fBuffIdx) { |
605 return; | 600 return; |
606 } | 601 } |
607 // This will automatically merge with previous runs since we use the same fo
nt. | 602 // This will automatically merge with previous runs since we use the same fo
nt. |
608 const SkTextBlobBuilder::RunBuffer& buff = fBuilder->allocRunPos(fFont, fBuf
fIdx); | 603 const SkTextBlobBuilder::RunBuffer& buff = fBuilder->allocRunPos(fFont, fBuf
fIdx); |
609 memcpy(buff.glyphs, fGlyphIds, fBuffIdx * sizeof(uint16_t)); | 604 memcpy(buff.glyphs, fGlyphIds, fBuffIdx * sizeof(uint16_t)); |
610 memcpy(buff.pos, fPositions[0].asScalars(), fBuffIdx * 2 * sizeof(SkScalar))
; | 605 memcpy(buff.pos, fPositions[0].asScalars(), fBuffIdx * 2 * sizeof(SkScalar))
; |
611 fBuffIdx = 0; | 606 fBuffIdx = 0; |
612 } | 607 } |
613 | 608 |
614 const SkTextBlob* GrStencilAndCoverTextContext::FallbackBlobBuilder::buildIfInit
ialized() { | 609 const SkTextBlob* GrStencilAndCoverTextContext::FallbackBlobBuilder::buildIfNeed
ed(int *count) { |
615 if (!this->isInitialized()) { | 610 *count = fCount; |
616 return nullptr; | 611 if (fCount) { |
| 612 this->flush(); |
| 613 return fBuilder->build(); |
617 } | 614 } |
618 this->flush(); | 615 return nullptr; |
619 return fBuilder->build(); | |
620 } | 616 } |
OLD | NEW |