Logo Search packages:      
Sourcecode: latexdraw version File versions  Download package

LShapeSVGGenerator.java

package latexDraw.generators.svg;

import static java.lang.Math.PI;
import static java.lang.Math.toDegrees;

import java.awt.Color;
import java.awt.geom.Point2D;
import java.text.ParseException;

import latexDraw.figures.ArrowHead;
import latexDraw.figures.Figure;
import latexDraw.figures.LaTeXDrawRectangle;
import latexDraw.figures.Line;
import latexDraw.parsers.svg.*;
import latexDraw.parsers.svg.elements.*;
import latexDraw.parsers.svg.elements.path.SVGPathSegLineto;
import latexDraw.parsers.svg.elements.path.SVGPathSegList;
import latexDraw.parsers.svg.elements.path.SVGPathSegMoveto;
import latexDraw.parsers.svg.parsers.SVGLengthParser;
import latexDraw.parsers.svg.parsers.URIReferenceParser;
import latexDraw.psTricks.PSTricksConstants;
import latexDraw.util.LaTeXDrawNamespace;
import latexDraw.util.LaTeXDrawPoint2D;

import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * This class allows the generation or the importation of SVG parameters to a general LaTeXDraw shape.<br>
 *<br>
 * This file is part of LaTeXDraw.<br>
 * Copyright (c) 2005-2008 Arnaud BLOUIN<br>
 *<br>
 *  LaTeXDraw 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 2 of the License, or
 *  (at your option) any later version.<br>
 *<br>
 *  LaTeXDraw is distributed 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.<br>
 *<br>
 * 10/24/07<br>
 * @author Arnaud BLOUIN<br>
 * @version 2.0.0<br>
 */
