1 /*
2 * Header for the xfstt (X Font Server for TrueType) font engine
3 *
4 * Copyright © 1997-1998 Herbert Duerr
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the Free Softaware
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 */
21
22 #ifndef TTF_H
23 #define TTF_H
24
25 /*
26 * usage example to get font info, glyph extents and glyph bitmaps:
27 *
28 * raster = new Rasterizer();
29 * font = new TTFont("fontname.ttf");
30 * raster->getFontInfo(&fontInfo);
31 * raster->setPixelSize(20, 0, 0, 20);
32 * raster->getFontExtent(&fontExtent);
33 * delete font;
34 * delete raster;
35 *
36 */
37
38 #include "config.h"
39
40 #include <cassert>
41 #include <cstdint>
42 #include <cstdio>
43 #include <string>
44
45 #include "arch.h"
46
47 using std::string;
48
49 #ifndef DEBUG
50 # define debug(format, ...) while (0) { }
51 # define DEBUG_ATTR_UNUSED XFSTT_ATTR_UNUSED
52 # define STATIC static
53 #else
54 # define debug(format, ...) fprintf(stderr, format, ##__VA_ARGS__)
55 # define DEBUG_ATTR_UNUSED
56 # define STATIC
57 #endif
58
59 #ifndef MEMDEBUG
cleanupMem()60 inline void cleanupMem() {}
61 #else
62 void cleanupMem();
63 #endif
64
65 #ifndef MAGNIFY
66 extern int MAGNIFY;
67 #endif
68
69 class RandomAccessFile {
70 protected:
71 uint8_t *ptr, *base; // low offset for frequently used members
72
73 private:
74 uint8_t *absbase; // XXX: hack for fileOffset();
75 int length;
76
77 public:
78 RandomAccessFile(const char *fileName);
RandomAccessFile(RandomAccessFile & f,int offset,int _length)79 RandomAccessFile(RandomAccessFile &f, int offset, int _length) {
80 length = _length;
81 absbase = f.base;
82 ptr = base = f.base + offset;
83 }
84 // XXX: virtual ~RandomAccessFile() {}
85
openError()86 int openError() { return (absbase == nullptr); }
87 void closeRAFile();
88
reset()89 void reset() { ptr = base; }
seekAbsolute(int ofs)90 void seekAbsolute(int ofs) { ptr = base + ofs; }
seekRelative(int rel)91 void seekRelative(int rel) { ptr += rel; }
tell()92 int tell() { return (ptr - base); }
fileOffset()93 int fileOffset() { return (ptr - absbase); }
getLength()94 uint32_t getLength() { return length; }
95
96 uint32_t calcChecksum();
97
98 // these inlined functions are generic and should be optimized
99 // for specific processors (alignment, endianness, ...)
100
readSByte()101 int8_t readSByte() {
102 int8_t i = ptr[0];
103 ptr += 1;
104 return i;
105 }
readUByte()106 uint8_t readUByte() {
107 uint8_t i = ptr[0];
108 ptr += 1;
109 return i;
110 }
readSShort()111 int16_t readSShort() {
112 int16_t i = ptr[0];
113 i = (i << 8) | ptr[1];
114 ptr += 2;
115 return i;
116 }
readUShort()117 uint16_t readUShort() {
118 uint16_t i = ptr[0];
119 i = (i << 8) | ptr[1];
120 ptr += 2;
121 return i;
122 }
readSInt()123 int32_t readSInt() {
124 int32_t i = ptr[0];
125 i = (i << 8) | ptr[1];
126 i = (i << 8) | ptr[2];
127 i = (i << 8) | ptr[3];
128 ptr += 4;
129 return i;
130 }
readUInt()131 uint32_t readUInt() {
132 uint32_t i = ptr[0];
133 i = (i << 8) | ptr[1];
134 i = (i << 8) | ptr[2];
135 i = (i << 8) | ptr[3];
136 ptr += 4;
137 return i;
138 }
readSLong()139 int64_t readSLong() {
140 int64_t i = (int64_t)readSInt() << 32;
141 return i | readUInt();
142 }
readULong()143 uint64_t readULong() {
144 uint64_t i = (uint64_t)readUInt() << 32;
145 return i | readUInt();
146 }
147
writeByte(uint8_t byte)148 void writeByte(uint8_t byte) {
149 *(ptr++) = byte;
150 }
151 };
152
153 void *allocMem(int size); // mmaping allocation
154 void *shrinkMem(void *ptr, int newsize);
155 void deallocMem(void *ptr, int size);
156
157 class NameTable;
158 class HeadTable;
159 class MaxpTable;
160 class CmapTable;
161 class LocaTable;
162 class GlyphTable;
163 class Rasterizer;
164
165 class FpgmTable;
166 class PrepTable;
167
168 class HheaTable;
169 class HmtxTable;
170 class OS2Table;
171 class CvtTable;
172
173 class LtshTable;
174 class HdmxTable;
175 class VdmxTable;
176
177 class GaspTable;
178
179 class EbdtTable;
180 class EblcTable;
181 class EbscTable;
182
183 //class PclTable;
184 class KernTable;
185 //class PostTable;
186 class VheaTable;
187 class MortTable;
188
189 enum {
190 ON_CURVE = 1,
191 X_TOUCHED = 0x40,
192 Y_TOUCHED = 0x80,
193 END_SUBGLYPH = 0x100
194 };
195
196 struct Point {
197 int xnow, ynow;
198 int xold, yold;
199 int flags;
200 };
201
202 struct FontInfo {
203 uint16_t firstChar, lastChar;
204 uint8_t panose[10];
205 size_t faceLength;
206 char faceName[32];
207 };
208
209 // Table of Tables
210 class TTFont: public RandomAccessFile {
211 friend class Rasterizer;
212
213 public: // XXX: perftest needs maxpTable
214 NameTable *nameTable;
215 HeadTable *headTable;
216 MaxpTable *maxpTable;
217 CmapTable *cmapTable;
218 LocaTable *locaTable;
219 GlyphTable *glyphTable;
220
221 FpgmTable *fpgmTable;
222 PrepTable *prepTable;
223 CvtTable *cvtTable;
224
225 HheaTable *hheaTable;
226 HmtxTable *hmtxTable;
227 OS2Table *os2Table;
228
229 LtshTable *ltshTable;
230 HdmxTable *hdmxTable;
231 VdmxTable *vdmxTable;
232
233 GaspTable *gaspTable;
234 KernTable *kernTable;
235
236 EbdtTable *ebdtTable;
237 EblcTable *eblcTable;
238 MortTable *mortTable;
239 VheaTable *vheaTable;
240
241 enum {
242 NAME_MAGIC = 0x6E616D65,
243 HEAD_MAGIC = 0x68656164,
244 MAXP_MAGIC = 0x6D617870,
245 CMAP_MAGIC = 0x636D6170,
246 LOCA_MAGIC = 0x6C6F6361,
247 GLYF_MAGIC = 0x676C7966,
248 LTSH_MAGIC = 0x4C545348,
249 HDMX_MAGIC = 0x68646D78,
250 VDMX_MAGIC = 0x56444D58,
251 OS2_MAGIC = 0x4F532F32,
252 FPGM_MAGIC = 0x6670676D,
253 PREP_MAGIC = 0x70726570,
254 CVT_MAGIC = 0x63767420,
255 HHEA_MAGIC = 0x68686561,
256 VHEA_MAGIC = 0x76686570,
257 HMTX_MAGIC = 0x686D7478,
258 KERN_MAGIC = 0x6B65726E,
259 POST_MAGIC = 0x706F7374,
260 GASP_MAGIC = 0x67617370,
261 EBLC_MAGIC = 0x45424C43,
262 BLOC_MAGIC = 0x626C6F63,
263 EBDT_MAGIC = 0x45424454,
264 BDAT_MAGIC = 0x62646174,
265 MORT_MAGIC = 0x6D6F7274
266 };
267
268 int *endPoints;
269 Point *points;
270
271 public:
272 TTFont(const char *fileName, int infoOnly = 0);
273 ~TTFont();
274
275 int badFont();
276 void getFontInfo(FontInfo *fi);
277
278 int getGlyphNo8(char charNo);
279 int getGlyphNo16(int charNo);
280 int getEmUnits();
281
282 int getMaxWidth(int mppemx);
283 int getGlyphWidth(int mppemx, int glyphNo);
284 int getGlyphMetrics(int glyphNo);
285
286 string getXLFDbase(string xlfd_templ);
287
288 // for comparing with reference implementation
289 int patchGlyphCode(GlyphTable *glyph, int instruction);
290 int checksum(uint8_t *buf, int len);
291 void updateChecksums();
292 int write2File(const char *filename);
293 void patchName(uint8_t *patchData, int patchLength);
294 };
295
296 class NameTable: public RandomAccessFile {
297 int strBase;
298 int nRecords;
299
300 public:
301 NameTable(RandomAccessFile &f, int offset, int length);
302
303 enum {
304 NAME_COPYRIGHT = 0,
305 NAME_FAMILY = 1,
306 NAME_SUBFAMILY = 2,
307 NAME_UNIQUE = 3,
308 NAME_FULLNAME = 4,
309 NAME_VERSION = 5,
310 NAME_POSTSCRIPT = 6,
311 NAME_TRADEMARK = 7
312 };
313
314 string getString(int platformId, int strId);
315 };
316
317 // Font specific flags
318 class HeadTable: public RandomAccessFile {
319 uint32_t headMagic;
320
321 public: // XXX
322 uint32_t checksumAdj;
323 uint16_t flags;
324 uint16_t emUnits;
325 int16_t xmin, ymin;
326 int16_t xmax, ymax;
327 uint16_t macStyle;
328 uint16_t lowestPP;
329 uint16_t locaMode;
330
331 enum {
332 FONTCRC_MAGIC = 0xB1B0AFBA,
333 VALIDHEAD_MAGIC = 0x5F0F3CF5
334 };
335
336 enum {
337 Y_BASELINE = 1,
338 X_BASELINE = 2,
339 CODE_VARIES = 4,
340 FORCE_INT = 8,
341 WIDTH_VARIES = 16
342 };
343
344 enum {
345 BOLD = 1,
346 ITALIC = 2
347 };
348
349 public:
350 HeadTable(RandomAccessFile &f, int offset, int length);
351
shortLoca()352 int shortLoca() { return locaMode == 0; }
badHeadMagic()353 int badHeadMagic() { return headMagic != VALIDHEAD_MAGIC; }
354 };
355
356 // Font limits
357 class MaxpTable: public RandomAccessFile {
358 friend class TTFont;
359 friend class Rasterizer;
360
361 uint16_t numGlyphs;
362 uint16_t maxPoints;
363 uint16_t maxContours;
364
365 uint16_t maxCompPoints;
366 uint16_t maxCompContours;
367 uint16_t maxZones;
368 uint16_t maxTwilightPoints;
369 uint16_t maxStorage;
370 uint16_t maxFunctionDefs;
371 uint16_t maxInstructionDefs;
372 uint16_t maxStackSize;
373 uint16_t maxCodeSize;
374 uint16_t maxComponentElements;
375 uint16_t maxComponentDepth;
376
377 public:
378 MaxpTable(RandomAccessFile &f, int offset, int length);
379
getNumGlyphs()380 uint16_t getNumGlyphs() { return numGlyphs;}
381 };
382
383 // Character code to glyph number mapping
384 class CmapTable: public RandomAccessFile {
385 enum {
386 BYTE_ENCODING = 0,
387 HIGH_BYTE_MAPPING = 2,
388 SEGMENT_MAPPING = 4,
389 TRIMMED_MAPPING = 6
390 }; // format
391
392 int format;
393 int subtableOffset;
394 int f4NSegments;
395 int f6FirstCode;
396 int f6EntryCount;
397
398 public:
399 CmapTable(RandomAccessFile &f, int offset, int length);
400
401 int char2glyphNo(char char8);
402 int unicode2glyphNo(uint16_t unicode);
403
404 uint16_t nextUnicode(uint16_t unicode);
405 uint16_t firstUnicode();
406 uint16_t lastUnicode();
407 };
408
409 // Glyph number to glyph data offset mapping
410 class LocaTable: public RandomAccessFile {
411 int maxGlyph;
412 int isShort;
413
414 public:
415 LocaTable(RandomAccessFile &f, int offset, int length);
416
setupLoca(int _isShort,int _maxGlyph)417 void setupLoca(int _isShort, int _maxGlyph) {
418 isShort = _isShort;
419 maxGlyph = _maxGlyph;
420 }
421
422 int getGlyphOffset(int glyphNo);
423 };
424
425 // Glyph data
426 class GlyphTable: /*public*/ RandomAccessFile {
427 friend class Rasterizer;
428
429 int16_t xmin;
430 // int16_t xmin, ymin;
431 // int16_t xmax, ymax;
432
433 int codeOffset;
434 int codeLength;
435
436 public: // XXX: needed by verify.cpp
437 enum {
438 ON_CURVE = 0x01,
439 X_SHORT = 0x02,
440 Y_SHORT = 0x04,
441 F_SAME = 0x08,
442 X_EXT = 0x10,
443 Y_EXT = 0x20
444 };
445
446 int nEndPoints;
447 int *endPoints;
448 int nPoints;
449 Point *points;
450
451 public:
452 GlyphTable(RandomAccessFile &f, int offset, int length);
453
setupGlyph(Point * _points,int * _endPoints)454 void setupGlyph(Point *_points, int *_endPoints) {
455 endPoints = _endPoints;
456 points = _points;
457 }
458
459 int getGlyphData(int glyphOffset, LocaTable *locaTable, Rasterizer*);
460
461 private:
462 int getCompositeGlyphData(int gn, LocaTable *locaTable, Rasterizer*);
463
464 enum {
465 ARGS_ARE_WORDS = 0x0001,
466 ARGS_ARE_XY = 0x0002,
467 ROUND_XY_TO_GRID= 0x0004,
468 HAS_A_SCALE = 0x0008,
469 // reserved = 0x0010,
470 // NO_OVERLAP = 0x0010, which one is the right one?
471 MORE_COMPONENTS = 0x0020,
472 HAS_XY_SCALE = 0x0040,
473 HAS_2X2_SCALE = 0x0080,
474 HAS_CODE = 0x0100,
475 USE_MY_METRICS = 0x0200
476 };
477 };
478
479 // Hhea
480 class HheaTable: public RandomAccessFile {
481 friend class TTFont;
482 friend class Rasterizer;
483
484 int yAscent;
485 int yDescent;
486 int advWidth;
487 int minLeftBear;
488 int minRightBear;
489 int maxExtent;
490 int caretSlopeNum;
491 int caretSlopeDenom;
492 int isMetric;
493 int nLongHMetrics;
494
495 HheaTable(RandomAccessFile &f, int offset, int length);
496 };
497
498 // Hmtx
499 class HmtxTable: public RandomAccessFile {
500 int nHMetrics;
501 public:
502 HmtxTable(RandomAccessFile &f, int offset, int length);
503
setupHmtx(int h)504 void setupHmtx(int h) { nHMetrics = h; }
505 void getHMetrics(int glyphNo, int *advWidth, int *lsdBear);
506 };
507
508 // OS/2
509 class OS2Table: public RandomAccessFile {
510 public:
511 int16_t weightClass;
512 uint16_t avg_width;
513 uint8_t panose[10];
514 uint32_t unicodeRange[4];
515 uint16_t firstCharNo;
516 uint16_t lastCharNo;
517 uint16_t selection;
518 uint16_t typoAscent;
519 uint16_t typoDescent;
520 uint16_t typoGap;
521 uint16_t winAscent;
522 uint16_t winDescent;
523
524 enum UnicodeRangeFlags {
525 LATIN_0 = 0,
526 LATIN_1 = 1,
527 LATIN_A = 2,
528 LATIN_B = 3,
529 IPA_EXT = 4,
530 SPACE_MOD = 5,
531 DIAC_MARKS = 6,
532 GREEK_0 = 7,
533 GREEK_SYM = 8,
534 CYRILLIC = 9,
535 ARMENIAN = 10,
536 HEBREW_0 = 11,
537 HEBREW_AB = 12,
538 ARABIC_0 = 13,
539 ARABIC_1 = 14,
540 DEVANAGARI = 15,
541 BENGALI = 16,
542 GURMUKHI = 17,
543 GUJARATI = 18,
544 ORIYA = 19,
545 TAMIL = 20,
546 TELUGU = 21,
547 KANNADA = 22,
548 MALAYALAM = 23,
549 THAI = 24,
550 LAO = 25,
551 GEORGIAN_0 = 26,
552 GEORGIAN_1 = 27,
553 HANGUL_1 = 28,
554 LATIN_EA = 29,
555 GREEK_A = 30,
556 PUNCT_0 = 31,
557 SUBSUPER = 32,
558 CURRENCY = 33,
559 DIAC_SYM = 34,
560 LETTER = 35,
561 NUMFORMS = 36,
562 ARROWS = 37,
563 MATHOP = 38,
564 MISCTECH = 39,
565 CNTRLPIC = 40,
566 OCR = 41,
567 ENCALPHA = 42,
568 BOXDRAW = 43,
569 BOXELEM = 44,
570 GSHAPES = 45,
571 MISCSYMS = 46,
572 DINGBATS = 47,
573 CJK_SYMS = 48,
574 HIRAGANA = 49,
575 KATAGANA = 50,
576 BOPOMOFO = 51,
577 HANGUL_2 = 52,
578 CJK_MISC = 53,
579 CJK_ENC = 54,
580 CJK_COMP = 55,
581 HANGUL_0 = 56,
582 RESERVED1 = 57,
583 RESERVED2 = 58,
584 CJK_IDEO0 = 59,
585 PRIVATE = 60,
586 CJK_IDEO1 = 61,
587 ALF_PRES = 62,
588 ARB_PRES0 = 63,
589 HALFMARK = 64,
590 CJK_FORM = 65,
591 SFORMV = 66,
592 ARB_PRESB = 67,
593 WIDTHFORM = 68,
594 SPECIALS = 69
595 };
596
597 enum SelectionFlags {
598 ITALIC = 1,
599 UNDERSCORE = 2,
600 NEGATIVE = 4,
601 OUTLINED = 8,
602 STRIKEOUT = 16,
603 BOLD = 32,
604 REGULAR = 64
605 };
606 public:
607 OS2Table(RandomAccessFile &f, int offset, int length);
608 };
609
610 // LTSH
611 class LtshTable: public RandomAccessFile {
612 int numGlyphs;
613
614 public:
615 LtshTable(RandomAccessFile &f, int offset, int length);
616
617 int getLinearThreshold(int glyphNo);
618 };
619
620 // hdmx
621 class HdmxTable: public RandomAccessFile {
622 int nRecords;
623 int recordLen;
624
625 public:
626 HdmxTable(RandomAccessFile &f, int offset, int length);
627
628 int getMaxWidth(int mppemx);
629 int getGlyphWidth(int mppemx, int glyphNo);
630 };
631
632 // VDMX
633 class VdmxTable: public RandomAccessFile {
634 int nRecords;
635 int nRatios;
636
637 public:
638 VdmxTable(RandomAccessFile &f, int offset, int length);
639
640 int getYmax(int pelHeight, int xres, int yres, int *ymax, int *ymin);
641 };
642
643 // cvt
644 class CvtTable: public RandomAccessFile {
645 int nVals;
646
647 public:
648 CvtTable(RandomAccessFile &f, int offset, int length);
649
numVals()650 int numVals() { return nVals; }
nextVal()651 int nextVal() { return readSShort(); }
652 };
653
654 // fpgm
655 class FpgmTable: public RandomAccessFile {
656 friend class TTFont;
657
658 FpgmTable(RandomAccessFile &f, int offset, int length);
659 };
660
661 // prep
662 class PrepTable: public RandomAccessFile {
663 friend class TTFont;
664
665 PrepTable(RandomAccessFile &f, int offset, int length);
666 };
667
668 // gasp
669 class GaspTable: public RandomAccessFile {
670 int nRanges;
671
672 public:
673 GaspTable(RandomAccessFile &f, int offset, int length);
674
675 enum {
676 GASP_GRIDFIT = 1,
677 GASP_DOGRAY = 2
678 };
679
680 int getFlags(int mppem);
681 };
682
683 // Kern kerning table
684 class KernTable: public RandomAccessFile {
685 int kernOffset;
686 uint16_t nPairs;
687 uint16_t kernLength;
688 uint16_t coverage;
689
690 public:
691 KernTable(RandomAccessFile &f, int offset, int length);
692
693 enum {
694 HORIZONTAL = 1,
695 MINIMUM = 2,
696 CROSS = 4,
697 OVERRIDE = 8,
698 FORMAT = 0xff00
699 };
700
701 int getKerning(int leftChar, int rightChar);
702 };
703
704 struct FontExtent {
705 int xBlackboxMin, xBlackboxMax;
706 int yBlackboxMin, yBlackboxMax;
707 int xLeftMin, xLeftMax;
708 int xRightMin, xRightMax;
709 int yAscentMin, yAscentMax;
710 int yDescentMin, yDescentMax;
711 int xAdvanceMin, xAdvanceMax;
712 int yAdvanceMin, yAdvanceMax;
713 int yWinAscent, yWinDescent;
714
715 uint8_t *buffer; // hack
716 uint8_t *bitmaps; // hack
717 int buflen; // hack
718 int bmplen; // hack
719 int numGlyphs; // hack
720 int bmpFormat; // hack
721 // format of buffer:
722 // CharInfo[numGlyphs]
723 // bitmaps[numGlyphs]
724 };
725
726 struct GlyphMetrics {
727 int xBlackbox, yBlackbox;
728 int xOrigin, yOrigin;
729 int xAdvance, yAdvance;
730 };
731
732 struct CharInfo {
733 GlyphMetrics gm;
734 int offset;
735 int length;
736 int tmpofs; // scratchpad offset
737 };
738
739 // EBLC embedded bitmap locations
740 class EblcTable: public RandomAccessFile {
741 enum {
742 HORIZONTAL = 0x01,
743 VERTICAL = 0x02
744 };
745
746 public:
747 EblcTable(RandomAccessFile &f, int offset, int length);
748
749 void readStrike(int glyphNo, int _ppemx, int _ppemy);
750 void readSubTableArray(int glyphNo, int ofsSTA);
751 void readSubTable(int first, int last);
752 };
753
754 // EBDT embedded bitmap data
755 class EbdtTable: public RandomAccessFile {
756 public:
757 EbdtTable(RandomAccessFile &f, int offset, int length);
758
759 int readBitmap(int format, uint8_t *bitmap, GlyphMetrics *gm);
760 };
761
762 // EBSC embedded bitmap scaling info
763 class EbscTable: public RandomAccessFile {
764 public:
765 EbscTable(RandomAccessFile &f, int offset, int length);
766 };
767
768 class GraphicsState {
769 friend class Rasterizer; // only Rasterizer needs this
770
GraphicsState()771 GraphicsState() {}
772
773 void init(Point** p);
774 int absNewMeasure(int dx, int dy);
775 int absOldMeasure(int dx, int dy);
776 void movePoint(Point &pp, int len10D6);
777 void recalc();
778
779 int f_vec_x; // freedom vector
780 int p_vec_x; // projection vector
781 int dp_vec_x; // dual projection vector
782
783 int f_vec_y;
784 int p_vec_y;
785 int dp_vec_y;
786
787 int flags;
788 int move_x;
789 int move_y;
790
791 Point *zp0, *zp1, *zp2;
792 int rp0, rp1, rp2; // reference points
793 int loop; // loop counter
794 int auto_flip;
795 int cvt_cut_in;
796 int round_state;
797 int round_phase;
798 int round_period;
799 int round_thold;
800 int min_distance;
801 int swidth_cut_in;
802 int swidth_value;
803 int delta_base;
804 int delta_shift;
805 int instr_control;
806 int dropout_control;
807 };
808
809 enum {
810 UNITY2D14 = 0x4000
811 };
812
813 enum {
814 SHIFT = 6,
815 SUBS = 64
816 };
817
818 enum {
819 VGARES = 96
820 };
821
822 // scan line converter
823 class Rasterizer {
824 private:
825 typedef struct {
826 RandomAccessFile *f;
827 int offset;
828 int length;
829 } FDefs;
830 typedef FDefs IDefs;
831
832 // often accessed members should be here (low offsets)
833
834 int *stack, *stackbase; // stack grows upward
835 Point *p[2]; // points (twilight + action zone)
836 int *endPoints;
837 int nPoints[2]; // number of points in zone 0 and 1
838 int nEndPoints;
839
840 int *cvt; // control value table
841 int *stor; // storage area
842 FDefs *fdefs; // function definitions
843 IDefs *idefs; // instruction definitions
844
845 TTFont* ttFont;
846
847 // misc
848
849 enum {
850 UNDERLINE = 1,
851 STRIKEOUT = 2,
852 SUBSCRIPT = 4,
853 SUPERSCRIPT = 8
854 };
855
856 int flags;
857
858 enum {
859 INVALID_FONT,
860 NOT_READY,
861 TRAFO_APPLIED,
862 FONT_DONE
863 } status;
864
865 // memory allocation status
866
867 int sizePoints[2], sizeContours, sizeStack;
868 int sizeCvt, sizeStor, sizeFDefs, sizeIDefs;
869
870 // used by interpreter
871
872 int xx, xy, yx, yy, xxexp;
873 int pointSize;
874 int mppem, mppemx, mppemy;
875
876 GraphicsState gs, default_gs;
877
878 // resulting bitmap
879 #define SCANLINEPAD (1 << LOGSLP)
880 #define SLPMASK (SCANLINEPAD - 1)
881
882 #if (LOGSLP == 3)
883 #define TYPESLP uint8_t
884 #elif (LOGSLP == 4)
885 #define TYPESLP uint16_t
886 #elif (LOGSLP == 5)
887 #define TYPESLP uint32_t
888 #elif (LOGSLP == 6)
889 #define TYPESLP uint64_t
890 #else
891 #error "illegal value for LOGSLP"
892 #endif
893
894 public: // XXX: clean up showttf so this can become private
895 int format; // >0 scanlinepad, <0 maxwidth
896
897 int width, height;
898 unsigned int length;
899 int dX;
900
901 int grid_fitting; // ==0: none, <0: enabled, >0: enabled+working
902 int anti_aliasing; // ==0: none, <0: enabled, >0: enabled+working
903
904 public:
905 Rasterizer(int _grid_fitting = 1, int _anti_aliasing = 0,
906 int _sizeTwilight = 0, int _sizePoints = 0,
907 int _sizeContours = 0, int _sizeStack = 0,
908 int _sizeCvt = 0, int _sizeStor = 0, int _sizeFDefs = 0);
909 ~Rasterizer();
910
911 void useTTFont(TTFont *_ttFont, int _flags=0);
912 void setPixelSize(int xx, int xy, int yx, int yy);
913 void setPointSize(int xx, int xy, int yx, int yy, int xres, int yres);
914 void getFontExtent(FontExtent *fe);
915
916 int putChar8Bitmap(char c8, uint8_t *bmp, uint8_t *bmpend, GlyphMetrics *gm);
917 int putChar16Bitmap(int c16, uint8_t *bmp, uint8_t *bmpend, GlyphMetrics *gm);
918 int putGlyphBitmap(int glyph, uint8_t *bmp, uint8_t *bmpend, GlyphMetrics *gm);
919
920 void printOutline(void);
921
922 private:
923 friend class GlyphTable;
924
925 void applyTransformation();
926 void scaleGlyph();
scaleX(int x,int y)927 int scaleX(int x, int y) {
928 return (((xx * x + xy * y) + 16) >> 5) << xxexp;
929 }
scaleY(int y,int x)930 int scaleY(int y, int x) {
931 return (((yx * x + yy * y) + 16) >> 5) << xxexp;
932 }
933 void hintGlyph(GlyphTable *g, int offset, int length);
934 void putGlyphData(int ne, int np, int *ep, Point *pp, int gn, int xm);
935
936 void initInterpreter();
937 void endInterpreter();
938 void calcCVT();
939
940 void execHints(RandomAccessFile *const f, int offset, int length);
941 void execOpcode(RandomAccessFile *const f);
942 static void skipHints(RandomAccessFile* const f);
943
944 int round(int x) const;
945
946 void interpolate(Point &pp, const Point &pRef1, const Point &pRef2);
947 STATIC void doIUP0(Point *const first, Point *const last);
948 STATIC void doIUP1(Point *const first, Point *const last);
949 STATIC void iup0(Point *const pp,
950 const Point* const pRef1, const Point *const pRef2);
951 STATIC void iup1(Point *const pp,
952 const Point *const pRef1, const Point *const pRef2);
953 int newMeasure(const Point &p2, const Point &p1);
954 int oldMeasure(const Point &p2, const Point &p1);
955 static void newLine2vector(const Point &p1, const Point &p2,
956 int &vx, int &vy);
957 static void oldLine2vector(const Point &p1, const Point &p2,
958 int &vx, int &vy);
959
960 static void openDraw();
961 static void closeDraw();
962 void drawGlyph(uint8_t *const startbmp, uint8_t *const endbmp);
963 void drawBitmap(uint8_t *const bmp, int height, int dX);
964 static void drawContour(Point *const first, Point *const last);
965 static const Point *drawPoly(const Point &p0, const Point &p1,
966 const Point &p2);
967 static void drawSegment(int x1, int y1, int x2, int y2);
968 static void bezier1(int x0, int y0, int x1, int y1, int x2, int y2);
969 void antiAliasing2(uint8_t *bmp);
970 };
971
972 // hint opcodes
973 enum {
974 // pushing values on the stack
975
976 NPUSHB = 0x40, // push n bytes
977 NPUSHW = 0x41, // push n words
978 PUSHB00 = 0xB0, // push bytes
979 PUSHB01,
980 PUSHB02,
981 PUSHB03,
982 PUSHB04,
983 PUSHB05,
984 PUSHB06,
985 PUSHB07,
986 PUSHW00 = 0xB8, // push words
987 PUSHW01,
988 PUSHW02,
989 PUSHW03,
990 PUSHW04,
991 PUSHW05,
992 PUSHW06,
993 PUSHW07,
994
995 // accessing the storage area
996
997 RS = 0x43, // read store
998 WS = 0x42, // write store
999
1000 // accessing the CVT table
1001
1002 WCVTP = 0x44, // write cvt in pixel units
1003 WCVTF = 0x70, // write cvt in Funits
1004 RCVT = 0x45, // read cvt element
1005
1006 // accessing the graphics state
1007
1008 SVTCA0 = 0x00, // set (freedom and projection) vector to yaxis
1009 SVTCA1 = 0x01, // set (freedom and projection) vector to xaxis
1010 SPVTCA0 = 0x02, // set projection vector to yaxis
1011 SPVTCA1 = 0x03, // set projection vector to xaxis
1012 SFVTCA0 = 0x04, // set freedom vector to yaxis
1013 SFVTCA1 = 0x05, // set freedom vector to xaxis
1014 SPVTL0 = 0x06, // set projection vector parallel to line
1015 SPVTL1 = 0x07, // set projection vector perpendicular to line
1016 SFVTL0 = 0x08, // set freedom vector parallel to line
1017 SFVTL1 = 0x09, // set freedom vector perpendicular to line
1018 SFVTPV = 0x0E, // set freedom to projection vector
1019 SDPVTL0 = 0x86, // set dual projection vector parallel to line
1020 SDPVTL1 = 0x87, // set dual projection vector perpendicular to line
1021 SPVFS = 0x0A, // set projection vector from stack
1022 SFVFS = 0x0B, // set freedom vector from stack
1023 GPV = 0x0C, // get projection vector
1024 GFV = 0x0D, // get freedom vector
1025 SRP0 = 0x10, // set reference point rp0
1026 SRP1,
1027 SRP2,
1028 SZP0 = 0x13, // set zone pointer zp0
1029 SZP1,
1030 SZP2,
1031 SZPS = 0x16, // set zp0, zp1, zp2
1032 RTHG = 0x19, // round to half grid
1033 RTG = 0x18, // round to grid
1034 RTDG = 0x3D, // round to double grid
1035 RDTG = 0x7D, // round down to grid
1036 RUTG = 0x7C, // round up to grid
1037 ROFF = 0x7A, // round off
1038 SROUND = 0x76, // super round
1039 S45ROUND = 0x77, // super round 45 degrees
1040 SLOOP = 0x17, // set loop counter
1041 SMD = 0x1A, // set minimum distance
1042 INSTCTRL = 0x8E, // instruction execution control
1043
1044 // scan conversion control
1045
1046 SCANCTRL = 0x85, // scan conversion control
1047 SCANTYPE = 0x8D, //
1048 SCVTCI = 0x1D, // set cvt cut_in
1049 SSWCI = 0x1E, // set single width cut_in
1050 SSW = 0x1F, // set single width value
1051 FLIPON = 0x4D, // sets auto_flip
1052 FLIPOFF = 0x4E, // reset auto_flip
1053 SANGW = 0x7E, // set angle weight
1054 SDB = 0x5E, // set delta base
1055 SDS = 0x5F, // set delta shift
1056
1057 // measurements
1058
1059 GC0 = 0x46, // get current coordinate projected
1060 GC1 = 0x47, // get original coordinate projected
1061 SCFS = 0x48, // set coordinates from stack
1062 MD0 = 0x49, // measure distance in current outline
1063 MD1 = 0x4A, // measure distance in original outline
1064 MPPEM = 0x4B, // measure pixels per em in p_vector direction
1065 MPS = 0x4C, // measure point size
1066
1067 // outline manipulation
1068
1069 FLIPPT = 0x80, // flip point
1070 FLIPRGON = 0x81, // flip range on
1071 FLIPRGOFF = 0x82, // flip range off
1072 SHP0 = 0x32, // shift point by last point rp2 zp1
1073 SHP1 = 0x33, // shift point by last point rp1 zp0
1074 SHC0 = 0x34, // shift contour by point
1075 SHC1 = 0x35, // shift contour by point
1076 SHZ0 = 0x36, // shift zone by point
1077 SHZ1 = 0x37, // shift zone by point
1078 SHPIX = 0x38, // shift zone by pixel
1079 MSIRP0 = 0x3A, // move stack indirect relative point, no set
1080 MSIRP1 = 0x3B, // move stack indirect relative point, set rp0
1081 MDAP0 = 0x2E, // move direct absolute point, no rounding
1082 MDAP1 = 0x2F, // move direct absolute point, rounding
1083 MIAP0 = 0x3E, // move indirect absolute point, no rounding
1084 MIAP1 = 0x3F, // move indirect absolute point, rounding
1085 MDRP00 = 0xC0, // move direct relative point
1086 MDRP01,
1087 MDRP02,
1088 MDRP03,
1089 MDRP04,
1090 MDRP05,
1091 MDRP06,
1092 MDRP07,
1093 MDRP08,
1094 MDRP09,
1095 MDRP0A,
1096 MDRP0B,
1097 MDRP0C,
1098 MDRP0D,
1099 MDRP0E,
1100 MDRP0F,
1101 MDRP10,
1102 MDRP11,
1103 MDRP12,
1104 MDRP13,
1105 MDRP14,
1106 MDRP15,
1107 MDRP16,
1108 MDRP17,
1109 MDRP18,
1110 MDRP19,
1111 MDRP1A,
1112 MDRP1B,
1113 MDRP1C,
1114 MDRP1D,
1115 MDRP1E,
1116 MDRP1F,
1117 MIRP00 = 0xE0, // move indirect relative point
1118 MIRP01,
1119 MIRP02,
1120 MIRP03,
1121 MIRP04,
1122 MIRP05,
1123 MIRP06,
1124 MIRP07,
1125 MIRP08,
1126 MIRP09,
1127 MIRP0A,
1128 MIRP0B,
1129 MIRP0C,
1130 MIRP0D,
1131 MIRP0E,
1132 MIRP0F,
1133 MIRP10,
1134 MIRP11,
1135 MIRP12,
1136 MIRP13,
1137 MIRP14,
1138 MIRP15,
1139 MIRP16,
1140 MIRP17,
1141 MIRP18,
1142 MIRP19,
1143 MIRP1A,
1144 MIRP1B,
1145 MIRP1C,
1146 MIRP1D,
1147 MIRP1E,
1148 MIRP1F,
1149 ALIGNRP = 0x3C, // align rp
1150 ALIGNPTS = 0x27, // align points
1151 ISECT = 0x0F, // move point to intersection of two lines
1152 AA = 0x7F, // adjust angle (no longer supported)
1153 IP = 0x39, // interpolate point
1154 UTP = 0x29, // untouch point
1155 IUP0 = 0x30, // interpolate untouched points, x direction
1156 IUP1 = 0x31, // interpolate untouched points, y direction
1157 DELTAP1 = 0x5D, // delta exception p1
1158 DELTAP2 = 0x71, // delta exception p2
1159 DELTAP3 = 0x72, // delta exception p3
1160 DELTAC1 = 0x73, // delta exception c1
1161 DELTAC2 = 0x74, // delta exception c2
1162 DELTAC3 = 0x75, // delta exception c3
1163
1164 // stack manipulation
1165
1166 DUP = 0x20, // duplicate stack top
1167 POP = 0x21, // pop
1168 CLEAR = 0x22, // clear entire stack
1169 SWAP = 0x23, // swap
1170 DEPTH = 0x24, // return depth of stack
1171 CINDEX = 0x25, // copy from stack index
1172 MINDEX = 0x26, // move from stack index
1173 ROLL = 0x8A, // roll top three stack elements
1174
1175 // control flow
1176
1177 IF = 0x58, // if
1178 ELSE = 0x1B, // else
1179 EIF = 0x59, // endif
1180 JROT = 0x78, // jump relative on true
1181 JMPR = 0x1C, // jump relative unconditionally
1182 JROF = 0x79, // jump relative on false
1183
1184 // arithmetic
1185
1186 LT = 0x50, // less than
1187 LTEQ = 0x51, // less than or equal
1188 GT = 0x52, // greater than
1189 GTEQ = 0x53, // greater than or equal
1190 EQ = 0x54, // equal
1191 NEQ = 0x55, // not equal
1192 ODD = 0x56, // odd
1193 EVEN = 0x57, // even
1194 AND = 0x5A, // logical and
1195 OR = 0x5B, // logical or
1196 NOT = 0x5C, // logical not
1197 ADD = 0x60, // add
1198 SUB = 0x61, // subtract
1199 DIV = 0x62, // divide
1200 MUL = 0x63, // multiply
1201 ABS = 0x64, // absolute
1202 NEG = 0x65, // negative
1203 FLOOR = 0x66, // floor
1204 CEILING = 0x67, // ceiling
1205 MAX = 0x8B, // maximum
1206 MIN = 0x8C, // minimum
1207 ROUND00 = 0x68, // round engine independent
1208 ROUND01,
1209 ROUND02,
1210 ROUND03,
1211 NROUND00 = 0x6C, // round engine dependent
1212 NROUND01,
1213 NROUND02,
1214 NROUND03,
1215
1216 // subroutines
1217
1218 FDEF = 0x2C, // function definition
1219 ENDF = 0x2D, // end of function
1220 CALL = 0x2B, // call
1221 LOOPCALL = 0x2A, // loop and call
1222 IDEF = 0x89, // instruction definition
1223
1224 // miscellaneous
1225
1226 DBG = 0x4F, // debug
1227 GETINFO = 0x88 // get info about glyph and scaler
1228 };
1229
1230 enum { // round state, do the constants in the spec make any sense?
1231 ROUND_OFF, //= 5,
1232 ROUND_GRID, //= 1,
1233 ROUND_DOWN, //= 3,
1234 ROUND_UP, //= 4,
1235 ROUND_HALF, //= 0,
1236 ROUND_DOUBLE, //= 2,
1237 ROUND_SUPER, //= 6,
1238 ROUND_SUPER45 //= 7
1239 };
1240
1241 enum { // instruction control
1242 INHIBIT_GRID_FIT = 1,
1243 IGNORE_CVT_CHANGES = 2
1244 };
1245
1246 enum { // getinfo parameters
1247 SCALER_VERSION = 1,
1248 GLYPH_ROTATED = 2,
1249 GLYPH_STRETCHED = 4,
1250 // getinfo results
1251 WIN_SCALER = 3,
1252 IS_ROTATED = 0x100,
1253 IS_STRETCHED = 0x200
1254 };
1255
1256 #endif
1257