1 /* Copyright (C) 2001-2012 Artifex Software, Inc.
2    All Rights Reserved.
3 
4    This software is provided AS-IS with no warranty, either express or
5    implied.
6 
7    This software is distributed under license and may not be copied,
8    modified or distributed except as expressly authorized under the terms
9    of the license contained in the file LICENSE in this distribution.
10 
11    Refer to licensing information at http://www.artifex.com or contact
12    Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134, San Rafael,
13    CA  94903, U.S.A., +1(415)492-9861, for further information.
14 */
15 
16 
17 /* Dropout prevention for a character rasterization. */
18 
19 #ifndef gxfdrop_INCLUDED
20 #  define gxfdrop_INCLUDED
21 
22 /*  The structure margin_set and related structures and functions are used for
23     preventing dropouts rasterizing a character with zero fill adjustment. The purpose
24     is to paint something along thin quazi-horizontal stems,
25     which are composed of multiple small segments (such as a result of flattenpath).
26     We call it "pseudo-rasterization".
27     When fill adjustment takes place, this stuff is not required and is being skipped.
28 
29     To prevent dropouts in thin quazi-horizontal stems we look at raster
30     through 1xN pixels window, where N is the width of the path bounding box.
31     This window moves from bottom to top synchronousely with the motion of
32     the filling loop, but its Y coordinate is always an integer plus one half
33     (actually it moves convulsively).
34     Through this window we can see an upper half of a pixel row,
35     and lower half of the next pixel row. Painted spots are visible through
36     this window as a set of "margins". To handle them we maintain
37     a list of margin_s structures (each of which describes an interval
38     to be painted), and array of "sections" (i-th section corresponds to
39     half-integer X-coordinate Xi = bbox_left + i + 0.5, and stores fraction
40     part of y-coordinate of intersection of the line x == Xi with margin
41     boudaries, being visible through window (only extremal coordinates are stored
42     into a section)).
43 
44     The structure margin_set snaps what has been painted inside window.
45     We handle 2 instances of margin_set : margin_set0 is being prepared and margin_set1 is
46     being refinished. When the filling loop steps down over a pixel center,
47     the refinished window is closed and released, the prapared window becomes
48     the refinished one, and a new one starts to prepare.
49 
50     fixme:
51     The current implementation is not optimised for very bold characters.
52     We could encrease performance for them with maintaining
53     a separate list of "exclusive" margins, which correspond
54     to intervals painted with regular trapezoids and made with
55     complete_margin. Using them we could skip access to 'sect' array elements
56     inside "exclusive" margins, so that the number of small steps
57     sensibly decreeses.
58 
59     fixme:
60     Another optimization could be applied to the regular(old) trapezoid algorithm.
61     Currently it breaks stems at any step of the Y cycle,
62     generating big number of trapezoids.
63     Perhaps we could store trapezoid vertices to active_line,
64     and delay rendering a trapezoid until stem changes boundary segments.
65     This also would make calls to the margin staff less frequent.
66 
67 */
68 
69 /*
70  * Configuration flags for the dropout prevention code.
71  */
72 #define ADJUST_SERIF 1 /* See comments near occurances. */
73 #define CHECK_SPOT_CONTIGUITY 1 /* See comments near occurances. */
74 
75 #ifndef active_line_DEFINED
76 #  define active_line_DEFINED
77 typedef struct active_line_s active_line;
78 #endif
79 
80 #ifndef line_list_DEFINED
81 #  define line_list_DEFINED
82 typedef struct line_list_s line_list;
83 #endif
84 
85 typedef struct margin_s
86 {   int ibeg, iend; /* Pixel indices of an interval to paint. */
87     struct margin_s *prev, *next;
88 } margin;
89 
90 typedef struct section_s
91 {   short y0, y1; /* Fraction part of y coordinates of intersections of the margin with line x==i + bbox_left */
92 #if ADJUST_SERIF && CHECK_SPOT_CONTIGUITY
93     short x0, x1; /* Pixel coverage by X for checking the contiguity. */
94 #endif
95 } section;
96 
97 typedef struct margin_set_s
98 {   fixed y;
99     margin *margin_list, *margin_touched;
100     section *sect;
101 } margin_set;
102 
103 extern_st(st_section);
104 
105 /* vd_trace helpers. */
106 #define VD_SCALE 0.03
107 #define VD_RECT(x, y, w, h, c) vd_rect(int2fixed(x), int2fixed(y), int2fixed(x + w), int2fixed(y + h), 1, c)
108 #define VD_TRAP_COLOR RGB(0, 255, 255)
109 #define VD_MARG_COLOR RGB(255, 0, 0)
110 
111 void init_section(section *sect, int i0, int i1);
112 void free_all_margins(line_list * ll);
113 int close_margins(gx_device * dev, line_list * ll, margin_set *ms);
114 int process_h_lists(line_list * ll, active_line * plp, active_line * flp, active_line * alp, fixed y0, fixed y1);
115 int margin_interior(line_list * ll, active_line * flp, active_line * alp, fixed y0, fixed y1);
116 int start_margin_set(gx_device * dev, line_list * ll, fixed y0);
117 int continue_margin_common(line_list * ll, margin_set * set, active_line * flp, active_line * alp, fixed y0, fixed y1);
118 
119 #endif /* gxfdrop_INCLUDED */
120