def _renderBackground(self, cx): """Renders the background area of the chart""" if self.options.background.hide: return cx.save() if self.options.background.baseColor: cx.set_source_rgb(*hex2rgb(self.options.background.baseColor)) cx.paint() if self.options.background.chartColor: cx.set_source_rgb(*hex2rgb(self.options.background.chartColor)) surface_width, surface_height = self.getSurfaceSize() cx.rectangle(self.options.padding.left, self.options.padding.top, surface_width - (self.options.padding.left + self.options.padding.right), surface_height - (self.options.padding.top + self.options.padding.bottom)) cx.fill() if self.options.background.lineColor: cx.set_source_rgb(*hex2rgb(self.options.background.lineColor)) cx.set_line_width(self.options.axis.lineWidth) self._renderLines(cx) cx.restore()
def _renderAxis(self, cx): """Renders axis""" if self.options.axis.x.hide and self.options.axis.y.hide: return cx.save() cx.set_line_width(self.options.axis.lineWidth) if not self.options.axis.y.hide: if self.yticks: for tick in self.yticks: self._renderYTick(cx, tick) if self.options.axis.y.label: self._renderYAxisLabel(cx, self.options.axis.y.label) cx.set_source_rgb(*hex2rgb(self.options.axis.lineColor)) self._renderYAxis(cx) if not self.options.axis.x.hide: if self.xticks: for tick in self.xticks: self._renderXTick(cx, tick) if self.options.axis.x.label: self._renderXAxisLabel(cx, self.options.axis.x.label) cx.set_source_rgb(*hex2rgb(self.options.axis.lineColor)) self._renderXAxis(cx) cx.restore()
def _renderBackground(self, cx): """Renders the background area of the chart""" if self.options.background.hide: return cx.save() if self.options.background.baseColor: cx.set_source_rgb(*hex2rgb(self.options.background.baseColor)) cx.paint() if self.options.background.chartColor: cx.set_source_rgb(*hex2rgb(self.options.background.chartColor)) cx.set_line_width(10.0) cx.arc(self.layout.chart.x + self.layout.chart.w / 2, self.layout.chart.y + self.layout.chart.h / 2, min(self.layout.chart.w / 2, self.layout.chart.h / 2), 0, 2 * math.pi) cx.fill() if self.options.background.lineColor: cx.set_source_rgb(*hex2rgb(self.options.background.lineColor)) cx.set_line_width(self.options.axis.lineWidth) self._renderLines(cx) cx.restore()
def _renderAxisLabel(self, cx, label, x, y, vertical=False): cx.save() cx.select_font_face(self.options.axis.labelFont, cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD) cx.set_font_size(self.options.axis.labelFontSize) cx.set_source_rgb(*hex2rgb(self.options.axis.labelColor)) xb, yb, width, height, xa, ya = cx.text_extents(label) if vertical: y = y + width / 2.0 cx.move_to(x - xb, y - yb) cx.translate(x, y) cx.rotate(-math.radians(90)) cx.move_to(-xb, -yb) cx.show_text(label) if self.debug: cx.rectangle(0, 0, width, height) cx.stroke() else: x = x - width / 2.0 cx.move_to(x - xb, y - yb) cx.show_text(label) if self.debug: cx.rectangle(x, y, width, height) cx.stroke() cx.restore()
def _renderAxis(self, cx): """Renders the axis for pie charts""" if self.options.axis.x.hide or not self.xticks: return self.xlabels = [] if self.debug: px = max(cx.device_to_user_distance(1, 1)) cx.set_source_rgba(0, 0, 1, 0.5) for x, y, w, h in self.layout.ticks: cx.rectangle(x, y, w, h) cx.stroke() cx.arc(x + w / 2.0, y + h / 2.0, 5 * px, 0, 2 * math.pi) cx.fill() cx.arc(x, y, 2 * px, 0, 2 * math.pi) cx.fill() cx.select_font_face(self.options.axis.tickFont, cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) cx.set_font_size(self.options.axis.tickFontSize) cx.set_source_rgb(*hex2rgb(self.options.axis.labelColor)) for i, tick in enumerate(self.xticks): label = tick[1] x, y, w, h = self.layout.ticks[i] xb, yb, width, height, xa, ya = cx.text_extents(label) # draw label with text tick[1] cx.move_to(x - xb, y - yb) cx.show_text(label) self.xlabels.append(label)
def _renderTick(self, cx, tick, x, y, x2, y2, rotate, text_position): """Aux method for _renderXTick and _renderYTick""" if callable(tick): return cx.new_path() cx.move_to(x, y) cx.line_to(x2, y2) cx.close_path() cx.stroke() cx.set_source_rgb(*hex2rgb('#000000')) cx.select_font_face(self.options.axis.tickFont, cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) cx.set_font_size(self.options.axis.tickFontSize) label = safe_unicode(tick[1], self.options.encoding) xb, yb, width, height, xa, ya = cx.text_extents(label) x, y = text_position if rotate: cx.save() cx.translate(x, y) cx.rotate(math.radians(rotate)) x = -width / 2.0 y = -height / 2.0 cx.move_to(x - xb, y - yb) cx.show_text(label) cx.set_source_rgb(*hex2rgb(self.options.axis.lineColor)) if self.debug: cx.rectangle(x, y, width, height) cx.stroke() cx.restore() else: x -= width / 2.0 y -= height / 2.0 cx.move_to(x - xb, y - yb) cx.show_text(label) cx.set_source_rgb(*hex2rgb(self.options.axis.lineColor)) if self.debug: cx.rectangle(x, y, width, height) cx.stroke() return label
def _renderBackground(self, cx): """Renders the background area of the chart""" if self.options.background.hide: return cx.save() if self.options.background.baseColor: cx.set_source_rgb(*hex2rgb(self.options.background.baseColor)) cx.paint() if self.options.background.chartColor: cx.set_source_rgb(*hex2rgb(self.options.background.chartColor)) cx.set_line_width(10.0) cx.new_path() init = None count = len(self.xticks) for index, tick in enumerate(self.xticks): ang = math.pi / 2 - index * 2 * math.pi / count x = (self.layout.chart.x + self.layout.chart.w / 2 - math.cos(ang) * min(self.layout.chart.w / 2, self.layout.chart.h / 2)) y = (self.layout.chart.y + self.layout.chart.h / 2 - math.sin(ang) * min(self.layout.chart.w / 2, self.layout.chart.h / 2)) if init is None: cx.move_to(x, y) init = (x, y) else: cx.line_to(x, y) cx.line_to(init[0], init[1]) cx.close_path() cx.fill() if self.options.background.lineColor: cx.set_source_rgb(*hex2rgb(self.options.background.lineColor)) cx.set_line_width(self.options.axis.lineWidth) self._renderLines(cx) cx.restore()
def _renderChart(self, cx): """Renders a pie chart""" self.centerx = self.layout.chart.x + self.layout.chart.w * 0.5 self.centery = self.layout.chart.y + self.layout.chart.h * 0.5 cx.set_line_join(cairo.LINE_JOIN_ROUND) if self.options.stroke.shadow and False: cx.save() cx.set_source_rgba(0, 0, 0, 0.15) cx.new_path() cx.move_to(self.centerx, self.centery) cx.arc(self.centerx + 1, self.centery + 2, self.layout.radius + 1, 0, math.pi * 2) cx.line_to(self.centerx, self.centery) cx.close_path() cx.fill() cx.restore() cx.save() for slice in self.slices: if slice.isBigEnough(): cx.set_source_rgb(*self.colorScheme[slice.name]) if self.options.shouldFill: slice.draw(cx, self.centerx, self.centery, self.layout.radius) cx.fill() if not self.options.stroke.hide: slice.draw(cx, self.centerx, self.centery, self.layout.radius) cx.set_line_width(self.options.stroke.width) cx.set_source_rgb(*hex2rgb(self.options.stroke.color)) cx.stroke() cx.restore() if self.debug: cx.set_source_rgba(1, 0, 0, 0.5) px = max(cx.device_to_user_distance(1, 1)) for x, y in self.layout._lines: cx.arc(x, y, 5 * px, 0, 2 * math.pi) cx.fill() cx.new_path() cx.move_to(self.centerx, self.centery) cx.line_to(x, y) cx.stroke()
def drawLine(storeName): if self.options.stroke.shadow: # draw shadow cx.save() cx.set_source_rgba(0, 0, 0, 0.15) cx.translate(2, -2) preparePath(storeName) cx.fill() cx.restore() # fill the line cx.set_source_rgb(*self.colorScheme[storeName]) preparePath(storeName) cx.fill() if not self.options.stroke.hide: # draw stroke cx.set_source_rgb(*hex2rgb(self.options.stroke.color)) preparePath(storeName) cx.stroke()
def _renderTitle(self, cx): if self.options.title: cx.save() cx.select_font_face(self.options.titleFont, cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD) cx.set_font_size(self.options.titleFontSize) cx.set_source_rgb(*hex2rgb(self.options.titleColor)) title = safe_unicode(self.options.title, self.options.encoding) extents = cx.text_extents(title) title_width = extents[2] x = (self.layout.title.x + self.layout.title.w / 2.0 - title_width / 2.0) y = self.layout.title.y - extents[1] - 10 cx.move_to(x, y) cx.show_text(title) cx.restore()
def _renderAxis(self, cx): """Renders axis""" if self.options.axis.x.hide and self.options.axis.y.hide: return cx.save() cx.set_source_rgb(*hex2rgb(self.options.axis.lineColor)) cx.set_line_width(self.options.axis.lineWidth) centerx = self.layout.chart.x + self.layout.chart.w / 2 centery = self.layout.chart.y + self.layout.chart.h / 2 if not self.options.axis.y.hide: if self.yticks: count = len(self.yticks) for i in range(0, count): self._renderYTick(cx, i, (centerx, centery)) if self.options.axis.y.label: self._renderYAxisLabel(cx, self.options.axis.y.label) self._renderYAxis(cx) if not self.options.axis.x.hide: fontAscent = cx.font_extents()[0] if self.xticks: count = len(self.xticks) for i in range(0, count): self._renderXTick(cx, i, fontAscent, (centerx, centery)) if self.options.axis.x.label: self._renderXAxisLabel(cx, self.options.axis.x.label) self._renderXAxis(cx) cx.restore()
def _renderLegend(self, cx): """This function adds a legend to the chart""" if self.options.legend.hide: return surface_width, surface_height = self.getSurfaceSize() # Compute legend dimensions padding = 4 bullet = 15 width = 0 height = padding keys = self._getDatasetsKeys() cx.select_font_face(self.options.legend.legendFont, cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) cx.set_font_size(self.options.legend.legendFontSize) for key in keys: key = safe_unicode(key, self.options.encoding) extents = cx.text_extents(key) width = max(extents[2], width) height += max(extents[3], bullet) + padding width = padding + bullet + padding + width + padding # Compute legend position legend = self.options.legend if legend.position.right is not None: legend.position.left = (surface_width - legend.position.right - width) if legend.position.bottom is not None: legend.position.top = (surface_height - legend.position.bottom - height) # Draw the legend cx.save() cx.rectangle(self.options.legend.position.left, self.options.legend.position.top, width, height) cx.set_source_rgba(1, 1, 1, self.options.legend.opacity) cx.fill_preserve() cx.set_line_width(self.options.legend.borderWidth) cx.set_source_rgb(*hex2rgb(self.options.legend.borderColor)) cx.stroke() def drawKey(key, x, y, text_height): cx.rectangle(x, y, bullet, bullet) cx.set_source_rgb(*self.colorScheme[key]) cx.fill_preserve() cx.set_source_rgb(0, 0, 0) cx.stroke() cx.move_to(x + bullet + padding, y + bullet / 2.0 + text_height / 2.0) cx.show_text(key) cx.set_line_width(1) x = self.options.legend.position.left + padding y = self.options.legend.position.top + padding for key in keys: extents = cx.text_extents(key) drawKey(key, x, y, extents[3]) y += max(extents[3], bullet) + padding cx.restore()