<commit_before>//
// $Id: ScaleAnimation.java 3123 2004-09-18 22:58:39Z mdb $

package com.threerings.media.animation;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Image;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Transparency;

import com.threerings.media.image.Mirage;
import com.threerings.media.sprite.Sprite;
import com.threerings.media.sprite.SpriteManager;
import com.threerings.media.util.LinearTimeFunction;
import com.threerings.media.util.TimeFunction;

/**
 * Animates an image changing size about its center point.
 */
public class ScaleAnimation extends Animation
{
    /**
     * Creates a scale animation with the supplied image.  If the image's
     * size would ever be 0 or less, it is not drawn.
     *
     * @param image The image to paint.
     *
     * @param center The screen coordinates of the pixel upon which the
     * image's center should always be rendered.
     *
     * @param startScale The amount to scale the image when it is rendered
     * at time 0.
     *
     * @param endScale The amount to scale the image at the final frame
     * of animation.
     *
     * @param duration The time in milliseconds the anim takes to complete.
     */
    public ScaleAnimation (Mirage image, Point center,
                           float startScale, float endScale, int duration)
    {
        super(getBounds(image, center, Math.max(startScale, endScale)));

        // Save inputted variables
        _image = image;
        _center = new Point(center);
        _startScale = startScale;
        _endScale = endScale;
        _duration = duration;

        // Hack the LinearTimeFunction to use fixed point rationals
        //
        // FIXME: This class doesn't seem to be saving me a lot of
        // work, since I have to repackage the outputs into floats
        // anyway.  Find some way to make the LinearTimeFunction do
        // more of this work for us, or write a new class that does.
        // Maybe IntLinearTimeFunction and FloatLinearTimeFunction
        // classes would be useful.
        _scaleFunc = new LinearTimeFunction(0, 10000, duration);
    }

    /**
     * Java wants the first call in a constructor to be super()
     * if it exists at all, so we have to trick it with this function.
     *
     * Oh, and this function computes how big the bounding box needs
     * to be.
     */
    public static Rectangle getBounds (Mirage image, Point center, float scale)
    {
        int width  = (int) (image.getWidth() * scale);
        int height = (int) (image.getWidth() * scale);

        return new Rectangle(center.x - width/2, center.y - height/2,
                             width, height);
    }

    // documentation inherited
    public void tick (long tickStamp)
    {
        // Compute the new scaling value
        float weight = _scaleFunc.getValue(tickStamp) / 10000.0f;
        float scale = ((1.0f - weight) * _startScale) +
                      ((       weight) *   _endScale);

        // Update the animation if the scaling changes
        if (_scale != scale)
        {
            _scale = scale;
            invalidate();
        }
    }

    // documentation inherited
    public void fastForward (long timeDelta)
    {
        _scaleFunc.fastForward(timeDelta);
    }

    // documentation inherited
    public void paint (Graphics2D gfx)
    {
        //XXX Write this
        /*
        // TODO: recreate our off image if the sprite bounds changed; we
        // also need to change the bounds of our animation which might
        // require some jockeying (especially if we shrink)
        if (_offimg == null) {
            _offimg = gfx.getDeviceConfiguration().createCompatibleImage(
                _bounds.width, _bounds.height, Transparency.TRANSLUCENT);
        }

        // create a mask image with our sprite and the appropriate color
        Graphics2D ogfx = (Graphics2D)_offimg.getGraphics();
        try {
            ogfx.setColor(_color);
            ogfx.fillRect(0, 0, _bounds.width, _bounds.height);
            ogfx.setComposite(AlphaComposite.DstAtop);
            ogfx.translate(-_sprite.getX(), -_sprite.getY());
            _sprite.paint(ogfx);
        } finally {
            ogfx.dispose();
        }

        Composite ocomp = null;
        Composite ncomp = AlphaComposite.getInstance(
            AlphaComposite.SRC_OVER, _alpha/1000f);

        // if we're fading the sprite in on the way up, set our alpha
        // composite before we render the sprite
        if (_fadeIn && _upfunc != null) {
            ocomp = gfx.getComposite();
            gfx.setComposite(ncomp);
        }

        // next render the sprite
        _sprite.paint(gfx);

        // if we're not fading in, we still need to alpha the white bits
        if (ocomp == null) {
            ocomp = gfx.getComposite();
            gfx.setComposite(ncomp);
        }

        // now alpha composite our mask atop the sprite
        gfx.drawImage(_offimg, _sprite.getX(), _sprite.getY(), null);
        gfx.setComposite(ocomp);
        */
    }

    /** The image to scale. */
    protected Mirage _image;

    /** The center pixel to render the image around. */
    protected Point _center;

    /** The amount of time the animation should last. */
    //XXX Is this needed?
    protected long _duration;

    /** The amount to scale the image at the start of the animation. */
    protected float _startScale;

    /** The amount to scale the image at the end of the animation. */
    protected float _endScale;

