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,