19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 2251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet * Copyright (C) 2010 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.graphics; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19918aaa5717fce6081557c82ce1c439b6922737d5Xavier Ducrohetimport com.android.ide.common.rendering.api.LayoutLog; 20d9c64369cf9be6568af2d79c35fb470cc261730dXavier Ducrohetimport com.android.layoutlib.bridge.Bridge; 21c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport com.android.layoutlib.bridge.impl.DelegateManager; 229a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohetimport com.android.tools.layoutlib.annotations.LayoutlibDelegate; 2345a7c285985976c23d818665694addbb25e02565Xavier Ducrohet 24251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohetimport android.graphics.Shader.TileMode; 25251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet 26251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet/** 27251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet * Delegate implementing the native methods of android.graphics.RadialGradient 28251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet * 29251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet * Through the layoutlib_create tool, the original native methods of RadialGradient have been 30251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet * replaced by calls to methods of the same name in this delegate class. 31251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet * 32251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet * This class behaves like the original native implementation, but in Java, keeping previously 33251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet * native data into its own objects and mapping them to int that are sent back and forth between 34251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet * it and the original RadialGradient class. 35251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet * 36251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet * Because this extends {@link Shader_Delegate}, there's no need to use a {@link DelegateManager}, 37251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet * as all the Shader classes will be added to the manager owned by {@link Shader_Delegate}. 38251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet * 39251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet * @see Shader_Delegate 40251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet * 41251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet */ 42251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohetpublic class RadialGradient_Delegate extends Gradient_Delegate { 43251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet 44251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet // ---- delegate data ---- 45251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet private java.awt.Paint mJavaPaint; 46251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet 47251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet // ---- Public Helper methods ---- 48251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet 49251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet @Override 50d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet public java.awt.Paint getJavaPaint() { 51251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet return mJavaPaint; 52251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet } 53251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet 54251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet // ---- native methods ---- 55251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet 569a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet @LayoutlibDelegate 57251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet /*package*/ static int nativeCreate1(float x, float y, float radius, 58251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet int colors[], float positions[], int tileMode) { 59251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet RadialGradient_Delegate newDelegate = new RadialGradient_Delegate(x, y, radius, 60d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet colors, positions, Shader_Delegate.getTileMode(tileMode)); 61cc4977d0fdaf657907912fd6cc2f9426dc8d2e36Xavier Ducrohet return sManager.addNewDelegate(newDelegate); 62251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet } 63251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet 649a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet @LayoutlibDelegate 65251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet /*package*/ static int nativeCreate2(float x, float y, float radius, 66251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet int color0, int color1, int tileMode) { 67251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet return nativeCreate1(x, y, radius, new int[] { color0, color1 }, null /*positions*/, 68251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet tileMode); 69251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet } 70251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet 719a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet @LayoutlibDelegate 72251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet /*package*/ static int nativePostCreate1(int native_shader, float x, float y, float radius, 73251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet int colors[], float positions[], int tileMode) { 74251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet // nothing to be done here. 75251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet return 0; 76251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet } 77251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet 789a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet @LayoutlibDelegate 79251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet /*package*/ static int nativePostCreate2(int native_shader, float x, float y, float radius, 80251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet int color0, int color1, int tileMode) { 81251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet // nothing to be done here. 82251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet return 0; 83251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet } 84251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet 85251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet // ---- Private delegate/helper methods ---- 8645a7c285985976c23d818665694addbb25e02565Xavier Ducrohet 8745a7c285985976c23d818665694addbb25e02565Xavier Ducrohet /** 8845a7c285985976c23d818665694addbb25e02565Xavier Ducrohet * Create a shader that draws a radial gradient given the center and radius. 8945a7c285985976c23d818665694addbb25e02565Xavier Ducrohet * 9045a7c285985976c23d818665694addbb25e02565Xavier Ducrohet * @param x The x-coordinate of the center of the radius 9145a7c285985976c23d818665694addbb25e02565Xavier Ducrohet * @param y The y-coordinate of the center of the radius 9245a7c285985976c23d818665694addbb25e02565Xavier Ducrohet * @param radius Must be positive. The radius of the circle for this 9345a7c285985976c23d818665694addbb25e02565Xavier Ducrohet * gradient 9445a7c285985976c23d818665694addbb25e02565Xavier Ducrohet * @param colors The colors to be distributed between the center and edge of 9545a7c285985976c23d818665694addbb25e02565Xavier Ducrohet * the circle 9645a7c285985976c23d818665694addbb25e02565Xavier Ducrohet * @param positions May be NULL. The relative position of each corresponding 9745a7c285985976c23d818665694addbb25e02565Xavier Ducrohet * color in the colors array. If this is NULL, the the colors are 9845a7c285985976c23d818665694addbb25e02565Xavier Ducrohet * distributed evenly between the center and edge of the circle. 9945a7c285985976c23d818665694addbb25e02565Xavier Ducrohet * @param tile The Shader tiling mode 10045a7c285985976c23d818665694addbb25e02565Xavier Ducrohet */ 101251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet private RadialGradient_Delegate(float x, float y, float radius, int colors[], float positions[], 10245a7c285985976c23d818665694addbb25e02565Xavier Ducrohet TileMode tile) { 10345a7c285985976c23d818665694addbb25e02565Xavier Ducrohet super(colors, positions); 104251d2e99245095369b52d891a660b2ed270f02e0Xavier Ducrohet mJavaPaint = new RadialGradientPaint(x, y, radius, mColors, mPositions, tile); 10563b2e616278c1b4284e1adbcc3936d0516083dcbXavier Ducrohet } 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 107d9c64369cf9be6568af2d79c35fb470cc261730dXavier Ducrohet private class RadialGradientPaint extends GradientPaint { 10845a7c285985976c23d818665694addbb25e02565Xavier Ducrohet 10945a7c285985976c23d818665694addbb25e02565Xavier Ducrohet private final float mX; 11045a7c285985976c23d818665694addbb25e02565Xavier Ducrohet private final float mY; 11145a7c285985976c23d818665694addbb25e02565Xavier Ducrohet private final float mRadius; 11245a7c285985976c23d818665694addbb25e02565Xavier Ducrohet 113d9c64369cf9be6568af2d79c35fb470cc261730dXavier Ducrohet public RadialGradientPaint(float x, float y, float radius, 114d9c64369cf9be6568af2d79c35fb470cc261730dXavier Ducrohet int[] colors, float[] positions, TileMode mode) { 11545a7c285985976c23d818665694addbb25e02565Xavier Ducrohet super(colors, positions, mode); 11645a7c285985976c23d818665694addbb25e02565Xavier Ducrohet mX = x; 11745a7c285985976c23d818665694addbb25e02565Xavier Ducrohet mY = y; 11845a7c285985976c23d818665694addbb25e02565Xavier Ducrohet mRadius = radius; 11945a7c285985976c23d818665694addbb25e02565Xavier Ducrohet } 12045a7c285985976c23d818665694addbb25e02565Xavier Ducrohet 12146d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohet @Override 12245a7c285985976c23d818665694addbb25e02565Xavier Ducrohet public java.awt.PaintContext createContext( 1233330927bdd2fedcbc8745f99d3f40929f47fdd31Xavier Ducrohet java.awt.image.ColorModel colorModel, 1243330927bdd2fedcbc8745f99d3f40929f47fdd31Xavier Ducrohet java.awt.Rectangle deviceBounds, 1253330927bdd2fedcbc8745f99d3f40929f47fdd31Xavier Ducrohet java.awt.geom.Rectangle2D userBounds, 12645a7c285985976c23d818665694addbb25e02565Xavier Ducrohet java.awt.geom.AffineTransform xform, 1273330927bdd2fedcbc8745f99d3f40929f47fdd31Xavier Ducrohet java.awt.RenderingHints hints) { 12845a7c285985976c23d818665694addbb25e02565Xavier Ducrohet precomputeGradientColors(); 129d9c64369cf9be6568af2d79c35fb470cc261730dXavier Ducrohet 130d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet java.awt.geom.AffineTransform canvasMatrix; 131d9c64369cf9be6568af2d79c35fb470cc261730dXavier Ducrohet try { 132d9c64369cf9be6568af2d79c35fb470cc261730dXavier Ducrohet canvasMatrix = xform.createInverse(); 133d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet } catch (java.awt.geom.NoninvertibleTransformException e) { 134918aaa5717fce6081557c82ce1c439b6922737d5Xavier Ducrohet Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE, 13551a7e5447de94791c464cda5cc6ebbf616d73c80Xavier Ducrohet "Unable to inverse matrix in RadialGradient", e, null /*data*/); 136d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet canvasMatrix = new java.awt.geom.AffineTransform(); 137d9c64369cf9be6568af2d79c35fb470cc261730dXavier Ducrohet } 138d9c64369cf9be6568af2d79c35fb470cc261730dXavier Ducrohet 139d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet java.awt.geom.AffineTransform localMatrix = getLocalMatrix(); 140d9c64369cf9be6568af2d79c35fb470cc261730dXavier Ducrohet try { 141d9c64369cf9be6568af2d79c35fb470cc261730dXavier Ducrohet localMatrix = localMatrix.createInverse(); 142d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet } catch (java.awt.geom.NoninvertibleTransformException e) { 143918aaa5717fce6081557c82ce1c439b6922737d5Xavier Ducrohet Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE, 14451a7e5447de94791c464cda5cc6ebbf616d73c80Xavier Ducrohet "Unable to inverse matrix in RadialGradient", e, null /*data*/); 145d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet localMatrix = new java.awt.geom.AffineTransform(); 146d9c64369cf9be6568af2d79c35fb470cc261730dXavier Ducrohet } 147d9c64369cf9be6568af2d79c35fb470cc261730dXavier Ducrohet 148d9c64369cf9be6568af2d79c35fb470cc261730dXavier Ducrohet return new RadialGradientPaintContext(canvasMatrix, localMatrix, colorModel); 14945a7c285985976c23d818665694addbb25e02565Xavier Ducrohet } 15045a7c285985976c23d818665694addbb25e02565Xavier Ducrohet 15145a7c285985976c23d818665694addbb25e02565Xavier Ducrohet private class RadialGradientPaintContext implements java.awt.PaintContext { 15245a7c285985976c23d818665694addbb25e02565Xavier Ducrohet 153d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet private final java.awt.geom.AffineTransform mCanvasMatrix; 154d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet private final java.awt.geom.AffineTransform mLocalMatrix; 15545a7c285985976c23d818665694addbb25e02565Xavier Ducrohet private final java.awt.image.ColorModel mColorModel; 15645a7c285985976c23d818665694addbb25e02565Xavier Ducrohet 157d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet public RadialGradientPaintContext( 158d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet java.awt.geom.AffineTransform canvasMatrix, 159d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet java.awt.geom.AffineTransform localMatrix, 160d348b6eaa98e23cb38d90906df109aaa2d20ea7fXavier Ducrohet java.awt.image.ColorModel colorModel) { 161d9c64369cf9be6568af2d79c35fb470cc261730dXavier Ducrohet mCanvasMatrix = canvasMatrix; 162d9c64369cf9be6568af2d79c35fb470cc261730dXavier Ducrohet mLocalMatrix = localMatrix; 16345a7c285985976c23d818665694addbb25e02565Xavier Ducrohet mColorModel = colorModel; 16445a7c285985976c23d818665694addbb25e02565Xavier Ducrohet } 16545a7c285985976c23d818665694addbb25e02565Xavier Ducrohet 16646d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohet @Override 16745a7c285985976c23d818665694addbb25e02565Xavier Ducrohet public void dispose() { 16845a7c285985976c23d818665694addbb25e02565Xavier Ducrohet } 16945a7c285985976c23d818665694addbb25e02565Xavier Ducrohet 17046d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohet @Override 17145a7c285985976c23d818665694addbb25e02565Xavier Ducrohet public java.awt.image.ColorModel getColorModel() { 17245a7c285985976c23d818665694addbb25e02565Xavier Ducrohet return mColorModel; 17345a7c285985976c23d818665694addbb25e02565Xavier Ducrohet } 17445a7c285985976c23d818665694addbb25e02565Xavier Ducrohet 17546d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohet @Override 17645a7c285985976c23d818665694addbb25e02565Xavier Ducrohet public java.awt.image.Raster getRaster(int x, int y, int w, int h) { 17745a7c285985976c23d818665694addbb25e02565Xavier Ducrohet java.awt.image.BufferedImage image = new java.awt.image.BufferedImage(w, h, 17845a7c285985976c23d818665694addbb25e02565Xavier Ducrohet java.awt.image.BufferedImage.TYPE_INT_ARGB); 17945a7c285985976c23d818665694addbb25e02565Xavier Ducrohet 18045a7c285985976c23d818665694addbb25e02565Xavier Ducrohet int[] data = new int[w*h]; 18145a7c285985976c23d818665694addbb25e02565Xavier Ducrohet 18245a7c285985976c23d818665694addbb25e02565Xavier Ducrohet // compute distance from each point to the center, and figure out the distance from 18345a7c285985976c23d818665694addbb25e02565Xavier Ducrohet // it. 18445a7c285985976c23d818665694addbb25e02565Xavier Ducrohet int index = 0; 185d9c64369cf9be6568af2d79c35fb470cc261730dXavier Ducrohet float[] pt1 = new float[2]; 186d9c64369cf9be6568af2d79c35fb470cc261730dXavier Ducrohet float[] pt2 = new float[2]; 18745a7c285985976c23d818665694addbb25e02565Xavier Ducrohet for (int iy = 0 ; iy < h ; iy++) { 18845a7c285985976c23d818665694addbb25e02565Xavier Ducrohet for (int ix = 0 ; ix < w ; ix++) { 189d9c64369cf9be6568af2d79c35fb470cc261730dXavier Ducrohet // handle the canvas transform 190d9c64369cf9be6568af2d79c35fb470cc261730dXavier Ducrohet pt1[0] = x + ix; 191d9c64369cf9be6568af2d79c35fb470cc261730dXavier Ducrohet pt1[1] = y + iy; 192d9c64369cf9be6568af2d79c35fb470cc261730dXavier Ducrohet mCanvasMatrix.transform(pt1, 0, pt2, 0, 1); 193d9c64369cf9be6568af2d79c35fb470cc261730dXavier Ducrohet 194d9c64369cf9be6568af2d79c35fb470cc261730dXavier Ducrohet // handle the local matrix 195d9c64369cf9be6568af2d79c35fb470cc261730dXavier Ducrohet pt1[0] = pt2[0] - mX; 196d9c64369cf9be6568af2d79c35fb470cc261730dXavier Ducrohet pt1[1] = pt2[1] - mY; 197d9c64369cf9be6568af2d79c35fb470cc261730dXavier Ducrohet mLocalMatrix.transform(pt1, 0, pt2, 0, 1); 198d9c64369cf9be6568af2d79c35fb470cc261730dXavier Ducrohet 199d9c64369cf9be6568af2d79c35fb470cc261730dXavier Ducrohet float _x = pt2[0]; 200d9c64369cf9be6568af2d79c35fb470cc261730dXavier Ducrohet float _y = pt2[1]; 20145a7c285985976c23d818665694addbb25e02565Xavier Ducrohet float distance = (float) Math.sqrt(_x * _x + _y * _y); 20245a7c285985976c23d818665694addbb25e02565Xavier Ducrohet 20345a7c285985976c23d818665694addbb25e02565Xavier Ducrohet data[index++] = getGradientColor(distance / mRadius); 20445a7c285985976c23d818665694addbb25e02565Xavier Ducrohet } 20545a7c285985976c23d818665694addbb25e02565Xavier Ducrohet } 20645a7c285985976c23d818665694addbb25e02565Xavier Ducrohet 20745a7c285985976c23d818665694addbb25e02565Xavier Ducrohet image.setRGB(0 /*startX*/, 0 /*startY*/, w, h, data, 0 /*offset*/, w /*scansize*/); 20845a7c285985976c23d818665694addbb25e02565Xavier Ducrohet 20945a7c285985976c23d818665694addbb25e02565Xavier Ducrohet return image.getRaster(); 21045a7c285985976c23d818665694addbb25e02565Xavier Ducrohet } 21145a7c285985976c23d818665694addbb25e02565Xavier Ducrohet 21245a7c285985976c23d818665694addbb25e02565Xavier Ducrohet } 21345a7c285985976c23d818665694addbb25e02565Xavier Ducrohet } 21445a7c285985976c23d818665694addbb25e02565Xavier Ducrohet 21545a7c285985976c23d818665694addbb25e02565Xavier Ducrohet} 216