1 #include "mupdf/fitz.h"
2 #include "mupdf/pdf.h"
3 
4 static void
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)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
pdf_t3_free_resources(fz_context * ctx,void * doc,void * rdb_)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 *
pdf_load_type3_font(fz_context * ctx,pdf_document * doc,pdf_obj * rdb,pdf_obj * dict)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 < (int)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 
pdf_load_type3_glyphs(fz_context * ctx,pdf_document * doc,pdf_font_desc * fontdesc)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