001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/graphics/sld/Mark.java $
002    /*----------------    FILE HEADER  ------------------------------------------
003    
004     This file is part of deegree.
005     Copyright (C) 2001-2008 by:
006     EXSE, Department of Geography, University of Bonn
007     http://www.giub.uni-bonn.de/deegree/
008     lat/lon GmbH
009     http://www.lat-lon.de
010    
011     This library is free software; you can redistribute it and/or
012     modify it under the terms of the GNU Lesser General Public
013     License as published by the Free Software Foundation; either
014     version 2.1 of the License, or (at your option) any later version.
015    
016     This library is distributed in the hope that it will be useful,
017     but WITHOUT ANY WARRANTY; without even the implied warranty of
018     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
019     Lesser General Public License for more details.
020    
021     You should have received a copy of the GNU Lesser General Public
022     License along with this library; if not, write to the Free Software
023     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
024    
025     Contact:
026    
027     Andreas Poth
028     lat/lon GmbH
029     Aennchenstr. 19
030     53115 Bonn
031     Germany
032     E-Mail: poth@lat-lon.de
033    
034     Prof. Dr. Klaus Greve
035     Department of Geography
036     University of Bonn
037     Meckenheimer Allee 166
038     53115 Bonn
039     Germany
040     E-Mail: greve@giub.uni-bonn.de
041    
042     
043     ---------------------------------------------------------------------------*/
044    package org.deegree.graphics.sld;
045    
046    import static org.deegree.framework.xml.XMLTools.escape;
047    
048    import java.awt.BasicStroke;
049    import java.awt.Color;
050    import java.awt.FontMetrics;
051    import java.awt.Graphics2D;
052    import java.awt.Polygon;
053    import java.awt.image.BufferedImage;
054    
055    import org.deegree.framework.util.StringTools;
056    import org.deegree.framework.xml.Marshallable;
057    import org.deegree.model.feature.Feature;
058    import org.deegree.model.filterencoding.FilterEvaluationException;
059    
060    /**
061     * A Mark takes a "shape" and applies coloring to it. The shape can be derived either from a
062     * well-known name (such as "square"), an external URL in various formats (such as, perhaps GIF), or
063     * from a glyph of a font. Multiple external formats may be used with the semantic that they all
064     * contain the equivalent shape in different formats. If an image format is used that has inherent
065     * coloring, the coloring is discarded and only the opacity channel (or equivalent) is used. A Halo,
066     * Fill, and/or Stroke is applied as appropriate for the shape's source format.
067     * <p>
068     * 
069     * @author <a href="mailto:k.lupp@web.de">Katharina Lupp </a>
070     * @author <a href="mailto:mschneider@lat-lon.de">Markus Schneider </a>
071     * @version $Revision: 12167 $ $Date: 2008-06-04 16:06:48 +0200 (Mi, 04 Jun 2008) $
072     */
073    
074    public class Mark implements Marshallable {
075    
076        private BufferedImage image = null;
077    
078        private Fill fill = null;
079    
080        private String wellKnownName = null;
081    
082        private Stroke stroke = null;
083    
084        /**
085         * Constructor for the default <tt>Mark</tt>.
086         */
087        Mark() {
088        }
089    
090        /**
091         * constructor initializing the class with the <Mark>
092         */
093        Mark( String wellKnownName, Stroke stroke, Fill fill ) {
094            setWellKnownName( wellKnownName );
095            setStroke( stroke );
096            setFill( fill );
097        }
098    
099        /**
100         * Gives the well known name of a Mark's shape. Allowed values include at least "square",
101         * "circle", "triangle", "star", "cross", and "x", though map servers may draw a different
102         * symbol instead if they don't have a shape for all of these. Renderings of these marks may be
103         * made solid or hollow depending on Fill and Stroke parameters. The default value is "square".
104         * 
105         * @return the WK-Name of the mark
106         * 
107         */
108        public String getWellKnownName() {
109            return wellKnownName;
110        }
111    
112        /**
113         * Sets the well known name of a Mark's shape. Allowed values include at least "square",
114         * "circle", "triangle", "star", "cross", and "x", though map servers may draw a different
115         * symbol instead if they don't have a shape for all of these. Renderings of these marks may be
116         * made solid or hollow depending on Fill and Stroke parameters. The default value is "square".
117         * 
118         * @param wellKnownName
119         *            the WK-Name of the mark
120         * 
121         */
122        public void setWellKnownName( String wellKnownName ) {
123            this.wellKnownName = wellKnownName;
124        }
125    
126        /**
127         * A Fill allows area geometries to be filled. There are two types of fills: solid-color and
128         * repeated GraphicFill. In general, if a Fill element is omitted in its containing element, no
129         * fill will be rendered. The default is a solid 50%-gray (color "#808080") opaque fill.
130         * 
131         * @return the fill of the mark
132         */
133        public Fill getFill() {
134            return fill;
135        }
136    
137        /**
138         * sets the <Fill>
139         * 
140         * @param fill
141         *            the fill of the mark
142         */
143        public void setFill( Fill fill ) {
144            this.fill = fill;
145        }
146    
147        /**
148         * A Stroke allows a string of line segments (or any linear geometry) to be rendered. There are
149         * three basic types of strokes: solid Color, GraphicFill (stipple), and repeated GraphicStroke.
150         * A repeated graphic is plotted linearly and has its graphic symbol bended around the curves of
151         * the line string. The default is a solid black line (Color "#000000").
152         * 
153         * @return the stroke of the mark
154         */
155        public Stroke getStroke() {
156            return stroke;
157        }
158    
159        /**
160         * sets <Stroke>
161         * 
162         * @param stroke
163         *            the stroke of the mark
164         */
165        public void setStroke( Stroke stroke ) {
166            this.stroke = stroke;
167        }
168    
169        /**
170         * DOCUMENT ME!
171         * 
172         * @param size
173         *            DOCUMENT ME!
174         * 
175         * @return DOCUMENT ME!
176         */
177        public BufferedImage getAsImage( Feature feature, int size )
178                                throws FilterEvaluationException {
179            double fillOpacity = 1.0;
180            double strokeOpacity = 1.0;
181            float[] dash = null;
182            float dashOffset = 0;
183            int cap = BasicStroke.CAP_ROUND;
184            int join = BasicStroke.JOIN_ROUND;
185            float width = 1;
186            Color fillColor = new Color( 128, 128, 128 );
187            Color strokeColor = new Color( 0, 0, 0 );
188    
189            if ( fill != null ) {
190                fillOpacity = fill.getOpacity( feature );
191                fillColor = fill.getFill( feature );
192            }
193    
194            if ( stroke != null ) {
195                strokeOpacity = stroke.getOpacity( feature );
196                strokeColor = stroke.getStroke( feature );
197                dash = stroke.getDashArray( feature );
198                cap = stroke.getLineCap( feature );
199                join = stroke.getLineJoin( feature );
200                width = (float) stroke.getWidth( feature );
201                dashOffset = stroke.getDashOffset( feature );
202            }
203    
204            if ( wellKnownName == null ) {
205                wellKnownName = "square";
206            }
207    
208            if ( wellKnownName.equalsIgnoreCase( "circle" ) ) {
209                image = drawCircle( size, fillOpacity, fillColor, strokeOpacity, strokeColor, dash, dashOffset, width, cap,
210                                    join );
211            } else if ( wellKnownName.equalsIgnoreCase( "triangle" ) ) {
212                image = drawTriangle( size, fillOpacity, fillColor, strokeOpacity, strokeColor, dash, dashOffset, width,
213                                      cap, join );
214            } else if ( wellKnownName.equalsIgnoreCase( "cross" ) ) {
215                image = drawCross1( size, strokeOpacity, strokeColor, dash, dashOffset, width, cap, join );
216            } else if ( wellKnownName.equalsIgnoreCase( "x" ) ) {
217                image = drawCross2( size, strokeOpacity, strokeColor, dash, dashOffset, width, cap, join );
218            } else if ( wellKnownName.startsWith( "CHAR" ) ) {
219                image = drawCharacter( size, fillOpacity, fillColor, strokeOpacity, strokeColor, wellKnownName );
220            } else if ( wellKnownName.equalsIgnoreCase( "star" ) ) {
221                image = drawStar( size, fillOpacity, fillColor, strokeOpacity, strokeColor, dash, dashOffset, width, cap,
222                                  join );
223            } else {
224                image = drawSquare( size, fillOpacity, fillColor, strokeOpacity, strokeColor, dash, dashOffset, width, cap,
225                                    join );
226            }
227    
228            return image;
229        }
230    
231        /**
232         * Sets the mark as an image. Rhis method is not part of the sld specifications but it is added
233         * to speed up applications.
234         * 
235         * @param bufferedImage
236         *            the bufferedImage to be set for the mark
237         */
238        public void setAsImage( BufferedImage bufferedImage ) {
239            this.image = bufferedImage;
240        }
241    
242        /**
243         * 
244         * @param dash
245         * @param dashOffset
246         * @param width
247         * @param cap
248         * @param join
249         * @return
250         * @throws FilterEvaluationException
251         */
252        private BasicStroke createBasicStroke( float[] dash, float dashOffset, float width, int cap, int join ) {
253            BasicStroke bs2 = null;
254            if ( ( dash == null ) || ( dash.length < 2 ) ) {
255                bs2 = new BasicStroke( width, cap, join );
256            } else {
257                bs2 = new BasicStroke( width, cap, join, 10.0f, dash, dashOffset );
258            }
259            return bs2;
260        }
261    
262        /**
263         * Draws a scaled instance of a triangle mark according to the given parameters.
264         * 
265         * @param size
266         *            resulting image's height and width
267         * @param fillOpacity
268         *            opacity value for the filled parts of the image
269         * @param fillColor
270         *            <tt>Color</tt> to be used for the fill
271         * @param strokeOpacity
272         *            opacity value for the stroked parts of the image
273         * @param strokeColor
274         *            <tt>Color</tt> to be used for the strokes
275         * @param dash
276         *            dash array for rendering boundary line
277         * @param width
278         *            of the boundary line
279         * @param cap
280         *            of the boundary line
281         * @param join
282         *            of the boundary line
283         * @param dashOffset
284         * 
285         * @return image displaying a triangle
286         */
287        public BufferedImage drawTriangle( int size, double fillOpacity, Color fillColor, double strokeOpacity,
288                                           Color strokeColor, float[] dash, float dashOffset, float width, int cap, int join ) {
289    
290            int offset = (int) ( width * 2 + 1 ) / 2;
291            BufferedImage image = new BufferedImage( size + offset * 2, size + offset * 2, BufferedImage.TYPE_INT_ARGB );
292    
293            int[] x_ = new int[3];
294            int[] y_ = new int[3];
295            x_[0] = offset;
296            y_[0] = offset;
297            x_[1] = size / 2 + offset;
298            y_[1] = size - 1 + offset;
299            x_[2] = size - 1 + offset;
300            y_[2] = offset;
301    
302            Graphics2D g2D = (Graphics2D) image.getGraphics();
303            BasicStroke bs = createBasicStroke( dash, dashOffset, width, cap, join );
304            g2D.setStroke( bs );
305            setColor( g2D, fillColor, fillOpacity );
306            g2D.fillPolygon( x_, y_, 3 );
307            setColor( g2D, strokeColor, strokeOpacity );
308            g2D.drawPolygon( x_, y_, 3 );
309    
310            return image;
311        }
312    
313        /**
314         * Draws a five-pointed star (pentagram) according to the given parameters.
315         * 
316         * @param size
317         *            resulting image's height and width
318         * @param fillOpacity
319         *            opacity value for the filled parts of the image
320         * @param fillColor
321         *            <tt>Color</tt> to be used for the fill
322         * @param strokeOpacity
323         *            opacity value for the stroked parts of the image
324         * @param strokeColor
325         *            <tt>Color</tt> to be used for the strokes
326         * @param dash
327         *            dash array for rendering boundary line
328         * @param width
329         *            of the boundary line
330         * @param cap
331         *            of the boundary line
332         * @param join
333         *            of the boundary line
334         * @param dashOffset
335         * 
336         * @return an image of a pentagram
337         */
338        public BufferedImage drawStar( int size, double fillOpacity, Color fillColor, double strokeOpacity,
339                                       Color strokeColor, float[] dash, float dashOffset, float width, int cap, int join ) {
340            int offset = (int) ( width * 2 + 1 ) / 2;
341            BufferedImage image = new BufferedImage( size + offset * 2, size + offset * 2, BufferedImage.TYPE_INT_ARGB );
342    
343            Graphics2D g2D = image.createGraphics();
344            BasicStroke bs = createBasicStroke( dash, dashOffset, width, cap, join );
345            g2D.setStroke( bs );
346            int s = size / 2;
347            int x0 = s;
348            int y0 = s;
349            double sin36 = Math.sin( Math.toRadians( 36 ) );
350            double cos36 = Math.cos( Math.toRadians( 36 ) );
351            double sin18 = Math.sin( Math.toRadians( 18 ) );
352            double cos18 = Math.cos( Math.toRadians( 18 ) );
353            int smallRadius = (int) ( s * sin18 / Math.sin( Math.toRadians( 54 ) ) );
354    
355            int p0X = x0;
356            int p0Y = y0 - s;
357            int p1X = x0 + (int) ( smallRadius * sin36 );
358            int p1Y = y0 - (int) ( smallRadius * cos36 );
359            int p2X = x0 + (int) ( s * cos18 );
360            int p2Y = y0 - (int) ( s * sin18 );
361            int p3X = x0 + (int) ( smallRadius * cos18 );
362            int p3Y = y0 + (int) ( smallRadius * sin18 );
363            int p4X = x0 + (int) ( s * sin36 );
364            int p4Y = y0 + (int) ( s * cos36 );
365            int p5Y = y0 + smallRadius;
366            int p6X = x0 - (int) ( s * sin36 );
367            int p7X = x0 - (int) ( smallRadius * cos18 );
368            int p8X = x0 - (int) ( s * cos18 );
369            int p9X = x0 - (int) ( smallRadius * sin36 );
370    
371            int[] x = new int[] { p0X, p1X, p2X, p3X, p4X, p0X, p6X, p7X, p8X, p9X };
372            int[] y = new int[] { p0Y, p1Y, p2Y, p3Y, p4Y, p5Y, p4Y, p3Y, p2Y, p1Y };
373            for ( int i = 0; i < y.length; i++ ) {
374                x[i] = x[i] + offset;
375                y[i] = y[i] + offset;
376            }
377            Polygon shape = new Polygon( x, y, 10 );
378    
379            setColor( g2D, fillColor, fillOpacity );
380            g2D.fill( shape );
381            setColor( g2D, strokeColor, strokeOpacity );
382            g2D.draw( shape );
383    
384            g2D.dispose();
385    
386            return image;
387        }
388    
389        /**
390         * Draws a scaled instance of a circle mark according to the given parameters.
391         * 
392         * @param size
393         *            resulting image's height and widthh
394         * @param fillOpacity
395         *            opacity value for the filled parts of the image
396         * @param fillColor
397         *            <tt>Color</tt> to be used for the fill
398         * @param strokeOpacity
399         *            opacity value for the stroked parts of the image
400         * @param strokeColor
401         *            <tt>Color</tt> to be used for the strokes
402         * @param dash
403         *            dash array for rendering boundary line
404         * @param width
405         *            of the boundary line
406         * @param cap
407         *            of the boundary line
408         * @param join
409         *            of the boundary line
410         * @param dashOffset
411         * 
412         * @return image displaying a circle
413         * @throws FilterEvaluationException
414         */
415        public BufferedImage drawCircle( int size, double fillOpacity, Color fillColor, double strokeOpacity,
416                                         Color strokeColor, float[] dash, float dashOffset, float width, int cap, int join ) {
417            int offset = (int) ( width * 2 + 1 ) / 2;
418            BufferedImage image = new BufferedImage( size + offset * 2, size + offset * 2, BufferedImage.TYPE_INT_ARGB );
419    
420            Graphics2D g2D = (Graphics2D) image.getGraphics();
421            BasicStroke bs = createBasicStroke( dash, dashOffset, width, cap, join );
422            g2D.setStroke( bs );
423            setColor( g2D, fillColor, fillOpacity );
424            g2D.fillOval( offset, offset, size, size );
425    
426            setColor( g2D, strokeColor, strokeOpacity );
427            g2D.drawOval( offset, offset, size, size );
428    
429            return image;
430        }
431    
432        /**
433         * Draws a scaled instance of a square mark according to the given parameters.
434         * 
435         * @param size
436         *            resulting image's height and widthh
437         * @param fillOpacity
438         *            opacity value for the filled parts of the image
439         * @param fillColor
440         *            <tt>Color</tt> to be used for the fill
441         * @param strokeOpacity
442         *            opacity value for the stroked parts of the image
443         * @param strokeColor
444         *            <tt>Color</tt> to be used for the strokes
445         * @param dash
446         *            dash array for rendering boundary line
447         * @param width
448         *            of the boundary line
449         * @param cap
450         *            of the boundary line
451         * @param join
452         *            of the boundary line
453         * @param dashOffset
454         * 
455         * @return image displaying a square
456         */
457        public BufferedImage drawSquare( int size, double fillOpacity, Color fillColor, double strokeOpacity,
458                                         Color strokeColor, float[] dash, float dashOffset, float width, int cap, int join ) {
459            int offset = (int) ( width * 2 + 1 ) / 2;
460            BufferedImage image = new BufferedImage( size + offset * 2, size + offset * 2, BufferedImage.TYPE_INT_ARGB );
461    
462            Graphics2D g2D = (Graphics2D) image.getGraphics();
463            BasicStroke bs = createBasicStroke( dash, dashOffset, width, cap, join );
464            g2D.setStroke( bs );
465            setColor( g2D, fillColor, fillOpacity );
466            g2D.fillRect( offset, offset, size, size );
467    
468            setColor( g2D, strokeColor, strokeOpacity );
469            g2D.drawRect( offset, offset, size - 1, size - 1 );
470    
471            return image;
472        }
473    
474        /**
475         * Draws a scaled instance of a cross mark (a "+") according to the given parameters.
476         * 
477         * @param size
478         *            resulting image's height and widthh
479         * @param strokeOpacity
480         *            opacity value for the stroked parts of the image
481         * @param strokeColor
482         *            <tt>Color</tt> to be used for the strokes
483         * @param dash
484         *            dash array for rendering boundary line
485         * @param width
486         *            of the boundary line
487         * @param cap
488         *            of the boundary line
489         * @param join
490         *            of the boundary line
491         * @param dashOffset
492         * 
493         * @return image displaying a cross (a "+")
494         */
495        public BufferedImage drawCross1( int size, double strokeOpacity, Color strokeColor, float[] dash, float dashOffset,
496                                         float width, int cap, int join ) {
497    
498            int offset = (int) ( width * 2 + 1 ) / 2;
499            BufferedImage image = new BufferedImage( size + offset * 2, size + offset * 2, BufferedImage.TYPE_INT_ARGB );
500    
501            Graphics2D g2D = (Graphics2D) image.getGraphics();
502    
503            BasicStroke bs = createBasicStroke( dash, dashOffset, width, cap, join );
504            g2D.setStroke( bs );
505    
506            setColor( g2D, strokeColor, strokeOpacity );
507            g2D.drawLine( offset, size / 2 + offset, size - 1 + offset, size / 2 + offset );
508            g2D.drawLine( size / 2 + offset, offset, size / 2 + offset, size - 1 + offset );
509    
510            return image;
511        }
512    
513        /**
514         * Draws a scaled instance of a cross mark (an "X") according to the given parameters.
515         * 
516         * @param size
517         *            resulting image's height and widthh
518         * @param strokeOpacity
519         *            opacity value for the stroked parts of the image
520         * @param strokeColor
521         *            <tt>Color</tt> to be used for the strokes
522         * @param dash
523         *            dash array for rendering boundary line
524         * @param width
525         *            of the boundary line
526         * @param cap
527         *            of the boundary line
528         * @param join
529         *            of the boundary line
530         * @param dashOffset
531         * 
532         * @return image displaying a cross (a "X")
533         */
534        public BufferedImage drawCross2( int size, double strokeOpacity, Color strokeColor, float[] dash, float dashOffset,
535                                         float width, int cap, int join ) {
536    
537            int offset = (int) ( width * 2 + 1 ) / 2;
538            BufferedImage image = new BufferedImage( size + offset * 2, size + offset * 2, BufferedImage.TYPE_INT_ARGB );
539    
540            Graphics2D g2D = (Graphics2D) image.getGraphics();
541    
542            BasicStroke bs = createBasicStroke( dash, dashOffset, width, cap, join );
543            g2D.setStroke( bs );
544    
545            setColor( g2D, strokeColor, strokeOpacity );
546            g2D.drawLine( offset, offset, size - 1 + offset, size - 1 + offset );
547            g2D.drawLine( offset, size - 1 + offset, size - 1 + offset, offset );
548    
549            return image;
550        }
551    
552        /**
553         * 
554         * @param size
555         * @param fillOpacity
556         * @param fillColor
557         * @param strokeOpacity
558         * @param strokeColor
559         * @param charDesc
560         *            e.g. CHAR:Times New Roman:45
561         */
562        private BufferedImage drawCharacter( int size, double fillOpacity, Color fillColor, double strokeOpacity,
563                                             Color strokeColor, String charDesc ) {
564    
565            String[] tmp = StringTools.toArray( charDesc, ":", false );
566    
567            BufferedImage image = new BufferedImage( size, size, BufferedImage.TYPE_INT_ARGB );
568    
569            Graphics2D g2 = (Graphics2D) image.getGraphics();
570            setColor( g2, fillColor, fillOpacity );
571            g2.fillRect( 0, 0, size, size );
572    
573            java.awt.Font font = new java.awt.Font( tmp[1], java.awt.Font.PLAIN, size );
574            g2.setFont( font );
575            FontMetrics fm = g2.getFontMetrics();
576    
577            char c = (char) Integer.parseInt( tmp[2] );
578            int w = fm.charWidth( c );
579            int h = fm.getHeight();
580    
581            String s = "" + c;
582            setColor( g2, strokeColor, strokeOpacity );
583            g2.drawString( s, size / 2 - w / 2, size / 2 + h / 2 - fm.getDescent() );
584            g2.dispose();
585            return image;
586        }
587    
588        /**
589         * @param g2D
590         * @param color
591         * @param opacity
592         */
593        private void setColor( Graphics2D g2D, Color color, double opacity ) {
594            if ( opacity < 0.999 ) {
595                final int alpha = (int) Math.round( opacity * 255 );
596                final int red = color.getRed();
597                final int green = color.getGreen();
598                final int blue = color.getBlue();
599                color = new Color( red, green, blue, alpha );
600            }
601    
602            g2D.setColor( color );
603        }
604    
605        /**
606         * exports the content of the Mark as XML formated String
607         * 
608         * @return xml representation of the Mark
609         */
610        public String exportAsXML() {
611    
612            StringBuffer sb = new StringBuffer( 1000 );
613            sb.append( "<Mark>" );
614            if ( wellKnownName != null && !wellKnownName.equals( "" ) ) {
615                sb.append( "<WellKnownName>" ).append( escape( wellKnownName ) );
616                sb.append( "</WellKnownName>" );
617            }
618            if ( fill != null ) {
619                sb.append( ( (Marshallable) fill ).exportAsXML() );
620            }
621            if ( stroke != null ) {
622                sb.append( ( (Marshallable) stroke ).exportAsXML() );
623            }
624    
625            sb.append( "</Mark>" );
626    
627            return sb.toString();
628        }
629    
630        // private void drawUnicode(Graphics2D g2, int x, int y, double rotation,
631        // double size, String m, Mark mark) {
632        // int sz = (int)size;
633        // double fo = mark.getFill().getOpacity();
634        // double so = mark.getStroke().getOpacity();
635        //        
636        // java.awt.Font font = new java.awt.Font("sans serif", java.awt.Font.PLAIN,
637        // sz);
638        // g2.setFont( font );
639        // FontMetrics fm = g2.getFontMetrics();
640        //        
641        // char c = (char)m.charAt(0);
642        // int w = fm.charWidth(c);
643        // int h = fm.getHeight();
644        //        
645        // g2 = setColor( g2, mark.getFill().getFill(), fo );
646        // g2.fillRect( x-w/2, y-h/2, w, h);
647        // g2 = setColor( g2, mark.getStroke().getStroke(), so );
648        //        
649        // String s = "" + c;
650        // g2.drawString( s, x-w/2, y+h/2-fm.getDescent());
651        // }
652        // else {
653        //            
654        // Mark[] marks = sym.getGraphic().getMarks();
655        // double rotation = sym.getGraphic().getRotation();
656        // double size = sym.getGraphic().getSize();
657        // if (marks != null) {
658        //                
659        // for (int k = 0; k > marks.length; k++) {
660        //                    
661        // float w = (float)marks[k].getStroke().getWidth();
662        // g2.setStroke( new BasicStroke( w ) );
663        //                    
664        // if (marks[k].getWellKnownName().equalsIgnoreCase("triangle") ) {
665        // drawTriangle( g2, x, y, rotation, size, marks[k] );
666        // }
667        // else
668        // if (marks[k].getWellKnownName().equalsIgnoreCase("circle") ) {
669        // drawCircle( g2, x, y, rotation, size, marks[k] );
670        // }
671        // else
672        // if (marks[k].getWellKnownName().equalsIgnoreCase("square") ) {
673        // drawSquare( g2, x, y, rotation, size, marks[k] );
674        // }
675        // else
676        // if (marks[k].getWellKnownName().equalsIgnoreCase("cross") ) {
677        // drawCross1( g2, x, y, rotation, size, marks[k] );
678        // }
679        // else
680        // if (marks[k].getWellKnownName().equalsIgnoreCase("x") ) {
681        // drawCross2( g2, x, y, rotation, size, marks[k] );
682        // }
683        // else
684        // if (marks[k].getWellKnownName().length() == 0 ) {
685        // drawSquare( g2, x, y, rotation, size, marks[k] );
686        // }
687        // else {
688        // drawUnicode( g2, x, y, rotation, size,
689        // marks[k].getWellKnownName(), marks[k] );
690        // }
691        // }
692        // }
693        // }
694    }