updates
This commit is contained in:
parent
e3e851d2d1
commit
de6df027fc
14 changed files with 116 additions and 85 deletions
|
@ -261,7 +261,7 @@ func (bc BarChart) drawYAxis(r Renderer, canvasBox Box, yr Range, ticks []Tick)
|
||||||
r.Stroke()
|
r.Stroke()
|
||||||
|
|
||||||
var ty int
|
var ty int
|
||||||
var tb Box
|
var tb Box2d
|
||||||
for _, t := range ticks {
|
for _, t := range ticks {
|
||||||
ty = canvasBox.Bottom - yr.Translate(t.Value)
|
ty = canvasBox.Bottom - yr.Translate(t.Value)
|
||||||
|
|
||||||
|
@ -272,7 +272,7 @@ func (bc BarChart) drawYAxis(r Renderer, canvasBox Box, yr Range, ticks []Tick)
|
||||||
|
|
||||||
axisStyle.GetTextOptions().WriteToRenderer(r)
|
axisStyle.GetTextOptions().WriteToRenderer(r)
|
||||||
tb = r.MeasureText(t.Label)
|
tb = r.MeasureText(t.Label)
|
||||||
Draw.Text(r, t.Label, canvasBox.Right+DefaultYAxisMargin+5, ty+(tb.Height()>>1), axisStyle)
|
Draw.Text(r, t.Label, canvasBox.Right+DefaultYAxisMargin+5, ty+(int(tb.Height())>>1), axisStyle)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -369,7 +369,7 @@ func (bc BarChart) getAdjustedCanvasBox(r Renderer, canvasBox Box, yrange Range,
|
||||||
lines := Text.WrapFit(r, bar.Label, barLabelBox.Width(), axisStyle)
|
lines := Text.WrapFit(r, bar.Label, barLabelBox.Width(), axisStyle)
|
||||||
linesBox := Text.MeasureLines(r, lines, axisStyle)
|
linesBox := Text.MeasureLines(r, lines, axisStyle)
|
||||||
|
|
||||||
xaxisHeight = util.Math.MinInt(linesBox.Height()+(2*DefaultXAxisMargin), xaxisHeight)
|
xaxisHeight = util.Math.MinInt(int(linesBox.Height())+(2*DefaultXAxisMargin), xaxisHeight)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
45
box_2d.go
45
box_2d.go
|
@ -26,13 +26,33 @@ func (bc Box2d) Points() []Point {
|
||||||
// Box return the Box2d as a regular box.
|
// Box return the Box2d as a regular box.
|
||||||
func (bc Box2d) Box() Box {
|
func (bc Box2d) Box() Box {
|
||||||
return Box{
|
return Box{
|
||||||
Top: int(math.Min(bc.TopLeft.Y, bc.TopRight.Y)),
|
Top: int(bc.Top()),
|
||||||
Left: int(math.Min(bc.TopLeft.X, bc.BottomLeft.X)),
|
Left: int(bc.Left()),
|
||||||
Right: int(math.Max(bc.TopRight.X, bc.BottomRight.X)),
|
Right: int(bc.Right()),
|
||||||
Bottom: int(math.Max(bc.BottomLeft.Y, bc.BottomRight.Y)),
|
Bottom: int(bc.Bottom()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Top returns the top-most corner y value.
|
||||||
|
func (bc Box2d) Top() float64 {
|
||||||
|
return math.Min(bc.TopLeft.Y, bc.TopRight.Y)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Left returns the left-most corner x value.
|
||||||
|
func (bc Box2d) Left() float64 {
|
||||||
|
return math.Min(bc.TopLeft.X, bc.BottomLeft.X)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Right returns the right-most corner x value.
|
||||||
|
func (bc Box2d) Right() float64 {
|
||||||
|
return math.Max(bc.TopRight.X, bc.BottomRight.X)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bottom returns the bottom-most corner y value.
|
||||||
|
func (bc Box2d) Bottom() float64 {
|
||||||
|
return math.Max(bc.BottomLeft.Y, bc.BottomLeft.Y)
|
||||||
|
}
|
||||||
|
|
||||||
// Width returns the width
|
// Width returns the width
|
||||||
func (bc Box2d) Width() float64 {
|
func (bc Box2d) Width() float64 {
|
||||||
minLeft := math.Min(bc.TopLeft.X, bc.BottomLeft.X)
|
minLeft := math.Min(bc.TopLeft.X, bc.BottomLeft.X)
|
||||||
|
@ -117,6 +137,17 @@ func (bc Box2d) Overlaps(other Box2d) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Grow grows a box by a given set of dimensions.
|
||||||
|
func (bc Box2d) Grow(by Box) Box2d {
|
||||||
|
top, left, right, bottom := float64(by.Top), float64(by.Left), float64(by.Right), float64(by.Bottom)
|
||||||
|
return Box2d{
|
||||||
|
TopLeft: Point{X: bc.TopLeft.X - left, Y: bc.TopLeft.Y - top},
|
||||||
|
TopRight: Point{X: bc.TopRight.X + right, Y: bc.TopRight.Y - top},
|
||||||
|
BottomRight: Point{X: bc.BottomRight.X + right, Y: bc.BottomRight.Y + bottom},
|
||||||
|
BottomLeft: Point{X: bc.BottomLeft.X - left, Y: bc.BottomLeft.Y + bottom},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (bc Box2d) String() string {
|
func (bc Box2d) String() string {
|
||||||
return fmt.Sprintf("Box2d{%s,%s,%s,%s}", bc.TopLeft.String(), bc.TopRight.String(), bc.BottomRight.String(), bc.BottomLeft.String())
|
return fmt.Sprintf("Box2d{%s,%s,%s,%s}", bc.TopLeft.String(), bc.TopRight.String(), bc.BottomRight.String(), bc.BottomLeft.String())
|
||||||
}
|
}
|
||||||
|
@ -136,8 +167,8 @@ func (p Point) Shift(x, y float64) Point {
|
||||||
|
|
||||||
// DistanceTo calculates the distance to another point.
|
// DistanceTo calculates the distance to another point.
|
||||||
func (p Point) DistanceTo(other Point) float64 {
|
func (p Point) DistanceTo(other Point) float64 {
|
||||||
dx := math.Pow(float64(p.X-other.X), 2)
|
dx := math.Pow(p.X-other.X, 2)
|
||||||
dy := math.Pow(float64(p.Y-other.Y), 2)
|
dy := math.Pow(p.Y-other.Y, 2)
|
||||||
return math.Pow(dx+dy, 0.5)
|
return math.Pow(dx+dy, 0.5)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,5 +179,5 @@ func (p Point) Equals(other Point) bool {
|
||||||
|
|
||||||
// String returns a string representation of the point.
|
// String returns a string representation of the point.
|
||||||
func (p Point) String() string {
|
func (p Point) String() string {
|
||||||
return fmt.Sprintf("P{%.2f,%.2f}", p.X, p.Y)
|
return fmt.Sprintf("(%.2f,%.2f)", p.X, p.Y)
|
||||||
}
|
}
|
||||||
|
|
4
chart.go
4
chart.go
|
@ -502,8 +502,8 @@ func (c Chart) drawTitle(r Renderer) {
|
||||||
textWidth := textBox.Width()
|
textWidth := textBox.Width()
|
||||||
textHeight := textBox.Height()
|
textHeight := textBox.Height()
|
||||||
|
|
||||||
titleX := (c.GetWidth() >> 1) - (textWidth >> 1)
|
titleX := (int(c.GetWidth()) >> 1) - (int(textWidth) >> 1)
|
||||||
titleY := c.TitleStyle.Padding.GetTop(DefaultTitleTop) + textHeight
|
titleY := c.TitleStyle.Padding.GetTop(DefaultTitleTop) + int(textHeight)
|
||||||
|
|
||||||
r.Text(c.Title, titleX, titleY)
|
r.Text(c.Title, titleX, titleY)
|
||||||
}
|
}
|
||||||
|
|
22
draw.go
22
draw.go
|
@ -233,8 +233,8 @@ func (d draw) MeasureAnnotation(r Renderer, canvasBox Box, style Style, lx, ly i
|
||||||
defer r.ResetStyle()
|
defer r.ResetStyle()
|
||||||
|
|
||||||
textBox := r.MeasureText(label)
|
textBox := r.MeasureText(label)
|
||||||
textWidth := textBox.Width()
|
textWidth := int(textBox.Width())
|
||||||
textHeight := textBox.Height()
|
textHeight := int(textBox.Height())
|
||||||
halfTextHeight := textHeight >> 1
|
halfTextHeight := textHeight >> 1
|
||||||
|
|
||||||
pt := style.Padding.GetTop(DefaultAnnotationPadding.Top)
|
pt := style.Padding.GetTop(DefaultAnnotationPadding.Top)
|
||||||
|
@ -262,8 +262,8 @@ func (d draw) Annotation(r Renderer, canvasBox Box, style Style, lx, ly int, lab
|
||||||
defer r.ResetStyle()
|
defer r.ResetStyle()
|
||||||
|
|
||||||
textBox := r.MeasureText(label)
|
textBox := r.MeasureText(label)
|
||||||
textWidth := textBox.Width()
|
textWidth := int(textBox.Width())
|
||||||
halfTextHeight := textBox.Height() >> 1
|
halfTextHeight := int(textBox.Height()) >> 1
|
||||||
|
|
||||||
style.GetFillAndStrokeOptions().WriteToRenderer(r)
|
style.GetFillAndStrokeOptions().WriteToRenderer(r)
|
||||||
|
|
||||||
|
@ -337,7 +337,7 @@ func (d draw) Text(r Renderer, text string, x, y int, style Style) {
|
||||||
r.Text(text, x, y)
|
r.Text(text, x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d draw) MeasureText(r Renderer, text string, style Style) Box {
|
func (d draw) MeasureText(r Renderer, text string, style Style) Box2d {
|
||||||
style.GetTextOptions().WriteToRenderer(r)
|
style.GetTextOptions().WriteToRenderer(r)
|
||||||
defer r.ResetStyle()
|
defer r.ResetStyle()
|
||||||
|
|
||||||
|
@ -356,9 +356,9 @@ func (d draw) TextWithin(r Renderer, text string, box Box, style Style) {
|
||||||
|
|
||||||
switch style.GetTextVerticalAlign() {
|
switch style.GetTextVerticalAlign() {
|
||||||
case TextVerticalAlignBottom, TextVerticalAlignBaseline: // i have to build better baseline handling into measure text
|
case TextVerticalAlignBottom, TextVerticalAlignBaseline: // i have to build better baseline handling into measure text
|
||||||
y = y - linesBox.Height()
|
y = y - int(linesBox.Height())
|
||||||
case TextVerticalAlignMiddle, TextVerticalAlignMiddleBaseline:
|
case TextVerticalAlignMiddle, TextVerticalAlignMiddleBaseline:
|
||||||
y = (y - linesBox.Height()) >> 1
|
y = (y - int(linesBox.Height())) >> 1
|
||||||
}
|
}
|
||||||
|
|
||||||
var tx, ty int
|
var tx, ty int
|
||||||
|
@ -366,19 +366,19 @@ func (d draw) TextWithin(r Renderer, text string, box Box, style Style) {
|
||||||
lineBox := r.MeasureText(line)
|
lineBox := r.MeasureText(line)
|
||||||
switch style.GetTextHorizontalAlign() {
|
switch style.GetTextHorizontalAlign() {
|
||||||
case TextHorizontalAlignCenter:
|
case TextHorizontalAlignCenter:
|
||||||
tx = box.Left + ((box.Width() - lineBox.Width()) >> 1)
|
tx = box.Left + ((int(box.Width()) - int(lineBox.Width())) >> 1)
|
||||||
case TextHorizontalAlignRight:
|
case TextHorizontalAlignRight:
|
||||||
tx = box.Right - lineBox.Width()
|
tx = box.Right - int(lineBox.Width())
|
||||||
default:
|
default:
|
||||||
tx = box.Left
|
tx = box.Left
|
||||||
}
|
}
|
||||||
if style.TextRotationDegrees == 0 {
|
if style.TextRotationDegrees == 0 {
|
||||||
ty = y + lineBox.Height()
|
ty = y + int(lineBox.Height())
|
||||||
} else {
|
} else {
|
||||||
ty = y
|
ty = y
|
||||||
}
|
}
|
||||||
|
|
||||||
r.Text(line, tx, ty)
|
r.Text(line, tx, ty)
|
||||||
y += lineBox.Height() + style.GetTextLineSpacing()
|
y += int(lineBox.Height()) + style.GetTextLineSpacing()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
34
legend.go
34
legend.go
|
@ -67,8 +67,8 @@ func Legend(c *Chart, userDefaults ...Style) Renderable {
|
||||||
if labelCount > 0 {
|
if labelCount > 0 {
|
||||||
legendContent.Bottom += DefaultMinimumTickVerticalSpacing
|
legendContent.Bottom += DefaultMinimumTickVerticalSpacing
|
||||||
}
|
}
|
||||||
legendContent.Bottom += tb.Height()
|
legendContent.Bottom += int(tb.Height())
|
||||||
right := legendContent.Left + tb.Width() + lineTextGap + lineLengthMinimum
|
right := legendContent.Left + int(tb.Width()) + lineTextGap + lineLengthMinimum
|
||||||
legendContent.Right = util.Math.MaxInt(legendContent.Right, right)
|
legendContent.Right = util.Math.MaxInt(legendContent.Right, right)
|
||||||
labelCount++
|
labelCount++
|
||||||
}
|
}
|
||||||
|
@ -95,12 +95,12 @@ func Legend(c *Chart, userDefaults ...Style) Renderable {
|
||||||
|
|
||||||
tb := r.MeasureText(label)
|
tb := r.MeasureText(label)
|
||||||
|
|
||||||
ty := ycursor + tb.Height()
|
ty := ycursor + int(tb.Height())
|
||||||
r.Text(label, tx, ty)
|
r.Text(label, tx, ty)
|
||||||
|
|
||||||
th2 := tb.Height() >> 1
|
th2 := int(tb.Height()) >> 1
|
||||||
|
|
||||||
lx := tx + tb.Width() + lineTextGap
|
lx := tx + int(tb.Width()) + lineTextGap
|
||||||
ly := ty - th2
|
ly := ty - th2
|
||||||
lx2 := legendContent.Right - legendPadding.Right
|
lx2 := legendContent.Right - legendPadding.Right
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ func Legend(c *Chart, userDefaults ...Style) Renderable {
|
||||||
r.LineTo(lx2, ly)
|
r.LineTo(lx2, ly)
|
||||||
r.Stroke()
|
r.Stroke()
|
||||||
|
|
||||||
ycursor += tb.Height()
|
ycursor += int(tb.Height())
|
||||||
legendCount++
|
legendCount++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -160,12 +160,12 @@ func LegendThin(c *Chart, userDefaults ...Style) Renderable {
|
||||||
|
|
||||||
var textHeight int
|
var textHeight int
|
||||||
var textWidth int
|
var textWidth int
|
||||||
var textBox Box
|
var textBox Box2d
|
||||||
for x := 0; x < len(labels); x++ {
|
for x := 0; x < len(labels); x++ {
|
||||||
if len(labels[x]) > 0 {
|
if len(labels[x]) > 0 {
|
||||||
textBox = r.MeasureText(labels[x])
|
textBox = r.MeasureText(labels[x])
|
||||||
textHeight = util.Math.MaxInt(textBox.Height(), textHeight)
|
textHeight = util.Math.MaxInt(int(textBox.Height()), textHeight)
|
||||||
textWidth = util.Math.MaxInt(textBox.Width(), textWidth)
|
textWidth = util.Math.MaxInt(int(textBox.Width()), textWidth)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,7 +200,7 @@ func LegendThin(c *Chart, userDefaults ...Style) Renderable {
|
||||||
textBox = r.MeasureText(label)
|
textBox = r.MeasureText(label)
|
||||||
r.Text(label, tx, ty)
|
r.Text(label, tx, ty)
|
||||||
|
|
||||||
lx = tx + textBox.Width() + lineTextGap
|
lx = tx + int(textBox.Width()) + lineTextGap
|
||||||
ly = ty - th2
|
ly = ty - th2
|
||||||
|
|
||||||
r.SetStrokeColor(lines[index].GetStrokeColor())
|
r.SetStrokeColor(lines[index].GetStrokeColor())
|
||||||
|
@ -211,7 +211,7 @@ func LegendThin(c *Chart, userDefaults ...Style) Renderable {
|
||||||
r.LineTo(lx+lineLengthMinimum, ly)
|
r.LineTo(lx+lineLengthMinimum, ly)
|
||||||
r.Stroke()
|
r.Stroke()
|
||||||
|
|
||||||
tx += textBox.Width() + DefaultMinimumTickHorizontalSpacing + lineTextGap + lineLengthMinimum
|
tx += int(textBox.Width()) + DefaultMinimumTickHorizontalSpacing + lineTextGap + lineLengthMinimum
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -279,8 +279,8 @@ func LegendLeft(c *Chart, userDefaults ...Style) Renderable {
|
||||||
if labelCount > 0 {
|
if labelCount > 0 {
|
||||||
legendContent.Bottom += DefaultMinimumTickVerticalSpacing
|
legendContent.Bottom += DefaultMinimumTickVerticalSpacing
|
||||||
}
|
}
|
||||||
legendContent.Bottom += tb.Height()
|
legendContent.Bottom += int(tb.Height())
|
||||||
right := legendContent.Left + tb.Width() + lineTextGap + lineLengthMinimum
|
right := legendContent.Left + int(tb.Width()) + lineTextGap + lineLengthMinimum
|
||||||
legendContent.Right = util.Math.MaxInt(legendContent.Right, right)
|
legendContent.Right = util.Math.MaxInt(legendContent.Right, right)
|
||||||
labelCount++
|
labelCount++
|
||||||
}
|
}
|
||||||
|
@ -307,12 +307,12 @@ func LegendLeft(c *Chart, userDefaults ...Style) Renderable {
|
||||||
|
|
||||||
tb := r.MeasureText(label)
|
tb := r.MeasureText(label)
|
||||||
|
|
||||||
ty := ycursor + tb.Height()
|
ty := ycursor + int(tb.Height())
|
||||||
r.Text(label, tx, ty)
|
r.Text(label, tx, ty)
|
||||||
|
|
||||||
th2 := tb.Height() >> 1
|
th2 := int(tb.Height()) >> 1
|
||||||
|
|
||||||
lx := tx + tb.Width() + lineTextGap
|
lx := tx + int(tb.Width()) + lineTextGap
|
||||||
ly := ty - th2
|
ly := ty - th2
|
||||||
lx2 := legendContent.Right - legendPadding.Right
|
lx2 := legendContent.Right - legendPadding.Right
|
||||||
|
|
||||||
|
@ -324,7 +324,7 @@ func LegendLeft(c *Chart, userDefaults ...Style) Renderable {
|
||||||
r.LineTo(lx2, ly)
|
r.LineTo(lx2, ly)
|
||||||
r.Stroke()
|
r.Stroke()
|
||||||
|
|
||||||
ycursor += tb.Height()
|
ycursor += int(tb.Height())
|
||||||
legendCount++
|
legendCount++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,7 +155,7 @@ func (mhr *MarketHoursRange) measureTimes(r Renderer, defaults Style, vf ValueFo
|
||||||
timeLabel := vf(t)
|
timeLabel := vf(t)
|
||||||
|
|
||||||
labelBox := r.MeasureText(timeLabel)
|
labelBox := r.MeasureText(timeLabel)
|
||||||
total += labelBox.Width()
|
total += int(labelBox.Width())
|
||||||
if index > 0 {
|
if index > 0 {
|
||||||
total += DefaultMinimumTickHorizontalSpacing
|
total += DefaultMinimumTickHorizontalSpacing
|
||||||
}
|
}
|
||||||
|
|
|
@ -162,8 +162,8 @@ func (pc PieChart) drawSlices(r Renderer, canvasBox Box, values []Value) {
|
||||||
lx, ly = util.Math.CirclePoint(cx, cy, labelRadius, delta2)
|
lx, ly = util.Math.CirclePoint(cx, cy, labelRadius, delta2)
|
||||||
|
|
||||||
tb := r.MeasureText(v.Label)
|
tb := r.MeasureText(v.Label)
|
||||||
lx = lx - (tb.Width() >> 1)
|
lx = lx - (int(tb.Width()) >> 1)
|
||||||
ly = ly + (tb.Height() >> 1)
|
ly = ly + (int(tb.Height()) >> 1)
|
||||||
|
|
||||||
r.Text(v.Label, lx, ly)
|
r.Text(v.Label, lx, ly)
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,13 +155,13 @@ func (rr *rasterRenderer) Text(body string, x, y int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// MeasureText returns the height and width in pixels of a string.
|
// MeasureText returns the height and width in pixels of a string.
|
||||||
func (rr *rasterRenderer) MeasureText(body string) Box {
|
func (rr *rasterRenderer) MeasureText(body string) Box2d {
|
||||||
rr.gc.SetFont(rr.s.Font)
|
rr.gc.SetFont(rr.s.Font)
|
||||||
rr.gc.SetFontSize(rr.s.FontSize)
|
rr.gc.SetFontSize(rr.s.FontSize)
|
||||||
rr.gc.SetFillColor(rr.s.FontColor)
|
rr.gc.SetFillColor(rr.s.FontColor)
|
||||||
l, t, r, b, err := rr.gc.GetStringBounds(body)
|
l, t, r, b, err := rr.gc.GetStringBounds(body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Box{}
|
return Box2d{}
|
||||||
}
|
}
|
||||||
if l < 0 {
|
if l < 0 {
|
||||||
r = r - l // equivalent to r+(-1*l)
|
r = r - l // equivalent to r+(-1*l)
|
||||||
|
@ -189,10 +189,10 @@ func (rr *rasterRenderer) MeasureText(body string) Box {
|
||||||
Bottom: int(math.Ceil(b)),
|
Bottom: int(math.Ceil(b)),
|
||||||
}
|
}
|
||||||
if rr.rotateRadians == nil {
|
if rr.rotateRadians == nil {
|
||||||
return textBox
|
return textBox.Corners()
|
||||||
}
|
}
|
||||||
|
|
||||||
return textBox.Corners().Rotate(util.Math.RadiansToDegrees(*rr.rotateRadians)).Box()
|
return textBox.Corners().Rotate(util.Math.RadiansToDegrees(*rr.rotateRadians))
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTextRotation sets a text rotation.
|
// SetTextRotation sets a text rotation.
|
||||||
|
|
|
@ -73,7 +73,7 @@ type Renderer interface {
|
||||||
Text(body string, x, y int)
|
Text(body string, x, y int)
|
||||||
|
|
||||||
// MeasureText measures text.
|
// MeasureText measures text.
|
||||||
MeasureText(body string) Box
|
MeasureText(body string) Box2d
|
||||||
|
|
||||||
// SetTextRotatation sets a rotation for drawing elements.
|
// SetTextRotatation sets a rotation for drawing elements.
|
||||||
SetTextRotation(radians float64)
|
SetTextRotation(radians float64)
|
||||||
|
|
|
@ -214,7 +214,7 @@ func (sbc StackedBarChart) drawYAxis(r Renderer, canvasBox Box) {
|
||||||
text := fmt.Sprintf("%0.0f%%", t*100)
|
text := fmt.Sprintf("%0.0f%%", t*100)
|
||||||
|
|
||||||
tb := r.MeasureText(text)
|
tb := r.MeasureText(text)
|
||||||
Draw.Text(r, text, canvasBox.Right+DefaultYAxisMargin+5, ty+(tb.Height()>>1), axisStyle)
|
Draw.Text(r, text, canvasBox.Right+DefaultYAxisMargin+5, ty+(int(tb.Height())>>1), axisStyle)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -254,7 +254,7 @@ func (sbc StackedBarChart) getAdjustedCanvasBox(r Renderer, canvasBox Box) Box {
|
||||||
lines := Text.WrapFit(r, bar.Name, barLabelBox.Width(), axisStyle)
|
lines := Text.WrapFit(r, bar.Name, barLabelBox.Width(), axisStyle)
|
||||||
linesBox := Text.MeasureLines(r, lines, axisStyle)
|
linesBox := Text.MeasureLines(r, lines, axisStyle)
|
||||||
|
|
||||||
xaxisHeight = util.Math.MaxInt(linesBox.Height()+(2*DefaultXAxisMargin), xaxisHeight)
|
xaxisHeight = util.Math.MaxInt(int(linesBox.Height())+(2*DefaultXAxisMargin), xaxisHeight)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Box{
|
return Box{
|
||||||
|
|
16
text.go
16
text.go
|
@ -85,7 +85,7 @@ func (t text) WrapFitWord(r Renderer, value string, width int, style Style) []st
|
||||||
var line string
|
var line string
|
||||||
var word string
|
var word string
|
||||||
|
|
||||||
var textBox Box
|
var textBox Box2d
|
||||||
|
|
||||||
for _, c := range value {
|
for _, c := range value {
|
||||||
if c == rune('\n') { // commit the line to output
|
if c == rune('\n') { // commit the line to output
|
||||||
|
@ -97,7 +97,7 @@ func (t text) WrapFitWord(r Renderer, value string, width int, style Style) []st
|
||||||
|
|
||||||
textBox = r.MeasureText(line + word + string(c))
|
textBox = r.MeasureText(line + word + string(c))
|
||||||
|
|
||||||
if textBox.Width() >= width {
|
if int(textBox.Width()) >= width {
|
||||||
output = append(output, t.Trim(line))
|
output = append(output, t.Trim(line))
|
||||||
line = word
|
line = word
|
||||||
word = string(c)
|
word = string(c)
|
||||||
|
@ -120,7 +120,7 @@ func (t text) WrapFitRune(r Renderer, value string, width int, style Style) []st
|
||||||
|
|
||||||
var output []string
|
var output []string
|
||||||
var line string
|
var line string
|
||||||
var textBox Box
|
var textBox Box2d
|
||||||
for _, c := range value {
|
for _, c := range value {
|
||||||
if c == rune('\n') {
|
if c == rune('\n') {
|
||||||
output = append(output, line)
|
output = append(output, line)
|
||||||
|
@ -130,7 +130,7 @@ func (t text) WrapFitRune(r Renderer, value string, width int, style Style) []st
|
||||||
|
|
||||||
textBox = r.MeasureText(line + string(c))
|
textBox = r.MeasureText(line + string(c))
|
||||||
|
|
||||||
if textBox.Width() >= width {
|
if int(textBox.Width()) >= width {
|
||||||
output = append(output, line)
|
output = append(output, line)
|
||||||
line = string(c)
|
line = string(c)
|
||||||
continue
|
continue
|
||||||
|
@ -144,18 +144,18 @@ func (t text) Trim(value string) string {
|
||||||
return strings.Trim(value, " \t\n\r")
|
return strings.Trim(value, " \t\n\r")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t text) MeasureLines(r Renderer, lines []string, style Style) Box {
|
func (t text) MeasureLines(r Renderer, lines []string, style Style) Box2d {
|
||||||
style.WriteTextOptionsToRenderer(r)
|
style.WriteTextOptionsToRenderer(r)
|
||||||
var output Box
|
var output Box
|
||||||
for index, line := range lines {
|
for index, line := range lines {
|
||||||
lineBox := r.MeasureText(line)
|
lineBox := r.MeasureText(line)
|
||||||
output.Right = util.Math.MaxInt(lineBox.Right, output.Right)
|
output.Right = util.Math.MaxInt(int(lineBox.Right()), output.Right)
|
||||||
output.Bottom += lineBox.Height()
|
output.Bottom += int(lineBox.Height())
|
||||||
if index < len(lines)-1 {
|
if index < len(lines)-1 {
|
||||||
output.Bottom += +style.GetTextLineSpacing()
|
output.Bottom += +style.GetTextLineSpacing()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return output
|
return output.Corners()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t text) appendLast(lines []string, text string) []string {
|
func (t text) appendLast(lines []string, text string) []string {
|
||||||
|
|
|
@ -7,11 +7,10 @@ import (
|
||||||
"math"
|
"math"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"golang.org/x/image/font"
|
|
||||||
|
|
||||||
util "github.com/blendlabs/go-util"
|
|
||||||
"github.com/golang/freetype/truetype"
|
"github.com/golang/freetype/truetype"
|
||||||
"github.com/wcharczuk/go-chart/drawing"
|
"github.com/wcharczuk/go-chart/drawing"
|
||||||
|
"github.com/wcharczuk/go-chart/util"
|
||||||
|
"golang.org/x/image/font"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SVG returns a new png/raster renderer.
|
// SVG returns a new png/raster renderer.
|
||||||
|
@ -162,7 +161,8 @@ func (vr *vectorRenderer) Text(body string, x, y int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// MeasureText uses the truetype font drawer to measure the width of text.
|
// MeasureText uses the truetype font drawer to measure the width of text.
|
||||||
func (vr *vectorRenderer) MeasureText(body string) (box Box) {
|
func (vr *vectorRenderer) MeasureText(body string) Box2d {
|
||||||
|
var box Box
|
||||||
if vr.s.GetFont() != nil {
|
if vr.s.GetFont() != nil {
|
||||||
vr.fc = &font.Drawer{
|
vr.fc = &font.Drawer{
|
||||||
Face: truetype.NewFace(vr.s.GetFont(), &truetype.Options{
|
Face: truetype.NewFace(vr.s.GetFont(), &truetype.Options{
|
||||||
|
@ -175,11 +175,11 @@ func (vr *vectorRenderer) MeasureText(body string) (box Box) {
|
||||||
box.Right = w
|
box.Right = w
|
||||||
box.Bottom = int(drawing.PointsToPixels(vr.dpi, vr.s.FontSize))
|
box.Bottom = int(drawing.PointsToPixels(vr.dpi, vr.s.FontSize))
|
||||||
if vr.c.textTheta == nil {
|
if vr.c.textTheta == nil {
|
||||||
return
|
return box.Corners()
|
||||||
}
|
}
|
||||||
box = box.Corners().Rotate(util.Math.RadiansToDegrees(*vr.c.textTheta)).Box()
|
return box.Corners().Rotate(util.Math.RadiansToDegrees(*vr.c.textTheta))
|
||||||
}
|
}
|
||||||
return
|
return box.Corners()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTextRotation sets the text rotation.
|
// SetTextRotation sets the text rotation.
|
||||||
|
|
20
xaxis.go
20
xaxis.go
|
@ -91,11 +91,11 @@ func (xa XAxis) Measure(r Renderer, canvasBox Box, ra Range, defaults Style, tic
|
||||||
tb := Draw.MeasureText(r, t.Label, tickStyle.GetTextOptions())
|
tb := Draw.MeasureText(r, t.Label, tickStyle.GetTextOptions())
|
||||||
|
|
||||||
tx = canvasBox.Left + ra.Translate(v)
|
tx = canvasBox.Left + ra.Translate(v)
|
||||||
ty = canvasBox.Bottom + DefaultXAxisMargin + tb.Height()
|
ty = canvasBox.Bottom + DefaultXAxisMargin + int(tb.Height())
|
||||||
switch tp {
|
switch tp {
|
||||||
case TickPositionUnderTick, TickPositionUnset:
|
case TickPositionUnderTick, TickPositionUnset:
|
||||||
ltx = tx - tb.Width()>>1
|
ltx = tx - int(tb.Width())>>1
|
||||||
rtx = tx + tb.Width()>>1
|
rtx = tx + int(tb.Width())>>1
|
||||||
break
|
break
|
||||||
case TickPositionBetweenTicks:
|
case TickPositionBetweenTicks:
|
||||||
if index > 0 {
|
if index > 0 {
|
||||||
|
@ -112,7 +112,7 @@ func (xa XAxis) Measure(r Renderer, canvasBox Box, ra Range, defaults Style, tic
|
||||||
|
|
||||||
if xa.NameStyle.Show && len(xa.Name) > 0 {
|
if xa.NameStyle.Show && len(xa.Name) > 0 {
|
||||||
tb := Draw.MeasureText(r, xa.Name, xa.NameStyle.InheritFrom(defaults))
|
tb := Draw.MeasureText(r, xa.Name, xa.NameStyle.InheritFrom(defaults))
|
||||||
bottom += DefaultXAxisMargin + tb.Height()
|
bottom += DefaultXAxisMargin + int(tb.Height())
|
||||||
}
|
}
|
||||||
|
|
||||||
return Box{
|
return Box{
|
||||||
|
@ -153,13 +153,13 @@ func (xa XAxis) Render(r Renderer, canvasBox Box, ra Range, defaults Style, tick
|
||||||
switch tp {
|
switch tp {
|
||||||
case TickPositionUnderTick, TickPositionUnset:
|
case TickPositionUnderTick, TickPositionUnset:
|
||||||
if tickStyle.TextRotationDegrees == 0 {
|
if tickStyle.TextRotationDegrees == 0 {
|
||||||
tx = tx - tb.Width()>>1
|
tx = tx - int(tb.Width())>>1
|
||||||
ty = canvasBox.Bottom + DefaultXAxisMargin + tb.Height()
|
ty = canvasBox.Bottom + DefaultXAxisMargin + int(tb.Height())
|
||||||
} else {
|
} else {
|
||||||
ty = canvasBox.Bottom + (1.5 * DefaultXAxisMargin)
|
ty = canvasBox.Bottom + (1.5 * DefaultXAxisMargin)
|
||||||
}
|
}
|
||||||
Draw.Text(r, t.Label, tx, ty, tickWithAxisStyle)
|
Draw.Text(r, t.Label, tx, ty, tickWithAxisStyle)
|
||||||
maxTextHeight = util.Math.MaxInt(maxTextHeight, tb.Height())
|
maxTextHeight = util.Math.MaxInt(maxTextHeight, int(tb.Height()))
|
||||||
break
|
break
|
||||||
case TickPositionBetweenTicks:
|
case TickPositionBetweenTicks:
|
||||||
if index > 0 {
|
if index > 0 {
|
||||||
|
@ -175,7 +175,7 @@ func (xa XAxis) Render(r Renderer, canvasBox Box, ra Range, defaults Style, tick
|
||||||
}, finalTickStyle)
|
}, finalTickStyle)
|
||||||
|
|
||||||
ftb := Text.MeasureLines(r, Text.WrapFit(r, t.Label, tx-ltx, finalTickStyle), finalTickStyle)
|
ftb := Text.MeasureLines(r, Text.WrapFit(r, t.Label, tx-ltx, finalTickStyle), finalTickStyle)
|
||||||
maxTextHeight = util.Math.MaxInt(maxTextHeight, ftb.Height())
|
maxTextHeight = util.Math.MaxInt(maxTextHeight, int(ftb.Height()))
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -184,8 +184,8 @@ func (xa XAxis) Render(r Renderer, canvasBox Box, ra Range, defaults Style, tick
|
||||||
nameStyle := xa.NameStyle.InheritFrom(defaults)
|
nameStyle := xa.NameStyle.InheritFrom(defaults)
|
||||||
if xa.NameStyle.Show && len(xa.Name) > 0 {
|
if xa.NameStyle.Show && len(xa.Name) > 0 {
|
||||||
tb := Draw.MeasureText(r, xa.Name, nameStyle)
|
tb := Draw.MeasureText(r, xa.Name, nameStyle)
|
||||||
tx := canvasBox.Right - (canvasBox.Width()>>1 + tb.Width()>>1)
|
tx := canvasBox.Right - (canvasBox.Width()>>1 + int(tb.Width())>>1)
|
||||||
ty := canvasBox.Bottom + DefaultXAxisMargin + maxTextHeight + DefaultXAxisMargin + tb.Height()
|
ty := canvasBox.Bottom + DefaultXAxisMargin + maxTextHeight + DefaultXAxisMargin + int(tb.Height())
|
||||||
Draw.Text(r, xa.Name, tx, ty, nameStyle)
|
Draw.Text(r, xa.Name, tx, ty, nameStyle)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
20
yaxis.go
20
yaxis.go
|
@ -99,17 +99,17 @@ func (ya YAxis) Measure(r Renderer, canvasBox Box, ra Range, defaults Style, tic
|
||||||
ly := canvasBox.Bottom - ra.Translate(v)
|
ly := canvasBox.Bottom - ra.Translate(v)
|
||||||
|
|
||||||
tb := r.MeasureText(t.Label)
|
tb := r.MeasureText(t.Label)
|
||||||
tbh2 := tb.Height() >> 1
|
tbh2 := int(tb.Height()) >> 1
|
||||||
finalTextX := tx
|
finalTextX := tx
|
||||||
if ya.AxisType == YAxisSecondary {
|
if ya.AxisType == YAxisSecondary {
|
||||||
finalTextX = tx - tb.Width()
|
finalTextX = tx - int(tb.Width())
|
||||||
}
|
}
|
||||||
|
|
||||||
maxTextHeight = util.Math.MaxInt(tb.Height(), maxTextHeight)
|
maxTextHeight = util.Math.MaxInt(int(tb.Height()), maxTextHeight)
|
||||||
|
|
||||||
if ya.AxisType == YAxisPrimary {
|
if ya.AxisType == YAxisPrimary {
|
||||||
minx = canvasBox.Right
|
minx = canvasBox.Right
|
||||||
maxx = util.Math.MaxInt(maxx, tx+tb.Width())
|
maxx = util.Math.MaxInt(maxx, tx+int(tb.Width()))
|
||||||
} else if ya.AxisType == YAxisSecondary {
|
} else if ya.AxisType == YAxisSecondary {
|
||||||
minx = util.Math.MinInt(minx, finalTextX)
|
minx = util.Math.MinInt(minx, finalTextX)
|
||||||
maxx = util.Math.MaxInt(maxx, tx)
|
maxx = util.Math.MaxInt(maxx, tx)
|
||||||
|
@ -160,18 +160,18 @@ func (ya YAxis) Render(r Renderer, canvasBox Box, ra Range, defaults Style, tick
|
||||||
|
|
||||||
tb := Draw.MeasureText(r, t.Label, tickStyle)
|
tb := Draw.MeasureText(r, t.Label, tickStyle)
|
||||||
|
|
||||||
if tb.Width() > maxTextWidth {
|
if int(tb.Width()) > maxTextWidth {
|
||||||
maxTextWidth = tb.Width()
|
maxTextWidth = int(tb.Width())
|
||||||
}
|
}
|
||||||
|
|
||||||
if ya.AxisType == YAxisSecondary {
|
if ya.AxisType == YAxisSecondary {
|
||||||
finalTextX = tx - tb.Width()
|
finalTextX = tx - int(tb.Width())
|
||||||
} else {
|
} else {
|
||||||
finalTextX = tx
|
finalTextX = tx
|
||||||
}
|
}
|
||||||
|
|
||||||
if tickStyle.TextRotationDegrees == 0 {
|
if tickStyle.TextRotationDegrees == 0 {
|
||||||
finalTextY = ly + tb.Height()>>1
|
finalTextY = ly + int(tb.Height())>>1
|
||||||
} else {
|
} else {
|
||||||
finalTextY = ly
|
finalTextY = ly
|
||||||
}
|
}
|
||||||
|
@ -203,9 +203,9 @@ func (ya YAxis) Render(r Renderer, canvasBox Box, ra Range, defaults Style, tick
|
||||||
|
|
||||||
var ty int
|
var ty int
|
||||||
if nameStyle.TextRotationDegrees == 0 {
|
if nameStyle.TextRotationDegrees == 0 {
|
||||||
ty = canvasBox.Top + (canvasBox.Height()>>1 - tb.Width()>>1)
|
ty = canvasBox.Top + (canvasBox.Height()>>1 - int(tb.Width())>>1)
|
||||||
} else {
|
} else {
|
||||||
ty = canvasBox.Top + (canvasBox.Height()>>1 - tb.Height()>>1)
|
ty = canvasBox.Top + (canvasBox.Height()>>1 - int(tb.Height())>>1)
|
||||||
}
|
}
|
||||||
|
|
||||||
Draw.Text(r, ya.Name, tx, ty, nameStyle)
|
Draw.Text(r, ya.Name, tx, ty, nameStyle)
|
||||||
|
|
Loading…
Reference in a new issue