<commit_before>/*
 * Copyright 2014 Google Inc.
 *
 * 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 com.google.android.apps.muzei.render

import android.annotation.SuppressLint
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Rect
import android.opengl.GLES20
import com.google.android.apps.muzei.util.divideRoundUp

import java.nio.FloatBuffer

internal fun BitmapRegionLoader.toGLPicture(maxHeight: Int): GLPicture? {
    if (maxHeight == 0 || width == 0 || height == 0) {
        return null
    }
    return GLPicture(this, maxHeight)
}

internal fun Bitmap.toGLPicture(): GLPicture? {
    if (width == 0 || height == 0) {
        return null
    }
    return GLPicture(this)
}

internal class GLPicture {

    companion object {
        private const val VERTEX_SHADER_CODE = "" +
                // This matrix member variable provides a hook to manipulate
                // the coordinates of the objects that use this vertex shader
                "uniform mat4 uMVPMatrix;" +
                "attribute vec4 aPosition;" +
                "attribute vec2 aTexCoords;" +
                "varying vec2 vTexCoords;" +
                "void main(){" +
                "  vTexCoords = aTexCoords;" +
                "  gl_Position = uMVPMatrix * aPosition;" +
                "}"

        private const val FRAGMENT_SHADER_CODE = "" +
                "precision mediump float;" +
                "uniform sampler2D uTexture;" +
                "uniform float uAlpha;" +
                "varying vec2 vTexCoords;" +
                "void main(){" +
                "  gl_FragColor = texture2D(uTexture, vTexCoords);" +
                "  gl_FragColor.a = uAlpha;" +
                "}"

        // number of coordinates per vertex in this array
        private const val COORDS_PER_VERTEX = 3
        private const val VERTEX_STRIDE_BYTES = COORDS_PER_VERTEX * GLUtil.BYTES_PER_FLOAT
        private const val VERTICES = 6 // TL, BL, BR, TL, BR, TR

        // S, T (or X, Y)
        private const val COORDS_PER_TEXTURE_VERTEX = 2
        private const val TEXTURE_VERTEX_STRIDE_BYTES = COORDS_PER_TEXTURE_VERTEX * GLUtil.BYTES_PER_FLOAT

        private val SQUARE_TEXTURE_VERTICES = floatArrayOf(0f, 0f, // top left
                0f, 1f, // bottom left
                1f, 1f, // bottom right

                0f, 0f, // top left
                1f, 1f, // bottom right
                1f, 0f)// top right

        private var PROGRAM_HANDLE: Int = 0
        private var ATTRIB_POSITION_HANDLE: Int = 0
        private var ATTRIB_TEXTURE_COORDS_HANDLE: Int = 0
        private var UNIFORM_ALPHA_HANDLE: Int = 0
        private var UNIFORM_TEXTURE_HANDLE: Int = 0
        private var UNIFORM_MVP_MATRIX_HANDLE: Int = 0

        private var TILE_SIZE: Int = 0

        fun initGl() {
            // Initialize shaders and create/link program
            val vertexShaderHandle = GLUtil.loadShader(GLES20.GL_VERTEX_SHADER, VERTEX_SHADER_CODE)
            val fragShaderHandle = GLUtil.loadShader(GLES20.GL_FRAGMENT_SHADER, FRAGMENT_SHADER_CODE)

            PROGRAM_HANDLE = GLUtil.createAndLinkProgram(vertexShaderHandle, fragShaderHandle, null)
            ATTRIB_POSITION_HANDLE = GLES20.glGetAttribLocation(PROGRAM_HANDLE, "aPosition")
            ATTRIB_TEXTURE_COORDS_HANDLE = GLES20.glGetAttribLocation(PROGRAM_HANDLE, "aTexCoords")
            UNIFORM_MVP_MATRIX_HANDLE = GLES20.glGetUniformLocation(PROGRAM_HANDLE, "uMVPMatrix")
            UNIFORM_TEXTURE_HANDLE = GLES20.glGetUniformLocation(PROGRAM_HANDLE, "uTexture")
            UNIFORM_ALPHA_HANDLE = GLES20.glGetUniformLocation(PROGRAM_HANDLE, "uAlpha")

            // Compute max texture size
            val maxTextureSize = IntArray(1)
            GLES20.glGetIntegerv(GLES20.GL_MAX_TEXTURE_SIZE, maxTextureSize, 0)
            TILE_SIZE = Math.min(512, maxTextureSize[0])
        }
    }

    private val vertices = FloatArray(COORDS_PER_VERTEX * VERTICES)
    private val vertexBuffer: FloatBuffer = GLUtil.newFloatBuffer(vertices.size)
    private val textureCoordsBuffer: FloatBuffer = GLUtil.asFloatBuffer(SQUARE_TEXTURE_VERTICES)

    private val numColumns: Int
    private val numRows: Int
    private val width: Int
    private val height: Int
    private val textureHandles: IntArray

    @SuppressLint("CheckResult")
    internal constructor(bitmapRegionLoader: BitmapRegionLoader, maxHeight: Int) {
        val originalWidth = bitmapRegionLoader.width
        val originalHeight = bitmapRegionLoader.height
        val sampleSize = originalHeight.sampleSize(maxHeight)

        width = originalWidth / sampleSize
        height = originalHeight / sampleSize

        val unsampledTileSize = TILE_SIZE * sampleSize
        val leftoverHeight = originalHeight % unsampledTileSize

        // Load m x n textures
        numColumns = width.divideRoundUp(TILE_SIZE)
        numRows = height.divideRoundUp(TILE_SIZE)

        textureHandles = IntArray(numColumns * numRows)

        val tileBitmap = Bitmap.createBitmap(TILE_SIZE, TILE_SIZE, Bitmap.Config.ARGB_8888)
        val rect = Rect()
        val options = BitmapFactory.Options()
        options.inSampleSize = sampleSize
        options.inBitmap = tileBitmap
        for (y in 0 until numRows) {
            for (x in 0 until numColumns) {
                rect.set(x * unsampledTileSize,
                        (numRows - y - 1) * unsampledTileSize,
                        (x + 1) * unsampledTileSize,
                        (numRows - y) * unsampledTileSize)
                // The bottom tiles must be full tiles for drawing, so only allow edge tiles
                // at the top
                if (leftoverHeight > 0) {
                    rect.offset(0, -unsampledTileSize + leftoverHeight)
                }
                rect.intersect(0, 0, originalWidth, originalHeight)
                val useBitmap = bitmapRegionLoader.decodeRegion(rect, options)
                if (useBitmap != null) {
                    textureHandles[y * numColumns + x] = GLUtil.loadTexture(useBitmap)
                    if (useBitmap != tileBitmap) {
                        useBitmap.recycle()
                    }
                }
            }
        }
    }

    @SuppressLint("CheckResult")
    internal constructor(bitmap: Bitmap) {
        width = bitmap.width
        height = bitmap.height
        val leftoverHeight = height % TILE_SIZE

        // Load m x n textures
        numColumns = width.divideRoundUp(TILE_SIZE)
        numRows = height.divideRoundUp(TILE_SIZE)

        textureHandles = IntArray(numColumns * numRows)
        if (numColumns == 1 && numRows == 1) {<commit_msg>Make multiple attempts to get a valid subbitmap<commit_after>/*
 * Copyright 2014 Google Inc.
 *
 * 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 com.google.android.apps.muzei.render

import android.annotation.SuppressLint
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Rect
import android.opengl.GLES20
import com.google.android.apps.muzei.util.divideRoundUp

import java.nio.FloatBuffer

internal fun BitmapRegionLoader.toGLPicture(maxHeight: Int): GLPicture? {
    if (maxHeight == 0 || width == 0 || height == 0) {
        return null
    }
    return GLPicture(this, maxHeight)
}

internal fun Bitmap.toGLPicture(): GLPicture? {
    if (width == 0 || height == 0) {
        return null
    }
    return GLPicture(this)
}

internal class GLPicture {

    companion object {
        private const val VERTEX_SHADER_CODE = "" +
                // This matrix member variable provides a hook to manipulate
                // the coordinates of the objects that use this vertex shader
                "uniform mat4 uMVPMatrix;" +
                "attribute vec4 aPosition;" +
                "attribute vec2 aTexCoords;" +
                "varying vec2 vTexCoords;" +
                "void main(){" +
                "  vTexCoords = aTexCoords;" +
                "  gl_Position = uMVPMatrix * aPosition;" +
                "}"

        private const val FRAGMENT_SHADER_CODE = "" +
                "precision mediump float;" +
                "uniform sampler2D uTexture;" +
                "uniform float uAlpha;" +
                "varying vec2 vTexCoords;" +
                "void main(){" +
                "  gl_FragColor = texture2D(uTexture, vTexCoords);" +
                "  gl_FragColor.a = uAlpha;" +
                "}"

        // number of coordinates per vertex in this array
        private const val COORDS_PER_VERTEX = 3
        private const val VERTEX_STRIDE_BYTES = COORDS_PER_VERTEX * GLUtil.BYTES_PER_FLOAT
        private const val VERTICES = 6 // TL, BL, BR, TL, BR, TR

        // S, T (or X, Y)
        private const val COORDS_PER_TEXTURE_VERTEX = 2
        private const val TEXTURE_VERTEX_STRIDE_BYTES = COORDS_PER_TEXTURE_VERTEX * GLUtil.BYTES_PER_FLOAT

        private val SQUARE_TEXTURE_VERTICES = floatArrayOf(0f, 0f, // top left
                0f, 1f, // bottom left
                1f, 1f, // bottom right

                0f, 0f, // top left
                1f, 1f, // bottom right
                1f, 0f)// top right

        private var PROGRAM_HANDLE: Int = 0
        private var ATTRIB_POSITION_HANDLE: Int = 0
        private var ATTRIB_TEXTURE_COORDS_HANDLE: Int = 0
        private var UNIFORM_ALPHA_HANDLE: Int = 0
        private var UNIFORM_TEXTURE_HANDLE: Int = 0
        private var UNIFORM_MVP_MATRIX_HANDLE: Int = 0

        private var TILE_SIZE: Int = 0

        fun initGl() {
            // Initialize shaders and create/link program
            val vertexShaderHandle = GLUtil.loadShader(GLES20.GL_VERTEX_SHADER, VERTEX_SHADER_CODE)
            val fragShaderHandle = GLUtil.loadShader(GLES20.GL_FRAGMENT_SHADER, FRAGMENT_SHADER_CODE)

            PROGRAM_HANDLE = GLUtil.createAndLinkProgram(vertexShaderHandle, fragShaderHandle, null)
            ATTRIB_POSITION_HANDLE = GLES20.glGetAttribLocation(PROGRAM_HANDLE, "aPosition")
            ATTRIB_TEXTURE_COORDS_HANDLE = GLES20.glGetAttribLocation(PROGRAM_HANDLE, "aTexCoords")
            UNIFORM_MVP_MATRIX_HANDLE = GLES20.glGetUniformLocation(PROGRAM_HANDLE, "uMVPMatrix")
            UNIFORM_TEXTURE_HANDLE = GLES20.glGetUniformLocation(PROGRAM_HANDLE, "uTexture")
            UNIFORM_ALPHA_HANDLE = GLES20.glGetUniformLocation(PROGRAM_HANDLE, "uAlpha")

            // Compute max texture size
            val maxTextureSize = IntArray(1)
            GLES20.glGetIntegerv(GLES20.GL_MAX_TEXTURE_SIZE, maxTextureSize, 0)
            TILE_SIZE = Math.min(512, maxTextureSize[0])
        }
    }

    private val vertices = FloatArray(COORDS_PER_VERTEX * VERTICES)
    private val vertexBuffer: FloatBuffer = GLUtil.newFloatBuffer(vertices.size)
    private val textureCoordsBuffer: FloatBuffer = GLUtil.asFloatBuffer(SQUARE_TEXTURE_VERTICES)

    private val numColumns: Int
    private val numRows: Int
    private val width: Int
    private val height: Int
    private val textureHandles: IntArray

    @SuppressLint("CheckResult")
    internal constructor(bitmapRegionLoader: BitmapRegionLoader, maxHeight: Int) {
        val originalWidth = bitmapRegionLoader.width
        val originalHeight = bitmapRegionLoader.height
        val sampleSize = originalHeight.sampleSize(maxHeight)

        width = originalWidth / sampleSize
        height = originalHeight / sampleSize

        val unsampledTileSize = TILE_SIZE * sampleSize
        val leftoverHeight = originalHeight % unsampledTileSize

        // Load m x n textures
        numColumns = width.divideRoundUp(TILE_SIZE)
        numRows = height.divideRoundUp(TILE_SIZE)

        textureHandles = IntArray(numColumns * numRows)

        val tileBitmap = Bitmap.createBitmap(TILE_SIZE, TILE_SIZE, Bitmap.Config.ARGB_8888)
        val rect = Rect()
        val options = BitmapFactory.Options()
        options.inSampleSize = sampleSize
        options.inBitmap = tileBitmap
        for (y in 0 until numRows) {
            for (x in 0 until numColumns) {
                rect.set(x * unsampledTileSize,
                        (numRows - y - 1) * unsampledTileSize,
                        (x + 1) * unsampledTileSize,
                        (numRows - y) * unsampledTileSize)
                // The bottom tiles must be full tiles for drawing, so only allow edge tiles
                // at the top
                if (leftoverHeight > 0) {
                    rect.offset(0, -unsampledTileSize + leftoverHeight)
                }
                rect.intersect(0, 0, originalWidth, originalHeight)
                for (attempt in 1..3) {
                    val useBitmap = bitmapRegionLoader.decodeRegion(rect, options)
                    if (useBitmap != null) {
                        textureHandles[y * numColumns + x] = GLUtil.loadTexture(useBitmap)
                        if (useBitmap != tileBitmap) {
                            useBitmap.recycle()
                        }
                        break
                    }
                }
            }
        }
    }

    @SuppressLint("CheckResult")
    internal constructor(bitmap: Bitmap) {
        width = bitmap.width
        height = bitmap.height
        val leftoverHeight = height % TILE_SIZE

        // Load m x n textures
        numColumns = width.divideRoundUp(TILE_SIZE)
        numRows = height.divideRoundUp(TILE_SIZE)

        textureHandles = IntArray(numColumns * numRows)
        if (numColumns == 1 && numRows == 1) {
{'fraction_non_alphanumeric': 0.0748074807480748, 'fraction_numerical': 0.011413641364136414, 'mean_word_length': 2.217208582172086, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6816946', 'n_tokens_mistral': 4313, 'n_tokens_neox': 4023, 'n_words': 1092}