Ejemplo n.º 1
0
def _(d: Line, ctx: cairo.Context, scale: float):
    ctx.save()
    ctx.move_to(d.x0 * scale, d.y0 * scale)
    ctx.line_to(d.x1 * scale, d.y1 * scale)
    ctx.stroke()
    # ctx.fill()
    ctx.restore()
Ejemplo n.º 2
0
def export_svg(fn, paths, size, line_with=0.1, scale_factor=None):

  from cairocffi 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()
Ejemplo n.º 3
0
def draw_elements(elements: Sequence[Element], ctx: cairo.Context,
                  scale: float):
    ctx.save()
    for element in elements:
        if element.drawing is not None:
            draw(element.drawing, ctx, scale)
        ctx.translate(element.thickness * scale, 0)
    ctx.restore()
Ejemplo n.º 4
0
 def paint_children(self, ctx: Context):
     for child in self.children:
         ctx.save()
         ctx.translate(*child.position(Anchor.TOP_LEFT))
         ctx.rectangle(0, 0, *child.size)
         ctx.clip()
         child.paint(ctx)
         ctx.restore()
Ejemplo n.º 5
0
def draw_ray_trace(r0: Sequence[float], elements: Sequence[Element],
                   ctx: cairo.Context, scale: float):
    ctx.save()
    r = r0
    for element in elements:
        ctx.move_to(0, r[0] * scale)
        ctx.translate(element.thickness * scale, 0)
        rp = element.matrix.dot(r)
        ctx.line_to(0, rp[0] * scale)
        ctx.stroke()
        r = rp
    ctx.restore()
Ejemplo n.º 6
0
 def draw(self, ctx: Context, surface: Surface):
     ctx.save()
     ctx.translate(self.translate_x, self.translate_y)
     ctx.rotate(self.rotation)
     ctx.scale(self.width / self.svg_width, self.height / self.svg_height)
     ctx.translate(-self.origin_x, -self.origin_y)
     CairoSVGSurface(self.tree,
                     None,
                     96,
                     output_cairo=surface,
                     output_cairo_context=ctx)
     ctx.restore()
Ejemplo n.º 7
0
    def draw(self, context: Context):
        text_path_glyph_items = self._compute_text_path_glyph_items()
        for text_path_glyph_item in text_path_glyph_items:
            glyph_position = text_path_glyph_item.position
            glyph_rotation = text_path_glyph_item.rotation

            context.save()
            context.translate(glyph_position.x, glyph_position.y)
            context.rotate(glyph_rotation)
            show_glyph_item(context, self._layout_text,
                            text_path_glyph_item.glyph_item)
            context.restore()
Ejemplo n.º 8
0
    def draw(self, ctx: Context):

        text_baseline = self.get_text_baseline(ctx)

        default_font_max_height = ctx.get_scaled_font().extents()[0]

        text_max_length = float('inf')
        line_string_bottom_length = text_baseline.length

        trimmed = False
        while text_max_length > line_string_bottom_length:
            text_max_length = ctx.text_extents(self.text)[4] / default_font_max_height * self.text_height + \
                              (len(self.text)-1) * self.text_spacing
            if text_max_length > line_string_bottom_length:
                self.text = self.text[:-1].strip()
                trimmed = True

        text_start_interp_pos_min = 0
        text_start_interp_pos_max = line_string_bottom_length - text_max_length
        if self.text_alignment == 'left':
            text_start_interp_pos = self.text_alignment_offset
        elif self.text_alignment == 'center':
            text_start_interp_pos = line_string_bottom_length / 2 - text_max_length / 2 - self.text_alignment_offset
        else:
            text_start_interp_pos = line_string_bottom_length - text_max_length - self.text_alignment_offset
        text_start_interp_pos = min(
            text_start_interp_pos_max,
            max(text_start_interp_pos_min, text_start_interp_pos))

        text_interp_pos = text_start_interp_pos
        for char in self.text:
            char_pos_origin = text_baseline.interpolate(text_interp_pos)
            char_advance_x = ctx.text_extents(
                char)[4] / default_font_max_height * self.text_height
            char_pos_end = text_baseline.interpolate(text_interp_pos +
                                                     char_advance_x)

            ctx.save()
            ctx.translate(char_pos_origin.x, char_pos_origin.y)
            text_angle = math.atan2(char_pos_end.y - char_pos_origin.y,
                                    char_pos_end.x - char_pos_origin.x)
            ctx.rotate(text_angle)
            ctx.scale(1 / default_font_max_height * self.text_height)
            if not trimmed:
                ctx.set_source_rgba(0, 0, 0, 1)
            else:
                ctx.set_source_rgba(0, 0, 0.2, 1)
            ctx.show_text(char)
            ctx.fill()
            ctx.restore()

            text_interp_pos += char_advance_x + self.text_spacing
