aboutsummaryrefslogtreecommitdiff
path: root/gui
diff options
context:
space:
mode:
authorVicent Marti2008-11-13 14:25:39 +0000
committerVicent Marti2008-11-13 14:25:39 +0000
commitf7bdf6b40f883ceeac2034763bc0bebc174a13df (patch)
tree247e1f379c591715807b14182a29b94f191dbb20 /gui
parent4e51c62e3978e451beb03c6e7c221a0709851e45 (diff)
downloadscummvm-rg350-f7bdf6b40f883ceeac2034763bc0bebc174a13df.tar.gz
scummvm-rg350-f7bdf6b40f883ceeac2034763bc0bebc174a13df.tar.bz2
scummvm-rg350-f7bdf6b40f883ceeac2034763bc0bebc174a13df.zip
Binary theme format parser.
Warning: Work in progress. May erase hard drive. svn-id: r35046
Diffstat (limited to 'gui')
-rw-r--r--gui/themes/themeparser.py279
1 files changed, 279 insertions, 0 deletions
diff --git a/gui/themes/themeparser.py b/gui/themes/themeparser.py
new file mode 100644
index 0000000000..c8c1670c13
--- /dev/null
+++ b/gui/themes/themeparser.py
@@ -0,0 +1,279 @@
+#!/usr/bin/env python
+# encoding: utf-8
+
+"""
+ " ScummVM - Graphic Adventure Engine
+ "
+ " ScummVM is the legal property of its developers, whose names
+ " are too numerous to list here. Please refer to the COPYRIGHT
+ " file distributed with this source distribution.
+ "
+ " This program is free software; you can redistribute it and/or
+ " modify it under the terms of the GNU General Public License
+ " as published by the Free Software Foundation; either version 2
+ " of the License, or (at your option) any later version.
+ "
+ " This program 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 General Public License for more details.
+ "
+ " You should have received a copy of the GNU General Public License
+ " along with this program; if not, write to the Free Software
+ " Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ "
+ " $URL$
+ " $Id$
+"""
+
+from __future__ import with_statement
+import os
+import xml.dom.minidom as DOM
+import struct
+
+class STXBinaryFile:
+ class InvalidRGBColor(Exception):
+ pass
+
+ class InvalidResolution(Exception):
+ pass
+
+ BLOCK_HEADERS = {
+ "palette" : 0x0100000A,
+ "bitmaps" : 0x0100000B,
+ "fonts" : 0x0100000C,
+ "defaults" : 0x0100000D,
+ "cursor" : 0x0100000E,
+ "drawdata" : 0x0100000F
+ }
+
+ DRAWSTEP_FORMAT_DEF = [
+ "stroke", "shadow",
+ "bevel", "factor",
+ "fg_color", "bg_color",
+ "fill", "gradient_start",
+ "gradient_end", "bevel_color",
+ "gradient_factor",
+ ]
+
+ DRAWSTEP_FORMAT = [
+ "func", "radius", "width", "height",
+ "xpos", "ypos", "file", "orientation",
+ ] + DRAWSTEP_FORMAT_DEF
+
+ def __init__(self, themeName, autoLoad = True, verbose = False):
+ self._themeName = themeName
+ self._stxFiles = []
+ self._verbose = verbose
+
+ if autoLoad:
+ if not os.path.isdir(themeName) or not os.path.isfile(os.path.join(themeName, "THEMERC")):
+ raise IOError
+
+ for filename in os.listdir(themeName):
+ filename = os.path.join(themeName, filename)
+ if os.path.isfile(filename) and filename.endswith('.stx'):
+ self._stxFiles.append(filename)
+
+ def debug(self, text):
+ if self._verbose: print text
+
+ def debugBinary(self, data):
+ if self._verbose:
+ print "BINARY OUTPUT (%d bytes):" % len(data), " ".join(["%0.2X" % ord(c) for c in data])
+
+ def addSTXFile(self, filename):
+ if not os.path.isfile(filename):
+ raise IOError
+ else:
+ self._stxFiles.append(filename)
+
+ def parse(self):
+ if not self._stxFiles:
+ self.debug("No files have been loaded for parsing on the theme.")
+ raise IOError
+
+ for f in self._stxFiles:
+ self.debug("Parsing %s." % f)
+ with open(f) as stxFile:
+ self.__parseFile(stxFile)
+
+ def __parseFile(self, xmlFile):
+ stxDom = DOM.parse(xmlFile)
+
+ for layout in stxDom.getElementsByTagName("layout_info"):
+ self.__parseLayout(layout)
+
+ for render in stxDom.getElementsByTagName("render_info"):
+ self.__parseRender(render)
+
+ stxDom.unlink()
+
+ def __parseDrawStep(self, drawstepDom):
+ pass
+
+
+ def __parseDrawStepToBin(self, stepDict, isDefault):
+ DRAWSTEP_BININFO = {
+ "stroke" : "B", "shadow" : "B", "bevel" : "B",
+ "factor" : "B", "fg_color" : "BBB", "bg_color" : "BBB",
+ "fill" : "B", "func" : "B", "radius" : "i",
+ "width" : "i", "height" : "i", "xpos" : "i",
+ "ypos" : "i", "orientation" : "B", "file" : "B%ds",
+
+ "gradient_start" : "BBB", "gradient_end" : "BBB",
+ "bevel_color" : "BBB", "gradient_factor" : "B",
+ }
+
+ packLayout = ""
+ packData = []
+ attributes = DRAWSTEP_FORMAT_DEF if isDefault else DRAWSTEP_FORMAT
+
+ for attr in attributes:
+ layout = DRAWSTEP_BININFO[attr]
+ data = stepDict[attr]
+
+ if layout == "B%ds":
+ packLayout += layout % (len(data) + 1)
+ packData.append(len(data))
+ packData.append(data)
+
+ else:
+ packLayout += stepDict[attr]
+
+ if isinstance(data, tuple):
+ for d in data:
+ packData.append(d)
+ else:
+ packData.append(data)
+
+ stepBin = struct.pack(packLayout, *tuple(packData))
+ self.debugBinary(stepBin)
+ return stepBin
+
+
+ def __parseResolutionToBin(self, resString):
+ """
+ /b bII bII bII/
+ b => number of resolution sections
+ bII => exclude byte, X resolution, Y resolution
+ """
+
+ if resString == "":
+ return struct.pack("bbII", 1, 0, 0, 0)
+
+ resolutions = resString.split(", ")
+ packFormat = "b" + "bII" * len(resolutions)
+ packData = [len(resolutions)]
+
+ for res in resolutions:
+ exclude = 0
+ if res[0] == '-':
+ exclude = 1
+ res = res[1:]
+
+ try:
+ x, y = res.split('x')
+ x = 0 if x == 'X' else int(x)
+ y = 0 if y == 'Y' else int(y)
+ except ValueError:
+ raise InvalidResolution
+
+ packData.append(exclude)
+ packData.append(x)
+ packData.append(y)
+
+ buff = struct.pack(packFormat, *tuple(packData))
+ self.debug("Pack format: %s => %s" % (packFormat, str(packData)))
+ self.debugBinary(buff)
+ return buff
+
+ def __parseRGBToBin(self, color):
+ """
+ /BBB/
+ B => red color byte
+ B => green color byte
+ B => blue color byte
+ """
+
+ try:
+ rgb = tuple(map(int, color.split(", ")))
+ except ValueError:
+ raise self.InvalidRGBColor
+
+ if len(rgb) != 3:
+ raise self.InvalidRGBColor
+
+ for c in rgb:
+ if c < 0 or c > 255:
+ raise self.InvalidRGBColor
+
+ rgb = struct.pack("BBB", *tuple(rgb))
+
+ self.debugBinary(rgb)
+ return rgb
+
+ def __parseColors(self, paletteDom):
+ self._colors = {}
+
+ for color in paletteDom.getElementsByTagName("color"):
+ color_name = color.getAttribute('name')
+ color_rgb = self.__parseRGBToBin(color.getAttribute('rgb'))
+
+ self._colors[color_name] = color_rgb
+ self.debug("COLOR: %s" % (color_name))
+
+
+ def __parseBitmaps(self, bitmapsDom):
+ self._bitmaps = []
+
+ for bitmap in bitmapsDom.getElementsByTagName("bitmap"):
+ bmpName = bitmap.getAttribute("filename")
+ resolution = self.__parseResolutionToBin(bitmap.getAttribute("resolution"))
+
+ self._bitmaps.append((bmpName, resolution))
+ self.debug("BITMAP: %s" % bmpName)
+
+ def __parseFonts(self, fontsDom):
+ self._fonts = []
+
+ for font in fontsDom.getElementsByTagName("font"):
+ ident = font.getAttribute("id")
+
+ color = font.getAttribute("color")
+ try:
+ color = self.__parseRGBToBin(color)
+ except self.InvalidRGBColor:
+ if color not in self._colors:
+ raise self.InvalidRGBColor
+ color = self._colors[color]
+
+ filename = font.getAttribute("file")
+# if filename != "default" and not os.path.isfile(os.path.join(self._themeName, filename)):
+# raise IOError
+
+ resolution = self.__parseResolutionToBin(font.getAttribute("resolution"))
+ self.debug("FONT: %s @ %s" % (ident, filename))
+ self._fonts.append((ident, filename, color, resolution))
+
+
+ def __parseLayout(self, layoutDom):
+ self.debug("GLOBAL SECTION: LAYOUT INFO.")
+
+ def __parseRender(self, renderDom):
+ self.debug("GLOBAL SECTION: RENDER INFO.")
+
+ paletteDom = renderDom.getElementsByTagName("palette")[0]
+ bitmapsDom = renderDom.getElementsByTagName("bitmaps")[0]
+ fontsDom = renderDom.getElementsByTagName("fonts")[0]
+ defaultsDom = renderDom.getElementsByTagName("defaults")[0]
+
+ self.__parseColors(paletteDom)
+ self.__parseBitmaps(bitmapsDom)
+ self.__parseFonts(fontsDom)
+
+
+if __name__ == '__main__':
+ bin = STXBinaryFile('scummmodern', True, True)
+ bin.parse()
+ \ No newline at end of file