19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed to the Apache Software Foundation (ASF) under one or more 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * contributor license agreements. See the NOTICE file distributed with 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * this work for additional information regarding copyright ownership. 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (the "License"); you may not use this file except in compliance with 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the License. You may obtain a copy of the License at 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @author Denis M. Kishenko 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @version $Revision$ 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage java.awt; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.awt.geom.AffineTransform; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.awt.geom.Point2D; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.awt.image.ColorModel; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.awt.image.DataBufferInt; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.awt.image.Raster; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.awt.image.WritableRaster; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass GradientPaintContext implements PaintContext { 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The size of noncyclic part of color lookup table 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static int LOOKUP_SIZE = 256; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The index mask to lookup color in the table 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static int LOOKUP_MASK = 0x1FF; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The min value equivalent to zero. If absolute value less then ZERO it considered as zero. 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static double ZERO = 1E-10; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The ColorModel user defined for PaintContext 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ColorModel cm; 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The indicator of cycle filling. 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean cyclic; 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The integer color value of the start point 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int c1; 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The integer color value of the end point 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int c2; 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The lookup gradient color table 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] table; 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The tempopary pre-calculated value to evalutae color index 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int dx; 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The tempopary pre-calculated value to evalutae color index 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int dy; 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The tempopary pre-calculated value to evalutae color index 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int delta; 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Constructs a new GradientPaintcontext 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param cm - not used 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param t - the fill transformation 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param point1 - the start fill point 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param color1 - color of the start point 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param point2 - the end fill point 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param color2 - color of the end point 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param cyclic - the indicator of cycle filling 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project GradientPaintContext(ColorModel cm, AffineTransform t, Point2D point1, Color color1, Point2D point2, Color color2, boolean cyclic) { 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.cyclic = cyclic; 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.cm = ColorModel.getRGBdefault(); 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project c1 = color1.getRGB(); 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project c2 = color2.getRGB(); 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project double px = point2.getX() - point1.getX(); 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project double py = point2.getY() - point1.getY(); 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Point2D p = t.transform(point1, null); 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Point2D bx = new Point2D.Double(px, py); 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Point2D by = new Point2D.Double(py, -px); 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t.deltaTransform(bx, bx); 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t.deltaTransform(by, by); 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project double vec = bx.getX() * by.getY() - bx.getY() * by.getX(); 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Math.abs(vec) < ZERO) { 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dx = dy = delta = 0; 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project table = new int[1]; 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project table[0] = c1; 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project double mult = LOOKUP_SIZE * 256 / vec; 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dx = (int)(by.getX() * mult); 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dy = (int)(by.getY() * mult); 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delta = (int)((p.getX() * by.getY() - p.getY() * by.getX()) * mult); 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project createTable(); 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create color index lookup table. Calculate 256 step trasformation from 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the start point color to the end point color. Colors multiplied by 256 to do integer calculations. 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void createTable() { 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project double ca = (c1 >> 24) & 0xFF; 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project double cr = (c1 >> 16) & 0xFF; 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project double cg = (c1 >> 8) & 0xFF; 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project double cb = c1 & 0xFF; 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project double k = 1.0 / LOOKUP_SIZE; 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project double da = (((c2 >> 24) & 0xFF) - ca) * k; 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project double dr = (((c2 >> 16) & 0xFF) - cr) * k; 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project double dg = (((c2 >> 8) & 0xFF) - cg) * k; 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project double db = ((c2 & 0xFF) - cb) * k; 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project table = new int[cyclic ? LOOKUP_SIZE + LOOKUP_SIZE : LOOKUP_SIZE]; 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for(int i = 0; i < LOOKUP_SIZE; i++) { 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project table[i] = 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (int)ca << 24 | 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (int)cr << 16 | 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (int)cg << 8 | 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (int)cb; 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ca += da; 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cr += dr; 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cg += dg; 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cb += db; 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cyclic) { 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for(int i = 0; i < LOOKUP_SIZE; i++) { 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project table[LOOKUP_SIZE + LOOKUP_SIZE - 1 - i] = table[i]; 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ColorModel getColorModel() { 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return cm; 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void dispose() { 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Raster getRaster(int x, int y, int w, int h) { 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project WritableRaster rast = cm.createCompatibleWritableRaster(w, h); 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] buf = ((DataBufferInt)rast.getDataBuffer()).getData(); 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int c = x * dy - y * dx - delta; 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int cx = dy; 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int cy = - w * dy - dx; 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int k = 0; 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cyclic) { 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for(int j = 0; j < h; j++) { 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for(int i = 0; i < w; i++) { 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buf[k++] = table[(c >> 8) & LOOKUP_MASK]; 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project c += cx; 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project c += cy; 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for(int j = 0; j < h; j++) { 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for(int i = 0; i < w; i++) { 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int index = c >> 8; 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buf[k++] = index < 0 ? c1 : index >= LOOKUP_SIZE ? c2 : table[index]; 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project c += cx; 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project c += cy; 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return rast; 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 205