Ejemplo n.º 9
0
def render_cluster_glyph_items(
        ctx: cairocffi.Context,
        layout: pangocffi.Layout
):
    """
    Renders each cluster within a layout with a unique rotation and color.

    Warning: Does not support bidirectional text.

    :param ctx:
        a Cairo context
    :param layout:
        a Pango layout
    """
    layout_run_iter = layout.get_iter()
    layout_cluster_iter = layout.get_iter()
    layout_text = layout.get_text()

    alternate = False
    while True:

        layout_run = layout_run_iter.get_run()
        layout_line_baseline = layout_run_iter.get_baseline()

        if layout_run is None:
            if not layout_run_iter.next_run():
                break
            continue

        clusters = get_clusters_from_glyph_item(layout_run, layout_text)
        for cluster in clusters:
            cluster_extents = layout_cluster_iter.get_cluster_extents()[1]
            layout_cluster_iter.next_cluster()
            alternate = not alternate
            ctx.set_source_rgba(0.5, 0, 1 if alternate else 0.5, 0.9)
            ctx.save()
            ctx.translate(
                pangocffi.units_to_double(cluster_extents.x),
                pangocffi.units_to_double(layout_line_baseline)
            )
            ctx.rotate(-0.05 if alternate else 0.05)
            pangocairocffi.show_glyph_item(
                ctx,
                layout_text,
                cluster
            )
            ctx.restore()

        if not layout_run_iter.next_run():
            break
Ejemplo n.º 10
0
def label_train_interfaces(ctx: cairo.Context,
                           train: trains.Train,
                           radius_factors=1,
                           broken_spaces: Sequence = None):
    spaces, brokens = break_spaces(train.spaces, broken_spaces)
    radius_factors = np.broadcast_to(radius_factors, (len(train.interfaces), ))

    ctx.save()
    ctx.translate(0, spaces[0])
    for interface, space, radius_factor in zip(train.interfaces, spaces[1:],
                                               radius_factors):
        label_interface(ctx, interface, radius_factor)
        ctx.translate(0, space)
    ctx.restore()
Ejemplo n.º 11
0
def make_train_spaces(ctx: cairo.Context,
                      train: trains.Train,
                      broken_spaces: Sequence = None,
                      frac: float = 1 / 4):
    spaces, brokens = break_spaces(train.spaces, broken_spaces)

    ctx.save()

    radius = train.interfaces[
        0].radius  # if len(self.interfaces) > 0 else self.spaces[0]
    y_next = 0
    xys_last = np.asarray([[-radius, 0], [radius, 0]])
    n = train.interfaces[0].n1
    for space, next_interface, broken in zip(spaces,
                                             train.interfaces + (None, ),
                                             brokens):
        ctx.set_source_rgba(*index_colors.get(n.name, (0, 0, 1, 1)))

        y_next += space

        # Generate next interface points.
        if next_interface is None:
            xys_next = np.asarray([[-radius, 0], [radius, 0]])
        else:
            xys_next = next_interface.get_points()

        xys_next += [0, y_next]
        if broken:
            num = 8
            n = np.arange(num + 1)
            jagged = np.c_[2 * (n / num - 0.5) * radius,
                           (n % 2) * space * frac + y_next - space / 2]

            xys = np.r_[xys_last, jagged[::-1, :] - (0, space * frac)]
            draw_polyline(ctx, xys)
            ctx.fill()

            xys = np.r_[jagged, xys_next[::-1, :]]
            draw_polyline(ctx, xys)
            ctx.fill()
        else:
            xys = np.r_[xys_last, xys_next[::-1, :]]
            draw_polyline(ctx, xys)
            ctx.fill()

        xys_last = xys_next
        if next_interface is not None:
            n = next_interface.n2
    ctx.restore()
