gsfcid2.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. /* Copyright (C) 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: gsfcid2.c,v 1.6 2004/08/04 19:36:12 stefan Exp $ */
  14. /* Create a CIDFontType 2 font from a Type 42 font. */
  15. #include "memory_.h"
  16. #include "gx.h"
  17. #include "gserrors.h"
  18. #include "gsstruct.h"
  19. #include "gsutil.h"
  20. #include "gxfont.h"
  21. #include "gxfcid.h"
  22. #include "gxfcmap.h"
  23. #include "gxfont0c.h"
  24. /*
  25. * Create a Type 2 CIDFont from a Type 42 font.
  26. */
  27. private int
  28. identity_CIDMap_proc(gs_font_cid2 *pfont, gs_glyph glyph)
  29. {
  30. ulong cid = glyph - gs_min_cid_glyph;
  31. if (cid >= pfont->cidata.common.CIDCount)
  32. return_error(gs_error_rangecheck);
  33. return (int)cid;
  34. }
  35. int
  36. gs_font_cid2_from_type42(gs_font_cid2 **ppfcid, gs_font_type42 *pfont42,
  37. int wmode, gs_memory_t *mem)
  38. {
  39. gs_font_cid2 *pfcid =
  40. gs_alloc_struct(mem, gs_font_cid2, &st_gs_font_cid2,
  41. "gs_font_cid2_from_type42");
  42. if (pfcid == 0)
  43. return_error(gs_error_VMerror);
  44. /* CIDFontType 2 is a subclass (extension) of FontType 42. */
  45. memcpy(pfcid, pfont42, sizeof(*pfont42));
  46. pfcid->memory = mem;
  47. pfcid->next = pfcid->prev = 0; /* probably not necessary */
  48. pfcid->is_resource = 0;
  49. gs_font_notify_init((gs_font *)pfcid);
  50. pfcid->id = gs_next_ids(mem, 1);
  51. pfcid->base = (gs_font *)pfcid;
  52. pfcid->FontType = ft_CID_TrueType;
  53. /* Fill in the rest of the CIDFont data. */
  54. cid_system_info_set_null(&pfcid->cidata.common.CIDSystemInfo);
  55. pfcid->cidata.common.CIDCount = pfont42->data.numGlyphs;
  56. pfcid->cidata.common.GDBytes = 2; /* not used */
  57. pfcid->cidata.MetricsCount = 0;
  58. pfcid->cidata.CIDMap_proc = identity_CIDMap_proc;
  59. /* Since MetricsCount == 0, don't need orig_procs. */
  60. *ppfcid = pfcid;
  61. return 0;
  62. }
  63. /* Set up a pointer to a substring of the font data. */
  64. #define ACCESS(base, length, vptr)\
  65. BEGIN\
  66. code = pfont->data.string_proc(pfont, (ulong)(base), length, &vptr);\
  67. if ( code < 0 ) return code;\
  68. END
  69. #define U16(p) (((uint)((p)[0]) << 8) + (p)[1])
  70. #define U32(p) get_u32_msb(p)
  71. #define PUT16(p, v)\
  72. BEGIN (p)[0] = (byte)((v) >> 8); (p)[1] = (byte)(v); END
  73. /*
  74. * Define a subclass of gs_cmap_t that accesses the most common type of
  75. * TrueType cmap (Platform 3, Encoding 1, Format 4) directly.
  76. */
  77. typedef struct gs_cmap_tt_16bit_format4_s {
  78. GS_CMAP_COMMON;
  79. gs_font_type42 *font;
  80. uint segCount2;
  81. ulong endCount, startCount, idDelta, idRangeOffset, glyphIdArray;
  82. } gs_cmap_tt_16bit_format4_t;
  83. gs_private_st_suffix_add1(st_cmap_tt_16bit_format4, gs_cmap_tt_16bit_format4_t,
  84. "gs_cmap_tt_16bit_format4_t",
  85. cmap_tt_16bit_format4_enum_ptrs, cmap_tt_16bit_format4_reloc_ptrs,
  86. st_cmap, font);
  87. private int
  88. tt_16bit_format4_decode_next(const gs_cmap_t * pcmap_in,
  89. const gs_const_string * pstr,
  90. uint * pindex, uint * pfidx,
  91. gs_char * pchr, gs_glyph * pglyph)
  92. {
  93. const gs_cmap_tt_16bit_format4_t *pcmap =
  94. (const gs_cmap_tt_16bit_format4_t *)pcmap_in;
  95. gs_font_type42 *pfont = pcmap->font;
  96. const byte *ttdata;
  97. int code;
  98. uint chr, value = 0;
  99. uint segment2;
  100. if (pstr->size < *pindex + 2) {
  101. *pglyph = gs_no_glyph;
  102. return (*pindex == pstr->size ? 2 : -1);
  103. }
  104. chr = U16(pstr->data + *pindex);
  105. /* The table is sorted, but we use linear search for simplicity. */
  106. for (segment2 = 0; segment2 < pcmap->segCount2; segment2 += 2) {
  107. uint start, delta, roff;
  108. ACCESS(pcmap->endCount + segment2, 2, ttdata);
  109. if (chr > U16(ttdata))
  110. continue;
  111. ACCESS(pcmap->startCount + segment2, 2, ttdata);
  112. start = U16(ttdata);
  113. if (chr < start)
  114. continue;
  115. ACCESS(pcmap->idDelta + segment2, 2, ttdata);
  116. delta = U16(ttdata);
  117. ACCESS(pcmap->idRangeOffset + segment2, 2, ttdata);
  118. roff = U16(ttdata);
  119. if (roff) {
  120. ulong gidoff = pcmap->idRangeOffset + segment2 + roff +
  121. (chr - start) * 2;
  122. ACCESS(gidoff, 2, ttdata);
  123. value = U16(ttdata);
  124. if (value != 0)
  125. value += delta;
  126. } else
  127. value = chr + delta;
  128. break;
  129. }
  130. *pglyph = gs_min_cid_glyph + (value & 0xffff);
  131. *pchr = chr;
  132. *pindex += 2;
  133. *pfidx = 0;
  134. return 0;
  135. }
  136. private int
  137. tt_16bit_format4_next_range(gs_cmap_ranges_enum_t *penum)
  138. {
  139. /* There is just a single 2-byte range. */
  140. if (penum->index == 0) {
  141. penum->range.first[0] = penum->range.first[1] = 0;
  142. penum->range.last[0] = penum->range.last[1] = 0xff;
  143. penum->range.size = 2;
  144. penum->index = 1;
  145. return 0;
  146. }
  147. return 1;
  148. }
  149. private const gs_cmap_ranges_enum_procs_t tt_16bit_format4_range_procs = {
  150. tt_16bit_format4_next_range
  151. };
  152. private void
  153. tt_16bit_format4_enum_ranges(const gs_cmap_t *pcmap,
  154. gs_cmap_ranges_enum_t *pre)
  155. {
  156. gs_cmap_ranges_enum_setup(pre, pcmap, &tt_16bit_format4_range_procs);
  157. }
  158. private int
  159. tt_16bit_format4_next_lookup(gs_cmap_lookups_enum_t *penum)
  160. {
  161. if (penum->index[0] == 0) {
  162. penum->entry.key_size = 2;
  163. penum->entry.key_is_range = true;
  164. penum->entry.value_type = CODE_VALUE_CID;
  165. penum->entry.value.size = 2;
  166. penum->entry.font_index = 0;
  167. penum->index[0] = 1;
  168. return 0;
  169. }
  170. return 1;
  171. }
  172. private int
  173. tt_16bit_format4_next_entry(gs_cmap_lookups_enum_t *penum)
  174. {
  175. /* index[1] is segment # << 17 + first code. */
  176. uint segment2 = penum->index[1] >> 16;
  177. uint next = penum->index[1] & 0xffff;
  178. const gs_cmap_tt_16bit_format4_t *pcmap =
  179. (const gs_cmap_tt_16bit_format4_t *)penum->cmap;
  180. gs_font_type42 *pfont = pcmap->font;
  181. const byte *ttdata;
  182. int code;
  183. uint start, end, delta, roff;
  184. uint value;
  185. top:
  186. if (segment2 >= pcmap->segCount2)
  187. return 1;
  188. ACCESS(pcmap->endCount + segment2, 2, ttdata);
  189. end = U16(ttdata);
  190. if (next > end) {
  191. segment2 += 2;
  192. goto top;
  193. }
  194. ACCESS(pcmap->startCount + segment2, 2, ttdata);
  195. start = U16(ttdata);
  196. if (next < start)
  197. next = start;
  198. PUT16(penum->entry.key[0], next);
  199. ACCESS(pcmap->idDelta + segment2, 2, ttdata);
  200. delta = U16(ttdata);
  201. ACCESS(pcmap->idRangeOffset + segment2, 2, ttdata);
  202. roff = U16(ttdata);
  203. if (roff) {
  204. /* Non-zero offset, table lookup. */
  205. ulong gidoff = pcmap->idRangeOffset + segment2 + roff;
  206. ACCESS(gidoff, 2, ttdata);
  207. value = U16(ttdata);
  208. if (value != 0)
  209. value += delta;
  210. ++next;
  211. } else {
  212. /* Zero offset, account for high-order byte changes. */
  213. value = next + delta;
  214. next = min(end, (next | 0xff)) + 1;
  215. }
  216. PUT16(penum->entry.key[1], next - 1);
  217. PUT16(penum->temp_value, value);
  218. penum->entry.value.data = penum->temp_value;
  219. penum->entry.value.size = 2;
  220. penum->index[1] = (segment2 << 16) + next;
  221. return 0;
  222. }
  223. private const gs_cmap_lookups_enum_procs_t tt_16bit_format4_lookup_procs = {
  224. tt_16bit_format4_next_lookup, tt_16bit_format4_next_entry
  225. };
  226. private void
  227. tt_16bit_format4_enum_lookups(const gs_cmap_t *pcmap, int which,
  228. gs_cmap_lookups_enum_t *pre)
  229. {
  230. gs_cmap_lookups_enum_setup(pre, pcmap,
  231. (which ? &gs_cmap_no_lookups_procs :
  232. &tt_16bit_format4_lookup_procs));
  233. }
  234. private const gs_cmap_procs_t tt_16bit_format4_procs = {
  235. tt_16bit_format4_decode_next,
  236. tt_16bit_format4_enum_ranges,
  237. tt_16bit_format4_enum_lookups,
  238. gs_cmap_compute_identity
  239. };
  240. /*
  241. * Create a CMap from a TrueType Platform 3, Encoding 1, Format 4 cmap.
  242. */
  243. int
  244. gs_cmap_from_type42_cmap(gs_cmap_t **ppcmap, gs_font_type42 *pfont,
  245. int wmode, gs_memory_t *mem)
  246. {
  247. ulong origin = pfont->data.cmap;
  248. gs_cmap_tt_16bit_format4_t *pcmap;
  249. int code;
  250. const byte *ttdata;
  251. ulong offset = origin;
  252. uint segCount2;
  253. if (origin == 0)
  254. return_error(gs_error_invalidfont);
  255. /*
  256. * Find the desired cmap sub-table, if any.
  257. */
  258. {
  259. uint cmap_count;
  260. uint i;
  261. ACCESS(origin + 2, 2, ttdata);
  262. cmap_count = U16(ttdata);
  263. for (i = 0; i < cmap_count; ++i) {
  264. ACCESS(origin + 4 + i * 8, 8, ttdata);
  265. if (U16(ttdata) != 3 || /* platform ID */
  266. U16(ttdata + 2) != 1 /* encoding ID */
  267. )
  268. continue;
  269. offset = origin + U32(ttdata + 4);
  270. ACCESS(offset, 2, ttdata);
  271. if (U16(ttdata) != 4 /* format */)
  272. continue;
  273. break;
  274. }
  275. if (i >= cmap_count) /* not found */
  276. return_error(gs_error_invalidfont);
  277. ACCESS(offset + 6, 2, ttdata);
  278. segCount2 = U16(ttdata);
  279. }
  280. /* Allocate the CMap. */
  281. {
  282. static const gs_cid_system_info_t null_cidsi = {
  283. { (const byte*) "none", 4 },
  284. { (const byte*) "none", 4 },
  285. 0
  286. };
  287. code = gs_cmap_alloc(ppcmap, &st_cmap_tt_16bit_format4, wmode,
  288. (const byte *)"none", 4, &null_cidsi, 1,
  289. &tt_16bit_format4_procs, mem);
  290. if (code < 0)
  291. return code;
  292. }
  293. pcmap = (gs_cmap_tt_16bit_format4_t *)*ppcmap;
  294. pcmap->from_Unicode = true;
  295. pcmap->font = pfont;
  296. pcmap->segCount2 = segCount2;
  297. pcmap->endCount = offset + 14;
  298. pcmap->startCount = pcmap->endCount + segCount2 + 2;
  299. pcmap->idDelta = pcmap->startCount + segCount2;
  300. pcmap->idRangeOffset = pcmap->idDelta + segCount2;
  301. pcmap->glyphIdArray = pcmap->idRangeOffset + segCount2;
  302. return 0;
  303. }