bool SVGLinearGradientElement::collectGradientAttributes(LinearGradientAttributes& attributes) { if (!renderer()) return false; HashSet<SVGGradientElement*> processedGradients; SVGGradientElement* current = this; setGradientAttributes(*current, attributes); processedGradients.add(current); while (true) { // Respect xlink:href, take attributes from referenced element Node* refNode = SVGURIReference::targetElementFromIRIString(current->href(), document()); if (is<SVGGradientElement>(refNode)) { current = downcast<SVGGradientElement>(refNode); // Cycle detection if (processedGradients.contains(current)) return true; if (!current->renderer()) return false; setGradientAttributes(*current, attributes, current->hasTagName(SVGNames::linearGradientTag)); processedGradients.add(current); } else return true; } ASSERT_NOT_REACHED(); return false; }
LinearGradientAttributes SVGLinearGradientElement::collectGradientProperties() { LinearGradientAttributes attributes; HashSet<SVGGradientElement*> processedGradients; bool isLinear = true; SVGGradientElement* current = this; while (current) { if (!attributes.hasSpreadMethod() && current->hasAttribute(SVGNames::spreadMethodAttr)) attributes.setSpreadMethod((GradientSpreadMethod) current->spreadMethod()); if (!attributes.hasBoundingBoxMode() && current->hasAttribute(SVGNames::gradientUnitsAttr)) attributes.setBoundingBoxMode(current->gradientUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX); if (!attributes.hasGradientTransform() && current->hasAttribute(SVGNames::gradientTransformAttr)) attributes.setGradientTransform(current->gradientTransform()->consolidate().matrix()); if (!attributes.hasStops()) { const Vector<Gradient::ColorStop>& stops(current->buildStops()); if (!stops.isEmpty()) attributes.setStops(stops); } if (isLinear) { SVGLinearGradientElement* linear = static_cast<SVGLinearGradientElement*>(current); if (!attributes.hasX1() && current->hasAttribute(SVGNames::x1Attr)) attributes.setX1(linear->x1()); if (!attributes.hasY1() && current->hasAttribute(SVGNames::y1Attr)) attributes.setY1(linear->y1()); if (!attributes.hasX2() && current->hasAttribute(SVGNames::x2Attr)) attributes.setX2(linear->x2()); if (!attributes.hasY2() && current->hasAttribute(SVGNames::y2Attr)) attributes.setY2(linear->y2()); } processedGradients.add(current); // Respect xlink:href, take attributes from referenced element Node* refNode = ownerDocument()->getElementById(SVGURIReference::getTarget(current->href())); if (refNode && (refNode->hasTagName(SVGNames::linearGradientTag) || refNode->hasTagName(SVGNames::radialGradientTag))) { current = static_cast<SVGGradientElement*>(refNode); // Cycle detection if (processedGradients.contains(current)) return LinearGradientAttributes(); isLinear = current->hasTagName(SVGNames::linearGradientTag); } else current = 0; } return attributes; }
bool SVGRadialGradientElement::collectGradientAttributes(RadialGradientAttributes& attributes) { if (!renderer()) return false; HashSet<SVGGradientElement*> processedGradients; SVGGradientElement* current = this; setGradientAttributes(*current, attributes); processedGradients.add(current); while (true) { // Respect xlink:href, take attributes from referenced element Node* refNode = SVGURIReference::targetElementFromIRIString(current->href(), document()); if (is<SVGGradientElement>(refNode)) { current = downcast<SVGGradientElement>(refNode); // Cycle detection if (processedGradients.contains(current)) break; if (!current->renderer()) return false; setGradientAttributes(*current, attributes, current->hasTagName(SVGNames::radialGradientTag)); processedGradients.add(current); } else break; } // Handle default values for fx/fy if (!attributes.hasFx()) attributes.setFx(attributes.cx()); if (!attributes.hasFy()) attributes.setFy(attributes.cy()); return true; }