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 19f5ef4801465a48ce3e33e1a75568060b2cf61185John Reckimport android.annotation.SuppressLint; 20f5ef4801465a48ce3e33e1a75568060b2cf61185John Reckimport android.annotation.TargetApi; 21d8732610ff48dc57063559d55ea3c84775e30e41John Reckimport android.content.Context; 22d8732610ff48dc57063559d55ea3c84775e30e41John Reckimport android.graphics.Bitmap; 23d8732610ff48dc57063559d55ea3c84775e30e41John Reckimport android.graphics.Canvas; 24d8732610ff48dc57063559d55ea3c84775e30e41John Reckimport android.graphics.Color; 25f5ef4801465a48ce3e33e1a75568060b2cf61185John Reckimport android.graphics.Matrix; 26d8732610ff48dc57063559d55ea3c84775e30e41John Reckimport android.graphics.Paint; 27d8732610ff48dc57063559d55ea3c84775e30e41John Reckimport android.graphics.Paint.Align; 28f5ef4801465a48ce3e33e1a75568060b2cf61185John Reckimport android.graphics.RectF; 29f5ef4801465a48ce3e33e1a75568060b2cf61185John Reckimport android.opengl.GLSurfaceView; 30d8732610ff48dc57063559d55ea3c84775e30e41John Reckimport android.opengl.GLSurfaceView.Renderer; 31f5ef4801465a48ce3e33e1a75568060b2cf61185John Reckimport android.os.Build; 32d8732610ff48dc57063559d55ea3c84775e30e41John Reckimport android.util.AttributeSet; 33f5ef4801465a48ce3e33e1a75568060b2cf61185John Reckimport android.view.Choreographer; 34f5ef4801465a48ce3e33e1a75568060b2cf61185John Reckimport android.view.Choreographer.FrameCallback; 35f5ef4801465a48ce3e33e1a75568060b2cf61185John Reckimport android.view.View; 36d8732610ff48dc57063559d55ea3c84775e30e41John Reckimport android.widget.FrameLayout; 37f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck 38f5ef4801465a48ce3e33e1a75568060b2cf61185John Reckimport com.android.gallery3d.glrenderer.BasicTexture; 39d8732610ff48dc57063559d55ea3c84775e30e41John Reckimport com.android.gallery3d.glrenderer.GLES20Canvas; 40d8732610ff48dc57063559d55ea3c84775e30e41John Reckimport com.android.photos.views.TiledImageRenderer.TileSource; 41d8732610ff48dc57063559d55ea3c84775e30e41John Reck 42d8732610ff48dc57063559d55ea3c84775e30e41John Reckimport javax.microedition.khronos.egl.EGLConfig; 43d8732610ff48dc57063559d55ea3c84775e30e41John Reckimport javax.microedition.khronos.opengles.GL10; 44d8732610ff48dc57063559d55ea3c84775e30e41John Reck 45f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck/** 46f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck * Shows an image using {@link TiledImageRenderer} using either {@link GLSurfaceView} 47f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck * or {@link BlockingGLTextureView}. 48f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck */ 49f5ef4801465a48ce3e33e1a75568060b2cf61185John Reckpublic class TiledImageView extends FrameLayout { 50d8732610ff48dc57063559d55ea3c84775e30e41John Reck 51f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck private static final boolean USE_TEXTURE_VIEW = false; 52f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck private static final boolean IS_SUPPORTED = 53f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN; 54f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck private static final boolean USE_CHOREOGRAPHER = 55f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN; 56d8732610ff48dc57063559d55ea3c84775e30e41John Reck 57d8732610ff48dc57063559d55ea3c84775e30e41John Reck private BlockingGLTextureView mTextureView; 58f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck private GLSurfaceView mGLSurfaceView; 59f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck private boolean mInvalPending = false; 60f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck private FrameCallback mFrameCallback; 61d8732610ff48dc57063559d55ea3c84775e30e41John Reck 62d8732610ff48dc57063559d55ea3c84775e30e41John Reck private static class ImageRendererWrapper { 63d8732610ff48dc57063559d55ea3c84775e30e41John Reck // Guarded by locks 64d8732610ff48dc57063559d55ea3c84775e30e41John Reck float scale; 65d8732610ff48dc57063559d55ea3c84775e30e41John Reck int centerX, centerY; 66d8732610ff48dc57063559d55ea3c84775e30e41John Reck int rotation; 67d8732610ff48dc57063559d55ea3c84775e30e41John Reck TileSource source; 68f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck Runnable isReadyCallback; 69d8732610ff48dc57063559d55ea3c84775e30e41John Reck 70d8732610ff48dc57063559d55ea3c84775e30e41John Reck // GL thread only 71d8732610ff48dc57063559d55ea3c84775e30e41John Reck TiledImageRenderer image; 72d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 73d8732610ff48dc57063559d55ea3c84775e30e41John Reck 74f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck private float[] mValues = new float[9]; 75d8732610ff48dc57063559d55ea3c84775e30e41John Reck 76d8732610ff48dc57063559d55ea3c84775e30e41John Reck // ------------------------- 77d8732610ff48dc57063559d55ea3c84775e30e41John Reck // Guarded by mLock 78d8732610ff48dc57063559d55ea3c84775e30e41John Reck // ------------------------- 79d8732610ff48dc57063559d55ea3c84775e30e41John Reck private Object mLock = new Object(); 80f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck private ImageRendererWrapper mRenderer; 81d8732610ff48dc57063559d55ea3c84775e30e41John Reck 82c31aee6a67b08716b916906b2db2096e1b929b4aJohn Reck public static boolean isTilingSupported() { 83c31aee6a67b08716b916906b2db2096e1b929b4aJohn Reck return IS_SUPPORTED; 84c31aee6a67b08716b916906b2db2096e1b929b4aJohn Reck } 85c31aee6a67b08716b916906b2db2096e1b929b4aJohn Reck 86d8732610ff48dc57063559d55ea3c84775e30e41John Reck public TiledImageView(Context context) { 87d8732610ff48dc57063559d55ea3c84775e30e41John Reck this(context, null); 88d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 89d8732610ff48dc57063559d55ea3c84775e30e41John Reck 90d8732610ff48dc57063559d55ea3c84775e30e41John Reck public TiledImageView(Context context, AttributeSet attrs) { 91d8732610ff48dc57063559d55ea3c84775e30e41John Reck super(context, attrs); 92f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck if (!IS_SUPPORTED) { 93f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck return; 94f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } 95f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck 96f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck mRenderer = new ImageRendererWrapper(); 97f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck mRenderer.image = new TiledImageRenderer(this); 98f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck View view; 99f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck if (USE_TEXTURE_VIEW) { 100f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck mTextureView = new BlockingGLTextureView(context); 101f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck mTextureView.setRenderer(new TileRenderer()); 102f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck view = mTextureView; 103f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } else { 104f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck mGLSurfaceView = new GLSurfaceView(context); 105f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck mGLSurfaceView.setEGLContextClientVersion(2); 106f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck mGLSurfaceView.setRenderer(new TileRenderer()); 107f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck mGLSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); 108f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck view = mGLSurfaceView; 109f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } 110f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck addView(view, new LayoutParams( 111d8732610ff48dc57063559d55ea3c84775e30e41John Reck LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); 112f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck //setTileSource(new ColoredTiles()); 113d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 114d8732610ff48dc57063559d55ea3c84775e30e41John Reck 115d8732610ff48dc57063559d55ea3c84775e30e41John Reck public void destroy() { 116f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck if (!IS_SUPPORTED) { 117f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck return; 118f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } 119f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck if (USE_TEXTURE_VIEW) { 120f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck mTextureView.destroy(); 121f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } else { 122f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck mGLSurfaceView.queueEvent(mFreeTextures); 123d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 124d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 125d8732610ff48dc57063559d55ea3c84775e30e41John Reck 126f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck private Runnable mFreeTextures = new Runnable() { 127d8732610ff48dc57063559d55ea3c84775e30e41John Reck 128f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck @Override 129f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck public void run() { 130f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck mRenderer.image.freeTextures(); 131f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } 132f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck }; 133d8732610ff48dc57063559d55ea3c84775e30e41John Reck 134f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck public void onPause() { 135f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck if (!IS_SUPPORTED) { 136f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck return; 137f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } 138f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck if (!USE_TEXTURE_VIEW) { 139f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck mGLSurfaceView.onPause(); 140f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } 141d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 142d8732610ff48dc57063559d55ea3c84775e30e41John Reck 143f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck public void onResume() { 144f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck if (!IS_SUPPORTED) { 145f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck return; 146f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } 147f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck if (!USE_TEXTURE_VIEW) { 148f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck mGLSurfaceView.onResume(); 149d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 150f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } 151d8732610ff48dc57063559d55ea3c84775e30e41John Reck 152f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck public void setTileSource(TileSource source, Runnable isReadyCallback) { 153f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck if (!IS_SUPPORTED) { 154f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck return; 155f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } 156d8732610ff48dc57063559d55ea3c84775e30e41John Reck synchronized (mLock) { 157f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck mRenderer.source = source; 158f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck mRenderer.isReadyCallback = isReadyCallback; 159f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck mRenderer.centerX = source != null ? source.getImageWidth() / 2 : 0; 160f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck mRenderer.centerY = source != null ? source.getImageHeight() / 2 : 0; 161f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck mRenderer.rotation = source != null ? source.getRotation() : 0; 162f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck mRenderer.scale = 0; 163f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck updateScaleIfNecessaryLocked(mRenderer); 164d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 165f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck invalidate(); 166d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 167d8732610ff48dc57063559d55ea3c84775e30e41John Reck 168d8732610ff48dc57063559d55ea3c84775e30e41John Reck @Override 169d8732610ff48dc57063559d55ea3c84775e30e41John Reck protected void onLayout(boolean changed, int left, int top, int right, 170d8732610ff48dc57063559d55ea3c84775e30e41John Reck int bottom) { 171d8732610ff48dc57063559d55ea3c84775e30e41John Reck super.onLayout(changed, left, top, right, bottom); 172f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck if (!IS_SUPPORTED) { 173f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck return; 174f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } 175d8732610ff48dc57063559d55ea3c84775e30e41John Reck synchronized (mLock) { 176f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck updateScaleIfNecessaryLocked(mRenderer); 177d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 178d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 179d8732610ff48dc57063559d55ea3c84775e30e41John Reck 180d8732610ff48dc57063559d55ea3c84775e30e41John Reck private void updateScaleIfNecessaryLocked(ImageRendererWrapper renderer) { 181f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck if (renderer == null || renderer.source == null 182f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck || renderer.scale > 0 || getWidth() == 0) { 183f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck return; 184f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } 185d8732610ff48dc57063559d55ea3c84775e30e41John Reck renderer.scale = Math.min( 186d8732610ff48dc57063559d55ea3c84775e30e41John Reck (float) getWidth() / (float) renderer.source.getImageWidth(), 187d8732610ff48dc57063559d55ea3c84775e30e41John Reck (float) getHeight() / (float) renderer.source.getImageHeight()); 188d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 189d8732610ff48dc57063559d55ea3c84775e30e41John Reck 190d8732610ff48dc57063559d55ea3c84775e30e41John Reck @Override 191d8732610ff48dc57063559d55ea3c84775e30e41John Reck protected void dispatchDraw(Canvas canvas) { 192f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck if (!IS_SUPPORTED) { 193f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck return; 194f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } 195f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck if (USE_TEXTURE_VIEW) { 196f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck mTextureView.render(); 197f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } 198d8732610ff48dc57063559d55ea3c84775e30e41John Reck super.dispatchDraw(canvas); 199d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 200d8732610ff48dc57063559d55ea3c84775e30e41John Reck 201f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck @SuppressLint("NewApi") 202f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck @Override 203f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck public void setTranslationX(float translationX) { 204f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck if (!IS_SUPPORTED) { 205f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck return; 206f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } 207f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck super.setTranslationX(translationX); 208f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } 209f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck 210d8732610ff48dc57063559d55ea3c84775e30e41John Reck @Override 211d8732610ff48dc57063559d55ea3c84775e30e41John Reck public void invalidate() { 212f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck if (!IS_SUPPORTED) { 213f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck return; 214f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } 215f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck if (USE_TEXTURE_VIEW) { 216f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck super.invalidate(); 217f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck mTextureView.invalidate(); 218f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } else { 219f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck if (USE_CHOREOGRAPHER) { 220f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck invalOnVsync(); 221f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } else { 222f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck mGLSurfaceView.requestRender(); 223f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } 224f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } 225f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } 226f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck 227f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck @TargetApi(Build.VERSION_CODES.JELLY_BEAN) 228f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck private void invalOnVsync() { 229f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck if (!mInvalPending) { 230f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck mInvalPending = true; 231f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck if (mFrameCallback == null) { 232f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck mFrameCallback = new FrameCallback() { 233f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck @Override 234f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck public void doFrame(long frameTimeNanos) { 235f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck mInvalPending = false; 236f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck mGLSurfaceView.requestRender(); 237f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } 238f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck }; 239f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } 240f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck Choreographer.getInstance().postFrameCallback(mFrameCallback); 241f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } 242f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } 243f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck 244f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck private RectF mTempRectF = new RectF(); 245f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck public void positionFromMatrix(Matrix matrix) { 246f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck if (!IS_SUPPORTED) { 247f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck return; 248f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } 249f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck if (mRenderer.source != null) { 250f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck final int rotation = mRenderer.source.getRotation(); 251f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck final boolean swap = !(rotation % 180 == 0); 252f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck final int width = swap ? mRenderer.source.getImageHeight() 253f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck : mRenderer.source.getImageWidth(); 254f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck final int height = swap ? mRenderer.source.getImageWidth() 255f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck : mRenderer.source.getImageHeight(); 256f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck mTempRectF.set(0, 0, width, height); 257f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck matrix.mapRect(mTempRectF); 258f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck matrix.getValues(mValues); 259f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck int cx = width / 2; 260f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck int cy = height / 2; 261f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck float scale = mValues[Matrix.MSCALE_X]; 262f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck int xoffset = Math.round((getWidth() - mTempRectF.width()) / 2 / scale); 263f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck int yoffset = Math.round((getHeight() - mTempRectF.height()) / 2 / scale); 264f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck if (rotation == 90 || rotation == 180) { 265f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck cx += (mTempRectF.left / scale) - xoffset; 266f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } else { 267f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck cx -= (mTempRectF.left / scale) - xoffset; 268f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } 269f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck if (rotation == 180 || rotation == 270) { 270f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck cy += (mTempRectF.top / scale) - yoffset; 271f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } else { 272f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck cy -= (mTempRectF.top / scale) - yoffset; 273f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } 274f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck mRenderer.scale = scale; 275f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck mRenderer.centerX = swap ? cy : cx; 276f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck mRenderer.centerY = swap ? cx : cy; 277f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck invalidate(); 278f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } 279d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 280d8732610ff48dc57063559d55ea3c84775e30e41John Reck 281d8732610ff48dc57063559d55ea3c84775e30e41John Reck private class TileRenderer implements Renderer { 282d8732610ff48dc57063559d55ea3c84775e30e41John Reck 283d8732610ff48dc57063559d55ea3c84775e30e41John Reck private GLES20Canvas mCanvas; 284d8732610ff48dc57063559d55ea3c84775e30e41John Reck 285d8732610ff48dc57063559d55ea3c84775e30e41John Reck @Override 286d8732610ff48dc57063559d55ea3c84775e30e41John Reck public void onSurfaceCreated(GL10 gl, EGLConfig config) { 287d8732610ff48dc57063559d55ea3c84775e30e41John Reck mCanvas = new GLES20Canvas(); 288f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck BasicTexture.invalidateAllTextures(); 289f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck mRenderer.image.setModel(mRenderer.source, mRenderer.rotation); 290d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 291d8732610ff48dc57063559d55ea3c84775e30e41John Reck 292d8732610ff48dc57063559d55ea3c84775e30e41John Reck @Override 293d8732610ff48dc57063559d55ea3c84775e30e41John Reck public void onSurfaceChanged(GL10 gl, int width, int height) { 294d8732610ff48dc57063559d55ea3c84775e30e41John Reck mCanvas.setSize(width, height); 295f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck mRenderer.image.setViewSize(width, height); 296d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 297d8732610ff48dc57063559d55ea3c84775e30e41John Reck 298d8732610ff48dc57063559d55ea3c84775e30e41John Reck @Override 299d8732610ff48dc57063559d55ea3c84775e30e41John Reck public void onDrawFrame(GL10 gl) { 300d8732610ff48dc57063559d55ea3c84775e30e41John Reck mCanvas.clearBuffer(); 301f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck Runnable readyCallback; 302d8732610ff48dc57063559d55ea3c84775e30e41John Reck synchronized (mLock) { 303f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck readyCallback = mRenderer.isReadyCallback; 304f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck mRenderer.image.setModel(mRenderer.source, mRenderer.rotation); 305f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck mRenderer.image.setPosition(mRenderer.centerX, mRenderer.centerY, 306f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck mRenderer.scale); 307d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 308f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck boolean complete = mRenderer.image.draw(mCanvas); 309f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck if (complete && readyCallback != null) { 310f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck synchronized (mLock) { 311f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck // Make sure we don't trample on a newly set callback/source 312f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck // if it changed while we were rendering 313f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck if (mRenderer.isReadyCallback == readyCallback) { 314f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck mRenderer.isReadyCallback = null; 315f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } 316f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } 317f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck if (readyCallback != null) { 318f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck post(readyCallback); 319f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } 320d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 321d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 322d8732610ff48dc57063559d55ea3c84775e30e41John Reck 323d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 324d8732610ff48dc57063559d55ea3c84775e30e41John Reck 325f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck @SuppressWarnings("unused") 326d8732610ff48dc57063559d55ea3c84775e30e41John Reck private static class ColoredTiles implements TileSource { 327f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck private static final int[] COLORS = new int[] { 328d8732610ff48dc57063559d55ea3c84775e30e41John Reck Color.RED, 329d8732610ff48dc57063559d55ea3c84775e30e41John Reck Color.BLUE, 330d8732610ff48dc57063559d55ea3c84775e30e41John Reck Color.YELLOW, 331d8732610ff48dc57063559d55ea3c84775e30e41John Reck Color.GREEN, 332d8732610ff48dc57063559d55ea3c84775e30e41John Reck Color.CYAN, 333d8732610ff48dc57063559d55ea3c84775e30e41John Reck Color.MAGENTA, 334d8732610ff48dc57063559d55ea3c84775e30e41John Reck Color.WHITE, 335d8732610ff48dc57063559d55ea3c84775e30e41John Reck }; 336d8732610ff48dc57063559d55ea3c84775e30e41John Reck 337d8732610ff48dc57063559d55ea3c84775e30e41John Reck private Paint mPaint = new Paint(); 338d8732610ff48dc57063559d55ea3c84775e30e41John Reck private Canvas mCanvas = new Canvas(); 339d8732610ff48dc57063559d55ea3c84775e30e41John Reck 340d8732610ff48dc57063559d55ea3c84775e30e41John Reck @Override 341d8732610ff48dc57063559d55ea3c84775e30e41John Reck public int getTileSize() { 342d8732610ff48dc57063559d55ea3c84775e30e41John Reck return 256; 343d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 344d8732610ff48dc57063559d55ea3c84775e30e41John Reck 345d8732610ff48dc57063559d55ea3c84775e30e41John Reck @Override 346d8732610ff48dc57063559d55ea3c84775e30e41John Reck public int getImageWidth() { 347d8732610ff48dc57063559d55ea3c84775e30e41John Reck return 16384; 348d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 349d8732610ff48dc57063559d55ea3c84775e30e41John Reck 350d8732610ff48dc57063559d55ea3c84775e30e41John Reck @Override 351d8732610ff48dc57063559d55ea3c84775e30e41John Reck public int getImageHeight() { 352d8732610ff48dc57063559d55ea3c84775e30e41John Reck return 8192; 353d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 354d8732610ff48dc57063559d55ea3c84775e30e41John Reck 355d8732610ff48dc57063559d55ea3c84775e30e41John Reck @Override 356f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck public int getRotation() { 357f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck return 0; 358f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } 359f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck 360f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck @Override 361d8732610ff48dc57063559d55ea3c84775e30e41John Reck public Bitmap getTile(int level, int x, int y, Bitmap bitmap) { 362d8732610ff48dc57063559d55ea3c84775e30e41John Reck int tileSize = getTileSize(); 363d8732610ff48dc57063559d55ea3c84775e30e41John Reck if (bitmap == null) { 364d8732610ff48dc57063559d55ea3c84775e30e41John Reck bitmap = Bitmap.createBitmap(tileSize, tileSize, 365d8732610ff48dc57063559d55ea3c84775e30e41John Reck Bitmap.Config.ARGB_8888); 366d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 367d8732610ff48dc57063559d55ea3c84775e30e41John Reck mCanvas.setBitmap(bitmap); 368d8732610ff48dc57063559d55ea3c84775e30e41John Reck mCanvas.drawColor(COLORS[level]); 369d8732610ff48dc57063559d55ea3c84775e30e41John Reck mPaint.setColor(Color.BLACK); 370d8732610ff48dc57063559d55ea3c84775e30e41John Reck mPaint.setTextSize(20); 371d8732610ff48dc57063559d55ea3c84775e30e41John Reck mPaint.setTextAlign(Align.CENTER); 372d8732610ff48dc57063559d55ea3c84775e30e41John Reck mCanvas.drawText(x + "x" + y, 128, 128, mPaint); 373d8732610ff48dc57063559d55ea3c84775e30e41John Reck tileSize <<= level; 374d8732610ff48dc57063559d55ea3c84775e30e41John Reck x /= tileSize; 375d8732610ff48dc57063559d55ea3c84775e30e41John Reck y /= tileSize; 376d8732610ff48dc57063559d55ea3c84775e30e41John Reck mCanvas.drawText(x + "x" + y + " @ " + level, 128, 30, mPaint); 377d8732610ff48dc57063559d55ea3c84775e30e41John Reck mCanvas.setBitmap(null); 378d8732610ff48dc57063559d55ea3c84775e30e41John Reck return bitmap; 379d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 380f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck 381f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck @Override 382f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck public BasicTexture getPreview() { 383f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck return null; 384f5ef4801465a48ce3e33e1a75568060b2cf61185John Reck } 385d8732610ff48dc57063559d55ea3c84775e30e41John Reck } 386d8732610ff48dc57063559d55ea3c84775e30e41John Reck} 387