1428d7b3dSmrg/* 2428d7b3dSmrg * Copyright © 1998 Keith Packard 3428d7b3dSmrg * Copyright © 2012 Intel Corporation 4428d7b3dSmrg * 5428d7b3dSmrg * Permission to use, copy, modify, distribute, and sell this software and its 6428d7b3dSmrg * documentation for any purpose is hereby granted without fee, provided that 7428d7b3dSmrg * the above copyright notice appear in all copies and that both that 8428d7b3dSmrg * copyright notice and this permission notice appear in supporting 9428d7b3dSmrg * documentation, and that the name of Keith Packard not be used in 10428d7b3dSmrg * advertising or publicity pertaining to distribution of the software without 11428d7b3dSmrg * specific, written prior permission. Keith Packard makes no 12428d7b3dSmrg * representations about the suitability of this software for any purpose. It 13428d7b3dSmrg * is provided "as is" without express or implied warranty. 14428d7b3dSmrg * 15428d7b3dSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16428d7b3dSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 17428d7b3dSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 18428d7b3dSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 19428d7b3dSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 20428d7b3dSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 21428d7b3dSmrg * PERFORMANCE OF THIS SOFTWARE. 22428d7b3dSmrg */ 23428d7b3dSmrg 24428d7b3dSmrg#include <stdlib.h> 25428d7b3dSmrg 26428d7b3dSmrg#include "fb.h" 27428d7b3dSmrg#include "fbclip.h" 28428d7b3dSmrg#include <miline.h> 29428d7b3dSmrg#include <scrnintstr.h> 30428d7b3dSmrg 31428d7b3dSmrg#define FbDashDeclare \ 32428d7b3dSmrg unsigned char *__dash, *__firstDash, *__lastDash 33428d7b3dSmrg 34428d7b3dSmrg#define FbDashInit(gc,pgc,dashOffset,dashlen,even) { \ 35428d7b3dSmrg (even) = TRUE; \ 36428d7b3dSmrg __firstDash = (gc)->dash; \ 37428d7b3dSmrg __lastDash = __firstDash + (gc)->numInDashList; \ 38428d7b3dSmrg (dashOffset) %= (pgc)->dashLength; \ 39428d7b3dSmrg \ 40428d7b3dSmrg __dash = __firstDash; \ 41428d7b3dSmrg while ((dashOffset) >= ((dashlen) = *__dash)) { \ 42428d7b3dSmrg (dashOffset) -= (dashlen); \ 43428d7b3dSmrg (even) = 1-(even); \ 44428d7b3dSmrg if (++__dash == __lastDash) \ 45428d7b3dSmrg __dash = __firstDash; \ 46428d7b3dSmrg } \ 47428d7b3dSmrg (dashlen) -= (dashOffset); \ 48428d7b3dSmrg} 49428d7b3dSmrg 50428d7b3dSmrg#define FbDashNext(dashlen) { \ 51428d7b3dSmrg if (++__dash == __lastDash) \ 52428d7b3dSmrg __dash = __firstDash; \ 53428d7b3dSmrg (dashlen) = *__dash; \ 54428d7b3dSmrg} 55428d7b3dSmrg 56428d7b3dSmrg/* as numInDashList is always even, this case can skip a test */ 57428d7b3dSmrg 58428d7b3dSmrg#define FbDashNextEven(dashlen) { \ 59428d7b3dSmrg (dashlen) = *++__dash; \ 60428d7b3dSmrg} 61428d7b3dSmrg 62428d7b3dSmrg#define FbDashNextOdd(dashlen) FbDashNext(dashlen) 63428d7b3dSmrg 64428d7b3dSmrg#define FbDashStep(dashlen,even) { \ 65428d7b3dSmrg if (!--(dashlen)) { \ 66428d7b3dSmrg FbDashNext(dashlen); \ 67428d7b3dSmrg (even) = 1-(even); \ 68428d7b3dSmrg } \ 69428d7b3dSmrg} 70428d7b3dSmrg 71428d7b3dSmrg#define fbBresShiftMask(mask,dir,bpp) ((bpp == FB_STIP_UNIT) ? 0 : \ 72428d7b3dSmrg ((dir < 0) ? FbStipLeft(mask,bpp) : \ 73428d7b3dSmrg FbStipRight(mask,bpp))) 74428d7b3dSmrg 75428d7b3dSmrgtypedef void FbBres(DrawablePtr drawable, 76428d7b3dSmrg GCPtr gc, 77428d7b3dSmrg int dashOffset, 78428d7b3dSmrg int sdx, 79428d7b3dSmrg int sdy, 80428d7b3dSmrg int axis, int x, int y, int e, int e1, int e3, int len); 81428d7b3dSmrg 82428d7b3dSmrg#define BRESSOLID fbBresSolid8 83428d7b3dSmrg#define BRESSOLIDR fbBresSolidR8 84428d7b3dSmrg#define BRESDASH fbBresDash8 85428d7b3dSmrg#define BITS BYTE 86428d7b3dSmrg#define BITS2 CARD16 87428d7b3dSmrg#define BITS4 CARD32 88428d7b3dSmrg#include "fbsegbits.h" 89428d7b3dSmrg#undef BRESSOLID 90428d7b3dSmrg#undef BRESSOLIDR 91428d7b3dSmrg#undef BRESDASH 92428d7b3dSmrg#undef BITS 93428d7b3dSmrg#undef BITS2 94428d7b3dSmrg#undef BITS4 95428d7b3dSmrg 96428d7b3dSmrg#define BRESSOLID fbBresSolid16 97428d7b3dSmrg#define BRESSOLIDR fbBresSolidR16 98428d7b3dSmrg#define BRESDASH fbBresDash16 99428d7b3dSmrg#define BITS CARD16 100428d7b3dSmrg#define BITS2 CARD32 101428d7b3dSmrg#include "fbsegbits.h" 102428d7b3dSmrg#undef BRESSOLID 103428d7b3dSmrg#undef BRESSOLIDR 104428d7b3dSmrg#undef BRESDASH 105428d7b3dSmrg#undef BITS 106428d7b3dSmrg#undef BITS2 107428d7b3dSmrg 108428d7b3dSmrg#define BRESSOLID fbBresSolid32 109428d7b3dSmrg#define BRESSOLIDR fbBresSolidR32 110428d7b3dSmrg#define BRESDASH fbBresDash32 111428d7b3dSmrg#define BITS CARD32 112428d7b3dSmrg#include "fbsegbits.h" 113428d7b3dSmrg#undef BRESSOLID 114428d7b3dSmrg#undef BRESSOLIDR 115428d7b3dSmrg#undef BRESDASH 116428d7b3dSmrg#undef BITS 117428d7b3dSmrg 118428d7b3dSmrgstatic void 119428d7b3dSmrgfbBresSolid(DrawablePtr drawable, GCPtr gc, int dashOffset, 120428d7b3dSmrg int sdx, int sdy, int axis, 121428d7b3dSmrg int x1, int y1, 122428d7b3dSmrg int e, int e1, int e3, int len) 123428d7b3dSmrg{ 124428d7b3dSmrg FbStip *dst; 125428d7b3dSmrg FbStride stride; 126428d7b3dSmrg int bpp; 127428d7b3dSmrg int dx, dy; 128428d7b3dSmrg FbGCPrivPtr pgc = fb_gc(gc); 129428d7b3dSmrg FbStip and = (FbStip) pgc->and; 130428d7b3dSmrg FbStip xor = (FbStip) pgc->xor; 131428d7b3dSmrg FbStip mask, mask0; 132428d7b3dSmrg FbStip bits; 133428d7b3dSmrg 134428d7b3dSmrg fbGetStipDrawable(drawable, dst, stride, bpp, dx, dy); 135428d7b3dSmrg dst += ((y1 + dy) * stride); 136428d7b3dSmrg x1 = (x1 + dx) * bpp; 137428d7b3dSmrg dst += x1 >> FB_STIP_SHIFT; 138428d7b3dSmrg x1 &= FB_STIP_MASK; 139428d7b3dSmrg mask0 = FbStipMask(0, bpp); 140428d7b3dSmrg mask = FbStipRight(mask0, x1); 141428d7b3dSmrg if (sdx < 0) 142428d7b3dSmrg mask0 = FbStipRight(mask0, FB_STIP_UNIT - bpp); 143428d7b3dSmrg if (sdy < 0) 144428d7b3dSmrg stride = -stride; 145428d7b3dSmrg if (axis == X_AXIS) { 146428d7b3dSmrg bits = 0; 147428d7b3dSmrg while (len--) { 148428d7b3dSmrg bits |= mask; 149428d7b3dSmrg mask = fbBresShiftMask(mask, sdx, bpp); 150428d7b3dSmrg if (!mask) { 151428d7b3dSmrg WRITE(dst, FbDoMaskRRop(READ(dst), and, xor, bits)); 152428d7b3dSmrg bits = 0; 153428d7b3dSmrg dst += sdx; 154428d7b3dSmrg mask = mask0; 155428d7b3dSmrg } 156428d7b3dSmrg e += e1; 157428d7b3dSmrg if (e >= 0) { 158428d7b3dSmrg WRITE(dst, FbDoMaskRRop(READ(dst), and, xor, bits)); 159428d7b3dSmrg bits = 0; 160428d7b3dSmrg dst += stride; 161428d7b3dSmrg e += e3; 162428d7b3dSmrg } 163428d7b3dSmrg } 164428d7b3dSmrg if (bits) 165428d7b3dSmrg WRITE(dst, FbDoMaskRRop(READ(dst), and, xor, bits)); 166428d7b3dSmrg } else { 167428d7b3dSmrg while (len--) { 168428d7b3dSmrg WRITE(dst, FbDoMaskRRop(READ(dst), and, xor, mask)); 169428d7b3dSmrg dst += stride; 170428d7b3dSmrg e += e1; 171428d7b3dSmrg if (e >= 0) { 172428d7b3dSmrg e += e3; 173428d7b3dSmrg mask = fbBresShiftMask(mask, sdx, bpp); 174428d7b3dSmrg if (!mask) { 175428d7b3dSmrg dst += sdx; 176428d7b3dSmrg mask = mask0; 177428d7b3dSmrg } 178428d7b3dSmrg } 179428d7b3dSmrg } 180428d7b3dSmrg } 181428d7b3dSmrg} 182428d7b3dSmrg 183428d7b3dSmrgstatic void 184428d7b3dSmrgfbBresDash(DrawablePtr drawable, GCPtr gc, int dashOffset, 185428d7b3dSmrg int sdx, int sdy, int axis, 186428d7b3dSmrg int x1, int y1, 187428d7b3dSmrg int e, int e1, int e3, int len) 188428d7b3dSmrg{ 189428d7b3dSmrg FbStip *dst; 190428d7b3dSmrg FbStride stride; 191428d7b3dSmrg int bpp; 192428d7b3dSmrg int dx, dy; 193428d7b3dSmrg FbGCPrivPtr pgc = fb_gc(gc); 194428d7b3dSmrg FbStip and = (FbStip) pgc->and; 195428d7b3dSmrg FbStip xor = (FbStip) pgc->xor; 196428d7b3dSmrg FbStip bgand = (FbStip) pgc->bgand; 197428d7b3dSmrg FbStip bgxor = (FbStip) pgc->bgxor; 198428d7b3dSmrg FbStip mask, mask0; 199428d7b3dSmrg 200428d7b3dSmrg FbDashDeclare; 201428d7b3dSmrg int dashlen; 202428d7b3dSmrg bool even; 203428d7b3dSmrg bool doOdd; 204428d7b3dSmrg 205428d7b3dSmrg fbGetStipDrawable(drawable, dst, stride, bpp, dx, dy); 206428d7b3dSmrg doOdd = gc->lineStyle == LineDoubleDash; 207428d7b3dSmrg 208428d7b3dSmrg FbDashInit(gc, pgc, dashOffset, dashlen, even); 209428d7b3dSmrg 210428d7b3dSmrg dst += ((y1 + dy) * stride); 211428d7b3dSmrg x1 = (x1 + dx) * bpp; 212428d7b3dSmrg dst += x1 >> FB_STIP_SHIFT; 213428d7b3dSmrg x1 &= FB_STIP_MASK; 214428d7b3dSmrg mask0 = FbStipMask(0, bpp); 215428d7b3dSmrg mask = FbStipRight(mask0, x1); 216428d7b3dSmrg if (sdx < 0) 217428d7b3dSmrg mask0 = FbStipRight(mask0, FB_STIP_UNIT - bpp); 218428d7b3dSmrg if (sdy < 0) 219428d7b3dSmrg stride = -stride; 220428d7b3dSmrg while (len--) { 221428d7b3dSmrg if (even) 222428d7b3dSmrg WRITE(dst, FbDoMaskRRop(READ(dst), and, xor, mask)); 223428d7b3dSmrg else if (doOdd) 224428d7b3dSmrg WRITE(dst, FbDoMaskRRop(READ(dst), bgand, bgxor, mask)); 225428d7b3dSmrg if (axis == X_AXIS) { 226428d7b3dSmrg mask = fbBresShiftMask(mask, sdx, bpp); 227428d7b3dSmrg if (!mask) { 228428d7b3dSmrg dst += sdx; 229428d7b3dSmrg mask = mask0; 230428d7b3dSmrg } 231428d7b3dSmrg e += e1; 232428d7b3dSmrg if (e >= 0) { 233428d7b3dSmrg dst += stride; 234428d7b3dSmrg e += e3; 235428d7b3dSmrg } 236428d7b3dSmrg } else { 237428d7b3dSmrg dst += stride; 238428d7b3dSmrg e += e1; 239428d7b3dSmrg if (e >= 0) { 240428d7b3dSmrg e += e3; 241428d7b3dSmrg mask = fbBresShiftMask(mask, sdx, bpp); 242428d7b3dSmrg if (!mask) { 243428d7b3dSmrg dst += sdx; 244428d7b3dSmrg mask = mask0; 245428d7b3dSmrg } 246428d7b3dSmrg } 247428d7b3dSmrg } 248428d7b3dSmrg FbDashStep(dashlen, even); 249428d7b3dSmrg } 250428d7b3dSmrg} 251428d7b3dSmrg 252428d7b3dSmrgstatic void 253428d7b3dSmrgfbBresFill(DrawablePtr drawable, GCPtr gc, int dashOffset, 254428d7b3dSmrg int sdx, int sdy, int axis, 255428d7b3dSmrg int x1, int y1, 256428d7b3dSmrg int e, int e1, int e3, int len) 257428d7b3dSmrg{ 258428d7b3dSmrg while (len--) { 259428d7b3dSmrg fbFill(drawable, gc, x1, y1, 1, 1); 260428d7b3dSmrg if (axis == X_AXIS) { 261428d7b3dSmrg x1 += sdx; 262428d7b3dSmrg e += e1; 263428d7b3dSmrg if (e >= 0) { 264428d7b3dSmrg e += e3; 265428d7b3dSmrg y1 += sdy; 266428d7b3dSmrg } 267428d7b3dSmrg } else { 268428d7b3dSmrg y1 += sdy; 269428d7b3dSmrg e += e1; 270428d7b3dSmrg if (e >= 0) { 271428d7b3dSmrg e += e3; 272428d7b3dSmrg x1 += sdx; 273428d7b3dSmrg } 274428d7b3dSmrg } 275428d7b3dSmrg } 276428d7b3dSmrg} 277428d7b3dSmrg 278428d7b3dSmrgstatic void 279428d7b3dSmrgfbSetFg(DrawablePtr drawable, GCPtr gc, Pixel fg) 280428d7b3dSmrg{ 281428d7b3dSmrg if (fg != gc->fgPixel) { 282428d7b3dSmrg gc->fgPixel = fg; 283428d7b3dSmrg fbValidateGC(gc, GCForeground, drawable); 284428d7b3dSmrg } 285428d7b3dSmrg} 286428d7b3dSmrg 287428d7b3dSmrgstatic void 288428d7b3dSmrgfbBresFillDash(DrawablePtr drawable, 289428d7b3dSmrg GCPtr gc, 290428d7b3dSmrg int dashOffset, 291428d7b3dSmrg int sdx, 292428d7b3dSmrg int sdy, 293428d7b3dSmrg int axis, int x1, int y1, int e, int e1, int e3, int len) 294428d7b3dSmrg{ 295428d7b3dSmrg FbGCPrivPtr pgc = fb_gc(gc); 296428d7b3dSmrg 297428d7b3dSmrg FbDashDeclare; 298428d7b3dSmrg int dashlen; 299428d7b3dSmrg bool even; 300428d7b3dSmrg bool doOdd; 301428d7b3dSmrg bool doBg; 302428d7b3dSmrg Pixel fg, bg; 303428d7b3dSmrg 304428d7b3dSmrg fg = gc->fgPixel; 305428d7b3dSmrg bg = gc->bgPixel; 306428d7b3dSmrg 307428d7b3dSmrg /* whether to fill the odd dashes */ 308428d7b3dSmrg doOdd = gc->lineStyle == LineDoubleDash; 309428d7b3dSmrg /* whether to switch fg to bg when filling odd dashes */ 310428d7b3dSmrg doBg = doOdd && (gc->fillStyle == FillSolid || 311428d7b3dSmrg gc->fillStyle == FillStippled); 312428d7b3dSmrg 313428d7b3dSmrg /* compute current dash position */ 314428d7b3dSmrg FbDashInit(gc, pgc, dashOffset, dashlen, even); 315428d7b3dSmrg 316428d7b3dSmrg while (len--) { 317428d7b3dSmrg if (even || doOdd) { 318428d7b3dSmrg if (doBg) { 319428d7b3dSmrg if (even) 320428d7b3dSmrg fbSetFg(drawable, gc, fg); 321428d7b3dSmrg else 322428d7b3dSmrg fbSetFg(drawable, gc, bg); 323428d7b3dSmrg } 324428d7b3dSmrg fbFill(drawable, gc, x1, y1, 1, 1); 325428d7b3dSmrg } 326428d7b3dSmrg if (axis == X_AXIS) { 327428d7b3dSmrg x1 += sdx; 328428d7b3dSmrg e += e1; 329428d7b3dSmrg if (e >= 0) { 330428d7b3dSmrg e += e3; 331428d7b3dSmrg y1 += sdy; 332428d7b3dSmrg } 333428d7b3dSmrg } else { 334428d7b3dSmrg y1 += sdy; 335428d7b3dSmrg e += e1; 336428d7b3dSmrg if (e >= 0) { 337428d7b3dSmrg e += e3; 338428d7b3dSmrg x1 += sdx; 339428d7b3dSmrg } 340428d7b3dSmrg } 341428d7b3dSmrg FbDashStep(dashlen, even); 342428d7b3dSmrg } 343428d7b3dSmrg if (doBg) 344428d7b3dSmrg fbSetFg(drawable, gc, fg); 345428d7b3dSmrg} 346428d7b3dSmrg 347428d7b3dSmrgstatic FbBres * 348428d7b3dSmrgfbSelectBres(DrawablePtr drawable, GCPtr gc) 349428d7b3dSmrg{ 350428d7b3dSmrg FbGCPrivPtr pgc = fb_gc(gc); 351428d7b3dSmrg int bpp = drawable->bitsPerPixel; 352428d7b3dSmrg FbBres *bres; 353428d7b3dSmrg 354428d7b3dSmrg DBG(("%s: line=%d, fill=%d, and=%lx, bgand=%lx\n", 355428d7b3dSmrg __FUNCTION__, gc->lineStyle, gc->fillStyle, 356428d7b3dSmrg (long)pgc->and, (long)pgc->bgand)); 357428d7b3dSmrg assert(gc->lineWidth == 0); 358428d7b3dSmrg 359428d7b3dSmrg if (gc->lineStyle == LineSolid) { 360428d7b3dSmrg bres = fbBresFill; 361428d7b3dSmrg if (gc->fillStyle == FillSolid) { 362428d7b3dSmrg bres = fbBresSolid; 363428d7b3dSmrg if (pgc->and == 0) { 364428d7b3dSmrg switch (bpp) { 365428d7b3dSmrg case 8: 366428d7b3dSmrg bres = fbBresSolid8; 367428d7b3dSmrg break; 368428d7b3dSmrg case 16: 369428d7b3dSmrg bres = fbBresSolid16; 370428d7b3dSmrg break; 371428d7b3dSmrg case 32: 372428d7b3dSmrg bres = fbBresSolid32; 373428d7b3dSmrg break; 374428d7b3dSmrg } 375428d7b3dSmrg } else { 376428d7b3dSmrg switch (bpp) { 377428d7b3dSmrg case 8: 378428d7b3dSmrg bres = fbBresSolidR8; 379428d7b3dSmrg break; 380428d7b3dSmrg case 16: 381428d7b3dSmrg bres = fbBresSolidR16; 382428d7b3dSmrg break; 383428d7b3dSmrg case 32: 384428d7b3dSmrg bres = fbBresSolidR32; 385428d7b3dSmrg break; 386428d7b3dSmrg } 387428d7b3dSmrg } 388428d7b3dSmrg } 389428d7b3dSmrg } else { 390428d7b3dSmrg bres = fbBresFillDash; 391428d7b3dSmrg if (gc->fillStyle == FillSolid) { 392428d7b3dSmrg bres = fbBresDash; 393428d7b3dSmrg if (pgc->and == 0 && 394428d7b3dSmrg (gc->lineStyle == LineOnOffDash || pgc->bgand == 0)) { 395428d7b3dSmrg switch (bpp) { 396428d7b3dSmrg case 8: 397428d7b3dSmrg bres = fbBresDash8; 398428d7b3dSmrg break; 399428d7b3dSmrg case 16: 400428d7b3dSmrg bres = fbBresDash16; 401428d7b3dSmrg break; 402428d7b3dSmrg case 32: 403428d7b3dSmrg bres = fbBresDash32; 404428d7b3dSmrg break; 405428d7b3dSmrg } 406428d7b3dSmrg } 407428d7b3dSmrg } 408428d7b3dSmrg } 409428d7b3dSmrg return bres; 410428d7b3dSmrg} 411428d7b3dSmrg 412428d7b3dSmrgstruct fbSegment { 413428d7b3dSmrg FbBres *bres; 414428d7b3dSmrg bool drawLast; 415428d7b3dSmrg int *dashOffset; 416428d7b3dSmrg int x1, y1, x2, y2; 417428d7b3dSmrg}; 418428d7b3dSmrg 419428d7b3dSmrgstatic void 420428d7b3dSmrg_fbSegment(DrawablePtr drawable, GCPtr gc, const BoxRec *b, void *_data) 421428d7b3dSmrg{ 422428d7b3dSmrg struct fbSegment *data = _data; 423428d7b3dSmrg const unsigned int bias = miGetZeroLineBias(drawable->pScreen); 424428d7b3dSmrg int adx, ady; /* abs values of dx and dy */ 425428d7b3dSmrg int sdx, sdy; /* sign of dx and dy */ 426428d7b3dSmrg int e, e1, e2, e3; /* bresenham error and increments */ 427428d7b3dSmrg int len, axis, octant; 428428d7b3dSmrg int dashoff, doff; 429428d7b3dSmrg unsigned int oc1, oc2; 430428d7b3dSmrg 431428d7b3dSmrg DBG(("%s box=(%d, %d),(%d, %d)\n", 432428d7b3dSmrg __FUNCTION__, b->x1, b->y1, b->x2, b->y2)); 433428d7b3dSmrg 434428d7b3dSmrg CalcLineDeltas(data->x1, data->y1, data->x2, data->y2, 435428d7b3dSmrg adx, ady, sdx, sdy, 1, 1, octant); 436428d7b3dSmrg 437428d7b3dSmrg if (adx > ady) { 438428d7b3dSmrg axis = X_AXIS; 439428d7b3dSmrg e1 = ady << 1; 440428d7b3dSmrg e2 = e1 - (adx << 1); 441428d7b3dSmrg e = e1 - adx; 442428d7b3dSmrg len = adx; 443428d7b3dSmrg } else { 444428d7b3dSmrg axis = Y_AXIS; 445428d7b3dSmrg e1 = adx << 1; 446428d7b3dSmrg e2 = e1 - (ady << 1); 447428d7b3dSmrg e = e1 - ady; 448428d7b3dSmrg SetYMajorOctant(octant); 449428d7b3dSmrg len = ady; 450428d7b3dSmrg } 451428d7b3dSmrg 452428d7b3dSmrg FIXUP_ERROR(e, octant, bias); 453428d7b3dSmrg 454428d7b3dSmrg /* 455428d7b3dSmrg * Adjust error terms to compare against zero 456428d7b3dSmrg */ 457428d7b3dSmrg e3 = e2 - e1; 458428d7b3dSmrg e = e - e1; 459428d7b3dSmrg 460428d7b3dSmrg if (data->drawLast) 461428d7b3dSmrg len++; 462428d7b3dSmrg dashoff = *data->dashOffset; 463428d7b3dSmrg *data->dashOffset = dashoff + len; 464428d7b3dSmrg 465428d7b3dSmrg oc1 = 0; 466428d7b3dSmrg oc2 = 0; 467428d7b3dSmrg OUTCODES(oc1, data->x1, data->y1, b); 468428d7b3dSmrg OUTCODES(oc2, data->x2, data->y2, b); 469428d7b3dSmrg if ((oc1 | oc2) == 0) { 470428d7b3dSmrg data->bres(drawable, gc, dashoff, 471428d7b3dSmrg sdx, sdy, axis, data->x1, data->y1, e, e1, e3, len); 472428d7b3dSmrg } else if (oc1 & oc2) { 473428d7b3dSmrg } else { 474428d7b3dSmrg int new_x1 = data->x1, new_y1 = data->y1; 475428d7b3dSmrg int new_x2 = data->x2, new_y2 = data->y2; 476428d7b3dSmrg int clip1 = 0, clip2 = 0; 477428d7b3dSmrg int clipdx, clipdy; 478428d7b3dSmrg int err; 479428d7b3dSmrg 480428d7b3dSmrg if (miZeroClipLine(b->x1, b->y1, b->x2-1, b->y2-1, 481428d7b3dSmrg &new_x1, &new_y1, &new_x2, &new_y2, 482428d7b3dSmrg adx, ady, &clip1, &clip2, 483428d7b3dSmrg octant, bias, oc1, oc2) == -1) 484428d7b3dSmrg return; 485428d7b3dSmrg 486428d7b3dSmrg if (axis == X_AXIS) 487428d7b3dSmrg len = abs(new_x2 - new_x1); 488428d7b3dSmrg else 489428d7b3dSmrg len = abs(new_y2 - new_y1); 490428d7b3dSmrg if (clip2 != 0 || data->drawLast) 491428d7b3dSmrg len++; 492428d7b3dSmrg if (len) { 493428d7b3dSmrg /* unwind bresenham error term to first point */ 494428d7b3dSmrg doff = dashoff; 495428d7b3dSmrg err = e; 496428d7b3dSmrg if (clip1) { 497428d7b3dSmrg clipdx = abs(new_x1 - data->x1); 498428d7b3dSmrg clipdy = abs(new_y1 - data->y1); 499428d7b3dSmrg if (axis == X_AXIS) { 500428d7b3dSmrg doff += clipdx; 501428d7b3dSmrg err += e3 * clipdy + e1 * clipdx; 502428d7b3dSmrg } else { 503428d7b3dSmrg doff += clipdy; 504428d7b3dSmrg err += e3 * clipdx + e1 * clipdy; 505428d7b3dSmrg } 506428d7b3dSmrg } 507428d7b3dSmrg data->bres(drawable, gc, doff, 508428d7b3dSmrg sdx, sdy, axis, new_x1, new_y1, 509428d7b3dSmrg err, e1, e3, len); 510428d7b3dSmrg } 511428d7b3dSmrg } 512428d7b3dSmrg} 513428d7b3dSmrg 514428d7b3dSmrgvoid 515428d7b3dSmrgfbSegment(DrawablePtr drawable, GCPtr gc, 516428d7b3dSmrg int x1, int y1, int x2, int y2, 517428d7b3dSmrg bool drawLast, int *dashOffset) 518428d7b3dSmrg{ 519428d7b3dSmrg struct fbSegment data; 520428d7b3dSmrg BoxRec box; 521428d7b3dSmrg 522428d7b3dSmrg DBG(("%s (%d, %d), (%d, %d), drawLast?=%d\n", 523428d7b3dSmrg __FUNCTION__, x1, y1, x2, y2, drawLast)); 524428d7b3dSmrg 525428d7b3dSmrg /* simple overestimate of line extents for clipping */ 526428d7b3dSmrg box.x1 = x1 - 1; 527428d7b3dSmrg box.y1 = y1 - 1; 528428d7b3dSmrg box.x2 = x2 + 1; 529428d7b3dSmrg box.y2 = y2 + 1; 530428d7b3dSmrg 531428d7b3dSmrg data.x1 = x1; 532428d7b3dSmrg data.y1 = y1; 533428d7b3dSmrg data.x2 = x2; 534428d7b3dSmrg data.y2 = y2; 535428d7b3dSmrg 536428d7b3dSmrg data.dashOffset = dashOffset; 537428d7b3dSmrg data.drawLast = drawLast; 538428d7b3dSmrg data.bres = fbSelectBres(drawable, gc); 539428d7b3dSmrg 540428d7b3dSmrg fbDrawableRunUnclipped(drawable, gc, &box, _fbSegment, &data); 541428d7b3dSmrg} 542428d7b3dSmrg 543428d7b3dSmrgvoid 544428d7b3dSmrgfbSegment1(DrawablePtr drawable, GCPtr gc, const BoxRec *b, 545428d7b3dSmrg int x1, int y1, int x2, int y2, 546428d7b3dSmrg bool drawLast, int *dashOffset) 547428d7b3dSmrg{ 548428d7b3dSmrg struct fbSegment data; 549428d7b3dSmrg 550428d7b3dSmrg DBG(("%s (%d, %d), (%d, %d), drawLast?=%d\n", 551428d7b3dSmrg __FUNCTION__, x1, y1, x2, y2, drawLast)); 552428d7b3dSmrg 553428d7b3dSmrg data.x1 = x1; 554428d7b3dSmrg data.y1 = y1; 555428d7b3dSmrg data.x2 = x2; 556428d7b3dSmrg data.y2 = y2; 557428d7b3dSmrg 558428d7b3dSmrg data.dashOffset = dashOffset; 559428d7b3dSmrg data.drawLast = drawLast; 560428d7b3dSmrg data.bres = fbSelectBres(drawable, gc); 561428d7b3dSmrg 562428d7b3dSmrg _fbSegment(drawable, gc, b, &data); 563428d7b3dSmrg} 564