/** * Copyright (c) 2016-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ package com.facebook.keyframes.model.keyframedmodels; import java.util.List; import android.graphics.Color; import com.facebook.keyframes.model.KFColorFrame; import com.facebook.keyframes.model.KFGradientColor; /** * A {link KeyFramedObject} which houses information for a gradient animation. This includes just * start and end colors. The modifiable class is a simple container object that wraps a start and * end color that can be modified and passed around. This is a post-process object used for * KFGradientColor. */ public class KeyFramedGradient extends KeyFramedObject<KFColorFrame, KeyFramedGradient.GradientColorPair> { /** * An enum for whether this gradient color is for the start (top) or end (bottom) color. */ public enum Position { START, END } /** * A simple container that includes a start and end color which can be passed around and modified. * The setter methods can only be called by this class, since all other classes should only need * to grab values from the container. */ public static class GradientColorPair { private int mStartColor; private int mEndColor; public int getStartColor() { return mStartColor; } private void setStartColor(int startColor) { mStartColor = startColor; } public int getEndColor() { return mEndColor; } private void setEndColor(int endColor) { mEndColor = endColor; } } /** * Constructs a KeyFramedGradient from a {@link KFGradientColor}. * @param gradientColor The corresponding {@link KFGradientColor} * @param position The position of this color, either START or END */ public static KeyFramedGradient fromGradient( KFGradientColor gradientColor, Position position) { return new KeyFramedGradient( gradientColor.getKeyValues(), gradientColor.getTimingCurves(), position); } private final Position mPosition; private KeyFramedGradient( List<KFColorFrame> objects, float[][][] timingCurves, Position position) { super(objects, timingCurves); mPosition = position; } /** * Applies the current state, given by the interpolationValue, to the {@link GradientColorPair}. * @param stateA Initial state * @param stateB End state * @param interpolationValue Progress [0..1] between stateA and stateB * @param modifiable The {@link GradientColorPair} to apply the values to */ @Override protected void applyImpl( KFColorFrame stateA, KFColorFrame stateB, float interpolationValue, GradientColorPair modifiable) { if (stateB == null) { if (mPosition == Position.START) { modifiable.setStartColor(stateA.getColor()); } else { modifiable.setEndColor(stateA.getColor()); } return; } if (mPosition == Position.START) { modifiable.setStartColor( getTransitionColor(interpolationValue, stateA.getColor(), stateB.getColor())); } else { modifiable.setEndColor( getTransitionColor(interpolationValue, stateA.getColor(), stateB.getColor())); } } /** * Given a start and end color, as well as a transition progress between the two, return a color * which is in between colorA and colorB, where 0 progress is colorA, 1 progress is colorB, and * all other progress values in between describe a linear transition. * @param progress Progress [0..1] between colorA and colorB. * @param colorA The color associated with progress 0 * @param colorB The color associated with progress 1 * @return The intermediate color that is {progress} between {colorA} and {colorB}. */ public static int getTransitionColor(float progress, int colorA, int colorB) { int startA = Color.alpha(colorA); int startR = Color.red(colorA); int startG = Color.green(colorA); int startB = Color.blue(colorA); int endA = Color.alpha(colorB); int endR = Color.red(colorB); int endG = Color.green(colorB); int endB = Color.blue(colorB); return ((startA + (int) (progress * (endA - startA))) << 24) | ((startR + (int) (progress * (endR - startR))) << 16) | ((startG + (int) (progress * (endG - startG))) << 8) | ((startB + (int) (progress * (endB - startB)))); } }