diff options
author | bptato <nincsnevem662@gmail.com> | 2024-02-24 18:14:00 +0100 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2024-02-24 18:19:58 +0100 |
commit | f11c942585446be074412b2cc270f30532351882 (patch) | |
tree | 5bc37a67f6bde5dccd8d685b47ef6f9602e33a26 /src | |
parent | ea3c192626b4a33d9a6201d82a1b4a1f306f58eb (diff) | |
download | chawan-f11c942585446be074412b2cc270f30532351882.tar.gz |
Allow non-RGB colors in CSS
The -cha-ansi color type now sets ANSI colors in CSS. Also, color correction etc. has been improved a bit: * don't completely reset output state in processFormat for new colors * defaultColor is now separated from ANSI color type 0 * bright ANSI colors are no longer replaced with bold + dark variant * replaced ANSI color map to match xterm defaults
Diffstat (limited to 'src')
-rw-r--r-- | src/css/cascade.nim | 6 | ||||
-rw-r--r-- | src/css/values.nim | 144 | ||||
-rw-r--r-- | src/display/term.nim | 191 | ||||
-rw-r--r-- | src/html/dom.nim | 10 | ||||
-rw-r--r-- | src/img/png.nim | 2 | ||||
-rw-r--r-- | src/render/renderdocument.nim | 32 | ||||
-rw-r--r-- | src/types/cell.nim | 11 | ||||
-rw-r--r-- | src/types/color.nim | 36 |
8 files changed, 252 insertions, 180 deletions
diff --git a/src/css/cascade.nim b/src/css/cascade.nim index 13282b4f..84eb481c 100644 --- a/src/css/cascade.nim +++ b/src/css/cascade.nim @@ -131,7 +131,7 @@ func calcPresentationalHints(element: Element): CSSComputedValues = if s != "": let c = parseLegacyColor(s) if c.isSome: - set_cv "background-color", c.get + set_cv "background-color", c.get.cellColor() template map_size = let s = element.attrul(atSize) if s.isSome: @@ -161,13 +161,13 @@ func calcPresentationalHints(element: Element): CSSComputedValues = if s != "": let c = parseLegacyColor(s) if c.isSome: - set_cv "color", c.get + set_cv "color", c.get.cellColor() template map_color = let s = element.attr(atColor) if s != "": let c = parseLegacyColor(s) if c.isSome: - set_cv "color", c.get + set_cv "color", c.get.cellColor() template map_colspan = let colspan = element.attrulgz(atColspan) if colspan.isSome: diff --git a/src/css/values.nim b/src/css/values.nim index bad8ef4a..a7296b8e 100644 --- a/src/css/values.nim +++ b/src/css/values.nim @@ -174,7 +174,7 @@ type CSSComputedValue* = ref object case v*: CSSValueType of VALUE_COLOR: - color*: RGBAColor + color*: CellColor of VALUE_LENGTH: length*: CSSLength of VALUE_FONT_STYLE: @@ -592,66 +592,114 @@ func parseDimensionValues*(s: string): Option[CSSLength] = if s[i] == '%': return some(CSSLength(num: n, unit: UNIT_PERC)) return some(CSSLength(num: n, unit: UNIT_PX)) -func skipWhitespace(vals: seq[CSSComponentValue], i: var int) = +func skipWhitespace(vals: openArray[CSSComponentValue], i: var int) = while i < vals.len: if vals[i] != CSS_WHITESPACE_TOKEN: break inc i -func cssColor*(val: CSSComponentValue): Opt[RGBAColor] = +func parseRGBA(value: openArray[CSSComponentValue]): Opt[CellColor] = + var i = 0 + var commaMode = false + template check_err(slash: bool) = + #TODO calc, percentages, etc (cssnumber function or something) + if not slash and i >= value.len or i < value.len and + value[i] != CSS_NUMBER_TOKEN: + return err() + template next_value(first = false, slash = false) = + inc i + value.skipWhitespace(i) + if i < value.len: + if value[i] == CSS_COMMA_TOKEN and (commaMode or first): + # legacy compatibility + inc i + value.skipWhitespace(i) + commaMode = true + elif commaMode: + return err() + elif slash: + let tok = value[i] + if tok != CSS_DELIM_TOKEN or CSSToken(tok).cvalue != '/': + return err() + inc i + value.skipWhitespace(i) + check_err slash + value.skipWhitespace(i) + check_err false + let r = CSSToken(value[i]).nvalue + next_value true + let g = CSSToken(value[i]).nvalue + next_value + let b = CSSToken(value[i]).nvalue + next_value false, true + let a = if i < value.len: + CSSToken(value[i]).nvalue + else: + 1 + value.skipWhitespace(i) + if i < value.len: + return err() + return ok(rgba(int(r), int(g), int(b), int(a * 255)).cellColor()) + +# syntax: -cha-ansi( number | ident ) +# where number is an ANSI color (0..255) +# and ident is in NameTable and may start with "bright-" +func parseANSI(value: openArray[CSSComponentValue]): Opt[CellColor] = + var i = 0 + value.skipWhitespace(i) + if i != value.high or not (value[i] of CSSToken): # only 1 param is valid + #TODO numeric functions + return err() + let tok = CSSToken(value[i]) + if tok.tokenType == CSS_NUMBER_TOKEN: + if tok.nvalue notin 0..255: + return err() # invalid numeric ANSI color + return ok(ANSIColor(tok.nvalue).cellColor()) + elif tok.tokenType == CSS_IDENT_TOKEN: + var name = tok.value + if name.equalsIgnoreCase("default"): + return ok(defaultColor) + var bright = false + if name.startsWithIgnoreCase("bright-"): + bright = true + name = name.substr("bright-".len) + const NameTable = [ + "black", + "red", + "green", + "yellow", + "blue", + "magenta", + "cyan", + "white" + ] + for i, it in NameTable: + if it.equalsIgnoreCase(name): + var i = int(i) + if bright: + i += 8 + return ok(ANSIColor(i).cellColor()) + return err() + +func cssColor*(val: CSSComponentValue): Opt[CellColor] = if val of CSSToken: let tok = CSSToken(val) case tok.tokenType of CSS_HASH_TOKEN: let c = parseHexColor(tok.value) if c.isSome: - return ok(c.get) + return ok(c.get.cellColor()) of CSS_IDENT_TOKEN: - let s = tok.value + let s = tok.value.toLowerAscii() if s in Colors: - return ok(Colors[s]) + return ok(Colors[s].cellColor()) else: discard elif val of CSSFunction: let f = CSSFunction(val) - var i = 0 - var commaMode = false - template check_err(slash: bool) = - #TODO calc, percentages, etc (cssnumber function or something) - if not slash and i >= f.value.len or i < f.value.len and - f.value[i] != CSS_NUMBER_TOKEN: - return err() - template next_value(first = false, slash = false) = - inc i - f.value.skipWhitespace(i) - if i < f.value.len: - if f.value[i] == CSS_COMMA_TOKEN and (commaMode or first): - # legacy compatibility - inc i - f.value.skipWhitespace(i) - commaMode = true - elif commaMode: - return err() - elif slash: - let tok = f.value[i] - if tok != CSS_DELIM_TOKEN or CSSToken(tok).cvalue != '/': - return err() - inc i - f.value.skipWhitespace(i) - check_err slash if f.name.equalsIgnoreCase("rgb") or f.name.equalsIgnoreCase("rgba"): - f.value.skipWhitespace(i) - check_err false - let r = CSSToken(f.value[i]).nvalue - next_value true - let g = CSSToken(f.value[i]).nvalue - next_value - let b = CSSToken(f.value[i]).nvalue - next_value false, true - let a = if i < f.value.len: - CSSToken(f.value[i]).nvalue - else: - 1 - return ok(rgba(int(r), int(g), int(b), int(a * 255))) + return parseRGBA(f.value) + elif f.name.equalsIgnoreCase("-cha-ansi"): + return parseANSI(f.value) return err() func isToken(cval: CSSComponentValue): bool {.inline.} = cval of CSSToken @@ -1205,14 +1253,14 @@ proc getValueFromDecl(val: CSSComputedValue, d: CSSDeclaration, discard return ok() -func getInitialColor(t: CSSPropertyType): RGBAColor = +func getInitialColor(t: CSSPropertyType): CellColor = case t of PROPERTY_COLOR: - return Colors["white"] + return Colors["white"].cellColor() of PROPERTY_BACKGROUND_COLOR: - return Colors["transparent"] + return Colors["transparent"].cellColor() else: - return Colors["black"] + return Colors["black"].cellColor() func getInitialLength(t: CSSPropertyType): CSSLength = case t diff --git a/src/display/term.nim b/src/display/term.nim index afe84db6..588951cd 100644 --- a/src/display/term.nim +++ b/src/display/term.nim @@ -134,15 +134,24 @@ else: template SGR*(s: varargs[string, `$`]): string = CSI(s) & "m" +#TODO a) this should be customizable b) these defaults sucks const ANSIColorMap = [ - ColorsRGB["black"], - ColorsRGB["red"], - ColorsRGB["green"], - ColorsRGB["yellow"], - ColorsRGB["blue"], - ColorsRGB["magenta"], - ColorsRGB["cyan"], - ColorsRGB["white"], + rgb(0, 0, 0), + rgb(205, 0, 0), + rgb(0, 205, 0), + rgb(205, 205, 0), + rgb(0, 0, 238), + rgb(205, 0, 205), + rgb(0, 205, 205), + rgb(229, 229, 229), + rgb(127, 127, 127), + rgb(255, 0, 0), + rgb(0, 255, 0), + rgb(255, 255, 0), + rgb(92, 92, 255), + rgb(255, 0, 255), + rgb(0, 255, 255), + rgb(255, 255, 255) ] proc flush*(term: Terminal) = @@ -218,24 +227,28 @@ proc disableAltScreen(term: Terminal): string = func mincontrast(term: Terminal): int32 = return term.config.display.minimum_contrast -proc getRGB(a: CellColor, bg: bool): RGBColor = - if a.rgb: +proc getRGB(a: CellColor, termDefault: RGBColor): RGBColor = + case a.t + of ctNone: + return termDefault + of ctANSI: + if a.color >= 16: + return EightBitColor(a.color).toRGB() + return ANSIColorMap[a.color] + of ctRGB: return a.rgbcolor - elif a.color >= 16: - return eightBitToRGB(EightBitColor(a.color)) - return ANSIColorMap[a.color] # Use euclidian distance to quantize RGB colors. proc approximateANSIColor(rgb, termDefault: RGBColor): CellColor = var a = 0i32 var n = -1 for i in -1 .. ANSIColorMap.high: - let color = if i > 0: + let color = if i >= 0: ANSIColorMap[i] else: termDefault if color == rgb: - return if i == -1: defaultColor else: cellColor(ANSIColor(i)) + return if i == -1: defaultColor else: ANSIColor(i).cellColor() let x = int32(color.r) - int32(rgb.r) let y = int32(color.g) - int32(rgb.g) let z = int32(color.b) - int32(rgb.b) @@ -243,23 +256,17 @@ proc approximateANSIColor(rgb, termDefault: RGBColor): CellColor = let yy = y * y let zz = z * z let b = xx + yy + zz - if n == -1 or b < a: + if i == -1 or b < a: n = i a = b - return if n == -1: defaultColor else: cellColor(ANSIColor(n)) + return if n == -1: defaultColor else: ANSIColor(n).cellColor() # Return a fgcolor contrasted to the background by term.mincontrast. proc correctContrast(term: Terminal, bgcolor, fgcolor: CellColor): CellColor = let contrast = term.mincontrast let cfgcolor = fgcolor - let bgcolor = if bgcolor == defaultColor: - term.defaultBackground - else: - getRGB(bgcolor, true) - let fgcolor = if fgcolor == defaultColor: - term.defaultForeground - else: - getRGB(fgcolor, false) + let bgcolor = getRGB(bgcolor, term.defaultBackground) + let fgcolor = getRGB(fgcolor, term.defaultForeground) let bgY = int(bgcolor.Y) var fgY = int(fgcolor.Y) let diff = abs(bgY - fgY) @@ -283,91 +290,95 @@ proc correctContrast(term: Terminal, bgcolor, fgcolor: CellColor): CellColor = of ANSI: return approximateANSIColor(newrgb, term.defaultForeground) of EIGHT_BIT: - return cellColor(rgbToEightBit(newrgb)) + return cellColor(newrgb.toEightBit()) of MONOCHROME: doAssert false return cfgcolor +template ansiSGR(n: uint8, bgmod: int): string = + if n < 8: + SGR(30 + bgmod + n) + else: + SGR(82 + bgmod + n) + +template eightBitSGR(n: uint8, bgmod: int): string = + if n < 16: + ansiSGR(n, bgmod) + else: + SGR(38 + bgmod, 5, n) + +template rgbSGR(rgb: RGBColor, bgmod: int): string = + SGR(38 + bgmod, 2, rgb.r, rgb.g, rgb.b) + proc processFormat*(term: Terminal, format: var Format, cellf: Format): string = for flag in FormatFlags: if flag in term.formatmode: if flag in format.flags and flag notin cellf.flags: result &= term.endFormat(flag) - + if flag notin format.flags and flag in cellf.flags: + result &= term.startFormat(flag) var cellf = cellf case term.colormode of ANSI: - if not cellf.bgcolor.rgb and cellf.bgcolor.color > 15: - let color = cellf.bgcolor.eightbit - cellf.bgcolor = cellColor(eightBitToRGB(color)) - if not cellf.fgcolor.rgb and cellf.fgcolor.color > 15: - let color = cellf.fgcolor.eightbit - cellf.fgcolor = cellColor(eightBitToRGB(color)) - if cellf.bgcolor.rgb: + # quantize + if cellf.bgcolor.t == ctANSI and cellf.bgcolor.color > 15: + cellf.bgcolor = cellf.fgcolor.eightbit.toRGB().cellColor() + if cellf.bgcolor.t == ctRGB: cellf.bgcolor = approximateANSIColor(cellf.bgcolor.rgbcolor, term.defaultBackground) - if cellf.fgcolor.rgb: - if cellf.bgcolor == defaultColor: + if cellf.fgcolor.t == ctANSI and cellf.fgcolor.color > 15: + cellf.fgcolor = cellf.fgcolor.eightbit.toRGB().cellColor() + if cellf.fgcolor.t == ctRGB: + if cellf.bgcolor.t == ctNone: cellf.fgcolor = approximateANSIColor(cellf.fgcolor.rgbcolor, term.defaultForeground) else: - # ANSI non-default fgcolor AND bgcolor at the same time is assumed - # to be broken. + # ANSI fgcolor + bgcolor at the same time is broken cellf.fgcolor = defaultColor + # correct + cellf.fgcolor = term.correctContrast(cellf.bgcolor, cellf.fgcolor) + # print + case cellf.fgcolor.t + of ctNone: result &= SGR(39) + of ctANSI: result &= ansiSGR(cellf.fgcolor.color, 0) + else: assert false + case cellf.bgcolor.t + of ctNone: result &= SGR(49) + of ctANSI: result &= ansiSGR(cellf.bgcolor.color, 10) + else: assert false of EIGHT_BIT: - if cellf.bgcolor.rgb: - cellf.bgcolor = cellColor(rgbToEightBit(cellf.bgcolor.rgbcolor)) - if cellf.fgcolor.rgb: - cellf.fgcolor = cellColor(rgbToEightBit(cellf.fgcolor.rgbcolor)) - of MONOCHROME: - cellf.fgcolor = defaultColor - cellf.bgcolor = defaultColor - of TRUE_COLOR: discard - - if term.colormode != MONOCHROME: + # quantize + if cellf.bgcolor.t == ctRGB: + cellf.bgcolor = cellf.bgcolor.rgbcolor.toEightBit().cellColor() + if cellf.fgcolor.t == ctRGB: + cellf.fgcolor = cellf.fgcolor.rgbcolor.toEightBit().cellColor() + # correct cellf.fgcolor = term.correctContrast(cellf.bgcolor, cellf.fgcolor) - if cellf.fgcolor != format.fgcolor and cellf.fgcolor == defaultColor or - cellf.bgcolor != format.bgcolor and cellf.bgcolor == defaultColor: - result &= term.resetFormat() - format = Format() - - if cellf.fgcolor != format.fgcolor: - var color = cellf.fgcolor - if color.rgb: - assert term.colormode == TRUE_COLOR - let rgb = color.rgbcolor - result &= SGR(38, 2, rgb.r, rgb.g, rgb.b) - elif color == defaultColor: - discard - else: - let n = color.color - if n < 8: - result &= SGR(30 + n) - else: - assert term.colormode in {TRUE_COLOR, EIGHT_BIT} - result &= SGR(38, 5, n) - - if cellf.bgcolor != format.bgcolor: - var color = cellf.bgcolor - if color.rgb: - assert term.colormode == TRUE_COLOR - let rgb = color.rgbcolor - result &= SGR(48, 2, rgb.r, rgb.g, rgb.b) - elif color == defaultColor: - discard - else: - let n = color.color - if n < 8: - result &= SGR(40 + n) - else: - assert term.colormode in {TRUE_COLOR, EIGHT_BIT} - result &= SGR(48, 5, n) - - for flag in FormatFlags: - if flag in term.formatmode: - if flag notin format.flags and flag in cellf.flags: - result &= term.startFormat(flag) - + # print + case cellf.fgcolor.t + of ctNone: result &= SGR(39) + of ctANSI: result &= eightBitSGR(cellf.fgcolor.color, 0) + of ctRGB: assert false + case cellf.bgcolor.t + of ctNone: result &= SGR(49) + of ctANSI: result &= eightBitSGR(cellf.bgcolor.color, 10) + of ctRGB: assert false + of TRUE_COLOR: + # correct + cellf.fgcolor = term.correctContrast(cellf.bgcolor, cellf.fgcolor) + # print + if cellf.fgcolor != format.fgcolor: + case cellf.fgcolor.t + of ctNone: result &= SGR(39) + of ctANSI: result &= eightBitSGR(cellf.fgcolor.color, 0) + of ctRGB: result &= rgbSGR(cellf.fgcolor.rgbcolor, 0) + if cellf.bgcolor != format.bgcolor: + case cellf.bgcolor.t + of ctNone: result &= SGR(49) + of ctANSI: result &= eightBitSGR(cellf.bgcolor.color, 10) + of ctRGB: result &= rgbSGR(cellf.bgcolor.rgbcolor, 10) + of MONOCHROME: + discard # nothing to do format = cellf proc windowChange*(term: Terminal, attrs: WindowAttributes) = diff --git a/src/html/dom.nim b/src/html/dom.nim index 597d34b9..39a80681 100644 --- a/src/html/dom.nim +++ b/src/html/dom.nim @@ -2288,12 +2288,18 @@ isDefaultPassive = func (eventTarget: EventTarget): bool = proc parseColor(element: Element, s: string): RGBAColor = let cval = parseComponentValue(newStringStream(s)) - #TODO TODO TODO return element style + #TODO return element style # For now we just use white. let ec = rgb(255, 255, 255) if cval.isErr: return ec - return cssColor(cval.get).get(ec) + let color0 = cssColor(cval.get) + if color0.isErr: + return ec + let color = color0.get + if color.t != ctRGB: + return ec + return color.rgbacolor #TODO ?? func target0*(element: Element): string = diff --git a/src/img/png.nim b/src/img/png.nim index 8239c35f..047a080f 100644 --- a/src/img/png.nim +++ b/src/img/png.nim @@ -108,7 +108,7 @@ type PNGReader = object i: int bitDepth: uint8 colorType: PNGColorType - background: RGBColor + background: RGBAColor isend: bool idatBuf: seq[uint8] uprow: seq[uint8] diff --git a/src/render/renderdocument.nim b/src/render/renderdocument.nim index ed0bc809..7526b111 100644 --- a/src/render/renderdocument.nim +++ b/src/render/renderdocument.nim @@ -14,7 +14,6 @@ import utils/strwidth func toFormat(computed: CSSComputedValues): Format = if computed == nil: return Format() - let fgcolor = computed{"color"}.cellColor() var flags: set[FormatFlags] if computed{"font-style"} in {FONT_STYLE_ITALIC, FONT_STYLE_OBLIQUE}: flags.incl(FLAG_ITALIC) @@ -29,7 +28,7 @@ func toFormat(computed: CSSComputedValues): Format = if TEXT_DECORATION_BLINK in computed{"text-decoration"}: flags.incl(FLAG_BLINK) return Format( - fgcolor: fgcolor, + fgcolor: computed{"color"}, flags: flags ) @@ -319,8 +318,9 @@ proc paintInlineFragment(grid: var FlexibleGrid; fragment: InlineFragment; proc renderInlineFragment(grid: var FlexibleGrid; state: var RenderState, fragment: InlineFragment; offset: Offset; attrs: WindowAttributes) = assert fragment.atoms.len == 0 or fragment.children.len == 0 - if fragment.computed{"background-color"}.a > 0: # TODO color blending - let bgcolor = fragment.computed{"background-color"}.cellColor() + let bgcolor = fragment.computed{"background-color"} + if bgcolor.t == ctANSI or bgcolor.t == ctRGB and bgcolor.rgbacolor.a > 0: + #TODO color blending grid.paintInlineFragment(fragment, offset, bgcolor, attrs) if fragment.atoms.len > 0: let format = fragment.computed.toFormat() @@ -380,18 +380,18 @@ proc renderBlockBox(grid: var FlexibleGrid; state: var RenderState; stack.add((nil, Offset(x: -1, y: -1))) if box.computed{"visibility"} == VISIBILITY_VISIBLE: - if box.computed{"-cha-bgcolor-is-canvas"} and - state.bgcolor == defaultColor: - #TODO bgimage - if box.computed{"background-color"}.a != 0: #TODO color blending - state.bgcolor = box.computed{"background-color"}.cellColor() - if box.computed{"background-color"}.a != 0: #TODO color blending - let ix = toInt(offset.x) - let iy = toInt(offset.y) - let iex = toInt(offset.x + box.size.w) - let iey = toInt(offset.y + box.size.h) - let color = box.computed{"background-color"}.cellColor() - grid.paintBackground(color, ix, iy, iex, iey, box.node, attrs) + let bgcolor = box.computed{"background-color"} + if bgcolor.t == ctANSI or bgcolor.t == ctRGB and bgcolor.rgbacolor.a > 0: + if box.computed{"-cha-bgcolor-is-canvas"} and + state.bgcolor == defaultColor: + #TODO bgimage + state.bgcolor = bgcolor + #TODO color blending + let ix = toInt(offset.x) + let iy = toInt(offset.y) + let iex = toInt(offset.x + box.size.w) + let iey = toInt(offset.y + box.size.h) + grid.paintBackground(bgcolor, ix, iy, iex, iey, box.node, attrs) if box.computed{"background-image"}.t == CONTENT_IMAGE and box.computed{"background-image"}.s != "": # ugly hack for background-image display... TODO actually display images diff --git a/src/types/cell.nim b/src/types/cell.nim index f3ffd919..2f2e5203 100644 --- a/src/types/cell.nim +++ b/src/types/cell.nim @@ -204,11 +204,8 @@ proc parseSGRDefColor(parser: AnsiCodeParser, format: var Format, set_color cellColor(gray(param0)) elif u == 5: let param0 = parser.getParamU8(i, colon = true) - if param0 in 0u8..7u8: + if param0 in 0u8..15u8: set_color cellColor(ANSIColor(param0)) - elif param0 in 8u8..15u8: - format.bold = true - set_color cellColor(ANSIColor(param0 - 8)) elif param0 in 16u8..255u8: set_color cellColor(EightBitColor(param0)) else: @@ -229,11 +226,9 @@ proc parseSGRColor(parser: AnsiCodeParser, format: var Format, elif u == 49: format.bgcolor = defaultColor elif u in 90u8..97u8: - format.fgcolor = cellColor(ANSIColor(u - 90u8)) - format.bold = true + format.fgcolor = cellColor(ANSIColor(u - 82)) elif u in 100u8..107u8: - format.bgcolor = cellColor(ANSIColor(u - 90u8)) - format.bold = true + format.bgcolor = cellColor(ANSIColor(u - 92)) else: return false return true diff --git a/src/types/color.nim b/src/types/color.nim index 1a93792d..2f3f7310 100644 --- a/src/types/color.nim +++ b/src/types/color.nim @@ -19,11 +19,17 @@ type EightBitColor* = distinct uint8 + # ctNone: default color (intentionally 0), n is unused + # ctANSI: ANSI color, as selected by SGR 38/48 + # ctRGB: RGB color + ColorTag* {.size: sizeof(uint32).} = enum + ctNone, ctANSI, ctRGB + CellColor* = object - rgb*: bool + t*: ColorTag n: uint32 -converter toRGBColor*(i: RGBAColor): RGBColor = +func toRGBColor*(i: RGBAColor): RGBColor = return RGBColor(uint32(i) and 0xFFFFFFu32) converter toRGBAColor*(i: RGBColor): RGBAColor = @@ -36,6 +42,9 @@ func `==`*(a, b: ANSIColor): bool {.borrow.} func rgbcolor*(color: CellColor): RGBColor = cast[RGBColor](color.n) +func rgbacolor*(color: CellColor): RGBAColor = + cast[RGBAColor](color.n) + func color*(color: CellColor): uint8 = cast[uint8](color.n) @@ -43,17 +52,20 @@ func eightbit*(color: CellColor): EightBitColor = EightBitColor(color.color) func cellColor*(rgb: RGBColor): CellColor = - return CellColor(rgb: true, n: uint32(rgb)) + return CellColor(t: ctRGB, n: uint32(rgb) or 0xFF000000u32) -func cellColor*(c: ANSIColor): CellColor = - return CellColor(rgb: false, n: uint32(c) mod 10) +func cellColor*(rgba: RGBAColor): CellColor = + return CellColor(t: ctRGB, n: uint32(rgba)) -#TODO maybe bright ANSI colors? (8..15) +#TODO bright ANSI colors (8..15) + +func cellColor*(c: ANSIColor): CellColor = + return CellColor(t: ctANSI, n: uint32(c)) func cellColor*(c: EightBitColor): CellColor = - return CellColor(rgb: false, n: uint32(c)) + return CellColor(t: ctANSI, n: uint32(c)) -const defaultColor* = CellColor(rgb: false, n: 0) +const defaultColor* = CellColor(t: ctNone, n: 0) const ANSI_BLACK* = ANSIColor(0u8) @@ -374,7 +386,7 @@ func gray*(n: uint8): RGBColor = return rgb(n, n, n) #TODO use yuv instead? # NOTE: this assumes n notin 0..15 (which would be ANSI 4-bit) -func eightBitToRGB*(param0: EightBitColor): RGBColor = +func toRGB*(param0: EightBitColor): RGBColor = doAssert uint8(param0) notin 0u8..15u8 let u = uint8(param0) if u in 16u8..231u8: @@ -389,7 +401,7 @@ func eightBitToRGB*(param0: EightBitColor): RGBColor = let n = (u - 232) * 10 + 8 return gray(n) -func rgbToEightBit*(rgb: RGBColor): EightBitColor = +func toEightBit*(rgb: RGBColor): EightBitColor = let r = int(rgb.r) let g = int(rgb.g) let b = int(rgb.b) @@ -410,8 +422,8 @@ template `$`*(rgbcolor: RGBColor): string = "rgb(" & $rgbcolor.r & ", " & $rgbcolor.g & ", " & $rgbcolor.b & ")" template `$`*(color: CellColor): string = - if color.rgb: - $color.rgbcolor + if color.t == ctRGB: + $color.rgbacolor else: "tcolor" & $color.n |