| 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 "SkDrawProcs.h" |
| 23 #include "SkGlyphCache.h" | 24 #include "SkGlyphCache.h" |
| 24 #include "SkGpuDevice.h" | 25 #include "SkGpuDevice.h" |
| 25 #include "SkGr.h" | 26 #include "SkGr.h" |
| 27 #include "SkTextMapStateProc.h" |
| 26 | 28 |
| 27 SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false, | 29 SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false, |
| 28 "Dump the contents of the font cache before every purge."); | 30 "Dump the contents of the font cache before every purge."); |
| 29 | 31 |
| 30 static const int kGlyphCoordsNoColorAttributeIndex = 1; | 32 static const int kGlyphCoordsNoColorAttributeIndex = 1; |
| 31 static const int kGlyphCoordsWithColorAttributeIndex = 2; | 33 static const int kGlyphCoordsWithColorAttributeIndex = 2; |
| 32 | 34 |
| 33 namespace { | 35 namespace { |
| 34 // position + texture coord | 36 // position + texture coord |
| 35 extern const GrVertexAttrib gTextVertexAttribs[] = { | 37 extern const GrVertexAttrib gTextVertexAttribs[] = { |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 256 fontScaler); | 258 fontScaler); |
| 257 } | 259 } |
| 258 | 260 |
| 259 fx += glyph.fAdvanceX; | 261 fx += glyph.fAdvanceX; |
| 260 fy += glyph.fAdvanceY; | 262 fy += glyph.fAdvanceY; |
| 261 } | 263 } |
| 262 | 264 |
| 263 this->finish(); | 265 this->finish(); |
| 264 } | 266 } |
| 265 | 267 |
| 266 /////////////////////////////////////////////////////////////////////////////// | |
| 267 // Copied from SkDraw | |
| 268 | |
| 269 // last parameter is interpreted as SkFixed [x, y] | |
| 270 // return the fixed position, which may be rounded or not by the caller | |
| 271 // e.g. subpixel doesn't round | |
| 272 typedef void (*AlignProc)(const SkPoint&, const SkGlyph&, SkIPoint*); | |
| 273 | |
| 274 static void leftAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* ds
t) { | |
| 275 dst->set(SkScalarToFixed(loc.fX), SkScalarToFixed(loc.fY)); | |
| 276 } | |
| 277 | |
| 278 static void centerAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint*
dst) { | |
| 279 dst->set(SkScalarToFixed(loc.fX) - (glyph.fAdvanceX >> 1), | |
| 280 SkScalarToFixed(loc.fY) - (glyph.fAdvanceY >> 1)); | |
| 281 } | |
| 282 | |
| 283 static void rightAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* d
st) { | |
| 284 dst->set(SkScalarToFixed(loc.fX) - glyph.fAdvanceX, | |
| 285 SkScalarToFixed(loc.fY) - glyph.fAdvanceY); | |
| 286 } | |
| 287 | |
| 288 static AlignProc pick_align_proc(SkPaint::Align align) { | |
| 289 static const AlignProc gProcs[] = { | |
| 290 leftAlignProc, centerAlignProc, rightAlignProc | |
| 291 }; | |
| 292 | |
| 293 SkASSERT((unsigned)align < SK_ARRAY_COUNT(gProcs)); | |
| 294 | |
| 295 return gProcs[align]; | |
| 296 } | |
| 297 | |
| 298 class BitmapTextMapState { | |
| 299 public: | |
| 300 mutable SkPoint fLoc; | |
| 301 | |
| 302 BitmapTextMapState(const SkMatrix& matrix, SkScalar y) | |
| 303 : fMatrix(matrix), fProc(matrix.getMapXYProc()), fY(y) {} | |
| 304 | |
| 305 typedef void (*Proc)(const BitmapTextMapState&, const SkScalar pos[]); | |
| 306 | |
| 307 Proc pickProc(int scalarsPerPosition); | |
| 308 | |
| 309 private: | |
| 310 const SkMatrix& fMatrix; | |
| 311 SkMatrix::MapXYProc fProc; | |
| 312 SkScalar fY; // ignored by MapXYProc | |
| 313 // these are only used by Only... procs | |
| 314 SkScalar fScaleX, fTransX, fTransformedY; | |
| 315 | |
| 316 static void MapXProc(const BitmapTextMapState& state, const SkScalar pos[])
{ | |
| 317 state.fProc(state.fMatrix, *pos, state.fY, &state.fLoc); | |
| 318 } | |
| 319 | |
| 320 static void MapXYProc(const BitmapTextMapState& state, const SkScalar pos[])
{ | |
| 321 state.fProc(state.fMatrix, pos[0], pos[1], &state.fLoc); | |
| 322 } | |
| 323 | |
| 324 static void MapOnlyScaleXProc(const BitmapTextMapState& state, | |
| 325 const SkScalar pos[]) { | |
| 326 state.fLoc.set(SkScalarMul(state.fScaleX, *pos) + state.fTransX, | |
| 327 state.fTransformedY); | |
| 328 } | |
| 329 | |
| 330 static void MapOnlyTransXProc(const BitmapTextMapState& state, | |
| 331 const SkScalar pos[]) { | |
| 332 state.fLoc.set(*pos + state.fTransX, state.fTransformedY); | |
| 333 } | |
| 334 }; | |
| 335 | |
| 336 BitmapTextMapState::Proc BitmapTextMapState::pickProc(int scalarsPerPosition) { | |
| 337 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); | |
| 338 | |
| 339 if (1 == scalarsPerPosition) { | |
| 340 unsigned mtype = fMatrix.getType(); | |
| 341 if (mtype & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) { | |
| 342 return MapXProc; | |
| 343 } else { | |
| 344 fScaleX = fMatrix.getScaleX(); | |
| 345 fTransX = fMatrix.getTranslateX(); | |
| 346 fTransformedY = SkScalarMul(fY, fMatrix.getScaleY()) + | |
| 347 fMatrix.getTranslateY(); | |
| 348 return (mtype & SkMatrix::kScale_Mask) ? | |
| 349 MapOnlyScaleXProc : MapOnlyTransXProc; | |
| 350 } | |
| 351 } else { | |
| 352 return MapXYProc; | |
| 353 } | |
| 354 } | |
| 355 | |
| 356 /////////////////////////////////////////////////////////////////////////////// | |
| 357 | |
| 358 void GrBitmapTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPai
nt, | 268 void GrBitmapTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPai
nt, |
| 359 const char text[], size_t byteLength, | 269 const char text[], size_t byteLength, |
| 360 const SkScalar pos[], SkScalar constY, | 270 const SkScalar pos[], SkScalar constY, |
| 361 int scalarsPerPosition) { | 271 int scalarsPerPosition) { |
| 362 SkASSERT(byteLength == 0 || text != NULL); | 272 SkASSERT(byteLength == 0 || text != NULL); |
| 363 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); | 273 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); |
| 364 | 274 |
| 365 // nothing to draw | 275 // nothing to draw |
| 366 if (text == NULL || byteLength == 0/* || fRC->isEmpty()*/) { | 276 if (text == NULL || byteLength == 0/* || fRC->isEmpty()*/) { |
| 367 return; | 277 return; |
| 368 } | 278 } |
| 369 | 279 |
| 370 this->init(paint, skPaint); | 280 this->init(paint, skPaint); |
| 371 | 281 |
| 372 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); | 282 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); |
| 373 | 283 |
| 374 SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, &fContext->getMa
trix()); | 284 SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, &fContext->getMa
trix()); |
| 375 SkGlyphCache* cache = autoCache.getCache(); | 285 SkGlyphCache* cache = autoCache.getCache(); |
| 376 GrFontScaler* fontScaler = GetGrFontScaler(cache); | 286 GrFontScaler* fontScaler = GetGrFontScaler(cache); |
| 377 | 287 |
| 378 // store original matrix before we reset, so we can use it to transform posi
tions | 288 // store original matrix before we reset, so we can use it to transform posi
tions |
| 379 SkMatrix ctm = fContext->getMatrix(); | 289 SkMatrix ctm = fContext->getMatrix(); |
| 380 GrContext::AutoMatrix autoMatrix; | 290 GrContext::AutoMatrix autoMatrix; |
| 381 autoMatrix.setIdentity(fContext, &fPaint); | 291 autoMatrix.setIdentity(fContext, &fPaint); |
| 382 | 292 |
| 383 const char* stop = text + byteLength; | 293 const char* stop = text + byteLength; |
| 384 AlignProc alignProc = pick_align_proc(fSkPaint.getTextAlign()); | 294 SkTextAlignProc alignProc(fSkPaint.getTextAlign()); |
| 385 BitmapTextMapState tms(ctm, constY); | 295 SkTextMapStateProc tmsProc(ctm, constY, scalarsPerPosition); |
| 386 BitmapTextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition); | |
| 387 SkFixed halfSampleX = 0, halfSampleY = 0; | 296 SkFixed halfSampleX = 0, halfSampleY = 0; |
| 388 | 297 |
| 389 if (cache->isSubpixel()) { | 298 if (cache->isSubpixel()) { |
| 390 // maybe we should skip the rounding if linearText is set | 299 // maybe we should skip the rounding if linearText is set |
| 391 SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(ctm); | 300 SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(ctm); |
| 392 | 301 |
| 393 SkFixed fxMask = ~0; | 302 SkFixed fxMask = ~0; |
| 394 SkFixed fyMask = ~0; | 303 SkFixed fyMask = ~0; |
| 395 if (kX_SkAxisAlignment == baseline) { | 304 if (kX_SkAxisAlignment == baseline) { |
| 396 fyMask = 0; | 305 fyMask = 0; |
| 397 #ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX | 306 #ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX |
| 398 halfSampleY = SK_FixedHalf; | 307 halfSampleY = SK_FixedHalf; |
| 399 #endif | 308 #endif |
| 400 } else if (kY_SkAxisAlignment == baseline) { | 309 } else if (kY_SkAxisAlignment == baseline) { |
| 401 fxMask = 0; | 310 fxMask = 0; |
| 402 #ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX | 311 #ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX |
| 403 halfSampleX = SK_FixedHalf; | 312 halfSampleX = SK_FixedHalf; |
| 404 #endif | 313 #endif |
| 405 } | 314 } |
| 406 | 315 |
| 407 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) { | 316 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) { |
| 408 while (text < stop) { | 317 while (text < stop) { |
| 409 tmsProc(tms, pos); | 318 SkPoint tmsLoc; |
| 410 SkFixed fx = SkScalarToFixed(tms.fLoc.fX) + halfSampleX; | 319 tmsProc(pos, &tmsLoc); |
| 411 SkFixed fy = SkScalarToFixed(tms.fLoc.fY) + halfSampleY; | 320 SkFixed fx = SkScalarToFixed(tmsLoc.fX) + halfSampleX; |
| 321 SkFixed fy = SkScalarToFixed(tmsLoc.fY) + halfSampleY; |
| 412 | 322 |
| 413 const SkGlyph& glyph = glyphCacheProc(cache, &text, | 323 const SkGlyph& glyph = glyphCacheProc(cache, &text, |
| 414 fx & fxMask, fy & fyMask); | 324 fx & fxMask, fy & fyMask); |
| 415 | 325 |
| 416 if (glyph.fWidth) { | 326 if (glyph.fWidth) { |
| 417 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(), | 327 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(), |
| 418 glyph.getSubXFixed(), | 328 glyph.getSubXFixed(), |
| 419 glyph.getSubYFixed()), | 329 glyph.getSubYFixed()), |
| 420 SkFixedFloorToFixed(fx), | 330 SkFixedFloorToFixed(fx), |
| 421 SkFixedFloorToFixed(fy), | 331 SkFixedFloorToFixed(fy), |
| 422 fontScaler); | 332 fontScaler); |
| 423 } | 333 } |
| 424 pos += scalarsPerPosition; | 334 pos += scalarsPerPosition; |
| 425 } | 335 } |
| 426 } else { | 336 } else { |
| 427 while (text < stop) { | 337 while (text < stop) { |
| 428 const char* currentText = text; | 338 const char* currentText = text; |
| 429 const SkGlyph& metricGlyph = glyphCacheProc(cache, &text, 0, 0); | 339 const SkGlyph& metricGlyph = glyphCacheProc(cache, &text, 0, 0); |
| 430 | 340 |
| 431 if (metricGlyph.fWidth) { | 341 if (metricGlyph.fWidth) { |
| 432 SkDEBUGCODE(SkFixed prevAdvX = metricGlyph.fAdvanceX;) | 342 SkDEBUGCODE(SkFixed prevAdvX = metricGlyph.fAdvanceX;) |
| 433 SkDEBUGCODE(SkFixed prevAdvY = metricGlyph.fAdvanceY;) | 343 SkDEBUGCODE(SkFixed prevAdvY = metricGlyph.fAdvanceY;) |
| 434 | 344 SkPoint tmsLoc; |
| 435 tmsProc(tms, pos); | 345 tmsProc(pos, &tmsLoc); |
| 436 SkIPoint fixedLoc; | 346 SkIPoint fixedLoc; |
| 437 alignProc(tms.fLoc, metricGlyph, &fixedLoc); | 347 alignProc(tmsLoc, metricGlyph, &fixedLoc); |
| 438 | 348 |
| 439 SkFixed fx = fixedLoc.fX + halfSampleX; | 349 SkFixed fx = fixedLoc.fX + halfSampleX; |
| 440 SkFixed fy = fixedLoc.fY + halfSampleY; | 350 SkFixed fy = fixedLoc.fY + halfSampleY; |
| 441 | 351 |
| 442 // have to call again, now that we've been "aligned" | 352 // have to call again, now that we've been "aligned" |
| 443 const SkGlyph& glyph = glyphCacheProc(cache, ¤tText, | 353 const SkGlyph& glyph = glyphCacheProc(cache, ¤tText, |
| 444 fx & fxMask, fy & fyMa
sk); | 354 fx & fxMask, fy & fyMa
sk); |
| 445 // the assumption is that the metrics haven't changed | 355 // the assumption is that the metrics haven't changed |
| 446 SkASSERT(prevAdvX == glyph.fAdvanceX); | 356 SkASSERT(prevAdvX == glyph.fAdvanceX); |
| 447 SkASSERT(prevAdvY == glyph.fAdvanceY); | 357 SkASSERT(prevAdvY == glyph.fAdvanceY); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 458 } | 368 } |
| 459 } | 369 } |
| 460 } else { // not subpixel | 370 } else { // not subpixel |
| 461 | 371 |
| 462 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) { | 372 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) { |
| 463 while (text < stop) { | 373 while (text < stop) { |
| 464 // the last 2 parameters are ignored | 374 // the last 2 parameters are ignored |
| 465 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); | 375 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); |
| 466 | 376 |
| 467 if (glyph.fWidth) { | 377 if (glyph.fWidth) { |
| 468 tmsProc(tms, pos); | 378 SkPoint tmsLoc; |
| 379 tmsProc(pos, &tmsLoc); |
| 469 | 380 |
| 470 SkFixed fx = SkScalarToFixed(tms.fLoc.fX) + SK_FixedHalf; //
halfSampleX; | 381 SkFixed fx = SkScalarToFixed(tmsLoc.fX) + SK_FixedHalf; //ha
lfSampleX; |
| 471 SkFixed fy = SkScalarToFixed(tms.fLoc.fY) + SK_FixedHalf; //
halfSampleY; | 382 SkFixed fy = SkScalarToFixed(tmsLoc.fY) + SK_FixedHalf; //ha
lfSampleY; |
| 472 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(), | 383 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(), |
| 473 glyph.getSubXFixed(), | 384 glyph.getSubXFixed(), |
| 474 glyph.getSubYFixed()), | 385 glyph.getSubYFixed()), |
| 475 SkFixedFloorToFixed(fx), | 386 SkFixedFloorToFixed(fx), |
| 476 SkFixedFloorToFixed(fy), | 387 SkFixedFloorToFixed(fy), |
| 477 fontScaler); | 388 fontScaler); |
| 478 } | 389 } |
| 479 pos += scalarsPerPosition; | 390 pos += scalarsPerPosition; |
| 480 } | 391 } |
| 481 } else { | 392 } else { |
| 482 while (text < stop) { | 393 while (text < stop) { |
| 483 // the last 2 parameters are ignored | 394 // the last 2 parameters are ignored |
| 484 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); | 395 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); |
| 485 | 396 |
| 486 if (glyph.fWidth) { | 397 if (glyph.fWidth) { |
| 487 tmsProc(tms, pos); | 398 SkPoint tmsLoc; |
| 399 tmsProc(pos, &tmsLoc); |
| 488 | 400 |
| 489 SkIPoint fixedLoc; | 401 SkIPoint fixedLoc; |
| 490 alignProc(tms.fLoc, glyph, &fixedLoc); | 402 alignProc(tmsLoc, glyph, &fixedLoc); |
| 491 | 403 |
| 492 SkFixed fx = fixedLoc.fX + SK_FixedHalf; //halfSampleX; | 404 SkFixed fx = fixedLoc.fX + SK_FixedHalf; //halfSampleX; |
| 493 SkFixed fy = fixedLoc.fY + SK_FixedHalf; //halfSampleY; | 405 SkFixed fy = fixedLoc.fY + SK_FixedHalf; //halfSampleY; |
| 494 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(), | 406 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(), |
| 495 glyph.getSubXFixed(), | 407 glyph.getSubXFixed(), |
| 496 glyph.getSubYFixed()), | 408 glyph.getSubYFixed()), |
| 497 SkFixedFloorToFixed(fx), | 409 SkFixedFloorToFixed(fx), |
| 498 SkFixedFloorToFixed(fy), | 410 SkFixedFloorToFixed(fy), |
| 499 fontScaler); | 411 fontScaler); |
| 500 } | 412 } |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 679 if (useColorVerts) { | 591 if (useColorVerts) { |
| 680 // color comes after position. | 592 // color comes after position. |
| 681 GrColor* colors = reinterpret_cast<GrColor*>(positions + 1); | 593 GrColor* colors = reinterpret_cast<GrColor*>(positions + 1); |
| 682 for (int i = 0; i < 4; ++i) { | 594 for (int i = 0; i < 4; ++i) { |
| 683 *colors = fPaint.getColor(); | 595 *colors = fPaint.getColor(); |
| 684 colors = reinterpret_cast<GrColor*>(reinterpret_cast<intptr_t>(colors
) + vertSize); | 596 colors = reinterpret_cast<GrColor*>(reinterpret_cast<intptr_t>(colors
) + vertSize); |
| 685 } | 597 } |
| 686 } | 598 } |
| 687 fCurrVertex += 4; | 599 fCurrVertex += 4; |
| 688 } | 600 } |
| OLD | NEW |