def draw_text( self, rect, x, y, parsed_text, style: TextStyle, styles, rotation=None, scale=None, **kwargs, ): # TODO: try basic Cairo text API with ctx_scope(self.ctx): layout = build_layout( self.reference_ctx, self.pctx, parsed_text, style, styles, resolution_scale=RESOLUTION_SCALE, spacing_scale=self.line_scaling, text_scale=scale, ) layout.set_width(to_pango_units(rect.width)) baseline = from_pango_units(layout.get_baseline()) if rotation is not None: transform(self.ctx, rect.mid_point, rotation=rotation) self.ctx.move_to(rect.x, y - baseline) pangocairocffi.show_layout(self.ctx, layout)
def test_pdf(): filename = 'tests/output/glyph_item.pdf' pt_per_mm = 72 / 25.4 width, height = 210 * pt_per_mm, 297 * pt_per_mm # A4 portrait surface = cairocffi.PDFSurface(filename, width, height) ctx = cairocffi.Context(surface) ctx.translate(width / 4, 100) layout = pangocairocffi.create_layout(ctx) layout.set_width(pangocffi.units_from_double(width / 2)) layout.set_alignment(pangocffi.Alignment.CENTER) layout.set_markup( '<span font="italic 30">Hi from Παν語</span>\n' '<span font="sans-serif">The text layout engine library for ' 'displaying <span font-weight="bold">multi-language</span> text!\n' 'Arabic: السَّلام عليكُم\n' 'Hebrew: שלום\n' 'Hindi नमस्ते, नमस्कार।\n' 'Russian: Здравствуйте!\n' 'Japanese: こんにちは, コンニチハ</span>' ) y_diff = 200 pangocairocffi.show_layout(ctx, layout) ctx.translate(0, y_diff) render_run_glyph_items(ctx, layout) ctx.translate(0, y_diff) render_cluster_glyph_items(ctx, layout) surface.finish()
def test_pdf(): filename = 'tests/output/error_underline.pdf' pt_per_mm = 72 / 25.4 width, height = 45 * pt_per_mm, 10 * pt_per_mm # A4 portrait surface = cairocffi.PDFSurface(filename, width, height) ctx = cairocffi.Context(surface) layout = pangocairocffi.create_layout(ctx) layout.set_width(pangocffi.units_from_double(width)) layout.set_alignment(pangocffi.Alignment.CENTER) layout.set_markup('Hi from Παν語') layout_logical_extent = layout.get_extents()[1] layout_baseline = pangocffi.units_to_double(layout.get_baseline()) layout_logical_extent_pixels = _convert_rectangle_to_pixels( layout_logical_extent) pangocairocffi.show_layout(ctx, layout) ctx.set_source_rgb(0.8, 0, 0) pangocairocffi.show_error_underline(ctx, layout_logical_extent_pixels[0], layout_baseline, layout_logical_extent_pixels[2], 2) surface.finish()
def draw(self, canvas: Canvas): for pango_object in self.pango_objects: canvas.context.save() canvas.context.translate(*pango_object.position.pt) canvas.context.set_source_rgba(*pango_object.color) pangocairocffi.show_layout(canvas.context, pango_object.pango_layout) canvas.context.restore()
def draw(text, width=-1): text = html.escape(text) if bold: text = f'<b>{text}</b>' layout.set_width( (width - COLUMN_MARGIN) * 1000) # pixel = 1000 pango units layout.set_markup(text, -1) PangoCairo.show_layout(context, layout) context.rel_move_to(width, 0)
def write_text(ctx, text, start_x, start_y): ctx.move_to(start_x, start_y) layout = pangocairocffi.create_layout(ctx) layout.set_width(pangocffi.units_from_double(width)) #layout.set_alignment(pangocffi.Alignment.CENTER) fontdesc = pangocffi.FontDescription() fontdesc.set_size(pangocffi.units_from_double(3)) fontdesc.set_family(font_family) layout.set_font_description(fontdesc) layout.set_text(text) pangocairocffi.show_layout(ctx, layout)
def _show_label( context: cairocffi.Context, position: Tuple[float, float], width: float, text: str ): context.translate(position[0], position[1]) label = pangocairocffi.create_layout(context) label.set_width(pangocffi.units_from_double(width)) label.set_alignment(pangocffi.Alignment.LEFT) label.set_markup('<span font-family="sans-serif">%s</span>' % text) pangocairocffi.show_layout(context, label) context.translate(-position[0], -position[1])
def text2svg(self): """Internally used function. Convert the text to SVG using Pango """ size = self.size * 10 line_spacing = self.line_spacing * 10 dir_name = config.get_dir("text_dir") disable_liga = self.disable_ligatures if not os.path.exists(dir_name): os.makedirs(dir_name) hash_name = self.text2hash() file_name = os.path.join(dir_name, hash_name) + ".svg" if os.path.exists(file_name): return file_name surface = cairocffi.SVGSurface(file_name, 600, 400) context = cairocffi.Context(surface) context.move_to(START_X, START_Y) settings = self.text2settings() offset_x = 0 last_line_num = 0 layout = pangocairocffi.create_layout(context) layout.set_width(pangocffi.units_from_double(600)) for setting in settings: family = setting.font style = self.str2style(setting.slant) weight = self.str2weight(setting.weight) text = self.text[setting.start : setting.end].replace("\n", " ") fontdesc = pangocffi.FontDescription() fontdesc.set_size(pangocffi.units_from_double(size)) if family: fontdesc.set_family(family) fontdesc.set_style(style) fontdesc.set_weight(weight) layout.set_font_description(fontdesc) if setting.line_num != last_line_num: offset_x = 0 last_line_num = setting.line_num context.move_to( START_X + offset_x, START_Y + line_spacing * setting.line_num ) pangocairocffi.update_layout(context, layout) if disable_liga: text = escape(text) layout.set_markup(f"<span font_features='liga=0'>{text}</span>") else: layout.set_text(text) logger.debug(f"Setting Text {text}") pangocairocffi.show_layout(context, layout) offset_x += pangocffi.units_to_double(layout.get_size()[0]) surface.finish() return file_name
def render_text(self, content: FormattedText, width): fontn = pango.FontDescription() fontn.set_family(content.font_family) fontn.set_size(pango.units_from_double(content.font_size)) self.pango_context.set_font_description(fontn) layout = pango.layout.Layout(self.pango_context) layout.set_text(content.text) if content.alignment == 'l': layout.set_alignment(pango.Alignment.LEFT) elif content.alignment == 'c': layout.set_alignment(pango.Alignment.CENTER) elif content.alignment == 'r': layout.set_alignment(pango.Alignment.RIGHT) layout.set_width(pango.units_from_double(width)) pc.update_layout(self.cairo_context, layout) pc.show_layout(self.cairo_context, layout)
def test_t2s() -> None: size = 1 temp_pango_text = Text("Helloworld", t2s={"world": ITALIC}) surface = cairocffi.SVGSurface(filename, WIDTH, HEIGTH) context = cairocffi.Context(surface) context.move_to(START_X, START_Y) layout = pangocairocffi.create_layout(context) layout.set_width(pangocffi.units_from_double(WIDTH)) fontdesc = pangocffi.FontDescription() fontdesc.set_size(pangocffi.units_from_double(size * 10)) layout.set_font_description(fontdesc) layout.set_markup( 'Hello<span style="italic">world</span>') # yay, pango markup pangocairocffi.show_layout(context, layout) surface.finish() assert compare_SVGObject_with_PangoText(temp_pango_text, filename)
def test_pdf(): filename = 'tests/output/test.pdf' pt_per_mm = 72 / 25.4 width, height = 210 * pt_per_mm, 297 * pt_per_mm # A4 portrait surface = cairocffi.PDFSurface(filename, width, height) context = cairocffi.Context(surface) context.translate(0, height / 2) context.rotate(-0.1) layout = pangocairocffi.create_layout(context) layout.set_width(pangocffi.units_from_double(width)) layout.set_alignment(pangocffi.Alignment.CENTER) layout.set_markup('<span font="italic 30">Hi from Παν語</span>') pangocairocffi.show_layout(context, layout) surface.finish()
def test_tabs_replace() -> None: """Checks whether are there in end svg image. Pango should handle tabs and line breaks.""" size = 1 temp_pango_text = Text("hello\thi\nf") assert temp_pango_text.text == "hellohif" surface = cairocffi.SVGSurface(filename, WIDTH, HEIGTH) context = cairocffi.Context(surface) context.move_to(START_X, START_Y) layout = pangocairocffi.create_layout(context) layout.set_width(pangocffi.units_from_double(WIDTH)) fontdesc = pangocffi.FontDescription() fontdesc.set_size(pangocffi.units_from_double(size * 10)) layout.set_font_description(fontdesc) layout.set_text("hellohif") pangocairocffi.show_layout(context, layout) surface.finish() assert compare_SVGObject_with_PangoText(temp_pango_text, filename)
def test_rtl_text_to_svgobject() -> None: """Checks number of submobjects generated when directly called using ``SVGMobject``""" size = 1 text = RTL_TEXT.replace("\n", "") temp_pango_text = Text(text, size=1) surface = cairocffi.SVGSurface(filename, WIDTH, HEIGTH) context = cairocffi.Context(surface) context.move_to(START_X, START_Y) layout = pangocairocffi.create_layout(context) layout.set_width(pangocffi.units_from_double(WIDTH)) fontdesc = pangocffi.FontDescription() fontdesc.set_size(pangocffi.units_from_double(size * 10)) layout.set_font_description(fontdesc) layout.set_text(text) pangocairocffi.show_layout(context, layout) surface.finish() assert compare_SVGObject_with_PangoText(temp_pango_text, filename)
def paint_foreground(self, ctx: Context): layout = self.font.get_layout(self.text, ctx, self.foreground, self.escape) if self.h_alignment == TextWidget.HAlignment.LEFT: layout.set_alignment(Alignment.LEFT) else: layout.set_width(round(self.width * 1000)) if self.h_alignment == TextWidget.HAlignment.CENTER: layout.set_alignment(Alignment.CENTER) elif self.h_alignment == TextWidget.HAlignment.RIGHT: layout.set_alignment(Alignment.RIGHT) y = -layout.get_extents()[0].y / 1000 if self.v_alignment == TextWidget.VAlignment.BOTTOM: y += self.height - layout.get_extents()[0].height / 1000 elif self.v_alignment == TextWidget.VAlignment.CENTER: y += (self.height - layout.get_extents()[0].height / 1000) / 2 ctx.move_to(0, y) pangocairo.show_layout(ctx, layout)
def test_font_face() -> None: """Checks font face using submobject len""" size = 1 text = RTL_TEXT.replace("\n", "") font_face = "sans" temp_pango_text = Text(text, size=1, font=font_face) surface = cairocffi.SVGSurface(filename, WIDTH, HEIGTH) context = cairocffi.Context(surface) context.move_to(START_X, START_Y) layout = pangocairocffi.create_layout(context) layout.set_width(pangocffi.units_from_double(WIDTH)) fontdesc = pangocffi.FontDescription() fontdesc.set_family(font_face) fontdesc.set_size(pangocffi.units_from_double(size * 10)) layout.set_font_description(fontdesc) layout.set_text(text) pangocairocffi.show_layout(context, layout) surface.finish() assert compare_SVGObject_with_PangoText(temp_pango_text, filename)
def _show_layout( context: cairocffi.Context, layout: pangocffi.Layout ): context.set_source_rgba(0, 0, 0, 0.9) pangocairocffi.show_layout(context, layout)
def textWithoutNewlinesToLines(self, text: str, equal_widths=True, hyphenate=True) -> List[Line]: if text.strip() == "": return [Line(0, self.params.line_height)] ans = [] layouts = [(word, self.createLayout(word)) for word in text.split(" ")] while layouts: surf = cairo.RecordingSurface(cairo.CONTENT_ALPHA, None) context = cairo.Context(surf) context.set_source_rgb(0, 0, 0) i = 0 il = [] wsum = 0 for word, layout in layouts: _, _, w, h = getLayoutExtent(layout) w, h = self._fixXY(w, h) if wsum + len( il ) * self.params.min_word_gap + w > self.params.line_width: if hyphenate and voikko and "-" not in word: syllables = re.split(r"-", voikko.hyphenate(word)) for j in range(len(syllables), 0, -1): text = "".join(syllables[0:j]) if len(stripMarkup(text)) <= 1: break new_l = self.createLayout(text + "-") _, _, new_w, new_h = getLayoutExtent(new_l) new_w, new_h = self._fixXY(new_w, new_h) if wsum + len( il ) * self.params.min_word_gap + new_w <= self.params.line_width: il.append(new_l) wsum += new_w layout.set_markup( fixMarkup("".join(syllables[j:]))) break word_gap = (self.params.line_width - wsum) / ( len(il) - 1) if len(il) > 1 else self.params.min_word_gap break il.append(layout) wsum += w i += 1 else: word_gap = self.params.min_word_gap if i == 0: _, _, w, h = getLayoutExtent(layouts[0][1]) w, h = self._fixXY(w, h) il.append(layouts[0][1]) wsum = w i += 1 x = 0 if self.params.text_align == "center": word_gap = self.params.min_word_gap x = (self.params.line_width - wsum - len(il) * self.params.min_word_gap) / 2 width = -word_gap height = self.params.line_height for l in il: context.translate(*self._fixXY(x, 0)) #pangocairo.update_context(context, l.get_context()) pangocairo.show_layout(context, l) context.translate(*self._fixXY(-x, 0)) _, _, w, h = getLayoutExtent(l) w, h = self._fixXY(w, h) x += word_gap + w width += word_gap + w if h > height: height = h if self.params.text_align == "center": width = self.params.line_width del layouts[:i] if height != self.params.line_height: print(f"Liian pitkä rivi: {height} {repr(text)}") ans.append(TextLine(surf, width, height, indent=self.params.indent)) # Aseta rivien leveystiedot yhdenmukaiseksi sarakealgoritmia varten if equal_widths: width = max(line.width for line in ans) for line in ans: line.width = width return ans