18

I'm using Imagick to generate simple logos, which are just text on a background.

I'm usually looping through all available fonts, to present the user with a choice of different renderings for every font (one image per font).

The problem is, some fonts don't support the ASCII characters (I think they've been designed for a given language only). And I guess that some of the fonts which support ASCII characters, will fail with non-ASCII characters as well.

Anyway, I end up with images such as these:

Imagick non-supported font characters Imagick non-supported font characters Imagick non-supported font characters

Is there a programmatic way in Imagick to tell whether a given font supports all the characters in a given string?

That would help me filter out those fonts which do not support the text the user typed in, and avoid displaying any garbage images such as the ones above.

BenMorel
  • 34,448
  • 50
  • 182
  • 322
  • After a bit of Googling around, it looks doubtful - it seems you'd have to parse the font file directly, which isn't trivial. – Pekka Dec 16 '13 at 14:30
  • @Pekka웃 I would definitely avoid doing so... Maybe there are other libraries than Imagick to query TTF fonts, hopefully someone will shed some light on this! – BenMorel Dec 16 '13 at 14:31
  • Possibly not in PHP. There are tools on the *nix command line: [Get Supported Unicode Ranges from Font *.ttf file on Ubuntu](http://superuser.com/q/409317) But apparently even they aren't 100% reliable – Pekka Dec 16 '13 at 14:38
  • Stick with one of the key fonts that support utf-8 like arial, times new roman, helvetica and you should get everything covered using fancier fonts can often result in non extended charsets being covered. If you want to do it by hand you can open the font file in windows charmap and see exactly what chars the font supports. There's also https://github.com/PhenX/php-font-lib which has maps for the fonts it uses defining if they're avilable or not etc, tcpdf also has alot of fonts/fontmaps inside its archive – Dave Dec 16 '13 at 14:42
  • 2
    In theory you could draw character which isn't supported for sure and compare characters you are interested in against that one. If they match pixel per pixel, other character is probably not supported as well. If you manage to pull this off, you can automatically build cache files, mapping fonts and supported chars. This is probably not what you are after and suggestions by Pekka and Dave seem far more reasonable. Also, this could potentially fail, if unsupported chars are printed as question marks. – Mikk Dec 16 '13 at 14:48
  • 1
    @Mikk that is a great idea! I thought about measuring the resulting character's width (using `imagettfbbox()` for example) but that would be fallible. Actually comparing the result is way better. – Pekka Dec 16 '13 at 14:58
  • Interesting idea guys. @Dave unfortunately, I specifically do want to use fancy fonts here, and don't have really control over the large quantity of fonts available, hence the need for an automated solution. – BenMorel Dec 16 '13 at 15:15
  • Not one I know of that is reliable your best bet would be to compare the error char images vs generated but as you posted above they're not always the same! different font sizing will mean you have different widths and heights as well so you can't really do a bounding compare either – Dave Dec 16 '13 at 15:25
  • 1
    The replacement character is in the Unicode standard at codepoint U+FFFD (rectangle and/or questionmark symbol). So you can use that to compare against. But thinking of it, you might as well compare A to B. If they are the same then the font is useless. – allcaps Dec 16 '13 at 16:14

1 Answers1

2

I don't know a way using imagemagik, but you could use the php-font-parser library from here:

https://github.com/Pomax/PHP-Font-Parser

Specifically, you can parse a font for each letter in your required string and check the return value:

    $fonts = array("myfont.ttf");

    /**
     * For this test, we'll print the header information for the
     * loaded font, and try to find the letter "g".
     */
    $letter = "g";
    $json = false;
    while($json === false && count($fonts)>0) {
            $font = new OTTTFont(array_pop($fonts));
            echo "font header data:\n" . $font->toString() . "\n";
            $data = $font->get_glyph($letter);
            if($data!==false) {
                    $json = $data->toJSON(); }}

    if($json===false) { die("the letter '$letter' could not be found!"); }
    echo "glyph information for '$letter':\n" . $json;

Above code comes from the font parser projects fonttest.php class:

https://github.com/Pomax/PHP-Font-Parser/blob/master/fonttest.php

DEzra
  • 2,978
  • 5
  • 31
  • 50