OSDN Git Service

Add support for icon masks
authorBraden Farmer <farmerbb@gmail.com>
Fri, 30 Sep 2016 04:56:04 +0000 (22:56 -0600)
committerBraden Farmer <farmerbb@gmail.com>
Fri, 30 Sep 2016 04:56:04 +0000 (22:56 -0600)
app/src/main/java/com/farmerbb/taskbar/fragment/AdvancedFragment.java
app/src/main/java/com/farmerbb/taskbar/util/IconPack.java
app/src/main/java/com/farmerbb/taskbar/util/U.java
app/src/main/res/values-ja/strings.xml
app/src/main/res/values/strings.xml
app/src/main/res/xml/pref_advanced.xml

index 622ace2..5f64138 100644 (file)
@@ -38,6 +38,7 @@ public class AdvancedFragment extends SettingsFragment {
         findPreference("keyboard_shortcut").setOnPreferenceClickListener(this);
 
         bindPreferenceSummaryToValue(findPreference("hide_when_keyboard_shown"));
+        bindPreferenceSummaryToValue(findPreference("icon_pack_use_mask"));
 
         AppCompatActivity activity = (AppCompatActivity) getActivity();
         activity.setTitle(R.string.pref_header_advanced);
index 14654ab..1da23f3 100644 (file)
@@ -21,6 +21,12 @@ package com.farmerbb.taskbar.util;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -29,9 +35,12 @@ import org.xmlpull.v1.XmlPullParserFactory;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Random;
 
 public class IconPack {
     private String packageName;
@@ -39,6 +48,11 @@ public class IconPack {
 
     private boolean mLoaded = false;
     private Map<String, String> mPackagesDrawables = new HashMap<>();
+
+    private List<Bitmap> mBackImages = new ArrayList<>();
+    private Bitmap mMaskImage = null;
+    private Bitmap mFrontImage = null;
+    private float mFactor = 0.5f;
     private int totalIcons;
 
     private Resources iconPackres = null;
@@ -85,7 +99,30 @@ public class IconPack {
                 int eventType = xpp.getEventType();
                 while(eventType != XmlPullParser.END_DOCUMENT) {
                     if(eventType == XmlPullParser.START_TAG) {
-                        if(xpp.getName().equals("item")) {
+                        if(xpp.getName().equals("iconback")) {
+                            for(int i = 0; i < xpp.getAttributeCount(); i++) {
+                                if(xpp.getAttributeName(i).startsWith("img")) {
+                                    String drawableName = xpp.getAttributeValue(i);
+                                    Bitmap iconback = loadBitmap(drawableName);
+                                    if(iconback != null)
+                                        mBackImages.add(iconback);
+                                }
+                            }
+                        } else if(xpp.getName().equals("iconmask")) {
+                            if(xpp.getAttributeCount() > 0 && xpp.getAttributeName(0).equals("img1")) {
+                                String drawableName = xpp.getAttributeValue(0);
+                                mMaskImage = loadBitmap(drawableName);
+                            }
+                        } else if(xpp.getName().equals("iconupon")) {
+                            if(xpp.getAttributeCount() > 0 && xpp.getAttributeName(0).equals("img1")) {
+                                String drawableName = xpp.getAttributeValue(0);
+                                mFrontImage = loadBitmap(drawableName);
+                            }
+                        } else if(xpp.getName().equals("scale")) {
+                            if(xpp.getAttributeCount() > 0 && xpp.getAttributeName(0).equals("factor")) {
+                                mFactor = Float.valueOf(xpp.getAttributeValue(0));
+                            }
+                        } else if(xpp.getName().equals("item")) {
                             String componentName = null;
                             String drawableName = null;
 
@@ -110,6 +147,16 @@ public class IconPack {
     }
 
     @SuppressWarnings("deprecation")
+    private Bitmap loadBitmap(String drawableName) {
+        int id = iconPackres.getIdentifier(drawableName, "drawable", packageName);
+        if(id > 0) {
+            Drawable bitmap = iconPackres.getDrawable(id);
+            if(bitmap instanceof BitmapDrawable)
+                return ((BitmapDrawable) bitmap).getBitmap();
+        }
+        return null;
+    }
+    @SuppressWarnings("deprecation")
     private Drawable loadDrawable(String drawableName) {
         int id = iconPackres.getIdentifier(drawableName, "drawable", packageName);
         if(id > 0) {
@@ -139,4 +186,86 @@ public class IconPack {
 
         return null;
     }
+
+    Bitmap getIconForPackage(Context mContext, String componentName, Bitmap defaultBitmap) {
+        if(!mLoaded) load(mContext);
+
+        String drawable = mPackagesDrawables.get(componentName);
+        if(drawable != null) {
+            Bitmap BMP = loadBitmap(drawable);
+            if(BMP == null) {
+                return generateBitmap(defaultBitmap);
+            } else {
+                return BMP;
+            }
+        } else {
+            // Try to get a resource with the component filename
+            if(componentName != null) {
+                int start = componentName.indexOf("{") + 1;
+                int end = componentName.indexOf("}", start);
+                if(end > start) {
+                    drawable = componentName.substring(start, end).toLowerCase(Locale.getDefault()).replace(".", "_").replace("/", "_");
+                    if(iconPackres.getIdentifier(drawable, "drawable", packageName) > 0)
+                        return loadBitmap(drawable);
+                }
+            }
+        }
+
+        return generateBitmap(defaultBitmap);
+    }
+
+    private Bitmap generateBitmap(Bitmap defaultBitmap) {
+        // If no support images in the icon pack, return the bitmap itself
+        if(mBackImages.size() == 0) return defaultBitmap;
+
+        Random r = new Random();
+        int backImageInd = r.nextInt(mBackImages.size());
+        Bitmap backImage = mBackImages.get(backImageInd);
+        int w = backImage.getWidth();
+        int h = backImage.getHeight();
+
+        // Create a bitmap for the result
+        Bitmap result = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
+        Canvas mCanvas = new Canvas(result);
+
+        // Draw the background first
+        mCanvas.drawBitmap(backImage, 0, 0, null);
+
+        // Create a mutable mask bitmap with the same mask
+        Bitmap scaledBitmap = Bitmap.createScaledBitmap(defaultBitmap, (int) (w * mFactor), (int) (h * mFactor), true);
+
+        if(mMaskImage != null) {
+            // Draw the scaled bitmap with mask
+            Bitmap mutableMask = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
+            Canvas maskCanvas = new Canvas(mutableMask);
+            maskCanvas.drawBitmap(mMaskImage, 0, 0, new Paint());
+
+            // Paint the bitmap with mask into the result
+            Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
+            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
+            mCanvas.drawBitmap(scaledBitmap, (w - scaledBitmap.getWidth()) / 2, (h - scaledBitmap.getHeight()) / 2, null);
+            mCanvas.drawBitmap(mutableMask, 0, 0, paint);
+            paint.setXfermode(null);
+        } else {
+            // Draw the scaled bitmap with the back image as mask
+            Bitmap mutableMask = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
+            Canvas maskCanvas = new Canvas(mutableMask);
+            maskCanvas.drawBitmap(backImage, 0, 0, new Paint());
+
+            // Paint the bitmap with mask into the result
+            Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
+            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
+            mCanvas.drawBitmap(scaledBitmap, (w - scaledBitmap.getWidth()) / 2, (h - scaledBitmap.getHeight()) / 2, null);
+            mCanvas.drawBitmap(mutableMask, 0, 0, paint);
+            paint.setXfermode(null);
+
+        }
+
+        // Paint the front
+        if(mFrontImage != null) {
+            mCanvas.drawBitmap(mFrontImage, 0, 0, null);
+        }
+
+        return result;
+    }
 }
\ No newline at end of file
index 923d1de..ad8846d 100644 (file)
@@ -30,6 +30,7 @@ import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.res.Configuration;
 import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.hardware.display.DisplayManager;
 import android.net.Uri;
@@ -431,6 +432,7 @@ public class U {
     public static Drawable loadIcon(Context context, PackageManager pm, ActivityInfo appInfo) {
         SharedPreferences pref = getSharedPreferences(context);
         String iconPackPackage = pref.getString("icon_pack", BuildConfig.APPLICATION_ID);
+        boolean useMask = pref.getBoolean("icon_pack_use_mask", false);
         IconPackManager iconPackManager = IconPackManager.getInstance();
 
         try {
@@ -445,9 +447,21 @@ public class U {
             return appInfo.loadIcon(pm);
         else {
             IconPack iconPack = iconPackManager.getIconPack(context, iconPackPackage);
-            Drawable icon = iconPack.getDrawableIconForPackage(context, new ComponentName(appInfo.packageName, appInfo.name).toString());
-
-            return icon == null ? appInfo.loadIcon(pm) : icon;
+            String componentName = new ComponentName(appInfo.packageName, appInfo.name).toString();
+
+            if(!useMask) {
+                Drawable icon = iconPack.getDrawableIconForPackage(context, componentName);
+                return icon == null ? appInfo.loadIcon(pm) : icon;
+            } else {
+                Drawable drawable = appInfo.loadIcon(pm);
+                if(drawable instanceof BitmapDrawable) {
+                    return new BitmapDrawable(context.getResources(),
+                            iconPack.getIconForPackage(context, componentName, ((BitmapDrawable) drawable).getBitmap()));
+                } else {
+                    Drawable icon = iconPack.getDrawableIconForPackage(context, componentName);
+                    return icon == null ? drawable : icon;
+                }
+            }
         }
     }
 
index 70a6e94..34b78ad 100644 (file)
     <string name="must_specify_extra">Must specify Intent.EXTRA_PACKAGE_NAME</string>
     <string name="invalid_package_name">Invalid package name</string>
 
+    <string name="pref_title_use_mask">Use masks for unthemed icons</string>
+    <string name="pref_description_use_mask">When an icon pack is set, generate icons unthemed apps using masking images found within the icon pack. (Experimental)</string>
+
 </resources>
index 370bbbf..e01d18d 100644 (file)
     <string name="must_specify_extra">Must specify Intent.EXTRA_PACKAGE_NAME</string>
     <string name="invalid_package_name">Invalid package name</string>
 
+    <string name="pref_title_use_mask">Use masks for unthemed icons</string>
+    <string name="pref_description_use_mask">When an icon pack is set, generate icons unthemed apps using masking images found within the icon pack. (Experimental)</string>
+
 </resources>
index a037754..bcdf7bf 100644 (file)
         android:title="@string/pref_title_hide_when_keyboard_shown"
         android:summary="@string/pref_description_hide_when_keyboard_shown" />
 
+    <CheckBoxPreference
+        android:defaultValue="false"
+        android:key="icon_pack_use_mask"
+        android:title="@string/pref_title_use_mask"
+        android:summary="@string/pref_description_use_mask" />
+
     <Preference
         android:key="clear_pinned_apps"
         android:title="@string/clear_pinned_apps"/>