summaryrefslogtreecommitdiff
path: root/support/lametex/src/format.ps
blob: a00cecf7ddf371df203f124895ba224b2626dc04 (plain)
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
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
%! This is a PostScript library meant to be printed only with other files %%%
%% Postscript Code by Jonathan Monsarrat Copyright 1992
%% permission given for anything except selling this or deleting the header.
%% This is the LameTeX Formatter, uses the LaTeX language
% Depends on "EndPage" and "StartPage" to be set up by a page formatter

/formatdict 100 dict def   % This should be 77?

formatdict begin
/wlist 100 array def     % Maximum of 100 words on a line
%% Better give these variables default values in case we try to
%% do an EndPage but they have not yet been defined

/baselineskip 200 def /wlen 0 def /baselineskip 0 def /bottommargin 0 def
/parindent 0 def /justify 0 def /rightmargin 0 def /leftmargin 0 def
/topmargin 0 def /parskip 0 def /newfontcmd 1 def /para 0 def
/vtotal 0 def /wordlen 0 def /ypos 0 def /ytemp 0 def

%%%%%%%%%%%%%%%%    num   InitWord    -  %%%%%%%%%%%%%%%%%%%%%%%
% InitWord takes an setflat values and flattens the current path
% It also defines some globals that will get "NextWord" up and running
/InitWord
{
  /xpos currentflat def % Save current flatness
  PageShape setflat flattenpath 
  % gsave stroke grestore  % Uncomment this line to show the margin path
  /coords Approx def
  pathbbox   % It the current path is bigger than the margins, widen them!
  dup TM gt { /TM exch def } { pop } ifelse
  dup RM gt { /RM exch def } { pop } ifelse
  dup BM lt { /BM exch def } { pop } ifelse
  dup LM lt { /LM exch def } { pop } ifelse

  xpos setflat   % Restore flatness.
  false fontnames newfontcmd get cvx exec
  /xlocs [ ] def 
  /welem 1 def /wlen 0 def /woids 0 def 
  /eslot LM def 
  /ypos TM topmargin sub def
  /vtotal 0 def
  /xpos 0 def /nxpos 0 def
  wlist 0 [ newfontcmd false ] put
  /wtemp 0 def
  NextSpace pop 
} bind def

%%%%%%%%%%%%%%%%%%%%%  -   NewXSpace    bool %%%%%%%%%%%%%%%%%%%%%%
% If there's "room on the bottom" as defined by xlocs, check to see if
% there's "room on the top" as defined by NewXSpace. Returns success boolean.
/NewXSpace
{
  nxpos newxlocs length 1 sub lt 
  {
    newxlocs nxpos 2 getinterval {} forall exch
    /nxpos nxpos 2 add def  
% If there's any intersection of top and bottom 'good places' set bslot, eslot
    dup xa le { pop xa } if leftmargin add /bslot exch def 
    dup xb ge { pop xb } if rightmargin sub /eslot exch def 
    bslot eslot lt { true } { NewXSpace } ifelse 
  }
  {
    false 
  } ifelse 
} bind def

%%%%%%%%%%%%%%%  -   NextSpace   bool  %%%%%%%%%%%%%%%%%%%%%%
% NextSpace defines the next space available for writing by
% setting ypos to the Y location and bslot and eslot to the beginning
% and end of the next open text writing area. Returns success boolean.
/NextSpace
{
   xpos xlocs length 1 sub lt      % are there any X's left on current line
   {
      /xa xlocs xpos get def 
      /xb xlocs xpos 1 add get def 
      NewXSpace 
      { true } 
      { 
        /nxpos 0 def 
        /xpos xpos 2 add def 
        NextSpace 
      } ifelse 
   }
   {
      ypos  % Leave on the stack for later comparison
      /ypos ypos
      vspace 0 eq
      {
        baselineskip para { parskip add } if /vtotal baselineskip def
      }
      {
        vspace /vspace 0 def
      } ifelse
      sub def 
      ypos BM bottommargin add ge 
      {
        /newxlocs coords 3 -1 roll 4 add true CheeseWhiz def 
        /xlocs coords ypos 4 sub true CheeseWhiz def 
        /xpos 0 def /nxpos 0 def 
        NextSpace 
      }
      {
        pop false
      } ifelse 
   } ifelse 
  % if we're doing a paragraph and the NextSpace isn't big enough
  % for the indentation, then choose a new space.
  % if found-space and para and justify
  dup para justify 102 eq and and   % 102 is ascii 'f' for FULL JUSTIFY
  { /bslot bslot parindent add def bslot eslot gt 
        { pop NextSpace pop 
        } if
  } if
  /para false def 
} bind def

