From a2f0c37903a8d5895c062cc771ddda756b238513 Mon Sep 17 00:00:00 2001 From: Tony Cook Date: Sun, 9 Sep 2012 11:43:11 +1000 Subject: [PATCH] thread-safe T1lib interface T1lib itself doesn't provide a thread-safe API, so we control access to it via a mutex. --- T1/T1.pm | 38 +++++------ T1/T1.xs | 62 ++++++++++-------- T1/imt1.c | 169 ++++++++++++++++++++++++++++++++++++++++-------- T1/imt1.h | 24 +++---- T1/t/t10type1.t | 45 ++++++------- T1/typemap | 1 + 6 files changed, 225 insertions(+), 114 deletions(-) create mode 100644 T1/typemap diff --git a/T1/T1.pm b/T1/T1.pm index 374fb5a7..188fa0de 100644 --- a/T1/T1.pm +++ b/T1/T1.pm @@ -5,7 +5,7 @@ use vars qw(@ISA $VERSION); @ISA = qw(Imager::Font); BEGIN { - $VERSION = "1.017"; + $VERSION = "1.018"; require XSLoader; XSLoader::load('Imager::Font::T1', $VERSION); @@ -19,13 +19,6 @@ my $t1aa; # $T1AA is in there because for some reason (probably cache related) antialiasing # is a system wide setting in t1 lib. -sub t1_set_aa_level { - if (!defined $t1aa or $_[0] != $t1aa) { - i_t1_set_aa($_[0]); - $t1aa=$_[0]; - } -} - sub new { my $class = shift; my %hsh=(color=>Imager::Color->new(255,0,0,255), @@ -65,13 +58,13 @@ sub new { $hsh{afm} = 0; } - my $id = i_t1_new($hsh{file},$hsh{afm}); - unless ($id >= 0) { # the low-level code may miss some error handling + my $font = Imager::Font::T1xs->new($hsh{file},$hsh{afm}); + unless ($font) { # the low-level code may miss some error handling Imager->_set_error(Imager->_error_as_msg); return; } return bless { - id => $id, + t1font => $font, aa => $hsh{aa} || 0, file => $hsh{file}, type => 't1', @@ -83,21 +76,20 @@ sub new { sub _draw { my $self = shift; my %input = @_; - t1_set_aa_level($input{aa}); my $flags = ''; $flags .= 'u' if $input{underline}; $flags .= 's' if $input{strikethrough}; $flags .= 'o' if $input{overline}; if (exists $input{channel}) { - i_t1_cp($input{image}{IMG}, $input{'x'}, $input{'y'}, - $input{channel}, $self->{id}, $input{size}, + $self->{t1font}->cp($input{image}{IMG}, $input{'x'}, $input{'y'}, + $input{channel}, $input{size}, $input{string}, length($input{string}), $input{align}, - $input{utf8}, $flags); + $input{utf8}, $flags, $input{aa}); } else { - i_t1_text($input{image}{IMG}, $input{'x'}, $input{'y'}, - $input{color}, $self->{id}, $input{size}, + $self->{t1font}->text($input{image}{IMG}, $input{'x'}, $input{'y'}, + $input{color}, $input{size}, $input{string}, length($input{string}), - $input{align}, $input{utf8}, $flags); + $input{align}, $input{utf8}, $flags, $input{aa}); } return $self; @@ -110,7 +102,7 @@ sub _bounding_box { $flags .= 'u' if $input{underline}; $flags .= 's' if $input{strikethrough}; $flags .= 'o' if $input{overline}; - return i_t1_bbox($self->{id}, $input{size}, $input{string}, + return $self->{t1font}->bbox($input{size}, $input{string}, length($input{string}), $input{utf8}, $flags); } @@ -122,8 +114,8 @@ sub has_chars { $Imager::ERRSTR = "No string supplied to \$font->has_chars()"; return; } - return i_t1_has_chars($self->{id}, $hsh{string}, - _first($hsh{'utf8'}, $self->{utf8}, 0)); + return $self->{t1font}->has_chars($hsh{string}, + _first($hsh{'utf8'}, $self->{utf8}, 0)); } sub utf8 { @@ -133,7 +125,7 @@ sub utf8 { sub face_name { my ($self) = @_; - i_t1_face_name($self->{id}); + return $self->{t1font}->face_name(); } sub glyph_names { @@ -144,7 +136,7 @@ sub glyph_names { or return Imager->_set_error("no string parameter passed to glyph_names"); my $utf8 = _first($input{utf8} || 0); - i_t1_glyph_name($self->{id}, $string, $utf8); + return $self->{t1font}->glyph_name($string, $utf8); } diff --git a/T1/T1.xs b/T1/T1.xs index f587fb09..63307331 100644 --- a/T1/T1.xs +++ b/T1/T1.xs @@ -11,38 +11,43 @@ extern "C" { DEFINE_IMAGER_CALLBACKS; +typedef i_t1_font_t Imager__Font__T1xs; + +#define i_t1_DESTROY(font) i_t1_destroy(font) + MODULE = Imager::Font::T1 PACKAGE = Imager::Font::T1 undef_int i_init_t1(t1log) int t1log -void -i_t1_set_aa(st) - int st +MODULE = Imager::Font::T1 PACKAGE = Imager::Font::T1xs PREFIX = i_t1_ -int -i_t1_new(pfb,afm) +Imager::Font::T1xs +i_t1_new(class,pfb,afm) char* pfb char* afm + C_ARGS: + pfb, afm -int -i_t1_destroy(font_id) - int font_id +void +i_t1_DESTROY(font) + Imager::Font::T1xs font undef_int -i_t1_cp(im,xb,yb,channel,fontnum,points,str_sv,len_ignored,align,utf8=0,flags="") +i_t1_cp(font,im,xb,yb,channel,points,str_sv, length(str),align,utf8=0,flags="",aa=1) + Imager::Font::T1xs font Imager::ImgRaw im i_img_dim xb i_img_dim yb int channel - int fontnum double points SV* str_sv int align int utf8 char* flags + int aa PREINIT: char *str; STRLEN len; @@ -52,15 +57,15 @@ i_t1_cp(im,xb,yb,channel,fontnum,points,str_sv,len_ignored,align,utf8=0,flags="" utf8 = 1; #endif str = SvPV(str_sv, len); - RETVAL = i_t1_cp(im, xb,yb,channel,fontnum,points,str,len,align, - utf8,flags); + RETVAL = i_t1_cp(font, im, xb,yb,channel,points,str,len,align, + utf8,flags,aa); OUTPUT: RETVAL void i_t1_bbox(fontnum,point,str_sv,len_ignored,utf8=0,flags="") - int fontnum + Imager::Font::T1xs fontnum double point SV* str_sv int utf8 @@ -87,17 +92,18 @@ i_t1_bbox(fontnum,point,str_sv,len_ignored,utf8=0,flags="") undef_int -i_t1_text(im,xb,yb,cl,fontnum,points,str_sv,len_ignored,align,utf8=0,flags="") +i_t1_text(font,im,xb,yb,cl,points,str_sv,length(str),align,utf8=0,flags="",aa=1) + Imager::Font::T1xs font Imager::ImgRaw im i_img_dim xb i_img_dim yb Imager::Color cl - int fontnum double points SV* str_sv int align int utf8 - char* flags + const char* flags + int aa PREINIT: char *str; STRLEN len; @@ -107,14 +113,14 @@ i_t1_text(im,xb,yb,cl,fontnum,points,str_sv,len_ignored,align,utf8=0,flags="") utf8 = 1; #endif str = SvPV(str_sv, len); - RETVAL = i_t1_text(im, xb,yb,cl,fontnum,points,str,len,align, - utf8,flags); + RETVAL = i_t1_text(font,im, xb,yb,cl,points,str,len,align, + utf8,flags,aa); OUTPUT: RETVAL void -i_t1_has_chars(handle, text_sv, utf8 = 0) - int handle +i_t1_has_chars(font, text_sv, utf8 = 0) + Imager::Font::T1xs font SV *text_sv int utf8 PREINIT: @@ -130,9 +136,10 @@ i_t1_has_chars(handle, text_sv, utf8 = 0) #endif text = SvPV(text_sv, len); work = mymalloc(len); - count = i_t1_has_chars(handle, text, len, utf8, work); + count = i_t1_has_chars(font, text, len, utf8, work); if (GIMME_V == G_ARRAY) { EXTEND(SP, count); + for (i = 0; i < count; ++i) { PUSHs(boolSV(work[i])); } @@ -144,21 +151,21 @@ i_t1_has_chars(handle, text_sv, utf8 = 0) myfree(work); void -i_t1_face_name(handle) - int handle +i_t1_face_name(font) + Imager::Font::T1xs font PREINIT: char name[255]; int len; PPCODE: - len = i_t1_face_name(handle, name, sizeof(name)); + len = i_t1_face_name(font, name, sizeof(name)); if (len) { EXTEND(SP, 1); PUSHs(sv_2mortal(newSVpv(name, strlen(name)))); } void -i_t1_glyph_name(handle, text_sv, utf8 = 0) - int handle +i_t1_glyph_name(font, text_sv, utf8 = 0) + Imager::Font::T1xs font SV *text_sv int utf8 PREINIT: @@ -187,7 +194,7 @@ i_t1_glyph_name(handle, text_sv, utf8 = 0) --len; } EXTEND(SP, 1); - if (i_t1_glyph_name(handle, ch, name, sizeof(name))) { + if (i_t1_glyph_name(font, ch, name, sizeof(name))) { PUSHs(sv_2mortal(newSVpv(name, 0))); } else { @@ -197,3 +204,4 @@ i_t1_glyph_name(handle, text_sv, utf8 = 0) BOOT: PERL_INITIALIZE_IMAGER_CALLBACKS; + i_t1_start(); \ No newline at end of file diff --git a/T1/imt1.c b/T1/imt1.c index 3027e424..41f12553 100644 --- a/T1/imt1.c +++ b/T1/imt1.c @@ -5,11 +5,33 @@ static int t1_get_flags(char const *flags); static char *t1_from_utf8(char const *in, size_t len, int *outlen); - +static undef_int i_init_t1_low(int t1log); static void t1_push_error(void); +static void i_t1_set_aa(int st); static int t1_active_fonts = 0; static int t1_initialized = 0; +static int t1_aa = 0; + +struct i_t1_font_tag { + int font_id; +}; + +static i_mutex_t mutex; + +/* +=item i_t1_start() + +Initialize the font driver. This does not actually initialize T1Lib, +it just allocates the mutex we use to gate access to it. + +=cut +*/ + +void +i_t1_start(void) { + mutex = i_mutex_new(); +} /* =item i_init_t1(t1log) @@ -21,6 +43,18 @@ Initializes the t1lib font rendering engine. undef_int i_init_t1(int t1log) { + undef_int result; + i_mutex_lock(mutex); + + result = i_init_t1_low(t1log); + + i_mutex_unlock(mutex); + + return result; +} + +static undef_int +i_init_t1_low(int t1log) { int init_flags = IGNORE_CONFIGFILE|IGNORE_FONTDATABASE; mm_log((1,"init_t1()\n")); @@ -64,8 +98,10 @@ Shuts the t1lib font rendering engine down. void i_close_t1(void) { + i_mutex_lock(mutex); T1_CloseLib(); t1_initialized = 0; + i_mutex_unlock(mutex); } @@ -80,21 +116,27 @@ Loads the fonts with the given filenames, returns its font id =cut */ -int +i_t1_font_t i_t1_new(char *pfb,char *afm) { int font_id; + i_t1_font_t font; + + i_mutex_lock(mutex); i_clear_error(); - if (!t1_initialized && i_init_t1(0)) - return -1; + if (!t1_initialized && i_init_t1_low(0)) { + i_mutex_unlock(mutex); + return NULL; + } 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)); t1_push_error(); - return font_id; + i_mutex_unlock(mutex); + return NULL; } if (afm != NULL) { @@ -107,33 +149,48 @@ i_t1_new(char *pfb,char *afm) { t1_push_error(); i_push_error(0, "loading font"); T1_DeleteFont(font_id); - return -1; + i_mutex_unlock(mutex); + return NULL; } ++t1_active_fonts; mm_log((1, "i_t1_new() -> %d\n", font_id)); - return font_id; + i_mutex_unlock(mutex); + + font = mymalloc(sizeof(*font)); + font->font_id = font_id; + + return font; } /* -=item i_t1_destroy(font_id) +=item i_t1_destroy(font) Frees resources for a t1 font with given font id. - font_id - number of the font to free + font - font to free =cut */ int -i_t1_destroy(int font_id) { - mm_log((1,"i_t1_destroy(font_id %d)\n",font_id)); +i_t1_destroy(i_t1_font_t font) { + int result; + + i_mutex_lock(mutex); + + mm_log((1,"i_t1_destroy(font_id %d)\n",font->font_id)); --t1_active_fonts; - return T1_DeleteFont(font_id); + result = T1_DeleteFont(font->font_id); + myfree(font); + + i_mutex_unlock(mutex); + + return result; } @@ -144,13 +201,19 @@ Sets the antialiasing level of the t1 library. st - 0 = NONE, 1 = LOW, 2 = HIGH. +Must be called with the mutex locked. + =cut */ -void +static void i_t1_set_aa(int st) { int i; unsigned long cst[17]; + + if (t1_aa == st) + return; + switch(st) { case 0: T1_AASetBitsPerPixel( 8 ); @@ -171,11 +234,13 @@ i_t1_set_aa(int st) { T1_AAHSetGrayValues( cst ); mm_log((1,"setting T1 antialias to high\n")); } + + t1_aa = st; } /* -=item i_t1_cp(im, xb, yb, channel, fontnum, points, str, len, align) +=item i_t1_cp(im, xb, yb, channel, fontnum, points, str, len, align,aa) Interface to text rendering into a single channel in an image @@ -188,21 +253,27 @@ Interface to text rendering into a single channel in an image str - string to render len - string length align - (0 - top of font glyph | 1 - baseline ) + aa - anti-aliasing =cut */ undef_int -i_t1_cp(i_img *im,i_img_dim xb,i_img_dim yb,int channel,int fontnum,double points,char* str,size_t len,int align, int utf8, char const *flags) { +i_t1_cp(i_t1_font_t font, i_img *im,i_img_dim xb,i_img_dim yb,int channel,double points,char* str,size_t len,int align, int utf8, char const *flags, int aa) { GLYPH *glyph; int xsize,ysize,x,y; i_color val; int mod_flags = t1_get_flags(flags); + int fontnum = font->font_id; unsigned int ch_mask_store; if (im == NULL) { mm_log((1,"i_t1_cp: Null image in input\n")); return(0); } + i_mutex_lock(mutex); + + i_t1_set_aa(aa); + if (utf8) { int worklen; char *work = t1_from_utf8(str, len, &worklen); @@ -212,8 +283,10 @@ i_t1_cp(i_img *im,i_img_dim xb,i_img_dim yb,int channel,int fontnum,double point else { glyph=T1_AASetString( fontnum, str, len, 0, mod_flags, points, NULL); } - if (glyph == NULL) + if (glyph == NULL) { + i_mutex_unlock(mutex); 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)); @@ -236,6 +309,9 @@ i_t1_cp(i_img *im,i_img_dim xb,i_img_dim yb,int channel,int fontnum,double point } im->ch_mask=ch_mask_store; + + i_mutex_unlock(mutex); + return 1; } @@ -267,12 +343,17 @@ function to get a strings bounding box given the font id and sizes */ int -i_t1_bbox(int fontnum, double points,const char *str,size_t len, i_img_dim cords[6], int utf8,char const *flags) { +i_t1_bbox(i_t1_font_t font, double points,const char *str,size_t len, i_img_dim cords[6], int utf8,char const *flags) { BBox bbox; BBox gbbox; int mod_flags = t1_get_flags(flags); i_img_dim advance; - int space_position = T1_GetEncodingIndex(fontnum, "space"); + int fontnum = font->font_id; + int space_position; + + i_mutex_lock(mutex); + + space_position = T1_GetEncodingIndex(fontnum, "space"); 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 */ @@ -322,12 +403,14 @@ i_t1_bbox(int fontnum, double points,const char *str,size_t len, i_img_dim cords cords[BBOX_RIGHT_BEARING] = cords[BBOX_ADVANCE_WIDTH] - cords[BBOX_POS_WIDTH]; + i_mutex_unlock(mutex); + return BBOX_RIGHT_BEARING+1; } /* -=item i_t1_text(im, xb, yb, cl, fontnum, points, str, len, align) +=item i_t1_text(im, xb, yb, cl, fontnum, points, str, len, align, aa) Interface to text rendering in a single color onto an image @@ -340,19 +423,25 @@ Interface to text rendering in a single color onto an image str - char pointer to string to render len - string length align - (0 - top of font glyph | 1 - baseline ) + aa - anti-aliasing level =cut */ undef_int -i_t1_text(i_img *im, i_img_dim xb, i_img_dim yb,const i_color *cl,int fontnum, double points,const char* str,size_t len,int align, int utf8, char const *flags) { +i_t1_text(i_t1_font_t font, i_img *im, i_img_dim xb, i_img_dim yb,const i_color *cl, double points,const char* str,size_t len,int align, int utf8, char const *flags, int aa) { GLYPH *glyph; int xsize,ysize,y; int mod_flags = t1_get_flags(flags); i_render *r; + int fontnum = font->font_id; if (im == NULL) { mm_log((1,"i_t1_cp: Null image in input\n")); return(0); } + i_mutex_lock(mutex); + + i_t1_set_aa(aa); + if (utf8) { int worklen; char *work = t1_from_utf8(str, len, &worklen); @@ -363,8 +452,10 @@ i_t1_text(i_img *im, i_img_dim xb, i_img_dim yb,const i_color *cl,int fontnum, d /* T1_AASetString() accepts a char * not a const char */ glyph=T1_AASetString( fontnum, (char *)str, len, 0, mod_flags, points, NULL); } - if (glyph == NULL) + if (glyph == NULL) { + i_mutex_unlock(mutex); 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)); @@ -383,6 +474,8 @@ i_t1_text(i_img *im, i_img_dim xb, i_img_dim yb,const i_color *cl,int fontnum, d i_render_color(r, xb, yb+y, xsize, (unsigned char *)glyph->bits+y*xsize, cl); } i_render_delete(r); + + i_mutex_unlock(mutex); return 1; } @@ -467,16 +560,20 @@ Returns the number of characters that were checked. */ int -i_t1_has_chars(int font_num, const char *text, size_t len, int utf8, +i_t1_has_chars(i_t1_font_t font, const char *text, size_t len, int utf8, char *out) { int count = 0; + int font_num = font->font_id; + i_mutex_lock(mutex); + 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(); + i_mutex_unlock(mutex); return 0; } @@ -486,6 +583,7 @@ i_t1_has_chars(int font_num, const char *text, size_t len, int utf8, c = i_utf8_advance(&text, &len); if (c == ~0UL) { i_push_error(0, "invalid UTF8 character"); + i_mutex_unlock(mutex); return 0; } } @@ -512,11 +610,13 @@ i_t1_has_chars(int font_num, const char *text, size_t len, int utf8, ++count; } + i_mutex_unlock(mutex); + return count; } /* -=item i_t1_face_name(font_num, name_buf, name_buf_size) +=item i_t1_face_name(font, name_buf, name_buf_size) Copies the face name of the given C to C. Returns the number of characters required to store the name (which can be @@ -530,53 +630,68 @@ will be truncated. name_buf will always be NUL termintaed. */ int -i_t1_face_name(int font_num, char *name_buf, size_t name_buf_size) { +i_t1_face_name(i_t1_font_t font, char *name_buf, size_t name_buf_size) { char *name; + int font_num = font->font_id; + + i_mutex_lock(mutex); T1_errno = 0; if (T1_LoadFont(font_num)) { t1_push_error(); + i_mutex_unlock(mutex); return 0; } name = T1_GetFontName(font_num); if (name) { + size_t len = strlen(name); strncpy(name_buf, name, name_buf_size); name_buf[name_buf_size-1] = '\0'; - return strlen(name) + 1; + i_mutex_unlock(mutex); + return len + 1; } else { t1_push_error(); + i_mutex_unlock(mutex); return 0; } } int -i_t1_glyph_name(int font_num, unsigned long ch, char *name_buf, +i_t1_glyph_name(i_t1_font_t font, unsigned long ch, char *name_buf, size_t name_buf_size) { char *name; + int font_num = font->font_id; + i_mutex_lock(mutex); i_clear_error(); if (ch > 0xFF) { + i_mutex_unlock(mutex); return 0; } if (T1_LoadFont(font_num)) { t1_push_error(); + i_mutex_unlock(mutex); return 0; } name = T1_GetCharName(font_num, (unsigned char)ch); if (name) { if (strcmp(name, ".notdef")) { + size_t len = strlen(name); strncpy(name_buf, name, name_buf_size); name_buf[name_buf_size-1] = '\0'; - return strlen(name) + 1; + i_mutex_unlock(mutex); + return len + 1; } else { + i_mutex_unlock(mutex); return 0; } } else { t1_push_error(); + i_mutex_unlock(mutex); return 0; } } diff --git a/T1/imt1.h b/T1/imt1.h index 489bcef7..5783e05f 100644 --- a/T1/imt1.h +++ b/T1/imt1.h @@ -3,38 +3,40 @@ #include "imdatatypes.h" +typedef struct i_t1_font_tag *i_t1_font_t; + +extern void +i_t1_start(void); + extern undef_int i_init_t1(int t1log); extern void i_close_t1(void); -extern int +extern i_t1_font_t i_t1_new(char *pfb,char *afm); extern int -i_t1_destroy(int font_id); - -extern void -i_t1_set_aa(int st); +i_t1_destroy(i_t1_font_t font); extern undef_int -i_t1_cp(i_img *im,i_img_dim xb,i_img_dim yb,int channel,int fontnum,double points,char* str,size_t len,int align, int utf8, char const *flags); +i_t1_cp(i_t1_font_t font, i_img *im,i_img_dim xb,i_img_dim yb,int channel,double points,char* str,size_t len,int align, int utf8, char const *flags, int aa); extern int -i_t1_bbox(int fontnum,double points,const char *str,size_t len,i_img_dim *cords, int utf8,char const *flags); +i_t1_bbox(i_t1_font_t font,double points,const char *str,size_t len,i_img_dim *cords, int utf8,char const *flags); extern undef_int -i_t1_text(i_img *im,i_img_dim xb,i_img_dim yb,const i_color *cl,int fontnum,double points,const char* str,size_t len,int align, int utf8, char const *flags); +i_t1_text(i_t1_font_t font, i_img *im,i_img_dim xb,i_img_dim yb,const i_color *cl,double points,const char* str,size_t len,int align, int utf8, char const *flags, int aa); extern int -i_t1_has_chars(int font_num, const char *text, size_t len, int utf8, +i_t1_has_chars(i_t1_font_t font, const char *text, size_t len, int utf8, char *out); extern int -i_t1_face_name(int font_num, char *name_buf, size_t name_buf_size); +i_t1_face_name(i_t1_font_t font, char *name_buf, size_t name_buf_size); extern int -i_t1_glyph_name(int font_num, unsigned long ch, char *name_buf, +i_t1_glyph_name(i_t1_font_t font, unsigned long ch, char *name_buf, size_t name_buf_size); #endif diff --git a/T1/t/t10type1.t b/T1/t/t10type1.t index 8e23561f..ec367492 100644 --- a/T1/t/t10type1.t +++ b/T1/t/t10type1.t @@ -8,7 +8,7 @@ use Cwd qw(getcwd abs_path); #$Imager::DEBUG=1; -plan tests => 97; +plan tests => 96; ok($Imager::formats{t1}, "must have t1"); @@ -40,7 +40,7 @@ SKIP: init(t1log=>0); unlink "t1lib.log"; - my $fnum=Imager::Font::T1::i_t1_new($fontname_pfb,$fontname_afm); # this will load the pfb font + my $fnum=Imager::Font::T1xs->new($fontname_pfb,$fontname_afm); # this will load the pfb font unless (ok($fnum >= 0, "load font $fontname_pfb")) { skip("without the font I can't do a thing", 90); } @@ -48,11 +48,11 @@ SKIP: my $bgcolor=Imager::Color->new(255,0,0,0); my $overlay=Imager::ImgRaw::new(200,70,3); - ok(Imager::Font::T1::i_t1_cp($overlay,5,50,1,$fnum,50.0,'XMCLH',5,1), "i_t1_cp"); + ok($fnum->cp($overlay,5,50,1,50.0,'XMCLH',5,1), "i_t1_cp"); i_line($overlay,0,50,100,50,$bgcolor,1); - my @bbox=Imager::Font::T1::i_t1_bbox(0,50.0,'XMCLH',5); + my @bbox=$fnum->bbox(50.0,'XMCLH',5); is(@bbox, 8, "i_t1_bbox"); print "# bbox: ($bbox[0], $bbox[1]) - ($bbox[2], $bbox[3])\n"; @@ -65,8 +65,7 @@ SKIP: $bgcolor=Imager::Color::set($bgcolor,200,200,200,0); my $backgr=Imager::ImgRaw::new(280,300,3); - Imager::Font::T1::i_t1_set_aa(2); - ok(Imager::Font::T1::i_t1_text($backgr,10,100,$bgcolor,$fnum,150.0,'test',4,1), "i_t1_text"); + ok($fnum->text($backgr,10,100,$bgcolor,150.0,'test',4,1,2), "i_t1_text"); # "UTF8" tests # for perl < 5.6 we can hand-encode text @@ -77,9 +76,9 @@ SKIP: my $text = pack("C*", 0x41, 0xC2, 0xA1, 0xE2, 0x80, 0x90, 0x41); my $alttext = "A\xA1A"; - my @utf8box = Imager::Font::T1::i_t1_bbox($fnum, 50.0, $text, length($text), 1); + my @utf8box = $fnum->bbox(50.0, $text, length($text), 1); is(@utf8box, 8, "utf8 bbox element count"); - my @base = Imager::Font::T1::i_t1_bbox($fnum, 50.0, $alttext, length($alttext), 0); + my @base = $fnum->bbox(50.0, $alttext, length($alttext), 0); is(@base, 8, "alt bbox element count"); my $maxdiff = $fontname_pfb eq $deffont ? 0 : $base[2] / 3; print "# (@utf8box vs @base)\n"; @@ -87,9 +86,9 @@ SKIP: "compare box sizes $utf8box[2] vs $base[2] (maxerror $maxdiff)"); # hand-encoded UTF8 drawing - ok(Imager::Font::T1::i_t1_text($backgr, 10, 140, $bgcolor, $fnum, 32, $text, length($text), 1,1), "draw hand-encoded UTF8"); + ok($fnum->text($backgr, 10, 140, $bgcolor, 32, $text, length($text), 1,1), "draw hand-encoded UTF8"); - ok(Imager::Font::T1::i_t1_cp($backgr, 80, 140, 1, $fnum, 32, $text, length($text), 1, 1), + ok($fnum->cp($backgr, 80, 140, 1, 32, $text, length($text), 1, 1), "cp hand-encoded UTF8"); # ok, try native perl UTF8 if available @@ -101,16 +100,16 @@ SKIP: # versions eval q{$text = "A\xA1\x{2010}A"}; # A, a with ogonek, HYPHEN, A in our test font #$text = "A".chr(0xA1).chr(0x2010)."A"; # this one works too - ok(Imager::Font::T1::i_t1_text($backgr, 10, 180, $bgcolor, $fnum, 32, $text, length($text), 1), + ok($fnum->text($backgr, 10, 180, $bgcolor, 32, $text, length($text), 1), "draw UTF8"); - ok(Imager::Font::T1::i_t1_cp($backgr, 80, 180, 1, $fnum, 32, $text, length($text), 1), + ok($fnum->cp($backgr, 80, 180, 1, 32, $text, length($text), 1), "cp UTF8"); - @utf8box = Imager::Font::T1::i_t1_bbox($fnum, 50.0, $text, length($text), 0); + @utf8box = $fnum->bbox(50.0, $text, length($text), 0); is(@utf8box, 8, "native utf8 bbox element count"); ok(abs($utf8box[2] - $base[2]) <= $maxdiff, "compare box sizes native $utf8box[2] vs $base[2] (maxerror $maxdiff)"); eval q{$text = "A\xA1\xA2\x01\x1F\x{0100}A"}; - ok(Imager::Font::T1::i_t1_text($backgr, 10, 220, $bgcolor, $fnum, 32, $text, 0, 1, 0, "uso"), + ok($fnum->text($backgr, 10, 220, $bgcolor, 32, $text, 0, 1, 0, "uso"), "more complex output"); } @@ -120,13 +119,7 @@ SKIP: i_writeppm_wiol($backgr, $IO); close(FH); - my $rc=Imager::Font::T1::i_t1_destroy($fnum); - unless (ok($rc >= 0, "i_t1_destroy")) { - print "# i_t1_destroy failed: rc=$rc\n"; - } - - print "# debug: ",join(" x ",Imager::Font::T1::i_t1_bbox(0,50,"eses",4) ),"\n"; - print "# debug: ",join(" x ",Imager::Font::T1::i_t1_bbox(0,50,"llll",4) ),"\n"; + undef $fnum; # character existance tests - uses the special ExistenceTest font my $exists_font = 'fontfiles/ExistenceTest.pfb'; @@ -134,22 +127,22 @@ SKIP: -e $exists_font or die "$exists_font not found"; - my $font_num = Imager::Font::T1::i_t1_new($exists_font, $exists_afm); + my $font_num = Imager::Font::T1xs->new($exists_font, $exists_afm); SKIP: { ok($font_num >= 0, 'loading test font') or skip('Could not load test font', 6); # first the list interface - my @exists = Imager::Font::T1::i_t1_has_chars($font_num, "!A"); + my @exists = $font_num->has_chars("!A"); is(@exists, 2, "return count from has_chars"); ok($exists[0], "we have an exclamation mark"); ok(!$exists[1], "we have no uppercase A"); # then the scalar interface - my $exists = Imager::Font::T1::i_t1_has_chars($font_num, "!A"); + my $exists = $font_num->has_chars("!A"); is(length($exists), 2, "return scalar length"); ok(ord(substr($exists, 0, 1)), "we have an exclamation mark"); ok(!ord(substr($exists, 1, 1)), "we have no upper-case A"); - Imager::Font::T1::i_t1_destroy($font_num); + undef $font_num; } my $font = Imager::Font->new(file=>$exists_font, type=>'t1'); @@ -174,7 +167,7 @@ SKIP: isnt($bbox[2], $bbox[5], "different advance to pos_width"); # names - my $face_name = Imager::Font::T1::i_t1_face_name($font->{id}); + my $face_name = $font->{t1font}->face_name(); print "# face $face_name\n"; is($face_name, 'ExistenceTest', "face name"); $face_name = $font->face_name; diff --git a/T1/typemap b/T1/typemap new file mode 100644 index 00000000..95e197e0 --- /dev/null +++ b/T1/typemap @@ -0,0 +1 @@ +Imager::Font::T1xs T_PTROBJ -- 2.39.5