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
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h
index 7b9e6af..4658525 100644
--- a/include/core/SkCanvas.h
+++ b/include/core/SkCanvas.h
@@ -816,6 +816,11 @@
// 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).
diff --git a/include/core/SkDevice.h b/include/core/SkDevice.h
index 083b893..97fff66 100644
--- a/include/core/SkDevice.h
+++ b/include/core/SkDevice.h
@@ -217,6 +217,10 @@
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,
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index aa6fe72..65f34cc 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -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 @@
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 @@
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
diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp
index 10acf07..12c8288 100644
--- a/src/core/SkDraw.cpp
+++ b/src/core/SkDraw.cpp
@@ -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 @@
}
}
-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 @@
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 @@
}
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 @@
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]
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
index 9cdce36..d459392 100644
--- a/src/pdf/SkPDFDevice.cpp
+++ b/src/pdf/SkPDFDevice.cpp
@@ -837,26 +837,6 @@
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,