1 /* <lambda>null2 * Copyright 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.egg.quares 18 19 import android.content.Context 20 import android.graphics.Bitmap 21 import android.graphics.Canvas 22 import android.graphics.drawable.Drawable 23 import android.graphics.drawable.Icon 24 import android.os.Parcel 25 import android.os.Parcelable 26 import java.util.ArrayList 27 import kotlin.math.abs 28 import kotlin.math.round 29 30 class Quare(val width: Int, val height: Int, val depth: Int) : Parcelable { 31 private val data: IntArray = IntArray(width * height) 32 private val user: IntArray = data.copyOf() 33 34 private fun loadAndQuantize(bitmap8bpp: Bitmap) { 35 bitmap8bpp.getPixels(data, 0, width, 0, 0, width, height) 36 if (depth == 8) return 37 val s = (255f / depth) 38 for (i in 0 until data.size) { 39 var f = (data[i] ushr 24).toFloat() / s 40 // f = f.pow(0.75f) // gamma adjust for bolder lines 41 f *= 1.25f // brightness adjust for bolder lines 42 f.coerceAtMost(1f) 43 data[i] = (round(f) * s).toInt() shl 24 44 } 45 } 46 47 fun isBlank(): Boolean { 48 return data.sum() == 0 49 } 50 51 fun load(drawable: Drawable) { 52 val resized = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8) 53 val canvas = Canvas(resized) 54 drawable.setBounds(0, 0, width, height) 55 drawable.setTint(0xFF000000.toInt()) 56 drawable.draw(canvas) 57 loadAndQuantize(resized) 58 resized.recycle() 59 } 60 61 fun load(context: Context, icon: Icon) { 62 icon.loadDrawable(context)?.let { 63 load(it) 64 } 65 } 66 67 fun bitmap(): Bitmap { 68 return Bitmap.createBitmap(data, width, height, Bitmap.Config.ALPHA_8) 69 } 70 71 fun getUserMark(x: Int, y: Int): Int { 72 return user[y * width + x] ushr 24 73 } 74 75 fun setUserMark(x: Int, y: Int, v: Int) { 76 user[y * width + x] = v shl 24 77 } 78 79 fun getDataAt(x: Int, y: Int): Int { 80 return data[y * width + x] ushr 24 81 } 82 83 fun check(): Boolean { 84 return data.contentEquals(user) 85 } 86 87 fun check(xSel: Int, ySel: Int): Boolean { 88 val xStart = if (xSel < 0) 0 else xSel 89 val xEnd = if (xSel < 0) width - 1 else xSel 90 val yStart = if (ySel < 0) 0 else ySel 91 val yEnd = if (ySel < 0) height - 1 else ySel 92 for (y in yStart..yEnd) 93 for (x in xStart..xEnd) 94 if (getDataAt(x, y) != getUserMark(x, y)) return false 95 return true 96 } 97 98 fun errors(): IntArray { 99 return IntArray(width * height) { 100 abs(data[it] - user[it]) 101 } 102 } 103 104 fun getRowClue(y: Int): IntArray { 105 return getClue(-1, y) 106 } 107 fun getColumnClue(x: Int): IntArray { 108 return getClue(x, -1) 109 } 110 fun getClue(xSel: Int, ySel: Int): IntArray { 111 val arr = ArrayList<Int>() 112 var len = 0 113 val xStart = if (xSel < 0) 0 else xSel 114 val xEnd = if (xSel < 0) width - 1 else xSel 115 val yStart = if (ySel < 0) 0 else ySel 116 val yEnd = if (ySel < 0) height - 1 else ySel 117 for (y in yStart..yEnd) 118 for (x in xStart..xEnd) 119 if (getDataAt(x, y) != 0) { 120 len++ 121 } else if (len > 0) { 122 arr.add(len) 123 len = 0 124 } 125 if (len > 0) arr.add(len) 126 else if (arr.size == 0) arr.add(0) 127 return arr.toIntArray() 128 } 129 130 fun resetUserMarks() { 131 user.forEachIndexed { index, _ -> user[index] = 0 } 132 } 133 134 // Parcelable interface 135 136 override fun describeContents(): Int { 137 return 0 138 } 139 140 override fun writeToParcel(p: Parcel?, flags: Int) { 141 p?.let { 142 p.writeInt(width) 143 p.writeInt(height) 144 p.writeInt(depth) 145 p.writeIntArray(data) 146 p.writeIntArray(user) 147 } 148 } 149 150 companion object CREATOR : Parcelable.Creator<Quare> { 151 override fun createFromParcel(p: Parcel?): Quare { 152 return p!!.let { 153 Quare( 154 p.readInt(), // width 155 p.readInt(), // height 156 p.readInt() // depth 157 ).also { 158 p.readIntArray(it.data) 159 p.readIntArray(it.user) 160 } 161 } 162 } 163 164 override fun newArray(size: Int): Array<Quare?> { 165 return arrayOfNulls(size) 166 } 167 } 168 } 169