001package com.hfg.svg; 002 003import com.hfg.util.Recursion; 004import com.hfg.util.StringUtil; 005import com.hfg.util.collection.CollectionUtil; 006import com.hfg.xml.XMLAttribute; 007import com.hfg.xml.XMLContainer; 008import com.hfg.xml.XMLNamespace; 009import com.hfg.html.HTML; 010import com.hfg.xml.XMLNode; 011import com.hfg.xml.XMLTag; 012 013import java.awt.*; 014import java.awt.geom.AffineTransform; 015import java.awt.geom.Rectangle2D; 016import java.util.List; 017 018//------------------------------------------------------------------------------ 019/** 020 Object representation of an SVG (Scalable Vector Graphics) 'use' tag. 021 <p> 022 See <a href='http://www.w3.org/TR/SVG11/struct.html#UseElement'>http://www.w3.org/TR/SVG11/struct.html#UseElement</a> 023 </p> 024 @author J. Alex Taylor, hairyfatguy.com 025 */ 026//------------------------------------------------------------------------------ 027// com.hfg XML/HTML Coding Library 028// 029// This library is free software; you can redistribute it and/or 030// modify it under the terms of the GNU Lesser General Public 031// License as published by the Free Software Foundation; either 032// version 2.1 of the License, or (at your option) any later version. 033// 034// This library is distributed in the hope that it will be useful, 035// but WITHOUT ANY WARRANTY; without even the implied warranty of 036// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 037// Lesser General Public License for more details. 038// 039// You should have received a copy of the GNU Lesser General Public 040// License along with this library; if not, write to the Free Software 041// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 042// 043// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com 044// jataylor@hairyfatguy.com 045//------------------------------------------------------------------------------ 046 047public class SvgUse extends AbstractSvgNode implements SvgNode 048{ 049 //########################################################################## 050 // CONSTRUCTORS 051 //########################################################################## 052 053 //--------------------------------------------------------------------------- 054 public SvgUse(String inURL) 055 { 056 this(inURL, null); 057 } 058 059 //--------------------------------------------------------------------------- 060 public SvgUse(String inURL, Point inLocation) 061 { 062 super(SVG.use); 063 064 XMLAttribute attr = new XMLAttribute(HTML.HREF, inURL); 065 attr.setNamespace(XMLNamespace.XLINK); 066 setAttribute(attr); 067 068 if (inLocation != null) 069 { 070 setAttribute(SvgAttr.x, (int) inLocation.getX()); 071 setAttribute(SvgAttr.y, (int) inLocation.getY()); 072 } 073 } 074 075 //--------------------------------------------------------------------------- 076 public SvgUse(XMLTag inXMLTag) 077 { 078 super(SVG.use); 079 080 initFromXMLTag(inXMLTag); 081 } 082 083 //########################################################################## 084 // PUBLIC METHODS 085 //########################################################################## 086 087 //-------------------------------------------------------------------------- 088 public String getURL() 089 { 090 return getAttributeValue(HTML.HREF); 091 } 092 093 //-------------------------------------------------------------------------- 094 @Override 095 public void draw(Graphics2D g2) 096 { 097 // Save settings 098 Font origFont = g2.getFont(); 099 Paint origPaint = g2.getPaint(); 100 Stroke origStroke = g2.getStroke(); 101 Color origBackground = g2.getBackground(); 102 AffineTransform origTransform = null; 103 104 if (getAttributeValue(SvgAttr.transform) != null) 105 { 106 origTransform = g2.getTransform(); 107 108 applyTransform(g2, getAttributeValue(SvgAttr.transform)); 109 } 110 111 Font locallyAdjustedFont = getAdjustedFont(origFont); 112 if (locallyAdjustedFont != null) 113 { 114 g2.setFont(locallyAdjustedFont); 115 } 116 117 AbstractSvgNode svgDefNode = null; 118 119 String url = getURL(); 120 if (StringUtil.isSet(url) 121 && url.startsWith("#")) 122 { 123 svgDefNode = getLocallyReferencedDefNode(); 124 } 125 126 if (svgDefNode != null) 127 { 128 svgDefNode.draw(g2); 129 } 130 131 // Restore settings 132 g2.setFont(origFont); 133 g2.setPaint(origPaint); 134 g2.setStroke(origStroke); 135 g2.setBackground(origBackground); 136 if (origTransform != null) 137 { 138 g2.setTransform(origTransform); 139 } 140 } 141 142 //--------------------------------------------------------------------------- 143 @Override 144 public Rectangle2D getBoundsBox() 145 { 146 AbstractSvgNode svgDefNode = getLocallyReferencedDefNode(); 147 148 Rectangle2D boundsBox = (svgDefNode != null ? svgDefNode.getBoundsBox() : null); 149 if (boundsBox != null) 150 { 151 adjustBoundsForTransform(boundsBox); 152 } 153 154 return boundsBox; 155 } 156 157 //########################################################################## 158 // PRIVATE METHODS 159 //########################################################################## 160 161 //-------------------------------------------------------------------------- 162 private AbstractSvgNode getLocallyReferencedDefNode() 163 { 164 AbstractSvgNode svgDefNode = null; 165 166 String url = getURL(); 167 if (StringUtil.isSet(url) 168 && url.startsWith("#")) 169 { 170 // This is a little tricky. We need to find the def referenced by the URL 171 // by traversing up the DOM structure and then locating any matching defs. 172 XMLContainer parentNode = getParentNode(); 173 while (parentNode.getParentNode() != null) 174 { 175 parentNode = parentNode.getParentNode(); 176 } 177 178 List<XMLNode> defNodes = parentNode.getSubtagsByName(SVG.defs, Recursion.ON); 179 if (CollectionUtil.hasValues(defNodes)) 180 { 181 for (XMLNode defNode : defNodes) 182 { 183 SvgDefs defs = (SvgDefs) defNode; 184 if (CollectionUtil.hasValues(defs.getSubtags())) 185 { 186 for (XMLTag xmlTag : (List<XMLTag>) (Object) defs.getSubtags()) 187 { 188 String id = xmlTag.getAttributeValue(SvgAttr.id); 189 if (StringUtil.isSet(id) 190 && id.equals(url.substring(1))) 191 { 192 svgDefNode = (AbstractSvgNode) xmlTag; 193 break; 194 } 195 } 196 } 197 198 if (svgDefNode != null) 199 { 200 break; 201 } 202 } 203 } 204 } 205 206 return svgDefNode; 207 } 208 209}