Hi all, The attached program main.c is modified from https://www.freetype.org/freetype2/docs/tutorial/example1.c. Compile it with
gcc $(pkg-config --cflags --libs freetype2) main.c -o main
and run it with
./main /path/to/FreeSerif.ttf
where FreeSerif.ttf can be downloaded from
http://ftp.gnu.org/gnu/freefont/freefont-ttf-20120503.zip (the specific
release of FreeFont is important!).
The program loads two glyphs (codepoints 0x21d0 LEFTWARDS DOUBLE ARROW and
0x21d1 UPWARDS DOUBLE ARROW) and renders them at 200dpi horizontal
resolution and 100dpi vertical resolution. The result (bad.txt) shows that
while the horizontal arrow is correctly stretched by a factor of 2 in x,
the vertical arrow is incorrectly stretched in y instead, and also badly
centered in y.
Interestingly, additionally passing FT_LOAD_FORCE_AUTOHINT to the
FT_Load_Char call fixes the problem (good.txt): now the vertical arrow is
correctly stretched in x as well, and correctly centered in y. One may
thus be led to believe that the font's native hinter perhaps(?) badly fails
when hinting with different x and y resolutions. However, passing
FT_LOAD_NO_HINTING instead of FT_LOAD_FORCE_AUTOHINT does *not* fix the
problem, and yields results similar to bad.txt, so that suggests it's not
the font's native hinter's fault.
I'm not really sure whether this behavior is a bug in FreeType or perhaps a
problem with the font... Thanks in advance for your insights,
Antony Lee
++
**+
+**+
****+
+****+
+ ******+
+**+ +***+**+
+****+ ***+ +**+
+****++ +**+ +**+
+*****+ **+ +**+
+*************************************************+ +**+ **+
+****+ +**+ ***+
+*****+ +***+ ***+
+*****+ +***+ ****+
+*****+ +**+*+ *+**+
+*****+ +** *+ *++**+
+****+ **+ *+ *+ **+
+*************************************************+ ++ *+ *+ +*
+*****+ *+ *+
+****++ *+ *+
+****+ *+ *+
+**+ *+ *+
*+ *+
*+ *+
*+ *+
*+ *+
*+ *+
*+ *+
*+ *+
*+ *+
*+ *+
*+ *+
*+ *+
*+ *+
*+ *+
*+ *+
*+ *+
*+ *+
*+ *+
*+ *+
*+ *+
*+ *+
*+ *+
*+ *+
*+ *+
*+ *+
*+ *+
#include <stdio.h>
#include <string.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#define WIDTH 100
#define HEIGHT 50
unsigned char image[HEIGHT][WIDTH];
void draw_bitmap( FT_Bitmap* bitmap, FT_Int x, FT_Int y )
{
FT_Int i, j, p, q;
FT_Int x_max = x + bitmap->width;
FT_Int y_max = y + bitmap->rows;
for ( i = x, p = 0; i < x_max; i++, p++ ) {
for ( j = y, q = 0; j < y_max; j++, q++ ) {
if ( i < 0 || j < 0 || i >= WIDTH || j >= HEIGHT ) continue;
image[j][i] |= bitmap->buffer[q * bitmap->width + p];
}
}
}
void show_image( void )
{
int i, j;
for ( i = 0; i < HEIGHT; i++ ) {
for ( j = 0; j < WIDTH; j++ )
putchar( image[i][j] == 0 ? ' '
: image[i][j] < 128 ? '+'
: '*' );
putchar( '\n' );
}
}
int
main( int argc, char** argv )
{
FT_Library library;
FT_Face face;
FT_GlyphSlot slot;
FT_Matrix matrix; /* transformation matrix */
FT_Vector pen; /* untransformed origin */
FT_Error error;
char* filename;
FT_ULong text[2];
int target_height;
int n, num_chars;
if ( argc != 2 )
{
exit( 1 );
}
filename = argv[1];
text[0] = 0x21d0;
text[1] = 0x21d1;
num_chars = 2;
target_height = HEIGHT;
error = FT_Init_FreeType( &library );
error = FT_New_Face( library, filename, 0, &face );
error = FT_Set_Char_Size( face, 24 * 64, 0, 200, 100 ); /* different x and y! */
slot = face->glyph;
matrix.xx = (FT_Fixed)( 1 * 0x10000L );
matrix.xy = (FT_Fixed)( 0 * 0x10000L );
matrix.yx = (FT_Fixed)( 0 * 0x10000L );
matrix.yy = (FT_Fixed)( 1 * 0x10000L );
pen.x = 0 * 64;
pen.y = ( target_height - 25 ) * 64;
for ( n = 0; n < num_chars; n++ )
{
FT_Set_Transform( face, &matrix, &pen );
error = FT_Load_Char( face, text[n], FT_LOAD_RENDER );
if ( error ) continue;
draw_bitmap( &slot->bitmap,
slot->bitmap_left,
target_height - slot->bitmap_top );
pen.x += slot->advance.x;
pen.y += slot->advance.y;
}
show_image();
FT_Done_Face ( face );
FT_Done_FreeType( library );
return 0;
}
/* EOF */
+*+
+*****+
+*********+
+******+******++
++*****++
++*****++
++******+
+******++
++********
********++
+**+ ++****++****
****++****++
+****+ +****+ ****
**** +****+
+*****+ ++ ****
**** ++
+*****+ ****
****
++************************************************ ****
****
++************************************************** ****
****
++*****+ ****
****
+*****++ ****
****
******+ ****
****
+*****+ ****
****
+*****+ ****
****
++************************************************** ****
****
++************************************************ ****
****
++****+ ****
****
+*****+ ****
****
+****+ ****
****
+**+ ****
****
****
****
****
****
****
****
****
****
++++
++++