%%%%%%%%%%%%%%%%%%%%%%% -  PrintWordList  -  %%%%%%%%%%%%%%%%%%%%%%%%%%%%
% PrintWordList prints the words stored in array "wlist" at Y location ypos
% with full justification between X locations bslot and eslot.
/PrintWordList
{
  /vtotal 0 def
  woids 0 ne
  { 
    % Legal values for /justify are (l)eft (r)ight (f)ull (c)enter in ASCII
    justify 99 eq  % 99 is ascii 'c' for CENTERED
    {
      bslot eslot bslot sub wlen sub 2 div add ypos moveto
    }
    {
      bslot justify 114 eq { eslot bslot sub wlen sub add } if   % 114 is 'r'
      ypos moveto 
    } ifelse
    /sp eslot bslot sub wlen sub woids div def
    0 1 welem 1 sub 
    {
      wlist exch get
      dup type /stringtype eq
      {
        SHOWIT ( ) stringwidth pop 0 rmoveto 
        justify 102 eq { sp 0 rmoveto } if  % 102 is ascii 'f'
      }
      {
        dup type /arraytype eq
        {
          { } forall
          {
             ( ) stringwidth pop neg 0 rmoveto 
             justify 102 eq { sp neg 0 rmoveto } if  % 102 is ascii 'f'
	  } if
          fontnames exch get cvx true exch exec
	}
        {
           0 rmoveto
	} ifelse
      } ifelse 
    } for
     wlist 0 [ newfontcmd false ] put
     /welem 1 def /wlen 0 def /woids 0 def 
  } if
} def

%%%%%%%%%%%%%%%%%%%%%%%%%  -   PrintClose  -  %%%%%%%%%%%%%%%%%%%%%%%%
% PrintClose prints the words stored in the array "wlist" at Y location ypos
% starting at X location bslot with left justification.
/PrintClose
{
  justify 102 eq  % 102 is ascii 'f'
  {
    /justify 108 def % 108 is ascii 'l' for flushleft
    PrintWordList 
    /justify 102 def
  }
  {
    PrintWordList 
  } ifelse
} bind def

%%%%%%%%%%%%%%%%  string  Parse  - %%%%%%%%%%%%%%%%%%%%%%%%
% Parse breaks a string into words based on spaces, passing each to NextWord
/Parse
{
   dup length 0 eq   % kill extra spaces by shaving them until null string
   { pop }
   { ( ) search { Parse pop Parse } { NW } ifelse } ifelse
} bind def

%%%%%%%%%%%%%%%%%%%%%%%  string  NextWord  - %%%%%%%%%%%%%%%%%%%%%%
% NextWord appends the string to an array of words
% and tries to place the text inside an arbitrary path (which was analyzed
% by InitWord). It's meant to be an iterative part of a long list of
% "string NextWord" sets which justifies text inside any closed path.
/NextWord
{
   /word exch def word stringwidth pop /wordlen exch def
   GrabSpace
} bind def

%%%%%%%%%% Takes a horizontal distance and a string for positioning
/GrabSpace
{
   wordlen wlen add 
   eslot bslot sub gt 
   {
     PrintWordList word type /stringtype ne { /welem 0 def } if
     NextSpace 
     {
       GrabSpace
     } 
     {
       % Have reached end of page
       ENDPAGE STARTPAGE
       /ypos baselineskip ypos add def /vtotal baselineskip def NEWLINE
       GrabSpace
     } ifelse 
   }
   {
     word type /stringtype eq
     { 
       wlist welem word put /welem welem 1 add def
       /wlen wlen ( ) stringwidth pop add def
       /woids woids 1 add def 
      } if
      /wlen wlen wordlen add def 
   } ifelse 
} def

%%%%%%%%%%%%%%%% xwidth HSpace  - %%%%%%%%%%%%%%
% Adds to the current wlen and adds the right thing in the wlist array
/HSpace
{
   dup wlen add /wlen exch def
   wlist welem 3 -1 roll put /welem welem 1 add def
} bind def


