summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Jamfile1
-rw-r--r--include/fitz/font.h2
-rw-r--r--include/fitz/math.h15
-rw-r--r--include/mupdf/content.h2
-rw-r--r--include/mupdf/rsrc.h17
-rw-r--r--mupdf/font.c57
-rw-r--r--mupdf/fontenc.h30
-rw-r--r--mupdf/fontfile.c2
-rw-r--r--mupdf/image.c44
-rw-r--r--mupdf/interpret.c31
-rw-r--r--mupdf/page.c2
-rw-r--r--mupdf/type3.c346
-rw-r--r--render/glyphcache.c8
-rw-r--r--render/render.c16
-rw-r--r--render/renderimage.c71
-rw-r--r--render/rendertext.c16
16 files changed, 523 insertions, 137 deletions
diff --git a/Jamfile b/Jamfile
index eb4038e0..24aa952a 100644
--- a/Jamfile
+++ b/Jamfile
@@ -109,6 +109,7 @@ Library libmupdf :
mupdf/cmap.c
mupdf/font.c
mupdf/fontfile.c
+ mupdf/type3.c
mupdf/colorspace.c
mupdf/image.c
mupdf/xobject.c
diff --git a/include/fitz/font.h b/include/fitz/font.h
index 4d9fb5e8..9fd9218b 100644
--- a/include/fitz/font.h
+++ b/include/fitz/font.h
@@ -8,7 +8,7 @@ struct fz_hmtx_s
{
unsigned short lo;
unsigned short hi;
- short w;
+ int w; /* type3 fonts can be big! */
};
struct fz_vmtx_s
diff --git a/include/fitz/math.h b/include/fitz/math.h
index bcbfee00..bfc1f8e6 100644
--- a/include/fitz/math.h
+++ b/include/fitz/math.h
@@ -4,6 +4,21 @@ static inline unsigned char fz_mul255(unsigned char a, unsigned char b)
return ((a + 1) * b) >> 8;
}
+/* floor / ceil towards/from +/- inf */
+static inline float fz_floor(float x)
+{
+ if (x > 0)
+ return floor(x);
+ return ceil(x);
+}
+
+static inline float fz_ceil(float x)
+{
+ if (x > 0)
+ return ceil(x);
+ return floor(x);
+}
+
/* divide and floor towards -inf */
static inline int fz_idiv(int a, int b)
{
diff --git a/include/mupdf/content.h b/include/mupdf/content.h
index 3f85fe06..96b31f8e 100644
--- a/include/mupdf/content.h
+++ b/include/mupdf/content.h
@@ -99,7 +99,7 @@ fz_error *pdf_flushtext(pdf_csi*);
fz_error *pdf_showimage(pdf_csi*, pdf_image *img);
/* interpret.c */
-fz_error *pdf_newcsi(pdf_csi **csip);
+fz_error *pdf_newcsi(pdf_csi **csip, int maskonly);
fz_error *pdf_runcsi(pdf_csi *, pdf_xref *xref, fz_obj *rdb, fz_file *);
void pdf_dropcsi(pdf_csi *csi);
diff --git a/include/mupdf/rsrc.h b/include/mupdf/rsrc.h
index 9dc12acd..896e4335 100644
--- a/include/mupdf/rsrc.h
+++ b/include/mupdf/rsrc.h
@@ -17,7 +17,6 @@ void *pdf_findresource(pdf_rsrc *list, fz_obj *ref);
* Functions
*/
-
typedef struct pdf_function_s pdf_function;
fz_error *pdf_loadfunction(pdf_function **func, pdf_xref *xref, fz_obj *obj);
@@ -91,9 +90,6 @@ struct pdf_font_s
{
fz_font super;
- void *ftface;
- int substitute;
-
/* FontDescriptor */
int flags;
float italicangle;
@@ -108,18 +104,16 @@ struct pdf_font_s
int ncidtogid;
unsigned short *cidtogid;
- /* Raw data for freetype */
+ /* Freetype */
+ int substitute;
+ void *ftface;
char *filename;
fz_buffer *fontdata;
-};
-struct pdf_type3_s
-{
+ /* Type3 data */
fz_rect bbox;
fz_matrix matrix;
- int widths[256];
fz_tree *charprocs[256];
- int tounicode[256];
};
/* cmap.c */
@@ -134,6 +128,9 @@ fz_error *pdf_loadembeddedfont(pdf_font *font, pdf_xref *xref, fz_obj *stmref);
fz_error *pdf_loadsystemfont(pdf_font *font, char *basefont, char *collection);
fz_error *pdf_loadsubstitutefont(pdf_font *font, int fdflags, char *collection);
+/* type3.c */
+fz_error *pdf_loadtype3font(pdf_font **fontp, pdf_xref *xref, fz_obj *font);
+
/* font.c */
fz_error *pdf_loadfontdescriptor(pdf_font *font, pdf_xref *xref, fz_obj *desc, char *collection);
fz_error *pdf_loadfont(pdf_font **fontp, pdf_xref *xref, fz_obj *font);
diff --git a/mupdf/font.c b/mupdf/font.c
index 1ab2ea5f..8d3b70b1 100644
--- a/mupdf/font.c
+++ b/mupdf/font.c
@@ -13,24 +13,42 @@
#include "fontenc.h"
#include "fontagl.h"
+static char *basefontnames[14][7] =
+{
+ { "Courier", "CourierNew", "CourierNewPSMT", 0 },
+ { "Courier-Bold", "CourierNew,Bold", "Courier,Bold",
+ "CourierNewPS-BoldMT", "CourierNew-Bold", 0 },
+ { "Courier-Oblique", "CourierNew,Italic", "Courier,Italic",
+ "CourierNewPS-ItalicMT", "CourierNew-Italic", 0 },
+ { "Courier-BoldOblique", "CourierNew,BoldItalic", "Courier,BoldItalic",
+ "CourierNewPS-BoldItalicMT", "CourierNew-BoldItalic", 0 },
+ { "Helvetica", "ArialMT", "Arial", 0 },
+ { "Helvetica-Bold", "Arial-BoldMT", "Arial,Bold", "Arial-Bold",
+ "Helvetica,Bold", 0 },
+ { "Helvetica-Oblique", "Arial-ItalicMT", "Arial,Italic", "Arial-Italic",
+ "Helvetica,Italic", "Helvetica-Italic", 0 },
+ { "Helvetica-BoldOblique", "Arial-BoldItalicMT",
+ "Arial,BoldItalic", "Arial-BoldItalic",
+ "Helvetica,BoldItalic", "Helvetica-BoldItalic", 0 },
+ { "Times-Roman", "TimesNewRomanPSMT", "TimesNewRoman",
+ "TimesNewRomanPS", 0 },
+ { "Times-Bold", "TimesNewRomanPS-BoldMT", "TimesNewRoman,Bold",
+ "TimesNewRomanPS-Bold", "TimesNewRoman-Bold", 0 },
+ { "Times-Italic", "TimesNewRomanPS-ItalicMT", "TimesNewRoman,Italic",
+ "TimesNewRomanPS-Italic", "TimesNewRoman-Italic", 0 },
+ { "Times-BoldItalic", "TimesNewRomanPS-BoldItalicMT",
+ "TimesNewRoman,BoldItalic", "TimesNewRomanPS-BoldItalic",
+ "TimesNewRoman-BoldItalic", 0 },
+ { "Symbol", 0 },
+ { "ZapfDingbats", 0 }
+};
+
/*
* FreeType and Rendering glue
*/
enum { UNKNOWN, TYPE1, CFF, TRUETYPE, CID };
-enum
-{
- FD_FIXED = 1 << 0,
- FD_SERIF = 1 << 1,
- FD_SYMBOLIC = 1 << 2,
- FD_SCRIPT = 1 << 3,
- FD_NONSYMBOLIC = 1 << 5,
- FD_ITALIC = 1 << 6,
- FD_ALLCAP = 1 << 16,
- FD_SMALLCAP = 1 << 17,
-};
-
static int ftkind(FT_Face face)
{
const char *kind = face->driver->clazz->root.module_name;
@@ -210,10 +228,11 @@ static void ftdropfont(fz_font *font)
// XXX free freetype face
}
-static pdf_font *
-newfont(char *name)
+pdf_font *
+pdf_newfont(char *name)
{
pdf_font *font;
+ int i;
font = fz_malloc(sizeof (pdf_font));
if (!font)
@@ -241,6 +260,9 @@ newfont(char *name)
font->filename = nil;
font->fontdata = nil;
+ for (i = 0; i < 256; i++)
+ font->charprocs[i] = nil;
+
return font;
}
@@ -275,7 +297,7 @@ loadsimplefont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict)
printf("loading simple font %s\n", basefont);
- font = *fontp = newfont(basefont);
+ font = *fontp = pdf_newfont(basefont);
if (!font)
return fz_outofmem;
@@ -364,7 +386,6 @@ printf("loading simple font %s\n", basefont);
if (fz_isname(base))
loadencoding(estrings, fz_toname(base));
-
diff = fz_dictgets(encoding, "Differences");
if (fz_isarray(diff))
{
@@ -578,7 +599,7 @@ printf(" collection %s\n", collection);
* Load font file
*/
- font = *fontp = newfont(basefont);
+ font = *fontp = pdf_newfont(basefont);
if (!font)
return fz_outofmem;
@@ -902,6 +923,8 @@ pdf_loadfont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict)
return loadsimplefont(fontp, xref, dict);
else if (!strcmp(subtype, "TrueType"))
return loadsimplefont(fontp, xref, dict);
+ else if (!strcmp(subtype, "Type3"))
+ return pdf_loadtype3font(fontp, xref, dict);
else
return fz_throw("unimplemented: %s fonts", subtype);
}
diff --git a/mupdf/fontenc.h b/mupdf/fontenc.h
index 376a3f2d..d64e3e49 100644
--- a/mupdf/fontenc.h
+++ b/mupdf/fontenc.h
@@ -4,36 +4,6 @@
#define _notdef 0
-static char *basefontnames[14][7] =
-{
- { "Courier", "CourierNew", "CourierNewPSMT", 0 },
- { "Courier-Bold", "CourierNew,Bold", "Courier,Bold",
- "CourierNewPS-BoldMT", "CourierNew-Bold", 0 },
- { "Courier-Oblique", "CourierNew,Italic", "Courier,Italic",
- "CourierNewPS-ItalicMT", "CourierNew-Italic", 0 },
- { "Courier-BoldOblique", "CourierNew,BoldItalic", "Courier,BoldItalic",
- "CourierNewPS-BoldItalicMT", "CourierNew-BoldItalic", 0 },
- { "Helvetica", "ArialMT", "Arial", 0 },
- { "Helvetica-Bold", "Arial-BoldMT", "Arial,Bold", "Arial-Bold",
- "Helvetica,Bold", 0 },
- { "Helvetica-Oblique", "Arial-ItalicMT", "Arial,Italic", "Arial-Italic",
- "Helvetica,Italic", "Helvetica-Italic", 0 },
- { "Helvetica-BoldOblique", "Arial-BoldItalicMT",
- "Arial,BoldItalic", "Arial-BoldItalic",
- "Helvetica,BoldItalic", "Helvetica-BoldItalic", 0 },
- { "Times-Roman", "TimesNewRomanPSMT", "TimesNewRoman",
- "TimesNewRomanPS", 0 },
- { "Times-Bold", "TimesNewRomanPS-BoldMT", "TimesNewRoman,Bold",
- "TimesNewRomanPS-Bold", "TimesNewRoman-Bold", 0 },
- { "Times-Italic", "TimesNewRomanPS-ItalicMT", "TimesNewRoman,Italic",
- "TimesNewRomanPS-Italic", "TimesNewRoman-Italic", 0 },
- { "Times-BoldItalic", "TimesNewRomanPS-BoldItalicMT",
- "TimesNewRoman,BoldItalic", "TimesNewRomanPS-BoldItalic",
- "TimesNewRoman-BoldItalic", 0 },
- { "Symbol", 0 },
- { "ZapfDingbats", 0 }
-};
-
static char *macroman[256] = { _notdef, _notdef,
_notdef, _notdef, _notdef, _notdef, _notdef, _notdef,
_notdef, _notdef, _notdef, _notdef, _notdef, _notdef,
diff --git a/mupdf/fontfile.c b/mupdf/fontfile.c
index a7ea31d3..e1997f7e 100644
--- a/mupdf/fontfile.c
+++ b/mupdf/fontfile.c
@@ -237,6 +237,8 @@ printf(" find cid font %s (%d)\n", collection, isserif);
}
}
+printf(" loading substitute font %s\n", name);
+
return pdf_loadbuiltinfont(font, name);
}
diff --git a/mupdf/image.c b/mupdf/image.c
index 044307eb..bcffda71 100644
--- a/mupdf/image.c
+++ b/mupdf/image.c
@@ -205,6 +205,7 @@ pdf_loadinlineimage(pdf_image **imgp, pdf_xref *xref, fz_obj *dict, fz_file *fil
fz_error *error;
pdf_image *img;
fz_filter *filter;
+ fz_obj *f;
fz_obj *cs;
fz_obj *d;
int ismask;
@@ -221,6 +222,7 @@ printf("inline image ");fz_debugobj(dict);printf("\n");
img->super.n = 0;
img->super.a = 0;
img->indexed = nil;
+ img->mask = nil;
img->super.w = fz_toint(fz_dictgetsa(dict, "Width", "W"));
img->super.h = fz_toint(fz_dictgetsa(dict, "Height", "H"));
@@ -277,19 +279,41 @@ printf(" decode array!\n");
img->stride = (img->super.w * (img->super.n + img->super.a) * img->bpc + 7) / 8;
/* load image data */
- error = pdf_decodefilter(&filter, dict);
- if (error)
- return error;
- error = fz_pushfilter(file, filter);
- if (error)
- return error;
+ f = fz_dictgetsa(dict, "Filter", "F");
+ if (f)
+ {
+ error = pdf_decodefilter(&filter, dict);
+ if (error)
+ return error;
- error = fz_readfile(&img->samples, file);
- if (error)
- return error;
+ error = fz_pushfilter(file, filter);
+ if (error)
+ return error;
+
+ error = fz_readfile(&img->samples, file);
+ if (error)
+ return error;
+
+ fz_popfilter(file);
+ }
+ else
+ {
+ error = fz_newbuffer(&img->samples, img->super.h * img->stride);
+ if (error)
+ return error;
- fz_popfilter(file);
+printf(" nullfilter %d\n", img->super.h * img->stride);
+
+ i = fz_read(file, img->samples->bp, img->super.h * img->stride);
+ error = fz_ferror(file);
+ if (error)
+ return error;
+
+printf(" read %d\n", i);
+
+ img->samples->wp += img->super.h * img->stride;
+ }
/* 0 means opaque and 1 means transparent, so we invert to get alpha */
if (ismask)
diff --git a/mupdf/interpret.c b/mupdf/interpret.c
index dfe7d36d..4fb10443 100644
--- a/mupdf/interpret.c
+++ b/mupdf/interpret.c
@@ -2,7 +2,7 @@
#include <mupdf.h>
fz_error *
-pdf_newcsi(pdf_csi **csip)
+pdf_newcsi(pdf_csi **csip, int maskonly)
{
fz_error *error;
pdf_csi *csi;
@@ -37,8 +37,16 @@ pdf_newcsi(pdf_csi **csip)
csi->tree->root = node;
csi->gstate[0].head = node;
- error = fz_newcolornode(&node, pdf_devicegray, 1, &white);
- fz_insertnode(csi->tree->root, node);
+ if (maskonly)
+ {
+ csi->gstate[0].fill.kind = PDF_MNONE;
+ csi->gstate[0].stroke.kind = PDF_MNONE;
+ }
+ else
+ {
+ error = fz_newcolornode(&node, pdf_devicegray, 1, &white);
+ fz_insertnode(csi->tree->root, node);
+ }
csi->clip = nil;
@@ -463,7 +471,7 @@ Lsetcolorspace:
for (i = 0; i < csi->top; i++)
v[i] = fz_toreal(csi->stack[i]);
- error = pdf_setcolor(csi, PDF_MFILL, v);
+ error = pdf_setcolor(csi, PDF_MSTROKE, v);
if (error) return error;
}
@@ -687,6 +695,16 @@ fz_debugobj(rdb);
}
}
+ else if (!strcmp(buf, "d0"))
+ {
+ fz_warn("unimplemented: d0 charprocs");
+ }
+
+ else if (!strcmp(buf, "d1"))
+ {
+printf("%g %g d0\n", fz_toreal(csi->stack[0]), fz_toreal(csi->stack[1]));
+ }
+
else
fprintf(stderr, "syntaxerror: unknown keyword '%s'\n", buf);
//return fz_throw("syntaxerror: unknown keyword '%s'", buf);
@@ -1036,9 +1054,14 @@ pdf_runcsi(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, fz_file *file)
if (!strcmp(buf, "BI"))
{
fz_obj *obj;
+
error = pdf_parsedict(&obj, file, buf, sizeof buf);
if (error)
return error;
+
+ /* read whitespace after ID keyword */
+ fz_readbyte(file);
+
error = runinlineimage(csi, xref, file, obj);
fz_dropobj(obj);
if (error)
diff --git a/mupdf/page.c b/mupdf/page.c
index 79fc6fd0..11ab6727 100644
--- a/mupdf/page.c
+++ b/mupdf/page.c
@@ -25,7 +25,7 @@ loadpagecontents(fz_tree **treep, pdf_xref *xref, fz_obj *rdb, fz_obj *ref)
pdf_csi *csi;
int i;
- error = pdf_newcsi(&csi);
+ error = pdf_newcsi(&csi, 0);
if (error)
return error;
diff --git a/mupdf/type3.c b/mupdf/type3.c
new file mode 100644
index 00000000..edc205cf
--- /dev/null
+++ b/mupdf/type3.c
@@ -0,0 +1,346 @@
+#include <fitz.h>
+#include <mupdf.h>
+
+extern pdf_font *pdf_newfont(char *name);
+
+/* TODO: factor out loadencoding which is common with simple fonts */
+
+#include "fontenc.h"
+
+static void loadencoding(char **estrings, char *encoding)
+{
+ char **bstrings = nil;
+ int i;
+
+ if (!strcmp(encoding, "MacRomanEncoding"))
+ bstrings = macroman;
+ if (!strcmp(encoding, "MacExpertEncoding"))
+ bstrings = macexpert;
+ if (!strcmp(encoding, "WinAnsiEncoding"))
+ bstrings = winansi;
+
+ if (bstrings)
+ for (i = 0; i < 256; i++)
+ estrings[i] = bstrings[i];
+}
+
+static void
+t3dropfont(fz_font *font)
+{
+ int i;
+ pdf_font *pfont = (pdf_font*)font;
+ if (pfont->encoding)
+ fz_dropcmap(pfont->encoding);
+ for (i = 0; i < 256; i++)
+ if (pfont->charprocs[i])
+ fz_droptree(pfont->charprocs[i]);
+}
+
+static fz_error *
+t3render(fz_glyph *glyph, fz_font *fzfont, int cid, fz_matrix trm)
+{
+ pdf_font *font = (pdf_font*)fzfont;
+ fz_error *error;
+ fz_renderer *gc;
+ fz_tree *tree;
+ fz_pixmap *pixmap;
+ fz_matrix ctm;
+ fz_rect bbox;
+ int i;
+
+ if (cid < 0 || cid > 255)
+ return fz_throw("rangecheck: glyph out of range");
+
+ tree = font->charprocs[cid];
+ if (!tree)
+ {
+ glyph->w = 0;
+ glyph->h = 0;
+ return nil;
+ }
+
+ ctm = fz_concat(font->matrix, trm);
+ bbox = fz_boundtree(tree, ctm);
+
+printf("glyph bbox %g %g %g %g\n",
+ bbox.min.x,
+ bbox.min.y,
+ bbox.max.x,
+ bbox.max.y);
+
+ bbox.min.x = fz_floor(bbox.min.x - 5.5);
+ bbox.min.y = fz_floor(bbox.min.y - 5.5);
+ bbox.max.x = fz_ceil(bbox.max.x + 5.5);
+ bbox.max.y = fz_ceil(bbox.max.y + 5.5);
+
+printf("glyph bbox %g %g %g %g\n",
+ bbox.min.x,
+ bbox.min.y,
+ bbox.max.x,
+ bbox.max.y);
+
+ error = fz_newrenderer(&gc, nil);
+ if (error)
+ return error;
+ error = fz_rendertree(&pixmap, gc, tree, ctm, bbox);
+ fz_droprenderer(gc);
+ if (error)
+ return error;
+
+ assert(pixmap->n == 1);
+
+printf("pixmap %d %d\n", pixmap->x, pixmap->y);
+
+ glyph->lsb = pixmap->x;
+ glyph->top = pixmap->h + pixmap->y;
+ glyph->w = pixmap->w;
+ glyph->h = pixmap->h;
+ glyph->bitmap = pixmap->samples;
+
+ unsigned char tmp[pixmap->w * pixmap->h];
+ memcpy(tmp, pixmap->samples, pixmap->w * pixmap->h);
+
+ for (i = 0; i < pixmap->h; i++)
+ {
+ memcpy( pixmap->samples + i * pixmap->w,
+ tmp + (pixmap->h - i - 1) * pixmap->w,
+ pixmap->w );
+ }
+
+ // XXX flip bitmap in ftrender instead; free pixmap
+
+ return nil;
+}
+
+static fz_error *
+loadcharproc(fz_tree **treep, pdf_xref *xref, fz_obj *rdb, fz_obj *stmref)
+{
+ fz_error *error;
+ pdf_csi *csi;
+
+ printf(" loading charproc %d %d obj\n",
+ fz_tonum(stmref), fz_togen(stmref));
+
+ error = pdf_newcsi(&csi, 1);
+
+ error = pdf_openstream(xref, fz_tonum(stmref), fz_togen(stmref));
+ if (error)
+ return error;
+
+ error = pdf_runcsi(csi, xref, rdb, xref->stream);
+
+ pdf_closestream(xref);
+
+ if (csi->tree)
+ fz_debugtree(csi->tree);
+
+ *treep = csi->tree;
+ csi->tree = nil;
+
+ pdf_dropcsi(csi);
+
+ return error;
+}
+
+fz_error *
+pdf_loadtype3font(pdf_font **fontp, pdf_xref *xref, fz_obj *dict)
+{
+ fz_error *error;
+ char buf[256];
+ char *estrings[256];
+ pdf_font *font;
+ fz_obj *encoding;
+ fz_obj *widths;
+ fz_obj *resources;
+ fz_obj *charprocs;
+ fz_obj *obj;
+ int first, last;
+ int i, k, n;
+
+ obj = fz_dictgets(dict, "Name");
+ if (obj)
+ strlcpy(buf, fz_toname(obj), sizeof buf);
+ else
+ sprintf(buf, "Unnamed-T3");
+
+printf("loading type3 font %s\n", buf);
+
+ font = pdf_newfont(buf);
+ if (!font)
+ return fz_outofmem;
+
+ font->super.render = t3render;
+ font->super.drop = (void(*)(fz_font*)) t3dropfont;
+
+ obj = fz_dictgets(dict, "FontMatrix");
+ font->matrix.a = fz_toreal(fz_arrayget(obj, 0));
+ font->matrix.b = fz_toreal(fz_arrayget(obj, 1));
+ font->matrix.c = fz_toreal(fz_arrayget(obj, 2));
+ font->matrix.d = fz_toreal(fz_arrayget(obj, 3));
+ font->matrix.e = fz_toreal(fz_arrayget(obj, 4));
+ font->matrix.f = fz_toreal(fz_arrayget(obj, 5));
+
+printf(" matrix [%g %g %g %g %g %g]\n",
+ font->matrix.a, font->matrix.b,
+ font->matrix.c, font->matrix.d,
+ font->matrix.e, font->matrix.f);
+
+ /* TODO: scale bbox by fontmatrix * 1000 */
+ obj = fz_dictgets(dict, "FontBBox");
+ fz_setfontbbox((fz_font*)font,
+ fz_toreal(fz_arrayget(obj, 0)),
+ fz_toreal(fz_arrayget(obj, 1)),
+ fz_toreal(fz_arrayget(obj, 2)),
+ fz_toreal(fz_arrayget(obj, 3)));
+
+ /*
+ * Encoding
+ */
+
+ for (i = 0; i < 256; i++)
+ estrings[i] = nil;
+
+ encoding = fz_dictgets(dict, "Encoding");
+ if (!encoding) {
+ error = fz_throw("syntaxerror: Type3 font missing Encoding");
+ goto cleanup;
+ }
+
+ error = pdf_resolve(&encoding, xref);
+ if (error)
+ goto cleanup;
+
+ if (fz_isname(obj))
+ loadencoding(estrings, fz_toname(encoding));
+
+ if (fz_isdict(encoding))
+ {
+ fz_obj *base, *diff, *item;
+
+ base = fz_dictgets(encoding, "BaseEncoding");
+ if (fz_isname(base))
+ loadencoding(estrings, fz_toname(base));
+
+ diff = fz_dictgets(encoding, "Differences");
+ if (fz_isarray(diff))
+ {
+ n = fz_arraylen(diff);
+ k = 0;
+ for (i = 0; i < n; i++)
+ {
+ item = fz_arrayget(diff, i);
+ if (fz_isint(item))
+ k = fz_toint(item);
+ if (fz_isname(item))
+ estrings[k++] = fz_toname(item);
+ if (k < 0) k = 0;
+ if (k > 255) k = 255;
+ }
+ }
+ }
+
+ fz_dropobj(encoding);
+
+ error = pdf_makeidentitycmap(&font->encoding, 0, 1);
+ if (error)
+ goto cleanup;
+
+ /*
+ * Widths
+ */
+
+ fz_setdefaulthmtx((fz_font*)font, 0);
+
+ first = fz_toint(fz_dictgets(dict, "FirstChar"));
+ last = fz_toint(fz_dictgets(dict, "LastChar"));
+
+ widths = fz_dictgets(dict, "Widths");
+ if (!widths) {
+ error = fz_throw("syntaxerror: Type3 font missing Widths");
+ goto cleanup;
+ }
+
+ error = pdf_resolve(&widths, xref);
+ if (error)
+ goto cleanup;
+
+ for (i = first; i <= last; i++)
+ {
+ float w = fz_toreal(fz_arrayget(widths, i - first));
+ w = font->matrix.a * w * 1000.0;
+ error = fz_addhmtx((fz_font*)font, i, i, w);
+ if (error) {
+ fz_dropobj(widths);
+ goto cleanup;
+ }
+ }
+
+ fz_dropobj(widths);
+
+ error = fz_endhmtx((fz_font*)font);
+ if (error)
+ goto cleanup;
+
+ /*
+ * Resources
+ */
+
+ obj = fz_dictgets(dict, "Resources");
+ if (!obj) {
+ error = fz_throw("syntaxerror: Type3 font missing Resources");
+ goto cleanup;
+ }
+
+ error = pdf_resolve(&obj, xref);
+ if (error)
+ goto cleanup;
+
+ error = pdf_loadresources(&resources, xref, obj);
+
+ fz_dropobj(obj);
+
+ if (error)
+ goto cleanup;
+
+ /*
+ * CharProcs
+ */
+
+ charprocs = fz_dictgets(dict, "CharProcs");
+ if (!charprocs)
+ {
+ error = fz_throw("syntaxerror: Type3 font missing CharProcs");
+ goto cleanup2;
+ }
+
+ error = pdf_resolve(&charprocs, xref);
+ if (error)
+ goto cleanup2;
+
+ for (i = 0; i < 256; i++)
+ {
+ if (estrings[i])
+ {
+ obj = fz_dictgets(charprocs, estrings[i]);
+ if (obj)
+ {
+ error = loadcharproc(&font->charprocs[i], xref, resources, obj);
+ if (error)
+ goto cleanup2;
+ }
+ }
+ }
+
+ fz_dropobj(charprocs);
+ fz_dropobj(resources);
+
+ *fontp = font;
+ return nil;
+
+cleanup2:
+ fz_dropobj(resources);
+cleanup:
+ fz_dropfont((fz_font*)font);
+ return error;
+}
+
diff --git a/render/glyphcache.c b/render/glyphcache.c
index e92b472e..ec77e857 100644
--- a/render/glyphcache.c
+++ b/render/glyphcache.c
@@ -310,8 +310,8 @@ fz_renderglyph(fz_glyphcache *arena, fz_glyph *glyph, fz_font *font, int cid, fz
key.b = ctm.b * 65536;
key.c = ctm.c * 65536;
key.d = ctm.d * 65536;
- key.e = (ctm.e - floor(ctm.e)) * HSUBPIX;
- key.f = (ctm.f - floor(ctm.f)) * VSUBPIX;
+ key.e = (ctm.e - fz_floor(ctm.e)) * HSUBPIX;
+ key.f = (ctm.f - fz_floor(ctm.f)) * VSUBPIX;
val = hashfind(arena, &key);
if (val)
@@ -328,8 +328,8 @@ fz_renderglyph(fz_glyphcache *arena, fz_glyph *glyph, fz_font *font, int cid, fz
return nil;
}
- ctm.e = floor(ctm.e) + key.e / HSUBPIX;
- ctm.f = floor(ctm.f) + key.f / HSUBPIX;
+ ctm.e = fz_floor(ctm.e) + key.e / HSUBPIX;
+ ctm.f = fz_floor(ctm.f) + key.f / HSUBPIX;
error = font->render(glyph, font, cid, ctm);
if (error)
diff --git a/render/render.c b/render/render.c
index fd3e0620..dd4b543d 100644
--- a/render/render.c
+++ b/render/render.c
@@ -77,6 +77,8 @@ fz_rendercolor(fz_renderer *gc, fz_colornode *color, fz_matrix ctm)
printf("render color\n");
+ assert(gc->model);
+
fz_convertcolor(color->cs, color->samples, gc->model, rgb);
gc->r = rgb[0] * 255;
gc->g = rgb[1] * 255;
@@ -146,7 +148,7 @@ fz_renderover(fz_renderer *gc, fz_overnode *over, fz_matrix ctm)
{
printf("begin over accumulator\n");
oldacc = gc->acc;
- error = fz_newpixmap(&gc->acc, gc->x, gc->y, gc->w, gc->h, 4);
+ error = fz_newpixmap(&gc->acc, gc->x, gc->y, gc->w, gc->h, gc->model ? 4 : 1);
if (error)
return error;
fz_clearpixmap(gc->acc);
@@ -285,14 +287,14 @@ fz_rendertree(fz_pixmap **outp, fz_renderer *gc, fz_tree *tree, fz_matrix ctm, f
{
fz_error *error;
- gc->x = floor(bbox.min.x);
- gc->y = floor(bbox.min.y);
- gc->w = ceil(bbox.max.x) - floor(bbox.min.x);
- gc->h = ceil(bbox.max.y) - floor(bbox.min.y);
+ gc->x = fz_floor(bbox.min.x);
+ gc->y = fz_floor(bbox.min.y);
+ gc->w = fz_ceil(bbox.max.x) - fz_floor(bbox.min.x);
+ gc->h = fz_ceil(bbox.max.y) - fz_floor(bbox.min.y);
/* compensate for rounding */
- ctm.e -= bbox.min.x - floor(bbox.min.x);
- ctm.f -= bbox.min.y - floor(bbox.min.y);
+ ctm.e -= bbox.min.x - gc->x;
+ ctm.f -= bbox.min.y - gc->y;
printf("render tree\n");
diff --git a/render/renderimage.c b/render/renderimage.c
index 73b45e0c..e2c98eb1 100644
--- a/render/renderimage.c
+++ b/render/renderimage.c
@@ -9,10 +9,10 @@ void fz_gammapixmap(fz_pixmap *pix, float gamma);
static inline int getcomp(fz_pixmap *pix, int u, int v, int k)
{
-// if (u < 0 || u >= pix->w)
-// return 0;
-// if (v < 0 || v >= pix->h)
-// return 0;
+ if (u < 0 || u >= pix->w)
+ return 0;
+ if (v < 0 || v >= pix->h)
+ return 0;
u = CLAMP(u, 0, pix->w - 1);
v = CLAMP(v, 0, pix->h - 1);
return pix->samples[ (v * pix->w + u) * pix->n + k ];
@@ -38,18 +38,21 @@ static inline int sampleimage(fz_pixmap *pix, int u, int v, int k)
static inline void
drawscan(fz_matrix *invmat, fz_pixmap *dst, fz_pixmap *src, int y, int x0, int x1)
{
- int x, k;
+ unsigned char *d;
+ int k, n;
int u = (invmat->a * x0 + invmat->c * y + invmat->e) * 65536;
int v = (invmat->b * x0 + invmat->d * y + invmat->f) * 65536;
int du = invmat->a * 65536;
int dv = invmat->b * 65536;
- for (x = x0; x < x1; x++)
+ n = x1 - x0;
+ d = dst->samples + ((y - dst->y) * dst->w + (x0 - dst->x)) * dst->n;
+
+ while (n--)
{
for (k = 0; k < src->n; k++)
- dst->samples[ (y * dst->w + x) * dst->n + k ]
- = sampleimage(src, u, v, k);
+ *d++ = sampleimage(src, u, v, k);
u += du;
v += dv;
}
@@ -98,13 +101,11 @@ static fz_error *
drawtile(fz_renderer *gc, fz_pixmap *out, fz_pixmap *tile, fz_matrix ctm, int over)
{
static const fz_point rect[4] = { {0, 0}, {0, 1}, {1, 1}, {1, 0} };
- fz_error *error;
- fz_gel *gel = gc->gel;
- fz_ael *ael = gc->ael;
fz_matrix imgmat;
fz_matrix invmat;
fz_point v[4];
- int i, e, y, x0, x1;
+ int top, bot, x0, x1, y;
+ int i;
imgmat.a = 1.0 / tile->w;
imgmat.b = 0.0;
@@ -116,41 +117,23 @@ drawtile(fz_renderer *gc, fz_pixmap *out, fz_pixmap *tile, fz_matrix ctm, int ov
for (i = 0; i < 4; i++)
v[i] = fz_transformpoint(ctm, rect[i]);
- fz_resetgel(gel, 1, 1);
- fz_insertgel(gel, v[0].x, v[0].y, v[1].x, v[1].y);
- fz_insertgel(gel, v[1].x, v[1].y, v[2].x, v[2].y);
- fz_insertgel(gel, v[2].x, v[2].y, v[3].x, v[3].y);
- fz_insertgel(gel, v[3].x, v[3].y, v[0].x, v[0].y);
- fz_sortgel(gel);
- e = 0;
- y = gel->edges[0].y;
+ top = fz_floor(MIN4(v[0].y, v[1].y, v[2].y, v[3].y)) - 1;
+ bot = fz_ceil(MAX4(v[0].y, v[1].y, v[2].y, v[3].y)) + 1;
+ x0 = fz_floor(MIN4(v[0].x, v[1].x, v[2].x, v[3].x)) - 1;
+ x1 = fz_ceil(MAX4(v[0].x, v[1].x, v[2].x, v[3].x)) + 1;
- while (ael->len > 0 || e < gel->len)
- {
- error = fz_insertael(ael, gel, y, &e);
- if (error)
- return error;
-
- x0 = ael->edges[0]->x;
- x1 = ael->edges[ael->len - 1]->x;
+ top = CLAMP(top, out->y, out->y + out->h - 1);
+ bot = CLAMP(bot, out->y, out->y + out->h - 1);
+ x0 = CLAMP(x0, out->x, out->x + out->w - 1);
+ x1 = CLAMP(x1, out->x, out->x + out->w - 1);
- if (y >= out->y && y < out->y + out->h)
- {
- x0 = CLAMP(x0, out->x, out->x + out->w - 1);
- x1 = CLAMP(x1, out->x, out->x + out->w - 1);
- if (over && tile->n == 4)
- overscanrgb(&invmat, out, tile, y, x0, x1);
- else
- drawscan(&invmat, out, tile, y, x0, x1);
- }
-
- fz_advanceael(ael);
-
- if (ael->len > 0)
- y ++;
- else if (e < gel->len)
- y = gel->edges[e].y;
+ for (y = top; y <= bot; y++)
+ {
+ if (over && tile->n == 4)
+ overscanrgb(&invmat, out, tile, y, x0, x1);
+ else
+ drawscan(&invmat, out, tile, y, x0, x1);
}
return nil;
diff --git a/render/rendertext.c b/render/rendertext.c
index 1a3c49db..6819ccd8 100644
--- a/render/rendertext.c
+++ b/render/rendertext.c
@@ -78,11 +78,11 @@ fz_rendertext(fz_renderer *gc, fz_textnode *text, fz_matrix ctm)
tm.f = y;
trm = fz_concat(tm, ctm);
- ix = floor(trm.e);
- iy = floor(trm.f);
+ ix = fz_floor(trm.e);
+ iy = fz_floor(trm.f);
- trm.e = (trm.e - floor(trm.e));
- trm.f = (trm.f - floor(trm.f));
+ trm.e = (trm.e - fz_floor(trm.e));
+ trm.f = (trm.f - fz_floor(trm.f));
error = fz_renderglyph(gc->cache, &gl, text->font, g, trm);
if (error)
@@ -121,11 +121,11 @@ fz_rendercolortext(fz_renderer *gc, fz_textnode *text, fz_colornode *color, fz_m
tm.f = y;
trm = fz_concat(tm, ctm);
- ix = floor(trm.e);
- iy = floor(trm.f);
+ ix = fz_floor(trm.e);
+ iy = fz_floor(trm.f);
- trm.e = (trm.e - floor(trm.e));
- trm.f = (trm.f - floor(trm.f));
+ trm.e = (trm.e - fz_floor(trm.e));
+ trm.f = (trm.f - fz_floor(trm.f));
error = fz_renderglyph(gc->cache, &gl, text->font, g, trm);
if (error)