- handle UTF8 strings passed to T1 low-level functions
authorTony Cook <tony@develop=help.com>
Thu, 9 May 2002 13:23:08 +0000 (13:23 +0000)
committerTony Cook <tony@develop=help.com>
Thu, 9 May 2002 13:23:08 +0000 (13:23 +0000)
        - handle flags for underline, strikethrough and overline for T1
          low-level output functions
        - OO interfaces to UTF8 and flags, for now leaving the flags as
          specific to Imager::Font::Type1

Changes
Imager.xs
TODO
font.c
image.h
lib/Imager/Font/Type1.pm
t/t30t1font.t
t/t36oofont.t
typemap

diff --git a/Changes b/Changes
index 35635f8..ed2598f 100644 (file)
--- a/Changes
+++ b/Changes
@@ -664,6 +664,11 @@ Revision history for Perl extension Imager.
         - support has_chars() method for Freetype 1.x
         - fixed log message for i_ft2_has_chars()
         - fixed some broken checking for UTF8 in FT2 code
+        - handle UTF8 strings passed to T1 low-level functions
+        - handle flags for underline, strikethrough and overline for T1
+          low-level output functions
+        - OO interfaces to UTF8 and flags, for now leaving the flags as
+          specific to Imager::Font::Type1
 
 =================================================================
 
index 341820e..2877f0f 100644 (file)
--- a/Imager.xs
+++ b/Imager.xs
@@ -1679,48 +1679,82 @@ i_t1_destroy(font_id)
 
 
 undef_int
-i_t1_cp(im,xb,yb,channel,fontnum,points,str,len,align)
+i_t1_cp(im,xb,yb,channel,fontnum,points,str_sv,len_ignored,align,utf8=0,flags="")
     Imager::ImgRaw     im
               int     xb
               int     yb
               int     channel
               int     fontnum
              float     points
-             char*    str
-              int     len
+               SV*    str_sv
               int     align
+               int     utf8
+              char*    flags
+             PREINIT:
+               char *str;
+               STRLEN len;
+             CODE:
+#ifdef SvUTF8
+               if (SvUTF8(str_sv))
+                 utf8 = 1;
+#endif
+               str = SvPV(str_sv, len);
+               RETVAL = i_t1_cp(im, xb,yb,channel,fontnum,points,str,len,align,
+                                  utf8,flags);
+           OUTPUT:
+             RETVAL
+
 
 void
-i_t1_bbox(fontnum,point,str,len)
+i_t1_bbox(fontnum,point,str_sv,len_ignored,utf8=0,flags="")
                int     fontnum
             float     point
-             char*    str
-              int     len
+               SV*    str_sv
+               int     utf8
+              char*    flags
             PREINIT:
+               char *str;
+               STRLEN len;
               int     cords[6];
+               int i;
             PPCODE:
-              i_t1_bbox(fontnum,point,str,len,cords);
-               EXTEND(SP, 4);
-               PUSHs(sv_2mortal(newSViv(cords[0])));
-               PUSHs(sv_2mortal(newSViv(cords[1])));
-               PUSHs(sv_2mortal(newSViv(cords[2])));
-               PUSHs(sv_2mortal(newSViv(cords[3])));
-               PUSHs(sv_2mortal(newSViv(cords[4])));
-               PUSHs(sv_2mortal(newSViv(cords[5])));
+#ifdef SvUTF8
+               if (SvUTF8(str_sv))
+                 utf8 = 1;
+#endif
+               str = SvPV(str_sv, len);
+              i_t1_bbox(fontnum,point,str,len,cords,utf8,flags);
+               EXTEND(SP, 6);
+               for (i = 0; i < 6; ++i)
+                 PUSHs(sv_2mortal(newSViv(cords[i])));
 
 
 
 undef_int
-i_t1_text(im,xb,yb,cl,fontnum,points,str,len,align)
+i_t1_text(im,xb,yb,cl,fontnum,points,str_sv,len_ignored,align,utf8=0,flags="")
     Imager::ImgRaw     im
               int     xb
               int     yb
      Imager::Color    cl
               int     fontnum
              float     points
-             char*    str
-              int     len
+               SV*    str_sv
               int     align
