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