2009-02-26 Stephen White <senorblanco@chromium.org>
authordarin@chromium.org <darin@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 27 Feb 2009 00:20:01 +0000 (00:20 +0000)
committerdarin@chromium.org <darin@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 27 Feb 2009 00:20:01 +0000 (00:20 +0000)
        Reviewed by Eric Seidel.

        https://bugs.webkit.org/show_bug.cgi?id=23957

        Fix for SVG gradient and pattern text for Chromium/skia.
        Added accessors for the fill and stroke gradients to
        GraphicsContext.  Changed the paintSkiaText function to take a
        GraphicsContext, so we can check for gradients/patterns.
        Changed the skiaDrawText function to set the SkPaint shader
        correctly, and to scale up the gradient shader matrix to
        encompass the entire text string.  Also offset each glyph
        separately, rather than transforming the canvas, so that the
        gradient/pattern stays fixed relative to the text origin.

        * platform/graphics/GraphicsContext.cpp:
        (WebCore::GraphicsContext::getFillGradient):
        (WebCore::GraphicsContext::getStrokeGradient):
        (WebCore::GraphicsContext::getFillPattern):
        (WebCore::GraphicsContext::getStrokePattern):
        * platform/graphics/GraphicsContext.h:
        * platform/graphics/chromium/FontChromiumWin.cpp:
        (WebCore::Font::drawGlyphs):
        * platform/graphics/chromium/UniscribeHelper.cpp:
        (WebCore::UniscribeHelper::draw):
        * platform/graphics/skia/SkiaFontWin.cpp:
        (WebCore::windowsCanHandleTextDrawing):
        (WebCore::skiaDrawText):
        (WebCore::paintSkiaText):
        * platform/graphics/skia/SkiaFontWin.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@41274 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebCore/ChangeLog
WebCore/platform/graphics/GraphicsContext.cpp
WebCore/platform/graphics/GraphicsContext.h
WebCore/platform/graphics/chromium/FontChromiumWin.cpp
WebCore/platform/graphics/chromium/UniscribeHelper.cpp
WebCore/platform/graphics/skia/SkiaFontWin.cpp
WebCore/platform/graphics/skia/SkiaFontWin.h

index f8785a6e7373417f6056b463b3eaa2c23aabb631..ae9502226258173eca4d7ae593d06bebc999209c 100644 (file)
@@ -1,3 +1,35 @@
+2009-02-26  Stephen White  <senorblanco@chromium.org>
+
+        Reviewed by Eric Seidel.
+
+        https://bugs.webkit.org/show_bug.cgi?id=23957
+
+        Fix for SVG gradient and pattern text for Chromium/skia. 
+        Added accessors for the fill and stroke gradients to
+        GraphicsContext.  Changed the paintSkiaText function to take a
+        GraphicsContext, so we can check for gradients/patterns. 
+        Changed the skiaDrawText function to set the SkPaint shader
+        correctly, and to scale up the gradient shader matrix to
+        encompass the entire text string.  Also offset each glyph
+        separately, rather than transforming the canvas, so that the
+        gradient/pattern stays fixed relative to the text origin.
+
+        * platform/graphics/GraphicsContext.cpp:
+        (WebCore::GraphicsContext::getFillGradient):
+        (WebCore::GraphicsContext::getStrokeGradient):
+        (WebCore::GraphicsContext::getFillPattern):
+        (WebCore::GraphicsContext::getStrokePattern):
+        * platform/graphics/GraphicsContext.h:
+        * platform/graphics/chromium/FontChromiumWin.cpp:
+        (WebCore::Font::drawGlyphs):
+        * platform/graphics/chromium/UniscribeHelper.cpp:
+        (WebCore::UniscribeHelper::draw):
+        * platform/graphics/skia/SkiaFontWin.cpp:
+        (WebCore::windowsCanHandleTextDrawing):
+        (WebCore::skiaDrawText):
+        (WebCore::paintSkiaText):
+        * platform/graphics/skia/SkiaFontWin.h:
+
 2009-02-26  Dimitri Glazkov  <dglazkov@chromium.org>
 
         Reviewed by Eric Seidel.
index 1ac91c0dc59b1a6addad2d3bc92b1166030e9aa7..f3ae7d553576b0c0964810c28d017cbcf3552a38 100644 (file)
@@ -245,6 +245,26 @@ void GraphicsContext::setFillGradient(PassRefPtr<Gradient> gradient)
     m_common->state.fillGradient = gradient;
 }
 
