emf.c 8.54 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*
 *  Dump an Enhanced Meta File
 *
 *  Copyright 2005 Mike McCormack
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 20
 */

21 22
#include "config.h"
#include "wine/port.h"
Mike McCormack's avatar
Mike McCormack committed
23
#include "winedump.h"
24

25
#include <stdio.h>
26 27 28 29 30 31
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
32 33 34 35 36 37 38
#include <fcntl.h>
#include <stdarg.h>

#include "windef.h"
#include "winbase.h"
#include "wingdi.h"

39
static const char *debugstr_wn(const WCHAR *wstr, unsigned int n)
40 41 42
{
    static char buf[80];
    char *p;
43
    unsigned int i;
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60

    if (!wstr) return "(null)";

    i = 0;
    p = buf;
    *p++ = '\"';
    while (i < n && i < sizeof(buf) - 2 && wstr[i])
    {
        if (wstr[i] < 127) *p++ = wstr[i];
        else *p++ = '.';
        i++;
    }
    *p++ = '\"';
    *p = 0;
    return buf;
}

61
static unsigned int read_int(const unsigned char *buffer)
62
{
63
    return buffer[0]
64 65 66 67 68 69 70
     + (buffer[1]<<8)
     + (buffer[2]<<16)
     + (buffer[3]<<24);
}

#define EMRCASE(x) case x: printf("%-20s %08x\n", #x, length); break

71 72 73
static unsigned offset = 0;

