1 /* This file is part of the GNU libxmi package.
2
3 Copyright (C) 1985, 1986, 1987, 1988, 1989, X Consortium. For an
4 associated permission notice, see the accompanying file README-X.
5
6 GNU enhancements Copyright (C) 1998, 1999, 2000, 2005, Free Software
7 Foundation, Inc.
8
9 The GNU libxmi package is free software. You may redistribute it
10 and/or modify it under the terms of the GNU General Public License as
11 published by the Free Software foundation; either version 2, or (at your
12 option) any later version.
13
14 The GNU libxmi package is distributed in the hope that it will be
15 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
18
19 You should have received a copy of the GNU General Public License along
20 with the GNU plotutils package; see the file COPYING. If not, write to
21 the Free Software Foundation, Inc., 51 Franklin St., Fifth Floor,
22 Boston, MA 02110-1301, USA. */
23
24 /* This module contains the miZeroLine() and miZeroDash() functions. They
25 a rasterize single-pixel (i.e., `zero-width') Bresenham polyline, either
26 solid or dashed.
27
28 The cap mode and join mode in the graphics context are ignored, except
29 that if the cap mode is MI_CAP_NOT_LAST, the final pixel of the polyline
30 is omitted.
31
32 All painting goes through the low-level MI_PAINT_SPANS() and
33 MI_COPY_AND_PAINT_SPANS() macros. */
34
35 /* Historical note: this is a merger of MI code from X11, written by Ken
36 Whaley, with low-level X11 CFB (color frame-buffer) code, of unknown
37 authorship. (I wrote Ken, and he remembers writing the monochrome frame
38 buffer code, but not the color code.) That's because the X11 MI code
39 included miZeroLine(), but not miZeroDash(). I based the latter on the
40 CFB routines. I needed to hack them extensively so that they would
41 generate a list of spans to paint. I also removed clipping code. --rsm */
42
43 #include "sys-defines.h"
44 #include "extern.h"
45
46 #include "xmi.h"
47 #include "mi_spans.h"
48 #include "mi_gc.h"
49 #include "mi_api.h"
50 #include "mi_line.h"
51
52 /* Comment on drawing solid lines (from Ken Whaley):
53
54 NON-SLOPED LINES
55
56 Horizontal lines are always drawn left to right; we have to move the
57 endpoints right by one after they're swapped. Vertical lines are always
58 drawn top to bottom (y-increasing). This requires adding one to the
59 y-coordinate of each endpoint after swapping. */
60
61 /* forward references */
62 static void cfbBresD (miPaintedSet *paintedSet, const miGC *pGC, int *pdashNum, int *pdashIndex, const unsigned int *pDash, int numInDashList, int *pdashOffset, bool isDoubleDash, int signdx, int signdy, int axis, int x1, int y1, int e, int e1, int e2, int len);
63 static void cfbBresS (miPaintedSet *paintedSet, const miGC *pGC, int signdx, int signdy, int axis, int x1, int y1, int e, int e1, int e2, int len);
64 static void cfbHorzS (miPaintedSet *paintedSet, const miGC *pGC, int x1, int y1, int len);
65 static void cfbVertS (miPaintedSet *paintedSet, const miGC *pGC, int x1, int y1, int len);
66
67
68 /* Macro for painting a single point. Used for ending line segments. */
69
70 #define MI_PAINT_POINT(paintedSet, pixel, xx, yy) \
71 {\
72 miPoint *point;\
73 unsigned int *width;\
74 point = (miPoint *)mi_xmalloc(sizeof(miPoint));\
75 width = (unsigned int *)mi_xmalloc(sizeof(unsigned int));\
76 *width = 1;\
77 point->x = xx;\
78 point->y = yy;\
79 MI_PAINT_SPANS(paintedSet, pixel, 1, point, width)\
80 }
81
82 /* Macro for generating a list of spans, used when the successive points on
83 a Bresenham line are generated. Assumes the availability of working
84 storage, accessed via pointers `ppt' and `pwidths', and also variables
85 numSpans (initted to 0), firstspan (initted to true), and ycurr. The
86 arrays should be at least as large as the longest generated Bresenham
87 line segment. */
88
89 #define MI_ADD_POINT(xx, yy, ppt, pwidth, numSpans, ycurr, firstspan, signdy) \
90 {\
91 if (!firstspan && yy == ycurr)\
92 {\
93 int xdelta = xx - ppt->x;\
94 if (xdelta < 0)\
95 {\
96 (*pwidth) -= xdelta;\
97 ppt->x = xx;\
98 }\
99 else if (xdelta > 0)\
100 { \
101 unsigned int widthcurr = *pwidth; \
102 (*pwidth) = UMAX(widthcurr, (unsigned int)(1 + xdelta));\
103 } \
104 }\
105 else\
106 {\
107 if (!firstspan)\
108 {\
109 ppt += signdy;\
110 pwidth += signdy;\
111 }\
112 else\
113 firstspan = false;\
114 ppt->x = xx;\
115 ppt->y = yy;\
116 *pwidth = 1;\
117 ycurr = yy;\
118 ++numSpans;\
119 }\
120 }
121
122 /*
123 * Draw a solid Bresenham polyline, i.e. a `zero-width' solid polyline,
124 * in paint type #1.
125 */
126
127 /* ARGS: mode = Origin or Previous
128 npt = number of points
129 pPts = point array */
130 void
miZeroLine(miPaintedSet * paintedSet,const miGC * pGC,miCoordMode mode,int npt,const miPoint * pPts)131 miZeroLine (miPaintedSet *paintedSet, const miGC *pGC, miCoordMode mode, int npt, const miPoint *pPts)
132 {
133 const miPoint *ppt; /* pointer to point within array */
134 /* temporaries */
135 int xstart, ystart;
136 int x1, x2;
137 int y1, y2;
138
139 /* ensure we have >=1 points */
140 if (npt <= 0)
141 return;
142
143 /* loop through points, drawing a solid Bresenham segment for each line
144 segment */
145 ppt = pPts;
146 xstart = ppt->x;
147 ystart = ppt->y;
148 x2 = xstart;
149 y2 = ystart;
150 while (--npt)
151 {
152 x1 = x2;
153 y1 = y2;
154 ++ppt;
155
156 x2 = ppt->x;
157 y2 = ppt->y;
158 if (mode == MI_COORD_MODE_PREVIOUS)
159 /* convert from relative coordinates */
160 {
161 x2 += x1;
162 y2 += y1;
163 }
164
165 if (x1 == x2) /* vertical line */
166 {
167 if (y1 > y2)
168 /* make line go top to bottom, keeping endpoint semantics */
169 {
170 int tmp;
171
172 tmp = y2;
173 y2 = y1 + 1;
174 y1 = tmp + 1;
175 }
176
177 /* draw line */
178 if (y1 != y2)
179 cfbVertS (paintedSet, pGC, x1, y1, y2 - y1);
180
181 /* restore final point */
182 y2 = ppt->y;
183 }
184
185 else if (y1 == y2) /* horizontal line */
186 {
187 if (x1 > x2)
188 /* force line from left to right, keeping endpoint semantics */
189 {
190 int tmp;
191
192 tmp = x2;
193 x2 = x1 + 1;
194 x1 = tmp + 1;
195 }
196
197 /* draw line */
198 if (x1 != x2)
199 cfbHorzS (paintedSet, pGC, x1, y1, x2 - x1);
200 /* restore final point */
201 x2 = ppt->x;
202 }
203
204 else /* sloped line */
205 {
206 int adx; /* abs values of dx and dy */
207 int ady;
208 int signdx; /* sign of dx and dy */
209 int signdy;
210 int e, e1, e2; /* Bresenham error and increments */
211 int axis; /* major axis */
212 int len; /* length of segment */
213
214 AbsDeltaAndSign(x2, x1, adx, signdx);
215 AbsDeltaAndSign(y2, y1, ady, signdy);
216 if (adx > ady)
217 {
218 axis = X_AXIS;
219 e1 = ady << 1;
220 e2 = e1 - (adx << 1);
221 e = e1 - adx;
222 FIXUP_X_MAJOR_ERROR(e, signdx, signdy);
223 }
224 else
225 {
226 axis = Y_AXIS;
227 e1 = adx << 1;
228 e2 = e1 - (ady << 1);
229 e = e1 - ady;
230 FIXUP_Y_MAJOR_ERROR(e, signdx, signdy);
231 }
232
233 /* we have Bresenham parameters and two points, so all we need to
234 do now is draw */
235 if (axis == X_AXIS)
236 len = adx;
237 else
238 len = ady;
239 cfbBresS (paintedSet, pGC,
240 signdx, signdy, axis, x1, y1,
241 e, e1, e2, len);
242 } /* sloped line */
243 } /* while (--npt) */
244
245 /* Paint the last point if the end style isn't CapNotLast. (I.e. assume
246 that a round/butt/projecting/triangular cap that is one pixel wide is
247 the same as the single pixel of the endpoint.) */
248 if (pGC->capStyle != (int)MI_CAP_NOT_LAST
249 &&
250 (xstart != x2 || ystart != y2 || ppt == pPts + 1))
251 MI_PAINT_POINT(paintedSet, pGC->pixels[1], x2, y2)
252 }
253
254
255 /*
256 * Draw a dashed Bresenham polyline, i.e. a `zero-width' dashed polyline.
257 */
258
259 /* ARGS: mode = Origin or Previous
260 npt = number of points
261 pPts = point array */
262 void
miZeroDash(miPaintedSet * paintedSet,const miGC * pGC,miCoordMode mode,int npt,const miPoint * pPts)263 miZeroDash (miPaintedSet *paintedSet, const miGC *pGC, miCoordMode mode, int npt, const miPoint *pPts)
264 {
265 const miPoint *ppt; /* pointer to current point */
266 /* temporaries */
267 int xstart, ystart;
268 int x1, x2, y1, y2;
269
270 const unsigned int *pDash;
271 int dashNum, dashIndex;
272 int dashOffset;
273 int numInDashList;
274 bool isDoubleDash;
275
276 /* ensure we have >=1 points */
277 if (npt <= 0)
278 return;
279
280 /* perform initial offsetting into the dash array; compute dash values */
281 pDash = pGC->dash;
282 numInDashList = pGC->numInDashList;
283 isDoubleDash = (pGC->lineStyle == (int)MI_LINE_DOUBLE_DASH ? true : false);
284 dashNum = 0;
285 dashIndex = 0;
286 dashOffset = 0;
287 miStepDash (pGC->dashOffset, &dashNum, &dashIndex,
288 pDash, numInDashList, &dashOffset);
289
290 /* loop through points, drawing a dashed Bresenham segment for each line
291 segment of nonzero length */
292 ppt = pPts;
293 xstart = ppt->x;
294 ystart = ppt->y;
295 x2 = xstart;
296 y2 = ystart;
297 while (--npt)
298 {
299 x1 = x2;
300 y1 = y2;
301 ++ppt;
302
303 x2 = ppt->x;
304 y2 = ppt->y;
305 if (mode == MI_COORD_MODE_PREVIOUS)
306 /* convert from relative coordinates */
307 {
308 x2 += x1;
309 y2 += y1;
310 }
311
312 /* use Bresenham algorithm for sloped lines (no special treatment for
313 horizontal or vertical lines, unlike the undashed case) */
314 {
315 int adx; /* abs values of dx and dy */
316 int ady;
317 int signdx; /* sign of dx and dy */
318 int signdy;
319 int e, e1, e2; /* Bresenham error and increments */
320 int axis; /* major axis */
321 int len;
322
323 AbsDeltaAndSign(x2, x1, adx, signdx);
324 AbsDeltaAndSign(y2, y1, ady, signdy);
325 if (adx > ady)
326 {
327 axis = X_AXIS;
328 e1 = ady << 1;
329 e2 = e1 - (adx << 1);
330 e = e1 - adx;
331 len = adx;
332 FIXUP_X_MAJOR_ERROR(e, signdx, signdy);
333 }
334 else
335 {
336 axis = Y_AXIS;
337 e1 = adx << 1;
338 e2 = e1 - (ady << 1);
339 e = e1 - ady;
340 len = ady;
341 FIXUP_Y_MAJOR_ERROR(e, signdx, signdy);
342 }
343
344 /* we have Bresenham parameters and two points, so all we need to
345 do now is draw (updating dashNum, dashIndex and dashOffset) */
346 cfbBresD (paintedSet, pGC,
347 &dashNum, &dashIndex, pDash, numInDashList,
348 &dashOffset, isDoubleDash,
349 signdx, signdy, axis, x1, y1,
350 e, e1, e2, len);
351 }
352 } /* while (nline--) */
353
354 /* paint the last point if the end style isn't CapNotLast.
355 (Assume that a projecting, butt, or round cap that is one
356 pixel wide is the same as the single pixel of the endpoint.) */
357 if (pGC->capStyle != (int)MI_CAP_NOT_LAST
358 &&
359 (xstart != x2 || ystart != y2 || ppt == pPts + 1))
360 {
361 if (dashNum & 1)
362 {
363 /* background dash */
364 if (isDoubleDash)
365 /* paint, in paint type #0 */
366 MI_PAINT_POINT(paintedSet, pGC->pixels[0], x2, y2);
367 }
368 else
369 /* foreground dash */
370 {
371 /* use a paint type that cycles through 1..(numPixels-1) */
372 int numPixels = pGC->numPixels;
373 int paintType = 1 + ((dashNum / 2) % (numPixels - 1));
374
375 MI_PAINT_POINT(paintedSet, pGC->pixels[paintType], x2, y2);
376 }
377 }
378 }
379
380
381 /* Internal: draw solid Bresenham line segment, in paint type #1. Called
382 by miZeroLine(). Endpoint semantics are used, i.e. we paint only len
383 pixels (i.e. |dx| or |dy| pixels), not including the endpoint. */
384
385 /* ARGS: signdx,signdy = signs of directions
386 axis = major axis (Y_AXIS or X_AXIS)
387 x1,y1 = initial point
388 e = error accumulator
389 e1,e2 = Bresenham increments
390 len = length of line in pixels */
391 static void
cfbBresS(miPaintedSet * paintedSet,const miGC * pGC,int signdx,int signdy,int axis,int x1,int y1,int e,int e1,int e2,int len)392 cfbBresS (miPaintedSet *paintedSet, const miGC *pGC, int signdx, int signdy, int axis, int x1, int y1, int e, int e1, int e2, int len)
393 {
394 miPoint *pptInit, *pptLast;
395 unsigned int *pwidthInit, *pwidthLast;
396 int x, y;
397 int e3;
398
399 /* variables in span generation code, i.e. in MI_ADD_POINT() */
400 int numSpans;
401 int ycurr;
402 miPoint *ppt;
403 unsigned int *pwidth;
404 bool firstspan;
405
406 if (len == 0)
407 return;
408
409 /* set up work arrays */
410 pptInit = (miPoint *)mi_xmalloc(len * sizeof(miPoint));
411 pwidthInit = (unsigned int *)mi_xmalloc(len * sizeof(unsigned int));
412 pptLast = pptInit + (len - 1);
413 pwidthLast = pwidthInit + (len - 1);
414
415 /* reset variables used in MI_ADD_POINT() */
416 numSpans = 0;
417 ycurr = 0;
418 firstspan = true;
419 if (signdy >= 0)
420 {
421 ppt = pptInit;
422 pwidth = pwidthInit;
423 }
424 else
425 {
426 ppt = pptLast;
427 pwidth = pwidthLast;
428 }
429
430 e3 = e2 - e1;
431 e = e - e1; /* make looping easier */
432
433 #define BresStep(minor,major) \
434 {if ((e += e1) >= 0) { e += e3; minor; } major;}
435
436 #define Loop_x(counter,store) while (counter--) \
437 {store; BresStep(y+=signdy,x+=signdx) }
438 #define Loop_y(counter,store) while (counter--) \
439 {store; BresStep(x+=signdx, y+=signdy) }
440
441 /* point to first point, and generate len pixels */
442 x = x1;
443 y = y1;
444
445 switch (axis)
446 {
447 case X_AXIS:
448 default:
449 Loop_x(len, MI_ADD_POINT(x, y, ppt, pwidth, numSpans, ycurr, firstspan, signdy))
450 break;
451 case Y_AXIS:
452 Loop_y(len, MI_ADD_POINT(x, y, ppt, pwidth, numSpans, ycurr, firstspan, signdy))
453 break;
454 }
455
456 if (numSpans > 0)
457 {
458 if (signdy < 0)
459 /* spans are offset, so shift downward */
460 {
461 miPoint *ppt_src = pptLast - (numSpans - 1);
462 miPoint *ppt_dst = pptInit;
463 unsigned int *pwidth_src = pwidthLast - (numSpans - 1);
464 unsigned int *pwidth_dst = pwidthInit;
465 int count = numSpans;
466
467 while (count--)
468 {
469 *ppt_dst++ = *ppt_src++;
470 *pwidth_dst++ = *pwidth_src++;
471 }
472 }
473
474 MI_PAINT_SPANS(paintedSet, pGC->pixels[1], numSpans, pptInit, pwidthInit)
475 }
476 }
477
478 /* Internal: draw dashed Bresenham line segment. Called by miZeroDash().
479 Endpoint semantics are used. */
480
481 /* ARGS: pdashNum = absolute dash number
482 pdashIndx = index into dash array
483 pDash = dash array
484 numInDashList = length of dash array
485 pdashOffset = offset into current dash
486 signdx,signdy = signs of directions
487 axis = major axis (Y_AXIS or X_AXIS)
488 x1,y1 = initial point
489 e = error accumulator
490 e1,e2 = Bresenham increments
491 len = length of line in pixels */
492 static void
cfbBresD(miPaintedSet * paintedSet,const miGC * pGC,int * pdashNum,int * pdashIndex,const unsigned int * pDash,int numInDashList,int * pdashOffset,bool isDoubleDash,int signdx,int signdy,int axis,int x1,int y1,int e,int e1,int e2,int len)493 cfbBresD (miPaintedSet *paintedSet, const miGC *pGC, int *pdashNum, int *pdashIndex, const unsigned int *pDash, int numInDashList, int *pdashOffset, bool isDoubleDash, int signdx, int signdy, int axis, int x1, int y1, int e, int e1, int e2, int len)
494 {
495 miPoint *pptInit_fg, *pptInit_bg = (miPoint *)NULL;
496 miPoint *pptLast_fg, *pptLast_bg = (miPoint *)NULL;
497 unsigned int *pwidthInit_fg, *pwidthInit_bg = (unsigned int *)NULL;
498 unsigned int *pwidthLast_fg, *pwidthLast_bg = (unsigned int *)NULL;
499 int x, y;
500 int e3;
501 int dashNum, dashIndex;
502 int dashOffset;
503 int dashRemaining;
504 int thisDash;
505
506 /* variables in span generation code, i.e. in MI_ADD_POINT() */
507 int numSpans_fg, numSpans_bg = 0;
508 int ycurr_fg, ycurr_bg = 0;
509 miPoint *ppt_fg, *ppt_bg = (miPoint *)NULL;
510 unsigned int *pwidth_fg, *pwidth_bg = (unsigned int *)NULL;
511 bool firstspan_fg, firstspan_bg = false;
512
513 /* set up work arrays */
514 pptInit_fg = (miPoint *)mi_xmalloc(len * sizeof(miPoint));
515 pwidthInit_fg = (unsigned int *)mi_xmalloc(len * sizeof(unsigned int));
516 pptLast_fg = pptInit_fg + (len - 1);
517 pwidthLast_fg = pwidthInit_fg + (len - 1);
518 if (isDoubleDash)
519 {
520 pptInit_bg = (miPoint *)mi_xmalloc(len * sizeof(miPoint));
521 pwidthInit_bg = (unsigned int *)mi_xmalloc(len * sizeof(unsigned int));
522 pptLast_bg = pptInit_bg + (len - 1);
523 pwidthLast_bg = pwidthInit_bg + (len - 1);
524 }
525
526 dashNum = *pdashNum; /* absolute number of current dash */
527 dashIndex = *pdashIndex; /* index of current dash */
528 dashOffset = *pdashOffset; /* offset into current dash */
529 dashRemaining = (int)(pDash[dashIndex]) - dashOffset; /* how much is left */
530 if (len <= (thisDash = dashRemaining))
531 /* line segment will be solid, not dashed */
532 {
533 thisDash = len;
534 dashRemaining -= len;
535 }
536
537 #define NextDash {\
538 dashNum++; \
539 dashIndex++; \
540 if (dashIndex == numInDashList) \
541 dashIndex = 0; \
542 dashRemaining = (int)(pDash[dashIndex]); \
543 if ((thisDash = dashRemaining) >= len) \
544 { \
545 dashRemaining -= len; \
546 thisDash = len; \
547 } \
548 }
549
550 e3 = e2-e1;
551 e = e - e1; /* make looping easier */
552
553 /* point to first point */
554 x = x1;
555 y = y1;
556
557 /* loop, generating dashes (in the absence of dashing, would
558 generate len pixels in all) */
559 for ( ; ; )
560 {
561 len -= thisDash;
562
563 /* reset variables used in MI_ADD_POINT() */
564 numSpans_fg = 0;
565 ycurr_fg = 0;
566 firstspan_fg = true;
567 if (signdy >= 0)
568 {
569 ppt_fg = pptInit_fg;
570 pwidth_fg = pwidthInit_fg;
571 }
572 else
573 {
574 ppt_fg = pptLast_fg;
575 pwidth_fg = pwidthLast_fg;
576 }
577 if (isDoubleDash)
578 {
579 numSpans_bg = 0;
580 ycurr_bg = 0;
581 firstspan_bg = true;
582 ppt_bg = pptInit_bg;
583 pwidth_bg = pwidthInit_bg;
584 if (signdy >= 0)
585 {
586 ppt_bg = pptInit_bg;
587 pwidth_bg = pwidthInit_bg;
588 }
589 else
590 {
591 ppt_bg = pptLast_bg;
592 pwidth_bg = pwidthLast_bg;
593 }
594 }
595
596 switch (axis)
597 {
598 case X_AXIS:
599 default:
600 if (dashIndex & 1)
601 {
602 if (isDoubleDash)
603 {
604 /* create background dash */
605 Loop_x(thisDash, MI_ADD_POINT(x, y, ppt_bg, pwidth_bg, numSpans_bg, ycurr_bg, firstspan_bg, signdy))
606 }
607 else
608 /* not double dashing; no background dash */
609 Loop_x(thisDash, ;);
610 }
611 else
612 /* create foreground dash */
613 Loop_x(thisDash, MI_ADD_POINT(x, y, ppt_fg, pwidth_fg, numSpans_fg, ycurr_fg, firstspan_fg, signdy))
614 break;
615 case Y_AXIS:
616 if (dashIndex & 1)
617 {
618 if (isDoubleDash)
619 {
620 /* create background dash */
621 Loop_y(thisDash, MI_ADD_POINT(x, y, ppt_bg, pwidth_bg, numSpans_bg, ycurr_bg, firstspan_bg, signdy))
622 }
623 else
624 /* not double dashing; no background dash */
625 Loop_y(thisDash, ;);
626 }
627 else
628 /* create foreground dash */
629 Loop_y(thisDash, MI_ADD_POINT(x, y, ppt_fg, pwidth_fg, numSpans_fg, ycurr_fg, firstspan_fg, signdy))
630 break;
631 } /* end switch */
632
633 if (numSpans_fg > 0)
634 /* have a foreground dash to paint */
635 {
636 miPoint *pptStart_fg;
637 unsigned int *pwidthStart_fg;
638
639 if (signdy >= 0)
640 {
641 pptStart_fg = pptInit_fg;
642 pwidthStart_fg = pwidthInit_fg;
643 }
644 else
645 {
646 pptStart_fg = pptLast_fg - (numSpans_fg - 1);
647 pwidthStart_fg = pwidthLast_fg - (numSpans_fg - 1);
648 }
649 /* for foreground dash, use a paint type that cycles through
650 1..(numPixels-1) */
651 {
652 int numPixels = pGC->numPixels;
653 int paintType = 1 + ((dashNum / 2) % (numPixels - 1));
654
655 MI_COPY_AND_PAINT_SPANS(paintedSet, pGC->pixels[paintType], numSpans_fg, pptStart_fg, pwidthStart_fg)
656 }
657 }
658
659 if (isDoubleDash && numSpans_bg > 0)
660 /* have a background dash to paint */
661 {
662 miPoint *pptStart_bg;
663 unsigned int *pwidthStart_bg;
664
665 if (signdy >= 0)
666 {
667 pptStart_bg = pptInit_bg;
668 pwidthStart_bg = pwidthInit_bg;
669 }
670 else
671 {
672 pptStart_bg = pptLast_bg - (numSpans_bg - 1);
673 pwidthStart_bg = pwidthLast_bg - (numSpans_bg - 1);
674 }
675 /* for background dash, use paint type #0 */
676 MI_COPY_AND_PAINT_SPANS(paintedSet, pGC->pixels[0], numSpans_bg, pptStart_bg, pwidthStart_bg)
677 }
678
679 if (len == 0)
680 break; /* break out of dash-generating loop */
681
682 NextDash /* update dashNum, dashIndex, thisDash, dashRemaining */
683
684 } /* end infinite dash-generating loop */
685
686 *pdashNum = dashNum;
687 *pdashIndex = dashIndex;
688 *pdashOffset = (int)(pDash[dashIndex]) - dashRemaining;
689
690 free (pwidthInit_fg);
691 free (pptInit_fg);
692 if (isDoubleDash)
693 {
694 free (pwidthInit_bg);
695 free (pptInit_bg);
696 }
697 }
698
699 /* Internal: draw horizontal zero-width solid line segment, in paint type #1.
700 Called by miZeroLine().
701 Called with len >= 1, and len=x2-x1. Endpoint semantics
702 are used, so we paint only len pixels, i.e. x1..x2-1. */
703
704 /* ARGS: x1,y1 = initial point, len = length of line */
705 static void
cfbHorzS(miPaintedSet * paintedSet,const miGC * pGC,int x1,int y1,int len)706 cfbHorzS (miPaintedSet *paintedSet, const miGC *pGC, int x1, int y1, int len)
707 {
708 miPoint *ppt;
709 unsigned int *pwidth;
710
711 ppt = (miPoint *)mi_xmalloc(sizeof(miPoint));
712 pwidth = (unsigned int *)mi_xmalloc(sizeof(unsigned int));
713
714 ppt->x = x1;
715 ppt->y = y1;
716 *pwidth = (unsigned int)len;
717
718 MI_PAINT_SPANS(paintedSet, pGC->pixels[1], 1, ppt, pwidth)
719 }
720
721 /* Internal: draw vertical zero-width solid line segment, in paint type #1.
722 Called by miZeroLine().
723 Called with len >= 1, and len=y2-y1. Endpoint semantics
724 are used, so we paint only len pixels, i.e. y1..y2-1. */
725
726 /* ARGS: x1,y1 = initial point, len = length of line */
727 static void
cfbVertS(miPaintedSet * paintedSet,const miGC * pGC,int x1,int y1,int len)728 cfbVertS (miPaintedSet *paintedSet, const miGC *pGC, int x1, int y1, int len)
729 {
730 miPoint *ppt, *pptInit;
731 unsigned int *pwidth, *pwidthInit;
732 int i;
733
734 ppt = pptInit = (miPoint *)mi_xmalloc(len * sizeof(miPoint));
735 pwidth = pwidthInit = (unsigned int *)mi_xmalloc(len * sizeof(unsigned int));
736
737 for (i = 0; i < len; i++)
738 {
739 ppt->x = x1;
740 ppt->y = y1 + i;
741 ppt++;
742 *pwidth++ = (unsigned int)1;
743 }
744
745 MI_PAINT_SPANS(paintedSet, pGC->pixels[1], len, pptInit, pwidthInit)
746 }
747