/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 are truncated click here to view the full file
- /***********************************************************************
- * mt4j Copyright (c) 2008 - 2009 C.Ruff, Fraunhofer-Gesellschaft All rights reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- ***********************************************************************/
- package org.mt4j.util.xml.svg;
-
- import java.awt.BasicStroke;
- import java.awt.Color;
- import java.awt.Graphics;
- import java.awt.Graphics2D;
- import java.awt.MultipleGradientPaint.CycleMethod;
- import java.awt.RadialGradientPaint;
- import java.awt.Rectangle;
- import java.awt.Stroke;
- import java.awt.geom.AffineTransform;
- import java.awt.geom.Point2D;
- import java.awt.geom.Rectangle2D;
- import java.io.File;
- import java.io.InputStream;
- import java.net.URI;
- import java.text.AttributedCharacterIterator;
- import java.text.AttributedCharacterIterator.Attribute;
- import java.util.ArrayList;
- import java.util.Iterator;
- import java.util.LinkedList;
- import java.util.List;
- import java.util.Map;
- import java.util.Set;
- import java.util.Stack;
-
- import javax.media.opengl.GL;
- import javax.media.opengl.glu.GLU;
- import javax.swing.JPanel;
-
- import org.apache.batik.bridge.AbstractSVGGradientElementBridge;
- import org.apache.batik.bridge.AbstractSVGGradientElementBridge.SVGStopElementBridge;
- import org.apache.batik.bridge.AbstractSVGGradientElementBridge.Stop;
- import org.apache.batik.bridge.Bridge;
- import org.apache.batik.bridge.BridgeContext;
- import org.apache.batik.bridge.BridgeException;
- import org.apache.batik.bridge.CSSUtilities;
- import org.apache.batik.bridge.DocumentLoader;
- import org.apache.batik.bridge.GVTBuilder;
- import org.apache.batik.bridge.PaintServer;
- import org.apache.batik.bridge.SVGTextElementBridge;
- import org.apache.batik.bridge.SVGUtilities;
- import org.apache.batik.bridge.TextUtilities;
- import org.apache.batik.bridge.UnitProcessor;
- import org.apache.batik.bridge.UserAgent;
- import org.apache.batik.bridge.UserAgentAdapter;
- import org.apache.batik.css.engine.SVGCSSEngine;
- import org.apache.batik.css.engine.value.ListValue;
- import org.apache.batik.css.engine.value.Value;
- import org.apache.batik.css.engine.value.svg.ICCColor;
- import org.apache.batik.dom.svg.SAXSVGDocumentFactory;
- import org.apache.batik.dom.svg.SVGGraphicsElement;
- import org.apache.batik.dom.svg.SVGOMCircleElement;
- import org.apache.batik.dom.svg.SVGOMClipPathElement;
- import org.apache.batik.dom.svg.SVGOMDefsElement;
- import org.apache.batik.dom.svg.SVGOMEllipseElement;
- import org.apache.batik.dom.svg.SVGOMForeignObjectElement;
- import org.apache.batik.dom.svg.SVGOMGElement;
- import org.apache.batik.dom.svg.SVGOMLineElement;
- import org.apache.batik.dom.svg.SVGOMLinearGradientElement;
- import org.apache.batik.dom.svg.SVGOMMaskElement;
- import org.apache.batik.dom.svg.SVGOMPathElement;
- import org.apache.batik.dom.svg.SVGOMPolygonElement;
- import org.apache.batik.dom.svg.SVGOMPolylineElement;
- import org.apache.batik.dom.svg.SVGOMRadialGradientElement;
- import org.apache.batik.dom.svg.SVGOMRectElement;
- import org.apache.batik.dom.svg.SVGOMSVGElement;
- import org.apache.batik.dom.svg.SVGOMSwitchElement;
- import org.apache.batik.dom.svg.SVGOMTSpanElement;
- import org.apache.batik.dom.svg.SVGOMTextElement;
- import org.apache.batik.dom.svg.SVGOMToBeImplementedElement;
- import org.apache.batik.dom.svg.SVGTextContentSupport;
- import org.apache.batik.dom.svg.SVGURIReferenceGraphicsElement;
- import org.apache.batik.dom.svg12.BindableElement;
- import org.apache.batik.dom.svg12.SVGOMFlowRootElement;
- import org.apache.batik.dom.util.XLinkSupport;
- import org.apache.batik.ext.awt.MultipleGradientPaint;
- import org.apache.batik.ext.awt.MultipleGradientPaint.CycleMethodEnum;
- import org.apache.batik.gvt.GraphicsNode;
- import org.apache.batik.gvt.TextNode;
- import org.apache.batik.gvt.font.AWTGVTFont;
- import org.apache.batik.gvt.font.GVTFont;
- import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
- import org.apache.batik.gvt.text.TextPaintInfo;
- import org.apache.batik.parser.PathParser;
- import org.apache.batik.parser.TransformListParser;
- import org.apache.batik.util.SVGConstants;
- import org.apache.batik.util.XMLResourceDescriptor;
- import org.mt4j.MTApplication;
- import org.mt4j.components.MTComponent;
- import org.mt4j.components.TransformSpace;
- import org.mt4j.components.bounds.BoundsZPlaneRectangle;
- import org.mt4j.components.bounds.IBoundingShape;
- import org.mt4j.components.clipping.FillPaint;
- import org.mt4j.components.visibleComponents.AbstractVisibleComponent;
- import org.mt4j.components.visibleComponents.font.FontManager;
- import org.mt4j.components.visibleComponents.font.IFont;
- import org.mt4j.components.visibleComponents.shapes.AbstractShape;
- import org.mt4j.components.visibleComponents.shapes.GeometryInfo;
- import org.mt4j.components.visibleComponents.shapes.MTEllipse;
- import org.mt4j.components.visibleComponents.shapes.MTLine;
- import org.mt4j.components.visibleComponents.shapes.MTPolygon;
- import org.mt4j.components.visibleComponents.shapes.MTRectangle;
- import org.mt4j.components.visibleComponents.shapes.MTRectangle.PositionAnchor;
- import org.mt4j.components.visibleComponents.shapes.MTRoundRectangle;
- import org.mt4j.components.visibleComponents.shapes.MTStencilPolygon;
- import org.mt4j.components.visibleComponents.shapes.mesh.MTTriangleMesh;
- import org.mt4j.components.visibleComponents.widgets.MTTextArea;
- import org.mt4j.input.gestureAction.DefaultDragAction;
- import org.mt4j.input.gestureAction.DefaultRotateAction;
- import org.mt4j.input.gestureAction.DefaultScaleAction;
- import org.mt4j.input.inputProcessors.IGestureEventListener;
- import org.mt4j.input.inputProcessors.componentProcessors.dragProcessor.DragProcessor;
- import org.mt4j.input.inputProcessors.componentProcessors.rotateProcessor.RotateProcessor;
- import org.mt4j.input.inputProcessors.componentProcessors.scaleProcessor.ScaleProcessor;
- import org.mt4j.util.HelperMethods;
- import org.mt4j.util.MT4jSettings;
- import org.mt4j.util.MTColor;
- import org.mt4j.util.SwingTextureRenderer;
- import org.mt4j.util.logging.ILogger;
- import org.mt4j.util.logging.MTLoggerFactory;
- import org.mt4j.util.math.ConvexityUtil;
- import org.mt4j.util.math.Matrix;
- import org.mt4j.util.math.ToolsGeometry;
- import org.mt4j.util.math.Vector3D;
- import org.mt4j.util.math.Vertex;
- import org.mt4j.util.opengl.GLTexture;
- import org.mt4j.util.opengl.GluTrianglulator;
- import org.w3c.dom.Document;
- import org.w3c.dom.Element;
- import org.w3c.dom.NamedNodeMap;
- import org.w3c.dom.Node;
- import org.w3c.dom.NodeList;
- import org.w3c.dom.css.CSSPrimitiveValue;
- import org.w3c.dom.css.CSSStyleDeclaration;
- import org.w3c.dom.css.CSSValue;
- import org.w3c.dom.svg.SVGAnimatedLength;
- import org.w3c.dom.svg.SVGDocument;
- import org.w3c.dom.svg.SVGElement;
- import org.w3c.dom.svg.SVGLength;
- import org.w3c.dom.svg.SVGLengthList;
- import org.w3c.dom.svg.SVGMatrix;
- import org.w3c.dom.svg.SVGPoint;
- import org.w3c.dom.svg.SVGPointList;
- import org.w3c.dom.svg.SVGSVGElement;
-
- import processing.core.PApplet;
- import processing.opengl.PGraphicsOpenGL;
-
-
- /**
- * This class can be used to load and display scalable vector graphics (svg) files.
- *
- * @author Christopher Ruff
- */
- public class SVGLoader implements SVGConstants{
- private static final ILogger logger = MTLoggerFactory.getLogger(SVGLoader.class.getName());
- static{
- logger.setLevel(ILogger.ERROR);
- }
-
- /** The svg doc. */
- private SVGDocument svgDoc;
-
- /** The user agent. */
- private UserAgent userAgent;
-
- /** The loader. */
- private DocumentLoader loader;
-
- /** The ctx. */
- private BridgeContext ctx;
-
- /** The builder. */
- private GVTBuilder builder;
-
- /** The root gn. */
- private GraphicsNode rootGN;
-
- /** The css engine. */
- protected SVGCSSEngine cssEngine;
-
- /** The pa. */
- private PApplet pa;
-
- /** The opacity stack. */
- private Stack<Float> opacityStack;
-
- /** The default drag action. */
- private IGestureEventListener defaultDragAction;
-
- /** The default rotate action. */
- private IGestureEventListener defaultRotateAction;
-
- /** The default scale action. */
- private IGestureEventListener defaultScaleAction;
-
- /** The current local transform matrix. */
- private Matrix currentLocalTransformMatrix;
-
-
-
- /**
- * Instantiates a new batik svg parser.
- *
- * @param pa the pa
- */
- public SVGLoader(PApplet pa){
- this.pa = pa;
-
- opacityStack = new Stack<Float>();
-
- currentLocalTransformMatrix = new Matrix();
-
- defaultDragAction = new DefaultDragAction();
- defaultRotateAction = new DefaultRotateAction();
- defaultScaleAction = new DefaultScaleAction();
- }
-
-
- /**
- * Loads a "*.svg" file, parses it, creates drawable components and returns the
- * toplevel component.
- *
- * @param filedescr the absolute path of the svg file as a string
- *
- * @return the MT base component
- *
- * the created top level component of the svg
- */
- public MTComponent loadSvg(String filedescr){
- return this.getCreatedSvgComponents(this.parseSvg(filedescr));
- }
-
-
- /**
- * Uses the batik parser to genererate an svg document from an svg file.
- * To create the components in that svg document, call <code>getCreatedSvgComponents(SVGDocument doc)</code>
- *
- * @param filedescr the filedescr
- *
- * @return the SVG document
- */
- public SVGDocument parseSvg(String filedescr){
- Document doc;
- try {
- String parser = XMLResourceDescriptor.getXMLParserClassName();
- SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(parser);
-
- File file = new File(filedescr);
- if (file.exists()){
- URI localFileAsUri = file.toURI();
- String uri = localFileAsUri.toASCIIString();
- doc = f.createDocument(uri);
- }else{
- InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(filedescr);
- if (in == null){
- in = pa.getClass().getResourceAsStream(filedescr);
- }
- doc = f.createDocument(filedescr, in);
-
- /*on it (after casting it to SVGOMDocument) to give it a
- URI of some sort. If the document needs to be able to have relative
- reference to files on the local file system, give it a URI like
- "file:///some/where/file.svg";
- */
- //FIXME HACK! this seems to help the "org.apache.batik.bridge.BridgeException: Unable to make sense of URL for connection" error
- //occuring with windmill.svg if loading from inputstream instead of local file system file
- //FIXME but this might create errors when loading external file like images from the relative svg path?
- doc.setDocumentURI("") ;
- // String sub = filedescr.substring(0, filedescr.lastIndexOf(MTApplication.separator));
- // System.out.println("F: " + filedescr + " sub; " + sub);
- // svgDoc.setDocumentURI(sub+ MTApplication.separator) ;
- }
- svgDoc = (SVGDocument)doc;
- } catch (Exception ex) {
- ex.printStackTrace();
- }
-
- //Neccesary? For booting css
- try{
- userAgent = new UserAgentAdapter();
- loader = new DocumentLoader(userAgent);
- ctx = new BridgeContext(userAgent, loader);
- ctx.setDynamicState(BridgeContext.DYNAMIC); //TODO use static?
- builder = new GVTBuilder();
- rootGN = builder.build(ctx, svgDoc);
-
- // ctx.getCSSEngineForElement(null).
- }catch(Exception e){
- e.printStackTrace();
- }
- return svgDoc;
- }
-
- /**
- * Creates and returns components of the provided svg document for displaying.
- *
- * @param svgDoc the svg doc
- *
- * @return the created svg components
- */
- public MTComponent getCreatedSvgComponents(SVGDocument svgDoc){
- ArrayList<MTComponent> components = new ArrayList<MTComponent>();
- opacityStack.push(1.0f);
- traverseSVGDoc(svgDoc, components);
- opacityStack.pop();
-
- MTComponent[] comps = components.toArray(new MTComponent[components.size()]);
- //Only returning the 1st component, since this should be the top-level <svg> element and only 1!?
- return comps[0];
- }
-
-
-
- /**
- * Traverse svg doc.
- *
- * @param node the node
- * @param comps the comps
- */
- private void traverseSVGDoc(Node node, ArrayList<MTComponent> comps){
- logger.debug("Traversing: " + node.getNodeName());
-
- //Damit transformationen konsistent sind muss
- //jedes tag, da? eine transform attribut hat
- //behandelt werden!
- //Default
- currentLocalTransformMatrix = new Matrix();
-
- //If there is a TRANSFORM attribute parse that and set the
- //current transformation matrix to be used with the svg components created after
- NamedNodeMap atts = node.getAttributes();
- if (atts != null){
- for (int i = 0; i < atts.getLength(); i++) {
- Node att = atts.item(i);
- if (att.getNodeName().equals(SVG_TRANSFORM_ATTRIBUTE)){
- CustomTransformHandler transFormHandler = new CustomTransformHandler();
- TransformListParser transFormListParser = new TransformListParser();
- transFormListParser.setTransformListHandler(transFormHandler);
- transFormListParser.parse(att.getNodeValue());
- //Overwrite current default matrix if the element has its own
- //transform defined, will be used at gfx obj creation
- currentLocalTransformMatrix = transFormHandler.getResultMatrix();
- }
- }
- }
-
- // logger.debug("Node: " + node.getNodeName() + " Class: " + node.getClass());
-
-
- //For opacity inheritance
- if (node instanceof SVGGraphicsElement){
- SVGGraphicsElement svgGfx = (SVGGraphicsElement)node;
- //Handle inherited opacity settings
- float opac = queryPrimitiveFloatValue(svgGfx, "opacity", 1f);
- opacityStack.push(opac *= opacityStack.peek());
- }
-
- // if G (GROUP) element, add all children to this element
- if ( node instanceof SVGOMGElement
- || node instanceof SVGSVGElement
- || node instanceof SVGOMSVGElement
- ){
- // SVGOMGElement gElem = (SVGOMGElement)node;
- SVGElement gElem = (SVGElement)node;
- MTComponent group = new MTComponent(pa);
- group.setName(gElem.getTagName());
-
- // Element viewPort = gElem.getViewportElement();
- // logger.debug("Viewport " + viewPort.getNodeName());
-
- //Set the <g> group to composite, meaning that it will
- //be returned at picking, when one of the children gets picked
- group.setComposite(true);
-
- group.setLocalMatrix(currentLocalTransformMatrix);
-
- //IF its <svg> element get the transform
- //(to honor the viewBox and the width/height attributes
- if (node instanceof SVGOMSVGElement ){
- SVGOMSVGElement svgGom = ((SVGOMSVGElement)node);
- Element viewPort = svgGom.getViewportElement();
- if (viewPort != null)
- logger.debug("Viewport " + viewPort.getNodeName());
-
- // SVGMatrix mat = svgGom.getScreenCTM();
-
- SVGAnimatedLength widthA = svgGom.getWidth();
- SVGAnimatedLength heightA = svgGom.getHeight();
-
- SVGLength w = widthA.getBaseVal();
- float width = w.getValue();
-
- SVGLength h = heightA.getBaseVal();
- float height = h.getValue();
-
- logger.debug("-> SVG Width: " + width + " Height: " + height);
-
-
- SVGMatrix mat = svgGom.getCTM();
- /*
- logger.debug("mat: " + mat.toString());
- logger.debug(mat.getA());
- logger.debug(mat.getB());
- logger.debug(mat.getC());
- logger.debug(mat.getD());
- logger.debug(mat.getE());
- logger.debug(mat.getF());
- SVGRect bbox = svgGom.getBBox();
- logger.debug("BBOx: X:" + bbox.getX() + " Y:" + bbox.getY() + " Width:" + bbox.getWidth() + " Height:" + bbox.getHeight());
- */
-
- //Hack, because if no width/height is specified default of 1.0
- //is assumed by batik -> things may get scaled too small
- if ( !(width == 1 && height == 1) ){
- currentLocalTransformMatrix = new Matrix(mat.getA(), mat.getC(), 0, mat.getE(),
- mat.getB(), mat.getD(), 0, mat.getF(),
- 0, 0, 1, 0,
- 0, 0, 0, 1
- );
- //logger.debug("Matrix: " + currentLocalTransformMatrix);
- group.setLocalMatrix(currentLocalTransformMatrix);
- }
- }
-
- //Make the group pickable and manipulatable
- group.setPickable(true);
-
- group.registerInputProcessor(new DragProcessor(pa));
- group.setGestureAllowance(DragProcessor.class, true);
- group.addGestureListener(DragProcessor.class, (IGestureEventListener)defaultDragAction);
-
- group.registerInputProcessor(new RotateProcessor(pa));
- group.addGestureListener(RotateProcessor.class, defaultRotateAction);
-
- group.registerInputProcessor(new ScaleProcessor(pa));
- group.addGestureListener(ScaleProcessor.class, defaultScaleAction);
-
- ArrayList<MTComponent> groupChildren = new ArrayList<MTComponent>();
- //Traverse the children and add them to a new arraylist
- traverseChildren(gElem, groupChildren);
-
- MTComponent[] childComps = groupChildren.toArray(new MTComponent[groupChildren.size()]);
- //Add the children to the group
- group.addChildren(childComps);
- //Add the group to the arraylist of the parent
- comps.add(group);
- }else{//If NOT GROUP
- if (node instanceof SVGGraphicsElement){
- SVGGraphicsElement svgGfxElem = (SVGGraphicsElement)node;
- //IF node isnt a group node just add it to the passed in comps arraylist
- try{
- //Create a component from the graphicsnode and add it to the parents arraylist
- MTComponent liveComponent = handleGraphicsNode(svgGfxElem);
- if (liveComponent != null){
- comps.add(liveComponent);
- }
- }catch(Exception e){
- logger.error("Error handling svg node: " + svgGfxElem.getTagName());
- e.printStackTrace();
- }
- }
-
- //FIXME IMPLEMENT
- if (node instanceof SVGOMTSpanElement){
- SVGOMTSpanElement tSpanElement = (SVGOMTSpanElement)node;
-
- }
-
- //FIXME TEST
- if (node instanceof SVGOMTextElement){
- boolean useVectorFont = false;
-
- SVGOMTextElement textElement = (SVGOMTextElement)node;
- //Get <text> position values (can be a list)
- List<Float> xValues = getSVGLengthListAsFloat(textElement.getX().getBaseVal());
- List<Float> yValues = getSVGLengthListAsFloat(textElement.getY().getBaseVal());
- // /*//Not used
- String textContent = TextUtilities.getElementContent(textElement);
- textContent = textContent.replaceAll("\\n","");
- textContent = textContent.trim();
- // */
- /*
- //TODO USE?
- textElement.getTextLength();
- textElement.getRotate();
- */
- if (textElement.getSVGContext() instanceof SVGTextElementBridge){
- SVGTextElementBridge b = (SVGTextElementBridge)textElement.getSVGContext();
- GraphicsNode gr = b.createGraphicsNode(ctx, textElement);
- TextNode tNode = (TextNode)gr;
- b.buildGraphicsNode(ctx, textElement, tNode);
- List<?> textRuns = tNode.getTextRuns();
- logger.debug("Text runs: " + textRuns);
- //Get font size
- float fontSize = b.getFontSize();
-
- logger.debug("Text:" + " x:" + xValues.get(0) + " y:" + yValues.get(0) + " FontSize: " + fontSize + " Text: '" + textContent + "'");
-
- //Get font FILL
- Value fillOpacValue = CSSUtilities.getComputedStyle(textElement, SVGCSSEngine.FILL_OPACITY_INDEX);
- float computedfillOpac = PaintServer.convertOpacity(fillOpacValue);
- Value fillIndexValue = CSSUtilities.getComputedStyle(textElement, SVGCSSEngine.FILL_INDEX);
- Object fill = SVGLoader.getFillOrStroke(textElement, fillIndexValue, computedfillOpac, ctx);
- MTColor fillColor = new MTColor(150,150,150,255);
- if (fill instanceof java.awt.Color) {
- java.awt.Color color = (Color) fill;
- fillColor.setColor(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
- }
-
- //Get STROKE
- // Stroke Opacity \\
- Value strokeOpacValue = CSSUtilities.getComputedStyle(textElement, SVGCSSEngine.STROKE_OPACITY_INDEX);
- float computedStrokeOpacity = PaintServer.convertOpacity(strokeOpacValue);
- // Stroke java.awt.Color \\
- Value strokeIndexValue = CSSUtilities.getComputedStyle(textElement, SVGCSSEngine.STROKE_INDEX);
- Object stroke = SVGLoader.getFillOrStroke(textElement, strokeIndexValue, computedStrokeOpacity, ctx);
- MTColor strokeColor = new MTColor(fillColor.getR(), fillColor.getG(), fillColor.getB(), fillColor.getAlpha());
- if (stroke instanceof java.awt.Color) {
- java.awt.Color color = (Color) stroke;
- strokeColor.setColor(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
- }
-
- //Get the font family
- Value fontFamilyValue = CSSUtilities.getComputedStyle(textElement, SVGCSSEngine.FONT_FAMILY_INDEX);
- String fontFamily = "arial"; //DEFAULT
- if (fontFamilyValue instanceof ListValue) {
- ListValue listValue = (ListValue) fontFamilyValue;
- Value firstValue = listValue.item(0); //Can be a List? -> take only the first one..
- if (firstValue != null)
- fontFamily = firstValue.getStringValue();
- }
- logger.debug("Font family: " + fontFamily);
-
- IFont font;
- if (useVectorFont)
- //Vector font
- font = FontManager.getInstance().createFont(pa,
- "arial.ttf", Math.round(fontSize), fillColor);
- else
- //Bitmap font
- font = FontManager.getInstance().createFont(pa,
- // "Arial", Math.round(fontSize),
- fontFamily, Math.round(fontSize), fillColor);
- // /*
-
- IFont fontToUse = font;
- IFont lastUsedFont = fontToUse;
- List<MTTextArea> textAreas = new ArrayList<MTTextArea>();
-
- AttributedCharacterIterator iter = tNode.getAttributedCharacterIterator();
- if (font != null && iter != null){ //To avoid not loaded fonts or if text ist empty
- for (int i = iter.getBeginIndex(); i < iter.getEndIndex(); i++) {
- char currentChar = iter.setIndex(i);
- Set<Attribute> keys = iter.getAllAttributeKeys();
- Map<Attribute, Object> charAtts = iter.getAttributes();
-
- Object baseLineShift = charAtts.get(SVGTextElementBridge.BASELINE_SHIFT);
- Object paintInfo = charAtts.get(SVGTextElementBridge.PAINT_INFO);
-
- Object charX = charAtts.get(GVTAttributedCharacterIterator.TextAttribute.X);
- Object charY = charAtts.get(GVTAttributedCharacterIterator.TextAttribute.Y);
- Object charDX = charAtts.get(GVTAttributedCharacterIterator.TextAttribute.DX);
- Object charDY = charAtts.get(GVTAttributedCharacterIterator.TextAttribute.DY);
- Object charRotation = charAtts.get(GVTAttributedCharacterIterator.TextAttribute.ROTATION);
- Object gvtFont = charAtts.get(GVTAttributedCharacterIterator.TextAttribute.GVT_FONT);
- Object gvtFonts = charAtts.get(GVTAttributedCharacterIterator.TextAttribute.GVT_FONTS);
- Object gvtFontFamilies = charAtts.get(GVTAttributedCharacterIterator.TextAttribute.GVT_FONT_FAMILIES);
- Object textCompoundDelimiter = charAtts.get(GVTAttributedCharacterIterator.TextAttribute.TEXT_COMPOUND_DELIMITER);
- Object verticalOrientation = charAtts.get(GVTAttributedCharacterIterator.TextAttribute.VERTICAL_ORIENTATION);
- logger.debug("Character: " + currentChar + " CharX:" + charX + " CharY: " + charY + " CharDX: " + charDX + " CharDY: " + charDY + " Font: " + gvtFont + " Fonts: " + gvtFonts + " FontFamilies: " + gvtFontFamilies);
- AWTGVTFont awtGvtFont = (AWTGVTFont)gvtFont;
- if (awtGvtFont != null)
- logger.debug("CharfontSize: " + awtGvtFont.getSize());
-
- //FIXME REMOVE, Not working always 0,0
- SVGPoint startPosOfChar = SVGTextContentSupport.getStartPositionOfChar(textElement, i);
-
- /////////////////////////////////////
- //Get the character information - font, colors
- String newFamilyName = fontFamily;
- float newFontSize = fontSize;
- MTColor newFillColor = new MTColor(fillColor);
- MTColor newStrokeColor = new MTColor(strokeColor);
- boolean charHasColorInfo = false;
- boolean charHasFontInfo = false;
- //Get chars paint info
- if (paintInfo != null && paintInfo instanceof TextPaintInfo){
- charHasColorInfo = true;
- TextPaintInfo texInfo = (TextPaintInfo)paintInfo;
- if (texInfo.fillPaint instanceof java.awt.Color){
- java.awt.Color color = (Color)texInfo.fillPaint;
- newFillColor.setColor(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
- }
- if (texInfo.strokePaint instanceof java.awt.Color){
- java.awt.Color color = (Color)texInfo.strokePaint;
- newStrokeColor.setColor(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
- }
- }
-
- //Get the chars font family and size
- GVTFont aGvtFont = null;
- if (gvtFonts!=null){
- if (gvtFonts instanceof List) {
- List<?> fonts = (List<?>) gvtFonts;
- for (Object o : fonts) {
- if (o instanceof GVTFont) {
- aGvtFont = (GVTFont) o;
- //logger.debug("Char font family: " + aGvtFont.getFamilyName() + " Size:" + aGvtFont.getSize());
- }
- }
- }
- }
- if (aGvtFont != null){
- charHasFontInfo = true;
- newFamilyName = aGvtFont.getFamilyName();
- newFontSize = aGvtFont.getSize();
- }else{
- logger.error("Character: " + currentChar + " has no font attached.");
- }
-
- if (charHasColorInfo && charHasFontInfo){
- logger.debug("Character '" + currentChar + "'-> has font info -> load font!" +
- " Family: " + newFamilyName +
- " Fontsize: " + Math.round(newFontSize) +
- " FillColor: " + newFillColor +
- " StrokeColor: " + newStrokeColor);
-
- if (useVectorFont)
- fontToUse = FontManager.getInstance().createFont(pa,
- "arial.ttf", Math.round(newFontSize), newFillColor);
- else
- fontToUse = FontManager.getInstance().createFont(pa, //uses cached font if available
- // "Arial", Math.round(fontSize),
- newFamilyName, Math.round(newFontSize), newFillColor);
- if (fontToUse == null){
- fontToUse = font;
- }
- }else{
- fontToUse = font;
- }
- boolean fontChanged = !FontManager.isFontsAreEqual(fontToUse, lastUsedFont);
- lastUsedFont = fontToUse;
-
- // //FIXME REMOVE TEST
- // fontChanged = true;
- ///////////////////////////////////////
- boolean textPositionChanged = charX != null || charY != null || charDX != null || charDY != null;
-
- //TODO if we forceAnewTextarea because of font change but ther is NO NEW POSITION, we
- //have to set the textareas anchor to the lower left
- //TODO problem if we have a tspan centered and a next tspan without new position
- //-> the first tspan textarea gets centered on the position
- //but we would have to treat them (all in the same line) as 1 textarea when center positioning!
-
- //FIXME there are slight differences because we use a different SPACE character length and no font KERNING!
-
- //FIXME DO WIDHTOUT USERDATA
- //FIXME bitmap font has no top border, vector has.. why?
- //TODO -> eventuell doch in handleSvgNode machen?
- //-> statt graphicsnode /stylable node ?bergeben? - SVGOMTextElement is nicht instanceof graphicsnode..
-
- // we have to check font/color etc at every character, not only at new positon because
- //pos doesent change at tspans without new posinfo
- //check if equal to last used font and if equal original text font
- if ( fontChanged || textPositionChanged
- ){ //Make a new textarea if the text position changed or if the font changed at the current character
- MTTextArea previousTextArea = null;
- if (!textAreas.isEmpty()){
- previousTextArea = textAreas.get(textAreas.size()-1);
- }
-
- float newXPos = 0;
- float newYPos = 0 ;
-
- //If there is a previous text, get its ending coordinates
- //for the DX and DY shift info for the next text area
- if (previousTextArea != null){
- PositionAnchor oldAnchor = previousTextArea.getAnchor();
- // previousTextArea.setAnchor(PositionAnchor.LOWER_RIGHT);
- previousTextArea.setAnchor(PositionAnchor.UPPER_LEFT);
- //Calculate last/current textposition for DX and DY use
- //add up the last textareas start position end position(width)
- Vector3D lastPos = previousTextArea.getPosition(TransformSpace.LOCAL);
- // lastPos.addLocal(new Vector3D(previousTextArea.getWidthXY(TransformSpace.LOCAL) - 1 * previousTextArea.getInnerPaddingLeft(),0));
- lastPos.addLocal(new Vector3D(previousTextArea.getWidthXY(TransformSpace.LOCAL) - 2 * previousTextArea.getInnerPaddingLeft(),0));
- // newXPos = lastPos.x - previousTextArea.getInnerPaddingLeft();
- newXPos = lastPos.x;
- newXPos += (Float)previousTextArea.getUserData("XPos");
-
- newYPos = lastPos.y;
- // newYPos -= previousTextArea.getInnerPaddingTop();
- // newYPos += fontToUse.getFontMaxDescent(); //FIXME WHY NEVESSARY?
- newYPos += (Float)previousTextArea.getUserData("YPos");
- previousTextArea.setAnchor(oldAnchor);
- }
-
- //IF absolute x or y is present overwrite the position values from the last textarea
- if (charX != null)
- newXPos = (Float)charX;
- if (charY != null)
- newYPos = (Float)charY;
- if (charDX != null)
- newXPos += (Float)charDX;
- if (charDY != null)
- newYPos += (Float)charDY;
-
- // Create the text area \\
- MTTextArea t = new MTTextArea(pa, fontToUse);
- t.setNoFill(true);
- t.setNoStroke(true);
- textAreas.add(t);
- try{
- t.setLocalMatrix(new Matrix(currentLocalTransformMatrix));
- }catch(Exception e){
- logger.error(e.getMessage());
- }
-
- //FIXME TEST
- // if (previousTextArea != null && !textPositionChange){
- // t.setAnchor(PositionAnchor.LOWER_LEFT);
- // t.setUserData("posRelParent", new Vector3D(newXPos , newYPos - fontToUse.getFontMaxDescent() , 0));
- // logger.debug("Character '" + currentChar + "' -> Anchor: LOWER_LEFT");
- // }else{
- Value v = CSSUtilities.getComputedStyle(textElement, SVGCSSEngine.TEXT_ANCHOR_INDEX);
- //INFO: we have to move the BASELINE of the text to the svg position
- //The textarea is usually fontmaxascent+fontmaxdescent+2*innerPadding big!
- switch (v.getStringValue().charAt(0)) {
- case 'e':
- t.setAnchor(PositionAnchor.LOWER_RIGHT);
- t.setUserData("posRelParent", new Vector3D((newXPos + t.getInnerPaddingLeft()) , newYPos - fontToUse.getFontMaxDescent() + t.getInnerPaddingTop() , 0));
- // t.setPositionRelativeToParent(new Vector3D(newXPos, newYPos - font.getFontMaxDescent() , 0));
- logger.debug("Character '" + currentChar + "' -> Anchor: LOWER_RIGHT");
- break;
- case 'm': //text-anchor="middle"
- t.setAnchor(PositionAnchor.CENTER);
- // t.setUserData("posRelParent", new Vector3D(newXPos, newYPos - fontToUse.getFontMaxAscent()*0.5f - fontToUse.getFontMaxDescent()*0.5f , 0));
- // t.setUserData("posRelParent", new Vector3D(newXPos, newYPos - fontToUse.getFontAbsoluteHeight()*0.5f + t.getInnerPaddingTop() , 0));
- // t.setPositionRelativeToParent(new Vector3D(newXPos, newYPos - font.getFontMaxAscent()*0.5f - font.getFontMaxDescent()*0.5f, 0)); //- font.getFontMaxAscent()*0.5f
- logger.debug("Character '" + currentChar + "' -> Anchor: CENTER");
- t.setUserData("posRelParent", new Vector3D((newXPos), (newYPos - fontToUse.getFontMaxDescent() + t.getInnerPaddingTop()) - t.getHeightXY(TransformSpace.LOCAL)/2f , 0));
- break;
- default: //text-anchor="start" //default!
- t.setAnchor(PositionAnchor.LOWER_LEFT);
- // t.setUserData("posRelParent", new Vector3D(newXPos -t.getInnerPaddingLeft(), newYPos - fontToUse.getFontMaxDescent() + t.getInnerPaddingTop() , 0));
- t.setUserData("posRelParent", new Vector3D(newXPos -t.getInnerPaddingLeft(), newYPos - fontToUse.getFontMaxDescent() + t.getInnerPaddingTop() , 0));
-
- // t.setAnchor(PositionAnchor.UPPER_LEFT);
- // t.setUserData("posRelParent", new Vector3D(newXPos -t.getInnerPaddingLeft(), newYPos, 0));
- // t.setPositionRelativeToParent(new Vector3D(newXPos, newYPos - font.getFontMaxDescent() , 0));
- logger.debug("Character '" + currentChar + "' -> Anchor: LOWER_LEFT");
- }
- t.setUserData("XPos", newXPos);
- t.setUserData("YPos", newYPos);
- // }
- }
- //Add character to the current textarea in the list
- if (!textAreas.isEmpty()){
- textAreas.get(textAreas.size()-1).appendCharByUnicode(Character.toString(currentChar));
- }
- }
- //Set the positions of the textareas
- for (MTTextArea textArea : textAreas) {
- logger.debug("Adding text area at: " + (Vector3D) textArea.getUserData("posRelParent"));
- textArea.setPositionRelativeToParent((Vector3D) textArea.getUserData("posRelParent"));
- }
- comps.addAll(textAreas);
- }
-
- /*
- //This gets only the text of this hierarchy level
- StringBuffer result = new StringBuffer();
- for (Node n = textElement.getFirstChild();
- n != null;
- n = n.getNextSibling()) {
- switch (n.getNodeType()) {
- case Node.ELEMENT_NODE:
- break;
- case Node.CDATA_SECTION_NODE:
- case Node.TEXT_NODE:
- result.append(n.getNodeValue());
- }
- }
- logger.debug("TEXTTTT2: " + result);
- */
- // */////////////////////
-
- }
- }
- }
-
-
- if (node instanceof SVGGraphicsElement){
- //Remove inherited opacity attribute from stack
- opacityStack.pop();
- }
-
- //Traverse the children, not if it was a group element
- //because then the children are already
- //traversed in the if (group) block above
- if ( !(node instanceof SVGOMGElement)
- && !(node instanceof SVGSVGElement)
- && !(node instanceof SVGOMSVGElement)
- ){
- traverseChildren(node, comps);
- }
- }
-
-
-
- /**
- * Traverse children.
- *
- * @param node the node
- * @param comps the comps
- */
- private void traverseChildren(Node node, ArrayList<MTComponent> comps){
-
- //Check the children
- NodeList nl = node.getChildNodes();
- for (int i = 0; i < nl.getLength(); i++) {
- Node currentNode = nl.item(i);
- traverseSVGDoc(currentNode, comps);
- }
- }
-
-
- /**
- * Handle graphics node.
- *
- * @param gfxElem the gfx elem
- *
- * @return the mT base component
- */
- private MTComponent handleGraphicsNode(SVGGraphicsElement gfxElem){
- MTComponent returnComp = null;
- // logger.debug("Handle Element: " + gfxElem.getTagName());
-
- //Print all css properties and values
- // logger.debug("Style Css Text: " + style.getCssText());
-
- // SVG Defaults \\
- float fillR = 255;
- float fillG = 255;
- float fillB = 255;
- boolean noFill = false;
- float strokeR = 0;
- float strokeG = 0;
- float strokeB = 0;
- float strokeWidth = 1.0f;
- boolean noStroke = false;
- float strokeOpacity = 1;
- float fillOpacity = 1;
- int windingRule = GLU.GLU_TESS_WINDING_NONZERO;
- // SVG Defaults \\
-
-
- // Opacity, not as a style attribute but a separate
- // as group opacity doesnt get computed right, so we
- // mannually track it on a stack
- float opacity = opacityStack.peek();
- //logger.debug("INHERITED OPACITY: " + opacity);
-
-
- // FILL-RULE \\
- Value fillRuleValue = CSSUtilities.getComputedStyle(gfxElem, SVGCSSEngine.FILL_RULE_INDEX);
- String fillRule = fillRuleValue.getStringValue();
- if (fillRule.equalsIgnoreCase("nonzero")){
- windingRule = GLU.GLU_TESS_WINDING_NONZERO;
- }else if (fillRule.equalsIgnoreCase("evenodd")){
- windingRule = GLU.GLU_TESS_WINDING_ODD;
- }else{
- windingRule = GLU.GLU_TESS_WINDING_NONZERO;
- }
- //logger.debug("fillRule: " + fillRule);
-
-
- // Fill Opacity \\
- fillOpacity = PaintServer.convertOpacity(CSSUtilities.getComputedStyle(gfxElem, SVGCSSEngine.FILL_OPACITY_INDEX));
- //Multiplicate inherited opacity with this components opacities
- fillOpacity *= opacity;
- //Save for eventual lineargradient creation later that needs the not interpolated value
- float originalFillOpacity = fillOpacity;
- //logger.debug("fill opacity unnormalized: " + fillOpacity);
-
-
- // Fill java.awt.Color \\
- Value fillIndexValue = CSSUtilities.getComputedStyle(gfxElem, SVGCSSEngine.FILL_INDEX);
- Object fill = SVGLoader.getFillOrStroke(gfxElem, fillIndexValue, fillOpacity, ctx);
- SVGOMLinearGradientElement linearGradient = null;
- SVGOMRadialGradientElement radialGradient = null;
- if (fill instanceof java.awt.Color) {
- java.awt.Color color = (Color) fill;
- fillR = color.getRed();
- fillG = color.getGreen();
- fillB = color.getBlue();
- fillOpacity = color.getAlpha();
- noFill = false;
- //logger.debug("Fill: " + color + " a=" + fillOpacity);
- }else if (fill instanceof SVGOMLinearGradientElement) {
- //TODO cache gradients so dass man nicht immer neu den gleichen
- //machen muss!
- linearGradient = (SVGOMLinearGradientElement) fill;
- noFill = false;
- }else if (fill instanceof SVGOMRadialGradientElement) {
- //TODO!! //FIXME TEST
- radialGradient = (SVGOMRadialGradientElement)fill;
- noFill = false;
- }else{
- noFill = true;
- }
-
-
- // Stroke Opacity \\
- strokeOpacity = PaintServer.convertOpacity(CSSUtilities.getComputedStyle(gfxElem, SVGCSSEngine.STROKE_OPACITY_INDEX));
- // Multiplicate inherited opacity with this components group opacities
- strokeOpacity *= opacity;
-
-
- // Stroke java.awt.Color \\
- Value strokeIndexValue = CSSUtilities.getComputedStyle(gfxElem, SVGCSSEngine.STROKE_INDEX);
- Object stroke = SVGLoader.getFillOrStroke(gfxElem, strokeIndexValue, strokeOpacity, ctx);
- if (stroke instanceof java.awt.Color) {
- java.awt.Color color = (Color) stroke;
- strokeR = color.getRed();
- strokeG = color.getGreen();
- strokeB = color.getBlue();
- strokeOpacity = color.getAlpha();
- noStroke = false;
- }else{
- noStroke = true;
- strokeR = fillR;
- strokeG = fillG;
- strokeB = fillB;
- }
-
-
- // Stroke Width \\
- Stroke s = PaintServer.convertStroke(gfxElem);
- if (s != null){
- if (s instanceof BasicStroke) {
- BasicStroke basicStroke = (BasicStroke) s;
- strokeWidth = basicStroke.getLineWidth();
- }
- }else{
- strokeWidth = 0.0f;
- noStroke = true;
- }
-
- /*
- logger.debug("Fill COL: " + fillR + " " + fillG + " " + fillB + " " fillopacity);
- logger.debug("STROKE COL: " + strokeR + " " + strokeG + " " + strokeB + " " strokeOpacity);
- */
-
- // CHECK WHAT KIND OF GRAPHICS ELEMENT IT IS AND CREATE IT \\
- if (gfxElem instanceof SVGOMPathElement){
- SVGOMPathElement pathElem = (SVGOMPathElement)gfxElem;
-
- //FIXME handle clip-paths in the future
- if (isUnderClipPath(pathElem)){
- logger.error("Discarding clip-path path element. Not implemented.");
- return null;
- }
-
- //Create the shape
- AbstractShape pathComp = getLivePathComponent(pathElem, noFill, windingRule);
-
- try{
- pathComp.setLocalMatrix(currentLocalTransformMatrix);
- }catch(Exception e){
- logger.error(e.getMessage());
- }
- returnComp = pathComp;
- }else if (gfxElem instanceof SVGOMPolygonElement){
- SVGOMPolygonElement polygonElem = (SVGOMPolygonElement)gfxElem;
-
- //Create the shape
- AbstractShape comp = getLivePolygonComponent(polygonElem, noFill, windingRule);
-
- try{
- comp.setLocalMatrix(currentLocalTransformMatrix);
- }catch(Exception e){
- logger.error(e.getMessage());
- }
- returnComp = comp;
- }else if (gfxElem instanceof SVGOMPolylineElement){
- SVGOMPolylineElement polyLineElem = (SVGOMPolylineElement)gfxElem;
-
- //Create Vertex[] from points
- SVGPointList pointList = polyLineElem.getPoints();
- Vertex[] vertices = new Vertex[pointList.getNumberOfItems()];
- for (int i = 0; i < pointList.getNumberOfItems(); i++) {
- SVGPoint p = pointList.getItem(i);
- vertices[i] = new Vertex(p.getX(), p.getY(),0);
- }
-
- //Create the shape
- AbstractShape comp = createPoly(vertices);
-
- try{
- comp.setLocalMatrix(currentLocalTransformMatrix);
- }catch(Exception e){
- logger.error(e.getMessage());
- }
- returnComp = comp;
- }else if (gfxElem instanceof SVGOMRectElement){
- SVGOMRectElement rectElem = (SVGOMRectElement)gfxElem;
- if (isUnderClipPath(rectElem)){
- logger.error("discarding clip-path Rect");
- return null;
- }
-
- float x = rectElem.getX().getBaseVal().getValue();
- float y = rectElem.getY().getBaseVal().getValue();
- float width = rectElem.getWidth().getBaseVal().getValue();
- float height = rectElem.getHeight().getBaseVal().getValue();
- float rx = rectElem.getRx().getBaseVal().getValue();
- float ry = rectElem.getRy().getBaseVal().getValue();
-
- AbstractShape comp;
- //Create a normal rectangle or a round rectangle
- if (rx != 0.0f || ry != 0.0f){
- if (rx > width/2 )
- rx = width/2;
- if (ry > height/2 )
- ry = height/2;
- comp = new MTRoundRectangle(pa,x,y, 0,width,height, rx, ry);
- }else{
- comp = new MTRectangle(pa,x, y,width, height);
- }
-
- try{
- comp.setLocalMatrix(currentLocalTransformMatrix);
- }catch(Exception e){
- logger.error(e.getMessage());
- }
- returnComp = comp;
- }else if (gfxElem instanceof SVGOMEllipseElement){
- SVGOMEllipseElement ellipseElem = (SVGOMEllipseElement)gfxElem;
- float cx = ellipseElem.getCx().getBaseVal().getValue();
- float cy = ellipseElem.getCy().getBaseVal().getValue();
- float r = ellipseElem.getRx().getBaseVal().getValue();
- float r2 = ellipseElem.getRy().getBaseVal().getValue();
-
- Vertex middlePoint = new Vertex(cx,cy,0);
- //Apply transformation, transform centerpoint and the radii
- try{
- middlePoint.transform(currentLocalTransformMatrix);
- }catch(Exception e){
- logger.error(e.getMessage());
- }
-
- //somehow the circle radii need to be doubled
- //or else theyre too small => processing bug?
- // r*=2;
- // r2*=2;
- MTEllipse comp = new MTEllipse(pa, middlePoint, r, r2);
- returnComp = comp;
- }else if (gfxElem instanceof SVGOMCircleElement){
- SVGOMCircleElement circleElem = (SVGOMCircleElement)gfxElem;
- float cx = circleElem.getCx().getBaseVal().getValue();
- float cy = circleElem.getCy().getBaseVal().getValue();
- float r = circleElem.getR().getBaseVal().getValue();
- float r2 = circleElem.getR().getBaseVal().getValue();
-
- Vertex middlePoint = new Vertex(cx,cy,0);
- //Apply transformation, transform centerpoint and the radii
- try{
- middlePoint.transform(currentLocalTransformMatrix);
- }catch(Exception e){
- logger.error(e.getMessage());
- }
-
- //somehow the circle radii need to be doubled
- //or else theyre too small => processing bug?
- // r*=2;
- // r2*=2;
- MTEllipse comp = new MTEllipse(pa, middlePoint, r, r2);
- returnComp = comp;
- }else if (gfxElem instanceof SVGOMLineElement){
- SVGOMLineElement line = (SVGOMLineElement)gfxElem;
- float x1 = line.getX1().getBaseVal().getValue();
- float y1 = line.getY1().getBaseVal().getValue();
- float x2 = line.getX2().getBaseVal().getValue();
- float y2 = line.getY2().getBaseVal().getValue();
- //logger.debug("Line x1: " + x1 + ",y1:" + y1 + ",x2:" + x2 + ",y2:" + y2);
-
- MTLine comp = new MTLine(pa, x1,y1 ,x2,y2);
-
- try{
- comp.setLocalMatrix(currentLocalTransformMatrix);
- }catch(Exception e){
- logger.error(e.getMessage());
- }
- returnComp = comp;
- }else if (gfxElem instanceof SVGOMClipPathElement){
- }else if (gfxElem instanceof SVGOMDefsElement){
- }else if (gfxElem instanceof SVGOMMaskElement){
- }else if (gfxElem instanceof SVGOMSwitchElement){
- }else if (gfxElem instanceof SVGOMFlowRootElement){
- }else if (gfxElem instanceof SVGURIReferenceGraphicsElement){
- }else if (gfxElem instanceof BindableElement){
- }else if (gfxElem instanceof SVGOMForeignObjectElement){
- }else if (gfxElem instanceof SVGOMToBeImplementedElement){
- }
-
- //Do the finishing touch of the svg graphics element
- if (returnComp != null){
- returnComp.setName(gfxElem.getTagName());
-
- //Set style infos
- if (returnComp instanceof AbstractVisibleComponent){
- AbstractVisibleComponent comp = (AbstractVisibleComponent)returnComp;
- //Set Fill
- comp.setFillColor(new MTColor(fillR, fillG, fillB, fillOpacity));
- comp.setNoFill(noFill);
- //Set Stroke
- comp.setStrokeColor(new MTColor(strokeR, strokeG, strokeB, strokeOpacity));
- //Opengl cant handle big lines well
- //So cap at width 3
- if (strokeWidth > 2.0f)
- strokeWidth = 2.0f;
- comp.setStrokeWeight(strokeWidth);
- comp.setNoStroke(noStroke);
- //Other
- comp.setDrawSmooth(true);
- comp.setPickable(false);
-
- //Hack for smoothing non stroked components with a stroke same as fillcolor
- if (comp.isNoStroke()
- && linearGradient == null
- ){
- comp.setStrokeColor(new MTColor(fillR, fillG, fillB, fillOpacity)); //fillOpacity
- comp.setStrokeWeight(0.6f);
- //Ellipse doesent smooth right with 0.1f strokeweight
- if (comp instanceof MTEllipse){
- comp.setStrokeWeight(1.0f);
- }
- comp.setNoStroke(false);
- }
-
- //Some settings for Geometric shapes (actually should all be)
- if (comp instanceof AbstractShape ){
- AbstractShape shape = (AbstractShape)comp;
- //Set a bounding rectangle to check first at picking
- if (shape.getVerticesLocal().length >= 3){
- shape.setBoundsBehaviour(AbstractShape.BOUNDS_CHECK_THEN_GEOMETRY_CHECK);
- //shape.setBoundingShape(new BoundsZPlaneRectangle(shape)); //already done by override, (ie svgpoly)
-
- //Create amd apply the linear gradient if existant and if we are in opengl rendering mode
- if (MT4jSettings.getInstance().isOpenGlMode()){
- if (linearGradient != null){
- FillPaint gradient = this.createLinearGradient(linearGradient, gfxElem, originalFillOpacity, shape);
- if (gradient != null){
- shape.setFillPaint(gradient);
- }
- }
- if (radialGradient != null){
- FillPaint gradient = this.createRadialGradient(radialGradient, gfxElem, opacity, shape);
- if (gradient != null){
- shape.setFillPaint(gradient);
- }
- }
- //Per default use direct gl drawing and displaylists in OGL mode
- if (pa instanceof MTApplication) {
- MTApplication app = (MTApplication) pa;…