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