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" |
11 #include "GrFontScaler.h" | 11 #include "GrFontScaler.h" |
12 #include "GrIndexBuffer.h" | 12 #include "GrIndexBuffer.h" |
13 #include "GrTextStrike.h" | 13 #include "GrTextStrike.h" |
14 #include "GrTextStrike_impl.h" | 14 #include "GrTextStrike_impl.h" |
15 #include "SkColorPriv.h" | 15 #include "SkColorPriv.h" |
16 #include "SkPath.h" | 16 #include "SkPath.h" |
17 #include "SkRTConf.h" | 17 #include "SkRTConf.h" |
18 #include "SkStrokeRec.h" | 18 #include "SkStrokeRec.h" |
19 #include "effects/GrCustomCoordsTextureEffect.h" | 19 #include "effects/GrCustomCoordsTextureEffect.h" |
20 | 20 |
21 #include "SkAutoKern.h" | 21 #include "SkAutoKern.h" |
22 #include "SkDraw.h" | 22 #include "SkDraw.h" |
23 #include "SkGlyphCache.h" | 23 #include "SkGlyphCache.h" |
24 #include "SkGpuDevice.h" | 24 #include "SkGpuDevice.h" |
25 #include "SkGr.h" | 25 #include "SkGr.h" |
26 | 26 |
27 static const int kGlyphCoordsAttributeIndex = 1; | |
28 | |
29 SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false, | 27 SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false, |
30 "Dump the contents of the font cache before every purge."); | 28 "Dump the contents of the font cache before every purge."); |
31 | 29 |
| 30 static const int kGlyphCoordsNoColorAttributeIndex = 1; |
| 31 static const int kGlyphCoordsWithColorAttributeIndex = 2; |
| 32 |
| 33 namespace { |
| 34 // position + texture coord |
| 35 extern const GrVertexAttrib gTextVertexAttribs[] = { |
| 36 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding
}, |
| 37 {kVec2f_GrVertexAttribType, sizeof(SkPoint) , kEffect_GrVertexAttribBinding} |
| 38 }; |
| 39 |
| 40 // position + color + texture coord |
| 41 extern const GrVertexAttrib gTextVertexWithColorAttribs[] = { |
| 42 {kVec2f_GrVertexAttribType, 0, kPosition_Gr
VertexAttribBinding}, |
| 43 {kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVer
texAttribBinding}, |
| 44 {kVec2f_GrVertexAttribType, sizeof(SkPoint) + sizeof(GrColor), kEffect_GrVe
rtexAttribBinding} |
| 45 }; |
| 46 |
| 47 }; |
| 48 |
32 GrBitmapTextContext::GrBitmapTextContext(GrContext* context, | 49 GrBitmapTextContext::GrBitmapTextContext(GrContext* context, |
33 const SkDeviceProperties& properties) | 50 const SkDeviceProperties& properties) |
34 : GrTextContext(context, properties) { | 51 : GrTextContext(context, properties) { |
35 fStrike = NULL; | 52 fStrike = NULL; |
36 | 53 |
37 fCurrTexture = NULL; | 54 fCurrTexture = NULL; |
38 fCurrVertex = 0; | 55 fCurrVertex = 0; |
39 | 56 |
40 fVertices = NULL; | 57 fVertices = NULL; |
41 fMaxVertices = 0; | 58 fMaxVertices = 0; |
(...skipping 27 matching lines...) Expand all Loading... |
69 | 86 |
70 if (fCurrVertex > 0) { | 87 if (fCurrVertex > 0) { |
71 fContext->getFontCache()->updateTextures(); | 88 fContext->getFontCache()->updateTextures(); |
72 | 89 |
73 // setup our sampler state for our text texture/atlas | 90 // setup our sampler state for our text texture/atlas |
74 SkASSERT(SkIsAlign4(fCurrVertex)); | 91 SkASSERT(SkIsAlign4(fCurrVertex)); |
75 SkASSERT(fCurrTexture); | 92 SkASSERT(fCurrTexture); |
76 GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kNon
e_FilterMode); | 93 GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kNon
e_FilterMode); |
77 | 94 |
78 // This effect could be stored with one of the cache objects (atlas?) | 95 // This effect could be stored with one of the cache objects (atlas?) |
| 96 int coordsIdx = drawState->hasColorVertexAttribute() ? kGlyphCoordsWithC
olorAttributeIndex : |
| 97 kGlyphCoordsNoCol
orAttributeIndex; |
79 drawState->addCoverageEffect( | 98 drawState->addCoverageEffect( |
80 GrCustomCoordsTextureEffect::Create(fCurrTexture
, params), | 99 GrCustomCoordsTextureEffect::Create(fCurrTexture
, params), |
81 kGlyphCoordsAttributeIndex)->unref(); | 100 coordsIdx)->unref(); |
82 | 101 SkASSERT(NULL != fStrike); |
83 if (NULL != fStrike && kARGB_GrMaskFormat == fStrike->getMaskFormat()) { | 102 switch (fStrike->getMaskFormat()) { |
84 drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlen
dCoeff()); | 103 // Color bitmap text |
85 drawState->setColor(0xffffffff); | 104 case kARGB_GrMaskFormat: |
86 } else if (!GrPixelConfigIsAlphaOnly(fCurrTexture->config())) { | 105 SkASSERT(!drawState->hasColorVertexAttribute()); |
87 if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() || | 106 drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDst
BlendCoeff()); |
88 kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() || | 107 drawState->setColor(0xffffffff); |
89 fPaint.numColorStages()) { | 108 break; |
90 GrPrintf("LCD Text will not draw correctly.\n"); | 109 // LCD text |
| 110 case kA888_GrMaskFormat: |
| 111 case kA565_GrMaskFormat: { |
| 112 if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() || |
| 113 kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() || |
| 114 fPaint.numColorStages()) { |
| 115 GrPrintf("LCD Text will not draw correctly.\n"); |
| 116 } |
| 117 SkASSERT(!drawState->hasColorVertexAttribute()); |
| 118 // We don't use the GrPaint's color in this case because it's be
en premultiplied by |
| 119 // alpha. Instead we feed in a non-premultiplied color, and mult
iply its alpha by |
| 120 // the mask texture color. The end result is that we get |
| 121 // mask*paintAlpha*paintColor + (1-mask*paintAlpha)*d
stColor |
| 122 int a = SkColorGetA(fSkPaint.getColor()); |
| 123 // paintAlpha |
| 124 drawState->setColor(SkColorSetARGB(a, a, a, a)); |
| 125 // paintColor |
| 126 drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSk
Paint.getColor())); |
| 127 drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff)
; |
| 128 break; |
91 } | 129 } |
92 // We don't use the GrPaint's color in this case because it's been p
remultiplied by | 130 // Grayscale/BW text |
93 // alpha. Instead we feed in a non-premultiplied color, and multiply
its alpha by | 131 case kA8_GrMaskFormat: |
94 // the mask texture color. The end result is that we get | 132 // set back to normal in case we took LCD path previously. |
95 // mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstCo
lor | 133 drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDst
BlendCoeff()); |
96 int a = SkColorGetA(fSkPaint.getColor()); | 134 //drawState->setColor(fPaint.getColor()); |
97 // paintAlpha | 135 // We're using per-vertex color. |
98 drawState->setColor(SkColorSetARGB(a, a, a, a)); | 136 SkASSERT(drawState->hasColorVertexAttribute()); |
99 // paintColor | 137 drawState->setColor(0xFFFFFFFF); |
100 drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSkPain
t.getColor())); | 138 break; |
101 drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff); | 139 default: |
102 } else { | 140 SkFAIL("Unexepected mask format."); |
103 // set back to normal in case we took LCD path previously. | |
104 drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlen
dCoeff()); | |
105 drawState->setColor(fPaint.getColor()); | |
106 } | 141 } |
107 | |
108 int nGlyphs = fCurrVertex / 4; | 142 int nGlyphs = fCurrVertex / 4; |
109 fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); | 143 fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); |
110 fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType, | 144 fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType, |
111 nGlyphs, | 145 nGlyphs, |
112 4, 6, &fVertexBounds); | 146 4, 6, &fVertexBounds); |
113 | 147 |
114 fDrawTarget->resetVertexSource(); | 148 fDrawTarget->resetVertexSource(); |
115 fVertices = NULL; | 149 fVertices = NULL; |
116 fMaxVertices = 0; | 150 fMaxVertices = 0; |
117 fCurrVertex = 0; | 151 fCurrVertex = 0; |
118 fVertexBounds.setLargestInverted(); | 152 fVertexBounds.setLargestInverted(); |
119 SkSafeSetNull(fCurrTexture); | 153 SkSafeSetNull(fCurrTexture); |
120 } | 154 } |
121 } | 155 } |
122 | 156 |
123 inline void GrBitmapTextContext::init(const GrPaint& paint, const SkPaint& skPai
nt) { | 157 inline void GrBitmapTextContext::init(const GrPaint& paint, const SkPaint& skPai
nt) { |
124 GrTextContext::init(paint, skPaint); | 158 GrTextContext::init(paint, skPaint); |
125 | 159 |
126 fStrike = NULL; | 160 fStrike = NULL; |
127 | 161 |
128 fCurrTexture = NULL; | 162 fCurrTexture = NULL; |
129 fCurrVertex = 0; | 163 fCurrVertex = 0; |
130 | 164 |
131 fVertices = NULL; | 165 fVertices = NULL; |
132 fMaxVertices = 0; | 166 fMaxVertices = 0; |
133 } | 167 } |
134 | 168 |
135 inline void GrBitmapTextContext::finish() { | 169 inline void GrBitmapTextContext::finish() { |
136 flushGlyphs(); | 170 this->flushGlyphs(); |
137 | 171 |
138 GrTextContext::finish(); | 172 GrTextContext::finish(); |
139 } | 173 } |
140 | 174 |
141 void GrBitmapTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint, | 175 void GrBitmapTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint, |
142 const char text[], size_t byteLength, | 176 const char text[], size_t byteLength, |
143 SkScalar x, SkScalar y) { | 177 SkScalar x, SkScalar y) { |
144 SkASSERT(byteLength == 0 || text != NULL); | 178 SkASSERT(byteLength == 0 || text != NULL); |
145 | 179 |
146 // nothing to draw | 180 // nothing to draw |
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
465 fontScaler); | 499 fontScaler); |
466 } | 500 } |
467 pos += scalarsPerPosition; | 501 pos += scalarsPerPosition; |
468 } | 502 } |
469 } | 503 } |
470 } | 504 } |
471 | 505 |
472 this->finish(); | 506 this->finish(); |
473 } | 507 } |
474 | 508 |
475 namespace { | |
476 | |
477 // position + texture coord | |
478 extern const GrVertexAttrib gTextVertexAttribs[] = { | |
479 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding
}, | |
480 {kVec2f_GrVertexAttribType, sizeof(SkPoint), kEffect_GrVertexAttribBinding} | |
481 }; | |
482 | |
483 }; | |
484 | |
485 void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed, | 509 void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed, |
486 SkFixed vx, SkFixed vy, | 510 SkFixed vx, SkFixed vy, |
487 GrFontScaler* scaler) { | 511 GrFontScaler* scaler) { |
488 if (NULL == fDrawTarget) { | 512 if (NULL == fDrawTarget) { |
489 return; | 513 return; |
490 } | 514 } |
491 | 515 |
492 if (NULL == fStrike) { | 516 if (NULL == fStrike) { |
493 fStrike = fContext->getFontCache()->getStrike(scaler, false); | 517 fStrike = fContext->getFontCache()->getStrike(scaler, false); |
494 } | 518 } |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
574 | 598 |
575 GrTexture* texture = glyph->fPlot->texture(); | 599 GrTexture* texture = glyph->fPlot->texture(); |
576 SkASSERT(texture); | 600 SkASSERT(texture); |
577 | 601 |
578 if (fCurrTexture != texture || fCurrVertex + 4 > fMaxVertices) { | 602 if (fCurrTexture != texture || fCurrVertex + 4 > fMaxVertices) { |
579 this->flushGlyphs(); | 603 this->flushGlyphs(); |
580 fCurrTexture = texture; | 604 fCurrTexture = texture; |
581 fCurrTexture->ref(); | 605 fCurrTexture->ref(); |
582 } | 606 } |
583 | 607 |
| 608 bool useColorVerts = kA8_GrMaskFormat == fStrike->getMaskFormat(); |
| 609 |
584 if (NULL == fVertices) { | 610 if (NULL == fVertices) { |
585 // If we need to reserve vertices allow the draw target to suggest | 611 // If we need to reserve vertices allow the draw target to suggest |
586 // a number of verts to reserve and whether to perform a flush. | 612 // a number of verts to reserve and whether to perform a flush. |
587 fMaxVertices = kMinRequestedVerts; | 613 fMaxVertices = kMinRequestedVerts; |
588 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>( | 614 if (useColorVerts) { |
589 SK_ARRAY_COUNT(gTextVertexAttribs)); | 615 fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttri
bs>( |
| 616 SK_ARRAY_COUNT(gTextVertexWithColorAttribs)); |
| 617 } else { |
| 618 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>( |
| 619 SK_ARRAY_COUNT(gTextVertexAttribs)); |
| 620 } |
590 bool flush = fDrawTarget->geometryHints(&fMaxVertices, NULL); | 621 bool flush = fDrawTarget->geometryHints(&fMaxVertices, NULL); |
591 if (flush) { | 622 if (flush) { |
592 this->flushGlyphs(); | 623 this->flushGlyphs(); |
593 fContext->flush(); | 624 fContext->flush(); |
594 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>( | 625 if (useColorVerts) { |
595 SK_ARRAY_COUNT(gTextVertexAttribs)); | 626 fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorA
ttribs>( |
| 627 SK_ARRAY_COUNT(gTextVertexWithColorAttribs)); |
| 628 } else { |
| 629 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>( |
| 630 SK_ARRAY_COUNT(gTextVertexAttribs)); |
| 631 } |
596 } | 632 } |
597 fMaxVertices = kDefaultRequestedVerts; | 633 fMaxVertices = kDefaultRequestedVerts; |
598 // ignore return, no point in flushing again. | 634 // ignore return, no point in flushing again. |
599 fDrawTarget->geometryHints(&fMaxVertices, NULL); | 635 fDrawTarget->geometryHints(&fMaxVertices, NULL); |
600 | 636 |
601 int maxQuadVertices = 4 * fContext->getQuadIndexBuffer()->maxQuads(); | 637 int maxQuadVertices = 4 * fContext->getQuadIndexBuffer()->maxQuads(); |
602 if (fMaxVertices < kMinRequestedVerts) { | 638 if (fMaxVertices < kMinRequestedVerts) { |
603 fMaxVertices = kDefaultRequestedVerts; | 639 fMaxVertices = kDefaultRequestedVerts; |
604 } else if (fMaxVertices > maxQuadVertices) { | 640 } else if (fMaxVertices > maxQuadVertices) { |
605 // don't exceed the limit of the index buffer | 641 // don't exceed the limit of the index buffer |
606 fMaxVertices = maxQuadVertices; | 642 fMaxVertices = maxQuadVertices; |
607 } | 643 } |
608 bool success = fDrawTarget->reserveVertexAndIndexSpace(fMaxVertices, | 644 bool success = fDrawTarget->reserveVertexAndIndexSpace(fMaxVertices, |
609 0, | 645 0, |
610 GrTCast<void**>(&
fVertices), | 646 &fVertices, |
611 NULL); | 647 NULL); |
612 GrAlwaysAssert(success); | 648 GrAlwaysAssert(success); |
613 SkASSERT(2*sizeof(SkPoint) == fDrawTarget->getDrawState().getVertexSize(
)); | |
614 } | 649 } |
615 | 650 |
616 SkFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX); | 651 SkFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX); |
617 SkFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY); | 652 SkFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY); |
618 | 653 |
619 SkRect r; | 654 SkRect r; |
620 r.fLeft = SkFixedToFloat(vx); | 655 r.fLeft = SkFixedToFloat(vx); |
621 r.fTop = SkFixedToFloat(vy); | 656 r.fTop = SkFixedToFloat(vy); |
622 r.fRight = SkFixedToFloat(vx + width); | 657 r.fRight = SkFixedToFloat(vx + width); |
623 r.fBottom = SkFixedToFloat(vy + height); | 658 r.fBottom = SkFixedToFloat(vy + height); |
624 | 659 |
625 fVertexBounds.growToInclude(r); | 660 fVertexBounds.growToInclude(r); |
626 | 661 |
627 fVertices[2*fCurrVertex].setRectFan(r.fLeft, r.fTop, r.fRight, r.fBottom, | 662 size_t vertSize = useColorVerts ? (2 * sizeof(SkPoint) + sizeof(GrColor)) : |
628 2 * sizeof(SkPoint)); | 663 (2 * sizeof(SkPoint)); |
629 fVertices[2*fCurrVertex+1].setRectFan(SkFixedToFloat(texture->normalizeFixed
X(tx)), | 664 |
630 SkFixedToFloat(texture->normalizeFixed
Y(ty)), | 665 SkASSERT(vertSize == fDrawTarget->getDrawState().getVertexSize()); |
631 SkFixedToFloat(texture->normalizeFixed
X(tx + width)), | 666 |
632 SkFixedToFloat(texture->normalizeFixed
Y(ty + height)), | 667 SkPoint* positions = reinterpret_cast<SkPoint*>( |
633 2 * sizeof(SkPoint)); | 668 reinterpret_cast<intptr_t>(fVertices) + vertSize * fCurrVertex); |
| 669 positions->setRectFan(r.fLeft, r.fTop, r.fRight, r.fBottom, vertSize); |
| 670 |
| 671 // The texture coords are last in both the with and without color vertex lay
outs. |
| 672 SkPoint* textureCoords = reinterpret_cast<SkPoint*>( |
| 673 reinterpret_cast<intptr_t>(positions) + vertSize - sizeof(SkPoint))
; |
| 674 textureCoords->setRectFan(SkFixedToFloat(texture->normalizeFixedX(tx)), |
| 675 SkFixedToFloat(texture->normalizeFixedY(ty)), |
| 676 SkFixedToFloat(texture->normalizeFixedX(tx + width
)), |
| 677 SkFixedToFloat(texture->normalizeFixedY(ty + heigh
t)), |
| 678 vertSize); |
| 679 if (useColorVerts) { |
| 680 // color comes after position. |
| 681 GrColor* colors = reinterpret_cast<GrColor*>(positions + 1); |
| 682 for (int i = 0; i < 4; ++i) { |
| 683 *colors = fPaint.getColor(); |
| 684 colors = reinterpret_cast<GrColor*>(reinterpret_cast<intptr_t>(colors
) + vertSize); |
| 685 } |
| 686 } |
634 fCurrVertex += 4; | 687 fCurrVertex += 4; |
635 } | 688 } |
OLD | NEW |