396 | 158M | } Unexecuted instantiation: gx_fill_trapezoid_cf_fd Unexecuted instantiation: gx_fill_trapezoid_cf_nd gdevddrw.c:gx_fill_trapezoid_as_fd Line | Count | Source | 137 | 4.05M | { | 138 | 4.05M | const fixed ymin = fixed_pixround(ybot) + fixed_half; | 139 | 4.05M | const fixed ymax = fixed_pixround(ytop); | 140 | | | 141 | 4.05M | if (ymin >= ymax) | 142 | 181k | return 0; /* no scan lines to sample */ | 143 | 3.87M | { | 144 | 3.87M | int iy = fixed2int_var(ymin); | 145 | 3.87M | const int iy1 = fixed2int_var(ymax); | 146 | 3.87M | trap_line l, r; | 147 | 3.87M | register int rxl, rxr; | 148 | 3.87M | #if !LINEAR_COLOR | 149 | 3.87M | int ry; | 150 | 3.87M | #endif | 151 | 3.87M | const fixed | 152 | 3.87M | x0l = left->start.x, x1l = left->end.x, x0r = right->start.x, | 153 | 3.87M | x1r = right->end.x, dxl = x1l - x0l, dxr = x1r - x0r; | 154 | 3.87M | const fixed /* partial pixel offset to first line to sample */ | 155 | 3.87M | ysl = ymin - left->start.y, ysr = ymin - right->start.y; | 156 | 3.87M | fixed fxl; | 157 | 3.87M | int code; | 158 | | # if CONTIGUOUS_FILL | 159 | | const bool peak0 = ((flags & 1) != 0); | 160 | | const bool peak1 = ((flags & 2) != 0); | 161 | | int peak_y0 = ybot + fixed_half; | 162 | | int peak_y1 = ytop - fixed_half; | 163 | | # endif | 164 | | # if LINEAR_COLOR | 165 | | int num_components = dev->color_info.num_components; | 166 | | frac31 lgc[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 167 | | int32_t lgf[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 168 | | int32_t lgnum[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 169 | | frac31 rgc[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 170 | | int32_t rgf[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 171 | | int32_t rgnum[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 172 | | frac31 xgc[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 173 | | int32_t xgf[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 174 | | int32_t xgnum[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 175 | | trap_gradient lg, rg, xg; | 176 | | # else | 177 | 3.87M | gx_color_index cindex = pdevc->colors.pure; | 178 | 3.87M | dev_proc_fill_rectangle((*fill_rect)) = | 179 | 3.87M | dev_proc(dev, fill_rectangle); | 180 | 3.87M | # endif | 181 | | | 182 | 3.87M | if_debug2m('z', dev->memory, "[z]y=[%d,%d]\n", iy, iy1); | 183 | | | 184 | 3.87M | l.h = left->end.y - left->start.y; | 185 | 3.87M | if (l.h == 0) | 186 | 0 | return 0; | 187 | 3.87M | r.h = right->end.y - right->start.y; | 188 | 3.87M | if (r.h == 0) | 189 | 0 | return 0; | 190 | 3.87M | l.x = x0l + (fixed_half - fixed_epsilon); | 191 | 3.87M | r.x = x0r + (fixed_half - fixed_epsilon); | 192 | 3.87M | #if !LINEAR_COLOR | 193 | 3.87M | ry = iy; | 194 | 3.87M | #endif | 195 | | | 196 | | /* | 197 | | * Free variables of FILL_TRAP_RECT: | 198 | | * SWAP_AXES, pdevc, dev, fa | 199 | | * Free variables of FILL_TRAP_RECT_DIRECT: | 200 | | * SWAP_AXES, fill_rect, dev, cindex | 201 | | */ | 202 | 3.87M | #define FILL_TRAP_RECT_INDIRECT(x,y,w,h)\ | 203 | 3.87M | (SWAP_AXES ? gx_fill_rectangle_device_rop(y, x, h, w, pdevc, dev, fa) :\ | 204 | 3.87M | gx_fill_rectangle_device_rop(x, y, w, h, pdevc, dev, fa)) | 205 | 3.87M | #define FILL_TRAP_RECT_DIRECT(x,y,w,h)\ | 206 | 3.87M | (SWAP_AXES ? (*fill_rect)(dev, y, x, h, w, cindex) :\ | 207 | 3.87M | (*fill_rect)(dev, x, y, w, h, cindex)) | 208 | | | 209 | | #if LINEAR_COLOR | 210 | | # define FILL_TRAP_RECT(x,y,w,h)\ | 211 | | (!(w) ? 0 : dev_proc(dev, fill_linear_color_scanline)(dev, fa, x, y, w, xg.c, xg.f, xg.num, xg.den)) | 212 | | #else | 213 | 3.87M | # define FILL_TRAP_RECT(x,y,w,h)\ | 214 | 3.87M | (FILL_DIRECT ? FILL_TRAP_RECT_DIRECT(x,y,w,h) : FILL_TRAP_RECT_INDIRECT(x,y,w,h)) | 215 | 3.87M | #endif | 216 | | | 217 | | /* Compute the dx/dy ratios. */ | 218 | | | 219 | | /* | 220 | | * Compute the x offsets at the first scan line to sample. We need | 221 | | * to be careful in computing ys# * dx#f {/,%} h# because the | 222 | | * multiplication may overflow. We know that all the quantities | 223 | | * involved are non-negative, and that ys# is usually less than 1 (as | 224 | | * a fixed, of course); this gives us a cheap conservative check for | 225 | | * overflow in the multiplication. | 226 | | */ | 227 | 3.87M | #define YMULT_QUO(ys, tl)\ | 228 | 3.87M | (ys < fixed_1 && tl.df < YMULT_LIMIT ? ys * tl.df / tl.h :\ | 229 | 3.87M | fixed_mult_quo(ys, tl.df, tl.h)) | 230 | | | 231 | | #if CONTIGUOUS_FILL | 232 | | /* | 233 | | * If left and right boundary round to same pixel index, | 234 | | * we would not paing the scan and would get a dropout. | 235 | | * Check for this case and choose one of two pixels | 236 | | * which is closer to the "axis". We need to exclude | 237 | | * 'peak' because it would paint an excessive pixel. | 238 | | */ | 239 | | #define SET_MINIMAL_WIDTH(ixl, ixr, l, r) \ | 240 | | if (ixl == ixr) \ | 241 | | if ((!peak0 || iy >= peak_y0) && (!peak1 || iy <= peak_y1)) {\ | 242 | | fixed x = int2fixed(ixl) + fixed_half;\ | 243 | | if (x - l.x < r.x - x)\ | 244 | | ++ixr;\ | 245 | | else\ | 246 | | --ixl;\ | 247 | | } | 248 | | | 249 | | #define CONNECT_RECTANGLES(ixl, ixr, rxl, rxr, iy, ry, adj1, adj2, fill)\ | 250 | | if (adj1 < adj2) {\ | 251 | | if (iy - ry > 1) {\ | 252 | | code = fill(rxl, ry, rxr - rxl, iy - ry - 1);\ | 253 | | if (code < 0)\ | 254 | | goto xit;\ | 255 | | ry = iy - 1;\ | 256 | | }\ | 257 | | adj1 = adj2 = (adj2 + adj2) / 2;\ | 258 | | } | 259 | | | 260 | | #else | 261 | 3.87M | #define SET_MINIMAL_WIDTH(ixl, ixr, l, r) DO_NOTHING | 262 | 3.87M | #define CONNECT_RECTANGLES(ixl, ixr, rxl, rxr, iy, ry, adj1, adj2, fill) DO_NOTHING | 263 | 3.87M | #endif | 264 | 3.87M | if (fixed_floor(l.x) == fixed_pixround(x1l)) { | 265 | | /* Left edge is vertical, we don't need to increment. */ | 266 | 1.28M | l.di = 0, l.df = 0; | 267 | 1.28M | fxl = 0; | 268 | 2.58M | } else { | 269 | 2.58M | compute_dx(&l, dxl, ysl); | 270 | 2.58M | fxl = YMULT_QUO(ysl, l); | 271 | 2.58M | l.x += fxl; | 272 | 2.58M | } | 273 | 3.87M | if (fixed_floor(r.x) == fixed_pixround(x1r)) { | 274 | | /* Right edge is vertical. If both are vertical, */ | 275 | | /* we have a rectangle. */ | 276 | 1.10M | # if !LINEAR_COLOR | 277 | 1.10M | if (l.di == 0 && l.df == 0) { | 278 | 1.02M | rxl = fixed2int_var(l.x); | 279 | 1.02M | rxr = fixed2int_var(r.x); | 280 | 1.02M | SET_MINIMAL_WIDTH(rxl, rxr, l, r); | 281 | 1.02M | code = FILL_TRAP_RECT(rxl, ry, rxr - rxl, iy1 - ry); | 282 | 1.02M | goto xit; | 283 | 1.02M | } | 284 | 74.6k | # endif | 285 | 74.6k | r.di = 0, r.df = 0; | 286 | 74.6k | } | 287 | | /* | 288 | | * The test for fxl != 0 is required because the right edge might | 289 | | * cross some pixel centers even if the left edge doesn't. | 290 | | */ | 291 | 2.76M | else if (dxr == dxl && fxl != 0) { | 292 | 1.04M | if (l.di == 0) | 293 | 560k | r.di = 0, r.df = l.df; | 294 | 488k | else | 295 | 488k | compute_dx(&r, dxr, ysr); | 296 | 1.04M | if (ysr == ysl && r.h == l.h) | 297 | 1.04M | r.x += fxl; | 298 | 108 | else | 299 | 108 | r.x += YMULT_QUO(ysr, r); | 300 | 1.72M | } else { | 301 | 1.72M | compute_dx(&r, dxr, ysr); | 302 | 1.72M | r.x += YMULT_QUO(ysr, r); | 303 | 1.72M | } | 304 | | /* Compute one line's worth of dx/dy. */ | 305 | 2.84M | compute_ldx(&l, ysl); | 306 | 2.84M | compute_ldx(&r, ysr); | 307 | | /* We subtracted fixed_epsilon from l.x, r.x to simplify rounding | 308 | | when the rational part is zero. Now add it back to get xl', xr' */ | 309 | 2.84M | l.x += fixed_epsilon; | 310 | 2.84M | r.x += fixed_epsilon; | 311 | | # if LINEAR_COLOR | 312 | | # ifdef DEBUG | 313 | | if (check_gradient_overflow(left, right)) { | 314 | | /* The caller must care of. | 315 | | Checking it here looses some performance with triangles. */ | 316 | | return_error(gs_error_unregistered); | 317 | | } | 318 | | # endif | 319 | | lg.c = lgc; | 320 | | lg.f = lgf; | 321 | | lg.num = lgnum; | 322 | | rg.c = rgc; | 323 | | rg.f = rgf; | 324 | | rg.num = rgnum; | 325 | | xg.c = xgc; | 326 | | xg.f = xgf; | 327 | | xg.num = xgnum; | 328 | | code = init_gradient(&lg, fa, left, right, &l, ymin, num_components); | 329 | | if (code < 0) | 330 | | return code; | 331 | | code = init_gradient(&rg, fa, right, left, &r, ymin, num_components); | 332 | | if (code < 0) | 333 | | return code; | 334 | | | 335 | | # endif | 336 | | | 337 | 2.84M | #define rational_floor(tl)\ | 338 | 2.84M | fixed2int_var(fixed_is_int(tl.x) && tl.xf == -tl.h ? tl.x - fixed_1 : tl.x) | 339 | 2.84M | #define STEP_LINE(ix, tl)\ | 340 | 2.84M | tl.x += tl.ldi;\ | 341 | 2.84M | if ( (tl.xf += tl.ldf) >= 0 ) tl.xf -= tl.h, tl.x++;\ | 342 | 2.84M | ix = rational_floor(tl) | 343 | | | 344 | 2.84M | rxl = rational_floor(l); | 345 | 2.84M | rxr = rational_floor(r); | 346 | 2.84M | SET_MINIMAL_WIDTH(rxl, rxr, l, r); | 347 | 275M | while (LINEAR_COLOR ? 1 : ++iy != iy1) { | 348 | | # if LINEAR_COLOR | 349 | | if (rxl != rxr) { | 350 | | code = set_x_gradient(&xg, &lg, &rg, &l, &r, rxl, rxr, num_components); | 351 | | if (code < 0) | 352 | | goto xit; | 353 | | code = FILL_TRAP_RECT(rxl, iy, rxr - rxl, 1); | 354 | | if (code < 0) | 355 | | goto xit; | 356 | | } | 357 | | if (++iy == iy1) | 358 | | break; | 359 | | STEP_LINE(rxl, l); | 360 | | STEP_LINE(rxr, r); | 361 | | step_gradient(&lg, num_components); | 362 | | step_gradient(&rg, num_components); | 363 | | # else | 364 | 273M | register int ixl, ixr; | 365 | | | 366 | 273M | STEP_LINE(ixl, l); | 367 | 273M | STEP_LINE(ixr, r); | 368 | 273M | SET_MINIMAL_WIDTH(ixl, ixr, l, r); | 369 | 273M | if (ixl != rxl || ixr != rxr) { | 370 | 46.1M | CONNECT_RECTANGLES(ixl, ixr, rxl, rxr, iy, ry, rxr, ixl, FILL_TRAP_RECT); | 371 | 46.1M | CONNECT_RECTANGLES(ixl, ixr, rxl, rxr, iy, ry, ixr, rxl, FILL_TRAP_RECT); | 372 | 46.1M | code = FILL_TRAP_RECT(rxl, ry, rxr - rxl, iy - ry); | 373 | 46.1M | if (code < 0) | 374 | 0 | goto xit; | 375 | 46.1M | rxl = ixl, rxr = ixr, ry = iy; | 376 | 46.1M | } | 377 | 273M | # endif | 378 | 273M | } | 379 | 2.84M | # if !LINEAR_COLOR | 380 | 2.84M | code = FILL_TRAP_RECT(rxl, ry, rxr - rxl, iy - ry); | 381 | | # else | 382 | | code = 0; | 383 | | # endif | 384 | 2.84M | #undef STEP_LINE | 385 | 2.84M | #undef SET_MINIMAL_WIDTH | 386 | 2.84M | #undef CONNECT_RECTANGLES | 387 | 2.84M | #undef FILL_TRAP_RECT | 388 | 2.84M | #undef FILL_TRAP_RECT_DIRECT | 389 | 2.84M | #undef FILL_TRAP_RECT_INRECT | 390 | 2.84M | #undef YMULT_QUO | 391 | 3.87M | xit: if (code < 0 && FILL_DIRECT) | 392 | 0 | return_error(code); | 393 | 3.87M | return_if_interrupt(dev->memory); | 394 | 3.87M | return code; | 395 | 3.87M | } | 396 | 3.87M | } |
gdevddrw.c:gx_fill_trapezoid_as_nd Line | Count | Source | 137 | 4.07M | { | 138 | 4.07M | const fixed ymin = fixed_pixround(ybot) + fixed_half; | 139 | 4.07M | const fixed ymax = fixed_pixround(ytop); | 140 | | | 141 | 4.07M | if (ymin >= ymax) | 142 | 54.1k | return 0; /* no scan lines to sample */ | 143 | 4.02M | { | 144 | 4.02M | int iy = fixed2int_var(ymin); | 145 | 4.02M | const int iy1 = fixed2int_var(ymax); | 146 | 4.02M | trap_line l, r; | 147 | 4.02M | register int rxl, rxr; | 148 | 4.02M | #if !LINEAR_COLOR | 149 | 4.02M | int ry; | 150 | 4.02M | #endif | 151 | 4.02M | const fixed | 152 | 4.02M | x0l = left->start.x, x1l = left->end.x, x0r = right->start.x, | 153 | 4.02M | x1r = right->end.x, dxl = x1l - x0l, dxr = x1r - x0r; | 154 | 4.02M | const fixed /* partial pixel offset to first line to sample */ | 155 | 4.02M | ysl = ymin - left->start.y, ysr = ymin - right->start.y; | 156 | 4.02M | fixed fxl; | 157 | 4.02M | int code; | 158 | | # if CONTIGUOUS_FILL | 159 | | const bool peak0 = ((flags & 1) != 0); | 160 | | const bool peak1 = ((flags & 2) != 0); | 161 | | int peak_y0 = ybot + fixed_half; | 162 | | int peak_y1 = ytop - fixed_half; | 163 | | # endif | 164 | | # if LINEAR_COLOR | 165 | | int num_components = dev->color_info.num_components; | 166 | | frac31 lgc[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 167 | | int32_t lgf[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 168 | | int32_t lgnum[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 169 | | frac31 rgc[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 170 | | int32_t rgf[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 171 | | int32_t rgnum[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 172 | | frac31 xgc[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 173 | | int32_t xgf[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 174 | | int32_t xgnum[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 175 | | trap_gradient lg, rg, xg; | 176 | | # else | 177 | 4.02M | gx_color_index cindex = pdevc->colors.pure; | 178 | 4.02M | dev_proc_fill_rectangle((*fill_rect)) = | 179 | 4.02M | dev_proc(dev, fill_rectangle); | 180 | 4.02M | # endif | 181 | | | 182 | 4.02M | if_debug2m('z', dev->memory, "[z]y=[%d,%d]\n", iy, iy1); | 183 | | | 184 | 4.02M | l.h = left->end.y - left->start.y; | 185 | 4.02M | if (l.h == 0) | 186 | 0 | return 0; | 187 | 4.02M | r.h = right->end.y - right->start.y; | 188 | 4.02M | if (r.h == 0) | 189 | 0 | return 0; | 190 | 4.02M | l.x = x0l + (fixed_half - fixed_epsilon); | 191 | 4.02M | r.x = x0r + (fixed_half - fixed_epsilon); | 192 | 4.02M | #if !LINEAR_COLOR | 193 | 4.02M | ry = iy; | 194 | 4.02M | #endif | 195 | | | 196 | | /* | 197 | | * Free variables of FILL_TRAP_RECT: | 198 | | * SWAP_AXES, pdevc, dev, fa | 199 | | * Free variables of FILL_TRAP_RECT_DIRECT: | 200 | | * SWAP_AXES, fill_rect, dev, cindex | 201 | | */ | 202 | 4.02M | #define FILL_TRAP_RECT_INDIRECT(x,y,w,h)\ | 203 | 4.02M | (SWAP_AXES ? gx_fill_rectangle_device_rop(y, x, h, w, pdevc, dev, fa) :\ | 204 | 4.02M | gx_fill_rectangle_device_rop(x, y, w, h, pdevc, dev, fa)) | 205 | 4.02M | #define FILL_TRAP_RECT_DIRECT(x,y,w,h)\ | 206 | 4.02M | (SWAP_AXES ? (*fill_rect)(dev, y, x, h, w, cindex) :\ | 207 | 4.02M | (*fill_rect)(dev, x, y, w, h, cindex)) | 208 | | | 209 | | #if LINEAR_COLOR | 210 | | # define FILL_TRAP_RECT(x,y,w,h)\ | 211 | | (!(w) ? 0 : dev_proc(dev, fill_linear_color_scanline)(dev, fa, x, y, w, xg.c, xg.f, xg.num, xg.den)) | 212 | | #else | 213 | 4.02M | # define FILL_TRAP_RECT(x,y,w,h)\ | 214 | 4.02M | (FILL_DIRECT ? FILL_TRAP_RECT_DIRECT(x,y,w,h) : FILL_TRAP_RECT_INDIRECT(x,y,w,h)) | 215 | 4.02M | #endif | 216 | | | 217 | | /* Compute the dx/dy ratios. */ | 218 | | | 219 | | /* | 220 | | * Compute the x offsets at the first scan line to sample. We need | 221 | | * to be careful in computing ys# * dx#f {/,%} h# because the | 222 | | * multiplication may overflow. We know that all the quantities | 223 | | * involved are non-negative, and that ys# is usually less than 1 (as | 224 | | * a fixed, of course); this gives us a cheap conservative check for | 225 | | * overflow in the multiplication. | 226 | | */ | 227 | 4.02M | #define YMULT_QUO(ys, tl)\ | 228 | 4.02M | (ys < fixed_1 && tl.df < YMULT_LIMIT ? ys * tl.df / tl.h :\ | 229 | 4.02M | fixed_mult_quo(ys, tl.df, tl.h)) | 230 | | | 231 | | #if CONTIGUOUS_FILL | 232 | | /* | 233 | | * If left and right boundary round to same pixel index, | 234 | | * we would not paing the scan and would get a dropout. | 235 | | * Check for this case and choose one of two pixels | 236 | | * which is closer to the "axis". We need to exclude | 237 | | * 'peak' because it would paint an excessive pixel. | 238 | | */ | 239 | | #define SET_MINIMAL_WIDTH(ixl, ixr, l, r) \ | 240 | | if (ixl == ixr) \ | 241 | | if ((!peak0 || iy >= peak_y0) && (!peak1 || iy <= peak_y1)) {\ | 242 | | fixed x = int2fixed(ixl) + fixed_half;\ | 243 | | if (x - l.x < r.x - x)\ | 244 | | ++ixr;\ | 245 | | else\ | 246 | | --ixl;\ | 247 | | } | 248 | | | 249 | | #define CONNECT_RECTANGLES(ixl, ixr, rxl, rxr, iy, ry, adj1, adj2, fill)\ | 250 | | if (adj1 < adj2) {\ | 251 | | if (iy - ry > 1) {\ | 252 | | code = fill(rxl, ry, rxr - rxl, iy - ry - 1);\ | 253 | | if (code < 0)\ | 254 | | goto xit;\ | 255 | | ry = iy - 1;\ | 256 | | }\ | 257 | | adj1 = adj2 = (adj2 + adj2) / 2;\ | 258 | | } | 259 | | | 260 | | #else | 261 | 4.02M | #define SET_MINIMAL_WIDTH(ixl, ixr, l, r) DO_NOTHING | 262 | 4.02M | #define CONNECT_RECTANGLES(ixl, ixr, rxl, rxr, iy, ry, adj1, adj2, fill) DO_NOTHING | 263 | 4.02M | #endif | 264 | 4.02M | if (fixed_floor(l.x) == fixed_pixround(x1l)) { | 265 | | /* Left edge is vertical, we don't need to increment. */ | 266 | 922k | l.di = 0, l.df = 0; | 267 | 922k | fxl = 0; | 268 | 3.09M | } else { | 269 | 3.09M | compute_dx(&l, dxl, ysl); | 270 | 3.09M | fxl = YMULT_QUO(ysl, l); | 271 | 3.09M | l.x += fxl; | 272 | 3.09M | } | 273 | 4.02M | if (fixed_floor(r.x) == fixed_pixround(x1r)) { | 274 | | /* Right edge is vertical. If both are vertical, */ | 275 | | /* we have a rectangle. */ | 276 | 800k | # if !LINEAR_COLOR | 277 | 800k | if (l.di == 0 && l.df == 0) { | 278 | 760k | rxl = fixed2int_var(l.x); | 279 | 760k | rxr = fixed2int_var(r.x); | 280 | 760k | SET_MINIMAL_WIDTH(rxl, rxr, l, r); | 281 | 760k | code = FILL_TRAP_RECT(rxl, ry, rxr - rxl, iy1 - ry); | 282 | 760k | goto xit; | 283 | 760k | } | 284 | 40.7k | # endif | 285 | 40.7k | r.di = 0, r.df = 0; | 286 | 40.7k | } | 287 | | /* | 288 | | * The test for fxl != 0 is required because the right edge might | 289 | | * cross some pixel centers even if the left edge doesn't. | 290 | | */ | 291 | 3.21M | else if (dxr == dxl && fxl != 0) { | 292 | 444k | if (l.di == 0) | 293 | 266k | r.di = 0, r.df = l.df; | 294 | 178k | else | 295 | 178k | compute_dx(&r, dxr, ysr); | 296 | 444k | if (ysr == ysl && r.h == l.h) | 297 | 444k | r.x += fxl; | 298 | 267 | else | 299 | 267 | r.x += YMULT_QUO(ysr, r); | 300 | 2.77M | } else { | 301 | 2.77M | compute_dx(&r, dxr, ysr); | 302 | 2.77M | r.x += YMULT_QUO(ysr, r); | 303 | 2.77M | } | 304 | | /* Compute one line's worth of dx/dy. */ | 305 | 3.25M | compute_ldx(&l, ysl); | 306 | 3.25M | compute_ldx(&r, ysr); | 307 | | /* We subtracted fixed_epsilon from l.x, r.x to simplify rounding | 308 | | when the rational part is zero. Now add it back to get xl', xr' */ | 309 | 3.25M | l.x += fixed_epsilon; | 310 | 3.25M | r.x += fixed_epsilon; | 311 | | # if LINEAR_COLOR | 312 | | # ifdef DEBUG | 313 | | if (check_gradient_overflow(left, right)) { | 314 | | /* The caller must care of. | 315 | | Checking it here looses some performance with triangles. */ | 316 | | return_error(gs_error_unregistered); | 317 | | } | 318 | | # endif | 319 | | lg.c = lgc; | 320 | | lg.f = lgf; | 321 | | lg.num = lgnum; | 322 | | rg.c = rgc; | 323 | | rg.f = rgf; | 324 | | rg.num = rgnum; | 325 | | xg.c = xgc; | 326 | | xg.f = xgf; | 327 | | xg.num = xgnum; | 328 | | code = init_gradient(&lg, fa, left, right, &l, ymin, num_components); | 329 | | if (code < 0) | 330 | | return code; | 331 | | code = init_gradient(&rg, fa, right, left, &r, ymin, num_components); | 332 | | if (code < 0) | 333 | | return code; | 334 | | | 335 | | # endif | 336 | | | 337 | 3.25M | #define rational_floor(tl)\ | 338 | 3.25M | fixed2int_var(fixed_is_int(tl.x) && tl.xf == -tl.h ? tl.x - fixed_1 : tl.x) | 339 | 3.25M | #define STEP_LINE(ix, tl)\ | 340 | 3.25M | tl.x += tl.ldi;\ | 341 | 3.25M | if ( (tl.xf += tl.ldf) >= 0 ) tl.xf -= tl.h, tl.x++;\ | 342 | 3.25M | ix = rational_floor(tl) | 343 | | | 344 | 3.25M | rxl = rational_floor(l); | 345 | 3.25M | rxr = rational_floor(r); | 346 | 3.25M | SET_MINIMAL_WIDTH(rxl, rxr, l, r); | 347 | 400M | while (LINEAR_COLOR ? 1 : ++iy != iy1) { | 348 | | # if LINEAR_COLOR | 349 | | if (rxl != rxr) { | 350 | | code = set_x_gradient(&xg, &lg, &rg, &l, &r, rxl, rxr, num_components); | 351 | | if (code < 0) | 352 | | goto xit; | 353 | | code = FILL_TRAP_RECT(rxl, iy, rxr - rxl, 1); | 354 | | if (code < 0) | 355 | | goto xit; | 356 | | } | 357 | | if (++iy == iy1) | 358 | | break; | 359 | | STEP_LINE(rxl, l); | 360 | | STEP_LINE(rxr, r); | 361 | | step_gradient(&lg, num_components); | 362 | | step_gradient(&rg, num_components); | 363 | | # else | 364 | 397M | register int ixl, ixr; | 365 | | | 366 | 397M | STEP_LINE(ixl, l); | 367 | 397M | STEP_LINE(ixr, r); | 368 | 397M | SET_MINIMAL_WIDTH(ixl, ixr, l, r); | 369 | 397M | if (ixl != rxl || ixr != rxr) { | 370 | 302M | CONNECT_RECTANGLES(ixl, ixr, rxl, rxr, iy, ry, rxr, ixl, FILL_TRAP_RECT); | 371 | 302M | CONNECT_RECTANGLES(ixl, ixr, rxl, rxr, iy, ry, ixr, rxl, FILL_TRAP_RECT); | 372 | 302M | code = FILL_TRAP_RECT(rxl, ry, rxr - rxl, iy - ry); | 373 | 302M | if (code < 0) | 374 | 0 | goto xit; | 375 | 302M | rxl = ixl, rxr = ixr, ry = iy; | 376 | 302M | } | 377 | 397M | # endif | 378 | 397M | } | 379 | 3.25M | # if !LINEAR_COLOR | 380 | 3.25M | code = FILL_TRAP_RECT(rxl, ry, rxr - rxl, iy - ry); | 381 | | # else | 382 | | code = 0; | 383 | | # endif | 384 | 3.25M | #undef STEP_LINE | 385 | 3.25M | #undef SET_MINIMAL_WIDTH | 386 | 3.25M | #undef CONNECT_RECTANGLES | 387 | 3.25M | #undef FILL_TRAP_RECT | 388 | 3.25M | #undef FILL_TRAP_RECT_DIRECT | 389 | 3.25M | #undef FILL_TRAP_RECT_INRECT | 390 | 3.25M | #undef YMULT_QUO | 391 | 4.02M | xit: if (code < 0 && FILL_DIRECT) | 392 | 0 | return_error(code); | 393 | 4.02M | return_if_interrupt(dev->memory); | 394 | 4.02M | return code; | 395 | 4.02M | } | 396 | 4.02M | } |
gdevddrw.c:gx_fill_trapezoid_ns_fd Line | Count | Source | 137 | 52.3M | { | 138 | 52.3M | const fixed ymin = fixed_pixround(ybot) + fixed_half; | 139 | 52.3M | const fixed ymax = fixed_pixround(ytop); | 140 | | | 141 | 52.3M | if (ymin >= ymax) | 142 | 9.97M | return 0; /* no scan lines to sample */ | 143 | 42.4M | { | 144 | 42.4M | int iy = fixed2int_var(ymin); | 145 | 42.4M | const int iy1 = fixed2int_var(ymax); | 146 | 42.4M | trap_line l, r; | 147 | 42.4M | register int rxl, rxr; | 148 | 42.4M | #if !LINEAR_COLOR | 149 | 42.4M | int ry; | 150 | 42.4M | #endif | 151 | 42.4M | const fixed | 152 | 42.4M | x0l = left->start.x, x1l = left->end.x, x0r = right->start.x, | 153 | 42.4M | x1r = right->end.x, dxl = x1l - x0l, dxr = x1r - x0r; | 154 | 42.4M | const fixed /* partial pixel offset to first line to sample */ | 155 | 42.4M | ysl = ymin - left->start.y, ysr = ymin - right->start.y; | 156 | 42.4M | fixed fxl; | 157 | 42.4M | int code; | 158 | | # if CONTIGUOUS_FILL | 159 | | const bool peak0 = ((flags & 1) != 0); | 160 | | const bool peak1 = ((flags & 2) != 0); | 161 | | int peak_y0 = ybot + fixed_half; | 162 | | int peak_y1 = ytop - fixed_half; | 163 | | # endif | 164 | | # if LINEAR_COLOR | 165 | | int num_components = dev->color_info.num_components; | 166 | | frac31 lgc[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 167 | | int32_t lgf[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 168 | | int32_t lgnum[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 169 | | frac31 rgc[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 170 | | int32_t rgf[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 171 | | int32_t rgnum[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 172 | | frac31 xgc[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 173 | | int32_t xgf[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 174 | | int32_t xgnum[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 175 | | trap_gradient lg, rg, xg; | 176 | | # else | 177 | 42.4M | gx_color_index cindex = pdevc->colors.pure; | 178 | 42.4M | dev_proc_fill_rectangle((*fill_rect)) = | 179 | 42.4M | dev_proc(dev, fill_rectangle); | 180 | 42.4M | # endif | 181 | | | 182 | 42.4M | if_debug2m('z', dev->memory, "[z]y=[%d,%d]\n", iy, iy1); | 183 | | | 184 | 42.4M | l.h = left->end.y - left->start.y; | 185 | 42.4M | if (l.h == 0) | 186 | 12 | return 0; | 187 | 42.4M | r.h = right->end.y - right->start.y; | 188 | 42.4M | if (r.h == 0) | 189 | 12 | return 0; | 190 | 42.4M | l.x = x0l + (fixed_half - fixed_epsilon); | 191 | 42.4M | r.x = x0r + (fixed_half - fixed_epsilon); | 192 | 42.4M | #if !LINEAR_COLOR | 193 | 42.4M | ry = iy; | 194 | 42.4M | #endif | 195 | | | 196 | | /* | 197 | | * Free variables of FILL_TRAP_RECT: | 198 | | * SWAP_AXES, pdevc, dev, fa | 199 | | * Free variables of FILL_TRAP_RECT_DIRECT: | 200 | | * SWAP_AXES, fill_rect, dev, cindex | 201 | | */ | 202 | 42.4M | #define FILL_TRAP_RECT_INDIRECT(x,y,w,h)\ | 203 | 42.4M | (SWAP_AXES ? gx_fill_rectangle_device_rop(y, x, h, w, pdevc, dev, fa) :\ | 204 | 42.4M | gx_fill_rectangle_device_rop(x, y, w, h, pdevc, dev, fa)) | 205 | 42.4M | #define FILL_TRAP_RECT_DIRECT(x,y,w,h)\ | 206 | 42.4M | (SWAP_AXES ? (*fill_rect)(dev, y, x, h, w, cindex) :\ | 207 | 42.4M | (*fill_rect)(dev, x, y, w, h, cindex)) | 208 | | | 209 | | #if LINEAR_COLOR | 210 | | # define FILL_TRAP_RECT(x,y,w,h)\ | 211 | | (!(w) ? 0 : dev_proc(dev, fill_linear_color_scanline)(dev, fa, x, y, w, xg.c, xg.f, xg.num, xg.den)) | 212 | | #else | 213 | 42.4M | # define FILL_TRAP_RECT(x,y,w,h)\ | 214 | 42.4M | (FILL_DIRECT ? FILL_TRAP_RECT_DIRECT(x,y,w,h) : FILL_TRAP_RECT_INDIRECT(x,y,w,h)) | 215 | 42.4M | #endif | 216 | | | 217 | | /* Compute the dx/dy ratios. */ | 218 | | | 219 | | /* | 220 | | * Compute the x offsets at the first scan line to sample. We need | 221 | | * to be careful in computing ys# * dx#f {/,%} h# because the | 222 | | * multiplication may overflow. We know that all the quantities | 223 | | * involved are non-negative, and that ys# is usually less than 1 (as | 224 | | * a fixed, of course); this gives us a cheap conservative check for | 225 | | * overflow in the multiplication. | 226 | | */ | 227 | 42.4M | #define YMULT_QUO(ys, tl)\ | 228 | 42.4M | (ys < fixed_1 && tl.df < YMULT_LIMIT ? ys * tl.df / tl.h :\ | 229 | 42.4M | fixed_mult_quo(ys, tl.df, tl.h)) | 230 | | | 231 | | #if CONTIGUOUS_FILL | 232 | | /* | 233 | | * If left and right boundary round to same pixel index, | 234 | | * we would not paing the scan and would get a dropout. | 235 | | * Check for this case and choose one of two pixels | 236 | | * which is closer to the "axis". We need to exclude | 237 | | * 'peak' because it would paint an excessive pixel. | 238 | | */ | 239 | | #define SET_MINIMAL_WIDTH(ixl, ixr, l, r) \ | 240 | | if (ixl == ixr) \ | 241 | | if ((!peak0 || iy >= peak_y0) && (!peak1 || iy <= peak_y1)) {\ | 242 | | fixed x = int2fixed(ixl) + fixed_half;\ | 243 | | if (x - l.x < r.x - x)\ | 244 | | ++ixr;\ | 245 | | else\ | 246 | | --ixl;\ | 247 | | } | 248 | | | 249 | | #define CONNECT_RECTANGLES(ixl, ixr, rxl, rxr, iy, ry, adj1, adj2, fill)\ | 250 | | if (adj1 < adj2) {\ | 251 | | if (iy - ry > 1) {\ | 252 | | code = fill(rxl, ry, rxr - rxl, iy - ry - 1);\ | 253 | | if (code < 0)\ | 254 | | goto xit;\ | 255 | | ry = iy - 1;\ | 256 | | }\ | 257 | | adj1 = adj2 = (adj2 + adj2) / 2;\ | 258 | | } | 259 | | | 260 | | #else | 261 | 42.4M | #define SET_MINIMAL_WIDTH(ixl, ixr, l, r) DO_NOTHING | 262 | 42.4M | #define CONNECT_RECTANGLES(ixl, ixr, rxl, rxr, iy, ry, adj1, adj2, fill) DO_NOTHING | 263 | 42.4M | #endif | 264 | 42.4M | if (fixed_floor(l.x) == fixed_pixround(x1l)) { | 265 | | /* Left edge is vertical, we don't need to increment. */ | 266 | 16.6M | l.di = 0, l.df = 0; | 267 | 16.6M | fxl = 0; | 268 | 25.8M | } else { | 269 | 25.8M | compute_dx(&l, dxl, ysl); | 270 | 25.8M | fxl = YMULT_QUO(ysl, l); | 271 | 25.8M | l.x += fxl; | 272 | 25.8M | } | 273 | 42.4M | if (fixed_floor(r.x) == fixed_pixround(x1r)) { | 274 | | /* Right edge is vertical. If both are vertical, */ | 275 | | /* we have a rectangle. */ | 276 | 16.7M | # if !LINEAR_COLOR | 277 | 16.7M | if (l.di == 0 && l.df == 0) { | 278 | 10.9M | rxl = fixed2int_var(l.x); | 279 | 10.9M | rxr = fixed2int_var(r.x); | 280 | 10.9M | SET_MINIMAL_WIDTH(rxl, rxr, l, r); | 281 | 10.9M | code = FILL_TRAP_RECT(rxl, ry, rxr - rxl, iy1 - ry); | 282 | 10.9M | goto xit; | 283 | 10.9M | } | 284 | 5.74M | # endif | 285 | 5.74M | r.di = 0, r.df = 0; | 286 | 5.74M | } | 287 | | /* | 288 | | * The test for fxl != 0 is required because the right edge might | 289 | | * cross some pixel centers even if the left edge doesn't. | 290 | | */ | 291 | 25.7M | else if (dxr == dxl && fxl != 0) { | 292 | 2.96M | if (l.di == 0) | 293 | 718k | r.di = 0, r.df = l.df; | 294 | 2.24M | else | 295 | 2.24M | compute_dx(&r, dxr, ysr); | 296 | 2.96M | if (ysr == ysl && r.h == l.h) | 297 | 1.70M | r.x += fxl; | 298 | 1.25M | else | 299 | 1.25M | r.x += YMULT_QUO(ysr, r); | 300 | 22.7M | } else { | 301 | 22.7M | compute_dx(&r, dxr, ysr); | 302 | 22.7M | r.x += YMULT_QUO(ysr, r); | 303 | 22.7M | } | 304 | | /* Compute one line's worth of dx/dy. */ | 305 | 31.4M | compute_ldx(&l, ysl); | 306 | 31.4M | compute_ldx(&r, ysr); | 307 | | /* We subtracted fixed_epsilon from l.x, r.x to simplify rounding | 308 | | when the rational part is zero. Now add it back to get xl', xr' */ | 309 | 31.4M | l.x += fixed_epsilon; | 310 | 31.4M | r.x += fixed_epsilon; | 311 | | # if LINEAR_COLOR | 312 | | # ifdef DEBUG | 313 | | if (check_gradient_overflow(left, right)) { | 314 | | /* The caller must care of. | 315 | | Checking it here looses some performance with triangles. */ | 316 | | return_error(gs_error_unregistered); | 317 | | } | 318 | | # endif | 319 | | lg.c = lgc; | 320 | | lg.f = lgf; | 321 | | lg.num = lgnum; | 322 | | rg.c = rgc; | 323 | | rg.f = rgf; | 324 | | rg.num = rgnum; | 325 | | xg.c = xgc; | 326 | | xg.f = xgf; | 327 | | xg.num = xgnum; | 328 | | code = init_gradient(&lg, fa, left, right, &l, ymin, num_components); | 329 | | if (code < 0) | 330 | | return code; | 331 | | code = init_gradient(&rg, fa, right, left, &r, ymin, num_components); | 332 | | if (code < 0) | 333 | | return code; | 334 | | | 335 | | # endif | 336 | | | 337 | 31.4M | #define rational_floor(tl)\ | 338 | 31.4M | fixed2int_var(fixed_is_int(tl.x) && tl.xf == -tl.h ? tl.x - fixed_1 : tl.x) | 339 | 31.4M | #define STEP_LINE(ix, tl)\ | 340 | 31.4M | tl.x += tl.ldi;\ | 341 | 31.4M | if ( (tl.xf += tl.ldf) >= 0 ) tl.xf -= tl.h, tl.x++;\ | 342 | 31.4M | ix = rational_floor(tl) | 343 | | | 344 | 31.4M | rxl = rational_floor(l); | 345 | 31.4M | rxr = rational_floor(r); | 346 | 31.4M | SET_MINIMAL_WIDTH(rxl, rxr, l, r); | 347 | 2.23G | while (LINEAR_COLOR ? 1 : ++iy != iy1) { | 348 | | # if LINEAR_COLOR | 349 | | if (rxl != rxr) { | 350 | | code = set_x_gradient(&xg, &lg, &rg, &l, &r, rxl, rxr, num_components); | 351 | | if (code < 0) | 352 | | goto xit; | 353 | | code = FILL_TRAP_RECT(rxl, iy, rxr - rxl, 1); | 354 | | if (code < 0) | 355 | | goto xit; | 356 | | } | 357 | | if (++iy == iy1) | 358 | | break; | 359 | | STEP_LINE(rxl, l); | 360 | | STEP_LINE(rxr, r); | 361 | | step_gradient(&lg, num_components); | 362 | | step_gradient(&rg, num_components); | 363 | | # else | 364 | 2.20G | register int ixl, ixr; | 365 | | | 366 | 2.20G | STEP_LINE(ixl, l); | 367 | 2.20G | STEP_LINE(ixr, r); | 368 | 2.20G | SET_MINIMAL_WIDTH(ixl, ixr, l, r); | 369 | 2.20G | if (ixl != rxl || ixr != rxr) { | 370 | 501M | CONNECT_RECTANGLES(ixl, ixr, rxl, rxr, iy, ry, rxr, ixl, FILL_TRAP_RECT); | 371 | 501M | CONNECT_RECTANGLES(ixl, ixr, rxl, rxr, iy, ry, ixr, rxl, FILL_TRAP_RECT); | 372 | 501M | code = FILL_TRAP_RECT(rxl, ry, rxr - rxl, iy - ry); | 373 | 501M | if (code < 0) | 374 | 0 | goto xit; | 375 | 501M | rxl = ixl, rxr = ixr, ry = iy; | 376 | 501M | } | 377 | 2.20G | # endif | 378 | 2.20G | } | 379 | 31.4M | # if !LINEAR_COLOR | 380 | 31.4M | code = FILL_TRAP_RECT(rxl, ry, rxr - rxl, iy - ry); | 381 | | # else | 382 | | code = 0; | 383 | | # endif | 384 | 31.4M | #undef STEP_LINE | 385 | 31.4M | #undef SET_MINIMAL_WIDTH | 386 | 31.4M | #undef CONNECT_RECTANGLES | 387 | 31.4M | #undef FILL_TRAP_RECT | 388 | 31.4M | #undef FILL_TRAP_RECT_DIRECT | 389 | 31.4M | #undef FILL_TRAP_RECT_INRECT | 390 | 31.4M | #undef YMULT_QUO | 391 | 42.4M | xit: if (code < 0 && FILL_DIRECT) | 392 | 0 | return_error(code); | 393 | 42.4M | return_if_interrupt(dev->memory); | 394 | 42.4M | return code; | 395 | 42.4M | } | 396 | 42.4M | } |
gdevddrw.c:gx_fill_trapezoid_ns_nd Line | Count | Source | 137 | 84.4M | { | 138 | 84.4M | const fixed ymin = fixed_pixround(ybot) + fixed_half; | 139 | 84.4M | const fixed ymax = fixed_pixround(ytop); | 140 | | | 141 | 84.4M | if (ymin >= ymax) | 142 | 23.5M | return 0; /* no scan lines to sample */ | 143 | 60.9M | { | 144 | 60.9M | int iy = fixed2int_var(ymin); | 145 | 60.9M | const int iy1 = fixed2int_var(ymax); | 146 | 60.9M | trap_line l, r; | 147 | 60.9M | register int rxl, rxr; | 148 | 60.9M | #if !LINEAR_COLOR | 149 | 60.9M | int ry; | 150 | 60.9M | #endif | 151 | 60.9M | const fixed | 152 | 60.9M | x0l = left->start.x, x1l = left->end.x, x0r = right->start.x, | 153 | 60.9M | x1r = right->end.x, dxl = x1l - x0l, dxr = x1r - x0r; | 154 | 60.9M | const fixed /* partial pixel offset to first line to sample */ | 155 | 60.9M | ysl = ymin - left->start.y, ysr = ymin - right->start.y; | 156 | 60.9M | fixed fxl; | 157 | 60.9M | int code; | 158 | | # if CONTIGUOUS_FILL | 159 | | const bool peak0 = ((flags & 1) != 0); | 160 | | const bool peak1 = ((flags & 2) != 0); | 161 | | int peak_y0 = ybot + fixed_half; | 162 | | int peak_y1 = ytop - fixed_half; | 163 | | # endif | 164 | | # if LINEAR_COLOR | 165 | | int num_components = dev->color_info.num_components; | 166 | | frac31 lgc[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 167 | | int32_t lgf[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 168 | | int32_t lgnum[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 169 | | frac31 rgc[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 170 | | int32_t rgf[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 171 | | int32_t rgnum[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 172 | | frac31 xgc[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 173 | | int32_t xgf[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 174 | | int32_t xgnum[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 175 | | trap_gradient lg, rg, xg; | 176 | | # else | 177 | 60.9M | gx_color_index cindex = pdevc->colors.pure; | 178 | 60.9M | dev_proc_fill_rectangle((*fill_rect)) = | 179 | 60.9M | dev_proc(dev, fill_rectangle); | 180 | 60.9M | # endif | 181 | | | 182 | 60.9M | if_debug2m('z', dev->memory, "[z]y=[%d,%d]\n", iy, iy1); | 183 | | | 184 | 60.9M | l.h = left->end.y - left->start.y; | 185 | 60.9M | if (l.h == 0) | 186 | 0 | return 0; | 187 | 60.9M | r.h = right->end.y - right->start.y; | 188 | 60.9M | if (r.h == 0) | 189 | 0 | return 0; | 190 | 60.9M | l.x = x0l + (fixed_half - fixed_epsilon); | 191 | 60.9M | r.x = x0r + (fixed_half - fixed_epsilon); | 192 | 60.9M | #if !LINEAR_COLOR | 193 | 60.9M | ry = iy; | 194 | 60.9M | #endif | 195 | | | 196 | | /* | 197 | | * Free variables of FILL_TRAP_RECT: | 198 | | * SWAP_AXES, pdevc, dev, fa | 199 | | * Free variables of FILL_TRAP_RECT_DIRECT: | 200 | | * SWAP_AXES, fill_rect, dev, cindex | 201 | | */ | 202 | 60.9M | #define FILL_TRAP_RECT_INDIRECT(x,y,w,h)\ | 203 | 60.9M | (SWAP_AXES ? gx_fill_rectangle_device_rop(y, x, h, w, pdevc, dev, fa) :\ | 204 | 60.9M | gx_fill_rectangle_device_rop(x, y, w, h, pdevc, dev, fa)) | 205 | 60.9M | #define FILL_TRAP_RECT_DIRECT(x,y,w,h)\ | 206 | 60.9M | (SWAP_AXES ? (*fill_rect)(dev, y, x, h, w, cindex) :\ | 207 | 60.9M | (*fill_rect)(dev, x, y, w, h, cindex)) | 208 | | | 209 | | #if LINEAR_COLOR | 210 | | # define FILL_TRAP_RECT(x,y,w,h)\ | 211 | | (!(w) ? 0 : dev_proc(dev, fill_linear_color_scanline)(dev, fa, x, y, w, xg.c, xg.f, xg.num, xg.den)) | 212 | | #else | 213 | 60.9M | # define FILL_TRAP_RECT(x,y,w,h)\ | 214 | 60.9M | (FILL_DIRECT ? FILL_TRAP_RECT_DIRECT(x,y,w,h) : FILL_TRAP_RECT_INDIRECT(x,y,w,h)) | 215 | 60.9M | #endif | 216 | | | 217 | | /* Compute the dx/dy ratios. */ | 218 | | | 219 | | /* | 220 | | * Compute the x offsets at the first scan line to sample. We need | 221 | | * to be careful in computing ys# * dx#f {/,%} h# because the | 222 | | * multiplication may overflow. We know that all the quantities | 223 | | * involved are non-negative, and that ys# is usually less than 1 (as | 224 | | * a fixed, of course); this gives us a cheap conservative check for | 225 | | * overflow in the multiplication. | 226 | | */ | 227 | 60.9M | #define YMULT_QUO(ys, tl)\ | 228 | 60.9M | (ys < fixed_1 && tl.df < YMULT_LIMIT ? ys * tl.df / tl.h :\ | 229 | 60.9M | fixed_mult_quo(ys, tl.df, tl.h)) | 230 | | | 231 | | #if CONTIGUOUS_FILL | 232 | | /* | 233 | | * If left and right boundary round to same pixel index, | 234 | | * we would not paing the scan and would get a dropout. | 235 | | * Check for this case and choose one of two pixels | 236 | | * which is closer to the "axis". We need to exclude | 237 | | * 'peak' because it would paint an excessive pixel. | 238 | | */ | 239 | | #define SET_MINIMAL_WIDTH(ixl, ixr, l, r) \ | 240 | | if (ixl == ixr) \ | 241 | | if ((!peak0 || iy >= peak_y0) && (!peak1 || iy <= peak_y1)) {\ | 242 | | fixed x = int2fixed(ixl) + fixed_half;\ | 243 | | if (x - l.x < r.x - x)\ | 244 | | ++ixr;\ | 245 | | else\ | 246 | | --ixl;\ | 247 | | } | 248 | | | 249 | | #define CONNECT_RECTANGLES(ixl, ixr, rxl, rxr, iy, ry, adj1, adj2, fill)\ | 250 | | if (adj1 < adj2) {\ | 251 | | if (iy - ry > 1) {\ | 252 | | code = fill(rxl, ry, rxr - rxl, iy - ry - 1);\ | 253 | | if (code < 0)\ | 254 | | goto xit;\ | 255 | | ry = iy - 1;\ | 256 | | }\ | 257 | | adj1 = adj2 = (adj2 + adj2) / 2;\ | 258 | | } | 259 | | | 260 | | #else | 261 | 60.9M | #define SET_MINIMAL_WIDTH(ixl, ixr, l, r) DO_NOTHING | 262 | 60.9M | #define CONNECT_RECTANGLES(ixl, ixr, rxl, rxr, iy, ry, adj1, adj2, fill) DO_NOTHING | 263 | 60.9M | #endif | 264 | 60.9M | if (fixed_floor(l.x) == fixed_pixround(x1l)) { | 265 | | /* Left edge is vertical, we don't need to increment. */ | 266 | 14.4M | l.di = 0, l.df = 0; | 267 | 14.4M | fxl = 0; | 268 | 46.4M | } else { | 269 | 46.4M | compute_dx(&l, dxl, ysl); | 270 | 46.4M | fxl = YMULT_QUO(ysl, l); | 271 | 46.4M | l.x += fxl; | 272 | 46.4M | } | 273 | 60.9M | if (fixed_floor(r.x) == fixed_pixround(x1r)) { | 274 | | /* Right edge is vertical. If both are vertical, */ | 275 | | /* we have a rectangle. */ | 276 | 18.9M | # if !LINEAR_COLOR | 277 | 18.9M | if (l.di == 0 && l.df == 0) { | 278 | 7.43M | rxl = fixed2int_var(l.x); | 279 | 7.43M | rxr = fixed2int_var(r.x); | 280 | 7.43M | SET_MINIMAL_WIDTH(rxl, rxr, l, r); | 281 | 7.43M | code = FILL_TRAP_RECT(rxl, ry, rxr - rxl, iy1 - ry); | 282 | 7.43M | goto xit; | 283 | 7.43M | } | 284 | 11.5M | # endif | 285 | 11.5M | r.di = 0, r.df = 0; | 286 | 11.5M | } | 287 | | /* | 288 | | * The test for fxl != 0 is required because the right edge might | 289 | | * cross some pixel centers even if the left edge doesn't. | 290 | | */ | 291 | 41.9M | else if (dxr == dxl && fxl != 0) { | 292 | 2.75M | if (l.di == 0) | 293 | 346k | r.di = 0, r.df = l.df; | 294 | 2.40M | else | 295 | 2.40M | compute_dx(&r, dxr, ysr); | 296 | 2.75M | if (ysr == ysl && r.h == l.h) | 297 | 1.79M | r.x += fxl; | 298 | 955k | else | 299 | 955k | r.x += YMULT_QUO(ysr, r); | 300 | 39.1M | } else { | 301 | 39.1M | compute_dx(&r, dxr, ysr); | 302 | 39.1M | r.x += YMULT_QUO(ysr, r); | 303 | 39.1M | } | 304 | | /* Compute one line's worth of dx/dy. */ | 305 | 53.5M | compute_ldx(&l, ysl); | 306 | 53.5M | compute_ldx(&r, ysr); | 307 | | /* We subtracted fixed_epsilon from l.x, r.x to simplify rounding | 308 | | when the rational part is zero. Now add it back to get xl', xr' */ | 309 | 53.5M | l.x += fixed_epsilon; | 310 | 53.5M | r.x += fixed_epsilon; | 311 | | # if LINEAR_COLOR | 312 | | # ifdef DEBUG | 313 | | if (check_gradient_overflow(left, right)) { | 314 | | /* The caller must care of. | 315 | | Checking it here looses some performance with triangles. */ | 316 | | return_error(gs_error_unregistered); | 317 | | } | 318 | | # endif | 319 | | lg.c = lgc; | 320 | | lg.f = lgf; | 321 | | lg.num = lgnum; | 322 | | rg.c = rgc; | 323 | | rg.f = rgf; | 324 | | rg.num = rgnum; | 325 | | xg.c = xgc; | 326 | | xg.f = xgf; | 327 | | xg.num = xgnum; | 328 | | code = init_gradient(&lg, fa, left, right, &l, ymin, num_components); | 329 | | if (code < 0) | 330 | | return code; | 331 | | code = init_gradient(&rg, fa, right, left, &r, ymin, num_components); | 332 | | if (code < 0) | 333 | | return code; | 334 | | | 335 | | # endif | 336 | | | 337 | 53.5M | #define rational_floor(tl)\ | 338 | 53.5M | fixed2int_var(fixed_is_int(tl.x) && tl.xf == -tl.h ? tl.x - fixed_1 : tl.x) | 339 | 53.5M | #define STEP_LINE(ix, tl)\ | 340 | 53.5M | tl.x += tl.ldi;\ | 341 | 53.5M | if ( (tl.xf += tl.ldf) >= 0 ) tl.xf -= tl.h, tl.x++;\ | 342 | 53.5M | ix = rational_floor(tl) | 343 | | | 344 | 53.5M | rxl = rational_floor(l); | 345 | 53.5M | rxr = rational_floor(r); | 346 | 53.5M | SET_MINIMAL_WIDTH(rxl, rxr, l, r); | 347 | 1.70G | while (LINEAR_COLOR ? 1 : ++iy != iy1) { | 348 | | # if LINEAR_COLOR | 349 | | if (rxl != rxr) { | 350 | | code = set_x_gradient(&xg, &lg, &rg, &l, &r, rxl, rxr, num_components); | 351 | | if (code < 0) | 352 | | goto xit; | 353 | | code = FILL_TRAP_RECT(rxl, iy, rxr - rxl, 1); | 354 | | if (code < 0) | 355 | | goto xit; | 356 | | } | 357 | | if (++iy == iy1) | 358 | | break; | 359 | | STEP_LINE(rxl, l); | 360 | | STEP_LINE(rxr, r); | 361 | | step_gradient(&lg, num_components); | 362 | | step_gradient(&rg, num_components); | 363 | | # else | 364 | 1.64G | register int ixl, ixr; | 365 | | | 366 | 1.64G | STEP_LINE(ixl, l); | 367 | 1.64G | STEP_LINE(ixr, r); | 368 | 1.64G | SET_MINIMAL_WIDTH(ixl, ixr, l, r); | 369 | 1.64G | if (ixl != rxl || ixr != rxr) { | 370 | 1.21G | CONNECT_RECTANGLES(ixl, ixr, rxl, rxr, iy, ry, rxr, ixl, FILL_TRAP_RECT); | 371 | 1.21G | CONNECT_RECTANGLES(ixl, ixr, rxl, rxr, iy, ry, ixr, rxl, FILL_TRAP_RECT); | 372 | 1.21G | code = FILL_TRAP_RECT(rxl, ry, rxr - rxl, iy - ry); | 373 | 1.21G | if (code < 0) | 374 | 0 | goto xit; | 375 | 1.21G | rxl = ixl, rxr = ixr, ry = iy; | 376 | 1.21G | } | 377 | 1.64G | # endif | 378 | 1.64G | } | 379 | 53.5M | # if !LINEAR_COLOR | 380 | 53.5M | code = FILL_TRAP_RECT(rxl, ry, rxr - rxl, iy - ry); | 381 | | # else | 382 | | code = 0; | 383 | | # endif | 384 | 53.5M | #undef STEP_LINE | 385 | 53.5M | #undef SET_MINIMAL_WIDTH | 386 | 53.5M | #undef CONNECT_RECTANGLES | 387 | 53.5M | #undef FILL_TRAP_RECT | 388 | 53.5M | #undef FILL_TRAP_RECT_DIRECT | 389 | 53.5M | #undef FILL_TRAP_RECT_INRECT | 390 | 53.5M | #undef YMULT_QUO | 391 | 60.9M | xit: if (code < 0 && FILL_DIRECT) | 392 | 0 | return_error(code); | 393 | 60.9M | return_if_interrupt(dev->memory); | 394 | 60.9M | return code; | 395 | 60.9M | } | 396 | 60.9M | } |
gdevddrw.c:gx_fill_trapezoid_as_lc Line | Count | Source | 137 | 3.13M | { | 138 | 3.13M | const fixed ymin = fixed_pixround(ybot) + fixed_half; | 139 | 3.13M | const fixed ymax = fixed_pixround(ytop); | 140 | | | 141 | 3.13M | if (ymin >= ymax) | 142 | 425k | return 0; /* no scan lines to sample */ | 143 | 2.70M | { | 144 | 2.70M | int iy = fixed2int_var(ymin); | 145 | 2.70M | const int iy1 = fixed2int_var(ymax); | 146 | 2.70M | trap_line l, r; | 147 | 2.70M | register int rxl, rxr; | 148 | | #if !LINEAR_COLOR | 149 | | int ry; | 150 | | #endif | 151 | 2.70M | const fixed | 152 | 2.70M | x0l = left->start.x, x1l = left->end.x, x0r = right->start.x, | 153 | 2.70M | x1r = right->end.x, dxl = x1l - x0l, dxr = x1r - x0r; | 154 | 2.70M | const fixed /* partial pixel offset to first line to sample */ | 155 | 2.70M | ysl = ymin - left->start.y, ysr = ymin - right->start.y; | 156 | 2.70M | fixed fxl; | 157 | 2.70M | int code; | 158 | | # if CONTIGUOUS_FILL | 159 | | const bool peak0 = ((flags & 1) != 0); | 160 | | const bool peak1 = ((flags & 2) != 0); | 161 | | int peak_y0 = ybot + fixed_half; | 162 | | int peak_y1 = ytop - fixed_half; | 163 | | # endif | 164 | 2.70M | # if LINEAR_COLOR | 165 | 2.70M | int num_components = dev->color_info.num_components; | 166 | 2.70M | frac31 lgc[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 167 | 2.70M | int32_t lgf[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 168 | 2.70M | int32_t lgnum[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 169 | 2.70M | frac31 rgc[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 170 | 2.70M | int32_t rgf[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 171 | 2.70M | int32_t rgnum[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 172 | 2.70M | frac31 xgc[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 173 | 2.70M | int32_t xgf[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 174 | 2.70M | int32_t xgnum[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 175 | 2.70M | trap_gradient lg, rg, xg; | 176 | | # else | 177 | | gx_color_index cindex = pdevc->colors.pure; | 178 | | dev_proc_fill_rectangle((*fill_rect)) = | 179 | | dev_proc(dev, fill_rectangle); | 180 | | # endif | 181 | | | 182 | 2.70M | if_debug2m('z', dev->memory, "[z]y=[%d,%d]\n", iy, iy1); | 183 | | | 184 | 2.70M | l.h = left->end.y - left->start.y; | 185 | 2.70M | if (l.h == 0) | 186 | 0 | return 0; | 187 | 2.70M | r.h = right->end.y - right->start.y; | 188 | 2.70M | if (r.h == 0) | 189 | 0 | return 0; | 190 | 2.70M | l.x = x0l + (fixed_half - fixed_epsilon); | 191 | 2.70M | r.x = x0r + (fixed_half - fixed_epsilon); | 192 | | #if !LINEAR_COLOR | 193 | | ry = iy; | 194 | | #endif | 195 | | | 196 | | /* | 197 | | * Free variables of FILL_TRAP_RECT: | 198 | | * SWAP_AXES, pdevc, dev, fa | 199 | | * Free variables of FILL_TRAP_RECT_DIRECT: | 200 | | * SWAP_AXES, fill_rect, dev, cindex | 201 | | */ | 202 | 2.70M | #define FILL_TRAP_RECT_INDIRECT(x,y,w,h)\ | 203 | 2.70M | (SWAP_AXES ? gx_fill_rectangle_device_rop(y, x, h, w, pdevc, dev, fa) :\ | 204 | 2.70M | gx_fill_rectangle_device_rop(x, y, w, h, pdevc, dev, fa)) | 205 | 2.70M | #define FILL_TRAP_RECT_DIRECT(x,y,w,h)\ | 206 | 2.70M | (SWAP_AXES ? (*fill_rect)(dev, y, x, h, w, cindex) :\ | 207 | 2.70M | (*fill_rect)(dev, x, y, w, h, cindex)) | 208 | | | 209 | 2.70M | #if LINEAR_COLOR | 210 | 2.70M | # define FILL_TRAP_RECT(x,y,w,h)\ | 211 | 2.70M | (!(w) ? 0 : dev_proc(dev, fill_linear_color_scanline)(dev, fa, x, y, w, xg.c, xg.f, xg.num, xg.den)) | 212 | | #else | 213 | | # define FILL_TRAP_RECT(x,y,w,h)\ | 214 | | (FILL_DIRECT ? FILL_TRAP_RECT_DIRECT(x,y,w,h) : FILL_TRAP_RECT_INDIRECT(x,y,w,h)) | 215 | | #endif | 216 | | | 217 | | /* Compute the dx/dy ratios. */ | 218 | | | 219 | | /* | 220 | | * Compute the x offsets at the first scan line to sample. We need | 221 | | * to be careful in computing ys# * dx#f {/,%} h# because the | 222 | | * multiplication may overflow. We know that all the quantities | 223 | | * involved are non-negative, and that ys# is usually less than 1 (as | 224 | | * a fixed, of course); this gives us a cheap conservative check for | 225 | | * overflow in the multiplication. | 226 | | */ | 227 | 2.70M | #define YMULT_QUO(ys, tl)\ | 228 | 2.70M | (ys < fixed_1 && tl.df < YMULT_LIMIT ? ys * tl.df / tl.h :\ | 229 | 2.70M | fixed_mult_quo(ys, tl.df, tl.h)) | 230 | | | 231 | | #if CONTIGUOUS_FILL | 232 | | /* | 233 | | * If left and right boundary round to same pixel index, | 234 | | * we would not paing the scan and would get a dropout. | 235 | | * Check for this case and choose one of two pixels | 236 | | * which is closer to the "axis". We need to exclude | 237 | | * 'peak' because it would paint an excessive pixel. | 238 | | */ | 239 | | #define SET_MINIMAL_WIDTH(ixl, ixr, l, r) \ | 240 | | if (ixl == ixr) \ | 241 | | if ((!peak0 || iy >= peak_y0) && (!peak1 || iy <= peak_y1)) {\ | 242 | | fixed x = int2fixed(ixl) + fixed_half;\ | 243 | | if (x - l.x < r.x - x)\ | 244 | | ++ixr;\ | 245 | | else\ | 246 | | --ixl;\ | 247 | | } | 248 | | | 249 | | #define CONNECT_RECTANGLES(ixl, ixr, rxl, rxr, iy, ry, adj1, adj2, fill)\ | 250 | | if (adj1 < adj2) {\ | 251 | | if (iy - ry > 1) {\ | 252 | | code = fill(rxl, ry, rxr - rxl, iy - ry - 1);\ | 253 | | if (code < 0)\ | 254 | | goto xit;\ | 255 | | ry = iy - 1;\ | 256 | | }\ | 257 | | adj1 = adj2 = (adj2 + adj2) / 2;\ | 258 | | } | 259 | | | 260 | | #else | 261 | 2.70M | #define SET_MINIMAL_WIDTH(ixl, ixr, l, r) DO_NOTHING | 262 | 2.70M | #define CONNECT_RECTANGLES(ixl, ixr, rxl, rxr, iy, ry, adj1, adj2, fill) DO_NOTHING | 263 | 2.70M | #endif | 264 | 2.70M | if (fixed_floor(l.x) == fixed_pixround(x1l)) { | 265 | | /* Left edge is vertical, we don't need to increment. */ | 266 | 1.42M | l.di = 0, l.df = 0; | 267 | 1.42M | fxl = 0; | 268 | 1.42M | } else { | 269 | 1.27M | compute_dx(&l, dxl, ysl); | 270 | 1.27M | fxl = YMULT_QUO(ysl, l); | 271 | 1.27M | l.x += fxl; | 272 | 1.27M | } | 273 | 2.70M | if (fixed_floor(r.x) == fixed_pixround(x1r)) { | 274 | | /* Right edge is vertical. If both are vertical, */ | 275 | | /* we have a rectangle. */ | 276 | | # if !LINEAR_COLOR | 277 | | if (l.di == 0 && l.df == 0) { | 278 | | rxl = fixed2int_var(l.x); | 279 | | rxr = fixed2int_var(r.x); | 280 | | SET_MINIMAL_WIDTH(rxl, rxr, l, r); | 281 | | code = FILL_TRAP_RECT(rxl, ry, rxr - rxl, iy1 - ry); | 282 | | goto xit; | 283 | | } | 284 | | # endif | 285 | 1.42M | r.di = 0, r.df = 0; | 286 | 1.42M | } | 287 | | /* | 288 | | * The test for fxl != 0 is required because the right edge might | 289 | | * cross some pixel centers even if the left edge doesn't. | 290 | | */ | 291 | 1.27M | else if (dxr == dxl && fxl != 0) { | 292 | 834k | if (l.di == 0) | 293 | 220k | r.di = 0, r.df = l.df; | 294 | 613k | else | 295 | 613k | compute_dx(&r, dxr, ysr); | 296 | 834k | if (ysr == ysl && r.h == l.h) | 297 | 834k | r.x += fxl; | 298 | 113 | else | 299 | 113 | r.x += YMULT_QUO(ysr, r); | 300 | 834k | } else { | 301 | 444k | compute_dx(&r, dxr, ysr); | 302 | 444k | r.x += YMULT_QUO(ysr, r); | 303 | 444k | } | 304 | | /* Compute one line's worth of dx/dy. */ | 305 | 2.70M | compute_ldx(&l, ysl); | 306 | 2.70M | compute_ldx(&r, ysr); | 307 | | /* We subtracted fixed_epsilon from l.x, r.x to simplify rounding | 308 | | when the rational part is zero. Now add it back to get xl', xr' */ | 309 | 2.70M | l.x += fixed_epsilon; | 310 | 2.70M | r.x += fixed_epsilon; | 311 | 2.70M | # if LINEAR_COLOR | 312 | | # ifdef DEBUG | 313 | | if (check_gradient_overflow(left, right)) { | 314 | | /* The caller must care of. | 315 | | Checking it here looses some performance with triangles. */ | 316 | | return_error(gs_error_unregistered); | 317 | | } | 318 | | # endif | 319 | 2.70M | lg.c = lgc; | 320 | 2.70M | lg.f = lgf; | 321 | 2.70M | lg.num = lgnum; | 322 | 2.70M | rg.c = rgc; | 323 | 2.70M | rg.f = rgf; | 324 | 2.70M | rg.num = rgnum; | 325 | 2.70M | xg.c = xgc; | 326 | 2.70M | xg.f = xgf; | 327 | 2.70M | xg.num = xgnum; | 328 | 2.70M | code = init_gradient(&lg, fa, left, right, &l, ymin, num_components); | 329 | 2.70M | if (code < 0) | 330 | 0 | return code; | 331 | 2.70M | code = init_gradient(&rg, fa, right, left, &r, ymin, num_components); | 332 | 2.70M | if (code < 0) | 333 | 0 | return code; | 334 | | | 335 | 2.70M | # endif | 336 | | | 337 | 2.70M | #define rational_floor(tl)\ | 338 | 2.70M | fixed2int_var(fixed_is_int(tl.x) && tl.xf == -tl.h ? tl.x - fixed_1 : tl.x) | 339 | 2.70M | #define STEP_LINE(ix, tl)\ | 340 | 2.70M | tl.x += tl.ldi;\ | 341 | 2.70M | if ( (tl.xf += tl.ldf) >= 0 ) tl.xf -= tl.h, tl.x++;\ | 342 | 2.70M | ix = rational_floor(tl) | 343 | | | 344 | 2.70M | rxl = rational_floor(l); | 345 | 2.70M | rxr = rational_floor(r); | 346 | 2.70M | SET_MINIMAL_WIDTH(rxl, rxr, l, r); | 347 | 63.1M | while (LINEAR_COLOR ? 1 : ++iy != iy1) { | 348 | 63.1M | # if LINEAR_COLOR | 349 | 63.1M | if (rxl != rxr) { | 350 | 41.9M | code = set_x_gradient(&xg, &lg, &rg, &l, &r, rxl, rxr, num_components); | 351 | 41.9M | if (code < 0) | 352 | 0 | goto xit; | 353 | 41.9M | code = FILL_TRAP_RECT(rxl, iy, rxr - rxl, 1); | 354 | 41.9M | if (code < 0) | 355 | 4 | goto xit; | 356 | 41.9M | } | 357 | 63.1M | if (++iy == iy1) | 358 | 2.70M | break; | 359 | 60.4M | STEP_LINE(rxl, l); | 360 | 60.4M | STEP_LINE(rxr, r); | 361 | 60.4M | step_gradient(&lg, num_components); | 362 | 60.4M | step_gradient(&rg, num_components); | 363 | | # else | 364 | | register int ixl, ixr; | 365 | | | 366 | | STEP_LINE(ixl, l); | 367 | | STEP_LINE(ixr, r); | 368 | | SET_MINIMAL_WIDTH(ixl, ixr, l, r); | 369 | | if (ixl != rxl || ixr != rxr) { | 370 | | CONNECT_RECTANGLES(ixl, ixr, rxl, rxr, iy, ry, rxr, ixl, FILL_TRAP_RECT); | 371 | | CONNECT_RECTANGLES(ixl, ixr, rxl, rxr, iy, ry, ixr, rxl, FILL_TRAP_RECT); | 372 | | code = FILL_TRAP_RECT(rxl, ry, rxr - rxl, iy - ry); | 373 | | if (code < 0) | 374 | | goto xit; | 375 | | rxl = ixl, rxr = ixr, ry = iy; | 376 | | } | 377 | | # endif | 378 | 60.4M | } | 379 | | # if !LINEAR_COLOR | 380 | | code = FILL_TRAP_RECT(rxl, ry, rxr - rxl, iy - ry); | 381 | | # else | 382 | 2.70M | code = 0; | 383 | 2.70M | # endif | 384 | 2.70M | #undef STEP_LINE | 385 | 2.70M | #undef SET_MINIMAL_WIDTH | 386 | 2.70M | #undef CONNECT_RECTANGLES | 387 | 2.70M | #undef FILL_TRAP_RECT | 388 | 2.70M | #undef FILL_TRAP_RECT_DIRECT | 389 | 2.70M | #undef FILL_TRAP_RECT_INRECT | 390 | 2.70M | #undef YMULT_QUO | 391 | 2.70M | xit: if (code < 0 && FILL_DIRECT) | 392 | 4 | return_error(code); | 393 | 2.70M | return_if_interrupt(dev->memory); | 394 | 2.70M | return code; | 395 | 2.70M | } | 396 | 2.70M | } |
gdevddrw.c:gx_fill_trapezoid_ns_lc Line | Count | Source | 137 | 73.7M | { | 138 | 73.7M | const fixed ymin = fixed_pixround(ybot) + fixed_half; | 139 | 73.7M | const fixed ymax = fixed_pixround(ytop); | 140 | | | 141 | 73.7M | if (ymin >= ymax) | 142 | 29.6M | return 0; /* no scan lines to sample */ | 143 | 44.1M | { | 144 | 44.1M | int iy = fixed2int_var(ymin); | 145 | 44.1M | const int iy1 = fixed2int_var(ymax); | 146 | 44.1M | trap_line l, r; | 147 | 44.1M | register int rxl, rxr; | 148 | | #if !LINEAR_COLOR | 149 | | int ry; | 150 | | #endif | 151 | 44.1M | const fixed | 152 | 44.1M | x0l = left->start.x, x1l = left->end.x, x0r = right->start.x, | 153 | 44.1M | x1r = right->end.x, dxl = x1l - x0l, dxr = x1r - x0r; | 154 | 44.1M | const fixed /* partial pixel offset to first line to sample */ | 155 | 44.1M | ysl = ymin - left->start.y, ysr = ymin - right->start.y; | 156 | 44.1M | fixed fxl; | 157 | 44.1M | int code; | 158 | | # if CONTIGUOUS_FILL | 159 | | const bool peak0 = ((flags & 1) != 0); | 160 | | const bool peak1 = ((flags & 2) != 0); | 161 | | int peak_y0 = ybot + fixed_half; | 162 | | int peak_y1 = ytop - fixed_half; | 163 | | # endif | 164 | 44.1M | # if LINEAR_COLOR | 165 | 44.1M | int num_components = dev->color_info.num_components; | 166 | 44.1M | frac31 lgc[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 167 | 44.1M | int32_t lgf[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 168 | 44.1M | int32_t lgnum[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 169 | 44.1M | frac31 rgc[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 170 | 44.1M | int32_t rgf[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 171 | 44.1M | int32_t rgnum[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 172 | 44.1M | frac31 xgc[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 173 | 44.1M | int32_t xgf[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 174 | 44.1M | int32_t xgnum[GX_DEVICE_COLOR_MAX_COMPONENTS]; | 175 | 44.1M | trap_gradient lg, rg, xg; | 176 | | # else | 177 | | gx_color_index cindex = pdevc->colors.pure; | 178 | | dev_proc_fill_rectangle((*fill_rect)) = | 179 | | dev_proc(dev, fill_rectangle); | 180 | | # endif | 181 | | | 182 | 44.1M | if_debug2m('z', dev->memory, "[z]y=[%d,%d]\n", iy, iy1); | 183 | | | 184 | 44.1M | l.h = left->end.y - left->start.y; | 185 | 44.1M | if (l.h == 0) | 186 | 0 | return 0; | 187 | 44.1M | r.h = right->end.y - right->start.y; | 188 | 44.1M | if (r.h == 0) | 189 | 0 | return 0; | 190 | 44.1M | l.x = x0l + (fixed_half - fixed_epsilon); | 191 | 44.1M | r.x = x0r + (fixed_half - fixed_epsilon); | 192 | | #if !LINEAR_COLOR | 193 | | ry = iy; | 194 | | #endif | 195 | | | 196 | | /* | 197 | | * Free variables of FILL_TRAP_RECT: | 198 | | * SWAP_AXES, pdevc, dev, fa | 199 | | * Free variables of FILL_TRAP_RECT_DIRECT: | 200 | | * SWAP_AXES, fill_rect, dev, cindex | 201 | | */ | 202 | 44.1M | #define FILL_TRAP_RECT_INDIRECT(x,y,w,h)\ | 203 | 44.1M | (SWAP_AXES ? gx_fill_rectangle_device_rop(y, x, h, w, pdevc, dev, fa) :\ | 204 | 44.1M | gx_fill_rectangle_device_rop(x, y, w, h, pdevc, dev, fa)) | 205 | 44.1M | #define FILL_TRAP_RECT_DIRECT(x,y,w,h)\ | 206 | 44.1M | (SWAP_AXES ? (*fill_rect)(dev, y, x, h, w, cindex) :\ | 207 | 44.1M | (*fill_rect)(dev, x, y, w, h, cindex)) | 208 | | | 209 | 44.1M | #if LINEAR_COLOR | 210 | 44.1M | # define FILL_TRAP_RECT(x,y,w,h)\ | 211 | 44.1M | (!(w) ? 0 : dev_proc(dev, fill_linear_color_scanline)(dev, fa, x, y, w, xg.c, xg.f, xg.num, xg.den)) | 212 | | #else | 213 | | # define FILL_TRAP_RECT(x,y,w,h)\ | 214 | | (FILL_DIRECT ? FILL_TRAP_RECT_DIRECT(x,y,w,h) : FILL_TRAP_RECT_INDIRECT(x,y,w,h)) | 215 | | #endif | 216 | | | 217 | | /* Compute the dx/dy ratios. */ | 218 | | | 219 | | /* | 220 | | * Compute the x offsets at the first scan line to sample. We need | 221 | | * to be careful in computing ys# * dx#f {/,%} h# because the | 222 | | * multiplication may overflow. We know that all the quantities | 223 | | * involved are non-negative, and that ys# is usually less than 1 (as | 224 | | * a fixed, of course); this gives us a cheap conservative check for | 225 | | * overflow in the multiplication. | 226 | | */ | 227 | 44.1M | #define YMULT_QUO(ys, tl)\ | 228 | 44.1M | (ys < fixed_1 && tl.df < YMULT_LIMIT ? ys * tl.df / tl.h :\ | 229 | 44.1M | fixed_mult_quo(ys, tl.df, tl.h)) | 230 | | | 231 | | #if CONTIGUOUS_FILL | 232 | | /* | 233 | | * If left and right boundary round to same pixel index, | 234 | | * we would not paing the scan and would get a dropout. | 235 | | * Check for this case and choose one of two pixels | 236 | | * which is closer to the "axis". We need to exclude | 237 | | * 'peak' because it would paint an excessive pixel. | 238 | | */ | 239 | | #define SET_MINIMAL_WIDTH(ixl, ixr, l, r) \ | 240 | | if (ixl == ixr) \ | 241 | | if ((!peak0 || iy >= peak_y0) && (!peak1 || iy <= peak_y1)) {\ | 242 | | fixed x = int2fixed(ixl) + fixed_half;\ | 243 | | if (x - l.x < r.x - x)\ | 244 | | ++ixr;\ | 245 | | else\ | 246 | | --ixl;\ | 247 | | } | 248 | | | 249 | | #define CONNECT_RECTANGLES(ixl, ixr, rxl, rxr, iy, ry, adj1, adj2, fill)\ | 250 | | if (adj1 < adj2) {\ | 251 | | if (iy - ry > 1) {\ | 252 | | code = fill(rxl, ry, rxr - rxl, iy - ry - 1);\ | 253 | | if (code < 0)\ | 254 | | goto xit;\ | 255 | | ry = iy - 1;\ | 256 | | }\ | 257 | | adj1 = adj2 = (adj2 + adj2) / 2;\ | 258 | | } | 259 | | | 260 | | #else | 261 | 44.1M | #define SET_MINIMAL_WIDTH(ixl, ixr, l, r) DO_NOTHING | 262 | 44.1M | #define CONNECT_RECTANGLES(ixl, ixr, rxl, rxr, iy, ry, adj1, adj2, fill) DO_NOTHING | 263 | 44.1M | #endif | 264 | 44.1M | if (fixed_floor(l.x) == fixed_pixround(x1l)) { | 265 | | /* Left edge is vertical, we don't need to increment. */ | 266 | 9.48M | l.di = 0, l.df = 0; | 267 | 9.48M | fxl = 0; | 268 | 34.6M | } else { | 269 | 34.6M | compute_dx(&l, dxl, ysl); | 270 | 34.6M | fxl = YMULT_QUO(ysl, l); | 271 | 34.6M | l.x += fxl; | 272 | 34.6M | } | 273 | 44.1M | if (fixed_floor(r.x) == fixed_pixround(x1r)) { | 274 | | /* Right edge is vertical. If both are vertical, */ | 275 | | /* we have a rectangle. */ | 276 | | # if !LINEAR_COLOR | 277 | | if (l.di == 0 && l.df == 0) { | 278 | | rxl = fixed2int_var(l.x); | 279 | | rxr = fixed2int_var(r.x); | 280 | | SET_MINIMAL_WIDTH(rxl, rxr, l, r); | 281 | | code = FILL_TRAP_RECT(rxl, ry, rxr - rxl, iy1 - ry); | 282 | | goto xit; | 283 | | } | 284 | | # endif | 285 | 9.44M | r.di = 0, r.df = 0; | 286 | 9.44M | } | 287 | | /* | 288 | | * The test for fxl != 0 is required because the right edge might | 289 | | * cross some pixel centers even if the left edge doesn't. | 290 | | */ | 291 | 34.7M | else if (dxr == dxl && fxl != 0) { | 292 | 2.39M | if (l.di == 0) | 293 | 947k | r.di = 0, r.df = l.df; | 294 | 1.44M | else | 295 | 1.44M | compute_dx(&r, dxr, ysr); | 296 | 2.39M | if (ysr == ysl && r.h == l.h) | 297 | 1.64M | r.x += fxl; | 298 | 744k | else | 299 | 744k | r.x += YMULT_QUO(ysr, r); | 300 | 32.3M | } else { | 301 | 32.3M | compute_dx(&r, dxr, ysr); | 302 | 32.3M | r.x += YMULT_QUO(ysr, r); | 303 | 32.3M | } | 304 | | /* Compute one line's worth of dx/dy. */ | 305 | 44.1M | compute_ldx(&l, ysl); | 306 | 44.1M | compute_ldx(&r, ysr); | 307 | | /* We subtracted fixed_epsilon from l.x, r.x to simplify rounding | 308 | | when the rational part is zero. Now add it back to get xl', xr' */ | 309 | 44.1M | l.x += fixed_epsilon; | 310 | 44.1M | r.x += fixed_epsilon; | 311 | 44.1M | # if LINEAR_COLOR | 312 | | # ifdef DEBUG | 313 | | if (check_gradient_overflow(left, right)) { | 314 | | /* The caller must care of. | 315 | | Checking it here looses some performance with triangles. */ | 316 | | return_error(gs_error_unregistered); | 317 | | } | 318 | | # endif | 319 | 44.1M | lg.c = lgc; | 320 | 44.1M | lg.f = lgf; | 321 | 44.1M | lg.num = lgnum; | 322 | 44.1M | rg.c = rgc; | 323 | 44.1M | rg.f = rgf; | 324 | 44.1M | rg.num = rgnum; | 325 | 44.1M | xg.c = xgc; | 326 | 44.1M | xg.f = xgf; | 327 | 44.1M | xg.num = xgnum; | 328 | 44.1M | code = init_gradient(&lg, fa, left, right, &l, ymin, num_components); | 329 | 44.1M | if (code < 0) | 330 | 0 | return code; | 331 | 44.1M | code = init_gradient(&rg, fa, right, left, &r, ymin, num_components); | 332 | 44.1M | if (code < 0) | 333 | 0 | return code; | 334 | | | 335 | 44.1M | # endif | 336 | | | 337 | 44.1M | #define rational_floor(tl)\ | 338 | 44.1M | fixed2int_var(fixed_is_int(tl.x) && tl.xf == -tl.h ? tl.x - fixed_1 : tl.x) | 339 | 44.1M | #define STEP_LINE(ix, tl)\ | 340 | 44.1M | tl.x += tl.ldi;\ | 341 | 44.1M | if ( (tl.xf += tl.ldf) >= 0 ) tl.xf -= tl.h, tl.x++;\ | 342 | 44.1M | ix = rational_floor(tl) | 343 | | | 344 | 44.1M | rxl = rational_floor(l); | 345 | 44.1M | rxr = rational_floor(r); | 346 | 44.1M | SET_MINIMAL_WIDTH(rxl, rxr, l, r); | 347 | 442M | while (LINEAR_COLOR ? 1 : ++iy != iy1) { | 348 | 442M | # if LINEAR_COLOR | 349 | 442M | if (rxl != rxr) { | 350 | 89.0M | code = set_x_gradient(&xg, &lg, &rg, &l, &r, rxl, rxr, num_components); | 351 | 89.0M | if (code < 0) | 352 | 0 | goto xit; | 353 | 89.0M | code = FILL_TRAP_RECT(rxl, iy, rxr - rxl, 1); | 354 | 89.0M | if (code < 0) | 355 | 13 | goto xit; | 356 | 89.0M | } | 357 | 442M | if (++iy == iy1) | 358 | 44.1M | break; | 359 | 398M | STEP_LINE(rxl, l); | 360 | 398M | STEP_LINE(rxr, r); | 361 | 398M | step_gradient(&lg, num_components); | 362 | 398M | step_gradient(&rg, num_components); | 363 | | # else | 364 | | register int ixl, ixr; | 365 | | | 366 | | STEP_LINE(ixl, l); | 367 | | STEP_LINE(ixr, r); | 368 | | SET_MINIMAL_WIDTH(ixl, ixr, l, r); | 369 | | if (ixl != rxl || ixr != rxr) { | 370 | | CONNECT_RECTANGLES(ixl, ixr, rxl, rxr, iy, ry, rxr, ixl, FILL_TRAP_RECT); | 371 | | CONNECT_RECTANGLES(ixl, ixr, rxl, rxr, iy, ry, ixr, rxl, FILL_TRAP_RECT); | 372 | | code = FILL_TRAP_RECT(rxl, ry, rxr - rxl, iy - ry); | 373 | | if (code < 0) | 374 | | goto xit; | 375 | | rxl = ixl, rxr = ixr, ry = iy; | 376 | | } | 377 | | # endif | 378 | 398M | } | 379 | | # if !LINEAR_COLOR | 380 | | code = FILL_TRAP_RECT(rxl, ry, rxr - rxl, iy - ry); | 381 | | # else | 382 | 44.1M | code = 0; | 383 | 44.1M | # endif | 384 | 44.1M | #undef STEP_LINE | 385 | 44.1M | #undef SET_MINIMAL_WIDTH | 386 | 44.1M | #undef CONNECT_RECTANGLES | 387 | 44.1M | #undef FILL_TRAP_RECT | 388 | 44.1M | #undef FILL_TRAP_RECT_DIRECT | 389 | 44.1M | #undef FILL_TRAP_RECT_INRECT | 390 | 44.1M | #undef YMULT_QUO | 391 | 44.1M | xit: if (code < 0 && FILL_DIRECT) | 392 | 13 | return_error(code); | 393 | 44.1M | return_if_interrupt(dev->memory); | 394 | 44.1M | return code; | 395 | 44.1M | } | 396 | 44.1M | } |
|