1c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam/* 2c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam * Copyright (C) 2015 The Android Open Source Project 3c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam * 4c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam * Licensed under the Apache License, Version 2.0 (the "License"); 5c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam * you may not use this file except in compliance with the License. 6c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam * You may obtain a copy of the License at 7c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam * 8c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam * http://www.apache.org/licenses/LICENSE-2.0 9c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam * 10c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam * Unless required by applicable law or agreed to in writing, software 11c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam * distributed under the License is distributed on an "AS IS" BASIS, 12c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam * See the License for the specific language governing permissions and 14c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam * limitations under the License. 15c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam */ 16c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam 17c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lampackage com.android.setupwizardlib; 18c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam 19c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lamimport android.annotation.SuppressLint; 20c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lamimport android.content.Context; 21c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lamimport android.content.res.TypedArray; 22a2f04916533b900d3661c9e8c9d98b71276fde13Maurice Lamimport android.graphics.Bitmap; 23c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lamimport android.graphics.Canvas; 24c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lamimport android.graphics.Color; 25c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lamimport android.graphics.ColorFilter; 26515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lamimport android.graphics.ColorMatrixColorFilter; 27c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lamimport android.graphics.Paint; 28c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lamimport android.graphics.Path; 296e0e22635d5fa943f72251e534f37527d3b3468cMaurice Lamimport android.graphics.PixelFormat; 30515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lamimport android.graphics.PorterDuff; 31515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lamimport android.graphics.PorterDuffXfermode; 32c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lamimport android.graphics.Rect; 33c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lamimport android.graphics.drawable.Drawable; 34c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lamimport android.os.Build; 354482fde98ebad2700ec1f8de5397abb90402b8b8Maurice Lamimport android.support.annotation.NonNull; 36903f83af5ba54075275b455a24c4273143fcb86aMaurice Lamimport android.support.annotation.VisibleForTesting; 37c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam 38515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lamimport java.lang.ref.SoftReference; 39515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam 40515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam/** 41515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam * This class draws the GLIF pattern used as the status bar background for phones and background for 42515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam * tablets in GLIF layout. 43515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam */ 44c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lampublic class GlifPatternDrawable extends Drawable { 45515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam /* 46515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam * This class essentially implements a simple SVG in Java code, with some special handling of 47515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam * scaling when given different bounds. 48515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam */ 49c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam 50c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam /* static section */ 51c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam 52c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam @SuppressLint("InlinedApi") 53c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam private static final int[] ATTRS_PRIMARY_COLOR = new int[]{ android.R.attr.colorPrimary }; 54c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam 55c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam private static final float VIEWBOX_HEIGHT = 768f; 56c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam private static final float VIEWBOX_WIDTH = 1366f; 57515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam // X coordinate of scale focus, as a fraction of of the width. (Range is 0 - 1) 58515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam private static final float SCALE_FOCUS_X = .146f; 59515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam // Y coordinate of scale focus, as a fraction of of the height. (Range is 0 - 1) 60515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam private static final float SCALE_FOCUS_Y = .228f; 61515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam 62515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam // Alpha component of the color to be drawn, on top of the grayscale pattern. (Range is 0 - 1) 63515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam private static final float COLOR_ALPHA = .8f; 64515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam // Int version of COLOR_ALPHA. (Range is 0 - 255) 65515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam private static final int COLOR_ALPHA_INT = (int) (COLOR_ALPHA * 255); 66515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam 67515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam // Cap the bitmap size, such that it won't hurt the performance too much 68515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam // and it won't crash due to a very large scale. 69515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam // The drawable will look blurry above this size. 70515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam // This is a multiplier applied on top of the viewbox size. 71515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam // Resulting max cache size = (1.5 x 1366, 1.5 x 768) = (2049, 1152) 72515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam private static final float MAX_CACHED_BITMAP_SCALE = 1.5f; 73515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam 74515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam private static final int NUM_PATHS = 7; 75515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam 76515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam private static SoftReference<Bitmap> sBitmapCache; 77515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam private static Path[] sPatternPaths; 78515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam private static int[] sPatternLightness; 79c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam 80c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam public static GlifPatternDrawable getDefault(Context context) { 81c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam int colorPrimary = 0; 82c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 83c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam final TypedArray a = context.obtainStyledAttributes(ATTRS_PRIMARY_COLOR); 84c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam colorPrimary = a.getColor(0, Color.BLACK); 85c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam a.recycle(); 86c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam } 87c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam return new GlifPatternDrawable(colorPrimary); 88c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam } 89c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam 90515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam @VisibleForTesting 91515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam public static void invalidatePattern() { 92515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam sBitmapCache = null; 93515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam } 94515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam 95c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam /* non-static section */ 96c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam 97c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam private int mColor; 98515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam private Paint mTempPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 99515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam private ColorFilter mColorFilter; 100c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam 101c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam public GlifPatternDrawable(int color) { 102c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam setColor(color); 103c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam } 104c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam 105c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam @Override 1064482fde98ebad2700ec1f8de5397abb90402b8b8Maurice Lam public void draw(@NonNull Canvas canvas) { 107515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam final Rect bounds = getBounds(); 108515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam int drawableWidth = bounds.width(); 109515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam int drawableHeight = bounds.height(); 110515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam Bitmap bitmap = null; 111515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam if (sBitmapCache != null) { 112515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam bitmap = sBitmapCache.get(); 113515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam } 114515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam if (bitmap != null) { 115515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam final int bitmapWidth = bitmap.getWidth(); 116515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam final int bitmapHeight = bitmap.getHeight(); 117515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam // Invalidate the cache if this drawable is bigger and we can still create a bigger 118515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam // cache. 119515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam if (drawableWidth > bitmapWidth 120515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam && bitmapWidth < VIEWBOX_WIDTH * MAX_CACHED_BITMAP_SCALE) { 121515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam bitmap = null; 122515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam } else if (drawableHeight > bitmapHeight 123515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam && bitmapHeight < VIEWBOX_HEIGHT * MAX_CACHED_BITMAP_SCALE) { 124515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam bitmap = null; 125515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam } 126515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam } 127515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam 128515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam if (bitmap == null) { 129515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam // Reset the paint so it can be used to draw the paths in renderOnCanvas 130515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam mTempPaint.reset(); 131515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam 132515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam bitmap = createBitmapCache(drawableWidth, drawableHeight); 133515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam sBitmapCache = new SoftReference<>(bitmap); 134515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam 135515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam // Reset the paint to so it can be used to draw the bitmap 136515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam mTempPaint.reset(); 137a2f04916533b900d3661c9e8c9d98b71276fde13Maurice Lam } 138515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam 139081551e44a801f439f0e0f30008303dd765c118fMaurice Lam canvas.save(); 140515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam canvas.clipRect(bounds); 141515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam 142515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam scaleCanvasToBounds(canvas, bitmap, bounds); 143515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB 144515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam && canvas.isHardwareAccelerated()) { 145515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam mTempPaint.setColorFilter(mColorFilter); 146515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam canvas.drawBitmap(bitmap, 0, 0, mTempPaint); 147515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam } else { 148515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam // Software renderer doesn't work properly with ColorMatrix filter on ALPHA_8 bitmaps. 149515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam canvas.drawColor(Color.BLACK); 150515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam mTempPaint.setColor(Color.WHITE); 151515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam canvas.drawBitmap(bitmap, 0, 0, mTempPaint); 152515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam canvas.drawColor(mColor); 153515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam } 154515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam 155081551e44a801f439f0e0f30008303dd765c118fMaurice Lam canvas.restore(); 156a2f04916533b900d3661c9e8c9d98b71276fde13Maurice Lam } 157a2f04916533b900d3661c9e8c9d98b71276fde13Maurice Lam 158515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam @VisibleForTesting 159515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam public Bitmap createBitmapCache(int drawableWidth, int drawableHeight) { 160515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam float scaleX = drawableWidth / VIEWBOX_WIDTH; 161515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam float scaleY = drawableHeight / VIEWBOX_HEIGHT; 162515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam float scale = Math.max(scaleX, scaleY); 163515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam scale = Math.min(MAX_CACHED_BITMAP_SCALE, scale); 164515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam 165515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam 166515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam int scaledWidth = (int) (VIEWBOX_WIDTH * scale); 167515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam int scaledHeight = (int) (VIEWBOX_HEIGHT * scale); 168515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam 169515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam // Use ALPHA_8 mask to save memory, since the pattern is grayscale only anyway. 170515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam Bitmap bitmap = Bitmap.createBitmap( 171515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam scaledWidth, 172515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam scaledHeight, 173515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam Bitmap.Config.ALPHA_8); 174515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam Canvas bitmapCanvas = new Canvas(bitmap); 175515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam renderOnCanvas(bitmapCanvas, scale); 176515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam return bitmap; 177515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam } 178515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam 179515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam private void renderOnCanvas(Canvas canvas, float scale) { 180c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam canvas.save(); 181515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam canvas.scale(scale, scale); 182c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam 183515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam mTempPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC)); 184c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam 185c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam // Draw the pattern by creating the paths, adjusting the colors and drawing them. The path 186c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam // values are extracted from the SVG of the pattern file. 187c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam 188515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam if (sPatternPaths == null) { 189515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam sPatternPaths = new Path[NUM_PATHS]; 190515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam // Lightness values of the pattern, range 0 - 255 191515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam sPatternLightness = new int[] { 10, 40, 51, 66, 91, 112, 130 }; 192515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam 193515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam Path p = sPatternPaths[0] = new Path(); 194515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.moveTo(1029.4f, 357.5f); 195515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.lineTo(1366f, 759.1f); 196515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.lineTo(1366f, 0f); 197515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.lineTo(1137.7f, 0f); 198515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.close(); 199515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam 200515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p = sPatternPaths[1] = new Path(); 201515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.moveTo(1138.1f, 0f); 202515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.rLineTo(-144.8f, 768f); 203515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.rLineTo(372.7f, 0f); 204515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.rLineTo(0f, -524f); 205515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.cubicTo(1290.7f, 121.6f, 1219.2f, 41.1f, 1178.7f, 0f); 206515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.close(); 207515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam 208515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p = sPatternPaths[2] = new Path(); 209515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.moveTo(949.8f, 768f); 210515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.rCubicTo(92.6f, -170.6f, 213f, -440.3f, 269.4f, -768f); 211515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.lineTo(585f, 0f); 212515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.rLineTo(2.1f, 766f); 213515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.close(); 214515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam 215515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p = sPatternPaths[3] = new Path(); 216515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.moveTo(471.1f, 768f); 217515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.rMoveTo(704.5f, 0f); 218515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.cubicTo(1123.6f, 563.3f, 1027.4f, 275.2f, 856.2f, 0f); 219515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.lineTo(476.4f, 0f); 220515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.rLineTo(-5.3f, 768f); 221515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.close(); 222515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam 223515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p = sPatternPaths[4] = new Path(); 224515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.moveTo(323.1f, 768f); 225515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.moveTo(777.5f, 768f); 226515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.cubicTo(661.9f, 348.8f, 427.2f, 21.4f, 401.2f, 25.4f); 227515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.lineTo(323.1f, 768f); 228515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.close(); 229515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam 230515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p = sPatternPaths[5] = new Path(); 231515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.moveTo(178.44286f, 766.85714f); 232515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.lineTo(308.7f, 768f); 233515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.cubicTo(381.7f, 604.6f, 481.6f, 344.3f, 562.2f, 0f); 234515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.lineTo(0f, 0f); 235515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.close(); 236515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam 237515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p = sPatternPaths[6] = new Path(); 238515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.moveTo(146f, 0f); 239515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.lineTo(0f, 0f); 240515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.lineTo(0f, 768f); 241515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.lineTo(394.2f, 768f); 242515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.cubicTo(327.7f, 475.3f, 228.5f, 201f, 146f, 0f); 243515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam p.close(); 244515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam } 245515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam 246515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam for (int i = 0; i < NUM_PATHS; i++) { 247515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam // Color is 0xAARRGGBB, so alpha << 24 will create a color with (alpha)% black. 248515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam // Although the color components don't really matter, since the backing bitmap cache is 249515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam // ALPHA_8. 250515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam mTempPaint.setColor(sPatternLightness[i] << 24); 251515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam canvas.drawPath(sPatternPaths[i], mTempPaint); 252515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam } 253c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam 254c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam canvas.restore(); 255515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam mTempPaint.reset(); 256c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam } 257c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam 258c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam @VisibleForTesting 259515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam public void scaleCanvasToBounds(Canvas canvas, Bitmap bitmap, Rect drawableBounds) { 260515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam int bitmapWidth = bitmap.getWidth(); 261515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam int bitmapHeight = bitmap.getHeight(); 262515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam float scaleX = drawableBounds.width() / (float) bitmapWidth; 263515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam float scaleY = drawableBounds.height() / (float) bitmapHeight; 264c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam 265c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam // First scale both sides to fit independently. 266c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam canvas.scale(scaleX, scaleY); 267c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam if (scaleY > scaleX) { 268515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam // Adjust x-scale to maintain aspect ratio using the pivot, so that more of the texture 269515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam // and less of the blank space on the left edge is seen. 270515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam canvas.scale(scaleY / scaleX, 1f, SCALE_FOCUS_X * bitmapWidth, 0f); 271515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam } else if (scaleX > scaleY) { 272515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam // Adjust y-scale to maintain aspect ratio using the pivot, so that an intersection of 273515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam // two "circles" can always be seen. 274515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam canvas.scale(1f, scaleX / scaleY, 0f, SCALE_FOCUS_Y * bitmapHeight); 275c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam } 276c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam } 277c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam 278c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam @Override 279c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam public void setAlpha(int i) { 280c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam // Ignore 281c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam } 282c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam 283c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam @Override 284c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam public void setColorFilter(ColorFilter colorFilter) { 285c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam // Ignore 286c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam } 287c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam 288c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam @Override 289c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam public int getOpacity() { 2906e0e22635d5fa943f72251e534f37527d3b3468cMaurice Lam return PixelFormat.UNKNOWN; 291c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam } 292c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam 293515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam /** 294515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam * Sets the color used as the base color of this pattern drawable. The alpha component of the 295515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam * color will be ignored. 296515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam */ 297c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam public void setColor(int color) { 298515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam final int r = Color.red(color); 299515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam final int g = Color.green(color); 300515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam final int b = Color.blue(color); 301515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam mColor = Color.argb(COLOR_ALPHA_INT, r, g, b); 302515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam mColorFilter = new ColorMatrixColorFilter(new float[] { 303515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam 0, 0, 0, 1 - COLOR_ALPHA, r * COLOR_ALPHA, 304515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam 0, 0, 0, 1 - COLOR_ALPHA, g * COLOR_ALPHA, 305515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam 0, 0, 0, 1 - COLOR_ALPHA, b * COLOR_ALPHA, 306515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam 0, 0, 0, 0, 255 307515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam }); 308c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam invalidateSelf(); 309c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam } 310c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam 311515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam /** 312515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam * @return The color used as the base color of this pattern drawable. The alpha component of 313515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam * this is always 255. 314515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam */ 315c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam public int getColor() { 316515c0b156d03f7ea348303c75e37ee4c16d90557Maurice Lam return Color.argb(255, Color.red(mColor), Color.green(mColor), Color.blue(mColor)); 317c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam } 318c3eebe9f664af4b77e5948a14bf266b25dc25cc8Maurice Lam} 319