KHTML
SVGGradientElement.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "config.h"
00024 #include "wtf/Platform.h"
00025
00026 #if ENABLE(SVG)
00027 #include "SVGGradientElement.h"
00028
00029 #include "CSSStyleSelector.h"
00030 #include "RenderPath.h"
00031 #include "RenderSVGHiddenContainer.h"
00032 #include "SVGNames.h"
00033 #include "SVGPaintServerLinearGradient.h"
00034 #include "SVGPaintServerRadialGradient.h"
00035 #include "SVGStopElement.h"
00036 #include "SVGTransformList.h"
00037 #include "SVGTransformable.h"
00038 #include "SVGUnitTypes.h"
00039
00040 namespace WebCore {
00041
00042 SVGGradientElement::SVGGradientElement(const QualifiedName& tagName, Document* doc)
00043 : SVGStyledElement(tagName, doc)
00044 , SVGURIReference()
00045 , SVGExternalResourcesRequired()
00046 , m_spreadMethod(0)
00047 , m_gradientUnits(SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
00048 , m_gradientTransform(SVGTransformList::create(SVGNames::gradientTransformAttr))
00049 {
00050 }
00051
00052 SVGGradientElement::~SVGGradientElement()
00053 {
00054 }
00055
00056 ANIMATED_PROPERTY_DEFINITIONS(SVGGradientElement, int, Enumeration, enumeration, GradientUnits, gradientUnits, SVGNames::gradientUnitsAttr, m_gradientUnits)
00057 ANIMATED_PROPERTY_DEFINITIONS(SVGGradientElement, SVGTransformList*, TransformList, transformList, GradientTransform, gradientTransform, SVGNames::gradientTransformAttr, m_gradientTransform.get())
00058 ANIMATED_PROPERTY_DEFINITIONS(SVGGradientElement, int, Enumeration, enumeration, SpreadMethod, spreadMethod, SVGNames::spreadMethodAttr, m_spreadMethod)
00059
00060 void SVGGradientElement::parseMappedAttribute(MappedAttribute* attr)
00061 {
00062 if (attr->name() == SVGNames::gradientUnitsAttr) {
00063 if (attr->value() == "userSpaceOnUse")
00064 setGradientUnitsBaseValue(SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE);
00065 else if (attr->value() == "objectBoundingBox")
00066 setGradientUnitsBaseValue(SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
00067 } else if (attr->name() == SVGNames::gradientTransformAttr) {
00068 SVGTransformList* gradientTransforms = gradientTransformBaseValue();
00069 if (!SVGTransformable::parseTransformAttribute(gradientTransforms, attr->value())) {
00070 ExceptionCode ec = 0;
00071 gradientTransforms->clear(ec);
00072 }
00073 } else if (attr->name() == SVGNames::spreadMethodAttr) {
00074 if (attr->value() == "reflect")
00075 setSpreadMethodBaseValue(SVG_SPREADMETHOD_REFLECT);
00076 else if (attr->value() == "repeat")
00077 setSpreadMethodBaseValue(SVG_SPREADMETHOD_REPEAT);
00078 else if (attr->value() == "pad")
00079 setSpreadMethodBaseValue(SVG_SPREADMETHOD_PAD);
00080 } else {
00081 if (SVGURIReference::parseMappedAttribute(attr))
00082 return;
00083 if (SVGExternalResourcesRequired::parseMappedAttribute(attr))
00084 return;
00085
00086 SVGStyledElement::parseMappedAttribute(attr);
00087 }
00088 }
00089
00090 void SVGGradientElement::svgAttributeChanged(const QualifiedName& attrName)
00091 {
00092 SVGStyledElement::svgAttributeChanged(attrName);
00093
00094 if (!m_resource)
00095 return;
00096
00097 if (attrName == SVGNames::gradientUnitsAttr ||
00098 attrName == SVGNames::gradientTransformAttr ||
00099 attrName == SVGNames::spreadMethodAttr ||
00100 SVGURIReference::isKnownAttribute(attrName) ||
00101 SVGExternalResourcesRequired::isKnownAttribute(attrName) ||
00102 SVGStyledElement::isKnownAttribute(attrName))
00103 m_resource->invalidate();
00104 }
00105
00106 void SVGGradientElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
00107 {
00108 SVGStyledElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
00109
00110 if (m_resource)
00111 m_resource->invalidate();
00112 }
00113
00114 RenderObject* SVGGradientElement::createRenderer(RenderArena* arena, RenderStyle*)
00115 {
00116 return new (arena) RenderSVGHiddenContainer(this);
00117 }
00118
00119 SVGResource* SVGGradientElement::canvasResource()
00120 {
00121 kDebug() << "request gradient paint server" << endl;
00122 if (!m_resource) {
00123 if (gradientType() == LinearGradientPaintServer)
00124 m_resource = SVGPaintServerLinearGradient::create(this);
00125 else
00126 m_resource = SVGPaintServerRadialGradient::create(this);
00127 }
00128
00129 return m_resource.get();
00130 }
00131
00132 Vector<SVGGradientStop> SVGGradientElement::buildStops() const
00133 {
00134 Vector<SVGGradientStop> stops;
00135 RenderStyle* gradientStyle = 0;
00136
00137 for (Node* n = firstChild(); n; n = n->nextSibling()) {
00138 SVGElement* element = n->isSVGElement() ? static_cast<SVGElement*>(n) : 0;
00139
00140 if (element && element->isGradientStop()) {
00141 SVGStopElement* stop = static_cast<SVGStopElement*>(element);
00142 float stopOffset = stop->offset();
00143
00144 Color color;
00145 float opacity;
00146
00147 if (stop->renderer()) {
00148 RenderStyle* stopStyle = stop->renderer()->style();
00149 color = stopStyle->svgStyle()->stopColor();
00150 opacity = stopStyle->svgStyle()->stopOpacity();
00151 } else {
00152
00153
00154
00155 if (!gradientStyle)
00156 gradientStyle = const_cast<SVGGradientElement*>(this)->styleForRenderer(parent()->renderer());
00157
00158 RenderStyle* stopStyle = stop->resolveStyle(gradientStyle);
00159
00160 color = stopStyle->svgStyle()->stopColor();
00161 opacity = stopStyle->svgStyle()->stopOpacity();
00162
00163
00164 }
00165
00166 stops.append(makeGradientStop(stopOffset, qRgba(color.red(), color.green(), color.blue(), int(opacity * 255.))));
00167 }
00168 }
00169
00170
00171
00172
00173 return stops;
00174 }
00175
00176 }
00177
00178 #endif // ENABLE(SVG)