content: /*
   * Copyright (C) 2006 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 android.view.animation;
  
  import android.content.Context;
  import android.content.res.Resources;
  import android.content.res.TypedArray;
  import android.util.AttributeSet;
  import android.util.TypedValue;
  
  /**
   * An animation that controls the scale of an object. You can specify the point
   * to use for the center of scaling.
   * 
   */
  public class ScaleAnimation extends Animation {
      private final Resources mResources;
  
      private float mFromX;
      private float mToX;
      private float mFromY;
      private float mToY;
  
      private int mFromXType = TypedValue.TYPE_NULL;
      private int mToXType = TypedValue.TYPE_NULL;
      private int mFromYType = TypedValue.TYPE_NULL;
      private int mToYType = TypedValue.TYPE_NULL;
  
      private int mFromXData = 0;
      private int mToXData = 0;
      private int mFromYData = 0;
      private int mToYData = 0;
  
      private int mPivotXType = ABSOLUTE;
      private int mPivotYType = ABSOLUTE;
      private float mPivotXValue = 0.0f;
      private float mPivotYValue = 0.0f;
  
      private float mPivotX;
      private float mPivotY;
  
      /**
       * Constructor used when a ScaleAnimation is loaded from a resource.
       * 
       * @param context Application context to use
       * @param attrs Attribute set from which to read values
       */
      public ScaleAnimation(Context context, AttributeSet attrs) {
          super(context, attrs);
  
          mResources = context.getResources();
  
          TypedArray a = context.obtainStyledAttributes(attrs,
                  com.android.internal.R.styleable.ScaleAnimation);
  
          TypedValue tv = a.peekValue(
                  com.android.internal.R.styleable.ScaleAnimation_fromXScale);
          mFromX = 0.0f;
          if (tv != null) {
              if (tv.type == TypedValue.TYPE_FLOAT) {
                  // This is a scaling factor.
                  mFromX = tv.getFloat();
              } else {
                  mFromXType = tv.type;
                  mFromXData = tv.data;
              }
          }
          tv = a.peekValue(
                  com.android.internal.R.styleable.ScaleAnimation_toXScale);
          mToX = 0.0f;
          if (tv != null) {
              if (tv.type == TypedValue.TYPE_FLOAT) {
                  // This is a scaling factor.
                  mToX = tv.getFloat();
              } else {
                  mToXType = tv.type;
                  mToXData = tv.data;
              }
          }
  
          tv = a.peekValue(
                  com.android.internal.R.styleable.ScaleAnimation_fromYScale);
          mFromY = 0.0f;
          if (tv != null) {
              if (tv.type == TypedValue.TYPE_FLOAT) {
                  // This is a scaling factor.
                  mFromY = tv.getFloat();
              } else {
                  mFromYType = tv.type;
                  mFromYData = tv.data;
              }
          }
          tv = a.peekValue(
                  com.android.internal.R.styleable.ScaleAnimation_toYScale);
          mToY = 0.0f;
          if (tv != null) {
              if (tv.type == TypedValue.TYPE_FLOAT) {
                  // This is a scaling factor.
                  mToY = tv.getFloat();
              } else {
                  mToYType = tv.type;
                  mToYData = tv.data;
              }
          }
  
          Description d = Description.parseValue(a.peekValue(
                  com.android.internal.R.styleable.ScaleAnimation_pivotX));
          mPivotXType = d.type;
          mPivotXValue = d.value;
  
          d = Description.parseValue(a.peekValue(
              com.android.internal.R.styleable.ScaleAnimation_pivotY));
          mPivotYType = d.type;
          mPivotYValue = d.value;
  
          a.recycle();
  
          initializePivotPoint();
      }
  
      /**
       * Constructor to use when building a ScaleAnimation from code
       * 
       * @param fromX Horizontal scaling factor to apply at the start of the
       *        animation
       * @param toX Horizontal scaling factor to apply at the end of the animation
       * @param fromY Vertical scaling factor to apply at the start of the
       *        animation
       * @param toY Vertical scaling factor to apply at the end of the animation
       */
      public ScaleAnimation(float fromX, float toX, float fromY, float toY) {
          mResources = null;
          mFromX = fromX;
          mToX = toX;
          mFromY = fromY;
          mToY = toY;
          mPivotX = 0;
          mPivotY = 0;
      }
  
      /**
       * Constructor to use when building a ScaleAnimation from code
       * 
       * @param fromX Horizontal scaling factor to apply at the start of the
       *        animation
       * @param toX Horizontal scaling factor to apply at the end of the animation
       * @param fromY Vertical scaling factor to apply at the start of the
       *        animation
       * @param toY Vertical scaling factor to apply at the end of the animation
       * @param pivotX The X coordinate of the point about which the object is
       *        being scaled, specified as an absolute number where 0 is the left
       *        edge. (This point remains fixed while the object changes size.)
       * @param pivotY The Y coordinate of the point about which the object is
       *        being scaled, specified as an absolute number where 0 is the top
       *        edge. (This point remains fixed while the object changes size.)
       */
      public ScaleAnimation(float fromX, float toX, float fromY, float toY,
              float pivotX, float pivotY) {
          mResources = null;
          mFromX = fromX;
          mToX = toX;
          mFromY = fromY;
          mToY = toY;
  
          mPivotXType = ABSOLUTE;
          mPivotYType = ABSOLUTE;
          mPivotXValue = pivotX;
          mPivotYValue = pivotY;
          initializePivotPoint();
      }
  
      /**
       * Constructor to use when building a ScaleAnimation from code
       * 
       * @param fromX Horizontal scaling factor to apply at the start of the
       *        animation
       * @param toX Horizontal scaling factor to apply at the end of the animation
       * @param fromY Vertical scaling factor to apply at the start of the
       *        animation
       * @param toY Vertical scaling factor to apply at the end of the animation
       * @param pivotXType Specifies how pivotXValue should be interpreted. One of
       *        Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
       *        Animation.RELATIVE_TO_PARENT.
       * @param pivotXValue The X coordinate of the point about which the object
       *        is being scaled, specified as an absolute number where 0 is the
       *        left edge. (This point remains fixed while the object changes
       *        size.) This value can either be an absolute number if pivotXType
       *        is ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise.
       * @param pivotYType Specifies how pivotYValue should be interpreted. One of
       *        Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
       *        Animation.RELATIVE_TO_PARENT.
       * @param pivotYValue The Y coordinate of the point about which the object
       *        is being scaled, specified as an absolute number where 0 is the
       *        top edge. (This point remains fixed while the object changes
       *        size.) This value can either be an absolute number if pivotYType
       *        is ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise.
       */
      public ScaleAnimation(float fromX, float toX, float fromY, float toY,
              int pivotXType, float pivotXValue, int pivotYType, float pivotYValue) {
          mResources = null;
          mFromX = fromX;
          mToX = toX;
          mFromY = fromY;
          mToY = toY;
  
          mPivotXValue = pivotXValue;
          mPivotXType = pivotXType;
          mPivotYValue = pivotYValue;
          mPivotYType = pivotYType;
          initializePivotPoint();
      }
  
      /**
       * Called at the end of constructor methods to initialize, if possible, values for
       * the pivot point. This is only possible for ABSOLUTE pivot values.
       */
      private void initializePivotPoint() {
          if (mPivotXType == ABSOLUTE) {
              mPivotX = mPivotXValue;
          }
          if (mPivotYType == ABSOLUTE) {
              mPivotY = mPivotYValue;
          }
      }
  
      @Override
      protected void applyTransformation(float interpolatedTime, Transformation t) {
          float sx = 1.0f;
          float sy = 1.0f;
          float scale = getScaleFactor();
  
          if (mFromX != 1.0f || mToX != 1.0f) {
              sx = mFromX + ((mToX - mFromX) * interpolatedTime);
          }
          if (mFromY != 1.0f || mToY != 1.0f) {
              sy = mFromY + ((mToY - mFromY) * interpolatedTime);
          }
  
          if (mPivotX == 0 && mPivotY == 0) {
              t.getMatrix().setScale(sx, sy);
          } else {
              t.getMatrix().setScale(sx, sy, scale * mPivotX, scale * mPivotY);
          }
      }
  
      float resolveScale(float scale, int type, int data, int size, int psize) {
          float targetSize;
          if (type == TypedValue.TYPE_FRACTION) {
              targetSize = TypedValue.complexToFraction(data, size, psize);
          } else if (type == TypedValue.TYPE_DIMENSION) {
              targetSize = TypedValue.complexToDimension(data, mResources.getDisplayMetrics());
          } else {
              return scale;
          }
  
          if (size == 0) {
              return 1;
          }
  
          return targetSize/(float)size;
      }
  
      @Override
      public void initialize(int width, int height, int parentWidth, int parentHeight) {
          super.initialize(width, height, parentWidth, parentHeight);
  
          mFromX = resolveScale(mFromX, mFromXType, mFromXData, width, parentWidth);
          mToX = resolveScale(mToX, mToXType, mToXData, width, parentWidth);
          mFromY = resolveScale(mFromY, mFromYType, mFromYData, height, parentHeight);
          mToY = resolveScale(mToY, mToYType, mToYData, height, parentHeight);
  
          mPivotX = resolveSize(mPivotXType, mPivotXValue, width, parentWidth);
          mPivotY = resolveSize(mPivotYType, mPivotYValue, height, parentHeight);
      }
  }
  