<commit_before>@file:Suppress("DEPRECATION")
@file:SuppressLint("SupportAnnotationUsage")

package coil.drawable

import android.annotation.SuppressLint
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.ColorFilter
import android.graphics.Movie
import android.graphics.Paint
import android.graphics.PixelFormat
import android.graphics.Rect
import android.graphics.drawable.Animatable
import android.graphics.drawable.AnimatedImageDrawable
import android.graphics.drawable.Drawable
import android.os.Build.VERSION.SDK_INT
import android.os.Build.VERSION_CODES.O
import android.os.SystemClock
import androidx.annotation.Px
import androidx.core.graphics.withScale
import coil.bitmappool.BitmapPool
import coil.decode.ImageDecoderDecoder
import coil.size.Scale
import kotlin.math.ceil
import kotlin.math.max
import kotlin.math.min

/**
 * A [Drawable] that supports rendering [Movie]s (i.e. GIFs).
 *
 * NOTE: Prefer using [ImageDecoderDecoder] and [AnimatedImageDrawable] on Android P and above.
 */
class MovieDrawable(
    private val movie: Movie,
    private val config: Bitmap.Config,
    private val scale: Scale,
    private val pool: BitmapPool
) : Drawable(), Animatable {

    init {
        require(SDK_INT < O || config != Bitmap.Config.HARDWARE) { "Bitmap config must not be hardware." }
    }

    private val paint = Paint(Paint.ANTI_ALIAS_FLAG or Paint.FILTER_BITMAP_FLAG)

    private var currentBounds: Rect? = null
    private var softwareCanvas: Canvas? = null
    private var softwareBitmap: Bitmap? = null

    private var softwareScale = 1f
    private var hardwareScale = 1f
    private var hardwareDx = 0f
    private var hardwareDy = 0f

    private var isRunning = false
    private var startTimeMillis = 0L

    override fun draw(canvas: Canvas) {
        val softwareCanvas = checkNotNull(softwareCanvas)
        val softwareBitmap = checkNotNull(softwareBitmap)

        val time = ((SystemClock.uptimeMillis() - startTimeMillis) % movie.duration()).toInt()
        movie.setTime(time)

        // Draw onto a software canvas first.
        softwareCanvas.withScale(
            x = softwareScale,
            y = softwareScale
        ) {
            movie.draw(this, 0f, 0f, paint)
        }

        // Draw onto the input canvas (may or may not be hardware).
        canvas.withScale(
            x = hardwareScale,
            y = hardwareScale,
            pivotX = hardwareDx,
            pivotY = hardwareDy
        ) {<commit_msg>Fix not clearing the GIF's canvas between frames. (#26)<commit_after>@file:Suppress("DEPRECATION")
@file:SuppressLint("SupportAnnotationUsage")

package coil.drawable

import android.annotation.SuppressLint
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.ColorFilter
import android.graphics.Movie
import android.graphics.Paint
import android.graphics.PixelFormat
import android.graphics.PorterDuff
import android.graphics.Rect
import android.graphics.drawable.Animatable
import android.graphics.drawable.AnimatedImageDrawable
import android.graphics.drawable.Drawable
import android.os.Build.VERSION.SDK_INT
import android.os.Build.VERSION_CODES.O
import android.os.SystemClock
import androidx.annotation.Px
import androidx.core.graphics.withScale
import coil.bitmappool.BitmapPool
import coil.decode.ImageDecoderDecoder
import coil.size.Scale
import kotlin.math.ceil
import kotlin.math.max
import kotlin.math.min

/**
 * A [Drawable] that supports rendering [Movie]s (i.e. GIFs).
 *
 * NOTE: Prefer using [ImageDecoderDecoder] and [AnimatedImageDrawable] on Android P and above.
 */
class MovieDrawable(
    private val movie: Movie,
    private val config: Bitmap.Config,
    private val scale: Scale,
    private val pool: BitmapPool
) : Drawable(), Animatable {

    init {
        require(SDK_INT < O || config != Bitmap.Config.HARDWARE) { "Bitmap config must not be hardware." }
    }

    private val paint = Paint(Paint.ANTI_ALIAS_FLAG or Paint.FILTER_BITMAP_FLAG)

    private var currentBounds: Rect? = null
    private var softwareCanvas: Canvas? = null
    private var softwareBitmap: Bitmap? = null

    private var softwareScale = 1f
    private var hardwareScale = 1f
    private var hardwareDx = 0f
    private var hardwareDy = 0f

    private var isRunning = false
    private var startTimeMillis = 0L

    override fun draw(canvas: Canvas) {
        val softwareCanvas = checkNotNull(softwareCanvas)
        val softwareBitmap = checkNotNull(softwareBitmap)

        val time = ((SystemClock.uptimeMillis() - startTimeMillis) % movie.duration()).toInt()
        movie.setTime(time)

        // Clear the software canvas.
        softwareCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)

        // Draw onto a software canvas first.
        softwareCanvas.withScale(
            x = softwareScale,
            y = softwareScale
        ) {
            movie.draw(this, 0f, 0f, paint)
        }

        // Draw onto the input canvas (may or may not be hardware).
        canvas.withScale(
            x = hardwareScale,
            y = hardwareScale,
            pivotX = hardwareDx,
            pivotY = hardwareDy
        ) {
{'fraction_non_alphanumeric': 0.08172248803827752, 'fraction_numerical': 0.003062200956937799, 'mean_word_length': 3.3225806451612905, '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': '7244773', 'n_tokens_mistral': 1498, 'n_tokens_neox': 1445, 'n_words': 406}