Gpu can draw underlined text.

http://codereview.appspot.com/4919047/


git-svn-id: http://skia.googlecode.com/svn/trunk@2154 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
bungeman@google.com 2011-08-22 21:30:43 +00:00
parent cf598b176d
commit 52c748b169
5 changed files with 87 additions and 88 deletions

View File

@ -816,6 +816,11 @@ private:
// shared by save() and saveLayer()
int internalSave(SaveFlags flags);
void internalRestore();
static void DrawRect(const SkDraw& draw, const SkPaint& paint,
const SkRect& r, SkScalar textSize);
static void DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
const char text[], size_t byteLength,
SkScalar x, SkScalar y);
/* These maintain a cache of the clip bounds in local coordinates,
(converted to 2s-compliment if floats are slow).

View File

@ -217,6 +217,10 @@ protected:
const SkMatrix& matrix, const SkPaint& paint);
virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
int x, int y, const SkPaint& paint);
/**
* Does not handle text decoration.
* Decorations (underline and stike-thru) will be handled by SkCanvas.
*/
virtual void drawText(const SkDraw&, const void* text, size_t len,
SkScalar x, SkScalar y, const SkPaint& paint);
virtual void drawPosText(const SkDraw&, const void* text, size_t len,

View File

@ -16,6 +16,7 @@
#include "SkPicture.h"
#include "SkScalarCompare.h"
#include "SkTemplates.h"
#include "SkTextFormatParams.h"
#include "SkTLazy.h"
#include "SkUtils.h"
@ -1381,6 +1382,78 @@ private:
SkLazyPaint fLazy;
};
void SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint,
const SkRect& r, SkScalar textSize) {
if (paint.getStyle() == SkPaint::kFill_Style) {
draw.fDevice->drawRect(draw, r, paint);
} else {
SkPaint p(paint);
p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth()));
draw.fDevice->drawRect(draw, r, p);
}
}
void SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
const char text[], size_t byteLength,
SkScalar x, SkScalar y) {
SkASSERT(byteLength == 0 || text != NULL);
// nothing to draw
if (text == NULL || byteLength == 0 ||
draw.fClip->isEmpty() ||
(paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
return;
}
SkScalar width = 0;
SkPoint start;
start.set(0, 0); // to avoid warning
if (paint.getFlags() & (SkPaint::kUnderlineText_Flag |
SkPaint::kStrikeThruText_Flag)) {
width = paint.measureText(text, byteLength);
SkScalar offsetX = 0;
if (paint.getTextAlign() == SkPaint::kCenter_Align) {
offsetX = SkScalarHalf(width);
} else if (paint.getTextAlign() == SkPaint::kRight_Align) {
offsetX = width;
}
start.set(x - offsetX, y);
}
if (0 == width) {
return;
}
uint32_t flags = paint.getFlags();
if (flags & (SkPaint::kUnderlineText_Flag |
SkPaint::kStrikeThruText_Flag)) {
SkScalar textSize = paint.getTextSize();
SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);
SkRect r;
r.fLeft = start.fX;
r.fRight = start.fX + width;
if (flags & SkPaint::kUnderlineText_Flag) {
SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset,
start.fY);
r.fTop = offset;
r.fBottom = offset + height;
DrawRect(draw, paint, r, textSize);
}
if (flags & SkPaint::kStrikeThruText_Flag) {
SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset,
start.fY);
r.fTop = offset;
r.fBottom = offset + height;
DrawRect(draw, paint, r, textSize);
}
}
}
void SkCanvas::drawText(const void* text, size_t byteLength,
SkScalar x, SkScalar y, const SkPaint& paint) {
LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
@ -1388,6 +1461,8 @@ void SkCanvas::drawText(const void* text, size_t byteLength,
while (iter.next()) {
SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
DrawTextDecorations(iter, dfp.paint(),
static_cast<const char*>(text), byteLength, x, y);
}
LOOPER_END

View File

@ -21,7 +21,6 @@
#include "SkShader.h"
#include "SkStroke.h"
#include "SkTemplatesPriv.h"
#include "SkTextFormatParams.h"
#include "SkTLazy.h"
#include "SkUtils.h"
@ -1277,47 +1276,6 @@ void SkDraw::drawText_asPaths(const char text[], size_t byteLength,
}
}
static void draw_paint_rect(const SkDraw* draw, const SkPaint& paint,
const SkRect& r, SkScalar textSize) {
if (paint.getStyle() == SkPaint::kFill_Style) {
draw->drawRect(r, paint);
} else {
SkPaint p(paint);
p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth()));
draw->drawRect(r, p);
}
}
static void handle_aftertext(const SkDraw* draw, const SkPaint& paint,
SkScalar width, const SkPoint& start) {
uint32_t flags = paint.getFlags();
if (flags & (SkPaint::kUnderlineText_Flag |
SkPaint::kStrikeThruText_Flag)) {
SkScalar textSize = paint.getTextSize();
SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);
SkRect r;
r.fLeft = start.fX;
r.fRight = start.fX + width;
if (flags & SkPaint::kUnderlineText_Flag) {
SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset,
start.fY);
r.fTop = offset;
r.fBottom = offset + height;
draw_paint_rect(draw, paint, r, textSize);
}
if (flags & SkPaint::kStrikeThruText_Flag) {
SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset,
start.fY);
r.fTop = offset;
r.fBottom = offset + height;
draw_paint_rect(draw, paint, r, textSize);
}
}
}
// disable warning : local variable used without having been initialized
#if defined _WIN32 && _MSC_VER >= 1300
#pragma warning ( push )
@ -1513,27 +1471,9 @@ void SkDraw::drawText(const char text[], size_t byteLength,
return;
}
SkScalar underlineWidth = 0;
SkPoint underlineStart;
underlineStart.set(0, 0); // to avoid warning
if (paint.getFlags() & (SkPaint::kUnderlineText_Flag |
SkPaint::kStrikeThruText_Flag)) {
underlineWidth = paint.measureText(text, byteLength);
SkScalar offsetX = 0;
if (paint.getTextAlign() == SkPaint::kCenter_Align) {
offsetX = SkScalarHalf(underlineWidth);
} else if (paint.getTextAlign() == SkPaint::kRight_Align) {
offsetX = underlineWidth;
}
underlineStart.set(x - offsetX, y);
}
if (/*paint.isLinearText() ||*/
(fMatrix->hasPerspective())) {
this->drawText_asPaths(text, byteLength, x, y, paint);
handle_aftertext(this, paint, underlineWidth, underlineStart);
return;
}
@ -1601,8 +1541,8 @@ void SkDraw::drawText(const char text[], size_t byteLength,
}
SkAutoKern autokern;
SkDraw1Glyph d1g;
SkDraw1Glyph::Proc proc = d1g.init(this, blitter.get(), cache);
SkDraw1Glyph d1g;
SkDraw1Glyph::Proc proc = d1g.init(this, blitter.get(), cache);
while (text < stop) {
const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask);
@ -1610,16 +1550,11 @@ void SkDraw::drawText(const char text[], size_t byteLength,
fx += autokern.adjust(glyph);
if (glyph.fWidth) {
proc(d1g, fx, fy, glyph);
proc(d1g, fx, fy, glyph);
}
fx += glyph.fAdvanceX;
fy += glyph.fAdvanceY;
}
if (underlineWidth) {
autoCache.release(); // release this now to free up the RAM
handle_aftertext(this, paint, underlineWidth, underlineStart);
}
}
// last parameter is interpreted as SkFixed [x, y]

View File

@ -837,26 +837,6 @@ void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len,
content.entry()->fContent.writeText(" Tj\n");
}
content.entry()->fContent.writeText("ET\n");
// Draw underline and/or strikethrough if the paint has them.
// drawPosText() and drawTextOnPath() don't draw underline or strikethrough
// because the raster versions don't. Use paint instead of textPaint
// because we may have changed strokeWidth to do fakeBold text.
if (paint.isUnderlineText() || paint.isStrikeThruText()) {
SkScalar textSize = paint.getTextSize();
SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);
if (paint.isUnderlineText()) {
SkScalar top = SkScalarMulAdd(textSize, kStdUnderline_Offset, y);
SkRect r = SkRect::MakeXYWH(x, top - height, width, height);
drawRect(d, r, paint);
}
if (paint.isStrikeThruText()) {
SkScalar top = SkScalarMulAdd(textSize, kStdStrikeThru_Offset, y);
SkRect r = SkRect::MakeXYWH(x, top - height, width, height);
drawRect(d, r, paint);
}
}
}
void SkPDFDevice::drawPosText(const SkDraw& d, const void* text, size_t len,