pdf-type3.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. // Copyright (C) 2004-2025 Artifex Software, Inc.
  2. //
  3. // This file is part of MuPDF.
  4. //
  5. // MuPDF is free software: you can redistribute it and/or modify it under the
  6. // terms of the GNU Affero General Public License as published by the Free
  7. // Software Foundation, either version 3 of the License, or (at your option)
  8. // any later version.
  9. //
  10. // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
  11. // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  12. // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
  13. // details.
  14. //
  15. // You should have received a copy of the GNU Affero General Public License
  16. // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
  17. //
  18. // Alternative licensing terms are available from the licensor.
  19. // For commercial licensing, see <https://www.artifex.com/> or contact
  20. // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
  21. // CA 94129, USA, for further information.
  22. #include "mupdf/fitz.h"
  23. #include "mupdf/pdf.h"
  24. static void
  25. pdf_run_glyph_func(fz_context *ctx, void *doc, void *rdb, fz_buffer *contents, fz_device *dev, fz_matrix ctm, void *gstate, fz_default_colorspaces *default_cs, void *fill_gstate, void *stroke_gstate)
  26. {
  27. pdf_run_glyph(ctx, doc, (pdf_obj *)rdb, contents, dev, ctm, gstate, default_cs, fill_gstate, stroke_gstate);
  28. }
  29. static void
  30. pdf_t3_free_resources(fz_context *ctx, void *doc, void *rdb_)
  31. {
  32. pdf_obj *rdb = (pdf_obj *)rdb_;
  33. pdf_drop_obj(ctx, rdb);
  34. }
  35. pdf_font_desc *
  36. pdf_load_type3_font(fz_context *ctx, pdf_document *doc, pdf_obj *rdb, pdf_obj *dict)
  37. {
  38. char buf[256];
  39. const char *estrings[256];
  40. pdf_font_desc *fontdesc = NULL;
  41. pdf_obj *encoding;
  42. pdf_obj *widths;
  43. pdf_obj *charprocs;
  44. pdf_obj *obj;
  45. int first, last;
  46. int i, k, n;
  47. fz_rect bbox;
  48. fz_matrix matrix;
  49. fz_font *font = NULL;
  50. fz_var(fontdesc);
  51. /* Make a new type3 font entry in the document */
  52. if (doc->num_type3_fonts == doc->max_type3_fonts)
  53. {
  54. int new_max = doc->max_type3_fonts * 2;
  55. if (new_max == 0)
  56. new_max = 4;
  57. doc->type3_fonts = fz_realloc_array(ctx, doc->type3_fonts, new_max, fz_font*);
  58. doc->max_type3_fonts = new_max;
  59. }
  60. fz_try(ctx)
  61. {
  62. obj = pdf_dict_get(ctx, dict, PDF_NAME(Name));
  63. if (pdf_is_name(ctx, obj))
  64. fz_strlcpy(buf, pdf_to_name(ctx, obj), sizeof buf);
  65. else
  66. fz_strlcpy(buf, "Unnamed-T3", sizeof buf);
  67. fontdesc = pdf_new_font_desc(ctx);
  68. matrix = pdf_dict_get_matrix(ctx, dict, PDF_NAME(FontMatrix));
  69. bbox = pdf_dict_get_rect(ctx, dict, PDF_NAME(FontBBox));
  70. bbox = fz_transform_rect(bbox, matrix);
  71. font = fz_new_type3_font(ctx, buf, matrix);
  72. fontdesc->font = font;
  73. fontdesc->size += sizeof(fz_font) + 256 * (sizeof(fz_buffer*) + sizeof(float));
  74. fz_set_font_bbox(ctx, font, bbox.x0, bbox.y0, bbox.x1, bbox.y1);
  75. font->ascender = bbox.y1;
  76. font->descender = bbox.y0;
  77. font->ascdesc_src = FZ_ASCDESC_FROM_BOUNDS;
  78. /* Encoding */
  79. for (i = 0; i < 256; i++)
  80. estrings[i] = NULL;
  81. encoding = pdf_dict_get(ctx, dict, PDF_NAME(Encoding));
  82. if (!encoding)
  83. {
  84. fz_throw(ctx, FZ_ERROR_SYNTAX, "Type3 font missing Encoding");
  85. }
  86. if (pdf_is_name(ctx, encoding))
  87. pdf_load_encoding(estrings, pdf_to_name(ctx, encoding));
  88. if (pdf_is_dict(ctx, encoding))
  89. {
  90. pdf_obj *base, *diff, *item;
  91. base = pdf_dict_get(ctx, encoding, PDF_NAME(BaseEncoding));
  92. if (pdf_is_name(ctx, base))
  93. pdf_load_encoding(estrings, pdf_to_name(ctx, base));
  94. diff = pdf_dict_get(ctx, encoding, PDF_NAME(Differences));
  95. if (pdf_is_array(ctx, diff))
  96. {
  97. n = pdf_array_len(ctx, diff);
  98. k = 0;
  99. for (i = 0; i < n; i++)
  100. {
  101. item = pdf_array_get(ctx, diff, i);
  102. if (pdf_is_int(ctx, item))
  103. k = pdf_to_int(ctx, item);
  104. if (pdf_is_name(ctx, item) && k >= 0 && k < (int)nelem(estrings))
  105. estrings[k++] = pdf_to_name(ctx, item);
  106. }
  107. }
  108. }
  109. fontdesc->encoding = pdf_new_identity_cmap(ctx, 0, 1);
  110. fontdesc->size += pdf_cmap_size(ctx, fontdesc->encoding);
  111. pdf_load_to_unicode(ctx, doc, fontdesc, estrings, NULL, pdf_dict_get(ctx, dict, PDF_NAME(ToUnicode)));
  112. /* Use the glyph index as ASCII when we can't figure out a proper encoding */
  113. if (fontdesc->cid_to_ucs_len == 256)
  114. {
  115. for (i = 32; i < 127; ++i)
  116. if (fontdesc->cid_to_ucs[i] == FZ_REPLACEMENT_CHARACTER)
  117. fontdesc->cid_to_ucs[i] = i;
  118. }
  119. /* Widths */
  120. pdf_set_default_hmtx(ctx, fontdesc, 0);
  121. first = pdf_dict_get_int(ctx, dict, PDF_NAME(FirstChar));
  122. last = pdf_dict_get_int(ctx, dict, PDF_NAME(LastChar));
  123. if (first < 0 || last > 255 || first > last)
  124. first = last = 0;
  125. widths = pdf_dict_get(ctx, dict, PDF_NAME(Widths));
  126. if (!widths)
  127. {
  128. fz_throw(ctx, FZ_ERROR_SYNTAX, "Type3 font missing Widths");
  129. }
  130. for (i = first; i <= last; i++)
  131. {
  132. float w = pdf_array_get_real(ctx, widths, i - first);
  133. w = font->t3matrix.a * w * 1000;
  134. font->t3widths[i] = w * 0.001f;
  135. pdf_add_hmtx(ctx, fontdesc, i, i, w);
  136. }
  137. pdf_end_hmtx(ctx, fontdesc);
  138. /* Resources -- inherit page resources if the font doesn't have its own */
  139. font->t3freeres = pdf_t3_free_resources;
  140. font->t3resources = pdf_dict_get(ctx, dict, PDF_NAME(Resources));
  141. if (!font->t3resources)
  142. font->t3resources = rdb;
  143. if (font->t3resources)
  144. pdf_keep_obj(ctx, font->t3resources);
  145. if (!font->t3resources)
  146. fz_warn(ctx, "no resource dictionary for type 3 font!");
  147. font->t3doc = doc;
  148. font->t3run = pdf_run_glyph_func;
  149. /* CharProcs */
  150. charprocs = pdf_dict_get(ctx, dict, PDF_NAME(CharProcs));
  151. if (!charprocs)
  152. {
  153. fz_throw(ctx, FZ_ERROR_SYNTAX, "Type3 font missing CharProcs");
  154. }
  155. for (i = 0; i < 256; i++)
  156. {
  157. if (estrings[i])
  158. {
  159. obj = pdf_dict_gets(ctx, charprocs, estrings[i]);
  160. if (pdf_is_stream(ctx, obj))
  161. {
  162. font->t3procs[i] = pdf_load_stream(ctx, obj);
  163. fz_trim_buffer(ctx, font->t3procs[i]);
  164. fontdesc->size += fz_buffer_storage(ctx, font->t3procs[i], NULL);
  165. fontdesc->size += 0; // TODO: display list size calculation
  166. }
  167. }
  168. }
  169. }
  170. fz_catch(ctx)
  171. {
  172. pdf_drop_font(ctx, fontdesc);
  173. fz_rethrow(ctx);
  174. }
  175. doc->type3_fonts[doc->num_type3_fonts++] = fz_keep_font(ctx, font);
  176. return fontdesc;
  177. }
  178. void pdf_load_type3_glyphs(fz_context *ctx, pdf_document *doc, pdf_font_desc *fontdesc)
  179. {
  180. int i;
  181. fz_try(ctx)
  182. {
  183. for (i = 0; i < 256; i++)
  184. {
  185. if (fontdesc->font->t3procs[i])
  186. {
  187. fz_prepare_t3_glyph(ctx, fontdesc->font, i);
  188. fontdesc->size += 0; // TODO: display list size calculation
  189. }
  190. }
  191. /* Derive missing font bbox from char bboxes if there are any. */
  192. if (fontdesc->font->flags.invalid_bbox && fontdesc->font->bbox_table != NULL)
  193. {
  194. /* Union all the char bboxes together. */
  195. fz_rect bbox = fz_empty_rect;
  196. for (i = 0; i < 256; i++)
  197. {
  198. if (fontdesc->font->t3procs[i])
  199. bbox = fz_union_rect(bbox, fontdesc->font->bbox_table[0][i]);
  200. }
  201. fontdesc->font->bbox = bbox;
  202. }
  203. }
  204. fz_catch(ctx)
  205. {
  206. fz_rethrow_if(ctx, FZ_ERROR_TRYLATER);
  207. fz_rethrow_if(ctx, FZ_ERROR_SYSTEM);
  208. fz_report_error(ctx);
  209. fz_warn(ctx, "type3 glyph load failed");
  210. }
  211. }