about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/css/cascade.nim6
-rw-r--r--src/css/cssvalues.nim28
-rw-r--r--src/html/dom.nim6
-rw-r--r--src/io/bufreader.nim4
-rw-r--r--src/io/bufwriter.nim4
-rw-r--r--src/layout/renderdocument.nim30
-rw-r--r--src/local/pager.nim2
-rw-r--r--src/local/term.nim39
-rw-r--r--src/types/cell.nim20
-rw-r--r--src/types/color.nim137
10 files changed, 148 insertions, 128 deletions
diff --git a/src/css/cascade.nim b/src/css/cascade.nim
index ebb74427..865906aa 100644
--- a/src/css/cascade.nim
+++ b/src/css/cascade.nim
@@ -145,7 +145,7 @@ func calcPresentationalHints(element: Element): CSSComputedValues =
     if s != "":
       let c = parseLegacyColor(s)
       if c.isSome:
-        set_cv "background-color", c.get.cellColor()
+        set_cv "background-color", c.get.cssColor()
   template map_size =
     let s = element.attrul(satSize)
     if s.isSome:
@@ -155,13 +155,13 @@ func calcPresentationalHints(element: Element): CSSComputedValues =
     if s != "":
       let c = parseLegacyColor(s)
       if c.isSome:
-        set_cv "color", c.get.cellColor()
+        set_cv "color", c.get.cssColor()
   template map_color =
     let s = element.attr(satColor)
     if s != "":
       let c = parseLegacyColor(s)
       if c.isSome:
-        set_cv "color", c.get.cellColor()
+        set_cv "color", c.get.cssColor()
   template map_colspan =
     let colspan = element.attrulgz(satColspan)
     if colspan.isSome:
diff --git a/src/css/cssvalues.nim b/src/css/cssvalues.nim
index 6eac8148..03543576 100644
--- a/src/css/cssvalues.nim
+++ b/src/css/cssvalues.nim
@@ -330,7 +330,7 @@ type
   CSSComputedValue* = ref object
     case v*: CSSValueType
     of cvtColor:
-      color*: CellColor
+      color*: CSSColor
     of cvtLength:
       length*: CSSLength
     of cvtFontStyle:
@@ -817,7 +817,7 @@ func skipWhitespace(vals: openArray[CSSComponentValue]; i: var int) =
       break
     inc i
 
-func parseARGB(value: openArray[CSSComponentValue]): Opt[CellColor] =
+func parseARGB(value: openArray[CSSComponentValue]): Opt[CSSColor] =
   var i = 0
   var commaMode = false
   template check_err(slash: bool) =
@@ -858,12 +858,12 @@ func parseARGB(value: openArray[CSSComponentValue]): Opt[CellColor] =
   value.skipWhitespace(i)
   if i < value.len:
     return err()
-  return ok(rgba(int(r), int(g), int(b), int(a * 255)).cellColor())
+  return ok(rgba(int(r), int(g), int(b), int(a * 255)).cssColor())
 
 # 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] =
+func parseANSI(value: openArray[CSSComponentValue]): Opt[CSSColor] =
   var i = 0
   value.skipWhitespace(i)
   if i != value.high or not (value[i] of CSSToken): # only 1 param is valid
@@ -873,11 +873,11 @@ func parseANSI(value: openArray[CSSComponentValue]): Opt[CellColor] =
   if tok.tokenType == cttNumber:
     if tok.tflagb != tflagbInteger or int(tok.nvalue) notin 0..255:
       return err() # invalid numeric ANSI color
-    return ok(ANSIColor(tok.nvalue).cellColor())
+    return ok(ANSIColor(tok.nvalue).cssColor())
   elif tok.tokenType == cttIdent:
     var name = tok.value
     if name.equalsIgnoreCase("default"):
-      return ok(defaultColor)
+      return ok(defaultColor.cssColor())
     var bright = false
     if name.startsWithIgnoreCase("bright-"):
       bright = true
@@ -897,23 +897,23 @@ func parseANSI(value: openArray[CSSComponentValue]): Opt[CellColor] =
         var i = int(i)
         if bright:
           i += 8
-        return ok(ANSIColor(i).cellColor())
+        return ok(ANSIColor(i).cssColor())
   return err()
 
