Chromium Code Reviews| Index: src/gpu/SkGpuDevice.cpp |
| diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp |
| index c6194e70312a5710891b2317e07f61dae90d8ca9..e36d2c61c59fac20451d74f5c8cf2ad1dbb84925 100644 |
| --- a/src/gpu/SkGpuDevice.cpp |
| +++ b/src/gpu/SkGpuDevice.cpp |
| @@ -1684,9 +1684,6 @@ SkDrawProcs* SkGpuDevice::initDrawForText(GrTextContext* context) { |
| fDrawProcs = SkNEW(GrSkDrawProcs); |
| fDrawProcs->fD1GProc = SkGPU_Draw1Glyph; |
| fDrawProcs->fContext = fContext; |
| -#if SK_DISTANCEFIELD_FONTS |
| - fDrawProcs->fFlags = 0; |
| -#endif |
| } |
| // init our (and GL's) state |
| @@ -1700,9 +1697,12 @@ void SkGpuDevice::drawText(const SkDraw& draw, const void* text, |
| const SkPaint& paint) { |
| CHECK_SHOULD_DRAW(draw, false); |
| - if (fContext->getMatrix().hasPerspective()) { |
| - // this guy will just call our drawPath() |
| - draw.drawText((const char*)text, byteLength, x, y, paint); |
| + if (draw.shouldDrawTextAsPaths(paint, fContext->getMatrix())) { |
| + draw.drawText_asPaths((const char*)text, byteLength, x, y, paint); |
| +#if SK_DISTANCEFIELD_FONTS |
| + } else if (!paint.getRasterizer()) { |
| + drawDFText((const char *)text, byteLength, x, y, paint); |
| +#endif |
| } else { |
| SkDraw myDraw(draw); |
| @@ -1710,23 +1710,93 @@ void SkGpuDevice::drawText(const SkDraw& draw, const void* text, |
| if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) { |
| return; |
| } |
| -#if SK_DISTANCEFIELD_FONTS |
| - if (paint.getRasterizer()) { |
| -#endif |
| - GrBitmapTextContext context(fContext, grPaint, paint.getColor()); |
| - myDraw.fProcs = this->initDrawForText(&context); |
| - this->INHERITED::drawText(myDraw, text, byteLength, x, y, paint); |
| -#if SK_DISTANCEFIELD_FONTS |
| - } else { |
| - GrDistanceFieldTextContext context(fContext, grPaint, paint.getColor(), |
| - paint.getTextSize()/SkDrawProcs::kBaseDFFontSize); |
| - myDraw.fProcs = this->initDrawForText(&context); |
| - fDrawProcs->fFlags |= SkDrawProcs::kSkipBakedGlyphTransform_Flag; |
| - fDrawProcs->fFlags |= SkDrawProcs::kUseScaledGlyphs_Flag; |
| - this->INHERITED::drawText(myDraw, text, byteLength, x, y, paint); |
| - fDrawProcs->fFlags = 0; |
| - } |
| -#endif |
| + |
| + GrBitmapTextContext context(fContext, grPaint, paint.getColor()); |
| + myDraw.fProcs = this->initDrawForText(&context); |
| + this->INHERITED::drawText(myDraw, text, byteLength, x, y, paint); |
| + } |
| +} |
| + |
| +static const int kBaseDFFontSize = 32; |
| + |
| +void SkGpuDevice::drawDFText(const char text[], size_t byteLength, |
| + SkScalar x, SkScalar y, |
| + const SkPaint& paint) { |
| + GrPaint grPaint; |
| + if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) { |
| + return; |
| + } |
| + |
| + SkASSERT(byteLength == 0 || text != NULL); |
| + |
| + SkDEBUGCODE(this->validate();) |
| + |
| + // nothing to draw |
| + if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/) { |
| + return; |
| + } |
| + |
| + SkScalar sizeRatio = paint.getTextSize()/kBaseDFFontSize; |
| + GrDistanceFieldTextContext context(fContext, grPaint, paint.getColor(), sizeRatio); |
| + |
| + SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc(); |
| + |
| + SkPaint paintCopy = paint; |
| + paintCopy.setTextSize(SkIntToScalar(kBaseDFFontSize)); |
| + paintCopy.setLCDRenderText(false); |
| + paintCopy.setAutohinted(false); |
| + paintCopy.setSubpixelText(false); |
| + SkAutoGlyphCache autoCache(paintCopy, &this->fLeakyProperties, NULL); |
| + SkGlyphCache* cache = autoCache.getCache(); |
| + |
| + // need to measure first |
| + // TODO - generate positions and pre-load cache as well? |
| + const char* stop = text + byteLength; |
| + if (paint.getTextAlign() != SkPaint::kLeft_Align) { |
| + SkFixed stopX = 0; |
| + SkFixed stopY = 0; |
| + |
| + const char* textPtr = text; |
| + while (textPtr < stop) { |
| + // don't need x, y here, since all subpixel variants will have the |
| + // same advance |
| + const SkGlyph& glyph = glyphCacheProc(cache, &textPtr, 0, 0); |
| + |
| + stopX += glyph.fAdvanceX; |
| + stopY += glyph.fAdvanceY; |
| + } |
| + SkASSERT(textPtr == stop); |
| + |
| + SkScalar alignX = SkFixedToScalar(stopX)*sizeRatio; |
| + SkScalar alignY = SkFixedToScalar(stopY)*sizeRatio; |
| + |
| + if (paint.getTextAlign() == SkPaint::kCenter_Align) { |
| + alignX = SkScalarHalf(alignX); |
| + alignY = SkScalarHalf(alignY); |
| + } |
| + |
| + x -= alignX; |
| + y -= alignY; |
| + } |
| + |
| + SkFixed fx = SkScalarToFixed(x) + SK_FixedHalf; |
| + SkFixed fy = SkScalarToFixed(y) + SK_FixedHalf; |
| + SkFixed fixedScale = SkScalarToFixed(sizeRatio); |
| + GrFontScaler* fontScaler = get_gr_font_scaler(cache); |
| + while (text < stop) { |
| + const SkGlyph& glyph = glyphCacheProc(cache, &text, fx, fy); |
| + |
| + if (glyph.fWidth) { |
| + context.drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(), |
| + glyph.getSubXFixed(), |
| + glyph.getSubYFixed()), |
| + SkFixedFloorToFixed(fx), |
| + SkFixedFloorToFixed(fy), |
| + fontScaler); |
| + } |
| + |
| + fx += SkFixedMul_portable(glyph.fAdvanceX, fixedScale); |
| + fy += SkFixedMul_portable(glyph.fAdvanceY, fixedScale); |
| } |
| } |
| @@ -1736,10 +1806,14 @@ void SkGpuDevice::drawPosText(const SkDraw& draw, const void* text, |
| const SkPaint& paint) { |
| CHECK_SHOULD_DRAW(draw, false); |
| - if (fContext->getMatrix().hasPerspective()) { |
| + if (draw.shouldDrawTextAsPaths(paint, fContext->getMatrix())) { |
| // this guy will just call our drawPath() |
| - draw.drawPosText((const char*)text, byteLength, pos, constY, |
| + draw.drawPosText_asPaths((const char*)text, byteLength, pos, constY, |
| scalarsPerPos, paint); |
| +#if SK_DISTANCEFIELD_FONTS |
| + } else if (!paint.getRasterizer()) { |
| + drawPosDFText((const char *)text, byteLength, pos, constY, scalarsPerPos, paint); |
|
bsalomon
2013/11/25 20:50:22
this->
|
| +#endif |
| } else { |
| SkDraw myDraw(draw); |
| @@ -1747,25 +1821,86 @@ void SkGpuDevice::drawPosText(const SkDraw& draw, const void* text, |
| if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) { |
| return; |
| } |
| -#if SK_DISTANCEFIELD_FONTS |
| - if (paint.getRasterizer()) { |
| -#endif |
| - GrBitmapTextContext context(fContext, grPaint, paint.getColor()); |
| - myDraw.fProcs = this->initDrawForText(&context); |
| - this->INHERITED::drawPosText(myDraw, text, byteLength, pos, constY, |
| - scalarsPerPos, paint); |
| -#if SK_DISTANCEFIELD_FONTS |
| - } else { |
| - GrDistanceFieldTextContext context(fContext, grPaint, paint.getColor(), |
| - paint.getTextSize()/SkDrawProcs::kBaseDFFontSize); |
| - myDraw.fProcs = this->initDrawForText(&context); |
| - fDrawProcs->fFlags |= SkDrawProcs::kSkipBakedGlyphTransform_Flag; |
| - fDrawProcs->fFlags |= SkDrawProcs::kUseScaledGlyphs_Flag; |
| - this->INHERITED::drawPosText(myDraw, text, byteLength, pos, constY, |
| - scalarsPerPos, paint); |
| - fDrawProcs->fFlags = 0; |
| + GrBitmapTextContext context(fContext, grPaint, paint.getColor()); |
| + myDraw.fProcs = this->initDrawForText(&context); |
| + this->INHERITED::drawPosText(myDraw, text, byteLength, pos, constY, |
| + scalarsPerPos, paint); |
| + } |
| +} |
| + |
| +void SkGpuDevice::drawPosDFText(const char text[], size_t byteLength, |
| + const SkScalar pos[], SkScalar constY, int scalarsPerPosition, |
| + const SkPaint& paint) { |
| + GrPaint grPaint; |
| + if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) { |
| + return; |
| + } |
| + |
| + SkASSERT(byteLength == 0 || text != NULL); |
| + SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); |
| + |
| + SkDEBUGCODE(this->validate();) |
| + |
| + // nothing to draw |
| + if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/) { |
| + return; |
| + } |
| + |
| + SkScalar sizeRatio = paint.getTextSize()/kBaseDFFontSize; |
| + GrDistanceFieldTextContext context(fContext, grPaint, paint.getColor(), sizeRatio); |
| + |
| + SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc(); |
| + |
| + SkPaint paintCopy = paint; |
| + paintCopy.setTextSize(SkIntToScalar(kBaseDFFontSize)); |
| + paintCopy.setLCDRenderText(false); |
| + paintCopy.setAutohinted(false); |
| + paintCopy.setSubpixelText(false); |
| + SkAutoGlyphCache autoCache(paintCopy, &this->fLeakyProperties, NULL); |
| + SkGlyphCache* cache = autoCache.getCache(); |
| + |
| + const char* stop = text + byteLength; |
| + GrFontScaler* fontScaler = get_gr_font_scaler(cache); |
| + |
| + if (SkPaint::kLeft_Align == paint.getTextAlign()) { |
| + while (text < stop) { |
| + // the last 2 parameters are ignored |
| + const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); |
| + |
| + if (glyph.fWidth) { |
| + SkScalar x = pos[0]; |
| + SkScalar y = scalarsPerPosition == 1 ? constY : pos[1]; |
| + |
| + context.drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(), |
| + glyph.getSubXFixed(), |
| + glyph.getSubYFixed()), |
| + SkScalarToFixed(x) + SK_FixedHalf, //d1g.fHalfSampleX, |
| + SkScalarToFixed(y) + SK_FixedHalf, //d1g.fHalfSampleY, |
| + fontScaler); |
| + } |
| + pos += scalarsPerPosition; |
| + } |
| + } else { |
|
robertphillips
2013/11/25 20:39:44
Is all this duplicate code just for the shift?
|
| + int alignShift = SkPaint::kCenter_Align == paint.getTextAlign() ? 1 : 0; |
| + while (text < stop) { |
| + // the last 2 parameters are ignored |
| + const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); |
| + |
| + if (glyph.fWidth) { |
| + SkScalar x = pos[0]; |
| + SkScalar y = scalarsPerPosition == 1 ? constY : pos[1]; |
| + |
| + context.drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(), |
| + glyph.getSubXFixed(), |
| + glyph.getSubYFixed()), |
| + SkScalarToFixed(x) - (glyph.fAdvanceX >> alignShift) |
| + + SK_FixedHalf, //d1g.fHalfSampleX, |
| + SkScalarToFixed(y) - (glyph.fAdvanceY >> alignShift) |
| + + SK_FixedHalf, //d1g.fHalfSampleY, |
| + fontScaler); |
| + } |
| + pos += scalarsPerPosition; |
| } |
| -#endif |
| } |
| } |