def draw_text(self, g: Graphics, component: Label, font: FontFace, color: RGBA) -> None: text = component.text size = component.text_size extents = component.context.toolkit.fonts.text_extent(text, font, size) padding = component.resolve_insets(StyleKeys.Padding).value_or( Insets(0, 0, 0, 0)) (x, y, w, h) = component.bounds.tuple rh = self._ratio_for_align[component.text_align] rv = self._ratio_for_align[component.text_vertical_align] tx = (w - extents.width - padding.left - padding.right) * rh + x + padding.left ty = (h - extents.height - padding.top - padding.bottom) * rv + extents.height + y + padding.top g.set_font_face(font) g.set_font_size(size) # FIXME: Temporary workaround until we get a better way of handling text shadows. if component.shadow: g.move_to(tx + 1, ty + 1) g.set_source_rgba(0, 0, 0, 0.8) g.show_text(text) g.move_to(tx, ty) g.set_source_rgba(color.r, color.g, color.b, color.a) g.show_text(text)
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
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
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()
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()
def draw_text(ctx: Context, text: str, x: float, y: float, scale: float): original = ctx.get_matrix() ctx.translate(x, y) ctx.scale(scale / 10) # Default font size is 10 mm (1cm) ctx.show_text(text) ctx.set_matrix(original)
y = mean_pin_y - label_height // 2 print(f"{text=}\t{y=}") if pass_ == 0: ctx.set_source_rgba(*color, 1) draw_rounded_rectangle(ctx, x, y, label_width, label_height, label_radius) ctx.fill() for pin_name in pin_names: pin_x, pin_y, align = pin_defs[pin_name] pin_x = pin_x * w pin_y = pin_y * h_bg - h_bg * y_offset ctx.move_to(line_origin_x, y + label_height // 2) ctx.line_to(w * pad_sides + pin_x, pin_y) ctx.set_line_width(4) ctx.stroke() else: ctx.move_to(x + label_pad[0] - x_bearing, y - y_bearing + label_pad[1]) ctx.set_source_rgb(1, 1, 1) ctx.show_text(text) # save to file canvas.write_to_png(f"{board_name}_{variant_name}.png") # stride = ImageSurface.format_stride_for_width(format, width) # data = bytearray(stride * height) # surface = ImageSurface(format, width, height, data, stride)