Pillow icon indicating copy to clipboard operation
Pillow copied to clipboard

Multiline ttb text is not supported

Open nulano opened this issue 4 years ago • 6 comments

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):

multiline

With #4930:

ValueError: ttb direction is unsupported for multiline text

nulano avatar Oct 04 '20 19:10 nulano

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?

radarhere avatar Oct 24 '20 00:10 radarhere

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.

nulano avatar Dec 11 '20 23:12 nulano

If You mean Top To Bottom 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()

kubinka0505 avatar Dec 17 '20 18:12 kubinka0505

@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.

andjc avatar Jun 29 '22 07:06 andjc

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

nulano avatar Jun 29 '22 07:06 nulano

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.

andjc avatar Jul 01 '22 13:07 andjc