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: Mon, 18 Oct 2004 10:03:01 +0200 (MEST)

Hello,

i go on investigating outlines in mono and i have a question about
vertical alignment in a horizontal layout. First, there's below a test
program which creates a .ppm of some the lower case letters

i draw them using their outlines. Line 173, i have increased
intentionnally pen.y by 1, to hightlight what i want to point out.

Looking at letters c, e, o and s in the ppm file, i assume that they
are correctly vertically aligned.

But, then, i think that letters f, h, i, k, l, m, n, r, t, v, w, x and
z should be on the same horizontal line, but they are at least 1 pixel
above.

More strange (for me): letters h, i, k and l are not 1 pixel above
letter c, but 2 pixels above. Another strange thing: letter a and b
(for example) are not on the same horizontal line.

so, is it normal (and what should i do to correct this) ? Does my program
do something wrong ? 

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;
}






reply via email to

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