-func cssColor*(val: CSSComponentValue): Opt[CellColor] =
+func cssColor*(val: CSSComponentValue): Opt[CSSColor] =
   if val of CSSToken:
     let tok = CSSToken(val)
     case tok.tokenType
     of cttHash:
       let c = parseHexColor(tok.value)
       if c.isSome:
-        return ok(c.get.cellColor())
+        return ok(c.get.cssColor())
     of cttIdent:
       if tok.value.equalsIgnoreCase("transparent"):
-        return ok(rgba(0, 0, 0, 0).cellColor())
+        return ok(rgba(0, 0, 0, 0).cssColor())
       let x = namedRGBColor(tok.value)
       if x.isSome:
-        return ok(x.get.cellColor())
+        return ok(x.get.cssColor())
     else: discard
   elif val of CSSFunction:
     let f = CSSFunction(val)
@@ -1219,10 +1219,10 @@ proc parseValue(cvals: openArray[CSSComponentValue]; t: CSSPropertyType):
   of cvtOverflow: return_new overflow, ?parseIdent[CSSOverflow](cval)
   of cvtNone: return err()
 
-func getInitialColor(t: CSSPropertyType): CellColor =
+func getInitialColor(t: CSSPropertyType): CSSColor =
   if t == cptBackgroundColor:
-    return rgba(0, 0, 0, 0).cellColor()
-  return defaultColor
+    return rgba(0, 0, 0, 0).cssColor()
+  return defaultColor.cssColor()
 
 func getInitialLength(t: CSSPropertyType): CSSLength =
   case t
diff --git a/src/html/dom.nim b/src/html/dom.nim
index 8462f29a..0edf17d6 100644
--- a/src/html/dom.nim
+++ b/src/html/dom.nim
@@ -2635,16 +2635,16 @@ proc parseColor(element: Element; s: string): ARGBColor =
   let cval = parseComponentValue(s)
   #TODO return element style
   # For now we just use white.
-  let ec = rgb(255, 255, 255)
+  let ec = rgba(255, 255, 255, 255)
   if cval.isNone:
     return ec
   let color0 = cssColor(cval.get)
   if color0.isNone:
     return ec
   let color = color0.get
-  if color.t != ctRGB:
+  if color.isCell:
     return ec
-  return color.argbcolor
+  return color.argb
 
 # HTMLHyperlinkElementUtils (for <a> and <area>)
 func href0(element: HTMLElement): string =
diff --git a/src/io/bufreader.nim b/src/io/bufreader.nim
index d4eb9953..7813bd93 100644
--- a/src/io/bufreader.nim
+++ b/src/io/bufreader.nim
@@ -24,7 +24,7 @@ proc sread*(reader: var BufferedReader; obj: var ref object)
 proc sread*[T](reader: var BufferedReader; o: var Option[T])
 proc sread*[T, E](reader: var BufferedReader; o: var Result[T, E])
 proc sread*(reader: var BufferedReader; c: var ARGBColor)
-proc sread*(reader: var BufferedReader; c: var RGBColor)
+proc sread*(reader: var BufferedReader; c: var CellColor)
 
 proc initReader*(stream: DynStream; len, auxLen: int): BufferedReader =
   assert len != 0
@@ -151,5 +151,5 @@ proc sread*[T, E](reader: var BufferedReader; o: var Result[T, E]) =
 proc sread*(reader: var BufferedReader; c: var ARGBColor) =
   reader.sread(uint32(c))
 
-proc sread*(reader: var BufferedReader; c: var RGBColor) =
+proc sread*(reader: var BufferedReader; c: var CellColor) =
   reader.sread(uint32(c))
diff --git a/src/io/bufwriter.nim b/src/io/bufwriter.nim
index 3bedf883..5b07e0d6 100644
--- a/src/io/bufwriter.nim
+++ b/src/io/bufwriter.nim
@@ -34,7 +34,7 @@ proc swrite*(writer: var BufferedWriter; obj: ref object)
 proc swrite*[T](writer: var BufferedWriter; o: Option[T])
 proc swrite*[T, E](writer: var BufferedWriter; o: Result[T, E])
 proc swrite*(writer: var BufferedWriter; c: ARGBColor)
