diff --git a/src/main/scala/ocelot/desktop/color_v2/Color.scala b/src/main/scala/ocelot/desktop/color_v2/Color.scala index 2f86837..380afc0 100644 --- a/src/main/scala/ocelot/desktop/color_v2/Color.scala +++ b/src/main/scala/ocelot/desktop/color_v2/Color.scala @@ -4,55 +4,55 @@ import ocelot.desktop.color_v2.repr.PackedInt import java.nio.ByteBuffer -/** - * Linear-RGB with 8 bits for alpha and 16 bits per color channel, packed into a [[Long]]. - * - * Has the following layout: A_RR_GG_BB. - * - * Uses premultiplied alpha (i.e. color channels are multiplied by alpha). This allows for accurate color blending - * without color leaking from transparent areas. Additionally, there is a unique representation of a fully-transparent - * color - that is (0, 0, 0, 0). Moreover, we get additive color blending for free - just set alpha to zero while - * keeping color channels nonzero. - * - * The rationale for such packed encoding is to use a primitive type ([[AnyVal]]) to avoid allocations. - * - * Using 16 bits per color channel allows seamless sRGB/linear round-trips, assuming we only care about 8 bits per - * channel in our images and on the screen. This doesn't quite hold when transcoding to formats which use - * both straight alpha and non-linear sRGB, but that doesn't matter since during alpha blending this extra precision - * would be lost anyway. - */ +/** Linear-RGB with 8 bits for alpha and 16 bits per color channel, packed into a [[Long]]. + * + * Has the following layout: A_RR_GG_BB. + * + * Uses premultiplied alpha (i.e. color channels are multiplied by alpha). This allows for accurate color blending + * without color leaking from transparent areas. Additionally, there is a unique representation of a fully-transparent + * color - that is (0, 0, 0, 0). Moreover, we get additive color blending for free - just set alpha to zero while + * keeping color channels nonzero. + * + * The rationale for such packed encoding is to use a primitive type ([[AnyVal]]) to avoid allocations. + * + * Using 16 bits per color channel allows seamless sRGB/linear round-trips, assuming we only care about 8 bits per + * channel in our images and on the screen. This doesn't quite hold when transcoding to formats which use + * both straight alpha and non-linear sRGB, but that doesn't matter since during alpha blending this extra precision + * would be lost anyway. + */ case class Color(inner: Long) extends AnyVal { + /** Red channel (0-65535). */ - def r16: Short = ((inner >> 32) & 0xFFFF).toShort + def r16: Short = ((inner >> 32) & 0xffff).toShort /** Green channel (0-65535). */ - def g16: Short = ((inner >> 16) & 0xFFFF).toShort + def g16: Short = ((inner >> 16) & 0xffff).toShort /** Blue channel (0-65535). */ - def b16: Short = (inner & 0xFFFF).toShort + def b16: Short = (inner & 0xffff).toShort /** Alpha channel (0-65535). */ - def a8: Byte = ((inner >> 48) & 0xFF).toByte + def a8: Byte = ((inner >> 48) & 0xff).toByte /** Checks whether two colors are close enough. */ def closeTo(other: Color, colorEps: Int = 10, alphaEps: Int = 1): Boolean = { - ((r16.toInt & 0xFFFF) - (other.r16.toInt & 0xFFFF)).abs <= colorEps && - ((g16.toInt & 0xFFFF) - (other.g16.toInt & 0xFFFF)).abs <= colorEps && - ((b16.toInt & 0xFFFF) - (other.b16.toInt & 0xFFFF)).abs <= colorEps && - ((a8.toInt & 0xFF) - (other.a8.toInt & 0xFF)).abs <= alphaEps + ((r16.toInt & 0xffff) - (other.r16.toInt & 0xffff)).abs <= colorEps && + ((g16.toInt & 0xffff) - (other.g16.toInt & 0xffff)).abs <= colorEps && + ((b16.toInt & 0xffff) - (other.b16.toInt & 0xffff)).abs <= colorEps && + ((a8.toInt & 0xff) - (other.a8.toInt & 0xff)).abs <= alphaEps } /** Performs alpha blending against a background. */ def blendOver(bg: Color): Color = { - val fgR = r16.toInt & 0xFFFF - val fgG = g16.toInt & 0xFFFF - val fgB = b16.toInt & 0xFFFF - val fgA = a8.toInt & 0xFF + val fgR = r16.toInt & 0xffff + val fgG = g16.toInt & 0xffff + val fgB = b16.toInt & 0xffff + val fgA = a8.toInt & 0xff - val bgR = bg.r16.toInt & 0xFFFF - val bgG = bg.g16.toInt & 0xFFFF - val bgB = bg.b16.toInt & 0xFFFF - val bgA = bg.a8.toInt & 0xFF + val bgR = bg.r16.toInt & 0xffff + val bgG = bg.g16.toInt & 0xffff + val bgB = bg.b16.toInt & 0xffff + val bgA = bg.a8.toInt & 0xff def alphaMul(r: Int, a: Int): Int = { // we want to compute: round((r / 0xFFFF) * (a / 0xFF) * 0xFFFF) @@ -76,39 +76,39 @@ case class Color(inner: Long) extends AnyVal { // (ra * 2^8 + ra + ra / 2^8 + 0x8000) / 2^16 val ra = r * a - (((ra << 8) + ra + (ra >> 8) + 0x8000) >> 16) & 0xFFFF + (((ra << 8) + ra + (ra >> 8) + 0x8000) >> 16) & 0xffff } - val resR = fgR + alphaMul(bgR, 0xFF - fgA) - val resG = fgG + alphaMul(bgG, 0xFF - fgA) - val resB = fgB + alphaMul(bgB, 0xFF - fgA) - val resA = fgA + alphaMul(bgA, 0xFF - fgA) + val resR = fgR + alphaMul(bgR, 0xff - fgA) + val resG = fgG + alphaMul(bgG, 0xff - fgA) + val resB = fgB + alphaMul(bgB, 0xff - fgA) + val resA = fgA + alphaMul(bgA, 0xff - fgA) Color.pack(resR.toShort, resG.toShort, resB.toShort, resA.toByte) } } object Color { - val White: Color = PackedInt(0xFFFFFF).toColor + val White: Color = PackedInt(0xffffff).toColor val Grey: Color = PackedInt(0x808080).toColor val Black: Color = PackedInt(0x000000).toColor - val Red: Color = PackedInt(0xFF0000).toColor - val Green: Color = PackedInt(0x00FF00).toColor - val Blue: Color = PackedInt(0x0000FF).toColor + val Red: Color = PackedInt(0xff0000).toColor + val Green: Color = PackedInt(0x00ff00).toColor + val Blue: Color = PackedInt(0x0000ff).toColor - val Cyan: Color = PackedInt(0x00FFF).toColor - val Magenta: Color = PackedInt(0xFF00FF).toColor - val Yellow: Color = PackedInt(0xFFFF00).toColor + val Cyan: Color = PackedInt(0x00fff).toColor + val Magenta: Color = PackedInt(0xff00ff).toColor + val Yellow: Color = PackedInt(0xffff00).toColor val Transparent: Color = Color(0) def pack(r16: Short, g16: Short, b16: Short, a8: Byte): Color = { Color( - ((a8.toLong & 0xFF) << 48) - | ((r16.toLong & 0xFFFF) << 32) - | ((g16.toLong & 0xFFFF) << 16) - | (b16.toLong & 0xFFFF) + ((a8.toLong & 0xff) << 48) + | ((r16.toLong & 0xffff) << 32) + | ((g16.toLong & 0xffff) << 16) + | (b16.toLong & 0xffff) ) } @@ -136,6 +136,7 @@ object Color { } object Encoding { + /** Linear encoding with a single 8-bit red channel. */ case object LinearR8 extends Encoding { override val size: Int = 1 @@ -146,7 +147,7 @@ object Color { override def decode(src: ByteBuffer): Color = { val r = extend8To16Bits(src.get()) - pack(r, r, r, 0xFF.toByte) + pack(r, r, r, 0xff.toByte) } } @@ -164,7 +165,7 @@ object Color { val r = extend8To16Bits(src.get()) val g = extend8To16Bits(src.get()) val b = extend8To16Bits(src.get()) - pack(r, g, b, 0xFF.toByte) + pack(r, g, b, 0xff.toByte) } } @@ -202,7 +203,7 @@ object Color { val r = srgb8ToLinear16(src.get()) val g = srgb8ToLinear16(src.get()) val b = srgb8ToLinear16(src.get()) - pack(r, g, b, 0xFF.toByte) + pack(r, g, b, 0xff.toByte) } } @@ -229,17 +230,17 @@ object Color { } /** Repeats a byte twice */ - private[color_v2] def extend8To16Bits(v: Byte): Short = (((v.toShort & 0xFF) << 8) | (v.toShort & 0xFF)).toShort + private[color_v2] def extend8To16Bits(v: Byte): Short = (((v.toShort & 0xff) << 8) | (v.toShort & 0xff)).toShort /** Returns high byte from 16-bit word */ private[color_v2] def shrink16To8Bits(v: Short): Byte = (v >> 8).toByte /** Converts non-linear sRGB color component (0-255) to linear color space (0-65535). */ - private[color_v2] def srgb8ToLinear16(v: Byte): Short = Srgb8ToLinear16Lut(v.toInt & 0xFF) + private[color_v2] def srgb8ToLinear16(v: Byte): Short = Srgb8ToLinear16Lut(v.toInt & 0xff) private lazy val Srgb8ToLinear16Lut: Array[Short] = { Array.tabulate(0x100) { i => - val srgb = i.toFloat / 0xFF.toFloat + val srgb = i.toFloat / 0xff.toFloat val linear = if (srgb <= 0.04045) { srgb / 12.92 @@ -247,16 +248,16 @@ object Color { math.pow((srgb + 0.055) / 1.055, 2.4) } - (linear * 0xFFFF.toFloat).toShort + (linear * 0xffff.toFloat).toShort } } /** Converts linear color component (0-65535) to non-linear sRGB color space (0-255). */ - private[color_v2] def linear16ToSrgb8(v: Short): Byte = Linear16ToSrgb8Lut(v.toInt & 0xFFFF) + private[color_v2] def linear16ToSrgb8(v: Short): Byte = Linear16ToSrgb8Lut(v.toInt & 0xffff) private lazy val Linear16ToSrgb8Lut: Array[Byte] = { Array.tabulate(0x10000) { i => - val linear = i.toFloat / 0xFFFF.toFloat + val linear = i.toFloat / 0xffff.toFloat val srgb = if (linear <= 0.0031308) { linear * 12.92 @@ -264,7 +265,7 @@ object Color { 1.055 * math.pow(linear, 1.0 / 2.4) - 0.055 } - math.min((srgb * 0xFF.toFloat).round, 255.0).toInt.toByte + math.min((srgb * 0xff.toFloat).round, 255.0).toInt.toByte } } -} \ No newline at end of file +} diff --git a/src/main/scala/ocelot/desktop/color_v2/repr/LinearRgba.scala b/src/main/scala/ocelot/desktop/color_v2/repr/LinearRgba.scala index 473a4d8..07f75c1 100644 --- a/src/main/scala/ocelot/desktop/color_v2/repr/LinearRgba.scala +++ b/src/main/scala/ocelot/desktop/color_v2/repr/LinearRgba.scala @@ -6,7 +6,7 @@ import ocelot.desktop.color_v2.Color._ /** Linear RGBA color with double components (0-1) with premultiplied alpha. */ case class LinearRgba(r: Double, g: Double, b: Double, a: Double) extends ReprInstance { override def toColor: Color = { - pack((r * 0xFFFF).toShort, (g * 0xFFFF).toShort, (b * 0xFFFF).toShort, (a * 0XFF).toByte) + pack((r * 0xffff).toShort, (g * 0xffff).toShort, (b * 0xffff).toShort, (a * 0xff).toByte) } def closeTo(other: LinearRgba, eps: Double = 1e-3): Boolean = { @@ -19,10 +19,10 @@ case object LinearRgba extends ReprObject { override def fromColor(color: Color): LinearRgba = { LinearRgba( - (color.r16.toInt & 0xFFFF).toDouble / 0xFFFF, - (color.g16.toInt & 0xFFFF).toDouble / 0xFFFF, - (color.b16.toInt & 0xFFFF).toDouble / 0xFFFF, - (color.a8.toInt & 0xFF).toDouble / 0xFF + (color.r16.toInt & 0xffff).toDouble / 0xffff, + (color.g16.toInt & 0xffff).toDouble / 0xffff, + (color.b16.toInt & 0xffff).toDouble / 0xffff, + (color.a8.toInt & 0xff).toDouble / 0xff, ) } } diff --git a/src/main/scala/ocelot/desktop/color_v2/repr/Okhsv.scala b/src/main/scala/ocelot/desktop/color_v2/repr/Okhsv.scala index ff72b53..15e619f 100644 --- a/src/main/scala/ocelot/desktop/color_v2/repr/Okhsv.scala +++ b/src/main/scala/ocelot/desktop/color_v2/repr/Okhsv.scala @@ -3,12 +3,12 @@ package ocelot.desktop.color_v2.repr import ocelot.desktop.color_v2.Color /** Color in Okhsv color space with premultiplied alpha. - * - * @param h Hue (0-360) - * @param s Saturation (0-1) - * @param v Value (0-1) - * @param a Alpha (0-1) - */ + * + * @param h Hue (0-360) + * @param s Saturation (0-1) + * @param v Value (0-1) + * @param a Alpha (0-1) + */ case class Okhsv(h: Double, s: Double, v: Double, a: Double) extends ReprInstance { override def toColor: Color = Okhsv.okhsvToOklav(this).toColor @@ -19,9 +19,9 @@ case class Okhsv(h: Double, s: Double, v: Double, a: Double) extends ReprInstanc } angleDiff(h, other.h) <= eps * 360 && - (s - other.s).abs <= eps && - (v - other.v).abs <= eps && - (a - other.a).abs <= eps + (s - other.s).abs <= eps && + (v - other.v).abs <= eps && + (a - other.a).abs <= eps } } @@ -66,7 +66,7 @@ case object Okhsv extends ReprObject { } private def computeMaxSaturation(a: Double, b: Double): Double = { - val (k0, k1, k2, k3, k4, wl, wm, ws) = + val (k0, k1, k2, k3, k4, wl, wm, ws) = { if (-1.88170328 * a - 0.80936493 * b > 1) { // Red component (1.19086277, 1.76576728, 0.59662641, 0.75515197, 0.56771245, @@ -80,6 +80,7 @@ case object Okhsv extends ReprObject { (1.35733652, -0.00915799, -1.15130210, -0.50559606, 0.00692167, -0.0041960863, -0.7034186147, 1.7076147010) } + } var S = k0 + k1 * a + k2 * b + k3 * a * a + k4 * a * b diff --git a/src/main/scala/ocelot/desktop/color_v2/repr/Oklab.scala b/src/main/scala/ocelot/desktop/color_v2/repr/Oklab.scala index 7258176..8a926fe 100644 --- a/src/main/scala/ocelot/desktop/color_v2/repr/Oklab.scala +++ b/src/main/scala/ocelot/desktop/color_v2/repr/Oklab.scala @@ -3,12 +3,12 @@ package ocelot.desktop.color_v2.repr import ocelot.desktop.color_v2.Color /** Color in Oklab color space with premultiplied alpha. - * - * @param lightness Perceived lightness. - * @param colorA How green/red the color is. - * @param colorB How blue/yellow the color is. - * @param alpha Alpha (0-1) - */ + * + * @param lightness Perceived lightness. + * @param colorA How green/red the color is. + * @param colorB How blue/yellow the color is. + * @param alpha Alpha (0-1) + */ case class Oklab(lightness: Double, colorA: Double, colorB: Double, alpha: Double) extends ReprInstance { private[repr] def toLinearRgba: LinearRgba = { val l_ = +0.2158037573 * colorB + 0.3963377774 * colorA + lightness @@ -18,10 +18,10 @@ case class Oklab(lightness: Double, colorA: Double, colorB: Double, alpha: Doubl val m = m_ * m_ * m_ val s = s_ * s_ * s_ LinearRgba( - r = +0.2309699292 * s + 4.0767416621 * l -3.3077115913 * m, - g = -0.3413193965 * s + -1.2684380046 * l +2.6097574011 * m, - b = +1.7076147010 * s + -0.0041960863 * l -0.7034186147 * m, - a = alpha + r = +0.2309699292 * s + 4.0767416621 * l - 3.3077115913 * m, + g = -0.3413193965 * s + -1.2684380046 * l + 2.6097574011 * m, + b = +1.7076147010 * s + -0.0041960863 * l - 0.7034186147 * m, + a = alpha, ) } @@ -29,9 +29,9 @@ case class Oklab(lightness: Double, colorA: Double, colorB: Double, alpha: Doubl def closeTo(other: Oklab, eps: Double = 1e-3): Boolean = { (lightness - other.lightness) <= eps && - (colorA - other.colorA) <= eps && - (colorB - other.colorB) <= eps && - (alpha - other.alpha) <= eps + (colorA - other.colorA) <= eps && + (colorB - other.colorB) <= eps && + (alpha - other.alpha) <= eps } } @@ -46,7 +46,7 @@ case object Oklab extends ReprObject { lightness = -0.0040720468 * s + 0.2104542553 * l + 0.7936177850 * m, colorA = +0.4505937099 * s + 1.9779984951 * l - 2.4285922050 * m, colorB = -0.8086757660 * s + 0.0259040371 * l + 0.7827717662 * m, - alpha = c.a + alpha = c.a, ) } diff --git a/src/main/scala/ocelot/desktop/color_v2/repr/PackedInt.scala b/src/main/scala/ocelot/desktop/color_v2/repr/PackedInt.scala index b875493..5012c80 100644 --- a/src/main/scala/ocelot/desktop/color_v2/repr/PackedInt.scala +++ b/src/main/scala/ocelot/desktop/color_v2/repr/PackedInt.scala @@ -5,17 +5,18 @@ import ocelot.desktop.color_v2.Color._ /** sRGB color packed into an [[Int]] (0xRRGGBB). No alpha. Very common in OpenComputers world. */ case class PackedInt(inner: Int) extends AnyVal with ReprInstance { + /** Red channel (0-255). */ - def r: Byte = ((inner >> 16) & 0xFF).toByte + def r: Byte = ((inner >> 16) & 0xff).toByte /** Green channel (0-255). */ - def g: Byte = ((inner >> 8) & 0xFF).toByte + def g: Byte = ((inner >> 8) & 0xff).toByte /** Blue channel (0-255). */ - def b: Byte = (inner & 0xFF).toByte + def b: Byte = (inner & 0xff).toByte override def toColor: Color = { - pack(srgb8ToLinear16(r), srgb8ToLinear16(g), srgb8ToLinear16(b), 0xFF.toByte) + pack(srgb8ToLinear16(r), srgb8ToLinear16(g), srgb8ToLinear16(b), 0xff.toByte) } } @@ -23,9 +24,9 @@ case object PackedInt extends ReprObject { override type Instance = PackedInt override def fromColor(color: Color): PackedInt = { - val r = linear16ToSrgb8(color.r16).toInt & 0xFF - val g = linear16ToSrgb8(color.g16).toInt & 0xFF - val b = linear16ToSrgb8(color.b16).toInt & 0xFF + val r = linear16ToSrgb8(color.r16).toInt & 0xff + val g = linear16ToSrgb8(color.g16).toInt & 0xff + val b = linear16ToSrgb8(color.b16).toInt & 0xff PackedInt((r << 16) | (g << 8) | b) } -} \ No newline at end of file +} diff --git a/src/main/scala/ocelot/desktop/color_v2/repr/package.scala b/src/main/scala/ocelot/desktop/color_v2/repr/package.scala index c0de23f..bafd1c4 100644 --- a/src/main/scala/ocelot/desktop/color_v2/repr/package.scala +++ b/src/main/scala/ocelot/desktop/color_v2/repr/package.scala @@ -1,8 +1,10 @@ package ocelot.desktop.color_v2 package object repr { + /** Provides encoding and decoding of various alternative color representations to [[Color]]. */ trait ReprObject { + /** Type of the alternative representation */ type Instance <: ReprInstance; @@ -12,6 +14,7 @@ package object repr { /** Provides encoding and decoding of various alternative color representations to [[Color]]. */ trait ReprInstance extends Any { + /** Converts this representation to a [[Color]]. */ def toColor: Color } diff --git a/src/main/scala/ocelot/desktop/graphics_v2/Encoder2D.scala b/src/main/scala/ocelot/desktop/graphics_v2/Encoder2D.scala index a9d41c1..e6c5ad9 100644 --- a/src/main/scala/ocelot/desktop/graphics_v2/Encoder2D.scala +++ b/src/main/scala/ocelot/desktop/graphics_v2/Encoder2D.scala @@ -4,29 +4,27 @@ import ocelot.desktop.color.Color import ocelot.desktop.geometry.{Rect2D, Transform2D} trait Encoder2D { - /** - * Draws a rectangle with a specified image and color. - * - * @param rect Rectangle to draw (its position and size). - * @param image Fill image. - * Pass [[Image.None]] for a solid fill. (default). - * @param color Color which is multiplied with the image linearly, i.e. tint. - * Pass [[Color.White]] for no tint (default). - */ + + /** Draws a rectangle with a specified image and color. + * + * @param rect Rectangle to draw (its position and size). + * @param image Fill image. + * Pass [[Image.None]] for a solid fill. (default). + * @param color Color which is multiplied with the image linearly, i.e. tint. + * Pass [[Color.White]] for no tint (default). + */ def rect(rect: Rect2D, image: Image = Image.None, color: Color = Color.White): Unit - /** - * Draws a group of objects with various optional effects. Takes a callback with a sub-encoder. - * - * @param scissor Apply a scissor rectangle (specified in the coordinate system of this encoder, - * not local coordinates of the inner encoder). - * @param transform Apply a transform to the inner encoder. - * @param color Apply a tint color to the group as a whole (i.e. if you make it semi-transparent, - * the entire group will be transparent without any color mixing within the group). - * @param callback Callback taking a sub-encoder. - */ + /** Draws a group of objects with various optional effects. Takes a callback with a sub-encoder. + * + * @param scissor Apply a scissor rectangle (specified in the coordinate system of this encoder, + * not local coordinates of the inner encoder). + * @param transform Apply a transform to the inner encoder. + * @param color Apply a tint color to the group as a whole (i.e. if you make it semi-transparent, + * the entire group will be transparent without any color mixing within the group). + * @param callback Callback taking a sub-encoder. + */ def group(scissor: Option[Rect2D] = None, transform: Transform2D = Transform2D.identity, - color: Color = Color.White) - (callback: Encoder2D => Unit): Unit + color: Color = Color.White)(callback: Encoder2D => Unit): Unit } diff --git a/src/main/scala/ocelot/desktop/graphics_v2/Graphics.scala b/src/main/scala/ocelot/desktop/graphics_v2/Graphics.scala index 44cb71c..4f4997f 100644 --- a/src/main/scala/ocelot/desktop/graphics_v2/Graphics.scala +++ b/src/main/scala/ocelot/desktop/graphics_v2/Graphics.scala @@ -5,27 +5,27 @@ import ocelot.desktop.color.Color import java.nio.ByteBuffer trait Graphics { - /** - * Type of [[Image.Static]] used by this graphics backend. - * - * Created with [[createStaticImage()]] and must be destroyed with [[destroyStaticImage()]] - */ + + /** Type of [[Image.Static]] used by this graphics backend. + * + * Created with [[createStaticImage()]] and must be destroyed with [[destroyStaticImage()]] + */ type StaticImage <: Image.Static - /** - * Type of [[Image.Surface]] used by this graphics backend. - * - * This is used for off-screen rendering and for rendering to the window. Though the latter requires you to obtain - * a window-bound surface using implementation-specific methods defined outside of this trait. - * - * Created with [[createSurface()]] and must be destroyed with [[destroySurface()]] - */ + /** Type of [[Image.Surface]] used by this graphics backend. + * + * This is used for off-screen rendering and for rendering to the window. Though the latter requires you to obtain + * a window-bound surface using implementation-specific methods defined outside of this trait. + * + * Created with [[createSurface()]] and must be destroyed with [[destroySurface()]] + */ type Surface <: Image.Surface /** Defines various passes that happen during the rendering process in sequence. */ sealed class Pass object Pass { + /** Clears the surface with a solid color. */ case class Clear(surface: Surface, color: Color) extends Pass @@ -36,27 +36,24 @@ trait Graphics { case class Download(surface: Surface, callback: ByteBuffer => Unit) extends Pass } - /** - * Creates a static image with given dimensions, format, and data (row-major, packed without alignment or padding). - * - * @throws IllegalArgumentException if width or height is zero or negative, - * if data is too short or too long for given format and dimensions - */ + /** Creates a static image with given dimensions, format, and data (row-major, packed without alignment or padding). + * + * @throws IllegalArgumentException if width or height is zero or negative, + * if data is too short or too long for given format and dimensions + */ def createStaticImage(width: Int, height: Int, format: Image.Format, packedData: ByteBuffer): StaticImage - /** - * Destroys a static image. - * @throws IllegalArgumentException if the image does not belong to this [[Graphics]] instance or is already destroyed. - */ + /** Destroys a static image. + * @throws IllegalArgumentException if the image does not belong to this [[Graphics]] instance or is already destroyed. + */ def destroyStaticImage(image: StaticImage): Unit /** Creates a drawable off-screen surface with given dimensions. */ def createSurface(width: Int, height: Int, format: Image.Format): Surface - /** - * Destroys a surface. - * @throws IllegalArgumentException if the surface does not belong to this [[Graphics]] instance or is already destroyed. - */ + /** Destroys a surface. + * @throws IllegalArgumentException if the surface does not belong to this [[Graphics]] instance or is already destroyed. + */ def destroySurface(surface: Surface): Unit /** Performs all rendering passes from the specified array in sequence. */ diff --git a/src/main/scala/ocelot/desktop/graphics_v2/Image.scala b/src/main/scala/ocelot/desktop/graphics_v2/Image.scala index bc45105..fc37aee 100644 --- a/src/main/scala/ocelot/desktop/graphics_v2/Image.scala +++ b/src/main/scala/ocelot/desktop/graphics_v2/Image.scala @@ -2,49 +2,42 @@ package ocelot.desktop.graphics_v2 import ocelot.desktop.geometry.{Rect2D, Size2D} -/** - * Image used to fill geometry with color. - */ -abstract sealed class Image { - /** - * Size of the image in pixels. - * - * Can be fractional. For instance, using [[Image.SubImage]] you can actually draw an image with a half-cropped pixel - * given enough zoom. - */ +/** Image used to fill geometry with color. */ +sealed abstract class Image { + + /** Size of the image in pixels. + * + * Can be fractional. For instance, using [[Image.SubImage]] you can actually draw an image with a half-cropped pixel + * given enough zoom. + */ def size: Size2D } object Image { - /** - * Just a white image (all channels are 1.0). Use this to fill something with solid color. - */ + + /** Just a white image (all channels are 1.0). Use this to fill something with solid color. */ object None extends Image { override def size: Size2D = Size2D(1, 1) } - /** - * A static image (loaded from a PNG resource or generated at runtime). - */ + /** A static image (loaded from a PNG resource or generated at runtime). */ abstract class Static extends Image - /** - * Image contents of a drawable surface (useful for screens, holographs). - */ + /** Image contents of a drawable surface (useful for screens, holographs). */ abstract class Surface extends Image - /** - * Rectangular portion of an image. - * - * @param srcImage Source image - * @param rect Normalized rectangle, where (0,0) is top-left and (1,1) is bottom-right. - */ + /** Rectangular portion of an image. + * + * @param srcImage Source image + * @param rect Normalized rectangle, where (0,0) is top-left and (1,1) is bottom-right. + */ case class SubImage(srcImage: Image, rect: Rect2D) extends Image { override def size: Size2D = srcImage.size * rect.size } /** Image formats */ - abstract sealed class Format { + sealed abstract class Format { + /** Returns true if the format is linear (has no gamma-correction). */ def isLinear: Boolean @@ -53,6 +46,7 @@ object Image { } object Format { + /** Linear format with one R 8-bit channel */ case object LinearR8 extends Format { override val isLinear = true @@ -67,11 +61,10 @@ object Image { override def bytesPerPixel: Int = 3 } - /** - * Linear format with four RGBA 8-bit channels. - * - * Color is NOT premultiplied by alpha. - */ + /** Linear format with four RGBA 8-bit channels. + * + * Color is NOT premultiplied by alpha. + */ case object LinearRgba8 extends Format { override val isLinear = true @@ -85,11 +78,10 @@ object Image { override def bytesPerPixel: Int = 3 } - /** - * Gamma-corrected (nonlinear sRGB) format with four RGBA 8-bit channels. - * - * Alpha is still linear. Color is NOT premultiplied by alpha. - */ + /** Gamma-corrected (nonlinear sRGB) format with four RGBA 8-bit channels. + * + * Alpha is still linear. Color is NOT premultiplied by alpha. + */ case object SrgbRgba8 extends Format { override val isLinear = false diff --git a/src/main/scala/ocelot/desktop/graphics_v2/reference_impl/GraphicsImpl.scala b/src/main/scala/ocelot/desktop/graphics_v2/reference_impl/GraphicsImpl.scala index 1d6a1c7..276ea79 100644 --- a/src/main/scala/ocelot/desktop/graphics_v2/reference_impl/GraphicsImpl.scala +++ b/src/main/scala/ocelot/desktop/graphics_v2/reference_impl/GraphicsImpl.scala @@ -33,15 +33,17 @@ class GraphicsImpl extends Graphics { } object GraphicsImpl { - class StaticImageImpl private[reference_impl](val owner: GraphicsImpl, val imageBuffer: ImageBuffer) extends Image.Static { + class StaticImageImpl private[reference_impl] (val owner: GraphicsImpl, val imageBuffer: ImageBuffer) + extends Image.Static { private[reference_impl] var isDestroyed = false override def size: Size2D = imageBuffer.size } - class SurfaceImpl private[reference_impl](val owner: GraphicsImpl, val imageBuffer: ImageBuffer) extends Image.Surface { + class SurfaceImpl private[reference_impl] (val owner: GraphicsImpl, val imageBuffer: ImageBuffer) + extends Image.Surface { private[reference_impl] var isDestroyed = false override def size: Size2D = imageBuffer.size } -} \ No newline at end of file +} diff --git a/src/main/scala/ocelot/desktop/graphics_v2/reference_impl/ImageBuffer.scala b/src/main/scala/ocelot/desktop/graphics_v2/reference_impl/ImageBuffer.scala index ea7f2db..cdef9b0 100644 --- a/src/main/scala/ocelot/desktop/graphics_v2/reference_impl/ImageBuffer.scala +++ b/src/main/scala/ocelot/desktop/graphics_v2/reference_impl/ImageBuffer.scala @@ -5,7 +5,8 @@ import ocelot.desktop.graphics_v2.Image import java.nio.ByteBuffer -private[reference_impl] class ImageBuffer(val width: Int, val height: Int, val format: Image.Format, val data: ByteBuffer) { +private[reference_impl] class ImageBuffer(val width: Int, val height: Int, val format: Image.Format, + val data: ByteBuffer) { require(width * height * format.bytesPerPixel == data.limit(), "Wrong ImageBuffer data size"); def this(width: Int, height: Int, format: Image.Format) { diff --git a/src/main/scala/ocelot/desktop/graphics_v2/reference_impl/PackedColor.scala b/src/main/scala/ocelot/desktop/graphics_v2/reference_impl/PackedColor.scala index 957ed90..e904b72 100644 --- a/src/main/scala/ocelot/desktop/graphics_v2/reference_impl/PackedColor.scala +++ b/src/main/scala/ocelot/desktop/graphics_v2/reference_impl/PackedColor.scala @@ -5,24 +5,23 @@ import ocelot.desktop.graphics_v2.Image.Format import java.nio.ByteBuffer -/** - * Packed linear color with premultiplied color with 8 bits for alpha and 16 bits per color channel. - * - * Has the following layout: A_RR_GG_BB. - * - * The rationale for such encoding is to use a primitive type ([[AnyVal]]) to avoid allocations. - * - * Using 16 bits per color channel allows seamless sRGB/linear and premultiplied/not-premultiplied round-trips, - * assuming we only store 8 bits per channel in our images. - */ +/** Packed linear color with premultiplied color with 8 bits for alpha and 16 bits per color channel. + * + * Has the following layout: A_RR_GG_BB. + * + * The rationale for such encoding is to use a primitive type ([[AnyVal]]) to avoid allocations. + * + * Using 16 bits per color channel allows seamless sRGB/linear and premultiplied/not-premultiplied round-trips, + * assuming we only store 8 bits per channel in our images. + */ private[reference_impl] case class PackedColor(packed: Long) extends AnyVal { - def r16: Short = ((packed >> 32) & 0xFFFF).toShort + def r16: Short = ((packed >> 32) & 0xffff).toShort - def g16: Short = ((packed >> 16) & 0xFFFF).toShort + def g16: Short = ((packed >> 16) & 0xffff).toShort - def b16: Short = (packed & 0xFFFF).toShort + def b16: Short = (packed & 0xffff).toShort - def a8: Byte = ((packed >> 48) & 0xFF).toByte + def a8: Byte = ((packed >> 48) & 0xff).toByte def encode(format: Image.Format, offset: Int, data: ByteBuffer): Unit = { PackedColor.encode(format, offset, data, this) @@ -31,20 +30,20 @@ private[reference_impl] case class PackedColor(packed: Long) extends AnyVal { private[reference_impl] object PackedColor { private def pack(r: Short, g: Short, b: Short, a: Short): PackedColor = { - PackedColor(((a & 0xFF) << 40) | ((r & 0xFFFF) << 32) | ((g & 0xFFFF) << 16) | (b & 0xFFFF)) + PackedColor(((a & 0xff) << 40) | ((r & 0xffff) << 32) | ((g & 0xffff) << 16) | (b & 0xffff)) } private def extend8To16Bits(v: Byte): Short = ((v << 8) | v).toShort - private def shrink16To8Bits(v: Short): Byte = (v / 0xFF).toByte + private def shrink16To8Bits(v: Short): Byte = (v / 0xff).toByte - private def preMultiply(col: Short, alpha: Byte): Short = (col * alpha / 0xFF).toShort + private def preMultiply(col: Short, alpha: Byte): Short = (col * alpha / 0xff).toShort - private def unPreMultiply(col: Short, alpha: Byte): Short = if (alpha == 0) 0 else (col * 0xFF / alpha).toShort + private def unPreMultiply(col: Short, alpha: Byte): Short = if (alpha == 0) 0 else (col * 0xff / alpha).toShort private val Srgb8ToLinear16Lut: Array[Short] = { - (0 to 0xFF).map { i => - val srgb = i.toFloat / 0xFF.toFloat + (0 to 0xff).map { i => + val srgb = i.toFloat / 0xff.toFloat val linear = if (srgb <= 0.04045) { srgb / 12.92 @@ -52,23 +51,23 @@ private[reference_impl] object PackedColor { math.pow((srgb + 0.055) / 1.055, 2.4) } - (linear * 0xFFFF.toFloat).toShort + (linear * 0xffff.toFloat).toShort }.toArray } private def srgb8ToLinear16(v: Byte): Short = Srgb8ToLinear16Lut(v) private val Linear16ToSrgb8Lut: Array[Byte] = { - (0 to 0xFFFF).map { i => - val linear = i.toFloat / 0xFFFF.toFloat + (0 to 0xffff).map { i => + val linear = i.toFloat / 0xffff.toFloat val srgb = if (linear <= 0.0031308) { linear * 12.92 } else { - 1.055 * math.pow(linear, 1.0/2.4) - 0.055 + 1.055 * math.pow(linear, 1.0 / 2.4) - 0.055 } - (srgb * 0xFF.toFloat).toByte + (srgb * 0xff.toFloat).toByte }.toArray } @@ -78,13 +77,13 @@ private[reference_impl] object PackedColor { format match { case Format.LinearR8 => val r = extend8To16Bits(data.get(offset)) - pack(r, r, r, 0xFF) + pack(r, r, r, 0xff) case Format.LinearRgb8 => val r = extend8To16Bits(data.get(offset + 0)) val g = extend8To16Bits(data.get(offset + 1)) val b = extend8To16Bits(data.get(offset + 2)) - pack(r, g, b, 0xFF) + pack(r, g, b, 0xff) case Format.LinearRgba8 => val r = extend8To16Bits(data.get(offset + 0)) @@ -97,7 +96,7 @@ private[reference_impl] object PackedColor { val r = srgb8ToLinear16(data.get(offset + 0)) val g = srgb8ToLinear16(data.get(offset + 1)) val b = srgb8ToLinear16(data.get(offset + 2)) - pack(r, g, b, 0xFF) + pack(r, g, b, 0xff) case Format.SrgbRgba8 => val a = data.get(offset + 3) @@ -141,4 +140,4 @@ private[reference_impl] object PackedColor { data.put(offset + 3, a) } } -} \ No newline at end of file +} diff --git a/src/test/scala/ocelot/desktop/color_v2/ColorTest.scala b/src/test/scala/ocelot/desktop/color_v2/ColorTest.scala index bde2cf6..3c913e0 100644 --- a/src/test/scala/ocelot/desktop/color_v2/ColorTest.scala +++ b/src/test/scala/ocelot/desktop/color_v2/ColorTest.scala @@ -27,9 +27,9 @@ class ColorTest extends UnitTest { } test("LinearR8 encoding examples") { - checkEncoding(Encoding.LinearR8, Array(0x00.toByte), 0xFF_0000_0000_0000L) - checkEncoding(Encoding.LinearR8, Array(0x13.toByte), 0xFF_1313_1313_1313L) - checkEncoding(Encoding.LinearR8, Array(0xFF.toByte), 0xFF_FFFF_FFFF_FFFFL) + checkEncoding(Encoding.LinearR8, Array(0x00.toByte), 0xff_0000_0000_0000L) + checkEncoding(Encoding.LinearR8, Array(0x13.toByte), 0xff_1313_1313_1313L) + checkEncoding(Encoding.LinearR8, Array(0xff.toByte), 0xff_ffff_ffff_ffffL) } test("LinearR8 encoding round-trip") { @@ -39,9 +39,9 @@ class ColorTest extends UnitTest { } test("LinearRgb8 encoding examples") { - checkEncoding(Encoding.LinearRgb8, Array(0x00.toByte, 0x00.toByte, 0x00.toByte), 0xFF_0000_0000_0000L) - checkEncoding(Encoding.LinearRgb8, Array(0x12.toByte, 0x34.toByte, 0x56.toByte), 0xFF_1212_3434_5656L) - checkEncoding(Encoding.LinearRgb8, Array(0xFF.toByte, 0xFF.toByte, 0xFF.toByte), 0xFF_FFFF_FFFF_FFFFL) + checkEncoding(Encoding.LinearRgb8, Array(0x00.toByte, 0x00.toByte, 0x00.toByte), 0xff_0000_0000_0000L) + checkEncoding(Encoding.LinearRgb8, Array(0x12.toByte, 0x34.toByte, 0x56.toByte), 0xff_1212_3434_5656L) + checkEncoding(Encoding.LinearRgb8, Array(0xff.toByte, 0xff.toByte, 0xff.toByte), 0xff_ffff_ffff_ffffL) } test("LinearRgb8 encoding round-trip") { @@ -51,9 +51,9 @@ class ColorTest extends UnitTest { } test("SrgbRgb8 encoding examples") { - checkEncoding(Encoding.SrgbRgb8, Array(0x00.toByte, 0x00.toByte, 0x00.toByte), 0xFF_0000_0000_0000L) - checkEncoding(Encoding.SrgbRgb8, Array(0x12.toByte, 0x34.toByte, 0x56.toByte), 0xFF_018C_08Ca_17D2L) - checkEncoding(Encoding.SrgbRgb8, Array(0xFF.toByte, 0xFF.toByte, 0xFF.toByte), 0xFF_FFFF_FFFF_FFFFL) + checkEncoding(Encoding.SrgbRgb8, Array(0x00.toByte, 0x00.toByte, 0x00.toByte), 0xff_0000_0000_0000L) + checkEncoding(Encoding.SrgbRgb8, Array(0x12.toByte, 0x34.toByte, 0x56.toByte), 0xff_018c_08ca_17d2L) + checkEncoding(Encoding.SrgbRgb8, Array(0xff.toByte, 0xff.toByte, 0xff.toByte), 0xff_ffff_ffff_ffffL) } test("SrgbRgb8 round-trip") { @@ -65,7 +65,7 @@ class ColorTest extends UnitTest { test("LinearRgba8 encoding examples") { checkEncoding(Encoding.LinearRgba8, Array(0x00.toByte, 0x00.toByte, 0x00.toByte, 0x00.toByte), 0x00_0000_0000_0000L) checkEncoding(Encoding.LinearRgba8, Array(0x12.toByte, 0x34.toByte, 0x56.toByte, 0x42.toByte), 0x42_1212_3434_5656L) - checkEncoding(Encoding.LinearRgba8, Array(0xFF.toByte, 0xFF.toByte, 0xFF.toByte, 0xFF.toByte), 0xFF_FFFF_FFFF_FFFFL) + checkEncoding(Encoding.LinearRgba8, Array(0xff.toByte, 0xff.toByte, 0xff.toByte, 0xff.toByte), 0xff_ffff_ffff_ffffL) } test("LinearRgba8 encoding round-trip") { @@ -76,8 +76,8 @@ class ColorTest extends UnitTest { test("SrgbRgba8 encoding examples") { checkEncoding(Encoding.SrgbRgba8, Array(0x00.toByte, 0x00.toByte, 0x00.toByte, 0x00.toByte), 0x00_0000_0000_0000L) - checkEncoding(Encoding.SrgbRgba8, Array(0x12.toByte, 0x34.toByte, 0x56.toByte, 0x42.toByte), 0x42_018C_08Ca_17D2L) - checkEncoding(Encoding.SrgbRgba8, Array(0xFF.toByte, 0xFF.toByte, 0xFF.toByte, 0xFF.toByte), 0xFF_FFFF_FFFF_FFFFL) + checkEncoding(Encoding.SrgbRgba8, Array(0x12.toByte, 0x34.toByte, 0x56.toByte, 0x42.toByte), 0x42_018c_08ca_17d2L) + checkEncoding(Encoding.SrgbRgba8, Array(0xff.toByte, 0xff.toByte, 0xff.toByte, 0xff.toByte), 0xff_ffff_ffff_ffffL) } test("SrgbRgba8 encoding round-trip") { @@ -92,18 +92,18 @@ class ColorTest extends UnitTest { } test("Alpha blending (opaque foreground)") { - checkAlphaBlending(0xFF_1234_5678_9ABCL, 0xFF_CBA9_8765_4321L, 0xFF_CBA9_8765_4321L); + checkAlphaBlending(0xff_1234_5678_9abcL, 0xff_cba9_8765_4321L, 0xff_cba9_8765_4321L); } test("Alpha blending (white bg + 33% black fg)") { - checkAlphaBlending(0xFF_FFFF_FFFF_FFFFL, 0x55_0000_0000_0000L, 0xFF_AAAA_AAAA_AAAAL); + checkAlphaBlending(0xff_ffff_ffff_ffffL, 0x55_0000_0000_0000L, 0xff_aaaa_aaaa_aaaaL); } test("Alpha blending (white bg, 50% black fg)") { - checkAlphaBlending(0xFF_FFFF_FFFF_FFFFL, 0x80_0000_0000_0000L, 0xFF_7F7F_7F7F_7F7FL); + checkAlphaBlending(0xff_ffff_ffff_ffffL, 0x80_0000_0000_0000L, 0xff_7f7f_7f7f_7f7fL); } test("Alpha blending (33% red bg, 66% cyan fg)") { - checkAlphaBlending(0x55_5555_0000_0000L, 0xAA_0000_AAAA_AAAAL, 0xC6_1C72_AAAA_AAAAL); + checkAlphaBlending(0x55_5555_0000_0000L, 0xaa_0000_aaaa_aaaaL, 0xc6_1c72_aaaa_aaaaL); } } diff --git a/src/test/scala/ocelot/desktop/color_v2/repr/LinearRgbaTest.scala b/src/test/scala/ocelot/desktop/color_v2/repr/LinearRgbaTest.scala index b57cd72..0027b2e 100644 --- a/src/test/scala/ocelot/desktop/color_v2/repr/LinearRgbaTest.scala +++ b/src/test/scala/ocelot/desktop/color_v2/repr/LinearRgbaTest.scala @@ -10,18 +10,18 @@ class LinearRgbaTest extends UnitTest { } test("Pure red") { - checkConversion(LinearRgba(1.0, 0.0, 0.0, 1.0), 0xFF_FFFF_0000_0000L) + checkConversion(LinearRgba(1.0, 0.0, 0.0, 1.0), 0xff_ffff_0000_0000L) } test("Pure green") { - checkConversion(LinearRgba(0.0, 1.0, 0.0, 1.0), 0xFF_0000_FFFF_0000L) + checkConversion(LinearRgba(0.0, 1.0, 0.0, 1.0), 0xff_0000_ffff_0000L) } test("Pure blue") { - checkConversion(LinearRgba(0.0, 0.0, 1.0, 1.0), 0xFF_0000_0000_FFFFL) + checkConversion(LinearRgba(0.0, 0.0, 1.0, 1.0), 0xff_0000_0000_ffffL) } test("33% red, 66% blue, 33% alpha") { - checkConversion(LinearRgba(1.0 / 3.0, 0.0, 2.0 / 3.0, 1.0 / 3.0), 0x55_5555_0000_AAAAL) + checkConversion(LinearRgba(1.0 / 3.0, 0.0, 2.0 / 3.0, 1.0 / 3.0), 0x55_5555_0000_aaaaL) } } diff --git a/src/test/scala/ocelot/desktop/color_v2/repr/OkhsvTest.scala b/src/test/scala/ocelot/desktop/color_v2/repr/OkhsvTest.scala index ec8be42..53ea0f7 100644 --- a/src/test/scala/ocelot/desktop/color_v2/repr/OkhsvTest.scala +++ b/src/test/scala/ocelot/desktop/color_v2/repr/OkhsvTest.scala @@ -10,18 +10,18 @@ class OkhsvTest extends UnitTest { } test("Pure red") { - checkConversion(Okhsv(29.23388519234263, 0.9995219692256989, 1.0000000001685625, 1), 0xFF_FFFF_0000_0000L) + checkConversion(Okhsv(29.23388519234263, 0.9995219692256989, 1.0000000001685625, 1), 0xff_ffff_0000_0000L) } test("Pure green") { - checkConversion(Okhsv(142.49533888780996, 0.9999997210415695, 0.9999999884428648, 1.0), 0xFF_0000_FFFF_0000L) + checkConversion(Okhsv(142.49533888780996, 0.9999997210415695, 0.9999999884428648, 1.0), 0xff_0000_ffff_0000L) } test("Pure blue") { - checkConversion(Okhsv(264.052020638055, 0.9999910912349018, 0.9999999646150918, 1), 0xFF_0000_0000_FFFFL) + checkConversion(Okhsv(264.052020638055, 0.9999910912349018, 0.9999999646150918, 1), 0xff_0000_0000_ffffL) } test("33% red, 66% blue, 33% alpha") { - checkConversion(Okhsv(311.9937528323292, 1.0005489476783134, 0.8409729279819962, 1.0 / 3.0), 0x55_5555_0000_AAAAL) + checkConversion(Okhsv(311.9937528323292, 1.0005489476783134, 0.8409729279819962, 1.0 / 3.0), 0x55_5555_0000_aaaaL) } } diff --git a/src/test/scala/ocelot/desktop/color_v2/repr/OklabTest.scala b/src/test/scala/ocelot/desktop/color_v2/repr/OklabTest.scala index 3f70bbb..54b84f4 100644 --- a/src/test/scala/ocelot/desktop/color_v2/repr/OklabTest.scala +++ b/src/test/scala/ocelot/desktop/color_v2/repr/OklabTest.scala @@ -10,18 +10,18 @@ class OklabTest extends UnitTest { } test("Pure red") { - checkConversion(Oklab(0.6279553606145516, 0.22486306106597398, 0.1258462985307351, 1), 0xFF_FFFF_0000_0000L) + checkConversion(Oklab(0.6279553606145516, 0.22486306106597398, 0.1258462985307351, 1), 0xff_ffff_0000_0000L) } test("Pure green") { - checkConversion(Oklab(0.8664396115356694, -0.23388757418790818, 0.17949847989672985, 1.0), 0xFF_0000_FFFF_0000L) + checkConversion(Oklab(0.8664396115356694, -0.23388757418790818, 0.17949847989672985, 1.0), 0xff_0000_ffff_0000L) } test("Pure blue") { - checkConversion(Oklab(0.4520137183853429, -0.03245698416876397, -0.3115281476783751, 1), 0xFF_0000_0000_FFFFL) + checkConversion(Oklab(0.4520137183853429, -0.03245698416876397, -0.3115281476783751, 1), 0xff_0000_0000_ffffL) } test("33% red, 66% blue, 33% alpha") { - checkConversion(Oklab(0.5281181319927706, 0.176826580031683, -0.19642887916863233, 1f / 3f), 0x55_5555_0000_AAAAL) + checkConversion(Oklab(0.5281181319927706, 0.176826580031683, -0.19642887916863233, 1f / 3f), 0x55_5555_0000_aaaaL) } } diff --git a/src/test/scala/ocelot/desktop/color_v2/repr/PackedIntTest.scala b/src/test/scala/ocelot/desktop/color_v2/repr/PackedIntTest.scala index c2a8f95..5aa8909 100644 --- a/src/test/scala/ocelot/desktop/color_v2/repr/PackedIntTest.scala +++ b/src/test/scala/ocelot/desktop/color_v2/repr/PackedIntTest.scala @@ -10,18 +10,18 @@ class PackedIntTest extends UnitTest { } test("Pure red") { - checkConversion(PackedInt(0xFF0000), 0xFF_FFFF_0000_0000L) + checkConversion(PackedInt(0xff0000), 0xff_ffff_0000_0000L) } test("Pure green") { - checkConversion(PackedInt(0x00FF00), 0xFF_0000_FFFF_0000L) + checkConversion(PackedInt(0x00ff00), 0xff_0000_ffff_0000L) } test("Pure blue") { - checkConversion(PackedInt(0x0000FF), 0xFF_0000_0000_FFFFL) + checkConversion(PackedInt(0x0000ff), 0xff_0000_0000_ffffL) } test("33% red, 66% blue") { - checkConversion(PackedInt(0x5500AA), 0xFF_1741_0000_66E7L) + checkConversion(PackedInt(0x5500aa), 0xff_1741_0000_66e7L) } }