func (g GridType) X(dataX float64) float64 {
	return g.xm*dataX + g.xb
}
X converts dataX, specified in logical data units, to the X position on the
current page.
package gofpdf
import (
	"math"
	"strconv"
)
func unused(args ...interface{}) {
}
type RGBType struct {
	R, G, B int
}
type RGBAType struct {
	R, G, B int
	Alpha   float64
}
type StateType struct {
	clrDraw, clrText, clrFill RGBType
	lineWd                    float64
	fontSize                  float64
	alpha                     float64
	blendStr                  string
	cellMargin                float64
}
func StateGet(pdf *Fpdf) (st StateType) {
	st.clrDraw.R, st.clrDraw.G, st.clrDraw.B = pdf.GetDrawColor()
	st.clrFill.R, st.clrFill.G, st.clrFill.B = pdf.GetFillColor()
	st.clrText.R, st.clrText.G, st.clrText.B = pdf.GetTextColor()
	st.lineWd = pdf.GetLineWidth()
	_, st.fontSize = pdf.GetFontSize()
	st.alpha, st.blendStr = pdf.GetAlpha()
	st.cellMargin = pdf.GetCellMargin()
	return
}
func (st StateType) Put(pdf *Fpdf) {
	pdf.SetDrawColor(st.clrDraw.R, st.clrDraw.G, st.clrDraw.B)
	pdf.SetFillColor(st.clrFill.R, st.clrFill.G, st.clrFill.B)
	pdf.SetTextColor(st.clrText.R, st.clrText.G, st.clrText.B)
	pdf.SetLineWidth(st.lineWd)
	pdf.SetFontUnitSize(st.fontSize)
	pdf.SetAlpha(st.alpha, st.blendStr)
	pdf.SetCellMargin(st.cellMargin)
}
type TickFormatFncType func(val float64, precision int) string
func defaultFormatter(val float64, precision int) string {
	return strconv.FormatFloat(val, 'f', precision, 64)
}
type GridType struct {
	x, y, w, h float64
	xm, xb, ym, yb float64
	xTicks, yTicks []float64
	XLabelIn, YLabelIn bool
	XLabelRotate bool
	XTickStr, YTickStr TickFormatFncType
	XDiv, YDiv int
	xPrecision, yPrecision int
	ClrText, ClrMain, ClrSub RGBAType
	WdMain, WdSub float64
	TextSize float64
}
func linear(x1, y1, x2, y2 float64) (slope, intercept float64) {
	if x2 != x1 {
		slope = (y2 - y1) / (x2 - x1)
		intercept = y2 - x2*slope
	}
	return
}
func linearTickmark(tm []float64, lo, hi float64) (slope, intercept float64) {
	ln := len(tm)
	if ln > 0 {
		slope, intercept = linear(tm[0], lo, tm[ln-1], hi)
	}
	return
}
func NewGrid(x, y, w, h float64) (grid GridType) {
	grid.x = x
	grid.y = y
	grid.w = w
	grid.h = h
	grid.TextSize = 7  
	grid.TickmarksExtentX(0, 1, 1)
	grid.TickmarksExtentY(0, 1, 1)
	grid.XLabelIn = false
	grid.YLabelIn = false
	grid.XLabelRotate = false
	grid.XDiv = 10
	grid.YDiv = 10
	grid.ClrText = RGBAType{R: 0, G: 0, B: 0, Alpha: 1}
	grid.ClrMain = RGBAType{R: 128, G: 160, B: 128, Alpha: 1}
	grid.ClrSub = RGBAType{R: 192, G: 224, B: 192, Alpha: 1}
	grid.WdMain = 0.1
	grid.WdSub = 0.1
	grid.YTickStr = defaultFormatter
	grid.XTickStr = defaultFormatter
	return
}
func (g GridType) WdAbs(dataWd float64) float64 {
	return math.Abs(g.xm * dataWd)
}
func (g GridType) Wd(dataWd float64) float64 {
	return g.xm * dataWd
}
func (g GridType) XY(dataX, dataY float64) (x, y float64) {
	return g.xm*dataX + g.xb, g.ym*dataY + g.yb
}
func (g GridType) Pos(xRel, yRel float64) (x, y float64) {
	x = g.w*xRel + g.x
	y = g.h*(1-yRel) + g.y
	return
}