merged in Ricardo Pedroso's new pdf2swf gui
authorMatthias Kramm <kramm@quiss.org>
Mon, 24 Aug 2009 16:06:31 +0000 (18:06 +0200)
committerMatthias Kramm <kramm@quiss.org>
Mon, 24 Aug 2009 16:06:31 +0000 (18:06 +0200)
26 files changed:
lib/MD5.c
lib/MD5.h
lib/as3/scripts.c
lib/gfxpoly/poly.c
wx/app.py [new file with mode: 0644]
wx/document.py [new file with mode: 0644]
wx/gpdf2swf.ico [new file with mode: 0644]
wx/gpdf2swf.py [new file with mode: 0644]
wx/gui/__init__.py [new file with mode: 0644]
wx/gui/boldstatictext.py [new file with mode: 0644]
wx/gui/choicetext.py [new file with mode: 0644]
wx/gui/dialogs.py [new file with mode: 0644]
wx/gui/fields.py [new file with mode: 0644]
wx/gui/main.py [new file with mode: 0644]
wx/gui/options/__init__.py [new file with mode: 0644]
wx/gui/options/quality.py [new file with mode: 0644]
wx/gui/options/viewer.py [new file with mode: 0644]
wx/gui/plugin.py [new file with mode: 0644]
wx/pdf2swf.gui.old.py [moved from wx/images.py with 91% similarity, mode: 0755]
wx/pdf2swf.py [deleted file]
wx/viewers/__init__.py [new file with mode: 0644]
wx/viewers/raw.py [new file with mode: 0644]
wx/viewers/rfx.py [new file with mode: 0644]
wx/viewers/rfx7.swf [new file with mode: 0644]
wx/viewers/rfx8.swf [new file with mode: 0644]
wx/viewers/simple.py [new file with mode: 0644]

index 9e60f50..f8dc3fe 100644 (file)
--- 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));
index ad54fe1..e560700 100644 (file)
--- 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
index a7f79bb..8bcd9de 100644 (file)
@@ -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)
index 2be5efb..95a8a22 100644 (file)
@@ -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 (file)
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 <kramm@quiss.org> 
+#
+# 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 (file)
index 0000000..70cbb82
--- /dev/null
@@ -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 <kramm@quiss.org> 
+#
+# 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 (file)
index 0000000..ad46ef0
Binary files /dev/null and b/wx/gpdf2swf.ico differ
diff --git a/wx/gpdf2swf.py b/wx/gpdf2swf.py
new file mode 100644 (file)
index 0000000..3fd12c6
--- /dev/null
@@ -0,0 +1,48 @@
+#!/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 <kramm@quiss.org> 
+#
+# 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 (file)
index 0000000..a12f187
--- /dev/null
@@ -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 <kramm@quiss.org> 
+#
+# 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 (file)
index 0000000..247e29c
--- /dev/null
@@ -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 <kramm@quiss.org> 
+#
+# 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 (file)
index 0000000..4e89864
--- /dev/null
@@ -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 <kramm@quiss.org> 
+#
+# 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 (file)
index 0000000..0d76613
--- /dev/null
@@ -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 <kramm@quiss.org> 
+#
+# 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 <kramm@quiss.org>")
+        info.Description = u"graphical user interface for pdf2swf"
+        info.Developers = [
+                           u"Matthias Kramm <kramm@quiss.org>",
+                           u"Ricardo Pedroso <rmdpedroso@gmail.com>",
+                          ]
+
+        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 (file)
index 0000000..457a4b3
--- /dev/null
@@ -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 <kramm@quiss.org> 
+#
+# 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 (file)
index 0000000..1aa686c
--- /dev/null
@@ -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 <kramm@quiss.org> 
+#
+# 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 (file)
index 0000000..6926daa
--- /dev/null
@@ -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 <kramm@quiss.org> 
+#
+# 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 (file)
index 0000000..5411592
--- /dev/null
@@ -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 <kramm@quiss.org> 
+#
+# 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 (file)
index 0000000..18c70af
--- /dev/null
@@ -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 <kramm@quiss.org> 
+#
+# 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 (file)
index 0000000..5cdc2a6
--- /dev/null
@@ -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 <kramm@quiss.org> 
+#
+# 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))
+
old mode 100644 (file)
new mode 100755 (executable)
similarity index 91%
rename from wx/images.py
rename to wx/pdf2swf.gui.old.py
index 3c8abbe..3657a30
@@ -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.
 # 
 # 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 = """<html>