00048 public abstract class LShapeSVGGenerator
{
      protected Figure shape;
      
      
      public LShapeSVGGenerator(Figure f)
      {
            if(f==null)
                  throw new IllegalArgumentException();
            
            shape = f;
      }
      
      
      
      /**
       * @return The SVG ID of the shape (starting with the token "id" followed by the number of the shape).
       * @since 2.0.0
       */
00067       public String getSVGID()
      {
            return "id" + shape.getNumber(); //$NON-NLS-1$
      }
      
      
      
      /**
       * Sets the ID of the figure according to the ID attribute of the SVGGElement, or an increment of meter if a problem occur.
       * @param g The SVGGElement.
       * @since 2.0.0
       */
00079       public void setNumber(SVGGElement g)
      {
            if(g==null)
                  return;
            
            String nb = g.getAttribute(g.getUsablePrefix()+SVGAttributes.SVG_ID);
            String pref = "id"; //$NON-NLS-1$
            
            if(nb==null)
                  shape.setNewNumber();
            else
                  try{ shape.setNumber(Double.valueOf(nb).intValue()); }
                  catch(NumberFormatException e) 
                  {
                        if(nb.startsWith(pref))
                              try { shape.setNumber(Double.valueOf(nb.substring(pref.length())).intValue()); }
                              catch(NumberFormatException e2) 
                              { shape.setNewNumber(); }
                        else
                              shape.setNewNumber();
                  }
      }

      
      
      
      /**
       * Applies the set of transformations that concerned the given SVG element to the shape.
       * @param elt The element that contains the SVG transformation list.
       * @since 2.0.0
       */
00110       public void applyTransformations(SVGElement elt)
      {
            if(elt==null)
                  return ;
            
            SVGTransformList tl = elt.getWholeTransform();  // The list of the transformations that are applied on the element.
            
            for(int i = tl.size()-1; i>=0; i--)
                  applyTransformation(tl.elementAt(i));
      }
      
      
      
      
      /**
       * Applies an SVG transformation on the shape.
       * @param t The SVG transformation to apply.
       * @since 2.0.0
       */
00129       public void applyTransformation(SVGTransform t)
      {
            if(t!=null)
                  switch(t.getType())
                  {
                        case SVGTransform.SVG_TRANSFORM_ROTATE:
                              getShape().rotate(new LaTeXDrawPoint2D(t.getMatrix().getE(), t.getMatrix().getF()), 
                                                                                          Math.toRadians(t.getRotationAngle()));
                              break;
                              
                        case SVGTransform.SVG_TRANSFORM_SCALE:
                              break;
                              
                        case SVGTransform.SVG_TRANSFORM_TRANSLATE:
                              getShape().shift(t.getTX(), t.getTY());
                              break;
                              
                        //TODO Quand 'Bordel !' sera implémenté, y mettre les trucs qui vont dans 'default:'.
                  }
      }
      
      
      
      /**
       * When the arrows are read from an SVG document, we need to set the parameters of the first 
       * arrow to the second arrow and vise et versa; because the arrows of a shape share the same
       * parameters. This method carries out this job.
       * @param ah1 The first arrow.
       * @param ah2 The second arrow.
       * @since 2.0.0
       */
00160       public void homogeniseArrows(ArrowHead ah1, ArrowHead ah2)
      {
            if(ah1==null || ah2==null)
                  return ;
            
            homogeniseArrowFrom(ah1, ah2);
            homogeniseArrowFrom(ah2, ah1);
      }
      
      
      
      /**
       * Copies the parameters of the first arrow to the second arrow (only
       * the parameters of the current style are copied).
       * @see #homogeniseArrows(ArrowHead, ArrowHead)
       * @param source The arrow that will be copied.
       * @param target The arrow that will be set.
       * @since 2.0.0
       */
00179       protected void homogeniseArrowFrom(ArrowHead source, ArrowHead target)
      {
            if(source==null || target==null)
                  return ;
            
            String style = source.getArrowStyle();
            
            if(style.equals(PSTricksConstants.NONEARROW_STYLE))
                  return ;
            
            if(style.equals(PSTricksConstants.BAREND_STYLE) || style.equals(PSTricksConstants.BARIN_STYLE))
            {
                  target.setTBarSizeDim(source.getTBarSizeDim());
                  target.setTBarSizeNum(source.getTBarSizeNum());
            }
            else if(style.equals(PSTricksConstants.LARROW_STYLE) || style.equals(PSTricksConstants.RARROW_STYLE) ||
                        style.equals(PSTricksConstants.DLARROW_STYLE) || style.equals(PSTricksConstants.DRARROW_STYLE))
            {
                  target.setArrowInset(source.getArrowInset());
                  target.setArrowLength(source.getArrowLength());
                  target.setArrowSizeDim(source.getArrowSizeDim());
                  target.setArrowSizeNum(target.getArrowSizeNum());
            }
            else if(style.equals(PSTricksConstants.RRBRACKET_STYLE) || style.equals(PSTricksConstants.LRBRACKET_STYLE))
            {
                  target.setRBracketNum(source.getRBracketNum());
                  target.setTBarSizeDim(source.getTBarSizeDim());
                  target.setTBarSizeNum(source.getTBarSizeNum());
            }
            else if(style.equals(PSTricksConstants.RSBRACKET_STYLE) || style.equals(PSTricksConstants.LSBRACKET_STYLE))
            {
                  target.setBracketNum(source.getBracketNum());
                  target.setTBarSizeDim(source.getTBarSizeDim());
                  target.setTBarSizeNum(source.getTBarSizeNum());
            }
            else if(style.equals(PSTricksConstants.DISKEND_STYLE) || style.equals(PSTricksConstants.DISKIN_STYLE) ||
                        style.equals(PSTricksConstants.CIRCLEEND_STYLE) || style.equals(PSTricksConstants.CIRCLEIN_STYLE))
            {
                  target.setDotSizeDim(source.getDotSizeDim());
                  target.setDotSizeNum(source.getDotSizeNum());
            }
      }
      
      
      
      /**
       * Sets the shadow parameters of the figure by using an SVG element having "type:shadow".
       * @param elt The source element.
       * @since 2.0.0
       */
00229       protected void setSVGShadowParameters(SVGElement elt)
      {
            if(elt==null || !shape.canHaveShadow())
                  return ;
            
            String fill = elt.getFill();
            
            if(fill!=null && !fill.equals(SVGAttributes.SVG_VALUE_NONE) && !fill.startsWith("url(#"))//$NON-NLS-1$
                  shape.setShadowColor(CSSColors.getRGBColour(fill));
            
            SVGTransformList tl = elt.getTransform();
            SVGTransform t;
            double tx, ty;
            boolean sSize = false, sAngle = false;
            
            for(int i=0, size=tl.size(); i<size && (!sSize || !sAngle); i++ )
            {
                  t = tl.elementAt(i);
                  
                  if(t.isTranslation())
                  {
                        tx = t.getTX();
                        ty = t.getTY();
                        
                        if(ty==0. && !sSize)// It is shadowSize.
                        {
                              shape.setShadowSize(tx);
                              sSize = true;
                        }
                        else
                              if(shape.getGravityCenter()!=null)
                              {
                                    shape.updateGravityCenter();
                                    Point2D.Double gravityCenter = shape.getGravityCenter();
                                    double angle = Double.NaN, shSize = shape.getShadowSize();
                                    
                                    if(ty==0.)
                                          angle = tx<0. ? Math.PI : 0.;
                                    else
                                          if(shSize==Math.abs(tx))
                                                angle = ty>0. ? -Math.PI/2. : Math.PI/2.;
                                          else
                                          {
                                                angle = Math.acos(gravityCenter.distance(gravityCenter.x+tx+shSize, gravityCenter.y)/
                                                                              gravityCenter.distance(gravityCenter.x+tx+shSize, gravityCenter.y+ty));
                                                
                                                if(tx+shSize<0)
                                                {
                                                      if(ty<0.)
                                                            angle = Math.PI - angle;
                                                      else
                                                            angle += Math.PI;
                                                }
                                                else
                                                      if(ty>0.)
                                                            angle *= -1;
                                          }
                                    
                                    shape.setShadowAngle(angle);
                                    sAngle = true;
                              }
                  }
            }
            
            shape.setHasShadow(true);
      }
      
      
      
      /**
       * Sets the double borders parameters of the figure by using an SVG element.
       * @param elt The SVG element.
       * @since 2.0.0
       */
00303       protected void setSVGDbleBordersParameters(SVGElement elt)
      {
            if(elt==null)
                  return ;
            
            shape.setDoubleSep(elt.getStrokeWidth());
            shape.setDoubleColor(elt.getStroke());
            shape.setThickness((float)((shape.getThickness()-shape.getDoubleSep())/2.));
            shape.setHasDoubleBoundary(true);
      }
      
      
      
      
      protected void setSVGLatexdrawParameters(SVGElement elt)
      {
            if(elt==null)
                  return ;
            
            if(shape.isBordersMovable())
            {
                  String bp = elt.getAttribute(elt.getUsablePrefix(LaTeXDrawNamespace.LATEXDRAW_NAMESPACE_URI)+
                                                            LaTeXDrawNamespace.XML_BORDERS_POS);
                  
                  if(bp!=null)
                        shape.setBordersPosition(bp);
            }
      }
      
      
      
      /**
       * Sets the global parameters of the figure by using an SVG element.
       * @param elt The SVG element.
       * @since 2.0.0
       */
00339       protected void setSVGParameters(SVGElement elt)
      {
            if(elt==null)
                  return ;
            
            if(shape.isThicknessable())
                  shape.setThickness((float)elt.getStrokeWidth());
            
            shape.setLinesColor(elt.getStroke());
            
            if(shape.isDashableOrDotable())
                  LShapeSVGGenerator.setDashedDotted(shape, elt.getStrokeDasharray(), elt.getLinecap());
            
            if(shape.canBeFilled())
                  LShapeSVGGenerator.setFill(shape, elt.getFill(), elt.getSVGRoot().getDefs());
            
            CSSStylesGenerator.setCSSStyles(shape, elt.getStylesCSS(), elt.getSVGRoot().getDefs());
      }

      
      
      /**
       * Sets the given arrow head using the SVG arrow with the ID arrowID
       * @param ah The arrow head to set.
       * @param arrowID The SVG ID of the SVG arrow head.
       * @param elt An element of the SVG document (useful to get the defs of the document).
       * @since 2.0.0
       */
00367       protected void setSVGArrow(ArrowHead ah, String arrowID, SVGElement elt)
      {
            if(ah==null || arrowID==null || elt==null)
                  return ;
            
            LArrowHeadSVGGenerator ahGen1 = new LArrowHeadSVGGenerator(ah);
            
            try{ ahGen1.setArrow((SVGMarkerElement)elt.getDef(new URIReferenceParser(arrowID).getURI()), getShape()); }
            catch(ClassCastException e) { e.printStackTrace(); }
      }
      
      
      
      
      /**
       * @param elt The source <code>g</code> element.
       * @param type The type of the latexdraw element (double borders, shadow, main), if null, the main element is returned.
       * @return The Researched element.
       * @since 2.0.0
       */
00387       protected SVGElement getLaTeXDrawElement(SVGGElement elt, String type)
      {
            if(elt==null)
                  return null;
            
            NodeList nl = elt.getChildNodes();
            int i=0, size = nl.getLength();
            Node ltdElt=null, n;
            String bis = elt.lookupPrefixUsable(LaTeXDrawNamespace.LATEXDRAW_NAMESPACE_URI);
            
            if(type==null)
                  while(i<size && ltdElt==null)
                  {
                        n = nl.item(i);
                        
                        if(((SVGElement)n).getAttribute(bis+LaTeXDrawNamespace.XML_TYPE)==null)
                              ltdElt = n;
                        else
                              i++;
                  }
            else
                  while(i<size && ltdElt==null)
                  {
                        n = nl.item(i);
                        
                        if(type.equals(((SVGElement)n).getAttribute(bis+LaTeXDrawNamespace.XML_TYPE)))
                              ltdElt = n;
                        else
                              i++;
                  }
            
            return (SVGElement)ltdElt;
      }

      
      
      /**
       * Sets the thickness of the given figure with the given SVG stroke-width.
       * @param f The figure to set.
       * @param strokeWidth The SVG stroke-width to convert.
       * @param stroke The stroke.
       * @since 2.0.0
       */
00430       public static void setThickness(Figure f, String strokeWidth, String stroke)
      {
            if(f==null || strokeWidth==null)
                  return;
            
            if(stroke==null || !stroke.equals(SVGAttributes.SVG_VALUE_NONE))
                  try{ f.setThickness((float)new SVGLengthParser(strokeWidth).parseLength().getValue()); }
                  catch(ParseException e){ e.printStackTrace(); }
      }
      
      
      
      /**
       * Creates an SVG element from the current latexdraw shape.
       * @param doc The SVG document.
       * @return The created SVGElement or null.
       * @since 2.0.0
       */
      public abstract SVGElement toSVG(SVGDocument doc);
      
      
      
      
      
      /**
       * @param elt Rotates the SVG element.
       * @exception IllegalArgumentException If elt is null.
       * @since 2.0.0
       */
00459       protected void setSVGRotationAttribute(Element elt)
      {
            if(elt==null)
                  throw new IllegalArgumentException();
            
            double rotationAngle = shape.getRotationAngle();
            LaTeXDrawPoint2D gravityCenter = shape.getGravityCenter();
            
            if((rotationAngle % (2*PI)) != 0)
            {
                  double x = -Math.cos(-rotationAngle) * gravityCenter.x + Math.sin(-rotationAngle) * gravityCenter.y + gravityCenter.x;
                  double y = -Math.sin(-rotationAngle) * gravityCenter.x - Math.cos(-rotationAngle) * gravityCenter.y + gravityCenter.y;
                  String transfo  = elt.getAttribute(SVGAttributes.SVG_TRANSFORM);
                  String rotation = SVGTransform.createRotation(toDegrees(rotationAngle), 0, 0) + " " +//$NON-NLS-1$
                                            SVGTransform.createTranslation(-x, -y);
                  
                  if(transfo!=null && transfo.length()>0)
                        transfo = rotation + " " + transfo;
                  else
                        transfo = rotation;
                  
                  elt.setAttribute(SVGAttributes.SVG_TRANSFORM, transfo);
            }
      }
      
      
      
      
      /**
       * Sets the double borders parameters to the given SVG element if the current figure has double borders.
       * @param elt The element to set.
       * @exception IllegalArgumentException If elt is null.
       * @since 2.0.0
       */
00493       protected void setSVGDoubleBordersAttributes(Element elt)
      {
            if(elt==null)
                  throw new IllegalArgumentException();
            
            if(shape.hasDoubleBoundary())
            {
                  elt.setAttribute(SVGAttributes.SVG_STROKE, CSSColors.getColorName(shape.getDoubleColor(), true));
                  elt.setAttribute(SVGAttributes.SVG_STROKE_WIDTH, String.valueOf(shape.getDoubleSep()));
                  elt.setAttribute(SVGAttributes.SVG_FILL, SVGAttributes.SVG_VALUE_NONE);
                  elt.setAttribute(LaTeXDrawNamespace.LATEXDRAW_NAMESPACE+':'+LaTeXDrawNamespace.XML_TYPE, LaTeXDrawNamespace.XML_TYPE_DBLE_BORDERS);
            }
      }
      
      
      
      /**
       * 
       * @param elt The element to set if the current figure has a shadow.
       * @param shadowFills True if a shadow must fill the figure.
       * @exception IllegalArgumentException If elt is null.
       * @since 2.0.0
       */
00516       protected void setSVGShadowAttributes(Element elt, boolean shadowFills)
      {
            if(elt==null)
                  throw new IllegalArgumentException();
            
            if(shape.hasShadow())
            {
                  LaTeXDrawPoint2D gravityCenter = shape.getGravityCenter();
                  LaTeXDrawPoint2D pt = new LaTeXDrawPoint2D(gravityCenter.x+shape.getShadowSize(), gravityCenter.y);
                  pt = shape.rotatePoint(pt, -shape.getShadowAngle());
                  
                  elt.setAttribute(SVGAttributes.SVG_TRANSFORM, 
                        SVGTransform.createTranslation((float)shape.getShadowSize(), 0) + " " + //$NON-NLS-1$
                        SVGTransform.createTranslation((float)(pt.x-gravityCenter.x-shape.getShadowSize()), (float)(pt.y-gravityCenter.y)));
                  elt.setAttribute(SVGAttributes.SVG_STROKE_WIDTH, String.valueOf(shape.hasDoubleBoundary() ? 
                                                shape.getThickness()*2+shape.getDoubleSep() : shape.getThickness()));
                  elt.setAttribute(SVGAttributes.SVG_FILL, shadowFills || shape.isFilled() ? CSSColors.getColorName(shape.getShadowColor(), true) : SVGAttributes.SVG_VALUE_NONE);
                  elt.setAttribute(SVGAttributes.SVG_STROKE, CSSColors.getColorName(shape.getShadowColor(), true));
                  elt.setAttribute(LaTeXDrawNamespace.LATEXDRAW_NAMESPACE+':'+LaTeXDrawNamespace.XML_TYPE, LaTeXDrawNamespace.XML_TYPE_SHADOW);
            }
      }
      
      
      
      /**
       * Sets the SVG attribute of the current figure.
       * @param doc The original document with which, all the elements will be created.
       * @param root The root element of the document.
       * @param shadowFills True if a shadow must fill the figure.
       * @since 2.0.0
       */
00547       protected void setSVGAttributes(SVGDocument doc, SVGElement root, boolean shadowFills)
      {
            if(root==null || doc.getFirstChild().getDefs()==null)
                  throw new IllegalArgumentException();
            
            SVGDefsElement defs = doc.getFirstChild().getDefs();
            
            if(shape.isBordersMovable())
              root.setAttribute(LaTeXDrawNamespace.LATEXDRAW_NAMESPACE +':'+ LaTeXDrawNamespace.XML_BORDERS_POS, shape.getBordersPosition());
            
            if(shape.isThicknessable())
            {
                  LShapeSVGGenerator.setThickness(root, shape.getThickness(), shape.hasDoubleBoundary(), shape.getDoubleSep());
                  root.setStroke(shape.getLinesColor());
            }
            
            if(shape.canBeFilled())
                  if((shape.isFilled() || (shape.hasShadow() && shadowFills)) && !shape.isHatched() && !shape.hasGradient())
                        root.setAttribute(SVGAttributes.SVG_FILL, CSSColors.getColorName(shape.getInteriorColor(), true));
                  else
                    if(shape.getHatchingStyle().equals(PSTricksConstants.TOKEN_FILL_NONE))
                        root.setAttribute(SVGAttributes.SVG_FILL, SVGAttributes.SVG_VALUE_NONE);
                    else
                        if(shape.getHatchingStyle().equals(PSTricksConstants.TOKEN_FILL_GRADIENT))
                        {
                              Element grad = new SVGLinearGradientElement(doc), stop;
                              String id = SVGElements.SVG_LINEAR_GRADIENT + shape.getNumber();
                              double gradMidPt = shape.getGradientAngle()>PI || (shape.getGradientAngle()<0 && shape.getGradientAngle()>-PI)? 
                                                            1-shape.getGradientMidPoint() : shape.getGradientMidPoint();
                              
                              grad.setAttribute(SVGAttributes.SVG_ID, id);
                              
                              if(((float)(shape.getGradientAngle()%(2*PI))) != (float)(PI/2f))
                              {
                                    Point2D.Float p1 = new Point2D.Float(), p2 = new Point2D.Float();
                                    
                                    getGradientPoints(p1, p2, true);
                                    
                                    grad.setAttribute(SVGAttributes.SVG_X1, String.valueOf(p1.x));
                                    grad.setAttribute(SVGAttributes.SVG_Y1, String.valueOf(p1.y));
                                    grad.setAttribute(SVGAttributes.SVG_X2, String.valueOf(p2.x));
                                    grad.setAttribute(SVGAttributes.SVG_Y2, String.valueOf(p2.y));
                                    grad.setAttribute(SVGAttributes.SVG_GRADIENT_UNITS, SVGAttributes.SVG_UNITS_VALUE_USR);
                              }
                              
                              
                              if(gradMidPt!=0)
                              {
                                    stop = doc.createElement(SVGElements.SVG_STOP);
                                    stop.setAttribute(SVGAttributes.SVG_OFFSET, "0");//$NON-NLS-1$
                                    stop.setAttribute(SVGAttributes.SVG_STOP_COLOR, CSSColors.getColorName(shape.getGradientStartColor(), true));
                                    grad.appendChild(stop);
                              }
                              
                              stop = doc.createElement(SVGElements.SVG_STOP);
                              stop.setAttribute(SVGAttributes.SVG_OFFSET, String.valueOf(gradMidPt));
                              stop.setAttribute(SVGAttributes.SVG_STOP_COLOR, CSSColors.getColorName(shape.getGradientEndColor(), true));
                              grad.appendChild(stop);
                              
                              if(gradMidPt!=1)
                              {
                                    stop = doc.createElement(SVGElements.SVG_STOP);
                                    stop.setAttribute(SVGAttributes.SVG_OFFSET, "1");//$NON-NLS-1$
                                    stop.setAttribute(SVGAttributes.SVG_STOP_COLOR, CSSColors.getColorName(shape.getGradientStartColor(), true));
                                    grad.appendChild(stop);
                              }
                              
                              defs.appendChild(grad);
                              root.setAttribute(SVGAttributes.SVG_FILL, "url(#" + id + ')');//$NON-NLS-1$
                        }
                        else
                        {
                              if(shape.isHatched())
                              {
                                    String id         = SVGElements.SVG_PATTERN + shape.getNumber();
                                    Element hatch     = doc.createElement(SVGElements.SVG_PATTERN);
                                    Element gPath     = doc.createElement(SVGElements.SVG_G);
                                    LaTeXDrawPoint2D max = shape.getTheSENonRotatedBoundPoint();
                                    
                                    root.setAttribute(SVGAttributes.SVG_FILL, "url(#" + id + ')');//$NON-NLS-1$
                                    hatch.setAttribute(LaTeXDrawNamespace.LATEXDRAW_NAMESPACE+':'+LaTeXDrawNamespace.XML_TYPE, shape.getHatchingStyle());
                                    hatch.setAttribute(LaTeXDrawNamespace.LATEXDRAW_NAMESPACE+':'+LaTeXDrawNamespace.XML_ROTATION, 
                                                                  String.valueOf(shape.getHatchingAngle()));
                                    hatch.setAttribute(LaTeXDrawNamespace.LATEXDRAW_NAMESPACE+':'+LaTeXDrawNamespace.XML_SIZE, 
                                                String.valueOf(shape.getHatchingSep()));
                                    hatch.setAttribute(SVGAttributes.SVG_PATTERN_UNITS, SVGAttributes.SVG_UNITS_VALUE_USR);
                                    hatch.setAttribute(SVGAttributes.SVG_ID, id);
                                    hatch.setAttribute(SVGAttributes.SVG_X, "0");
                                    hatch.setAttribute(SVGAttributes.SVG_Y, "0");
                                    hatch.setAttribute(SVGAttributes.SVG_WIDTH,  String.valueOf((int)max.x));
                                    hatch.setAttribute(SVGAttributes.SVG_HEIGHT, String.valueOf((int)max.y));
                                    gPath.setAttribute(SVGAttributes.SVG_STROKE, CSSColors.getColorName(shape.getHatchingColor(), true));
                                    gPath.setAttribute(SVGAttributes.SVG_STROKE_WIDTH, String.valueOf(shape.getHatchingWidth()));
                                    gPath.setAttribute(SVGAttributes.SVG_STROKE_DASHARRAY, SVGAttributes.SVG_VALUE_NONE);
                                    
                                    Element path = doc.createElement(SVGElements.SVG_PATH);
                                    
                                    path.setAttribute(SVGAttributes.SVG_D, getSVGHatchingsPath().toString());
                                    gPath.appendChild(path);
                                    
                                    if(shape.isFilled() || (shape.hasShadow() && shadowFills))
                                    {
                                          Element fill = doc.createElement(SVGElements.SVG_RECT);
                                          fill.setAttribute(SVGAttributes.SVG_FILL,   CSSColors.getColorName(shape.getInteriorColor(), true));
                                          fill.setAttribute(SVGAttributes.SVG_STROKE, SVGAttributes.SVG_VALUE_NONE);
                                          fill.setAttribute(SVGAttributes.SVG_WIDTH,  String.valueOf((int)max.x));
                                          fill.setAttribute(SVGAttributes.SVG_HEIGHT, String.valueOf((int)max.y));
                                          
                                          hatch.appendChild(fill);
                                    }
                                    
                                    defs.appendChild(hatch);
                                    hatch.appendChild(gPath);
                              }
                        }//else
        
            if(shape.isDashableOrDotable())
              LShapeSVGGenerator.setDashedDotted(root, shape.getBlackDashLength(), shape.getWhiteDashLength(), shape.getDotSep(), 
                        shape.getLineStyle(), shape.hasDoubleBoundary(), shape.getThickness(), shape.getDoubleSep());
      }

      
      
      /**
       * @return The path of the hatchings of the shape.
       * @since 2.0.0
       */
00674       public SVGPathSegList getSVGHatchingsPath()
      {
            SVGPathSegList path = new SVGPathSegList();
            
            if(!shape.isHatched())
                  return path;

            String hatchingStyle = shape.getHatchingStyle();
            double hatchingAngle = shape.getHatchingAngle();
            LaTeXDrawRectangle bound = new LaTeXDrawRectangle(shape.getTheNWNonRotatedBoundPoint(),
                                                                                      shape.getTheSENonRotatedBoundPoint(), false);
            
            if(hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_VLINES) || 
                  hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_VLINES_F)) 
                  getSVGHatchingsPath_(path, hatchingAngle, bound);
                  else 
                        if(hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_HLINES) || 
                           hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_HLINES_F)) 
                              getSVGHatchingsPath_(path, hatchingAngle>0?hatchingAngle-Math.PI/2.:hatchingAngle+Math.PI/2., bound);
                  else 
                        if(hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_CROSSHATCH) ||
                           hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_CROSSHATCH_F)) 
                        {
                              getSVGHatchingsPath_(path, hatchingAngle, bound);
                              getSVGHatchingsPath_(path, hatchingAngle>0?hatchingAngle-Math.PI/2.:hatchingAngle+Math.PI/2., bound);
                        }
            
            return path;
      }
      
      
      
      private void getSVGHatchingsPath_(SVGPathSegList path, double hAngle, LaTeXDrawRectangle bound)
      {
            if(path == null || bound==null)
                  return;
            
            double angle2  = hAngle%(Math.PI*2.);
            float halphPI  = (float)(Math.PI/2.);
            double hatchingWidth = shape.getHatchingWidth();
            double hatchingSep   = shape.getHatchingSep();
            LaTeXDrawPoint2D nw = bound.getTheNWPoint();
            LaTeXDrawPoint2D se = bound.getTheSEPoint();
            
            if(angle2>0)
            {
                  if((float)angle2>3f*halphPI)
                        angle2 = angle2-Math.PI*2.;
                  else
                        if((float)angle2>halphPI)
                              angle2 = angle2-Math.PI;
            }
            else
                  if((float)angle2<-3f*halphPI)
                        angle2 = angle2+Math.PI*2.;
                  else
                        if((float)angle2<-halphPI)
                              angle2 = angle2+Math.PI;
            
            double val              = hatchingWidth+hatchingSep;
            float fAngle            = (float)angle2;
            
            if(fAngle==0f)
                  for(double x = nw.x; x<se.x; x+=val)
                  {
                        path.add(new SVGPathSegMoveto(x, nw.y, false));
                        path.add(new SVGPathSegLineto(x, se.y, false));
                  }
            else 
                  if(fAngle==halphPI || fAngle==-halphPI)
                        for(double y = nw.y; y<se.y; y+=val)
                        {
                              path.add(new SVGPathSegMoveto(nw.x, y, false));
                              path.add(new SVGPathSegLineto(se.x, y, false));
                        }
                  else 
                  {
                        double incX = val/Math.cos(angle2);
                        double incY = val/Math.sin(angle2);
                        double maxX;
                        double y1, x2, y2, x1;
                        
                        if(fAngle>0f) 
                        {
                              y1 = nw.y;
                              maxX  = se.x + (se.y-(nw.y<0?nw.y:0)) * Math.tan(angle2);
                        }
                        else 
                        {
                              y1 = se.y;
                              maxX  = se.x - se.y * Math.tan(angle2);
                        }
                        
                        x1 = nw.x;
                        x2 = x1;
                        y2 = y1;
                        
                        if(((float)incX)<=0f)
                              return ;
                        
                        while(x2 < maxX)
                        {
                              x2 += incX;
                              y1 += incY;
                              path.add(new SVGPathSegMoveto(x1, y1, false));
                              path.add(new SVGPathSegLineto(x2, y2, false));
                        }
                  }
      }
      
      
      
      /**
       * Gets the points needed to the gradient definition. The given points must not be null, there value will be set in the method.
       * @param p1 The first point to set.
       * @param p2 The second point to set.
       * @param ignoreMidPt True, gradientMidPt will be ignored.
       * @throws IllegalArgumentException If p1 or p2 is null.
       * @since 2.0.0
       */
