From 41858a40b004e866460e5290cfedcf17f36c73dd Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 15 Sep 2007 23:38:56 +0000 Subject: [PATCH] Created LRF parser. --- src/libprs500/ebooks/lrf/objects.py | 435 ++++++++++++++++++++++++++++ src/libprs500/ebooks/lrf/parser.py | 60 ++++ src/libprs500/ebooks/lrf/tags.py | 279 ++++++++++++++++++ 3 files changed, 774 insertions(+) create mode 100644 src/libprs500/ebooks/lrf/objects.py create mode 100644 src/libprs500/ebooks/lrf/parser.py create mode 100644 src/libprs500/ebooks/lrf/tags.py diff --git a/src/libprs500/ebooks/lrf/objects.py b/src/libprs500/ebooks/lrf/objects.py new file mode 100644 index 0000000000..a6b552e1ab --- /dev/null +++ b/src/libprs500/ebooks/lrf/objects.py @@ -0,0 +1,435 @@ +## Copyright (C) 2007 Kovid Goyal kovid@kovidgoyal.net +## 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. +import struct, array, zlib + +from libprs500.ebooks.lrf import LRFParseError +from libprs500.ebooks.lrf.tags import Tag + +class LRFObject(object): + + tag_map = { + 0xF500: ['', ''], + 0xF502: ['infoLink', 'D'], + 0xF501: ['', ''], + + # Ruby tags + 0xF575: ['rubyAlignAndAdjust', 'W'], + 0xF576: ['rubyoverhang', 'W', {0: 'none', 1:'auto'}], + 0xF577: ['empdotsposition', 'W', {1: 'before', 2:'after'}], + 0xF578: ['','parse_empdots'], + 0xF579: ['emplineposition', 'W', {1: 'before', 2:'after'}], + 0xF57A: ['emplinetype', 'W', {0: 'none', 0x10: 'solid', 0x20: 'dashed', 0x30: 'double', 0x40: 'dotted'}] + + } + + @classmethod + def descramble_buffer(cls, buf, l, xorKey): + i = 0 + a = array.array('B',buf) + while l>0: + a[i] ^= xorKey + i+=1 + l-=1 + return a.tostring() + + @classmethod + def parse_empdots(self, tag, f): + self.refEmpDotsFont, self.empDotsFontName, self.empDotsCode = tag.contents + + def __init__(self, stream, id, scramble_key, boundary): + self._scramble_key = scramble_key + + while stream.tell() < boundary: + tag = Tag(stream) + self.handle_tag(tag, stream) + + def parse_bg_image(self, tag, f): + self.bg_image_mode, self.bg_image_id = struct.unpack(" 0x8000: + val -= 0x10000 + elif h[1] == 'B': + val = tag.paramByte() + elif h[1] == 'P': + val = tag.contents + elif h[1] != '': + val = getattr(self, h[1])(tag, stream) + + if h[1] != '' and h[0] != '': + if len(h) > 2: + val = h[2][val] + setattr(self, h[0], val) + else: + raise LRFParseError("Unknown tag in %s: %s" % (self.__class__.__name__, str(tag))) + +class LRFStream(LRFObject): + tag_map = { + 0xF504: ['', 'read_stream_size'], + 0xF554: ['stream_flags', 'W'], + 0xF505: ['', 'read_stream'], + 0xF506: ['', 'end_stream'], + } + tag_map.update(LRFObject.tag_map) + + def __init__(self, stream, id, scramble_key, boundary): + self.stream = '' + self.stream_size = 0 + self.stream_read = False + LRFObject.__init__(self, stream, id, scramble_key, boundary) + + def read_stream_size(self, tag, stream): + self.stream_size = tag.dword + + def end_stream(self, tag, stream): + self.stream_read = True + + def read_stream(self, tag, stream): + if self.stream_read: + raise LRFParseError('There can be only one stream per object') + if not hasattr(self, 'stream_flags'): + raise LRFParseError('Stream flags not initialized') + self.stream = stream.read(self.stream_size) + if self.stream_flags & 0x200 !=0: + l = len(self.stream); + key = l % self._scramble_key + 0xF; + if l > 0x400 and (isinstance(self, ImageStream) or isinstance(self, Font) or isinstance(self, SoundStream)): + l = 0x400; + self.stream = self.descramble_buffer(self.stream, l, key) + if self.stream_flags & 0x100 !=0: + decomp_size = struct.unpack(" + 0xF562: ['','do_base_button'], # + 0xF563: ['',''], # + 0xF564: ['','do_focusin_button'], # + 0xF565: ['',''], # + 0xF566: ['','do_push_button'], # + 0xF567: ['',''], # + 0xF568: ['','do_up_button'], # + 0xF569: ['',''], # + 0xF56A: ['','do_start_actions'], #start actions + 0xF56B: ['',''], #end actions + 0xF56C: ['','parse_jump_to'], #JumpTo + 0xF56D: ['','parse_send_message'], # + 0xF5D6: ['','parse_sound_stop'], # + 0xF5F9: ['','parse_run'], #Run + } + tag_map.update(LRFObject.tag_map) + + def __init__(self, stream, id, scramble_key, boundary): + self.xml = u'' + self.refimage = {} + self.actions = {} + self.to_dump = True + LRFObject.__init__(self, stream, id, scramble_key, boundary) + + def do_ref_image(self, tag, f): + self.refimage[self.button_yype] = tag.dword + + def do_base_button(self, tag, f): + self.button_type = 0 + self.actions[self.button_type] = [] + + def do_focus_in_button(self, tag, f): + self.button_type = 1 + + def do_push_button(self, tag, f): + self.button_type = 2 + + def do_up_button(self, tag, f): + self.button_type = 3 + + def do_start_actions(self, tag, f): + self.actions[self.button_type] = [] + + def parse_jump_to(self, tag, f): + self.actions[self.button_type].append((1, struct.unpack(" 0: + res.append(struct.unpack("