4852bf81ac5f5da04cc3ad4c7d5f4d88ee13ec6b
[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
46 Add a new reference to the context.
47
48 =cut
49 */
50
51 void
52 im_context_refinc(im_context_t ctx, const char *where) {
53   ++ctx->refcount;
54
55 #ifdef IMAGER_TRACE_CONTEXT
56   fprintf(stderr, "im_context:%s: refinc %p (count now %lu)\n", where,
57           ctx, (unsigned long)ctx->refcount);
58 #endif
59 }
60
61 /*
62 =item im_context_refdec(ctx)
63
64 Release memory used by an Imager context object.
65
66 =cut
67 */
68
69 void
70 im_context_refdec(im_context_t ctx, const char *where) {
71   int i;
72
73   im_assert(ctx->refcount > 0);
74
75   --ctx->refcount;
76
77 #ifdef IMAGER_TRACE_CONTEXT
78   fprintf(stderr, "im_context:%s: delete %p (count now %lu)\n", where,
79           ctx, (unsigned long)ctx->refcount);
80 #endif
81
82   if (ctx->refcount != 0)
83     return;
84
85   for (i = 0; i < IM_ERROR_COUNT; ++i) {
86     if (ctx->error_stack[i].msg)
87       myfree(ctx->error_stack[i].msg);
88   }
89 #ifdef IMAGER_LOG
90   if (ctx->lg_file)
91     fclose(ctx->lg_file);
92 #endif
93
94   free(ctx);
95 }
96
97 /*
98 =item im_context_clone(ctx)
99
100 Clone an Imager context object, returning the result.
101
102 =cut
103 */
104
105 im_context_t
106 im_context_clone(im_context_t ctx, const char *where) {
107   im_context_t nctx = malloc(sizeof(im_context_struct));
108   int i;
109
110   if (!nctx)
111     return NULL;
112
113   nctx->error_sp = ctx->error_sp;
114   for (i = 0; i < IM_ERROR_COUNT; ++i) {
115     if (ctx->error_stack[i].msg) {
116       size_t sz = ctx->error_alloc[i];
117       nctx->error_alloc[i] = sz;
118       nctx->error_stack[i].msg = mymalloc(sz);
119       memcpy(nctx->error_stack[i].msg, ctx->error_stack[i].msg, sz);
120     }
121     else {
122       nctx->error_alloc[i] = 0;
123       nctx->error_stack[i].msg = NULL;
124     }
125     nctx->error_stack[i].code = ctx->error_stack[i].code;
126   }
127 #ifdef IMAGER_LOG
128   nctx->log_level = ctx->log_level;
129   if (ctx->lg_file) {
130     /* disable buffering, this isn't perfect */
131     setvbuf(ctx->lg_file, NULL, _IONBF, 0);
132
133     /* clone that and disable buffering some more */
134     nctx->lg_file = fdopen(fileno(ctx->lg_file), "a");
135     if (nctx->lg_file)
136       setvbuf(nctx->lg_file, NULL, _IONBF, 0);
137   }
138   else {
139     nctx->lg_file = NULL;
140   }
141 #endif
142   nctx->max_width = ctx->max_width;
143   nctx->max_height = ctx->max_height;
144   nctx->max_bytes = ctx->max_bytes;
145   nctx->refcount = 1;
146
147 #ifdef IMAGER_TRACE_CONTEXT
148   fprintf(stderr, "im_context:%s: cloned %p to %p\n", where, ctx, nctx);
149 #endif
150
151   return nctx;
152 }