|
1 /* |
|
2 * Copyright © 2004 Keith Packard |
|
3 * |
|
4 * Permission to use, copy, modify, distribute, and sell this software and its |
|
5 * documentation for any purpose is hereby granted without fee, provided that |
|
6 * the above copyright notice appear in all copies and that both that |
|
7 * copyright notice and this permission notice appear in supporting |
|
8 * documentation, and that the name of Keith Packard not be used in |
|
9 * advertising or publicity pertaining to distribution of the software without |
|
10 * specific, written prior permission. Keith Packard makes no |
|
11 * representations about the suitability of this software for any purpose. It |
|
12 * is provided "as is" without express or implied warranty. |
|
13 * |
|
14 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
|
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO |
|
16 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
|
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, |
|
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
|
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
|
20 * PERFORMANCE OF THIS SOFTWARE. |
|
21 */ |
|
22 |
|
23 #ifndef rasterize_span |
|
24 #endif |
|
25 |
|
26 static void |
|
27 RASTERIZE_EDGES (pixman_image_t *image, |
|
28 pixman_edge_t *l, |
|
29 pixman_edge_t *r, |
|
30 pixman_fixed_t t, |
|
31 pixman_fixed_t b) |
|
32 { |
|
33 pixman_fixed_t y = t; |
|
34 uint32_t *line; |
|
35 uint32_t *buf = (image)->bits.bits; |
|
36 int stride = (image)->bits.rowstride; |
|
37 int width = (image)->bits.width; |
|
38 |
|
39 line = buf + pixman_fixed_to_int (y) * stride; |
|
40 |
|
41 for (;;) |
|
42 { |
|
43 pixman_fixed_t lx; |
|
44 pixman_fixed_t rx; |
|
45 int lxi; |
|
46 int rxi; |
|
47 |
|
48 lx = l->x; |
|
49 rx = r->x; |
|
50 #if N_BITS == 1 |
|
51 /* For the non-antialiased case, round the coordinates up, in effect |
|
52 * sampling just slightly to the left of the pixel. This is so that |
|
53 * when the sample point lies exactly on the line, we round towards |
|
54 * north-west. |
|
55 * |
|
56 * (The AA case does a similar adjustment in RENDER_SAMPLES_X) |
|
57 */ |
|
58 lx += X_FRAC_FIRST(1) - pixman_fixed_e; |
|
59 rx += X_FRAC_FIRST(1) - pixman_fixed_e; |
|
60 #endif |
|
61 /* clip X */ |
|
62 if (lx < 0) |
|
63 lx = 0; |
|
64 if (pixman_fixed_to_int (rx) >= width) |
|
65 #if N_BITS == 1 |
|
66 rx = pixman_int_to_fixed (width); |
|
67 #else |
|
68 /* Use the last pixel of the scanline, covered 100%. |
|
69 * We can't use the first pixel following the scanline, |
|
70 * because accessing it could result in a buffer overrun. |
|
71 */ |
|
72 rx = pixman_int_to_fixed (width) - 1; |
|
73 #endif |
|
74 |
|
75 /* Skip empty (or backwards) sections */ |
|
76 if (rx > lx) |
|
77 { |
|
78 |
|
79 /* Find pixel bounds for span */ |
|
80 lxi = pixman_fixed_to_int (lx); |
|
81 rxi = pixman_fixed_to_int (rx); |
|
82 |
|
83 #if N_BITS == 1 |
|
84 { |
|
85 |
|
86 #define LEFT_MASK(x) \ |
|
87 (((x) & 0x1f) ? \ |
|
88 SCREEN_SHIFT_RIGHT (0xffffffff, (x) & 0x1f) : 0) |
|
89 #define RIGHT_MASK(x) \ |
|
90 (((32 - (x)) & 0x1f) ? \ |
|
91 SCREEN_SHIFT_LEFT (0xffffffff, (32 - (x)) & 0x1f) : 0) |
|
92 |
|
93 #define MASK_BITS(x,w,l,n,r) { \ |
|
94 n = (w); \ |
|
95 r = RIGHT_MASK ((x) + n); \ |
|
96 l = LEFT_MASK (x); \ |
|
97 if (l) { \ |
|
98 n -= 32 - ((x) & 0x1f); \ |
|
99 if (n < 0) { \ |
|
100 n = 0; \ |
|
101 l &= r; \ |
|
102 r = 0; \ |
|
103 } \ |
|
104 } \ |
|
105 n >>= 5; \ |
|
106 } |
|
107 |
|
108 uint32_t *a = line; |
|
109 uint32_t startmask; |
|
110 uint32_t endmask; |
|
111 int nmiddle; |
|
112 int width = rxi - lxi; |
|
113 int x = lxi; |
|
114 |
|
115 a += x >> 5; |
|
116 x &= 0x1f; |
|
117 |
|
118 MASK_BITS (x, width, startmask, nmiddle, endmask); |
|
119 |
|
120 if (startmask) { |
|
121 WRITE(image, a, READ(image, a) | startmask); |
|
122 a++; |
|
123 } |
|
124 while (nmiddle--) |
|
125 WRITE(image, a++, 0xffffffff); |
|
126 if (endmask) |
|
127 WRITE(image, a, READ(image, a) | endmask); |
|
128 } |
|
129 #else |
|
130 { |
|
131 DEFINE_ALPHA(line,lxi); |
|
132 int lxs; |
|
133 int rxs; |
|
134 |
|
135 /* Sample coverage for edge pixels */ |
|
136 lxs = RENDER_SAMPLES_X (lx, N_BITS); |
|
137 rxs = RENDER_SAMPLES_X (rx, N_BITS); |
|
138 |
|
139 /* Add coverage across row */ |
|
140 if (lxi == rxi) |
|
141 { |
|
142 ADD_ALPHA (rxs - lxs); |
|
143 } |
|
144 else |
|
145 { |
|
146 int xi; |
|
147 |
|
148 ADD_ALPHA (N_X_FRAC(N_BITS) - lxs); |
|
149 STEP_ALPHA; |
|
150 for (xi = lxi + 1; xi < rxi; xi++) |
|
151 { |
|
152 ADD_ALPHA (N_X_FRAC(N_BITS)); |
|
153 STEP_ALPHA; |
|
154 } |
|
155 ADD_ALPHA (rxs); |
|
156 } |
|
157 } |
|
158 #endif |
|
159 } |
|
160 |
|
161 if (y == b) |
|
162 break; |
|
163 |
|
164 #if N_BITS > 1 |
|
165 if (pixman_fixed_frac (y) != Y_FRAC_LAST(N_BITS)) |
|
166 { |
|
167 RENDER_EDGE_STEP_SMALL (l); |
|
168 RENDER_EDGE_STEP_SMALL (r); |
|
169 y += STEP_Y_SMALL(N_BITS); |
|
170 } |
|
171 else |
|
172 #endif |
|
173 { |
|
174 RENDER_EDGE_STEP_BIG (l); |
|
175 RENDER_EDGE_STEP_BIG (r); |
|
176 y += STEP_Y_BIG(N_BITS); |
|
177 line += stride; |
|
178 } |
|
179 } |
|
180 } |
|
181 |
|
182 #undef rasterize_span |