static void writeStyle(TextStream& ts, const RenderObject& object) { const RenderStyle* style = object.style(); const SVGRenderStyle* svgStyle = style->svgStyle(); if (!object.localTransform().isIdentity()) writeNameValuePair(ts, "transform", object.localTransform()); writeIfNotDefault(ts, "image rendering", style->imageRendering(), RenderStyle::initialImageRendering()); writeIfNotDefault(ts, "opacity", style->opacity(), RenderStyle::initialOpacity()); if (object.isSVGShape()) { const RenderSVGShape& shape = static_cast<const RenderSVGShape&>(object); ASSERT(shape.node()); ASSERT(shape.node()->isSVGElement()); Color fallbackColor; if (RenderSVGResource* strokePaintingResource = RenderSVGResource::strokePaintingResource(const_cast<RenderSVGShape*>(&shape), shape.style(), fallbackColor)) { TextStreamSeparator s(" "); ts << " [stroke={" << s; writeSVGPaintingResource(ts, strokePaintingResource); SVGLengthContext lengthContext(toSVGElement(shape.node())); double dashOffset = svgStyle->strokeDashOffset().value(lengthContext); double strokeWidth = svgStyle->strokeWidth().value(lengthContext); const Vector<SVGLength>& dashes = svgStyle->strokeDashArray(); DashArray dashArray; const Vector<SVGLength>::const_iterator end = dashes.end(); for (Vector<SVGLength>::const_iterator it = dashes.begin(); it != end; ++it) dashArray.append((*it).value(lengthContext)); writeIfNotDefault(ts, "opacity", svgStyle->strokeOpacity(), 1.0f); writeIfNotDefault(ts, "stroke width", strokeWidth, 1.0); writeIfNotDefault(ts, "miter limit", svgStyle->strokeMiterLimit(), 4.0f); writeIfNotDefault(ts, "line cap", svgStyle->capStyle(), ButtCap); writeIfNotDefault(ts, "line join", svgStyle->joinStyle(), MiterJoin); writeIfNotDefault(ts, "dash offset", dashOffset, 0.0); if (!dashArray.isEmpty()) writeNameValuePair(ts, "dash array", dashArray); ts << "}]"; } if (RenderSVGResource* fillPaintingResource = RenderSVGResource::fillPaintingResource(const_cast<RenderSVGShape*>(&shape), shape.style(), fallbackColor)) { TextStreamSeparator s(" "); ts << " [fill={" << s; writeSVGPaintingResource(ts, fillPaintingResource); writeIfNotDefault(ts, "opacity", svgStyle->fillOpacity(), 1.0f); writeIfNotDefault(ts, "fill rule", svgStyle->fillRule(), RULE_NONZERO); ts << "}]"; } writeIfNotDefault(ts, "clip rule", svgStyle->clipRule(), RULE_NONZERO); } writeIfNotEmpty(ts, "start marker", svgStyle->markerStartResource()); writeIfNotEmpty(ts, "middle marker", svgStyle->markerMidResource()); writeIfNotEmpty(ts, "end marker", svgStyle->markerEndResource()); }
static void writeStyle(TextStream& ts, const RenderObject& object) { const RenderStyle* style = object.style(); const SVGRenderStyle* svgStyle = style->svgStyle(); if (!object.localTransform().isIdentity()) writeNameValuePair(ts, "transform", object.localTransform()); writeIfNotDefault(ts, "image rendering", svgStyle->imageRendering(), SVGRenderStyle::initialImageRendering()); writeIfNotDefault(ts, "opacity", style->opacity(), RenderStyle::initialOpacity()); if (object.isRenderPath()) { const RenderPath& path = static_cast<const RenderPath&>(object); SVGPaintServer* strokePaintServer = SVGPaintServer::strokePaintServer(style, &path); if (strokePaintServer) { TextStreamSeparator s(" "); ts << " [stroke={"; if (strokePaintServer) ts << s << *strokePaintServer; double dashOffset = SVGRenderStyle::cssPrimitiveToLength(&path, svgStyle->strokeDashOffset(), 0.0f); const DashArray& dashArray = dashArrayFromRenderingStyle(style, object.document()->documentElement()->renderStyle()); double strokeWidth = SVGRenderStyle::cssPrimitiveToLength(&path, svgStyle->strokeWidth(), 1.0f); writeIfNotDefault(ts, "opacity", svgStyle->strokeOpacity(), 1.0f); writeIfNotDefault(ts, "stroke width", strokeWidth, 1.0); writeIfNotDefault(ts, "miter limit", svgStyle->strokeMiterLimit(), 4.0f); writeIfNotDefault(ts, "line cap", svgStyle->capStyle(), ButtCap); writeIfNotDefault(ts, "line join", svgStyle->joinStyle(), MiterJoin); writeIfNotDefault(ts, "dash offset", dashOffset, 0.0); if (!dashArray.isEmpty()) writeNameValuePair(ts, "dash array", dashArray); ts << "}]"; } SVGPaintServer* fillPaintServer = SVGPaintServer::fillPaintServer(style, &path); if (fillPaintServer) { TextStreamSeparator s(" "); ts << " [fill={"; if (fillPaintServer) ts << s << *fillPaintServer; writeIfNotDefault(ts, "opacity", svgStyle->fillOpacity(), 1.0f); writeIfNotDefault(ts, "fill rule", svgStyle->fillRule(), RULE_NONZERO); ts << "}]"; } } if (!svgStyle->clipPath().isEmpty()) writeNameAndQuotedValue(ts, "clip path", svgStyle->clipPath()); writeIfNotEmpty(ts, "start marker", svgStyle->startMarker()); writeIfNotEmpty(ts, "middle marker", svgStyle->midMarker()); writeIfNotEmpty(ts, "end marker", svgStyle->endMarker()); writeIfNotEmpty(ts, "filter", svgStyle->filter()); }
static void writeStyle(TextStream& ts, const LayoutObject& object) { const ComputedStyle& style = object.styleRef(); const SVGComputedStyle& svgStyle = style.svgStyle(); if (!object.localTransform().isIdentity()) writeNameValuePair(ts, "transform", object.localTransform()); writeIfNotDefault(ts, "image rendering", style.imageRendering(), ComputedStyle::initialImageRendering()); writeIfNotDefault(ts, "opacity", style.opacity(), ComputedStyle::initialOpacity()); if (object.isSVGShape()) { const LayoutSVGShape& shape = static_cast<const LayoutSVGShape&>(object); ASSERT(shape.element()); SVGPaintDescription strokePaintDescription = LayoutSVGResourcePaintServer::requestPaintDescription(shape, shape.styleRef(), ApplyToStrokeMode); if (strokePaintDescription.isValid) { TextStreamSeparator s(" "); ts << " [stroke={" << s; writeSVGPaintingResource(ts, strokePaintDescription); SVGLengthContext lengthContext(shape.element()); double dashOffset = lengthContext.valueForLength(svgStyle.strokeDashOffset(), style); double strokeWidth = lengthContext.valueForLength(svgStyle.strokeWidth()); DashArray dashArray = SVGLayoutSupport::resolveSVGDashArray(*svgStyle.strokeDashArray(), style, lengthContext); writeIfNotDefault(ts, "opacity", svgStyle.strokeOpacity(), 1.0f); writeIfNotDefault(ts, "stroke width", strokeWidth, 1.0); writeIfNotDefault(ts, "miter limit", svgStyle.strokeMiterLimit(), 4.0f); writeIfNotDefault(ts, "line cap", svgStyle.capStyle(), ButtCap); writeIfNotDefault(ts, "line join", svgStyle.joinStyle(), MiterJoin); writeIfNotDefault(ts, "dash offset", dashOffset, 0.0); if (!dashArray.isEmpty()) writeNameValuePair(ts, "dash array", dashArray); ts << "}]"; } SVGPaintDescription fillPaintDescription = LayoutSVGResourcePaintServer::requestPaintDescription(shape, shape.styleRef(), ApplyToFillMode); if (fillPaintDescription.isValid) { TextStreamSeparator s(" "); ts << " [fill={" << s; writeSVGPaintingResource(ts, fillPaintDescription); writeIfNotDefault(ts, "opacity", svgStyle.fillOpacity(), 1.0f); writeIfNotDefault(ts, "fill rule", svgStyle.fillRule(), RULE_NONZERO); ts << "}]"; } writeIfNotDefault(ts, "clip rule", svgStyle.clipRule(), RULE_NONZERO); } writeIfNotEmpty(ts, "start marker", svgStyle.markerStartResource()); writeIfNotEmpty(ts, "middle marker", svgStyle.markerMidResource()); writeIfNotEmpty(ts, "end marker", svgStyle.markerEndResource()); }
static inline void writeCommonGradientProperties(TextStream& ts, GradientSpreadMethod spreadMethod, const AffineTransform& gradientTransform, bool boundingBoxMode) { writeNameValuePair(ts, "gradientUnits", boundingBoxModeString(boundingBoxMode)); if (spreadMethod != SpreadMethodPad) ts << " [spreadMethod=" << spreadMethod << "]"; if (!gradientTransform.isIdentity()) ts << " [gradientTransform=" << gradientTransform << "]"; }
static inline void writeCommonGradientProperties(TextStream& ts, SVGSpreadMethodType spreadMethod, const AffineTransform& gradientTransform, SVGUnitTypes::SVGUnitType gradientUnits) { writeNameValuePair(ts, "gradientUnits", gradientUnits); if (spreadMethod != SVGSpreadMethodPad) ts << " [spreadMethod=" << spreadMethod << "]"; if (!gradientTransform.isIdentity()) ts << " [gradientTransform=" << gradientTransform << "]"; }
static void writeRenderSVGTextBox(TextStream& ts, const RenderBlock& text) { SVGRootInlineBox* box = static_cast<SVGRootInlineBox*>(text.firstRootBox()); if (!box) return; Vector<SVGTextChunk>& chunks = const_cast<Vector<SVGTextChunk>& >(box->svgTextChunks()); ts << " at (" << text.x() << "," << text.y() << ") size " << box->width() << "x" << box->height() << " contains " << chunks.size() << " chunk(s)"; if (text.parent() && (text.parent()->style()->color() != text.style()->color())) writeNameValuePair(ts, "color", text.style()->color().name()); }
static void writeRenderSVGTextBox(TextStream& ts, const RenderBlock& text) { SVGRootInlineBox* box = static_cast<SVGRootInlineBox*>(text.firstRootBox()); if (!box) return; ts << " at (" << text.x() << "," << text.y() << ") size " << box->logicalWidth() << "x" << box->logicalHeight(); // FIXME: Remove this hack, once the new text layout engine is completly landed. We want to preserve the old layout test results for now. ts << " contains 1 chunk(s)"; if (text.parent() && (text.parent()->style()->visitedDependentColor(CSSPropertyColor) != text.style()->visitedDependentColor(CSSPropertyColor))) writeNameValuePair(ts, "color", text.style()->visitedDependentColor(CSSPropertyColor).name()); }
static void writeRenderSVGTextBox(TextStream& ts, const RenderSVGText& text) { SVGRootInlineBox* box = toSVGRootInlineBox(text.firstRootBox()); if (!box) return; ts << " " << enclosingIntRect(FloatRect(text.location(), FloatSize(box->logicalWidth(), box->logicalHeight()))); // FIXME: Remove this hack, once the new text layout engine is completly landed. We want to preserve the old layout test results for now. ts << " contains 1 chunk(s)"; if (text.parent() && (text.parent()->style()->visitedDependentColor(CSSPropertyColor) != text.style()->visitedDependentColor(CSSPropertyColor))) writeNameValuePair(ts, "color", text.resolveColor(CSSPropertyColor).nameForRenderTreeAsText()); }
void writeSVGResource(TextStream& ts, const RenderObject& object, int indent) { writeStandardPrefix(ts, object, indent); Element* element = static_cast<Element*>(object.node()); const AtomicString& id = element->getIDAttribute(); writeNameAndQuotedValue(ts, "id", id); RenderSVGResource* resource = const_cast<RenderObject&>(object).toRenderSVGResource(); if (resource->resourceType() == MaskerResourceType) { RenderSVGResourceMasker* masker = static_cast<RenderSVGResourceMasker*>(resource); ASSERT(masker); writeNameValuePair(ts, "maskUnits", masker->maskUnits()); writeNameValuePair(ts, "maskContentUnits", masker->maskContentUnits()); } else if (resource->resourceType() == ClipperResourceType) { RenderSVGResourceClipper* clipper = static_cast<RenderSVGResourceClipper*>(resource); ASSERT(clipper); writeNameValuePair(ts, "clipPathUnits", clipper->clipPathUnits()); } // FIXME: Handle other RenderSVGResource* classes here, after converting them from SVGResource*. ts << "\n"; writeChildren(ts, object, indent); }
static void writeRenderSVGTextBox(TextStream& ts, const RenderBlock& text) { SVGRootInlineBox* box = static_cast<SVGRootInlineBox*>(text.firstRootBox()); if (!box) return; // FIXME: For now use an int for logicalWidth, although this makes it harder // to detect any changes caused by the conversion to floating point. :( int logicalWidth = ceilf(box->x() + box->logicalWidth()) - box->x(); ts << " at (" << text.x() << "," << text.y() << ") size " << logicalWidth << "x" << box->logicalHeight(); // FIXME: Remove this hack, once the new text layout engine is completly landed. We want to preserve the old layout test results for now. ts << " contains 1 chunk(s)"; if (text.parent() && (text.parent()->style()->visitedDependentColor(CSSPropertyColor) != text.style()->visitedDependentColor(CSSPropertyColor))) writeNameValuePair(ts, "color", text.style()->visitedDependentColor(CSSPropertyColor).nameForRenderTreeAsText()); }
void writeSVGResourceContainer(TextStream& ts, const RenderObject& object, int indent) { writeStandardPrefix(ts, object, indent); Element* element = toElement(object.node()); const AtomicString& id = element->getIdAttribute(); writeNameAndQuotedValue(ts, "id", id); RenderSVGResourceContainer* resource = const_cast<RenderObject&>(object).toRenderSVGResourceContainer(); ASSERT(resource); if (resource->resourceType() == MaskerResourceType) { RenderSVGResourceMasker* masker = toRenderSVGResourceMasker(resource); writeNameValuePair(ts, "maskUnits", masker->maskUnits()); writeNameValuePair(ts, "maskContentUnits", masker->maskContentUnits()); ts << "\n"; } else if (resource->resourceType() == FilterResourceType) { RenderSVGResourceFilter* filter = toRenderSVGResourceFilter(resource); writeNameValuePair(ts, "filterUnits", filter->filterUnits()); writeNameValuePair(ts, "primitiveUnits", filter->primitiveUnits()); ts << "\n"; // Creating a placeholder filter which is passed to the builder. FloatRect dummyRect; RefPtr<SVGFilter> dummyFilter = SVGFilter::create(AffineTransform(), dummyRect, dummyRect, dummyRect, true); if (RefPtr<SVGFilterBuilder> builder = filter->buildPrimitives(dummyFilter.get())) { if (FilterEffect* lastEffect = builder->lastEffect()) lastEffect->externalRepresentation(ts, indent + 1); } } else if (resource->resourceType() == ClipperResourceType) { writeNameValuePair(ts, "clipPathUnits", toRenderSVGResourceClipper(resource)->clipPathUnits()); ts << "\n"; } else if (resource->resourceType() == MarkerResourceType) { RenderSVGResourceMarker* marker = toRenderSVGResourceMarker(resource); writeNameValuePair(ts, "markerUnits", marker->markerUnits()); ts << " [ref at " << marker->referencePoint() << "]"; ts << " [angle="; if (marker->angle() == -1) ts << "auto" << "]\n"; else ts << marker->angle() << "]\n"; } else if (resource->resourceType() == PatternResourceType) { RenderSVGResourcePattern* pattern = static_cast<RenderSVGResourcePattern*>(resource); // Dump final results that are used for rendering. No use in asking SVGPatternElement for its patternUnits(), as it may // link to other patterns using xlink:href, we need to build the full inheritance chain, aka. collectPatternProperties() PatternAttributes attributes; toSVGPatternElement(pattern->element())->collectPatternAttributes(attributes); writeNameValuePair(ts, "patternUnits", attributes.patternUnits()); writeNameValuePair(ts, "patternContentUnits", attributes.patternContentUnits()); AffineTransform transform = attributes.patternTransform(); if (!transform.isIdentity()) ts << " [patternTransform=" << transform << "]"; ts << "\n"; } else if (resource->resourceType() == LinearGradientResourceType) { RenderSVGResourceLinearGradient* gradient = static_cast<RenderSVGResourceLinearGradient*>(resource); // Dump final results that are used for rendering. No use in asking SVGGradientElement for its gradientUnits(), as it may // link to other gradients using xlink:href, we need to build the full inheritance chain, aka. collectGradientProperties() LinearGradientAttributes attributes; toSVGLinearGradientElement(gradient->element())->collectGradientAttributes(attributes); writeCommonGradientProperties(ts, attributes.spreadMethod(), attributes.gradientTransform(), attributes.gradientUnits()); ts << " [start=" << gradient->startPoint(attributes) << "] [end=" << gradient->endPoint(attributes) << "]\n"; } else if (resource->resourceType() == RadialGradientResourceType) { RenderSVGResourceRadialGradient* gradient = toRenderSVGResourceRadialGradient(resource); // Dump final results that are used for rendering. No use in asking SVGGradientElement for its gradientUnits(), as it may // link to other gradients using xlink:href, we need to build the full inheritance chain, aka. collectGradientProperties() RadialGradientAttributes attributes; toSVGRadialGradientElement(gradient->element())->collectGradientAttributes(attributes); writeCommonGradientProperties(ts, attributes.spreadMethod(), attributes.gradientTransform(), attributes.gradientUnits()); FloatPoint focalPoint = gradient->focalPoint(attributes); FloatPoint centerPoint = gradient->centerPoint(attributes); float radius = gradient->radius(attributes); float focalRadius = gradient->focalRadius(attributes); ts << " [center=" << centerPoint << "] [focal=" << focalPoint << "] [radius=" << radius << "] [focalRadius=" << focalRadius << "]\n"; } else ts << "\n"; writeChildren(ts, object, indent); }
static TextStream& operator<<(TextStream& ts, const RenderSVGPath& path) { writePositionAndStyle(ts, path); ASSERT(path.node()->isSVGElement()); SVGElement* svgElement = static_cast<SVGElement*>(path.node()); if (svgElement->hasTagName(SVGNames::rectTag)) { SVGRectElement* element = static_cast<SVGRectElement*>(svgElement); writeNameValuePair(ts, "x", element->x().value(element)); writeNameValuePair(ts, "y", element->y().value(element)); writeNameValuePair(ts, "width", element->width().value(element)); writeNameValuePair(ts, "height", element->height().value(element)); } else if (svgElement->hasTagName(SVGNames::lineTag)) { SVGLineElement* element = static_cast<SVGLineElement*>(svgElement); writeNameValuePair(ts, "x1", element->x1().value(element)); writeNameValuePair(ts, "y1", element->y1().value(element)); writeNameValuePair(ts, "x2", element->x2().value(element)); writeNameValuePair(ts, "y2", element->y2().value(element)); } else if (svgElement->hasTagName(SVGNames::ellipseTag)) { SVGEllipseElement* element = static_cast<SVGEllipseElement*>(svgElement); writeNameValuePair(ts, "cx", element->cx().value(element)); writeNameValuePair(ts, "cy", element->cy().value(element)); writeNameValuePair(ts, "rx", element->rx().value(element)); writeNameValuePair(ts, "ry", element->ry().value(element)); } else if (svgElement->hasTagName(SVGNames::circleTag)) { SVGCircleElement* element = static_cast<SVGCircleElement*>(svgElement); writeNameValuePair(ts, "cx", element->cx().value(element)); writeNameValuePair(ts, "cy", element->cy().value(element)); writeNameValuePair(ts, "r", element->r().value(element)); } else if (svgElement->hasTagName(SVGNames::polygonTag) || svgElement->hasTagName(SVGNames::polylineTag)) { SVGPolyElement* element = static_cast<SVGPolyElement*>(svgElement); writeNameAndQuotedValue(ts, "points", element->pointList().valueAsString()); } else if (svgElement->hasTagName(SVGNames::pathTag)) { SVGPathElement* element = static_cast<SVGPathElement*>(svgElement); String pathString; // FIXME: We should switch to UnalteredParsing here - this will affect the path dumping output of dozens of tests. SVGPathParserFactory::self()->buildStringFromByteStream(element->pathByteStream(), pathString, NormalizedParsing); writeNameAndQuotedValue(ts, "data", pathString); } else ASSERT_NOT_REACHED(); return ts; }
static TextStream& operator<<(TextStream& ts, const RenderSVGShape& shape) { writePositionAndStyle(ts, shape); SVGElement* svgElement = shape.element(); SVGLengthContext lengthContext(svgElement); if (svgElement->hasTagName(SVGNames::rectTag)) { SVGRectElement* element = toSVGRectElement(svgElement); writeNameValuePair(ts, "x", element->xCurrentValue().value(lengthContext)); writeNameValuePair(ts, "y", element->yCurrentValue().value(lengthContext)); writeNameValuePair(ts, "width", element->widthCurrentValue().value(lengthContext)); writeNameValuePair(ts, "height", element->heightCurrentValue().value(lengthContext)); } else if (svgElement->hasTagName(SVGNames::lineTag)) { SVGLineElement* element = toSVGLineElement(svgElement); writeNameValuePair(ts, "x1", element->x1CurrentValue().value(lengthContext)); writeNameValuePair(ts, "y1", element->y1CurrentValue().value(lengthContext)); writeNameValuePair(ts, "x2", element->x2CurrentValue().value(lengthContext)); writeNameValuePair(ts, "y2", element->y2CurrentValue().value(lengthContext)); } else if (svgElement->hasTagName(SVGNames::ellipseTag)) { SVGEllipseElement* element = toSVGEllipseElement(svgElement); writeNameValuePair(ts, "cx", element->cxCurrentValue().value(lengthContext)); writeNameValuePair(ts, "cy", element->cyCurrentValue().value(lengthContext)); writeNameValuePair(ts, "rx", element->rxCurrentValue().value(lengthContext)); writeNameValuePair(ts, "ry", element->ryCurrentValue().value(lengthContext)); } else if (svgElement->hasTagName(SVGNames::circleTag)) { SVGCircleElement* element = toSVGCircleElement(svgElement); writeNameValuePair(ts, "cx", element->cxCurrentValue().value(lengthContext)); writeNameValuePair(ts, "cy", element->cyCurrentValue().value(lengthContext)); writeNameValuePair(ts, "r", element->rCurrentValue().value(lengthContext)); } else if (svgElement->hasTagName(SVGNames::polygonTag) || svgElement->hasTagName(SVGNames::polylineTag)) { writeNameAndQuotedValue(ts, "points", toSVGPolyElement(svgElement)->pointList().valueAsString()); } else if (svgElement->hasTagName(SVGNames::pathTag)) { String pathString; // FIXME: We should switch to UnalteredParsing here - this will affect the path dumping output of dozens of tests. buildStringFromByteStream(toSVGPathElement(svgElement)->pathByteStream(), pathString, NormalizedParsing); writeNameAndQuotedValue(ts, "data", pathString); } else ASSERT_NOT_REACHED(); return ts; }
static void writeIfNotDefault(TextStream& ts, const char* name, ValueType value, ValueType defaultValue) { if (value != defaultValue) writeNameValuePair(ts, name, value); }
static void writeIfNotEmpty(TextStream& ts, const char* name, const String& value) { if (!value.isEmpty()) writeNameValuePair(ts, name, value); }
static TextStream& operator<<(TextStream& ts, const LayoutSVGShape& shape) { writePositionAndStyle(ts, shape); SVGElement* svgElement = shape.element(); ASSERT(svgElement); SVGLengthContext lengthContext(svgElement); if (isSVGRectElement(*svgElement)) { SVGRectElement& element = toSVGRectElement(*svgElement); writeNameValuePair(ts, "x", element.x()->currentValue()->value(lengthContext)); writeNameValuePair(ts, "y", element.y()->currentValue()->value(lengthContext)); writeNameValuePair(ts, "width", element.width()->currentValue()->value(lengthContext)); writeNameValuePair(ts, "height", element.height()->currentValue()->value(lengthContext)); } else if (isSVGLineElement(*svgElement)) { SVGLineElement& element = toSVGLineElement(*svgElement); writeNameValuePair(ts, "x1", element.x1()->currentValue()->value(lengthContext)); writeNameValuePair(ts, "y1", element.y1()->currentValue()->value(lengthContext)); writeNameValuePair(ts, "x2", element.x2()->currentValue()->value(lengthContext)); writeNameValuePair(ts, "y2", element.y2()->currentValue()->value(lengthContext)); } else if (isSVGEllipseElement(*svgElement)) { SVGEllipseElement& element = toSVGEllipseElement(*svgElement); writeNameValuePair(ts, "cx", element.cx()->currentValue()->value(lengthContext)); writeNameValuePair(ts, "cy", element.cy()->currentValue()->value(lengthContext)); writeNameValuePair(ts, "rx", element.rx()->currentValue()->value(lengthContext)); writeNameValuePair(ts, "ry", element.ry()->currentValue()->value(lengthContext)); } else if (isSVGCircleElement(*svgElement)) { SVGCircleElement& element = toSVGCircleElement(*svgElement); writeNameValuePair(ts, "cx", element.cx()->currentValue()->value(lengthContext)); writeNameValuePair(ts, "cy", element.cy()->currentValue()->value(lengthContext)); writeNameValuePair(ts, "r", element.r()->currentValue()->value(lengthContext)); } else if (isSVGPolyElement(*svgElement)) { writeNameAndQuotedValue(ts, "points", toSVGPolyElement(*svgElement).points()->currentValue()->valueAsString()); } else if (isSVGPathElement(*svgElement)) { String pathString; // FIXME: We should switch to UnalteredParsing here - this will affect the path dumping output of dozens of tests. buildStringFromByteStream(*toSVGPathElement(*svgElement).pathByteStream(), pathString, NormalizedParsing); writeNameAndQuotedValue(ts, "data", pathString); } else { ASSERT_NOT_REACHED(); } return ts; }
static TextStream& operator<<(TextStream& ts, const RenderSVGShape& shape) { writePositionAndStyle(ts, shape); SVGGraphicsElement& svgElement = shape.graphicsElement(); SVGLengthContext lengthContext(&svgElement); if (isSVGRectElement(svgElement)) { const SVGRectElement& element = toSVGRectElement(svgElement); writeNameValuePair(ts, "x", element.x().value(lengthContext)); writeNameValuePair(ts, "y", element.y().value(lengthContext)); writeNameValuePair(ts, "width", element.width().value(lengthContext)); writeNameValuePair(ts, "height", element.height().value(lengthContext)); } else if (isSVGLineElement(svgElement)) { const SVGLineElement& element = toSVGLineElement(svgElement); writeNameValuePair(ts, "x1", element.x1().value(lengthContext)); writeNameValuePair(ts, "y1", element.y1().value(lengthContext)); writeNameValuePair(ts, "x2", element.x2().value(lengthContext)); writeNameValuePair(ts, "y2", element.y2().value(lengthContext)); } else if (isSVGEllipseElement(svgElement)) { const SVGEllipseElement& element = toSVGEllipseElement(svgElement); writeNameValuePair(ts, "cx", element.cx().value(lengthContext)); writeNameValuePair(ts, "cy", element.cy().value(lengthContext)); writeNameValuePair(ts, "rx", element.rx().value(lengthContext)); writeNameValuePair(ts, "ry", element.ry().value(lengthContext)); } else if (isSVGCircleElement(svgElement)) { const SVGCircleElement& element = toSVGCircleElement(svgElement); writeNameValuePair(ts, "cx", element.cx().value(lengthContext)); writeNameValuePair(ts, "cy", element.cy().value(lengthContext)); writeNameValuePair(ts, "r", element.r().value(lengthContext)); } else if (svgElement.hasTagName(SVGNames::polygonTag) || svgElement.hasTagName(SVGNames::polylineTag)) { const SVGPolyElement& element = toSVGPolyElement(svgElement); writeNameAndQuotedValue(ts, "points", element.pointList().valueAsString()); } else if (isSVGPathElement(svgElement)) { const SVGPathElement& element = toSVGPathElement(svgElement); String pathString; // FIXME: We should switch to UnalteredParsing here - this will affect the path dumping output of dozens of tests. buildStringFromByteStream(element.pathByteStream(), pathString, NormalizedParsing); writeNameAndQuotedValue(ts, "data", pathString); } else ASSERT_NOT_REACHED(); return ts; }
void writeSVGResourceContainer(TextStream& ts, const RenderObject& object, int indent) { writeStandardPrefix(ts, object, indent); Element* element = static_cast<Element*>(object.node()); const AtomicString& id = element->getIdAttribute(); writeNameAndQuotedValue(ts, "id", id); RenderSVGResourceContainer* resource = const_cast<RenderObject&>(object).toRenderSVGResourceContainer(); ASSERT(resource); if (resource->resourceType() == MaskerResourceType) { RenderSVGResourceMasker* masker = static_cast<RenderSVGResourceMasker*>(resource); writeNameValuePair(ts, "maskUnits", masker->maskUnits()); writeNameValuePair(ts, "maskContentUnits", masker->maskContentUnits()); ts << "\n"; #if ENABLE(FILTERS) } else if (resource->resourceType() == FilterResourceType) { RenderSVGResourceFilter* filter = static_cast<RenderSVGResourceFilter*>(resource); writeNameValuePair(ts, "filterUnits", filter->filterUnits()); writeNameValuePair(ts, "primitiveUnits", filter->primitiveUnits()); ts << "\n"; if (RefPtr<SVGFilterBuilder> builder = filter->buildPrimitives()) { if (FilterEffect* lastEffect = builder->lastEffect()) lastEffect->externalRepresentation(ts, indent + 1); } #endif } else if (resource->resourceType() == ClipperResourceType) { RenderSVGResourceClipper* clipper = static_cast<RenderSVGResourceClipper*>(resource); writeNameValuePair(ts, "clipPathUnits", clipper->clipPathUnits()); ts << "\n"; } else if (resource->resourceType() == MarkerResourceType) { RenderSVGResourceMarker* marker = static_cast<RenderSVGResourceMarker*>(resource); writeNameValuePair(ts, "markerUnits", marker->markerUnits()); ts << " [ref at " << marker->referencePoint() << "]"; ts << " [angle="; if (marker->angle() == -1) ts << "auto" << "]\n"; else ts << marker->angle() << "]\n"; } else if (resource->resourceType() == PatternResourceType) { RenderSVGResourcePattern* pattern = static_cast<RenderSVGResourcePattern*>(resource); // Dump final results that are used for rendering. No use in asking SVGPatternElement for its patternUnits(), as it may // link to other patterns using xlink:href, we need to build the full inheritance chain, aka. collectPatternProperties() PatternAttributes attributes = static_cast<SVGPatternElement*>(pattern->node())->collectPatternProperties(); writeNameValuePair(ts, "patternUnits", boundingBoxModeString(attributes.boundingBoxMode())); writeNameValuePair(ts, "patternContentUnits", boundingBoxModeString(attributes.boundingBoxModeContent())); AffineTransform transform = attributes.patternTransform(); if (!transform.isIdentity()) ts << " [patternTransform=" << transform << "]"; ts << "\n"; } else if (resource->resourceType() == LinearGradientResourceType) { RenderSVGResourceLinearGradient* gradient = static_cast<RenderSVGResourceLinearGradient*>(resource); // Dump final results that are used for rendering. No use in asking SVGGradientElement for its gradientUnits(), as it may // link to other gradients using xlink:href, we need to build the full inheritance chain, aka. collectGradientProperties() SVGLinearGradientElement* linearGradientElement = static_cast<SVGLinearGradientElement*>(gradient->node()); LinearGradientAttributes attributes = linearGradientElement->collectGradientProperties(); writeCommonGradientProperties(ts, attributes.spreadMethod(), attributes.gradientTransform(), attributes.boundingBoxMode()); FloatPoint startPoint; FloatPoint endPoint; linearGradientElement->calculateStartEndPoints(attributes, startPoint, endPoint); ts << " [start=" << startPoint << "] [end=" << endPoint << "]\n"; } else if (resource->resourceType() == RadialGradientResourceType) { RenderSVGResourceRadialGradient* gradient = static_cast<RenderSVGResourceRadialGradient*>(resource); // Dump final results that are used for rendering. No use in asking SVGGradientElement for its gradientUnits(), as it may // link to other gradients using xlink:href, we need to build the full inheritance chain, aka. collectGradientProperties() SVGRadialGradientElement* radialGradientElement = static_cast<SVGRadialGradientElement*>(gradient->node()); RadialGradientAttributes attributes = radialGradientElement->collectGradientProperties(); writeCommonGradientProperties(ts, attributes.spreadMethod(), attributes.gradientTransform(), attributes.boundingBoxMode()); FloatPoint focalPoint; FloatPoint centerPoint; float radius; radialGradientElement->calculateFocalCenterPointsAndRadius(attributes, focalPoint, centerPoint, radius); ts << " [center=" << centerPoint << "] [focal=" << focalPoint << "] [radius=" << radius << "]\n"; } else ts << "\n"; writeChildren(ts, object, indent); }