]> git.imager.perl.org - imager.git/commitdiff
revert threading changes, they aren't ready for the mainline yet
authorTony Cook <tony@develop-help.com>
Sat, 29 Sep 2012 00:05:51 +0000 (10:05 +1000)
committerTony Cook <tony@develop-help.com>
Sat, 29 Sep 2012 00:09:47 +0000 (10:09 +1000)
87 files changed:
Changes
FT2/Changes
FT2/FT2.pm
FT2/FT2.xs
FT2/MANIFEST
FT2/Makefile.PL
FT2/freetyp2.c
FT2/imft2.h
FT2/t/t20thread.t [deleted file]
GIF/Changes
GIF/GIF.pm
GIF/GIF.xs
GIF/Makefile.PL
GIF/imgif.c
GIF/imgif.h
GIF/t/t10gif.t
Imager.pm
Imager.xs
JPEG/JPEG.pm
JPEG/imjpeg.c
MANIFEST
Makefile.PL
T1/Changes
T1/MANIFEST
T1/T1.pm
T1/T1.xs
T1/imt1.c
T1/imt1.h
T1/t/t10type1.t
T1/typemap [deleted file]
TIFF/Changes
TIFF/TIFF.pm
TIFF/TIFF.xs
TIFF/imtiff.c
TIFF/imtiff.h
apidocs.perl
bench/largish.png [deleted file]
bench/largish.tif [deleted file]
bench/tifthread.pl [deleted file]
bmp.c
context.c [deleted file]
conv.im
convert.im
datatypes.c
draw.c
dynaload.c
error.c
ext.h
fills.c
filters.im
flip.im
font.c [new file with mode: 0644]
fontft1.c [deleted file]
gaussian.im
hlines.c
image.c
imager.h
imageri.h
imdatatypes.h
imerror.h
imext.c
imext.h
imexttypes.h
img16.c
img8.c
imgdouble.c
immacros.h
iolayer.c
iolayer.h
iolayert.h
lib/Imager/API.pod
lib/Imager/APIRef.pod
lib/Imager/Threads.pod [deleted file]
limits.c
log.c
log.h
maskimg.c
mutexnull.c [deleted file]
mutexpthr.c [deleted file]
mutexwin.c [deleted file]
palimg.c
plug.h
t/t82inline.t
t/t84inlinectx.t [deleted file]
t/x20spell.t
t/x90cmpversion.t
typemap.local

diff --git a/Changes b/Changes
index f3caca68a039dd86e1dacb42e946553563fbb94c..7dc6eb409ca29a29bd30ec79f7c353ea52d4a283 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,46 +1,5 @@
 Imager release history.  Older releases can be found in Changes.old
 
- - improved thread safety
-   - the internal error stack and log file handle are now in a per-thread
-     context object
-   - JPEG now captures IPTC information in a thread-safe way
-   - avoid globals where possible for warning capture in libtiff
-   - use a mutex to avoid re-entering thread-unsafe giflib
-   - use a mutex to avoid re-entering thread-unsafe tifflib
-   - use a mutex to avoid re-entering thread-unsafe T1Lib
-   - use a library handle per thread for freetype 2.
-   - use an engine handle per thread for freetype 1.x.
-
- - T1:
-   - improve error reporting
-   - provide better control of the level of anti-aliasing
-
- - support for giflib 5.0.
-   https://rt.cpan.org/Ticket/Display.html?id=79029
-
- - allow freetype-config to be found on cygwin
-
-Imager 0.92_01 - 18 Aug 2012
-==============
-
-This development release was a work in progress release of the thread
-safety changes:
-
-Development release, let's see what broke.
-
-This release is not Imager API binary compatible with older releases,
-if you have a module that uses Imager's API it will need to be
-reinstalled.
-
- - improved thread safety
-   - the internal error stack and log file handle are now in a per-thread
-     context object
-   - JPEG now captures IPTC information in a thread-safe way
-   - avoid globals where possible for warning capture in libtiff
-   - avoid re-entering libtiff or giflib since they aren't thread safe
-
-This release was removed from CPAN after a short time.
-
 Imager 0.92 - 14 Aug 2012
 ===========
 
index 1a7449fc38bf0aea2127ea042e7e07d90406afa3..561bc69e9b359353411aa761ac079b32f1b004eb 100644 (file)
@@ -1,10 +1,3 @@
-Imager-Font-FT2 0.85
-====================
-
- - improve thread safety
-
- - allow freetype-config to be found on cygwin
-
 Imager-Font-FT2 0.85
 ====================
 
index a3a8418a219992bb1d10d4853884e3cada51d2f5..aa83aab0fcae0d20cc67f14feddd705a236021b4 100644 (file)
@@ -1,12 +1,11 @@
 package Imager::Font::FT2;
 use strict;
 use Imager;
-use Scalar::Util ();
 use vars qw($VERSION @ISA);
 @ISA = qw(Imager::Font);
 
 BEGIN {
-  $VERSION = "0.86";
+  $VERSION = "0.85";
 
   require XSLoader;
   XSLoader::load('Imager::Font::FT2', $VERSION);
@@ -51,10 +50,6 @@ sub new {
 
 sub _draw {
   my $self = shift;
-
-  $self->_valid
-    or return;
-
   my %input = @_;
   if (exists $input{channel}) {
     i_ft2_cp($self->{id}, $input{image}{IMG}, $input{'x'}, $input{'y'},
@@ -74,19 +69,12 @@ sub _bounding_box {
   my $self = shift;
   my %input = @_;
 
-  $self->_valid
-    or return;
-
   return i_ft2_bbox($self->{id}, $input{size}, $input{sizew}, $input{string}, 
                    $input{utf8});
 }
 
 sub dpi {
   my $self = shift;
-
-  $self->_valid
-    or return;
-
   my @old = i_ft2_getdpi($self->{id});
   if (@_) {
     my %hsh = @_;
@@ -109,18 +97,12 @@ sub dpi {
 sub hinting {
   my ($self, %opts) = @_;
 
-  $self->_valid
-    or return;
-
   i_ft2_sethinting($self->{id}, $opts{hinting} || 0);
 }
 
 sub _transform {
   my $self = shift;
 
-  $self->_valid
-    or return;
-
   my %hsh = @_;
   my $matrix = $hsh{matrix} or return undef;
 
@@ -135,9 +117,6 @@ sub utf8 {
 sub has_chars {
   my ($self, %hsh) = @_;
 
-  $self->_valid
-    or return;
-
   unless (defined $hsh{string} && length $hsh{string}) {
     $Imager::ERRSTR = "No string supplied to \$font->has_chars()";
     return;
@@ -149,9 +128,6 @@ sub has_chars {
 sub face_name {
   my ($self) = @_;
 
-  $self->_valid
-    or return;
-
   i_ft2_face_name($self->{id});
 }
 
@@ -162,9 +138,6 @@ sub can_glyph_names {
 sub glyph_names {
   my ($self, %input) = @_;
 
-  $self->_valid
-    or return;
-
   my $string = $input{string};
   defined $string
     or return Imager->_set_error("no string parameter passed to glyph_names");
@@ -181,18 +154,12 @@ sub glyph_names {
 sub is_mm {
   my ($self) = @_;
 
-  $self->_valid
-    or return;
-
   i_ft2_is_multiple_master($self->{id});
 }
 
 sub mm_axes {
   my ($self) = @_;
 
-  $self->_valid
-    or return;
-
   my ($num_axis, $num_design, @axes) =
     i_ft2_get_multiple_masters($self->{id})
       or return Imager->_set_error(Imager->_error_as_msg);
@@ -203,9 +170,6 @@ sub mm_axes {
 sub set_mm_coords {
   my ($self, %opts) = @_;
 
-  $self->_valid
-    or return;
-
   $opts{coords}
     or return Imager->_set_error("Missing coords parameter");
   ref($opts{coords}) && $opts{coords} =~ /ARRAY\(0x[\da-f]+\)$/
@@ -216,19 +180,6 @@ sub set_mm_coords {
 
   return 1;
 }
-
-# objects may be invalidated on thread creation (or Win32 fork emulation)
-sub _valid {
-  my $self = shift;
-
-  unless ($self->{id} && Scalar::Util::blessed($self->{id})) {
-    Imager->_set_error("font object was created in another thread");
-    return;
-  }
-
-  return 1;
-}
-
 1;
 
 __END__
index 61a964efb1edb380d86690e8c2035ed91a125a5d..ac8396efbd7779de4fd19e0cd90323435efc184b 100644 (file)
@@ -356,4 +356,3 @@ i_ft2_set_mm_coords(handle, ...)
 
 BOOT:
        PERL_INITIALIZE_IMAGER_CALLBACKS;
-       i_ft2_start();
index 4e4becf8637d202ac54b0d2fdc873fb2be306c91..0f154ff5b4618c4582d210a2cb7c2b4c2bf65330 100644 (file)
@@ -16,5 +16,4 @@ MANIFEST                      This list of files
 MANIFEST.SKIP
 README
 t/t10ft2.t
-t/t20thread.t
 typemap
index c0a43cca1c1632c162496a2c2b90b1b9eb9ff23b..076e5a32656e06468749f3ab0883fdf9aa46b6c9 100644 (file)
@@ -61,7 +61,6 @@ else {
     $opts{PREREQ_PM} =
       {
        @Imager_req,
-       'Scalar::Util' => 1.00,
        XSLoader => 0,
       };
   }
@@ -155,9 +154,6 @@ sub is_exe {
   if ($^O eq 'MSWin32') {
     push @exe_suffix, qw/.bat .cmd/;
   }
-  elsif ($^O eq 'cygwin') {
-    push @exe_suffix, "";
-  }
 
   for my $dir (File::Spec->path) {
     for my $suffix (@exe_suffix) {
index c1e6ed540ae34075c859be0076a7e344f27cdffb..fc060efdb1c521a091f1017210af146868338325 100644 (file)
@@ -49,84 +49,40 @@ Truetype, Type1 and Windows FNT.
 
 static void ft2_push_message(int code);
 
-static void ft2_final(void *);
-
-static im_slot_t slot = -1;
-
-typedef struct {
-  int initialized;
-  FT_Library library;
-  im_context_t ctx;
-} ft2_state;
+static int ft2_initialized = 0;
+static FT_Library library;
 
 static i_img_dim i_min(i_img_dim a, i_img_dim b);
 static i_img_dim i_max(i_img_dim a, i_img_dim b);
 
-void
-i_ft2_start(void) {
-  if (slot == -1)
-    slot = im_context_slot_new(ft2_final, "FT2");
-}
-
 /*
 =item i_ft2_init(void)
 
 Initializes the Freetype 2 library.
 
-Returns ft2_state * on success or NULL on failure.
+Returns true on success, false on failure.
 
 =cut
 */
-
-static ft2_state *
+int
 i_ft2_init(void) {
   FT_Error error;
-  im_context_t ctx = im_get_context();
-  ft2_state *ft2 = im_context_slot_get(ctx, slot);
-
-  if (ft2 == NULL) {
-    ft2 = mymalloc(sizeof(ft2_state));
-    ft2->initialized = 0;
-    ft2->library = NULL;
-    ft2->ctx = ctx;
-    im_context_slot_set(ctx, slot, ft2);
-    mm_log((1, "created FT2 state %p for context %p\n", ft2, ctx));
-  }
 
   i_clear_error();
-  if (!ft2->initialized) {
-    error = FT_Init_FreeType(&ft2->library);
-    if (error) {
-      ft2_push_message(error);
-      i_push_error(0, "Initializing Freetype2");
-      return NULL;
-    }
-    mm_log((1, "initialized FT2 state %p\n", ft2));
-
-    ft2->initialized = 1;
+  error = FT_Init_FreeType(&library);
+  if (error) {
+    ft2_push_message(error);
+    i_push_error(0, "Initializing Freetype2");
+    return 0;
   }
 
-  return ft2;
-}
-
-static void
-ft2_final(void *state) {
-  ft2_state *ft2 = state;
-
-  if (ft2->initialized) {
-    mm_log((1, "finalizing FT2 state %p\n", state));
-    FT_Done_FreeType(ft2->library);
-    ft2->library = NULL;
-    ft2->initialized = 0;
-  }
+  ft2_initialized = 1;
 
-  mm_log((1, "freeing FT2 state %p\n", state));
-  myfree(state);
+  return 1;
 }
 
 struct FT2_Fonthandle {
   FT_Face face;
-  ft2_state *state;
   int xdpi, ydpi;
   int hint;
   FT_Encoding encoding;
@@ -182,15 +138,14 @@ i_ft2_new(const char *name, int index) {
   int i, j;
   FT_Encoding encoding;
   int score;
-  ft2_state *ft2;
 
   mm_log((1, "i_ft2_new(name %p, index %d)\n", name, index));
 
-  if ((ft2 = i_ft2_init()) == NULL)
+  if (!ft2_initialized && !i_ft2_init())
     return NULL;
 
   i_clear_error();
-  error = FT_New_Face(ft2->library, name, index, &face);
+  error = FT_New_Face(library, name, index, &face);
   if (error) {
     ft2_push_message(error);
     i_push_error(error, "Opening face");
@@ -218,7 +173,6 @@ i_ft2_new(const char *name, int index) {
 
   result = mymalloc(sizeof(FT2_Fonthandle));
   result->face = face;
-  result->state = ft2;
   result->xdpi = result->ydpi = 72;
   result->encoding = encoding;
 
@@ -290,7 +244,7 @@ i_ft2_setdpi(FT2_Fonthandle *handle, int xdpi, int ydpi) {
   if (xdpi > 0 && ydpi > 0) {
     handle->xdpi = xdpi;
     handle->ydpi = ydpi;
-    return 1;
+    return 0;
   }
   else {
     i_push_error(0, "resolutions must be positive");
index 6c641c90ca7d77691eb0f3cc2219fc0e124112e7..57b71293732e2e9fa9889ac6a605e9983dd254bd 100644 (file)
@@ -7,7 +7,7 @@ typedef struct FT2_Fonthandle FT2_Fonthandle;
 
 typedef FT2_Fonthandle* Imager__Font__FT2x;
 
-extern void i_ft2_start(void);
+extern int i_ft2_init(void);
 extern FT2_Fonthandle * i_ft2_new(const char *name, int index);
 extern void i_ft2_destroy(FT2_Fonthandle *handle);
 extern int i_ft2_setdpi(FT2_Fonthandle *handle, int xdpi, int ydpi);
diff --git a/FT2/t/t20thread.t b/FT2/t/t20thread.t
deleted file mode 100644 (file)
index 723189d..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-#!perl -w
-use strict;
-use Imager;
-
-use Config;
-my $loaded_threads;
-BEGIN {
-  if ($Config{useithreads} && $] > 5.008007) {
-    $loaded_threads =
-      eval {
-       require threads;
-       threads->import;
-       1;
-      };
-  }
-}
-
-use Test::More;
-
-$Config{useithreads}
-  or plan skip_all => "can't test Imager's lack of threads support with no threads";
-$] > 5.008007
-  or plan skip_all => "require a perl with CLONE_SKIP to test Imager's lack of threads support";
-$loaded_threads
-  or plan skip_all => "couldn't load threads";
-
-$INC{"Devel/Cover.pm"}
-  and plan skip_all => "threads and Devel::Cover don't get along";
-
-# https://rt.cpan.org/Ticket/Display.html?id=65812
-# https://github.com/schwern/test-more/issues/labels/Test-Builder2#issue/100
-$Test::More::VERSION =~ /^2\.00_/
-  and plan skip_all => "threads are hosed in 2.00_06 and presumably all 2.00_*";
-
-plan tests => 8;
-
-Imager->open_log(log => "testout/t20thread.log");
-
-my $ft1 = Imager::Font->new(file => "fontfiles/dodge.ttf", type => "ft2");
-ok($ft1, "make a font");
-ok($ft1->_valid, "and it's valid");
-my $ft2;
-
-my $thr = threads->create
-  (
-   sub {
-     ok(!$ft1->_valid, "first font no longer valid");
-     $ft2 = Imager::Font->new(file => "fontfiles/dodge.ttf", type => "ft2");
-     ok($ft2, "make a new font in thread");
-     ok($ft2->_valid, "and it's valid");
-     1;
-   },
-  );
-
-ok($thr->join, "join the thread");
-ok($ft1->_valid, "original font still valid in main thread");
-is($ft2, undef, "font created in thread shouldn't be set in main thread");
-
-Imager->close_log();
index dfc8de7ef66b76b69c3c72c3fe826c5f07434981..a854d3e12b2e8dfd725073c26ac9f91a4ba83b2d 100644 (file)
@@ -1,10 +1,4 @@
-Imager-File-GIF 0.85
-====================
-
- - add giflib 5.0 support.
-   https://rt.cpan.org/Ticket/Display.html?id=79029
-
-Imager-File-GIF 0.84 - released with Imager 0.92_01
+Imager-File-GIF 0.84
 ====================
 
  - giflib 4.2 eliminates the GIF_LIB_VERSION macro, handle that
index 5d92f7a953342569fadb7c69e167165453a98356..db78872543644c0b74a28447cd3287b4d766ce0c 100644 (file)
@@ -4,7 +4,7 @@ use Imager;
 use vars qw($VERSION @ISA);
 
 BEGIN {
-  $VERSION = "0.85";
+  $VERSION = "0.84";
 
   require XSLoader;
   XSLoader::load('Imager::File::GIF', $VERSION);
index 7641b8c3fcc28bf9f66bf0a96535b789515574cb..75687b8217fa585801bcc19b5a59b05f411a71bf 100644 (file)
@@ -147,4 +147,3 @@ i_readgif_multi_wiol(ig)
 BOOT:
        PERL_INITIALIZE_IMAGER_CALLBACKS;
        PERL_INITIALIZE_IMAGER_PERL_CALLBACKS;
-       i_init_gif();
index 378dd435eef6db190b527b30062bd5b207321dff..0640ba326df8a3908e587b354deed92a0bbc62aa 100644 (file)
@@ -74,7 +74,7 @@ my %probe =
    inccheck => sub { -e File::Spec->catfile($_[0], "gif_lib.h") },
    libbase => "gif",
    testcode => _gif_test_code(),
-   testcodeheaders => [ "stddef.h", "gif_lib.h", "stdio.h" ],
+   testcodeheaders => [ "gif_lib.h", "stdio.h" ],
    incpath => \@incpaths,
    libpath => \@libpaths,
   );
@@ -119,13 +119,8 @@ int ver_min;
 #else
 int ver_maj = GIFLIB_MAJOR;
 int ver_min = GIFLIB_MINOR;
-int error;
 #endif
-#if defined(GIFLIB_MAJOR) && GIFLIB_MAJOR >= 5
-gf=DGifOpenFileName("testimg/expected.gif", &error);
-#else
 gf=DGifOpenFileName("testimg/expected.gif");
-#endif
 if (!gf) {
   fprintf(stderr, "GIF: Cannot open testimg/expected.gif\n");
   return 1;
@@ -134,11 +129,9 @@ if (gf->SWidth != 16 || gf->SHeight != 16) {
   fprintf(stderr, "GIF: bad screen description (%d x %d)\n", gf->SWidth, gf->SHeight);
   return 1;
 }
-#if !defined(GIFLIB_MAJOR) || GIFLIB_MAJOR < 5
-/* crashes in older versions of giflib, not used in giflib 5 */
+/* crashes in older versions of giflib */
 EGifSetGifVersion("89a");
 EGifSetGifVersion("87a");
-#endif
 
 #ifdef GIF_LIB_VERSION
 /* skip the " Version " */
index 506e10054ae1fbf6744d82a1e9e8d7d8f0c3817a..78f6554e4fb4fdf36fd67d64f844da9b0ea10ac7 100644 (file)
@@ -59,70 +59,16 @@ functionality with giflib3.
 =cut
 */
 
-#if defined(GIFLIB_MAJOR) && GIFLIB_MAJOR >= 5
-#define myDGifOpen(userPtr, readFunc, Error) DGifOpen((userPtr), (readFunc), (Error))
-#define myEGifOpen(userPtr, readFunc, Error) EGifOpen((userPtr), (readFunc), (Error))
-#define myGifError(gif) ((gif)->Error)
-#define MakeMapObject GifMakeMapObject
-#define FreeMapObject GifFreeMapObject
-
-#define gif_mutex_lock()
-#define gif_mutex_unlock()
-#else
-static GifFileType *
-myDGifOpen(void *userPtr, InputFunc readFunc, int *error) {
-  GifFileType *result = DGifOpen(userPtr, readFunc);
-  if (!result)
-    *error = GifLastError();
-
-  return result;
-}
-static GifFileType *
-myEGifOpen(void *userPtr, OutputFunc outputFunc, int *error) {
-  GifFileType *result = EGifOpen(userPtr, outputFunc);
-  if (!result)
-    *error = GifLastError();
-
-  return result;
-}
-#define myGifError(gif) GifLastError()
-
-#define gif_mutex_lock() i_mutex_lock(mutex)
-#define gif_mutex_unlock() i_mutex_unlock(mutex)
-#define NEED_MUTEX
-#endif
-
 static char const *gif_error_msg(int code);
-static void gif_push_error(int code);
+static void gif_push_error(void);
 
 /* Make some variables global, so we could access them faster: */
 
-static const int
+static int
   InterlacedOffset[] = { 0, 4, 2, 1 }, /* The way Interlaced image should. */
   InterlacedJumps[] = { 8, 8, 4, 2 };    /* be read - offsets and jumps... */
 
 
-#ifdef NEED_MUTEX
-static i_mutex_t mutex;
-#endif
-
-/*
-=item i_init_gif()
-
-Initialize GIF support.
-
-For versions of giflib that require it, create a mutex to avoid
-reentrancy.
-
-=cut
-*/
-
-void
-i_init_gif(void) {
-#ifdef NEED_MUTEX
-  mutex = i_mutex_new();
-#endif
-}
 
 static
 void
@@ -192,7 +138,7 @@ i_readgif_low(GifFileType *GifFile, int **colour_table, int *colours) {
   GifByteType *Extension;
   
   GifRowType GifRow;
-  GifColorType *ColorMapEntry;
+  static GifColorType *ColorMapEntry;
   i_color col;
 
   mm_log((1,"i_readgif_low(GifFile %p, colour_table %p, colours %p)\n", GifFile, colour_table, colours));
@@ -241,7 +187,7 @@ i_readgif_low(GifFileType *GifFile, int **colour_table, int *colours) {
   /* Scan the content of the GIF file and load the image(s) in: */
   do {
     if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) {
-      gif_push_error(myGifError(GifFile));
+      gif_push_error();
       i_push_error(0, "Unable to get record type");
       if (colour_table && *colour_table) {
        myfree(*colour_table);
@@ -256,7 +202,7 @@ i_readgif_low(GifFileType *GifFile, int **colour_table, int *colours) {
     switch (RecordType) {
     case IMAGE_DESC_RECORD_TYPE:
       if (DGifGetImageDesc(GifFile) == GIF_ERROR) {
-       gif_push_error(myGifError(GifFile));
+       gif_push_error();
        i_push_error(0, "Unable to get image descriptor");
        if (colour_table && *colour_table) {
          myfree(*colour_table);
@@ -310,7 +256,7 @@ i_readgif_low(GifFileType *GifFile, int **colour_table, int *colours) {
        for (Count = i = 0; i < 4; i++) for (j = Row + InterlacedOffset[i]; j < Row + Height; j += InterlacedJumps[i]) {
          Count++;
          if (DGifGetLine(GifFile, GifRow, Width) == GIF_ERROR) {
-           gif_push_error(myGifError(GifFile));
+           gif_push_error();
            i_push_error(0, "Reading GIF line");
            if (colour_table && *colour_table) {
              myfree(*colour_table);
@@ -335,7 +281,7 @@ i_readgif_low(GifFileType *GifFile, int **colour_table, int *colours) {
       else {
        for (i = 0; i < Height; i++) {
          if (DGifGetLine(GifFile, GifRow, Width) == GIF_ERROR) {
-           gif_push_error(myGifError(GifFile));
+           gif_push_error();
            i_push_error(0, "Reading GIF line");
            if (colour_table && *colour_table) {
              myfree(*colour_table);
@@ -361,7 +307,7 @@ i_readgif_low(GifFileType *GifFile, int **colour_table, int *colours) {
     case EXTENSION_RECORD_TYPE:
       /* Skip any extension blocks in file: */
       if (DGifGetExtension(GifFile, &ExtCode, &Extension) == GIF_ERROR) {
-       gif_push_error(myGifError(GifFile));
+       gif_push_error();
        i_push_error(0, "Reading extension record");
        if (colour_table && *colour_table) {
          myfree(*colour_table);
@@ -374,7 +320,7 @@ i_readgif_low(GifFileType *GifFile, int **colour_table, int *colours) {
       }
       while (Extension != NULL) {
        if (DGifGetExtensionNext(GifFile, &Extension) == GIF_ERROR) {
-         gif_push_error(myGifError(GifFile));
+         gif_push_error();
          i_push_error(0, "reading next block of extension");
          if (colour_table && *colour_table) {
            myfree(*colour_table);
@@ -397,7 +343,7 @@ i_readgif_low(GifFileType *GifFile, int **colour_table, int *colours) {
   myfree(GifRow);
   
   if (DGifCloseFile(GifFile) == GIF_ERROR) {
-    gif_push_error(myGifError(GifFile));
+    gif_push_error();
     i_push_error(0, "Closing GIF file object");
     if (colour_table && *colour_table) {
       myfree(*colour_table);
@@ -417,8 +363,7 @@ i_readgif_low(GifFileType *GifFile, int **colour_table, int *colours) {
 Internal function called by i_readgif_multi_low() in error handling
 
 */
-static void
-free_images(i_img **imgs, int count) {
+static void free_images(i_img **imgs, int count) {
   int i;
   
   if (count) {
@@ -512,8 +457,7 @@ standard.
 =cut
 */
 
-i_img **
-i_readgif_multi_low(GifFileType *GifFile, int *count, int page) {
+i_img **i_readgif_multi_low(GifFileType *GifFile, int *count, int page) {
   i_img *img;
   int i, j, Size, Width, Height, ExtCode, Count;
   int ImageNum = 0, BackGround = 0, ColorMapSize = 0;
@@ -553,7 +497,7 @@ i_readgif_multi_low(GifFileType *GifFile, int *count, int page) {
   /* Scan the content of the GIF file and load the image(s) in: */
   do {
     if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) {
-      gif_push_error(myGifError(GifFile));
+      gif_push_error();
       i_push_error(0, "Unable to get record type");
       free_images(results, *count);
       DGifCloseFile(GifFile);
@@ -566,7 +510,7 @@ i_readgif_multi_low(GifFileType *GifFile, int *count, int page) {
     switch (RecordType) {
     case IMAGE_DESC_RECORD_TYPE:
       if (DGifGetImageDesc(GifFile) == GIF_ERROR) {
-       gif_push_error(myGifError(GifFile));
+       gif_push_error();
        i_push_error(0, "Unable to get image descriptor");
         free_images(results, *count);
        DGifCloseFile(GifFile);
@@ -699,7 +643,7 @@ i_readgif_multi_low(GifFileType *GifFile, int *count, int page) {
                 j += InterlacedJumps[i]) {
              Count++;
              if (DGifGetLine(GifFile, GifRow, Width) == GIF_ERROR) {
-               gif_push_error(myGifError(GifFile));
+               gif_push_error();
                i_push_error(0, "Reading GIF line");
                free_images(results, *count);
                DGifCloseFile(GifFile);
@@ -728,7 +672,7 @@ i_readgif_multi_low(GifFileType *GifFile, int *count, int page) {
        else {
          for (i = 0; i < Height; i++) {
            if (DGifGetLine(GifFile, GifRow, Width) == GIF_ERROR) {
-             gif_push_error(myGifError(GifFile));
+             gif_push_error();
              i_push_error(0, "Reading GIF line");
              free_images(results, *count);
              DGifCloseFile(GifFile);
@@ -769,7 +713,7 @@ i_readgif_multi_low(GifFileType *GifFile, int *count, int page) {
        /* giflib does't have an interface to skip the image data */
        for (i = 0; i < Height; i++) {
          if (DGifGetLine(GifFile, GifRow, Width) == GIF_ERROR) {
-           gif_push_error(myGifError(GifFile));
+           gif_push_error();
            i_push_error(0, "Reading GIF line");
            free_images(results, *count);
            myfree(GifRow);
@@ -791,7 +735,7 @@ i_readgif_multi_low(GifFileType *GifFile, int *count, int page) {
     case EXTENSION_RECORD_TYPE:
       /* Skip any extension blocks in file: */
       if (DGifGetExtension(GifFile, &ExtCode, &Extension) == GIF_ERROR) {
-       gif_push_error(myGifError(GifFile));
+       gif_push_error();
        i_push_error(0, "Reading extension record");
         free_images(results, *count);
        myfree(GifRow);
@@ -816,7 +760,7 @@ i_readgif_multi_low(GifFileType *GifFile, int *count, int page) {
       if (ExtCode == 0xFF && *Extension == 11) {
         if (memcmp(Extension+1, "NETSCAPE2.0", 11) == 0) {
           if (DGifGetExtensionNext(GifFile, &Extension) == GIF_ERROR) {
-            gif_push_error(myGifError(GifFile));
+            gif_push_error();
             i_push_error(0, "reading loop extension");
             free_images(results, *count);
            myfree(GifRow);
@@ -846,7 +790,7 @@ i_readgif_multi_low(GifFileType *GifFile, int *count, int page) {
       }
       while (Extension != NULL) {
        if (DGifGetExtensionNext(GifFile, &Extension) == GIF_ERROR) {
-         gif_push_error(myGifError(GifFile));
+         gif_push_error();
          i_push_error(0, "reading next block of extension");
           free_images(results, *count);
          myfree(GifRow);
@@ -875,7 +819,7 @@ i_readgif_multi_low(GifFileType *GifFile, int *count, int page) {
   myfree(GifRow);
   
   if (DGifCloseFile(GifFile) == GIF_ERROR) {
-    gif_push_error(myGifError(GifFile));
+    gif_push_error();
     i_push_error(0, "Closing GIF file object");
     free_images(results, *count);
     return NULL;
@@ -902,26 +846,17 @@ static int io_glue_read_cb(GifFileType *gft, GifByteType *buf, int length);
 i_img **
 i_readgif_multi_wiol(io_glue *ig, int *count) {
   GifFileType *GifFile;
-  i_img **result;
-  int gif_error;
-
-  gif_mutex_lock();
-
+  
   i_clear_error();
   
-  if ((GifFile = myDGifOpen((void *)ig, io_glue_read_cb, &gif_error )) == NULL) {
-    gif_push_error(gif_error);
+  if ((GifFile = DGifOpen((void *)ig, io_glue_read_cb )) == NULL) {
+    gif_push_error();
     i_push_error(0, "Cannot create giflib callback object");
     mm_log((1,"i_readgif_multi_wiol: Unable to open callback datasource.\n"));
-    gif_mutex_unlock();
     return NULL;
   }
     
-  result = i_readgif_multi_low(GifFile, count, -1);
-
-  gif_mutex_unlock();
-
-  return result;
+  return i_readgif_multi_low(GifFile, count, -1);
 }
 
 static int
@@ -934,26 +869,17 @@ io_glue_read_cb(GifFileType *gft, GifByteType *buf, int length) {
 i_img *
 i_readgif_wiol(io_glue *ig, int **color_table, int *colors) {
   GifFileType *GifFile;
-  i_img *result;
-  int gif_error;
-
-  gif_mutex_lock();
 
   i_clear_error();
 
-  if ((GifFile = myDGifOpen((void *)ig, io_glue_read_cb, &gif_error )) == NULL) {
-    gif_push_error(gif_error);
+  if ((GifFile = DGifOpen((void *)ig, io_glue_read_cb )) == NULL) {
+    gif_push_error();
     i_push_error(0, "Cannot create giflib callback object");
     mm_log((1,"i_readgif_wiol: Unable to open callback datasource.\n"));
-    gif_mutex_unlock();
     return NULL;
   }
     
-  result = i_readgif_low(GifFile, color_table, colors);
-
-  gif_mutex_unlock();
-
-  return result;
+  return i_readgif_low(GifFile, color_table, colors);
 }
 
 /*
@@ -998,8 +924,6 @@ Returns NULL if the page isn't found.
 i_img *
 i_readgif_single_wiol(io_glue *ig, int page) {
   GifFileType *GifFile;
-  i_img *result;
-  int gif_error;
 
   i_clear_error();
   if (page < 0) {
@@ -1007,21 +931,14 @@ i_readgif_single_wiol(io_glue *ig, int page) {
     return NULL;
   }
 
-  gif_mutex_lock();
-
-  if ((GifFile = myDGifOpen((void *)ig, io_glue_read_cb, &gif_error )) == NULL) {
-    gif_push_error(gif_error);
+  if ((GifFile = DGifOpen((void *)ig, io_glue_read_cb )) == NULL) {
+    gif_push_error();
     i_push_error(0, "Cannot create giflib callback object");
     mm_log((1,"i_readgif_wiol: Unable to open callback datasource.\n"));
-    gif_mutex_unlock();
     return NULL;
   }
     
-  result = i_readgif_single_low(GifFile, page);
-
-  gif_mutex_unlock();
-
-  return result;
+  return i_readgif_single_low(GifFile, page);
 }
 
 /*
@@ -1041,7 +958,7 @@ do_write(GifFileType *gf, int interlace, i_img *img, i_palidx *data) {
     for (i = 0; i < 4; ++i) {
       for (j = InterlacedOffset[i]; j < img->ysize; j += InterlacedJumps[i]) {
        if (EGifPutLine(gf, data+j*img->xsize, img->xsize) == GIF_ERROR) {
-         gif_push_error(myGifError(gf));
+         gif_push_error();
          i_push_error(0, "Could not save image data:");
          mm_log((1, "Error in EGifPutLine\n"));
          EGifCloseFile(gf);
@@ -1054,7 +971,7 @@ do_write(GifFileType *gf, int interlace, i_img *img, i_palidx *data) {
     int y;
     for (y = 0; y < img->ysize; ++y) {
       if (EGifPutLine(gf, data, img->xsize) == GIF_ERROR) {
-       gif_push_error(myGifError(gf));
+       gif_push_error();
        i_push_error(0, "Could not save image data:");
        mm_log((1, "Error in EGifPutLine\n"));
        EGifCloseFile(gf);
@@ -1076,9 +993,7 @@ Returns non-zero on success.
 
 =cut
 */
-
-static int
-do_gce(GifFileType *gf, i_img *img, int want_trans, int trans_index)
+static int do_gce(GifFileType *gf, i_img *img, int want_trans, int trans_index)
 {
   unsigned char gce[4] = {0};
   int want_gce = 0;
@@ -1107,7 +1022,7 @@ do_gce(GifFileType *gf, i_img *img, int want_trans, int trans_index)
   }
   if (want_gce) {
     if (EGifPutExtension(gf, 0xF9, sizeof(gce), gce) == GIF_ERROR) {
-      gif_push_error(myGifError(gf));
+      gif_push_error();
       i_push_error(0, "Could not save GCE");
     }
   }
@@ -1121,9 +1036,7 @@ Write any comments in the image.
 
 =cut
 */
-
-static int
-do_comments(GifFileType *gf, i_img *img) {
+static int do_comments(GifFileType *gf, i_img *img) {
   int pos = -1;
 
   while (i_tags_find(&img->tags, "gif_comment", pos+1, &pos)) {
@@ -1161,9 +1074,7 @@ writing extension blocks so that they could only be written to files.
 
 =cut
 */
-
-static int
-do_ns_loop(GifFileType *gf, i_img *img)
+static int do_ns_loop(GifFileType *gf, i_img *img)
 {
   /* EGifPutExtension() doesn't appear to handle application 
      extension blocks in any way
@@ -1180,33 +1091,19 @@ do_ns_loop(GifFileType *gf, i_img *img)
   if (i_tags_get_int(&img->tags, "gif_loop", 0, &loop_count)) {
     unsigned char nsle[12] = "NETSCAPE2.0";
     unsigned char subblock[3];
-
-    subblock[0] = 1;
-    subblock[1] = loop_count % 256;
-    subblock[2] = loop_count / 256;
-
-#if defined(GIFLIB_MAJOR) && GIFLIB_MAJOR >= 5
-    if (EGifPutExtensionLeader(gf, APPLICATION_EXT_FUNC_CODE) == GIF_ERROR
-       || EGifPutExtensionBlock(gf, 11, nsle) == GIF_ERROR
-       || EGifPutExtensionBlock(gf, 3, subblock) == GIF_ERROR
-       || EGifPutExtensionTrailer(gf) == GIF_ERROR) {
-      gif_push_error(myGifError(gf));
-      i_push_error(0, "writing loop extension");
-      return 0;
-    }
-       
-#else
     if (EGifPutExtensionFirst(gf, APPLICATION_EXT_FUNC_CODE, 11, nsle) == GIF_ERROR) {
-      gif_push_error(myGifError(gf));
+      gif_push_error();
       i_push_error(0, "writing loop extension");
       return 0;
     }
+    subblock[0] = 1;
+    subblock[1] = loop_count % 256;
+    subblock[2] = loop_count / 256;
     if (EGifPutExtensionLast(gf, APPLICATION_EXT_FUNC_CODE, 3, subblock) == GIF_ERROR) {
-      gif_push_error(myGifError(gf));
+      gif_push_error();
       i_push_error(0, "writing loop extension sub-block");
       return 0;
     }
-#endif
   }
 
   return 1;
@@ -1220,8 +1117,8 @@ Create a giflib color map object from an Imager color map.
 =cut
 */
 
-static ColorMapObject *
-make_gif_map(i_quantize *quant, i_img *img, int want_trans) {
+static ColorMapObject *make_gif_map(i_quantize *quant, i_img *img, 
+                                    int want_trans) {
   GifColorType colors[256];
   int i;
   int size = quant->mc_count;
@@ -1256,6 +1153,7 @@ make_gif_map(i_quantize *quant, i_img *img, int want_trans) {
   map = MakeMapObject(map_size, colors);
   mm_log((1, "XXX map is at %p and colors at %p\n", map, map->Colors));
   if (!map) {
+    gif_push_error();
     i_push_error(0, "Could not create color map object");
     return NULL;
   }
@@ -1292,14 +1190,10 @@ If t/t105gif.t crashes here then run Makefile.PL with
 
 or install a less buggy giflib.
 
-This code is completely unnecessary in giflib 5
-
 =cut
 */
 
-static void
-gif_set_version(i_quantize *quant, i_img **imgs, int count) {
-#if !defined(GIFLIB_MAJOR) || GIFLIB_MAJOR < 5
+static void gif_set_version(i_quantize *quant, i_img **imgs, int count) {
   int need_89a = 0;
   int temp;
   int i;
@@ -1330,7 +1224,6 @@ gif_set_version(i_quantize *quant, i_img **imgs, int count) {
      EGifSetGifVersion("89a");
   else
      EGifSetGifVersion("87a");
-#endif
 }
 
 static int 
@@ -1613,7 +1506,7 @@ i_writegif_low(i_quantize *quant, GifFileType *gf, i_img **imgs, int count) {
     myfree(localmaps);
     myfree(glob_imgs);
     quant->mc_colors = orig_colors;
-    gif_push_error(myGifError(gf));
+    gif_push_error();
     i_push_error(0, "Could not save screen descriptor");
     FreeMapObject(map);
     myfree(result);
@@ -1721,7 +1614,7 @@ i_writegif_low(i_quantize *quant, GifFileType *gf, i_img **imgs, int count) {
     myfree(localmaps);
     myfree(glob_imgs);
     quant->mc_colors = orig_colors;
-    gif_push_error(myGifError(gf));
+    gif_push_error();
     i_push_error(0, "Could not save image descriptor");
     EGifCloseFile(gf);
     mm_log((1, "Error in EGifPutImageDesc."));
@@ -1838,7 +1731,7 @@ i_writegif_low(i_quantize *quant, GifFileType *gf, i_img **imgs, int count) {
       myfree(localmaps);
       myfree(glob_imgs);
       quant->mc_colors = orig_colors;
-      gif_push_error(myGifError(gf));
+      gif_push_error();
       i_push_error(0, "Could not save image descriptor");
       myfree(result);
       if (map)
@@ -1866,7 +1759,7 @@ i_writegif_low(i_quantize *quant, GifFileType *gf, i_img **imgs, int count) {
     myfree(glob_colors);
     myfree(localmaps);
     myfree(glob_imgs);
-    gif_push_error(myGifError(gf));
+    gif_push_error();
     i_push_error(0, "Could not close GIF file");
     mm_log((1, "Error in EGifCloseFile\n"));
     return 0;
@@ -1903,26 +1796,20 @@ i_writegif_wiol(io_glue *ig, i_quantize *quant, i_img **imgs,
                 int count) {
   GifFileType *GifFile;
   int result;
-  int gif_error;
-
-  gif_mutex_lock();
 
   i_clear_error();
 
   gif_set_version(quant, imgs, count);
   
-  if ((GifFile = myEGifOpen((void *)ig, io_glue_write_cb, &gif_error )) == NULL) {
-    gif_push_error(gif_error);
+  if ((GifFile = EGifOpen((void *)ig, io_glue_write_cb )) == NULL) {
+    gif_push_error();
     i_push_error(0, "Cannot create giflib callback object");
     mm_log((1,"i_writegif_wiol: Unable to open callback datasource.\n"));
-    gif_mutex_unlock();
     return 0;
   }
   
   result = i_writegif_low(quant, GifFile, imgs, count);
   
-  gif_mutex_unlock();
-
   if (i_io_close(ig))
     return 0;
   
@@ -1935,16 +1822,15 @@ i_writegif_wiol(io_glue *ig, i_quantize *quant, i_img **imgs,
 Grabs the most recent giflib error code from GifLastError() and 
 returns a string that describes that error.
 
-Returns NULL for unknown error codes.
+The returned pointer points to a static buffer, either from a literal
+C string or a static buffer.
 
 =cut
 */
 
-static char const *
-gif_error_msg(int code) {
-#if defined(GIFLIB_MAJOR) && GIFLIB_MAJOR >= 5
-  return GifErrorString(code);
-#else
+static char const *gif_error_msg(int code) {
+  static char msg[80];
+
   switch (code) {
   case E_GIF_ERR_OPEN_FAILED: /* should not see this */
     return "Failed to open given file";
@@ -2016,13 +1902,17 @@ gif_error_msg(int code) {
     return "Unexpected EOF - invalid file";
 
   default:
-    return NULL;
-  }
+#ifdef IMAGER_SNPRINTF
+    snprintf(msg, sizeof(msg), "Unknown giflib error code %d", code);
+#else
+    sprintf(msg, "Unknown giflib error code %d", code);
 #endif
+    return msg;
+  }
 }
 
 /*
-=item gif_push_error(code)
+=item gif_push_error()
 
 Utility function that takes the current GIF error code, converts it to
 an error message and pushes it on the error stack.
@@ -2030,22 +1920,31 @@ an error message and pushes it on the error stack.
 =cut
 */
 
-static void
-gif_push_error(int code) {
-  const char *msg = gif_error_msg(code);
-  if (msg)
-    i_push_error(code, msg);
-  else
-    i_push_errorf(code, "Unknown GIF error %d", code);
+static void gif_push_error(void) {
+  int code = GifLastError(); /* clears saved error */
+
+  i_push_error(code, gif_error_msg(code));
 }
 
 /*
+=head1 BUGS
+
+The Netscape loop extension isn't implemented.  Giflib's extension
+writing code doesn't seem to support writing named extensions in this 
+form.
+
+A bug in giflib is tickled by the i_writegif_callback().  This isn't a
+problem on ungiflib, but causes a SEGV on giflib.  A patch is provided
+in t/t10formats.t
+
+The GIF file tag (GIF87a vs GIF89a) currently isn't set.  Using the
+supplied interface in giflib 4.1.0 causes a SEGV in
+EGifSetGifVersion().  See L<gif_set_version> for an explanation.
+
 =head1 AUTHOR
 
 Arnar M. Hrafnkelsson, addi@umich.edu
 
-Tony Cook <tonyc@cpan.org>
-
 =head1 SEE ALSO
 
 perl(1), Imager(3)
index 9a92e8c21ae7972b41da5ce3d830a93cdf67a440..ca92af5d3fd1e6519bcba9b781388cf2327dfae2 100644 (file)
@@ -3,7 +3,6 @@
 
 #include "imext.h"
 
-void i_init_gif(void);
 double i_giflib_version(void);
 i_img *i_readgif_wiol(io_glue *ig, int **colour_table, int *colours);
 i_img *i_readgif_single_wiol(io_glue *ig, int page);
index b766f81e290f03fd99f857016935c6ed38de05dc..c926b0c6bcfe787f21b7a10e36dc6ba0d23b7642 100644 (file)
@@ -404,8 +404,7 @@ read_failure('testimg/nocmap.gif');
      ($io, { make_colors=>'addi',
             translate=>'closest',
             transp=>'ordered',
-          }, @imgs), "write from paletted")
-    or diag(Imager->_error_as_msg());
+          }, @imgs), "write from paletted");
   close FH;
   
   # make sure nothing bad happened
index 399a20936054f7e970c801da4537060ca01f09d6..71af06867ce35bf7a66764ce7029194b08e83db3 100644 (file)
--- a/Imager.pm
+++ b/Imager.pm
@@ -4363,10 +4363,6 @@ L<Imager::ExtUtils> - tools to get access to Imager's C API.
 
 L<Imager::Security> - brief security notes.
 
-=item *
-
-L<Imager::Threads> - brief information on working with threads.
-
 =back
 
 =head2 Basic Overview
@@ -4808,8 +4804,6 @@ text, wrapping text in an area - L<Imager::Font::Wrap>
 
 text, measuring - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
 
-threads - L<Imager::Threads>
-
 tiles, color - L<Imager::Filters/mosaic>
 
 transparent images - L<Imager::ImageTypes>,
@@ -4823,6 +4817,15 @@ watermark - L<Imager::Filters/watermark>
 
 writing an image to a file - L<Imager::Files>
 
+=head1 THREADS
+
+Imager doesn't support perl threads.
+
+Imager has limited code to prevent double frees if you create images,
+colors etc, and then create a thread, but has no code to prevent two
+threads entering Imager's error handling code, and none is likely to
+be added.
+
 =head1 SUPPORT
 
 The best place to get help with Imager is the mailing list.
index 81918e8e888ffa79dab99fc31fd8687ae648914c..2a01e2a88476ea27c3e122d397fd5a6ece841c02 100644 (file)
--- a/Imager.xs
+++ b/Imager.xs
@@ -29,69 +29,6 @@ extern "C" {
 
 #include "imperl.h"
 
-/*
-
-Context object management
-
-*/
-
-typedef im_context_t Imager__Context;
-
-#define im_context_DESTROY(ctx) im_context_refdec((ctx), "DESTROY")
-
-#ifdef PERL_IMPLICIT_CONTEXT
-
-#define MY_CXT_KEY "Imager::_context" XS_VERSION
-
-typedef struct {
-  im_context_t ctx;
-} my_cxt_t;
-
-START_MY_CXT
-
-im_context_t fallback_context;
-
-static void
-start_context(pTHX) {
-  dMY_CXT;
-  MY_CXT.ctx = im_context_new();
-  sv_setref_pv(get_sv("Imager::_context", GV_ADD), "Imager::Context", MY_CXT.ctx);
-
-  /* Ideally we'd free this reference, but the error message memory
-     was never released on exit, so the associated memory here is reasonable
-     to keep.
-     With logging enabled we always need at least one context, since
-     objects may be released fairly late and attempt to get the log file.
-  */
-  im_context_refinc(MY_CXT.ctx, "start_context");
-  fallback_context = MY_CXT.ctx;
-}
-
-static im_context_t
-perl_get_context(void) {
-  dTHX;
-  dMY_CXT;
-  
-  return MY_CXT.ctx ? MY_CXT.ctx : fallback_context;
-}
-
-#else
-
-static im_context_t perl_context;
-
-static void
-start_context(pTHX) {
-  perl_context = im_context_new();
-  im_context_refinc(perl_context, "start_context");
-}
-
-static im_context_t
-perl_get_context(void) {
-  return perl_context;
-}
-
-#endif
-
 /* used to represent channel lists parameters */
 typedef struct i_channel_list_tag {
   int *channels;
@@ -790,6 +727,7 @@ validate_i_ppal(i_img *im, i_palidx const *indexes, int count) {
   }
 }
 
+
 /* I don't think ICLF_* names belong at the C interface
    this makes the XS code think we have them, to let us avoid 
    putting function bodies in the XS code
@@ -4051,37 +3989,6 @@ i_int_hlines_CLONE_SKIP(cls)
 
 #endif
 
-MODULE = Imager  PACKAGE = Imager::Context PREFIX=im_context_
-
-void
-im_context_DESTROY(ctx)
-   Imager::Context ctx
-
-#ifdef PERL_IMPLICIT_CONTEXT
-
-void
-im_context_CLONE(...)
-    CODE:
-      MY_CXT_CLONE;
-      (void)items;
-      /* the following sv_setref_pv() will free this inc */
-      im_context_refinc(MY_CXT.ctx, "CLONE");
-      MY_CXT.ctx = im_context_clone(MY_CXT.ctx, "CLONE");
-      sv_setref_pv(get_sv("Imager::_context", GV_ADD), "Imager::Context", MY_CXT.ctx);
-
-#endif
-
 BOOT:
         PERL_SET_GLOBAL_CALLBACKS;
        PERL_PL_SET_GLOBAL_CALLBACKS;
-#ifdef PERL_IMPLICIT_CONTEXT
-       {
-          MY_CXT_INIT;
-         (void)MY_CXT;
-       }
-#endif
-       start_context(aTHX);
-       im_get_context = perl_get_context;
-#ifdef HAVE_LIBTT
-        i_tt_start();
-#endif
index 1812140e562daf5f67330ebe14d8eb88956916a2..370ad4b27d3a28c083d037b1ede47cd523ceb95a 100644 (file)
@@ -4,7 +4,7 @@ use Imager;
 use vars qw($VERSION @ISA);
 
 BEGIN {
-  $VERSION = "0.85";
+  $VERSION = "0.84";
 
   require XSLoader;
   XSLoader::load('Imager::File::JPEG', $VERSION);
index c9787bd5ba51cead5df37cf16caebbfc4258b7bb..d4341b40bd28784d32de32277a8a5152371a0ca4 100644 (file)
@@ -28,12 +28,12 @@ Reads and writes JPEG images
 #include <unistd.h>
 #endif
 #include <setjmp.h>
-#include <string.h>
 
 #include "jpeglib.h"
 #include "jerror.h"
 #include <errno.h>
 #include <stdlib.h>
+#include <stdio.h>
 #include "imexif.h"
 
 #define JPEG_APP13       0xED    /* APP13 marker code */
@@ -44,8 +44,15 @@ Reads and writes JPEG images
 
 static unsigned char fake_eoi[]={(JOCTET) 0xFF,(JOCTET) JPEG_EOI};
 
+/* Bad design right here */
+
+static int tlength=0;
+static char **iptc_text=NULL;
+
+
 /* Source and Destination managers */
 
+
 typedef struct {
   struct jpeg_source_mgr pub;  /* public fields */
   io_glue *data;
@@ -64,6 +71,7 @@ typedef struct {
 typedef wiol_source_mgr *wiol_src_ptr;
 typedef wiol_destination_mgr *wiol_dest_ptr;
 
+
 /*
  * Methods for io manager objects 
  * 
@@ -263,6 +271,38 @@ jpeg_wiol_dest(j_compress_ptr cinfo, io_glue *ig) {
   dest->pub.next_output_byte    = dest->buffer;
 }
 
+LOCAL(unsigned int)
+jpeg_getc (j_decompress_ptr cinfo)
+/* Read next byte */
+{
+  struct jpeg_source_mgr * datasrc = cinfo->src;
+
+  if (datasrc->bytes_in_buffer == 0) {
+    if (! (*datasrc->fill_input_buffer) (cinfo))
+      { fprintf(stderr,"Jpeglib: cant suspend.\n"); exit(3); }
+      /*      ERREXIT(cinfo, JERR_CANT_SUSPEND);*/
+  }
+  datasrc->bytes_in_buffer--;
+  return GETJOCTET(*datasrc->next_input_byte++);
+}
+
+METHODDEF(boolean)
+APP13_handler (j_decompress_ptr cinfo) {
+  INT32 length;
+  unsigned int cnt=0;
+  
+  length = jpeg_getc(cinfo) << 8;
+  length += jpeg_getc(cinfo);
+  length -= 2; /* discount the length word itself */
+  
+  tlength=length;
+
+  if ( ((*iptc_text)=mymalloc(length)) == NULL ) return FALSE;
+  while (--length >= 0) (*iptc_text)[cnt++] = jpeg_getc(cinfo); 
+  return TRUE;
+}
+
 METHODDEF(void)
 my_output_message (j_common_ptr cinfo) {
   char buffer[JMSG_LENGTH_MAX];
@@ -360,9 +400,7 @@ i_readjpeg_wiol(io_glue *data, int length, char** iptc_itext, int *itlength) {
 
   i_clear_error();
 
-  *iptc_itext = NULL;
-  *itlength = 0;
-
+  iptc_text = iptc_itext;
   cinfo.err = jpeg_std_error(&jerr.pub);
   jerr.pub.error_exit     = my_error_exit;
   jerr.pub.output_message = my_output_message;
@@ -372,6 +410,8 @@ i_readjpeg_wiol(io_glue *data, int length, char** iptc_itext, int *itlength) {
     if (src_set)
       wiol_term_source(&cinfo);
     jpeg_destroy_decompress(&cinfo); 
+    *iptc_itext=NULL;
+    *itlength=0;
     if (line_buffer)
       myfree(line_buffer);
     if (im)
@@ -380,7 +420,7 @@ i_readjpeg_wiol(io_glue *data, int length, char** iptc_itext, int *itlength) {
   }
   
   jpeg_create_decompress(&cinfo);
-  jpeg_save_markers(&cinfo, JPEG_APP13, 0xFFFF);
+  jpeg_set_marker_processor(&cinfo, JPEG_APP13, APP13_handler);
   jpeg_save_markers(&cinfo, JPEG_APP1, 0xFFFF);
   jpeg_save_markers(&cinfo, JPEG_COM, 0xFFFF);
   jpeg_wiol_src(&cinfo, data, length);
@@ -475,11 +515,6 @@ i_readjpeg_wiol(io_glue *data, int length, char** iptc_itext, int *itlength) {
     else if (markerp->marker == JPEG_APP1 && !seen_exif) {
       seen_exif = i_int_decode_exif(im, markerp->data, markerp->data_length);
     }
-    else if (markerp->marker == JPEG_APP13) {
-      *iptc_itext = mymalloc(markerp->data_length);
-      memcpy(*iptc_itext, markerp->data, markerp->data_length);
-      *itlength = markerp->data_length;
-    }
 
     markerp = markerp->next;
   }
@@ -522,6 +557,7 @@ i_readjpeg_wiol(io_glue *data, int length, char** iptc_itext, int *itlength) {
 
   (void) jpeg_finish_decompress(&cinfo);
   jpeg_destroy_decompress(&cinfo);
+  *itlength=tlength;
 
   i_tags_set(&im->tags, "i_format", "jpeg", 4);
 
index 18c0e8de8106e422ec1e2778a05457846ba3dca5..67abad36070dbbd4a20d7648b679f901f43511e1 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -7,7 +7,6 @@ Changes.old                     Old changes
 color.c                                Color translation and handling
 combine.im                     Channel combine
 compose.im
-context.c
 conv.im
 convert.im
 CountColor/CountColor.pm       sample XS access to API
@@ -50,7 +49,7 @@ Flines/Flines.xs
 Flines/Makefile.PL
 Flines/t/t00flines.t
 flip.im
-fontft1.c
+font.c
 fontfiles/dodge.ttf
 fontfiles/ExistenceTest.ttf    generated using pfaedit
 fontfiles/ImUgly.ttf
@@ -69,7 +68,6 @@ FT2/imft2.h
 FT2/Makefile.PL
 FT2/README
 FT2/t/t10ft2.t
-FT2/t/t20thread.t
 FT2/typemap
 gaussian.im
 GIF/GIF.pm
@@ -201,7 +199,6 @@ lib/Imager/regmach.pod
 lib/Imager/Regops.pm
 lib/Imager/Security.pod
 lib/Imager/Test.pm
-lib/Imager/Threads.pod
 lib/Imager/Transform.pm
 lib/Imager/Transformations.pod
 lib/Imager/Tutorial.pod
@@ -218,9 +215,6 @@ MANIFEST
 MANIFEST.SKIP
 map.c
 maskimg.c
-mutexnull.c
-mutexpthr.c
-mutexwin.c
 palimg.c
 paste.im
 plug.h
@@ -355,7 +349,6 @@ t/t80texttools.t            Test text wrapping
 t/t81hlines.t                  Test hlines.c
 t/t82inline.t                  Test Inline::C integration
 t/t83extutil.t                 Test Imager::ExtUtils
-t/t84inlinectx.t
 t/t90cc.t
 t/t91pod.t                     Test POD with Test::Pod
 t/t92samples.t
@@ -380,7 +373,6 @@ T1/t/t10type1.t
 T1/t/t20oo.t
 T1/T1.pm
 T1/T1.xs
-T1/typemap
 tags.c
 testimg/alpha16.tga            16-bit/pixel TGA with alpha "channel" RT 32926
 testimg/bad1oflow.bmp          1-bit/pixel, overflow integer on 32-bit machines
index aee608cd7415cc43bf0ad188e9e9cc88ed95758f..0f7a98bba0a7499000a09fa768c6f8fab1b1eda5 100644 (file)
@@ -48,7 +48,6 @@ my @incpaths; # places to look for headers
 my @libpaths; # places to look for libraries
 my $coverage; # build for coverage testing
 my $assert; # build with assertions
-my $trace_context; # trace context management to stderr
 GetOptions("help" => \$help,
            "enable=s" => \@enable,
            "disable=s" => \@disable,
@@ -57,8 +56,7 @@ GetOptions("help" => \$help,
            "verbose|v" => \$VERBOSE,
            "nolog" => \$NOLOG,
           'coverage' => \$coverage,
-          "assert|a" => \$assert,
-          "tracecontext" => \$trace_context);
+          "assert|a" => \$assert);
 
 setenv();
 
@@ -161,42 +159,19 @@ my $OSDEF  = "-DOS_$^O";
 if ($^O eq 'hpux')                { $OSLIBS .= ' -ldld'; }
 if (defined $Config{'d_dlsymun'}) { $OSDEF  .= ' -DDLSYMUN'; }
 
-my @objs = qw(Imager.o context.o draw.o polygon.o image.o io.o iolayer.o
-              log.o gaussian.o conv.o pnm.o raw.o feat.o combine.o
+my @objs = qw(Imager.o draw.o polygon.o image.o io.o iolayer.o
+              log.o gaussian.o conv.o pnm.o raw.o feat.o font.o combine.o
               filters.o dynaload.o stackmach.o datatypes.o
               regmach.o trans2.o quant.o error.o convert.o
               map.o tags.o palimg.o maskimg.o img8.o img16.o rotate.o
               bmp.o tga.o color.o fills.o imgdouble.o limits.o hlines.o
               imext.o scale.o rubthru.o render.o paste.o compose.o flip.o);
 
-if ($Config{useithreads}) {
-  if ($Config{i_pthread}) {
-    print "POSIX threads\n";
-    push @objs, "mutexpthr.o";
-  }
-  elsif ($^O eq 'MSWin32') {
-    print "Win32 threads\n";
-    push @objs, "mutexwin.o";
-  }
-  else {
-    print "Unsupported threading model\n";
-    push @objs, "mutexnull.o";
-  }
-}
-else {
-  print "No threads\n";
-  push @objs, "mutexnull.o";
-}
-
 my @typemaps = qw(typemap.local typemap);
 if ($] < 5.008) {
     unshift @typemaps, "typemap.oldperl";
 }
 
-if ($trace_context) {
-  $CFLAGS .= " -DIMAGER_TRACE_CONTEXT";
-}
-
 my %opts=
   (
    'NAME'         => 'Imager',
@@ -546,7 +521,7 @@ sub init {
                        && !-e catfile($_[0], 'fterrors.h') },
      libcheck=>sub { $_[0] eq "libttf$aext" or $_[0] eq "libttf.$lext" },
      libfiles=>'-lttf',
-     objfiles=>'fontft1.o',
+     objfiles=>'',
      code => \&freetype1_probe,
      docs=>q{
 Truetype fonts are scalable fonts. They can include 
index 7efa4a731d0e135c02af0bd37927298eb4a9df17..23c7f6d343d8cf1421bc5cdb77d209fdf61c24c3 100644 (file)
@@ -1,12 +1,3 @@
-Imager::Font::T1 1.018
-======================
-
- - use mutexes to avoid re-entrancy into the thread-unsafe T1Lib
-
- - improve error handling and reporting
-
- - provide better control of the level of anti-aliasing
-
 Imager::Font::T1 1.017
 ======================
 
index bbbf21c70ddb2f863b89a477c92a13e45c89c133..88f3ac8323488d06109091046a9778786ba92a79 100644 (file)
@@ -16,4 +16,3 @@ t/t10type1.t
 t/t20oo.t
 T1.pm
 T1.xs
-typemap
index d184b83a57a8c1f81a70a68777e62a6fb2835a76..374fb5a7ad24ab7a7951e3967ea24238ec2f7e93 100644 (file)
--- a/T1/T1.pm
+++ b/T1/T1.pm
@@ -5,7 +5,7 @@ use vars qw(@ISA $VERSION);
 @ISA = qw(Imager::Font);
 
 BEGIN {
-  $VERSION = "1.018";
+  $VERSION = "1.017";
 
   require XSLoader;
   XSLoader::load('Imager::Font::T1', $VERSION);
@@ -14,7 +14,17 @@ BEGIN {
 
 *_first = \&Imager::Font::_first;
 
-my $t1aa = 2;
+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;
@@ -55,42 +65,39 @@ sub new {
          $hsh{afm} = 0;
   }
 
-  my $font = Imager::Font::T1xs->new($hsh{file},$hsh{afm});
-  unless ($font) { # the low-level code may miss some error handling
+  my $id = i_t1_new($hsh{file},$hsh{afm});
+  unless ($id >= 0) { # the low-level code may miss some error handling
     Imager->_set_error(Imager->_error_as_msg);
     return;
   }
   return bless {
-               t1font    => $font,
+               id    => $id,
                aa    => $hsh{aa} || 0,
                file  => $hsh{file},
                type  => 't1',
                size  => $hsh{size},
                color => $hsh{color},
-               t1aa  => $t1aa,
               }, $class;
 }
 
 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};
-  my $aa = $input{aa} ? $self->{t1aa} : 0;
   if (exists $input{channel}) {
-    $self->{t1font}->cp($input{image}{IMG}, $input{'x'}, $input{'y'},
-                   $input{channel}, $input{size},
+    i_t1_cp($input{image}{IMG}, $input{'x'}, $input{'y'},
+                   $input{channel}, $self->{id}, $input{size},
                    $input{string}, length($input{string}), $input{align},
-                    $input{utf8}, $flags, $aa)
-      or return;
+                    $input{utf8}, $flags);
   } else {
-    $self->{t1font}->text($input{image}{IMG}, $input{'x'}, $input{'y'}, 
-                     $input{color}, $input{size}, 
+    i_t1_text($input{image}{IMG}, $input{'x'}, $input{'y'}, 
+                     $input{color}, $self->{id}, $input{size}, 
                      $input{string}, length($input{string}), 
-                     $input{align}, $input{utf8}, $flags, $aa)
-      or return;
+                     $input{align}, $input{utf8}, $flags);
   }
 
   return $self;
@@ -103,7 +110,7 @@ sub _bounding_box {
   $flags .= 'u' if $input{underline};
   $flags .= 's' if $input{strikethrough};
   $flags .= 'o' if $input{overline};
-  return $self->{t1font}->bbox($input{size}, $input{string},
+  return i_t1_bbox($self->{id}, $input{size}, $input{string},
                           length($input{string}), $input{utf8}, $flags);
 }
 
@@ -115,8 +122,8 @@ sub has_chars {
     $Imager::ERRSTR = "No string supplied to \$font->has_chars()";
     return;
   }
-  return $self->{t1font}->has_chars($hsh{string}, 
-                                   _first($hsh{'utf8'}, $self->{utf8}, 0));
+  return i_t1_has_chars($self->{id}, $hsh{string}, 
+                               _first($hsh{'utf8'}, $self->{utf8}, 0));
 }
 
 sub utf8 {
@@ -126,7 +133,7 @@ sub utf8 {
 sub face_name {
   my ($self) = @_;
 
-  return $self->{t1font}->face_name();
+  i_t1_face_name($self->{id});
 }
 
 sub glyph_names {
@@ -137,27 +144,9 @@ sub glyph_names {
     or return Imager->_set_error("no string parameter passed to glyph_names");
   my $utf8 = _first($input{utf8} || 0);
 
-  return $self->{t1font}->glyph_name($string, $utf8);
+  i_t1_glyph_name($self->{id}, $string, $utf8);
 }
 
-sub set_aa_level {
-  my ($self, $new_t1aa) = @_;
-
-  if (!defined $new_t1aa ||
-      ($new_t1aa != 1 && $new_t1aa != 2)) {
-    Imager->_set_error("set_aa_level: parameter must be 1 or 2");
-    return;
-  }
-
-  if (ref $self) {
-    $self->{t1aa} = $new_t1aa;
-  }
-  else {
-    $t1aa = $new_t1aa;
-  }
-
-  return 1;
-}
 
 1;
 
@@ -208,32 +197,6 @@ C<strikethrough> - Draw the text with a strikethrough.
 Obviously, if you're calculating the bounding box the size of the line
 is included in the box, and the line isn't drawn :)
 
-=head2 Anti-aliasing
-
-T1Lib supports multiple levels of anti-aliasing, by default, if you
-request anti-aliased output, Imager::Font::T1 will use the maximum
-level.
-
-You can override this with the set_t1_aa() method:
-
-=over
-
-=item set_aa_level()
-
-Usage:
-
-  $font->set_aa_level(1);
-  Imager::Font::T1->set_aa_level(2);
-
-Sets the T1Lib anti-aliasing level either for the specified font, or
-for new font objects.
-
-The only parameter must be 1 or 2.
-
-Returns true on success.
-
-=back
-
 =head1 AUTHOR
 
 Addi, Tony
index 63307331d29d7e51def731e0fbd6f60dd2432103..f587fb094212f8b60e107f97e2bb9cbda1b54e16 100644 (file)
--- a/T1/T1.xs
+++ b/T1/T1.xs
@@ -11,43 +11,38 @@ 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
 
-MODULE = Imager::Font::T1  PACKAGE = Imager::Font::T1xs PREFIX = i_t1_
+void
+i_t1_set_aa(st)
+              int     st
 
-Imager::Font::T1xs
-i_t1_new(class,pfb,afm)
+int
+i_t1_new(pfb,afm)
                      char*    pfb
                      char*    afm
-  C_ARGS:
-    pfb, afm
 
-void
-i_t1_DESTROY(font)
- Imager::Font::T1xs font       
+int
+i_t1_destroy(font_id)
+                      int     font_id
 
 
 undef_int
-i_t1_cp(font,im,xb,yb,channel,points,str_sv, length(str),align,utf8=0,flags="",aa=1)
- Imager::Font::T1xs     font
+i_t1_cp(im,xb,yb,channel,fontnum,points,str_sv,len_ignored,align,utf8=0,flags="")
     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;
@@ -57,15 +52,15 @@ i_t1_cp(font,im,xb,yb,channel,points,str_sv, length(str),align,utf8=0,flags="",a
                  utf8 = 1;
 #endif
                str = SvPV(str_sv, len);
-               RETVAL = i_t1_cp(font, im, xb,yb,channel,points,str,len,align,
-                                  utf8,flags,aa);
+               RETVAL = i_t1_cp(im, xb,yb,channel,fontnum,points,str,len,align,
+                                  utf8,flags);
            OUTPUT:
              RETVAL
 
 
 void
 i_t1_bbox(fontnum,point,str_sv,len_ignored,utf8=0,flags="")
Imager::Font::T1xs     fontnum
              int     fontnum
            double     point
                SV*    str_sv
                int     utf8
@@ -92,18 +87,17 @@ i_t1_bbox(fontnum,point,str_sv,len_ignored,utf8=0,flags="")
 
 
 undef_int
-i_t1_text(font,im,xb,yb,cl,points,str_sv,length(str),align,utf8=0,flags="",aa=1)
- Imager::Font::T1xs font
+i_t1_text(im,xb,yb,cl,fontnum,points,str_sv,len_ignored,align,utf8=0,flags="")
     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
-        const char*    flags
-              int     aa
+              char*    flags
              PREINIT:
                char *str;
                STRLEN len;
@@ -113,14 +107,14 @@ i_t1_text(font,im,xb,yb,cl,points,str_sv,length(str),align,utf8=0,flags="",aa=1)
                  utf8 = 1;
 #endif
                str = SvPV(str_sv, len);
-               RETVAL = i_t1_text(font,im, xb,yb,cl,points,str,len,align,
-                                  utf8,flags,aa);
+               RETVAL = i_t1_text(im, xb,yb,cl,fontnum,points,str,len,align,
+                                  utf8,flags);
            OUTPUT:
              RETVAL
 
 void
-i_t1_has_chars(font, text_sv, utf8 = 0)
- Imager::Font::T1xs font
+i_t1_has_chars(handle, text_sv, utf8 = 0)
+        int handle
         SV  *text_sv
         int utf8
       PREINIT:
@@ -136,10 +130,9 @@ i_t1_has_chars(font, text_sv, utf8 = 0)
 #endif
         text = SvPV(text_sv, len);
         work = mymalloc(len);
-        count = i_t1_has_chars(font, text, len, utf8, work);
+        count = i_t1_has_chars(handle, text, len, utf8, work);
         if (GIMME_V == G_ARRAY) {
           EXTEND(SP, count);
-
           for (i = 0; i < count; ++i) {
             PUSHs(boolSV(work[i]));
           }
@@ -151,21 +144,21 @@ i_t1_has_chars(font, text_sv, utf8 = 0)
         myfree(work);
 
 void
-i_t1_face_name(font)
- Imager::Font::T1xs font
+i_t1_face_name(handle)
+        int handle
       PREINIT:
         char name[255];
         int len;
       PPCODE:
-        len = i_t1_face_name(font, name, sizeof(name));
+        len = i_t1_face_name(handle, name, sizeof(name));
         if (len) {
           EXTEND(SP, 1);
           PUSHs(sv_2mortal(newSVpv(name, strlen(name))));
         }
 
 void
-i_t1_glyph_name(font, text_sv, utf8 = 0)
- Imager::Font::T1xs font
+i_t1_glyph_name(handle, text_sv, utf8 = 0)
+        int handle
         SV *text_sv
         int utf8
       PREINIT:
@@ -194,7 +187,7 @@ i_t1_glyph_name(font, text_sv, utf8 = 0)
             --len;
           }
           EXTEND(SP, 1);
-          if (i_t1_glyph_name(font, ch, name, sizeof(name))) {
+          if (i_t1_glyph_name(handle, ch, name, sizeof(name))) {
             PUSHs(sv_2mortal(newSVpv(name, 0)));
           }
           else {
@@ -204,4 +197,3 @@ i_t1_glyph_name(font, text_sv, utf8 = 0)
 
 BOOT:
        PERL_INITIALIZE_IMAGER_CALLBACKS;
-       i_t1_start();
\ No newline at end of file
index d0686bbdd47c896e0d4174e346a1c9fadd431bd3..3027e424373c3aef7405d51c30ef58acad9b5095 100644 (file)
--- a/T1/imt1.c
+++ b/T1/imt1.c
@@ -5,33 +5,11 @@
 
 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)
@@ -43,21 +21,8 @@ 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(%d)\n", t1log));
+  mm_log((1,"init_t1()\n"));
 
   i_clear_error();
 
@@ -80,6 +45,7 @@ i_init_t1_low(int t1log) {
     return(1);
   }
   T1_SetLogLevel(T1LOG_DEBUG);
+  i_t1_set_aa(1); /* Default Antialias value */
 
   ++t1_initialized;
 
@@ -98,10 +64,8 @@ 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);
 }
 
 
@@ -116,27 +80,21 @@ Loads the fonts with the given filenames, returns its font id
 =cut
 */
 
-i_t1_font_t
+int
 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_low(0)) {
-    i_mutex_unlock(mutex);
-    return NULL;
-  }
+  if (!t1_initialized && i_init_t1(0))
+    return -1;
 
   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();
-    i_mutex_unlock(mutex);
-    return NULL;
+    return font_id;
   }
   
   if (afm != NULL) {
@@ -149,48 +107,33 @@ i_t1_new(char *pfb,char *afm) {
     t1_push_error();
     i_push_error(0, "loading font");
     T1_DeleteFont(font_id);
-    i_mutex_unlock(mutex);
-    return NULL;
+    return -1;
   }
 
   ++t1_active_fonts;
 
-  i_mutex_unlock(mutex);
-
-  font = mymalloc(sizeof(*font));
-  font->font_id = font_id;
-
-  mm_log((1, "i_t1_new() -> %p (%d)\n", font, font_id));
+  mm_log((1, "i_t1_new() -> %d\n", font_id));
 
-  return font;
+  return font_id;
 }
 
 /*
-=item i_t1_destroy(font)
+=item i_t1_destroy(font_id)
 
 Frees resources for a t1 font with given font id.
 
-   font - font to free
+   font_id - number of the font to free
 
 =cut
 */
 
 int
-i_t1_destroy(i_t1_font_t font) {
-  int result;
-
-  i_mutex_lock(mutex);
-
-  mm_log((1,"i_t1_destroy(font %p (%d))\n", font, font->font_id));
+i_t1_destroy(int font_id) {
+  mm_log((1,"i_t1_destroy(font_id %d)\n",font_id));
 
   --t1_active_fonts;
 
-  result = T1_DeleteFont(font->font_id);
-  myfree(font);
-
-  i_mutex_unlock(mutex);
-
-  return result;
+  return T1_DeleteFont(font_id);
 }
 
 
@@ -201,19 +144,13 @@ Sets the antialiasing level of the t1 library.
 
    st - 0 =  NONE, 1 = LOW, 2 =  HIGH.
 
-Must be called with the mutex locked.
-
 =cut
 */
 
-static void
+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 );
@@ -234,13 +171,11 @@ 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,aa)
+=item i_t1_cp(im, xb, yb, channel, fontnum, points, str, len, align)
 
 Interface to text rendering into a single channel in an image
 
@@ -253,35 +188,20 @@ 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 level
 
 =cut
 */
 
 undef_int
-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) {
+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) {
   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;
   
-  i_clear_error();
-
-  mm_log((1, "i_t1_cp(font %p (%d), im %p, (xb,yb)=" i_DFp ", channel %d, points %g, str %p, len %u, align %d, utf8 %d, flags '%s', aa %d)\n",
-         font, fontnum, im, i_DFcp(xb, yb), channel, points, str, (unsigned)len, align, utf8, flags, aa));
-
-  if (im == NULL) {
-    mm_log((1,"i_t1_cp: Null image in input\n"));
-    i_push_error(0, "null image");
-    return(0);
-  }
-
-  i_mutex_lock(mutex);
-
-  i_t1_set_aa(aa);
+  if (im == NULL) { mm_log((1,"i_t1_cp: Null image in input\n")); return(0); }
 
   if (utf8) {
     int worklen;
@@ -292,12 +212,8 @@ i_t1_cp(i_t1_font_t font, i_img *im,i_img_dim xb,i_img_dim yb,int channel,double
   else {
     glyph=T1_AASetString( fontnum, str, len, 0, mod_flags, points, NULL);
   }
-  if (glyph == NULL) {
-    t1_push_error();
-    i_push_error(0, "i_t1_cp: T1_AASetString failed");
-    i_mutex_unlock(mutex);
+  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));
@@ -320,9 +236,6 @@ i_t1_cp(i_t1_font_t font, i_img *im,i_img_dim xb,i_img_dim yb,int channel,double
   }
   
   im->ch_mask=ch_mask_store;
-
-  i_mutex_unlock(mutex);
-
   return 1;
 }
 
@@ -354,19 +267,14 @@ function to get a strings bounding box given the font id and sizes
 */
 
 int
-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) {
+i_t1_bbox(int fontnum, 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 fontnum = font->font_id;
-  int space_position;
-
-  i_mutex_lock(mutex);
-
-  space_position = T1_GetEncodingIndex(fontnum, "space");
+  int space_position = T1_GetEncodingIndex(fontnum, "space");
   
-  mm_log((1,"i_t1_bbox(font %p (%d),points %.2f,str '%.*s', len %d)\n",font, fontnum,points,len,str,len));
+  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 (len == 0) {
@@ -414,14 +322,12 @@ i_t1_bbox(i_t1_font_t font, double points,const char *str,size_t len, i_img_dim
   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, aa)
+=item i_t1_text(im, xb, yb, cl, fontnum, points, str, len, align)
 
 Interface to text rendering in a single color onto an image
 
@@ -434,33 +340,18 @@ 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_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) {
+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) {
   GLYPH *glyph;
   int xsize,ysize,y;
   int mod_flags = t1_get_flags(flags);
   i_render *r;
-  int fontnum = font->font_id;
 
-  mm_log((1, "i_t1_text(font %p (%d), im %p, (xb,yb)=" i_DFp ", cl (%d,%d,%d,%d), points %g, str %p, len %u, align %d, utf8 %d, flags '%s', aa %d)\n",
-         font, fontnum, im, i_DFcp(xb, yb), cl->rgba.r, cl->rgba.g, cl->rgba.b, cl->rgba.a, points, str, (unsigned)len, align, utf8, flags, aa));
-
-  i_clear_error();
-
-  if (im == NULL) {
-    i_push_error(0, "null image");
-    mm_log((1,"i_t1_text: Null image in input\n"));
-    return(0);
-  }
-
-  i_mutex_lock(mutex);
-
-  i_t1_set_aa(aa);
+  if (im == NULL) { mm_log((1,"i_t1_cp: Null image in input\n")); return(0); }
 
   if (utf8) {
     int worklen;
@@ -472,13 +363,8 @@ i_t1_text(i_t1_font_t font, i_img *im, i_img_dim xb, i_img_dim yb,const i_color
     /* T1_AASetString() accepts a char * not a const char */
     glyph=T1_AASetString( fontnum, (char *)str, len, 0, mod_flags, points, NULL);
   }
-  if (glyph == NULL) {
-    mm_log((1, "T1_AASetString failed\n"));
-    t1_push_error();
-    i_push_error(0, "i_t1_text(): T1_AASetString failed");
-    i_mutex_unlock(mutex);
+  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));
@@ -497,8 +383,6 @@ i_t1_text(i_t1_font_t font, i_img *im, i_img_dim xb, i_img_dim yb,const i_color
     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;
 }
@@ -583,20 +467,16 @@ Returns the number of characters that were checked.
 */
 
 int
-i_t1_has_chars(i_t1_font_t font, const char *text, size_t len, int utf8,
+i_t1_has_chars(int font_num, 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;
   }
 
@@ -606,7 +486,6 @@ i_t1_has_chars(i_t1_font_t font, 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;
       }
     }
@@ -633,13 +512,11 @@ i_t1_has_chars(i_t1_font_t font, const char *text, size_t len, int utf8,
     ++count;
   }
 
-  i_mutex_unlock(mutex);
-
   return count;
 }
 
 /*
-=item i_t1_face_name(font, name_buf, name_buf_size)
+=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
@@ -653,68 +530,53 @@ will be truncated.  name_buf will always be NUL termintaed.
 */
 
 int
-i_t1_face_name(i_t1_font_t font, char *name_buf, size_t name_buf_size) {
+i_t1_face_name(int font_num, 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';
-    i_mutex_unlock(mutex);
-    return len + 1;
+    return strlen(name) + 1;
   }
   else {
     t1_push_error();
-    i_mutex_unlock(mutex);
     return 0;
   }
 }
 
 int
-i_t1_glyph_name(i_t1_font_t font, unsigned long ch, char *name_buf, 
+i_t1_glyph_name(int font_num, 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';
-      i_mutex_unlock(mutex);
-      return len + 1;
+      return strlen(name) + 1;
     }
     else {
-      i_mutex_unlock(mutex);
       return 0;
     }
   }
   else {
     t1_push_error();
-    i_mutex_unlock(mutex);
     return 0;
   }
 }
@@ -732,109 +594,103 @@ t1_push_error(void) {
 
 #ifdef T1ERR_SCAN_FONT_FORMAT
   case T1ERR_SCAN_FONT_FORMAT:
-    i_push_error(T1ERR_SCAN_FONT_FORMAT, "Attempt to Load Multiple Master Font"); 
+    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, "Type 1 Font File Open Error"); 
+    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, "Virtual Memory Exceeded"); 
+    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, "Syntactical Error Scanning Font File"); 
+    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, "Premature End of Font File Encountered"); 
+    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 Construction 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, "Font is Corrupt"); 
+    i_push_error(T1ERR_PARSE_ERROR, "PARSE_ERROR"); 
     break;
 #endif
 
 #ifdef T1ERR_TYPE1_ABORT
   case T1ERR_TYPE1_ABORT:
-    i_push_error(T1ERR_TYPE1_ABORT, "Rasterization Aborted"); 
+    i_push_error(T1ERR_TYPE1_ABORT, "TYPE1_ABORT"); 
     break;
 #endif
 
 #ifdef T1ERR_INVALID_FONTID
   case T1ERR_INVALID_FONTID:
-    i_push_error(T1ERR_INVALID_FONTID, "Font ID Invalid in this Context"); 
+    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 Argument in Function Call"); 
+    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, "Operation 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, "Memory Allocation Error"); 
+    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, "Error Opening File"); 
+    i_push_error(T1ERR_FILE_OPEN_ERR, "FILE_OPEN_ERR"); 
     break;
 #endif
 
 #ifdef T1ERR_UNSPECIFIED
   case T1ERR_UNSPECIFIED:
-    i_push_error(T1ERR_UNSPECIFIED, "Unspecified T1Lib Error"); 
+    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, "Missing 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 Interface Error"); 
+    i_push_error(T1ERR_X11, "X11"); 
     break;
 #endif
 
 #ifdef T1ERR_COMPOSITE_CHAR
   case T1ERR_COMPOSITE_CHAR:
-    i_push_error(T1ERR_COMPOSITE_CHAR, "Missing Component of Composite Character"); 
-    break;
-#endif
-
-#ifdef T1ERR_SCAN_ENCODING
-  case T1ERR_SCAN_ENCODING:
-    i_push_error(T1ERR_SCAN_ENCODING, "Error Scanning Encoding File"); 
+    i_push_error(T1ERR_COMPOSITE_CHAR, "COMPOSITE_CHAR"); 
     break;
 #endif
 
index 5783e05fa71a55518b0c1df70fcdd0a4bade164e..489bcef737eb1c5a2a1595d6cbbb5af12fa2d5c7 100644 (file)
--- a/T1/imt1.h
+++ b/T1/imt1.h
@@ -3,40 +3,38 @@
 
 #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 i_t1_font_t
+extern int
 i_t1_new(char *pfb,char *afm);
 
 extern int
-i_t1_destroy(i_t1_font_t font);
+i_t1_destroy(int font_id);
+
+extern void
+i_t1_set_aa(int st);
 
 extern undef_int
-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);
+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);
 
 extern int
-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);
+i_t1_bbox(int fontnum,double points,const char *str,size_t len,i_img_dim *cords, int utf8,char const *flags);
 
 extern undef_int
-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);
+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);
 
 extern int
-i_t1_has_chars(i_t1_font_t font, const char *text, size_t len, int utf8,
+i_t1_has_chars(int font_num, const char *text, size_t len, int utf8,
                char *out);
 
 extern int
-i_t1_face_name(i_t1_font_t font, char *name_buf, size_t name_buf_size);
+i_t1_face_name(int font_num, char *name_buf, size_t name_buf_size);
 
 extern int
-i_t1_glyph_name(i_t1_font_t font, unsigned long ch, char *name_buf, 
+i_t1_glyph_name(int font_num, unsigned long ch, char *name_buf, 
                size_t name_buf_size);
 #endif
index 5b4456fae844b1205e10d230211ee093fbd95f82..8e23561f9d2abe17da79e094ae27fbfe9a7544cd 100644 (file)
@@ -2,13 +2,13 @@
 use strict;
 use Test::More;
 use Imager ':all';
-use Imager::Test qw(diff_text_with_nul is_color3 is_image isnt_image);
+use Imager::Test qw(diff_text_with_nul is_color3);
 use Imager::Font::T1;
 use Cwd qw(getcwd abs_path);
 
 #$Imager::DEBUG=1;
 
-plan tests => 108;
+plan tests => 97;
 
 ok($Imager::formats{t1}, "must have t1");
 
@@ -40,7 +40,7 @@ SKIP:
   init(t1log=>0);
   unlink "t1lib.log";
 
-  my $fnum=Imager::Font::T1xs->new($fontname_pfb,$fontname_afm); # this will load the pfb font
+  my $fnum=Imager::Font::T1::i_t1_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($fnum->cp($overlay,5,50,1,50.0,'XMCLH',5,1), "i_t1_cp");
+  ok(Imager::Font::T1::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);
 
-  my @bbox=$fnum->bbox(50.0,'XMCLH',5);
+  my @bbox=Imager::Font::T1::i_t1_bbox(0,50.0,'XMCLH',5);
   is(@bbox, 8, "i_t1_bbox");
   print "# bbox: ($bbox[0], $bbox[1]) - ($bbox[2], $bbox[3])\n";
 
@@ -65,7 +65,8 @@ SKIP:
   $bgcolor=Imager::Color::set($bgcolor,200,200,200,0);
   my $backgr=Imager::ImgRaw::new(280,300,3);
 
-  ok($fnum->text($backgr,10,100,$bgcolor,150.0,'test',4,1,2), "i_t1_text");
+  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");
 
   # "UTF8" tests
   # for perl < 5.6 we can hand-encode text
@@ -76,9 +77,9 @@ SKIP:
   my $text = pack("C*", 0x41, 0xC2, 0xA1, 0xE2, 0x80, 0x90, 0x41);
   my $alttext = "A\xA1A";
   
-  my @utf8box = $fnum->bbox(50.0, $text, length($text), 1);
+  my @utf8box = Imager::Font::T1::i_t1_bbox($fnum, 50.0, $text, length($text), 1);
   is(@utf8box, 8, "utf8 bbox element count");
-  my @base = $fnum->bbox(50.0, $alttext, length($alttext), 0);
+  my @base = Imager::Font::T1::i_t1_bbox($fnum, 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";
@@ -86,9 +87,9 @@ SKIP:
       "compare box sizes $utf8box[2] vs $base[2] (maxerror $maxdiff)");
 
   # hand-encoded UTF8 drawing
-  ok($fnum->text($backgr, 10, 140, $bgcolor, 32, $text, length($text), 1,1), "draw hand-encoded UTF8");
+  ok(Imager::Font::T1::i_t1_text($backgr, 10, 140, $bgcolor, $fnum, 32, $text, length($text), 1,1), "draw hand-encoded UTF8");
 
-  ok($fnum->cp($backgr, 80, 140, 1, 32, $text, length($text), 1, 1), 
+  ok(Imager::Font::T1::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
@@ -100,16 +101,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($fnum->text($backgr, 10, 180, $bgcolor, 32, $text, length($text), 1),
+    ok(Imager::Font::T1::i_t1_text($backgr, 10, 180, $bgcolor, $fnum, 32, $text, length($text), 1),
         "draw UTF8");
-    ok($fnum->cp($backgr, 80, 180, 1, 32, $text, length($text), 1),
+    ok(Imager::Font::T1::i_t1_cp($backgr, 80, 180, 1, $fnum, 32, $text, length($text), 1),
         "cp UTF8");
-    @utf8box = $fnum->bbox(50.0, $text, length($text), 0);
+    @utf8box = Imager::Font::T1::i_t1_bbox($fnum, 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($fnum->text($backgr, 10, 220, $bgcolor, 32, $text, 0, 1, 0, "uso"),
+    ok(Imager::Font::T1::i_t1_text($backgr, 10, 220, $bgcolor, $fnum, 32, $text, 0, 1, 0, "uso"),
        "more complex output");
   }
 
@@ -119,7 +120,13 @@ SKIP:
   i_writeppm_wiol($backgr, $IO);
   close(FH);
 
-  undef $fnum;
+  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";
 
   # character existance tests - uses the special ExistenceTest font
   my $exists_font = 'fontfiles/ExistenceTest.pfb';
@@ -127,22 +134,22 @@ SKIP:
   
   -e $exists_font or die "$exists_font not found";
     
-  my $font_num = Imager::Font::T1xs->new($exists_font, $exists_afm);
+  my $font_num = Imager::Font::T1::i_t1_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 = $font_num->has_chars("!A");
+    my @exists = Imager::Font::T1::i_t1_has_chars($font_num, "!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 = $font_num->has_chars("!A");
+    my $exists = Imager::Font::T1::i_t1_has_chars($font_num, "!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");
-    undef $font_num;
+    Imager::Font::T1::i_t1_destroy($font_num);
   }
   
   my $font = Imager::Font->new(file=>$exists_font, type=>'t1');
@@ -167,7 +174,7 @@ SKIP:
     isnt($bbox[2], $bbox[5], "different advance to pos_width");
 
     # names
-    my $face_name = $font->{t1font}->face_name();
+    my $face_name = Imager::Font::T1::i_t1_face_name($font->{id});
     print "# face $face_name\n";
     is($face_name, 'ExistenceTest', "face name");
     $face_name = $font->face_name;
@@ -360,40 +367,6 @@ SKIP:
     ok($font, "found font by drive relative path")
       or print "# path $drive_path\n";
   }
-
-  {
-    Imager->log("Testing aa levels", 1);
-    my $f1 = Imager::Font->new(file => $deffont, type => "t1");
-    is($f1->{t1aa}, 2, "should have default aa level");
-    my $imbase = Imager->new(xsize => 100, ysize => 20);
-    ok($imbase->string(text => "test", size => 18, x => 5, y => 18,
-                      color => "#FFF", font => $f1, aa => 1),
-       "draw text with def aa level");
-    ok(Imager::Font::T1->set_aa_level(1), "set aa level to 1");
-    my $f2 = Imager::Font->new(file => $deffont, type => "t1");
-    is($f2->{t1aa}, 1, "new font has new aa level");
-    my $imaa1 = Imager->new(xsize => 100, ysize => 20);
-    ok($imaa1->string(text => "test", size => 18, x => 5, y => 18,
-                      color => "#FFF", font => $f2, aa => 1),
-       "draw text with non-def aa level");
-    isnt_image($imbase, $imaa1, "images should differ");
-    ok($f2->set_aa_level(2), "set aa level of font");
-    is($f2->{t1aa}, 2, "check new aa level");
-    my $imaa2 = Imager->new(xsize => 100, ysize => 20);
-    ok($imaa2->string(text => "test", size => 18, x => 5, y => 18,
-                      color => "#FFF", font => $f2, aa => 1),
-       "draw text with non-def but 2 aa level");
-    is_image($imbase, $imaa2, "check images match");
-  }
-
-  { # error handling check
-    my $im = Imager->new(xsize => 100, ysize => 20);
-    my $fnum = Imager::Font->new(file => $deffont, type => "t1");
-    ok(!$im->string(font => $fnum, string => "text", size => -10),
-       "set invalid size");
-    is($im->errstr, "i_t1_text(): T1_AASetString failed: Invalid Argument in Function Call",
-       "check error message");
-  }
 }
 
 #malloc_state();
diff --git a/T1/typemap b/T1/typemap
deleted file mode 100644 (file)
index 95e197e..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Imager::Font::T1xs     T_PTROBJ
index 2c3c19d8fd66863e3292f81cea39087d0c9d885c..37a8707436e8fc25f6b41908da8a414cb1053cd7 100644 (file)
@@ -1,9 +1,3 @@
-Imager-File-TIFF 0.85
-=====================
-
- - for libtiff versions that support extended warning handlers (3.8.0
-   or later), use them to avoid some global variables.
-
 Imager-File-TIFF 0.83
 =====================
 
index 4c95a922a458e74d336596029549943bcb276e4f..55e3ca9b589b9b63917ff60201cff017b8b730be 100644 (file)
@@ -4,7 +4,7 @@ use Imager;
 use vars qw($VERSION @ISA);
 
 BEGIN {
-  $VERSION = "0.84";
+  $VERSION = "0.83";
 
   require XSLoader;
   XSLoader::load('Imager::File::TIFF', $VERSION);
index c57486cef16a1a11676241cd4e83d1626869a7ba..3765d4f6d1579fa656be698a8ac274741ded3943 100644 (file)
@@ -143,4 +143,3 @@ i_tiff_has_compression(name)
 
 BOOT:
        PERL_INITIALIZE_IMAGER_CALLBACKS;
-       i_tiff_init();
\ No newline at end of file
index d94f686793a95683b18480a9ebe9fd2dde42a677..832f38d41e1ef88b58fcc277134fd1c99d2c3683 100644 (file)
@@ -171,69 +171,12 @@ fallback_rgb_channels(TIFF *tif, i_img_dim width, i_img_dim height, int *channel
 static const int text_tag_count = 
   sizeof(text_tag_names) / sizeof(*text_tag_names);
 
-#if TIFFLIB_VERSION >= 20051230
-#define USE_EXT_WARN_HANDLER
-#endif
-
-#define TIFFIO_MAGIC 0xC6A340CC
-
 static void error_handler(char const *module, char const *fmt, va_list ap) {
   mm_log((1, "tiff error fmt %s\n", fmt));
   i_push_errorvf(0, fmt, ap);
 }
 
-typedef struct {
-  unsigned magic;
-  io_glue *ig;
-#ifdef USE_EXT_WARN_HANDLER
-  char *warn_buffer;
-  size_t warn_size;
-#endif
-} tiffio_context_t;
-
-static void
-tiffio_context_init(tiffio_context_t *c, io_glue *ig);
-static void
-tiffio_context_final(tiffio_context_t *c);
-
 #define WARN_BUFFER_LIMIT 10000
-
-#ifdef USE_EXT_WARN_HANDLER
-
-static void
-warn_handler_ex(thandle_t h, const char *module, const char *fmt, va_list ap) {
-  tiffio_context_t *c = (tiffio_context_t *)h;
-  char buf[200];
-
-  if (c->magic != TIFFIO_MAGIC)
-    return;
-
-  buf[0] = '\0';
-#ifdef IMAGER_VSNPRINTF
-  vsnprintf(buf, sizeof(buf), fmt, ap);
-#else
-  vsprintf(buf, fmt, ap);
-#endif
-  mm_log((1, "tiff warning %s\n", buf));
-
-  if (!c->warn_buffer || strlen(c->warn_buffer)+strlen(buf)+2 > c->warn_size) {
-    size_t new_size = c->warn_size + strlen(buf) + 2;
-    char *old_buffer = c->warn_buffer;
-    if (new_size > WARN_BUFFER_LIMIT) {
-      new_size = WARN_BUFFER_LIMIT;
-    }
-    c->warn_buffer = myrealloc(c->warn_buffer, new_size);
-    if (!old_buffer) c->warn_buffer[0] = '\0';
-    c->warn_size = new_size;
-  }
-  if (strlen(c->warn_buffer)+strlen(buf)+2 <= c->warn_size) {
-    strcat(c->warn_buffer, buf);
-    strcat(c->warn_buffer, "\n");
-  }
-}
-
-#else
-
 static char *warn_buffer = NULL;
 static int warn_buffer_size = 0;
 
@@ -264,15 +207,6 @@ static void warn_handler(char const *module, char const *fmt, va_list ap) {
   }
 }
 
-#endif
-
-static i_mutex_t mutex;
-
-void
-i_tiff_init(void) {
-  mutex = i_mutex_new();
-}
-
 static int save_tiff_tags(TIFF *tif, i_img *im);
 
 static void 
@@ -299,7 +233,7 @@ Compatability for 64 bit systems like latest freebsd (internal)
 static
 toff_t
 comp_seek(thandle_t h, toff_t o, int w) {
-  io_glue *ig = ((tiffio_context_t *)h)->ig;
+  io_glue *ig = (io_glue*)h;
   return (toff_t) i_io_seek(ig, o, w);
 }
 
@@ -336,17 +270,17 @@ comp_munmap(thandle_t h, tdata_t p, toff_t off) {
 
 static tsize_t
 comp_read(thandle_t h, tdata_t p, tsize_t size) {
-  return i_io_read(((tiffio_context_t *)h)->ig, p, size);
+  return i_io_read((io_glue *)h, p, size);
 }
 
 static tsize_t
 comp_write(thandle_t h, tdata_t p, tsize_t size) {
-  return i_io_write(((tiffio_context_t *)h)->ig, p, size);
+  return i_io_write((io_glue *)h, p, size);
 }
 
 static int
 comp_close(thandle_t h) {
-  return i_io_close(((tiffio_context_t *)h)->ig);
+  return i_io_close((io_glue *)h);
 }
 
 static i_img *read_one_tiff(TIFF *tif, int allow_incomplete) {
@@ -586,20 +520,10 @@ static i_img *read_one_tiff(TIFF *tif, int allow_incomplete) {
   }
 
   i_tags_set(&im->tags, "i_format", "tiff", 4);
-#ifdef USE_EXT_WARN_HANDLER
-  {
-    tiffio_context_t *ctx = TIFFClientdata(tif);
-    if (ctx->warn_buffer && ctx->warn_buffer[0]) {
-      i_tags_set(&im->tags, "i_warning", ctx->warn_buffer, -1);
-      ctx->warn_buffer[0] = '\0';
-    }
-  }
-#else
   if (warn_buffer && *warn_buffer) {
     i_tags_set(&im->tags, "i_warning", warn_buffer, -1);
     *warn_buffer = '\0';
   }
-#endif
 
   for (i = 0; i < compress_value_count; ++i) {
     if (compress_values[i].tag == compress) {
@@ -621,35 +545,23 @@ i_readtiff_wiol(io_glue *ig, int allow_incomplete, int page) {
   TIFF* tif;
   TIFFErrorHandler old_handler;
   TIFFErrorHandler old_warn_handler;
-#ifdef USE_EXT_WARN_HANDLER
-  TIFFErrorHandlerExt old_ext_warn_handler;
-#endif
   i_img *im;
   int current_page;
-  tiffio_context_t ctx;
-
-  i_mutex_lock(mutex);
 
   i_clear_error();
   old_handler = TIFFSetErrorHandler(error_handler);
-#ifdef USE_EXT_WARN_HANDLER
-  old_warn_handler = TIFFSetWarningHandler(NULL);
-  old_ext_warn_handler = TIFFSetWarningHandlerExt(warn_handler_ex);
-#else
   old_warn_handler = TIFFSetWarningHandler(warn_handler);
   if (warn_buffer)
     *warn_buffer = '\0';
-#endif
 
   /* Add code to get the filename info from the iolayer */
   /* Also add code to check for mmapped code */
 
   mm_log((1, "i_readtiff_wiol(ig %p, allow_incomplete %d, page %d)\n", ig, allow_incomplete, page));
   
-  tiffio_context_init(&ctx, ig);
   tif = TIFFClientOpen("(Iolayer)", 
                       "rm", 
-                      (thandle_t) &ctx,
+                      (thandle_t) ig,
                       comp_read,
                       comp_write,
                       comp_seek,
@@ -663,11 +575,6 @@ i_readtiff_wiol(io_glue *ig, int allow_incomplete, int page) {
     i_push_error(0, "Error opening file");
     TIFFSetErrorHandler(old_handler);
     TIFFSetWarningHandler(old_warn_handler);
-#ifdef USE_EXT_WARN_HANDLER
-    TIFFSetWarningHandlerExt(old_ext_warn_handler);
-#endif
-    tiffio_context_final(&ctx);
-    i_mutex_unlock(mutex);
     return NULL;
   }
 
@@ -677,12 +584,7 @@ i_readtiff_wiol(io_glue *ig, int allow_incomplete, int page) {
       i_push_errorf(0, "could not switch to page %d", page);
       TIFFSetErrorHandler(old_handler);
       TIFFSetWarningHandler(old_warn_handler);
-#ifdef USE_EXT_WARN_HANDLER
-    TIFFSetWarningHandlerExt(old_ext_warn_handler);
-#endif
       TIFFClose(tif);
-      tiffio_context_final(&ctx);
-      i_mutex_unlock(mutex);
       return NULL;
     }
   }
@@ -692,13 +594,7 @@ i_readtiff_wiol(io_glue *ig, int allow_incomplete, int page) {
   if (TIFFLastDirectory(tif)) mm_log((1, "Last directory of tiff file\n"));
   TIFFSetErrorHandler(old_handler);
   TIFFSetWarningHandler(old_warn_handler);
-#ifdef USE_EXT_WARN_HANDLER
-    TIFFSetWarningHandlerExt(old_ext_warn_handler);
-#endif
   TIFFClose(tif);
-  tiffio_context_final(&ctx);
-    i_mutex_unlock(mutex);
-
   return im;
 }
 
@@ -714,27 +610,14 @@ i_readtiff_multi_wiol(io_glue *ig, int *count) {
   TIFF* tif;
   TIFFErrorHandler old_handler;
   TIFFErrorHandler old_warn_handler;
-#ifdef USE_EXT_WARN_HANDLER
-  TIFFErrorHandlerExt old_ext_warn_handler;
-#endif
   i_img **results = NULL;
   int result_alloc = 0;
-  tiffio_context_t ctx;
-
-  i_mutex_lock(mutex);
 
   i_clear_error();
   old_handler = TIFFSetErrorHandler(error_handler);
-#ifdef USE_EXT_WARN_HANDLER
-  old_warn_handler = TIFFSetWarningHandler(NULL);
-  old_ext_warn_handler = TIFFSetWarningHandlerExt(warn_handler_ex);
-#else
   old_warn_handler = TIFFSetWarningHandler(warn_handler);
   if (warn_buffer)
     *warn_buffer = '\0';
-#endif
-
-  tiffio_context_init(&ctx, ig);
 
   /* Add code to get the filename info from the iolayer */
   /* Also add code to check for mmapped code */
@@ -743,7 +626,7 @@ i_readtiff_multi_wiol(io_glue *ig, int *count) {
   
   tif = TIFFClientOpen("(Iolayer)", 
                       "rm", 
-                      (thandle_t) &ctx,
+                      (thandle_t) ig,
                       comp_read,
                       comp_write,
                       comp_seek,
@@ -757,11 +640,6 @@ i_readtiff_multi_wiol(io_glue *ig, int *count) {
     i_push_error(0, "Error opening file");
     TIFFSetErrorHandler(old_handler);
     TIFFSetWarningHandler(old_warn_handler);
-#ifdef USE_EXT_WARN_HANDLER
-    TIFFSetWarningHandlerExt(old_ext_warn_handler);
-#endif
-    tiffio_context_final(&ctx);
-    i_mutex_unlock(mutex);
     return NULL;
   }
 
@@ -791,13 +669,7 @@ i_readtiff_multi_wiol(io_glue *ig, int *count) {
 
   TIFFSetWarningHandler(old_warn_handler);
   TIFFSetErrorHandler(old_handler);
-#ifdef USE_EXT_WARN_HANDLER
-    TIFFSetWarningHandlerExt(old_ext_warn_handler);
-#endif
   TIFFClose(tif);
-  tiffio_context_final(&ctx);
-  i_mutex_unlock(mutex);
-
   return results;
 }
 
@@ -1460,9 +1332,6 @@ i_writetiff_multi_wiol(io_glue *ig, i_img **imgs, int count) {
   TIFF* tif;
   TIFFErrorHandler old_handler;
   int i;
-  tiffio_context_t ctx;
-
-  i_mutex_lock(mutex);
 
   old_handler = TIFFSetErrorHandler(error_handler);
 
@@ -1470,11 +1339,11 @@ i_writetiff_multi_wiol(io_glue *ig, i_img **imgs, int count) {
   mm_log((1, "i_writetiff_multi_wiol(ig %p, imgs %p, count %d)\n", 
           ig, imgs, count));
 
-  tiffio_context_init(&ctx, ig);
+  /* FIXME: Enable the mmap interface */
   
   tif = TIFFClientOpen("No name", 
                       "wm",
-                      (thandle_t) &ctx
+                      (thandle_t) ig
                       comp_read,
                       comp_write,
                       comp_seek,
@@ -1489,8 +1358,6 @@ i_writetiff_multi_wiol(io_glue *ig, i_img **imgs, int count) {
     mm_log((1, "i_writetiff_multi_wiol: Unable to open tif file for writing\n"));
     i_push_error(0, "Could not create TIFF object");
     TIFFSetErrorHandler(old_handler);
-    tiffio_context_final(&ctx);
-    i_mutex_unlock(mutex);
     return 0;
   }
 
@@ -1498,8 +1365,6 @@ i_writetiff_multi_wiol(io_glue *ig, i_img **imgs, int count) {
     if (!i_writetiff_low(tif, imgs[i])) {
       TIFFClose(tif);
       TIFFSetErrorHandler(old_handler);
-      tiffio_context_final(&ctx);
-      i_mutex_unlock(mutex);
       return 0;
     }
 
@@ -1507,17 +1372,12 @@ i_writetiff_multi_wiol(io_glue *ig, i_img **imgs, int count) {
       i_push_error(0, "Cannot write TIFF directory");
       TIFFClose(tif);
       TIFFSetErrorHandler(old_handler);
-      tiffio_context_final(&ctx);
-      i_mutex_unlock(mutex);
       return 0;
     }
   }
 
   TIFFSetErrorHandler(old_handler);
   (void) TIFFClose(tif);
-  tiffio_context_final(&ctx);
-
-  i_mutex_unlock(mutex);
 
   if (i_io_close(ig))
     return 0;
@@ -1543,9 +1403,6 @@ i_writetiff_multi_wiol_faxable(io_glue *ig, i_img **imgs, int count, int fine) {
   TIFF* tif;
   int i;
   TIFFErrorHandler old_handler;
-  tiffio_context_t ctx;
-
-  i_mutex_lock(mutex);
 
   old_handler = TIFFSetErrorHandler(error_handler);
 
@@ -1553,11 +1410,11 @@ i_writetiff_multi_wiol_faxable(io_glue *ig, i_img **imgs, int count, int fine) {
   mm_log((1, "i_writetiff_multi_wiol(ig %p, imgs %p, count %d)\n", 
           ig, imgs, count));
 
-  tiffio_context_init(&ctx, ig);
+  /* FIXME: Enable the mmap interface */
   
   tif = TIFFClientOpen("No name", 
                       "wm",
-                      (thandle_t) &ctx
+                      (thandle_t) ig
                       comp_read,
                       comp_write,
                       comp_seek,
@@ -1572,8 +1429,6 @@ i_writetiff_multi_wiol_faxable(io_glue *ig, i_img **imgs, int count, int fine) {
     mm_log((1, "i_writetiff_mulit_wiol: Unable to open tif file for writing\n"));
     i_push_error(0, "Could not create TIFF object");
     TIFFSetErrorHandler(old_handler);
-    tiffio_context_final(&ctx);
-    i_mutex_unlock(mutex);
     return 0;
   }
 
@@ -1581,8 +1436,6 @@ i_writetiff_multi_wiol_faxable(io_glue *ig, i_img **imgs, int count, int fine) {
     if (!i_writetiff_low_faxable(tif, imgs[i], fine)) {
       TIFFClose(tif);
       TIFFSetErrorHandler(old_handler);
-      tiffio_context_final(&ctx);
-      i_mutex_unlock(mutex);
       return 0;
     }
 
@@ -1590,17 +1443,12 @@ i_writetiff_multi_wiol_faxable(io_glue *ig, i_img **imgs, int count, int fine) {
       i_push_error(0, "Cannot write TIFF directory");
       TIFFClose(tif);
       TIFFSetErrorHandler(old_handler);
-      tiffio_context_final(&ctx);
-      i_mutex_unlock(mutex);
       return 0;
     }
   }
 
   (void) TIFFClose(tif);
   TIFFSetErrorHandler(old_handler);
-  tiffio_context_final(&ctx);
-
-  i_mutex_unlock(mutex);
 
   if (i_io_close(ig))
     return 0;
@@ -1622,20 +1470,17 @@ undef_int
 i_writetiff_wiol(i_img *img, io_glue *ig) {
   TIFF* tif;
   TIFFErrorHandler old_handler;
-  tiffio_context_t ctx;
-
-  i_mutex_lock(mutex);
 
   old_handler = TIFFSetErrorHandler(error_handler);
 
   i_clear_error();
   mm_log((1, "i_writetiff_wiol(img %p, ig %p)\n", img, ig));
 
-  tiffio_context_init(&ctx, ig);
+  /* FIXME: Enable the mmap interface */
 
   tif = TIFFClientOpen("No name", 
                       "wm",
-                      (thandle_t) &ctx
+                      (thandle_t) ig
                       comp_read,
                       comp_write,
                       comp_seek,
@@ -1649,24 +1494,18 @@ i_writetiff_wiol(i_img *img, io_glue *ig) {
   if (!tif) {
     mm_log((1, "i_writetiff_wiol: Unable to open tif file for writing\n"));
     i_push_error(0, "Could not create TIFF object");
-    tiffio_context_final(&ctx);
     TIFFSetErrorHandler(old_handler);
-    i_mutex_unlock(mutex);
     return 0;
   }
 
   if (!i_writetiff_low(tif, img)) {
     TIFFClose(tif);
-    tiffio_context_final(&ctx);
     TIFFSetErrorHandler(old_handler);
-    i_mutex_unlock(mutex);
     return 0;
   }
 
   (void) TIFFClose(tif);
   TIFFSetErrorHandler(old_handler);
-  tiffio_context_final(&ctx);
-  i_mutex_unlock(mutex);
 
   if (i_io_close(ig))
     return 0;
@@ -1695,20 +1534,17 @@ undef_int
 i_writetiff_wiol_faxable(i_img *im, io_glue *ig, int fine) {
   TIFF* tif;
   TIFFErrorHandler old_handler;
-  tiffio_context_t ctx;
-
-  i_mutex_lock(mutex);
 
   old_handler = TIFFSetErrorHandler(error_handler);
 
   i_clear_error();
   mm_log((1, "i_writetiff_wiol(img %p, ig %p)\n", im, ig));
 
-  tiffio_context_init(&ctx, ig);
+  /* FIXME: Enable the mmap interface */
   
   tif = TIFFClientOpen("No name", 
                       "wm",
-                      (thandle_t) &ctx
+                      (thandle_t) ig
                       comp_read,
                       comp_write,
                       comp_seek,
@@ -1723,23 +1559,17 @@ i_writetiff_wiol_faxable(i_img *im, io_glue *ig, int fine) {
     mm_log((1, "i_writetiff_wiol: Unable to open tif file for writing\n"));
     i_push_error(0, "Could not create TIFF object");
     TIFFSetErrorHandler(old_handler);
-    tiffio_context_final(&ctx);
-    i_mutex_unlock(mutex);
     return 0;
   }
 
   if (!i_writetiff_low_faxable(tif, im, fine)) {
     TIFFClose(tif);
     TIFFSetErrorHandler(old_handler);
-    tiffio_context_final(&ctx);
-    i_mutex_unlock(mutex);
     return 0;
   }
 
   (void) TIFFClose(tif);
   TIFFSetErrorHandler(old_handler);
-  tiffio_context_final(&ctx);
-  i_mutex_unlock(mutex);
 
   if (i_io_close(ig))
     return 0;
@@ -1760,7 +1590,7 @@ static int save_tiff_tags(TIFF *tif, i_img *im) {
       }
     }
   }
-
   return 1;
 }
 
@@ -2811,25 +2641,6 @@ myTIFFIsCODECConfigured(uint16 scheme) {
   return TIFFIsCODECConfigured(scheme);
 }
 
-static void
-tiffio_context_init(tiffio_context_t *c, io_glue *ig) {
-  c->magic = TIFFIO_MAGIC;
-  c->ig = ig;
-#ifdef USE_EXT_WARN_HANDLER
-  c->warn_buffer = NULL;
-  c->warn_size = 0;
-#endif
-}
-
-static void
-tiffio_context_final(tiffio_context_t *c) {
-  c->magic = TIFFIO_MAGIC;
-#ifdef USE_EXT_WARN_HANDLER
-  if (c->warn_buffer)
-    myfree(c->warn_buffer);
-#endif
-}
-
 /*
 =back
 
index 2e7cfe4635317d73d61839bebd120f81ed6e465b..84222b6e42a3f0fc7af5f4d30a625b2005a6f98b 100644 (file)
@@ -3,7 +3,6 @@
 
 #include "imdatatypes.h"
 
-void i_tiff_init(void);
 i_img   * i_readtiff_wiol(io_glue *ig, int allow_incomplete, int page);
 i_img  ** i_readtiff_multi_wiol(io_glue *ig, int *count);
 undef_int i_writetiff_wiol(i_img *im, io_glue *ig);
index b96c72775dc7e3a45c299e7b62d93da67455a2b1..d08cf1f26306d2c90d4d23b64aaca4021f7153d6 100644 (file)
@@ -178,7 +178,7 @@ Tony Cook <tonyc@cpan.org>
 
 =head1 SEE ALSO
 
-Imager, Imager::API, Imager::ExtUtils, Imager::Inline
+Imager, Imager::ExtUtils, Imager::Inline
 
 =cut
 EOS
@@ -187,13 +187,13 @@ close OUT;
 
 
 sub make_func_list {
-  my @funcs = qw(i_img i_color i_fcolor i_fill_t mm_log mm_log i_img_color_channels i_img_has_alpha i_img_dim i_DF i_DFc i_DFp i_DFcp i_psamp_bits i_gsamp_bits i_psamp i_psampf);
+  my @funcs = qw(i_img i_color i_fcolor i_fill_t mm_log i_img_color_channels i_img_has_alpha i_img_dim i_DF i_DFc i_DFp i_DFcp i_psamp_bits i_gsamp_bits i_psamp i_psampf);
   open FUNCS, "< imexttypes.h"
     or die "Cannot open imexttypes.h: $!\n";
   my $in_struct;
   while (<FUNCS>) {
     /^typedef struct/ && ++$in_struct;
-    if ($in_struct && /\(\*f_(i[om]?_\w+)/) {
+    if ($in_struct && /\(\*f_(io?_\w+)/) {
       my $name = $1;
       $name =~ s/_imp$//;
       push @funcs, $name;
diff --git a/bench/largish.png b/bench/largish.png
deleted file mode 100755 (executable)
index aec5878..0000000
Binary files a/bench/largish.png and /dev/null differ
diff --git a/bench/largish.tif b/bench/largish.tif
deleted file mode 100755 (executable)
index b5128e9..0000000
Binary files a/bench/largish.tif and /dev/null differ
diff --git a/bench/tifthread.pl b/bench/tifthread.pl
deleted file mode 100644 (file)
index 7190106..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-#!perl -w
-use strict;
-use threads;
-use Imager;
-
-++$|;
-Imager->preload;
-
-my @tests =
-  (
-   [ "bench/largish.tif", "" ],
-   [ "TIFF/testimg/grey16.tif", "" ],
-   [ "TIFF/testimg/comp4bad.tif", "(Iolayer): Read error at scanline 120; got 0 bytes, expected 32" ],
-  );
-
-my @threads;
-my $name = "A";
-for my $test (@tests) {
-  push @threads,
-    threads->create
-      (
-       sub  {
-        my ($file, $result, $name) = @_;
-        for (1 .. 100000) {
-          print $name;
-          my $im = Imager->new(file => $file);
-          if ($result) {
-            $im and die "Expected error from $file, got image";
-            Imager->errstr eq $result
-              or die "Expected error '$result', got '",Imager->errstr, "'"
-          }
-          else {
-            $im or die "Expected image got error '", Imager->errstr, "'";
-          }
-        }
-        return;
-       },
-       @$test,
-       $name
-      );
-  ++$name;
-}
-
-for my $t (@threads) {
-  $t->join();
-}
diff --git a/bmp.c b/bmp.c
index 0e8fe8e75c2ee9674106979f611612fcb5a3ca59..4f770b8080328e6a3dc111d84b84126e3a98f350 100644 (file)
--- a/bmp.c
+++ b/bmp.c
@@ -1,4 +1,3 @@
-#define IMAGER_NO_CONTEXT
 #include <stdarg.h>
 #include "imageri.h"
 
@@ -77,7 +76,6 @@ Never compresses the image.
 */
 int
 i_writebmp_wiol(i_img *im, io_glue *ig) {
-  dIMCTXim(im);
   i_clear_error();
 
   /* pick a format */
@@ -118,9 +116,8 @@ i_readbmp_wiol(io_glue *ig, int allow_incomplete) {
   i_packed_t xsize, ysize, planes, bit_count, compression, size_image, xres, yres;
   i_packed_t clr_used, clr_important, offbits;
   i_img *im;
-  dIMCTXio(ig);
 
-  im_log((aIMCTX, 1, "i_readbmp_wiol(ig %p)\n", ig));
+  mm_log((1, "i_readbmp_wiol(ig %p)\n", ig));
   
   i_clear_error();
 
@@ -138,7 +135,7 @@ i_readbmp_wiol(io_glue *ig, int allow_incomplete) {
     return 0;
   }
 
-  im_log((aIMCTX, 1, " bmp header: filesize %d offbits %d xsize %d ysize %d planes %d "
+  mm_log((1, " bmp header: filesize %d offbits %d xsize %d ysize %d planes %d "
           "bit_count %d compression %d size %d xres %d yres %d clr_used %d "
           "clr_important %d\n", (int)filesize, (int)offbits, (int)xsize,
          (int)ysize, (int)planes, (int)bit_count, (int)compression, 
@@ -146,7 +143,7 @@ i_readbmp_wiol(io_glue *ig, int allow_incomplete) {
           (int)clr_important));
 
   if (!i_int_check_image_file_limits(xsize, abs(ysize), 3, sizeof(i_sample_t))) {
-    im_log((aIMCTX, 1, "i_readbmp_wiol: image size exceeds limits\n"));
+    mm_log((1, "i_readbmp_wiol: image size exceeds limits\n"));
     return NULL;
   }
   
@@ -174,7 +171,7 @@ i_readbmp_wiol(io_glue *ig, int allow_incomplete) {
     break;
 
   default:
-    im_push_errorf(aIMCTX, 0, "unknown bit count for BMP file (%d)", (int)bit_count);
+    i_push_errorf(0, "unknown bit count for BMP file (%d)", (int)bit_count);
     return NULL;
   }
 
@@ -276,10 +273,7 @@ read_packed(io_glue *ig, char *format, ...) {
       break;
       
     default:
-      {
-       dIMCTXio(ig);
-       im_fatal(aIMCTX, 1, "Unknown read_packed format code 0x%02x", code);
-      }
+      i_fatal(1, "Unknown read_packed format code 0x%02x", code);
     }
   }
   return 1;
@@ -331,10 +325,7 @@ write_packed(io_glue *ig, char *format, ...) {
       break;
 
     default:
-      {
-       dIMCTXio(ig);
-       im_fatal(aIMCTX, 1, "Unknown write_packed format code 0x%02x", *format);
-      }
+      i_fatal(1, "Unknown write_packed format code 0x%02x", *format);
     }
     ++format;
   }
@@ -359,7 +350,6 @@ int write_bmphead(io_glue *ig, i_img *im, int bit_count, int data_size) {
   int got_xres, got_yres, aspect_only;
   int colors_used = 0;
   int offset = FILEHEAD_SIZE + INFOHEAD_SIZE;
-  dIMCTXim(im);
 
   if (im->xsize > SIGNMAX32 || im->ysize > SIGNMAX32) {
     i_push_error(0, "image too large to write to BMP");
@@ -461,7 +451,6 @@ write_1bit_data(io_glue *ig, i_img *im) {
   int line_size = (im->xsize+7) / 8;
   int x, y;
   int unpacked_size;
-  dIMCTXim(im);
 
   /* round up to nearest multiple of four */
   line_size = (line_size + 3) / 4 * 4;
@@ -533,7 +522,6 @@ write_4bit_data(io_glue *ig, i_img *im) {
   int line_size = (im->xsize+1) / 2;
   int x, y;
   int unpacked_size;
-  dIMCTXim(im);
 
   /* round up to nearest multiple of four */
   line_size = (line_size + 3) / 4 * 4;
@@ -592,7 +580,6 @@ write_8bit_data(io_glue *ig, i_img *im) {
   int line_size = im->xsize;
   int y;
   int unpacked_size;
-  dIMCTXim(im);
 
   /* round up to nearest multiple of four */
   line_size = (line_size + 3) / 4 * 4;
@@ -640,7 +627,6 @@ write_24bit_data(io_glue *ig, i_img *im) {
   int y;
   int line_size = 3 * im->xsize;
   i_color bg;
-  dIMCTXim(im);
 
   i_get_file_background(im, &bg);
 
@@ -695,7 +681,6 @@ read_bmp_pal(io_glue *ig, i_img *im, int count) {
   int i;
   i_packed_t r, g, b, x;
   i_color c;
-  dIMCTXio(ig);
   
   for (i = 0; i < count; ++i) {
     if (!read_packed(ig, "CCCC", &b, &g, &r, &x)) {
@@ -734,10 +719,9 @@ read_1bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
   int bit;
   unsigned char *in;
   long base_offset;
-  dIMCTXio(ig);
 
   if (compression != BI_RGB) {
-    im_push_errorf(aIMCTX, 0, "unknown 1-bit BMP compression (%d)", compression);
+    i_push_errorf(0, "unknown 1-bit BMP compression (%d)", compression);
     return NULL;
   }
 
@@ -768,13 +752,13 @@ read_1bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
   if (!clr_used)
     clr_used = 2;
   if (clr_used < 0 || clr_used > 2) {
-    im_push_errorf(aIMCTX, 0, "out of range colors used (%d)", clr_used);
+    i_push_errorf(0, "out of range colors used (%d)", clr_used);
     return NULL;
   }
 
   base_offset = FILEHEAD_SIZE + INFOHEAD_SIZE + clr_used * 4;
   if (offbits < base_offset) {
-    im_push_errorf(aIMCTX, 0, "image data offset too small (%ld)", offbits);
+    i_push_errorf(0, "image data offset too small (%ld)", offbits);
     return NULL;
   }
 
@@ -863,7 +847,6 @@ read_4bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
   int size, i;
   long base_offset;
   int starty;
-  dIMCTXio(ig);
 
   /* line_size is going to be smaller than xsize in most cases (and
      when it's not, xsize is itself small), and hence not overflow */
@@ -886,13 +869,13 @@ read_4bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
     clr_used = 16;
 
   if (clr_used > 16 || clr_used < 0) {
-    im_push_errorf(aIMCTX, 0, "out of range colors used (%d)", clr_used);
+    i_push_errorf(0, "out of range colors used (%d)", clr_used);
     return NULL;
   }
 
   base_offset = FILEHEAD_SIZE + INFOHEAD_SIZE + clr_used * 4;
   if (offbits < base_offset) {
-    im_push_errorf(aIMCTX, 0, "image data offset too small (%ld)", offbits);
+    i_push_errorf(0, "image data offset too small (%ld)", offbits);
     return NULL;
   }
 
@@ -984,7 +967,7 @@ read_4bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
          myfree(packed);
          myfree(line);
          i_push_error(0, "invalid data during decompression");
-         im_log((aIMCTX, 1, "read 4-bit: scanline overflow x %d + count %d vs xlimit %d (y %d)\n",
+         mm_log((1, "read 4-bit: scanline overflow x %d + count %d vs xlimit %d (y %d)\n",
                  (int)x, count, (int)xlimit, (int)y));
          i_img_destroy(im);
          return NULL;
@@ -1034,7 +1017,7 @@ read_4bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
            myfree(packed);
            myfree(line);
            i_push_error(0, "invalid data during decompression");
-           im_log((aIMCTX, 1, "read 4-bit: scanline overflow (unpacked) x %d + count %d vs xlimit %d (y %d)\n",
+           mm_log((1, "read 4-bit: scanline overflow (unpacked) x %d + count %d vs xlimit %d (y %d)\n",
                  (int)x, count, (int)xlimit, (int)y));
            i_img_destroy(im);
            return NULL;
@@ -1069,7 +1052,7 @@ read_4bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
   else { /*if (compression == BI_RLE4) {*/
     myfree(packed);
     myfree(line);
-    im_push_errorf(aIMCTX, 0, "unknown 4-bit BMP compression (%d)", compression);
+    i_push_errorf(0, "unknown 4-bit BMP compression (%d)", compression);
     i_img_destroy(im);
     return NULL;
   }
@@ -1094,7 +1077,6 @@ read_8bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
   i_palidx *line;
   int line_size = xsize;
   long base_offset;
-  dIMCTXio(ig);
 
   line_size = (line_size+3) / 4 * 4;
   if (line_size < xsize) { /* if it overflowed (unlikely, but check) */
@@ -1118,13 +1100,13 @@ read_8bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
   if (!clr_used)
     clr_used = 256;
   if (clr_used > 256 || clr_used < 0) {
-    im_push_errorf(aIMCTX, 0, "out of range colors used (%d)", clr_used);
+    i_push_errorf(0, "out of range colors used (%d)", clr_used);
     return NULL;
   }
 
   base_offset = FILEHEAD_SIZE + INFOHEAD_SIZE + clr_used * 4;
   if (offbits < base_offset) {
-    im_push_errorf(aIMCTX, 0, "image data offset too small (%ld)", offbits);
+    i_push_errorf(0, "image data offset too small (%ld)", offbits);
     return NULL;
   }
 
@@ -1267,7 +1249,7 @@ read_8bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
   }
   else { 
     myfree(line);
-    im_push_errorf(aIMCTX, 0, "unknown 8-bit BMP compression (%d)", compression);
+    i_push_errorf(0, "unknown 8-bit BMP compression (%d)", compression);
     i_img_destroy(im);
     return NULL;
   }
@@ -1340,7 +1322,6 @@ read_direct_bmp(io_glue *ig, int xsize, int ysize, int bit_count,
   const char *compression_name;
   int bytes;
   long base_offset = FILEHEAD_SIZE + INFOHEAD_SIZE;
-  dIMCTXio(ig);
   
   unpack_code[0] = *("v3V"+pix_size-2);
   unpack_code[1] = '\0';
@@ -1387,7 +1368,7 @@ read_direct_bmp(io_glue *ig, int xsize, int ysize, int bit_count,
         return 0;
       }
       if (rmask == 0) {
-       im_push_errorf(aIMCTX, 0, "Zero mask for channel %d", i);
+       i_push_errorf(0, "Zero mask for channel %d", i);
        return NULL;
       }
       masks.masks[i] = rmask;
@@ -1411,12 +1392,12 @@ read_direct_bmp(io_glue *ig, int xsize, int ysize, int bit_count,
     base_offset += 3 * 4;
   }
   else {
-    im_push_errorf(aIMCTX, 0, "unknown 24-bit BMP compression (%d)", compression);
+    i_push_errorf(0, "unknown 24-bit BMP compression (%d)", compression);
     return NULL;
   }
 
   if (offbits < base_offset) {
-    im_push_errorf(aIMCTX, 0, "image data offset too small (%ld)", offbits);
+    i_push_errorf(0, "image data offset too small (%ld)", offbits);
     return NULL;
   }
 
diff --git a/context.c b/context.c
deleted file mode 100644 (file)
index 0dd7062..0000000
--- a/context.c
+++ /dev/null
@@ -1,300 +0,0 @@
-#include "imageri.h"
-#include <stdio.h>
-
-static im_slot_t slot_count;
-static im_slot_destroy_t *slot_destructors;
-static i_mutex_t slot_mutex;
-
-/*
-=item im_context_new()
-
-Create a new Imager context object.
-
-=cut
-*/
-
-im_context_t
-im_context_new(void) {
-  im_context_t ctx = malloc(sizeof(im_context_struct));
-  int i;
-
-  if (!slot_mutex)
-    slot_mutex = i_mutex_new();
-
-  if (!ctx)
-    return NULL;
-  
-  ctx->error_sp = IM_ERROR_COUNT-1;
-  for (i = 0; i < IM_ERROR_COUNT; ++i) {
-    ctx->error_alloc[i] = 0;
-    ctx->error_stack[i].msg = NULL;
-    ctx->error_stack[i].code = 0;
-  }
-#ifdef IMAGER_LOG
-  ctx->log_level = 0;
-  ctx->lg_file = NULL;
-#endif
-  ctx->max_width = 0;
-  ctx->max_height = 0;
-  ctx->max_bytes = DEF_BYTES_LIMIT;
-
-  ctx->slot_alloc = slot_count;
-  ctx->slots = calloc(sizeof(void *), ctx->slot_alloc);
-  if (!ctx->slots) {
-    free(ctx);
-    return NULL;
-  }
-
-  ctx->refcount = 1;
-
-#ifdef IMAGER_TRACE_CONTEXT
-  fprintf(stderr, "im_context: created %p\n", ctx);
-#endif
-
-
-  return ctx;
-}
-
-/*
-=item im_context_refinc(ctx, where)
-X<im_context_refinc API>
-=section Context objects
-=synopsis im_context_refinc(aIMCTX, "a description");
-
-Add a new reference to the context.
-
-=cut
-*/
-
-void
-im_context_refinc(im_context_t ctx, const char *where) {
-  ++ctx->refcount;
-
-#ifdef IMAGER_TRACE_CONTEXT
-  fprintf(stderr, "im_context:%s: refinc %p (count now %lu)\n", where,
-         ctx, (unsigned long)ctx->refcount);
-#endif
-}
-
-/*
-=item im_context_refdec(ctx, where)
-X<im_context_refdec API>
-=section Context objects
-=synopsis im_context_refdec(aIMCTX, "a description");
-
-Remove a reference to the context, releasing it if all references have
-been removed.
-
-=cut
-*/
-
-void
-im_context_refdec(im_context_t ctx, const char *where) {
-  int i;
-  im_slot_t slot;
-
-  im_assert(ctx->refcount > 0);
-
-  --ctx->refcount;
-
-#ifdef IMAGER_TRACE_CONTEXT
-  fprintf(stderr, "im_context:%s: delete %p (count now %lu)\n", where,
-         ctx, (unsigned long)ctx->refcount);
-#endif
-
-  if (ctx->refcount != 0)
-    return;
-
-  for (slot = 0; slot < ctx->slot_alloc; ++slot) {
-    if (ctx->slots[slot] && slot_destructors[slot])
-      slot_destructors[slot](ctx->slots[slot]);
-  }
-
-  free(ctx->slots);
-
-  for (i = 0; i < IM_ERROR_COUNT; ++i) {
-    if (ctx->error_stack[i].msg)
-      myfree(ctx->error_stack[i].msg);
-  }
-#ifdef IMAGER_LOG
-  if (ctx->lg_file)
-    fclose(ctx->lg_file);
-#endif
-
-  free(ctx);
-}
-
-/*
-=item im_context_clone(ctx)
-
-Clone an Imager context object, returning the result.
-
-=cut
-*/
-
-im_context_t
-im_context_clone(im_context_t ctx, const char *where) {
-  im_context_t nctx = malloc(sizeof(im_context_struct));
-  int i;
-
-  if (!nctx)
-    return NULL;
-
-  nctx->slot_alloc = slot_count;
-  nctx->slots = calloc(sizeof(void *), ctx->slot_alloc);
-  if (!nctx->slots) {
-    free(nctx);
-    return NULL;
-  }
-
-  nctx->error_sp = ctx->error_sp;
-  for (i = 0; i < IM_ERROR_COUNT; ++i) {
-    if (ctx->error_stack[i].msg) {
-      size_t sz = ctx->error_alloc[i];
-      nctx->error_alloc[i] = sz;
-      nctx->error_stack[i].msg = mymalloc(sz);
-      memcpy(nctx->error_stack[i].msg, ctx->error_stack[i].msg, sz);
-    }
-    else {
-      nctx->error_alloc[i] = 0;
-      nctx->error_stack[i].msg = NULL;
-    }
-    nctx->error_stack[i].code = ctx->error_stack[i].code;
-  }
-#ifdef IMAGER_LOG
-  nctx->log_level = ctx->log_level;
-  if (ctx->lg_file) {
-    /* disable buffering, this isn't perfect */
-    setvbuf(ctx->lg_file, NULL, _IONBF, 0);
-
-    /* clone that and disable buffering some more */
-    nctx->lg_file = fdopen(fileno(ctx->lg_file), "a");
-    if (nctx->lg_file)
-      setvbuf(nctx->lg_file, NULL, _IONBF, 0);
-  }
-  else {
-    nctx->lg_file = NULL;
-  }
-#endif
-  nctx->max_width = ctx->max_width;
-  nctx->max_height = ctx->max_height;
-  nctx->max_bytes = ctx->max_bytes;
-
-  nctx->refcount = 1;
-
-#ifdef IMAGER_TRACE_CONTEXT
-  fprintf(stderr, "im_context:%s: cloned %p to %p\n", where, ctx, nctx);
-#endif
-
-  return nctx;
-}
-
-/*
-=item im_context_slot_new(destructor, where)
-
-Allocate a new context-local-storage slot.
-
-=cut
-*/
-
-im_slot_t
-im_context_slot_new(im_slot_destroy_t destructor, const char *where) {
-  im_slot_t new_slot;
-  im_slot_destroy_t *new_destructors;
-  if (!slot_mutex)
-    slot_mutex = i_mutex_new();
-
-  i_mutex_lock(slot_mutex);
-
-  new_slot = slot_count++;
-  new_destructors = realloc(slot_destructors, sizeof(void *) * slot_count);
-  if (!new_destructors)
-    i_fatal(1, "Cannot allocate memory for slot destructors");
-  slot_destructors = new_destructors;
-
-  slot_destructors[new_slot] = destructor;
-
-#ifdef IMAGER_TRACE_CONTEXT
-  fprintf(stderr, "im_context: slot %d allocated for %s\n",
-         (int)new_slot, where);
-#endif
-
-  i_mutex_unlock(slot_mutex);
-
-  return new_slot;
-}
-
-/*
-=item im_context_slot_set(slot, value)
-
-Set the value of a slot.
-
-Returns true on success.
-
-Aborts if the slot supplied is invalid.
-
-If reallocation of slot storage fails, returns false.
-
-=cut
-*/
-
-int
-im_context_slot_set(im_context_t ctx, im_slot_t slot, void *value) {
-  if (slot < 0 || slot >= slot_count) {
-    fprintf(stderr, "Invalid slot %d (valid 0 - %d)\n",
-           (int)slot, (int)slot_count-1);
-    abort();
-  }
-
-  if (slot >= ctx->slot_alloc) {
-    ssize_t i;
-    size_t new_alloc = slot_count;
-    void **new_slots = realloc(ctx->slots, sizeof(void *) * new_alloc);
-
-    if (!new_slots)
-      return 0;
-
-    for (i = ctx->slot_alloc; i < new_alloc; ++i)
-      new_slots[i] = NULL;
-
-    ctx->slots = new_slots;
-    ctx->slot_alloc = new_alloc;
-  }
-
-  ctx->slots[slot] = value;
-
-#ifdef IMAGER_TRACE_CONTEXT
-  fprintf(stderr, "im_context: ctx %p slot %d set to %p\n",
-         ctx, (int)slot, value);
-#endif
-
-  return 1;
-}
-
-/*
-=item im_context_slot_get(ctx, slot)
-
-Retrieve the value previously stored in the given slot of the context
-object.
-
-=cut
-*/
-
-void *
-im_context_slot_get(im_context_t ctx, im_slot_t slot) {
-  if (slot < 0 || slot >= slot_count) {
-    fprintf(stderr, "Invalid slot %d (valid 0 - %d)\n",
-           (int)slot, (int)slot_count-1);
-    abort();
-  }
-
-  if (slot >= ctx->slot_alloc)
-    return NULL;
-
-#ifdef IMAGER_TRACE_CONTEXT
-  fprintf(stderr, "im_context: ctx %p slot %d retrieved as %p\n",
-         ctx, (int)slot, ctx->slots[slot]);
-#endif
-
-  return ctx->slots[slot];
-}
diff --git a/conv.im b/conv.im
index ced813ea75ffe500ebfcddbd4193f046cd2e36c4..f02db85633db7824087c8b21d179218143c591d5 100644 (file)
--- a/conv.im
+++ b/conv.im
@@ -1,4 +1,3 @@
-#define IMAGER_NO_CONTEXT
 #include "imager.h"
 #include "imageri.h"
 
@@ -20,13 +19,12 @@ i_conv(i_img *im, const double *coeff,int len) {
   double pc;
   double res[MAXCHANNELS];
   i_img *timg;
-  dIMCTXim(im);
 
-  im_log((aIMCTX,1,"i_conv(im %p, coeff %p, len %d)\n",im,coeff,len));
-  im_clear_error(aIMCTX);
+  mm_log((1,"i_conv(im %p, coeff %p, len %d)\n",im,coeff,len));
+  i_clear_error();
 
   if (len < 1) {
-    im_push_error(aIMCTX, 0, "there must be at least one coefficient");
+    i_push_error(0, "there must be at least one coefficient");
     return 0;
   }
  
index 2d5a8a96a6890a57956112b547cae3d7e729c3b0..3ab6d177634d5b5c4cec15cd45fb43c848c0e3ea 100644 (file)
@@ -17,7 +17,6 @@ converting from RGBA to greyscale and back.
 =cut
 */
 
-#define IMAGER_NO_CONTEXT
 #include "imager.h"
 
 struct chan_copy {
@@ -70,18 +69,17 @@ i_convert(i_img *src, const double *coeff, int outchan, int inchan) {
   int i, j;
   int ilimit;
   i_img *im = NULL;
-  dIMCTXim(src);
 
-  im_log((aIMCTX,1,"i_convert(im %p, src %p, coeff %p,outchan %d, inchan %d)\n",
+  mm_log((1,"i_convert(im %p, src %p, coeff %p,outchan %d, inchan %d)\n",
          im, src, coeff, outchan, inchan));
  
-  im_clear_error(aIMCTX);
+  i_clear_error();
 
   ilimit = inchan;
   if (ilimit > src->channels)
     ilimit = src->channels;
   if (outchan > MAXCHANNELS) {
-    im_push_error(aIMCTX, 0, "cannot have outchan > MAXCHANNELS");
+    i_push_error(0, "cannot have outchan > MAXCHANNELS");
     return 0;
   }
 
@@ -132,8 +130,8 @@ i_convert(i_img *src, const double *coeff, int outchan, int inchan) {
     i_color *colors;
     i_palidx *vals;
 
-    im = im_img_pal_new(aIMCTX, src->xsize, src->ysize, outchan, 
-                       i_maxcolors(src));
+    im = i_img_pal_new(src->xsize, src->ysize, outchan, 
+                      i_maxcolors(src));
 
     /* just translate the color table */
     count = i_colorcount(src);
index c6604100e17a16138066aca120c4a074b276e7ce..e8ef231dd668453c9c6476bc8733fd77ea10304f 100644 (file)
@@ -1,7 +1,6 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
-#define IMAGER_NO_CONTEXT
 #include "imager.h"
 
 /*
@@ -130,9 +129,8 @@ llist_push(struct llist *l,const void *data) {
     }
   }
   /*   fprintf(stderr,"0x%08X\n",l->t); */
-  if (llist_llink_push(l,l->t,data)) {
-    dIMCTX;
-    im_fatal(aIMCTX, 3, "out of memory\n");
+  if (llist_llink_push(l,l->t,data)) { 
+    i_fatal(3, "out of memory\n");
   }
 }
 
diff --git a/draw.c b/draw.c
index b74fe2e6178d077532ca4386df415d56e4e28ac2..f36949aade24090ab89b14fcce2edc5fd8f841d6 100644 (file)
--- a/draw.c
+++ b/draw.c
@@ -1,4 +1,3 @@
-#define IMAGER_NO_CONTEXT
 #include "imager.h"
 #include "draw.h"
 #include "log.h"
@@ -237,10 +236,6 @@ of angles in degrees from d1 to d2, with the color.
 void
 i_arc(i_img *im, i_img_dim x, i_img_dim y,double rad,double d1,double d2,const i_color *val) {
   i_int_hlines hlines;
-  dIMCTXim(im);
-
-  im_log((aIMCTX,1,"i_arc(im %p,(x,y)=(" i_DFp "), rad %f, d1 %f, d2 %f, col %p)",
-         im, i_DFcp(x, y), rad, d1, d2, val));
 
   i_int_init_hlines_img(&hlines, im);
 
@@ -269,10 +264,6 @@ of angles in degrees from d1 to d2, with the fill object.
 void
 i_arc_cfill(i_img *im, i_img_dim x, i_img_dim y,double rad,double d1,double d2,i_fill_t *fill) {
   i_int_hlines hlines;
-  dIMCTXim(im);
-
-  im_log((aIMCTX,1,"i_arc_cfill(im %p,(x,y)=(" i_DFp "), rad %f, d1 %f, d2 %f, fill %p)",
-         im, i_DFcp(x, y), rad, d1, d2, fill));
 
   i_int_init_hlines_img(&hlines, im);
 
@@ -372,10 +363,6 @@ i_arc_aa(i_img *im, double x, double y, double rad, double d1, double d2,
         const i_color *val) {
   double *xvals, *yvals;
   int count;
-  dIMCTXim(im);
-
-  im_log((aIMCTX,1,"i_arc_aa(im %p,(x,y)=(%f,%f), rad %f, d1 %f, d2 %f, col %p)",
-         im, x, y, rad, d1, d2, val));
 
   arc_poly(&count, &xvals, &yvals, x, y, rad, d1, d2);
 
@@ -402,10 +389,6 @@ i_arc_aa_cfill(i_img *im, double x, double y, double rad, double d1, double d2,
               i_fill_t *fill) {
   double *xvals, *yvals;
   int count;
-  dIMCTXim(im);
-
-  im_log((aIMCTX,1,"i_arc_aa_cfill(im %p,(x,y)=(%f,%f), rad %f, d1 %f, d2 %f, fill %p)",
-         im, x, y, rad, d1, d2, fill));
 
   arc_poly(&count, &xvals, &yvals, x, y, rad, d1, d2);
 
@@ -430,12 +413,12 @@ polar_to_plane(double cx, double cy, float angle, double radius, frac *x, frac *
 
 static
 void
-make_minmax_list(pIMCTX, i_mmarray *dot, double x, double y, double radius) {
+make_minmax_list(i_mmarray *dot, double x, double y, double radius) {
   float angle = 0.0;
   float astep = radius>0.1 ? .5/radius : 10;
   frac cx, cy, lx, ly, sx, sy;
 
-  im_log((aIMCTX, 1, "make_minmax_list(dot %p, x %.2f, y %.2f, radius %.2f)\n", dot, x, y, radius));
+  mm_log((1, "make_minmax_list(dot %p, x %.2f, y %.2f, radius %.2f)\n", dot, x, y, radius));
 
   polar_to_plane(x, y, angle, radius, &sx, &sy);
   
@@ -511,13 +494,12 @@ i_circle_aa(i_img *im, double x, double y, double rad, const i_color *val) {
   i_mmarray dot;
   i_color temp;
   i_img_dim ly;
-  dIMCTXim(im);
 
-  im_log((aIMCTX, 1, "i_circle_aa(im %p, centre(" i_DFp "), rad %.2f, val %p)\n",
+  mm_log((1, "i_circle_aa(im %p, centre(" i_DFp "), rad %.2f, val %p)\n",
          im, i_DFcp(x, y), rad, val));
 
   i_mmarray_cr(&dot,16*im->ysize);
-  make_minmax_list(aIMCTX, &dot, x, y, rad);
+  make_minmax_list(&dot, x, y, rad);
 
   for(ly = 0; ly<im->ysize; ly++) {
     int ix, cy, minx = INT_MAX, maxx = INT_MIN;
@@ -587,15 +569,11 @@ i_circle_out(i_img *im, i_img_dim xc, i_img_dim yc, i_img_dim r,
   i_img_dim x, y;
   i_img_dim dx, dy;
   int error;
-  dIMCTXim(im);
 
-  im_log((aIMCTX, 1, "i_circle_out(im %p, centre(" i_DFp "), rad %" i_DF ", col %p)\n",
-         im, i_DFcp(xc, yc), i_DFc(r), col));
-
-  im_clear_error(aIMCTX);
+  i_clear_error();
 
   if (r < 0) {
-    im_push_error(aIMCTX, 0, "circle: radius must be non-negative");
+    i_push_error(0, "circle: radius must be non-negative");
     return 0;
   }
 
@@ -706,15 +684,11 @@ i_arc_out(i_img *im, i_img_dim xc, i_img_dim yc, i_img_dim r,
   i_img_dim seg2 = scale * 4;
   i_img_dim seg3 = scale * 6;
   i_img_dim seg4 = scale * 8;
-  dIMCTXim(im);
-
-  im_log((aIMCTX,1,"i_arc_out(im %p,centre(" i_DFp "), rad %" i_DF ", d1 %f, d2 %f, col %p)",
-         im, i_DFcp(xc, yc), i_DFc(r), d1, d2, col));
 
-  im_clear_error(aIMCTX);
+  i_clear_error();
 
   if (r <= 0) {
-    im_push_error(aIMCTX, 0, "arc: radius must be non-negative");
+    i_push_error(0, "arc: radius must be non-negative");
     return 0;
   }
   if (d1 + 360 <= d2)
@@ -846,14 +820,10 @@ i_circle_out_aa(i_img *im, i_img_dim xc, i_img_dim yc, i_img_dim r, const i_colo
   double t;
   i_color workc = *col;
   int orig_alpha = col->channel[3];
-  dIMCTXim(im);
-
-  im_log((aIMCTX,1,"i_circle_out_aa(im %p,centre(" i_DFp "), rad %" i_DF ", col %p)",
-         im, i_DFcp(xc, yc), i_DFc(r), col));
 
-  im_clear_error(aIMCTX);
+  i_clear_error();
   if (r <= 0) {
-    im_push_error(aIMCTX, 0, "arc: radius must be non-negative");
+    i_push_error(0, "arc: radius must be non-negative");
     return 0;
   }
   i = r;
@@ -960,14 +930,10 @@ i_arc_out_aa(i_img *im, i_img_dim xc, i_img_dim yc, i_img_dim r, double d1, doub
   i_img_dim seg2 = scale * 4;
   i_img_dim seg3 = scale * 6;
   i_img_dim seg4 = scale * 8;
-  dIMCTXim(im);
 
-  im_log((aIMCTX,1,"i_arc_out_aa(im %p,centre(" i_DFp "), rad %" i_DF ", d1 %f, d2 %f, col %p)",
-         im, i_DFcp(xc, yc), i_DFc(r), d1, d2, col));
-
-  im_clear_error(aIMCTX);
+  i_clear_error();
   if (r <= 0) {
-    im_push_error(aIMCTX, 0, "arc: radius must be non-negative");
+    i_push_error(0, "arc: radius must be non-negative");
     return 0;
   }
   if (d1 + 360 <= d2)
@@ -1087,9 +1053,7 @@ Outlines the box from (x1,y1) to (x2,y2) inclusive with I<color>.
 void
 i_box(i_img *im,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2,const i_color *val) {
   i_img_dim x,y;
-  dIMCTXim(im);
-
-  im_log((aIMCTX, 1,"i_box(im* %p, p1(" i_DFp "), p2(" i_DFp "),val %p)\n",
+  mm_log((1,"i_box(im* %p, p1(" i_DFp "), p2(" i_DFp "),val %p)\n",
          im, i_DFcp(x1,y1), i_DFcp(x2,y2), val));
   for(x=x1;x<x2+1;x++) {
     i_ppix(im,x,y1,val);
@@ -1116,9 +1080,8 @@ void
 i_box_filled(i_img *im,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2, const i_color *val) {
   i_img_dim x, y, width;
   i_palidx index;
-  dIMCTXim(im);
 
-  im_log((aIMCTX,1,"i_box_filled(im* %p, p1(" i_DFp "), p2(" i_DFp "),val %p)\n",
+  mm_log((1,"i_box_filled(im* %p, p1(" i_DFp "), p2(" i_DFp "),val %p)\n",
          im, i_DFcp(x1, y1), i_DFcp(x2,y2) ,val));
 
   if (x1 > x2 || y1 > y2
@@ -1177,9 +1140,8 @@ color.
 int
 i_box_filledf(i_img *im,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2, const i_fcolor *val) {
   i_img_dim x, y, width;
-  dIMCTXim(im);
 
-  im_log((aIMCTX, 1,"i_box_filledf(im* %p, p1(" i_DFp "), p2(" i_DFp "),val %p)\n",
+  mm_log((1,"i_box_filledf(im* %p, p1(" i_DFp "), p2(" i_DFp "),val %p)\n",
          im, i_DFcp(x1, y1), i_DFcp(x2, y2), val));
 
   if (x1 > x2 || y1 > y2
@@ -1236,9 +1198,8 @@ Fills the box from (x1,y1) to (x2,y2) inclusive with fill.
 void
 i_box_cfill(i_img *im,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2,i_fill_t *fill) {
   i_render r;
-  dIMCTXim(im);
 
-  im_log((aIMCTX,1,"i_box_cfill(im* %p, p1(" i_DFp "), p2(" i_DFp "), fill %p)\n",
+  mm_log((1,"i_box_cfill(im* %p, p1(" i_DFp "), p2(" i_DFp "), fill %p)\n",
          im, i_DFcp(x1, y1), i_DFcp(x2,y2), fill));
 
   ++x2;
@@ -1855,15 +1816,11 @@ i_flood_fill(i_img *im, i_img_dim seedx, i_img_dim seedy, const i_color *dcol) {
   struct i_bitmap *btm;
   i_img_dim x, y;
   i_color val;
-  dIMCTXim(im);
-
-  im_log((aIMCTX, 1, "i_flood_fill(im %p, seed(" i_DFp "), col %p)",
-          im, i_DFcp(seedx, seedy), dcol));
 
-  im_clear_error(aIMCTX);
+  i_clear_error();
   if (seedx < 0 || seedx >= im->xsize ||
       seedy < 0 || seedy >= im->ysize) {
-    im_push_error(aIMCTX, 0, "i_flood_cfill: Seed pixel outside of image");
+    i_push_error(0, "i_flood_cfill: Seed pixel outside of image");
     return 0;
   }
 
@@ -1900,16 +1857,12 @@ i_flood_cfill(i_img *im, i_img_dim seedx, i_img_dim seedy, i_fill_t *fill) {
   i_img_dim bxmin, bxmax, bymin, bymax;
   struct i_bitmap *btm;
   i_color val;
-  dIMCTXim(im);
 
-  im_log((aIMCTX, 1, "i_flood_cfill(im %p, seed(" i_DFp "), fill %p)",
-          im, i_DFcp(seedx, seedy), fill));
-
-  im_clear_error(aIMCTX);
+  i_clear_error();
   
   if (seedx < 0 || seedx >= im->xsize ||
       seedy < 0 || seedy >= im->ysize) {
-    im_push_error(aIMCTX, 0, "i_flood_cfill: Seed pixel outside of image");
+    i_push_error(0, "i_flood_cfill: Seed pixel outside of image");
     return 0;
   }
 
@@ -1946,15 +1899,11 @@ i_flood_fill_border(i_img *im, i_img_dim seedx, i_img_dim seedy, const i_color *
   i_img_dim bxmin, bxmax, bymin, bymax;
   struct i_bitmap *btm;
   i_img_dim x, y;
-  dIMCTXim(im);
-
-  im_log((aIMCTX, 1, "i_flood_cfill(im %p, seed(" i_DFp "), dcol %p, border %p)",
-          im, i_DFcp(seedx, seedy), dcol, border));
 
-  im_clear_error(aIMCTX);
+  i_clear_error();
   if (seedx < 0 || seedx >= im->xsize ||
       seedy < 0 || seedy >= im->ysize) {
-    im_push_error(aIMCTX, 0, "i_flood_cfill: Seed pixel outside of image");
+    i_push_error(0, "i_flood_cfill: Seed pixel outside of image");
     return 0;
   }
 
@@ -1989,16 +1938,12 @@ i_flood_cfill_border(i_img *im, i_img_dim seedx, i_img_dim seedy, i_fill_t *fill
                     const i_color *border) {
   i_img_dim bxmin, bxmax, bymin, bymax;
   struct i_bitmap *btm;
-  dIMCTXim(im);
-
-  im_log((aIMCTX, 1, "i_flood_cfill_border(im %p, seed(" i_DFp "), fill %p, border %p)",
-          im, i_DFcp(seedx, seedy), fill, border));
 
-  im_clear_error(aIMCTX);
+  i_clear_error();
   
   if (seedx < 0 || seedx >= im->xsize ||
       seedy < 0 || seedy >= im->ysize) {
-    im_push_error(aIMCTX, 0, "i_flood_cfill_border: Seed pixel outside of image");
+    i_push_error(0, "i_flood_cfill_border: Seed pixel outside of image");
     return 0;
   }
 
index faa605daa68b2cee038fa38a7472d6b40c40a0f0..8838038a959d3b41ad1080a0fb5b3bf12d133fc7 100644 (file)
@@ -11,7 +11,7 @@ typedef HMODULE minthandle_t;
 typedef void *minthandle_t; 
 #endif 
 
-#include "ext.h"
+#include "plug.h"
 
 struct DSO_handle_tag {
   minthandle_t handle;
@@ -24,18 +24,14 @@ struct DSO_handle_tag {
 /* #include "XSUB.h"  so we can compile on threaded perls */
 #include "imageri.h"
 
-static im_context_t
-do_get_context(void) {
-  return im_get_context();
-}
-
 static symbol_table_t symbol_table=
   {
     i_has_format,
     ICL_set_internal,
     ICL_info,
-    do_get_context,
-    im_img_empty_ch,
+    i_img_new,
+    i_img_empty,
+    i_img_empty_ch,
     i_img_exorcise,
     i_img_info,
     i_img_setmask,
diff --git a/error.c b/error.c
index a782e3a038f0910453ee1ac21428c9040ce1b82b..84785a2a2fd59d0a188b979198b84e55ec8cb991 100644 (file)
--- a/error.c
+++ b/error.c
@@ -61,24 +61,112 @@ C).  The Perl level won't use all of this.
 =cut
 */
 
-#include "imageri.h"
+#include "imager.h"
 #include <stdio.h>
 #include <stdlib.h>
 
+/* we never actually use the last item - it's the NULL terminator */
+#define ERRSTK 20
+static i_errmsg error_stack[ERRSTK];
+static int error_sp = ERRSTK - 1;
+/* we track the amount of space used each string, so we don't reallocate 
+   space unless we need to.
+   This also means that a memory tracking library may see the memory 
+   allocated for this as a leak. */
+static int error_space[ERRSTK];
+
+static i_error_cb error_cb;
+static i_failed_cb failed_cb;
+static int failures_fatal;
+static char *argv0;
+
+/*
+=item i_set_argv0(char const *program)
+
+Sets the name of the program to be displayed in fatal error messages.
+
+The simplest way to use this is just:
+
+  i_set_argv0(argv[0]);
+
+when your program starts.
+*/
+void i_set_argv0(char const *name) {
+  char *dupl;
+  if (!name)
+    return;
+  /* if the user has an existing string of MAXINT length then
+     the system is broken anyway */
+  dupl = mymalloc(strlen(name)+1); /* check 17jul05 tonyc */
+  strcpy(dupl, name);
+  if (argv0)
+    myfree(argv0);
+  argv0 = dupl;
+}
+
 /*
-=item im_errors(ctx)
-=synopsis i_errmsg *errors = im_errors(aIMCTX);
-=synopsis i_errmsg *errors = i_errors();
+=item i_set_failure_fatal(int failure_fatal)
+
+If failure_fatal is non-zero then any future failures will result in
+Imager exiting your program with a message describing the failure.
+
+Returns the previous setting.
+
+=cut
+*/
+int i_set_failures_fatal(int fatal) {
+  int old = failures_fatal;
+  failures_fatal = fatal;
+
+  return old;
+}
+
+/*
+=item i_set_error_cb(i_error_cb)
+
+Sets a callback function that is called each time an error is pushed
+onto the error stack.
+
+Returns the previous callback.
+
+i_set_failed_cb() is probably more useful.
+
+=cut
+*/
+i_error_cb i_set_error_cb(i_error_cb cb) {
+  i_error_cb old = error_cb;
+  error_cb = cb;
+
+  return old;
+}
+
+/*
+=item i_set_failed_cb(i_failed_cb cb)
+
+Sets a callback function that is called each time an Imager function
+fails.
+
+Returns the previous callback.
+
+=cut
+*/
+i_failed_cb i_set_failed_cb(i_failed_cb cb) {
+  i_failed_cb old = failed_cb;
+  failed_cb = cb;
+
+  return old;
+}
+
+/*
+=item i_errors()
 
 Returns a pointer to the first element of an array of error messages,
 terminated by a NULL pointer.  The highest level message is first.
 
-Also callable as C<i_errors()>.
-
 =cut
 */
-i_errmsg *im_errors(im_context_t ctx) {
-  return ctx->error_stack + ctx->error_sp;
+i_errmsg *i_errors() {
+  return error_stack + error_sp;
 }
 
 /*
@@ -94,9 +182,7 @@ the mark.
 
 =over
 
-=item im_clear_error(ctx)
-X<im_clear_error API>X<i_clear_error API>
-=synopsis im_clear_error(aIMCTX);
+=item i_clear_error()
 =synopsis i_clear_error();
 =category Error handling
 
@@ -104,33 +190,27 @@ Clears the error stack.
 
 Called by any Imager function before doing any other processing.
 
-Also callable as C<i_clear_error()>.
-
 =cut
 */
-
-void
-im_clear_error(im_context_t ctx) {
+void i_clear_error() {
 #ifdef IMAGER_DEBUG_MALLOC
   int i;
 
-  for (i = 0; i < IM_ERROR_COUNT; ++i) {
-    if (ctx->error_space[i]) {
-      myfree(ctx->error_stack[i].msg);
-      ctx->error_stack[i].msg = NULL;
-      ctx->error_space[i] = 0;
+  for (i = 0; i < ERRSTK; ++i) {
+    if (error_space[i]) {
+      myfree(error_stack[i].msg);
+      error_stack[i].msg = NULL;
+      error_space[i] = 0;
     }
   }
 #endif
-  ctx->error_sp = IM_ERROR_COUNT-1;
+  error_sp = ERRSTK-1;
 }
 
 /*
-=item im_push_error(ctx, code, message)
-X<im_push_error API>X<i_push_error API>
+=item i_push_error(int code, char const *msg)
 =synopsis i_push_error(0, "Yep, it's broken");
 =synopsis i_push_error(errno, "Error writing");
-=synopsis im_push_error(aIMCTX, 0, "Something is wrong");
 =category Error handling
 
 Called by an Imager function to push an error message onto the stack.
@@ -141,35 +221,34 @@ error handling is calling function that does.).
 
 =cut
 */
-void
-im_push_error(im_context_t ctx, int code, char const *msg) {
+void i_push_error(int code, char const *msg) {
   size_t size = strlen(msg)+1;
 
-  if (ctx->error_sp <= 0)
+  if (error_sp <= 0)
     /* bad, bad programmer */
     return;
 
-  --ctx->error_sp;
-  if (ctx->error_alloc[ctx->error_sp] < size) {
-    if (ctx->error_stack[ctx->error_sp].msg)
-      myfree(ctx->error_stack[ctx->error_sp].msg);
+  --error_sp;
+  if (error_space[error_sp] < size) {
+    if (error_stack[error_sp].msg)
+      myfree(error_stack[error_sp].msg);
     /* memory allocated on the following line is only ever released when 
        we need a bigger string */
     /* size is size (len+1) of an existing string, overflow would mean
        the system is broken anyway */
-    ctx->error_stack[ctx->error_sp].msg = mymalloc(size); /* checked 17jul05 tonyc */
-    ctx->error_alloc[ctx->error_sp] = size;
+    error_stack[error_sp].msg = mymalloc(size); /* checked 17jul05 tonyc */
+    error_space[error_sp] = size;
   }
-  strcpy(ctx->error_stack[ctx->error_sp].msg, msg);
-  ctx->error_stack[ctx->error_sp].code = code;
+  strcpy(error_stack[error_sp].msg, msg);
+  error_stack[error_sp].code = code;
+
+  if (error_cb)
+    error_cb(code, msg);
 }
 
 /*
-=item im_push_errorvf(ctx, code, format, args)
-X<im_push_error_vf API>X<i_push_errorvf API>
-=synopsis va_args args;
-=synopsis va_start(args, lastarg);
-=synopsis im_push_errorvf(ctx, code, format, args);
+=item i_push_errorvf(int C<code>, char const *C<fmt>, va_list C<ap>)
+
 =category Error handling
 
 Intended for use by higher level functions, takes a varargs pointer
@@ -177,12 +256,9 @@ and a format to produce the finally pushed error message.
 
 Does not support perl specific format codes.
 
-Also callable as C<i_push_errorvf(code, format, args)>
-
 =cut
 */
-void 
-im_push_errorvf(im_context_t ctx, int code, char const *fmt, va_list ap) {
+void i_push_errorvf(int code, char const *fmt, va_list ap) {
   char buf[1024];
 #if defined(IMAGER_VSNPRINTF)
   vsnprintf(buf, sizeof(buf), fmt, ap);
@@ -195,7 +271,7 @@ im_push_errorvf(im_context_t ctx, int code, char const *fmt, va_list ap) {
    */
   vsprintf(buf, fmt, ap);
 #endif
-  im_push_error(ctx, code, buf);
+  i_push_error(code, buf);
 }
 
 /*
@@ -209,33 +285,13 @@ Does not support perl specific format codes.
 
 =cut
 */
-void
-i_push_errorf(int code, char const *fmt, ...) {
+void i_push_errorf(int code, char const *fmt, ...) {
   va_list ap;
   va_start(ap, fmt);
   i_push_errorvf(code, fmt, ap);
   va_end(ap);
 }
 
-/*
-=item im_push_errorf(ctx, code, char const *fmt, ...)
-=synopsis im_push_errorf(aIMCTX, errno, "Cannot open file %s: %d", filename, errno);
-=category Error handling
-
-A version of im_push_error() that does printf() like formatting.
-
-Does not support perl specific format codes.
-
-=cut
-*/
-void
-im_push_errorf(im_context_t ctx, int code, char const *fmt, ...) {
-  va_list ap;
-  va_start(ap, fmt);
-  im_push_errorvf(ctx, code, fmt, ap);
-  va_end(ap);
-}
-
 #ifdef IMAGER_I_FAILED
 #error "This isn't used and is untested"
 
@@ -313,7 +369,7 @@ void
 im_assert_fail(char const *file, int line, char const *message) {
   fprintf(stderr, "Assertion failed line %d file %s: %s\n", 
          line, file, message);
-  abort();
+  exit(EXIT_FAILURE);
 }
 
 /*
diff --git a/ext.h b/ext.h
index 9a25820ae280a6c5fa4036a691094ccf657b276b..dd1cfbd8f0e545c8388e95684fa7a41c87517788 100644 (file)
--- a/ext.h
+++ b/ext.h
@@ -1,4 +1,4 @@
-#include "imdatatypes.h"
+#include "imager.h"
 
 #ifndef IMAGER_EXT_H
 #define IMAGER_EXT_H
@@ -20,31 +20,4 @@ typedef struct {
   int (*getobj)(void *hv_t,char* key,char* type,void **store);
 } UTIL_table_t;
 
-typedef struct {
-  undef_int (*i_has_format)(char *frmt);
-  i_color*(*ICL_set)(i_color *cl,unsigned char r,unsigned char g,unsigned char b,unsigned char a);
-  void (*ICL_info)(const i_color *cl);
-
-  im_context_t (*im_get_context_f)(void);
-  i_img*(*im_img_empty_ch_f)(im_context_t, i_img *im,i_img_dim x,i_img_dim y,int ch);
-  void(*i_img_exorcise_f)(i_img *im);
-
-  void(*i_img_info_f)(i_img *im,i_img_dim *info);
-  
-  void(*i_img_setmask_f)(i_img *im,int ch_mask);
-  int (*i_img_getmask_f)(i_img *im);
-  
-  /*
-  int (*i_ppix)(i_img *im,i_img_dim x,i_img_dim y,i_color *val);
-  int (*i_gpix)(i_img *im,i_img_dim x,i_img_dim y,i_color *val);
-  */
-  void(*i_box)(i_img *im,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2,const i_color *val);
-  void(*i_line)(i_img *im,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2,const i_color *val,int endp);
-  void(*i_arc)(i_img *im,i_img_dim x,i_img_dim y,double rad,double d1,double d2,const i_color *val);
-  void(*i_copyto)(i_img *im,i_img *src,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2,i_img_dim tx,i_img_dim ty);
-  void(*i_copyto_trans)(i_img *im,i_img *src,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2,i_img_dim tx,i_img_dim ty,const i_color *trans);
-  int(*i_rubthru)(i_img *im,i_img *src,i_img_dim tx,i_img_dim ty, i_img_dim src_minx, i_img_dim src_miny, i_img_dim src_maxx, i_img_dim src_maxy);
-
-} symbol_table_t;
-
 #endif
diff --git a/fills.c b/fills.c
index 76508c98af6ed79221083562c47c174a6de4d880..795f7cd88e93886dc30cb318701f1c8454f2ca0b 100644 (file)
--- a/fills.c
+++ b/fills.c
@@ -1,4 +1,3 @@
-#define IMAGER_NO_CONTEXT
 #include "imager.h"
 #include "imageri.h"
 
index 918963ece368c5ed8491c059b5f571404947b7cd..06ac6a1ff5e2a064849f54cccc542caccf329147 100644 (file)
@@ -1,4 +1,3 @@
-#define IMAGER_NO_CONTEXT
 #include "imager.h"
 #include "imageri.h"
 #include <stdlib.h>
@@ -74,9 +73,8 @@ i_contrast(i_img *im, float intensity) {
   unsigned char ch;
   unsigned int new_color;
   i_color rcolor;
-  dIMCTXim(im);
   
-  im_log((aIMCTX, 1,"i_contrast(im %p, intensity %f)\n", im, intensity));
+  mm_log((1,"i_contrast(im %p, intensity %f)\n", im, intensity));
   
   if(intensity < 0) return;
   
@@ -102,9 +100,8 @@ s_hardinvert_low(i_img *im, int all) {
   i_img_dim x, y;
   int ch;
   int invert_channels = all ? im->channels : i_img_color_channels(im);
-  dIMCTXim(im);
 
-  im_log((aIMCTX,1,"i_hardinvert)low(im %p, all %d)\n", im, all));
+  mm_log((1,"i_hardinvert(im %p)\n", im));
   
 #code im->bits <= 8  
   IM_COLOR *row, *entry;
@@ -187,9 +184,8 @@ i_noise(i_img *im, float amount, unsigned char type) {
   float damount = amount * 2;
   i_color rcolor;
   int color_inc = 0;
-  dIMCTXim(im);
   
-  im_log((aIMCTX, 1,"i_noise(im %p, intensity %.2f\n", im, amount));
+  mm_log((1,"i_noise(im %p, intensity %.2f\n", im, amount));
   
   if(amount < 0) return;
   
@@ -249,15 +245,15 @@ i_bumpmap(i_img *im, i_img *bump, int channel, i_img_dim light_x, i_img_dim ligh
   double aX, aY, aL;
   double fZ;
   unsigned char px1, px2, py1, py2;
-  dIMCTXim(im);
+  
   i_img new_im;
 
-  im_log((aIMCTX, 1, "i_bumpmap(im %p, add_im %p, channel %d, light(" i_DFp "), st %" i_DF ")\n",
+  mm_log((1, "i_bumpmap(im %p, add_im %p, channel %d, light(" i_DFp "), st %" i_DF ")\n",
          im, bump, channel, i_DFcp(light_x, light_y), i_DFc(st)));
 
 
   if(channel >= bump->channels) {
-    im_log((aIMCTX, 1, "i_bumpmap: channel = %d while bump image only has %d channels\n", channel, bump->channels));
+    mm_log((1, "i_bumpmap: channel = %d while bump image only has %d channels\n", channel, bump->channels));
     return;
   }
 
@@ -431,14 +427,12 @@ i_bumpmap_complex(i_img *im,
   fvec R;         /* Reflection vector    */
   fvec V;         /* Vision vector        */
 
-  dIMCTXim(im);
-
-  im_log((aIMCTX, 1, "i_bumpmap_complex(im %p, bump %p, channel %d, t(" i_DFp 
+  mm_log((1, "i_bumpmap_complex(im %p, bump %p, channel %d, t(" i_DFp 
          "), Lx %.2f, Ly %.2f, Lz %.2f, cd %.2f, cs %.2f, n %.2f, Ia %p, Il %p, Is %p)\n",
          im, bump, channel, i_DFcp(tx, ty), Lx, Ly, Lz, cd, cs, n, Ia, Il, Is));
   
   if (channel >= bump->channels) {
-    im_log((aIMCTX, 1, "i_bumpmap_complex: channel = %d while bump image only has %d channels\n", channel, bump->channels));
+    mm_log((1, "i_bumpmap_complex: channel = %d while bump image only has %d channels\n", channel, bump->channels));
     return;
   }
 
@@ -674,9 +668,8 @@ i_autolevels(i_img *im, float lsat, float usat, float skew) {
   i_img_dim gsum, gmin, gmax;
   i_img_dim bsum, bmin, bmax;
   i_img_dim rcl, rcu, gcl, gcu, bcl, bcu;
-  dIMCTXim(im);
 
-  im_log((aIMCTX, 1,"i_autolevels(im %p, lsat %f,usat %f,skew %f)\n", im, lsat,usat,skew));
+  mm_log((1,"i_autolevels(im %p, lsat %f,usat %f,skew %f)\n", im, lsat,usat,skew));
 
   rsum=gsum=bsum=0;
   for(i=0;i<256;i++) rhist[i]=ghist[i]=bhist[i] = 0;
@@ -931,12 +924,11 @@ i_gradgen(i_img *im, int num, i_img_dim *xo, i_img_dim *yo, i_color *ival, int d
   size_t bytes;
 
   double *fdist;
-  dIMCTXim(im);
 
-  im_log((aIMCTX, 1,"i_gradgen(im %p, num %d, xo %p, yo %p, ival %p, dmeasure %d)\n", im, num, xo, yo, ival, dmeasure));
+  mm_log((1,"i_gradgen(im %p, num %d, xo %p, yo %p, ival %p, dmeasure %d)\n", im, num, xo, yo, ival, dmeasure));
   
   for(p = 0; p<num; p++) {
-    im_log((aIMCTX,1,"i_gradgen: p%d(" i_DFp ")\n", p, i_DFcp(xo[p], yo[p])));
+    mm_log((1,"i_gradgen: p%d(" i_DFp ")\n", p, i_DFcp(xo[p], yo[p])));
     ICL_info(&ival[p]);
   }
 
@@ -972,7 +964,7 @@ i_gradgen(i_img *im, int num, i_img_dim *xo, i_img_dim *yo, i_color *ival, int d
        fdist[p]  = i_max(xd*xd, yd*yd); /* manhattan distance */
        break;
       default:
-       im_fatal(aIMCTX, 3,"i_gradgen: Unknown distance measure\n");
+       i_fatal(3,"i_gradgen: Unknown distance measure\n");
       }
       cs += fdist[p];
     }
@@ -999,12 +991,11 @@ i_nearest_color_foo(i_img *im, int num, i_img_dim *xo, i_img_dim *yo, i_color *i
   i_img_dim x, y;
   i_img_dim xsize    = im->xsize;
   i_img_dim ysize    = im->ysize;
-  dIMCTXim(im);
 
-  im_log((aIMCTX,1,"i_gradgen(im %p, num %d, xo %p, yo %p, ival %p, dmeasure %d)\n", im, num, xo, yo, ival, dmeasure));
+  mm_log((1,"i_gradgen(im %p, num %d, xo %p, yo %p, ival %p, dmeasure %d)\n", im, num, xo, yo, ival, dmeasure));
   
   for(p = 0; p<num; p++) {
-    im_log((aIMCTX, 1,"i_gradgen: p%d(" i_DFp ")\n", p, i_DFcp(xo[p], yo[p])));
+    mm_log((1,"i_gradgen: p%d(" i_DFp ")\n", p, i_DFcp(xo[p], yo[p])));
     ICL_info(&ival[p]);
   }
 
@@ -1027,7 +1018,7 @@ i_nearest_color_foo(i_img *im, int num, i_img_dim *xo, i_img_dim *yo, i_color *i
       mindist = i_max(xd*xd, yd*yd); /* manhattan distance */
       break;
     default:
-      im_fatal(aIMCTX, 3,"i_nearest_color: Unknown distance measure\n");
+      i_fatal(3,"i_nearest_color: Unknown distance measure\n");
     }
 
     for(p = 1; p<num; p++) {
@@ -1044,7 +1035,7 @@ i_nearest_color_foo(i_img *im, int num, i_img_dim *xo, i_img_dim *yo, i_color *i
        curdist = i_max(xd*xd, yd*yd); /* manhattan distance */
        break;
       default:
-       im_fatal(aIMCTX, 3,"i_nearest_color: Unknown distance measure\n");
+       i_fatal(3,"i_nearest_color: Unknown distance measure\n");
       }
       if (curdist < mindist) {
        mindist = curdist;
@@ -1134,9 +1125,8 @@ i_nearest_color(i_img *im, int num, i_img_dim *xo, i_img_dim *yo, i_color *oval,
   i_img_dim ysize    = im->ysize;
   int *cmatch;
   size_t ival_bytes, tval_bytes;
-  dIMCTXim(im);
 
-  im_log((aIMCTX, 1,"i_nearest_color(im %p, num %d, xo %p, yo %p, oval %p, dmeasure %d)\n", im, num, xo, yo, oval, dmeasure));
+  mm_log((1,"i_nearest_color(im %p, num %d, xo %p, yo %p, oval %p, dmeasure %d)\n", im, num, xo, yo, oval, dmeasure));
 
   i_clear_error();
 
@@ -1189,7 +1179,7 @@ i_nearest_color(i_img *im, int num, i_img_dim *xo, i_img_dim *yo, i_color *oval,
       mindist = i_max(xd*xd, yd*yd); /* manhattan distance */
       break;
     default:
-      im_fatal(aIMCTX, 3,"i_nearest_color: Unknown distance measure\n");
+      i_fatal(3,"i_nearest_color: Unknown distance measure\n");
     }
     
     for(p = 1; p<num; p++) {
@@ -1206,7 +1196,7 @@ i_nearest_color(i_img *im, int num, i_img_dim *xo, i_img_dim *yo, i_color *oval,
        curdist = i_max(xd*xd, yd*yd); /* manhattan distance */
        break;
       default:
-       im_fatal(aIMCTX, 3,"i_nearest_color: Unknown distance measure\n");
+       i_fatal(3,"i_nearest_color: Unknown distance measure\n");
       }
       if (curdist < mindist) {
        mindist = curdist;
@@ -1330,7 +1320,6 @@ i_diff_image(i_img *im1, i_img *im2, double mindist) {
   i_img *out;
   int outchans, diffchans;
   i_img_dim xsize, ysize;
-  dIMCTXim(im1);
 
   i_clear_error();
   if (im1->channels != im2->channels) {
@@ -1653,7 +1642,6 @@ i_fountain(i_img *im, double xa, double ya, double xb, double yb,
   i_fountain_seg *my_segs;
   i_fill_combine_f combine_func = NULL;
   i_fill_combinef_f combinef_func = NULL;
-  dIMCTXim(im);
 
   i_clear_error();
 
diff --git a/flip.im b/flip.im
index d286b91f432c3e206a5dcaf1ff629be62f8ae42d..5bb1c74f4400dc541e16295e81bf5c3300afea08 100644 (file)
--- a/flip.im
+++ b/flip.im
@@ -1,4 +1,3 @@
-#define IMAGER_NO_CONTEXT
 #include "imager.h"
 
 static void flip_h(i_img *im);
@@ -23,10 +22,9 @@ Returns 0 if parameters are invalid.
 
 undef_int
 i_flipxy(i_img *im, int direction) {
-  dIMCTXim(im);
   i_clear_error();
 
-  im_log((aIMCTX, 1, "i_flipxy(im %p, direction %d)\n", im, direction ));
+  mm_log((1, "i_flipxy(im %p, direction %d)\n", im, direction ));
 
   if (!im)
     return 0;
@@ -45,9 +43,10 @@ i_flipxy(i_img *im, int direction) {
     break;
 
   default:
-    im_log((aIMCTX, 1, "i_flipxy: direction is invalid\n" ));
-    im_push_errorf(aIMCTX, 0, "direction %d invalid", direction);
+    mm_log((1, "i_flipxy: direction is invalid\n" ));
+    i_push_errorf(0, "direction %d invalid", direction);
     return 0;
+
   }
   return 1;
 }
diff --git a/font.c b/font.c
new file mode 100644 (file)
index 0000000..a162f70
--- /dev/null
+++ b/font.c
@@ -0,0 +1,1378 @@
+#include "imager.h"
+#include "imrender.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef HAVE_LIBT1
+#endif
+
+
+/*
+=head1 NAME
+
+font.c - implements font handling functions for t1 and truetype fonts
+
+=head1 SYNOPSIS
+
+  i_init_fonts();
+
+  #ifdef HAVE_LIBT1
+  fontnum = i_t1_new(path_to_pfb, path_to_afm);
+  i_t1_bbox(fontnum, points, "foo", 3, i_img_dim cords[BOUNDING_BOX_COUNT]);
+  rc = i_t1_destroy(fontnum);
+  #endif
+
+  #ifdef HAVE_LIBTT
+  handle = i_tt_new(path_to_ttf);
+  rc = i_tt_bbox(handle, points, "foo", 3, int cords[6], utf8);
+  i_tt_destroy(handle);
+
+  // and much more
+
+=head1 DESCRIPTION
+
+font.c implements font creation, rendering, bounding box functions and
+more for Imager.
+
+=head1 FUNCTION REFERENCE
+
+Some of these functions are internal.
+
+=over
+
+=cut
+
+*/
+
+
+/* Truetype font support */
+#ifdef HAVE_LIBTT
+
+/* 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
+
+#ifdef FTXPOST
+#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
+#define TT_MS_LANGID_ENGLISH_GENERAL 0x0409
+#endif
+
+/* convert a code point into an index in the glyph cache */
+#define TT_HASH(x) ((x) & 0xFF)
+
+typedef struct i_glyph_entry_ {
+  TT_Glyph glyph;
+  unsigned long ch;
+} i_tt_glyph_entry;
+
+#define TT_NOCHAR (~0UL)
+
+struct TT_Instancehandle_ {
+  TT_Instance instance;
+  TT_Instance_Metrics imetrics;
+  TT_Glyph_Metrics gmetrics[256];
+  i_tt_glyph_entry glyphs[256];
+  int smooth;
+  int order;
+  i_img_dim ptsize;
+};
+
+typedef struct TT_Instancehandle_ TT_Instancehandle;
+
+struct TT_Fonthandle_ {
+  TT_Face face;
+  TT_Face_Properties properties;
+  TT_Instancehandle instanceh[TT_CHC];
+  TT_CharMap char_map;
+#ifdef FTXPOST
+  int loaded_names;
+  TT_Error load_cond;
+#endif
+};
+
+/* Defines */
+
+#define USTRCT(x) ((x).z)
+#define TT_VALID( handle )  ( ( handle ).z != NULL )
+
+static void i_tt_push_error(TT_Error rc);
+
+/* Prototypes */
+
+static  int i_tt_get_instance( TT_Fonthandle *handle, i_img_dim points, int smooth );
+static void i_tt_init_raster_map( TT_Raster_Map* bit, i_img_dim width, i_img_dim height, int smooth );
+static void i_tt_done_raster_map( TT_Raster_Map *bit );
+static void i_tt_clear_raster_map( TT_Raster_Map* bit );
+static void i_tt_blit_or( TT_Raster_Map *dst, TT_Raster_Map *src,i_img_dim x_off, i_img_dim y_off );
+static  int i_tt_get_glyph( TT_Fonthandle *handle, int inst, unsigned long j );
+static void 
+i_tt_render_glyph( TT_Glyph glyph, TT_Glyph_Metrics* gmetrics, 
+                   TT_Raster_Map *bit, TT_Raster_Map *small_bit, 
+                   i_img_dim x_off, i_img_dim y_off, int smooth );
+static int
+i_tt_render_all_glyphs( TT_Fonthandle *handle, int inst, TT_Raster_Map *bit, 
+                        TT_Raster_Map *small_bit, i_img_dim cords[6], 
+                        char const* txt, size_t len, int smooth, int utf8 );
+static void i_tt_dump_raster_map2( i_img* im, TT_Raster_Map* bit, i_img_dim xb, i_img_dim yb, const i_color *cl, int smooth );
+static void i_tt_dump_raster_map_channel( i_img* im, TT_Raster_Map* bit, i_img_dim xb, i_img_dim yb, int channel, int smooth );
+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 );
+static undef_int i_tt_bbox_inst( TT_Fonthandle *handle, int inst ,const char *txt, size_t len, i_img_dim 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 */
+
+
+/*
+ * FreeType interface
+ */
+
+
+/*
+=item init_tt()
+
+Initializes the freetype font rendering engine
+
+=cut
+*/
+
+static undef_int
+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",
+           (unsigned)error));
+    i_tt_push_error(error);
+    i_push_error(0, "Could not initialize freetype 1.x");
+    return(1);
+  }
+
+#ifdef FTXPOST
+  error = TT_Init_Post_Extension( 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;
+  }
+#endif
+
+  error = TT_Set_Raster_Gray_Palette(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;
+  }
+
+  TT_initialized = 1;
+
+  return(0);
+}
+
+
+/* 
+=item i_tt_get_instance(handle, points, smooth)
+
+Finds a points+smooth instance or if one doesn't exist in the cache
+allocates room and returns its cache entry
+
+   fontname - path to the font to load
+   handle   - handle to the font.
+   points   - points of the requested font
+   smooth   - boolean (True: antialias on, False: antialias is off)
+
+=cut
+*/
+
+static
+int
+i_tt_get_instance( TT_Fonthandle *handle, i_img_dim points, int smooth ) {
+  int i,idx;
+  TT_Error error;
+  
+  mm_log((1,"i_tt_get_instance(handle %p, points %" i_DF ", smooth %d)\n",
+          handle, i_DFc(points), smooth));
+  
+  if (smooth == -1) { /* Smooth doesn't matter for this search */
+    for(i=0;i<TT_CHC;i++) {
+      if (handle->instanceh[i].ptsize==points) {
+        mm_log((1,"i_tt_get_instance: in cache - (non selective smoothing search) returning %d\n",i));
+        return i;
+      }
+    }
+    smooth=1; /* We will be adding a font - add it as smooth then */
+  } else { /* Smooth doesn't matter for this search */
+    for(i=0;i<TT_CHC;i++) {
+      if (handle->instanceh[i].ptsize == points 
+          && handle->instanceh[i].smooth == smooth) {
+        mm_log((1,"i_tt_get_instance: in cache returning %d\n",i));
+        return i;
+      }
+    }
+  }
+  
+  /* Found the instance in the cache - return the cache index */
+  
+  for(idx=0;idx<TT_CHC;idx++) {
+    if (!(handle->instanceh[idx].order)) break; /* find the lru item */
+  }
+
+  mm_log((1,"i_tt_get_instance: lru item is %d\n",idx));
+  mm_log((1,"i_tt_get_instance: lru pointer %p\n",
+          USTRCT(handle->instanceh[idx].instance) ));
+  
+  if ( USTRCT(handle->instanceh[idx].instance) ) {
+    mm_log((1,"i_tt_get_instance: freeing lru item from cache %d\n",idx));
+
+    /* Free cached glyphs */
+    for(i=0;i<256;i++)
+      if ( USTRCT(handle->instanceh[idx].glyphs[i].glyph) )
+       TT_Done_Glyph( handle->instanceh[idx].glyphs[i].glyph );
+
+    for(i=0;i<256;i++) {
+      handle->instanceh[idx].glyphs[i].ch = TT_NOCHAR;
+      USTRCT(handle->instanceh[idx].glyphs[i].glyph)=NULL;
+    }
+
+    /* Free instance if needed */
+    TT_Done_Instance( handle->instanceh[idx].instance );
+  }
+  
+  /* create and initialize instance */
+  /* FIXME: probably a memory leak on fail */
+  
+  (void) (( error = TT_New_Instance( handle->face, &handle->instanceh[idx].instance ) ) || 
+         ( error = TT_Set_Instance_Resolutions( handle->instanceh[idx].instance, LTT_dpi, LTT_dpi ) ) ||
+         ( error = TT_Set_Instance_CharSize( handle->instanceh[idx].instance, points*64 ) ) );
+  
+  if ( error ) {
+    mm_log((1, "Could not create and initialize instance: error %x.\n",
+           (unsigned)error ));
+    return -1;
+  }
+  
+  /* Now that the instance should the inplace we need to lower all of the
+     ru counts and put `this' one with the highest entry */
+  
+  for(i=0;i<TT_CHC;i++) handle->instanceh[i].order--;
+
+  handle->instanceh[idx].order=TT_CHC-1;
+  handle->instanceh[idx].ptsize=points;
+  handle->instanceh[idx].smooth=smooth;
+  TT_Get_Instance_Metrics( handle->instanceh[idx].instance, &(handle->instanceh[idx].imetrics) );
+
+  /* Zero the memory for the glyph storage so they are not thought as
+     cached if they haven't been cached since this new font was loaded */
+
+  for(i=0;i<256;i++) {
+    handle->instanceh[idx].glyphs[i].ch = TT_NOCHAR;
+    USTRCT(handle->instanceh[idx].glyphs[i].glyph)=NULL;
+  }
+  
+  return idx;
+}
+
+
+/*
+=item i_tt_new(fontname)
+
+Creates a new font handle object, finds a character map and initialise the
+the font handle's cache
+
+   fontname - path to the font to load
+
+=cut
+*/
+
+TT_Fonthandle*
+i_tt_new(const char *fontname) {
+  TT_Error error;
+  TT_Fonthandle *handle;
+  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));
+  
+  /* allocate memory for the structure */
+  
+  handle = mymalloc( sizeof(TT_Fonthandle) ); /* checked 5Nov05 tonyc */
+
+  /* load the typeface */
+  error = TT_Open_Face( engine, fontname, &handle->face );
+  if ( error ) {
+    if ( error == TT_Err_Could_Not_Open_File ) {
+      mm_log((1, "Could not find/open %s.\n", fontname ));
+    }
+    else {
+      mm_log((1, "Error while opening %s, error code = 0x%x.\n",fontname, 
+              (unsigned)error )); 
+    }
+    i_tt_push_error(error);
+    return NULL;
+  }
+  
+  TT_Get_Face_Properties( handle->face, &(handle->properties) );
+
+  /* First, look for a Unicode charmap */
+  n = handle->properties.num_CharMaps;
+  USTRCT( handle->char_map )=NULL; /* Invalidate character map */
+  
+  for ( i = 0; i < n; i++ ) {
+    TT_Get_CharMap_ID( handle->face, i, &platform, &encoding );
+    if ( (platform == 3 && encoding == 1 ) 
+         || (platform == 0 && encoding == 0 ) ) {
+      mm_log((2,"i_tt_new - found char map platform %u encoding %u\n", 
+              platform, encoding));
+      TT_Get_CharMap( handle->face, i, &(handle->char_map) );
+      break;
+    }
+  }
+  if (!USTRCT(handle->char_map) && n != 0) {
+    /* just use the first one */
+    TT_Get_CharMap( handle->face, 0, &(handle->char_map));
+  }
+
+  /* Zero the pointsizes - and ordering */
+  
+  for(i=0;i<TT_CHC;i++) {
+    USTRCT(handle->instanceh[i].instance)=NULL;
+    handle->instanceh[i].order=i;
+    handle->instanceh[i].ptsize=0;
+    handle->instanceh[i].smooth=-1;
+  }
+
+#ifdef FTXPOST
+  handle->loaded_names = 0;
+#endif
+
+  mm_log((1,"i_tt_new <- %p\n",handle));
+  return handle;
+}
+
+
+
+/*
+ * raster map management
+ */
+
+/* 
+=item i_tt_init_raster_map(bit, width, height, smooth)
+
+Allocates internal memory for the bitmap as needed by the parameters (internal)
+                
+   bit    - bitmap to allocate into
+   width  - width of the bitmap
+   height - height of the bitmap
+   smooth - boolean (True: antialias on, False: antialias is off)
+
+=cut
+*/
+
+static
+void
+i_tt_init_raster_map( TT_Raster_Map* bit, i_img_dim width, i_img_dim height, int smooth ) {
+
+  mm_log((1,"i_tt_init_raster_map( bit %p, width %" i_DF ", height %" i_DF
+         ", smooth %d)\n", bit, i_DFc(width), i_DFc(height), smooth));
+  
+  bit->rows  = height;
+  bit->width = ( width + 3 ) & -4;
+  bit->flow  = TT_Flow_Down;
+  
+  if ( smooth ) {
+    bit->cols  = bit->width;
+    bit->size  = bit->rows * bit->width;
+  } else {
+    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) {
+    i_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 %ld)\n", bit->width, bit->cols, bit->rows, bit->size ));
+
+  bit->bitmap = (void *) mymalloc( bit->size ); /* checked 6Nov05 tonyc */
+  if ( !bit->bitmap ) i_fatal(0,"Not enough memory to allocate bitmap (%d)!\n",bit->size );
+}
+
+
+/*
+=item i_tt_clear_raster_map(bit)
+
+Frees the bitmap data and sets pointer to NULL (internal)
+                
+   bit - bitmap to free
+
+=cut
+*/
+
+static
+void
+i_tt_done_raster_map( TT_Raster_Map *bit ) {
+  myfree( bit->bitmap );
+  bit->bitmap = NULL;
+}
+
+
+/*
+=item i_tt_clear_raster_map(bit)
+
+Clears the specified bitmap (internal)
+                
+   bit - bitmap to zero
+
+=cut
+*/
+
+
+static
+void
+i_tt_clear_raster_map( TT_Raster_Map*  bit ) {
+  memset( bit->bitmap, 0, bit->size );
+}
+
+
+/* 
+=item i_tt_blit_or(dst, src, x_off, y_off)
+
+function that blits one raster map into another (internal)
+                
+   dst   - destination bitmap
+   src   - source bitmap
+   x_off - x offset into the destination bitmap
+   y_off - y offset into the destination bitmap
+
+=cut
+*/
+
+static
+void
+i_tt_blit_or( TT_Raster_Map *dst, TT_Raster_Map *src,i_img_dim x_off, i_img_dim y_off ) {
+  i_img_dim  x,  y;
+  i_img_dim  x1, x2, y1, y2;
+  unsigned char *s, *d;
+  
+  x1 = x_off < 0 ? -x_off : 0;
+  y1 = y_off < 0 ? -y_off : 0;
+  
+  x2 = (int)dst->cols - x_off;
+  if ( x2 > src->cols ) x2 = src->cols;
+  
+  y2 = (int)dst->rows - y_off;
+  if ( y2 > src->rows ) y2 = src->rows;
+
+  if ( x1 >= x2 ) return;
+
+  /* do the real work now */
+
+  for ( y = y1; y < y2; ++y ) {
+    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)
+       *d = *s;
+      d++;
+      s++;
+    }
+  }
+}
+
+/* useful for debugging */
+#if 0
+
+static void dump_raster_map(FILE *out, TT_Raster_Map *bit ) {
+  int x, y;
+  fprintf(out, "cols %d rows %d  flow %d\n", bit->cols, bit->rows, bit->flow);
+  for (y = 0; y < bit->rows; ++y) {
+    fprintf(out, "%2d:", y);
+    for (x = 0; x < bit->cols; ++x) {
+      if ((x & 7) == 0 && x) putc(' ', out);
+      fprintf(out, "%02x", ((unsigned char *)bit->bitmap)[y*bit->cols+x]);
+    }
+    putc('\n', out);
+  }
+}
+
+#endif
+
+/* 
+=item i_tt_get_glyph(handle, inst, j) 
+
+Function to see if a glyph exists and if so cache it (internal)
+                
+   handle - pointer to font handle
+   inst   - font instance
+   j      - charcode of glyph
+
+=cut
+*/
+
+static
+int
+i_tt_get_glyph( TT_Fonthandle *handle, int inst, unsigned long j) {
+  unsigned short load_flags, code;
+  TT_Error error;
+
+  mm_log((1, "i_tt_get_glyph(handle %p, inst %d, j %lu (%c))\n",
+          handle,inst,j, (int)((j >= ' ' && j <= '~') ? j : '.')));
+  
+  /*mm_log((1, "handle->instanceh[inst].glyphs[j]=0x%08X\n",handle->instanceh[inst].glyphs[j] ));*/
+
+  if ( TT_VALID(handle->instanceh[inst].glyphs[TT_HASH(j)].glyph)
+       && handle->instanceh[inst].glyphs[TT_HASH(j)].ch == j) {
+    mm_log((1,"i_tt_get_glyph: %lu in cache\n",j));
+    return 1;
+  }
+
+  if ( TT_VALID(handle->instanceh[inst].glyphs[TT_HASH(j)].glyph) ) {
+    /* clean up the entry */
+    TT_Done_Glyph( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph );
+    USTRCT( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph ) = NULL;
+    handle->instanceh[inst].glyphs[TT_HASH(j)].ch = TT_NOCHAR;
+  }
+  
+  /* Ok - it wasn't cached - try to get it in */
+  load_flags = TTLOAD_SCALE_GLYPH;
+  if ( LTT_hinted ) load_flags |= TTLOAD_HINT_GLYPH;
+  
+  if ( !TT_VALID(handle->char_map) ) {
+    code = (j - ' ' + 1) < 0 ? 0 : (j - ' ' + 1);
+    if ( code >= handle->properties.num_Glyphs ) code = 0;
+  } else code = TT_Char_Index( handle->char_map, j );
+  
+  if ( (error = TT_New_Glyph( handle->face, &handle->instanceh[inst].glyphs[TT_HASH(j)].glyph)) ) {
+    mm_log((1, "Cannot allocate and load glyph: error %#x.\n", (unsigned)error ));
+    i_push_error(error, "TT_New_Glyph()");
+    return 0;
+  }
+  if ( (error = TT_Load_Glyph( handle->instanceh[inst].instance, handle->instanceh[inst].glyphs[TT_HASH(j)].glyph, code, load_flags)) ) {
+    mm_log((1, "Cannot allocate and load glyph: error %#x.\n", (unsigned)error ));
+    /* Don't leak */
+    TT_Done_Glyph( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph );
+    USTRCT( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph ) = NULL;
+    i_push_error(error, "TT_Load_Glyph()");
+    return 0;
+  }
+
+  /* At this point the glyph should be allocated and loaded */
+  handle->instanceh[inst].glyphs[TT_HASH(j)].ch = j;
+
+  /* Next get the glyph metrics */
+  error = TT_Get_Glyph_Metrics( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph, 
+                                &handle->instanceh[inst].gmetrics[TT_HASH(j)] );
+  if (error) {
+    mm_log((1, "TT_Get_Glyph_Metrics: error %#x.\n", (unsigned)error ));
+    TT_Done_Glyph( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph );
+    USTRCT( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph ) = NULL;
+    handle->instanceh[inst].glyphs[TT_HASH(j)].ch = TT_NOCHAR;
+    i_push_error(error, "TT_Get_Glyph_Metrics()");
+    return 0;
+  }
+
+  return 1;
+}
+
+/*
+=item i_tt_has_chars(handle, 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).
+
+Returns the number of characters that were checked.
+
+=cut
+*/
+
+size_t
+i_tt_has_chars(TT_Fonthandle *handle, char const *text, size_t len, int utf8,
+               char *out) {
+  size_t count = 0;
+  mm_log((1, "i_tt_has_chars(handle %p, text %p, len %ld, utf8 %d)\n", 
+          handle, text, (long)len, utf8));
+
+  while (len) {
+    unsigned long c;
+    int index;
+    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 (TT_VALID(handle->char_map)) {
+      index = TT_Char_Index(handle->char_map, c);
+    }
+    else {
+      index = (c - ' ' + 1) < 0 ? 0 : (c - ' ' + 1);
+      if (index >= handle->properties.num_Glyphs)
+        index = 0;
+    }
+    *out++ = index != 0;
+    ++count;
+  }
+
+  return count;
+}
+
+/* 
+=item i_tt_destroy(handle)
+
+Clears the data taken by a font including all cached data such as
+pixmaps and glyphs
+                
+   handle - pointer to font handle
+
+=cut
+*/
+
+void
+i_tt_destroy( TT_Fonthandle *handle) {
+  TT_Close_Face( handle->face );
+  myfree( handle );
+  
+  /* FIXME: Should these be freed automatically by the library? 
+
+  TT_Done_Instance( instance );
+  void
+    i_tt_done_glyphs( void ) {
+    int  i;
+
+    if ( !glyphs ) return;
+    
+    for ( i = 0; i < 256; ++i ) TT_Done_Glyph( glyphs[i] );
+    free( glyphs );
+    
+    glyphs = NULL;
+  }
+  */
+}
+
+
+/*
+ * FreeType Rendering functions
+ */
+
+
+/* 
+=item i_tt_render_glyph(handle, gmetrics, bit, smallbit, x_off, y_off, smooth)
+
+Renders a single glyph into the bit rastermap (internal)
+
+   handle   - pointer to font handle
+   gmetrics - the metrics for the glyph to be rendered
+   bit      - large bitmap that is the destination for the text
+   smallbit - small bitmap that is used only if smooth is true
+   x_off    - x offset of glyph
+   y_off    - y offset of glyph
+   smooth   - boolean (True: antialias on, False: antialias is off)
+
+=cut
+*/
+
+static
+void
+i_tt_render_glyph( TT_Glyph glyph, TT_Glyph_Metrics* gmetrics, TT_Raster_Map *bit, TT_Raster_Map *small_bit, i_img_dim x_off, i_img_dim y_off, int smooth ) {
+  
+  mm_log((1,"i_tt_render_glyph(glyph %p, gmetrics %p, bit %p, small_bit %p, x_off %" i_DF ", y_off %" i_DF ", smooth %d)\n",
+         USTRCT(glyph), gmetrics, bit, small_bit, i_DFc(x_off),
+         i_DFc(y_off), smooth));
+  
+  if ( !smooth ) TT_Get_Glyph_Bitmap( glyph, bit, x_off * 64, y_off * 64);
+  else {
+    TT_F26Dot6 xmin, ymin, xmax, ymax;
+
+    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_tt_blit_or( bit, small_bit, xmin/64 + x_off, -ymin/64 - y_off );
+  }
+}
+
+
+/*
+=item i_tt_render_all_glyphs(handle, inst, bit, small_bit, cords, txt, len, smooth)
+
+calls i_tt_render_glyph to render each glyph into the bit rastermap (internal)
+
+   handle   - pointer to font handle
+   inst     - font instance
+   bit      - large bitmap that is the destination for the text
+   smallbit - small bitmap that is used only if smooth is true
+   txt      - string to render
+   len      - length of the string to render
+   smooth   - boolean (True: antialias on, False: antialias is off)
+
+=cut
+*/
+
+static
+int
+i_tt_render_all_glyphs( TT_Fonthandle *handle, int inst, TT_Raster_Map *bit,
+                        TT_Raster_Map *small_bit, i_img_dim cords[6], 
+                        char const* txt, size_t len, int smooth, int utf8 ) {
+  unsigned long j;
+  TT_F26Dot6 x,y;
+  
+  mm_log((1,"i_tt_render_all_glyphs( handle %p, inst %d, bit %p, small_bit %p, txt '%.*s', len %ld, smooth %d, utf8 %d)\n",
+         handle, inst, bit, small_bit, (int)len, txt, (long)len, smooth, utf8));
+  
+  /* 
+     y=-( handle->properties.horizontal->Descender * handle->instanceh[inst].imetrics.y_ppem )/(handle->properties.header->Units_Per_EM);
+  */
+
+  x=-cords[0]; /* FIXME: If you font is antialiased this should be expanded by one to allow for aa expansion and the allocation too - do before passing here */
+  y=-cords[4];
+  
+  while (len) {
+    if (utf8) {
+      j = i_utf8_advance(&txt, &len);
+      if (j == ~0UL) {
+        i_push_error(0, "invalid UTF8 character");
+        return 0;
+      }
+    }
+    else {
+      j = (unsigned char)*txt++;
+      --len;
+    }
+    if ( !i_tt_get_glyph(handle,inst,j) ) 
+      continue;
+    i_tt_render_glyph( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph, 
+                       &handle->instanceh[inst].gmetrics[TT_HASH(j)], bit, 
+                       small_bit, x, y, smooth );
+    x += handle->instanceh[inst].gmetrics[TT_HASH(j)].advance / 64;
+  }
+
+  return 1;
+}
+
+
+/*
+ * Functions to render rasters (single channel images) onto images
+ */
+
+/* 
+=item i_tt_dump_raster_map2(im, bit, xb, yb, cl, smooth)
+
+Function to dump a raster onto an image in color used by i_tt_text() (internal).
+
+   im     - image to dump raster on
+   bit    - bitmap that contains the text to be dumped to im
+   xb, yb - coordinates, left edge and baseline
+   cl     - color to use for text
+   smooth - boolean (True: antialias on, False: antialias is off)
+
+=cut
+*/
+
+static
+void
+i_tt_dump_raster_map2( i_img* im, TT_Raster_Map* bit, i_img_dim xb, i_img_dim yb, const i_color *cl, int smooth ) {
+  unsigned char *bmap;
+  i_img_dim x, y;
+  mm_log((1,"i_tt_dump_raster_map2(im %p, bit %p, xb %" i_DF ", yb %" i_DF ", cl %p)\n",
+         im, bit, i_DFc(xb), i_DFc(yb), cl));
+  
+  bmap = bit->bitmap;
+
+  if ( smooth ) {
+
+    i_render r;
+    i_render_init(&r, im, bit->cols);
+    for(y=0;y<bit->rows;y++) {
+      i_render_color(&r, xb, yb+y, bit->cols, bmap + y*bit->cols, cl);
+    }
+    i_render_done(&r);
+  } else {
+    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;
+       }
+      }
+    }
+
+  }
+}
+
+
+/*
+=item i_tt_dump_raster_map_channel(im, bit, xb, yb, channel, smooth)
+
+Function to dump a raster onto a single channel image in color (internal)
+
+   im      - image to dump raster on
+   bit     - bitmap that contains the text to be dumped to im
+   xb, yb  - coordinates, left edge and baseline
+   channel - channel to copy to
+   smooth  - boolean (True: antialias on, False: antialias is off)
+
+=cut
+*/
+
+static
+void
+i_tt_dump_raster_map_channel( i_img* im, TT_Raster_Map*  bit, i_img_dim xb, i_img_dim yb, int channel, int smooth ) {
+  unsigned char *bmap;
+  i_color val;
+  int c;
+  i_img_dim x,y;
+  int old_mask = im->ch_mask;
+  im->ch_mask = 1 << channel;
+
+  mm_log((1,"i_tt_dump_raster_channel(im %p, bit %p, xb %" i_DF ", yb %" i_DF ", channel %d)\n",
+         im, bit, i_DFc(xb), i_DFc(yb), channel));
+  
+  bmap = bit->bitmap;
+  
+  if ( smooth ) {
+    for(y=0;y<bit->rows;y++) for(x=0;x<bit->width;x++) {
+      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++) {
+      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;
+}
+
+
+/* 
+=item i_tt_rasterize(handle, bit, cords, points, txt, len, smooth) 
+
+interface for generating single channel raster of text (internal)
+
+   handle - pointer to font handle
+   bit    - the bitmap that is allocated, rendered into and NOT freed
+   cords  - the bounding box (modified in place)
+   points - font size to use
+   txt    - string to render
+   len    - length of the string to render
+   smooth - boolean (True: antialias on, False: antialias is off)
+
+=cut
+*/
+
+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 ) {
+  int inst;
+  i_img_dim width, height;
+  TT_Raster_Map small_bit;
+  
+  /* find or install an instance */
+  if ( (inst=i_tt_get_instance(handle,points,smooth)) < 0) { 
+    mm_log((1,"i_tt_rasterize: get instance failed\n"));
+    return 0;
+  }
+  
+  /* calculate bounding box */
+  if (!i_tt_bbox_inst( handle, inst, txt, len, cords, utf8 ))
+    return 0;
+    
+  
+  width  = cords[2]-cords[0];
+  height = cords[5]-cords[4];
+  
+  mm_log((1,"i_tt_rasterize: width=%" i_DF ", height=%" i_DF "\n",
+         i_DFc(width), i_DFc(height) )); 
+  
+  i_tt_init_raster_map ( bit, width, height, smooth );
+  i_tt_clear_raster_map( bit );
+  if ( smooth ) i_tt_init_raster_map( &small_bit, handle->instanceh[inst].imetrics.x_ppem + 32, height, smooth );
+  
+  if (!i_tt_render_all_glyphs( handle, inst, bit, &small_bit, cords, txt, len, 
+                               smooth, utf8 )) {
+    if ( smooth ) 
+      i_tt_done_raster_map( &small_bit );
+    return 0;
+  }
+
+  if ( smooth ) i_tt_done_raster_map( &small_bit );
+  return 1;
+}
+
+
+
+/* 
+ * Exported text rendering interfaces
+ */
+
+
+/*
+=item i_tt_cp(handle, im, xb, yb, channel, points, txt, len, smooth, utf8)
+
+Interface to text rendering into a single channel in an image
+
+   handle  - pointer to font handle
+   im      - image to render text on to
+   xb, yb  - coordinates, left edge and baseline
+   channel - channel to render into
+   points  - font size to use
+   txt     - string to render
+   len     - length of the string to render
+   smooth  - boolean (True: antialias on, False: antialias is off)
+
+=cut
+*/
+
+undef_int
+i_tt_cp( TT_Fonthandle *handle, i_img *im, i_img_dim xb, i_img_dim yb, int channel, double points, char const* txt, size_t len, int smooth, int utf8, int align ) {
+
+  i_img_dim cords[BOUNDING_BOX_COUNT];
+  i_img_dim 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[BBOX_ASCENT];
+  st_offset=cords[BBOX_NEG_WIDTH];
+  y = align ? yb-ascent : yb;
+
+  i_tt_dump_raster_map_channel( im, &bit, xb-st_offset , y, channel, smooth );
+  i_tt_done_raster_map( &bit );
+
+  return 1;
+}
+
+
+/* 
+=item i_tt_text(handle, im, xb, yb, cl, points, txt, len, smooth, utf8) 
+
+Interface to text rendering in a single color onto an image
+
+   handle  - pointer to font handle
+   im      - image to render text on to
+   xb, yb  - coordinates, left edge and baseline
+   cl      - color to use for text
+   points  - font size to use
+   txt     - string to render
+   len     - length of the string to render
+   smooth  - boolean (True: antialias on, False: antialias is off)
+
+=cut
+*/
+
+undef_int
+i_tt_text( TT_Fonthandle *handle, i_img *im, i_img_dim xb, i_img_dim yb, const i_color *cl, double points, char const* txt, size_t len, int smooth, int utf8, int align) {
+  i_img_dim cords[BOUNDING_BOX_COUNT];
+  i_img_dim 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[BBOX_ASCENT];
+  st_offset=cords[BBOX_NEG_WIDTH];
+  y = align ? yb-ascent : yb;
+
+  i_tt_dump_raster_map2( im, &bit, xb+st_offset, y, cl, smooth ); 
+  i_tt_done_raster_map( &bit );
+
+  return 1;
+}
+
+
+/*
+=item i_tt_bbox_inst(handle, inst, txt, len, cords, utf8) 
+
+Function to get texts bounding boxes given the instance of the font (internal)
+
+   handle - pointer to font handle
+   inst   -  font instance
+   txt    -  string to measure
+   len    -  length of the string to render
+   cords  - the bounding box (modified in place)
+
+=cut
+*/
+
+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 ) {
+  int upm, casc, cdesc, first;
+  
+  int start    = 0;
+  i_img_dim width    = 0;
+  int gdescent = 0;
+  int gascent  = 0;
+  int descent  = 0;
+  int ascent   = 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));
+
+  upm     = handle->properties.header->Units_Per_EM;
+  gascent  = ( handle->properties.horizontal->Ascender  * handle->instanceh[inst].imetrics.y_ppem + upm - 1) / upm;
+  gdescent = ( handle->properties.horizontal->Descender * handle->instanceh[inst].imetrics.y_ppem - upm + 1) / upm;
+  
+  width   = 0;
+  start   = 0;
+  
+  mm_log((1, "i_tt_box_inst: gascent=%d gdescent=%d\n", gascent, gdescent));
+
+  first=1;
+  while (len) {
+    if (utf8) {
+      j = i_utf8_advance(&txt, &len);
+      if (j == ~0UL) {
+        i_push_error(0, "invalid UTF8 character");
+        return 0;
+      }
+    }
+    else {
+      j = (unsigned char)*txt++;
+      --len;
+    }
+    if ( i_tt_get_glyph(handle,inst,j) ) {
+      TT_Glyph_Metrics *gm = handle->instanceh[inst].gmetrics + TT_HASH(j);
+      width += gm->advance   / 64;
+      casc   = (gm->bbox.yMax+63) / 64;
+      cdesc  = (gm->bbox.yMin-63) / 64;
+
+      mm_log((1, "i_tt_box_inst: glyph='%c' casc=%d cdesc=%d\n", 
+              (int)((j >= ' ' && j <= '~') ? j : '.'), casc, cdesc));
+
+      if (first) {
+       start    = gm->bbox.xMin / 64;
+       ascent   = (gm->bbox.yMax+63) / 64;
+       descent  = (gm->bbox.yMin-63) / 64;
+       first = 0;
+      }
+      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
+       */
+       rightb = gm->advance - gm->bearingX 
+         - (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); */
+      }
+
+      ascent  = (ascent  >  casc ?  ascent : casc );
+      descent = (descent < cdesc ? descent : cdesc);
+    }
+  }
+  
+  cords[BBOX_NEG_WIDTH]=start;
+  cords[BBOX_GLOBAL_DESCENT]=gdescent;
+  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_RIGHT_BEARING + 1;
+}
+
+
+/*
+=item i_tt_bbox(handle, points, txt, len, cords, utf8)
+
+Interface to get a strings bounding box
+
+   handle - pointer to font handle
+   points - font size to use
+   txt    - string to render
+   len    - length of the string to render
+   cords  - the bounding box (modified in place)
+
+=cut
+*/
+
+undef_int
+i_tt_bbox( TT_Fonthandle *handle, double points,const char *txt,size_t len,i_img_dim cords[6], int utf8) {
+  int inst;
+
+  i_clear_error();
+  mm_log((1,"i_tt_box(handle %p,points %f,txt '%.*s', len %ld, utf8 %d)\n",
+         handle, points, (int)len, txt, (long)len, utf8));
+
+  if ( (inst=i_tt_get_instance(handle,points,-1)) < 0) {
+    i_push_errorf(0, "i_tt_get_instance(%g)", points);
+    mm_log((1,"i_tt_text: get instance failed\n"));
+    return 0;
+  }
+
+  return i_tt_bbox_inst(handle, inst, txt, len, cords, utf8);
+}
+
+/*
+=item i_tt_face_name(handle, name_buf, name_buf_size)
+
+Retrieve's the font's postscript name.
+
+This is complicated by the need to handle encodings and so on.
+
+=cut
+ */
+size_t
+i_tt_face_name(TT_Fonthandle *handle, char *name_buf, size_t name_buf_size) {
+  TT_Face_Properties props;
+  int name_count;
+  int i;
+  TT_UShort platform_id, encoding_id, lang_id, name_id;
+  TT_UShort name_len;
+  TT_String *name;
+  int want_index = -1; /* an acceptable but not perfect name */
+  int score = 0;
+
+  i_clear_error();
+  
+  TT_Get_Face_Properties(handle->face, &props);
+  name_count = props.num_Names;
+  for (i = 0; i < name_count; ++i) {
+    TT_Get_Name_ID(handle->face, i, &platform_id, &encoding_id, &lang_id, 
+                   &name_id);
+
+    TT_Get_Name_String(handle->face, i, &name, &name_len);
+
+    if (platform_id != TT_PLATFORM_APPLE_UNICODE && name_len
+        && name_id == TT_NAME_ID_PS_NAME) {
+      int might_want_index = -1;
+      int might_score = 0;
+      if ((platform_id == TT_PLATFORM_MACINTOSH && encoding_id == TT_MAC_ID_ROMAN)
+          ||
+          (platform_id == TT_PLATFORM_MICROSOFT && encoding_id == TT_MS_LANGID_ENGLISH_UNITED_STATES)) {
+        /* exactly what we want */
+        want_index = i;
+        break;
+      }
+      
+      if (platform_id == TT_PLATFORM_MICROSOFT
+          && (encoding_id & 0xFF) == TT_MS_LANGID_ENGLISH_GENERAL) {
+        /* any english is good */
+        might_want_index = i;
+        might_score = 9;
+      }
+      /* there might be something in between */
+      else {
+        /* anything non-unicode is better than nothing */
+        might_want_index = i;
+        might_score = 1;
+      }
+      if (might_score > score) {
+        score = might_score;
+        want_index = might_want_index;
+      }
+    }
+  }
+
+  if (want_index != -1) {
+    TT_Get_Name_String(handle->face, want_index, &name, &name_len);
+    
+    strncpy(name_buf, name, name_buf_size);
+    name_buf[name_buf_size-1] = '\0';
+
+    return strlen(name) + 1;
+  }
+  else {
+    i_push_error(0, "no face name present");
+    return 0;
+  }
+}
+
+void i_tt_dump_names(TT_Fonthandle *handle) {
+  TT_Face_Properties props;
+  int name_count;
+  int i;
+  TT_UShort platform_id, encoding_id, lang_id, name_id;
+  TT_UShort name_len;
+  TT_String *name;
+  
+  TT_Get_Face_Properties(handle->face, &props);
+  name_count = props.num_Names;
+  for (i = 0; i < name_count; ++i) {
+    TT_Get_Name_ID(handle->face, i, &platform_id, &encoding_id, &lang_id, 
+                   &name_id);
+    TT_Get_Name_String(handle->face, i, &name, &name_len);
+
+    printf("# %d: plat %d enc %d lang %d name %d value ", i, platform_id,
+           encoding_id, lang_id, name_id);
+    if (platform_id == TT_PLATFORM_APPLE_UNICODE) {
+      printf("(unicode)\n");
+    }
+    else {
+      printf("'%s'\n", name);
+    }
+  }
+  fflush(stdout);
+}
+
+size_t
+i_tt_glyph_name(TT_Fonthandle *handle, unsigned long ch, char *name_buf, 
+                 size_t name_buf_size) {
+#ifdef FTXPOST
+  TT_Error rc;
+  TT_String *psname;
+  TT_UShort index;
+
+  i_clear_error();
+
+  if (!handle->loaded_names) {
+    TT_Post post;
+    mm_log((1, "Loading PS Names"));
+    handle->load_cond = TT_Load_PS_Names(handle->face, &post);
+    ++handle->loaded_names;
+  }
+
+  if (handle->load_cond) {
+    i_push_errorf(handle->load_cond, "error loading names (%#x)",
+                 (unsigned)handle->load_cond);
+    return 0;
+  }
+  
+  index = TT_Char_Index(handle->char_map, ch);
+  if (!index) {
+    i_push_error(0, "no such character");
+    return 0;
+  }
+
+  rc = TT_Get_PS_Name(handle->face, index, &psname);
+
+  if (rc) {
+    i_push_error(rc, "error getting name");
+    return 0;
+  }
+
+  strncpy(name_buf, psname, name_buf_size);
+  name_buf[name_buf_size-1] = '\0';
+
+  return strlen(psname) + 1;
+#else
+  mm_log((1, "FTXPOST extension not enabled\n"));
+  i_clear_error();
+  i_push_error(0, "Use of FTXPOST extension disabled");
+
+  return 0;
+#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 */
+
+
+/*
+=back
+
+=head1 AUTHOR
+
+Arnar M. Hrafnkelsson <addi@umich.edu>
+
+=head1 SEE ALSO
+
+Imager(3)
+
+=cut
+*/
diff --git a/fontft1.c b/fontft1.c
deleted file mode 100644 (file)
index 591d68b..0000000
--- a/fontft1.c
+++ /dev/null
@@ -1,1403 +0,0 @@
-#include "imager.h"
-#include "imrender.h"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-
-
-/*
-=head1 NAME
-
-fontft1.c - Freetype 1.x font driver for Imager
-
-=head1 SYNOPSIS
-
-  handle = i_tt_new(path_to_ttf);
-  rc = i_tt_bbox(handle, points, "foo", 3, int cords[6], utf8);
-  i_tt_destroy(handle);
-
-  // and much more
-
-=head1 DESCRIPTION
-
-fontft1.c implements font creation, rendering, bounding box functions and
-more for Imager using Freetype 1.x.
-
-In general this driver should be ignored in favour of the FT2 driver.
-
-=head1 FUNCTION REFERENCE
-
-Some of these functions are internal.
-
-=over
-
-=cut
-
-*/
-
-
-/* Truetype font support */
-/* 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
-
-#ifdef FTXPOST
-#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
-#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;
-} i_tt_glyph_entry;
-
-#define TT_NOCHAR (~0UL)
-
-struct TT_Instancehandle_ {
-  TT_Instance instance;
-  TT_Instance_Metrics imetrics;
-  TT_Glyph_Metrics gmetrics[256];
-  i_tt_glyph_entry glyphs[256];
-  int smooth;
-  int order;
-  i_img_dim ptsize;
-};
-
-typedef struct TT_Instancehandle_ TT_Instancehandle;
-
-struct TT_Fonthandle_ {
-  TT_Face face;
-  TT_Face_Properties properties;
-  TT_Instancehandle instanceh[TT_CHC];
-  TT_CharMap char_map;
-#ifdef FTXPOST
-  int loaded_names;
-  TT_Error load_cond;
-#endif
-};
-
-/* Defines */
-
-#define USTRCT(x) ((x).z)
-#define TT_VALID( handle )  ( ( handle ).z != NULL )
-
-static void i_tt_push_error(TT_Error rc);
-static void i_tt_uninit(void *);
-
-/* Prototypes */
-
-static  int i_tt_get_instance( TT_Fonthandle *handle, i_img_dim points, int smooth );
-static void i_tt_init_raster_map( TT_Raster_Map* bit, i_img_dim width, i_img_dim height, int smooth );
-static void i_tt_done_raster_map( TT_Raster_Map *bit );
-static void i_tt_clear_raster_map( TT_Raster_Map* bit );
-static void i_tt_blit_or( TT_Raster_Map *dst, TT_Raster_Map *src,i_img_dim x_off, i_img_dim y_off );
-static  int i_tt_get_glyph( TT_Fonthandle *handle, int inst, unsigned long j );
-static void 
-i_tt_render_glyph( TT_Glyph glyph, TT_Glyph_Metrics* gmetrics, 
-                   TT_Raster_Map *bit, TT_Raster_Map *small_bit, 
-                   i_img_dim x_off, i_img_dim y_off, int smooth );
-static int
-i_tt_render_all_glyphs( TT_Fonthandle *handle, int inst, TT_Raster_Map *bit, 
-                        TT_Raster_Map *small_bit, i_img_dim cords[6], 
-                        char const* txt, size_t len, int smooth, int utf8 );
-static void i_tt_dump_raster_map2( i_img* im, TT_Raster_Map* bit, i_img_dim xb, i_img_dim yb, const i_color *cl, int smooth );
-static void i_tt_dump_raster_map_channel( i_img* im, TT_Raster_Map* bit, i_img_dim xb, i_img_dim yb, int channel, int smooth );
-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 );
-static undef_int i_tt_bbox_inst( TT_Fonthandle *handle, int inst ,const char *txt, size_t len, i_img_dim cords[6], int utf8 );
-
-
-/* static globals needed */
-
-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, "TT");
-}
-
-
-/*
-=item init_tt()
-
-Initializes the freetype font rendering engine (if needed)
-
-=cut
-*/
-
-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"));
-
-  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 NULL;
-  }
-
-#ifdef FTXPOST
-  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 NULL;
-  }
-#endif
-
-  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 NULL;
-  }
-
-  mm_log((1, "initialized FT1 state %p\n", result));
-
-  result->initialized = 1;
-
-  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)
-
-Finds a points+smooth instance or if one doesn't exist in the cache
-allocates room and returns its cache entry
-
-   fontname - path to the font to load
-   handle   - handle to the font.
-   points   - points of the requested font
-   smooth   - boolean (True: antialias on, False: antialias is off)
-
-=cut
-*/
-
-static
-int
-i_tt_get_instance( TT_Fonthandle *handle, i_img_dim points, int smooth ) {
-  int i,idx;
-  TT_Error error;
-  
-  mm_log((1,"i_tt_get_instance(handle %p, points %" i_DF ", smooth %d)\n",
-          handle, i_DFc(points), smooth));
-  
-  if (smooth == -1) { /* Smooth doesn't matter for this search */
-    for(i=0;i<TT_CHC;i++) {
-      if (handle->instanceh[i].ptsize==points) {
-        mm_log((1,"i_tt_get_instance: in cache - (non selective smoothing search) returning %d\n",i));
-        return i;
-      }
-    }
-    smooth=1; /* We will be adding a font - add it as smooth then */
-  } else { /* Smooth doesn't matter for this search */
-    for(i=0;i<TT_CHC;i++) {
-      if (handle->instanceh[i].ptsize == points 
-          && handle->instanceh[i].smooth == smooth) {
-        mm_log((1,"i_tt_get_instance: in cache returning %d\n",i));
-        return i;
-      }
-    }
-  }
-  
-  /* Found the instance in the cache - return the cache index */
-  
-  for(idx=0;idx<TT_CHC;idx++) {
-    if (!(handle->instanceh[idx].order)) break; /* find the lru item */
-  }
-
-  mm_log((1,"i_tt_get_instance: lru item is %d\n",idx));
-  mm_log((1,"i_tt_get_instance: lru pointer %p\n",
-          USTRCT(handle->instanceh[idx].instance) ));
-  
-  if ( USTRCT(handle->instanceh[idx].instance) ) {
-    mm_log((1,"i_tt_get_instance: freeing lru item from cache %d\n",idx));
-
-    /* Free cached glyphs */
-    for(i=0;i<256;i++)
-      if ( USTRCT(handle->instanceh[idx].glyphs[i].glyph) )
-       TT_Done_Glyph( handle->instanceh[idx].glyphs[i].glyph );
-
-    for(i=0;i<256;i++) {
-      handle->instanceh[idx].glyphs[i].ch = TT_NOCHAR;
-      USTRCT(handle->instanceh[idx].glyphs[i].glyph)=NULL;
-    }
-
-    /* Free instance if needed */
-    TT_Done_Instance( handle->instanceh[idx].instance );
-  }
-  
-  /* create and initialize instance */
-  /* FIXME: probably a memory leak on fail */
-  
-  (void) (( error = TT_New_Instance( handle->face, &handle->instanceh[idx].instance ) ) || 
-         ( error = TT_Set_Instance_Resolutions( handle->instanceh[idx].instance, LTT_dpi, LTT_dpi ) ) ||
-         ( error = TT_Set_Instance_CharSize( handle->instanceh[idx].instance, points*64 ) ) );
-  
-  if ( error ) {
-    mm_log((1, "Could not create and initialize instance: error %x.\n",
-           (unsigned)error ));
-    return -1;
-  }
-  
-  /* Now that the instance should the inplace we need to lower all of the
-     ru counts and put `this' one with the highest entry */
-  
-  for(i=0;i<TT_CHC;i++) handle->instanceh[i].order--;
-
-  handle->instanceh[idx].order=TT_CHC-1;
-  handle->instanceh[idx].ptsize=points;
-  handle->instanceh[idx].smooth=smooth;
-  TT_Get_Instance_Metrics( handle->instanceh[idx].instance, &(handle->instanceh[idx].imetrics) );
-
-  /* Zero the memory for the glyph storage so they are not thought as
-     cached if they haven't been cached since this new font was loaded */
-
-  for(i=0;i<256;i++) {
-    handle->instanceh[idx].glyphs[i].ch = TT_NOCHAR;
-    USTRCT(handle->instanceh[idx].glyphs[i].glyph)=NULL;
-  }
-  
-  return idx;
-}
-
-
-/*
-=item i_tt_new(fontname)
-
-Creates a new font handle object, finds a character map and initialise the
-the font handle's cache
-
-   fontname - path to the font to load
-
-=cut
-*/
-
-TT_Fonthandle*
-i_tt_new(const char *fontname) {
-  TT_Error error;
-  TT_Fonthandle *handle;
-  unsigned short i,n;
-  unsigned short platform,encoding;
-  i_tt_engine *tteng;
-
-  if ((tteng = i_init_tt()) == NULL) {
-    i_push_error(0, "Could not initialize FT1 engine");
-    return NULL;
-  }
-
-  i_clear_error();
-  
-  mm_log((1,"i_tt_new(fontname '%s')\n",fontname));
-  
-  /* allocate memory for the structure */
-  
-  handle = mymalloc( sizeof(TT_Fonthandle) ); /* checked 5Nov05 tonyc */
-
-  /* load the typeface */
-  error = TT_Open_Face( tteng->engine, fontname, &handle->face );
-  if ( error ) {
-    if ( error == TT_Err_Could_Not_Open_File ) {
-      mm_log((1, "Could not find/open %s.\n", fontname ));
-    }
-    else {
-      mm_log((1, "Error while opening %s, error code = 0x%x.\n",fontname, 
-              (unsigned)error )); 
-    }
-    i_tt_push_error(error);
-    return NULL;
-  }
-  
-  TT_Get_Face_Properties( handle->face, &(handle->properties) );
-
-  /* First, look for a Unicode charmap */
-  n = handle->properties.num_CharMaps;
-  USTRCT( handle->char_map )=NULL; /* Invalidate character map */
-  
-  for ( i = 0; i < n; i++ ) {
-    TT_Get_CharMap_ID( handle->face, i, &platform, &encoding );
-    if ( (platform == 3 && encoding == 1 ) 
-         || (platform == 0 && encoding == 0 ) ) {
-      mm_log((2,"i_tt_new - found char map platform %u encoding %u\n", 
-              platform, encoding));
-      TT_Get_CharMap( handle->face, i, &(handle->char_map) );
-      break;
-    }
-  }
-  if (!USTRCT(handle->char_map) && n != 0) {
-    /* just use the first one */
-    TT_Get_CharMap( handle->face, 0, &(handle->char_map));
-  }
-
-  /* Zero the pointsizes - and ordering */
-  
-  for(i=0;i<TT_CHC;i++) {
-    USTRCT(handle->instanceh[i].instance)=NULL;
-    handle->instanceh[i].order=i;
-    handle->instanceh[i].ptsize=0;
-    handle->instanceh[i].smooth=-1;
-  }
-
-#ifdef FTXPOST
-  handle->loaded_names = 0;
-#endif
-
-  mm_log((1,"i_tt_new <- %p\n",handle));
-  return handle;
-}
-
-
-
-/*
- * raster map management
- */
-
-/* 
-=item i_tt_init_raster_map(bit, width, height, smooth)
-
-Allocates internal memory for the bitmap as needed by the parameters (internal)
-                
-   bit    - bitmap to allocate into
-   width  - width of the bitmap
-   height - height of the bitmap
-   smooth - boolean (True: antialias on, False: antialias is off)
-
-=cut
-*/
-
-static
-void
-i_tt_init_raster_map( TT_Raster_Map* bit, i_img_dim width, i_img_dim height, int smooth ) {
-
-  mm_log((1,"i_tt_init_raster_map( bit %p, width %" i_DF ", height %" i_DF
-         ", smooth %d)\n", bit, i_DFc(width), i_DFc(height), smooth));
-  
-  bit->rows  = height;
-  bit->width = ( width + 3 ) & -4;
-  bit->flow  = TT_Flow_Down;
-  
-  if ( smooth ) {
-    bit->cols  = bit->width;
-    bit->size  = bit->rows * bit->width;
-  } else {
-    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) {
-    i_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 %ld)\n", bit->width, bit->cols, bit->rows, bit->size ));
-
-  bit->bitmap = (void *) mymalloc( bit->size ); /* checked 6Nov05 tonyc */
-  if ( !bit->bitmap ) i_fatal(0,"Not enough memory to allocate bitmap (%d)!\n",bit->size );
-}
-
-
-/*
-=item i_tt_clear_raster_map(bit)
-
-Frees the bitmap data and sets pointer to NULL (internal)
-                
-   bit - bitmap to free
-
-=cut
-*/
-
-static
-void
-i_tt_done_raster_map( TT_Raster_Map *bit ) {
-  myfree( bit->bitmap );
-  bit->bitmap = NULL;
-}
-
-
-/*
-=item i_tt_clear_raster_map(bit)
-
-Clears the specified bitmap (internal)
-                
-   bit - bitmap to zero
-
-=cut
-*/
-
-
-static
-void
-i_tt_clear_raster_map( TT_Raster_Map*  bit ) {
-  memset( bit->bitmap, 0, bit->size );
-}
-
-
-/* 
-=item i_tt_blit_or(dst, src, x_off, y_off)
-
-function that blits one raster map into another (internal)
-                
-   dst   - destination bitmap
-   src   - source bitmap
-   x_off - x offset into the destination bitmap
-   y_off - y offset into the destination bitmap
-
-=cut
-*/
-
-static
-void
-i_tt_blit_or( TT_Raster_Map *dst, TT_Raster_Map *src,i_img_dim x_off, i_img_dim y_off ) {
-  i_img_dim  x,  y;
-  i_img_dim  x1, x2, y1, y2;
-  unsigned char *s, *d;
-  
-  x1 = x_off < 0 ? -x_off : 0;
-  y1 = y_off < 0 ? -y_off : 0;
-  
-  x2 = (int)dst->cols - x_off;
-  if ( x2 > src->cols ) x2 = src->cols;
-  
-  y2 = (int)dst->rows - y_off;
-  if ( y2 > src->rows ) y2 = src->rows;
-
-  if ( x1 >= x2 ) return;
-
-  /* do the real work now */
-
-  for ( y = y1; y < y2; ++y ) {
-    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)
-       *d = *s;
-      d++;
-      s++;
-    }
-  }
-}
-
-/* useful for debugging */
-#if 0
-
-static void dump_raster_map(FILE *out, TT_Raster_Map *bit ) {
-  int x, y;
-  fprintf(out, "cols %d rows %d  flow %d\n", bit->cols, bit->rows, bit->flow);
-  for (y = 0; y < bit->rows; ++y) {
-    fprintf(out, "%2d:", y);
-    for (x = 0; x < bit->cols; ++x) {
-      if ((x & 7) == 0 && x) putc(' ', out);
-      fprintf(out, "%02x", ((unsigned char *)bit->bitmap)[y*bit->cols+x]);
-    }
-    putc('\n', out);
-  }
-}
-
-#endif
-
-/* 
-=item i_tt_get_glyph(handle, inst, j) 
-
-Function to see if a glyph exists and if so cache it (internal)
-                
-   handle - pointer to font handle
-   inst   - font instance
-   j      - charcode of glyph
-
-=cut
-*/
-
-static
-int
-i_tt_get_glyph( TT_Fonthandle *handle, int inst, unsigned long j) {
-  unsigned short load_flags, code;
-  TT_Error error;
-
-  mm_log((1, "i_tt_get_glyph(handle %p, inst %d, j %lu (%c))\n",
-          handle,inst,j, (int)((j >= ' ' && j <= '~') ? j : '.')));
-  
-  /*mm_log((1, "handle->instanceh[inst].glyphs[j]=0x%08X\n",handle->instanceh[inst].glyphs[j] ));*/
-
-  if ( TT_VALID(handle->instanceh[inst].glyphs[TT_HASH(j)].glyph)
-       && handle->instanceh[inst].glyphs[TT_HASH(j)].ch == j) {
-    mm_log((1,"i_tt_get_glyph: %lu in cache\n",j));
-    return 1;
-  }
-
-  if ( TT_VALID(handle->instanceh[inst].glyphs[TT_HASH(j)].glyph) ) {
-    /* clean up the entry */
-    TT_Done_Glyph( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph );
-    USTRCT( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph ) = NULL;
-    handle->instanceh[inst].glyphs[TT_HASH(j)].ch = TT_NOCHAR;
-  }
-  
-  /* Ok - it wasn't cached - try to get it in */
-  load_flags = TTLOAD_SCALE_GLYPH;
-  if ( LTT_hinted ) load_flags |= TTLOAD_HINT_GLYPH;
-  
-  if ( !TT_VALID(handle->char_map) ) {
-    code = (j - ' ' + 1) < 0 ? 0 : (j - ' ' + 1);
-    if ( code >= handle->properties.num_Glyphs ) code = 0;
-  } else code = TT_Char_Index( handle->char_map, j );
-  
-  if ( (error = TT_New_Glyph( handle->face, &handle->instanceh[inst].glyphs[TT_HASH(j)].glyph)) ) {
-    mm_log((1, "Cannot allocate and load glyph: error %#x.\n", (unsigned)error ));
-    i_push_error(error, "TT_New_Glyph()");
-    return 0;
-  }
-  if ( (error = TT_Load_Glyph( handle->instanceh[inst].instance, handle->instanceh[inst].glyphs[TT_HASH(j)].glyph, code, load_flags)) ) {
-    mm_log((1, "Cannot allocate and load glyph: error %#x.\n", (unsigned)error ));
-    /* Don't leak */
-    TT_Done_Glyph( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph );
-    USTRCT( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph ) = NULL;
-    i_push_error(error, "TT_Load_Glyph()");
-    return 0;
-  }
-
-  /* At this point the glyph should be allocated and loaded */
-  handle->instanceh[inst].glyphs[TT_HASH(j)].ch = j;
-
-  /* Next get the glyph metrics */
-  error = TT_Get_Glyph_Metrics( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph, 
-                                &handle->instanceh[inst].gmetrics[TT_HASH(j)] );
-  if (error) {
-    mm_log((1, "TT_Get_Glyph_Metrics: error %#x.\n", (unsigned)error ));
-    TT_Done_Glyph( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph );
-    USTRCT( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph ) = NULL;
-    handle->instanceh[inst].glyphs[TT_HASH(j)].ch = TT_NOCHAR;
-    i_push_error(error, "TT_Get_Glyph_Metrics()");
-    return 0;
-  }
-
-  return 1;
-}
-
-/*
-=item i_tt_has_chars(handle, 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).
-
-Returns the number of characters that were checked.
-
-=cut
-*/
-
-size_t
-i_tt_has_chars(TT_Fonthandle *handle, char const *text, size_t len, int utf8,
-               char *out) {
-  size_t count = 0;
-  mm_log((1, "i_tt_has_chars(handle %p, text %p, len %ld, utf8 %d)\n", 
-          handle, text, (long)len, utf8));
-
-  while (len) {
-    unsigned long c;
-    int index;
-    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 (TT_VALID(handle->char_map)) {
-      index = TT_Char_Index(handle->char_map, c);
-    }
-    else {
-      index = (c - ' ' + 1) < 0 ? 0 : (c - ' ' + 1);
-      if (index >= handle->properties.num_Glyphs)
-        index = 0;
-    }
-    *out++ = index != 0;
-    ++count;
-  }
-
-  return count;
-}
-
-/* 
-=item i_tt_destroy(handle)
-
-Clears the data taken by a font including all cached data such as
-pixmaps and glyphs
-                
-   handle - pointer to font handle
-
-=cut
-*/
-
-void
-i_tt_destroy( TT_Fonthandle *handle) {
-  TT_Close_Face( handle->face );
-  myfree( handle );
-  
-  /* FIXME: Should these be freed automatically by the library? 
-
-  TT_Done_Instance( instance );
-  void
-    i_tt_done_glyphs( void ) {
-    int  i;
-
-    if ( !glyphs ) return;
-    
-    for ( i = 0; i < 256; ++i ) TT_Done_Glyph( glyphs[i] );
-    free( glyphs );
-    
-    glyphs = NULL;
-  }
-  */
-}
-
-
-/*
- * FreeType Rendering functions
- */
-
-
-/* 
-=item i_tt_render_glyph(handle, gmetrics, bit, smallbit, x_off, y_off, smooth)
-
-Renders a single glyph into the bit rastermap (internal)
-
-   handle   - pointer to font handle
-   gmetrics - the metrics for the glyph to be rendered
-   bit      - large bitmap that is the destination for the text
-   smallbit - small bitmap that is used only if smooth is true
-   x_off    - x offset of glyph
-   y_off    - y offset of glyph
-   smooth   - boolean (True: antialias on, False: antialias is off)
-
-=cut
-*/
-
-static
-void
-i_tt_render_glyph( TT_Glyph glyph, TT_Glyph_Metrics* gmetrics, TT_Raster_Map *bit, TT_Raster_Map *small_bit, i_img_dim x_off, i_img_dim y_off, int smooth ) {
-  
-  mm_log((1,"i_tt_render_glyph(glyph %p, gmetrics %p, bit %p, small_bit %p, x_off %" i_DF ", y_off %" i_DF ", smooth %d)\n",
-         USTRCT(glyph), gmetrics, bit, small_bit, i_DFc(x_off),
-         i_DFc(y_off), smooth));
-  
-  if ( !smooth ) TT_Get_Glyph_Bitmap( glyph, bit, x_off * 64, y_off * 64);
-  else {
-    TT_F26Dot6 xmin, ymin, xmax, ymax;
-
-    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_tt_blit_or( bit, small_bit, xmin/64 + x_off, -ymin/64 - y_off );
-  }
-}
-
-
-/*
-=item i_tt_render_all_glyphs(handle, inst, bit, small_bit, cords, txt, len, smooth)
-
-calls i_tt_render_glyph to render each glyph into the bit rastermap (internal)
-
-   handle   - pointer to font handle
-   inst     - font instance
-   bit      - large bitmap that is the destination for the text
-   smallbit - small bitmap that is used only if smooth is true
-   txt      - string to render
-   len      - length of the string to render
-   smooth   - boolean (True: antialias on, False: antialias is off)
-
-=cut
-*/
-
-static
-int
-i_tt_render_all_glyphs( TT_Fonthandle *handle, int inst, TT_Raster_Map *bit,
-                        TT_Raster_Map *small_bit, i_img_dim cords[6], 
-                        char const* txt, size_t len, int smooth, int utf8 ) {
-  unsigned long j;
-  TT_F26Dot6 x,y;
-  
-  mm_log((1,"i_tt_render_all_glyphs( handle %p, inst %d, bit %p, small_bit %p, txt '%.*s', len %ld, smooth %d, utf8 %d)\n",
-         handle, inst, bit, small_bit, (int)len, txt, (long)len, smooth, utf8));
-  
-  /* 
-     y=-( handle->properties.horizontal->Descender * handle->instanceh[inst].imetrics.y_ppem )/(handle->properties.header->Units_Per_EM);
-  */
-
-  x=-cords[0]; /* FIXME: If you font is antialiased this should be expanded by one to allow for aa expansion and the allocation too - do before passing here */
-  y=-cords[4];
-  
-  while (len) {
-    if (utf8) {
-      j = i_utf8_advance(&txt, &len);
-      if (j == ~0UL) {
-        i_push_error(0, "invalid UTF8 character");
-        return 0;
-      }
-    }
-    else {
-      j = (unsigned char)*txt++;
-      --len;
-    }
-    if ( !i_tt_get_glyph(handle,inst,j) ) 
-      continue;
-    i_tt_render_glyph( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph, 
-                       &handle->instanceh[inst].gmetrics[TT_HASH(j)], bit, 
-                       small_bit, x, y, smooth );
-    x += handle->instanceh[inst].gmetrics[TT_HASH(j)].advance / 64;
-  }
-
-  return 1;
-}
-
-
-/*
- * Functions to render rasters (single channel images) onto images
- */
-
-/* 
-=item i_tt_dump_raster_map2(im, bit, xb, yb, cl, smooth)
-
-Function to dump a raster onto an image in color used by i_tt_text() (internal).
-
-   im     - image to dump raster on
-   bit    - bitmap that contains the text to be dumped to im
-   xb, yb - coordinates, left edge and baseline
-   cl     - color to use for text
-   smooth - boolean (True: antialias on, False: antialias is off)
-
-=cut
-*/
-
-static
-void
-i_tt_dump_raster_map2( i_img* im, TT_Raster_Map* bit, i_img_dim xb, i_img_dim yb, const i_color *cl, int smooth ) {
-  unsigned char *bmap;
-  i_img_dim x, y;
-  mm_log((1,"i_tt_dump_raster_map2(im %p, bit %p, xb %" i_DF ", yb %" i_DF ", cl %p)\n",
-         im, bit, i_DFc(xb), i_DFc(yb), cl));
-  
-  bmap = bit->bitmap;
-
-  if ( smooth ) {
-
-    i_render r;
-    i_render_init(&r, im, bit->cols);
-    for(y=0;y<bit->rows;y++) {
-      i_render_color(&r, xb, yb+y, bit->cols, bmap + y*bit->cols, cl);
-    }
-    i_render_done(&r);
-  } else {
-    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;
-       }
-      }
-    }
-
-  }
-}
-
-
-/*
-=item i_tt_dump_raster_map_channel(im, bit, xb, yb, channel, smooth)
-
-Function to dump a raster onto a single channel image in color (internal)
-
-   im      - image to dump raster on
-   bit     - bitmap that contains the text to be dumped to im
-   xb, yb  - coordinates, left edge and baseline
-   channel - channel to copy to
-   smooth  - boolean (True: antialias on, False: antialias is off)
-
-=cut
-*/
-
-static
-void
-i_tt_dump_raster_map_channel( i_img* im, TT_Raster_Map*  bit, i_img_dim xb, i_img_dim yb, int channel, int smooth ) {
-  unsigned char *bmap;
-  i_color val;
-  int c;
-  i_img_dim x,y;
-  int old_mask = im->ch_mask;
-  im->ch_mask = 1 << channel;
-
-  mm_log((1,"i_tt_dump_raster_channel(im %p, bit %p, xb %" i_DF ", yb %" i_DF ", channel %d)\n",
-         im, bit, i_DFc(xb), i_DFc(yb), channel));
-  
-  bmap = bit->bitmap;
-  
-  if ( smooth ) {
-    for(y=0;y<bit->rows;y++) for(x=0;x<bit->width;x++) {
-      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++) {
-      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;
-}
-
-
-/* 
-=item i_tt_rasterize(handle, bit, cords, points, txt, len, smooth) 
-
-interface for generating single channel raster of text (internal)
-
-   handle - pointer to font handle
-   bit    - the bitmap that is allocated, rendered into and NOT freed
-   cords  - the bounding box (modified in place)
-   points - font size to use
-   txt    - string to render
-   len    - length of the string to render
-   smooth - boolean (True: antialias on, False: antialias is off)
-
-=cut
-*/
-
-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 ) {
-  int inst;
-  i_img_dim width, height;
-  TT_Raster_Map small_bit;
-  
-  /* find or install an instance */
-  if ( (inst=i_tt_get_instance(handle,points,smooth)) < 0) { 
-    mm_log((1,"i_tt_rasterize: get instance failed\n"));
-    return 0;
-  }
-  
-  /* calculate bounding box */
-  if (!i_tt_bbox_inst( handle, inst, txt, len, cords, utf8 ))
-    return 0;
-    
-  
-  width  = cords[2]-cords[0];
-  height = cords[5]-cords[4];
-  
-  mm_log((1,"i_tt_rasterize: width=%" i_DF ", height=%" i_DF "\n",
-         i_DFc(width), i_DFc(height) )); 
-  
-  i_tt_init_raster_map ( bit, width, height, smooth );
-  i_tt_clear_raster_map( bit );
-  if ( smooth ) i_tt_init_raster_map( &small_bit, handle->instanceh[inst].imetrics.x_ppem + 32, height, smooth );
-  
-  if (!i_tt_render_all_glyphs( handle, inst, bit, &small_bit, cords, txt, len, 
-                               smooth, utf8 )) {
-    if ( smooth ) 
-      i_tt_done_raster_map( &small_bit );
-    return 0;
-  }
-
-  if ( smooth ) i_tt_done_raster_map( &small_bit );
-  return 1;
-}
-
-
-
-/* 
- * Exported text rendering interfaces
- */
-
-
-/*
-=item i_tt_cp(handle, im, xb, yb, channel, points, txt, len, smooth, utf8)
-
-Interface to text rendering into a single channel in an image
-
-   handle  - pointer to font handle
-   im      - image to render text on to
-   xb, yb  - coordinates, left edge and baseline
-   channel - channel to render into
-   points  - font size to use
-   txt     - string to render
-   len     - length of the string to render
-   smooth  - boolean (True: antialias on, False: antialias is off)
-
-=cut
-*/
-
-undef_int
-i_tt_cp( TT_Fonthandle *handle, i_img *im, i_img_dim xb, i_img_dim yb, int channel, double points, char const* txt, size_t len, int smooth, int utf8, int align ) {
-
-  i_img_dim cords[BOUNDING_BOX_COUNT];
-  i_img_dim 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[BBOX_ASCENT];
-  st_offset=cords[BBOX_NEG_WIDTH];
-  y = align ? yb-ascent : yb;
-
-  i_tt_dump_raster_map_channel( im, &bit, xb-st_offset , y, channel, smooth );
-  i_tt_done_raster_map( &bit );
-
-  return 1;
-}
-
-
-/* 
-=item i_tt_text(handle, im, xb, yb, cl, points, txt, len, smooth, utf8) 
-
-Interface to text rendering in a single color onto an image
-
-   handle  - pointer to font handle
-   im      - image to render text on to
-   xb, yb  - coordinates, left edge and baseline
-   cl      - color to use for text
-   points  - font size to use
-   txt     - string to render
-   len     - length of the string to render
-   smooth  - boolean (True: antialias on, False: antialias is off)
-
-=cut
-*/
-
-undef_int
-i_tt_text( TT_Fonthandle *handle, i_img *im, i_img_dim xb, i_img_dim yb, const i_color *cl, double points, char const* txt, size_t len, int smooth, int utf8, int align) {
-  i_img_dim cords[BOUNDING_BOX_COUNT];
-  i_img_dim 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[BBOX_ASCENT];
-  st_offset=cords[BBOX_NEG_WIDTH];
-  y = align ? yb-ascent : yb;
-
-  i_tt_dump_raster_map2( im, &bit, xb+st_offset, y, cl, smooth ); 
-  i_tt_done_raster_map( &bit );
-
-  return 1;
-}
-
-
-/*
-=item i_tt_bbox_inst(handle, inst, txt, len, cords, utf8) 
-
-Function to get texts bounding boxes given the instance of the font (internal)
-
-   handle - pointer to font handle
-   inst   -  font instance
-   txt    -  string to measure
-   len    -  length of the string to render
-   cords  - the bounding box (modified in place)
-
-=cut
-*/
-
-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 ) {
-  int upm, casc, cdesc, first;
-  
-  int start    = 0;
-  i_img_dim width    = 0;
-  int gdescent = 0;
-  int gascent  = 0;
-  int descent  = 0;
-  int ascent   = 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));
-
-  upm     = handle->properties.header->Units_Per_EM;
-  gascent  = ( handle->properties.horizontal->Ascender  * handle->instanceh[inst].imetrics.y_ppem + upm - 1) / upm;
-  gdescent = ( handle->properties.horizontal->Descender * handle->instanceh[inst].imetrics.y_ppem - upm + 1) / upm;
-  
-  width   = 0;
-  start   = 0;
-  
-  mm_log((1, "i_tt_box_inst: gascent=%d gdescent=%d\n", gascent, gdescent));
-
-  first=1;
-  while (len) {
-    if (utf8) {
-      j = i_utf8_advance(&txt, &len);
-      if (j == ~0UL) {
-        i_push_error(0, "invalid UTF8 character");
-        return 0;
-      }
-    }
-    else {
-      j = (unsigned char)*txt++;
-      --len;
-    }
-    if ( i_tt_get_glyph(handle,inst,j) ) {
-      TT_Glyph_Metrics *gm = handle->instanceh[inst].gmetrics + TT_HASH(j);
-      width += gm->advance   / 64;
-      casc   = (gm->bbox.yMax+63) / 64;
-      cdesc  = (gm->bbox.yMin-63) / 64;
-
-      mm_log((1, "i_tt_box_inst: glyph='%c' casc=%d cdesc=%d\n", 
-              (int)((j >= ' ' && j <= '~') ? j : '.'), casc, cdesc));
-
-      if (first) {
-       start    = gm->bbox.xMin / 64;
-       ascent   = (gm->bbox.yMax+63) / 64;
-       descent  = (gm->bbox.yMin-63) / 64;
-       first = 0;
-      }
-      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
-       */
-       rightb = gm->advance - gm->bearingX 
-         - (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); */
-      }
-
-      ascent  = (ascent  >  casc ?  ascent : casc );
-      descent = (descent < cdesc ? descent : cdesc);
-    }
-  }
-  
-  cords[BBOX_NEG_WIDTH]=start;
-  cords[BBOX_GLOBAL_DESCENT]=gdescent;
-  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_RIGHT_BEARING + 1;
-}
-
-
-/*
-=item i_tt_bbox(handle, points, txt, len, cords, utf8)
-
-Interface to get a strings bounding box
-
-   handle - pointer to font handle
-   points - font size to use
-   txt    - string to render
-   len    - length of the string to render
-   cords  - the bounding box (modified in place)
-
-=cut
-*/
-
-undef_int
-i_tt_bbox( TT_Fonthandle *handle, double points,const char *txt,size_t len,i_img_dim cords[6], int utf8) {
-  int inst;
-
-  i_clear_error();
-  mm_log((1,"i_tt_box(handle %p,points %f,txt '%.*s', len %ld, utf8 %d)\n",
-         handle, points, (int)len, txt, (long)len, utf8));
-
-  if ( (inst=i_tt_get_instance(handle,points,-1)) < 0) {
-    i_push_errorf(0, "i_tt_get_instance(%g)", points);
-    mm_log((1,"i_tt_text: get instance failed\n"));
-    return 0;
-  }
-
-  return i_tt_bbox_inst(handle, inst, txt, len, cords, utf8);
-}
-
-/*
-=item i_tt_face_name(handle, name_buf, name_buf_size)
-
-Retrieve's the font's postscript name.
-
-This is complicated by the need to handle encodings and so on.
-
-=cut
- */
-size_t
-i_tt_face_name(TT_Fonthandle *handle, char *name_buf, size_t name_buf_size) {
-  TT_Face_Properties props;
-  int name_count;
-  int i;
-  TT_UShort platform_id, encoding_id, lang_id, name_id;
-  TT_UShort name_len;
-  TT_String *name;
-  int want_index = -1; /* an acceptable but not perfect name */
-  int score = 0;
-
-  i_clear_error();
-  
-  TT_Get_Face_Properties(handle->face, &props);
-  name_count = props.num_Names;
-  for (i = 0; i < name_count; ++i) {
-    TT_Get_Name_ID(handle->face, i, &platform_id, &encoding_id, &lang_id, 
-                   &name_id);
-
-    TT_Get_Name_String(handle->face, i, &name, &name_len);
-
-    if (platform_id != TT_PLATFORM_APPLE_UNICODE && name_len
-        && name_id == TT_NAME_ID_PS_NAME) {
-      int might_want_index = -1;
-      int might_score = 0;
-      if ((platform_id == TT_PLATFORM_MACINTOSH && encoding_id == TT_MAC_ID_ROMAN)
-          ||
-          (platform_id == TT_PLATFORM_MICROSOFT && encoding_id == TT_MS_LANGID_ENGLISH_UNITED_STATES)) {
-        /* exactly what we want */
-        want_index = i;
-        break;
-      }
-      
-      if (platform_id == TT_PLATFORM_MICROSOFT
-          && (encoding_id & 0xFF) == TT_MS_LANGID_ENGLISH_GENERAL) {
-        /* any english is good */
-        might_want_index = i;
-        might_score = 9;
-      }
-      /* there might be something in between */
-      else {
-        /* anything non-unicode is better than nothing */
-        might_want_index = i;
-        might_score = 1;
-      }
-      if (might_score > score) {
-        score = might_score;
-        want_index = might_want_index;
-      }
-    }
-  }
-
-  if (want_index != -1) {
-    TT_Get_Name_String(handle->face, want_index, &name, &name_len);
-    
-    strncpy(name_buf, name, name_buf_size);
-    name_buf[name_buf_size-1] = '\0';
-
-    return strlen(name) + 1;
-  }
-  else {
-    i_push_error(0, "no face name present");
-    return 0;
-  }
-}
-
-void i_tt_dump_names(TT_Fonthandle *handle) {
-  TT_Face_Properties props;
-  int name_count;
-  int i;
-  TT_UShort platform_id, encoding_id, lang_id, name_id;
-  TT_UShort name_len;
-  TT_String *name;
-  
-  TT_Get_Face_Properties(handle->face, &props);
-  name_count = props.num_Names;
-  for (i = 0; i < name_count; ++i) {
-    TT_Get_Name_ID(handle->face, i, &platform_id, &encoding_id, &lang_id, 
-                   &name_id);
-    TT_Get_Name_String(handle->face, i, &name, &name_len);
-
-    printf("# %d: plat %d enc %d lang %d name %d value ", i, platform_id,
-           encoding_id, lang_id, name_id);
-    if (platform_id == TT_PLATFORM_APPLE_UNICODE) {
-      printf("(unicode)\n");
-    }
-    else {
-      printf("'%s'\n", name);
-    }
-  }
-  fflush(stdout);
-}
-
-size_t
-i_tt_glyph_name(TT_Fonthandle *handle, unsigned long ch, char *name_buf, 
-                 size_t name_buf_size) {
-#ifdef FTXPOST
-  TT_Error rc;
-  TT_String *psname;
-  TT_UShort index;
-
-  i_clear_error();
-
-  if (!handle->loaded_names) {
-    TT_Post post;
-    mm_log((1, "Loading PS Names"));
-    handle->load_cond = TT_Load_PS_Names(handle->face, &post);
-    ++handle->loaded_names;
-  }
-
-  if (handle->load_cond) {
-    i_push_errorf(handle->load_cond, "error loading names (%#x)",
-                 (unsigned)handle->load_cond);
-    return 0;
-  }
-  
-  index = TT_Char_Index(handle->char_map, ch);
-  if (!index) {
-    i_push_error(0, "no such character");
-    return 0;
-  }
-
-  rc = TT_Get_PS_Name(handle->face, index, &psname);
-
-  if (rc) {
-    i_push_error(rc, "error getting name");
-    return 0;
-  }
-
-  strncpy(name_buf, psname, name_buf_size);
-  name_buf[name_buf_size-1] = '\0';
-
-  return strlen(psname) + 1;
-#else
-  mm_log((1, "FTXPOST extension not enabled\n"));
-  i_clear_error();
-  i_push_error(0, "Use of FTXPOST extension disabled");
-
-  return 0;
-#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
-}
-
-
-/*
-=back
-
-=head1 AUTHOR
-
-Arnar M. Hrafnkelsson <addi@umich.edu>
-
-=head1 SEE ALSO
-
-Imager(3)
-
-=cut
-*/
index 7e937692332c05852239ce97714bb27ebffba8b1..45fc02d9ce04742f9e55a515da2d787e81224639 100644 (file)
@@ -1,4 +1,3 @@
-#define IMAGER_NO_CONTEXT
 #include "imager.h"
 #include <math.h>
 
@@ -26,9 +25,8 @@ i_gaussian(i_img *im, double stddev) {
   double res[MAXCHANNELS];
   i_img *timg;
   int radius, diameter;
-  dIMCTXim(im);
 
-  im_log((aIMCTX, 1,"i_gaussian(im %p, stdev %.2f)\n",im,stddev));
+  mm_log((1,"i_gaussian(im %p, stdev %.2f)\n",im,stddev));
   i_clear_error();
 
   if (stddev <= 0) {
index 460a20ff82c5fbb48610a699ab1d06b366b20d3c..c4b04cc1e621a981516ff27fb5646c8c22db26ec 100644 (file)
--- a/hlines.c
+++ b/hlines.c
@@ -1,4 +1,3 @@
-#define IMAGER_NO_CONTEXT
 #include "imageri.h"
 #include <stdlib.h>
 
@@ -69,8 +68,7 @@ i_int_init_hlines(
   size_t bytes = count_y * sizeof(i_int_hline_entry *);
 
   if (bytes / count_y != sizeof(i_int_hline_entry *)) {
-    dIMCTX;
-    im_fatal(aIMCTX, 3, "integer overflow calculating memory allocation\n");
+    i_fatal(3, "integer overflow calculating memory allocation\n");
   }
 
   hlines->start_y = start_y;
@@ -113,8 +111,7 @@ i_int_hlines_add(i_int_hlines *hlines, i_img_dim y, i_img_dim x, i_img_dim width
   i_img_dim x_limit = x + width;
 
   if (width < 0) {
-    dIMCTX;
-    im_fatal(aIMCTX, 3, "negative width %d passed to i_int_hlines_add\n", width);
+    i_fatal(3, "negative width %d passed to i_int_hlines_add\n", width);
   }
 
   /* just return if out of range */
diff --git a/image.c b/image.c
index 10228d113dc917a74c3144e038d61d799cd88c4c..a8045f24f884e845c8a7477293234ad1b9b50eb4 100644 (file)
--- a/image.c
+++ b/image.c
@@ -1,5 +1,3 @@
-#define IMAGER_NO_CONTEXT
-
 #include "imager.h"
 #include "imageri.h"
 
@@ -14,7 +12,7 @@ image.c - implements most of the basic functions of Imager and much of the rest
   i_color *c;
   c = i_color_new(red, green, blue, alpha);
   ICL_DESTROY(c);
-  i = i_img_8_new();
+  i = i_img_new();
   i_img_destroy(i);
   // and much more
 
@@ -32,8 +30,6 @@ Some of these functions are internal.
 =cut
 */
 
-im_context_t (*im_get_context)(void) = NULL;
-
 #define XAXIS 0
 #define YAXIS 1
 #define XYAXIS 2
@@ -44,11 +40,8 @@ im_context_t (*im_get_context)(void) = NULL;
 void i_linker_bug_fake(void) { ceil(1); }
 
 /*
-=item im_img_alloc(aIMCTX)
-X<im_img_alloc API>X<i_img_alloc API>
+=item i_img_alloc()
 =category Image Implementation
-=synopsis i_img *im = im_img_alloc(aIMCTX);
-=synopsis i_img *im = i_img_alloc();
 
 Allocates a new i_img structure.
 
@@ -77,29 +70,25 @@ object.
 */
 
 i_img *
-im_img_alloc(pIMCTX) {
+i_img_alloc(void) {
   return mymalloc(sizeof(i_img));
 }
 
 /*
-=item im_img_init(aIMCTX, image)
-X<im_img_init API>X<i_img_init API>
+=item i_img_init(C<img>)
 =category Image Implementation
-=synopsis im_img_init(aIMCTX, im);
-=synopsis i_img_init(im);
 
 Imager internal initialization of images.
 
-See L</im_img_alloc(aIMCTX)> for more information.
+Currently this does very little, in the future it may be used to
+support threads, or color profiles.
 
 =cut
 */
 
 void
-im_img_init(pIMCTX, i_img *img) {
+i_img_init(i_img *img) {
   img->im_data = NULL;
-  img->context = aIMCTX;
-  im_context_refinc(aIMCTX, "img_init");
 }
 
 /* 
@@ -118,16 +107,15 @@ Return a new color object with values passed to it.
 i_color *
 ICL_new_internal(unsigned char r,unsigned char g,unsigned char b,unsigned char a) {
   i_color *cl = NULL;
-  dIMCTX;
 
-  im_log((aIMCTX,1,"ICL_new_internal(r %d,g %d,b %d,a %d)\n", r, g, b, a));
+  mm_log((1,"ICL_new_internal(r %d,g %d,b %d,a %d)\n", r, g, b, a));
 
-  if ( (cl=mymalloc(sizeof(i_color))) == NULL) im_fatal(aIMCTX, 2,"malloc() error\n");
+  if ( (cl=mymalloc(sizeof(i_color))) == NULL) i_fatal(2,"malloc() error\n");
   cl->rgba.r = r;
   cl->rgba.g = g;
   cl->rgba.b = b;
   cl->rgba.a = a;
-  im_log((aIMCTX,1,"(%p) <- ICL_new_internal\n",cl));
+  mm_log((1,"(%p) <- ICL_new_internal\n",cl));
   return cl;
 }
 
@@ -148,16 +136,15 @@ ICL_new_internal(unsigned char r,unsigned char g,unsigned char b,unsigned char a
 
 i_color *
 ICL_set_internal(i_color *cl,unsigned char r,unsigned char g,unsigned char b,unsigned char a) {
-  dIMCTX;
-  im_log((aIMCTX,1,"ICL_set_internal(cl* %p,r %d,g %d,b %d,a %d)\n",cl,r,g,b,a));
+  mm_log((1,"ICL_set_internal(cl* %p,r %d,g %d,b %d,a %d)\n",cl,r,g,b,a));
   if (cl == NULL)
     if ( (cl=mymalloc(sizeof(i_color))) == NULL)
-      im_fatal(aIMCTX, 2,"malloc() error\n");
+      i_fatal(2,"malloc() error\n");
   cl->rgba.r=r;
   cl->rgba.g=g;
   cl->rgba.b=b;
   cl->rgba.a=a;
-  im_log((aIMCTX,1,"(%p) <- ICL_set_internal\n",cl));
+  mm_log((1,"(%p) <- ICL_set_internal\n",cl));
   return cl;
 }
 
@@ -195,9 +182,8 @@ Dump color information to log - strictly for debugging.
 
 void
 ICL_info(i_color const *cl) {
-  dIMCTX;
-  im_log((aIMCTX, 1,"i_color_info(cl* %p)\n",cl));
-  im_log((aIMCTX, 1,"i_color_info: (%d,%d,%d,%d)\n",cl->rgba.r,cl->rgba.g,cl->rgba.b,cl->rgba.a));
+  mm_log((1,"i_color_info(cl* %p)\n",cl));
+  mm_log((1,"i_color_info: (%d,%d,%d,%d)\n",cl->rgba.r,cl->rgba.g,cl->rgba.b,cl->rgba.a));
 }
 
 /* 
@@ -212,8 +198,7 @@ Destroy ancillary data for Color object.
 
 void
 ICL_DESTROY(i_color *cl) {
-  dIMCTX;
-  im_log((aIMCTX, 1,"ICL_DESTROY(cl* %p)\n",cl));
+  mm_log((1,"ICL_DESTROY(cl* %p)\n",cl));
   myfree(cl);
 }
 
@@ -224,16 +209,15 @@ ICL_DESTROY(i_color *cl) {
 */
 i_fcolor *i_fcolor_new(double r, double g, double b, double a) {
   i_fcolor *cl = NULL;
-  dIMCTX;
 
-  im_log((aIMCTX, 1,"i_fcolor_new(r %g,g %g,b %g,a %g)\n", r, g, b, a));
+  mm_log((1,"i_fcolor_new(r %g,g %g,b %g,a %g)\n", r, g, b, a));
 
-  if ( (cl=mymalloc(sizeof(i_fcolor))) == NULL) im_fatal(aIMCTX, 2,"malloc() error\n");
+  if ( (cl=mymalloc(sizeof(i_fcolor))) == NULL) i_fatal(2,"malloc() error\n");
   cl->rgba.r = r;
   cl->rgba.g = g;
   cl->rgba.b = b;
   cl->rgba.a = a;
-  im_log((aIMCTX, 1,"(%p) <- i_fcolor_new\n",cl));
+  mm_log((1,"(%p) <- i_fcolor_new\n",cl));
 
   return cl;
 }
@@ -259,8 +243,7 @@ Free image data.
 
 void
 i_img_exorcise(i_img *im) {
-  dIMCTXim(im);
-  im_log((aIMCTX,1,"i_img_exorcise(im* %p)\n",im));
+  mm_log((1,"i_img_exorcise(im* %p)\n",im));
   i_tags_destroy(&im->tags);
   if (im->i_f_destroy)
     (im->i_f_destroy)(im);
@@ -286,11 +269,9 @@ Destroy an image object
 
 void
 i_img_destroy(i_img *im) {
-  dIMCTXim(im);
-  im_log((aIMCTX, 1,"i_img_destroy(im %p)\n",im));
+  mm_log((1,"i_img_destroy(im %p)\n",im));
   i_img_exorcise(im);
   if (im) { myfree(im); }
-  im_context_refdec(aIMCTX, "img_destroy");
 }
 
 /* 
@@ -316,13 +297,12 @@ info is an array of 4 integers with the following values:
 
 void
 i_img_info(i_img *im, i_img_dim *info) {
-  dIMCTXim(im);
-  im_log((aIMCTX,1,"i_img_info(im %p)\n",im));
+  mm_log((1,"i_img_info(im %p)\n",im));
   if (im != NULL) {
-    im_log((aIMCTX,1,"i_img_info: xsize=%" i_DF " ysize=%" i_DF " channels=%d "
+    mm_log((1,"i_img_info: xsize=%" i_DF " ysize=%" i_DF " channels=%d "
            "mask=%ud\n",
            i_DFc(im->xsize), i_DFc(im->ysize), im->channels,im->ch_mask));
-    im_log((aIMCTX,1,"i_img_info: idata=%p\n",im->idata));
+    mm_log((1,"i_img_info: idata=%p\n",im->idata));
     info[0] = im->xsize;
     info[1] = im->ysize;
     info[2] = im->channels;
@@ -421,9 +401,8 @@ i_copyto_trans(i_img *im,i_img *src,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img
   i_color pv;
   i_img_dim x,y,t,ttx,tty,tt;
   int ch;
-  dIMCTXim(im);
 
-  im_log((aIMCTX, 1,"i_copyto_trans(im* %p,src %p, p1(" i_DFp "), p2(" i_DFp "), "
+  mm_log((1,"i_copyto_trans(im* %p,src %p, p1(" i_DFp "), p2(" i_DFp "), "
          "to(" i_DFp "), trans* %p)\n",
          im, src, i_DFcp(x1, y1), i_DFcp(x2, y2), i_DFcp(tx, ty), trans));
   
@@ -466,10 +445,9 @@ Returns: i_img *
 i_img *
 i_copy(i_img *src) {
   i_img_dim y, y1, x1;
-  dIMCTXim(src);
   i_img *im = i_sametype(src, src->xsize, src->ysize);
 
-  im_log((aIMCTX,1,"i_copy(src %p)\n", src));
+  mm_log((1,"i_copy(src %p)\n", src));
 
   if (!im)
     return NULL;
@@ -555,10 +533,9 @@ i_scaleaxis(i_img *im, double Value, int Axis) {
   i_img *new_img;
   int has_alpha = i_img_has_alpha(im);
   int color_chans = i_img_color_channels(im);
-  dIMCTXim(im);
 
   i_clear_error();
-  im_log((aIMCTX, 1,"i_scaleaxis(im %p,Value %.2f,Axis %d)\n",im,Value,Axis));
+  mm_log((1,"i_scaleaxis(im %p,Value %.2f,Axis %d)\n",im,Value,Axis));
 
   if (Axis == XAXIS) {
     hsize = (i_img_dim)(0.5 + im->xsize * Value);
@@ -583,7 +560,7 @@ i_scaleaxis(i_img *im, double Value, int Axis) {
     iEnd = hsize;
   }
   
-  new_img = i_img_8_new(hsize, vsize, im->channels);
+  new_img = i_img_empty_ch(NULL, hsize, vsize, im->channels);
   if (!new_img) {
     i_push_error(0, "cannot create output image");
     return NULL;
@@ -733,7 +710,7 @@ i_scaleaxis(i_img *im, double Value, int Axis) {
   myfree(l0);
   myfree(l1);
 
-  im_log((aIMCTX, 1,"(%p) <- i_scaleaxis\n", new_img));
+  mm_log((1,"(%p) <- i_scaleaxis\n", new_img));
 
   return new_img;
 }
@@ -756,9 +733,8 @@ i_scale_nn(i_img *im, double scx, double scy) {
   i_img_dim nxsize,nysize,nx,ny;
   i_img *new_img;
   i_color val;
-  dIMCTXim(im);
 
-  im_log((aIMCTX, 1,"i_scale_nn(im %p,scx %.2f,scy %.2f)\n",im,scx,scy));
+  mm_log((1,"i_scale_nn(im %p,scx %.2f,scy %.2f)\n",im,scx,scy));
 
   nxsize = (i_img_dim) ((double) im->xsize * scx);
   if (nxsize < 1) {
@@ -779,7 +755,7 @@ i_scale_nn(i_img *im, double scx, double scy) {
     i_ppix(new_img,nx,ny,&val);
   }
 
-  im_log((aIMCTX, 1,"(%p) <- i_scale_nn\n",new_img));
+  mm_log((1,"(%p) <- i_scale_nn\n",new_img));
 
   return new_img;
 }
@@ -797,10 +773,7 @@ For paletted images the palette is copied from the source.
 =cut
 */
 
-i_img *
-i_sametype(i_img *src, i_img_dim xsize, i_img_dim ysize) {
-  dIMCTXim(src);
-
+i_img *i_sametype(i_img *src, i_img_dim xsize, i_img_dim ysize) {
   if (src->type == i_direct_type) {
     if (src->bits == 8) {
       return i_img_empty_ch(NULL, xsize, ysize, src->channels);
@@ -843,10 +816,7 @@ For paletted images the equivalent direct type is returned.
 =cut
 */
 
-i_img *
-i_sametype_chans(i_img *src, i_img_dim xsize, i_img_dim ysize, int channels) {
-  dIMCTXim(src);
-
+i_img *i_sametype_chans(i_img *src, i_img_dim xsize, i_img_dim ysize, int channels) {
   if (src->bits == 8) {
     return i_img_empty_ch(NULL, xsize, ysize, channels);
   }
@@ -887,9 +857,8 @@ i_transform(i_img *im, int *opx,int opxl,int *opy,int opyl,double parm[],int par
   i_img_dim nxsize,nysize,nx,ny;
   i_img *new_img;
   i_color val;
-  dIMCTXim(im);
   
-  im_log((aIMCTX, 1,"i_transform(im %p, opx %p, opxl %d, opy %p, opyl %d, parm %p, parmlen %d)\n",im,opx,opxl,opy,opyl,parm,parmlen));
+  mm_log((1,"i_transform(im %p, opx %p, opxl %d, opy %p, opyl %d, parm %p, parmlen %d)\n",im,opx,opxl,opy,opyl,parm,parmlen));
 
   nxsize = im->xsize;
   nysize = im->ysize ;
@@ -911,7 +880,7 @@ i_transform(i_img *im, int *opx,int opxl,int *opy,int opyl,double parm[],int par
     i_ppix(new_img,nx,ny,&val);
   }
 
-  im_log((aIMCTX, 1,"(%p) <- i_transform\n",new_img));
+  mm_log((1,"(%p) <- i_transform\n",new_img));
   return new_img;
 }
 
@@ -934,15 +903,14 @@ i_img_diff(i_img *im1,i_img *im2) {
   int ch, chb;
   float tdiff;
   i_color val1,val2;
-  dIMCTXim(im1);
 
-  im_log((aIMCTX, 1,"i_img_diff(im1 %p,im2 %p)\n",im1,im2));
+  mm_log((1,"i_img_diff(im1 %p,im2 %p)\n",im1,im2));
 
   xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
   yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
   chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
 
-  im_log((aIMCTX, 1,"i_img_diff: b=(" i_DFp ") chb=%d\n",
+  mm_log((1,"i_img_diff: b=(" i_DFp ") chb=%d\n",
          i_DFcp(xb,yb), chb));
 
   tdiff=0;
@@ -952,7 +920,7 @@ i_img_diff(i_img *im1,i_img *im2) {
 
     for(ch=0;ch<chb;ch++) tdiff+=(val1.channel[ch]-val2.channel[ch])*(val1.channel[ch]-val2.channel[ch]);
   }
-  im_log((aIMCTX, 1,"i_img_diff <- (%.2f)\n",tdiff));
+  mm_log((1,"i_img_diff <- (%.2f)\n",tdiff));
   return tdiff;
 }
 
@@ -977,15 +945,14 @@ i_img_diffd(i_img *im1,i_img *im2) {
   int ch, chb;
   double tdiff;
   i_fcolor val1,val2;
-  dIMCTXim(im1);
 
-  im_log((aIMCTX, 1,"i_img_diffd(im1 %p,im2 %p)\n",im1,im2));
+  mm_log((1,"i_img_diffd(im1 %p,im2 %p)\n",im1,im2));
 
   xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
   yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
   chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
 
-  im_log((aIMCTX, 1,"i_img_diffd: b(" i_DFp ") chb=%d\n",
+  mm_log((1,"i_img_diffd: b(" i_DFp ") chb=%d\n",
          i_DFcp(xb, yb), chb));
 
   tdiff=0;
@@ -998,7 +965,7 @@ i_img_diffd(i_img *im1,i_img *im2) {
       tdiff += sdiff * sdiff;
     }
   }
-  im_log((aIMCTX, 1,"i_img_diffd <- (%.2f)\n",tdiff));
+  mm_log((1,"i_img_diffd <- (%.2f)\n",tdiff));
 
   return tdiff;
 }
@@ -1008,18 +975,17 @@ i_img_samef(i_img *im1,i_img *im2, double epsilon, char const *what) {
   i_img_dim x,y,xb,yb;
   int ch, chb;
   i_fcolor val1,val2;
-  dIMCTXim(im1);
 
   if (what == NULL)
     what = "(null)";
 
-  im_log((aIMCTX,1,"i_img_samef(im1 %p,im2 %p, epsilon %g, what '%s')\n", im1, im2, epsilon, what));
+  mm_log((1,"i_img_samef(im1 %p,im2 %p, epsilon %g, what '%s')\n", im1, im2, epsilon, what));
 
   xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
   yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
   chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
 
-  im_log((aIMCTX, 1,"i_img_samef: b(" i_DFp ") chb=%d\n",
+  mm_log((1,"i_img_samef: b(" i_DFp ") chb=%d\n",
          i_DFcp(xb, yb), chb));
 
   for(y = 0; y < yb; y++) {
@@ -1030,14 +996,14 @@ i_img_samef(i_img *im1,i_img *im2, double epsilon, char const *what) {
       for(ch = 0; ch < chb; ch++) {
        double sdiff = val1.channel[ch] - val2.channel[ch];
        if (fabs(sdiff) > epsilon) {
-         im_log((aIMCTX, 1,"i_img_samef <- different %g @(" i_DFp ")\n",
+         mm_log((1,"i_img_samef <- different %g @(" i_DFp ")\n",
                  sdiff, i_DFcp(x, y)));
          return 0;
        }
       }
     }
   }
-  im_log((aIMCTX, 1,"i_img_samef <- same\n"));
+  mm_log((1,"i_img_samef <- same\n"));
 
   return 1;
 }
@@ -1052,7 +1018,6 @@ i_haar(i_img *im) {
   int ch,c;
   i_img *new_img,*new_img2;
   i_color val1,val2,dval1,dval2;
-  dIMCTXim(im);
   
   mx=im->xsize;
   my=im->ysize;
@@ -1464,8 +1429,6 @@ int i_findcolor_forward(i_img *im, const i_color *color, i_palidx *entry) {
 i_img_dim
 i_gsamp_bits_fb(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned *samps, 
                const int *chans, int chan_count, int bits) {
-  dIMCTXim(im);
-
   if (bits < 1 || bits > 32) {
     i_push_error(0, "Invalid bits, must be 1..32");
     return -1;
@@ -1490,7 +1453,7 @@ i_gsamp_bits_fb(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned *samp
       /* make sure we have good channel numbers */
       for (ch = 0; ch < chan_count; ++ch) {
         if (chans[ch] < 0 || chans[ch] >= im->channels) {
-          im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
+          i_push_errorf(0, "No channel %d in this image", chans[ch]);
           return -1;
         }
       }
index a62c6761f5f579b596fcd9e1cb02eaeec7c6862c..aba1399bac3a2091f5a368cccea275bd90226948 100644 (file)
--- a/imager.h
+++ b/imager.h
@@ -2,11 +2,12 @@
 #define _IMAGE_H_
 
 #include "imconfig.h"
-#include "immacros.h"
 #include "imio.h"
 #include "iolayer.h"
+#include "log.h"
 #include "stackmach.h"
 
+
 #ifndef _MSC_VER
 #include <unistd.h>
 #endif
@@ -47,20 +48,22 @@ extern void i_hsv_to_rgbf(i_fcolor *color);
 extern void i_rgb_to_hsv(i_color *color);
 extern void i_hsv_to_rgb(i_color *color);
 
-i_img *im_img_8_new(pIMCTX, i_img_dim x,i_img_dim y,int ch);
-#define i_img_empty(im, x, y) i_img_empty_ch((im), (x), (y), 3)
-i_img *im_img_empty_ch(pIMCTX, i_img *im,i_img_dim x,i_img_dim y,int ch);
-#define i_img_empty_ch(im, x, y, ch) im_img_empty_ch(aIMCTX, (im), (x), (y), (ch))
+i_img *i_img_8_new(i_img_dim x,i_img_dim y,int ch);
+i_img *i_img_new( void );
+i_img *i_img_empty(i_img *im,i_img_dim x,i_img_dim y);
+i_img *i_img_empty_ch(i_img *im,i_img_dim x,i_img_dim y,int ch);
 void   i_img_exorcise(i_img *im);
 void   i_img_destroy(i_img *im);
-i_img *im_img_alloc(pIMCTX);
-void im_img_init(pIMCTX, i_img *im);
+i_img *i_img_alloc(void);
+void i_img_init(i_img *im);
 
 void   i_img_info(i_img *im,i_img_dim *info);
 
 extern i_img *i_sametype(i_img *im, i_img_dim xsize, i_img_dim ysize);
 extern i_img *i_sametype_chans(i_img *im, i_img_dim xsize, i_img_dim ysize, int channels);
 
+i_img *i_img_pal_new(i_img_dim x, i_img_dim y, int ch, int maxpal);
+
 /* Image feature settings */
 
 void   i_img_setmask    (i_img *im,int ch_mask);
@@ -71,36 +74,74 @@ i_img_dim i_img_get_height(i_img *im);
 
 /* Base functions */
 
-extern int (i_ppix)(i_img *im,i_img_dim x,i_img_dim y, const i_color *val);
-extern int (i_gpix)(i_img *im,i_img_dim x,i_img_dim y,i_color *val);
-extern int (i_ppixf)(i_img *im,i_img_dim x,i_img_dim y, const i_fcolor *val);
-extern int (i_gpixf)(i_img *im,i_img_dim x,i_img_dim y,i_fcolor *val);
-
-extern i_img_dim (i_plin)(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
-                         const i_color *vals);
-extern i_img_dim (i_glin)(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
-                         i_color *vals);
-extern i_img_dim (i_plinf)(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
-                          const i_fcolor *vals);
-extern i_img_dim (i_glinf)(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, 
-                          i_fcolor *vals);
-extern i_img_dim (i_gsamp)(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
-                          i_sample_t *samp, const int *chans, int chan_count);
-extern i_img_dim
-(i_gsampf)(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samp,
-          const int *chans, int chan_count);
-extern i_img_dim
-(i_gpal)(i_img *im, i_img_dim x, i_img_dim r, i_img_dim y, i_palidx *vals);
-extern i_img_dim
-(i_ppal)(i_img *im, i_img_dim x, i_img_dim r, i_img_dim y, const i_palidx *vals);
-extern int (i_addcolors)(i_img *im, const i_color *colors, int count);
-extern int (i_getcolors)(i_img *im, int i, i_color *, int count);
-extern int (i_colorcount)(i_img *im);
-extern int (i_maxcolors)(i_img *im);
-extern int (i_findcolor)(i_img *im, const i_color *color, i_palidx *entry);
-extern int (i_setcolors)(i_img *im, int index, const i_color *colors, 
+extern int i_ppix(i_img *im,i_img_dim x,i_img_dim y, const i_color *val);
+extern int i_gpix(i_img *im,i_img_dim x,i_img_dim y,i_color *val);
+extern int i_ppixf(i_img *im,i_img_dim x,i_img_dim y, const i_fcolor *val);
+extern int i_gpixf(i_img *im,i_img_dim x,i_img_dim y,i_fcolor *val);
+
+#define i_ppix(im, x, y, val) (((im)->i_f_ppix)((im), (x), (y), (val)))
+#define i_gpix(im, x, y, val) (((im)->i_f_gpix)((im), (x), (y), (val)))
+#define i_ppixf(im, x, y, val) (((im)->i_f_ppixf)((im), (x), (y), (val)))
+#define i_gpixf(im, x, y, val) (((im)->i_f_gpixf)((im), (x), (y), (val)))
+
+extern i_img_dim i_plin(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_color *vals);
+extern i_img_dim i_glin(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_color *vals);
+extern i_img_dim i_plinf(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fcolor *vals);
+extern i_img_dim i_glinf(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *vals);
+extern i_img_dim i_gsamp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_sample_t *samp, 
+                   const int *chans, int chan_count);
+extern i_img_dim i_gsampf(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samp, 
+                   const int *chans, int chan_count);
+extern i_img_dim i_gpal(i_img *im, i_img_dim x, i_img_dim r, i_img_dim y, i_palidx *vals);
+extern i_img_dim i_ppal(i_img *im, i_img_dim x, i_img_dim r, i_img_dim y, const i_palidx *vals);
+extern int i_addcolors(i_img *im, const i_color *colors, int count);
+extern int i_getcolors(i_img *im, int i, i_color *, int count);
+extern int i_colorcount(i_img *im);
+extern int i_maxcolors(i_img *im);
+extern int i_findcolor(i_img *im, const i_color *color, i_palidx *entry);
+extern int i_setcolors(i_img *im, int index, const i_color *colors, 
                        int count);
 
+#define i_plin(im, l, r, y, val) (((im)->i_f_plin)(im, l, r, y, val))
+#define i_glin(im, l, r, y, val) (((im)->i_f_glin)(im, l, r, y, val))
+#define i_plinf(im, l, r, y, val) (((im)->i_f_plinf)(im, l, r, y, val))
+#define i_glinf(im, l, r, y, val) (((im)->i_f_glinf)(im, l, r, y, val))
+
+#define i_gsamp(im, l, r, y, samps, chans, count) \
+  (((im)->i_f_gsamp)((im), (l), (r), (y), (samps), (chans), (count)))
+#define i_gsampf(im, l, r, y, samps, chans, count) \
+  (((im)->i_f_gsampf)((im), (l), (r), (y), (samps), (chans), (count)))
+
+#define i_gsamp_bits(im, l, r, y, samps, chans, count, bits) \
+  (((im)->i_f_gsamp_bits) ? ((im)->i_f_gsamp_bits)((im), (l), (r), (y), (samps), (chans), (count), (bits)) : -1)
+#define i_psamp_bits(im, l, r, y, samps, chans, count, bits) \
+  (((im)->i_f_psamp_bits) ? ((im)->i_f_psamp_bits)((im), (l), (r), (y), (samps), (chans), (count), (bits)) : -1)
+
+#define i_findcolor(im, color, entry) \
+  (((im)->i_f_findcolor) ? ((im)->i_f_findcolor)((im), (color), (entry)) : 0)
+
+#define i_gpal(im, l, r, y, vals) \
+  (((im)->i_f_gpal) ? ((im)->i_f_gpal)((im), (l), (r), (y), (vals)) : 0)
+#define i_ppal(im, l, r, y, vals) \
+  (((im)->i_f_ppal) ? ((im)->i_f_ppal)((im), (l), (r), (y), (vals)) : 0)
+#define i_addcolors(im, colors, count) \
+  (((im)->i_f_addcolors) ? ((im)->i_f_addcolors)((im), (colors), (count)) : -1)
+#define i_getcolors(im, index, color, count) \
+  (((im)->i_f_getcolors) ? \
+   ((im)->i_f_getcolors)((im), (index), (color), (count)) : 0)
+#define i_setcolors(im, index, color, count) \
+  (((im)->i_f_setcolors) ? \
+   ((im)->i_f_setcolors)((im), (index), (color), (count)) : 0)
+#define i_colorcount(im) \
+  (((im)->i_f_colorcount) ? ((im)->i_f_colorcount)(im) : -1)
+#define i_maxcolors(im) \
+  (((im)->i_f_maxcolors) ? ((im)->i_f_maxcolors)(im) : -1)
+#define i_findcolor(im, color, entry) \
+  (((im)->i_f_findcolor) ? ((im)->i_f_findcolor)((im), (color), (entry)) : 0)
+
+#define i_img_virtual(im) ((im)->virtual)
+#define i_img_type(im) ((im)->type)
+#define i_img_bits(im) ((im)->bits)
 
 extern i_fill_t *i_new_fill_solidf(const i_fcolor *c, int combine);
 extern i_fill_t *i_new_fill_solid(const i_color *c, int combine);
@@ -184,9 +225,9 @@ int i_img_samef(i_img *im1,i_img *im2, double epsilon, const char *what);
 
 /* font routines */
 
-#ifdef HAVE_LIBTT
+undef_int i_init_fonts( int t1log );
 
-extern void i_tt_start(void);
+#ifdef HAVE_LIBTT
 
 TT_Fonthandle* i_tt_new(const char *fontname);
 void i_tt_destroy( TT_Fonthandle *handle );
@@ -206,15 +247,14 @@ extern void i_quant_makemap(i_quantize *quant, i_img **imgs, int count);
 extern i_palidx *i_quant_translate(i_quantize *quant, i_img *img);
 extern void i_quant_transparent(i_quantize *quant, i_palidx *indices, i_img *img, i_palidx trans_index);
 
-i_img *im_img_pal_new(pIMCTX, i_img_dim x, i_img_dim y, int ch, int maxpal);
-
+extern i_img *i_img_pal_new(i_img_dim x, i_img_dim y, int channels, int maxpal);
 extern i_img *i_img_to_pal(i_img *src, i_quantize *quant);
 extern i_img *i_img_to_rgb(i_img *src);
 extern i_img *i_img_masked_new(i_img *targ, i_img *mask, i_img_dim x, i_img_dim y, 
                                i_img_dim w, i_img_dim h);
-extern i_img *im_img_16_new(pIMCTX, i_img_dim x, i_img_dim y, int ch);
+extern i_img *i_img_16_new(i_img_dim x, i_img_dim y, int ch);
 extern i_img *i_img_to_rgb16(i_img *im);
-extern i_img *im_img_double_new(pIMCTX, i_img_dim x, i_img_dim y, int ch);
+extern i_img *i_img_double_new(i_img_dim x, i_img_dim y, int ch);
 extern i_img *i_img_to_drgb(i_img *im);
 
 extern int i_img_is_monochrome(i_img *im, int *zero_is_white);
@@ -291,6 +331,36 @@ i_new_fill_fount(double xa, double ya, double xb, double yb,
 
 void malloc_state( void );
 
+/* this is sort of obsolete now */
+
+typedef struct {
+  undef_int (*i_has_format)(char *frmt);
+  i_color*(*ICL_set)(i_color *cl,unsigned char r,unsigned char g,unsigned char b,unsigned char a);
+  void (*ICL_info)(const i_color *cl);
+
+  i_img*(*i_img_new)( void );
+  i_img*(*i_img_empty)(i_img *im,i_img_dim x,i_img_dim y);
+  i_img*(*i_img_empty_ch)(i_img *im,i_img_dim x,i_img_dim y,int ch);
+  void(*i_img_exorcise)(i_img *im);
+
+  void(*i_img_info)(i_img *im,i_img_dim *info);
+  
+  void(*i_img_setmask)(i_img *im,int ch_mask);
+  int (*i_img_getmask)(i_img *im);
+  
+  /*
+  int (*i_ppix)(i_img *im,i_img_dim x,i_img_dim y,i_color *val);
+  int (*i_gpix)(i_img *im,i_img_dim x,i_img_dim y,i_color *val);
+  */
+  void(*i_box)(i_img *im,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2,const i_color *val);
+  void(*i_line)(i_img *im,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2,const i_color *val,int endp);
+  void(*i_arc)(i_img *im,i_img_dim x,i_img_dim y,double rad,double d1,double d2,const i_color *val);
+  void(*i_copyto)(i_img *im,i_img *src,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2,i_img_dim tx,i_img_dim ty);
+  void(*i_copyto_trans)(i_img *im,i_img *src,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2,i_img_dim tx,i_img_dim ty,const i_color *trans);
+  int(*i_rubthru)(i_img *im,i_img *src,i_img_dim tx,i_img_dim ty, i_img_dim src_minx, i_img_dim src_miny, i_img_dim src_maxx, i_img_dim src_maxy);
+
+} symbol_table_t;
+
 #include "imerror.h"
 
 /* image tag processing */
@@ -328,11 +398,11 @@ extern void i_tags_print(i_img_tags *tags);
 
 /* image file limits */
 extern int
-im_set_image_file_limits(im_context_t ctx, i_img_dim width, i_img_dim height, size_t bytes);
+i_set_image_file_limits(i_img_dim width, i_img_dim height, size_t bytes);
 extern int
-im_get_image_file_limits(im_context_t ctx, i_img_dim *width, i_img_dim *height, size_t *bytes);
+i_get_image_file_limits(i_img_dim *width, i_img_dim *height, size_t *bytes);
 extern int
-im_int_check_image_file_limits(im_context_t ctx, i_img_dim width, i_img_dim height, int channels, size_t sample_size);
+i_int_check_image_file_limits(i_img_dim width, i_img_dim height, int channels, size_t sample_size);
 
 /* memory allocation */
 void* mymalloc(size_t size);
@@ -358,6 +428,7 @@ void  malloc_state(void);
 #endif /* IMAGER_MALLOC_DEBUG */
 
 #include "imrender.h"
+#include "immacros.h"
 
 extern void
 i_adapt_colors(int dest_channels, int src_channels, i_color *colors, 
@@ -381,23 +452,6 @@ extern int
 i_gsampf_bg(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samples, 
           int out_channels, i_fcolor const *bg);
 
-/* context object management */
-extern im_context_t im_context_new(void);
-extern void im_context_refinc(im_context_t ctx, const char *where);
-extern void im_context_refdec(im_context_t ctx, const char *where);
-extern im_context_t im_context_clone(im_context_t ctx, const char *where);
-extern im_slot_t im_context_slot_new(im_slot_destroy_t, const char *);
-extern void *im_context_slot_get(im_context_t ctx, im_slot_t slot);
-extern int im_context_slot_set(im_context_t ctx, im_slot_t slot, void *);
-
-extern im_context_t (*im_get_context)(void);
-
-/* mutex API */
-extern i_mutex_t i_mutex_new(void);
-extern void i_mutex_destroy(i_mutex_t m);
-extern void i_mutex_lock(i_mutex_t m);
-extern void i_mutex_unlock(i_mutex_t m);
-
 #include "imio.h"
 
 #endif
index 6ef28a7aa2ceef5db09a1a80644e69aa3878b547..347e2abdfec225bd98f8aea88e7cdd557e890b37 100644 (file)
--- a/imageri.h
+++ b/imageri.h
@@ -6,7 +6,6 @@
 #define IMAGEI_H_
 
 #include "imager.h"
-#include <stddef.h>
 
 /* wrapper functions that implement the floating point sample version of a 
    function in terms of the 8-bit sample version
@@ -112,29 +111,4 @@ i_img_dim i_abs(i_img_dim x);
 
 #define color_to_grey(col) ((col)->rgb.r * 0.222  + (col)->rgb.g * 0.707 + (col)->rgb.b * 0.071)
 
-#define IM_ERROR_COUNT 20
-typedef struct im_context_tag {
-  int error_sp;
-  size_t error_alloc[IM_ERROR_COUNT];
-  i_errmsg error_stack[IM_ERROR_COUNT];
-#ifdef IMAGER_LOG
-  int log_level;
-  FILE *lg_file;
-  const char *filename;
-  int line;
-#endif
-
-  /* file size limits */
-  i_img_dim max_width, max_height;
-  size_t max_bytes;
-
-  /* per context storage */
-  size_t slot_alloc;
-  void **slots;
-
-  ptrdiff_t refcount;
-} im_context_struct;
-
-#define DEF_BYTES_LIMIT 0x40000000
-
 #endif
index a7419ea5bc93625356446cbcfb6e56bbac602142..d9ad0eb4f7541d8b525311e4148037ed4d08a5c1 100644 (file)
@@ -6,11 +6,6 @@
 
 #define MAXCHANNELS 4
 
-typedef struct im_context_tag *im_context_t;
-
-typedef ptrdiff_t im_slot_t;
-typedef void (*im_slot_destroy_t)(void *);
-
 /* used for palette indices in some internal code (which might be 
    exposed at some point
 */
@@ -288,14 +283,6 @@ i_f_psamp - implements psamp() for this image.
 
 i_f_psampf - implements psamp() for this image.
 
-=item *
-
-C<im_data> - image specific data internal to Imager.
-
-=item *
-
-C<context> - the Imager API context this image belongs to.
-
 =back
 
 =cut
@@ -348,9 +335,6 @@ struct i_img_ {
   i_f_psampf_t i_f_psampf;
 
   void *im_data;
-
-  /* 0.91 */
-  im_context_t context;
 };
 
 /* ext_data for paletted images
@@ -556,18 +540,6 @@ typedef enum {
   ic_color
 } i_combine_t;
 
-/*
-=item i_mutex_t
-X<i_mutex>
-=category mutex
-=synopsis i_mutex_t mutex;
-
-Opaque type for Imager's mutex API.
-
-=cut
- */
-typedef struct i_mutex_tag *i_mutex_t;
-
 /*
    describes an axis of a MM font.
    Modelled on FT2's FT_MM_Axis.
@@ -709,13 +681,6 @@ enum {
 
 #include "iolayert.h"
 
-/* error message information returned by im_errors() */
-
-typedef struct {
-  char *msg;
-  int code;
-} i_errmsg;
-
 typedef struct i_render_tag i_render;
 
 #ifdef IMAGER_FORMAT_ATTR
index e1cfc943e79f3d76b8a7016d1f5f92b5db05e79c..da56df1f53d49aa9c57bba3ce5e536197b51d673 100644 (file)
--- a/imerror.h
+++ b/imerror.h
@@ -5,21 +5,23 @@
    see error.c for documentation
    the error information is currently global
 */
+typedef struct {
+  char *msg;
+  int code;
+} i_errmsg;
+
 typedef void (*i_error_cb)(int code, char const *msg);
 typedef void (*i_failed_cb)(i_errmsg *msgs);
 extern i_error_cb i_set_error_cb(i_error_cb);
 extern i_failed_cb i_set_failed_cb(i_failed_cb);
 extern void i_set_argv0(char const *);
 extern int i_set_errors_fatal(int new_fatal);
-extern i_errmsg *im_errors(pIMCTX);
+extern i_errmsg *i_errors(void);
 
-extern void im_push_error(pIMCTX, int code, char const *msg);
-#ifndef IMAGER_NO_CONTEXT
+extern void i_push_error(int code, char const *msg);
 extern void i_push_errorf(int code, char const *fmt, ...) I_FORMAT_ATTR(2, 3);
-#endif
-extern void im_push_errorf(pIMCTX, int code, char const *fmt, ...) I_FORMAT_ATTR(3, 4);
-extern void im_push_errorvf(im_context_t ctx, int code, char const *fmt, va_list);
-extern void im_clear_error(pIMCTX);
+extern void i_push_errorvf(int code, char const *fmt, va_list);
+extern void i_clear_error(void);
 extern int i_failed(int code, char const *msg);
 
 #endif
diff --git a/imext.c b/imext.c
index 9b85350eb3c194916a9015e27d6ae3a0e829f319..6afaadd40dfe62ab75f97a62dc65d4aff448bc58 100644 (file)
--- a/imext.c
+++ b/imext.c
@@ -2,8 +2,6 @@
 #include "imager.h"
 #include "imio.h"
 
-static im_context_t get_context(void);
-
 /*
  DON'T ADD CASTS TO THESE
 */
@@ -20,10 +18,10 @@ im_ext_funcs imager_function_table =
     myfree_file_line,
     myrealloc_file_line,
 
-    im_img_8_new,
-    im_img_16_new,
-    im_img_double_new,
-    im_img_pal_new,
+    i_img_8_new,
+    i_img_16_new,
+    i_img_double_new,
+    i_img_pal_new,
     i_img_destroy,
     i_sametype,
     i_sametype_chans,
@@ -60,10 +58,10 @@ im_ext_funcs imager_function_table =
     i_quant_translate,
     i_quant_transparent,
 
-    im_clear_error,
-    im_push_error,
+    i_clear_error,
+    i_push_error,
     i_push_errorf,
-    im_push_errorvf,
+    i_push_errorvf,
 
     i_tags_new,
     i_tags_set,
@@ -101,9 +99,9 @@ im_ext_funcs imager_function_table =
     i_rubthru,
 
     /* IMAGER_API_LEVEL 2 functions */
-    im_set_image_file_limits,
-    im_get_image_file_limits,
-    im_int_check_image_file_limits,
+    i_set_image_file_limits,
+    i_get_image_file_limits,
+    i_int_check_image_file_limits,
 
     i_flood_fill_border,
     i_flood_cfill_border,
@@ -118,8 +116,8 @@ im_ext_funcs imager_function_table =
     i_loog,
 
     /* IMAGER_API_LEVEL 4 functions */
-    im_img_alloc,
-    im_img_init,
+    i_img_alloc,
+    i_img_init,
 
     /* IMAGER_API_LEVEL 5 functions */
     i_img_is_monochrome,
@@ -147,28 +145,12 @@ im_ext_funcs imager_function_table =
     i_io_close,
     i_io_set_buffered,
     i_io_gets,
-    im_io_new_fd,
-    im_io_new_bufchain,
-    im_io_new_buffer,
-    im_io_new_cb,
+    io_new_fd,
+    io_new_bufchain,
+    io_new_buffer,
+    io_new_cb,
     io_slurp,
-    io_glue_destroy,
-
-    /* level 8 */
-    get_context,
-    im_push_errorf,
-    im_lhead,
-    im_loog,
-    im_context_refinc,
-    im_context_refdec,
-    im_errors,
-    i_mutex_new,
-    i_mutex_destroy,
-    i_mutex_lock,
-    i_mutex_unlock,
-    im_context_slot_new,
-    im_context_slot_set,
-    im_context_slot_get
+    io_glue_destroy
   };
 
 /* in general these functions aren't called by Imager internally, but
@@ -568,20 +550,3 @@ int
   return i_setcolors(im, index, colors, count);
 }
 
-/*
-=item im_get_context()
-
-Retrieve the context object for the current thread.
-
-Inside Imager itself this is just a function pointer, which the
-F<Imager.xs> BOOT handler initializes for use within perl.  If you're
-taking the Imager code and embedding it elsewhere you need to
-initialize the C<im_get_context> pointer at some point.
-
-=cut
-*/
-
-static im_context_t
-get_context(void) {
-  return im_get_context();
-}
diff --git a/imext.h b/imext.h
index 3cab9e32ceb60b20fc1b974aa3c1d344039aab4e..8c42b903aa2078d9160831e0d2198e84215614f6 100644 (file)
--- a/imext.h
+++ b/imext.h
@@ -30,10 +30,6 @@ extern im_ext_funcs *imager_function_ext_table;
 /* just for use here */
 #define im_extt imager_function_ext_table
 
-#define im_get_context() ((im_extt->f_im_get_context)())
-#define im_context_refinc(ctx, where) ((im_extt->f_im_context_refinc)((ctx), (where)))
-#define im_context_refdec(ctx, where) ((im_extt->f_im_context_refdec)((ctx), (where)))
-
 #ifdef IMAGER_DEBUG_MALLOC
 
 #define mymalloc(size) ((im_extt->f_mymalloc_file_line)((size), __FILE__, __LINE__))
@@ -48,10 +44,10 @@ extern im_ext_funcs *imager_function_ext_table;
 
 #endif
 
-#define im_img_8_new(ctx, xsize, ysize, channels) ((im_extt->f_im_img_8_new)((ctx), (xsize), (ysize), (channels)))
-#define im_img_16_new(ctx, xsize, ysize, channels) ((im_extt->f_im_img_16_new)((ctx), (xsize), (ysize), (channels)))
-#define im_img_double_new(ctx, xsize, ysize, channels) ((im_extt->f_im_img_double_new)((ctx), (xsize), (ysize), (channels)))
-#define im_img_pal_new(ctx, xsize, ysize, channels, maxpal) ((im_extt->f_im_img_pal_new)((ctx), (xsize), (ysize), (channels), (maxpal)))
+#define i_img_8_new(xsize, ysize, channels) ((im_extt->f_i_img_8_new)((xsize), (ysize), (channels)))
+#define i_img_16_new(xsize, ysize, channels) ((im_extt->f_i_img_16_new)((xsize), (ysize), (channels)))
+#define i_img_double_new(xsize, ysize, channels) ((im_extt->f_i_img_double_new)((xsize), (ysize), (channels)))
+#define i_img_pal_new(xsize, ysize, channels, maxpal) ((im_extt->f_i_img_pal_new)((xsize), (ysize), (channels), (maxpal)))
 
 #define i_img_destroy(im) ((im_extt->f_i_img_destroy)(im))
 #define i_sametype(im, xsize, ysize) ((im_extt->f_i_sametype)((im), (xsize), (ysize)))
@@ -62,8 +58,43 @@ extern im_ext_funcs *imager_function_ext_table;
 #define IMAGER_DIRECT_IMAGE_CALLS 1
 #endif
 
-#if !IMAGER_DIRECT_IMAGE_CALLS
+#if IMAGER_DIRECT_IMAGE_CALLS
+#define i_ppix(im, x, y, val) (((im)->i_f_ppix)((im), (x), (y), (val)))
+#define i_gpix(im, x, y, val) (((im)->i_f_gpix)((im), (x), (y), (val)))
+#define i_ppixf(im, x, y, val) (((im)->i_f_ppixf)((im), (x), (y), (val)))
+#define i_gpixf(im, x, y, val) (((im)->i_f_gpixf)((im), (x), (y), (val)))
+#define i_plin(im, l, r, y, val) (((im)->i_f_plin)(im, l, r, y, val))
+#define i_glin(im, l, r, y, val) (((im)->i_f_glin)(im, l, r, y, val))
+#define i_plinf(im, l, r, y, val) (((im)->i_f_plinf)(im, l, r, y, val))
+#define i_glinf(im, l, r, y, val) (((im)->i_f_glinf)(im, l, r, y, val))
 
+#define i_gsamp(im, l, r, y, samps, chans, count) \
+  (((im)->i_f_gsamp)((im), (l), (r), (y), (samps), (chans), (count)))
+#define i_gsampf(im, l, r, y, samps, chans, count) \
+  (((im)->i_f_gsampf)((im), (l), (r), (y), (samps), (chans), (count)))
+
+#define i_findcolor(im, color, entry) \
+  (((im)->i_f_findcolor) ? ((im)->i_f_findcolor)((im), (color), (entry)) : 0)
+
+#define i_gpal(im, l, r, y, vals) \
+  (((im)->i_f_gpal) ? ((im)->i_f_gpal)((im), (l), (r), (y), (vals)) : 0)
+#define i_ppal(im, l, r, y, vals) \
+  (((im)->i_f_ppal) ? ((im)->i_f_ppal)((im), (l), (r), (y), (vals)) : 0)
+#define i_addcolors(im, colors, count) \
+  (((im)->i_f_addcolors) ? ((im)->i_f_addcolors)((im), (colors), (count)) : -1)
+#define i_getcolors(im, index, color, count) \
+  (((im)->i_f_getcolors) ? \
+   ((im)->i_f_getcolors)((im), (index), (color), (count)) : 0)
+#define i_setcolors(im, index, color, count) \
+  (((im)->i_f_setcolors) ? \
+   ((im)->i_f_setcolors)((im), (index), (color), (count)) : 0)
+#define i_colorcount(im) \
+  (((im)->i_f_colorcount) ? ((im)->i_f_colorcount)(im) : -1)
+#define i_maxcolors(im) \
+  (((im)->i_f_maxcolors) ? ((im)->i_f_maxcolors)(im) : -1)
+#define i_findcolor(im, color, entry) \
+  (((im)->i_f_findcolor) ? ((im)->i_f_findcolor)((im), (color), (entry)) : 0)
+#else
 #define i_ppix(im, x, y, val) ((im_extt->f_i_ppix)((im), (x), (y), (val)))
 #define i_gpix(im, x, y, val) ((im_extt->f_i_gpix)((im), (x), (y), (val)))
 #define i_ppixf(im, x, y, val) ((im_extt->f_i_ppixf)((im), (x), (y), (val)))
@@ -103,11 +134,11 @@ extern im_ext_funcs *imager_function_ext_table;
 #define i_quant_transparent(quant, indices, img, trans_index) \
   ((im_extt->f_i_quant_transparent)((quant), (indices), (img), (trans_index)))
 
-#define im_clear_error(ctx) ((im_extt->f_im_clear_error)(ctx))
-#define im_push_error(ctx, code, msg) ((im_extt->f_im_push_error)((ctx), (code), (msg)))
+#define i_clear_error() ((im_extt->f_i_clear_error)())
+#define i_push_error(code, msg) ((im_extt->f_i_push_error)((code), (msg)))
 #define i_push_errorf (im_extt->f_i_push_errorf)
-#define im_push_errorvf(ctx, code, fmt, list)          \
-  ((im_extt->f_im_push_errorvf)((ctx), (code), (fmt), (list)))
+#define i_push_errorvf(code, fmt, list) \
+  ((im_extt->f_i_push_errorvf)((code), (fmt), (list)))
 
 #define i_tags_new(tags) ((im_extt->f_i_tags_new)(tags))
 #define i_tags_set(tags, name, data, size) \
@@ -163,12 +194,12 @@ extern im_ext_funcs *imager_function_ext_table;
 #define i_rubthru(im, src, tx, ty, src_minx, src_miny, src_maxx, src_maxy) \
   ((im_extt->f_i_rubthru)((im), (src), (tx), (ty), (src_minx), (src_miny), (src_maxx), (src_maxy)))
 
-#define im_set_image_file_limits(ctx, max_width, max_height, max_bytes)        \
-  ((im_extt->f_im_set_image_file_limits)((max_width), (max_height), (max_bytes)))
-#define im_get_image_file_limits(ctx, pmax_width, pmax_height, pmax_bytes) \
-  ((im_extt->f_im_get_image_file_limits)((ctx), (pmax_width), (pmax_height), (pmax_bytes)))
-#define im_int_check_image_file_limits(ctx, width, height, channels, sample_size) \
-  ((im_extt->f_im_int_check_image_file_limits)((ctx), (width), (height), (channels), (sample_size)))
+#define i_set_image_file_limits(max_width, max_height, max_bytes) \
+  ((im_extt->f_i_set_image_file_limits)((max_width), (max_height), (max_bytes)))
+#define i_get_image_file_limits(pmax_width, pmax_height, pmax_bytes) \
+  ((im_extt->f_i_get_image_file_limits)((pmax_width), (pmax_height), (pmax_bytes)))
+#define i_int_check_image_file_limits(width, height, channels, sample_size) \
+  ((im_extt->f_i_int_check_image_file_limits)((width), (height), (channels), (sample_size)))
 
 #define i_img_setmask(img, mask) ((im_extt->f_i_img_setmask)((img), (mask)))
 #define i_img_getmask(img) ((im_extt->f_i_img_getmask)(img))
@@ -177,11 +208,9 @@ extern im_ext_funcs *imager_function_ext_table;
 #define i_img_get_height(img) ((im_extt->f_i_img_get_height)(img))
 #define i_lhead(file, line) ((im_extt->f_i_lhead)((file), (line)))
 #define i_loog (im_extt->f_i_loog)
-#define im_lhead(ctx, file, line) ((im_extt->f_im_lhead)((ctx), (file), (line)))
-#define im_loog (im_extt->f_im_loog)
 
-#define im_img_alloc(ctx) ((im_extt->f_im_img_alloc)(ctx))
-#define im_img_init(ctx, img) ((im_extt->fm_i_img_init)((ctx), (img)))
+#define i_img_alloc() ((im_extt->f_i_img_alloc)())
+#define i_img_init(img) ((im_extt->f_i_img_init)(img))
 
 #define i_img_is_monochrome(img, zero_is_white) ((im_extt->f_i_img_is_monochrome)((img), (zero_is_white)))
 
@@ -218,33 +247,20 @@ extern im_ext_funcs *imager_function_ext_table;
 #define i_io_close (im_extt->f_i_io_close)
 #define i_io_set_buffered (im_extt->f_i_io_set_buffered)
 #define i_io_gets (im_extt->f_i_io_gets)
-#define im_io_new_fd(ctx, fd) ((im_extt->f_im_io_new_fd)(ctx, fd))
-#define im_io_new_bufchain(ctx) ((im_extt->f_im_io_new_bufchain)(ctx))
-#define im_io_new_buffer(ctx, data, len, closecb, closedata)           \
-  ((im_extt->f_im_io_new_buffer)((ctx), (data), (len), (closecb), (closedata)))
-#define im_io_new_cb(ctx, p, readcb, writecb, seekcb, closecb, destroycb) \
-  ((im_extt->f_im_io_new_cb)((ctx), (p), (readcb), (writecb), (seekcb), (closecb), (destroycb)))
+#define io_new_fd(fd) ((im_extt->f_io_new_fd)(fd))
+#define io_new_bufchain() ((im_extt->f_io_new_bufchain)())
+#define io_new_buffer(data, len, closecb, closedata) \
+  ((im_extt->f_io_new_buffer)((data), (len), (closecb), (closedata)))
+#define io_new_cb(p, readcb, writecb, seekcb, closecb, destroycb) \
+  ((im_extt->f_io_new_cb)((p), (readcb), (writecb), (seekcb), (closecb), (destroycb)))
 #define io_slurp(ig, datap) ((im_extt->f_io_slurp)((ig), (datap)))
 #define io_glue_destroy(ig) ((im_extt->f_io_glue_destroy)(ig))
 
-#define i_mutex_new() ((im_extt->f_i_mutex_new)())
-#define i_mutex_destroy(m) ((im_extt->f_i_mutex_destroy)(m))
-#define i_mutex_lock(m) ((im_extt->f_i_mutex_lock)(m))
-#define i_mutex_unlock(m) ((im_extt->f_i_mutex_unlock)(m))
-
-#define im_context_slot_new(destructor, where) ((im_extt->f_im_context_slot_new)((destructor), (where)))
-#define im_context_slot_get(ctx, slot) ((im_extt->f_im_context_slot_get)((ctx), (slot)))
-#define im_context_slot_set(ctx, slot, value) ((im_extt->f_im_context_slot_set)((ctx), (slot), (value)))
-
-#define im_push_errorf (im_extt->f_im_push_errorf)
-
 #ifdef IMAGER_LOG
-#ifndef IMAGER_NO_CONTEXT
 #define mm_log(x) { i_lhead(__FILE__,__LINE__); i_loog x; } 
-#endif
-#define im_log(x) { im_lhead(aIMCTX, __FILE__,__LINE__); im_loog x; } 
 #else
 #define mm_log(x)
 #endif
 
+
 #endif
index b92d4ee82bd75150216ae38aeb5deb1454f9aae1..9fd1a0c045c253c57cbac68727a8e231fae534ce 100644 (file)
  Version 5 changed the return types of i_get_file_background() and
  i_get_file_backgroundf() from void to int.
 
- Version 6 added 
-
 */
-#define IMAGER_API_VERSION 6
+#define IMAGER_API_VERSION 5
 
 /*
  IMAGER_API_LEVEL is the level of the structure.  New function pointers
@@ -50,10 +48,10 @@ typedef struct {
   void  (*f_myfree_file_line)(void *p, char*file, int line);
   void* (*f_myrealloc_file_line)(void *p, size_t newsize, char* file,int line);
 
-  i_img *(*f_im_img_8_new)(im_context_t ctx, i_img_dim xsize, i_img_dim ysize, int channels);
-  i_img *(*f_im_img_16_new)(im_context_t ctx, i_img_dim xsize, i_img_dim ysize, int channels);
-  i_img *(*f_im_img_double_new)(im_context_t ctx, i_img_dim xsize, i_img_dim ysize, int channels);
-  i_img *(*f_im_img_pal_new)(im_context_t ctx, i_img_dim xsize, i_img_dim ysize, int channels, int maxpal);
+  i_img *(*f_i_img_8_new)(i_img_dim xsize, i_img_dim ysize, int channels);
+  i_img *(*f_i_img_16_new)(i_img_dim xsize, i_img_dim ysize, int channels);
+  i_img *(*f_i_img_double_new)(i_img_dim xsize, i_img_dim ysize, int channels);
+  i_img *(*f_i_img_pal_new)(i_img_dim xsize, i_img_dim ysize, int channels, int maxpal);
   void (*f_i_img_destroy)(i_img *im);
   i_img *(*f_i_sametype)(i_img *im, i_img_dim xsize, i_img_dim ysize);
   i_img *(*f_i_sametype_chans)(i_img *im, i_img_dim xsize, i_img_dim ysize, int channels);
@@ -104,10 +102,10 @@ typedef struct {
   void (*f_i_quant_transparent)(i_quantize *quant, i_palidx *indices, 
                                 i_img *img, i_palidx trans_index);
 
-  void (*f_im_clear_error)(im_context_t ctx);
-  void (*f_im_push_error)(im_context_t ctx, int code, char const *msg);
+  void (*f_i_clear_error)(void);
+  void (*f_i_push_error)(int code, char const *msg);
   void (*f_i_push_errorf)(int code, char const *fmt, ...);
-  void (*f_im_push_errorvf)(im_context_t ctx, int code, char const *fmt, va_list);
+  void (*f_i_push_errorvf)(int code, char const *fmt, va_list);
   
   void (*f_i_tags_new)(i_img_tags *tags);
   int (*f_i_tags_set)(i_img_tags *tags, char const *name, char const *data, 
@@ -154,9 +152,9 @@ typedef struct {
   int (*f_i_rubthru)(i_img *im, i_img *src, i_img_dim tx, i_img_dim ty, i_img_dim src_minx, i_img_dim src_miny, i_img_dim src_maxx, i_img_dim src_maxy);
 
   /* IMAGER_API_LEVEL 2 functions */
-  int (*f_im_set_image_file_limits)(im_context_t ctx, i_img_dim width, i_img_dim height, size_t bytes);
-  int (*f_im_get_image_file_limits)(im_context_t ctx, i_img_dim *width, i_img_dim *height, size_t *bytes);
-  int (*f_im_int_check_image_file_limits)(im_context_t ctx, i_img_dim width, i_img_dim height, int channels, size_t sample_size);
+  int (*f_i_set_image_file_limits)(i_img_dim width, i_img_dim height, size_t bytes);
+  int (*f_i_get_image_file_limits)(i_img_dim *width, i_img_dim *height, size_t *bytes);
+  int (*f_i_int_check_image_file_limits)(i_img_dim width, i_img_dim height, int channels, size_t sample_size);
   int (*f_i_flood_fill_border)(i_img *im, i_img_dim seedx, i_img_dim seedy, const i_color *dcol, const i_color *border);
   int (*f_i_flood_cfill_border)(i_img *im, i_img_dim seedx, i_img_dim seedy, i_fill_t *fill, const i_color *border);
 
@@ -170,8 +168,8 @@ typedef struct {
   void (*f_i_loog)(int level, const char *msg, ...);
 
   /* IMAGER_API_LEVEL 4 functions will be added here */
-  i_img *(*f_im_img_alloc)(im_context_t ctx);
-  void (*f_im_img_init)(im_context_t ctx, i_img *);
+  i_img *(*f_i_img_alloc)(void);
+  void (*f_i_img_init)(i_img *);
 
   /* IMAGER_API_LEVEL 5 functions will be added here */
   /* added i_psampf?_bits macros */
@@ -212,29 +210,15 @@ typedef struct {
   int (*f_i_io_set_buffered)(io_glue *ig, int buffered);
   ssize_t (*f_i_io_gets)(io_glue *ig, char *, size_t, int);
 
-  i_io_glue_t *(*f_im_io_new_fd)(im_context_t ctx, int fd);
-  i_io_glue_t *(*f_im_io_new_bufchain)(im_context_t ctx);
-  i_io_glue_t *(*f_im_io_new_buffer)(im_context_t ctx, const char *data, size_t len, i_io_closebufp_t closecb, void *closedata);
-  i_io_glue_t *(*f_im_io_new_cb)(im_context_t ctx, void *p, i_io_readl_t readcb, i_io_writel_t writecb, i_io_seekl_t seekcb, i_io_closel_t closecb, i_io_destroyl_t destroycb);
+  i_io_glue_t *(*f_io_new_fd)(int fd);
+  i_io_glue_t *(*f_io_new_bufchain)(void);
+  i_io_glue_t *(*f_io_new_buffer)(const char *data, size_t len, i_io_closebufp_t closecb, void *closedata);
+  i_io_glue_t *(*f_io_new_cb)(void *p, i_io_readl_t readcb, i_io_writel_t writecb, i_io_seekl_t seekcb, i_io_closel_t closecb, i_io_destroyl_t destroycb);
   size_t (*f_io_slurp)(i_io_glue_t *ig, unsigned char **c);
   void (*f_io_glue_destroy)(i_io_glue_t *ig);
 
   /* IMAGER_API_LEVEL 8 functions will be added here */
-  im_context_t (*f_im_get_context)(void);
-
-  void (*f_im_push_errorf)(im_context_t , int code, char const *fmt, ...);
-  void (*f_im_lhead)( im_context_t, const char *file, int line  );
-  void (*f_im_loog)(im_context_t, int level,const char *msg, ... ) I_FORMAT_ATTR(3,4);
-  void (*f_im_context_refinc)(im_context_t, const char *where);
-  void (*f_im_context_refdec)(im_context_t, const char *where);
-  i_errmsg *(*f_im_errors)(im_context_t);
-  i_mutex_t (*f_i_mutex_new)(void);
-  void (*f_i_mutex_destroy)(i_mutex_t m);
-  void (*f_i_mutex_lock)(i_mutex_t m);
-  void (*f_i_mutex_unlock)(i_mutex_t m);
-  im_slot_t (*f_im_context_slot_new)(im_slot_destroy_t, const char *);
-  int (*f_im_context_slot_set)(im_context_t, im_slot_t, void *);
-  void *(*f_im_context_slot_get)(im_context_t, im_slot_t);
+
 } im_ext_funcs;
 
 #define PERL_FUNCTION_TABLE_NAME "Imager::__ext_func_table"
diff --git a/img16.c b/img16.c
index 1b3e45212cbbfa67ccda868f42eb356124bf66d6..970a173168545b99f34b6d3b50b4b8c5b817b6b6 100644 (file)
--- a/img16.c
+++ b/img16.c
@@ -20,8 +20,6 @@ sample image type to work with.
 =cut
 */
 
-#define IMAGER_NO_CONTEXT
-
 #include "imager.h"
 #include "imageri.h"
 
@@ -150,40 +148,36 @@ typedef unsigned short i_sample16_t;
      ((((i_sample16_t *)(bytes))[offset]+127) / 257)
 
 /*
-=item im_img_16_new(ctx, x, y, ch)
-X<im_img_16_new API>X<i_img_16_new API>
+=item i_img_16_new(x, y, ch)
+
 =category Image creation/destruction
-=synopsis i_img *img = im_img_16_new(aIMCTX, width, height, channels);
 =synopsis i_img *img = i_img_16_new(width, height, channels);
 
 Create a new 16-bit/sample image.
 
 Returns the image on success, or NULL on failure.
 
-Also callable as C<i_img_16_new(x, y, ch)>
-
 =cut
 */
 
-i_img *
-im_img_16_new(pIMCTX, i_img_dim x, i_img_dim y, int ch) {
+i_img *i_img_16_new(i_img_dim x, i_img_dim y, int ch) {
   i_img *im;
   size_t bytes, line_bytes;
 
-  im_log((aIMCTX, 1,"i_img_16_new(x %" i_DF ", y %" i_DF ", ch %d)\n",
+  mm_log((1,"i_img_16_new(x %" i_DF ", y %" i_DF ", ch %d)\n",
          i_DFc(x), i_DFc(y), ch));
 
   if (x < 1 || y < 1) {
-    im_push_error(aIMCTX, 0, "Image sizes must be positive");
+    i_push_error(0, "Image sizes must be positive");
     return NULL;
   }
   if (ch < 1 || ch > MAXCHANNELS) {
-    im_push_errorf(aIMCTX, 0, "channels must be between 1 and %d", MAXCHANNELS);
+    i_push_errorf(0, "channels must be between 1 and %d", MAXCHANNELS);
     return NULL;
   }
   bytes =  x * y * ch * 2;
   if (bytes / y / ch / 2 != x) {
-    im_push_errorf(aIMCTX, 0, "integer overflow calculating image allocation");
+    i_push_errorf(0, "integer overflow calculating image allocation");
     return NULL;
   }
   
@@ -192,11 +186,11 @@ im_img_16_new(pIMCTX, i_img_dim x, i_img_dim y, int ch) {
      working with the image */
   line_bytes = sizeof(i_fcolor) * x;
   if (line_bytes / x != sizeof(i_fcolor)) {
-    im_push_error(aIMCTX, 0, "integer overflow calculating scanline allocation");
+    i_push_error(0, "integer overflow calculating scanline allocation");
     return NULL;
   }
 
-  im = im_img_alloc(aIMCTX);
+  im = i_img_alloc();
   *im = IIM_base_16bit_direct;
   i_tags_new(&im->tags);
   im->xsize = x;
@@ -207,7 +201,7 @@ im_img_16_new(pIMCTX, i_img_dim x, i_img_dim y, int ch) {
   im->idata = mymalloc(im->bytes);
   memset(im->idata, 0, im->bytes);
 
-  im_img_init(aIMCTX, im);
+  i_img_init(im);
 
   return im;
 }
@@ -229,9 +223,8 @@ i_img_to_rgb16(i_img *im) {
   i_img *targ;
   i_fcolor *line;
   i_img_dim y;
-  dIMCTXim(im);
 
-  targ = im_img_16_new(aIMCTX, im->xsize, im->ysize, im->channels);
+  targ = i_img_16_new(im->xsize, im->ysize, im->channels);
   if (!targ)
     return NULL;
   line = mymalloc(sizeof(i_fcolor) * im->xsize);
@@ -442,8 +435,7 @@ static i_img_dim i_gsamp_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i
       /* make sure we have good channel numbers */
       for (ch = 0; ch < chan_count; ++ch) {
         if (chans[ch] < 0 || chans[ch] >= im->channels) {
-         dIMCTXim(im);
-          im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
+          i_push_errorf(0, "No channel %d in this image", chans[ch]);
           return 0;
         }
       }
@@ -457,8 +449,7 @@ static i_img_dim i_gsamp_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i
     }
     else {
       if (chan_count <= 0 || chan_count > im->channels) {
-       dIMCTXim(im);
-       im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels", 
+       i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels", 
                      chan_count);
        return 0;
       }
@@ -495,8 +486,7 @@ static i_img_dim i_gsampf_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
       /* make sure we have good channel numbers */
       for (ch = 0; ch < chan_count; ++ch) {
         if (chans[ch] < 0 || chans[ch] >= im->channels) {
-         dIMCTXim(im);
-          im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
+          i_push_errorf(0, "No channel %d in this image", chans[ch]);
           return 0;
         }
       }
@@ -510,8 +500,7 @@ static i_img_dim i_gsampf_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
     }
     else {
       if (chan_count <= 0 || chan_count > im->channels) {
-       dIMCTXim(im);
-       im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels", 
+       i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels", 
                      chan_count);
        return 0;
       }
@@ -553,8 +542,7 @@ i_gsamp_bits_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned *sam
       /* make sure we have good channel numbers */
       for (ch = 0; ch < chan_count; ++ch) {
         if (chans[ch] < 0 || chans[ch] >= im->channels) {
-         dIMCTXim(im);
-          im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
+          i_push_errorf(0, "No channel %d in this image", chans[ch]);
           return -1;
         }
       }
@@ -568,7 +556,6 @@ i_gsamp_bits_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned *sam
     }
     else {
       if (chan_count <= 0 || chan_count > im->channels) {
-       dIMCTXim(im);
        i_push_error(0, "Invalid channel count");
        return -1;
       }
@@ -584,7 +571,6 @@ i_gsamp_bits_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned *sam
     return count;
   }
   else {
-    dIMCTXim(im);
     i_push_error(0, "Image position outside of image");
     return -1;
   }
@@ -598,7 +584,6 @@ i_psamp_bits_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned cons
   i_img_dim off;
 
   if (bits != 16) {
-    dIMCTXim(im);
     i_push_error(0, "Invalid bits for 16-bit image");
     return -1;
   }
@@ -614,8 +599,7 @@ i_psamp_bits_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned cons
       /* make sure we have good channel numbers */
       for (ch = 0; ch < chan_count; ++ch) {
         if (chans[ch] < 0 || chans[ch] >= im->channels) {
-         dIMCTXim(im);
-          im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
+          i_push_errorf(0, "No channel %d in this image", chans[ch]);
           return -1;
         }
       }
@@ -631,7 +615,6 @@ i_psamp_bits_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned cons
     }
     else {
       if (chan_count <= 0 || chan_count > im->channels) {
-       dIMCTXim(im);
        i_push_error(0, "Invalid channel count");
        return -1;
       }
@@ -649,7 +632,6 @@ i_psamp_bits_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned cons
     return count;
   }
   else {
-    dIMCTXim(im);
     i_push_error(0, "Image position outside of image");
     return -1;
   }
@@ -689,8 +671,7 @@ i_psamp_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
       int all_in_mask = 1;
       for (ch = 0; ch < chan_count; ++ch) {
         if (chans[ch] < 0 || chans[ch] >= im->channels) {
-         dIMCTXim(im);
-          im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
+          i_push_errorf(0, "No channel %d in this image", chans[ch]);
           return -1;
         }
        if (!((1 << chans[ch]) & im->ch_mask))
@@ -720,8 +701,7 @@ i_psamp_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
     }
     else {
       if (chan_count <= 0 || chan_count > im->channels) {
-       dIMCTXim(im);
-       im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels", 
+       i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels", 
                      chan_count);
        return -1;
       }
@@ -741,7 +721,6 @@ i_psamp_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
     return count;
   }
   else {
-    dIMCTXim(im);
     i_push_error(0, "Image position outside of image");
     return -1;
   }
@@ -781,8 +760,7 @@ i_psampf_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
       int all_in_mask = 1;
       for (ch = 0; ch < chan_count; ++ch) {
         if (chans[ch] < 0 || chans[ch] >= im->channels) {
-         dIMCTXim(im);
-          im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
+          i_push_errorf(0, "No channel %d in this image", chans[ch]);
           return -1;
         }
        if (!((1 << chans[ch]) & im->ch_mask))
@@ -815,8 +793,7 @@ i_psampf_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
     }
     else {
       if (chan_count <= 0 || chan_count > im->channels) {
-       dIMCTXim(im);
-       im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels", 
+       i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels", 
                      chan_count);
        return -1;
       }
@@ -838,7 +815,6 @@ i_psampf_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
     return count;
   }
   else {
-    dIMCTXim(im);
     i_push_error(0, "Image position outside of image");
     return -1;
   }
diff --git a/img8.c b/img8.c
index c7804733f30794829ea7f9c643cca3f3fc8e5a42..d905fa2c55d6a0fc6e01ef488b19c3d3e48e25e1 100644 (file)
--- a/img8.c
+++ b/img8.c
@@ -1,5 +1,3 @@
-#define IMAGER_NO_CONTEXT
-
 #include "imager.h"
 #include "imageri.h"
 
@@ -82,10 +80,10 @@ static i_img IIM_base_8bit_direct =
   }*/
 
 /*
-=item im_img_8_new(ctx, x, y, ch)
-X<im_img_8_new API>X<i_img_8_new API>
+=item i_img_8_new(x, y, ch)
+
 =category Image creation/destruction
-=synopsis i_img *img = im_img_8_new(aIMCTX, width, height, channels);
+
 =synopsis i_img *img = i_img_8_new(width, height, channels);
 
 Creates a new image object I<x> pixels wide, and I<y> pixels high with
@@ -94,16 +92,49 @@ I<ch> channels.
 =cut
 */
 
+
 i_img *
-im_img_8_new(pIMCTX, i_img_dim x,i_img_dim y,int ch) {
+i_img_8_new(i_img_dim x,i_img_dim y,int ch) {
   i_img *im;
 
-  im_log((aIMCTX, 1,"im_img_8_new(x %" i_DF ", y %" i_DF ", ch %d)\n",
+  mm_log((1,"IIM_new(x %" i_DF ", y %" i_DF ", ch %d)\n",
          i_DFc(x), i_DFc(y), ch));
 
-  im = im_img_empty_ch(aIMCTX, NULL,x,y,ch);
+  im=i_img_empty_ch(NULL,x,y,ch);
+  
+  mm_log((1,"(%p) <- IIM_new\n",im));
+  return im;
+}
+
+/* 
+=item i_img_new()
+
+Create new image reference - notice that this isn't an object yet and
+this should be fixed asap.
+
+=cut
+*/
+
+
+i_img *
+i_img_new() {
+  i_img *im;
+  
+  mm_log((1,"i_img_struct()\n"));
+
+  im = i_img_alloc();
+  
+  *im = IIM_base_8bit_direct;
+  im->xsize=0;
+  im->ysize=0;
+  im->channels=3;
+  im->ch_mask=MAXINT;
+  im->bytes=0;
+  im->idata=NULL;
+
+  i_img_init(im);
   
-  im_log((aIMCTX, 1,"(%p) <- IIM_new\n",im));
+  mm_log((1,"(%p) <- i_img_struct\n",im));
   return im;
 }
 
@@ -124,10 +155,10 @@ Should this just call i_img_empty_ch()?
 */
 
 i_img *
-im_img_empty(pIMCTX, i_img *im,i_img_dim x,i_img_dim y) {
-  im_log((aIMCTX, 1,"i_img_empty(*im %p, x %" i_DF ", y %" i_DF ")\n",
+i_img_empty(i_img *im,i_img_dim x,i_img_dim y) {
+  mm_log((1,"i_img_empty(*im %p, x %" i_DF ", y %" i_DF ")\n",
          im, i_DFc(x), i_DFc(y)));
-  return im_img_empty_ch(aIMCTX, im, x, y, 3);
+  return i_img_empty_ch(im, x, y, 3);
 }
 
 /* 
@@ -144,29 +175,29 @@ Re-new image reference
 */
 
 i_img *
-im_img_empty_ch(pIMCTX, i_img *im,i_img_dim x,i_img_dim y,int ch) {
+i_img_empty_ch(i_img *im,i_img_dim x,i_img_dim y,int ch) {
   size_t bytes;
 
-  im_log((aIMCTX, 1,"i_img_empty_ch(*im %p, x %" i_DF ", y %" i_DF ", ch %d)\n",
+  mm_log((1,"i_img_empty_ch(*im %p, x %" i_DF ", y %" i_DF ", ch %d)\n",
          im, i_DFc(x), i_DFc(y), ch));
 
   if (x < 1 || y < 1) {
-    im_push_error(aIMCTX, 0, "Image sizes must be positive");
+    i_push_error(0, "Image sizes must be positive");
     return NULL;
   }
   if (ch < 1 || ch > MAXCHANNELS) {
-    im_push_errorf(aIMCTX, 0, "channels must be between 1 and %d", MAXCHANNELS);
+    i_push_errorf(0, "channels must be between 1 and %d", MAXCHANNELS);
     return NULL;
   }
   /* check this multiplication doesn't overflow */
   bytes = x*y*ch;
   if (bytes / y / ch != x) {
-    im_push_errorf(aIMCTX, 0, "integer overflow calculating image allocation");
+    i_push_errorf(0, "integer overflow calculating image allocation");
     return NULL;
   }
 
   if (im == NULL)
-    im = im_img_alloc(aIMCTX);
+    im = i_img_alloc();
 
   memcpy(im, &IIM_base_8bit_direct, sizeof(i_img));
   i_tags_new(&im->tags);
@@ -176,14 +207,14 @@ im_img_empty_ch(pIMCTX, i_img *im,i_img_dim x,i_img_dim y,int ch) {
   im->ch_mask  = MAXINT;
   im->bytes=bytes;
   if ( (im->idata=mymalloc(im->bytes)) == NULL) 
-    im_fatal(aIMCTX, 2,"malloc() error\n"); 
+    i_fatal(2,"malloc() error\n"); 
   memset(im->idata,0,(size_t)im->bytes);
   
   im->ext_data = NULL;
 
-  im_img_init(aIMCTX, im);
+  i_img_init(im);
   
-  im_log((aIMCTX, 1,"(%p) <- i_img_empty_ch\n",im));
+  mm_log((1,"(%p) <- i_img_empty_ch\n",im));
   return im;
 }
 
@@ -472,8 +503,7 @@ i_gsamp_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_sample_t *samps,
       /* make sure we have good channel numbers */
       for (ch = 0; ch < chan_count; ++ch) {
         if (chans[ch] < 0 || chans[ch] >= im->channels) {
-         dIMCTXim(im);
-          im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
+          i_push_errorf(0, "No channel %d in this image", chans[ch]);
           return 0;
         }
       }
@@ -487,8 +517,7 @@ i_gsamp_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_sample_t *samps,
     }
     else {
       if (chan_count <= 0 || chan_count > im->channels) {
-       dIMCTXim(im);
-       im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels", 
+       i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels", 
                      chan_count);
        return 0;
       }
@@ -528,8 +557,7 @@ i_gsampf_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samps,
   unsigned char *data;
   for (ch = 0; ch < chan_count; ++ch) {
     if (chans[ch] < 0 || chans[ch] >= im->channels) {
-      dIMCTXim(im);
-      im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
+      i_push_errorf(0, "No channel %d in this image", chans[ch]);
     }
   }
   if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
@@ -543,8 +571,7 @@ i_gsampf_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samps,
       /* make sure we have good channel numbers */
       for (ch = 0; ch < chan_count; ++ch) {
         if (chans[ch] < 0 || chans[ch] >= im->channels) {
-         dIMCTXim(im);
-          im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
+          i_push_errorf(0, "No channel %d in this image", chans[ch]);
           return 0;
         }
       }
@@ -558,8 +585,7 @@ i_gsampf_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samps,
     }
     else {
       if (chan_count <= 0 || chan_count > im->channels) {
-       dIMCTXim(im);
-       im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels", 
+       i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels", 
                      chan_count);
        return 0;
       }
@@ -612,8 +638,7 @@ i_psamp_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
       int all_in_mask = 1;
       for (ch = 0; ch < chan_count; ++ch) {
         if (chans[ch] < 0 || chans[ch] >= im->channels) {
-         dIMCTXim(im);
-          im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
+          i_push_errorf(0, "No channel %d in this image", chans[ch]);
           return -1;
         }
        if (!((1 << chans[ch]) & im->ch_mask))
@@ -642,8 +667,7 @@ i_psamp_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
     }
     else {
       if (chan_count <= 0 || chan_count > im->channels) {
-       dIMCTXim(im);
-       im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels", 
+       i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels", 
                      chan_count);
        return -1;
       }
@@ -663,7 +687,6 @@ i_psamp_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
     return count;
   }
   else {
-    dIMCTXim(im);
     i_push_error(0, "Image position outside of image");
     return -1;
   }
@@ -703,8 +726,7 @@ i_psampf_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
       int all_in_mask = 1;
       for (ch = 0; ch < chan_count; ++ch) {
         if (chans[ch] < 0 || chans[ch] >= im->channels) {
-         dIMCTXim(im);
-          im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
+          i_push_errorf(0, "No channel %d in this image", chans[ch]);
           return -1;
         }
        if (!((1 << chans[ch]) & im->ch_mask))
@@ -734,8 +756,7 @@ i_psampf_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
     }
     else {
       if (chan_count <= 0 || chan_count > im->channels) {
-       dIMCTXim(im);
-       im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels", 
+       i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels", 
                      chan_count);
        return -1;
       }
@@ -755,7 +776,6 @@ i_psampf_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
     return count;
   }
   else {
-    dIMCTXim(im);
     i_push_error(0, "Image position outside of image");
     return -1;
   }
index fdd3302022dc6e7cf987675e730d387373db21e9..fe1ad6248b54ab58610018fb0b8eb916be20fb25 100644 (file)
@@ -20,7 +20,6 @@ sample image type to work with.
 =cut
 */
 
-#define IMAGER_NO_CONTEXT
 #include "imager.h"
 #include "imageri.h"
 
@@ -92,41 +91,36 @@ static i_img IIM_base_double_direct =
 };
 
 /*
-=item im_img_double_new(ctx, x, y, ch)
-X<im_img_double_new API>X<i_img_double_new API>
+=item i_img_double_new(i_img_dim x, i_img_dim y, int ch)
 =category Image creation/destruction
-=synopsis i_img *img = im_img_double_new(aIMCTX, width, height, channels);
 =synopsis i_img *img = i_img_double_new(width, height, channels);
 
 Creates a new double per sample image.
 
-Also callable as C<i_img_double_new(width, height, channels)>.
-
 =cut
 */
-i_img *
-im_img_double_new(pIMCTX, i_img_dim x, i_img_dim y, int ch) {
+i_img *i_img_double_new(i_img_dim x, i_img_dim y, int ch) {
   size_t bytes;
   i_img *im;
 
-  im_log((aIMCTX, 1,"i_img_double_new(x %" i_DF ", y %" i_DF ", ch %d)\n",
+  mm_log((1,"i_img_double_new(x %" i_DF ", y %" i_DF ", ch %d)\n",
          i_DFc(x), i_DFc(y), ch));
 
   if (x < 1 || y < 1) {
-    im_push_error(aIMCTX, 0, "Image sizes must be positive");
+    i_push_error(0, "Image sizes must be positive");
     return NULL;
   }
   if (ch < 1 || ch > MAXCHANNELS) {
-    im_push_errorf(aIMCTX, 0, "channels must be between 1 and %d", MAXCHANNELS);
+    i_push_errorf(0, "channels must be between 1 and %d", MAXCHANNELS);
     return NULL;
   }
   bytes = x * y * ch * sizeof(double);
   if (bytes / y / ch / sizeof(double) != x) {
-    im_push_errorf(aIMCTX, 0, "integer overflow calculating image allocation");
+    i_push_errorf(0, "integer overflow calculating image allocation");
     return NULL;
   }
   
-  im = im_img_alloc(aIMCTX);
+  im = i_img_alloc();
   *im = IIM_base_double_direct;
   i_tags_new(&im->tags);
   im->xsize = x;
@@ -136,7 +130,7 @@ im_img_double_new(pIMCTX, i_img_dim x, i_img_dim y, int ch) {
   im->ext_data = NULL;
   im->idata = mymalloc(im->bytes);
   memset(im->idata, 0, im->bytes);
-  im_img_init(aIMCTX, im);
+  i_img_init(im);
   
   return im;
 }
@@ -338,8 +332,7 @@ static i_img_dim i_gsamp_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
       /* make sure we have good channel numbers */
       for (ch = 0; ch < chan_count; ++ch) {
         if (chans[ch] < 0 || chans[ch] >= im->channels) {
-         dIMCTXim(im);
-          im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
+          i_push_errorf(0, "No channel %d in this image", chans[ch]);
           return 0;
         }
       }
@@ -353,8