-proc swrite*(writer: var BufferedWriter; c: RGBColor)
+proc swrite*(writer: var BufferedWriter; c: CellColor)
 
 const InitLen = sizeof(int) * 2
 const SizeInit = max(64, InitLen)
@@ -153,5 +153,5 @@ proc swrite*[T, E](writer: var BufferedWriter; o: Result[T, E]) =
 proc swrite*(writer: var BufferedWriter; c: ARGBColor) =
   writer.swrite(uint32(c))
 
-proc swrite*(writer: var BufferedWriter; c: RGBColor) =
+proc swrite*(writer: var BufferedWriter; c: CellColor) =
   writer.swrite(uint32(c))
diff --git a/src/layout/renderdocument.nim b/src/layout/renderdocument.nim
index 7a4797ac..93af649a 100644
--- a/src/layout/renderdocument.nim
+++ b/src/layout/renderdocument.nim
@@ -67,7 +67,8 @@ func toFormat(computed: CSSComputedValues): Format =
   if TextDecorationBlink in computed{"text-decoration"}:
     flags.incl(ffBlink)
   return Format(
-    fgcolor: computed{"color"},
+    #TODO this ignores alpha; we should blend somewhere.
+    fgcolor: computed{"color"}.cellColor(),
     flags: flags
   )
 
@@ -325,13 +326,15 @@ proc renderInlineFragment(grid: var FlexibleGrid; state: var RenderState;
     fragment: InlineFragment; offset: Offset; bgcolor0: ARGBColor) =
   let bgcolor = fragment.computed{"background-color"}
   var bgcolor0 = bgcolor0
-  case bgcolor.t
-  of ctNone: discard
-  of ctANSI: grid.paintInlineFragment(state, fragment, offset, bgcolor)
-  of ctRGB:
-    bgcolor0 = bgcolor0.blend(bgcolor.argbcolor)
+  if bgcolor.isCell:
+    let bgcolor = bgcolor.cellColor()
+    if bgcolor.t != ctNone:
+      grid.paintInlineFragment(state, fragment, offset, bgcolor)
+  else:
+    bgcolor0 = bgcolor0.blend(bgcolor.argb)
     if bgcolor0.a > 0:
-      grid.paintInlineFragment(state, fragment, offset, bgcolor0.cellColor())
+      grid.paintInlineFragment(state, fragment, offset,
+        bgcolor0.rgb.cellColor())
   if fragment.t == iftParent:
     for child in fragment.children:
       grid.renderInlineFragment(state, child, offset, bgcolor0)
@@ -402,13 +405,14 @@ proc renderBlockBox(grid: var FlexibleGrid; state: var RenderState;
       ))
       stack.add((nil, offset(-1, -1)))
     if box.computed{"visibility"} == VisibilityVisible:
-      let bgcolor = box.computed{"background-color"}
-      if bgcolor.t == ctANSI or bgcolor.t == ctRGB and bgcolor.argbcolor.a > 0:
+      #TODO maybe blend with the terminal background?
+      let bgcolor = box.computed{"background-color"}.cellColor()
+      if bgcolor != defaultColor:
         if box.computed{"-cha-bgcolor-is-canvas"} and
             state.bgcolor == defaultColor:
           #TODO bgimage
+          # note: this eats the alpha
           state.bgcolor = bgcolor
-        #TODO color blending
         let ix = toInt(offset.x)
         let iy = toInt(offset.y)
         let e = offset + box.state.size
