Home | History | Annotate | Download | only in setupwizardlib
      1 /*
      2  * Copyright (C) 2015 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 com.android.setupwizardlib;
     18 
     19 import android.annotation.SuppressLint;
     20 import android.content.Context;
     21 import android.content.res.TypedArray;
     22 import android.graphics.Bitmap;
     23 import android.graphics.Canvas;
     24 import android.graphics.Color;
     25 import android.graphics.ColorFilter;
     26 import android.graphics.Paint;
     27 import android.graphics.Path;
     28 import android.graphics.Rect;
     29 import android.graphics.drawable.Drawable;
     30 import android.os.Build;
     31 
     32 import com.android.setupwizardlib.annotations.VisibleForTesting;
     33 
     34 public class GlifPatternDrawable extends Drawable {
     35 
     36     /* static section */
     37 
     38     @SuppressLint("InlinedApi")
     39     private static final int[] ATTRS_PRIMARY_COLOR = new int[]{ android.R.attr.colorPrimary };
     40 
     41     private static final float VIEWBOX_HEIGHT = 768f;
     42     private static final float VIEWBOX_WIDTH = 1366f;
     43     private static final float SCALE_FOCUS_X = 200f;
     44     private static final float SCALE_FOCUS_Y = 175f;
     45 
     46     public static GlifPatternDrawable getDefault(Context context) {
     47         int colorPrimary = 0;
     48         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
     49             final TypedArray a = context.obtainStyledAttributes(ATTRS_PRIMARY_COLOR);
     50             colorPrimary = a.getColor(0, Color.BLACK);
     51             a.recycle();
     52         }
     53         return new GlifPatternDrawable(colorPrimary);
     54     }
     55 
     56     /* non-static section */
     57 
     58     private int mColor;
     59     private Paint mPaint;
     60     private float[] mTempHsv = new float[3];
     61     private Path mTempPath = new Path();
     62     private Bitmap mBitmap;
     63 
     64     public GlifPatternDrawable(int color) {
     65         mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
     66         setColor(color);
     67     }
     68 
     69     @Override
     70     public void draw(Canvas canvas) {
     71         if (mBitmap == null) {
     72             mBitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(),
     73                     Bitmap.Config.ARGB_8888);
     74             Canvas bitmapCanvas = new Canvas(mBitmap);
     75             renderOnCanvas(bitmapCanvas);
     76         }
     77         canvas.drawBitmap(mBitmap, 0, 0, null);
     78     }
     79 
     80     private void renderOnCanvas(Canvas canvas) {
     81         canvas.save();
     82         canvas.clipRect(getBounds());
     83 
     84         Color.colorToHSV(mColor, mTempHsv);
     85         scaleCanvasToBounds(canvas);
     86 
     87         // Draw the pattern by creating the paths, adjusting the colors and drawing them. The path
     88         // values are extracted from the SVG of the pattern file.
     89 
     90         mTempHsv[2] = 0.753f;
     91         Path p = mTempPath;
     92         p.reset();
     93         p.moveTo(1029.4f, 357.5f);
     94         p.lineTo(1366f, 759.1f);
     95         p.lineTo(1366f, 0f);
     96         p.lineTo(1137.7f, 0f);
     97         p.close();
     98         drawPath(canvas, p, mTempHsv);
     99 
    100         mTempHsv[2] = 0.78f;
    101         p.reset();
    102         p.moveTo(1138.1f, 0f);
    103         p.rLineTo(-144.8f, 768f);
    104         p.rLineTo(372.7f, 0f);
    105         p.rLineTo(0f, -524f);
    106         p.cubicTo(1290.7f, 121.6f, 1219.2f, 41.1f, 1178.7f, 0f);
    107         p.close();
    108         drawPath(canvas, p, mTempHsv);
    109 
    110         mTempHsv[2] = 0.804f;
    111         p.reset();
    112         p.moveTo(949.8f, 768f);
    113         p.rCubicTo(92.6f, -170.6f, 213f, -440.3f, 269.4f, -768f);
    114         p.lineTo(585f, 0f);
    115         p.rLineTo(2.1f, 766f);
    116         p.close();
    117         drawPath(canvas, p, mTempHsv);
    118 
    119         mTempHsv[2] = 0.827f;
    120         p.reset();
    121         p.moveTo(471.1f, 768f);
    122         p.rMoveTo(704.5f, 0f);
    123         p.cubicTo(1123.6f, 563.3f, 1027.4f, 275.2f, 856.2f, 0f);
    124         p.lineTo(476.4f, 0f);
    125         p.rLineTo(-5.3f, 768f);
    126         p.close();
    127         drawPath(canvas, p, mTempHsv);
    128 
    129         mTempHsv[2] = 0.867f;
    130         p.reset();
    131         p.moveTo(323.1f, 768f);
    132         p.moveTo(777.5f, 768f);
    133         p.cubicTo(661.9f, 348.8f, 427.2f, 21.4f, 401.2f, 25.4f);
    134         p.lineTo(323.1f, 768f);
    135         p.close();
    136         drawPath(canvas, p, mTempHsv);
    137 
    138         mTempHsv[2] = 0.894f;
    139         p.reset();
    140         p.moveTo(178.44286f, 766.85714f);
    141         p.lineTo(308.7f, 768f);
    142         p.cubicTo(381.7f, 604.6f, 481.6f, 344.3f, 562.2f, 0f);
    143         p.lineTo(0f, 0f);
    144         p.close();
    145         drawPath(canvas, p, mTempHsv);
    146 
    147         mTempHsv[2] = 0.929f;
    148         p.reset();
    149         p.moveTo(146f, 0f);
    150         p.lineTo(0f, 0f);
    151         p.lineTo(0f, 768f);
    152         p.lineTo(394.2f, 768f);
    153         p.cubicTo(327.7f, 475.3f, 228.5f, 201f, 146f, 0f);
    154         p.close();
    155         drawPath(canvas, p, mTempHsv);
    156 
    157         canvas.restore();
    158     }
    159 
    160     @VisibleForTesting
    161     public void scaleCanvasToBounds(Canvas canvas) {
    162         final Rect bounds = getBounds();
    163         final int height = bounds.height();
    164         final int width = bounds.width();
    165 
    166         float scaleY = height / VIEWBOX_HEIGHT;
    167         float scaleX = width / VIEWBOX_WIDTH;
    168         // First scale both sides to fit independently.
    169         canvas.scale(scaleX, scaleY);
    170         if (scaleY > scaleX) {
    171             // Adjust x-scale to maintain aspect ratio, but using (200, 0) as the pivot instead,
    172             // so that more of the texture and less of the blank space on the left edge is seen.
    173             canvas.scale(scaleY / scaleX, 1f, SCALE_FOCUS_X, 0f);
    174         } else {
    175             // Adjust y-scale to maintain aspect ratio, but using (0, 175) as the pivot instead,
    176             // so that an intersection of two "circles" can always be seen.
    177             canvas.scale(1f, scaleX / scaleY, 0f, SCALE_FOCUS_Y);
    178         }
    179     }
    180 
    181     private void drawPath(Canvas canvas, Path path, float[] hsv) {
    182         mPaint.setColor(Color.HSVToColor(hsv));
    183         canvas.drawPath(path, mPaint);
    184     }
    185 
    186     @Override
    187     public void setAlpha(int i) {
    188         // Ignore
    189     }
    190 
    191     @Override
    192     public void setColorFilter(ColorFilter colorFilter) {
    193         // Ignore
    194     }
    195 
    196     @Override
    197     public int getOpacity() {
    198         return 0;
    199     }
    200 
    201     public void setColor(int color) {
    202         mColor = color;
    203         mPaint.setColor(color);
    204         mBitmap = null;
    205         invalidateSelf();
    206     }
    207 
    208     public int getColor() {
    209         return mColor;
    210     }
    211 }
    212