Skip to content

Instantly share code, notes, and snippets.

@romainguy
Last active May 19, 2024 23:05
Show Gist options
  • Save romainguy/4beb128d2349e081ebbcd4b717305187 to your computer and use it in GitHub Desktop.
Save romainguy/4beb128d2349e081ebbcd4b717305187 to your computer and use it in GitHub Desktop.
inline fun Int.uncheckedCoerceIn(minimumValue: Int, maximumValue: Int) =
this.coerceAtLeast(minimumValue).coerceAtMost(maximumValue)
inline fun Rect(l: Int, t: Int, r: Int, b: Int) =
Rect((
((l.uncheckedCoerceIn(0, 8) and 0xf) shl 12) or
((t.uncheckedCoerceIn(0, 8) and 0xf) shl 8) or
((r.uncheckedCoerceIn(0, 8) and 0xf) shl 4) or
((b.uncheckedCoerceIn(0, 8) and 0xf) )
).toShort())
@JvmInline
value class Rect @PublishedApi internal constructor(@PublishedApi internal val points: Short) {
inline val l: Int get() = points.toInt() ushr 12
inline val t: Int get() = (points.toInt() shr 8) and 0xf
inline val r: Int get() = (points.toInt() shr 4) and 0xf
inline val b: Int get() = points.toInt() and 0xf
override fun toString() = "Rect($l, $t, $r, $b)"
}
inline fun Grid() = Grid(0L)
inline fun Grid(r: Rect) = Grid(rasterize(r.l, r.t, r.r, r.b))
inline fun Grid(l: Int, t: Int, r: Int, b: Int) = Grid(rasterize(l, t, r, b))
@JvmInline
value class Grid @PublishedApi internal constructor(@PublishedApi internal val cells: Long) {
inline fun forEach(block: (Int, Int) -> Unit) {
var v = cells
while (v.hasNext()) {
val index = v.get()
block(index and 0x7, index ushr 3)
v = v.next()
}
}
inline operator fun get(x: Int, y: Int) =
((cells ushr ((7 - y) shl 3)) and (0x1L shl (7 - x))) != 0L
inline operator fun plus(r: Rect) =
Grid(cells or rasterize(r.l, r.t, r.r, r.b))
inline operator fun minus(r: Rect) =
Grid(cells and rasterize(r.l, r.t, r.r, r.b).inv())
inline infix fun and(r: Rect) =
Grid(cells and rasterize(r.l, r.t, r.r, r.b))
inline fun intersects(r: Rect) =
(cells and rasterize(r.l, r.t, r.r, r.b)) != 0L
override fun toString() = buildString {
for (y in 0..7) {
val line = (cells ushr (56 - y shl 3) and 0xffL).toString(2).padStart(8, '0')
appendLine(line)
}
}
}
@PublishedApi
internal inline fun Long.get() = 63 - countTrailingZeroBits()
@PublishedApi
internal inline fun Long.hasNext() = this != 0L
@PublishedApi
internal inline fun Long.next() = this and (this - 1L)
@PublishedApi
internal fun rasterize(l: Int, t: Int, r: Int, b: Int): Long {
val w = r - l
val h = b - t
val scanline = 0xffL ushr (8 - w) shl (8 - r)
val rows = 0x01_01_01_01_01_01_01_01L ushr ((8 - h) shl 3) shl ((8 - b) shl 3)
return rows * scanline
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment