[Libreoffice-commits] mso-dumper.git: 6 commits - msodumper/emfrecord.py msodumper/msodraw.py msodumper/wmfrecord.py
Miklos Vajna
vmiklos at collabora.co.uk
Fri Apr 25 13:21:58 PDT 2014
msodumper/emfrecord.py | 150 +++++++++++++++++++++++++++-
msodumper/msodraw.py | 64 +++++++++++
msodumper/wmfrecord.py | 262 +++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 471 insertions(+), 5 deletions(-)
New commits:
commit 154a8a3c0cc0cb864fbebc55f13ca8b187214609
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date: Fri Apr 25 22:19:05 2014 +0200
dump EmrExtcreatepen
diff --git a/msodumper/emfrecord.py b/msodumper/emfrecord.py
index 2f7a290..6df170a 100644
--- a/msodumper/emfrecord.py
+++ b/msodumper/emfrecord.py
@@ -28,6 +28,29 @@ DIBColors = {
0x02: "DIB_PAL_INDICES"
}
+# The PenStyle enumeration defines the attributes of pens that can be used in graphics operations.
+PenStyle = {
+ 0x00000000: "PS_COSMETIC",
+ 0x00000000: "PS_ENDCAP_ROUND",
+ 0x00000000: "PS_JOIN_ROUND",
+ 0x00000000: "PS_SOLID",
+ 0x00000001: "PS_DASH",
+ 0x00000002: "PS_DOT",
+ 0x00000003: "PS_DASHDOT",
+ 0x00000004: "PS_DASHDOTDOT",
+ 0x00000005: "PS_NULL",
+ 0x00000006: "PS_INSIDEFRAME",
+ 0x00000007: "PS_USERSTYLE",
+ 0x00000008: "PS_ALTERNATE",
+ 0x00000100: "PS_ENDCAP_SQUARE",
+ 0x00000200: "PS_ENDCAP_FLAT",
+ 0x00001000: "PS_JOIN_BEVEL",
+ 0x00002000: "PS_JOIN_MITER",
+ 0x00010000: "PS_GEOMETRIC",
+ # Additional combinations
+ 0x00010200: "PS_GEOMETRIC, PS_ENDCAP_FLAT",
+}
+
class EMFStream(DOCDirStream):
def __init__(self, bytes):
@@ -530,6 +553,50 @@ class EmrBitblt(EMFRecord):
assert self.pos - posOrig == self.Size
+class LogPenEx(EMFRecord):
+ """The LogPenEx object specifies the style, width, and color of an extended logical pen."""
+ def __init__(self, parent, name):
+ EMFRecord.__init__(self, parent)
+ self.name = name
+
+ def dump(self):
+ print '<%s type="LogPenEx">' % self.name
+ self.printAndSet("PenStyle", self.readuInt32(), dict=PenStyle)
+ self.printAndSet("Width", self.readuInt32())
+ self.printAndSet("BrushStyle", self.readuInt32(), dict=wmfrecord.BrushStyle)
+ wmfrecord.ColorRef(self, "ColorRef").dump()
+ if self.BrushStyle == 0x0002: # "BS_HATCHED"
+ self.printAndSet("BrushHatch", self.readuInt32(), dict=wmfrecord.HatchStyle)
+ else:
+ self.printAndSet("BrushHatch", self.readuInt32())
+ self.printAndSet("NumStyleEntries", self.readuInt32())
+ if self.NumStyleEntries > 0:
+ print '<todo what="LogPenEx::dump(): self.NumStyleEntries != 0"/>'
+ print '</%s>' % self.name
+ self.parent.pos = self.pos
+
+
+class EmrExtcreatepen(EMFRecord):
+ """Defines an extended logical pen."""
+ def __init__(self, parent):
+ EMFRecord.__init__(self, parent)
+
+ def dump(self):
+ posOrig = self.pos
+ self.printAndSet("Type", self.readuInt32())
+ self.printAndSet("Size", self.readuInt32(), hexdump=False)
+ self.printAndSet("ihPen", self.readuInt32(), hexdump=False)
+ self.printAndSet("offBmi", self.readuInt32(), hexdump=False)
+ self.printAndSet("cbBmi", self.readuInt32(), hexdump=False)
+ self.printAndSet("offBits", self.readuInt32(), hexdump=False)
+ self.printAndSet("cbBits", self.readuInt32(), hexdump=False)
+ LogPenEx(self, "elp").dump()
+ if self.cbBmi:
+ print '<todo what="LogPenEx::dump(): self.cbBmi != 0"/>'
+ if self.cbBits:
+ print '<todo what="LogPenEx::dump(): self.cbBits != 0"/>'
+
+
class EmrEof(EMFRecord):
"""Indicates the end of the metafile and specifies a palette."""
def __init__(self, parent):
@@ -747,7 +814,7 @@ RecordType = {
0x0000005C: ['EMR_POLYDRAW16'],
0x0000005D: ['EMR_CREATEMONOBRUSH'],
0x0000005E: ['EMR_CREATEDIBPATTERNBRUSHPT'],
- 0x0000005F: ['EMR_EXTCREATEPEN'],
+ 0x0000005F: ['EMR_EXTCREATEPEN', EmrExtcreatepen],
0x00000060: ['EMR_POLYTEXTOUTA'],
0x00000061: ['EMR_POLYTEXTOUTW'],
0x00000062: ['EMR_SETICMMODE', EmrSeticmmode],
commit 98ba933a00f93421dc705c144a846c704c2722ad
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date: Fri Apr 25 21:48:57 2014 +0200
dump EmrBitblt
diff --git a/msodumper/emfrecord.py b/msodumper/emfrecord.py
index 55eb34c..2f7a290 100644
--- a/msodumper/emfrecord.py
+++ b/msodumper/emfrecord.py
@@ -22,6 +22,12 @@ RegionMode = {
0x05: "RGN_COPY"
}
+DIBColors = {
+ 0x00: "DIB_RGB_COLORS",
+ 0x01: "DIB_PAL_COLORS",
+ 0x02: "DIB_PAL_INDICES"
+}
+
class EMFStream(DOCDirStream):
def __init__(self, bytes):
@@ -497,6 +503,33 @@ class EmrStrokeandfillpath(EMFRecord):
assert self.pos - posOrig == self.Size
+class EmrBitblt(EMFRecord):
+ """Specifies a block transfer of pixels from a source bitmap to a destination rectangle."""
+ def __init__(self, parent):
+ EMFRecord.__init__(self, parent)
+
+ def dump(self):
+ posOrig = self.pos
+ self.printAndSet("Type", self.readuInt32())
+ self.printAndSet("Size", self.readuInt32(), hexdump=False)
+ wmfrecord.RectL(self, "Bounds").dump()
+ self.printAndSet("xDest", self.readInt32(), hexdump=False)
+ self.printAndSet("yDest", self.readInt32(), hexdump=False)
+ self.printAndSet("cxDest", self.readInt32(), hexdump=False)
+ self.printAndSet("cyDest", self.readInt32(), hexdump=False)
+ self.printAndSet("BitBltRasterOperation", self.readuInt32(), dict=wmfrecord.RasterPolishMap)
+ self.printAndSet("xSrc", self.readInt32(), hexdump=False)
+ self.printAndSet("ySrc", self.readInt32(), hexdump=False)
+ XForm(self, "XformSrc").dump()
+ wmfrecord.ColorRef(self, "BkColorSrc").dump()
+ self.printAndSet("UsageSrc", self.readInt32(), dict=DIBColors)
+ self.printAndSet("offBmiSrc", self.readuInt32())
+ self.printAndSet("cbBmiSrc", self.readuInt32())
+ self.printAndSet("offBitsSrc", self.readuInt32())
+ self.printAndSet("cbBitsSrc", self.readuInt32())
+ assert self.pos - posOrig == self.Size
+
+
class EmrEof(EMFRecord):
"""Indicates the end of the metafile and specifies a palette."""
def __init__(self, parent):
@@ -695,7 +728,7 @@ RecordType = {
0x00000049: ['EMR_INVERTRGN'],
0x0000004A: ['EMR_PAINTRGN'],
0x0000004B: ['EMR_EXTSELECTCLIPRGN', EmrExtselectcliprgn],
- 0x0000004C: ['EMR_BITBLT'],
+ 0x0000004C: ['EMR_BITBLT', EmrBitblt],
0x0000004D: ['EMR_STRETCHBLT'],
0x0000004E: ['EMR_MASKBLT'],
0x0000004F: ['EMR_PLGBLT'],
diff --git a/msodumper/wmfrecord.py b/msodumper/wmfrecord.py
index dd4e8ea..5b23e35 100644
--- a/msodumper/wmfrecord.py
+++ b/msodumper/wmfrecord.py
@@ -34,6 +34,268 @@ HatchStyle = {
}
+# No idea what's the proper name of this thing, see
+# http://msdn.microsoft.com/en-us/library/dd145130%28VS.85%29.aspx
+RasterPolishMap = {
+ 0x00000042: "0",
+ 0x00010289: "DPSoon",
+ 0x00020C89: "DPSona",
+ 0x000300AA: "PSon",
+ 0x00040C88: "SDPona",
+ 0x000500A9: "DPon",
+ 0x00060865: "PDSxnon",
+ 0x000702C5: "PDSaon",
+ 0x00080F08: "SDPnaa",
+ 0x00090245: "PDSxon",
+ 0x000A0329: "DPna",
+ 0x000B0B2A: "PSDnaon",
+ 0x000C0324: "SPna",
+ 0x000D0B25: "PDSnaon",
+ 0x000E08A5: "PDSonon",
+ 0x000F0001: "Pn",
+ 0x00100C85: "PDSona",
+ 0x001100A6: "DSon",
+ 0x00120868: "SDPxnon",
+ 0x001302C8: "SDPaon",
+ 0x00140869: "DPSxnon",
+ 0x001502C9: "DPSaon",
+ 0x00165CCA: "PSDPSanaxx",
+ 0x00171D54: "SSPxDSxaxn",
+ 0x00180D59: "SPxPDxa",
+ 0x00191CC8: "SDPSanaxn",
+ 0x001A06C5: "PDSPaox",
+ 0x001B0768: "SDPSxaxn",
+ 0x001C06CA: "PSDPaox",
+ 0x001D0766: "DSPDxaxn",
+ 0x001E01A5: "PDSox",
+ 0x001F0385: "PDSoan",
+ 0x00200F09: "DPSnaa",
+ 0x00210248: "SDPxon",
+ 0x00220326: "DSna",
+ 0x00230B24: "SPDnaon",
+ 0x00240D55: "SPxDSxa",
+ 0x00251CC5: "PDSPanaxn",
+ 0x002606C8: "SDPSaox",
+ 0x00271868: "SDPSxnox",
+ 0x00280369: "DPSxa",
+ 0x002916CA: "PSDPSaoxxn",
+ 0x002A0CC9: "DPSana",
+ 0x002B1D58: "SSPxPDxaxn",
+ 0x002C0784: "SPDSoax",
+ 0x002D060A: "PSDnox",
+ 0x002E064A: "PSDPxox",
+ 0x002F0E2A: "PSDnoan",
+ 0x0030032A: "PSna",
+ 0x00310B28: "SDPnaon",
+ 0x00320688: "SDPSoox",
+ 0x00330008: "Sn",
+ 0x003406C4: "SPDSaox",
+ 0x00351864: "SPDSxnox",
+ 0x003601A8: "SDPox",
+ 0x00370388: "SDPoan",
+ 0x0038078A: "PSDPoax",
+ 0x00390604: "SPDnox",
+ 0x003A0644: "SPDSxox",
+ 0x003B0E24: "SPDnoan",
+ 0x003C004A: "PSx",
+ 0x003D18A4: "SPDSonox",
+ 0x003E1B24: "SPDSnaox",
+ 0x003F00EA: "PSan",
+ 0x00400F0A: "PSDnaa",
+ 0x00410249: "DPSxon",
+ 0x00420D5D: "SDxPDxa",
+ 0x00431CC4: "SPDSanaxn",
+ 0x00440328: "SDna",
+ 0x00450B29: "DPSnaon",
+ 0x004606C6: "DSPDaox",
+ 0x0047076A: "PSDPxaxn",
+ 0x00480368: "SDPxa",
+ 0x004916C5: "PDSPDaoxxn",
+ 0x004A0789: "DPSDoax",
+ 0x004B0605: "PDSnox",
+ 0x004C0CC8: "SDPana",
+ 0x004D1954: "SSPxDSxoxn",
+ 0x004E0645: "PDSPxox",
+ 0x004F0E25: "PDSnoan",
+ 0x00500325: "PDna",
+ 0x00510B26: "DSPnaon",
+ 0x005206C9: "DPSDaox",
+ 0x00530764: "SPDSxaxn",
+ 0x005408A9: "DPSonon",
+ 0x00550009: "Dn",
+ 0x005601A9: "DPSox",
+ 0x00570389: "DPSoan",
+ 0x00580785: "PDSPoax",
+ 0x00590609: "DPSnox",
+ 0x005A0049: "DPx",
+ 0x005B18A9: "DPSDonox",
+ 0x005C0649: "DPSDxox",
+ 0x005D0E29: "DPSnoan",
+ 0x005E1B29: "DPSDnaox",
+ 0x005F00E9: "DPan",
+ 0x00600365: "PDSxa",
+ 0x006116C6: "DSPDSaoxxn",
+ 0x00620786: "DSPDoax",
+ 0x00630608: "SDPnox",
+ 0x00640788: "SDPSoax",
+ 0x00650606: "DSPnox",
+ 0x00660046: "DSx",
+ 0x006718A8: "SDPSonox",
+ 0x006858A6: "DSPDSonoxxn",
+ 0x00690145: "PDSxxn",
+ 0x006A01E9: "DPSax",
+ 0x006B178A: "PSDPSoaxxn",
+ 0x006C01E8: "SDPax",
+ 0x006D1785: "PDSPDoaxxn",
+ 0x006E1E28: "SDPSnoax",
+ 0x006F0C65: "PDSxnan",
+ 0x00700CC5: "PDSana",
+ 0x00711D5C: "SSDxPDxaxn",
+ 0x00720648: "SDPSxox",
+ 0x00730E28: "SDPnoan",
+ 0x00740646: "DSPDxox",
+ 0x00750E26: "DSPnoan",
+ 0x00761B28: "SDPSnaox",
+ 0x007700E6: "DSan",
+ 0x007801E5: "PDSax",
+ 0x00791786: "DSPDSoaxxn",
+ 0x007A1E29: "DPSDnoax",
+ 0x007B0C68: "SDPxnan",
+ 0x007C1E24: "SPDSnoax",
+ 0x007D0C69: "DPSxnan",
+ 0x007E0955: "SPxDSxo",
+ 0x007F03C9: "DPSaan",
+ 0x008003E9: "DPSaa",
+ 0x00810975: "SPxDSxon",
+ 0x00820C49: "DPSxna",
+ 0x00831E04: "SPDSnoaxn",
+ 0x00840C48: "SDPxna",
+ 0x00851E05: "PDSPnoaxn",
+ 0x008617A6: "DSPDSoaxx",
+ 0x008701C5: "PDSaxn",
+ 0x008800C6: "DSa",
+ 0x00891B08: "SDPSnaoxn",
+ 0x008A0E06: "DSPnoa",
+ 0x008B0666: "DSPDxoxn",
+ 0x008C0E08: "SDPnoa",
+ 0x008D0668: "SDPSxoxn",
+ 0x008E1D7C: "SSDxPDxax",
+ 0x008F0CE5: "PDSanan",
+ 0x00900C45: "PDSxna",
+ 0x00911E08: "SDPSnoaxn",
+ 0x009217A9: "DPSDPoaxx",
+ 0x009301C4: "SPDaxn",
+ 0x009417AA: "PSDPSoaxx",
+ 0x009501C9: "DPSaxn",
+ 0x00960169: "DPSxx",
+ 0x0097588A: "PSDPSonoxx",
+ 0x00981888: "SDPSonoxn",
+ 0x00990066: "DSxn",
+ 0x009A0709: "DPSnax",
+ 0x009B07A8: "SDPSoaxn",
+ 0x009C0704: "SPDnax",
+ 0x009D07A6: "DSPDoaxn",
+ 0x009E16E6: "DSPDSaoxx",
+ 0x009F0345: "PDSxan",
+ 0x00A000C9: "DPa",
+ 0x00A11B05: "PDSPnaoxn",
+ 0x00A20E09: "DPSnoa",
+ 0x00A30669: "DPSDxoxn",
+ 0x00A41885: "PDSPonoxn",
+ 0x00A50065: "PDxn",
+ 0x00A60706: "DSPnax",
+ 0x00A707A5: "PDSPoaxn",
+ 0x00A803A9: "DPSoa",
+ 0x00A90189: "DPSoxn",
+ 0x00AA0029: "D",
+ 0x00AB0889: "DPSono",
+ 0x00AC0744: "SPDSxax",
+ 0x00AD06E9: "DPSDaoxn",
+ 0x00AE0B06: "DSPnao",
+ 0x00AF0229: "DPno",
+ 0x00B00E05: "PDSnoa",
+ 0x00B10665: "PDSPxoxn",
+ 0x00B21974: "SSPxDSxox",
+ 0x00B30CE8: "SDPanan",
+ 0x00B4070A: "PSDnax",
+ 0x00B507A9: "DPSDoaxn",
+ 0x00B616E9: "DPSDPaoxx",
+ 0x00B70348: "SDPxan",
+ 0x00B8074A: "PSDPxax",
+ 0x00B906E6: "DSPDaoxn",
+ 0x00BA0B09: "DPSnao",
+ 0x00BB0226: "DSno",
+ 0x00BC1CE4: "SPDSanax",
+ 0x00BD0D7D: "SDxPDxan",
+ 0x00BE0269: "DPSxo",
+ 0x00BF08C9: "DPSano",
+ 0x00C000CA: "PSa",
+ 0x00C11B04: "SPDSnaoxn",
+ 0x00C21884: "SPDSonoxn",
+ 0x00C3006A: "PSxn",
+ 0x00C40E04: "SPDnoa",
+ 0x00C50664: "SPDSxoxn",
+ 0x00C60708: "SDPnax",
+ 0x00C707AA: "PSDPoaxn",
+ 0x00C803A8: "SDPoa",
+ 0x00C90184: "SPDoxn",
+ 0x00CA0749: "DPSDxax",
+ 0x00CB06E4: "SPDSaoxn",
+ 0x00CC0020: "S",
+ 0x00CD0888: "SDPono",
+ 0x00CE0B08: "SDPnao",
+ 0x00CF0224: "SPno",
+ 0x00D00E0A: "PSDnoa",
+ 0x00D1066A: "PSDPxoxn",
+ 0x00D20705: "PDSnax",
+ 0x00D307A4: "SPDSoaxn",
+ 0x00D41D78: "SSPxPDxax",
+ 0x00D50CE9: "DPSanan",
+ 0x00D616EA: "PSDPSaoxx",
+ 0x00D70349: "DPSxan",
+ 0x00D80745: "PDSPxax",
+ 0x00D906E8: "SDPSaoxn",
+ 0x00DA1CE9: "DPSDanax",
+ 0x00DB0D75: "SPxDSxan",
+ 0x00DC0B04: "SPDnao",
+ 0x00DD0228: "SDno",
+ 0x00DE0268: "SDPxo",
+ 0x00DF08C8: "SDPano",
+ 0x00E003A5: "PDSoa",
+ 0x00E10185: "PDSoxn",
+ 0x00E20746: "DSPDxax",
+ 0x00E306EA: "PSDPaoxn",
+ 0x00E40748: "SDPSxax",
+ 0x00E506E5: "PDSPaoxn",
+ 0x00E61CE8: "SDPSanax",
+ 0x00E70D79: "SPxPDxan",
+ 0x00E81D74: "SSPxDSxax",
+ 0x00E95CE6: "DSPDSanaxxn",
+ 0x00EA02E9: "DPSao",
+ 0x00EB0849: "DPSxno",
+ 0x00EC02E8: "SDPao",
+ 0x00ED0848: "SDPxno",
+ 0x00EE0086: "DSo",
+ 0x00EF0A08: "SDPnoo",
+ 0x00F00021: "P",
+ 0x00F10885: "PDSono",
+ 0x00F20B05: "PDSnao",
+ 0x00F3022A: "PSno",
+ 0x00F40B0A: "PSDnao",
+ 0x00F50225: "PDno",
+ 0x00F60265: "PDSxo",
+ 0x00F708C5: "PDSano",
+ 0x00F802E5: "PDSao",
+ 0x00F90845: "PDSxno",
+ 0x00FA0089: "DPo",
+ 0x00FB0A09: "DPSnoo",
+ 0x00FC008A: "PSo",
+ 0x00FD0A0A: "PSDnoo",
+ 0x00FE02A9: "DPSoo",
+ 0x00FF0062: "1"
+}
+
+
class WMFRecord(DOCDirStream):
def __init__(self, parent):
DOCDirStream.__init__(self, parent.bytes)
commit 20ca1d9b734f333d00066724fb5488dfa8b06d40
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date: Fri Apr 25 16:04:15 2014 +0200
dump EmrStrokeandfillpath
diff --git a/msodumper/emfrecord.py b/msodumper/emfrecord.py
index 56455e9..55eb34c 100644
--- a/msodumper/emfrecord.py
+++ b/msodumper/emfrecord.py
@@ -483,6 +483,20 @@ class EmrFillpath(EMFRecord):
assert self.pos - posOrig == self.Size
+class EmrStrokeandfillpath(EMFRecord):
+ """The EMR_STROKEANDFILLPATH record closes any open figures in a path, strokes the outline of the
+ path by using the current pen, and fills its interior by using the current brush."""
+ def __init__(self, parent):
+ EMFRecord.__init__(self, parent)
+
+ def dump(self):
+ posOrig = self.pos
+ self.printAndSet("Type", self.readuInt32())
+ self.printAndSet("Size", self.readuInt32(), hexdump=False)
+ wmfrecord.RectL(self, "Bounds").dump()
+ assert self.pos - posOrig == self.Size
+
+
class EmrEof(EMFRecord):
"""Indicates the end of the metafile and specifies a palette."""
def __init__(self, parent):
@@ -669,7 +683,7 @@ RecordType = {
0x0000003C: ['EMR_ENDPATH', EmrEndpath],
0x0000003D: ['EMR_CLOSEFIGURE', EmrClosefigure],
0x0000003E: ['EMR_FILLPATH', EmrFillpath],
- 0x0000003F: ['EMR_STROKEANDFILLPATH'],
+ 0x0000003F: ['EMR_STROKEANDFILLPATH', EmrStrokeandfillpath],
0x00000040: ['EMR_STROKEPATH'],
0x00000041: ['EMR_FLATTENPATH'],
0x00000042: ['EMR_WIDENPATH'],
commit 608069a6b41ca7608bc026aa8647b04c8f5dc078
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date: Fri Apr 25 16:01:30 2014 +0200
dump EmrFillpath
diff --git a/msodumper/emfrecord.py b/msodumper/emfrecord.py
index 36c9f52..56455e9 100644
--- a/msodumper/emfrecord.py
+++ b/msodumper/emfrecord.py
@@ -469,6 +469,20 @@ class EmrClosefigure(EMFRecord):
assert self.pos - posOrig == self.Size
+class EmrFillpath(EMFRecord):
+ """Closes any open figures in the current path and fills the path's
+ interior with the current brush and polygon-filling mode."""
+ def __init__(self, parent):
+ EMFRecord.__init__(self, parent)
+
+ def dump(self):
+ posOrig = self.pos
+ self.printAndSet("Type", self.readuInt32())
+ self.printAndSet("Size", self.readuInt32(), hexdump=False)
+ wmfrecord.RectL(self, "Bounds").dump()
+ assert self.pos - posOrig == self.Size
+
+
class EmrEof(EMFRecord):
"""Indicates the end of the metafile and specifies a palette."""
def __init__(self, parent):
@@ -654,7 +668,7 @@ RecordType = {
0x0000003B: ['EMR_BEGINPATH', EmrBeginpath],
0x0000003C: ['EMR_ENDPATH', EmrEndpath],
0x0000003D: ['EMR_CLOSEFIGURE', EmrClosefigure],
- 0x0000003E: ['EMR_FILLPATH'],
+ 0x0000003E: ['EMR_FILLPATH', EmrFillpath],
0x0000003F: ['EMR_STROKEANDFILLPATH'],
0x00000040: ['EMR_STROKEPATH'],
0x00000041: ['EMR_FLATTENPATH'],
commit c690ade6318e568fc051771d29870286888408e7
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date: Fri Apr 25 15:59:12 2014 +0200
dump EmrClosefigure
diff --git a/msodumper/emfrecord.py b/msodumper/emfrecord.py
index 68ad15b..36c9f52 100644
--- a/msodumper/emfrecord.py
+++ b/msodumper/emfrecord.py
@@ -457,6 +457,18 @@ class EmrEndpath(EMFRecord):
assert self.pos - posOrig == self.Size
+class EmrClosefigure(EMFRecord):
+ """This record closes an open figure in a path."""
+ def __init__(self, parent):
+ EMFRecord.__init__(self, parent)
+
+ def dump(self):
+ posOrig = self.pos
+ self.printAndSet("Type", self.readuInt32())
+ self.printAndSet("Size", self.readuInt32(), hexdump=False)
+ assert self.pos - posOrig == self.Size
+
+
class EmrEof(EMFRecord):
"""Indicates the end of the metafile and specifies a palette."""
def __init__(self, parent):
@@ -641,7 +653,7 @@ RecordType = {
0x0000003A: ['EMR_SETMITERLIMIT'],
0x0000003B: ['EMR_BEGINPATH', EmrBeginpath],
0x0000003C: ['EMR_ENDPATH', EmrEndpath],
- 0x0000003D: ['EMR_CLOSEFIGURE'],
+ 0x0000003D: ['EMR_CLOSEFIGURE', EmrClosefigure],
0x0000003E: ['EMR_FILLPATH'],
0x0000003F: ['EMR_STROKEANDFILLPATH'],
0x00000040: ['EMR_STROKEPATH'],
commit dcf267f84f3cd325fddd0f143a751d415c79b265
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date: Fri Apr 25 15:44:21 2014 +0200
msodraw: dump BlipEMF
Not connected to the EMF dumper yet, just provide the raw data as a
base64 dump.
diff --git a/msodumper/msodraw.py b/msodumper/msodraw.py
index 0b4f99a..cfaf245 100644
--- a/msodumper/msodraw.py
+++ b/msodumper/msodraw.py
@@ -7,6 +7,9 @@
import globals, xlsmodel
import sys
+import textwrap
+import zlib
+import base64
from pptrecord import shapeTypes
def indent (level):
@@ -33,6 +36,9 @@ def hexdump(value):
ret.append("%02x" % ord(i))
return "".join(ret)
+def inflate(bytes):
+ return textwrap.fill(base64.b64encode(zlib.decompress(bytes)), width=160)
+
class RecordHeader:
size = 8
@@ -54,6 +60,7 @@ class RecordHeader:
FClientAnchor = 0xF010
FClientData = 0xF011
FConnectorRule = 0xF012
+ BlipEMF = 0xF01A
BlipPNG = 0xF01E
FDGSL = 0xF119
SplitMenuColorContainer = 0xF11E
@@ -291,6 +298,62 @@ class FDGSL:
for shape in self.shapesSelected:
recHdl.appendLine(" ID of shape selected: %d"%shape)
+class MetafileHeader:
+ """[MS-ODRAW] 2.2.31 The OfficeArtMetafileHeader record specifies how to process a metafile."""
+ def __init__(self, strm):
+ self.strm = strm
+
+ def parseBytes(self, rh):
+ self.cbSize = self.strm.readUnsignedInt(4)
+ self.strm.readBytes(16) # TODO rcBounds
+ self.strm.readBytes(8) # TODO ptSize
+ self.cbSave = self.strm.readUnsignedInt(4)
+ self.compression = self.strm.readUnsignedInt(1)
+ self.filter = self.strm.readUnsignedInt(1)
+
+ def appendLines(self, recHdl, rh):
+ pass
+
+ def dumpXml(self, recHdl, model, rh):
+ recHdl.appendLine('<metafileHeader type="OfficeArtMetafileHeader">')
+ recHdl.appendLine('<cbSize value="%s"/>' % self.cbSize)
+ recHdl.appendLine('<cbSave value="%s"/>' % self.cbSave)
+ recHdl.appendLine('<compression value="%s"/>' % hex(self.compression))
+ recHdl.appendLine('<filter value="%s"/>' % hex(self.filter))
+ recHdl.appendLine('</metafileHeader>')
+
+class BlipEMF:
+ """[MS-ODRAW] 2.2.24 The OfficeArtBlipEMF record specifies BLIP file data for the enhanced metafile format (EMF)."""
+ def __init__(self, strm):
+ self.strm = strm
+
+ def __parseBytes(self, rh):
+ pos = self.strm.pos
+ self.rgbUid1 = self.strm.readBytes(16)
+ if rh.recInstance == 0x3D5:
+ self.rgbUid2 = self.strm.readBytes(16)
+ else:
+ self.rgbUid2 = None
+ self.metafileHeader = MetafileHeader(self.strm)
+ self.metafileHeader.parseBytes(rh)
+ self.BLIPFileData = self.strm.readBytes(self.metafileHeader.cbSave)
+
+ def appendLines(self, recHdl, rh):
+ pass
+
+ def dumpXml(self, recHdl, model, rh):
+ recHdl.appendLine('<blipEmf type="OfficeArtBlipEMF">')
+ self.__parseBytes(rh)
+ recHdl.appendLine('<rgbUid1 value="%s"/>' % hexdump(self.rgbUid1))
+ if self.rgbUid2:
+ recHdl.appendLine('<rgbUid2 value="%s"/>' % hexdump(self.rgbUid2))
+ self.metafileHeader.dumpXml(recHdl, model, rh)
+ if self.metafileHeader.compression == 0x00:
+ recHdl.appendLine('<BLIPFileData value="%s"/>' % inflate(self.BLIPFileData))
+ else:
+ recHdl.appendLine('<todo what="BlipEMF::dumpXml(): unexpected metafileHeader.compression == %s"/>' % hex(self.metafileHeader.compression))
+ recHdl.appendLine('</blipEmf>')
+
class BlipPNG:
def __init__(self, strm):
self.strm = strm
@@ -1286,6 +1349,7 @@ recData = {
RecordHeader.Type.FConnectorRule: FConnectorRule,
RecordHeader.Type.FDGSL: FDGSL,
RecordHeader.Type.BlipPNG: BlipPNG,
+ RecordHeader.Type.BlipEMF: BlipEMF,
RecordHeader.Type.FClientAnchor: FClientAnchorSheet,
RecordHeader.Type.FClientData: FClientData,
RecordHeader.Type.FClientTextbox: FClientTextbox,
More information about the Libreoffice-commits
mailing list