1 // -*- related-file-name: "../include/efont/t1rw.hh" -*-
2 
3 /* t1rw.{cc,hh} -- Type 1 font reading and writing
4  *
5  * Copyright (c) 1998-2019 Eddie Kohler
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the Free
9  * Software Foundation; either version 2 of the License, or (at your option)
10  * any later version. This program is distributed in the hope that it will be
11  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
13  * Public License for more details.
14  */
15 
16 #ifdef HAVE_CONFIG_H
17 # include <config.h>
18 #endif
19 #include <efont/t1rw.hh>
20 #include <efont/t1cs.hh>
21 #include <lcdf/straccum.hh>
22 #include <stdlib.h>
23 #include <ctype.h>
24 #include <string.h>
25 namespace Efont {
26 
27 unsigned char Type1Reader::xvalue_store[257];
28 unsigned char *Type1Reader::xvalue = &Type1Reader::xvalue_store[1];
29 
30 void
static_initialize()31 Type1Reader::static_initialize()
32 {
33     if (xvalue['A'])
34         return;
35     // rely on static data being initialized to 0
36     xvalue['0'] = 0;  xvalue['1'] = 1;  xvalue['2'] = 2;  xvalue['3'] = 3;
37     xvalue['4'] = 4;  xvalue['5'] = 5;  xvalue['6'] = 6;  xvalue['7'] = 7;
38     xvalue['8'] = 8;  xvalue['9'] = 9;
39     xvalue['A'] = 10; xvalue['B'] = 11; xvalue['C'] = 12; xvalue['D'] = 13;
40     xvalue['E'] = 14; xvalue['F'] = 15;
41     xvalue['a'] = 10; xvalue['b'] = 11; xvalue['c'] = 12; xvalue['d'] = 13;
42     xvalue['e'] = 14; xvalue['f'] = 15;
43 }
44 
45 
Type1Reader()46 Type1Reader::Type1Reader()
47     : _data(new unsigned char[DATA_SIZE]), _len(0), _pos(0),
48       _ungot(-1), _eexec(false)
49 {
50     static_initialize();
51 }
52 
~Type1Reader()53 Type1Reader::~Type1Reader()
54 {
55     delete[] _data;
56 }
57 
58 
59 void
set_charstring_definer(PermString x)60 Type1Reader::set_charstring_definer(PermString x)
61 {
62     _charstring_definer = x;
63 }
64 
65 void
switch_eexec(bool on,unsigned char * data,int len)66 Type1Reader::switch_eexec(bool on, unsigned char *data, int len)
67 {
68     if (on) {
69         if (_pos < len + 3) {
70             unsigned char *new_data = new unsigned char[len + 3 + DATA_SIZE];
71             assert(_len <= DATA_SIZE);
72             memcpy(new_data + len + 3, _data + _pos, _len - _pos);
73             _len = len + 3 + _len - _pos;
74             _pos = len + 3;
75             delete[] _data;
76             _data = new_data;
77         }
78         int original_pos = _pos;
79         // don't forget _ungot!!
80         if (_ungot >= 0)
81             _data[--_pos] = _ungot, _ungot = -1;
82         if (_crlf == 0 || _crlf == 2)
83             _data[--_pos] = '\n';
84         if (_crlf == 1 || _crlf == 2)
85             _data[--_pos] = '\r';
86         memcpy(_data + _pos - len, data, len);
87         _pos -= len;
88         start_eexec(original_pos - _pos);
89     }
90     _eexec = on;
91 }
92 
93 
94 int
more_data()95 Type1Reader::more_data()
96 {
97     _pos = 0;
98     _len = more_data(_data, DATA_SIZE);
99     if (_len < 0)
100         return -1;
101     else
102         return _data[_pos++];
103 }
104 
105 
106 inline int
get_base()107 Type1Reader::get_base()
108 {
109     if (_pos >= _len)
110         return more_data();
111     else
112         return _data[_pos++];
113 }
114 
115 
116 inline int
eexec(int c)117 Type1Reader::eexec(int c)
118 {
119     unsigned char answer = (unsigned char)(c ^ (_r >> 8));
120     _r = (((unsigned char)c + _r) * (uint32_t) t1C1 + t1C2) & 0xFFFF;
121     return answer;
122 }
123 
124 
125 int
ascii_eexec_get()126 Type1Reader::ascii_eexec_get()
127 {
128     int d1 = get_base();
129     while (isspace(d1))
130         d1 = get_base();
131 
132     int d2 = get_base();
133     while (isspace(d2))
134         d2 = get_base();
135     if (d2 < 0)
136         return -1;
137 
138     return eexec((xvalue[d1] << 4) | (xvalue[d2]));
139 }
140 
141 
142 inline int
get()143 Type1Reader::get()
144 {
145     if (!_eexec)
146         return get_base();
147 
148     else if (_binary_eexec) {
149         int c = get_base();
150         return c < 0 ? c : eexec(c);
151 
152     } else
153         return ascii_eexec_get();
154 }
155 
156 
157 void
start_eexec(int initial_ascii)158 Type1Reader::start_eexec(int initial_ascii)
159 {
160     /* God damn this _ungot thing!! It makes sense not to check it on every
161        char fetch, since it can only be set at the end of next_line; therefore,
162        only the first get() into a user-visible function might need to check
163        _ungot. The problem is I forgot start_eexec() was such a function! */
164     int c = _ungot < 0 ? get_base() : _ungot;
165     initial_ascii--;
166     _ungot = -1;
167 
168     /* Strictly speaking, I should look for whitespace even in binary sections
169        of PFB fonts; but it turns out some PFBs would be unreadable with that
170        pedantic rule. */
171     while (isspace(c) && (initial_ascii >= 0 || !preserve_whitespace()))
172         c = get_base(), initial_ascii--;
173 
174     /* Differentiate between ASCII eexec and binary eexec. */
175     int rand_bytes[4];
176     _binary_eexec = false;
177     for (int i = 0; i < 4; i++) {
178         if (i)
179             c = get_base();
180         rand_bytes[i] = c;
181         if (!isxdigit(c))
182             _binary_eexec = true;
183     }
184 
185     _r = t1R_ee;
186     if (_binary_eexec)
187         for (int i = 0; i < 4; i++)
188             eexec(rand_bytes[i]);
189     else {
190         for (int i = 0; i < 2; i++) {
191             c = xvalue[rand_bytes[i*2]] * 16 + xvalue[rand_bytes[i*2+1]];
192             eexec(c);
193         }
194         ascii_eexec_get();
195         ascii_eexec_get();
196     }
197 }
198 
199 
200 bool
test_charstring(StringAccum & str)201 Type1Reader::test_charstring(StringAccum &str)
202 {
203     /* PERFORMANCE NOTE: This function is definitely a bottleneck. Making it
204        more efficient cut time by about 40%. */
205 
206     if (!_charstring_definer)
207         return false;
208     if (_charstring_len >= 0)
209         return str.length() <= _charstring_start + _charstring_len;
210 
211     str.append('\0');           // protect against running off end of string
212     char *s = str.data();
213     char *start;
214     while (*s == ' ')
215         s++;
216 
217     if (s[0] == '/')
218         s++;
219     else if (s[0] == 'd' && s[1] == 'u' && s[2] == 'p' && isspace((unsigned char) s[3])) {
220         s += 4;
221         // 17.Jan.2000 -- some fonts have extra space here.
222         while (isspace((unsigned char) *s))
223             s++;
224     } else
225         goto not_charstring;
226 
227     // Force one literal space rather than isspace().
228     // Why? Consistency: we force 1 literal space around _charstring_definer.
229     while (*s != ' ' && *s)
230         s++;
231     if (*s++ != ' ' || !isdigit((unsigned char) *s))
232         goto not_charstring;
233     start = s;
234     s++;
235     while (*s != ' ' && *s)
236         s++;
237     if (strncmp(s, _charstring_definer.c_str(), _charstring_definer.length()) != 0)
238         goto not_charstring;
239 
240     _charstring_len = strtol(start, 0, 10);
241     _charstring_start = (s - str.data()) + _charstring_definer.length();
242     str.pop_back();
243     return str.length() <= _charstring_start + _charstring_len;
244 
245   not_charstring:
246     str.pop_back();
247     return false;
248 }
249 
250 
251 /* PERFORMANCE NOTE: All kinds of speedup tricks tried with eexec -- buffering
252    (doing eexec processing at more_data time), etc., and all this stuff -- and
253    found to have essentially zero effect for PFB fonts. Now, it might be
254    effective for PFAs; but who cares? I hate PFAs. */
255 
256 bool
next_line(StringAccum & s)257 Type1Reader::next_line(StringAccum &s)
258 {
259     if (_len < 0)
260         return false;
261 
262     // Can't be a charstring if incoming accumulator has nonzero length.
263     _charstring_start = 0;
264     _charstring_len = (s.length() > 0 ? 0 : -1);
265 
266     int first_char = _ungot < 0 ? get() : _ungot;
267     _ungot = -1;
268 
269     for (int c = first_char; c >= 0; c = get())
270         switch (c) {
271 
272           case '\n':
273             if (test_charstring(s))
274                 goto normal;
275             else {
276                 _crlf = 0;
277                 goto done;
278             }
279 
280           case '\r':
281             // check for \r\n (counts as only one line ending)
282             if (test_charstring(s))
283                 goto normal;
284             c = get();
285             if (c != '\n' || preserve_whitespace())
286                 _ungot = c, _crlf = 1;
287             else
288                 _crlf = 2;
289             goto done;
290 
291           normal:
292           default:
293             s.append((char)c);
294             break;
295 
296         }
297 
298   done:
299     return true;
300 }
301 
302 
303 int
get_data(unsigned char * data,int len)304 Type1Reader::get_data(unsigned char *data, int len)
305 {
306     if (_len < 0)
307         return -1;
308     if (len <= 0)
309         return 0;
310 
311     int pos = 0;
312     if (_ungot >= 0) {
313         *data++ = _ungot;
314         pos++;
315         _ungot = -1;
316     }
317 
318     for (; pos < len; pos++) {
319         int c = get();
320         if (c < 0)
321             break;
322         *data++ = c;
323     }
324 
325     return pos;
326 }
327 
328 
329 /*****
330  * Type1PFAReader
331  **/
332 
Type1PFAReader(FILE * f)333 Type1PFAReader::Type1PFAReader(FILE *f)
334     : _f(f)
335 {
336 }
337 
338 int
more_data(unsigned char * data,int len)339 Type1PFAReader::more_data(unsigned char *data, int len)
340 {
341     size_t size = fread(data, 1, len, _f);
342     return size ? (int)size : -1;
343 }
344 
345 
346 /*****
347  * Type1PFBReader
348  **/
349 
Type1PFBReader(FILE * f)350 Type1PFBReader::Type1PFBReader(FILE *f)
351     : _f(f), _binary(false), _left(0)
352 {
353 }
354 
355 int
more_data(unsigned char * data,int len)356 Type1PFBReader::more_data(unsigned char *data, int len)
357 {
358     while (_left == 0) {
359         int c = getc(_f);
360         if (c != 128)
361             return -1;
362 
363         c = getc(_f);
364         if (c == 3 || c < 1 || c > 3)
365             return -1;
366         _binary = (c == 2);
367 
368         _left = getc(_f);
369         _left |= getc(_f) << 8;
370         _left |= getc(_f) << 16;
371         _left |= getc(_f) << 24;
372     }
373 
374     if (_left < 0)
375         return -1;
376 
377     if (len > _left)
378         len = _left;
379     _left -= len;
380 
381     return fread(data, 1, len, _f);
382 }
383 
384 bool
preserve_whitespace() const385 Type1PFBReader::preserve_whitespace() const
386 {
387     return _binary;
388 }
389 
390 
391 /*****
392  * Type1SubsetReader
393  **/
394 
Type1SubsetReader(Type1Reader * r,int left)395 Type1SubsetReader::Type1SubsetReader(Type1Reader *r, int left)
396     : _reader(r), _left(left)
397 {
398 }
399 
400 int
more_data(unsigned char * data,int len)401 Type1SubsetReader::more_data(unsigned char *data, int len)
402 {
403     if (_left <= 0)
404         return -1;
405     if (len > _left)
406         len = _left;
407     int how_much = _reader->get_data(data, len);
408     if (how_much > 0)
409         _left -= how_much;
410     return how_much;
411 }
412 
413 bool
preserve_whitespace() const414 Type1SubsetReader::preserve_whitespace() const
415 {
416     return _reader->preserve_whitespace();
417 }
418 
419 
420 /*****
421  * Writer
422  **/
423 
Type1Writer()424 Type1Writer::Type1Writer()
425     : _buf(new unsigned char[BufSize]), _pos(0),
426       _eexec(false), _eexec_start(-1), _eexec_end(-1), _lenIV(4)
427 {
428 }
429 
430 
~Type1Writer()431 Type1Writer::~Type1Writer()
432 {
433     assert(!_pos);
434     delete[] _buf;
435 }
436 
437 
438 inline unsigned char
eexec(int p)439 Type1Writer::eexec(int p)
440 {
441     unsigned char c = ((unsigned char)p ^ (_r >> 8)) & 0xFF;
442     _r = ((c + _r) * (uint32_t) t1C1 + t1C2) & 0xFFFF;
443     return c;
444 }
445 
446 
447 void
flush()448 Type1Writer::flush()
449 {
450     local_flush();
451 }
452 
453 
454 /* PERFORMANCE NOTE: Doing eexec processing during flush -- which streamlines
455    code for the print() methods -- seems to save some time (4-5%). It also
456    makes write performance more consistent. But I have mixed feelings. */
457 
458 void
local_flush()459 Type1Writer::local_flush()
460 {
461     if (_eexec_start >= 0 && _eexec_end < 0)
462         _eexec_end = _pos;
463     for (int p = _eexec_start; p < _eexec_end; p++)
464         _buf[p] = eexec(_buf[p]);
465     print0(_buf, _pos);
466     _pos = 0;
467     _eexec_start = _eexec ? 0 : -1;
468     _eexec_end = -1;
469 }
470 
471 
472 void
print(const char * s,int n)473 Type1Writer::print(const char *s, int n)
474 {
475     while (n > 0) {
476         if (_pos >= BufSize)
477             local_flush();
478         int copy = BufSize - _pos;
479         if (copy > n) copy = n;
480         memcpy(_buf + _pos, s, copy);
481         _pos += copy;
482         s += copy;
483         n -= copy;
484     }
485 }
486 
487 
488 Type1Writer &
operator <<(int x)489 Type1Writer::operator<<(int x)
490 {
491     char str[128];
492     sprintf(str, "%d", x);
493     print(str, strlen(str));
494     return *this;
495 }
496 
497 
498 Type1Writer &
operator <<(double x)499 Type1Writer::operator<<(double x)
500 {
501     char str[256];
502     sprintf(str, "%g", x);
503     print(str, strlen(str));
504     return *this;
505 }
506 
507 
508 void
switch_eexec(bool on)509 Type1Writer::switch_eexec(bool on)
510 {
511     _eexec = on;
512     if (_eexec) {
513         _eexec_start = _pos;
514         _r = t1R_ee;
515         print("SUCK", 4);
516     } else
517         _eexec_end = _pos;
518 }
519 
520 
521 /*****
522  * Type1PFAWriter
523  **/
524 
Type1PFAWriter(FILE * f)525 Type1PFAWriter::Type1PFAWriter(FILE *f)
526     : _f(f), _hex_line(0)
527 {
528 }
529 
~Type1PFAWriter()530 Type1PFAWriter::~Type1PFAWriter()
531 {
532     flush();
533 }
534 
535 
536 void
switch_eexec(bool on)537 Type1PFAWriter::switch_eexec(bool on)
538 {
539     flush();
540     _hex_line = 0;
541     Type1Writer::switch_eexec(on);
542 }
543 
544 void
print0(const unsigned char * c,int l)545 Type1PFAWriter::print0(const unsigned char *c, int l)
546 {
547     if (eexecing()) {
548         const char *hex = "0123456789ABCDEF";
549         for (; l; c++, l--) {
550             putc(hex[*c / 16], _f);
551             putc(hex[*c % 16], _f);
552             if (++_hex_line == 39) {
553                 putc('\n', _f);
554                 _hex_line = 0;
555             }
556         }
557     } else {
558         ssize_t result = fwrite(c, 1, l, _f);
559         (void) result;
560     }
561 }
562 
563 
564 /*****
565  * Type1PFBWriter
566  **/
567 
Type1PFBWriter(FILE * f)568 Type1PFBWriter::Type1PFBWriter(FILE *f)
569     : _f(f), _binary(false)
570 {
571 }
572 
~Type1PFBWriter()573 Type1PFBWriter::~Type1PFBWriter()
574 {
575     flush();
576     fputc(128, _f);
577     fputc(3, _f);
578 }
579 
580 void
flush()581 Type1PFBWriter::flush()
582 {
583     Type1Writer::flush();
584     if (_save.length()) {
585         fputc(128, _f);
586         fputc(_binary ? 2 : 1, _f);
587         long l = _save.length();
588         fputc(l & 0xFF, _f);
589         fputc((l >> 8) & 0xFF, _f);
590         fputc((l >> 16) & 0xFF, _f);
591         fputc((l >> 24) & 0xFF, _f);
592         ssize_t result = fwrite(_save.data(), 1, _save.length(), _f);
593         (void) result;
594         _save.clear();
595     }
596 }
597 
598 void
switch_eexec(bool on)599 Type1PFBWriter::switch_eexec(bool on)
600 {
601     flush();
602     Type1Writer::switch_eexec(on);
603     _binary = on;
604 }
605 
606 void
print0(const unsigned char * c,int l)607 Type1PFBWriter::print0(const unsigned char *c, int l)
608 {
609     char *m = _save.extend(l);
610     memcpy(m, c, l);
611 }
612 
613 }
614