[Top][All Lists]
[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
>