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