    /** The current amount of scaling to render. */
    protected float _scale;<commit_msg>Bunch of updates to handle actual drawing of the image.  Some bug fixes too.<commit_after>//
// $Id: ScaleAnimation.java 3123 2004-09-18 22:58:39Z mdb $

package com.threerings.media.animation;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Image;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Transparency;

import java.awt.image.BufferedImage;

import com.threerings.media.image.Mirage;
import com.threerings.media.sprite.Sprite;
import com.threerings.media.sprite.SpriteManager;
import com.threerings.media.util.LinearTimeFunction;
import com.threerings.media.util.TimeFunction;

/**
 * Animates an image changing size about its center point.
 */
public class ScaleAnimation extends Animation
{
    /**
     * Creates a scale animation with the supplied image.  If the image's
     * size would ever be 0 or less, it is not drawn.
     *
     * @param image The image to paint.
     *
     * @param center The screen coordinates of the pixel upon which the
     * image's center should always be rendered.
     *
     * @param startScale The amount to scale the image when it is rendered
     * at time 0.
     *
     * @param endScale The amount to scale the image at the final frame
     * of animation.
     *
     * @param duration The time in milliseconds the anim takes to complete.
     */
    public ScaleAnimation (Mirage image, Point center,
                           float startScale, float endScale, int duration)
    {
        super(getBounds(Math.max(startScale, endScale), center, image));

        // Save inputted variables
        _image = image;
        _bufferedImage = _image.getSnapshot();
        _center = new Point(center);
        _startScale = startScale;
        _endScale = endScale;
        _duration = duration;

        // Hack the LinearTimeFunction to use fixed point rationals
        //
        // FIXME: This class doesn't seem to be saving me a lot of
        // work, since I have to repackage the outputs into floats
        // anyway.  Find some way to make the LinearTimeFunction do
        // more of this work for us, or write a new class that does.
        // Maybe IntLinearTimeFunction and FloatLinearTimeFunction
        // classes would be useful.
        _scaleFunc = new LinearTimeFunction(0, 10000, duration);
    }

    /**
     * Java wants the first call in a constructor to be super()
     * if it exists at all, so we have to trick it with this function.
     *
     * Oh, and this function computes how big the bounding box needs
     * to be to bound the inputted image scaled to the inputted size
     * centered around the inputted center poitn.
     */
    public static Rectangle getBounds (float scale, Point center, Mirage image)
    {
        Point size = getSize(scale, image);
        Point corner = getCorner(center, size);
        return new Rectangle(corner.x, corner.y, size.x, size.y);
    }

    /**
     * Compute the bounds to use to render the animation's image
     * right now.
     */
    public Rectangle getBounds ()
    {
        return getBounds(_scale, _center, _image);
    }

    /** Computes the width and height to which an image should be scaled. */
    public static Point getSize (float scale, Mirage image)
    {
        int width  = Math.max(0, Math.round(image.getWidth()  * scale));
        int height = Math.max(0, Math.round(image.getHeight() * scale));
        return new Point(width, height);
    }

    /**
     * Computes the upper left corner where the image should be drawn,
     * given the center and dimensions to which the image should be scaled.
     */
    public static Point getCorner (Point center, Point size)
    {
        return new Point(center.x - size.x/2, center.y - size.y/2);
    }

    // documentation inherited
    public void tick (long tickStamp)
    {
        // Compute the new scaling value
        float weight = _scaleFunc.getValue(tickStamp) / 10000.0f;
        float scale = ((1.0f - weight) * _startScale) +
                      ((       weight) *   _endScale);

        // Update the animation if the scaling changes
        if (_scale != scale)
        {
            _scale = scale;
            invalidate();
        }
    }

    // documentation inherited
    public void fastForward (long timeDelta)
    {
        _scaleFunc.fastForward(timeDelta);
    }

    // documentation inherited
    public void paint (Graphics2D gfx)
    {
        // Compute the bounding box to render this image
        Rectangle bounds = getBounds();

        // Paint nothing if the image was scaled to nothing
        if (bounds.width <= 0 || bounds.height <= 0) {
            return;
        }

        // Smooth out the image scaling
        // 
        // FIXME: Should this be turned off when the painting is done?
        gfx.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                             RenderingHints.VALUE_INTERPOLATION_BILINEAR);

        // Paint the image scaled to this location
        gfx.drawImage(_bufferedImage,
                      bounds.x,
                      bounds.y,
                      bounds.x + bounds.width,
                      bounds.y + bounds.height,
                      0,
                      0,
                      _bufferedImage.getWidth(),
                      _bufferedImage.getHeight(),
                      null);
    }

    /** The image to scale. */
    protected Mirage _image;

    /** The image converted to a format Graphics2D likes, and cached. */
    protected BufferedImage _bufferedImage;

    /** The center pixel to render the image around. */
    protected Point _center;

    /** The amount of time the animation should last. */
    //XXX Is this needed?
    protected long _duration;

    /** The amount to scale the image at the start of the animation. */
    protected float _startScale;

    /** The amount to scale the image at the end of the animation. */
    protected float _endScale;

    /** The current amount of scaling to render. */
    protected float _scale;
{'fraction_non_alphanumeric': 0.08352373698908352, 'fraction_numerical': 0.007700770077007701, 'mean_word_length': 2.1140974967061923, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6538993', 'n_tokens_mistral': 3327, 'n_tokens_neox': 3152, 'n_words': 1171}