aboutsummaryrefslogtreecommitdiff
path: root/sys/gio/calcomp/ccpcseg.x
blob: 7b55adc7cfe4de43c9342c8cfcded016e2a220bc (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.

include <gki.h>
include <gset.h>
include <mach.h>
include	"ccp.h"

# CCP_CALCSEG -- Calculate a contiguous line segment; used to return individual
# line segments under the various options of line type simulation.  (Width is
# not simulated here).  Each segment returned is actually drawable, guaranteeing
# constant-length dashes and gaps along the exact length of the input polyline. 
# Normally called by ccp_polyline.

procedure ccp_calcseg (p, npts, ltype, curpl_pt, segsize, xseg,yseg, nsegpts)

short	p[ARB]			# points defining line
int	npts			# number of points, i.e., (x,y) pairs
int	ltype			# line type; CCP_CLEAR <= ltype <= CCP_DASHDOT
int	curpl_pt		# current polyline point; input and output
int	segsize			# current segment memory size
pointer	xseg,yseg		# plotter-unit contiguous line segment, output
int	nsegpts			# number of points in segment, output

int	i, j
real	lastp_x, lastp_y, x, y, curseglen
bool	toggle

include	"ccp.com"

begin
	if (curpl_pt == 1) {	# always start line w/beginning of dash, etc.
	    lastp_x   = XTRAN(p[1])
	    lastp_y   = YTRAN(p[2])
	    curpl_pt  = curpl_pt + 1 
	    toggle    = false
	} 

	XSEG(1)   = lastp_x
	YSEG(1)   = lastp_y
	nsegpts   = 1
	curseglen = 0.0

	switch (ltype) {
	case GL_CLEAR:
	    nsegpts = 0

	case GL_DASHED:
	    # Return one contiguous polyline segment worth one dash:
	    call ccx_dash (p, npts, curpl_pt, curseglen, nsegpts, segsize,
		xseg,yseg, lastp_x,lastp_y)

	    # Now increment internal counters for gap width for next call
	    call ccx_gap (p, npts, curpl_pt, curseglen, g_dashlen + g_gaplen,
		lastp_x,lastp_y)

	case GL_DOTTED:
	    # Since we already built one point, we need only the following gap:
	    call ccx_gap (p, npts, curpl_pt, curseglen, g_gaplen,
		lastp_x,lastp_y)

	case GL_DOTDASH:
	    # Implement as dash/gap/dot/gap/:
	    if (toggle) {			# build dot/gap/
		x = lastp_x #XTRAN(p[i])
		y = lastp_y #YTRAN(p[i+1])
		nsegpts = 0
		call ccx_addsegpt (x,y, xseg,yseg, nsegpts, segsize)
		toggle = false
	        call ccx_gap (p, npts, curpl_pt, curseglen, g_gaplen, 
		    lastp_x,lastp_y)

	    } else {				# build dash/gap/
	        call ccx_dash (p, npts, curpl_pt, curseglen, nsegpts, 
		    segsize, xseg,yseg, lastp_x,lastp_y)
	        call ccx_gap (p, npts, curpl_pt, curseglen,
		    g_dashlen + g_gaplen, lastp_x,lastp_y)
		toggle = true
	    }

	default:				# solid line
	    do i = curpl_pt, npts {
		j = (i-1) * 2 + 1
		x = XTRAN(p[j])
		y = YTRAN(p[j+1])
		call ccx_addsegpt (x,y, xseg,yseg, nsegpts, segsize)
	    }
	    curpl_pt = npts
	}
end


# CCX_DASH -- Do the actual work of building a dashed line segment (no gap)

procedure ccx_dash (p, npts, curpl_pt, curseglen, cursegpt, segsize,
		    xseg,yseg, lastp_x,lastp_y)

short	p[ARB]		# Input:  points defining line
int	npts		# Input:  number of points, i.e., (x,y) pairs
int	curpl_pt	# In/Output: current polyline point
real	curseglen	# Output: length of current simulated ltype unit (._)
int	cursegpt	# Output: index of current drawable point in segment
int	segsize		# In/Output: current segment size
pointer	xseg,yseg	# Output: plotter-units, contiguous line segment
real	lastp_x,lastp_y	# Output: last point in segment (visible or invisible)

int	i
real	temppl_dis, x, y, delx, dely
real	actual_dis, rem_dashlen

include	"ccp.com"

begin
	rem_dashlen = g_dashlen

	# Build up current "dash" (may be bent any number of times).

	while (curseglen + EPSILON < g_dashlen && curpl_pt <= npts) {
	    i = (curpl_pt-1) * 2 + 1
	    x = XTRAN(p[i])
	    y = YTRAN(p[i+1])
	    temppl_dis  = DIS(lastp_x, lastp_y, x, y)
	    if (temppl_dis >= EPSILON) {
		actual_dis  = min (temppl_dis, rem_dashlen)
		rem_dashlen = rem_dashlen - actual_dis

		delx = x - lastp_x
		dely = y - lastp_y
		x = lastp_x + delx * actual_dis / temppl_dis
		y = lastp_y + dely * actual_dis / temppl_dis

		call ccx_addsegpt (x,y, xseg,yseg, cursegpt, segsize)
		curseglen = curseglen + actual_dis
		lastp_x   = XSEG(cursegpt)
		lastp_y   = YSEG(cursegpt)
	    }
	    if (curseglen + EPSILON < g_dashlen)
	        curpl_pt = curpl_pt + 1
	}
end


# CCX_GAP -- Do the actual work of building an invisible gap along original
# polyline.

procedure ccx_gap (p, npts, curpl_pt, curseglen, matchlen, lastp_x,lastp_y)

short	p[ARB]		# Input: points defining line
int	npts		# Input: number of points, i.e., (x,y) pairs
int	curpl_pt	# In/Output: current polyline point
real	curseglen	# In/Output: length of current simulated ltype unit (._)
real	matchlen	# Output: length to build curseglen up to
real	lastp_x,lastp_y	# Output: last point in segment (visible, invisible)

int	i
real	x, y, delx, dely
real	temppl_dis, actual_dis, rem_gaplen

include	"ccp.com"

begin
	rem_gaplen = g_gaplen

	# Build up current "gap" (may be bent any number of times).

	while ((curseglen + EPSILON < (matchlen)) && (curpl_pt <= npts)) {
	    i = (curpl_pt-1) * 2 + 1
	    x = XTRAN(p[i])
	    y = YTRAN(p[i+1])

	    temppl_dis = DIS(lastp_x, lastp_y, x, y)
	    if (temppl_dis >= EPSILON) {
		actual_dis = min (temppl_dis, rem_gaplen)
		rem_gaplen = rem_gaplen - actual_dis

		delx = x - lastp_x
		dely = y - lastp_y
		curseglen = curseglen + actual_dis
		lastp_x = lastp_x + delx * actual_dis / temppl_dis
		lastp_y = lastp_y + dely * actual_dis / temppl_dis
	    }
	    if (curseglen + EPSILON < matchlen)
		curpl_pt = curpl_pt + 1
	}
end


# CCX_ADDSEGPT -- add a point to the segment structure; handle memory needs

procedure ccx_addsegpt (x,y, xseg,yseg, cursegpt,segsize)

real	x,y			# point to be added to output segment
pointer	xseg,yseg		# NDC-coord contiguous line segment, output
int	cursegpt		# index of current drawable point in segment
int	segsize			# current segment size

begin
	cursegpt = cursegpt + 1

	if (cursegpt > segsize) {
	    segsize = segsize + SEGSIZE
	    call realloc (xseg, segsize, TY_REAL)
	    call realloc (yseg, segsize, TY_REAL)
	}

	XSEG(cursegpt) = x
	YSEG(cursegpt) = y
end