1 | #include "mupdf/fitz.h" |
2 | #include "mupdf/pdf.h" |
3 | |
4 | static void |
5 | 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) |
6 | { |
7 | pdf_run_glyph(ctx, doc, (pdf_obj *)rdb, contents, dev, ctm, gstate, default_cs); |
8 | } |
9 | |
10 | static void |
11 | pdf_t3_free_resources(fz_context *ctx, void *doc, void *rdb_) |
12 | { |
13 | pdf_obj *rdb = (pdf_obj *)rdb_; |
14 | pdf_drop_obj(ctx, rdb); |
15 | } |
16 | |
17 | pdf_font_desc * |
18 | pdf_load_type3_font(fz_context *ctx, pdf_document *doc, pdf_obj *rdb, pdf_obj *dict) |
19 | { |
20 | char buf[256]; |
21 | const char *estrings[256]; |
22 | pdf_font_desc *fontdesc = NULL; |
23 | pdf_obj *encoding; |
24 | pdf_obj *widths; |
25 | pdf_obj *charprocs; |
26 | pdf_obj *obj; |
27 | int first, last; |
28 | int i, k, n; |
29 | fz_rect bbox; |
30 | fz_matrix matrix; |
31 | fz_font *font = NULL; |
32 | |
33 | fz_var(fontdesc); |
34 | |
35 | /* Make a new type3 font entry in the document */ |
36 | if (doc->num_type3_fonts == doc->max_type3_fonts) |
37 | { |
38 | int new_max = doc->max_type3_fonts * 2; |
39 | |
40 | if (new_max == 0) |
41 | new_max = 4; |
42 | doc->type3_fonts = fz_realloc_array(ctx, doc->type3_fonts, new_max, fz_font*); |
43 | doc->max_type3_fonts = new_max; |
44 | } |
45 | |
46 | fz_try(ctx) |
47 | { |
48 | obj = pdf_dict_get(ctx, dict, PDF_NAME(Name)); |
49 | if (pdf_is_name(ctx, obj)) |
50 | fz_strlcpy(buf, pdf_to_name(ctx, obj), sizeof buf); |
51 | else |
52 | fz_strlcpy(buf, "Unnamed-T3" , sizeof buf); |
53 | |
54 | fontdesc = pdf_new_font_desc(ctx); |
55 | |
56 | matrix = pdf_dict_get_matrix(ctx, dict, PDF_NAME(FontMatrix)); |
57 | bbox = pdf_dict_get_rect(ctx, dict, PDF_NAME(FontBBox)); |
58 | bbox = fz_transform_rect(bbox, matrix); |
59 | |
60 | font = fz_new_type3_font(ctx, buf, matrix); |
61 | fontdesc->font = font; |
62 | fontdesc->size += sizeof(fz_font) + 256 * (sizeof(fz_buffer*) + sizeof(float)); |
63 | |
64 | fz_set_font_bbox(ctx, font, bbox.x0, bbox.y0, bbox.x1, bbox.y1); |
65 | |
66 | /* Encoding */ |
67 | |
68 | for (i = 0; i < 256; i++) |
69 | estrings[i] = NULL; |
70 | |
71 | encoding = pdf_dict_get(ctx, dict, PDF_NAME(Encoding)); |
72 | if (!encoding) |
73 | { |
74 | fz_throw(ctx, FZ_ERROR_SYNTAX, "Type3 font missing Encoding" ); |
75 | } |
76 | |
77 | if (pdf_is_name(ctx, encoding)) |
78 | pdf_load_encoding(estrings, pdf_to_name(ctx, encoding)); |
79 | |
80 | if (pdf_is_dict(ctx, encoding)) |
81 | { |
82 | pdf_obj *base, *diff, *item; |
83 | |
84 | base = pdf_dict_get(ctx, encoding, PDF_NAME(BaseEncoding)); |
85 | if (pdf_is_name(ctx, base)) |
86 | pdf_load_encoding(estrings, pdf_to_name(ctx, base)); |
87 | |
88 | diff = pdf_dict_get(ctx, encoding, PDF_NAME(Differences)); |
89 | if (pdf_is_array(ctx, diff)) |
90 | { |
91 | n = pdf_array_len(ctx, diff); |
92 | k = 0; |
93 | for (i = 0; i < n; i++) |
94 | { |
95 | item = pdf_array_get(ctx, diff, i); |
96 | if (pdf_is_int(ctx, item)) |
97 | k = pdf_to_int(ctx, item); |
98 | if (pdf_is_name(ctx, item) && k >= 0 && k < nelem(estrings)) |
99 | estrings[k++] = pdf_to_name(ctx, item); |
100 | } |
101 | } |
102 | } |
103 | |
104 | fontdesc->encoding = pdf_new_identity_cmap(ctx, 0, 1); |
105 | fontdesc->size += pdf_cmap_size(ctx, fontdesc->encoding); |
106 | |
107 | pdf_load_to_unicode(ctx, doc, fontdesc, estrings, NULL, pdf_dict_get(ctx, dict, PDF_NAME(ToUnicode))); |
108 | |
109 | /* Use the glyph index as ASCII when we can't figure out a proper encoding */ |
110 | if (fontdesc->cid_to_ucs_len == 256) |
111 | { |
112 | for (i = 32; i < 127; ++i) |
113 | if (fontdesc->cid_to_ucs[i] == FZ_REPLACEMENT_CHARACTER) |
114 | fontdesc->cid_to_ucs[i] = i; |
115 | } |
116 | |
117 | /* Widths */ |
118 | |
119 | pdf_set_default_hmtx(ctx, fontdesc, 0); |
120 | |
121 | first = pdf_dict_get_int(ctx, dict, PDF_NAME(FirstChar)); |
122 | last = pdf_dict_get_int(ctx, dict, PDF_NAME(LastChar)); |
123 | |
124 | if (first < 0 || last > 255 || first > last) |
125 | first = last = 0; |
126 | |
127 | widths = pdf_dict_get(ctx, dict, PDF_NAME(Widths)); |
128 | if (!widths) |
129 | { |
130 | fz_throw(ctx, FZ_ERROR_SYNTAX, "Type3 font missing Widths" ); |
131 | } |
132 | |
133 | for (i = first; i <= last; i++) |
134 | { |
135 | float w = pdf_array_get_real(ctx, widths, i - first); |
136 | w = font->t3matrix.a * w * 1000; |
137 | font->t3widths[i] = w * 0.001f; |
138 | pdf_add_hmtx(ctx, fontdesc, i, i, w); |
139 | } |
140 | |
141 | pdf_end_hmtx(ctx, fontdesc); |
142 | |
143 | /* Resources -- inherit page resources if the font doesn't have its own */ |
144 | |
145 | font->t3freeres = pdf_t3_free_resources; |
146 | font->t3resources = pdf_dict_get(ctx, dict, PDF_NAME(Resources)); |
147 | if (!font->t3resources) |
148 | font->t3resources = rdb; |
149 | if (font->t3resources) |
150 | pdf_keep_obj(ctx, font->t3resources); |
151 | if (!font->t3resources) |
152 | fz_warn(ctx, "no resource dictionary for type 3 font!" ); |
153 | |
154 | font->t3doc = doc; |
155 | font->t3run = pdf_run_glyph_func; |
156 | |
157 | /* CharProcs */ |
158 | |
159 | charprocs = pdf_dict_get(ctx, dict, PDF_NAME(CharProcs)); |
160 | if (!charprocs) |
161 | { |
162 | fz_throw(ctx, FZ_ERROR_SYNTAX, "Type3 font missing CharProcs" ); |
163 | } |
164 | |
165 | for (i = 0; i < 256; i++) |
166 | { |
167 | if (estrings[i]) |
168 | { |
169 | obj = pdf_dict_gets(ctx, charprocs, estrings[i]); |
170 | if (pdf_is_stream(ctx, obj)) |
171 | { |
172 | font->t3procs[i] = pdf_load_stream(ctx, obj); |
173 | fz_trim_buffer(ctx, font->t3procs[i]); |
174 | fontdesc->size += fz_buffer_storage(ctx, font->t3procs[i], NULL); |
175 | fontdesc->size += 0; // TODO: display list size calculation |
176 | } |
177 | } |
178 | } |
179 | } |
180 | fz_catch(ctx) |
181 | { |
182 | pdf_drop_font(ctx, fontdesc); |
183 | fz_rethrow(ctx); |
184 | } |
185 | |
186 | doc->type3_fonts[doc->num_type3_fonts++] = fz_keep_font(ctx, font); |
187 | |
188 | return fontdesc; |
189 | } |
190 | |
191 | void pdf_load_type3_glyphs(fz_context *ctx, pdf_document *doc, pdf_font_desc *fontdesc) |
192 | { |
193 | int i; |
194 | |
195 | fz_try(ctx) |
196 | { |
197 | for (i = 0; i < 256; i++) |
198 | { |
199 | if (fontdesc->font->t3procs[i]) |
200 | { |
201 | fz_prepare_t3_glyph(ctx, fontdesc->font, i); |
202 | fontdesc->size += 0; // TODO: display list size calculation |
203 | } |
204 | } |
205 | } |
206 | fz_catch(ctx) |
207 | { |
208 | fz_rethrow_if(ctx, FZ_ERROR_TRYLATER); |
209 | fz_warn(ctx, "Type3 glyph load failed: %s" , fz_caught_message(ctx)); |
210 | } |
211 | } |
212 | |