From d0db6604a35a5ffc4e135a96c225424feebb694a Mon Sep 17 00:00:00 2001 From: Pandaaaa906 Date: Thu, 28 Dec 2023 16:15:15 +0800 Subject: [PATCH 1/2] quick fix of https://github.com/Kozea/CairoSVG/issues/317 --- cairosvg/text.py | 54 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/cairosvg/text.py b/cairosvg/text.py index 72c5d3c4..d334eb0a 100644 --- a/cairosvg/text.py +++ b/cairosvg/text.py @@ -49,8 +49,9 @@ def point_following_path(path, width): return x, y -def text(surface, node, draw_as_text=False): - """Draw a text ``node``.""" +def initial_context_font(surface, node, context=None): + if context is None: + context = surface.context font_family = ( (node.get('font-family') or 'sans-serif').split(',')[0].strip('"\' ')) font_style = getattr( @@ -63,8 +64,49 @@ def text(surface, node, draw_as_text=False): font_weight = getattr( cairo, (f'font_weight_{node_font_weight}'.upper()), cairo.FONT_WEIGHT_NORMAL) - surface.context.select_font_face(font_family, font_style, font_weight) - surface.context.set_font_size(surface.font_size) + context.select_font_face(font_family, font_style, font_weight) + node_font_size = node.get('font-size') + if node_font_size and node_font_size.isdigit(): + font_size = float(node_font_size) + else: + font_size = surface.font_size + context.set_font_size(font_size) + + +def get_single_node_text_extends(surface, node): + with surface.context as context: + initial_context_font(surface, node, context) + return context.text_extents(node.text) + + +def iter_nodes(node): + yield node + for sub_node in node.children: + yield from iter_nodes(sub_node) + + +def get_node_text_extents(surface, node): + parent_text_node = node + while parent_text_node.tag != 'text' and parent_text_node.parent: + parent_text_node = parent_text_node.parent + if parent_text_node is not node and parent_text_node.tag != 'text': + parent_text_node = node + x_bearing, y_bearing, width, height, x_advance, y_advance = 0, 0, 0, 0, 0, 0 + for sub_node in iter_nodes(parent_text_node): + a, b, c, d, e, f = get_single_node_text_extends(surface, sub_node) + if sub_node is node: + x_bearing = a + y_bearing = b + height = d + width += c + x_advance = width - x_bearing + y_advance = height - y_bearing + return x_bearing, y_bearing, width, height, x_advance, y_advance + + +def text(surface, node, draw_as_text=False): + """Draw a text ``node``.""" + initial_context_font(surface, node) ascent, descent, _, max_x_advance, max_y_advance = ( surface.context.font_extents()) @@ -74,8 +116,8 @@ def text(surface, node, draw_as_text=False): else: text_path = None letter_spacing = size(surface, node.get('letter-spacing')) - x_bearing, y_bearing, width, height = ( - surface.context.text_extents(node.text)[:4]) + # quick fix for https://github.com/Kozea/CairoSVG/issues/317 + x_bearing, y_bearing, width, height = get_node_text_extents(surface, node)[:4] x, y, dx, dy, rotate = [], [], [], [], [0] if 'x' in node: From 91b782266a6b0aec9119d895a6e1368aee25770d Mon Sep 17 00:00:00 2001 From: Pandaaaa906 Date: Thu, 28 Dec 2023 16:15:15 +0800 Subject: [PATCH 2/2] quick fix of https://github.com/Kozea/CairoSVG/issues/317 --- cairosvg/text.py | 50 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/cairosvg/text.py b/cairosvg/text.py index 72c5d3c4..7f55d7ec 100644 --- a/cairosvg/text.py +++ b/cairosvg/text.py @@ -49,8 +49,7 @@ def point_following_path(path, width): return x, y -def text(surface, node, draw_as_text=False): - """Draw a text ``node``.""" +def initial_context_font(surface, node): font_family = ( (node.get('font-family') or 'sans-serif').split(',')[0].strip('"\' ')) font_style = getattr( @@ -64,7 +63,48 @@ def text(surface, node, draw_as_text=False): cairo, (f'font_weight_{node_font_weight}'.upper()), cairo.FONT_WEIGHT_NORMAL) surface.context.select_font_face(font_family, font_style, font_weight) - surface.context.set_font_size(surface.font_size) + node_font_size = node.get('font-size') + if node_font_size and node_font_size.isdigit(): + font_size = float(node_font_size) + else: + font_size = surface.font_size + surface.context.set_font_size(font_size) + + +def get_single_node_text_extends(surface, node): + with surface.context: + initial_context_font(surface, node) + return surface.context.text_extents(node.text) + + +def iter_nodes(node): + yield node + for sub_node in node.children: + yield from iter_nodes(sub_node) + + +def get_node_text_extents(surface, node): + parent_text_node = node + while parent_text_node.tag != 'text' and parent_text_node.parent: + parent_text_node = parent_text_node.parent + if parent_text_node is not node and parent_text_node.tag != 'text': + parent_text_node = node + x_bearing, y_bearing, width, height, x_advance, y_advance = 0, 0, 0, 0, 0, 0 + for sub_node in iter_nodes(parent_text_node): + a, b, c, d, e, f = get_single_node_text_extends(surface, sub_node) + if sub_node is node: + x_bearing = a + y_bearing = b + height = d + width += c + x_advance = width - x_bearing + y_advance = height - y_bearing + return x_bearing, y_bearing, width, height, x_advance, y_advance + + +def text(surface, node, draw_as_text=False): + """Draw a text ``node``.""" + initial_context_font(surface, node) ascent, descent, _, max_x_advance, max_y_advance = ( surface.context.font_extents()) @@ -74,8 +114,8 @@ def text(surface, node, draw_as_text=False): else: text_path = None letter_spacing = size(surface, node.get('letter-spacing')) - x_bearing, y_bearing, width, height = ( - surface.context.text_extents(node.text)[:4]) + # quick fix for https://github.com/Kozea/CairoSVG/issues/317 + x_bearing, y_bearing, width, height = get_node_text_extents(surface, node)[:4] x, y, dx, dy, rotate = [], [], [], [], [0] if 'x' in node: