Home | History | Annotate | Download | only in ui
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.gallery3d.ui;
     18 
     19 import android.graphics.Rect;
     20 import android.graphics.RectF;
     21 import android.view.animation.DecelerateInterpolator;
     22 import android.view.animation.Interpolator;
     23 
     24 import com.android.gallery3d.anim.Animation;
     25 import com.android.gallery3d.data.Path;
     26 import com.android.gallery3d.ui.AlbumSlotRenderer.SlotFilter;
     27 
     28 import java.util.ArrayList;
     29 
     30 public class PhotoFallbackEffect extends Animation implements SlotFilter {
     31 
     32     private static final int ANIM_DURATION = 300;
     33     private static final Interpolator ANIM_INTERPOLATE = new DecelerateInterpolator(1.5f);
     34 
     35     public static class Entry {
     36         public int index;
     37         public Path path;
     38         public Rect source;
     39         public Rect dest;
     40         public RawTexture texture;
     41 
     42         public Entry(Path path, Rect source, RawTexture texture) {
     43             this.path = path;
     44             this.source = source;
     45             this.texture = texture;
     46         }
     47     }
     48 
     49     public interface PositionProvider {
     50         public Rect getPosition(int index);
     51         public int getItemIndex(Path path);
     52     }
     53 
     54     private RectF mSource = new RectF();
     55     private RectF mTarget = new RectF();
     56     private float mProgress;
     57     private PositionProvider mPositionProvider;
     58 
     59     private ArrayList<Entry> mList = new ArrayList<Entry>();
     60 
     61     public PhotoFallbackEffect() {
     62         setDuration(ANIM_DURATION);
     63         setInterpolator(ANIM_INTERPOLATE);
     64     }
     65 
     66     public void addEntry(Path path, Rect rect, RawTexture texture) {
     67         mList.add(new Entry(path, rect, texture));
     68     }
     69 
     70     public Entry getEntry(Path path) {
     71         for (int i = 0, n = mList.size(); i < n; ++i) {
     72             Entry entry = mList.get(i);
     73             if (entry.path == path) return entry;
     74         }
     75         return null;
     76     }
     77 
     78     public boolean draw(GLCanvas canvas) {
     79         boolean more = calculate(AnimationTime.get());
     80         for (int i = 0, n = mList.size(); i < n; ++i) {
     81             Entry entry = mList.get(i);
     82             if (entry.index < 0) continue;
     83             entry.dest = mPositionProvider.getPosition(entry.index);
     84             drawEntry(canvas, entry);
     85         }
     86         return more;
     87     }
     88 
     89     private void drawEntry(GLCanvas canvas, Entry entry) {
     90         if (!entry.texture.isLoaded()) return;
     91 
     92         int w = entry.texture.getWidth();
     93         int h = entry.texture.getHeight();
     94 
     95         Rect s = entry.source;
     96         Rect d = entry.dest;
     97 
     98         // the following calculation is based on d.width() == d.height()
     99 
    100         float p = mProgress;
    101 
    102         float fullScale = (float) d.height() / Math.min(s.width(), s.height());
    103         float scale = fullScale * p + 1 * (1 - p);
    104 
    105         float cx = d.centerX() * p + s.centerX() * (1 - p);
    106         float cy = d.centerY() * p + s.centerY() * (1 - p);
    107 
    108         float ch = s.height() * scale;
    109         float cw = s.width() * scale;
    110 
    111         if (w > h) {
    112             // draw the center part
    113             mTarget.set(cx - ch / 2, cy - ch / 2, cx + ch / 2, cy + ch / 2);
    114             mSource.set((w - h) / 2, 0, (w + h) / 2, h);
    115             canvas.drawTexture(entry.texture, mSource, mTarget);
    116 
    117             canvas.save(GLCanvas.SAVE_FLAG_ALPHA);
    118             canvas.multiplyAlpha(1 - p);
    119 
    120             // draw the left part
    121             mTarget.set(cx - cw / 2, cy - ch / 2, cx - ch / 2, cy + ch / 2);
    122             mSource.set(0, 0, (w - h) / 2, h);
    123             canvas.drawTexture(entry.texture, mSource, mTarget);
    124 
    125             // draw the right part
    126             mTarget.set(cx + ch / 2, cy - ch / 2, cx + cw / 2, cy + ch / 2);
    127             mSource.set((w + h) / 2, 0, w, h);
    128             canvas.drawTexture(entry.texture, mSource, mTarget);
    129 
    130             canvas.restore();
    131         } else {
    132             // draw the center part
    133             mTarget.set(cx - cw / 2, cy - cw / 2, cx + cw / 2, cy + cw / 2);
    134             mSource.set(0, (h - w) / 2, w, (h + w) / 2);
    135             canvas.drawTexture(entry.texture, mSource, mTarget);
    136 
    137             canvas.save(GLCanvas.SAVE_FLAG_ALPHA);
    138             canvas.multiplyAlpha(1 - p);
    139 
    140             // draw the upper part
    141             mTarget.set(cx - cw / 2, cy - ch / 2, cx + cw / 2, cy - cw / 2);
    142             mSource.set(0, 0, w, (h - w) / 2);
    143             canvas.drawTexture(entry.texture, mSource, mTarget);
    144 
    145             // draw the bottom part
    146             mTarget.set(cx - cw / 2, cy + cw / 2, cx + cw / 2, cy + ch / 2);
    147             mSource.set(0, (w + h) / 2, w, h);
    148             canvas.drawTexture(entry.texture, mSource, mTarget);
    149 
    150             canvas.restore();
    151         }
    152     }
    153 
    154     @Override
    155     protected void onCalculate(float progress) {
    156         mProgress = progress;
    157     }
    158 
    159     public void setPositionProvider(PositionProvider provider) {
    160         mPositionProvider = provider;
    161         if (mPositionProvider != null) {
    162             for (int i = 0, n = mList.size(); i < n; ++i) {
    163                 Entry entry = mList.get(i);
    164                 entry.index = mPositionProvider.getItemIndex(entry.path);
    165             }
    166         }
    167     }
    168 
    169     @Override
    170     public boolean acceptSlot(int index) {
    171         for (int i = 0, n = mList.size(); i < n; ++i) {
    172             Entry entry = mList.get(i);
    173             if (entry.index == index) return false;
    174         }
    175         return true;
    176     }
    177 }
    178