need to be very specific about points vs. pixels.
This commit is contained in:
parent
8bc8b1087c
commit
80d6be9849
6 changed files with 60 additions and 25 deletions
|
@ -91,7 +91,7 @@ func GetDefaultSeriesStrokeColor(index int) color.RGBA {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// DefaultFinalLabelPadding is the padding around the final label.
|
// DefaultFinalLabelPadding is the padding around the final label.
|
||||||
DefaultFinalLabelPadding = Box{Top: 5, Left: 0, Right: 5, Bottom: 5}
|
DefaultFinalLabelPadding = Box{Top: 5, Left: 0, Right: 7, Bottom: 5}
|
||||||
// DefaultBackgroundPadding is the default canvas padding config.
|
// DefaultBackgroundPadding is the default canvas padding config.
|
||||||
DefaultBackgroundPadding = Box{Top: 5, Left: 5, Right: 5, Bottom: 5}
|
DefaultBackgroundPadding = Box{Top: 5, Left: 5, Right: 5, Bottom: 5}
|
||||||
)
|
)
|
||||||
|
|
|
@ -3,7 +3,4 @@ package drawing
|
||||||
const (
|
const (
|
||||||
// DefaultDPI is the default image DPI.
|
// DefaultDPI is the default image DPI.
|
||||||
DefaultDPI = 96.0
|
DefaultDPI = 96.0
|
||||||
|
|
||||||
// EMRatio is the ratio of something to something else.
|
|
||||||
EMRatio = 64.0 / 72.0
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -149,9 +149,8 @@ func (rgc *RasterGraphicContext) CreateStringPath(s string, x, y float64) (curso
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetStringBounds returns the approximate pixel bounds of a string.
|
// GetStringBounds returns the approximate points bounds of a string.
|
||||||
// The the left edge of the em square of the first character of s
|
// It will be required to convert points to pixels for measurement.
|
||||||
// and the baseline intersect at 0, 0 in the returned coordinates.
|
|
||||||
func (rgc *RasterGraphicContext) GetStringBounds(s string) (left, top, right, bottom float64, err error) {
|
func (rgc *RasterGraphicContext) GetStringBounds(s string) (left, top, right, bottom float64, err error) {
|
||||||
f := rgc.GetFont()
|
f := rgc.GetFont()
|
||||||
if f == nil {
|
if f == nil {
|
||||||
|
@ -192,7 +191,7 @@ func (rgc *RasterGraphicContext) GetStringBounds(s string) (left, top, right, bo
|
||||||
// recalc recalculates scale and bounds values from the font size, screen
|
// recalc recalculates scale and bounds values from the font size, screen
|
||||||
// resolution and font metrics, and invalidates the glyph cache.
|
// resolution and font metrics, and invalidates the glyph cache.
|
||||||
func (rgc *RasterGraphicContext) recalc() {
|
func (rgc *RasterGraphicContext) recalc() {
|
||||||
rgc.current.Scale = rgc.current.FontSize * float64(rgc.DPI) * EMRatio
|
rgc.current.Scale = rgc.current.FontSizePoints * float64(rgc.DPI)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetFont sets the font used to draw text.
|
// SetFont sets the font used to draw text.
|
||||||
|
@ -206,8 +205,8 @@ func (rgc *RasterGraphicContext) GetFont() *truetype.Font {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetFontSize sets the font size in points (as in ``a 12 point font'').
|
// SetFontSize sets the font size in points (as in ``a 12 point font'').
|
||||||
func (rgc *RasterGraphicContext) SetFontSize(fontSize float64) {
|
func (rgc *RasterGraphicContext) SetFontSize(fontSizePoints float64) {
|
||||||
rgc.current.FontSize = fontSize
|
rgc.current.FontSizePoints = fontSizePoints
|
||||||
rgc.recalc()
|
rgc.recalc()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,8 +25,8 @@ type ContextStack struct {
|
||||||
Cap LineCap
|
Cap LineCap
|
||||||
Join LineJoin
|
Join LineJoin
|
||||||
|
|
||||||
FontSize float64
|
FontSizePoints float64
|
||||||
Font *truetype.Font
|
Font *truetype.Font
|
||||||
|
|
||||||
Scale float64
|
Scale float64
|
||||||
|
|
||||||
|
@ -45,118 +45,145 @@ func NewStackGraphicContext() *StackGraphicContext {
|
||||||
gc.current.Cap = RoundCap
|
gc.current.Cap = RoundCap
|
||||||
gc.current.FillRule = FillRuleEvenOdd
|
gc.current.FillRule = FillRuleEvenOdd
|
||||||
gc.current.Join = RoundJoin
|
gc.current.Join = RoundJoin
|
||||||
gc.current.FontSize = 10
|
gc.current.FontSizePoints = 10
|
||||||
return gc
|
return gc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetMatrixTransform returns the matrix transform.
|
||||||
func (gc *StackGraphicContext) GetMatrixTransform() Matrix {
|
func (gc *StackGraphicContext) GetMatrixTransform() Matrix {
|
||||||
return gc.current.Tr
|
return gc.current.Tr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gc *StackGraphicContext) SetMatrixTransform(Tr Matrix) {
|
// SetMatrixTransform sets the matrix transform.
|
||||||
gc.current.Tr = Tr
|
func (gc *StackGraphicContext) SetMatrixTransform(tr Matrix) {
|
||||||
|
gc.current.Tr = tr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gc *StackGraphicContext) ComposeMatrixTransform(Tr Matrix) {
|
// ComposeMatrixTransform composes a transform into the current transform.
|
||||||
gc.current.Tr.Compose(Tr)
|
func (gc *StackGraphicContext) ComposeMatrixTransform(tr Matrix) {
|
||||||
|
gc.current.Tr.Compose(tr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Rotate rotates the matrix transform by an angle in degrees.
|
||||||
func (gc *StackGraphicContext) Rotate(angle float64) {
|
func (gc *StackGraphicContext) Rotate(angle float64) {
|
||||||
gc.current.Tr.Rotate(angle)
|
gc.current.Tr.Rotate(angle)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Translate translates a transform.
|
||||||
func (gc *StackGraphicContext) Translate(tx, ty float64) {
|
func (gc *StackGraphicContext) Translate(tx, ty float64) {
|
||||||
gc.current.Tr.Translate(tx, ty)
|
gc.current.Tr.Translate(tx, ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Scale scales a transform.
|
||||||
func (gc *StackGraphicContext) Scale(sx, sy float64) {
|
func (gc *StackGraphicContext) Scale(sx, sy float64) {
|
||||||
gc.current.Tr.Scale(sx, sy)
|
gc.current.Tr.Scale(sx, sy)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetStrokeColor sets the stroke color.
|
||||||
func (gc *StackGraphicContext) SetStrokeColor(c color.Color) {
|
func (gc *StackGraphicContext) SetStrokeColor(c color.Color) {
|
||||||
gc.current.StrokeColor = c
|
gc.current.StrokeColor = c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetFillColor sets the fill color.
|
||||||
func (gc *StackGraphicContext) SetFillColor(c color.Color) {
|
func (gc *StackGraphicContext) SetFillColor(c color.Color) {
|
||||||
gc.current.FillColor = c
|
gc.current.FillColor = c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetFillRule sets the fill rule.
|
||||||
func (gc *StackGraphicContext) SetFillRule(f FillRule) {
|
func (gc *StackGraphicContext) SetFillRule(f FillRule) {
|
||||||
gc.current.FillRule = f
|
gc.current.FillRule = f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetLineWidth sets the line width.
|
||||||
func (gc *StackGraphicContext) SetLineWidth(lineWidth float64) {
|
func (gc *StackGraphicContext) SetLineWidth(lineWidth float64) {
|
||||||
gc.current.LineWidth = lineWidth
|
gc.current.LineWidth = lineWidth
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetLineCap sets the line cap.
|
||||||
func (gc *StackGraphicContext) SetLineCap(cap LineCap) {
|
func (gc *StackGraphicContext) SetLineCap(cap LineCap) {
|
||||||
gc.current.Cap = cap
|
gc.current.Cap = cap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetLineJoin sets the line join.
|
||||||
func (gc *StackGraphicContext) SetLineJoin(join LineJoin) {
|
func (gc *StackGraphicContext) SetLineJoin(join LineJoin) {
|
||||||
gc.current.Join = join
|
gc.current.Join = join
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetLineDash sets the line dash.
|
||||||
func (gc *StackGraphicContext) SetLineDash(dash []float64, dashOffset float64) {
|
func (gc *StackGraphicContext) SetLineDash(dash []float64, dashOffset float64) {
|
||||||
gc.current.Dash = dash
|
gc.current.Dash = dash
|
||||||
gc.current.DashOffset = dashOffset
|
gc.current.DashOffset = dashOffset
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gc *StackGraphicContext) SetFontSize(fontSize float64) {
|
// SetFontSize sets the font size.
|
||||||
gc.current.FontSize = fontSize
|
func (gc *StackGraphicContext) SetFontSize(fontSizePoints float64) {
|
||||||
|
gc.current.FontSizePoints = fontSizePoints
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetFontSize gets the font size.
|
||||||
func (gc *StackGraphicContext) GetFontSize() float64 {
|
func (gc *StackGraphicContext) GetFontSize() float64 {
|
||||||
return gc.current.FontSize
|
return gc.current.FontSizePoints
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetFont sets the current font.
|
||||||
func (gc *StackGraphicContext) SetFont(f *truetype.Font) {
|
func (gc *StackGraphicContext) SetFont(f *truetype.Font) {
|
||||||
gc.current.Font = f
|
gc.current.Font = f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetFont returns the font.
|
||||||
func (gc *StackGraphicContext) GetFont() *truetype.Font {
|
func (gc *StackGraphicContext) GetFont() *truetype.Font {
|
||||||
return gc.current.Font
|
return gc.current.Font
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BeginPath starts a new path.
|
||||||
func (gc *StackGraphicContext) BeginPath() {
|
func (gc *StackGraphicContext) BeginPath() {
|
||||||
gc.current.Path.Clear()
|
gc.current.Path.Clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsEmpty returns if the path is empty.
|
||||||
func (gc *StackGraphicContext) IsEmpty() bool {
|
func (gc *StackGraphicContext) IsEmpty() bool {
|
||||||
return gc.current.Path.IsEmpty()
|
return gc.current.Path.IsEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gc *StackGraphicContext) LastPoint() (float64, float64) {
|
// LastPoint returns the last point on the path.
|
||||||
|
func (gc *StackGraphicContext) LastPoint() (x float64, y float64) {
|
||||||
return gc.current.Path.LastPoint()
|
return gc.current.Path.LastPoint()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MoveTo moves the cursor for a path.
|
||||||
func (gc *StackGraphicContext) MoveTo(x, y float64) {
|
func (gc *StackGraphicContext) MoveTo(x, y float64) {
|
||||||
gc.current.Path.MoveTo(x, y)
|
gc.current.Path.MoveTo(x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LineTo draws a line.
|
||||||
func (gc *StackGraphicContext) LineTo(x, y float64) {
|
func (gc *StackGraphicContext) LineTo(x, y float64) {
|
||||||
gc.current.Path.LineTo(x, y)
|
gc.current.Path.LineTo(x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// QuadCurveTo draws a quad curve.
|
||||||
func (gc *StackGraphicContext) QuadCurveTo(cx, cy, x, y float64) {
|
func (gc *StackGraphicContext) QuadCurveTo(cx, cy, x, y float64) {
|
||||||
gc.current.Path.QuadCurveTo(cx, cy, x, y)
|
gc.current.Path.QuadCurveTo(cx, cy, x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CubicCurveTo draws a cubic curve.
|
||||||
func (gc *StackGraphicContext) CubicCurveTo(cx1, cy1, cx2, cy2, x, y float64) {
|
func (gc *StackGraphicContext) CubicCurveTo(cx1, cy1, cx2, cy2, x, y float64) {
|
||||||
gc.current.Path.CubicCurveTo(cx1, cy1, cx2, cy2, x, y)
|
gc.current.Path.CubicCurveTo(cx1, cy1, cx2, cy2, x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ArcTo draws an arc.
|
||||||
func (gc *StackGraphicContext) ArcTo(cx, cy, rx, ry, startAngle, angle float64) {
|
func (gc *StackGraphicContext) ArcTo(cx, cy, rx, ry, startAngle, angle float64) {
|
||||||
gc.current.Path.ArcTo(cx, cy, rx, ry, startAngle, angle)
|
gc.current.Path.ArcTo(cx, cy, rx, ry, startAngle, angle)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close closes a path.
|
||||||
func (gc *StackGraphicContext) Close() {
|
func (gc *StackGraphicContext) Close() {
|
||||||
gc.current.Path.Close()
|
gc.current.Path.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Save pushes a context onto the stack.
|
||||||
func (gc *StackGraphicContext) Save() {
|
func (gc *StackGraphicContext) Save() {
|
||||||
context := new(ContextStack)
|
context := new(ContextStack)
|
||||||
context.FontSize = gc.current.FontSize
|
context.FontSizePoints = gc.current.FontSizePoints
|
||||||
context.Font = gc.current.Font
|
context.Font = gc.current.Font
|
||||||
context.LineWidth = gc.current.LineWidth
|
context.LineWidth = gc.current.LineWidth
|
||||||
context.StrokeColor = gc.current.StrokeColor
|
context.StrokeColor = gc.current.StrokeColor
|
||||||
|
@ -174,6 +201,7 @@ func (gc *StackGraphicContext) Save() {
|
||||||
gc.current = context
|
gc.current = context
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Restore restores the previous context.
|
||||||
func (gc *StackGraphicContext) Restore() {
|
func (gc *StackGraphicContext) Restore() {
|
||||||
if gc.current.Previous != nil {
|
if gc.current.Previous != nil {
|
||||||
oldContext := gc.current
|
oldContext := gc.current
|
||||||
|
|
|
@ -9,6 +9,18 @@ import (
|
||||||
"github.com/golang/freetype/truetype"
|
"github.com/golang/freetype/truetype"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// PixelsToPoints returns the points for a given number of pixels at a DPI.
|
||||||
|
func PixelsToPoints(dpi, pixels float64) (points float64) {
|
||||||
|
points = (pixels * 72.0) / dpi
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// PointsToPixels returns the pixels for a given number of points at a DPI.
|
||||||
|
func PointsToPixels(dpi, points float64) (pixels float64) {
|
||||||
|
pixels = (points * dpi) / 72.0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func abs(i int) int {
|
func abs(i int) int {
|
||||||
if i < 0 {
|
if i < 0 {
|
||||||
return -i
|
return -i
|
||||||
|
|
|
@ -5,7 +5,6 @@ import (
|
||||||
"image/color"
|
"image/color"
|
||||||
"image/png"
|
"image/png"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
|
||||||
|
|
||||||
"github.com/golang/freetype/truetype"
|
"github.com/golang/freetype/truetype"
|
||||||
"github.com/wcharczuk/go-chart/drawing"
|
"github.com/wcharczuk/go-chart/drawing"
|
||||||
|
@ -130,8 +129,8 @@ func (rr *rasterRenderer) MeasureText(body string) (width int, height int) {
|
||||||
}
|
}
|
||||||
dw := r - l
|
dw := r - l
|
||||||
dh := b - t
|
dh := b - t
|
||||||
width = int(math.Ceil(dw * (4.0 / 3.0)))
|
width = int(drawing.PointsToPixels(rr.gc.GetDPI(), dw))
|
||||||
height = int(math.Ceil(dh * (4.0 / 3.0)))
|
height = int(drawing.PointsToPixels(rr.gc.GetDPI(), dh))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue