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