/* * Geotoolkit - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2013-2014, Geomatys * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotoolkit.display2d.ext.cellular; import java.awt.Dimension; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import org.apache.sis.storage.DataStoreException; import org.geotoolkit.data.FeatureStoreUtilities; import org.geotoolkit.display2d.GO2Utilities; import org.geotoolkit.display2d.canvas.RenderingContext2D; import org.geotoolkit.display2d.service.DefaultGlyphService; import org.geotoolkit.display2d.style.CachedRule; import org.geotoolkit.display2d.style.renderer.AbstractSymbolizerRendererService; import org.geotoolkit.display2d.style.renderer.SymbolizerRenderer; import org.geotoolkit.map.CoverageMapLayer; import org.geotoolkit.map.FeatureMapLayer; import org.geotoolkit.map.MapBuilder; import org.geotoolkit.map.MapLayer; import org.opengis.feature.FeatureType; import org.opengis.style.PointSymbolizer; import org.opengis.style.Rule; /** * * @author Johann Sorel (Geomatys) */ public class CellRendererService extends AbstractSymbolizerRendererService<CellSymbolizer,CachedCellSymbolizer>{ private static final int HEADER_SIZE = 16; private static final Font HEADER_FONT = new Font("monospaced", Font.PLAIN, 11); private static final FontMetrics FM = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB).createGraphics().getFontMetrics(HEADER_FONT); @Override public boolean isGroupSymbolizer() { return true; } @Override public Class<CellSymbolizer> getSymbolizerClass() { return CellSymbolizer.class; } @Override public Class<CachedCellSymbolizer> getCachedSymbolizerClass() { return CachedCellSymbolizer.class; } @Override public CachedCellSymbolizer createCachedSymbolizer(CellSymbolizer symbol) { return new CachedCellSymbolizer(symbol, this); } @Override public SymbolizerRenderer createRenderer(CachedCellSymbolizer symbol, RenderingContext2D context) { return new CellSymbolizerRenderer(this, symbol, context); } @Override public Rectangle2D glyphPreferredSize(CachedCellSymbolizer symbol, MapLayer layer) { //fake layer final FeatureMapLayer fakelayer = mimicCellLayer(layer); final Rule rule = symbol.getSource().getRule(); // if(symbol.getSource().getPointSymbolizer() != null){ // //generate 4 arrows base on an approximate size // final PointSymbolizer ps = symbol.getSource().getPointSymbolizer(); // final Expression exp = ps.getGraphic().getSize(); // String text = getTitle(ps); // // int width = FM.stringWidth(text); // width = Math.max(100, width); // // Dimension dim = new Dimension(width,32*3+HEADER_SIZE); // return new Rectangle2D.Double(0, 0, dim.width, dim.height); // // }else{ Dimension dim = new Dimension(5,5); final CachedRule r = symbol.getCachedRule(); dim = DefaultGlyphService.glyphPreferredSize(r.getSource(), dim, fakelayer); dim.width = dim.width*2; dim.height = dim.height*2; return new Rectangle2D.Double(0, 0, dim.width, dim.height); // } } @Override public void glyph(Graphics2D g, Rectangle2D rect, CachedCellSymbolizer symbol, MapLayer layer) { final double halfwidth = rect.getWidth()/2; final double halfheight = rect.getHeight()/2; //fake layer final FeatureMapLayer fakelayer = mimicCellLayer(layer); // if(fakelayer != null && symbol.getSource().getPointSymbolizer() != null){ // //generate 4 arrows base on an approximate size // final PointSymbolizer ps = symbol.getSource().getPointSymbolizer(); // final String text = getTitle(ps); // // g.setColor(Color.BLACK); // g.setFont(HEADER_FONT); // g.drawString(text, (int)rect.getX()+2, HEADER_SIZE-5); // // final double best = (rect.getHeight() - HEADER_SIZE)/3 ; // // final DefaultPointSymbolizerRendererService srs = new DefaultPointSymbolizerRendererService(); // final CachedPointSymbolizer cps = symbol.getCachedPointSymbolizer(); // // //first symbol at 1/1 size // Rectangle.Double rectA = new Rectangle.Double(rect.getX(), rect.getY()+HEADER_SIZE, best, best); // srs.glyph(g, rectA, cps, fakelayer, (float)best); // g.setColor(Color.BLACK); // g.drawString(NumberFormat.getNumberInstance().format(best), (int)rectA.getMaxX(), (int)rectA.getCenterY()); // // //second symbol at 1/2 size // rectA = new Rectangle.Double(rect.getX(), rect.getY()+HEADER_SIZE+best, best, best); // srs.glyph(g, rectA, cps, fakelayer, (float)best*0.6f); // g.setColor(Color.BLACK); // g.drawString(NumberFormat.getNumberInstance().format(best*0.6), (int)rectA.getMaxX(), (int)rectA.getCenterY()); // // //thrid symbol at 1/10 size // rectA = new Rectangle.Double(rect.getX(), rect.getY()+HEADER_SIZE+best*2, best, best); // srs.glyph(g, rectA, cps, fakelayer, (float)best*0.2f); // g.setColor(Color.BLACK); // g.drawString(NumberFormat.getNumberInstance().format(best*0.2), (int)rectA.getMaxX(), (int)rectA.getCenterY()); // // }else{ glyphBlock(g, new Rectangle.Double(rect.getX(), rect.getY(), halfwidth, halfheight), symbol, fakelayer); glyphBlock(g, new Rectangle.Double(rect.getX(), rect.getY()+halfheight, halfwidth, halfheight), symbol, fakelayer); glyphBlock(g, new Rectangle.Double(rect.getX()+halfwidth, rect.getY(), halfwidth, halfheight), symbol, fakelayer); glyphBlock(g, new Rectangle.Double(rect.getX()+halfwidth, rect.getY()+halfheight, halfwidth, halfheight), symbol, fakelayer); // } } private void glyphBlock(Graphics2D g, Rectangle2D rect, CachedCellSymbolizer symbol, MapLayer layer){ final CachedRule r = symbol.getCachedRule(); DefaultGlyphService.render(r.getSource(), rect, g, layer); } private static FeatureMapLayer mimicCellLayer(MapLayer layer){ //fake layer if(layer instanceof CoverageMapLayer){ try { final FeatureType sft = CellSymbolizer.buildCellType((CoverageMapLayer)layer); layer = MapBuilder.createFeatureLayer(FeatureStoreUtilities.collection("", sft), GO2Utilities.STYLE_FACTORY.style()); } catch (DataStoreException ex) { //not important } }else if(layer instanceof FeatureMapLayer){ final FeatureType sft = CellSymbolizer.buildCellType( ((FeatureMapLayer)layer).getCollection().getFeatureType(),null); layer = MapBuilder.createFeatureLayer(FeatureStoreUtilities.collection("", sft), GO2Utilities.STYLE_FACTORY.style()); }else{ layer = null; } return (FeatureMapLayer) layer; } private static String getTitle(PointSymbolizer ps){ final StringBuilder sb = new StringBuilder(); String title = ps.getDescription().getTitle().toString(); if(title!=null && !title.isEmpty()){ sb.append(sb); } String desc = ps.getDescription().getAbstract().toString(); if(desc!=null && !desc.isEmpty()){ sb.append(' '); if(title!=null && !title.isEmpty()) sb.append('('); sb.append(desc); if(title!=null && !title.isEmpty()) sb.append(')'); } return sb.toString(); } }