+               int     utf8
+              char*    flags
+             PREINIT:
+               char *str;
+               STRLEN len;
+             CODE:
+#ifdef SvUTF8
+               if (SvUTF8(str_sv))
+                 utf8 = 1;
+#endif
+               str = SvPV(str_sv, len);
+               RETVAL = i_t1_text(im, xb,yb,cl,fontnum,points,str,len,align,
+                                  utf8,flags);
+           OUTPUT:
+             RETVAL
 
 #endif 
 
diff --git a/TODO b/TODO
index 1ab7a51..2186dee 100644 (file)
--- a/TODO
+++ b/TODO
@@ -119,8 +119,6 @@ Clean up:
 
 - Compile with memory debugging enabled and fix all leaks
 
-- dynaload.c is strongly tied to perl
-
 - Add mycalloc() memory allocation wrappers.
 
 - should we overload <=> or cmp for Imager::Color objects?
diff --git a/font.c b/font.c
index 3fb111f..499079d 100644 (file)
--- a/font.c
+++ b/font.c
@@ -7,11 +7,6 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-
-
-
-
-
 /*
 =head1 NAME
 
@@ -90,7 +85,8 @@ i_init_fonts(int t1log) {
 
 #ifdef HAVE_LIBT1
 
-
+static int t1_get_flags(char const *flags);
+static char *t1_from_utf8(char const *in, int len, int *outlen);
 
 /* 
 =item i_init_t1(t1log)
@@ -147,6 +143,7 @@ Loads the fonts with the given filenames, returns its font id
 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) {
@@ -158,6 +155,7 @@ i_t1_new(char *pfb,char *afm) {
     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));
   }
+
   return font_id;
 }
 
@@ -234,16 +232,25 @@ Interface to text rendering into a single channel in an image
 */
 
 undef_int
-i_t1_cp(i_img *im,int xb,int yb,int channel,int fontnum,float points,char* str,int len,int align) {
+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); }
 
-  glyph=T1_AASetString( fontnum, str, len, 0, T1_KERNING, points, NULL);
+  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;
 
@@ -288,13 +295,22 @@ function to get a strings bounding box given the font id and sizes
 */
 
 void
-i_t1_bbox(int fontnum,float points,char *str,int len,int cords[6]) {
+i_t1_bbox(int fontnum,float points,char *str,int len,int cords[6], int utf8,char const *flags) {
   BBox bbox;
   BBox gbbox;
+  int mod_flags = t1_get_flags(flags);
   
   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 */ 
-  bbox = T1_GetStringBBox(fontnum,str,len,0,T1_KERNING);
+  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,str,len,0,mod_flags);
+  }
   gbbox = T1_GetFontBBox(fontnum);
   
   mm_log((1,"bbox: (%d,%d,%d,%d)\n",
@@ -336,15 +352,24 @@ 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) {
+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) {
   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); }
 
-  glyph=T1_AASetString( fontnum, str, len, 0, T1_KERNING, points, NULL);
+  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;
 
@@ -370,6 +395,65 @@ i_t1_text(i_img *im,int xb,int yb,i_color *cl,int fontnum,float points,char* str
   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) {
+  char *out = mymalloc(len+1);
+  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;
+}
 
 #endif /* HAVE_LIBT1 */
 
diff --git a/image.h b/image.h
index d2ff41a..f73526e 100644 (file)
--- a/image.h
+++ b/image.h
@@ -248,9 +248,9 @@ undef_int i_init_fonts( int t1log );
 undef_int i_init_t1( int t1log );
 int       i_t1_new( char *pfb, char *afm );
 int       i_t1_destroy( int font_id );
-undef_int i_t1_cp( i_img *im, int xb, int yb, int channel, int fontnum, float points, char* str, int len, int align );
-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 );
-void      i_t1_bbox( int fontnum, float point, char *str, int len, int cords[6] );
+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 );
+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 );
+void      i_t1_bbox( int fontnum, float point, char *str, int len, int cords[6], int utf8, char const *flags );
 void      i_t1_set_aa( int st );
 void      close_t1( void );
 
