package cn.lankton.anyshape;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Path;
import android.os.AsyncTask;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by taofangxin on 16/3/24.
 */
public class PathManager {
    private Map<Integer,PathInfo> pathMap = new HashMap<>();
    private static PathManager instance = null;

    // the limit for bitmap of masks.used for avoiding OOM
    public static final int maskLimitedWidth = 600;
    public static final int maskLimitedHeight = 600;

    public static synchronized PathManager getInstance() {
        if (null == instance) {
            instance = new PathManager();
        }
        return instance;
    }

    public void addPathInfo(int resId, PathInfo pi) {
        pathMap.put(resId, pi);
    }

    public PathInfo getPathInfo(int resId) {
        return pathMap.get(resId);
    }

    /**
     * get the path from a mask bitmap
     * @param mask
     * @return
     */
    public Path getPathFromBitmap(Bitmap mask) {
        Path path = new Path();
        int bWidth = mask.getWidth();
        int bHeight = mask.getHeight();
        int[] origin = new int[bWidth];
        int lastA;
        for (int i = 0; i < bHeight; i++) {
            mask.getPixels(origin, 0, bWidth, 0, i, bWidth, 1);
            lastA = 0;
            for (int j = 0; j < bWidth; j++) {
                int a = Color.alpha(origin[j]);
                if (a != 0 && lastA == 0) {
                    path.moveTo(j, i);
                } else if (a == 0 && lastA !=0 ) {
                    path.lineTo(j - 1, i);
                } else if (a != 0 && j == bWidth - 1) {
                    path.lineTo(j, i);
                }
                lastA = a;
            }
        }
        return path;
    }

    /**
     * Asynchronous method to init paths by resourceids, using the default limit
     * @param context
     * @param resList
     */
    public void createPaths(Context context, List<Integer> resList) {
        for (Integer resId : resList) {
            if (resId > 0) {
                PathAsyncTask task = new PathAsyncTask(context, maskLimitedWidth, maskLimitedHeight);
                task.execute(resId);
            }
        }
    }

    /**
     * Asynchronous method to init paths by resourceids, using the self-defined limit
     * @param context
     * @param resList
     * @param limitedWidth the limt you set for mask width
     * @param limitedHeight the limit you set for mask height
     */
    public void createPaths(Context context, List<Integer> resList, int limitedWidth, int limitedHeight) {
        for (Integer resId : resList) {
            if (resId > 0) {
                PathAsyncTask task = new PathAsyncTask(context, limitedWidth, limitedHeight);
                task.execute(resId);
            }
        }
    }

    class PathAsyncTask extends AsyncTask <Integer, Void, Path> {
        private Context context;
        private int limitedWidth = 600;
        private int limitedHeight = 600;
        public PathAsyncTask(Context context, int limitedWidth, int limitedHeight){
            super();
            this.context = context;
            this.limitedWidth = limitedWidth;
            this.limitedHeight = limitedHeight;
        }

        @Override
        protected Path doInBackground(Integer... params) {
            int resId = params[0];
            PathInfo pi = new PathInfo();
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeResource(context.getResources(), resId, options);
            int widthRatio = (int)(options.outWidth * 1f / this.limitedWidth + 0.5);
            int heightRatio = (int)(options.outHeight * 1f / this.limitedHeight + 0.5);
            if (widthRatio > heightRatio) {
                options.inSampleSize = widthRatio;
            } else {
                options.inSampleSize = heightRatio;
            }
            if (options.inSampleSize == 0) {
                options.inSampleSize = 1;
            }
            options.inJustDecodeBounds = false;
            Bitmap maskBitmap = BitmapFactory.decodeResource(context.getResources(), resId, options);
            pi.path = PathManager.getInstance().getPathFromBitmap(maskBitmap);
            pi.width = maskBitmap.getWidth();
            pi.height = maskBitmap.getHeight();
            //creating is done, add the path info into the cache
            PathManager.getInstance().addPathInfo(resId, pi);
            maskBitmap.recycle();
            return null;
        }

    }
}

