Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: jpicedt/format/pstricks/PstricksFormatter.java


1   /*  jPicEdt version 1.3.2, a picture editor for LaTeX.
2       Copyright (C) 1999-2002  Sylvain Reynal
3   
4       This program is free software; you can redistribute it and/or modify
5       it under the terms of the GNU General Public License as published by
6       the Free Software Foundation; either version 2 of the License, or
7       (at your option) any later version.
8   
9       This program is distributed in the hope that it will be useful,
10      but WITHOUT ANY WARRANTY; without even the implied warranty of
11      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12      GNU General Public License for more details.
13  
14      You should have received a copy of the GNU General Public License
15      along with this program; if not, write to the Free Software
16      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  
18      Sylvain Reynal
19      Département de Physique
20      Ecole Nationale Supérieure de l'Electronique et de ses Applications (ENSEA)
21      6, avenue du Ponceau
22      95014 CERGY CEDEX
23      FRANCE
24  
25      Tel : 00 +33 130 736 245
26      Fax : 00 +33 130 736 667
27      e-mail : reynal@ensea.fr
28      jPicEdt web page : http://www.jpicedt.org/
29  */
30  
31  package jpicedt.format.pstricks;
32  
33  import jpicedt.graphic.io.formatter.*;
34  import jpicedt.graphic.*;
35  import jpicedt.graphic.model.*;
36  
37  import java.awt.*;
38  import java.awt.geom.*;
39  import java.util.*;
40  
41  /**
42   * FormatterFactory that produces formatters for the Pstricks macro package.
43   * @author $Author: reynal $
44   * @version $Id: PstricksFormatter.java,v 1.2 2002/08/05 16:44:10 reynal Exp $ 
45   */
46  public class PstricksFormatter implements FormatterFactory, PicObjectConstants, PstricksConstants {
47  
48    protected static String fileWrapperProlog = DEFAULT_FILE_WRAPPER_PROLOG;
49    protected static String fileWrapperEpilog = DEFAULT_FILE_WRAPPER_EPILOG;
50    
51    /** 
52     * @return a Formatter able to format the given Element in the PsTricks format
53     */
54    public Formatter createFormatter(Element e){
55      if (e instanceof PicBezierQuad) return new PicBezierCubicFormatter(new PicBezierCubic((PicBezierQuad)e),this);
56      if (e instanceof PicBezierCubic) return new PicBezierCubicFormatter((PicBezierCubic)e,this);
57      if (e instanceof PicEllipse) return new PicEllipseFormatter((PicEllipse)e,this);
58      if (e instanceof PicPolygon) return new PicPolygonFormatter((PicPolygon)e,this);
59      if (e instanceof PicRectangle) return new PicRectangleFormatter((PicRectangle)e,this);
60      if (e instanceof PicText) return new PicTextFormatter((PicText)e,this);
61      if (e instanceof PicGroup) return new PicGroupFormatter((PicGroup)e,this);
62      return null;
63    }
64  
65    /**
66     * Configure static fields using the given Properties object
67     * @param properties used to read shared parameters
68     *        If null, default values are used.
69     */
70    public static void configure(Properties preferences){
71      fileWrapperProlog = preferences.getProperty(KEY_FILE_WRAPPER_PROLOG,DEFAULT_FILE_WRAPPER_PROLOG);
72      fileWrapperEpilog = preferences.getProperty(KEY_FILE_WRAPPER_EPILOG,DEFAULT_FILE_WRAPPER_EPILOG);
73    }
74    
75    /** 
76     * @return a Formatter able to format the given Drawing in the PsTricks format ;
77     *         this may reliy on calls to <code>createFormatter(Element e)</code> on the elements
78     *         of the drawing, plus creating auxiliary
79     * @param outputConstraint constraint used by the factory to create a specific Formatter on-the-fly
80     */
81    public Formatter createFormatter(Drawing d, Object outputConstraint){
82      return new DrawingFormatter(d,outputConstraint);
83    }
84  
85    ////////////////////////////////////////////////////////////////////
86    //// Toolkit
87    ////////////////////////////////////////////////////////////////////
88  
89    /**
90     * @return PsTricks's "standard" parameter string for the given Element :
91     * - linewidth=xxx, linecolor=xxxx, doubleline=true/false and rel.
92     * - if dash non-nul : linestyle=dashed, dash=xx yy
93     * - if object if filled : fillstyle=solid, fillcolor=xxxx + possibly shadow and hatch parameter
94     * leading and trailing bracket must be added by the caller ! (this allows the caller to add its own set of parameters
95     * <p>
96     * Not supported yet : "border" and "bordercolor"
97     */
98    public ParameterString createParameterString(Element obj){
99  
100     PicAttributeSet attributes = obj.getAttributeSet();
101     
102     StringBuffer paramBuf = new StringBuffer(100);
103     StringBuffer userDefinedColorBuffer=null; // no user-defined colour by default
104 
105     // linewidth
106     paramBuf.append("linewidth=");
107     paramBuf.append(PEToolKit.doubleToString(StyleConstants.getLineWidth(attributes)));
108 
109     // linecolor
110     paramBuf.append(",linecolor=");
111     Color lineColor = StyleConstants.getLineColor(attributes);
112     String lineColorName = PstricksUtilities.getPsTricksColorName(lineColor);
113     if (lineColorName != null)
114       paramBuf.append(lineColorName); // ok, this is a predefined colour
115     else { // define a new colour named "userLineColor" (it doesn't matter if it's not a unique name, provided the caller insert it just BEFORE the command that needs it)
116       float[] colourComponents = lineColor.getRGBColorComponents(null); // creates the array from scratch
117       userDefinedColorBuffer = new StringBuffer(100);
118       userDefinedColorBuffer.append("\\newrgbcolor{userLineColour}{");
119       userDefinedColorBuffer.append(PEToolKit.doubleToString(colourComponents[0]));
120       userDefinedColorBuffer.append(" ");
121       userDefinedColorBuffer.append(PEToolKit.doubleToString(colourComponents[1]));
122       userDefinedColorBuffer.append(" ");
123       userDefinedColorBuffer.append(PEToolKit.doubleToString(colourComponents[2]));
124       userDefinedColorBuffer.append("}");
125       userDefinedColorBuffer.append(CR_LF);
126       paramBuf.append("userLineColour");
127     }
128 
129     // linestyle
130     if (StyleConstants.getLineStyle(attributes)==DASHED){
131       paramBuf.append(",linestyle=dashed,dash=");
132       paramBuf.append(PEToolKit.doubleToString(StyleConstants.getDashOpaque(attributes)));
133       paramBuf.append(" ");
134       paramBuf.append(PEToolKit.doubleToString(StyleConstants.getDashTransparent(attributes)));
135     }
136     else if (StyleConstants.getLineStyle(attributes)==DOTTED){
137       paramBuf.append(",linestyle=dotted,dotsep=");
138       paramBuf.append(PEToolKit.doubleToString(StyleConstants.getDotSep(attributes)));
139     }
140     else if (StyleConstants.getLineStyle(attributes)==NONE){
141       paramBuf.append(",linestyle=none");
142     }
143     // else paramBuf.append(",linestyle=solid"); default
144 
145     // fill style and fill colour
146     String fillStyle = StyleConstants.getFillStyle(attributes);
147     if (fillStyle==NONE){
148     }
149     else { // solid or hatches -> add fill colour (even if it's redundant for hatches that are not "starred"=
150       paramBuf.append(",fillcolor=");
151       Color fillColor = StyleConstants.getFillColor(attributes);
152       String fillColorName = PstricksUtilities.getPsTricksColorName(fillColor);
153       if (fillColorName != null)
154         paramBuf.append(fillColorName); // ok, this is a predefined colour
155       else { // define a new colour named "userFillColor" (it doesn't matter if it's not a unique name, provided the caller insert it just BEFORE the command that needs it)
156         float[] colourComponents = fillColor.getRGBColorComponents(null); // creates the array from scratch
157         if (userDefinedColorBuffer==null) userDefinedColorBuffer = new StringBuffer(100); // there was no user-defined colour for linecolor
158         userDefinedColorBuffer.append("\\newrgbcolor{userFillColour}{");
159         userDefinedColorBuffer.append(PEToolKit.doubleToString(colourComponents[0]));
160         userDefinedColorBuffer.append(" ");
161         userDefinedColorBuffer.append(PEToolKit.doubleToString(colourComponents[1]));
162         userDefinedColorBuffer.append(" ");
163         userDefinedColorBuffer.append(PEToolKit.doubleToString(colourComponents[2]));
164         userDefinedColorBuffer.append("}");
165         userDefinedColorBuffer.append(CR_LF);
166         paramBuf.append("userFillColour");
167       }
168       
169       if (fillStyle==SOLID) paramBuf.append(",fillstyle=solid");
170       else { // hatches
171         if (fillStyle==VLINES) paramBuf.append(",fillstyle=vlines");
172         else if (fillStyle==VLINES_FILLED) paramBuf.append(",fillstyle=vlines*");
173         else if (fillStyle==HLINES) paramBuf.append(",fillstyle=hlines");
174         else if (fillStyle==HLINES_FILLED) paramBuf.append(",fillstyle=vlines*");
175         else if (fillStyle==CROSSHATCH) paramBuf.append(",fillstyle=crosshatch");
176         else if (fillStyle==CROSSHATCH_FILLED) paramBuf.append(",fillstyle=crosshatch*");
177       
178         paramBuf.append(",hatchwidth=");
179         paramBuf.append(PEToolKit.doubleToString(StyleConstants.getHatchWidth(attributes)));
180         paramBuf.append(",hatchsep=");
181         paramBuf.append(PEToolKit.doubleToString(StyleConstants.getHatchSep(attributes)));
182         paramBuf.append(",hatchangle=");
183         paramBuf.append(PEToolKit.doubleToString(StyleConstants.getHatchAngle(attributes)));
184         paramBuf.append(",hatchcolor=");
185         Color hatchColor = StyleConstants.getHatchColor(attributes);
186         String hatchColorName = PstricksUtilities.getPsTricksColorName(hatchColor);
187         if (hatchColorName != null)
188           paramBuf.append(hatchColorName); // ok, this is a predefined colour
189         else { // define a new colour named "userHatchColor" (it doesn't matter if it's not a unique name, provided the caller insert it just BEFORE the command that needs it)
190           float[] colourComponents = hatchColor.getRGBColorComponents(null); // creates the array from scratch
191           if (userDefinedColorBuffer==null) userDefinedColorBuffer = new StringBuffer(100); // there was no user-defined colour for linecolor or fillcolor
192           userDefinedColorBuffer.append("\\newrgbcolor{userHatchColour}{");
193           userDefinedColorBuffer.append(PEToolKit.doubleToString(colourComponents[0]));
194           userDefinedColorBuffer.append(" ");
195           userDefinedColorBuffer.append(PEToolKit.doubleToString(colourComponents[1]));
196           userDefinedColorBuffer.append(" ");
197           userDefinedColorBuffer.append(PEToolKit.doubleToString(colourComponents[2]));
198           userDefinedColorBuffer.append("}");
199           userDefinedColorBuffer.append(CR_LF);
200           paramBuf.append("userHatchColour");
201         }
202       }
203     }
204     // shadow 
205     if (StyleConstants.isShadow(attributes)){
206       paramBuf.append(",shadow=true");
207       paramBuf.append(",shadowsize=");
208       paramBuf.append(PEToolKit.doubleToString(StyleConstants.getShadowSize(attributes)));
209       paramBuf.append(",shadowangle=");
210       paramBuf.append(PEToolKit.doubleToString(StyleConstants.getShadowAngle(attributes)));
211       paramBuf.append(",shadowcolor=");
212       Color shadowColor = StyleConstants.getShadowColor(attributes);
213       String shadowColorName = PstricksUtilities.getPsTricksColorName(shadowColor);
214       if (shadowColorName != null)
215         paramBuf.append(shadowColorName); // ok, this is a predefined colour
216       else { // define a new colour named "userShadowColor" 
217         float[] colourComponents = shadowColor.getRGBColorComponents(null); // creates the array from scratch
218         if (userDefinedColorBuffer==null) userDefinedColorBuffer = new StringBuffer(100); // there was no user-defined colour for linecolor or fillcolor
219         userDefinedColorBuffer.append("\\newrgbcolor{userShadowColour}{");
220         userDefinedColorBuffer.append(PEToolKit.doubleToString(colourComponents[0]));
221         userDefinedColorBuffer.append(" ");
222         userDefinedColorBuffer.append(PEToolKit.doubleToString(colourComponents[1]));
223         userDefinedColorBuffer.append(" ");
224         userDefinedColorBuffer.append(PEToolKit.doubleToString(colourComponents[2]));
225         userDefinedColorBuffer.append("}");
226         userDefinedColorBuffer.append(CR_LF);
227         paramBuf.append("userShadowColour");
228       }
229     }
230     
231     // double line
232     if (StyleConstants.isDoubleLine(attributes)) {
233       paramBuf.append(",doubleline=true");
234       paramBuf.append(",doublesep=");
235       paramBuf.append(PEToolKit.doubleToString(StyleConstants.getDoubleLineSep(attributes)));
236       paramBuf.append(",doublecolor=");
237       Color doubleColor = StyleConstants.getDoubleLineColor(attributes);
238       String doubleColorName = PstricksUtilities.getPsTricksColorName(doubleColor);
239       if (doubleColorName != null)
240         paramBuf.append(doubleColorName); // ok, this is a predefined colour
241       else { // define a new colour named "userDoubleColor" 
242         float[] colourComponents = doubleColor.getRGBColorComponents(null); 
243         if (userDefinedColorBuffer==null) userDefinedColorBuffer = new StringBuffer(100); 
244         userDefinedColorBuffer.append("\\newrgbcolor{userDoubleColour}{");
245         userDefinedColorBuffer.append(PEToolKit.doubleToString(colourComponents[0]));
246         userDefinedColorBuffer.append(" ");
247         userDefinedColorBuffer.append(PEToolKit.doubleToString(colourComponents[1]));
248         userDefinedColorBuffer.append(" ");
249         userDefinedColorBuffer.append(PEToolKit.doubleToString(colourComponents[2]));
250         userDefinedColorBuffer.append("}");
251         userDefinedColorBuffer.append(CR_LF);
252         paramBuf.append("userDoubleColour");
253       }
254     }
255 
256     // misc params
257     if (StyleConstants.getDimen(attributes)==INNER) paramBuf.append(",dimen=inner");
258     else if (StyleConstants.getDimen(attributes)==MIDDLE) paramBuf.append(",dimen=inner");
259     // else default
260     
261     return (new ParameterString(paramBuf, userDefinedColorBuffer));
262   }
263 
264   /**
265    * an inner class that represents a PsTricks parameter string (useful especially to handle User Defined Colours)
266    *
267    * the basic problem is that, if a new colour has to be defined, this has to be done through e.g. a \\newrgbcolor command
268    * BEFORE the Element command appears in the file. Hence it's necessary to return an object encapsulating
269    * several strings, not only the parameter string that appears inside the Element formated string.
270    */    
271   public class ParameterString {
272 
273     /* formated parameter string */
274     StringBuffer paramBuf;
275 
276     /* a formated string for user-defined colour commands (aka \\newrgbcolour... each being separated by CR's)
277      * that may be used for "linecolor" or "fillcolor" for instance.
278      * if non-null, there's a user-defined colour (i.e. a colour that doesn't belong to PsTricks default colour dictionary)
279      * if null, there's no user-defined colour
280      * It's the responsability of the caller to insert this string at the appropriate location */
281     StringBuffer userDefinedColourBuf;
282 
283     public ParameterString(StringBuffer paramBuf, StringBuffer userDefinedColourBuf){
284 
285       this.paramBuf = paramBuf;
286       this.userDefinedColourBuf = userDefinedColourBuf;
287     }
288 
289     /**
290      * @return true if there's at least one user-defined colour that need to be defined
291      */
292     public boolean isDefinedColourString(){ return (userDefinedColourBuf != null);}
293 
294     /**
295      * @return the formated parameter string (w/o leading and trailing brackets)
296      */
297     public StringBuffer getParameterBuffer(){ return paramBuf;}
298 
299     /**
300      * @return a string containing \\newrgbcolor... like commands, separated by CR's,
301      *         or an empty stringBuffer if there's no user-defined colours.
302      */
303     public StringBuffer getUserDefinedColourBuffer(){
304       if (isDefinedColourString()) return userDefinedColourBuf;
305       else return new StringBuffer(); // empty !
306     }
307   } // inner class
308 
309 
310 
311 
312 
313   ////////////////////////////////////////////////////////////////////////////////////
314   //// DRAWING
315   ////////////////////////////////////////////////////////////////////////////////////
316 
317   /**
318    * "begin{pspicture}(x0,y0)(x1,y1)" (PsTricks) where 
319    * (x0,y0)=lower-left corner and 
320    * (x1,y1)=upper-right corner
321    */
322   public class DrawingFormatter implements Formatter {
323 
324     /** the Drawing this formatter acts upon */
325     private Drawing drawing;
326     private Object outputConstraint;
327 
328     /**
329      * init this formatter for the given drawing
330      * @param outputConstraint if MAKE_STANDALONE_FILE, prepend/append prolog and epilog.
331      */
332     public DrawingFormatter(Drawing drawing,Object outputConstraint){
333       this.drawing = drawing;
334       this.outputConstraint = outputConstraint;
335     }
336 
337     /**
338      * @return  a String representing this Drawing in the PsTricks format
339      * !!! PsTricks's default unit = 1cm !!!
340      */
341     public String format(){
342 
343       StringBuffer buf = new StringBuffer(200);
344       buf.append("%Created by jPicEdt 1.x"+CR_LF+"%PsTricks format (pstricks.sty needed)"+CR_LF+"%");
345       buf.append(new Date());
346       buf.append(CR_LF);
347       if (outputConstraint == FormatterFactory.MAKE_STANDALONE_FILE) buf.append(fileWrapperProlog);
348       buf.append("\\psset{xunit=1mm,yunit=1mm,runit=1mm}"+CR_LF); // make 1mm the default unit
349 
350       /* first we compute the coordinates of the "begin{pspicture}(x0,y0)(x1,y1)" command from the drawing's bounding box */
351 
352       //
353       // first we compute the location of the upper-right corner of the picture,
354       // then we convert it in LaTeX coordinates
355       Rectangle2D box = drawing.getBoundingBox(); // recursively calls getBounds2D() on each Element [pending] annoying bug with PicText objects !
356       //jpicedt.Log.debug(this,"format","bbox = "+box);
357       buf.append("\\begin{pspicture}(0,0)(");
358       buf.append(PEToolKit.doubleToString(box.getMaxX()));
359       buf.append(",");
360       buf.append(PEToolKit.doubleToString(box.getMaxY()));
361       buf.append(")");
362       buf.append(CR_LF);
363 
364       /*  then for each Element in the Drawing, we call "toFormatedString" and append the returned String to our buffer */
365       for (Iterator it=drawing.elements(); it.hasNext(); ){
366         Element e = (Element)it.next();
367         buf.append(createFormatter(e).format());
368       }
369       // previously registered not-parsed-commands:
370       String s = drawing.getNotparsedCommands();
371       if (s != null  && !s.equals("")){
372         buf.append("%Begin not parsed");
373         buf.append(CR_LF);
374         buf.append(s);
375         buf.append("%End not parsed");
376         buf.append(CR_LF);
377       }
378       //épilogue
379       buf.append("\\end{pspicture}");
380       buf.append(CR_LF);
381       if (outputConstraint == FormatterFactory.MAKE_STANDALONE_FILE) buf.append(fileWrapperEpilog);
382       return buf.toString();
383     }
384   }
385 
386 }