File indexing completed on 2024-04-28 15:24:35
0001 /* 0002 Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org> 0003 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org> 0004 0005 This file is part of the KDE project 0006 0007 This library is free software; you can redistribute it and/or 0008 modify it under the terms of the GNU Library General Public 0009 License as published by the Free Software Foundation; either 0010 version 2 of the License, or (at your option) any later version. 0011 0012 This library is distributed in the hope that it will be useful, 0013 but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0015 Library General Public License for more details. 0016 0017 You should have received a copy of the GNU Library General Public License 0018 along with this library; see the file COPYING.LIB. If not, write to 0019 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0020 Boston, MA 02110-1301, USA. 0021 */ 0022 0023 #if ENABLE(SVG) 0024 #include "SVGMarkerElement.h" 0025 0026 #include "PlatformString.h" 0027 #include "RenderSVGViewportContainer.h" 0028 #include "SVGAngle.h" 0029 #include "SVGLength.h" 0030 #include "SVGNames.h" 0031 #include "SVGPreserveAspectRatio.h" 0032 #include "SVGSVGElement.h" 0033 0034 namespace WebCore 0035 { 0036 0037 SVGMarkerElement::SVGMarkerElement(const QualifiedName &tagName, Document *doc) 0038 : SVGStyledElement(tagName, doc) 0039 , SVGLangSpace() 0040 , SVGExternalResourcesRequired() 0041 , SVGFitToViewBox() 0042 , m_refX(this, LengthModeWidth) 0043 , m_refY(this, LengthModeHeight) 0044 , m_markerWidth(this, LengthModeWidth) 0045 , m_markerHeight(this, LengthModeHeight) 0046 , m_markerUnits(SVG_MARKERUNITS_STROKEWIDTH) 0047 , m_orientType(0) 0048 , m_orientAngle(new SVGAngle()) 0049 { 0050 // Spec: If the attribute is not specified, the effect is as if a value of "3" were specified. 0051 setMarkerWidthBaseValue(SVGLength(this, LengthModeWidth, "3")); 0052 setMarkerHeightBaseValue(SVGLength(this, LengthModeHeight, "3")); 0053 } 0054 0055 SVGMarkerElement::~SVGMarkerElement() 0056 { 0057 } 0058 0059 ANIMATED_PROPERTY_DEFINITIONS(SVGMarkerElement, SVGLength, Length, length, RefX, refX, SVGNames::refXAttr, m_refX) 0060 ANIMATED_PROPERTY_DEFINITIONS(SVGMarkerElement, SVGLength, Length, length, RefY, refY, SVGNames::refYAttr, m_refY) 0061 ANIMATED_PROPERTY_DEFINITIONS(SVGMarkerElement, int, Enumeration, enumeration, MarkerUnits, markerUnits, SVGNames::markerUnitsAttr, m_markerUnits) 0062 ANIMATED_PROPERTY_DEFINITIONS(SVGMarkerElement, SVGLength, Length, length, MarkerWidth, markerWidth, SVGNames::markerWidthAttr, m_markerWidth) 0063 ANIMATED_PROPERTY_DEFINITIONS(SVGMarkerElement, SVGLength, Length, length, MarkerHeight, markerHeight, SVGNames::markerHeightAttr, m_markerHeight) 0064 ANIMATED_PROPERTY_DEFINITIONS_WITH_CUSTOM_IDENTIFIER(SVGMarkerElement, int, Enumeration, enumeration, OrientType, orientType, SVGNames::orientAttr, "orientType", m_orientType) 0065 ANIMATED_PROPERTY_DEFINITIONS_WITH_CUSTOM_IDENTIFIER(SVGMarkerElement, SVGAngle *, Angle, angle, OrientAngle, orientAngle, SVGNames::orientAttr, "orientAngle", m_orientAngle.get()) 0066 0067 void SVGMarkerElement::parseMappedAttribute(MappedAttribute *attr) 0068 { 0069 if (attr->name() == SVGNames::markerUnitsAttr) { 0070 if (attr->value() == "userSpaceOnUse") { 0071 setMarkerUnitsBaseValue(SVG_MARKERUNITS_USERSPACEONUSE); 0072 } 0073 } else if (attr->name() == SVGNames::refXAttr) { 0074 setRefXBaseValue(SVGLength(this, LengthModeWidth, attr->value())); 0075 } else if (attr->name() == SVGNames::refYAttr) { 0076 setRefYBaseValue(SVGLength(this, LengthModeHeight, attr->value())); 0077 } else if (attr->name() == SVGNames::markerWidthAttr) { 0078 setMarkerWidthBaseValue(SVGLength(this, LengthModeWidth, attr->value())); 0079 } else if (attr->name() == SVGNames::markerHeightAttr) { 0080 setMarkerHeightBaseValue(SVGLength(this, LengthModeHeight, attr->value())); 0081 } else if (attr->name() == SVGNames::orientAttr) { 0082 if (attr->value() == "auto") { 0083 setOrientToAuto(); 0084 } else { 0085 SVGAngle *angle = new SVGAngle(); 0086 angle->setValueAsString(attr->value()); 0087 setOrientToAngle(angle); 0088 } 0089 } else { 0090 if (SVGLangSpace::parseMappedAttribute(attr)) { 0091 return; 0092 } 0093 if (SVGExternalResourcesRequired::parseMappedAttribute(attr)) { 0094 return; 0095 } 0096 if (SVGFitToViewBox::parseMappedAttribute(attr)) { 0097 return; 0098 } 0099 0100 SVGStyledElement::parseMappedAttribute(attr); 0101 } 0102 } 0103 0104 void SVGMarkerElement::svgAttributeChanged(const QualifiedName &attrName) 0105 { 0106 SVGStyledElement::svgAttributeChanged(attrName); 0107 0108 if (!m_marker) { 0109 return; 0110 } 0111 0112 if (attrName == SVGNames::markerUnitsAttr || attrName == SVGNames::refXAttr || 0113 attrName == SVGNames::refYAttr || attrName == SVGNames::markerWidthAttr || 0114 attrName == SVGNames::markerHeightAttr || attrName == SVGNames::orientAttr || 0115 SVGLangSpace::isKnownAttribute(attrName) || 0116 SVGExternalResourcesRequired::isKnownAttribute(attrName) || 0117 SVGFitToViewBox::isKnownAttribute(attrName) || 0118 SVGStyledElement::isKnownAttribute(attrName)) { 0119 if (renderer()) { 0120 renderer()->setNeedsLayout(true); 0121 } 0122 0123 m_marker->invalidate(); 0124 } 0125 } 0126 0127 void SVGMarkerElement::childrenChanged(bool changedByParser, Node *beforeChange, Node *afterChange, int childCountDelta) 0128 { 0129 SVGStyledElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); 0130 0131 if (renderer()) { 0132 renderer()->setNeedsLayout(true); 0133 } 0134 0135 if (m_marker) { 0136 m_marker->invalidate(); 0137 } 0138 } 0139 0140 void SVGMarkerElement::setOrientToAuto() 0141 { 0142 setOrientTypeBaseValue(SVG_MARKER_ORIENT_AUTO); 0143 } 0144 0145 void SVGMarkerElement::setOrientToAngle(SVGAngle *angle) 0146 { 0147 setOrientTypeBaseValue(SVG_MARKER_ORIENT_ANGLE); 0148 setOrientAngleBaseValue(angle); 0149 } 0150 0151 SVGResource *SVGMarkerElement::canvasResource() 0152 { 0153 if (!m_marker) { 0154 m_marker = SVGResourceMarker::create(); 0155 } 0156 0157 m_marker->setMarker(static_cast<RenderSVGViewportContainer *>(renderer())); 0158 0159 // Spec: If the attribute is not specified, the effect is as if a 0160 // value of "0" were specified. 0161 if (!m_orientType) { 0162 setOrientToAngle(SVGSVGElement::createSVGAngle()); 0163 } 0164 0165 if (orientType() == SVG_MARKER_ORIENT_ANGLE) { 0166 m_marker->setAngle(orientAngle()->value()); 0167 } else { 0168 m_marker->setAutoAngle(); 0169 } 0170 0171 m_marker->setRef(refX().value(), refY().value()); 0172 m_marker->setUseStrokeWidth(markerUnits() == SVG_MARKERUNITS_STROKEWIDTH); 0173 0174 return m_marker.get(); 0175 } 0176 0177 RenderObject *SVGMarkerElement::createRenderer(RenderArena *arena, RenderStyle *style) 0178 { 0179 RenderSVGViewportContainer *markerContainer = new(arena) RenderSVGViewportContainer(this); 0180 markerContainer->setDrawsContents(false); // Marker contents will be explicitly drawn. 0181 return markerContainer; 0182 } 0183 0184 } 0185 0186 #endif // ENABLE(SVG)