// drawPieChart provides a function to draw the c:plotArea element for pie
// chart by given format sets.
972535
func (f *File) drawPieChart(formatSet *formatChart) *cPlotArea {
	return &cPlotArea{
		PieChart: &cCharts{
			VaryColors: &attrValBool{
				Val: true,
			},
			Ser: f.drawChartSeries(formatSet),
		},
	}
}
442389
func (b *Button) Draw(p *Painter) {
	style := "button"
	if b.IsFocused() {
		style += ".focused"
	}
	p.WithStyle(style, func(p *Painter) {
		lines := strings.Split(b.text, "\n")
		for i, line := range lines {
			p.FillRect(0, i, b.Size().X, 1)
			p.DrawText(0, i, line)
		}
	})
}
840560
func (f *File) drawBaseChart(formatSet *formatChart) *cPlotArea {
	c := cCharts{
		BarDir: &attrValString{
			Val: "col",
		},
		Grouping: &attrValString{
			Val: "clustered",
		},
		VaryColors: &attrValBool{
			Val: true,
		},
		Ser:   f.drawChartSeries(formatSet),
		DLbls: f.drawChartDLbls(formatSet),
		AxID: []*attrValInt{
			{Val: 754001152},
			{Val: 753999904},
		},
	}
	var ok bool
	c.BarDir.Val, ok = plotAreaChartBarDir[formatSet.Type]
	if !ok {
		c.BarDir = nil
	}
	c.Grouping.Val = plotAreaChartGrouping[formatSet.Type]
	if formatSet.Type == "colStacked" || formatSet.Type == "barStacked" || formatSet.Type == "barPercentStacked" || formatSet.Type == "colPercentStacked" || formatSet.Type == "areaPercentStacked" {
		c.Overlap = &attrValInt{Val: 100}
	}
	catAx := f.drawPlotAreaCatAx(formatSet)
	valAx := f.drawPlotAreaValAx(formatSet)
	charts := map[string]*cPlotArea{
		"area": {
			AreaChart: &c,
			CatAx:     catAx,
			ValAx:     valAx,
		},
		"areaStacked": {
			AreaChart: &c,
			CatAx:     catAx,
			ValAx:     valAx,
		},
		"areaPercentStacked": {
			AreaChart: &c,
			CatAx:     catAx,
			ValAx:     valAx,
		},
		"area3D": {
			Area3DChart: &c,
			CatAx:       catAx,
			ValAx:       valAx,
		},
		"area3DStacked": {
			Area3DChart: &c,
			CatAx:       catAx,
			ValAx:       valAx,
		},
		"area3DPercentStacked": {
			Area3DChart: &c,
			CatAx:       catAx,
			ValAx:       valAx,
		},
		"bar": {
			BarChart: &c,
			CatAx:    catAx,
			ValAx:    valAx,
		},
		"barStacked": {
			BarChart: &c,
			CatAx:    catAx,
			ValAx:    valAx,
		},
		"barPercentStacked": {
			BarChart: &c,
			CatAx:    catAx,
			ValAx:    valAx,
		},
		"bar3DClustered": {
			Bar3DChart: &c,
			CatAx:      catAx,
			ValAx:      valAx,
		},
		"bar3DStacked": {
			Bar3DChart: &c,
			CatAx:      catAx,
			ValAx:      valAx,
		},
		"bar3DPercentStacked": {
			Bar3DChart: &c,
			CatAx:      catAx,
			ValAx:      valAx,
		},
		"col": {
			BarChart: &c,
			CatAx:    catAx,
			ValAx:    valAx,
		},
		"colStacked": {
			BarChart: &c,
			CatAx:    catAx,
			ValAx:    valAx,
		},
		"colPercentStacked": {
			BarChart: &c,
			CatAx:    catAx,
			ValAx:    valAx,
		},
		"col3DClustered": {
			Bar3DChart: &c,
			CatAx:      catAx,
			ValAx:      valAx,
		},
		"col3D": {
			Bar3DChart: &c,
			CatAx:      catAx,
			ValAx:      valAx,
		},
		"col3DStacked": {
			Bar3DChart: &c,
			CatAx:      catAx,
			ValAx:      valAx,
		},
		"col3DPercentStacked": {
			Bar3DChart: &c,
			CatAx:      catAx,
			ValAx:      valAx,
		},
	}
	return charts[formatSet.Type]
}
1259545
func (t *Text) Draw() {
	v := t.view
	if v == nil {
		return
	}

	width, height := v.Size()
	if width == 0 || height == 0 {
		return
	}

	t.clear()

	// Note that we might wind up with a negative X if the width
	// is larger than the length.  That's OK, and correct even.
	// The view will clip it properly in that case.

	// We align to the left & top by default.
	y := t.calcY(height)
	r := rune(0)
	w := 0
	x := 0
	var styl tcell.Style
	var comb []rune
	line := 0
	newline := true
	for i, l := range t.text {

		if newline {
			x = t.calcX(width, line)
			newline = false
		}
		if l == '\n' {
			if w != 0 {
				v.SetContent(x, y, r, comb, styl)
			}
			newline = true
			w = 0
			comb = nil
			line++
			y++
			continue
		}
		if t.widths[i] == 0 {
			comb = append(comb, l)
			continue
		}
		if w != 0 {
			v.SetContent(x, y, r, comb, styl)
			x += w
		}
		r = l
		w = t.widths[i]
		styl = t.styles[i]
		comb = nil
	}
	if w != 0 {
		v.SetContent(x, y, r, comb, styl)
	}
}
963326
func (s *SpacesService) ListCharts(spaceID uint) ([]SpaceChart, *http.Response, error) {
	u := fmt.Sprintf("spaces/%d/charts", spaceID)
	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	charts := new([]SpaceChart)
	resp, err := s.client.Do(req, charts)
	if err != nil {
		return nil, resp, err
	}

	return *charts, resp, err
}
564455
func (s *SpacesService) DeleteChart(spaceID, chartID uint) (*http.Response, error) {
	u := fmt.Sprintf("spaces/%d/charts/%d", spaceID, chartID)
	req, err := s.client.NewRequest("DELETE", u, nil)
	if err != nil {
		return nil, err
	}

	return s.client.Do(req, nil)
}
1353792
func (c *Menu) Draw() {
	useFg, useBg := c.fg, c.bg
	if c.active {
		useFg, useBg = c.activeFg, c.activeBg
	}
	// First blank out the area we'll be putting the menu
	FillWithChar(' ', c.x, c.y, c.x+c.width, c.y+c.height, useFg, useBg)
	// Now draw the border
	optionStartX := c.x
	optionStartY := c.y
	optionWidth := c.width
	_ = optionWidth
	optionHeight := c.height
	if optionHeight == -1 {
		optionHeight = len(c.options)
	}
	if c.bordered {
		pct := float64(c.GetSelectedIndex()) / float64(len(c.options))
		if c.title == "" {
			if len(c.options) > c.height-2 {
				DrawBorderWithPct(c.x, c.y, c.x+c.width, c.y+c.height, pct, useFg, useBg)
			} else {
				DrawBorder(c.x, c.y, c.x+c.width, c.y+c.height, useFg, useBg)
			}
		} else {
			if len(c.options) > c.height-2 {
				DrawBorderWithTitleAndPct(c.x, c.y, c.x+c.width, c.y+c.height, " "+c.title+" ", pct, useFg, useBg)
			} else {
				DrawBorderWithTitle(c.x, c.y, c.x+c.width, c.y+c.height, " "+c.title+" ", useFg, useBg)
			}
		}
		optionStartX = c.x + 1
		optionStartY = c.y + 1
		optionWidth = c.width - 1
		optionHeight -= 2
	}

	if len(c.options) > 0 {
		firstDispIdx := 0
		lastDispIdx := len(c.options) - 1
		if len(c.options) > c.height-2 {
			lastDispIdx = c.height - 2
		}
		if c.GetSelectedIndex() > c.height-2 {
			firstDispIdx = c.GetSelectedIndex() - (c.height - 2)
			lastDispIdx = c.GetSelectedIndex()
		}
		for idx := firstDispIdx; idx < lastDispIdx; idx++ {
			currOpt := &c.options[idx]
			outTxt := currOpt.GetText()
			if currOpt.IsDisabled() {
				DrawStringAtPoint(outTxt, optionStartX, optionStartY, c.disabledFg, c.disabledBg)
			} else if c.GetSelectedOption() == currOpt {
				DrawStringAtPoint(outTxt, optionStartX, optionStartY, c.selectedFg, c.selectedBg)
			} else {
				DrawStringAtPoint(outTxt, optionStartX, optionStartY, useFg, useBg)
			}
			optionStartY++
		}
	}
	/*
			// Print the options
			bldHeight := (optionHeight / 2)
			startIdx := c.GetSelectedIndex()
			endIdx := c.GetSelectedIndex()
			for bldHeight > 0 && startIdx >= 1 {
				startIdx--
				bldHeight--
			}
			bldHeight += (optionHeight / 2)
			for bldHeight > 0 && endIdx < len(c.options) {
				endIdx++
				bldHeight--
			}

			for idx := startIdx; idx < endIdx; idx++ {
				if c.GetSelectedIndex()-idx >= optionHeight-1 {
					// Skip this one
					continue
				}
				currOpt := &c.options[idx]
				outTxt := currOpt.GetText()
				if len(outTxt) >= c.width {
					outTxt = outTxt[:c.width]
				}
				if currOpt.IsDisabled() {
					DrawStringAtPoint(outTxt, optionStartX, optionStartY, c.disabledFg, c.disabledBg)
				} else if c.GetSelectedOption() == currOpt {
					DrawStringAtPoint(outTxt, optionStartX, optionStartY, c.selectedFg, c.selectedBg)
				} else {
					DrawStringAtPoint(outTxt, optionStartX, optionStartY, useFg, useBg)
				}
				optionStartY++
				if optionStartY > c.y+optionHeight-1 {
					break
				}
			}
		}
	*/
}
856311
func (c *Canvas) Draw(t pixel.Target, matrix pixel.Matrix) {
	c.sprite.Draw(t, matrix)
}
1352672
func (f *File) addDrawingChart(sheet, drawingXML, cell string, width, height, rID int, formatSet *formatPicture) error {
	col, row, err := CellNameToCoordinates(cell)
	if err != nil {
		return err
	}
	colIdx := col - 1
	rowIdx := row - 1

	width = int(float64(width) * formatSet.XScale)
	height = int(float64(height) * formatSet.YScale)
	colStart, rowStart, _, _, colEnd, rowEnd, x2, y2 :=
		f.positionObjectPixels(sheet, colIdx, rowIdx, formatSet.OffsetX, formatSet.OffsetY, width, height)
	content, cNvPrID := f.drawingParser(drawingXML)
	twoCellAnchor := xdrCellAnchor{}
	twoCellAnchor.EditAs = formatSet.Positioning
	from := xlsxFrom{}
	from.Col = colStart
	from.ColOff = formatSet.OffsetX * EMU
	from.Row = rowStart
	from.RowOff = formatSet.OffsetY * EMU
	to := xlsxTo{}
	to.Col = colEnd
	to.ColOff = x2 * EMU
	to.Row = rowEnd
	to.RowOff = y2 * EMU
	twoCellAnchor.From = &from
	twoCellAnchor.To = &to

	graphicFrame := xlsxGraphicFrame{
		NvGraphicFramePr: xlsxNvGraphicFramePr{
			CNvPr: &xlsxCNvPr{
				ID:   f.countCharts() + f.countMedia() + 1,
				Name: "Chart " + strconv.Itoa(cNvPrID),
			},
		},
		Graphic: &xlsxGraphic{
			GraphicData: &xlsxGraphicData{
				URI: NameSpaceDrawingMLChart,
				Chart: &xlsxChart{
					C:   NameSpaceDrawingMLChart,
					R:   SourceRelationship,
					RID: "rId" + strconv.Itoa(rID),
				},
			},
		},
	}
	graphic, _ := xml.Marshal(graphicFrame)
	twoCellAnchor.GraphicFrame = string(graphic)
	twoCellAnchor.ClientData = &xdrClientData{
		FLocksWithSheet:  formatSet.FLocksWithSheet,
		FPrintsWithSheet: formatSet.FPrintsWithSheet,
	}
	content.TwoCellAnchor = append(content.TwoCellAnchor, &twoCellAnchor)
	f.Drawings[drawingXML] = content
	return err
}
845425
func (c *HistChart) Plot(g Graphics) {
	layout := layout(g, c.Title, c.XRange.Label, c.YRange.Label,
		c.XRange.TicSetting.Hide || c.XRange.TicSetting.HideLabels,
		c.YRange.TicSetting.Hide || c.YRange.TicSetting.HideLabels,
		&c.Key)
	fw, fh, _ := g.FontMetrics(elementStyle(c.Options, MajorAxisElement).Font)

	width, height := layout.Width, layout.Height
	topm, leftm := layout.Top, layout.Left
	numxtics, numytics := layout.NumXtics, layout.NumYtics

	// Outside bound ranges for histograms are nicer
	leftm += int(2 * fw)
	width -= int(2 * fw)
	height -= int(fh)

	c.XRange.Setup(numxtics, numxtics+4, width, leftm, false)

	// TODO(vodo) a) BinWidth might be input, alignment to tics should be nice, binCnt, ...
	if c.BinWidth == 0 {
		c.findBinWidth()
	}

	xmin, _ := c.XRange.Min, c.XRange.Max
	binStart := c.BinWidth * math.Ceil(xmin/c.BinWidth)
	c.FirstBin = binStart + c.BinWidth/2
	binCnt := int(math.Floor(c.XRange.Max-binStart) / c.BinWidth)
	// DebugLogger.Printf("Using %d bins from %.3f to %.3f width %.3f  (xrange: %.3f--%.3f)\n", binCnt, binStart, binStart+c.BinWidth*float64(binCnt), c.BinWidth, xmin, xmax)
	counts, max := c.binify(binStart, c.BinWidth, binCnt)

	// Calculate smoothed density plots and re-max y.
	var smoothed [][]EPoint
	if !c.Stacked && c.Kernel != nil {
		smoothed = make([][]EPoint, len(c.Data))
		for d := range c.Data {
			p, m := c.smoothed(d, binCnt)
			smoothed[d] = p
			if m > max {
				max = m
			}
		}
	}

	// Fix lower end of y axis
	c.YRange.DataMin = 0
	c.YRange.MinMode.Fixed = true
	c.YRange.MinMode.Value = 0
	c.YRange.autoscale(float64(max))
	c.YRange.Setup(numytics, numytics+2, height, topm, true)

	g.Begin()

	if c.Title != "" {
		drawTitle(g, c.Title, elementStyle(c.Options, TitleElement))
	}

	g.XAxis(c.XRange, topm+height+fh, topm, c.Options)
	g.YAxis(c.YRange, leftm-int(2*fw), leftm+width, c.Options)

	xf := c.XRange.Data2Screen
	yf := c.YRange.Data2Screen

	numSets := len(c.Data)
	n := float64(numSets)
	gf, sf := c.widthFactor()

	ww := c.BinWidth * (1 - gf) // w'
	var w, s float64
	if !c.Stacked && c.Shifted {
		w = ww / (n + (n-1)*sf)
		s = w * sf
	} else {
		w = ww
		s = -ww
	}

	// DebugLogger.Printf("gf=%.3f, sf=%.3f, bw=%.3f   ===>  ww=%.2f,   w=%.2f,  s=%.2f\n", gf, sf, c.BinWidth, ww, w, s)

	if c.Shifted || c.Stacked {
		for d := numSets - 1; d >= 0; d-- {
			bars := make([]Barinfo, 0, binCnt)
			ws := 0
			for b := 0; b < binCnt; b++ {
				if counts[d][b] == 0 {
					continue
				}
				xb := binStart + (float64(b)+0.5)*c.BinWidth
				x := xb - ww/2 + float64(d)*(s+w)
				xs := xf(x)
				xss := xf(x + w)
				ws = xss - xs
				thebar := Barinfo{x: xs, w: xss - xs}

				off := 0.0
				if c.Stacked {
					for dd := d - 1; dd >= 0; dd-- {
						off += counts[dd][b]
					}
				}
				a, aa := yf(float64(off+counts[d][b])), yf(float64(off))
				thebar.y, thebar.h = a, iabs(a-aa)
				bars = append(bars, thebar)
			}
			g.Bars(bars, c.Data[d].Style)

			if !c.Stacked && sf < 0 && gf != 0 && fh > 1 {
				// Whitelining
				lw := 1
				if ws > 25 {
					lw = 2
				}
				white := Style{LineColor: color.NRGBA{0xff, 0xff, 0xff, 0xff}, LineWidth: lw, LineStyle: SolidLine}
				for _, b := range bars {
					g.Line(b.x, b.y-1, b.x+b.w+1, b.y-1, white)
					g.Line(b.x+b.w+1, b.y-1, b.x+b.w+1, b.y+b.h, white)
				}
			}
		}

	} else {
		bars := make([]Barinfo, 1)
		order := make([]int, numSets)
		for b := 0; b < binCnt; b++ {
			// shame on me...
			for d := 0; d < numSets; d++ {
				order[d] = d
			}
			for d := 0; d < numSets; d++ {
				for p := 0; p < numSets-1; p++ {
					if counts[order[p]][b] < counts[order[p+1]][b] {
						order[p], order[p+1] = order[p+1], order[p]
					}
				}
			}
			for d := 0; d < numSets; d++ {
				if counts[order[d]][b] == 0 {
					continue
				}
				xb := binStart + (float64(b)+0.5)*c.BinWidth
				x := xb - ww/2 + float64(d)*(s+w)
				xs := xf(x)
				xss := xf(x + w)
				thebar := Barinfo{x: xs, w: xss - xs}

				a, aa := yf(float64(counts[order[d]][b])), yf(0)
				thebar.y, thebar.h = a, iabs(a-aa)
				bars[0] = thebar
				g.Bars(bars, c.Data[order[d]].Style)
			}
		}
	}

	if !c.Stacked && c.Kernel != nil {
		for d := numSets - 1; d >= 0; d-- {
			style := Style{Symbol: /*c.Data[d].Style.Symbol*/ 'X', LineColor: c.Data[d].Style.LineColor,
				LineWidth: 1, LineStyle: SolidLine}
			for j := range smoothed[d] {
				// now YRange is set up: transform to screen coordinates
				smoothed[d][j].Y = float64(c.YRange.Data2Screen(smoothed[d][j].Y))
			}
			g.Scatter(smoothed[d], PlotStyleLines, style)
		}
	}

	if !c.Key.Hide {
		g.Key(layout.KeyX, layout.KeyY, c.Key, c.Options)
	}
	g.End()
}
729956
func (a *AIP1640Driver) DrawPixel(x, y byte, enabled bool) {
	if x >= 8 || y >= 8 {
		return
	}
	y = 7 - y
	if enabled {
		a.buffer[y] |= 1 << x
	} else {
		a.buffer[y] &^= 1 << x
	}
}
331327
func (c *Context) DrawArrays(mode, first, count int) {
	c.Call("drawArrays", mode, first, count)
}
1329356
func (f *File) drawChartSeriesVal(v formatChartSeries, formatSet *formatChart) *cVal {
	val := &cVal{
		NumRef: &cNumRef{
			F: v.Values,
		},
	}
	chartSeriesVal := map[string]*cVal{Area: val, AreaStacked: val, AreaPercentStacked: val, Area3D: val, Area3DStacked: val, Area3DPercentStacked: val, Bar: val, BarStacked: val, BarPercentStacked: val, Bar3DClustered: val, Bar3DStacked: val, Bar3DPercentStacked: val, Col: val, ColStacked: val, ColPercentStacked: val, Col3DClustered: val, Col3D: val, Col3DStacked: val, Col3DPercentStacked: val, Doughnut: val, Line: val, Pie: val, Pie3D: val, Radar: val, Scatter: nil}
	return chartSeriesVal[formatSet.Type]
}
829383
func DrawList(r *Box, items []string, selected int) {
	for i, s := range items {
		color := LISTTEXT
		if i == selected {
			color = LISTFOCUS
		}
		Write(r.frame.X, r.frame.Y+i, s, color, BOXBG)
	}
}
535180
func (b *Box) Draw(p *Painter) {
	style := "box"
	if b.IsFocused() {
		style += ".focused"
	}

	p.WithStyle(style, func(p *Painter) {

		sz := b.Size()

		if b.border {
			p.WithStyle(style+".border", func(p *Painter) {
				p.DrawRect(0, 0, sz.X, sz.Y)
			})
			p.WithStyle(style, func(p *Painter) {
				p.WithMask(image.Rect(0, 0, sz.X-1, 1), func(p *Painter) {
					p.DrawText(1, 0, b.title)
				})
			})
			p.FillRect(1, 1, sz.X-2, sz.Y-2)
			p.Translate(1, 1)
			defer p.Restore()
		} else {
			p.FillRect(0, 0, sz.X, sz.Y)
		}

		var off image.Point
		for _, child := range b.children {
			switch b.Alignment() {
			case Horizontal:
				p.Translate(off.X, 0)
			case Vertical:
				p.Translate(0, off.Y)
			}

			p.WithMask(image.Rectangle{
				Min: image.ZP,
				Max: child.Size(),
			}, func(p *Painter) {
				child.Draw(p)
			})

			p.Restore()

			off = off.Add(child.Size())
		}
	})
}
421499
func (f *File) drawChartSeriesYVal(v formatChartSeries, formatSet *formatChart) *cVal {
	val := &cVal{
		NumRef: &cNumRef{
			F: v.Values,
		},
	}
	chartSeriesYVal := map[string]*cVal{Area: nil, AreaStacked: nil, AreaPercentStacked: nil, Area3D: nil, Area3DStacked: nil, Area3DPercentStacked: nil, Bar: nil, BarStacked: nil, BarPercentStacked: nil, Bar3DClustered: nil, Bar3DStacked: nil, Bar3DPercentStacked: nil, Col: nil, ColStacked: nil, ColPercentStacked: nil, Col3DClustered: nil, Col3D: nil, Col3DStacked: nil, Col3DPercentStacked: nil, Doughnut: nil, Line: nil, Pie: nil, Pie3D: nil, Radar: nil, Scatter: val}
	return chartSeriesYVal[formatSet.Type]
}
64346
func (c *BarChart) Plot(g Graphics) {
	// layout
	layout := layout(g, c.Title, c.XRange.Label, c.YRange.Label,
		c.XRange.TicSetting.Hide || c.XRange.TicSetting.HideLabels,
		c.YRange.TicSetting.Hide || c.YRange.TicSetting.HideLabels,
		&c.Key)
	width, height := layout.Width, layout.Height
	topm, leftm := layout.Top, layout.Left
	numxtics, numytics := layout.NumXtics, layout.NumYtics
	font := elementStyle(c.Options, MajorAxisElement).Font
	fw, fh, _ := g.FontMetrics(font)

	// Outside bound ranges for bar plots are nicer
	leftm += int(2 * fw)
	width -= int(2 * fw)
	height -= fh

	c.rescaleStackedY()
	c.XRange.Setup(numxtics, numxtics+3, width, leftm, false)
	c.YRange.Setup(numytics, numytics+2, height, topm, true)

	// Start of drawing
	g.Begin()
	if c.Title != "" {
		drawTitle(g, c.Title, elementStyle(c.Options, TitleElement))
	}

	g.XAxis(c.XRange, topm+height+fh, topm, c.Options)
	g.YAxis(c.YRange, leftm-int(2*fw), leftm+width, c.Options)

	xf := c.XRange.Data2Screen
	yf := c.YRange.Data2Screen
	var sy0 int
	switch {
	case c.YRange.Min >= 0:
		sy0 = yf(c.YRange.Min)
	case c.YRange.Min < 0 && c.YRange.Max > 0:
		sy0 = yf(0)
	case c.YRange.Max <= 0:
		sy0 = yf(c.YRange.Max)
	default:
		fmt.Printf("No f.... idea how this can happen. You've been fiddeling?")
	}

	// TODO: gap between bars.
	var sbw, fbw int // ScreenBarWidth

	var low, high map[float64]float64
	if c.Stacked {
		high = make(map[float64]float64, 50)
		low = make(map[float64]float64, 50)
	}
	for dn, data := range c.Data {
		mindeltax := c.minimumSampleSep(dn)
		// DebugLogger.Printf("Minimum x-distance for set %d: %.3f\n", dn, mindeltax)
		if c.Stacked {
			sbw = (xf(2*mindeltax) - xf(0)) / 4
			fbw = sbw
		} else {
			//        V
			//   xxx === 000 ... xxx    sbw = 3
			//   xx == 00 ## .. xx ==   fbw = 11
			sbw = (xf(mindeltax)-xf(0))/(len(c.Data)+1) - 1
			fbw = len(c.Data)*sbw + len(c.Data) - 1
		}
		// DebugLogger.Printf("sbw = %d ,  fbw = %d\n", sbw, fbw)

		bars := make([]Barinfo, 0, len(data.Samples))
		if c.Stacked {
			for _, p := range data.Samples {
				if _, ok := high[p.X]; !ok {
					high[p.X], low[p.X] = 0, 0
				}
			}
		}
		for _, p := range data.Samples {
			x, y := p.X, p.Y
			if y == 0 {
				continue
			}

			sx := xf(x) - fbw/2
			if !c.Stacked {
				sx += dn * (sbw + 1)
			}

			var sy, sh int
			if c.Stacked {
				if y > 0 {
					top := y + high[x]
					sy = yf(top)
					sh = yf(high[x]) - sy
					high[x] = top

				} else {
					bot := low[x] + y
					sy = yf(low[x])
					sh = yf(bot) - sy
					low[x] = bot
				}
			} else {
				if y > 0 {
					sy = yf(y)
					sh = sy0 - sy
				} else {
					sy = sy0
					sh = yf(y) - sy0
				}
			}
			bar := Barinfo{x: sx, y: sy, w: sbw, h: sh}
			c.addLabel(&bar, y)
			bars = append(bars, bar)

		}
		g.Bars(bars, data.Style)

	}

	if !c.Key.Hide {
		g.Key(layout.KeyX, layout.KeyY, c.Key, c.Options)
	}

	g.End()

	/******** old code **************

	// find bar width
	lbw, ubw := c.extremBarWidth()
	var barWidth float64
	if c.SameBarWidth {
		barWidth = lbw
	} else {
		barWidth = ubw
	}

	// set up range and extend if bar would not fit
	c.XRange.Setup(numxtics, numxtics+4, width, leftm, false)
	c.YRange.Setup(numytics, numytics+2, height, topm, true)
	if c.XRange.DataMin-barWidth/2 < c.XRange.Min {
		c.XRange.DataMin -= barWidth / 2
	}
	if c.XRange.DataMax+barWidth > c.XRange.Max {
		c.XRange.DataMax += barWidth / 2
	}
	c.XRange.Setup(numxtics, numxtics+4, width, leftm, false)

	// Start of drawing
	g.Begin()
	if c.Title != "" {
		g.Title(c.Title)
	}

	g.XAxis(c.XRange, topm+height, topm)
	g.YAxis(c.YRange, leftm, leftm+width)

	xf := c.XRange.Data2Screen
	yf := c.YRange.Data2Screen
	sy0 := yf(c.YRange.Min)

	barWidth = lbw
	for i, data := range c.Data {
		if !c.SameBarWidth {
			barWidth = c.barWidth(i)
		}
		sbw := imax(1, xf(2*barWidth)-xf(barWidth)-1) // screen bar width TODO
		bars := make([]Barinfo, len(data.Samples))

		for i, point := range data.Samples {
			x, y := point.X, point.Y
			sx := xf(x-barWidth/2) + 1
			// sw := xf(x+barWidth/2) - sx
			sy := yf(y)
			sh := sy0 - sy
			bars[i].x, bars[i].y = sx, sy
			bars[i].w, bars[i].h = sbw, sh
		}
		g.Bars(bars, data.Style)
	}

	if !c.Key.Hide {
		g.Key(layout.KeyX, layout.KeyY, c.Key)
	}

	g.End()


	 **********************************************************/
}