/*
* Geotoolkit - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2009-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.style.interval;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.LinearGradientPaint;
import java.awt.MultipleGradientPaint;
import java.awt.Rectangle;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.text.NumberFormat;
import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
/**
*
* @author Johann Sorel (Geomatys)
* @module
*/
public class DefaultIntervalPalette implements IntervalPalette{
private final int[] ARGB;
private final double[] fractions;
public DefaultIntervalPalette(final Color[] colors) {
this(null,colors);
}
public DefaultIntervalPalette(double[] fractions, final Color[] colors) {
if(fractions == null){
fractions = new double[colors.length];
for(int i=0;i<colors.length;i++){
fractions[i] = ((double)i)/ (colors.length-1);
}
}
this.ARGB = new int[colors.length];
for(int i=0;i<colors.length;i++){
ARGB[i] = colors[i].getRGB();
}
this.fractions = fractions;
}
public int[] getARGB() {
return ARGB;
}
@Override
public List<Entry<Double, Color>> getSteps() {
final List<Entry<Double, Color>> steps = new ArrayList<Entry<Double, Color>>();
for(int i=0;i<fractions.length;i++){
steps.add(new SimpleImmutableEntry<Double, Color>(fractions[i], new Color(ARGB[i])) );
}
return steps;
}
@Override
public void render(final Graphics2D g, final Rectangle rectangle, boolean interpolate) {
final float[] fractions = new float[ARGB.length];
final Color[] colors = new Color[ARGB.length];
for(int i=0;i<ARGB.length;i++){
fractions[i] = (float)i/(ARGB.length-1);
colors[i] = new Color(ARGB[i]);
}
if(interpolate){
final MultipleGradientPaint.CycleMethod cycleMethod = MultipleGradientPaint.CycleMethod.NO_CYCLE;
final LinearGradientPaint paint = new LinearGradientPaint(
new Point2D.Double(rectangle.getMinX(),rectangle.getMinY()),
new Point2D.Double(rectangle.getMaxX(),rectangle.getMinY()),
fractions,
colors,
cycleMethod
);
g.setPaint(paint);
g.fill(rectangle);
g.setColor(Color.WHITE);
final Font font = new Font("Dialog", Font.BOLD, 13);
final FontMetrics fm = g.getFontMetrics(font);
final String text = NumberFormat.getNumberInstance().format(this.fractions[0])
+"..."+NumberFormat.getNumberInstance().format(this.fractions[this.fractions.length-1]);
final Rectangle2D rect = fm.getStringBounds(text, g);
g.drawString(text,
(float)( (rectangle.getWidth()-rect.getWidth())/2),
(float)(rectangle.getHeight() - (rectangle.getHeight()-rect.getHeight())/2) );
}else{
double step = rectangle.getWidth()/colors.length;
double start = rectangle.getX();
for(int i=0;i<colors.length;i++){
g.setColor(colors[i]);
g.fill(new Rectangle2D.Double(start, rectangle.getY(), step, rectangle.getHeight()));
start += step;
}
}
}
@Override
public Color interpolate(final double d) {
float lastStep = -1;
int lastColor = -1;
for(int k=0;k<ARGB.length;k++){
final int currentColor = ARGB[k];
double kd = k;
double total = ARGB.length-1;
final float currentStep = (float) (kd / total);
//first element, dont interpolate colors
if(k == 0){
lastColor = currentColor;
lastStep = 0;
}
if(d>currentStep){
lastStep = currentStep;
lastColor = currentColor;
continue;
}
if(d == currentStep){
return new Color(currentColor);
}
final float stepInterval = currentStep - lastStep;
final int lastAlpha = (lastColor>>>24) & 0xFF;
final int lastRed = (lastColor>>>16) & 0xFF;
final int lastGreen = (lastColor>>> 8) & 0xFF;
final int lastBlue = (lastColor>>> 0) & 0xFF;
final int alphaInterval = ((currentColor>>>24) & 0xFF) - lastAlpha;
final int redInterval = ((currentColor>>>16) & 0xFF) - lastRed;
final int greenInterval = ((currentColor>>> 8) & 0xFF) - lastGreen;
final int blueInterval = ((currentColor>>> 0) & 0xFF) - lastBlue;
//calculate interpolated color
final float relativePosition = (float) (d - lastStep);
final double pourcent = (double)( (double)relativePosition / (double)stepInterval);
int a = lastAlpha + (int)(pourcent*alphaInterval);
int r = lastRed + (int)(pourcent*redInterval);
int g = lastGreen + (int)(pourcent*greenInterval);
int b = lastBlue + (int)(pourcent*blueInterval);
a <<= 24;
r <<= 16;
g <<= 8;
b <<= 0;
return new Color(a|r|g|b);
}
return new Color(ARGB[ARGB.length-1]);
}
}