home *** CD-ROM | disk | FTP | other *** search
/ DTP Toolbox / DTPToolbox.iso / utilities / archiveutils / wmf.lha / src / amiga.c next >
Encoding:
C/C++ Source or Header  |  1995-12-04  |  11.2 KB  |  453 lines

  1. /* 
  2. * Amiga Graphics for Window Metafile Reader.
  3. *
  4. * $Log: amiga.c,v $
  5. *  Revision 1.9  1995/12/04  19:27:25  JFusco
  6. *  Added interlace flag to OpenScreen().
  7. *  Added debug statements.
  8. *
  9. *  Revision 1.8  1994/11/09  08:16:51  JFusco
  10. *  Does not print title if file is being saved.
  11. *
  12. *  Revision 1.7  1994/11/08  22:10:52  JFusco
  13. *  Added iff save.
  14. *
  15. *  Revision 1.6  1994/06/27  22:40:00  JFusco
  16. *  Reverted to 400x200 window for aspect ratio, which still needs work.
  17. *
  18. *  Revision 1.5  1994/06/26  18:03:53  JFusco
  19. *  Fixes color matching problems.
  20. *
  21. *  Revision 1.4  1994/06/25  02:28:03  JFusco
  22. *  Better fills (?).  Tries to match luminance of color values.
  23. *
  24. *  Revision 1.3  1994/06/20  23:22:21  JFusco
  25. *  Now does polygon filling (barely).
  26. *
  27. *  Revision 1.2  1994/06/19  22:59:55  JFusco
  28. *  Added still more machine dependent stuff.
  29. *
  30. *  Revision 1.1  1994/06/18  03:09:47  JFusco
  31. *  Initial revision
  32. *
  33. */
  34.  
  35. #include <stdio.h>
  36. #include <string.h>
  37. #undef memcmp
  38. #include <assert.h>
  39.  
  40. #define INTUI_V36_NAMES_ONLY
  41.  
  42. #include <exec/types.h>
  43. #include <exec/memory.h>
  44. #include <intuition/intuition.h>
  45. #include <graphics/copper.h>
  46. #include <graphics/display.h>
  47. #include <graphics/view.h>
  48. #include <time.h>
  49.  
  50. #include <clib/exec_protos.h>
  51. #include <clib/intuition_protos.h>
  52. #include <clib/graphics_protos.h>
  53.  
  54. #include "wmf.h"
  55. extern wmf_hdr_t FileHdr;
  56. extern char *filename, *savename;
  57.  
  58. #include "amiga.h"
  59.  
  60. #define ONE_TIME_WARNING(msg) { static warn=1;\
  61.   if (warn) {warn=0; fprintf(stderr,msg);}}
  62.  
  63. #ifdef DEBUG
  64. extern int RecCtr;
  65. #define DBGREC printf("RecCtr=%d\n",RecCtr)
  66. #else
  67. #define DBGREC
  68. #endif
  69.  
  70. static unsigned            numColors  = NUM_COLORS;
  71. static unsigned            ColorsUsed = 1;
  72. static RGB_color_t      ColorTable[NUM_COLORS];
  73.  
  74. #ifdef LATTICE
  75. int CXBRK(void)      {CleanExit(0);return 0;}
  76. /* void chkabort(void)  {return;} */
  77. #endif
  78.  
  79. struct Screen  *AmigaScreen = NULL;
  80. struct Window  *AmigaWindow = NULL;
  81. struct Library *IntuitionBase = NULL, *GfxBase = NULL;
  82.  
  83. static unsigned char *tmpRasBuf = NULL;
  84.  
  85. /* Virtual Window (for debug only) */
  86. extern short Top, Left, Bottom, Right;
  87.  
  88. /* Local Prototypes. */
  89. void OpenAmigaLibs();
  90. void GetCCIR( RGB_color_t *, unsigned long *, long *, long * );
  91. void OpenAmigaWindow();
  92. void SetRGBColor( RGB_color_t * );
  93.  
  94. void OpenAmigaLibs()
  95. {
  96.    if(!(IntuitionBase = OpenLibrary("intuition.library", 37L))) {
  97.       printf("Could not open intuition.library!\n");
  98.       exit(0);
  99.    }
  100.  
  101.    if(!(GfxBase = OpenLibrary("graphics.library",0))) {
  102.       printf("Could not open graphics.library!\n");
  103.       exit(0);
  104.    };
  105.  
  106. void CleanAmiga()
  107. {
  108.    int i;
  109. #ifdef DEBUG
  110.    printf("ColorsUsed=%d\n",ColorsUsed);
  111.    for(i=0;i<ColorsUsed;i++) {
  112.       printf("%2d r=%02x g=%02x b=%02x\n", i, 
  113.               ColorTable[i].Red, ColorTable[i].Green, ColorTable[i].Blue );
  114.    }
  115. #endif
  116.    if (tmpRasBuf) FreeMem( tmpRasBuf, BITPLANE_SIZE );
  117.    if (AmigaWindow)   CloseWindow(AmigaWindow);
  118.    if (AmigaScreen)   CloseScreen(AmigaScreen);
  119.    if (IntuitionBase) CloseLibrary(IntuitionBase);
  120.    if (GfxBase)       CloseLibrary(GfxBase);
  121. }
  122.  
  123. void OpenAmigaWindow()
  124. {
  125.    unsigned short *areabuffer = NULL;
  126.    static struct AreaInfo area_info;
  127.    static struct TmpRas tmp_ras;
  128.    static UWORD pens[] = { ~0 };
  129.    unsigned i;
  130.  
  131.    OpenAmigaLibs();
  132.  
  133.    AmigaScreen = OpenScreenTags( NULL,
  134.                                  SA_Width,      SCREENX,
  135.                                  SA_Height,     SCREENY,
  136.                                  SA_Depth,      SCREEN_DEPTH,
  137.                                  SA_Type,       CUSTOMSCREEN,
  138.                                  SA_Pens,       (ULONG) pens,
  139.                                  SA_DisplayID,  HIRES_KEY | LACE,
  140.                                  SA_Title,      filename,
  141.                                  SA_ShowTitle,  (ULONG)(savename==NULL),
  142.                                  TAG_DONE );
  143.    if (!(AmigaScreen)) {
  144.       perror("could not open screen.");
  145.       CleanAmiga();
  146.       exit(1);
  147.    };
  148.  
  149.    AmigaWindow = OpenWindowTags( NULL,
  150.                          WA_Left, 10,
  151.                          WA_Top, 10,
  152.                          WA_Width, WINDOWX,
  153.                          WA_Height, WINDOWY,
  154.                          WA_Borderless, TRUE,
  155.                          WA_Backdrop, TRUE,
  156.                          WA_CloseGadget, FALSE,
  157.                          WA_SizeGadget, TRUE,
  158.                          WA_DragBar, TRUE,
  159.                          WA_SmartRefresh, TRUE,
  160.                          WA_CustomScreen, AmigaScreen,
  161.                          WA_IDCMP, IDCMP_VANILLAKEY | IDCMP_MOUSEBUTTONS,
  162.                          TAG_DONE );
  163.  
  164.    if (!(AmigaWindow)) {
  165.       perror("could not open window.");
  166.       CleanAmiga();
  167.       exit(1);
  168.    };
  169.  
  170.    /* Default the color palette. */
  171.    for (i=0; i<numColors; i++) {
  172.       SetRGB4( &AmigaScreen->ViewPort, i,
  173.                (15-(i*(16/numColors))),
  174.                (15-(i*(16/numColors))),
  175.                (15-(i*(16/numColors))) );
  176.    }
  177.  
  178.    /* Set default value for pens and drawing mode. */
  179.    SetAPen(AmigaWindow->RPort,(numColors-1));
  180.    SetBPen(AmigaWindow->RPort,0);
  181.    SetDrMd(AmigaWindow->RPort,JAM2);
  182.  
  183.    /* Reserve pen 0 for background store 8-bit color regs. */
  184.    ColorTable[0].Type  = 0;
  185.    ColorTable[0].Red   = 0xff;
  186.    ColorTable[0].Green = 0xff;
  187.    ColorTable[0].Blue  = 0xff;
  188.    ColorsUsed = 1;
  189.  
  190.    /* Initialize AreaInfo - this should be way too much space! */
  191.    areabuffer = (unsigned short *) calloc(FileHdr.Largest, sizeof(unsigned short));
  192.    tmpRasBuf = AllocMem( BITPLANE_SIZE, MEMF_CLEAR | MEMF_CHIP );
  193.    assert( tmpRasBuf );
  194.    assert( areabuffer );
  195.    InitArea(&area_info, areabuffer,(FileHdr.Largest*sizeof(short))/5 ); 
  196.    InitTmpRas(&tmp_ras, tmpRasBuf, BITPLANE_SIZE );
  197.  
  198.    AmigaWindow->RPort->TmpRas = &tmp_ras;
  199.    AmigaWindow->RPort->AreaInfo = &area_info;
  200. }
  201.  
  202. MoveAmiga( short x, short y )
  203. {
  204.    Move( AmigaWindow->RPort, x, y );
  205. }
  206.  
  207. DrawAmiga( short x, short y )
  208. {
  209.    Draw( AmigaWindow->RPort, x, y );
  210. }
  211.  
  212. AmigaDelay( unsigned t )
  213. {
  214.    time_t time1;
  215.  
  216.    time1 = time(NULL);
  217.    while (time(NULL) - time1 < t);
  218. }
  219.  
  220. void AmigaWait()
  221. {
  222.    ULONG signalmask, signals = 0;
  223.  
  224.    signalmask = 1L << AmigaWindow->UserPort->mp_SigBit;
  225.  
  226.    while( !(signals & signalmask) ) {
  227.       signals = Wait(signalmask);
  228.    }
  229. }
  230.  
  231. void AmigaSave( char *fname )
  232. {
  233.    ScreenDump(AmigaScreen, fname);
  234. }
  235.  
  236. GetPixelAspect( int *x, int *y )
  237. {
  238.    /* Needs more, okay for now. */
  239.    if (INTERLACED) {
  240.       *x=1;
  241.       *y=1;
  242.    }
  243.    else {
  244.       *x=1;
  245.       *y=2;
  246.    }
  247. }
  248.  
  249. SetDrawingMode( unsigned short mode )
  250. {
  251.    switch( mode ) {
  252.    case 7:
  253.       DBGREC;
  254.       SetDrMd(AmigaWindow->RPort, JAM2 );
  255.       fprintf(stderr,"XOR drawing\n");
  256.       break;
  257.    case 13:
  258.       SetDrMd(AmigaWindow->RPort, JAM2 | INVERSVID);
  259.       break;
  260.    default:
  261.       DBGREC;
  262.       fprintf(stderr,"Unimplemented Drawing Mode %04hx\n", mode);
  263.       SetDrMd(AmigaWindow->RPort, JAM2 | INVERSVID);
  264.       break;
  265.    };
  266. }
  267.  
  268. PolygonMoveAmiga( short x, short y )
  269. {
  270.    AreaMove( AmigaWindow->RPort, x, y );
  271. }
  272.  
  273. PolygonDrawAmiga( short x, short y )
  274. {
  275.    AreaDraw( AmigaWindow->RPort, x, y );
  276. }
  277.  
  278. PolygonEndAmiga()
  279. {
  280.    if (AreaEnd( AmigaWindow->RPort ))
  281.    {
  282.       DBGREC;
  283.       fprintf(stderr,"Invalid area\n");
  284.    }
  285. }
  286.  
  287. SetBrushStyleAmiga( brush_t *Brush )
  288. {
  289.    SetRGBColor( &Brush->Color.RGB );
  290.    switch (Brush->Style) {
  291.    case 0: /* Solid */
  292.       SetDrMd(AmigaWindow->RPort,JAM2);
  293.       break;
  294.    case 1: /* Hollow */
  295.       SetDrMd(AmigaWindow->RPort,JAM2|COMPLEMENT);
  296.       break;
  297.    case 2:
  298.       ONE_TIME_WARNING("Cross hatched brush not supported\n");
  299.       break;
  300.    default:
  301.       ONE_TIME_WARNING("Unknown brush type.\n");
  302.       break;
  303.    }
  304. }
  305.  
  306. SetPenStyleAmiga( pen_t *Pen )
  307. {
  308.    static int warnings=0;
  309.    unsigned short pattern;
  310.  
  311.    if (Pen->Width>1) { 
  312.       ONE_TIME_WARNING("Only pen width of 1 supported.\n"); 
  313.    }
  314.  
  315.    switch( Pen->Style ) {
  316.    case 0:
  317.       pattern = 0xffff; /* Solid */
  318.       break;
  319.    case 1:
  320.       pattern = 0xcccc; /* Dashed */
  321.       break;
  322.    case 2:
  323.       pattern = 0xaaaa; /* Dotted */
  324.       break;
  325.    case 3:
  326.       pattern = 0xd6b5; /* Alternating Dot and Dash */
  327.       break;
  328.    case 4: 
  329.       pattern = 0xb5ad; /* Alternating Dash and two Dots */
  330.       break;
  331.    case 5: 
  332.       pattern = 0xffff; /* None ? */
  333.       break;
  334.    case 6:
  335.       /* Inside Frame. */
  336.       DBGREC;
  337.       fprintf(stderr,"Inside frame pen type is unimplemented.\n");
  338.       break;
  339.    default:
  340.       DBGREC;
  341.       fprintf(stderr,"Unrecognized pen style %hd assuming solid.\n",Pen->Style);
  342.       pattern = 0xffff;
  343.       break;
  344.    }
  345.    SetRGBColor( &Pen->Color.RGB );
  346. }
  347.  
  348. void SetRGBColor( RGB_color_t *Color )
  349. {
  350.    unsigned long lum, mlum;
  351.    long Cb, Cr, best, mCb, mCr, match, bestdiff;
  352.    unsigned idx, idx_match;
  353.  
  354.    if (Color->Type != 1) {
  355.  
  356.       /* Set to zero for memcmp. */
  357.       Color->Type = 0;
  358.  
  359.       /* Check to see if it's already in the color table. */
  360.       for( idx=0; idx<ColorsUsed; idx++) {
  361.  
  362.          if (memcmp( &ColorTable[idx], 
  363.                      Color, sizeof(RGB_color_t)) == 0 ) break;
  364.       }
  365.  
  366.       if (ColorsUsed && idx < ColorsUsed) {
  367.  
  368.          /* It's already in the color table. */
  369.          SetAPen(AmigaWindow->RPort,idx);
  370.       }
  371.  
  372.       else if ( ColorsUsed != numColors ) {
  373.  
  374.          /* Not in the color table, but there's room for a new entry. */
  375.          assert( ColorsUsed < numColors );
  376.          memcpy( &ColorTable[ColorsUsed], 
  377.                  Color, sizeof(RGB_color_t));
  378.          ColorTable[ColorsUsed].Type = 0;
  379.          SetRGB4( &AmigaScreen->ViewPort, 
  380.                   ColorsUsed,
  381.                   (ColorTable[ColorsUsed].Red   >> 4),
  382.                   (ColorTable[ColorsUsed].Green >> 4),
  383.                   (ColorTable[ColorsUsed].Blue  >> 4) );
  384.          SetAPen(AmigaWindow->RPort,ColorsUsed);
  385.          ColorsUsed++;
  386.       }
  387.  
  388.       else {
  389.  
  390.          /* Not in the table and there's no more room. */
  391.          /* Get the closest match.                     */
  392.          ONE_TIME_WARNING("Too many colors, will find closest match.\n");
  393.          GetCCIR( Color, &lum, &Cb, &Cr );
  394.  
  395.          for( idx=0; idx<ColorsUsed; idx++) {
  396.  
  397.             GetCCIR( &ColorTable[idx], &mlum, &mCb, &mCr );
  398.  
  399.         /* Compare the dot product of the two color 'vectors' */
  400.             match = lum * mlum + Cb * mCb + Cr * mCr;
  401.  
  402.             if (idx==0) {
  403.                idx_match = 0;
  404.                bestdiff = abs(match);
  405.                best = match;
  406.             }
  407.  
  408.             /* Take our best match and compare the difference. */
  409.         else if (bestdiff > abs(match-best)) {
  410.                idx_match = idx;
  411.            bestdiff = abs(match-best);
  412.                best = match;
  413.             }
  414.          }
  415.          SetAPen(AmigaWindow->RPort,idx_match);
  416.       }
  417.       SetBPen(AmigaWindow->RPort,0);
  418.    }
  419.    else {
  420.       Indexed_color_t *lu = (Indexed_color_t *)Color;
  421.       if (lu->Index < ColorsUsed) {
  422.          fprintf(stderr,"Using color index\n");
  423.          SetAPen(AmigaWindow->RPort,lu->Index);
  424.       }
  425.       else {
  426.          DBGREC;
  427.          fprintf(stderr,"Color index out of range (not supported)\n");
  428.       }
  429.    }
  430. }
  431.  
  432. /* Make a color vector. */
  433. void GetCCIR( RGB_color_t *Color, unsigned long *lum, 
  434.                              long *Cb, long *Cr )
  435. {
  436.    *lum =  Color->Red   * 30
  437.          + Color->Green * 59
  438.          + Color->Blue  * 11;
  439.  
  440.    *Cb  =  Color->Red   * 17
  441.          - Color->Green * 33
  442.          + Color->Blue  * 50;
  443.  
  444.    *Cr  =  Color->Red   * 50
  445.          - Color->Green * 42
  446.          - Color->Blue  *  8;
  447.  
  448.    *lum /= 100;
  449.    *Cb  /= 100;
  450.    *Cr  /= 100;
  451. }
  452.