/src/mupdf/source/pdf/pdf-resources.c
Line | Count | Source |
1 | | // Copyright (C) 2004-2025 Artifex Software, Inc. |
2 | | // |
3 | | // This file is part of MuPDF. |
4 | | // |
5 | | // MuPDF is free software: you can redistribute it and/or modify it under the |
6 | | // terms of the GNU Affero General Public License as published by the Free |
7 | | // Software Foundation, either version 3 of the License, or (at your option) |
8 | | // any later version. |
9 | | // |
10 | | // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY |
11 | | // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
12 | | // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more |
13 | | // details. |
14 | | // |
15 | | // You should have received a copy of the GNU Affero General Public License |
16 | | // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html> |
17 | | // |
18 | | // Alternative licensing terms are available from the licensor. |
19 | | // For commercial licensing, see <https://www.artifex.com/> or contact |
20 | | // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, |
21 | | // CA 94129, USA, for further information. |
22 | | |
23 | | #include "mupdf/fitz.h" |
24 | | #include "mupdf/pdf.h" |
25 | | |
26 | | #include <zlib.h> /* for crc32 */ |
27 | | |
28 | | #include <string.h> |
29 | | |
30 | | static void pdf_drop_obj_as_void(fz_context *ctx, void *obj) |
31 | 0 | { |
32 | 0 | pdf_drop_obj(ctx, obj); |
33 | 0 | } |
34 | | |
35 | | /* We do need to come up with an effective way to see what is already in the |
36 | | * file to avoid adding to what is already there. This is avoided for pdfwrite |
37 | | * as we check as we add each font. For adding text to an existing file though |
38 | | * it may be more problematic. */ |
39 | | |
40 | | pdf_obj * |
41 | | pdf_find_font_resource(fz_context *ctx, pdf_document *doc, int type, int encoding, fz_font *item, pdf_font_resource_key *key) |
42 | 0 | { |
43 | 0 | pdf_obj *res; |
44 | |
|
45 | 0 | if (!doc->resources.fonts) |
46 | 0 | doc->resources.fonts = fz_new_hash_table(ctx, 4096, sizeof(*key), -1, pdf_drop_obj_as_void); |
47 | |
|
48 | 0 | memset(key, 0, sizeof(*key)); |
49 | 0 | fz_font_digest(ctx, item, key->digest); |
50 | |
|
51 | 0 | key->type = type; |
52 | 0 | key->encoding = encoding; |
53 | 0 | key->local_xref = doc->local_xref_nesting > 0; |
54 | |
|
55 | 0 | res = fz_hash_find(ctx, doc->resources.fonts, (void *)key); |
56 | 0 | if (res) |
57 | 0 | pdf_keep_obj(ctx, res); |
58 | 0 | return res; |
59 | 0 | } |
60 | | |
61 | | pdf_obj * |
62 | | pdf_find_colorspace_resource(fz_context *ctx, pdf_document *doc, fz_colorspace *item, pdf_colorspace_resource_key *key) |
63 | 0 | { |
64 | 0 | pdf_obj *res; |
65 | |
|
66 | 0 | if (!doc->resources.colorspaces) |
67 | 0 | doc->resources.colorspaces = fz_new_hash_table(ctx, 4096, sizeof(*key), -1, pdf_drop_obj_as_void); |
68 | |
|
69 | 0 | memset(key, 0, sizeof(*key)); |
70 | 0 | fz_colorspace_digest(ctx, item, key->digest); |
71 | |
|
72 | 0 | key->local_xref = doc->local_xref_nesting > 0; |
73 | |
|
74 | 0 | res = fz_hash_find(ctx, doc->resources.colorspaces, (void *)key); |
75 | 0 | if (res) |
76 | 0 | pdf_keep_obj(ctx, res); |
77 | 0 | return res; |
78 | 0 | } |
79 | | |
80 | | pdf_obj * |
81 | | pdf_find_image_resource(fz_context *ctx, pdf_document *doc, fz_image *item, pdf_image_resource_key *key) |
82 | 0 | { |
83 | 0 | pdf_obj *res; |
84 | |
|
85 | 0 | if (!doc->resources.images) |
86 | 0 | doc->resources.images = fz_new_hash_table(ctx, 4096, sizeof(*key), -1, pdf_drop_obj_as_void); |
87 | |
|
88 | 0 | memset(key, 0, sizeof(*key)); |
89 | |
|
90 | 0 | key->w = item->w; |
91 | 0 | key->h = item->h; |
92 | 0 | key->n = item->n; |
93 | 0 | key->bpc = item->bpc; |
94 | 0 | key->imagemask = item->imagemask; |
95 | 0 | key->use_colorkey = item->use_colorkey; |
96 | 0 | key->use_decode = item->use_decode; |
97 | 0 | key->decode = crc32(0, (unsigned char *)item->decode, 2 * item->n * sizeof(float)); |
98 | 0 | key->decode = crc32(key->decode, (unsigned char *)item->colorkey, 2 * item->n * sizeof(int)); |
99 | |
|
100 | 0 | if (item->mask) |
101 | 0 | fz_image_digest(ctx, item->mask, key->mask); |
102 | |
|
103 | 0 | fz_image_digest(ctx, item, key->digest); |
104 | |
|
105 | 0 | key->local_xref = doc->local_xref_nesting > 0; |
106 | |
|
107 | 0 | res = fz_hash_find(ctx, doc->resources.images, (void *)key); |
108 | 0 | if (res) |
109 | 0 | pdf_keep_obj(ctx, res); |
110 | 0 | return res; |
111 | 0 | } |
112 | | |
113 | | pdf_obj * |
114 | | pdf_insert_font_resource(fz_context *ctx, pdf_document *doc, pdf_font_resource_key *key, pdf_obj *obj) |
115 | 0 | { |
116 | 0 | pdf_obj *res = fz_hash_insert(ctx, doc->resources.fonts, (void *)key, obj); |
117 | 0 | if (res) |
118 | 0 | fz_warn(ctx, "warning: font resource already present"); |
119 | 0 | else |
120 | 0 | res = pdf_keep_obj(ctx, obj); |
121 | 0 | return pdf_keep_obj(ctx, res); |
122 | 0 | } |
123 | | |
124 | | pdf_obj * |
125 | | pdf_insert_colorspace_resource(fz_context *ctx, pdf_document *doc, pdf_colorspace_resource_key *key, pdf_obj *obj) |
126 | 0 | { |
127 | 0 | pdf_obj *res = fz_hash_insert(ctx, doc->resources.colorspaces, (void *)key, obj); |
128 | 0 | if (res) |
129 | 0 | fz_warn(ctx, "warning: colorspace resource already present"); |
130 | 0 | else |
131 | 0 | res = pdf_keep_obj(ctx, obj); |
132 | 0 | return pdf_keep_obj(ctx, res); |
133 | 0 | } |
134 | | |
135 | | pdf_obj * |
136 | | pdf_insert_image_resource(fz_context *ctx, pdf_document *doc, pdf_image_resource_key *key, pdf_obj *obj) |
137 | 0 | { |
138 | 0 | pdf_obj *res = fz_hash_insert(ctx, doc->resources.images, (void *)key, obj); |
139 | 0 | if (res) |
140 | 0 | fz_warn(ctx, "warning: image resource already present"); |
141 | 0 | else |
142 | 0 | res = pdf_keep_obj(ctx, obj); |
143 | 0 | return pdf_keep_obj(ctx, res); |
144 | 0 | } |
145 | | |
146 | | static int purge_local_font_resource(fz_context *ctx, void *state, void *key_, int keylen, void *val) |
147 | 0 | { |
148 | 0 | pdf_font_resource_key *key = key_; |
149 | 0 | if (key->local_xref) |
150 | 0 | { |
151 | 0 | pdf_drop_obj(ctx, val); |
152 | 0 | return 1; |
153 | 0 | } |
154 | 0 | return 0; |
155 | 0 | } |
156 | | |
157 | | static int purge_local_colorspace_resource(fz_context *ctx, void *state, void *key_, int keylen, void *val) |
158 | 0 | { |
159 | 0 | pdf_colorspace_resource_key *key = key_; |
160 | 0 | if (key->local_xref) |
161 | 0 | { |
162 | 0 | pdf_drop_obj(ctx, val); |
163 | 0 | return 1; |
164 | 0 | } |
165 | 0 | return 0; |
166 | 0 | } |
167 | | |
168 | | static int purge_local_image_resource(fz_context *ctx, void *state, void *key_, int keylen, void *val) |
169 | 0 | { |
170 | 0 | pdf_image_resource_key *key = key_; |
171 | 0 | if (key->local_xref) |
172 | 0 | { |
173 | 0 | pdf_drop_obj(ctx, val); |
174 | 0 | return 1; |
175 | 0 | } |
176 | 0 | return 0; |
177 | 0 | } |
178 | | |
179 | | void |
180 | | pdf_purge_local_resources(fz_context *ctx, pdf_document *doc) |
181 | 10 | { |
182 | 10 | if (doc->resources.fonts) |
183 | 0 | fz_hash_filter(ctx, doc->resources.fonts, NULL, purge_local_font_resource); |
184 | 10 | if (doc->resources.colorspaces) |
185 | 0 | fz_hash_filter(ctx, doc->resources.colorspaces, NULL, purge_local_colorspace_resource); |
186 | 10 | if (doc->resources.images) |
187 | 0 | fz_hash_filter(ctx, doc->resources.images, NULL, purge_local_image_resource); |
188 | 10 | } |
189 | | |
190 | | void |
191 | | pdf_drop_resource_tables(fz_context *ctx, pdf_document *doc) |
192 | 10 | { |
193 | 10 | if (doc) |
194 | 10 | { |
195 | 10 | fz_drop_hash_table(ctx, doc->resources.colorspaces); |
196 | 10 | fz_drop_hash_table(ctx, doc->resources.fonts); |
197 | 10 | fz_drop_hash_table(ctx, doc->resources.images); |
198 | 10 | } |
199 | 10 | } |