| 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 |