comparison mupdf-source/source/fitz/device.c @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
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
25 #include <string.h>
26
27 fz_device *
28 fz_new_device_of_size(fz_context *ctx, int size)
29 {
30 fz_device *dev = Memento_label(fz_calloc(ctx, 1, size), "fz_device");
31 dev->refs = 1;
32 return dev;
33 }
34
35 static void
36 fz_disable_device(fz_context *ctx, fz_device *dev)
37 {
38 dev->close_device = NULL;
39 dev->fill_path = NULL;
40 dev->stroke_path = NULL;
41 dev->clip_path = NULL;
42 dev->clip_stroke_path = NULL;
43 dev->fill_text = NULL;
44 dev->stroke_text = NULL;
45 dev->clip_text = NULL;
46 dev->clip_stroke_text = NULL;
47 dev->ignore_text = NULL;
48 dev->fill_shade = NULL;
49 dev->fill_image = NULL;
50 dev->fill_image_mask = NULL;
51 dev->clip_image_mask = NULL;
52 dev->pop_clip = NULL;
53 dev->begin_mask = NULL;
54 dev->end_mask = NULL;
55 dev->begin_group = NULL;
56 dev->end_group = NULL;
57 dev->begin_tile = NULL;
58 dev->end_tile = NULL;
59 dev->render_flags = NULL;
60 dev->set_default_colorspaces = NULL;
61 dev->begin_layer = NULL;
62 dev->end_layer = NULL;
63 dev->begin_structure = NULL;
64 dev->end_structure = NULL;
65 dev->begin_metatext = NULL;
66 dev->end_metatext = NULL;
67 }
68
69 void
70 fz_close_device(fz_context *ctx, fz_device *dev)
71 {
72 if (dev == NULL)
73 return;
74
75 fz_try(ctx)
76 {
77 if (dev->close_device)
78 dev->close_device(ctx, dev);
79 }
80 fz_always(ctx)
81 fz_disable_device(ctx, dev);
82 fz_catch(ctx)
83 fz_rethrow(ctx);
84 }
85
86 fz_device *
87 fz_keep_device(fz_context *ctx, fz_device *dev)
88 {
89 return fz_keep_imp(ctx, dev, &dev->refs);
90 }
91
92 void
93 fz_drop_device(fz_context *ctx, fz_device *dev)
94 {
95 if (fz_drop_imp(ctx, dev, &dev->refs))
96 {
97 if (dev->close_device)
98 fz_warn(ctx, "dropping unclosed device");
99 if (dev->drop_device)
100 dev->drop_device(ctx, dev);
101 fz_free(ctx, dev->container);
102 fz_free(ctx, dev);
103 }
104 }
105
106 void
107 fz_enable_device_hints(fz_context *ctx, fz_device *dev, int hints)
108 {
109 dev->hints |= hints;
110 }
111
112 void
113 fz_disable_device_hints(fz_context *ctx, fz_device *dev, int hints)
114 {
115 dev->hints &= ~hints;
116 }
117
118 static void
119 push_clip_stack(fz_context *ctx, fz_device *dev, fz_rect rect, int type)
120 {
121 if (dev->container_len == dev->container_cap)
122 {
123 int newmax = dev->container_cap * 2;
124 if (newmax == 0)
125 newmax = 4;
126 dev->container = fz_realloc_array(ctx, dev->container, newmax, fz_device_container_stack);
127 dev->container_cap = newmax;
128 }
129 if (dev->container_len == 0)
130 dev->container[0].scissor = rect;
131 else
132 {
133 dev->container[dev->container_len].scissor = fz_intersect_rect(dev->container[dev->container_len-1].scissor, rect);
134 }
135 dev->container[dev->container_len].type = type;
136 dev->container[dev->container_len].user = 0;
137 dev->container_len++;
138 }
139
140 static void
141 pop_clip_stack(fz_context *ctx, fz_device *dev, int type)
142 {
143 if (dev->container_len == 0 || dev->container[dev->container_len-1].type != type)
144 {
145 fz_disable_device(ctx, dev);
146 fz_throw(ctx, FZ_ERROR_ARGUMENT, "device calls unbalanced");
147 }
148 dev->container_len--;
149 }
150
151 static void
152 pop_push_clip_stack(fz_context *ctx, fz_device *dev, int pop_type, int push_type)
153 {
154 if (dev->container_len == 0 || dev->container[dev->container_len-1].type != pop_type)
155 {
156 fz_disable_device(ctx, dev);
157 fz_throw(ctx, FZ_ERROR_ARGUMENT, "device calls unbalanced");
158 }
159 dev->container[dev->container_len-1].type = push_type;
160 }
161
162 void
163 fz_fill_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even_odd, fz_matrix ctm,
164 fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
165 {
166 if (dev->fill_path)
167 {
168 fz_try(ctx)
169 dev->fill_path(ctx, dev, path, even_odd, ctm, colorspace, color, alpha, color_params);
170 fz_catch(ctx)
171 {
172 fz_disable_device(ctx, dev);
173 fz_rethrow(ctx);
174 }
175 }
176 }
177
178 void
179 fz_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, const fz_stroke_state *stroke, fz_matrix ctm,
180 fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
181 {
182 if (dev->stroke_path)
183 {
184 fz_try(ctx)
185 dev->stroke_path(ctx, dev, path, stroke, ctm, colorspace, color, alpha, color_params);
186 fz_catch(ctx)
187 {
188 fz_disable_device(ctx, dev);
189 fz_rethrow(ctx);
190 }
191 }
192 }
193
194 void
195 fz_clip_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even_odd, fz_matrix ctm, fz_rect scissor)
196 {
197 fz_rect bbox = fz_bound_path(ctx, path, NULL, ctm);
198 bbox = fz_intersect_rect(bbox, scissor);
199 push_clip_stack(ctx, dev, bbox, fz_device_container_stack_is_clip);
200
201 if (dev->clip_path)
202 {
203 fz_try(ctx)
204 dev->clip_path(ctx, dev, path, even_odd, ctm, scissor);
205 fz_catch(ctx)
206 {
207 fz_disable_device(ctx, dev);
208 fz_rethrow(ctx);
209 }
210 }
211 }
212
213 void
214 fz_clip_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, const fz_stroke_state *stroke, fz_matrix ctm, fz_rect scissor)
215 {
216 fz_rect bbox = fz_bound_path(ctx, path, stroke, ctm);
217 bbox = fz_intersect_rect(bbox, scissor);
218 push_clip_stack(ctx, dev, bbox, fz_device_container_stack_is_clip);
219
220 if (dev->clip_stroke_path)
221 {
222 fz_try(ctx)
223 dev->clip_stroke_path(ctx, dev, path, stroke, ctm, scissor);
224 fz_catch(ctx)
225 {
226 fz_disable_device(ctx, dev);
227 fz_rethrow(ctx);
228 }
229 }
230 }
231
232 void
233 fz_fill_text(fz_context *ctx, fz_device *dev, const fz_text *text, fz_matrix ctm,
234 fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
235 {
236 if (dev->fill_text)
237 {
238 fz_try(ctx)
239 dev->fill_text(ctx, dev, text, ctm, colorspace, color, alpha, color_params);
240 fz_catch(ctx)
241 {
242 fz_disable_device(ctx, dev);
243 fz_rethrow(ctx);
244 }
245 }
246 }
247
248 void
249 fz_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_stroke_state *stroke, fz_matrix ctm,
250 fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
251 {
252 if (dev->stroke_text)
253 {
254 fz_try(ctx)
255 dev->stroke_text(ctx, dev, text, stroke, ctm, colorspace, color, alpha, color_params);
256 fz_catch(ctx)
257 {
258 fz_disable_device(ctx, dev);
259 fz_rethrow(ctx);
260 }
261 }
262 }
263
264 void
265 fz_clip_text(fz_context *ctx, fz_device *dev, const fz_text *text, fz_matrix ctm, fz_rect scissor)
266 {
267 fz_rect bbox = fz_bound_text(ctx, text, NULL, ctm);
268 bbox = fz_intersect_rect(bbox, scissor);
269 push_clip_stack(ctx, dev, bbox, fz_device_container_stack_is_clip);
270
271 if (dev->clip_text)
272 {
273 fz_try(ctx)
274 dev->clip_text(ctx, dev, text, ctm, scissor);
275 fz_catch(ctx)
276 {
277 fz_disable_device(ctx, dev);
278 fz_rethrow(ctx);
279 }
280 }
281 }
282
283 void
284 fz_clip_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_stroke_state *stroke, fz_matrix ctm, fz_rect scissor)
285 {
286 fz_rect bbox = fz_bound_text(ctx, text, stroke, ctm);
287 bbox = fz_intersect_rect(bbox, scissor);
288 push_clip_stack(ctx, dev, bbox, fz_device_container_stack_is_clip);
289
290 if (dev->clip_stroke_text)
291 {
292 fz_try(ctx)
293 dev->clip_stroke_text(ctx, dev, text, stroke, ctm, scissor);
294 fz_catch(ctx)
295 {
296 fz_disable_device(ctx, dev);
297 fz_rethrow(ctx);
298 }
299 }
300 }
301
302 void
303 fz_ignore_text(fz_context *ctx, fz_device *dev, const fz_text *text, fz_matrix ctm)
304 {
305 if (dev->ignore_text)
306 {
307 fz_try(ctx)
308 dev->ignore_text(ctx, dev, text, ctm);
309 fz_catch(ctx)
310 {
311 fz_disable_device(ctx, dev);
312 fz_rethrow(ctx);
313 }
314 }
315 }
316
317 void
318 fz_pop_clip(fz_context *ctx, fz_device *dev)
319 {
320 pop_clip_stack(ctx, dev, fz_device_container_stack_is_clip);
321
322 if (dev->pop_clip)
323 {
324 fz_try(ctx)
325 dev->pop_clip(ctx, dev);
326 fz_catch(ctx)
327 {
328 fz_disable_device(ctx, dev);
329 fz_rethrow(ctx);
330 }
331 }
332 }
333
334 void
335 fz_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, fz_matrix ctm, float alpha, fz_color_params color_params)
336 {
337 if (dev->fill_shade)
338 {
339 fz_try(ctx)
340 dev->fill_shade(ctx, dev, shade, ctm, alpha, color_params);
341 fz_catch(ctx)
342 {
343 fz_disable_device(ctx, dev);
344 fz_rethrow(ctx);
345 }
346 }
347 }
348
349 void
350 fz_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, fz_matrix ctm, float alpha, fz_color_params color_params)
351 {
352 if (image->colorspace == NULL)
353 fz_throw(ctx, FZ_ERROR_ARGUMENT, "argument to fill image must be a color image");
354 if (dev->fill_image)
355 {
356 fz_try(ctx)
357 dev->fill_image(ctx, dev, image, ctm, alpha, color_params);
358 fz_catch(ctx)
359 {
360 fz_disable_device(ctx, dev);
361 fz_rethrow(ctx);
362 }
363 }
364 }
365
366 void
367 fz_fill_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, fz_matrix ctm,
368 fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
369 {
370 if (dev->fill_image_mask)
371 {
372 fz_try(ctx)
373 dev->fill_image_mask(ctx, dev, image, ctm, colorspace, color, alpha, color_params);
374 fz_catch(ctx)
375 {
376 fz_disable_device(ctx, dev);
377 fz_rethrow(ctx);
378 }
379 }
380 }
381
382 void
383 fz_clip_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, fz_matrix ctm, fz_rect scissor)
384 {
385 fz_rect bbox = fz_transform_rect(fz_unit_rect, ctm);
386 bbox = fz_intersect_rect(bbox, scissor);
387 push_clip_stack(ctx, dev, bbox, fz_device_container_stack_is_clip);
388
389 if (dev->clip_image_mask)
390 {
391 fz_try(ctx)
392 dev->clip_image_mask(ctx, dev, image, ctm, scissor);
393 fz_catch(ctx)
394 {
395 fz_disable_device(ctx, dev);
396 fz_rethrow(ctx);
397 }
398 }
399 }
400
401 void
402 fz_begin_mask(fz_context *ctx, fz_device *dev, fz_rect area, int luminosity, fz_colorspace *colorspace, const float *bc, fz_color_params color_params)
403 {
404 push_clip_stack(ctx, dev, area, fz_device_container_stack_is_mask);
405
406 if (dev->begin_mask)
407 {
408 fz_try(ctx)
409 dev->begin_mask(ctx, dev, area, luminosity, colorspace, bc, color_params);
410 fz_catch(ctx)
411 {
412 fz_disable_device(ctx, dev);
413 fz_rethrow(ctx);
414 }
415 }
416 }
417
418 void
419 fz_end_mask_tr(fz_context *ctx, fz_device *dev, fz_function *fn)
420 {
421 pop_push_clip_stack(ctx, dev, fz_device_container_stack_is_mask, fz_device_container_stack_is_clip);
422
423 if (dev->end_mask)
424 {
425 fz_try(ctx)
426 dev->end_mask(ctx, dev, fn);
427 fz_catch(ctx)
428 {
429 fz_disable_device(ctx, dev);
430 fz_rethrow(ctx);
431 }
432 }
433 }
434
435 void
436 fz_end_mask(fz_context *ctx, fz_device *dev)
437 {
438 fz_end_mask_tr(ctx, dev, NULL);
439 }
440
441 void
442 fz_begin_group(fz_context *ctx, fz_device *dev, fz_rect area, fz_colorspace *cs, int isolated, int knockout, int blendmode, float alpha)
443 {
444 push_clip_stack(ctx, dev, area, fz_device_container_stack_is_group);
445
446 if (dev->begin_group)
447 {
448 fz_try(ctx)
449 dev->begin_group(ctx, dev, area, cs, isolated, knockout, blendmode, alpha);
450 fz_catch(ctx)
451 {
452 fz_disable_device(ctx, dev);
453 fz_rethrow(ctx);
454 }
455 }
456 }
457
458 void
459 fz_end_group(fz_context *ctx, fz_device *dev)
460 {
461 pop_clip_stack(ctx, dev, fz_device_container_stack_is_group);
462
463 if (dev->end_group)
464 {
465 fz_try(ctx)
466 dev->end_group(ctx, dev);
467 fz_catch(ctx)
468 {
469 fz_disable_device(ctx, dev);
470 fz_rethrow(ctx);
471 }
472 }
473 }
474
475 void
476 fz_begin_tile(fz_context *ctx, fz_device *dev, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm)
477 {
478 (void)fz_begin_tile_id(ctx, dev, area, view, xstep, ystep, ctm, 0);
479 }
480
481 int
482 fz_begin_tile_id(fz_context *ctx, fz_device *dev, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm, int id)
483 {
484 return fz_begin_tile_tid(ctx, dev, area, view, xstep, ystep, ctm, id, 0);
485 }
486
487 int
488 fz_begin_tile_tid(fz_context *ctx, fz_device *dev, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm, int id, int doc_id)
489 {
490 int result = 0;
491
492 push_clip_stack(ctx, dev, area, fz_device_container_stack_is_tile);
493
494 if (xstep < 0)
495 xstep = -xstep;
496 if (ystep < 0)
497 ystep = -ystep;
498 if (dev->begin_tile)
499 {
500 fz_try(ctx)
501 result = dev->begin_tile(ctx, dev, area, view, xstep, ystep, ctm, id, doc_id);
502 fz_catch(ctx)
503 {
504 fz_disable_device(ctx, dev);
505 fz_rethrow(ctx);
506 }
507 }
508
509 return result;
510 }
511
512 void
513 fz_end_tile(fz_context *ctx, fz_device *dev)
514 {
515 pop_clip_stack(ctx, dev, fz_device_container_stack_is_tile);
516
517 if (dev->end_tile)
518 {
519 fz_try(ctx)
520 dev->end_tile(ctx, dev);
521 fz_catch(ctx)
522 {
523 fz_disable_device(ctx, dev);
524 fz_rethrow(ctx);
525 }
526 }
527 }
528
529 void
530 fz_render_flags(fz_context *ctx, fz_device *dev, int set, int clear)
531 {
532 if (dev->render_flags)
533 {
534 fz_try(ctx)
535 dev->render_flags(ctx, dev, set, clear);
536 fz_catch(ctx)
537 {
538 fz_disable_device(ctx, dev);
539 fz_rethrow(ctx);
540 }
541 }
542 }
543
544 void
545 fz_set_default_colorspaces(fz_context *ctx, fz_device *dev, fz_default_colorspaces *default_cs)
546 {
547 if (dev->set_default_colorspaces)
548 {
549 fz_try(ctx)
550 dev->set_default_colorspaces(ctx, dev, default_cs);
551 fz_catch(ctx)
552 {
553 fz_disable_device(ctx, dev);
554 fz_rethrow(ctx);
555 }
556 }
557 }
558
559 void fz_begin_layer(fz_context *ctx, fz_device *dev, const char *layer_name)
560 {
561 if (dev->begin_layer)
562 {
563 fz_try(ctx)
564 dev->begin_layer(ctx, dev, layer_name);
565 fz_catch(ctx)
566 {
567 fz_disable_device(ctx, dev);
568 fz_rethrow(ctx);
569 }
570 }
571 }
572
573 void fz_end_layer(fz_context *ctx, fz_device *dev)
574 {
575 if (dev->end_layer)
576 {
577 fz_try(ctx)
578 dev->end_layer(ctx, dev);
579 fz_catch(ctx)
580 {
581 fz_disable_device(ctx, dev);
582 fz_rethrow(ctx);
583 }
584 }
585 }
586
587 void fz_begin_structure(fz_context *ctx, fz_device *dev, fz_structure str, const char *raw, int idx)
588 {
589 if (dev->begin_structure)
590 {
591 fz_try(ctx)
592 dev->begin_structure(ctx, dev, str, raw, idx);
593 fz_catch(ctx)
594 {
595 fz_disable_device(ctx, dev);
596 fz_rethrow(ctx);
597 }
598 }
599 }
600
601 void fz_end_structure(fz_context *ctx, fz_device *dev)
602 {
603 if (dev->end_structure)
604 {
605 fz_try(ctx)
606 dev->end_structure(ctx, dev);
607 fz_catch(ctx)
608 {
609 fz_disable_device(ctx, dev);
610 fz_rethrow(ctx);
611 }
612 }
613 }
614
615 void fz_begin_metatext(fz_context *ctx, fz_device *dev, fz_metatext meta, const char *meta_text)
616 {
617 if (dev->begin_metatext)
618 {
619 fz_try(ctx)
620 dev->begin_metatext(ctx, dev, meta, meta_text);
621 fz_catch(ctx)
622 {
623 fz_disable_device(ctx, dev);
624 fz_rethrow(ctx);
625 }
626 }
627 }
628
629 void fz_end_metatext(fz_context *ctx, fz_device *dev)
630 {
631 if (dev->end_metatext)
632 {
633 fz_try(ctx)
634 dev->end_metatext(ctx, dev);
635 fz_catch(ctx)
636 {
637 fz_disable_device(ctx, dev);
638 fz_rethrow(ctx);
639 }
640 }
641 }
642
643 fz_rect
644 fz_device_current_scissor(fz_context *ctx, fz_device *dev)
645 {
646 if (dev->container_len > 0)
647 return dev->container[dev->container_len-1].scissor;
648 return fz_infinite_rect;
649 }
650
651 const char *
652 fz_structure_to_string(fz_structure type)
653 {
654 switch (type)
655 {
656 default:
657 return "Invalid";
658 case FZ_STRUCTURE_DOCUMENT:
659 return "Document";
660 case FZ_STRUCTURE_PART:
661 return "Part";
662 case FZ_STRUCTURE_ART:
663 return "Art";
664 case FZ_STRUCTURE_SECT:
665 return "Sect";
666 case FZ_STRUCTURE_DIV:
667 return "Div";
668 case FZ_STRUCTURE_BLOCKQUOTE:
669 return "BlockQuote";
670 case FZ_STRUCTURE_CAPTION:
671 return "Caption";
672 case FZ_STRUCTURE_TOC:
673 return "TOC";
674 case FZ_STRUCTURE_TOCI:
675 return "TOCI";
676 case FZ_STRUCTURE_INDEX:
677 return "Index";
678 case FZ_STRUCTURE_NONSTRUCT:
679 return "NonDtruct";
680 case FZ_STRUCTURE_PRIVATE:
681 return "Private";
682 /* Grouping elements (PDF 2.0 - Table 364) */
683 case FZ_STRUCTURE_DOCUMENTFRAGMENT:
684 return "DocumentFragment";
685 /* Grouping elements (PDF 2.0 - Table 365) */
686 case FZ_STRUCTURE_ASIDE:
687 return "Aside";
688 /* Grouping elements (PDF 2.0 - Table 366) */
689 case FZ_STRUCTURE_TITLE:
690 return "Title";
691 case FZ_STRUCTURE_FENOTE:
692 return "FENote";
693 /* Grouping elements (PDF 2.0 - Table 367) */
694 case FZ_STRUCTURE_SUB:
695 return "Sub";
696
697 /* Paragraphlike elements (PDF 1.7 - Table 10.21) */
698 case FZ_STRUCTURE_P:
699 return "P";
700 case FZ_STRUCTURE_H:
701 return "H";
702 case FZ_STRUCTURE_H1:
703 return "H1";
704 case FZ_STRUCTURE_H2:
705 return "H2";
706 case FZ_STRUCTURE_H3:
707 return "H3";
708 case FZ_STRUCTURE_H4:
709 return "H4";
710 case FZ_STRUCTURE_H5:
711 return "H5";
712 case FZ_STRUCTURE_H6:
713 return "H6";
714
715 /* List elements (PDF 1.7 - Table 10.23) */
716 case FZ_STRUCTURE_LIST:
717 return "L";
718 case FZ_STRUCTURE_LISTITEM:
719 return "LI";
720 case FZ_STRUCTURE_LABEL:
721 return "Lbl";
722 case FZ_STRUCTURE_LISTBODY:
723 return "LBody";
724
725 /* Table elements (PDF 1.7 - Table 10.24) */
726 case FZ_STRUCTURE_TABLE:
727 return "Table";
728 case FZ_STRUCTURE_TR:
729 return "TR";
730 case FZ_STRUCTURE_TH:
731 return "TH";
732 case FZ_STRUCTURE_TD:
733 return "TD";
734 case FZ_STRUCTURE_THEAD:
735 return "THead";
736 case FZ_STRUCTURE_TBODY:
737 return "TBody";
738 case FZ_STRUCTURE_TFOOT:
739 return "TFoot";
740
741 /* Inline elements (PDF 1.7 - Table 10.25) */
742 case FZ_STRUCTURE_SPAN:
743 return "Span";
744 case FZ_STRUCTURE_QUOTE:
745 return "Quote";
746 case FZ_STRUCTURE_NOTE:
747 return "Note";
748 case FZ_STRUCTURE_REFERENCE:
749 return "Reference";
750 case FZ_STRUCTURE_BIBENTRY:
751 return "BibEntry";
752 case FZ_STRUCTURE_CODE:
753 return "Code";
754 case FZ_STRUCTURE_LINK:
755 return "Link";
756 case FZ_STRUCTURE_ANNOT:
757 return "Annot";
758 /* Inline elements (PDF 2.0 - Table 368) */
759 case FZ_STRUCTURE_EM:
760 return "Em";
761 case FZ_STRUCTURE_STRONG:
762 return "Strong";
763
764 /* Ruby inline element (PDF 1.7 - Table 10.26) */
765 case FZ_STRUCTURE_RUBY:
766 return "Ruby";
767 case FZ_STRUCTURE_RB:
768 return "RB";
769 case FZ_STRUCTURE_RT:
770 return "RT";
771 case FZ_STRUCTURE_RP:
772 return "RP";
773
774 /* Warichu inline element (PDF 1.7 - Table 10.26) */
775 case FZ_STRUCTURE_WARICHU:
776 return "Warichu";
777 case FZ_STRUCTURE_WT:
778 return "WT";
779 case FZ_STRUCTURE_WP:
780 return "WP";
781
782 /* Illustration elements (PDF 1.7 - Table 10.27) */
783 case FZ_STRUCTURE_FIGURE:
784 return "Figure";
785 case FZ_STRUCTURE_FORMULA:
786 return "Formula";
787 case FZ_STRUCTURE_FORM:
788 return "Form";
789
790 /* Artifact structure type (PDF 2.0 - Table 375) */
791 case FZ_STRUCTURE_ARTIFACT:
792 return "Artifact";
793 }
794 }
795
796 fz_structure
797 fz_structure_from_string(const char *str)
798 {
799 if (!strcmp(str, "Document")) return FZ_STRUCTURE_DOCUMENT;
800 if (!strcmp(str, "Part")) return FZ_STRUCTURE_PART;
801 if (!strcmp(str, "Art")) return FZ_STRUCTURE_ART;
802 if (!strcmp(str, "Sect")) return FZ_STRUCTURE_SECT;
803 if (!strcmp(str, "Div")) return FZ_STRUCTURE_DIV;
804 if (!strcmp(str, "BlockQuote")) return FZ_STRUCTURE_BLOCKQUOTE;
805 if (!strcmp(str, "Caption")) return FZ_STRUCTURE_CAPTION;
806 if (!strcmp(str, "TOC")) return FZ_STRUCTURE_TOC;
807 if (!strcmp(str, "TOCI")) return FZ_STRUCTURE_TOCI;
808 if (!strcmp(str, "Index")) return FZ_STRUCTURE_INDEX;
809 if (!strcmp(str, "NonStruct")) return FZ_STRUCTURE_NONSTRUCT;
810 if (!strcmp(str, "Private")) return FZ_STRUCTURE_PRIVATE;
811 if (!strcmp(str, "P")) return FZ_STRUCTURE_P;
812 if (!strcmp(str, "H")) return FZ_STRUCTURE_H;
813 if (!strcmp(str, "H1")) return FZ_STRUCTURE_H1;
814 if (!strcmp(str, "H2")) return FZ_STRUCTURE_H2;
815 if (!strcmp(str, "H3")) return FZ_STRUCTURE_H3;
816 if (!strcmp(str, "H4")) return FZ_STRUCTURE_H4;
817 if (!strcmp(str, "H5")) return FZ_STRUCTURE_H5;
818 if (!strcmp(str, "H6")) return FZ_STRUCTURE_H6;
819 if (!strcmp(str, "L")) return FZ_STRUCTURE_LIST;
820 if (!strcmp(str, "LI")) return FZ_STRUCTURE_LISTITEM;
821 if (!strcmp(str, "Lbl")) return FZ_STRUCTURE_LABEL;
822 if (!strcmp(str, "LBody")) return FZ_STRUCTURE_LISTBODY;
823 if (!strcmp(str, "Table")) return FZ_STRUCTURE_TABLE;
824 if (!strcmp(str, "TR")) return FZ_STRUCTURE_TR;
825 if (!strcmp(str, "TH")) return FZ_STRUCTURE_TH;
826 if (!strcmp(str, "TD")) return FZ_STRUCTURE_TD;
827 if (!strcmp(str, "THead")) return FZ_STRUCTURE_THEAD;
828 if (!strcmp(str, "TBody")) return FZ_STRUCTURE_TBODY;
829 if (!strcmp(str, "TFoot")) return FZ_STRUCTURE_TFOOT;
830 if (!strcmp(str, "Span")) return FZ_STRUCTURE_SPAN;
831 if (!strcmp(str, "Quote")) return FZ_STRUCTURE_QUOTE;
832 if (!strcmp(str, "Note")) return FZ_STRUCTURE_NOTE;
833 if (!strcmp(str, "Reference")) return FZ_STRUCTURE_REFERENCE;
834 if (!strcmp(str, "BibEntry")) return FZ_STRUCTURE_BIBENTRY;
835 if (!strcmp(str, "Code")) return FZ_STRUCTURE_CODE;
836 if (!strcmp(str, "Link")) return FZ_STRUCTURE_LINK;
837 if (!strcmp(str, "Annot")) return FZ_STRUCTURE_ANNOT;
838 if (!strcmp(str, "Ruby")) return FZ_STRUCTURE_RUBY;
839 if (!strcmp(str, "RB")) return FZ_STRUCTURE_RB;
840 if (!strcmp(str, "RT")) return FZ_STRUCTURE_RT;
841 if (!strcmp(str, "RP")) return FZ_STRUCTURE_RP;
842 if (!strcmp(str, "Warichu")) return FZ_STRUCTURE_WARICHU;
843 if (!strcmp(str, "WT")) return FZ_STRUCTURE_WT;
844 if (!strcmp(str, "WP")) return FZ_STRUCTURE_WP;
845 if (!strcmp(str, "Figure")) return FZ_STRUCTURE_FIGURE;
846 if (!strcmp(str, "Formula")) return FZ_STRUCTURE_FORMULA;
847 if (!strcmp(str, "Form")) return FZ_STRUCTURE_FORM;
848 return FZ_STRUCTURE_INVALID;
849 }
850
851 fz_function *
852 fz_keep_function(fz_context *ctx, fz_function *func)
853 {
854 return fz_keep_storable(ctx, &func->storable);
855 }
856
857 void
858 fz_drop_function(fz_context *ctx, fz_function *func)
859 {
860 fz_drop_storable(ctx, &func->storable);
861 }
862
863 size_t
864 fz_function_size(fz_context *ctx, fz_function *func)
865 {
866 return (func ? func->size : 0);
867 }
868
869 void
870 fz_eval_function(fz_context *ctx, fz_function *func, const float *in, int inlen, float *out, int outlen)
871 {
872 float fakein[FZ_FUNCTION_MAX_M];
873 float fakeout[FZ_FUNCTION_MAX_N];
874 int i;
875
876 if (inlen < func->m)
877 {
878 for (i = 0; i < inlen; ++i)
879 fakein[i] = in[i];
880 for (; i < func->m; ++i)
881 fakein[i] = 0;
882 in = fakein;
883 }
884
885 if (outlen < func->n)
886 {
887 func->eval(ctx, func, in, fakeout);
888 for (i = 0; i < outlen; ++i)
889 out[i] = fakeout[i];
890 }
891 else
892 {
893 func->eval(ctx, func, in, out);
894 for (i = func->n; i < outlen; ++i)
895 out[i] = 0;
896 }
897 }
898
899 fz_function *
900 fz_new_function_of_size(fz_context *ctx, int size, size_t size2, int m, int n, fz_function_eval_fn *eval, fz_store_drop_fn *drop)
901 {
902 fz_function *fn = fz_calloc(ctx, 1, size);
903
904 FZ_INIT_STORABLE(fn, 1, drop);
905 fn->eval = eval;
906 fn->m = m;
907 fn->n = n;
908
909 return fn;
910 }