10f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh/* 20f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh * Copyright (C) 2010 The Android Open Source Project 30f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh * 40f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh * Licensed under the Apache License, Version 2.0 (the "License"); 50f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh * you may not use this file except in compliance with the License. 60f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh * You may obtain a copy of the License at 70f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh * 80f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh * http://www.apache.org/licenses/LICENSE-2.0 90f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh * 100f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh * Unless required by applicable law or agreed to in writing, software 110f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh * distributed under the License is distributed on an "AS IS" BASIS, 120f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh * See the License for the specific language governing permissions and 140f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh * limitations under the License. 150f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh */ 160f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 170f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsiehpackage com.android.photoeditor; 180f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 190f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsiehimport android.graphics.Bitmap; 200f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsiehimport android.os.Handler; 210f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsiehimport android.os.HandlerThread; 220f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsiehimport android.os.Message; 230f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 240f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsiehimport com.android.photoeditor.filters.Filter; 250f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 260f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsiehimport java.util.Stack; 270f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsiehimport java.util.Vector; 280f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 290f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh/** 300f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh * A stack of filters to be applied onto a photo. 310f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh */ 320f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsiehpublic class FilterStack { 330f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 340f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh /** 350f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh * Listener of stack changes. 360f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh */ 370f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh public interface StackListener { 380f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 390f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh void onStackChanged(boolean canUndo, boolean canRedo); 400f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh } 410f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 420f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh private static class OutputMessageObj { 430f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh PhotoOutputCallback callback; 440f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh Photo result; 450f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh } 460f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 470f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh private static final int COPY_SOURCE = 1; 480f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh private static final int COPY_RESULT = 2; 490f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh private static final int SET_SOURCE = 3; 500f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh private static final int CLEAR_SOURCE = 4; 510f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh private static final int CLEAR_STACKS = 5; 520f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh private static final int PUSH_FILTER = 6; 530f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh private static final int UNDO = 7; 540f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh private static final int REDO = 8; 550f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh private static final int TOP_FILTER_CHANGE = 9; 560f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh private static final int OUTPUT = 10; 570f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 580f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh private final Stack<Filter> appliedStack = new Stack<Filter>(); 590f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh private final Stack<Filter> redoStack = new Stack<Filter>(); 600f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh private final Vector<Message> pendingMessages = new Vector<Message>(); 610f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh private final Handler mainHandler; 620f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh private final Handler workerHandler; 630f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 640f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh // Use two photo buffers as in and out in turns to apply filters in the stack. 650f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh private final Photo[] buffers = new Photo[2]; 660f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 670f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh private Photo source; 680f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh private StackListener stackListener; 690f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 700f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh public FilterStack() { 710f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh HandlerThread workerThread = new HandlerThread("FilterStackWorker"); 720f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh workerThread.start(); 730f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 740f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh mainHandler = new Handler() { 750f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 760f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh @Override 770f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh public void handleMessage(Message msg) { 780f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh switch (msg.what) { 790f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh case OUTPUT: 800f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh OutputMessageObj obj = (OutputMessageObj) msg.obj; 810f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh obj.callback.onReady(obj.result); 820f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh break; 830f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh } 840f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh } 850f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh }; 860f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh workerHandler = new Handler(workerThread.getLooper()) { 870f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 880f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh private void output(PhotoOutputCallback callback, Photo target) { 890f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh // Copy target photo in rgb-565 format to update photo-view or save. 900f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh OutputMessageObj obj = new OutputMessageObj(); 910f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh obj.callback = callback; 920f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh obj.result = (target != null) ? target.copy(Bitmap.Config.RGB_565) : null; 930f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh mainHandler.sendMessage(mainHandler.obtainMessage(OUTPUT, obj)); 940f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh } 950f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 960f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh private void clearBuffers() { 970f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh pendingMessages.clear(); 980f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh workerHandler.removeMessages(TOP_FILTER_CHANGE); 990f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh mainHandler.removeMessages(OUTPUT); 1000f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh for (int i = 0; i < buffers.length; i++) { 1010f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh if (buffers[i] != null) { 1020f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh buffers[i].clear(); 1030f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh buffers[i] = null; 1040f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh } 1050f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh } 1060f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh } 1070f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 1080f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh private void reallocateBuffer(int target) { 1090f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh int other = target ^ 1; 1100f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh buffers[target] = Photo.create(Bitmap.createBitmap( 1110f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh buffers[other].width(), buffers[other].height(), Bitmap.Config.ARGB_8888)); 1120f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh } 1130f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 1140f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh private void invalidate() { 1150f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh // In/out buffers need redrawn by reloading source photo and re-applying filters. 1160f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh clearBuffers(); 1170f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh buffers[0] = (source != null) ? source.copy(Bitmap.Config.ARGB_8888) : null; 1180f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh if (buffers[0] != null) { 1190f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh reallocateBuffer(1); 1200f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 1210f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh int out = 1; 1220f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh for (Filter filter : appliedStack) { 1230f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh runFilter(filter, out); 1240f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh out = out ^ 1; 1250f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh } 1260f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh } 1270f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh } 1280f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 1290f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh private void runFilter(Filter filter, int out) { 1300f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh if ((buffers[0] != null) && (buffers[1] != null)) { 1310f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh int in = out ^ 1; 1320f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh filter.process(buffers[in], buffers[out]); 1330f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh if (!buffers[in].matchDimension(buffers[out])) { 1340f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh buffers[in].clear(); 1350f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh reallocateBuffer(in); 1360f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh } 1370f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh } 1380f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh } 1390f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 1400f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh private int getOutBufferIndex() { 1410f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh // buffers[0] and buffers[1] are swapped in turns as the in/out buffers for 1420f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh // processing stacked filters. For example, the first filter reads buffer[0] and 1430f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh // writes buffer[1]; the second filter then reads buffer[1] and writes buffer[0]. 1440f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh return appliedStack.size() % 2; 1450f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh } 1460f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 1470f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh @Override 1480f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh public void handleMessage(Message msg) { 1490f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh switch (msg.what) { 1500f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh case COPY_SOURCE: 1510f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh output((PhotoOutputCallback) msg.obj, source); 1520f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh break; 1530f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 1540f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh case COPY_RESULT: 1550f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh output((PhotoOutputCallback) msg.obj, buffers[getOutBufferIndex()]); 1560f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh break; 1570f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 1580f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh case SET_SOURCE: 1590f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh source = (Photo) msg.obj; 1600f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh invalidate(); 1610f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh break; 1620f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 1630f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh case CLEAR_SOURCE: 1640f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh if (source != null) { 1650f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh source.clear(); 1660f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh source = null; 1670f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh } 1680f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh clearBuffers(); 1690f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh break; 1700f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 1710f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh case CLEAR_STACKS: 1720f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh redoStack.clear(); 1730f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh appliedStack.clear(); 1740f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh break; 1750f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 1760f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh case PUSH_FILTER: 1770f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh redoStack.clear(); 1780f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh appliedStack.push((Filter) msg.obj); 1790f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh stackChanged(); 1800f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh break; 1810f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 1820f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh case UNDO: 1830f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh if (!appliedStack.empty()) { 1840f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh redoStack.push(appliedStack.pop()); 1850f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh stackChanged(); 1860f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh invalidate(); 1870f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh } 1880f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh output((PhotoOutputCallback) msg.obj, buffers[getOutBufferIndex()]); 1890f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh break; 1900f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 1910f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh case REDO: 1920f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh if (!redoStack.empty()) { 1930f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh Filter filter = redoStack.pop(); 1940f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh appliedStack.push(filter); 1950f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh stackChanged(); 1960f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh runFilter(filter, getOutBufferIndex()); 1970f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh } 1980f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh output((PhotoOutputCallback) msg.obj, buffers[getOutBufferIndex()]); 1990f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh break; 2000f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 2010f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh case TOP_FILTER_CHANGE: 2020f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh if (pendingMessages.remove(msg) && !appliedStack.empty()) { 2030f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh int out = getOutBufferIndex(); 2040f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh runFilter(appliedStack.peek(), out); 2050f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh output((PhotoOutputCallback) msg.obj, buffers[out]); 2060f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh } 2070f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh break; 2080f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh } 2090f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh } 2100f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh }; 2110f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh } 2120f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 2130f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh public void getSourceCopy(PhotoOutputCallback callback) { 2140f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh workerHandler.sendMessage(workerHandler.obtainMessage(COPY_SOURCE, callback)); 2150f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh } 2160f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 2170f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh public void getResultCopy(PhotoOutputCallback callback) { 2180f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh workerHandler.sendMessage(workerHandler.obtainMessage(COPY_RESULT, callback)); 2190f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh } 2200f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 2210f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh public void setPhotoSource(Photo source) { 2220f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh workerHandler.sendMessage(workerHandler.obtainMessage(SET_SOURCE, source)); 2230f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh } 2240f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 2250f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh public void clearPhotoSource() { 2260f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh workerHandler.sendMessage(workerHandler.obtainMessage(CLEAR_SOURCE)); 2270f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh } 2280f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 2290f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh public void clearStacks() { 2300f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh workerHandler.sendMessage(workerHandler.obtainMessage(CLEAR_STACKS)); 2310f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh } 2320f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 2330f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh public void pushFilter(Filter filter) { 2340f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh workerHandler.sendMessage(workerHandler.obtainMessage(PUSH_FILTER, filter)); 2350f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh } 2360f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 2370f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh public void undo(PhotoOutputCallback callback) { 2380f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh workerHandler.sendMessage(workerHandler.obtainMessage(UNDO, callback)); 2390f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh } 2400f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 2410f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh public void redo(PhotoOutputCallback callback) { 2420f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh workerHandler.sendMessage(workerHandler.obtainMessage(REDO, callback)); 2430f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh } 2440f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 2450f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh public void topFilterChanged(PhotoOutputCallback callback) { 2460f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh // Flush outdated top-filter messages before sending new ones. 2470f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh Message msg = workerHandler.obtainMessage(TOP_FILTER_CHANGE, callback); 2480f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh pendingMessages.clear(); 2490f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh pendingMessages.add(msg); 2500f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh workerHandler.removeMessages(TOP_FILTER_CHANGE); 2510f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh workerHandler.sendMessage(msg); 2520f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh } 2530f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 2540f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh public synchronized void setStackListener(StackListener listener) { 2550f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh stackListener = listener; 2560f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh } 2570f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh 2580f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh private synchronized void stackChanged() { 2590f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh if (stackListener != null) { 2600f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh stackListener.onStackChanged(!appliedStack.empty(), !redoStack.empty()); 2610f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh } 2620f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh } 2630f8a40e4cfdc5f6cd47c22e81f69ed0446067c54Andrew Hsieh} 264