Конвертер GDF шрифтов (PHP класс)

9 комментариев

Многие из PHP кодеров наверняка замечали что в библиотеке GD, помимо использования шрифтов TrueType, FreeType, встроенных в GD шрифтов и т.д. можно использовать некие GDF шрифты.

Формат этот очень редкий и используется только в библиотеке GD. Конечно если хорошо погуглить то можно найти уже перекодированные шрифты, онлайн сервисы для перекодирования из TTF и десктопную программу 2002 года под винь для рисования GDF шрифтов и перекодированию из TTF. Но к сожалению, не все шрифты уже перекодированны да и что делать если нам нужен свой шрифт? Онлайн сервисы не всегда удобны. А десктопная программа — не всегда лучший выход.

Структура файла

Официальный мануал дает описание этого формата (пруф):

Описание, конечно, скудновато. Но, впринципе, этого достаточно чтобы разобраться в формате и написать свой конвертер. Кстати, пожалуй, надо обратить на следующее замечание в мануале:

The font file format is currently binary and architecture dependent. This means you should generate the font files on the same type of CPU as the machine you are running PHP on.

Если перевести:

Формат файла шрифта двоичный и зависим от архитектуры. Это означает, что вы должны генерировать файлы шрифтов на том же типе процессора, на котором запущен PHP.

По-идее это связанно с методом упаковки числа Int в двоичный формат. Разница будет при использовании 32битной архитиктуры и 64битной.

Описание класса

Возможности класса:

  • Конвертация шрифта TTF в GDF формат.
  • Создание своего GDF-шрифта из набора изображений

Методы класса:

/** Переконвертировать TTF-шрифт в GDF-шрифт
*
* @param string $ttf_file путь к файлу с TTF-шрифтом
* @param integer $char_size размер выходного шрифта в PT
* @param array $char_names [опционально] массив со списком конвертируемых символов, если не указанно, будут загруженны все символы
* @return string бинарное содержимое файла-шрифта, null - в случае неудачи
*/
function GenerateGdfFromTTF($ttf_file, $char_size, $char_names=null){}

/** Сгенерировать GDF-шрифт на основе списка изображений
*
* @param array $char_names массив с символами
* @param array $char_resources массив с списком путей к изображениям символов в порядке соответствующему параметру "$char_names"
* @param integer $char_width ширина всех символов
* @param integer $char_height высота всех символов
* @return string бинарное содержимое файла-шрифта, null - в случае неудачи
*/
function GenerateGdfFromFiles($char_names, $char_files, $char_width, $char_height){}

Примеры

Несколько примеров. Пример конвертации TTF в GDF:

include('class.GDFConverter.php');
$converter=new GDFConvertor();

$data_font=$converter->GenerateGdfFromTTF('./fonts/arial.ttf', 12);
file_put_contents('./fonts/test.gdf', $data_font);

Пример генерации GDF из набора изображений (в папке «chars» содержится набор картинок с символами именовыными в соответствии изображенному на них символу):

$files=glob('chars/*.png');

$chars=array();
foreach($files as $filename){
	$char=substr(basename($filename), 0, 1);
	$chars[$char]=$filename;
}

include('class.GDFConverter.php');
$converter=new GDFConvertor();

$data_font=$converter->GenerateGdfFromFiles(array_keys($chars), $chars, 6, 7);
file_put_contents('./fonts/test.gdf', $data_font);

И последний пример. Вывод строки с помощью GDF шрифта:

$string='foobar';

$image=imagecreate(100, 100);
$font_res=imageloadfont('./fonts/test.gdf');

imagefilledrectangle($image, 0, 0, imagesx($image), imagesy($image), imagecolorallocate($image, 255, 255, 255));
imagestring($image, $font_res, 10, 50, $string, imagecolorallocate($image, 0, 0, 0));

Скачать

Скачать архив с классом: class.GDFConverter (3кб)

Пользуйтесь на здоровье.

  1. Aseg

    @param array $char_names [опционально] массив со списком конвертируемых символов, если не указанно, будут загруженны все символы

    Скажите а зачем это вынесенно в отдельный параметр? Не могу понять смысла конвертации лишь выборочных символов.

    1. Дмитрий Амиров Автор

      Все очнь просто, чем меньше символов указанно тем меньше будет весить выходящий файл.

      1. Aseg

        На много ли?

        Да и вот обратил еще у вас баг, указываешь допустим всего лишь два символа «0» и «9», а добавляются все цифры, почему так? По идее должно добавится всего два символа?

        1. Дмитрий Амиров Автор

          Да, на относительно много. Формат такой. Каждый символ весит height*width байт. Для среднестатистического шрифта это 100-150 байт на символ. Десять лишних символов это уже лишний килобайт ну и тд. Надо оно или нет, решать вам)

          Формат GDF обязывает описывать каждый символ по таблице ASCII начиная от стартового. То есть для того чтобы включить символы «0 и «9» в шрифт, приходится описывать символ «0», затем следующие символы по таблице, до девятки (т.е. «1», «2», «3», «4», «5», «7», «8») и только потом «9». В итоге получаем — просили всего два символа, а получили 10. К сожалению от этого избавиться не возможно. Вот такой вот кривой формат =(

          1. Aseg

            А где вообще можно почитать про формат gdf? Перерыл весь интернет и ничего не нашел.

            1. Дмитрий Амиров Автор

              К сожалению, кроме оффициального мануала других источников нет. Все, что я писал, было выяснено личным опытным путем. Если вас интересует что то конкретное, спрашивайте, не стесняйтесь.

          2. Aseg

            Да не то чтобы что то конкретное. Просто любопытство, не более =) Но спасибо за отзывчивость.

  2. Игорь

    И последний пример. Вывод строки с помощью GDF шрифта:
    Кириллицу не поддерживает. Пробовал шрифт который работает в модуле друпала а через ваш php код не работает. Видимо для вывода кириллицы нужен другой php код?

    1. Дмитрий Амиров Автор

      Да нет, боюсь что разницы кирилица или латиница быть не должно. Хотя я лично насколько я помню не проверял. Попробуйте поэксперементируйте с кодировками UTF-8/cp1251

Добавить комментарий

Прочли запись? Понравилась? Не стесняйтесь, оставьте, пожалуйста, свой комментарий. Мне очень интересно, что вы думаете об этом. Кстати в комментарии вы можете задать мне любой вопрос. Я обязательно отвечу.

Вы можете оставить коментарий анонимно, для этого можно не указывать Имя и email. Все комментарии проходят модерацию, поэтому ваш комментарий появится не сразу.