Pillow
Pillow copied to clipboard
Multiline ttb text is not supported
Drawing multiline text currently draws a single vertical line of overlapping characters. I'm not sure how/if this can be fixed within the existing API since it is not clear whether ttb lines should advance to the left or the right.
What did you do?
from PIL import ImageFont, ImageDraw, Image
im = Image.new("RGB", (200, 200), "white")
draw = ImageDraw.Draw(im)
font = ImageFont.truetype("Tests/fonts/DejaVuSans.ttf", 24)
dram.text((100, 10), "abc\n123\nXYZ", "black", font, direction="ttb")
im.show()
What actually happened?
Before #4930 (master):
With #4930:
ValueError: ttb direction is unsupported for multiline text
https://www.w3.org/International/questions/qa-scripts#:~:text=Ideographic%20languages%20(e.g.%20Japanese%2C%20Korean,occasionally%20written%20right%20to%20left.
Ideographic languages (e.g. Japanese, Korean, Chinese) are more flexible in their writing direction. They are generally written left-to-right, or vertically top-to-bottom (with the vertical lines proceeding from right to left).
Should ttb lines then advance to the left?
Advancing lines to the left would be fine for languages that actually use ttb, but not for e.g. English text written in ttb mode. For example, the Bungee font is designed with English ttb in mind, and that would most likely advance to the right.
How's this proposal: The spacing=4
parameter is currently used to add an additional offset to the line-height automatically chosen by Pillow (height of the letter A). In ttb mode, it could be reused to specify the exact distance between lines horizontally, so 20 would place lines at 20px intervals advancing to the right and -10 would place lines at 10px intervals advancing to the left. The default value doesn't make sense here, but ttb fonts might not have a glyph for the letter A anyway.
If You mean T
op T
o B
ottom it could be easily done by setting spacing
variable as @nulano said, and getting textwrap.wrap
with it to work, but in your case I see it can be splitted by newlines.
No offence, but I strongly advise You to write fonts on new transparent Image
instances, since it's easier to manipulate them later.
from PIL import Image, ImageDraw, ImageFont
im = Image.new("RGB", (200, 200), "white")
im_text = Image.new("RGBA", im.size, (0,) * 4)
draw = ImageDraw.Draw(im_text)
#---#
text = "abc\n123\nXYZ"
font = ImageFont.truetype(r"Roboto.otf", 24)
co_ords = (100, 10)
#---#
spacing = 0
for Line in text.split("\n"):
draw.text((0, spacing), Line, fill = "black", font)
spacing += font.getsize(Line)[1]
# Crop transparent pixels
im_text = im_text.crop(im_text.getbbox())
im.paste(im_text, co_ords, im_text)
im.show()
@radarhere asked:
Should ttb lines then advance to the left?
I am wondering how it is implemented in Raqm, what their values are in terms of layout. Two different things seem to be mixed up together, text direction and text progression.
ttb tells you the direction of the text run, but doesn't tell you the progression of lines of text.
For instance, Han ideographs when written vertically (Chinese, Japanese, Korean (in Hanja), Vietnamese in Chữ Nôm) is written in lines from top of text area to bottom, with lines of text progressing to the left.
Mongolian script on the other hand is written top to bottom as well, but lines of text progress to the right instead of the left, so as Mongolian progression is the opposite to Han ideographs, any rendering system needs to be able to support vertical text progression in either direction.
I am wondering how it is implemented in Raqm
Raqm does not yet support line-breaking, but instead treats the whole input as a single line of text: https://github.com/HOST-Oman/libraqm/issues/50
Thanks @nulano,
I suspected that was the case, although I guess it's a moot point at the moment, since I can't get a single vertical line to correctly render, let alone multiple lines. I suspect that the writing system (script) I am working with isn't supported in raqm yet.