1
/* $Xorg: miwideline.c,v 1.4 2001/02/09 02:05:22 xorgcvs Exp $ */
4
Copyright 1988, 1998 The Open Group
6
Permission to use, copy, modify, distribute, and sell this software and its
7
documentation for any purpose is hereby granted without fee, provided that
8
the above copyright notice appear in all copies and that both that
9
copyright notice and this permission notice appear in supporting
12
The above copyright notice and this permission notice shall be included
13
in all copies or substantial portions of the Software.
15
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
19
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21
OTHER DEALINGS IN THE SOFTWARE.
23
Except as contained in this notice, the name of The Open Group shall
24
not be used in advertising or otherwise to promote the sale, use or
25
other dealings in this Software without prior written authorization
29
/* $XFree86: xc/programs/Xserver/mi/miwideline.c,v 1.12 2001/12/14 20:00:28 dawes Exp $ */
31
/* Author: Keith Packard, MIT X Consortium */
34
* Mostly integer wideline code. Uses a technique similar to
35
* bresenham zero-width lines, except walks an X edge
38
#ifdef HAVE_DIX_CONFIG_H
39
#include <dix-config.h>
46
#define _XOPEN_SOURCE /* to get prototype for hypot on some systems */
51
#include "windowstr.h"
53
#include "regionstr.h"
54
#include "miwideline.h"
61
static void miLineArc(DrawablePtr pDraw, register GCPtr pGC,
62
unsigned long pixel, SpanDataPtr spanData,
63
register LineFacePtr leftFace,
64
register LineFacePtr rightFace,
65
double xorg, double yorg, Bool isInt);
69
* spans-based polygon filler
73
miFillPolyHelper (pDrawable, pGC, pixel, spanData, y, overall_height,
74
left, right, left_count, right_count)
75
DrawablePtr pDrawable;
79
int y; /* start y coordinate */
80
int overall_height; /* height of entire segment */
81
PolyEdgePtr left, right;
82
int left_count, right_count;
84
register int left_x = 0, left_e = 0;
87
int left_dy = 0, left_dx = 0;
89
register int right_x = 0, right_e = 0;
92
int right_dy = 0, right_dx = 0;
95
int left_height = 0, right_height = 0;
97
register DDXPointPtr ppt;
98
DDXPointPtr pptInit = NULL;
100
int *pwidthInit = NULL;
110
pptInit = (DDXPointPtr) ALLOCATE_LOCAL (overall_height * sizeof(*ppt));
113
pwidthInit = (int *) ALLOCATE_LOCAL (overall_height * sizeof(*pwidth));
116
DEALLOCATE_LOCAL (pptInit);
121
oldPixel = pGC->fgPixel;
122
if (pixel != oldPixel)
124
DoChangeGC (pGC, GCForeground, (XID *)&pixel, FALSE);
125
ValidateGC (pDrawable, pGC);
130
spanRec.points = (DDXPointPtr) xalloc (overall_height * sizeof (*ppt));
133
spanRec.widths = (int *) xalloc (overall_height * sizeof (int));
136
xfree (spanRec.points);
139
ppt = spanRec.points;
140
pwidth = spanRec.widths;
144
if (pGC->miTranslate)
149
while ((left_count || left_height) &&
150
(right_count || right_height))
155
height = left_height;
156
if (height > right_height)
157
height = right_height;
159
left_height -= height;
160
right_height -= height;
162
while (--height >= 0)
164
if (right_x >= left_x)
167
ppt->x = left_x + xorg;
169
*pwidth++ = right_x - left_x + 1;
180
(*pGC->ops->FillSpans) (pDrawable, pGC, ppt - pptInit, pptInit, pwidthInit, TRUE);
181
DEALLOCATE_LOCAL (pwidthInit);
182
DEALLOCATE_LOCAL (pptInit);
183
if (pixel != oldPixel)
185
DoChangeGC (pGC, GCForeground, &oldPixel, FALSE);
186
ValidateGC (pDrawable, pGC);
191
spanRec.count = ppt - spanRec.points;
192
AppendSpanGroup (pGC, pixel, &spanRec, spanData)
197
miFillRectPolyHelper (
198
DrawablePtr pDrawable,
201
SpanDataPtr spanData,
207
register DDXPointPtr ppt;
208
register int *pwidth;
219
oldPixel = pGC->fgPixel;
220
if (pixel != oldPixel)
222
DoChangeGC (pGC, GCForeground, (XID *)&pixel, FALSE);
223
ValidateGC (pDrawable, pGC);
225
(*pGC->ops->PolyFillRect) (pDrawable, pGC, 1, &rect);
226
if (pixel != oldPixel)
228
DoChangeGC (pGC, GCForeground, &oldPixel, FALSE);
229
ValidateGC (pDrawable, pGC);
234
spanRec.points = (DDXPointPtr) xalloc (h * sizeof (*ppt));
237
spanRec.widths = (int *) xalloc (h * sizeof (int));
240
xfree (spanRec.points);
243
ppt = spanRec.points;
244
pwidth = spanRec.widths;
246
if (pGC->miTranslate)
259
spanRec.count = ppt - spanRec.points;
260
AppendSpanGroup (pGC, pixel, &spanRec, spanData)
265
miPolyBuildEdge (x0, y0, k, dx, dy, xi, yi, left, edge)
267
double k; /* x0 * dy - y0 * dx */
271
register PolyEdgePtr edge;
285
double realk, kerror;
286
realk = x0 * dy - y0 * dx;
287
kerror = Fabs (realk - k);
289
printf ("realk: %g k: %g\n", realk, k);
293
xady = ICEIL (k) + y * dx;
296
x = - (-xady / dy) - 1;
305
edge->stepx = dx / dy;
311
edge->stepx = - (-dx / dy);
316
edge->x = x + left + xi;
317
edge->e = e - dy; /* bias to compare against 0 instead of dy */
321
#define StepAround(v, incr, max) (((v) + (incr) < 0) ? (max - 1) : ((v) + (incr) == max) ? 0 : ((v) + (incr)))
324
miPolyBuildPoly (vertices, slopes, count, xi, yi, left, right, pnleft, pnright, h)
325
register PolyVertexPtr vertices;
326
register PolySlopePtr slopes;
329
PolyEdgePtr left, right;
330
int *pnleft, *pnright;
340
register int nright, nleft;
341
int y, lasty = 0, bottomy, topy = 0;
343
/* find the top of the polygon */
344
maxy = miny = vertices[0].y;
346
for (i = 1; i < count; i++)
348
if (vertices[i].y < miny)
351
miny = vertices[i].y;
353
if (vertices[i].y >= maxy)
356
maxy = vertices[i].y;
363
j = StepAround (top, -1, count);
365
if (slopes[j].dy * slopes[i].dx > slopes[i].dy * slopes[j].dx)
371
bottomy = ICEIL (maxy) + yi;
375
s = StepAround (top, slopeoff, count);
379
if (slopes[s].dy != 0)
381
y = miPolyBuildEdge (vertices[i].x, vertices[i].y,
383
slopes[s].dx, slopes[s].dy,
387
right[nright-1].height = y - lasty;
394
i = StepAround (i, clockwise, count);
395
s = StepAround (s, clockwise, count);
398
right[nright-1].height = bottomy - lasty;
406
s = StepAround (top, slopeoff, count);
410
if (slopes[s].dy != 0)
412
y = miPolyBuildEdge (vertices[i].x, vertices[i].y,
414
slopes[s].dx, slopes[s].dy, xi, yi, 1,
418
left[nleft-1].height = y - lasty;
422
i = StepAround (i, -clockwise, count);
423
s = StepAround (s, -clockwise, count);
426
left[nleft-1].height = bottomy - lasty;
435
DrawablePtr pDrawable,
438
SpanDataPtr spanData,
444
unsigned long oldPixel;
446
MILINESETPIXEL (pDrawable, pGC, pixel, oldPixel);
447
if (pGC->fillStyle == FillSolid)
451
(*pGC->ops->PolyPoint) (pDrawable, pGC, CoordModeOrigin, 1, &pt);
456
if (pGC->miTranslate)
463
(*pGC->ops->FillSpans) (pDrawable, pGC, 1, &pt, &wid, TRUE);
465
MILINERESETPIXEL (pDrawable, pGC, pixel, oldPixel);
470
DrawablePtr pDrawable,
473
SpanDataPtr spanData,
474
register LineFacePtr pLeft,
475
register LineFacePtr pRight)
477
double mx = 0, my = 0;
479
PolyVertexRec vertices[4];
480
PolySlopeRec slopes[4];
482
PolyEdgeRec left[4], right[4];
486
int joinStyle = pGC->joinStyle;
487
int lw = pGC->lineWidth;
489
if (lw == 1 && !spanData) {
490
/* See if one of the lines will draw the joining pixel */
491
if (pLeft->dx > 0 || (pLeft->dx == 0 && pLeft->dy > 0))
493
if (pRight->dx > 0 || (pRight->dx == 0 && pRight->dy > 0))
495
if (joinStyle != JoinRound) {
496
denom = - pLeft->dx * (double)pRight->dy + pRight->dx * (double)pLeft->dy;
498
return; /* no join to draw */
500
if (joinStyle != JoinMiter) {
501
miLineOnePoint (pDrawable, pGC, pixel, spanData, pLeft->x, pLeft->y);
505
if (joinStyle == JoinRound)
507
miLineArc(pDrawable, pGC, pixel, spanData,
509
(double)0.0, (double)0.0, TRUE);
512
denom = - pLeft->dx * (double)pRight->dy + pRight->dx * (double)pLeft->dy;
514
return; /* no join to draw */
520
pLeft->xa = -pLeft->xa;
521
pLeft->ya = -pLeft->ya;
522
pLeft->dx = -pLeft->dx;
523
pLeft->dy = -pLeft->dy;
528
pRight->xa = -pRight->xa;
529
pRight->ya = -pRight->ya;
530
pRight->dx = -pRight->dx;
531
pRight->dy = -pRight->dy;
534
vertices[0].x = pRight->xa;
535
vertices[0].y = pRight->ya;
536
slopes[0].dx = -pRight->dy;
537
slopes[0].dy = pRight->dx;
542
slopes[1].dx = pLeft->dy;
543
slopes[1].dy = -pLeft->dx;
546
vertices[2].x = pLeft->xa;
547
vertices[2].y = pLeft->ya;
549
if (joinStyle == JoinMiter)
551
my = (pLeft->dy * (pRight->xa * pRight->dy - pRight->ya * pRight->dx) -
552
pRight->dy * (pLeft->xa * pLeft->dy - pLeft->ya * pLeft->dx )) /
556
mx = pLeft->xa + (my - pLeft->ya) *
557
(double) pLeft->dx / (double) pLeft->dy;
561
mx = pRight->xa + (my - pRight->ya) *
562
(double) pRight->dx / (double) pRight->dy;
564
/* check miter limit */
565
if ((mx * mx + my * my) * 4 > SQSECANT * lw * lw)
566
joinStyle = JoinBevel;
569
if (joinStyle == JoinMiter)
571
slopes[2].dx = pLeft->dx;
572
slopes[2].dy = pLeft->dy;
573
slopes[2].k = pLeft->k;
576
slopes[2].dx = -slopes[2].dx;
577
slopes[2].dy = -slopes[2].dy;
578
slopes[2].k = -slopes[2].k;
582
slopes[3].dx = pRight->dx;
583
slopes[3].dy = pRight->dy;
584
slopes[3].k = pRight->k;
587
slopes[3].dx = -slopes[3].dx;
588
slopes[3].dy = -slopes[3].dy;
589
slopes[3].k = -slopes[3].k;
595
double scale, dx, dy, adx, ady;
597
adx = dx = pRight->xa - pLeft->xa;
598
ady = dy = pRight->ya - pLeft->ya;
606
slopes[2].dx = (dx * 65536) / scale;
607
slopes[2].dy = (dy * 65536) / scale;
608
slopes[2].k = ((pLeft->xa + pRight->xa) * slopes[2].dy -
609
(pLeft->ya + pRight->ya) * slopes[2].dx) / 2.0;
613
y = miPolyBuildPoly (vertices, slopes, edgecount, pLeft->x, pLeft->y,
614
left, right, &nleft, &nright, &height);
615
miFillPolyHelper (pDrawable, pGC, pixel, spanData, y, height, left, right, nleft, nright);
627
register DDXPointPtr tpts, bpts;
628
register int *twids, *bwids;
629
register int x, y, e, ex, slw;
633
if (pGC->miTranslate)
638
slw = pGC->lineWidth;
650
e = - ((y << 2) + 3);
661
e += (ex = -((x << 3) + 4));
665
if ((e == ex) && (slw > 1))
671
if ((y != 0) && ((slw > 1) || (e != ex)))
679
return (pGC->lineWidth);
682
#define CLIPSTEPEDGE(edgey,edge,edgeleft) \
683
if (ybase == edgey) \
696
edge->x += edge->stepx; \
697
edge->e += edge->dx; \
700
edge->x += edge->signdx; \
701
edge->e -= edge->dy; \
720
register DDXPointPtr pts;
722
double radius, x0, y0, el, er, yk, xlk, xrk, k;
723
int xbase, ybase, y, boty, xl, xr, xcl, xcr;
725
Bool edge1IsMin, edge2IsMin;
732
ybase = ICEIL (yorg);
734
if (pGC->miTranslate)
738
edge1->x += pDraw->x;
739
edge2->x += pDraw->x;
746
radius = ((double)pGC->lineWidth) / 2.0;
747
y = floor(radius - y0 + 1.0);
765
if ((edge1->signdx < 0) == edgeleft1)
783
if ((edge2->signdx < 0) == edgeleft2)
790
if (edge2IsMin && ymin1 > ymin2)
792
} else if (edge2IsMin)
794
el = radius * radius - ((y + y0) * (y + y0)) - (x0 * x0);
803
boty = (y0 < -0.5) ? 1 : 0;
804
if (ybase + y - boty > ymax)
805
boty = ymax - ybase - y;
813
er += xrk - (xr << 1);
819
el += (xl << 1) - xlk;
827
CLIPSTEPEDGE(edgey1, edge1, edgeleft1);
828
CLIPSTEPEDGE(edgey2, edge2, edgeleft2);
834
*wids++ = xcr - xcl + 1;
837
er = xrk - (xr << 1) - er;
838
el = (xl << 1) - xlk - el;
839
boty = floor(-y0 - radius + 1.0);
840
if (ybase + y - boty > ymax)
841
boty = ymax - ybase - y;
846
while ((er >= 0.0) && (xr >= 0))
849
er += xrk - (xr << 1);
852
while ((el > 0.0) && (xl <= 0))
855
el += (xl << 1) - xlk;
863
CLIPSTEPEDGE(edgey1, edge1, edgeleft1);
864
CLIPSTEPEDGE(edgey2, edge2, edgeleft2);
870
*wids++ = xcr - xcl + 1;
873
return (pts - points);
877
miRoundJoinFace (face, edge, leftEdge)
878
register LineFacePtr face;
879
register PolyEdgePtr edge;
897
if (dy < 0 || (dy == 0 && dx > 0))
903
if (dx == 0 && dy == 0)
907
y = ICEIL (face->ya) + face->y;
918
y = miPolyBuildEdge (xa, ya, 0.0, dx, dy, face->x, face->y, !left, edge);
919
edge->height = 32767;
926
miRoundJoinClip (pLeft, pRight, edge1, edge2, y1, y2, left1, left2)
927
register LineFacePtr pLeft, pRight;
928
PolyEdgePtr edge1, edge2;
934
denom = - pLeft->dx * (double)pRight->dy + pRight->dx * (double)pLeft->dy;
938
pLeft->xa = -pLeft->xa;
939
pLeft->ya = -pLeft->ya;
943
pRight->xa = -pRight->xa;
944
pRight->ya = -pRight->ya;
946
*y1 = miRoundJoinFace (pLeft, edge1, left1);
947
*y2 = miRoundJoinFace (pRight, edge2, left2);
951
miRoundCapClip (face, isInt, edge, leftEdge)
952
register LineFacePtr face;
954
register PolyEdgePtr edge;
970
if (dy < 0 || (dy == 0 && dx > 0))
978
if (dx == 0 && dy == 0)
982
y = ICEIL (face->ya) + face->y;
993
y = miPolyBuildEdge (xa, ya, k, dx, dy, face->x, face->y, !left, edge);
994
edge->height = 32767;
1004
unsigned long pixel,
1005
SpanDataPtr spanData,
1006
register LineFacePtr leftFace,
1007
register LineFacePtr rightFace,
1014
int xorgi = 0, yorgi = 0;
1018
PolyEdgeRec edge1, edge2;
1020
Bool edgeleft1, edgeleft2;
1024
xorgi = leftFace ? leftFace->x : rightFace->x;
1025
yorgi = leftFace ? leftFace->y : rightFace->y;
1029
edge1.x = 0; /* not used, keep memory checkers happy */
1031
edge2.x = 0; /* not used, keep memory checkers happy */
1035
if ((pGC->lineStyle != LineSolid || pGC->lineWidth > 2) &&
1036
((pGC->capStyle == CapRound && pGC->joinStyle != JoinRound) ||
1037
(pGC->joinStyle == JoinRound && pGC->capStyle == CapButt)))
1041
xorg = (double) xorgi;
1042
yorg = (double) yorgi;
1044
if (leftFace && rightFace)
1046
miRoundJoinClip (leftFace, rightFace, &edge1, &edge2,
1047
&edgey1, &edgey2, &edgeleft1, &edgeleft2);
1051
edgey1 = miRoundCapClip (leftFace, isInt, &edge1, &edgeleft1);
1055
edgey2 = miRoundCapClip (rightFace, isInt, &edge2, &edgeleft2);
1061
points = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * pGC->lineWidth);
1064
widths = (int *)ALLOCATE_LOCAL(sizeof(int) * pGC->lineWidth);
1067
DEALLOCATE_LOCAL(points);
1070
oldPixel = pGC->fgPixel;
1071
if (pixel != oldPixel)
1073
DoChangeGC(pGC, GCForeground, (XID *)&pixel, FALSE);
1074
ValidateGC (pDraw, pGC);
1079
points = (DDXPointPtr) xalloc (pGC->lineWidth * sizeof (DDXPointRec));
1082
widths = (int *) xalloc (pGC->lineWidth * sizeof (int));
1088
spanRec.points = points;
1089
spanRec.widths = widths;
1092
n = miLineArcI(pDraw, pGC, xorgi, yorgi, points, widths);
1094
n = miLineArcD(pDraw, pGC, xorg, yorg, points, widths,
1095
&edge1, edgey1, edgeleft1,
1096
&edge2, edgey2, edgeleft2);
1100
(*pGC->ops->FillSpans)(pDraw, pGC, n, points, widths, TRUE);
1101
DEALLOCATE_LOCAL(widths);
1102
DEALLOCATE_LOCAL(points);
1103
if (pixel != oldPixel)
1105
DoChangeGC(pGC, GCForeground, &oldPixel, FALSE);
1106
ValidateGC (pDraw, pGC);
1112
AppendSpanGroup (pGC, pixel, &spanRec, spanData)
1117
miLineProjectingCap (pDrawable, pGC, pixel, spanData, face, isLeft, xorg, yorg, isInt)
1118
DrawablePtr pDrawable;
1120
unsigned long pixel;
1121
SpanDataPtr spanData;
1122
register LineFacePtr face;
1127
int xorgi = 0, yorgi = 0;
1129
PolyEdgeRec lefts[2], rights[2];
1130
int lefty, righty, topy, bottomy;
1131
PolyEdgePtr left, right;
1132
PolyEdgePtr top, bottom;
1137
double projectXoff, projectYoff;
1146
lw = pGC->lineWidth;
1152
lefts[0].height = lw;
1155
lefts[0].x -= (lw >> 1);
1157
lefts[0].signdx = 1;
1161
rights[0].height = lw;
1162
rights[0].x = xorgi;
1164
rights[0].x += ((lw + 1) >> 1);
1165
rights[0].stepx = 0;
1166
rights[0].signdx = 1;
1170
miFillPolyHelper (pDrawable, pGC, pixel, spanData, yorgi - (lw >> 1), lw,
1171
lefts, rights, 1, 1);
1180
bottomy = yorgi + dy;
1184
bottomy += (lw >> 1);
1185
lefts[0].height = bottomy - topy;
1186
lefts[0].x = xorgi - (lw >> 1);
1188
lefts[0].signdx = 1;
1193
rights[0].height = bottomy - topy;
1194
rights[0].x = lefts[0].x + (lw-1);
1195
rights[0].stepx = 0;
1196
rights[0].signdx = 1;
1200
miFillPolyHelper (pDrawable, pGC, pixel, spanData, topy, bottomy - topy, lefts, rights, 1, 1);
1220
bottom = &rights[1];
1224
righty = miPolyBuildEdge (xa, ya,
1225
k, dx, dy, xorgi, yorgi, 0, right);
1230
lefty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff,
1231
k, dx, dy, xorgi, yorgi, 1, left);
1237
xap = xa - projectXoff;
1238
yap = ya - projectYoff;
1239
topy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy,
1240
-dy, dx, xorgi, yorgi, dx > 0, top);
1241
bottomy = miPolyBuildEdge (xa, ya,
1242
0.0, -dy, dx, xorgi, yorgi, dx < 0, bottom);
1247
righty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff,
1248
k, dx, dy, xorgi, yorgi, 0, right);
1253
lefty = miPolyBuildEdge (xa, ya,
1254
k, dx, dy, xorgi, yorgi, 1, left);
1260
xap = xa - projectXoff;
1261
yap = ya - projectYoff;
1262
topy = miPolyBuildEdge (xa, ya, 0.0, -dy, dx, xorgi, xorgi, dx > 0, top);
1263
bottomy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy,
1264
-dy, dx, xorgi, xorgi, dx < 0, bottom);
1265
maxy = -ya + projectYoff;
1267
finaly = ICEIL(maxy) + yorgi;
1270
left->height = bottomy - lefty;
1271
right->height = finaly - righty;
1272
top->height = righty - topy;
1276
right->height = bottomy - righty;
1277
left->height = finaly - lefty;
1278
top->height = lefty - topy;
1280
bottom->height = finaly - bottomy;
1281
miFillPolyHelper (pDrawable, pGC, pixel, spanData, topy,
1282
bottom->height + bottomy - topy, lefts, rights, 2, 2);
1288
DrawablePtr pDrawable,
1290
unsigned long pixel,
1291
SpanDataPtr spanData,
1298
register LineFacePtr leftFace,
1299
register LineFacePtr rightFace)
1303
double projectXoff = 0.0, projectYoff = 0.0;
1309
PolyEdgePtr left, right;
1310
PolyEdgePtr top, bottom;
1311
int lefty, righty, topy, bottomy;
1313
PolyEdgeRec lefts[2], rights[2];
1315
int lw = pGC->lineWidth;
1317
/* draw top-to-bottom always */
1318
if (y2 < y1 || (y2 == y1 && x2 < x1))
1329
projectLeft = projectRight;
1333
leftFace = rightFace;
1350
rightFace->dx = -dx;
1351
rightFace->dy = -dy;
1356
rightFace->ya = (double) lw / 2.0;
1357
rightFace->k = -(double) (lw * dx) / 2.0;
1359
leftFace->ya = -rightFace->ya;
1360
leftFace->k = rightFace->k;
1367
dx += ((lw + 1) >> 1);
1369
miFillRectPolyHelper (pDrawable, pGC, pixel, spanData,
1374
leftFace->xa = (double) lw / 2.0;
1376
leftFace->k = (double) (lw * dy) / 2.0;
1377
rightFace->xa = -leftFace->xa;
1379
rightFace->k = leftFace->k;
1386
dy += ((lw + 1) >> 1);
1388
miFillRectPolyHelper (pDrawable, pGC, pixel, spanData,
1393
l = ((double) lw) / 2.0;
1394
L = hypot ((double) dx, (double) dy);
1408
bottom = &rights[1];
1412
/* coord of upper bound at integral y */
1416
if (projectLeft | projectRight)
1422
/* xa * dy - ya * dx */
1428
rightFace->xa = -xa;
1429
rightFace->ya = -ya;
1433
righty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff,
1434
k, dx, dy, x1, y1, 0, right);
1436
righty = miPolyBuildEdge (xa, ya,
1437
k, dx, dy, x1, y1, 0, right);
1439
/* coord of lower bound at integral y */
1443
/* xa * dy - ya * dx */
1447
lefty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff,
1448
k, dx, dy, x1, y1, 1, left);
1450
lefty = miPolyBuildEdge (xa, ya,
1451
k, dx, dy, x1, y1, 1, left);
1453
/* coord of top face at integral y */
1463
double xap = xa - projectXoff;
1464
double yap = ya - projectYoff;
1465
topy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy,
1466
-dy, dx, x1, y1, dx > 0, top);
1469
topy = miPolyBuildEdge (xa, ya, 0.0, -dy, dx, x1, y1, dx > 0, top);
1471
/* coord of bottom face at integral y */
1475
double xap = xa + projectXoff;
1476
double yap = ya + projectYoff;
1477
bottomy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy,
1478
-dy, dx, x2, y2, dx < 0, bottom);
1479
maxy = -ya + projectYoff;
1483
bottomy = miPolyBuildEdge (xa, ya,
1484
0.0, -dy, dx, x2, y2, dx < 0, bottom);
1488
finaly = ICEIL (maxy) + y2;
1492
left->height = bottomy - lefty;
1493
right->height = finaly - righty;
1494
top->height = righty - topy;
1498
right->height = bottomy - righty;
1499
left->height = finaly - lefty;
1500
top->height = lefty - topy;
1502
bottom->height = finaly - bottomy;
1503
miFillPolyHelper (pDrawable, pGC, pixel, spanData, topy,
1504
bottom->height + bottomy - topy, lefts, rights, 2, 2);
1509
miSetupSpanData (pGC, spanData, npt)
1511
SpanDataPtr spanData;
1514
if ((npt < 3 && pGC->capStyle != CapRound) || miSpansEasyRop(pGC->alu))
1515
return (SpanDataPtr) NULL;
1516
if (pGC->lineStyle == LineDoubleDash)
1517
miInitSpanGroup (&spanData->bgGroup);
1518
miInitSpanGroup (&spanData->fgGroup);
1523
miCleanupSpanData (pDrawable, pGC, spanData)
1524
DrawablePtr pDrawable;
1526
SpanDataPtr spanData;
1528
if (pGC->lineStyle == LineDoubleDash)
1530
XID oldPixel, pixel;
1532
pixel = pGC->bgPixel;
1533
oldPixel = pGC->fgPixel;
1534
if (pixel != oldPixel)
1536
DoChangeGC (pGC, GCForeground, &pixel, FALSE);
1537
ValidateGC (pDrawable, pGC);
1539
miFillUniqueSpanGroup (pDrawable, pGC, &spanData->bgGroup);
1540
miFreeSpanGroup (&spanData->bgGroup);
1541
if (pixel != oldPixel)
1543
DoChangeGC (pGC, GCForeground, &oldPixel, FALSE);
1544
ValidateGC (pDrawable, pGC);
1547
miFillUniqueSpanGroup (pDrawable, pGC, &spanData->fgGroup);
1548
miFreeSpanGroup (&spanData->fgGroup);
1552
miWideLine (pDrawable, pGC, mode, npt, pPts)
1553
DrawablePtr pDrawable;
1557
register DDXPointPtr pPts;
1560
SpanDataRec spanDataRec;
1561
SpanDataPtr spanData;
1562
unsigned long pixel;
1563
Bool projectLeft, projectRight;
1564
LineFaceRec leftFace, rightFace, prevRightFace;
1565
LineFaceRec firstFace;
1567
Bool somethingDrawn = FALSE;
1570
spanData = miSetupSpanData (pGC, &spanDataRec, npt);
1571
pixel = pGC->fgPixel;
1578
if (mode == CoordModePrevious)
1581
DDXPointPtr pPtsTmp;
1593
if (x2 == x1 && y2 == y1)
1596
else if (x2 == pPts[npt-1].x && y2 == pPts[npt-1].y)
1601
projectLeft = pGC->capStyle == CapProjecting && !selfJoin;
1602
projectRight = FALSE;
1610
if (mode == CoordModePrevious)
1615
if (x1 != x2 || y1 != y2)
1617
somethingDrawn = TRUE;
1618
if (npt == 1 && pGC->capStyle == CapProjecting && !selfJoin)
1619
projectRight = TRUE;
1620
miWideSegment (pDrawable, pGC, pixel, spanData, x1, y1, x2, y2,
1621
projectLeft, projectRight, &leftFace, &rightFace);
1625
firstFace = leftFace;
1626
else if (pGC->capStyle == CapRound)
1628
if (pGC->lineWidth == 1 && !spanData)
1629
miLineOnePoint (pDrawable, pGC, pixel, spanData, x1, y1);
1631
miLineArc (pDrawable, pGC, pixel, spanData,
1632
&leftFace, (LineFacePtr) NULL,
1633
(double)0.0, (double)0.0,
1639
miLineJoin (pDrawable, pGC, pixel, spanData, &leftFace,
1642
prevRightFace = rightFace;
1644
projectLeft = FALSE;
1646
if (npt == 1 && somethingDrawn)
1649
miLineJoin (pDrawable, pGC, pixel, spanData, &firstFace,
1651
else if (pGC->capStyle == CapRound)
1653
if (pGC->lineWidth == 1 && !spanData)
1654
miLineOnePoint (pDrawable, pGC, pixel, spanData, x2, y2);
1656
miLineArc (pDrawable, pGC, pixel, spanData,
1657
(LineFacePtr) NULL, &rightFace,
1658
(double)0.0, (double)0.0,
1663
/* handle crock where all points are coincedent */
1664
if (!somethingDrawn)
1666
projectLeft = pGC->capStyle == CapProjecting;
1667
miWideSegment (pDrawable, pGC, pixel, spanData,
1668
x2, y2, x2, y2, projectLeft, projectLeft,
1669
&leftFace, &rightFace);
1670
if (pGC->capStyle == CapRound)
1672
miLineArc (pDrawable, pGC, pixel, spanData,
1673
&leftFace, (LineFacePtr) NULL,
1674
(double)0.0, (double)0.0,
1676
rightFace.dx = -1; /* sleezy hack to make it work */
1677
miLineArc (pDrawable, pGC, pixel, spanData,
1678
(LineFacePtr) NULL, &rightFace,
1679
(double)0.0, (double)0.0,
1684
miCleanupSpanData (pDrawable, pGC, spanData);
1694
DrawablePtr pDrawable,
1696
SpanDataPtr spanData,
1705
LineFacePtr leftFace,
1706
LineFacePtr rightFace)
1708
int dashIndex, dashRemain;
1709
unsigned char *pDash;
1712
PolyVertexRec vertices[4];
1713
PolyVertexRec saveRight, saveBottom;
1714
PolySlopeRec slopes[4];
1715
PolyEdgeRec left[2], right[2];
1716
LineFaceRec lcapFace, rcapFace;
1721
unsigned long pixel;
1725
double dashDx, dashDy;
1728
double lcenterx, lcentery, rcenterx = 0.0, rcentery = 0.0;
1729
unsigned long fgPixel, bgPixel;
1733
dashIndex = *pDashIndex;
1735
dashRemain = pDash[dashIndex] - *pDashOffset;
1736
fgPixel = pGC->fgPixel;
1737
bgPixel = pGC->bgPixel;
1738
if (pGC->fillStyle == FillOpaqueStippled ||
1739
pGC->fillStyle == FillTiled)
1744
l = ((double) pGC->lineWidth) / 2.0;
1769
L = hypot ((double) dx, (double) dy);
1777
/* All position comments are relative to a line with dx and dy > 0,
1778
* but the code does not depend on this */
1780
slopes[V_TOP].dx = dx;
1781
slopes[V_TOP].dy = dy;
1782
slopes[V_TOP].k = k;
1784
slopes[V_RIGHT].dx = -dy;
1785
slopes[V_RIGHT].dy = dx;
1786
slopes[V_RIGHT].k = 0;
1788
slopes[V_BOTTOM].dx = -dx;
1789
slopes[V_BOTTOM].dy = -dy;
1790
slopes[V_BOTTOM].k = k;
1792
slopes[V_LEFT].dx = dy;
1793
slopes[V_LEFT].dy = -dx;
1794
slopes[V_LEFT].k = 0;
1796
/* preload the start coordinates */
1797
vertices[V_RIGHT].x = vertices[V_TOP].x = rdy;
1798
vertices[V_RIGHT].y = vertices[V_TOP].y = -rdx;
1800
vertices[V_BOTTOM].x = vertices[V_LEFT].x = -rdy;
1801
vertices[V_BOTTOM].y = vertices[V_LEFT].y = rdx;
1805
vertices[V_TOP].x -= rdx;
1806
vertices[V_TOP].y -= rdy;
1808
vertices[V_LEFT].x -= rdx;
1809
vertices[V_LEFT].y -= rdy;
1811
slopes[V_LEFT].k = rdx * dx + rdy * dy;
1817
if (pGC->capStyle == CapRound)
1829
while (LRemain > dashRemain)
1831
dashDx = (dashRemain * dx) / L;
1832
dashDy = (dashRemain * dy) / L;
1834
rcenterx = lcenterx + dashDx;
1835
rcentery = lcentery + dashDy;
1837
vertices[V_RIGHT].x += dashDx;
1838
vertices[V_RIGHT].y += dashDy;
1840
vertices[V_BOTTOM].x += dashDx;
1841
vertices[V_BOTTOM].y += dashDy;
1843
slopes[V_RIGHT].k = vertices[V_RIGHT].x * dx + vertices[V_RIGHT].y * dy;
1845
if (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1))
1847
if (pGC->lineStyle == LineOnOffDash &&
1848
pGC->capStyle == CapProjecting)
1850
saveRight = vertices[V_RIGHT];
1851
saveBottom = vertices[V_BOTTOM];
1852
saveK = slopes[V_RIGHT].k;
1856
vertices[V_TOP].x -= rdx;
1857
vertices[V_TOP].y -= rdy;
1859
vertices[V_LEFT].x -= rdx;
1860
vertices[V_LEFT].y -= rdy;
1862
slopes[V_LEFT].k = vertices[V_LEFT].x *
1864
vertices[V_LEFT].y *
1868
vertices[V_RIGHT].x += rdx;
1869
vertices[V_RIGHT].y += rdy;
1871
vertices[V_BOTTOM].x += rdx;
1872
vertices[V_BOTTOM].y += rdy;
1874
slopes[V_RIGHT].k = vertices[V_RIGHT].x *
1875
slopes[V_RIGHT].dy -
1876
vertices[V_RIGHT].y *
1879
y = miPolyBuildPoly (vertices, slopes, 4, x1, y1,
1880
left, right, &nleft, &nright, &h);
1881
pixel = (dashIndex & 1) ? bgPixel : fgPixel;
1882
miFillPolyHelper (pDrawable, pGC, pixel, spanData, y, h, left, right, nleft, nright);
1884
if (pGC->lineStyle == LineOnOffDash)
1886
switch (pGC->capStyle)
1889
vertices[V_BOTTOM] = saveBottom;
1890
vertices[V_RIGHT] = saveRight;
1891
slopes[V_RIGHT].k = saveK;
1898
lcapFace.xa = -vertices[V_LEFT].x;
1899
lcapFace.ya = -vertices[V_LEFT].y;
1900
lcapFace.k = slopes[V_LEFT].k;
1904
lcapFace.xa = vertices[V_TOP].x;
1905
lcapFace.ya = vertices[V_TOP].y;
1906
lcapFace.k = -slopes[V_LEFT].k;
1908
miLineArc (pDrawable, pGC, pixel, spanData,
1909
&lcapFace, (LineFacePtr) NULL,
1910
lcenterx, lcentery, FALSE);
1914
rcapFace.xa = vertices[V_BOTTOM].x;
1915
rcapFace.ya = vertices[V_BOTTOM].y;
1916
rcapFace.k = slopes[V_RIGHT].k;
1920
rcapFace.xa = -vertices[V_RIGHT].x;
1921
rcapFace.ya = -vertices[V_RIGHT].y;
1922
rcapFace.k = -slopes[V_RIGHT].k;
1924
miLineArc (pDrawable, pGC, pixel, spanData,
1925
(LineFacePtr) NULL, &rcapFace,
1926
rcenterx, rcentery, FALSE);
1931
LRemain -= dashRemain;
1933
if (dashIndex == pGC->numInDashList)
1935
dashRemain = pDash[dashIndex];
1937
lcenterx = rcenterx;
1938
lcentery = rcentery;
1940
vertices[V_TOP] = vertices[V_RIGHT];
1941
vertices[V_LEFT] = vertices[V_BOTTOM];
1942
slopes[V_LEFT].k = -slopes[V_RIGHT].k;
1946
if (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1))
1948
vertices[V_TOP].x -= dx;
1949
vertices[V_TOP].y -= dy;
1951
vertices[V_LEFT].x -= dx;
1952
vertices[V_LEFT].y -= dy;
1954
vertices[V_RIGHT].x = rdy;
1955
vertices[V_RIGHT].y = -rdx;
1957
vertices[V_BOTTOM].x = -rdy;
1958
vertices[V_BOTTOM].y = rdx;
1963
vertices[V_RIGHT].x += rdx;
1964
vertices[V_RIGHT].y += rdy;
1966
vertices[V_BOTTOM].x += rdx;
1967
vertices[V_BOTTOM].y += rdy;
1968
slopes[V_RIGHT].k = vertices[V_RIGHT].x *
1969
slopes[V_RIGHT].dy -
1970
vertices[V_RIGHT].y *
1974
slopes[V_RIGHT].k = 0;
1976
if (!first && pGC->lineStyle == LineOnOffDash &&
1977
pGC->capStyle == CapProjecting)
1979
vertices[V_TOP].x -= rdx;
1980
vertices[V_TOP].y -= rdy;
1982
vertices[V_LEFT].x -= rdx;
1983
vertices[V_LEFT].y -= rdy;
1984
slopes[V_LEFT].k = vertices[V_LEFT].x *
1986
vertices[V_LEFT].y *
1990
slopes[V_LEFT].k += dx * dx + dy * dy;
1993
y = miPolyBuildPoly (vertices, slopes, 4, x2, y2,
1994
left, right, &nleft, &nright, &h);
1996
pixel = (dashIndex & 1) ? pGC->bgPixel : pGC->fgPixel;
1997
miFillPolyHelper (pDrawable, pGC, pixel, spanData, y, h, left, right, nleft, nright);
1998
if (!first && pGC->lineStyle == LineOnOffDash &&
1999
pGC->capStyle == CapRound)
2005
lcapFace.xa = -vertices[V_LEFT].x;
2006
lcapFace.ya = -vertices[V_LEFT].y;
2007
lcapFace.k = slopes[V_LEFT].k;
2011
lcapFace.xa = vertices[V_TOP].x;
2012
lcapFace.ya = vertices[V_TOP].y;
2013
lcapFace.k = -slopes[V_LEFT].k;
2015
miLineArc (pDrawable, pGC, pixel, spanData,
2016
&lcapFace, (LineFacePtr) NULL,
2017
rcenterx, rcentery, FALSE);
2020
dashRemain = ((double) dashRemain) - LRemain;
2021
if (dashRemain == 0)
2024
if (dashIndex == pGC->numInDashList)
2026
dashRemain = pDash[dashIndex];
2034
leftFace->ya = -rdx;
2039
rightFace->dx = -dx;
2040
rightFace->dy = -dy;
2041
rightFace->xa = -rdy;
2042
rightFace->ya = rdx;
2045
*pDashIndex = dashIndex;
2046
*pDashOffset = pDash[dashIndex] - dashRemain;
2050
miWideDash (pDrawable, pGC, mode, npt, pPts)
2051
DrawablePtr pDrawable;
2055
register DDXPointPtr pPts;
2058
unsigned long pixel;
2059
Bool projectLeft, projectRight;
2060
LineFaceRec leftFace, rightFace, prevRightFace;
2061
LineFaceRec firstFace;
2063
int dashIndex, dashOffset;
2064
register int prevDashIndex;
2065
SpanDataRec spanDataRec;
2066
SpanDataPtr spanData;
2067
Bool somethingDrawn = FALSE;
2069
Bool endIsFg = FALSE, startIsFg = FALSE;
2070
Bool firstIsFg = FALSE, prevIsFg = FALSE;
2072
#ifndef XFree86Server
2073
/* XXX backward compatibility */
2074
if (pGC->lineWidth == 0)
2076
miZeroDashLine (pDrawable, pGC, mode, npt, pPts);
2080
if (pGC->lineStyle == LineDoubleDash &&
2081
(pGC->fillStyle == FillOpaqueStippled || pGC->fillStyle == FillTiled))
2083
miWideLine (pDrawable, pGC, mode, npt, pPts);
2088
spanData = miSetupSpanData (pGC, &spanDataRec, npt);
2093
if (mode == CoordModePrevious)
2096
DDXPointPtr pPtsTmp;
2108
if (x2 == x1 && y2 == y1)
2111
else if (x2 == pPts[npt-1].x && y2 == pPts[npt-1].y)
2115
projectLeft = pGC->capStyle == CapProjecting && !selfJoin;
2116
projectRight = FALSE;
2119
miStepDash ((int)pGC->dashOffset, &dashIndex,
2120
pGC->dash, (int)pGC->numInDashList, &dashOffset);
2128
if (mode == CoordModePrevious)
2133
if (x1 != x2 || y1 != y2)
2135
somethingDrawn = TRUE;
2136
if (npt == 1 && pGC->capStyle == CapProjecting &&
2137
(!selfJoin || !firstIsFg))
2138
projectRight = TRUE;
2139
prevDashIndex = dashIndex;
2140
miWideDashSegment (pDrawable, pGC, spanData, &dashOffset, &dashIndex,
2142
projectLeft, projectRight, &leftFace, &rightFace);
2143
startIsFg = !(prevDashIndex & 1);
2144
endIsFg = (dashIndex & 1) ^ (dashOffset != 0);
2145
if (pGC->lineStyle == LineDoubleDash || startIsFg)
2147
pixel = startIsFg ? pGC->fgPixel : pGC->bgPixel;
2148
if (first || (pGC->lineStyle == LineOnOffDash && !prevIsFg))
2150
if (first && selfJoin)
2152
firstFace = leftFace;
2153
firstIsFg = startIsFg;
2155
else if (pGC->capStyle == CapRound)
2156
miLineArc (pDrawable, pGC, pixel, spanData,
2157
&leftFace, (LineFacePtr) NULL,
2158
(double)0.0, (double)0.0, TRUE);
2162
miLineJoin (pDrawable, pGC, pixel, spanData, &leftFace,
2166
prevRightFace = rightFace;
2169
projectLeft = FALSE;
2171
if (npt == 1 && somethingDrawn)
2173
if (pGC->lineStyle == LineDoubleDash || endIsFg)
2175
pixel = endIsFg ? pGC->fgPixel : pGC->bgPixel;
2176
if (selfJoin && (pGC->lineStyle == LineDoubleDash || firstIsFg))
2178
miLineJoin (pDrawable, pGC, pixel, spanData, &firstFace,
2183
if (pGC->capStyle == CapRound)
2184
miLineArc (pDrawable, pGC, pixel, spanData,
2185
(LineFacePtr) NULL, &rightFace,
2186
(double)0.0, (double)0.0, TRUE);
2191
/* glue a cap to the start of the line if
2192
* we're OnOffDash and ended on odd dash
2194
if (selfJoin && firstIsFg)
2196
pixel = pGC->fgPixel;
2197
if (pGC->capStyle == CapProjecting)
2198
miLineProjectingCap (pDrawable, pGC, pixel, spanData,
2200
(double)0.0, (double)0.0, TRUE);
2201
else if (pGC->capStyle == CapRound)
2202
miLineArc (pDrawable, pGC, pixel, spanData,
2203
&firstFace, (LineFacePtr) NULL,
2204
(double)0.0, (double)0.0, TRUE);
2209
/* handle crock where all points are coincident */
2210
if (!somethingDrawn && (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1)))
2212
/* not the same as endIsFg computation above */
2213
pixel = (dashIndex & 1) ? pGC->bgPixel : pGC->fgPixel;
2214
switch (pGC->capStyle) {
2216
miLineArc (pDrawable, pGC, pixel, spanData,
2217
(LineFacePtr) NULL, (LineFacePtr) NULL,
2218
(double)x2, (double)y2,
2222
x1 = pGC->lineWidth;
2223
miFillRectPolyHelper (pDrawable, pGC, pixel, spanData,
2224
x2 - (x1 >> 1), y2 - (x1 >> 1), x1, x1);
2229
miCleanupSpanData (pDrawable, pGC, spanData);
2232
/* these are stubs to allow old ddx ValidateGCs to work without change */