]> git.imager.perl.org - imager.git/blobdiff - font.c
try to generate all coverage into the one cover_db
[imager.git] / font.c
diff --git a/font.c b/font.c
index e228fbab859812813c4797d1ceac246868823379..efb8355022b77db6fe3d2790063586c01ff5848b 100644 (file)
--- a/font.c
+++ b/font.c
@@ -1,4 +1,5 @@
 #include "imager.h"
+#include "imrender.h"
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -8,7 +9,6 @@
 #include <stdlib.h>
 
 #ifdef HAVE_LIBT1
-#include <t1lib.h>
 #endif
 
 
@@ -49,690 +49,6 @@ Some of these functions are internal.
 
 */
 
-/* 
-=item i_init_fonts()
-
-Initialize font rendering libraries if they are avaliable.
-
-=cut
-*/
-
-undef_int 
-i_init_fonts(int t1log) {
-  mm_log((1,"Initializing fonts\n"));
-
-#ifdef HAVE_LIBT1
-  i_init_t1(t1log);
-#endif
-  
-#ifdef HAVE_LIBTT
-  i_init_tt();
-#endif
-
-#ifdef HAVE_FT2
-  if (!i_ft2_init())
-    return 0;
-#endif
-
-  return(1); /* FIXME: Always true - check the return values of the init_t1 and init_tt functions */
-}
-
-
-
-
-#ifdef HAVE_LIBT1
-
-static int t1_get_flags(char const *flags);
-static char *t1_from_utf8(char const *in, int len, int *outlen);
-
-static void t1_push_error(void);
-
-static int t1_active_fonts = 0;
-static int t1_initialized = 0;
-
-/* 
-=item i_init_t1(t1log)
-
-Initializes the t1lib font rendering engine.
-
-=cut
-*/
-
-undef_int
-i_init_t1(int t1log) {
-  int init_flags = IGNORE_CONFIGFILE|IGNORE_FONTDATABASE;
-  mm_log((1,"init_t1()\n"));
-
-  if (t1_active_fonts) {
-    mm_log((1, "Cannot re-initialize T1 - active fonts\n"));
-    return 1;
-  }
-
-  if (t1_initialized) {
-    T1_CloseLib();
-  }
-  
-  if (t1log)
-    init_flags |= LOGFILE;
-  if ((T1_InitLib(init_flags) == NULL)){
-    mm_log((1,"Initialization of t1lib failed\n"));
-    return(1);
-  }
-  T1_SetLogLevel(T1LOG_DEBUG);
-  i_t1_set_aa(1); /* Default Antialias value */
-
-  ++t1_initialized;
-
-  return(0);
-}
-
-
-/* 
-=item i_close_t1()
-
-Shuts the t1lib font rendering engine down.
-
-  This it seems that this function is never used.
-
-=cut
-*/
-
-void
-i_close_t1(void) {
-  T1_CloseLib();
-  t1_initialized = 0;
-}
-
-
-/*
-=item i_t1_new(pfb, afm)
-
-Loads the fonts with the given filenames, returns its font id
-
- pfb -  path to pfb file for font
- afm -  path to afm file for font
-
-=cut
-*/
-
-int
-i_t1_new(char *pfb,char *afm) {
-  int font_id;
-
-  mm_log((1,"i_t1_new(pfb %s,afm %s)\n",pfb,(afm?afm:"NULL")));
-  font_id = T1_AddFont(pfb);
-  if (font_id<0) {
-    mm_log((1,"i_t1_new: Failed to load pfb file '%s' - return code %d.\n",pfb,font_id));
-    return font_id;
-  }
-  
-  if (afm != NULL) {
-    mm_log((1,"i_t1_new: requesting afm file '%s'.\n",afm));
-    if (T1_SetAfmFileName(font_id,afm)<0) mm_log((1,"i_t1_new: afm loading of '%s' failed.\n",afm));
-  }
-
-  ++t1_active_fonts;
-
-  return font_id;
-}
-
-/*
-=item i_t1_destroy(font_id)
-
-Frees resources for a t1 font with given font id.
-
-   font_id - number of the font to free
-
-=cut
-*/
-
-int
-i_t1_destroy(int font_id) {
-  mm_log((1,"i_t1_destroy(font_id %d)\n",font_id));
-
-  --t1_active_fonts;
-
-  return T1_DeleteFont(font_id);
-}
-
-
-/*
-=item i_t1_set_aa(st)
-
-Sets the antialiasing level of the t1 library.
-
-   st - 0 =  NONE, 1 = LOW, 2 =  HIGH.
-
-=cut
-*/
-
-void
-i_t1_set_aa(int st) {
-  int i;
-  unsigned long cst[17];
-  switch(st) {
-  case 0:
-    T1_AASetBitsPerPixel( 8 );
-    T1_AASetLevel( T1_AA_NONE );
-    T1_AANSetGrayValues( 0, 255 );
-    mm_log((1,"setting T1 antialias to none\n"));
-    break;
-  case 1:
-    T1_AASetBitsPerPixel( 8 );
-    T1_AASetLevel( T1_AA_LOW );
-    T1_AASetGrayValues( 0,65,127,191,255 );
-    mm_log((1,"setting T1 antialias to low\n"));
-    break;
-  case 2:
-    T1_AASetBitsPerPixel(8);
-    T1_AASetLevel(T1_AA_HIGH);
-    for(i=0;i<17;i++) cst[i]=(i*255)/16;
-    T1_AAHSetGrayValues( cst );
-    mm_log((1,"setting T1 antialias to high\n"));
-  }
-}
-
-
-/* 
-=item i_t1_cp(im, xb, yb, channel, fontnum, points, str, len, align)
-
-Interface to text rendering into a single channel in an image
-
-   im        pointer to image structure
-   xb        x coordinate of start of string
-   yb        y coordinate of start of string ( see align )
-   channel - destination channel
-   fontnum - t1 library font id
-   points  - number of points in fontheight
-   str     - string to render
-   len     - string length
-   align   - (0 - top of font glyph | 1 - baseline )
-
-=cut
-*/
-
-undef_int
-i_t1_cp(i_img *im,int xb,int yb,int channel,int fontnum,float points,char* str,int len,int align, int utf8, char const *flags) {
-  GLYPH *glyph;
-  int xsize,ysize,x,y;
-  i_color val;
-  int mod_flags = t1_get_flags(flags);
-
-  unsigned int ch_mask_store;
-  
-  if (im == NULL) { mm_log((1,"i_t1_cp: Null image in input\n")); return(0); }
-
-  if (utf8) {
-    int worklen;
-    char *work = t1_from_utf8(str, len, &worklen);
-    glyph=T1_AASetString( fontnum, work, worklen, 0, mod_flags, points, NULL);
-    myfree(work);
-  }
-  else {
-    glyph=T1_AASetString( fontnum, str, len, 0, mod_flags, points, NULL);
-  }
-  if (glyph == NULL)
-    return 0;
-
-  mm_log((1,"metrics: ascent: %d descent: %d\n",glyph->metrics.ascent,glyph->metrics.descent));
-  mm_log((1," leftSideBearing: %d rightSideBearing: %d\n",glyph->metrics.leftSideBearing,glyph->metrics.rightSideBearing));
-  mm_log((1," advanceX: %d  advanceY: %d\n",glyph->metrics.advanceX,glyph->metrics.advanceY));
-  mm_log((1,"bpp: %d\n",glyph->bpp));
-  
-  xsize=glyph->metrics.rightSideBearing-glyph->metrics.leftSideBearing;
-  ysize=glyph->metrics.ascent-glyph->metrics.descent;
-  
-  mm_log((1,"width: %d height: %d\n",xsize,ysize));
-
-  ch_mask_store=im->ch_mask;
-  im->ch_mask=1<<channel;
-
-  if (align==1) { xb+=glyph->metrics.leftSideBearing; yb-=glyph->metrics.ascent; }
-  
-  for(y=0;y<ysize;y++) for(x=0;x<xsize;x++) {
-    val.channel[channel]=glyph->bits[y*xsize+x];
-    i_ppix(im,x+xb,y+yb,&val);
-  }
-  
-  im->ch_mask=ch_mask_store;
-  return 1;
-}
-
-
-/*
-=item i_t1_bbox(handle, fontnum, points, str, len, cords)
-
-function to get a strings bounding box given the font id and sizes
-
-   handle  - pointer to font handle   
-   fontnum - t1 library font id
-   points  - number of points in fontheight
-   str     - string to measure
-   len     - string length
-   cords   - the bounding box (modified in place)
-
-=cut
-*/
-
-int
-i_t1_bbox(int fontnum,float points,const char *str,int len,int cords[6], int utf8,char const *flags) {
-  BBox bbox;
-  BBox gbbox;
-  int mod_flags = t1_get_flags(flags);
-  int advance;
-  
-  mm_log((1,"i_t1_bbox(fontnum %d,points %.2f,str '%.*s', len %d)\n",fontnum,points,len,str,len));
-  T1_LoadFont(fontnum);  /* FIXME: Here a return code is ignored - haw haw haw */ 
-  if (utf8) {
-    int worklen;
-    char *work = t1_from_utf8(str, len, &worklen);
-    bbox = T1_GetStringBBox(fontnum,work,worklen,0,mod_flags);
-    myfree(work);
-  }
-  else {
-    bbox = T1_GetStringBBox(fontnum,(char *)str,len,0,mod_flags);
-  }
-  gbbox = T1_GetFontBBox(fontnum);
-  advance = T1_GetStringWidth(fontnum, (char *)str, len, 0, mod_flags);
-  
-  mm_log((1,"bbox: (%d,%d,%d,%d)\n",
-         (int)(bbox.llx*points/1000),
-         (int)(gbbox.lly*points/1000),
-         (int)(bbox.urx*points/1000),
-         (int)(gbbox.ury*points/1000),
-         (int)(bbox.lly*points/1000),
-         (int)(bbox.ury*points/1000) ));
-
-
-  cords[BBOX_NEG_WIDTH]=((float)bbox.llx*points)/1000;
-  cords[BBOX_POS_WIDTH]=((float)bbox.urx*points)/1000;
-
-  cords[BBOX_GLOBAL_DESCENT]=((float)gbbox.lly*points)/1000;
-  cords[BBOX_GLOBAL_ASCENT]=((float)gbbox.ury*points)/1000;
-
-  cords[BBOX_DESCENT]=((float)bbox.lly*points)/1000;
-  cords[BBOX_ASCENT]=((float)bbox.ury*points)/1000;
-
-  cords[BBOX_ADVANCE_WIDTH] = ((float)advance * points)/1000;
-  cords[BBOX_RIGHT_BEARING] = 
-    cords[BBOX_ADVANCE_WIDTH] - cords[BBOX_POS_WIDTH];
-
-  return BBOX_RIGHT_BEARING+1;
-}
-
-
-/*
-=item i_t1_text(im, xb, yb, cl, fontnum, points, str, len, align)
-
-Interface to text rendering in a single color onto an image
-
-   im      - pointer to image structure
-   xb      - x coordinate of start of string
-   yb      - y coordinate of start of string ( see align )
-   cl      - color to draw the text in
-   fontnum - t1 library font id
-   points  - number of points in fontheight
-   str     - char pointer to string to render
-   len     - string length
-   align   - (0 - top of font glyph | 1 - baseline )
-
-=cut
-*/
-
-undef_int
-i_t1_text(i_img *im,int xb,int yb,const i_color *cl,int fontnum,float points,const char* str,int len,int align, int utf8, char const *flags) {
-  GLYPH *glyph;
-  int xsize,ysize,x,y,ch;
-  i_color val;
-  unsigned char c,i;
-  int mod_flags = t1_get_flags(flags);
-
-  if (im == NULL) { mm_log((1,"i_t1_cp: Null image in input\n")); return(0); }
-
-  if (utf8) {
-    int worklen;
-    char *work = t1_from_utf8(str, len, &worklen);
-    glyph=T1_AASetString( fontnum, work, worklen, 0, mod_flags, points, NULL);
-    myfree(work);
-  }
-  else {
-    /* T1_AASetString() accepts a char * not a const char */
-    glyph=T1_AASetString( fontnum, (char *)str, len, 0, mod_flags, points, NULL);
-  }
-  if (glyph == NULL)
-    return 0;
-
-  mm_log((1,"metrics:  ascent: %d descent: %d\n",glyph->metrics.ascent,glyph->metrics.descent));
-  mm_log((1," leftSideBearing: %d rightSideBearing: %d\n",glyph->metrics.leftSideBearing,glyph->metrics.rightSideBearing));
-  mm_log((1," advanceX: %d advanceY: %d\n",glyph->metrics.advanceX,glyph->metrics.advanceY));
-  mm_log((1,"bpp: %d\n",glyph->bpp));
-  
-  xsize=glyph->metrics.rightSideBearing-glyph->metrics.leftSideBearing;
-  ysize=glyph->metrics.ascent-glyph->metrics.descent;
-  
-  mm_log((1,"width: %d height: %d\n",xsize,ysize));
-
-  if (align==1) { xb+=glyph->metrics.leftSideBearing; yb-=glyph->metrics.ascent; }
-  
-  for(y=0;y<ysize;y++) for(x=0;x<xsize;x++) {
-    c=glyph->bits[y*xsize+x];
-    i=255-c;
-    i_gpix(im,x+xb,y+yb,&val);
-    for(ch=0;ch<im->channels;ch++) val.channel[ch]=(c*cl->channel[ch]+i*val.channel[ch])/255;
-    i_ppix(im,x+xb,y+yb,&val);
-  }
-  return 1;
-}
-
-/*
-=item t1_get_flags(flags)
-
-Processes the characters in I<flags> to create a mod_flags value used
-by some T1Lib functions.
-
-=cut
- */
-static int
-t1_get_flags(char const *flags) {
-  int mod_flags = T1_KERNING;
-
-  while (*flags) {
-    switch (*flags++) {
-    case 'u': case 'U': mod_flags |= T1_UNDERLINE; break;
-    case 'o': case 'O': mod_flags |= T1_OVERLINE; break;
-    case 's': case 'S': mod_flags |= T1_OVERSTRIKE; break;
-      /* ignore anything we don't recognize */
-    }
-  }
-
-  return mod_flags;
-}
-
-/*
-=item t1_from_utf8(char const *in, int len, int *outlen)
-
-Produces an unencoded version of I<in> by dropping any Unicode
-character over 255.
-
-Returns a newly allocated buffer which should be freed with myfree().
-Sets *outlen to the number of bytes used in the output string.
-
-=cut
-*/
-
-static char *
-t1_from_utf8(char const *in, int len, int *outlen) {
-  /* at this point len is from a perl SV, so can't approach MAXINT */
-  char *out = mymalloc(len+1); /* checked 5Nov05 tonyc */
-  char *p = out;
-  unsigned long c;
-
-  while (len) {
-    c = i_utf8_advance(&in, &len);
-    if (c == ~0UL) {
-      myfree(out);
-      i_push_error(0, "invalid UTF8 character");
-      return 0;
-    }
-    /* yeah, just drop them */
-    if (c < 0x100) {
-      *p++ = (char)c;
-    }
-  }
-  *p = '\0';
-  *outlen = p - out;
-
-  return out;
-}
-
-/*
-=item i_t1_has_chars(font_num, text, len, utf8, out)
-
-Check if the given characters are defined by the font.  Note that len
-is the number of bytes, not the number of characters (when utf8 is
-non-zero).
-
-out[char index] will be true if the character exists.
-
-Accepts UTF-8, but since T1 can only have 256 characters, any chars
-with values over 255 will simply be returned as false.
-
-Returns the number of characters that were checked.
-
-=cut
-*/
-
-int
-i_t1_has_chars(int font_num, const char *text, int len, int utf8,
-               char *out) {
-  int count = 0;
-  
-  mm_log((1, "i_t1_has_chars(font_num %d, text %p, len %d, utf8 %d)\n", 
-          font_num, text, len, utf8));
-
-  i_clear_error();
-  if (T1_LoadFont(font_num)) {
-    t1_push_error();
-    return 0;
-  }
-
-  while (len) {
-    unsigned long c;
-    if (utf8) {
-      c = i_utf8_advance(&text, &len);
-      if (c == ~0UL) {
-        i_push_error(0, "invalid UTF8 character");
-        return 0;
-      }
-    }
-    else {
-      c = (unsigned char)*text++;
-      --len;
-    }
-    
-    if (c >= 0x100) {
-      /* limit of 256 characters for T1 */
-      *out++ = 0;
-    }
-    else {
-      char const * name = T1_GetCharName(font_num, (unsigned char)c);
-
-      if (name) {
-        *out++ = strcmp(name, ".notdef") != 0;
-      }
-      else {
-        mm_log((2, "  No name found for character %lx\n", c));
-        *out++ = 0;
-      }
-    }
-    ++count;
-  }
-
-  return count;
-}
-
-/*
-=item i_t1_face_name(font_num, name_buf, name_buf_size)
-
-Copies the face name of the given C<font_num> to C<name_buf>.  Returns
-the number of characters required to store the name (which can be
-larger than C<name_buf_size>, including the space required to store
-the terminating NUL).
-
-If name_buf is too small (as specified by name_buf_size) then the name
-will be truncated.  name_buf will always be NUL termintaed.
-
-=cut
-*/
-
-int
-i_t1_face_name(int font_num, char *name_buf, size_t name_buf_size) {
-  char *name;
-
-  T1_errno = 0;
-  if (T1_LoadFont(font_num)) {
-    t1_push_error();
-    return 0;
-  }
-  name = T1_GetFontName(font_num);
-
-  if (name) {
-    strncpy(name_buf, name, name_buf_size);
-    name_buf[name_buf_size-1] = '\0';
-    return strlen(name) + 1;
-  }
-  else {
-    t1_push_error();
-    return 0;
-  }
-}
-
-int
-i_t1_glyph_name(int font_num, unsigned long ch, char *name_buf, 
-                 size_t name_buf_size) {
-  char *name;
-
-  i_clear_error();
-  if (ch > 0xFF) {
-    return 0;
-  }
-  if (T1_LoadFont(font_num)) {
-    t1_push_error();
-    return 0;
-  }
-  name = T1_GetCharName(font_num, (unsigned char)ch);
-  if (name) {
-    if (strcmp(name, ".notdef")) {
-      strncpy(name_buf, name, name_buf_size);
-      name_buf[name_buf_size-1] = '\0';
-      return strlen(name) + 1;
-    }
-    else {
-      return 0;
-    }
-  }
-  else {
-    t1_push_error();
-    return 0;
-  }
-}
-
-static void
-t1_push_error(void) {
-  switch (T1_errno) {
-  case 0: 
-    i_push_error(0, "No error"); 
-    break;
-
-#ifdef T1ERR_SCAN_FONT_FORMAT
-  case T1ERR_SCAN_FONT_FORMAT:
-    i_push_error(T1ERR_SCAN_FONT_FORMAT, "SCAN_FONT_FORMAT"); 
-    break;
-#endif
-
-#ifdef T1ERR_SCAN_FILE_OPEN_ERR
-  case T1ERR_SCAN_FILE_OPEN_ERR:
-    i_push_error(T1ERR_SCAN_FILE_OPEN_ERR, "SCAN_FILE_OPEN_ERR"); 
-    break;
-#endif
-
-#ifdef T1ERR_SCAN_OUT_OF_MEMORY
-  case T1ERR_SCAN_OUT_OF_MEMORY:
-    i_push_error(T1ERR_SCAN_OUT_OF_MEMORY, "SCAN_OUT_OF_MEMORY"); 
-    break;
-#endif
-
-#ifdef T1ERR_SCAN_ERROR
-  case T1ERR_SCAN_ERROR:
-    i_push_error(T1ERR_SCAN_ERROR, "SCAN_ERROR"); 
-    break;
-#endif
-
-#ifdef T1ERR_SCAN_FILE_EOF
-  case T1ERR_SCAN_FILE_EOF:
-    i_push_error(T1ERR_SCAN_FILE_EOF, "SCAN_FILE_EOF"); 
-    break;
-#endif
-
-#ifdef T1ERR_PATH_ERROR
-  case T1ERR_PATH_ERROR:
-    i_push_error(T1ERR_PATH_ERROR, "PATH_ERROR"); 
-    break;
-#endif
-
-#ifdef T1ERR_PARSE_ERROR
-  case T1ERR_PARSE_ERROR:
-    i_push_error(T1ERR_PARSE_ERROR, "PARSE_ERROR"); 
-    break;
-#endif
-
-#ifdef T1ERR_TYPE1_ABORT
-  case T1ERR_TYPE1_ABORT:
-    i_push_error(T1ERR_TYPE1_ABORT, "TYPE1_ABORT"); 
-    break;
-#endif
-
-#ifdef T1ERR_INVALID_FONTID
-  case T1ERR_INVALID_FONTID:
-    i_push_error(T1ERR_INVALID_FONTID, "INVALID_FONTID"); 
-    break;
-#endif
-
-#ifdef T1ERR_INVALID_PARAMETER
-  case T1ERR_INVALID_PARAMETER:
-    i_push_error(T1ERR_INVALID_PARAMETER, "INVALID_PARAMETER"); 
-    break;
-#endif
-
-#ifdef T1ERR_OP_NOT_PERMITTED
-  case T1ERR_OP_NOT_PERMITTED:
-    i_push_error(T1ERR_OP_NOT_PERMITTED, "OP_NOT_PERMITTED"); 
-    break;
-#endif
-
-#ifdef T1ERR_ALLOC_MEM
-  case T1ERR_ALLOC_MEM:
-    i_push_error(T1ERR_ALLOC_MEM, "ALLOC_MEM"); 
-    break;
-#endif
-
-#ifdef T1ERR_FILE_OPEN_ERR
-  case T1ERR_FILE_OPEN_ERR:
-    i_push_error(T1ERR_FILE_OPEN_ERR, "FILE_OPEN_ERR"); 
-    break;
-#endif
-
-#ifdef T1ERR_UNSPECIFIED
-  case T1ERR_UNSPECIFIED:
-    i_push_error(T1ERR_UNSPECIFIED, "UNSPECIFIED"); 
-    break;
-#endif
-
-#ifdef T1ERR_NO_AFM_DATA
-  case T1ERR_NO_AFM_DATA:
-    i_push_error(T1ERR_NO_AFM_DATA, "NO_AFM_DATA"); 
-    break;
-#endif
-
-#ifdef T1ERR_X11
-  case T1ERR_X11:
-    i_push_error(T1ERR_X11, "X11"); 
-    break;
-#endif
-
-#ifdef T1ERR_COMPOSITE_CHAR
-  case T1ERR_COMPOSITE_CHAR:
-    i_push_error(T1ERR_COMPOSITE_CHAR, "COMPOSITE_CHAR"); 
-    break;
-#endif
-
-  default:
-    i_push_errorf(T1_errno, "unknown error %d", (int)T1_errno);
-  }
-}
-
-#endif /* HAVE_LIBT1 */
-
 
 /* Truetype font support */
 #ifdef HAVE_LIBTT
