001    //$HeadURL: svn+ssh://developername@svn.wald.intevation.org/deegree/base/trunk/src/org/deegree/graphics/legend/LegendElement.java $
002    /*----------------------------------------------------------------------------
003     This file is part of deegree, http://deegree.org/
004     Copyright (C) 2001-2009 by:
005       Department of Geography, University of Bonn
006     and
007       lat/lon GmbH
008    
009     This library is free software; you can redistribute it and/or modify it under
010     the terms of the GNU Lesser General Public License as published by the Free
011     Software Foundation; either version 2.1 of the License, or (at your option)
012     any later version.
013     This library is distributed in the hope that it will be useful, but WITHOUT
014     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
015     FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
016     details.
017     You should have received a copy of the GNU Lesser General Public License
018     along with this library; if not, write to the Free Software Foundation, Inc.,
019     59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020    
021     Contact information:
022    
023     lat/lon GmbH
024     Aennchenstr. 19, 53177 Bonn
025     Germany
026     http://lat-lon.de/
027    
028     Department of Geography, University of Bonn
029     Prof. Dr. Klaus Greve
030     Postfach 1147, 53001 Bonn
031     Germany
032     http://www.geographie.uni-bonn.de/deegree/
033    
034     e-mail: info@deegree.org
035    ----------------------------------------------------------------------------*/
036    package org.deegree.graphics.legend;
037    
038    import java.awt.BasicStroke;
039    import java.awt.Color;
040    import java.awt.FontMetrics;
041    import java.awt.Graphics;
042    import java.awt.Graphics2D;
043    import java.awt.image.BufferedImage;
044    import java.util.ArrayList;
045    
046    import org.deegree.framework.log.ILogger;
047    import org.deegree.framework.log.LoggerFactory;
048    import org.deegree.graphics.displayelements.DisplayElementFactory;
049    import org.deegree.graphics.displayelements.IncompatibleGeometryTypeException;
050    import org.deegree.graphics.displayelements.PolygonDisplayElement;
051    import org.deegree.graphics.sld.LineSymbolizer;
052    import org.deegree.graphics.sld.PointSymbolizer;
053    import org.deegree.graphics.sld.PolygonSymbolizer;
054    import org.deegree.graphics.sld.RasterSymbolizer;
055    import org.deegree.graphics.sld.Rule;
056    import org.deegree.graphics.sld.Symbolizer;
057    import org.deegree.graphics.sld.TextSymbolizer;
058    import org.deegree.graphics.transformation.WorldToScreenTransform;
059    import org.deegree.model.filterencoding.FilterEvaluationException;
060    import org.deegree.model.spatialschema.Envelope;
061    import org.deegree.model.spatialschema.GeometryFactory;
062    import org.deegree.model.spatialschema.Position;
063    import org.deegree.model.spatialschema.Surface;
064    import org.deegree.ogcwebservices.wms.GraphicContextFactory;
065    
066    /**
067     * The implements the basic legend element. a legend element may has a label that can be set to eight positions relative
068     * to the legend graphic. A <tt>LegendElement</tt> can be activated or deactivated. It depends on the using
069     * application what effect this behavior will have.
070     * <p>
071     * <tt>LegendElement</tt>s can be collected in a <tt>LegendElementCollection</tt> which also is a
072     * <tt>LegendElement</tt> to group elements or to create more complex elements.
073     * <p>
074     * Each <tt>LegendElement</tt> is able to paint itself as <tt>BufferedImage</tt>
075     *
076     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
077     * @version $Revision: 7363 $ $Date: 2007-05-29 20:47:55 +0200 (Di, 29 Mai 2007) $
078     */
079    public class LegendElement {
080    
081        private static final ILogger LOG = LoggerFactory.getLogger( LegendElement.class );
082    
083        /**
084         * the list of rules
085         */
086        protected ArrayList<Rule> ruleslist = null;
087    
088        /**
089         * The initial empty label.
090         */
091        protected String label = "";
092    
093        /**
094         * The orientation initialized with 0.
095         */
096        protected double orientation = 0;
097    
098        /**
099         * The label position initialized with -1.
100         */
101        protected int labelPosition = -1;
102    
103        /**
104         * A flag signaling if the legend is active initialized with false.
105         */
106        protected boolean active = false;
107    
108        /**
109         * The width of the legend element initialized with 0;
110         */
111        protected int width = 0;
112    
113        /**
114         * The height of the legend element initialized with 0;
115         */
116        protected int height = 0;
117    
118        /**
119         * The width in pixels between the legend and it's label initialized with 10;
120         */
121        protected int bufferBetweenLegendAndLabel = 10;
122    
123        /**
124         * The icon of the legend
125         */
126        protected BufferedImage bi;
127    
128        /**
129         * empty constructor
130         *
131         */
132        protected LegendElement() {
133            this.ruleslist = new ArrayList<Rule>();
134        }
135    
136        /**
137         * @param legendImage
138         *            the icon of the legend.
139         *
140         *
141         */
142        LegendElement( BufferedImage legendImage ) {
143            this();
144            bi = legendImage;
145        }
146    
147        /**
148         * constructor
149         *
150         * @param rules
151         *            the different rules from the SLD
152         * @param label
153         *            the label beneath the legend symbol
154         * @param orientation
155         *            the rotation of the text in the legend
156         * @param labelPosition
157         *            the position of the text according to the symbol
158         * @param active
159         *            whether the legendsymbol is active or not
160         * @param width
161         *            the requested width of the legend symbol
162         * @param height
163         *            the requested height of the legend symbol
164         */
165        LegendElement( Rule[] rules, String label, double orientation, int labelPosition, boolean active, int width,
166                       int height ) {
167            this();
168            setRules( rules );
169            setLabel( label );
170            setLabelOrientation( orientation );
171            setLabelPlacement( labelPosition );
172            setActive( active );
173            setWidth( width );
174            setHeight( height );
175        }
176    
177        /**
178         * gets the Rules as an array
179         *
180         * @return array of sld rules
181         */
182        public Rule[] getRules() {
183            if ( ruleslist != null && ruleslist.size() > 0 ) {
184                return ruleslist.toArray( new Rule[ruleslist.size()] );
185            }
186            return null;
187        }
188    
189        /**
190         * adds a rule to the ArrayList ruleslist
191         *
192         * @param rule
193         *            a sld rule
194         */
195        public void addRule( Rule rule ) {
196            this.ruleslist.add( rule );
197        }
198    
199        /**
200         * sets the rules
201         *
202         * @param rules
203         *            an array of sld rules
204         */
205        public void setRules( Rule[] rules ) {
206            this.ruleslist.clear();
207    
208            if ( rules != null ) {
209                for ( int i = 0; i < rules.length; i++ ) {
210                    this.ruleslist.add( rules[i] );
211                }
212            }
213        }
214    
215        /**
216         * sets the label of the <tt>LegendElement</tt>
217         *
218         * @param label
219         *            label of the <tt>LegendElement</tt>
220         *
221         */
222        public void setLabel( String label ) {
223            this.label = label;
224        }
225    
226        /**
227         * returns the label set to <tt>LegendElement</tt>. If no label is set, the method returns <tt>null</tt>
228         *
229         * @return label of the <tt>LegendElement</tt> or <tt>null</tt>
230         *
231         */
232        public String getLabel() {
233            return this.label;
234        }
235    
236        /**
237         * sets the orientation of the label of the <tt>LegendElement</tt>. A label can have an orientation from -90� to
238         * 90� expressed in radians, where 0� is horizontal
239         *
240         * @param orientation
241         */
242        public void setLabelOrientation( double orientation ) {
243            this.orientation = orientation;
244        }
245    
246        /**
247         * returns the current orientation of the label of the <tt>LegendElement</tt> in radians. If the element hasn't a
248         * label <tt>Double.NEGATIVE_INFINITY</tt> will be returned.
249         *
250         * @return orientation of the label of the <tt>LegendElement</tt> in radians
251         */
252        public double getLabelOrientation() {
253            return this.orientation;
254        }
255    
256        /**
257         * sets the placement of the label relative to the legend symbol. Possible values are:
258         * <ul>
259         * <li>LP_TOPCENTER
260         * <li>LP_TOPLEFT
261         * <li>LP_TOPRIGHT
262         * <li>LP_RIGHT
263         * <li>LP_LEFT
264         * <li>LP_BOTTOMCENTER
265         * <li>LP_BOTTOMRIGHT
266         * <li>LP_BOTTOMLEFT
267         * </ul>
268         *
269         * <pre>
270         *   +---+---+---+
271         *   | 1 | 0 | 2 |
272         *   +---+---+---+
273         *   | 4 |LEG| 3 |
274         *   +---+---+---+
275         *   | 7 | 5 | 6 |
276         *   +---+---+---+
277         * </pre>
278         *
279         * An implementation of the interface may not supoort all positions.
280         *
281         * @param labelPosition
282         */
283        public void setLabelPlacement( int labelPosition ) {
284            this.labelPosition = labelPosition;
285        }
286    
287        /**
288         * returns the placement of the label relative to the legend symbol. If the element hasn't a label
289         * <tt>LegendElement.LP_NOLABEL</tt> will be returned. Otherwise possible values are:
290         * <ul>
291         * <li>LP_TOPCENTER
292         * <li>LP_TOPLEFT
293         * <li>LP_TOPRIGHT
294         * <li>LP_RIGHT
295         * <li>LP_LEFT
296         * <li>LP_BOTTOMCENTER
297         * <li>LP_BOTTOMRIGHT
298         * <li>LP_BOTTOMLEFT
299         * </ul>
300         *
301         * @return coded placement of the label relative to the legend symbol
302         */
303        public int getLabelPlacement() {
304            return this.labelPosition;
305        }
306    
307        /**
308         * activates or deactivates the label
309         *
310         * @param active
311         */
312        public void setActive( boolean active ) {
313            this.active = active;
314        }
315    
316        /**
317         * @return the activtion-status of the label
318         */
319        public boolean isActive() {
320            return this.active;
321        }
322    
323        /**
324         * sets the width of the LegendSymbol (in pixels)
325         *
326         * @param width
327         */
328        public void setWidth( int width ) {
329            this.width = width;
330        }
331    
332        /**
333         * @return the width of the LegendSymbol (in pixels)
334         */
335        public int getWidth() {
336            return this.width;
337        }
338    
339        /**
340         * sets the height of the LegendSymbol (in pixels)
341         *
342         * @param height
343         */
344        public void setHeight( int height ) {
345            this.height = height;
346        }
347    
348        /**
349         * @return the height of the LegendSymbol (in pixels)
350         */
351        public int getHeight() {
352            return this.height;
353        }
354    
355        /**
356         * returns the buffer place between the legend symbol and the legend label in pixels
357         *
358         * @return the buffer as integer in pixels
359         */
360        public int getBufferBetweenLegendAndLabel() {
361            return this.bufferBetweenLegendAndLabel;
362        }
363    
364        /**
365         * @see org.deegree.graphics.legend.LegendElement#getBufferBetweenLegendAndLabel()
366         * @param i
367         *            the buffer as integer in pixels
368         */
369        public void setBufferBetweenLegendAndLabel( int i ) {
370            this.bufferBetweenLegendAndLabel = i;
371        }
372    
373        /**
374         * draws a legendsymbol, if the SLD defines a point
375         *
376         * @param g
377         *            the graphics context
378         * @param c
379         *            the PointSymbolizer representing the drawable point
380         * @param width
381         *            the requested width of the symbol
382         * @param height
383         *            the requested height of the symbol
384         * @throws LegendException
385         *             is thrown, if the parsing of the sld failes.
386         */
387        protected void drawPointLegend( Graphics g, PointSymbolizer c, int width, int height )
388                                throws LegendException {
389            org.deegree.graphics.sld.Graphic deegreegraphic = c.getGraphic();
390            try {
391                BufferedImage buffi = deegreegraphic.getAsImage( null );
392                int w = buffi.getWidth();
393                int h = buffi.getHeight();
394                g.drawImage( buffi, width / 2 - w / 2, height / 2 - h / 2, null );
395            } catch ( FilterEvaluationException feex ) {
396                throw new LegendException( "FilterEvaluationException occured during " + "the creation of the legend:\n"
397                                           + "The legend for the PointSymbol can't be processed.\n" + feex.getMessage() );
398            }
399    
400        }
401    
402        /**
403         * draws a legendsymbol, if the SLD defines a line
404         *
405         * @param g
406         *            the graphics context
407         * @param ls
408         *            the LineSymbolizer representing the drawable line
409         * @param width
410         *            the requested width of the symbol
411         * @param height
412         *            the requested height of the symbol
413         * @throws LegendException
414         *             is thrown, if the parsing of the sld failes.
415         */
416        protected void drawLineStringLegend( Graphics2D g, LineSymbolizer ls, int width, int height )
417                                throws LegendException {
418    
419            org.deegree.graphics.sld.Stroke sldstroke = ls.getStroke();
420            try {
421                // color, opacity
422                setColor( g, sldstroke.getStroke( null ), sldstroke.getOpacity( null ) );
423                g.setStroke( getBasicStroke( sldstroke ) );
424            } catch ( FilterEvaluationException feex ) {
425                throw new LegendException( "FilterEvaluationException occured during the creation "
426                                           + "of the legend:\n The legend for the LineSymbol can't be " + "processed.\n"
427                                           + feex.getMessage() );
428            }
429    
430            // p1 = [0 | height]
431            // p2 = [width / 3 | height / 3]
432            // p3 = [width - width / 3 | height - height / 3]
433            // p4 = [width | 0]
434            int[] xPoints = { 0, width / 3, width - width / 3, width };
435            int[] yPoints = { height, height / 3, height - height / 3, 0 };
436            int nPoints = 4;
437    
438            g.drawPolyline( xPoints, yPoints, nPoints );
439    
440        }
441    
442        /**
443         * draws a legendsymbol, if the SLD defines a polygon
444         *
445         * @param g
446         *            the graphics context
447         * @param ps
448         *            the PolygonSymbolizer representing the drawable polygon
449         * @param width
450         *            the requested width of the symbol
451         * @param height
452         *            the requested height of the symbol
453         * @throws LegendException
454         *             if the parsing of the sld failes.
455         */
456        protected void drawPolygonLegend( Graphics2D g, PolygonSymbolizer ps, int width, int height )
457                                throws LegendException {
458    
459            Position p1 = GeometryFactory.createPosition( 0, 0 );
460            Position p2 = GeometryFactory.createPosition( 0, height - 1 );
461            Position p3 = GeometryFactory.createPosition( width - 1, height - 1 );
462            Position p4 = GeometryFactory.createPosition( width - 1, 0 );
463    
464            Position[] pos = { p1, p2, p3, p4, p1 };
465            Surface surface = null;
466            try {
467                surface = GeometryFactory.createSurface( pos, null, null, null );
468            } catch ( Exception ex ) {
469                throw new LegendException( "Exception occured during the creation of the legend:\n"
470                                           + "The legendsymbol for the Polygon can't be processed.\n"
471                                           + "Error in creating the Surface from the Positions.\n" + ex.getMessage() );
472            }
473    
474            PolygonDisplayElement pde = null;
475            try {
476                // Feature, Geometry, PolygonSymbolizer
477                pde = DisplayElementFactory.buildPolygonDisplayElement( null, surface, ps );
478            } catch ( IncompatibleGeometryTypeException igtex ) {
479                throw new LegendException( "IncompatibleGeometryTypeException occured during "
480                                           + "the creation of the legend:\n The legendsymbol for "
481                                           + "the Polygon can't be processed.\nError in creating "
482                                           + "the PolygonDisplayElement.\n" + igtex.getMessage() );
483            } catch ( Exception e ) {
484                throw new LegendException( "Could not create symbolizer:\n" + e.getMessage() );
485            }
486    
487            Envelope envelope = GeometryFactory.createEnvelope( p1, p3, null );
488    
489            WorldToScreenTransform wtst = new WorldToScreenTransform( envelope, envelope );
490            pde.paint( g, wtst, -1 );
491    
492        }
493    
494        /**
495         * sets the color including an opacity
496         *
497         * @param g2
498         *            the graphics contect as Graphics2D
499         * @param color
500         *            the requested color of the legend symbol
501         * @param opacity
502         *            the requested opacity of the legend symbol
503         * @return the Graphics2D object containing color and opacity
504         */
505        private Graphics2D setColor( Graphics2D g2, Color color, double opacity ) {
506            if ( opacity < 0.999 ) {
507                final int alpha = (int) Math.round( opacity * 255 );
508                final int red = color.getRed();
509                final int green = color.getGreen();
510                final int blue = color.getBlue();
511                color = new Color( red, green, blue, alpha );
512            }
513            g2.setColor( color );
514            return g2;
515        }
516    
517        /**
518         * constructs a java.awt.BasicStroke for painting a LineString legend symbol.
519         *
520         * @param sldstroke
521         *            the deegree sld stroke
522         * @return a java.awt.BasicStroke
523         * @throws LegendException
524         *             if the sld cannot be processed
525         */
526        private BasicStroke getBasicStroke( org.deegree.graphics.sld.Stroke sldstroke )
527                                throws LegendException {
528            BasicStroke bs = null;
529            try {
530                float width = (float) sldstroke.getWidth( null );
531                int cap = sldstroke.getLineCap( null );
532                int join = sldstroke.getLineJoin( null );
533                float miterlimit = 1f;
534                float[] dash = sldstroke.getDashArray( null );
535                float dash_phase = sldstroke.getDashOffset( null );
536    
537                bs = new BasicStroke( width, cap, join, miterlimit, dash, dash_phase );
538                // return new BasicStroke((float)sldstroke.getWidth(null), sldstroke.getLineCap(null),
539                // sldstroke.getLineJoin(null), 1f, sldstroke.getDashArray(null),
540                // sldstroke.getDashOffset(null));
541    
542            } catch ( FilterEvaluationException ex ) {
543                throw new LegendException( "FilterEvaluationException occured during the creation of the legend:\n"
544                                           + "The Stroke of the element can't be processed.\n" + ex.getMessage() );
545            }
546            return bs;
547        }
548    
549        /**
550         * calculates the FontMetrics of the LegendLabel in pixels. It returns an 3-dimensional array containing [0] the
551         * width, [1] the ascent and [2] the descent.
552         *
553         * @param label
554         *            the label of the LegendElement
555         * @return the 3-dimensional INT-Array contains [0] the width of the string, [1] the ascent and [2] the descent.
556         */
557        protected int[] calculateFontMetrics( String label ) {
558            int[] fontmetrics = new int[3];
559    
560            BufferedImage bi = new BufferedImage( 1, 1, BufferedImage.TYPE_INT_ARGB );
561            Graphics g = bi.getGraphics();
562    
563            FontMetrics fm = g.getFontMetrics();
564    
565            if ( label != null && label.length() > 0 ) {
566                fontmetrics[0] = fm.stringWidth( label );
567                fontmetrics[1] = fm.getAscent();
568                fontmetrics[2] = fm.getDescent();
569            } else {
570                fontmetrics[0] = 0;
571                fontmetrics[1] = 0;
572                fontmetrics[2] = 0;
573                // value = 1, because of a bug, which doesn't paint the right border of the
574                // polygon-symbol.
575                setBufferBetweenLegendAndLabel( 1 );
576            }
577            g.dispose();
578    
579            return fontmetrics;
580        }
581    
582        /**
583         * calculates the width and height of the resulting LegendSymbol depending on the LabelPlacement
584         */
585        private BufferedImage calculateImage( int labelposition, int labelwidth, int ascent, int descent, int legendwidth,
586                                              int legendheight, int buffer, String mime ) {
587            // eliminate buffer if label width is zero, so pixel counting works for the reference
588            // implementation
589            if ( labelwidth == 0 ) {
590                buffer = 0;
591            }
592    
593            BufferedImage bi = (BufferedImage) GraphicContextFactory.createGraphicTarget(
594                                                                                          mime,
595                                                                                          ( legendwidth + buffer + labelwidth ),
596                                                                                          legendheight );
597    
598            Graphics g = bi.getGraphics();
599            if ( !( mime.equalsIgnoreCase( "image/png" ) || mime.equalsIgnoreCase( "image/gif" ) ) ) {
600                g.setColor( Color.WHITE );
601                g.fillRect( 0, 0, bi.getWidth(), bi.getHeight() );
602            }
603            g.setColor( Color.BLACK );
604            // TODO labelposition
605    
606            switch ( labelposition ) {
607            // LP_TOPCENTER
608            case 0: {
609                LOG.logInfo( "The text-position LP_TOPCENTER in the legend is not "
610                             + "implemented yet.\n We put the text on the right side (EAST) of " + "the legendsymbol." );
611                g.drawString( getLabel(), width + 10, height / 2 + ( ( ascent - descent ) / 2 ) );
612                break;
613            }
614                // LP_TOPLEFT
615            case 1: {
616                LOG.logInfo( "The text-position LP_TOPLEFT in the legend is not implemented "
617                             + "yet.\n We put the text on the right side (EAST) of the legendsymbol." );
618                g.drawString( getLabel(), width + 10, height / 2 + ( ( ascent - descent ) / 2 ) );
619                break;
620            }
621                // LP_TOPRIGHT
622            case 2: {
623                LOG.logInfo( "The text-position LP_TOPRIGHT in the legend is not implemented "
624                             + "yet.\n We put the text on the right side (EAST) of the legendsymbol." );
625                g.drawString( getLabel(), width + 10, height / 2 + ( ( ascent - descent ) / 2 ) );
626                break;
627            }
628                // LP_RIGHT
629            case 3: {
630                LOG.logInfo( "The text-position LP_RIGHT in the legend is not implemented "
631                             + "yet.\n We put the text on the right side (EAST) of the legendsymbol." );
632                g.drawString( getLabel(), width + 10, height / 2 + ( ( ascent - descent ) / 2 ) );
633                break;
634    
635            }
636                // LP_LEFT
637            case 4: {
638                g.drawString( getLabel(), width + 10, height / 2 + ( ( ascent - descent ) / 2 ) );
639                break;
640            }
641                // LP_BOTTOMCENTER
642            case 5: {
643                LOG.logInfo( "The text-position LP_BOTTOMCENTER in the legend is not "
644                             + "implemented yet.\n We put the text on the right side (EAST) of " + "the legendsymbol." );
645                g.drawString( getLabel(), width + 10, height / 2 + ( ( ascent - descent ) / 2 ) );
646                break;
647            }
648                // LP_BOTTOMRIGHT
649            case 6: {
650                LOG.logInfo( "The text-position LP_BOTTOMRIGHT in the legend is not "
651                             + "implemented yet.\n We put the text on the right side (EAST) of " + "the legendsymbol." );
652                g.drawString( getLabel(), width + 10, height / 2 + ( ( ascent - descent ) / 2 ) );
653                break;
654            }
655                // LP_BOTTOMLEFT
656            case 7: {
657                LOG.logInfo( "The text-position LP_BOTTOMLEFT in the legend is not implemented "
658                             + "yet.\n We put the text on the right side (EAST) of the legendsymbol." );
659                g.drawString( getLabel(), width + 10, height / 2 + ( ( ascent - descent ) / 2 ) );
660                break;
661            }
662            }
663            g.dispose();
664            return bi;
665        }
666    
667        /**
668         * exports the <tt>LegendElement</tt> as </tt>BufferedImage</tt>
669         *
670         * @param mime
671         *
672         * @return the image
673         * @throws LegendException
674         */
675        public BufferedImage exportAsImage( String mime )
676                                throws LegendException {
677    
678            if ( bi == null ) {
679                // calculates the fontmetrics and creates the bufferedimage
680                // if getLabel() is null is checked in calculateFontMetrics!
681                int[] fontmetrics = calculateFontMetrics( getLabel() );
682                bi = calculateImage( getLabelPlacement(), fontmetrics[0], fontmetrics[1], fontmetrics[2], getWidth(),
683                                     getHeight(), getBufferBetweenLegendAndLabel(), mime );
684                Graphics g = bi.getGraphics();
685                ( (Graphics2D) g ).setClip( 0, 0, getWidth(), getHeight() );
686                g.setColor( Color.WHITE );
687                Rule[] myrules = getRules();
688                Symbolizer[] symbolizer = null;
689                // determines the legendsymbol and paints it
690                for ( int a = 0; a < myrules.length; a++ ) {
691                    symbolizer = myrules[a].getSymbolizers();
692    
693                    for ( int b = 0; b < symbolizer.length; b++ ) {
694                        if ( symbolizer[b] instanceof PointSymbolizer ) {
695                            drawPointLegend( g, (PointSymbolizer) symbolizer[b], getWidth(), getHeight() );
696                        }
697                        if ( symbolizer[b] instanceof LineSymbolizer ) {
698                            drawLineStringLegend( (Graphics2D) g, (LineSymbolizer) symbolizer[b], width, height );
699                        }
700                        if ( symbolizer[b] instanceof PolygonSymbolizer ) {
701                            drawPolygonLegend( (Graphics2D) g, (PolygonSymbolizer) symbolizer[b], width, height );
702                        }
703                        if ( symbolizer[b] instanceof RasterSymbolizer ) {
704                            // throw new LegendException("RasterSymbolizer is not implemented yet!");
705                        }
706                        if ( symbolizer[b] instanceof TextSymbolizer ) {
707                            // throw new LegendException("TextSymbolizer is not implemented yet!");
708                        }
709                    }
710    
711                    // g.setColor(Color.black);
712                    // g.drawString(getLabel(), width + 10, height / 2 + ((fontmetrics[1] -
713                    // fontmetrics[2]) / 2));
714    
715                }
716            } else {
717                if ( mime.equalsIgnoreCase( "image/gif" ) || mime.equalsIgnoreCase( "image/png" ) ) {
718                    BufferedImage bii = new BufferedImage( bi.getWidth(), bi.getHeight(), BufferedImage.TYPE_INT_ARGB );
719                    Graphics g = bii.getGraphics();
720                    g.drawImage( bi, 0, 0, null );
721                    g.dispose();
722                    bi = bii;
723                } else if ( mime.equalsIgnoreCase( "image/jpg" ) || mime.equalsIgnoreCase( "image/jpeg" )
724                            || mime.equalsIgnoreCase( "image/tif" ) || mime.equalsIgnoreCase( "image/tiff" )
725                            || mime.equalsIgnoreCase( "image/bmp" ) ) {
726                    BufferedImage bii = new BufferedImage( bi.getWidth(), bi.getHeight(), BufferedImage.TYPE_INT_RGB );
727                    Graphics g = bii.getGraphics();
728                    g.drawImage( bi, 0, 0, null );
729                    g.dispose();
730                    bi = bii;
731                } else if ( mime.equalsIgnoreCase( "image/svg+xml" ) ) {
732                    // not implemented yet
733                }
734            }
735            return bi;
736        }
737    }