| 1 | /* |
| 2 | * Copyright © 1998 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 | #ifdef HAVE_DIX_CONFIG_H |
| 24 | #include <dix-config.h> |
| 25 | #endif |
| 26 | |
| 27 | #include <stdlib.h> |
| 28 | |
| 29 | #include "fb.h" |
| 30 | #include "miline.h" |
| 31 | |
| 32 | #define fbBresShiftMask(mask,dir,bpp) ((bpp == FB_STIP_UNIT) ? 0 : \ |
| 33 | ((dir < 0) ? FbStipLeft(mask,bpp) : \ |
| 34 | FbStipRight(mask,bpp))) |
| 35 | |
| 36 | void |
| 37 | fbBresSolid(DrawablePtr pDrawable, |
| 38 | GCPtr pGC, |
| 39 | int dashOffset, |
| 40 | int signdx, |
| 41 | int signdy, |
| 42 | int axis, int x1, int y1, int e, int e1, int e3, int len) |
| 43 | { |
| 44 | FbStip *dst; |
| 45 | FbStride dstStride; |
| 46 | int dstBpp; |
| 47 | int dstXoff, dstYoff; |
| 48 | FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); |
| 49 | FbStip and = (FbStip) pPriv->and; |
| 50 | FbStip xor = (FbStip) pPriv->xor; |
| 51 | FbStip mask, mask0; |
| 52 | FbStip bits; |
| 53 | |
| 54 | fbGetStipDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); |
| 55 | dst += ((y1 + dstYoff) * dstStride); |
| 56 | x1 = (x1 + dstXoff) * dstBpp; |
| 57 | dst += x1 >> FB_STIP_SHIFT; |
| 58 | x1 &= FB_STIP_MASK; |
| 59 | mask0 = FbStipMask(0, dstBpp); |
| 60 | mask = FbStipRight(mask0, x1); |
| 61 | if (signdx < 0) |
| 62 | mask0 = FbStipRight(mask0, FB_STIP_UNIT - dstBpp); |
| 63 | if (signdy < 0) |
| 64 | dstStride = -dstStride; |
| 65 | if (axis == X_AXIS) { |
| 66 | bits = 0; |
| 67 | while (len--) { |
| 68 | if (e >= 0) { |
| 69 | WRITE(dst, FbDoMaskRRop (READ(dst), and, xor, bits)); |
| 70 | bits = 0; |
| 71 | dst += dstStride; |
| 72 | e += e3; |
| 73 | } |
| 74 | bits |= mask; |
| 75 | mask = fbBresShiftMask(mask, signdx, dstBpp); |
| 76 | if (!mask) { |
| 77 | WRITE(dst, FbDoMaskRRop(READ(dst), and, xor, bits)); |
| 78 | bits = 0; |
| 79 | dst += signdx; |
| 80 | mask = mask0; |
| 81 | } |
| 82 | e += e1; |
| 83 | } |
| 84 | if (bits) |
| 85 | WRITE(dst, FbDoMaskRRop(READ(dst), and, xor, bits)); |
| 86 | } |
| 87 | else { |
| 88 | while (len--) { |
| 89 | if (e >= 0) { |
| 90 | e += e3; |
| 91 | mask = fbBresShiftMask(mask, signdx, dstBpp); |
| 92 | if (!mask) { |
| 93 | dst += signdx; |
| 94 | mask = mask0; |
| 95 | } |
| 96 | } |
| 97 | WRITE(dst, FbDoMaskRRop(READ(dst), and, xor, mask)); |
| 98 | dst += dstStride; |
| 99 | e += e1; |
| 100 | } |
| 101 | } |
| 102 | |
| 103 | fbFinishAccess(pDrawable); |
| 104 | } |
| 105 | |
| 106 | void |
| 107 | fbBresDash(DrawablePtr pDrawable, |
| 108 | GCPtr pGC, |
| 109 | int dashOffset, |
| 110 | int signdx, |
| 111 | int signdy, int axis, int x1, int y1, int e, int e1, int e3, int len) |
| 112 | { |
| 113 | FbStip *dst; |
| 114 | FbStride dstStride; |
| 115 | int dstBpp; |
| 116 | int dstXoff, dstYoff; |
| 117 | FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); |
| 118 | FbStip and = (FbStip) pPriv->and; |
| 119 | FbStip xor = (FbStip) pPriv->xor; |
| 120 | FbStip bgand = (FbStip) pPriv->bgand; |
| 121 | FbStip bgxor = (FbStip) pPriv->bgxor; |
| 122 | FbStip mask, mask0; |
| 123 | |
| 124 | FbDashDeclare; |
| 125 | int dashlen; |
| 126 | Bool even; |
| 127 | Bool doOdd; |
| 128 | |
| 129 | fbGetStipDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); |
| 130 | doOdd = pGC->lineStyle == LineDoubleDash; |
| 131 | |
| 132 | FbDashInit(pGC, pPriv, dashOffset, dashlen, even); |
| 133 | |
| 134 | dst += ((y1 + dstYoff) * dstStride); |
| 135 | x1 = (x1 + dstXoff) * dstBpp; |
| 136 | dst += x1 >> FB_STIP_SHIFT; |
| 137 | x1 &= FB_STIP_MASK; |
| 138 | mask0 = FbStipMask(0, dstBpp); |
| 139 | mask = FbStipRight(mask0, x1); |
| 140 | if (signdx < 0) |
| 141 | mask0 = FbStipRight(mask0, FB_STIP_UNIT - dstBpp); |
| 142 | if (signdy < 0) |
| 143 | dstStride = -dstStride; |
| 144 | while (len--) { |
| 145 | if (even) |
| 146 | WRITE(dst, FbDoMaskRRop(READ(dst), and, xor, mask)); |
| 147 | else if (doOdd) |
| 148 | WRITE(dst, FbDoMaskRRop(READ(dst), bgand, bgxor, mask)); |
| 149 | if (axis == X_AXIS) { |
| 150 | mask = fbBresShiftMask(mask, signdx, dstBpp); |
| 151 | if (!mask) { |
| 152 | dst += signdx; |
| 153 | mask = mask0; |
| 154 | } |
| 155 | e += e1; |
| 156 | if (e >= 0) { |
| 157 | dst += dstStride; |
| 158 | e += e3; |
| 159 | } |
| 160 | } |
| 161 | else { |
| 162 | dst += dstStride; |
| 163 | e += e1; |
| 164 | if (e >= 0) { |
| 165 | e += e3; |
| 166 | mask = fbBresShiftMask(mask, signdx, dstBpp); |
| 167 | if (!mask) { |
| 168 | dst += signdx; |
| 169 | mask = mask0; |
| 170 | } |
| 171 | } |
| 172 | } |
| 173 | FbDashStep(dashlen, even); |
| 174 | } |
| 175 | |
| 176 | fbFinishAccess(pDrawable); |
| 177 | } |
| 178 | |
| 179 | void |
| 180 | fbBresFill(DrawablePtr pDrawable, |
| 181 | GCPtr pGC, |
| 182 | int dashOffset, |
| 183 | int signdx, |
| 184 | int signdy, int axis, int x1, int y1, int e, int e1, int e3, int len) |
| 185 | { |
| 186 | while (len--) { |
| 187 | fbFill(pDrawable, pGC, x1, y1, 1, 1); |
| 188 | if (axis == X_AXIS) { |
| 189 | x1 += signdx; |
| 190 | e += e1; |
| 191 | if (e >= 0) { |
| 192 | e += e3; |
| 193 | y1 += signdy; |
| 194 | } |
| 195 | } |
| 196 | else { |
| 197 | y1 += signdy; |
| 198 | e += e1; |
| 199 | if (e >= 0) { |
| 200 | e += e3; |
| 201 | x1 += signdx; |
| 202 | } |
| 203 | } |
| 204 | } |
| 205 | } |
| 206 | |
| 207 | static void |
| 208 | fbSetFg(DrawablePtr pDrawable, GCPtr pGC, Pixel fg) |
| 209 | { |
| 210 | if (fg != pGC->fgPixel) { |
| 211 | ChangeGCVal val; |
| 212 | |
| 213 | val.val = fg; |
| 214 | ChangeGC(NullClient, pGC, GCForeground, &val); |
| 215 | ValidateGC(pDrawable, pGC); |
| 216 | } |
| 217 | } |
| 218 | |
| 219 | void |
| 220 | fbBresFillDash(DrawablePtr pDrawable, |
| 221 | GCPtr pGC, |
| 222 | int dashOffset, |
| 223 | int signdx, |
| 224 | int signdy, |
| 225 | int axis, int x1, int y1, int e, int e1, int e3, int len) |
| 226 | { |
| 227 | FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); |
| 228 | |
| 229 | FbDashDeclare; |
| 230 | int dashlen; |
| 231 | Bool even; |
| 232 | Bool doOdd; |
| 233 | Bool doBg; |
| 234 | Pixel fg, bg; |
| 235 | |
| 236 | fg = pGC->fgPixel; |
| 237 | bg = pGC->bgPixel; |
| 238 | |
| 239 | /* whether to fill the odd dashes */ |
| 240 | doOdd = pGC->lineStyle == LineDoubleDash; |
| 241 | /* whether to switch fg to bg when filling odd dashes */ |
| 242 | doBg = doOdd && (pGC->fillStyle == FillSolid || |
| 243 | pGC->fillStyle == FillStippled); |
| 244 | |
| 245 | /* compute current dash position */ |
| 246 | FbDashInit(pGC, pPriv, dashOffset, dashlen, even); |
| 247 | |
| 248 | while (len--) { |
| 249 | if (even || doOdd) { |
| 250 | if (doBg) { |
| 251 | if (even) |
| 252 | fbSetFg(pDrawable, pGC, fg); |
| 253 | else |
| 254 | fbSetFg(pDrawable, pGC, bg); |
| 255 | } |
| 256 | fbFill(pDrawable, pGC, x1, y1, 1, 1); |
| 257 | } |
| 258 | if (axis == X_AXIS) { |
| 259 | x1 += signdx; |
| 260 | e += e1; |
| 261 | if (e >= 0) { |
| 262 | e += e3; |
| 263 | y1 += signdy; |
| 264 | } |
| 265 | } |
| 266 | else { |
| 267 | y1 += signdy; |
| 268 | e += e1; |
| 269 | if (e >= 0) { |
| 270 | e += e3; |
| 271 | x1 += signdx; |
| 272 | } |
| 273 | } |
| 274 | FbDashStep(dashlen, even); |
| 275 | } |
| 276 | if (doBg) |
| 277 | fbSetFg(pDrawable, pGC, fg); |
| 278 | } |
| 279 | |
| 280 | static void |
| 281 | fbBresSolid24RRop(DrawablePtr pDrawable, |
| 282 | GCPtr pGC, |
| 283 | int dashOffset, |
| 284 | int signdx, |
| 285 | int signdy, |
| 286 | int axis, int x1, int y1, int e, int e1, int e3, int len) |
| 287 | { |
| 288 | FbStip *dst; |
| 289 | FbStride dstStride; |
| 290 | int dstBpp; |
| 291 | int dstXoff, dstYoff; |
| 292 | FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); |
| 293 | FbStip and = pPriv->and; |
| 294 | FbStip xor = pPriv->xor; |
| 295 | FbStip leftMask, rightMask; |
| 296 | int nl; |
| 297 | FbStip *d; |
| 298 | int x; |
| 299 | int rot; |
| 300 | FbStip andT, xorT; |
| 301 | |
| 302 | fbGetStipDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); |
| 303 | dst += ((y1 + dstYoff) * dstStride); |
| 304 | x1 = (x1 + dstXoff) * 24; |
| 305 | if (signdy < 0) |
| 306 | dstStride = -dstStride; |
| 307 | signdx *= 24; |
| 308 | while (len--) { |
| 309 | d = dst + (x1 >> FB_STIP_SHIFT); |
| 310 | x = x1 & FB_STIP_MASK; |
| 311 | rot = FbFirst24Rot(x); |
| 312 | andT = FbRot24Stip(and, rot); |
| 313 | xorT = FbRot24Stip(xor, rot); |
| 314 | FbMaskStip(x, 24, leftMask, nl, rightMask); |
| 315 | if (leftMask) { |
| 316 | WRITE(d, FbDoMaskRRop(READ(d), andT, xorT, leftMask)); |
| 317 | d++; |
| 318 | andT = FbNext24Stip(andT); |
| 319 | xorT = FbNext24Stip(xorT); |
| 320 | } |
| 321 | if (rightMask) |
| 322 | WRITE(d, FbDoMaskRRop(READ(d), andT, xorT, rightMask)); |
| 323 | if (axis == X_AXIS) { |
| 324 | x1 += signdx; |
| 325 | e += e1; |
| 326 | if (e >= 0) { |
| 327 | e += e3; |
| 328 | dst += dstStride; |
| 329 | } |
| 330 | } |
| 331 | else { |
| 332 | dst += dstStride; |
| 333 | e += e1; |
| 334 | if (e >= 0) { |
| 335 | e += e3; |
| 336 | x1 += signdx; |
| 337 | } |
| 338 | } |
| 339 | } |
| 340 | |
| 341 | fbFinishAccess(pDrawable); |
| 342 | } |
| 343 | |
| 344 | static void |
| 345 | fbBresDash24RRop(DrawablePtr pDrawable, |
| 346 | GCPtr pGC, |
| 347 | int dashOffset, |
| 348 | int signdx, |
| 349 | int signdy, |
| 350 | int axis, int x1, int y1, int e, int e1, int e3, int len) |
| 351 | { |
| 352 | FbStip *dst; |
| 353 | FbStride dstStride; |
| 354 | int dstBpp; |
| 355 | int dstXoff, dstYoff; |
| 356 | FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); |
| 357 | FbStip andT, xorT; |
| 358 | FbStip fgand = pPriv->and; |
| 359 | FbStip fgxor = pPriv->xor; |
| 360 | FbStip bgand = pPriv->bgand; |
| 361 | FbStip bgxor = pPriv->bgxor; |
| 362 | FbStip leftMask, rightMask; |
| 363 | int nl; |
| 364 | FbStip *d; |
| 365 | int x; |
| 366 | int rot; |
| 367 | |
| 368 | FbDashDeclare; |
| 369 | int dashlen; |
| 370 | Bool even; |
| 371 | Bool doOdd; |
| 372 | |
| 373 | fbGetStipDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); |
| 374 | doOdd = pGC->lineStyle == LineDoubleDash; |
| 375 | |
| 376 | /* compute current dash position */ |
| 377 | FbDashInit(pGC, pPriv, dashOffset, dashlen, even); |
| 378 | |
| 379 | dst += ((y1 + dstYoff) * dstStride); |
| 380 | x1 = (x1 + dstXoff) * 24; |
| 381 | if (signdy < 0) |
| 382 | dstStride = -dstStride; |
| 383 | signdx *= 24; |
| 384 | while (len--) { |
| 385 | if (even || doOdd) { |
| 386 | if (even) { |
| 387 | andT = fgand; |
| 388 | xorT = fgxor; |
| 389 | } |
| 390 | else { |
| 391 | andT = bgand; |
| 392 | xorT = bgxor; |
| 393 | } |
| 394 | d = dst + (x1 >> FB_STIP_SHIFT); |
| 395 | x = x1 & FB_STIP_MASK; |
| 396 | rot = FbFirst24Rot(x); |
| 397 | andT = FbRot24Stip(andT, rot); |
| 398 | xorT = FbRot24Stip(xorT, rot); |
| 399 | FbMaskStip(x, 24, leftMask, nl, rightMask); |
| 400 | if (leftMask) { |
| 401 | WRITE(d, FbDoMaskRRop(READ(d), andT, xorT, leftMask)); |
| 402 | d++; |
| 403 | andT = FbNext24Stip(andT); |
| 404 | xorT = FbNext24Stip(xorT); |
| 405 | } |
| 406 | if (rightMask) |
| 407 | WRITE(d, FbDoMaskRRop(READ(d), andT, xorT, rightMask)); |
| 408 | } |
| 409 | if (axis == X_AXIS) { |
| 410 | x1 += signdx; |
| 411 | e += e1; |
| 412 | if (e >= 0) { |
| 413 | e += e3; |
| 414 | dst += dstStride; |
| 415 | } |
| 416 | } |
| 417 | else { |
| 418 | dst += dstStride; |
| 419 | e += e1; |
| 420 | if (e >= 0) { |
| 421 | e += e3; |
| 422 | x1 += signdx; |
| 423 | } |
| 424 | } |
| 425 | FbDashStep(dashlen, even); |
| 426 | } |
| 427 | |
| 428 | fbFinishAccess(pDrawable); |
| 429 | } |
| 430 | |
| 431 | /* |
| 432 | * For drivers that want to bail drawing some lines, this |
| 433 | * function takes care of selecting the appropriate rasterizer |
| 434 | * based on the contents of the specified GC. |
| 435 | */ |
| 436 | |
| 437 | FbBres * |
| 438 | fbSelectBres(DrawablePtr pDrawable, GCPtr pGC) |
| 439 | { |
| 440 | FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); |
| 441 | int dstBpp = pDrawable->bitsPerPixel; |
| 442 | FbBres *bres; |
| 443 | |
| 444 | if (pGC->lineStyle == LineSolid) { |
| 445 | bres = fbBresFill; |
| 446 | if (pGC->fillStyle == FillSolid) { |
| 447 | bres = fbBresSolid; |
| 448 | if (dstBpp == 24) |
| 449 | bres = fbBresSolid24RRop; |
| 450 | if (pPriv->and == 0) { |
| 451 | switch (dstBpp) { |
| 452 | case 8: |
| 453 | bres = fbBresSolid8; |
| 454 | break; |
| 455 | case 16: |
| 456 | bres = fbBresSolid16; |
| 457 | break; |
| 458 | case 24: |
| 459 | bres = fbBresSolid24; |
| 460 | break; |
| 461 | case 32: |
| 462 | bres = fbBresSolid32; |
| 463 | break; |
| 464 | } |
| 465 | } |
| 466 | } |
| 467 | } |
| 468 | else { |
| 469 | bres = fbBresFillDash; |
| 470 | if (pGC->fillStyle == FillSolid) { |
| 471 | bres = fbBresDash; |
| 472 | if (dstBpp == 24) |
| 473 | bres = fbBresDash24RRop; |
| 474 | if (pPriv->and == 0 && |
| 475 | (pGC->lineStyle == LineOnOffDash || pPriv->bgand == 0)) { |
| 476 | switch (dstBpp) { |
| 477 | case 8: |
| 478 | bres = fbBresDash8; |
| 479 | break; |
| 480 | case 16: |
| 481 | bres = fbBresDash16; |
| 482 | break; |
| 483 | case 24: |
| 484 | bres = fbBresDash24; |
| 485 | break; |
| 486 | case 32: |
| 487 | bres = fbBresDash32; |
| 488 | break; |
| 489 | } |
| 490 | } |
| 491 | } |
| 492 | } |
| 493 | return bres; |
| 494 | } |
| 495 | |
| 496 | void |
| 497 | fbBres(DrawablePtr pDrawable, |
| 498 | GCPtr pGC, |
| 499 | int dashOffset, |
| 500 | int signdx, |
| 501 | int signdy, int axis, int x1, int y1, int e, int e1, int e3, int len) |
| 502 | { |
| 503 | (*fbSelectBres(pDrawable, pGC)) (pDrawable, pGC, dashOffset, |
| 504 | signdx, signdy, axis, x1, y1, |
| 505 | e, e1, e3, len); |
| 506 | } |
| 507 | |
| 508 | void |
| 509 | fbSegment(DrawablePtr pDrawable, |
| 510 | GCPtr pGC, |
| 511 | int x1, int y1, int x2, int y2, Bool drawLast, int *dashOffset) |
| 512 | { |
| 513 | FbBres *bres; |
| 514 | RegionPtr pClip = fbGetCompositeClip(pGC); |
| 515 | BoxPtr pBox; |
| 516 | int nBox; |
| 517 | int adx; /* abs values of dx and dy */ |
| 518 | int ady; |
| 519 | int signdx; /* sign of dx and dy */ |
| 520 | int signdy; |
| 521 | int e, e1, e2, e3; /* bresenham error and increments */ |
| 522 | int len; /* length of segment */ |
| 523 | int axis; /* major axis */ |
| 524 | int octant; |
| 525 | int dashoff; |
| 526 | int doff; |
| 527 | unsigned int bias = miGetZeroLineBias(pDrawable->pScreen); |
| 528 | unsigned int oc1; /* outcode of point 1 */ |
| 529 | unsigned int oc2; /* outcode of point 2 */ |
| 530 | |
| 531 | nBox = RegionNumRects(pClip); |
| 532 | pBox = RegionRects(pClip); |
| 533 | |
| 534 | bres = fbSelectBres(pDrawable, pGC); |
| 535 | |
| 536 | CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy, 1, 1, octant); |
| 537 | |
| 538 | if (adx > ady) { |
| 539 | axis = X_AXIS; |
| 540 | e1 = ady << 1; |
| 541 | e2 = e1 - (adx << 1); |
| 542 | e = e1 - adx; |
| 543 | len = adx; |
| 544 | } |
| 545 | else { |
| 546 | axis = Y_AXIS; |
| 547 | e1 = adx << 1; |
| 548 | e2 = e1 - (ady << 1); |
| 549 | e = e1 - ady; |
| 550 | SetYMajorOctant(octant); |
| 551 | len = ady; |
| 552 | } |
| 553 | |
| 554 | FIXUP_ERROR(e, octant, bias); |
| 555 | |
| 556 | /* |
| 557 | * Adjust error terms to compare against zero |
| 558 | */ |
| 559 | e3 = e2 - e1; |
| 560 | e = e - e1; |
| 561 | |
| 562 | /* we have bresenham parameters and two points. |
| 563 | all we have to do now is clip and draw. |
| 564 | */ |
| 565 | |
| 566 | if (drawLast) |
| 567 | len++; |
| 568 | dashoff = *dashOffset; |
| 569 | *dashOffset = dashoff + len; |
| 570 | while (nBox--) { |
| 571 | oc1 = 0; |
| 572 | oc2 = 0; |
| 573 | OUTCODES(oc1, x1, y1, pBox); |
| 574 | OUTCODES(oc2, x2, y2, pBox); |
| 575 | if ((oc1 | oc2) == 0) { |
| 576 | (*bres) (pDrawable, pGC, dashoff, |
| 577 | signdx, signdy, axis, x1, y1, e, e1, e3, len); |
| 578 | break; |
| 579 | } |
| 580 | else if (oc1 & oc2) { |
| 581 | pBox++; |
| 582 | } |
| 583 | else { |
| 584 | int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2; |
| 585 | int clip1 = 0, clip2 = 0; |
| 586 | int clipdx, clipdy; |
| 587 | int err; |
| 588 | |
| 589 | if (miZeroClipLine(pBox->x1, pBox->y1, pBox->x2 - 1, |
| 590 | pBox->y2 - 1, |
| 591 | &new_x1, &new_y1, &new_x2, &new_y2, |
| 592 | adx, ady, &clip1, &clip2, |
| 593 | octant, bias, oc1, oc2) == -1) { |
| 594 | pBox++; |
| 595 | continue; |
| 596 | } |
| 597 | |
| 598 | if (axis == X_AXIS) |
| 599 | len = abs(new_x2 - new_x1); |
| 600 | else |
| 601 | len = abs(new_y2 - new_y1); |
| 602 | if (clip2 != 0 || drawLast) |
| 603 | len++; |
| 604 | if (len) { |
| 605 | /* unwind bresenham error term to first point */ |
| 606 | doff = dashoff; |
| 607 | err = e; |
| 608 | if (clip1) { |
| 609 | clipdx = abs(new_x1 - x1); |
| 610 | clipdy = abs(new_y1 - y1); |
| 611 | if (axis == X_AXIS) { |
| 612 | doff += clipdx; |
| 613 | err += e3 * clipdy + e1 * clipdx; |
| 614 | } |
| 615 | else { |
| 616 | doff += clipdy; |
| 617 | err += e3 * clipdx + e1 * clipdy; |
| 618 | } |
| 619 | } |
| 620 | (*bres) (pDrawable, pGC, doff, |
| 621 | signdx, signdy, axis, new_x1, new_y1, |
| 622 | err, e1, e3, len); |
| 623 | } |
| 624 | pBox++; |
| 625 | } |
| 626 | } /* while (nBox--) */ |
| 627 | } |