@@ -817,17 +133,18 @@ i_tt_render_glyph( TT_Glyph glyph, TT_Glyph_Metrics* gmetrics,
 static int
 i_tt_render_all_glyphs( TT_Fonthandle *handle, int inst, TT_Raster_Map *bit, 
                         TT_Raster_Map *small_bit, int cords[6], 
-                        char const* txt, int len, int smooth, int utf8 );
+                        char const* txt, size_t len, int smooth, int utf8 );
 static void i_tt_dump_raster_map2( i_img* im, TT_Raster_Map* bit, int xb, int yb, const i_color *cl, int smooth );
 static void i_tt_dump_raster_map_channel( i_img* im, TT_Raster_Map* bit, int xb, int yb, int channel, int smooth );
 static  int
 i_tt_rasterize( TT_Fonthandle *handle, TT_Raster_Map *bit, int cords[6], 
-                float points, char const* txt, int len, int smooth, int utf8 );
-static undef_int i_tt_bbox_inst( TT_Fonthandle *handle, int inst ,const char *txt, int len, int cords[6], int utf8 );
+                float points, char const* txt, size_t len, int smooth, int utf8 );
+static undef_int i_tt_bbox_inst( TT_Fonthandle *handle, int inst ,const char *txt, size_t len, int cords[6], int utf8 );
 
 
 /* static globals needed */
 
