|
|
@@ -4,6 +4,7 @@ import (
|
|
|
"bytes"
|
|
|
"fmt"
|
|
|
"io"
|
|
|
+ "math"
|
|
|
"os"
|
|
|
"strconv"
|
|
|
"strings"
|
|
|
@@ -402,7 +403,7 @@ loop:
|
|
|
continue
|
|
|
}
|
|
|
token := strings.Split(cs, ";")
|
|
|
- for i := 0; i < len(token); i+=1 {
|
|
|
+ for i := 0; i < len(token); i += 1 {
|
|
|
ns := token[i]
|
|
|
if n, err = strconv.Atoi(ns); err == nil {
|
|
|
switch {
|
|
|
@@ -480,75 +481,13 @@ loop:
|
|
|
}
|
|
|
|
|
|
type consoleColor struct {
|
|
|
+ rgb int
|
|
|
red bool
|
|
|
green bool
|
|
|
blue bool
|
|
|
intensity bool
|
|
|
}
|
|
|
|
|
|
-func minmax3(a, b, c int) (min, max int) {
|
|
|
- if a < b {
|
|
|
- if b < c {
|
|
|
- return a, c
|
|
|
- } else if a < c {
|
|
|
- return a, b
|
|
|
- } else {
|
|
|
- return c, b
|
|
|
- }
|
|
|
- } else {
|
|
|
- if a < c {
|
|
|
- return b, c
|
|
|
- } else if b < c {
|
|
|
- return b, a
|
|
|
- } else {
|
|
|
- return c, a
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-func toConsoleColor(rgb int) (c consoleColor) {
|
|
|
- r, g, b := (rgb&0xFF0000)>>16, (rgb&0x00FF00)>>8, rgb&0x0000FF
|
|
|
- min, max := minmax3(r, g, b)
|
|
|
- a := (min + max) / 2
|
|
|
- if r < 128 && g < 128 && b < 128 {
|
|
|
- if r >= a {
|
|
|
- c.red = true
|
|
|
- }
|
|
|
- if g >= a {
|
|
|
- c.green = true
|
|
|
- }
|
|
|
- if b >= a {
|
|
|
- c.blue = true
|
|
|
- }
|
|
|
- // non-intensed white is lighter than intensed black, so swap those.
|
|
|
- if c.red && c.green && c.blue {
|
|
|
- c.red, c.green, c.blue = false, false, false
|
|
|
- c.intensity = true
|
|
|
- }
|
|
|
- } else {
|
|
|
- if min < 128 {
|
|
|
- min = 128
|
|
|
- a = (min + max) / 2
|
|
|
- }
|
|
|
- if r >= a {
|
|
|
- c.red = true
|
|
|
- }
|
|
|
- if g >= a {
|
|
|
- c.green = true
|
|
|
- }
|
|
|
- if b >= a {
|
|
|
- c.blue = true
|
|
|
- }
|
|
|
- c.intensity = true
|
|
|
- // intensed black is darker than non-intensed white, so swap those.
|
|
|
- if !c.red && !c.green && !c.blue {
|
|
|
- c.red, c.green, c.blue = true, true, true
|
|
|
- c.intensity = false
|
|
|
- }
|
|
|
- }
|
|
|
- return c
|
|
|
-}
|
|
|
-
|
|
|
func (c consoleColor) foregroundAttr() (attr word) {
|
|
|
if c.red {
|
|
|
attr |= foregroundRed
|
|
|
@@ -581,14 +520,121 @@ func (c consoleColor) backgroundAttr() (attr word) {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
+var color16 = []consoleColor{
|
|
|
+ consoleColor{0x000000, false, false, false, false},
|
|
|
+ consoleColor{0x000080, false, false, true, false},
|
|
|
+ consoleColor{0x008000, false, true, false, false},
|
|
|
+ consoleColor{0x008080, false, true, true, false},
|
|
|
+ consoleColor{0x800000, true, false, false, false},
|
|
|
+ consoleColor{0x800080, true, false, true, false},
|
|
|
+ consoleColor{0x808000, true, true, false, false},
|
|
|
+ consoleColor{0xc0c0c0, true, true, true, false},
|
|
|
+ consoleColor{0x808080, false, false, false, true},
|
|
|
+ consoleColor{0x0000ff, false, false, true, true},
|
|
|
+ consoleColor{0x00ff00, false, true, false, true},
|
|
|
+ consoleColor{0x00ffff, false, true, true, true},
|
|
|
+ consoleColor{0xff0000, true, false, false, true},
|
|
|
+ consoleColor{0xff00ff, true, false, true, true},
|
|
|
+ consoleColor{0xffff00, true, true, false, true},
|
|
|
+ consoleColor{0xffffff, true, true, true, true},
|
|
|
+}
|
|
|
+
|
|
|
+type hsv struct {
|
|
|
+ h, s, v float32
|
|
|
+}
|
|
|
+
|
|
|
+func (a hsv) dist(b hsv) float32 {
|
|
|
+ dh := a.h - b.h
|
|
|
+ switch {
|
|
|
+ case dh > 0.5:
|
|
|
+ dh = 1 - dh
|
|
|
+ case dh < -0.5:
|
|
|
+ dh = -1 - dh
|
|
|
+ }
|
|
|
+ ds := a.s - b.s
|
|
|
+ dv := a.v - b.v
|
|
|
+ return float32(math.Sqrt(float64(dh*dh + ds*ds + dv*dv)))
|
|
|
+}
|
|
|
+
|
|
|
+func toHSV(rgb int) hsv {
|
|
|
+ r, g, b := float32((rgb&0xFF0000)>>16)/256.0,
|
|
|
+ float32((rgb&0x00FF00)>>8)/256.0,
|
|
|
+ float32(rgb&0x0000FF)/256.0
|
|
|
+ min, max := minmax3f(r, g, b)
|
|
|
+ h := max - min
|
|
|
+ if h > 0 {
|
|
|
+ if max == r {
|
|
|
+ h = (g - b) / h
|
|
|
+ if h < 0 {
|
|
|
+ h += 6
|
|
|
+ }
|
|
|
+ } else if max == g {
|
|
|
+ h = 2 + (b-r)/h
|
|
|
+ } else {
|
|
|
+ h = 4 + (r-g)/h
|
|
|
+ }
|
|
|
+ }
|
|
|
+ h /= 6.0
|
|
|
+ s := max - min
|
|
|
+ if max != 0 {
|
|
|
+ s /= max
|
|
|
+ }
|
|
|
+ v := max
|
|
|
+ return hsv{h: h, s: s, v: v}
|
|
|
+}
|
|
|
+
|
|
|
+type hsvTable []hsv
|
|
|
+
|
|
|
+func toHSVTable(rgbTable []consoleColor) hsvTable {
|
|
|
+ t := make(hsvTable, len(rgbTable))
|
|
|
+ for i, c := range rgbTable {
|
|
|
+ t[i] = toHSV(c.rgb)
|
|
|
+ }
|
|
|
+ return t
|
|
|
+}
|
|
|
+
|
|
|
+func (t hsvTable) find(rgb int) consoleColor {
|
|
|
+ hsv := toHSV(rgb)
|
|
|
+ n := 7
|
|
|
+ l := float32(5.0)
|
|
|
+ for i, p := range t {
|
|
|
+ d := hsv.dist(p)
|
|
|
+ if d < l {
|
|
|
+ l, n = d, i
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return color16[n]
|
|
|
+}
|
|
|
+
|
|
|
+func minmax3f(a, b, c float32) (min, max float32) {
|
|
|
+ if a < b {
|
|
|
+ if b < c {
|
|
|
+ return a, c
|
|
|
+ } else if a < c {
|
|
|
+ return a, b
|
|
|
+ } else {
|
|
|
+ return c, b
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if a < c {
|
|
|
+ return b, c
|
|
|
+ } else if b < c {
|
|
|
+ return b, a
|
|
|
+ } else {
|
|
|
+ return c, a
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
var n256foreAttr []word
|
|
|
var n256backAttr []word
|
|
|
|
|
|
func n256setup() {
|
|
|
n256foreAttr = make([]word, 256)
|
|
|
n256backAttr = make([]word, 256)
|
|
|
+ t := toHSVTable(color16)
|
|
|
for i, rgb := range color256 {
|
|
|
- c := toConsoleColor(rgb)
|
|
|
+ c := t.find(rgb)
|
|
|
n256foreAttr[i] = c.foregroundAttr()
|
|
|
n256backAttr[i] = c.backgroundAttr()
|
|
|
}
|