1 /*
2  * AMIGA.C: This is the Graphics Window interface to MetaFont for online
3  * displays on the Commodore Amiga.  This file was written by Edmund Mergl
4  * for his Amiga port of TeX 3.1 and MetaFont 2.7 from the original Unix
5  * sources (see Fish Disks 611-616).
6  *
7  * Some modifications and improvements were made since 1993 by Andreas and
8  * Stefan Scherer, Abt-Wolf-Strasse 17, 96215 Lichtenfels, Germany.  The
9  * most recent entries from top to bottom always superseed their ancestors,
10  * just read this as a bit of history:
11  *
12  *   August 12, 1993:
13  *
14  *   - We use the `memory hack', so the values for `screenwidth'
15  *     and `screendepth' are to be found in `mfmemory.config'.  The
16  *     display height should be set to an InterLace value, this will
17  *     be dealt with by `lacefactor' (see below).
18  *
19  *   - The display window is no longer resizeable, because no
20  *     `screenupdate' is called and the picture is destroyed.
21  *
22  *   - Based on ideas by Stefan Becker used in his famous MetaFont port
23  *     to the Amiga of 1991 (see Fish Disk 486) there is a variable
24  *     `scalefactor', which can be set to a (small) positiv integer in
25  *     `mfmemory.config'.  This results in a reduced size of the displayed
26  *     characters, so that large font pictures can be drawn on
27  *     small-sized screens (although some distortions are possible).
28  *
29  *   - By replacing `Move' and `Draw' with `WritePixelLine' and friends
30  *     the speed of the display was heavily increased.
31  *
32  *   - The display screen is totally controlled by `screenwidth' and
33  *     `screendepth' from `mfmemory.config', when you set `screen_rows'
34  *     and `screen_cols' both to the maximum value `4095' in your local
35  *     device modes file.  MetaFont takes the smaller of these pairs.
36  *
37  *   - `blankrectangle' *always* set the complete display window to the
38  *     background color, not only the area specified by `left', `right',
39  *     `top', and `bottom'.  These MetaFont coordinates are now obeyed.
40  *
41  *   September 11, 1993:
42  *
43  *   - The changes for `Computers and Typesetting -- Volume A-E' provided
44  *     by Addison-Wesley Publishing Company resulted in MetaFont 2.71.
45  *     This caused a change in the window title.
46  *
47  *   October 22, 1993:
48  *
49  *   - The official version 2.71 has the same window title.  :-)
50  *
51  *   January 28, 1994:
52  *
53  *   - Although SAS/C has an AutoOpen feature for Amiga libraries,
54  *     it is better to define the library bases explicitly.
55  *
56  *   February 15, 1995:
57  *
58  *   - Here's my new address:
59  *     Andreas Scherer, Rolandstra�e 16, 52070 Aachen, Germany.
60  *     <scherer@genesis.informatik.rwth-aachen.de> (Internet).
61  *   - Make `amiga.c' compliant with the syntax of the other modules
62  *     in the Web2C 6.1 distribution.
63  *
64  *   February 19, 1995:
65  *
66  *   - `close_all()' must not have arguments, because we want to
67  *     link it into the `atexit()' function list.
68  *   - To distinguish this version from the old distribution, the
69  *     window title is modified.
70  *
71  *   March 23, 1995:
72  *
73  *   - MetaFont has the new version number 2.718.
74  *
75  *   April 9, 1995:
76  *
77  *   - rename `screenheight' to `screendepth' for consistency.
78  *
79  *   October 10, 1995:
80  *
81  *   - Yet another change in my address, now it's a UNIX CIP pool:
82  *     <scherer@physik.rwth-aachen.de>
83  *   - Cleanup for the new web2c release.
84  *
85  *   January 20, 2010:
86  *
87  *   - MetaFont has the new version number 2.718281.
88  */
89 
90 #define EXTERN extern
91 
92 #include "../mfd.h"
93 
94 #ifdef AMIGAWIN /* Whole file */
95 
96 #include <proto/exec.h>
97 #include <proto/graphics.h>
98 #include <proto/intuition.h>
99 
100 struct GfxBase *GfxBase;
101 struct IntuitionBase *IntuitionBase;
102 
103 struct Screen *Scr;
104 struct Window *Win;
105 
106 struct BitMap tempbm;
107 struct RastPort temprp;
108 
109 UBYTE *linearray;
110 
111 int scaledwidth  = 0;
112 int scaledheight = 0;
113 
114 #ifndef scalefactor
115 #define scalefactor 1
116 #endif
117 
118 /*
119  * The configuration `mf.mcf' of AmiWeb2C holds values for `screenwidth'
120  * and `screendepth' that always refer to an InterLace screen.  In case
121  * you open the display on a non-InterLaced screen, only half the lines
122  * are shown to you.  This is automatically done by reading the screen
123  * information and setting `lacefactor'.
124  */
125 int lacefactor;
126 
127 #define BACKGROUNDCOLOR 0
128 #define PENCOLOR        1
129 
130 #define PUBSCREEN 0
131 
132 /*
133  * Allocating memory for the array used in `WritePixelLine' needs
134  * WORD-aligned arguments.
135  */
136 #define ALIGN_SIXTEEN_BIT(A) ((((A)+15)/16)*16)
137 #ifndef min
138 #define min(a,b) ((a)<(b)?(a):(b))
139 #endif
140 
141 /*
142  * CLOSE_ALL: Clean up on MetaFont termination.  This routine has to be
143  * called just before leaving the program, which is done automatically
144  * when it gets entered into the `atexit' function list.  (See below.)
145  */
close_all(void)146 void close_all(void)
147 {
148   if (linearray)        free(linearray);
149   if (tempbm.Planes[0]) FreeRaster(tempbm.Planes[0], scaledwidth, 1);
150   if (Win)              CloseWindow(Win);
151   if (GfxBase)          CloseLibrary((struct Library *)GfxBase);
152   if (IntuitionBase)    CloseLibrary((struct Library *)IntuitionBase);
153 
154 } /* close_all() */
155 
156 #include <mfdisplay.h>
157 
158 /*
159  * INITSCREEN: Initialize the physical display window on the WorkBench
160  * screen of the Commodore Amiga.  Open the necessary libraries and open
161  * the window according to `screenwidth' and `screendepth' as given in
162  * the configuration file `mf.mcf'.  For this purpose, the
163  * `OpenWindowTagList' routine was replaced with `OpenWindowTags'.
164  * The `WFLG_SIZEGADGET' window flag has been removed; resizing the
165  * window kills the picture and never triggered an `updatescreen'.
166  */
mf_amiga_initscreen(void)167 int mf_amiga_initscreen(void)
168 {
169 #ifdef DEBUG
170   printf("\ninitscreen()\n");
171 #endif
172 
173   /*
174    * Make sure the resources are correctly returned to the system
175    * when leaving the program.
176    */
177   if(atexit(&close_all)) { /* Can't happen. */
178     fprintf(stderr, "Exit trap failure! (close_all)\n");
179     uexit(1);
180     }
181 
182   if (!(IntuitionBase = (struct IntuitionBase *)
183     OpenLibrary((unsigned char *)"intuition.library",(unsigned long)37L)))
184   {
185     fprintf(stderr,"\nCan't open intuition library. V37 required.\n");
186     close_all();
187     return(FALSE);
188   }
189 
190   if (!(GfxBase = (struct GfxBase *)
191     OpenLibrary((unsigned char *)"graphics.library",(unsigned long)37L)))
192   {
193     fprintf(stderr,"\nCan't open intuition library. V37 required.\n");
194     close_all();
195     return(FALSE);
196   }
197 
198   if (!(Scr = LockPubScreen(PUBSCREEN)))
199   {
200     fprintf(stderr,
201       "\nCan't get lock on public screen (%d).\n", PUBSCREEN);
202     close_all();
203     return(FALSE);
204   }
205 
206   scaledwidth  = screenwidth/scalefactor;
207   scaledheight = screendepth/scalefactor;
208 
209   lacefactor  = ((Scr->ViewPort.Modes & LACE) ? 1 : 2);
210 
211   if (!(Win = (struct Window *)OpenWindowTags( NULL,
212     WA_InnerWidth,  scaledwidth,
213     WA_InnerHeight, scaledheight/lacefactor,
214     WA_Flags,       WFLG_DRAGBAR|WFLG_DEPTHGADGET,
215     WA_AutoAdjust,  FALSE,
216     WA_Title,       (ULONG)" MetaFont V2.718281 Online Display",
217     WA_PubScreen,   (ULONG)Scr,
218     TAG_DONE)))
219   {
220 
221     fprintf(stderr,
222        "\nCan't open online display window at size %d times %d.\n"
223 #ifdef VARMEM
224        "Change your configuration file.\n",
225 #else
226        "If you really absolutely need more capacity,\n"
227        "you can ask a wizard to enlarge me.\n",
228 #endif
229     screenwidth,screendepth);
230 
231     close_all();
232     return(FALSE);
233   }
234 
235   InitBitMap(&tempbm, 1, scaledwidth, 1);
236 
237   tempbm.Planes[0] = NULL;
238 
239   if(!(tempbm.Planes[0] = (PLANEPTR)AllocRaster(scaledwidth, 1)))
240      return(FALSE);
241 
242   InitRastPort(&temprp);
243 
244   temprp.BitMap = &tempbm;
245 
246   if(!(linearray = (UBYTE *)
247     calloc(ALIGN_SIXTEEN_BIT(scaledwidth),sizeof(UBYTE))))
248     return(FALSE);
249 
250   UnlockPubScreen(NULL, Scr);
251 
252 #ifdef DEBUG
253    printf("initscreen() ok\n");
254 #endif
255 
256    return(TRUE);
257 
258 } /* mf_amiga_initscreen() */
259 
260 /*
261  * UPDATESCREEN: I really don't know what this function is supposed
262  * to do.
263  */
mf_amiga_updatescreen(void)264 void mf_amiga_updatescreen(void)
265 {
266 #ifdef DEBUG
267   printf("updatescreen()\n");
268 #endif
269 } /* mf_amiga_update_screen() */
270 
271 /*
272  * BLANKRECTANGLE: Reset the drawing rectangle bounded by
273  * ([left,right],[top,bottom]) to the background color.
274  */
mf_amiga_blankrectangle(screencol left,screencol right,screenrow top,screenrow bottom)275 void mf_amiga_blankrectangle(screencol left, screencol right,
276   screenrow top, screenrow bottom)
277 {
278 #ifdef DEBUG
279   printf("blankrectangle() - left: %d right: %d top: %d bottom: %d\n",
280     left, right, top, bottom);
281 #endif
282 
283   SetAPen (Win->RPort, BACKGROUNDCOLOR);
284   RectFill(Win->RPort,
285     (SHORT)(Win->BorderLeft + left/scalefactor),
286     (SHORT)(Win->BorderTop + top/(scalefactor*lacefactor)),
287     (SHORT)(Win->BorderLeft + right/scalefactor - 1),
288     (SHORT)(Win->BorderTop + bottom/(scalefactor*lacefactor) - 1));
289 } /* mf_amiga_blankrectangle() */
290 
291 /*
292  * PAINTROW: Paint a `row' starting with color `init_color', up to the
293  * next transition specified by `transition_vector', switch colors, and
294  * continue for `vector_size' transitions.  It now only
295  * draws into the display window when a new raster line will be affected.
296  * A lot of pre-drawing and inter-drawing calculations and conditionals
297  * are evaluated to prepare a fast and clean drawing under the most
298  * circumstances to be expected on the Amiga.  InterLace/Lace is taken
299  * care of and the sizes are set appropriately not to clobber the borders.
300  * (Don't ask me why this works; at least on my machine with my config.)
301  */
mf_amiga_paintrow(screenrow row,pixelcolor init_color,transspec transition_vector,screencol vector_size)302 void mf_amiga_paintrow(screenrow row, pixelcolor init_color,
303   transspec transition_vector, screencol vector_size)
304 {
305   int start, scaledstart, scaledrow, scaledlaced;
306   register int i=0, j=0, col, color;
307 
308 #ifdef DEBUG
309     printf("paintrow() - vector size: %d\n", vector_size);
310 #endif
311 
312   color       = ((0 == init_color) ? BACKGROUNDCOLOR : PENCOLOR);
313   scaledlaced = scalefactor * lacefactor;
314   start       = *transition_vector++;
315   scaledstart = start / scalefactor;
316   scaledrow   = row / scaledlaced;
317 
318   ReadPixelLine8(Win->RPort, Win->BorderLeft + scaledstart,
319     Win->BorderTop + scaledrow, scaledwidth - scaledstart,
320     linearray, &temprp);
321 
322   if(scalefactor>1) {
323 
324     do {
325       for(col = *transition_vector++; i<col-start; i++) {
326         linearray[j] |= color;
327         if((i%scalefactor)==0) j++;
328       }
329 
330       color = PENCOLOR - color;
331 
332 #ifdef DEBUG
333       printf("move col: %d row: %d ", col, row);
334       printf("draw col: %d row: %d\n", (*transition_vector)-1, row);
335 #endif
336 
337     } while (--vector_size);
338 
339     if(i >= col-start) linearray[++j] |= color;
340 
341   } else {
342 
343     do {
344       for(col = *transition_vector++; j<col-start; j++) {
345          linearray[j] |= color;
346          }
347 
348       color = PENCOLOR - color;
349 
350 #ifdef DEBUG
351       printf("move col: %d row: %d ", col, row);
352       printf("draw col: %d row: %d\n", (*transition_vector)-1, row);
353 #endif
354 
355     } while (--vector_size);
356   }
357 
358   if( (  Win->BorderTop + scaledrow ) <
359       (  Win->Height - Win->BorderBottom ) )
360     WritePixelLine8(Win->RPort, Win->BorderLeft + scaledstart,
361       Win->BorderTop + scaledrow,
362       min(Win->Width - Win->BorderLeft - Win->BorderRight - scaledstart,j),
363       linearray, &temprp);
364 
365 } /* mf_amiga_paintrow() */
366 
367 #else
368 int amiga_dummy;
369 #endif /* AMIGAWIN */
370