diff options
author | Miran <narimiran@disroot.org> | 2019-05-21 21:28:30 +0200 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2019-05-21 21:28:29 +0200 |
commit | 68b5e3e3fe8c4bf314d31d18c147650db99b4f7d (patch) | |
tree | 05a09396b30cc186e3a38ad20b6afb7a35618861 | |
parent | 1251e1ad16845203decb5c9087e6e0240c8d066f (diff) | |
download | Nim-68b5e3e3fe8c4bf314d31d18c147650db99b4f7d.tar.gz |
colors: fix `mix`, add documentation (#11295)
-rw-r--r-- | lib/pure/colors.nim | 124 |
1 files changed, 104 insertions, 20 deletions
diff --git a/lib/pure/colors.nim b/lib/pure/colors.nim index b58166b05..159bc8023 100644 --- a/lib/pure/colors.nim +++ b/lib/pure/colors.nim @@ -13,10 +13,18 @@ import strutils from algorithm import binarySearch type - Color* = distinct int ## a color stored as RGB + Color* = distinct int ## A color stored as RGB, e.g. `0xff00cc`. proc `==` *(a, b: Color): bool {.borrow.} - ## compares two colors. + ## Compares two colors. + ## + ## .. code-block:: + ## var + ## a = Color(0xff_00_ff) + ## b = colFuchsia + ## c = Color(0x00_ff_cc) + ## assert a == b + ## assert not a == c template extract(a: Color, r, g, b: untyped) = var r = a.int shr 16 and 0xff @@ -40,24 +48,58 @@ proc satMinus(a, b: int): int {.inline.} = if result < 0: result = 0 proc `+`*(a, b: Color): Color = - ## adds two colors: This uses saturated artithmetic, so that each color + ## Adds two colors. + ## + ## This uses saturated artithmetic, so that each color ## component cannot overflow (255 is used as a maximum). + ## + ## .. code-block:: + ## var + ## a = Color(0xaa_00_ff) + ## b = Color(0x11_cc_cc) + ## assert a + b == Color(0xbb_cc_ff) + ## colorOp(satPlus) proc `-`*(a, b: Color): Color = - ## subtracts two colors: This uses saturated artithmetic, so that each color - ## component cannot overflow (255 is used as a maximum). + ## Subtracts two colors. + ## + ## This uses saturated artithmetic, so that each color + ## component cannot underflow (0 is used as a minimum). + ## + ## .. code-block:: + ## var + ## a = Color(0xff_33_ff) + ## b = Color(0x11_ff_cc) + ## assert a - b == Color(0xee_00_33) + ## colorOp(satMinus) proc extractRGB*(a: Color): tuple[r, g, b: range[0..255]] = - ## extracts the red/green/blue components of the color `a`. + ## Extracts the red/green/blue components of the color `a`. + ## + ## .. code-block:: + ## var + ## a = Color(0xff_00_ff) + ## b = Color(0x00_ff_cc) + ## echo extractRGB(a) # => (r: 255, g: 0, b: 255) + ## echo extractRGB(b) # => (r: 0, g: 255, b: 204) + ## result.r = a.int shr 16 and 0xff result.g = a.int shr 8 and 0xff result.b = a.int and 0xff proc intensity*(a: Color, f: float): Color = - ## returns `a` with intensity `f`. `f` should be a float from 0.0 (completely + ## Returns `a` with intensity `f`. `f` should be a float from 0.0 (completely ## dark) to 1.0 (full color intensity). + ## + ## .. code-block:: + ## var + ## a = Color(0xff_00_ff) + ## b = Color(0x00_42_cc) + ## assert a.intensity(0.5) == Color(0x80_00_80) + ## assert b.intensity(0.5) == Color(0x00_21_66) + ## var r = toInt(toFloat(a.int shr 16 and 0xff) * f) var g = toInt(toFloat(a.int shr 8 and 0xff) * f) var b = toInt(toFloat(a.int and 0xff) * f) @@ -67,10 +109,22 @@ proc intensity*(a: Color, f: float): Color = result = rawRGB(r, g, b) template mix*(a, b: Color, fn: untyped): untyped = - ## uses `fn` to mix the colors `a` and `b`. `fn` is invoked for each component - ## R, G, and B. This is a template because `fn` should be inlined and the - ## compiler cannot inline proc pointers yet. If `fn`'s result is not in the - ## range[0..255], it will be saturated to be so. + ## Uses `fn` to mix the colors `a` and `b`. + ## + ## `fn` is invoked for each component R, G, and B. + ## If `fn`'s result is not in the `range[0..255]`, + ## it will be saturated to be so. + ## + ## .. code-block:: + ## var + ## a = Color(0x0a2814) + ## b = Color(0x050a03) + ## + ## proc myMix(x, y: int): int = + ## 2 * x - 3 * y + ## + ## assert mix(a, b, myMix) == Color(0x05_32_1f) + ## template `><` (x: untyped): untyped = # keep it in the range 0..255 block: @@ -79,9 +133,10 @@ template mix*(a, b: Color, fn: untyped): untyped = y = if y < 0: 0 else: 255 y - (bind extract)(a, ar, ag, ab) - (bind extract)(b, br, bg, bb) - (bind rawRGB)(><fn(ar, br), ><fn(ag, bg), ><fn(ab, bb)) + var ar, ag, ab, br, bg, bb: int + extract(a, ar, ag, ab) + extract(b, br, bg, bb) + rawRGB(><fn(ar, br), ><fn(ag, bg), ><fn(ab, bb)) const @@ -369,15 +424,31 @@ const ("yellowgreen", colYellowGreen)] proc `$`*(c: Color): string = - ## converts a color into its textual representation. Example: ``#00FF00``. + ## Converts a color into its textual representation. + ## + ## .. code-block:: + ## assert $colFuchsia == "#FF00FF" + ## result = '#' & toHex(int(c), 6) proc colorNameCmp(x: tuple[name: string, col: Color], y: string): int = result = cmpIgnoreCase(x.name, y) proc parseColor*(name: string): Color = - ## parses `name` to a color value. If no valid color could be - ## parsed ``ValueError`` is raised. Case insensitive. + ## Parses `name` to a color value. + ## + ## If no valid color could be parsed ``ValueError`` is raised. + ## Case insensitive. + ## + ## .. code-block:: + ## var + ## a = "silver" + ## b = "#0179fc" + ## c = "#zzmmtt" + ## assert parseColor(a) == Color(0xc0_c0_c0) + ## assert parseColor(b) == Color(0x01_79_fc) + ## doAssertRaises(ValueError): discard parseColor(c) + ## if name[0] == '#': result = Color(parseHexInt(name)) else: @@ -386,8 +457,18 @@ proc parseColor*(name: string): Color = result = colorNames[idx][1] proc isColor*(name: string): bool = - ## returns true if `name` is a known color name or a hexadecimal color + ## Returns true if `name` is a known color name or a hexadecimal color ## prefixed with ``#``. Case insensitive. + ## + ## .. code-block:: + ## var + ## a = "silver" + ## b = "#0179fc" + ## c = "#zzmmtt" + ## assert a.isColor + ## assert b.isColor + ## assert not c.isColor + ## if name[0] == '#': for i in 1 .. name.len-1: if name[i] notin {'0'..'9', 'a'..'f', 'A'..'F'}: return false @@ -396,6 +477,9 @@ proc isColor*(name: string): bool = result = binarySearch(colorNames, name, colorNameCmp) >= 0 proc rgb*(r, g, b: range[0..255]): Color = - ## constructs a color from RGB values. + ## Constructs a color from RGB values. + ## + ## .. code-block:: + ## assert rgb(0, 255, 128) == Color(0x00_ff_80) + ## result = rawRGB(r, g, b) - |