%%%%%%%%%%%%%%%%% size type NewFont %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% NewFont sets a new font, given a type and size
/NewFont
{
  { } forall /word exch def /newfontcmd exch def 
  word wlist welem [ newfontcmd 5 -1 roll ] put /welem welem 1 add def
  false fontnames newfontcmd get cvx exec
  word true eq woids 0 gt and
  { 
       /wlen wlen ( ) stringwidth pop sub def
  } if
} bind def

%%%%%%%%%%%%%% x y READJUST %%%%%%%%%%%%%%
% Readjusts the line down by given amountif big fonts are being placed
% in a small vertical space, and across if a horizontal space is being added.
/READJUST
{
   wtemp type /arraytype eq    % Don't do recursive READJUSTs
   {
      pop pop
   }
   {
      /vspace exch def /wordlen exch def
      /welem welem 1 sub def
      GrabSpace vspace 0 ne { SKIPLINE } if % Skip to a new page if needed
      /wtemp wlist def /woids 0 def /wlen 0 def
      0 1 welem /welem 0 def
      {
        wtemp exch get
        dup type /stringtype eq
        {
          NextWord
        }
        {
           dup type /arraytype eq
           {
             NewFont
           }
           {
             HSpace
           } ifelse
        } ifelse
      } for
      wordlen HSpace
      /wtemp 0 def
   } ifelse
} bind def

%%%% Skipline skips a given amount of vertical space
/SKIPLINE
{
   vspace 0 eq vspace vtotal gt or
   {
     vspace vtotal gt
     {
        /vspace vspace vtotal sub /vtotal vspace def def
     } if
  
     /ytemp ypos def
     true
     20  % repeat
     {
        NextSpace not   % did it get a new line successfully?
        {  
           ENDPAGE STARTPAGE
           /ypos baselineskip ypos add def /vtotal baselineskip def NEWLINE
        } if
        ypos ytemp ne { pop false exit } if
     } repeat
  
     {       % Did the repeat "fail" by falling off the end?
        erasepage
        grestoreall
        /Times-Roman findfont 20 scalefont setfont
        50 100 moveto
        (Could not place words anywhere on the virtual page) show
        showpage
        quit
     } if
   } if
} bind def

%%%%%%%%%%%%%%%%%%%%%
% Some startup definitions
/para true def
/vspace 0 def

% User command definitions, meant to be called from outside
/NW { NextWord } bind def
/SHOWIT { show } bind def
/NEWLINE { PrintWordList NextSpace pop } def
/NEWPARA
{
   PrintClose
   /para true def
   SKIPLINE
} bind def

/ENUMERATE { dup stringwidth pop 9 add 
             bslot exch sub ypos moveto show } bind def
/BULLET
{
   newpath bslot 9 sub
   ( ) stringwidth pop 1.7 div dup ypos add exch
   0 360 arc currentgray 0 setgray fill setgray
} bind def

/TIMESROMAN
{
  pop  /Times-Roman findfont 10 scalefont setfont
} bind def

/BASELINESKIP
{
  /baselineskip exch def
} bind def

/STARTPAGE
{
  end
  /savetype save def
  StartPage
  formatdict begin
  InitWord
} def

/ENDPAGE
{
  PrintClose
  % Put all the variables we want to save on the stack
  baselineskip bottommargin parindent justify rightmargin leftmargin
  topmargin parskip newfontcmd para wordlen ypos ytemp
  word type /stringtype eq
  {
    mark word {} forall true
  }
  {
    word false
  } ifelse
  end

  savetype restore

  formatdict
  begin
     {
       counttomark string /word exch def
       counttomark 1 sub -1 0
       {
         exch word 3 1 roll put  % Builds word out of individual characters
       } for
       pop
     }
     {
       /word exch def
     } ifelse
   
     % Recover all the variables
     /ytemp exch def /ypos exch def /wordlen exch def
     /para exch def /newfontcmd exch def
     /parskip exch def /topmargin exch def /leftmargin exch def
     /rightmargin exch def /justify exch def /parindent exch def
     /bottommargin exch def /baselineskip exch def
  end
  EndPage
  formatdict begin
} def