]> git.sesse.net Git - rdpsrv/blob - Xserver/programs/Xserver/cfb/cfbline.c
Import X server from vnc-3.3.7.
[rdpsrv] / Xserver / programs / Xserver / cfb / cfbline.c
1 /***********************************************************
2
3 Copyright (c) 1987  X Consortium
4
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal
7 in the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 Except as contained in this notice, the name of the X Consortium shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from the X Consortium.
25
26
27 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
28
29                         All Rights Reserved
30
31 Permission to use, copy, modify, and distribute this software and its 
32 documentation for any purpose and without fee is hereby granted, 
33 provided that the above copyright notice appear in all copies and that
34 both that copyright notice and this permission notice appear in 
35 supporting documentation, and that the name of Digital not be
36 used in advertising or publicity pertaining to distribution of the
37 software without specific, written prior permission.  
38
39 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
40 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
41 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
42 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
43 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
44 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
45 SOFTWARE.
46
47 ******************************************************************/
48 /* $XConsortium: cfbline.c,v 1.24 94/07/28 14:33:33 dpw Exp $ */
49 /* $XFree86: xc/programs/Xserver/cfb/cfbline.c,v 3.0 1996/06/29 09:05:38 dawes Exp $ */
50 #include "X.h"
51
52 #include "gcstruct.h"
53 #include "windowstr.h"
54 #include "pixmapstr.h"
55 #include "regionstr.h"
56 #include "scrnintstr.h"
57 #include "mistruct.h"
58
59 #include "cfb.h"
60 #include "cfbmskbits.h"
61 #include "miline.h"
62
63 /* single-pixel lines on a color frame buffer
64
65    NON-SLOPED LINES
66    horizontal lines are always drawn left to right; we have to
67 move the endpoints right by one after they're swapped.
68    horizontal lines will be confined to a single band of a
69 region.  the code finds that band (giving up if the lower
70 bound of the band is above the line we're drawing); then it
71 finds the first box in that band that contains part of the
72 line.  we clip the line to subsequent boxes in that band.
73    vertical lines are always drawn top to bottom (y-increasing.)
74 this requires adding one to the y-coordinate of each endpoint
75 after swapping.
76
77    SLOPED LINES
78    when clipping a sloped line, we bring the second point inside
79 the clipping box, rather than one beyond it, and then add 1 to
80 the length of the line before drawing it.  this lets us use
81 the same box for finding the outcodes for both endpoints.  since
82 the equation for clipping the second endpoint to an edge gives us
83 1 beyond the edge, we then have to move the point towards the
84 first point by one step on the major axis.
85    eventually, there will be a diagram here to explain what's going
86 on.  the method uses Cohen-Sutherland outcodes to determine
87 outsideness, and a method similar to Pike's layers for doing the
88 actual clipping.
89
90 */
91
92 void
93 #ifdef POLYSEGMENT
94 cfbSegmentSS (pDrawable, pGC, nseg, pSeg)
95     DrawablePtr pDrawable;
96     GCPtr       pGC;
97     int         nseg;
98     register xSegment   *pSeg;
99 #else
100 cfbLineSS (pDrawable, pGC, mode, npt, pptInit)
101     DrawablePtr pDrawable;
102     GCPtr       pGC;
103     int         mode;           /* Origin or Previous */
104     int         npt;            /* number of points */
105     DDXPointPtr pptInit;
106 #endif
107 {
108     int nboxInit;
109     register int nbox;
110     BoxPtr pboxInit;
111     register BoxPtr pbox;
112 #ifndef POLYSEGMENT
113     register DDXPointPtr ppt;   /* pointer to list of translated points */
114 #endif
115
116     unsigned int oc1;           /* outcode of point 1 */
117     unsigned int oc2;           /* outcode of point 2 */
118
119     unsigned long *addrl;       /* address of destination pixmap */
120     int nlwidth;                /* width in longwords of destination pixmap */
121     int xorg, yorg;             /* origin of window */
122
123     int adx;            /* abs values of dx and dy */
124     int ady;
125     int signdx;         /* sign of dx and dy */
126     int signdy;
127     int e, e1, e2;              /* bresenham error and increments */
128     int len;                    /* length of segment */
129     int axis;                   /* major axis */
130     int octant;
131     unsigned int bias = miGetZeroLineBias(pDrawable->pScreen);
132
133                                 /* a bunch of temporaries */
134     int tmp;
135     register int y1, y2;
136     register int x1, x2;
137     RegionPtr cclip;
138     cfbPrivGCPtr    devPriv;
139     unsigned long   xor, and;
140     int             alu;
141
142     devPriv = cfbGetGCPrivate(pGC);
143     cclip = devPriv->pCompositeClip;
144     pboxInit = REGION_RECTS(cclip);
145     nboxInit = REGION_NUM_RECTS(cclip);
146
147     cfbGetLongWidthAndPointer (pDrawable, nlwidth, addrl)
148
149     alu = devPriv->rop;
150     xor = devPriv->xor;
151     and = devPriv->and;
152     xorg = pDrawable->x;
153     yorg = pDrawable->y;
154 #ifdef POLYSEGMENT
155     while (nseg--)
156 #else
157     ppt = pptInit;
158     x2 = ppt->x + xorg;
159     y2 = ppt->y + yorg;
160     while(--npt)
161 #endif
162     {
163         nbox = nboxInit;
164         pbox = pboxInit;
165
166 #ifdef POLYSEGMENT
167         x1 = pSeg->x1 + xorg;
168         y1 = pSeg->y1 + yorg;
169         x2 = pSeg->x2 + xorg;
170         y2 = pSeg->y2 + yorg;
171         pSeg++;
172 #else
173         x1 = x2;
174         y1 = y2;
175         ++ppt;
176         if (mode == CoordModePrevious)
177         {
178             xorg = x1;
179             yorg = y1;
180         }
181         x2 = ppt->x + xorg;
182         y2 = ppt->y + yorg;
183 #endif
184
185         if (x1 == x2)  /* vertical line */
186         {
187             /* make the line go top to bottom of screen, keeping
188                endpoint semantics
189             */
190             if (y1 > y2)
191             {
192                 register int tmp;
193
194                 tmp = y2;
195                 y2 = y1 + 1;
196                 y1 = tmp + 1;
197 #ifdef POLYSEGMENT
198                 if (pGC->capStyle != CapNotLast)
199                     y1--;
200 #endif
201             }
202 #ifdef POLYSEGMENT
203             else if (pGC->capStyle != CapNotLast)
204                 y2++;
205 #endif
206             /* get to first band that might contain part of line */
207             while ((nbox) && (pbox->y2 <= y1))
208             {
209                 pbox++;
210                 nbox--;
211             }
212
213             if (nbox)
214             {
215                 /* stop when lower edge of box is beyond end of line */
216                 while((nbox) && (y2 >= pbox->y1))
217                 {
218                     if ((x1 >= pbox->x1) && (x1 < pbox->x2))
219                     {
220                         int y1t, y2t;
221                         /* this box has part of the line in it */
222                         y1t = max(y1, pbox->y1);
223                         y2t = min(y2, pbox->y2);
224                         if (y1t != y2t)
225                         {
226                             cfbVertS (alu, and, xor,
227                                       addrl, nlwidth, 
228                                       x1, y1t, y2t-y1t);
229                         }
230                     }
231                     nbox--;
232                     pbox++;
233                 }
234             }
235 #ifndef POLYSEGMENT
236             y2 = ppt->y + yorg;
237 #endif
238         }
239         else if (y1 == y2)  /* horizontal line */
240         {
241             /* force line from left to right, keeping
242                endpoint semantics
243             */
244             if (x1 > x2)
245             {
246                 register int tmp;
247
248                 tmp = x2;
249                 x2 = x1 + 1;
250                 x1 = tmp + 1;
251 #ifdef POLYSEGMENT
252                 if (pGC->capStyle != CapNotLast)
253                     x1--;
254 #endif
255             }
256 #ifdef POLYSEGMENT
257             else if (pGC->capStyle != CapNotLast)
258                 x2++;
259 #endif
260
261             /* find the correct band */
262             while( (nbox) && (pbox->y2 <= y1))
263             {
264                 pbox++;
265                 nbox--;
266             }
267
268             /* try to draw the line, if we haven't gone beyond it */
269             if ((nbox) && (pbox->y1 <= y1))
270             {
271                 /* when we leave this band, we're done */
272                 tmp = pbox->y1;
273                 while((nbox) && (pbox->y1 == tmp))
274                 {
275                     int x1t, x2t;
276
277                     if (pbox->x2 <= x1)
278                     {
279                         /* skip boxes until one might contain start point */
280                         nbox--;
281                         pbox++;
282                         continue;
283                     }
284
285                     /* stop if left of box is beyond right of line */
286                     if (pbox->x1 >= x2)
287                     {
288                         nbox = 0;
289                         break;
290                     }
291
292                     x1t = max(x1, pbox->x1);
293                     x2t = min(x2, pbox->x2);
294                     if (x1t != x2t)
295                     {
296                         cfbHorzS (alu, and, xor,
297                                   addrl, nlwidth, 
298                                   x1t, y1, x2t-x1t);
299                     }
300                     nbox--;
301                     pbox++;
302                 }
303             }
304 #ifndef POLYSEGMENT
305             x2 = ppt->x + xorg;
306 #endif
307         }
308         else    /* sloped line */
309         {
310             CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy,
311                            1, 1, octant);
312
313             if (adx > ady)
314             {
315                 axis = X_AXIS;
316                 e1 = ady << 1;
317                 e2 = e1 - (adx << 1);
318                 e = e1 - adx;
319             }
320             else
321             {
322                 axis = Y_AXIS;
323                 e1 = adx << 1;
324                 e2 = e1 - (ady << 1);
325                 e = e1 - ady;
326                 SetYMajorOctant(octant);
327             }
328
329             FIXUP_ERROR(e, octant, bias);
330
331             /* we have bresenham parameters and two points.
332                all we have to do now is clip and draw.
333             */
334
335             while(nbox--)
336             {
337                 oc1 = 0;
338                 oc2 = 0;
339                 OUTCODES(oc1, x1, y1, pbox);
340                 OUTCODES(oc2, x2, y2, pbox);
341                 if ((oc1 | oc2) == 0)
342                 {
343                     if (axis == X_AXIS)
344                         len = adx;
345                     else
346                         len = ady;
347 #ifdef POLYSEGMENT
348                     if (pGC->capStyle != CapNotLast)
349                         len++;
350 #endif
351                     cfbBresS (alu, and, xor,
352                           addrl, nlwidth,
353                           signdx, signdy, axis, x1, y1,
354                           e, e1, e2, len);
355                     break;
356                 }
357                 else if (oc1 & oc2)
358                 {
359                     pbox++;
360                 }
361                 else
362                 {
363                     int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2;
364                     int clip1 = 0, clip2 = 0;
365                     int clipdx, clipdy;
366                     int err;
367                     
368                     if (miZeroClipLine(pbox->x1, pbox->y1, pbox->x2-1,
369                                        pbox->y2-1,
370                                        &new_x1, &new_y1, &new_x2, &new_y2,
371                                        adx, ady, &clip1, &clip2,
372                                        octant, bias, oc1, oc2) == -1)
373                     {
374                         pbox++;
375                         continue;
376                     }
377
378                     if (axis == X_AXIS)
379                         len = abs(new_x2 - new_x1);
380                     else
381                         len = abs(new_y2 - new_y1);
382 #ifdef POLYSEGMENT
383                     if (clip2 != 0 || pGC->capStyle != CapNotLast)
384                         len++;
385 #else
386                     len += (clip2 != 0);
387 #endif
388                     if (len)
389                     {
390                         /* unwind bresenham error term to first point */
391                         if (clip1)
392                         {
393                             clipdx = abs(new_x1 - x1);
394                             clipdy = abs(new_y1 - y1);
395                             if (axis == X_AXIS)
396                                 err = e+((clipdy*e2) + ((clipdx-clipdy)*e1));
397                             else
398                                 err = e+((clipdx*e2) + ((clipdy-clipdx)*e1));
399                         }
400                         else
401                             err = e;
402                             cfbBresS(alu, and, xor,
403                                      addrl, nlwidth,
404                                      signdx, signdy, axis, new_x1, new_y1,
405                                      err, e1, e2, len);
406                     }
407                     pbox++;
408                 }
409             } /* while (nbox--) */
410         } /* sloped line */
411     } /* while (nline--) */
412
413 #ifndef POLYSEGMENT
414     /* paint the last point if the end style isn't CapNotLast.
415        (Assume that a projecting, butt, or round cap that is one
416         pixel wide is the same as the single pixel of the endpoint.)
417     */
418
419     if ((pGC->capStyle != CapNotLast) &&
420         ((ppt->x + xorg != pptInit->x + pDrawable->x) ||
421          (ppt->y + yorg != pptInit->y + pDrawable->y) ||
422          (ppt == pptInit + 1)))
423     {
424         nbox = nboxInit;
425         pbox = pboxInit;
426         while (nbox--)
427         {
428             if ((x2 >= pbox->x1) &&
429                 (y2 >= pbox->y1) &&
430                 (x2 <  pbox->x2) &&
431                 (y2 <  pbox->y2))
432             {
433                 unsigned long mask;
434                 unsigned long scrbits;
435
436 #if PSZ == 24
437                 mask = cfbmask[(x2 & 3)<<1];
438                 addrl += (y2 * nlwidth) + ((x2*3) >> 2);
439 #else
440                 mask = cfbmask[x2 & PIM];
441                 addrl += (y2 * nlwidth) + (x2 >> PWSH);
442 #endif
443                 scrbits = *addrl;
444                 *addrl = (scrbits & ~mask) |
445                          (DoRRop (scrbits, and, xor) & mask);
446                 break;
447             }
448             else
449                 pbox++;
450         }
451     }
452 #endif
453 }
454
455 /*
456  * Draw dashed 1-pixel lines.
457  */
458
459 void
460 #ifdef POLYSEGMENT
461 cfbSegmentSD (pDrawable, pGC, nseg, pSeg)
462     DrawablePtr pDrawable;
463     register GCPtr      pGC;
464     int         nseg;
465     register xSegment   *pSeg;
466 #else
467 cfbLineSD( pDrawable, pGC, mode, npt, pptInit)
468     DrawablePtr pDrawable;
469     register GCPtr pGC;
470     int mode;           /* Origin or Previous */
471     int npt;            /* number of points */
472     DDXPointPtr pptInit;
473 #endif
474 {
475     int nboxInit;
476     register int nbox;
477     BoxPtr pboxInit;
478     register BoxPtr pbox;
479 #ifndef POLYSEGMENT
480     register DDXPointPtr ppt;   /* pointer to list of translated points */
481 #endif
482
483     register unsigned int oc1;          /* outcode of point 1 */
484     register unsigned int oc2;          /* outcode of point 2 */
485
486     unsigned long *addrl;               /* address of destination pixmap */
487     int nlwidth;                /* width in longwords of destination pixmap */
488     int xorg, yorg;             /* origin of window */
489
490     int adx;            /* abs values of dx and dy */
491     int ady;
492     int signdx;         /* sign of dx and dy */
493     int signdy;
494     int e, e1, e2;              /* bresenham error and increments */
495     int len;                    /* length of segment */
496     int axis;                   /* major axis */
497     int octant;
498     unsigned int bias = miGetZeroLineBias(pDrawable->pScreen);
499     int x1, x2, y1, y2;
500     RegionPtr cclip;
501     cfbRRopRec      rrops[2];
502     unsigned char   *pDash;
503     int             dashOffset;
504     int             numInDashList;
505     int             dashIndex;
506     int             isDoubleDash;
507     int             dashIndexTmp, dashOffsetTmp;
508     int             unclippedlen;
509     cfbPrivGCPtr    devPriv;
510
511     devPriv = cfbGetGCPrivate(pGC);
512     cclip = devPriv->pCompositeClip;
513     rrops[0].rop = devPriv->rop;
514     rrops[0].and = devPriv->and;
515     rrops[0].xor = devPriv->xor;
516     if (pGC->alu == GXcopy)
517     {
518         rrops[1].rop = GXcopy;
519         rrops[1].and = 0;
520         rrops[1].xor = PFILL (pGC->bgPixel);
521     }
522     else
523     {
524         rrops[1].rop = cfbReduceRasterOp (pGC->alu,
525                                           pGC->bgPixel, pGC->planemask,
526                                           &rrops[1].and, &rrops[1].xor);
527     }
528     pboxInit = REGION_RECTS(cclip);
529     nboxInit = REGION_NUM_RECTS(cclip);
530
531     cfbGetLongWidthAndPointer (pDrawable, nlwidth, addrl)
532
533     /* compute initial dash values */
534      
535     pDash = (unsigned char *) pGC->dash;
536     numInDashList = pGC->numInDashList;
537     isDoubleDash = (pGC->lineStyle == LineDoubleDash);
538     dashIndex = 0;
539     dashOffset = 0;
540     miStepDash ((int)pGC->dashOffset, &dashIndex, pDash,
541                 numInDashList, &dashOffset);
542
543     xorg = pDrawable->x;
544     yorg = pDrawable->y;
545 #ifdef POLYSEGMENT
546     while (nseg--)
547 #else
548     ppt = pptInit;
549     x2 = ppt->x + xorg;
550     y2 = ppt->y + yorg;
551     while(--npt)
552 #endif
553     {
554         nbox = nboxInit;
555         pbox = pboxInit;
556
557 #ifdef POLYSEGMENT
558         x1 = pSeg->x1 + xorg;
559         y1 = pSeg->y1 + yorg;
560         x2 = pSeg->x2 + xorg;
561         y2 = pSeg->y2 + yorg;
562         pSeg++;
563 #else
564         x1 = x2;
565         y1 = y2;
566         ++ppt;
567         if (mode == CoordModePrevious)
568         {
569             xorg = x1;
570             yorg = y1;
571         }
572         x2 = ppt->x + xorg;
573         y2 = ppt->y + yorg;
574 #endif
575
576         CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy, 1, 1, octant);
577
578         if (adx > ady)
579         {
580             axis = X_AXIS;
581             e1 = ady << 1;
582             e2 = e1 - (adx << 1);
583             e = e1 - adx;
584             unclippedlen = adx;
585         }
586         else
587         {
588             axis = Y_AXIS;
589             e1 = adx << 1;
590             e2 = e1 - (ady << 1);
591             e = e1 - ady;
592             unclippedlen = ady;
593             SetYMajorOctant(octant);
594         }
595
596         FIXUP_ERROR(e, octant, bias);
597
598         /* we have bresenham parameters and two points.
599            all we have to do now is clip and draw.
600         */
601
602         while(nbox--)
603         {
604             oc1 = 0;
605             oc2 = 0;
606             OUTCODES(oc1, x1, y1, pbox);
607             OUTCODES(oc2, x2, y2, pbox);
608             if ((oc1 | oc2) == 0)
609             {
610 #ifdef POLYSEGMENT
611                 if (pGC->capStyle != CapNotLast)
612                     unclippedlen++;
613                 dashIndexTmp = dashIndex;
614                 dashOffsetTmp = dashOffset;
615                 cfbBresD (rrops,
616                       &dashIndexTmp, pDash, numInDashList,
617                       &dashOffsetTmp, isDoubleDash,
618                       addrl, nlwidth,
619                       signdx, signdy, axis, x1, y1,
620                       e, e1, e2, unclippedlen);
621                 break;
622 #else
623                 cfbBresD (rrops,
624                       &dashIndex, pDash, numInDashList,
625                       &dashOffset, isDoubleDash,
626                       addrl, nlwidth,
627                       signdx, signdy, axis, x1, y1,
628                       e, e1, e2, unclippedlen);
629                 goto dontStep;
630 #endif
631             }
632             else if (oc1 & oc2)
633             {
634                 pbox++;
635             }
636             else /* have to clip */
637             {
638                 int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2;
639                 int clip1 = 0, clip2 = 0;
640                 int clipdx, clipdy;
641                 int err;
642                 int dashIndexTmp, dashOffsetTmp;
643                 
644                 if (miZeroClipLine(pbox->x1, pbox->y1, pbox->x2-1,
645                                    pbox->y2-1,
646                                    &new_x1, &new_y1, &new_x2, &new_y2,
647                                    adx, ady, &clip1, &clip2,
648                                    octant, bias, oc1, oc2) == -1)
649                 {
650                     pbox++;
651                     continue;
652                 }
653
654                 dashIndexTmp = dashIndex;
655                 dashOffsetTmp = dashOffset;
656
657                 if (clip1)
658                 {
659                     int dlen;
660     
661                     if (axis == X_AXIS)
662                         dlen = abs(new_x1 - x1);
663                     else
664                         dlen = abs(new_y1 - y1);
665                     miStepDash (dlen, &dashIndexTmp, pDash,
666                                 numInDashList, &dashOffsetTmp);
667                 }
668                 
669                 if (axis == X_AXIS)
670                     len = abs(new_x2 - new_x1);
671                 else
672                     len = abs(new_y2 - new_y1);
673 #ifdef POLYSEGMENT
674                 if (clip2 != 0 || pGC->capStyle != CapNotLast)
675                     len++;
676 #else
677                 len += (clip2 != 0);
678 #endif
679                 if (len)
680                 {
681                     /* unwind bresenham error term to first point */
682                     if (clip1)
683                     {
684                         clipdx = abs(new_x1 - x1);
685                         clipdy = abs(new_y1 - y1);
686                         if (axis == X_AXIS)
687                             err = e+((clipdy*e2) + ((clipdx-clipdy)*e1));
688                         else
689                             err = e+((clipdx*e2) + ((clipdy-clipdx)*e1));
690                     }
691                     else
692                         err = e;
693                     cfbBresD (rrops,
694                               &dashIndexTmp, pDash, numInDashList,
695                               &dashOffsetTmp, isDoubleDash,
696                               addrl, nlwidth,
697                               signdx, signdy, axis, new_x1, new_y1,
698                               err, e1, e2, len);
699                 }
700                 pbox++;
701             }
702         } /* while (nbox--) */
703 #ifndef POLYSEGMENT
704         /*
705          * walk the dash list around to the next line
706          */
707         miStepDash (unclippedlen, &dashIndex, pDash,
708                     numInDashList, &dashOffset);
709 dontStep:       ;
710 #endif
711     } /* while (nline--) */
712
713 #ifndef POLYSEGMENT
714     /* paint the last point if the end style isn't CapNotLast.
715        (Assume that a projecting, butt, or round cap that is one
716         pixel wide is the same as the single pixel of the endpoint.)
717     */
718
719     if ((pGC->capStyle != CapNotLast) &&
720         ((dashIndex & 1) == 0 || isDoubleDash) &&
721         ((ppt->x + xorg != pptInit->x + pDrawable->x) ||
722          (ppt->y + yorg != pptInit->y + pDrawable->y) ||
723          (ppt == pptInit + 1)))
724     {
725         nbox = nboxInit;
726         pbox = pboxInit;
727         while (nbox--)
728         {
729             if ((x2 >= pbox->x1) &&
730                 (y2 >= pbox->y1) &&
731                 (x2 <  pbox->x2) &&
732                 (y2 <  pbox->y2))
733             {
734                 unsigned long   mask;
735                 int             pix;
736
737                 pix = 0;
738                 if (dashIndex & 1)
739                     pix = 1;
740 #if PSZ == 24
741                 mask = cfbmask[(x2 & 3)<<1];
742                 addrl += (y2 * nlwidth) + ((x2 *3)>> 2);
743 #else
744                 mask = cfbmask[x2 & PIM];
745                 addrl += (y2 * nlwidth) + (x2 >> PWSH);
746 #endif
747                 *addrl = DoMaskRRop (*addrl, rrops[pix].and, rrops[pix].xor, mask);
748                 break;
749             }
750             else
751                 pbox++;
752         }
753     }
754 #endif
755 }