OSDN Git Service

updated with TeX Live 2014.
[putex/putex.git] / src / dvipdfmx-pu / src / pdfresource.c
1 /*  
2
3     This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
4
5     Copyright (C) 2002-2012 by Jin-Hwan Cho and Shunsaku Hirata,
6     the dvipdfmx project team.
7
8     Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks@kettering.edu>
9
10     This program is free software; you can redistribute it and/or modify
11     it under the terms of the GNU General Public License as published by
12     the Free Software Foundation; either version 2 of the License, or
13     (at your option) any later version.
14
15     This program is distributed in the hope that it will be useful,
16     but WITHOUT ANY WARRANTY; without even the implied warranty of
17     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18     GNU General Public License for more details.
19
20     You should have received a copy of the GNU General Public License
21     along with this program; if not, write to the Free Software
22     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23 */
24
25 /*
26  * Currently, this is nearly useless.
27  */
28
29 #if HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include "system.h"
34 #include "mem.h"
35 #include "error.h"
36
37 #include "dpxutil.h"
38
39 #include "pdfobj.h"
40
41 #include "pdfresource.h"
42
43 #define PDF_RESOURCE_DEBUG_STR "PDF"
44 #define PDF_RESOURCE_DEBUG     3
45
46 #define PDF_RESOURCE_FONT       0
47 #define PDF_RESOURCE_CIDFONT    1
48 #define PDF_RESOURCE_ENCODING   2
49 #define PDF_RESOURCE_CMAP       3
50 #define PDF_RESOURCE_XOBJECT    4
51 #define PDF_RESOURCE_COLORSPACE 5
52 #define PDF_RESOURCE_SHADING    6
53 #define PDF_RESOURCE_PATTERN    7
54 #define PDF_RESOURCE_GSTATE     8
55
56 typedef struct pdf_res
57 {
58   char    *ident;
59
60   int      flags;
61
62   int      category;
63   void    *cdata;
64
65   pdf_obj *object;
66   pdf_obj *reference;
67 } pdf_res;
68
69 static struct {
70   const char *name;
71   int         cat_id;
72 } pdf_resource_categories[] = {
73   {"Font",       PDF_RESOURCE_FONT},
74   {"CIDFont",    PDF_RESOURCE_CIDFONT},
75   {"Encoding",   PDF_RESOURCE_ENCODING},
76   {"CMap",       PDF_RESOURCE_CMAP},
77   {"XObject",    PDF_RESOURCE_XOBJECT},
78   {"ColorSpace", PDF_RESOURCE_COLORSPACE},
79   {"Shading",    PDF_RESOURCE_SHADING},
80   {"Pattern",    PDF_RESOURCE_PATTERN},
81   {"ExtGState",  PDF_RESOURCE_GSTATE},
82 };
83
84 #define PDF_NUM_RESOURCE_CATEGORIES (sizeof(pdf_resource_categories)/sizeof(pdf_resource_categories[0]))
85
86 #define CACHE_ALLOC_SIZE 16u
87 struct res_cache
88 {
89   int      count;
90   int      capacity;
91   pdf_res *resources;
92 };
93
94 static struct res_cache resources[PDF_NUM_RESOURCE_CATEGORIES];
95
96 static void
97 pdf_init_resource (pdf_res *res)
98 {
99   ASSERT(res);
100
101   res->ident     = NULL;
102   res->category  = -1;
103   res->flags     = 0;
104   res->cdata     = NULL;
105   res->object    = NULL;
106   res->reference = NULL;
107
108   return;
109 }
110
111 static void
112 pdf_flush_resource (pdf_res *res)
113 {
114   if (res) {
115     if (res->reference)
116       pdf_release_obj(res->reference);
117     if (res->object)
118       pdf_release_obj(res->object);
119
120     res->reference = NULL;
121     res->object    = NULL;
122   }
123 }
124
125 static void
126 pdf_clean_resource (pdf_res *res)
127 {
128   if (res) {
129     if (res->reference || res->object)
130       WARN("Trying to release un-flushed object.");
131     if (res->reference)
132       pdf_release_obj(res->reference);
133     if (res->object)
134       pdf_release_obj(res->object);
135     if (res->ident)
136       RELEASE(res->ident);
137     res->ident    = NULL;
138     res->category = -1;
139     res->flags    = 0;
140   }
141 }
142
143 void
144 pdf_init_resources (void)
145 {
146   int  i;
147
148   for (i = 0;
149        i < PDF_NUM_RESOURCE_CATEGORIES; i++) {
150     resources[i].count     = 0;
151     resources[i].capacity  = 0;
152     resources[i].resources = NULL;
153   }
154 }
155
156 void
157 pdf_close_resources (void)
158 {
159   int  i;
160
161   for (i = 0;
162        i < PDF_NUM_RESOURCE_CATEGORIES; i++) {
163     struct res_cache *rc;
164     int    j;
165
166     rc = &resources[i];
167     for (j = 0; j < rc->count; j++) {
168       pdf_flush_resource(&rc->resources[j]);
169       pdf_clean_resource(&rc->resources[j]);
170     }
171     RELEASE(rc->resources);
172
173     rc->count     = 0;
174     rc->capacity  = 0;
175     rc->resources = NULL;
176   }
177 }
178
179 static int
180 get_category (const char *category)
181 {
182   int  i;
183
184   for (i = 0;
185        i < PDF_NUM_RESOURCE_CATEGORIES; i++) {
186     if (!strcmp(category, pdf_resource_categories[i].name)) {
187       return pdf_resource_categories[i].cat_id;
188     }
189   }
190
191   return -1;
192 }
193
194 long
195 pdf_defineresource (const char *category,
196                     const char *resname, pdf_obj *object, int flags)
197 {
198   int      res_id;
199   struct res_cache *rc;
200   int      cat_id;
201   pdf_res *res = NULL;
202
203   ASSERT(category && object);
204
205   cat_id = get_category(category);
206   if (cat_id < 0) {
207     ERROR("Unknown resource category: %s", category);
208     return -1;
209   }
210
211   rc = &resources[cat_id];
212   if (resname) {
213     for (res_id = 0; res_id < rc->count; res_id++) {
214       res = &rc->resources[res_id];
215       if (!strcmp(resname, res->ident)) {
216         WARN("Resource %s (category: %s) already defined...",
217              resname, category);
218         pdf_flush_resource(res);
219         res->flags    = flags;
220         if (flags & PDF_RES_FLUSH_IMMEDIATE) {
221           res->reference = pdf_ref_obj(object);
222           pdf_release_obj(object);
223         } else {
224           res->object = object;
225         }
226         return (long) ((cat_id << 16)|(res_id));
227       }
228     }
229   } else {
230     res_id = rc->count;
231   }
232
233   if (res_id == rc->count) {
234     if (rc->count >= rc->capacity) {
235       rc->capacity += CACHE_ALLOC_SIZE;
236       rc->resources = RENEW(rc->resources, rc->capacity, pdf_res);
237     }
238     res = &rc->resources[res_id];
239
240     pdf_init_resource(res);
241     if (resname && resname[0] != '\0') {
242       res->ident = NEW(strlen(resname) + 1, char);
243       strcpy(res->ident, resname);
244     }
245     res->category = cat_id;
246     res->flags    = flags;
247     if (flags & PDF_RES_FLUSH_IMMEDIATE) {
248       res->reference = pdf_ref_obj(object);
249       pdf_release_obj(object);
250     } else {
251       res->object = object;
252     }
253     rc->count++;
254   }
255
256   return (long) ((cat_id << 16)|(res_id));
257 }
258
259 #if 0
260 int
261 pdf_resource_exist (const char *category, const char *resname)
262 {
263   int    res_id;
264   struct res_cache *rc;
265   int    cat_id;
266
267   ASSERT(resname && category);
268
269   cat_id = get_category(category);
270   if (cat_id < 0)
271     ERROR("Unknown resource category: %s", category);
272
273   rc = &resources[cat_id];
274   for (res_id = 0; res_id < rc->count; res_id++) {
275     pdf_res *res;
276
277     res = &rc->resources[res_id];
278     if (!strcmp(resname, res->ident)) {
279       return 1;
280     }
281   }
282
283   return 0;
284 }
285 #endif
286
287 long
288 pdf_findresource (const char *category, const char *resname)
289 {
290   pdf_res *res;
291   int      res_id, cat_id;
292   struct res_cache *rc;
293
294   ASSERT(resname && category);
295
296   cat_id = get_category(category);
297   if (cat_id < 0) {
298     ERROR("Unknown resource category: %s", category);
299     return -1;
300   }
301
302   rc = &resources[cat_id];
303   for (res_id = 0; res_id < rc->count; res_id++) {
304     res = &rc->resources[res_id];
305     if (!strcmp(resname, res->ident)) {
306       return (long) (cat_id << 16|res_id);
307     }
308   }
309
310   return -1;
311 }
312
313 pdf_obj *
314 pdf_get_resource_reference (long rc_id)
315 {
316   int  cat_id, res_id;
317   struct res_cache *rc;
318   pdf_res *res;
319
320   cat_id = (rc_id >> 16) & 0xffff;
321   res_id = rc_id & 0xffff;
322
323   if (cat_id < 0 ||
324       cat_id >= PDF_NUM_RESOURCE_CATEGORIES) {
325     ERROR("Invalid category ID: %d", cat_id);
326     return NULL;
327   }
328   rc  = &resources[cat_id];
329   if (res_id < 0 || res_id >= rc->count) {
330     ERROR("Invalid resource ID: %d", res_id);
331     return NULL;
332   }
333
334   res = &rc->resources[res_id];
335   if (!res->reference) {
336     if (!res->object) {
337       ERROR("Undefined object...");
338       return NULL;
339     } else {
340       res->reference = pdf_ref_obj(res->object);
341     }
342   }
343
344   return pdf_link_obj(res->reference);
345 }
346
347 #if 0
348 pdf_obj *
349 pdf_get_resource (long rc_id)
350 {
351   int  cat_id, res_id;
352   struct res_cache *rc;
353   pdf_res *res;
354
355   cat_id = (rc_id >> 16) & 0xffff;
356   res_id = rc_id & 0xffff;
357
358   if (cat_id < 0 ||
359       cat_id >= PDF_NUM_RESOURCE_CATEGORIES) {
360     ERROR("Invalid category ID: %d", cat_id);
361     return NULL;
362   }
363   rc  = &resources[cat_id];
364   if (res_id < 0 || res_id >= rc->count) {
365     ERROR("Invalid resource ID: %d", res_id);
366     return NULL;
367   }
368
369   res = &rc->resources[res_id];
370   if (!res->object) {
371     ERROR("Object already flushed???");
372     return NULL;
373   }
374
375   return res->object;
376 }
377 #endif