Home > Net >  Pillow - draw a literal tag glyph?
Pillow - draw a literal tag glyph?

Time:07-09

The Unifont contains glyphs for Tags, Variation Selectors, and other non-printable characters.

For example at the end of Screenshot showing lots of characters in FontForge.

Each one has a glyph which should be printable:

Outline drawing of a character.

I want to draw that glyph, using the Unifont, on an image with Pillow.

from PIL import Image, ImageDraw, ImageFont

text = chr(0x2A6B2)   " "   chr(0x0E0026)

font = ImageFont.truetype("unifont_upper-14.0.04.ttf", size=64)

image1 = Image.new("RGB", (256, 64), "white")
draw1  = ImageDraw.Draw(image1)
draw1.text( (0 , 0), text, font=font, fill="black")
image1.save("test aa.png")

The first character (a CJK ideograph) draws correctly. But the tag character is invisible.

Is there any way to get Pillow to draw the shape that I can see in FontForge?

CodePudding user response:

It seems the short answer is, unfortunately, "no you can't".

Pillow generally uses libraqm to lay out text (i.e. do stuff like map the Unicode string to the glyphs in the font, specifically the raqm_layout function.

That library in turn has uses a library called harfbuzz to do the text shaping.

The tag characters you want, including U E0026, have the Unicode default ignorable property. By default harfbuzz doesn't display characters with this property, replacing them with a blank glyph. But it is possible, with the use of flags, to modify this behaviour: specifically, calling hb_buffer_set_flags with HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES seems like it will achieve what you want, displaying these characters rather than blanking them out.

The trouble is, libraqm has no way of setting this flag when it calls harfbuzz - it does let you set some of the other flags, but not this one :(

To achieve what you want I guess you'd have to use a lower level library - there are apparently Python bindings for both FreeType and harfbuzz, though I've not used either so I can't comment on how much pain that might involve.

CodePudding user response:

From Section 23.9, Tag Characters in The Unicode Standard, Chapter 23, Special Areas and Format Characters:

Tag Characters: U E0000–U E007F

This block encodes a set of 95 special-use tag characters to enable the spelling out of ASCII-based string tags using characters that can be strictly separated from ordinary text content characters in Unicode…

Display. Characters in the tag character block have no visible rendering in normal text and the language tags themselves are not displayed.

And from the Unicode Frequently Asked Questions (with my own emphasizing):

Q: Which characters should be displayed as invisible, if not supported?

All default-ignorable characters should be rendered as completely invisible (and non advancing, i.e. "zero width"), if not explicitly supported in rendering.

Q: Does that mean that a font can never display one of these characters?

No. Rendering systems may also support special modes such as “Display Hidden”, which are intended to reveal characters that would not otherwise display. Fonts can contain glyphs intended for visible display of default ignorable code points that would otherwise be rendered invisibly when not supported.

More resources (required reading, incomplete):

  • Related