OSDN Git Service

binding with libharu.
[putex/putex.git] / src / texsourc / lib / libhpdf / src / hpdf_dict.c
1 /*
2  * << Haru Free PDF Library >> -- hpdf_dict.c
3  *
4  * URL: http://libharu.org
5  *
6  * Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
7  * Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
8  *
9  * Permission to use, copy, modify, distribute and sell this software
10  * and its documentation for any purpose is hereby granted without fee,
11  * provided that the above copyright notice appear in all copies and
12  * that both that copyright notice and this permission notice appear
13  * in supporting documentation.
14  * It is provided "as is" without express or implied warranty.
15  *
16  */
17
18 #include "hpdf_conf.h"
19 #include "hpdf_utils.h"
20 #include "hpdf_objects.h"
21
22 HPDF_DictElement
23 GetElement  (HPDF_Dict      dict,
24              const char    *key);
25
26 /*--------------------------------------------------------------------------*/
27
28 HPDF_Dict
29 HPDF_Dict_New  (HPDF_MMgr  mmgr)
30 {
31     HPDF_Dict obj;
32
33     obj = (HPDF_Dict)HPDF_GetMem (mmgr, sizeof(HPDF_Dict_Rec));
34     if (obj) {
35         HPDF_MemSet (obj, 0, sizeof(HPDF_Dict_Rec));
36         obj->header.obj_class = HPDF_OCLASS_DICT;
37         obj->mmgr = mmgr;
38         obj->error = mmgr->error;
39         obj->list = HPDF_List_New (mmgr, HPDF_DEF_ITEMS_PER_BLOCK);
40         obj->filter = HPDF_STREAM_FILTER_NONE;
41         if (!obj->list) {
42             HPDF_FreeMem (mmgr, obj);
43             obj = NULL;
44         }
45     }
46
47     return obj;
48 }
49
50
51 HPDF_Dict
52 HPDF_DictStream_New  (HPDF_MMgr  mmgr,
53                       HPDF_Xref  xref)
54 {
55     HPDF_Dict  obj;
56     HPDF_Number length;
57     HPDF_STATUS ret = 0;
58
59     obj = HPDF_Dict_New (mmgr);
60     if (!obj)
61         return NULL;
62
63     /* only stream object is added to xref automatically */
64     ret += HPDF_Xref_Add (xref, obj);
65     if (ret != HPDF_OK)
66         return NULL;
67
68     length = HPDF_Number_New (mmgr, 0);
69     if (!length)
70         return NULL;
71
72     ret = HPDF_Xref_Add (xref, length);
73     if (ret != HPDF_OK)
74         return NULL;
75
76     ret = HPDF_Dict_Add (obj, "Length", length);
77     if (ret != HPDF_OK)
78         return NULL;
79
80     obj->stream = HPDF_MemStream_New (mmgr, HPDF_STREAM_BUF_SIZ);
81     if (!obj->stream)
82         return NULL;
83
84     return obj;
85 }
86
87
88 void
89 HPDF_Dict_Free  (HPDF_Dict  dict)
90 {
91     HPDF_UINT i;
92
93     if (!dict)
94         return;
95
96     if (dict->free_fn)
97         dict->free_fn (dict);
98
99     for (i = 0; i < dict->list->count; i++) {
100         HPDF_DictElement element =
101                 (HPDF_DictElement)HPDF_List_ItemAt (dict->list, i);
102
103         if (element) {
104             HPDF_Obj_Free (dict->mmgr, element->value);
105             HPDF_FreeMem (dict->mmgr, element);
106         }
107     }
108
109     if (dict->stream)
110         HPDF_Stream_Free (dict->stream);
111
112     HPDF_List_Free (dict->list);
113
114     dict->header.obj_class = 0;
115
116     HPDF_FreeMem (dict->mmgr, dict);
117 }
118
119 HPDF_STATUS
120 HPDF_Dict_Add_FilterParams(HPDF_Dict    dict, HPDF_Dict filterParam)
121 {
122     HPDF_Array paramArray;
123     /* prepare params object */
124     paramArray = HPDF_Dict_GetItem (dict, "DecodeParms",
125                                               HPDF_OCLASS_ARRAY);
126     if(paramArray==NULL) {
127         paramArray = HPDF_Array_New (dict->mmgr);
128        if (!paramArray)
129             return HPDF_Error_GetCode (dict->error);
130
131         /* add parameters */
132         HPDF_Dict_Add(dict, "DecodeParms", paramArray);
133     }
134     HPDF_Array_Add(paramArray, filterParam);
135     return HPDF_OK;
136 }
137
138
139 HPDF_STATUS
140 HPDF_Dict_Write  (HPDF_Dict     dict,
141                   HPDF_Stream   stream,
142                   HPDF_Encrypt  e)
143 {
144     HPDF_UINT i;
145     HPDF_STATUS ret;
146
147     ret = HPDF_Stream_WriteStr (stream, "<<\012");
148     if (ret != HPDF_OK)
149         return ret;
150
151     if (dict->before_write_fn) {
152         if ((ret = dict->before_write_fn (dict)) != HPDF_OK)
153             return ret;
154     }
155
156     /* encrypt-dict must not be encrypted. */
157     if (dict->header.obj_class == (HPDF_OCLASS_DICT | HPDF_OSUBCLASS_ENCRYPT))
158         e = NULL;
159
160     if (dict->stream) {
161         /* set filter element */
162         if (dict->filter == HPDF_STREAM_FILTER_NONE)
163             HPDF_Dict_RemoveElement (dict, "Filter");
164         else {
165             HPDF_Array array = HPDF_Dict_GetItem (dict, "Filter",
166                         HPDF_OCLASS_ARRAY);
167
168             if (!array) {
169                 array = HPDF_Array_New (dict->mmgr);
170                 if (!array)
171                     return HPDF_Error_GetCode (dict->error);
172
173                 ret = HPDF_Dict_Add (dict, "Filter", array);
174                 if (ret != HPDF_OK)
175                     return ret;
176             }
177
178             HPDF_Array_Clear (array);
179
180 #ifndef LIBHPDF_HAVE_NOZLIB
181             if (dict->filter & HPDF_STREAM_FILTER_FLATE_DECODE)
182                 HPDF_Array_AddName (array, "FlateDecode");
183 #endif /* LIBHPDF_HAVE_NOZLIB */
184
185             if (dict->filter & HPDF_STREAM_FILTER_DCT_DECODE)
186                 HPDF_Array_AddName (array, "DCTDecode");
187
188             if(dict->filter & HPDF_STREAM_FILTER_CCITT_DECODE)
189                 HPDF_Array_AddName (array, "CCITTFaxDecode");
190
191             if(dict->filterParams!=NULL)
192             {
193                 HPDF_Dict_Add_FilterParams(dict, dict->filterParams);
194             }
195         }
196     }
197
198     for (i = 0; i < dict->list->count; i++) {
199         HPDF_DictElement element =
200                 (HPDF_DictElement)HPDF_List_ItemAt (dict->list, i);
201         HPDF_Obj_Header *header = (HPDF_Obj_Header *)(element->value);
202
203         if (!element->value)
204             return HPDF_SetError (dict->error, HPDF_INVALID_OBJECT, 0);
205
206         if  (header->obj_id & HPDF_OTYPE_HIDDEN) {
207             HPDF_PTRACE((" HPDF_Dict_Write obj=%p skipped obj_id=0x%08X\n",
208                     element->value, (HPDF_UINT)header->obj_id));
209         } else {
210             ret = HPDF_Stream_WriteEscapeName (stream, element->key);
211             if (ret != HPDF_OK)
212                 return ret;
213
214             ret = HPDF_Stream_WriteChar (stream, ' ');
215             if (ret != HPDF_OK)
216                 return ret;
217
218             ret = HPDF_Obj_Write (element->value, stream, e);
219             if (ret != HPDF_OK)
220                 return ret;
221
222             ret = HPDF_Stream_WriteStr (stream, "\012");
223             if (ret != HPDF_OK)
224                 return ret;
225         }
226     }
227
228     if (dict->write_fn) {
229         if ((ret = dict->write_fn (dict, stream)) != HPDF_OK)
230             return ret;
231     }
232
233     if ((ret = HPDF_Stream_WriteStr (stream, ">>")) != HPDF_OK)
234         return ret;
235
236     if (dict->stream) {
237         HPDF_UINT32 strptr;
238         HPDF_Number length;
239
240         /* get "length" element */
241         length = (HPDF_Number)HPDF_Dict_GetItem (dict, "Length",
242                 HPDF_OCLASS_NUMBER);
243         if (!length)
244             return HPDF_SetError (dict->error,
245                     HPDF_DICT_STREAM_LENGTH_NOT_FOUND, 0);
246
247         /* "length" element must be indirect-object */
248         if (!(length->header.obj_id & HPDF_OTYPE_INDIRECT)) {
249             return HPDF_SetError (dict->error, HPDF_DICT_ITEM_UNEXPECTED_TYPE,
250                     0);
251         }
252
253         if ((ret = HPDF_Stream_WriteStr (stream, "\012stream\015\012")) /* Acrobat 8.15 requires both \r and \n here */
254                 != HPDF_OK)
255             return ret;
256
257         strptr = stream->size;
258
259         if (e)
260             HPDF_Encrypt_Reset (e);
261
262         if ((ret = HPDF_Stream_WriteToStream (dict->stream, stream,
263                         dict->filter, e)) != HPDF_OK)
264             return ret;
265
266         HPDF_Number_SetValue (length, stream->size - strptr);
267
268         ret = HPDF_Stream_WriteStr (stream, "\012endstream");
269     }
270
271     /* 2006.08.13 add. */
272     if (dict->after_write_fn) {
273         if ((ret = dict->after_write_fn (dict)) != HPDF_OK)
274             return ret;
275     }
276
277     return ret;
278 }
279
280 HPDF_STATUS
281 HPDF_Dict_Add  (HPDF_Dict        dict,
282                 const char  *key,
283                 void             *obj)
284 {
285     HPDF_Obj_Header *header;
286     HPDF_STATUS ret = HPDF_OK;
287     HPDF_DictElement element;
288
289     if (!obj) {
290         if (HPDF_Error_GetCode (dict->error) == HPDF_OK)
291             return HPDF_SetError (dict->error, HPDF_INVALID_OBJECT, 0);
292         else
293             return HPDF_INVALID_OBJECT;
294     }
295
296     header = (HPDF_Obj_Header *)obj;
297
298     if (header->obj_id & HPDF_OTYPE_DIRECT)
299         return HPDF_SetError (dict->error, HPDF_INVALID_OBJECT, 0);
300
301     if (!key) {
302         HPDF_Obj_Free (dict->mmgr, obj);
303         return HPDF_SetError (dict->error, HPDF_INVALID_OBJECT, 0);
304     }
305
306     if (dict->list->count >= HPDF_LIMIT_MAX_DICT_ELEMENT) {
307         HPDF_PTRACE((" HPDF_Dict_Add exceed limitatin of dict count(%d)\n",
308                     HPDF_LIMIT_MAX_DICT_ELEMENT));
309
310         HPDF_Obj_Free (dict->mmgr, obj);
311         return HPDF_SetError (dict->error, HPDF_DICT_COUNT_ERR, 0);
312     }
313
314     /* check whether there is an object which has same name */
315     element = GetElement (dict, key);
316
317     if (element) {
318         HPDF_Obj_Free (dict->mmgr, element->value);
319         element->value = NULL;
320     } else {
321         element = (HPDF_DictElement)HPDF_GetMem (dict->mmgr,
322                 sizeof(HPDF_DictElement_Rec));
323
324         if (!element) {
325             /* cannot create element object */
326             if (!(header->obj_id & HPDF_OTYPE_INDIRECT))
327                 HPDF_Obj_Free (dict->mmgr, obj);
328
329             return HPDF_Error_GetCode (dict->error);
330         }
331
332         HPDF_StrCpy (element->key, key, element->key +
333                 HPDF_LIMIT_MAX_NAME_LEN + 1);
334         element->value = NULL;
335
336         ret = HPDF_List_Add (dict->list, element);
337         if (ret != HPDF_OK) {
338             if (!(header->obj_id & HPDF_OTYPE_INDIRECT))
339                 HPDF_Obj_Free (dict->mmgr, obj);
340
341             HPDF_FreeMem (dict->mmgr, element);
342
343             return HPDF_Error_GetCode (dict->error);
344         }
345     }
346
347     if (header->obj_id & HPDF_OTYPE_INDIRECT) {
348         HPDF_Proxy proxy = HPDF_Proxy_New (dict->mmgr, obj);
349
350         if (!proxy)
351             return HPDF_Error_GetCode (dict->error);
352
353         element->value = proxy;
354         proxy->header.obj_id |= HPDF_OTYPE_DIRECT;
355     } else {
356         element->value = obj;
357         header->obj_id |= HPDF_OTYPE_DIRECT;
358     }
359
360     return ret;
361 }
362
363
364 HPDF_STATUS
365 HPDF_Dict_AddName (HPDF_Dict        dict,
366                    const char  *key,
367                    const char  *value)
368 {
369     HPDF_Name name = HPDF_Name_New (dict->mmgr, value);
370     if (!name)
371         return HPDF_Error_GetCode (dict->error);
372
373     return HPDF_Dict_Add (dict, key, name);
374 }
375
376
377 HPDF_STATUS
378 HPDF_Dict_AddNumber  (HPDF_Dict        dict,
379                       const char  *key,
380                       HPDF_INT32       value)
381 {
382     HPDF_Number number = HPDF_Number_New (dict->mmgr, value);
383
384     if (!number)
385         return HPDF_Error_GetCode (dict->error);
386
387     return HPDF_Dict_Add (dict, key, number);
388 }
389
390
391 HPDF_STATUS
392 HPDF_Dict_AddReal  (HPDF_Dict        dict,
393                     const char  *key,
394                     HPDF_REAL        value)
395 {
396     HPDF_Real real = HPDF_Real_New (dict->mmgr, value);
397
398     if (!real)
399         return HPDF_Error_GetCode (dict->error);
400
401     return HPDF_Dict_Add (dict, key, real);
402 }
403
404
405 HPDF_STATUS
406 HPDF_Dict_AddBoolean  (HPDF_Dict      dict,
407                       const char    *key,
408                       HPDF_BOOL      value)
409 {
410     HPDF_Boolean obj = HPDF_Boolean_New (dict->mmgr, value);
411
412     if (!obj)
413         return HPDF_Error_GetCode (dict->error);
414
415     return HPDF_Dict_Add (dict, key, obj);
416 }
417
418
419 void*
420 HPDF_Dict_GetItem  (HPDF_Dict        dict,
421                     const char  *key,
422                     HPDF_UINT16      obj_class)
423 {
424     HPDF_DictElement element = GetElement (dict, key);
425     void *obj;
426
427     if (element && HPDF_StrCmp(key, element->key) == 0) {
428         HPDF_Obj_Header *header = (HPDF_Obj_Header *)element->value;
429
430         if (header->obj_class == HPDF_OCLASS_PROXY) {
431             HPDF_Proxy p = element->value;
432             header = (HPDF_Obj_Header *)p->obj;
433             obj = p->obj;
434         } else
435             obj = element->value;
436
437         if ((header->obj_class & HPDF_OCLASS_ANY) != obj_class) {
438             HPDF_PTRACE((" HPDF_Dict_GetItem dict=%p key=%s obj_class=0x%08X\n",
439                     dict, key, (HPDF_UINT)header->obj_class));
440             HPDF_SetError (dict->error, HPDF_DICT_ITEM_UNEXPECTED_TYPE, 0);
441
442             return NULL;
443         }
444
445         return obj;
446     }
447
448     return NULL;
449 }
450
451
452 HPDF_DictElement
453 GetElement  (HPDF_Dict        dict,
454              const char  *key)
455 {
456     HPDF_UINT i;
457
458     for (i = 0; i < dict->list->count; i++) {
459         HPDF_DictElement element =
460                 (HPDF_DictElement)HPDF_List_ItemAt (dict->list, i);
461
462         if (HPDF_StrCmp (key, element->key) == 0)
463             return element;
464     }
465
466     return NULL;
467 }
468
469
470 HPDF_STATUS
471 HPDF_Dict_RemoveElement  (HPDF_Dict        dict,
472                           const char  *key)
473 {
474     HPDF_UINT i;
475
476     for (i = 0; i < dict->list->count; i++) {
477         HPDF_DictElement element =
478                 (HPDF_DictElement)HPDF_List_ItemAt (dict->list, i);
479
480         if (HPDF_StrCmp (key, element->key) == 0) {
481             HPDF_List_Remove (dict->list, element);
482
483             HPDF_Obj_Free (dict->mmgr, element->value);
484             HPDF_FreeMem (dict->mmgr, element);
485
486             return HPDF_OK;
487         }
488     }
489
490     return HPDF_DICT_ITEM_NOT_FOUND;
491 }
492
493 const char*
494 HPDF_Dict_GetKeyByObj (HPDF_Dict  dict,
495                        void       *obj)
496 {
497     HPDF_UINT i;
498
499     for (i = 0; i < dict->list->count; i++) {
500         HPDF_Obj_Header *header;
501         HPDF_DictElement element =
502                 (HPDF_DictElement)HPDF_List_ItemAt (dict->list, i);
503
504         header = (HPDF_Obj_Header *)(element->value);
505         if (header->obj_class == HPDF_OCLASS_PROXY) {
506             HPDF_Proxy p = element->value;
507
508             if (p->obj == obj)
509                 return element->key;
510         } else {
511             if (element->value == obj)
512                 return element->key;
513         }
514     }
515
516     return NULL;
517 }
518