aboutsummaryrefslogtreecommitdiff
path: root/sys/gio/calcomp/ccpdrawch.x
blob: dab89158fc22a578aa5d698599b16e8f9ee67f78 (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
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.

include	<math.h>
include	<gki.h>
include	<gset.h>
include	"ccp.h"
include	"font.h"

define	ITALIC_TILT	0.30	# fraction of xsize to tilt italics at top
define	MAX_STROKESIZE	32	# max number of vectors making up one stroke
define	CALCOMP_CHSTART	16	# maximum calcomp special symbol plus 1
define	SYMBOL_ASPECT	1.17	# calcomp height = 7/6 width for normal spacing.
define	LOW_REDRAWS	5	# multiple traces for low-quality bold text
define	HIGH_REDRAWS	9	# multiple traces for high-quality bold text


# CCP_DRAWCHAR -- Draw a character of the given size and orientation at the
# given position.

procedure ccp_drawchar (ch, x, y, xsize, ysize, orien, font, quality)

char	ch			# character to be drawn
int	x, y			# lower left GKI coords of character
int	xsize, ysize		# char width and height in unscaled GKI units
int	orien			# orientation of character (0 degrees normal)
int	font			# desired character font
int	quality			# quality control -- low(calcomp); other(iraf)

real	px, py, coso, sino, theta, xto_nicesize, yto_nicesize
real	sx[MAX_STROKESIZE], sy[MAX_STROKESIZE]
int	stroke, tab1, tab2, i, j, pen
int	bitupk()

include "ccp.com"
include	"font.com"

begin
	# Compute correction factor for absolute physical character size.
	# This also corrects for distortion of high-qual text if xscale<>yscale.
	xto_nicesize = g_xdefault_scale / g_xndcto_p
	yto_nicesize = g_ydefault_scale / g_yndcto_p

	# Set the font.
	call ccp_font (font)

	if (quality == GT_LOW) {
	    # If low text quality requested, draw with Calcomp's SYMBOL call.
	    # We avoid machine-dependency word-size problems by always
	    # calling SYMBOL only from here, one char per call.
	    # Calcomp's SYMBOL expects height as only size; aspect is height
	    # = 7/6 (width) for normal character spacing.

	    call ccx_intersymbol (XTRAN(x),YTRAN(y), real(xsize) * xto_nicesize,
	        real(ysize) * yto_nicesize, ch, real(orien))

	} else {
	    # Text quality requested is not low; draw font either with single-
	    # width line or bold, via ccp_drawseg.

	    if (ch < CHARACTER_START || ch > CHARACTER_END)
		i = '?' - CHARACTER_START + 1
	    else
		i = ch  - CHARACTER_START + 1

	    tab1 = chridx[i]
	    tab2 = chridx[i+1] - 1

	    if (tab2 - tab1 + 1 > MAX_STROKESIZE) {
		call eprintf (
		    "CCP KERNEL WARNING: up-dimension MAX_STROKESIZE\n")
		call eprintf (
		    "in module ccp_drawch; new stroke size %d, char %s\n")
		    call pargi (tab2 - tab1 + 1)
		    call pargc (ch)
		tab2 = tab1 + MAX_STROKESIZE - 1
	    }

	    theta = -DEGTORAD(orien)
	    coso = cos(theta)
	    sino = sin(theta)

	    j = 0
	    do i = tab1, tab2 {
		stroke = chrtab[i]
		px  = bitupk (stroke, COORD_X_START,   COORD_X_LEN)
		py  = bitupk (stroke, COORD_Y_START,   COORD_Y_LEN)
		pen = bitupk (stroke, COORD_PEN_START, COORD_PEN_LEN)

		# Scale size of character in unwarped (xscale == yscale) system.
		px = px / FONT_WIDTH  * xsize
		py = py / FONT_HEIGHT * ysize

		# The italic font is implemented applying a tilt.
		if (font == GT_ITALIC)
		    px = px + ((py / ysize) * xsize * ITALIC_TILT)

		if (pen == 0 && j > 0) {	# new stroke segment; draw last
		    if (j > 1) 
			call ccx_interpoly (sx, sy, j, quality)
		    j = 0
		} 

		# Rotate, shift (unwarped), then correct for xscale <> yscale.
		j     = j + 1
		sx[j] = XTRAN(x + ( px * coso + py * sino) * xto_nicesize)
		sy[j] = YTRAN(y + (-px * sino + py * coso) * yto_nicesize)
	    }

	    # last stroke segment:
	    if (j > 1)
	        call ccx_interpoly (sx, sy, j, quality)
	}
end


# CCX_INTERPOLY -- intermediate routine to 1) pass simple draw instruction to 
# calcomp plot routines if linewidth single or bold method = penchange, or 
# 2) simulate bold text by offsetting to the four corners and four edges
# of a box surrounding the character.

procedure ccx_interpoly (x, y, npts, quality)

real	x[ARB],y[ARB] 	# plotter-unit coordinates to be drawn as polyline
int	npts		# number points in x,y
int	quality		# text quality (distinguish between medium and high)

int	i, j, num_redraws, twidth
real	xp, yp
real	xoff[HIGH_REDRAWS],yoff[HIGH_REDRAWS]

include	"ccp.com"

data	xoff/0., 1., 0., -1.,  0.,    1., -1., -1.,  1./
data	yoff/0., 0., 1.,  0., -1.,    1.,  1., -1., -1./

begin
	if (npts <= 0) 
	    return

	# If line width override is on, or linewidth is single, do simple move
	# and draws.

	num_redraws = 1
	twidth = nint(GKI_UNPACKREAL(CCP_WIDTH(g_cc)))
	if (!g_lwover)
	    if (g_lwtype == 'p' && twidth >= 1)
		call ccp_lwidth (twidth)
	    else if (twidth > 1 && quality == GT_HIGH)
		num_redraws = HIGH_REDRAWS
	    else
		num_redraws = LOW_REDRAWS

	if (num_redraws == 1) {
	    call plot (x[1], y[1], CCP_UP)
	    g_max_x = max (x[1], g_max_x)

	    if (npts == 1) {	# single pt is special case; drop pen
		call plot (x[1], y[1], CCP_DOWN)
	    } else {		# draw normally
		do i = 2, npts {
		    call plot (x[i], y[i], CCP_DOWN)
		    g_max_x = max (x[i], g_max_x)
		}
	    }
	} else {
	    do i = 1, num_redraws {
		xp = x[1] + xoff[i] * g_plwsep
		yp = y[1] + yoff[i] * g_plwsep
		call plot (xp, yp, CCP_UP)
		g_max_x = max (xp, g_max_x)

		if (npts == 1) {	# single pt is special case; drop pen
		    call plot (xp, yp, CCP_DOWN)
		} else {		# draw normally
		    do j = 2, npts {
			xp = x[j] + xoff[i] * g_plwsep
			yp = y[j] + yoff[i] * g_plwsep
			call plot (xp, yp, CCP_DOWN)
			g_max_x = max (xp, g_max_x)
		    }
		}
	    }
	}
end


# CCX_INTERSYMBOL -- routine intermediate to Calcomp SYMBOL routine; handles
# bold text.

procedure ccx_intersymbol (x,y, xsize,ysize, ch, orien)

real	x,y		# plotter-unit coords of lower left of character
real	xsize,ysize	# char width, height in GKI units scaled to "nice" sizes
char	ch		# character to be drawn
real	orien		# degrees counterclockwise from +x axis to text path

int	i, nsym, symchar, num_redraws
real	xp,yp, xoff[HIGH_REDRAWS],yoff[HIGH_REDRAWS], csize

include	"ccp.com"

data	xoff/0., 1., 0., -1.,  0.,    1., -1., -1.,  1./
data	yoff/0., 0., 1.,  0., -1.,    1.,  1., -1., -1./

begin
	symchar = int (ch)
	nsym    = 1

	if (ch < CALCOMP_CHSTART && ch >= 0) {
	    nsym = -1
	} else if (ch < ' ' || ch > '~')
	    ch = '~'

	# Since we are only called if text_quality == low, implement
	# bold text with only the center and edge positions (LOW_REDRAWS).
	num_redraws = 1
	if (!g_lwover && nint(GKI_UNPACKREAL(CCP_WIDTH(g_cc))) > 1)
	    num_redraws = LOW_REDRAWS

	# Set the size as the height of the character in device units; we
	# start with the width to avoid overlapping, and we use the default
	# scale, which results in reasonable-sized characters; the specified
	# scale would produce strange results as orien passes from 0 to 90.

	csize = min (xsize * g_xndcto_p * SYMBOL_ASPECT, ysize * g_yndcto_p)

	do i = 1, num_redraws {
	    xp = x + xoff[i] * g_plwsep
	    yp = y + yoff[i] * g_plwsep
	    call symbol (xp, yp, csize, symchar, orien, nsym)
	    g_max_x = max (xp + csize, g_max_x)
	}
end