/*
* Geotoolkit - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2008 - 2009, 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;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Paint;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.TexturePaint;
import java.awt.image.BufferedImage;
import org.geotoolkit.display2d.GO2Utilities;
import org.opengis.filter.expression.Expression;
import org.opengis.style.Fill;
import org.opengis.style.GraphicFill;
/**
* Cached Fill.
*
* @author Johann Sorel (Geomatys)
* @module
*/
public class CachedFill extends Cache<Fill>{
//Cached values
private AlphaComposite cachedComposite = null;
private Paint cachedPaint = null;
private CachedGraphic cachedGraphic = null;
private CachedFill(final Fill fill){
super(fill);
}
/**
* {@inheritDoc }
*/
@Override
protected void evaluate(){
if(!isNotEvaluated) return;
this.isStatic = true;
if(!evaluateComposite() || !evaluatePaint() ){
//composite is completely translucent or paint is not visible
//we cache nothing seens nothing can be render
cachedComposite = null;
cachedPaint = null;
cachedGraphic = null;
requieredAttributs = EMPTY_ATTRIBUTS;
isStatic = true;
}
isNotEvaluated = false;
}
/**
* @return false if it's not even necessary to paint anything.
*/
private boolean evaluateComposite(){
final Expression opacity = styleElement.getOpacity();
if(GO2Utilities.isStatic(opacity)){
float j2dOpacity = GO2Utilities.evaluate(opacity, null, 1f,0f,1f);
//we return false, opacity is 0 no need to cache or draw anything
if(j2dOpacity <= 0){
isStaticVisible = VisibilityState.UNVISIBLE;
return false;
}
//this style is visible
if(isStaticVisible == VisibilityState.NOT_DEFINED) isStaticVisible = VisibilityState.VISIBLE;
//we cache the composite
cachedComposite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, j2dOpacity);
}else{
//this style visibility is dynamic
if(isStaticVisible != VisibilityState.UNVISIBLE) isStaticVisible = VisibilityState.DYNAMIC;
isStatic = false;
GO2Utilities.getRequieredAttributsName(opacity,requieredAttributs);
}
return true;
}
/**
* @return false if it's not even necessary to paint anything.
*/
private boolean evaluatePaint(){
final GraphicFill graphicFill = styleElement.getGraphicFill();
if(graphicFill != null && graphicFill != null){
cachedGraphic = CachedGraphic.cache(graphicFill);
switch(cachedGraphic.isStaticVisible()){
//graphic is not visible even if some value are dynamic, this fill is not visible neither
case UNVISIBLE :
isStaticVisible = VisibilityState.UNVISIBLE;
return false;
//graphic visibility is dynamic, so this fill too
case DYNAMIC :
if(isStaticVisible != VisibilityState.UNVISIBLE) isStaticVisible = VisibilityState.DYNAMIC;
break;
//this graphic is visible
default :
if(isStaticVisible == VisibilityState.NOT_DEFINED) isStaticVisible = VisibilityState.VISIBLE;
}
cachedGraphic.getRequieredAttributsName(requieredAttributs);
}else{
final Expression expColor = styleElement.getColor();
if(GO2Utilities.isStatic(expColor)){
Color j2dColor = GO2Utilities.evaluate(expColor, null, Color.class, Color.BLACK);
//we return false, opacity is 0 no need to cache or draw anything
if( j2dColor.getAlpha() <= 0 ){
isStaticVisible = VisibilityState.UNVISIBLE;
return false;
}
//this style is visible even if something else is dynamic
//evaluatePaint may change this value
if(isStaticVisible == VisibilityState.NOT_DEFINED) isStaticVisible = VisibilityState.VISIBLE;
//we cache the paint
cachedPaint = j2dColor;
}else{
//this style visibility is dynamic
if(isStaticVisible != VisibilityState.UNVISIBLE) isStaticVisible = VisibilityState.DYNAMIC;
isStatic = false;
GO2Utilities.getRequieredAttributsName(expColor,requieredAttributs);
}
}
return true;
}
/**
* {@inheritDoc }
*/
@Override
public boolean isVisible(final Object candidate){
evaluate();
if(isStaticVisible == VisibilityState.VISIBLE){
//visible whatever feature we have
return true;
}else if(isStaticVisible == VisibilityState.UNVISIBLE){
//unvisible whatever feature we have
return false;
}else{
//dynamic visibility
//test dynamic composite
if(cachedComposite == null){
final Expression opacity = styleElement.getOpacity();
Float j2dOpacity = GO2Utilities.evaluate(opacity, candidate, 1f,0f,1f);
if(j2dOpacity <= 0) return false;
}
//test dynamic paint
if(cachedPaint == null){
final Expression expColor = styleElement.getColor();
if (cachedGraphic != null) {
boolean visible = cachedGraphic.isVisible(candidate);
if(!visible) return false;
} else {
//or it's a normal plain inside
Color color = GO2Utilities.evaluate(expColor, null, Color.class, Color.BLACK);
if(color.getAlpha() <= 0) return false;
}
}
return true;
}
}
/**
* @return Java2D composite for this feature
*/
public AlphaComposite getJ2DComposite(final Object candidate){
evaluate();
if(cachedComposite == null){
//if composite is null it means it is dynamic
final Expression opacity = styleElement.getOpacity();
Float j2dOpacity = GO2Utilities.evaluate(opacity, candidate, 1f,0f,1f);
return AlphaComposite.getInstance(AlphaComposite.SRC_OVER, j2dOpacity.floatValue());
}
return cachedComposite;
}
/**
*
* @return true if the paint is a texture, in this case X/Y value must be correct
* when calling getJ2DPaint method.
*/
public boolean isMosaic(){
return cachedPaint != null && cachedGraphic != null;
}
/**
*
* @return Java2D paint for this feature
*/
public Paint getJ2DPaint(final Object candidate, final int x, final int y, final float coeff, final RenderingHints hints){
evaluate();
if(cachedPaint == null){
//if paint is null it means it is dynamic
final Expression expColor = styleElement.getColor();
if (cachedGraphic != null) {
//we have a graphic inside
BufferedImage mosaique = cachedGraphic.getImage(candidate, coeff, hints);
if (mosaique != null) {
return new TexturePaint(mosaique, new Rectangle(x, y, mosaique.getWidth(), mosaique.getHeight()));
} else {
return Color.BLACK;
}
} else {
//or it's a normal plain inside
return GO2Utilities.evaluate(expColor, candidate, Color.class, Color.BLACK);
}
}
return cachedPaint;
}
public static CachedFill cache(final Fill fill){
return new CachedFill(fill);
}
}