]> git.imager.perl.org - imager.git/blobdiff - font.c
- smarter warning removal
[imager.git] / font.c
diff --git a/font.c b/font.c
index 685991e3c7a203bec0d03ee9f314e3f8d5b3a450..9dfc83db461a3618f37e257ea381db9fc1db9d10 100644 (file)
--- a/font.c
+++ b/font.c
@@ -1,4 +1,4 @@
-#include "image.h"
+#include "imager.h"
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -7,6 +7,11 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#ifdef HAVE_LIBT1
+#include <t1lib.h>
+#endif
+
+
 /*
 =head1 NAME
 
@@ -82,6 +87,9 @@ 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)
 
@@ -94,6 +102,15 @@ 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;
@@ -103,6 +120,9 @@ i_init_t1(int t1log) {
   }
   T1_SetLogLevel(T1LOG_DEBUG);
   i_t1_set_aa(1); /* Default Antialias value */
+
+  ++t1_initialized;
+
   return(0);
 }
 
@@ -120,6 +140,7 @@ Shuts the t1lib font rendering engine down.
 void
 i_close_t1(void) {
   T1_CloseLib();
+  t1_initialized = 0;
 }
 
 
@@ -150,6 +171,8 @@ i_t1_new(char *pfb,char *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;
 }
 
@@ -166,6 +189,9 @@ Frees resources for a t1 font with given font id.
 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);
 }
 
@@ -289,7 +315,7 @@ function to get a strings bounding box given the font id and sizes
 */
 
 int
-i_t1_bbox(int fontnum,float points,char *str,int len,int cords[6], int utf8,char const *flags) {
+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);
@@ -304,10 +330,10 @@ i_t1_bbox(int fontnum,float points,char *str,int len,int cords[6], int utf8,char
     myfree(work);
   }
   else {
-    bbox = T1_GetStringBBox(fontnum,str,len,0,mod_flags);
+    bbox = T1_GetStringBBox(fontnum,(char *)str,len,0,mod_flags);
   }
   gbbox = T1_GetFontBBox(fontnum);