00794       protected void getGradientPoints(Point2D.Float p1, Point2D.Float p2, boolean ignoreMidPt)
      {
            if(p1==null || p2==null)
                  throw new IllegalArgumentException();
            
            try
            {
                  LaTeXDrawPoint2D NW = shape.getTheNWPoint();
                  LaTeXDrawPoint2D SE = shape.getTheSEPoint();
                  LaTeXDrawPoint2D pt1 = new LaTeXDrawPoint2D((NW.x+SE.x)/2., NW.y);
                  LaTeXDrawPoint2D pt2 = new LaTeXDrawPoint2D((NW.x+SE.x)/2., SE.y);
                  double angle = shape.getGradientAngle()%(2*PI);
                  double gradMidPt = shape.getGradientMidPoint();
                  
                  if(angle<0)
                        angle = 2*PI + angle;
                  
                  if(angle>=PI)
                  {
                        gradMidPt = 1 - shape.getGradientMidPoint();
                        angle = angle-PI;
                  }
                  
                  if(angle!=0)
                  {
                        if((angle%(PI/2.))==0)
                        {
                              pt1 = new LaTeXDrawPoint2D(NW.x, (NW.y+SE.y)/2.);
                              pt2 = new LaTeXDrawPoint2D(SE.x, (NW.y+SE.y)/2.);
                              
                              if(!ignoreMidPt &&gradMidPt<0.5)
                                    pt1.x = pt2.x - Point2D.distance(pt2.x, pt2.y, SE.x,(NW.y+SE.y)/2.);
                              
                              pt2.x = (NW.x+(SE.x-NW.x)*(ignoreMidPt ? 1 : gradMidPt));
                        }
                        else
                        {
                              LaTeXDrawPoint2D cg = shape.getGravityCenter();
                              Line l2, l;
                              
                              pt1 = Figure.rotatePoint(pt1, cg, -angle);
                              pt2 = Figure.rotatePoint(pt2, cg, -angle);
                              l = new Line(pt1, pt2, false);
                              
                              if(angle>=0 && angle<(PI/2.))
                                     l2 = l.getPerpendicularLine(NW, false);
                              else l2 = l.getPerpendicularLine(new LaTeXDrawPoint2D(NW.x,SE.y), false);
                              
                              pt1 = l.getIntersection(l2);
                              double distance = Point2D.distance(cg.x, cg.y, pt1.x, pt1.y);
                              l.setPointAt(pt1, 0);
                              LaTeXDrawPoint2D[] pts = l.findPoints(pt1, 2*distance*(ignoreMidPt ? 1 : gradMidPt));
                              pt2 = pts[0];
                              
                              if(!ignoreMidPt && gradMidPt<0.5)
                                    pt1 = Figure.rotatePoint(pt1, cg, PI);
                        }
                  }//if(angle!=0)
                  else 
                  {
                        if(!ignoreMidPt && gradMidPt<0.5)
                              pt1.y = pt2.y - Point2D.distance(pt2.x, pt2.y, (NW.x+SE.x)/2.,SE.y);
                        
                        pt2.y = (NW.y+(SE.y-NW.y)*(ignoreMidPt ? 1 : gradMidPt));
                  }
                  
                  p1.setLocation(pt1.x, pt1.y);
                  p2.setLocation(pt2.x, pt2.y);
                  
            }catch(Exception e)
            {
                  p1.setLocation(0, 0);
                  p2.setLocation(0, 0);
            }
      }
      
      
      
      /**
       * Sets the colour of the line of the shape with the given SVG stroke.
       * @param f The shape to set.
       * @param stoke The stroke of the shape.
       * @since 2.0.0
       */
