]> git.imager.perl.org - imager.git/blob - context.c
08e9a4d72c28a20ca91b3efb72c009a36cc59a94
[imager.git] / context.c
1 #include "imageri.h"
2 #include <stdio.h>
3
4 /*
5 =item im_context_new()
6
7 Create a new Imager context object.
8
9 =cut
10 */
11
12 im_context_t
13 im_context_new(void) {
14   im_context_t ctx = malloc(sizeof(im_context_struct));
15   int i;
16
17   if (!ctx)
18     return NULL;
19   
20   ctx->error_sp = IM_ERROR_COUNT-1;
21   for (i = 0; i < IM_ERROR_COUNT; ++i) {
22     ctx->error_alloc[i] = 0;
23     ctx->error_stack[i].msg = NULL;
24     ctx->error_stack[i].code = 0;
25   }
26 #ifdef IMAGER_LOG
27   ctx->log_level = 0;
28   ctx->lg_file = NULL;
29 #endif
30   ctx->max_width = 0;
31   ctx->max_height = 0;
32   ctx->max_bytes = DEF_BYTES_LIMIT;
33
34   ctx->refcount = 1;
35
36 #ifdef IMAGER_TRACE_CONTEXT
37   fprintf(stderr, "im_context: created %p\n", ctx);
38 #endif
39
40   return ctx;
41 }
42
43 /*
44 =item im_context_refinc(ctx, where)
45 X<im_context_refinc API>
46 =section Context objects
47 =synopsis im_context_refinc(aIMCTX, "a description");
48
49 Add a new reference to the context.
50
51 =cut
52 */
53
54 void
55 im_context_refinc(im_context_t ctx, const char *where) {
56   ++ctx->refcount;
57
58 #ifdef IMAGER_TRACE_CONTEXT
59   fprintf(stderr, "im_context:%s: refinc %p (count now %lu)\n", where,
60           ctx, (unsigned long)ctx->refcount);
61 #endif
62 }
63
64 /*
65 =item im_context_refdec(ctx, where)
66 X<im_context_refdec API>
67 =section Context objects
68 =synopsis im_context_refdec(aIMCTX, "a description");
69
70 Remove a reference to the context, releasing it if all references have
71 been removed.
72
73 =cut
74 */
75
76 void
77 im_context_refdec(im_context_t ctx, const char *where) {
78   int i;
79
80   im_assert(ctx->refcount > 0);
81
82   --ctx->refcount;
83
84 #ifdef IMAGER_TRACE_CONTEXT
85   fprintf(stderr, "im_context:%s: delete %p (count now %lu)\n", where,
86           ctx, (unsigned long)ctx->refcount);
87 #endif
88
89   if (ctx->refcount != 0)
90     return;
91
92   for (i = 0; i < IM_ERROR_COUNT; ++i) {
93     if (ctx->error_stack[i].msg)
94       myfree(ctx->error_stack[i].msg);
95   }
96 #ifdef IMAGER_LOG
97   if (ctx->lg_file)
98     fclose(ctx->lg_file);
99 #endif
100
101   free(ctx);
102 }
103
104 /*
105 =item im_context_clone(ctx)
106
107 Clone an Imager context object, returning the result.
108
109 =cut
110 */
111
112 im_context_t
113 im_context_clone(im_context_t ctx, const char *where) {
114   im_context_t nctx = malloc(sizeof(im_context_struct));
115   int i;
116
117   if (!nctx)
118     return NULL;
119
120   nctx->error_sp = ctx->error_sp;
121   for (i = 0; i < IM_ERROR_COUNT; ++i) {
122     if (ctx->error_stack[i].msg) {
123       size_t sz = ctx->error_alloc[i];
124       nctx->error_alloc[i] = sz;
125       nctx->error_stack[i].msg = mymalloc(sz);
126       memcpy(nctx->error_stack[i].msg, ctx->error_stack[i].msg, sz);
127     }
128     else {
129       nctx->error_alloc[i] = 0;
130       nctx->error_stack[i].msg = NULL;
131     }
132     nctx->error_stack[i].code = ctx->error_stack[i].code;
133   }
134 #ifdef IMAGER_LOG
135   nctx->log_level = ctx->log_level;
136   if (ctx->lg_file) {
137     /* disable buffering, this isn't perfect */
138     setvbuf(ctx->lg_file, NULL, _IONBF, 0);
139
140     /* clone that and disable buffering some more */
141     nctx->lg_file = fdopen(fileno(ctx->lg_file), "a");
142     if (nctx->lg_file)
143       setvbuf(nctx->lg_file, NULL, _IONBF, 0);
144   }
145   else {
146     nctx->lg_file = NULL;
147   }
148 #endif
149   nctx->max_width = ctx->max_width;
150   nctx->max_height = ctx->max_height;
151   nctx->max_bytes = ctx->max_bytes;
152   nctx->refcount = 1;
153
154 #ifdef IMAGER_TRACE_CONTEXT
155   fprintf(stderr, "im_context:%s: cloned %p to %p\n", where, ctx, nctx);
156 #endif
157
158   return nctx;
159 }