205 lines
5.7 KiB
Java
205 lines
5.7 KiB
Java
/*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership.
|
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
|
* (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
/**
|
|
* @author Denis M. Kishenko
|
|
* @version $Revision$
|
|
*/
|
|
package java.awt;
|
|
|
|
import java.awt.geom.AffineTransform;
|
|
import java.awt.geom.Point2D;
|
|
import java.awt.image.ColorModel;
|
|
import java.awt.image.DataBufferInt;
|
|
import java.awt.image.Raster;
|
|
import java.awt.image.WritableRaster;
|
|
|
|
class GradientPaintContext implements PaintContext {
|
|
|
|
/**
|
|
* The size of noncyclic part of color lookup table
|
|
*/
|
|
static int LOOKUP_SIZE = 256;
|
|
|
|
/**
|
|
* The index mask to lookup color in the table
|
|
*/
|
|
static int LOOKUP_MASK = 0x1FF;
|
|
|
|
/**
|
|
* The min value equivalent to zero. If absolute value less then ZERO it considered as zero.
|
|
*/
|
|
static double ZERO = 1E-10;
|
|
|
|
/**
|
|
* The ColorModel user defined for PaintContext
|
|
*/
|
|
ColorModel cm;
|
|
|
|
/**
|
|
* The indicator of cycle filling.
|
|
*/
|
|
boolean cyclic;
|
|
|
|
/**
|
|
* The integer color value of the start point
|
|
*/
|
|
int c1;
|
|
|
|
/**
|
|
* The integer color value of the end point
|
|
*/
|
|
int c2;
|
|
|
|
/**
|
|
* The lookup gradient color table
|
|
*/
|
|
int[] table;
|
|
|
|
/**
|
|
* The tempopary pre-calculated value to evalutae color index
|
|
*/
|
|
int dx;
|
|
|
|
/**
|
|
* The tempopary pre-calculated value to evalutae color index
|
|
*/
|
|
int dy;
|
|
|
|
/**
|
|
* The tempopary pre-calculated value to evalutae color index
|
|
*/
|
|
int delta;
|
|
|
|
/**
|
|
* Constructs a new GradientPaintcontext
|
|
* @param cm - not used
|
|
* @param t - the fill transformation
|
|
* @param point1 - the start fill point
|
|
* @param color1 - color of the start point
|
|
* @param point2 - the end fill point
|
|
* @param color2 - color of the end point
|
|
* @param cyclic - the indicator of cycle filling
|
|
*/
|
|
GradientPaintContext(ColorModel cm, AffineTransform t, Point2D point1, Color color1, Point2D point2, Color color2, boolean cyclic) {
|
|
this.cyclic = cyclic;
|
|
this.cm = ColorModel.getRGBdefault();
|
|
|
|
c1 = color1.getRGB();
|
|
c2 = color2.getRGB();
|
|
|
|
double px = point2.getX() - point1.getX();
|
|
double py = point2.getY() - point1.getY();
|
|
|
|
Point2D p = t.transform(point1, null);
|
|
Point2D bx = new Point2D.Double(px, py);
|
|
Point2D by = new Point2D.Double(py, -px);
|
|
|
|
t.deltaTransform(bx, bx);
|
|
t.deltaTransform(by, by);
|
|
|
|
double vec = bx.getX() * by.getY() - bx.getY() * by.getX();
|
|
|
|
if (Math.abs(vec) < ZERO) {
|
|
dx = dy = delta = 0;
|
|
table = new int[1];
|
|
table[0] = c1;
|
|
} else {
|
|
double mult = LOOKUP_SIZE * 256 / vec;
|
|
dx = (int)(by.getX() * mult);
|
|
dy = (int)(by.getY() * mult);
|
|
delta = (int)((p.getX() * by.getY() - p.getY() * by.getX()) * mult);
|
|
createTable();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create color index lookup table. Calculate 256 step trasformation from
|
|
* the start point color to the end point color. Colors multiplied by 256 to do integer calculations.
|
|
*/
|
|
void createTable() {
|
|
double ca = (c1 >> 24) & 0xFF;
|
|
double cr = (c1 >> 16) & 0xFF;
|
|
double cg = (c1 >> 8) & 0xFF;
|
|
double cb = c1 & 0xFF;
|
|
|
|
double k = 1.0 / LOOKUP_SIZE;
|
|
double da = (((c2 >> 24) & 0xFF) - ca) * k;
|
|
double dr = (((c2 >> 16) & 0xFF) - cr) * k;
|
|
double dg = (((c2 >> 8) & 0xFF) - cg) * k;
|
|
double db = ((c2 & 0xFF) - cb) * k;
|
|
|
|
table = new int[cyclic ? LOOKUP_SIZE + LOOKUP_SIZE : LOOKUP_SIZE];
|
|
for(int i = 0; i < LOOKUP_SIZE; i++) {
|
|
table[i] =
|
|
(int)ca << 24 |
|
|
(int)cr << 16 |
|
|
(int)cg << 8 |
|
|
(int)cb;
|
|
ca += da;
|
|
cr += dr;
|
|
cg += dg;
|
|
cb += db;
|
|
}
|
|
if (cyclic) {
|
|
for(int i = 0; i < LOOKUP_SIZE; i++) {
|
|
table[LOOKUP_SIZE + LOOKUP_SIZE - 1 - i] = table[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
public ColorModel getColorModel() {
|
|
return cm;
|
|
}
|
|
|
|
public void dispose() {
|
|
}
|
|
|
|
public Raster getRaster(int x, int y, int w, int h) {
|
|
WritableRaster rast = cm.createCompatibleWritableRaster(w, h);
|
|
|
|
int[] buf = ((DataBufferInt)rast.getDataBuffer()).getData();
|
|
|
|
int c = x * dy - y * dx - delta;
|
|
int cx = dy;
|
|
int cy = - w * dy - dx;
|
|
int k = 0;
|
|
|
|
if (cyclic) {
|
|
for(int j = 0; j < h; j++) {
|
|
for(int i = 0; i < w; i++) {
|
|
buf[k++] = table[(c >> 8) & LOOKUP_MASK];
|
|
c += cx;
|
|
}
|
|
c += cy;
|
|
}
|
|
} else {
|
|
for(int j = 0; j < h; j++) {
|
|
for(int i = 0; i < w; i++) {
|
|
int index = c >> 8;
|
|
buf[k++] = index < 0 ? c1 : index >= LOOKUP_SIZE ? c2 : table[index];
|
|
c += cx;
|
|
}
|
|
c += cy;
|
|
}
|
|
}
|
|
|
|
return rast;
|
|
}
|
|
|
|
}
|
|
|