index d0b3260..78e78a4 100644 (file)
@@ -69,15 +69,20 @@ 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}) {
     Imager::i_t1_cp($input{image}{IMG}, $input{'x'}, $input{'y'},
                    $input{channel}, $self->{id}, $input{size},
-                   $input{string}, length($input{string}), $input{align});
+                   $input{string}, length($input{string}), $input{align},
+                    $input{utf8}, $flags);
   } else {
     Imager::i_t1_text($input{image}{IMG}, $input{'x'}, $input{'y'}, 
                      $input{color}, $self->{id}, $input{size}, 
                      $input{string}, length($input{string}), 
-                     $input{align});
+                     $input{align}, $input{utf8}, $flags);
   }
 
   return $self;
@@ -86,8 +91,12 @@ sub _draw {
 sub _bounding_box {
   my $self = shift;
   my %input = @_;
+  my $flags = '';
+  $flags .= 'u' if $input{underline};
+  $flags .= 's' if $input{strikethrough};
+  $flags .= 'o' if $input{overline};
   return Imager::i_t1_bbox($self->{id}, $input{size}, $input{string},
-                          length($input{string}));
+                          length($input{string}), $input{utf8}, $flags);
 }
 
 1;
@@ -113,6 +122,28 @@ can re-enable that by calling Imager::init() with the C<t1log> option:
 
   Imager::init(t1log=>1);
 
+Currently specific to Imager::Font::Type1, you can use the following
+flags when drawing text or calculating a bounding box:
+
+=over
+
+=item underline
+
+Draw the text with an underline.
+
+=item overline
+
+Draw the text with an overline.
+
+=item strikethrough
+
+Draw the text with a strikethrough.
+
+=back
+
+Obviously, if you're calculating the bounding box the size of the line
+is included in the box, and the line isn't drawn :)
+
 =head1 AUTHOR
 
 Addi, Tony
index 090856b..cd68975 100644 (file)
@@ -1,3 +1,4 @@
+#!perl -w
 # Before `make install' is performed this script should be runnable with
 # `make test'. After `make install' it should work as `perl test.pl'
 
 
 # Change 1..1 below to 1..last_test_to_print .
 # (It may become useful if the test is moved to ./t subdirectory.)
-
-BEGIN { $| = 1; print "1..6\n"; }
+use strict;
+my $loaded;
+BEGIN { $| = 1; print "1..18\n"; }
 END {print "not ok 1\n" unless $loaded;}
 use Imager qw(:all);
 use Imager::Color;
+require "t/testtools.pl";
 
 $loaded = 1;
-print "ok 1\n";
+okx(1, "loaded");
 
 #$Imager::DEBUG=1;
 
 init_log("testout/t30t1font.log",1);
 
