gdevpsft.c 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206
  1. /* Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
  2. This software is provided AS-IS with no warranty, either express or
  3. implied.
  4. This software is distributed under license and may not be copied,
  5. modified or distributed except as expressly authorized under the terms
  6. of the license contained in the file LICENSE in this distribution.
  7. For more information about licensing, please refer to
  8. http://www.ghostscript.com/licensing/. For information on
  9. commercial licensing, go to http://www.artifex.com/licensing/ or
  10. contact Artifex Software, Inc., 101 Lucas Valley Road #110,
  11. San Rafael, CA 94903, U.S.A., +1(415)492-9861.
  12. */
  13. /* $Id: gdevpsft.c,v 1.35 2004/12/08 21:35:13 stefan Exp $ */
  14. /* Write an embedded TrueType font */
  15. #include "memory_.h"
  16. #include <assert.h>
  17. #include <stdlib.h> /* for qsort */
  18. #include "gx.h"
  19. #include "gscencs.h"
  20. #include "gserrors.h"
  21. #include "gsmatrix.h"
  22. #include "gsutil.h"
  23. #include "gxfcid.h"
  24. #include "gxfont.h"
  25. #include "gxfont42.h"
  26. #include "gxttf.h"
  27. #include "stream.h"
  28. #include "spprint.h"
  29. #include "gdevpsf.h"
  30. /* Internally used options */
  31. #define WRITE_TRUETYPE_STRIPPED 0x1000 /* internal */
  32. #define WRITE_TRUETYPE_CID 0x2000 /* internal */
  33. #define MAX_COMPOSITE_PIECES 3 /* adhoc */
  34. /*
  35. * The following are only for debugging. They force various format choices
  36. * in the output. The normal (non-debugging) values for all of these are
  37. * as indicated in the comments.
  38. *
  39. * Note that these options interact. Here is the complete list of settings
  40. * that make sense.
  41. 0 -1,0,1 N/A 0,1 0,1
  42. 0xf000 -1 N/A 1 0,1
  43. 0xf000 0,1 0,1 1 0,1
  44. */
  45. /* Define whether to use the 0xf000 character bias for generated tables. */
  46. #define TT_BIAS 0xf000 /* 0xf000 */
  47. /* Define whether to use cmap format 6 never(-1), sometimes(0), always(1). */
  48. #define TT_FORCE_CMAP_6 0 /* 0 */
  49. /* Define whether to use the bias for the cmap format 6 "first code". */
  50. #define TT_BIAS_CMAP_6 0 /* 0 */
  51. /* Define whether to generate an OS/2 table if none is supplied. */
  52. #define TT_GENERATE_OS_2 1 /* 1 */
  53. /* Define whether to adjust the OS/2 range bits. */
  54. #define TT_ADJUST_OS_2 1 /* 1 */
  55. /*
  56. * End of options.
  57. */
  58. /* ---------------- Utilities ---------------- */
  59. #define ACCESS(base, length, vptr)\
  60. BEGIN\
  61. code = string_proc(pfont, (ulong)(base), length, &vptr);\
  62. if (code < 0) return code;\
  63. END
  64. /* Pad to a multiple of 4 bytes. */
  65. private void
  66. put_pad(stream *s, uint length)
  67. {
  68. static const byte pad_to_4[3] = {0, 0, 0};
  69. stream_write(s, pad_to_4, (uint)(-(int)length & 3));
  70. }
  71. /* Put short and long values on a stream. */
  72. private void
  73. put_ushort(stream *s, uint v)
  74. {
  75. stream_putc(s, (byte)(v >> 8));
  76. stream_putc(s, (byte)v);
  77. }
  78. private void
  79. put_ulong(stream *s, ulong v)
  80. {
  81. put_ushort(s, (uint)(v >> 16));
  82. put_ushort(s, (uint)v);
  83. }
  84. private void
  85. put_loca(stream *s, ulong offset, int indexToLocFormat)
  86. {
  87. if (indexToLocFormat)
  88. put_ulong(s, offset);
  89. else
  90. put_ushort(s, (uint)(offset >> 1));
  91. }
  92. /* Get or put 2- or 4-byte quantities from/into a table. */
  93. #define U8(p) ((uint)((p)[0]))
  94. #define S8(p) (int)((U8(p) ^ 0x80) - 0x80)
  95. #define U16(p) (((uint)((p)[0]) << 8) + (p)[1])
  96. #define S16(p) (int)((U16(p) ^ 0x8000) - 0x8000)
  97. #define u32(p) get_u32_msb(p)
  98. private void
  99. put_u16(byte *p, uint v)
  100. {
  101. p[0] = (byte)(v >> 8);
  102. p[1] = (byte)v;
  103. }
  104. private void
  105. put_u32(byte *p, ulong v)
  106. {
  107. put_u16(p, (ushort)(v >> 16));
  108. put_u16(p + 2, (ushort)v);
  109. }
  110. private ulong
  111. put_table(byte tab[16], const char *tname, ulong checksum, ulong offset,
  112. uint length)
  113. {
  114. memcpy(tab, (const byte *)tname, 4);
  115. put_u32(tab + 4, checksum);
  116. put_u32(tab + 8, offset + 0x40000000);
  117. put_u32(tab + 12, (ulong)length);
  118. return offset + round_up(length, 4);
  119. }
  120. /* Write one range of a TrueType font. */
  121. private int
  122. write_range(stream *s, gs_font_type42 *pfont, ulong start, uint length)
  123. {
  124. ulong base = start;
  125. ulong limit = base + length;
  126. if_debug3('l', "[l]write_range pos = %ld, start = %lu, length = %u\n",
  127. stell(s), start, length);
  128. while (base < limit) {
  129. uint size = limit - base;
  130. const byte *ptr;
  131. int code;
  132. /* Write the largest block we can access consecutively. */
  133. while ((code = pfont->data.string_proc(pfont, base, size, &ptr)) < 0) {
  134. if (size <= 1)
  135. return code;
  136. size >>= 1;
  137. }
  138. if (code > 0 && size > code)
  139. size = code; /* Segmented data - see z42_string_proc. */
  140. stream_write(s, ptr, size);
  141. base += size;
  142. }
  143. return 0;
  144. }
  145. /*
  146. * Determine the Macintosh glyph number for a given character, if any.
  147. * If no glyph can be found, return -1 and store the name in *pstr.
  148. */
  149. private int
  150. mac_glyph_index(gs_font *font, int ch, gs_const_string *pstr)
  151. {
  152. gs_glyph glyph = font->procs.encode_char(font, (gs_char)ch,
  153. GLYPH_SPACE_NAME);
  154. int code;
  155. if (glyph == gs_no_glyph)
  156. return 0; /* .notdef */
  157. code = font->procs.glyph_name(font, glyph, pstr);
  158. assert(code >= 0);
  159. if (glyph < gs_min_cid_glyph) {
  160. gs_char mac_char;
  161. gs_glyph mac_glyph;
  162. gs_const_string mstr;
  163. /* Look (not very hard) for a match in the Mac glyph space. */
  164. if (ch >= 32 && ch <= 126)
  165. mac_char = ch - 29;
  166. else if (ch >= 128 && ch <= 255)
  167. mac_char = ch - 30;
  168. else
  169. return -1;
  170. mac_glyph = gs_c_known_encode(mac_char, ENCODING_INDEX_MACGLYPH);
  171. if (mac_glyph == gs_no_glyph)
  172. return -1;
  173. code = gs_c_glyph_name(mac_glyph, &mstr);
  174. assert(code >= 0);
  175. if (!bytes_compare(pstr->data, pstr->size, mstr.data, mstr.size))
  176. return (int)mac_char;
  177. }
  178. return -1;
  179. }
  180. /* ---------------- Individual tables ---------------- */
  181. /* ------ cmap ------ */
  182. /* Write a generated cmap table. */
  183. static const byte cmap_initial_0[] = {
  184. 0, 0, /* table version # = 0 */
  185. 0, 2, /* # of encoding tables = 2 */
  186. /* First table, Macintosh */
  187. 0, 1, /* platform ID = Macintosh */
  188. 0, 0, /* platform encoding ID = ??? */
  189. 0, 0, 0, 4+8+8, /* offset to table start */
  190. /* Second table, Windows */
  191. 0, 3, /* platform ID = Microsoft */
  192. 0, 0, /* platform encoding ID = unknown */
  193. 0, 0, 1, 4+8+8+6, /* offset to table start */
  194. /* Start of Macintosh format 0 table */
  195. 0, 0, /* format = 0, byte encoding table */
  196. 1, 6, /* length */
  197. 0, 0 /* version number */
  198. };
  199. static const byte cmap_initial_6[] = {
  200. 0, 0, /* table version # = 0 */
  201. 0, 2, /* # of encoding tables = 2 */
  202. /* First table, Macintosh */
  203. 0, 1, /* platform ID = Macintosh */
  204. 0, 0, /* platform encoding ID = ??? */
  205. 0, 0, 0, 4+8+8, /* offset to table start */
  206. /* Second table, Windows */
  207. 0, 3, /* platform ID = Microsoft */
  208. 0, 0, /* platform encoding ID = unknown */
  209. 0, 0, 0, 4+8+8+10, /* offset to table start */
  210. /* *VARIABLE*, add 2 x # of entries */
  211. /* Start of Macintosh format 6 table */
  212. 0, 6, /* format = 6, trimmed table mapping */
  213. 0, 10, /* length *VARIABLE*, add 2 x # of entries */
  214. 0, 0, /* version number */
  215. 0, 0, /* first character code */
  216. 0, 0 /* # of entries *VARIABLE* */
  217. };
  218. static const byte cmap_initial_4[] = {
  219. 0, 0, /* table version # = 0 */
  220. 0, 1, /* # of encoding tables = 2 */
  221. /* Single table, Windows */
  222. 0, 3, /* platform ID = Microsoft */
  223. 0, 0, /* platform encoding ID = unknown */
  224. 0, 0, 0, 4+8 /* offset to table start */
  225. };
  226. static const byte cmap_sub_initial[] = {
  227. 0, 4, /* format = 4, segment mapping */
  228. 0, 32, /* length ** VARIABLE, add 2 x # of glyphs ** */
  229. 0, 0, /* version # */
  230. 0, 4, /* 2 x segCount */
  231. 0, 4, /* searchRange = 2 x 2 ^ floor(log2(segCount)) */
  232. 0, 1, /* floor(log2(segCount)) */
  233. 0, 0, /* 2 x segCount - searchRange */
  234. 0, 0, /* endCount[0] **VARIABLE** */
  235. 255, 255, /* endCount[1] */
  236. 0, 0, /* reservedPad */
  237. 0, 0, /* startCount[0] **VARIABLE** */
  238. 255, 255, /* startCount[1] */
  239. 0, 0, /* idDelta[0] */
  240. 0, 1, /* idDelta[1] */
  241. 0, 4, /* idRangeOffset[0] */
  242. 0, 0 /* idRangeOffset[1] */
  243. };
  244. /*
  245. * The following nonsense is required because C defines sizeof()
  246. * inconsistently.
  247. */
  248. #define CMAP_ENTRIES_SIZE (256 * 2)
  249. private void
  250. write_cmap_0(stream *s, byte* entries /*[CMAP_ENTRIES_SIZE]*/, uint num_glyphs)
  251. {
  252. int i;
  253. memset(entries + 2 * num_glyphs, 0, CMAP_ENTRIES_SIZE - 2 * num_glyphs);
  254. stream_write(s, cmap_initial_0, sizeof(cmap_initial_0));
  255. for (i = 0; i <= 0xff; ++i)
  256. sputc(s, (byte)entries[2 * i + 1]);
  257. }
  258. private void
  259. write_cmap_6(stream *s, byte *entries /*[CMAP_ENTRIES_SIZE]*/, uint first_code,
  260. uint first_entry, uint num_entries)
  261. {
  262. byte cmap_data[sizeof(cmap_initial_6)];
  263. memcpy(cmap_data, cmap_initial_6, sizeof(cmap_initial_6));
  264. put_u16(cmap_data + 18,
  265. U16(cmap_data + 18) + num_entries * 2); /* offset */
  266. put_u16(cmap_data + 22,
  267. U16(cmap_data + 22) + num_entries * 2); /* length */
  268. put_u16(cmap_data + 26,
  269. #if TT_BIAS_CMAP_6
  270. first_code +
  271. #endif
  272. first_entry);
  273. put_u16(cmap_data + 28, num_entries);
  274. stream_write(s, cmap_data, sizeof(cmap_data));
  275. stream_write(s, entries + first_entry * 2, num_entries * 2);
  276. }
  277. private void
  278. write_cmap(stream *s, gs_font *font, uint first_code, int num_glyphs,
  279. gs_glyph max_glyph, int options, uint cmap_length)
  280. {
  281. byte cmap_sub[sizeof(cmap_sub_initial)];
  282. byte entries[CMAP_ENTRIES_SIZE];
  283. int first_entry = 0, end_entry = num_glyphs;
  284. bool can_use_trimmed = !(options & WRITE_TRUETYPE_NO_TRIMMED_TABLE);
  285. uint merge = 0;
  286. uint num_entries;
  287. int i;
  288. /* Collect the table entries. */
  289. for (i = 0; i < num_glyphs; ++i) {
  290. gs_glyph glyph =
  291. font->procs.encode_char(font, (gs_char)i, GLYPH_SPACE_INDEX);
  292. uint glyph_index;
  293. if (glyph == gs_no_glyph || glyph < GS_MIN_GLYPH_INDEX ||
  294. glyph > max_glyph
  295. )
  296. glyph = GS_MIN_GLYPH_INDEX;
  297. glyph_index = (uint)(glyph - GS_MIN_GLYPH_INDEX);
  298. merge |= glyph_index;
  299. put_u16(entries + 2 * i, glyph_index);
  300. }
  301. while (end_entry > first_entry && !U16(entries + 2 * end_entry - 2))
  302. --end_entry;
  303. while (first_entry < end_entry && !U16(entries + 2 * first_entry))
  304. ++first_entry;
  305. num_entries = end_entry - first_entry;
  306. /* Write the table header and Macintosh sub-table (if any). */
  307. #if TT_FORCE_CMAP_6 > 0
  308. /* Always use format 6. */
  309. write_cmap_6(s, entries, first_code, first_entry, num_entries);
  310. #else
  311. # if TT_FORCE_CMAP_6 < 0
  312. /* Never use format 6. Use format 0 if possible. */
  313. if (merge == (byte)merge)
  314. write_cmap_0(s, entries, num_glyphs);
  315. else
  316. # else /* TT_FORCE_CMAP == 0 */
  317. /*
  318. * Use format 0 if possible and (economical or format 6 disallowed),
  319. * otherwise format 6 if allowed.
  320. */
  321. if (merge == (byte)merge && (num_entries <= 127 || !can_use_trimmed))
  322. write_cmap_0(s, entries, num_glyphs);
  323. else if (can_use_trimmed)
  324. write_cmap_6(s, entries, first_code, first_entry, num_entries);
  325. else
  326. # endif
  327. {
  328. /*
  329. * Punt. Acrobat Reader 3 can't handle any other Mac table format.
  330. * (AR3 for Linux doesn't seem to be able to handle Windows format,
  331. * either, but maybe AR3 for Windows can.)
  332. */
  333. stream_write(s, cmap_initial_4, sizeof(cmap_initial_4));
  334. }
  335. #endif
  336. /* Write the Windows sub-table. */
  337. memcpy(cmap_sub, cmap_sub_initial, sizeof(cmap_sub_initial));
  338. put_u16(cmap_sub + 2, U16(cmap_sub + 2) + num_entries * 2); /* length */
  339. put_u16(cmap_sub + 14, first_code + end_entry - 1); /* endCount[0] */
  340. put_u16(cmap_sub + 20, first_code + first_entry); /* startCount[0] */
  341. stream_write(s, cmap_sub, sizeof(cmap_sub));
  342. stream_write(s, entries + first_entry * 2, num_entries * 2);
  343. put_pad(s, cmap_length);
  344. }
  345. private uint
  346. size_cmap(gs_font *font, uint first_code, int num_glyphs, gs_glyph max_glyph,
  347. int options)
  348. {
  349. stream poss;
  350. s_init(&poss, NULL);
  351. swrite_position_only(&poss);
  352. write_cmap(&poss, font, first_code, num_glyphs, max_glyph, options, 0);
  353. return stell(&poss);
  354. }
  355. /* ------ hmtx/vmtx ------ */
  356. private void
  357. write_mtx(stream *s, gs_font_type42 *pfont, const gs_type42_mtx_t *pmtx,
  358. int wmode)
  359. {
  360. uint num_metrics = pmtx->numMetrics;
  361. uint len = num_metrics * 4;
  362. double factor = pfont->data.unitsPerEm * (wmode ? -1 : 1);
  363. float sbw[4];
  364. uint i;
  365. sbw[0] = sbw[1] = sbw[2] = sbw[3] = 0; /* in case of failures */
  366. for (i = 0; i < pmtx->numMetrics; ++i) {
  367. DISCARD(pfont->data.get_metrics(pfont, i, wmode, sbw));
  368. put_ushort(s, (ushort)(sbw[wmode + 2] * factor)); /* width */
  369. put_ushort(s, (ushort)(sbw[wmode] * factor)); /* lsb, may be <0 */
  370. }
  371. for (; len < pmtx->length; ++i, len += 2) {
  372. DISCARD(pfont->data.get_metrics(pfont, i, wmode, sbw));
  373. put_ushort(s, (ushort)(sbw[wmode] * factor)); /* lsb, may be <0 */
  374. }
  375. }
  376. /* Compute the metrics from the glyph_info. */
  377. private uint
  378. size_mtx(gs_font_type42 *pfont, gs_type42_mtx_t *pmtx, uint max_glyph,
  379. int wmode)
  380. {
  381. int prev_width = min_int;
  382. uint last_width = 0; /* pacify compilers */
  383. double factor = pfont->data.unitsPerEm * (wmode ? -1 : 1);
  384. uint i;
  385. for (i = 0; i <= max_glyph; ++i) {
  386. float sbw[4];
  387. int code = pfont->data.get_metrics(pfont, i, wmode, sbw);
  388. int width;
  389. if (code < 0)
  390. continue;
  391. width = (int)(sbw[wmode + 2] * factor + 0.5);
  392. if (width != prev_width)
  393. prev_width = width, last_width = i;
  394. }
  395. pmtx->numMetrics = last_width + 1;
  396. pmtx->length = pmtx->numMetrics * 4 + (max_glyph - last_width) * 2;
  397. return pmtx->length;
  398. }
  399. /* ------ name ------ */
  400. /* Write a generated name table. */
  401. static const byte name_initial[] = {
  402. 0, 0, /* format */
  403. 0, 1, /* # of records = 1 */
  404. 0, 18, /* start of string storage */
  405. 0, 2, /* platform ID = ISO */
  406. 0, 2, /* encoding ID = ISO 8859-1 */
  407. 0, 0, /* language ID (none) */
  408. 0, 6, /* name ID = PostScript name */
  409. 0, 0, /* length *VARIABLE* */
  410. 0, 0 /* start of string within string storage */
  411. };
  412. private uint
  413. size_name(const gs_const_string *font_name)
  414. {
  415. return sizeof(name_initial) + font_name->size;
  416. }
  417. private void
  418. write_name(stream *s, const gs_const_string *font_name)
  419. {
  420. byte name_bytes[sizeof(name_initial)];
  421. memcpy(name_bytes, name_initial, sizeof(name_initial));
  422. put_u16(name_bytes + 14, font_name->size);
  423. stream_write(s, name_bytes, sizeof(name_bytes));
  424. stream_write(s, font_name->data, font_name->size);
  425. put_pad(s, size_name(font_name));
  426. }
  427. /* ------ OS/2 ------ */
  428. /* Write a generated OS/2 table. */
  429. #define OS_2_LENGTH sizeof(ttf_OS_2_t)
  430. private void
  431. update_OS_2(ttf_OS_2_t *pos2, uint first_glyph, int num_glyphs)
  432. {
  433. put_u16(pos2->usFirstCharIndex, first_glyph);
  434. put_u16(pos2->usLastCharIndex, first_glyph + num_glyphs - 1);
  435. #if TT_ADJUST_OS_2
  436. if (first_glyph >= 0xf000) {
  437. /* This font is being treated as a symbolic font. */
  438. memset(pos2->ulUnicodeRanges, 0, sizeof(pos2->ulUnicodeRanges));
  439. pos2->ulUnicodeRanges[7] = 8; /* bit 60, private use range */
  440. memset(pos2->ulCodePageRanges, 0, sizeof(pos2->ulCodePageRanges));
  441. pos2->ulCodePageRanges[3] = 1; /* bit 31, symbolic */
  442. }
  443. #endif
  444. }
  445. private void
  446. write_OS_2(stream *s, gs_font *font, uint first_glyph, int num_glyphs)
  447. {
  448. ttf_OS_2_t os2;
  449. /*
  450. * We don't bother to set most of the fields. The really important
  451. * ones, which affect character mapping, are usFirst/LastCharIndex.
  452. * We also need to set usWeightClass and usWidthClass to avoid
  453. * crashing ttfdump.
  454. */
  455. memset(&os2, 0, sizeof(os2));
  456. put_u16(os2.version, 1);
  457. put_u16(os2.usWeightClass, 400); /* Normal */
  458. put_u16(os2.usWidthClass, 5); /* Normal */
  459. update_OS_2(&os2, first_glyph, num_glyphs);
  460. stream_write(s, &os2, sizeof(os2));
  461. put_pad(s, sizeof(os2));
  462. }
  463. /* ------ post ------ */
  464. /* Construct and then write the post table. */
  465. typedef struct post_glyph_s {
  466. byte char_index;
  467. byte size;
  468. ushort glyph_index;
  469. } post_glyph_t;
  470. private int
  471. compare_post_glyphs(const void *pg1, const void *pg2)
  472. {
  473. gs_glyph g1 = ((const post_glyph_t *)pg1)->glyph_index,
  474. g2 = ((const post_glyph_t *)pg2)->glyph_index;
  475. return (g1 < g2 ? -1 : g1 > g2 ? 1 : 0);
  476. }
  477. typedef struct post_s {
  478. post_glyph_t glyphs[256 + 1];
  479. int count, glyph_count;
  480. uint length;
  481. } post_t;
  482. /*
  483. * If necessary, compute the length of the post table. Note that we
  484. * only generate post entries for characters in the Encoding.
  485. */
  486. private void
  487. compute_post(gs_font *font, post_t *post)
  488. {
  489. int i;
  490. for (i = 0, post->length = 32 + 2; i <= 255; ++i) {
  491. gs_const_string str;
  492. gs_glyph glyph = font->procs.encode_char(font, (gs_char)i,
  493. GLYPH_SPACE_INDEX);
  494. int mac_index = mac_glyph_index(font, i, &str);
  495. if (mac_index != 0) {
  496. post->glyphs[post->count].char_index = i;
  497. post->glyphs[post->count].size =
  498. (mac_index < 0 ? str.size + 1 : 0);
  499. post->glyphs[post->count].glyph_index = glyph - GS_MIN_GLYPH_INDEX;
  500. post->count++;
  501. }
  502. }
  503. if (post->count) {
  504. int j;
  505. qsort(post->glyphs, post->count, sizeof(post->glyphs[0]),
  506. compare_post_glyphs);
  507. /* Eliminate duplicate references to the same glyph. */
  508. for (i = j = 0; i < post->count; ++i) {
  509. if (i == 0 ||
  510. post->glyphs[i].glyph_index !=
  511. post->glyphs[i - 1].glyph_index
  512. ) {
  513. post->length += post->glyphs[i].size;
  514. post->glyphs[j++] = post->glyphs[i];
  515. }
  516. }
  517. post->count = j;
  518. post->glyph_count = post->glyphs[post->count - 1].glyph_index + 1;
  519. }
  520. post->length += post->glyph_count * 2;
  521. }
  522. /* Write the post table */
  523. private void
  524. write_post(stream *s, gs_font *font, post_t *post)
  525. {
  526. byte post_initial[32 + 2];
  527. uint name_index;
  528. uint glyph_index;
  529. int i;
  530. memset(post_initial, 0, 32);
  531. put_u32(post_initial, 0x00020000);
  532. put_u16(post_initial + 32, post->glyph_count);
  533. stream_write(s, post_initial, sizeof(post_initial));
  534. /* Write the name index table. */
  535. for (i = 0, name_index = 258, glyph_index = 0; i < post->count; ++i) {
  536. gs_const_string str;
  537. int ch = post->glyphs[i].char_index;
  538. int mac_index = mac_glyph_index(font, ch, &str);
  539. for (; glyph_index < post->glyphs[i].glyph_index; ++glyph_index)
  540. put_ushort(s, 0);
  541. glyph_index++;
  542. if (mac_index >= 0)
  543. put_ushort(s, mac_index);
  544. else {
  545. put_ushort(s, name_index);
  546. name_index++;
  547. }
  548. }
  549. /* Write the string names of the glyphs. */
  550. for (i = 0; i < post->count; ++i) {
  551. gs_const_string str;
  552. int ch = post->glyphs[i].char_index;
  553. int mac_index = mac_glyph_index(font, ch, &str);
  554. if (mac_index < 0) {
  555. spputc(s, (byte)str.size);
  556. stream_write(s, str.data, str.size);
  557. }
  558. }
  559. put_pad(s, post->length);
  560. }
  561. /* ---------------- Main program ---------------- */
  562. /* Write the definition of a TrueType font. */
  563. private int
  564. compare_table_tags(const void *pt1, const void *pt2)
  565. {
  566. ulong t1 = u32(pt1), t2 = u32(pt2);
  567. return (t1 < t2 ? -1 : t1 > t2 ? 1 : 0);
  568. }
  569. private int
  570. psf_write_truetype_data(stream *s, gs_font_type42 *pfont, int options,
  571. psf_glyph_enum_t *penum, bool is_subset,
  572. const gs_const_string *alt_font_name)
  573. {
  574. gs_font *const font = (gs_font *)pfont;
  575. gs_const_string font_name;
  576. int (*string_proc)(gs_font_type42 *, ulong, uint, const byte **) =
  577. pfont->data.string_proc;
  578. const byte *OffsetTable;
  579. uint numTables_stored, numTables, numTables_out;
  580. #define MAX_NUM_TABLES 40
  581. byte tables[MAX_NUM_TABLES * 16];
  582. uint i;
  583. ulong offset;
  584. gs_glyph glyph, glyph_prev;
  585. ulong max_glyph;
  586. uint glyf_length, loca_length;
  587. ulong glyf_checksum = 0L; /****** NO CHECKSUM ******/
  588. ulong loca_checksum[2] = {0L,0L};
  589. ulong glyf_alignment = 0;
  590. uint numGlyphs = 0; /* original value from maxp */
  591. byte head[56]; /* 0 mod 4 */
  592. gs_type42_mtx_t mtx[2];
  593. post_t post;
  594. ulong head_checksum, file_checksum = 0;
  595. int indexToLocFormat = 0;
  596. bool
  597. writing_cid = (options & WRITE_TRUETYPE_CID) != 0,
  598. writing_stripped = (options & WRITE_TRUETYPE_STRIPPED) != 0,
  599. generate_mtx = (options & WRITE_TRUETYPE_HVMTX) != 0,
  600. no_generate = writing_cid | writing_stripped,
  601. have_cmap = no_generate,
  602. have_name = !(options & WRITE_TRUETYPE_NAME),
  603. have_OS_2 = no_generate,
  604. have_post = no_generate;
  605. int have_hvhea[2];
  606. uint cmap_length = 0;
  607. ulong OS_2_start = 0;
  608. uint OS_2_length = OS_2_LENGTH;
  609. int code;
  610. have_hvhea[0] = have_hvhea[1] = 0;
  611. if (alt_font_name)
  612. font_name = *alt_font_name;
  613. else
  614. font_name.data = font->font_name.chars,
  615. font_name.size = font->font_name.size;
  616. /*
  617. * Count the number of tables, including the eventual glyf and loca
  618. * (which may not actually be present in the font), and copy the
  619. * table directory.
  620. */
  621. ACCESS(0, 12, OffsetTable);
  622. numTables_stored = U16(OffsetTable + 4);
  623. for (i = numTables = 0; i < numTables_stored; ++i) {
  624. const byte *tab;
  625. const byte *data;
  626. ulong start;
  627. uint length;
  628. if (numTables == MAX_NUM_TABLES)
  629. return_error(gs_error_limitcheck);
  630. ACCESS(12 + i * 16, 16, tab);
  631. start = u32(tab + 8);
  632. length = u32(tab + 12);
  633. /* Copy the table data now, since another ACCESS may invalidate it. */
  634. memcpy(&tables[numTables * 16], tab, 16);
  635. #define W(a,b,c,d)\
  636. ( ((a) << 24) + ((b) << 16) + ((c) << 8) + (d))
  637. switch (u32(tab)) {
  638. case W('h','e','a','d'):
  639. if (length != 54)
  640. return_error(gs_error_invalidfont);
  641. ACCESS(start, length, data);
  642. memcpy(head, data, length);
  643. continue;
  644. case W('g','l','y','f'): /* synthesized */
  645. case W('g','l','y','x'): /* Adobe bogus */
  646. case W('l','o','c','a'): /* synthesized */
  647. case W('l','o','c','x'): /* Adobe bogus */
  648. case W('g','d','i','r'): /* Adobe marker */
  649. continue;
  650. case W('c','m','a','p'):
  651. if (options & (WRITE_TRUETYPE_CMAP | WRITE_TRUETYPE_CID))
  652. continue;
  653. have_cmap = true;
  654. break;
  655. case W('m','a','x','p'):
  656. ACCESS(start, length, data);
  657. numGlyphs = U16(data + 4);
  658. break;
  659. case W('n','a','m','e'):
  660. if (writing_cid)
  661. continue;
  662. have_name = true;
  663. break;
  664. case W('O','S','/','2'):
  665. if (writing_cid)
  666. continue;
  667. have_OS_2 = true;
  668. if (length > OS_2_LENGTH)
  669. return_error(gs_error_invalidfont);
  670. OS_2_start = start;
  671. OS_2_length = length;
  672. continue;
  673. case W('p','o','s','t'):
  674. have_post = true;
  675. break;
  676. case W('h','h','e','a'):
  677. have_hvhea[0] = 1;
  678. break;
  679. case W('v','h','e','a'):
  680. have_hvhea[1] = 1;
  681. break;
  682. case W('h','m','t','x'):
  683. case W('v','m','t','x'):
  684. if (generate_mtx)
  685. continue;
  686. /* falls through */
  687. case W('c','v','t',' '):
  688. case W('f','p','g','m'):
  689. case W('g','a','s','p'):
  690. case W('k','e','r','n'):
  691. case W('p','r','e','p'):
  692. break; /* always copy these if present */
  693. default:
  694. if (writing_cid)
  695. continue;
  696. break;
  697. }
  698. numTables++;
  699. }
  700. /*
  701. * Enumerate the glyphs to get the size of glyf and loca,
  702. * and to compute the checksums for these tables.
  703. */
  704. /****** NO CHECKSUMS YET ******/
  705. for (max_glyph = 0, glyf_length = 0;
  706. (code = psf_enumerate_glyphs_next(penum, &glyph)) != 1;
  707. ) {
  708. uint glyph_index;
  709. gs_glyph_data_t glyph_data;
  710. if (glyph < gs_min_cid_glyph)
  711. return_error(gs_error_invalidfont);
  712. glyph_index = glyph & ~GS_GLYPH_TAG;
  713. if_debug1('L', "[L]glyph_index %u\n", glyph_index);
  714. glyph_data.memory = pfont->memory;
  715. if ((code = pfont->data.get_outline(pfont, glyph_index, &glyph_data)) >= 0) {
  716. /* Since indexToLocFormat==0 assumes even glyph lengths,
  717. round it up here. If later we choose indexToLocFormat==1,
  718. subtract the glyf_alignment to compensate it. */
  719. uint l = (glyph_data.bits.size + 1) & ~1;
  720. max_glyph = max(max_glyph, glyph_index);
  721. glyf_length += l;
  722. if (l != glyph_data.bits.size)
  723. glyf_alignment++;
  724. if_debug1('L', "[L] size %u\n", glyph_data.bits.size);
  725. gs_glyph_data_free(&glyph_data, "psf_write_truetype_data");
  726. }
  727. }
  728. /*
  729. * For subset fonts, we should trim the loca table so that it only
  730. * contains entries through max_glyph. Unfortunately, this would
  731. * require changing numGlyphs in maxp, which in turn would affect hdmx,
  732. * hhea, hmtx, vdmx, vhea, vmtx, and possibly other tables. This is way
  733. * more work than we want to do right now.
  734. */
  735. if (writing_stripped) {
  736. glyf_length = 0;
  737. loca_length = 0;
  738. } else {
  739. /*loca_length = (max_glyph + 2) << 2;*/
  740. loca_length = (numGlyphs + 1) << 2;
  741. indexToLocFormat = (glyf_length > 0x1fffc);
  742. if (!indexToLocFormat)
  743. loca_length >>= 1;
  744. else
  745. glyf_length -= glyf_alignment;
  746. /* Acrobat Reader won't accept fonts with empty glyfs. */
  747. if (glyf_length == 0)
  748. glyf_length = 1;
  749. }
  750. if_debug2('l', "[l]max_glyph = %lu, glyf_length = %lu\n",
  751. (ulong)max_glyph, (ulong)glyf_length);
  752. /*
  753. * If necessary, compute the length of the post table. Note that we
  754. * only generate post entries for characters in the Encoding. */
  755. if (!have_post) {
  756. memset(&post, 0, sizeof(post));
  757. if (options & WRITE_TRUETYPE_POST)
  758. compute_post(font, &post);
  759. else
  760. post.length = 32; /* dummy table */
  761. }
  762. /* Fix up the head table. */
  763. memset(head + 8, 0, 4);
  764. head[51] = (byte)indexToLocFormat;
  765. memset(head + 54, 0, 2);
  766. for (head_checksum = 0, i = 0; i < 56; i += 4)
  767. head_checksum += u32(&head[i]);
  768. /*
  769. * Construct the table directory, except for glyf, loca, head, OS/2,
  770. * and, if necessary, generated cmap, name, and post tables.
  771. * Note that the existing directory is already sorted by tag.
  772. */
  773. numTables_out = numTables + 1 /* head */
  774. + !writing_stripped * 2 /* glyf, loca */
  775. + generate_mtx * (have_hvhea[0] + have_hvhea[1]) /* hmtx, vmtx */
  776. + !have_OS_2 /* OS/2 */
  777. + !have_cmap + !have_name + !have_post;
  778. if (numTables_out >= MAX_NUM_TABLES)
  779. return_error(gs_error_limitcheck);
  780. offset = 12 + numTables_out * 16;
  781. for (i = 0; i < numTables; ++i) {
  782. byte *tab = &tables[i * 16];
  783. ulong length = u32(tab + 12);
  784. offset += round_up(length, 4);
  785. }
  786. /* Make the table directory entries for generated tables. */
  787. {
  788. byte *tab = &tables[numTables * 16];
  789. if (!writing_stripped) {
  790. offset = put_table(tab, "glyf", glyf_checksum,
  791. offset, glyf_length);
  792. tab += 16;
  793. offset = put_table(tab, "loca", loca_checksum[indexToLocFormat],
  794. offset, loca_length);
  795. tab += 16;
  796. }
  797. if (!have_cmap) {
  798. cmap_length = size_cmap(font, TT_BIAS, 256,
  799. GS_MIN_GLYPH_INDEX + max_glyph, options);
  800. offset = put_table(tab, "cmap", 0L /****** NO CHECKSUM ******/,
  801. offset, cmap_length);
  802. tab += 16;
  803. }
  804. if (!have_name) {
  805. offset = put_table(tab, "name", 0L /****** NO CHECKSUM ******/,
  806. offset, size_name(&font_name));
  807. tab += 16;
  808. }
  809. if (!no_generate) {
  810. offset = put_table(tab, "OS/2", 0L /****** NO CHECKSUM ******/,
  811. offset, OS_2_length);
  812. tab += 16;
  813. }
  814. if (generate_mtx)
  815. for (i = 0; i < 2; ++i)
  816. if (have_hvhea[i]) {
  817. offset = put_table(tab, (i ? "vmtx" : "hmtx"),
  818. 0L /****** NO CHECKSUM ******/,
  819. offset,
  820. size_mtx(pfont, &mtx[i], max_glyph, i));
  821. tab += 16;
  822. }
  823. if (!have_post) {
  824. offset = put_table(tab, "post", 0L /****** NO CHECKSUM ******/,
  825. offset, post.length);
  826. tab += 16;
  827. }
  828. /*
  829. * Note that the 'head' table must have length 54, even though
  830. * it occupies 56 bytes on the file.
  831. */
  832. offset = put_table(tab, "head", head_checksum, offset, 54);
  833. tab += 16;
  834. }
  835. numTables = numTables_out;
  836. /* Write the font header. */
  837. {
  838. static const byte version[4] = {0, 1, 0, 0};
  839. stream_write(s, version, 4);
  840. }
  841. put_ushort(s, numTables);
  842. for (i = 0; 1 << i <= numTables; ++i)
  843. DO_NOTHING;
  844. --i;
  845. put_ushort(s, 16 << i); /* searchRange */
  846. put_ushort(s, i); /* entrySelectors */
  847. put_ushort(s, numTables * 16 - (16 << i)); /* rangeShift */
  848. /* Write the table directory. */
  849. qsort(tables, numTables, 16, compare_table_tags);
  850. offset = 12 + numTables * 16;
  851. for (i = 0; i < numTables; ++i) {
  852. const byte *tab = &tables[i * 16];
  853. byte entry[16];
  854. memcpy(entry, tab, 16);
  855. if (entry[8] < 0x40) {
  856. /* Not a generated table. */
  857. uint length = u32(tab + 12);
  858. put_u32(entry + 8, offset);
  859. offset += round_up(length, 4);
  860. } else {
  861. entry[8] -= 0x40;
  862. }
  863. stream_write(s, entry, 16);
  864. }
  865. /* Write tables other than the ones we generate here. */
  866. for (i = 0; i < numTables; ++i) {
  867. const byte *tab = &tables[i * 16];
  868. if (tab[8] < 0x40) {
  869. ulong start = u32(tab + 8);
  870. uint length = u32(tab + 12);
  871. switch (u32(tab)) {
  872. case W('O','S','/','2'):
  873. if (!have_cmap) {
  874. /*
  875. * Adjust the first and last character indices in the OS/2
  876. * table to reflect the values in the generated cmap.
  877. */
  878. const byte *pos2;
  879. ttf_OS_2_t os2;
  880. ACCESS(OS_2_start, OS_2_length, pos2);
  881. memcpy(&os2, pos2, min(OS_2_length, sizeof(os2)));
  882. update_OS_2(&os2, TT_BIAS, 256);
  883. stream_write(s, &os2, OS_2_length);
  884. put_pad(s, OS_2_length);
  885. } else {
  886. /* Just copy the existing OS/2 table. */
  887. write_range(s, pfont, OS_2_start, OS_2_length);
  888. put_pad(s, OS_2_length);
  889. }
  890. break;
  891. case W('h','h','e','a'):
  892. case W('v','h','e','a'):
  893. if (generate_mtx) {
  894. write_range(s, pfont, start, length - 2); /* 34 */
  895. put_ushort(s, mtx[tab[0] == 'v'].numMetrics);
  896. break;
  897. }
  898. /* falls through */
  899. default:
  900. write_range(s, pfont, start, length);
  901. }
  902. put_pad(s, length);
  903. }
  904. }
  905. if (!writing_stripped) {
  906. /* Write glyf. */
  907. psf_enumerate_glyphs_reset(penum);
  908. for (offset = 0; psf_enumerate_glyphs_next(penum, &glyph) != 1; ) {
  909. gs_glyph_data_t glyph_data;
  910. glyph_data.memory = pfont->memory;
  911. if ((code = pfont->data.get_outline(pfont,
  912. glyph & ~GS_GLYPH_TAG,
  913. &glyph_data)) >= 0
  914. ) {
  915. uint l = glyph_data.bits.size, zero = 0;
  916. if (!indexToLocFormat)
  917. l = (l + 1) & ~1;
  918. stream_write(s, glyph_data.bits.data, glyph_data.bits.size);
  919. if (glyph_data.bits.size < l)
  920. stream_write(s, &zero, 1);
  921. offset += l;
  922. if_debug2('L', "[L]glyf index = %u, size = %u\n",
  923. i, glyph_data.bits.size);
  924. gs_glyph_data_free(&glyph_data, "psf_write_truetype_data");
  925. }
  926. }
  927. if_debug1('l', "[l]glyf final offset = %lu\n", offset);
  928. /* Add a dummy byte if necessary to make glyf non-empty. */
  929. while (offset < glyf_length)
  930. stream_putc(s, 0), ++offset;
  931. put_pad(s, (uint)offset);
  932. /* Write loca. */
  933. psf_enumerate_glyphs_reset(penum);
  934. glyph_prev = 0;
  935. for (offset = 0; psf_enumerate_glyphs_next(penum, &glyph) != 1; ) {
  936. gs_glyph_data_t glyph_data;
  937. uint glyph_index = glyph & ~GS_GLYPH_TAG;
  938. for (; glyph_prev <= glyph_index; ++glyph_prev)
  939. put_loca(s, offset, indexToLocFormat);
  940. glyph_data.memory = pfont->memory;
  941. if ((code = pfont->data.get_outline(pfont, glyph_index,
  942. &glyph_data)) >= 0
  943. ) {
  944. uint l = glyph_data.bits.size;
  945. if (!indexToLocFormat)
  946. l = (l + 1) & ~1;
  947. offset += l;
  948. gs_glyph_data_free(&glyph_data, "psf_write_truetype_data");
  949. }
  950. }
  951. /* Pad to numGlyphs + 1 entries (including the trailing entry). */
  952. for (; glyph_prev <= numGlyphs; ++glyph_prev)
  953. put_loca(s, offset, indexToLocFormat);
  954. put_pad(s, loca_length);
  955. /* If necessary, write cmap, name, and OS/2. */
  956. if (!have_cmap)
  957. write_cmap(s, font, TT_BIAS, 256, GS_MIN_GLYPH_INDEX + max_glyph,
  958. options, cmap_length);
  959. if (!have_name)
  960. write_name(s, &font_name);
  961. if (!have_OS_2)
  962. write_OS_2(s, font, TT_BIAS, 256);
  963. /* If necessary, write [hv]mtx. */
  964. if (generate_mtx)
  965. for (i = 0; i < 2; ++i)
  966. if (have_hvhea[i]) {
  967. write_mtx(s, pfont, &mtx[i], i);
  968. put_pad(s, mtx[i].length);
  969. }
  970. /* If necessary, write post. */
  971. if (!have_post) {
  972. if (options & WRITE_TRUETYPE_POST)
  973. write_post(s, font, &post);
  974. else {
  975. byte post_initial[32 + 2];
  976. memset(post_initial, 0, 32);
  977. put_u32(post_initial, 0x00030000);
  978. stream_write(s, post_initial, 32);
  979. }
  980. }
  981. }
  982. /* Write head. */
  983. /****** CHECKSUM WAS NEVER COMPUTED ******/
  984. /*
  985. * The following nonsense is to avoid warnings about the constant
  986. * 0xb1b0afbaL being "unsigned in ANSI C, signed with -traditional".
  987. */
  988. #if ARCH_SIZEOF_LONG > ARCH_SIZEOF_INT
  989. # define HEAD_MAGIC 0xb1b0afbaL
  990. #else
  991. # define HEAD_MAGIC ((ulong)~0x4e4f5045)
  992. #endif
  993. put_u32(head + 8, HEAD_MAGIC - file_checksum); /* per spec */
  994. #undef HEAD_MAGIC
  995. stream_write(s, head, 56);
  996. return 0;
  997. }
  998. /* Write a TrueType font. */
  999. int
  1000. psf_write_truetype_font(stream *s, gs_font_type42 *pfont, int options,
  1001. gs_glyph *orig_subset_glyphs, uint orig_subset_size,
  1002. const gs_const_string *alt_font_name)
  1003. {
  1004. gs_font *const font = (gs_font *)pfont;
  1005. psf_glyph_enum_t genum;
  1006. gs_glyph subset_data[256 * MAX_COMPOSITE_PIECES];
  1007. gs_glyph *subset_glyphs = orig_subset_glyphs;
  1008. uint subset_size = orig_subset_size;
  1009. /* Sort the subset glyphs, if any. */
  1010. if (subset_glyphs) {
  1011. /* Add the component glyphs for composites. */
  1012. int code;
  1013. memcpy(subset_data, orig_subset_glyphs,
  1014. sizeof(gs_glyph) * subset_size);
  1015. subset_glyphs = subset_data;
  1016. code = psf_add_subset_pieces(subset_glyphs, &subset_size,
  1017. countof(subset_data),
  1018. countof(subset_data),
  1019. font);
  1020. if (code < 0)
  1021. return code;
  1022. subset_size = psf_sort_glyphs(subset_glyphs, subset_size);
  1023. }
  1024. psf_enumerate_glyphs_begin(&genum, font, subset_glyphs,
  1025. (subset_glyphs ? subset_size : 0),
  1026. GLYPH_SPACE_INDEX);
  1027. return psf_write_truetype_data(s, pfont, options & ~WRITE_TRUETYPE_CID,
  1028. &genum, subset_glyphs != 0, alt_font_name);
  1029. }
  1030. /* Write a stripped TrueType font. */
  1031. int
  1032. psf_write_truetype_stripped(stream *s, gs_font_type42 *pfont)
  1033. {
  1034. psf_glyph_enum_t genum;
  1035. byte no_subset = 0;
  1036. psf_enumerate_bits_begin(&genum, (gs_font *)pfont, &no_subset, 0,
  1037. GLYPH_SPACE_INDEX);
  1038. return psf_write_truetype_data(s, pfont, WRITE_TRUETYPE_STRIPPED,
  1039. &genum, true, NULL);
  1040. }
  1041. /* Write a CIDFontType 2 font. */
  1042. int
  1043. psf_write_cid2_font(stream *s, gs_font_cid2 *pfont, int options,
  1044. const byte *subset_bits, uint subset_size,
  1045. const gs_const_string *alt_font_name)
  1046. {
  1047. gs_font *const font = (gs_font *)pfont;
  1048. psf_glyph_enum_t genum;
  1049. psf_enumerate_bits_begin(&genum, font, subset_bits,
  1050. (subset_bits ? subset_size : 0),
  1051. GLYPH_SPACE_INDEX);
  1052. return psf_write_truetype_data(s, (gs_font_type42 *)font,
  1053. options | WRITE_TRUETYPE_CID, &genum,
  1054. subset_bits != 0, alt_font_name);
  1055. }
  1056. /* Write a stripped CIDFontType 2 font. */
  1057. int
  1058. psf_write_cid2_stripped(stream *s, gs_font_cid2 *pfont)
  1059. {
  1060. gs_font *const font = (gs_font *)pfont;
  1061. psf_glyph_enum_t genum;
  1062. byte no_subset = 0;
  1063. psf_enumerate_bits_begin(&genum, font, &no_subset, 0,
  1064. GLYPH_SPACE_INDEX);
  1065. return psf_write_truetype_data(s, (gs_font_type42 *)font,
  1066. WRITE_TRUETYPE_STRIPPED |
  1067. WRITE_TRUETYPE_CID,
  1068. &genum, true, NULL);
  1069. }