-  advance = T1_GetStringWidth(fontnum, str, len, 0, mod_flags);
+  advance = T1_GetStringWidth(fontnum, (char *)str, len, 0, mod_flags);
   
   mm_log((1,"bbox: (%d,%d,%d,%d)\n",
          (int)(bbox.llx*points/1000),
@@ -328,8 +354,10 @@ i_t1_bbox(int fontnum,float points,char *str,int len,int cords[6], int utf8,char
   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_ADVANCE_WIDTH+1;
+  return BBOX_RIGHT_BEARING+1;
 }
 
 
@@ -352,7 +380,7 @@ Interface to text rendering in a single color onto an image
 */
 
 undef_int
-i_t1_text(i_img *im,int xb,int yb,i_color *cl,int fontnum,float points,char* str,int len,int align, int utf8, char const *flags) {
+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;
@@ -368,7 +396,8 @@ i_t1_text(i_img *im,int xb,int yb,i_color *cl,int fontnum,float points,char* str
     myfree(work);
   }
   else {
-    glyph=T1_AASetString( fontnum, str, len, 0, mod_flags, points, NULL);
+    /* 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;
@@ -433,7 +462,8 @@ Sets *outlen to the number of bytes used in the output string.
 
 static char *
 t1_from_utf8(char const *in, int len, int *outlen) {
-  char *out = mymalloc(len+1);
+  /* 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;
 
@@ -488,7 +518,6 @@ i_t1_has_chars(int font_num, const char *text, int len, int utf8,
 
   while (len) {
     unsigned long c;
-    int index;
     if (utf8) {
       c = i_utf8_advance(&text, &len);
       if (c == ~0UL) {
@@ -708,12 +737,13 @@ t1_push_error(void) {
 /* Truetype font support */
 #ifdef HAVE_LIBTT
 
-/* This is enabled by default when configuring Freetype 1.x
+/* These are enabled by default when configuring Freetype 1.x
    I haven't a clue how to reliably detect it at compile time.
 
    We need a compilation probe in Makefile.PL
 */
 #define FTXPOST 1
+#define FTXERR18 1
 
 #include <freetype.h>
 #define TT_CHC 5
@@ -722,6 +752,10 @@ t1_push_error(void) {
 #include <ftxpost.h>
 #endif
 
+#ifdef FTXERR18
+#include <ftxerr18.h>
+#endif
+
 /* some versions of FT1.x don't seem to define this - it's font defined
    so it won't change */
 #ifndef TT_MS_LANGID_ENGLISH_GENERAL
@@ -766,6 +800,7 @@ struct TT_Fonthandle_ {
 #define USTRCT(x) ((x).z)
 #define TT_VALID( handle )  ( ( handle ).z != NULL )
 
+static void i_tt_push_error(TT_Error rc);
 
 /* Prototypes */
 
@@ -783,7 +818,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 );
-static void i_tt_dump_raster_map2( i_img* im, TT_Raster_Map* bit, int xb, int yb, i_color *cl, int smooth );
+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], 
@@ -947,17 +982,19 @@ the font handle's cache
 */
 
 TT_Fonthandle*
-i_tt_new(char *fontname) {
+i_tt_new(const char *fontname) {
   TT_Error error;
   TT_Fonthandle *handle;
   unsigned short i,n;
   unsigned short platform,encoding;
+
+  i_clear_error();
   
   mm_log((1,"i_tt_new(fontname '%s')\n",fontname));
   
   /* allocate memory for the structure */
   
-  handle = mymalloc( sizeof(TT_Fonthandle) );
+  handle = mymalloc( sizeof(TT_Fonthandle) ); /* checked 5Nov05 tonyc */
 
   /* load the typeface */
   error = TT_Open_Face( engine, fontname, &handle->face );
@@ -969,6 +1006,7 @@ i_tt_new(char *fontname) {
       mm_log((1, "Error while opening %s, error code = 0x%x.\n",fontname, 
               error )); 
     }
+    i_tt_push_error(error);
     return NULL;
   }
   
@@ -1046,10 +1084,16 @@ i_tt_init_raster_map( TT_Raster_Map* bit, int width, int height, int smooth ) {
     bit->cols  = ( bit->width + 7 ) / 8;    /* convert to # of bytes     */
     bit->size  = bit->rows * bit->cols;     /* number of bytes in buffer */
   }
+
+  /* rows can be 0 for some glyphs, for example ' ' */
+  if (bit->rows && bit->size / bit->rows != bit->cols) {
+    m_fatal(0, "Integer overflow calculating bitmap size (%d, %d)\n",
+            bit->width, bit->rows);
+  }
   
   mm_log((1,"i_tt_init_raster_map: bit->width %d, bit->cols %d, bit->rows %d, bit->size %d)\n", bit->width, bit->cols, bit->rows, bit->size ));
 
-  bit->bitmap = (void *) mymalloc( bit->size );
+  bit->bitmap = (void *) mymalloc( bit->size ); /* checked 6Nov05 tonyc */
   if ( !bit->bitmap ) m_fatal(0,"Not enough memory to allocate bitmap (%d)!\n",bit->size );
 }
 
@@ -1247,7 +1291,6 @@ int
 i_tt_has_chars(TT_Fonthandle *handle, char const *text, int len, int utf8,
                char *out) {
   int count = 0;
-  int inst;
   mm_log((1, "i_tt_has_chars(handle %p, text %p, len %d, utf8 %d)\n", 
           handle, text, len, utf8));
 
@@ -1381,7 +1424,6 @@ 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 ) {
   unsigned long j;
-  int i;
   TT_F26Dot6 x,y;
   
   mm_log((1,"i_tt_render_all_glyphs( handle 0x%X, inst %d, bit 0x%X, small_bit 0x%X, txt '%.*s', len %d, smooth %d, utf8 %d)\n",
@@ -1438,7 +1480,7 @@ 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, i_color *cl, int smooth ) {
+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;
@@ -1563,8 +1605,6 @@ i_tt_rasterize( TT_Fonthandle *handle, TT_Raster_Map *bit, int cords[6], float p
     return 0;
   }
 
-  /*  ascent = ( handle->properties.horizontal->Ascender  * handle->instanceh[inst].imetrics.y_ppem ) / handle->properties.header->Units_Per_EM; */
-  
   if ( smooth ) i_tt_done_raster_map( &small_bit );
   return 1;
 }
@@ -1594,19 +1634,20 @@ 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 ) {
+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 ) {
 
   int cords[BOUNDING_BOX_COUNT];
-  int ascent, st_offset;
+  int ascent, st_offset, y;
   TT_Raster_Map bit;
   
   i_clear_error();
   if (! i_tt_rasterize( handle, &bit, cords, points, txt, len, smooth, utf8 ) ) return 0;
   
-  ascent=cords[5];
-  st_offset=cords[0];
+  ascent=cords[BBOX_ASCENT];
+  st_offset=cords[BBOX_NEG_WIDTH];
+  y = align ? yb-ascent : yb;
 
-  i_tt_dump_raster_map_channel( im, &bit, xb-st_offset , yb-ascent, channel, smooth );
+  i_tt_dump_raster_map_channel( im, &bit, xb-st_offset , y, channel, smooth );
   i_tt_done_raster_map( &bit );
 
   return 1;
@@ -1631,19 +1672,20 @@ 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, i_color *cl, float points, char const* txt, int len, int smooth, int utf8) {
+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) {
   int cords[BOUNDING_BOX_COUNT];
-  int ascent, st_offset;
+  int ascent, st_offset, y;
   TT_Raster_Map bit;
 
   i_clear_error();
   
   if (! i_tt_rasterize( handle, &bit, cords, points, txt, len, smooth, utf8 ) ) return 0;
   
-  ascent=cords[5];
-  st_offset=cords[0];
+  ascent=cords[BBOX_ASCENT];
+  st_offset=cords[BBOX_NEG_WIDTH];
+  y = align ? yb-ascent : yb;
 
-  i_tt_dump_raster_map2( im, &bit, xb+st_offset, yb-ascent, cl, smooth ); 
+  i_tt_dump_raster_map2( im, &bit, xb+st_offset, y, cl, smooth ); 
   i_tt_done_raster_map( &bit );
 
   return 1;
@@ -1667,7 +1709,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 ) {
-  int i, upm, casc, cdesc, first;
+  int upm, casc, cdesc, first;
   
   int start    = 0;
   int width    = 0;
@@ -1720,7 +1762,7 @@ i_tt_bbox_inst( TT_Fonthandle *handle, int inst ,const char *txt, int len, int c
        descent  = (gm->bbox.yMin-63) / 64;
        first = 0;
       }
-      if (i == len-1) {
+      if (!len) { /* if at end of string */
        /* the right-side bearing - in case the right-side of a 
           character goes past the right of the advance width,
           as is common for italic fonts
@@ -1729,8 +1771,6 @@ i_tt_bbox_inst( TT_Fonthandle *handle, int inst ,const char *txt, int len, int c
          - (gm->bbox.xMax - gm->bbox.xMin);
        /* fprintf(stderr, "font info last: %d %d %d %d\n", 
           gm->bbox.xMax, gm->bbox.xMin, gm->advance, rightb); */
-       if (rightb > 0)
-         rightb = 0;
       }
 
       ascent  = (ascent  >  casc ?  ascent : casc );
@@ -1740,13 +1780,16 @@ i_tt_bbox_inst( TT_Fonthandle *handle, int inst ,const char *txt, int len, int c
   
   cords[BBOX_NEG_WIDTH]=start;
   cords[BBOX_GLOBAL_DESCENT]=gdescent;
-  cords[BBOX_POS_WIDTH]=width - rightb / 64;
+  cords[BBOX_POS_WIDTH]=width;
+  if (rightb < 0)
+    cords[BBOX_POS_WIDTH] -= rightb / 64;
   cords[BBOX_GLOBAL_ASCENT]=gascent;
   cords[BBOX_DESCENT]=descent;
   cords[BBOX_ASCENT]=ascent;
   cords[BBOX_ADVANCE_WIDTH] = width;
+  cords[BBOX_RIGHT_BEARING] = rightb / 64;
 
-  return BBOX_ADVANCE_WIDTH + 1;
+  return BBOX_RIGHT_BEARING + 1;
 }
 
 
@@ -1765,7 +1808,7 @@ Interface to get a strings bounding box
 */
 
 undef_int
-i_tt_bbox( TT_Fonthandle *handle, float points,char *txt,int len,int cords[6], int utf8) {
+i_tt_bbox( TT_Fonthandle *handle, float points,const char *txt,int len,int cords[6], int utf8) {
   int inst;
 
   i_clear_error();
@@ -1929,6 +1972,24 @@ i_tt_glyph_name(TT_Fonthandle *handle, unsigned long ch, char *name_buf,
 #endif
 }
 
+/*
+=item i_tt_push_error(code)
+
+Push an error message and code onto the Imager error stack.
+
+=cut
+*/
+static void
+i_tt_push_error(TT_Error rc) {
+#ifdef FTXERR18
+  TT_String const *msg = TT_ErrToString18(rc);
+
+  i_push_error(rc, msg);
+#else
+  i_push_errorf(rc, "Error code 0x%04x", (unsigned)rc);
+#endif
+}
+
 #endif /* HAVE_LIBTT */