Reviewed by Nikolas Zimmermann.
https://bugs.webkit.org/show_bug.cgi?id=23435
Make spreadMethod a member of Gradient rather than GraphicsContext.
Implement spreadMethod for Skia.
* platform/graphics/Gradient.cpp:
(WebCore::Gradient::Gradient):
* platform/graphics/Gradient.h:
(WebCore::Gradient::setSpreadMethod):
(WebCore::Gradient::spreadMethod):
* platform/graphics/GraphicsContext.cpp:
* platform/graphics/GraphicsContext.h:
* platform/graphics/GraphicsContextPrivate.h:
* platform/graphics/GraphicsTypes.h:
(WebCore::):
* platform/graphics/cairo/GradientCairo.cpp:
(WebCore::Gradient::platformGradient):
* platform/graphics/cairo/GraphicsContextCairo.cpp:
(WebCore::GraphicsContext::fillPath):
(WebCore::GraphicsContext::strokePath):
* platform/graphics/qt/GradientQt.cpp:
(WebCore::Gradient::platformGradient):
* platform/graphics/qt/GraphicsContextQt.cpp:
(WebCore::GraphicsContext::fillPath):
(WebCore::GraphicsContext::strokePath):
* platform/graphics/skia/GradientSkia.cpp:
(WebCore::Gradient::platformGradient):
* svg/SVGLinearGradientElement.cpp:
(WebCore::SVGLinearGradientElement::buildGradient):
* svg/SVGRadialGradientElement.cpp:
(WebCore::SVGRadialGradientElement::buildGradient):
* svg/graphics/SVGPaintServerGradient.cpp:
(WebCore::SVGPaintServerGradient::SVGPaintServerGradient):
(WebCore::SVGPaintServerGradient::setup):
(WebCore::SVGPaintServerGradient::externalRepresentation):
* svg/graphics/SVGPaintServerGradient.h:
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@40292
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2009-01-27 Evan Stade <estade@chromium.org>
+
+ Reviewed by Nikolas Zimmermann.
+
+ https://bugs.webkit.org/show_bug.cgi?id=23435
+ Make spreadMethod a member of Gradient rather than GraphicsContext.
+ Implement spreadMethod for Skia.
+
+ * platform/graphics/Gradient.cpp:
+ (WebCore::Gradient::Gradient):
+ * platform/graphics/Gradient.h:
+ (WebCore::Gradient::setSpreadMethod):
+ (WebCore::Gradient::spreadMethod):
+ * platform/graphics/GraphicsContext.cpp:
+ * platform/graphics/GraphicsContext.h:
+ * platform/graphics/GraphicsContextPrivate.h:
+ * platform/graphics/GraphicsTypes.h:
+ (WebCore::):
+ * platform/graphics/cairo/GradientCairo.cpp:
+ (WebCore::Gradient::platformGradient):
+ * platform/graphics/cairo/GraphicsContextCairo.cpp:
+ (WebCore::GraphicsContext::fillPath):
+ (WebCore::GraphicsContext::strokePath):
+ * platform/graphics/qt/GradientQt.cpp:
+ (WebCore::Gradient::platformGradient):
+ * platform/graphics/qt/GraphicsContextQt.cpp:
+ (WebCore::GraphicsContext::fillPath):
+ (WebCore::GraphicsContext::strokePath):
+ * platform/graphics/skia/GradientSkia.cpp:
+ (WebCore::Gradient::platformGradient):
+ * svg/SVGLinearGradientElement.cpp:
+ (WebCore::SVGLinearGradientElement::buildGradient):
+ * svg/SVGRadialGradientElement.cpp:
+ (WebCore::SVGRadialGradientElement::buildGradient):
+ * svg/graphics/SVGPaintServerGradient.cpp:
+ (WebCore::SVGPaintServerGradient::SVGPaintServerGradient):
+ (WebCore::SVGPaintServerGradient::setup):
+ (WebCore::SVGPaintServerGradient::externalRepresentation):
+ * svg/graphics/SVGPaintServerGradient.h:
+
2009-01-27 Ariya Hidayat <ariya.hidayat@trolltech.com>
Rubber-stamped by Simon Hausmann.
, m_r1(0)
, m_stopsSorted(false)
, m_lastStop(0)
+ , m_spreadMethod(SpreadMethodPad)
{
platformInit();
}
return m_lastStop;
}
+GradientSpreadMethod Gradient::setSpreadMethod(GradientSpreadMethod spreadMethod)
+{
+ // FIXME: Should it become necessary, allow calls to this method after m_gradient has been set.
+ ASSERT(m_gradient == 0);
+ m_spreadMethod = spreadMethod;
+}
+
} //namespace
#include "FloatPoint.h"
#include "Generator.h"
+#include "GraphicsTypes.h"
#include <wtf/PassRefPtr.h>
#include <wtf/Vector.h>
void setStopsSorted(bool s) { m_stopsSorted = s; }
+ void setSpreadMethod(GradientSpreadMethod);
+ GradientSpreadMethod spreadMethod() { return m_spreadMethod; }
+
virtual void fill(GraphicsContext*, const FloatRect&);
private:
mutable Vector<ColorStop> m_stops;
mutable bool m_stopsSorted;
mutable int m_lastStop;
+ GradientSpreadMethod m_spreadMethod;
PlatformGradient m_gradient;
};
m_common->state.fillRule = fillRule;
}
-GradientSpreadMethod GraphicsContext::spreadMethod() const
-{
- return m_common->state.spreadMethod;
-}
-
-void GraphicsContext::setSpreadMethod(GradientSpreadMethod spreadMethod)
-{
- m_common->state.spreadMethod = spreadMethod;
-}
-
void GraphicsContext::setFillColor(const Color& color)
{
m_common->state.fillColorSpace = SolidColorSpace;
InterpolationHigh
};
- // FIXME: Currently these constants have to match the values used in the SVG
- // DOM API. That's a mistake. We need to make cut that dependency.
- enum GradientSpreadMethod {
- SpreadMethodPad = 1,
- SpreadMethodReflect = 2,
- SpreadMethodRepeat = 3
- };
-
class GraphicsContext : Noncopyable {
public:
GraphicsContext(PlatformGraphicsContext*);
WindRule fillRule() const;
void setFillRule(WindRule);
- GradientSpreadMethod spreadMethod() const;
- void setSpreadMethod(GradientSpreadMethod);
Color fillColor() const;
void setFillColor(const Color&);
void setFillPattern(PassRefPtr<Pattern>);
RefPtr<Pattern> strokePattern;
WindRule fillRule;
- GradientSpreadMethod spreadMethod;
ColorSpace fillColorSpace;
Color fillColor;
RefPtr<Gradient> fillGradient;
CompositePlusLighter
};
+ // FIXME: Currently these constants have to match the values used in the SVG
+ // DOM API. That's a mistake. We need to make cut that dependency.
+ enum GradientSpreadMethod {
+ SpreadMethodPad = 1,
+ SpreadMethodReflect = 2,
+ SpreadMethodRepeat = 3
+ };
+
enum LineCap { ButtCap, RoundCap, SquareCap };
enum LineJoin { MiterJoin, RoundJoin, BevelJoin };
++stopIterator;
}
+ switch (m_spreadMethod) {
+ case SpreadMethodPad:
+ cairo_pattern_set_extend(m_gradient, CAIRO_EXTEND_PAD);
+ break;
+ case SpreadMethodReflect:
+ cairo_pattern_set_extend(m_gradient, CAIRO_EXTEND_REFLECT);
+ break;
+ case SpreadMethodRepeat:
+ cairo_pattern_set_extend(m_gradient, CAIRO_EXTEND_REPEAT);
+ break;
+ }
+
return m_gradient;
}
cairo_fill(cr);
}
-static inline cairo_pattern_t* applySpreadMethod(cairo_pattern_t* pattern, GradientSpreadMethod spreadMethod)
-{
- switch (spreadMethod) {
- case SpreadMethodPad:
- cairo_pattern_set_extend(pattern, CAIRO_EXTEND_PAD);
- break;
- case SpreadMethodReflect:
- cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REFLECT);
- break;
- case SpreadMethodRepeat:
- cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
- break;
- }
- return pattern;
-}
-
GraphicsContext::GraphicsContext(PlatformGraphicsContext* cr)
: m_common(createGraphicsContextPrivate())
, m_data(new GraphicsContextPlatformPrivate)
}
case GradientColorSpace:
cairo_pattern_t* pattern = m_common->state.fillGradient->platformGradient();
- pattern = applySpreadMethod(pattern, spreadMethod());
cairo_set_source(cr, pattern);
cairo_clip(cr);
cairo_paint_with_alpha(cr, m_common->state.globalAlpha);
}
case GradientColorSpace:
cairo_pattern_t* pattern = m_common->state.strokeGradient->platformGradient();
- pattern = applySpreadMethod(pattern, spreadMethod());
cairo_set_source(cr, pattern);
if (m_common->state.globalAlpha < 1.0f) {
cairo_push_group(cr);
++stopIterator;
}
+ switch(m_spreadMethod) {
+ case SpreadMethodPad:
+ m_gradient->setSpread(QGradient::PadSpread);
+ break;
+ case SpreadMethodReflect:
+ m_gradient->setSpread(QGradient::ReflectSpread);
+ break;
+ case SpreadMethodRepeat:
+ m_gradient->setSpread(QGradient::RepeatSpread);
+ break;
+ }
+
return m_gradient;
}
return Qt::NoPen;
}
-static inline QGradient applySpreadMethod(QGradient gradient, GradientSpreadMethod spreadMethod)
-{
- switch (spreadMethod) {
- case SpreadMethodPad:
- gradient.setSpread(QGradient::PadSpread);
- break;
- case SpreadMethodReflect:
- gradient.setSpread(QGradient::ReflectSpread);
- break;
- case SpreadMethodRepeat:
- gradient.setSpread(QGradient::RepeatSpread);
- break;
- }
- return gradient;
-}
-
struct TransparencyLayer
{
TransparencyLayer(const QPainter* p, const QRect &rect)
}
case GradientColorSpace:
QGradient* gradient = m_common->state.fillGradient->platformGradient();
- *gradient = applySpreadMethod(*gradient, spreadMethod());
p->fillPath(path, QBrush(*gradient));
break;
}
}
case GradientColorSpace: {
QGradient* gradient = m_common->state.strokeGradient->platformGradient();
- *gradient = applySpreadMethod(*gradient, spreadMethod());
pen.setBrush(QBrush(*gradient));
p->setPen(pen);
p->strokePath(path, pen);
fillStops(m_stops.data(), m_stops.size(), pos, colors);
+ SkShader::TileMode tile = SkShader::kClamp_TileMode;
+ switch (m_spreadMethod) {
+ case SpreadMethodReflect:
+ tile = SkShader::kMirror_TileMode;
+ break;
+ case SpreadMethodRepeat:
+ tile = SkShader::kRepeat_TileMode;
+ break;
+ case SpreadMethodPad:
+ tile = SkShader::kClamp_TileMode;
+ break;
+ }
+
if (m_radial) {
// FIXME: CSS radial Gradients allow an offset focal point (the
// "start circle"), but skia doesn't seem to support that, so this just
// description of the expected behavior.
m_gradient = SkGradientShader::CreateRadial(m_p1,
WebCoreFloatToSkScalar(m_r1), colors, pos,
- static_cast<int>(countUsed), SkShader::kClamp_TileMode);
+ static_cast<int>(countUsed), tile);
} else {
SkPoint pts[2] = { m_p0, m_p1 };
m_gradient = SkGradientShader::CreateLinear(pts, colors, pos,
- static_cast<int>(countUsed), SkShader::kClamp_TileMode);
+ static_cast<int>(countUsed), tile);
}
return m_gradient;
FloatPoint endPoint = FloatPoint::narrowPrecision(attributes.x2(), attributes.y2());
RefPtr<Gradient> gradient = Gradient::create(startPoint, endPoint);
+ gradient->setSpreadMethod(attributes.spreadMethod());
Vector<SVGGradientStop> m_stops = attributes.stops();
float previousOffset = 0.0f;
linearGradient->setGradientStops(attributes.stops());
// These should possibly be supported on Gradient
- linearGradient->setGradientSpreadMethod(attributes.spreadMethod());
linearGradient->setGradientTransform(attributes.gradientTransform());
linearGradient->setGradientStart(startPoint);
linearGradient->setGradientEnd(endPoint);
0.f, // SVG does not support a "focus radius"
centerPoint,
narrowPrecisionToFloat(attributes.r()));
+ gradient->setSpreadMethod(attributes.spreadMethod());
Vector<SVGGradientStop> stops = attributes.stops();
float previousOffset = 0.0f;
return;
radialGradient->setBoundingBoxMode(attributes.boundingBoxMode());
- radialGradient->setGradientSpreadMethod(attributes.spreadMethod());
radialGradient->setGradientTransform(attributes.gradientTransform());
radialGradient->setGradientCenter(centerPoint);
radialGradient->setGradientFocal(focalPoint);
}
SVGPaintServerGradient::SVGPaintServerGradient(const SVGGradientElement* owner)
- : m_spreadMethod(SpreadMethodPad)
- , m_boundingBoxMode(true)
+ : m_boundingBoxMode(true)
, m_ownerElement(owner)
#if PLATFORM(CG)
m_gradient = gradient;
}
-GradientSpreadMethod SVGPaintServerGradient::spreadMethod() const
-{
- return m_spreadMethod;
-}
-
-void SVGPaintServerGradient::setGradientSpreadMethod(const GradientSpreadMethod& method)
-{
- m_spreadMethod = method;
-}
-
bool SVGPaintServerGradient::boundingBoxMode() const
{
return m_boundingBoxMode;
context->setStrokeThickness(strokeThickness);
}
context->concatCTM(gradientTransform());
- context->setSpreadMethod(spreadMethod());
return true;
}
// abstract, don't stream type
ts << "[stops=" << gradientStops() << "]";
- if (spreadMethod() != SpreadMethodPad)
- ts << "[method=" << spreadMethod() << "]";
+ if (m_gradient->spreadMethod() != SpreadMethodPad)
+ ts << "[method=" << m_gradient->spreadMethod() << "]";
if (!boundingBoxMode())
ts << " [bounding box mode=" << boundingBoxMode() << "]";
if (!gradientTransform().isIdentity())
void setGradient(PassRefPtr<Gradient>);
Gradient* gradient() const;
- GradientSpreadMethod spreadMethod() const;
- void setGradientSpreadMethod(const GradientSpreadMethod&);
-
// Gradient start and end points are percentages when used in boundingBox mode.
// For instance start point with value (0,0) is top-left and end point with
// value (100, 100) is bottom-right. BoundingBox mode is enabled by default.
private:
Vector<SVGGradientStop> m_stops;
RefPtr<Gradient> m_gradient;
- GradientSpreadMethod m_spreadMethod;
bool m_boundingBoxMode;
TransformationMatrix m_gradientTransform;
const SVGGradientElement* m_ownerElement;