summaryrefslogtreecommitdiff
path: root/source/pdf/pdf-type3.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/pdf/pdf-type3.c')
-rw-r--r--source/pdf/pdf-type3.c190
1 files changed, 190 insertions, 0 deletions
diff --git a/source/pdf/pdf-type3.c b/source/pdf/pdf-type3.c
new file mode 100644
index 00000000..d85d9f11
--- /dev/null
+++ b/source/pdf/pdf-type3.c
@@ -0,0 +1,190 @@
+#include "mupdf/pdf.h"
+
+static void
+pdf_run_glyph_func(void *doc, void *rdb, fz_buffer *contents, fz_device *dev, const fz_matrix *ctm, void *gstate, int nested_depth)
+{
+ pdf_run_glyph(doc, (pdf_obj *)rdb, contents, dev, ctm, gstate, nested_depth);
+}
+
+static void
+pdf_t3_free_resources(void *doc, void *rdb_)
+{
+ pdf_obj *rdb = (pdf_obj *)rdb_;
+ pdf_drop_obj(rdb);
+}
+
+pdf_font_desc *
+pdf_load_type3_font(pdf_document *xref, pdf_obj *rdb, pdf_obj *dict)
+{
+ char buf[256];
+ char *estrings[256];
+ pdf_font_desc *fontdesc = NULL;
+ pdf_obj *encoding;
+ pdf_obj *widths;
+ pdf_obj *charprocs;
+ pdf_obj *obj;
+ int first, last;
+ int i, k, n;
+ fz_rect bbox;
+ fz_matrix matrix;
+ fz_context *ctx = xref->ctx;
+
+ fz_var(fontdesc);
+
+ fz_try(ctx)
+ {
+ obj = pdf_dict_gets(dict, "Name");
+ if (pdf_is_name(obj))
+ fz_strlcpy(buf, pdf_to_name(obj), sizeof buf);
+ else
+ sprintf(buf, "Unnamed-T3");
+
+ fontdesc = pdf_new_font_desc(ctx);
+
+ obj = pdf_dict_gets(dict, "FontMatrix");
+ pdf_to_matrix(ctx, obj, &matrix);
+
+ obj = pdf_dict_gets(dict, "FontBBox");
+ fz_transform_rect(pdf_to_rect(ctx, obj, &bbox), &matrix);
+
+ fontdesc->font = fz_new_type3_font(ctx, buf, &matrix);
+ fontdesc->size += sizeof(fz_font) + 256 * (sizeof(fz_buffer*) + sizeof(float));
+
+ fz_set_font_bbox(ctx, fontdesc->font, bbox.x0, bbox.y0, bbox.x1, bbox.y1);
+
+ /* Encoding */
+
+ for (i = 0; i < 256; i++)
+ estrings[i] = NULL;
+
+ encoding = pdf_dict_gets(dict, "Encoding");
+ if (!encoding)
+ {
+ fz_throw(ctx, FZ_ERROR_GENERIC, "syntaxerror: Type3 font missing Encoding");
+ }
+
+ if (pdf_is_name(encoding))
+ pdf_load_encoding(estrings, pdf_to_name(encoding));
+
+ if (pdf_is_dict(encoding))
+ {
+ pdf_obj *base, *diff, *item;
+
+ base = pdf_dict_gets(encoding, "BaseEncoding");
+ if (pdf_is_name(base))
+ pdf_load_encoding(estrings, pdf_to_name(base));
+
+ diff = pdf_dict_gets(encoding, "Differences");
+ if (pdf_is_array(diff))
+ {
+ n = pdf_array_len(diff);
+ k = 0;
+ for (i = 0; i < n; i++)
+ {
+ item = pdf_array_get(diff, i);
+ if (pdf_is_int(item))
+ k = pdf_to_int(item);
+ if (pdf_is_name(item) && k >= 0 && k < nelem(estrings))
+ estrings[k++] = pdf_to_name(item);
+ }
+ }
+ }
+
+ fontdesc->encoding = pdf_new_identity_cmap(ctx, 0, 1);
+ fontdesc->size += pdf_cmap_size(ctx, fontdesc->encoding);
+
+ pdf_load_to_unicode(xref, fontdesc, estrings, NULL, pdf_dict_gets(dict, "ToUnicode"));
+
+ /* Widths */
+
+ pdf_set_default_hmtx(ctx, fontdesc, 0);
+
+ first = pdf_to_int(pdf_dict_gets(dict, "FirstChar"));
+ last = pdf_to_int(pdf_dict_gets(dict, "LastChar"));
+
+ if (first < 0 || last > 255 || first > last)
+ first = last = 0;
+
+ widths = pdf_dict_gets(dict, "Widths");
+ if (!widths)
+ {
+ fz_throw(ctx, FZ_ERROR_GENERIC, "syntaxerror: Type3 font missing Widths");
+ }
+
+ for (i = first; i <= last; i++)
+ {
+ float w = pdf_to_real(pdf_array_get(widths, i - first));
+ w = fontdesc->font->t3matrix.a * w * 1000;
+ fontdesc->font->t3widths[i] = w * 0.001f;
+ pdf_add_hmtx(ctx, fontdesc, i, i, w);
+ }
+
+ pdf_end_hmtx(ctx, fontdesc);
+
+ /* Resources -- inherit page resources if the font doesn't have its own */
+
+ fontdesc->font->t3freeres = pdf_t3_free_resources;
+ fontdesc->font->t3resources = pdf_dict_gets(dict, "Resources");
+ if (!fontdesc->font->t3resources)
+ fontdesc->font->t3resources = rdb;
+ if (fontdesc->font->t3resources)
+ pdf_keep_obj(fontdesc->font->t3resources);
+ if (!fontdesc->font->t3resources)
+ fz_warn(ctx, "no resource dictionary for type 3 font!");
+
+ fontdesc->font->t3doc = xref;
+ fontdesc->font->t3run = pdf_run_glyph_func;
+
+ /* CharProcs */
+
+ charprocs = pdf_dict_gets(dict, "CharProcs");
+ if (!charprocs)
+ {
+ fz_throw(ctx, FZ_ERROR_GENERIC, "syntaxerror: Type3 font missing CharProcs");
+ }
+
+ for (i = 0; i < 256; i++)
+ {
+ if (estrings[i])
+ {
+ obj = pdf_dict_gets(charprocs, estrings[i]);
+ if (pdf_is_stream(xref, pdf_to_num(obj), pdf_to_gen(obj)))
+ {
+ fontdesc->font->t3procs[i] = pdf_load_stream(xref, pdf_to_num(obj), pdf_to_gen(obj));
+ fontdesc->size += fontdesc->font->t3procs[i]->cap;
+ fontdesc->size += 0; // TODO: display list size calculation
+ }
+ }
+ }
+ }
+ fz_catch(ctx)
+ {
+ if (fontdesc)
+ pdf_drop_font(ctx, fontdesc);
+ fz_rethrow_message(ctx, "cannot load type3 font (%d %d R)", pdf_to_num(dict), pdf_to_gen(dict));
+ }
+ return fontdesc;
+}
+
+void pdf_load_type3_glyphs(pdf_document *xref, pdf_font_desc *fontdesc, int nested_depth)
+{
+ int i;
+ fz_context *ctx = xref->ctx;
+
+ fz_try(ctx)
+ {
+ for (i = 0; i < 256; i++)
+ {
+ if (fontdesc->font->t3procs[i])
+ {
+ fz_prepare_t3_glyph(ctx, fontdesc->font, i, nested_depth);
+ fontdesc->size += 0; // TODO: display list size calculation
+ }
+ }
+ }
+ fz_catch(ctx)
+ {
+ /* FIXME: TryLater */
+ fz_warn(ctx, "Type3 glyph load failed: %s", fz_caught_message(ctx));
+ }
+}