TiledImageView.java revision d8732610ff48dc57063559d55ea3c84775e30e41
1d8732610ff48dc57063559d55ea3c84775e30e41John Reck/* 2d8732610ff48dc57063559d55ea3c84775e30e41John Reck * Copyright (C) 2013 The Android Open Source Project 3d8732610ff48dc57063559d55ea3c84775e30e41John Reck * 4d8732610ff48dc57063559d55ea3c84775e30e41John Reck * Licensed under the Apache License, Version 2.0 (the "License"); 5d8732610ff48dc57063559d55ea3c84775e30e41John Reck * you may not use this file except in compliance with the License. 6d8732610ff48dc57063559d55ea3c84775e30e41John Reck * You may obtain a copy of the License at 7d8732610ff48dc57063559d55ea3c84775e30e41John Reck * 8d8732610ff48dc57063559d55ea3c84775e30e41John Reck * http://www.apache.org/licenses/LICENSE-2.0 9d8732610ff48dc57063559d55ea3c84775e30e41John Reck * 10d8732610ff48dc57063559d55ea3c84775e30e41John Reck * Unless required by applicable law or agreed to in writing, software 11d8732610ff48dc57063559d55ea3c84775e30e41John Reck * distributed under the License is distributed on an "AS IS" BASIS, 12d8732610ff48dc57063559d55ea3c84775e30e41John Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d8732610ff48dc57063559d55ea3c84775e30e41John Reck * See the License for the specific language governing permissions and 14d8732610ff48dc57063559d55ea3c84775e30e41John Reck * limitations under the License. 15d8732610ff48dc57063559d55ea3c84775e30e41John Reck */ 16d8732610ff48dc57063559d55ea3c84775e30e41John Reck 17d8732610ff48dc57063559d55ea3c84775e30e41John Reckpackage com.android.photos.views; 18d8732610ff48dc57063559d55ea3c84775e30e41John Reck 19d8732610ff48dc57063559d55ea3c84775e30e41John Reckimport android.content.Context; 20d8732610ff48dc57063559d55ea3c84775e30e41John Reckimport android.graphics.Bitmap; 21d8732610ff48dc57063559d55ea3c84775e30e41John Reckimport android.graphics.Canvas; 22d8732610ff48dc57063559d55ea3c84775e30e41John Reckimport android.graphics.Color; 23d8732610ff48dc57063559d55ea3c84775e30e41John Reckimport android.graphics.Paint; 24d8732610ff48dc57063559d55ea3c84775e30e41John Reckimport android.graphics.Paint.Align; 25d8732610ff48dc57063559d55ea3c84775e30e41John Reckimport android.opengl.GLSurfaceView.Renderer; 26d8732610ff48dc57063559d55ea3c84775e30e41John Reckimport android.util.AttributeSet; 27d8732610ff48dc57063559d55ea3c84775e30e41John Reckimport android.view.MotionEvent; 28d8732610ff48dc57063559d55ea3c84775e30e41John Reckimport android.view.ScaleGestureDetector; 29d8732610ff48dc57063559d55ea3c84775e30e41John Reckimport android.view.ScaleGestureDetector.OnScaleGestureListener; 30d8732610ff48dc57063559d55ea3c84775e30e41John Reckimport android.widget.FrameLayout; 31d8732610ff48dc57063559d55ea3c84775e30e41John Reckimport com.android.gallery3d.glrenderer.GLES20Canvas; 32d8732610ff48dc57063559d55ea3c84775e30e41John Reckimport com.android.photos.views.TiledImageRenderer.TileSource; 33d8732610ff48dc57063559d55ea3c84775e30e41John Reck 34d8732610ff48dc57063559d55ea3c84775e30e41John Reckimport javax.microedition.khronos.egl.EGLConfig; 35d8732610ff48dc57063559d55ea3c84775e30e41John Reckimport javax.microedition.khronos.opengles.GL10; 36d8732610ff48dc57063559d55ea3c84775e30e41John Reck 37d8732610ff48dc57063559d55ea3c84775e30e41John Reck 38d8732610ff48dc57063559d55ea3c84775e30e41John Reckpublic class TiledImageView extends FrameLayout implements OnScaleGestureListener { 39d8732610ff48dc57063559d55ea3c84775e30e41John Reck 40d8732610ff48dc57063559d55ea3c84775e30e41John Reck private BlockingGLTextureView mTextureView; 41d8732610ff48dc57063559d55ea3c84775e30e41John Reck private float mLastX, mLastY; 42d8732610ff48dc57063559d55ea3c84775e30e41John Reck 43d8732610ff48dc57063559d55ea3c84775e30e41John Reck private static class ImageRendererWrapper { 44d8732610ff48dc57063559d55ea3c84775e30e41John Reck // Guarded by locks 45d8732610ff48dc57063559d55ea3c84775e30e41John Reck float scale; 46d8732610ff48dc57063559d55ea3c84775e30e41John Reck int centerX, centerY; 47d8732610ff48dc57063559d55ea3c84775e30e41John Reck int rotation; 48d8732610ff48dc57063559d55ea3c84775e30e41John Reck TileSource source; 49d8732610ff48dc57063559d55ea3c84775e30e41John Reck 50d8732610ff48dc57063559d55ea3c84775e30e41John Reck // GL thread only 51d8732610ff48dc57063559d55ea3c84775e30e41John Reck TiledImageRenderer image; 52d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 53d8732610ff48dc57063559d55ea3c84775e30e41John Reck 54d8732610ff48dc57063559d55ea3c84775e30e41John Reck // TODO: left/right paging 55d8732610ff48dc57063559d55ea3c84775e30e41John Reck private ImageRendererWrapper mRenderers[] = new ImageRendererWrapper[1]; 56d8732610ff48dc57063559d55ea3c84775e30e41John Reck private ImageRendererWrapper mFocusedRenderer; 57d8732610ff48dc57063559d55ea3c84775e30e41John Reck 58d8732610ff48dc57063559d55ea3c84775e30e41John Reck // ------------------------- 59d8732610ff48dc57063559d55ea3c84775e30e41John Reck // Guarded by mLock 60d8732610ff48dc57063559d55ea3c84775e30e41John Reck // ------------------------- 61d8732610ff48dc57063559d55ea3c84775e30e41John Reck private Object mLock = new Object(); 62d8732610ff48dc57063559d55ea3c84775e30e41John Reck private ScaleGestureDetector mScaleGestureDetector; 63d8732610ff48dc57063559d55ea3c84775e30e41John Reck 64d8732610ff48dc57063559d55ea3c84775e30e41John Reck public TiledImageView(Context context) { 65d8732610ff48dc57063559d55ea3c84775e30e41John Reck this(context, null); 66d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 67d8732610ff48dc57063559d55ea3c84775e30e41John Reck 68d8732610ff48dc57063559d55ea3c84775e30e41John Reck public TiledImageView(Context context, AttributeSet attrs) { 69d8732610ff48dc57063559d55ea3c84775e30e41John Reck super(context, attrs); 70d8732610ff48dc57063559d55ea3c84775e30e41John Reck mTextureView = new BlockingGLTextureView(context); 71d8732610ff48dc57063559d55ea3c84775e30e41John Reck addView(mTextureView, new LayoutParams( 72d8732610ff48dc57063559d55ea3c84775e30e41John Reck LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); 73d8732610ff48dc57063559d55ea3c84775e30e41John Reck mTextureView.setRenderer(new TileRenderer()); 74d8732610ff48dc57063559d55ea3c84775e30e41John Reck setTileSource(new ColoredTiles()); 75d8732610ff48dc57063559d55ea3c84775e30e41John Reck mScaleGestureDetector = new ScaleGestureDetector(context, this); 76d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 77d8732610ff48dc57063559d55ea3c84775e30e41John Reck 78d8732610ff48dc57063559d55ea3c84775e30e41John Reck public void destroy() { 79d8732610ff48dc57063559d55ea3c84775e30e41John Reck mTextureView.destroy(); 80d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 81d8732610ff48dc57063559d55ea3c84775e30e41John Reck 82d8732610ff48dc57063559d55ea3c84775e30e41John Reck public void setTileSource(TileSource source) { 83d8732610ff48dc57063559d55ea3c84775e30e41John Reck synchronized (mLock) { 84d8732610ff48dc57063559d55ea3c84775e30e41John Reck for (int i = 0; i < mRenderers.length; i++) { 85d8732610ff48dc57063559d55ea3c84775e30e41John Reck ImageRendererWrapper renderer = mRenderers[i]; 86d8732610ff48dc57063559d55ea3c84775e30e41John Reck if (renderer == null) { 87d8732610ff48dc57063559d55ea3c84775e30e41John Reck renderer = mRenderers[i] = new ImageRendererWrapper(); 88d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 89d8732610ff48dc57063559d55ea3c84775e30e41John Reck renderer.source = source; 90d8732610ff48dc57063559d55ea3c84775e30e41John Reck renderer.centerX = renderer.source.getImageWidth() / 2; 91d8732610ff48dc57063559d55ea3c84775e30e41John Reck renderer.centerY = renderer.source.getImageHeight() / 2; 92d8732610ff48dc57063559d55ea3c84775e30e41John Reck renderer.rotation = 0; 93d8732610ff48dc57063559d55ea3c84775e30e41John Reck renderer.scale = 0; 94d8732610ff48dc57063559d55ea3c84775e30e41John Reck renderer.image = new TiledImageRenderer(this); 95d8732610ff48dc57063559d55ea3c84775e30e41John Reck updateScaleIfNecessaryLocked(renderer); 96d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 97d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 98d8732610ff48dc57063559d55ea3c84775e30e41John Reck mFocusedRenderer = mRenderers[0]; 99d8732610ff48dc57063559d55ea3c84775e30e41John Reck invalidate(); 100d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 101d8732610ff48dc57063559d55ea3c84775e30e41John Reck 102d8732610ff48dc57063559d55ea3c84775e30e41John Reck @Override 103d8732610ff48dc57063559d55ea3c84775e30e41John Reck public boolean onScaleBegin(ScaleGestureDetector detector) { 104d8732610ff48dc57063559d55ea3c84775e30e41John Reck return true; 105d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 106d8732610ff48dc57063559d55ea3c84775e30e41John Reck 107d8732610ff48dc57063559d55ea3c84775e30e41John Reck @Override 108d8732610ff48dc57063559d55ea3c84775e30e41John Reck public boolean onScale(ScaleGestureDetector detector) { 109d8732610ff48dc57063559d55ea3c84775e30e41John Reck // Don't need the lock because this will only fire inside of onTouchEvent 110d8732610ff48dc57063559d55ea3c84775e30e41John Reck mFocusedRenderer.scale *= detector.getScaleFactor(); 111d8732610ff48dc57063559d55ea3c84775e30e41John Reck invalidate(); 112d8732610ff48dc57063559d55ea3c84775e30e41John Reck return true; 113d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 114d8732610ff48dc57063559d55ea3c84775e30e41John Reck 115d8732610ff48dc57063559d55ea3c84775e30e41John Reck @Override 116d8732610ff48dc57063559d55ea3c84775e30e41John Reck public void onScaleEnd(ScaleGestureDetector detector) { 117d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 118d8732610ff48dc57063559d55ea3c84775e30e41John Reck 119d8732610ff48dc57063559d55ea3c84775e30e41John Reck @Override 120d8732610ff48dc57063559d55ea3c84775e30e41John Reck public boolean onTouchEvent(MotionEvent event) { 121d8732610ff48dc57063559d55ea3c84775e30e41John Reck int action = event.getActionMasked(); 122d8732610ff48dc57063559d55ea3c84775e30e41John Reck final boolean pointerUp = action == MotionEvent.ACTION_POINTER_UP; 123d8732610ff48dc57063559d55ea3c84775e30e41John Reck final int skipIndex = pointerUp ? event.getActionIndex() : -1; 124d8732610ff48dc57063559d55ea3c84775e30e41John Reck 125d8732610ff48dc57063559d55ea3c84775e30e41John Reck // Determine focal point 126d8732610ff48dc57063559d55ea3c84775e30e41John Reck float sumX = 0, sumY = 0; 127d8732610ff48dc57063559d55ea3c84775e30e41John Reck final int count = event.getPointerCount(); 128d8732610ff48dc57063559d55ea3c84775e30e41John Reck for (int i = 0; i < count; i++) { 129d8732610ff48dc57063559d55ea3c84775e30e41John Reck if (skipIndex == i) continue; 130d8732610ff48dc57063559d55ea3c84775e30e41John Reck sumX += event.getX(i); 131d8732610ff48dc57063559d55ea3c84775e30e41John Reck sumY += event.getY(i); 132d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 133d8732610ff48dc57063559d55ea3c84775e30e41John Reck final int div = pointerUp ? count - 1 : count; 134d8732610ff48dc57063559d55ea3c84775e30e41John Reck float x = sumX / div; 135d8732610ff48dc57063559d55ea3c84775e30e41John Reck float y = sumY / div; 136d8732610ff48dc57063559d55ea3c84775e30e41John Reck 137d8732610ff48dc57063559d55ea3c84775e30e41John Reck synchronized (mLock) { 138d8732610ff48dc57063559d55ea3c84775e30e41John Reck mScaleGestureDetector.onTouchEvent(event); 139d8732610ff48dc57063559d55ea3c84775e30e41John Reck switch (action) { 140d8732610ff48dc57063559d55ea3c84775e30e41John Reck case MotionEvent.ACTION_MOVE: 141d8732610ff48dc57063559d55ea3c84775e30e41John Reck mFocusedRenderer.centerX += (mLastX - x) / mFocusedRenderer.scale; 142d8732610ff48dc57063559d55ea3c84775e30e41John Reck mFocusedRenderer.centerY += (mLastY - y) / mFocusedRenderer.scale; 143d8732610ff48dc57063559d55ea3c84775e30e41John Reck invalidate(); 144d8732610ff48dc57063559d55ea3c84775e30e41John Reck break; 145d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 146d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 147d8732610ff48dc57063559d55ea3c84775e30e41John Reck 148d8732610ff48dc57063559d55ea3c84775e30e41John Reck mLastX = x; 149d8732610ff48dc57063559d55ea3c84775e30e41John Reck mLastY = y; 150d8732610ff48dc57063559d55ea3c84775e30e41John Reck return true; 151d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 152d8732610ff48dc57063559d55ea3c84775e30e41John Reck 153d8732610ff48dc57063559d55ea3c84775e30e41John Reck @Override 154d8732610ff48dc57063559d55ea3c84775e30e41John Reck protected void onLayout(boolean changed, int left, int top, int right, 155d8732610ff48dc57063559d55ea3c84775e30e41John Reck int bottom) { 156d8732610ff48dc57063559d55ea3c84775e30e41John Reck super.onLayout(changed, left, top, right, bottom); 157d8732610ff48dc57063559d55ea3c84775e30e41John Reck synchronized (mLock) { 158d8732610ff48dc57063559d55ea3c84775e30e41John Reck for (ImageRendererWrapper renderer : mRenderers) { 159d8732610ff48dc57063559d55ea3c84775e30e41John Reck updateScaleIfNecessaryLocked(renderer); 160d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 161d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 162d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 163d8732610ff48dc57063559d55ea3c84775e30e41John Reck 164d8732610ff48dc57063559d55ea3c84775e30e41John Reck private void updateScaleIfNecessaryLocked(ImageRendererWrapper renderer) { 165d8732610ff48dc57063559d55ea3c84775e30e41John Reck if (renderer.scale > 0 || getWidth() == 0) return; 166d8732610ff48dc57063559d55ea3c84775e30e41John Reck renderer.scale = Math.min( 167d8732610ff48dc57063559d55ea3c84775e30e41John Reck (float) getWidth() / (float) renderer.source.getImageWidth(), 168d8732610ff48dc57063559d55ea3c84775e30e41John Reck (float) getHeight() / (float) renderer.source.getImageHeight()); 169d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 170d8732610ff48dc57063559d55ea3c84775e30e41John Reck 171d8732610ff48dc57063559d55ea3c84775e30e41John Reck @Override 172d8732610ff48dc57063559d55ea3c84775e30e41John Reck protected void dispatchDraw(Canvas canvas) { 173d8732610ff48dc57063559d55ea3c84775e30e41John Reck mTextureView.render(); 174d8732610ff48dc57063559d55ea3c84775e30e41John Reck super.dispatchDraw(canvas); 175d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 176d8732610ff48dc57063559d55ea3c84775e30e41John Reck 177d8732610ff48dc57063559d55ea3c84775e30e41John Reck @Override 178d8732610ff48dc57063559d55ea3c84775e30e41John Reck public void invalidate() { 179d8732610ff48dc57063559d55ea3c84775e30e41John Reck super.invalidate(); 180d8732610ff48dc57063559d55ea3c84775e30e41John Reck mTextureView.invalidate(); 181d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 182d8732610ff48dc57063559d55ea3c84775e30e41John Reck 183d8732610ff48dc57063559d55ea3c84775e30e41John Reck private class TileRenderer implements Renderer { 184d8732610ff48dc57063559d55ea3c84775e30e41John Reck 185d8732610ff48dc57063559d55ea3c84775e30e41John Reck private GLES20Canvas mCanvas; 186d8732610ff48dc57063559d55ea3c84775e30e41John Reck 187d8732610ff48dc57063559d55ea3c84775e30e41John Reck @Override 188d8732610ff48dc57063559d55ea3c84775e30e41John Reck public void onSurfaceCreated(GL10 gl, EGLConfig config) { 189d8732610ff48dc57063559d55ea3c84775e30e41John Reck mCanvas = new GLES20Canvas(); 190d8732610ff48dc57063559d55ea3c84775e30e41John Reck for (ImageRendererWrapper renderer : mRenderers) { 191d8732610ff48dc57063559d55ea3c84775e30e41John Reck renderer.image.setModel(renderer.source, renderer.rotation); 192d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 193d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 194d8732610ff48dc57063559d55ea3c84775e30e41John Reck 195d8732610ff48dc57063559d55ea3c84775e30e41John Reck @Override 196d8732610ff48dc57063559d55ea3c84775e30e41John Reck public void onSurfaceChanged(GL10 gl, int width, int height) { 197d8732610ff48dc57063559d55ea3c84775e30e41John Reck mCanvas.setSize(width, height); 198d8732610ff48dc57063559d55ea3c84775e30e41John Reck for (ImageRendererWrapper renderer : mRenderers) { 199d8732610ff48dc57063559d55ea3c84775e30e41John Reck renderer.image.setViewSize(width, height); 200d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 201d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 202d8732610ff48dc57063559d55ea3c84775e30e41John Reck 203d8732610ff48dc57063559d55ea3c84775e30e41John Reck @Override 204d8732610ff48dc57063559d55ea3c84775e30e41John Reck public void onDrawFrame(GL10 gl) { 205d8732610ff48dc57063559d55ea3c84775e30e41John Reck mCanvas.clearBuffer(); 206d8732610ff48dc57063559d55ea3c84775e30e41John Reck synchronized (mLock) { 207d8732610ff48dc57063559d55ea3c84775e30e41John Reck for (ImageRendererWrapper renderer : mRenderers) { 208d8732610ff48dc57063559d55ea3c84775e30e41John Reck renderer.image.setModel(renderer.source, renderer.rotation); 209d8732610ff48dc57063559d55ea3c84775e30e41John Reck renderer.image.setPosition(renderer.centerX, renderer.centerY, renderer.scale); 210d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 211d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 212d8732610ff48dc57063559d55ea3c84775e30e41John Reck for (ImageRendererWrapper renderer : mRenderers) { 213d8732610ff48dc57063559d55ea3c84775e30e41John Reck renderer.image.draw(mCanvas); 214d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 215d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 216d8732610ff48dc57063559d55ea3c84775e30e41John Reck 217d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 218d8732610ff48dc57063559d55ea3c84775e30e41John Reck 219d8732610ff48dc57063559d55ea3c84775e30e41John Reck private static class ColoredTiles implements TileSource { 220d8732610ff48dc57063559d55ea3c84775e30e41John Reck private static int[] COLORS = new int[] { 221d8732610ff48dc57063559d55ea3c84775e30e41John Reck Color.RED, 222d8732610ff48dc57063559d55ea3c84775e30e41John Reck Color.BLUE, 223d8732610ff48dc57063559d55ea3c84775e30e41John Reck Color.YELLOW, 224d8732610ff48dc57063559d55ea3c84775e30e41John Reck Color.GREEN, 225d8732610ff48dc57063559d55ea3c84775e30e41John Reck Color.CYAN, 226d8732610ff48dc57063559d55ea3c84775e30e41John Reck Color.MAGENTA, 227d8732610ff48dc57063559d55ea3c84775e30e41John Reck Color.WHITE, 228d8732610ff48dc57063559d55ea3c84775e30e41John Reck }; 229d8732610ff48dc57063559d55ea3c84775e30e41John Reck 230d8732610ff48dc57063559d55ea3c84775e30e41John Reck private Paint mPaint = new Paint(); 231d8732610ff48dc57063559d55ea3c84775e30e41John Reck private Canvas mCanvas = new Canvas(); 232d8732610ff48dc57063559d55ea3c84775e30e41John Reck 233d8732610ff48dc57063559d55ea3c84775e30e41John Reck @Override 234d8732610ff48dc57063559d55ea3c84775e30e41John Reck public int getTileSize() { 235d8732610ff48dc57063559d55ea3c84775e30e41John Reck return 256; 236d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 237d8732610ff48dc57063559d55ea3c84775e30e41John Reck 238d8732610ff48dc57063559d55ea3c84775e30e41John Reck @Override 239d8732610ff48dc57063559d55ea3c84775e30e41John Reck public int getImageWidth() { 240d8732610ff48dc57063559d55ea3c84775e30e41John Reck return 16384; 241d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 242d8732610ff48dc57063559d55ea3c84775e30e41John Reck 243d8732610ff48dc57063559d55ea3c84775e30e41John Reck @Override 244d8732610ff48dc57063559d55ea3c84775e30e41John Reck public int getImageHeight() { 245d8732610ff48dc57063559d55ea3c84775e30e41John Reck return 8192; 246d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 247d8732610ff48dc57063559d55ea3c84775e30e41John Reck 248d8732610ff48dc57063559d55ea3c84775e30e41John Reck @Override 249d8732610ff48dc57063559d55ea3c84775e30e41John Reck public Bitmap getTile(int level, int x, int y, Bitmap bitmap) { 250d8732610ff48dc57063559d55ea3c84775e30e41John Reck int tileSize = getTileSize(); 251d8732610ff48dc57063559d55ea3c84775e30e41John Reck if (bitmap == null) { 252d8732610ff48dc57063559d55ea3c84775e30e41John Reck bitmap = Bitmap.createBitmap(tileSize, tileSize, 253d8732610ff48dc57063559d55ea3c84775e30e41John Reck Bitmap.Config.ARGB_8888); 254d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 255d8732610ff48dc57063559d55ea3c84775e30e41John Reck mCanvas.setBitmap(bitmap); 256d8732610ff48dc57063559d55ea3c84775e30e41John Reck mCanvas.drawColor(COLORS[level]); 257d8732610ff48dc57063559d55ea3c84775e30e41John Reck mPaint.setColor(Color.BLACK); 258d8732610ff48dc57063559d55ea3c84775e30e41John Reck mPaint.setTextSize(20); 259d8732610ff48dc57063559d55ea3c84775e30e41John Reck mPaint.setTextAlign(Align.CENTER); 260d8732610ff48dc57063559d55ea3c84775e30e41John Reck mCanvas.drawText(x + "x" + y, 128, 128, mPaint); 261d8732610ff48dc57063559d55ea3c84775e30e41John Reck tileSize <<= level; 262d8732610ff48dc57063559d55ea3c84775e30e41John Reck x /= tileSize; 263d8732610ff48dc57063559d55ea3c84775e30e41John Reck y /= tileSize; 264d8732610ff48dc57063559d55ea3c84775e30e41John Reck mCanvas.drawText(x + "x" + y + " @ " + level, 128, 30, mPaint); 265d8732610ff48dc57063559d55ea3c84775e30e41John Reck mCanvas.setBitmap(null); 266d8732610ff48dc57063559d55ea3c84775e30e41John Reck return bitmap; 267d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 268d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 269d8732610ff48dc57063559d55ea3c84775e30e41John Reck} 270