Ejemplo n.º 12
0
def make_train_interfaces(ctx: cairo.Context,
                          train: trains.Train,
                          broken_spaces: Sequence = None):
    """
    Propagation is along positive y axis, starting from origin.

    Args:
        size (scalar): Full transverse dimension of interfaces.
    """
    spaces, brokens = break_spaces(train.spaces, broken_spaces)

    ctx.save()
    ctx.translate(0, spaces[0])
    for interface, space in zip(train.interfaces, spaces[1:]):
        make_interface(ctx, interface)
        ctx.translate(0, space)
    ctx.restore()
Ejemplo n.º 13
0
def label_train_spaces(ctx: cairo.Context,
                       train: trains.Train,
                       radius_factors=1,
                       broken_spaces: Sequence = None):
    """Draw material name and thickness of the spaces.

    Args:
        radius_factors (scalar or sequence): Factor by which the average interface radii is multiplied to place the text. If
            a scalar is given it is broadcast.
    """
    spaces, brokens = break_spaces(train.spaces, broken_spaces)
    radius_factors = np.broadcast_to(radius_factors, (len(spaces), ))
    radius_last = train.interfaces[0].radius
    y_last = 0
    h_last = 0
    n = train.interfaces[0].n1
    for space, next_interface, radius_factor in zip(
            spaces, train.interfaces + (None, ), radius_factors):
        if next_interface is None:
            radius_next = radius_last
            h_next = 0
        else:
            radius_next = next_interface.radius
            h_next = functions.calc_sphere_sag(next_interface.roc, radius_next)
        y_next = y_last + space
        if space != 0:
            string = '%.3f mm %s' % (space * 1e3, n.name)
            radius = (radius_last + radius_next) / 2
            x = radius_factor * radius
            y = (y_next + h_next + y_last + h_last) / 2

            ctx.save()
            ctx.translate(x, y)
            ctx.show_text(string)
            ctx.new_path()
            ctx.restore()

            if radius_factor > 1:
                draw_polyline(ctx, ((radius, y), (x, y)))
                ctx.stroke()

        y_last = y_next
        h_last = h_next
        if next_interface is not None:
            n = next_interface.n2
            radius_last = next_interface.radius
Ejemplo n.º 14
0
    def draw_children(self, g: Graphics) -> None:
        ui = cast(ContainerUI, self.ui)

        (cx, cy, cw, ch) = ui.content_bounds(self).tuple

        g.save()

        g.rectangle(cx, cy, cw, ch)
        g.clip()

        try:
            # noinspection PyTypeChecker
            for child in self.children:
                child.draw(g)
        except BaseException as e:
            self.error_handler(e)

        g.restore()