00878       public static void setLineColour(Figure f, String stoke)
      {
            if(f==null || stoke==null)
                  return;
            
            f.setLinesColor(CSSColors.getRGBColour(stoke));
      }
      
      
      
      /**
       * Sets the fill properties to the given figure.
       * @param f The figure to set.
       * @param fill The fill properties
       * @param defs The definition that may be useful to the the fill properties (url), may be null.
       * @since 2.0.0
       */
00895       public static void setFill(Figure f, String fill, SVGDefsElement defs)
      {
            if(fill==null || f==null || fill.equals(SVGAttributes.SVG_VALUE_NONE))
                  return ;
            
            if(fill.startsWith("url(#") && fill.endsWith(")") && defs!=null)//$NON-NLS-1$//$NON-NLS-2$
            {
                  String uri = fill.substring(5, fill.length()-1);
                  SVGElement def = defs.getDef(uri);
                  
                  if(def!=null)
                        if(def instanceof SVGPatternElement)
                        {
                              SVGPatternElement pat = (SVGPatternElement)def;
                              Color c     = pat.getBackgroundColor();
                              String str  = pat.getAttribute(pat.getUsablePrefix(LaTeXDrawNamespace.LATEXDRAW_NAMESPACE_URI)+LaTeXDrawNamespace.XML_TYPE);
                              double angle;
                              double sep;
                              double width;
                              String attr;
                              
                              try { angle = Double.valueOf(pat.getAttribute(pat.getUsablePrefix(LaTeXDrawNamespace.LATEXDRAW_NAMESPACE_URI)+
                                                      LaTeXDrawNamespace.XML_ROTATION));
                              }catch(Exception e) { angle = 0.; }

                              attr = pat.getAttribute(pat.getUsablePrefix(LaTeXDrawNamespace.LATEXDRAW_NAMESPACE_URI)+LaTeXDrawNamespace.XML_SIZE);
                              
                              if(attr==null)
                                    sep = pat.getHatchingSep();
                              else
                                    try { sep = Double.valueOf(attr);
                                    }catch(Exception e) { sep = 0.; }
                              
                              if(PSTricksConstants.isValidFillStyle(str))
                                    f.setHatchingStyle(str);
                              
                              if(!Double.isNaN(angle))
                                    f.setHatchingAngle(angle);
                              
                              f.setIsFilled(c!=null);
                              f.setInteriorColor(c);
                              f.setHatchingColor(pat.getHatchingColor());
                              
                              if(!Double.isNaN(sep))
                                    f.setHatchingSep(sep);
                              
                              width = pat.getHatchingStrokeWidth();
                              
                              if(!Double.isNaN(width))
                                    f.setHatchingWidth((float)width);
                        }
                        else
                              if(def instanceof SVGLinearGradientElement)
                              {
                                    SVGLinearGradientElement grad = (SVGLinearGradientElement)def;
                                    
                                    f.setGradientStartColor(grad.getStartColor());
                                    f.setGradientEndColor(grad.getEndColor());
                                    f.setHatchingStyle(PSTricksConstants.TOKEN_FILL_GRADIENT);
                                    f.setGradientMidPoint(grad.getMiddlePoint());
                                    f.setGradientAngle(grad.getAngle());
                              }
            }
            else
            {
                  Color c = CSSColors.getRGBColour(fill);
                  
                  if(c!=null)
                  {
                        f.setInteriorColor(c);
                        f.setIsFilled(true);
                  }
            }
      }
      
      
      
      /**
       * Sets the figure properties concerning the line properties.
       * @param f The figure to set.
       * @param dashArray The dash array SVG property.
       * @param linecap The line cap SVG property.
       * @since 2.0.0
       */
