def text_height(self, width, pango_context): fontn = pango.FontDescription() fontn.set_family(self.font_family) fontn.set_size(pango.units_from_double(self.font_size)) pango_context.set_font_description(fontn) layout = pango.layout.Layout(pango_context) layout.set_width(pango.units_from_double(width)) layout.set_text(self.text) _, raw_height = layout.get_size() return pango.units_to_double(raw_height)
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 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 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 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_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_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_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 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_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 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 __init__(self, args: Namespace): self.width = float(args.width) self.height = float(args.height) self.margin = float(args.margin) self.line_width = float(self.width - 2 * self.margin) self.line_height = float(16) self.page_height = float(self.height - 2 * self.margin) self.pg_gap = float(16) self.column_gap = float(10) self.min_word_gap = float(5) self.indent = float(0) self.quote_indent = float(50) self.text_align = "justify" self.font_size = float(10) self.font = "rm" self.fonts = {} self.fonts["rm"] = pango.FontDescription() self.fonts["rm"].set_family(args.font) self.fonts["rm"].set_size(pango.units_from_double(10)) print(f"Paperin koko {self.width}x{self.height}") print(f"Piirtoalueen koko {self.line_width}x{self.page_height}")
def height(self, x: CanvasUnit): self._layout.set_height(pangocffi.units_from_double(x.pt))
def addFont(self, varname, fontname): print(f"Lisätään fontti {varname} = {repr(fontname)}") self.fonts[varname] = pango.FontDescription() self.fonts[varname].set_family(fontname) self.fonts[varname].set_size(pango.units_from_double(10))
def paragraphsToLines(self, paragraphs: List[DocumentObj]): all_lines: List[Line] = [] for i, pg in enumerate(paragraphs): print(i + 1, "/", len(paragraphs), end="\r") if isinstance(pg, Table): if all_lines and all_lines[-1].is_content_line: all_lines.append( ParagraphGap(0, self.params.pg_gap, pg.no_page_break)) with self._stackFrame(): self._getFont().set_size( pango.units_from_double(self.params.font_size)) indent = self.params.indent self.params.resetLayout() num_columns = max(len(row) for row in pg.rows) max_line_width = self.params.line_width self.params.line_width = (max_line_width - self.params.column_gap * (num_columns - 1)) / num_columns rendered_rows: List[List[List[Line]]] = [ [] for _ in range(len(pg.rows)) ] for i in range(num_columns): max_width = 0 for j in range(len(pg.rows)): if i >= len(pg.rows[j]): pg.rows[j].append(Paragraph.fromText(text="")) rendered_rows[j].append( self.paragraphsToLines([pg.rows[j][i]])) width = rendered_rows[j][i][ 0].width if rendered_rows[j][i] else 0 if width > max_width: max_width = width for rrow in rendered_rows: for line in rrow[i]: line.width = max_width if i != num_columns - 1: self.params.line_width = ( max_line_width - max_width - self.params.column_gap * (num_columns - i - 1)) / (num_columns - i - 1) lines = [] for rrow in rendered_rows: for i in range(max(len(c) for c in rrow)): column_lines: List[Line] = [ c[i] if i < len(c) else Line( c[0].width if c else 0, self.params.line_height) for c in rrow ] lines.append( ColumnLine(column_lines, self.params.column_gap, indent=indent)) lines[-1].no_page_break = pg.no_page_break elif isinstance(pg, Paragraph): if all_lines and all_lines[-1].is_content_line: all_lines.append( ParagraphGap(0, self.params.pg_gap, pg.no_page_break)) with self._stackFrame(): if pg.type != "text": level, self.params.font_size, self.params.line_height, self.params.text_align = TITLES[ pg.type] else: level = -1 self._getFont().set_size( pango.units_from_double(self.params.font_size)) lines = self.textToLines(pg.text, hyphenate=level < 0) if lines: lines[0].no_page_break = pg.no_page_break if level >= 0: lines[0].outline = (level, pg.text) if "title" in pg.type: for line in lines[1:]: line.no_page_break = True elif isinstance(pg, VSpace): lines = [ Line(self.params.line_width, pg.height or self.params.line_height) ] elif isinstance(pg, Eval): pg.func(self.params) lines = [] elif isinstance(pg, Subenvironment): with self._stackFrame(): lines = self.paragraphsToLines(pg.paragraphs) else: print(f"Tuntematon kappaletyyppi {type(pg)}") lines = [] all_lines += lines return all_lines
def test_pdf(): filename = 'tests/output/extents.pdf' pt_per_mm = 72 / 25.4 width, height = 210 * pt_per_mm, 400 * pt_per_mm # A4 portrait surface = cairocffi.PDFSurface(filename, width, height) ctx = cairocffi.Context(surface) ctx.translate(width / 2, 10) 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' 'The text layout engine library for displaying ' '<span font-weight="bold">multi-language</span> text!') translate_y = 110 label_pos = (-width / 2 + 30, 30) label_width = width / 2.5 _show_layout_logical_extents(ctx, layout) _show_layout(ctx, layout) _show_label(ctx, label_pos, label_width, 'Layout (logical extents)') ctx.translate(0, translate_y) _show_layout_ink_extents(ctx, layout) _show_layout(ctx, layout) _show_label(ctx, label_pos, label_width, 'Layout (ink extents)') ctx.translate(0, translate_y) _show_layout_line_logical_extents(ctx, layout) _show_layout(ctx, layout) _show_label(ctx, label_pos, label_width, 'Layout Line (logical extents)') ctx.translate(0, translate_y) _show_layout_line_ink_extents(ctx, layout) _show_layout(ctx, layout) _show_label(ctx, label_pos, label_width, 'Layout Line (ink extents)') ctx.translate(0, translate_y) _show_layout_baseline(ctx, layout) _show_layout(ctx, layout) _show_label( ctx, label_pos, label_width, 'y-range (top), Baseline,\ny-range (bottom)' ) ctx.translate(0, translate_y) _show_run_logical_extents(ctx, layout) _show_layout(ctx, layout) _show_label(ctx, label_pos, label_width, 'Layout Run (logical extents)') ctx.translate(0, translate_y) _show_run_ink_extents(ctx, layout) _show_layout(ctx, layout) _show_label(ctx, label_pos, label_width, 'Layout Run (ink extents)') ctx.translate(0, translate_y) _show_cluster_logical_extents(ctx, layout) _show_layout(ctx, layout) _show_label(ctx, label_pos, label_width, 'Cluster (logical extents)') ctx.translate(0, translate_y) _show_cluster_ink_extents(ctx, layout) _show_layout(ctx, layout) _show_label(ctx, label_pos, label_width, 'Cluster (ink extents)') ctx.translate(0, translate_y) _show_character_extents(ctx, layout) _show_layout(ctx, layout) _show_label(ctx, label_pos, label_width, 'Character extents') ctx.translate(0, translate_y) surface.finish()
def test_context_properties(): assert pangocffi.units_from_double(0) == 0 assert pangocffi.units_from_double(0.1201171875) == 123
def test_pango_scale_is_consistent_with_library(self): assert CanvasUnit.from_pt(2).pango == pangocffi.units_from_double(2) assert CanvasUnit.from_pango(512).pt == pangocffi.units_to_double(512)
def width(self, x: CanvasUnit): self._layout.set_width(pangocffi.units_from_double(x.pt))
def to_pango_units(size: float) -> int: return pangocffi.units_from_double(size)
def test_attributes(): width = 150 height = 50 # CFFIs and Contexts context_creator = ContextCreator.create_pdf( 'tests/acceptance/output/attributes.pdf', width, height) pangocairo = context_creator.pangocairo cairo_context = context_creator.cairo_context text = 'Hi from Παν語! This test is to make sure that text is correctly ' \ 'annotated, and to also highlight functionality that is not ' \ 'available from methods like pango.set_markup(\'...\'). ' \ 'For instance, Attribute.from_shape() allows you to embed a ' \ 'picture or a widget in a layout. Example: Ø.' text_utf8 = text.encode('utf-8') # Using pangocairocffi, this would be `pangocairocffi.create_layout()` with # a cairocffi context object. layout = Layout.from_pointer( pangocairo.pango_cairo_create_layout(cairo_context)) layout.set_width(pangocffi.units_from_double(width * 72 / 25.4)) layout.set_text(text) attr_list = AttrList() # Example: Handling byte indexes correctly. # When handling byte indexes, make sure to always use UTF-8 byte strings. # For example , while the string '語' has a length of 1 character in # python, in a UTF-8 byte string this is 3 bytes: `0xe8 0xaa 0x9e`. Pango # will not like byte indexes that occur in the middle of a character. text_to_match = 'Παν語!'.encode('utf-8') match_index = text_utf8.index(text_to_match) match_index_end = match_index + len(text_to_match) attr_list.insert( Attribute.from_style(Style.ITALIC, match_index, match_index_end)) # Example: Color alpha # `set_markup()` doesn't appear to have the ability to control color # alphas, but it is supported by Attributes! Note that the alpha color for # underline and foreground text cannot be controlled separately. text_to_match = 'correctly'.encode('utf-8') match_index = text_utf8.index(text_to_match) match_index_end = match_index + len(text_to_match) attr_list.insert( Attribute.from_underline(Underline.ERROR, match_index, match_index_end)) attr_list.insert( Attribute.from_foreground_color(65535, 0, 0, match_index, match_index_end)) attr_list.insert( Attribute.from_underline_color(0, 0, 65535, match_index, match_index_end)) attr_list.insert( Attribute.from_background_color(0, 65535, 0, match_index, match_index_end)) attr_list.insert( Attribute.from_foreground_alpha(32768, match_index, match_index_end)) attr_list.insert( Attribute.from_background_alpha(8192, match_index, match_index_end)) # Example: Highlight multiple Monospace texts markup_texts = ('pango.set_markup(\'...\')', 'Attribute.from_shape()') for markup_text in markup_texts: text_to_match = markup_text.encode('utf-8') match_index = text_utf8.index(text_to_match) match_index_end = match_index + len(text_to_match) attr_list.insert( Attribute.from_family('monospace', match_index, match_index_end)) # Example: Shape placeholders # `Attribute.from_shape()` can be used to insert a box within the layout. # In this case, we're inserting a 1cm square that sits on the baseline of # the final line. Note the negative y coordinate of the rectangle. # Visually, the background color will appear a bit larger, that's because # it will also apply a background below the baseline of the font. # Once rendered, it should be possible to retrieve the position of the # shape using using LayoutIter so that an actual image can be rendered in # place should you need to. text_to_match = 'Ø'.encode('utf-8') match_index = text_utf8.index(text_to_match) match_index_end = match_index + len(text_to_match) glyph_length = pangocffi.units_from_double(10 * 72 / 25.4) # 10 mm ink = Rectangle(width=glyph_length, height=glyph_length, x=0, y=-glyph_length) logical = Rectangle(width=glyph_length, height=glyph_length, x=0, y=-glyph_length) attr_list.insert( Attribute.from_background_color(65535, 0, 0, match_index, match_index_end)) attr_list.insert( Attribute.from_background_alpha(8192, match_index, match_index_end)) attr_list.insert( Attribute.from_shape(ink, logical, match_index, match_index_end)) # Apply all the attributes to the layout layout.set_attributes(attr_list) # Using pangocairocffi, this would be `pangocairocffi.show_layout(layout)` pangocairo.pango_cairo_show_layout(cairo_context, layout.get_pointer()) context_creator.close()