Added some (naive) text wrapping in the schedule #3010

Before - https://i.imgur.com/dJPQ788.png
After - https://i.imgur.com/T1FtI8H.png

For it to work make sure you have word wrapping in ods.

It's still very naive since it's taking constant font width which could vary depending on font type, font size, font lettering. The proper way would be is to either find some svg way to do it (couldn't find any stable one) or to render text to identify it's width (could be done with PIL but seems overkill, atleast for now).
This commit is contained in:
Andrej730
2023-05-03 11:51:46 +05:00
parent 8d2ea88b9b
commit 595e73ca19
@@ -23,8 +23,10 @@ from odf.opendocument import load
from odf.table import Table, TableRow, TableColumn, TableCell
from odf.text import P
from odf.style import Style
from textwrap import wrap
FONT_SIZE = 4.13
FONT_WIDTH = FONT_SIZE * 0.45
class Scheduler:
@@ -146,7 +148,9 @@ class Scheduler:
elif box_alignment.startswith("bottom"):
text_position[1] = y + height - self.padding
self.add_text(value[0], *text_position, box_alignment=box_alignment)
self.add_text(
value[0], *text_position, box_alignment=box_alignment, wrap_text=wrap_text, cell_width=width
)
x += width
tdi += column_span
@@ -157,15 +161,41 @@ class Scheduler:
self.svg["viewBox"] = "0 0 {} {}".format(total_width, y)
self.svg.save(pretty=True)
def add_text(self, text, x, y, box_alignment="bottom-left"):
def add_text(self, text, x, y, box_alignment="bottom-left", wrap_text=False, cell_width=100):
"""
Adds text to svg.
Args:
box_alignment: alignment of text in box
wrap_text: if True, text will be wrapped to fit in cell
cell_width: width of cell, used for wrapping text
"""
text = str(text).upper()
box_alignment_params = SvgWriter.get_box_alignment_parameters(box_alignment)
text_params = {
"font-size": FONT_SIZE,
"font-family": "OpenGost Type B TT",
"text-anchor": "start",
}
text_params.update(box_alignment_params)
text_tag = self.svg.text(str(text).upper(), insert=tuple((x, y)), **text_params)
if wrap_text:
text_tag = self.svg.text(
"",
**({"style": "font-size: 0;"} | box_alignment_params),
)
# TODO: should be done in less naive way
# without using magic number for FONT_WIDTH
# currently it might not work for all fonts and font sizes
text_lines = wrap(text, width=int(cell_width // FONT_WIDTH), break_long_words=False)
for line_number, text_line in enumerate(text_lines[::-1]):
# position has to be inserted at tspan to avoid x offset between tspans
tspan = self.svg.tspan(text_line, insert=(x, y), **text_params)
# doing it here and not in tspan constructor because constructor adds unnecessary spaces
tspan.update({"dy": f"-{line_number}em"})
text_tag.add(tspan)
else:
text_params.update(box_alignment_params)
text_tag = self.svg.text(text, insert=(x, y), **text_params)
self.svg.add(text_tag)
def convert_to_mm(self, value):