001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2002-2006, GeoTools Project Managment Committee (PMC)
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation;
009: * version 2.1 of the License.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: */
016: package org.geotools.renderer.lite;
017:
018: import java.util.logging.Logger;
019:
020: import org.geotools.filter.FilterAttributeExtractor;
021: import org.geotools.styling.AnchorPoint;
022: import org.geotools.styling.ColorMap;
023: import org.geotools.styling.ColorMapEntry;
024: import org.geotools.styling.Displacement;
025: import org.geotools.styling.ExternalGraphic;
026: import org.geotools.styling.FeatureTypeConstraint;
027: import org.geotools.styling.FeatureTypeStyle;
028: import org.geotools.styling.Fill;
029: import org.geotools.styling.Graphic;
030: import org.geotools.styling.Halo;
031: import org.geotools.styling.LinePlacement;
032: import org.geotools.styling.LineSymbolizer;
033: import org.geotools.styling.Mark;
034: import org.geotools.styling.NamedLayer;
035: import org.geotools.styling.PointPlacement;
036: import org.geotools.styling.PointSymbolizer;
037: import org.geotools.styling.PolygonSymbolizer;
038: import org.geotools.styling.RasterSymbolizer;
039: import org.geotools.styling.Rule;
040: import org.geotools.styling.Stroke;
041: import org.geotools.styling.Style;
042: import org.geotools.styling.StyleVisitor;
043: import org.geotools.styling.StyledLayer;
044: import org.geotools.styling.StyledLayerDescriptor;
045: import org.geotools.styling.Symbolizer;
046: import org.geotools.styling.TextSymbolizer;
047: import org.geotools.styling.UserLayer;
048: import org.opengis.filter.Filter;
049: import org.opengis.filter.expression.Literal;
050:
051: /**
052: * Parses a style or part of it and returns the size of the largest stroke and the biggest point
053: * symbolizer whose width is specified with a literal expression.<br>
054: * Also provides an indication wheter the stroke width is accurate, or if a non literal width has
055: * been found.
056: */
057:
058: public class MetaBufferEstimator extends FilterAttributeExtractor
059: implements StyleVisitor {
060: /** The logger for the rendering module. */
061: private static final Logger LOGGER = org.geotools.util.logging.Logging
062: .getLogger("org.geotools.rendering");
063:
064: boolean estimateAccurate = true;
065:
066: int buffer = 0;
067:
068: /**
069: * Should you reuse this extractor multiple time, calling this method will reset the buffer and
070: * flags
071: *
072: */
073: public void reset() {
074: estimateAccurate = true;
075: buffer = 0;
076: }
077:
078: public int getBuffer() {
079: return buffer;
080: }
081:
082: public boolean isEstimateAccurate() {
083: return estimateAccurate;
084: }
085:
086: public void visit(Style style) {
087: FeatureTypeStyle[] ftStyles = style.getFeatureTypeStyles();
088:
089: for (int i = 0; i < ftStyles.length; i++) {
090: ftStyles[i].accept(this );
091: }
092: }
093:
094: public void visit(Rule rule) {
095: Filter filter = rule.getFilter();
096:
097: if (filter != null) {
098: filter.accept(this , null);
099: }
100:
101: Symbolizer[] symbolizers = rule.getSymbolizers();
102:
103: if (symbolizers != null) {
104: for (int i = 0; i < symbolizers.length; i++) {
105: Symbolizer symbolizer = symbolizers[i];
106: symbolizer.accept(this );
107: }
108: }
109:
110: Graphic[] legendGraphics = rule.getLegendGraphic();
111:
112: if (legendGraphics != null) {
113: }
114: }
115:
116: public void visit(FeatureTypeStyle fts) {
117: Rule[] rules = fts.getRules();
118:
119: for (int i = 0; i < rules.length; i++) {
120: Rule rule = rules[i];
121: rule.accept(this );
122: }
123: }
124:
125: public void visit(Fill fill) {
126: // nothing to do here
127: }
128:
129: /**
130: * @see org.geotools.styling.StyleVisitor#visit(org.geotools.styling.Stroke)
131: */
132: public void visit(Stroke stroke) {
133: try {
134: if (stroke.getWidth() != null) {
135: if (stroke.getWidth() instanceof Literal) {
136: Literal lw = (Literal) stroke.getWidth();
137: final Number val = (Number) lw.evaluate(null,
138: Double.class);
139: if (val != null) {
140: int iw = (int) Math.ceil(val.doubleValue());
141: if (iw > buffer)
142: buffer = iw;
143: } else {
144: estimateAccurate = false;
145: }
146: } else {
147: estimateAccurate = false;
148: }
149: }
150: } catch (ClassCastException e) {
151: estimateAccurate = false;
152: LOGGER.info("Could not parse stroke width, "
153: + "it's a literal but not a Number...");
154: }
155: }
156:
157: /**
158: * @see org.geotools.styling.StyleVisitor#visit(org.geotools.styling.Symbolizer)
159: */
160: public void visit(Symbolizer sym) {
161: if (sym instanceof PointSymbolizer) {
162: visit((PointSymbolizer) sym);
163: }
164:
165: if (sym instanceof LineSymbolizer) {
166: visit((LineSymbolizer) sym);
167: }
168:
169: if (sym instanceof PolygonSymbolizer) {
170: visit((PolygonSymbolizer) sym);
171: }
172:
173: if (sym instanceof TextSymbolizer) {
174: visit((TextSymbolizer) sym);
175: }
176:
177: if (sym instanceof RasterSymbolizer) {
178: visit((RasterSymbolizer) sym);
179: }
180: }
181:
182: public void visit(RasterSymbolizer rs) {
183: if (rs.getGeometryPropertyName() != null) {
184: attributeNames.add(rs.getGeometryPropertyName());
185:
186: // FIXME
187: // LiteRenderer2 trhwos an Exception:
188: // Do not know how to deep copy
189: // org.geotools.coverage.grid.GridCoverage2D
190: // attributeNames.add("grid");
191: }
192:
193: if (rs.getImageOutline() != null) {
194: rs.getImageOutline().accept(this );
195: }
196:
197: if (rs.getOpacity() != null) {
198: rs.getOpacity().accept(this , null);
199: }
200: }
201:
202: /**
203: * @see org.geotools.styling.StyleVisitor#visit(org.geotools.styling.PointSymbolizer)
204: */
205: public void visit(PointSymbolizer ps) {
206: if (ps.getGraphic() != null) {
207: ps.getGraphic().accept(this );
208: }
209: }
210:
211: /**
212: * @see org.geotools.styling.StyleVisitor#visit(org.geotools.styling.LineSymbolizer)
213: */
214: public void visit(LineSymbolizer line) {
215: if (line.getStroke() != null) {
216: line.getStroke().accept(this );
217: }
218: }
219:
220: /**
221: * @see org.geotools.styling.StyleVisitor#visit(org.geotools.styling.PolygonSymbolizer)
222: */
223: public void visit(PolygonSymbolizer poly) {
224: if (poly.getStroke() != null) {
225: poly.getStroke().accept(this );
226: }
227: }
228:
229: /**
230: * @see org.geotools.styling.StyleVisitor#visit(org.geotools.styling.TextSymbolizer)
231: */
232: public void visit(TextSymbolizer text) {
233: // nothing to do here
234: }
235:
236: /**
237: * @see org.geotools.styling.StyleVisitor#visit(org.geotools.styling.Graphic)
238: */
239: public void visit(Graphic gr) {
240: try {
241: if (gr.getSize() instanceof Literal) {
242: Literal lw = (Literal) gr.getSize();
243: final Number val = (Number) lw.evaluate(null,
244: Double.class);
245: if (val != null) {
246: int iw = (int) Math.ceil((val).doubleValue());
247: if (iw > buffer)
248: buffer = iw;
249: } else {
250: estimateAccurate = false;
251: }
252: } else {
253: estimateAccurate = false;
254: }
255: } catch (ClassCastException e) {
256: estimateAccurate = false;
257: LOGGER.info("Could not parse graphic size, "
258: + "it's a literal but not a Number...");
259: }
260: }
261:
262: /**
263: * @see org.geotools.styling.StyleVisitor#visit(org.geotools.styling.Mark)
264: */
265: public void visit(Mark mark) {
266: // nothing to do here
267: }
268:
269: /**
270: * @see org.geotools.styling.StyleVisitor#visit(org.geotools.styling.ExternalGraphic)
271: */
272: public void visit(ExternalGraphic exgr) {
273: // nothing to do
274: }
275:
276: /**
277: * @see org.geotools.styling.StyleVisitor#visit(org.geotools.styling.PointPlacement)
278: */
279: public void visit(PointPlacement pp) {
280: // nothing to do here
281: }
282:
283: /**
284: * @see org.geotools.styling.StyleVisitor#visit(org.geotools.styling.AnchorPoint)
285: */
286: public void visit(AnchorPoint ap) {
287: // nothing to do here
288: }
289:
290: /**
291: * @see org.geotools.styling.StyleVisitor#visit(org.geotools.styling.Displacement)
292: */
293: public void visit(Displacement dis) {
294: // nothing to do here
295: }
296:
297: /**
298: * @see org.geotools.styling.StyleVisitor#visit(org.geotools.styling.LinePlacement)
299: */
300: public void visit(LinePlacement lp) {
301: // nothing to do here
302: }
303:
304: /**
305: * @see org.geotools.styling.StyleVisitor#visit(org.geotools.styling.Halo)
306: */
307: public void visit(Halo halo) {
308: // nothing to do here
309: }
310:
311: public void visit(StyledLayerDescriptor sld) {
312: StyledLayer[] layers = sld.getStyledLayers();
313:
314: for (int i = 0; i < layers.length; i++) {
315: if (layers[i] instanceof NamedLayer) {
316: ((NamedLayer) layers[i]).accept(this );
317: } else if (layers[i] instanceof UserLayer) {
318: ((UserLayer) layers[i]).accept(this );
319: }
320: }
321: }
322:
323: public void visit(NamedLayer layer) {
324: Style[] styles = layer.getStyles();
325:
326: for (int i = 0; i < styles.length; i++) {
327: styles[i].accept(this );
328: }
329: }
330:
331: public void visit(UserLayer layer) {
332: Style[] styles = layer.getUserStyles();
333:
334: for (int i = 0; i < styles.length; i++) {
335: styles[i].accept(this );
336: }
337: }
338:
339: public void visit(FeatureTypeConstraint ftc) {
340: // TODO Auto-generated method stub
341: }
342:
343: public void visit(ColorMap map) {
344: // nothing to do here
345: }
346:
347: public void visit(ColorMapEntry entry) {
348: // nothing to do here
349: }
350: }
|