Ejemplo n.º 15
0
    def draw(self, g: Graphics) -> None:
        if self.visible:
            g.save()

            (dx,
             dy) = self.parent.map(lambda p: p.location).value_or(Point(0, 0))
            (cx, cy, cw, ch) = self.ui.clip_bounds(self).tuple

            g.translate(dx, dy)
            g.rectangle(cx, cy, cw, ch)

            g.clip()

            try:
                self.draw_component(g)
            except BaseException as e:
                self.error_handler(e)

            g.restore()
    def __draw_sector (self: 'HueSatWheelWidget', cr: cairocffi.Context,
                       center_x: float, center_y: float) -> None:
        cr.save ()
        cr.set_line_width (1)

        offset = self.rotation

        for idx, sector in enumerate (self.sector[0]):
            half_angle = 2 * numpy.pi * sector / 2
            offset += self.sector[1][idx] * 2 * numpy.pi
            cr.set_source_rgba (0, 0, 0, 1)
            cr.move_to (center_x, center_y)
            cr.arc (center_x, center_y, (self.size - 2) / 2.,
                    offset - half_angle, half_angle + offset)
            cr.line_to (center_x, center_y)
            cr.stroke_preserve ()
            cr.set_source_rgba (0, 0, 0, 0.25)
            cr.fill ()

        cr.restore ()
Ejemplo n.º 17
0
def label_interface(ctx: cairo.Context,
                    face: trains.Interface,
                    radius_factor=1):
    """Draw text saying ROC, and a line from the edge of the interface to the text.

    Args:
        radius_factor (scalar): Factor by which interface radius is multiplied to get text x position.
    """
    x = radius_factor * face.radius
    y = functions.calc_sphere_sag(face.roc, face.radius)
    string = 'ROC %.3f mm' % (face.roc * 1e3)
    ctx.set_source_rgb(0, 0, 0)
    ctx.save()
    ctx.translate(x, y)
    ctx.show_text(string)
    ctx.new_path()
    ctx.restore()
    if radius_factor > 1:
        draw_polyline(ctx, ((face.radius, y), (x, y)))
        ctx.stroke()
Ejemplo n.º 18
0
def render_run_glyph_items(
        ctx: cairocffi.Context,
        layout: pangocffi.Layout
) -> None:
    """
    Renders each layout run within a layout with a unique rotation and color.

    :param ctx:
        a Cairo context
    :param layout:
        a Pango layout
    """
    layout_iter = layout.get_iter()
    layout_text = layout.get_text()

    alternate = False
    while True:
        layout_run = layout_iter.get_run()
        layout_run_extents = layout_iter.get_run_extents()[1]
        layout_line_baseline = layout_iter.get_baseline()

        if layout_run is None:
            if not layout_iter.next_run():
                break
            continue

        alternate = not alternate
        ctx.set_source_rgba(0, 0.5, 1 if alternate else 0.5, 0.9)
        ctx.save()
        ctx.translate(
            pangocffi.units_to_double(layout_run_extents.x),
            pangocffi.units_to_double(layout_line_baseline)
        )
        ctx.rotate(0.05 if alternate else -0.05)
        pangocairocffi.show_glyph_item(ctx, layout_text, layout_run)
        ctx.restore()

        if not layout_iter.next_run():
            break
Ejemplo n.º 19
0
 def _generate_layer(self, transcription, page, layer):
     surface = PDFSurface(layer, *page.page_size)
     context = Context(surface)
     # context.select_font_face('Georgia')
     context.set_source_rgba(1, 1, 1, 1 / 256)  # almost invisible
     context.set_font_size(2)
     for line_ink, line_transcription in zip(page.lines, transcription):
         ink, transformation = writing.normalized(line_ink)
         context.save()
         context.transform(
             Matrix(*(Transformation.translation(
                 0, page.page_size[1]).parameter)))
         context.transform(Matrix(*(Transformation.mirror(0).parameter)))
         context.transform(Matrix(*((~transformation).parameter)))
         context.transform(Matrix(*(Transformation.mirror(0).parameter)))
         HANDWRITING_WIDTH = ink.boundary_box[1]
         TYPEWRITING_WIDTH = context.text_extents(line_transcription)[2]
         context.scale(HANDWRITING_WIDTH / TYPEWRITING_WIDTH, 1)
         context.move_to(0, 0)
         context.show_text(line_transcription)
         context.restore()
     context.stroke()
     context.show_page()
     surface.flush()
