1
// pmap percentage maps
13
"github.com/ajstarks/svgo"
16
// Pmap defines a porportional map
18
Top int `xml:"top,attr"`
19
Left int `xml:"left,attr"`
20
Title string `xml:"title,attr"`
21
Pdata []Pdata `xml:"pdata"`
24
// Pdata defines data with a portpotional map
26
Legend string `xml:"legend,attr"`
27
Stagger string `xml:"stagger,attr"`
28
Alternate string `xml:"alternate,attr"`
29
Item []Item `xml:"item"`
32
// Item defines an item with porpotional map data
34
Name string `xml:",chardata"`
35
Value float64 `xml:"value,attr"`
39
width, height, fontsize, fontscale, round, gutter, pred, pgreen, pblue, oflen int
40
bgcolor, olcolor, colorspec, title string
41
showpercent, showdata, alternate, showtitle, stagger, showlegend, showtotal bool
45
canvas = svg.New(os.Stdout)
49
globalfmt = "stroke-width:1;font-family:Calibri,sans-serif;text-anchor:middle;font-size:%dpt"
50
legendstyle = "text-anchor:start;font-size:150%"
54
func dopmap(location string) {
57
if len(location) > 0 {
58
f, err = os.Open(location)
66
fmt.Fprintf(os.Stderr, "%v\n", err)
70
func readpmap(r io.Reader) {
72
if err := xml.NewDecoder(r).Decode(&pm); err == nil {
75
fmt.Fprintf(os.Stderr, "Unable to parse pmap (%v)\n", err)
79
func drawpmap(m Pmap) {
87
topmargin = fs * fontscale
98
for _, p := range m.Pdata {
100
y += fs*fontscale + (gutter + fs*2)
104
func pmap(x, y, fs int, m Pdata) {
105
var tfill, vfmt, oc string
109
slen := fs + (fs / 2)
113
for _, v := range m.Item {
117
if len(olcolor) > 0 {
122
loffset := (fs * fontscale) + fs
123
gline := fmt.Sprintf(linefmt, "gray")
124
wline := fmt.Sprintf(linefmt, oc)
125
if len(m.Legend) > 0 && showlegend {
127
canvas.Text(x, y-fs, fmt.Sprintf("%s (total: "+floatfmt(sum)+")", m.Legend, sum), legendstyle)
129
canvas.Text(x, y-fs, m.Legend, legendstyle)
132
for i, p := range m.Item {
139
pw := int(pct * float64(fw))
148
canvas.Roundrect(x, y, pw, h, round, round, canvas.RGBA(pred, pgreen, pblue, pct))
150
canvas.Rect(x, y, pw, h, canvas.RGBA(pred, pgreen, pblue, pct))
153
dy := yh + fs + (fs / 2)
154
if pct <= ofpct || len(k) > oflen { // overflow label
158
canvas.Line(xw, y, xw, dy+(fs/2), gline)
162
canvas.Line(xw, y+h, xw, dy-(fs*3), gline)
175
canvas.Text(xw, yh, k, tfill)
176
dpfmt := tfill + ";font-size:75%"
179
case showpercent && !showdata:
180
canvas.Text(xw, dy, fmt.Sprintf("%.1f%%", pct*100), dpfmt)
181
case showpercent && showdata:
182
canvas.Text(xw, dy, fmt.Sprintf(vfmt+", %.1f%%", v, pct*100), dpfmt)
183
case showdata && !showpercent:
184
canvas.Text(xw, dy, fmt.Sprintf(vfmt, v), dpfmt)
188
canvas.Line(x, y, x, y+h, wline)
193
func floatfmt(v float64) string {
195
if v-float64(int(v)) == 0.0 {
201
func dotitle(s string) {
203
canvas.Text(leftmargin, height-offset, s, "text-anchor:start;font-size:250%")
207
flag.IntVar(&width, "w", 1024, "width")
208
flag.IntVar(&height, "h", 768, "height")
209
flag.IntVar(&fontsize, "f", 12, "font size (pt)")
210
flag.IntVar(&fontscale, "s", 5, "font scaling factor")
211
flag.IntVar(&round, "r", 0, "rounded corner size")
212
flag.IntVar(&gutter, "g", 100, "gutter")
213
flag.IntVar(&oflen, "ol", 20, "overflow length")
214
flag.StringVar(&bgcolor, "bg", "white", "background color")
215
flag.StringVar(&olcolor, "oc", "", "outline color")
216
flag.StringVar(&colorspec, "c", "0,0,0", "color (r,g,b)")
217
flag.StringVar(&title, "t", "Proportions", "title")
218
flag.BoolVar(&showpercent, "p", false, "show percentage")
219
flag.BoolVar(&showdata, "d", false, "show data")
220
flag.BoolVar(&alternate, "a", false, "alternate overflow labels")
221
flag.BoolVar(&stagger, "stagger", false, "stagger labels")
222
flag.BoolVar(&showlegend, "showlegend", true, "show the legend")
223
flag.BoolVar(&showtitle, "showtitle", false, "show the title")
224
flag.BoolVar(&showtotal, "showtotal", false, "show totals in the legend")
225
flag.Float64Var(&ofpct, "op", 0.05, "overflow percentage")
227
fmt.Sscanf(colorspec, "%d,%d,%d", &pred, &pgreen, &pblue)
231
canvas.Start(width, height)
232
canvas.Rect(0, 0, width, height, "fill:"+bgcolor)
233
canvas.Gstyle(fmt.Sprintf(globalfmt, fontsize))
235
if len(flag.Args()) == 0 {
238
for _, f := range flag.Args() {