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