Back to index

tetex-bin  3.0
amiga.c
Go to the documentation of this file.
00001 /*
00002  * AMIGA.C: This is the Graphics Window interface to MetaFont for online
00003  * displays on the Commodore Amiga.  This file was written by Edmund Mergl
00004  * for his Amiga port of TeX 3.1 and MetaFont 2.7 from the original Unix
00005  * sources (see Fish Disks 611-616).
00006  *
00007  * Some modifications and improvements were made since 1993 by Andreas and
00008  * Stefan Scherer, Abt-Wolf-Strasse 17, 96215 Lichtenfels, Germany.  The
00009  * most recent entries from top to bottom always superseed their ancestors,
00010  * just read this as a bit of history:
00011  *
00012  *   August 12, 1993:
00013  *
00014  *   - We use the `memory hack', so the values for `screenwidth'
00015  *     and `screendepth' are to be found in `mfmemory.config'.  The
00016  *     display height should be set to an InterLace value, this will
00017  *     be dealt with by `lacefactor' (see below).
00018  *
00019  *   - The display window is no longer resizeable, because no
00020  *     `screenupdate' is called and the picture is destroyed.
00021  *
00022  *   - Based on ideas by Stefan Becker used in his famous MetaFont port
00023  *     to the Amiga of 1991 (see Fish Disk 486) there is a variable
00024  *     `scalefactor', which can be set to a (small) positiv integer in
00025  *     `mfmemory.config'.  This results in a reduced size of the displayed
00026  *     characters, so that large font pictures can be drawn on
00027  *     small-sized screens (although some distortions are possible).
00028  *
00029  *   - By replacing `Move' and `Draw' with `WritePixelLine' and friends
00030  *     the speed of the display was heavily increased.
00031  *
00032  *   - The display screen is totally controlled by `screenwidth' and
00033  *     `screendepth' from `mfmemory.config', when you set `screen_rows'
00034  *     and `screen_cols' both to the maximum value `4095' in your local
00035  *     device modes file.  MetaFont takes the smaller of these pairs.
00036  *
00037  *   - `blankrectangle' *always* set the complete display window to the
00038  *     background color, not only the area specified by `left', `right',
00039  *     `top', and `bottom'.  These MetaFont coordinates are now obeyed.
00040  *
00041  *   September 11, 1993:
00042  *
00043  *   - The changes for `Computers and Typesetting -- Volume A-E' provided
00044  *     by Addison-Wesley Publishing Company resulted in MetaFont 2.71.
00045  *     This caused a change in the window title.
00046  *
00047  *   October 22, 1993:
00048  *
00049  *   - The official version 2.71 has the same window title.  :-)
00050  *
00051  *   January 28, 1994:
00052  *
00053  *   - Although SAS/C has an AutoOpen feature for Amiga libraries,
00054  *     it is better to define the library bases explicitly.
00055  *
00056  *   February 15, 1995:
00057  *
00058  *   - Here's my new address:
00059  *     Andreas Scherer, Rolandstraße 16, 52070 Aachen, Germany.
00060  *     <scherer@genesis.informatik.rwth-aachen.de> (Internet).
00061  *   - Make `amiga.c' compliant with the syntax of the other modules
00062  *     in the Web2C 6.1 distribution.
00063  *
00064  *   February 19, 1995:
00065  *
00066  *   - `close_all()' must not have arguments, because we want to
00067  *     link it into the `atexit()' function list.
00068  *   - To distinguish this version from the old distribution, the
00069  *     window title is modified.
00070  *
00071  *   March 23, 1995:
00072  *
00073  *   - MetaFont has the new version number 2.718.
00074  *
00075  *   April 9, 1995:
00076  *
00077  *   - rename `screenheight' to `screendepth' for consistency.
00078  *
00079  *   October 10, 1995:
00080  *
00081  *   - Yet another change in my address, now it's a UNIX CIP pool:
00082  *     <scherer@physik.rwth-aachen.de>
00083  *   - Cleanup for the new web2c release.
00084  */
00085 
00086 #define EXTERN extern
00087 
00088 #include "../mfd.h"
00089 
00090 #ifdef AMIGAWIN /* Whole file */
00091 
00092 #include <proto/exec.h>
00093 #include <proto/graphics.h>
00094 #include <proto/intuition.h>
00095 
00096 struct GfxBase *GfxBase;
00097 struct IntuitionBase *IntuitionBase;
00098 
00099 struct Screen *Scr;
00100 struct Window *Win;
00101 
00102 struct BitMap tempbm;
00103 struct RastPort temprp;
00104 
00105 UBYTE *linearray;
00106 
00107 int scaledwidth  = 0;
00108 int scaledheight = 0;
00109 
00110 #ifndef scalefactor
00111 #define scalefactor 1
00112 #endif
00113 
00114 /*
00115  * The configuration `mf.mcf' of AmiWeb2C holds values for `screenwidth'
00116  * and `screendepth' that always refer to an InterLace screen.  In case
00117  * you open the display on a non-InterLaced screen, only half the lines
00118  * are shown to you.  This is automatically done by reading the screen
00119  * information and setting `lacefactor'.
00120  */
00121 int lacefactor;
00122 
00123 #define BACKGROUNDCOLOR 0
00124 #define PENCOLOR        1
00125 
00126 #define PUBSCREEN 0
00127 
00128 /*
00129  * Allocating memory for the array used in `WritePixelLine' needs
00130  * WORD-aligned arguments.
00131  */
00132 #define ALIGN_SIXTEEN_BIT(A) ((((A)+15)/16)*16)
00133 #ifndef min
00134 #define min(a,b) ((a)<(b)?(a):(b))
00135 #endif
00136 
00137 /*
00138  * CLOSE_ALL: Clean up on MetaFont termination.  This routine has to be
00139  * called just before leaving the program, which is done automatically
00140  * when it gets entered into the `atexit' function list.  (See below.)
00141  */
00142 void close_all(void)
00143 {
00144   if (linearray)        free(linearray);
00145   if (tempbm.Planes[0]) FreeRaster(tempbm.Planes[0], scaledwidth, 1);
00146   if (Win)              CloseWindow(Win);
00147   if (GfxBase)          CloseLibrary((struct Library *)GfxBase);
00148   if (IntuitionBase)    CloseLibrary((struct Library *)IntuitionBase);
00149 
00150 } /* close_all() */
00151 
00152 /*
00153  * INITSCREEN: Initialize the physical display window on the WorkBench
00154  * screen of the Commodore Amiga.  Open the necessary libraries and open
00155  * the window according to `screenwidth' and `screendepth' as given in
00156  * the configuration file `mf.mcf'.  For this purpose, the
00157  * `OpenWindowTagList' routine was replaced with `OpenWindowTags'.
00158  * The `WFLG_SIZEGADGET' window flag has been removed; resizing the
00159  * window kills the picture and never triggered an `updatescreen'.
00160  */
00161 boolean mf_amiga_initscreen(void)
00162 {
00163 #ifdef DEBUG
00164   printf("\ninitscreen()\n");
00165 #endif
00166 
00167   /*
00168    * Make sure the resources are correctly returned to the system
00169    * when leaving the program.
00170    */
00171   if(atexit(&close_all)) { /* Can't happen. */
00172     fprintf(stderr, "Exit trap failure! (close_all)\n");
00173     uexit(1);
00174     }
00175 
00176   if (!(IntuitionBase = (struct IntuitionBase *)
00177     OpenLibrary((unsigned char *)"intuition.library",(unsigned long)37L)))
00178   {
00179     fprintf(stderr,"\nCan't open intuition library. V37 required.\n");
00180     close_all();
00181     return(FALSE);
00182   }
00183 
00184   if (!(GfxBase = (struct GfxBase *)
00185     OpenLibrary((unsigned char *)"graphics.library",(unsigned long)37L)))
00186   {
00187     fprintf(stderr,"\nCan't open intuition library. V37 required.\n");
00188     close_all();
00189     return(FALSE);
00190   }
00191 
00192   if (!(Scr = LockPubScreen(PUBSCREEN)))
00193   {
00194     fprintf(stderr,
00195       "\nCan't get lock on public screen (%d).\n", PUBSCREEN);
00196     close_all();
00197     return(FALSE);
00198   }
00199 
00200   scaledwidth  = screenwidth/scalefactor;
00201   scaledheight = screendepth/scalefactor;
00202 
00203   lacefactor  = ((Scr->ViewPort.Modes & LACE) ? 1 : 2);
00204 
00205   if (!(Win = (struct Window *)OpenWindowTags( NULL,
00206     WA_InnerWidth,  scaledwidth,
00207     WA_InnerHeight, scaledheight/lacefactor,
00208     WA_Flags,       WFLG_DRAGBAR|WFLG_DEPTHGADGET,
00209     WA_AutoAdjust,  FALSE,
00210     WA_Title,       (ULONG)" MetaFont V2.718 Online Display",
00211     WA_PubScreen,   (ULONG)Scr,
00212     TAG_DONE)))
00213   {
00214 
00215     fprintf(stderr,
00216        "\nCan't open online display window at size %d times %d.\n"
00217 #ifdef VARMEM
00218        "Change your configuration file.\n",
00219 #else
00220        "If you really absolutely need more capacity,\n"
00221        "you can ask a wizard to enlarge me.\n",
00222 #endif
00223     screenwidth,screendepth);
00224 
00225     close_all();
00226     return(FALSE);
00227   }
00228 
00229   InitBitMap(&tempbm, 1, scaledwidth, 1);
00230 
00231   tempbm.Planes[0] = NULL;
00232 
00233   if(!(tempbm.Planes[0] = (PLANEPTR)AllocRaster(scaledwidth, 1)))
00234      return(FALSE);
00235 
00236   InitRastPort(&temprp);
00237 
00238   temprp.BitMap = &tempbm;
00239 
00240   if(!(linearray = (UBYTE *)
00241     calloc(ALIGN_SIXTEEN_BIT(scaledwidth),sizeof(UBYTE))))
00242     return(FALSE);
00243 
00244   UnlockPubScreen(NULL, Scr);
00245 
00246 #ifdef DEBUG
00247    printf("initscreen() ok\n");
00248 #endif
00249 
00250    return(TRUE);
00251 
00252 } /* mf_amiga_initscreen() */
00253 
00254 /*
00255  * UPDATESCREEN: I really don't know what this function is supposed
00256  * to do.
00257  */
00258 void mf_amiga_updatescreen(void)
00259 {
00260 #ifdef DEBUG
00261   printf("updatescreen()\n");
00262 #endif
00263 } /* mf_amiga_update_screen() */
00264 
00265 /*
00266  * BLANKRECTANGLE: Reset the drawing rectangle bounded by
00267  * ([left,right],[top,bottom]) to the background color.
00268  */
00269 void mf_amiga_blankrectangle(screencol left, screencol right,
00270   screenrow top, screenrow bottom)
00271 {
00272 #ifdef DEBUG
00273   printf("blankrectangle() - left: %d right: %d top: %d bottom: %d\n",
00274     left, right, top, bottom);
00275 #endif
00276 
00277   SetAPen (Win->RPort, BACKGROUNDCOLOR);
00278   RectFill(Win->RPort,
00279     (SHORT)(Win->BorderLeft + left/scalefactor),
00280     (SHORT)(Win->BorderTop + top/(scalefactor*lacefactor)),
00281     (SHORT)(Win->BorderLeft + right/scalefactor - 1),
00282     (SHORT)(Win->BorderTop + bottom/(scalefactor*lacefactor) - 1));
00283 } /* mf_amiga_blankrectangle() */
00284 
00285 /*
00286  * PAINTROW: Paint a `row' starting with color `init_color', up to the
00287  * next transition specified by `transition_vector', switch colors, and
00288  * continue for `vector_size' transitions.  It now only
00289  * draws into the display window when a new raster line will be affected.
00290  * A lot of pre-drawing and inter-drawing calculations and conditionals
00291  * are evaluated to prepare a fast and clean drawing under the most
00292  * circumstances to be expected on the Amiga.  InterLace/Lace is taken
00293  * care of and the sizes are set appropriately not to clobber the borders.
00294  * (Don't ask me why this works; at least on my machine with my config.)
00295  */
00296 void mf_amiga_paintrow(screenrow row, pixelcolor init_color,
00297   transspec transition_vector, screencol vector_size)
00298 {
00299   int start, scaledstart, scaledrow, scaledlaced;
00300   register int i=0, j=0, col, color;
00301 
00302 #ifdef DEBUG
00303     printf("paintrow() - vector size: %d\n", vector_size);
00304 #endif
00305 
00306   color       = ((0 == init_color) ? BACKGROUNDCOLOR : PENCOLOR);
00307   scaledlaced = scalefactor * lacefactor;
00308   start       = *transition_vector++;
00309   scaledstart = start / scalefactor;
00310   scaledrow   = row / scaledlaced;
00311 
00312   ReadPixelLine8(Win->RPort, Win->BorderLeft + scaledstart,
00313     Win->BorderTop + scaledrow, scaledwidth - scaledstart,
00314     linearray, &temprp);
00315 
00316   if(scalefactor>1) {
00317 
00318     do {
00319       for(col = *transition_vector++; i<col-start; i++) {
00320         linearray[j] |= color;
00321         if((i%scalefactor)==0) j++;
00322       }
00323 
00324       color = PENCOLOR - color;
00325 
00326 #ifdef DEBUG
00327       printf("move col: %d row: %d ", col, row);
00328       printf("draw col: %d row: %d\n", (*transition_vector)-1, row);
00329 #endif
00330 
00331     } while (--vector_size);
00332 
00333     if(i >= col-start) linearray[++j] |= color;
00334 
00335   } else {
00336 
00337     do {
00338       for(col = *transition_vector++; j<col-start; j++) {
00339          linearray[j] |= color;
00340          }
00341 
00342       color = PENCOLOR - color;
00343 
00344 #ifdef DEBUG
00345       printf("move col: %d row: %d ", col, row);
00346       printf("draw col: %d row: %d\n", (*transition_vector)-1, row);
00347 #endif
00348 
00349     } while (--vector_size);
00350   }
00351 
00352   if( (  Win->BorderTop + scaledrow ) <
00353       (  Win->Height - Win->BorderBottom ) )
00354     WritePixelLine8(Win->RPort, Win->BorderLeft + scaledstart,
00355       Win->BorderTop + scaledrow,
00356       min(Win->Width - Win->BorderLeft - Win->BorderRight - scaledstart,j),
00357       linearray, &temprp);
00358 
00359 } /* mf_amiga_paintrow() */
00360 
00361 #else
00362 int amiga_dummy;
00363 #endif /* AMIGAWIN */