00979       public static void setDashedDotted(Figure f, String dashArray, String linecap)
      {
            if(f==null || dashArray==null)
                  return ;
            
            if(!dashArray.equals(SVGAttributes.SVG_VALUE_NONE))
                  if(linecap!=null && SVGAttributes.SVG_LINECAP_VALUE_ROUND.equals(linecap))
                        f.setLineStyle(PSTricksConstants.LINE_DOTTED_STYLE);
                  else
                        f.setLineStyle(PSTricksConstants.LINE_DASHED_STYLE);
      }
      
      
      
      public static void setThickness(SVGElement elt, float thickness, boolean hasDoubleBorders, double doubleSep)
      {
            if(elt==null)
                  return ;
            
            elt.setStrokeWidth(hasDoubleBorders ? thickness*2. + doubleSep : thickness);
      }
      
      
      
      public static void setDashedDotted(Element elt, float blackDash, float whiteDash, float dotSep, String lineStyle, 
                                                            boolean hasDoubleBorders, float thickness, double doubleSep)
      {
            if(elt==null)
                  return ;
            
        if(lineStyle.equals(PSTricksConstants.LINE_DASHED_STYLE))
            elt.setAttribute(SVGAttributes.SVG_STROKE_DASHARRAY, blackDash + ", " + whiteDash);//$NON-NLS-1$
        else 
            if(lineStyle.equals(PSTricksConstants.LINE_DOTTED_STYLE))
              {
                  elt.setAttribute(SVGAttributes.SVG_STROKE_LINECAP, SVGAttributes.SVG_LINECAP_VALUE_ROUND);
                  elt.setAttribute(SVGAttributes.SVG_STROKE_DASHARRAY, 1 + ", " + 
                                          (dotSep + (hasDoubleBorders ? thickness*2f + doubleSep : thickness)));//$NON-NLS-1$
              }
      }

      
      
      
      /**
       * If a figure can move its border, we have to compute the difference between the PSTricks shape and the SVG shape.
       * @return The gap computed with the border position, the thickness and the double boundary. Or NaN if the shape cannot move
       * its border.
       * @since 2.0.0
       */
