Pillow icon indicating copy to clipboard operation
Pillow copied to clipboard

ParryHotter font isn't displayed

Open Zuzu-Typ opened this issue 7 years ago • 17 comments

What did you do?

I tried to create a text using the font "ParryHotter" (using the code below)

What did you expect to happen?

I expected to see an image with the text "Parry Hotter" in the corresponding font

What actually happened?

A blank image opened

What versions of Pillow and Python are you using?

Python 2.7.13 and 3.6.1 Pillow 4.1.1 Please include code that reproduces the issue and whenever possible, an image that demonstrates the issue. Please upload images to GitHub, not to third-party file hosting sites. If necessary, add the image to a zip or tar archive.

The best reproductions are self-contained scripts with minimal dependencies. If you are using a framework such as plone, Django, or buildout, try to replicate the issue just using Pillow.

from PIL import Image, ImageFont, ImageDraw

font = ImageFont.truetype("parryhotter.ttf", 20)

image = Image.new("RGBA", font.getsize("Parry Hotter"))

draw = ImageDraw.Draw(image)

draw.text((0,0),"Parry Hotter", font=font)

image.show()

Zuzu-Typ avatar Jun 16 '17 21:06 Zuzu-Typ

Can you post the font?

wiredfool avatar Jun 17 '17 10:06 wiredfool

Here you go: https://mfi.re/?6k1d126g8ryt93o

The font is also shipped with Windows by default.

Zuzu-Typ avatar Jun 17 '17 10:06 Zuzu-Typ

I've found some more fonts that aren't displayed correctly (or at all). http://www.mediafire.com/file/h5n71j24pnluqx0/xfiles.ttf (not at all displayed) http://www.mediafire.com/file/1qtmbhbz2hvihdk/woodcut.ttf (displayed as squares).

Another font that doesn't seem to be correctly loaded is Segoe UI Symbol, where

font.getsize("Segoe UI Symbol text that ends with a j")

isn't quite large enough to display the whole text. j

Zuzu-Typ avatar Jun 17 '17 17:06 Zuzu-Typ

Parry Hotter is from www.anke-art.de, it's donation-ware, so I find it hard to believe that it ships with Windows.

At any rate, it does not define any glyphs in the unicode range < 0x8f, so ordinary ascii text is not going to show up. It appears that the font is entirely contained in the unicode region 0x10002 to 0x100aa. The other two fonts are similar.

wiredfool avatar Jun 19 '17 20:06 wiredfool

Well then I don't know how the font got onto my system, probably installed by some software that needed it. Probably Gimp or something.

Nevertheless what you said about "ordinary ascii text not showing up" isn't correct. Pygame doesn't have any issues displaying Ascii text and neither does Windows. Have a look yourself. ph This looks basically the same for all of the three fonts.

