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

Commit 738e82e1 authored by Yuli Huang's avatar Yuli Huang
Browse files

Fix b/5510870 by saving/restoring Activity states.

1. Filters implement Parcelable for saving/restoring states.
2. Extract Doodle for making doodling paths parcelable.

Change-Id: Ice8e6e068891da8a8f9251e62d95ea755fa99933
parent 13105e73
Loading
Loading
Loading
Loading
+30 −8
Original line number Diff line number Diff line
@@ -17,9 +17,11 @@
package com.android.gallery3d.photoeditor;

import android.graphics.Bitmap;
import android.os.Bundle;

import com.android.gallery3d.photoeditor.filters.Filter;

import java.util.ArrayList;
import java.util.Stack;

/**
@@ -35,6 +37,9 @@ public class FilterStack {
        void onStackChanged(boolean canUndo, boolean canRedo);
    }

    private static final String APPLIED_STACK_KEY = "applied_stack";
    private static final String REDO_STACK_KEY = "redo_stack";

    private final Stack<Filter> appliedStack = new Stack<Filter>();
    private final Stack<Filter> redoStack = new Stack<Filter>();

@@ -45,12 +50,28 @@ public class FilterStack {

    private Photo source;
    private Runnable queuedTopFilterChange;
    private boolean topFilterOutputted;
    private boolean outputTopFilter;
    private volatile boolean paused;

    public FilterStack(PhotoView photoView, StackListener stackListener) {
    public FilterStack(PhotoView photoView, StackListener stackListener, Bundle savedState) {
        this.photoView = photoView;
        this.stackListener = stackListener;
        if (savedState != null) {
            appliedStack.addAll(getFilters(savedState, APPLIED_STACK_KEY));
            redoStack.addAll(getFilters(savedState, REDO_STACK_KEY));
            outputTopFilter = true;
            stackChanged();
       }
    }

    private ArrayList<Filter> getFilters(Bundle savedState, String key) {
        // Infer Filter array-list from the Parcelable array-list by the specified returned type.
        return savedState.getParcelableArrayList(key);
    }

    public void saveStacks(Bundle outState) {
        outState.putParcelableArrayList(APPLIED_STACK_KEY, new ArrayList<Filter>(appliedStack));
        outState.putParcelableArrayList(REDO_STACK_KEY, new ArrayList<Filter>(redoStack));
    }

    private void reallocateBuffer(int target) {
@@ -72,18 +93,19 @@ public class FilterStack {

            // Source photo will be displayed if there is no filter stacked.
            Photo photo = source;
            int size = topFilterOutputted ? appliedStack.size() : appliedStack.size() - 1;
            int size = outputTopFilter ? appliedStack.size() : appliedStack.size() - 1;
            for (int i = 0; i < size && !paused; i++) {
                photo = runFilter(i);
            }
            photoView.setPhoto(photo, topFilterOutputted);
            // Clear photo-view transformation when the top filter will be outputted.
            photoView.setPhoto(photo, outputTopFilter);
        }
    }

    private void invalidateTopFilter() {
        if (!appliedStack.empty()) {
            outputTopFilter = true;
            photoView.setPhoto(runFilter(appliedStack.size() - 1), true);
            topFilterOutputted = true;
        }
    }

@@ -133,12 +155,12 @@ public class FilterStack {
        });
    }

    public void saveBitmap(final OnDoneBitmapCallback callback) {
    public void getOutputBitmap(final OnDoneBitmapCallback callback) {
        photoView.queue(new Runnable() {

            @Override
            public void run() {
                int filterIndex = appliedStack.size() - (topFilterOutputted ? 1 : 2);
                int filterIndex = appliedStack.size() - (outputTopFilter ? 1 : 2);
                Photo photo = (filterIndex < 0) ? source : buffers[getOutBufferIndex(filterIndex)];
                final Bitmap bitmap = (photo != null) ? photo.save() : null;
                photoView.post(new Runnable() {
@@ -166,7 +188,7 @@ public class FilterStack {

    private void pushFilterInternal(Filter filter) {
        appliedStack.push(filter);
        topFilterOutputted = false;
        outputTopFilter = false;
        stackChanged();
    }

+8 −2
Original line number Diff line number Diff line
@@ -53,7 +53,7 @@ public class PhotoEditor extends Activity {
                    public void onStackChanged(boolean canUndo, boolean canRedo) {
                        actionBar.updateButtons(canUndo, canRedo);
                    }
        });
        }, savedInstanceState);

        EffectsBar effectsBar = (EffectsBar) findViewById(R.id.effects_bar);
        effectsBar.initialize(filterStack);
@@ -125,7 +125,7 @@ public class PhotoEditor extends Activity {
                    @Override
                    public void run() {
                        final SpinnerProgressDialog progressDialog = createProgressDialog();
                        filterStack.saveBitmap(new OnDoneBitmapCallback() {
                        filterStack.getOutputBitmap(new OnDoneBitmapCallback() {

                            @Override
                            public void onDone(Bitmap bitmap) {
@@ -199,6 +199,12 @@ public class PhotoEditor extends Activity {
        };
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        filterStack.saveStacks(outState);
    }

    @Override
    public void onBackPressed() {
        actionBar.clickBack();
+1 −1
Original line number Diff line number Diff line
@@ -44,7 +44,7 @@ public class ColorTemperatureAction extends EffectAction {
            @Override
            public void onProgressChanged(float progress, boolean fromUser) {
                if (fromUser) {
                    filter.setColorTemperature(progress);
                    filter.setScale(progress);
                    notifyFilterChanged(filter, true);
                }
            }
+122 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.gallery3d.photoeditor.actions;

import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.RectF;
import android.os.Parcel;
import android.os.Parcelable;

import java.util.Vector;

/**
 * Doodle that consists of a color and doodling path for drawing.
 */
