Source Code Cross Referenced for SLDStyleFactory.java in  » GIS » GeoTools-2.4.1 » org » geotools » renderer » style » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » GIS » GeoTools 2.4.1 » org.geotools.renderer.style 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *    GeoTools - OpenSource mapping toolkit
0003:         *    http://geotools.org
0004:         *    (C) 2003-2006, Geotools Project Managment Committee (PMC)
0005:         *
0006:         *    This library is free software; you can redistribute it and/or
0007:         *    modify it under the terms of the GNU Lesser General Public
0008:         *    License as published by the Free Software Foundation; either
0009:         *    version 2.1 of the License, or (at your option) any later version.
0010:         *
0011:         *    This library is distributed in the hope that it will be useful,
0012:         *    but WITHOUT ANY WARRANTY; without even the implied warranty of
0013:         *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0014:         *    Lesser General Public License for more details.
0015:         */
0016:        package org.geotools.renderer.style;
0017:
0018:        import java.awt.AlphaComposite;
0019:        import java.awt.BasicStroke;
0020:        import java.awt.Canvas;
0021:        import java.awt.Color;
0022:        import java.awt.Composite;
0023:        import java.awt.FontFormatException;
0024:        import java.awt.Graphics2D;
0025:        import java.awt.GraphicsEnvironment;
0026:        import java.awt.MediaTracker;
0027:        import java.awt.Paint;
0028:        import java.awt.Shape;
0029:        import java.awt.Stroke;
0030:        import java.awt.TexturePaint;
0031:        import java.awt.geom.AffineTransform;
0032:        import java.awt.geom.Point2D;
0033:        import java.awt.geom.Rectangle2D;
0034:        import java.awt.image.AffineTransformOp;
0035:        import java.awt.image.BufferedImage;
0036:        import java.io.File;
0037:        import java.io.FileInputStream;
0038:        import java.io.FileNotFoundException;
0039:        import java.io.IOException;
0040:        import java.io.InputStream;
0041:        import java.net.MalformedURLException;
0042:        import java.net.URL;
0043:        import java.util.ArrayList;
0044:        import java.util.Arrays;
0045:        import java.util.HashMap;
0046:        import java.util.HashSet;
0047:        import java.util.Iterator;
0048:        import java.util.List;
0049:        import java.util.Map;
0050:        import java.util.Set;
0051:        import java.util.WeakHashMap;
0052:        import java.util.logging.Level;
0053:        import java.util.logging.Logger;
0054:
0055:        import javax.imageio.ImageIO;
0056:        import javax.media.jai.util.Range;
0057:
0058:        import org.apache.batik.transcoder.SVGAbstractTranscoder;
0059:        import org.apache.batik.transcoder.TranscoderInput;
0060:        import org.apache.batik.transcoder.TranscoderOutput;
0061:        import org.geotools.factory.CommonFactoryFinder;
0062:        import org.geotools.feature.Feature;
0063:        import org.opengis.filter.FilterFactory;
0064:        import org.opengis.filter.expression.Expression;
0065:        import org.opengis.filter.expression.PropertyName;
0066:        import org.geotools.renderer.lite.CustomGlyphRenderer;
0067:        import org.geotools.renderer.lite.GlyphRenderer;
0068:        import org.geotools.renderer.lite.SVGGlyphRenderer;
0069:        import org.geotools.styling.ExternalGraphic;
0070:        import org.geotools.styling.Fill;
0071:        import org.geotools.styling.Font;
0072:        import org.geotools.styling.Graphic;
0073:        import org.geotools.styling.Halo;
0074:        import org.geotools.styling.LabelPlacement;
0075:        import org.geotools.styling.LinePlacement;
0076:        import org.geotools.styling.LineSymbolizer;
0077:        import org.geotools.styling.Mark;
0078:        import org.geotools.styling.PointPlacement;
0079:        import org.geotools.styling.PointSymbolizer;
0080:        import org.geotools.styling.PolygonSymbolizer;
0081:        import org.geotools.styling.StyleAttributeExtractorTruncated;
0082:        import org.geotools.styling.StyleFactoryFinder;
0083:        import org.geotools.styling.Symbol;
0084:        import org.geotools.styling.Symbolizer;
0085:        import org.geotools.styling.TextMark;
0086:        import org.geotools.styling.TextSymbolizer;
0087:        import org.geotools.styling.TextSymbolizer2;
0088:        import org.geotools.util.SoftValueHashMap;
0089:        import org.w3c.dom.Document;
0090:
0091:        import com.vividsolutions.jts.geom.Geometry;
0092:
0093:        /**
0094:         * Factory object that converts SLD style into rendered styles.
0095:         *
0096:         * DJB:  I've made a few changes to this.
0097:         *       The old behavior was for this class to convert <LinePlacement> tags to <PointPlacement> tags.
0098:         *       (ie. there never was a LinePlacement option)
0099:         *       This is *certainly* not the correct place to do this, and it was doing a very poor job of it too,
0100:         *       and the renderer was not expecting it to be doing it!
0101:         *
0102:         *       I added support in TextStyle3D for this and had this class correctly set Line/Point placement selection.
0103:         *       NOTE: PointPlacement is the default if not present.
0104:         *
0105:         * @author aaime
0106:         * @author dblasby
0107:         */
0108:
0109:        /*
0110:         *  orginal message on the subject:
0111:         *
0112:         * I was attempting to write documentation for label placement (plus fix
0113:         all the inconsistencies with the spec), and I noticed some problems
0114:         with the SLDStyleFactory and TextStyle2D.
0115:
0116:         It turns out the SLDStyleFactory is actually trying to do [poor] label
0117:         placement (see around line 570)! This also results in a loss of
0118:         information if you're using a <LinePlacement> element in your SLD.
0119:
0120:
0121:         1. remove the placement code from SLDStyleFactory!
0122:         2. get rid of the "AbsoluteLineDisplacement" stuff and replace it with
0123:         something that represents <PointPlacement>/<LinePlacement> elements in
0124:         the TextSymbolizer.
0125:
0126:         The current implementation seems to try to convert a <LinePlacement> and
0127:         an actual line into a <PointPlacement> (and setting the
0128:         AbsoluteLineDisplacement flag)!! This should be done by the real
0129:         labeling code.
0130:
0131:         This change could affect the j2d renderer as it appears to use the
0132:         "AbsoluteLineDisplacement" flag.
0133:         * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/render/src/main/java/org/geotools/renderer/style/SLDStyleFactory.java $
0134:         */
0135:
0136:        public class SLDStyleFactory {
0137:            /** The logger for the rendering module. */
0138:            private static final Logger LOGGER = org.geotools.util.logging.Logging
0139:                    .getLogger("org.geotools.rendering");
0140:
0141:            /** Holds a lookup bewteen SLD names and java constants. */
0142:            private static final java.util.Map joinLookup = new java.util.HashMap();
0143:
0144:            /** Holds a lookup bewteen SLD names and java constants. */
0145:            private static final java.util.Map capLookup = new java.util.HashMap();
0146:
0147:            /** Holds a lookup bewteen SLD names and java constants. */
0148:            private static final java.util.Map fontStyleLookup = new java.util.HashMap();
0149:
0150:            private static final FilterFactory ff = CommonFactoryFinder
0151:                    .getFilterFactory(null);
0152:
0153:            /** Set containing the font families known of this machine */
0154:            private static Set fontFamilies = null;
0155:
0156:            /** Fonts already loaded */
0157:            private static Map loadedFonts = new HashMap();
0158:
0159:            /** Holds the set of well-known marks. */
0160:            static Set wellKnownMarks = new java.util.HashSet();
0161:
0162:            /** Holds the of graphic formats supported by the current jdk */
0163:            static Set supportedGraphicFormats = null;
0164:
0165:            /** Current way to load images */
0166:            static ImageLoader imageLoader = new ImageLoader();
0167:
0168:            /** This one is used as the observer object in image tracks */
0169:            private static final Canvas obs = new Canvas();
0170:
0171:            /** This one holds the list of glyphRenderers that can convert glyphs into an image */
0172:            private static List glyphRenderers = new ArrayList();
0173:
0174:            static { //static block to populate the lookups
0175:                joinLookup.put("miter", new Integer(BasicStroke.JOIN_MITER));
0176:                joinLookup.put("bevel", new Integer(BasicStroke.JOIN_BEVEL));
0177:                joinLookup.put("round", new Integer(BasicStroke.JOIN_ROUND));
0178:
0179:                capLookup.put("butt", new Integer(BasicStroke.CAP_BUTT));
0180:                capLookup.put("round", new Integer(BasicStroke.CAP_ROUND));
0181:                capLookup.put("square", new Integer(BasicStroke.CAP_SQUARE));
0182:
0183:                fontStyleLookup.put("normal", new Integer(java.awt.Font.PLAIN));
0184:                fontStyleLookup
0185:                        .put("italic", new Integer(java.awt.Font.ITALIC));
0186:                fontStyleLookup.put("oblique",
0187:                        new Integer(java.awt.Font.ITALIC));
0188:                fontStyleLookup.put("bold", new Integer(java.awt.Font.BOLD));
0189:
0190:                /**
0191:                 * A list of wellknownshapes that we know about: square, circle, triangle, star, cross, x.
0192:                 * Note arrow is an implementation specific mark.
0193:                 */
0194:                wellKnownMarks.add("Square");
0195:                wellKnownMarks.add("Triangle");
0196:                wellKnownMarks.add("Cross");
0197:                wellKnownMarks.add("Circle");
0198:                wellKnownMarks.add("Star");
0199:                wellKnownMarks.add("X");
0200:                wellKnownMarks.add("Arrow");
0201:                wellKnownMarks.add("Hatch");
0202:                wellKnownMarks.add("square");
0203:                wellKnownMarks.add("triangle");
0204:                wellKnownMarks.add("cross");
0205:                wellKnownMarks.add("circle");
0206:                wellKnownMarks.add("star");
0207:                wellKnownMarks.add("x");
0208:                wellKnownMarks.add("arrow");
0209:                wellKnownMarks.add("hatch");
0210:
0211:                /**
0212:                 * Initialize the gliph renderers array with the default ones
0213:                 */
0214:                glyphRenderers.add(new CustomGlyphRenderer());
0215:
0216:                try {
0217:                    glyphRenderers.add(new SVGGlyphRenderer());
0218:                } catch (Exception e) {
0219:                    LOGGER.warning("Will not support SVG External Graphics "
0220:                            + e);
0221:                }
0222:            }
0223:
0224:            /** Parsed SVG glyphs */
0225:            Map svgGlyphs = new SoftValueHashMap();
0226:
0227:            /** Symbolizers that depend on attributes */
0228:            Map dynamicSymbolizers = new SoftValueHashMap();
0229:
0230:            /** Symbolizers that do not depend on attributes */
0231:            Map staticSymbolizers = new SoftValueHashMap();
0232:
0233:            private static Set getSupportedGraphicFormats() {
0234:                if (supportedGraphicFormats == null) {
0235:                    supportedGraphicFormats = new java.util.HashSet();
0236:
0237:                    String[] types = ImageIO.getReaderMIMETypes();
0238:
0239:                    for (int i = 0; i < types.length; i++) {
0240:                        supportedGraphicFormats.add(types[i]);
0241:                    }
0242:                }
0243:
0244:                return supportedGraphicFormats;
0245:            }
0246:
0247:            private long hits;
0248:
0249:            private long requests;
0250:
0251:            /**
0252:             * Holds value of property mapScaleDenominator.
0253:             */
0254:            private double mapScaleDenominator = Double.NaN;;
0255:
0256:            public double getHitRatio() {
0257:                return (double) hits / (double) requests;
0258:            }
0259:
0260:            public long getHits() {
0261:                return hits;
0262:            }
0263:
0264:            public long getRequests() {
0265:                return requests;
0266:            }
0267:
0268:            /**
0269:             * <p>
0270:             * Creates a rendered style
0271:             * </p>
0272:             *
0273:             * <p>
0274:             * Makes use of a symbolizer cache based on identity to avoid recomputing over and over the
0275:             * same style object and to reduce memory usage. The same Style2D object will be returned by
0276:             * subsequent calls using the same feature independent symbolizer with the same scaleRange.
0277:             * </p>
0278:             *
0279:             * @param drawMe The feature
0280:             * @param symbolizer The SLD symbolizer
0281:             * @param scaleRange The scale range in which the feature should be painted according to the
0282:             *        symbolizer
0283:             *
0284:             * @return A rendered style equivalent to the symbolizer
0285:             */
0286:            public Style2D createStyle(Object drawMe, Symbolizer symbolizer,
0287:                    Range scaleRange) {
0288:                Style2D style = null;
0289:
0290:                SymbolizerKey key = new SymbolizerKey(symbolizer, scaleRange);
0291:                style = (Style2D) staticSymbolizers.get(key);
0292:
0293:                requests++;
0294:
0295:                if (style != null) {
0296:                    hits++;
0297:                } else {
0298:                    style = createStyleInternal(drawMe, symbolizer, scaleRange);
0299:
0300:                    // if known dynamic symbolizer return the style
0301:                    if (dynamicSymbolizers.containsKey(key)) {
0302:                        return style;
0303:                    } else {
0304:                        // lets see if it's static or dynamic
0305:                        StyleAttributeExtractorTruncated sae = new StyleAttributeExtractorTruncated();
0306:                        sae.visit(symbolizer);
0307:
0308:                        Set nameSet = sae.getAttributeNameSet();
0309:
0310:                        if ((nameSet == null) || (nameSet.size() == 0)) {
0311:                            staticSymbolizers.put(key, style);
0312:                        } else {
0313:                            dynamicSymbolizers.put(key, Boolean.TRUE);
0314:                        }
0315:                    }
0316:                }
0317:                return style;
0318:            }
0319:
0320:            /**
0321:             * Really creates the symbolizer
0322:             *
0323:             * @param drawMe DOCUMENT ME!
0324:             * @param symbolizer DOCUMENT ME!
0325:             * @param scaleRange DOCUMENT ME!
0326:             *
0327:             * @return DOCUMENT ME!
0328:             */
0329:            private Style2D createStyleInternal(Object drawMe,
0330:                    Symbolizer symbolizer, Range scaleRange) {
0331:                Style2D style = null;
0332:
0333:                if (symbolizer instanceof  PolygonSymbolizer) {
0334:                    style = createPolygonStyle(drawMe,
0335:                            (PolygonSymbolizer) symbolizer, scaleRange);
0336:                } else if (symbolizer instanceof  LineSymbolizer) {
0337:                    style = createLineStyle(drawMe,
0338:                            (LineSymbolizer) symbolizer, scaleRange);
0339:                } else if (symbolizer instanceof  PointSymbolizer) {
0340:                    style = createPointStyle(drawMe,
0341:                            (PointSymbolizer) symbolizer, scaleRange);
0342:                } else if (symbolizer instanceof  TextSymbolizer) {
0343:                    style = createTextStyle(drawMe,
0344:                            (TextSymbolizer) symbolizer, scaleRange);
0345:                }
0346:
0347:                return style;
0348:            }
0349:
0350:            /**
0351:             * Creates a rendered style
0352:             *
0353:             * @param f The feature
0354:             * @param symbolizer The SLD symbolizer
0355:             * @param scaleRange The scale range in which the feature should be painted according to the
0356:             *        symbolizer
0357:             *
0358:             * @return A rendered style equivalent to the symbolizer
0359:             *
0360:             * @throws UnsupportedOperationException if an unknown symbolizer is passed to this method
0361:             */
0362:            public Style2D createDynamicStyle(Feature f, Symbolizer symbolizer,
0363:                    Range scaleRange) {
0364:                Style2D style = null;
0365:
0366:                if (symbolizer instanceof  PolygonSymbolizer) {
0367:                    style = createDynamicPolygonStyle(f,
0368:                            (PolygonSymbolizer) symbolizer, scaleRange);
0369:                } else if (symbolizer instanceof  LineSymbolizer) {
0370:                    style = createDynamicLineStyle(f,
0371:                            (LineSymbolizer) symbolizer, scaleRange);
0372:                } else {
0373:                    throw new UnsupportedOperationException(
0374:                            "This kind of symbolizer is not yet supported");
0375:                }
0376:
0377:                return style;
0378:            }
0379:
0380:            Style2D createPolygonStyle(Object feature,
0381:                    PolygonSymbolizer symbolizer, Range scaleRange) {
0382:                PolygonStyle2D style = new PolygonStyle2D();
0383:
0384:                setScaleRange(style, scaleRange);
0385:                style.setStroke(getStroke(symbolizer.getStroke(), feature));
0386:                style.setGraphicStroke(getGraphicStroke(symbolizer.getStroke(),
0387:                        feature));
0388:                style
0389:                        .setContour(getStrokePaint(symbolizer.getStroke(),
0390:                                feature));
0391:                style.setContourComposite(getStrokeComposite(symbolizer
0392:                        .getStroke(), feature));
0393:                style.setFill(getPaint(symbolizer.getFill(), feature));
0394:                style.setFillComposite(getComposite(symbolizer.getFill(),
0395:                        feature));
0396:
0397:                return style;
0398:            }
0399:
0400:            Style2D createDynamicPolygonStyle(Feature feature,
0401:                    PolygonSymbolizer symbolizer, Range scaleRange) {
0402:                PolygonStyle2D style = new DynamicPolygonStyle2D(feature,
0403:                        symbolizer);
0404:
0405:                setScaleRange(style, scaleRange);
0406:
0407:                //setStroke(style, symbolizer.getStroke(), feature);
0408:                //setFill(style, symbolizer.getFill(), feature);
0409:                return style;
0410:            }
0411:
0412:            Style2D createLineStyle(Object feature, LineSymbolizer symbolizer,
0413:                    Range scaleRange) {
0414:                LineStyle2D style = new LineStyle2D();
0415:                setScaleRange(style, scaleRange);
0416:                style.setStroke(getStroke(symbolizer.getStroke(), feature));
0417:                style.setGraphicStroke(getGraphicStroke(symbolizer.getStroke(),
0418:                        feature));
0419:                style
0420:                        .setContour(getStrokePaint(symbolizer.getStroke(),
0421:                                feature));
0422:                style.setContourComposite(getStrokeComposite(symbolizer
0423:                        .getStroke(), feature));
0424:
0425:                return style;
0426:            }
0427:
0428:            Style2D createDynamicLineStyle(Feature feature,
0429:                    LineSymbolizer symbolizer, Range scaleRange) {
0430:                LineStyle2D style = new DynamicLineStyle2D(feature, symbolizer);
0431:                setScaleRange(style, scaleRange);
0432:
0433:                //setStroke(style, symbolizer.getStroke(), feature);
0434:                return style;
0435:            }
0436:
0437:            Style2D createPointStyle(Object feature,
0438:                    PointSymbolizer symbolizer, Range scaleRange) {
0439:                Style2D retval = null;
0440:
0441:                // extract base properties
0442:                Graphic sldGraphic = symbolizer.getGraphic();
0443:                float opacity = evalOpacity(sldGraphic.getOpacity(), feature);
0444:                int size;
0445:
0446:                try {
0447:                    size = (int) evalToDouble(sldGraphic.getSize(), feature, 10);
0448:                } catch (NumberFormatException nfe) {
0449:                    size = 10;
0450:                }
0451:
0452:                float rotation = (float) ((evalToFloat(
0453:                        sldGraphic.getRotation(), feature, 0) * Math.PI) / 180);
0454:
0455:                // Extract the sequence of external graphics and symbols and process them in order
0456:                // to recognize which one will be used for rendering
0457:                Symbol[] symbols = sldGraphic.getSymbols();
0458:                final int length = symbols.length;
0459:                ExternalGraphic eg;
0460:                GlyphRenderer r;
0461:                BufferedImage img = null;
0462:                double dsize;
0463:                AffineTransform scaleTx;
0464:                AffineTransformOp ato;
0465:                BufferedImage scaledImage;
0466:                Mark mark;
0467:                Shape shape;
0468:                MarkStyle2D ms2d;
0469:                for (int i = 0; i < length; i++) {
0470:                    if (LOGGER.isLoggable(Level.FINER)) {
0471:                        LOGGER.finer("trying to render symbol " + i);
0472:                    }
0473:
0474:                    // try loading external graphic and creating a GraphicsStyle2D
0475:                    if (symbols[i] instanceof  ExternalGraphic) {
0476:                        if (LOGGER.isLoggable(Level.FINER)) {
0477:                            LOGGER.finer("rendering External graphic");
0478:                        }
0479:
0480:                        eg = (ExternalGraphic) symbols[i];
0481:                        img = null;
0482:
0483:                        // first see if any glyph renderers can handle this
0484:                        for (Iterator it = glyphRenderers.iterator(); it
0485:                                .hasNext()
0486:                                && (img == null);) {
0487:                            r = (GlyphRenderer) it.next();
0488:
0489:                            if (r.canRender(eg.getFormat())) {
0490:                                img = r.render(sldGraphic, eg, feature, size);
0491:                                break; // dont render twice
0492:                            }
0493:                        }
0494:
0495:                        // if no-one of the glyph renderers can handle the eg, try to load it as an external image
0496:                        if (img == null) {
0497:                            img = getImage(eg, size); //size is only a hint
0498:                        }
0499:
0500:                        if (img == null) {
0501:                            continue;
0502:                        }
0503:
0504:                        //SLD SPEC page 52 on ExternalGraphic
0505:                        // The default size of an image format (such as GIF) is the inherent size of the image. The
0506:                        //default size of a format without an inherent size (such as SVG) is defined to be 16 pixels
0507:                        //in height and the corresponding aspect in width. If a size is specified, the height of the
0508:                        //graphic will be scaled to that size and the corresponding aspect will be used for the width.
0509:
0510:                        //				dsize = (double) size;
0511:                        //				scaleTx = AffineTransform.getScaleInstance(dsize
0512:                        //						/ img.getWidth(), dsize / img.getHeight());
0513:                        //				ato = new AffineTransformOp(scaleTx,
0514:                        //						AffineTransformOp.TYPE_BILINEAR);
0515:                        //				scaledImage = ato.createCompatibleDestImage(img, img
0516:                        //						.getColorModel());
0517:                        //				img = ato.filter(img, scaledImage);
0518:
0519:                        // therefore, we determine the scaling required for "y" (height), then calculate a corresponding
0520:                        // scaling for "x" in which we keep the original's aspect ratio
0521:
0522:                        if (img.getHeight() != size) //need to scale
0523:                        {
0524:                            dsize = (double) size;
0525:
0526:                            double scaleY = dsize / img.getHeight(); // >1 if you're magnifying
0527:                            double scaleX = scaleY; // keep aspect ratio!
0528:
0529:                            scaleTx = AffineTransform.getScaleInstance(scaleX,
0530:                                    scaleY); //DJB: keep aspect ratio
0531:                            ato = new AffineTransformOp(scaleTx,
0532:                                    AffineTransformOp.TYPE_BILINEAR);
0533:                            scaledImage = ato.createCompatibleDestImage(img,
0534:                                    img.getColorModel());
0535:                            img = ato.filter(img, scaledImage);
0536:                        }
0537:
0538:                        if (img != null) {
0539:                            retval = new GraphicStyle2D(img, rotation, opacity);
0540:
0541:                            break;
0542:                        }
0543:                    }
0544:
0545:                    if (symbols[i] instanceof  Mark) {
0546:                        if (LOGGER.isLoggable(Level.FINER)) {
0547:                            LOGGER.finer("rendering mark @ PointRenderer "
0548:                                    + symbols[i].toString());
0549:                        }
0550:
0551:                        mark = (Mark) symbols[i];
0552:                        shape = Java2DMark.getWellKnownMark(mark
0553:                                .getWellKnownName().evaluate(feature)
0554:                                .toString());
0555:
0556:                        ms2d = new MarkStyle2D();
0557:                        ms2d.setShape(shape);
0558:                        ms2d.setFill(getPaint(mark.getFill(), feature));
0559:                        ms2d.setFillComposite(getComposite(mark.getFill(),
0560:                                feature));
0561:                        ms2d.setStroke(getStroke(mark.getStroke(), feature));
0562:                        ms2d.setContour(getStrokePaint(mark.getStroke(),
0563:                                feature));
0564:                        ms2d.setContourComposite(getStrokeComposite(mark
0565:                                .getStroke(), feature));
0566:                        ms2d.setSize(size);
0567:                        ms2d.setRotation(rotation);
0568:                        retval = ms2d;
0569:
0570:                        break;
0571:                    }
0572:
0573:                    if (symbols[i] instanceof  TextMark) {
0574:                        // for the moment don't support TextMarks since they are not part
0575:                        // of the SLD specification
0576:                        continue;
0577:
0578:                        /**
0579:                         * if (LOGGER.isLoggable(Level.FINER)) {     LOGGER.finer("rendering text symbol");
0580:                         * } flag = renderTextSymbol(geom, sldgraphic, feature, (TextMark) symbols[i]); if
0581:                         * (flag) {     return; }
0582:                         */
0583:                    }
0584:                }
0585:
0586:                if (retval != null) {
0587:                    setScaleRange(retval, scaleRange);
0588:                }
0589:
0590:                return retval;
0591:            }
0592:
0593:            Style2D createTextStyle(Object feature, TextSymbolizer symbolizer,
0594:                    Range scaleRange) {
0595:                TextStyle2D ts2d = new TextStyle2D();
0596:                setScaleRange(ts2d, scaleRange);
0597:
0598:                if (LOGGER.isLoggable(Level.FINER)) {
0599:                    LOGGER.finer("creating text style");
0600:                }
0601:
0602:                String geomName = symbolizer.getGeometryPropertyName();
0603:
0604:                if (LOGGER.isLoggable(Level.FINER)) {
0605:                    LOGGER.finer("geomName = " + geomName);
0606:                }
0607:
0608:                // extract label
0609:                Object obj = symbolizer.getLabel().evaluate(feature);
0610:                String label = obj == null ? "" : obj.toString();
0611:
0612:                if (LOGGER.isLoggable(Level.FINER)) {
0613:                    LOGGER.finer("label is " + label);
0614:                }
0615:
0616:                ts2d.setLabel(label);
0617:
0618:                // get the sequence of fonts to be used and set the first one available
0619:                Font[] fonts = symbolizer.getFonts();
0620:                java.awt.Font javaFont = getFont(feature, fonts);
0621:                ts2d.setFont(javaFont);
0622:
0623:                // compute label position, anchor, rotation and displacement
0624:                LabelPlacement placement = symbolizer.getLabelPlacement();
0625:                double anchorX = 0;
0626:                double anchorY = 0;
0627:                double rotation = 0;
0628:                double dispX = 0;
0629:                double dispY = 0;
0630:
0631:                if (placement instanceof  PointPlacement) {
0632:                    if (LOGGER.isLoggable(Level.FINER)) {
0633:                        LOGGER.finer("setting pointPlacement");
0634:                    }
0635:
0636:                    // compute anchor point and displacement
0637:                    PointPlacement p = (PointPlacement) placement;
0638:                    anchorX = ((Number) p.getAnchorPoint().getAnchorPointX()
0639:                            .evaluate(feature)).doubleValue();
0640:                    anchorY = ((Number) p.getAnchorPoint().getAnchorPointY()
0641:                            .evaluate(feature)).doubleValue();
0642:
0643:                    dispX = ((Number) p.getDisplacement().getDisplacementX()
0644:                            .evaluate(feature)).doubleValue();
0645:                    dispY = ((Number) p.getDisplacement().getDisplacementY()
0646:                            .evaluate(feature)).doubleValue();
0647:
0648:                    // rotation
0649:                    if ((symbolizer instanceof  TextSymbolizer2)
0650:                            && (((TextSymbolizer2) symbolizer).getGraphic() != null)) {
0651:                        // don't rotate labels that are being placed on shields.
0652:                        rotation = 0.0;
0653:                    } else {
0654:                        rotation = ((Number) p.getRotation().evaluate(feature))
0655:                                .doubleValue();
0656:                        rotation *= (Math.PI / 180.0);
0657:                    }
0658:
0659:                    ts2d.setPointPlacement(true);
0660:                } else if (placement instanceof  LinePlacement) {
0661:                    // this code used to really really really really suck, so I removed it!
0662:                    if (LOGGER.isLoggable(Level.FINER)) {
0663:                        LOGGER.finer("setting pointPlacement");
0664:                    }
0665:                    ts2d.setPointPlacement(false);
0666:                    LinePlacement p = (LinePlacement) placement;
0667:                    int displace = ((Number) p.getPerpendicularOffset()
0668:                            .evaluate(feature)).intValue();
0669:                    ts2d.setPerpendicularOffset(displace);
0670:                }
0671:
0672:                ts2d.setAnchorX(anchorX);
0673:                ts2d.setAnchorY(anchorY);
0674:                ts2d.setRotation((float) rotation);
0675:                ts2d.setDisplacementX(dispX);
0676:                ts2d.setDisplacementY(dispY);
0677:
0678:                // setup fill and composite
0679:                ts2d.setFill(getPaint(symbolizer.getFill(), feature));
0680:                ts2d.setComposite(getComposite(symbolizer.getFill(), feature));
0681:
0682:                // compute halo parameters
0683:                Halo halo = symbolizer.getHalo();
0684:
0685:                if (halo != null) {
0686:                    ts2d.setHaloFill(getPaint(halo.getFill(), feature));
0687:                    ts2d
0688:                            .setHaloComposite(getComposite(halo.getFill(),
0689:                                    feature));
0690:                    ts2d.setHaloRadius(((Number) halo.getRadius().evaluate(
0691:                            feature)).floatValue());
0692:                }
0693:
0694:                Graphic graphicShield = null;
0695:                if (symbolizer instanceof  TextSymbolizer2) {
0696:                    graphicShield = ((TextSymbolizer2) symbolizer).getGraphic();
0697:                    if (graphicShield != null) {
0698:                        PointSymbolizer p = StyleFactoryFinder
0699:                                .createStyleFactory().createPointSymbolizer();
0700:                        p.setGraphic(graphicShield);
0701:
0702:                        Style2D shieldStyle = createPointStyle(feature, p,
0703:                                scaleRange);
0704:                        ts2d.setGraphic(shieldStyle);
0705:                    }
0706:                }
0707:
0708:                return ts2d;
0709:            }
0710:
0711:            /**
0712:             * Extracts the named geometry from feature. If geomName is null then the feature's default
0713:             * geometry is used. If geomName cannot be found in feature then null is returned.
0714:             *
0715:             * @param feature The feature to find the geometry in
0716:             * @param geomName The name of the geometry to find: null if the default geometry should be
0717:             *        used.
0718:             *
0719:             * @return The geometry extracted from feature or null if this proved impossible.
0720:             */
0721:            private Geometry findGeometry(final Object feature, String geomName) {
0722:                Geometry geom = null;
0723:
0724:                if (geomName == null) {
0725:                    geomName = ""; // ie default geometry
0726:                }
0727:                PropertyName property = ff.property(geomName);
0728:                return (Geometry) property.evaluate(feature, Geometry.class);
0729:            }
0730:
0731:            /**
0732:             * Returns the first font associated to the feature that can be found on the current machine
0733:             *
0734:             * @param feature The feature whose font is to be found
0735:             * @param fonts An array of fonts dependent of the feature, the first that is found on the
0736:             *        current machine is returned
0737:             *
0738:             * @return The first of the specified fonts found on this machine or null if none found
0739:             */
0740:            private java.awt.Font getFont(Object feature, Font[] fonts) {
0741:                // we need to synchronize font loading or multithreaded access may
0742:                // result in us returning the wrong font
0743:                synchronized (loadedFonts) {
0744:                    if (fontFamilies == null) {
0745:                        GraphicsEnvironment ge = GraphicsEnvironment
0746:                                .getLocalGraphicsEnvironment();
0747:                        fontFamilies = new HashSet();
0748:
0749:                        List f = Arrays
0750:                                .asList(ge.getAvailableFontFamilyNames());
0751:                        fontFamilies.addAll(f);
0752:
0753:                        if (LOGGER.isLoggable(Level.FINEST)) {
0754:                            LOGGER.finest("there are " + fontFamilies.size()
0755:                                    + " fonts available");
0756:                        }
0757:                    }
0758:
0759:                    java.awt.Font javaFont = null;
0760:
0761:                    int styleCode = 0;
0762:                    int size = 6;
0763:                    String requestedFont = "";
0764:
0765:                    for (int k = 0; k < fonts.length; k++) {
0766:                        requestedFont = fonts[k].getFontFamily().evaluate(
0767:                                feature).toString();
0768:
0769:                        if (LOGGER.isLoggable(Level.FINEST)) {
0770:                            LOGGER.finest("trying to load " + requestedFont);
0771:                        }
0772:
0773:                        if (loadedFonts.containsKey(requestedFont)) {
0774:                            javaFont = (java.awt.Font) loadedFonts
0775:                                    .get(requestedFont);
0776:
0777:                            String reqStyle = (String) fonts[k].getFontStyle()
0778:                                    .evaluate(feature);
0779:
0780:                            if (fontStyleLookup.containsKey(reqStyle)) {
0781:                                styleCode = ((Integer) fontStyleLookup
0782:                                        .get(reqStyle)).intValue();
0783:                            } else {
0784:                                styleCode = java.awt.Font.PLAIN;
0785:                            }
0786:
0787:                            String reqWeight = (String) fonts[k]
0788:                                    .getFontWeight().evaluate(feature);
0789:
0790:                            if (reqWeight.equalsIgnoreCase("Bold")) {
0791:                                styleCode = styleCode | java.awt.Font.BOLD;
0792:                            }
0793:
0794:                            size = ((Number) fonts[k].getFontSize().evaluate(
0795:                                    feature)).intValue();
0796:
0797:                            return javaFont.deriveFont(styleCode, size);
0798:                        }
0799:
0800:                        if (LOGGER.isLoggable(Level.FINEST)) {
0801:                            LOGGER.finest("not already loaded");
0802:                        }
0803:
0804:                        if (fontFamilies.contains(requestedFont)) {
0805:                            String reqStyle = (String) fonts[k].getFontStyle()
0806:                                    .evaluate(feature);
0807:
0808:                            if (fontStyleLookup.containsKey(reqStyle)) {
0809:                                styleCode = ((Integer) fontStyleLookup
0810:                                        .get(reqStyle)).intValue();
0811:                            } else {
0812:                                styleCode = java.awt.Font.PLAIN;
0813:                            }
0814:
0815:                            String reqWeight = (String) fonts[k]
0816:                                    .getFontWeight().evaluate(feature);
0817:
0818:                            if (reqWeight.equalsIgnoreCase("Bold")) {
0819:                                styleCode = styleCode | java.awt.Font.BOLD;
0820:                            }
0821:
0822:                            size = ((Number) fonts[k].getFontSize().evaluate(
0823:                                    feature)).intValue();
0824:
0825:                            if (LOGGER.isLoggable(Level.FINEST)) {
0826:                                LOGGER.finest("requesting " + requestedFont
0827:                                        + " " + styleCode + " " + size);
0828:                            }
0829:
0830:                            javaFont = new java.awt.Font(requestedFont,
0831:                                    styleCode, size);
0832:                            loadedFonts.put(requestedFont, javaFont);
0833:
0834:                            return javaFont;
0835:                        }
0836:
0837:                        if (LOGGER.isLoggable(Level.FINEST)) {
0838:                            LOGGER.finest("not a system font");
0839:                        }
0840:
0841:                        // may be its a file or url
0842:                        InputStream is = null;
0843:
0844:                        if (requestedFont.startsWith("http")
0845:                                || requestedFont.startsWith("file:")) {
0846:                            try {
0847:                                URL url = new URL(requestedFont);
0848:                                is = url.openStream();
0849:                            } catch (MalformedURLException mue) {
0850:                                // this may be ok - but we should mention it
0851:                                if (LOGGER.isLoggable(Level.INFO)) {
0852:                                    LOGGER.info("Bad url in SLDStyleFactory "
0853:                                            + requestedFont + "\n" + mue);
0854:                                }
0855:                            } catch (IOException ioe) {
0856:                                // we'll ignore this for the moment
0857:                                if (LOGGER.isLoggable(Level.INFO)) {
0858:                                    LOGGER.info("IO error in SLDStyleFactory "
0859:                                            + requestedFont + "\n" + ioe);
0860:                                }
0861:                            }
0862:                        } else {
0863:                            if (LOGGER.isLoggable(Level.FINEST)) {
0864:                                LOGGER.finest("not a URL");
0865:                            }
0866:
0867:                            File file = new File(requestedFont);
0868:
0869:                            //if(file.canRead()){
0870:                            try {
0871:                                is = new FileInputStream(file);
0872:                            } catch (FileNotFoundException fne) {
0873:                                // this may be ok - but we should mention it
0874:                                if (LOGGER.isLoggable(Level.INFO)) {
0875:                                    LOGGER
0876:                                            .info("Bad file name in SLDStyleFactory"
0877:                                                    + requestedFont
0878:                                                    + "\n"
0879:                                                    + fne);
0880:                                }
0881:                            }
0882:                        }
0883:
0884:                        if (LOGGER.isLoggable(Level.FINEST)) {
0885:                            LOGGER.finest("about to load");
0886:                        }
0887:
0888:                        if (is == null) {
0889:                            if (LOGGER.isLoggable(Level.INFO)) {
0890:                                LOGGER.info("null input stream");
0891:                            }
0892:
0893:                            continue;
0894:                        }
0895:
0896:                        try {
0897:                            javaFont = java.awt.Font.createFont(
0898:                                    java.awt.Font.TRUETYPE_FONT, is);
0899:                        } catch (FontFormatException ffe) {
0900:                            if (LOGGER.isLoggable(Level.INFO)) {
0901:                                LOGGER
0902:                                        .info("Font format error in SLDStyleFactory "
0903:                                                + requestedFont + "\n" + ffe);
0904:                            }
0905:
0906:                            continue;
0907:                        } catch (IOException ioe) {
0908:                            // we'll ignore this for the moment
0909:                            if (LOGGER.isLoggable(Level.INFO)) {
0910:                                LOGGER.info("IO error in SLDStyleFactory "
0911:                                        + requestedFont + "\n" + ioe);
0912:                            }
0913:
0914:                            continue;
0915:                        }
0916:
0917:                        loadedFonts.put(requestedFont, javaFont);
0918:
0919:                        return javaFont;
0920:                    }
0921:
0922:                    // if everything else fails fall back on a default font distributed
0923:                    // along with the jdk
0924:                    return new java.awt.Font("Serif", java.awt.Font.PLAIN, 12);
0925:                }
0926:            }
0927:
0928:            void setScaleRange(Style style, Range scaleRange) {
0929:                double min = ((Number) scaleRange.getMinValue()).doubleValue();
0930:                double max = ((Number) scaleRange.getMaxValue()).doubleValue();
0931:                style.setMinMaxScale(min, max);
0932:            }
0933:
0934:            // Builds an image version of the graphics with the proper size, no further scaling will
0935:            // be needed during rendering
0936:            private BufferedImage getGraphicStroke(
0937:                    org.geotools.styling.Stroke stroke, Object feature) {
0938:                if ((stroke == null) || (stroke.getGraphicStroke() == null)) {
0939:                    return null;
0940:                }
0941:
0942:                Graphic graphicStroke = stroke.getGraphicStroke();
0943:
0944:                // lets see if an external image is to be used
0945:                BufferedImage image = getExternalGraphic(graphicStroke);
0946:
0947:                double size = ((Number) graphicStroke.getSize().evaluate(
0948:                        feature)).doubleValue();
0949:
0950:                if (image != null) {
0951:                    int trueImageWidth = image.getWidth();
0952:                    int trueImageHeight = image.getHeight();
0953:                    double scalex = size / trueImageWidth;
0954:                    double scaley = size / trueImageWidth;
0955:
0956:                    AffineTransform at = AffineTransform.getScaleInstance(
0957:                            scalex, scaley);
0958:                    AffineTransformOp ato = new AffineTransformOp(at,
0959:                            AffineTransformOp.TYPE_BILINEAR);
0960:                    BufferedImage scaledImage = ato.createCompatibleDestImage(
0961:                            image, image.getColorModel());
0962:                    ato.filter(image, scaledImage);
0963:
0964:                    image = scaledImage;
0965:
0966:                    if (LOGGER.isLoggable(Level.FINER)) {
0967:                        LOGGER.finer("got an image in graphic fill");
0968:                    }
0969:                } else {
0970:                    if (LOGGER.isLoggable(Level.FINER)) {
0971:                        LOGGER.finer("going for the mark from graphic fill");
0972:                    }
0973:
0974:                    Mark mark = getMark(graphicStroke, feature);
0975:                    image = new BufferedImage((int) size, (int) size,
0976:                            BufferedImage.TYPE_INT_ARGB);
0977:
0978:                    Graphics2D ig2d = image.createGraphics();
0979:                    double rotation = 0.0;
0980:                    rotation = ((Number) graphicStroke.getRotation().evaluate(
0981:                            feature)).doubleValue();
0982:                    rotation *= (Math.PI / 180.0);
0983:                    fillDrawMark(ig2d, size / 2, size / 2, mark, (int) size,
0984:                            rotation, feature);
0985:
0986:                    MediaTracker track = new MediaTracker(obs);
0987:                    track.addImage(image, 1);
0988:
0989:                    try {
0990:                        track.waitForID(1);
0991:                    } catch (InterruptedException e) {
0992:                        LOGGER.warning(e.toString());
0993:                    }
0994:                }
0995:
0996:                return image;
0997:            }
0998:
0999:            private Stroke getStroke(org.geotools.styling.Stroke stroke,
1000:                    Object feature) {
1001:                if (stroke == null) {
1002:                    return null;
1003:                }
1004:
1005:                // resolve join type into a join code
1006:                String joinType;
1007:                int joinCode;
1008:
1009:                joinType = evaluateExpression(stroke.getLineJoin(), feature,
1010:                        "miter");
1011:
1012:                if (joinLookup.containsKey(joinType)) {
1013:                    joinCode = ((Integer) joinLookup.get(joinType)).intValue();
1014:                } else {
1015:                    joinCode = java.awt.BasicStroke.JOIN_MITER;
1016:                }
1017:
1018:                // resolve cap type into a cap code
1019:                String capType;
1020:                int capCode;
1021:
1022:                capType = evaluateExpression(stroke.getLineCap(), feature,
1023:                        "square");
1024:
1025:                if (capLookup.containsKey(capType)) {
1026:                    capCode = ((Integer) capLookup.get(capType)).intValue();
1027:                } else {
1028:                    capCode = java.awt.BasicStroke.CAP_SQUARE;
1029:                }
1030:
1031:                // get the other properties needed for the stroke
1032:                float[] dashes = stroke.getDashArray();
1033:                float width = evalToFloat(stroke.getWidth(), feature, 1);
1034:                float dashOffset = evalToFloat(stroke.getDashOffset(), feature,
1035:                        0);
1036:
1037:                // Simple optimization: let java2d use the fast drawing path if the line width
1038:                // is small enough...
1039:                if (width < 1.5) {
1040:                    width = 0;
1041:                }
1042:
1043:                // now set up the stroke
1044:                BasicStroke stroke2d;
1045:
1046:                if ((dashes != null) && (dashes.length > 0)) {
1047:                    stroke2d = new BasicStroke(width, capCode, joinCode, 1,
1048:                            dashes, dashOffset);
1049:                } else {
1050:                    stroke2d = new BasicStroke(width, capCode, joinCode, 1);
1051:                }
1052:
1053:                return stroke2d;
1054:            }
1055:
1056:            private Paint getStrokePaint(org.geotools.styling.Stroke stroke,
1057:                    Object feature) {
1058:                if (stroke == null) {
1059:                    return null;
1060:                }
1061:
1062:                // the foreground color
1063:                Paint contourPaint = evalToColor(stroke.getColor(), feature,
1064:                        Color.BLACK);
1065:
1066:                // if a graphic fill is to be used, prepare the paint accordingly....
1067:                org.geotools.styling.Graphic gr = stroke.getGraphicFill();
1068:
1069:                if (gr != null) {
1070:                    contourPaint = getTexturePaint(gr, feature);
1071:                }
1072:
1073:                return contourPaint;
1074:            }
1075:
1076:            private Composite getStrokeComposite(
1077:                    org.geotools.styling.Stroke stroke, Object feature) {
1078:                if (stroke == null) {
1079:                    return null;
1080:                }
1081:
1082:                // get the opacity and prepare the composite
1083:                float opacity = evalOpacity(stroke.getOpacity(), feature);
1084:                Composite composite = AlphaComposite.getInstance(
1085:                        AlphaComposite.SRC_OVER, opacity);
1086:
1087:                return composite;
1088:            }
1089:
1090:            protected Paint getPaint(Fill fill, Object feature) {
1091:                if (fill == null) {
1092:                    return null;
1093:                }
1094:
1095:                // get fill color
1096:                Paint fillPaint = null;
1097:
1098:                if (fill.getColor() != null) {
1099:                    fillPaint = Color.decode((String) fill.getColor().evaluate(
1100:                            feature));
1101:
1102:                    if (LOGGER.isLoggable(Level.FINER)) {
1103:                        LOGGER.finer("Setting fill: " + fillPaint.toString());
1104:                    }
1105:                }
1106:
1107:                // if a graphic fill is to be used, prepare the paint accordingly....
1108:                org.geotools.styling.Graphic gr = fill.getGraphicFill();
1109:
1110:                if (gr != null) {
1111:                    fillPaint = getTexturePaint(gr, feature);
1112:                }
1113:
1114:                return fillPaint;
1115:            }
1116:
1117:            /**
1118:             * Computes the Composite equivalent to the opacity in the SLD Fill
1119:             *
1120:             * @param fill
1121:             * @param feature
1122:             *
1123:             */
1124:            protected Composite getComposite(Fill fill, Object feature) {
1125:                if (fill == null) {
1126:                    return null;
1127:                }
1128:
1129:                // get the opacity and prepare the composite
1130:                float opacity = evalOpacity(fill.getOpacity(), feature);
1131:                Composite composite = AlphaComposite.getInstance(
1132:                        AlphaComposite.SRC_OVER, opacity);
1133:
1134:                return composite;
1135:            }
1136:
1137:            /**
1138:             * DOCUMENT ME!
1139:             *
1140:             * @param gr DOCUMENT ME!
1141:             * @param feature DOCUMENT ME!
1142:             *
1143:             * @return DOCUMENT ME!
1144:             */
1145:            public TexturePaint getTexturePaint(
1146:                    org.geotools.styling.Graphic gr, Object feature) {
1147:                BufferedImage image = getExternalGraphic(gr);
1148:
1149:                if (image != null) {
1150:                    if (LOGGER.isLoggable(Level.FINER)) {
1151:                        LOGGER.finer("got an image in graphic fill");
1152:                    }
1153:                } else {
1154:                    if (LOGGER.isLoggable(Level.FINER)) {
1155:                        LOGGER.finer("going for the mark from graphic fill");
1156:                    }
1157:
1158:                    org.geotools.styling.Mark mark = getMark(gr, feature);
1159:
1160:                    if (mark == null) {
1161:                        return null;
1162:                    }
1163:
1164:                    int size = 200;
1165:
1166:                    image = new BufferedImage(size, size,
1167:                            BufferedImage.TYPE_INT_ARGB);
1168:
1169:                    Graphics2D g2d = image.createGraphics();
1170:                    double rotation = 0.0;
1171:
1172:                    rotation = ((Number) gr.getRotation().evaluate(feature))
1173:                            .doubleValue();
1174:                    rotation *= (Math.PI / 180.0);
1175:
1176:                    fillDrawMark(g2d, 100, 100, mark, (int) (size * .9),
1177:                            rotation, feature);
1178:
1179:                    java.awt.MediaTracker track = new java.awt.MediaTracker(obs);
1180:                    track.addImage(image, 1);
1181:
1182:                    try {
1183:                        track.waitForID(1);
1184:                    } catch (InterruptedException e) {
1185:                        // TODO: what should we do with this?
1186:                        LOGGER
1187:                                .warning("An unterupptedException occurred while drawing a local image..."
1188:                                        + e);
1189:                    }
1190:                }
1191:
1192:                int size = ((Number) gr.getSize().evaluate(feature)).intValue();
1193:                double width = image.getWidth();
1194:                double height = image.getHeight();
1195:
1196:                double unitSize = Math.max(width, height);
1197:                double drawSize = (double) size / unitSize;
1198:
1199:                width *= drawSize;
1200:                height *= -drawSize;
1201:
1202:                if (LOGGER.isLoggable(Level.FINER)) {
1203:                    LOGGER.finer("size = " + size + " unitsize " + unitSize
1204:                            + " drawSize " + drawSize);
1205:                }
1206:
1207:                Rectangle2D.Double rect = new Rectangle2D.Double(0.0, 0.0,
1208:                        width, height);
1209:                TexturePaint imagePaint = new TexturePaint(image, rect);
1210:
1211:                if (LOGGER.isLoggable(Level.FINER)) {
1212:                    LOGGER.finer("applied TexturePaint " + imagePaint);
1213:                }
1214:
1215:                return imagePaint;
1216:            }
1217:
1218:            private BufferedImage getExternalGraphic(Graphic graphic) {
1219:                ExternalGraphic[] extgraphics = graphic.getExternalGraphics();
1220:
1221:                if (extgraphics != null) {
1222:                    for (int i = 0; i < extgraphics.length; i++) {
1223:                        ExternalGraphic eg = extgraphics[i];
1224:                        BufferedImage img = getImage(eg, -1);
1225:
1226:                        if (img != null) {
1227:                            return img;
1228:                        }
1229:                    }
1230:                }
1231:
1232:                return null;
1233:            }
1234:
1235:            private BufferedImage getImage(ExternalGraphic eg, int sizeHint) {
1236:                if (LOGGER.isLoggable(Level.FINEST)) {
1237:                    LOGGER.finest("got a " + eg.getFormat());
1238:                }
1239:
1240:                BufferedImage img;
1241:
1242:                if (eg.getFormat().toLowerCase().equals("image/svg")) {
1243:                    try {
1244:                        URL svgfile = eg.getLocation();
1245:                        InternalTranscoder svgTranscoder = new InternalTranscoder();
1246:                        TranscoderInput in;
1247:
1248:                        if (svgGlyphs.containsKey(svgfile)) {
1249:                            in = new TranscoderInput((Document) svgGlyphs
1250:                                    .get(svgfile));
1251:                        } else {
1252:                            in = new TranscoderInput(svgfile.openStream());
1253:                        }
1254:
1255:                        if (sizeHint > 0) {
1256:                            svgTranscoder.addTranscodingHint(
1257:                                    SVGAbstractTranscoder.KEY_WIDTH, new Float(
1258:                                            sizeHint));
1259:                        }
1260:
1261:                        TranscoderOutput out = new TranscoderOutput();
1262:                        svgTranscoder.transcode(in, out);
1263:
1264:                        svgGlyphs.put(svgfile, svgTranscoder.getDocument());
1265:                        img = svgTranscoder.getImage();
1266:
1267:                        return img;
1268:                    } catch (IOException mue) {
1269:                        LOGGER.warning("Unable to load external svg file, "
1270:                                + mue.getMessage());
1271:
1272:                        return null;
1273:                    }
1274:                    //            catch(org.apache.batik.transcoder.TranscoderException te){
1275:                    //                this.LOGGER.warning("Unable to render external svg file, " + te.getMessage());
1276:                    //                return null;
1277:                    //            }
1278:                    catch (Exception e) {
1279:                        LOGGER
1280:                                .warning("Unable to process or render external svg file, "
1281:                                        + e.getMessage());
1282:
1283:                        return null;
1284:                    }
1285:                }
1286:
1287:                if (getSupportedGraphicFormats().contains(
1288:                        eg.getFormat().toLowerCase())) {
1289:                    if (LOGGER.isLoggable(Level.FINER)) {
1290:                        LOGGER.finer("a java supported format");
1291:                    }
1292:
1293:                    try {
1294:                        // imageLoader is not
1295:                        synchronized (imageLoader) {
1296:                            img = imageLoader.get(eg.getLocation(), false);
1297:                        }
1298:
1299:                        if (LOGGER.isLoggable(Level.FINEST)) {
1300:                            LOGGER.finest("Image return = " + img);
1301:                        }
1302:
1303:                        return img;
1304:                    } catch (java.net.MalformedURLException e) {
1305:                        LOGGER.warning("ExternalGraphic has a malformed url: "
1306:                                + e);
1307:                    }
1308:                }
1309:
1310:                return null;
1311:            }
1312:
1313:            private Mark getMark(Graphic graphic, Object feature) {
1314:                Mark[] marks = graphic.getMarks();
1315:                Mark mark;
1316:
1317:                for (int i = 0; i < marks.length; i++) {
1318:                    String name = marks[i].getWellKnownName().evaluate(feature)
1319:                            .toString();
1320:
1321:                    if (wellKnownMarks.contains(name)) {
1322:                        mark = marks[i];
1323:
1324:                        return mark;
1325:                    }
1326:                }
1327:
1328:                mark = null;
1329:
1330:                return mark;
1331:            }
1332:
1333:            private void fillDrawMark(Graphics2D graphic, double tx, double ty,
1334:                    Mark mark, int size, double rotation, Object feature) {
1335:                AffineTransform temp = graphic.getTransform();
1336:                AffineTransform markAT = new AffineTransform();
1337:                Shape shape = Java2DMark.getWellKnownMark(mark
1338:                        .getWellKnownName().evaluate(feature).toString());
1339:
1340:                Point2D mapCentre = new Point2D.Double(tx, ty);
1341:                Point2D graphicCentre = new Point2D.Double();
1342:                temp.transform(mapCentre, graphicCentre);
1343:                markAT.translate(graphicCentre.getX(), graphicCentre.getY());
1344:
1345:                double shearY = temp.getShearY();
1346:                double scaleY = temp.getScaleY();
1347:
1348:                double originalRotation = Math.atan(shearY / scaleY);
1349:
1350:                if (LOGGER.isLoggable(Level.FINER)) {
1351:                    LOGGER.finer("originalRotation " + originalRotation);
1352:                }
1353:
1354:                markAT.rotate(rotation - originalRotation);
1355:
1356:                double unitSize = 1.0; // getbounds is broken !!!
1357:                double drawSize = (double) size / unitSize;
1358:                markAT.scale(drawSize, -drawSize);
1359:
1360:                graphic.setTransform(markAT);
1361:
1362:                if (mark.getFill() != null) {
1363:                    if (LOGGER.isLoggable(Level.FINER)) {
1364:                        LOGGER.finer("applying fill to mark");
1365:                    }
1366:
1367:                    graphic.setPaint(getPaint(mark.getFill(), null));
1368:                    graphic.setComposite(getComposite(mark.getFill(), null));
1369:                    graphic.fill(shape);
1370:                }
1371:
1372:                if (mark.getStroke() != null) {
1373:                    if (LOGGER.isLoggable(Level.FINER)) {
1374:                        LOGGER.finer("applying stroke to mark");
1375:                    }
1376:
1377:                    graphic.setPaint(getStrokePaint(mark.getStroke(), null));
1378:                    graphic.setComposite(getStrokeComposite(mark.getStroke(),
1379:                            null));
1380:                    graphic.setStroke(getStroke(mark.getStroke(), null));
1381:                    graphic.draw(shape);
1382:                }
1383:
1384:                graphic.setTransform(temp);
1385:
1386:                if (mark.getFill() != null) {
1387:                    graphic.setComposite(AlphaComposite.getInstance(
1388:                            AlphaComposite.SRC_OVER, 1.0f));
1389:                }
1390:
1391:                return;
1392:            }
1393:
1394:            /**
1395:             * Evaluates an expression over the passed feature, if the expression or the result is null,
1396:             * the default value will be returned
1397:             *
1398:             * @param e
1399:             * @param drawMe
1400:             * @param defaultValue
1401:             *
1402:             */
1403:            private String evaluateExpression(
1404:                    org.opengis.filter.expression.Expression e, Object drawMe,
1405:                    String defaultValue) {
1406:                String result = defaultValue;
1407:
1408:                if (e != null) {
1409:                    result = (String) e.evaluate(drawMe);
1410:
1411:                    if (result == null) {
1412:                        result = defaultValue;
1413:                    }
1414:                }
1415:
1416:                return result;
1417:            }
1418:
1419:            /**
1420:             * DOCUMENT ME!
1421:             *
1422:             * @param joinType DOCUMENT ME!
1423:             *
1424:             * @return DOCUMENT ME!
1425:             */
1426:            public static int lookUpJoin(String joinType) {
1427:                if (SLDStyleFactory.joinLookup.containsKey(joinType)) {
1428:                    return ((Integer) joinLookup.get(joinType)).intValue();
1429:                } else {
1430:                    return java.awt.BasicStroke.JOIN_MITER;
1431:                }
1432:            }
1433:
1434:            /**
1435:             * DOCUMENT ME!
1436:             *
1437:             * @param capType DOCUMENT ME!
1438:             *
1439:             * @return DOCUMENT ME!
1440:             */
1441:            public static int lookUpCap(String capType) {
1442:                if (SLDStyleFactory.capLookup.containsKey(capType)) {
1443:                    return ((Integer) capLookup.get(capType)).intValue();
1444:                } else {
1445:                    return java.awt.BasicStroke.CAP_SQUARE;
1446:                }
1447:            }
1448:
1449:            /**
1450:             * Getter for property mapScaleDenominator.
1451:             * @return Value of property mapScaleDenominator.
1452:             */
1453:            public double getMapScaleDenominator() {
1454:
1455:                return this .mapScaleDenominator;
1456:            }
1457:
1458:            /**
1459:             * Setter for property mapScaleDenominator.
1460:             * @param mapScaleDenominator New value of property mapScaleDenominator.
1461:             */
1462:            public void setMapScaleDenominator(double mapScaleDenominator) {
1463:
1464:                this .mapScaleDenominator = mapScaleDenominator;
1465:            }
1466:
1467:            /**
1468:             * Simple key used to cache Style2D objects based on the originating symbolizer and scale
1469:             * range. Will compare symbolizers by identity, avoiding a possibly very long comparison
1470:             *
1471:             * @author aaime
1472:             */
1473:            private static class SymbolizerKey {
1474:                private Symbolizer symbolizer;
1475:                private double minScale;
1476:                private double maxScale;
1477:
1478:                public SymbolizerKey(Symbolizer symbolizer, Range scaleRange) {
1479:                    this .symbolizer = symbolizer;
1480:                    minScale = ((Number) scaleRange.getMinValue())
1481:                            .doubleValue();
1482:                    maxScale = ((Number) scaleRange.getMaxValue())
1483:                            .doubleValue();
1484:                }
1485:
1486:                /**
1487:                 * @see java.lang.Object#equals(java.lang.Object)
1488:                 */
1489:                public boolean equals(Object obj) {
1490:                    if (!(obj instanceof  SymbolizerKey)) {
1491:                        return false;
1492:                    }
1493:
1494:                    SymbolizerKey other = (SymbolizerKey) obj;
1495:
1496:                    return (other.symbolizer == symbolizer)
1497:                            && (other.minScale == minScale)
1498:                            && (other.maxScale == maxScale);
1499:                }
1500:
1501:                /**
1502:                 * @see java.lang.Object#hashCode()
1503:                 */
1504:                public int hashCode() {
1505:                    return ((((17 + System.identityHashCode(symbolizer)) * 37) + doubleHash(minScale)) * 37)
1506:                            + doubleHash(maxScale);
1507:                }
1508:
1509:                private int doubleHash(double value) {
1510:                    long bits = Double.doubleToLongBits(value);
1511:
1512:                    return (int) (bits ^ (bits >>> 32));
1513:                }
1514:            }
1515:
1516:            private float evalToFloat(Expression exp, Object f, float fallback) {
1517:                if (exp == null) {
1518:                    return fallback;
1519:                }
1520:                Object o = exp.evaluate(f);
1521:                if (o instanceof  Number)
1522:                    return ((Number) o).floatValue();
1523:                Float fo = (Float) exp.evaluate(f, Float.class);
1524:                if (fo != null) {
1525:                    return fo.floatValue();
1526:                }
1527:                return fallback;
1528:            }
1529:
1530:            private double evalToDouble(Expression exp, Object f,
1531:                    double fallback) {
1532:
1533:                if (exp == null) {
1534:                    return fallback;
1535:                }
1536:                Object o = exp.evaluate(f);
1537:                if (o instanceof  Number)
1538:                    return ((Number) o).doubleValue();
1539:                Double d = (Double) exp.evaluate(f, Double.class);
1540:                if (d != null) {
1541:                    return d.doubleValue();
1542:                }
1543:                return fallback;
1544:            }
1545:
1546:            private Color evalToColor(Expression exp, Object f, Color fallback) {
1547:                if (exp == null) {
1548:                    return fallback;
1549:                }
1550:                try {
1551:                    return Color.decode((String) exp.evaluate(f));
1552:                } catch (NumberFormatException nfe) {
1553:                    return fallback;
1554:                }
1555:            }
1556:
1557:            private float evalOpacity(Expression e, Object f) {
1558:                return evalToFloat(e, f, 1);
1559:            }
1560:
1561:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.