PageRenderTime 150ms CodeModel.GetById 59ms app.highlight 76ms RepoModel.GetById 1ms app.codeStats 1ms

/src/org/mt4j/util/xml/svg/SVGLoader.java

http://mt4j.googlecode.com/
Java | 2589 lines | 1581 code | 318 blank | 690 comment | 297 complexity | a0e5b4b9ced62d905339e4e815e4d032 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/***********************************************************************
   2 * mt4j Copyright (c) 2008 - 2009 C.Ruff, Fraunhofer-Gesellschaft All rights reserved.
   3 *  
   4 *   This program is free software: you can redistribute it and/or modify
   5 *   it under the terms of the GNU General Public License as published by
   6 *   the Free Software Foundation, either version 3 of the License, or
   7 *   (at your option) any later version.
   8 *
   9 *   This program is distributed in the hope that it will be useful,
  10 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12 *   GNU General Public License for more details.
  13 *
  14 *   You should have received a copy of the GNU General Public License
  15 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
  16 *
  17 ***********************************************************************/
  18package org.mt4j.util.xml.svg;
  19
  20import java.awt.BasicStroke;
  21import java.awt.Color;
  22import java.awt.Graphics;
  23import java.awt.Graphics2D;
  24import java.awt.MultipleGradientPaint.CycleMethod;
  25import java.awt.RadialGradientPaint;
  26import java.awt.Rectangle;
  27import java.awt.Stroke;
  28import java.awt.geom.AffineTransform;
  29import java.awt.geom.Point2D;
  30import java.awt.geom.Rectangle2D;
  31import java.io.File;
  32import java.io.InputStream;
  33import java.net.URI;
  34import java.text.AttributedCharacterIterator;
  35import java.text.AttributedCharacterIterator.Attribute;
  36import java.util.ArrayList;
  37import java.util.Iterator;
  38import java.util.LinkedList;
  39import java.util.List;
  40import java.util.Map;
  41import java.util.Set;
  42import java.util.Stack;
  43
  44import javax.media.opengl.GL;
  45import javax.media.opengl.glu.GLU;
  46import javax.swing.JPanel;
  47
  48import org.apache.batik.bridge.AbstractSVGGradientElementBridge;
  49import org.apache.batik.bridge.AbstractSVGGradientElementBridge.SVGStopElementBridge;
  50import org.apache.batik.bridge.AbstractSVGGradientElementBridge.Stop;
  51import org.apache.batik.bridge.Bridge;
  52import org.apache.batik.bridge.BridgeContext;
  53import org.apache.batik.bridge.BridgeException;
  54import org.apache.batik.bridge.CSSUtilities;
  55import org.apache.batik.bridge.DocumentLoader;
  56import org.apache.batik.bridge.GVTBuilder;
  57import org.apache.batik.bridge.PaintServer;
  58import org.apache.batik.bridge.SVGTextElementBridge;
  59import org.apache.batik.bridge.SVGUtilities;
  60import org.apache.batik.bridge.TextUtilities;
  61import org.apache.batik.bridge.UnitProcessor;
  62import org.apache.batik.bridge.UserAgent;
  63import org.apache.batik.bridge.UserAgentAdapter;
  64import org.apache.batik.css.engine.SVGCSSEngine;
  65import org.apache.batik.css.engine.value.ListValue;
  66import org.apache.batik.css.engine.value.Value;
  67import org.apache.batik.css.engine.value.svg.ICCColor;
  68import org.apache.batik.dom.svg.SAXSVGDocumentFactory;
  69import org.apache.batik.dom.svg.SVGGraphicsElement;
  70import org.apache.batik.dom.svg.SVGOMCircleElement;
  71import org.apache.batik.dom.svg.SVGOMClipPathElement;
  72import org.apache.batik.dom.svg.SVGOMDefsElement;
  73import org.apache.batik.dom.svg.SVGOMEllipseElement;
  74import org.apache.batik.dom.svg.SVGOMForeignObjectElement;
  75import org.apache.batik.dom.svg.SVGOMGElement;
  76import org.apache.batik.dom.svg.SVGOMLineElement;
  77import org.apache.batik.dom.svg.SVGOMLinearGradientElement;
  78import org.apache.batik.dom.svg.SVGOMMaskElement;
  79import org.apache.batik.dom.svg.SVGOMPathElement;
  80import org.apache.batik.dom.svg.SVGOMPolygonElement;
  81import org.apache.batik.dom.svg.SVGOMPolylineElement;
  82import org.apache.batik.dom.svg.SVGOMRadialGradientElement;
  83import org.apache.batik.dom.svg.SVGOMRectElement;
  84import org.apache.batik.dom.svg.SVGOMSVGElement;
  85import org.apache.batik.dom.svg.SVGOMSwitchElement;
  86import org.apache.batik.dom.svg.SVGOMTSpanElement;
  87import org.apache.batik.dom.svg.SVGOMTextElement;
  88import org.apache.batik.dom.svg.SVGOMToBeImplementedElement;
  89import org.apache.batik.dom.svg.SVGTextContentSupport;
  90import org.apache.batik.dom.svg.SVGURIReferenceGraphicsElement;
  91import org.apache.batik.dom.svg12.BindableElement;
  92import org.apache.batik.dom.svg12.SVGOMFlowRootElement;
  93import org.apache.batik.dom.util.XLinkSupport;
  94import org.apache.batik.ext.awt.MultipleGradientPaint;
  95import org.apache.batik.ext.awt.MultipleGradientPaint.CycleMethodEnum;
  96import org.apache.batik.gvt.GraphicsNode;
  97import org.apache.batik.gvt.TextNode;
  98import org.apache.batik.gvt.font.AWTGVTFont;
  99import org.apache.batik.gvt.font.GVTFont;
 100import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
 101import org.apache.batik.gvt.text.TextPaintInfo;
 102import org.apache.batik.parser.PathParser;
 103import org.apache.batik.parser.TransformListParser;
 104import org.apache.batik.util.SVGConstants;
 105import org.apache.batik.util.XMLResourceDescriptor;
 106import org.mt4j.MTApplication;
 107import org.mt4j.components.MTComponent;
 108import org.mt4j.components.TransformSpace;
 109import org.mt4j.components.bounds.BoundsZPlaneRectangle;
 110import org.mt4j.components.bounds.IBoundingShape;
 111import org.mt4j.components.clipping.FillPaint;
 112import org.mt4j.components.visibleComponents.AbstractVisibleComponent;
 113import org.mt4j.components.visibleComponents.font.FontManager;
 114import org.mt4j.components.visibleComponents.font.IFont;
 115import org.mt4j.components.visibleComponents.shapes.AbstractShape;
 116import org.mt4j.components.visibleComponents.shapes.GeometryInfo;
 117import org.mt4j.components.visibleComponents.shapes.MTEllipse;
 118import org.mt4j.components.visibleComponents.shapes.MTLine;
 119import org.mt4j.components.visibleComponents.shapes.MTPolygon;
 120import org.mt4j.components.visibleComponents.shapes.MTRectangle;
 121import org.mt4j.components.visibleComponents.shapes.MTRectangle.PositionAnchor;
 122import org.mt4j.components.visibleComponents.shapes.MTRoundRectangle;
 123import org.mt4j.components.visibleComponents.shapes.MTStencilPolygon;
 124import org.mt4j.components.visibleComponents.shapes.mesh.MTTriangleMesh;
 125import org.mt4j.components.visibleComponents.widgets.MTTextArea;
 126import org.mt4j.input.gestureAction.DefaultDragAction;
 127import org.mt4j.input.gestureAction.DefaultRotateAction;
 128import org.mt4j.input.gestureAction.DefaultScaleAction;
 129import org.mt4j.input.inputProcessors.IGestureEventListener;
 130import org.mt4j.input.inputProcessors.componentProcessors.dragProcessor.DragProcessor;
 131import org.mt4j.input.inputProcessors.componentProcessors.rotateProcessor.RotateProcessor;
 132import org.mt4j.input.inputProcessors.componentProcessors.scaleProcessor.ScaleProcessor;
 133import org.mt4j.util.HelperMethods;
 134import org.mt4j.util.MT4jSettings;
 135import org.mt4j.util.MTColor;
 136import org.mt4j.util.SwingTextureRenderer;
 137import org.mt4j.util.logging.ILogger;
 138import org.mt4j.util.logging.MTLoggerFactory;
 139import org.mt4j.util.math.ConvexityUtil;
 140import org.mt4j.util.math.Matrix;
 141import org.mt4j.util.math.ToolsGeometry;
 142import org.mt4j.util.math.Vector3D;
 143import org.mt4j.util.math.Vertex;
 144import org.mt4j.util.opengl.GLTexture;
 145import org.mt4j.util.opengl.GluTrianglulator;
 146import org.w3c.dom.Document;
 147import org.w3c.dom.Element;
 148import org.w3c.dom.NamedNodeMap;
 149import org.w3c.dom.Node;
 150import org.w3c.dom.NodeList;
 151import org.w3c.dom.css.CSSPrimitiveValue;
 152import org.w3c.dom.css.CSSStyleDeclaration;
 153import org.w3c.dom.css.CSSValue;
 154import org.w3c.dom.svg.SVGAnimatedLength;
 155import org.w3c.dom.svg.SVGDocument;
 156import org.w3c.dom.svg.SVGElement;
 157import org.w3c.dom.svg.SVGLength;
 158import org.w3c.dom.svg.SVGLengthList;
 159import org.w3c.dom.svg.SVGMatrix;
 160import org.w3c.dom.svg.SVGPoint;
 161import org.w3c.dom.svg.SVGPointList;
 162import org.w3c.dom.svg.SVGSVGElement;
 163
 164import processing.core.PApplet;
 165import processing.opengl.PGraphicsOpenGL;
 166
 167
 168/**
 169 * This class can be used to load and display scalable vector graphics (svg) files.
 170 * 
 171 * @author Christopher Ruff
 172 */
 173public class SVGLoader implements SVGConstants{
 174	private static final ILogger logger = MTLoggerFactory.getLogger(SVGLoader.class.getName());
 175	static{
 176		logger.setLevel(ILogger.ERROR);
 177	}
 178	
 179	/** The svg doc. */
 180	private SVGDocument    svgDoc;
 181	
 182	/** The user agent. */
 183	private UserAgent      userAgent;
 184	
 185	/** The loader. */
 186	private DocumentLoader loader;
 187	
 188	/** The ctx. */
 189	private BridgeContext  ctx;
 190	
 191	/** The builder. */
 192	private GVTBuilder     builder;
 193	
 194	/** The root gn. */
 195	private GraphicsNode   rootGN;
 196	
 197	/** The css engine. */
 198	protected SVGCSSEngine cssEngine; 
 199	
 200	/** The pa. */
 201	private PApplet pa;
 202	
 203	/** The opacity stack. */
 204	private Stack<Float> opacityStack;
 205	
 206	/** The default drag action. */
 207	private IGestureEventListener defaultDragAction;
 208	
 209	/** The default rotate action. */
 210	private IGestureEventListener defaultRotateAction;
 211	
 212	/** The default scale action. */
 213	private IGestureEventListener defaultScaleAction;
 214	
 215	/** The current local transform matrix. */
 216	private Matrix currentLocalTransformMatrix;
 217
 218	
 219	
 220	/**
 221	 * Instantiates a new batik svg parser.
 222	 * 
 223	 * @param pa the pa
 224	 */
 225	public SVGLoader(PApplet pa){
 226		this.pa = pa;
 227		
 228		opacityStack = new Stack<Float>();
 229		
 230		currentLocalTransformMatrix = new Matrix();
 231		
 232		defaultDragAction 		= new DefaultDragAction();
 233		defaultRotateAction 	= new DefaultRotateAction();
 234		defaultScaleAction 		= new DefaultScaleAction();
 235	}
 236	
 237	
 238	/**
 239	 * Loads a "*.svg" file, parses it, creates drawable components and returns the
 240	 * toplevel component.
 241	 * 
 242	 * @param filedescr the absolute path of the svg file as a string
 243	 * 
 244	 * @return the MT base component
 245	 * 
 246	 * the created top level component of the svg
 247	 */
 248	public MTComponent loadSvg(String filedescr){
 249		return this.getCreatedSvgComponents(this.parseSvg(filedescr));
 250	}
 251	
 252	
 253	/**
 254	 * Uses the batik parser to genererate an svg document from an svg file.
 255	 * To create the components in that svg document, call <code>getCreatedSvgComponents(SVGDocument doc)</code>
 256	 * 
 257	 * @param filedescr the filedescr
 258	 * 
 259	 * @return the SVG document
 260	 */
 261	public SVGDocument parseSvg(String filedescr){
 262        Document doc;
 263        try {
 264            String parser = XMLResourceDescriptor.getXMLParserClassName();
 265            SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(parser);
 266            
 267            File file = new File(filedescr);
 268            if (file.exists()){
 269                URI localFileAsUri = file.toURI(); 
 270                String uri = localFileAsUri.toASCIIString();
 271                doc = f.createDocument(uri);
 272            }else{
 273            	InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(filedescr);
 274            	if (in == null){
 275            		in = pa.getClass().getResourceAsStream(filedescr);
 276            	}
 277            	doc = f.createDocument(filedescr, in);
 278            	
 279            	 /*on it (after casting it to  SVGOMDocument) to give it a
 280                URI of some sort.  If the document needs to be able to have relative
 281                reference to files on the local file system, give it a URI like
 282                "file:///some/where/file.svg";
 283                */ 
 284                //FIXME HACK! this seems to help the "org.apache.batik.bridge.BridgeException: Unable to make sense of URL for connection" error
 285                //occuring with windmill.svg if loading from inputstream instead of local file system file
 286                //FIXME but this might create errors when loading external file like images from the relative svg path?
 287            	doc.setDocumentURI("") ; 
 288//                String sub = filedescr.substring(0, filedescr.lastIndexOf(MTApplication.separator));
 289//                System.out.println("F: " + filedescr + " sub; " + sub);
 290//                svgDoc.setDocumentURI(sub+ MTApplication.separator) ; 
 291            }
 292            svgDoc = (SVGDocument)doc;
 293        } catch (Exception ex) {
 294            ex.printStackTrace();
 295        }
 296	        
 297        //Neccesary? For booting css 
 298        try{
 299	        userAgent = new UserAgentAdapter();
 300	        loader    = new DocumentLoader(userAgent);
 301	        ctx       = new BridgeContext(userAgent, loader);
 302	        ctx.setDynamicState(BridgeContext.DYNAMIC); //TODO use static?
 303	        builder   = new GVTBuilder();
 304	        rootGN    = builder.build(ctx, svgDoc);
 305	        
 306//	        ctx.getCSSEngineForElement(null).
 307        }catch(Exception e){
 308        	e.printStackTrace();
 309        }
 310        return svgDoc;
 311	}
 312	
 313	/**
 314	 * Creates and returns components of the provided svg document for displaying.
 315	 * 
 316	 * @param svgDoc the svg doc
 317	 * 
 318	 * @return the created svg components
 319	 */
 320	public MTComponent getCreatedSvgComponents(SVGDocument svgDoc){
 321		ArrayList<MTComponent> components = new ArrayList<MTComponent>();
 322		opacityStack.push(1.0f);
 323		traverseSVGDoc(svgDoc, components);
 324		opacityStack.pop();
 325		
 326		MTComponent[] comps = components.toArray(new MTComponent[components.size()]);
 327		//Only returning the 1st component, since this should be the top-level <svg> element and only 1!?
 328		return comps[0];
 329	}
 330	
 331	
 332	
 333	/**
 334	 * Traverse svg doc.
 335	 * 
 336	 * @param node the node
 337	 * @param comps the comps
 338	 */
 339	private void traverseSVGDoc(Node node, ArrayList<MTComponent> comps){
 340		logger.debug("Traversing: " + node.getNodeName());
 341		
 342		//Damit transformationen konsistent sind muss
 343		//jedes tag, da? eine transform attribut hat
 344		//behandelt werden!
 345		//Default
 346		currentLocalTransformMatrix = new Matrix();
 347		
 348		//If there is a TRANSFORM attribute parse that and set the 
 349		//current transformation matrix to be used with the svg components created after
 350		NamedNodeMap atts = node.getAttributes();
 351		if (atts != null){
 352			for (int i = 0; i < atts.getLength(); i++) {
 353				Node att = atts.item(i);
 354				if (att.getNodeName().equals(SVG_TRANSFORM_ATTRIBUTE)){
 355					CustomTransformHandler transFormHandler = new CustomTransformHandler();
 356					TransformListParser transFormListParser = new TransformListParser();
 357					transFormListParser.setTransformListHandler(transFormHandler);
 358					transFormListParser.parse(att.getNodeValue());
 359					//Overwrite current default matrix if the element has its own 
 360					//transform defined, will be used at gfx obj creation
 361					currentLocalTransformMatrix = transFormHandler.getResultMatrix();
 362				}
 363			}
 364		}
 365		
 366//		logger.debug("Node: " + node.getNodeName() + " Class: " + node.getClass());
 367		
 368		
 369		//For opacity inheritance
 370		  if (node instanceof SVGGraphicsElement){
 371			  SVGGraphicsElement svgGfx = (SVGGraphicsElement)node;
 372			  //Handle inherited opacity settings
 373			  float opac = queryPrimitiveFloatValue(svgGfx, "opacity", 1f);
 374			  opacityStack.push(opac *= opacityStack.peek());
 375		  }
 376
 377		  // if G (GROUP) element, add all children to this element
 378		  if (  node instanceof SVGOMGElement 
 379			 || node instanceof SVGSVGElement
 380			 || node instanceof SVGOMSVGElement
 381		  ){
 382//			  SVGOMGElement gElem = (SVGOMGElement)node;
 383			  SVGElement gElem = (SVGElement)node;
 384			  MTComponent group = new MTComponent(pa);
 385			  group.setName(gElem.getTagName());
 386
 387//			  Element viewPort = gElem.getViewportElement();
 388//			  logger.debug("Viewport " + viewPort.getNodeName());
 389
 390			  //Set the <g> group to composite, meaning that it will
 391			  //be returned at picking, when one of the children gets picked
 392			  group.setComposite(true);
 393
 394			  group.setLocalMatrix(currentLocalTransformMatrix);
 395			  
 396			  //IF its <svg> element get the transform 
 397			  //(to honor the viewBox and the width/height attributes
 398			  if (node instanceof SVGOMSVGElement ){ 
 399				  SVGOMSVGElement svgGom = ((SVGOMSVGElement)node);
 400				  Element viewPort = svgGom.getViewportElement();
 401				  if (viewPort != null)
 402					  logger.debug("Viewport " + viewPort.getNodeName());
 403				  
 404//				  SVGMatrix mat = svgGom.getScreenCTM();
 405				  
 406				  SVGAnimatedLength widthA = svgGom.getWidth();
 407				  SVGAnimatedLength heightA = svgGom.getHeight();
 408				  
 409				  SVGLength w = widthA.getBaseVal();
 410				  float width = w.getValue();
 411				  
 412				  SVGLength h = heightA.getBaseVal();
 413				  float height = h.getValue();
 414				  
 415				  logger.debug("-> SVG Width: " + width + " Height: " + height);
 416				  
 417				  
 418				  SVGMatrix mat = svgGom.getCTM();
 419				  /*
 420				  logger.debug("mat: " + mat.toString());
 421				  logger.debug(mat.getA());
 422				  logger.debug(mat.getB());
 423				  logger.debug(mat.getC());
 424				  logger.debug(mat.getD());
 425				  logger.debug(mat.getE());
 426				  logger.debug(mat.getF());
 427				  SVGRect bbox = svgGom.getBBox();
 428				  logger.debug("BBOx: X:" + bbox.getX() + " Y:" + bbox.getY() + " Width:" + bbox.getWidth() + " Height:" + bbox.getHeight());
 429				  */
 430				  
 431				  //Hack, because if no width/height is specified default of 1.0
 432				  //is assumed by batik -> things may get scaled too small
 433				  if ( !(width == 1 && height == 1) ){
 434					  currentLocalTransformMatrix = new Matrix(mat.getA(), mat.getC(), 	0, mat.getE(),
 435							  								   mat.getB(), mat.getD(), 	0, mat.getF(),
 436							  								   0, 			0, 			1, 			0,
 437							  								   0, 			0, 			0, 			1
 438					  );
 439					  //logger.debug("Matrix: " + currentLocalTransformMatrix);
 440					  group.setLocalMatrix(currentLocalTransformMatrix);
 441				  }
 442			  }
 443
 444			  //Make the group pickable and manipulatable 
 445			  group.setPickable(true);
 446			  
 447			  group.registerInputProcessor(new DragProcessor(pa));
 448			  group.setGestureAllowance(DragProcessor.class, true);
 449			  group.addGestureListener(DragProcessor.class, (IGestureEventListener)defaultDragAction);
 450			  
 451			  group.registerInputProcessor(new RotateProcessor(pa));
 452			  group.addGestureListener(RotateProcessor.class, defaultRotateAction);
 453			  
 454			  group.registerInputProcessor(new ScaleProcessor(pa));
 455			  group.addGestureListener(ScaleProcessor.class,  defaultScaleAction);
 456			  
 457			  ArrayList<MTComponent> groupChildren = new ArrayList<MTComponent>();
 458			  //Traverse the children and add them to a new arraylist
 459			  traverseChildren(gElem, groupChildren);
 460			  
 461			  MTComponent[] childComps = groupChildren.toArray(new MTComponent[groupChildren.size()]);
 462			  //Add the children to the group
 463			  group.addChildren(childComps);
 464			  //Add the group to the arraylist of the parent
 465			  comps.add(group);
 466		  }else{//If NOT GROUP
 467			  if (node instanceof SVGGraphicsElement){
 468				  SVGGraphicsElement svgGfxElem = (SVGGraphicsElement)node;
 469				  //IF node isnt a group node just add it to the passed in comps arraylist
 470				  try{
 471					  //Create a component from the graphicsnode and add it to the parents arraylist
 472					  MTComponent liveComponent = handleGraphicsNode(svgGfxElem);
 473					  if (liveComponent != null){
 474						  comps.add(liveComponent);
 475					  }
 476				  }catch(Exception e){
 477					  logger.error("Error handling svg node: " + svgGfxElem.getTagName());
 478					  e.printStackTrace();
 479				  }
 480			  }
 481
 482			  //FIXME IMPLEMENT
 483			  if (node instanceof SVGOMTSpanElement){
 484				  SVGOMTSpanElement tSpanElement = (SVGOMTSpanElement)node;
 485				  
 486			  }
 487
 488			  //FIXME TEST
 489			  if (node instanceof SVGOMTextElement){
 490				  boolean useVectorFont = false;
 491				  
 492				  SVGOMTextElement textElement = (SVGOMTextElement)node;
 493				  //Get <text> position values (can be a list)
 494				  List<Float> xValues = getSVGLengthListAsFloat(textElement.getX().getBaseVal());
 495				  List<Float> yValues = getSVGLengthListAsFloat(textElement.getY().getBaseVal());
 496//				  /*//Not used 
 497				  String textContent = TextUtilities.getElementContent(textElement);
 498				  textContent = textContent.replaceAll("\\n","");
 499				  textContent = textContent.trim();
 500//				   */
 501				  /*
 502				  //TODO USE?
 503				  textElement.getTextLength();
 504				  textElement.getRotate();
 505				   */
 506				  if (textElement.getSVGContext() instanceof SVGTextElementBridge){
 507					  SVGTextElementBridge b = (SVGTextElementBridge)textElement.getSVGContext();
 508					  GraphicsNode gr = b.createGraphicsNode(ctx, textElement);
 509					  TextNode tNode = (TextNode)gr;
 510					  b.buildGraphicsNode(ctx, textElement, tNode);
 511					  List<?> textRuns = tNode.getTextRuns();
 512					  logger.debug("Text runs: " + textRuns);
 513					  //Get font size
 514					  float fontSize = b.getFontSize();
 515
 516					  logger.debug("Text:" +  " x:" + xValues.get(0) + " y:" + yValues.get(0) + " FontSize: " + fontSize +  " Text: '" + textContent + "'");
 517
 518					  //Get font FILL
 519					  Value fillOpacValue = CSSUtilities.getComputedStyle(textElement, SVGCSSEngine.FILL_OPACITY_INDEX);
 520					  float computedfillOpac = PaintServer.convertOpacity(fillOpacValue);
 521					  Value fillIndexValue = CSSUtilities.getComputedStyle(textElement, SVGCSSEngine.FILL_INDEX);
 522					  Object fill = SVGLoader.getFillOrStroke(textElement, fillIndexValue, computedfillOpac, ctx);
 523					  MTColor fillColor = new MTColor(150,150,150,255);
 524					  if (fill instanceof java.awt.Color) {
 525						  java.awt.Color color = (Color) fill;
 526						  fillColor.setColor(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
 527					  }
 528
 529					  //Get STROKE
 530					  // Stroke Opacity \\
 531					  Value strokeOpacValue = CSSUtilities.getComputedStyle(textElement, SVGCSSEngine.STROKE_OPACITY_INDEX);
 532					  float computedStrokeOpacity = PaintServer.convertOpacity(strokeOpacValue);
 533					  // Stroke java.awt.Color \\
 534					  Value strokeIndexValue = CSSUtilities.getComputedStyle(textElement, SVGCSSEngine.STROKE_INDEX);
 535					  Object stroke = SVGLoader.getFillOrStroke(textElement, strokeIndexValue, computedStrokeOpacity, ctx);
 536					  MTColor strokeColor = new MTColor(fillColor.getR(), fillColor.getG(), fillColor.getB(), fillColor.getAlpha());
 537					  if (stroke instanceof java.awt.Color) {
 538						  java.awt.Color color = (Color) stroke;
 539						  strokeColor.setColor(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
 540					  }
 541
 542					  //Get the font family
 543					  Value fontFamilyValue = CSSUtilities.getComputedStyle(textElement, SVGCSSEngine.FONT_FAMILY_INDEX);
 544					  String fontFamily = "arial"; //DEFAULT
 545					  if (fontFamilyValue instanceof ListValue) {
 546						  ListValue listValue = (ListValue) fontFamilyValue;
 547						  Value firstValue = listValue.item(0); //Can be a List? -> take only the first one..
 548						  if (firstValue != null)
 549							  fontFamily = firstValue.getStringValue();
 550					  }
 551					  logger.debug("Font family: " + fontFamily);
 552
 553					  IFont font;
 554					  if (useVectorFont)
 555						  //Vector font
 556						  font = FontManager.getInstance().createFont(pa, 
 557								  "arial.ttf", Math.round(fontSize), fillColor);
 558					  else
 559						  //Bitmap font
 560						  font = FontManager.getInstance().createFont(pa, 
 561//								  "Arial", Math.round(fontSize),
 562								  fontFamily, Math.round(fontSize), fillColor);
 563//					  /* 
 564
 565					  IFont fontToUse = font;
 566					  IFont lastUsedFont = fontToUse;
 567					  List<MTTextArea> textAreas = new ArrayList<MTTextArea>();
 568
 569					  AttributedCharacterIterator iter = tNode.getAttributedCharacterIterator();
 570					  if (font != null && iter != null){ //To avoid not loaded fonts or if text ist empty
 571						  for (int i = iter.getBeginIndex(); i < iter.getEndIndex(); i++) {
 572							  char currentChar = iter.setIndex(i);
 573							  Set<Attribute> keys = iter.getAllAttributeKeys();
 574							  Map<Attribute, Object> charAtts = iter.getAttributes();
 575							  
 576							  Object baseLineShift = charAtts.get(SVGTextElementBridge.BASELINE_SHIFT);
 577							  Object paintInfo = charAtts.get(SVGTextElementBridge.PAINT_INFO);
 578
 579							  Object charX = charAtts.get(GVTAttributedCharacterIterator.TextAttribute.X);
 580							  Object charY = charAtts.get(GVTAttributedCharacterIterator.TextAttribute.Y);
 581							  Object charDX = charAtts.get(GVTAttributedCharacterIterator.TextAttribute.DX);
 582							  Object charDY = charAtts.get(GVTAttributedCharacterIterator.TextAttribute.DY);
 583							  Object charRotation = charAtts.get(GVTAttributedCharacterIterator.TextAttribute.ROTATION);
 584							  Object gvtFont = charAtts.get(GVTAttributedCharacterIterator.TextAttribute.GVT_FONT);
 585							  Object gvtFonts = charAtts.get(GVTAttributedCharacterIterator.TextAttribute.GVT_FONTS);
 586							  Object gvtFontFamilies = charAtts.get(GVTAttributedCharacterIterator.TextAttribute.GVT_FONT_FAMILIES);
 587							  Object textCompoundDelimiter = charAtts.get(GVTAttributedCharacterIterator.TextAttribute.TEXT_COMPOUND_DELIMITER);
 588							  Object verticalOrientation = charAtts.get(GVTAttributedCharacterIterator.TextAttribute.VERTICAL_ORIENTATION);
 589							  logger.debug("Character: "  + currentChar + " CharX:" + charX + " CharY: " + charY + " CharDX: " +  charDX + " CharDY: " + charDY +  " Font: " + gvtFont +  " Fonts: " + gvtFonts +   " FontFamilies: " + gvtFontFamilies);
 590							  AWTGVTFont awtGvtFont = (AWTGVTFont)gvtFont;
 591							  if (awtGvtFont != null)
 592								  logger.debug("CharfontSize: " + awtGvtFont.getSize());
 593
 594							  //FIXME REMOVE, Not working always 0,0
 595							  SVGPoint startPosOfChar = SVGTextContentSupport.getStartPositionOfChar(textElement, i);
 596
 597							  /////////////////////////////////////
 598							  //Get the character information - font, colors
 599							  String newFamilyName = fontFamily;
 600							  float newFontSize = fontSize;
 601							  MTColor newFillColor = new MTColor(fillColor);
 602							  MTColor newStrokeColor = new MTColor(strokeColor);
 603							  boolean charHasColorInfo = false;
 604							  boolean charHasFontInfo = false;
 605							  //Get chars paint info
 606							  if (paintInfo != null && paintInfo instanceof TextPaintInfo){
 607								  charHasColorInfo = true;
 608								  TextPaintInfo texInfo = (TextPaintInfo)paintInfo;
 609								  if (texInfo.fillPaint instanceof java.awt.Color){
 610									  java.awt.Color color = (Color)texInfo.fillPaint;
 611									  newFillColor.setColor(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
 612								  }
 613								  if (texInfo.strokePaint instanceof java.awt.Color){
 614									  java.awt.Color color = (Color)texInfo.strokePaint;
 615									  newStrokeColor.setColor(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
 616								  }
 617							  }
 618
 619							  //Get the chars font family and size
 620							  GVTFont aGvtFont = null;
 621							  if (gvtFonts!=null){
 622								  if (gvtFonts instanceof List) {
 623									  List<?> fonts = (List<?>) gvtFonts;
 624                                      for (Object o : fonts) {
 625                                          if (o instanceof GVTFont) {
 626                                              aGvtFont = (GVTFont) o;
 627                                              //logger.debug("Char font family: " + aGvtFont.getFamilyName() + " Size:" + aGvtFont.getSize());
 628                                          }
 629                                      }
 630								  }
 631							  }
 632							  if (aGvtFont != null){
 633								  charHasFontInfo = true;
 634								  newFamilyName = aGvtFont.getFamilyName();
 635								  newFontSize = aGvtFont.getSize();
 636							  }else{
 637								  logger.error("Character: " + currentChar + " has no font attached.");
 638							  }
 639
 640							  if (charHasColorInfo && charHasFontInfo){
 641								  logger.debug("Character '" + currentChar + "'-> has font info -> load font!" +
 642										  " Family: " + newFamilyName +
 643										  " Fontsize: " + Math.round(newFontSize) +
 644										  " FillColor: " + newFillColor +
 645										  " StrokeColor: " + newStrokeColor);
 646								  
 647								  if (useVectorFont)
 648									  fontToUse = FontManager.getInstance().createFont(pa, 
 649											  "arial.ttf", Math.round(newFontSize), newFillColor);
 650								  else
 651									  fontToUse = FontManager.getInstance().createFont(pa, //uses cached font if available
 652//											  "Arial", Math.round(fontSize),
 653											  newFamilyName, Math.round(newFontSize), newFillColor);
 654								  if (fontToUse == null){
 655									  fontToUse = font;
 656								  }
 657							  }else{
 658								  fontToUse = font;
 659							  }
 660							  boolean fontChanged = !FontManager.isFontsAreEqual(fontToUse, lastUsedFont);
 661							  lastUsedFont = fontToUse;
 662
 663//							  //FIXME REMOVE TEST
 664//							  fontChanged = true;
 665							  ///////////////////////////////////////
 666							  boolean textPositionChanged = charX != null || charY != null  || charDX != null || charDY != null;
 667
 668							  //TODO if we forceAnewTextarea because of font change but ther is NO NEW POSITION, we
 669							  //have to set the textareas anchor to the lower left
 670							  //TODO problem if we have a tspan centered and a next tspan without new position
 671							  //-> the first tspan textarea gets centered on the position 
 672							  //but we would have to treat them (all in the same line) as 1 textarea when center positioning!
 673							  
 674							  //FIXME there are slight differences because we use a different SPACE character length and no font KERNING!
 675							  
 676							  //FIXME DO WIDHTOUT USERDATA
 677							  //FIXME bitmap font has no top border, vector has.. why?
 678							  //TODO -> eventuell doch in handleSvgNode machen?
 679							  //-> statt graphicsnode /stylable node ?bergeben? - SVGOMTextElement is nicht instanceof graphicsnode..
 680							  
 681							  // we have to check font/color etc at every character, not only at new positon because 
 682							  //pos doesent change at tspans without new posinfo
 683							  //check if equal to last used font and if equal original text font
 684							  if ( fontChanged || textPositionChanged					
 685							  ){ //Make a new textarea if the text position changed or if the font changed at the current character
 686								  MTTextArea previousTextArea = null;
 687								  if (!textAreas.isEmpty()){
 688									  previousTextArea = textAreas.get(textAreas.size()-1);
 689								  }
 690
 691								  float newXPos = 0; 
 692								  float newYPos = 0 ;
 693
 694								  //If there is a previous text, get its ending coordinates 
 695								  //for the DX and DY shift info for the next text area
 696								  if (previousTextArea != null){
 697									  PositionAnchor oldAnchor = previousTextArea.getAnchor();
 698//									  previousTextArea.setAnchor(PositionAnchor.LOWER_RIGHT);
 699									  previousTextArea.setAnchor(PositionAnchor.UPPER_LEFT);
 700									  //Calculate last/current textposition for DX and DY use
 701									  //add up the last textareas start position end position(width)
 702									  Vector3D lastPos = previousTextArea.getPosition(TransformSpace.LOCAL);
 703//									  lastPos.addLocal(new Vector3D(previousTextArea.getWidthXY(TransformSpace.LOCAL) - 1 * previousTextArea.getInnerPaddingLeft(),0));
 704									  lastPos.addLocal(new Vector3D(previousTextArea.getWidthXY(TransformSpace.LOCAL) - 2 * previousTextArea.getInnerPaddingLeft(),0));
 705//									  newXPos = lastPos.x - previousTextArea.getInnerPaddingLeft();
 706									  newXPos = lastPos.x;
 707									  newXPos += (Float)previousTextArea.getUserData("XPos");
 708
 709									  newYPos = lastPos.y;
 710//									  newYPos -= previousTextArea.getInnerPaddingTop();
 711//									  newYPos += fontToUse.getFontMaxDescent(); //FIXME WHY NEVESSARY?
 712									  newYPos += (Float)previousTextArea.getUserData("YPos");
 713									  previousTextArea.setAnchor(oldAnchor);
 714								  }
 715
 716								  //IF absolute x or y is present overwrite the position values from the last textarea
 717								  if (charX != null)
 718									  newXPos = (Float)charX;
 719								  if (charY != null)
 720									  newYPos = (Float)charY;
 721								  if (charDX != null)
 722									  newXPos += (Float)charDX;
 723								  if (charDY != null)
 724									  newYPos += (Float)charDY;
 725								  
 726								  // Create the text area \\
 727								  MTTextArea t = new MTTextArea(pa, fontToUse);
 728								  t.setNoFill(true);
 729								  t.setNoStroke(true);
 730								  textAreas.add(t);
 731								  try{
 732									  t.setLocalMatrix(new Matrix(currentLocalTransformMatrix));
 733								  }catch(Exception e){
 734									  logger.error(e.getMessage());
 735								  }
 736
 737								  //FIXME TEST
 738//								  if (previousTextArea != null && !textPositionChange){
 739//								  t.setAnchor(PositionAnchor.LOWER_LEFT);
 740//								  t.setUserData("posRelParent", new Vector3D(newXPos , newYPos - fontToUse.getFontMaxDescent() , 0));
 741//								  logger.debug("Character '" + currentChar + "' -> Anchor: LOWER_LEFT");
 742//								  }else{
 743								  Value v = CSSUtilities.getComputedStyle(textElement, SVGCSSEngine.TEXT_ANCHOR_INDEX);
 744								  //INFO: we have to move the BASELINE of the text to the svg position
 745								  //The textarea is usually fontmaxascent+fontmaxdescent+2*innerPadding big!
 746								  switch (v.getStringValue().charAt(0)) {
 747								  case 'e':
 748									  t.setAnchor(PositionAnchor.LOWER_RIGHT);
 749									  t.setUserData("posRelParent", new Vector3D((newXPos + t.getInnerPaddingLeft()) , newYPos - fontToUse.getFontMaxDescent()  +  t.getInnerPaddingTop() , 0));
 750//									  t.setPositionRelativeToParent(new Vector3D(newXPos, newYPos - font.getFontMaxDescent() , 0));
 751									  logger.debug("Character '" + currentChar + "' -> Anchor: LOWER_RIGHT");
 752									  break;
 753								  case 'm': //text-anchor="middle"
 754									  t.setAnchor(PositionAnchor.CENTER);
 755//									  t.setUserData("posRelParent", new Vector3D(newXPos, newYPos - fontToUse.getFontMaxAscent()*0.5f - fontToUse.getFontMaxDescent()*0.5f , 0));
 756//									  t.setUserData("posRelParent", new Vector3D(newXPos, newYPos - fontToUse.getFontAbsoluteHeight()*0.5f + t.getInnerPaddingTop() , 0));
 757//									  t.setPositionRelativeToParent(new Vector3D(newXPos, newYPos - font.getFontMaxAscent()*0.5f - font.getFontMaxDescent()*0.5f, 0)); //- font.getFontMaxAscent()*0.5f
 758									  logger.debug("Character '" + currentChar + "' -> Anchor: CENTER");
 759									  t.setUserData("posRelParent", new Vector3D((newXPos), (newYPos - fontToUse.getFontMaxDescent() + t.getInnerPaddingTop()) - t.getHeightXY(TransformSpace.LOCAL)/2f , 0));
 760									  break;
 761								  default: //text-anchor="start" //default!
 762									  t.setAnchor(PositionAnchor.LOWER_LEFT);
 763//									  t.setUserData("posRelParent", new Vector3D(newXPos -t.getInnerPaddingLeft(), newYPos - fontToUse.getFontMaxDescent() + t.getInnerPaddingTop() , 0));
 764									  t.setUserData("posRelParent", new Vector3D(newXPos -t.getInnerPaddingLeft(), newYPos - fontToUse.getFontMaxDescent() + t.getInnerPaddingTop() , 0));
 765									  
 766//									  t.setAnchor(PositionAnchor.UPPER_LEFT);
 767//									  t.setUserData("posRelParent", new Vector3D(newXPos -t.getInnerPaddingLeft(), newYPos, 0));
 768//								  t.setPositionRelativeToParent(new Vector3D(newXPos, newYPos - font.getFontMaxDescent() , 0));
 769								  logger.debug("Character '" + currentChar + "' -> Anchor: LOWER_LEFT");
 770								  }
 771								  t.setUserData("XPos", newXPos); 
 772								  t.setUserData("YPos", newYPos);
 773//								  }
 774							  }
 775							  //Add character to the current textarea in the list
 776							  if (!textAreas.isEmpty()){
 777								  textAreas.get(textAreas.size()-1).appendCharByUnicode(Character.toString(currentChar));
 778							  }
 779						  }
 780						  //Set the positions of the textareas
 781                          for (MTTextArea textArea : textAreas) {
 782                              logger.debug("Adding text area at: " + (Vector3D) textArea.getUserData("posRelParent"));
 783                              textArea.setPositionRelativeToParent((Vector3D) textArea.getUserData("posRelParent"));
 784                          }
 785						  comps.addAll(textAreas);
 786					  }
 787
 788					  /*
 789					  //This gets only the text of this hierarchy level
 790					  StringBuffer result = new StringBuffer();
 791					  for (Node n = textElement.getFirstChild();
 792					  n != null;
 793					  n = n.getNextSibling()) {
 794						  switch (n.getNodeType()) {
 795						  case Node.ELEMENT_NODE:
 796							  break;
 797						  case Node.CDATA_SECTION_NODE:
 798						  case Node.TEXT_NODE:
 799							  result.append(n.getNodeValue());
 800						  }
 801					  }
 802					  logger.debug("TEXTTTT2: " + result);
 803					   */
 804//					  */////////////////////
 805
 806				  }
 807			  }
 808		  }
 809
 810
 811		if (node instanceof SVGGraphicsElement){
 812			  //Remove inherited opacity attribute from stack
 813			  opacityStack.pop();
 814		}
 815		
 816		//Traverse the children, not if it was a group element 
 817		//because then the children are already
 818		//traversed in the if (group) block above
 819		if (   !(node instanceof SVGOMGElement)
 820			&& !(node instanceof SVGSVGElement) 
 821			&& !(node instanceof SVGOMSVGElement) 
 822		){
 823		  traverseChildren(node, comps);
 824		}
 825	}
 826	
 827	
 828	
 829	/**
 830	 * Traverse children.
 831	 * 
 832	 * @param node the node
 833	 * @param comps the comps
 834	 */
 835	private void traverseChildren(Node node, ArrayList<MTComponent> comps){
 836				
 837		//Check the children
 838		NodeList nl = node.getChildNodes();
 839		  for (int i = 0; i < nl.getLength(); i++) {
 840			Node currentNode = nl.item(i);
 841			traverseSVGDoc(currentNode, comps);
 842		}
 843	}
 844	
 845	
 846	/**
 847	 * Handle graphics node.
 848	 * 
 849	 * @param gfxElem the gfx elem
 850	 * 
 851	 * @return the mT base component
 852	 */
 853	private MTComponent handleGraphicsNode(SVGGraphicsElement gfxElem){
 854		  MTComponent returnComp = null;
 855//		  logger.debug("Handle Element: " + gfxElem.getTagName());
 856		  
 857		  //Print all css properties and values
 858//		  logger.debug("Style Css Text: " + style.getCssText());
 859		  
 860		  // SVG Defaults \\
 861		  float fillR 			= 255;
 862		  float fillG 			= 255;
 863		  float fillB 			= 255;
 864		  boolean noFill 		= false;
 865		  float strokeR 		= 0;
 866		  float strokeG 		= 0;
 867		  float strokeB 		= 0;
 868		  float strokeWidth 	= 1.0f;
 869		  boolean noStroke 		= false;
 870		  float strokeOpacity 	= 1;
 871		  float fillOpacity   	= 1;
 872		  int windingRule 		= GLU.GLU_TESS_WINDING_NONZERO;
 873		  // SVG Defaults \\
 874		  
 875		  
 876		  // Opacity, not as a style attribute but a separate 
 877		  // as group opacity doesnt get computed right, so we 
 878		  // mannually track it on a stack
 879		  float opacity = opacityStack.peek();
 880		  //logger.debug("INHERITED OPACITY: " + opacity);
 881		  
 882		  
 883		  // FILL-RULE \\
 884		  Value fillRuleValue = CSSUtilities.getComputedStyle(gfxElem, SVGCSSEngine.FILL_RULE_INDEX);
 885		  String fillRule = fillRuleValue.getStringValue();
 886		  if (fillRule.equalsIgnoreCase("nonzero")){
 887			  windingRule = GLU.GLU_TESS_WINDING_NONZERO;
 888		  }else if (fillRule.equalsIgnoreCase("evenodd")){
 889			  windingRule = GLU.GLU_TESS_WINDING_ODD;
 890		  }else{
 891			  windingRule = GLU.GLU_TESS_WINDING_NONZERO;
 892		  }
 893		  //logger.debug("fillRule: " + fillRule);
 894		  
 895		  
 896		  // Fill Opacity \\
 897		  fillOpacity =  PaintServer.convertOpacity(CSSUtilities.getComputedStyle(gfxElem, SVGCSSEngine.FILL_OPACITY_INDEX));
 898		  //Multiplicate inherited opacity with this components opacities
 899		  fillOpacity 	*= opacity;
 900		  //Save for eventual lineargradient creation later that needs the not interpolated value
 901		  float originalFillOpacity = fillOpacity;
 902		  //logger.debug("fill opacity unnormalized: " + fillOpacity);
 903		  
 904		  
 905		  // Fill java.awt.Color \\
 906		  Value fillIndexValue = CSSUtilities.getComputedStyle(gfxElem, SVGCSSEngine.FILL_INDEX);
 907		  Object fill = SVGLoader.getFillOrStroke(gfxElem, fillIndexValue, fillOpacity, ctx);
 908		  SVGOMLinearGradientElement linearGradient = null;
 909		  SVGOMRadialGradientElement radialGradient = null;
 910		  if (fill instanceof java.awt.Color) {
 911			  java.awt.Color color = (Color) fill;
 912			  fillR = color.getRed();
 913			  fillG = color.getGreen();
 914			  fillB = color.getBlue();
 915			  fillOpacity = color.getAlpha();
 916			  noFill = false;
 917			  //logger.debug("Fill: " + color +  " a=" + fillOpacity);
 918		  }else if (fill instanceof SVGOMLinearGradientElement) {
 919          	//TODO cache gradients so dass man nicht immer neu den gleichen
 920          	//machen muss!
 921			  linearGradient = (SVGOMLinearGradientElement) fill;
 922			  noFill = false;
 923		  }else if (fill instanceof SVGOMRadialGradientElement) {
 924			//TODO!! //FIXME TEST
 925			  radialGradient = (SVGOMRadialGradientElement)fill;
 926			  noFill = false;
 927		  }else{
 928			  noFill = true;
 929		  }
 930		  
 931		  
 932		  // Stroke Opacity \\
 933		  strokeOpacity = PaintServer.convertOpacity(CSSUtilities.getComputedStyle(gfxElem, SVGCSSEngine.STROKE_OPACITY_INDEX));
 934		  // Multiplicate inherited opacity with this components group opacities
 935		  strokeOpacity *= opacity;
 936		  
 937		  
 938		  // Stroke java.awt.Color \\
 939		  Value strokeIndexValue = CSSUtilities.getComputedStyle(gfxElem, SVGCSSEngine.STROKE_INDEX);
 940		  Object stroke = SVGLoader.getFillOrStroke(gfxElem, strokeIndexValue, strokeOpacity, ctx);
 941		  if (stroke instanceof java.awt.Color) {
 942			  java.awt.Color color = (Color) stroke;
 943			  strokeR = color.getRed();
 944			  strokeG = color.getGreen();
 945			  strokeB = color.getBlue();
 946			  strokeOpacity = color.getAlpha();
 947			  noStroke = false;
 948		  }else{
 949			  noStroke = true;
 950			  strokeR = fillR;
 951			  strokeG = fillG;
 952			  strokeB = fillB;
 953		  }
 954		  
 955		  
 956		  // Stroke Width \\
 957		  Stroke s = PaintServer.convertStroke(gfxElem);
 958		  if (s != null){
 959			  if (s instanceof BasicStroke) {
 960				  BasicStroke basicStroke = (BasicStroke) s;
 961				  strokeWidth = basicStroke.getLineWidth();
 962			  }
 963		  }else{
 964			  strokeWidth = 0.0f;
 965			  noStroke = true;
 966		  }
 967		  
 968		 /*
 969		 logger.debug("Fill COL: " + fillR + " " + fillG + " " + fillB + " " fillopacity);
 970		 logger.debug("STROKE COL: " + strokeR + " " + strokeG + " " + strokeB + " " strokeOpacity);
 971		 */
 972		  
 973		  // CHECK WHAT KIND OF GRAPHICS ELEMENT IT IS AND CREATE IT \\
 974		  if (gfxElem instanceof SVGOMPathElement){
 975			  SVGOMPathElement pathElem = (SVGOMPathElement)gfxElem;
 976			  
 977			  //FIXME handle clip-paths in the future
 978			  if (isUnderClipPath(pathElem)){
 979				  logger.error("Discarding clip-path path element. Not implemented.");
 980				  return null;
 981			  }
 982			  
 983			  //Create the shape
 984			  AbstractShape pathComp = getLivePathComponent(pathElem, noFill, windingRule);
 985			  
 986			  try{
 987				  pathComp.setLocalMatrix(currentLocalTransformMatrix);
 988			  }catch(Exception e){
 989				  logger.error(e.getMessage());
 990			  }
 991			  returnComp = pathComp;
 992		  }else if (gfxElem instanceof SVGOMPolygonElement){
 993			  SVGOMPolygonElement polygonElem = (SVGOMPolygonElement)gfxElem;
 994			  
 995			  //Create the shape
 996			  AbstractShape comp = getLivePolygonComponent(polygonElem, noFill, windingRule);
 997			  			  
 998			  try{
 999				  comp.setLocalMatrix(currentLocalTransformMatrix);
1000			  }catch(Exception e){
1001				  logger.error(e.getMessage());
1002			  }
1003			  returnComp = comp;
1004		  }else if (gfxElem instanceof SVGOMPolylineElement){
1005			  SVGOMPolylineElement polyLineElem = (SVGOMPolylineElement)gfxElem;
1006			  
1007			  //Create Vertex[] from points
1008			  SVGPointList pointList = polyLineElem.getPoints();
1009			  Vertex[] vertices = new Vertex[pointList.getNumberOfItems()];
1010			  for (int i = 0; i < pointList.getNumberOfItems(); i++) {
1011				SVGPoint p = pointList.getItem(i);
1012				vertices[i] = new Vertex(p.getX(), p.getY(),0);
1013			  }
1014			  
1015			  //Create the shape
1016			  AbstractShape comp = createPoly(vertices);
1017			  
1018			  try{
1019				  comp.setLocalMatrix(currentLocalTransformMatrix);
1020			  }catch(Exception e){
1021				  logger.error(e.getMessage());
1022			  }
1023			  returnComp = comp;
1024		  }else if (gfxElem instanceof SVGOMRectElement){ 
1025			  SVGOMRectElement rectElem = (SVGOMRectElement)gfxElem;
1026			  if (isUnderClipPath(rectElem)){
1027				  logger.error("discarding clip-path Rect");
1028				  return null;
1029			  }
1030			  
1031			  float x 		= rectElem.getX().getBaseVal().getValue();
1032			  float y 		= rectElem.getY().getBaseVal().getValue();
1033			  float width 	= rectElem.getWidth().getBaseVal().getValue();
1034			  float height 	= rectElem.getHeight().getBaseVal().getValue();
1035			  float rx 		= rectElem.getRx().getBaseVal().getValue();
1036			  float ry 		= rectElem.getRy().getBaseVal().getValue();
1037			  
1038			  AbstractShape comp;
1039			  //Create a normal rectangle or a round rectangle
1040			  if (rx != 0.0f || ry != 0.0f){
1041				  if (rx > width/2 )
1042					  rx = width/2;
1043				  if (ry > height/2 )
1044					  ry = height/2;
1045				  comp = new MTRoundRectangle(pa,x,y, 0,width,height, rx, ry);
1046			  }else{
1047				  comp = new MTRectangle(pa,x, y,width, height); 
1048			  }
1049			  
1050			  try{
1051				  comp.setLocalMatrix(currentLocalTransformMatrix);
1052			  }catch(Exception e){
1053				  logger.error(e.getMessage());
1054			  }
1055			  returnComp = comp;
1056		  }else if (gfxElem instanceof SVGOMEllipseElement){ 
1057			  SVGOMEllipseElement ellipseElem = (SVGOMEllipseElement)gfxElem;
1058			  float cx = ellipseElem.getCx().getBaseVal().getValue();
1059			  float cy = ellipseElem.getCy().getBaseVal().getValue();
1060			  float r  = ellipseElem.getRx().getBaseVal().getValue();
1061			  float r2 = ellipseElem.getRy().getBaseVal().getValue();
1062			  
1063			  Vertex middlePoint = new Vertex(cx,cy,0);
1064			  //Apply transformation, transform centerpoint and the radii
1065			  try{
1066				  middlePoint.transform(currentLocalTransformMatrix);
1067			  }catch(Exception e){
1068				  logger.error(e.getMessage());
1069			  }
1070			  
1071			  //somehow the circle radii need to be doubled
1072			  //or else theyre too small => processing bug?
1073//			  r*=2;
1074//			  r2*=2;
1075			  MTEllipse comp = new MTEllipse(pa, middlePoint, r, r2);
1076			  returnComp = comp;
1077		  }else if (gfxElem instanceof SVGOMCircleElement){ 
1078			  SVGOMCircleElement circleElem = (SVGOMCircleElement)gfxElem;
1079			  float cx = circleElem.getCx().getBaseVal().getValue();
1080			  float cy = circleElem.getCy().getBaseVal().getValue();
1081			  float r = circleElem.getR().getBaseVal().getValue();
1082			  float r2 = circleElem.getR().getBaseVal().getValue();
1083			  
1084			  Vertex middlePoint = new Vertex(cx,cy,0);
1085			  //Apply transformation, transform centerpoint and the radii
1086			  try{
1087				  middlePoint.transform(currentLocalTransformMatrix);
1088			  }catch(Exception e){
1089				  logger.error(e.getMessage());
1090			  }
1091			  
1092			  //somehow the circle radii need to be doubled
1093			  //or else theyre too small => processing bug?
1094//			  r*=2;
1095//			  r2*=2;
1096			  MTEllipse comp = new MTEllipse(pa, middlePoint, r, r2);
1097			  returnComp = comp;
1098		  }else if (gfxElem instanceof SVGOMLineElement){
1099			  SVGOMLineElement line = (SVGOMLineElement)gfxElem;
1100			  float x1 = line.getX1().getBaseVal().getValue();
1101			  float y1 = line.getY1().getBaseVal().getValue();
1102			  float x2 = line.getX2().getBaseVal().getValue();
1103			  float y2 = line.getY2().getBaseVal().getValue();
1104			  //logger.debug("Line x1: " + x1 + ",y1:" + y1 + ",x2:" + x2 + ",y2:" + y2);
1105			  
1106			  MTLine comp = new MTLine(pa, x1,y1 ,x2,y2);
1107			 
1108			  try{
1109				  comp.setLocalMatrix(currentLocalTransformMatrix);
1110			  }catch(Exception e){
1111				  logger.error(e.getMessage());
1112			  }
1113			  returnComp = comp;
1114		  }else if (gfxElem instanceof SVGOMClipPathElement){ 
1115		  }else if (gfxElem instanceof SVGOMDefsElement){ 
1116		  }else if (gfxElem instanceof SVGOMMaskElement){ 
1117		  }else if (gfxElem instanceof SVGOMSwitchElement){ 
1118		  }else if (gfxElem instanceof SVGOMFlowRootElement){ 
1119		  }else if (gfxElem instanceof SVGURIReferenceGraphicsElement){ 
1120		  }else if (gfxElem instanceof BindableElement){ 
1121		  }else if (gfxElem instanceof SVGOMForeignObjectElement){ 
1122		  }else if (gfxElem instanceof SVGOMToBeImplementedElement){ 
1123		  }
1124		  
1125		  //Do the finishing touch of the svg graphics element
1126		  if (returnComp != null){
1127			  returnComp.setName(gfxElem.getTagName());
1128			  
1129			  //Set style infos
1130			  if (returnComp instanceof AbstractVisibleComponent){
1131				  AbstractVisibleComponent comp = (AbstractVisibleComponent)returnComp;
1132				  //Set Fill
1133				  comp.setFillColor(new MTColor(fillR, fillG, fillB, fillOpacity));
1134				  comp.setNoFill(noFill);
1135				  //Set Stroke
1136				  comp.setStrokeColor(new MTColor(strokeR, strokeG, strokeB, strokeOpacity));
1137				  //Opengl cant handle big lines well
1138				  //So cap at width 3
1139				  if (strokeWidth > 2.0f)
1140					  strokeWidth = 2.0f;
1141				  comp.setStrokeWeight(strokeWidth);
1142				  comp.setNoStroke(noStroke);
1143				  //Other
1144				  comp.setDrawSmooth(true);
1145				  comp.setPickable(false);
1146				  
1147				  //Hack for smoothing non stroked components with a stroke same as fillcolor
1148				  if (comp.isNoStroke()
1149					 && linearGradient == null
1150				  ){  
1151					  comp.setStrokeColor(new MTColor(fillR, fillG, fillB, fillOpacity)); //fillOpacity
1152					  comp.setStrokeWeight(0.6f);
1153					  //Ellipse doesent smooth right with 0.1f strokeweight
1154					  if (comp instanceof MTEllipse){
1155						  comp.setStrokeWeight(1.0f);
1156					  }
1157					  comp.setNoStroke(false);
1158				  }
1159
1160				  //Some settings for Geometric shapes (actually should all be)
1161				  if (comp instanceof AbstractShape ){
1162					  AbstractShape shape = (AbstractShape)comp;
1163					  //Set a bounding rectangle to check first at picking
1164					  if (shape.getVerticesLocal().length >= 3){
1165						  shape.setBoundsBehaviour(AbstractShape.BOUNDS_CHECK_THEN_GEOMETRY_CHECK);
1166						  //shape.setBoundingShape(new BoundsZPlaneRectangle(shape)); //already done by override, (ie svgpoly)
1167						  
1168						  //Create amd apply the linear gradient if existant and if we are in opengl rendering mode
1169						  if (MT4jSettings.getInstance().isOpenGlMode()){
1170							  if (linearGradient != null){
1171								  FillPaint gradient = this.createLinearGradient(linearGradient, gfxElem, originalFillOpacity, shape);
1172								  if (gradient != null){
1173									  shape.setFillPaint(gradient);
1174								  }
1175							  }
1176							  if (radialGradient != null){
1177								  FillPaint gradient = this.createRadialGradient(radialGradient, gfxElem, opacity, shape);
1178								  if (gradient != null){
1179									  shape.setFillPaint(gradient);
1180								  }
1181							  }
1182							//Per default use direct gl drawing and displaylists in OGL mode
1183							if (pa instanceof MTApplication) {
1184								MTApplication app = (MTApplication) pa;
1185

Large files files are truncated, but you can click here to view the full file