/* WMF decoder/viewer, based on code by a taiwanese programmer */
// compiler: BC3.1, target: DOS, model: small, calling: pascal
// floatpoint: none, alignment: 2
// h#s 11/06
#include <stdio.h>
#define elemof(x) (sizeof(x)/sizeof((x)[0]))
typedef enum {false, true} bool;
const int regular[] = {
0x001E,0x0035,0x0037,0x004F,0x0050,0x0052,0x005E,0x0102,0x0103,
0x0104,0x0105,0x0106,0x0107,0x0108,0x0127,0x012A,0x012B,0x012C,
0x012D,0x012E,0x012E,0x0139,0x014C,0x014D,0x01f0,0x0201,
0x020A,0x020B,0x020C,0x020D,0x020E,0x020F,0x0211,0x0213,0x0214,
0x0220,0x0228,0x0231,0x0410,0x0412,0x0415,0x0416,0x0418,
0x0419,0x041B,0x041F,0x0429,0x0548,0x061C,0x061D,0x0817,0x081A,
0x0830,0x0d33,0x0000,
};
const char *regtext[] = {
"SaveDC","RealizePalette","SetPalEntries","StartPage","EndPage",
"AbortDoc","EndDoc","SetBkMode","SetMapMode","SetROP2","SetRelabs",
"SetPolyFillMode","SetStretchBltMode","SetTextCharExtra","RestoreDC",
"InvertRegion","PaintRegion","SelectClipRegion","SelectObject",
"SetTextAlign","SetTextAlign","ResizePalette","ResetDc","StartDoc",
"DeleteObject","SetBkColor","SetTextJustification",
"SetWindowOrg","SetWindowExt","SetViewportOrg","SetViewportExt",
"OffsetWindowOrg","OffsetViewportOrg","LineTo","MoveTo",
"OffsetClipRgn","FillRegion","SetMapperFlags","ScaleWindowExt",
"ScaleViewportExt","ExcludeClipRect","IntersectClipRect","Ellipse",
"FloodFill","Rectangle","SetPixel","FrameRegion","ExtFloodFill",
"RoundRect","PatBlt","Arc","Pie","Chord","SetDibToDev","EOF"
};
const int unregular[] = {
0x00F7,0x00F8,0x0142,0x01F0,0x01F9,0x0234,0x02FA,0x02FB,0x02FC,
0x02FD,0x0324,0x0325,0x0436,0x0521,0x0538,0x0626,0x062F,
0x06FE,0x06FF,0x0922,0x0940,0x0A32,0x0B23,0x0B41,0x0F43,0x0209
};
const char *unregtext[] = {
"CreatePalette","CreateBrush","DibCreatePatternBrush","DeleteObject",
"CreatePatternBrush","SelectPalatte","CreatePenIndirect",
"CreateFontIndirect",
"CreateBrushIndirect","CreateBitmapIndirect","Polygon","Polyline",
"AnimatePalette","TextOut","PolyPolygon","Escape","DrawText",
"CreateBitmap","CreateRegion","BitBlt","DibBitblt","ExtTextOut",
"StretchBlt","DibStretchBlt","StretchDIBits","SetTextColor"
};
int in_regular (int func) {
int i;
for (i=0; i<elemof(regular); i++)
if (regular[i] == func) return i;
return -1;
}
int in_unreg (int func) {
int i;
for (i=0; i<elemof(unregular); i++)
if (unregular[i] == func) return i;
return -1;
}
static const long HtmlColors[]={
0x000000L,0x808080L,0x800000L,0xFF0000L,
0x008000L,0x00FF00L,0x808000L,0xFFFF00L,
0x000080L,0x0000FFL,0x800080L,0xFF00FFL,
0x008080L,0x00FFFFL,0xC0C0C0L,0xFFFFFFL};
static const char *HtmlNames[]={
"black","gray","maroon","red",
"green","lime","olive","yellow",
"navy","blue","purple","fuchsia",
"teal","aqua","silver","white"};
const char* C(long color) {
static char buf[8];
int i;
color=((color&0xFF)<<16)|(color&0xFF00)|((color>>16)&0xFF);
for (i=0; i<elemof(HtmlColors); i++)
if (color==HtmlColors[i]) return HtmlNames[i];
sprintf(buf,"#%06X",color);
return buf;
}
bool funcprint(FILE *out, FILE *wmf) {
int a, i, j;
long l,recstart;
struct{
long len;
short fu;
}rhdr;
fprintf(out,"============= Records =================\n");
recstart=ftell(wmf);
if (fread(&rhdr,sizeof(rhdr),1,wmf)!=1) return false;
fprintf(out,"Size:\t\t%ld\n",rhdr.len);
fprintf(out,"Function:\t%04x\n",rhdr.fu);
a=in_regular(rhdr.fu);
if (a>=0) {
fprintf(out,"Name:\t\t%s(",regtext[a]);
for (i=3; i<rhdr.len; i++) {
short val;
fread(&val,sizeof(val),1,wmf);
if (i>3) fputc(',',out);
fprintf(out,"%d",val);
}
fprintf(out,")\n");
if (!rhdr.fu) return false; // exit on EOF record
}else{ // not regular function
a=in_unreg(rhdr.fu);
if (a>=0) {
fprintf(out,"Name:\t\t%s\n",unregtext[a]);
switch (rhdr.fu) {
case 0x0F7: { // CreatePalette
struct{
short ver;
short num;
}h;
fread(&h,sizeof(h),1,wmf);
fprintf(out,"Version:\t%04x\n",h.ver);
fprintf(out,"Num of Entry:\t%d\n",h.num);
for (i=0; i<h.num; i++) {
fread(&l,4,1,wmf);
fprintf(out,"Entry %3d:\t%08lx\n",i+1,l);
}
}break;
case 0x142: { // CreatePatternBrush3
struct{
short type;
short usage;
}h;
fread(&h,sizeof(h),1,wmf);
fprintf(out,"Type:\t%04x\n",h.type);
fprintf(out,"Usage:\t%04x\n",h.usage);
// not over...
}break;
case 0x234: { // SelectPalette
short h;
fread(&h,sizeof(h),1,wmf);
fprintf(out,"Handle:\t\t%04x\n",h);
}break;
case 0x2FA: { // CreatePenIndirect
const char *sty[]={
"solid","dashed","dotted","dot and dash",
"dash ans two dots","none","inside frame"};
struct{
short style;
short width;
short height;
long color;
}h;
fread(&h,sizeof(h),1,wmf);
fprintf(out,"Style:\t\t%d\t%s\n",h.style,
(unsigned)h.style<elemof(sty)?sty[h.style]:"?");
fprintf(out,"Width:\t\t%d\n",h.width);
fprintf(out,"Color:\t\t%06lX\t%s\n",h.color,C(h.color));
}break;
case 0x209: { // SetTextColor
long color;
fread(&color,sizeof(color),1,wmf);
fprintf(out,"Color:\t\t%06lX\t%s\n",color,C(color));
}break;
case 0x2FB: { // CreateFontIndirect
struct{
short height;
short width;
short escape;
short orient;
short weight;
char italic;
char underline;
char strikeout;
char charset;
char oprecis;
char cprecis;
char oqual;
char pitch_fam;
char facename[32];
}h;
fread(&h,sizeof(h),1,wmf);
fprintf(out,"Height:\t\t%d\n",h.height);
fprintf(out,"Width:\t\t%d\n",h.width);
fprintf(out,"Escapement:\t%d\t%d.%d°\n",h.escape,h.escape/10,h.escape%10);
fprintf(out,"Orientation:\t%d\t%d.%d°\n",h.orient,h.orient/10,h.orient%10);
fprintf(out,"Weight:\t\t%d\n",h.weight);
fprintf(out,"Italic:\t\t%d\t%s\n",h.italic,h.italic?"yes":"no");
fprintf(out,"UnderLine:\t%d\t%s\n",h.underline,h.underline?"yes":"no");
fprintf(out,"Strikeout:\t%d\t%s\n",h.strikeout,h.strikeout?"yes":"no");
fprintf(out,"Character set:\t%d\n",h.charset);
fprintf(out,"Output Precis:\t%d\n",h.oprecis);
fprintf(out,"Clip Precis:\t%d\n",h.cprecis);
fprintf(out,"Output Quality:\t%d\n",h.oqual);
fprintf(out,"Pitch:\t\t%d\n",h.pitch_fam&3);
fprintf(out,"Font type:\t%d\n",h.pitch_fam>>4);
fprintf(out,"Font face Name:\t%.32s\n",h.facename);
}break;
case 0x2FC: { // CreateBrushIndirect
struct{
short style;
long color;
short hatch;
}h;
fread(&h,sizeof(h),1,wmf);
fprintf(out,"Style:\t\t%d\n",h.style);
fprintf(out,"Color:\t\t%06lX\t%s\n",h.color,C(h.color));
fprintf(out,"Cross-hatch line type:%d\n",h.hatch);
}break;
case 0x325: // Polyline
case 0x324: { // Polygon
short h;
fread(&h,sizeof(h),1,wmf);
fprintf(out,"Num of Points:\t%d\n",h);
for (i=0; i<h; i++) {
struct{
short x;
short y;
}p;
fread(&p,sizeof(p),1,wmf);
fprintf(out,"Point %4d:\t(%3d,%3d)\n",i,p.x,p.y);
}
}break;
case 0x436: { // AnimatePalatte
struct{
short start;
short num;
}h;
fread(&h,sizeof(h),1,wmf);
fprintf(out,"Starting Palette Entry Number:\t%d\n",h.start);
fprintf(out,"Number of entries to animete:\t%d\n",h.num);
for (i=0; i<h.num; i++) {
long l;
fread(&l,sizeof(l),1,wmf);
fprintf(out,"New Palette Entry %d:\t%08x\n",i,l);
}
}break;
case 0x521: { // TextOut
short h;
struct {
short y;
short x;
}p;
fread(&h,sizeof(h),1,wmf);
fprintf(out,"String Length:\t%d\n",h);
fprintf(out,"String:\t\t");
for (i=0; i<h; i++) {
char c;
c=fgetc(wmf);
fputc(c,out);
}
fputc('\n',out);
if (h&1) fgetc(wmf); // odd number of characters: align file pointer
fread(&p,sizeof(p),1,wmf);
fprintf(out,"X Origin:\t%d\n",p.x);
fprintf(out,"Y Origin:\t%d\n",p.y);
}break;
case 0x538: { // PolyPolygon
short npoly;
fread(&npoly,sizeof(npoly),1,wmf);
fprintf(out,"Num of Polygons:\t%d\n",npoly);
for (i=j=0; i<npoly; i++) {
short npt;
fread(&npt,sizeof(npt),1,wmf);
j+=npt;
fprintf(out,"Polygon %d has %d points\n",i,npt);
}
for (i=0; i<j; i++) {
struct{
short x;
short y;
}p;
fread(&p,sizeof(p),1,wmf);
fprintf(out,"Point %d:\t(%3d,%3d)\n",i,p.x,p.y);
}
}break;
case 0x626: { // Escape
struct{
short num;
short size;
}h;
fread(&h,sizeof(h),1,wmf);
fprintf(out,"Escape Number:\t%d\n",h.num);
fprintf(out,"Escape Size:\t%d\n",h.size);
fprintf(out,"Escape Data:\t");
for (i=0; i<h.size; i++) {
char c;
c=fgetc(wmf);
fputc(c,out);
}
fputc('\n',out);
}break;
case 0x940: { // BitBlt3
struct{
short too;
short y;
short x;
short dh;
short dw;
short dy;
short dx;
short bfType;
long bfSize;
long u1;
long bfOffbits;
long biSize;
long biWidth;
long biHeight;
short biPlanes;
short biBitCount;
long biCompression;
long biSizeImage;
long biXPelsPerMeter;
long biYPelsPerMeter;
long biClrUsed;
long biClrImportant;
}h;
fread(&h,sizeof(h),1,wmf);
fprintf(out,"Type of Operation:\t%d\n",h.too);
fprintf(out,"Bitmap Y Origin:\t\t%d\n",h.y);
fprintf(out,"Bitmap X Origin:\t\t%d\n",h.x);
fprintf(out,"Destination area height:\t%d\n",h.dh);
fprintf(out,"Destination area width:\t%d\n",h.dw);
fprintf(out,"Destination Y Origin:\t%d\n",h.dy);
fprintf(out,"Destination X Origin:\t%d\n",h.dx);
fprintf(out,"------ Bitmap File Header -------\n");
fprintf(out,"\tbfType:\t%d\n",h.bfType);
fprintf(out,"\tbfSize:\t%d\n",h.bfSize);
fprintf(out,"\tbfOffbits:\t%d\n",h.bfOffbits);
fprintf(out,"------ Windows 3 Bitmap Header --\n");
fprintf(out,"\tbiSize:\t%d\n",h.biSize);
fprintf(out,"\tbiWidth:\t%d\n",h.biWidth);
fprintf(out,"\tbiHeight:\t%d\n",h.biHeight);
fprintf(out,"\tbiPlanes:\t%d\n",h.biPlanes);
fprintf(out,"\tbiBitCount:\t%d\n",h.biBitCount);
fprintf(out,"\tbiCompression:\t%d\n",h.biCompression);
fprintf(out,"\tbiSizeImage:\t%d\n",h.biSizeImage);
fprintf(out,"\tbiXPelsPerMeter:\t%d\n",h.biXPelsPerMeter);
fprintf(out,"\tbiYPelsPerMeter:\t%d\n",h.biYPelsPerMeter);
fprintf(out,"\tbiClrUsed:\t%d\n",h.biClrUsed);
fprintf(out,"\tbiClrImportant:\t%d\n",h.biClrImportant);
for (i=0; i<h.biClrUsed; i++) {
long l;
fread(&l,sizeof(l),1,wmf);
fprintf(out,"\tColor Map:\t06lX\t%s\n",l,C(l));
}
}break;
}
}else{
fprintf(out,"Unknown record:\t\t%X\n",rhdr.fu);
}
}
fseek(wmf,recstart+rhdr.len*2,0); // position file pointer to next
return true;
}
void pheadprint(FILE *out, FILE*wmf) {
struct{
long id;
short handle;
short left;
short top;
short right;
short bottom;
short inch;
long reserved;
short checksum;
}h;
fread(&h,sizeof(h),1,wmf);
fprintf(out,"=============== Placeable Heads =======\n");
fprintf(out,"Top Left X:\t%d\n",h.left);
fprintf(out,"Top Left Y:\t%d\n",h.top);
fprintf(out,"Bottom Right X:\t%d\n",h.right);
fprintf(out,"Bottom Right Y:\t%d\n",h.bottom);
fprintf(out,"Scale:\t\t%d units per inch\n",h.inch);
fprintf(out,"Checksum:\t%d\n",h.checksum);
}
void headprint(FILE *out, FILE*wmf) {
long l;
struct{
short type;
short headsize;
short version;
long filesize; // this struct requires at least pack(2)!!
short nobj;
long maxrecsize;
short nparams;
}h;
fread(&l,sizeof(l),1,wmf);
fseek(wmf,-4,1); // seek back
if (l==0x9AC6CDD7UL) // placeable metafile
pheadprint(out,wmf);
fread(&h,sizeof(h),1,wmf);
fprintf(out,"=============== Heads =================\n");
fprintf(out,"Filetype:\t%d\n",h.type);
fprintf(out,"Head Size:\t%d words\n",h.headsize);
fprintf(out,"Version:\t%#x\n",h.version);
fprintf(out,"File Size:\t%ld words\n",h.filesize);
fprintf(out,"Num of Object:\t%d\n",h.nobj);
fprintf(out,"Max Record Size:%ld words\n",h.maxrecsize);
fprintf(out,"Num of Params:\t%d(not use)\n\n",h.nparams);
}
int _cdecl main (int argc, char **argv) {
FILE *wmf, *out;
if (argc < 2) {
printf("Usage:\t%s wmf-file out-file\n",argv[0]);
return 1;
}
wmf=fopen(argv[1],"rb");
if (argc==3) out=fopen(argv[2],"wt");
else out=fopen("out.txt","wt");
headprint(out,wmf);
while (funcprint(out,wmf));
return 0;
}
Vorgefundene Kodierung: UTF-8 | 0
|