+Gradient* GraphicsContext::fillGradient() const
+{
+    return m_common->state.fillGradient.get();
+}
+
+Gradient* GraphicsContext::strokeGradient() const
+{
+    return m_common->state.strokeGradient.get();
+}
+
+Pattern* GraphicsContext::fillPattern() const
+{
+    return m_common->state.fillPattern.get();
+}
+
+Pattern* GraphicsContext::strokePattern() const
+{
+    return m_common->state.strokePattern.get();
+}
+
 void GraphicsContext::setShadowsIgnoreTransforms(bool ignoreTransforms)
 {
     m_common->state.shadowsIgnoreTransforms = ignoreTransforms;
index 8027d3b392c29e7592ff8406d62df92b88c1a3e3..15b25af0e2d97c9c72a023b25b4d80a579632f18 100644 (file)
@@ -138,15 +138,24 @@ namespace WebCore {
         void setStrokeStyle(const StrokeStyle& style);
         Color strokeColor() const;
         void setStrokeColor(const Color&);
+
         void setStrokePattern(PassRefPtr<Pattern>);
+        Pattern* strokePattern() const;
+
         void setStrokeGradient(PassRefPtr<Gradient>);
+        Gradient* strokeGradient() const;
 
         WindRule fillRule() const;
         void setFillRule(WindRule);
         Color fillColor() const;
         void setFillColor(const Color&);
+
         void setFillPattern(PassRefPtr<Pattern>);
+        Pattern* fillPattern() const;
+
         void setFillGradient(PassRefPtr<Gradient>);
+        Gradient* fillGradient() const;
+
         void setShadowsIgnoreTransforms(bool);
 
         void setShouldAntialias(bool);
@@ -357,3 +366,4 @@ namespace WebCore {
 } // namespace WebCore
 
 #endif // GraphicsContext_h
+
index d5626a44b56ddcd1acbd0ee8fb931469991139c9..db4f3b2ea9cd01c27796ff4b761223ff923f7b66 100644 (file)
@@ -131,7 +131,7 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext,
                 // Skia's text drawing origin is the baseline, like WebKit, not
                 // the top, like Windows.
                 SkPoint origin = { x, point.y() };
-                success = paintSkiaText(context, font->platformData().hfont(),
+                success = paintSkiaText(graphicsContext, font->platformData().hfont(),
                         numGlyphs, reinterpret_cast<const WORD*>(&glyphs[0]),
                         &advances[0], 0, &origin);
             }
index e8a3cd2959d87d28b4e88e9f61c57d0265b9b07a..39b08479c5f3b1ca9e2f7828f283120f5437d962 100644 (file)
@@ -297,7 +297,6 @@ void UniscribeHelper::draw(GraphicsContext* graphicsContext,
     int curX = x;
     bool firstRun = true;
     bool useWindowsDrawing = windowsCanHandleTextDrawing(graphicsContext);
-    PlatformGraphicsContext* context = graphicsContext->platformContext();
 
     for (size_t screenIndex = 0; screenIndex < m_runs.size(); screenIndex++) {
         int itemIndex = m_screenOrder[screenIndex];
@@ -403,7 +402,7 @@ void UniscribeHelper::draw(GraphicsContext* graphicsContext,
                     SkPoint origin;
                     origin.fX = curX + + innerOffset;
                     origin.fY = y + m_ascent - shaping.m_ascentOffset;
-                    textOutOk = paintSkiaText(context,
+                    textOutOk = paintSkiaText(graphicsContext,
                                               shaping.m_hfont,
                                               glyphCount,
                                               &shaping.m_glyphs[fromGlyph],
index 5a387e5c9dea8cb0f422825952f8ba2bc014d129..50ac9df8360dfddf026f5ce7ac01381402a43c1d 100644 (file)
 #include "SkiaFontWin.h"
 
 #include "PlatformContextSkia.h"
+#include "Gradient.h"
+#include "Pattern.h"
 #include "SkCanvas.h"
 #include "SkPaint.h"
+#include "SkShader.h"
 #include "TransformationMatrix.h"
 
 #include <wtf/ListHashSet.h>
@@ -232,6 +235,14 @@ bool windowsCanHandleTextDrawing(GraphicsContext* context)
     if (context->platformContext()->getTextDrawingMode() != cTextFill)
         return false;
 
+    // Check for gradients.
+    if (context->fillGradient() || context->strokeGradient())
+        return false;
+
+    // Check for patterns.
+    if (context->fillPattern() || context->strokePattern())
+        return false;
+
     // Check for shadow effects.
     if (context->platformContext()->getDrawLooper())
         return false;
@@ -239,45 +250,70 @@ bool windowsCanHandleTextDrawing(GraphicsContext* context)
     return true;
 }
 
+// Draws the given text string using skia.  Note that gradient or
+// pattern may be NULL, in which case a solid colour is used.
 static bool skiaDrawText(HFONT hfont,
                          HDC dc,
                          SkCanvas* canvas,
                          const SkPoint& point,
                          SkPaint* paint,
+                         const TransformationMatrix& transformationMatrix,
+                         Gradient* gradient,
+                         Pattern* pattern,
                          const WORD* glyphs,
                          const int* advances,
                          const GOFFSET* offsets,
                          int numGlyphs)
 {
-    canvas->save();
-    canvas->translate(point.fX, point.fY);
+    SkShader* shader = NULL;
+    SkMatrix oldShaderMatrix;
+    if (gradient) {
+        shader = gradient->platformGradient();
+        // Get the length of the string in pixels.
+        int width = 0;
+        for (int i = 0; i < numGlyphs; i++)
+            width += advances[i];
+
+        // Save the current shader matrix.
+        shader->getLocalMatrix(&oldShaderMatrix);
+
+        // Scale up the gradient matrix by the width of the text string.
+        SkMatrix shaderMatrix(oldShaderMatrix);
+        shaderMatrix.postScale(static_cast<float>(width), 1.0f);
+        shaderMatrix.postTranslate(point.fX, point.fY);
+        shader->setLocalMatrix(shaderMatrix);
+    } else if (pattern)
+        shader = pattern->createPlatformPattern(transformationMatrix);
+
+    paint->setShader(shader);
+    float x = point.fX, y = point.fY;
 
     for (int i = 0; i < numGlyphs; i++) {
         const SkPath* path = SkiaWinOutlineCache::lookupOrCreatePathForGlyph(dc, hfont, glyphs[i]);
         if (!path)
             return false;
 
-        bool offset = false;
+        float offsetX = 0.0f, offsetY = 0.0f;
         if (offsets && (offsets[i].du != 0 || offsets[i].dv != 0)) {
-            offset = true;
-            canvas->translate(offsets[i].du, offsets[i].dv);
+            offsetX = offsets[i].du;
+            offsetY = offsets[i].dv;
         }
 
-        canvas->drawPath(*path, *paint);
+        SkPath newPath;
+        newPath.addPath(*path, x + offsetX, y + offsetY);
+        canvas->drawPath(newPath, *paint);
         
-        if (offset) {
-            canvas->translate(advances[i] - offsets[i].du, -offsets[i].dv);
-        } else {
-            canvas->translate(advances[i], 0);
-        }
+        x += advances[i];
     }
 
-    canvas->restore();
+    // Restore the previous shader matrix.
+    if (gradient)
+        shader->setLocalMatrix(oldShaderMatrix);
 
     return true;
 }
 
-bool paintSkiaText(PlatformContextSkia* platformContext,
+bool paintSkiaText(GraphicsContext* context,
                    HFONT hfont,
                    int numGlyphs,
                    const WORD* glyphs,
@@ -288,6 +324,7 @@ bool paintSkiaText(PlatformContextSkia* platformContext,
     HDC dc = GetDC(0);
     HGDIOBJ oldFont = SelectObject(dc, hfont);
 
+    PlatformContextSkia* platformContext = context->platformContext();
     int textMode = platformContext->getTextDrawingMode();
 
     // Filling (if necessary). This is the common case.
@@ -298,7 +335,9 @@ bool paintSkiaText(PlatformContextSkia* platformContext,
 
     if ((textMode & cTextFill) && SkColorGetA(paint.getColor())) {
         if (!skiaDrawText(hfont, dc, platformContext->canvas(), *origin, &paint,
-                          &glyphs[0], &advances[0], &offsets[0], numGlyphs))
+                          context->getCTM(), context->fillGradient(),
+                          context->fillPattern(), &glyphs[0], &advances[0],
+                          &offsets[0], numGlyphs))
             return false;
         didFill = true;
     }
@@ -325,7 +364,9 @@ bool paintSkiaText(PlatformContextSkia* platformContext,
         }
 
         if (!skiaDrawText(hfont, dc, platformContext->canvas(), *origin, &paint,
-                          &glyphs[0], &advances[0], &offsets[0], numGlyphs))
+                          context->getCTM(), context->strokeGradient(),
+                          context->strokePattern(), &glyphs[0], &advances[0],
+                          &offsets[0], numGlyphs))
             return false;
     }
 
index 5d118beee0520d873467ea3aaae3aa4a90f472d8..0e0c95391528bd44e7b8fe0a45b9bc6ab8b62660 100644 (file)
@@ -76,7 +76,7 @@ bool windowsCanHandleTextDrawing(GraphicsContext* context);
 //
 // Returns true of the text was drawn successfully. False indicates an error
 // from Windows.
-bool paintSkiaText(PlatformContextSkia* platformContext,
+bool paintSkiaText(GraphicsContext* graphicsContext,
                    HFONT hfont,
                    int numGlyphs,
                    const WORD* glyphs,