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