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 "SVGLinearGradientElement.h"
00028
00029 #include "FloatPoint.h"
00030 #include "LinearGradientAttributes.h"
00031 #include "SVGLength.h"
00032 #include "SVGNames.h"
00033 #include "SVGPaintServerLinearGradient.h"
00034 #include "SVGTransform.h"
00035 #include "SVGTransformList.h"
00036 #include "SVGUnitTypes.h"
00037
00038 namespace WebCore {
00039
00040 SVGLinearGradientElement::SVGLinearGradientElement(const QualifiedName& tagName, Document* doc)
00041 : SVGGradientElement(tagName, doc)
00042 , m_x1(this, LengthModeWidth)
00043 , m_y1(this, LengthModeHeight)
00044 , m_x2(this, LengthModeWidth)
00045 , m_y2(this, LengthModeHeight)
00046 {
00047
00048 setX2BaseValue(SVGLength(this, LengthModeWidth, "100%"));
00049 }
00050
00051 SVGLinearGradientElement::~SVGLinearGradientElement()
00052 {
00053 }
00054
00055 ANIMATED_PROPERTY_DEFINITIONS(SVGLinearGradientElement, SVGLength, Length, length, X1, x1, SVGNames::x1Attr, m_x1)
00056 ANIMATED_PROPERTY_DEFINITIONS(SVGLinearGradientElement, SVGLength, Length, length, Y1, y1, SVGNames::y1Attr, m_y1)
00057 ANIMATED_PROPERTY_DEFINITIONS(SVGLinearGradientElement, SVGLength, Length, length, X2, x2, SVGNames::x2Attr, m_x2)
00058 ANIMATED_PROPERTY_DEFINITIONS(SVGLinearGradientElement, SVGLength, Length, length, Y2, y2, SVGNames::y2Attr, m_y2)
00059
00060 void SVGLinearGradientElement::parseMappedAttribute(MappedAttribute* attr)
00061 {
00062 if (attr->name() == SVGNames::x1Attr)
00063 setX1BaseValue(SVGLength(this, LengthModeWidth, attr->value()));
00064 else if (attr->name() == SVGNames::y1Attr)
00065 setY1BaseValue(SVGLength(this, LengthModeHeight, attr->value()));
00066 else if (attr->name() == SVGNames::x2Attr)
00067 setX2BaseValue(SVGLength(this, LengthModeWidth, attr->value()));
00068 else if (attr->name() == SVGNames::y2Attr)
00069 setY2BaseValue(SVGLength(this, LengthModeHeight, attr->value()));
00070 else
00071 SVGGradientElement::parseMappedAttribute(attr);
00072 }
00073
00074 void SVGLinearGradientElement::svgAttributeChanged(const QualifiedName& attrName)
00075 {
00076 SVGGradientElement::svgAttributeChanged(attrName);
00077
00078 if (!m_resource)
00079 return;
00080
00081 if (attrName == SVGNames::x1Attr || attrName == SVGNames::y1Attr ||
00082 attrName == SVGNames::x2Attr || attrName == SVGNames::y2Attr)
00083 m_resource->invalidate();
00084 }
00085
00086 void SVGLinearGradientElement::buildGradient() const
00087 {
00088 LinearGradientAttributes attributes = collectGradientProperties();
00089
00090
00091 if (attributes.stops().isEmpty())
00092 return;
00093
00094 RefPtr<SVGPaintServerLinearGradient> linearGradient = WTF::static_pointer_cast<SVGPaintServerLinearGradient>(m_resource);
00095
00096 linearGradient->setGradientStops(attributes.stops());
00097 linearGradient->setBoundingBoxMode(attributes.boundingBoxMode());
00098 linearGradient->setGradientSpreadMethod(attributes.spreadMethod());
00099 linearGradient->setGradientTransform(attributes.gradientTransform());
00100 linearGradient->setGradientStart(FloatPoint::narrowPrecision(attributes.x1(), attributes.y1()));
00101 linearGradient->setGradientEnd(FloatPoint::narrowPrecision(attributes.x2(), attributes.y2()));
00102 }
00103
00104 LinearGradientAttributes SVGLinearGradientElement::collectGradientProperties() const
00105 {
00106 LinearGradientAttributes attributes;
00107 HashSet<const SVGGradientElement*> processedGradients;
00108
00109 bool isLinear = true;
00110 const SVGGradientElement* current = this;
00111
00112 while (current) {
00113 if (!attributes.hasSpreadMethod() && current->hasAttribute(SVGNames::spreadMethodAttr))
00114 attributes.setSpreadMethod((SVGGradientSpreadMethod) current->spreadMethod());
00115
00116 if (!attributes.hasBoundingBoxMode() && current->hasAttribute(SVGNames::gradientUnitsAttr))
00117 attributes.setBoundingBoxMode(current->getAttribute(SVGNames::gradientUnitsAttr) == "objectBoundingBox");
00118
00119 if (!attributes.hasGradientTransform() && current->hasAttribute(SVGNames::gradientTransformAttr))
00120 attributes.setGradientTransform(current->gradientTransform()->consolidate().matrix());
00121
00122 if (!attributes.hasStops()) {
00123 const Vector<SVGGradientStop>& stops(current->buildStops());
00124 kDebug() << "stops.isEmpty()" << stops.isEmpty() << endl;
00125 if (!stops.isEmpty())
00126 attributes.setStops(stops);
00127 }
00128
00129 if (isLinear) {
00130 const SVGLinearGradientElement* linear = static_cast<const SVGLinearGradientElement*>(current);
00131
00132 if (!attributes.hasX1() && current->hasAttribute(SVGNames::x1Attr))
00133 attributes.setX1(linear->x1().valueAsPercentage());
00134
00135 if (!attributes.hasY1() && current->hasAttribute(SVGNames::y1Attr))
00136 attributes.setY1(linear->y1().valueAsPercentage());
00137
00138 if (!attributes.hasX2() && current->hasAttribute(SVGNames::x2Attr))
00139 attributes.setX2(linear->x2().valueAsPercentage());
00140
00141 if (!attributes.hasY2() && current->hasAttribute(SVGNames::y2Attr))
00142 attributes.setY2(linear->y2().valueAsPercentage());
00143 }
00144
00145 processedGradients.add(current);
00146
00147
00148 Node* refNode = ownerDocument()->getElementById(SVGURIReference::getTarget(current->href()));
00149 if (refNode && (refNode->hasTagName(SVGNames::linearGradientTag) || refNode->hasTagName(SVGNames::radialGradientTag))) {
00150 current = static_cast<const SVGGradientElement*>(const_cast<const Node*>(refNode));
00151 int ec;
00152 kDebug() << "take attributes from" << current->getAttributeNS("", "id", ec) << endl;
00153
00154
00155 if (processedGradients.contains(current))
00156 return LinearGradientAttributes();
00157
00158 isLinear = current->gradientType() == LinearGradientPaintServer;
00159 } else
00160 current = 0;
00161 }
00162
00163 return attributes;
00164 }
00165
00166
00167 quint32 SVGLinearGradientElement::id() const
00168 {
00169 return SVGNames::linearGradientTag.id();
00170 }
00171
00172 }
00173
00174 #endif // ENABLE(SVG)