RadialGradient_Delegate.java revision 56222cfbe9973c518f7e8c9113c614de80b5a4b2
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.graphics; 18 19import com.android.layoutlib.bridge.Bridge; 20import com.android.layoutlib.bridge.BridgeConstants; 21import com.android.layoutlib.bridge.impl.DelegateManager; 22 23import android.graphics.Shader.TileMode; 24 25/** 26 * Delegate implementing the native methods of android.graphics.RadialGradient 27 * 28 * Through the layoutlib_create tool, the original native methods of RadialGradient have been 29 * replaced by calls to methods of the same name in this delegate class. 30 * 31 * This class behaves like the original native implementation, but in Java, keeping previously 32 * native data into its own objects and mapping them to int that are sent back and forth between 33 * it and the original RadialGradient class. 34 * 35 * Because this extends {@link Shader_Delegate}, there's no need to use a {@link DelegateManager}, 36 * as all the Shader classes will be added to the manager owned by {@link Shader_Delegate}. 37 * 38 * @see Shader_Delegate 39 * 40 */ 41public class RadialGradient_Delegate extends Gradient_Delegate { 42 43 // ---- delegate data ---- 44 private java.awt.Paint mJavaPaint; 45 46 // ---- Public Helper methods ---- 47 48 @Override 49 public java.awt.Paint getJavaPaint() { 50 return mJavaPaint; 51 } 52 53 // ---- native methods ---- 54 55 /*package*/ static int nativeCreate1(float x, float y, float radius, 56 int colors[], float positions[], int tileMode) { 57 RadialGradient_Delegate newDelegate = new RadialGradient_Delegate(x, y, radius, 58 colors, positions, Shader_Delegate.getTileMode(tileMode)); 59 return sManager.addDelegate(newDelegate); 60 } 61 62 /*package*/ static int nativeCreate2(float x, float y, float radius, 63 int color0, int color1, int tileMode) { 64 return nativeCreate1(x, y, radius, new int[] { color0, color1 }, null /*positions*/, 65 tileMode); 66 } 67 68 /*package*/ static int nativePostCreate1(int native_shader, float x, float y, float radius, 69 int colors[], float positions[], int tileMode) { 70 // nothing to be done here. 71 return 0; 72 } 73 74 /*package*/ static int nativePostCreate2(int native_shader, float x, float y, float radius, 75 int color0, int color1, int tileMode) { 76 // nothing to be done here. 77 return 0; 78 } 79 80 // ---- Private delegate/helper methods ---- 81 82 /** 83 * Create a shader that draws a radial gradient given the center and radius. 84 * 85 * @param x The x-coordinate of the center of the radius 86 * @param y The y-coordinate of the center of the radius 87 * @param radius Must be positive. The radius of the circle for this 88 * gradient 89 * @param colors The colors to be distributed between the center and edge of 90 * the circle 91 * @param positions May be NULL. The relative position of each corresponding 92 * color in the colors array. If this is NULL, the the colors are 93 * distributed evenly between the center and edge of the circle. 94 * @param tile The Shader tiling mode 95 */ 96 private RadialGradient_Delegate(float x, float y, float radius, int colors[], float positions[], 97 TileMode tile) { 98 super(colors, positions); 99 mJavaPaint = new RadialGradientPaint(x, y, radius, mColors, mPositions, tile); 100 } 101 102 private class RadialGradientPaint extends GradientPaint { 103 104 private final float mX; 105 private final float mY; 106 private final float mRadius; 107 108 public RadialGradientPaint(float x, float y, float radius, 109 int[] colors, float[] positions, TileMode mode) { 110 super(colors, positions, mode); 111 mX = x; 112 mY = y; 113 mRadius = radius; 114 } 115 116 public java.awt.PaintContext createContext( 117 java.awt.image.ColorModel colorModel, 118 java.awt.Rectangle deviceBounds, 119 java.awt.geom.Rectangle2D userBounds, 120 java.awt.geom.AffineTransform xform, 121 java.awt.RenderingHints hints) { 122 precomputeGradientColors(); 123 124 java.awt.geom.AffineTransform canvasMatrix; 125 try { 126 canvasMatrix = xform.createInverse(); 127 } catch (java.awt.geom.NoninvertibleTransformException e) { 128 Bridge.getLog().fidelityWarning(BridgeConstants.TAG_MATRIX, 129 "Unable to inverse matrix in RadialGradient", e); 130 canvasMatrix = new java.awt.geom.AffineTransform(); 131 } 132 133 java.awt.geom.AffineTransform localMatrix = getLocalMatrix(); 134 try { 135 localMatrix = localMatrix.createInverse(); 136 } catch (java.awt.geom.NoninvertibleTransformException e) { 137 Bridge.getLog().fidelityWarning(BridgeConstants.TAG_MATRIX, 138 "Unable to inverse matrix in RadialGradient", e); 139 localMatrix = new java.awt.geom.AffineTransform(); 140 } 141 142 return new RadialGradientPaintContext(canvasMatrix, localMatrix, colorModel); 143 } 144 145 private class RadialGradientPaintContext implements java.awt.PaintContext { 146 147 private final java.awt.geom.AffineTransform mCanvasMatrix; 148 private final java.awt.geom.AffineTransform mLocalMatrix; 149 private final java.awt.image.ColorModel mColorModel; 150 151 public RadialGradientPaintContext( 152 java.awt.geom.AffineTransform canvasMatrix, 153 java.awt.geom.AffineTransform localMatrix, 154 java.awt.image.ColorModel colorModel) { 155 mCanvasMatrix = canvasMatrix; 156 mLocalMatrix = localMatrix; 157 mColorModel = colorModel; 158 } 159 160 public void dispose() { 161 } 162 163 public java.awt.image.ColorModel getColorModel() { 164 return mColorModel; 165 } 166 167 public java.awt.image.Raster getRaster(int x, int y, int w, int h) { 168 java.awt.image.BufferedImage image = new java.awt.image.BufferedImage(w, h, 169 java.awt.image.BufferedImage.TYPE_INT_ARGB); 170 171 int[] data = new int[w*h]; 172 173 // compute distance from each point to the center, and figure out the distance from 174 // it. 175 int index = 0; 176 float[] pt1 = new float[2]; 177 float[] pt2 = new float[2]; 178 for (int iy = 0 ; iy < h ; iy++) { 179 for (int ix = 0 ; ix < w ; ix++) { 180 // handle the canvas transform 181 pt1[0] = x + ix; 182 pt1[1] = y + iy; 183 mCanvasMatrix.transform(pt1, 0, pt2, 0, 1); 184 185 // handle the local matrix 186 pt1[0] = pt2[0] - mX; 187 pt1[1] = pt2[1] - mY; 188 mLocalMatrix.transform(pt1, 0, pt2, 0, 1); 189 190 float _x = pt2[0]; 191 float _y = pt2[1]; 192 float distance = (float) Math.sqrt(_x * _x + _y * _y); 193 194 data[index++] = getGradientColor(distance / mRadius); 195 } 196 } 197 198 image.setRGB(0 /*startX*/, 0 /*startY*/, w, h, data, 0 /*offset*/, w /*scansize*/); 199 200 return image.getRaster(); 201 } 202 203 } 204 } 205 206} 207