| /* |
| * 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; |
| } |
| |
| } |
| |