def _append_hand_path(self, cr: cairo.Context, pos: Vector2[float], angle: float, radius: float) -> None: if radius == 0: return cr.move_to(*pos) cr.rel_line_to(radius * math.cos(angle), radius * math.sin(angle))
def bezier(self, cr: cairo.Context, x0, y0, x1, y1, x2, y2, x3, y3): mesh_f = 35 cr.set_line_width(0.5e-2) p = [[x0, y0], [x1, y1], [x2, y2], [x3, y3]] cr.move_to(*p[0]) cr.curve_to(*p[1], *p[2], *p[3]) cr.stroke() # cr.move_to(*p[0]) # # for j in p[1:]: # cr.line_to(*j) # cr.stroke() l = [] for i in range(len(p) - 1): lx = np.linspace(p[i][0], p[i + 1][0], mesh_f) ly = np.linspace(p[i][1], p[i + 1][1], mesh_f) l.append([lx, ly]) cr.set_line_width(0.5e-3) for l1, l2 in zip(l[:-1], l[1:]): for ix, iy, jx, jy in zip(l1[0], l1[1], l2[0], l2[1]): cr.move_to(ix, iy) cr.line_to(jx, jy) cr.stroke()
def background(self, cr: cairo.Context): linear = cairo.LinearGradient(0, 0, .25, 1) linear.add_color_stop_rgb(0.0, *colors[0]) linear.add_color_stop_rgb(0.4, *colors[5]) linear.add_color_stop_rgb(1.0, *colors[6]) cr.rectangle(0, 0, .5, 1) cr.set_source(linear) cr.fill() cr.rectangle(0.5, 0, 1, 1) linear = cairo.LinearGradient(1, 0, .75, 1) linear.add_color_stop_rgb(0.0, *colors[0]) linear.add_color_stop_rgb(0.4, *colors[5]) linear.add_color_stop_rgb(1.0, *colors[6]) cr.set_source(linear) cr.fill() cr.move_to(.5, 0) # lower left cr.rel_line_to(-.5, 1) cr.rel_line_to(1, 0) cr.close_path() radial = cairo.RadialGradient(0.5, 0.5, 0.1, 0.5, 0.5, 0.75) radial.add_color_stop_rgba(0, *colors[3], 0.7) radial.add_color_stop_rgba(.4, *colors[1], 0.5) radial.add_color_stop_rgba(1, *colors[2], 0.1) cr.set_source(radial) cr.fill()
def renegerate_overlay_buffer(self): image = ImageSurface(cairo.FORMAT_ARGB32, self.video_width, self.video_height) context = Context(image) text = "Foo bar 123" font = pango.FontDescription('sans normal 22') text_offset = [6, 6] textOverflowed = False if text: pcContext = pangocairo.CairoContext(context) pangoLayout = pcContext.create_layout() font = pango.FontDescription('sans normal 22') pangoLayout.set_font_description(font) context.move_to(text_offset[0]+2, text_offset[1]+2) pangoLayout.set_markup('<span foreground="black" >%s</span>' % text) pcContext.show_layout(pangoLayout) context.move_to(text_offset[0], text_offset[1]) pangoLayout.set_markup('<span foreground="white" >%s</span>' % text) pcContext.show_layout(pangoLayout) textWidth, textHeight = pangoLayout.get_pixel_size() self.overlay_buffer = image.get_data() print "overlay_buffer size: %d" % len(self.overlay_buffer)
def draw_triag(self, cr: cairo.Context, p): # p-> lower left coordinate of the triangle cr.move_to(*p) # lower left cr.rel_line_to(2 * self.dx, 0) # line to lower right cr.rel_line_to(-self.dx, -self.dy) cr.close_path()
def export_svg(fn, paths, size, line_with=0.1, scale_factor=None): from cairo import SVGSurface, Context from numpy import array from ddd import spatial_sort_2d as sort if not scale_factor: scale_factor = size one = 1.0/size s = SVGSurface(fn, size, size) c = Context(s) c.set_line_width(0.1) paths = sort(paths) for path in paths: path *= scale_factor c.new_path() c.move_to(*path[0,:]) for p in path[1:]: c.line_to(*p) c.stroke() c.save()
def write_text(self): if not self.text: # Nothing useful to draw, return now! return if self.resized( ) or self.text != self.prev_text or self.text_overlay is None: # Need to recreate the cache drawing self.text_overlay = ImageSurface(FORMAT_ARGB32, self.width, self.height) ctx = Context(self.text_overlay) pg = CairoContext(ctx) pl = pg.create_layout() pl.set_font_description(self.text_font) pl.set_width(-1) # No text wrapping pl.set_text(self.text) plsize = pl.get_size() text_width = plsize[0] // SCALE text_height = plsize[1] // SCALE area_width_without_text = self.width - text_width area_height_without_text = self.height - text_height ctx.move_to(area_width_without_text // 2, area_height_without_text // 2) ctx.set_source_rgb(1, 1, 1) pg.update_layout(pl) pg.show_layout(pl) self.cr.set_source_surface(self.text_overlay) self.cr.paint()
def export_svg(fn, paths, size, line_with=0.1, scale_factor=None): from cairo import SVGSurface, Context from .ddd import spatial_sort_2d as sort if not scale_factor: scale_factor = size s = SVGSurface(fn, size, size) c = Context(s) c.set_line_width(0.1) paths = sort(paths) for path in paths: path *= scale_factor c.new_path() c.move_to(*path[0, :]) for p in path[1:]: c.line_to(*p) c.stroke() c.save()
def draw_base(self, cr: cairo.Context): cr.identity_matrix() cr.set_matrix(self.matrix) cr.rectangle(-1, -1, 2, 2) cr.set_source_rgb(*colors[0]) cr.fill() if self.gtk_mode: cr.rectangle(-1, .65, .15, .35) cr.set_source_rgb(*colors[1]) cr.fill() cr.set_source_rgb(*colors[1]) cr.set_line_width(9e-3) cr.arc(0, 0, self.radius, 0, 2 * PI) # cr.stroke() for theta in np.linspace(0, 2 * PI, self.radio_button + 1): cr.move_to(0, 0) x, y = self.radius * np.cos(theta), self.radius * np.sin(theta) cr.line_to(x, y) if (x, y) not in self.inter_sections: self.inter_sections.append((x, y)) cr.stroke()
def _do_draw(self, _: Gtk.DrawingArea, cr: cairo.Context): height = self.get_allocated_height() current_dt = self.current_date cr.set_font_size(16) cr.set_source_rgb(0.5, 0.5, 0.5) for h in range(24): hx = self.timeline_helper.datetime_to_pixel(current_dt) hour_string = str(current_dt.hour).rjust(2, '0') (tx, _, hour_text_width, hour_text_height, dx, _) = cr.text_extents(hour_string) cr.move_to(hx - tx - (hour_text_width / 2), (height + hour_text_height) / 2) cr.show_text(hour_string) current_dt += datetime.timedelta(hours=1) cr.set_source_rgb(1, 0.64, 0) for te in self.tagged_timeline_entries: cr.rectangle(te.start_x, 10, te.width, 20) cr.fill() cr.set_source_rgb(0.3, 0.3, 0.8) for le in self.logged_timeline_entries: cr.rectangle(le.start_x, 50, le.width, 20) cr.fill() start_x = self.timeline_helper.datetime_to_pixel( dt=self.boundary_start) stop_x = self.timeline_helper.datetime_to_pixel(dt=self.boundary_stop) cr.set_source_rgba(0.4, 0.4, 0.4, 0.5) cr.rectangle(start_x, 0, stop_x - start_x, height) cr.fill()
def connect_line(self, cr: cairo.Context, x0, y0): cr.set_source_rgb(*colors[1]) cr.set_line_width(9e-3) cr.move_to(x0, y0) cr.line_to(*self.mousePos) cr.stroke() cr.stroke()
def draw_player(cr: cairo.Context, player: Player) -> None: with save_context(cr): cr.translate(player.x, player.y) with save_context(cr): cr.rotate(player.rotation) # draw player cr.set_source_rgb(0, 0, 0) cr.arc(0, 0, 10, 0, math.tau) cr.fill() # draw arms cr.move_to(2, -10) cr.rel_line_to(12, 0) cr.move_to(2, 10) cr.rel_line_to(12, 0) cr.stroke() # draw health cr.set_source_rgb(1, 1, 1) cr.rectangle(-20, -35, 40, 8) cr.fill() # cr.set_source_rgb(.1, .9, .2) cr.set_source_rgb(2 * (1 - player.health), 2 * player.health, 0) cr.rectangle(-20, -35, 40 * player.health, 8) cr.fill() cr.set_line_width(1) cr.set_source_rgb(0, 0, 0) cr.rectangle(-20, -35, 40, 8) cr.stroke()
def showWrappedText(ctx: cairo.Context, text: str, top=0.0, left=0.0, right=None, lineHeight=12.0): maxWidth = right - left inputLines = text.split('\n') inputWords = [line.split(' ') for line in inputLines] currentOffset = 0 for line in inputWords: currentLine = [] while len(line): nextWord = line.pop(0) nextLine = currentLine + [nextWord] if (ctx.text_extents(' '.join(nextLine)).width > maxWidth): ctx.move_to(left, top + currentOffset) ctx.show_text(' '.join(currentLine)) currentLine = [nextWord] currentOffset = currentOffset + lineHeight else: currentLine = nextLine if (len(currentLine)): ctx.move_to(left, top + currentOffset) ctx.show_text(' '.join(currentLine)) currentOffset = currentOffset + lineHeight * 1.4
def selection_draw_callback(self, ctx: cairo.Context, x: int, y: int): if self.interaction_mode == DrawerInteraction.CHUNKS: # Draw a chunk chunks_at_frame = self.animation_context.current()[self.edited_layer] ctx.set_source_surface( chunks_at_frame[self.interaction_chunks_selected_id], x, y ) ctx.get_source().set_filter(cairo.Filter.NEAREST) ctx.paint() elif self.interaction_mode == DrawerInteraction.COL: # Draw collision if self.interaction_col_solid: ctx.set_source_rgba(1, 0, 0, 1) ctx.rectangle( x, y, BPC_TILE_DIM, BPC_TILE_DIM ) ctx.fill() elif self.interaction_mode == DrawerInteraction.DAT: # Draw data if self.interaction_dat_value > 0: ctx.select_font_face("monospace", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) ctx.set_font_size(6) ctx.set_source_rgb(1, 1, 1) ctx.move_to(x, y + BPC_TILE_DIM - 2) ctx.show_text(f"{self.interaction_dat_value:02x}")
def on_draw(self, widget: Widget, context: cairo.Context): if not self.is_shape_set: self.layout(context) context.set_font_size(self.font_size) self.shape.draw_on_context(context) context.set_source_rgb(1, 1, 1) context.fill_preserve() context.set_source_rgb(0, 0, 0) context.stroke() shape = self.shape label = self.label if len(label) > 0 and label[-1] == ' ': label += '.' xb, yb, w, h, xa, ya = context.text_extents(label) context.rectangle(shape.start.x + self.padding, shape.start.y, shape.width - self.padding, shape.height) context.clip() context.move_to(shape.start.x + (shape.width - self.padding - w)/2, shape.start.y + shape.height - self.padding) context.show_text(self.label)
def draw(self, cr: cairo.Context) -> None: line = self._line stroke_color = self._stroke_color stroke_width = self._stroke_width scale_strokes = self._scale_strokes if line is None: return if line.pt0 == line.pt1: return clip_extents = Rect2(cr.clip_extents()) start = line.eval(x=clip_extents.x0) end = line.eval(x=clip_extents.x1) if not clip_extents.contains(start): start = line.eval(y=clip_extents.y0 if start.y < clip_extents.y0 else clip_extents.y1) if not clip_extents.contains(end): end = line.eval(y=clip_extents. y0 if end.y < clip_extents.y0 else clip_extents.y1) cr.move_to(*start) cr.line_to(*end) cr.save() if scale_strokes: cr.identity_matrix() cr.set_source_rgb(*stroke_color) cr.set_line_width(stroke_width) cr.stroke() cr.restore()
def draw_precip_curve( self, context: cairo.Context, points: List[Tuple[int, int]], bottom: int, color, curviness: float = 7, ): # Draw the top curves for i, point in enumerate(points): if i == 0: context.move_to(*point) else: last_point = points[i - 1] context.curve_to( last_point[0] + curviness, last_point[1], point[0] - curviness, point[1], point[0], point[1], ) # Draw the rest and fill context.line_to(points[-1][0], bottom) context.line_to(points[0][0], bottom) context.close_path() context.set_source_rgb(*color) context.fill()
def draw_circular_roman( ctx: cairo.Context, rng: Generator, pos_x: float, pos_y: float, radius_outer: float, radius_inner: float, ): chunks = rng.integers(6, 16) _calendar_base(ctx, pos_x, pos_y, radius_outer, radius_inner, chunks) ctx.select_font_face("Noto Sans Symbols") font_size = 0.8 * (radius_outer - radius_inner) ctx.set_font_size(font_size) angle_offset = pi / chunks for i, (x, y) in enumerate( points_along_arc( pos_x, pos_y, (radius_inner + radius_outer) / 2.0, angle_offset, angle_offset + tau, chunks, ), 1, ): with translation(ctx, x, y), rotation(ctx, (i * tau / chunks) + (pi / 2) - angle_offset): roman = int_to_roman(i) extents = ctx.text_extents(roman) ctx.move_to(-1 * extents.width / 2.0, extents.height / 2.0) ctx.show_text(roman) ctx.new_path()
def _draw_cell(self, context: cairo.Context, cell_value: CrucipixelCellValue, area: Rectangle): r, g, b = self.crucipixel_cell_value_to_color[cell_value] context.set_source_rgb(r, g, b) context.rectangle(area.start.x, area.start.y, area.width, area.height) context.fill() if not self.victory_screen and cell_value == CrucipixelCellValue.EMPTY: # draw the X r, g, b = self.crucipixel_cell_value_to_color[ CrucipixelCellValue.SELECTED ] context.set_source_rgb(r, g, b) context.set_line_cap(cairo.LINE_CAP_ROUND) delta_x = self.cell_width // 2.8 delta_y = self.cell_height // 2.8 context.move_to(area.start.x + area.width - delta_x, area.start.y + delta_y) context.line_to(area.start.x + delta_x, area.start.y + area.height - delta_y) context.move_to(area.start.x + area.width - delta_x, area.start.y + area.width - delta_y) context.line_to(area.start.x + delta_x, area.start.y + delta_y) context.stroke()
def draw(self, cr: cairo.Context, drawing_options: DrawingOptions): cr.set_source_rgb(*drawing_options.sleeper_color) # The half-sleepers at either end cr.set_line_width(1) cr.move_to(0.5, -4) cr.line_to(0.5, 4) cr.move_to(self.length - 0.5, -4) cr.line_to(self.length - 0.5, 4) cr.stroke() # The sleepers in between cr.set_line_width(2) for x in range(4, int(self.length), 4): cr.move_to(x, -4) cr.line_to(x, 4) cr.stroke() cr.set_source_rgb(*drawing_options.rail_color) cr.set_line_width(1) cr.move_to(0, -2.5) cr.line_to(self.length, -2.5) cr.move_to(0, 2.5) cr.line_to(self.length, 2.5) cr.stroke()
def draw_polyline(context: cairo.Context, polyline: symbols.Polyline) -> None: """draw a polyline""" if not polyline.lines: return # The gotchas for animation and joints will be handled by polyline_frac, not this. context.set_line_width(polyline.thickness) _set_color(context, polyline.color) if polyline.joint_type != '': context.set_line_join(polyline.joint_type) context.move_to(polyline.lines[0].start[0], polyline.lines[0].start[1]) if polyline.closed: for line in polyline.lines[:-1]: context.line_to(line.end[0], line.end[1]) context.close_path() else: for line in polyline.lines: context.line_to(line.end[0], line.end[1]) context.stroke()
def draw_line(context: cairo.Context, line: symbols.Line) -> None: """draw a line""" context.set_line_width(line.thickness) _set_color(context, line.color) context.move_to(line.start[0], line.start[1]) context.line_to(line.end[0], line.end[1]) context.stroke()
def do_render(self, model: Dazzle.GraphModel, x_begin: int, x_end: int, y_begin: float, y_end: float, cairo_context: cairo.Context, area: cairo.RectangleInt) -> None: model_iter = Dazzle.GraphModelIter() cairo_context.save() if model.get_iter_first(model_iter): chunk = area.width / (model.props.max_samples - 1) / 2.0 last_x = self._calc_x(model_iter, x_begin, x_end, area.width) last_y = float(area.height) cairo_context.move_to(last_x, area.height) while Dazzle.GraphModel.iter_next(model_iter): x = self._calc_x(model_iter, x_begin, x_end, area.width) y = self._calc_y(model_iter, y_begin, y_end, area.height, self._column) cairo_context.curve_to(last_x + chunk, last_y, last_x + chunk, y, x, y) last_x = x last_y = y cairo_context.set_line_width(self._line_width) cairo_context.set_source_rgba(self._stacked_color_rgba.red, self._stacked_color_rgba.green, self._stacked_color_rgba.blue, self._stacked_color_rgba.alpha) cairo_context.rel_line_to(0, area.height) cairo_context.stroke_preserve() cairo_context.close_path() cairo_context.fill() if model.get_iter_first(model_iter): chunk = area.width / (model.props.max_samples - 1) / 2.0 last_x = self._calc_x(model_iter, x_begin, x_end, area.width) last_y = float(area.height) cairo_context.move_to(last_x, last_y) while Dazzle.GraphModel.iter_next(model_iter): x = self._calc_x(model_iter, x_begin, x_end, area.width) y = self._calc_y(model_iter, y_begin, y_end, area.height, self._column) cairo_context.curve_to(last_x + chunk, last_y, last_x + chunk, y, x, y) last_x = x last_y = y cairo_context.set_source_rgba(self._stroke_color_rgba.red, self._stroke_color_rgba.green, self._stroke_color_rgba.blue, self._stacked_color_rgba.alpha) cairo_context.stroke() cairo_context.restore()
def draw_poly(poly: RegularPolygon, ctx: cairo.Context): ctx.save() v = poly.vertices() ctx.move_to(v[0][0], v[0][1]) for i in range(1, len(v)): ctx.line_to(v[i][0], v[i][1]) ctx.close_path() ctx.stroke() ctx.restore()
def _draw_performer(self, ctx: cairo.Context, performer: SsaPerformer, x, y, w, h): # Label ctx.select_font_face("monospace", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) ctx.set_source_rgb(*COLOR_PERFORMER) ctx.set_font_size(12) ctx.move_to(x - 4, y - 8) ctx.show_text(f'{performer.type}') # Direction arrow self._triangle(ctx, x, y, BPC_TILE_DIM, COLOR_PERFORMER, performer.pos.direction.id)
def draw(self, cr: cairo.Context) -> None: vertex_pos = self._vertex_pos if vertex_pos is None: return vertex_pos = self._parent._widget_coord_from_canvas(vertex_pos) start_angle = -self._start_angle delta_angle = -self._delta_angle end_angle = start_angle + delta_angle if not (math.isfinite(start_angle) and math.isfinite(end_angle)): return stroke_width = self._stroke_width stroke_color = self._stroke_color cr.set_line_width(stroke_width) cr.set_source_rgb(*stroke_color) # Start marker path start_marker_radius = self._start_marker_radius self._append_hand_path(cr, vertex_pos, start_angle, start_marker_radius) # End marker path end_marker_radius = self._end_marker_radius self._append_hand_path(cr, vertex_pos, end_angle, end_marker_radius) cr.stroke() # Angle arc path angle_radius = self._angle_radius if self._clockwise: which_arc = cr.arc else: which_arc = cr.arc_negative which_arc(*vertex_pos, angle_radius, start_angle, end_angle) cr.stroke() # Text mid_angle = (start_angle + end_angle) / 2 text_radius = self._text_radius text_font_size = self._text_font_size cr.move_to(*vertex_pos) cr.rel_move_to(text_radius * math.cos(mid_angle), text_radius * math.sin(mid_angle)) cr.set_font_size(text_font_size) cr.set_source_rgb(*stroke_color) angle_text = '{:.1f}°'.format(math.degrees(abs(delta_angle))) text_extents = cr.text_extents(angle_text) cr.rel_move_to(-text_extents.x_bearing, -text_extents.y_bearing) cr.rel_move_to(-text_extents.width / 2, -text_extents.height / 2) cr.show_text(angle_text)
def _draw_boost(self, ctx: cairo.Context, display_id: int): if display_id == 0: ctx.set_source_rgb(1.0, 0, 0) ctx.move_to(10, 20) ctx.set_font_size(20) ctx.show_text("BOOST") ctx.set_font_size(12) ctx.move_to(10, 30) ctx.show_text("Debugging disabled.")
def draw_outline(self, bounding_box: Rectangle, cr: CairoContext) -> None: """Draw the outline and header of the swimlanes.""" cr.move_to(0, bounding_box.height) cr.line_to(0, 0) cr.line_to(bounding_box.width, 0) cr.line_to(bounding_box.width, bounding_box.height) cr.move_to(0, bounding_box.height) cr.line_to(0, HEADER_HEIGHT) cr.line_to(0 + bounding_box.width, HEADER_HEIGHT) cr.line_to(0 + bounding_box.width, bounding_box.height)
def draw_one_rect(ctx: cairo.Context, rect: PColoredRectangle) -> None: ctx.move_to(rect.x, rect.y) x2 = rect.x + rect.width y2 = rect.y + rect.height ctx.line_to(x2, rect.y) ctx.line_to(x2, y2) ctx.line_to(rect.x, y2) ctx.close_path() ctx.set_source_rgba(rect.r, rect.g, rect.b, rect.a) ctx.fill()
class Canvas: def __init__(self, width, height): self.xform = lambda x, y: (x, y) self.img = ImageSurface(FORMAT_RGB24, width, height) self.ctx = Context(self.img) self.ctx.move_to(0, 0) self.ctx.line_to(width, 0) self.ctx.line_to(width, height) self.ctx.line_to(0, height) self.ctx.line_to(0, 0) self.ctx.set_source_rgb(1, 1, 1) self.ctx.fill() self.width = width self.height = height def fit(self, left, top, right, bottom): xoff = left yoff = top xscale = self.width / float(right - left) yscale = self.height / float(bottom - top) if abs(xscale) > abs(yscale): xscale *= abs(yscale) / abs(xscale) elif abs(xscale) < abs(yscale): yscale *= abs(xscale) / abs(yscale) self.xform = lambda x, y: ((x - xoff) * xscale, (y - yoff) * yscale) def dot(self, x, y, size=4, fill=(.5, .5, .5)): x, y = self.xform(x, y) self.ctx.arc(x, y, size/2., 0, 2*pi) self.ctx.set_source_rgb(*fill) self.ctx.fill() def line(self, points, stroke=(.5, .5, .5), width=1): self.ctx.move_to(*self.xform(*points[0])) for (x, y) in points[1:]: self.ctx.line_to(*self.xform(x, y)) self.ctx.set_source_rgb(*stroke) self.ctx.set_line_cap(LINE_CAP_ROUND) self.ctx.set_line_width(width) self.ctx.stroke() def save(self, filename): self.img.write_to_png(filename)
def _draw_trigger(self, ctx: cairo.Context, trigger: SsaEvent, *coords_hitbox): # Draw hitbox self._draw_hitbox(ctx, COLOR_PERFORMER, *coords_hitbox) # Label ctx.select_font_face("monospace", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) ctx.set_source_rgb(1, 1, 1) ctx.set_font_size(12) ctx.move_to(coords_hitbox[0] + 4, coords_hitbox[1] + 14) ctx.show_text(f'{self._cb_trigger_label(trigger.trigger_id)}') return coords_hitbox
class Canvas: def __init__(self, width, height): self.xform = lambda x, y: (x, y) self.img = ImageSurface(FORMAT_RGB24, width, height) self.ctx = Context(self.img) self.ctx.move_to(0, 0) self.ctx.line_to(width, 0) self.ctx.line_to(width, height) self.ctx.line_to(0, height) self.ctx.line_to(0, 0) self.ctx.set_source_rgb(1, 1, 1) self.ctx.fill() self.width = width self.height = height def fit(self, left, top, right, bottom): xoff = left yoff = top xscale = self.width / float(right - left) yscale = self.height / float(bottom - top) if abs(xscale) > abs(yscale): xscale *= abs(yscale) / abs(xscale) elif abs(xscale) < abs(yscale): yscale *= abs(xscale) / abs(yscale) self.xform = lambda x, y: ((x - xoff) * xscale, (y - yoff) * yscale) def dot(self, x, y, size=4, fill=(.5, .5, .5)): x, y = self.xform(x, y) self.ctx.arc(x, y, size / 2., 0, 2 * pi) self.ctx.set_source_rgb(*fill) self.ctx.fill() def line(self, points, stroke=(.5, .5, .5), width=1): self.ctx.move_to(*self.xform(*points[0])) for (x, y) in points[1:]: self.ctx.line_to(*self.xform(x, y)) self.ctx.set_source_rgb(*stroke) self.ctx.set_line_cap(LINE_CAP_ROUND) self.ctx.set_line_width(width) self.ctx.stroke() def save(self, filename): self.img.write_to_png(filename)
def draw_dodecahedron( ctx: cairo.Context, rng: Generator, pos_x: float, pos_y: float, radius: float, rotation: float = 0, ): # Outer boundary outer_points = list( points_along_arc(pos_x, pos_y, radius, rotation, rotation + tau, 10)) for prev_index, (bx, by) in enumerate(outer_points, -1): ax, ay = outer_points[prev_index] ctx.move_to(ax, ay) ctx.line_to(bx, by) ctx.stroke() # Frontside inner pentagon inner_fs_points = list( points_along_arc(pos_x, pos_y, 0.6 * radius, rotation, rotation + tau, 5)) for prev_index, (bx, by) in enumerate(inner_fs_points, -1): ax, ay = inner_fs_points[prev_index] ctx.move_to(ax, ay) ctx.line_to(bx, by) ctx.stroke() # Outer to frontside inner for (ax, ay), (bx, by) in zip(inner_fs_points, outer_points[::2]): ctx.move_to(ax, ay) ctx.line_to(bx, by) ctx.stroke() # backside inner pentagon offset = pi / 5 inner_bs_points = list( points_along_arc( pos_x, pos_y, 0.6 * radius, rotation + offset, rotation + offset + tau, 5, )) for prev_index, (bx, by) in enumerate(inner_bs_points, -1): ax, ay = inner_bs_points[prev_index] ctx.move_to(ax, ay) ctx.line_to(bx, by) ctx.stroke() # Outer to backside inner for (ax, ay), (bx, by) in zip(inner_bs_points, outer_points[1::2]): ctx.move_to(ax, ay) ctx.line_to(bx, by) ctx.stroke()
def _draw_boost(self, ctx: cairo.Context, display_id: int): if display_id == 0: ctx.set_source_rgb(1.0, 0, 0) ctx.move_to(10, 20) ctx.set_font_size(20) ctx.show_text( _("BOOST") ) # TRANSLATORS: Shown in enulator when boosting / fast-forward ctx.set_font_size(12) ctx.move_to(10, 30) ctx.show_text(_("Debugging disabled."))
def _draw_plus(self, ctx: cairo.Context): arrow_len = BPC_TILE_DIM / 4 ctx.set_source_rgb(1, 1, 1) ctx.translate(-arrow_len, 0) ctx.move_to(0, 0) ctx.rel_line_to(arrow_len * 2, 0) ctx.stroke() ctx.translate(arrow_len, -arrow_len) ctx.move_to(0, 0) ctx.rel_line_to(0, arrow_len * 2) ctx.stroke() ctx.translate(0, arrow_len)
def on_draw(self, widget: Widget, context: cairo.Context): super().on_draw(widget, context) if self.shape is not None: self.__wrapper_shape.draw_on_context(context) context.stroke() context.set_source_rgb(*global_constants.background) self.__outer_font_box.draw_on_context(context) context.fill_preserve() context.set_source_rgb(0, 0, 0) context.stroke() context.move_to(self.__title_start_point.x, self.__title_start_point.y) context.set_font_size(self.font_size) context.show_text(self.title)
def on_draw(self, widget: Widget, context: cairo.Context): for b in self._buttons: b.set_shape_from_context(context) shapes = [b.shape for b in self._buttons] context.save() context.select_font_face("", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD) xb, yb, w, h, xa, ya = context.text_extents(self.title) width = max(shape.width for shape in shapes) width = max(width, xa) container_width = self.container_size[0] translation = Point(0, self.distance) if container_width > width: translation += Point((container_width)/2, 0) else: translation += Point(width/2, 0) context.move_to(translation.x - xa/2, h + 2 * self.distance) context.show_text(self.title) context.restore() height = h + self.distance * 3 for b in self._buttons: height += b.shape.height + self.distance self.min_size = width + 2 * self.distance, height + self.distance start_point = context.get_current_point() translation += Point(0, h + self.distance * 3) context.translate(translation.x, translation.y) distance_offset = Point(0, self.distance) for b in self._buttons: context.move_to(*start_point) b.set_translate(translation.x, translation.y) context.save() b.on_draw(widget, context) context.restore() to_translate = Point(distance_offset.x, distance_offset.y + b.shape.height) context.translate(to_translate.x, to_translate.y) translation += to_translate
def on_draw(self, widget: Widget, context: cairo.Context): shape = self.shape if shape is None: self.layout(context) shape = self.shape shape.draw_on_context(context) context.set_source_rgb(1, 1, 1) context.fill_preserve() context.set_source_rgb(0, 0, 0) context.stroke() text = str(self.value) context.set_font_size(self.font_size) xb, yb, w, h, xa, ya = context.text_extents(text) context.move_to(shape.start.x + shape.width - w - self.padding, shape.start.y + shape.height - self.padding) context.show_text(text)
def export_svg(fn, paths, w, h, line_width=0.1): from cairo import SVGSurface, Context s = SVGSurface(fn, w, h) c = Context(s) c.set_line_width(line_width) for path in paths: c.new_path() c.move_to(*path[0,:]) for p in path[1:]: c.line_to(*p) c.stroke() c.save()
def on_draw(self, widget: Widget, context: cairo.Context): max_height = 0 max_width = 0 for line in self._lines: line.set_shape_from_context(context) max_height = max(max_height, line.shape.height) max_width = max(max_width, line.shape.width) offset = 0 if self._orientation == Orientation.HORIZONTAL: def handle_line(line: _GuideLine): nonlocal offset line.line_extension = max_height - line.shape.height line.set_translate(offset, 0) offset += line.shape.width else: def handle_line(line: _GuideLine): nonlocal offset line.line_extension = max_width - line.shape.width line.set_translate(0, offset) offset += line.shape.height for line in self._lines: handle_line(line) super().on_draw(self, context) context.set_line_width(self.THICK_LINE) if self._orientation == Orientation.HORIZONTAL: context.move_to(offset, 0) context.line_to(offset, -max_height) else: context.move_to(0, offset) context.line_to(-max_width, offset) context.stroke()
def on_draw(self, widget: Widget, context: cairo.Context): start_x, start_y = context.get_current_point() context.set_font_size(self.font_size) context.move_to(0, 0) if not self.is_shape_set: self.set_shape_from_context(context) shape = self.shape start = shape.start padding = self.padding h = shape.height - 2 * padding label = self.label context.set_source_rgb(*self.background_color) shape.draw_on_context(context) context.fill_preserve() context.set_line_width(1) context.set_source_rgb(*self.label_color) context.stroke() if self.disabled: context.set_source_rgba(1, 1, 1, .7) context.move_to(start.x + padding-1, start.y + padding + h+1) context.show_text(label) context.set_source_rgba(*self.label_color, .9) else: context.set_source_rgb(*self.label_color) context.move_to(start.x + padding, start.y + padding + h) context.show_text(label) if self.disabled: context.set_source_rgba(1, 1, 1, .7) context.move_to(0, 0) shape.draw_on_context(context) context.fill()
def on_draw(self, widget: Widget, context: cairo.Context): self.set_shape_from_context(context) shape = self.shape context.set_line_width(self.line_thickness) if self.orientation == Orientation.HORIZONTAL: context.move_to(shape.start.x - self.line_extension, shape.start.y) context.line_to(shape.start.x + shape.width, shape.start.y) else: context.move_to(shape.start.x, shape.start.y - self.line_extension) context.line_to(shape.start.x, shape.start.y + shape.height) context.stroke() for element in self._elements: context.move_to(*element.position) context.set_source_rgb(*element.color) context.show_text(element.label)
def on_draw(self, widget: Widget, context: cairo.Context): self.min_size = 200, 150 super().on_draw(widget, context) context.save() context.set_font_size(self.font_size) if self._table_extents is None: self._update_table_extents(context) skip = max(self.skip, 0) how_many = self.how_many table_extents = self._table_extents title_extents = self._table_extents.title_extents expected_height = title_extents.total_height + self.margin entries = self.entries base = skip up_to = skip over = False while up_to < len(entries) and not over: expected_height += table_extents[up_to].total_height over = expected_height >= self._max_height if not over: up_to += 1 while base > 0 and not over: expected_height += table_extents[base-1].total_height over = expected_height >= self._max_height if not over: base -= 1 how_many = up_to - base skip = base self.base = base entries = self.entries[skip:skip + how_many] def table_extents_iterator(): return table_extents.iter_over( skip, how_many ) start_x, start_y = context.get_current_point() start_y += title_extents.total_height h = title_extents.total_height self.title_height = h for (index, cell), data in zip(enumerate(title_extents), self.title): context.save() offset = title_extents.get_cell_data_left(index) context.rectangle(start_x + offset, start_y - h, cell.width, 2*h) context.clip() context.move_to( start_x + offset, start_y ) context.show_text(data) context.restore() # start_y += self.margin curr_x, curr_y = start_x, start_y# + title_extents.total_height for line_index, (line_extent, entry) in enumerate(zip(table_extents_iterator(), entries)): h = line_extent.total_height curr_y += h if curr_y + self.margin >= self._max_height: break for (cell_index, cell), data in zip(enumerate(line_extent), entry): context.save() offset = line_extent.get_cell_data_left(cell_index) context.rectangle(curr_x + offset, curr_y - h, cell.width, 2*h) context.clip() context.move_to( curr_x + offset, curr_y ) context.show_text(data) context.restore() curr_x = start_x end_x = table_extents.entries_width curr_y = start_y + self.margin end_y = table_extents.get_height_up_to(skip, how_many) + start_y + self.margin + 1 self.table_height = end_y self.table_width = end_x for line in table_extents_iterator(): context.move_to(curr_x, curr_y) context.line_to(end_x, curr_y) context.stroke() curr_y += line.total_height context.move_to(curr_x, curr_y) context.line_to(end_x, curr_y) context.stroke() curr_x = start_x curr_y = start_y - 1 + self.margin if self._how_many > 0: line = table_extents[0] for cell in line: context.move_to(curr_x, curr_y) context.line_to(curr_x, end_y) context.stroke() curr_x += cell.total_width + 2 * self.margin context.move_to(curr_x, curr_y) context.line_to(curr_x, end_y) context.stroke() if self._to_highlight is not None: r, g, b = global_constants.highlight context.set_source_rgba(r, g, b, .6) index = self._to_highlight base = start_y + table_extents.get_height_up_to(skip, index) + self.margin h = table_extents.get_height_of(skip, how_many, index) context.rectangle(start_x, base, table_extents.entries_width, h) context.fill() context.restore() self._shown = how_many
ctx.scale(0.25,0.25) ctx.translate(-cbox.xMin + 40,-cbox.yMin + 40) ctx.transform(Matrix(1,0,0,-1)) ctx.translate(0, -(cbox.yMax + cbox.yMin)) # difference! Curve_Tag = [FT_Curve_Tag(tag) for tag in outline.tags] start, end = 0, 0 VERTS, CODES = [], [] # Iterate over each contour ctx.set_source_rgb(0.5,0.5,0.5) for i in range(len(outline.contours)): end = outline.contours[i] ctx.move_to(outline.points[start][0],outline.points[start][1]) for j in range(start, end+1): point = outline.points[j] ctx.line_to(point[0],point[1]) #back to origin ctx.line_to(outline.points[start][0], outline.points[start][1]) start = end+1 ctx.fill_preserve() ctx.set_source_rgb(0,1,0) ctx.stroke() start, end = 0, 0 for i in range(len(outline.contours)): end = outline.contours[i] ctx.new_path()
def generateOverlay(text, font, showFlumotion, showCC, showXiph, width, height): """Generate an transparent image with text + logotypes rendered on top of it suitable for mixing into a video stream @param text: text to put in the top left corner @type text: str @param font: font description used to render the text @type: str @param showFlumotion: if we should show the flumotion logo @type showFlumotion: bool @param showCC: if we should show the Creative Common logo @type showCC: bool @param showXiph: if we should show the xiph logo @type showXiph: bool @param width: width of the image to generate @type width: int @param height: height of the image to generate @type height: int @returns: raw image and if images or if text overflowed @rtype: 3 sized tuple of string and 2 booleans """ from cairo import ImageSurface from cairo import Context image = ImageSurface(cairo.FORMAT_ARGB32, width, height) context = Context(image) subImages = [] if showXiph: subImages.append(os.path.join(configure.imagedir, '36x36', 'xiph.png')) if showCC: subImages.append(os.path.join(configure.imagedir, '36x36', 'cc.png')) if showFlumotion: subImages.append(os.path.join(configure.imagedir, '36x36', 'fluendo.png')) imagesOverflowed = False offsetX = BORDER for subPath in subImages: sub = ImageSurface.create_from_png(subPath) subX = sub.get_width() subY = sub.get_height() offsetY = height - subY - BORDER context.set_source_surface(sub, offsetX, offsetY) context.paint() if (offsetX + subX) > width: imagesOverflowed = True offsetX += subX + BORDER textOverflowed = False if text: pcContext = pangocairo.CairoContext(context) pangoLayout = pcContext.create_layout() if font is not None: font = pango.FontDescription(font) if not font.get_family() or \ not font.get_family().lower() in [family.get_name().lower() for family in pangoLayout.get_context().list_families()]: font.set_family(FONT) if font.get_size() == 0: font.set_size(FONT_SIZE) else: font = pango.FontDescription('%s %s' % (FONT, FONT_PROPS)) pangoLayout.set_font_description(font) context.move_to(TEXT_XOFFSET+2, TEXT_YOFFSET+2) pangoLayout.set_markup('<span foreground="black" >%s</span>' % text) pcContext.show_layout(pangoLayout) context.move_to(TEXT_XOFFSET, TEXT_YOFFSET) pangoLayout.set_markup('<span foreground="white" >%s</span>' % text) pcContext.show_layout(pangoLayout) textWidth, textHeight = pangoLayout.get_pixel_size() if textWidth > width: textOverflowed = True if cairo.version < '1.2.6': buf = image.get_data_as_rgba() else: buf = image.get_data() return buf, imagesOverflowed, textOverflowed
def on_draw(self, widget: "Widget", context: cairo.Context): self._set_font(context) for tl in self.__text_lines: context.move_to(tl.start.x, tl.start.y) context.show_text(tl.text)
def main(marker, paper, format, bbox, emergency, place, recipient, sender, text, sender_is_recipient, map_href): """ """ mark = Location(*marker) handle, filename = mkstemp(prefix='safetymap-', suffix='.pdf') close(handle) if paper == 'a4': surf = PDFSurface(filename, 210*ptpmm, 297*ptpmm) elif paper == 'letter': surf = PDFSurface(filename, 8.5*ptpin, 11*ptpin) ctx = Context(surf) ctx.scale(ptpmm, ptpmm) set_font_face_from_file(ctx, 'assets/HelveticaNeue.ttc') if paper == 'a4': draw_a4_master(ctx, format, map_href) ctx.translate(19, 24) elif paper == 'letter': draw_letter_master(ctx, format, map_href) ctx.translate(21, 18) ctx.set_line_width(.25 * mmppt) ctx.set_source_rgb(*md_gray) ctx.set_dash([3 * mmppt]) reps = {'4up': 4, '2up-fridge': 2, 'poster': 0} if reps[format]: card_img, mark_point = get_map_image(bbox, 84, 39, mark) for i in range(reps[format]): # dashed outlines ctx.move_to(0, 61) ctx.line_to(0, 0) ctx.line_to(173, 0) ctx.line_to(173, 61) #ctx.move_to(86, 0) #ctx.line_to(86, 61) ctx.stroke() # two card sides and contents draw_card_left(ctx, recipient, sender, text, sender_is_recipient) ctx.translate(86.5, 0) draw_card_right(ctx, card_img, mark_point, emergency, place) ctx.translate(-86.5, 61) if format == '4up': # bottom dashed outline ctx.move_to(0, 0) ctx.line_to(172, 0) ctx.stroke() elif format == '2up-fridge': # prepare to draw sideways ctx.translate(0, 122.5) ctx.rotate(-pi/2) ctx.rectangle(0, 0, 122.5, 173) ctx.stroke() poster_img, mark_point = get_map_image(bbox, 109, 77, mark) draw_small_poster(ctx, poster_img, mark_point, emergency, place, recipient, sender, text, sender_is_recipient) elif format == 'poster': ctx.rectangle(0, 0, 173, 245) ctx.stroke() poster_img, mark_point = get_map_image(bbox, 153, 108, mark) draw_large_poster(ctx, poster_img, mark_point, emergency, place, recipient, sender, text, sender_is_recipient) surf.finish() chmod(filename, 0644) return filename
def _paint_panel(self, key, width, height, panel_h): self.db.IUD("update web_stat_panels set HEIGHT = %s where ID = %s" % (panel_h, key)) self.db.commit() color_x_line = (0.7, 0.7, 0.7) color_x_line_2 = (0.9, 0.9, 0.9) color_y_line = (0.9, 0.9, 0.9) color_y_line_date = (0.7, 0.7, 0.7) color_border = (0.5, 0.5, 0.5) left = 40 right = 10 bottom = 15 var_ids = "0" series = [0, 0, 0, 0] typ = 0 for row in self.db.select( "select SERIES_1, SERIES_2, SERIES_3, SERIES_4, TYP " " from web_stat_panels " " where ID = " + str(key) ): series = row var_ids = "%s, %s, %s, %s" % row[0:4] typ = row[4] width, height = int(width), int(height) if width <= 0: width = 300 if height <= 0: height = 150 interval = self.param("range") delta_x = 1 if interval == "-6 hour": delta_x = 6 * 3600 elif interval == "-12 hour": delta_x = 12 * 3600 elif interval == "-1 day": delta_x = 24 * 3600 elif interval == "-3 day": delta_x = 3 * 24 * 3600 elif interval == "-7 day": delta_x = 7 * 24 * 3600 elif interval == "-14 day": delta_x = 14 * 24 * 3600 elif interval == "-30 day": delta_x = 30 * 24 * 3600 elif interval == "-90 day": delta_x = 3 * 30 * 24 * 3600 elif interval == "-180 day": delta_x = 6 * 30 * 24 * 3600 elif interval == "-360 day": delta_x = 12 * 30 * 24 * 3600 min_x = int(self.param("start")) - delta_x // 2 max_x = min_x + delta_x min_x_q = min_x - delta_x # // 100 max_x_q = max_x + delta_x # // 100 max_y = -9999 min_y = 9999 # Делаем полную выборку данных. Выкидываем подозрительные точки и # собираем статистику. prev_vals = [-9999] * 4 chart_data = [[], [], [], []] zoom_step = delta_x / (width * 5) if zoom_step < 1 or typ != 0: zoom_step = 1 x_min_max_values = [] mi_x = max_x_q ma_x = min_x_q tt = -100 for row in self.db.select( "select UNIX_TIMESTAMP(CHANGE_DATE) D, MIN(VALUE) + (MAX(VALUE) - MIN(VALUE)) VALUE, VARIABLE_ID " " from core_variable_changes " " where VARIABLE_ID in (%s) " " and CHANGE_DATE >= FROM_UNIXTIME(%s) " " and CHANGE_DATE <= FROM_UNIXTIME(%s) " " group by 3, ROUND(UNIX_TIMESTAMP(CHANGE_DATE) / %s)" " order by 3, 1 " % (var_ids, min_x_q, max_x_q, zoom_step) ): ind = series.index(row[2]) chart_data[ind] += [row] if row[0] > min_x and row[0] < max_x: max_y = max(max_y, row[1]) min_y = min(min_y, row[1]) if tt == -100: tt = row[2] if tt != row[2]: v = [tt, mi_x, ma_x] x_min_max_values += [v] mi_x = max_x_q ma_x = min_x_q tt = row[2] if row[0] < mi_x: mi_x = row[0] if row[0] > ma_x: ma_x = row[0] if tt != -1: v = [tt, mi_x, ma_x] x_min_max_values += [v] # print(x_min_max_values) # print(series) """ for row in self.db.select("select UNIX_TIMESTAMP(CHANGE_DATE) D, VALUE, VARIABLE_ID, ID " " from core_variable_changes " " where VARIABLE_ID in (" + var_ids + ") " " and CHANGE_DATE >= FROM_UNIXTIME(%s) " " and CHANGE_DATE <= FROM_UNIXTIME(%s) " "order by CHANGE_DATE " % (min_x_q, max_x_q)): """ """ try: self.db.IUD("set @rn := 0") sql = ("select UNIX_TIMESTAMP(CHANGE_DATE) D, VALUE, VARIABLE_ID, ID " " from core_variable_changes " " where VARIABLE_ID in (" + var_ids + ") " " and CHANGE_DATE >= FROM_UNIXTIME(%s) " " and CHANGE_DATE <= FROM_UNIXTIME(%s) " "order by CHANGE_DATE " % (min_x_q, max_x_q)) for c in self.db.select("select count(*) c " " from core_variable_changes " " where VARIABLE_ID in (" + var_ids + ") " " and CHANGE_DATE >= FROM_UNIXTIME(%s) " " and CHANGE_DATE <= FROM_UNIXTIME(%s) " % (min_x_q, max_x_q)): cou = c[0] ccc = 1000 * 4 if cou > ccc: sql = ("select UNIX_TIMESTAMP(CHANGE_DATE) D, VALUE, VARIABLE_ID, ID, @rn := @rn + 1 rownum " " from core_variable_changes " " where VARIABLE_ID in (" + var_ids + ") " " and CHANGE_DATE >= FROM_UNIXTIME(%s) " " and CHANGE_DATE <= FROM_UNIXTIME(%s) " "having mod(rownum, %s) = 0 " "order by VARIABLE_ID, CHANGE_DATE " % (min_x_q, max_x_q, math.ceil(cou / ccc))) for row in self.db.select(sql): ind = series.index(row[2]) prev_vals[ind] = row[1] if abs(prev_vals[ind] - row[1]) < 10: chart_data[ind] += [row] if row[0] > min_x and row[0] < max_x: max_y = max(max_y, row[1]) min_y = min(min_y, row[1]) prev_vals[ind] = row[1] except: pass """ if min_y is None or max_y is None or min_y == 9999 or max_y == -9999 or min_y == max_y: max_y = 1 min_y = 0 min_y = math.floor(min_y) max_y = math.ceil(max_y) if typ == 2: if min_y < 0 and max_y < 0: max_y = 0 elif min_y > 0 and max_y > 0: min_y = 0 # Определяем цвета colors = [[1, 0, 0], [0, 0.65, 0.31], [0, 0, 1], [1, 0, 1]] off_y = (max_y - min_y) / 10 min_y -= off_y max_y += off_y try: kx = (max_x - min_x) / (width - left - right) ky = (max_y - min_y) / (height - bottom) if ky == 0: ky = 1 except: kx, ky = 1, 1 img = ImageSurface(FORMAT_ARGB32, width, height) ctx = Context(img) width -= right ctx.set_line_width(1) # Рисуем сетку ctx.set_font_size(12) try: b_w, b_h = ctx.text_extents("00-00-0000")[2:4] # Метки на оси Y count = math.ceil(max_y) - math.ceil(min_y) space_count = math.ceil(count / ((height - bottom) / (b_h * 1.5))) sc = 0 for i in range(math.ceil(min_y), math.ceil(max_y)): if sc == 0: y = height - bottom + (min_y - i) / ky ctx.set_source_rgb(*(color_x_line)) ctx.move_to(left, y) ctx.line_to(width, y) ctx.stroke() ctx.set_source_rgb(0, 0, 0) num = str(i) tw, th = ctx.text_extents(num)[2:4] ctx.move_to(left - 5 - tw, y + th // 2) ctx.show_text(num) sc = space_count sc -= 1 # Метки на оси Х x_step = 3600 if interval == "-6 hour" or interval == "-12 hour" or interval == "-1 day": # Дополнительно метки часов x_step = 3600 for i in range(math.ceil(min_x / x_step), math.ceil(max_x / x_step)): x = (i * x_step - min_x) / kx + left ctx.set_source_rgb(*(color_x_line_2)) ctx.move_to(x, 0) ctx.line_to(x, height - bottom) ctx.stroke() num = datetime.datetime.fromtimestamp(i * x_step).strftime("%H") tw, th = ctx.text_extents(num)[2:4] ctx.move_to(x + 2, height - bottom - 3) ctx.set_source_rgb(*(color_x_line)) ctx.show_text(num) x_step = 3600 * 24 space_count = 1 count = math.ceil(max_x / x_step) - math.ceil(min_x / x_step) try: if (width / count) < b_w: space_count = 2 except: pass sc = 0 tz = 3600 * 2 tx_prev = -100 for i in range(math.ceil(min_x / x_step), math.ceil(max_x / x_step) + 1): if sc == 0: d_i = datetime.datetime.fromtimestamp(i * x_step) x = (i * x_step - min_x - tz) / kx + left ctx.set_source_rgb(0, 0, 0) num = d_i.strftime("%d-%m-%Y %H") x -= (int(d_i.strftime("%H")) * 3600 - tz) / kx tw, th = ctx.text_extents(num)[2:4] tx = x - tw // 2 ctx.move_to(tx, height - bottom + th + 5) if tx - tx_prev > tw: ctx.show_text(num) tx_prev = tx ctx.set_source_rgb(*(color_y_line_date)) else: ctx.set_source_rgb(*(color_y_line)) if x >= left and x < width: ctx.move_to(x, 0) ctx.line_to(x, height - bottom) ctx.stroke() sc = space_count sc -= 1 except Exception as e: pass # Рисуем верхний и правый бордер ctx.set_source_rgb(*color_border) ctx.move_to(left, 0) ctx.line_to(width, 0) ctx.line_to(width, height - bottom) ctx.stroke() # Рисуем сами графики ctx.rectangle(left, 0, width - left, height) ctx.clip() is_first = True currVarID = -1 prevX = -1 if typ == 0: # Линейная for ind in range(4): """ if len(chart_data[ind]) > 0: for i in range(len(chart_data[ind]) - 1): chart_data[ind][i] = list(chart_data[ind][i]) r1 = chart_data[ind][i] r2 = chart_data[ind][i + 1] chart_data[ind][i][0] += (r2[0] - r1[0]) / 2 chart_data[ind][i][1] += (r2[1] - r1[1]) / 2 """ ctx.set_source_rgb(*colors[ind]) is_first = True for row in chart_data[ind]: x = (row[0] - min_x) / kx + left y = height - bottom - (row[1] - min_y) / ky if is_first: ctx.move_to(x, y) else: if row[0] - prevX > 10000: ctx.move_to(x, y) else: ctx.line_to(x, y) prevX = row[0] is_first = False ctx.stroke() elif typ == 1: # Точечная for ind in range(4): if chart_data[ind]: ctx.set_source_rgb(*colors[ind]) for row in chart_data[ind]: x = (row[0] - min_x) / kx + left y = height - bottom - (row[1] - min_y) / ky ctx.rectangle(x - 3, y - 3, 6, 6) ctx.fill() elif typ == 2: # Столбчатая cy = height - bottom - (-min_y) / ky for ind in range(4): for row in chart_data[ind]: if currVarID != row[2]: ctx.fill() for i in range(4): if series[i] == row[2]: ctx.set_source_rgb(*colors[i]) x = (row[0] - min_x) / kx + left y = height - bottom - (row[1] - min_y) / ky ctx.rectangle(x - 5, y, 10, cy - y) currVarID = row[2] ctx.fill() else: # Линейчастая # one_vals = self._get_one_val(series, min_x_q, max_x_q) one_vals = self._get_one_val(series, x_min_max_values, min_x_q, max_x_q) for ind in range(4): if series[ind]: is_now = True for r in one_vals[ind]: if r[4] == 1: chart_data[ind].insert(0, r) else: chart_data[ind] += [r] is_now = False if is_now: if len(chart_data[ind]) > 0: r = list(chart_data[ind][len(chart_data[ind]) - 1]) r[0] = datetime.datetime.now().timestamp() chart_data[ind] += [r] color = colors[ind] color_fill = color.copy() color_fill += [0.3] is_first = True y0 = height - bottom + min_y / ky for row in chart_data[ind]: x = (row[0] - min_x) / kx + left y = height - bottom - (row[1] - min_y) / ky if is_first: is_first = False else: ctx.set_source_rgb(*color) ctx.move_to(prevX, prevY) ctx.line_to(x, prevY) ctx.line_to(x, y) ctx.stroke() ctx.set_source_rgba(*color_fill) rx, ry, rw, rh = prevX, y0, x - prevX, prevY - y0 ctx.rectangle(rx, ry, rw, rh) ctx.fill() prevX, prevY = x, y # Рисуем оси ctx.set_source_rgb(0, 0, 0) ctx.move_to(left, 0) ctx.line_to(left, height - bottom) ctx.line_to(width, height - bottom) ctx.stroke() # --------------------------- del ctx byt = BytesIO() img.write_to_png(byt) byt.seek(0) return byt.read()
codes.extend([ CURVE3, CURVE3]) verts.append(segment[-1]) codes.append(CURVE3) [tags.pop() for x in range(len(segment) - 1)] VERTS.extend(verts) CODES.extend(codes) start = end+1 # Draw glyph ctx.new_path() ctx.set_source_rgba(0.8,0.5,0.8, 1) i = 0 while (i < len(CODES)): if (CODES[i] == MOVETO): ctx.move_to(VERTS[i][0],VERTS[i][1]) i += 1 elif (CODES[i] == LINETO): ctx.line_to(VERTS[i][0],VERTS[i][1]) i += 1 elif (CODES[i] == CURVE3): ctx.curve_to(VERTS[i][0],VERTS[i][1], VERTS[i+1][0],VERTS[i+1][1], # undocumented VERTS[i+1][0],VERTS[i+1][1]) i += 2 elif (CODES[i] == CURVE4): ctx.curve_to(VERTS[i][0],VERTS[i][1], VERTS[i+1][0],VERTS[i+1][1], VERTS[i+2][0],VERTS[i+2][1]) i += 3 ctx.fill_preserve()