2
* plines.c -- $Id: plines.c 685 2003-03-08 15:26:51Z travo $
3
* p_lines for MS Windows
5
* Copyright (c) 1999. See accompanying LEGAL file for details.
10
/* Following advantages of paths would be nice, BUT paths cost
11
* a factor of two or so in performance, so forget it:
12
* Reasons to use paths for all lines and fills:
13
* (1) Win9x join and cap styles only work for paths
14
* (2) Other fill primitives use pen, requiring it to be set NULL
15
* affects prect.c, ellipse.c
18
/* MS Windows unclear on what happens when begin and end points
19
* of a line are identical, making the inconsistent claim that
20
* the first point on a line is always included and the last point
21
* on a line is always excluded
22
* -- experimentally, the last point can be included by adding
23
* a single segment one pixel long to the end (last segment
24
* cannot be zero pixels long) -- Munro's Win95 box
25
* -- but on Langer's WinNT box, last point *is* included,
26
* the two boxes also differ in does_linetypes, so the hack here
27
* uses that to distinguish -- I dont know what else to do... */
29
static int w_polyline_to(HDC dc, int type, int width, POINT *pxy, int n,
31
static void w_final_pt(HDC dc, POINT *pxy);
32
static float w_hypot(float dx, float dy);
38
HDC dc = w_getdc(w, 2);
40
POINT *pxy = w_pt_list;
42
int closed = (pxy[0].x==pxy[n-1].x && pxy[0].y==pxy[n-1].y);
43
if ((w->pen_type&7)==P_SOLID || w->s->does_linetypes) {
44
/* NOTE: PolylineTo is MUCH slower than Polyline */
46
if (!closed && !w->s->does_linetypes)
47
MoveToEx(dc, pxy[n-1].x, pxy[n-1].y, 0),
48
w_final_pt(dc, &pxy[n-2]);
50
MoveToEx(dc, pxy[0].x, pxy[0].y, 0);
51
w_polyline_to(dc, w->pen_type&7, w->pen_width, &pxy[0], n-1, closed);
54
MoveToEx(dc, pxy[0].x, pxy[0].y, 0);
55
LineTo(dc, pxy[0].x+1, pxy[0].y);
63
int n = w_pt_count / 2;
64
HDC dc = w_getdc(w, 2);
66
POINT *pxy = w_pt_list;
68
MoveToEx(dc, pxy[0].x, pxy[0].y, 0);
69
if (pxy[1].x!=pxy[0].x || pxy[1].y!=pxy[0].y) {
70
if ((w->pen_type&7)==P_SOLID || w->s->does_linetypes) {
71
LineTo(dc, pxy[1].x, pxy[1].y);
72
if (!w->s->does_linetypes) w_final_pt(dc, pxy);
74
w_polyline_to(dc, w->pen_type&7, w->pen_width, &pxy[0], 1, 0);
77
LineTo(dc, pxy[1].x+1, pxy[1].y);
88
HDC dc = w_getdc(w, 0);
90
POINT *pxy = w_pt_list;
91
COLORREF color = w_color(w, w->color);
93
SetPixelV(dc, pxy[0].x, pxy[0].y, color);
100
w_final_pt(HDC dc, POINT *pxy)
102
/* Windows maddeningly wont draw final pixel on a polyline
103
* -- this hack works pretty well onscreen, worse in metafiles */
104
long dx = pxy[1].x - pxy[0].x;
105
long dy = pxy[1].y - pxy[0].y;
109
ix = -((dy > dx) || (dx < 2*dy));
110
iy = -((dx > dy) || (dy < 2*dx));
112
ix = -((dy < -dx) || (-dx > 2*dy));
113
iy = ((-dx < dy) || (dy > -2*dx));
117
ix = ((-dy < dx) || (dx > -2*dy));
118
iy = -((dx < -dy) || (-dy > 2*dx));
120
ix = ((dy < dx) || (dx > 2*dy));
121
iy = ((dx < dy) || (dy > 2*dx));
124
LineTo(dc, pxy[1].x+ix, pxy[1].y+iy);
127
static float dashed[] = { 5, 5 };
128
static float dotted[] = { 1, 3 };
129
static float dashdot[] = { 5, 2, 1, 2 };
130
static float dashdotdot[] = { 5, 2, 1, 2, 1, 2 };
131
static float *x_dash[] = { 0, dashed, dotted, dashdot, dashdotdot };
132
static int x_ndash[] = { 0, 2, 2, 4, 6 };
135
w_polyline_to(HDC dc, int type, int width, POINT *pxy, int n, int closed)
137
int ndash = x_ndash[type];
138
int i, x, y, xmv=0, ymv=0;
140
float dash[6], len, dx, dy, d=0.0;
142
for (i=0 ; i<ndash ; i++) {
143
dash[i] = x_dash[type][i];
144
if (width>1 && dash[i]>1) dash[i] *= width;
152
dx = (float)(pxy[0].x - x);
153
dy = (float)(pxy[0].y - y);
154
len = w_hypot(dx, dy);
155
if (d+len > dash[i]) {
163
xx = x + (int)(f*dx);
164
yy = y + (int)(f*dy);
166
xmv = xx, ymv = yy, moved = 1;
168
if (moved) MoveToEx(dc, xmv, ymv, 0), moved = 0;
171
if ((++i) == ndash) i = 0;
172
} while (s+dash[i] < len);
173
d = len - s; /* 0 < d <= dash[i] */
178
xmv = pxy[0].x, ymv = pxy[0].y, moved = 1;
180
if (moved) MoveToEx(dc, xmv, ymv, 0), moved = 0;
181
LineTo(dc, pxy[0].x, pxy[0].y);
184
if (!moved && !closed) LineTo(dc, pxy[0].x+1, pxy[0].y);
189
w_hypot(float dx, float dy)
191
if (dx<0.0) dx = -dx;
192
if (dy<0.0) dy = -dy;
198
/* biggest error is when dx==dy -- off by 6 percent */
199
if (dx) dx += 0.5f*dy*dy/dx;