OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 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 "GrBitmapTextContext.h" | 8 #include "GrBitmapTextContext.h" |
9 #include "GrAtlas.h" | 9 #include "GrAtlas.h" |
10 #include "GrDrawTarget.h" | 10 #include "GrDrawTarget.h" |
(...skipping 29 matching lines...) Expand all Loading... |
40 | 40 |
41 static const size_t kTextVASize = 2 * sizeof(SkPoint); | 41 static const size_t kTextVASize = 2 * sizeof(SkPoint); |
42 | 42 |
43 // position + color + texture coord | 43 // position + color + texture coord |
44 extern const GrVertexAttrib gTextVertexWithColorAttribs[] = { | 44 extern const GrVertexAttrib gTextVertexWithColorAttribs[] = { |
45 {kVec2f_GrVertexAttribType, 0, kPosition_Gr
VertexAttribBinding}, | 45 {kVec2f_GrVertexAttribType, 0, kPosition_Gr
VertexAttribBinding}, |
46 {kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVer
texAttribBinding}, | 46 {kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVer
texAttribBinding}, |
47 {kVec2f_GrVertexAttribType, sizeof(SkPoint) + sizeof(GrColor), kGeometryPro
cessor_GrVertexAttribBinding} | 47 {kVec2f_GrVertexAttribType, sizeof(SkPoint) + sizeof(GrColor), kGeometryPro
cessor_GrVertexAttribBinding} |
48 }; | 48 }; |
49 | 49 |
50 static const size_t kTextVAColorSize = 2 * sizeof(SkPoint) + sizeof(GrColor); | 50 static const size_t kTextVAColorSize = 2 * sizeof(SkPoint) + sizeof(GrColor); |
51 | 51 |
| 52 static const int kVerticesPerGlyph = 4; |
| 53 static const int kIndicesPerGlyph = 6; |
52 }; | 54 }; |
53 | 55 |
54 GrBitmapTextContext::GrBitmapTextContext(GrContext* context, | 56 GrBitmapTextContext::GrBitmapTextContext(GrContext* context, |
55 const SkDeviceProperties& properties) | 57 const SkDeviceProperties& properties) |
56 : GrTextContext(context, properties) { | 58 : GrTextContext(context, properties) { |
57 fStrike = NULL; | 59 fStrike = NULL; |
58 | 60 |
59 fCurrTexture = NULL; | 61 fCurrTexture = NULL; |
60 fCurrVertex = 0; | |
61 fEffectTextureUniqueID = SK_InvalidUniqueID; | 62 fEffectTextureUniqueID = SK_InvalidUniqueID; |
62 | 63 |
63 fVertices = NULL; | 64 fVertices = NULL; |
64 fMaxVertices = 0; | 65 fCurrVertex = 0; |
| 66 fAllocVertexCount = 0; |
| 67 fTotalVertexCount = 0; |
65 | 68 |
66 fVertexBounds.setLargestInverted(); | 69 fVertexBounds.setLargestInverted(); |
67 } | 70 } |
68 | 71 |
69 GrBitmapTextContext* GrBitmapTextContext::Create(GrContext* context, | 72 GrBitmapTextContext* GrBitmapTextContext::Create(GrContext* context, |
70 const SkDeviceProperties& props
) { | 73 const SkDeviceProperties& props
) { |
71 return SkNEW_ARGS(GrBitmapTextContext, (context, props)); | 74 return SkNEW_ARGS(GrBitmapTextContext, (context, props)); |
72 } | 75 } |
73 | 76 |
74 GrBitmapTextContext::~GrBitmapTextContext() { | 77 GrBitmapTextContext::~GrBitmapTextContext() { |
75 this->flush(); | 78 this->finish(); |
76 } | 79 } |
77 | 80 |
78 bool GrBitmapTextContext::canDraw(const SkPaint& paint) { | 81 bool GrBitmapTextContext::canDraw(const SkPaint& paint) { |
79 return !SkDraw::ShouldDrawTextAsPaths(paint, fContext->getMatrix()); | 82 return !SkDraw::ShouldDrawTextAsPaths(paint, fContext->getMatrix()); |
80 } | 83 } |
81 | 84 |
82 inline void GrBitmapTextContext::init(const GrPaint& paint, const SkPaint& skPai
nt) { | 85 inline void GrBitmapTextContext::init(const GrPaint& paint, const SkPaint& skPai
nt) { |
83 GrTextContext::init(paint, skPaint); | 86 GrTextContext::init(paint, skPaint); |
84 | 87 |
85 fStrike = NULL; | 88 fStrike = NULL; |
86 | 89 |
87 fCurrTexture = NULL; | 90 fCurrTexture = NULL; |
88 fCurrVertex = 0; | 91 fCurrVertex = 0; |
89 | 92 |
90 fVertices = NULL; | 93 fVertices = NULL; |
91 fMaxVertices = 0; | 94 fAllocVertexCount = 0; |
| 95 fTotalVertexCount = 0; |
92 } | 96 } |
93 | 97 |
94 void GrBitmapTextContext::onDrawText(const GrPaint& paint, const SkPaint& skPain
t, | 98 void GrBitmapTextContext::onDrawText(const GrPaint& paint, const SkPaint& skPain
t, |
95 const char text[], size_t byteLength, | 99 const char text[], size_t byteLength, |
96 SkScalar x, SkScalar y) { | 100 SkScalar x, SkScalar y) { |
97 SkASSERT(byteLength == 0 || text != NULL); | 101 SkASSERT(byteLength == 0 || text != NULL); |
98 | 102 |
99 // nothing to draw | 103 // nothing to draw |
100 if (text == NULL || byteLength == 0 /*|| fRC->isEmpty()*/) { | 104 if (text == NULL || byteLength == 0 /*|| fRC->isEmpty()*/) { |
101 return; | 105 return; |
102 } | 106 } |
103 | 107 |
104 this->init(paint, skPaint); | 108 this->init(paint, skPaint); |
105 | 109 |
106 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); | 110 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); |
107 | 111 |
108 SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, &fContext->getMa
trix()); | 112 SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, &fContext->getMa
trix()); |
109 SkGlyphCache* cache = autoCache.getCache(); | 113 SkGlyphCache* cache = autoCache.getCache(); |
110 GrFontScaler* fontScaler = GetGrFontScaler(cache); | 114 GrFontScaler* fontScaler = GetGrFontScaler(cache); |
111 | 115 |
112 // transform our starting point | 116 // transform our starting point |
113 { | 117 { |
114 SkPoint loc; | 118 SkPoint loc; |
115 fContext->getMatrix().mapXY(x, y, &loc); | 119 fContext->getMatrix().mapXY(x, y, &loc); |
116 x = loc.fX; | 120 x = loc.fX; |
117 y = loc.fY; | 121 y = loc.fY; |
118 } | 122 } |
119 | 123 |
120 // need to measure first | 124 // need to measure first |
| 125 int numGlyphs; |
121 if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) { | 126 if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) { |
122 SkVector stop; | 127 SkVector stopVector; |
| 128 numGlyphs = MeasureText(cache, glyphCacheProc, text, byteLength, &stopVe
ctor); |
123 | 129 |
124 MeasureText(cache, glyphCacheProc, text, byteLength, &stop); | 130 SkScalar stopX = stopVector.fX; |
125 | 131 SkScalar stopY = stopVector.fY; |
126 SkScalar stopX = stop.fX; | |
127 SkScalar stopY = stop.fY; | |
128 | 132 |
129 if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) { | 133 if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) { |
130 stopX = SkScalarHalf(stopX); | 134 stopX = SkScalarHalf(stopX); |
131 stopY = SkScalarHalf(stopY); | 135 stopY = SkScalarHalf(stopY); |
132 } | 136 } |
133 x -= stopX; | 137 x -= stopX; |
134 y -= stopY; | 138 y -= stopY; |
| 139 } else { |
| 140 numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL); |
135 } | 141 } |
| 142 fTotalVertexCount = kVerticesPerGlyph*numGlyphs; |
136 | 143 |
137 const char* stop = text + byteLength; | 144 const char* stop = text + byteLength; |
138 | 145 |
139 SkAutoKern autokern; | 146 SkAutoKern autokern; |
140 | 147 |
141 SkFixed fxMask = ~0; | 148 SkFixed fxMask = ~0; |
142 SkFixed fyMask = ~0; | 149 SkFixed fyMask = ~0; |
143 SkFixed halfSampleX, halfSampleY; | 150 SkFixed halfSampleX, halfSampleY; |
144 if (cache->isSubpixel()) { | 151 if (cache->isSubpixel()) { |
145 halfSampleX = halfSampleY = (SK_FixedHalf >> SkGlyph::kSubBits); | 152 halfSampleX = halfSampleY = (SK_FixedHalf >> SkGlyph::kSubBits); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
200 | 207 |
201 SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, &fContext->getMa
trix()); | 208 SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, &fContext->getMa
trix()); |
202 SkGlyphCache* cache = autoCache.getCache(); | 209 SkGlyphCache* cache = autoCache.getCache(); |
203 GrFontScaler* fontScaler = GetGrFontScaler(cache); | 210 GrFontScaler* fontScaler = GetGrFontScaler(cache); |
204 | 211 |
205 // store original matrix before we reset, so we can use it to transform posi
tions | 212 // store original matrix before we reset, so we can use it to transform posi
tions |
206 SkMatrix ctm = fContext->getMatrix(); | 213 SkMatrix ctm = fContext->getMatrix(); |
207 GrContext::AutoMatrix autoMatrix; | 214 GrContext::AutoMatrix autoMatrix; |
208 autoMatrix.setIdentity(fContext, &fPaint); | 215 autoMatrix.setIdentity(fContext, &fPaint); |
209 | 216 |
| 217 int numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL); |
| 218 fTotalVertexCount = kVerticesPerGlyph*numGlyphs; |
| 219 |
210 const char* stop = text + byteLength; | 220 const char* stop = text + byteLength; |
211 SkTextAlignProc alignProc(fSkPaint.getTextAlign()); | 221 SkTextAlignProc alignProc(fSkPaint.getTextAlign()); |
212 SkTextMapStateProc tmsProc(ctm, offset, scalarsPerPosition); | 222 SkTextMapStateProc tmsProc(ctm, offset, scalarsPerPosition); |
213 SkFixed halfSampleX = 0, halfSampleY = 0; | 223 SkFixed halfSampleX = 0, halfSampleY = 0; |
214 | 224 |
215 if (cache->isSubpixel()) { | 225 if (cache->isSubpixel()) { |
216 // maybe we should skip the rounding if linearText is set | 226 // maybe we should skip the rounding if linearText is set |
217 SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(ctm); | 227 SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(ctm); |
218 | 228 |
219 SkFixed fxMask = ~0; | 229 SkFixed fxMask = ~0; |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
328 fontScaler); | 338 fontScaler); |
329 } | 339 } |
330 pos += scalarsPerPosition; | 340 pos += scalarsPerPosition; |
331 } | 341 } |
332 } | 342 } |
333 } | 343 } |
334 | 344 |
335 this->finish(); | 345 this->finish(); |
336 } | 346 } |
337 | 347 |
| 348 static void* alloc_vertices(GrDrawTarget* drawTarget, int numVertices, bool useC
olorVerts) { |
| 349 if (numVertices <= 0) { |
| 350 return NULL; |
| 351 } |
| 352 |
| 353 // set up attributes |
| 354 if (useColorVerts) { |
| 355 drawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttribs>( |
| 356 SK_ARRAY_COUNT(gTextVertexWithColorAttribs),
kTextVAColorSize); |
| 357 } else { |
| 358 drawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>( |
| 359 SK_ARRAY_COUNT(gTextVertexAttribs), kTextVAS
ize); |
| 360 } |
| 361 void* vertices = NULL; |
| 362 bool success = drawTarget->reserveVertexAndIndexSpace(numVertices, |
| 363 0, |
| 364 &vertices, |
| 365 NULL); |
| 366 GrAlwaysAssert(success); |
| 367 return vertices; |
| 368 } |
| 369 |
338 void GrBitmapTextContext::appendGlyph(GrGlyph::PackedID packed, | 370 void GrBitmapTextContext::appendGlyph(GrGlyph::PackedID packed, |
339 SkFixed vx, SkFixed vy, | 371 SkFixed vx, SkFixed vy, |
340 GrFontScaler* scaler) { | 372 GrFontScaler* scaler) { |
341 if (NULL == fDrawTarget) { | 373 if (NULL == fDrawTarget) { |
342 return; | 374 return; |
343 } | 375 } |
344 | 376 |
345 if (NULL == fStrike) { | 377 if (NULL == fStrike) { |
346 fStrike = fContext->getFontCache()->getStrike(scaler, false); | 378 fStrike = fContext->getFontCache()->getStrike(scaler, false); |
347 } | 379 } |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
411 this->flush(); | 443 this->flush(); |
412 | 444 |
413 GrContext::AutoMatrix am; | 445 GrContext::AutoMatrix am; |
414 SkMatrix translate; | 446 SkMatrix translate; |
415 translate.setTranslate(SkFixedToScalar(vx - SkIntToFixed(glyph->fBounds.
fLeft)), | 447 translate.setTranslate(SkFixedToScalar(vx - SkIntToFixed(glyph->fBounds.
fLeft)), |
416 SkFixedToScalar(vy - SkIntToFixed(glyph->fBounds.
fTop))); | 448 SkFixedToScalar(vy - SkIntToFixed(glyph->fBounds.
fTop))); |
417 GrPaint tmpPaint(fPaint); | 449 GrPaint tmpPaint(fPaint); |
418 am.setPreConcat(fContext, translate, &tmpPaint); | 450 am.setPreConcat(fContext, translate, &tmpPaint); |
419 GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle); | 451 GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle); |
420 fContext->drawPath(tmpPaint, *glyph->fPath, strokeInfo); | 452 fContext->drawPath(tmpPaint, *glyph->fPath, strokeInfo); |
| 453 |
| 454 // remove this glyph from the vertices we need to allocate |
| 455 fTotalVertexCount -= kVerticesPerGlyph; |
421 return; | 456 return; |
422 } | 457 } |
423 | 458 |
424 HAS_ATLAS: | 459 HAS_ATLAS: |
425 SkASSERT(glyph->fPlot); | 460 SkASSERT(glyph->fPlot); |
426 GrDrawTarget::DrawToken drawToken = fDrawTarget->getCurrentDrawToken(); | 461 GrDrawTarget::DrawToken drawToken = fDrawTarget->getCurrentDrawToken(); |
427 glyph->fPlot->setDrawToken(drawToken); | 462 glyph->fPlot->setDrawToken(drawToken); |
428 | 463 |
429 // now promote them to fixed (TODO: Rethink using fixed pt). | 464 // now promote them to fixed (TODO: Rethink using fixed pt). |
430 width = SkIntToFixed(width); | 465 width = SkIntToFixed(width); |
431 height = SkIntToFixed(height); | 466 height = SkIntToFixed(height); |
432 | 467 |
433 // the current texture/maskformat must match what the glyph needs | 468 // the current texture/maskformat must match what the glyph needs |
434 GrTexture* texture = glyph->fPlot->texture(); | 469 GrTexture* texture = glyph->fPlot->texture(); |
435 SkASSERT(texture); | 470 SkASSERT(texture); |
436 | 471 |
437 if (fCurrTexture != texture || fCurrVertex + 4 > fMaxVertices) { | 472 if (fCurrTexture != texture || fCurrVertex + kVerticesPerGlyph > fAllocVerte
xCount) { |
438 this->flush(); | 473 this->flush(); |
439 fCurrTexture = texture; | 474 fCurrTexture = texture; |
440 fCurrTexture->ref(); | 475 fCurrTexture->ref(); |
441 fCurrMaskFormat = glyph->fMaskFormat; | 476 fCurrMaskFormat = glyph->fMaskFormat; |
442 } | 477 } |
443 | 478 |
444 bool useColorVerts = kA8_GrMaskFormat == fCurrMaskFormat; | 479 bool useColorVerts = kA8_GrMaskFormat == fCurrMaskFormat; |
445 | 480 |
446 if (NULL == fVertices) { | 481 if (NULL == fVertices) { |
447 // If we need to reserve vertices allow the draw target to suggest | 482 int maxQuadVertices = kVerticesPerGlyph * fContext->getQuadIndexBuffer()
->maxQuads(); |
448 // a number of verts to reserve and whether to perform a flush. | 483 fAllocVertexCount = SkMin32(fTotalVertexCount, maxQuadVertices); |
449 fMaxVertices = kMinRequestedVerts; | 484 fVertices = alloc_vertices(fDrawTarget, fAllocVertexCount, useColorVerts
); |
450 if (useColorVerts) { | |
451 fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttri
bs>( | |
452 SK_ARRAY_COUNT(gTextVertexWithColorAttribs), kTextVAColorSize); | |
453 } else { | |
454 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>( | |
455 SK_ARRAY_COUNT(gTextVertexAttribs), kTextVASize); | |
456 } | |
457 bool flush = fDrawTarget->geometryHints(&fMaxVertices, NULL); | |
458 if (flush) { | |
459 this->flush(); | |
460 fContext->flush(); | |
461 if (useColorVerts) { | |
462 fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorA
ttribs>( | |
463 SK_ARRAY_COUNT(gTextVertexWithColorAttribs), kTextVAColorSiz
e); | |
464 } else { | |
465 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>( | |
466 SK_ARRAY_COUNT(gTextVertexAttribs), kTextVASize); | |
467 } | |
468 } | |
469 fMaxVertices = kDefaultRequestedVerts; | |
470 // ignore return, no point in flushing again. | |
471 fDrawTarget->geometryHints(&fMaxVertices, NULL); | |
472 | |
473 int maxQuadVertices = 4 * fContext->getQuadIndexBuffer()->maxQuads(); | |
474 if (fMaxVertices < kMinRequestedVerts) { | |
475 fMaxVertices = kDefaultRequestedVerts; | |
476 } else if (fMaxVertices > maxQuadVertices) { | |
477 // don't exceed the limit of the index buffer | |
478 fMaxVertices = maxQuadVertices; | |
479 } | |
480 bool success = fDrawTarget->reserveVertexAndIndexSpace(fMaxVertices, | |
481 0, | |
482 &fVertices, | |
483 NULL); | |
484 GrAlwaysAssert(success); | |
485 } | 485 } |
486 | 486 |
487 SkFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX); | 487 SkFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX); |
488 SkFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY); | 488 SkFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY); |
489 | 489 |
490 SkRect r; | 490 SkRect r; |
491 r.fLeft = SkFixedToFloat(vx); | 491 r.fLeft = SkFixedToFloat(vx); |
492 r.fTop = SkFixedToFloat(vy); | 492 r.fTop = SkFixedToFloat(vy); |
493 r.fRight = SkFixedToFloat(vx + width); | 493 r.fRight = SkFixedToFloat(vx + width); |
494 r.fBottom = SkFixedToFloat(vy + height); | 494 r.fBottom = SkFixedToFloat(vy + height); |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
590 // Grayscale/BW text | 590 // Grayscale/BW text |
591 case kA8_GrMaskFormat: | 591 case kA8_GrMaskFormat: |
592 // set back to normal in case we took LCD path previously. | 592 // set back to normal in case we took LCD path previously. |
593 drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDst
BlendCoeff()); | 593 drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDst
BlendCoeff()); |
594 // We're using per-vertex color. | 594 // We're using per-vertex color. |
595 SkASSERT(drawState->hasColorVertexAttribute()); | 595 SkASSERT(drawState->hasColorVertexAttribute()); |
596 break; | 596 break; |
597 default: | 597 default: |
598 SkFAIL("Unexpected mask format."); | 598 SkFAIL("Unexpected mask format."); |
599 } | 599 } |
600 int nGlyphs = fCurrVertex / 4; | 600 int nGlyphs = fCurrVertex / kVerticesPerGlyph; |
601 fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); | 601 fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); |
602 fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType, | 602 fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType, |
603 nGlyphs, | 603 nGlyphs, |
604 4, 6, &fVertexBounds); | 604 kVerticesPerGlyph, kIndicesPerGlyph, &
fVertexBounds); |
605 | 605 |
606 fDrawTarget->resetVertexSource(); | 606 fDrawTarget->resetVertexSource(); |
607 fVertices = NULL; | 607 fVertices = NULL; |
608 fMaxVertices = 0; | 608 fAllocVertexCount = 0; |
| 609 // reset to be those that are left |
| 610 fTotalVertexCount -= fCurrVertex; |
609 fCurrVertex = 0; | 611 fCurrVertex = 0; |
610 fVertexBounds.setLargestInverted(); | 612 fVertexBounds.setLargestInverted(); |
611 SkSafeSetNull(fCurrTexture); | 613 SkSafeSetNull(fCurrTexture); |
612 } | 614 } |
613 } | 615 } |
614 | 616 |
615 inline void GrBitmapTextContext::finish() { | 617 inline void GrBitmapTextContext::finish() { |
616 this->flush(); | 618 this->flush(); |
| 619 fTotalVertexCount = 0; |
617 | 620 |
618 GrTextContext::finish(); | 621 GrTextContext::finish(); |
619 } | 622 } |
620 | 623 |
OLD | NEW |