Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 094c82ad authored by ztenghui's avatar ztenghui Committed by Android (Google) Code Review
Browse files

Merge "Scaling (Animated)VectorDrawable inside ImageView" into mnc-dev

parents 3368e69e 35289f12
Loading
Loading
Loading
Loading
+54 −29
Original line number Diff line number Diff line
@@ -200,6 +200,11 @@ public class VectorDrawable extends Drawable {
    private static final int LINEJOIN_ROUND = 1;
    private static final int LINEJOIN_BEVEL = 2;

    // Cap the bitmap size, such that it won't hurt the performance too much
    // and it won't crash due to a very large scale.
    // The drawable will look blurry above this size.
    private static final int MAX_CACHED_BITMAP_SIZE = 2048;

    private static final boolean DBG_VECTOR_DRAWABLE = false;

    private VectorDrawableState mVectorState;
@@ -219,6 +224,11 @@ public class VectorDrawable extends Drawable {
    private int mDpiScaledHeight = 0;
    private Insets mDpiScaleInsets = Insets.NONE;

    // Temp variable, only for saving "new" operation at the draw() time.
    private final float[] mTmpFloats = new float[9];
    private final Matrix mTmpMatrix = new Matrix();
    private final Rect mTmpBounds = new Rect();

    public VectorDrawable() {
        this(null, null);
    }
@@ -262,44 +272,59 @@ public class VectorDrawable extends Drawable {

    @Override
    public void draw(Canvas canvas) {
        final Rect bounds = getBounds();
        if (bounds.width() <= 0 || bounds.height() <= 0) {
        // We will offset the bounds for drawBitmap, so copyBounds() here instead
        // of getBounds().
        copyBounds(mTmpBounds);
        if (mTmpBounds.width() <= 0 || mTmpBounds.height() <= 0) {
            // Nothing to draw
            return;
        }

        // Color filters always override tint filters.
        final ColorFilter colorFilter = (mColorFilter == null ? mTintFilter : mColorFilter);

        // The imageView can scale the canvas in different ways, in order to
        // avoid blurry scaling, we have to draw into a bitmap with exact pixel
        // size first. This bitmap size is determined by the bounds and the
        // canvas scale.
        canvas.getMatrix(mTmpMatrix);
        mTmpMatrix.getValues(mTmpFloats);
        float canvasScaleX = Math.abs(mTmpFloats[Matrix.MSCALE_X]);
        float canvasScaleY = Math.abs(mTmpFloats[Matrix.MSCALE_Y]);
        int scaledWidth = (int) (mTmpBounds.width() * canvasScaleX);
        int scaledHeight = (int) (mTmpBounds.height() * canvasScaleY);
        scaledWidth = Math.min(MAX_CACHED_BITMAP_SIZE, scaledWidth);
        scaledHeight = Math.min(MAX_CACHED_BITMAP_SIZE, scaledHeight);

        if (scaledWidth <= 0 || scaledHeight <= 0) {
            return;
        }

        final int saveCount = canvas.save();
        final boolean needMirroring = needMirroring();
        canvas.translate(mTmpBounds.left, mTmpBounds.top);

        canvas.translate(bounds.left, bounds.top);
        // Handle RTL mirroring.
        final boolean needMirroring = needMirroring();
        if (needMirroring) {
            canvas.translate(bounds.width(), 0);
            canvas.translate(mTmpBounds.width(), 0);
            canvas.scale(-1.0f, 1.0f);
        }

        // Color filters always override tint filters.
        final ColorFilter colorFilter = mColorFilter == null ? mTintFilter : mColorFilter;
        // At this point, canvas has been translated to the right position.
        // And we use this bound for the destination rect for the drawBitmap, so
        // we offset to (0, 0);
        mTmpBounds.offsetTo(0, 0);

        mVectorState.createCachedBitmapIfNeeded(scaledWidth, scaledHeight);
        if (!mAllowCaching) {
            // AnimatedVectorDrawable
            if (!mVectorState.hasTranslucentRoot()) {
                mVectorState.mVPathRenderer.draw(
                        canvas, bounds.width(), bounds.height(), colorFilter);
            mVectorState.updateCachedBitmap(scaledWidth, scaledHeight);
        } else {
                mVectorState.createCachedBitmapIfNeeded(bounds);
                mVectorState.updateCachedBitmap(bounds);
                mVectorState.drawCachedBitmapWithRootAlpha(canvas, colorFilter);
            }
        } else {
            // Static Vector Drawable case.
            mVectorState.createCachedBitmapIfNeeded(bounds);
            if (!mVectorState.canReuseCache()) {
                mVectorState.updateCachedBitmap(bounds);
                mVectorState.updateCachedBitmap(scaledWidth, scaledHeight);
                mVectorState.updateCacheStates();
            }
            mVectorState.drawCachedBitmapWithRootAlpha(canvas, colorFilter);
        }

        mVectorState.drawCachedBitmapWithRootAlpha(canvas, colorFilter, mTmpBounds);
        canvas.restoreToCount(saveCount);
    }

@@ -770,10 +795,11 @@ public class VectorDrawable extends Drawable {
            }
        }

        public void drawCachedBitmapWithRootAlpha(Canvas canvas, ColorFilter filter) {
        public void drawCachedBitmapWithRootAlpha(Canvas canvas, ColorFilter filter,
                Rect originalBounds) {
            // The bitmap's size is the same as the bounds.
            final Paint p = getPaint(filter);
            canvas.drawBitmap(mCachedBitmap, 0, 0, p);
            canvas.drawBitmap(mCachedBitmap, null, originalBounds, p);
        }

        public boolean hasTranslucentRoot() {
@@ -797,16 +823,15 @@ public class VectorDrawable extends Drawable {
            return mTempPaint;
        }

        public void updateCachedBitmap(Rect bounds) {
        public void updateCachedBitmap(int width, int height) {
            mCachedBitmap.eraseColor(Color.TRANSPARENT);
            Canvas tmpCanvas = new Canvas(mCachedBitmap);
            mVPathRenderer.draw(tmpCanvas, bounds.width(), bounds.height(), null);
            mVPathRenderer.draw(tmpCanvas, width, height, null);
        }

        public void createCachedBitmapIfNeeded(Rect bounds) {
            if (mCachedBitmap == null || !canReuseBitmap(bounds.width(),
                    bounds.height())) {
                mCachedBitmap = Bitmap.createBitmap(bounds.width(), bounds.height(),
        public void createCachedBitmapIfNeeded(int width, int height) {
            if (mCachedBitmap == null || !canReuseBitmap(width, height)) {
                mCachedBitmap = Bitmap.createBitmap(width, height,
                        Bitmap.Config.ARGB_8888);
                mCacheDirty = true;
            }
+11 −4
Original line number Diff line number Diff line
@@ -37,8 +37,8 @@ public class ScaleDrawableTests extends Activity {
    };

    protected int icon = R.drawable.bitmap_drawable01;

    protected int vector_icon = R.drawable.vector_drawable16;
    protected int animated_vector_icon = R.drawable.ic_hourglass_animation;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
@@ -46,12 +46,12 @@ public class ScaleDrawableTests extends Activity {
        ScrollView scrollView = new ScrollView(this);
        GridLayout container = new GridLayout(this);
        scrollView.addView(container);
        container.setColumnCount(3);
        container.setColumnCount(4);
        container.setBackgroundColor(0xFF888888);

        LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
        params.width = 400;
        params.height = 300;
        params.width = 300;
        params.height = 200;

        for (int i = 0; i < scaleTypes.length; i++) {
            TextView t = new TextView(this);
@@ -71,6 +71,13 @@ public class ScaleDrawableTests extends Activity {
            view.setScaleType(scaleType);
            view.setImageResource(vector_icon);
            container.addView(view);

            ImageView avd_view = new ImageView(this);
            avd_view.setLayoutParams(params);
            avd_view.setScaleType(scaleType);
            avd_view.setImageResource(animated_vector_icon);
            container.addView(avd_view);

        }

        setContentView(scrollView);