blob: 3ca09ab968d4f5ebb72f25e81e0e72972e19dfcc [file] [log] [blame]
/*
* 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.ui;
import android.graphics.Rect;
import android.graphics.RectF;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import com.android.gallery3d.anim.Animation;
import com.android.gallery3d.data.Path;
import com.android.gallery3d.ui.AlbumSlotRenderer.SlotFilter;
import java.util.ArrayList;
public class PhotoFallbackEffect extends Animation implements SlotFilter {
private static final int ANIM_DURATION = 300;
private static final Interpolator ANIM_INTERPOLATE = new DecelerateInterpolator(1.5f);
public static class Entry {
public int index;
public Path path;
public Rect source;
public Rect dest;
public RawTexture texture;
public Entry(Path path, Rect source, RawTexture texture) {
this.path = path;
this.source = source;
this.texture = texture;
}
}
public interface PositionProvider {
public Rect getPosition(int index);
public int getItemIndex(Path path);
}
private RectF mSource = new RectF();
private RectF mTarget = new RectF();
private float mProgress;
private PositionProvider mPositionProvider;
private ArrayList<Entry> mList = new ArrayList<Entry>();
public PhotoFallbackEffect() {
setDuration(ANIM_DURATION);
setInterpolator(ANIM_INTERPOLATE);
}
public void addEntry(Path path, Rect rect, RawTexture texture) {
mList.add(new Entry(path, rect, texture));
}
public Entry getEntry(Path path) {
for (int i = 0, n = mList.size(); i < n; ++i) {
Entry entry = mList.get(i);
if (entry.path == path) return entry;
}
return null;
}
public boolean draw(GLCanvas canvas) {
boolean more = calculate(AnimationTime.get());
for (int i = 0, n = mList.size(); i < n; ++i) {
Entry entry = mList.get(i);
if (entry.index < 0) continue;
entry.dest = mPositionProvider.getPosition(entry.index);
drawEntry(canvas, entry);
}
return more;
}
private void drawEntry(GLCanvas canvas, Entry entry) {
if (!entry.texture.isLoaded()) return;
int w = entry.texture.getWidth();
int h = entry.texture.getHeight();
Rect s = entry.source;
Rect d = entry.dest;
// the following calculation is based on d.width() == d.height()
float p = mProgress;
float fullScale = (float) d.height() / Math.min(s.width(), s.height());
float scale = fullScale * p + 1 * (1 - p);
float cx = d.centerX() * p + s.centerX() * (1 - p);
float cy = d.centerY() * p + s.centerY() * (1 - p);
float ch = s.height() * scale;
float cw = s.width() * scale;
if (w > h) {
// draw the center part
mTarget.set(cx - ch / 2, cy - ch / 2, cx + ch / 2, cy + ch / 2);
mSource.set((w - h) / 2, 0, (w + h) / 2, h);
canvas.drawTexture(entry.texture, mSource, mTarget);
canvas.save(GLCanvas.SAVE_FLAG_ALPHA);
canvas.multiplyAlpha(1 - p);
// draw the left part
mTarget.set(cx - cw / 2, cy - ch / 2, cx - ch / 2, cy + ch / 2);
mSource.set(0, 0, (w - h) / 2, h);
canvas.drawTexture(entry.texture, mSource, mTarget);
// draw the right part
mTarget.set(cx + ch / 2, cy - ch / 2, cx + cw / 2, cy + ch / 2);
mSource.set((w + h) / 2, 0, w, h);
canvas.drawTexture(entry.texture, mSource, mTarget);
canvas.restore();
} else {
// draw the center part
mTarget.set(cx - cw / 2, cy - cw / 2, cx + cw / 2, cy + cw / 2);
mSource.set(0, (h - w) / 2, w, (h + w) / 2);
canvas.drawTexture(entry.texture, mSource, mTarget);
canvas.save(GLCanvas.SAVE_FLAG_ALPHA);
canvas.multiplyAlpha(1 - p);
// draw the upper part
mTarget.set(cx - cw / 2, cy - ch / 2, cx + cw / 2, cy - cw / 2);
mSource.set(0, 0, w, (h - w) / 2);
canvas.drawTexture(entry.texture, mSource, mTarget);
// draw the bottom part
mTarget.set(cx - cw / 2, cy + cw / 2, cx + cw / 2, cy + ch / 2);
mSource.set(0, (w + h) / 2, w, h);
canvas.drawTexture(entry.texture, mSource, mTarget);
canvas.restore();
}
}
@Override
protected void onCalculate(float progress) {
mProgress = progress;
}
public void setPositionProvider(PositionProvider provider) {
mPositionProvider = provider;
if (mPositionProvider != null) {
for (int i = 0, n = mList.size(); i < n; ++i) {
Entry entry = mList.get(i);
entry.index = mPositionProvider.getItemIndex(entry.path);
}
}
}
@Override
public boolean acceptSlot(int index) {
for (int i = 0, n = mList.size(); i < n; ++i) {
Entry entry = mList.get(i);
if (entry.index == index) return false;
}
return true;
}
}