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: Vincent Torri
Subject: RE: [Freetype] rendering a string, using outlines, in mono
Date: Tue, 19 Oct 2004 11:10:53 +0200 (MEST)

Hello,

i've tried what you have suggested, but it does not work for characters
which have pixels below the origin, like the char 'g'. Actually, i've
already tried that solution, and i have left the 'g' in my string test
(see the end of the prog) to test such char.
With that solution, the bottom of 'g' is at the same vertical coord than
the bottom of all other chars.

In addition, there's something that i don't understand: i've checked all
the bearingY and yMax values of the chars of my test string, and (except
for 't'), they are all *equal*.
 So, according to the definition of bearingY (which is the distance
between the top of the glyph bitmap and the origin), all these chars *have 
to* be well vertically aligned. This is not the case. I should not have to
modify the pen.x value.

What do you think of that ?

Vincent TORRI

On Mon, 18 Oct 2004, Turner, David wrote:

> 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
> > 
> 
> _______________________________________________
> Freetype mailing list
> address@hidden
> http://www.freetype.org/mailman/listinfo/freetype
> 
> 




reply via email to

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