public class Doodle implements Parcelable {

    private final int color;
    private final Path normalizedPath = new Path();
    private final Vector<PointF> points = new Vector<PointF>();

    /**
     * Creates paint for doodles.
     */
    public static Paint createPaint() {
        Paint paint = new Paint(Paint.DITHER_FLAG | Paint.ANTI_ALIAS_FLAG);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeJoin(Paint.Join.ROUND);
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setStrokeWidth(15);
        return paint;
    }

    public Doodle(int color, PointF startPoint) {
        this.color = Color.argb(192, Color.red(color), Color.green(color), Color.blue(color));
        normalizedPath.moveTo(startPoint.x, startPoint.y);
        points.add(startPoint);
    }

    /**
     * Adds control points whose coordinates range from 0 to 1 to construct the doodle path.
     *
     * @return true if the constructed path is in (0, 0, 1, 1) bounds; otherwise, false.
     */
    public boolean addControlPoint(PointF point) {
        PointF last = points.lastElement();
        normalizedPath.quadTo(last.x, last.y, (last.x + point.x) / 2, (last.y + point.y) / 2);
        points.add(point);

        RectF r = new RectF();
        normalizedPath.computeBounds(r, false);
        return r.intersects(0, 0, 1, 1);
    }

    public int getColor() {
        return color;
    }

    public boolean isEmpty() {
        return normalizedPath.isEmpty();
    }

    /**
     * Gets the drawing path from the normalized doodle path.
     */
    public void getDrawingPath(Matrix matrix, Path path) {
        path.set(normalizedPath);
        path.transform(matrix);
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(color);
        dest.writeInt(points.size());
        for (PointF point : points) {
            dest.writeParcelable(point, 0);
        }
    }

    public static final Parcelable.Creator<Doodle> CREATOR = new Parcelable.Creator<Doodle>() {

        @Override
        public Doodle createFromParcel(Parcel source) {
            int color = source.readInt();
            int size = source.readInt();
            if (size > 0) {
                Doodle doodle = new Doodle(color, (PointF) source.readParcelable(null));
                for (int i = 1; i < size; i++) {
                    doodle.addControlPoint((PointF) source.readParcelable(null));
                }
                return doodle;
            }
            return new Doodle(color, new PointF(0, 0));
        }

        @Override
        public Doodle[] newArray(int size) {
            return new Doodle[size];
        }};
}
+2 −3
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
package com.android.gallery3d.photoeditor.actions;

import android.content.Context;
import android.graphics.Path;
import android.util.AttributeSet;

import com.android.gallery3d.photoeditor.filters.DoodleFilter;
@@ -64,8 +63,8 @@ public class DoodleAction extends EffectAction {
            }

            @Override
            public void onDoodleFinished(Path path, int color) {
                filter.addPath(path, color);
            public void onDoodleFinished(Doodle doodle) {
                filter.addDoodle(doodle);
                notifyFilterChanged(filter, false);
            }
        });
Loading