@@ -42,94 +42,23 @@
 oid.
-content.Context;%0Aimport android.graphics.Bitmap;%0Aimport android.graphics.BitmapFactory
+graphics.Bitmap
 ;%0Aim
@@ -119,37 +119,8 @@
 ath;
-%0Aimport android.os.AsyncTask;
 %0A%0Aim
@@ -147,31 +147,8 @@
 ap;%0A
-import java.util.List;%0A
 impo
@@ -352,172 +352,8 @@
 l;%0A%0A
-    // the limit for bitmap of masks.used for avoiding OOM%0A    public static final int maskLimitedWidth = 600;%0A    public static final int maskLimitedHeight = 600;%0A
 %0A   
@@ -1610,2825 +1610,6 @@
  %7D%0A%0A
-    /**%0A     * Asynchronous method to init paths by resourceids, using the default limit%0A     * @param context%0A     * @param resList%0A     */%0A    public void createPaths(Context context, List%3CInteger%3E resList) %7B%0A        for (Integer resId : resList) %7B%0A            if (resId %3E 0) %7B%0A                PathAsyncTask task = new PathAsyncTask(context, maskLimitedWidth, maskLimitedHeight);%0A                task.execute(resId);%0A            %7D%0A        %7D%0A    %7D%0A%0A    /**%0A     * Asynchronous method to init paths by resourceids, using the self-defined limit%0A     * @param context%0A     * @param resList%0A     * @param limitedWidth the limt you set for mask width%0A     * @param limitedHeight the limit you set for mask height%0A     */%0A    public void createPaths(Context context, List%3CInteger%3E resList, int limitedWidth, int limitedHeight) %7B%0A        for (Integer resId : resList) %7B%0A            if (resId %3E 0) %7B%0A                PathAsyncTask task = new PathAsyncTask(context, limitedWidth, limitedHeight);%0A                task.execute(resId);%0A            %7D%0A        %7D%0A    %7D%0A%0A    class PathAsyncTask extends AsyncTask %3CInteger, Void, Path%3E %7B%0A        private Context context;%0A        private int limitedWidth = 600;%0A        private int limitedHeight = 600;%0A        public PathAsyncTask(Context context, int limitedWidth, int limitedHeight)%7B%0A            super();%0A            this.context = context;%0A            this.limitedWidth = limitedWidth;%0A            this.limitedHeight = limitedHeight;%0A        %7D%0A%0A        @Override%0A        protected Path doInBackground(Integer... params) %7B%0A            int resId = params%5B0%5D;%0A            PathInfo pi = new PathInfo();%0A            BitmapFactory.Options options = new BitmapFactory.Options();%0A            options.inJustDecodeBounds = true;%0A            BitmapFactory.decodeResource(context.getResources(), resId, options);%0A            int widthRatio = (int)(options.outWidth * 1f / this.limitedWidth + 0.5);%0A            int heightRatio = (int)(options.outHeight * 1f / this.limitedHeight + 0.5);%0A            if (widthRatio %3E heightRatio) %7B%0A                options.inSampleSize = widthRatio;%0A            %7D else %7B%0A                options.inSampleSize = heightRatio;%0A            %7D%0A            if (options.inSampleSize == 0) %7B%0A                options.inSampleSize = 1;%0A            %7D%0A            options.inJustDecodeBounds = false;%0A            Bitmap maskBitmap = BitmapFactory.decodeResource(context.getResources(), resId, options);%0A            pi.path = PathManager.getInstance().getPathFromBitmap(maskBitmap);%0A            pi.width = maskBitmap.getWidth();%0A            pi.height = maskBitmap.getHeight();%0A            //creating is done, add the path info into the cache%0A            PathManager.getInstance().addPathInfo(resId, pi);%0A            maskBitmap.recycle();%0A            return null;%0A        %7D%0A%0A    %7D%0A
 %7D%0A

remove unnessesary function -- PathManager.createPaths