...

Source file src/oss.terrastruct.com/d2/lib/color/color.go

Documentation: oss.terrastruct.com/d2/lib/color

     1  package color
     2  
     3  import (
     4  	"fmt"
     5  	"math"
     6  	"regexp"
     7  	"strconv"
     8  	"strings"
     9  
    10  	"github.com/lucasb-eyer/go-colorful"
    11  	"github.com/mazznoer/csscolorparser"
    12  )
    13  
    14  var themeColorRegex = regexp.MustCompile(`^(N[1-7]|B[1-6]|AA[245]|AB[45])$`)
    15  
    16  func IsThemeColor(colorString string) bool {
    17  	return themeColorRegex.MatchString(colorString)
    18  }
    19  
    20  func Darken(colorString string) (string, error) {
    21  	if IsThemeColor(colorString) {
    22  		switch {
    23  		case colorString[0] == 'B':
    24  			switch colorString[1] {
    25  			case '1', '2':
    26  				return B1, nil
    27  			case '3':
    28  				return B2, nil
    29  			case '4':
    30  				return B3, nil
    31  			case '5':
    32  				return B4, nil
    33  			case '6':
    34  				return B5, nil
    35  			}
    36  
    37  		case colorString[0:2] == "AA":
    38  			switch colorString[2] {
    39  			case '2', '4':
    40  				return AA2, nil
    41  			case '5':
    42  				return AA4, nil
    43  			}
    44  
    45  		case colorString[0:2] == "AB":
    46  			switch colorString[2] {
    47  			case '4':
    48  				return AB4, nil
    49  			case '5':
    50  				return AB5, nil
    51  			}
    52  
    53  		case colorString[0] == 'N':
    54  			switch colorString[1] {
    55  			case '1', '2':
    56  				return N1, nil
    57  			case '3':
    58  				return N2, nil
    59  			case '4':
    60  				return N3, nil
    61  			case '5':
    62  				return N4, nil
    63  			case '6':
    64  				return N5, nil
    65  			case '7':
    66  				return N6, nil
    67  			}
    68  		}
    69  
    70  		return "", fmt.Errorf("invalid color \"%s\"", colorString)
    71  	}
    72  
    73  	return darkenCSS(colorString)
    74  }
    75  
    76  func darkenCSS(colorString string) (string, error) {
    77  	c, err := csscolorparser.Parse(colorString)
    78  	if err != nil {
    79  		return "", err
    80  	}
    81  	h, s, l := colorful.Color{R: c.R, G: c.G, B: c.B}.Hsl()
    82  	// decrease luminance by 10%
    83  	return colorful.Hsl(h, s, l-.1).Clamped().Hex(), nil
    84  }
    85  
    86  func LuminanceCategory(colorString string) (string, error) {
    87  	l, err := Luminance(colorString)
    88  	if err != nil {
    89  		return "", err
    90  	}
    91  
    92  	switch {
    93  	case l >= .88:
    94  		return "bright", nil
    95  	case l >= .55:
    96  		return "normal", nil
    97  	case l >= .30:
    98  		return "dark", nil
    99  	default:
   100  		return "darker", nil
   101  	}
   102  }
   103  
   104  func Luminance(colorString string) (float64, error) {
   105  	c, err := csscolorparser.Parse(colorString)
   106  	if err != nil {
   107  		return 0, err
   108  	}
   109  
   110  	// https://stackoverflow.com/a/596243
   111  	l := float64(
   112  		float64(0.299)*float64(c.R) +
   113  			float64(0.587)*float64(c.G) +
   114  			float64(0.114)*float64(c.B),
   115  	)
   116  	return l, nil
   117  }
   118  
   119  const (
   120  	N1 = "N1" // foreground color
   121  	N2 = "N2"
   122  	N3 = "N3"
   123  	N4 = "N4"
   124  	N5 = "N5"
   125  	N6 = "N6"
   126  	N7 = "N7" // background color
   127  
   128  	// Base Colors: used for containers
   129  	B1 = "B1"
   130  	B2 = "B2"
   131  	B3 = "B3"
   132  	B4 = "B4"
   133  	B5 = "B5"
   134  	B6 = "B6"
   135  
   136  	// Alternative colors A
   137  	AA2 = "AA2"
   138  	AA4 = "AA4"
   139  	AA5 = "AA5"
   140  
   141  	// Alternative colors B
   142  	AB4 = "AB4"
   143  	AB5 = "AB5"
   144  
   145  	// Special
   146  	Empty = ""
   147  	None  = "none"
   148  )
   149  
   150  type RGB struct {
   151  	Red   uint8
   152  	Green uint8
   153  	Blue  uint8
   154  }
   155  
   156  // https://github.com/go-playground/colors/blob/main/rgb.go#L89
   157  func (c *RGB) IsLight() bool {
   158  	r := float64(c.Red)
   159  	g := float64(c.Green)
   160  	b := float64(c.Blue)
   161  
   162  	hsp := math.Sqrt(0.299*math.Pow(r, 2) + 0.587*math.Pow(g, 2) + 0.114*math.Pow(b, 2))
   163  
   164  	return hsp > 130
   165  }
   166  
   167  // https://gist.github.com/CraigChilds94/6514edbc6a2db5e434a245487c525c75
   168  func Hex2RGB(hex string) (RGB, error) {
   169  	var rgb RGB
   170  	if len(hex) > 3 && hex[0] == '#' {
   171  		hex = hex[1:]
   172  	} else {
   173  		return RGB{}, fmt.Errorf("cannot parse hex color %v", hex)
   174  	}
   175  	values, err := strconv.ParseUint(hex, 16, 32)
   176  	if err != nil {
   177  		return RGB{}, err
   178  	}
   179  
   180  	rgb = RGB{
   181  		Red:   uint8(values >> 16),
   182  		Green: uint8((values >> 8) & 0xFF),
   183  		Blue:  uint8(values & 0xFF),
   184  	}
   185  
   186  	return rgb, nil
   187  }
   188  
   189  // https://www.w3.org/TR/css-color-4/#svg-color
   190  var namedRgbMap = map[string][]uint8{
   191  	"aliceblue":            {240, 248, 255}, // #F0F8FF
   192  	"antiquewhite":         {250, 235, 215}, // #FAEBD7
   193  	"aqua":                 {0, 255, 255},   // #00FFFF
   194  	"aquamarine":           {127, 255, 212}, // #7FFFD4
   195  	"azure":                {240, 255, 255}, // #F0FFFF
   196  	"beige":                {245, 245, 220}, // #F5F5DC
   197  	"bisque":               {255, 228, 196}, // #FFE4C4
   198  	"black":                {0, 0, 0},       // #000000
   199  	"blanchedalmond":       {255, 235, 205}, // #FFEBCD
   200  	"blue":                 {0, 0, 255},     // #0000FF
   201  	"blueviolet":           {138, 43, 226},  // #8A2BE2
   202  	"brown":                {165, 42, 42},   // #A52A2A
   203  	"burlywood":            {222, 184, 135}, // #DEB887
   204  	"cadetblue":            {95, 158, 160},  // #5F9EA0
   205  	"chartreuse":           {127, 255, 0},   // #7FFF00
   206  	"chocolate":            {210, 105, 30},  // #D2691E
   207  	"coral":                {255, 127, 80},  // #FF7F50
   208  	"cornflowerblue":       {100, 149, 237}, // #6495ED
   209  	"cornsilk":             {255, 248, 220}, // #FFF8DC
   210  	"crimson":              {220, 20, 60},   // #DC143C
   211  	"cyan":                 {0, 255, 255},   // #00FFFF
   212  	"darkblue":             {0, 0, 139},     // #00008B
   213  	"darkcyan":             {0, 139, 139},   // #008B8B
   214  	"darkgoldenrod":        {184, 134, 11},  // #B8860B
   215  	"darkgray":             {169, 169, 169}, // #A9A9A9
   216  	"darkgreen":            {0, 100, 0},     // #006400
   217  	"darkgrey":             {169, 169, 169}, // #A9A9A9
   218  	"darkkhaki":            {189, 183, 107}, // #BDB76B
   219  	"darkmagenta":          {139, 0, 139},   // #8B008B
   220  	"darkolivegreen":       {85, 107, 47},   // #556B2F
   221  	"darkorange":           {255, 140, 0},   // #FF8C00
   222  	"darkorchid":           {153, 50, 204},  // #9932CC
   223  	"darkred":              {139, 0, 0},     // #8B0000
   224  	"darksalmon":           {233, 150, 122}, // #E9967A
   225  	"darkseagreen":         {143, 188, 143}, // #8FBC8F
   226  	"darkslateblue":        {72, 61, 139},   // #483D8B
   227  	"darkslategray":        {47, 79, 79},    // #2F4F4F
   228  	"darkslategrey":        {47, 79, 79},    // #2F4F4F
   229  	"darkturquoise":        {0, 206, 209},   // #00CED1
   230  	"darkviolet":           {148, 0, 211},   // #9400D3
   231  	"deeppink":             {255, 20, 147},  // #FF1493
   232  	"deepskyblue":          {0, 191, 255},   // #00BFFF
   233  	"dimgray":              {105, 105, 105}, // #696969
   234  	"dimgrey":              {105, 105, 105}, // #696969
   235  	"dodgerblue":           {30, 144, 255},  // #1E90FF
   236  	"firebrick":            {178, 34, 34},   // #B22222
   237  	"floralwhite":          {255, 250, 240}, // #FFFAF0
   238  	"forestgreen":          {34, 139, 34},   // #228B22
   239  	"fuchsia":              {255, 0, 255},   // #FF00FF
   240  	"gainsboro":            {220, 220, 220}, // #DCDCDC
   241  	"ghostwhite":           {248, 248, 255}, // #F8F8FF
   242  	"gold":                 {255, 215, 0},   // #FFD700
   243  	"goldenrod":            {218, 165, 32},  // #DAA520
   244  	"gray":                 {128, 128, 128}, // #808080
   245  	"green":                {0, 128, 0},     // #008000
   246  	"greenyellow":          {173, 255, 47},  // #ADFF2F
   247  	"grey":                 {128, 128, 128}, // #808080
   248  	"honeydew":             {240, 255, 240}, // #F0FFF0
   249  	"hotpink":              {255, 105, 180}, // #FF69B4
   250  	"indianred":            {205, 92, 92},   // #CD5C5C
   251  	"indigo":               {75, 0, 130},    // #4B0082
   252  	"ivory":                {255, 255, 240}, // #FFFFF0
   253  	"khaki":                {240, 230, 140}, // #F0E68C
   254  	"lavender":             {230, 230, 250}, // #E6E6FA
   255  	"lavenderblush":        {255, 240, 245}, // #FFF0F5
   256  	"lawngreen":            {124, 252, 0},   // #7CFC00
   257  	"lemonchiffon":         {255, 250, 205}, // #FFFACD
   258  	"lightblue":            {173, 216, 230}, // #ADD8E6
   259  	"lightcoral":           {240, 128, 128}, // #F08080
   260  	"lightcyan":            {224, 255, 255}, // #E0FFFF
   261  	"lightgoldenrodyellow": {250, 250, 210}, // #FAFAD2
   262  	"lightgray":            {211, 211, 211}, // #D3D3D3
   263  	"lightgreen":           {144, 238, 144}, // #90EE90
   264  	"lightgrey":            {211, 211, 211}, // #D3D3D3
   265  	"lightpink":            {255, 182, 193}, // #FFB6C1
   266  	"lightsalmon":          {255, 160, 122}, // #FFA07A
   267  	"lightseagreen":        {32, 178, 170},  // #20B2AA
   268  	"lightskyblue":         {135, 206, 250}, // #87CEFA
   269  	"lightslategray":       {119, 136, 153}, // #778899
   270  	"lightslategrey":       {119, 136, 153}, // #778899
   271  	"lightsteelblue":       {176, 196, 222}, // #B0C4DE
   272  	"lightyellow":          {255, 255, 224}, // #FFFFE0
   273  	"lime":                 {0, 255, 0},     // #00FF00
   274  	"limegreen":            {50, 205, 50},   // #32CD32
   275  	"linen":                {250, 240, 230}, // #FAF0E6
   276  	"magenta":              {255, 0, 255},   // #FF00FF
   277  	"maroon":               {128, 0, 0},     // #800000
   278  	"mediumaquamarine":     {102, 205, 170}, // #66CDAA
   279  	"mediumblue":           {0, 0, 205},     // #0000CD
   280  	"mediumorchid":         {186, 85, 211},  // #BA55D3
   281  	"mediumpurple":         {147, 112, 219}, // #9370DB
   282  	"mediumseagreen":       {60, 179, 113},  // #3CB371
   283  	"mediumslateblue":      {123, 104, 238}, // #7B68EE
   284  	"mediumspringgreen":    {0, 250, 154},   // #00FA9A
   285  	"mediumturquoise":      {72, 209, 204},  // #48D1CC
   286  	"mediumvioletred":      {199, 21, 133},  // #C71585
   287  	"midnightblue":         {25, 25, 112},   // #191970
   288  	"muintcream":           {245, 255, 250}, // #F5FFFA
   289  	"mistyrose":            {255, 228, 225}, // #FFE4E1
   290  	"moccasin":             {255, 228, 181}, // #FFE4B5
   291  	"navajowhite":          {255, 222, 173}, // #FFDEAD
   292  	"navy":                 {0, 0, 128},     // #000080
   293  	"oldlace":              {253, 245, 230}, // #FDF5E6
   294  	"olive":                {128, 128, 0},   // #808000
   295  	"olivedrab":            {107, 142, 35},  // #6B8E23
   296  	"orange":               {255, 165, 0},   // #FFA500
   297  	"orangered":            {255, 69, 0},    // #FF4500
   298  	"orchid":               {218, 112, 214}, // #DA70D6
   299  	"palegoldenrod":        {238, 232, 170}, // #EEE8AA
   300  	"palegreen":            {152, 251, 152}, // #98FB98
   301  	"paleturquoise":        {175, 238, 238}, // #AFEEEE
   302  	"palevioletred":        {219, 112, 147}, // #DB7093
   303  	"papayawhip":           {255, 239, 213}, // #FFEFD5
   304  	"peachpuff":            {255, 218, 185}, // #FFDAB9
   305  	"peru":                 {205, 133, 63},  // #CD853F
   306  	"pink":                 {255, 192, 203}, // #FFC0CB
   307  	"plum":                 {221, 160, 221}, // #DDA0DD
   308  	"powderblue":           {176, 224, 230}, // #B0E0E6
   309  	"purple":               {128, 0, 128},   // #800080
   310  	"red":                  {255, 0, 0},     // #FF0000
   311  	"rebeccapurple":        {102, 51, 153},  // #663399
   312  	"rosybrown":            {188, 143, 143}, // #BC8F8F
   313  	"royalblue":            {65, 105, 225},  // #4169E1
   314  	"saddlebrown":          {139, 69, 19},   // #8B4513
   315  	"salmon":               {250, 128, 114}, // #FA8072
   316  	"sandybrown":           {244, 164, 96},  // #F4A460
   317  	"seagreen":             {46, 139, 87},   // #2E8B57
   318  	"seashell":             {255, 245, 238}, // #FFF5EE
   319  	"sienna":               {160, 82, 45},   // #A0522D
   320  	"silver":               {192, 192, 192}, // #C0C0C0
   321  	"skyblue":              {135, 206, 235}, // #87CEEB
   322  	"slateblue":            {106, 90, 205},  // #6A5ACD
   323  	"slategray":            {112, 128, 144}, // #708090
   324  	"slategrey":            {112, 128, 144}, // #708090
   325  	"snow":                 {255, 250, 250}, // #FFFAFA
   326  	"springgreen":          {0, 255, 127},   // #00FF7F
   327  	"steelblue":            {70, 130, 180},  // #4682B4
   328  	"tan":                  {210, 180, 140}, // #D2B48C
   329  	"teal":                 {0, 128, 128},   // #008080
   330  	"thistle":              {216, 191, 216}, // #D8BFD8
   331  	"tomato":               {255, 99, 71},   // #FF6347
   332  	"turquoise":            {64, 224, 208},  // #40E0D0
   333  	"violet":               {238, 130, 238}, // #EE82EE
   334  	"wheat":                {245, 222, 179}, // #F5DEB3
   335  	"white":                {255, 255, 255}, // #FFFFFF
   336  	"whitesmoke":           {245, 245, 245}, // #F5F5F5
   337  	"yellow":               {255, 255, 0},   // #FFFF00
   338  	"yellowgreen":          {154, 205, 50},  // #9ACD32
   339  }
   340  
   341  func Name2RGB(name string) RGB {
   342  	if rgb, ok := namedRgbMap[strings.ToLower(name)]; ok {
   343  		return RGB{
   344  			Red:   rgb[0],
   345  			Green: rgb[1],
   346  			Blue:  rgb[2],
   347  		}
   348  	}
   349  	return RGB{}
   350  }
   351  
   352  var NamedColors = []string{
   353  	"currentcolor",
   354  	"transparent",
   355  	"aliceblue",
   356  	"antiquewhite",
   357  	"aqua",
   358  	"aquamarine",
   359  	"azure",
   360  	"beige",
   361  	"bisque",
   362  	"black",
   363  	"blanchedalmond",
   364  	"blue",
   365  	"blueviolet",
   366  	"brown",
   367  	"burlywood",
   368  	"cadetblue",
   369  	"chartreuse",
   370  	"chocolate",
   371  	"coral",
   372  	"cornflowerblue",
   373  	"cornsilk",
   374  	"crimson",
   375  	"cyan",
   376  	"darkblue",
   377  	"darkcyan",
   378  	"darkgoldenrod",
   379  	"darkgray",
   380  	"darkgrey",
   381  	"darkgreen",
   382  	"darkkhaki",
   383  	"darkmagenta",
   384  	"darkolivegreen",
   385  	"darkorange",
   386  	"darkorchid",
   387  	"darkred",
   388  	"darksalmon",
   389  	"darkseagreen",
   390  	"darkslateblue",
   391  	"darkslategray",
   392  	"darkslategrey",
   393  	"darkturquoise",
   394  	"darkviolet",
   395  	"deeppink",
   396  	"deepskyblue",
   397  	"dimgray",
   398  	"dimgrey",
   399  	"dodgerblue",
   400  	"firebrick",
   401  	"floralwhite",
   402  	"forestgreen",
   403  	"fuchsia",
   404  	"gainsboro",
   405  	"ghostwhite",
   406  	"gold",
   407  	"goldenrod",
   408  	"gray",
   409  	"grey",
   410  	"green",
   411  	"greenyellow",
   412  	"honeydew",
   413  	"hotpink",
   414  	"indianred",
   415  	"indigo",
   416  	"ivory",
   417  	"khaki",
   418  	"lavender",
   419  	"lavenderblush",
   420  	"lawngreen",
   421  	"lemonchiffon",
   422  	"lightblue",
   423  	"lightcoral",
   424  	"lightcyan",
   425  	"lightgoldenrodyellow",
   426  	"lightgray",
   427  	"lightgrey",
   428  	"lightgreen",
   429  	"lightpink",
   430  	"lightsalmon",
   431  	"lightseagreen",
   432  	"lightskyblue",
   433  	"lightslategray",
   434  	"lightslategrey",
   435  	"lightsteelblue",
   436  	"lightyellow",
   437  	"lime",
   438  	"limegreen",
   439  	"linen",
   440  	"magenta",
   441  	"maroon",
   442  	"mediumaquamarine",
   443  	"mediumblue",
   444  	"mediumorchid",
   445  	"mediumpurple",
   446  	"mediumseagreen",
   447  	"mediumslateblue",
   448  	"mediumspringgreen",
   449  	"mediumturquoise",
   450  	"mediumvioletred",
   451  	"midnightblue",
   452  	"mintcream",
   453  	"mistyrose",
   454  	"moccasin",
   455  	"navajowhite",
   456  	"navy",
   457  	"oldlace",
   458  	"olive",
   459  	"olivedrab",
   460  	"orange",
   461  	"orangered",
   462  	"orchid",
   463  	"palegoldenrod",
   464  	"palegreen",
   465  	"paleturquoise",
   466  	"palevioletred",
   467  	"papayawhip",
   468  	"peachpuff",
   469  	"peru",
   470  	"pink",
   471  	"plum",
   472  	"powderblue",
   473  	"purple",
   474  	"rebeccapurple",
   475  	"red",
   476  	"rosybrown",
   477  	"royalblue",
   478  	"saddlebrown",
   479  	"salmon",
   480  	"sandybrown",
   481  	"seagreen",
   482  	"seashell",
   483  	"sienna",
   484  	"silver",
   485  	"skyblue",
   486  	"slateblue",
   487  	"slategray",
   488  	"slategrey",
   489  	"snow",
   490  	"springgreen",
   491  	"steelblue",
   492  	"tan",
   493  	"teal",
   494  	"thistle",
   495  	"tomato",
   496  	"turquoise",
   497  	"violet",
   498  	"wheat",
   499  	"white",
   500  	"whitesmoke",
   501  	"yellow",
   502  	"yellowgreen",
   503  }
   504  
   505  var ColorHexRegex = regexp.MustCompile(`^#(([0-9a-fA-F]{2}){3}|([0-9a-fA-F]){3})$`)
   506  

View as plain text