+<body style="padding: 0px; margin: 0px">
+<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
+        width="%(width)s"
+        height="%(height)s"
+        codebase="http://active.macromedia.com/flash5/cabs/swflash.cab#version=%(version)d,0,0,0">
+        <param name="MOVIE" value="%(swffilename)s">
+        <param name="PLAY" value="true">
+        <param name="LOOP" value="true">
+        <param name="QUALITY" value="high">
+        <param name="FLASHVARS" value="%(flashvars)s">
+          <embed src="%(swffilename)s" width="%(width)s" height="%(height)s"
+                 play="true" ALIGN="" loop="true" quality="high"
+                 type="application/x-shockwave-flash"
+                 flashvars="%(flashvars)s"
+                 pluginspage="http://www.macromedia.com/go/getflashplayer">
+          </embed>
+</object>
+</body>
+</html>
+"""
+
+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.pdf.pages:
+                state.changePage(state.pagenr+1)
+
+    def OnPageChange(self):
+        self.Refresh()
+
+    def OnSize(self, event):
+        self.Refresh()
+
+    def Draw(self,dc=None):
+        global bitmap
+        if not dc:
+            dc = wx.ClientDC(self)
+        posx = 0 
+        posy = 0
+        window_width,window_height = self.GetSize()
+        dc.Clear()
+
+        if not state.pdf or not state.page:
+            return
+
+        if state.page.width * window_height > 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 (executable)
index 7e3f4bd..0000000
+++ /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 <kramm@quiss.org> 
-#
-# 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 = """<html>
-<body style="padding: 0px; margin: 0px">
-<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
-        width="%(width)s"
-        height="%(height)s"
-        codebase="http://active.macromedia.com/flash5/cabs/swflash.cab#version=%(version)d,0,0,0">
-        <param name="MOVIE" value="%(swffilename)s">
-        <param name="PLAY" value="true">
-        <param name="LOOP" value="true">
-        <param name="QUALITY" value="high">
-        <param name="FLASHVARS" value="%(flashvars)s">
-          <embed src="%(swffilename)s" width="%(width)s" height="%(height)s"
-                 play="true" ALIGN="" loop="true" quality="high"
-                 type="application/x-shockwave-flash"
-                 flashvars="%(flashvars)s"
-                 pluginspage="http://www.macromedia.com/go/getflashplayer">
-          </embed>
-</object>
-</body>
-</html>
-"""
-
-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.pdf.pages:
-                state.changePage(state.pagenr+1)
-
-    def OnPageChange(self):
-        self.Refresh()
-
-    def OnSize(self, event):
-        self.Refresh()
-
-    def Draw(self,dc=None):
-        global bitmap
-        if not dc:
-            dc = wx.ClientDC(self)
-        posx = 0 
-        posy = 0
-        window_width,window_height = self.GetSize()
-        dc.Clear()
-
-        if not state.pdf or not state.page:
-            return
-
-        if state.page.width * window_height > 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 (file)
index 0000000..25f7df3
--- /dev/null
@@ -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 <kramm@quiss.org> 
+#
+# 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 (file)
index 0000000..a7d71ce
--- /dev/null
@@ -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 <kramm@quiss.org> 
+#
+# 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 (file)
index 0000000..15343f9
--- /dev/null
@@ -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 <kramm@quiss.org> 
+#
+# 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 = """<html>
+<body style="padding: 0px; margin: 0px">
+<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
+        width="%(width)s"
+        height="%(height)s"
+        codebase="http://active.macromedia.com/flash5/cabs/swflash.cab#version=%(version)d,0,0,0">
+        <param name="MOVIE" value="%(swffilename)s">
+        <param name="PLAY" value="true">
+        <param name="LOOP" value="true">
+        <param name="QUALITY" value="high">
+        <param name="FLASHVARS" value="%(flashvars)s">
+          <embed src="%(swffilename)s" width="%(width)s" height="%(height)s"
+                 play="true" ALIGN="" loop="true" quality="high"
+                 type="application/x-shockwave-flash"
+                 flashvars="%(flashvars)s"
+                 pluginspage="http://www.macromedia.com/go/getflashplayer">
+          </embed>
+</object>
+</body>
+</html>
+"""
+
+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 (file)
index 0000000..7c2a25b
Binary files /dev/null and b/wx/viewers/rfx7.swf differ
diff --git a/wx/viewers/rfx8.swf b/wx/viewers/rfx8.swf
new file mode 100644 (file)
index 0000000..1862ee7
Binary files /dev/null and b/wx/viewers/rfx8.swf differ
diff --git a/wx/viewers/simple.py b/wx/viewers/simple.py
new file mode 100644 (file)
index 0000000..93918b5
--- /dev/null
@@ -0,0 +1,174 @@
+#!/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 <kramm@quiss.org> 
+#
+# 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(
+    "iVBORw0KGgoAAAANSUhEUgAAAGYAAABmCAIAAAC2vXM1AAAAAXNSR0IArs4c6QAAF8NJREFU"
+    "eNrtXWtQW+eZPhIS6ILu0kEIJCQQNwlZmJu5mVBsAnaMY7tpkmnjZHLpTtvZTNptt+5sZ6ed"
+    "bvsjM5vZZpttZ2dnO2mbJrEx4DvIAcTFiJuQEJIskEASSAKE7hLoftkfX4f12E6K3TTGtt5f"
+    "R0ffOUc85/ue932f9z0HCErbAxoCgqBUKpUGYq94IRDINAoPamnI0pClIUtDloYsDVna0pCl"
+    "IUtDlobsaTHUA6VXBALhSQUiEAjsMdd+AMgIBMK5c+eqq6u/eFgymUQgEKlUCol8bKbw3Nzc"
+    "u+++++XPMgiCqqurOzs7P+/baDT68//8ucvuev/f3hc3iX/3H79ra2lLc9nnWvfV7obXG648"
+    "c2UrsJVKpVANqLdn337u28+tra2lIbvbtDpt69nWnzt+Dn0EZdVmpaBUMpnMyMrA/BBj+aXl"
+    "2LvHvv+L74dCoTRkEARBXq/3tR+99o3//Yb3N17MGxgIAUEQlIJSqVQKgURAEITOQWP+C3Oz"
+    "82b9a/V/uPCHpxqyZDL53n+/d/gfD8+9OYf9d2wGOePOb1OpFIAPGLYOizqPejfy7uFvHlaq"
+    "lE8jZEOjQ7Uv1P4+7/eZH2VmlWfd9S1YmGCW3RGhQNiz2O3/2X6159VX/ukVl8t13zNvbm7e"
+    "tXHfMbFY7K/e0WQy+ejjst0ZNDoz6kg6iOXE+w7Y2toaGRkJhULZUPbd9weLjOXF9Df1U1NT"
+    "+fn5BoMhJycHhuHS0lKPxzMxMREIBPh8fiqVMhqNJ06ckEqlTU1Nk5OTIpGIw+Fcu3ZNKBRu"
+    "bGy8//77P/jBD2AYlkgkbDY7kUgsLS0xmUwKhZKdna3X6zEYzNLS0ltvvbUvZhkCgfjFP//i"
+    "R20/Ev5a6PmhJxFI3DUgEokYDAY0Bn3X/uBw0NXheiv+1nvff8/v98/NzQmFwmQyqVQqIQi6"
+    "fv16e3t7KBQyGAyLi4tgz/Hjx69fv76xscHhcMLh8MrKSjweX1tbE4vFMAyDa/X19c3OztbV"
+    "1fn9frVaffHixfX19VAoVFdXt19mGbC8vLzT8On2nfZfv/jryAsR3Ou4XfAxWAyfz0e4/n9h"
+    "RoyR7Z9snyg50fRGk0gkmpiYyMjIKCwsJJFISCQykUhAEFRRUdHT05OXl7e9vY1Go2k0GofD"
+    "6evrO3DgAFjFyWSSy+Wur6/DMOz3+zc2NmAYttls2dnZXC43Ozs7Ly8Pg8Hk5+e7XC6RSDQ8"
+    "PHzgwIG/F5+l9mYEAqG/v//e/Z/0fVL5jUrBiKAqVVWVqup8s9PhcFT+a2VVqkrsF5f/S/mz"
+    "rzxrt9tT+9j6+/sJBMJeRn45cdnLp16e/mj69Mzp8OvhyEoEUG8qlQr+Ppj9D9l/OP0HyZ8k"
+    "YB39Vdq+i/jv9QZf4Bb2Y1p+p1mtVoVC0dLSMj4+fvjw4Vu3bnU2dJ5uO/3OuXcyMjOGh4cd"
+    "3Y7vfvu7R985evXKVQadYTKZ2Gz2Rx999OKLL5JIpJ2dnVAoFAwGGxoaVCqV0+msrKycmJgQ"
+    "CoVOp3Nzc9NisRw9etRisczPzxcWFno8HpfLZbfb8Xi81+vV6/WHDx/WarVer/fEiROPB2RS"
+    "qfTs2bOffPLJSy+99PHHH0ej0Z2dnZycnO+d+V44HMZgMO//8v1QKFRfX282m+Px+Pz8/Orq"
+    "allZGZVKXVpaWl9f39nZAR4tEolIpVIcDkelUicnJ1EolMfjOXv2rEQiiUaj6+vrHA7HZDLF"
+    "YrGzZ89++umnkUjkm9/8Zl9fXywW8/v9j00oW1RU1NvbW1lZ2dfXV1lZyeVyGQwGg8HY2dlp"
+    "bm6Ox+MHDhzAYDCTk5M0Gi2ZTNLpdIFAQKfT/X7/4uLizs5OYWEhOJXNZiMQCIlEYmJigslk"
+    "wjAcj8d7e3urqqqoVCqPxwNMT6PRBgcHYRhms9loNJpOp2dlZT2yBPZvpP8vxWw22/r6Otie"
+    "nZ3dyyFSqXR8fPyrp3/U34J1NBrd3t6ORqM0Gg2NRt87AKwdGo0GQZDL5SISiXcNS6VSW1tb"
+    "OTk5LBZrd2dNTc193QKTyQQxPVDiWltbHyf639jYUKvVFRUVS0tLCARCIpH85Cc/wePxN27c"
+    "qK6utlgs2dnZFAplYmKCQqG0t7drtdorV668+eabcrlcJBKx2WyHw6FQKJqbm61Wq8/ngyAI"
+    "jUZrNBqhUKjVaolEIgqFKisrk8lkbW1ts7Oz09PT586dGxkZsVgsra2ter2+urp6fHycSCTG"
+    "YrHS0lKNRlNZWel2uz0eT35+/vLy8rPPPruPIOvu7mYymTqdDolEbm5uisViEonkdrstFktZ"
+    "WdmNGzdYLFZ2dnZ9fb3JZIIgSKlUFhYWzszMVFZWDg8Pv/rqqxcvXszLy5udnXW5XPF4PJlM"
+    "MpnMQCCg0WgaGxu7u7spFMrq6uqZM2fOnz9Po9GIRCIEQXQ6PTc39+LFi3Q6PZVK5eTkKJVK"
+    "CoWyuLhYXl4ulUqRSCQKhbLb7X+/OfiQ9H/o0KGsrCwej0cmk2EYRiAQHo8HiUSy2WyXyyUQ"
+    "CMrKyng83ujoKIVCgSCIRCKZzWaxWDw6Osrn8yEIqq+vT6VSxcXFDAYjFottbm4C70EikQgE"
+    "QmlpKQzDQqHw8uXLLS0tdrs9Go1CEMThcFQqVV1dHZlMzs/PB/kpCPoGBwfB74lEIiwWi0Qi"
+    "PeH0/zeaVqsNBoP7Ovq/NwoHe3Z2dkDYed8x90b/YM/29vb29vYDxfd3nmpzc1MgEGCx2HA4"
+    "7PV69yn9r66uejweg8HQ0tKi0+nQaHQikdjZ2RkaGhKLxdnZ2VqtViaTnTlzpqSkRK/XGwwG"
+    "EomkUCiampqqq6v1en1eXt7y8vKFCxd+9rOfmc3mVCplMplEIhHQczo7OwcHB4uKipxOJwaD"
+    "8Xg8HA6nqKjI7/fLZDKRSPTBBx/89Kc/zc7OHhgY0Ov1p06d0mg0ZWVlW1tboVAoJycnHA7H"
+    "4/FoNEqn08vKyh49l5lMpunp6WPHjn322WdGo7GmpsZkMk1OTgqFwmg0urKy4na7SSSSUqlM"
+    "pVIKhcJut9tsNhiGQU1PqVR6vV6Px1NZWZmZmQmEikQi0dfXl0qlBALB+fPnGQyGTCbTaDQY"
+    "DEatVt+6dQuCoJ6enlQqpVKpwI3R6XQwDKPR6Fu3bnG5XJBCJRIJuVyuUCgAmYIDHz1kMAxz"
+    "OByg0iAQCLlcDsMwk8lUKpVkMpnFYrnd7kgkwufzL1y4AMMwSA8EAoFMJgPakUQioVKpgUAg"
+    "Go3i8fhUKuV0OolEIh6Pl0qlR44cUavVbDa7sLCwqKiIQqEIBALgNKLRqFAoTCQSgUCAx+Mp"
+    "FAoUCsXlcmdnZ8vLy9lsNhCICgsL6XR6QUFBeXl5mv4ff/HngZzGflBvHg39q1QqoNwzGIxQ"
+    "KOTz+RoaGiQSSX5+fjgcdjqdR48eHRoaqq6uZrFYJpNJq9V2dnaOjIyANHtlZaW2tpbJZK6u"
+    "rnq93mg02tzc/IQX5ebm5ioqKhKJxPz8fCQSkUgkEomksbFxenp6cXGRSqVaLJZkMtnT0wNB"
+    "UDgc3traAiwG4HM6nYuLi8FgcG5uLhKJXLp06cmfZVwuF4TXyWTSarVmZ2cfOHDg5s2biUSC"
+    "y+UCkcfr9ZLJZLAeU6kUBoMBYbrH45mamnr++eevXLmCw+FsNhsOh1tfX0cgELm5uY8HbF8K"
+    "/QeDwd7eXqPRuJdTyeXyp47+QZDt8/l2o3AsFnv69Gkej7eXID4vL++L04m9e4mv3p885ML8"
+    "9NNPv/Od7/T19ZnN5ldffbWwsFCr1fr9fjqdbjAYDh48uLa2BgLazMxMkUjEYrF0Op3ZbO7s"
+    "7JRIJAaD4e233zaZTBqNhkgkZmRkoNHoYDC4K/ugUKidnZ3bt28Dia2xsXF5ebmgoMBgMCST"
+    "ye3tbSqVury8XF1dvbq6arFYIpFIQUHB/Pw8gUBAIpEtLS37DjIE4i9lyrKyMiBJd3d3U6lU"
+    "Op3e1dV148YNsFSpVKpYLB4ZGXn55ZcjkYharUYikTk5OUARun379qFDh3p6eoDaYbfbd2Uf"
+    "IMm1tLRcuHCBTCY3NjaSyeSenh40Gr2wsAAudPr06atXr6ZSqfz8/EuXLnV0dIjF4uvXr4PD"
+    "9x1kNTU1PT09JSUloL5dXFxcV1cXi8XIZDIej2cwGGAYHo8nEomA9dfX17OysthstkwmA9os"
+    "jUYDOs9fasYYzJ0fMzMzCQRCSUkJ+Ein041G4zvvvIPBYJLJJB6Px+Fw4EJWqxWPx1MoFDKZ"
+    "vHv4k6/9P3XR/144+L513z2S913dPmD7C46Nx+OgHrqPFuba2trCwoJIJEokEvF43OPxhMNh"
+    "tVrd1dWVTCYvXbpUUFDAYrEUCkVra+vQ0BCfz//Tn/708ssvezweFouFQCDy8/MHBwedTufr"
+    "r7/udrtnZmZqamp8Pl8gEEAikaFQiEwm22w2MpkcCoVQKNSHH3548uRJi8XCZrOvXr3a1dUV"
+    "CARsNlssFqNQKAaDoaGhgUaj6fV6BoPhdrsNBoPX62UymUQiEYfD6XQ6BoOBxWKZTObc3Nwz"
+    "zzwzNjbW3Nz8EMT3kLNsbGyMx+MZDAaNRjM3N2cymcxmM+gDj8fjwWBweXlZKpVWVVUNDAxY"
+    "LBYikSgWi5VKZXNzs1KpVCqVAwMDra2t4XAYuI5EIqFSqT744AM0Gn3x4sWpqamZmZmGhgat"
+    "VtvU1GQymbhcrkAgAK0+BQUFAoHAZDItLS3p9fqZmZmOjo7BwUEgK21ubm5sbIDfCcaDAUC2"
+    "Gx4ePnnyZH9///Hjx69du/bVzTIOhyOVSsVisdlsBgUeBoNhMBgikQgKhSooKIjFYgQCYXh4"
+    "uLa2FoVC2Wy2SCSSk5ODQqEyMzN1Ot23vvWtvr4+KpUKJJ3V1VUWi3Xs2LHV1dXa2loEAoHD"
+    "4bBYLB6Pv3XrFgzDGAxmfn4etPoUFBSoVCrQAhSJRBgMBhqNBq4AhuGxsbHGxsbMzMzMzEyT"
+    "yYTH4/Pz83E4HJfLBfFjb2+vWCy+dOmSWCz+Sunf6/UaDIY0/T8A35NIJFAr+rw6wOft9Pl8"
+    "dzZox+Pxu+6f3W7f4zkfp7R8ZGTk0KFDQNL5zW9+8/Wvfx0UJdva2sAdQyAQMzMz7e3tGAzm"
+    "6tWrVCoVhUKB7LKkpIRKpWKxWL1eD0HQxMQEj8drbW1dWVlZXFw8cuSITCZjsVg2m211dVUs"
+    "FnO53JWVFY/HYzab3W53Z2cnEolUqVTRaBSLxZLJ5KysLAaDoVKpIpFIbm6uSqU6evQoBoPZ"
+    "X+LPnZJOfn7+7du3h4aGmpubb968ub297Xa7gRAGZrLD4bBarSaTaXV11efzOZ3OQCAAqHpu"
+    "bo5Op4MmzXA4vLa2plAogEak0+nsdrtGo4nFYsDDKJVKPp8/NzcHPIZMJoNh+Ny5c4DFLl68"
+    "ODk5GQwGt7e3h4aG9p1eBsPwrqTjcDgwGExZWVl/f39VVRWPxwONOslkEkADhH8Yhul0ejwe"
+    "z8jIwGKxIOtaW1sTCAQTExMgQ0IikVlZWXQ6HYZh4CWqqqq6u7uzsrIA2Y+Pj4P4vra2tri4"
+    "eGFh4c033wT+sba2ls/nb21txWIxPB7/lEb/d7UA7bEj6AnR/t1u9166Pu/NZO/6GI/Hdx8B"
+    "jMfjKysrdz4R+AUuAhT9HiX939X4OTExgcFgfD5fZ2fnwMAAiUTy+/2nTp2SSCSlpaXBYPDa"
+    "tWuvvfaaQqGoqKjgcDhbW1vT09PNzc0TExN1dXXz8/Ogz2dubq6trU0mkwmFwq2tLVAigGF4"
+    "bW3N5/OFw+GNjQ08Hv/cc89BEGSz2cbGxnp6el555RUEAhEIBDwej9/vNxqNnZ2d0WhUIpGI"
+    "xeJwOEwkEvV6vUqlOnPmjFarPXLkSEZGxlfNZVKpFMTQzz333LVr1+x2u16vr6mpkcvlOzs7"
+    "er0ehuH+/n4ejzc+Pq5UKouKikC5YGRkBIIgiUTS1dUllUqPHj0qkUisVqvD4QDOYWRkxOVy"
+    "3bp1S6PRuN3uxcXF7e1tUCK4fPkyjUa7s6Gfx+O1tLQolUqTyQRchMlkAgSaTCZBN6RSqTQa"
+    "jRkZGXV1dd3d3W63W6fTPQL6v7fxs7S0lEAggNC8tLSUTqeXlJTMzMxwuVwymWw0GkUi0djY"
+    "WFFREQRB5eXlvb29Bw4cuHz5skAgAP6BTqfHYjGg9ggEAhwOB1rYrl27lpGRARSe4uLi6elp"
+    "uVwOxCKtVms0Gjs6OtRqdSgUgmEYhmHgqX0+H6jYk8lkuVzOZrN1Ol19fT0Wi71XE35y6F+h"
+    "UCQSiSck+t/L3F5YWNi9JWq1+iHOcPDgQdDjGQgEzGbzfcc4nc719fW7zmyz2cDaBNHyvoj+"
+    "XS7XZ599lpGRAZpQSCSSWq0uKCjY3Nw8c+YMAoG4cOHC7du3MzIybt++3djYuLS0ZDKZUCgU"
+    "EonE4XAtLS0ul0sikQQCgZqaGi6Xe/78eT6fbzab8/LyVldXU6lUU1PT9evXRSLR1tZWRUVF"
+    "d3d3fX09mUw2m801NTUDAwPFxcVYLFYulzc2Nk5OTubm5m5sbBQUFPh8vj/+8Y8//vGPiUSi"
+    "2+3+7W9/m5ube/r06UccylqtVrvd3tbWZrPZDAaDw+H42te+Njo6mkwmvV6vz+fD4XBMJlOl"
+    "Uh07dmx6ejqZTIZCIZfL5XQ6QS3DarW6XK4XXnhhenoaqIZ4PN5ms4Fm15qamvn5+fLycrlc"
+    "jkKhnE5nQ0ODw+EYGxtDoVAgAN7a2lpeXq6rq7Pb7Uaj0eVyhUKhmpoah8NRWVlJoVCSyeT6"
+    "+jqZTAYdkI94llVUVIANFotlNpt5PB6JROrq6jIajXg8PjMzEzSy1tbW3rx5s7293WKx2O32"
+    "rKws0PJ65xmEQiEEQZWVlWVlZcvLy6BGpVAojhw5EgwGORzOwsICeIKQwWDU1taq1WoOh4NE"
+    "IkFdeWFhoa2tDYIgMpkMSoIVFRVOp9PlclEolPLy8i8rHNvX9A8W5hOu/e8y/a4BAr53+77H"
+    "6nQ6p9MZiUR29cu9+J+FhYV7r7t/xZ/h4eHi4mKXy2UwGIA44/f7c3Nzo9Ho6OhoeXn5+Pj4"
+    "Sy+9tLS0RKFQpFLpiy++qNVqaTRaS0sLUE3Hx8eDwWBWVpbT6czPz9doNFgs9sSJE0tLSysr"
+    "K6WlpRMTE7vpgdVqDYVCJ06ciMfj3d3d1dXVLpfLarVCEOT3+/l8vtvtHh4ezszMRCKRb7zx"
+    "xt/1rSYPeWq/39/X1+fxeJqamsBDujabbWNjw+125+XlWSyW4uJiNpvtdDpv3rwJOtXVajVo"
+    "Oy4uLv7Vr34Fw7BMJgN7rFYrDMMgoxwdHUUikW63G4FA2Gw2NBptsVhGR0f9fn88Hl9eXubz"
+    "+SUlJQAvcF3AXGw2G4fDlZWV7Qr/+2uWdXR0DA0NgTigsbExFAolEgmdTicSiaRS6bFjx3A4"
+    "3MrKSlZWVn19PZfL3djYaGhoALJfbm6uQCAQCoUdHR3RaJTJZEIQVFBQMDU1xWQyn3/++amp"
+    "KTKZTCQS6XS62+1mMpldXV2bm5sgD+3r6yOTybveA4lEarXaQ4cO5eTkRKNR8NjA41T6DQaD"
+    "Docjrf3f3+6MyHeZGIvF0ul06Im2h1yYcrl8fn6+tLR0dnaWSqU6HA4IgnA4nEajqaio6O/v"
+    "r6mp8Xq9xcXFoKTyJNlDzrLFxcXGxkafz0cmk3dTvJmZmVOnTk1NTYHnsBAIxOe9QuRpnGW1"
+    "tbVKpbKxsVGr1QqFQpBpMpnM3t7ezs7Ozc1NFos1Pj6ek5Mjl8vv+3zl423pzp/92/f/VHPZ"
+    "02yoJ+mPGRsbC4VCHR0dnzdgfHwchmECgTA2NlZYWPhw7wV6omaZ0Wj0er0ymezjjz/e2dn5"
+    "85///OGHH6rV6suXLwPfffDgwcnJSRaLVV9f73a70wsTWl9fZzKZ4ImgwcHBvLy8UCg0NjaG"
+    "RqPtdjsEQbvvTxgYGGhvb09DBh0/fvyZZ56h0Wg5OTkHDx70eDxer/fkyZOxWAzkJKC4B6bb"
+    "Q5cyH+DfvRCJxL28V3b/mEKh4PP5uzrwFxh4r+xeXoeDAO37e4Qs/fZiAMIDeMz0/x5Kx2Vp"
+    "yNKQpSFLQ5aGLG1pyNKQpSFLQ5aGLG1pyNL2iO3/AKxo1C8LNvv2AAAAAElFTkSuQmCC")
+getpreviewData = preview.GetData
+getpreviewImage = preview.GetImage
+getpreviewBitmap = preview.GetBitmap
+getpreviewIcon = preview.GetIcon