Rendering Text!
elkplot can render text in a number of different fonts using the built in text
function. Here are all the
provided fonts plotted on letter paper:
The full list of fonts as you'd use them in code are: elkplot.ASTROLOGY, elkplot.CURSIVE, elkplot.CYRILLIC_1, elkplot.CYRILLIC, elkplot.FUTURAL, elkplot.FUTURAM, elkplot.GOTHGBT, elkplot.GOTHGRT, elkplot.GOTHICENG, elkplot.GOTHICGER, elkplot.GOTHICITA, elkplot.GOTHITT, elkplot.GREEK, elkplot.GREEKC, elkplot.GREEKS, elkplot.JAPANESE, elkplot.MARKERS, elkplot.MATHLOW, elkplot.MATHUPP, elkplot.METEOROLOGY, elkplot.MUSIC, elkplot.ROWMAND, elkplot.ROWMANS, elkplot.ROWMANT, elkplot.SCRIPTC, elkplot.SCRIPTS, elkplot.SYMBOLIC, elkplot.TIMESG, elkplot.TIMESI, elkplot.TIMESIB, elkplot.TIMESR, elkplot.TIMESRB
.
Sample Code
import elkplot
size = 4 * elkplot.UNITS.inch, 2 * elkplot.UNITS.inch
font = elkplot.Font(elkplot.METEOROLOGY, 25)
text_drawing = font.wrap("The quick brown fox jumps over the lazy dog.", 3)
text_drawing = elkplot.center(text_drawing, *size)
elkplot.draw(text_drawing, *size, plot=False)
The above code results in the following plot (as viewed in the preview window). The paper is 4 inches wide, but the text
has been wrapped to fit in a column 3 inches wide.
Note that all the text generating functions return text that is situated at the origin - use functions
like elkplot.center()
or elkplot.scale_to_fit()
to move and scale your text-drawing or
use shapely.affinity.translate()
to
reposition the text-drawing to arbitrary positions.
Font
Source code in elkplot/text/hershey.py
| class Font:
def __init__(self, font: HersheyFont, point_size: float):
"""A class that renders text in a given font and point size"""
self.font = font
self.max_height = size(text(printable, font))[1]
self.scale = ((point_size / 72) / self.max_height).magnitude
def text(self, string: str) -> shapely.MultiLineString:
"""
Render a string using this font's size and font in a single long line.
Args:
string: The text to be rendered
Returns:
The drawing of the text
"""
t = text(string, self.font)
t = affinity.scale(t, self.scale, self.scale, origin=(0, 0))
return t
def measure(self, string: str) -> tuple[pint.Quantity, pint.Quantity]:
"""Return the width and height of a given string rendered using this font/size combo"""
t = self.text(string)
return size(t)
@elkplot.UNITS.wraps(None, [None, None, "inch", None, None], False)
def wrap(
self,
string: str,
width: float,
line_spacing: float = 1,
align: float = 0,
) -> shapely.MultiLineString:
"""
Render a given string such that the text is confined to a column of a given width by inserting line breaks.
Args:
string: The text to be rendered
width: The width of the column
line_spacing: A multiplier on the gap between lines. Setting this to 0.5 would cut the space between lines
in half, and setting this to 2 would double the space between lines.
align: 0=align text left, 1=align text right, 2=align text center
Returns:
The drawing of the text
"""
lines = word_wrap(string, width, self.measure)
line_shapes = [self.text(line) for line in lines]
max_width = max(size(t)[0] for t in line_shapes)
spacing = line_spacing * self.max_height * self.scale
result = []
y = 0
for line_shape in line_shapes:
w, h = size(line_shape)
if align == 0:
x = 0
elif align == 1:
x = (max_width - w).m
else:
x = (max_width / 2 - w / 2).m
line_shape = affinity.translate(line_shape, x, y)
result.append(line_shape)
y += spacing.m
return shapely.union_all(result)
|
__init__(font, point_size)
A class that renders text in a given font and point size
Source code in elkplot/text/hershey.py
| def __init__(self, font: HersheyFont, point_size: float):
"""A class that renders text in a given font and point size"""
self.font = font
self.max_height = size(text(printable, font))[1]
self.scale = ((point_size / 72) / self.max_height).magnitude
|
measure(string)
Return the width and height of a given string rendered using this font/size combo
Source code in elkplot/text/hershey.py
| def measure(self, string: str) -> tuple[pint.Quantity, pint.Quantity]:
"""Return the width and height of a given string rendered using this font/size combo"""
t = self.text(string)
return size(t)
|
text(string)
Render a string using this font's size and font in a single long line.
Args:
string: The text to be rendered
Returns:
Type |
Description |
MultiLineString
|
|
Source code in elkplot/text/hershey.py
| def text(self, string: str) -> shapely.MultiLineString:
"""
Render a string using this font's size and font in a single long line.
Args:
string: The text to be rendered
Returns:
The drawing of the text
"""
t = text(string, self.font)
t = affinity.scale(t, self.scale, self.scale, origin=(0, 0))
return t
|
wrap(string, width, line_spacing=1, align=0)
Render a given string such that the text is confined to a column of a given width by inserting line breaks.
Args:
string: The text to be rendered
width: The width of the column
line_spacing: A multiplier on the gap between lines. Setting this to 0.5 would cut the space between lines
in half, and setting this to 2 would double the space between lines.
align: 0=align text left, 1=align text right, 2=align text center
Returns:
Type |
Description |
MultiLineString
|
|
Source code in elkplot/text/hershey.py
| @elkplot.UNITS.wraps(None, [None, None, "inch", None, None], False)
def wrap(
self,
string: str,
width: float,
line_spacing: float = 1,
align: float = 0,
) -> shapely.MultiLineString:
"""
Render a given string such that the text is confined to a column of a given width by inserting line breaks.
Args:
string: The text to be rendered
width: The width of the column
line_spacing: A multiplier on the gap between lines. Setting this to 0.5 would cut the space between lines
in half, and setting this to 2 would double the space between lines.
align: 0=align text left, 1=align text right, 2=align text center
Returns:
The drawing of the text
"""
lines = word_wrap(string, width, self.measure)
line_shapes = [self.text(line) for line in lines]
max_width = max(size(t)[0] for t in line_shapes)
spacing = line_spacing * self.max_height * self.scale
result = []
y = 0
for line_shape in line_shapes:
w, h = size(line_shape)
if align == 0:
x = 0
elif align == 1:
x = (max_width - w).m
else:
x = (max_width / 2 - w / 2).m
line_shape = affinity.translate(line_shape, x, y)
result.append(line_shape)
y += spacing.m
return shapely.union_all(result)
|