Skip to content

Commit 3de60b6

Browse files
committed
Initial commit
0 parents  commit 3de60b6

File tree

8 files changed

+1521
-0
lines changed

8 files changed

+1521
-0
lines changed

.editorconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[*.scala]
2+
indent_style = space
3+
indent_size = 2
4+
5+
[*.java]
6+
indent_style = space
7+
indent_size = 4

.gitignore

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Scala SBT
2+
target/
3+
*.class
4+
.bsp
5+
6+
# IntelliJ IDEA
7+
*.iml
8+
*.ipr
9+
*.iws
10+
.idea/
11+
out/
12+
13+
# Directories
14+
.DS_Store
15+
.directory

build.sbt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Project info
2+
name := "ColorLib"
3+
organization := "io.github.scalamath"
4+
version := "1.0"
5+
description := "A Scala library for color math"
6+
// Project scala version
7+
scalaVersion := "2.13.12"
8+
9+
// VecMatLib dependency
10+
libraryDependencies += "io.github.scalamath" % "vecmatlib" % "3.0"
11+
// Scala test dependency
12+
libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.17" % Test
13+
// Junit test dependency
14+
libraryDependencies += "com.github.sbt" % "junit-interface" % "0.13.3" % Test
15+
16+
// Opt out of Scala-version source directory convention
17+
// Needed to run Java Junit tests
18+
crossPaths := false
19+
20+
// Show deprecation warnings
21+
scalacOptions ++= Seq("-unchecked", "-deprecation")

