Skip to content

Commit

Permalink
Don't clamp when parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
ajalt committed Apr 16, 2024
1 parent 5194755 commit 36647f6
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 28 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

### Changed
- `Color.parse` now parses `lch()` and `lab()` functions with the with D50 white points instead of D65 in order to comply with the latest draft of CSS Color Module 4.
- `Color.parse` no longer clamps out-of-gamut values by default. Use the new `clamp` method on the returned color if desired.

### Fixed
- `ColorSpace.equals` will now properly return true when comparing color companions with the space they represent e.g. `XYZ == XYZ65`
Expand Down
45 changes: 44 additions & 1 deletion colormath/api/colormath.api
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public final class com/github/ajalt/colormath/AngleUnit : java/lang/Enum {

public abstract interface class com/github/ajalt/colormath/Color {
public static final field Companion Lcom/github/ajalt/colormath/Color$Companion;
public abstract fun clamp ()Lcom/github/ajalt/colormath/Color;
public abstract fun getAlpha ()F
public abstract fun getSpace ()Lcom/github/ajalt/colormath/ColorSpace;
public abstract fun toAnsi16 ()Lcom/github/ajalt/colormath/model/Ansi16;
Expand Down Expand Up @@ -39,6 +40,7 @@ public final class com/github/ajalt/colormath/Color$Companion {
}

public final class com/github/ajalt/colormath/Color$DefaultImpls {
public static fun clamp (Lcom/github/ajalt/colormath/Color;)Lcom/github/ajalt/colormath/Color;
public static fun toAnsi16 (Lcom/github/ajalt/colormath/Color;)Lcom/github/ajalt/colormath/model/Ansi16;
public static fun toAnsi256 (Lcom/github/ajalt/colormath/Color;)Lcom/github/ajalt/colormath/model/Ansi256;
public static fun toCMYK (Lcom/github/ajalt/colormath/Color;)Lcom/github/ajalt/colormath/model/CMYK;
Expand All @@ -61,6 +63,9 @@ public final class com/github/ajalt/colormath/Color$DefaultImpls {

public final class com/github/ajalt/colormath/ColorComponentInfo {
public fun <init> (Ljava/lang/String;Z)V
public fun <init> (Ljava/lang/String;ZFF)V
public final fun getMax ()F
public final fun getMin ()F
public final fun getName ()Ljava/lang/String;
public final fun isPolar ()Z
}
Expand Down Expand Up @@ -104,6 +109,7 @@ public abstract interface class com/github/ajalt/colormath/HueColor : com/github
}

public final class com/github/ajalt/colormath/HueColor$DefaultImpls {
public static fun clamp (Lcom/github/ajalt/colormath/HueColor;)Lcom/github/ajalt/colormath/Color;
public static fun toAnsi16 (Lcom/github/ajalt/colormath/HueColor;)Lcom/github/ajalt/colormath/model/Ansi16;
public static fun toAnsi256 (Lcom/github/ajalt/colormath/HueColor;)Lcom/github/ajalt/colormath/model/Ansi256;
public static fun toCMYK (Lcom/github/ajalt/colormath/HueColor;)Lcom/github/ajalt/colormath/model/CMYK;
Expand Down Expand Up @@ -195,6 +201,7 @@ public final class com/github/ajalt/colormath/calculate/GamutKt {
public final class com/github/ajalt/colormath/model/Ansi16 : com/github/ajalt/colormath/Color {
public static final field Companion Lcom/github/ajalt/colormath/model/Ansi16$Companion;
public fun <init> (I)V
public fun clamp ()Lcom/github/ajalt/colormath/Color;
public final fun component1 ()I
public final fun copy (I)Lcom/github/ajalt/colormath/model/Ansi16;
public static synthetic fun copy$default (Lcom/github/ajalt/colormath/model/Ansi16;IILjava/lang/Object;)Lcom/github/ajalt/colormath/model/Ansi16;
Expand Down Expand Up @@ -238,6 +245,7 @@ public final class com/github/ajalt/colormath/model/Ansi16$Companion : com/githu
public final class com/github/ajalt/colormath/model/Ansi256 : com/github/ajalt/colormath/Color {
public static final field Companion Lcom/github/ajalt/colormath/model/Ansi256$Companion;
public fun <init> (I)V
public fun clamp ()Lcom/github/ajalt/colormath/Color;
public final fun component1 ()I
public final fun copy (I)Lcom/github/ajalt/colormath/model/Ansi256;
public static synthetic fun copy$default (Lcom/github/ajalt/colormath/model/Ansi256;IILjava/lang/Object;)Lcom/github/ajalt/colormath/model/Ansi256;
Expand Down Expand Up @@ -286,6 +294,7 @@ public final class com/github/ajalt/colormath/model/CMYK : com/github/ajalt/colo
public synthetic fun <init> (IIIIFILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;)V
public synthetic fun <init> (Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun clamp ()Lcom/github/ajalt/colormath/Color;
public final fun component1 ()F
public final fun component2 ()F
public final fun component3 ()F
Expand Down Expand Up @@ -339,6 +348,8 @@ public final class com/github/ajalt/colormath/model/HPLuv : com/github/ajalt/col
public synthetic fun <init> (FFFFILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;)V
public synthetic fun <init> (Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun clamp ()Lcom/github/ajalt/colormath/Color;
public fun clamp ()Lcom/github/ajalt/colormath/model/HPLuv;
public final fun component1 ()F
public final fun component2 ()F
public final fun component3 ()F
Expand Down Expand Up @@ -390,6 +401,8 @@ public final class com/github/ajalt/colormath/model/HSL : com/github/ajalt/color
public synthetic fun <init> (FFFFILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;)V
public synthetic fun <init> (Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun clamp ()Lcom/github/ajalt/colormath/Color;
public fun clamp ()Lcom/github/ajalt/colormath/model/HSL;
public final fun component1 ()F
public final fun component2 ()F
public final fun component3 ()F
Expand Down Expand Up @@ -441,6 +454,8 @@ public final class com/github/ajalt/colormath/model/HSLuv : com/github/ajalt/col
public synthetic fun <init> (FFFFILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;)V
public synthetic fun <init> (Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun clamp ()Lcom/github/ajalt/colormath/Color;
public fun clamp ()Lcom/github/ajalt/colormath/model/HSLuv;
public final fun component1 ()F
public final fun component2 ()F
public final fun component3 ()F
Expand Down Expand Up @@ -492,6 +507,8 @@ public final class com/github/ajalt/colormath/model/HSV : com/github/ajalt/color
public synthetic fun <init> (FFFFILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;)V
public synthetic fun <init> (Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun clamp ()Lcom/github/ajalt/colormath/Color;
public fun clamp ()Lcom/github/ajalt/colormath/model/HSV;
public final fun component1 ()F
public final fun component2 ()F
public final fun component3 ()F
Expand Down Expand Up @@ -543,6 +560,8 @@ public final class com/github/ajalt/colormath/model/HWB : com/github/ajalt/color
public synthetic fun <init> (FFFFILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;)V
public synthetic fun <init> (Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun clamp ()Lcom/github/ajalt/colormath/Color;
public fun clamp ()Lcom/github/ajalt/colormath/model/HWB;
public final fun component1 ()F
public final fun component2 ()F
public final fun component3 ()F
Expand Down Expand Up @@ -594,6 +613,8 @@ public final class com/github/ajalt/colormath/model/ICtCp : com/github/ajalt/col
public synthetic fun <init> (FFFFILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;)V
public synthetic fun <init> (Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun clamp ()Lcom/github/ajalt/colormath/Color;
public fun clamp ()Lcom/github/ajalt/colormath/model/ICtCp;
public final fun component1 ()F
public final fun component2 ()F
public final fun component3 ()F
Expand Down Expand Up @@ -646,6 +667,8 @@ public final class com/github/ajalt/colormath/model/JzAzBz : com/github/ajalt/co
public synthetic fun <init> (FFFFILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;)V
public synthetic fun <init> (Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun clamp ()Lcom/github/ajalt/colormath/Color;
public fun clamp ()Lcom/github/ajalt/colormath/model/JzAzBz;
public final fun component1 ()F
public final fun component2 ()F
public final fun component3 ()F
Expand Down Expand Up @@ -697,6 +720,8 @@ public final class com/github/ajalt/colormath/model/JzCzHz : com/github/ajalt/co
public synthetic fun <init> (FFFFILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;)V
public synthetic fun <init> (Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun clamp ()Lcom/github/ajalt/colormath/Color;
public fun clamp ()Lcom/github/ajalt/colormath/model/JzCzHz;
public final fun component1 ()F
public final fun component2 ()F
public final fun component3 ()F
Expand Down Expand Up @@ -744,6 +769,8 @@ public final class com/github/ajalt/colormath/model/JzCzHz$Companion : com/githu

public final class com/github/ajalt/colormath/model/LAB : com/github/ajalt/colormath/Color {
public static final field Companion Lcom/github/ajalt/colormath/model/LAB$Companion;
public synthetic fun clamp ()Lcom/github/ajalt/colormath/Color;
public fun clamp ()Lcom/github/ajalt/colormath/model/LAB;
public final fun component1 ()F
public final fun component2 ()F
public final fun component3 ()F
Expand Down Expand Up @@ -819,6 +846,8 @@ public final class com/github/ajalt/colormath/model/LABKt {

public final class com/github/ajalt/colormath/model/LCHab : com/github/ajalt/colormath/HueColor {
public static final field Companion Lcom/github/ajalt/colormath/model/LCHab$Companion;
public synthetic fun clamp ()Lcom/github/ajalt/colormath/Color;
public fun clamp ()Lcom/github/ajalt/colormath/model/LCHab;
public final fun component1 ()F
public final fun component2 ()F
public final fun component3 ()F
Expand Down Expand Up @@ -894,6 +923,8 @@ public final class com/github/ajalt/colormath/model/LCHabKt {

public final class com/github/ajalt/colormath/model/LCHuv : com/github/ajalt/colormath/HueColor {
public static final field Companion Lcom/github/ajalt/colormath/model/LCHuv$Companion;
public synthetic fun clamp ()Lcom/github/ajalt/colormath/Color;
public fun clamp ()Lcom/github/ajalt/colormath/model/LCHuv;
public final fun component1 ()F
public final fun component2 ()F
public final fun component3 ()F
Expand Down Expand Up @@ -969,6 +1000,8 @@ public final class com/github/ajalt/colormath/model/LCHuvKt {

public final class com/github/ajalt/colormath/model/LUV : com/github/ajalt/colormath/Color {
public static final field Companion Lcom/github/ajalt/colormath/model/LUV$Companion;
public synthetic fun clamp ()Lcom/github/ajalt/colormath/Color;
public fun clamp ()Lcom/github/ajalt/colormath/model/LUV;
public final fun component1 ()F
public final fun component2 ()F
public final fun component3 ()F
Expand Down Expand Up @@ -1048,6 +1081,8 @@ public final class com/github/ajalt/colormath/model/Oklab : com/github/ajalt/col
public synthetic fun <init> (FFFFILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;)V
public synthetic fun <init> (Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun clamp ()Lcom/github/ajalt/colormath/Color;
public fun clamp ()Lcom/github/ajalt/colormath/model/Oklab;
public final fun component1 ()F
public final fun component2 ()F
public final fun component3 ()F
Expand Down Expand Up @@ -1099,6 +1134,8 @@ public final class com/github/ajalt/colormath/model/Oklch : com/github/ajalt/col
public synthetic fun <init> (FFFFILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;)V
public synthetic fun <init> (Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun clamp ()Lcom/github/ajalt/colormath/Color;
public fun clamp ()Lcom/github/ajalt/colormath/model/Oklch;
public final fun component1 ()F
public final fun component2 ()F
public final fun component3 ()F
Expand Down Expand Up @@ -1146,7 +1183,8 @@ public final class com/github/ajalt/colormath/model/Oklch$Companion : com/github

public final class com/github/ajalt/colormath/model/RGB : com/github/ajalt/colormath/Color {
public static final field Companion Lcom/github/ajalt/colormath/model/RGB$Companion;
public final fun clamp ()Lcom/github/ajalt/colormath/model/RGB;
public synthetic fun clamp ()Lcom/github/ajalt/colormath/Color;
public fun clamp ()Lcom/github/ajalt/colormath/model/RGB;
public final fun component1 ()F
public final fun component2 ()F
public final fun component3 ()F
Expand Down Expand Up @@ -1280,6 +1318,9 @@ public final class com/github/ajalt/colormath/model/RGBColorSpacesKt {
public final class com/github/ajalt/colormath/model/RGBInt : com/github/ajalt/colormath/Color {
public static final field Companion Lcom/github/ajalt/colormath/model/RGBInt$Companion;
public static final synthetic fun box-impl (I)Lcom/github/ajalt/colormath/model/RGBInt;
public synthetic fun clamp ()Lcom/github/ajalt/colormath/Color;
public fun clamp-RGiG7fk ()I
public static fun clamp-RGiG7fk (I)I
public static final fun component1-w2LRezQ (I)B
public static final fun component2-w2LRezQ (I)B
public static final fun component3-w2LRezQ (I)B
Expand Down Expand Up @@ -1393,6 +1434,8 @@ public final class com/github/ajalt/colormath/model/XYZ : com/github/ajalt/color
public final fun adaptTo (Lcom/github/ajalt/colormath/model/XYZColorSpace;)Lcom/github/ajalt/colormath/model/XYZ;
public final fun adaptTo (Lcom/github/ajalt/colormath/model/XYZColorSpace;[F)Lcom/github/ajalt/colormath/model/XYZ;
public final fun adaptTo (Lcom/github/ajalt/colormath/model/XYZColorSpace;[F[F)Lcom/github/ajalt/colormath/model/XYZ;
public synthetic fun clamp ()Lcom/github/ajalt/colormath/Color;
public fun clamp ()Lcom/github/ajalt/colormath/model/XYZ;
public final fun component1 ()F
public final fun component2 ()F
public final fun component3 ()F
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,9 @@ private fun rgb(match: MatchResult): Color {
val a = alpha(match.groupValues[4])

return if (match.groupValues[1].endsWith("%")) {
RGB(r.clampF(), g.clampF(), b.clampF(), a) // TODO: remove clamping and coerceAtLeast
RGB(r, g, b, a)
} else {
RGB(r.clampInt() / 255f, g.clampInt() / 255f, b.clampInt() / 255f, a)
RGB(r / 255f, g / 255f, b / 255f, a)
}
}

Expand All @@ -132,31 +132,31 @@ private fun hsl(match: MatchResult): Color {
val s = percentOrNumber(match.groupValues[2], HSL.components[1].max)
val l = percentOrNumber(match.groupValues[3], HSL.components[2].max)
val a = alpha(match.groupValues[4])
return HSL(h, s.clampF(), l.clampF(), a.clampF())
return HSL(h, s, l, a)
}

private fun lab(match: MatchResult): Color {
val l = percentOrNumber(match.groupValues[1], LAB.components[0].max)
val a = percentOrNumber(match.groupValues[2], LAB.components[1].max)
val b = percentOrNumber(match.groupValues[3], LAB.components[2].max)
val alpha = alpha(match.groupValues[4])
return LAB50(l.coerceAtLeast(0f), a, b, alpha)
return LAB50(l, a, b, alpha)
}

private fun lch(match: MatchResult): Color {
val l = percentOrNumber(match.groupValues[1], LCHab.components[0].max)
val c = percentOrNumber(match.groupValues[2], LCHab.components[1].max)
val h = hue(match.groupValues[3])
val a = alpha(match.groupValues[4])
return LCHab50(l.coerceAtLeast(0f), c.coerceAtLeast(0f), h, a)
return LCHab50(l, c, h, a)
}

private fun hwb(match: MatchResult): Color {
val h = hue(match.groupValues[1])
val w = percentOrNumber(match.groupValues[2], HWB.components[1].max)
val b = percentOrNumber(match.groupValues[3], HWB.components[2].max)
val a = alpha(match.groupValues[4])
return HWB(h, w.clampF(), b.clampF(), a)
return HWB(h, w, b, a)
}


Expand Down Expand Up @@ -187,7 +187,9 @@ private fun percentOrNumber(str: String, max: Float): Float {
}
}

private fun alpha(str: String) = (if (str.isEmpty()) 1f else percentOrNumber(str, 1f)).clampF()
private fun alpha(str: String): Float {
return (if (str.isEmpty()) 1f else percentOrNumber(str, 1f)).coerceIn(0f, 1f)
}

/** return degrees in [0, 360] */
private fun hue(str: String): Float {
Expand All @@ -199,6 +201,3 @@ private fun hue(str: String): Float {
else -> number(str)
}.normalizeDeg()
}

private fun Float.clampInt(min: Int = 0, max: Int = 255) = roundToInt().coerceIn(min, max)
private fun Float.clampF(min: Float = 0f, max: Float = 1f) = coerceIn(min, max)
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,6 @@ private fun Color.renderAlpha(
}
}

// TODO: HSL, HWB have different ref ranges
private fun Float.render(percent: Boolean = false, precision: Int = 4): String = when {
isNaN() -> "none"
percent -> "${(this * 100).roundToInt()}%"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ data class HWB(override val h: Float, val w: Float, val b: Float, override val a
val b = this.b / 100
val s = 1 - w / (1 - b)
val v = 1 - b
return HSV(h.roundToInt(), (s * 100).roundToInt(), (v * 100).roundToInt(), alpha)
return HSV(h, s * 100, v * 100, alpha)
}

override fun toHWB(): HWB = this
Expand Down
Loading

0 comments on commit 36647f6

Please sign in to comment.