Also, you seem to have missed what I said about Segoe UI (which by the way is Windows Vista - 10's default font)

Zuzu-Typ avatar Jun 20 '17 06:06 Zuzu-Typ

This is the ordinary low ascii area of the Harry Potter font. Nothing is there: screen shot 2017-06-20 at 12 23 02 pm

(for reference, here's DejaVuSans) screen shot 2017-06-20 at 12 22 55 pm

This is where the actual glyphs are: screen shot 2017-06-20 at 12 23 21 pm

So, there's something going on where unicode ranges are remapped. Clearly it's in a layer that Pillow isn't using.

As for Segoe UI, I don't have that font easily available.

wiredfool avatar Jun 20 '17 11:06 wiredfool

How about these three though? They appear correctly in FontForge, but are displayed as squares when using PIL. Fonts (f.zip) frankventt

Zuzu-Typ avatar Jun 23 '17 14:06 Zuzu-Typ

Could you please re-upload the fonts to github, instead of a file hosting site that expires them and blocks wget?

wiredfool avatar Jun 26 '17 15:06 wiredfool

f.zip

hugovk avatar Jun 26 '17 15:06 hugovk

That doesn't have ParryHotter, xfiles, or woodcut.

wiredfool avatar Jun 26 '17 15:06 wiredfool

The files didn't expire. I took them down, because they aren't my property, so hosting them didn't feel right. f2.zip

Zuzu-Typ avatar Jun 26 '17 15:06 Zuzu-Typ

Ok, so I've poked at this some more. There's a clear problem with the first three font files.

Truetype fonts have at least one 'cmap' table (https://www.microsoft.com/typography/otspec/cmap.htm), and these have three. There is one with a Mac platform ID and one with a Windows platform ID, both with roughly equivalent contents. There's also an empty cmap of platformID0, platformEncodingId of 3. Deleting that empty table fixes the first three fonts. (using https://github.com/fonttools/fonttools) Additionally, the woodcut and parryhotter fonts had hdmx tables that fonttools couldn't interpret, so I had to hack those out as well.

I'm not sure why freetype is using the cmap that it's using, but that would be the next thing to look at.

wiredfool avatar Jun 26 '17 17:06 wiredfool

I found another font where the "J" isn't displayed or rather computed correctly. This time it is Littlelordfontleroy. Here you can see the code I used:

from PIL import Image, ImageFont, ImageDraw

font = ImageFont.truetype("littlelo.ttf", 100)

image = Image.new("RGBA", font.getsize("james P Sullivan"))

draw = ImageDraw.Draw(image)

draw.text((0,0),"james P Sullivan", font=font, fill=(0,0,0))

image.show()

Where this is the output when using a capital "J": jps -capital And this when using a non-capital "j" jps

Zuzu-Typ avatar Jul 03 '17 22:07 Zuzu-Typ

The 'J' metrics is a totally different issue, it looks like the x-advance is being used as the full width of the character for bounding box issues.

wiredfool avatar Jul 05 '17 07:07 wiredfool

I inspected Littlelordfontleroy in FontForge and several of the glyphs have a a negative Bearing X and are self-interesecting. Since the beginning of the rendering is at (0,0) it should be expected that the first letter gets clipped as there is no image to draw on. If you print with " james" instead, it works fine. This doesn't seem like a Pillow problem.

nawagers avatar Nov 07 '17 19:11 nawagers

It's not just Pillow. This is with Apple's font rendering, on a font shipped with the OS.

There's some extension into -x at the beginning of the line, and some beyond even that that's clipped. What Apple does do is align the visual edge of the glyph with the margin.

screen shot 2017-11-07 at 8 23 09 pm

Doing this properly is going to take a different api than we have, as it has to reference the baseline, return an extents, and the offset to the visual margin.

wiredfool avatar Nov 07 '17 20:11 wiredfool

I found another font where the "J" isn't displayed or rather computed correctly. This time it is Littlelordfontleroy.

When I try this with a somewhat recent build of master, I find that this looks a bit better now (maybe due to #4910, IIRC there were some fixes for negative x bearing in there): littlelo_1

Using the new font.getbbox function from #4959 you can shift the text by the negative bearing to get a better bounding box:

im2 = Image.new("RGBA", (-bbox[0]+bbox[2], -bbox[1]+bbox[3]))
d2 = ImageDraw.Draw(im2)
d2.text((-bbox[0],-bbox[1]), "james P Sullivan", font=font, fill="black")
im2.show()

littlelo_2

The 'j' is no longer cropped, because the text is no longer visually aligned with (0, 0).


For the first font, Parry Hotter, it seems to have three cmap tables:

C:\Windows\System32>D:\Downloads\freetype-demos-master\bin\ftdump.exe -c D:\Downloads\parryhotter.ttf
There is 1 face in this file.

----- Face number: 0 -----

font name entries
   family:              Parry Hotter

<snip>

charmaps (3)
   0: armn, platform 1, encoding  0, format  0, language 0
     0020-0022,0026-003b,003d,003f-005d,005f,0061-007b,007d,0082,0084,0091-0094,00c4,00d6,00dc,00df,00e4,00f6,00fc
   1: unic, platform 3, encoding  1, format  4, language 0
     0020-007e,00a1,00a7,00b0,00b4,00bf-00c5,00c7-00cf,00d1-00d4,00d6,00d9-00dc,00df-00e5,00e7-00ef,00f1-00f6,00f9-00fc,2018-201a,201c-201e,e000,e001
 * 2: unic, platform 0, encoding  3, format  4, language 0

I have found that specifying encoding="armn" allows this font to be displayed properly:

ft = ImageFont.truetype("D:\Downloads\parryhotter.ttf", 20, encoding="armn")
bbox = ft.getbbox("Parry Hotter")
image = Image.new("RGBA", (-bbox[0]+bbox[2], -bbox[1]+bbox[3]))
draw = ImageDraw.Draw(image)
draw.text((-bbox[0],-bbox[1]), "Parry Hotter", font=ft)
image.show()

(white text, might be hard to see in light GitHub style) parryhotter


How about these three though? They appear correctly in FontForge, but are displayed as squares when using PIL.

Frankfurter Venetian TT also displays correctly with encoding="armn":

charmaps (2)
   0: armn, platform 1, encoding  0, format  0, language 0
     0000,0008,0009,000d,001d,0020-007e,0080-00ac,00ae,00af,00b1,00b4,00b5,00bb,00bc,00be-00c2,00c4,00c7-00d6,00d8,00d9,00db-00dd,00e0-00ef,00f1-00f4,00f6-00f8,00fc
   1: symb, platform 3, encoding  0, format  4, language 0
     0020-007e,00a0-00ac,00ae-00ff,0152,0153,0160,0161,0178,0192,02c6,02dc,2013,2014,2018-201a,201c-201e,2020-2022,2026,2030,2039,203a,2122

(white text, might be hard to see in light GitHub style) Frnkvent


Doing this properly is going to take a different api than we have, as it has to reference the baseline, return an extents, and the offset to the visual margin.

I believe this part has been resolved by the addition of font.getbbox in #4959 and support for draw.text(..., anchor=...) in #4930.


Edit:

font.getsize("Segoe UI Symbol text that ends with a j")

This also seems to be working fine now:

(white text, might be hard to see in light GitHub style) seguisym

nulano avatar Jan 02 '22 11:01 nulano

Russrite.ttf, woodcut.ttf and xfiles.ttf also work with encoding="armn", and Hombre__.ttf doesn't even need encoding to be specified to work.

@nulano is there anything left to do here, or is this resolved?

radarhere avatar Oct 03 '22 02:10 radarhere

I believe this is resolved.

nulano avatar Oct 03 '22 02:10 nulano