#define TT_MS_LANGID_ENGLISH_GENERAL 0x0409
#endif
+static im_slot_t slot = -1;
+
/* convert a code point into an index in the glyph cache */
#define TT_HASH(x) ((x) & 0xFF)
+typedef struct {
+ int initialized;
+ TT_Engine engine;
+} i_tt_engine;
+
typedef struct i_glyph_entry_ {
TT_Glyph glyph;
unsigned long ch;
#define TT_VALID( handle ) ( ( handle ).z != NULL )
static void i_tt_push_error(TT_Error rc);
+static void i_tt_uninit(void *);
/* Prototypes */
/* 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 */
* FreeType interface
*/
+void
+i_tt_start(void) {
+ if (slot == -1)
+ slot = im_context_slot_new(i_tt_uninit);
+}
+
/*
=item init_tt()
-Initializes the freetype font rendering engine
+Initializes the freetype font rendering engine (if needed)
=cut
*/
-static undef_int
+static i_tt_engine *
i_init_tt(void) {
TT_Error error;
+ im_context_t ctx = im_get_context();
TT_Byte palette[] = { 0, 64, 127, 191, 255 };
+ i_tt_engine *result = im_context_slot_get(ctx, slot);
i_clear_error();
+ if (result == NULL) {
+ result = mymalloc(sizeof(i_tt_engine));
+ memset(result, 0, sizeof(*result));
+ im_context_slot_set(ctx, slot, result);
+ mm_log((1, "allocated FT1 state %p\n", result));
+ }
+
mm_log((1,"init_tt()\n"));
- error = TT_Init_FreeType( &engine );
+
+ if (result->initialized)
+ return result;
+
+ error = TT_Init_FreeType( &result->engine );
if ( error ){
mm_log((1,"Initialization of freetype failed, code = 0x%x\n",
(unsigned)error));
i_tt_push_error(error);
i_push_error(0, "Could not initialize freetype 1.x");
- return(1);
+ return NULL;
}
#ifdef FTXPOST
- error = TT_Init_Post_Extension( engine );
+ error = TT_Init_Post_Extension( result->engine );
if (error) {
mm_log((1, "Initialization of Post extension failed = 0x%x\n",
(unsigned)error));
i_tt_push_error(error);
i_push_error(0, "Could not initialize FT 1.x POST extension");
- return 1;
+ return NULL;
}
#endif
- error = TT_Set_Raster_Gray_Palette(engine, palette);
+ error = TT_Set_Raster_Gray_Palette(result->engine, palette);
if (error) {
mm_log((1, "Initialization of gray levels failed = 0x%x\n",
(unsigned)error));
i_tt_push_error(error);
i_push_error(0, "Could not initialize FT 1.x POST extension");
- return 1;
+ return NULL;
}
- TT_initialized = 1;
+ mm_log((1, "initialized FT1 state %p\n", result));
+
+ result->initialized = 1;
- return(0);
+ return result;
}
+static void
+i_tt_uninit(void *p) {
+ i_tt_engine *tteng = p;
+
+ if (tteng->initialized) {
+ mm_log((1, "finalizing FT1 state %p\n", tteng));
+ TT_Done_FreeType(tteng->engine);
+ }
+ mm_log((1, "freeing FT1 state %p\n", tteng));
+ myfree(tteng);
+}
/*
=item i_tt_get_instance(handle, points, smooth)
TT_Fonthandle *handle;
unsigned short i,n;
unsigned short platform,encoding;
+ i_tt_engine *tteng;
- if (!TT_initialized && i_init_tt()) {
+ if ((tteng = i_init_tt()) == NULL) {
i_push_error(0, "Could not initialize FT1 engine");
return NULL;
}
handle = mymalloc( sizeof(TT_Fonthandle) ); /* checked 5Nov05 tonyc */
/* load the typeface */
- error = TT_Open_Face( engine, fontname, &handle->face );
+ error = TT_Open_Face( tteng->engine, fontname, &handle->face );
if ( error ) {
+ myfree(handle);
if ( error == TT_Err_Could_Not_Open_File ) {
mm_log((1, "Could not find/open %s.\n", fontname ));
}
if ( LTT_hinted ) load_flags |= TTLOAD_HINT_GLYPH;
if ( !TT_VALID(handle->char_map) ) {
- code = (j - ' ' + 1) < 0 ? 0 : (j - ' ' + 1);
+ code = (j < ' ' - 1) ? 0 : (j - (' ' - 1));
if ( code >= handle->properties.num_Glyphs ) code = 0;
} else code = TT_Char_Index( handle->char_map, j );
index = TT_Char_Index(handle->char_map, c);
}
else {
- index = (c - ' ' + 1) < 0 ? 0 : (c - ' ' + 1);
+ index = (c < ' ' - 1) ? 0 : (c - (' ' - 1));
if (index >= handle->properties.num_Glyphs)
index = 0;
}
if ( !smooth ) TT_Get_Glyph_Bitmap( glyph, bit, x_off * 64, y_off * 64);
else {
- TT_F26Dot6 xmin, ymin, xmax, ymax;
+ TT_F26Dot6 xmin, ymin;
xmin = gmetrics->bbox.xMin & -64;
ymin = gmetrics->bbox.yMin & -64;
- xmax = (gmetrics->bbox.xMax + 63) & -64;
- ymax = (gmetrics->bbox.yMax + 63) & -64;
i_tt_clear_raster_map( small_bit );
TT_Get_Glyph_Pixmap( glyph, small_bit, -xmin, -ymin );
}
i_render_done(&r);
} else {
+ unsigned char *bmp = mymalloc(bit->width);
+ i_render r;
+
+ i_render_init(&r, im, bit->width);
+
for(y=0;y<bit->rows;y++) {
unsigned mask = 0x80;
unsigned char *p = bmap + y * bit->cols;
+ unsigned char *pout = bmp;
for(x = 0; x < bit->width; x++) {
- if (*p & mask) {
- i_ppix(im, x+xb, y+yb, cl);
- }
+ *pout++ = (*p & mask) ? 0xFF : 0;
mask >>= 1;
if (!mask) {
mask = 0x80;
++p;
}
}
+
+ i_render_color(&r, xb, yb+y, bit->width, bmp, cl);
}
+ i_render_done(&r);
+ myfree(bmp);
}
}
static
int
-i_tt_rasterize( TT_Fonthandle *handle, TT_Raster_Map *bit, i_img_dim cords[6], double points, char const* txt, size_t len, int smooth, int utf8 ) {
+i_tt_rasterize( TT_Fonthandle *handle, TT_Raster_Map *bit, i_img_dim *cords, double points, char const* txt, size_t len, int smooth, int utf8 ) {
int inst;
i_img_dim width, height;
TT_Raster_Map small_bit;
static
undef_int
-i_tt_bbox_inst( TT_Fonthandle *handle, int inst ,const char *txt, size_t len, i_img_dim cords[BOUNDING_BOX_COUNT], int utf8 ) {
+i_tt_bbox_inst( TT_Fonthandle *handle, int inst ,const char *txt, size_t len, i_img_dim *cords, int utf8 ) {
int upm, casc, cdesc, first;
int start = 0;
int rightb = 0;
unsigned long j;
- unsigned char *ustr;
- ustr=(unsigned char*)txt;
mm_log((1,"i_tt_box_inst(handle %p,inst %d,txt '%.*s', len %ld, utf8 %d)\n",
handle, inst, (int)len, txt, (long)len, utf8));
*/
undef_int
-i_tt_bbox( TT_Fonthandle *handle, double points,const char *txt,size_t len,i_img_dim cords[6], int utf8) {
+i_tt_bbox( TT_Fonthandle *handle, double points,const char *txt,size_t len,i_img_dim *cords, int utf8) {
int inst;
i_clear_error();