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/display | |
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/display')
-rw-r--r-- | src/display/term.nim | 191 |
1 files changed, 101 insertions, 90 deletions
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) = |