static int dump_emfrecord(void)
74
{
75
    const unsigned char*        ptr;
76
    unsigned int type, length, i;
77

78 79
    ptr = PRD(offset, 8);
    if (!ptr) return -1;
80

81 82
    type = read_int(ptr);
    length = read_int(ptr + 4);
83 84 85 86

    switch(type)
    {
    EMRCASE(EMR_HEADER);
87
    EMRCASE(EMR_POLYBEZIER);
88 89
    EMRCASE(EMR_POLYGON);
    EMRCASE(EMR_POLYLINE);
90 91 92 93
    EMRCASE(EMR_POLYBEZIERTO);
    EMRCASE(EMR_POLYLINETO);
    EMRCASE(EMR_POLYPOLYLINE);
    EMRCASE(EMR_POLYPOLYGON);
94 95 96
    EMRCASE(EMR_SETWINDOWEXTEX);
    EMRCASE(EMR_SETWINDOWORGEX);
    EMRCASE(EMR_SETVIEWPORTEXTEX);
97 98
    EMRCASE(EMR_SETVIEWPORTORGEX);
    EMRCASE(EMR_SETBRUSHORGEX);
99
    EMRCASE(EMR_EOF);
100 101
    EMRCASE(EMR_SETPIXELV);
    EMRCASE(EMR_SETMAPPERFLAGS);
102
    EMRCASE(EMR_SETMAPMODE);
103
    EMRCASE(EMR_SETBKMODE);
104 105
    EMRCASE(EMR_SETPOLYFILLMODE);
    EMRCASE(EMR_SETROP2);
106 107 108 109 110 111 112 113 114
    EMRCASE(EMR_SETSTRETCHBLTMODE);
    EMRCASE(EMR_SETTEXTALIGN);
    EMRCASE(EMR_SETCOLORADJUSTMENT);
    EMRCASE(EMR_SETTEXTCOLOR);
    EMRCASE(EMR_SETBKCOLOR);
    EMRCASE(EMR_OFFSETCLIPRGN);
    EMRCASE(EMR_MOVETOEX);
    EMRCASE(EMR_SETMETARGN);
    EMRCASE(EMR_EXCLUDECLIPRECT);
115 116 117

    case EMR_INTERSECTCLIPRECT:
    {
118
        const EMRINTERSECTCLIPRECT *clip = PRD(offset, sizeof(*clip));
119 120 121 122 123 124 125 126

        printf("%-20s %08x\n", "EMR_INTERSECTCLIPRECT", length);
        printf("rect %d,%d - %d, %d\n",
               clip->rclClip.left, clip->rclClip.top,
               clip->rclClip.right, clip->rclClip.bottom);
        break;
    }

127
    EMRCASE(EMR_SCALEVIEWPORTEXTEX);
128 129
    EMRCASE(EMR_SCALEWINDOWEXTEX);
    EMRCASE(EMR_SAVEDC);
130 131 132
    EMRCASE(EMR_RESTOREDC);
    EMRCASE(EMR_SETWORLDTRANSFORM);
    EMRCASE(EMR_MODIFYWORLDTRANSFORM);
133 134 135 136
    EMRCASE(EMR_SELECTOBJECT);
    EMRCASE(EMR_CREATEPEN);
    EMRCASE(EMR_CREATEBRUSHINDIRECT);
    EMRCASE(EMR_DELETEOBJECT);
137 138
    EMRCASE(EMR_ANGLEARC);
    EMRCASE(EMR_ELLIPSE);
139
    EMRCASE(EMR_RECTANGLE);
140 141 142 143
    EMRCASE(EMR_ROUNDRECT);
    EMRCASE(EMR_ARC);
    EMRCASE(EMR_CHORD);
    EMRCASE(EMR_PIE);
144
    EMRCASE(EMR_SELECTPALETTE);
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
    EMRCASE(EMR_CREATEPALETTE);
    EMRCASE(EMR_SETPALETTEENTRIES);
    EMRCASE(EMR_RESIZEPALETTE);
    EMRCASE(EMR_REALIZEPALETTE);
    EMRCASE(EMR_EXTFLOODFILL);
    EMRCASE(EMR_LINETO);
    EMRCASE(EMR_ARCTO);
    EMRCASE(EMR_POLYDRAW);
    EMRCASE(EMR_SETARCDIRECTION);
    EMRCASE(EMR_SETMITERLIMIT);
    EMRCASE(EMR_BEGINPATH);
    EMRCASE(EMR_ENDPATH);
    EMRCASE(EMR_CLOSEFIGURE);
    EMRCASE(EMR_FILLPATH);
    EMRCASE(EMR_STROKEANDFILLPATH);
    EMRCASE(EMR_STROKEPATH);
    EMRCASE(EMR_FLATTENPATH);
    EMRCASE(EMR_WIDENPATH);
    EMRCASE(EMR_SELECTCLIPPATH);
    EMRCASE(EMR_ABORTPATH);
165
    EMRCASE(EMR_GDICOMMENT);
166 167 168 169
    EMRCASE(EMR_FILLRGN);
    EMRCASE(EMR_FRAMERGN);
    EMRCASE(EMR_INVERTRGN);
    EMRCASE(EMR_PAINTRGN);
170 171 172

    case EMR_EXTSELECTCLIPRGN:
    {
173
        const EMREXTSELECTCLIPRGN *clip = PRD(offset, sizeof(*clip));
174
        const RGNDATA *data = (const RGNDATA *)clip->RgnData;
175
        DWORD i, rc_count = 0;
176
        const RECT *rc;
177 178 179 180 181 182

        if (length >= sizeof(*clip) + sizeof(*data))
            rc_count = data->rdh.nCount;

        printf("%-20s %08x\n", "EMREXTSELECTCLIPRGN", length);
        printf("mode %d, rects %d\n", clip->iMode, rc_count);
183
        for (i = 0, rc = (const RECT *)data->Buffer; i < rc_count; i++, rc++)
184 185 186 187 188
            printf(" (%d,%d)-(%d,%d)", rc->left, rc->top, rc->right, rc->bottom);
        if (rc_count != 0) printf("\n");
        break;
    }

189 190 191 192 193 194
    EMRCASE(EMR_BITBLT);
    EMRCASE(EMR_STRETCHBLT);
    EMRCASE(EMR_MASKBLT);
    EMRCASE(EMR_PLGBLT);
    EMRCASE(EMR_SETDIBITSTODEVICE);
    EMRCASE(EMR_STRETCHDIBITS);
195 196 197

    case EMR_EXTCREATEFONTINDIRECTW:
    {
198
        const EMREXTCREATEFONTINDIRECTW *pf = PRD(offset, sizeof(*pf));
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
        const LOGFONTW *plf = &pf->elfw.elfLogFont;

        printf("%-20s %08x\n", "EMR_EXTCREATEFONTINDIRECTW", length);
        printf("(%d %d %d %d %x out %d clip %x quality %d charset %d) %s %s %s %s\n",
               plf->lfHeight, plf->lfWidth,
               plf->lfEscapement, plf->lfOrientation,
               plf->lfPitchAndFamily,
               plf->lfOutPrecision, plf->lfClipPrecision,
               plf->lfQuality, plf->lfCharSet,
               debugstr_wn(plf->lfFaceName, LF_FACESIZE),
               plf->lfWeight > 400 ? "Bold" : "",
               plf->lfItalic ? "Italic" : "",
               plf->lfUnderline ? "Underline" : "");
	break;
    }

215
    EMRCASE(EMR_EXTTEXTOUTA);
216 217 218

    case EMR_EXTTEXTOUTW:
    {
219
        const EMREXTTEXTOUTW *etoW = PRD(offset, sizeof(*etoW));
220 221 222 223 224 225 226 227 228 229 230

        printf("%-20s %08x\n", "EMR_EXTTEXTOUTW", length);
        printf("pt (%d,%d) rect (%d,%d - %d,%d) flags %#x, %s\n",
               etoW->emrtext.ptlReference.x, etoW->emrtext.ptlReference.y,
               etoW->emrtext.rcl.left, etoW->emrtext.rcl.top,
               etoW->emrtext.rcl.right, etoW->emrtext.rcl.bottom,
               etoW->emrtext.fOptions,
               debugstr_wn((LPCWSTR)((const BYTE *)etoW + etoW->emrtext.offString), etoW->emrtext.nChars));
	break;
    }

231
    EMRCASE(EMR_POLYBEZIER16);
232 233
    EMRCASE(EMR_POLYGON16);
    EMRCASE(EMR_POLYLINE16);
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
    EMRCASE(EMR_POLYBEZIERTO16);
    EMRCASE(EMR_POLYLINETO16);
    EMRCASE(EMR_POLYPOLYLINE16);
    EMRCASE(EMR_POLYPOLYGON16);
    EMRCASE(EMR_POLYDRAW16);
    EMRCASE(EMR_CREATEMONOBRUSH);
    EMRCASE(EMR_CREATEDIBPATTERNBRUSHPT);
    EMRCASE(EMR_EXTCREATEPEN);
    EMRCASE(EMR_POLYTEXTOUTA);
    EMRCASE(EMR_POLYTEXTOUTW);
    EMRCASE(EMR_SETICMMODE);
    EMRCASE(EMR_CREATECOLORSPACE);
    EMRCASE(EMR_SETCOLORSPACE);
    EMRCASE(EMR_DELETECOLORSPACE);
    EMRCASE(EMR_GLSRECORD);
    EMRCASE(EMR_GLSBOUNDEDRECORD);
    EMRCASE(EMR_PIXELFORMAT);
    EMRCASE(EMR_DRAWESCAPE);
    EMRCASE(EMR_EXTESCAPE);
    EMRCASE(EMR_STARTDOC);
    EMRCASE(EMR_SMALLTEXTOUT);
    EMRCASE(EMR_FORCEUFIMAPPING);
    EMRCASE(EMR_NAMEDESCAPE);
    EMRCASE(EMR_COLORCORRECTPALETTE);
    EMRCASE(EMR_SETICMPROFILEA);
    EMRCASE(EMR_SETICMPROFILEW);
    EMRCASE(EMR_ALPHABLEND);
    EMRCASE(EMR_SETLAYOUT);
    EMRCASE(EMR_TRANSPARENTBLT);
    EMRCASE(EMR_RESERVED_117);
    EMRCASE(EMR_GRADIENTFILL);
    EMRCASE(EMR_SETLINKEDUFI);
    EMRCASE(EMR_SETTEXTJUSTIFICATION);
    EMRCASE(EMR_COLORMATCHTOTARGETW);
    EMRCASE(EMR_CREATECOLORSPACEW);
269 270

    default:
271
        printf("%u %08x\n", type, length);
272 273 274 275 276 277 278 279
        break;
    }

    if ( (length < 8) || (length % 4) )
        return -1;

    length -= 8;

280 281
    offset += 8;

282 283 284 285
    for(i=0; i<length; i+=4)
    {
         if (i%16 == 0)
             printf("   ");
286 287 288 289
         if (!(ptr = PRD(offset, 4))) return -1;
         offset += 4;
         printf("%08x ", read_int(ptr));
         if ( (i % 16 == 12) || (i + 4 == length))
290 291 292 293 294 295
             printf("\n");
    }

    return 0;
}

296
enum FileSig get_kind_emf(void)
297
{
298 299 300 301 302 303
    const ENHMETAHEADER*        hdr;

    hdr = PRD(0, sizeof(*hdr));
    if (hdr && hdr->iType == EMR_HEADER && hdr->dSignature == ENHMETA_SIGNATURE)
        return SIG_EMF;
    return SIG_UNKNOWN;
304 305
}

306
void emf_dump(void)
307
{
308 309
    offset = 0;
    while (!dump_emfrecord());
310
}