163 lines
4.0 KiB
Python
Executable File
163 lines
4.0 KiB
Python
Executable File
#!/usr/bin/env python
|
|
import sys
|
|
from pdflib.sgml import PDFSGMLParser, Document
|
|
stdout = sys.stdout
|
|
stderr = sys.stderr
|
|
try:
|
|
import pygame
|
|
from pygame.locals import *
|
|
except ImportError:
|
|
print >>stderr, 'you need pygame'
|
|
sys.exit(111)
|
|
|
|
|
|
def scale(x):
|
|
return int(x*0.002)
|
|
|
|
|
|
## FontManager
|
|
##
|
|
class FontManager:
|
|
|
|
fonts = {}
|
|
#default_font = '/Library/Fonts/Vera.ttf'
|
|
default_font = '/usr/share/fonts/truetype/kochi/kochi-gothic.ttf'
|
|
|
|
@classmethod
|
|
def get_font(klass, path, size):
|
|
if not path:
|
|
path = klass.default_font
|
|
size = int(size)
|
|
k = (path,size)
|
|
if k not in klass.fonts:
|
|
font = pygame.font.Font(path, size)
|
|
klass.fonts[k] = font
|
|
else:
|
|
font = klass.fonts[k]
|
|
return font
|
|
|
|
|
|
## PDFViewer
|
|
##
|
|
class PDFViewer:
|
|
|
|
BGCOLOR = (255,255,255)
|
|
FGCOLOR = (0,0,0)
|
|
|
|
def __init__(self, display, doc):
|
|
self.display = display
|
|
self.buf = None
|
|
self.pages = doc.get_pages()
|
|
self.render_page(0)
|
|
return
|
|
|
|
def render_page(self, pageno):
|
|
print >>stderr, 'rendering: page=%d...' % pageno
|
|
page = self.pages[pageno]
|
|
(x,y,w,h) = page.bbox
|
|
self.width = scale(w)
|
|
self.height = scale(h)
|
|
self.buf = pygame.Surface((self.width, self.height))
|
|
self.buf.fill(self.BGCOLOR)
|
|
for text in page.get_texts():
|
|
font = FontManager.get_font(None, scale(text.size*0.7))
|
|
(x,y,w,h) = text.bbox
|
|
r = font.render(text.data, 1, self.FGCOLOR)
|
|
self.buf.blit(r, (scale(x), self.height-scale(y)))
|
|
self.pageno = pageno
|
|
self.pos = (0,0)
|
|
self.refresh()
|
|
return
|
|
|
|
def refresh(self):
|
|
size = self.display.get_size()
|
|
self.display.blit(self.buf, (0,0), (self.pos, size))
|
|
pygame.display.flip()
|
|
return
|
|
|
|
STEP = 8
|
|
def run(self):
|
|
loop = True
|
|
key = None
|
|
(w,h) = self.display.get_size()
|
|
xmax = self.width - w
|
|
ymax = self.height - h
|
|
while loop:
|
|
for e in pygame.event.get():
|
|
if e.type == VIDEOEXPOSE:
|
|
self.refresh()
|
|
elif e.type == KEYDOWN:
|
|
if e.key in (K_ESCAPE, K_RETURN, K_q):
|
|
loop = False
|
|
break
|
|
elif e.key == K_SPACE:
|
|
if self.pageno < len(self.pages)-1:
|
|
self.render_page(self.pageno+1)
|
|
elif e.key == K_b:
|
|
if 0 < self.pageno:
|
|
self.render_page(self.pageno-1)
|
|
else:
|
|
key = e.key
|
|
elif e.type == KEYUP:
|
|
key = None
|
|
if key:
|
|
(x,y) = self.pos
|
|
if key in (K_h, K_LEFT, K_KP4):
|
|
x = max(0, x-self.STEP)
|
|
elif key in (K_l, K_RIGHT, K_KP6):
|
|
x = min(xmax, x+self.STEP)
|
|
elif key in (K_k, K_UP, K_KP8):
|
|
y = max(0, y-self.STEP)
|
|
elif key in (K_j, K_DOWN, K_KP2):
|
|
y = min(ymax, y+self.STEP)
|
|
self.pos = (x,y)
|
|
self.refresh()
|
|
return
|
|
|
|
# main
|
|
def main(argv):
|
|
import getopt
|
|
def usage():
|
|
print 'usage: %s [-d] [-c encoding] file' % argv[0]
|
|
return 100
|
|
try:
|
|
(opts, args) = getopt.getopt(argv[1:], 'dc:P:')
|
|
except getopt.GetoptError:
|
|
return usage()
|
|
if not args: return usage()
|
|
debug = 0
|
|
encoding = 'utf-8'
|
|
cmapdir = 'CMap'
|
|
cdbcmapdir = 'CDBCMap'
|
|
password = ''
|
|
for (k, v) in opts:
|
|
if k == '-d': debug += 1
|
|
elif k == '-c': encoding = v
|
|
elif k == '-P': password = v
|
|
#
|
|
fname = args.pop(0)
|
|
if fname.endswith('.pdf'):
|
|
# convert .pdf to sgml
|
|
import tempfile
|
|
from pdf2txt import CMapDB, PDFResourceManager, pdf2txt
|
|
print >>stderr, 'reading %r...' % fname
|
|
CMapDB.initialize(cmapdir, cdbcmapdir, debug=debug)
|
|
rsrc = PDFResourceManager(debug=debug)
|
|
fp = tempfile.TemporaryFile()
|
|
pdf2txt(fp, rsrc, fname, None, encoding, password=password, debug=debug)
|
|
fp.seek(0)
|
|
else:
|
|
fp = file(fname, 'rb')
|
|
doc = Document()
|
|
parser = PDFSGMLParser(doc)
|
|
parser.feedfile(fp, encoding)
|
|
parser.close()
|
|
fp.close()
|
|
#
|
|
pygame.init()
|
|
pygame.display.set_mode((640,480))
|
|
PDFViewer(pygame.display.get_surface(), doc).run()
|
|
return
|
|
|
|
if __name__ == '__main__': sys.exit(main(sys.argv))
|