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 "SkColorFilter.h" | 10 #include "SkColorFilter.h" |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
45 #else | 45 #else |
46 fEnableDFRendering = enable; | 46 fEnableDFRendering = enable; |
47 #endif | 47 #endif |
48 fStrike = NULL; | 48 fStrike = NULL; |
49 fGammaTexture = NULL; | 49 fGammaTexture = NULL; |
50 | 50 |
51 fCurrTexture = NULL; | 51 fCurrTexture = NULL; |
52 fCurrVertex = 0; | 52 fCurrVertex = 0; |
53 | 53 |
54 fVertices = NULL; | 54 fVertices = NULL; |
| 55 fMaxVertices = 0; |
55 } | 56 } |
56 | 57 |
57 GrDistanceFieldTextContext::~GrDistanceFieldTextContext() { | 58 GrDistanceFieldTextContext::~GrDistanceFieldTextContext() { |
58 this->flushGlyphs(); | 59 this->flushGlyphs(); |
59 SkSafeSetNull(fGammaTexture); | 60 SkSafeSetNull(fGammaTexture); |
60 } | 61 } |
61 | 62 |
62 bool GrDistanceFieldTextContext::canDraw(const SkPaint& paint) { | 63 bool GrDistanceFieldTextContext::canDraw(const SkPaint& paint) { |
63 if (!fEnableDFRendering && !paint.isDistanceFieldTextTEMP()) { | 64 if (!fEnableDFRendering && !paint.isDistanceFieldTextTEMP()) { |
64 return false; | 65 return false; |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 drawState->setColor(fPaint.getColor()); | 171 drawState->setColor(fPaint.getColor()); |
171 } | 172 } |
172 | 173 |
173 int nGlyphs = fCurrVertex / 4; | 174 int nGlyphs = fCurrVertex / 4; |
174 fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); | 175 fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); |
175 fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType, | 176 fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType, |
176 nGlyphs, | 177 nGlyphs, |
177 4, 6); | 178 4, 6); |
178 fDrawTarget->resetVertexSource(); | 179 fDrawTarget->resetVertexSource(); |
179 fVertices = NULL; | 180 fVertices = NULL; |
| 181 fMaxVertices = 0; |
180 fCurrVertex = 0; | 182 fCurrVertex = 0; |
181 SkSafeSetNull(fCurrTexture); | 183 SkSafeSetNull(fCurrTexture); |
182 } | 184 } |
183 } | 185 } |
184 | 186 |
185 namespace { | 187 namespace { |
186 | 188 |
187 // position + texture coord | 189 // position + texture coord |
188 extern const GrVertexAttrib gTextVertexAttribs[] = { | 190 extern const GrVertexAttrib gTextVertexAttribs[] = { |
189 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding
}, | 191 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding
}, |
190 {kVec2f_GrVertexAttribType, sizeof(SkPoint), kEffect_GrVertexAttribBinding} | 192 {kVec2f_GrVertexAttribType, sizeof(SkPoint), kEffect_GrVertexAttribBinding} |
191 }; | 193 }; |
192 | 194 |
193 }; | 195 }; |
194 | 196 |
195 void GrDistanceFieldTextContext::drawPackedGlyph(GrGlyph::PackedID packed, | 197 void GrDistanceFieldTextContext::drawPackedGlyph(GrGlyph::PackedID packed, |
196 SkFixed vx, SkFixed vy, | 198 SkFixed vx, SkFixed vy, |
197 GrFontScaler* scaler) { | 199 GrFontScaler* scaler) { |
| 200 if (NULL == fDrawTarget) { |
| 201 return; |
| 202 } |
| 203 if (NULL == fStrike) { |
| 204 fStrike = fContext->getFontCache()->getStrike(scaler, true); |
| 205 } |
| 206 |
198 GrGlyph* glyph = fStrike->getGlyph(packed, scaler); | 207 GrGlyph* glyph = fStrike->getGlyph(packed, scaler); |
199 if (NULL == glyph || glyph->fBounds.isEmpty()) { | 208 if (NULL == glyph || glyph->fBounds.isEmpty()) { |
200 return; | 209 return; |
201 } | 210 } |
202 | 211 |
203 SkScalar sx = SkFixedToScalar(vx); | 212 SkScalar sx = SkFixedToScalar(vx); |
204 SkScalar sy = SkFixedToScalar(vy); | 213 SkScalar sy = SkFixedToScalar(vy); |
205 /* | 214 /* |
206 // not valid, need to find a different solution for this | 215 // not valid, need to find a different solution for this |
207 vx += SkIntToFixed(glyph->fBounds.fLeft); | 216 vx += SkIntToFixed(glyph->fBounds.fLeft); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 } | 279 } |
271 | 280 |
272 HAS_ATLAS: | 281 HAS_ATLAS: |
273 SkASSERT(glyph->fPlot); | 282 SkASSERT(glyph->fPlot); |
274 GrDrawTarget::DrawToken drawToken = fDrawTarget->getCurrentDrawToken(); | 283 GrDrawTarget::DrawToken drawToken = fDrawTarget->getCurrentDrawToken(); |
275 glyph->fPlot->setDrawToken(drawToken); | 284 glyph->fPlot->setDrawToken(drawToken); |
276 | 285 |
277 GrTexture* texture = glyph->fPlot->texture(); | 286 GrTexture* texture = glyph->fPlot->texture(); |
278 SkASSERT(texture); | 287 SkASSERT(texture); |
279 | 288 |
280 if (fCurrTexture != texture) { | 289 if (fCurrTexture != texture || fCurrVertex + 4 > fMaxVertices) { |
281 this->flushGlyphs(); | 290 this->flushGlyphs(); |
282 fCurrTexture = texture; | 291 fCurrTexture = texture; |
283 fCurrTexture->ref(); | 292 fCurrTexture->ref(); |
284 } | 293 } |
285 | 294 |
| 295 if (NULL == fVertices) { |
| 296 // If we need to reserve vertices allow the draw target to suggest |
| 297 // a number of verts to reserve and whether to perform a flush. |
| 298 fMaxVertices = kMinRequestedVerts; |
| 299 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>( |
| 300 SK_ARRAY_COUNT(gTextVertexAttribs)); |
| 301 bool flush = fDrawTarget->geometryHints(&fMaxVertices, NULL); |
| 302 if (flush) { |
| 303 this->flushGlyphs(); |
| 304 fContext->flush(); |
| 305 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>( |
| 306 SK_ARRAY_COUNT(gTextVertexAttribs)); |
| 307 } |
| 308 fMaxVertices = kDefaultRequestedVerts; |
| 309 // ignore return, no point in flushing again. |
| 310 fDrawTarget->geometryHints(&fMaxVertices, NULL); |
| 311 |
| 312 int maxQuadVertices = 4 * fContext->getQuadIndexBuffer()->maxQuads(); |
| 313 if (fMaxVertices < kMinRequestedVerts) { |
| 314 fMaxVertices = kDefaultRequestedVerts; |
| 315 } else if (fMaxVertices > maxQuadVertices) { |
| 316 // don't exceed the limit of the index buffer |
| 317 fMaxVertices = maxQuadVertices; |
| 318 } |
| 319 bool success = fDrawTarget->reserveVertexAndIndexSpace(fMaxVertices, |
| 320 0, |
| 321 GrTCast<void**>(&
fVertices), |
| 322 NULL); |
| 323 GrAlwaysAssert(success); |
| 324 SkASSERT(2*sizeof(SkPoint) == fDrawTarget->getDrawState().getVertexSize(
)); |
| 325 } |
| 326 |
286 SkScalar dx = SkIntToScalar(glyph->fBounds.fLeft + SK_DistanceFieldInset); | 327 SkScalar dx = SkIntToScalar(glyph->fBounds.fLeft + SK_DistanceFieldInset); |
287 SkScalar dy = SkIntToScalar(glyph->fBounds.fTop + SK_DistanceFieldInset); | 328 SkScalar dy = SkIntToScalar(glyph->fBounds.fTop + SK_DistanceFieldInset); |
288 SkScalar width = SkIntToScalar(glyph->fBounds.width() - 2*SK_DistanceFieldIn
set); | 329 SkScalar width = SkIntToScalar(glyph->fBounds.width() - 2*SK_DistanceFieldIn
set); |
289 SkScalar height = SkIntToScalar(glyph->fBounds.height() - 2*SK_DistanceField
Inset); | 330 SkScalar height = SkIntToScalar(glyph->fBounds.height() - 2*SK_DistanceField
Inset); |
290 | 331 |
291 SkScalar scale = fTextRatio; | 332 SkScalar scale = fTextRatio; |
292 dx *= scale; | 333 dx *= scale; |
293 dy *= scale; | 334 dy *= scale; |
294 sx += dx; | 335 sx += dx; |
295 sy += dy; | 336 sy += dy; |
296 width *= scale; | 337 width *= scale; |
297 height *= scale; | 338 height *= scale; |
298 | 339 |
299 SkFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX + SK_DistanceFieldInset); | 340 SkFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX + SK_DistanceFieldInset); |
300 SkFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY + SK_DistanceFieldInset); | 341 SkFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY + SK_DistanceFieldInset); |
301 SkFixed tw = SkIntToFixed(glyph->fBounds.width() - 2*SK_DistanceFieldInset); | 342 SkFixed tw = SkIntToFixed(glyph->fBounds.width() - 2*SK_DistanceFieldInset); |
302 SkFixed th = SkIntToFixed(glyph->fBounds.height() - 2*SK_DistanceFieldInset)
; | 343 SkFixed th = SkIntToFixed(glyph->fBounds.height() - 2*SK_DistanceFieldInset)
; |
303 | 344 |
304 static const size_t kVertexSize = 2 * sizeof(SkPoint); | 345 static const size_t kVertexSize = 2 * sizeof(SkPoint); |
305 SkPoint* positions = reinterpret_cast<SkPoint*>( | 346 fVertices[2*fCurrVertex].setRectFan(sx, |
306 reinterpret_cast<intptr_t>(fVertices) + kVertexS
ize * fCurrVertex); | 347 sy, |
307 positions->setRectFan(sx, | 348 sx + width, |
308 sy, | 349 sy + height, |
309 sx + width, | 350 kVertexSize); |
310 sy + height, | 351 fVertices[2*fCurrVertex+1].setRectFan(SkFixedToFloat(texture->normalizeFixed
X(tx)), |
311 kVertexSize); | |
312 SkPoint* textureCoords = reinterpret_cast<SkPoint*>( | |
313 reinterpret_cast<intptr_t>(positions) + kVertexSize
- sizeof(SkPoint)); | |
314 textureCoords->setRectFan(SkFixedToFloat(texture->normalizeFixedX(tx)), | |
315 SkFixedToFloat(texture->normalizeFixed
Y(ty)), | 352 SkFixedToFloat(texture->normalizeFixed
Y(ty)), |
316 SkFixedToFloat(texture->normalizeFixed
X(tx + tw)), | 353 SkFixedToFloat(texture->normalizeFixed
X(tx + tw)), |
317 SkFixedToFloat(texture->normalizeFixed
Y(ty + th)), | 354 SkFixedToFloat(texture->normalizeFixed
Y(ty + th)), |
318 kVertexSize); | 355 kVertexSize); |
319 fCurrVertex += 4; | 356 fCurrVertex += 4; |
320 } | 357 } |
321 | 358 |
322 inline void GrDistanceFieldTextContext::init(const GrPaint& paint, const SkPaint
& skPaint) { | 359 inline void GrDistanceFieldTextContext::init(const GrPaint& paint, const SkPaint
& skPaint) { |
323 GrTextContext::init(paint, skPaint); | 360 GrTextContext::init(paint, skPaint); |
324 | 361 |
325 fStrike = NULL; | 362 fStrike = NULL; |
326 | 363 |
327 fCurrTexture = NULL; | 364 fCurrTexture = NULL; |
328 fCurrVertex = 0; | 365 fCurrVertex = 0; |
329 | 366 |
330 fVertices = NULL; | 367 fVertices = NULL; |
| 368 fMaxVertices = 0; |
331 | 369 |
332 if (fSkPaint.getTextSize() <= kSmallDFFontLimit) { | 370 if (fSkPaint.getTextSize() <= kSmallDFFontLimit) { |
333 fTextRatio = fSkPaint.getTextSize()/kSmallDFFontSize; | 371 fTextRatio = fSkPaint.getTextSize()/kSmallDFFontSize; |
334 fSkPaint.setTextSize(SkIntToScalar(kSmallDFFontSize)); | 372 fSkPaint.setTextSize(SkIntToScalar(kSmallDFFontSize)); |
335 } else if (fSkPaint.getTextSize() <= kMediumDFFontLimit) { | 373 } else if (fSkPaint.getTextSize() <= kMediumDFFontLimit) { |
336 fTextRatio = fSkPaint.getTextSize()/kMediumDFFontSize; | 374 fTextRatio = fSkPaint.getTextSize()/kMediumDFFontSize; |
337 fSkPaint.setTextSize(SkIntToScalar(kMediumDFFontSize)); | 375 fSkPaint.setTextSize(SkIntToScalar(kMediumDFFontSize)); |
338 } else { | 376 } else { |
339 fTextRatio = fSkPaint.getTextSize()/kLargeDFFontSize; | 377 fTextRatio = fSkPaint.getTextSize()/kLargeDFFontSize; |
340 fSkPaint.setTextSize(SkIntToScalar(kLargeDFFontSize)); | 378 fSkPaint.setTextSize(SkIntToScalar(kLargeDFFontSize)); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
401 SkASSERT(byteLength == 0 || text != NULL); | 439 SkASSERT(byteLength == 0 || text != NULL); |
402 | 440 |
403 // nothing to draw or can't draw | 441 // nothing to draw or can't draw |
404 if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/ | 442 if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/ |
405 || fSkPaint.getRasterizer()) { | 443 || fSkPaint.getRasterizer()) { |
406 return; | 444 return; |
407 } | 445 } |
408 | 446 |
409 this->init(paint, skPaint); | 447 this->init(paint, skPaint); |
410 | 448 |
411 if (NULL == fDrawTarget) { | |
412 return; | |
413 } | |
414 | |
415 SkScalar sizeRatio = fTextRatio; | 449 SkScalar sizeRatio = fTextRatio; |
416 | 450 |
417 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); | 451 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); |
418 | 452 |
419 SkAutoGlyphCacheNoGamma autoCache(fSkPaint, &fDeviceProperties, NULL); | 453 SkAutoGlyphCacheNoGamma autoCache(fSkPaint, &fDeviceProperties, NULL); |
420 SkGlyphCache* cache = autoCache.getCache(); | 454 SkGlyphCache* cache = autoCache.getCache(); |
421 GrFontScaler* fontScaler = GetGrFontScaler(cache); | 455 GrFontScaler* fontScaler = GetGrFontScaler(cache); |
422 if (NULL == fStrike) { | |
423 fStrike = fContext->getFontCache()->getStrike(fontScaler, true); | |
424 } | |
425 | 456 |
426 setup_gamma_texture(fContext, cache, fDeviceProperties, &fGammaTexture); | 457 setup_gamma_texture(fContext, cache, fDeviceProperties, &fGammaTexture); |
427 | 458 |
428 // allocate vertices | |
429 SkASSERT(NULL == fVertices); | |
430 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>( | |
431 SK_ARRAY_COUNT(g
TextVertexAttribs)); | |
432 int numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL); | |
433 bool success = fDrawTarget->reserveVertexAndIndexSpace(4*numGlyphs, | |
434 0, | |
435 &fVertices, | |
436 NULL); | |
437 GrAlwaysAssert(success); | |
438 | |
439 // need to measure first | 459 // need to measure first |
440 // TODO - generate positions and pre-load cache as well? | 460 // TODO - generate positions and pre-load cache as well? |
441 const char* stop = text + byteLength; | 461 const char* stop = text + byteLength; |
442 if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) { | 462 if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) { |
443 SkFixed stopX = 0; | 463 SkFixed stopX = 0; |
444 SkFixed stopY = 0; | 464 SkFixed stopY = 0; |
445 | 465 |
446 const char* textPtr = text; | 466 const char* textPtr = text; |
447 while (textPtr < stop) { | 467 while (textPtr < stop) { |
448 // don't need x, y here, since all subpixel variants will have the | 468 // don't need x, y here, since all subpixel variants will have the |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
496 SkASSERT(byteLength == 0 || text != NULL); | 516 SkASSERT(byteLength == 0 || text != NULL); |
497 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); | 517 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); |
498 | 518 |
499 // nothing to draw | 519 // nothing to draw |
500 if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/)
{ | 520 if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/)
{ |
501 return; | 521 return; |
502 } | 522 } |
503 | 523 |
504 this->init(paint, skPaint); | 524 this->init(paint, skPaint); |
505 | 525 |
506 if (NULL == fDrawTarget) { | |
507 return; | |
508 } | |
509 | |
510 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); | 526 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); |
511 | 527 |
512 SkAutoGlyphCacheNoGamma autoCache(fSkPaint, &fDeviceProperties, NULL); | 528 SkAutoGlyphCacheNoGamma autoCache(fSkPaint, &fDeviceProperties, NULL); |
513 SkGlyphCache* cache = autoCache.getCache(); | 529 SkGlyphCache* cache = autoCache.getCache(); |
514 GrFontScaler* fontScaler = GetGrFontScaler(cache); | 530 GrFontScaler* fontScaler = GetGrFontScaler(cache); |
515 if (NULL == fStrike) { | |
516 fStrike = fContext->getFontCache()->getStrike(fontScaler, true); | |
517 } | |
518 | |
519 // allocate vertices | |
520 SkASSERT(NULL == fVertices); | |
521 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>( | |
522 SK_ARRAY_COUNT(g
TextVertexAttribs)); | |
523 int numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL); | |
524 bool success = fDrawTarget->reserveVertexAndIndexSpace(4*numGlyphs, | |
525 0, | |
526 &fVertices, | |
527 NULL); | |
528 GrAlwaysAssert(success); | |
529 | 531 |
530 setup_gamma_texture(fContext, cache, fDeviceProperties, &fGammaTexture); | 532 setup_gamma_texture(fContext, cache, fDeviceProperties, &fGammaTexture); |
531 | 533 |
532 const char* stop = text + byteLength; | 534 const char* stop = text + byteLength; |
533 | 535 |
534 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) { | 536 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) { |
535 while (text < stop) { | 537 while (text < stop) { |
536 // the last 2 parameters are ignored | 538 // the last 2 parameters are ignored |
537 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); | 539 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); |
538 | 540 |
(...skipping 26 matching lines...) Expand all Loading... |
565 SkScalarToFixed(x) - (glyph.fAdvanceX >> a
lignShift), | 567 SkScalarToFixed(x) - (glyph.fAdvanceX >> a
lignShift), |
566 SkScalarToFixed(y) - (glyph.fAdvanceY >> a
lignShift), | 568 SkScalarToFixed(y) - (glyph.fAdvanceY >> a
lignShift), |
567 fontScaler); | 569 fontScaler); |
568 } | 570 } |
569 pos += scalarsPerPosition; | 571 pos += scalarsPerPosition; |
570 } | 572 } |
571 } | 573 } |
572 | 574 |
573 this->finish(); | 575 this->finish(); |
574 } | 576 } |
OLD | NEW |