comparison mupdf-source/source/fitz/draw-imp.h @ 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-2021 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 #ifndef MUPDF_DRAW_IMP_H
24 #define MUPDF_DRAW_IMP_H
25
26 #define BBOX_MIN -(1<<20)
27 #define BBOX_MAX (1<<20)
28
29 /* divide and floor towards -inf */
30 static inline int fz_idiv(int a, int b)
31 {
32 return a < 0 ? (a - b + 1) / b : a / b;
33 }
34
35 /* divide and ceil towards inf */
36 static inline int fz_idiv_up(int a, int b)
37 {
38 return a < 0 ? a / b : (a + b - 1) / b;
39 }
40
41 #ifdef AA_BITS
42
43 #define fz_aa_scale 0
44 #define fz_rasterizer_aa_scale(ras) 0
45
46 #if AA_BITS > 6
47 #define AA_SCALE(s, x) (x)
48 #define fz_aa_hscale 17
49 #define fz_aa_vscale 15
50 #define fz_aa_bits 8
51 #define fz_aa_text_bits 8
52 #define fz_rasterizer_aa_hscale(ras) 17
53 #define fz_rasterizer_aa_vscale(ras) 15
54 #define fz_rasterizer_aa_bits(ras) 8
55 #define fz_rasterizer_aa_text_bits(ras) 8
56
57 #elif AA_BITS > 4
58 #define AA_SCALE(s, x) ((x * 255) >> 6)
59 #define fz_aa_hscale 8
60 #define fz_aa_vscale 8
61 #define fz_aa_bits 6
62 #define fz_aa_text_bits 6
63 #define fz_rasterizer_aa_hscale(ras) 8
64 #define fz_rasterizer_aa_vscale(ras) 8
65 #define fz_rasterizer_aa_bits(ras) 6
66 #define fz_rasterizer_aa_text_bits(ras) 6
67
68 #elif AA_BITS > 2
69 #define AA_SCALE(s, x) (x * 17)
70 #define fz_aa_hscale 5
71 #define fz_aa_vscale 3
72 #define fz_aa_bits 4
73 #define fz_aa_text_bits 4
74 #define fz_rasterizer_aa_hscale(ras) 5
75 #define fz_rasterizer_aa_vscale(ras) 3
76 #define fz_rasterizer_aa_bits(ras) 4
77 #define fz_rasterizer_aa_text_bits(ras) 4
78
79 #elif AA_BITS > 0
80 #define AA_SCALE(s, x) ((x * 255) >> 2)
81 #define fz_aa_hscale 2
82 #define fz_aa_vscale 2
83 #define fz_aa_bits 2
84 #define fz_aa_text_bits 2
85 #define fz_rasterizer_aa_hscale(ras) 2
86 #define fz_rasterizer_aa_vscale(ras) 2
87 #define fz_rasterizer_aa_bits(ras) 2
88 #define fz_rasterizer_aa_text_bits(ras) 2
89
90 #else
91 #define AA_SCALE(s, x) (x * 255)
92 #define fz_aa_hscale 1
93 #define fz_aa_vscale 1
94 #define fz_aa_bits 0
95 #define fz_aa_text_bits 0
96 #define fz_rasterizer_aa_hscale(ras) 1
97 #define fz_rasterizer_aa_vscale(ras) 1
98 #define fz_rasterizer_aa_bits(ras) 0
99 #define fz_rasterizer_aa_text_bits(ras) 0
100
101 #endif
102 #else
103
104 #define AA_SCALE(scale, x) ((x * scale) >> 8)
105 #define fz_aa_hscale (ctx->aa.hscale)
106 #define fz_aa_vscale (ctx->aa.vscale)
107 #define fz_aa_scale (ctx->aa.scale)
108 #define fz_aa_bits (ctx->aa.bits)
109 #define fz_aa_text_bits (ctx->aa.text_bits)
110 #define fz_rasterizer_aa_hscale(ras) ((ras)->aa.hscale)
111 #define fz_rasterizer_aa_vscale(ras) ((ras)->aa.vscale)
112 #define fz_rasterizer_aa_scale(ras) ((ras)->aa.scale)
113 #define fz_rasterizer_aa_bits(ras) ((ras)->aa.bits)
114 #define fz_rasterizer_aa_text_bits(ras) ((ras)->aa.text_bits)
115
116 #endif
117
118 /* If AA_BITS is defined, then we assume constant N bits of antialiasing. We
119 * will attempt to provide at least that number of bits of accuracy in the
120 * antialiasing (to a maximum of 8). If it is defined to be 0 then no
121 * antialiasing is done. If it is undefined to we will leave the antialiasing
122 * accuracy as a run time choice.
123 */
124
125 struct fz_overprint
126 {
127 /* Bit i set -> never alter this color */
128 uint32_t mask[(FZ_MAX_COLORS+31)/32];
129 };
130
131 static void inline fz_set_overprint(fz_overprint *op, int i)
132 {
133 op->mask[i>>5] |= 1<<(i&31);
134 }
135
136 static int inline fz_overprint_component(const fz_overprint *op, int i)
137 {
138 return ((op->mask[i>>5]>>(i & 31)) & 1) == 0;
139 }
140
141 static int inline fz_overprint_required(const fz_overprint *op)
142 {
143 int i;
144
145 if (op == NULL)
146 return 0;
147
148 for (i = 0; i < (FZ_MAX_COLORS+31)/32; i++)
149 if (op->mask[i] != 0)
150 return 1;
151
152 return 0;
153 }
154
155 typedef struct fz_rasterizer fz_rasterizer;
156
157 typedef void (fz_rasterizer_drop_fn)(fz_context *ctx, fz_rasterizer *r);
158 typedef int (fz_rasterizer_reset_fn)(fz_context *ctx, fz_rasterizer *r);
159 typedef void (fz_rasterizer_postindex_fn)(fz_context *ctx, fz_rasterizer *r);
160 typedef void (fz_rasterizer_insert_fn)(fz_context *ctx, fz_rasterizer *r, float x0, float y0, float x1, float y1, int rev);
161 typedef void (fz_rasterizer_insert_rect_fn)(fz_context *ctx, fz_rasterizer *r, float fx0, float fy0, float fx1, float fy1);
162 typedef void (fz_rasterizer_gap_fn)(fz_context *ctx, fz_rasterizer *r);
163 typedef fz_irect *(fz_rasterizer_bound_fn)(fz_context *ctx, const fz_rasterizer *r, fz_irect *bbox);
164 typedef void (fz_rasterizer_fn)(fz_context *ctx, fz_rasterizer *r, int eofill, const fz_irect *clip, fz_pixmap *pix, unsigned char *colorbv, fz_overprint *eop);
165 typedef int (fz_rasterizer_is_rect_fn)(fz_context *ctx, fz_rasterizer *r);
166
167 typedef struct
168 {
169 fz_rasterizer_drop_fn *drop;
170 fz_rasterizer_reset_fn *reset;
171 fz_rasterizer_postindex_fn *postindex;
172 fz_rasterizer_insert_fn *insert;
173 fz_rasterizer_insert_rect_fn *rect;
174 fz_rasterizer_gap_fn *gap;
175 fz_rasterizer_fn *convert;
176 fz_rasterizer_is_rect_fn *is_rect;
177 int reusable;
178 } fz_rasterizer_fns;
179
180 struct fz_rasterizer
181 {
182 fz_rasterizer_fns fns;
183 fz_aa_context aa;
184 fz_irect clip; /* Specified clip rectangle */
185 fz_irect bbox; /* Measured bbox of path while stroking/filling */
186 };
187
188 /*
189 When rasterizing a shape, we first create a rasterizer then
190 run through the edges of the shape, feeding them in.
191
192 For a fill, this is easy as we just run along the path, feeding
193 edges as we go.
194
195 For a stroke, this is trickier, as we feed in edges from
196 alternate sides of the stroke as we proceed along it. It is only
197 when we reach the end of a subpath that we know whether we need
198 an initial cap, or whether the list of edges match up.
199
200 To identify whether a given edge fed in is forward or reverse,
201 we tag it with a 'rev' value.
202
203 Consider the following simplified example:
204
205 Consider a simple path A, B, C, D, close.
206
207 +------->-------+ The outside edge of this shape is the
208 | A B | forward edge. This is fed into the rasterizer
209 | +---<---+ | in order, with rev=0.
210 | | | |
211 ^ v ^ v The inside edge of this shape is the reverse
212 | | | | edge. These edges are generated as we step
213 | +--->---+ | through the path in clockwise order, but
214 | D C | conceptually the path runs the other way.
215 +-------<-------+ These are fed into the rasterizer in clockwise
216 order, with rev=1.
217
218 Consider another path, this time an open one: A,B,C,D
219
220 +--->-------+ The outside edge of this shape is again the
221 * A B | forward edge. This is fed into the rasterizer
222 +---<---+ | in order, with rev=0.
223 | |
224 ^ v The inside edge of this shape is the reverse
225 | | edge. These edges are generated as we step
226 +--->---+ | through the path in clockwise order, but
227 ^ D C | conceptually the path runs the other way.
228 +---<-------+ These are fed into the rasterizer in clockwise
229 order, with rev=1.
230
231 At the end of the path, we realise that this is an open path, and we
232 therefore have to put caps on. The cap at 'D' is easy, because it's
233 a simple continuation of the rev=0 edge list that joins to the end
234 of the rev=1 edge list.
235
236 The cap at 'A' is trickier; it either needs to be (an) edge(s) prepended
237 to the rev=0 list or the rev=1 list. We signal this special case by
238 sending them with the special value rev=2.
239
240 The "edge" rasterizer ignores these values. The "edgebuffer" rasterizer
241 needs to use them to ensure that edges are correctly joined together
242 to allow for any part of a pixel operation.
243 */
244
245 /*
246 fz_new_rasterizer: Create a new rasterizer instance.
247 This encapsulates a scan converter.
248
249 A single rasterizer instance can be used to scan convert many
250 things.
251
252 aa: The antialiasing settings to use (or NULL).
253 */
254 fz_rasterizer *fz_new_rasterizer(fz_context *ctx, const fz_aa_context *aa);
255
256 /*
257 fz_drop_rasterizer: Dispose of a rasterizer once
258 finished with.
259 */
260 static inline void fz_drop_rasterizer(fz_context *ctx, fz_rasterizer *r)
261 {
262 if (r)
263 r->fns.drop(ctx, r);
264 }
265
266 /*
267 fz_reset_rasterizer: Reset a rasterizer, ready to scan convert
268 a new shape.
269
270 clip: A pointer to a (device space) clipping rectangle.
271
272 Returns 1 if a indexing pass is required, or 0 if not.
273
274 After this, the edges should be 'inserted' into the rasterizer.
275 */
276 int fz_reset_rasterizer(fz_context *ctx, fz_rasterizer *r, fz_irect clip);
277
278 /*
279 fz_insert_rasterizer: Insert an edge into a rasterizer.
280
281 x0, y0: Initial point
282
283 x1, y1: Final point
284
285 rev: 'reverse' value, 0, 1 or 2. See above.
286 */
287 static inline void fz_insert_rasterizer(fz_context *ctx, fz_rasterizer *r, float x0, float y0, float x1, float y1, int rev)
288 {
289 r->fns.insert(ctx, r, x0, y0, x1, y1, rev);
290 }
291
292 /*
293 fz_insert_rasterizer_rect: Insert a rectangle into a rasterizer.
294
295 x0, y0: One corner of the rectangle.
296
297 x1, y1: The opposite corner of the rectangle.
298
299 The rectangle inserted is conceptually:
300 (x0,y0)->(x1,y0)->(x1,y1)->(x0,y1)->(x0,y0).
301
302 This method is only used for axis aligned rectangles,
303 and enables rasterizers to perform special 'anti-dropout'
304 processing to ensure that horizontal artifacts aren't
305 lost.
306 */
307 static inline void fz_insert_rasterizer_rect(fz_context *ctx, fz_rasterizer *r, float x0, float y0, float x1, float y1)
308 {
309 r->fns.rect(ctx, r, x0, y0, x1, y1);
310 }
311
312 /*
313 fz_gap_rasterizer: Called to indicate that there is a gap
314 in the lists of edges fed into the rasterizer (i.e. when
315 a path hits a move).
316 */
317 static inline void fz_gap_rasterizer(fz_context *ctx, fz_rasterizer *r)
318 {
319 if (r->fns.gap)
320 r->fns.gap(ctx, r);
321 }
322
323 /*
324 fz_antidropout_rasterizer: Detect whether antidropout
325 behaviour is required with this rasterizer.
326
327 Returns 1 if required, 0 otherwise.
328 */
329 static inline int fz_antidropout_rasterizer(fz_context *ctx, fz_rasterizer *r)
330 {
331 return r->fns.rect != NULL;
332 }
333
334 /*
335 fz_postindex_rasterizer: Called to signify the end of the
336 indexing phase.
337
338 After this has been called, the edges should be inserted
339 again.
340 */
341 static inline void fz_postindex_rasterizer(fz_context *ctx, fz_rasterizer *r)
342 {
343 if (r->fns.postindex)
344 r->fns.postindex(ctx, r);
345 }
346
347 /*
348 fz_bound_rasterizer: Once a set of edges has been fed into a
349 rasterizer, the (device space) bounding box can be retrieved.
350 */
351 fz_irect fz_bound_rasterizer(fz_context *ctx, const fz_rasterizer *rast);
352
353 /*
354 fz_scissor_rasterizer: Retrieve the clipping box with which the
355 rasterizer was reset.
356 */
357 fz_rect fz_scissor_rasterizer(fz_context *ctx, const fz_rasterizer *rast);
358
359 /*
360 fz_convert_rasterizer: Convert the set of edges that have
361 been fed in, into pixels within the pixmap.
362
363 eofill: Fill rule; True for even odd, false for non zero.
364
365 pix: The pixmap to fill into.
366
367 colorbv: The color components corresponding to the pixmap.
368
369 eop: effective overprint.
370 */
371 void fz_convert_rasterizer(fz_context *ctx, fz_rasterizer *r, int eofill, fz_pixmap *pix, unsigned char *colorbv, fz_overprint *eop);
372
373 /*
374 fz_is_rect_rasterizer: Detect if the edges fed into a
375 rasterizer make up a simple rectangle.
376 */
377 static inline int fz_is_rect_rasterizer(fz_context *ctx, fz_rasterizer *r)
378 {
379 return r->fns.is_rect(ctx, r);
380 }
381
382 void *fz_new_rasterizer_of_size(fz_context *ctx, int size, const fz_rasterizer_fns *fns);
383
384 #define fz_new_derived_rasterizer(C,M,F) \
385 ((M*)Memento_label(fz_new_rasterizer_of_size(C, sizeof(M), F), #M))
386
387 /*
388 fz_rasterizer_text_aa_level: Get the number of bits of
389 antialiasing we are using for text in a given rasterizer.
390 Between 0 and 8.
391 */
392 int fz_rasterizer_text_aa_level(fz_rasterizer *ras);
393
394 /*
395 fz_set_rasterizer_text_aa_level: Set the number of bits of
396 antialiasing we should use for text in a given configuration.
397
398 bits: The number of bits of antialiasing to use (values are clamped
399 to within the 0 to 8 range).
400 */
401 void fz_set_rasterizer_text_aa_level(fz_context *ctx, fz_aa_context *aa, int bits);
402
403 /*
404 fz_rasterizer_graphics_aa_level: Get the number of bits of
405 antialiasing we are using for graphics in a given rasterizer.
406
407 Between 0 and 8.
408 */
409 int fz_rasterizer_graphics_aa_level(fz_rasterizer *ras);
410
411 /*
412 fz_set_rasterizer_graphics_aa_level: Set the number of bits of
413 antialiasing we should use for graphics in a given rasterizer.
414
415 bits: The number of bits of antialiasing to use (values are clamped
416 to within the 0 to 8 range).
417 */
418 void fz_set_rasterizer_graphics_aa_level(fz_context *ctx, fz_aa_context *aa, int bits);
419
420 /*
421 fz_rasterizer_graphics_min_line_width: Get the minimum line
422 width to be used for stroked lines in a given rasterizer.
423
424 min_line_width: The minimum line width to use (in pixels).
425 */
426 float fz_rasterizer_graphics_min_line_width(fz_rasterizer *ras);
427
428 /*
429 fz_set_rasterizer_graphics_min_line_width: Set the minimum line
430 width to be used for stroked lines in a given configuration.
431
432 min_line_width: The minimum line width to use (in pixels).
433 */
434 void fz_set_rasterizer_graphics_min_line_width(fz_context *ctx, fz_aa_context *aa, float min_line_width);
435
436 fz_rasterizer *fz_new_gel(fz_context *ctx);
437
438 typedef enum
439 {
440 FZ_EDGEBUFFER_ANY_PART_OF_PIXEL,
441 FZ_EDGEBUFFER_CENTER_OF_PIXEL
442 } fz_edgebuffer_rule;
443
444 fz_rasterizer *fz_new_edgebuffer(fz_context *ctx, fz_edgebuffer_rule rule);
445
446 int fz_flatten_fill_path(fz_context *ctx, fz_rasterizer *rast, const fz_path *path, fz_matrix ctm, float flatness, fz_irect scissor, fz_irect *bbox);
447 int fz_flatten_stroke_path(fz_context *ctx, fz_rasterizer *rast, const fz_path *path, const fz_stroke_state *stroke, fz_matrix ctm, float flatness, float linewidth, fz_irect scissor, fz_irect *bbox);
448
449 fz_irect *fz_bound_path_accurate(fz_context *ctx, fz_irect *bbox, fz_irect scissor, const fz_path *path, const fz_stroke_state *stroke, fz_matrix ctm, float flatness, float linewidth);
450
451 typedef void (fz_solid_color_painter_t)(unsigned char * FZ_RESTRICT dp, int n, int w, const unsigned char * FZ_RESTRICT color, int da, const fz_overprint * FZ_RESTRICT eop);
452
453 typedef void (fz_span_painter_t)(unsigned char * FZ_RESTRICT dp, int da, const unsigned char * FZ_RESTRICT sp, int sa, int n, int w, int alpha, const fz_overprint * FZ_RESTRICT eop);
454 typedef void (fz_span_color_painter_t)(unsigned char * FZ_RESTRICT dp, const unsigned char * FZ_RESTRICT mp, int n, int w, const unsigned char * FZ_RESTRICT color, int da, const fz_overprint * FZ_RESTRICT eop);
455
456 fz_solid_color_painter_t *fz_get_solid_color_painter(int n, const unsigned char * FZ_RESTRICT color, int da, const fz_overprint * FZ_RESTRICT eop);
457 fz_span_painter_t *fz_get_span_painter(int da, int sa, int n, int alpha, const fz_overprint * FZ_RESTRICT eop);
458 fz_span_color_painter_t *fz_get_span_color_painter(int n, int da, const unsigned char * FZ_RESTRICT color, const fz_overprint * FZ_RESTRICT eop);
459
460 void fz_paint_image(fz_context *ctx, fz_pixmap * FZ_RESTRICT dst, const fz_irect * FZ_RESTRICT scissor, fz_pixmap * FZ_RESTRICT shape, fz_pixmap * FZ_RESTRICT group_alpha, fz_pixmap * FZ_RESTRICT img, fz_matrix ctm, int alpha, int lerp_allowed, const fz_overprint * FZ_RESTRICT eop);
461 void fz_paint_image_with_color(fz_context *ctx, fz_pixmap * FZ_RESTRICT dst, const fz_irect * FZ_RESTRICT scissor, fz_pixmap * FZ_RESTRICT shape, fz_pixmap * FZ_RESTRICT group_alpha, fz_pixmap * FZ_RESTRICT img, fz_matrix ctm, const unsigned char * FZ_RESTRICT colorbv, int lerp_allowed, const fz_overprint * FZ_RESTRICT eop);
462
463 void fz_paint_pixmap(fz_pixmap * FZ_RESTRICT dst, const fz_pixmap * FZ_RESTRICT src, int alpha);
464 void fz_paint_pixmap_alpha(fz_pixmap * FZ_RESTRICT dst, const fz_pixmap * FZ_RESTRICT src, int alpha);
465 void fz_paint_pixmap_with_mask(fz_pixmap * FZ_RESTRICT dst, const fz_pixmap * FZ_RESTRICT src, const fz_pixmap * FZ_RESTRICT msk);
466 void fz_paint_over_pixmap_with_mask(fz_pixmap * FZ_RESTRICT dst, const fz_pixmap * FZ_RESTRICT src, const fz_pixmap * FZ_RESTRICT msk);
467 void fz_paint_pixmap_with_bbox(fz_pixmap * FZ_RESTRICT dst, const fz_pixmap * FZ_RESTRICT src, int alpha, fz_irect bbox);
468 void fz_paint_pixmap_with_overprint(fz_pixmap * FZ_RESTRICT dst, const fz_pixmap * FZ_RESTRICT src, const fz_overprint * FZ_RESTRICT eop);
469
470 void fz_blend_pixmap(fz_context *ctx, fz_pixmap * FZ_RESTRICT dst, fz_pixmap * FZ_RESTRICT src, int alpha, int blendmode, int isolated, const fz_pixmap * FZ_RESTRICT shape);
471 void fz_blend_pixmap_knockout(fz_context *ctx, fz_pixmap * FZ_RESTRICT dst, fz_pixmap * FZ_RESTRICT src, const fz_pixmap * FZ_RESTRICT shape);
472
473 void fz_paint_glyph(const unsigned char * FZ_RESTRICT colorbv, fz_pixmap * FZ_RESTRICT dst, unsigned char * FZ_RESTRICT dp, const fz_glyph * FZ_RESTRICT glyph, int w, int h, int skip_x, int skip_y, const fz_overprint * FZ_RESTRICT eop);
474
475 #endif