01029       protected double getPositionGap()
      {
            double gap;
            
        if(!shape.isBordersMovable() || shape.getBordersPosition().equals(PSTricksConstants.BORDERS_MIDDLE))
            gap = 0;
        else 
            if(shape.getBordersPosition().equals(PSTricksConstants.BORDERS_INSIDE))
                  gap = -shape.getThickness() - (shape.hasDoubleBoundary() ? (float)shape.getDoubleSep()/2f + shape.getThickness() : 0) ;
            else
                  gap = shape.getThickness() + (shape.hasDoubleBoundary() ? (float)shape.getDoubleSep()/2f + shape.getThickness() : 0);
        
        return gap;
      }
      
      
      
      /**
       * Creates a line with the style of the 'show points' option.
       * @param doc The document owner.
       * @param thickness The thickness of the line to create.
       * @param col The colour of the line.
       * @param p1 The first point of the line.
       * @param p2 The second point of the line.
       * @param blackDash The black dash interval.
       * @param whiteDash The white dash interval.
       * @param hasDble Defines if the shape had double borders.
       * @param dotSep The dot interval.
       * @return The created SVG line or null.
       * @since 2.0.0
       */
01060       protected static SVGLineElement getShowPointsLine(SVGDocument doc, float thickness, Color col, 
                                                      LaTeXDrawPoint2D p1, LaTeXDrawPoint2D p2, float blackDash, float whiteDash, 
                                                      boolean hasDble, float dotSep, double doubleSep)
      {
            if(doc==null)
                  return null;
            
            SVGLineElement line = new SVGLineElement(doc);
            
            if(p1!=null)
            {
                  line.setX1(p1.x);
                  line.setY1(p1.y);
            }
            
            if(p2!=null)
            {
                  line.setX2(p2.x);
                  line.setY2(p2.y);
            }
            
            line.setStrokeWidth(thickness);
            line.setStroke(col);
            LShapeSVGGenerator.setDashedDotted(line, blackDash, whiteDash, dotSep, 
                                          PSTricksConstants.LINE_DASHED_STYLE, hasDble, thickness, doubleSep);
            
            return line;
      }
      
      
      
      /**
       * Creates an SVG circle that represents a dot for the option 'show points'.
       * @param doc The document owner.
       * @param rad The radius of the circle.
       * @param pt The position of the point.
       * @param col The colour of the dot.
       * @return The created dot or null.
       * @since 2.0.0
       */
