"""
Enhanced Meta File
"""
from construct import *
record_type = Enum(ULInt32("record_type"),
ABORTPATH = 68,
ANGLEARC = 41,
ARC = 45,
ARCTO = 55,
BEGINPATH = 59,
BITBLT = 76,
CHORD = 46,
CLOSEFIGURE = 61,
CREATEBRUSHINDIRECT = 39,
CREATEDIBPATTERNBRUSHPT = 94,
CREATEMONOBRUSH = 93,
CREATEPALETTE = 49,
CREATEPEN = 38,
DELETEOBJECT = 40,
ELLIPSE = 42,
ENDPATH = 60,
EOF = 14,
EXCLUDECLIPRECT = 29,
EXTCREATEFONTINDIRECTW = 82,
EXTCREATEPEN = 95,
EXTFLOODFILL = 53,
EXTSELECTCLIPRGN = 75,
EXTTEXTOUTA = 83,
EXTTEXTOUTW = 84,
FILLPATH = 62,
FILLRGN = 71,
FLATTENPATH = 65,
FRAMERGN = 72,
GDICOMMENT = 70,
HEADER = 1,
INTERSECTCLIPRECT = 30,
INVERTRGN = 73,
LINETO = 54,
MASKBLT = 78,
MODIFYWORLDTRANSFORM = 36,
MOVETOEX = 27,
OFFSETCLIPRGN = 26,
PAINTRGN = 74,
PIE = 47,
PLGBLT = 79,
POLYBEZIER = 2,
POLYBEZIER16 = 85,
POLYBEZIERTO = 5,
POLYBEZIERTO16 = 88,
POLYDRAW = 56,
POLYDRAW16 = 92,
POLYGON = 3,
POLYGON16 = 86,
POLYLINE = 4,
POLYLINE16 = 87,
POLYLINETO = 6,
POLYLINETO16 = 89,
POLYPOLYGON = 8,
POLYPOLYGON16 = 91,
POLYPOLYLINE = 7,
POLYPOLYLINE16 = 90,
POLYTEXTOUTA = 96,
POLYTEXTOUTW = 97,
REALIZEPALETTE = 52,
RECTANGLE = 43,
RESIZEPALETTE = 51,
RESTOREDC = 34,
ROUNDRECT = 44,
SAVEDC = 33,
SCALEVIEWPORTEXTEX = 31,
SCALEWINDOWEXTEX = 32,
SELECTCLIPPATH = 67,
SELECTOBJECT = 37,
SELECTPALETTE = 48,
SETARCDIRECTION = 57,
SETBKCOLOR = 25,
SETBKMODE = 18,
SETBRUSHORGEX = 13,
SETCOLORADJUSTMENT = 23,
SETDIBITSTODEVICE = 80,
SETMAPMODE = 17,
SETMAPPERFLAGS = 16,
SETMETARGN = 28,
SETMITERLIMIT = 58,
SETPALETTEENTRIES = 50,
SETPIXELV = 15,
SETPOLYFILLMODE = 19,
SETROP2 = 20,
SETSTRETCHBLTMODE = 21,
SETTEXTALIGN = 22,
SETTEXTCOLOR = 24,
SETVIEWPORTEXTEX = 11,
SETVIEWPORTORGEX = 12,
SETWINDOWEXTEX = 9,
SETWINDOWORGEX = 10,
SETWORLDTRANSFORM = 35,
STRETCHBLT = 77,
STRETCHDIBITS = 81,
STROKEANDFILLPATH = 63,
STROKEPATH = 64,
WIDENPATH = 66,
_default_ = Pass,
)
generic_record = Struct("records",
record_type,
ULInt32("record_size"), # Size of the record in bytes
Union("params", # Parameters
Field("raw", lambda ctx: ctx._.record_size - 8),
Array(lambda ctx: (ctx._.record_size - 8) // 4, ULInt32("params"))
),
)
header_record = Struct("header_record",
Const(record_type, "HEADER"),
ULInt32("record_size"), # Size of the record in bytes
SLInt32("bounds_left"), # Left inclusive bounds
SLInt32("bounds_right"), # Right inclusive bounds
SLInt32("bounds_top"), # Top inclusive bounds
SLInt32("bounds_bottom"), # Bottom inclusive bounds
SLInt32("frame_left"), # Left side of inclusive picture frame
SLInt32("frame_right"), # Right side of inclusive picture frame
SLInt32("frame_top"), # Top side of inclusive picture frame
SLInt32("frame_bottom"), # Bottom side of inclusive picture frame
Const(ULInt32("signature"), 0x464D4520),
ULInt32("version"), # Version of the metafile
ULInt32("size"), # Size of the metafile in bytes
ULInt32("num_of_records"), # Number of records in the metafile
ULInt16("num_of_handles"), # Number of handles in the handle table
Padding(2),
ULInt32("description_size"), # Size of description string in WORDs
ULInt32("description_offset"), # Offset of description string in metafile
ULInt32("num_of_palette_entries"), # Number of color palette entries
SLInt32("device_width_pixels"), # Width of reference device in pixels
SLInt32("device_height_pixels"), # Height of reference device in pixels
SLInt32("device_width_mm"), # Width of reference device in millimeters
SLInt32("device_height_mm"), # Height of reference device in millimeters
# description string
Pointer(lambda ctx: ctx.description_offset,
StringAdapter(
Array(lambda ctx: ctx.description_size,
Field("description", 2)
)
)
),
# padding up to end of record
Padding(lambda ctx: ctx.record_size - 88),
)
emf_file = Struct("emf_file",
header_record,
Array(lambda ctx: ctx.header_record.num_of_records - 1,
generic_record
),
)
if __name__ == "__main__":
obj = emf_file.parse_stream(open("../../../tests/emf1.emf", "rb"))
print (obj)