bbox-device.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. // Copyright (C) 2004-2024 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. #include "mupdf/fitz.h"
  23. #include <assert.h>
  24. #define STACK_SIZE 96
  25. typedef struct fz_bbox_device_s
  26. {
  27. fz_device super;
  28. fz_rect *result;
  29. int top;
  30. fz_rect stack[STACK_SIZE];
  31. /* mask content and tiles are ignored */
  32. int ignore;
  33. } fz_bbox_device;
  34. static void
  35. fz_bbox_add_rect(fz_context *ctx, fz_device *dev, fz_rect rect, int clip)
  36. {
  37. fz_bbox_device *bdev = (fz_bbox_device*)dev;
  38. if (0 < bdev->top && bdev->top <= STACK_SIZE)
  39. {
  40. rect = fz_intersect_rect(rect, bdev->stack[bdev->top-1]);
  41. }
  42. if (!clip && bdev->top <= STACK_SIZE && !bdev->ignore)
  43. {
  44. *bdev->result = fz_union_rect(*bdev->result, rect);
  45. }
  46. if (clip && ++bdev->top <= STACK_SIZE)
  47. {
  48. bdev->stack[bdev->top-1] = rect;
  49. }
  50. }
  51. static void
  52. fz_bbox_fill_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even_odd, fz_matrix ctm,
  53. fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
  54. {
  55. fz_bbox_add_rect(ctx, dev, fz_bound_path(ctx, path, NULL, ctm), 0);
  56. }
  57. static void
  58. fz_bbox_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, const fz_stroke_state *stroke,
  59. fz_matrix ctm, fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
  60. {
  61. fz_bbox_add_rect(ctx, dev, fz_bound_path(ctx, path, stroke, ctm), 0);
  62. }
  63. static void
  64. fz_bbox_fill_text(fz_context *ctx, fz_device *dev, const fz_text *text, fz_matrix ctm,
  65. fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
  66. {
  67. fz_bbox_add_rect(ctx, dev, fz_bound_text(ctx, text, NULL, ctm), 0);
  68. }
  69. static void
  70. fz_bbox_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_stroke_state *stroke,
  71. fz_matrix ctm, fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
  72. {
  73. fz_bbox_add_rect(ctx, dev, fz_bound_text(ctx, text, stroke, ctm), 0);
  74. }
  75. static void
  76. fz_bbox_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, fz_matrix ctm, float alpha, fz_color_params color_params)
  77. {
  78. fz_bbox_add_rect(ctx, dev, fz_bound_shade(ctx, shade, ctm), 0);
  79. }
  80. static void
  81. fz_bbox_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, fz_matrix ctm, float alpha, fz_color_params color_params)
  82. {
  83. fz_bbox_add_rect(ctx, dev, fz_transform_rect(fz_unit_rect, ctm), 0);
  84. }
  85. static void
  86. fz_bbox_fill_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, fz_matrix ctm,
  87. fz_colorspace *colorspace, const float *color, float alpha, fz_color_params color_params)
  88. {
  89. fz_bbox_add_rect(ctx, dev, fz_transform_rect(fz_unit_rect, ctm), 0);
  90. }
  91. static void
  92. fz_bbox_clip_path(fz_context *ctx, fz_device *dev, const fz_path *path, int even_odd, fz_matrix ctm, fz_rect scissor)
  93. {
  94. fz_bbox_add_rect(ctx, dev, fz_bound_path(ctx, path, NULL, ctm), 1);
  95. }
  96. static void
  97. fz_bbox_clip_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, const fz_stroke_state *stroke, fz_matrix ctm, fz_rect scissor)
  98. {
  99. fz_bbox_add_rect(ctx, dev, fz_bound_path(ctx, path, stroke, ctm), 1);
  100. }
  101. static void
  102. fz_bbox_clip_text(fz_context *ctx, fz_device *dev, const fz_text *text, fz_matrix ctm, fz_rect scissor)
  103. {
  104. fz_bbox_add_rect(ctx, dev, fz_bound_text(ctx, text, NULL, ctm), 1);
  105. }
  106. static void
  107. fz_bbox_clip_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz_stroke_state *stroke, fz_matrix ctm, fz_rect scissor)
  108. {
  109. fz_bbox_add_rect(ctx, dev, fz_bound_text(ctx, text, stroke, ctm), 1);
  110. }
  111. static void
  112. fz_bbox_clip_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, fz_matrix ctm, fz_rect scissor)
  113. {
  114. fz_bbox_add_rect(ctx, dev, fz_transform_rect(fz_unit_rect, ctm), 1);
  115. }
  116. static void
  117. fz_bbox_pop_clip(fz_context *ctx, fz_device *dev)
  118. {
  119. fz_bbox_device *bdev = (fz_bbox_device*)dev;
  120. if (bdev->top > 0)
  121. bdev->top--;
  122. else
  123. fz_warn(ctx, "unexpected pop clip");
  124. }
  125. static void
  126. fz_bbox_begin_mask(fz_context *ctx, fz_device *dev, fz_rect rect, int luminosity, fz_colorspace *colorspace, const float *color, fz_color_params color_params)
  127. {
  128. fz_bbox_device *bdev = (fz_bbox_device*)dev;
  129. fz_bbox_add_rect(ctx, dev, rect, 1);
  130. bdev->ignore++;
  131. }
  132. static void
  133. fz_bbox_end_mask(fz_context *ctx, fz_device *dev, fz_function *tr)
  134. {
  135. fz_bbox_device *bdev = (fz_bbox_device*)dev;
  136. assert(bdev->ignore > 0);
  137. bdev->ignore--;
  138. }
  139. static void
  140. fz_bbox_begin_group(fz_context *ctx, fz_device *dev, fz_rect rect, fz_colorspace *cs, int isolated, int knockout, int blendmode, float alpha)
  141. {
  142. fz_bbox_add_rect(ctx, dev, rect, 1);
  143. }
  144. static void
  145. fz_bbox_end_group(fz_context *ctx, fz_device *dev)
  146. {
  147. fz_bbox_pop_clip(ctx, dev);
  148. }
  149. static int
  150. fz_bbox_begin_tile(fz_context *ctx, fz_device *dev, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm, int id)
  151. {
  152. fz_bbox_device *bdev = (fz_bbox_device*)dev;
  153. fz_bbox_add_rect(ctx, dev, fz_transform_rect(area, ctm), 0);
  154. bdev->ignore++;
  155. return 0;
  156. }
  157. static void
  158. fz_bbox_end_tile(fz_context *ctx, fz_device *dev)
  159. {
  160. fz_bbox_device *bdev = (fz_bbox_device*)dev;
  161. assert(bdev->ignore > 0);
  162. bdev->ignore--;
  163. }
  164. fz_device *
  165. fz_new_bbox_device(fz_context *ctx, fz_rect *result)
  166. {
  167. fz_bbox_device *dev = fz_new_derived_device(ctx, fz_bbox_device);
  168. dev->super.fill_path = fz_bbox_fill_path;
  169. dev->super.stroke_path = fz_bbox_stroke_path;
  170. dev->super.clip_path = fz_bbox_clip_path;
  171. dev->super.clip_stroke_path = fz_bbox_clip_stroke_path;
  172. dev->super.fill_text = fz_bbox_fill_text;
  173. dev->super.stroke_text = fz_bbox_stroke_text;
  174. dev->super.clip_text = fz_bbox_clip_text;
  175. dev->super.clip_stroke_text = fz_bbox_clip_stroke_text;
  176. dev->super.fill_shade = fz_bbox_fill_shade;
  177. dev->super.fill_image = fz_bbox_fill_image;
  178. dev->super.fill_image_mask = fz_bbox_fill_image_mask;
  179. dev->super.clip_image_mask = fz_bbox_clip_image_mask;
  180. dev->super.pop_clip = fz_bbox_pop_clip;
  181. dev->super.begin_mask = fz_bbox_begin_mask;
  182. dev->super.end_mask = fz_bbox_end_mask;
  183. dev->super.begin_group = fz_bbox_begin_group;
  184. dev->super.end_group = fz_bbox_end_group;
  185. dev->super.begin_tile = fz_bbox_begin_tile;
  186. dev->super.end_tile = fz_bbox_end_tile;
  187. dev->result = result;
  188. dev->top = 0;
  189. dev->ignore = 0;
  190. *result = fz_empty_rect;
  191. return (fz_device*)dev;
  192. }