From d51c9b672a2a23d9e9c7bc4c2d366ca8d66bda0e Mon Sep 17 00:00:00 2001 From: Matthias Kramm Date: Mon, 24 Aug 2009 18:06:31 +0200 Subject: [PATCH] merged in Ricardo Pedroso's new pdf2swf gui --- lib/MD5.c | 2 +- lib/MD5.h | 2 +- lib/as3/scripts.c | 2 +- lib/gfxpoly/poly.c | 2 +- wx/app.py | 413 +++++++++++++ wx/document.py | 163 +++++ wx/gpdf2swf.ico | Bin 0 -> 22382 bytes wx/gpdf2swf.py | 48 ++ wx/gui/__init__.py | 26 + wx/gui/boldstatictext.py | 33 ++ wx/gui/choicetext.py | 73 +++ wx/gui/dialogs.py | 123 ++++ wx/gui/fields.py | 195 ++++++ wx/gui/main.py | 323 ++++++++++ wx/gui/options/__init__.py | 26 + wx/gui/options/quality.py | 94 +++ wx/gui/options/viewer.py | 186 ++++++ wx/gui/plugin.py | 97 +++ wx/{images.py => pdf2swf.gui.old.py} | 1070 ++++++++++++++++++++++++++++++++- wx/pdf2swf.py | 1088 ---------------------------------- wx/viewers/__init__.py | 24 + wx/viewers/raw.py | 119 ++++ wx/viewers/rfx.py | 363 ++++++++++++ wx/viewers/rfx7.swf | Bin 0 -> 4857 bytes wx/viewers/rfx8.swf | Bin 0 -> 4857 bytes wx/viewers/simple.py | 174 ++++++ 26 files changed, 3551 insertions(+), 1095 deletions(-) create mode 100644 wx/app.py create mode 100644 wx/document.py create mode 100644 wx/gpdf2swf.ico create mode 100644 wx/gpdf2swf.py create mode 100644 wx/gui/__init__.py create mode 100644 wx/gui/boldstatictext.py create mode 100644 wx/gui/choicetext.py create mode 100644 wx/gui/dialogs.py create mode 100644 wx/gui/fields.py create mode 100644 wx/gui/main.py create mode 100644 wx/gui/options/__init__.py create mode 100644 wx/gui/options/quality.py create mode 100644 wx/gui/options/viewer.py create mode 100644 wx/gui/plugin.py rename wx/{images.py => pdf2swf.gui.old.py} (91%) mode change 100644 => 100755 delete mode 100755 wx/pdf2swf.py create mode 100644 wx/viewers/__init__.py create mode 100644 wx/viewers/raw.py create mode 100644 wx/viewers/rfx.py create mode 100644 wx/viewers/rfx7.swf create mode 100644 wx/viewers/rfx8.swf create mode 100644 wx/viewers/simple.py diff --git a/lib/MD5.c b/lib/MD5.c index 9e60f50..f8dc3fe 100644 --- a/lib/MD5.c +++ b/lib/MD5.c @@ -176,7 +176,7 @@ void hash_md5(const unsigned char*buf, int len, unsigned char*dest) MD5Final(dest, &ctx); } -void* init_md5() +void* inititialize_md5() { MD5_CTX* ctx = malloc(sizeof(MD5_CTX)); memset(ctx, 0, sizeof(MD5_CTX)); diff --git a/lib/MD5.h b/lib/MD5.h index ad54fe1..e560700 100644 --- a/lib/MD5.h +++ b/lib/MD5.h @@ -26,7 +26,7 @@ char * crypt_md5(const char *pw, const char *salt); void hash_md5(const unsigned char*buf, int len, unsigned char*dest); //dest needs to be 16 bytes wide -void* init_md5(); +void* initialize_md5(); void update_md5(void*ctx, unsigned char*data, int len); void finish_md5(void*ctx, unsigned char*dest); #endif diff --git a/lib/as3/scripts.c b/lib/as3/scripts.c index a7f79bb..8bcd9de 100644 --- a/lib/as3/scripts.c +++ b/lib/as3/scripts.c @@ -31,7 +31,7 @@ void swf_AddButtonLinks(SWF*swf, char stop_each_frame, char events) int has_buttons = 0; TAG*tag=swf->firstTag; - void*md5 = init_md5(); + void*md5 = initialize_md5(); while(tag) { if(tag->id == ST_SHOWFRAME) diff --git a/lib/gfxpoly/poly.c b/lib/gfxpoly/poly.c index 2be5efb..95a8a22 100644 --- a/lib/gfxpoly/poly.c +++ b/lib/gfxpoly/poly.c @@ -19,7 +19,7 @@ void gfxpoly_fail(char*expr, char*file, int line, const char*function) exit(1); } - void*md5 = init_md5(); + void*md5 = initialize_md5(); int s,t; gfxpolystroke_t*stroke = current_polygon->strokes; diff --git a/wx/app.py b/wx/app.py new file mode 100644 index 0000000..204ddaa --- /dev/null +++ b/wx/app.py @@ -0,0 +1,413 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# +# gpdf2swf.py +# graphical user interface for pdf2swf +# +# Part of the swftools package. +# +# Copyright (c) 2008,2009 Matthias Kramm +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +from __future__ import division +import os +import wx +import time +import pickle + +from wx.lib.wordwrap import wordwrap +from wx.lib.pubsub import Publisher + +from document import Document +from gui import (PdfFrame, ProgressDialog, OptionsDialog, AboutDialog, + ID_INVERT_SELECTION, ID_SELECT_ODD, ID_SELECT_EVEN) + + +def GetDataDir(): + """ + Return the standard location on this platform for application data + """ + sp = wx.StandardPaths.Get() + return sp.GetUserDataDir() + +def GetConfig(): + if not os.path.exists(GetDataDir()): + os.makedirs(GetDataDir()) + + config = wx.FileConfig( + localFilename=os.path.join(GetDataDir(), "options")) + return config + + +class Pdf2Swf: + def __init__(self): + self.__doc = Document() + + self.__threads = {} + + self.__busy = None + self.__progress = None + + self.__can_save = False + + self.view = PdfFrame() + wx.GetApp().SetTopWindow(self.view) + # Call Show after the current and pending event + # handlers have been completed. Otherwise on MSW + # we see the frame been draw and after that we saw + # the menubar appear + wx.CallAfter(self.view.Show) + + self.options = OptionsDialog(self.view) + self.__ReadConfigurationFile() + + Publisher.subscribe(self.OnPageChanged, "PAGE_CHANGED") + Publisher.subscribe(self.OnFileLoaded, "FILE_LOADED") + Publisher.subscribe(self.OnDiffSizes, "DIFF_SIZES") + Publisher.subscribe(self.OnThumbnailAdded, "THUMBNAIL_ADDED") + Publisher.subscribe(self.OnThumbnailDone, "THUMBNAIL_DONE") + Publisher.subscribe(self.OnProgressBegin, "SWF_BEGIN_SAVE") + Publisher.subscribe(self.OnProgressUpdate, "SWF_PAGE_SAVED") + Publisher.subscribe(self.OnProgressDone, "SWF_FILE_SAVED") + Publisher.subscribe(self.OnCombineError, "SWF_COMBINE_ERROR") + Publisher.subscribe(self.OnFileDroped, "FILE_DROPED") + Publisher.subscribe(self.OnFilesDroped, "FILES_DROPED") + + self.view.Bind(wx.EVT_MENU, self.OnMenuOpen, id=wx.ID_OPEN) + self.view.Bind(wx.EVT_MENU, self.OnMenuSave, id=wx.ID_SAVE) + self.view.Bind(wx.EVT_MENU, self.OnMenuSaveSelected, id=wx.ID_SAVEAS) + self.view.Bind(wx.EVT_MENU, self.OnMenuExit, id=wx.ID_EXIT) + self.view.Bind(wx.EVT_MENU_RANGE, self.OnFileHistory, + id=wx.ID_FILE1, id2=wx.ID_FILE9) + + self.view.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=wx.ID_SAVE) + self.view.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=wx.ID_SAVEAS) + + self.view.Bind(wx.EVT_MENU, self.OnMenuSelectAll, id=wx.ID_SELECTALL) + self.view.Bind(wx.EVT_MENU, + self.OnMenuInvertSelection, id=ID_INVERT_SELECTION) + self.view.Bind(wx.EVT_MENU, self.OnMenuSelectOdd, id=ID_SELECT_ODD) + self.view.Bind(wx.EVT_MENU, self.OnMenuSelectEven, id=ID_SELECT_EVEN) + self.view.Bind(wx.EVT_MENU, self.OnMenuOptions, id=wx.ID_PREFERENCES) + + self.view.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=wx.ID_SELECTALL) + self.view.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=ID_INVERT_SELECTION) + self.view.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=ID_SELECT_ODD) + self.view.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=ID_SELECT_EVEN) + + self.view.Bind(wx.EVT_MENU, self.OnAbout, id=wx.ID_ABOUT) + + self.view.Bind(wx.EVT_MENU, self.OnZoom, id=wx.ID_ZOOM_IN) + self.view.Bind(wx.EVT_MENU, self.OnZoom, id=wx.ID_ZOOM_OUT) + self.view.Bind(wx.EVT_MENU, self.OnZoom, id=wx.ID_ZOOM_100) + self.view.Bind(wx.EVT_MENU, self.OnFit, id=wx.ID_ZOOM_FIT) + + self.view.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=wx.ID_ZOOM_IN) + self.view.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=wx.ID_ZOOM_OUT) + self.view.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=wx.ID_ZOOM_100) + self.view.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=wx.ID_ZOOM_FIT) + + self.view.page_list.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnSelectItem) + self.view.Bind(wx.EVT_CLOSE, self.OnMenuExit) + + # statusbar cancel thumbanails generation button + self.view.statusbar.btn_cancel.Bind(wx.EVT_BUTTON, + self.OnThumbnailCancel) + + def OnFilesDroped(self, evt): + dlg = wx.MessageDialog(self.view, + u"You must drop only one file.", + u"Notice", + style=wx.OK, pos=wx.DefaultPosition) + dlg.ShowModal() + dlg.Destroy() + + def OnFileDroped(self, message): + self.__Load(message.data["filename"]) + + def OnFileHistory(self, evt): + # get the file based on the menu ID + fileNum = evt.GetId() - wx.ID_FILE1 + filename = self.view.filehistory.GetHistoryFile(fileNum) + + self.__Load(filename) + + def OnProgressBegin(self, message): + if self.__progress: + self.__progress.Destroy() + pages = message.data["pages"] + style = ( + wx.PD_APP_MODAL|wx.PD_ELAPSED_TIME| + wx.PD_REMAINING_TIME|wx.PD_CAN_ABORT| + wx.PD_AUTO_HIDE + ) + self.__progress = ProgressDialog(u"Saving...", + u"Start saving SWF pages", + maximum=pages-1, + parent=self.view, style=style) + self.__progress.Show() + self.view.SetStatusText(u"Saving document...") + + def OnProgressUpdate(self, message): + pagenr = message.data["pagenr"] + pagenr0 = pagenr - 1 # 0 based + pages = message.data["pages"] + + keep_running, skip = self.__progress.Update( + pagenr0, + u"Saving SWF page %d of %d" % (pagenr, pages) + ) + if not keep_running and self.__threads.has_key("progress"): + self.view.SetStatusText(u"Cancelling...") + self.__threads.pop("progress").Stop() + + # Send size events to resize the progress dialog, + # this will allow the progress message label to resize accordingly. + # Here we minimize that events every 10 times. + if pagenr0 % 10 == 0: + self.__progress.SendSizeEvent() + + def OnProgressDone(self, message): + self.__progress.Hide() + if self.__threads.has_key("progress"): # it goes all the way? + self.__threads.pop("progress") + self.view.SetStatusText(u"SWF document saved successfully.") + else: + self.view.SetStatusText(u"") + + def OnCombineError(self, message): + from wx.lib.dialogs import ScrolledMessageDialog + ScrolledMessageDialog(self.view, message.data, u"Notice").ShowModal() + + + def OnThumbnailAdded(self, message): + self.view.statusbar.SetGaugeValue(message.data['pagenr']) + tot = self.view.page_list.GetItemCount() + self.view.SetStatusText(u"Generating thumbnails %s/%d" % + (message.data['pagenr'], tot), 0) + + def OnThumbnailDone(self, message): + self.view.statusbar.SetGaugeValue(0) + self.view.SetStatusText(u"", 0) + if self.__threads.has_key("thumbnails"): + self.__threads.pop("thumbnails") + + def OnThumbnailCancel(self, event): + if self.__threads.has_key("thumbnails"): + self.__threads["thumbnails"].Stop() + + def OnSelectItem(self, event): + self.__doc.ChangePage(event.GetIndex() + 1) + + def OnPageChanged(self, message): + # ignore if we have more than one item selected + if self.view.page_list.GetSelectedItemCount() > 1: + return + + self.view.page_preview.DisplayPage(message.data) + + def OnFileLoaded(self, message): + if self.__progress: + self.__progress.Destroy() + self.__progress = None + + self.view.SetStatusText(u"Document loaded successfully.") + self.view.page_list.DisplayEmptyThumbnails(message.data["pages"]) + thumbs = self.__doc.GetThumbnails() + t = self.view.page_list.DisplayThumbnails(thumbs) + self.__threads["thumbnails"] = t + self.view.statusbar.SetGaugeRange(message.data["pages"]) + del self.__busy + + def OnDiffSizes(self, message): + # just let the user know- for now, we can't handle this properly + self.Message( + u"In this PDF, width or height are not the same for " + u"each page. This might cause problems if you export " + u"pages of different dimensions into the same SWF file.", + u"Notice") + + def OnMenuOpen(self, event): + dlg = wx.FileDialog(self.view, u"Choose PDF File:", + style = wx.FD_CHANGE_DIR|wx.FD_OPEN, + wildcard = u"PDF files (*.pdf)|*.pdf|all files (*.*)|*.*") + + if dlg.ShowModal() == wx.ID_OK: + filename = dlg.GetPath() + self.__Load(filename) + + def OnMenuSave(self, event, pages=None): + defaultFile = self.__doc.lastsavefile + allFiles = "*.*" if "wxMSW" in wx.PlatformInfo else "*" + self.view.SetStatusText(u"") + dlg = wx.FileDialog(self.view, u"Choose Save Filename:", + style = wx.SAVE | wx.OVERWRITE_PROMPT, + defaultFile=defaultFile, + wildcard=u"SWF files (*.swf)|*.swf" + "|all files (%s)|%s" % (allFiles, allFiles)) + + if dlg.ShowModal() == wx.ID_OK: + self.__threads["progress"] = self.__doc.SaveSWF(dlg.GetPath(), + pages, self.options) + + def OnUpdateUI(self, event): + menubar = self.view.GetMenuBar() + menubar.Enable(event.GetId(), self.__can_save) + + self.view.GetToolBar().EnableTool(event.GetId(), self.__can_save) + + def OnMenuSaveSelected(self, event): + pages = [] + page = self.view.page_list.GetFirstSelected() + pages.append(page+1) + + while True: + page = self.view.page_list.GetNextSelected(page) + if page == -1: + break + pages.append(page+1) + + self.OnMenuSave(event, pages) + + def OnMenuExit(self, event): + self.view.SetStatusText(u"Cleaning up...") + + # Stop any running thread + self.__StopThreads() + + config = GetConfig() + self.view.filehistory.Save(config) + config.Flush() + # A little extra cleanup is required for the FileHistory control + del self.view.filehistory + + # Save quality options + dirpath = GetDataDir() + data = self.options.quality_panel.pickle() + try: + f = file(os.path.join(dirpath, 'quality.pkl'), 'wb') + pickle.dump(data, f) + f.close() + except IOError: + pass + + # Save viewer options + try: + f = file(os.path.join(dirpath, 'viewers.pkl'), 'wb') + data = self.options.viewers_panel.pickle() + pickle.dump(data, f) + f.close() + except Exception, e: + pass + + self.view.Destroy() + + def OnMenuSelectAll(self, event): + for i in range(0, self.view.page_list.GetItemCount()): + self.view.page_list.Select(i, True) + + def OnMenuInvertSelection(self, event): + for i in range(0, self.view.page_list.GetItemCount()): + self.view.page_list.Select(i, not self.view.page_list.IsSelected(i)) + + def OnMenuSelectOdd(self, event): + for i in range(0, self.view.page_list.GetItemCount()): + self.view.page_list.Select(i, not bool(i%2)) + + def OnMenuSelectEven(self, event): + for i in range(0, self.view.page_list.GetItemCount()): + self.view.page_list.Select(i, bool(i%2)) + + def OnMenuOptions(self, event): + self.options.ShowModal() + + def OnFit(self, event): + self.__doc.Fit(self.view.page_preview.GetClientSize()) + + def OnZoom(self, event): + zoom = { + wx.ID_ZOOM_IN: .1, + wx.ID_ZOOM_OUT: -.1, + wx.ID_ZOOM_100: 1, + } + self.__doc.Zoom(zoom[event.GetId()]) + + def OnAbout(self, evt): + AboutDialog(self.view) + + def __Load(self, filename): + self.__can_save = True + self.__StopThreads() + self.view.SetStatusText(u"Loading document...") + self.__busy = wx.BusyInfo(u"One moment please, " + u"opening pdf document...") + + self.view.filehistory.AddFileToHistory(filename) + + # Need to delay the file load a little bit + # for the BusyInfo get a change to repaint itself + wx.FutureCall(150, self.__doc.Load, filename) + + def __StopThreads(self): + for n, t in self.__threads.items(): + t.Stop() + + running = True + while running: + running = False + for n, t in self.__threads.items(): + running = running + t.IsRunning() + time.sleep(0.1) + + def __ReadConfigurationFile(self): + config = GetConfig() + self.view.filehistory.Load(config) + + dirpath = GetDataDir() + try: + f = file(os.path.join(dirpath, 'quality.pkl'), 'rb') + try: + data = pickle.load(f) + self.options.quality_panel.unpickle(data) + except: + self.Message( + u"Error loading quality settings. " + u"They will be reset to defaults. ") + f.close() + except IOError: + pass + + try: + f = file(os.path.join(dirpath, 'viewers.pkl'), 'rb') + try: + data = pickle.load(f) + self.options.viewers_panel.unpickle(data) + except: + self.Message( + u"Error loading viewers settings. " + u"They will be reset to defaults. ") + f.close() + except IOError: + pass + #d = pickle.load(f) + + def Message(self, message): + dlg = wx.MessageDialog(self.view, + message, + style=wx.OK, pos=wx.DefaultPosition) + dlg.ShowModal() + dlg.Destroy() + diff --git a/wx/document.py b/wx/document.py new file mode 100644 index 0000000..70cbb82 --- /dev/null +++ b/wx/document.py @@ -0,0 +1,163 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# +# gpdf2swf.py +# graphical user interface for pdf2swf +# +# Part of the swftools package. +# +# Copyright (c) 2008,2009 Matthias Kramm +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +from __future__ import division +import os +import time +import thread +import gfx +import wx +from wx.lib.pubsub import Publisher +from subprocess import Popen, PIPE + +class _SaveSWFThread: + def __init__(self, filename, doc, pages, options): + self.__doc = doc + self.__filename = filename + self.__pages = pages or range(1, doc.pages+1) + self.__options = options + + def Start(self): + self.__keep_running = self.__running = True + thread.start_new_thread(self.Run, ()) + #self.Run() + + def Stop(self): + self.__keep_running = False + + def IsRunning(self): + return self.__running + + def Run(self): + pages = len(self.__pages) + wx.CallAfter(Publisher.sendMessage, "SWF_BEGIN_SAVE", + {'pages': pages,}) + + time.sleep(0.05) + + swf = gfx.SWF() + self.set_swf_parameters(swf) + + plugin = self.__options.viewers.init(swf, self.__filename) + + plugin.before_render() + for i, pagenr in enumerate(self.__pages): + page = self.__doc.getPage(pagenr) + swf.startpage(page.width, page.height) + page.render(swf) + swf.endpage() + wx.CallAfter(Publisher.sendMessage, "SWF_PAGE_SAVED", + {'pagenr': i+1, + 'pages': pages,}) + time.sleep(0.05) + if not self.__keep_running: + break + else: + # This will not run if we break the for loop + plugin.before_save(page) + swf.save(self.__filename) + plugin.after_save(page) + + # No need. But to be sure that it's clean up + # as soon as possible + del swf + + wx.CallAfter(Publisher.sendMessage, "SWF_FILE_SAVED") + time.sleep(0.05) + + self.__running = False + + def set_swf_parameters(self, swf): + for opt in self.__options.quality: + if type(opt.name) in (tuple, list): + for name, value in ( + # Example to better understand the list comprehension: + # opt.name = ['a', 'b', 'c'] + # opt.value = [1, 2, 3] + # zip them = [('a',1), ('b', 2), ('c', 3)] + # pair will be in this example ('a', 1) due to + # the if pair[1] condition + pair for pair in zip(opt.name, opt.value) if pair[1] == 1 + ): + #print "1.swf.setparameter(%s, %s)" % (name, value) + swf.setparameter(str(name), str(value)) + else: + #print "2.swf.setparameter(%s, %s)" % (opt.name, str(opt.value)) + swf.setparameter(opt.name, str(opt.value)) + + +class Document: + def __init__(self): + self.__page = None + self.__zoom = 1 + self.__lastsavefile = "output.swf" + + def __get_lastsavefile(self): + return self.__lastsavefile + def __set_lastsavefile(self, lastsavefile): + self.__lastsavefile = lastsavefile + lastsavefile = property(__get_lastsavefile, __set_lastsavefile) + + def __SwapExtension(self, filename, newext): + basename, ext = os.path.splitext(filename) + return "%s.%s" % (basename, newext) + + def __Reload(self): + Publisher.sendMessage("PAGE_CHANGED", + {'page': self.__page, + 'width': int(self.__page.width * self.__zoom), + 'height': int(self.__page.height * self.__zoom)}) + + def Load(self, filename): + self.__lastsavefile = self.__SwapExtension(filename, "swf") + #self.__htmlfilename = self.__SwapExtension(filename, "html") + self.__pdf = gfx.open("pdf", filename) + Publisher.sendMessage("FILE_LOADED", {'pages': self.__pdf.pages}) + + def ChangePage(self, pagenr=1, size=None): + self.__page = page = self.__pdf.getPage(pagenr) + self.__Reload() + + def Fit(self, size): + w = size[0] / self.__page.width + h = size[1] / self.__page.height + self.__zoom = min(w, h) + self.__Reload() + + def Zoom(self, zoom): + self.__zoom = 1 if zoom == 1 else self.__zoom + zoom + self.__Reload() + + def GetThumbnails(self): + for pagenr in range(1, self.__pdf.pages + 1): + page = self.__pdf.getPage(pagenr) + yield page + + def SaveSWF(self, filename, pages, options): + self.__lastsavefile = filename + t = _SaveSWFThread(filename, self.__pdf, pages, options) + t.Start() + return t + + diff --git a/wx/gpdf2swf.ico b/wx/gpdf2swf.ico new file mode 100644 index 0000000000000000000000000000000000000000..ad46ef06d3bf117a7140350aa798f06cf2db72a8 GIT binary patch literal 22382 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 +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +from __future__ import division +import os +import sys +import imp + +def main_is_frozen(): + return (hasattr(sys, "frozen") or # new py2exe + hasattr(sys, "importers") # old py2exe + or imp.is_frozen("__main__")) # tools/freeze + +if main_is_frozen(): + sys.path.insert(0, os.path.join("..", "python25")) +else: + sys.path.insert(0, os.path.join("..", "lib", "python")) + +import wx +from app import Pdf2Swf + +if __name__ == "__main__": + app = wx.App(False) + app.SetAppName(u"gpdf2swf") + Pdf2Swf() + app.MainLoop() + diff --git a/wx/gui/__init__.py b/wx/gui/__init__.py new file mode 100644 index 0000000..a12f187 --- /dev/null +++ b/wx/gui/__init__.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# +# gpdf2swf.py +# graphical user interface for pdf2swf +# +# Part of the swftools package. +# +# Copyright (c) 2008,2009 Matthias Kramm +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +from main import * +from dialogs import * diff --git a/wx/gui/boldstatictext.py b/wx/gui/boldstatictext.py new file mode 100644 index 0000000..247e29c --- /dev/null +++ b/wx/gui/boldstatictext.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# +# gpdf2swf.py +# graphical user interface for pdf2swf +# +# Part of the swftools package. +# +# Copyright (c) 2008,2009 Matthias Kramm +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +import wx + +class BoldStaticText(wx.StaticText): + def __init__(self, *args, **kwargs): + wx.StaticText.__init__(self, *args, **kwargs) + font = self.GetFont() + font.SetWeight(wx.BOLD) + self.SetFont(font) + diff --git a/wx/gui/choicetext.py b/wx/gui/choicetext.py new file mode 100644 index 0000000..4e89864 --- /dev/null +++ b/wx/gui/choicetext.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# +# gpdf2swf.py +# graphical user interface for pdf2swf +# +# Part of the swftools package. +# +# Copyright (c) 2008,2009 Matthias Kramm +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +import wx +import wx.lib.intctrl + +class ChoiceInt(wx.Panel): + def __init__(self, parent, choices=[], editselection=None): + wx.Panel.__init__(self, parent) + choices = choices + self.editselection = editselection + + s = wx.BoxSizer(wx.HORIZONTAL) + + self.choice = choice = wx.Choice(self, choices=choices) + self.text = text = wx.lib.intctrl.IntCtrl(self) + s.Add(choice, 1, wx.EXPAND) + s.Add(text, 1, wx.EXPAND) + + self.SetSizer(s) + + choice.Bind(wx.EVT_CHOICE, self.__OnChoice) + + def IsEditableSelection(self, n): + return n == self.editselection + + def GetValue(self): + return self.text.GetValue() + + def SetValue(self, value): + self.text.SetValue(value) + + def GetSelectionAndValue(self): + return self.choice.GetSelection(), self.text.GetValue() + + def SetSelectionAndValue(self, n, value): + self.SetSelection(n) + self.text.SetValue(value) + + def GetSelection(self): + return self.choice.GetSelection() + + def SetSelection(self, n): + self.choice.SetSelection(n) + self.EnableText(self.IsEditableSelection(n)) + + def EnableText(self, enable): + self.text.Enable(enable) + + def __OnChoice(self, event): + self.EnableText(self.IsEditableSelection(event.Selection)) + diff --git a/wx/gui/dialogs.py b/wx/gui/dialogs.py new file mode 100644 index 0000000..0d76613 --- /dev/null +++ b/wx/gui/dialogs.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# +# gpdf2swf.py +# graphical user interface for pdf2swf +# +# Part of the swftools package. +# +# Copyright (c) 2008,2009 Matthias Kramm +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +from __future__ import division +import os + +import wx +from wx.lib.wordwrap import wordwrap + +from gui.options import Quality, ViewerBook + + +class ProgressDialog(wx.ProgressDialog): + def __init__(self, title, message, maximum=100, parent=None, + style=wx.PD_AUTO_HIDE|wx.PD_APP_MODAL): + wx.ProgressDialog.__init__(self, title, message, maximum=maximum, + parent=parent, style=style) + +class OptionsDialog(wx.Dialog): + def __init__(self, parent): + wx.Dialog.__init__(self, parent) + + app_name = wx.GetApp().GetAppName() + self.SetTitle(u"%s options" % app_name) + + p = wx.Notebook(self) + self.__quality = Quality(p) + self.__viewers = ViewerBook(p) + p.AddPage(self.__quality, u"Quality") + p.AddPage(self.__viewers, u"Viewer") + + sizer = wx.BoxSizer(wx.VERTICAL) + btnsizer = wx.BoxSizer(wx.HORIZONTAL) + + btn = wx.Button(self, wx.ID_CLOSE) + self.SetAffirmativeId(wx.ID_CLOSE) + btnsizer.Add(btn) + + sizer.Add(p, 0, wx.EXPAND|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5) + sizer.Add(btnsizer, 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5) + + self.SetSizer(sizer) + sizer.Fit(self) + + def __get_quality(self): + return self.__quality + quality_panel = property(__get_quality) + + def __get_viewers(self): + return self.__viewers + viewers_panel = property(__get_viewers) + + def __get_quality_options(self): + return self.__quality.options + quality = property(__get_quality_options) + + def __get_viewers_options(self): + return self.__viewers.options + viewers = property(__get_viewers_options) + + +class AboutDialog: + def __init__(self, parent): + info = wx.AboutDialogInfo() + # no need to get app name + #info.Name = wx.GetApp().GetAppName() + info.Version = u"0.9.0" + info.Copyright = (u"Copyright (c) 2008,2009 " + u"Matthias Kramm ") + info.Description = u"graphical user interface for pdf2swf" + info.Developers = [ + u"Matthias Kramm ", + u"Ricardo Pedroso ", + ] + + if 'wxGTK' in wx.PlatformInfo: + info.WebSite = (u"http://www.swftools.org/", u"swftools home page") + licenseText = [ + u"%(name)s is free software; you can redistribute " + u"it and/or modify it under the terms of the GNU General " + u"Public License as published by the Free Software " + u"Foundation; either version 2 of the License, or (at " + u"your option) any later version." + ] + licenseText.append( + u"%(name)s is distributed in the hope that it will " + u"be useful, but WITHOUT ANY WARRANTY; without even the " + u"implied warranty of MERCHANTABILITY or FITNESS FOR A " + u"PARTICULAR PURPOSE. See the GNU General Public License " + u"for more details." + ) + licenseText.append( + u"You should have received a copy of the GNU General " + u"Public License along with %(name)s; if not, " + u"write to the Free Software Foundation, Inc., 51 " + u"Franklin St, Fifth Floor, Boston, MA 02110-1301 USA" + ) + lic = (os.linesep*2).join(licenseText) % {'name': info.Name} + info.License = wordwrap(lic, 350, wx.ClientDC(parent)) + + wx.AboutBox(info) + diff --git a/wx/gui/fields.py b/wx/gui/fields.py new file mode 100644 index 0000000..457a4b3 --- /dev/null +++ b/wx/gui/fields.py @@ -0,0 +1,195 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# +# gpdf2swf.py +# graphical user interface for pdf2swf +# +# Part of the swftools package. +# +# Copyright (c) 2008,2009 Matthias Kramm +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +import wx +from choicetext import ChoiceInt + +class Option(object): + def __init__(self, name, label, data, selection): + self.name = name + self.label = label + self.data = data + self.selection = selection + + def _Update(self): + self.value = self.ctrl.GetValue() + + def _SetControlValue(self, value): + self.value = value + self.ctrl.SetValue(value) + + def _OnUpdate(self, event): + self._Update() + event.Skip() + + def SetValue(self, value): + self._SetControlValue(value) + +class Hidden: + def __init__(self, name, value): + self.name = name + self.value = value + + def draw(self, parent): + return None, None + + def SetValue(self, value): + self.value = value + +class Choose(Option): + klass = wx.Choice + def __init__(self, name, label, data, selection): + Option.__init__(self, name, label, data, selection) + self.choices = data[0::2] + self.data = data[1::2] + + def draw(self, parent): + label = wx.StaticText(parent, label=self.label) + self.ctrl = ctrl = self.klass(parent, choices=self.choices) + ctrl.Bind(wx.EVT_CHOICE, self._OnUpdate) + self._SetControlValue(self.selection) + return label, ctrl + + def _Update(self): + n = self.ctrl.GetSelection() + self.value = self.data[n] + + def _SetControlValue(self, n): + self.ctrl.SetSelection(n) + self.value = self.data[n] + + def SetValue(self, value): + # in python < 2.6 tuples doesnt have the index method + # be sure that we are using a list + tmp = list(self.data) + try: + n = tmp.index(value) + except ValueError: + n = self.selection + self._SetControlValue(n) + +class ChooseAndInt(Choose): + klass = ChoiceInt + def __init__(self, name, label, data, selection, editselection, editvalue): + Choose.__init__(self, name, label, data, selection) + self.editselection = editselection + self.editvalue = editvalue + + def draw(self, parent): + label = wx.StaticText(parent, label=self.label) + self.ctrl = ctrl = self.klass(parent, choices=self.choices, + editselection=self.editselection) + ctrl.choice.Bind(wx.EVT_CHOICE, self._OnUpdate) + ctrl.text.Bind(wx.EVT_TEXT, self._OnUpdate) + self._SetControlValue(self.selection) + return label, ctrl + + def _Update(self): + n = self.ctrl.GetSelection() + if self.ctrl.IsEditableSelection(n): + self.value = self.ctrl.GetValue() + else: + self.value = self.data[n] + + def _SetControlValue(self, n): + self.ctrl.SetSelectionAndValue(n, self.editvalue) + self.value = self.data[n] + + def SetValue(self, value): + # in python < 2.6 tuples doesnt have the index method + # be sure that we are using a list + tmp = list(self.data) + try: + n = tmp.index(value) + except ValueError: + n = self.editselection + self.editvalue = value + self._SetControlValue(n) + +class Radio(Option): + klass = wx.RadioBox + def __init__(self, name, label, data, selection): + Option.__init__(self, name, label, data, selection) + self.choices = data[0::2] + self.data = data[1::2] + self.selection = selection + + def draw(self, parent): + self.ctrl = ctrl = self.klass(parent, label=self.label, + choices=self.choices, + majorDimension=1, + style=wx.RA_SPECIFY_COLS) + ctrl.Bind(wx.EVT_RADIOBOX, self._OnUpdate) + self._SetControlValue(self.selection) + return ctrl + + def _Update(self): + n = self.ctrl.GetSelection() + self.value = self.data[n] + + def _SetControlValue(self, n): + self.ctrl.SetSelection(n) + self.value = self.data[n] + + def SetValue(self, value): + # in python < 2.6 tuples doesnt have the index method + # be sure that we are using a list + tmp = list(self.data) + try: + n = tmp.index(value) + except ValueError: + n = self.selection + self._SetControlValue(n) + +class Spinner(Option): + klass = wx.SpinCtrl + def __init__(self, name, label, data, selection): + Option.__init__(self, name, label, data, selection) + self.min = data[0] + self.max = data[1] + + def draw(self, parent): + label = wx.StaticText(parent, label=self.label) + self.ctrl = ctrl = self.klass(parent, min=self.min, max=self.max, + initial=self.selection) + ctrl.Bind(wx.EVT_SPINCTRL, self._OnUpdate) + self._SetControlValue(self.selection) + return label, ctrl + +class Slider(Option): + klass = wx.Slider + def __init__(self, name, label, data, selection): + Option.__init__(self, name, label, data, selection) + self.min = data[0] + self.max = data[1] + + def draw(self, parent): + label = wx.StaticText(parent, label=self.label) + self.ctrl = ctrl = self.klass(parent, minValue=self.min, + maxValue=self.max, + value=self.selection, + style=wx.SL_LABELS) + ctrl.Bind(wx.EVT_SCROLL, self._OnUpdate) + self._SetControlValue(self.selection) + return label, ctrl diff --git a/wx/gui/main.py b/wx/gui/main.py new file mode 100644 index 0000000..1aa686c --- /dev/null +++ b/wx/gui/main.py @@ -0,0 +1,323 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# +# gpdf2swf.py +# graphical user interface for pdf2swf +# +# Part of the swftools package. +# +# Copyright (c) 2008,2009 Matthias Kramm +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +from __future__ import division +import os +import wx +from wx.lib.pubsub import Publisher +from wx.lib.embeddedimage import PyEmbeddedImage +import thread +import time + +ICON_SIZE = 64 + +ID_INVERT_SELECTION = wx.NewId() +ID_SELECT_ODD = wx.NewId() +ID_SELECT_EVEN = wx.NewId() + +# TODO: move into images.py +blank = PyEmbeddedImage( + "iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAAAAZiS0dE" + "AP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9kHDAscKjCK/4UAAABo" + "SURBVHja7dABAcBAEAIgXf/Ofo8dRKDblqPa5stxAgQIECBAgAABAgQIECBAgAABAgQIECBA" + "gAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEPALTbLLAQ8OIAV9" + "8WNeKwAAAABJRU5ErkJggg==") +getblankData = blank.GetData +getblankImage = blank.GetImage +getblankBitmap = blank.GetBitmap + +stop_width=8 +stop_height=8 +stop_data="""\xd5\x07\x07\xd5\x08\x08\xd5\x09\x09\xd4\x0a\x0a\xd4\x0a\x0a\xd5\x09\x09\xd5\x08\x08\xd5\x07\x07\xd5\x08\x08\xd4\x12\x12\xd4<<\xd1--\xd1,-\xd4;;\xd5\x12\x12\xd6\x08\x08\xd5\x0a\x0a\xd2@@\xd4\xc6\xc7\xd5kk\xd2gi\xd2\xc4\xc6\xd4<<\xd6\x0a\x0a\xd4\x0c\x0c\xcb66\xd6gi\xe3\xeb\xed\xe1\xeb\xed\xd4bc\xd3++\xd5\x0c\x0c\xd4\x0b\x0b\xd0--\xd3hi\xe2\xeb\xed\xe2\xed\xee\xd5cd\xd3++\xd5\x0c\x0c\xd5\x09\x09\xd4:;\xd3\xc5\xc7\xd3ij\xd3jj\xd3\xc5\xc7\xd4<<\xd6\x0a\x0a\xd5\x08\x08\xd4\x12\x12\xd5<=\xd2..\xd1,,\xd4;;\xd5\x12\x12\xd6\x08\x08\xd5\x07\x07\xd6\x08\x08\xd6\x0a\x0a\xd5\x0b\x0b\xd4\x0b\x0b\xd5\x09\x09\xd5\x08\x08\xd5\x07\x07""" + + +class _AppendThumbnailThread: + def __init__(self, win, thumbs): + self.__win = win + self.__thumbs = thumbs + + def Start(self): + self.__keep_running = self.running = True + thread.start_new_thread(self.Run, ()) + + def IsRunning(self): + return self.running + + def Stop(self): + self.__keep_running = False + + def Run(self): + thumbs = self.__thumbs + different_sizes = False + for pos, thumb in enumerate(thumbs): + if pos == 0: + width, height = thumb.width, thumb.height + else: + if abs(width - thumb.width) > 2 or \ + abs(height - thumb.height) > 2: + different_sizes = True + + wx.CallAfter(self.__win.AppendThumbnail, pos, + thumb.asImage(ICON_SIZE, ICON_SIZE)) + wx.CallAfter(Publisher.sendMessage, "THUMBNAIL_ADDED", + {'pagenr':pos+1,}) + time.sleep(.05) + if not self.__keep_running: + break + + else: + if different_sizes: + wx.CallAfter(Publisher.sendMessage, "DIFF_SIZES") + time.sleep(.10) + wx.CallAfter(Publisher.sendMessage, "THUMBNAIL_DONE") + time.sleep(.10) + + self.running = False + +class FileDropTarget(wx.FileDropTarget): + def __init__(self, window): + wx.FileDropTarget.__init__(self) + self.window = window + + def OnDropFiles(self, x, y, filenames): + if len(filenames) == 1: + Publisher.sendMessage("FILE_DROPED", + {'filename': filenames[0]} + ) + else: + Publisher.sendMessage("FILES_DROPED", + {'filenames': filenames} + ) + +class PagePreviewWindow(wx.ScrolledWindow): + def __init__(self, parent): + wx.ScrolledWindow.__init__(self, parent) + self.SetBackgroundColour('grey') + self.SetScrollRate(20, 20) + + self.__buffer = wx.EmptyBitmap(1, 1) + + self.Bind(wx.EVT_PAINT, self.__OnPaint) + + def DisplayPage(self, page): + thread.start_new_thread(self.__DisplayPageThread, (page,)) + + def __OnPaint(self, event): + dc = wx.BufferedPaintDC(self, self.__buffer, wx.BUFFER_VIRTUAL_AREA) + + def __DisplayPage(self, w, h, page): + self.SetVirtualSize((w, h)) + self.__buffer = wx.EmptyBitmap(w+2, h+2) + dc = wx.BufferedDC(None, self.__buffer) + dc.Clear() + dc.DrawRectangle(0, 0, w+2, h+2) + dc.DrawBitmap(wx.BitmapFromBuffer(w, h, page), 1, 1, True) + self.Refresh() + + def __DisplayPageThread(self, page): + w = page['width'] + h = page['height'] + time.sleep(.02) + page = page["page"].asImage(w, h) + wx.CallAfter(self.__DisplayPage, w, h, page) + + +class PageListCtrl(wx.ListView): + def __init__(self, parent): + wx.ListView.__init__(self, parent, style=wx.LC_ICON) + self.Bind(wx.EVT_CONTEXT_MENU, self.OnContextMenu) + + def OnContextMenu(self, event): + menu = wx.Menu() + menu.Append(wx.ID_SELECTALL, u"Select All\tCTRL-A") + menu.AppendSeparator() + menu.Append(wx.ID_SAVE, u"Save SWF (all pages)\tCTRL-W") + menu.Append(wx.ID_SAVEAS, u"Save SWF (selected pages)\tCTRL-S") + self.PopupMenu(menu) + menu.Destroy() + + def DisplayEmptyThumbnails(self, pages): + self.DeleteAllItems() + self.imglist = wx.ImageList(ICON_SIZE, ICON_SIZE, mask=True) + self.AssignImageList(self.imglist, wx.IMAGE_LIST_NORMAL) + bmp = getblankBitmap() + for pos in range(pages): + self.imglist.Add(bmp) + self.InsertImageStringItem(pos, u"Page %s" % (pos+1), pos) + + def DisplayThumbnails(self, thumbs): + t = _AppendThumbnailThread(self, thumbs) + t.Start() + return t + + def AppendThumbnail(self, pos, thumb): + bmp = wx.BitmapFromBuffer(ICON_SIZE, ICON_SIZE, thumb) + self.imglist.Replace(pos, bmp) + if pos == 0: + wx.CallAfter(self.Select, 0) + self.Refresh() + + +class StatusBar(wx.StatusBar): + def __init__(self, parent): + wx.StatusBar.__init__(self, parent, -1) + + self.sizeChanged = False + self.Bind(wx.EVT_SIZE, self.OnSize) + self.Bind(wx.EVT_IDLE, self.OnIdle) + + self.gauge = wx.Gauge(self) + + bmp = wx.BitmapFromImage(wx.ImageFromData(stop_width,stop_height,stop_data)) + self.btn_cancel = wx.BitmapButton(self, bitmap=bmp, + style = wx.NO_BORDER) + self.gauge.Hide() + self.btn_cancel.Hide() + + self.Reposition() + + def SetGaugeValue(self, value): + if value == 0: + self.gauge.Hide() + self.btn_cancel.Hide() + self.gauge.SetValue(value) + + def SetGaugeRange(self, pages): + self.gauge.Show() + self.btn_cancel.Show() + self.gauge.SetRange(pages) + + def OnSize(self, evt): + self.Reposition() + self.sizeChanged = True + + def OnIdle(self, evt): + if self.sizeChanged: + self.Reposition() + + def Reposition(self): + rect = self.GetFieldRect(0) + of = rect.width // 1.5 + self.gauge.SetPosition((rect.x+of , rect.y+2)) + self.gauge.SetSize((rect.width-of-24, rect.height-4)) + self.btn_cancel.SetPosition((rect.width-22, rect.y+1)) + self.btn_cancel.SetSize((22, rect.height-2)) + self.sizeChanged = False + + +class PdfFrame(wx.Frame): + def __init__(self): + wx.Frame.__init__(self, None, size=(750,550), title=u"gpdf2swf") + + icon = self.__MakeIcon(os.path.join("images", "pdf2swf_gui.ico")) + self.SetIcon(icon) + self.__CreateMenu() + self.__CreateToolbar() + self.statusbar = StatusBar(self) + self.SetStatusBar(self.statusbar) + + dt = FileDropTarget(self) + self.SetDropTarget(dt) + + hsplit = wx.SplitterWindow(self, style=wx.SP_3D|wx.SP_LIVE_UPDATE) + self.page_list = PageListCtrl(hsplit) + self.page_preview = PagePreviewWindow(hsplit) + hsplit.SplitVertically(self.page_list, self.page_preview, + sashPosition=ICON_SIZE*2) + hsplit.SetMinimumPaneSize(ICON_SIZE*2) + + def __MakeIcon(self, filename): + # TODO: Probably include the icon on a .py file + img = wx.Bitmap(filename).ConvertToImage() + if "wxMSW" in wx.PlatformInfo: + img = img.Scale(16, 16) + #elif "wxGTK" in wx.PlatformInfo: + # img = img.Scale(22, 22) + # wxMac and wxGTK???? can be any size up to 128x128, + # so leave the source img alone.... + icon = wx.IconFromBitmap(img.ConvertToBitmap()) + return icon + + def __CreateMenu(self): + menubar = wx.MenuBar() + + menu = wx.Menu() + menu.Append(wx.ID_OPEN, u"Open PDF\tCTRL-O", u"Open a PDF document") + menu.AppendSeparator() + menu.Append(wx.ID_SAVE, u"Save SWF (all pages)\tCTRL-W", + u"Save all pages") + menu.Append(wx.ID_SAVEAS, u"Save SWF (selected pages)\tCTRL-S", + u"Save selected pages") + menu.AppendSeparator() + menu.Append(wx.ID_EXIT, u"Exit\tCTRL-Q") + menubar.Append(menu, u"&File") + + self.filehistory = wx.FileHistory() + self.filehistory.UseMenu(menu) + + menu = wx.Menu() + menu.Append(wx.ID_SELECTALL, u"Select All\tCTRL-A", + u"Select all pages") + menu.Append(ID_INVERT_SELECTION, u"Invert Selection", + u"Invert current selection") + menu.Append(ID_SELECT_ODD, u"Select Odd", + u"Select odd pages") + menu.Append(ID_SELECT_EVEN, u"Select Even", + u"Select even pages") + menu.AppendSeparator() + menu.Append(wx.ID_PREFERENCES, u"Options\tCTRL-R", + u"Show options dialog") + menubar.Append(menu, u"&Edit") + + menu = wx.Menu() + menu.Append(wx.ID_ZOOM_IN, u"Zoom In\tCTRL-+") + menu.Append(wx.ID_ZOOM_OUT, u"Zoom Out\tCTRL--") + menu.Append(wx.ID_ZOOM_100, u"Normal Size\tCTRL-0") + menu.Append(wx.ID_ZOOM_FIT, u"Fit\tCTRL-1") + menubar.Append(menu, u"&View") + + menu = wx.Menu() + menu.Append(wx.ID_ABOUT, u"About") + menubar.Append(menu, u"&Help") + self.SetMenuBar(menubar) + + def __CreateToolbar(self): + tsize = (16,16) + wxart = wx.ArtProvider.GetBitmap + self.toolbar = self.CreateToolBar(wx.TB_HORIZONTAL | + wx.NO_BORDER | wx.TB_FLAT) + self.toolbar.AddSimpleTool(wx.ID_OPEN, + wxart(wx.ART_FILE_OPEN, + wx.ART_TOOLBAR, tsize), + u"Open") + self.toolbar.AddSimpleTool(wx.ID_SAVE, + wxart(wx.ART_FILE_SAVE, + wx.ART_TOOLBAR, tsize), + u"Save SWF (all pages)") + self.toolbar.AddSimpleTool(wx.ID_PREFERENCES, + wxart(wx.ART_LIST_VIEW, + wx.ART_TOOLBAR, tsize), + u"Options") + self.toolbar.Realize() + diff --git a/wx/gui/options/__init__.py b/wx/gui/options/__init__.py new file mode 100644 index 0000000..6926daa --- /dev/null +++ b/wx/gui/options/__init__.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# +# gpdf2swf.py +# graphical user interface for pdf2swf +# +# Part of the swftools package. +# +# Copyright (c) 2008,2009 Matthias Kramm +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +from quality import * +from viewer import * diff --git a/wx/gui/options/quality.py b/wx/gui/options/quality.py new file mode 100644 index 0000000..5411592 --- /dev/null +++ b/wx/gui/options/quality.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# +# gpdf2swf.py +# graphical user interface for pdf2swf +# +# Part of the swftools package. +# +# Copyright (c) 2008,2009 Matthias Kramm +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +import wx +from gui import fields + +class Quality(wx.Panel): + def __init__(self, parent): + wx.Panel.__init__(self, parent) + self.__options = [] + + sizer = wx.BoxSizer(wx.VERTICAL) + obj = fields.Radio( + ("bitmap", "poly2bitmap", "bitmapfonts"), + u"Rendering mode", + [u"Convert polygons to polygons and fonts to fonts", (0, 0, 0), + u"Convert fonts to fonts, everything else to bitmaps", (0, 1, 0), + u"Convert everthing to bitmaps", (1, 0, 1), + ], 0) + + ra = obj.draw(self) + self.__options.append(obj) + sizer.Add(ra, 0, wx.EXPAND|wx.ALL, 5) + + quality = [ + ('Spinner', 'zoom', u'Resolution (in dpi):', (0, 100), 72), + ('Slider', 'fontquality', u'Font quality:', (0, 100), 20), + ('Choose', 'storeallcharacters', u'Insert full fonts in SWF file:', + (u'no', 0, u'yes', 1), 0), + ('Slider', 'splinequality', u'Polygon quality:', (0, 100), 100), + ('Slider', 'jpegquality', u'JPEG quality:', (0, 100), 75), + ('Choose', 'jpegsubpixels', u'JPEG image resolution:', + (u'same as in PDF', 0, u'1x', 1, u'2x', 2, u'4x', 4), 0), + ('Choose', 'ppmsubpixels', u'non-JPEG image resolution:', + (u'same as in PDF', 0, u'1x', 1, u'2x', 2, u'4x', 4), 0), + ] + + box = wx.StaticBox(self, label=u"Quality") + bsizer = wx.StaticBoxSizer(box, wx.VERTICAL) + + flex = wx.FlexGridSizer(rows=1, cols=2, hgap=0, vgap=0) + flex.AddGrowableCol(0) + flex.AddGrowableCol(1) + for ctrl, opt, label, range, value in quality: + wxobj = getattr(fields, ctrl) + optobj = wxobj(opt, label, range, value) + lb, sp = optobj.draw(self) + flex.Add(lb, 0, wx.TOP|wx.ALIGN_CENTER_VERTICAL, 5) + flex.Add(sp, 0, wx.TOP|wx.EXPAND, 5) + self.__options.append(optobj) + + bsizer.Add(flex, 0, wx.EXPAND) + sizer.Add(bsizer, 0, wx.EXPAND|wx.ALL, 5) + + self.SetSizer(sizer) + + def __get_options(self): + return self.__options + options = property(__get_options) + + def pickle(self): + data = {} + for opt in self.__options: + data[opt.name] = opt.value + return data + + def unpickle(self, data): + fields = {} + for opt in self.__options: + fields[opt.name] = opt + + for k, v in data.items(): + fields[k].SetValue(v) diff --git a/wx/gui/options/viewer.py b/wx/gui/options/viewer.py new file mode 100644 index 0000000..18c70af --- /dev/null +++ b/wx/gui/options/viewer.py @@ -0,0 +1,186 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# +# gpdf2swf.py +# graphical user interface for pdf2swf +# +# Part of the swftools package. +# +# Copyright (c) 2008,2009 Matthias Kramm +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +import os +import wx +import operator +import imp +from wx.lib.wordwrap import wordwrap +from gui.boldstatictext import BoldStaticText +import viewers +import gui.fields + +class Viewers: + def __init__(self): + self.viewers = [] + self.modules = [] + self.list_viewers() + self.import_viewers() + + def list_viewers(self): + for file in os.listdir('viewers'): + if (file.startswith('.') or file.startswith('_') + or file.endswith(".pyc") or not file.endswith('.py')): + continue + self.viewers.append(os.path.splitext(file)[0]) + + def import_viewers(self): + for file in self.viewers: + _temp = imp.load_source("viewers.%s" % file, os.path.join(os.getcwdu(), "viewers/%s.py" % file)) + self.modules.append(_temp) + + + +class ViewerBook(wx.Listbook): + def __init__(self, parent): + wx.Listbook.__init__(self, parent, wx.ID_ANY, style= + wx.BK_DEFAULT + ) + + self.__mod = [] + self.__viewers = viewers = Viewers() + + # make an image list + il = wx.ImageList(102, 102) + self.AssignImageList(il) + + # Sort viewers by attribute order. + # The attribute order must be an int from 0..n + viewers.modules.sort(key=operator.attrgetter('order')) + + # Make a bunch of panels for the list book + for idx, mod in enumerate(viewers.modules): + bmp = mod.preview.GetBitmap() + il.Add(bmp) + + win = self.makePanel(mod) + self.AddPage(win, mod, imageId=idx) + + # A hack to avoid having the scrollbar be on bottom + # the first time the control is created + self.ListView.Select(self.ListView.GetItemCount()-1) + self.ListView.Select(0) + + def makePanel(self, mod): + p = wx.Panel(self) + sizer = wx.BoxSizer(wx.VERTICAL) + + nameCtrl = BoldStaticText(p, label=mod.name) + sizer.Add(nameCtrl, 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 10) + + t = wordwrap(mod.desc, 400, wx.ClientDC(p)) + descCtrl = wx.StaticText(p, label=t) + sizer.Add(descCtrl, 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 10) + + #swf_options = [] + + # Avoid showing an empty StaticBox + if (len(mod.swf_options) == 1 + and isinstance(mod.swf_options[0], gui.fields.Hidden) + ): + hidden = True + else: + hidden = False + + if mod.swf_options and not hidden: + box = wx.StaticBox(p, label=u"SWF") + bsizer = wx.StaticBoxSizer(box, wx.VERTICAL) + + flex = wx.FlexGridSizer(rows=len(mod.swf_options), cols=2, hgap=0, vgap=0) + flex.AddGrowableCol(1) + + for option in mod.swf_options: + #swf_options.append(option) + label, ctrl = option.draw(p) + if label and ctrl: + flex.Add(label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 4) + flex.Add(ctrl, 0, wx.EXPAND|wx.ALL, 4) + + bsizer.Add(flex, 0, wx.EXPAND) + sizer.Add(bsizer, 0, wx.EXPAND) + + #vie_options = [] + if mod.viewer_options: + box = wx.StaticBox(p, label=u"Viewer") + bsizer = wx.StaticBoxSizer(box, wx.VERTICAL) + + flex = wx.FlexGridSizer(rows=len(mod.viewer_options), + cols=2, hgap=0, vgap=0) + flex.AddGrowableCol(1) + + for option in mod.viewer_options: + #vie_options.append(option) + label, ctrl = option.draw(p) + if label and ctrl: + flex.Add(label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 4) + flex.Add(ctrl, 0, wx.EXPAND|wx.ALL, 4) + + bsizer.Add(flex, 0, wx.EXPAND) + sizer.Add(bsizer, 0, wx.EXPAND) + + p.SetSizer(sizer) + return p + + def AddPage(self, win, mod, select=False, imageId=-1): + wx.Listbook.AddPage(self, win, mod.name, select, imageId) + self.__mod.append(mod) + + def __get_options(self): + page = self.GetSelection() + return self.__mod[page] + + options = property(__get_options) + + def pickle(self): + data = {} + data['selected_viewer'] = self.GetSelection() + + for viewer, module in zip(self.__viewers.viewers, self.__viewers.modules): + data[viewer] = {} + for opt in module.swf_options: + data[viewer][opt.name] = opt.value + for opt in module.viewer_options: + data[viewer][opt.name] = opt.value + + return data + + def unpickle(self, data): + if not data: + return + + selected_viewer = data.pop('selected_viewer') + self.SetSelection(selected_viewer) + + _fields = {} + for viewer, module in zip(self.__viewers.viewers, self.__viewers.modules): + _fields[viewer] = {} + + all_opts = module.swf_options + module.viewer_options + for field in all_opts: + _fields[viewer][field.name] = field + + for modname, opts in data.items(): + for k, v in opts.items(): + _fields[modname][k].SetValue(v) + diff --git a/wx/gui/plugin.py b/wx/gui/plugin.py new file mode 100644 index 0000000..5cdc2a6 --- /dev/null +++ b/wx/gui/plugin.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# +# gpdf2swf.py +# graphical user interface for pdf2swf +# +# Part of the swftools package. +# +# Copyright (c) 2008,2009 Matthias Kramm +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +import os +import time +import wx +from wx.lib.pubsub import Publisher +from subprocess import Popen, PIPE + +class Plugin: + def before_render(self): + pass + + def before_save(self, page): + pass + + def after_save(self, page): + pass + + def _swap_extension(self, filename, newext, flashversion=""): + name, ext = os.path.splitext(filename) + return u"%s%s.%s" % (name, flashversion, newext) + + def __find_swfcombine(self): + found = False + prog = "swfcombine.exe" if "wxMSW" in wx.PlatformInfo else "swfcombine" + basedir = os.path.dirname(__file__) + + opj = os.path.join + locations = [opj(basedir, prog)] + if "wxMSW" in wx.PlatformInfo: + locations.extend([ + opj("c:", "swftools", prog), + opj("c:", "Program Files", "SWFTools", prog) + ]) + else: + locations.extend([ + opj(os.sep, "usr", "local", "bin", prog), + opj(os.sep, "usr", "bin", prog), + ]) + + exe = prog + for e in locations: + if os.path.isfile(e): + exe = e + found = True + break + return exe, found + + def swfcombine(self, *args): + try: + self.__swfcombine(*args) + except Exception, e: + wx.CallAfter(Publisher.sendMessage, + "SWF_COMBINE_ERROR", unicode(e)) + time.sleep(0.05) + + def __swfcombine(self, *args): + exe, found = self.__find_swfcombine() + # uncoment to test a failed swfcombine find + #found = False + + if not found: + raise Exception(u"Could not execute %s: %s not found" % (exe, exe)) + + # Create a command line + cmd = [exe,] + cmd.extend(args) + + output = Popen(cmd, stdout=PIPE).communicate()[0] + + # Check the process output + if output: + raise Exception(u"Error executing %s:%s%s" % + (u" ".join(cmd), os.linesep, output)) + diff --git a/wx/images.py b/wx/pdf2swf.gui.old.py old mode 100644 new mode 100755 similarity index 91% rename from wx/images.py rename to wx/pdf2swf.gui.old.py index 3c8abbe..3657a30 --- a/wx/images.py +++ b/wx/pdf2swf.gui.old.py @@ -1,8 +1,8 @@ #!/usr/bin/env python +# -*- coding: ISO-8859-15 -*- # -# images.py -# -# graphical user interface for pdf2swf: image data +# pdf2swf.py +# graphical user interface for pdf2swf # # Part of the swftools package. # @@ -23,6 +23,1067 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +import sys +import wx +import os +sys.path+=["../lib/python"] +import gfx +import images +import stat + +basedir = os.getcwd() + +gfx.verbose(3) + +#try: +# gfx.setparameter("wxwindowparams", "1") +#except: +# gfx.setoption("wxwindowparams", "1") + +class StaticData: + def __init__(self): + self.simpleviewer_bitmap = wx.BitmapFromImage(wx.ImageFromData(images.simpleviewer_width,images.simpleviewer_height,images.simpleviewer_data)) + self.raw_bitmap = wx.BitmapFromImage(wx.ImageFromData(images.raw_width,images.raw_height,images.raw_data)) + self.motionpaper_bitmap = wx.BitmapFromImage(wx.ImageFromData(images.motionpaper_width,images.motionpaper_height,images.motionpaper_data)) + self.rfxview_bitmap = wx.BitmapFromImage(wx.ImageFromData(images.rfxview_width,images.rfxview_height,images.rfxview_data)) +staticdata = None + +HTMLTEMPLATE = """ + + + + + + + + + + + + +""" + +def error(msg): + dlg = wx.MessageDialog(None, msg, "Error", style=wx.OK, pos=wx.DefaultPosition) + dlg.ShowModal() + dlg.Destroy() + +def savefilestatus(msg): + dlg = wx.MessageDialog(None, msg, "Save file status", style=wx.OK, pos=wx.DefaultPosition) + dlg.ShowModal() + dlg.Destroy() + +def swfcombine(params): + exe = "swfcombine" + if os.path.sep == '/': + locations = [os.path.join(basedir, "swfcombine"), + "/usr/local/bin/swfcombine", + "/usr/bin/swfcombine" + ] + else: + locations = [os.path.join(basedir, "swfcombine.exe"), + "c:\\swftools\\swfcombine.exe"] + params = ['"'+p+'"' for p in params] + + for e in locations: + if os.path.isfile(e): + exe = e + break + + if hasattr(os,"spawnv"): + print "spawnv",exe,params + ret = -1 + try: + ret = os.spawnv(os.P_WAIT, exe, ["swfcombine"]+params) + except: + ret = -1 + if not ret: + return + + cmd = '"' + exe + '"' + " " + (" ".join(params)) + print "system",cmd + ret = os.system(cmd) + if ret&0xff00: + error("Couldn't execute swfcombine.exe- error code "+str(ret)) + +ICON_SIZE = 64 + +EVENT_PAGE_CHANGE = 1 +EVENT_FILE_CHANGE = 2 +EVENT_STATUS_TEXT = 4 + +class ProgressFrame(wx.Dialog): + def __init__(self, parent, message=""): + wx.Dialog.__init__(self, parent, -1, "Progress", size=(350, 150)) + panel = wx.Panel(self, -1) + self.count = 0 + + self.msg = wx.StaticText(panel, -1, message, (20,25)) + self.gauge = wx.Gauge(panel, -1, 100, (20, 50), (250, 25)) + + self.gauge.SetBezelFace(3) + self.gauge.SetShadowWidth(3) + + self.Bind(wx.EVT_WINDOW_DESTROY, self.close, id=wx.ID_CLOSE) + + def setProgress(self, num): + self.gauge.SetValue(int(num)) + + def close(self, event): + print "close" + + +def swapextension(filename,newext): + basename,ext = os.path.splitext(filename) + return basename + "." + newext + +def has_different_size_pages(doc): + width,height = 0,0 + for i in range(1,doc.pages+1): + page = doc.getPage(i) + if i==1: + width,height = page.width,page.height + else: + if abs(width-page.width)>2 or \ + abs(height-page.height)>2: + return 1 + return 0 + + +options = [] +gfx_options = {} + +class Option: + def __init__(self, parameter, text, options, default, mapping=None): + self.parameter = parameter + self.text = text + self.options = options + self.default = default + self.mapping = mapping + self.control = None + self.enabled = 1 + self.register() + + def generateControl(self, panel): + if type(self.options) == type((0,)): + control = wx.Choice(panel, -1, choices=self.options) + control.SetSelection(self.default) + elif self.options == "slider": + control = wx.Slider(panel, -1, self.default, 0, 100, size=(100, -1), style=wx.SL_HORIZONTAL|wx.SL_LABELS|wx.SL_TOP) + elif self.options == "spinner": + control = wx.SpinCtrl(panel, -1, str(self.default)) + else: + control = wx.Choice(panel, -1, choices=["broken"]) + control.SetSelection(0) + + self.control = control + return self.control + + def getSettings(self): + value = "" + if type(self.options) == type((0,)): + value = self.options[self.control.GetCurrentSelection()] + if self.mapping and value in self.mapping: + value = str(self.mapping[value]) + if value == "yes": + value = "1" + elif value == "no": + value = "0" + return {self.parameter:value} + elif self.options == "slider" or self.options == "spinner": + value = str(self.control.GetValue()) + return {self.parameter:value} + + def register(self): + global options + options += [self] + +class Option2(Option): + + def __init__(self, parameter, text, options, default, mapping=None): + Option.__init__(self, parameter, text, options, default, mapping) + self.enabled = 0 + + def generateControl(self, panel): + p = wx.Panel(panel, -1) + #p.SetOwnBackgroundColour('#ff0000') + h = wx.BoxSizer(wx.HORIZONTAL) + control = wx.Choice(p, -1, choices=self.options) + control.SetSelection(self.default) + text = wx.StaticText(p, -1, self.text) + h.Add(text,1,wx.EXPAND|wx.ALIGN_LEFT|wx.TOP, 5) + h.Add(control,1,wx.EXPAND|wx.ALIGN_RIGHT|wx.ALIGN_TOP) + self.control = control + if self.enabled: + control.Enable() + else: + control.Disable() + p.SetSizer(h) + p.Fit() + return p + + def Disable(self): + self.enabled=0 + if self.control: + self.control.Disable() + + def Enable(self): + self.enabled=1 + if self.control: + self.control.Enable() + + def getSettings(self): + if not self.enabled: + return {} + return Option.getSettings(self) + +class ChooseAndText(Option): + def __init__(self, parameter, text, options, default, editselection, textvalue=""): + Option.__init__(self, parameter, text, options, default) + self.editselection = editselection + self.selection = default + self.textvalue = textvalue + self.enabled = 0 + self.choice = None + + def generateControl(self, panel): + p = wx.Panel(panel, -1) + h = wx.BoxSizer(wx.HORIZONTAL) + control = wx.Choice(p, -1, choices=self.options) + p.Bind(wx.EVT_CHOICE, self.OnChoice, control) + control.SetSelection(self.default) + text = wx.StaticText(p, -1, self.text) + if self.selection == self.editselection: + edittext = wx.TextCtrl(p, -1, self.textvalue) + self.textvalue = "" + else: + edittext = wx.TextCtrl(p, -1, "") + edittext.Disable() + p.Bind(wx.EVT_TEXT, self.OnText, edittext) + h.Add(text,1,wx.EXPAND|wx.ALIGN_LEFT|wx.TOP, 5) + h.Add(control,1,wx.EXPAND|wx.ALIGN_RIGHT) + h.Add(edittext,1,wx.EXPAND|wx.ALIGN_RIGHT) + self.choice = control + self.edittext = edittext + if self.enabled: + control.Enable() + else: + control.Disable() + p.SetSizer(h) + p.Fit() + return p + + def OnText(self, event): + text = self.edittext.GetValue() + text2 = "".join(c for c in text if c.isdigit()) + if text2!=text: + self.edittext.SetValue(text2) + + def OnChoice(self, event): + self.selection = self.choice.GetCurrentSelection() + if self.selection != self.editselection: + if not self.textvalue and self.edittext.GetValue(): + self.textvalue = self.edittext.GetValue() + self.edittext.SetValue("") + self.edittext.Disable() + else: + if self.textvalue and not self.edittext.GetValue(): + self.edittext.SetValue(self.textvalue) + self.textvalue = "" + self.edittext.Enable() + + def Disable(self): + self.enabled=0 + if not self.choice: + return + self.choice.Disable() + self.edittext.Disable() + + def Enable(self): + self.enabled=1 + if not self.choice: + return + self.choice.Enable() + if self.choice.GetCurrentSelection() == self.editselection: + if self.textvalue and not self.edittext.GetValue(): + self.edittext.SetValue(self.textvalue) + self.textvalue = "" + self.edittext.Enable() + else: + self.edittext.Disable() + + def getSettings(self): + if not self.enabled: + return {} + if self.choice.GetCurrentSelection() != self.editselection: + value = self.options[self.choice.GetCurrentSelection()] + else: + value = self.edittext.GetValue().strip() + return {self.parameter:value} + +class TextOption: + def __init__(self, parameter, label, default=""): + self.parameter = parameter + self.label = label + self.default = default + self.register() + + def generateControl(self, panel): + v = wx.BoxSizer(wx.VERTICAL) + self.control = wx.TextCtrl(panel, -1, self.default, size=(250, -1)) + self.control.Fit() + return self.control + + def getSettings(self): + settings = {} + for items in self.control.GetValue().split(" "): + if "=" in items: + l = items.split("=") + if len(l) == 2: + settings[l[0]] = l[1] + return settings + + def register(self): + global options + options += [self] + +class RadioOption(Option): + def __init__(self, text, options): + self.text = text + self.options = options + self.selected = "==nothing==" + self.radios = [] + self.register() + + def generateControl(self, panel): + control = wx.Panel(panel, -1) + vsplit = wx.BoxSizer(wx.VERTICAL) + for i in range(len(self.options)/2): + text = self.options[i*2] + if i == 0: + c = wx.RadioButton(control, -1, text, style=wx.RB_GROUP) + else: + c = wx.RadioButton(control, -1, text) + control.Bind(wx.EVT_RADIOBUTTON, self.OnRadio, c) + self.radios += [c] + vsplit.Add(c) + control.SetSizer(vsplit) + control.Fit() + self.control = control + return control + + def OnRadio(self, event): + self.selected = event.GetEventObject().GetLabel() + + def getSettings(self): + for i in range(len(self.options)/2): + if self.options[i*2] == self.selected: + return self.options[i*2+1] + return self.options[1] + +class BitmapWindow(wx.Window): + def __init__(self, parent, image): + wx.Window.__init__(self, parent, -1) + self.image = image + self.SetMinSize((image.GetWidth()+2, image.GetHeight()+2)) + self.SetMaxSize((image.GetWidth()+2, image.GetHeight()+2)) + self.SetSize((image.GetWidth()+2, image.GetHeight()+2)) + self.Bind(wx.EVT_PAINT, self.OnPaint) + self.Update() + def OnPaint(self, event): + dc = wx.PaintDC(self) + self.Draw(dc) + def Draw(self,dc=None): + if not dc: + dc = wx.ClientDC(self) + dc.DrawRectangleRect((0, 0, self.image.GetWidth()+2, self.image.GetHeight()+2)) + dc.DrawBitmap(self.image, 1, 1, False) + +class ImageRadioOption(Option): + def __init__(self, text, options): + self.text = text + self.options = options + self.selected = "==nothing==" + self.radios = [] + self.register() + self.ids = [] + + def generateControl(self, panel): + control = wx.Panel(panel, -1) + vsplit = wx.BoxSizer(wx.VERTICAL) + first = 1 + for image,text,params,selected,extraoptions in self.options: + hsplit = wx.BoxSizer(wx.HORIZONTAL) + + v = wx.BoxSizer(wx.VERTICAL) + + name,text = text.split("- ") + + c = wx.CheckBox(control, -1, name) + control.Bind(wx.EVT_CHECKBOX, self.OnRadio, c) + + # radio buttons crash windows when clicked on- even without event bindings. + # This is caused by the subpanel which is created for extra options + # (I tried this with a empty Panel(), and even that crashed) + #if first: + # c = wx.RadioButton(control, -1, name, style=wx.RB_GROUP) + #else: + # c = wx.RadioButton(control, -1, name) + #control.Bind(wx.EVT_RADIOBUTTON, self.OnRadio, c) + + self.ids += [c.GetId()] + + first = 0 + + if "disable" in text: + c.Enable(False) + if selected: + self.selected = c.GetId() + c.SetValue(True) + else: + c.SetValue(False) + self.radios += [c] + + bitmap = BitmapWindow(control, image) + t = wx.StaticText(control, -1, text, size=(400,50)) + + v.Add(c, 0, wx.EXPAND) + v.Add(t, 0, wx.EXPAND|wx.LEFT, 20) + + for o in extraoptions: + cx = o.generateControl(control) + if selected: + o.Enable() + else: + o.Disable() + v.Add(cx, 0, wx.EXPAND|wx.LEFT, 20) + + v.SetMinSize((330,170)) + + hsplit.Add(bitmap, 0, wx.LEFT|wx.RIGHT|wx.BOTTOM|wx.ALIGN_TOP, 5) + hsplit.Add(v, 0, wx.EXPAND) + vsplit.Add(hsplit, 0, wx.EXPAND) + + control.SetSizer(vsplit) + control.Fit() + self.control = control + return vsplit + + def OnRadio(self, event): + self.selected = event.GetEventObject().GetId() + for c in self.radios: + if c.GetId() == self.selected: + c.SetValue(1) + else: + c.SetValue(0) + i = 0 + for image,text,params,selected,extraoptions in self.options: + if self.ids[i] == self.selected: + for xo in extraoptions: + xo.Enable() + pass + else: + for xo in extraoptions: + xo.Disable() + pass + i = i + 1 + event.ResumePropagation(0) + + def getSettings(self): + i = 0 + for image,text,params,s,extraoptions in self.options: + id = self.ids[i] + i = i + 1 + if id == self.selected: + return params + return {} + + +class OptionFrame(wx.Dialog): + + def __init__(self, parent): + wx.Dialog.__init__(self, parent, -1, "Options") + + #self.nb = wx.Notebook(self, -1)#, wx.Point(0,0), wx.Size(0,0), wxNB_FIXEDWIDTH) + self.nb = wx.Notebook(self, -1) + + self.needreload = 0 + + options0 = [RadioOption('Rendering mode', + ["Convert polygons to polygons and fonts to fonts", {}, + "Convert fonts to fonts, everything else to bitmaps", {"poly2bitmap":"1"}, + "Convert everthing to bitmaps", {"poly2bitmap":"1", "bitmapfonts":"1"} + ])] + + mp_options = [] + sv_options = [Option2('flashversion', 'Flash version:', ('4','5','6','7','8'), 2), + Option2('transparent', 'Make SWF file transparent:', ('no','yes'), 0), + ] + + raw_options = [Option2('flashversion', 'Flash version:', ('4','5','6','7','8','9'), 2), + Option2('insertstop', 'Insert stop after each frame:', ('no','yes'), 0), + Option2('transparent', 'Make SWF file transparent:', ('no','yes'), 0), + ] + rfxview_options = [ChooseAndText('rfxwidth', 'Width:', ('same as PDF','fullscreen','custom'),1,2,"600"), + ChooseAndText('rfxheight', 'Height:', ('same as PDF','fullscreen','custom'),1,2,"800"), + Option2('rfxzoomtype', 'Initial zoom level:', ('Original resolution','Show all','Maximum width/height'),2), + ] + + options4 = [ImageRadioOption('Select Paging GUI', + [(staticdata.raw_bitmap, "No Viewer- The SWF will be in \"raw\" format, with each page a seperate frame. Use this if you want to add a viewer yourself afterwards.", {}, 0, raw_options), + (staticdata.simpleviewer_bitmap, "SimpleViewer- A tiny viewer, which attaches directly to the SWF, and provides small previous/next buttons in the upper left corner", {"simpleviewer":"1", "insertstop":"1"}, 0, sv_options), + (staticdata.rfxview_bitmap, "rfxView- A more sophisticated viewer with zooming and scrolling.", {"rfxview":"1", "flashversion":"8"}, 1, rfxview_options), + #(staticdata.motionpaper_bitmap, "MotionPaper- A highly sophisticated viewer with page flipping. (disabled in this evaluation version)", {}, 0, mp_options), + #(staticdata.motionpaper_bitmap, "Your advertisement here- Are you are company who developed a viewer for pdf2swf, or who offers commercial PDF hosting service? Place your advertisement or demo viewer here, or allow pdf2swf to upload SWFs directly to your site! contact sales@swftools.org for details.", {}, 0, mp_options), + ])] + + options1 = [Option('zoom', 'Resolution (in dpi):', "spinner", 72), + Option('fontquality', 'Font quality:', "slider", 20), + Option('storeallcharacters', 'Insert full fonts in SWF file:', ('no','yes'), 0), + Option('splinequality', 'Polygon quality:', "slider", 100), + Option('jpegquality', 'JPEG quality:', "slider", 75), + Option('jpegsubpixels', 'JPEG image resolution:', ('same as in PDF', '1x', '2x', '4x'), 0, {"same as in PDF": 0, "1x": 1, "2x": 2, "3x": 3}), + Option('ppmsubpixels', 'non-JPEG image resolution:', ('same as in PDF', '1x', '2x', '4x'), 0, {"same as in PDF": 0, "1x": 1, "2x": 2, "3x": 3}), + ] + + + options3 = [TextOption('_additional_', 'Additional options')] + + panel1 = [('Rendering options', options0,''), + ('Quality',options1,'v')] + panel3 = [('Select paging GUI', options4,'')] + panel4 = [('Additional options', options3,'')] + + panels = [('Quality', panel1), + ('Viewer', panel3), + ('Advanced', panel4)] + + for name,poptions in panels: + panel = wx.Panel(self.nb, -1) + self.nb.AddPage(panel, name) + + vsplit = wx.BoxSizer(wx.VERTICAL) + + for name,options,align in poptions: + optiongroup = wx.StaticBox(panel, -1, name) + optiongroupsizer= wx.StaticBoxSizer(optiongroup, wx.VERTICAL) + optiongroup.SetSizer(optiongroupsizer) + + if align == 'v': + grid = wx.GridSizer(rows=len(options), cols=2, hgap=3, vgap=3) + optiongroupsizer.Add(grid, 1, wx.EXPAND, 0) + else: + grid = wx.GridSizer(rows=len(options), cols=1, hgap=3, vgap=3) + optiongroupsizer.Add(grid, 1, wx.EXPAND, 0) + + for option in options: + if align=='v': + t = wx.StaticText(panel, -1, option.text) + grid.Add(t, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) + optionbox = option.generateControl(panel) + grid.Add(optionbox, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) + + vsplit.Add(optiongroupsizer, 0, wx.EXPAND, 0) + + #hs = wx.BoxSizer(wx.HORIZONTAL) + #hs.Add(gobutton, 0, wx.ALIGN_CENTER, 0) + gobutton = wx.Button(panel, -1, "Apply") + self.Bind(wx.EVT_BUTTON, self.Apply, gobutton) + + vsplit.Add(gobutton, 0, wx.ALIGN_CENTER|wx.ALL, 0) + + panel.SetSizer(vsplit) + panel.Fit() + + self.nb.Fit() + + self.Fit() + + + def updateOptions(self): + global options,gfx_options + a = [] + + # FIXME: we clear *our* options- but gfx will still have + # stored the old ones. Critical for options in the "imageradio" section. + gfx_options.clear() + i = 0 + print "----- options ------" + for option in options: + for k,v in option.getSettings().items(): + gfx_options[k] = v + gfx.setparameter(k,v) + print k,v + i = i + 1 + + # TODO: filter out "global" options, and do this only if + # pdf layer is affected + + def Apply(self, event): + self.updateOptions() + self.Hide() + self.needreload = 1 + + +class State: + def __init__(self): + self.pdf = None + self.page = None + self.pagenr = 1 + self.pagebitmap = None + self.bitmap_width = 0 + self.bitmap_height = 0 + self.bitmap_page = 0 + self.filename = None + self.status_text = None + self.lastsavefile = "output.swf" + self.lasthtmlfile = "index.html" + + self.listeners = [] + + def onEvent(self,event_type, function): + self.listeners += [(event_type,function)] + def loadPDF(self,filename): + self.filename = filename + self.lastsavefile = swapextension(filename,"swf") + self.lasthtmlfile = swapextension(filename,"html") + + self.pdf = gfx.open("pdf",filename) + if(has_different_size_pages(self.pdf)): + # just let the user know- for now, we can't handle this properly + dlg = wx.MessageDialog(app.frame, """In this PDF, width or height are not the same for each page. This might cause problems if you export pages of different dimensions into the same SWF file.""", "Notice", style=wx.OK, pos=wx.DefaultPosition) + dlg.ShowModal() + dlg.Destroy() + + self.changePage(1) + + for type,f in self.listeners: + if type&EVENT_PAGE_CHANGE or type&EVENT_FILE_CHANGE: + f() + self.setStatus("File loaded successfully.") + + def saveSWF(self, filename, progress, pages=None, html=0): + if html: + basename,ext = os.path.splitext(filename) + if not ext: + html = basename + ".html" + filename = basename + ".swf" + elif ext.lower() != ".swf": + html = filename + filename = basename + ".swf" + else: + html = basename + ".html" + filename = filename + + steps = 100.0 / (self.pdf.pages*2 + 3) + pos = [0] + + self.lastsavefile = filename + if html: + self.lasthtmlfile = html + + swf = gfx.SWF() + for k,v in gfx_options.items(): + swf.setparameter(k,v) + if pages is None: + pages = range(1,self.pdf.pages+1) + pdfwidth,pdfheight=0,0 + for pagenr in pages: + page = self.pdf.getPage(pagenr) + pdfwidth = page.width + pdfheight = page.height + swf.startpage(page.width, page.height) + page.render(swf) + swf.endpage() + swf.save(filename) + if not os.path.isfile(filename): + error("Couldn't create file "+filename) + + if gfx_options.get("rfxview",None): + rfxview = os.path.join(basedir, "rfxview.swf") + if not os.path.isfile(rfxview): + error("File rfxview.swf not found in working directory") + else: + size1 = os.stat(filename)[stat.ST_SIZE] + swfcombine([rfxview,"viewport="+filename,"-o",filename]) + size2 = os.stat(filename)[stat.ST_SIZE] + if size1 == size2: + error("Couldn't add viewer to file "+filename) + + if html: + version = int(gfx_options.get("flashversion", "8")) + swf = gfx.open("swf", filename) + page1 = swf.getPage(1) + + width,height = str(page1.width),str(page1.height) + + + w = gfx_options.get("rfxwidth","") + if w == "fullscreen": width = "100%" + elif w == "same as PDF": width = pdfwidth+40 + elif w.isdigit(): width = w + else: width = pdfwidth + + h = gfx_options.get("rfxheight","") + if h == "fullscreen": height = "100%" + elif h == "same as PDF": height = pdfheight+70 + elif h.isdigit(): height = h + else: height = pdfwidth + + flashvars = "" + zoomtype = gfx_options.get("rfxzoomtype","") + if zoomtype=="Original resolution": + flashvars = "zoomtype=1" + elif zoomtype=="Show all": + flashvars = "zoomtype=2" + elif zoomtype=="Maximum width/height": + flashvars = "zoomtype=3" + + swffilename = os.path.basename(filename) + fi = open(html, "wb") + fi.write(HTMLTEMPLATE % locals()) + fi.close() + + + def changePage(self,page): + self.pagenr = page + self.page = self.pdf.getPage(self.pagenr) + for type,f in self.listeners: + if type&EVENT_PAGE_CHANGE: + f() + + def getPageIcon(self,pagenr): + page = self.pdf.getPage(pagenr) + return wx.BitmapFromImage(wx.ImageFromData(ICON_SIZE,ICON_SIZE,page.asImage(ICON_SIZE,ICON_SIZE))) + #return wx.BitmapFromImage(wx.ImageFromData(8,8,"0"*(64*3))) + + def getPageImage(self, width, height): + if self.bitmap_width == width and self.bitmap_height == height and self.bitmap_page == self.pagenr: + return self.pagebitmap + else: + self.bitmap_width = width + self.bitmap_height = height + self.bitmap_page = self.pagenr + self.pagebitmap = wx.BitmapFromImage(wx.ImageFromData(width,height,self.page.asImage(width,height))) + #self.pagebitmap = wx.BitmapFromImage(wx.ImageFromData(8,8,"0"*(64*3))) + return self.pagebitmap + + def setStatus(self,text): + self.status_text = text + for type,f in self.listeners: + if type&EVENT_STATUS_TEXT: + f() + +state = State() + +class PageListWidget(wx.ListCtrl): + def __init__(self,parent): + wx.ListCtrl.__init__(self,parent,style=wx.LC_ICON|wx.LC_AUTOARRANGE) + #self.SetMinSize((ICON_SIZE+8,-1)) + #self.SetMaxSize((ICON_SIZE+8,-1)) + #self.SetSize((ICON_SIZE+8,-1)) + self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.SelectItem) + state.onEvent(EVENT_FILE_CHANGE, self.reload) + state.onEvent(EVENT_PAGE_CHANGE, self.switchPage) + self.reload() + self.dontcare = 0 + #self.Bind(wx.EVT_IDLE, self.OnIdle) + #print dir(self) + + def processFiles(self): + if self.filepos >= 0 and self.filepos < state.pdf.pages: + icon = state.getPageIcon(self.filepos+1) + self.imglist.Add(icon) + self.InsertImageStringItem(self.filepos, str(self.filepos+1), self.filepos) + self.filepos = self.filepos + 1 + self.Update() + + def OnIdle(self,event): + self.processFiles() + event.ResumePropagation(0) + + def reload(self): + self.filepos = -1 + self.DeleteAllItems() + self.imglist = wx.ImageList(ICON_SIZE,ICON_SIZE,mask=False) + self.AssignImageList(self.imglist,wx.IMAGE_LIST_NORMAL) + self.filepos = 0 + while state.pdf and self.filepos < state.pdf.pages: + self.processFiles() + + def switchPage(self): + if self.dontcare: + self.dontcare = 0 + return + for i in range(0,self.GetItemCount()): + self.Select(i, False) + self.Select(state.pagenr-1, True) + self.Focus(state.pagenr-1) + self.Update() + + def SelectItem(self,event): + self.dontcare = 1 #ignore next change event + state.changePage(event.GetIndex()+1) + + +helptxt = """ +This is the SWF preview window. +Here, you will see how the SWF file generated from +the PDF file will look like. Changing parameters in +the configuration which affect the appeareance of +the final SWF will affect this preview, too, so you +can always evaluate the final output beforehand. +""" + + +class OnePageWidget(wx.Window): + def __init__(self,parent): + wx.Window.__init__(self, parent) + self.SetSize((160,100)) + self.SetMinSize((160,100)) + self.Fit() + self.Bind(wx.EVT_PAINT, self.OnPaint) + self.Bind(wx.EVT_SIZE, self.OnSize) + self.Bind(wx.EVT_KEY_DOWN, self.key_down) + state.onEvent(EVENT_PAGE_CHANGE, self.OnPageChange) + + def key_down(self, event): + if state.pdf: + if event.GetKeyCode() == 312 and state.pagenr>1: + state.changePage(state.pagenr-1) + elif event.GetKeyCode() == 313 and state.pagenr state.page.height * window_width: + width = window_width + height = window_width * state.page.height / state.page.width + posy = (window_height - height) / 2 + else: + width = window_height * state.page.width / state.page.height + height = window_height + posx = (window_width - width) / 2 + + dc.DrawBitmap(state.getPageImage(width,height), posx,posy, False) + #state.getPageImage( + + def OnPaint(self, event): + dc = wx.PaintDC(self) + self.Draw(dc) + +class Pdf2swfFrame(wx.Frame): + #def __init__(self): + #wx.Window.__init__(self, None, id=-1, pos=wx.DefaultPosition, size=wx.DefaultSize) + def __init__(self,application): + wx.Frame.__init__(self, None, -1, style = wx.DEFAULT_FRAME_STYLE) + self.application = application + + self.SetTitle("pdf2swf") + self.createMenu() + self.createToolbar() + self.createStatusBar() + self.createMainFrame() + + self.SetSize((800,600)) + + self.options = OptionFrame(None) + self.options.Show(False) + self.options.updateOptions() + + state.onEvent(EVENT_STATUS_TEXT, self.status_change) + self.html = 0 + + #self.table = wx.AcceleratorTable([(wx.ACCEL_ALT, ord('X'), 333),]) + #self.SetAcceleratorTable(self.table) + + self.Bind(wx.EVT_IDLE, self.OnIdle) + self.Bind(wx.EVT_CLOSE, self.menu_exit) + return + + def menu_open(self,event): + global state + if state.filename: + dlg = wx.FileDialog(self, "Choose PDF File:", style = wx.DD_DEFAULT_STYLE, defaultFile = state.filename, wildcard = "PDF files (*.pdf)|*.pdf|all files (*.*)|*.*") + else: + dlg = wx.FileDialog(self, "Choose PDF File:", style = wx.DD_DEFAULT_STYLE, wildcard = "PDF files (*.pdf)|*.pdf|all files (*.*)|*.*") + + if dlg.ShowModal() == wx.ID_OK: + self.filename = dlg.GetFilename() + state.loadPDF(self.filename) + + def menu_save(self,event,pages=None): + html,self.html = self.html,0 + global state + if not state.pdf: + return + print "html",html + if not html: + defaultFile = state.lastsavefile + else: + defaultFile = state.lasthtmlfile + dlg = wx.FileDialog(self, "Choose Save Filename:", style = wx.SAVE | wx.OVERWRITE_PROMPT, defaultFile = defaultFile, wildcard = "all files (*.*)|*.*|SWF files (*.swf)|*.swf|HTML template (*.html)|*.html") + + if dlg.ShowModal() == wx.ID_OK: + filename = os.path.join(dlg.GetDirectory(),dlg.GetFilename()) + + #progress = ProgressFrame(self, "Saving %s File '%s'..." % (html and "HTML" or "SWF", filename)) + #progress.Show(True) + progress = None + state.saveSWF(filename, progress, pages, html) + #progress.Destroy() + + def menu_save_selected(self,event): + if not state.pdf: + return + p = [] + for i in range(0,self.pagelist.GetItemCount()): + if self.pagelist.IsSelected(i): + p += [i+1] + self.menu_save(event, pages=p) + + def menu_save_html(self,event): + self.html = 1 + return self.menu_save(event) + + def menu_save_selected_html(self,event): + self.html = 1 + return self.menu_save_selected(event) + + def menu_exit(self,event): + self.application.Exit() + + def menu_selectall(self,event): + for i in range(0,self.pagelist.GetItemCount()): + self.pagelist.Select(i, True) + def menu_options(self,event): + self.options.Show(True) + + def status_change(self): + self.statusbar.SetStatusText(state.status_text) + + def OnIdle(self,event): + if self.options.needreload: + self.options.needreload = 0 + if state.pdf: + # reload + state.loadPDF(state.filename) + + def createMenu(self): + menubar = wx.MenuBar() + + menu = wx.Menu();menubar.Append(menu, "&File") + menu.Append(wx.ID_OPEN, "Open PDF\tCTRL-O");self.Bind(wx.EVT_MENU, self.menu_open, id=wx.ID_OPEN) + menu.AppendSeparator() + menu.Append(wx.ID_SAVE, "Save SWF (all pages)\tCTRL-W");self.Bind(wx.EVT_MENU, self.menu_save, id=wx.ID_SAVE) + menu.Append(wx.ID_SAVEAS, "Save SWF (selected pages)\tCTRL-S");self.Bind(wx.EVT_MENU, self.menu_save_selected, id=wx.ID_SAVEAS) + menu.AppendSeparator() + menu.Append(2001, "Save HTML template (all pages)\tCTRL-H");self.Bind(wx.EVT_MENU, self.menu_save_html, id=2001) + menu.Append(2002, "Save HTML template (selected pages)");self.Bind(wx.EVT_MENU, self.menu_save_selected_html, id=2002) + menu.AppendSeparator() + menu.Append(wx.ID_EXIT, "Exit\tCTRL-Q");self.Bind(wx.EVT_MENU, self.menu_exit, id=wx.ID_EXIT) + + menu = wx.Menu();menubar.Append(menu, "&Edit") + menu.Append(wx.ID_SELECTALL, "Select All\tCTRL-A");self.Bind(wx.EVT_MENU, self.menu_selectall, id=wx.ID_SELECTALL) + menu.AppendSeparator() + menu.Append(wx.ID_PREFERENCES, "Options\tCTRL-R");self.Bind(wx.EVT_MENU, self.menu_options, id=wx.ID_PREFERENCES) + + menu = wx.Menu();menubar.Append(menu, "&Help") + + self.SetMenuBar(menubar) + + + def createToolbar(self): + + tsize = (16,16) + self.toolbar = self.CreateToolBar(wx.TB_HORIZONTAL | wx.NO_BORDER | wx.TB_FLAT) + + self.toolbar.AddSimpleTool(wx.ID_OPEN, + wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN, wx.ART_TOOLBAR, tsize), + "Open") + self.toolbar.AddSimpleTool(wx.ID_SAVE, + wx.ArtProvider.GetBitmap(wx.ART_FILE_SAVE, wx.ART_TOOLBAR, tsize), + "Save selected pages") + self.toolbar.AddSimpleTool(wx.ID_PREFERENCES, + wx.ArtProvider.GetBitmap(wx.ART_LIST_VIEW, wx.ART_TOOLBAR, tsize), + "Options") + #self.toolbar.AddSeparator() + self.toolbar.Realize() + + def createStatusBar(self): + self.statusbar = self.CreateStatusBar(1) + + def createMainFrame(self): + + if 0: + self.pagelist = PageListWidget(self) + self.onepage = OnePageWidget(self) + hsplit = wx.BoxSizer(wx.HORIZONTAL) + pagelistbox = wx.StaticBox(self, -1, "Pages") + pagelistboxsizer= wx.StaticBoxSizer(pagelistbox, wx.VERTICAL) + pagelistboxsizer.Add(self.pagelist, proportion=1, flag=wx.EXPAND) + onepagebox = wx.StaticBox(self, -1, "Page 1") + onepageboxsizer= wx.StaticBoxSizer(onepagebox, wx.VERTICAL) + onepageboxsizer.Add(self.onepage, proportion=1, flag=wx.EXPAND) + hsplit.Add(pagelistboxsizer, 0, wx.EXPAND, 0) + hsplit.Add(onepageboxsizer, 1, wx.EXPAND, 0) + self.SetAutoLayout(True) + self.SetSizer(hsplit) + hsplit.Fit(self) + hsplit.SetSizeHints(self) + else: + hsplit = wx.SplitterWindow(self, style=wx.SP_3D|wx.SP_LIVE_UPDATE) + #p1 = wx.Panel(hsplit,-1, style=wx.SUNKEN_BORDER) + #p2 = wx.Panel(hsplit,-1, style=wx.SUNKEN_BORDER) + self.pagelist = PageListWidget(hsplit) + self.onepage = OnePageWidget(hsplit) + #hsplit.SplitVertically(p1,p2, sashPosition=64) + hsplit.SplitVertically(self.pagelist, self.onepage, sashPosition=ICON_SIZE*3/2) + hsplit.SetMinimumPaneSize(10) + +class MyApp(wx.App): + def __init__(self): + wx.App.__init__(self, redirect=False, filename=None, useBestVisual=False) + + #state.loadPDF("sitis2007.pdf") + #state.loadPDF("wxPython-Advanced-OSCON2004.pdf") + global staticdata + staticdata = StaticData() + + self.frame = Pdf2swfFrame(self) + self.SetTopWindow(self.frame) + self.frame.Show(True) + + #self.frame = TestFrame(self) + #self.frame.Show(True) + + def OnInit(self): + return True + + raw_width=100 raw_height=100 raw_data="""\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfa\xfa\xfa\xff\xff\xffQQQ\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"""+\ @@ -399,3 +1460,6 @@ rfxview_data="""\xcb\xcb\xcb\xcb\xcb\xcb\xcc\xcc\xcc\xcb\xcb\xcb\xcc\xcc\xcc\xcb """\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xfd\xfd\xfd\xff\xff\xff\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfd\xfd\xfd\xfd\xfd\xfd\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\xfc\xfc\xfc\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd"""+\ """\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfb\xfb\xfb\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xf3\xf3\xf3\xa6\xa6\xa6\xf7\xf7\xf7\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\xfc\xfc\xfc\xff\xff\xff\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xff\xc3\xc3\xc3\xb2\xb2\xb2\xec\xec\xec\xff\xff\xff\xff\xff\xff\xd1\xd1\xd1\xcb\xcb\xcb\xb0\xb0\xb0bbbkkk\xb1\xb1\xb1\xfb\xfb\xfb\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfb\xfb\xfb\xfd\xfd\xfd\xfc\xfc\xfc\xfc\xfc\xfc\xfd\xfd\xfd\xfd\xfd\xfd\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfb\xfb\xfb\xfc\xfc\xfc\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xfb\xfb\xfb\xfc\xfc\xfc\xfd\xfd\xfd\xfb\xfb\xfb\xfd\xfd\xfd\xfa\xfa\xfa\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfc\xfc\xfc\xfd\xfd\xfd\xfb\xfb\xfb\xfb\xfb\xfb\xfd\xfd\xfd\xfc\xfc\xfc\xfc\xfc\xfc\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfb\xfb\xfb\xfc\xfc\xfc\xfc\xfc\xfc\xfb\xfb\xfb\xfc\xfc\xfc\xff\xff\xff\xfb\xfb\xfb\xfd\xfd\xfd\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfc\xfc\xfc\xfe\xfe\xfe\xfe\xfe\xfe\xfb\xfb\xfb\xfc\xfc\xfc\xfd\xfd\xfd\xfb\xfb\xfb\xfd\xfd\xfd\xfc\xfc\xfc\xfb\xfb\xfb\xfd\xfd\xfd\xfc\xfc\xfc\xfd\xfd\xfd\xfd\xfd\xfd\xfc\xfc\xfc\xfc\xfc\xfc\xfd\xfd\xfd\xfd\xfd\xfd\xfc\xfc\xfc\xfe\xfe\xfe\xfc\xfc\xfc\xfc\xfc\xfc\xfd\xfd\xfd\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfb\xfb\xfb\xff\xff\xff\xd0\xd0\xd0\xcb\xcb\xcb\xb0\xb0\xb0bbbkkk\xb1\xb1\xb1\xf5\xf5\xf5\xc0\xc0\xc0\xc4\xc4\xc4\xff\xff\xff\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xff\xf2\xf2\xf2\xc8\xc8\xc8\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xff\xfa\xfa\xfa\xc5\xc5\xc5\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfc\xfc\xfc\xff\xff\xff\xc9\xc9\xc9\xef\xef\xef\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xf5\xf5\xf5\xb0\xb0\xb0\xfa\xfa\xfa\xff\xff\xff\xfd\xfd\xfd\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfc\xfc\xfc\xfd\xfd\xfd\xfc\xfc\xfc\xff\xff\xff\xd3\xd3\xd3\xe2\xe2\xe2\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xff\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xfd\xfd\xfd\xfd\xfd\xfd\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xff\xd1\xd1\xd1\xcb\xcb\xcb\xb0\xb0\xb0bbbkkk\xb1\xb1\xb1\x80\x80\x80\x97\x97\x97\xf2\xf2\xf2\xfe\xfe\xfe\xfc\xfc\xfc\xff\xff\xff\xe8\xe8\xe8\xde\xde\xde\xed\xed\xed\xea\xea\xea\xe6\xe6\xe6\xf2\xf2\xf2\xec\xec\xec\xe9\xe9\xe9\xf9\xf9\xf9\xe2\xe2\xe2\xd6\xd6\xd6\xf1\xf1\xf1\xa4\xa4\xa4\xe9\xe9\xe9\xdd\xdd\xdd\xec\xec\xec\xe0\xe0\xe0\xe2\xe2\xe2\xf2\xf2\xf2\xe4\xe4\xe4\xfa\xfa\xfa\xa5\xa5\xa5\xe4\xe4\xe4\xda\xda\xda\xfc\xfc\xfc\xe3\xe3\xe3\xe5\xe5\xe5\xfa\xfa\xfa\xe0\xe0\xe0\xd5\xd5\xd5\xfb\xfb\xfb\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xff\xd8\xd8\xd8\xf4\xf4\xf4\xf6\xf6\xf6\xe9\xe9\xe9\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xc7\xc7\xc7\xbb\xbb\xbb\xf8\xf8\xf8\xe4\xe4\xe4\xf8\xf8\xf8\x7c\x7c\x7c\xe0\xe0\xe0\xe5\xe5\xe5\xf8\xf8\xf8\xe3\xe3\xe3\xf8\xf8\xf8\xe6\xe6\xe6\xd3\xd3\xd3\xf5\xf5\xf5\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xdf\xdf\xdf\xe8\xe8\xe8\xec\xec\xec\xd1\xd1\xd1\xf8\xf8\xf8\xad\xad\xad\xdb\xdb\xdb\xf5\xf5\xf5\xda\xda\xda\xfa\xfa\xfa\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xff\xf2\xf2\xf2\xe4\xe4\xe4\xfc\xfc\xfc\xf5\xf5\xf5\xd9\xd9\xd9\xf7\xf7\xf7\xef\xef\xef\xdb\xdb\xdb\xfc\xfc\xfc\xe6\xe6\xe6\xe3\xe3\xe3\xf4\xf4\xf4\xe8\xe8\xe8\xe7\xe7\xe7\xef\xef\xef\xe8\xe8\xe8\xd8\xd8\xd8\xc6\xc6\xc6\xcd\xcd\xcd\xaf\xaf\xafbbbkkk\xb1\xb1\xb1ddd\x9e\x9e\x9e\xff\xff\xff\xfb\xfb\xfb\xff\xff\xff\xcc\xcc\xcc\xbd\xbd\xbd\x98\x98\x98\xa4\xa4\xa4\xa3\xa3\xa3\xa4\xa4\xa4\xa8\xa8\xa8\xca\xca\xca\x8c\x8c\x8c\xc0\xc0\xc0\x82\x82\x82\x8e\x8e\x8e\xaa\xaa\xaa\x83\x83\x83\xd8\xd8\xd8\x7f\x7f\x7f\xf4\xf4\xf4\x91\x91\x91\x95\x95\x95\xd9\xd9\xd9\x93\x93\x93\xb1\xb1\xb1\x82\x82\x82\xd8\xd8\xd8\x86\x86\x86\xba\xba\xba\xbc\xbc\xbc\x9c\x9c\x9c\xa7\xa7\xa7\x87\x87\x87\x87\x87\x87\xc7\xc7\xc7\xff\xff\xff\xfa\xfa\xfa\xff\xff\xff\x87\x87\x87\xbe\xbe\xbe\x96\x96\x96\xdf\xdf\xdf\xff\xff\xff\xfb\xfb\xfb\xff\xff\xff\xa0\xa0\xa0\xa5\xa5\xa5\xd5\xd5\xd5\x8f\x8f\x8f\xbe\xbe\xbe\x87\x87\x87\xad\xad\xad\xe5\xe5\xe5\xaf\xaf\xaf\x7f\x7f\x7f\xad\xad\xad\x87\x87\x87\x8e\x8e\x8e\xa9\xa9\xa9\xff\xff\xff\xf8\xf8\xf8\xff\xff\xff\x99\x99\x99\xb7\xb7\xb7\x8b\x8b\x8b\x8e\x8e\x8e\xa6\xa6\xa6\x8c\x8c\x8c\xbc\xbc\xbc\xab\xab\xab\xb9\xb9\xb9\x98\x98\x98\xff\xff\xff\xfa\xfa\xfa\xff\xff\xff\xc9\xc9\xc9\x97\x97\x97\xa9\xa9\xa9\xbe\xbe\xbe\xc0\xc0\xc0\xaa\xaa\xaa\xbe\xbe\xbe\xbc\xbc\xbc\xa6\xa6\xa6\xbc\xbc\xbc\xa4\xa4\xa4\x9c\x9c\x9c\xa2\xa2\xa2\xa3\xa3\xa3\xa9\xa9\xa9\x8b\x8b\x8b\x94\x94\x94uuu\xdb\xdb\xdb\xae\xae\xaeccclll\xb2\xb2\xb2mmm\xab\xab\xab\xff\xff\xff\xf8\xf8\xf8\xff\xff\xff\x9b\x9b\x9b\xc0\xc0\xc0\xaf\xaf\xaf\xa5\xa5\xa5\xa3\xa3\xa3\xa9\xa9\xa9\x9c\x9c\x9c\xbd\xbd\xbd\x80\x80\x80\xb6\xb6\xb6\x9c\x9c\x9c\xb3\xb3\xb3\x9e\x9e\x9e\x95\x95\x95\xe6\xe6\xe6\x7c\x7c\x7c\xf2\xf2\xf2nnn\xf4\xf4\xf4\xb8\xb8\xb8\x90\x90\x90\xa6\xa6\xa6\x93\x93\x93\xe5\xe5\xe5\x83\x83\x83\x84\x84\x84\xc8\xc8\xc8\xbe\xbe\xbe\x87\x87\x87\xa7\xa7\xa7\xa9\xa9\xa9\xb6\xb6\xb6\xff\xff\xff\xf9\xf9\xf9\xff\xff\xff\x82\x82\x82\xcf\xcf\xcf\x95\x95\x95\x85\x85\x85\xff\xff\xff\xfa\xfa\xfa\xff\xff\xff\xaa\xaa\xaa\xb3\xb3\xb3\xc5\xc5\xc5\x89\x89\x89\xb3\xb3\xb3ssslll\xe9\xe9\xe9xxx\xeb\xeb\xeb\xdd\xdd\xdd\x90\x90\x90\xbe\xbe\xbe\x9c\x9c\x9c\xff\xff\xff\xf8\xf8\xf8\xff\xff\xff\x9b\x9b\x9b\xb6\xb6\xb6\x9b\x9b\x9b\xbe\xbe\xbe\x9d\x9d\x9d\xa0\xa0\xa0\xab\xab\xab\x89\x89\x89\xf4\xf4\xf4\x79\x79\x79\xff\xff\xff\xfb\xfb\xfb\xff\xff\xff\xb7\xb7\xb7\x97\x97\x97\x87\x87\x87\x8a\x8a\x8a\xff\xff\xff\xb6\xb6\xb6\x92\x92\x92\xff\xff\xff\x8c\x8c\x8c\xbb\xbb\xbb\xce\xce\xce\x7b\x7b\x7b\xa5\xa5\xa5\xa4\xa4\xa4\xa9\xa9\xa9\x99\x99\x99\xc3\xc3\xc3hhh\xdc\xdc\xdc\xae\xae\xaeccclll\xb2\xb2\xb2\x85\x85\x85\xab\xab\xab\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xde\xde\xde\x88\x88\x88xxx\xc4\xc4\xc4\x98\x98\x98\x93\x93\x93\xb2\xb2\xb2\x90\x90\x90\x99\x99\x99\xa7\xa7\xa7\xa9\xa9\xa9\xb5\xb5\xb5\xb6\xb6\xb6\x9a\x9a\x9a\xc1\xc1\xc1\x9f\x9f\x9f\xa9\xa9\xa9\x9e\x9e\x9e\xd8\xd8\xd8\x8c\x8c\x8c\x97\x97\x97\xa7\xa7\xa7\x9c\x9c\x9c\xc0\xc0\xc0\x97\x97\x97\xd4\xd4\xd4\xa5\xa5\xa5\xc8\xc8\xc8\xce\xce\xce\xa5\xa5\xa5\xb1\xb1\xb1\xbf\xbf\xbf\xff\xff\xff\xfb\xfb\xfb\xff\xff\xff\x98\x98\x98\xc1\xc1\xc1\xd8\xd8\xd8\xad\xad\xad\xfd\xfd\xfd\xfd\xfd\xfd\xff\xff\xff\xc8\xc8\xc8\x9c\x9c\x9c\x94\x94\x94\x98\x98\x98\x9d\x9d\x9d\xaa\xaa\xaa\xa3\xa3\xa3\xad\xad\xad\x9e\x9e\x9e\x98\x98\x98\xde\xde\xde\x9d\x9d\x9d\xbe\xbe\xbe\xa8\xa8\xa8\xff\xff\xff\xfa\xfa\xfa\xff\xff\xff\xa9\xa9\xa9\xb6\xb6\xb6\xa4\xa4\xa4\xbd\xbd\xbd\xad\xad\xad\xaa\xaa\xaa\xb9\xb9\xb9\xaf\xaf\xaf\xb9\xb9\xb9\xd9\xd9\xd9\xff\xff\xff\xfb\xfb\xfb\xff\xff\xff\x93\x93\x93\x96\x96\x96\xa9\xa9\xa9\x9e\x9e\x9e\x87\x87\x87\xe7\xe7\xe7\x81\x81\x81\xa3\xa3\xa3\xe1\xe1\xe1\xa3\xa3\xa3\xc2\xc2\xc2\xe4\xe4\xe4\x92\x92\x92\x92\x92\x92\xb9\xb9\xb9\xa3\xa3\xa3\xc2\xc2\xc2\x82\x82\x82\xd8\xd8\xd8\xae\xae\xaeccclll\xb2\xb2\xb2\xfd\xfd\xfd\xfc\xfc\xfc\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfb\xfb\xfb\xff\xff\xff\x8a\x8a\x8a\xbe\xbe\xbe\xff\xff\xff\xfa\xfa\xfa\xff\xff\xff\xfc\xfc\xfc\xfd\xfd\xfd\xfc\xfc\xfc\xfd\xfd\xfd\xfc\xfc\xfc\xfd\xfd\xfd\xfd\xfd\xfd\xfc\xfc\xfc\xfd\xfd\xfd\xfd\xfd\xfd\xf9\xf9\xf9\xfa\xfa\xfa\xfe\xfe\xfe\xfc\xfc\xfc\xfe\xfe\xfe\xfe\xfe\xfe\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xfb\xfb\xfb\xfb\xfb\xfb\xfe\xfe\xfe\xfc\xfc\xfc\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfc\xfc\xfc\xfd\xfd\xfd\xf8\xf8\xf8\xfd\xfd\xfd\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfc\xfc\xfc\xfd\xfd\xfd\xfc\xfc\xfc\xfd\xfd\xfd\xfc\xfc\xfc\xfd\xfd\xfd\xfc\xfc\xfc\xfd\xfd\xfd\xfa\xfa\xfa\xfd\xfd\xfd\xfc\xfc\xfc\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfd\xfd\xfd\xfd\xfd\xfd\xfc\xfc\xfc\xfd\xfd\xfd\xf9\xf9\xf9\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfd\xfd\xfd\xfc\xfc\xfc\xfe\xfe\xfe\xfe\xfe\xfe\xfb\xfb\xfb\xff\xff\xff\xfd\xfd\xfd\xfc\xfc\xfc\xff\xff\xff\xfb\xfb\xfb\xfa\xfa\xfa\xff\xff\xff\xfc\xfc\xfc\xfc\xfc\xfc\xfe\xfe\xfe\xfb\xfb\xfb\xff\xff\xff\xd2\xd2\xd2\xcc\xcc\xcc\xb1\xb1\xb1ccclll\xb2\xb2\xb2\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xe2\xe2\xe2\xec\xec\xec\xff\xff\xff\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfc\xfc\xfc\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfc\xfc\xfc\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfc\xfc\xfc\xfe\xfe\xfe\xfd\xfd\xfd\xfc\xfc\xfc\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfc\xfc\xfc\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfc\xfc\xfc\xff\xff\xff\xd0\xd0\xd0\xcc\xcc\xcc\xb1\xb1\xb1ccclll\xb2\xb2\xb2\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xf2\xf2\xf2\xf4\xf4\xf4\xff\xff\xff\xfe\xfe\xfe\xfc\xfc\xfc\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfc\xfc\xfc\xfd\xfd\xfd\xfc\xfc\xfc\xfc\xfc\xfc\xfd\xfd\xfd\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfd\xfd\xfd\xfd\xfd\xfd\xfc\xfc\xfc\xff\xff\xff\xfb\xfb\xfb\xf5\xf5\xf5\xfc\xfc\xfc\xfc\xfc\xfc\xfd\xfd\xfd\xfd\xfd\xfd\xfc\xfc\xfc\xfd\xfd\xfd\xfb\xfb\xfb\xf7\xf7\xf7\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfc\xfc\xfc\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfc\xfc\xfc\xfe\xfe\xfe\xfe\xfe\xfe\xfc\xfc\xfc\xf5\xf5\xf5\xfc\xfc\xfc\xfc\xfc\xfc\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfc\xfc\xfc\xfd\xfd\xfd\xfc\xfc\xfc\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfc\xfc\xfc\xfc\xfc\xfc\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfc\xfc\xfc\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xfc\xfc\xfc\xff\xff\xff\xd2\xd2\xd2\xcc\xcc\xcc\xb1\xb1\xb1ccclll\xb2\xb2\xb2\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfc\xfc\xfc\xff\xff\xff\x82\x82\x82\xa8\xa8\xa8\xff\xff\xff\xfc\xfc\xfc\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xf3\xf3\xf3\xe2\xe2\xe2\x83\x83\x83\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xff\xe5\xe5\xe5\x88\x88\x88\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xf3\xf3\xf3\x81\x81\x81\xfd\xfd\xfd\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfc\xfc\xfc\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfa\xfa\xfa\xc4\xc4\xc4\xcf\xcf\xcf\xb0\xb0\xb0ccclll\xb2\xb2\xb2\xfd\xfd\xfd\xfd\xfd\xfd\xff\xff\xff\xfb\xfb\xfb\xff\xff\xff\x8b\x8b\x8b\xb5\xb5\xb5\xc5\xc5\xc5\x98\x98\x98\xb8\xb8\xb8\xff\xff\xff\xfb\xfb\xfb\xff\xff\xff\xd7\xd7\xd7\xb5\xb5\xb5\xcc\xcc\xcc\xbb\xbb\xbb\xcd\xcd\xcd\xb1\xb1\xb1\xcf\xcf\xcf\x93\x93\x93\xd6\xd6\xd6\xff\xff\xff\xff\xff\xff\xcb\xcb\xcb\xa8\xa8\xa8\xab\xab\xab\xb2\xb2\xb2\xba\xba\xba\xf2\xf2\xf2\xa8\xa8\xa8\xc1\xc1\xc1\x7f\x7f\x7f\xc6\xc6\xc6\x80\x80\x80\x9e\x9e\x9e\xd4\xd4\xd4\xdb\xdb\xdb\xb0\xb0\xb0\xd1\xd1\xd1\xe9\xe9\xe9\xb3\xb3\xb3xxx\xff\xff\xff\xfb\xfb\xfb\xfe\xfe\xfe\xff\xff\xff\xe2\xe2\xe2\xa9\xa9\xa9\xbd\xbd\xbd\xca\xca\xca\xd0\xd0\xd0\xdd\xdd\xdd\xac\xac\xac\xbf\xbf\xbf\xff\xff\xff\xfd\xfd\xfd\xfd\xfd\xfd\x7a\x7a\x7a\x9b\x9b\x9b\xce\xce\xce\xdc\xdc\xdc\xb1\xb1\xb1\xce\xce\xce\xab\xab\xab\xc6\xc6\xc6\xb3\xb3\xb3\xdc\xdc\xdc\xd4\xd4\xd4\xc9\xc9\xc9\xab\xab\xab\xa6\xa6\xa6\xd3\xd3\xd3\xce\xce\xce\xdc\xdc\xdc\xaf\xaf\xaf\xbe\xbe\xbe\xbd\xbd\xbd\x99\x99\x99\xec\xec\xec\xff\xff\xff\xfb\xfb\xfb\xb0\xb0\xb0\xcc\xcc\xcc\xb5\xb5\xb5\xe1\xe1\xe1\xd3\xd3\xd3\xee\xee\xee\xcb\xcb\xcb\x9f\x9f\x9f\xf5\xf5\xf5\xfe\xfe\xfe\xff\xff\xff\xa0\xa0\xa0\x80\x80\x80\xdc\xdc\xdc\xae\xae\xaeccclll\xb2\xb2\xb2\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfb\xfb\xfb\xff\xff\xff\x8b\x8b\x8b\xbf\xbf\xbf\x9b\x9b\x9b\xb5\xb5\xb5\x8a\x8a\x8a\xff\xff\xff\xfe\xfe\xfe\xf9\xf9\xf9xxx\xf7\xf7\xf7\x7e\x7e\x7e\x82\x82\x82\xc2\xc2\xc2\x8d\x8d\x8d\xa7\xa7\xa7\x9e\x9e\x9e\xff\xff\xff\xfa\xfa\xfa\xff\xff\xff\xaa\xaa\xaa\xa3\xa3\xa3\x9a\x9a\x9a\xbd\xbd\xbd\x8d\x8d\x8d\x94\x94\x94\xaf\xaf\xaf\xb7\xb7\xb7\x8f\x8f\x8f\xdb\xdb\xdb\x8e\x8e\x8e\xc7\xc7\xc7\x83\x83\x83\x8a\x8a\x8a\xf7\xf7\xf7iii\x8c\x8c\x8c\xe9\xe9\xe9\x84\x84\x84\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xfb\xfb\xfb\x84\x84\x84\x8e\x8e\x8e\x80\x80\x80\xda\xda\xda\x8f\x8f\x8f\xb1\xb1\xb1\xb0\xb0\xb0\xff\xff\xff\xfe\xfe\xfe\xfb\xfb\xfb\x86\x86\x86\xca\xca\xca\x7e\x7e\x7e\x88\x88\x88\xf4\xf4\xf4\x7d\x7d\x7d\x95\x95\x95\x96\x96\x96lll\xd0\xd0\xd0\xaa\xaa\xaa\x9f\x9f\x9f\xb5\xb5\xb5\xb0\xb0\xb0\x88\x88\x88\xd3\xd3\xd3\x90\x90\x90\xae\xae\xae\xba\xba\xba\x87\x87\x87\xc8\xc8\xc8\xff\xff\xff\xfd\xfd\xfd\xff\xff\xff\x88\x88\x88\xbf\xbf\xbf\x90\x90\x90\xab\xab\xab\x8e\x8e\x8e\xbb\xbb\xbb\x9c\x9c\x9c\xa9\xa9\xa9\xe6\xe6\xe6\xff\xff\xff\xff\xff\xff\xab\xab\xab\x8d\x8d\x8d\xdb\xdb\xdb\xae\xae\xaeccclll\xb2\xb2\xb2\xe0\xe0\xe0\xd4\xd4\xd4\xff\xff\xff\xfa\xfa\xfa\xff\xff\xff\x7d\x7d\x7d\xb4\xb4\xb4\x9b\x9b\x9b\xbd\xbd\xbd\x83\x83\x83\xff\xff\xff\xfd\xfd\xfd\xff\xff\xffvvv\xd5\xd5\xd5\xab\xab\xab\x8b\x8b\x8b\x9b\x9b\x9b\x82\x82\x82\xa3\xa3\xa3\xaa\xaa\xaa\xff\xff\xff\xf9\xf9\xf9\xff\xff\xff\xa9\xa9\xa9\xa6\xa6\xa6\x9a\x9a\x9a\xc1\xc1\xc1\x8f\x8f\x8f\x7e\x7e\x7e\xac\xac\xac\xf0\xf0\xf0\x7e\x7e\x7e\xc0\xc0\xc0\x8d\x8d\x8d\xc7\xc7\xc7\x87\x87\x87\x84\x84\x84\xdb\xdb\xdb\x9a\x9a\x9aooo\xb4\xb4\xb4\x7a\x7a\x7a\xd4\xd4\xd4\xdb\xdb\xdb\xff\xff\xff\xfa\xfa\xfa\xff\xff\xff\xa6\xa6\xa6\x8a\x8a\x8a\x7d\x7d\x7d\xe1\xe1\xe1\x83\x83\x83\xb1\xb1\xb1\xe6\xe6\xe6\xfe\xfe\xfe\xff\xff\xff\xf8\xf8\xf8\x82\x82\x82\xcb\xcb\xcb\x82\x82\x82\x82\x82\x82\xda\xda\xda\x9f\x9f\x9f\xde\xde\xdesss\x95\x95\x95\xad\xad\xad\xc8\xc8\xc8\x7b\x7b\x7b\xe2\xe2\xe2\xf8\xf8\xf8lll\xdf\xdf\xdf\x8a\x8a\x8a\xa6\xa6\xa6\xf3\xf3\xf3\x81\x81\x81\xd8\xd8\xd8\xff\xff\xff\xfb\xfb\xfb\xff\xff\xff\x83\x83\x83\x9c\x9c\x9c\x7c\x7c\x7c\xea\xea\xea\x85\x85\x85\x84\x84\x84\x84\x84\x84\xdf\xdf\xdf\xf1\xf1\xf1\xfe\xfe\xfe\xff\xff\xff\xaa\xaa\xaa\x7e\x7e\x7e\xdc\xdc\xdc\xae\xae\xaeccclll\xb2\xb2\xb2\xe1\xe1\xe1\xd6\xd6\xd6\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xcc\xcc\xcc\xdb\xdb\xdb\xd6\xd6\xd6\xdf\xdf\xdf\xd1\xd1\xd1\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xeb\xeb\xeb\xca\xca\xca\xf2\xf2\xf2\xeb\xeb\xeb\xbc\xbc\xbc\xdb\xdb\xdb\xd8\xd8\xd8\xd8\xd8\xd8\xff\xff\xff\xfd\xfd\xfd\xff\xff\xff\xdf\xdf\xdf\xda\xda\xda\xd5\xd5\xd5\xe0\xe0\xe0\xd5\xd5\xd5\xe6\xe6\xe6\xae\xae\xae\xee\xee\xee\xd9\xd9\xd9\xd0\xd0\xd0\xd5\xd5\xd5\xdc\xdc\xdc\xda\xda\xda\xea\xea\xea\xca\xca\xca\xf7\xf7\xf7\xe3\xe3\xe3\xb6\xb6\xb6\xdc\xdc\xdc\xbd\xbd\xbd\xbe\xbe\xbe\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xf1\xf1\xf1\xec\xec\xec\xeb\xeb\xeb\xfb\xfb\xfb\xea\xea\xea\xae\xae\xae\xeb\xeb\xeb\xff\xff\xff\xff\xff\xff\xf8\xf8\xf8\xcf\xcf\xcf\xde\xde\xde\xd8\xd8\xd8\xea\xea\xea\xcb\xcb\xcb\xf2\xf2\xf2\xfe\xfe\xfe\xe5\xe5\xe5\xf1\xf1\xf1\xed\xed\xed\xff\xff\xff\xb9\xb9\xb9\xcc\xcc\xcc\xff\xff\xff\xe4\xe4\xe4\xf9\xf9\xf9\xef\xef\xef\xae\xae\xae\xe8\xe8\xe8\xd2\xd2\xd2\xe6\xe6\xe6\xff\xff\xff\xfd\xfd\xfd\xff\xff\xff\xdb\xdb\xdb\xbf\xbf\xbf\xdf\xdf\xdf\xe3\xe3\xe3\xe1\xe1\xe1\xf8\xf8\xf8\xbf\xbf\xbf\xc8\xc8\xc8\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xed\xed\xed\xac\xac\xac\xd2\xd2\xd2\xb0\xb0\xb0ccclll\xb2\xb2\xb2\xff\xff\xff\xfd\xfd\xfd\xfc\xfc\xfc\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xff\xfd\xfd\xfd\xfd\xfd\xfd\xff\xff\xff\xff\xff\xff\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xff\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\xfc\xfc\xfc\xff\xff\xff\xd2\xd2\xd2\xcb\xcb\xcb\xb0\xb0\xb0bbbkkk\xb1\xb1\xb1\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfc\xfc\xfc\xfc\xfc\xfc\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfc\xfc\xfc\xfc\xfc\xfc\xfd\xfd\xfd\xfd\xfd\xfd\xfa\xfa\xfa\xfc\xfc\xfc\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfc\xfc\xfc\xfc\xfc\xfc\xfb\xfb\xfb\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xfc\xfc\xfc\xff\xff\xff\xfc\xfc\xfc\xfb\xfb\xfb\xfc\xfc\xfc\xfe\xfe\xfe\xfc\xfc\xfc\xfb\xfb\xfb\xfb\xfb\xfb\xfd\xfd\xfd\xfd\xfd\xfd\xfb\xfb\xfb\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfb\xfb\xfb\xfd\xfd\xfd\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfc\xfc\xfc\xfd\xfd\xfd\xfc\xfc\xfc\xfd\xfd\xfd\xfc\xfc\xfc\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfb\xfb\xfb\xfc\xfc\xfc\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfb\xfb\xfb\xfd\xfd\xfd\xfc\xfc\xfc\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfd\xfd\xfd\xfb\xfb\xfb\xfc\xfc\xfc\xfd\xfd\xfd\xfc\xfc\xfc\xfe\xfe\xfe\xfc\xfc\xfc\xfc\xfc\xfc\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xd0\xd0\xd0\xcc\xcc\xcc\xb1\xb1\xb1ccclll\xb2\xb2\xb2\xff\xff\xff\xd0\xd0\xd0\xd6\xd6\xd6\xff\xff\xff\xfc\xfc\xfc\xfc\xfc\xfc\xff\xff\xff\xe5\xe5\xe5\xb1\xb1\xb1\xee\xee\xee\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xff\xff\xff\xfd\xfd\xfd\xc8\xc8\xc8\xfb\xfb\xfb\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xee\xee\xee\xc2\xc2\xc2\xe6\xe6\xe6\xd4\xd4\xd4\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xcb\xcb\xcb\xf2\xf2\xf2\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xf6\xf6\xf6\xe8\xe8\xe8\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfc\xfc\xfc\xff\xff\xff\xd1\xd1\xd1\xcb\xcb\xcb\xb0\xb0\xb0bbbkkk\xb1\xb1\xb1\xff\xff\xff\xaf\xaf\xaf\xa5\xa5\xa5\xff\xff\xff\xfa\xfa\xfa\xfd\xfd\xfd\xfe\xfe\xfe\x84\x84\x84\xc8\xc8\xc8\xef\xef\xef\xe4\xe4\xe4\xfa\xfa\xfa\xf5\xf5\xf5\xde\xde\xde\xf8\xf8\xf8\xff\xff\xff\xff\xff\xff\xf1\xf1\xf1\xf2\xf2\xf2\xda\xda\xda\xf6\xf6\xf6\xec\xec\xec\xe5\xe5\xe5\xed\xed\xed\xe9\xe9\xe9\xfb\xfb\xfb\xe8\xe8\xe8\xe6\xe6\xe6\xf0\xf0\xf0\x7a\x7a\x7a\xeb\xeb\xeb\xe0\xe0\xe0\xff\xff\xff\xe1\xe1\xe1\xf7\xf7\xf7\xde\xde\xde\xe3\xe3\xe3\xb2\xb2\xb2\xed\xed\xed\xf0\xf0\xf0\xf6\xf6\xf6\xf1\xf1\xf1\xff\xff\xff\xbe\xbe\xbe\xe1\xe1\xe1\xff\xff\xff\xfc\xfc\xfc\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfc\xfc\xfc\xff\xff\xff\xd1\xd1\xd1\xcb\xcb\xcb\xb0\xb0\xb0bbbkkk\xb1\xb1\xb1\xc6\xc6\xc6\xb4\xb4\xb4\xad\xad\xad\xff\xff\xff\xfa\xfa\xfa\xff\xff\xff\xf9\xf9\xf9qqq\xd8\xd8\xd8\xac\xac\xac\xb5\xb5\xb5\xa0\xa0\xa0\x87\x87\x87\x9a\x9a\x9a\xf2\xf2\xf2\xff\xff\xff\xba\xba\xba\xa7\xa7\xa7\xea\xea\xea\x87\x87\x87\xc8\xc8\xc8\x7f\x7f\x7f\x98\x98\x98\x9a\x9a\x9a\x92\x92\x92\xaa\xaa\xaa\x89\x89\x89\x85\x85\x85\xb8\xb8\xb8\x9c\x9c\x9c\xbb\xbb\xbb\x9a\x9a\x9a\xc8\xc8\xc8\xb4\xb4\xb4\xbf\xbf\xbf\x95\x95\x95\xb6\xb6\xb6\x85\x85\x85\xc5\xc5\xc5\x84\x84\x84\xca\xca\xca\xd3\xd3\xd3\xff\xff\xff\xca\xca\xca\x9f\x9f\x9f\xff\xff\xff\xfa\xfa\xfa\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfc\xfc\xfc\xff\xff\xff\xd1\xd1\xd1\xcb\xcb\xcb\xb0\xb0\xb0bbbkkk\xb1\xb1\xb1\xec\xec\xec\xb1\xb1\xb1\xa9\xa9\xa9\xff\xff\xff\xfa\xfa\xfa\xfd\xfd\xfd\xff\xff\xff\x89\x89\x89\xc8\xc8\xc8\x82\x82\x82\xf8\xf8\xf8\x7d\x7d\x7d\x86\x86\x86\xe5\xe5\xe5\xff\xff\xff\xff\xff\xff\xdc\xdc\xdcggg\xc2\xc2\xc2\x81\x81\x81\xc9\xc9\xc9\x92\x92\x92\xb6\xb6\xb6\xb3\xb3\xb3\xa0\xa0\xa0\xa0\xa0\xa0\xb6\xb6\xb6\xc4\xc4\xc4\x94\x94\x94\x9c\x9c\x9c\xbf\xbf\xbf\x87\x87\x87\x8d\x8d\x8d\xf2\xf2\xf2\xff\xff\xff\x80\x80\x80\xba\xba\xba\x8f\x8f\x8f\xff\xff\xff\x7b\x7b\x7b\x9c\x9c\x9c\xff\xff\xff\xff\xff\xff\xd4\xd4\xd4\x92\x92\x92\xff\xff\xff\xfb\xfb\xfb\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfc\xfc\xfc\xff\xff\xff\xd1\xd1\xd1\xcb\xcb\xcb\xb0\xb0\xb0bbbkkk\xb1\xb1\xb1\xf1\xf1\xf1\xb2\xb2\xb2\xb4\xb4\xb4\xa0\xa0\xa0\xdf\xdf\xdf\xff\xff\xff\xfa\xfa\xfa\x85\x85\x85\xe5\xe5\xe5\xa4\xa4\xa4\xba\xba\xba\xd3\xd3\xd3\x93\x93\x93\xdb\xdb\xdb\xff\xff\xff\xff\xff\xff\xdf\xdf\xdf\xbd\xbd\xbd\xb4\xb4\xb4\x95\x95\x95\xc5\xc5\xc5\x9d\x9d\x9d\xb4\xb4\xb4\xb4\xb4\xb4\xaa\xaa\xaa\xa4\xa4\xa4\x8d\x8d\x8d\xbf\xbf\xbf\xd3\xd3\xd3\x98\x98\x98\xbc\xbc\xbc\xa3\xa3\xa3\xac\xac\xac\x79\x79\x79\xe6\xe6\xe6\x93\x93\x93\xc8\xc8\xc8\x86\x86\x86\xfc\xfc\xfc\xb6\xb6\xb6\xb4\xb4\xb4\xd4\xd4\xd4\xdc\xdc\xdc\xc2\xc2\xc2\xb8\xb8\xb8\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfd\xfd\xfd\xff\xff\xff\xd2\xd2\xd2\xcc\xcc\xcc\xb1\xb1\xb1ccclll\xb2\xb2\xb2\xfe\xfe\xfe\xfb\xfb\xfb\xff\xff\xff\xd7\xd7\xd7\xf2\xf2\xf2\xff\xff\xff\xfc\xfc\xfc\xfb\xfb\xfb\xfc\xfc\xfc\xfc\xfc\xfc\xf4\xf4\xf4\xfe\xfe\xfe\xfb\xfb\xfb\xfb\xfb\xfb\xfe\xfe\xfe\xfe\xfe\xfe\xfb\xfb\xfb\xf5\xf5\xf5\xfd\xfd\xfd\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xf9\xf9\xf9\xff\xff\xff\xb7\xb7\xb7\x89\x89\x89\xff\xff\xff\xfa\xfa\xfa\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfd\xfd\xfd\xf6\xf6\xf6\xfd\xfd\xfd\xfb\xfb\xfb\xfb\xfb\xfb\xff\xff\xff\xd3\xd3\xd3\x98\x98\x98\xf8\xf8\xf8\xfe\xfe\xfe\xf6\xf6\xf6\xc4\xc4\xc4\xf9\xf9\xf9\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfc\xfc\xfc\xff\xff\xff\xd1\xd1\xd1\xcb\xcb\xcb\xb0\xb0\xb0bbbkkk\xb1\xb1\xb1\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfc\xfc\xfc\xfe\xfe\xfe\xfc\xfc\xfc\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xe9\xe9\xe9\xdc\xdc\xdc\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfc\xfc\xfc\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xff\xe6\xe6\xe6\xda\xda\xda\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\xfc\xfc\xfc\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfd\xfd\xfd\xff\xff\xff\xd2\xd2\xd2\xcc\xcc\xcc\xb1\xb1\xb1ccclll\xb2\xb2\xb2\xfb\xfb\xfb\xfb\xfb\xfb\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfc\xfc\xfc\xfc\xfc\xfc\xfd\xfd\xfd\xfc\xfc\xfc\xfc\xfc\xfc\xfe\xfe\xfe\xfe\xfe\xfe\xfc\xfc\xfc\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfd\xfd\xfd\xf8\xf8\xf8\xf3\xf3\xf3\xf3\xf3\xf3\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfb\xfb\xfb\xfe\xfe\xfe\xfc\xfc\xfc\xfc\xfc\xfc\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfc\xfc\xfc\xfc\xfc\xfc\xfd\xfd\xfd\xfb\xfb\xfb\xfd\xfd\xfd\xfd\xfd\xfd\xfc\xfc\xfc\xfd\xfd\xfd\xfc\xfc\xfc\xfb\xfb\xfb\xfd\xfd\xfd\xfc\xfc\xfc\xfb\xfb\xfb\xfd\xfd\xfd\xfd\xfd\xfd\xfc\xfc\xfc\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfc\xfc\xfc\xfc\xfc\xfc\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfb\xfb\xfb\xfe\xfe\xfe\xfd\xfd\xfd\xfc\xfc\xfc\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfd\xfd\xfd\xfc\xfc\xfc\xfd\xfd\xfd\xfc\xfc\xfc\xfd\xfd\xfd\xfc\xfc\xfc\xfb\xfb\xfb\xfc\xfc\xfc\xfe\xfe\xfe\xfc\xfc\xfc\xfc\xfc\xfc\xfe\xfe\xfe\xfb\xfb\xfb\xff\xff\xff\xd2\xd2\xd2\xcc\xcc\xcc\xb1\xb1\xb1ccclll\xb2\xb2\xb2\xfc\xfc\xfc\xff\xff\xff\xd7\xd7\xd7\xa0\xa0\xa0\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xff\xff\xff\xa0\xa0\xa0\xd5\xd5\xd5\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xfc\xfc\xfc\xff\xff\xff\x9b\x9b\x9b\xa1\xa1\xa1\xb8\xb8\xb8\xbe\xbe\xbe\xff\xff\xff\xfd\xfd\xfd\xff\xff\xff\xfb\xfb\xfb\xfc\xfc\xfc\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfc\xfc\xfc\xff\xff\xff\xb5\xb5\xb5\xbb\xbb\xbb\xff\xff\xff\xfb\xfb\xfb\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfd\xfd\xfd\xfd\xfd\xfd\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xbc\xbc\xbc\xc3\xc3\xc3\xff\xff\xff\xfd\xfd\xfd\xfd\xfd\xfd\xfa\xfa\xfa\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xd9\xd9\xd9\xa2\xa2\xa2\xff\xff\xff\xfc\xfc\xfc\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xff\xd2\xd2\xd2\xcc\xcc\xcc\xb1\xb1\xb1ccclll\xb2\xb2\xb2\xa8\xa8\xa8\xc0\xc0\xc0\xe5\xe5\xe5\x88\x88\x88\xfc\xfc\xfc\xc6\xc6\xc6\xd9\xd9\xd9\xfe\xfe\xfe\xca\xca\xca\xdb\xdb\xdb\x9d\x9d\x9d\xb9\xb9\xb9\xd4\xd4\xd4\xfa\xfa\xfa\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\x8a\x8a\x8a\xdd\xdd\xdd\xff\xff\xffxxx\xf8\xf8\xf8\xff\xff\xff\xfd\xfd\xfd\x84\x84\x84\xe3\xe3\xe3\xdd\xdd\xdd\xc5\xc5\xc5\xf7\xf7\xf7\xfe\xfe\xfe\xff\xff\xff\xba\xba\xba\x7a\x7a\x7a\xc0\xc0\xc0\xfa\xfa\xfa\xd6\xd6\xd6\xcc\xcc\xcc\xff\xff\xff\xff\xff\xff\xfd\xfd\xfd\xce\xce\xce\xc1\xc1\xc1\xcf\xcf\xcf\xc1\xc1\xc1\xee\xee\xee\xd9\xd9\xd9\xd8\xd8\xd8\xeb\xeb\xeb\xc7\xc7\xc7\xb8\xb8\xb8\xe5\xe5\xe5\xcc\xcc\xcc\xb4\xb4\xb4\xe9\xe9\xe9\xef\xef\xef\xc2\xc2\xc2\xef\xef\xef\xf0\xf0\xf0\x8b\x8b\x8b\xab\xab\xab\xff\xff\xff\xff\xff\xff\xbc\xbc\xbc\x9f\x9f\x9f\xfb\xfb\xfb\xc7\xc7\xc7\xd7\xd7\xd7\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\x8c\x8c\x8c\xc3\xc3\xc3\x7f\x7f\x7f\xbf\xbf\xbf\xf0\xf0\xf0\xe9\xe9\xe9\xc3\xc3\xc3\xf5\xf5\xf5\xff\xff\xff\xff\xff\xff\xda\xda\xda\xb9\xb9\xb9\xd1\xd1\xd1\xd3\xd3\xd3\xeb\xeb\xeb\xd9\xd9\xd9\xb6\xb6\xb6\xd1\xd1\xd1\xfd\xfd\xfd\xcb\xcb\xcb\xc4\xc4\xc4\xf5\xf5\xf5\xd1\xd1\xd1\xd7\xd7\xd7\xd6\xd6\xd6\xcb\xcb\xcb\xb1\xb1\xb1ccclll\xb2\xb2\xb2\xef\xef\xef\x7b\x7b\x7b\xae\xae\xae\xa0\xa0\xa0\x98\x98\x98\xd9\xd9\xd9\x8a\x8a\x8a\x8a\x8a\x8a\xd6\xd6\xd6\xd4\xd4\xd4\x9a\x9a\x9auuu\xf2\xf2\xf2\xff\xff\xff\xfd\xfd\xfd\xff\xff\xff\xf7\xf7\xf7\x80\x80\x80\xff\xff\xff\xec\xec\xecppp\xff\xff\xff\xfd\xfd\xfd\xfc\xfc\xfc\x86\x86\x86\xb7\xb7\xb7\xae\xae\xae\xbb\xbb\xbb\x94\x94\x94\xff\xff\xff\xff\xff\xff\xb8\xb8\xb8\x99\x99\x99\x91\x91\x91\x7a\x7a\x7a\xab\xab\xab\x84\x84\x84\xf2\xf2\xf2\xff\xff\xff\xff\xff\xffqqq\xb7\xb7\xb7\x8c\x8c\x8c\xa1\xa1\xa1\xa8\xa8\xa8\xcd\xcd\xcd\x84\x84\x84\xb0\xb0\xb0\x89\x89\x89\xb1\xb1\xb1vvv\x86\x86\x86\xb7\xb7\xb7nnn\xa7\xa7\xa7\x94\x94\x94\x94\x94\x94\xc7\xc7\xc7\xb0\xb0\xb0\xac\xac\xac\xff\xff\xff\xff\xff\xff\xb0\xb0\xb0\xab\xab\xab\x9e\x9e\x9e\xdb\xdb\xdb\x7c\x7c\x7c\xdf\xdf\xdf\xff\xff\xff\xfc\xfc\xfc\x80\x80\x80\xd1\xd1\xd1\x8f\x8f\x8f\xa8\xa8\xa8\x92\x92\x92\xaa\xaa\xaa\x88\x88\x88\xcb\xcb\xcb\xff\xff\xff\xff\xff\xff\x8c\x8c\x8c\xa7\xa7\xa7\xd2\xd2\xd2\x9c\x9c\x9c\xa2\xa2\xa2\x9a\x9a\x9a\x9c\x9c\x9c\x95\x95\x95\xb4\xb4\xb4\xa2\xa2\xa2\x8d\x8d\x8d\xab\xab\xab\x9d\x9d\x9d\x90\x90\x90\xd1\xd1\xd1\xcb\xcb\xcb\xb0\xb0\xb0bbbkkk\xb1\xb1\xb1\xff\xff\xff\xb3\xb3\xb3\xac\xac\xac\x99\x99\x99\x7b\x7b\x7b\xdd\xdd\xdd\xab\xab\xab```\xb6\xb6\xb6\xff\xff\xff\x9c\x9c\x9cQQQ\xbf\xbf\xbf\xff\xff\xff\xfb\xfb\xfb\xff\xff\xff\xcb\xcb\xcb\x86\x86\x86\xff\xff\xff\xa4\xa4\xa4\xbc\xbc\xbc\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\x8a\x8a\x8a\xa3\xa3\xa3\x95\x95\x95\xe0\xe0\xe0\x92\x92\x92\xff\xff\xff\xff\xff\xff\xb2\xb2\xb2\xae\xae\xae\xd6\xd6\xd6]]]\xa3\xa3\xa3\xed\xed\xed\xf2\xf2\xf2\xff\xff\xff\xff\xff\xff\x7a\x7a\x7a\xcf\xcf\xcf\x98\x98\x98\xbb\xbb\xbb\x90\x90\x90\xa4\xa4\xa4\x82\x82\x82\xa9\xa9\xa9\xa0\xa0\xa0\xde\xde\xde\x84\x84\x84\x97\x97\x97\xe7\xe7\xe7uuurrr\xf2\xf2\xf2\xa7\xa7\xa7\x95\x95\x95\xb4\xb4\xb4\x9f\x9f\x9f\xff\xff\xff\xff\xff\xff\xb6\xb6\xb6\xa9\xa9\xa9\x7c\x7c\x7c\xe1\xe1\xe1\x99\x99\x99\xd6\xd6\xd6\xff\xff\xff\xff\xff\xff\x82\x82\x82\xc6\xc6\xc6\x9a\x9a\x9a\xc6\xc6\xc6\x7c\x7c\x7c\x84\x84\x84\xe9\xe9\xe9\xe9\xe9\xe9\xfe\xfe\xfe\xff\xff\xff\x93\x93\x93\xd6\xd6\xd6\xb7\xb7\xb7\x8a\x8a\x8a\x97\x97\x97\x9e\x9e\x9e\xbc\xbc\xbc\x8f\x8f\x8f\xd4\xd4\xd4\x8b\x8b\x8b\xe6\xe6\xe6\x8e\x8e\x8e\xab\xab\xab\xf2\xf2\xf2\xca\xca\xca\xcd\xcd\xcd\xb1\xb1\xb1ccclll\xb2\xb2\xb2\xc9\xc9\xc9\xd6\xd6\xd6\xe1\xe1\xe1\xb6\xb6\xb6\xe4\xe4\xe4\xb4\xb4\xb4\xdc\xdc\xdc\xea\xea\xea\x86\x86\x86\xd2\xd2\xd2\xc4\xc4\xc4\xca\xca\xca\xa6\xa6\xa6\xf5\xf5\xf5\xff\xff\xff\xff\xff\xff\xc0\xc0\xc0\xb5\xb5\xb5\xd0\xd0\xd0\xd2\xd2\xd2\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xff\xaf\xaf\xaf\xd3\xd3\xd3\xc2\xc2\xc2\xc4\xc4\xc4\xf3\xf3\xf3\xff\xff\xff\xff\xff\xff\xe4\xe4\xe4\xb0\xb0\xb0\xd5\xd5\xd5\xef\xef\xef\x93\x93\x93\xc3\xc3\xc3\xff\xff\xff\xff\xff\xff\xfd\xfd\xfd\xb1\xb1\xb1\xd2\xd2\xd2\xba\xba\xba\xcd\xcd\xcd\xba\xba\xba\xa9\xa9\xa9\xb5\xb5\xb5\xb1\xb1\xb1\x7f\x7f\x7f\xcc\xcc\xcc\xde\xde\xdewww\xc0\xc0\xc0\xec\xec\xec\xb6\xb6\xb6\x9f\x9f\x9f\xf0\xf0\xf0\xaa\xaa\xaa\x9e\x9e\x9e\xca\xca\xca\xff\xff\xff\xff\xff\xff\xe1\xe1\xe1\xad\xad\xad\xe0\xe0\xe0\xb6\xb6\xb6\xd8\xd8\xd8\xff\xff\xff\xfd\xfd\xfd\xff\xff\xff\xb4\xb4\xb4\xbb\xbb\xbb\xbe\xbe\xbe\xc6\xc6\xc6\xca\xca\xca\xb0\xb0\xb0\xa6\xa6\xa6\xf7\xf7\xf7\xff\xff\xff\xff\xff\xff\xb7\xb7\xb7\xda\xda\xda\xc2\xc2\xc2\xa9\xa9\xa9\xb6\xb6\xb6\xb7\xb7\xb7\xcc\xcc\xcc\xbc\xbc\xbc\xba\xba\xba\x8c\x8c\x8c\x98\x98\x98\xd2\xd2\xd2\x92\x92\x92\xd3\xd3\xd3\xd5\xd5\xd5\xcb\xcb\xcb\xb1\xb1\xb1ccclll\xb2\xb2\xb2\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xff\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xff\xd9\xd9\xd9\x86\x86\x86\xff\xff\xff\xe8\xe8\xe8\x7f\x7f\x7f\xfc\xfc\xfc\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfc\xfc\xfc\xff\xff\xff\xac\xac\xac\x9f\x9f\x9f\xcc\xcc\xcc\xf7\xf7\xf7\xff\xff\xff\xff\xff\xff\xd2\xd2\xd2\xcc\xcc\xcc\xb1\xb1\xb1ccclll\xb2\xb2\xb2\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xfc\xfc\xfc\xfd\xfd\xfd\xfd\xfd\xfd\xfb\xfb\xfb\xfc\xfc\xfc\xff\xff\xff\xfd\xfd\xfd\xfb\xfb\xfb\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfc\xfc\xfc\xfc\xfc\xfc\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xfe\xfe\xfe\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfc\xfc\xfc\xfd\xfd\xfd\xfd\xfd\xfd\xfb\xfb\xfb\xfc\xfc\xfc\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfc\xfc\xfc\xfd\xfd\xfd\xfb\xfb\xfb\xff\xff\xff\xfd\xfd\xfd\xfb\xfb\xfb\xfe\xfe\xfe\xfb\xfb\xfb\xf5\xf5\xf5\xfb\xfb\xfb\xfb\xfb\xfb\xf6\xf6\xf6\xfa\xfa\xfa\xfe\xfe\xfe\xfb\xfb\xfb\xfb\xfb\xfb\xfd\xfd\xfd\xfc\xfc\xfc\xfb\xfb\xfb\xfc\xfc\xfc\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfb\xfb\xfb\xfd\xfd\xfd\xff\xff\xff\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xfd\xfd\xfd\xfc\xfc\xfc\xfb\xfb\xfb\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xf9\xf9\xf9\xfe\xfe\xfe\xfc\xfc\xfc\xfa\xfa\xfa\xff\xff\xff\xd2\xd2\xd2\xcc\xcc\xcc\xb1\xb1\xb1ccclll\xb2\xb2\xb2\xfd\xfd\xfd\xff\xff\xff\xf4\xf4\xf4\xe5\xe5\xe5\xff\xff\xff\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfc\xfc\xfc\xff\xff\xff\xec\xec\xec\xf2\xf2\xf2\xff\xff\xff\xfb\xfb\xfb\xdc\xdc\xdc\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xfd\xfd\xfd\xfd\xfd\xfd\xff\xff\xff\xe7\xe7\xe7\xf1\xf1\xf1\xe5\xe5\xe5\xf7\xf7\xf7\xff\xff\xff\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfd\xfd\xfd\xfd\xfd\xfd\xff\xff\xff\xe0\xe0\xe0\xf1\xf1\xf1\xe4\xe4\xe4\xfc\xfc\xfc\xfd\xfd\xfd\xff\xff\xff\xe4\xe4\xe4\xf0\xf0\xf0\xff\xff\xff\xee\xee\xee\xe8\xe8\xe8\xff\xff\xff\xfd\xfd\xfd\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xfc\xfc\xfc\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfc\xfc\xfc\xff\xff\xff\xee\xee\xee\xe5\xe5\xe5\xff\xff\xff\xf6\xf6\xf6\xe3\xe3\xe3\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfc\xfc\xfc\xfd\xfd\xfd\xff\xff\xff\xeb\xeb\xeb\xea\xea\xea\xff\xff\xff\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xf3\xf3\xf3\xcd\xcd\xcd\xbe\xbe\xbe\xda\xda\xda\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xd2\xd2\xd2\xcc\xcc\xcc\xb1\xb1\xb1ccclll\xb2\xb2\xb2\xf8\xf8\xf8\xff\xff\xff\xe0\xe0\xe0\x7d\x7d\x7d\xff\xff\xff\xfd\xfd\xfd\xfd\xfd\xfd\xfc\xfc\xfc\xfc\xfc\xfc\xff\xff\xff\x9c\x9c\x9c\xb3\xb3\xb3\xff\xff\xff\xf8\xf8\xf8\xd1\xd1\xd1\xff\xff\xff\xfc\xfc\xfc\xfa\xfa\xfa\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xf6\xf6\xf6\xff\xff\xff\x98\x98\x98\xbe\xbe\xbe\x8f\x8f\x8f\xd5\xd5\xd5\xff\xff\xff\xfd\xfd\xfd\xf9\xf9\xf9\xfd\xfd\xfd\xfb\xfb\xfb\xfc\xfc\xfc\xfb\xfb\xfb\xfd\xfd\xfd\xf8\xf8\xf8\xff\xff\xff\xd5\xd5\xd5\xed\xed\xedxxx\xf5\xf5\xf5\xf8\xf8\xf8\xff\xff\xff\x98\x98\x98\xb2\xb2\xb2\xff\xff\xff\xc7\xc7\xc7\x88\x88\x88\xff\xff\xff\xf9\xf9\xf9\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfc\xfc\xfc\xfb\xfb\xfb\xfa\xfa\xfa\xff\xff\xff\xfd\xfd\xfd\xf9\xf9\xf9\xff\xff\xff\xfb\xfb\xfb\xf8\xf8\xf8\xff\xff\xff\xfd\xfd\xfd\xfc\xfc\xfc\xfd\xfd\xfd\xff\xff\xff\xc8\xc8\xc8\x86\x86\x86\xff\xff\xff\xf1\xf1\xf1uuu\xfb\xfb\xfb\xfb\xfb\xfb\xf9\xf9\xf9\xff\xff\xff\xf8\xf8\xf8\xff\xff\xff\xb8\xb8\xb8\x97\x97\x97\xff\xff\xff\xf8\xf8\xf8\xf9\xf9\xf9\xfa\xfa\xfa\xff\xff\xff\xf2\xf2\xf2\xc0\xc0\xc0vvv\xb4\xb4\xb4vvv\xb7\xb7\xb7\xff\xff\xff\xff\xff\xff\xd2\xd2\xd2\xcc\xcc\xcc\xb1\xb1\xb1ccclll\xb2\xb2\xb2\xc7\xc7\xc7\xac\xac\xac\xbf\xbf\xbf\x81\x81\x81\x92\x92\x92\xc8\xc8\xc8\xd3\xd3\xd3\x88\x88\x88\xca\xca\xca\xd7\xd7\xd7\x85\x85\x85\xb1\xb1\xb1\xff\xff\xff\xec\xec\xec\xa7\xa7\xa7\xc8\xc8\xc8\x90\x90\x90\x8f\x8f\x8f\xef\xef\xef\xff\xff\xff\xdb\xdb\xdb\xac\xac\xac\xc9\xc9\xc9\xae\xae\xae\xc1\xc1\xc1\x9e\x9e\x9e\xd2\xd2\xd2\xff\xff\xff\xe0\xe0\xe0\xaf\xaf\xaf\xbf\xbf\xbf\x9c\x9c\x9c\xca\xca\xca\xc9\xc9\xc9\xc3\xc3\xc3\xac\xac\xac\xce\xce\xce\xac\xac\xac\xe3\xe3\xe3\x8c\x8c\x8c\xd5\xd5\xd5\xb1\xb1\xb1\xc3\xc3\xc3\xb0\xb0\xb0qqq\x91\x91\x91\xc9\xc9\xc9\x96\x96\x96\xea\xea\xea\x96\x96\x96\xa9\xa9\xa9\xff\xff\xff\xed\xed\xed\x86\x86\x86\xa7\xa7\xa7\xbd\xbd\xbd\xad\xad\xad\xd2\xd2\xd2\x95\x95\x95\x8d\x8d\x8d\xd0\xd0\xd0\xc4\xc4\xc4\x93\x93\x93\xb5\xb5\xb5\xd8\xd8\xd8\x89\x89\x89\xc6\xc6\xc6\xff\xff\xff\xd9\xd9\xd9nnn\x81\x81\x81\xce\xce\xce\x8e\x8e\x8e\xdf\xdf\xdf\xba\xba\xba\xa7\xa7\xa7\xda\xda\xda\xc5\xc5\xc5\xac\xac\xac\xb3\xb3\xb3\x9a\x9a\x9a\xcf\xcf\xcf\xd4\xd4\xd4\xbe\xbe\xbe\xe1\xe1\xe1\xff\xff\xff\xf8\xf8\xf8\xf5\xf5\xf5\x86\x86\x86\xff\xff\xff\xcf\xcf\xcf\x90\x90\x90\xff\xff\xff\xec\xec\xec\xd0\xd0\xd0\xcb\xcb\xcb\xb0\xb0\xb0bbbkkk\xb1\xb1\xb1\xf9\xf9\xf9\xf8\xf8\xf8\xd5\xd5\xd5\x94\x94\x94\xcb\xcb\xcb\x81\x81\x81\x93\x93\x93\xd7\xd7\xd7\x8f\x8f\x8f\xbe\xbe\xbe\xba\xba\xba\xaf\xaf\xaf\xff\xff\xff\xf0\xf0\xf0\x7b\x7b\x7b\xbc\xbc\xbc\xa7\xa7\xa7\x99\x99\x99\xd5\xd5\xd5\xff\xff\xff\xdc\xdc\xdc\xa6\xa6\xa6\x93\x93\x93\xb1\xb1\xb1\xc1\xc1\xc1\x9e\x9e\x9e\xd3\xd3\xd3\xff\xff\xff\xe1\xe1\xe1\xad\xad\xad\x88\x88\x88\xcc\xcc\xcc\x7c\x7c\x7c\xda\xda\xda\xd6\xd6\xd6\x93\x93\x93\xa9\xa9\xa9\x90\x90\x90\xd2\xd2\xd2\x91\x91\x91\xd7\xd7\xd7\xaf\xaf\xaf\x8d\x8d\x8d\xa5\xa5\xa5\xc4\xc4\xc4\xa8\xa8\xa8\x96\x96\x96\xa2\xa2\xa2\x93\x93\x93\xc3\xc3\xc3\xc2\xc2\xc2\xff\xff\xff\xf2\xf2\xf2\x7e\x7e\x7e\xfa\xfa\xfa\xc4\xc4\xc4\x83\x83\x83\xbb\xbb\xbb\x99\x99\x99\xb2\xb2\xb2\xa7\xa7\xa7\x9f\x9f\x9f\xb7\xb7\xb7\xb3\xb3\xb3\x92\x92\x92\xca\xca\xca\xcc\xcc\xcc\xff\xff\xff\xd1\xd1\xd1\x99\x99\x99\xd2\xd2\xd2\x8a\x8a\x8a\xa3\xa3\xa3\x8f\x8f\x8f\xc4\xc4\xc4\xcb\xcb\xcbTTT\xbf\xbf\xbf\xff\xff\xff\xc8\xc8\xc8===\xd3\xd3\xd3\xf7\xf7\xf7hhh\xbc\xbc\xbc\xff\xff\xff\xff\xff\xff\xdd\xdd\xdd\x9a\x9a\x9a\xff\xff\xff\xb3\xb3\xb3\xdc\xdc\xdc\xdd\xdd\xdd\x9d\x9d\x9d\xdc\xdc\xdc\xca\xca\xca\xb1\xb1\xb1ccclll\xb2\xb2\xb2hhh\xad\xad\xad\xd3\xd3\xd3\x8b\x8b\x8b\xb9\xb9\xb9\x8f\x8f\x8f\x7d\x7d\x7d\xc2\xc2\xc2\xbc\xbc\xbc\x80\x80\x80\x8b\x8b\x8b\xa3\xa3\xa3\xff\xff\xff\xec\xec\xec\x7a\x7a\x7a\xb2\xb2\xb2\xa4\xa4\xa4\x92\x92\x92\xcf\xcf\xcf\xff\xff\xff\xa0\xa0\xa0\x7f\x7f\x7f\x8c\x8c\x8c\x99\x99\x99\xb8\xb8\xb8\x91\x91\x91\xcb\xcb\xcb\xff\xff\xff\xac\xac\xac\x80\x80\x80\x79\x79\x79\xf6\xf6\xf6vvv\xec\xec\xec\x8e\x8e\x8e\x83\x83\x83\x98\x98\x98\x86\x86\x86\xc7\xc7\xc7\x8e\x8e\x8e\x9e\x9e\x9e\x80\x80\x80\x89\x89\x89\xa0\xa0\xa0\xa6\xa6\xa6\xc6\xc6\xc6\xb4\xb4\xb4\x95\x95\x95\x96\x96\x96\x96\x96\x96\xdf\xdf\xdf\xff\xff\xff\xed\xed\xed\x7a\x7a\x7a\xe9\xe9\xe9www\x84\x84\x84\x9f\x9f\x9f\x98\x98\x98\xa8\xa8\xa8\xae\xae\xae\xaa\xaa\xaa\x90\x90\x90\xe1\xe1\xe1vvv\xb2\xb2\xb2\xe6\xe6\xe6\xff\xff\xff\xda\xda\xda\x8a\x8a\x8a\xcb\xcb\xcb\xc1\xc1\xc1\x88\x88\x88\xb6\xb6\xb6\x99\x99\x99\xc8\xc8\xc8\xa6\xa6\xa6ooo\xc8\xc8\xc8\xbd\xbd\xbdxxx\x82\x82\x82\xd8\xd8\xd8\xbf\xbf\xbf\x84\x84\x84\xff\xff\xff\xff\xff\xff\xa7\xa7\xa7\x92\x92\x92\xcc\xcc\xcc\xd2\xd2\xd2\xff\xff\xff\xb8\xb8\xb8\xc6\xc6\xc6\xdf\xdf\xdf\xca\xca\xca\xb1\xb1\xb1ccclll\xb2\xb2\xb2\xcf\xcf\xcf\xd5\xd5\xd5\xf7\xf7\xf7\xe5\xe5\xe5\xe8\xe8\xe8\xee\xee\xee\xe8\xe8\xe8\xcf\xcf\xcf\xff\xff\xff\xde\xde\xde\xd7\xd7\xd7\xf1\xf1\xf1\xff\xff\xff\xf7\xf7\xf7\xe4\xe4\xe4\xe9\xe9\xe9\xea\xea\xea\xe6\xe6\xe6\xf2\xf2\xf2\xff\xff\xff\xf1\xf1\xf1\xde\xde\xde\xe5\xe5\xe5\xe3\xe3\xe3\xec\xec\xec\xe5\xe5\xe5\xf1\xf1\xf1\xff\xff\xff\xf4\xf4\xf4\xde\xde\xde\xe2\xe2\xe2\xf7\xf7\xf7\xf5\xf5\xf5\xfe\xfe\xfe\xea\xea\xea\xdf\xdf\xdf\xe4\xe4\xe4\xe4\xe4\xe4\xed\xed\xed\xe5\xe5\xe5\xee\xee\xee\xde\xde\xde\xe4\xe4\xe4\xf0\xf0\xf0\xdd\xdd\xdd\xf1\xf1\xf1\xf2\xf2\xf2\xe6\xe6\xe6\xf7\xf7\xf7\xcb\xcb\xcb\xf2\xf2\xf2\xff\xff\xff\xf7\xf7\xf7\xe1\xe1\xe1\xfa\xfa\xfa\xe1\xe1\xe1\xe3\xe3\xe3\xe3\xe3\xe3\xe8\xe8\xe8\xee\xee\xee\xd7\xd7\xd7\x8a\x8a\x8a\xa7\xa7\xa7\xb3\xb3\xb3\xf2\xf2\xf2\xcc\xcc\xcc\xfb\xfb\xfb\xfe\xfe\xfe\xfe\xfe\xfe\xe2\xe2\xe2\xe6\xe6\xe6\xf9\xf9\xf9\xe1\xe1\xe1\xfa\xfa\xfa\xe4\xe4\xe4\xe5\xe5\xe5\xff\xff\xff\xda\xda\xda\xdd\xdd\xdd\xf1\xf1\xf1\xeb\xeb\xeb\xe6\xe6\xe6\xe3\xe3\xe3\xea\xea\xea\xf8\xf8\xf8\xfe\xfe\xfe\xff\xff\xff\xe5\xe5\xe5\xd9\xd9\xd9\xf3\xf3\xf3\xfe\xfe\xfe\xff\xff\xff\x94\x94\x94\xe4\xe4\xe4\xd8\xd8\xd8\xca\xca\xca\xb0\xb0\xb0bbbkkk\xb1\xb1\xb1\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfd\xfd\xfd\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xf9\xf9\xf9\xb2\xb2\xb2\xc9\xc9\xc9\xfa\xfa\xfa\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfc\xfc\xfc\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\xfc\xfc\xfc\xe8\xe8\xe8\xfe\xfe\xfe\xd3\xd3\xd3\xcc\xcc\xcc\xb1\xb1\xb1ccclll\xb2\xb2\xb2\xf9\xf9\xf9\xfb\xfb\xfb\xfe\xfe\xfe\xfd\xfd\xfd\xfb\xfb\xfb\xfb\xfb\xfb\xfc\xfc\xfc\xfb\xfb\xfb\xfd\xfd\xfd\xfe\xfe\xfe\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xfc\xfc\xfc\xfb\xfb\xfb\xfb\xfb\xfb\xfd\xfd\xfd\xfc\xfc\xfc\xfb\xfb\xfb\xfc\xfc\xfc\xfb\xfb\xfb\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfc\xfc\xfc\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\xfc\xfc\xfc\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xff\xd1\xd1\xd1\xcb\xcb\xcb\xb0\xb0\xb0bbbkkk\xb1\xb1\xb1\xfc\xfc\xfc\xff\xff\xff\xd4\xd4\xd4\xdd\xdd\xdd\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xc3\xc3\xc3\xf8\xf8\xf8\xff\xff\xff\xff\xff\xff\xe5\xe5\xe5\xce\xce\xce\xff\xff\xff\xfd\xfd\xfd\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfb\xfb\xfb\xfc\xfc\xfc\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfc\xfc\xfc\xff\xff\xff\xd2\xd2\xd2\xcc\xcc\xcc\xb1\xb1\xb1ccclll\xb2\xb2\xb2\xaf\xaf\xaf\xe1\xe1\xe1\xe1\xe1\xe1\xe2\xe2\xe2\xdc\xdc\xdc\xc9\xc9\xc9\xd7\xd7\xd7\xca\xca\xca\xf1\xf1\xf1\xd5\xd5\xd5\xe6\xe6\xe6\xd8\xd8\xd8\xcc\xcc\xcc\xe0\xe0\xe0\xdc\xdc\xdc\xe3\xe3\xe3\xc0\xc0\xc0\xd7\xd7\xd7\xff\xff\xff\xd3\xd3\xd3\xcf\xcf\xcf\xeb\xeb\xeb\xd5\xd5\xd5\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfd\xfd\xfd\xff\xff\xff\xd2\xd2\xd2\xcc\xcc\xcc\xb1\xb1\xb1ccclll\xb2\xb2\xb2\x98\x98\x98\x9a\x9a\x9a\xa3\xa3\xa3\xaf\xaf\xaf\x86\x86\x86\xab\xab\xab\x88\x88\x88\x9d\x9d\x9d\xb1\xb1\xb1\x80\x80\x80\xe2\xe2\xe2\xb7\xb7\xb7\x7c\x7c\x7c\xc7\xc7\xc7\x93\x93\x93\x9f\x9f\x9f\x95\x95\x95\x92\x92\x92\xb8\xb8\xb8\xa0\xa0\xa0\x80\x80\x80\xe5\xe5\xe5\xd4\xd4\xd4\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfd\xfd\xfd\xff\xff\xff\xd2\xd2\xd2\xcc\xcc\xcc\xb1\xb1\xb1ccclll\xb2\xb2\xb2\xc5\xc5\xc5\x99\x99\x99\xa6\xa6\xa6\xb1\xb1\xb1\x8f\x8f\x8f\xc7\xc7\xc7\x96\x96\x96\xb8\xb8\xb8\xaa\xaa\xaa\x82\x82\x82\xe1\xe1\xe1qqq\xe3\xe3\xe3\xc4\xc4\xc4\x96\x96\x96\xa5\xa5\xa5\xba\xba\xba\x90\x90\x90\xd2\xd2\xd2\x93\x93\x93\xd4\xd4\xd4\xfc\xfc\xfc\xf5\xf5\xf5\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfd\xfd\xfd\xff\xff\xff\xd2\xd2\xd2\xcc\xcc\xcc\xb1\xb1\xb1ccclll\xb2\xb2\xb2\xcd\xcd\xcd\xb5\xb5\xb5\xbd\xbd\xbd\xc1\xc1\xc1\xb3\xb3\xb3\xcd\xcd\xcd\xb3\xb3\xb3\xc7\xc7\xc7\xbc\xbc\xbc\xb1\xb1\xb1\xbf\xbf\xbf\xa3\xa3\xa3\xd7\xd7\xd7\xbe\xbe\xbe\xb7\xb7\xb7\xba\xba\xba\xc6\xc6\xc6\xb5\xb5\xb5\xc0\xc0\xc0\x8a\x8a\x8a\x98\x98\x98\xd5\xd5\xd5\xbf\xbf\xbf\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfd\xfd\xfd\xff\xff\xff\xd2\xd2\xd2\xcc\xcc\xcc\xb1\xb1\xb1ccclll\xb2\xb2\xb2\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfc\xfc\xfc\xff\xff\xff\xac\xac\xac\x9e\x9e\x9e\xc7\xc7\xc7\xf3\xf3\xf3\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfc\xfc\xfc\xff\xff\xff\xd1\xd1\xd1\xcb\xcb\xcb\xb0\xb0\xb0bbbkkk\xb1\xb1\xb1\xfd\xfd\xfd\xfc\xfc\xfc\xfd\xfd\xfd\xfd\xfd\xfd\xfc\xfc\xfc\xfd\xfd\xfd\xfc\xfc\xfc\xfd\xfd\xfd\xfd\xfd\xfd\xfc\xfc\xfc\xfd\xfd\xfd\xfc\xfc\xfc\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfc\xfc\xfc\xe6\xe6\xe6\xf7\xf7\xf7\xff\xff\xff\xfc\xfc\xfc\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfc\xfc\xfc\xff\xff\xff\xd1\xd1\xd1\xcb\xcb\xcb\xb0\xb0\xb0bbbkkk\xb1\xb1\xb1\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfc\xfc\xfc\xff\xff\xff\xd1\xd1\xd1\xcb\xcb\xcb\xb0\xb0\xb0bbbkkk\xb1\xb1\xb1\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfc\xfc\xfc\xff\xff\xff\xd1\xd1\xd1\xcb\xcb\xcb\xb0\xb0\xb0bbbkkk\xb1\xb1\xb1\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfd\xfd\xfd\xff\xff\xff\xd2\xd2\xd2\xcc\xcc\xcc\xb1\xb1\xb1ccclll\xb2\xb2\xb2\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfd\xfd\xfd\xff\xff\xff\xd2\xd2\xd2\xcc\xcc\xcc\xb1\xb1\xb1ccclll\xb2\xb2\xb2\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfd\xfd\xfd\xff\xff\xff\xd2\xd2\xd2\xcc\xcc\xcc\xb1\xb1\xb1ccclll\xb2\xb2\xb2\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfd\xfd\xfd\xff\xff\xff\xd2\xd2\xd2\xcc\xcc\xcc\xb1\xb1\xb1ccclll\xb2\xb2\xb2\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfd\xfd\xfd\xff\xff\xff\xd2\xd2\xd2\xcc\xcc\xcc\xb1\xb1\xb1ccclll\xb2\xb2\xb2\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfd\xfd\xfd\xff\xff\xff\xd2\xd2\xd2\xcc\xcc\xcc\xb1\xb1\xb1ccclll\xb2\xb2\xb2\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfc\xfc\xfc\xff\xff\xff\xd1\xd1\xd1\xcb\xcb\xcb\xb0\xb0\xb0bbbkkk\xb1\xb1\xb1\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfd\xfd\xfd\xff\xff\xff\xd2\xd2\xd2\xcc\xcc\xcc\xb1\xb1\xb1ccclll\xb2\xb2\xb2\xfe\xfe\xfe\xfd\xfd\xfd\xfc\xfc\xfc\xfc\xfc\xfc\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfc\xfc\xfc\xff\xff\xff\xd1\xd1\xd1\xcb\xcb\xcb\xb0\xb0\xb0ccclll\xb1\xb1\xb1\xfa\xfa\xfa\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfc\xfc\xfc\xfb\xfb\xfb\xfd\xfd\xfd\xfc\xfc\xfc\xfc\xfc\xfc\xfd\xfd\xfd\xfc\xfc\xfc\xfa\xfa\xfa\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfc\xfc\xfc\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfc\xfc\xfc\xff\xff\xff\xd1\xd1\xd1\xcb\xcb\xcb\xb2\xb2\xb2___hhh\xb2\xb2\xb2\xfb\xfb\xfb\xe8\xe8\xe8\xc9\xc9\xc9\xd7\xd7\xd7\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xff\xd2\xd2\xd2\xcb\xcb\xcb\xa1\xa1\xa1nnnwww\xa3\xa3\xa3\xff\xff\xff\x9f\x9f\x9f\x94\x94\x94\x82\x82\x82\xf9\xf9\xf9\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfb\xfb\xfb\xff\xff\xff\xb0\xb0\xb0\x89\x89\x89\xc3\xc3\xc3\xb4\xb4\xb4\xb9\xb9\xb9\xb2\xb2\xb2\x99\x99\x99ttt\xde\xde\xde\xff\xff\xff\xfc\xfc\xfc\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xff\xec\xec\xec\xd1\xd1\xd1\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xff\xf1\xf1\xf1\xf0\xf0\xf0\xff\xff\xff\xff\xff\xff\xd2\xd2\xd2\xc7\xc7\xc7\x9c\x9c\x9c\x9f\x9f\x9f\xae\xae\xae\x9c\x9c\x9c\xff\xff\xff\xa7\xa7\xa7\xbc\xbc\xbc\x8c\x8c\x8c\xf3\xf3\xf3\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xff\xd0\xd0\xd0\x1c\x1c\x1c\xd6\xd6\xd6\xfe\xfe\xfe\xf3\xf3\xf3\xf4\xf4\xf4\xec\xec\xec\xa8\xa8\xa8\xa9\xa9\xa9\xff\xff\xff\xf2\xf2\xf2\xf5\xf5\xf5\xff\xff\xff\xfc\xfc\xfc\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xda\xda\xda\xc4\xc4\xc4\xf6\xf6\xf6\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfb\xfb\xfb\xf8\xf8\xf8\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfd\xfd\xfd\xf6\xf6\xf6\xef\xef\xef\xfa\xfa\xfa\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xf1\xf1\xf1\xf8\xf8\xf8\xf3\xf3\xf3\xc3\xc3\xc3\xa3\xa3\xa3\xef\xef\xef\xff\xff\xff\xd2\xd2\xd2\xc9\xc9\xc9\x9f\x9f\x9f\x9b\x9b\x9b\xaa\xaa\xaa\x9d\x9d\x9d\xe3\xe3\xe3\xb3\xb3\xb3\xc2\xc2\xc2\xa3\xa3\xa3\xf0\xf0\xf0\xff\xff\xff\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfa\xfa\xfa\xff\xff\xff\x9c\x9c\x9c777\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xf1\xf1\xf1\xfd\xfd\xfd\xbc\xbc\xbc\xf1\xf1\xf1\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfc\xfc\xfc\xff\xff\xff\xd8\xd8\xd8\x7f\x7f\x7f\xd3\xd3\xd3\xa1\xa1\xa1\xf6\xf6\xf6\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfa\xfa\xfa\xf6\xf6\xf6\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xe5\xe5\xe5\x95\x95\x95\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\x7e\x7e\x7e\xc0\xc0\xc0\xa6\xa6\xa6\xe8\xe8\xe8\xff\xff\xff\xfd\xfd\xfd\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xff\xe8\xe8\xe8\xc2\xc2\xc2\xff\xff\xff\xf3\xf3\xf3\xb3\xb3\xb3\xf4\xf4\xf4\xff\xff\xff\xd1\xd1\xd1\xc7\xc7\xc7\x9e\x9e\x9e\x9b\x9b\x9b\xaa\xaa\xaa\x9d\x9d\x9d\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xfb\xfb\xfb\xff\xff\xffeeejjj\xff\xff\xff\xfc\xfc\xfc\xfd\xfd\xfd\xfa\xfa\xfa\xff\xff\xff\xdd\xdd\xdd\xb0\xb0\xb0\xff\xff\xff\xe9\xe9\xe9\xd5\xd5\xd5\xef\xef\xef\xff\xff\xff\xfa\xfa\xfa\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfd\xfd\xfd\xfa\xfa\xfa\xfc\xfc\xfc\xfc\xfc\xfc\xff\xff\xff\xbe\xbe\xbe\x9b\x9b\x9b\xff\xff\xff\x96\x96\x96\xbb\xbb\xbb\xff\xff\xff\xfc\xfc\xfc\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xeb\xeb\xeb\xcc\xcc\xcc\xff\xff\xff\xfb\xfb\xfb\xff\xff\xff\xd3\xd3\xd3\xab\xab\xab\xff\xff\xff\xf8\xf8\xf8\xfc\xfc\xfc\xff\xff\xff\xfe\xfe\xfe\xff\xff\xff\xfc\xfc\xfc\xfa\xfa\xfa\xfd\xfd\xfd\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xf2\xf2\xf2\x7d\x7d\x7d\xff\xff\xff\x89\x89\x89\xd9\xd9\xd9\xff\xff\xff\xfd\xfd\xfd\xff\xff\xff\xfe\xfe\xfe\xfd\xfd\xfd\xff\xff\xff\xb1\xb1\xb1\xef\xef\xef\xa3\xa3\xa3\xa1\xa1\xa1\xfc\xfc\xfc\xff\xff\xff\xd2\xd2\xd2\xc8\xc8\xc8\x9f\x9f\x9f\x9c\x9c\x9c\xab\xab\xab\x9d\x9d\x9d""" +app = MyApp() +app.MainLoop() + diff --git a/wx/pdf2swf.py b/wx/pdf2swf.py deleted file mode 100755 index 7e3f4bd..0000000 --- a/wx/pdf2swf.py +++ /dev/null @@ -1,1088 +0,0 @@ -#!/usr/bin/env python -# -*- coding: ISO-8859-15 -*- -# -# pdf2swf.py -# graphical user interface for pdf2swf -# -# Part of the swftools package. -# -# Copyright (c) 2008,2009 Matthias Kramm -# -# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - - -import sys -import wx -import os -sys.path+=["../lib/python"] -import gfx -import images -import stat - -basedir = os.getcwd() - -gfx.verbose(3) - -#try: -# gfx.setparameter("wxwindowparams", "1") -#except: -# gfx.setoption("wxwindowparams", "1") - -class StaticData: - def __init__(self): - self.simpleviewer_bitmap = wx.BitmapFromImage(wx.ImageFromData(images.simpleviewer_width,images.simpleviewer_height,images.simpleviewer_data)) - self.raw_bitmap = wx.BitmapFromImage(wx.ImageFromData(images.raw_width,images.raw_height,images.raw_data)) - self.motionpaper_bitmap = wx.BitmapFromImage(wx.ImageFromData(images.motionpaper_width,images.motionpaper_height,images.motionpaper_data)) - self.rfxview_bitmap = wx.BitmapFromImage(wx.ImageFromData(images.rfxview_width,images.rfxview_height,images.rfxview_data)) -staticdata = None - -HTMLTEMPLATE = """ - - - - - - - - - - - - -""" - -def error(msg): - dlg = wx.MessageDialog(None, msg, "Error", style=wx.OK, pos=wx.DefaultPosition) - dlg.ShowModal() - dlg.Destroy() - -def savefilestatus(msg): - dlg = wx.MessageDialog(None, msg, "Save file status", style=wx.OK, pos=wx.DefaultPosition) - dlg.ShowModal() - dlg.Destroy() - -def swfcombine(params): - exe = "swfcombine" - if os.path.sep == '/': - locations = [os.path.join(basedir, "swfcombine"), - "/usr/local/bin/swfcombine", - "/usr/bin/swfcombine" - ] - else: - locations = [os.path.join(basedir, "swfcombine.exe"), - "c:\\swftools\\swfcombine.exe"] - params = ['"'+p+'"' for p in params] - - for e in locations: - if os.path.isfile(e): - exe = e - break - - if hasattr(os,"spawnv"): - print "spawnv",exe,params - ret = -1 - try: - ret = os.spawnv(os.P_WAIT, exe, ["swfcombine"]+params) - except: - ret = -1 - if not ret: - return - - cmd = '"' + exe + '"' + " " + (" ".join(params)) - print "system",cmd - ret = os.system(cmd) - if ret&0xff00: - error("Couldn't execute swfcombine.exe- error code "+str(ret)) - -ICON_SIZE = 64 - -EVENT_PAGE_CHANGE = 1 -EVENT_FILE_CHANGE = 2 -EVENT_STATUS_TEXT = 4 - -class ProgressFrame(wx.Dialog): - def __init__(self, parent, message=""): - wx.Dialog.__init__(self, parent, -1, "Progress", size=(350, 150)) - panel = wx.Panel(self, -1) - self.count = 0 - - self.msg = wx.StaticText(panel, -1, message, (20,25)) - self.gauge = wx.Gauge(panel, -1, 100, (20, 50), (250, 25)) - - self.gauge.SetBezelFace(3) - self.gauge.SetShadowWidth(3) - - self.Bind(wx.EVT_WINDOW_DESTROY, self.close, id=wx.ID_CLOSE) - - def setProgress(self, num): - self.gauge.SetValue(int(num)) - - def close(self, event): - print "close" - - -def swapextension(filename,newext): - basename,ext = os.path.splitext(filename) - return basename + "." + newext - -def has_different_size_pages(doc): - width,height = 0,0 - for i in range(1,doc.pages+1): - page = doc.getPage(i) - if i==1: - width,height = page.width,page.height - else: - if abs(width-page.width)>2 or \ - abs(height-page.height)>2: - return 1 - return 0 - - -options = [] -gfx_options = {} - -class Option: - def __init__(self, parameter, text, options, default, mapping=None): - self.parameter = parameter - self.text = text - self.options = options - self.default = default - self.mapping = mapping - self.control = None - self.enabled = 1 - self.register() - - def generateControl(self, panel): - if type(self.options) == type((0,)): - control = wx.Choice(panel, -1, choices=self.options) - control.SetSelection(self.default) - elif self.options == "slider": - control = wx.Slider(panel, -1, self.default, 0, 100, size=(100, -1), style=wx.SL_HORIZONTAL|wx.SL_LABELS|wx.SL_TOP) - elif self.options == "spinner": - control = wx.SpinCtrl(panel, -1, str(self.default)) - else: - control = wx.Choice(panel, -1, choices=["broken"]) - control.SetSelection(0) - - self.control = control - return self.control - - def getSettings(self): - value = "" - if type(self.options) == type((0,)): - value = self.options[self.control.GetCurrentSelection()] - if self.mapping and value in self.mapping: - value = str(self.mapping[value]) - if value == "yes": - value = "1" - elif value == "no": - value = "0" - return {self.parameter:value} - elif self.options == "slider" or self.options == "spinner": - value = str(self.control.GetValue()) - return {self.parameter:value} - - def register(self): - global options - options += [self] - -class Option2(Option): - - def __init__(self, parameter, text, options, default, mapping=None): - Option.__init__(self, parameter, text, options, default, mapping) - self.enabled = 0 - - def generateControl(self, panel): - p = wx.Panel(panel, -1) - #p.SetOwnBackgroundColour('#ff0000') - h = wx.BoxSizer(wx.HORIZONTAL) - control = wx.Choice(p, -1, choices=self.options) - control.SetSelection(self.default) - text = wx.StaticText(p, -1, self.text) - h.Add(text,1,wx.EXPAND|wx.ALIGN_LEFT|wx.TOP, 5) - h.Add(control,1,wx.EXPAND|wx.ALIGN_RIGHT|wx.ALIGN_TOP) - self.control = control - if self.enabled: - control.Enable() - else: - control.Disable() - p.SetSizer(h) - p.Fit() - return p - - def Disable(self): - self.enabled=0 - if self.control: - self.control.Disable() - - def Enable(self): - self.enabled=1 - if self.control: - self.control.Enable() - - def getSettings(self): - if not self.enabled: - return {} - return Option.getSettings(self) - -class ChooseAndText(Option): - def __init__(self, parameter, text, options, default, editselection, textvalue=""): - Option.__init__(self, parameter, text, options, default) - self.editselection = editselection - self.selection = default - self.textvalue = textvalue - self.enabled = 0 - self.choice = None - - def generateControl(self, panel): - p = wx.Panel(panel, -1) - h = wx.BoxSizer(wx.HORIZONTAL) - control = wx.Choice(p, -1, choices=self.options) - p.Bind(wx.EVT_CHOICE, self.OnChoice, control) - control.SetSelection(self.default) - text = wx.StaticText(p, -1, self.text) - if self.selection == self.editselection: - edittext = wx.TextCtrl(p, -1, self.textvalue) - self.textvalue = "" - else: - edittext = wx.TextCtrl(p, -1, "") - edittext.Disable() - p.Bind(wx.EVT_TEXT, self.OnText, edittext) - h.Add(text,1,wx.EXPAND|wx.ALIGN_LEFT|wx.TOP, 5) - h.Add(control,1,wx.EXPAND|wx.ALIGN_RIGHT) - h.Add(edittext,1,wx.EXPAND|wx.ALIGN_RIGHT) - self.choice = control - self.edittext = edittext - if self.enabled: - control.Enable() - else: - control.Disable() - p.SetSizer(h) - p.Fit() - return p - - def OnText(self, event): - text = self.edittext.GetValue() - text2 = "".join(c for c in text if c.isdigit()) - if text2!=text: - self.edittext.SetValue(text2) - - def OnChoice(self, event): - self.selection = self.choice.GetCurrentSelection() - if self.selection != self.editselection: - if not self.textvalue and self.edittext.GetValue(): - self.textvalue = self.edittext.GetValue() - self.edittext.SetValue("") - self.edittext.Disable() - else: - if self.textvalue and not self.edittext.GetValue(): - self.edittext.SetValue(self.textvalue) - self.textvalue = "" - self.edittext.Enable() - - def Disable(self): - self.enabled=0 - if not self.choice: - return - self.choice.Disable() - self.edittext.Disable() - - def Enable(self): - self.enabled=1 - if not self.choice: - return - self.choice.Enable() - if self.choice.GetCurrentSelection() == self.editselection: - if self.textvalue and not self.edittext.GetValue(): - self.edittext.SetValue(self.textvalue) - self.textvalue = "" - self.edittext.Enable() - else: - self.edittext.Disable() - - def getSettings(self): - if not self.enabled: - return {} - if self.choice.GetCurrentSelection() != self.editselection: - value = self.options[self.choice.GetCurrentSelection()] - else: - value = self.edittext.GetValue().strip() - return {self.parameter:value} - -class TextOption: - def __init__(self, parameter, label, default=""): - self.parameter = parameter - self.label = label - self.default = default - self.register() - - def generateControl(self, panel): - v = wx.BoxSizer(wx.VERTICAL) - self.control = wx.TextCtrl(panel, -1, self.default, size=(250, -1)) - self.control.Fit() - return self.control - - def getSettings(self): - settings = {} - for items in self.control.GetValue().split(" "): - if "=" in items: - l = items.split("=") - if len(l) == 2: - settings[l[0]] = l[1] - return settings - - def register(self): - global options - options += [self] - -class RadioOption(Option): - def __init__(self, text, options): - self.text = text - self.options = options - self.selected = "==nothing==" - self.radios = [] - self.register() - - def generateControl(self, panel): - control = wx.Panel(panel, -1) - vsplit = wx.BoxSizer(wx.VERTICAL) - for i in range(len(self.options)/2): - text = self.options[i*2] - if i == 0: - c = wx.RadioButton(control, -1, text, style=wx.RB_GROUP) - else: - c = wx.RadioButton(control, -1, text) - control.Bind(wx.EVT_RADIOBUTTON, self.OnRadio, c) - self.radios += [c] - vsplit.Add(c) - control.SetSizer(vsplit) - control.Fit() - self.control = control - return control - - def OnRadio(self, event): - self.selected = event.GetEventObject().GetLabel() - - def getSettings(self): - for i in range(len(self.options)/2): - if self.options[i*2] == self.selected: - return self.options[i*2+1] - return self.options[1] - -class BitmapWindow(wx.Window): - def __init__(self, parent, image): - wx.Window.__init__(self, parent, -1) - self.image = image - self.SetMinSize((image.GetWidth()+2, image.GetHeight()+2)) - self.SetMaxSize((image.GetWidth()+2, image.GetHeight()+2)) - self.SetSize((image.GetWidth()+2, image.GetHeight()+2)) - self.Bind(wx.EVT_PAINT, self.OnPaint) - self.Update() - def OnPaint(self, event): - dc = wx.PaintDC(self) - self.Draw(dc) - def Draw(self,dc=None): - if not dc: - dc = wx.ClientDC(self) - dc.DrawRectangleRect((0, 0, self.image.GetWidth()+2, self.image.GetHeight()+2)) - dc.DrawBitmap(self.image, 1, 1, False) - -class ImageRadioOption(Option): - def __init__(self, text, options): - self.text = text - self.options = options - self.selected = "==nothing==" - self.radios = [] - self.register() - self.ids = [] - - def generateControl(self, panel): - control = wx.Panel(panel, -1) - vsplit = wx.BoxSizer(wx.VERTICAL) - first = 1 - for image,text,params,selected,extraoptions in self.options: - hsplit = wx.BoxSizer(wx.HORIZONTAL) - - v = wx.BoxSizer(wx.VERTICAL) - - name,text = text.split("- ") - - c = wx.CheckBox(control, -1, name) - control.Bind(wx.EVT_CHECKBOX, self.OnRadio, c) - - # radio buttons crash windows when clicked on- even without event bindings. - # This is caused by the subpanel which is created for extra options - # (I tried this with a empty Panel(), and even that crashed) - #if first: - # c = wx.RadioButton(control, -1, name, style=wx.RB_GROUP) - #else: - # c = wx.RadioButton(control, -1, name) - #control.Bind(wx.EVT_RADIOBUTTON, self.OnRadio, c) - - self.ids += [c.GetId()] - - first = 0 - - if "disable" in text: - c.Enable(False) - if selected: - self.selected = c.GetId() - c.SetValue(True) - else: - c.SetValue(False) - self.radios += [c] - - bitmap = BitmapWindow(control, image) - t = wx.StaticText(control, -1, text, size=(400,50)) - - v.Add(c, 0, wx.EXPAND) - v.Add(t, 0, wx.EXPAND|wx.LEFT, 20) - - for o in extraoptions: - cx = o.generateControl(control) - if selected: - o.Enable() - else: - o.Disable() - v.Add(cx, 0, wx.EXPAND|wx.LEFT, 20) - - v.SetMinSize((330,170)) - - hsplit.Add(bitmap, 0, wx.LEFT|wx.RIGHT|wx.BOTTOM|wx.ALIGN_TOP, 5) - hsplit.Add(v, 0, wx.EXPAND) - vsplit.Add(hsplit, 0, wx.EXPAND) - - control.SetSizer(vsplit) - control.Fit() - self.control = control - return vsplit - - def OnRadio(self, event): - self.selected = event.GetEventObject().GetId() - for c in self.radios: - if c.GetId() == self.selected: - c.SetValue(1) - else: - c.SetValue(0) - i = 0 - for image,text,params,selected,extraoptions in self.options: - if self.ids[i] == self.selected: - for xo in extraoptions: - xo.Enable() - pass - else: - for xo in extraoptions: - xo.Disable() - pass - i = i + 1 - event.ResumePropagation(0) - - def getSettings(self): - i = 0 - for image,text,params,s,extraoptions in self.options: - id = self.ids[i] - i = i + 1 - if id == self.selected: - return params - return {} - - -class OptionFrame(wx.Dialog): - - def __init__(self, parent): - wx.Dialog.__init__(self, parent, -1, "Options") - - #self.nb = wx.Notebook(self, -1)#, wx.Point(0,0), wx.Size(0,0), wxNB_FIXEDWIDTH) - self.nb = wx.Notebook(self, -1) - - self.needreload = 0 - - options0 = [RadioOption('Rendering mode', - ["Convert polygons to polygons and fonts to fonts", {}, - "Convert fonts to fonts, everything else to bitmaps", {"poly2bitmap":"1"}, - "Convert everthing to bitmaps", {"poly2bitmap":"1", "bitmapfonts":"1"} - ])] - - mp_options = [] - sv_options = [Option2('flashversion', 'Flash version:', ('4','5','6','7','8'), 2), - Option2('transparent', 'Make SWF file transparent:', ('no','yes'), 0), - ] - - raw_options = [Option2('flashversion', 'Flash version:', ('4','5','6','7','8','9'), 2), - Option2('insertstop', 'Insert stop after each frame:', ('no','yes'), 0), - Option2('transparent', 'Make SWF file transparent:', ('no','yes'), 0), - ] - rfxview_options = [ChooseAndText('rfxwidth', 'Width:', ('same as PDF','fullscreen','custom'),1,2,"600"), - ChooseAndText('rfxheight', 'Height:', ('same as PDF','fullscreen','custom'),1,2,"800"), - Option2('rfxzoomtype', 'Initial zoom level:', ('Original resolution','Show all','Maximum width/height'),2), - ] - - options4 = [ImageRadioOption('Select Paging GUI', - [(staticdata.raw_bitmap, "No Viewer- The SWF will be in \"raw\" format, with each page a seperate frame. Use this if you want to add a viewer yourself afterwards.", {}, 0, raw_options), - (staticdata.simpleviewer_bitmap, "SimpleViewer- A tiny viewer, which attaches directly to the SWF, and provides small previous/next buttons in the upper left corner", {"simpleviewer":"1", "insertstop":"1"}, 0, sv_options), - (staticdata.rfxview_bitmap, "rfxView- A more sophisticated viewer with zooming and scrolling.", {"rfxview":"1", "flashversion":"8"}, 1, rfxview_options), - #(staticdata.motionpaper_bitmap, "MotionPaper- A highly sophisticated viewer with page flipping. (disabled in this evaluation version)", {}, 0, mp_options), - #(staticdata.motionpaper_bitmap, "Your advertisement here- Are you are company who developed a viewer for pdf2swf, or who offers commercial PDF hosting service? Place your advertisement or demo viewer here, or allow pdf2swf to upload SWFs directly to your site! contact sales@swftools.org for details.", {}, 0, mp_options), - ])] - - options1 = [Option('zoom', 'Resolution (in dpi):', "spinner", 72), - Option('fontquality', 'Font quality:', "slider", 20), - Option('storeallcharacters', 'Insert full fonts in SWF file:', ('no','yes'), 0), - Option('splinequality', 'Polygon quality:', "slider", 100), - Option('jpegquality', 'JPEG quality:', "slider", 75), - Option('jpegsubpixels', 'JPEG image resolution:', ('same as in PDF', '1x', '2x', '4x'), 0, {"same as in PDF": 0, "1x": 1, "2x": 2, "3x": 3}), - Option('ppmsubpixels', 'non-JPEG image resolution:', ('same as in PDF', '1x', '2x', '4x'), 0, {"same as in PDF": 0, "1x": 1, "2x": 2, "3x": 3}), - ] - - - options3 = [TextOption('_additional_', 'Additional options')] - - panel1 = [('Rendering options', options0,''), - ('Quality',options1,'v')] - panel3 = [('Select paging GUI', options4,'')] - panel4 = [('Additional options', options3,'')] - - panels = [('Quality', panel1), - ('Viewer', panel3), - ('Advanced', panel4)] - - for name,poptions in panels: - panel = wx.Panel(self.nb, -1) - self.nb.AddPage(panel, name) - - vsplit = wx.BoxSizer(wx.VERTICAL) - - for name,options,align in poptions: - optiongroup = wx.StaticBox(panel, -1, name) - optiongroupsizer= wx.StaticBoxSizer(optiongroup, wx.VERTICAL) - optiongroup.SetSizer(optiongroupsizer) - - if align == 'v': - grid = wx.GridSizer(rows=len(options), cols=2, hgap=3, vgap=3) - optiongroupsizer.Add(grid, 1, wx.EXPAND, 0) - else: - grid = wx.GridSizer(rows=len(options), cols=1, hgap=3, vgap=3) - optiongroupsizer.Add(grid, 1, wx.EXPAND, 0) - - for option in options: - if align=='v': - t = wx.StaticText(panel, -1, option.text) - grid.Add(t, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) - optionbox = option.generateControl(panel) - grid.Add(optionbox, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) - - vsplit.Add(optiongroupsizer, 0, wx.EXPAND, 0) - - #hs = wx.BoxSizer(wx.HORIZONTAL) - #hs.Add(gobutton, 0, wx.ALIGN_CENTER, 0) - gobutton = wx.Button(panel, -1, "Apply") - self.Bind(wx.EVT_BUTTON, self.Apply, gobutton) - - vsplit.Add(gobutton, 0, wx.ALIGN_CENTER|wx.ALL, 0) - - panel.SetSizer(vsplit) - panel.Fit() - - self.nb.Fit() - - self.Fit() - - - def updateOptions(self): - global options,gfx_options - a = [] - - # FIXME: we clear *our* options- but gfx will still have - # stored the old ones. Critical for options in the "imageradio" section. - gfx_options.clear() - i = 0 - print "----- options ------" - for option in options: - for k,v in option.getSettings().items(): - gfx_options[k] = v - gfx.setparameter(k,v) - print k,v - i = i + 1 - - # TODO: filter out "global" options, and do this only if - # pdf layer is affected - - def Apply(self, event): - self.updateOptions() - self.Hide() - self.needreload = 1 - - -class State: - def __init__(self): - self.pdf = None - self.page = None - self.pagenr = 1 - self.pagebitmap = None - self.bitmap_width = 0 - self.bitmap_height = 0 - self.bitmap_page = 0 - self.filename = None - self.status_text = None - self.lastsavefile = "output.swf" - self.lasthtmlfile = "index.html" - - self.listeners = [] - - def onEvent(self,event_type, function): - self.listeners += [(event_type,function)] - def loadPDF(self,filename): - self.filename = filename - self.lastsavefile = swapextension(filename,"swf") - self.lasthtmlfile = swapextension(filename,"html") - - self.pdf = gfx.open("pdf",filename) - if(has_different_size_pages(self.pdf)): - # just let the user know- for now, we can't handle this properly - dlg = wx.MessageDialog(app.frame, """In this PDF, width or height are not the same for each page. This might cause problems if you export pages of different dimensions into the same SWF file.""", "Notice", style=wx.OK, pos=wx.DefaultPosition) - dlg.ShowModal() - dlg.Destroy() - - self.changePage(1) - - for type,f in self.listeners: - if type&EVENT_PAGE_CHANGE or type&EVENT_FILE_CHANGE: - f() - self.setStatus("File loaded successfully.") - - def saveSWF(self, filename, progress, pages=None, html=0): - if html: - basename,ext = os.path.splitext(filename) - if not ext: - html = basename + ".html" - filename = basename + ".swf" - elif ext.lower() != ".swf": - html = filename - filename = basename + ".swf" - else: - html = basename + ".html" - filename = filename - - steps = 100.0 / (self.pdf.pages*2 + 3) - pos = [0] - - self.lastsavefile = filename - if html: - self.lasthtmlfile = html - - swf = gfx.SWF() - for k,v in gfx_options.items(): - swf.setparameter(k,v) - if pages is None: - pages = range(1,self.pdf.pages+1) - pdfwidth,pdfheight=0,0 - for pagenr in pages: - page = self.pdf.getPage(pagenr) - pdfwidth = page.width - pdfheight = page.height - swf.startpage(page.width, page.height) - page.render(swf) - swf.endpage() - swf.save(filename) - if not os.path.isfile(filename): - error("Couldn't create file "+filename) - - if gfx_options.get("rfxview",None): - rfxview = os.path.join(basedir, "rfxview.swf") - if not os.path.isfile(rfxview): - error("File rfxview.swf not found in working directory") - else: - size1 = os.stat(filename)[stat.ST_SIZE] - swfcombine([rfxview,"viewport="+filename,"-o",filename]) - size2 = os.stat(filename)[stat.ST_SIZE] - if size1 == size2: - error("Couldn't add viewer to file "+filename) - - if html: - version = int(gfx_options.get("flashversion", "8")) - swf = gfx.open("swf", filename) - page1 = swf.getPage(1) - - width,height = str(page1.width),str(page1.height) - - - w = gfx_options.get("rfxwidth","") - if w == "fullscreen": width = "100%" - elif w == "same as PDF": width = pdfwidth+40 - elif w.isdigit(): width = w - else: width = pdfwidth - - h = gfx_options.get("rfxheight","") - if h == "fullscreen": height = "100%" - elif h == "same as PDF": height = pdfheight+70 - elif h.isdigit(): height = h - else: height = pdfwidth - - flashvars = "" - zoomtype = gfx_options.get("rfxzoomtype","") - if zoomtype=="Original resolution": - flashvars = "zoomtype=1" - elif zoomtype=="Show all": - flashvars = "zoomtype=2" - elif zoomtype=="Maximum width/height": - flashvars = "zoomtype=3" - - swffilename = os.path.basename(filename) - fi = open(html, "wb") - fi.write(HTMLTEMPLATE % locals()) - fi.close() - - - def changePage(self,page): - self.pagenr = page - self.page = self.pdf.getPage(self.pagenr) - for type,f in self.listeners: - if type&EVENT_PAGE_CHANGE: - f() - - def getPageIcon(self,pagenr): - page = self.pdf.getPage(pagenr) - return wx.BitmapFromImage(wx.ImageFromData(ICON_SIZE,ICON_SIZE,page.asImage(ICON_SIZE,ICON_SIZE))) - #return wx.BitmapFromImage(wx.ImageFromData(8,8,"0"*(64*3))) - - def getPageImage(self, width, height): - if self.bitmap_width == width and self.bitmap_height == height and self.bitmap_page == self.pagenr: - return self.pagebitmap - else: - self.bitmap_width = width - self.bitmap_height = height - self.bitmap_page = self.pagenr - self.pagebitmap = wx.BitmapFromImage(wx.ImageFromData(width,height,self.page.asImage(width,height))) - #self.pagebitmap = wx.BitmapFromImage(wx.ImageFromData(8,8,"0"*(64*3))) - return self.pagebitmap - - def setStatus(self,text): - self.status_text = text - for type,f in self.listeners: - if type&EVENT_STATUS_TEXT: - f() - -state = State() - -class PageListWidget(wx.ListCtrl): - def __init__(self,parent): - wx.ListCtrl.__init__(self,parent,style=wx.LC_ICON|wx.LC_AUTOARRANGE) - #self.SetMinSize((ICON_SIZE+8,-1)) - #self.SetMaxSize((ICON_SIZE+8,-1)) - #self.SetSize((ICON_SIZE+8,-1)) - self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.SelectItem) - state.onEvent(EVENT_FILE_CHANGE, self.reload) - state.onEvent(EVENT_PAGE_CHANGE, self.switchPage) - self.reload() - self.dontcare = 0 - #self.Bind(wx.EVT_IDLE, self.OnIdle) - #print dir(self) - - def processFiles(self): - if self.filepos >= 0 and self.filepos < state.pdf.pages: - icon = state.getPageIcon(self.filepos+1) - self.imglist.Add(icon) - self.InsertImageStringItem(self.filepos, str(self.filepos+1), self.filepos) - self.filepos = self.filepos + 1 - self.Update() - - def OnIdle(self,event): - self.processFiles() - event.ResumePropagation(0) - - def reload(self): - self.filepos = -1 - self.DeleteAllItems() - self.imglist = wx.ImageList(ICON_SIZE,ICON_SIZE,mask=False) - self.AssignImageList(self.imglist,wx.IMAGE_LIST_NORMAL) - self.filepos = 0 - while state.pdf and self.filepos < state.pdf.pages: - self.processFiles() - - def switchPage(self): - if self.dontcare: - self.dontcare = 0 - return - for i in range(0,self.GetItemCount()): - self.Select(i, False) - self.Select(state.pagenr-1, True) - self.Focus(state.pagenr-1) - self.Update() - - def SelectItem(self,event): - self.dontcare = 1 #ignore next change event - state.changePage(event.GetIndex()+1) - - -helptxt = """ -This is the SWF preview window. -Here, you will see how the SWF file generated from -the PDF file will look like. Changing parameters in -the configuration which affect the appeareance of -the final SWF will affect this preview, too, so you -can always evaluate the final output beforehand. -""" - - -class OnePageWidget(wx.Window): - def __init__(self,parent): - wx.Window.__init__(self, parent) - self.SetSize((160,100)) - self.SetMinSize((160,100)) - self.Fit() - self.Bind(wx.EVT_PAINT, self.OnPaint) - self.Bind(wx.EVT_SIZE, self.OnSize) - self.Bind(wx.EVT_KEY_DOWN, self.key_down) - state.onEvent(EVENT_PAGE_CHANGE, self.OnPageChange) - - def key_down(self, event): - if state.pdf: - if event.GetKeyCode() == 312 and state.pagenr>1: - state.changePage(state.pagenr-1) - elif event.GetKeyCode() == 313 and state.pagenr state.page.height * window_width: - width = window_width - height = window_width * state.page.height / state.page.width - posy = (window_height - height) / 2 - else: - width = window_height * state.page.width / state.page.height - height = window_height - posx = (window_width - width) / 2 - - dc.DrawBitmap(state.getPageImage(width,height), posx,posy, False) - #state.getPageImage( - - def OnPaint(self, event): - dc = wx.PaintDC(self) - self.Draw(dc) - -class Pdf2swfFrame(wx.Frame): - #def __init__(self): - #wx.Window.__init__(self, None, id=-1, pos=wx.DefaultPosition, size=wx.DefaultSize) - def __init__(self,application): - wx.Frame.__init__(self, None, -1, style = wx.DEFAULT_FRAME_STYLE) - self.application = application - - self.SetTitle("pdf2swf") - self.createMenu() - self.createToolbar() - self.createStatusBar() - self.createMainFrame() - - self.SetSize((800,600)) - - self.options = OptionFrame(None) - self.options.Show(False) - self.options.updateOptions() - - state.onEvent(EVENT_STATUS_TEXT, self.status_change) - self.html = 0 - - #self.table = wx.AcceleratorTable([(wx.ACCEL_ALT, ord('X'), 333),]) - #self.SetAcceleratorTable(self.table) - - self.Bind(wx.EVT_IDLE, self.OnIdle) - self.Bind(wx.EVT_CLOSE, self.menu_exit) - return - - def menu_open(self,event): - global state - if state.filename: - dlg = wx.FileDialog(self, "Choose PDF File:", style = wx.DD_DEFAULT_STYLE, defaultFile = state.filename, wildcard = "PDF files (*.pdf)|*.pdf|all files (*.*)|*.*") - else: - dlg = wx.FileDialog(self, "Choose PDF File:", style = wx.DD_DEFAULT_STYLE, wildcard = "PDF files (*.pdf)|*.pdf|all files (*.*)|*.*") - - if dlg.ShowModal() == wx.ID_OK: - self.filename = dlg.GetFilename() - state.loadPDF(self.filename) - - def menu_save(self,event,pages=None): - html,self.html = self.html,0 - global state - if not state.pdf: - return - print "html",html - if not html: - defaultFile = state.lastsavefile - else: - defaultFile = state.lasthtmlfile - dlg = wx.FileDialog(self, "Choose Save Filename:", style = wx.SAVE | wx.OVERWRITE_PROMPT, defaultFile = defaultFile, wildcard = "all files (*.*)|*.*|SWF files (*.swf)|*.swf|HTML template (*.html)|*.html") - - if dlg.ShowModal() == wx.ID_OK: - filename = os.path.join(dlg.GetDirectory(),dlg.GetFilename()) - - #progress = ProgressFrame(self, "Saving %s File '%s'..." % (html and "HTML" or "SWF", filename)) - #progress.Show(True) - progress = None - state.saveSWF(filename, progress, pages, html) - #progress.Destroy() - - def menu_save_selected(self,event): - if not state.pdf: - return - p = [] - for i in range(0,self.pagelist.GetItemCount()): - if self.pagelist.IsSelected(i): - p += [i+1] - self.menu_save(event, pages=p) - - def menu_save_html(self,event): - self.html = 1 - return self.menu_save(event) - - def menu_save_selected_html(self,event): - self.html = 1 - return self.menu_save_selected(event) - - def menu_exit(self,event): - self.application.Exit() - - def menu_selectall(self,event): - for i in range(0,self.pagelist.GetItemCount()): - self.pagelist.Select(i, True) - def menu_options(self,event): - self.options.Show(True) - - def status_change(self): - self.statusbar.SetStatusText(state.status_text) - - def OnIdle(self,event): - if self.options.needreload: - self.options.needreload = 0 - if state.pdf: - # reload - state.loadPDF(state.filename) - - def createMenu(self): - menubar = wx.MenuBar() - - menu = wx.Menu();menubar.Append(menu, "&File") - menu.Append(wx.ID_OPEN, "Open PDF\tCTRL-O");self.Bind(wx.EVT_MENU, self.menu_open, id=wx.ID_OPEN) - menu.AppendSeparator() - menu.Append(wx.ID_SAVE, "Save SWF (all pages)\tCTRL-W");self.Bind(wx.EVT_MENU, self.menu_save, id=wx.ID_SAVE) - menu.Append(wx.ID_SAVEAS, "Save SWF (selected pages)\tCTRL-S");self.Bind(wx.EVT_MENU, self.menu_save_selected, id=wx.ID_SAVEAS) - menu.AppendSeparator() - menu.Append(2001, "Save HTML template (all pages)\tCTRL-H");self.Bind(wx.EVT_MENU, self.menu_save_html, id=2001) - menu.Append(2002, "Save HTML template (selected pages)");self.Bind(wx.EVT_MENU, self.menu_save_selected_html, id=2002) - menu.AppendSeparator() - menu.Append(wx.ID_EXIT, "Exit\tCTRL-Q");self.Bind(wx.EVT_MENU, self.menu_exit, id=wx.ID_EXIT) - - menu = wx.Menu();menubar.Append(menu, "&Edit") - menu.Append(wx.ID_SELECTALL, "Select All\tCTRL-A");self.Bind(wx.EVT_MENU, self.menu_selectall, id=wx.ID_SELECTALL) - menu.AppendSeparator() - menu.Append(wx.ID_PREFERENCES, "Options\tCTRL-R");self.Bind(wx.EVT_MENU, self.menu_options, id=wx.ID_PREFERENCES) - - menu = wx.Menu();menubar.Append(menu, "&Help") - - self.SetMenuBar(menubar) - - - def createToolbar(self): - - tsize = (16,16) - self.toolbar = self.CreateToolBar(wx.TB_HORIZONTAL | wx.NO_BORDER | wx.TB_FLAT) - - self.toolbar.AddSimpleTool(wx.ID_OPEN, - wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN, wx.ART_TOOLBAR, tsize), - "Open") - self.toolbar.AddSimpleTool(wx.ID_SAVE, - wx.ArtProvider.GetBitmap(wx.ART_FILE_SAVE, wx.ART_TOOLBAR, tsize), - "Save selected pages") - self.toolbar.AddSimpleTool(wx.ID_PREFERENCES, - wx.ArtProvider.GetBitmap(wx.ART_LIST_VIEW, wx.ART_TOOLBAR, tsize), - "Options") - #self.toolbar.AddSeparator() - self.toolbar.Realize() - - def createStatusBar(self): - self.statusbar = self.CreateStatusBar(1) - - def createMainFrame(self): - - if 0: - self.pagelist = PageListWidget(self) - self.onepage = OnePageWidget(self) - hsplit = wx.BoxSizer(wx.HORIZONTAL) - pagelistbox = wx.StaticBox(self, -1, "Pages") - pagelistboxsizer= wx.StaticBoxSizer(pagelistbox, wx.VERTICAL) - pagelistboxsizer.Add(self.pagelist, proportion=1, flag=wx.EXPAND) - onepagebox = wx.StaticBox(self, -1, "Page 1") - onepageboxsizer= wx.StaticBoxSizer(onepagebox, wx.VERTICAL) - onepageboxsizer.Add(self.onepage, proportion=1, flag=wx.EXPAND) - hsplit.Add(pagelistboxsizer, 0, wx.EXPAND, 0) - hsplit.Add(onepageboxsizer, 1, wx.EXPAND, 0) - self.SetAutoLayout(True) - self.SetSizer(hsplit) - hsplit.Fit(self) - hsplit.SetSizeHints(self) - else: - hsplit = wx.SplitterWindow(self, style=wx.SP_3D|wx.SP_LIVE_UPDATE) - #p1 = wx.Panel(hsplit,-1, style=wx.SUNKEN_BORDER) - #p2 = wx.Panel(hsplit,-1, style=wx.SUNKEN_BORDER) - self.pagelist = PageListWidget(hsplit) - self.onepage = OnePageWidget(hsplit) - #hsplit.SplitVertically(p1,p2, sashPosition=64) - hsplit.SplitVertically(self.pagelist, self.onepage, sashPosition=ICON_SIZE*3/2) - hsplit.SetMinimumPaneSize(10) - -class MyApp(wx.App): - def __init__(self): - wx.App.__init__(self, redirect=False, filename=None, useBestVisual=False) - - #state.loadPDF("sitis2007.pdf") - #state.loadPDF("wxPython-Advanced-OSCON2004.pdf") - global staticdata - staticdata = StaticData() - - self.frame = Pdf2swfFrame(self) - self.SetTopWindow(self.frame) - self.frame.Show(True) - - #self.frame = TestFrame(self) - #self.frame.Show(True) - - def OnInit(self): - return True - -app = MyApp() -app.MainLoop() - diff --git a/wx/viewers/__init__.py b/wx/viewers/__init__.py new file mode 100644 index 0000000..25f7df3 --- /dev/null +++ b/wx/viewers/__init__.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# +# gpdf2swf.py +# graphical user interface for pdf2swf +# +# Part of the swftools package. +# +# Copyright (c) 2008,2009 Matthias Kramm +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + diff --git a/wx/viewers/raw.py b/wx/viewers/raw.py new file mode 100644 index 0000000..a7d71ce --- /dev/null +++ b/wx/viewers/raw.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# +# gpdf2swf.py +# graphical user interface for pdf2swf +# +# Part of the swftools package. +# +# Copyright (c) 2008,2009 Matthias Kramm +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +from gui.fields import Choose + +order = 0 +type = "core" +name = u"No Viewer" +desc = (u'The SWF will be in "raw" format, with each page a seperate frame. ' + u"Use this if you want to add a viewer yourself afterwards.") + +swf_options = [ + Choose("flashversion", u"Flash version:", + (u"4", 4, u"5", 5, u"6", 6, u"7", 7, u"8", 8, u"9", 9), 2), + Choose("insertstop", u"Insert stop after each frame:", + (u"no", 0, u"yes", 1), 0), + Choose("transparent", u"Make SWF file transparent:", + (u"no", 0, u"yes", 1), 0), + ] + +viewer_options = [] + +from gui.plugin import Plugin +class Raw(Plugin): + def __init__(self, swf, filename): + for opt in swf_options: + swf.setparameter(opt.name, str(opt.value)) + +def init(swf, filename): + return Raw(swf, filename) + +from wx.lib.embeddedimage import PyEmbeddedImage +preview = PyEmbeddedImage( + "iVBORw0KGgoAAAANSUhEUgAAAGYAAABmCAIAAAC2vXM1AAAAAXNSR0IArs4c6QAADGNJREFU" + "eNrtXX1MFEcU36/74LwDvByNnIqaFL9ORU2MEUNtE6AVIxWjFuN30ESNTWtiIhpBTVDSNk2j" + "Jq3RfvxhNPEPg2kaVFo1ChgNKQo5vURRMIBIICdwX9zt7Gz/eHZc9/aWQ45DcN8fl7nZudmZ" + "t++9+b33ZucoSqN3IPFtwhhjjKFAPiOR9GooFBJFsaCgYGyzi4t5j8FgcNOmTTt37kQIMQxD" + "URRN0/BgaJom/KUoimEYuCR9eLIaqIQC/DxSA7hKWkZqI72LtDK8K+ntBEFgWbaxsXH37t2x" + "ZxnG+OOPP87MzBx78mU2m4dFymiaDgQCgiAghFiWlT1bQRDu3bvX09MjCEJmZqbVagVxE0WR" + "YRhBEMhDhkqMMRSgHmPMsizIKZGOuElZX1/fsLAMWAATk7IM7vr8+fOtW7du27YtFArNmzfv" + "o48+Ar6wLBsKhfR6vUw9WZaFq+QrQojjuDgrJtwa7AwnNRYy2wEF2dVIhoYsI7L1RCp9oijy" + "PL9w4cJDhw5RFNXW1rZz506DwZCbm9vX11dZWWmxWIqLi5OSkn744Qe/39/Z2bl+/fp//vmH" + "oqiSkpLk5OSff/65trZ2woQJpaWl48ePVxxwNOOM1D7S3KVzYeJsDoxGY0NDw9dff11eXt7S" + "0nLz5s29e/euWLEiJyenrKwsFAqdPn163Lhxf/75544dOwoKCg4cOFBaWmqz2a5evXrnzp0r" + "V678+uuvHMedOHEC7GacocVrKQsXY1Ip/VQxXqRA2hOSqUMwGJwxY0ZpaSnHcU+fPs3Kypo6" + "dWogEPjxxx9tNpvdbne73R6PZ8mSJbNmzfL5fNnZ2Varddq0aZ2dnRjjQCDwxx9/6PX6GTNm" + "yMYmHWSkAUfZOHzu0unEXjFlJLuKEMIYp6SkwDi8Xi/G2O1219fXnzt3rqyszOv1iqLo8/l4" + "ng8Gg4FAQBTFQCAQDAYXLlx4/vz5vLy8cePGQW+wMsRNMYdLymQke1BWq3X58uWgUDabLScn" + "h6Zpu92+bdu2Y8eOTZ06ddKkSXq9Pjs7m2XZ1NTUTz75hKIoh8PR2dnpcDi2bt1aXl5uNps3" + "b96cmpoK62mcpYwOtwgqq4bi0yNXeZ7X6XR5eXkLFiw4duyYIsiAMtwRZqvePzRWbCmTiDiA" + "jNra2qysrEFImeLcpDUcx9E0zXEcy7JQiPQwiWiEjzj8FopypCgyKqxXHEkk32NgWxY9RgUr" + "oy5lPT09vb29Xq9XUcrIZyRZGCmHyWQyMQyDMVYX+WhZBuixpqZmy5YtixcvJhhdNkkoG43G" + "Z8+e7dq1SzaB95llCCGfz1dRUSEV/yGxDLru6ekxGAwXLlyIFAuR4oxRR4WFhX6/32KxqCOE" + "aFkGXGBZ1mAwkLVCZtQJpxBCpBJCQ+BqCIIAPib4UhhjMHYkgiTV4nhKGZBOp5P2ELPgD/BL" + "2jU4gL/88svdu3cpilq0aNGePXtIe+IbiqIIjiGpkWoi8RnjjOZlZlo2tdiwLBxtgbBcvXq1" + "sLAwKyuLZdnm5ma/39/R0bFgwYJbt26JopiTk2OxWDo6OjweT2NjY25urtvtbmxszMnJMRqN" + "NE1XVVUFAoEvvvhCr9cDQFUR9gEx12Bx2WDtCTf050NRVFJSUnNzs9VqXbRo0TfffENR1Lp1" + "67q6utxu97Nnz65du3bmzJmTJ08+fvx4/vz5v//++7Jly168eOF0Og8ePPjdd995PB6apuvr" + "6w8fPhwNUhtZio1bLghCc3Ozy+Xq7u5mWbaoqGjNmjWpqakTJ06cM2dOXV2dz+djGCYvL6+k" + "pARj/Omnn544ceLBgwetra0VFRXz5s1zOBw1NTVtbW2w0r/vgewBfcxwtzE8KrJ9+/bFixdD" + "5bRp0xBCJ0+eRAh99dVXHMf5fD6TyWS32xFCM2fONJlMwBeSXrDb7cePH7fZbMRzVHcPVQb8" + "bj6m4gSH5GOqe44Mw/h8PkEQGIZhGAZwnNVqbW1tvXv3rtfr1el0oijCcsnzPKgeQigtLW31" + "6tX19fUGg4G4DZEUc7htWfjUFNF/VBkmmGRlZWVGRoYs7SQIgiiKLpfr1atXUPPo0SOIRiCE" + "Ll++fPv2bZfL1d/f39LS0t3djTF+8uSJx+PBGDudTujn2rVrZ8+eraurU8xp4f8pUrpLepWU" + "I7WRdiJtv3HjRo/HI8urkZaAnGpqamJm/mfOnElqZs2aRXzDL7/8ktRPmTKFJFOg4HA44IHl" + "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" + "gg==") +getpreviewData = preview.GetData +getpreviewImage = preview.GetImage +getpreviewBitmap = preview.GetBitmap +getpreviewIcon = preview.GetIcon diff --git a/wx/viewers/rfx.py b/wx/viewers/rfx.py new file mode 100644 index 0000000..15343f9 --- /dev/null +++ b/wx/viewers/rfx.py @@ -0,0 +1,363 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# +# gpdf2swf.py +# graphical user interface for pdf2swf +# +# Part of the swftools package. +# +# Copyright (c) 2008,2009 Matthias Kramm +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +from gui.fields import Choose, ChooseAndInt + +order = 2 +type = "custom" +name = u"rfx Viewer" +desc = u"A more sophisticated viewer with zooming and scrolling." + +swf_options = [ + Choose("flashversion", u"Flash version:", + (u"7", 7, u"8", 8), 1), +] + +viewer_options = [ + Choose("html", u"Save HTML:", + (u"no", False, u"yes", True, ), True), + ChooseAndInt('width', 'Width:', + ('same as PDF', -2, 'fullscreen', -1, 'custom', 0), 1, 2, 600), + ChooseAndInt('height', 'Height:', + ('same as PDF', -2, 'fullscreen', -1, 'custom', 0), 1, 2, 800), + Choose('zoomtype', 'Initial zoom level:', + ('Original resolution', 1, + 'Show all', 2, + 'Maximum width/height', 3), 2), +] + + +html_template = """ + + + + + + + + + + + + +""" + +from gui.plugin import Plugin +import os + +class Rfx(Plugin): + def __init__(self, swf, filename): + self.__swf = swf + self.__filename = filename + + for opt in swf_options: + swf.setparameter(opt.name, str(opt.value)) + setattr(self, "_%s" % opt.name, opt.value) + + for opt in viewer_options: + setattr(self, "_%s" % opt.name, opt.value) + + def after_save(self, page): + viewerfilename = self._swap_extension(__file__, "swf", self._flashversion) + + self.swfcombine( + u"%s" % viewerfilename, + u"viewport=%s" % self.__filename, + u"-o", u"%s" % self.__filename, + ) + + if not self._html: + return + + if self._width == -1: + width = "100%" + elif self._width == -2: + width = page.width+40 + else: + width = self._width + + if self._height == -1: + height = "100%" + elif self._height == -2: + height = page.height+70 + else: + height = self._height + + template_vars = { + 'width': width, + 'height': height, + 'version': self._flashversion, + 'flashvars': "zoomtype=%s" % self._zoomtype, + 'swffilename': os.path.basename(self.__filename), + } + + htmlfilename = self._swap_extension(self.__filename, "html") + f = open(htmlfilename, "wb") + f.write(html_template % template_vars) + f.close() + + +def init(swf, filename): + return Rfx(swf, filename) + +from wx.lib.embeddedimage import PyEmbeddedImage + +preview = PyEmbeddedImage( + "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") +getpreviewData = preview.GetData +getpreviewImage = preview.GetImage +getpreviewBitmap = preview.GetBitmap +getpreviewIcon = preview.GetIcon + diff --git a/wx/viewers/rfx7.swf b/wx/viewers/rfx7.swf new file mode 100644 index 0000000000000000000000000000000000000000..7c2a25b4cf1c45be5bee9fa3ee5299ae2f899aa6 GIT binary patch literal 4857 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 literal 0 HcmV?d00001 diff --git a/wx/viewers/rfx8.swf b/wx/viewers/rfx8.swf new file mode 100644 index 0000000000000000000000000000000000000000..1862ee73b4d98543226026fef3bcaa85af873a64 GIT binary patch literal 4857 zcmV*~BrJ0)c(Bf9vU;noJ>-NMw%QrLM z3^P40_j&%}x14uB@A;kgyx%l~@Djiv6+k2dxq_1?PiA{o0{{bWpi2Or=sgZydFb-> z@Yteqt7|_or}L%Cr;;vr<}W|J^>50j|L><6UuC{tEPm>?GfEf zTcAJKeW??YU<_mmWr9b9w*ky-9`-^7vJ2Us9zsCQb|RNvkd7#s=$eYI zx6pMNUE>*mQ|S5?U5^R?uAwW`4d7jL&2R@;;EuyX|JjUHlh1U0_|cOYPb_~CN4(_N zAGJbL?z;6WG}5e!xSxw8Ys^04?TbwRUf$w8ar$tNRu$Xcd7OY zT{&ML@>Sw&b?f1kzjQ}@0j0+UUg6#P`JY3ds0IX9 zvWHnZ;r)!LpffP@T2;ZO4jq%=8#w8v*T$8abj2h{zqJ0ENpP;nZ^wm>+4FA+9`Ex~ zF5l-dE-0p{`0ocob25~x+NXVUwCY7^ z35+{CvhcMLbIk#{=9!NblrQ)$9LKUj<<>a$-E>25eOgGaCijIRD)~CGi(axD9 z_rgcdw{*PUzwWu}aU=UATJy%b>f*UW^}kOr{ucdk;^nW_-&yW1sEQH_ryL)q5(JkC zSGK;jf9yf*U6CuT{9+3)$QlTdRqo?uAj6 z&@t&yd*to2f~qq2zw6idnZqhUbvd!4`JdP4YZo6mbK#li%|VsW@W!+)vkKpV;cuH$ z4oP0$3DFAZOz2(zp4aSGgH|4YJw|-J_2h)2HHP7NV_W&PQjk_f)lyQYS~4zWQS_>$<8y$P=Et{ z$bSx6NB=3T_MzoHl9^D_`S7gevs*W9y`}Iy3t=Z6Mcux%4d*Y`3iL(Nld-#M|N8af zS+c#!P^kO*!|l&M#-z*?E%^Szzj{1NATDHMep$^w7-cQfmjC{v5YUH%dhh7R7h29Y zUuZtxBJ_cXq)eZPgn#=1M8POXL?ucI$uJsHAQjS35z0U%>pk~vOqEE-=$O-jfqyy% zWPVY?$n7j3~xnMl=m%pUkye{DaW1Z`y=(>*1t5`%jbvq7b5XMm|G6TXd#EVV6kZhKFAdwYMsN~O9#+v%(b z3ZBl<6anMAL%sI(t>5(mXV?}rP{Z-55k5z@+%EjtJJtIL(iFSWw1wnUGnr)vXbPaO zudlx!N!yf0NU>5^qj&5dSV`hU3A?lRWT%wPjz?6FyYd$OjL+`!J-2uJ?b*_Gd(Z8z zE!}=yx4X-C`*r(rcBFR|z@OPkW<8TgE6!UUbAB!SB()rz-`HD{qUeg7>rV8KxQ^5S~XZL!v7P%FlyZP1Bp!M&}E|y=+ zn7p+7@{2!z2b@+XQPKlE^x{q7EU_hh+Wg1b9^)O@WKDHybIyt;epb()HDeOg_UMVOE9Yg87x8Q(E7&&SglWw#e6%(m&vfOZ0NsP`IuDyf z32vxCK6-NV)c|Bs*RGh-3e`@s5quxn@Uq&ic9o5g2h9fZvG(Ax8?Jm{RD|9eDnxV* zW8KrhNgl%PBM;(%79H~t{-AjfQ&hO}f%6b?Z+T!jEbA^Aoa8}vA9;`rwCI=z`Ge*` z!tD+hKGf(QdDnT^jCY4OiaPqr#+a~tmChW+BECa9iqU=0y`^Il4%NqI*yt?QQow!P z{pZ8tWNp?5S7YL)^cY>0i^2C+E_}IVTy=@&W04bhMBfKI{H%5txq`=#2Ze_p2M?z{ zUSWrlmBa-DeanZDhkH1Apn1}x35eh@A{aphWmHh^Oi)1t{i$F86%2GHIGhLuQNds; z7~)JYh6qMd!9i3o%9&s+5gbefqp9GKfr8KBd@4Y3V=~HJZ4w>}U^pnQpFrbkGIoO) zG*;tvBV%`n1;w?G(RdLV3t<=xz3PF^HUk-pU?>c|c@d54lHizR1oDRSyGj%-h7mAN zQ~r2Wow1>&0_1EQlmXiVS!U~JLZo~7_8-#|o?D*?S0wRBwL>(5fjH2gte5pdV|{s@ z(O^)P;&nGR5xYt@!D_|#&4Wer;wEL81<=&g)ZdT0Zc9%QH%O55$#1fdy!=r3LNW@O zZpEe(KyNM!b+?)(HpAIOn9SfeE>-=^Q29}jEgnpQ1k?qmAqee3zZZ@Os){=qFpwe1RowmjVl??_%lfJ^F0~*~tP2Ive zO-+>+>P?zD(}X%r72sQyzNQKqp-l|p7`(zDYZCw~Q0L(X9Wd%PA&7%<=j|ZI=Sa}1 ziiMcxHZFuyc1MU|g@uSXnQ4hd0`(?iEpcrLvrb!Cr>)o7heM(P;s%+ryfZYiVq%;j z#@$%=LbStYA@)d=hn1pe2IA3r&?R1hOU5W@oM&u?7E!bt`piWMe-^_~iTaX3DwJkK z7b5ha#I6-Zi%?Fv#hlk*G8t<~w&iRpLP?ex0mX*3Wv9QKG$!i3rPmSG(kxg@tRq9oF~&JEERd5R^H~IP>D1E}47o85 zkke`PRXURmbImR>rvsM=^SBEjdQ-9gH_XjJ>=X;;($JdlFqZ*3jJf3)bD3b$CE<*^ z!&nIZ4bV`DIYJnRUOCuhS=N*XyEc)6MIK@xOwzMTXH6)kOAy)>H~ts(l#Moey(AlE z!V>_;VA)^+MBz2+ce7S&C~v64vqwp&($+Lo&qHTd63msT5OONO=f$U!EIIIz%|Is{DAa%15%fbcb*?y`S#08&7z*B;HtpA^16>P9PA>r4W1$LvR9GvPQkOsn%F$ z0)w{Ff<6v-yKckbu!m#x1k;-CZWNkpwb+m7|apB4{8`h*+_lA}$hzWR1oO zJ!deZ&ZxeCb(7=dd7=3QE5iT*Rl{N7W64A`*<~1JxllEio-b#A?*9O*aw(dJq&$(i;q*t*IbSUd~IK$()cQ z`m|=bUTZ4Q)ISaeO}%N6(O3=ShNwj-5$ZZ;n~c2HL6y;D%&Dm;A#l{1)F@MUInzd(Oxxg=}@Sa(@jZ- zVmf45i5w3-h^mzJEVPZhSZ`v%2agfem#X-2Lw`C9V0~ox1i~GVlu!a$KSG&ADM&Pk z*bC+)$yr7Ggb;ctCvT&N*~y2Ivkkojk{8M+Gr~k%nZ2l5xSg7EfLge7wFo=4sRPs^ zoU6&~)G7w3$(*an?bHavrce3K)FNH0<#BvxYJ;4pQ8JZA_bBe2*Hhquy`88Bx5Jmu zE41PDzh~4=p|C9&#AQf`oGfB|G>Y-b&kiOM(X@S`$fIlKNxLUvnUfmAm-28WHFThq zrD5}t#nq8y?fUf0-{)xPY3wiq}?oP^;Z$JK83hdX? zlgH!8!>Gz|OqMuVSTW^sP9rTFm?2y0Pi8K+pZUEidJc?c=$}N&r3Y*j1+_Vx?4B4l zKvrlQ#P6b~gM{|Y@ISdBw&_n4BCVQa}IZL!q zB^D|>hHI_yJy=b!mMQb3cD!iq9BVTeL=1+K9b_{YL<~|YJC0{Clp4&U2FGH9B;FJn zZ=n#+-52GNB+wrvklH_ro*YL)^||Hol}W8N zJWoy+h-WB}Z^+-qBZjDVZe9KD4I%Li`g*-BKKG|^_fYE0nRmEdVNnj=;iU^oXqLb(G-gw zO6!k|HAbg8p>{fJUGqWF}e8!E_*r3(VHs)35c!%Y+_z36wuwTDI+o$C~ek#YGMmamk zBv~R{jIp8T5lS#&2#+v*3J#2CEuEkx(Xn({n(iQeTQHUuo-s~Nex~~mABlM +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +from gui.fields import Hidden, Choose + +order = 1 +type = "core" +name = u"Simple Viewer" +desc = (u"A tiny viewer, which attaches directly to the SWF, " + u"and provides small previous/next buttons in the upper left corner") + +swf_options = [ + Hidden('simpleviewer', u'1'), + Choose('flashversion', u'Flash version:', + (u'4', 4, u'5', 5, u'6', 6, u'7', 7, u'8', 8), 2 + ), + Choose('transparent', u'Make SWF file transparent:', (u'no', 0, u'yes', 1), 0), + ] + +viewer_options = [] + +from gui.plugin import Plugin +class Simple(Plugin): + def __init__(self, swf, filename): + + for opt in swf_options: + swf.setparameter(opt.name, str(opt.value)) + + +def init(swf, filename): + return Simple(swf, filename) + + +from wx.lib.embeddedimage import PyEmbeddedImage +preview = PyEmbeddedImage( + "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") +getpreviewData = preview.GetData +getpreviewImage = preview.GetImage +getpreviewBitmap = preview.GetBitmap +getpreviewIcon = preview.GetIcon -- 1.7.10.4