Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/source/fitz/device.c @ 3:2c135c81b16c
MERGE: upstream PyMuPDF 1.26.4 with MuPDF 1.26.7
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:44:09 +0200 |
| parents | b50eed0cc0ef |
| children |
comparison
equal
deleted
inserted
replaced
| 0:6015a75abc2d | 3:2c135c81b16c |
|---|---|
| 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 } |
