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 "GrDistanceFieldTextContext.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 "SkGlyphCache.h" |
12 #include "GrIndexBuffer.h" | 13 #include "GrIndexBuffer.h" |
13 #include "GrTextStrike.h" | 14 #include "GrTextStrike.h" |
14 #include "GrTextStrike_impl.h" | 15 #include "GrTextStrike_impl.h" |
15 #include "SkPath.h" | 16 #include "SkPath.h" |
16 #include "SkRTConf.h" | 17 #include "SkRTConf.h" |
17 #include "SkStrokeRec.h" | 18 #include "SkStrokeRec.h" |
18 #include "effects/GrDistanceFieldTextureEffect.h" | 19 #include "effects/GrDistanceFieldTextureEffect.h" |
19 | 20 |
20 static const int kGlyphCoordsAttributeIndex = 1; | 21 static const int kGlyphCoordsAttributeIndex = 1; |
21 | 22 |
| 23 static const int kBaseDFFontSize = 32; |
| 24 |
22 SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false, | 25 SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false, |
23 "Dump the contents of the font cache before every purge."); | 26 "Dump the contents of the font cache before every purge."); |
24 | 27 |
25 | |
26 GrDistanceFieldTextContext::GrDistanceFieldTextContext(GrContext* context, | 28 GrDistanceFieldTextContext::GrDistanceFieldTextContext(GrContext* context, |
27 const GrPaint& paint, | 29 const GrPaint& grPaint, |
28 SkColor color, | 30 const SkPaint& skPaint) |
29 SkScalar textRatio) | 31 : GrTextContext(context, gr
Paint), |
30 : GrTextContext(context, pa
int) | 32 fSkPaint(skPaint) { |
31 , fTextRatio(textRatio) { | |
32 fSkPaintColor = color; | |
33 | |
34 fStrike = NULL; | 33 fStrike = NULL; |
35 | 34 |
36 fCurrTexture = NULL; | 35 fCurrTexture = NULL; |
37 fCurrVertex = 0; | 36 fCurrVertex = 0; |
38 | 37 |
39 fVertices = NULL; | 38 fVertices = NULL; |
40 fMaxVertices = 0; | 39 fMaxVertices = 0; |
| 40 |
| 41 fTextRatio = fSkPaint.getTextSize()/kBaseDFFontSize; |
| 42 |
| 43 fSkPaint.setTextSize(SkIntToScalar(kBaseDFFontSize)); |
| 44 fSkPaint.setLCDRenderText(false); |
| 45 fSkPaint.setAutohinted(false); |
| 46 fSkPaint.setSubpixelText(false); |
41 } | 47 } |
42 | 48 |
43 GrDistanceFieldTextContext::~GrDistanceFieldTextContext() { | 49 GrDistanceFieldTextContext::~GrDistanceFieldTextContext() { |
44 this->flushGlyphs(); | 50 this->flushGlyphs(); |
45 } | 51 } |
46 | 52 |
47 static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) { | 53 static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) { |
48 unsigned r = SkColorGetR(c); | 54 unsigned r = SkColorGetR(c); |
49 unsigned g = SkColorGetG(c); | 55 unsigned g = SkColorGetG(c); |
50 unsigned b = SkColorGetB(c); | 56 unsigned b = SkColorGetB(c); |
(...skipping 23 matching lines...) Expand all Loading... |
74 if (!GrPixelConfigIsAlphaOnly(fCurrTexture->config())) { | 80 if (!GrPixelConfigIsAlphaOnly(fCurrTexture->config())) { |
75 if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() || | 81 if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() || |
76 kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() || | 82 kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() || |
77 fPaint.numColorStages()) { | 83 fPaint.numColorStages()) { |
78 GrPrintf("LCD Text will not draw correctly.\n"); | 84 GrPrintf("LCD Text will not draw correctly.\n"); |
79 } | 85 } |
80 // We don't use the GrPaint's color in this case because it's been p
remultiplied by | 86 // We don't use the GrPaint's color in this case because it's been p
remultiplied by |
81 // alpha. Instead we feed in a non-premultiplied color, and multiply
its alpha by | 87 // alpha. Instead we feed in a non-premultiplied color, and multiply
its alpha by |
82 // the mask texture color. The end result is that we get | 88 // the mask texture color. The end result is that we get |
83 // mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstCo
lor | 89 // mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstCo
lor |
84 int a = SkColorGetA(fSkPaintColor); | 90 int a = SkColorGetA(fSkPaint.getColor()); |
85 // paintAlpha | 91 // paintAlpha |
86 drawState->setColor(SkColorSetARGB(a, a, a, a)); | 92 drawState->setColor(SkColorSetARGB(a, a, a, a)); |
87 // paintColor | 93 // paintColor |
88 drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSkPain
tColor)); | 94 drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSkPain
t.getColor())); |
89 drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff); | 95 drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff); |
90 } else { | 96 } else { |
91 // set back to normal in case we took LCD path previously. | 97 // set back to normal in case we took LCD path previously. |
92 drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlen
dCoeff()); | 98 drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlen
dCoeff()); |
93 drawState->setColor(fPaint.getColor()); | 99 drawState->setColor(fPaint.getColor()); |
94 } | 100 } |
95 | 101 |
96 int nGlyphs = fCurrVertex / 4; | 102 int nGlyphs = fCurrVertex / 4; |
97 fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); | 103 fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); |
98 fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType, | 104 fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType, |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
269 sx + width, | 275 sx + width, |
270 sy + height, | 276 sy + height, |
271 2 * sizeof(SkPoint)); | 277 2 * sizeof(SkPoint)); |
272 fVertices[2*fCurrVertex+1].setRectFan(SkFixedToFloat(texture->normalizeFixed
X(tx)), | 278 fVertices[2*fCurrVertex+1].setRectFan(SkFixedToFloat(texture->normalizeFixed
X(tx)), |
273 SkFixedToFloat(texture->normalizeFixed
Y(ty)), | 279 SkFixedToFloat(texture->normalizeFixed
Y(ty)), |
274 SkFixedToFloat(texture->normalizeFixed
X(tx + tw)), | 280 SkFixedToFloat(texture->normalizeFixed
X(tx + tw)), |
275 SkFixedToFloat(texture->normalizeFixed
Y(ty + th)), | 281 SkFixedToFloat(texture->normalizeFixed
Y(ty + th)), |
276 2 * sizeof(SkPoint)); | 282 2 * sizeof(SkPoint)); |
277 fCurrVertex += 4; | 283 fCurrVertex += 4; |
278 } | 284 } |
| 285 |
| 286 void GrDistanceFieldTextContext::drawText(const char text[], size_t byteLength, |
| 287 SkScalar x, SkScalar y, SkGlyphCache*
cache, |
| 288 GrFontScaler* fontScaler) { |
| 289 SkASSERT(byteLength == 0 || text != NULL); |
| 290 |
| 291 // nothing to draw |
| 292 if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/)
{ |
| 293 return; |
| 294 } |
| 295 |
| 296 SkScalar sizeRatio = fTextRatio; |
| 297 |
| 298 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); |
| 299 |
| 300 // need to measure first |
| 301 // TODO - generate positions and pre-load cache as well? |
| 302 const char* stop = text + byteLength; |
| 303 if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) { |
| 304 SkFixed stopX = 0; |
| 305 SkFixed stopY = 0; |
| 306 |
| 307 const char* textPtr = text; |
| 308 while (textPtr < stop) { |
| 309 // don't need x, y here, since all subpixel variants will have the |
| 310 // same advance |
| 311 const SkGlyph& glyph = glyphCacheProc(cache, &textPtr, 0, 0); |
| 312 |
| 313 stopX += glyph.fAdvanceX; |
| 314 stopY += glyph.fAdvanceY; |
| 315 } |
| 316 SkASSERT(textPtr == stop); |
| 317 |
| 318 SkScalar alignX = SkFixedToScalar(stopX)*sizeRatio; |
| 319 SkScalar alignY = SkFixedToScalar(stopY)*sizeRatio; |
| 320 |
| 321 if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) { |
| 322 alignX = SkScalarHalf(alignX); |
| 323 alignY = SkScalarHalf(alignY); |
| 324 } |
| 325 |
| 326 x -= alignX; |
| 327 y -= alignY; |
| 328 } |
| 329 |
| 330 SkFixed fx = SkScalarToFixed(x) + SK_FixedHalf; |
| 331 SkFixed fy = SkScalarToFixed(y) + SK_FixedHalf; |
| 332 SkFixed fixedScale = SkScalarToFixed(sizeRatio); |
| 333 while (text < stop) { |
| 334 const SkGlyph& glyph = glyphCacheProc(cache, &text, fx, fy); |
| 335 |
| 336 if (glyph.fWidth) { |
| 337 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(), |
| 338 glyph.getSubXFixed(), |
| 339 glyph.getSubYFixed()), |
| 340 SkFixedFloorToFixed(fx), |
| 341 SkFixedFloorToFixed(fy), |
| 342 fontScaler); |
| 343 } |
| 344 |
| 345 fx += SkFixedMul_portable(glyph.fAdvanceX, fixedScale); |
| 346 fy += SkFixedMul_portable(glyph.fAdvanceY, fixedScale); |
| 347 } |
| 348 } |
| 349 |
| 350 void GrDistanceFieldTextContext::drawPosText(const char text[], size_t byteLengt
h, |
| 351 const SkScalar pos[], SkScalar cons
tY, |
| 352 int scalarsPerPosition, |
| 353 SkGlyphCache* cache, GrFontScaler*
fontScaler) { |
| 354 |
| 355 SkASSERT(byteLength == 0 || text != NULL); |
| 356 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); |
| 357 |
| 358 // nothing to draw |
| 359 if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/)
{ |
| 360 return; |
| 361 } |
| 362 |
| 363 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); |
| 364 |
| 365 const char* stop = text + byteLength; |
| 366 |
| 367 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) { |
| 368 while (text < stop) { |
| 369 // the last 2 parameters are ignored |
| 370 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); |
| 371 |
| 372 if (glyph.fWidth) { |
| 373 SkScalar x = pos[0]; |
| 374 SkScalar y = scalarsPerPosition == 1 ? constY : pos[1]; |
| 375 |
| 376 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(), |
| 377 glyph.getSubXFixed(), |
| 378 glyph.getSubYFixed()), |
| 379 SkScalarToFixed(x) + SK_FixedHalf, //d1g.f
HalfSampleX, |
| 380 SkScalarToFixed(y) + SK_FixedHalf, //d1g.f
HalfSampleY, |
| 381 fontScaler); |
| 382 } |
| 383 pos += scalarsPerPosition; |
| 384 } |
| 385 } else { |
| 386 int alignShift = SkPaint::kCenter_Align == fSkPaint.getTextAlign() ? 1 :
0; |
| 387 while (text < stop) { |
| 388 // the last 2 parameters are ignored |
| 389 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); |
| 390 |
| 391 if (glyph.fWidth) { |
| 392 SkScalar x = pos[0]; |
| 393 SkScalar y = scalarsPerPosition == 1 ? constY : pos[1]; |
| 394 |
| 395 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(), |
| 396 glyph.getSubXFixed(), |
| 397 glyph.getSubYFixed()), |
| 398 SkScalarToFixed(x) - (glyph.fAdvanceX >> a
lignShift) |
| 399 + SK_FixedHalf, //d1g.fHalfSampleX, |
| 400 SkScalarToFixed(y) - (glyph.fAdvanceY >> a
lignShift) |
| 401 + SK_FixedHalf, //d1g.fHalfSampleY, |
| 402 fontScaler); |
| 403 } |
| 404 pos += scalarsPerPosition; |
| 405 } |
| 406 } |
| 407 } |
| 408 |
OLD | NEW |