1if not modules then modules = { } end modules [ ' font-otr ' ] = {
2 version = 1 . 001 ,
3 comment = " companion to font-ini.mkiv " ,
4 author = " Hans Hagen, PRAGMA-ADE, Hasselt NL " ,
5 copyright = " PRAGMA ADE / ConTeXt Development Team " ,
6 license = " see context related readme files "
7}
8
9
10
11
12
13
14
15local ioopen = io . open
16local replacesuffix = file . replacesuffix
17
18local readers = fonts and fonts . handlers . otf . readers
19
20local streamreader = readers and readers . streamreader or utilities . files
21local streamwriter = readers and readers . streamwriter or utilities . files
22
23local readstring = streamreader . readstring
24local readcardinal2 = streamreader . readcardinal2
25local readcardinal4 = streamreader . readcardinal4
26local getsize = streamreader . getsize
27local setposition = streamreader . setposition
28local getposition = streamreader . getposition
29
30local writestring = streamwriter . writestring
31local writecardinal4 = streamwriter . writecardinal4
32local writecardinal2 = streamwriter . writecardinal2
33local writebyte = streamwriter . writebyte
34
35local decompress = zlib . decompress
36
37directives . register ( " fonts.streamreader " , function ( )
38
39 streamreader = utilities . streams
40
41 readstring = streamreader . readstring
42 readcardinal2 = streamreader . readcardinal2
43 readcardinal4 = streamreader . readcardinal4
44 getsize = streamreader . getsize
45 setposition = streamreader . setposition
46 getposition = streamreader . getposition
47
48end )
49
50local infotags = {
51 [ " os/2 " ] = true ,
52 [ " head " ] = true ,
53 [ " maxp " ] = true ,
54 [ " hhea " ] = true ,
55 [ " hmtx " ] = true ,
56 [ " post " ] = true ,
57 [ " cmap " ] = true ,
58}
59
60local report = logs . reporter ( " fonts " , " woff " )
61
62local runner = sandbox . registerrunner {
63 name = " woff2otf " ,
64 method = " execute " ,
65 program = " woff2_decompress " ,
66 template = " %inputfile% %outputfile% " ,
67 reporter = report ,
68 checkers = {
69 inputfile = " readable " ,
70 outputfile = " writable " ,
71 }
72}
73
74local function woff2otf ( inpname , outname , infoonly )
75
76 local outname = outname or replacesuffix ( inpname , " otf " )
77 local inp = ioopen ( inpname , " rb " )
78
79 if not inp then
80 report ( " invalid input file %a " , inpname )
81 return
82 end
83
84 local signature = readstring ( inp , 4 )
85
86 if not ( signature = = " wOFF " or signature = = " wOF2 " ) then
87 inp : close ( )
88 report ( " invalid signature in %a " , inpname )
89 return
90 end
91
92 local flavor = readstring ( inp , 4 )
93
94 if not ( flavor = = " OTTO " or flavor = = " true " or flavor = = " \0\1\0\0 " ) then
95 inp : close ( )
96 report ( " unsupported flavor %a in %a " , flavor , inpname )
97 return
98 end
99
100 if signature = = " wOF2 " then
101 inp : close ( )
102 if false then
103 if runner then
104 runner {
105 inputfile = inpname ,
106 outputfile = outname ,
107 }
108 end
109 return outname , flavor
110 else
111 report ( " skipping version 2 file %a " , inpname )
112 return
113 end
114 end
115
116 local out = ioopen ( outname , " wb " )
117
118 if not out then
119 inp : close ( )
120 report ( " invalid output file %a " , outname )
121 return
122 end
123
124 local header = {
125 signature = signature ,
126 flavor = flavor ,
127 length = readcardinal4 ( inp ) ,
128 numtables = readcardinal2 ( inp ) ,
129 reserved = readcardinal2 ( inp ) ,
130 totalsfntsize = readcardinal4 ( inp ) ,
131 majorversion = readcardinal2 ( inp ) ,
132 minorversion = readcardinal2 ( inp ) ,
133 metaoffset = readcardinal4 ( inp ) ,
134 metalength = readcardinal4 ( inp ) ,
135 metaoriglength = readcardinal4 ( inp ) ,
136 privoffset = readcardinal4 ( inp ) ,
137 privlength = readcardinal4 ( inp ) ,
138 }
139
140 local entries = { }
141
142 for i = 1 , header . numtables do
143 local entry = {
144 tag = readstring ( inp , 4 ) ,
145 offset = readcardinal4 ( inp ) ,
146 compressed = readcardinal4 ( inp ) ,
147 size = readcardinal4 ( inp ) ,
148 checksum = readcardinal4 ( inp ) ,
149 }
150 if not infoonly or infotags [ lower ( entry . tag ) ] then
151 entries [ # entries + 1 ] = entry
152 end
153 end
154
155 local nofentries = # entries
156 local entryselector = 0
157 local searchrange = 0
158 local rangeshift = 0
159
160 writestring ( out , flavor )
161 writecardinal2 ( out , nofentries )
162 writecardinal2 ( out , entryselector )
163 writecardinal2 ( out , searchrange )
164 writecardinal2 ( out , rangeshift )
165
166 local offset = 12 + nofentries * 16
167 local offsets = { }
168
169 for i = 1 , nofentries do
170 local entry = entries [ i ]
171 local size = entry . size
172 writestring ( out , entry . tag )
173 writecardinal4 ( out , entry . checksum )
174 writecardinal4 ( out , offset )
175 writecardinal4 ( out , size )
176 offsets [ i ] = offset
177 offset = offset + size
178 local p = 4 - offset % 4
179 if p > 0 then
180 offset = offset + p
181 end
182 end
183
184 for i = 1 , nofentries do
185 local entry = entries [ i ]
186 local offset = offsets [ i ]
187 local size = entry . size
188 setposition ( inp , entry . offset + 1 )
189 local data = readstring ( inp , entry . compressed )
190 if # data ~ = size then
191 data = decompress ( data )
192 end
193 setposition ( out , offset + 1 )
194 writestring ( out , data )
195 local p = 4 - offset + size % 4
196 if p > 0 then
197 for i = 1 , p do
198 writebyte ( out , 0 )
199 end
200 end
201 end
202
203 inp : close ( )
204 out : close ( )
205
206 return outname , flavor
207
208end
209
210if readers then
211 readers . woff2otf = woff2otf
212else
213 return woff2otf
214end
215 |