Cat.java revision 27a9fcc61823f919cee773df563b49ee11004f3b
127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler/*
227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler * Copyright (C) 2016 The Android Open Source Project
327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler *
427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler * except in compliance with the License. You may obtain a copy of the License at
627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler *
727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler *      http://www.apache.org/licenses/LICENSE-2.0
827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler *
927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler * Unless required by applicable law or agreed to in writing, software distributed under the
1027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
1127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler * KIND, either express or implied. See the License for the specific language governing
1227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler * permissions and limitations under the License.
1327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler */
1427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
1527a9fcc61823f919cee773df563b49ee11004f3bDan Sandlerpackage com.android.egg.neko;
1627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
1727a9fcc61823f919cee773df563b49ee11004f3bDan Sandlerimport android.app.Notification;
1827a9fcc61823f919cee773df563b49ee11004f3bDan Sandlerimport android.app.PendingIntent;
1927a9fcc61823f919cee773df563b49ee11004f3bDan Sandlerimport android.content.ComponentName;
2027a9fcc61823f919cee773df563b49ee11004f3bDan Sandlerimport android.content.Context;
2127a9fcc61823f919cee773df563b49ee11004f3bDan Sandlerimport android.content.Intent;
2227a9fcc61823f919cee773df563b49ee11004f3bDan Sandlerimport android.content.res.Resources;
2327a9fcc61823f919cee773df563b49ee11004f3bDan Sandlerimport android.graphics.*;
2427a9fcc61823f919cee773df563b49ee11004f3bDan Sandlerimport android.graphics.drawable.Drawable;
2527a9fcc61823f919cee773df563b49ee11004f3bDan Sandlerimport android.graphics.drawable.Icon;
2627a9fcc61823f919cee773df563b49ee11004f3bDan Sandlerimport android.os.Bundle;
2727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
2827a9fcc61823f919cee773df563b49ee11004f3bDan Sandlerimport java.util.Random;
2927a9fcc61823f919cee773df563b49ee11004f3bDan Sandlerimport java.util.concurrent.ThreadLocalRandom;
3027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
3127a9fcc61823f919cee773df563b49ee11004f3bDan Sandlerimport com.android.egg.R;
3227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
3327a9fcc61823f919cee773df563b49ee11004f3bDan Sandlerpublic class Cat extends Drawable {
3427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    private Random mNotSoRandom;
3527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    private Bitmap mBitmap;
3627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    private long mSeed;
3727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    private String mName;
3827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    private int mBodyColor;
3927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
4027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    private synchronized Random notSoRandom(long seed) {
4127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        if (mNotSoRandom == null) {
4227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            mNotSoRandom = new Random();
4327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            mNotSoRandom.setSeed(seed);
4427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        }
4527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        return mNotSoRandom;
4627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
4727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
4827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public static final float frandrange(Random r, float a, float b) {
4927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        return (b-a)*r.nextFloat() + a;
5027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
5127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
5227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public static final Object choose(Random r, Object...l) {
5327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        return l[r.nextInt(l.length)];
5427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
5527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
5627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public static final int chooseP(Random r, int[] a) {
5727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        int pct = r.nextInt(1000);
5827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        final int stop = a.length-2;
5927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        int i=0;
6027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        while (i<stop) {
6127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            pct -= a[i];
6227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            if (pct < 0) break;
6327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            i+=2;
6427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        }
6527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        return a[i+1];
6627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
6727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
6827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public static final int[] P_BODY_COLORS = {
6927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            180, 0xFF212121, // black
7027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            180, 0xFFFFFFFF, // white
7127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            140, 0xFF616161, // gray
7227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            140, 0xFF795548, // brown
7327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            100, 0xFF90A4AE, // steel
7427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            100, 0xFFFFF9C4, // buff
7527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            100, 0xFFFF8F00, // orange
7627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler              5, 0xFF29B6F6, // blue..?
7727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler              5, 0xFFFFCDD2, // pink!?
7827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler              5, 0xFFCE93D8, // purple?!?!?
7927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler              4, 0xFF43A047, // yeah, why not green
8027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler              1, 0,          // ?!?!?!
8127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    };
8227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
8327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public static final int[] P_COLLAR_COLORS = {
8427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            250, 0xFFFFFFFF,
8527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            250, 0xFF000000,
8627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            250, 0xFFF44336,
8727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler             50, 0xFF1976D2,
8827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler             50, 0xFFFDD835,
8927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler             50, 0xFFFB8C00,
9027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler             50, 0xFFF48FB1,
9127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler             50, 0xFF4CAF50,
9227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    };
9327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
9427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public static final int[] P_BELLY_COLORS = {
9527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            750, 0,
9627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            250, 0xFFFFFFFF,
9727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    };
9827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
9927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public static final int[] P_DARK_SPOT_COLORS = {
10027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            700, 0,
10127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            250, 0xFF212121,
10227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler             50, 0xFF6D4C41,
10327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    };
10427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
10527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public static final int[] P_LIGHT_SPOT_COLORS = {
10627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            700, 0,
10727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            300, 0xFFFFFFFF,
10827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    };
10927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
11027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    private CatParts D;
11127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
11227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public static void tint(int color, Drawable ... ds) {
11327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        for (Drawable d : ds) {
11427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            if (d != null) {
11527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                d.mutate().setTint(color);
11627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            }
11727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        }
11827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
11927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
12027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public static boolean isDark(int color) {
12127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        final int r = (color & 0xFF0000) >> 16;
12227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        final int g = (color & 0x00FF00) >> 8;
12327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        final int b = color & 0x0000FF;
12427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        return (r + g + b) < 0x80;
12527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
12627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
12727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public Cat(Context context, long seed) {
12827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        D = new CatParts(context);
12927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        mSeed = seed;
13027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
13127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        setName(context.getString(R.string.default_cat_name,
13227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                String.valueOf(mSeed).substring(0, 3)));
13327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
13427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        final Random nsr = notSoRandom(seed);
13527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
13627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        // body color
13727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        mBodyColor = chooseP(nsr, P_BODY_COLORS);
13827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        if (mBodyColor == 0) mBodyColor = Color.HSVToColor(new float[] {
13927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                nsr.nextFloat()*360f, frandrange(nsr,0.5f,1f), frandrange(nsr,0.5f, 1f)});
14027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
14127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        tint(mBodyColor, D.body, D.head, D.leg1, D.leg2, D.leg3, D.leg4, D.tail,
14227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                D.leftEar, D.rightEar, D.foot1, D.foot2, D.foot3, D.foot4, D.tailCap);
14327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        tint(0x20000000, D.leg2Shadow, D.tailShadow);
14427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        if (isDark(mBodyColor)) {
14527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            tint(0xFFFFFFFF, D.leftEye, D.rightEye, D.mouth, D.nose);
14627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        }
14727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        tint(isDark(mBodyColor) ? 0xFFEF9A9A : 0x20D50000, D.leftEarInside, D.rightEarInside);
14827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
14927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        tint(chooseP(nsr, P_BELLY_COLORS), D.belly);
15027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        tint(chooseP(nsr, P_BELLY_COLORS), D.back);
15127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        final int faceColor = chooseP(nsr, P_BELLY_COLORS);
15227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        tint(faceColor, D.faceSpot);
15327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        if (!isDark(faceColor)) {
15427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            tint(0xFF000000, D.mouth, D.nose);
15527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        }
15627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
15727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        if (nsr.nextFloat() < 0.25f) {
15827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            tint(0xFFFFFFFF, D.foot1, D.foot2, D.foot3, D.foot4);
15927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        } else {
16027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            if (nsr.nextFloat() < 0.25f) {
16127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                tint(0xFFFFFFFF, D.foot1, D.foot2);
16227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            } else if (nsr.nextFloat() < 0.25f) {
16327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                tint(0xFFFFFFFF, D.foot3, D.foot4);
16427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            } else if (nsr.nextFloat() < 0.1f) {
16527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                tint(0xFFFFFFFF, (Drawable) choose(nsr, D.foot1, D.foot2, D.foot3, D.foot4));
16627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            }
16727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        }
16827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
16927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        tint(nsr.nextFloat() < 0.333f ? 0xFFFFFFFF : mBodyColor, D.tailCap);
17027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
17127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        final int capColor = chooseP(nsr, isDark(mBodyColor) ? P_LIGHT_SPOT_COLORS : P_DARK_SPOT_COLORS);
17227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        tint(capColor, D.cap);
17327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        //tint(chooseP(nsr, isDark(bodyColor) ? P_LIGHT_SPOT_COLORS : P_DARK_SPOT_COLORS), D.nose);
17427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
17527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        final int collarColor = chooseP(nsr, P_COLLAR_COLORS);
17627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        tint(collarColor, D.collar);
17727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        tint((nsr.nextFloat() < 0.1f) ? collarColor : 0, D.bowtie);
17827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
17927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
18027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public static Cat create(Context context) {
18127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        return new Cat(context, Math.abs(ThreadLocalRandom.current().nextInt()));
18227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
18327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
18427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public Notification.Builder buildNotification(Context context) {
18527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        final Bundle extras = new Bundle();
18627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        extras.putString("android.substName", context.getString(R.string.notification_name));
18727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        final Intent intent = new Intent(Intent.ACTION_MAIN)
18827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                .setClass(context, NekoLand.class)
18927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
19027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        return new Notification.Builder(context)
19127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                .setSmallIcon(Icon.createWithResource(context, R.drawable.stat_icon))
19227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                .setLargeIcon(createLargeIcon(context))
19327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                .setColor(getBodyColor())
19427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                .setPriority(Notification.PRIORITY_LOW)
19527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                .setContentTitle(context.getString(R.string.notification_title))
19627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                .setShowWhen(true)
19727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                .setCategory(Notification.CATEGORY_STATUS)
19827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                .setContentText(getName())
19927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                .setContentIntent(PendingIntent.getActivity(context, 0, intent, 0))
20027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                .setAutoCancel(true)
20127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                .addExtras(extras);
20227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
20327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
20427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public long getSeed() {
20527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        return mSeed;
20627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
20727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
20827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    @Override
20927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public void draw(Canvas canvas) {
21027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        final int w = Math.min(canvas.getWidth(), canvas.getHeight());
21127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        final int h = w;
21227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
21327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        if (mBitmap == null || mBitmap.getWidth() != w || mBitmap.getHeight() != h) {
21427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
21527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            final Canvas bitCanvas = new Canvas(mBitmap);
21627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            slowDraw(bitCanvas, 0, 0, w, h);
21727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        }
21827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        canvas.drawBitmap(mBitmap, 0, 0, null);
21927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
22027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
22127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    private void slowDraw(Canvas canvas, int x, int y, int w, int h) {
22227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        for (int i = 0; i < D.drawingOrder.length; i++) {
22327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            final Drawable d = D.drawingOrder[i];
22427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            if (d != null) {
22527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                d.setBounds(x, y, x+w, y+h);
22627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                d.draw(canvas);
22727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            }
22827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        }
22927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
23027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
23127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
23227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public Bitmap createBitmap(int w, int h) {
23327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        if (mBitmap != null && mBitmap.getWidth() == w && mBitmap.getHeight() == h) {
23427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            return mBitmap.copy(mBitmap.getConfig(), true);
23527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        }
23627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        Bitmap result = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
23727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        slowDraw(new Canvas(result), 0, 0, w, h);
23827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        return result;
23927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
24027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
24127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public Icon createLargeIcon(Context context) {
24227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        final Resources res = context.getResources();
24327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        final int w = res.getDimensionPixelSize(android.R.dimen.notification_large_icon_width);
24427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        final int h = res.getDimensionPixelSize(android.R.dimen.notification_large_icon_height);
24527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
24627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        Bitmap result = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
24727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        final Canvas canvas = new Canvas(result);
24827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        final Paint pt = new Paint();
24927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        float[] hsv = new float[3];
25027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        Color.colorToHSV(mBodyColor, hsv);
25127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        hsv[2] = (hsv[2]>0.5f)
25227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                ? (hsv[2] - 0.25f)
25327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                : (hsv[2] + 0.25f);
25427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        pt.setColor(Color.HSVToColor(hsv));
25527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        float r = w/2;
25627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        canvas.drawCircle(r, r, r, pt);
25727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        int m = w/10;
25827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
25927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        slowDraw(canvas, m, m, w-m-m, h-m-m);
26027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
26127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        return Icon.createWithBitmap(result);
26227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
26327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
26427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    @Override
26527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public void setAlpha(int i) {
26627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
26727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
26827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
26927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    @Override
27027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public void setColorFilter(ColorFilter colorFilter) {
27127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
27227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
27327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
27427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    @Override
27527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public int getOpacity() {
27627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        return PixelFormat.TRANSLUCENT;
27727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
27827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
27927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public String getName() {
28027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        return mName;
28127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
28227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
28327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public void setName(String name) {
28427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        this.mName = name;
28527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
28627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
28727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public int getBodyColor() {
28827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        return mBodyColor;
28927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
29027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
29127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    public static class CatParts {
29227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable leftEar;
29327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable rightEar;
29427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable rightEarInside;
29527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable leftEarInside;
29627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable head;
29727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable faceSpot;
29827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable cap;
29927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable mouth;
30027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable body;
30127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable foot1;
30227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable leg1;
30327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable foot2;
30427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable leg2;
30527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable foot3;
30627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable leg3;
30727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable foot4;
30827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable leg4;
30927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable tail;
31027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable leg2Shadow;
31127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable tailShadow;
31227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable tailCap;
31327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable belly;
31427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable back;
31527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable rightEye;
31627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable leftEye;
31727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable nose;
31827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable bowtie;
31927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable collar;
32027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public Drawable[] drawingOrder;
32127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler
32227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        public CatParts(Context context) {
32327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            body = context.getDrawable(R.drawable.body);
32427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            head = context.getDrawable(R.drawable.head);
32527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            leg1 = context.getDrawable(R.drawable.leg1);
32627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            leg2 = context.getDrawable(R.drawable.leg2);
32727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            leg3 = context.getDrawable(R.drawable.leg3);
32827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            leg4 = context.getDrawable(R.drawable.leg4);
32927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            tail = context.getDrawable(R.drawable.tail);
33027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            leftEar = context.getDrawable(R.drawable.left_ear);
33127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            rightEar = context.getDrawable(R.drawable.right_ear);
33227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            rightEarInside = context.getDrawable(R.drawable.right_ear_inside);
33327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            leftEarInside = context.getDrawable(R.drawable.left_ear_inside);
33427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            faceSpot = context.getDrawable(R.drawable.face_spot);
33527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            cap = context.getDrawable(R.drawable.cap);
33627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            mouth = context.getDrawable(R.drawable.mouth);
33727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            foot4 = context.getDrawable(R.drawable.foot4);
33827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            foot3 = context.getDrawable(R.drawable.foot3);
33927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            foot1 = context.getDrawable(R.drawable.foot1);
34027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            foot2 = context.getDrawable(R.drawable.foot2);
34127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            leg2Shadow = context.getDrawable(R.drawable.leg2_shadow);
34227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            tailShadow = context.getDrawable(R.drawable.tail_shadow);
34327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            tailCap = context.getDrawable(R.drawable.tail_cap);
34427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            belly = context.getDrawable(R.drawable.belly);
34527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            back = context.getDrawable(R.drawable.back);
34627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            rightEye = context.getDrawable(R.drawable.right_eye);
34727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            leftEye = context.getDrawable(R.drawable.left_eye);
34827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            nose = context.getDrawable(R.drawable.nose);
34927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            collar = context.getDrawable(R.drawable.collar);
35027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            bowtie = context.getDrawable(R.drawable.bowtie);
35127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            drawingOrder = getDrawingOrder();
35227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        }
35327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        private Drawable[] getDrawingOrder() {
35427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            return new Drawable[] {
35527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                    collar,
35627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                    leftEar, leftEarInside, rightEar, rightEarInside,
35727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                    head,
35827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                    faceSpot,
35927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                    cap,
36027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                    leftEye, rightEye,
36127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                    nose, mouth,
36227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                    tail, tailCap, tailShadow,
36327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                    foot1, leg1,
36427a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                    foot2, leg2,
36527a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                    foot3, leg3,
36627a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                    foot4, leg4,
36727a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                    leg2Shadow,
36827a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                    body, belly,
36927a9fcc61823f919cee773df563b49ee11004f3bDan Sandler                    bowtie
37027a9fcc61823f919cee773df563b49ee11004f3bDan Sandler            };
37127a9fcc61823f919cee773df563b49ee11004f3bDan Sandler        }
37227a9fcc61823f919cee773df563b49ee11004f3bDan Sandler    }
37327a9fcc61823f919cee773df563b49ee11004f3bDan Sandler}
374