@@ -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