Leaked source code of windows server 2003
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.

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