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 "GrDistanceFieldTextContext.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 "SkPath.h" | 15 #include "SkPath.h" |
16 #include "SkRTConf.h" | 16 #include "SkRTConf.h" |
17 #include "SkStrokeRec.h" | 17 #include "SkStrokeRec.h" |
18 #include "effects/GrCustomCoordsTextureEffect.h" | 18 #include "effects/GrDistanceFieldTextureEffect.h" |
19 | 19 |
20 static const int kGlyphCoordsAttributeIndex = 1; | 20 static const int kGlyphCoordsAttributeIndex = 1; |
21 | 21 |
22 SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false, | 22 SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false, |
23 "Dump the contents of the font cache before every purge."); | 23 "Dump the contents of the font cache before every purge."); |
24 | 24 |
25 GrBitmapTextContext::GrBitmapTextContext(GrContext* context, const GrPaint& pain
t) : | |
26 GrTextContext(context, paint) { | |
27 fAutoMatrix.setIdentity(fContext, &fPaint); | |
28 | 25 |
| 26 GrDistanceFieldTextContext::GrDistanceFieldTextContext(GrContext* context, |
| 27 const GrPaint& paint, |
| 28 SkScalar textSize) : |
| 29 GrTextContext(context, paint), |
| 30 fTextSize(textSize) { |
29 fStrike = NULL; | 31 fStrike = NULL; |
30 | 32 |
31 fCurrTexture = NULL; | 33 fCurrTexture = NULL; |
32 fCurrVertex = 0; | 34 fCurrVertex = 0; |
33 | 35 |
34 fVertices = NULL; | 36 fVertices = NULL; |
35 fMaxVertices = 0; | 37 fMaxVertices = 0; |
36 } | 38 } |
37 | 39 |
38 GrBitmapTextContext::~GrBitmapTextContext() { | 40 GrDistanceFieldTextContext::~GrDistanceFieldTextContext() { |
39 this->flushGlyphs(); | 41 this->flushGlyphs(); |
40 } | 42 } |
41 | 43 |
42 void GrBitmapTextContext::flushGlyphs() { | 44 void GrDistanceFieldTextContext::flushGlyphs() { |
43 if (NULL == fDrawTarget) { | 45 if (NULL == fDrawTarget) { |
44 return; | 46 return; |
45 } | 47 } |
46 | 48 |
47 GrDrawState* drawState = fDrawTarget->drawState(); | 49 GrDrawState* drawState = fDrawTarget->drawState(); |
48 GrDrawState::AutoRestoreEffects are(drawState); | 50 GrDrawState::AutoRestoreEffects are(drawState); |
49 drawState->setFromPaint(fPaint, SkMatrix::I(), fContext->getRenderTarget()); | 51 SkMatrix transform; |
| 52 transform.reset(); |
| 53 transform = fContext->getMatrix(); |
| 54 drawState->setFromPaint(fPaint, transform, fContext->getRenderTarget()); |
50 | 55 |
51 if (fCurrVertex > 0) { | 56 if (fCurrVertex > 0) { |
52 // setup our sampler state for our text texture/atlas | 57 // setup our sampler state for our text texture/atlas |
53 SkASSERT(GrIsALIGN4(fCurrVertex)); | 58 SkASSERT(GrIsALIGN4(fCurrVertex)); |
54 SkASSERT(fCurrTexture); | 59 SkASSERT(fCurrTexture); |
55 GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kNon
e_FilterMode); | 60 GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kBil
erp_FilterMode); |
56 | 61 |
57 // This effect could be stored with one of the cache objects (atlas?) | 62 // This effect could be stored with one of the cache objects (atlas?) |
58 drawState->addCoverageEffect( | 63 drawState->addCoverageEffect( |
59 GrCustomCoordsTextureEffect::Create(fCurrTexture
, params), | 64 GrDistanceFieldTextureEffect::Create(fCurrTextur
e, params), |
60 kGlyphCoordsAttributeIndex)->unref(); | 65 kGlyphCoordsAttributeIndex)->unref(); |
61 | 66 |
62 if (!GrPixelConfigIsAlphaOnly(fCurrTexture->config())) { | 67 if (!GrPixelConfigIsAlphaOnly(fCurrTexture->config())) { |
63 if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() || | 68 if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() || |
64 kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() || | 69 kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() || |
65 fPaint.numColorStages()) { | 70 fPaint.numColorStages()) { |
66 GrPrintf("LCD Text will not draw correctly.\n"); | 71 GrPrintf("LCD Text will not draw correctly.\n"); |
67 } | 72 } |
68 // setup blend so that we get mask * paintColor + (1-mask)*dstColor | 73 // setup blend so that we get mask * paintColor + (1-mask)*dstColor |
69 drawState->setBlendConstant(fPaint.getColor()); | 74 drawState->setBlendConstant(fPaint.getColor()); |
(...skipping 23 matching lines...) Expand all Loading... |
93 namespace { | 98 namespace { |
94 | 99 |
95 // position + texture coord | 100 // position + texture coord |
96 extern const GrVertexAttrib gTextVertexAttribs[] = { | 101 extern const GrVertexAttrib gTextVertexAttribs[] = { |
97 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding
}, | 102 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding
}, |
98 {kVec2f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding} | 103 {kVec2f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding} |
99 }; | 104 }; |
100 | 105 |
101 }; | 106 }; |
102 | 107 |
103 void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed, | 108 void GrDistanceFieldTextContext::drawPackedGlyph(GrGlyph::PackedID packed, |
104 GrFixed vx, GrFixed vy, | 109 GrFixed vx, GrFixed vy, |
105 GrFontScaler* scaler) { | 110 GrFontScaler* scaler) { |
106 if (NULL == fDrawTarget) { | 111 if (NULL == fDrawTarget) { |
107 return; | 112 return; |
108 } | 113 } |
109 if (NULL == fStrike) { | 114 if (NULL == fStrike) { |
110 fStrike = fContext->getFontCache()->getStrike(scaler); | 115 fStrike = fContext->getFontCache()->getStrike(scaler, true); |
111 } | 116 } |
112 | 117 |
113 GrGlyph* glyph = fStrike->getGlyph(packed, scaler); | 118 GrGlyph* glyph = fStrike->getGlyph(packed, scaler); |
114 if (NULL == glyph || glyph->fBounds.isEmpty()) { | 119 if (NULL == glyph || glyph->fBounds.isEmpty()) { |
115 return; | 120 return; |
116 } | 121 } |
117 | 122 |
| 123 SkScalar sx = SkFixedToScalar(vx); |
| 124 SkScalar sy = SkFixedToScalar(vy); |
| 125 /* |
| 126 // not valid, need to find a different solution for this |
118 vx += SkIntToFixed(glyph->fBounds.fLeft); | 127 vx += SkIntToFixed(glyph->fBounds.fLeft); |
119 vy += SkIntToFixed(glyph->fBounds.fTop); | 128 vy += SkIntToFixed(glyph->fBounds.fTop); |
120 | 129 |
121 // keep them as ints until we've done the clip-test | 130 // keep them as ints until we've done the clip-test |
122 GrFixed width = glyph->fBounds.width(); | 131 GrFixed width = glyph->fBounds.width(); |
123 GrFixed height = glyph->fBounds.height(); | 132 GrFixed height = glyph->fBounds.height(); |
124 | 133 |
125 // check if we clipped out | 134 // check if we clipped out |
126 if (true || NULL == glyph->fPlot) { | 135 if (true || NULL == glyph->fPlot) { |
127 int x = vx >> 16; | 136 int x = vx >> 16; |
128 int y = vy >> 16; | 137 int y = vy >> 16; |
129 if (fClipRect.quickReject(x, y, x + width, y + height)) { | 138 if (fClipRect.quickReject(x, y, x + width, y + height)) { |
130 // SkCLZ(3); // so we can set a break-point in the debugger | 139 // SkCLZ(3); // so we can set a break-point in the debugger |
131 return; | 140 return; |
132 } | 141 } |
133 } | 142 } |
134 | 143 */ |
135 if (NULL == glyph->fPlot) { | 144 if (NULL == glyph->fPlot) { |
136 if (fStrike->getGlyphAtlas(glyph, scaler)) { | 145 if (fStrike->getGlyphAtlas(glyph, scaler)) { |
137 goto HAS_ATLAS; | 146 goto HAS_ATLAS; |
138 } | 147 } |
139 | 148 |
140 // try to clear out an unused plot before we flush | 149 // try to clear out an unused plot before we flush |
141 fContext->getFontCache()->freePlotExceptFor(fStrike); | 150 fContext->getFontCache()->freePlotExceptFor(fStrike); |
142 if (fStrike->getGlyphAtlas(glyph, scaler)) { | 151 if (fStrike->getGlyphAtlas(glyph, scaler)) { |
143 goto HAS_ATLAS; | 152 goto HAS_ATLAS; |
144 } | 153 } |
(...skipping 20 matching lines...) Expand all Loading... |
165 if (!scaler->getGlyphPath(glyph->glyphID(), path)) { | 174 if (!scaler->getGlyphPath(glyph->glyphID(), path)) { |
166 // flag the glyph as being dead? | 175 // flag the glyph as being dead? |
167 delete path; | 176 delete path; |
168 return; | 177 return; |
169 } | 178 } |
170 glyph->fPath = path; | 179 glyph->fPath = path; |
171 } | 180 } |
172 | 181 |
173 GrContext::AutoMatrix am; | 182 GrContext::AutoMatrix am; |
174 SkMatrix translate; | 183 SkMatrix translate; |
175 translate.setTranslate(SkFixedToScalar(vx - SkIntToFixed(glyph->fBounds.
fLeft)), | 184 translate.setTranslate(sx, sy); |
176 SkFixedToScalar(vy - SkIntToFixed(glyph->fBounds.
fTop))); | |
177 GrPaint tmpPaint(fPaint); | 185 GrPaint tmpPaint(fPaint); |
178 am.setPreConcat(fContext, translate, &tmpPaint); | 186 am.setPreConcat(fContext, translate, &tmpPaint); |
179 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); | 187 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); |
180 fContext->drawPath(tmpPaint, *glyph->fPath, stroke); | 188 fContext->drawPath(tmpPaint, *glyph->fPath, stroke); |
181 return; | 189 return; |
182 } | 190 } |
183 | 191 |
184 HAS_ATLAS: | 192 HAS_ATLAS: |
185 SkASSERT(glyph->fPlot); | 193 SkASSERT(glyph->fPlot); |
186 GrDrawTarget::DrawToken drawToken = fDrawTarget->getCurrentDrawToken(); | 194 GrDrawTarget::DrawToken drawToken = fDrawTarget->getCurrentDrawToken(); |
187 glyph->fPlot->setDrawToken(drawToken); | 195 glyph->fPlot->setDrawToken(drawToken); |
188 | 196 |
189 // now promote them to fixed (TODO: Rethink using fixed pt). | |
190 width = SkIntToFixed(width); | |
191 height = SkIntToFixed(height); | |
192 | |
193 GrTexture* texture = glyph->fPlot->texture(); | 197 GrTexture* texture = glyph->fPlot->texture(); |
194 SkASSERT(texture); | 198 SkASSERT(texture); |
195 | 199 |
196 if (fCurrTexture != texture || fCurrVertex + 4 > fMaxVertices) { | 200 if (fCurrTexture != texture || fCurrVertex + 4 > fMaxVertices) { |
197 this->flushGlyphs(); | 201 this->flushGlyphs(); |
198 fCurrTexture = texture; | 202 fCurrTexture = texture; |
199 fCurrTexture->ref(); | 203 fCurrTexture->ref(); |
200 } | 204 } |
201 | 205 |
202 if (NULL == fVertices) { | 206 if (NULL == fVertices) { |
(...skipping 21 matching lines...) Expand all Loading... |
224 fMaxVertices = maxQuadVertices; | 228 fMaxVertices = maxQuadVertices; |
225 } | 229 } |
226 bool success = fDrawTarget->reserveVertexAndIndexSpace(fMaxVertices, | 230 bool success = fDrawTarget->reserveVertexAndIndexSpace(fMaxVertices, |
227 0, | 231 0, |
228 GrTCast<void**>(&
fVertices), | 232 GrTCast<void**>(&
fVertices), |
229 NULL); | 233 NULL); |
230 GrAlwaysAssert(success); | 234 GrAlwaysAssert(success); |
231 SkASSERT(2*sizeof(GrPoint) == fDrawTarget->getDrawState().getVertexSize(
)); | 235 SkASSERT(2*sizeof(GrPoint) == fDrawTarget->getDrawState().getVertexSize(
)); |
232 } | 236 } |
233 | 237 |
| 238 SkScalar dx = SkIntToScalar(glyph->fBounds.fLeft); |
| 239 SkScalar dy = SkIntToScalar(glyph->fBounds.fTop); |
| 240 SkScalar width = SkIntToScalar(glyph->fBounds.width()); |
| 241 SkScalar height = SkIntToScalar(glyph->fBounds.height()); |
| 242 |
| 243 SkScalar scale = fTextSize/32.f; |
| 244 dx *= scale; |
| 245 dy *= scale; |
| 246 sx += dx; |
| 247 sy += dy; |
| 248 width *= scale; |
| 249 height *= scale; |
| 250 |
234 GrFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX); | 251 GrFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX); |
235 GrFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY); | 252 GrFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY); |
| 253 GrFixed tw = SkIntToFixed(glyph->fBounds.width()); |
| 254 GrFixed th = SkIntToFixed(glyph->fBounds.height()); |
236 | 255 |
237 fVertices[2*fCurrVertex].setRectFan(SkFixedToFloat(vx), | 256 fVertices[2*fCurrVertex].setRectFan(sx, |
238 SkFixedToFloat(vy), | 257 sy, |
239 SkFixedToFloat(vx + width), | 258 sx + width, |
240 SkFixedToFloat(vy + height), | 259 sy + height, |
241 2 * sizeof(SkPoint)); | 260 2 * sizeof(SkPoint)); |
242 fVertices[2*fCurrVertex+1].setRectFan(SkFixedToFloat(texture->normalizeFixed
X(tx)), | 261 fVertices[2*fCurrVertex+1].setRectFan(SkFixedToScalar(texture->normalizeFixe
dX(tx)), |
243 SkFixedToFloat(texture->normalizeFixed
Y(ty)), | 262 SkFixedToScalar(texture->normalizeFixe
dY(ty)), |
244 SkFixedToFloat(texture->normalizeFixed
X(tx + width)), | 263 SkFixedToScalar(texture->normalizeFixe
dX(tx + tw)), |
245 SkFixedToFloat(texture->normalizeFixed
Y(ty + height)), | 264 SkFixedToScalar(texture->normalizeFixe
dY(ty + th)), |
246 2 * sizeof(SkPoint)); | 265 2 * sizeof(SkPoint)); |
247 fCurrVertex += 4; | 266 fCurrVertex += 4; |
248 } | 267 } |
OLD | NEW |