1 /* 2 * Copyright (C) 2009 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 17 package android.graphics.utils; 18 19 import android.graphics.Bitmap; 20 import android.graphics.BitmapShader; 21 import android.graphics.Canvas; 22 import android.graphics.Paint; 23 import android.graphics.Shader; 24 import android.graphics.Xfermode; 25 26 /** 27 * @hide 28 */ 29 public class BoundaryPatch { 30 private Paint mPaint; 31 private Bitmap mTexture; 32 private int mRows; 33 private int mCols; 34 private float[] mCubicPoints; 35 private boolean mDirty; 36 // these are the computed output of the native code 37 private float[] mVerts; 38 private short[] mIndices; 39 BoundaryPatch()40 public BoundaryPatch() { 41 mRows = mCols = 2; // default minimum 42 mCubicPoints = new float[24]; 43 mPaint = new Paint(); 44 mPaint.setDither(true); 45 mPaint.setFilterBitmap(true); 46 mDirty = true; 47 } 48 49 /** 50 * Set the boundary to be 4 cubics. This takes a single array of floats, 51 * and picks up the 12 pairs starting at offset, and treats them as 52 * the x,y coordinates of the cubic control points. The points wrap around 53 * a patch, as follows. For documentation purposes, pts[i] will mean the 54 * x,y pair of floats, as if pts[] were an array of "points". 55 * 56 * Top: pts[0..3] 57 * Right: pts[3..6] 58 * Bottom: pts[6..9] 59 * Right: pts[9..11], pts[0] 60 * 61 * The coordinates are copied from the input array, so subsequent changes 62 * to pts[] will not be reflected in the boundary. 63 * 64 * @param pts The src array of x,y pairs for the boundary cubics 65 * @param offset The index into pts of the first pair 66 * @param rows The number of points across to approximate the boundary. 67 * Must be >= 2, though very large values may slow down drawing 68 * @param cols The number of points down to approximate the boundary. 69 * Must be >= 2, though very large values may slow down drawing 70 */ setCubicBoundary(float[] pts, int offset, int rows, int cols)71 public void setCubicBoundary(float[] pts, int offset, int rows, int cols) { 72 if (rows < 2 || cols < 2) { 73 throw new RuntimeException("rows and cols must be >= 2"); 74 } 75 System.arraycopy(pts, offset, mCubicPoints, 0, 24); 76 if (mRows != rows || mCols != cols) { 77 mRows = rows; 78 mCols = cols; 79 } 80 mDirty = true; 81 } 82 83 /** 84 * Reference a bitmap texture to be mapped onto the patch. 85 */ setTexture(Bitmap texture)86 public void setTexture(Bitmap texture) { 87 if (mTexture != texture) { 88 if (mTexture == null || 89 mTexture.getWidth() != texture.getWidth() || 90 mTexture.getHeight() != texture.getHeight()) { 91 // need to recompute texture coordinates 92 mDirty = true; 93 } 94 mTexture = texture; 95 mPaint.setShader(new BitmapShader(texture, 96 Shader.TileMode.CLAMP, 97 Shader.TileMode.CLAMP)); 98 } 99 } 100 101 /** 102 * Return the paint flags for the patch 103 */ getPaintFlags()104 public int getPaintFlags() { 105 return mPaint.getFlags(); 106 } 107 108 /** 109 * Set the paint flags for the patch 110 */ setPaintFlags(int flags)111 public void setPaintFlags(int flags) { 112 mPaint.setFlags(flags); 113 } 114 115 /** 116 * Set the xfermode for the patch 117 */ setXfermode(Xfermode mode)118 public void setXfermode(Xfermode mode) { 119 mPaint.setXfermode(mode); 120 } 121 122 /** 123 * Set the alpha for the patch 124 */ setAlpha(int alpha)125 public void setAlpha(int alpha) { 126 mPaint.setAlpha(alpha); 127 } 128 129 /** 130 * Draw the patch onto the canvas. 131 * 132 * setCubicBoundary() and setTexture() must be called before drawing. 133 */ draw(Canvas canvas)134 public void draw(Canvas canvas) { 135 if (mDirty) { 136 buildCache(); 137 mDirty = false; 138 } 139 140 // cut the count in half, since mVerts.length is really the length of 141 // the verts[] and tex[] arrays combined 142 // (tex[] are stored after verts[]) 143 int vertCount = mVerts.length >> 1; 144 canvas.drawVertices(Canvas.VertexMode.TRIANGLES, vertCount, 145 mVerts, 0, mVerts, vertCount, null, 0, 146 mIndices, 0, mIndices.length, 147 mPaint); 148 } 149 buildCache()150 private void buildCache() { 151 // we need mRows * mCols points, for verts and another set for textures 152 // so *2 for going from points -> floats, and *2 for verts and textures 153 int vertCount = mRows * mCols * 4; 154 if (mVerts == null || mVerts.length != vertCount) { 155 mVerts = new float[vertCount]; 156 } 157 158 int indexCount = (mRows - 1) * (mCols - 1) * 6; 159 if (mIndices == null || mIndices.length != indexCount) { 160 mIndices = new short[indexCount]; 161 } 162 163 nativeComputeCubicPatch(mCubicPoints, 164 mTexture.getWidth(), mTexture.getHeight(), 165 mRows, mCols, mVerts, mIndices); 166 } 167 168 private static native nativeComputeCubicPatch(float[] cubicPoints, int texW, int texH, int rows, int cols, float[] verts, short[] indices)169 void nativeComputeCubicPatch(float[] cubicPoints, 170 int texW, int texH, int rows, int cols, 171 float[] verts, short[] indices); 172 } 173 174