+static int TT_initialized = 0;
 static TT_Engine    engine;
 static int  LTT_dpi    = 72; /* FIXME: this ought to be a part of the call interface */
 static int  LTT_hinted = 1;  /* FIXME: this too */
@@ -847,12 +164,18 @@ Initializes the freetype font rendering engine
 */
 
 undef_int
-i_init_tt() {
+i_init_tt(void) {
   TT_Error  error;
+  TT_Byte palette[] = { 0, 64, 127, 191, 255 };
+
+  i_clear_error();
+
   mm_log((1,"init_tt()\n"));
   error = TT_Init_FreeType( &engine );
   if ( error ){
     mm_log((1,"Initialization of freetype failed, code = 0x%x\n",error));
+    i_tt_push_error(error);
+    i_push_error(0, "Could not initialize freetype 1.x");
     return(1);
   }
 
@@ -860,10 +183,23 @@ i_init_tt() {
   error = TT_Init_Post_Extension( engine );
   if (error) {
     mm_log((1, "Initialization of Post extension failed = 0x%x\n", error));
+    
+    i_tt_push_error(error);
+    i_push_error(0, "Could not initialize FT 1.x POST extension");
     return 1;
   }
 #endif
 
+  error = TT_Set_Raster_Gray_Palette(engine, palette);
+  if (error) {
+    mm_log((1, "Initialization of gray levels failed = 0x%x\n", error));
+    i_tt_push_error(error);
+    i_push_error(0, "Could not initialize FT 1.x POST extension");
+    return 1;
+  }
+
+  TT_initialized = 1;
+
   return(0);
 }
 
@@ -988,6 +324,11 @@ i_tt_new(const char *fontname) {
   unsigned short i,n;
   unsigned short platform,encoding;
 
+  if (!TT_initialized && i_init_tt()) {
+    i_push_error(0, "Could not initialize FT1 engine");
+    return NULL;
+  }
+
   i_clear_error();
   
   mm_log((1,"i_tt_new(fontname '%s')\n",fontname));
@@ -1152,7 +493,7 @@ void
 i_tt_blit_or( TT_Raster_Map *dst, TT_Raster_Map *src,int x_off, int y_off ) {
   int  x,  y;
   int  x1, x2, y1, y2;
-  char *s, *d;
+  unsigned char *s, *d;
   
   x1 = x_off < 0 ? -x_off : 0;
   y1 = y_off < 0 ? -y_off : 0;
@@ -1168,8 +509,8 @@ i_tt_blit_or( TT_Raster_Map *dst, TT_Raster_Map *src,int x_off, int y_off ) {
   /* do the real work now */
 
   for ( y = y1; y < y2; ++y ) {
-    s = ( (char*)src->bitmap ) + y * src->cols + x1;
-    d = ( (char*)dst->bitmap ) + ( y + y_off ) * dst->cols + x1 + x_off;
+    s = ( (unsigned char*)src->bitmap ) + y * src->cols + x1;
+    d = ( (unsigned char*)dst->bitmap ) + ( y + y_off ) * dst->cols + x1 + x_off;
     
     for ( x = x1; x < x2; ++x ) {
       if (*s > *d)
@@ -1288,7 +629,7 @@ Returns the number of characters that were checked.
 */
 
 int
-i_tt_has_chars(TT_Fonthandle *handle, char const *text, int len, int utf8,
+i_tt_has_chars(TT_Fonthandle *handle, char const *text, size_t len, int utf8,
                char *out) {
   int count = 0;
   mm_log((1, "i_tt_has_chars(handle %p, text %p, len %d, utf8 %d)\n", 
@@ -1422,7 +763,7 @@ static
 int
 i_tt_render_all_glyphs( TT_Fonthandle *handle, int inst, TT_Raster_Map *bit,
                         TT_Raster_Map *small_bit, int cords[6], 
-                        char const* txt, int len, int smooth, int utf8 ) {
+                        char const* txt, size_t len, int smooth, int utf8 ) {
   unsigned long j;
   TT_F26Dot6 x,y;
   
@@ -1481,31 +822,46 @@ Function to dump a raster onto an image in color used by i_tt_text() (internal).
 static
 void
 i_tt_dump_raster_map2( i_img* im, TT_Raster_Map* bit, int xb, int yb, const i_color *cl, int smooth ) {
-  char *bmap;
-  i_color val;
-  int c, i, ch, x, y;
+  unsigned char *bmap;
+  int x, y;
   mm_log((1,"i_tt_dump_raster_map2(im 0x%x, bit 0x%X, xb %d, yb %d, cl 0x%X)\n",im,bit,xb,yb,cl));
   
-  bmap = (char *)bit->bitmap;
+  bmap = bit->bitmap;
 
   if ( smooth ) {
 
-    for(y=0;y<bit->rows;y++) for(x=0;x<bit->width;x++) {
-      c=(255*bmap[y*(bit->cols)+x])/4;
-      i=255-c;
-      i_gpix(im,x+xb,y+yb,&val);
-      for(ch=0;ch<im->channels;ch++) val.channel[ch]=(c*cl->channel[ch]+i*val.channel[ch])/255;
-      i_ppix(im,x+xb,y+yb,&val);
+    i_render r;
+    i_render_init(&r, im, bit->cols);
+    for(y=0;y<bit->rows;y++) {
+#if 0
+      for(x=0;x<bit->width;x++) {
+       c = (unsigned char)bmap[y*(bit->cols)+x];
+       i=255-c;
+       i_gpix(im,x+xb,y+yb,&val);
+       for(ch=0;ch<im->channels;ch++) 
+         val.channel[ch] = (c*cl->channel[ch]+i*val.channel[ch])/255;
+       i_ppix(im,x+xb,y+yb,&val);
+      }
+#else
+      i_render_color(&r, xb, yb+y, bit->cols, bmap + y*bit->cols, cl);
+#endif
     }
-
+    i_render_done(&r);
   } else {
-
-    for(y=0;y<bit->rows;y++) for(x=0;x<bit->width;x++) {
-      c=( bmap[y*bit->cols+x/8] & (128>>(x%8)) ) ? 255 : 0;
-      i=255-c;
-      i_gpix(im,x+xb,y+yb,&val);
-      for(ch=0;ch<im->channels;ch++) val.channel[ch]=(c*cl->channel[ch]+i*val.channel[ch])/255;
-      i_ppix(im,x+xb,y+yb,&val);
+    for(y=0;y<bit->rows;y++) {
+      unsigned mask = 0x80;
+      unsigned char *p = bmap + y * bit->cols;
+
+      for(x = 0; x < bit->width; x++) {
+       if (*p & mask) {
+         i_ppix(im, x+xb, y+yb, cl);
+       }
+       mask >>= 1;
+       if (!mask) {
+         mask = 0x80;
+         ++p;
+       }
+      }
     }
 
   }
@@ -1529,29 +885,40 @@ Function to dump a raster onto a single channel image in color (internal)
 static
 void
 i_tt_dump_raster_map_channel( i_img* im, TT_Raster_Map*  bit, int xb, int yb, int channel, int smooth ) {
-  char *bmap;
+  unsigned char *bmap;
   i_color val;
   int c,x,y;
+  int old_mask = im->ch_mask;
+  im->ch_mask = 1 << channel;
 
   mm_log((1,"i_tt_dump_raster_channel(im 0x%x, bit 0x%X, xb %d, yb %d, channel %d)\n",im,bit,xb,yb,channel));
   
-  bmap = (char *)bit->bitmap;
+  bmap = bit->bitmap;
   
   if ( smooth ) {
     for(y=0;y<bit->rows;y++) for(x=0;x<bit->width;x++) {
-      c=(255*bmap[y*(bit->cols)+x])/4;
-      i_gpix(im,x+xb,y+yb,&val);
-      val.channel[channel]=c;
+      c = bmap[y*(bit->cols)+x];
+      val.channel[channel] = c;
       i_ppix(im,x+xb,y+yb,&val);
     }
   } else {
-    for(y=0;y<bit->rows;y++) for(x=0;x<bit->width;x++) {
-      c=( bmap[y*bit->cols+x/8] & (128>>(x%8)) ) ? 255 : 0;
-      i_gpix(im,x+xb,y+yb,&val);
-      val.channel[channel]=c;
-      i_ppix(im,x+xb,y+yb,&val);
+    for(y=0;y<bit->rows;y++) {
+      unsigned mask = 0x80;
+      unsigned char *p = bmap + y * bit->cols;
+
+      for(x=0;x<bit->width;x++) {
+       val.channel[channel] = (*p & mask) ? 255 : 0;
+       i_ppix(im,x+xb,y+yb,&val);
+       
+       mask >>= 1;
+       if (!mask) {
+         ++p;
+         mask = 0x80;
+       }
+      }
     }
   }
+  im->ch_mask = old_mask;
 }
 
 
@@ -1573,7 +940,7 @@ interface for generating single channel raster of text (internal)
 
 static
 int
-i_tt_rasterize( TT_Fonthandle *handle, TT_Raster_Map *bit, int cords[6], float points, char const* txt, int len, int smooth, int utf8 ) {
+i_tt_rasterize( TT_Fonthandle *handle, TT_Raster_Map *bit, int cords[6], float points, char const* txt, size_t len, int smooth, int utf8 ) {
   int inst;
   int width, height;
   TT_Raster_Map small_bit;
@@ -1634,7 +1001,7 @@ Interface to text rendering into a single channel in an image
 */
 
 undef_int
-i_tt_cp( TT_Fonthandle *handle, i_img *im, int xb, int yb, int channel, float points, char const* txt, int len, int smooth, int utf8, int align ) {
+i_tt_cp( TT_Fonthandle *handle, i_img *im, int xb, int yb, int channel, float points, char const* txt, size_t len, int smooth, int utf8, int align ) {
 
   int cords[BOUNDING_BOX_COUNT];
   int ascent, st_offset, y;
@@ -1672,7 +1039,7 @@ Interface to text rendering in a single color onto an image
 */
 
 undef_int
-i_tt_text( TT_Fonthandle *handle, i_img *im, int xb, int yb, const i_color *cl, float points, char const* txt, int len, int smooth, int utf8, int align) {
+i_tt_text( TT_Fonthandle *handle, i_img *im, int xb, int yb, const i_color *cl, float points, char const* txt, size_t len, int smooth, int utf8, int align) {
   int cords[BOUNDING_BOX_COUNT];
   int ascent, st_offset, y;
   TT_Raster_Map bit;
@@ -1708,7 +1075,7 @@ Function to get texts bounding boxes given the instance of the font (internal)
 
 static
 undef_int
-i_tt_bbox_inst( TT_Fonthandle *handle, int inst ,const char *txt, int len, int cords[BOUNDING_BOX_COUNT], int utf8 ) {
+i_tt_bbox_inst( TT_Fonthandle *handle, int inst ,const char *txt, size_t len, int cords[BOUNDING_BOX_COUNT], int utf8 ) {
   int upm, casc, cdesc, first;
   
   int start    = 0;
@@ -1808,7 +1175,7 @@ Interface to get a strings bounding box
 */
 
 undef_int
-i_tt_bbox( TT_Fonthandle *handle, float points,const char *txt,int len,int cords[6], int utf8) {
+i_tt_bbox( TT_Fonthandle *handle, float points,const char *txt,size_t len,int cords[6], int utf8) {
   int inst;
 
   i_clear_error();
@@ -1922,6 +1289,7 @@ void i_tt_dump_names(TT_Fonthandle *handle) {
       printf("'%s'\n", name);
     }
   }
+  fflush(stdout);
 }
 
 int
@@ -1942,7 +1310,7 @@ i_tt_glyph_name(TT_Fonthandle *handle, unsigned long ch, char *name_buf,
   }
 
   if (handle->load_cond) {
-    i_push_errorf(rc, "error loading names (%d)", handle->load_cond);
+    i_push_errorf(handle->load_cond, "error loading names (%d)", handle->load_cond);
     return 0;
   }