-if (!(i_has_format("t1")) ) {
-  for (2..6) {
-    print "ok $_ # skip t1lib unavailable or disabled\n";
-  }
-} else {
+my $deffont = './fontfiles/dcr10.pfb';
 
-  print "# has t1\n";
+my $fontname_pfb=$ENV{'T1FONTTESTPFB'}||$deffont;
+my $fontname_afm=$ENV{'T1FONTTESTAFM'}||'./fontfiles/dcr10.afm';
 
-  $fontname_pfb=$ENV{'T1FONTTESTPFB'}||'./fontfiles/dcr10.pfb';
-  $fontname_afm=$ENV{'T1FONTTESTAFM'}||'./fontfiles/dcr10.afm';
 
-  if (! -f $fontname_pfb) {
-    print "# cannot find fontfile for truetype test $fontname_pfb\n";
-    skip();    
-  }
+if (!(i_has_format("t1")) ) {
+  skipx(17, "t1lib unavailable or disabled");
+}
+elsif (! -f $fontname_pfb) {
+  skipx(17, "cannot find fontfile for truetype test $fontname_pfb");
+}
+elsif (! -f $fontname_afm) {
+  skipx(17, "cannot find fontfile for truetype test $fontname_afm");
+} else {
 
-  if (! -f $fontname_afm) {
-    print "# cannot find fontfile for truetype test $fontname_afm\n";
-    skip();
-  }
+  print "# has t1\n";
 
-  i_init_fonts();
   i_t1_set_aa(1);
 
-  $fnum=Imager::i_t1_new($fontname_pfb,$fontname_afm); # this will load the pfb font
-  if ($fnum<0) { die "Couldn't load font $fontname_pfb"; }
+  my $fnum=Imager::i_t1_new($fontname_pfb,$fontname_afm); # this will load the pfb font
+  unless (okx($fnum >= 0, "load font $fontname_pfb")) {
+    skipx(6, "without the font I can't do a thing");
+    exit;
+  }
 
-  $bgcolor=Imager::Color->new(255,0,0,0);
-  $overlay=Imager::ImgRaw::new(200,70,3);
+  my $bgcolor=Imager::Color->new(255,0,0,0);
+  my $overlay=Imager::ImgRaw::new(200,70,3);
   
-  i_t1_cp($overlay,5,50,1,$fnum,50.0,'XMCLH',5,1)
-    or print "not ";
-  print "ok 2\n";
+  okx(i_t1_cp($overlay,5,50,1,$fnum,50.0,'XMCLH',5,1), "i_t1_cp");
 
   i_line($overlay,0,50,100,50,$bgcolor,1);
 
-  @bbox=i_t1_bbox(0,50.0,'XMCLH',5);
-  print "bbox: ($bbox[0], $bbox[1]) - ($bbox[2], $bbox[3])\n";
+  my @bbox=i_t1_bbox(0,50.0,'XMCLH',5);
+  okx(@bbox == 6, "i_t1_bbox");
+  print "# bbox: ($bbox[0], $bbox[1]) - ($bbox[2], $bbox[3])\n";
 
   open(FH,">testout/t30t1font.ppm") || die "cannot open testout/t35t1font.ppm\n";
   binmode(FH); # for os2
-  $IO = Imager::io_new_fd( fileno(FH) );
+  my $IO = Imager::io_new_fd( fileno(FH) );
   i_writeppm_wiol($overlay,$IO);
   close(FH);
 
   $bgcolor=Imager::Color::set($bgcolor,200,200,200,0);
-  $backgr=Imager::ImgRaw::new(280,150,3);
+  my $backgr=Imager::ImgRaw::new(280,300,3);
 
   i_t1_set_aa(2);
-  i_t1_text($backgr,10,100,$bgcolor,$fnum,150.0,'test',4,1)
-    or print "not ";
-  
-  print "ok 3\n";
+  okx(i_t1_text($backgr,10,100,$bgcolor,$fnum,150.0,'test',4,1), "i_t1_text");
+
+  # "UTF8" tests
+  # for perl < 5.6 we can hand-encode text
+  # since T1 doesn't support over 256 chars in an encoding we just drop
+  # chars over \xFF
+  # the following is "A\xA1\x{2010}A"
+  # 
+  my $text = pack("C*", 0x41, 0xC2, 0xA1, 0xE2, 0x80, 0x90, 0x41);
+  my $alttext = "A\xA1A";
   
+  my @utf8box = i_t1_bbox($fnum, 50.0, $text, length($text), 1);
+  okx(@utf8box == 6, "utf8 bbox element count");
+  my @base = i_t1_bbox($fnum, 50.0, $alttext, length($alttext), 0);
+  okx(@base == 6, "alt bbox element count");
+  my $maxdiff = $fontname_pfb eq $deffont ? 0 : $base[2] / 3;
+  print "# (@utf8box vs @base)\n";
+  okx(abs($utf8box[2] - $base[2]) <= $maxdiff, 
+      "compare box sizes $utf8box[2] vs $base[2] (maxerror $maxdiff)");
+
+  # hand-encoded UTF8 drawing
+  okx(i_t1_text($backgr, 10, 140, $bgcolor, $fnum, 32, $text, length($text), 1,1), "draw hand-encoded UTF8");
+
+  okx(i_t1_cp($backgr, 80, 140, 1, $fnum, 32, $text, length($text), 1, 1), 
+      "cp hand-encoded UTF8");
+
+  # ok, try native perl UTF8 if available
+  if ($] >= 5.006) {
+    my $text;
+    # we need to do this in eval to prevent compile time errors in older
+    # 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
+    okx(i_t1_text($backgr, 10, 180, $bgcolor, $fnum, 32, $text, length($text), 1),
+        "draw UTF8");
+    okx(i_t1_cp($backgr, 80, 180, 1, $fnum, 32, $text, length($text), 1),
+        "cp UTF8");
+    @utf8box = i_t1_bbox($fnum, 50.0, $text, length($text), 0);
+    okx(@utf8box == 6, "native utf8 bbox element count");
+    okx(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"};
+    okx(i_t1_text($backgr, 10, 220, $bgcolor, $fnum, 32, $text, 0, 1, 0, "uso"),
+        "more complex output");
+  }
+  else {
+    skipx(5, "perl too old to test native UTF8 support");
+  }
+
   open(FH,">testout/t30t1font2.ppm") || die "cannot open testout/t35t1font.ppm\n";
   binmode(FH);
   $IO = Imager::io_new_fd( fileno(FH) );
   i_writeppm_wiol($backgr, $IO);
   close(FH);
 
-  $rc=i_t1_destroy($fnum);
-  if ($fnum <0) { die "i_t1_destroy failed: rc=$rc\n"; }
-
-  print "ok 4\n";
+  my $rc=i_t1_destroy($fnum);
+  unless (okx($rc >= 0, "i_t1_destroy")) {
+    print "# i_t1_destroy failed: rc=$rc\n";
+  }
 
   print "# debug: ",join(" x ",i_t1_bbox(0,50,"eses",4) ),"\n";
   print "# debug: ",join(" x ",i_t1_bbox(0,50,"llll",4) ),"\n";
 
   unlink "t1lib.log"; # lose it if it exists
   init(t1log=>0);
-  print -e("t1lib.log") ? "not ok 5\n" : "ok 5\n";
+  okx(!-e("t1lib.log"), "disable t1log");
   init(t1log=>1);
-  print -e("t1lib.log") ? "ok 6\n" : "not ok 6\n";
+  okx(-e("t1lib.log"), "enable t1log");
   init(t1log=>0);
   unlink "t1lib.log";
 }
index 2b4c5c8..7cc80b3 100644 (file)
@@ -12,7 +12,7 @@ use strict;
 # (It may become useful if the test is moved to ./t subdirectory.)
 
 my $loaded;
-BEGIN { $| = 1; print "1..16\n"; }
+BEGIN { $| = 1; print "1..20\n"; }
 END {print "not ok 1\n" unless $loaded;}
 use Imager;
 require "t/testtools.pl";
@@ -50,12 +50,34 @@ if (i_has_format("t1") and -f $fontname_pfb) {
 
   $img->box(box=>\@bbox, color=>$green);
 
+  # "utf8" support
+  $text = pack("C*", 0x41, 0xE2, 0x80, 0x90, 0x41);
+  okx($img->string(font=>$font, text=>$text, 'x'=>100, 'y'=>50, utf8=>1,
+                   overline=>1),
+      "draw 'utf8' hand-encoded text");
+
+  okx($img->string(font=>$font, text=>$text, 'x'=>140, 'y'=>50, utf8=>1, 
+                   underline=>1, channel=>2),
+      "channel 'utf8' hand-encoded text");
+
+  if($] >= 5.006) {
+    eval q{$text = "A\x{2010}A"};
+    okx($img->string(font=>$font, text=>$text, 'x'=>180, 'y'=>50,
+                    strikethrough=>1),
+       "draw native UTF8 text");
+    okx($img->string(font=>$font, text=>$text, 'x'=>220, 'y'=>50, channel=>1),
+       "channel native UTF8 text");
+  }
+  else {
+    skipx(2, "perl too old for native utf8");
+  }
+
   okx($img->write(file=>"testout/t36oofont1.ppm", type=>'pnm'),
       "write t36oofont1.ppm")
     or print "# ",$img->errstr,"\n";
 
 } else {
-  skipx(4, "T1lib missing or disabled");
+  skipx(8, "T1lib missing or disabled");
 }
 
 if (i_has_format("tt") and -f $fontname_tt) {
diff --git a/typemap b/typemap
index 52ad53c..7e36a8c 100644 (file)
--- a/typemap
+++ b/typemap
@@ -11,6 +11,7 @@ float                 T_FLOAT
 float*                 T_ARRAY
 undef_int              T_IV_U
 HASH                   T_HVREF
+utf8_str               T_UTF8_STR
 #############################################################################
 INPUT
 T_PTR_NULL