freetype
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: [Freetype] rendering a string, using outlines, in mono


From: Turner, David
Subject: RE: [Freetype] rendering a string, using outlines, in mono
Date: Mon, 18 Oct 2004 10:26:54 +0200

Hello Vincent,

> so, is it normal (and what should i do to correct this) ? 
> Does my program do something wrong ? 
> 
Your program is incorrect. It doesn't compute top[n] correctly,
and it doesn't position the glyphs correctly in the final
bitmap anyway.

Here's some help:

 - first, it's important to realize that FreeType works in
   vector space with the Y-upwards convention, while most
   developers address bitmaps in pixel space with Y-downwards
   orientation.

   in the rest of this post, I'll write vector Y-upwards coordinates
   as (x,y), and bitmap Y-downwards ones as [X,Y]. I'll also
   consider that (x,y) are in floating point coordinates to not
   write the fixed-floating point conversions all the time.


 - when you compute the glyph string's bounding box as
   (xMin,yMin,xMax,yMax), this information gives you two
   important pieces of the puzzle:

     * the width and height of the corresponding bitmap
       i.e. [W,H] = [xMax-xMin,yMax-yMin]

     * the location of the original pen in the bitmap,
       at:  (ox,oy) = (-xMin,-yMin) or 
            [OX,OY] = [-xMin,bitmap.rows-yMin]

 - when you render the string, you must place the pen
   in the bitmap at coordinates that are relative to this
   original location, so you should have:

       pen.x = OX + pos[n].x
       pen.y = OY + pos[n].y

   you don't need top[n] or left[n] during the rendering, because
   you already have everything positionned for you.



Hope this help,s

- David Turner
- The FreeType Project  (www.freetype.org)