Ejemplo n.º 20
0
def _(d: Arc, ctx: cairo.Context, scale: float):
    ctx.save()
    ctx.arc(d.xc * scale, d.yc * scale, d.radius * scale, d.theta0, d.theta1)
    ctx.stroke()
    ctx.restore()
Ejemplo n.º 21
0
def _(d: Scaling, ctx: cairo.Context, scale: float):
    ctx.save()
    ctx.scale(d.x, d.y)
    draw(d.child, ctx, scale)
    ctx.restore()
Ejemplo n.º 22
0
def _(d: Translation, ctx: cairo.Context, scale: float):
    ctx.save()
    ctx.translate(d.x * scale, d.y * scale)
    draw(d.child, ctx, scale)
    ctx.restore()
Ejemplo n.º 23
0
def ctx_scope(ctx: cairo.Context):
    try:
        ctx.save()
        yield ctx
    finally:
        ctx.restore()
    def __draw_ring (self: 'HueSatWheelWidget', cr: cairocffi.Context,
                     width: int, height: int, center_x: float, center_y: float,
                     outer: float, inner: float) -> None:
        self.__redraw = False
        stride = cairocffi.ImageSurface.format_stride_for_width (cairocffi.FORMAT_ARGB32, width)
        buf = numpy.empty (int (height * stride), dtype = numpy.uint8)

        for y in range (height):
            idx = y * width * 4

            dy = -(y - center_y)

            for x in range (width):
                dx = x - center_x

                dist = dx * dx + dy * dy

                angle = math.atan2 (dy, dx)

                if angle < 0:
                    angle += 2 * numpy.pi

                hue = angle / (2 * numpy.pi)

                hue_idx = int ((angle + 2 * numpy.pi / 3) / (2 * numpy.pi) * 255)
                hue_idx = hue_idx % 256

                if dist < ((inner - 1) ** 2) * (1 - self.__hist[255 - hue_idx]) or \
                   dist > ((outer + 1) ** 2):
                    buf[idx + 0] = 0
                    buf[idx + 1] = 0
                    buf[idx + 2] = 0
                    buf[idx + 3] = 0
                    idx += 4
                    continue

                r, g, b = colorsys.hsv_to_rgb (hue, 1.0, 1.0)
                a = 255

                buf[idx + 0] = int (math.floor (r * 255 + 0.5))
                buf[idx + 1] = int (math.floor (g * 255 + 0.5))
                buf[idx + 2] = int (math.floor (b * 255 + 0.5))
                buf[idx + 3] = a
                idx += 4

        source = cairocffi.ImageSurface.create_for_data (
            memoryview (buf), cairocffi.FORMAT_ARGB32, width, height, stride
        )

        fg_color = self.get_style_context ().get_color (Gtk.StateFlags.NORMAL)

        cr.save ()

        cr.set_source_rgba (0, 0, 0, 0)
        cr.paint ()

        cr.set_source_surface (source, 0, 0)
        cr.paint ()

        cr.set_line_width (1)
        cr.new_path ()
        cr.set_source_rgba (*list (fg_color))

        cr.arc (center_x, center_y, (self.size - 4) / 2. - self.ring_width,
                0, 2 * numpy.pi)
        cr.stroke ()

        cr.arc (center_x, center_y, (self.size - 2) / 2, 0, 2 * numpy.pi)
        cr.stroke ()

        cr.arc (center_x, center_y, 5, 0, 2 * numpy.pi)
        cr.fill ()

        cr.restore ()
Ejemplo n.º 25
0
 def draw(self, ctx: Context, surface: Surface):
     ctx.save()
     ctx.translate(self.position_x, self.position_y)
     ctx.scale(self.width / self.svg_width, self.height / self.svg_height)
     CairoSVGSurface(self.tree, surface, ctx, 96)
     ctx.restore()