@@ -444,7 +448,11 @@ proc renderDocument*(grid: var FlexibleGrid; bgcolor: var CellColor;
   if styledRoot == nil:
     # no HTML element when we run cascade; just clear all lines.
     return
-  var state = RenderState(absolutePos: @[AbsolutePos()], attrsp: attrsp)
+  var state = RenderState(
+    absolutePos: @[AbsolutePos()],
+    attrsp: attrsp,
+    bgcolor: defaultColor
+  )
   let rootBox = styledRoot.layout(attrsp)
   grid.renderBlockBox(state, rootBox, offset(0, 0))
   if grid.len == 0:
diff --git a/src/local/pager.nim b/src/local/pager.nim
index ad4fc8ed..f5480c6f 100644
--- a/src/local/pager.nim
+++ b/src/local/pager.nim
@@ -682,7 +682,7 @@ proc draw*(pager: Pager) =
   if container != nil:
     if container.redraw:
       pager.clearDisplay()
-      let hlcolor = cellColor(pager.config.display.highlight_color)
+      let hlcolor = cellColor(pager.config.display.highlight_color.rgb)
       container.drawLines(pager.display.grid, hlcolor)
       if pager.config.display.highlight_marks:
         container.highlightMarks(pager.display.grid, hlcolor)
diff --git a/src/local/term.nim b/src/local/term.nim
index d99da8ed..0d760fbe 100644
--- a/src/local/term.nim
+++ b/src/local/term.nim
@@ -270,6 +270,16 @@ proc resetFormat(term: Terminal): string =
       return term.cap me
   return CSI & 'm'
 
+const FormatCodes: array[FormatFlag, tuple[s, e: uint8]] = [
+  ffBold: (1u8, 22u8),
+  ffItalic: (3u8, 23u8),
+  ffUnderline: (4u8, 24u8),
+  ffReverse: (7u8, 27u8),
+  ffStrike: (9u8, 29u8),
+  ffOverline: (53u8, 55u8),
+  ffBlink: (5u8, 25u8),
+]
+
 proc startFormat(term: Terminal; flag: FormatFlag): string =
   when TermcapFound:
     if term.tc != nil:
@@ -315,11 +325,12 @@ proc getRGB(term: Terminal; a: CellColor; termDefault: RGBColor): RGBColor =
   of ctNone:
     return termDefault
   of ctANSI:
-    if a.color >= 16:
-      return EightBitColor(a.color).toRGB()
-    return term.colorMap[a.color]
+    let n = a.ansi
+    if uint8(n) >= 16:
+      return n.toRGB()
+    return term.colorMap[uint8(n)]
   of ctRGB:
-    return a.rgbcolor
+    return a.rgb
 
 # Use euclidian distance to quantize RGB colors.
 proc approximateANSIColor(term: Terminal; rgb, termDefault: RGBColor):
@@ -390,7 +401,7 @@ proc addColorSGR(res: var string; c: CellColor; bgmod: uint8) =
   of ctNone:
     res &= 39 + bgmod
   of ctANSI:
-    let n = c.color
+    let n = uint8(c.ansi)
     if n < 16:
       if n < 8:
         res &= 30 + bgmod + n
@@ -401,7 +412,7 @@ proc addColorSGR(res: var string; c: CellColor; bgmod: uint8) =
       res &= ";5;"
       res &= n
   of ctRGB:
-    let rgb = c.rgbcolor
+    let rgb = c.rgb
     res &= 38 + bgmod
     res &= ";2;"
     res &= rgb.r
@@ -415,25 +426,25 @@ proc addColorSGR(res: var string; c: CellColor; bgmod: uint8) =
 proc reduceColors(term: Terminal; cellf: var Format) =
   case term.colorMode
   of cmANSI:
-    if cellf.bgcolor.t == ctANSI and cellf.bgcolor.color > 15:
-      cellf.bgcolor = cellf.fgcolor.eightbit.toRGB().cellColor()
+    if cellf.bgcolor.t == ctANSI and uint8(cellf.bgcolor.ansi) > 15:
+      cellf.bgcolor = cellf.fgcolor.ansi.toRGB().cellColor()
     if cellf.bgcolor.t == ctRGB:
-      cellf.bgcolor = term.approximateANSIColor(cellf.bgcolor.rgbcolor,
+      cellf.bgcolor = term.approximateANSIColor(cellf.bgcolor.rgb,
         term.defaultBackground)
-    if cellf.fgcolor.t == ctANSI and cellf.fgcolor.color > 15:
-      cellf.fgcolor = cellf.fgcolor.eightbit.toRGB().cellColor()
+    if cellf.fgcolor.t == ctANSI and uint8(cellf.fgcolor.ansi) > 15:
+      cellf.fgcolor = cellf.fgcolor.ansi.toRGB().cellColor()
     if cellf.fgcolor.t == ctRGB:
       if cellf.bgcolor.t == ctNone:
-        cellf.fgcolor = term.approximateANSIColor(cellf.fgcolor.rgbcolor,
+        cellf.fgcolor = term.approximateANSIColor(cellf.fgcolor.rgb,
           term.defaultForeground)
       else:
         # ANSI fgcolor + bgcolor at the same time is broken
         cellf.fgcolor = defaultColor
   of cmEightBit:
     if cellf.bgcolor.t == ctRGB:
-      cellf.bgcolor = cellf.bgcolor.rgbcolor.toEightBit().cellColor()
+      cellf.bgcolor = cellf.bgcolor.rgb.toEightBit().cellColor()
     if cellf.fgcolor.t == ctRGB:
-      cellf.fgcolor = cellf.fgcolor.rgbcolor.toEightBit().cellColor()
+      cellf.fgcolor = cellf.fgcolor.rgb.toEightBit().cellColor()
   of cmMonochrome, cmTrueColor:
     discard # nothing to do
 
diff --git a/src/types/cell.nim b/src/types/cell.nim
index bc2f6924..d8aab32d 100644
--- a/src/types/cell.nim
+++ b/src/types/cell.nim
@@ -50,16 +50,6 @@ iterator items*(grid: FixedGrid): FixedCell {.inline.} =
   for cell in grid.cells:
     yield cell
 
-const FormatCodes*: array[FormatFlag, tuple[s, e: uint8]] = [
-  ffBold: (1u8, 22u8),
-  ffItalic: (3u8, 23u8),
-  ffUnderline: (4u8, 24u8),
-  ffReverse: (7u8, 27u8),
-  ffStrike: (9u8, 29u8),
-  ffOverline: (53u8, 55u8),
-  ffBlink: (5u8, 25u8),
-]
-
 func newFixedGrid*(w: int; h: int = 1): FixedGrid =
   return FixedGrid(width: w, height: h, cells: newSeq[FixedCell](w * h))
 
@@ -78,13 +68,11 @@ func findFormatN*(line: SimpleFlexibleLine; pos: int): int =
 func findFormat*(line: SimpleFlexibleLine; pos: int): SimpleFormatCell =
   let i = line.findFormatN(pos) - 1
   if i != -1:
-    result = line.formats[i]
-  else:
-    result.pos = -1
+    return line.formats[i]
+  return SimpleFormatCell(pos: -1)
 
 func findNextFormat*(line: SimpleFlexibleLine; pos: int): SimpleFormatCell =
   let i = line.findFormatN(pos)
   if i < line.formats.len:
-    result = line.formats[i]
-  else:
-    result.pos = -1
+    return line.formats[i]
+  return SimpleFormatCell(pos: -1)
diff --git a/src/types/color.nim b/src/types/color.nim
index 13564f1d..815f769f 100644
--- a/src/types/color.nim
+++ b/src/types/color.nim
@@ -19,64 +19,101 @@ type
     b*: uint8
     a*: uint8
 
+  # Either a 3-bit ANSI color (0..7), a 3-bit bright ANSI color (8..15),
+  # a color on the RGB cube (16..231), or a grayscale color (232..255).
   ANSIColor* = distinct uint8
 
-  EightBitColor* = distinct uint8
-
   # ctNone: default color (intentionally 0), n is unused
   # ctANSI: ANSI color, as selected by SGR 38/48
   # ctRGB: RGB color
   ColorTag* = enum
     ctNone, ctANSI, ctRGB
 
-  CellColor* = object
-    t*: ColorTag
+  # Color that can be represented by a terminal cell.
+  # Crucially, this does not include colors with an alpha channel.
+  CellColor* = distinct uint32
+
+  # Color that can be represented in CSS.
+  # As an extension, we also recognize ANSI colors, so ARGB does not suffice.
+  # (Actually, it would, but then we'd have to copy over the ANSI color
+  # table and then re-quantize on render. I'm fine with wasting a few
+  # bytes instead.)
+  CSSColor* = object
+    isCell*: bool # if true, n is a CellColor. otherwise, it's ARGBColor.
     n: uint32
 
 func rgba*(r, g, b, a: uint8): ARGBColor
 
-func toRGBColor*(i: ARGBColor): RGBColor =
-  return RGBColor(uint32(i) and 0xFFFFFFu32)
+func r*(c: ARGBColor): uint8 =
+  return uint8(uint32(c) shr 16)
+
+func g*(c: ARGBColor): uint8 =
+  return uint8(uint32(c) shr 8)
+
+func b*(c: ARGBColor): uint8 =
+  return uint8(uint32(c))
+
+func a*(c: ARGBColor): uint8 =
+  return uint8(uint32(c) shr 24)
 
-converter toARGBColor*(i: RGBColor): ARGBColor =
-  return ARGBColor(uint32(i) or 0xFF000000u32)
+func rgb*(c: ARGBColor): RGBColor =
+  return RGBColor(uint32(c) and 0xFFFFFFu32)
 
-converter toARGBColor*(c: RGBAColorBE): ARGBColor =
+func argb*(c: RGBColor): ARGBColor =
+  return ARGBColor(uint32(c) or 0xFF000000u32)
+
+proc argb*(c: RGBAColorBE): ARGBColor =
   return rgba(c.r, c.g, c.b, c.a)
 
 func `==`*(a, b: ARGBColor): bool {.borrow.}
 
+func `==`*(a, b: RGBColor): bool {.borrow.}
+
 func `==`*(a, b: ANSIColor): bool {.borrow.}
 
-func `==`*(a, b: EightBitColor): bool {.borrow.}
+func `==`*(a, b: CellColor): bool {.borrow.}
 
-func rgbcolor*(color: CellColor): RGBColor =
-  cast[RGBColor](color.n)
+func t*(color: CellColor): ColorTag =
+  return cast[ColorTag](uint32(color) shr 24)
 
-func argbcolor*(color: CellColor): ARGBColor =
-  cast[ARGBColor](color.n)
+func rgb*(color: CellColor): RGBColor =
+  return RGBColor(uint32(color) and 0xFFFFFF)
 
-func color*(color: CellColor): uint8 =
-  uint8(color.n)
+func ansi*(color: CellColor): ANSIColor =
+  return ANSIColor(color)
 
-func eightbit*(color: CellColor): EightBitColor =
-  EightBitColor(color.color)
+func cellColor(t: ColorTag; n: uint32): CellColor =
+  return CellColor((uint32(t) shl 24) or (n and 0xFFFFFF))
 
 func cellColor*(rgb: RGBColor): CellColor =
-  return CellColor(t: ctRGB, n: uint32(rgb) or 0xFF000000u32)
+  return cellColor(ctRGB, uint32(rgb))
 
-func cellColor*(rgba: ARGBColor): CellColor =
-  return CellColor(t: ctRGB, n: uint32(rgba))
+func cellColor*(c: ANSIColor): CellColor =
+  return cellColor(ctANSI, uint32(c))
 
-#TODO bright ANSI colors (8..15)
+const defaultColor* = cellColor(ctNone, 0)
 
-func cellColor*(c: ANSIColor): CellColor =
-  return CellColor(t: ctANSI, n: uint32(c))
+func cssColor*(c: ARGBColor): CSSColor =
+  return CSSColor(isCell: false, n: uint32(c))
+
+func cssColor*(c: RGBColor): CSSColor =
+  return c.argb.cssColor()
+
+func cssColor*(c: CellColor): CSSColor =
+  return CSSColor(isCell: true, n: uint32(c))
 
-func cellColor*(c: EightBitColor): CellColor =
-  return CellColor(t: ctANSI, n: uint32(c))
+func cssColor*(c: ANSIColor): CSSColor =
+  return c.cellColor().cssColor()
 
-const defaultColor* = CellColor(t: ctNone, n: 0)
+func argb*(c: CSSColor): ARGBColor =
+  return ARGBColor(c.n)
+
+func cellColor*(c: CSSColor): CellColor =
+  if c.isCell:
+    return CellColor(c.n)
+  if c.argb.a == 0:
+    return defaultColor
+  return cellColor(ctRGB, c.n)
 
 const ColorsRGBMap = {
   "aliceblue": 0xF0F8FFu32,
@@ -238,30 +275,6 @@ func namedRGBColor*(s: string): Option[RGBColor] =
     return some(RGBColor(ColorsRGBMap[i][1]))
   return none(RGBColor)
 
-func r*(c: ARGBColor): uint8 =
-  return uint8(uint32(c) shr 16)
-
-func g*(c: ARGBColor): uint8 =
-  return uint8(uint32(c) shr 8)
-
-func b*(c: ARGBColor): uint8 =
-  return uint8(uint32(c))
-
-func a*(c: ARGBColor): uint8 =
-  return uint8(uint32(c) shr 24)
-
-proc `r=`*(c: var ARGBColor, r: uint8) =
-  c = ARGBColor(uint32(c) or (uint32(r) shl 16))
-
-proc `g=`*(c: var ARGBColor, g: uint8) =
-  c = ARGBColor(uint32(c) or (uint32(g) shl 8))
-
-proc `b=`*(c: var ARGBColor, b: uint8) =
-  c = ARGBColor(uint32(c) or uint32(b))
-
-proc `a=`*(c: var ARGBColor, a: uint8) =
-  c = ARGBColor(uint32(c) or (uint32(a) shl 24))
-
 # https://html.spec.whatwg.org/#serialisation-of-a-color
 func serialize*(color: ARGBColor): string =
   if color.a == 255:
@@ -398,7 +411,7 @@ func gray_be*(n: uint8): RGBAColorBE =
   return rgb_be(n, n, n)
 
 # NOTE: this assumes n notin 0..15 (which would be ANSI 4-bit)
-func toRGB*(param0: EightBitColor): RGBColor =
+func toRGB*(param0: ANSIColor): RGBColor =
   doAssert uint8(param0) notin 0u8..15u8
   let u = uint8(param0)
   if u in 16u8..231u8:
@@ -413,7 +426,7 @@ func toRGB*(param0: EightBitColor): RGBColor =
     let n = (u - 232) * 10 + 8
     return gray(n)
 
-func toEightBit(r, g, b: uint8): EightBitColor =
+func toEightBit(r, g, b: uint8): ANSIColor =
   let r = int(r)
   let g = int(g)
   let b = int(b)
@@ -422,24 +435,24 @@ func toEightBit(r, g, b: uint8): EightBitColor =
   # abs(U - 128) < 5 & abs(V - 128 < 5), but is definitely faster.
   if r shr 4 == g shr 4 and g shr 4 == b shr 4:
     if r < 8:
-      return EightBitColor(16)
+      return ANSIColor(16)
     if r > 248:
-      return EightBitColor(231)
-    return EightBitColor(uint8(((r - 8) * 24 div 247) + 232))
+      return ANSIColor(231)
+    return ANSIColor(uint8(((r - 8) * 24 div 247) + 232))
   #16 + 36 * r + 6 * g + b
-  return EightBitColor(uint8(16 + 36 * (r * 5 div 255) +
-    6 * (g * 5 div 255) + (b * 5 div 255)))
+  return ANSIColor(uint8(16 + 36 * (r * 5 div 255) + 6 * (g * 5 div 255) +
+    (b * 5 div 255)))
 
-func toEightBit*(c: RGBColor): EightBitColor =
+func toEightBit*(c: RGBColor): ANSIColor =
   return toEightBit(c.r, c.g, c.b)
 
-func toEightBit*(c: RGBAColorBE): EightBitColor =
+func toEightBit*(c: RGBAColorBE): ANSIColor =
   return toEightBit(c.r, c.g, c.b)
 
 template `$`*(color: CellColor): string =
   case color.t
   of ctNone: "none"
-  of ctRGB: $color.argbcolor
+  of ctRGB: $color.rgb
   of ctANSI: "ansi" & $color.n
 
 func parseHexColor*(s: openArray[char]): Option[ARGBColor] =
@@ -476,7 +489,7 @@ func parseHexColor*(s: openArray[char]): Option[ARGBColor] =
 
 func parseARGBColor*(s: string): Option[ARGBColor] =
   if (let x = namedRGBColor(s); x.isSome):
-    return some(x.get.toARGBColor())
+    return some(x.get.argb)
   if (s.len == 3 or s.len == 4 or s.len == 6 or s.len == 8) and s[0] == '#':
     return parseHexColor(s.toOpenArray(1, s.high))
   if s.len > 2 and s[0] == '0' and s[1] == 'x':