home *** CD-ROM | disk | FTP | other *** search
- /*
- * Windows Metafile Reader
- *
- * $Log: wmf.c,v $
- * Revision 1.16 1995/12/04 19:23:10 fuscoj
- * Added debug code.
- *
- * Revision 1.15 1995/02/20 21:21:03 JFusco
- * Pre-release.
- *
- * Revision 1.14 1994/11/08 22:10:52 JFusco
- * Added iff save.
- *
- * Revision 1.13 1994/06/27 22:40:55 JFusco
- * Removed color printf()'s.
- *
- * Revision 1.12 1994/06/26 18:03:53 JFusco
- * Better support for colors and brushes, still no fill patterns.
- *
- * Revision 1.11 1994/06/25 02:28:03 JFusco
- * Better fills (?). Tries to match luminance of color values.
- *
- * Revision 1.10 1994/06/22 22:22:09 JFusco
- * Checking to determine if Handles are being handled properly.
- *
- * Revision 1.9 1994/06/20 23:23:06 JFusco
- * Added polygon fill routines
- *
- * Revision 1.8 1994/06/19 22:59:29 JFusco
- * Removed printfs. Uses stderr for really important info.
- *
- * Revision 1.7 1994/06/18 03:10:00 JFusco
- * Lots of changes, too numerous to mention.
- * Added amiga.c and window.c so it now draws to the screen.
- *
- */
-
- #include <sys/types.h> /* ULONG, UWORD, etc. */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <assert.h>
-
- #include "dformat.h"
- #include "wmf.h"
- #include "window.h"
-
- /* Unconditional pointer test or DIE!!!. */
- #define ASSERT(a) if (!(a)) { perror("no memory!\n"); CleanExit(1); }
- #ifndef TRUE
- #define TRUE 1
- #endif
- #ifdef DEBUG
- int AbortFlag=0;
- int RecCtr=0;
- #define DBGREC printf("RecCtr=%d\n",RecCtr);
- #else
- #define DBGREC
- #endif
-
- /* Local Prototypes. */
- void FunctionHandler( struct rec_tmpl * );
- char *wmf_func_name( unsigned short, unsigned char );
- unsigned CreateHandle( wmf_objects, struct rec_tmpl * );
-
- char *filename=NULL, *savename=NULL;
- wmf_hdr_t FileHdr;
- static wmf_handle_t *Handle;
- static wmf_place_hdr_t PlaceHdr;
-
- unsigned window_okay = 0;
-
- main(int argc, char **argv)
- {
- FILE *fin;
- unsigned short hbuf[2];
- struct rec_tmpl *Rec;
-
- if ((argc<2) || (! (fin = fopen( argv[1], "rb" )))) {
- fprintf(stderr,"WMF viewer version 1.0 by John Fusco, 1994\n");
- fprintf(stderr,"usage: wmf {wmf_filename} [{save_as_iff}]\n");
- exit(1);
- }
- filename = argv[1];
- if (argc==3) savename = argv[2];
-
- /* Read 4 bytes to determine if this is a normal or placeable metafile. */
- fread( (char *) hbuf, 1, 4, fin );
- reformat_short( hbuf, sizeof(hbuf) );
-
- /* Most files should have the place header. */
- if (hbuf[0] == 0xcdd7 && hbuf[1]==0x9ac6) {
- memcpy( &PlaceHdr, &hbuf[0], 4);
- fread((char *)&PlaceHdr.unused0, 1,sizeof(PlaceHdr)-4,fin);
- reformat_short(&PlaceHdr.unused0, sizeof(PlaceHdr)-4);
-
- /* Set the window extent to maximum until we're told otherwise. */
- WindowExt.X = abs( PlaceHdr.Left - PlaceHdr.Right );
- WindowExt.Y = abs( PlaceHdr.Top - PlaceHdr.Bottom );
-
- /* We can use what we have if necessary. */
- window_okay = TRUE;
-
- /* Read the file header, which immediately follows. */
- fread((char *)&FileHdr, 1,sizeof(FileHdr),fin);
- reformat_short( (unsigned short *)&FileHdr, 4);
- }
- else {
- /* No place header, just a file header. */
- memcpy( &FileHdr, &hbuf[0], sizeof(hbuf));
- fread((char *)&FileHdr.Ver, 1,sizeof(FileHdr)-4,fin);
- }
-
- /* Finish little endian to big endian conversion. */
- reformat_short(&FileHdr.Ver, 14);
- fix_mixed_longs( &FileHdr.Fsize, sizeof(FileHdr.Fsize));
- fix_mixed_longs( &FileHdr.Largest, sizeof(FileHdr.Largest));
-
- /* Sanity checks. */
- if ( FileHdr.Type != 1 ||
- FileHdr.Hsize != 9 ||
- FileHdr.Largest > FileHdr.Fsize ) {
- fprintf(stderr,"Not a Windows Metafile!\n");
- exit(1);
- }
-
- /* All wmf sizes are in 16-bit words. */
- FileHdr.Largest <<= 1;
- Rec = (struct rec_tmpl *) malloc(FileHdr.Largest);
- Handle = (wmf_handle_t *)calloc(sizeof(wmf_handle_t),FileHdr.numHandles);
- if (Rec==NULL || Handle==NULL) {
- perror("allocating initial space.");
- exit(1);
- }
-
- #ifdef DEBUG
- fprintf(stderr,"Top Left x=%6d y=%6d\n",PlaceHdr.Left,PlaceHdr.Top);
- fprintf(stderr,"Bottom Right x=%6d y=%6d\n",PlaceHdr.Right,PlaceHdr.Bottom);
- fprintf(stderr,"%d pixels per inch\n",PlaceHdr.pixelsPerInch);
- fprintf(stderr,"%d Handles used.\n\n",FileHdr.numHandles);
- #endif
-
- while ( fread((char *)Rec, 1, 6, fin ) == 6 ) {
-
- #ifdef DEBUG
- RecCtr++;
- #endif
- /* Little endian to big endian conversion. */
- reformat_long( &Rec->Size, 4);
- reformat_short(&Rec->Func, 2);
-
- Rec->Size <<= 1;
- if (Rec->Size>FileHdr.Largest) {
- fprintf(stderr,"Record too large: %ld bytes; expected %ld\n",
- Rec->Size, FileHdr.Largest);
- break;
- }
-
- /* Read the rest of the record. */
- Rec->Size -= 6;
- if (fread((char *)Rec->Data, 1, Rec->Size, fin ) != Rec->Size ) break;
-
- /* Convert data, any embedded longs will have to be corrected. */
- reformat_short( Rec->Data, Rec->Size );
-
- FunctionHandler( Rec );
-
- #ifdef DEBUG
- if (AbortFlag) break;
- #endif
- };
-
- fclose(fin);
- if (savename) {
- AmigaSave( savename );
- }
- else {
- AmigaWait();
- }
- CleanExit(0);
- }
-
- void FunctionHandler( struct rec_tmpl *Rec )
- {
- switch( Rec->Func ) {
- #ifdef DEBUG
- case WMF_AnimatePalette:
- case WMF_Arc:
- case WMF_BitBlt:
- case WMF_BitBlt3:
- case WMF_Chord:
- case WMF_DrawText:
- case WMF_Ellipse:
- case WMF_Escape:
- case WMF_ExcludeClipRect:
- case WMF_ExtTextOut:
- case WMF_FloodFill:
- case WMF_InsertClipRect:
- case WMF_LineTo:
- case WMF_MoveTo:
- case WMF_OffsetClipRgn:
- case WMF_OffsetViewportOrg:
- case WMF_OffsetWindowOrg:
- case WMF_PatBlt:
- case WMF_Pie:
- case WMF_PolyPolygon:
- case WMF_RealizePalette:
- case WMF_Rectangle:
- case WMF_ResizePalette:
- case WMF_RestoreDC:
- case WMF_RoundRect:
- case WMF_SaveDC:
- case WMF_ScaleViewportExt:
- case WMF_ScaleWindowExt:
- case WMF_SelectClipRgn:
- case WMF_SelectPalette:
- case WMF_SetBkColor:
- case WMF_SetBkMode:
- case WMF_SetDIBitsToDevice:
- case WMF_SetMapMode:
- case WMF_SetMapperFlags:
- case WMF_SetPaletteEntries:
- case WMF_SetPixel:
- case WMF_SetStretchBltMode:
- case WMF_SetTextAlign:
- case WMF_SetTextCharExtra:
- case WMF_SetTextColor:
- case WMF_SetTextJustification:
- case WMF_SetViewportExt:
- case WMF_SetViewportOrg:
- case WMF_StretchBlt:
- case WMF_StretchBlt3:
- case WMF_StretchDIBits:
- case WMF_TextOut:
- MyDeepestApologies( Rec->Func );
- break;
- #endif
- /* Got to keep track of these even if I don't implement them. */
- case WMF_CreateFontIndirect:
- CreateHandle( FONT, Rec );
- break;
-
- case WMF_CreatePalette:
- CreateHandle( PALETTE, Rec );
- break;
-
- case WMF_CreatePatternBrush:
- CreateHandle( PATTERNBRUSH, Rec );
- break;
-
- case WMF_CreatePatternBrush3:
- CreateHandle( PATTERNBRUSH3, Rec );
- break;
-
- case WMF_CreateRegion:
- MyDeepestApologies( Rec->Func );
- fprintf(stderr,"Did you know this function is undocumented!\n");
- CleanExit(1);
- break;
-
- /* Stuff I've actually implemented!!! (or plan to).*/
- case WMF_CreatePenIndirect:
- {
- static WarnPenColor=1;
- pen_t *Pen = (pen_t *) Rec->Data;
- fix_mixed_longs( &Pen->Color, 4 );
- if (Pen->Color.IDX.Type==1 && WarnPenColor) {
- WarnPenColor=0;
- fprintf(stderr,"Color index not implemented: %08lx\n",
- Pen->Color);
- }
- }
- CreateHandle( PEN, Rec );
- break;
-
- case WMF_CreateBrushIndirect:
- {
- static WarnBrushColor=1;
- brush_t *Brush = (brush_t *) Rec->Data;
- fix_mixed_longs( &Brush->Color, 4 );
- if (Brush->Color.IDX.Type==1 && WarnBrushColor) {
- DBGREC;
- WarnBrushColor=0;
- fprintf(stderr,"Color index not implemented: %08lx\n",
- Brush->Color);
- }
- }
- CreateHandle( BRUSH, Rec );
- break;
-
- case WMF_SelectObject:
- assert( Rec->Data[0]<FileHdr.numHandles && Rec->Data[0] >= 0 );
- SelectObject( Rec->Data[0] );
- break;
-
- case WMF_DeleteObject:
- assert( Rec->Data[0]<FileHdr.numHandles && Rec->Data[0] >= 0 );
- {
- unsigned idx = Rec->Data[0];
- Handle[idx].Type = NOTANOBJ;
- free( Handle[idx].Data );
- Handle[idx].Data = NULL;
- }
- break;
-
-
- case WMF_Polygon:
- {
- unsigned i;
- poly_point_tmpl_t *Poly= (poly_point_tmpl_t *) Rec->Data;
-
- PolygonMoveWC( Poly->Point[0].X, Poly->Point[0].Y );
- for (i=1; i<Poly->numPoints; i++) {
- PolygonDrawWC( Poly->Point[i].X, Poly->Point[i].Y );
- }
- PolygonEndWC();
- }
- break;
-
- case WMF_Polyline:
- {
- unsigned i;
- poly_point_tmpl_t *Poly= (poly_point_tmpl_t *) Rec->Data;
-
- MoveWC( Poly->Point[0].X, Poly->Point[0].Y );
- for (i=1; i<Poly->numPoints; i++) {
- DrawWC( Poly->Point[i].X, Poly->Point[i].Y );
- }
- }
- break;
-
- case WMF_SetPolyFillMode:
- {
- static warn=0;
- if (warn==0) {
- DBGREC;
- warn = 1;
- fprintf(stderr,"Using default fill mode\n");
- }
- }
- break;
-
- case WMF_SetWindowExt:
- memcpy( &WindowExt, &Rec->Data[0], sizeof(WindowExt));
- InitVirtualWindow( &PlaceHdr );
- OpenAmigaWindow();
- break;
-
- case WMF_SetWindowOrg:
- memcpy( &WindowOrg, &Rec->Data[0], sizeof(WindowOrg));
- break;
-
- case WMF_SetROP2:
- SetDrawingMode( Rec->Data[0] );
- break;
-
- case WMF_Null:
- break;
-
- default:
- DBGREC;
- fprintf(stderr,"%s: Unknown function (%x)\n", filename, Rec->Func);
- break;
- }
- return;
- }
-
- MyDeepestApologies( USHORT Func )
- {
- DBGREC;
- fprintf(stderr,"WARNING: %s unimplemented and is being ignored!\n",
- wmf_func_name( Func, 0 ));
- }
-
- CleanExit(int x)
- {
- CleanAmiga();
- exit(x);
- }
-
- /* Lookup values for metafile functions. */
- struct function_code {
- unsigned short opcode;
- char *name, found;
- } wmf_function[] = {
- {0x000,"Null",0},
- {0x01e,"SaveDC",0},
- {0x035,"RealizePalette",0},
- {0x037,"SetPaletteEntries",0},
- {0x0f7,"CreatePalette",0},
- {0x102,"SetBkMode",0},
- {0x103,"SetMapMode",0},
- {0x104,"SetROP2",0},
- {0x106,"SetPolyFillMode",0},
- {0x107,"SetStretchBltMode",0},
- {0x108,"SetTextCharExtra",0},
- {0x127,"RestoreDC",0},
- {0x12c,"SelectClipRgn",0},
- {0x12d,"SelectObject",0},
- {0x12e,"SetTextAlign",0},
- {0x139,"ResizePalette",0},
- {0x142,"CreatePatternBrush3",0},
- {0x1f0,"DeleteObject",0},
- {0x1f9,"CreatePatternBrush",0},
- {0x201,"SetBkColor",0},
- {0x209,"SetTextColor",0},
- {0x20a,"SetTextJustification",0},
- {0x20b,"SetWindowOrg",0},
- {0x20c,"SetWindowExt",0},
- {0x20d,"SetViewportOrg",0},
- {0x20e,"SetViewportExt",0},
- {0x20f,"OffsetWindowOrg",0},
- {0x211,"OffsetViewportOrg",0},
- {0x213,"LineTo",0},
- {0x214,"MoveTo",0},
- {0x220,"OffsetClipRgn",0},
- {0x231,"SetMapperFlags",0},
- {0x234,"SelectPalette",0},
- {0x2fa,"CreatePenIndirect",0},
- {0x2fb,"CreateFontIndirect",0},
- {0x2fc,"CreateBrushIndirect",0},
- {0x324,"Polygon",0},
- {0x325,"Polyline",0},
- {0x400,"ScaleWindowExt",0},
- {0x412,"ScaleViewportExt",0},
- {0x415,"ExcludeClipRect",0},
- {0x416,"InsertClipRect",0},
- {0x418,"Ellipse",0},
- {0x419,"FloodFill",0},
- {0x41b,"Rectangle",0},
- {0x41f,"SetPixel",0},
- {0x436,"AnimatePalette",0},
- {0x521,"TextOut",0},
- {0x538,"PolyPolygon",0},
- {0x61c,"RoundRect",0},
- {0x61d,"PatBlt",0},
- {0x626,"Escape",0},
- {0x62f,"DrawText",0},
- {0x6ff,"CreateRegion",0},
- {0x817,"Arc",0},
- {0x81a,"Pie",0},
- {0x830,"Chord",0},
- {0x922,"BitBlt",0},
- {0x940,"BitBlt3",0},
- {0xa32,"ExtTextOut",0},
- {0xb23,"StretchBlt",0},
- {0xb41,"StretchBlt3",0},
- {0xd33,"SetDIBitsToDevice",0},
- {0xf43,"StretchDIBits",0},
- {0xffff,"Unknown Function",0} /* This must be last */
- };
-
- char *wmf_func_name( unsigned short func, unsigned char dup )
- {
- unsigned i;
-
- /* Last function will be "Unknown" if we got through the loop
- /* without a find. */
- for(i=0; i<sizeof(wmf_function)/sizeof(wmf_function[0]); i++) {
- if (wmf_function[i].opcode >= func) break;
- }
- if ((wmf_function[i].opcode == func) && ! (wmf_function[i].found) ) {
- if (dup) wmf_function[i].found = 1;
- return( wmf_function[i].name );
- }
- else if (wmf_function[i].found)
- return( NULL );
- else
- return( wmf_function[i].name ); /* Unknown function. */
- }
-
- SelectObject( unsigned short idx )
- {
- /* NOTANOBJ, BRUSH, FONT, PALETTE, PATTERNBRUSH, PATTERNBRUSH3, PEN */
- switch ( Handle[idx].Type ) {
-
- case PEN:
- SetPenStyleAmiga( Handle[idx].Data );
- break;
-
- case BRUSH:
- SetBrushStyleAmiga( Handle[idx].Data );
- break;
-
- case FONT:
- {
- static warn=0;
- if (!(warn)) {
- warn=1;
- DBGREC;
- fprintf(stderr,"Font objects not selectable\n");
- }
- }
- break;
-
- case PALETTE:
- {
- static warn=0;
- if (!(warn)) {
- warn=1;
- DBGREC;
- fprintf(stderr,"Palette objects not selectable\n");
- }
- }
- break;
-
- case PATTERNBRUSH:
- case PATTERNBRUSH3:
- {
- static warn=0;
- if (!(warn)) {
- warn=1;
- DBGREC;
- fprintf(stderr,"Pattern brush objects not selectable\n");
- }
- }
- break;
-
- default:
- DBGREC;
- fprintf(stderr,"Unimplemented object selected %ld\n",Handle[idx].Type);
- break;
- };
- }
-
- unsigned CreateHandle( wmf_objects Type, struct rec_tmpl *Rec )
- {
- unsigned i;
-
- /* Find free slot. */
- for (i=0; i<FileHdr.numHandles; i++) {
- if (Handle[i].Type == NOTANOBJ) break;
- };
-
- if (i>=FileHdr.numHandles) {
- fprintf(stderr,"Corrupt WMF file! Bad handle.\n");
- CleanExit(1);
- };
-
- Handle[i].Type = Type;
- Handle[i].Data = (USHORT *) malloc( Rec->Size );
- ASSERT(Handle[i].Data);
- memcpy( &Handle[i].Data[0], &Rec->Data[0], Rec->Size );
- return i;
- }
-