Example #1
0
    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))
Example #2
0
    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()
Example #3
0
    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)
Example #5
0
    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()
Example #6
0
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()
Example #7
0
    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()
Example #8
0
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()
Example #9
0
    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()
Example #10
0
    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()
Example #11
0
 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()
Example #12
0
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()
Example #13
0
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
Example #14
0
 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}")
Example #15
0
    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)
Example #16
0
    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()
Example #17
0
 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()
Example #18
0
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()
Example #19
0
    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()
Example #20
0
    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()
Example #21
0
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()
Example #22
0
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()
Example #24
0
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()
Example #25
0
 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)
Example #26
0
    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)
Example #27
0
 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.")
Example #28
0
 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()
Example #30
0
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)
Example #31
0
    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
Example #32
0
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)
Example #33
0
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()
Example #34
0
 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."))
Example #35
0
 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)
Example #36
0
 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)
Example #37
0
    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
Example #38
0
    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)
Example #39
0
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()
Example #40
0
    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()
Example #41
0
    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()
Example #42
0
    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)
Example #43
0
    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
Example #44
0
    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()
Example #45
0
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
Example #46
0
 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)
Example #47
0
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
Example #48
0
    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()