/*
* Geotoolkit - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2008 - 2015, 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.style.renderer;
import java.awt.Color;
import java.awt.Font;
import java.awt.Paint;
import java.awt.geom.AffineTransform;
import org.geotoolkit.display.VisitFilter;
import org.geotoolkit.display.PortrayalException;
import org.geotoolkit.display2d.canvas.RenderingContext2D;
import org.geotoolkit.display2d.primitive.ProjectedCoverage;
import org.geotoolkit.display2d.primitive.ProjectedGeometry;
import org.geotoolkit.display2d.primitive.ProjectedObject;
import org.geotoolkit.display2d.primitive.SearchAreaJ2D;
import org.geotoolkit.display2d.style.CachedHalo;
import org.geotoolkit.display2d.style.CachedLabelPlacement;
import org.geotoolkit.display2d.style.CachedLinePlacement;
import org.geotoolkit.display2d.style.CachedPointPlacement;
import org.geotoolkit.display2d.style.CachedTextSymbolizer;
import org.geotoolkit.display2d.style.labeling.DefaultLinearLabelDescriptor;
import org.geotoolkit.display2d.style.labeling.DefaultPointLabelDescriptor;
import org.geotoolkit.display2d.style.labeling.LabelDescriptor;
import org.geotoolkit.display2d.style.labeling.LabelLayer;
import org.geotoolkit.display2d.style.labeling.LabelRenderer;
import org.geotoolkit.referencing.operation.matrix.XAffineTransform;
/**
* @author Johann Sorel (Geomatys)
* @module
*/
public class DefaultTextSymbolizerRenderer extends AbstractSymbolizerRenderer<CachedTextSymbolizer>{
private LabelLayer labelLayer;
public DefaultTextSymbolizerRenderer(final SymbolizerRendererService service, final CachedTextSymbolizer symbol, final RenderingContext2D context){
super(service,symbol,context);
}
public LabelLayer getLabelLayer() {
if(labelLayer == null){
final LabelRenderer renderer = renderingContext.getLabelRenderer(true);
labelLayer = renderer.createLabelLayer();
renderer.append(labelLayer);
}
return labelLayer;
}
/**
* {@inheritDoc }
*/
@Override
public void portray(final ProjectedCoverage projectedCoverage) throws PortrayalException{
//portray the border of the coverage
final ProjectedGeometry projectedGeometry = projectedCoverage.getEnvelopeGeometry();
//could not find the border geometry
if(projectedGeometry == null) return;
portray(projectedGeometry, null, projectedCoverage);
}
/**
* {@inheritDoc }
*/
@Override
public void portray(final ProjectedObject projectedFeature) throws PortrayalException{
final Object candidate = projectedFeature.getCandidate();
//test if the symbol is visible on this feature
if(symbol.isVisible(candidate)){
ProjectedGeometry projectedGeometry = projectedFeature.getGeometry(geomPropertyName);
portray(projectedGeometry, candidate, projectedFeature);
}
}
public void portray(ProjectedGeometry projectedGeometry, Object candidate, final ProjectedObject projectedFeature) throws PortrayalException{
//test if the symbol is visible on this feature
if(!symbol.isVisible(candidate)) return;
//we adjust coefficient for rendering ------------------------------
float coeff = 1;
if(dispGeom){
//symbol is in display unit
coeff = 1;
}else{
//we have a special unit we must adjust the coefficient
coeff = renderingContext.getUnitCoefficient(symbolUnit);
// calculate scale difference between objective and display
final AffineTransform inverse = renderingContext.getObjectiveToDisplay();
coeff *= Math.abs(XAffineTransform.getScale(inverse));
}
//start to extract label parameters---------------------------------
String label = symbol.getLabel(candidate);
if(label == null) return; //nothing to paint
label = label.trim();
if(label.isEmpty()) return; //nothing to paint
final CachedHalo halo = symbol.getHalo();
final CachedLabelPlacement placement = symbol.getPlacement();
//extract halo parameters
final float haloWidth;
final Paint haloPaint;
if(halo != null){
haloWidth = halo.getWidth(candidate);
haloPaint = halo.getJ2DPaint(candidate, 0, 0, hints);
}else{
haloWidth = 0;
haloPaint = Color.WHITE;
}
//extract text parameters
final Paint fontPaint = symbol.getFontPaint(candidate, 0,0, coeff, hints);
final Font j2dFont = symbol.getJ2dFont(candidate, coeff);
//symbolizer doesnt match the featuretype, no geometry found with this name.
if(projectedGeometry == null) return;
projectedGeometry = new ProjectedGeometry(projectedGeometry);
//add in futur painting layer
final LabelLayer labelLayer = getLabelLayer();
final Object feature = projectedFeature.getCandidate();
if(placement instanceof CachedPointPlacement){
final CachedPointPlacement pp = (CachedPointPlacement) placement;
final float[] anchor = pp.getAnchor(feature, null);
final float[] disp = pp.getDisplacement(feature,null);
final float rotation = pp.getRotation(feature);
final LabelDescriptor descriptor = new DefaultPointLabelDescriptor(
label, j2dFont, fontPaint,
haloWidth, haloPaint,
anchor[0], anchor[1],
disp[0], disp[1],
rotation, renderingContext.getDisplayCRS(),
projectedGeometry);
labelLayer.labels().add(descriptor);
}else if(placement instanceof CachedLinePlacement){
final CachedLinePlacement lp = (CachedLinePlacement) placement;
final LabelDescriptor descriptor = new DefaultLinearLabelDescriptor(
label,
j2dFont,
fontPaint,
haloWidth,
haloPaint,
lp.getGap(feature),
lp.getInitialGap(feature),
lp.getOffset(feature),
lp.isRepeated(),
lp.isAligned(),
lp.isGeneralizeLine(),
projectedGeometry);
labelLayer.labels().add(descriptor);
}else{
throw new PortrayalException("Text symbolizer has no label placement, this should not be possible.");
}
}
/**
* {@inheritDoc }
*/
@Override
public boolean hit(final ProjectedObject candidate, final SearchAreaJ2D mask, final VisitFilter filter) {
//text symbolizer are not hittable
return false;
}
/**
* {@inheritDoc }
*/
@Override
public boolean hit(final ProjectedCoverage graphic, final SearchAreaJ2D mask, final VisitFilter filter) {
return false;
}
}