> thank you
> 
> Vincent TORRI
> 
> test program:
> /* gcc -O2 -Wall -o test test.c `freetype-config --libs --cflags` */
> 
> #include <freetype/freetype.h>
> #include <freetype/ftglyph.h>
> #include <freetype/ftoutln.h>
> #include <freetype/ftbbox.h>
> 
> 
> static FT_Library library; /* handle to library */ 
> 
> void
> create_mono_ppm (char *filename, unsigned char *bitmap, int pitch, int
> width, int height)
> {
>   FILE *file;
>   unsigned int i, j, off;
>   unsigned char num, mask;
> 
>   /* Open the ppm file */
>   file = fopen (filename, "w+b");
>   if (file == NULL)
>     {
>       printf ("The file can't be opened for writing\n");
>       return;
>     }
>   
>   /* En-tete */
> 
>   fprintf (file, "P3\n# colorbars.ppm\n%d %d\n256\n", width, height);
> 
>   off = 0;
>   for (j = 0 ; j < height ; j++)
>     {
>       for (i=0 ; i<width ; i++)
>       {
>         unsigned char val;
>         num = i >> 3; /* num of the byte we are currently reading */
>         unsigned char byte = bitmap[off + num];
>         mask = 128 >> (i & 7);
>         val = ((byte & mask) == mask) * 255;
>         fprintf (file, "%d %d %d\n",
>                  val, val, val);
>       }
>       off += pitch;
>     }
> 
>   fclose (file);
> }
> 
> void
> GetTextBoundingBox (FT_Face face, char *str)
> {
>   FT_UInt glyph_index;
>   FT_Bool use_kerning;
>   FT_UInt previous;
>   FT_Vector pos [100];
>   FT_Pos left[100];
>   FT_Pos top[100];
>   FT_Pos height[100];
>   FT_Vector pen;
>   FT_BBox bbox;
>   int n, l;
>   
>   FT_Outline out;
>   FT_Outline my_outline[100];
>   
>   pen.x = 0;
>   pen.y = 0;
>   l = strlen (str);
>   use_kerning = FT_HAS_KERNING (face);
>   previous = 0;
> 
>   printf ("get outlines\n");
> 
>   for (n=0 ; n<l ; n++)
>     {
>       glyph_index = FT_Get_Char_Index (face, str[n]);
>       if (use_kerning && previous && glyph_index)
>       {
>         FT_Vector delta;
> 
>         FT_Get_Kerning (face, previous, glyph_index,
>                         FT_KERNING_DEFAULT, &delta);
>         pen.x += delta.x >> 6;
>       }
> 
>       FT_Load_Glyph (face, glyph_index, FT_LOAD_RENDER |
> FT_LOAD_TARGET_MONO);
> 
> 
>       out = face->glyph->outline;
>       FT_Outline_New (face->glyph->library, out.n_points, 
> out.n_contours,
> &my_outline[n]);
>       FT_Outline_Copy (&out, &my_outline[n]);
>       height[n] = face->glyph->metrics.height >> 6;
>       left[n] = face->glyph->metrics.horiBearingX >> 6;
>       top[n] = (face->glyph->metrics.height -
> face->glyph->metrics.horiBearingY) >> 6;
>       pos[n].x = pen.x;
>       pos[n].y = pen.y;
> 
>       pen.x += face->glyph->advance.x >> 6;
>       previous = glyph_index;
>     }
> 
>   printf ("compute bbox\n");
> 
>   bbox.xMin = bbox.yMin = 32000;
>   bbox.xMax = bbox.yMax = -32000;
>   /* for each glyph image, compute its bounding box, */
>   /* translate it, and grow the string bbox */
>   for ( n = 0; n < l; n++ )
>     {
>       FT_BBox glyph_bbox;
> 
>       FT_Outline_Get_CBox (&(my_outline[n]),
>                        &glyph_bbox);
>       
>       printf ("  Outline Bbox %d: %ld %ld %ld %ld\n",n,
>             glyph_bbox.xMin >> 6, glyph_bbox.xMax >> 6,
>             glyph_bbox.yMin >> 6, glyph_bbox.yMax >> 6);
>       
>       glyph_bbox.xMin = glyph_bbox.xMin >> 6;
>       glyph_bbox.xMax = glyph_bbox.xMax >> 6;
>       glyph_bbox.yMin = glyph_bbox.yMin >> 6;
>       glyph_bbox.yMax = glyph_bbox.yMax >> 6;
> 
>       glyph_bbox.xMin += pos[n].x;
>       glyph_bbox.xMax += pos[n].x;
>       glyph_bbox.yMin += pos[n].y;
>       glyph_bbox.yMax += pos[n].y;
>       if (glyph_bbox.xMin < bbox.xMin)
>       bbox.xMin = glyph_bbox.xMin;
>       if (glyph_bbox.yMin < bbox.yMin)
>       bbox.yMin = glyph_bbox.yMin;
>       if (glyph_bbox.xMax > bbox.xMax)
>       bbox.xMax = glyph_bbox.xMax;
>       if (glyph_bbox.yMax > bbox.yMax)
>       bbox.yMax = glyph_bbox.yMax;
>     }
>   /* check that we really grew the string bbox */
>   if (bbox.xMin > bbox.xMax)
>     {
>       bbox.xMin = 0;
>       bbox.yMin = 0;
>       bbox.xMax = 0;
>       bbox.yMax = 0;
>     }
> 
>   printf ("fill final bitmap\n");
> 
>   FT_Bitmap bitmap_f;
>   
>   bitmap_f.rows = bbox.yMax - bbox.yMin;
>   if (bitmap_f.rows > 32000)
>     bitmap_f.rows = 32000;
>   bitmap_f.width = bbox.xMax - bbox.xMin;
>   if (bitmap_f.width > 32000)
>     bitmap_f.width = 32000;
>   bitmap_f.pitch = ((bitmap_f.width + 7) >> 3);
>   bitmap_f.buffer = (unsigned char *)malloc (sizeof (unsigned char) *
> 
> bitmap_f.pitch*bitmap_f.rows);
>   bitmap_f.pixel_mode = FT_PIXEL_MODE_MONO;
> 
>   printf ("box size : %d %d\n", bitmap_f.rows, bitmap_f.width);
> 
>   /* Filling of final bitmap with 0 */
>   memset (bitmap_f.buffer,
>         0,
>         sizeof (unsigned char)*bitmap_f.pitch*bitmap_f.rows);
> 
>   for ( n = 0; n < l; n++ )
>     {
>       FT_Vector pen;
> 
>       pen.x = pos[n].x - left[0];
>       pen.y = pos[n].y + 1;
> 
>       printf ("pos %c : %ld, %ld %ld %ld\n",str[n],
>             pen.x, pen.y, top[n], height[n]);
> 
>       FT_Outline_Translate (&my_outline[n], pen.x << 6, pen.y << 6);
>       FT_Outline_Get_Bitmap (library,
>                            &my_outline[n],
>                            &bitmap_f);
>       FT_Outline_Translate (&my_outline[n], -pen.x << 6, -pen.y << 6);
>       FT_Outline_Done (library, &my_outline[n]);
>     }
>   
>   create_mono_ppm ("AV.ppm",
>                  bitmap_f.buffer, bitmap_f.pitch,
>                  bitmap_f.width, bitmap_f.rows);
> }
> 
> int
> main (int argc, char *argv[])
> { 
>   FT_Face    face;       /* handle to face object */
>   FT_Error   error;
>   
>   FT_Init_FreeType (&library);
> 
>   FT_New_Face (library, 
> "/usr/share/fonts/ttf/vera/VeraBd.ttf", 0, &face);
> 
>   error = FT_Set_Char_Size (face,   /* handle to face object */  
>                           0,      /* char_width in 1/64th of 
> points */  
>                           16*64,  /* char_height in 1/64th of 
> points */  
>                           300,    /* horizontal device resolution */  
>                           300);   /* vertical device resolution */
> 
> 
>   /* Bounding Box et other... */
> 
>   GetTextBoundingBox (face, "gabcdefhiklmnorstuvwxz");
>   
>   return 1;
> }
> 
> 
> 
> 
> _______________________________________________
> Freetype mailing list
> address@hidden
> http://www.freetype.org/mailman/listinfo/freetype
> 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]