Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2347 lines
53 KiB

  1. /***
  2. **
  3. ** Module: Builder
  4. **
  5. ** Description:
  6. ** This is a module of the T1 to TT font converter. The module
  7. ** contains functions that will write the tables found in a
  8. ** TrueType font file.
  9. **
  10. ** Author: Michael Jansson
  11. **
  12. ** Created: 5/26/93
  13. **
  14. ***/
  15. /**** INCLUDES */
  16. /* General types and definitions. */
  17. #include <string.h> /* Prototype for memset */
  18. #include <limits.h>
  19. /* Special types and definitions. */
  20. #include "types.h"
  21. #include "metrics.h"
  22. #include "safemem.h"
  23. #include "encoding.h"
  24. #include "t1msg.h"
  25. /* Module dependent types and prototypes. */
  26. #include "titott.h"
  27. #include "builder.h"
  28. #include "fwriter.h"
  29. #if DBG
  30. #define STATIC
  31. #else
  32. #define STATIC static
  33. #endif
  34. /***** LOCAL TYPES */
  35. struct GlyphKerning {
  36. USHORT left;
  37. USHORT right;
  38. funit delta;
  39. };
  40. struct GlyphList {
  41. long offset; /* File offset of the sub-table for this glyph. */
  42. const struct encoding *code; /* Encoding key (see the "Encoding" module. */
  43. funit aw; /* Advance width. */
  44. funit lsb; /* Left side bearing. */
  45. USHORT pts; /* Total number of points in the glyph. */
  46. Point bbox[2]; /* Bounding box of the glyph. */
  47. USHORT conts; /* Number of contours. */
  48. };
  49. /* MS cmap encoding sub-table. */
  50. struct MSEncoding {
  51. USHORT segCount;
  52. USHORT *startCount;
  53. USHORT *endCount;
  54. USHORT *idOffsets;
  55. USHORT *gi;
  56. USHORT giCount;
  57. USHORT giMax;
  58. };
  59. struct TTHandle {
  60. OutputFile *file;
  61. Point bbox[2];
  62. struct GlyphList *pool;
  63. /* Accumulative 'maxp' entries. */
  64. USHORT count;
  65. USHORT maxcnt;
  66. USHORT maxpts;
  67. USHORT maxcontours;
  68. USHORT maxcomppts;
  69. USHORT maxcompcont;
  70. USHORT maxcompelements;
  71. USHORT maxstack;
  72. USHORT maxinstructions;
  73. USHORT maxtwilight;
  74. };
  75. /***** CONSTANTS */
  76. #define SHORT_LOCA_MAX 65535
  77. #define KERN_HORIZONTAL 0x0001
  78. #define KERN_PAIR 0x0000
  79. #define KERN_FORMAT0 0x0000
  80. #define GASP_GRIDFIT 0x0001
  81. #define GASP_DOGRAY 0x0002
  82. #define PLT_MAC (USHORT)1
  83. #define PLT_MS (USHORT)3
  84. #define ENC_ROMAN (USHORT)0
  85. // for platform id = 3 cmap table, symbol font or ugl
  86. #define ENC_SYMBOL (USHORT)0
  87. #define ENC_UGL (USHORT)1
  88. #define LAN_MS_US (USHORT)0x0409
  89. #define LAN_MAC_US (USHORT)0
  90. #define COPYRIGHT (USHORT)0
  91. #define FAMILY (USHORT)1
  92. #define SUBFAMILY (USHORT)2
  93. #define ID (USHORT)3
  94. #define FULLNAME (USHORT)4
  95. #define VERSION (USHORT)5
  96. #define PSNAME (USHORT)6
  97. #define NOTICE (USHORT)7
  98. /* Glyph constants. */
  99. #define FLG_ONCURVE 0x01
  100. #define FLG_SHORTX 0x02
  101. #define FLG_SHORTY 0x04
  102. #define FLG_REPEAT 0x08
  103. #define FLG_SAMEX 0x10
  104. #define FLG_SAMEY 0x20
  105. #define ARGS_1_2_ARE_WORDS 0x0001
  106. #define ARGS_ARE_XY_VALUES 0x0002
  107. #define ROUND_XY_TO_GRID 0x0004
  108. #define MORE_COMPONENTS 0x0020
  109. #define GLYPHBUF 64 /* GlyphList's that are allocated each time */
  110. #define MACSIZE (USHORT)256 /* Length of the Mac encoding vector. */
  111. /* Table constants. */
  112. #define FIRSTCHAR (USHORT)0x0020 /* First defined char. */
  113. #define LASTCHAR (USHORT)0xf002 /* Last defined char. */
  114. #define MAXZONES (USHORT)2 /* Number of zones in the font. */
  115. #define MAXIDEFS (USHORT)0 /* Number of idefs in the fpgm. */
  116. #define MAXDEPTH (USHORT)1 /* Number of recursions in composits. */
  117. #define FM_READONLY (USHORT)2 /* fsType Read Only. */
  118. #define NO_CLASS (USHORT)0 /* 0 = No class id for the font. */
  119. #define OS2VERSION (USHORT)0 /* Version of the OS/2 table. */
  120. #define CARET_RISE (USHORT)1 /* Vertical caret slope rise. */
  121. #define CARET_RUN (USHORT)0 /* Vertical caret slope run. */
  122. #define RESERVED0 (USHORT)0
  123. #define MAGICCOOKIE 0x5F0F3CF5L /* Magic cookie. */
  124. #define BASELINEY (USHORT)0x0001 /* Baseline at y==0 */
  125. #define LOWPPEM (USHORT)8 /* Lowest PPEM size. */
  126. #define ROMAN (USHORT)2 /* Direction = left,right&neutrals.*/
  127. #define GLYPH_FORMAT (USHORT)0 /* Current glyphs format. */
  128. #define VERSION0 (USHORT)0 /* Version zero of a table. */
  129. #define NUM_CMAPS (USHORT)2 /* Number of cmap sub-tables. */
  130. #define SEGMENT_MAP (USHORT)4 /* MS segment mapping of cmap table. */
  131. #define PAD0 (USHORT)0 /* Padding byte. */
  132. #define MAX_PPEM_SIZE (USHORT)65535 /* Maximum PPEM size in GASP table. */
  133. /* LOCA constants */
  134. #define SHORTOFFSETS 0
  135. #define LONGOFFSETS 1
  136. /* Weighted average character width. */
  137. STATIC const long Weights[] = {
  138. 64,
  139. 14,
  140. 27,
  141. 35,
  142. 100,
  143. 20,
  144. 14,
  145. 42,
  146. 63,
  147. 3,
  148. 6,
  149. 35,
  150. 20,
  151. 56,
  152. 56,
  153. 17,
  154. 4,
  155. 49,
  156. 56,
  157. 71,
  158. 31,
  159. 10,
  160. 18,
  161. 3,
  162. 18,
  163. 2
  164. };
  165. /***** MACROS */
  166. #define LONGVERSION(v,r) ((((long)v)<<16L) | (long)r)
  167. /***** STATIC FUNCTIONS */
  168. /***
  169. ** Function: SearchRange
  170. **
  171. ** Description:
  172. ** Compute the search range key for the CMAP subtable
  173. ** for Windows.
  174. ***/
  175. STATIC USHORT SearchRange(const USHORT cnt)
  176. {
  177. USHORT i;
  178. i = 0;
  179. while ((1u<<i) <= cnt) {
  180. i++;
  181. }
  182. return (USHORT)(1<<i);
  183. }
  184. /***
  185. ** Function: EntrySelector
  186. **
  187. ** Description:
  188. ** Compute the entry selector key for the CMAP subtable
  189. ** for Windows.
  190. ***/
  191. STATIC USHORT EntrySelector(const USHORT cnt)
  192. {
  193. USHORT i;
  194. i = 0;
  195. while ((1u<<(i+1)) <= cnt) {
  196. i++;
  197. }
  198. return i;
  199. }
  200. /***
  201. ** Function: RangeShift
  202. **
  203. ** Description:
  204. ** Compute the range shift key for the CMAP subtable
  205. ** for Windows.
  206. ***/
  207. STATIC USHORT RangeShift(const USHORT cnt)
  208. {
  209. return (USHORT)(2*cnt - SearchRange(cnt));
  210. }
  211. /***
  212. ** Function: PutGASP
  213. **
  214. ** Description:
  215. ** This function writes the optional 'GASP' table to the
  216. ** TT font file.
  217. **
  218. ***/
  219. STATIC errcode PutGASP(OutputFile *file,
  220. const USHORT treshold)
  221. {
  222. long offset;
  223. offset = FileTell(file);
  224. WriteShort(VERSION0, file);
  225. WriteShort(3, file);
  226. /* First range 0 - 8 : GRIDFIT */
  227. WriteShort(8, file);
  228. WriteShort(GASP_DOGRAY, file);
  229. /* Second range 8 - onpix : GRIDFIT */
  230. WriteShort(treshold, file);
  231. WriteShort(GASP_GRIDFIT, file);
  232. /* Third range onpix - inf. : GRIDFIT | GRAYSCALE */
  233. WriteShort(MAX_PPEM_SIZE, file);
  234. WriteShort(GASP_GRIDFIT | GASP_DOGRAY, file);
  235. return CompleteTable(offset, TBL_GASP, file);
  236. }
  237. /***
  238. ** Function: cmpKern
  239. **
  240. ** Description:
  241. **
  242. ***/
  243. STATIC int CDECL cmpKern(const void *a1, const void *a2)
  244. {
  245. const struct GlyphKerning *k1 = a1;
  246. const struct GlyphKerning *k2 = a2;
  247. ULONG first;
  248. ULONG second;
  249. first = ((k1->left)<<16L) + k1->right;
  250. second = ((k2->left)<<16L) + k2->right;
  251. return (int)(first - second);
  252. }
  253. /***
  254. ** Function: StdEncToGlyphIndex
  255. **
  256. ** Description:
  257. ** This function maps an StdEncoding character code to a
  258. ** glyph index.
  259. **
  260. ***/
  261. USHORT StdEncToGlyphIndex(const struct GlyphList *pool,
  262. const USHORT count,
  263. const USHORT code)
  264. {
  265. USHORT i;
  266. for (i=0; i<count; i++) {
  267. if (LookupCharCode(pool[i].code, ENC_MSWINDOWS) == code)
  268. return i;
  269. }
  270. return 0;
  271. }
  272. /***
  273. ** Function: PutKERN
  274. **
  275. ** Description:
  276. ** This function writes the optional 'KERN' table to the
  277. ** TT font file.
  278. **
  279. ***/
  280. STATIC errcode PutKERN(OutputFile *file,
  281. struct kerning *charkerns,
  282. const USHORT kernsize,
  283. const struct GlyphList *pool,
  284. const USHORT count)
  285. {
  286. struct GlyphKerning *kerns;
  287. long offset;
  288. unsigned i;
  289. USHORT cnt;
  290. if ((kerns = malloc(sizeof(struct GlyphKerning)*kernsize))==NULL)
  291. return FAILURE;
  292. /* Translate the kerning from char codes to glyph index. */
  293. for (i=0, cnt=0; i<kernsize; i++) {
  294. if ((kerns[cnt].left = StdEncToGlyphIndex(pool, count, charkerns[i].left))!=0 &&
  295. (kerns[cnt].right = StdEncToGlyphIndex(pool, count, charkerns[i].right))!=0)
  296. {
  297. kerns[cnt].delta = charkerns[i].delta;
  298. cnt++;
  299. }
  300. }
  301. /* Sort the kerning pairs. */
  302. qsort((void *)kerns, cnt, sizeof(struct GlyphKerning), cmpKern);
  303. offset = FileTell(file);
  304. WriteShort(VERSION0, file);
  305. WriteShort(1, file);
  306. /* First sub-table header. */
  307. WriteShort(VERSION0, file);
  308. WriteShort((USHORT)(2+2+2+ 2+2+2+2+ cnt*(2+2+2)), file);
  309. WriteShort(KERN_HORIZONTAL | KERN_PAIR | KERN_FORMAT0, file);
  310. /* First sub-table, format 0 */
  311. WriteShort(cnt, file);
  312. WriteShort(SearchRange(cnt), file);
  313. WriteShort(EntrySelector(cnt), file);
  314. WriteShort(RangeShift(cnt), file);
  315. for (i=0; i<cnt; i++) {
  316. WriteShort((USHORT)kerns[i].left, file);
  317. WriteShort((USHORT)kerns[i].right, file);
  318. WriteShort((USHORT)kerns[i].delta, file);
  319. }
  320. free(kerns);
  321. return CompleteTable(offset, TBL_KERN, file);
  322. }
  323. /***
  324. ** Function: PutCVT
  325. **
  326. ** Description:
  327. ** This function writes the optional 'cvt' table to the
  328. ** TT font file.
  329. **
  330. ***/
  331. STATIC errcode PutCVT(OutputFile *file,
  332. const short *ppgm,
  333. const USHORT num)
  334. {
  335. USHORT i;
  336. long offset;
  337. offset = FileTell(file);
  338. for (i=0; i<num; i++)
  339. WriteShort((USHORT)ppgm[i], file);
  340. return CompleteTable(offset, TBL_CVT, file);
  341. }
  342. /***
  343. ** Function: PutPREP
  344. **
  345. ** Description:
  346. ** This function writes the optional 'prep' table to the
  347. ** TT font file.
  348. **
  349. ***/
  350. STATIC errcode PutPREP(OutputFile *file,
  351. const UBYTE *prep,
  352. const USHORT num)
  353. {
  354. long offset;
  355. offset = FileTell(file);
  356. (void)WriteBytes(prep, num, file);
  357. return CompleteTable(offset, TBL_PREP, file);
  358. }
  359. /***
  360. ** Function: PutFPGM
  361. **
  362. ** Description:
  363. ** This function writes the optional 'fpgm' table to the
  364. ** TT font file.
  365. **
  366. ***/
  367. STATIC errcode PutFPGM(OutputFile *file,
  368. const UBYTE *fpgm,
  369. const USHORT num)
  370. {
  371. long offset;
  372. offset = FileTell(file);
  373. (void)WriteBytes(fpgm, num, file);
  374. return CompleteTable(offset, TBL_FPGM, file);
  375. }
  376. /***
  377. ** Function: PutPOST
  378. **
  379. ** Description:
  380. ** This function writes the required 'post' table to the
  381. ** TT font file.
  382. **
  383. ***/
  384. STATIC errcode PutPOST(OutputFile *file,
  385. struct GlyphList *pool,
  386. USHORT count,
  387. struct TTMetrics *ttm)
  388. {
  389. const char *str;
  390. long offset;
  391. USHORT i;
  392. offset = FileTell(file);
  393. WriteLong(LONGVERSION(2, 0), file);
  394. WriteLong((ULONG)ttm->angle, file);
  395. WriteShort((USHORT)ttm->underline, file);
  396. WriteShort((USHORT)ttm->uthick, file);
  397. WriteLong((ULONG)ttm->isFixPitched, file);
  398. WriteLong(0L, file);
  399. WriteLong(0L, file);
  400. WriteLong(0L, file);
  401. WriteLong(0L, file);
  402. /* Write the character codes. */
  403. WriteShort(count, file);
  404. for (i=0; i<count; i++) {
  405. if (pool[i].code)
  406. WriteShort(LookupCharCode(pool[i].code, ENC_MACCODES), file);
  407. else
  408. WriteShort((USHORT)0, file);
  409. }
  410. /* Write the character names. */
  411. for (i=0; i<count; i++) {
  412. if (pool[i].code) {
  413. str = LookupCharName(pool[i].code);
  414. WriteByte((UBYTE)strlen(str), file);
  415. (void)WriteBytes((UBYTE*)str, (USHORT)strlen(str), file);
  416. }
  417. }
  418. return CompleteTable(offset, TBL_POST, file);
  419. }
  420. /***
  421. ** Function: PutMAXP
  422. **
  423. ** Description:
  424. ** This function writes the required 'maxp' table to the
  425. ** TT font file.
  426. **
  427. ***/
  428. STATIC errcode PutMAXP(struct TTHandle *tt,
  429. const USHORT maxstorage,
  430. const USHORT maxprepstack,
  431. const USHORT maxfuns)
  432. {
  433. long offset;
  434. offset = FileTell(tt->file);
  435. WriteLong(LONGVERSION(1, 0), tt->file);
  436. WriteShort(tt->count, tt->file);
  437. WriteShort(tt->maxpts, tt->file);
  438. WriteShort(tt->maxcontours, tt->file);
  439. WriteShort(tt->maxcomppts, tt->file);
  440. WriteShort(tt->maxcompcont, tt->file);
  441. WriteShort(MAXZONES, tt->file);
  442. WriteShort(tt->maxtwilight, tt->file);
  443. WriteShort(maxstorage, tt->file);
  444. WriteShort(maxfuns, tt->file);
  445. WriteShort(MAXIDEFS, tt->file);
  446. WriteShort((USHORT)MAX(tt->maxstack, maxprepstack), tt->file);
  447. WriteShort(tt->maxinstructions, tt->file);
  448. WriteShort(tt->maxcompelements, tt->file);
  449. WriteShort(MAXDEPTH, tt->file);
  450. return CompleteTable(offset, TBL_MAXP, tt->file);
  451. }
  452. /***
  453. ** Function: PutOS2
  454. **
  455. ** Description:
  456. ** This function writes the required 'OS/2' table to the
  457. ** TT font file.
  458. **
  459. ***/
  460. STATIC errcode PutOS2(OutputFile *file,
  461. const struct GlyphList *pool,
  462. const USHORT count,
  463. const struct TTMetrics *ttm)
  464. {
  465. long offset;
  466. long aw;
  467. USHORT i;
  468. offset = FileTell(file);
  469. /* Compute some font metrics. */
  470. aw = 0;
  471. /* Do a weighted average? */
  472. if (ttm->Encoding==NULL) {
  473. for (i=0; i<count; i++) {
  474. short letter = (short)LookupCharCode(pool[i].code, ENC_MACCODES);
  475. if (letter==' ') {
  476. aw = aw + 166L * pool[i].aw;
  477. } else if ((letter>='a' && letter <= 'z')) {
  478. aw = aw + pool[i].aw * Weights[letter - 'a'];
  479. }
  480. }
  481. aw /= 1000;
  482. } else {
  483. for (i=0; i<count; i++) {
  484. aw += pool[i].aw;
  485. }
  486. aw = aw / count;
  487. }
  488. WriteShort(OS2VERSION, file);
  489. WriteShort((USHORT)aw, file);
  490. WriteShort(ttm->usWeightClass, file);
  491. WriteShort(ttm->usWidthClass, file);
  492. WriteShort(FM_READONLY, file);
  493. WriteShort((USHORT)ttm->subsize.x, file);
  494. WriteShort((USHORT)ttm->subsize.y, file);
  495. WriteShort((USHORT)ttm->suboff.x, file);
  496. WriteShort((USHORT)ttm->suboff.y, file);
  497. WriteShort((USHORT)ttm->supersize.x, file);
  498. WriteShort((USHORT)ttm->supersize.y, file);
  499. WriteShort((USHORT)ttm->superoff.x, file);
  500. WriteShort((USHORT)ttm->superoff.y, file);
  501. WriteShort((USHORT)ttm->strikesize, file);
  502. WriteShort((USHORT)ttm->strikeoff, file);
  503. WriteShort(NO_CLASS, file);
  504. /* Panose */
  505. WriteBytes(ttm->panose, (USHORT)10, file);
  506. /* Char range. */
  507. WriteLong(0L, file);
  508. WriteLong(0L, file);
  509. WriteLong(0L, file);
  510. WriteLong(0L, file);
  511. /* Vend ID. */
  512. WriteLong(0L, file);
  513. WriteShort(ttm->fsSelection, file);
  514. WriteShort(FIRSTCHAR, file);
  515. WriteShort(LASTCHAR, file);
  516. WriteShort((USHORT)ttm->typAscender, file);
  517. WriteShort((USHORT)ttm->typDescender, file);
  518. WriteShort((USHORT)ttm->typLinegap, file);
  519. WriteShort((USHORT)ttm->winAscender, file);
  520. WriteShort((USHORT)ttm->winDescender, file);
  521. return CompleteTable(offset, TBL_OS2, file);
  522. }
  523. /***
  524. ** Function: PutLOCA
  525. **
  526. ** Description:
  527. ** This function writes the required 'loca' table to the
  528. ** TT font file.
  529. **
  530. ***/
  531. STATIC errcode PutLOCA(OutputFile *file,
  532. const struct GlyphList *pool,
  533. const USHORT count,
  534. short *format)
  535. {
  536. long offset;
  537. USHORT i;
  538. offset = FileTell(file);
  539. /* Check for offset size format. */
  540. for (i=0, (*format) = SHORTOFFSETS; i<=count &&
  541. (*format)==SHORTOFFSETS; i++) {
  542. if (pool[i].offset/2>SHORT_LOCA_MAX)
  543. (*format) = LONGOFFSETS;
  544. }
  545. if ((*format)==LONGOFFSETS)
  546. for (i=0; i<=count; i++)
  547. WriteLong((ULONG)pool[i].offset, file);
  548. else
  549. for (i=0; i<=count; i++)
  550. WriteShort((USHORT)(pool[i].offset/2), file);
  551. return CompleteTable(offset, TBL_LOCA, file);
  552. }
  553. /***
  554. ** Function: PutHMTX
  555. **
  556. ** Description:
  557. ** This function writes the required 'hmtx' table to the
  558. ** TT font file.
  559. **
  560. ***/
  561. STATIC errcode PutHMTX(OutputFile *file,
  562. const struct GlyphList *pool,
  563. const USHORT count,
  564. const funit *widths,
  565. const USHORT first,
  566. const USHORT last,
  567. const struct encoding *enc)
  568. {
  569. long offset;
  570. USHORT std;
  571. USHORT i;
  572. USHORT usEnc = (USHORT) (enc? ENC_MACCODES : ENC_UNICODE);
  573. offset = FileTell(file);
  574. if (widths) {
  575. for (i=0; i<count; i++) {
  576. if (pool[i].code) {
  577. std = LookupCharCode(pool[i].code, usEnc);
  578. } else {
  579. std = NOTDEFGLYPH;
  580. }
  581. if (std>=first && std<=last)
  582. WriteShort((USHORT)widths[std-first], file);
  583. else
  584. WriteShort((USHORT)pool[i].aw, file);
  585. WriteShort((USHORT)pool[i].lsb, file);
  586. }
  587. } else {
  588. for (i=0; i<count; i++) {
  589. WriteShort((USHORT)pool[i].aw, file);
  590. WriteShort((USHORT)pool[i].lsb, file);
  591. }
  592. }
  593. return CompleteTable(offset, TBL_HMTX, file);
  594. }
  595. /***
  596. ** Function: PutHHEA
  597. **
  598. ** Description:
  599. ** This function writes the required 'HHEA' table to the
  600. ** TT font file.
  601. **
  602. ***/
  603. STATIC errcode PutHHEA(OutputFile *file,
  604. const struct GlyphList *pool,
  605. const USHORT count,
  606. const Point bbox[2],
  607. const funit linegap,
  608. const struct TTMetrics *ttm
  609. )
  610. {
  611. funit awmin, awmax, xmax, lsb;
  612. long offset;
  613. USHORT i;
  614. offset = FileTell(file);
  615. /* Compute some font metrics. */
  616. awmax = SHRT_MIN;
  617. awmin = SHRT_MAX;
  618. xmax = SHRT_MIN;
  619. lsb = SHRT_MAX;
  620. for (i=0; i<count; i++) {
  621. funit rsb = pool[i].aw - pool[i].lsb -
  622. (pool[i].bbox[1].x - pool[i].bbox[0].x);
  623. funit ext = pool[i].lsb +
  624. (pool[i].bbox[1].x - pool[i].bbox[0].x);
  625. if (ext>xmax)
  626. xmax = ext;
  627. if (rsb<awmin)
  628. awmin = rsb;
  629. if (pool[i].aw>awmax)
  630. awmax = pool[i].aw;
  631. if (pool[i].lsb<lsb)
  632. lsb = pool[i].lsb;
  633. }
  634. WriteLong(LONGVERSION(1, 0), file);
  635. WriteShort((USHORT)bbox[1].y, file);
  636. WriteShort((USHORT)bbox[0].y, file);
  637. WriteShort((USHORT)linegap, file);
  638. WriteShort((USHORT)awmax, file);
  639. WriteShort((USHORT)lsb, file);
  640. WriteShort((USHORT)awmin, file);
  641. WriteShort((USHORT)xmax, file);
  642. WriteShort(CARET_RISE, file);
  643. WriteShort(CARET_RUN, file);
  644. WriteShort((USHORT)(ttm->FirstChar << 8), file);
  645. WriteShort((USHORT)(ttm->LastChar << 8), file);
  646. WriteShort((USHORT)(ttm->DefaultChar << 8), file);
  647. WriteShort((USHORT)(ttm->BreakChar << 8), file);
  648. WriteShort((USHORT)(ttm->CharSet << 8), file);
  649. WriteShort(RESERVED0, file);
  650. WriteShort(count, file);
  651. return CompleteTable(offset, TBL_HHEA, file);
  652. }
  653. /***
  654. ** Function: PutHEAD
  655. **
  656. ** Description:
  657. ** This function writes the required 'head' table to the
  658. ** TT font file.
  659. **
  660. ***/
  661. STATIC errcode PutHEAD(OutputFile *file,
  662. const Point bbox[2],
  663. const struct TTMetrics *ttm,
  664. const short loca,
  665. long *csum)
  666. {
  667. long offset;
  668. offset = FileTell(file);
  669. WriteLong(LONGVERSION(1, 0), file);
  670. WriteShort(ttm->version.ver, file);
  671. WriteShort(ttm->version.rev, file);
  672. (*csum) = (long)FileTell(file);
  673. WriteLong(0L, file);
  674. WriteLong(MAGICCOOKIE, file);
  675. WriteShort(BASELINEY, file);
  676. WriteShort((USHORT)ttm->emheight, file);
  677. WriteLong(ttm->created.a, file);WriteLong(ttm->created.b, file);
  678. WriteLong(ttm->created.a, file);WriteLong(ttm->created.b, file);
  679. WriteShort((USHORT)bbox[0].x, file);
  680. WriteShort((USHORT)bbox[0].y, file);
  681. WriteShort((USHORT)bbox[1].x, file);
  682. WriteShort((USHORT)bbox[1].y, file);
  683. WriteShort((USHORT)ttm->macStyle, file);
  684. WriteShort(LOWPPEM, file);
  685. WriteShort(ROMAN, file);
  686. WriteShort((USHORT)loca, file);
  687. WriteShort(GLYPH_FORMAT, file);
  688. return CompleteTable(offset, TBL_HEAD, file);
  689. }
  690. /***
  691. ** Function: WriteNameEntry
  692. **
  693. ** Description:
  694. ** This function writes an entry in the NAME table
  695. ** header for one string.
  696. **
  697. ***/
  698. STATIC USHORT WriteNameEntry(OutputFile *file,
  699. const USHORT platform,
  700. const USHORT encoding,
  701. const USHORT language,
  702. const USHORT nameid,
  703. const char *str,
  704. const USHORT off)
  705. {
  706. USHORT len;
  707. if (str) {
  708. len = (USHORT)strlen(str);
  709. switch (platform) {
  710. case PLT_MS:
  711. len *= 2;
  712. break;
  713. case PLT_MAC:
  714. len *= 1;
  715. break;
  716. default:
  717. LogError(MSG_WARNING, MSG_PLATFORM, NULL);
  718. len *= 1;
  719. break;
  720. }
  721. WriteShort(platform, file);
  722. WriteShort(encoding, file);
  723. WriteShort(language, file);
  724. WriteShort(nameid, file);
  725. WriteShort(len, file);
  726. WriteShort(off, file);
  727. } else {
  728. len = 0;
  729. }
  730. return len;
  731. }
  732. /***
  733. ** Function: WriteNameString
  734. **
  735. ** Description:
  736. ** This function write the textual data of a string
  737. ** to the NAME table, according to the platform and
  738. ** encoding schema.
  739. **
  740. ***/
  741. STATIC void WriteNameString(OutputFile *file,
  742. const USHORT platform,
  743. const char *str)
  744. {
  745. USHORT i;
  746. if (str) {
  747. switch (platform) {
  748. default:
  749. case PLT_MAC:
  750. (void)WriteBytes((UBYTE *)str, (USHORT)strlen(str), file);
  751. break;
  752. case PLT_MS:
  753. for (i=0; i<strlen(str); i++)
  754. WriteShort(LookupCharCode(DecodeChar(NULL,
  755. (short)0,
  756. ENC_STANDARD,
  757. (USHORT)(UBYTE)str[i]),
  758. ENC_UNICODE),
  759. file);
  760. break;
  761. }
  762. }
  763. }
  764. /***
  765. ** Function: PutNAME
  766. **
  767. ** Description:
  768. ** This function writes the required 'name' table to the
  769. ** TT font file.
  770. **
  771. ***/
  772. STATIC errcode PutNAME(OutputFile *file, const struct TTMetrics *ttm)
  773. {
  774. USHORT stroff = 0;
  775. USHORT count = 0;
  776. USHORT encId = ttm->Encoding ? ENC_SYMBOL : ENC_UGL;
  777. ULONG offset;
  778. char *id;
  779. char *pszStyle = NULL;
  780. if (ttm->usWeightClass < 500)
  781. {
  782. if (ttm->angle == 0)
  783. {
  784. pszStyle = "Regular";
  785. }
  786. else
  787. {
  788. pszStyle = "Italic";
  789. }
  790. }
  791. else
  792. {
  793. if (ttm->angle == 0)
  794. {
  795. pszStyle = "Bold";
  796. }
  797. else
  798. {
  799. pszStyle = "Bold Italic";
  800. }
  801. }
  802. /* Count the number of names. */
  803. if (ttm->copyright)
  804. count++;
  805. if (ttm->family)
  806. count++;
  807. if (pszStyle)
  808. count++;
  809. if (ttm->id) {
  810. count++;
  811. id = ttm->id;
  812. } else {
  813. id = ttm->name;
  814. count++;
  815. }
  816. if (ttm->fullname)
  817. count++;
  818. if (ttm->verstr)
  819. count++;
  820. if (ttm->name)
  821. count++;
  822. if (ttm->notice)
  823. count++;
  824. count *= 2;
  825. /* Write the name table. */
  826. offset = (ULONG)FileTell(file);
  827. WriteShort(VERSION0, file);
  828. WriteShort(count, file);
  829. WriteShort((USHORT)(6+count*12), file);
  830. /* Mac names */
  831. stroff = (USHORT)(stroff + WriteNameEntry(file, PLT_MAC, ENC_ROMAN,
  832. LAN_MAC_US, COPYRIGHT,
  833. ttm->copyright, stroff));
  834. stroff = (USHORT)(stroff + WriteNameEntry(file, PLT_MAC, ENC_ROMAN,
  835. LAN_MAC_US, FAMILY,
  836. ttm->family, stroff));
  837. stroff = (USHORT)(stroff + WriteNameEntry(file, PLT_MAC, ENC_ROMAN,
  838. LAN_MAC_US, SUBFAMILY,
  839. pszStyle, stroff));
  840. stroff = (USHORT)(stroff + WriteNameEntry(file, PLT_MAC, ENC_ROMAN,
  841. LAN_MAC_US, ID,
  842. id, stroff));
  843. stroff = (USHORT)(stroff + WriteNameEntry(file, PLT_MAC, ENC_ROMAN,
  844. LAN_MAC_US, FULLNAME,
  845. ttm->fullname, stroff));
  846. stroff = (USHORT)(stroff + WriteNameEntry(file, PLT_MAC, ENC_ROMAN,
  847. LAN_MAC_US, VERSION,
  848. ttm->verstr, stroff));
  849. stroff = (USHORT)(stroff + WriteNameEntry(file, PLT_MAC, ENC_ROMAN,
  850. LAN_MAC_US, PSNAME,
  851. ttm->name, stroff));
  852. stroff = (USHORT)(stroff + WriteNameEntry(file, PLT_MAC, ENC_ROMAN,
  853. LAN_MAC_US, NOTICE,
  854. ttm->notice, stroff));
  855. /* MS names */
  856. stroff = (USHORT)(stroff + WriteNameEntry(file, PLT_MS, encId,
  857. LAN_MS_US, COPYRIGHT,
  858. ttm->copyright, stroff));
  859. stroff = (USHORT)(stroff + WriteNameEntry(file, PLT_MS, encId,
  860. LAN_MS_US, FAMILY,
  861. ttm->family, stroff));
  862. stroff = (USHORT)(stroff + WriteNameEntry(file, PLT_MS, encId,
  863. LAN_MS_US, SUBFAMILY,
  864. pszStyle, stroff));
  865. stroff = (USHORT)(stroff + WriteNameEntry(file, PLT_MS, encId,
  866. LAN_MS_US, ID,
  867. id, stroff));
  868. stroff = (USHORT)(stroff + WriteNameEntry(file, PLT_MS, encId,
  869. LAN_MS_US, FULLNAME,
  870. ttm->fullname, stroff));
  871. stroff = (USHORT)(stroff + WriteNameEntry(file, PLT_MS, encId,
  872. LAN_MS_US, VERSION,
  873. ttm->verstr, stroff));
  874. stroff = (USHORT)(stroff + WriteNameEntry(file, PLT_MS, encId,
  875. LAN_MS_US, PSNAME,
  876. ttm->name, stroff));
  877. stroff = (USHORT)(stroff + WriteNameEntry(file, PLT_MS, encId,
  878. LAN_MS_US, NOTICE,
  879. ttm->notice, stroff));
  880. WriteNameString(file, PLT_MAC, ttm->copyright);
  881. WriteNameString(file, PLT_MAC, ttm->family);
  882. WriteNameString(file, PLT_MAC, pszStyle);
  883. WriteNameString(file, PLT_MAC, id);
  884. WriteNameString(file, PLT_MAC, ttm->fullname);
  885. WriteNameString(file, PLT_MAC, ttm->verstr);
  886. WriteNameString(file, PLT_MAC, ttm->name);
  887. WriteNameString(file, PLT_MAC, ttm->notice);
  888. WriteNameString(file, PLT_MS, ttm->copyright);
  889. WriteNameString(file, PLT_MS, ttm->family);
  890. WriteNameString(file, PLT_MS, pszStyle);
  891. WriteNameString(file, PLT_MS, id);
  892. WriteNameString(file, PLT_MS, ttm->fullname);
  893. WriteNameString(file, PLT_MS, ttm->verstr);
  894. WriteNameString(file, PLT_MS, ttm->name);
  895. WriteNameString(file, PLT_MS, ttm->notice);
  896. return CompleteTable((long)offset, TBL_NAME, file);
  897. }
  898. /***
  899. ** Function: BoundingBox
  900. **
  901. ** Description:
  902. ** Extend an already initialized rectangle (two points)
  903. ** so that it encolses a number of coordinates.
  904. ***/
  905. STATIC void BoundingBox(Point bbox[2],
  906. const Point *pts,
  907. const USHORT cnt)
  908. {
  909. USHORT i;
  910. for (i=0; i<cnt; i++) {
  911. if (bbox[0].x > pts[i].x)
  912. bbox[0].x = pts[i].x;
  913. if (bbox[1].x < pts[i].x)
  914. bbox[1].x = pts[i].x;
  915. if (bbox[0].y > pts[i].y)
  916. bbox[0].y = pts[i].y;
  917. if (bbox[1].y < pts[i].y)
  918. bbox[1].y = pts[i].y;
  919. }
  920. }
  921. /***
  922. ** Function: RecordGlyph
  923. **
  924. ** Description:
  925. ** Record information about glyph record of the glyf table.
  926. ***/
  927. STATIC errcode RecordGlyph(struct TTHandle *tt,
  928. const struct encoding *code,
  929. const Point *bbox,
  930. const funit aw,
  931. const USHORT pts,
  932. const USHORT conts)
  933. {
  934. errcode status;
  935. USHORT i;
  936. i = tt->count;
  937. /* Make sure that there is enough memory in the pool. */
  938. if (tt->count+1>=tt->maxcnt) {
  939. struct GlyphList *gl;
  940. if ((gl = Realloc(tt->pool,
  941. (size_t)(tt->maxcnt+GLYPHBUF)*
  942. sizeof(struct GlyphList)))==NULL) {
  943. SetError(status=NOMEM);
  944. return status;
  945. } else {
  946. tt->maxcnt += GLYPHBUF;
  947. tt->pool = gl;
  948. }
  949. }
  950. /* Record metrics. */
  951. tt->count++;
  952. tt->pool[i].pts = pts;
  953. tt->pool[i].conts = conts;
  954. tt->pool[i].lsb = bbox[0].x;
  955. tt->pool[i].aw = aw;
  956. tt->pool[i].bbox[0] = bbox[0];
  957. tt->pool[i].bbox[1] = bbox[1];
  958. tt->pool[i].code = code;
  959. tt->pool[i].offset = FileTell(tt->file) - 12L - (long)TBLDIRSIZE*NUMTBL;
  960. /* Update the global bounding box. */
  961. BoundingBox(tt->bbox, bbox, (short)2);
  962. /* Update maxp. */
  963. if (conts>tt->maxcontours)
  964. tt->maxcontours = conts;
  965. if (pts>tt->maxpts)
  966. tt->maxpts = pts;
  967. return SUCCESS;
  968. }
  969. /***
  970. ** Function: BuildMacCMAP
  971. **
  972. ** Description:
  973. ** Compute the CMAP subtable for the Mac.
  974. ***/
  975. STATIC void BuildMacCMAP(const struct GlyphList *pool,
  976. const USHORT count,
  977. UBYTE *ascii2gi,
  978. const struct encoding *encRoot,
  979. const int encSize)
  980. {
  981. const struct encoding *notdef = LookupNotDef();
  982. USHORT code;
  983. UBYTE i;
  984. /* Initiate the ascii to glyph-index array. Glyph 0 is the "notdef"
  985. character, so any unassigned character will be mapped to "notdef". */
  986. memset(ascii2gi, NOTDEFGLYPH, (unsigned int)MACSIZE);
  987. /* Build the ascii to glyph-index array. */
  988. if (encRoot==NULL)
  989. {
  990. for (i=2; i<MIN(255,count); i++)
  991. {
  992. if (pool[i].code!=NULL)
  993. {
  994. /* i = glyph index, Lookup..() = character code.
  995. Map glyph i only if it is a valid Mac character. */
  996. if (pool[i].code!=NULL &&
  997. (code = LookupCharCode(pool[i].code,ENC_MACCODES))!=NOTDEFCODE)
  998. ascii2gi[code] = i;
  999. }
  1000. }
  1001. }
  1002. else
  1003. {
  1004. for (i=2; i<MIN(255,count); i++)
  1005. {
  1006. if (pool[i].code!=NULL && pool[i].code!=notdef)
  1007. {
  1008. const struct encoding *encGlyph;
  1009. encGlyph = LookupFirstEnc(encRoot, encSize, pool[i].code);
  1010. do
  1011. {
  1012. if ((code = LookupCharCode(encGlyph, ENC_MACCODES))!=NOTDEFCODE)
  1013. ascii2gi[code] = i;
  1014. } while (encGlyph = LookupNextEnc(encRoot, encSize, encGlyph));
  1015. }
  1016. }
  1017. }
  1018. /* Constant Mac glyph/encoding mapping for standard encoded fonts */
  1019. if (encRoot==NULL)
  1020. {
  1021. /* Missing glyphs. */
  1022. for (i=1; i<=31; i++)
  1023. ascii2gi[i] = NOTDEFGLYPH;
  1024. ascii2gi[127] = NOTDEFGLYPH;
  1025. /* Null glyphs. */
  1026. ascii2gi[0] = 1;
  1027. ascii2gi[8] = 1;
  1028. ascii2gi[13] = 1;
  1029. ascii2gi[29] = 1;
  1030. /* No countours + positive advance width. */
  1031. ascii2gi[9] = ascii2gi[32];
  1032. ascii2gi[13] = ascii2gi[32];
  1033. ascii2gi[202] = ascii2gi[32];
  1034. }
  1035. }
  1036. /***
  1037. ** Function: FreeMSEncoding
  1038. **
  1039. ** Description:
  1040. ** Free resourses used while computing the CMAP subtable
  1041. ** for Windows.
  1042. ***/
  1043. STATIC void FreeMSEncoding(struct MSEncoding *ms)
  1044. {
  1045. if (ms->startCount)
  1046. Free(ms->startCount);
  1047. if (ms->gi)
  1048. Free(ms->gi);
  1049. }
  1050. /***
  1051. ** Function: BuildMSCMAP
  1052. **
  1053. ** Description:
  1054. ** Compute the CMAP subtable for Windows.
  1055. ***/
  1056. STATIC errcode BuildMSCMAP(const struct GlyphList *pool,
  1057. const USHORT count,
  1058. struct MSEncoding *ms,
  1059. const struct encoding *encRoot,
  1060. const int encSize
  1061. )
  1062. {
  1063. USHORT *twobyte = NULL;
  1064. USHORT idOffset;
  1065. USHORT code, max;
  1066. USHORT i, j, k, big, n;
  1067. /* Get the range of the UGL characters. */
  1068. max = 0;
  1069. big = 0;
  1070. if (encRoot==NULL)
  1071. {
  1072. for (i=2; i<count; i++)
  1073. {
  1074. if (pool[i].code!=NULL)
  1075. {
  1076. if ((code = LookupCharCode(pool[i].code, ENC_UNICODE))!=NOTDEFCODE)
  1077. {
  1078. if (code<=0xff)
  1079. {
  1080. if (code>max)
  1081. max = code;
  1082. }
  1083. else
  1084. {
  1085. big++;
  1086. }
  1087. }
  1088. }
  1089. }
  1090. }
  1091. else
  1092. /* A non-standard encoded font, i.e. a fonts with an explicit
  1093. encoding array may reference the same glyph more than once,
  1094. though each glyph only refers to one encoding item. We have to
  1095. enumerate through all code point for each glyph in this case.
  1096. */
  1097. {
  1098. for (i=2; i<count; i++)
  1099. {
  1100. if (pool[i].code!=NULL)
  1101. {
  1102. const struct encoding *encGlyph = LookupFirstEnc(encRoot,
  1103. encSize,pool[i].code);
  1104. do
  1105. {
  1106. if ((code = LookupCharCode(encGlyph, ENC_MACCODES))!=NOTDEFCODE)
  1107. {
  1108. if (code>max)
  1109. max = code;
  1110. }
  1111. } while (encGlyph = LookupNextEnc(encRoot, encSize, encGlyph));
  1112. }
  1113. }
  1114. }
  1115. max++;
  1116. max = (USHORT)(max + big);
  1117. if ((ms->gi = Malloc(sizeof(USHORT)*max))==NULL) {
  1118. return NOMEM;
  1119. }
  1120. memset(ms->gi, NOTDEFGLYPH, max*sizeof(USHORT));
  1121. if (big && (twobyte = Malloc(sizeof(USHORT)*big))==NULL) {
  1122. Free(ms->gi);
  1123. ms->gi = NULL;
  1124. return NOMEM;
  1125. }
  1126. j = 0;
  1127. if (encRoot==NULL)
  1128. {
  1129. /* Glyph zero and Glyp one are the "notdef" and the "null" glyph,
  1130. and are not encoded here, so skip the first two glyph.
  1131. */
  1132. for (i=2; i<count; i++)
  1133. {
  1134. code = LookupCharCode(pool[i].code, ENC_UNICODE);
  1135. if (pool[i].code && code!=NOTDEFCODE)
  1136. {
  1137. if (code<=0xff)
  1138. {
  1139. ms->gi[code] = i;
  1140. }
  1141. else
  1142. {
  1143. for (k=0; k<j; k++)
  1144. if (twobyte[k]>code)
  1145. break;
  1146. for (n=j; n>k; n--)
  1147. {
  1148. twobyte[n] = twobyte[n-1];
  1149. ms->gi[max-big+n] = ms->gi[max-big+n-1];
  1150. }
  1151. twobyte[k] = code;
  1152. ms->gi[max-big+k] = i;
  1153. j++;
  1154. }
  1155. }
  1156. }
  1157. }
  1158. else
  1159. {
  1160. for (i=2; i<count; i++)
  1161. {
  1162. const struct encoding *encGlyph;
  1163. if (pool[i].code)
  1164. {
  1165. encGlyph = LookupFirstEnc(encRoot, encSize, pool[i].code);
  1166. do
  1167. {
  1168. if ((code = LookupCharCode(encGlyph, ENC_MACCODES))!=NOTDEFCODE)
  1169. {
  1170. ms->gi[code] = i;
  1171. }
  1172. } while (encGlyph = LookupNextEnc(encRoot, encSize, encGlyph));
  1173. }
  1174. }
  1175. }
  1176. /* Count the segments. */
  1177. ms->segCount=(USHORT)(2+big);
  1178. for (i=0; i<max-big-1; i++) {
  1179. if (ms->gi[i]!=NOTDEFGLYPH && ms->gi[i+1]==NOTDEFGLYPH) {
  1180. ms->segCount++;
  1181. }
  1182. }
  1183. ms->startCount = Malloc(3 * (sizeof(USHORT)*ms->segCount));
  1184. if (ms->startCount==NULL) {
  1185. if (twobyte)
  1186. Free(twobyte);
  1187. FreeMSEncoding(ms);
  1188. return NOMEM;
  1189. }
  1190. ms->endCount = (USHORT *)((char *)ms->startCount + sizeof(USHORT)*ms->segCount);
  1191. ms->idOffsets = (USHORT *)((char *)ms->endCount + sizeof(USHORT)*ms->segCount);
  1192. /* i=UGL index, j=segment index, k=glyph index. */
  1193. for (i=0, j=0, k=0; i<max-big; i++) {
  1194. if (ms->gi[i]!=NOTDEFGLYPH) {
  1195. if (i==0 || (ms->gi[i-1]==NOTDEFGLYPH)) {
  1196. ms->startCount[j] = i;
  1197. ms->idOffsets[j] = (USHORT)((ms->segCount-j+k)*2);
  1198. }
  1199. if ((i==max-1-big) || (ms->gi[i+1]==NOTDEFGLYPH)) {
  1200. ms->endCount[j] = i;
  1201. j++;
  1202. }
  1203. k++;
  1204. }
  1205. }
  1206. /* Segment for the double byte characters. */
  1207. idOffset = (USHORT)((ms->segCount-j+k)*2);
  1208. for (i=0; i<big; i++) {
  1209. ms->startCount[j] = twobyte[i];
  1210. ms->idOffsets[j] = idOffset;
  1211. ms->endCount[j] = twobyte[i];
  1212. k++;
  1213. j++;
  1214. }
  1215. ms->giCount = k;
  1216. ms->giMax = max;
  1217. /* Sentinel segments. */
  1218. ms->startCount[ms->segCount-1] = 0xffff;
  1219. ms->endCount[ms->segCount-1] = 0xffff;
  1220. ms->idOffsets[ms->segCount-1] = 0;
  1221. if (twobyte)
  1222. Free(twobyte);
  1223. return SUCCESS;
  1224. }
  1225. /***
  1226. ** Function: PutCMAP
  1227. **
  1228. ** Description:
  1229. ** This function writes the required 'cmap' table to the
  1230. ** TT font file.
  1231. ***/
  1232. STATIC errcode PutCMAP(
  1233. struct TTHandle *tt,
  1234. UBYTE *ascii2gi,
  1235. const struct encoding *enc,
  1236. const int encSize)
  1237. {
  1238. struct MSEncoding ms;
  1239. long end, offset;
  1240. errcode status = SUCCESS;
  1241. USHORT i;
  1242. USHORT usBias = (USHORT)(enc ? 0xf000 : 0); // bias for the first glyph
  1243. /* Build Mac encoding table. */
  1244. BuildMacCMAP(tt->pool, tt->count, ascii2gi, enc, encSize);
  1245. /* Build MS encoding table. */
  1246. if ((status = BuildMSCMAP(tt->pool, tt->count, &ms, enc, encSize))!=SUCCESS)
  1247. return status;
  1248. offset = FileTell(tt->file);
  1249. /* Write cmap table. */
  1250. WriteShort(VERSION0, tt->file);
  1251. WriteShort(NUM_CMAPS, tt->file);
  1252. /*== CMAP table directory ==*/
  1253. WriteShort(PLT_MAC, tt->file);
  1254. WriteShort(ENC_ROMAN, tt->file);
  1255. WriteLong(0L, tt->file);
  1256. WriteShort(PLT_MS, tt->file);
  1257. WriteShort((USHORT)(enc ? ENC_SYMBOL : ENC_UGL), tt->file);
  1258. WriteLong(0L, tt->file);
  1259. /* Standard apple encoding. */
  1260. end = FileTell(tt->file);
  1261. (void)FileSeek(tt->file, offset+8);
  1262. WriteLong((ULONG)(end-offset), tt->file);
  1263. (void)FileSeek(tt->file, end);
  1264. WriteShort((USHORT)0, tt->file);
  1265. WriteShort((USHORT)(2+2+2+MACSIZE), tt->file);
  1266. WriteShort((USHORT)0, tt->file);
  1267. (void)WriteBytes(ascii2gi, MACSIZE, tt->file);
  1268. /* Long word align the subtable. */
  1269. end = FileTell(tt->file);
  1270. if ((end-offset)%4)
  1271. for (i=0; (short)i<(4-((end-offset)%4)); i++)
  1272. WriteByte(0, tt->file);
  1273. /* MS delta encoding. */
  1274. end = FileTell(tt->file);
  1275. (void)FileSeek(tt->file, offset+16);
  1276. WriteLong((ULONG)(end-offset), tt->file);
  1277. (void)FileSeek(tt->file, end);
  1278. /* format */
  1279. WriteShort(SEGMENT_MAP, tt->file);
  1280. /* length */
  1281. WriteShort((USHORT)(16+ms.segCount*(2+2+2+2)+ms.giCount*2), tt->file);
  1282. /* version */
  1283. WriteShort(VERSION0, tt->file);
  1284. /* 2*segCount */
  1285. WriteShort((USHORT)(ms.segCount*2), tt->file);
  1286. /* searchRange */
  1287. WriteShort(SearchRange(ms.segCount), tt->file);
  1288. /* entrySelector */
  1289. WriteShort(EntrySelector(ms.segCount), tt->file);
  1290. /* rangeShift */
  1291. WriteShort(RangeShift(ms.segCount), tt->file);
  1292. /* endCount */
  1293. for (i=0; i<ms.segCount; i++)
  1294. WriteShort((USHORT)(ms.endCount[i] | usBias), tt->file);
  1295. WriteShort(PAD0, tt->file);
  1296. /* startCount */
  1297. for (i=0; i<ms.segCount; i++)
  1298. WriteShort((USHORT)(ms.startCount[i] | usBias), tt->file);
  1299. /* idDelta */
  1300. for (i=0; i<ms.segCount; i++)
  1301. WriteShort(PAD0, tt->file);
  1302. /* rangeOffsets */
  1303. for (i=0; i<ms.segCount; i++)
  1304. WriteShort(ms.idOffsets[i], tt->file);
  1305. for (i=0; i<ms.giMax; i++)
  1306. if (ms.gi[i]!=NOTDEFGLYPH)
  1307. WriteShort(ms.gi[i], tt->file);
  1308. /* Free resources. */
  1309. FreeMSEncoding(&ms);
  1310. return CompleteTable(offset, TBL_CMAP, tt->file);
  1311. }
  1312. /***** FUNCTIONS */
  1313. /***
  1314. ** Function: TypographicalAscender
  1315. **
  1316. ** Description:
  1317. ** Compute the typographical ascender height, as ymax of
  1318. ** the letter 'b'.
  1319. ***/
  1320. funit TypographicalAscender(const struct TTHandle *tt)
  1321. {
  1322. USHORT i;
  1323. funit height = 0;
  1324. for (i=0; (i<tt->count) && height==0; i++) {
  1325. if (tt->pool[i].code &&
  1326. !strcmp(LookupCharName(tt->pool[i].code), "b"))
  1327. height = tt->pool[i].bbox[1].y;
  1328. }
  1329. return height;
  1330. }
  1331. /***
  1332. ** Function: TypographicalDescender
  1333. **
  1334. ** Description:
  1335. ** Compute the typographical descender height, as ymin of
  1336. ** the letter 'g'.
  1337. ***/
  1338. funit TypographicalDescender(const struct TTHandle *tt)
  1339. {
  1340. USHORT i;
  1341. funit height = 0;
  1342. for (i=0; i<tt->count && height==0; i++) {
  1343. if (tt->pool[i].code &&
  1344. !strcmp(LookupCharName(tt->pool[i].code), "g"))
  1345. height = tt->pool[i].bbox[0].y;
  1346. }
  1347. return height;
  1348. }
  1349. /***
  1350. ** Function: WindowsBBox
  1351. **
  1352. ** Description:
  1353. ** Compute the bounding box of the characters that are
  1354. ** used in Windows character set.
  1355. ***/
  1356. #ifdef NOT_NEEDED_ON_NT
  1357. void WindowsBBox(const struct TTHandle *tt, Point *bbox)
  1358. {
  1359. USHORT i;
  1360. funit height = 0;
  1361. bbox[0].x = bbox[0].y = SHRT_MAX;
  1362. bbox[1].x = bbox[1].y = SHRT_MIN;
  1363. for (i=0; i<tt->count && height==0; i++) {
  1364. if (tt->pool[i].code && LookupCharCode(tt->pool[i].code,
  1365. ENC_MSWINDOWS)) {
  1366. BoundingBox(bbox, tt->pool[i].bbox, (USHORT)2);
  1367. }
  1368. }
  1369. }
  1370. #endif
  1371. /***
  1372. ** Function: MacBBox
  1373. **
  1374. ** Description:
  1375. ** Compute the bounding box of the characters that are
  1376. ** used in Mac character set.
  1377. **
  1378. ** This is currently set to the global bounding box
  1379. ** (tt->bbox) of all characters in the font. This will
  1380. ** ensure that accents are not sqeezed on Mac platforms.
  1381. ***/
  1382. void MacBBox(const struct TTHandle *tt, Point *bbox)
  1383. {
  1384. bbox[0] = tt->bbox[0];
  1385. bbox[1] = tt->bbox[1];
  1386. }
  1387. void GlobalBBox(const struct TTHandle *tt, Point *bbox)
  1388. {
  1389. bbox[0] = tt->bbox[0];
  1390. bbox[1] = tt->bbox[1];
  1391. }
  1392. /***
  1393. ** Function: InitTTOutput
  1394. **
  1395. ** Description:
  1396. ** This function allocates the resources needed to
  1397. ** write a TT font file.
  1398. ***/
  1399. errcode InitTTOutput(const struct TTArg *arg, struct TTHandle **tt)
  1400. {
  1401. errcode status = SUCCESS;
  1402. /* Allocate resources. */
  1403. if (((*tt)=Malloc(sizeof(struct TTHandle)))==NULL) {
  1404. SetError(status = NOMEM);
  1405. } else {
  1406. /* Initiate. */
  1407. memset((*tt), '\0', sizeof(**tt));
  1408. /* Open the file. */
  1409. if (((*tt)->file=OpenOutputFile(arg->name))==NULL) {
  1410. SetError(status = BADOUTPUTFILE);
  1411. } else {
  1412. /* Allocate space for glyph records. */
  1413. if (((*tt)->pool
  1414. = Malloc(sizeof(struct GlyphList)*GLYPHBUF))==NULL) {
  1415. SetError(status = NOMEM);
  1416. } else {
  1417. /* Initiate. */
  1418. (*tt)->bbox[0].x = (*tt)->bbox[0].y = SHRT_MAX;
  1419. (*tt)->bbox[1].x = (*tt)->bbox[1].y = SHRT_MIN;
  1420. (*tt)->count = 0;
  1421. (*tt)->maxcnt = GLYPHBUF;
  1422. (*tt)->maxcontours = 0;
  1423. (*tt)->maxpts = 0;
  1424. (*tt)->maxcompelements = 0;
  1425. (*tt)->maxtwilight = 0;
  1426. /* Write header. */
  1427. WriteTableHeader((*tt)->file);
  1428. /* Check error condition. */
  1429. if (FileError((*tt)->file))
  1430. status = BADOUTPUTFILE;
  1431. }
  1432. }
  1433. }
  1434. return status;
  1435. }
  1436. /***
  1437. ** Function: FreeTTMetrics
  1438. **
  1439. ** Description:
  1440. ** This function free's the resources used to represent
  1441. ** TT specific metrics and auxiliary font information.
  1442. ***/
  1443. void FreeTTMetrics(struct TTMetrics *ttm)
  1444. {
  1445. if (ttm->verstr)
  1446. Free(ttm->verstr);
  1447. if (ttm->cvt)
  1448. Free(ttm->cvt);
  1449. if (ttm->widths)
  1450. Free(ttm->widths);
  1451. if (ttm->prep)
  1452. Free((UBYTE *)ttm->prep);
  1453. }
  1454. /***
  1455. ** Function: CleanUpTT
  1456. **
  1457. ** Description:
  1458. ** This function free's the resources used while
  1459. ** writing a TT font file.
  1460. ***/
  1461. errcode CleanUpTT(struct TTHandle *tt,
  1462. const struct TTArg *ttarg,
  1463. const errcode status)
  1464. {
  1465. errcode rc = SUCCESS;
  1466. if (tt) {
  1467. if (tt->file)
  1468. rc = CloseOutputFile(tt->file);
  1469. /* Nuke the output file? */
  1470. if (status!=SUCCESS || rc!=SUCCESS)
  1471. RemoveFile(ttarg->name);
  1472. if (tt->pool)
  1473. Free(tt->pool);
  1474. Free(tt);
  1475. }
  1476. return rc;
  1477. }
  1478. /***
  1479. ** Function: FreeTTGlyph
  1480. **
  1481. ** Description:
  1482. ** This function will free the memory used to represent a
  1483. ** a TrueType glyph.
  1484. **
  1485. ***/
  1486. void FreeTTGlyph(struct TTGlyph *glyph)
  1487. {
  1488. Outline *path = NULL;
  1489. /* Free the memory. */
  1490. if (glyph) {
  1491. while (glyph->paths) {
  1492. path = glyph->paths->next;
  1493. Free(glyph->paths->pts);
  1494. Free(glyph->paths->onoff);
  1495. Free(glyph->paths);
  1496. glyph->paths = path;
  1497. }
  1498. if (glyph->hints)
  1499. Free(glyph->hints);
  1500. Free(glyph);
  1501. }
  1502. }
  1503. /***
  1504. ** Function: PutTTNotDefGlyph
  1505. **
  1506. ** Description:
  1507. ** This function adds a record for a the ".notdef" glyph to the
  1508. ** 'glyf' table of the TT font file.
  1509. **
  1510. ***/
  1511. errcode PutTTNotDefGlyph(struct TTHandle *tt, const struct TTGlyph *glyph)
  1512. {
  1513. struct TTGlyph ttg;
  1514. long end = FileTell(tt->file);
  1515. errcode status = SUCCESS;
  1516. USHORT oldcount = tt->count;
  1517. Outline *path;
  1518. int conts = 0;
  1519. int size = 0;
  1520. int cnt = 0;
  1521. /* Determine if there is enough room. */
  1522. for (path=glyph->paths; path; path=path->next) {
  1523. cnt += path->count;
  1524. conts += 1;
  1525. }
  1526. size = cnt * sizeof(Point) + /* coordinates */
  1527. conts * sizeof(short) + /* end points */
  1528. glyph->num + /* instructions */
  1529. cnt * sizeof(char) * 2; /* flag bytes */
  1530. ttg = *glyph;
  1531. if (size > MAXNOTDEFSIZE) {
  1532. ttg.num = 0;
  1533. ttg.stack = 0;
  1534. ttg.twilights = 0;
  1535. ttg.hints = NULL;
  1536. if (size - glyph->num > MAXNOTDEFSIZE) {
  1537. ttg.paths = NULL;
  1538. }
  1539. }
  1540. /* Move back to glyph #0, i.e. the missing glyph. */
  1541. tt->count = 0;
  1542. (void)FileSeek(tt->file,
  1543. tt->pool[NOTDEFGLYPH].offset+12L+(long)TBLDIRSIZE*NUMTBL);
  1544. status = PutTTGlyph(tt, &ttg, FALSE);
  1545. tt->count = oldcount;
  1546. (void)FileSeek(tt->file, end);
  1547. /* Missing outline? */
  1548. if (ttg.paths==NULL)
  1549. tt->pool[NOTDEFGLYPH].offset = tt->pool[NULLGLYPH].offset;
  1550. return status;
  1551. }
  1552. /***
  1553. ** Function: PutTTGlyph
  1554. **
  1555. ** Description:
  1556. ** This function adds a record for a simple glyph to the
  1557. ** 'glyf' table of the TT font file.
  1558. **
  1559. ***/
  1560. errcode PutTTGlyph(struct TTHandle *tt, const struct TTGlyph *glyph,
  1561. const boolean fStdEncoding)
  1562. {
  1563. errcode status = SUCCESS;
  1564. UBYTE flag, prev, cnt;
  1565. USHORT i, c, n = 0;
  1566. Outline *path;
  1567. Point bbox[2];
  1568. funit x, y;
  1569. if (glyph!=NULL) {
  1570. #ifdef DOT
  1571. /* Replace the '.' character. */
  1572. if (LookupCharCode(glyph->code, ENC_STANDARD)==0x2e) {
  1573. STATIC struct TTGlyph marker;
  1574. STATIC Outline box;
  1575. STATIC ULONG onoff[1];
  1576. STATIC Point pts[4];
  1577. STATIC UBYTE xleading[] = {
  1578. 0x00,
  1579. 0xb9, 0, 3, 0, 0,
  1580. 0x38, /* SHPIX[], 4, 640 */
  1581. };
  1582. marker = *glyph;
  1583. glyph = &marker;
  1584. marker.paths = &box;
  1585. marker.num = sizeof(xleading);
  1586. marker.hints = xleading;
  1587. box.next = NULL;
  1588. box.count = 4;
  1589. box.onoff = &onoff[0];
  1590. onoff[0] = 0;
  1591. box.pts = pts;
  1592. pts[0].x = 200; pts[0].y = 1400;
  1593. pts[1].x = 600; pts[1].y = 1400;
  1594. pts[2].x = 600; pts[2].y = 1800;
  1595. pts[3].x = 200; pts[3].y = 1800;
  1596. }
  1597. #endif
  1598. /* Update maxp */
  1599. if (glyph->num>tt->maxinstructions)
  1600. tt->maxinstructions = glyph->num;
  1601. if (glyph->stack>tt->maxstack)
  1602. tt->maxstack = glyph->stack;
  1603. if (glyph->twilights>tt->maxtwilight)
  1604. tt->maxtwilight = glyph->twilights;
  1605. if (glyph->paths==NULL) {
  1606. bbox[0].x = bbox[1].x = glyph->lsb;
  1607. bbox[0].y = bbox[1].y = 0;
  1608. status=RecordGlyph(tt, glyph->code, bbox,
  1609. glyph->aw, (USHORT)0, (USHORT)0);
  1610. } else {
  1611. /* Compute header information. */
  1612. bbox[0].x = bbox[0].y = SHRT_MAX;
  1613. bbox[1].x = bbox[1].y = SHRT_MIN;
  1614. for (c=0, path=glyph->paths; path; path=path->next, c++) {
  1615. BoundingBox(bbox, path->pts, path->count);
  1616. n = (USHORT)(n + path->count);
  1617. }
  1618. /* Record loca and cmap info. */
  1619. if ((status=RecordGlyph(tt, glyph->code, bbox,
  1620. glyph->aw, n, c))==SUCCESS) {
  1621. /* Write number of contours. */
  1622. WriteShort(c, tt->file);
  1623. /* Write bounding box. */
  1624. if (c) {
  1625. WriteShort((USHORT)bbox[0].x, tt->file);
  1626. WriteShort((USHORT)bbox[0].y, tt->file);
  1627. WriteShort((USHORT)bbox[1].x, tt->file);
  1628. WriteShort((USHORT)bbox[1].y, tt->file);
  1629. } else {
  1630. WriteShort(PAD0, tt->file);
  1631. WriteShort(PAD0, tt->file);
  1632. WriteShort(PAD0, tt->file);
  1633. WriteShort(PAD0, tt->file);
  1634. }
  1635. /* Write endPts */
  1636. for (c=0, path=glyph->paths; path; path=path->next) {
  1637. c = (USHORT)(c + path->count);
  1638. WriteShort((short)(c-1), tt->file);
  1639. }
  1640. /* Write instruction length. */
  1641. WriteShort(glyph->num, tt->file);
  1642. /* Write instruction. */
  1643. (void)WriteBytes(glyph->hints, glyph->num, tt->file);
  1644. /* Write the flags. */
  1645. x=0; y=0;
  1646. prev = 255;
  1647. cnt = 0;
  1648. for (path=glyph->paths; path; path=path->next) {
  1649. for (i=0; i<path->count; i++) {
  1650. flag = 0;
  1651. if (OnCurve(path->onoff, i))
  1652. flag |= FLG_ONCURVE;
  1653. if (path->pts[i].x==x) {
  1654. flag |= FLG_SAMEX;
  1655. } else if (ABS(path->pts[i].x - x) <= 255) {
  1656. flag |= FLG_SHORTX;
  1657. if (path->pts[i].x > x)
  1658. flag |= FLG_SAMEX;
  1659. }
  1660. if (path->pts[i].y==y) {
  1661. flag |= FLG_SAMEY;
  1662. } else if (ABS(path->pts[i].y - y) <= 255) {
  1663. flag |= FLG_SHORTY;
  1664. if (path->pts[i].y > y)
  1665. flag |= FLG_SAMEY;
  1666. }
  1667. x = path->pts[i].x;
  1668. y = path->pts[i].y;
  1669. if (prev!=255) {
  1670. if (prev!=flag) {
  1671. if (cnt) {
  1672. prev |= FLG_REPEAT;
  1673. WriteByte(prev, tt->file);
  1674. WriteByte(cnt, tt->file);
  1675. } else {
  1676. WriteByte(prev, tt->file);
  1677. }
  1678. cnt = 0;
  1679. } else {
  1680. cnt ++;
  1681. }
  1682. }
  1683. prev = flag;
  1684. }
  1685. }
  1686. if (cnt) {
  1687. prev |= FLG_REPEAT;
  1688. WriteByte(prev, tt->file);
  1689. WriteByte(cnt, tt->file);
  1690. } else {
  1691. WriteByte(prev, tt->file);
  1692. }
  1693. /* Write the x's */
  1694. x = 0;
  1695. for (path=glyph->paths; path; path=path->next) {
  1696. for (i=0; i<path->count; i++) {
  1697. if (path->pts[i].x != x) {
  1698. funit dx = path->pts[i].x - x;
  1699. if (ABS(dx)<=255) {
  1700. WriteByte((UBYTE)ABS(dx), tt->file);
  1701. } else {
  1702. WriteShort((USHORT)dx, tt->file);
  1703. }
  1704. }
  1705. x = path->pts[i].x;
  1706. }
  1707. }
  1708. /* Write the y's */
  1709. y = 0;
  1710. for (path=glyph->paths; path; path=path->next) {
  1711. for (i=0; i<path->count; i++) {
  1712. if (path->pts[i].y != y) {
  1713. funit dy = path->pts[i].y - y;
  1714. if (ABS(dy)<=255) {
  1715. WriteByte((UBYTE)ABS(dy), tt->file);
  1716. } else {
  1717. WriteShort((USHORT)dy, tt->file);
  1718. }
  1719. }
  1720. y = path->pts[i].y;
  1721. }
  1722. }
  1723. /* Word align the glyph entry. */
  1724. if (FileTell(tt->file) & 1)
  1725. WriteByte(0, tt->file);
  1726. /* Poll the file status. */
  1727. if (FileError(tt->file))
  1728. status = FAILURE;
  1729. }
  1730. }
  1731. /* Check for aliases. */
  1732. if (fStdEncoding)
  1733. {
  1734. if (LookupCharCode(glyph->code, ENC_UNICODE)==0x20) {
  1735. struct TTGlyph nobreak;
  1736. nobreak = *glyph;
  1737. nobreak.code = LookupPSName(NULL, 0, "nbspace");
  1738. PutTTGlyph(tt, &nobreak, FALSE);
  1739. }
  1740. if (LookupCharCode(glyph->code, ENC_UNICODE)==0x2d) {
  1741. struct TTGlyph sfthyphen;
  1742. sfthyphen = *glyph;
  1743. sfthyphen.code = LookupPSName(NULL, 0, "sfthyphen");
  1744. PutTTGlyph(tt, &sfthyphen, FALSE);
  1745. }
  1746. }
  1747. }
  1748. return status;
  1749. }
  1750. /***
  1751. ** Function: PutTTOther
  1752. **
  1753. ** Description:
  1754. ** This function writes the required TT tables to the
  1755. ** TT font file, except for the 'glyf' table which is
  1756. ** only completed (check sum is computed, etc.).
  1757. **
  1758. ***/
  1759. errcode PutTTOther(struct TTHandle *tt, struct TTMetrics *ttm)
  1760. {
  1761. long offset = TBLDIRSIZE*NUMTBL+12;
  1762. errcode status = SUCCESS;
  1763. UBYTE ascii2gi[MACSIZE];
  1764. errcode err = SUCCESS;
  1765. short locafmt = 0;
  1766. long csum = 0;
  1767. /*==GLYF===*/
  1768. tt->pool[tt->count].offset = FileTell(tt->file) - offset;
  1769. err = CompleteTable(offset, TBL_GLYF, tt->file);
  1770. /*==CMAP===*/
  1771. if (err==SUCCESS)
  1772. err = PutCMAP(tt, ascii2gi, ttm->Encoding, ttm->encSize);
  1773. /*==LOCA===*/
  1774. if (err==SUCCESS)
  1775. err = PutLOCA(tt->file, tt->pool, tt->count, &locafmt);
  1776. /*==HEAD===*/
  1777. if (err==SUCCESS)
  1778. err = PutHEAD(tt->file, tt->bbox, ttm, locafmt, &csum);
  1779. /*==HHEA===*/
  1780. if (err==SUCCESS)
  1781. err = PutHHEA(tt->file, tt->pool, tt->count,
  1782. tt->bbox, ttm->macLinegap, ttm);
  1783. /*==HMTX===*/
  1784. if (err==SUCCESS)
  1785. err = PutHMTX(tt->file, tt->pool, tt->count,
  1786. ttm->widths, ttm->FirstChar, ttm->LastChar,ttm->Encoding);
  1787. /*==OS/2===*/
  1788. if (err==SUCCESS)
  1789. err = PutOS2(tt->file, tt->pool, tt->count, ttm);
  1790. /*==MAXP===*/
  1791. if (err==SUCCESS)
  1792. err = PutMAXP(tt, ttm->maxstorage, ttm->maxprepstack, ttm->maxfpgm);
  1793. /*==Name===*/
  1794. if (err==SUCCESS)
  1795. err = PutNAME(tt->file, ttm);
  1796. /*==POST===*/
  1797. if (err==SUCCESS)
  1798. err = PutPOST(tt->file, tt->pool, tt->count, ttm);
  1799. /*==PREP===*/
  1800. if (err==SUCCESS)
  1801. err = PutPREP(tt->file,
  1802. ttm->prep, ttm->prep_size);
  1803. /*==FPGM===*/
  1804. if (err==SUCCESS)
  1805. err = PutFPGM(tt->file,
  1806. ttm->fpgm, ttm->fpgm_size);
  1807. /*==CVT===*/
  1808. if (err==SUCCESS)
  1809. err = PutCVT(tt->file, ttm->cvt, ttm->cvt_cnt);
  1810. /*==GASP==*/
  1811. if (err==SUCCESS)
  1812. err = PutGASP(tt->file, ttm->onepix);
  1813. if (ttm->kerns && (err==SUCCESS))
  1814. err = PutKERN(tt->file, ttm->kerns, ttm->kernsize, tt->pool, tt->count);
  1815. /*=====*/
  1816. /* Compute check sum. */
  1817. if (err==SUCCESS) {
  1818. WriteChecksum(csum, tt->file);
  1819. if (FileError(tt->file))
  1820. err = BADOUTPUTFILE;
  1821. }
  1822. if (err != SUCCESS)
  1823. SetError(status = err);
  1824. return status;
  1825. }
  1826. /***
  1827. ** Function: PutTTComposite
  1828. **
  1829. ** Description:
  1830. **
  1831. ***/
  1832. errcode PutTTComposite(struct TTHandle *tt, struct TTComposite *comp)
  1833. {
  1834. errcode status;
  1835. Point bbox[2], pts[2];
  1836. USHORT ai=0, bi=0, oi=0;
  1837. USHORT n,c;
  1838. /* Convert the encoding handles to glyph indices. */
  1839. while (ai<tt->count && comp->aenc!=tt->pool[ai].code)
  1840. ai++;
  1841. while (bi<tt->count && comp->benc!=tt->pool[bi].code)
  1842. bi++;
  1843. if (comp->oenc) {
  1844. while (oi<tt->count && comp->oenc!=tt->pool[oi].code)
  1845. oi++;
  1846. }
  1847. /* Update the bounding box. */
  1848. comp->dx += tt->pool[bi].bbox[0].x - tt->pool[ai].bbox[0].x;
  1849. bbox[0] = tt->pool[bi].bbox[0]; bbox[1] = tt->pool[bi].bbox[1];
  1850. pts[0] = tt->pool[ai].bbox[0]; pts[1] = tt->pool[ai].bbox[1];
  1851. pts[0].x += comp->dx; pts[1].x += comp->dx;
  1852. pts[0].y += comp->dy; pts[1].y += comp->dy;
  1853. BoundingBox(bbox, pts, (USHORT)2);
  1854. bbox[0].x = tt->pool[bi].bbox[0].x; bbox[1].x = tt->pool[bi].bbox[1].x;
  1855. if (comp->oenc)
  1856. BoundingBox(bbox, tt->pool[oi].bbox, (USHORT)2);
  1857. if ((status=RecordGlyph(tt, comp->cenc, bbox,
  1858. comp->aw, (USHORT)0, (USHORT)0))==FAILURE)
  1859. return status;
  1860. /* Update max composite points/contours/elements. */
  1861. n = (USHORT)(tt->pool[bi].pts + tt->pool[ai].pts);
  1862. c = (USHORT)(tt->pool[bi].conts + tt->pool[ai].conts);
  1863. if (n>tt->maxcomppts)
  1864. tt->maxcomppts = n;
  1865. if (c>tt->maxcompcont)
  1866. tt->maxcompcont = c;
  1867. if (comp->oenc)
  1868. tt->maxcompelements = 3;
  1869. else if (tt->maxcompelements<2)
  1870. tt->maxcompelements = 2;
  1871. /* Write number of contours. */
  1872. WriteShort((USHORT)-1, tt->file);
  1873. /* Write bounding box. */
  1874. WriteShort((USHORT)bbox[0].x, tt->file);
  1875. WriteShort((USHORT)bbox[0].y, tt->file);
  1876. WriteShort((USHORT)bbox[1].x, tt->file);
  1877. WriteShort((USHORT)bbox[1].y, tt->file);
  1878. /* Write flags. */
  1879. WriteShort((USHORT)(MORE_COMPONENTS |
  1880. ARGS_ARE_XY_VALUES |
  1881. ROUND_XY_TO_GRID),
  1882. tt->file);
  1883. /* Write base glyph index. */
  1884. WriteShort(bi, tt->file);
  1885. WriteByte(0, tt->file);
  1886. WriteByte(0, tt->file);
  1887. if (comp->oenc) {
  1888. WriteShort((USHORT)(MORE_COMPONENTS |
  1889. ARGS_ARE_XY_VALUES |
  1890. ROUND_XY_TO_GRID),
  1891. tt->file);
  1892. WriteShort(oi, tt->file);
  1893. WriteByte(0, tt->file);
  1894. WriteByte(0, tt->file);
  1895. }
  1896. WriteShort((USHORT)(ARGS_1_2_ARE_WORDS |
  1897. ARGS_ARE_XY_VALUES |
  1898. ROUND_XY_TO_GRID),
  1899. tt->file);
  1900. WriteShort(ai, tt->file);
  1901. WriteShort((USHORT)comp->dx, tt->file);
  1902. WriteShort((USHORT)comp->dy, tt->file);
  1903. /* Word align the glyph entry. */
  1904. if (FileTell(tt->file) & 1)
  1905. WriteByte(0, tt->file);
  1906. if (FileError(tt->file))
  1907. return FAILURE;
  1908. return SUCCESS;
  1909. }
  1910. /***
  1911. ** Function: GetPrep
  1912. **
  1913. ** Description:
  1914. ** This function allocates needed space for the
  1915. ** pre-program.
  1916. **
  1917. ***/
  1918. UBYTE *GetPrep(const int size)
  1919. {
  1920. return Malloc((size_t)size);
  1921. }
  1922. /***
  1923. ** Function: UsePrep
  1924. **
  1925. ** Description:
  1926. ** This function records the pre-program in the
  1927. ** TTMetrics record, until an appropriate time
  1928. ** when the data can be stored in the TT file.
  1929. **
  1930. ***/
  1931. void UsePrep(struct TTMetrics *ttm,
  1932. const UBYTE *prep,
  1933. const USHORT prep_size)
  1934. {
  1935. ttm->prep = (UBYTE *)prep;
  1936. ttm->prep_size = prep_size;
  1937. }
  1938. /***
  1939. ** Function: SetFPGM
  1940. **
  1941. ** Description:
  1942. ** This function records the font-program in the
  1943. ** TTMetrics record, until an appropriate time
  1944. ** when the data can be stored in the TT file.
  1945. **
  1946. ***/
  1947. void SetFPGM(struct TTMetrics *ttm,
  1948. const UBYTE *fpgm,
  1949. const USHORT fpgm_size,
  1950. const USHORT num)
  1951. {
  1952. ttm->fpgm = fpgm;
  1953. ttm->fpgm_size = fpgm_size;
  1954. ttm->maxfpgm = num;
  1955. }