Skip to content

Commit

Permalink
Provide Color constant references in chartdraw package
Browse files Browse the repository at this point in the history
The need to use `drawing` to reference specific colors was non-obvious to new users.
This change puts all previous (and some new) color constants in the `charts` package, making them easier to find and use.
  • Loading branch information
jentfoo committed Jan 25, 2025
1 parent ef0971d commit de68c5a
Show file tree
Hide file tree
Showing 27 changed files with 436 additions and 211 deletions.
7 changes: 3 additions & 4 deletions axis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"github.com/stretchr/testify/require"

"github.com/go-analyze/charts/chartdraw"
"github.com/go-analyze/charts/chartdraw/drawing"
)

func TestAxis(t *testing.T) {
Expand Down Expand Up @@ -201,7 +200,7 @@ func TestAxis(t *testing.T) {
Data: letterLabels,
FontStyle: FontStyle{
FontSize: 40.0,
FontColor: drawing.ColorBlue,
FontColor: ColorBlue,
},
}
},
Expand Down Expand Up @@ -232,8 +231,8 @@ func TestAxis(t *testing.T) {
axisTheme := MakeTheme(ThemeOption{
IsDarkMode: false,
AxisStrokeColor: Color{R: 110, G: 112, B: 121, A: 255},
AxisSplitLineColor: drawing.ColorBlack,
BackgroundColor: drawing.ColorWhite,
AxisSplitLineColor: ColorBlack,
BackgroundColor: ColorWhite,
TextColor: Color{R: 70, G: 70, B: 70, A: 255},
})
for i, tt := range tests {
Expand Down
4 changes: 1 addition & 3 deletions bar_chart_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import (

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/go-analyze/charts/chartdraw/drawing"
)

func makeBasicBarChartOption() BarChartOption {
Expand Down Expand Up @@ -111,7 +109,7 @@ func TestBarChart(t *testing.T) {
opt := makeBasicBarChartOption()
customFont := FontStyle{
FontSize: 4.0,
FontColor: drawing.ColorBlue,
FontColor: ColorBlue,
}
opt.Legend.FontStyle = customFont
opt.XAxis.FontStyle = customFont
Expand Down
6 changes: 2 additions & 4 deletions benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ package charts
import (
"errors"
"testing"

"github.com/go-analyze/charts/chartdraw"
)

func makeDefaultMultiChartOptions() ChartOption {
Expand All @@ -18,7 +16,7 @@ func makeDefaultMultiChartOptions() ChartOption {
"Milk Tea", "Matcha Latte", "Cheese Cocoa", "Walnut Brownie",
},
},
Padding: chartdraw.Box{
Padding: Box{
Top: 10,
Right: 10,
Bottom: 10,
Expand Down Expand Up @@ -53,7 +51,7 @@ func makeDefaultMultiChartOptions() ChartOption {
"Milk Tea", "Matcha Latte", "Cheese Cocoa", "Walnut Brownie",
},
},
Box: chartdraw.Box{
Box: Box{
Top: 20,
Left: 400,
Right: 500,
Expand Down
141 changes: 139 additions & 2 deletions color.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,120 @@ package charts

import (
"math"
"strings"

"github.com/go-analyze/charts/chartdraw"
"github.com/go-analyze/charts/chartdraw/drawing"
)

var (
// ColorTransparent is a fully transparent color.
ColorTransparent = drawing.ColorTransparent
// ColorWhite is R: 255, G: 255, B: 255.
ColorWhite = drawing.ColorWhite
// ColorBlack is R: 0, G: 0, B: 0.
ColorBlack = drawing.ColorBlack
// ColorGray is R: 128, G: 128, B: 128.
ColorGray = drawing.ColorGray
// ColorRed is R: 255, G: 0, B: 0.
ColorRed = drawing.ColorRed
// ColorGreen is R: 0, G: 128, B: 0.
ColorGreen = drawing.ColorGreen
// ColorBlue is R: 0, G: 0, B: 255.
ColorBlue = drawing.ColorBlue
// ColorSilver is R: 192, G: 192, B: 192.
ColorSilver = drawing.ColorSilver
// ColorMaroon is R: 128, G: 0, B: 0.
ColorMaroon = drawing.ColorMaroon
// ColorPurple is R: 128, G: 0, B: 128.
ColorPurple = drawing.ColorPurple
// ColorFuchsia is R: 255, G: 0, B: 255.
ColorFuchsia = drawing.ColorFuchsia
// ColorLime is R: 0, G: 255, B: 0.
ColorLime = drawing.ColorLime
// ColorOlive is R: 128, G: 128, B: 0.
ColorOlive = drawing.ColorOlive
// ColorYellow is R: 255, G: 255, B: 0.
ColorYellow = drawing.ColorYellow
// ColorNavy is R: 0, G: 0, B: 128.
ColorNavy = drawing.ColorNavy
// ColorTeal is R: 0, G: 128, B: 128.
ColorTeal = drawing.ColorTeal
// ColorAqua (or Cyan) is R: 0, G: 255, B: 255.
ColorAqua = drawing.ColorAqua
// ColorDarkGray is R: 40, G: 40, B: 40.
ColorDarkGray = Color{R: 40, G: 40, B: 40, A: 255}
// ColorLightGray is R: 211, G: 211, B: 211.
ColorLightGray = drawing.ColorLightGray
// ColorSlateGray is R: 112, G: 128, B: 144.
ColorSlateGray = drawing.ColorSlateGray
// ColorLightSlateGray is R: 119, G: 136, B: 211.
ColorLightSlateGray = drawing.ColorLightSlateGray
// ColorAzure is R: 240, G: 255, B: 255.
ColorAzure = drawing.ColorAzure
// ColorBeige is R: 245, G: 245, B: 220.
ColorBeige = drawing.ColorBeige
// ColorBrown is R: 165, G: 42, B: 42.
ColorBrown = drawing.ColorBrown
// ColorChocolate is R: 210, G: 105, B: 30.
ColorChocolate = drawing.ColorChocolate
// ColorCoral is R: 255, G: 127, B: 80.
ColorCoral = drawing.ColorCoral
// ColorGold is R: 255, G: 215, B: 0.
ColorGold = drawing.ColorGold
// ColorIndigo is R: 75, G: 0, B: 130.
ColorIndigo = drawing.ColorIndigo
// ColorIvory is R: 255, G: 255, B: 250.
ColorIvory = drawing.ColorIvory
// ColorOrange is R: 255, G: 165, B: 0.
ColorOrange = drawing.ColorOrange
// ColorPink is R: 255, G: 192, B: 203.
ColorPink = drawing.ColorPink
// ColorPlum is R: 221, G: 160, B: 221.
ColorPlum = drawing.ColorPlum
// ColorSalmon is R: 250, G: 128, B: 114.
ColorSalmon = drawing.ColorSalmon
// ColorTan is R: 210, G: 180, B: 140.
ColorTan = drawing.ColorTan
// ColorKhaki is R: 240, G: 230, B: 140.
ColorKhaki = drawing.ColorKhaki
// ColorTurquoise is R: 64, G: 224, B: 208.
ColorTurquoise = drawing.ColorTurquoise
// ColorViolet is R: 238, G: 130, B: 238.
ColorViolet = drawing.ColorViolet

// alternate non-standard shades //

// ColorBlackAlt1 is slightly lighter shade of black: R: 51, G: 51, B: 51.
ColorBlackAlt1 = chartdraw.ColorBlack
// ColorBlueAlt1 is lighter shade of blue: R:0, G: 116, B: 217.
ColorBlueAlt1 = chartdraw.ColorBlue
// ColorBlueAlt2 is a sea blue: R: 106, G: 195, B: 203.
ColorBlueAlt2 = chartdraw.ColorAlternateBlue
// ColorAquaAlt1 is a lighter aqua: R: 0, G: 217, B: 210.
ColorAquaAlt1 = chartdraw.ColorCyan
// ColorGreenAlt1 is lighter green: R: 0, G: 217, B: 101.
ColorGreenAlt1 = chartdraw.ColorGreen
// ColorGreenAlt2 is R: 42, G: 190, B: 137.
ColorGreenAlt2 = chartdraw.ColorAlternateGreen
// ColorGreenAlt3 is darker green: R: 59, G: 162, B: 114.
ColorGreenAlt3 = Color{R: 59, G: 162, B: 114, A: 255}
// ColorGreenAlt4 is darker green: R: 80, G: 134, B: 66.
ColorGreenAlt4 = Color{R: 80, G: 143, B: 66, A: 255}
// ColorRedAlt1 is slightly purple red: R: 217, G: 0, B: 116.
ColorRedAlt1 = chartdraw.ColorRed
// ColorRedAlt2 is darker purple red: R: 226, G: 77, B: 66.
ColorRedAlt2 = Color{R: 226, G: 77, B: 66, A: 255}
// ColorOrangeAlt1 is more typical orange: R: 217, G: 101, B: 0.
ColorOrangeAlt1 = chartdraw.ColorOrange
// ColorOrangeAlt2 is a lighter orange: R: 250, G: 200, B: 88.
ColorOrangeAlt2 = Color{R: 250, G: 200, B: 88, A: 255}
// ColorOrangeAlt3 is a lighter orange: R: 255, G: 152, B: 69.
ColorOrangeAlt3 = Color{R: 255, G: 152, B: 69, A: 255}
// ColorYellowAlt1 is a slightly darker yellow: R: 217, G: 210, B: 0.
ColorYellowAlt1 = chartdraw.ColorYellow
)

func isLightColor(c Color) bool {
r := float64(c.R) * float64(c.R) * 0.299
g := float64(c.G) * float64(c.G) * 0.587
Expand All @@ -15,6 +125,33 @@ func isLightColor(c Color) bool {

// ParseColor parses a color from a string. The color can be specified in hex with a `#` prefix (for example '#313233'),
// in rgb(i,i,i) or rgba(i,i,i,f) format, or as a common name (for example 'red').
func ParseColor(color string) Color {
return drawing.ParseColor(color)
func ParseColor(rawColor string) Color {
if strings.HasPrefix(rawColor, "#") {
return ColorFromHex(rawColor)
} else if strings.HasPrefix(rawColor, "rgb") {
return ColorFromRGBA(rawColor)
}
return ColorFromKnown(rawColor)
}

// ColorFromKnown returns an internal color from a known (basic) color name.
func ColorFromKnown(known string) Color {
return drawing.ColorFromKnown(known)
}

// ColorFromHex returns a color from a css hex code.
//
// NOTE: it will trim a leading '#' character if present.
func ColorFromHex(hex string) Color {
return drawing.ColorFromHex(hex)
}

// ColorFromRGBA returns a color from a `rgb(i,i,i)` or `rgba(i,i,i,f)` css function.
func ColorFromRGBA(color string) Color {
return drawing.ColorFromRGBA(color)
}

// ColorFromRGBAValues returns the system alpha mixed rgba values.
func ColorFromRGBAValues(r, g, b, a uint32) Color {
return drawing.ColorFromAlphaMixedRGBA(r, g, b, a)
}
112 changes: 84 additions & 28 deletions color_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,91 @@ import (
"testing"

"github.com/stretchr/testify/assert"

"github.com/go-analyze/charts/chartdraw/drawing"
"github.com/stretchr/testify/require"
)

func BenchmarkParseColor(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = ParseColor("#333")
_ = ParseColor("#313233")
_ = ParseColor("rgb(31,32,33)")
_ = ParseColor("rgba(50,51,52,250)")
}
}

func BenchmarkColorString(b *testing.B) {
c := ParseColor("rgb(31,32,33)")
for i := 0; i < b.N; i++ {
_ = c.String()
}
}

const makeColorShadeSamples = false

func testColorShades(t *testing.T, colors ...Color) {
if !makeColorShadeSamples {
return // color samples are generated through a test failure
}
t.Helper()

p := NewPainter(PainterOptions{
OutputFormat: ChartOutputSVG,
Width: 600,
Height: 400,
})

sampleWidth := p.Width() / len(colors)
for i, c := range colors {
p.FilledRect(i*sampleWidth, 0, (i+1)*sampleWidth, p.Height(),
c, ColorTransparent, 0.0)
}

data, err := p.Bytes()
require.NoError(t, err)
assertEqualSVG(t, "", data)
}

func TestGrayColors(t *testing.T) {
testColorShades(t, ColorDarkGray, ColorGray, ColorLightGray)
}

func TestBlueColors(t *testing.T) {
testColorShades(t, ColorBlue, ColorBlueAlt1, ColorBlueAlt2)
}

func TestGreenColors(t *testing.T) {
testColorShades(t, ColorGreen, ColorGreenAlt1, ColorGreenAlt2, ColorGreenAlt3, ColorGreenAlt4)
}

func TestRedColors(t *testing.T) {
testColorShades(t, ColorRed, ColorRedAlt1, ColorRedAlt2)
}

func TestOrangeColors(t *testing.T) {
testColorShades(t, ColorOrange, ColorOrangeAlt1, ColorOrangeAlt2, ColorOrangeAlt3)
}

func TestAquaColors(t *testing.T) {
testColorShades(t, ColorAqua, ColorAquaAlt1)
}

func TestYellowColors(t *testing.T) {
testColorShades(t, ColorYellow, ColorYellowAlt1)
}

func TestPurpleColors(t *testing.T) {
testColorShades(t, ColorPurple, ColorViolet, ColorPlum, ColorFuchsia)
}

func TestIsLightColor(t *testing.T) {
t.Parallel()

assert.True(t, isLightColor(drawing.Color{R: 255, G: 255, B: 255}))
assert.True(t, isLightColor(drawing.Color{R: 145, G: 204, B: 117}))
assert.True(t, isLightColor(Color{R: 255, G: 255, B: 255}))
assert.True(t, isLightColor(Color{R: 145, G: 204, B: 117}))

assert.False(t, isLightColor(drawing.Color{R: 88, G: 112, B: 198}))
assert.False(t, isLightColor(drawing.Color{R: 0, G: 0, B: 0}))
assert.False(t, isLightColor(drawing.Color{R: 16, G: 12, B: 42}))
assert.False(t, isLightColor(Color{R: 88, G: 112, B: 198}))
assert.False(t, isLightColor(Color{R: 0, G: 0, B: 0}))
assert.False(t, isLightColor(Color{R: 16, G: 12, B: 42}))
}

func TestParseColor(t *testing.T) {
Expand All @@ -26,33 +98,17 @@ func TestParseColor(t *testing.T) {
assert.True(t, c.IsZero())

c = ParseColor("#333")
assert.Equal(t, drawing.Color{R: 51, G: 51, B: 51, A: 255}, c)
assert.Equal(t, Color{R: 51, G: 51, B: 51, A: 255}, c)

c = ParseColor("#313233")
assert.Equal(t, drawing.Color{R: 49, G: 50, B: 51, A: 255}, c)
assert.Equal(t, Color{R: 49, G: 50, B: 51, A: 255}, c)

c = ParseColor("rgb(31,32,33)")
assert.Equal(t, drawing.Color{R: 31, G: 32, B: 33, A: 255}, c)
assert.Equal(t, Color{R: 31, G: 32, B: 33, A: 255}, c)

c = ParseColor("rgba(50,51,52,.981)")
assert.Equal(t, drawing.Color{R: 50, G: 51, B: 52, A: 250}, c)
assert.Equal(t, Color{R: 50, G: 51, B: 52, A: 250}, c)

c = ParseColor("rgba(50,51,52,250)")
assert.Equal(t, drawing.Color{R: 50, G: 51, B: 52, A: 250}, c)
}

func BenchmarkParseColor(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = ParseColor("#333")
_ = ParseColor("#313233")
_ = ParseColor("rgb(31,32,33)")
_ = ParseColor("rgba(50,51,52,250)")
}
}

func BenchmarkColorString(b *testing.B) {
c := ParseColor("rgb(31,32,33)")
for i := 0; i < b.N; i++ {
_ = c.String()
}
assert.Equal(t, Color{R: 50, G: 51, B: 52, A: 250}, c)
}
4 changes: 2 additions & 2 deletions echarts.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ func (ey *EChartsYAxis) UnmarshalJSON(data []byte) error {
}

type EChartsPadding struct {
Box chartdraw.Box
Box Box
}

func (eb *EChartsPadding) UnmarshalJSON(data []byte) error {
Expand Down Expand Up @@ -344,7 +344,7 @@ type EChartsOption struct {
Theme string `json:"theme"`
FontFamily string `json:"fontFamily"`
Padding EChartsPadding `json:"padding"`
Box chartdraw.Box `json:"box"`
Box Box `json:"box"`
Width int `json:"width"`
Height int `json:"height"`
Title struct {
Expand Down
Loading

0 comments on commit de68c5a

Please sign in to comment.