project/build.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
sbt.version = 1.9.9
Lines changed: 289 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
package io.github.scalamath.colorlib
2+
3+
import io.github.scalamath
4+
5+
/**
6+
* A color represented by a single integer in the RGBA format.
7+
*
8+
* This representation only requires 4 bytes, whereas [[Col4f]] requires 16, but does not allow values outside of the `[0, 255]` range.
9+
*
10+
* @constructor Constructs a color from the given integer value in the RGBA format.
11+
* @param rgba The integer value of this color in the RGBA format.
12+
*/
13+
case class Col1i(override val rgba: Int) extends Color {
14+
15+
/**
16+
* Constructs a color from the four given components in the `[0, 255]` range.
17+
*
18+
* Values outside of the range are clamped.
19+
*
20+
* @param r The red component of the color.
21+
* @param g The green component of the color.
22+
* @param b The blue component of the color.
23+
* @param a The alpha component of the color.
24+
*/
25+
def this(r: Int, g: Int, b: Int, a: Int) = this((scalamath.clamp(r, 0, 255) << 24) | (scalamath.clamp(g, 0, 255) << 16) | (scalamath.clamp(b, 0, 255) << 8) | scalamath.clamp(a, 0, 255))
26+
27+
/**
28+
* Constructs a color from the three given components in the `[0, 255]` range and sets the alpha component to `255`.
29+
*
30+
* Values outside of the range are clamped.
31+
*
32+
* @param r The red component of the color.
33+
* @param g The green component of the color.
34+
* @param b The blue component of the color.
35+
*/
36+
def this(r: Int, g: Int, b: Int) = this(r, g, b, 255)
37+
38+
/**
39+
* Constructs a color from the four given components in the `[0.0, 1.0] range`.
40+
*
41+
* Values outside of the range are clamped.
42+
*
43+
* @param r The red component of the color.
44+
* @param g The green component of the color.
45+
* @param b The blue component of the color.
46+
* @param a The alpha component of the color.
47+
*/
48+
def this(r: Float, g: Float, b: Float, a: Float) = this((scalamath.clamp(r, 0.0f, 1.0f) * 255.0f).round, (scalamath.clamp(g, 0.0f, 1.0f) * 255.0f).round, (scalamath.clamp(b, 0.0f, 1.0f) * 255.0f).round, (scalamath.clamp(a, 0.0f, 1.0f) * 255.0f).round)
49+
50+
/**
51+
* Constructs a color from the three given components and sets the alpha component to `1.0`.
52+
*
53+
* Values outside of the range are clamped.
54+
*
55+
* @param r The red component of the color.
56+
* @param g The green component of the color.
57+
* @param b The blue component of the color.
58+
*/
59+
def this(r: Float, g: Float, b: Float) = this(r, g, b, 1.0f)
60+
61+
/**
62+
* Returns the red component of this color as an integer in the `[0, 255]` range.
63+
*
64+
* @return The red component of this color as an integer in the `[0, 255]` range.
65+
*/
66+
override def r8: Int = (this.rgba >> 24) & 0xff
67+
68+
/**
69+
* Returns the red component of this color as a float in the `[0.0, 1.0]` range.
70+
*
71+
* @return Returns the red component of this color as a float in the `[0.0, 1.0]` range.
72+
*/
73+
override def r: Float = this.r8 / 255.0f
74+
75+
/**
76+
* Returns the green component of this color as an integer in the `[0, 255]` range.
77+
*
78+
* @return The green component of this color as an integer in the `[0, 255]` range.
79+
*/
80+
override def g8: Int = (this.rgba >> 16) & 0xff
81+
82+
/**
83+
* Returns the green component of this color as a float in the `[0.0, 1.0]` range.
84+
*
85+
* @return Returns the green component of this color as a float in the `[0.0, 1.0]` range.
86+
*/
87+
override def g: Float = this.g8 / 255.0f
88+
89+
/**
90+
* Returns the blue component of this color as an integer in the `[0, 255]` range.
91+
*
92+
* @return The blue component of this color as an integer in the `[0, 255]` range.
93+
*/
94+
override def b8: Int = (this.rgba >> 8) & 0xff
95+
96+
/**
97+
* Returns the blue component of this color as a float in the `[0.0, 1.0]` range.
98+
*
99+
* @return Returns the blue component of this color as a float in the `[0.0, 1.0]` range.
100+
*/
101+
override def b: Float = this.b8 / 255.0f
102+
103+
/**
104+
* Returns the alpha component of this color as an integer in the `[0, 255]` range.
105+
*
106+
* A value of 0 means that the color is fully transparent. A value of 255 means that the color is fully opaque.
107+
*
108+
* @return The alpha component of this color as an integer in the `[0, 255]` range.
109+
*/
110+
override def a8: Int = this.rgba & 0xff
111+
112+
/**
113+
* Returns the alpha component of this color as a float in the `[0.0, 1.0]` range.
114+
*
115+
* A value of 0 means that the color is fully transparent. A value of 1 means that the color is fully opaque.
116+
*
117+
* @return Returns the alpha component of this color as a float in the `[0.0, 1.0]` range.
118+
*/
119+
override def a: Float = this.a8 / 255.0f
120+
121+
/**
122+
* Adds the given values to each component of this color and returns the result.
123+
*
124+
* The result is clamped.
125+
*
126+
* @param r The red component to add in the `[0.0, 1.0]` range.
127+
* @param g The green component to add in the `[0.0, 1.0]` range.
128+
* @param b The blue component to add in the `[0.0, 1.0]` range.
129+
* @param a The alpha component to add in the `[0.0, 1.0]` range.
130+
* @return The sum between this color and the given components.
131+
*/
132+
override def +(r: Float, g: Float, b: Float, a: Float): Color = this + ((r * 255.0f).round, (g * 255.0f).round, (b * 255.0f).round, (a * 255.0f).round)
133+
134+
/**
135+
* Adds the given values to each component of this color and returns the result.
136+
*
137+
* The result is clamped.
138+
*
139+
* @param r The red component to add in the `[0, 255]` range.
140+
* @param g The green component to add in the `[0, 255]` range.
141+
* @param b The blue component to add in the `[0, 255]` range.
142+
* @param a The alpha component to add in the `[0, 255]` range.
143+
* @return The sum between this color and the given components.
144+
*/
145+
override def +(r: Int, g: Int, b: Int, a: Int): Color = Col1i(this.r8 + r, this.g8 + g, this.b8 + b, this.a8 + a)
146+
147+
/**
148+
* Subtracts the given values from each component of this color and returns the result.
149+
*
150+
* The result is clamped.
151+
*
152+
* @param r The red component to subtract in the `[0.0, 1.0]` range.
153+
* @param g The green component to subtract in the `[0.0, 1.0]` range.
154+
* @param b The blue component to subtract in the `[0.0, 1.0]` range.
155+
* @param a The alpha component to subtract in the `[0.0, 1.0]` range.
156+
* @return The subtraction between this color and the given components.
157+
*/
158+
override def -(r: Float, g: Float, b: Float, a: Float): Color = this - ((r * 255.0f).round, (g * 255.0f).round, (b * 255.0f).round, (a * 255.0f).round)
159+
160+
/**
161+
* Subtracts the given values from each component of this color and returns the result.
162+
*
163+
* The result is clamped.
164+
*
165+
* @param r The red component to subtract in the `[0, 255]` range.
166+
* @param g The green component to subtract in the `[0, 255]` range.
167+
* @param b The blue component to subtract in the `[0, 255]` range.
168+
* @param a The alpha component to subtract in the `[0, 255]` range.
169+
* @return The subtraction between this color and the given components.
170+
*/
171+
override def -(r: Int, g: Int, b: Int, a: Int): Color = Col1i(this.r8 - r, this.g8 - g, this.b8 - b, this.a8 - a)
172+
173+
/**
174+
* Multiplies each component of this color with the given values and returns the result.
175+
*
176+
* The result is clamped.
177+
*
178+
* @param r The red component to multiply in the `[0.0, 1.0]` range.
179+
* @param g The green component to multiply in the `[0.0, 1.0]` range.
180+
* @param b The blue component to multiply in the `[0.0, 1.0]` range.
181+
* @param a The alpha component to multiply in the `[0.0, 1.0]` range.
182+
* @return The component-wise product between this color and the given values.
183+
*/
184+
override def *(r: Float, g: Float, b: Float, a: Float): Color = Col1i((this.r8 * r).round, (this.g8 * g).round, (this.b8 * b).round, (this.a8 * a).round)
185+
186+
/**
187+
* Returns this color with its `r`, `g`, and `b` components inverted.
188+
*
189+
* This is the equivalent of `(255 - r, 255 - b, 255 - g)`.
190+
*
191+
* @return The inverse of this color.
192+
*/
193+
override def inverted: Color = Col1i(255 - this.r8, 255 - this.g8, 255 - this.b8, this.a8)
194+
195+
/**
196+
* Makes this color darker by the given amount and returns the result.
197+
*
198+
* @param k The ratio from `0.0` to `1.0`.
199+
* @return A color resulting from making this color darker by the given amount.
200+
* @see [[lighter]]
201+
*/
202+
override def darker(k: Float): Color = Col1i(this.r * (1.0f - k), this.g * (1.0f - k), this.b * (1.0f - k), this.a)
203+
204+
/**
205+
* Makes this color lighter by the given amount and returns the result.
206+
*
207+
* @param k The ratio from `0.0` to `1.0`.
208+
* @return A color resulting from making this color lighter by the given amount.
209+
* @see [[darker]]
210+
*/
211+
override def lighter(k: Float): Color = Col1i(this.r + (1.0f - this.r) * k, this.g + (1.0f - this.g) * k, this.b + (1.0f - this.b) * k, this.a)
212+
213+
/**
214+
* Blends this color and the given one and returns the result.
215+
*
216+
* @param c The color to blend this one with.
217+
* @return The color resulting from overlaying this color over the given one.
218+
*/
219+
override def blend(c: Color): Color = {
220+
val sa = 1.0f - c.a
221+
val a = this.a * sa + c.a
222+
if(a == 0.0f) {
223+
Col1i(0)
224+
} else {
225+
Col1i(
226+
(this.r * this.a * sa + c.r * c.a) / a,
227+
(this.g * this.a * sa + c.g * c.a) / a,
228+
(this.b * this.a * sa + c.b * c.a) / a, a
229+
)
230+
}
231+
}
232+
233+
override def toString: String = s"Col1i(${this.rgba.toHexString})"
234+
}
235+
236+
/**
237+
* Factory methods for colors.
238+
*/
239+
object Col1i {
240+
241+
/**
242+
* Constructs a color from the four given components in the `[0, 255]` range.
243+
*
244+
* Values outside of the range are clamped.
245+
*
246+
* @param r The red component of the color.
247+
* @param g The green component of the color.
248+
* @param b The blue component of the color.
249+
* @param a The alpha component of the color.
250+
* @return A new color constructed from the four given components.
251+
*/
252+
def apply(r: Int, g: Int, b: Int, a: Int) = new Col1i(r, g, b, a)
253+
254+
/**
255+
* Constructs a color from the three given components in the `[0, 255]` range and sets the alpha component to `255`.
256+
*
257+
* Values outside of the range are clamped.
258+
*
259+
* @param r The red component of the color.
260+
* @param g The green component of the color.
261+
* @param b The blue component of the color.
262+
* @return A new color constructed from the three given components.
263+
*/
264+
def apply(r: Int, g: Int, b: Int) = new Col1i(r, g, b)
265+
266+
/**
267+
* Constructs a color from the three given components in the `[0.0, 1.0]` range.
268+
*
269+
* Values outside of the range are clamped.
270+
*
271+
* @param r The red component of the color.
272+
* @param g The green component of the color.
273+
* @param b The blue component of the color.
274+
* @return A new color constructed from the three given components.
275+
*/
276+
def apply(r: Float, g: Float, b: Float, a: Float) = new Col1i(r, g, b, a)
277+
278+
/**
279+
* Constructs a color from the three given components and sets the alpha component to `1.0`.
280+
*
281+
* Values outside of the range are clamped.
282+
*
283+
* @param r The red component of the color.
284+
* @param g The green component of the color.
285+
* @param b The blue component of the color.
286+
* @return A new color constructed from the three given components.
287+
*/
288+
def apply(r: Float, g: Float, b: Float) = new Col1i(r, g, b)
289+
}

0 commit comments

Comments
 (0)