1 /*******************************************************************************
2  * truetype.cpp
3  *
4  * This module implements rendering of TrueType fonts.
5  * This file was written by Alexander Enzmann.  He wrote the code for
6  * rendering glyphs and generously provided us these enhancements.
7  *
8  * ---------------------------------------------------------------------------
9  * Persistence of Vision Ray Tracer ('POV-Ray') version 3.7.
10  * Copyright 1991-2013 Persistence of Vision Raytracer Pty. Ltd.
11  *
12  * POV-Ray is free software: you can redistribute it and/or modify
13  * it under the terms of the GNU Affero General Public License as
14  * published by the Free Software Foundation, either version 3 of the
15  * License, or (at your option) any later version.
16  *
17  * POV-Ray is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU Affero General Public License for more details.
21  *
22  * You should have received a copy of the GNU Affero General Public License
23  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
24  * ---------------------------------------------------------------------------
25  * POV-Ray is based on the popular DKB raytracer version 2.12.
26  * DKBTrace was originally written by David K. Buck.
27  * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
28  * ---------------------------------------------------------------------------
29  * $File: //depot/public/povray/3.x/source/backend/shape/truetype.cpp $
30  * $Revision: #1 $
31  * $Change: 6069 $
32  * $DateTime: 2013/11/06 11:59:40 $
33  * $Author: chrisc $
34  *******************************************************************************/
35 
36 // frame.h must always be the first POV file included (pulls in platform config)
37 #include "backend/frame.h"
38 #include "backend/povray.h"
39 #include "backend/math/vector.h"
40 #include "backend/bounding/bbox.h"
41 #include "backend/math/matrices.h"
42 #include "backend/scene/objects.h"
43 #include "backend/shape/truetype.h"
44 #include "backend/shape/csg.h"                /* [ARE 11/94] */
45 #include "backend/scene/threaddata.h"
46 #include "backend/support/fileutil.h"
47 
48 // this must be the last file included
49 #include "base/povdebug.h"
50 
51 namespace pov
52 {
53 
54 /*****************************************************************************
55 * Local preprocessor defines
56 ******************************************************************************/
57 
58 /* uncomment this to debug ttf. DEBUG1 gives less output than DEBUG2
59 #define TTF_DEBUG2 1
60 #define TTF_DEBUG 1
61 #define TTF_DEBUG3 1
62 */
63 
64 const DBL TTF_Tolerance = 1.0e-6;    /* -4 worked, -8 failed */
65 
66 const int MAX_ITERATIONS = 50;
67 const DBL COEFF_LIMIT = 1.0e-20;
68 
69 /* For decoding glyph coordinate bit flags */
70 const int ONCURVE            = 0x01;
71 const int XSHORT             = 0x02;
72 const int YSHORT             = 0x04;
73 const int REPEAT_FLAGS       = 0x08;  /* repeat flag n times */
74 const int SHORT_X_IS_POS     = 0x10;  /* the short vector is positive */
75 const int NEXT_X_IS_ZERO     = 0x10;  /* the relative x coordinate is zero */
76 const int SHORT_Y_IS_POS     = 0x20;  /* the short vector is positive */
77 const int NEXT_Y_IS_ZERO     = 0x20;  /* the relative y coordinate is zero */
78 
79 /* For decoding multi-component glyph bit flags */
80 const int ARG_1_AND_2_ARE_WORDS    = 0x0001;
81 const int ARGS_ARE_XY_VALUES       = 0x0002;
82 const int ROUND_XY_TO_GRID         = 0x0004;
83 const int WE_HAVE_A_SCALE          = 0x0008;
84 /*      RESERVED                 = 0x0010 */
85 const int MORE_COMPONENTS          = 0x0020;
86 const int WE_HAVE_AN_X_AND_Y_SCALE = 0x0040;
87 const int WE_HAVE_A_TWO_BY_TWO     = 0x0080;
88 const int WE_HAVE_INSTRUCTIONS     = 0x0100;
89 const int USE_MY_METRICS           = 0x0200;
90 
91 /* For decoding kern coverage bit flags */
92 const int KERN_HORIZONTAL    = 0x01;
93 const int KERN_MINIMUM       = 0x02;
94 const int KERN_CROSS_STREAM  = 0x04;
95 const int KERN_OVERRIDE      = 0x08;
96 
97 /* Some marcos to make error detection easier, as well as clarify code */
98 #define READSHORT(fp) readSHORT(fp, __LINE__, __FILE__)
99 #define READLONG(fp) readLONG(fp, __LINE__, __FILE__)
100 #define READUSHORT(fp) readUSHORT(fp, __LINE__, __FILE__)
101 #define READULONG(fp) readULONG(fp, __LINE__, __FILE__)
102 #define READFIXED(fp) readLONG(fp, __LINE__, __FILE__)
103 #define READFWORD(fp) readSHORT(fp, __LINE__, __FILE__)
104 #define READUFWORD(fp) readUSHORT(fp, __LINE__, __FILE__)
105 
106 /*****************************************************************************
107 * Local typedefs
108 ******************************************************************************/
109 
110 /* Type definitions to match the TTF spec, makes code clearer */
111 typedef char CHAR;
112 typedef unsigned char BYTE;
113 typedef short SHORT;
114 typedef unsigned short USHORT;
115 typedef int LONG;
116 typedef unsigned int ULONG;
117 typedef short FWord;
118 typedef unsigned short uFWord;
119 
120 #if !defined(TARGET_OS_MAC)
121 typedef int Fixed;
122 #endif
123 
124 typedef struct
125 {
126 	Fixed version;                /* 0x10000 (1.0) */
127 	USHORT numTables;             /* number of tables */
128 	USHORT searchRange;           /* (max2 <= numTables)*16 */
129 	USHORT entrySelector;         /* log2 (max2 <= numTables) */
130 	USHORT rangeShift;            /* numTables*16-searchRange */
131 } sfnt_OffsetTable;
132 
133 typedef struct
134 {
135 	BYTE tag[4];
136 	ULONG checkSum;
137 	ULONG offset;
138 	ULONG length;
139 } sfnt_TableDirectory;
140 
141 typedef sfnt_TableDirectory *sfnt_TableDirectoryPtr;
142 
143 typedef struct
144 {
145 	ULONG bc;
146 	ULONG ad;
147 } longDateTime;
148 
149 typedef struct
150 {
151 	Fixed version;                /* for this table, set to 1.0 */
152 	Fixed fontRevision;           /* For Font Manufacturer */
153 	ULONG checkSumAdjustment;
154 	ULONG magicNumber;            /* signature, must be 0x5F0F3CF5 == MAGIC */
155 	USHORT flags;
156 	USHORT unitsPerEm;            /* How many in Font Units per EM */
157 
158 	longDateTime created;
159 	longDateTime modified;
160 
161 	FWord xMin;                   /* Font wide bounding box in ideal space */
162 	FWord yMin;                   /* Baselines and metrics are NOT worked */
163 	FWord xMax;                   /* into these numbers) */
164 	FWord yMax;
165 
166 	USHORT macStyle;              /* macintosh style word */
167 	USHORT lowestRecPPEM;         /* lowest recommended pixels per Em */
168 
169 	SHORT fontDirectionHint;
170 	SHORT indexToLocFormat;       /* 0 - short offsets, 1 - long offsets */
171 	SHORT glyphDataFormat;
172 } sfnt_FontHeader;
173 
174 typedef struct
175 {
176 	USHORT platformID;
177 	USHORT specificID;
178 	ULONG offset;
179 } sfnt_platformEntry;
180 
181 typedef sfnt_platformEntry *sfnt_platformEntryPtr;
182 
183 typedef struct
184 {
185 	USHORT format;
186 	USHORT length;
187 	USHORT version;
188 } sfnt_mappingTable;
189 
190 typedef struct
191 {
192 	Fixed version;
193 
194 	FWord Ascender;
195 	FWord Descender;
196 	FWord LineGap;
197 
198 	uFWord advanceWidthMax;
199 	FWord minLeftSideBearing;
200 	FWord minRightSideBearing;
201 	FWord xMaxExtent;
202 	SHORT caretSlopeRise;
203 	SHORT caretSlopeRun;
204 
205 	SHORT reserved1;
206 	SHORT reserved2;
207 	SHORT reserved3;
208 	SHORT reserved4;
209 	SHORT reserved5;
210 
211 	SHORT metricDataFormat;
212 	USHORT numberOfHMetrics;      /* number of hMetrics in the hmtx table */
213 } sfnt_HorizHeader;
214 
215 typedef struct
216 {
217 	SHORT numContours;
218 	SHORT xMin;
219 	SHORT yMin;
220 	SHORT xMax;
221 	SHORT yMax;
222 } GlyphHeader;
223 
224 typedef struct
225 {
226 	GlyphHeader header;
227 	USHORT numPoints;
228 	USHORT *endPoints;
229 	BYTE *flags;
230 	DBL *x, *y;
231 	USHORT myMetrics;
232 } GlyphOutline;
233 
234 typedef struct
235 {
236 	BYTE inside_flag;             /* 1 if this an inside contour, 0 if outside */
237 	USHORT count;                 /* Number of points in the contour */
238 	BYTE *flags;                  /* On/off curve flags */
239 	DBL *x, *y;                   /* Coordinates of control vertices */
240 } Contour;
241 
242 
243 /* Contour information for a single glyph */
244 typedef struct GlyphStruct
245 {
246 	GlyphHeader header;           /* Count and sizing information about this
247 	                               * glyph */
248 	USHORT glyph_index;           /* Internal glyph index for this character */
249 	Contour *contours;            /* Array of outline contours */
250 	USHORT unitsPerEm;            /* Max units character */
251 	GlyphPtr next;                /* Next cached glyph */
252 	USHORT c;                     /* Character code */
253 	USHORT myMetrics;             /* Which glyph index this is for metrics */
254 } Glyph;
255 
256 typedef struct KernData_struct
257 {
258 	USHORT left, right;           /* Glyph index of left/right to kern */
259 	FWord value;                  /* Delta in FUnits to apply in between */
260 } KernData;
261 
262 /*
263  * [esp] There's already a "KernTable" on the Mac... renamed to TTKernTable for
264  * now in memorium to its author.
265  */
266 
267 typedef struct KernStruct
268 {
269 	USHORT coverage;              /* Coverage bit field of this subtable */
270 	USHORT nPairs;                /* # of kerning pairs in this table */
271 	KernData *kern_pairs;         /* Array of kerning values */
272 } TTKernTable;
273 
274 typedef struct KernTableStruct
275 {
276 	USHORT nTables;               /* # of subtables in the kerning table */
277 	TTKernTable *tables;
278 } KernTables;
279 
280 typedef struct longHorMertric
281 {
282 	uFWord advanceWidth;          /* Total width of a glyph in FUnits */
283 	FWord lsb;                    /* FUnits to the left of the glyph */
284 } longHorMetric;
285 
286 /* Useful general data about this font */
287 struct FontFileInfo;
288 
289 struct FontFileInfo
290 {
291 	UCS2 *filename;
292 	IStream *fp;
293 	USHORT platformID[4];             /* Character encoding search order */
294 	USHORT specificID[4];
295 	ULONG cmap_table_offset;          /* File locations for these tables */
296 	ULONG glyf_table_offset;
297 	USHORT numGlyphs;                 /* How many symbols in this file */
298 	USHORT unitsPerEm;                /* The "resoultion" of this font */
299 	SHORT indexToLocFormat;           /* 0 - short format, 1 - long format */
300 	ULONG *loca_table;                /* Mapping from characters to glyphs */
301 	GlyphPtr glyphs;                  /* Cached info for this font */
302 	KernTables kerning_tables;        /* Kerning info for this font */
303 	USHORT numberOfHMetrics;          /* The number of explicit spacings */
304 	longHorMetric *hmtx_table;        /* Horizontal spacing info */
305 	ULONG glyphIDoffset;              /* Offset for Type 4 encoding tables */
306 	USHORT segCount, searchRange,     /* Counts for Type 4 encoding tables */
307 	       entrySelector, rangeShift;
308 	USHORT *startCount, *endCount,    /* Type 4 (MS) encoding tables */
309 	       *idDelta, *idRangeOffset;
310 	FontFileInfo *next;  /* Next font */
311 };
312 
313 /*****************************************************************************
314 * Local variables
315 ******************************************************************************/
316 
317 const BYTE tag_CharToIndexMap[] = "cmap"; /* 0x636d6170; */
318 const BYTE tag_FontHeader[]     = "head"; /* 0x68656164; */
319 const BYTE tag_GlyphData[]      = "glyf"; /* 0x676c7966; */
320 const BYTE tag_IndexToLoc[]     = "loca"; /* 0x6c6f6361; */
321 const BYTE tag_Kerning[]        = "kern"; /* 0x6b65726e; */
322 const BYTE tag_MaxProfile[]     = "maxp"; /* 0x6d617870; */
323 const BYTE tag_HorizHeader[]    = "hhea"; /* 0x68686561; */
324 const BYTE tag_HorizMetric[]    = "hmtx"; /* 0x686d7478; */
325 const BYTE tag_TTCFontFile[]    = "ttcf"; /* */
326 
327 /*****************************************************************************
328 * Static functions
329 ******************************************************************************/
330 
331 /* Byte order independent I/O routines (probably already in other routines) */
332 SHORT readSHORT(IStream *infile, int line, const char *file);
333 USHORT readUSHORT(IStream *infile, int line, const char *file);
334 LONG readLONG(IStream *infile, int line, const char *file);
335 ULONG readULONG(IStream *infile, int line, const char *file);
336 int compare_tag4(BYTE *ttf_tag, BYTE *known_tag);
337 
338 /* Internal TTF input routines */
339 FontFileInfo *ProcessFontFile(const char *fontfilename, const int font_id, Parser *parser, shared_ptr<SceneData>& sceneData);
340 FontFileInfo *OpenFontFile(const char *filename, const int font_id, Parser *parser, shared_ptr<SceneData>& sceneData);
341 void ProcessHeadTable(FontFileInfo *ffile, int head_table_offset);
342 void ProcessLocaTable(FontFileInfo *ffile, int loca_table_offset);
343 void ProcessMaxpTable(FontFileInfo *ffile, int maxp_table_offset);
344 void ProcessKernTable(FontFileInfo *ffile, int kern_table_offset);
345 void ProcessHheaTable(FontFileInfo *ffile, int hhea_table_offset);
346 void ProcessHmtxTable(FontFileInfo *ffile, int hmtx_table_offset);
347 GlyphPtr ProcessCharacter(FontFileInfo *ffile, unsigned int search_char, unsigned int *glyph_index);
348 USHORT ProcessCharMap(FontFileInfo *ffile, unsigned int search_char);
349 USHORT ProcessFormat0Glyph(FontFileInfo *ffile, unsigned int search_char);
350 USHORT ProcessFormat4Glyph(FontFileInfo *ffile, unsigned int search_char);
351 USHORT ProcessFormat6Glyph(FontFileInfo *ffile, unsigned int search_char);
352 GlyphPtr ExtractGlyphInfo(FontFileInfo *ffile, unsigned int glyph_index, unsigned int c);
353 GlyphOutline *ExtractGlyphOutline(FontFileInfo *ffile, unsigned int glyph_index, unsigned int c);
354 GlyphPtr ConvertOutlineToGlyph(FontFileInfo *ffile, const GlyphOutline *ttglyph);
355 
356 /*
357  * The following work as macros if sizeof(short) == 16 bits and
358  * sizeof(long) == 32 bits, but tend to break otherwise.  Making these
359  * into error functions also allows file error checking.  Do not attempt to
360  * "optimize" these functions - some architectures require them the way
361  * that they are written.
362  */
readSHORT(IStream * infile,int line,const char * file)363 SHORT readSHORT(IStream *infile, int line, const char *file)
364 {
365 	int i0, i1 = 0; /* To quiet warnings */
366 
367 	if ((i0 = infile->Read_Byte ()) == EOF || (i1  = infile->Read_Byte ()) == EOF)
368 	{
369 		throw POV_EXCEPTION(kFileDataErr, "Cannot read TrueType font file.");
370 	}
371 
372 	if (i0 & 0x80) /* Subtract 1 after value is negated to avoid overflow [AED] */
373 		return -(((255 - i0) << 8) | (255 - i1)) - 1;
374 	else
375 		return (i0 << 8) | i1;
376 }
377 
readUSHORT(IStream * infile,int line,const char * file)378 USHORT readUSHORT(IStream *infile, int line, const char *file)
379 {
380 	int i0, i1 = 0; /* To quiet warnings */
381 
382 	if ((i0  = infile->Read_Byte ()) == EOF || (i1  = infile->Read_Byte ()) == EOF)
383 	{
384 		throw POV_EXCEPTION(kFileDataErr, "Cannot read TrueType font file.");
385 	}
386 
387 	return (USHORT)((((USHORT)i0) << 8) | ((USHORT)i1));
388 }
389 
readLONG(IStream * infile,int line,const char * file)390 LONG readLONG(IStream *infile, int line, const char *file)
391 {
392 	LONG i0, i1 = 0, i2 = 0, i3 = 0; /* To quiet warnings */
393 
394 	if ((i0 = infile->Read_Byte ()) == EOF || (i1 = infile->Read_Byte ()) == EOF ||
395 	    (i2 = infile->Read_Byte ()) == EOF || (i3 = infile->Read_Byte ()) == EOF)
396 	{
397 		throw POV_EXCEPTION(kFileDataErr, "Cannot read TrueType font file.");
398 	}
399 
400 	if (i0 & 0x80) /* Subtract 1 after value is negated to avoid overflow [AED] */
401 		return -(((255 - i0) << 24) | ((255 - i1) << 16) |
402 		         ((255 - i2) << 8)  |  (255 - i3)) - 1;
403 	else
404 		return (i0 << 24) | (i1 << 16) | (i2 << 8) | i3;
405 }
406 
readULONG(IStream * infile,int line,const char * file)407 ULONG readULONG(IStream *infile, int line, const char *file)
408 {
409 	int i0, i1 = 0, i2 = 0, i3 = 0;  /* To quiet warnings */
410 
411 	if ((i0 = infile->Read_Byte ()) == EOF || (i1 = infile->Read_Byte ()) == EOF ||
412 	    (i2 = infile->Read_Byte ()) == EOF || (i3 = infile->Read_Byte ()) == EOF)
413 	{
414 		throw POV_EXCEPTION(kFileDataErr, "Cannot read TrueType font file.");
415 	}
416 
417 	return (ULONG) ((((ULONG) i0) << 24) | (((ULONG) i1) << 16) |
418 	                (((ULONG) i2) << 8)  |  ((ULONG) i3));
419 }
420 
compare_tag4(const BYTE * ttf_tag,const BYTE * known_tag)421 int compare_tag4(const BYTE *ttf_tag, const BYTE *known_tag)
422 {
423 	return (ttf_tag[0] == known_tag[0] && ttf_tag[1] == known_tag[1] &&
424 	        ttf_tag[2] == known_tag[2] && ttf_tag[3] == known_tag[3]);
425 }
426 
427 /*****************************************************************************
428 *
429 * FUNCTION
430 *
431 *   ProcessNewTTF
432 *
433 * INPUT
434 *
435 * OUTPUT
436 *
437 * RETURNS
438 *
439 * AUTHOR
440 *
441 *   Alexander Ennzmann
442 *
443 * DESCRIPTION
444 *
445 *   Takes an input string and a font filename, and creates a POV-Ray CSG
446 *   object for each letter in the string.
447 *
448 * CHANGES
449 *
450 *   Allow usage of built-in fonts via an additional parameter
451 *   (triggered when filename is null) - Oct 2012 [JG]
452 *
453 ******************************************************************************/
ProcessNewTTF(CSG * Object,const char * filename,const int font_id,const UCS2 * text_string,DBL depth,const VECTOR offset,Parser * parser,shared_ptr<SceneData> & sceneData)454 void TrueType::ProcessNewTTF(CSG *Object, const char *filename, const int font_id, const UCS2 *text_string, DBL depth, const VECTOR offset, Parser *parser, shared_ptr<SceneData>& sceneData)
455 {
456 	FontFileInfo *ffile;
457 	VECTOR local_offset, total_offset;
458 	TrueType *ttf;
459 	DBL funit_size;
460 	TTKernTable *table;
461 	USHORT coverage;
462 	unsigned int search_char;
463 	unsigned int glyph_index, last_index = 0;
464 	FWord kern_value_x, kern_value_min_x;
465 	FWord kern_value_y, kern_value_min_y;
466 	int i, j, k;
467 	TRANSFORM Trans;
468 
469 	/* Get general font info */
470 	ffile = ProcessFontFile(filename, font_id, parser, sceneData);
471 
472 	if((sceneData->languageVersion < 350) && (sceneData->stringEncoding == 0))
473 	{
474 // TODO MESSAGE		PossibleError("Text may not be displayed as expected.\n"
475 //		              "Please refer to the user manual regarding changes\n"
476 //		              "in POV-Ray 3.5 and later.");
477 	}
478 
479 	/* Get info about each character in the string */
480 	Make_Vector(total_offset, 0.0, 0.0, 0.0);
481 
482 	for (i = 0; text_string[i] != 0; i++)
483 	{
484 		/*
485 		 * We need to make sure (for now) that this is only the lower 8 bits,
486 		 * so we don't have all the high bits set if converted from a signed
487 		 * char to an unsigned short.
488 		 */
489 		search_char = (unsigned int)(text_string[i]);
490 
491 #ifdef TTF_DEBUG
492 		Debug_Info("\nChar: '%c' (0x%X), Offset[%d]: <%g,%g,%g>\n", (char)search_char,
493 			search_char, i, total_offset[X], total_offset[Y], total_offset[Z]);
494 #endif
495 
496 		/* Make a new child for each character */
497 		ttf = new TrueType();
498 
499 		/* Set the depth information for the character */
500 		ttf->depth = depth;
501 
502 		/*
503 		 * Get pointers to the contour information for each character
504 		 * in the text string.
505 		 */
506 		ttf->glyph = ProcessCharacter(ffile, search_char, &glyph_index);
507 		funit_size = 1.0 / (DBL)(ffile->unitsPerEm);
508 
509 		/*
510 		 * Spacing based on the horizontal metric table, the kerning table,
511 		 * and (possibly) the previous glyph.
512 		 */
513 		if (i == 0) /* Ignore spacing on the left for the first character only */
514 		{
515 			/* Shift the glyph to start at the origin */
516 			total_offset[X] = -ttf->glyph->header.xMin * funit_size;
517 
518 			Compute_Translation_Transform(&Trans, total_offset);
519 
520 			ttf->Translate(total_offset, &Trans);
521 
522 			/* Shift next glyph by the width of this one excluding the left offset*/
523 			total_offset[X] = (ffile->hmtx_table[ttf->glyph->myMetrics].advanceWidth -
524 			                   ffile->hmtx_table[ttf->glyph->myMetrics].lsb) * funit_size;
525 
526 #ifdef TTF_DEBUG
527 			Debug_Info("aw(%d): %g\n", i,
528 			                   (ffile->hmtx_table[ttf->glyph->myMetrics].advanceWidth -
529 			                    ffile->hmtx_table[ttf->glyph->myMetrics].lsb)*funit_size);
530 #endif
531 		}
532 		else /* Kern all of the other characters */
533 		{
534 			kern_value_x = kern_value_y = 0;
535 			kern_value_min_x = kern_value_min_y = -ffile->unitsPerEm;
536 			Make_Vector(local_offset, 0.0, 0.0, 0.0);
537 
538 			for (j = 0; j < ffile->kerning_tables.nTables; j++)
539 			{
540 				table = ffile->kerning_tables.tables;
541 				coverage = table->coverage;
542 
543 				/*
544 				 * Don't use vertical kerning until such a time when we support
545 				 * characters moving in the vertical direction...
546 				 */
547 				if (!(coverage & KERN_HORIZONTAL))
548 					continue;
549 
550 				/*
551 				 * If we were keen, we could do a binary search for this
552 				 * character combination, since the pairs are sorted in
553 				 * order as if the left and right index values were a 32 bit
554 				 * unsigned int (mostly - at least they are sorted on the
555 				 * left glyph).  Something to do when everything else works...
556 				 */
557 				for (k = 0; k < table[j].nPairs; k++)
558 				{
559 					if (table[j].kern_pairs[k].left == last_index &&
560 					    table[j].kern_pairs[k].right == ttf->glyph->myMetrics)
561 					{
562 #ifdef TTF_DEBUG2
563 						Debug_Info("Found a kerning for <%d, %d> = %d\n",
564 						           last_index, glyph_index, table[j].kern_pairs[k].value);
565 #endif
566 
567 						/*
568 						 * By default, Windows & OS/2 assume at most a single table with
569 						 * !KERN_MINIMUM, !KERN_CROSS_STREAM, KERN_OVERRIDE.
570 						 */
571 						if (coverage & KERN_MINIMUM)
572 						{
573 #ifdef TTF_DEBUG2
574 							Debug_Info(" KERN_MINIMUM\n");
575 #endif
576 							if (coverage & KERN_CROSS_STREAM)
577 								kern_value_min_y = table[j].kern_pairs[k].value;
578 							else
579 								kern_value_min_x = table[j].kern_pairs[k].value;
580 						}
581 						else
582 						{
583 							if (coverage & KERN_CROSS_STREAM)
584 							{
585 #ifdef TTF_DEBUG2
586 								Debug_Info(" KERN_CROSS_STREAM\n");
587 #endif
588 								if (table[j].kern_pairs[k].value == (FWord)0x8000)
589 								{
590 									kern_value_y = 0;
591 								}
592 								else
593 								{
594 									if (coverage & KERN_OVERRIDE)
595 										kern_value_y = table[j].kern_pairs[k].value;
596 									else
597 										kern_value_y += table[j].kern_pairs[k].value;
598 								}
599 							}
600 							else
601 							{
602 #ifdef TTF_DEBUG2
603 								Debug_Info(" KERN_VALUE\n");
604 #endif
605 								if (coverage & KERN_OVERRIDE)
606 									kern_value_x = table[j].kern_pairs[k].value;
607 								else
608 									kern_value_x += table[j].kern_pairs[k].value;
609 							}
610 						}
611 						break;
612 					}
613 					/* Abort now if we have passed all potential matches */
614 					else if (table[j].kern_pairs[k].left > last_index)
615 					{
616 						break;
617 					}
618 				}
619 			}
620 			kern_value_x = (kern_value_x > kern_value_min_x ?
621 			                kern_value_x : kern_value_min_x);
622 			kern_value_y = (kern_value_y > kern_value_min_y ?
623 			                kern_value_y : kern_value_min_y);
624 
625 			/*
626 			 * Offset this character so that the left edge of the glyph is at
627 			 * the previous offset + the lsb + any kerning amount.
628 			 */
629 			local_offset[X] = total_offset[X] +
630 			                  (DBL)(ffile->hmtx_table[ttf->glyph->myMetrics].lsb -
631 			                        ttf->glyph->header.xMin + kern_value_x) * funit_size;
632 			local_offset[Y] = total_offset[Y] + (DBL)kern_value_y * funit_size;
633 
634 			/* Translate this glyph to its final position in the string */
635 			Compute_Translation_Transform(&Trans, local_offset);
636 
637 			ttf->Translate(local_offset, &Trans);
638 
639 			/* Shift next glyph by the width of this one + any kerning amount */
640 			total_offset[X] += (ffile->hmtx_table[ttf->glyph->myMetrics].advanceWidth +kern_value_x) * funit_size;
641 
642 #ifdef TTF_DEBUG
643 			Debug_Info("kern(%d): <%d, %d> (%g,%g)\n", i, last_index, glyph_index,
644 			           (DBL)kern_value_x*funit_size, (DBL)kern_value_y * funit_size);
645 			Debug_Info("lsb(%d): %g\n", i,
646 			           (DBL)ffile->hmtx_table[glyph->myMetrics].lsb * funit_size);
647 			Debug_Info("aw(%d): %g\n", i,
648 			           (DBL)ffile->hmtx_table[glyph->myMetrics].advanceWidth *
649 			           funit_size);
650 #endif
651 		}
652 
653 		/*
654 		 * Add to the offset of the next character the minimum spacing specified.
655 		 */
656 		VAddEq(total_offset, offset);
657 
658 		/* Link this glyph with the others in the union */
659 		Object->Type |= (ttf->Type & CHILDREN_FLAGS);
660 		ttf->Type |= IS_CHILD_OBJECT;
661 		Object->children.push_back(ttf);
662 
663 		last_index = glyph_index;
664 	}
665 
666 #ifdef TTF_DEBUG
667 	if (filename)
668 	{
669 		Debug_Info("TTF parsing of \"%s\" from %s complete\n", text_string, filename);
670 	}
671 	else
672 	{
673 		Debug_Info("TTF parsing of \"%s\" from builtin %d complete\n", text_string, font_id);
674 	}
675 #endif
676 
677 	/* Close the font file descriptor */
678 	if(ffile->fp!=NULL)
679 	{
680 		delete ffile->fp;
681 		ffile->fp = NULL;
682 	}
683 }
684 
685 /*****************************************************************************
686 *
687 * FUNCTION
688 *
689 *   ProcessFontFile
690 *
691 * INPUT
692 *
693 * OUTPUT
694 *
695 * RETURNS
696 *
697 * AUTHOR
698 *
699 *   Alexander Ennzmann
700 *
701 * DESCRIPTION
702 *
703 * Read the header information about the specific font.  Parse the tables
704 * as we come across them.
705 *
706 * CHANGES
707 *
708 *   Added tests for reading manditory tables/validity checks - Jan 1996 [AED]
709 *   Reordered table parsing to avoid lots of file seeking - Jan 1996 [AED]
710 *
711 *   Added builtin fonts when fontfilename is nullptr - Oct 2012 [JG]
712 *
713 ******************************************************************************/
ProcessFontFile(const char * fontfilename,const int font_id,Parser * parser,shared_ptr<SceneData> & sceneData)714 FontFileInfo *ProcessFontFile(const char *fontfilename, const int font_id, Parser *parser, shared_ptr<SceneData>& sceneData)
715 {
716 	unsigned i;
717 	int head_table_offset = 0;
718 	int loca_table_offset = 0;
719 	int maxp_table_offset = 0;
720 	int kern_table_offset = 0;
721 	int hhea_table_offset = 0;
722 	int hmtx_table_offset = 0;
723 	BYTE temp_tag[4];
724 	sfnt_OffsetTable OffsetTable;
725 	sfnt_TableDirectory Table;
726 	FontFileInfo *ffile;
727 
728 	/* Open the font file */
729 
730 	ffile = OpenFontFile(fontfilename, font_id, parser, sceneData);
731 
732 	/* We have already read all the header info, no need to do it again */
733 
734 	if (ffile->cmap_table_offset != 0)
735 	{
736 		return (ffile);
737 	}
738 
739 	/*
740 	 * Read the initial directory header on the TTF.  The numTables variable
741 	 * tells us how many tables are present in this file.
742 	 */
743 	if (!ffile->fp->read((char *)(&temp_tag), sizeof(BYTE) * 4))
744 	{
745 		throw POV_EXCEPTION(kFileDataErr, "Cannot read TrueType font file table tag");
746 	}
747 	if (compare_tag4(temp_tag, tag_TTCFontFile))
748 	{
749 		READFIXED(ffile->fp); // header version - ignored [trf]
750 		READULONG(ffile->fp); // directory count - ignored [trf]
751 		// go to first font data block listed in the directory table entry [trf]
752 		ffile->fp->seekg(READULONG(ffile->fp), SEEK_SET);
753 	}
754 	else
755 	{
756 		// if it is no TTC style file, it is a regular TTF style file
757 		ffile->fp->seekg(0, SEEK_SET);
758 	}
759 
760 	OffsetTable.version = READFIXED(ffile->fp);
761 	OffsetTable.numTables = READUSHORT(ffile->fp);
762 	OffsetTable.searchRange = READUSHORT(ffile->fp);
763 	OffsetTable.entrySelector = READUSHORT(ffile->fp);
764 	OffsetTable.rangeShift = READUSHORT(ffile->fp);
765 
766 #ifdef TTF_DEBUG
767 	Debug_Info("OffsetTable:\n");
768 	Debug_Info("version=%d\n", OffsetTable.version);
769 	Debug_Info("numTables=%u\n", OffsetTable.numTables);
770 	Debug_Info("searchRange=%u\n", OffsetTable.searchRange);
771 	Debug_Info("entrySelector=%u\n", OffsetTable.entrySelector);
772 	Debug_Info("rangeShift=%u\n", OffsetTable.rangeShift);
773 #endif
774 
775 	/*
776 	 * I don't know why we limit this to 40 tables, since the spec says there
777 	 * can be any number, but that's how it was when I got it.  Added a warning
778 	 * just in case it ever happens in real life. [AED]
779 	 */
780 	if (OffsetTable.numTables > 40)
781 	{
782 // TODO MESSAGE    Warning(0, "More than 40 (%d) TTF Tables in %s - some info may be lost!",
783 //            OffsetTable.numTables, ffile->filename);
784 	}
785 
786 	/* Process general font information and save it. */
787 
788 	for (i = 0; i < OffsetTable.numTables && i < 40; i++)
789 	{
790 		if (!ffile->fp->read((char *)(&Table.tag), sizeof(BYTE) * 4))
791 		{
792 			throw POV_EXCEPTION(kFileDataErr, "Cannot read TrueType font file table tag");
793 		}
794 		Table.checkSum = READULONG(ffile->fp);
795 		Table.offset   = READULONG(ffile->fp);
796 		Table.length   = READULONG(ffile->fp);
797 
798 #ifdef TTF_DEBUG
799 		Debug_Info("\nTable %d:\n",i);
800 		Debug_Info("tag=%c%c%c%c\n", Table.tag[0], Table.tag[1],
801 		                             Table.tag[2], Table.tag[3]);
802 		Debug_Info("checkSum=%u\n", Table.checkSum);
803 		Debug_Info("offset=%u\n", Table.offset);
804 		Debug_Info("length=%u\n", Table.length);
805 #endif
806 
807 		if (compare_tag4(Table.tag, tag_CharToIndexMap))
808 			ffile->cmap_table_offset = Table.offset;
809 		else if (compare_tag4(Table.tag, tag_GlyphData))
810 			ffile->glyf_table_offset = Table.offset;
811 		else if (compare_tag4(Table.tag, tag_FontHeader))
812 			head_table_offset = Table.offset;
813 		else if (compare_tag4(Table.tag, tag_IndexToLoc))
814 			loca_table_offset = Table.offset;
815 		else if (compare_tag4(Table.tag, tag_MaxProfile))
816 			maxp_table_offset = Table.offset;
817 		else if (compare_tag4(Table.tag, tag_Kerning))
818 			kern_table_offset = Table.offset;
819 		else if (compare_tag4(Table.tag, tag_HorizHeader))
820 			hhea_table_offset = Table.offset;
821 		else if (compare_tag4(Table.tag, tag_HorizMetric))
822 			hmtx_table_offset = Table.offset;
823 	}
824 
825 	if (ffile->cmap_table_offset == 0 || ffile->glyf_table_offset == 0 ||
826 	    head_table_offset == 0 || loca_table_offset == 0 ||
827 	    hhea_table_offset == 0 || hmtx_table_offset == 0 ||
828 	    maxp_table_offset == 0)
829 	{
830 // TODO MESSAGE    throw POV_EXCEPTION(kFileDataErr, "Invalid TrueType font headers in %s", ffile->filename);
831 	}
832 
833 	ProcessHeadTable(ffile, head_table_offset);  /* Need indexToLocFormat */
834 	if ((ffile->indexToLocFormat != 0 && ffile->indexToLocFormat != 1) ||
835 	    (ffile->unitsPerEm < 16 || ffile->unitsPerEm > 16384))
836 ;// TODO MESSAGE    Error("Invalid TrueType font data in %s", ffile->filename);
837 
838 	ProcessMaxpTable(ffile, maxp_table_offset);  /* Need numGlyphs */
839 	if (ffile->numGlyphs <= 0)
840 ;// TODO MESSAGE    Error("Invalid TrueType font data in %s", ffile->filename);
841 
842 	ProcessLocaTable(ffile, loca_table_offset);  /* Now we can do loca_table */
843 
844 	ProcessHheaTable(ffile, hhea_table_offset);  /* Need numberOfHMetrics */
845 	if (ffile->numberOfHMetrics <= 0)
846 ;// TODO MESSAGE    Error("Invalid TrueType font data in %s", ffile->filename);
847 
848 	ProcessHmtxTable(ffile, hmtx_table_offset);  /* Now we can read HMetrics */
849 
850 	if (kern_table_offset != 0)
851 		ProcessKernTable(ffile, kern_table_offset);
852 
853 	/* Return the information about this font */
854 
855 	return ffile;
856 }
857 
858 /*****************************************************************************
859 *
860 * FUNCTION
861 *
862 *   OpenFontFile
863 *
864 * INPUT
865 *
866 * OUTPUT
867 *
868 * RETURNS
869 *
870 * AUTHOR
871 *
872 *   Alexander Ennzmann
873 *
874 * DESCRIPTION
875 *
876 *   -
877 *
878 * CHANGES
879 *
880 *   Added support for builtin fonts - Oct 2012 [JG]
881 *
882 ******************************************************************************/
OpenFontFile(const char * asciifn,const int font_id,Parser * parser,shared_ptr<SceneData> & sceneData)883 FontFileInfo *OpenFontFile(const char *asciifn, const int font_id, Parser *parser, shared_ptr<SceneData>& sceneData)
884 {
885 	/* int i; */ /* tw, mtg */
886 	FontFileInfo *fontlist = NULL;
887 	UCS2String b, ign;
888 	if (asciifn)
889 	{
890 		UCS2String filename(ASCIItoUCS2String(asciifn));
891 
892 		/* First look to see if we have already opened this font */
893 
894 		for(fontlist = sceneData->TTFonts; fontlist != NULL; fontlist = fontlist->next)
895 			if(!parser->UCS2_strcmp(filename.c_str(), fontlist->filename))
896 				break;
897 
898 	}
899 	if(fontlist != NULL)
900 	{
901 		if(fontlist->fp == NULL)
902 		{
903 			/* We have a match, use the previous information */
904 			fontlist->fp = Locate_File(parser, sceneData, fontlist->filename,POV_File_Font_TTF,ign,true);
905 			if(fontlist->fp == NULL)
906 			{
907 				throw POV_EXCEPTION(kCannotOpenFileErr, "Cannot open font file.");
908 			}
909 		}
910 		else
911 		{
912 			#ifdef TTF_DEBUG
913 			Debug_Info("Using cached font info for %s\n", fontlist->filename);
914 			#endif
915 		}
916 	}
917 	else
918 	{
919 		/*
920 		 * We haven't looked at this font before, let's allocate a holder for the
921 		 * information and set some defaults
922 		 */
923 
924 		fontlist = (FontFileInfo *)POV_CALLOC(1, sizeof(FontFileInfo), "FontFileInfo");
925 
926 		if (asciifn)
927 		{
928 			UCS2String filename(ASCIItoUCS2String(asciifn));
929 
930 			if((fontlist->fp = Locate_File(parser, sceneData, filename,POV_File_Font_TTF,b,true)) == NULL)
931 			{
932 				throw POV_EXCEPTION(kCannotOpenFileErr, "Cannot open font file.");
933 			}
934 		}
935 		else
936 		{
937 			fontlist->fp = Internal_Font_File(font_id,b);
938 		}
939 
940 		fontlist->filename = parser->UCS2_strdup(b.c_str());
941 
942 		/*
943 		 * For Microsoft encodings 3, 1 is for Unicode
944 		 *                         3, 0 is for Non-Unicode (ie symbols)
945 		 * For Macintosh encodings 1, 0 is for Roman character set
946 		 * For Unicode encodings   0, 3 is for Unicode
947 		 */
948 		switch(sceneData->stringEncoding)
949 		{
950 			case 0: // ASCII
951 				// first choice
952 				fontlist->platformID[0] = 1;
953 				fontlist->specificID[0] = 0;
954 				// second choice
955 				fontlist->platformID[1] = 3;
956 				fontlist->specificID[1] = 1;
957 				// third choice
958 				fontlist->platformID[2] = 0;
959 				fontlist->specificID[2] = 3;
960 				// fourth choice
961 				fontlist->platformID[3] = 3;
962 				fontlist->specificID[3] = 0;
963 				break;
964 			case 1: // UTF8
965 			case 2: // System Specific
966 				// first choice
967 				fontlist->platformID[0] = 0;
968 				fontlist->specificID[0] = 3;
969 				// second choice
970 				fontlist->platformID[1] = 3;
971 				fontlist->specificID[1] = 1;
972 				// third choice
973 				fontlist->platformID[2] = 1;
974 				fontlist->specificID[2] = 0;
975 				// fourth choice
976 				fontlist->platformID[3] = 3;
977 				fontlist->specificID[3] = 0;
978 				break;
979 		}
980 		fontlist->next = sceneData->TTFonts;
981 		sceneData->TTFonts = fontlist;
982 	}
983 
984 	return fontlist;
985 }
986 
FreeFontInfo(FontFileInfo * ffi)987 void FreeFontInfo(FontFileInfo *ffi)
988 {
989 	int i;
990 	FontFileInfo *oldfont, *tempfont;
991 	GlyphPtr glyphs, tempglyph;
992 
993 	for (oldfont = ffi; oldfont != NULL;)
994 	{
995 		if (oldfont->fp != NULL)
996 			delete oldfont->fp;
997 
998 		if (oldfont->filename != NULL)
999 			POV_FREE(oldfont->filename);
1000 
1001 		if (oldfont->loca_table != NULL)
1002 			POV_FREE(oldfont->loca_table);
1003 
1004 		if (oldfont->hmtx_table != NULL)
1005 			POV_FREE(oldfont->hmtx_table);
1006 
1007 		if (oldfont->kerning_tables.nTables != 0)
1008 		{
1009 			for (i = 0; i < oldfont->kerning_tables.nTables; i++)
1010 			{
1011 				if (oldfont->kerning_tables.tables[i].kern_pairs)
1012 					POV_FREE(oldfont->kerning_tables.tables[i].kern_pairs);
1013 			}
1014 
1015 			POV_FREE(oldfont->kerning_tables.tables);
1016 		}
1017 
1018 		for (glyphs = oldfont->glyphs; glyphs != NULL;)
1019 		{
1020 			for (i = 0; i < glyphs->header.numContours; i++)
1021 			{
1022 				POV_FREE(glyphs->contours[i].flags);
1023 				POV_FREE(glyphs->contours[i].x);
1024 				POV_FREE(glyphs->contours[i].y);
1025 			}
1026 
1027 			if (glyphs->contours != NULL)
1028 				POV_FREE(glyphs->contours);
1029 
1030 			tempglyph = glyphs;
1031 			glyphs = glyphs->next;
1032 			POV_FREE(tempglyph);
1033 		}
1034 
1035 		if (oldfont->segCount != 0)
1036 		{
1037 			POV_FREE(oldfont->endCount);
1038 			POV_FREE(oldfont->startCount);
1039 			POV_FREE(oldfont->idDelta);
1040 			POV_FREE(oldfont->idRangeOffset);
1041 		}
1042 
1043 		tempfont = oldfont;
1044 		oldfont = oldfont->next;
1045 		POV_FREE(tempfont);
1046 	}
1047 }
1048 
1049 /* Process the font header table */
ProcessHeadTable(FontFileInfo * ffile,int head_table_offset)1050 void ProcessHeadTable(FontFileInfo *ffile, int head_table_offset)
1051 {
1052 	sfnt_FontHeader fontHeader;
1053 
1054 	/* Read head table */
1055 	ffile->fp->seekg(head_table_offset) ;
1056 
1057 	fontHeader.version = READFIXED(ffile->fp);
1058 	fontHeader.fontRevision = READFIXED(ffile->fp);
1059 	fontHeader.checkSumAdjustment = READULONG(ffile->fp);
1060 	fontHeader.magicNumber = READULONG(ffile->fp);   /* should be 0x5F0F3CF5 */
1061 	fontHeader.flags = READUSHORT(ffile->fp);
1062 	fontHeader.unitsPerEm = READUSHORT(ffile->fp);
1063 	fontHeader.created.bc = READULONG(ffile->fp);
1064 	fontHeader.created.ad = READULONG(ffile->fp);
1065 	fontHeader.modified.bc = READULONG(ffile->fp);
1066 	fontHeader.modified.ad = READULONG(ffile->fp);
1067 	fontHeader.xMin = READFWORD(ffile->fp);
1068 	fontHeader.yMin = READFWORD(ffile->fp);
1069 	fontHeader.xMax = READFWORD(ffile->fp);
1070 	fontHeader.yMax = READFWORD(ffile->fp);
1071 	fontHeader.macStyle = READUSHORT(ffile->fp);
1072 	fontHeader.lowestRecPPEM = READUSHORT(ffile->fp);
1073 	fontHeader.fontDirectionHint = READSHORT(ffile->fp);
1074 	fontHeader.indexToLocFormat = READSHORT(ffile->fp);
1075 	fontHeader.glyphDataFormat = READSHORT(ffile->fp);
1076 
1077 #ifdef TTF_DEBUG
1078 	Debug_Info("\nfontHeader:\n");
1079 	Debug_Info("version: %d\n",fontHeader.version);
1080 	Debug_Info("fontRevision: %d\n",fontHeader.fontRevision);
1081 	Debug_Info("checkSumAdjustment: %u\n",fontHeader.checkSumAdjustment);
1082 	Debug_Info("magicNumber: 0x%8X\n",fontHeader.magicNumber);
1083 	Debug_Info("flags: %u\n",fontHeader.flags);
1084 	Debug_Info("unitsPerEm: %u\n",fontHeader.unitsPerEm);
1085 	Debug_Info("created.bc: %u\n",fontHeader.created.bc);
1086 	Debug_Info("created.ad: %u\n",fontHeader.created.ad);
1087 	Debug_Info("modified.bc: %u\n",fontHeader.modified.bc);
1088 	Debug_Info("modified.ad: %u\n",fontHeader.modified.ad);
1089 	Debug_Info("xMin: %d\n",fontHeader.xMin);
1090 	Debug_Info("yMin: %d\n",fontHeader.yMin);
1091 	Debug_Info("xMax: %d\n",fontHeader.xMax);
1092 	Debug_Info("yMax: %d\n",fontHeader.yMax);
1093 	Debug_Info("macStyle: %u\n",fontHeader.macStyle);
1094 	Debug_Info("lowestRecPPEM: %u\n",fontHeader.lowestRecPPEM);
1095 	Debug_Info("fontDirectionHint: %d\n",fontHeader.fontDirectionHint);
1096 	Debug_Info("indexToLocFormat: %d\n",fontHeader.indexToLocFormat);
1097 	Debug_Info("glyphDataFormat: %d\n",fontHeader.glyphDataFormat);
1098 #endif
1099 
1100 	if (fontHeader.magicNumber != 0x5F0F3CF5)
1101 	{
1102 		throw POV_EXCEPTION(kFileDataErr, "Cannot read TrueType font.");
1103 	}
1104 
1105 	ffile->indexToLocFormat = fontHeader.indexToLocFormat;
1106 	ffile->unitsPerEm = fontHeader.unitsPerEm;
1107 }
1108 
1109 /* Determine the relative offsets of glyphs */
ProcessLocaTable(FontFileInfo * ffile,int loca_table_offset)1110 void ProcessLocaTable(FontFileInfo *ffile, int loca_table_offset)
1111 {
1112 	int i;
1113 
1114 	/* Move to location of table in file */
1115 	ffile->fp->seekg(loca_table_offset) ;
1116 
1117 	ffile->loca_table = (ULONG *)POV_MALLOC((ffile->numGlyphs+1) * sizeof(ULONG), "ttf");
1118 
1119 #ifdef TTF_DEBUG
1120 	Debug_Info("\nlocation table:\n");
1121 	Debug_Info("version: %s\n",(ffile->indexToLocFormat?"long":"short"));
1122 #endif
1123 
1124 	/* Now read and save the location table */
1125 
1126 	if (ffile->indexToLocFormat == 0)                  /* short version */
1127 	{
1128 		for (i = 0; i < ffile->numGlyphs; i++)
1129 		{
1130 			ffile->loca_table[i] = ((ULONG)READUSHORT(ffile->fp)) << 1;
1131 #ifdef TTF_DEBUG2
1132 			Debug_Info("loca_table[%d] @ %u\n", i, ffile->loca_table[i]);
1133 #endif
1134 		}
1135 	}
1136 	else                                               /* long version */
1137 	{
1138 		for (i = 0; i < ffile->numGlyphs; i++)
1139 		{
1140 			ffile->loca_table[i] = READULONG(ffile->fp);
1141 #ifdef TTF_DEBUG2
1142 			Debug_Info("loca_table[%d] @ %u\n", i, ffile->loca_table[i]);
1143 #endif
1144 		}
1145 	}
1146 }
1147 
1148 
1149 /*
1150  * This routine determines the total number of glyphs in a TrueType file.
1151  * Necessary so that we can allocate the proper amount of storage for the glyph
1152  * location table.
1153  */
ProcessMaxpTable(FontFileInfo * ffile,int maxp_table_offset)1154 void ProcessMaxpTable(FontFileInfo *ffile, int maxp_table_offset)
1155 {
1156 	/* seekg to the maxp table, skipping the 4 byte version number */
1157 	ffile->fp->seekg(maxp_table_offset + 4) ;
1158 
1159 	ffile->numGlyphs = READUSHORT(ffile->fp);
1160 
1161 #ifdef TTF_DEBUG
1162 	Debug_Info("\nmaximum profile table:\n");
1163 	Debug_Info("numGlyphs: %u\n", ffile->numGlyphs);
1164 #endif
1165 }
1166 
1167 
1168 /* Read the kerning information for a glyph */
ProcessKernTable(FontFileInfo * ffile,int kern_table_offset)1169 void ProcessKernTable(FontFileInfo *ffile, int kern_table_offset)
1170 {
1171 	int i, j;
1172 	USHORT temp16;
1173 	USHORT length;
1174 	KernTables *kern_table;
1175 
1176 	kern_table = &ffile->kerning_tables;
1177 
1178 	/* Move to the beginning of the kerning table, skipping the 2 byte version */
1179 	ffile->fp->seekg(kern_table_offset + 2) ;
1180 
1181 	/* Read in the number of kerning tables */
1182 
1183 	kern_table->nTables = READUSHORT(ffile->fp);
1184 	kern_table->tables = NULL;      /*<==[esp] added (in case nTables is zero)*/
1185 
1186 #ifdef TTF_DEBUG
1187 	Debug_Info("\nKerning table:\n", kern_table_offset);
1188 	Debug_Info("Offset: %d\n", kern_table_offset);
1189 	Debug_Info("Number of tables: %u\n",kern_table->nTables);
1190 #endif
1191 
1192 	/* Don't do any more work if there isn't kerning info */
1193 
1194 	if (kern_table->nTables == 0)
1195 		return;
1196 
1197 	kern_table->tables = (TTKernTable *)POV_MALLOC(kern_table->nTables * sizeof(TTKernTable),
1198 	                                "ProcessKernTable");
1199 
1200 	for (i = 0; i < kern_table->nTables; i++)
1201 	{
1202 		/* Read in a subtable */
1203 
1204 		temp16 = READUSHORT(ffile->fp);                      /* Subtable version */
1205 		length = READUSHORT(ffile->fp);                       /* Subtable length */
1206 		kern_table->tables[i].coverage = READUSHORT(ffile->fp); /* Coverage bits */
1207 
1208 #ifdef TTF_DEBUG
1209 		Debug_Info("Coverage table[%d] (0x%X):", i, kern_table->tables[i].coverage);
1210 		Debug_Info("  type %u", (kern_table->tables[i].coverage >> 8));
1211 		Debug_Info(" %s", (kern_table->tables[i].coverage & KERN_HORIZONTAL ?
1212 		                     "Horizontal" : "Vertical" ));
1213 		Debug_Info(" %s values", (kern_table->tables[i].coverage & KERN_MINIMUM ?
1214 		                     "Minimum" : "Kerning" ));
1215 		Debug_Info("%s", (kern_table->tables[i].coverage & KERN_CROSS_STREAM ?
1216 		                     " Cross-stream" : "" ));
1217 		Debug_Info("%s\n", (kern_table->tables[i].coverage & KERN_OVERRIDE ?
1218 		                     " Override" : "" ));
1219 #endif
1220 
1221 		kern_table->tables[i].kern_pairs = NULL;   /*<==[esp] added*/
1222 		kern_table->tables[i].nPairs = 0;          /*<==[esp] added*/
1223 
1224 		if ((kern_table->tables[i].coverage >> 8) == 0)
1225 		{
1226 			/* Can only handle format 0 kerning subtables */
1227 			kern_table->tables[i].nPairs = READUSHORT(ffile->fp);
1228 
1229 #ifdef TTF_DEBUG
1230 			Debug_Info("entries in table[%d]: %d\n", i, kern_table->tables[i].nPairs);
1231 #endif
1232 
1233 			temp16 = READUSHORT(ffile->fp);     /* searchRange */
1234 			temp16 = READUSHORT(ffile->fp);     /* entrySelector */
1235 			temp16 = READUSHORT(ffile->fp);     /* rangeShift */
1236 
1237 			kern_table->tables[i].kern_pairs =
1238 			(KernData *)POV_MALLOC(kern_table->tables[i].nPairs * sizeof(KernData), "Kern Pairs");
1239 
1240 			for (j = 0; j < kern_table->tables[i].nPairs; j++)
1241 			{
1242 				/* Read in a kerning pair */
1243 				kern_table->tables[i].kern_pairs[j].left = READUSHORT(ffile->fp);
1244 				kern_table->tables[i].kern_pairs[j].right = READUSHORT(ffile->fp);
1245 				kern_table->tables[i].kern_pairs[j].value = READFWORD(ffile->fp);
1246 
1247 #ifdef TTF_DEBUG2
1248 				Debug_Info("Kern pair: <%d,%d> = %d\n",
1249 				           (int)kern_table->tables[i].kern_pairs[j].left,
1250 				           (int)kern_table->tables[i].kern_pairs[j].right,
1251 				           (int)kern_table->tables[i].kern_pairs[j].value);
1252 #endif
1253 			}
1254 		}
1255 		else
1256 		{
1257 #ifdef TTF_DEBUG2
1258 			Warning(0, "Cannot handle format %u kerning data",
1259 			        (kern_table->tables[i].coverage >> 8));
1260 #endif
1261 			/*
1262 			 * seekg to the end of this table, excluding the length of the version,
1263 			 * length, and coverage USHORTs, which we have already read.
1264 			 */
1265 			ffile->fp->seekg((int)(length - 6), POV_SEEK_CUR) ;
1266 			kern_table->tables[i].nPairs = 0;
1267 		}
1268 	}
1269 }
1270 
1271 /*
1272  * This routine determines the total number of horizontal metrics.
1273  */
ProcessHheaTable(FontFileInfo * ffile,int hhea_table_offset)1274 void ProcessHheaTable(FontFileInfo *ffile, int hhea_table_offset)
1275 {
1276 #ifdef TTF_DEBUG
1277 	sfnt_HorizHeader horizHeader;
1278 
1279 	/* seekg to the hhea table */
1280 	ffile->fp->seekg(hhea_table_offset);
1281 
1282 	horizHeader.version = READFIXED(ffile->fp);
1283 	horizHeader.Ascender = READFWORD(ffile->fp);
1284 	horizHeader.Descender = READFWORD(ffile->fp);
1285 	horizHeader.LineGap = READFWORD(ffile->fp);
1286 	horizHeader.advanceWidthMax = READUFWORD(ffile->fp);
1287 	horizHeader.minLeftSideBearing = READFWORD(ffile->fp);
1288 	horizHeader.minRightSideBearing = READFWORD(ffile->fp);
1289 	horizHeader.xMaxExtent = READFWORD(ffile->fp);
1290 	horizHeader.caretSlopeRise = READSHORT(ffile->fp);
1291 	horizHeader.caretSlopeRun = READSHORT(ffile->fp);
1292 	horizHeader.reserved1 = READSHORT(ffile->fp);
1293 	horizHeader.reserved2 = READSHORT(ffile->fp);
1294 	horizHeader.reserved3 = READSHORT(ffile->fp);
1295 	horizHeader.reserved4 = READSHORT(ffile->fp);
1296 	horizHeader.reserved5 = READSHORT(ffile->fp);
1297 	horizHeader.metricDataFormat = READSHORT(ffile->fp);
1298 #else
1299 
1300 	/* seekg to the hhea table, skipping all that stuff we don't need */
1301 	ffile->fp->seekg (hhea_table_offset + 34) ;
1302 
1303 #endif
1304 
1305 	ffile->numberOfHMetrics = READUSHORT(ffile->fp);
1306 
1307 #ifdef TTF_DEBUG
1308 	Debug_Info("\nhorizontal header table:\n");
1309 	Debug_Info("Ascender: %d\n",horizHeader.Ascender);
1310 	Debug_Info("Descender: %d\n",horizHeader.Descender);
1311 	Debug_Info("LineGap: %d\n",horizHeader.LineGap);
1312 	Debug_Info("advanceWidthMax: %d\n",horizHeader.advanceWidthMax);
1313 	Debug_Info("minLeftSideBearing: %d\n",horizHeader.minLeftSideBearing);
1314 	Debug_Info("minRightSideBearing: %d\n",horizHeader.minRightSideBearing);
1315 	Debug_Info("xMaxExtent: %d\n",horizHeader.xMaxExtent);
1316 	Debug_Info("caretSlopeRise: %d\n",horizHeader.caretSlopeRise);
1317 	Debug_Info("caretSlopeRun: %d\n",horizHeader.caretSlopeRun);
1318 	Debug_Info("metricDataFormat: %d\n",horizHeader.metricDataFormat);
1319 	Debug_Info("numberOfHMetrics: %d\n",ffile->numberOfHMetrics);
1320 #endif
1321 }
1322 
ProcessHmtxTable(FontFileInfo * ffile,int hmtx_table_offset)1323 void ProcessHmtxTable (FontFileInfo *ffile, int hmtx_table_offset)
1324 {
1325 	int i;
1326 	longHorMetric *metric;
1327 	uFWord lastAW = 0;     /* Just to quiet warnings. */
1328 
1329 	ffile->fp->seekg (hmtx_table_offset) ;
1330 
1331 	ffile->hmtx_table = (longHorMetric *)POV_MALLOC(ffile->numGlyphs*sizeof(longHorMetric), "ttf");
1332 
1333 	/*
1334 	 * Read in the total glyph width, and the left side offset.  There is
1335 	 * guaranteed to be at least one longHorMetric entry in this table to
1336 	 * set the advanceWidth for the subsequent lsb entries.
1337 	 */
1338 	for (i=0, metric=ffile->hmtx_table; i < ffile->numberOfHMetrics; i++,metric++)
1339 	{
1340 		lastAW = metric->advanceWidth = READUFWORD(ffile->fp);
1341 		metric->lsb = READFWORD(ffile->fp);
1342 	}
1343 
1344 	/* Read in the remaining left offsets */
1345 	for (; i < ffile->numGlyphs; i++, metric++)
1346 	{
1347 		metric->advanceWidth = lastAW;
1348 		metric->lsb = READFWORD(ffile->fp);
1349 	}
1350 }
1351 
1352 /*****************************************************************************
1353 *
1354 * FUNCTION
1355 *
1356 *   ProcessCharacter
1357 *
1358 * INPUT
1359 *
1360 * OUTPUT
1361 *
1362 * RETURNS
1363 *
1364 * AUTHOR
1365 *
1366 *   POV-Ray Team
1367 *
1368 * DESCRIPTION
1369 *
1370 *   Finds the glyph description for the current character.
1371 *
1372 * CHANGES
1373 *
1374 *   -
1375 *
1376 ******************************************************************************/
1377 
ProcessCharacter(FontFileInfo * ffile,unsigned int search_char,unsigned int * glyph_index)1378 GlyphPtr ProcessCharacter(FontFileInfo *ffile, unsigned int search_char, unsigned int *glyph_index)
1379 {
1380 	GlyphPtr glyph;
1381 
1382 	/* See if we have already processed this glyph */
1383 	for (glyph = ffile->glyphs; glyph != NULL; glyph = glyph->next)
1384 	{
1385 		if (glyph->c == search_char)
1386 		{
1387 			/* Found it, no need to do any more work */
1388 #ifdef TTF_DEBUG
1389 			Debug_Info("Cached glyph: %c/%u\n",(char)search_char,glyph->glyph_index);
1390 #endif
1391 			*glyph_index = glyph->glyph_index;
1392 			return glyph;
1393 		}
1394 	}
1395 
1396 	*glyph_index = ProcessCharMap(ffile, search_char);
1397 
1398 	if (*glyph_index == 0)
1399 ;// TODO MESSAGE    Warning(0, "Character %d (0x%X) not found in %s", (BYTE)search_char,
1400 //            search_char, ffile->filename);
1401 
1402 	/* See if we have already processed this glyph (using the glyph index) */
1403 	for (glyph = ffile->glyphs; glyph != NULL; glyph = glyph->next)
1404 	{
1405 		if (glyph->glyph_index == *glyph_index)
1406 		{
1407 			/* Found it, no need to do any more work */
1408 #ifdef TTF_DEBUG
1409 			Debug_Info("Cached glyph: %c/%u\n",(char)search_char,glyph->glyph_index);
1410 #endif
1411 			*glyph_index = glyph->glyph_index;
1412 			return glyph;
1413 		}
1414 	}
1415 
1416 	glyph = ExtractGlyphInfo(ffile, *glyph_index, search_char);
1417 
1418 	/* Add this glyph to the ones we already know about */
1419 
1420 	glyph->next = ffile->glyphs;
1421 	ffile->glyphs = glyph;
1422 
1423 	/* Glyph is all built */
1424 
1425 	return glyph;
1426 }
1427 
1428 /*****************************************************************************
1429 *
1430 * FUNCTION
1431 *
1432 *   ProcessCharMap
1433 *
1434 * INPUT
1435 *
1436 * OUTPUT
1437 *
1438 * RETURNS
1439 *
1440 * AUTHOR
1441 *
1442 *   POV-Ray Team
1443 *
1444 * DESCRIPTION
1445 *
1446 *   Find the character mapping for 'search_char'.  We should really know
1447 *   which character set we are using (ie ISO 8859-1, Mac, Unicode, etc).
1448 *   Search char should really be a USHORT to handle double byte systems.
1449 *
1450 * CHANGES
1451 *
1452 *   961120  esp  Added check to allow Macintosh encodings to pass
1453 *
1454 ******************************************************************************/
ProcessCharMap(FontFileInfo * ffile,unsigned int search_char)1455 USHORT ProcessCharMap(FontFileInfo *ffile, unsigned int search_char)
1456 {
1457 	int initial_table_offset;
1458 	int old_table_offset;
1459 	int entry_offset;
1460 	sfnt_platformEntry cmapEntry;
1461 	sfnt_mappingTable encodingTable;
1462 	int i, j, table_count;
1463 
1464 	/* Move to the start of the character map, skipping the 2 byte version */
1465 	ffile->fp->seekg (ffile->cmap_table_offset + 2) ;
1466 
1467 	table_count = READUSHORT(ffile->fp);
1468 
1469 	#ifdef TTF_DEBUG
1470 	Debug_Info("table_count=%d\n", table_count);
1471 	#endif
1472 
1473 	/*
1474 	 * Search the tables until we find the glyph index for the search character.
1475 	 * Just return the first one we find...
1476 	 */
1477 
1478 	initial_table_offset = ffile->fp->tellg (); /* Save the initial position */
1479 
1480 	for(j = 0; j <= 3; j++)
1481 	{
1482 		ffile->fp->seekg(initial_table_offset); /* Always start new search at the initial position */
1483 
1484 		for (i = 0; i < table_count; i++)
1485 		{
1486 			cmapEntry.platformID = READUSHORT(ffile->fp);
1487 			cmapEntry.specificID = READUSHORT(ffile->fp);
1488 			cmapEntry.offset     = READULONG(ffile->fp);
1489 
1490 			#ifdef TTF_DEBUG
1491 			Debug_Info("cmapEntry: platformID=%d\n", cmapEntry.platformID);
1492 			Debug_Info("cmapEntry: specificID=%d\n", cmapEntry.specificID);
1493 			Debug_Info("cmapEntry: offset=%d\n", cmapEntry.offset);
1494 			#endif
1495 
1496 			/*
1497 			 * Check if this is the encoding table we want to use.
1498 			 * The search is done according to user preference.
1499 			 */
1500 			if ( ffile->platformID[j] != cmapEntry.platformID ) /* [JAC 01/99] */
1501 			{
1502 				continue;
1503 			}
1504 
1505 			entry_offset = cmapEntry.offset;
1506 
1507 			old_table_offset = ffile->fp->tellg (); /* Save the current position */
1508 
1509 			ffile->fp->seekg (ffile->cmap_table_offset + entry_offset) ;
1510 
1511 			encodingTable.format = READUSHORT(ffile->fp);
1512 			encodingTable.length = READUSHORT(ffile->fp);
1513 			encodingTable.version = READUSHORT(ffile->fp);
1514 
1515 			#ifdef TTF_DEBUG
1516 			Debug_Info("Encoding table, format: %u, length: %u, version: %u\n",
1517 			           encodingTable.format, encodingTable.length, encodingTable.version);
1518 			#endif
1519 
1520 			if (encodingTable.format == 0)
1521 			{
1522 				/*
1523 				 * Translation is simple - add 'entry_char' to the start of the
1524 				 * table and grab what's there.
1525 				 */
1526 				#ifdef TTF_DEBUG
1527 				Debug_Info("Apple standard index mapping\n");
1528 				#endif
1529 
1530 				return(ProcessFormat0Glyph(ffile, search_char));
1531 			}
1532 			#if 0  /* Want to get the rest of these working first */
1533 			else if (encodingTable.format == 2)
1534 			{
1535 				/* Used for multi-byte character encoding (Chinese, Japanese, etc) */
1536 				#ifdef TTF_DEBUG
1537 				Debug_Info("High-byte index mapping\n");
1538 				#endif
1539 
1540 				return(ProcessFormat2Glyph(ffile, search_char));
1541 			}
1542 			#endif
1543 			else if (encodingTable.format == 4)
1544 			{
1545 				/* Microsoft UGL encoding */
1546 				#ifdef TTF_DEBUG
1547 				Debug_Info("Microsoft standard index mapping\n");
1548 				#endif
1549 
1550 				return(ProcessFormat4Glyph(ffile, search_char));
1551 			}
1552 			else if (encodingTable.format == 6)
1553 			{
1554 				#ifdef TTF_DEBUG
1555 				Debug_Info("Trimmed table mapping\n");
1556 				#endif
1557 
1558 				return(ProcessFormat6Glyph(ffile, search_char));
1559 			}
1560 			#ifdef TTF_DEBUG
1561 			else
1562 				Debug_Info("Unsupported TrueType font index mapping format: %u\n",
1563 				           encodingTable.format);
1564 			#endif
1565 
1566 			/* Go to the next table entry if we didn't find a match */
1567 			ffile->fp->seekg (old_table_offset) ;
1568 		}
1569 	}
1570 
1571 	/*
1572 	 * No character mapping was found - very odd, we should really have had the
1573 	 * character in at least one table.  Perhaps getting here means we didn't
1574 	 * have any character mapping tables.  '0' means no mapping.
1575 	 */
1576 
1577 	return 0;
1578 }
1579 
1580 
1581 /*****************************************************************************
1582 *
1583 * FUNCTION
1584 *
1585 *   ProcessFormat0Glyph
1586 *
1587 * INPUT
1588 *
1589 * OUTPUT
1590 *
1591 * RETURNS
1592 *
1593 * AUTHOR
1594 *
1595 *   POV-Ray Team
1596 *
1597 * DESCRIPTION
1598 *
1599 * This handles the Apple standard index mapping for glyphs.
1600 * The file pointer must be pointing immediately after the version entry in the
1601 * encoding table for the next two functions to work.
1602 *
1603 * CHANGES
1604 *
1605 *   -
1606 *
1607 ******************************************************************************/
ProcessFormat0Glyph(FontFileInfo * ffile,unsigned int search_char)1608 USHORT ProcessFormat0Glyph(FontFileInfo *ffile, unsigned int search_char)
1609 {
1610 	BYTE temp_index;
1611 
1612 	ffile->fp->seekg ((int)search_char, POV_SEEK_CUR) ;
1613 
1614 	if (!ffile->fp->read ((char *)(&temp_index), 1)) /* Each index is 1 byte */
1615 	{
1616 		throw POV_EXCEPTION(kFileDataErr, "Cannot read TrueType font file.");
1617 	}
1618 
1619 	return (USHORT)(temp_index);
1620 }
1621 
1622 /*****************************************************************************
1623 *
1624 * FUNCTION
1625 *
1626 *   ProcessFormat4Glyph
1627 *
1628 * INPUT
1629 *
1630 * OUTPUT
1631 *
1632 * RETURNS
1633 *
1634 * AUTHOR
1635 *
1636 *   POV-Ray Team
1637 *
1638 * DESCRIPTION
1639 *
1640 * This handles the Microsoft standard index mapping for glyph tables
1641 *
1642 * CHANGES
1643 *
1644 *   Mar 26, 1996: Cache segment info rather than read each time.  [AED]
1645 *
1646 ******************************************************************************/
ProcessFormat4Glyph(FontFileInfo * ffile,unsigned int search_char)1647 USHORT ProcessFormat4Glyph(FontFileInfo *ffile, unsigned int search_char)
1648 {
1649 	int i;
1650 	unsigned int glyph_index = 0;  /* Set the glyph index to "not present" */
1651 
1652 	/*
1653 	 * If this is the first time we are here, read all of the segment headers,
1654 	 * and save them for later calls to this function, rather than seeking and
1655 	 * mallocing for each character
1656 	 */
1657 	if (ffile->segCount == 0)
1658 	{
1659 		USHORT temp16;
1660 
1661 		ffile->segCount = READUSHORT(ffile->fp) >> 1;
1662 		ffile->searchRange = READUSHORT(ffile->fp);
1663 		ffile->entrySelector = READUSHORT(ffile->fp);
1664 		ffile->rangeShift = READUSHORT(ffile->fp);
1665 
1666 		/* Now allocate and read in the segment arrays */
1667 
1668 		ffile->endCount = (USHORT *)POV_MALLOC(ffile->segCount * sizeof(USHORT), "ttf");
1669 		ffile->startCount = (USHORT *)POV_MALLOC(ffile->segCount * sizeof(USHORT), "ttf");
1670 		ffile->idDelta = (USHORT *)POV_MALLOC(ffile->segCount * sizeof(USHORT), "ttf");
1671 		ffile->idRangeOffset = (USHORT *)POV_MALLOC(ffile->segCount * sizeof(USHORT), "ttf");
1672 
1673 		for (i = 0; i < ffile->segCount; i++)
1674 		{
1675 			ffile->endCount[i] = READUSHORT(ffile->fp);
1676 		}
1677 
1678 		temp16 = READUSHORT(ffile->fp);  /* Skip over 'reservedPad' */
1679 
1680 		for (i = 0; i < ffile->segCount; i++)
1681 		{
1682 			ffile->startCount[i] = READUSHORT(ffile->fp);
1683 		}
1684 
1685 		for (i = 0; i < ffile->segCount; i++)
1686 		{
1687 			ffile->idDelta[i] = READUSHORT(ffile->fp);
1688 		}
1689 
1690 		/* location of start of idRangeOffset */
1691 		ffile->glyphIDoffset = ffile->fp->tellg () ;
1692 
1693 		for (i = 0; i < ffile->segCount; i++)
1694 		{
1695 			ffile->idRangeOffset[i] = READUSHORT(ffile->fp);
1696 		}
1697 	}
1698 
1699 	/* Search the segments for our character */
1700 
1701 glyph_search:
1702 	for (i = 0; i < ffile->segCount; i++)
1703 	{
1704 		if (search_char <= ffile->endCount[i])
1705 		{
1706 			if (search_char >= ffile->startCount[i])
1707 			{
1708 				/* Found correct range for this character */
1709 
1710 				if (ffile->idRangeOffset[i] == 0)
1711 				{
1712 					glyph_index = search_char + ffile->idDelta[i];
1713 				}
1714 				else
1715 				{
1716 					/*
1717 					 * Alternate encoding of glyph indices, relies on a quite unusual way
1718 					 * of storing the offsets.  We need the *2s because we are talking
1719 					 * about addresses of shorts and not bytes.
1720 					 *
1721 					 * (glyphIDoffset + i*2 + idRangeOffset[i]) == &idRangeOffset[i]
1722 					 */
1723 					ffile->fp->seekg (ffile->glyphIDoffset + 2*i + ffile->idRangeOffset[i]+
1724 					                 2*(search_char - ffile->startCount[i]));
1725 
1726 					glyph_index = READUSHORT(ffile->fp);
1727 
1728 					if (glyph_index != 0)
1729 						glyph_index = glyph_index + ffile->idDelta[i];
1730 				}
1731 			}
1732 			break;
1733 		}
1734 	}
1735 
1736 	/*
1737 	 * If we haven't found the character yet, and this is the first time to
1738 	 * search the tables, try looking in the Unicode user space, since this
1739 	 * is the location Microsoft recommends for symbol characters like those
1740 	 * in wingdings and dingbats.
1741 	 */
1742 	if (glyph_index == 0 && search_char < 0x100)
1743 	{
1744 		search_char += 0xF000;
1745 #ifdef TTF_DEBUG
1746 		Debug_Info("Looking for glyph in Unicode user space (0x%X)\n", search_char);
1747 #endif
1748 		goto glyph_search;
1749 	}
1750 
1751 	/* Deallocate the memory we used for the segment arrays */
1752 
1753 	return glyph_index;
1754 }
1755 
1756 /*****************************************************************************
1757 *
1758 * FUNCTION
1759 *
1760 *   ProcessFormat6Glyph
1761 *
1762 * INPUT
1763 *
1764 * OUTPUT
1765 *
1766 * RETURNS
1767 *
1768 * AUTHOR
1769 *
1770 *   POV-Ray Team
1771 *
1772 * DESCRIPTION
1773 *
1774 *  This handles the trimmed table mapping for glyphs.
1775 *
1776 * CHANGES
1777 *
1778 *   -
1779 *
1780 ******************************************************************************/
ProcessFormat6Glyph(FontFileInfo * ffile,unsigned int search_char)1781 USHORT ProcessFormat6Glyph(FontFileInfo *ffile, unsigned int search_char)
1782 {
1783 	USHORT firstCode, entryCount;
1784 	USHORT glyph_index;
1785 
1786 	firstCode = READUSHORT(ffile->fp);
1787 	entryCount = READUSHORT(ffile->fp);
1788 
1789 	if (search_char >= firstCode && search_char < firstCode + entryCount)
1790 	{
1791 		ffile->fp->seekg (((int)(search_char - firstCode))*2, POV_SEEK_CUR) ;
1792 		glyph_index = READUSHORT(ffile->fp);
1793 	}
1794 	else
1795 		glyph_index = 0;
1796 
1797 	return glyph_index;
1798 }
1799 
1800 
1801 /*****************************************************************************
1802 *
1803 * FUNCTION
1804 *
1805 *   ExtractGlyphInfo
1806 *
1807 * INPUT
1808 *
1809 * OUTPUT
1810 *
1811 * RETURNS
1812 *
1813 * AUTHOR
1814 *
1815 *   POV-Ray Team
1816 *
1817 * DESCRIPTION
1818 *
1819 *   Change TTF outline information for the glyph(s) into a useful format
1820 *
1821 * CHANGES
1822 *
1823 *   -
1824 *
1825 ******************************************************************************/
ExtractGlyphInfo(FontFileInfo * ffile,unsigned int glyph_index,unsigned int c)1826 GlyphPtr ExtractGlyphInfo(FontFileInfo *ffile, unsigned int glyph_index, unsigned int c)
1827 {
1828 	GlyphOutline *ttglyph;
1829 	GlyphPtr glyph;
1830 
1831 	ttglyph = ExtractGlyphOutline(ffile, glyph_index, c);
1832 
1833 	/*
1834 	 * Convert the glyph outline information from TrueType layout into a more
1835 	 * easily processed format
1836 	 */
1837 
1838 	glyph = ConvertOutlineToGlyph(ffile, ttglyph);
1839 	glyph->c = c;
1840 	glyph->glyph_index = glyph_index;
1841 	glyph->myMetrics = ttglyph->myMetrics;
1842 
1843 	/* Free up outline information */
1844 
1845 	if (ttglyph)
1846 	{
1847 		if (ttglyph->y) POV_FREE(ttglyph->y);
1848 		if (ttglyph->x) POV_FREE(ttglyph->x);
1849 		if (ttglyph->endPoints) POV_FREE(ttglyph->endPoints);
1850 		if (ttglyph->flags) POV_FREE(ttglyph->flags);
1851 
1852 		POV_FREE(ttglyph);
1853 	}
1854 
1855 #ifdef TTF_DEBUG3
1856 	int i, j;
1857 
1858 	Debug_Info("// Character '%c'\n", (char)c);
1859 
1860 	for(i = 0; i < (int)glyph->header.numContours; i++)
1861 	{
1862 		Debug_Info("BYTE gGlypthFlags_%c_%d[] = \n", (char)c, i);
1863 		Debug_Info("{");
1864 		for(j = 0; j <= (int)glyph->contours[i].count; j++)
1865 		{
1866 			if((j % 10) == 0)
1867 				Debug_Info("\n\t");
1868 			Debug_Info("0x%x, ", (unsigned int)glyph->contours[i].flags[j]);
1869 		}
1870 		Debug_Info("\n};\n\n");
1871 
1872 		Debug_Info("DBL gGlypthX_%c_%d[] = \n", (char)c, i);
1873 		Debug_Info("{");
1874 		for(j = 0; j <= (int)glyph->contours[i].count; j++)
1875 		{
1876 			if((j % 10) == 0)
1877 				Debug_Info("\n\t");
1878 			Debug_Info("%f, ", (DBL)glyph->contours[i].x[j]);
1879 		}
1880 		Debug_Info("\n};\n\n");
1881 
1882 		Debug_Info("DBL gGlypthY_%c_%d[] = \n", (char)c, i);
1883 		Debug_Info("{");
1884 		for(j = 0; j <= (int)glyph->contours[i].count; j++)
1885 		{
1886 			if((j % 10) == 0)
1887 				Debug_Info("\n\t");
1888 			Debug_Info("%f, ", (DBL)glyph->contours[i].y[j]);
1889 		}
1890 		Debug_Info("\n};\n\n");
1891 	}
1892 
1893 	Debug_Info("Contour gGlypthContour_%c[] = \n", (char)c);
1894 	Debug_Info("{\n");
1895 	for(i = 0; i < glyph->header.numContours; i++)
1896 	{
1897 		Debug_Info("\t{\n");
1898 		Debug_Info("\t\t%u, // inside_flag \n", (unsigned int)glyph->contours[i].inside_flag);
1899 		Debug_Info("\t\t%u, // count \n", (unsigned int)glyph->contours[i].count);
1900 		Debug_Info("\t\tgGlypthFlags_%c_%d, // flags[]\n", (char)c, i);
1901 		Debug_Info("\t\tgGlypthX_%c_%d, // x[]\n", (char)c, i);
1902 		Debug_Info("\t\tgGlypthY_%c_%d // y[]\n", (char)c, i);
1903 		Debug_Info("\t},\n");
1904 	}
1905 	Debug_Info("\n};\n\n");
1906 
1907 	Debug_Info("Glyph gGlypth_%c = \n", (char)c);
1908 	Debug_Info("{\n");
1909 	Debug_Info("\t{ // header\n");
1910 	Debug_Info("\t\t%u, // header.numContours \n", (unsigned int)glyph->header.numContours);
1911 	Debug_Info("\t\t%f, // header.xMin\n", (DBL)glyph->header.xMin);
1912 	Debug_Info("\t\t%f, // header.yMin\n", (DBL)glyph->header.yMin);
1913 	Debug_Info("\t\t%f, // header.xMax\n", (DBL)glyph->header.xMax);
1914 	Debug_Info("\t\t%f // header.yMax\n", (DBL)glyph->header.yMax);
1915 	Debug_Info("\t},\n");
1916 	Debug_Info("\t%u, // glyph_index\n", (unsigned int)glyph->glyph_index);
1917 	Debug_Info("\tgGlypthContour_%c, // contours[]\n", (char)c);
1918 	Debug_Info("\t%u, // unitsPerEm\n", (unsigned int)glyph->unitsPerEm);
1919 	Debug_Info("\tNULL, // next\n");
1920 	Debug_Info("\t%u, // c\n", (unsigned int)glyph->c);
1921 	Debug_Info("\t%u // myMetrics\n", (unsigned int)glyph->myMetrics);
1922 
1923 	Debug_Info("};\n\n");
1924 #endif
1925 
1926 	return glyph;
1927 }
1928 
1929 
1930 
1931 /*****************************************************************************
1932 *
1933 * FUNCTION
1934 *
1935 *   ExtractGlyphOutline
1936 *
1937 * INPUT
1938 *
1939 * OUTPUT
1940 *
1941 * RETURNS
1942 *
1943 * AUTHOR
1944 *
1945 *   POV-Ray Team
1946 *
1947 * DESCRIPTION
1948 *
1949 *   Read the contour information for a specific glyph.  This has to be a
1950 *   separate routine from ExtractGlyphInfo because we call it recurisvely
1951 *   for multiple component glyphs.
1952 *
1953 * CHANGES
1954 *
1955 *   -
1956 *
1957 ******************************************************************************/
ExtractGlyphOutline(FontFileInfo * ffile,unsigned int glyph_index,unsigned int c)1958 GlyphOutline *ExtractGlyphOutline(FontFileInfo *ffile, unsigned int glyph_index, unsigned int c)
1959 {
1960 	int i;
1961 	USHORT n;
1962 	SHORT nc;
1963 	GlyphOutline *ttglyph;
1964 
1965 	ttglyph = (GlyphOutline *)POV_CALLOC(1, sizeof(GlyphOutline), "ttf");
1966 	ttglyph->myMetrics = glyph_index;
1967 
1968 	/* Have to treat space characters differently */
1969 	if (c != ' ')
1970 	{
1971 		ffile->fp->seekg (ffile->glyf_table_offset+ffile->loca_table[glyph_index]);
1972 
1973 		ttglyph->header.numContours = READSHORT(ffile->fp);
1974 		ttglyph->header.xMin = READFWORD(ffile->fp);   /* These may be  */
1975 		ttglyph->header.yMin = READFWORD(ffile->fp);   /* unreliable in */
1976 		ttglyph->header.xMax = READFWORD(ffile->fp);   /* some fonts.   */
1977 		ttglyph->header.yMax = READFWORD(ffile->fp);
1978 	}
1979 
1980 #ifdef TTF_DEBUG
1981 	Debug_Info("ttglyph->header:\n");
1982 	Debug_Info("glyph_index=%d\n", glyph_index);
1983 	Debug_Info("loca_table[%d]=%d\n",glyph_index,ffile->loca_table[glyph_index]);
1984 	Debug_Info("numContours=%d\n", (int)ttglyph->header.numContours);
1985 #endif
1986 
1987 	nc = ttglyph->header.numContours;
1988 
1989 	/*
1990 	 * A positive number of contours means a regular glyph, with possibly
1991 	 * several separate line segments making up the outline.
1992 	 */
1993 	if (nc > 0)
1994 	{
1995 		FWord coord;
1996 		BYTE flag, repeat_count;
1997 		USHORT temp16;
1998 
1999 		/* Grab the contour endpoints */
2000 
2001 		ttglyph->endPoints = (USHORT *)POV_MALLOC(nc * sizeof(USHORT), "ttf");
2002 
2003 		for (i = 0; i < nc; i++)
2004 		{
2005 			ttglyph->endPoints[i] = READUSHORT(ffile->fp);
2006 #ifdef TTF_DEBUG
2007 			Debug_Info("endPoints[%d]=%d\n", i, ttglyph->endPoints[i]);
2008 #endif
2009 		}
2010 
2011 		/* Skip over the instructions */
2012 		temp16 = READUSHORT(ffile->fp);
2013 		ffile->fp->seekg (temp16, POV_SEEK_CUR);
2014 #ifdef TTF_DEBUG
2015 		Debug_Info("skipping instruction bytes: %d\n", temp16);
2016 #endif
2017 
2018 		/* Determine the number of points making up this glyph */
2019 
2020 		n = ttglyph->numPoints = ttglyph->endPoints[nc - 1] + 1;
2021 #ifdef TTF_DEBUG
2022 		Debug_Info("numPoints=%d\n", ttglyph->numPoints);
2023 #endif
2024 
2025 		/* Read the flags */
2026 
2027 		ttglyph->flags = (BYTE *)POV_MALLOC(n * sizeof(BYTE), "ttf");
2028 
2029 		for (i = 0; i < ttglyph->numPoints; i++)
2030 		{
2031 			if (!ffile->fp->read((char *)(&ttglyph->flags[i]), sizeof(BYTE)))
2032 			{
2033 				throw POV_EXCEPTION(kFileDataErr, "Cannot read TrueType font file.");
2034 			}
2035 
2036 			if (ttglyph->flags[i] & REPEAT_FLAGS)
2037 			{
2038 				if (!ffile->fp->read((char *)(&repeat_count), sizeof(BYTE)))
2039 				{
2040 					throw POV_EXCEPTION(kFileDataErr, "Cannot read TrueType font file.");
2041 				}
2042 				for (; repeat_count > 0; repeat_count--, i++)
2043 				{
2044 #ifdef TTF_DEBUG
2045 					if (i>=n)
2046 					{
2047 						Debug_Info("readflags ERROR: i >= n (%d > %d)\n", i, n);
2048 					}
2049 #endif
2050 					if (i<n)      /* hack around a bug that is trying to write too many flags */
2051 						ttglyph->flags[i + 1] = ttglyph->flags[i];
2052 				}
2053 			}
2054 		}
2055 #ifdef  TTF_DEBUG
2056 		Debug_Info("flags:");
2057 		for (i=0; i<n; i++)
2058 			Debug_Info(" %02x", ttglyph->flags[i]);
2059 		Debug_Info("\n");
2060 #endif
2061 		/* Read the coordinate vectors */
2062 
2063 		ttglyph->x = (DBL *)POV_MALLOC(n * sizeof(DBL), "ttf");
2064 		ttglyph->y = (DBL *)POV_MALLOC(n * sizeof(DBL), "ttf");
2065 
2066 		coord = 0;
2067 
2068 		for (i = 0; i < ttglyph->numPoints; i++)
2069 		{
2070 			/* Read each x coordinate */
2071 
2072 			flag = ttglyph->flags[i];
2073 
2074 			if (flag & XSHORT)
2075 			{
2076 				BYTE temp8;
2077 
2078 				if (!ffile->fp->read((char *)(&temp8), 1))
2079 				{
2080 					throw POV_EXCEPTION(kFileDataErr, "Cannot read TrueType font file.");
2081 				}
2082 
2083 				if (flag & SHORT_X_IS_POS)
2084 					coord += temp8;
2085 				else
2086 					coord -= temp8;
2087 			}
2088 			else if (!(flag & NEXT_X_IS_ZERO))
2089 			{
2090 				coord += READSHORT(ffile->fp);
2091 			}
2092 
2093 			/* Find our own maximum and minimum x coordinates */
2094 			if (coord > ttglyph->header.xMax)
2095 				ttglyph->header.xMax = coord;
2096 			if (coord < ttglyph->header.xMin)
2097 				ttglyph->header.xMin = coord;
2098 
2099 			ttglyph->x[i] = (DBL)coord / (DBL)ffile->unitsPerEm;
2100 		}
2101 
2102 		coord = 0;
2103 
2104 		for (i = 0; i < ttglyph->numPoints; i++)
2105 		{
2106 			/* Read each y coordinate */
2107 
2108 			flag = ttglyph->flags[i];
2109 
2110 			if (flag & YSHORT)
2111 			{
2112 				BYTE temp8;
2113 
2114 				if (!ffile->fp->read((char *)(&temp8), 1))
2115 				{
2116 					throw POV_EXCEPTION(kFileDataErr, "Cannot read TrueType font file.");
2117 				}
2118 
2119 				if (flag & SHORT_Y_IS_POS)
2120 					coord += temp8;
2121 				else
2122 					coord -= temp8;
2123 			}
2124 			else if (!(flag & NEXT_Y_IS_ZERO))
2125 			{
2126 				coord += READSHORT(ffile->fp);
2127 			}
2128 
2129 			/* Find out our own maximum and minimum y coordinates */
2130 			if (coord > ttglyph->header.yMax)
2131 				ttglyph->header.yMax = coord;
2132 			if (coord < ttglyph->header.yMin)
2133 				ttglyph->header.yMin = coord;
2134 
2135 			ttglyph->y[i] = (DBL)coord / (DBL)ffile->unitsPerEm;
2136 		}
2137 	}
2138 	/*
2139 	 * A negative number for numContours means that this glyph is
2140 	 * made up of several separate glyphs.
2141 	 */
2142 	else if (nc < 0)
2143 	{
2144 		USHORT flags;
2145 
2146 		ttglyph->header.numContours = 0;
2147 		ttglyph->numPoints = 0;
2148 
2149 		do
2150 		{
2151 			GlyphOutline *sub_ttglyph;
2152 			unsigned int sub_glyph_index;
2153 			int   current_pos;
2154 			SHORT arg1, arg2;
2155 			DBL xoff = 0, yoff = 0;
2156 			DBL xscale = 1, yscale = 1;
2157 			DBL scale01 = 0, scale10 = 0;
2158 			USHORT n2;
2159 			SHORT nc2;
2160 
2161 			flags = READUSHORT(ffile->fp);
2162 			sub_glyph_index = READUSHORT(ffile->fp);
2163 
2164 #ifdef TTF_DEBUG
2165 			Debug_Info("sub_glyph %d: ", sub_glyph_index);
2166 #endif
2167 
2168 			if (flags & ARG_1_AND_2_ARE_WORDS)
2169 			{
2170 #ifdef TTF_DEBUG
2171 				Debug_Info("ARG_1_AND_2_ARE_WORDS ");
2172 #endif
2173 				arg1 = READSHORT(ffile->fp);
2174 				arg2 = READSHORT(ffile->fp);
2175 			}
2176 			else
2177 			{
2178 				arg1 = READUSHORT(ffile->fp);
2179 				arg2 = arg1 & 0xFF;
2180 				arg1 = (arg1 >> 8) & 0xFF;
2181 			}
2182 
2183 #ifdef TTF_DEBUG
2184 			if (flags & ROUND_XY_TO_GRID)
2185 			{
2186 				Debug_Info("ROUND_XY_TO_GRID ");
2187 			}
2188 
2189 			if (flags & MORE_COMPONENTS)
2190 			{
2191 				Debug_Info("MORE_COMPONENTS ");
2192 			}
2193 #endif
2194 
2195 			if (flags & WE_HAVE_A_SCALE)
2196 			{
2197 				xscale = yscale = (DBL)READSHORT(ffile->fp)/0x4000;
2198 #ifdef TTF_DEBUG
2199 				Debug_Info("WE_HAVE_A_SCALE ");
2200 				Debug_Info("xscale = %lf\t", xscale);
2201 				Debug_Info("scale01 = %lf\n", scale01);
2202 				Debug_Info("scale10 = %lf\t", scale10);
2203 				Debug_Info("yscale = %lf\n", yscale);
2204 #endif
2205 			}
2206 			else if (flags & WE_HAVE_AN_X_AND_Y_SCALE)
2207 			{
2208 				xscale = (DBL)READSHORT(ffile->fp)/0x4000;
2209 				yscale = (DBL)READSHORT(ffile->fp)/0x4000;
2210 #ifdef TTF_DEBUG
2211 				Debug_Info("WE_HAVE_AN_X_AND_Y_SCALE ");
2212 				Debug_Info("xscale = %lf\t", xscale);
2213 				Debug_Info("scale01 = %lf\n", scale01);
2214 				Debug_Info("scale10 = %lf\t", scale10);
2215 				Debug_Info("yscale = %lf\n", yscale);
2216 #endif
2217 			}
2218 			else if (flags & WE_HAVE_A_TWO_BY_TWO)
2219 			{
2220 				xscale  = (DBL)READSHORT(ffile->fp)/0x4000;
2221 				scale01 = (DBL)READSHORT(ffile->fp)/0x4000;
2222 				scale10 = (DBL)READSHORT(ffile->fp)/0x4000;
2223 				yscale  = (DBL)READSHORT(ffile->fp)/0x4000;
2224 #ifdef TTF_DEBUG
2225 				Debug_Info("WE_HAVE_A_TWO_BY_TWO ");
2226 				Debug_Info("xscale = %lf\t", xscale);
2227 				Debug_Info("scale01 = %lf\n", scale01);
2228 				Debug_Info("scale10 = %lf\t", scale10);
2229 				Debug_Info("yscale = %lf\n", yscale);
2230 #endif
2231 			}
2232 
2233 			if (flags & ARGS_ARE_XY_VALUES)
2234 			{
2235 				xoff = (DBL)arg1 / ffile->unitsPerEm;
2236 				yoff = (DBL)arg2 / ffile->unitsPerEm;
2237 
2238 #ifdef TTF_DEBUG
2239 				Debug_Info("ARGS_ARE_XY_VALUES ");
2240 				Debug_Info("\narg1 = %d  xoff = %lf\t", arg1, xoff);
2241 				Debug_Info("arg2 = %d  yoff = %lf\n", arg2, yoff);
2242 #endif
2243 			}
2244 			else  /* until I understand how this method works... */
2245 			{
2246 // TODO MESSAGE        Warning(0, "Cannot handle part of glyph %d (0x%X).", c, c);
2247 				continue;
2248 			}
2249 
2250 			if (flags & USE_MY_METRICS)
2251 			{
2252 #ifdef TTF_DEBUG
2253 				Debug_Info("USE_MY_METRICS ");
2254 #endif
2255 				ttglyph->myMetrics = sub_glyph_index;
2256 			}
2257 
2258 			current_pos = ffile->fp->tellg () ;
2259 			sub_ttglyph = ExtractGlyphOutline(ffile, sub_glyph_index, c);
2260 			ffile->fp->seekg (current_pos) ;
2261 
2262 			if ((nc2 = sub_ttglyph->header.numContours) == 0)
2263 				continue;
2264 
2265 			nc = ttglyph->header.numContours;
2266 			n = ttglyph->numPoints;
2267 			n2 = sub_ttglyph->numPoints;
2268 
2269 			ttglyph->endPoints = (USHORT *)POV_REALLOC(ttglyph->endPoints,
2270 			                                 (nc + nc2) * sizeof(USHORT), "ttf");
2271 			ttglyph->flags = (BYTE *)POV_REALLOC(ttglyph->flags, (n+n2)*sizeof(BYTE), "ttf");
2272 			ttglyph->x = (DBL *)POV_REALLOC(ttglyph->x, (n + n2) * sizeof(DBL), "ttf");
2273 			ttglyph->y = (DBL *)POV_REALLOC(ttglyph->y, (n + n2) * sizeof(DBL), "ttf");
2274 
2275 			/* Add the sub glyph info to the end of the current glyph */
2276 
2277 			ttglyph->header.numContours += nc2;
2278 			ttglyph->numPoints += n2;
2279 
2280 			for (i = 0; i < nc2; i++)
2281 			{
2282 				ttglyph->endPoints[i + nc] = sub_ttglyph->endPoints[i] + n;
2283 #ifdef TTF_DEBUG
2284 				Debug_Info("endPoints[%d]=%d\n", i + nc, ttglyph->endPoints[i + nc]);
2285 #endif
2286 			}
2287 
2288 			for (i = 0; i < n2; i++)
2289 			{
2290 #ifdef TTF_DEBUG
2291 				Debug_Info("x[%d]=%lf\t", i, sub_ttglyph->x[i]);
2292 				Debug_Info("y[%d]=%lf\n", i, sub_ttglyph->y[i]);
2293 #endif
2294 				ttglyph->flags[i + n] = sub_ttglyph->flags[i];
2295 				ttglyph->x[i + n] = xscale * sub_ttglyph->x[i] +
2296 				                    scale01 * sub_ttglyph->y[i] + xoff;
2297 				ttglyph->y[i + n] = scale10 * sub_ttglyph->x[i] +
2298 				                    yscale * sub_ttglyph->y[i] + yoff;
2299 
2300 #ifdef TTF_DEBUG
2301 				Debug_Info("x[%d]=%lf\t", i+n, ttglyph->x[i+n]);
2302 				Debug_Info("y[%d]=%lf\n", i+n, ttglyph->y[i+n]);
2303 #endif
2304 
2305 				if (ttglyph->x[i + n] < ttglyph->header.xMin)
2306 					ttglyph->header.xMin = ttglyph->x[i + n];
2307 
2308 				if (ttglyph->x[i + n] > ttglyph->header.xMax)
2309 					ttglyph->header.xMax = ttglyph->x[i + n];
2310 
2311 				if (ttglyph->y[i + n] < ttglyph->header.yMin)
2312 					ttglyph->header.yMin = ttglyph->y[i + n];
2313 
2314 				if (ttglyph->y[i + n] > ttglyph->header.yMax)
2315 					ttglyph->header.yMax = ttglyph->y[i + n];
2316 			}
2317 
2318 			/* Free up the sub glyph outline information */
2319 
2320 			if (sub_ttglyph->y) POV_FREE(sub_ttglyph->y);
2321 			if (sub_ttglyph->x) POV_FREE(sub_ttglyph->x);
2322 			if (sub_ttglyph->endPoints) POV_FREE(sub_ttglyph->endPoints);
2323 			if (sub_ttglyph->flags) POV_FREE(sub_ttglyph->flags);
2324 
2325 			POV_FREE(sub_ttglyph);
2326 		} while (flags & MORE_COMPONENTS);
2327 	}
2328 
2329 #ifdef TTF_DEBUG
2330 		Debug_Info("xMin=%d\n",ttglyph->header.xMin);
2331 		Debug_Info("yMin=%d\n",ttglyph->header.yMin);
2332 		Debug_Info("xMax=%d\n",ttglyph->header.xMax);
2333 		Debug_Info("yMax=%d\n",ttglyph->header.yMax);
2334 #endif
2335 
2336 	return ttglyph;
2337 }
2338 
2339 
2340 
2341 /*****************************************************************************
2342 *
2343 * FUNCTION
2344 *
2345 *   ConvertOutlineToGlyph
2346 *
2347 * INPUT
2348 *
2349 * OUTPUT
2350 *
2351 * RETURNS
2352 *
2353 * AUTHOR
2354 *
2355 *   POV-Ray Team
2356 *
2357 * DESCRIPTION
2358 *
2359 * Transform a glyph from TrueType storage format to something a little easier
2360 * to manage.
2361 *
2362 * CHANGES
2363 *
2364 *   -
2365 *
2366 ******************************************************************************/
ConvertOutlineToGlyph(FontFileInfo * ffile,const GlyphOutline * ttglyph)2367 GlyphPtr ConvertOutlineToGlyph(FontFileInfo *ffile, const GlyphOutline *ttglyph)
2368 {
2369 	GlyphPtr glyph;
2370 	DBL *temp_x, *temp_y;
2371 	BYTE *temp_f;
2372 	USHORT i, j, last_j;
2373 
2374 	/* Create storage for this glyph */
2375 
2376 	glyph = (Glyph *)POV_MALLOC(sizeof(Glyph), "ttf");
2377 	if (ttglyph->header.numContours > 0)
2378 	{
2379 		glyph->contours = (Contour *)POV_MALLOC(ttglyph->header.numContours * sizeof(Contour), "ttf");
2380 	}
2381 	else
2382 	{
2383 		glyph->contours = NULL;
2384 	}
2385 
2386 	/* Copy sizing information about this glyph */
2387 
2388 	POV_MEMCPY(&glyph->header, &ttglyph->header, sizeof(GlyphHeader));
2389 
2390 	/* Keep track of the size for this glyph */
2391 
2392 	glyph->unitsPerEm = ffile->unitsPerEm;
2393 
2394 	/* Now copy the vertex information into the contours */
2395 
2396 	for (i = 0, last_j = 0; i < (USHORT) ttglyph->header.numContours; i++)
2397 	{
2398 		/* Figure out number of points in contour */
2399 
2400 		j = ttglyph->endPoints[i] - last_j + 1;
2401 
2402 		/* Copy the coordinate information into the glyph */
2403 
2404 		temp_x = (DBL *)POV_MALLOC((j + 1) * sizeof(DBL), "ttf");
2405 		temp_y = (DBL *)POV_MALLOC((j + 1) * sizeof(DBL), "ttf");
2406 
2407 		temp_f = (BYTE *)POV_MALLOC((j + 1) * sizeof(BYTE), "ttf");
2408 		POV_MEMCPY(temp_x, &ttglyph->x[last_j], j * sizeof(DBL));
2409 		POV_MEMCPY(temp_y, &ttglyph->y[last_j], j * sizeof(DBL));
2410 
2411 		POV_MEMCPY(temp_f, &ttglyph->flags[last_j], j * sizeof(BYTE));
2412 		temp_x[j] = ttglyph->x[last_j];
2413 		temp_y[j] = ttglyph->y[last_j];
2414 		temp_f[j] = ttglyph->flags[last_j];
2415 
2416 		/* Figure out if this is an inside or outside contour */
2417 
2418 		glyph->contours[i].inside_flag = 0;
2419 
2420 		/* Plug in the reset of the contour components into the glyph */
2421 
2422 		glyph->contours[i].count = j;
2423 		glyph->contours[i].x = temp_x;
2424 		glyph->contours[i].y = temp_y;
2425 		glyph->contours[i].flags = temp_f;
2426 
2427 		/*
2428 		 * Set last_j to point to the beginning of the next contour's coordinate
2429 		 * information
2430 		 */
2431 
2432 		last_j = ttglyph->endPoints[i] + 1;
2433 	}
2434 
2435 	/* Show statistics about this glyph */
2436 
2437 #ifdef TTF_DEBUG
2438 	Debug_Info("Number of contours: %u\n", glyph->header.numContours);
2439 	Debug_Info("X extent: [%f, %f]\n",
2440 		(DBL)glyph->header.xMin / (DBL)ffile->unitsPerEm,
2441 		(DBL)glyph->header.xMax / (DBL)ffile->unitsPerEm);
2442 
2443 	Debug_Info("Y extent: [%f, %f]\n",
2444 		(DBL)glyph->header.yMin / (DBL)ffile->unitsPerEm,
2445 		(DBL)glyph->header.yMax / (DBL)ffile->unitsPerEm);
2446 
2447 	Debug_Info("Converted coord list(%d):\n", (int)glyph->header.numContours);
2448 
2449 	for (i=0;i<(USHORT)glyph->header.numContours;i++)
2450 	{
2451 		for (j=0;j<=glyph->contours[i].count;j++)
2452 			Debug_Info("  %c[%f, %f]\n",
2453 				(glyph->contours[i].flags[j] & ONCURVE ? '*' : ' '),
2454 				glyph->contours[i].x[j], glyph->contours[i].y[j]);
2455 		Debug_Info("\n");
2456 	}
2457 #endif
2458 
2459 	return glyph;
2460 }
2461 
2462 /* Test to see if "point" is inside the splined polygon "points". */
Inside_Glyph(double x,double y,const GlyphStruct * glyph) const2463 bool TrueType::Inside_Glyph(double x, double y, const GlyphStruct* glyph) const
2464 {
2465 	int i, j, k, n, n1, crossings;
2466 	int qi, ri, qj, rj;
2467 	Contour *contour;
2468 	double xt[3], yt[3], roots[2];
2469 	DBL *xv, *yv;
2470 	double x0, x1, x2, t;
2471 	double y0, y1, y2;
2472 	double m, b, xc;
2473 	BYTE *fv;
2474 
2475 	crossings = 0;
2476 
2477 	n = glyph->header.numContours;
2478 
2479 	contour = glyph->contours;
2480 
2481 	for (i = 0; i < n; i++)
2482 	{
2483 		xv = contour[i].x;
2484 		yv = contour[i].y;
2485 		fv = contour[i].flags;
2486 		x0 = xv[0];
2487 		y0 = yv[0];
2488 		n1 = contour[i].count;
2489 
2490 		for (j = 1; j <= n1; j++)
2491 		{
2492 			x1 = xv[j];
2493 			y1 = yv[j];
2494 
2495 			if (fv[j] & ONCURVE)
2496 			{
2497 				/* Straight line - first set up for the next */
2498 				/* Now do the crossing test */
2499 
2500 				qi = ri = qj = rj = 0;
2501 
2502 				if (y0 == y1)
2503 					goto end_line_test;
2504 
2505 				/* if (fabs((y - y0) / (y1 - y0)) < EPSILON) goto end_line_test; */
2506 
2507 				if (y0 < y)
2508 					qi = 1;
2509 
2510 				if (y1 < y)
2511 					qj = 1;
2512 
2513 				if (qi == qj)
2514 					goto end_line_test;
2515 
2516 				if (x0 > x)
2517 					ri = 1;
2518 
2519 				if (x1 > x)
2520 					rj = 1;
2521 
2522 				if (ri & rj)
2523 				{
2524 					crossings++;
2525 					goto end_line_test;
2526 				}
2527 
2528 				if ((ri | rj) == 0)
2529 					goto end_line_test;
2530 
2531 				m = (y1 - y0) / (x1 - x0);
2532 				b = (y1 - y) - m * (x1 - x);
2533 
2534 				if ((b / m) < EPSILON)
2535 				{
2536 					crossings++;
2537 				}
2538 
2539 			end_line_test:
2540 				x0 = x1;
2541 				y0 = y1;
2542 			}
2543 			else
2544 			{
2545 				if (j == n1)
2546 				{
2547 					x2 = xv[0];
2548 					y2 = yv[0];
2549 				}
2550 				else
2551 				{
2552 					x2 = xv[j + 1];
2553 					y2 = yv[j + 1];
2554 
2555 					if (!(fv[j + 1] & ONCURVE))
2556 					{
2557 						/*
2558 						 * Parabola with far end floating - readjust the far end so that it
2559 						 * is on the curve.
2560 						 */
2561 
2562 						x2 = 0.5 * (x1 + x2);
2563 						y2 = 0.5 * (y1 + y2);
2564 					}
2565 				}
2566 
2567 				/* only test crossing when y is in the range */
2568 				/* this should also help saving some computations */
2569 				if (((y0 < y) && (y1 < y) && (y2 < y)) ||
2570 				    ((y0 > y) && (y1 > y) && (y2 > y)))
2571 					goto end_curve_test;
2572 
2573 				yt[0] = y0 - 2.0 * y1 + y2;
2574 				yt[1] = 2.0 * (y1 - y0);
2575 				yt[2] = y0 - y;
2576 
2577 				k = solve_quad(yt, roots, 0.0, 1.0);
2578 
2579 				for (ri = 0; ri < k;) {
2580 					if (roots[ri] <= EPSILON) {
2581 						/* if y actually is not in range, discard the root */
2582 						if (((y <= y0) && (y < y1)) || ((y >= y0) && (y > y1))) {
2583 							k--;
2584 							if (k > ri)
2585 								roots[ri] = roots[ri+1];
2586 							continue;
2587 						}
2588 					}
2589 					else if (roots[ri] >= (1.0 - EPSILON)) {
2590 						/* if y actually is not in range, discard the root */
2591 						if (((y < y2) && (y < y1)) || ((y > y2) && (y > y1))) {
2592 							k--;
2593 							if (k > ri)
2594 								roots[ri] = roots[ri+1];
2595 							continue;
2596 						}
2597 					}
2598 
2599 					ri++;
2600 				}
2601 
2602 				if (k > 0)
2603 				{
2604 					xt[0] = x0 - 2.0 * x1 + x2;
2605 					xt[1] = 2.0 * (x1 - x0);
2606 					xt[2] = x0;
2607 
2608 					t = roots[0];
2609 
2610 					xc = (xt[0] * t + xt[1]) * t + xt[2];
2611 
2612 					if (xc > x)
2613 						crossings++;
2614 
2615 					if (k > 1)
2616 					{
2617 						t = roots[1];
2618 						xc = (xt[0] * t + xt[1]) * t + xt[2];
2619 
2620 						if (xc > x)
2621 							crossings++;
2622 					}
2623 				}
2624 
2625 end_curve_test:
2626 
2627 				x0 = x2;
2628 
2629 				y0 = y2;
2630 			}
2631 		}
2632 	}
2633 
2634 	return ((crossings & 1) != 0);
2635 }
2636 
2637 
solve_quad(double * x,double * y,double mindist,DBL maxdist) const2638 int TrueType::solve_quad(double *x, double *y, double mindist, DBL maxdist) const
2639 {
2640 	double d, t, a, b, c, q;
2641 
2642 	a = x[0];
2643 	b = -x[1];
2644 	c = x[2];
2645 
2646 	if (fabs(a) < COEFF_LIMIT)
2647 	{
2648 		if (fabs(b) < COEFF_LIMIT)
2649 			return 0;
2650 
2651 		q = c / b;
2652 
2653 		if (q >= mindist && q <= maxdist)
2654 		{
2655 			y[0] = q;
2656 			return 1;
2657 		}
2658 		else
2659 			return 0;
2660 	}
2661 
2662 	d = b * b - 4.0 * a * c;
2663 
2664 	if (d < EPSILON)
2665 		return 0;
2666 
2667 	d = sqrt(d);
2668 	t = 2.0 * a;
2669 	q = (b + d) / t;
2670 
2671 	if (q >= mindist && q <= maxdist)
2672 	{
2673 		y[0] = q;
2674 		q = (b - d) / t;
2675 
2676 		if (q >= mindist && q <= maxdist)
2677 		{
2678 			y[1] = q;
2679 			return 2;
2680 		}
2681 
2682 		return 1;
2683 	}
2684 
2685 	q = (b - d) / t;
2686 
2687 	if (q >= mindist && q <= maxdist)
2688 	{
2689 		y[0] = q;
2690 		return 1;
2691 	}
2692 
2693 	return 0;
2694 }
2695 
2696 /*
2697  * Returns the distance to z = 0 in t0, and the distance to z = 1 in t1.
2698  * These distances are to the the bottom and top surfaces of the glyph.
2699  * The distances are set to -1 if there is no hit.
2700  */
GetZeroOneHits(const GlyphStruct * glyph,const VECTOR P,const VECTOR D,DBL glyph_depth,double * t0,double * t1) const2701 void TrueType::GetZeroOneHits(const GlyphStruct* glyph, const VECTOR P, const VECTOR D, DBL glyph_depth, double *t0, double *t1) const
2702 {
2703 	double x0, y0, t;
2704 
2705 	*t0 = -1.0;
2706 	*t1 = -1.0;
2707 
2708 	/* Are we parallel to the x-y plane? */
2709 
2710 	if (fabs(D[Z]) < EPSILON)
2711 		return;
2712 
2713 	/* Solve: P[Y] + t * D[Y] = 0 */
2714 
2715 	t = -P[Z] / D[Z];
2716 
2717 	x0 = P[X] + t * D[X];
2718 	y0 = P[Y] + t * D[Y];
2719 
2720 	if (Inside_Glyph(x0, y0, glyph))
2721 		*t0 = t;
2722 
2723 	/* Solve: P[Y] + t * D[Y] = glyph_depth */
2724 
2725 	t += (glyph_depth / D[Z]);
2726 
2727 	x0 = P[X] + t * D[X];
2728 	y0 = P[Y] + t * D[Y];
2729 
2730 	if (Inside_Glyph(x0, y0, glyph))
2731 		*t1 = t;
2732 }
2733 
2734 /*
2735  * Solving for a linear sweep of a non-linear curve can be performed by
2736  * projecting the ray onto the x-y plane, giving a parametric equation for the
2737  * ray as:
2738  *
2739  * x = x0 + x1 t, y = y0 + y1 t
2740  *
2741  * Eliminating t from the above gives the implicit equation:
2742  *
2743  * y1 x - x1 y - (x0 y1 - y0 x1) = 0.
2744  *
2745  * Substituting a parametric equation for x and y gives:
2746  *
2747  * y1 x(s) - x1 y(s) - (x0 y1 - y0 x1) = 0.
2748  *
2749  * which can be written as
2750  *
2751  * a x(s) + b y(s) + c = 0,
2752  *
2753  * where a = y1, b = -x1, c = (y0 x1 - x0 y1).
2754  *
2755  * For piecewise quadratics, the parametric equations will have the forms:
2756  *
2757  * x(s) = (1-s)^2 P0(x) + 2 s (1 - s) P1(x) + s^2 P2(x) y(s) = (1-s)^2 P0(y) + 2 s
2758  * (1 - s) P1(y) + s^2 P2(y)
2759  *
2760  * where P0 is the first defining vertex of the spline, P1 is the second, P2 is
2761  * the third.  Using the substitutions:
2762  *
2763  * xt2 = x0 - 2 x1 + x2, xt1 = 2 * (x1 - x0), xt0 = x0; yt2 = y0 - 2 y1 + y2, yt1
2764  * = 2 * (y1 - y0), yt0 = y0;
2765  *
2766  * the equations can be written as:
2767  *
2768  * x(s) = xt2 s^2 + xt1 s + xt0, y(s) = yt2 s^2 + yt1 s + yt0.
2769  *
2770  * Substituting and multiplying out gives the following equation in s:
2771  *
2772  * s^2 * (a*xt2 + b*yt2) + s   * (a*xt1 + b*yt1) + c + a*xt0 + b*yt0
2773  *
2774  * This is then solved using the quadratic formula.  Any solutions of s that are
2775  * between 0 and 1 (inclusive) are valid solutions.
2776  */
GlyphIntersect(const VECTOR P,const VECTOR D,const GlyphStruct * glyph,DBL glyph_depth,const Ray & ray,IStack & Depth_Stack,TraceThreadData * Thread)2777 bool TrueType::GlyphIntersect(const VECTOR P, const VECTOR D, const GlyphStruct* glyph, DBL glyph_depth, const Ray& ray, IStack& Depth_Stack, TraceThreadData *Thread)
2778 {
2779 	Contour *contour;
2780 	int i, j, k, l, n, m;
2781 	bool Flag = false;
2782 	VECTOR N, IPoint;
2783 	DBL Depth;
2784 	double x0, x1, y0, y1, x2, y2, t, t0, t1, z;
2785 	double xt0, xt1, xt2, yt0, yt1, yt2;
2786 	double a, b, c, d0, d1, C[3], S[2];
2787 	DBL *xv, *yv;
2788 	BYTE *fv;
2789 	int dirflag = 0;
2790 
2791 	/*
2792 	 * First thing to do is to get any hits at z = 0 and z = 1 (which are the
2793 	 * bottom and top surfaces of the glyph.
2794 	 */
2795 
2796 	GetZeroOneHits(glyph, P, D, glyph_depth, &t0, &t1);
2797 
2798 	if (t0 > 0.0)
2799 	{
2800 		Depth = t0 /* / len */;
2801 		VScale(IPoint, ray.Direction, Depth);
2802 		VAddEq(IPoint, ray.Origin);
2803 
2804 		if (Depth > TTF_Tolerance && (Clip.empty() || Point_In_Clip(IPoint, Clip, Thread)))
2805 		{
2806 			Make_Vector(N, 0.0, 0.0, -1.0);
2807 			MTransNormal(N, N, Trans);
2808 			VNormalize(N, N);
2809 			Depth_Stack->push(Intersection(Depth, IPoint, N, this));
2810 			Flag = true;
2811 		}
2812 	}
2813 
2814 	if (t1 > 0.0)
2815 	{
2816 		Depth = t1 /* / len */;
2817 		VScale(IPoint, ray.Direction, Depth);
2818 		VAddEq(IPoint, ray.Origin);
2819 
2820 		if (Depth > TTF_Tolerance && (Clip.empty() || Point_In_Clip(IPoint, Clip, Thread)))
2821 		{
2822 			Make_Vector(N, 0.0, 0.0, 1.0);
2823 			MTransNormal(N, N, Trans);
2824 			VNormalize(N, N);
2825 			Depth_Stack->push(Intersection(Depth, IPoint, N, this));
2826 			Flag = true;
2827 		}
2828 	}
2829 
2830 	/* Simple test to see if we can just toss this ray */
2831 
2832 	if (fabs(D[X]) < EPSILON)
2833 	{
2834 		if (fabs(D[Y]) < EPSILON)
2835 		{
2836 			/*
2837 			 * This means the ray is moving parallel to the walls of the sweep
2838 			 * surface
2839 			 */
2840 			return Flag;
2841 		}
2842 		else
2843 		{
2844 			dirflag = 0;
2845 		}
2846 	}
2847 	else
2848 	{
2849 		dirflag = 1;
2850 	}
2851 
2852 	/*
2853 	 * Now walk through the glyph, looking for places where the ray hits the
2854 	 * walls
2855 	 */
2856 
2857 	a = D[Y];
2858 	b = -D[X];
2859 	c = (P[Y] * D[X] - P[X] * D[Y]);
2860 
2861 	n = glyph->header.numContours;
2862 
2863 	for (i = 0, contour = glyph->contours; i < n; i++, contour++)
2864 	{
2865 		xv = contour->x;
2866 		yv = contour->y;
2867 		fv = contour->flags;
2868 		x0 = xv[0];
2869 		y0 = yv[0];
2870 		m = contour->count;
2871 
2872 		for (j = 1; j <= m; j++)
2873 		{
2874 			x1 = xv[j];
2875 			y1 = yv[j];
2876 
2877 			if (fv[j] & ONCURVE)
2878 			{
2879 				/* Straight line */
2880 				d0 = (x1 - x0);
2881 				d1 = (y1 - y0);
2882 
2883 				t0 = d1 * D[X] - d0 * D[Y];
2884 
2885 				if (fabs(t0) < EPSILON)
2886 					/* No possible intersection */
2887 					goto end_line_test;
2888 
2889 				t = (D[X] * (P[Y] - y0) - D[Y] * (P[X] - x0)) / t0;
2890 
2891 				if (t < 0.0 || t > 1.0)
2892 					goto end_line_test;
2893 
2894 				if (dirflag)
2895 					t = ((x0 + t * d0) - P[X]) / D[X];
2896 				else
2897 					t = ((y0 + t * d1) - P[Y]) / D[Y];
2898 
2899 				z = P[Z] + t * D[Z];
2900 
2901 				Depth = t /* / len */;
2902 
2903 				if (z >= 0 && z <= glyph_depth && Depth > TTF_Tolerance)
2904 				{
2905 					VScale(IPoint, ray.Direction, Depth);
2906 					VAddEq(IPoint, ray.Origin);
2907 
2908 					if (Clip.empty() || Point_In_Clip(IPoint, Clip, Thread))
2909 					{
2910 						Make_Vector(N, d1, -d0, 0.0);
2911 						MTransNormal(N, N, Trans);
2912 						VNormalize(N, N);
2913 						Depth_Stack->push(Intersection(Depth, IPoint, N, this));
2914 						Flag = true;
2915 					}
2916 				}
2917 			end_line_test:
2918 				x0 = x1;
2919 				y0 = y1;
2920 			}
2921 			else
2922 			{
2923 				if (j == m)
2924 				{
2925 					x2 = xv[0];
2926 					y2 = yv[0];
2927 				}
2928 				else
2929 				{
2930 					x2 = xv[j + 1];
2931 					y2 = yv[j + 1];
2932 
2933 					if (!(fv[j + 1] & ONCURVE))
2934 					{
2935 
2936 						/*
2937 						 * Parabola with far end DBLing - readjust the far end so that it
2938 						 * is on the curve.  (In the correct place too.)
2939 						 */
2940 
2941 						x2 = 0.5 * (x1 + x2);
2942 						y2 = 0.5 * (y1 + y2);
2943 					}
2944 				}
2945 
2946 				/* Make the interpolating quadrics */
2947 
2948 				xt2 = x0 - 2.0 * x1 + x2;
2949 				xt1 = 2.0 * (x1 - x0);
2950 				xt0 = x0;
2951 				yt2 = y0 - 2.0 * y1 + y2;
2952 				yt1 = 2.0 * (y1 - y0);
2953 				yt0 = y0;
2954 
2955 				C[0] = a * xt2 + b * yt2;
2956 				C[1] = a * xt1 + b * yt1;
2957 				C[2] = a * xt0 + b * yt0 + c;
2958 
2959 				k = solve_quad(C, S, 0.0, 1.0);
2960 
2961 				for (l = 0; l < k; l++)
2962 				{
2963 					if (dirflag)
2964 						t = ((S[l] * S[l] * xt2 + S[l] * xt1 + xt0) - P[X]) / D[X];
2965 					else
2966 						t = ((S[l] * S[l] * yt2 + S[l] * yt1 + yt0) - P[Y]) / D[Y];
2967 
2968 					/*
2969 					 * If the intersection with this wall is between 0 and glyph_depth
2970 					 * along the z-axis, then it is a valid hit.
2971 					 */
2972 
2973 					z = P[Z] + t * D[Z];
2974 
2975 					Depth = t /* / len */;
2976 
2977 					if (z >= 0 && z <= glyph_depth && Depth > TTF_Tolerance)
2978 					{
2979 						VScale(IPoint, ray.Direction, Depth);
2980 						VAddEq(IPoint, ray.Origin);
2981 
2982 						if (Clip.empty() || Point_In_Clip(IPoint, Clip, Thread))
2983 						{
2984 							Make_Vector(N, 2.0 * yt2 * S[l] + yt1, -2.0 * xt2 * S[l] - xt1, 0.0);
2985 							MTransNormal(N, N, Trans);
2986 							VNormalize(N, N);
2987 							Depth_Stack->push(Intersection(Depth, IPoint, N, this));
2988 							Flag = true;
2989 						}
2990 					}
2991 				}
2992 
2993 				x0 = x2;
2994 				y0 = y2;
2995 			}
2996 		}
2997 	}
2998 
2999 	return Flag;
3000 }
3001 
All_Intersections(const Ray & ray,IStack & Depth_Stack,TraceThreadData * Thread)3002 bool TrueType::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadData *Thread)
3003 {
3004 	VECTOR P, D;
3005 
3006 	Thread->Stats()[Ray_TTF_Tests]++;
3007 
3008 	/* Transform the point into the glyph's space */
3009 
3010 	MInvTransPoint(P, ray.Origin, Trans);
3011 	MInvTransDirection(D, ray.Direction, Trans);
3012 
3013 	/* Tweak the ray to try to avoid pathalogical intersections */
3014 /* 	DBL len;
3015 
3016 	D[0] *= 1.0000013147;
3017 	D[1] *= 1.0000022741;
3018 	D[2] *= 1.0000017011;
3019 
3020 	VLength(len, D);
3021 	VInverseScaleEq(D, len);*/
3022 
3023 	if (GlyphIntersect(P, D, glyph, depth, ray, Depth_Stack, Thread)) /* tw */
3024 	{
3025 		Thread->Stats()[Ray_TTF_Tests_Succeeded]++;
3026 		return true;
3027 	}
3028 
3029 	return false;
3030 }
3031 
Inside(const VECTOR IPoint,TraceThreadData * Thread) const3032 bool TrueType::Inside(const VECTOR IPoint, TraceThreadData *Thread) const
3033 {
3034 	VECTOR New_Point;
3035 
3036 	/* Transform the point into font space */
3037 
3038 	MInvTransPoint(New_Point, IPoint, Trans);
3039 
3040 	if (New_Point[Z] >= 0.0 && New_Point[Z] <= depth &&
3041 	    Inside_Glyph(New_Point[X], New_Point[Y], glyph))
3042 		return (!Test_Flag(this, INVERTED_FLAG));
3043 	else
3044 		return (Test_Flag(this, INVERTED_FLAG));
3045 }
3046 
Normal(VECTOR Result,Intersection * Inter,TraceThreadData * Thread) const3047 void TrueType::Normal(VECTOR Result, Intersection *Inter, TraceThreadData *Thread) const
3048 {
3049 	/* Use precomputed normal. [ARE 11/94] */
3050 
3051 	Assign_Vector(Result, Inter->INormal);
3052 }
3053 
Copy()3054 ObjectPtr TrueType::Copy()
3055 {
3056 	TrueType *New = new TrueType();
3057 	Destroy_Transform(New->Trans);
3058 	*New = *this;
3059 	New->Trans = Copy_Transform(Trans);
3060 	New->glyph = glyph; // TODO - How can this work correctly? [trf]
3061 	return (New);
3062 }
3063 
Translate(const VECTOR,const TRANSFORM * tr)3064 void TrueType::Translate(const VECTOR /*Vector*/, const TRANSFORM *tr)
3065 {
3066 	Transform(tr);
3067 }
3068 
Rotate(const VECTOR,const TRANSFORM * tr)3069 void TrueType::Rotate(const VECTOR /*Vector*/, const TRANSFORM *tr)
3070 {
3071 	Transform(tr);
3072 }
3073 
Scale(const VECTOR,const TRANSFORM * tr)3074 void TrueType::Scale(const VECTOR /*Vector*/, const TRANSFORM *tr)
3075 {
3076 	Transform(tr);
3077 }
3078 
Invert()3079 void TrueType::Invert()
3080 {
3081 	Invert_Flag(this, INVERTED_FLAG);
3082 }
3083 
Transform(const TRANSFORM * tr)3084 void TrueType::Transform(const TRANSFORM *tr)
3085 {
3086 	Compose_Transforms(Trans, tr);
3087 
3088 	/* Calculate the bounds */
3089 
3090 	Compute_BBox();
3091 }
3092 
TrueType()3093 TrueType::TrueType() : ObjectBase(TTF_OBJECT)
3094 {
3095 	/* Initialize TTF specific information */
3096 
3097 	Trans = Create_Transform();
3098 
3099 	glyph = NULL;
3100 	depth = 1.0;
3101 
3102 	/* Default bounds */
3103 	Make_BBox(BBox, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0);
3104 }
3105 
~TrueType()3106 TrueType::~TrueType()
3107 {
3108 	Destroy_Transform(Trans);
3109 }
3110 
3111 
3112 
3113 /*****************************************************************************
3114 *
3115 * FUNCTION
3116 *
3117 *   Compute_TTF_BBox
3118 *
3119 * INPUT
3120 *
3121 *   ttf - ttf
3122 *
3123 * OUTPUT
3124 *
3125 *   ttf
3126 *
3127 * RETURNS
3128 *
3129 * AUTHOR
3130 *
3131 *   Dieter Bayer, August 1994
3132 *
3133 * DESCRIPTION
3134 *
3135 *   Calculate the bounding box of a true type font.
3136 *
3137 * CHANGES
3138 *
3139 *   -
3140 *
3141 ******************************************************************************/
Compute_BBox()3142 void TrueType::Compute_BBox()
3143 {
3144 	DBL funit_size, xMin, yMin, zMin, xMax, yMax, zMax;
3145 
3146 	funit_size = 1.0 / (DBL)(glyph->unitsPerEm);
3147 
3148 	xMin = (DBL)glyph->header.xMin * funit_size;
3149 	yMin = (DBL)glyph->header.yMin * funit_size;
3150 	zMin = -TTF_Tolerance;
3151 
3152 	xMax = (DBL)glyph->header.xMax * funit_size;
3153 	yMax = (DBL)glyph->header.yMax * funit_size;
3154 	zMax = depth + TTF_Tolerance;
3155 
3156 	Make_BBox(BBox, xMin, yMin, zMin, xMax - xMin, yMax - yMin, zMax - zMin);
3157 
3158 #ifdef TTF_DEBUG
3159 	Debug_Info("Bounds: <%g,%g,%g> -> <%g,%g,%g>\n",
3160 	           ttf->BBox.Lower_Left[0],
3161 	           ttf->BBox.Lower_Left[1],
3162 	           ttf->BBox.Lower_Left[2],
3163 	           ttf->BBox.Lengths[0],
3164 	           ttf->BBox.Lengths[1],
3165 	           ttf->BBox.Lengths[2]);
3166 #endif
3167 
3168 	/* Apply the transformation to the bounding box */
3169 
3170 	Recompute_BBox(&BBox, Trans);
3171 }
3172 
3173 }
3174 
3175