+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.
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);
} // namespace WebCore
#endif // GraphicsContext_h
+
#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>
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;
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,
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.
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;
}
}
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;
}