01100       protected static SVGCircleElement getShowPointsDot(SVGDocument doc, double rad, LaTeXDrawPoint2D pt, Color col)
      {
            if(doc==null)
                  return null;
            
            SVGCircleElement circle = new SVGCircleElement(doc);
            
            circle.setR(rad);
            
            if(pt!=null)
            {
                  circle.setCx(pt.x);
                  circle.setCy(pt.y);
            }
            
            circle.setFill(col);
            
            return circle;
      }
      
      
      /**
       * When a shape has a shadow and is filled, the background of its borders must be filled with the
       * colour of the interior of the shape. This method does not test if it must be done, it sets a
       * SVG element which carries out that.
       * @param elt The element that will be set to define the background of the borders.
       * @param root The root element to which 'elt' will be appended.
       * @since 2.0.0
       */
01129       protected void setSVGBorderBackground(SVGElement elt, SVGElement root)
      {
            if(elt==null || root==null)
                  return ;
            
            elt.setAttribute(LaTeXDrawNamespace.LATEXDRAW_NAMESPACE+':'+LaTeXDrawNamespace.XML_TYPE, LaTeXDrawNamespace.XML_TYPE_BG);
        elt.setFill(shape.getInteriorColor());
        elt.setStroke(shape.getInteriorColor());
        setThickness(elt, shape.getThickness(), shape.hasDoubleBoundary(), shape.getDoubleSep());
        root.appendChild(elt);
      }

      
      
      /**
       * @return the shape.
       * @since 2.0.0
       */
01147       public Figure getShape()
      {
            return shape;
      }
}

Generated by  Doxygen 1.6.0   Back to index