Skip to content

Commit ea44a17

Browse files
committed
Type3 shading dicts
1 parent d272ffd commit ea44a17

6 files changed

Lines changed: 934 additions & 8 deletions

File tree

libs/pdf/include/pdf/color_space.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ typedef struct {
3737
typedef struct {
3838
PdfNameVec* names;
3939
PdfName alternate_space;
40-
PdfObject* tilt_transform;
40+
PdfObject tint_transform;
4141
PdfDictOptional attributes;
4242
} PdfDeviceNParams;
4343

@@ -57,6 +57,7 @@ typedef enum {
5757

5858
typedef union {
5959
PdfCalRGBParams cal_rgb;
60+
PdfDeviceNParams device_n;
6061
} PdfColorSpaceParams;
6162

6263
typedef struct {

libs/pdf/src/color_space.c

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,150 @@ Error* pdf_deserde_color_space(
137137
break;
138138
}
139139
case PDF_COLOR_SPACE_DEVICE_N: {
140+
if (resolved.type != PDF_OBJECT_TYPE_ARRAY) {
141+
return ERROR(
142+
PDF_ERR_INCORRECT_TYPE,
143+
"DeviceN color spaces must be arrays"
144+
);
145+
}
146+
147+
size_t num_elements =
148+
pdf_object_vec_len(resolved.data.array.elements);
149+
if (num_elements != 4 && num_elements != 5) {
150+
return ERROR(
151+
PDF_ERR_INCORRECT_TYPE,
152+
"DeviceN color spaces must have exactly 4 or 5 elements, "
153+
"found %zu",
154+
num_elements
155+
);
156+
}
157+
158+
PdfObject names_object;
159+
RELEASE_ASSERT(pdf_object_vec_get(
160+
resolved.data.array.elements,
161+
1,
162+
&names_object
163+
));
164+
PdfArray names_array;
165+
TRY(pdf_deserde_array(&names_object, &names_array, resolver));
166+
if (pdf_object_vec_len(names_array.elements) == 0) {
167+
return ERROR(
168+
PDF_ERR_INCORRECT_TYPE,
169+
"DeviceN color space names array must contain at least one "
170+
"colorant name"
171+
);
172+
}
173+
174+
target_ptr->params.device_n.names =
175+
pdf_name_vec_new(pdf_resolver_arena(resolver));
176+
for (size_t idx = 0; idx < pdf_object_vec_len(names_array.elements);
177+
idx++) {
178+
PdfObject name_object;
179+
RELEASE_ASSERT(
180+
pdf_object_vec_get(names_array.elements, idx, &name_object)
181+
);
182+
183+
PdfName name;
184+
TRY(pdf_deserde_name(&name_object, &name, resolver));
185+
pdf_name_vec_push(target_ptr->params.device_n.names, name);
186+
}
187+
188+
PdfObject alternate_object;
189+
RELEASE_ASSERT(pdf_object_vec_get(
190+
resolved.data.array.elements,
191+
2,
192+
&alternate_object
193+
));
194+
195+
PdfObject alternate_resolved;
196+
TRY(pdf_resolve_object(
197+
resolver,
198+
&alternate_object,
199+
&alternate_resolved,
200+
true
201+
));
202+
203+
if (alternate_resolved.type == PDF_OBJECT_TYPE_NAME) {
204+
target_ptr->params.device_n.alternate_space =
205+
alternate_resolved.data.name;
206+
} else if (alternate_resolved.type == PDF_OBJECT_TYPE_ARRAY) {
207+
PdfObject first;
208+
if (!pdf_object_vec_get(
209+
alternate_resolved.data.array.elements,
210+
0,
211+
&first
212+
)) {
213+
return ERROR(
214+
PDF_ERR_INCORRECT_TYPE,
215+
"DeviceN alternate color space array must contain a "
216+
"base color space name"
217+
);
218+
}
219+
220+
PdfObject first_resolved;
221+
TRY(
222+
pdf_resolve_object(resolver, &first, &first_resolved, true)
223+
);
224+
225+
if (first_resolved.type != PDF_OBJECT_TYPE_NAME) {
226+
return ERROR(
227+
PDF_ERR_INCORRECT_TYPE,
228+
"DeviceN alternate color space array must start with "
229+
"a color space name"
230+
);
231+
}
232+
233+
target_ptr->params.device_n.alternate_space =
234+
first_resolved.data.name;
235+
} else {
236+
return ERROR(
237+
PDF_ERR_INCORRECT_TYPE,
238+
"DeviceN alternate color space must be a name or array"
239+
);
240+
}
241+
242+
PdfObject tint_transform_object;
243+
RELEASE_ASSERT(pdf_object_vec_get(
244+
resolved.data.array.elements,
245+
3,
246+
&tint_transform_object
247+
));
248+
249+
PdfObject tint_transform_resolved;
250+
TRY(pdf_resolve_object(
251+
resolver,
252+
&tint_transform_object,
253+
&tint_transform_resolved,
254+
true
255+
));
256+
if (tint_transform_resolved.type != PDF_OBJECT_TYPE_DICT
257+
&& tint_transform_resolved.type != PDF_OBJECT_TYPE_STREAM) {
258+
return ERROR(
259+
PDF_ERR_INCORRECT_TYPE,
260+
"DeviceN TintTransform must be a function dictionary or "
261+
"stream"
262+
);
263+
}
264+
target_ptr->params.device_n.tint_transform =
265+
tint_transform_resolved;
266+
267+
if (num_elements == 5) {
268+
PdfObject attributes_object;
269+
RELEASE_ASSERT(pdf_object_vec_get(
270+
resolved.data.array.elements,
271+
4,
272+
&attributes_object
273+
));
274+
TRY(pdf_deserde_dict(
275+
&attributes_object,
276+
&target_ptr->params.device_n.attributes.value,
277+
resolver
278+
));
279+
target_ptr->params.device_n.attributes.is_some = true;
280+
} else {
281+
target_ptr->params.device_n.attributes =
282+
(PdfDictOptional) {.is_some = false};
283+
}
140284
break;
141285
}
142286
default: {

0 commit comments

Comments
 (0)