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:
parent
cf598b176d
commit
52c748b169
@ -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).
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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]
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user