Use new text accessors.
[geda-gaf/berndj.git] / libgeda / share / prolog.ps
blobb8bb24216042e6e83824eb6bedc70628e937976e
1 % Prolog for gEDA, define all the functions needed for rendering
2 % schematics on Postscript devices
5 % Draw a line from the second coordinate to the first
6 % x2 y2 x1 y1 width line -
7 /line {
8     setlinewidth
9     % pop off first element and moveto
10     moveto
11     % pop off remaining elements and draw a line segment
12     lineto
13     % draw it
14     stroke
15 } bind def
18 % Draw a dot
19 % x y r dot -
20 /dot {
21     0 360 arc fill
22 } bind def
24 % Draw a dot-dashed line, a bunch of lined segments,
25 % if the array element only has length two, draw a dot.
26 % [ [x2 y2 x1 y1] [x4 y4 x3 y3] [x5 y5] ... ] width dashed -
27 /width 0 def
28 /dashed {
29     dup 2.0 div /width exch def
30     setlinewidth
31     % pop off each line segment and draw it as a dot or as a line
32     {
33         aload length 2 gt
34         { moveto lineto stroke}
35         { width dot } ifelse
36     } forall
37 } bind def
39 % Draw an arc segment
40 % x y r ang1 ang2 width darc -
41 /darc {
42     setlinewidth
43     arc stroke
44 } bind def
46 % Draw a series of arc segment bits, if the array element only has a single
47 % element in it, draw a dot.
48 % [ [sa1 ea1] [sa2 ea2] ... ] x y r width dashedarc -
49 /x 0 def
50 /y 0 def
51 /dashedarc {
52     dup /width exch def
53     setlinewidth
54     /r exch def  
55     /y exch def
56     /x exch def
57     { aload length 1 gt
58         {
59             % this element had two angles in it
60             % extract start and stop angles
61             x y r   % drop x y and r onto stack
62                     % at this point we have: sa ea x y r
63                     % we need                      x y r sa ea
64                     % so..
65             5 -2 roll
66             % and add it to the current path, and draw it
67             arc stroke
68         } {
69             % this element only had one angle in it, place a
70             % filled dot at the appropriate place
71             % compute center point of the arc using the angle
72             % that is on the top of the stack
73             dup                 % angle angle
74             cos r mul x add     % angle x
75             exch                % x angle
76             sin r mul y add     % x y
77             width               % x y width/2
78             dot                 % draw the dot
79         } ifelse
80     } forall
82     % Now draw it
83     stroke
84 } bind def
86 % Draw a box
87 % width height x y linethickness box -
88 /box {
89     setlinewidth
90     moveto
91     exch dup 0 rlineto   % w h, h w w 0      -- Draw bottom line
92     exch 0 exch rlineto  % h w, w h 0, w 0 h -- Draw right line 
93     neg 0 rlineto        % w, -w 0           -- Draw Top line
94     closepath            % finish and draw it
95     stroke
96 } bind def                           
98 % Draw a filled box
99 % width height x y fbox -
100 /fbox {
101     moveto
102     exch dup 0 rlineto  
103     exch 0 exch rlineto 
104     neg 0 rlineto               
105     closepath                   
106     fill                        
107 } bind def
109 % Font reincoding utilities
111 % ISOLatin1Encoding, extended with remaining uncoded glyphs
112 /ISOLatin1Extended [
113     /.notdef /Lslash /lslash /OE /oe /Scaron /scaron /Zcaron /zcaron
114     /Ydieresis /trademark /bullet /dagger /daggerdbl /ellipsis /emdash
115     /endash /fi /fl /florin /fraction /guilsinglleft /guilsinglright
116     /perthousand /quotedblbase /quotedblleft /quotedblright
117     /quotesinglbase /quotesingle /.notdef /.notdef /.notdef /space
118     /exclam /quotedbl /numbersign /dollar /percent /ampersand
119     /quoteright /parenleft /parenright /asterisk /plus /comma /minus
120     /period /slash /zero /one /two /three /four /five /six /seven /eight
121     /nine /colon /semicolon /less /equal /greater /question /at /A /B /C
122     /D /E /F /G /H /I /J /K /L /M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z
123     /bracketleft /backslash /bracketright /asciicircum /underscore
124     /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o /p /q /r /s
125     /t /u /v /w /x /y /z /braceleft /bar /braceright /asciitilde
126     /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
127     /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
128     /.notdef /.notdef /.notdef /dotlessi /grave /acute /circumflex
129     /tilde /macron /breve /dotaccent /dieresis /.notdef /ring /cedilla
130     /.notdef /hungarumlaut /ogonek /caron /space /exclamdown /cent
131     /sterling /currency /yen /brokenbar /section /dieresis /copyright
132     /ordfeminine /guillemotleft /logicalnot /hyphen /registered /macron
133     /degree /plusminus /twosuperior /threesuperior /acute /mu /paragraph
134     /periodcentered /cedilla /onesuperior /ordmasculine /guillemotright
135     /onequarter /onehalf /threequarters /questiondown /Agrave /Aacute
136     /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla /Egrave /Eacute
137     /Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex /Idieresis /Eth
138     /Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply
139     /Oslash /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn
140     /germandbls /agrave /aacute /acircumflex /atilde /adieresis /aring
141     /ae /ccedilla /egrave /eacute /ecircumflex /edieresis /igrave
142     /iacute /icircumflex /idieresis /eth /ntilde /ograve /oacute
143     /ocircumflex /otilde /odieresis /divide /oslash /ugrave /uacute
144     /ucircumflex /udieresis /yacute /thorn /ydieresis
145 ] def
147 % `new-font-name' `encoding-vector' `old-font-name' RE -
148 /RE {
149     findfont
150     dup maxlength dict begin {
151         1 index /FID ne { def } { pop pop } ifelse
152     } forall
153     /Encoding exch def
154     dup /FontName exch def
155     currentdict end definefont pop
156 } bind def
158 % Text handling functions, select the font and scale it, then we need
159 % only to apply the appropriate transformations to get the text
160 % justified into the right spots.  The bad thing here is that we don't
161 % do any kerning, so the output may look a bit strange.
163 % compute the height of one character and return lly and ury
164 % (char) charheight lly ury
165 /charheight {
166     gsave                       % push graphics state
167         newpath                 % clear current path
168         0 0 moveto              % Set current point
169         false charpath          % get path
170         flattenpath             % flatten path
171         pathbbox                % stack = llx lly urx ury
172         exch pop                % stack = llx lly ury
173         3 -1 roll pop           % stack = lly ury
174     grestore                    % pop graphics state
175 } bind def
177 % compute the height of a string, one character at a time
178 % (string) stringheight lly ury
179 /lly 0.0 def
180 /ury 0.0 def
182 /stringheight {
183     /lly 0.0 def                        % initial value of heightmin
184     /ury 0.0 def                        % initial value of heightmax
185     {                           % work through string
186         ( ) dup 0 4 -1 roll put % create one character string
187         charheight              % measure it's height
188         dup ury gt {            % if ury gt heightmax
189             /ury exch def       % update with new value
190         } {
191             pop                 % else discard ury
192         } ifelse
193         dup lly lt {            % if lly lt heightmin
194             /lly exch def       % update with new value
195         } {
196             pop                 % else discard lly
197         } ifelse
198     } forall
199     lly ury                     % Return the results
200 } bind def
202 % calculate the string width taking into account the escapes.
203 /mystrx 0.0 def
204 /mystry 0.0 def
205 /mystresc false def
207 /mystringwidth {
208     /mystrx 0.0 def
209     /mystry 0.0 def
210     /mystresc false def
211     {                           % work through string
212         % did we process the escape character last?
213         mystresc {
214             % last character was escape
215             % handle the escape
216             % is it an _ = 95?
217             dup 95 eq {
218                 pop  % we don't need the character anymore
219                 % toggle drawing overbars
220                 0.0 0.0 % make it like it never happened...
221             } {
222                 % otherwise measure the character 
223                 (\\ ) dup 1 4 -1 roll put % count a \ and the character
224                 stringwidth
225             } ifelse
226             % and reset the flag
227             /mystresc false def
228         } {
229             % last character was not escape
230             % is this escape
231             dup 92 eq {
232                 % yes, escape character, set flag
233                 /mystresc true def
234                 pop % drop character
235                 0.0 0.0 % make like this character has no width and height
236             } {
237                 ( ) dup 0 4 -1 roll put % create one character string
238                 stringwidth             % measure it's height/width
239             } ifelse
240         } ifelse
241         % accumulate x and y movements
242         mystry add /mystry exch def
243         mystrx add /mystrx exch def
244     } forall
245     mystrx mystry % drop results on stack
246 } bind def
248 % Render a string with overbars
250 /escaped false def
251 /drawoverbar false def
252 /fontsize 0.0 def
254 %string1 string2 append -
255 /append {
256     2 copy length exch length add % find new length
257     string dup % string1 string2 string string
258     4 2 roll % string string string1 string2
259     2 index 0 3 index
260     % string string string1 string2 string 0 string1
261     putinterval % string string string1 string2
262     exch length exch putinterval
263 } bind def
265 % If drawoverbar is set, draw a line of the same length as the given string
266 % string overbarshowline -
267 /overbarshowline {
268     % print overbar if necessary
269     stringwidth pop 0
270     drawoverbar {
271         rlineto
272         gsave stroke grestore
273     } {
274         rmoveto
275     } ifelse
276 } bind def
278 % Draws overbars for the given string, then shows the string itself
279 % string overbarshow
280 /overbarshow {
281     /overbarshowacc () def
282     /overbarshowtxt () def
284     gsave
285     fontsize 10.0 div setlinewidth
286     0 fontsize rmoveto  % move to (0,overbarheight)
288     {                           % work through string
289         escaped {
290             % the last character was the escape
291             % handle the escape
292             % is it an _ = 95?
293             dup 95 eq {
294                 pop  % we don't need the character anymore
295                 overbarshowacc overbarshowline
296                 % toggle drawing overbars
297                 /drawoverbar drawoverbar not def
299                 % Append the contents off the accumulator to the text
300                 % string we're eventually going to show
301                 /overbarshowtxt overbarshowtxt overbarshowacc append def
303                 % clear accumulator
304                 /overbarshowacc () def
305             } {
306                 % add to accumulator
307                 (\\ ) dup 1 4 -1 roll put
308                 overbarshowacc exch append
309                 /overbarshowacc exch def
310             } ifelse
311             % and reset the flag
312             /escaped false def
313         } {
314             % check for escape character \ = 92
315             dup 92 eq {
316                 % yes, escape character, set flag
317                 /escaped true def
318                 pop % drop character
319             } {
320                 % add to accumulator
321                 ( ) dup 0 4 -1 roll put
322                 overbarshowacc exch append
323                 /overbarshowacc exch def
324             } ifelse
325         } ifelse
326     } forall
327     % Catch any leftovers
328     overbarshowacc overbarshowline
329     overbarshowtxt overbarshowacc append
331     grestore
332     show
333 } bind def
336 % hcenter rjustify vcenter vjustify spacing [(line1) (line2) ... ] rot x y size text -
337 /stringw 0.0 def
338 /stringh 0.0 def
339 /spacing 0.0 def
340 /strings [ ] def
341 /stringtxt ( ) def
342 /stringcount 0 def
343 /rot 0.0 def
345 /text {
346     gsave               % save state for later
347     /drawoverbar false def      % start by not drawing overbars
349     dup /fontsize exch def  % save font size for corrections later
350     % do font selection 
351     /gEDAFont findfont
352     exch scalefont
353     setfont
355     % set up coordinates
356     translate           % move origin to given point
357     rotate              % rotate so that text is drawn
358     0 0 moveto
359     dup length /stringcount exch def                    % Get number of strings
360     /strings exch def                                   % save strings
361     /spacing exch def
362     % do we have more than 1 string to render?
363     stringcount 1 eq {
364         /stringtxt strings aload pop def                % get the string 
365         /stringw stringtxt mystringwidth pop neg def    % get the -width
366         /stringh stringtxt stringheight exch pop neg def% get the -height
368         % First do vertical calculations
369         % hcenter rjustify vcenter vjustify 
370         % vertical justification
371         { 0 stringh rmoveto } if 
372         % vertical center
373         { 0 stringh 0.3571425 mul rmoveto } if  % not 0.5, so that
374                                                 % it looks nicer
375         % Then do horizontal calculations
376         % right justify
377         { stringw 0 rmoveto } if
378         % center
379         { stringw 2.0 div 0 rmoveto } if
380         % Draw the text
381         stringtxt overbarshow
382     } {
383         % More than one line, compute bounding box for the text
385         % vertical height, don't use the actual hieght of the characters
386         % assume that the user wants to make the baselines line up with two
387         % text boxes placed side by side
388         /stringh stringcount spacing mul neg def
389         % Now figure out horizontal size, this amounts to keeping track
390         % of the longest string
391         /stringw 0.0 def
392         strings {
393             mystringwidth pop
394             dup stringw gt {
395                 /stringw exch def
396             } {
397                 pop
398             } ifelse
399         } forall
400         /stringw stringw neg def        % get the -width
401         
402         % First do vertical calculations
403         % hcenter rjustify vcenter vjustify 
404         % vertical justification
405         { 0 stringh fontsize add rmoveto } if 
406         % vertical center
407         { 0 stringh 0.5 mul rmoveto } if 
408         % Then do horizontal calculations
409         % right justify
410         { stringw 0 rmoveto } if
411         % center
412         { stringw 2.0 div 0 rmoveto } if
413         % now move up to the first line and begin rendering
414         0 stringcount 1 sub spacing mul rmoveto
415         strings {
416             gsave               % Save starting point
417             overbarshow         % render the text
418             grestore
419             0 spacing neg rmoveto
420         } forall
421     } ifelse
422     grestore    % Restore old state
423 } bind def