1
0
Fork 0
mirror of https://git.lynn.is/Gwen/python-layout.git synced 2024-01-13 01:31:55 +01:00
python-layout/pillow_layout/text.py
2023-02-07 23:56:17 +01:00

107 lines
3.9 KiB
Python

from PIL import ImageDraw, ImageFont
from . import Layout, TextAlign, TextVerticalAlign, TextWrap
from .internal.textlayouter import TextLayouter
from .internal.helpers import min_with_none, max_with_none, get_line_height
class Text(Layout):
def __init__(
self,
text=None,
text_align=TextAlign.LEFT,
vertical_text_align=TextVerticalAlign.TOP,
text_wrap=TextWrap.NO_WRAP,
line_spacing=0,
**kwargs
):
super().__init__(**kwargs)
self.text_layouter = None
self.text = text
self.text_align = text_align
self.vertical_text_align = vertical_text_align
self.text_wrap = text_wrap
self.line_spacing = line_spacing
def complete_init(self, container):
super().complete_init(container)
if self.is_empty():
lines = []
elif isinstance(self.text, list):
lines = self.text
else:
lines = self.text.splitlines()
self.text_layouter = TextLayouter(lines=lines,
align=self.text_align,
vertical_align=self.vertical_text_align,
wrap=self.text_wrap,
font=self.get_font(),
line_height=self.get_line_height_with_spacing())
def is_empty(self):
return self.text is None or self.text == '' or (isinstance(self.text, list)
and len(self.text) == 0)
def get_min_inner_width(self, max_height=None):
if self.is_empty():
width = 0
else:
if max_height is not None:
max_height += self.line_spacing
width = self.text_layouter.get_dimensions(0, max_height)[0]
return max_with_none(width, self.min_width)
def get_min_inner_height(self, max_width=None):
if self.is_empty():
height = 0
else:
# no spacing after the last line
height = self.text_layouter.get_dimensions(max_width, 0)[1] - self.line_spacing
return max_with_none(height, self.min_height)
def get_ideal_inner_dimensions(self, min_width=None, min_height=None, available_width=None, available_height=None):
available_width = min_with_none(available_width, self.width)
available_height = min_with_none(available_height, self.height)
width, height = self.text_layouter.get_dimensions(available_width, available_height)
height -= self.line_spacing # no spacing after the last line
if self.width is not None:
width = self.width
if self.height is not None:
height = self.height
width = max_with_none(width, self.min_width)
height = max_with_none(height, self.min_height)
width = min_with_none(width, self.max_width)
height = min_with_none(height, self.max_height)
return width, height
def render_content(self, rect):
image = self.make_canvas()
d = ImageDraw.Draw(image)
x1, y1, x2, y2 = rect
width, height = x2 - x1 + 1, y2 - y1 + 1
if self.max_width is not None:
width = min(width, self.max_width)
if self.min_width is not None:
width = max(width, self.min_width)
if self.max_height is not None:
height = min(height, self.max_height)
if self.min_height is not None:
height = max(height, self.min_height)
lines = self.text_layouter.get_lines(width, height)
color = self.get_fg_color()
font = self.get_font()
for posx, posy, text in lines:
d.text((x1 + posx, y1 + posy), text, font=font, fill=color)
return image
def get_line_height_with_spacing(self):
return get_line_height(self.get_font()) + self.line_spacing