Разница в ширине отображаемого текста, измеренная между типами freetype и pango/cairo
Я пытаюсь предсказать, насколько широко будет выглядеть текст, отображаемый библиотекой pango, но я пытаюсь добиться этого в чистом виде Freetype для повышения производительности.
Чтобы ответить комментаторам - да, я измерил производительность с callgrind
инструмент. А pango проводит большую часть своего времени в fontconfig, который невозможно обойти. pango_layout_get_extents
тоже не очень быстро. В то же время производительность freetype невероятно быстрая, но, тем не менее, дает неточные результаты из-за отсутствия надлежащих настроек. К сожалению, я не могу публиковать рендеринг растровых изображений, так как я делаю только простые измерения - но это может быть стоящее усилие для реализации ради сравнения. Рендеринг в моем случае использования выполняется веб-браузером в SVG, и мне нужно только предсказать, какой будет длина отображаемого текста - следовательно, не предоставлять растровые изображения в вопросе, поскольку у меня нет кода рендеринга.
Моя тестовая программа запускается:
> ./freetype_text /usr/share/fonts/truetype/verdana.ttf "WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW"
Width: 374
Однако.. тот же текст с размером шрифта 10 (72dpi) отображается в pango с 340px. Измерение осуществляется по общему методу измерения макета с:
PangoRectangle logical_rect = {0, 0};
pango_layout_get_extents (layout, NULL, &logical_rect);
В чем может быть причина различий, которые я наблюдаю? Различия, которые я наблюдаю, колеблются от 0% до 15%.
Ниже моя программа тестирования freetype (скомпилировать с gcc freetype_text.c $(pkg-config --cflags --libs freetype2))
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_OUTLINE_H
#include FT_STROKER_H
#include FT_GLYPH_H
#include FT_TRUETYPE_IDS_H
static FT_Library library;
int main(int argc, char** argv)
{
FT_Error error = FT_Init_FreeType( &library );
if ( error ) {
return 1;
}
int i;
FT_Face face;
error = FT_New_Face( library, argv[1], 0, &face );
if(error) {
return 2;
}
FT_Set_Pixel_Sizes(face, 0, 10);
char* str = argv[2];
wchar_t ch = 0;
FT_GlyphSlot slot = face->glyph;
int w = 0;
int previous = 0;
while( (ch = *str) != 0) {
int glyph_index = FT_Get_Char_Index( face, ch );
error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT|FT_LOAD_NO_BITMAP);
str++;
w += slot->advance.x;
if(previous && glyph_index )
{
FT_Vector delta;
FT_Get_Kerning( face, previous, glyph_index, FT_KERNING_DEFAULT, &delta );
w += delta.x ;
}
previous = glyph_index;
}
printf("Width: %i\n", w/64);
return 0;
}