-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtex2mbm-fast.py
222 lines (196 loc) · 10.2 KB
/
tex2mbm-fast.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
#!/usr/bin/env python2
print "tex2mbm-fast v1.2 (c) 2008,2009 Silas S. Brown. License: Apache 2" # see below
import sys
# NB if you have more files than will fit on sys.argv,
# you can add to them here by doing something like
# import os ; sys.argv += filter(lambda x:x.startswith("myfile-"), sorted(os.listdir(".")))
if len(sys.argv)<2:
print "Syntax: python2 tex2mbm-fast.py .tex-files"
print "Creates contents.dat, sequence.dat and *.mbm"
print "which should be loaded onto the EPOC device with MbmShow"
sys.exit()
# ---- Change these variables : --------------
device_resolution = (640, 480) # for S7
# device_resolution = (480, 160) # for Revo
# device_resolution = (320, 240) # for many Windows Mobile handsets
# bmconv_command = "Bmconv.exe"
# bmconv_command = "wine Bmconv.exe"
# bmconv_command = "cp /other/downloads/bmconv/Bmconv.exe . && wine Bmconv.exe"
bmconv_command = "~/bin/Bmconv.exe"
# The following variables are used for setting the
# font size etc of TeX files, and are ignored for
# .ps files which the program assumes are already
# at your desired size :
lines_per_screen = 3 # number of lines you want
# to fit on the screen at a time
# (if not integer, leading can be added)
baseSize_points = 25 # the font size of the
# document at the moment (e.g. 25 if you're
# using \huge in 12pt, see latex-papersize.py)
documentClass = "\\documentclass[12pt]{article}"
max_symbol_height = 1.67 # the number of (document) lines
# that the biggest symbol will take - this will
# be used to make one screen line
path_to_latexPapersize = "/usr/local/bin/latex-papersize.py"
# Make sure to point this at a latex-papersize.py,
# must be at least version 1.4
just_print_Bmconv_commands = False # if non-False,
# should be open("some-file","w") - will just
# print the bmconv.exe commands to that file,
# rather than trying to run them (and will not
# delete the temporary *.bmp files they need).
also_make_HTML_files = False
also_make_compressed_XBM = False
leave_tex_logs = False # set if you don't want them deleted
# --- End of variables that need changing -----
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Where to find history:
# on GitHub at https://github.com/ssb22/scan-reflow
# and on GitLab at https://gitlab.com/ssb22/scan-reflow
# and on BitBucket https://bitbucket.org/ssb22/scan-reflow
# and at https://gitlab.developers.cam.ac.uk/ssb22/scan-reflow
# and in China: https://gitee.com/ssb22/scan-reflow
import os, re
baseFilename = "font"
dpi_to_set_at = 100 # regardless of actual device DPI - be nice to metafont
papersize_px = (device_resolution[0],device_resolution[1]/lines_per_screen)
fontsize_px = papersize_px[1] / max_symbol_height
fontsize_pt = fontsize_px * 72.0 / dpi_to_set_at
papersize_mm = tuple(map(lambda x: x*25.4/dpi_to_set_at, papersize_px))
latex_paper_command = "margin_left=0 margin_top=0 paper_width="+str(papersize_mm[0])+" paper_height="+str(papersize_mm[1])+" python \""+path_to_latexPapersize+"\" "+str(baseSize_points)+" "+str(fontsize_pt)+" "
assert open(path_to_latexPapersize), "path_to_latexPapersize does not appear to be set properly" # (more likely to raise IOError than AssertionError, but still)
startString = documentClass + os.popen(latex_paper_command+"tex").read()
startString += "\\usepackage[T1]{fontenc}" # hack to ensure uses bitmaps not outlines in teTeX 2+ (not needed in teTeX 1)
tempDir = os.popen("mktemp -d").read().strip()
texToCharNo = {} ; charNoToTex = {} ; charNoToFlag = {}
bmconv_params = []
seq=open("sequence.dat","w")
contents = open("contents.dat","w")
oldDir = os.getcwd()
first_file_preamble = last_file_end = None
def lsbmsb16(num): return chr(num%256)+chr(num/256)
def lsbmsb32(num): return lsbmsb16(num%65536)+lsbmsb16(num/65536)
for inputFile in sys.argv[1:]:
dat = open(inputFile).read().replace("\r\n","\n")
if not first_file_preamble:
first_file_preamble=dat[:dat.index("\n%StartWord\n")]+"\n"
for thing in "documentclass textwidth textheight topmargin marginparwidth oddsidemargin evensidemargin".split(): assert not "\\"+thing in first_file_preamble, "TeX files must NOT contain \\"+thing+" (this will be added by the script)"
else: assert first_file_preamble==dat[:dat.index("\n%StartWord\n")]+"\n", "All TeX files must contain identical material before the first %StartWord"
last_file_end = dat[dat.rindex("\n%EndWord\n"):]
if also_make_HTML_files:
fileNo = contents.tell()/4
htmlFile=open("%05d.html" % fileNo,"w")
htmlFile.write("<HTML><BODY>\n")
contents.write(lsbmsb32(seq.tell()))
for word in dat.split("\n%StartWord\n")[1:]:
word += "\n" ; word=word[:word.index("\n%EndWord\n")+1] # +1 to include the \n
if not word.strip(): continue # ignore any completely-blank 'words'
if word not in texToCharNo:
c=len(texToCharNo)
charNoToTex[c]=word
if "%Colour" in word: charNoToFlag[c]="/c4"
elif "%Grey" in word: charNoToFlag[c]="/2"
else: charNoToFlag[c]="/1"
texToCharNo[word]=c
seq.write(lsbmsb16(texToCharNo[word]))
if also_make_HTML_files: htmlFile.write("<IMG SRC=%08d.png>\n" % texToCharNo[word])
if also_make_HTML_files:
htmlFile.write("<BR>")
if not inputFile==sys.argv[-1]: htmlFile.write("<A HREF=%05d.html>Next</A>\n" % (fileNo+1))
if fileNo: htmlFile.write("<A HREF=%05d.html>Previous</A>\n" % (fileNo-1))
htmlFile.write("</BODY></HTML>")
htmlFile.close()
l = charNoToTex.items() ; l.sort()
os.chdir(tempDir)
open("tmp.tex","w").write(startString+first_file_preamble+"\n".join(map(lambda (x,y): y, l))+last_file_end)
ret = os.system("latex tmp.tex")
assert not ret, "TeX error"
ret = os.system(os.popen(latex_paper_command+"tmp.dvi").read().strip()+" -o tmp.ps -D "+str(dpi_to_set_at))
assert not ret, "dvips error"
print "Running gs to get PNGs"
ret = os.system("gs -sDEVICE=png16 -sOutputFile=tmp%%08d.png -g%dx%d -r%dx%d -q -dNOPAUSE - < tmp.ps" % (papersize_px[0],papersize_px[1],dpi_to_set_at,dpi_to_set_at))
assert not ret, "gs error"
print "Trimming PNGs"
pngs = os.listdir(os.getcwd()) ; pngs.sort()
assert len(pngs)>=len(texToCharNo), "Not enough pages were generated (maybe some of your words did not actually generate pages?)"
count = 0
for f in pngs:
if count==len(texToCharNo): break # already had enough pages - rest is probably a blank one at the end
if not f.endswith(".png"): continue # ignore
dat=os.popen('pngtopnm "'+f+'" | pnmcrop -white -left -right -bottom').read() # (don't crop top because we're using it for alignment)
if not dat: continue # maybe it was a blank page (pnmcrop error) - ignore it
flag = charNoToFlag[count]
fname="%08d.bmp" % count
bmconv_params.append(flag+fname)
if also_make_HTML_files: os.popen("pnmtopng -compression 9 > \""+oldDir+os.sep+("%08d.png" % count)+"\"","w").write(dat)
if also_make_compressed_XBM: os.popen("ppmtopgm|pgmtopbm -threshold | pbmtoxbm > \""+oldDir+os.sep+("%08d.xbm" % count)+"\"","w").write(dat)
count += 1
os.popen("ppmtobmp > "+fname,"w").write(dat)
print "Done",count,"of",len(texToCharNo)
if not leave_tex_logs: os.system("find . -name 'tmp*' | xargs rm") # leaves the .bmp files
AllUnique = (seq.tell()/2 == len(texToCharNo))
ContentsNotNeeded = (contents.tell() == 4) # only 1 document
del texToCharNo, charNoToTex, charNoToFlag, contents, seq
startPoints=range(0,len(bmconv_params),510)+[len(bmconv_params)]
for i in range(len(startPoints)-1):
if i==0: extra=""
else: extra=hex(i)[2:].upper() # (drop '0x' at beginning)
this_cmd = bmconv_command+" "+baseFilename+extra+".mbm "+' '.join(bmconv_params[startPoints[i]:startPoints[i+1]])
if just_print_Bmconv_commands: just_print_Bmconv_commands.write(this_cmd+"\n")
else:
ret=os.system(this_cmd)
assert not ret, "bmconv_command exitted with an error"
os.system("mv "+baseFilename+extra+".mbm \""+oldDir+"\"")
os.chdir(oldDir)
# clean up, zip, print report
toPrint = ["\n--------------------------"] ; toZip = []
if ContentsNotNeeded:
toPrint.append("Didn't make contents.dat, as there was only one input document")
os.remove("contents.dat")
else:
toPrint.append("Made contents.dat")
toZip.append("contents.dat")
AllUnique = False # because we DO make sequence.dat if we made contents.dat
if AllUnique:
toPrint.append("Didn't make sequence.dat, as all images were unique")
os.remove("sequence.dat")
else:
toPrint.append("Made sequence.dat")
toZip.append("sequence.dat")
if just_print_Bmconv_commands:
print "\n".join(toPrint)
print "Made bmconv commands (which should be run using the *.bmp files in %s)" % (tempDir,)
else:
os.system("rm -rf \"%s\"" % (tempDir,))
toPrint.append("Made "+baseFilename+"*.mbm")
toZip.append(baseFilename+"*.mbm")
assert not " " in baseFilename, "you'll be sorry..."
os.system("zip -9 to-epoc.zip "+" ".join(toZip)+" && rm "+" ".join(toZip))
print "\n".join(toPrint)
print "Zipped into to-epoc.zip for transfer to the device"
if also_make_HTML_files: os.system("echo zipping HTML files... && find . -maxdepth 1 -name '*.png' -o -name '*.html' | xargs zip -9q htmlfiles.zip && find . -maxdepth 1 '(' -name '*.png' -o -name '*.html' ')' -exec rm '{}' ';' && echo Made htmlfiles.zip")
if also_make_compressed_XBM:
i=0 ; dat=[]
while True:
try:
dat.append(zlib.compress(open(("%08d.xbm" % i),"rb").read()))
os.remove("%08d.xbm" % i)
except: break
i += 1
o=open("images.dat","wb")
offset=4*(len(dat)+1)
def writeOffset(o,offset): o.write(chr(offset&255)+chr((offset>>8)&255)+chr((offset>>16)&255)+chr((offset>>24)&255))
for d in dat:
writeOffset(o,offset)
offset += len(d)
writeOffset(o,offset)
for d in dat: o.write(d)
print "Made images.dat (compressed XBM for XBMshow.py)"