1 #include "sfnt.h"
2 #include "sfnt_int.h"
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <errno.h>
7 #include <assert.h>
8 #include "bitset.h"
9
otf_ttc_extract(OTF_FILE * otf,OUTPUT_FN output,void * context)10 int otf_ttc_extract(OTF_FILE *otf,OUTPUT_FN output,void *context) // {{{
11 {
12 assert(otf);
13 assert(output);
14 assert(otf->numTTC);
15 int iA;
16
17 struct _OTF_WRITE *otw;
18 otw=malloc(sizeof(struct _OTF_WRITE)*otf->numTables);
19 if (!otw) {
20 fprintf(stderr,"Bad alloc: %s\n", strerror(errno));
21 return -1;
22 }
23
24 // just copy everything
25 for (iA=0;iA<otf->numTables;iA++) {
26 otw[iA].tag=otf->tables[iA].tag;
27 otw[iA].action=otf_action_copy;
28 otw[iA].param=otf;
29 otw[iA].length=iA;
30 }
31 iA=otf_write_sfnt(otw,otf->version,otf->numTables,output,context);
32 free(otw);
33
34 return iA;
35 }
36 // }}}
37
38 // otw {0,}-terminated, will be modified; returns numTables for otf_write_sfnt
otf_intersect_tables(OTF_FILE * otf,struct _OTF_WRITE * otw)39 int otf_intersect_tables(OTF_FILE *otf,struct _OTF_WRITE *otw) // {{{
40 {
41 int iA,iB,numTables=0;
42 for (iA=0,iB=0;(iA<otf->numTables)&&(otw[iB].tag);) {
43 if (otf->tables[iA].tag==otw[iB].tag) {
44 if (otw[iB].action==otf_action_copy) {
45 otw[iB].length=iA; // original table location found.
46 }
47 if (iB!=numTables) { // >, actually
48 memmove(otw+numTables,otw+iB,sizeof(struct _OTF_WRITE));
49 }
50 iA++;
51 iB++;
52 numTables++;
53 } else if (otf->tables[iA].tag<otw[iB].tag) {
54 iA++;
55 } else { // not in otf->tables
56 if (otw[iB].action!=otf_action_copy) { // keep
57 if (iB!=numTables) { // >, actually
58 memmove(otw+numTables,otw+iB,sizeof(struct _OTF_WRITE));
59 }
60 numTables++;
61 } // else delete
62 iB++;
63 }
64 }
65 return numTables;
66 }
67 // }}}
68
69
70 // include components (set bit in >glyphs) of currently loaded compound glyph (with >curgid)
71 // returns additional space requirements (when bits below >donegid are touched)
otf_subset_glyf(OTF_FILE * otf,int curgid,int donegid,BITSET glyphs)72 static int otf_subset_glyf(OTF_FILE *otf,int curgid,int donegid,BITSET glyphs) // {{{
73 {
74 int ret=0;
75 if (get_SHORT(otf->gly)>=0) { // not composite
76 return ret; // done
77 }
78
79 char *cur=otf->gly+10;
80
81 unsigned short flags;
82 do {
83 flags=get_USHORT(cur);
84 const unsigned short sub_gid=get_USHORT(cur+2);
85 assert(sub_gid<otf->numGlyphs);
86 if (!bit_check(glyphs,sub_gid)) {
87 // bad: temporarily load sub glyph
88 const int len=otf_get_glyph(otf,sub_gid);
89 assert(len>0);
90 bit_set(glyphs,sub_gid);
91 if (sub_gid<donegid) {
92 ret+=len;
93 ret+=otf_subset_glyf(otf,sub_gid,donegid,glyphs); // composite of composites?, e.g. in DejaVu
94 }
95 const int res=otf_get_glyph(otf,curgid); // reload current glyph
96 assert(res);
97 }
98
99 // skip parameters
100 cur+=6;
101 if (flags&0x01) {
102 cur+=2;
103 }
104 if (flags&0x08) {
105 cur+=2;
106 } else if (flags&0x40) {
107 cur+=4;
108 } else if (flags&0x80) {
109 cur+=8;
110 }
111 } while (flags&0x20); // more components
112
113 return ret;
114 }
115 // }}}
116
117 // TODO: cmap only required in non-CID context
otf_subset(OTF_FILE * otf,BITSET glyphs,OUTPUT_FN output,void * context)118 int otf_subset(OTF_FILE *otf,BITSET glyphs,OUTPUT_FN output,void *context) // {{{ - returns number of bytes written
119 {
120 assert(otf);
121 assert(glyphs);
122 assert(output);
123
124 int iA,b,c;
125
126 // first pass: include all required glyphs
127 bit_set(glyphs,0); // .notdef always required
128 int glyfSize=0;
129 for (iA=0,b=0,c=1;iA<otf->numGlyphs;iA++,c<<=1) {
130 if (!c) {
131 b++;
132 c=1;
133 }
134 if (glyphs[b]&c) {
135 int len=otf_get_glyph(otf,iA);
136 if (len<0) {
137 assert(0);
138 return -1;
139 } else if (len>0) {
140 glyfSize+=len;
141 len=otf_subset_glyf(otf,iA,iA,glyphs);
142 if (len<0) {
143 assert(0);
144 return -1;
145 }
146 glyfSize+=len;
147 }
148 }
149 }
150
151 // second pass: calculate new glyf and loca
152 int locaSize=(otf->numGlyphs+1)*(otf->indexToLocFormat+1)*2;
153
154 char *new_loca=malloc(locaSize);
155 char *new_glyf=malloc(glyfSize);
156 if ( (!new_loca)||(!new_glyf) ) {
157 fprintf(stderr,"Bad alloc: %s\n", strerror(errno));
158 assert(0);
159 free(new_loca);
160 free(new_glyf);
161 return -1;
162 }
163
164 int offset=0;
165 for (iA=0,b=0,c=1;iA<otf->numGlyphs;iA++,c<<=1) {
166 if (!c) {
167 b++;
168 c=1;
169 }
170
171 assert(offset%2==0);
172 // TODO? change format? if glyfSize<0x20000
173 if (otf->indexToLocFormat==0) {
174 set_USHORT(new_loca+iA*2,offset/2);
175 } else { // ==1
176 set_ULONG(new_loca+iA*4,offset);
177 }
178
179 if (glyphs[b]&c) {
180 const int len=otf_get_glyph(otf,iA);
181 assert(len>=0);
182 memcpy(new_glyf+offset,otf->gly,len);
183 offset+=len;
184 }
185 }
186 // last entry
187 if (otf->indexToLocFormat==0) {
188 set_USHORT(new_loca+otf->numGlyphs*2,offset/2);
189 } else { // ==1
190 set_ULONG(new_loca+otf->numGlyphs*4,offset);
191 }
192 assert(offset==glyfSize);
193
194 // determine new tables.
195 struct _OTF_WRITE otw[]={ // sorted
196 // TODO: cmap only required in non-CID context or always in CFF
197 {OTF_TAG('c','m','a','p'),otf_action_copy,otf,},
198 {OTF_TAG('c','v','t',' '),otf_action_copy,otf,},
199 {OTF_TAG('f','p','g','m'),otf_action_copy,otf,},
200 {OTF_TAG('g','l','y','f'),otf_action_replace,new_glyf,glyfSize},
201 {OTF_TAG('h','e','a','d'),otf_action_copy,otf,}, // _copy_head
202 {OTF_TAG('h','h','e','a'),otf_action_copy,otf,},
203 {OTF_TAG('h','m','t','x'),otf_action_copy,otf,},
204 {OTF_TAG('l','o','c','a'),otf_action_replace,new_loca,locaSize},
205 {OTF_TAG('m','a','x','p'),otf_action_copy,otf,},
206 {OTF_TAG('n','a','m','e'),otf_action_copy,otf,},
207 {OTF_TAG('p','r','e','p'),otf_action_copy,otf,},
208 // vhea vmtx (never used in PDF, but possible in PS>=3011)
209 {0,0,0,0}};
210
211 // and write them
212 int numTables=otf_intersect_tables(otf,otw);
213 int ret=otf_write_sfnt(otw,otf->version,numTables,output,context);
214
215 free(new_loca);
216 free(new_glyf);
217 return ret;
218
219 //TODO ? reduce cmap [to (1,0) ;-)]
220 //TODO (cmap for non-cid)
221 }
222 // }}}
223
224 // TODO no subsetting actually done (for now)
otf_subset_cff(OTF_FILE * otf,BITSET glyphs,OUTPUT_FN output,void * context)225 int otf_subset_cff(OTF_FILE *otf,BITSET glyphs,OUTPUT_FN output,void *context) // {{{ - returns number of bytes written
226 {
227 assert(otf);
228 assert(output);
229
230 // TODO char *new_cff=cff_subset(...);
231
232 // determine new tables.
233 struct _OTF_WRITE otw[]={
234 {OTF_TAG('C','F','F',' '),otf_action_copy,otf,},
235 // {OTF_TAG('C','F','F',' '),otf_action_replace,new_glyf,glyfSize},
236 {OTF_TAG('c','m','a','p'),otf_action_copy,otf,},
237 #if 0 // not actually needed!
238 {OTF_TAG('c','v','t',' '),otf_action_copy,otf,},
239 {OTF_TAG('f','p','g','m'),otf_action_copy,otf,},
240 {OTF_TAG('h','e','a','d'),otf_action_copy,otf,}, // _copy_head
241 {OTF_TAG('h','h','e','a'),otf_action_copy,otf,},
242 {OTF_TAG('h','m','t','x'),otf_action_copy,otf,},
243 {OTF_TAG('m','a','x','p'),otf_action_copy,otf,},
244 {OTF_TAG('n','a','m','e'),otf_action_copy,otf,},
245 {OTF_TAG('p','r','e','p'),otf_action_copy,otf,},
246 #endif
247 {0,0,0,0}};
248
249 // and write them
250 int numTables=otf_intersect_tables(otf,otw);
251 int ret=otf_write_sfnt(otw,otf->version,numTables,output,context);
252
253 // free(new_cff);
254 return ret;
255 }
256 // }}}
257
258 //int copy_block(FILE *f,long pos,int length,OUTPUT_FN output,void *context); // copied bytes or -1 (also on premature EOF)
259
copy_block(FILE * f,long pos,int length,OUTPUT_FN output,void * context)260 static int copy_block(FILE *f,long pos,int length,OUTPUT_FN output,void *context) // {{{
261 {
262 assert(f);
263 assert(output);
264
265 char buf[4096];
266 int iA,ret;
267
268 ret=fseek(f,pos,SEEK_SET);
269 if (ret==-1) {
270 fprintf(stderr,"Seek failed: %s\n", strerror(errno));
271 return -1;
272 }
273 ret=0;
274 while (length>4096) {
275 iA=fread(buf,1,4096,f);
276 if (iA<4096) {
277 return -1;
278 }
279 (*output)(buf,iA,context);
280 ret+=iA;
281 length-=iA;
282 };
283 iA=fread(buf,1,length,f);
284 if (iA<length) {
285 return -1;
286 }
287 (*output)(buf,iA,context);
288 ret+=iA;
289
290 return ret;
291 }
292 // }}}
293
otf_cff_extract(OTF_FILE * otf,OUTPUT_FN output,void * context)294 int otf_cff_extract(OTF_FILE *otf,OUTPUT_FN output,void *context) // {{{ - returns number of bytes written
295 {
296 assert(otf);
297 assert(output);
298
299 int idx=otf_find_table(otf,OTF_TAG('C','F','F',' '));
300 if (idx==-1) {
301 return -1;
302 }
303 const OTF_DIRENT *table=otf->tables+idx;
304
305 return copy_block(otf->f,table->offset,table->length,output,context);
306 }
307 // }}}
308
309 // CFF *otf_get_cff(); // not load, but create by "substream"-in ctor
310 #if 0 // TODO elsewhere : char *cff_subset(...);
311 // first pass: include all required glyphs
312 bit_set(glyphs,0); // .notdef always required
313 int glyfSize=0;
314 for (iA=0,b=0,c=1;iA<otf->numGlyphs;iA++,c<<=1) {
315 if (!c) {
316 b++;
317 c=1;
318 }
319 if (glyphs[b]&c) {
320 // TODO: cff_glyph
321 }
322 }
323
324 // second pass: calculate new glyf and loca
325 char *new_cff=malloc(cffSize);
326 if (!new_cff) {
327 fprintf(stderr,"Bad alloc: %s\n", strerror(errno));
328 assert(0);
329 return -1;
330 }
331
332 int offset=0;
333 for (iA=0,b=0,c=1;iA<otf->numGlyphs;iA++,c<<=1) {
334 if (!c) {
335 b++;
336 c=1;
337 }
338 if (glyphs[b]&c) {
339 //...
340 }
341 }
342 return new_cff;
343 #endif
344