summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2012-01-17 00:23:13 +0000
committerRobin Watts <robin@ghostscript.com>2012-01-18 13:11:52 +0000
commit2c836b57d5295b47655988cf8deaffda731e1c3c (patch)
tree01b0e51a30412ac90e53993f59c9cc649a8aa88d
parentb2c87fcd70b3f069388755baf7baa6b3c2590123 (diff)
downloadmupdf-2c836b57d5295b47655988cf8deaffda731e1c3c.tar.xz
Better handling of 'uncacheable' Type3 glyphs. Bug 692745.
Some Type 3 fonts contain glyphs that rely on inheriting various aspects of the graphics state from their calling code. (i.e. a glyph might use d0, then fill an area without setting a color first). While the spec is vague on this point, we believe that technically it is invalid. Previously mupdf defaulted all elements of the graphic state back when beginning to draw the glyph. This does not match what Acrobat does though, so we change the approach taken. We now watch (by use of bits in the device flags word) for the use of parts of the graphics state before it is set. If such use is detected, then we note that the glyph is 'uncacheable' and render it direct. This seems to match Acrobats behaviour.
-rw-r--r--fitz/fitz.h32
-rw-r--r--fitz/res_font.c56
-rw-r--r--pdf/mupdf.h2
-rw-r--r--pdf/pdf_interpret.c181
-rw-r--r--pdf/pdf_type3.c4
5 files changed, 212 insertions, 63 deletions
diff --git a/fitz/fitz.h b/fitz/fitz.h
index 769111e3..ccfa0bd6 100644
--- a/fitz/fitz.h
+++ b/fitz/fitz.h
@@ -200,9 +200,9 @@ The macro based nature of this system has 3 main limitations:
start of fz_try and something in fz_try throwing an exception may become
undefined as part of the process of throwing that exception.
-As a way of mitigating this problem, we provide an fz_var() macro that
-tells the compiler to ensure that that variable is not unset by the
-act of throwing the exception.
+ As a way of mitigating this problem, we provide an fz_var() macro that
+ tells the compiler to ensure that that variable is not unset by the
+ act of throwing the exception.
A model piece of code using these macros then might be:
@@ -1052,7 +1052,7 @@ struct fz_font_s
char *t3flags; /* has 256 entries if used */
void *t3xref; /* a pdf_xref for the callback */
void (*t3run)(void *xref, fz_obj *resources, fz_buffer *contents,
- struct fz_device_s *dev, fz_matrix ctm);
+ struct fz_device_s *dev, fz_matrix ctm, void *gstate);
fz_rect bbox; /* font bbox is used only for t3 fonts */
@@ -1063,7 +1063,7 @@ struct fz_font_s
/* substitute metrics */
int width_count;
- int *width_table; // in 1000 units
+ int *width_table; /* in 1000 units */
};
void fz_new_font_context(fz_context *ctx);
@@ -1081,6 +1081,7 @@ void fz_debug_font(fz_font *font);
void fz_set_font_bbox(fz_font *font, float xmin, float ymin, float xmax, float ymax);
fz_rect fz_bound_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm);
+int fz_glyph_cacheable(fz_font *font, int gid);
/*
* Vector path buffer.
@@ -1164,6 +1165,8 @@ void fz_debug_path(fz_path *, int indent);
* Glyph cache
*/
+typedef struct fz_device_s fz_device;
+
void fz_new_glyph_cache_context(fz_context *ctx);
void fz_free_glyph_cache_context(fz_context *ctx);
@@ -1172,6 +1175,7 @@ fz_pixmap *fz_render_t3_glyph(fz_context *ctx, fz_font *font, int cid, fz_matrix
fz_pixmap *fz_render_ft_stroked_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm, fz_matrix ctm, fz_stroke_state *state);
fz_pixmap *fz_render_glyph(fz_context *ctx, fz_font*, int, fz_matrix, fz_colorspace *model);
fz_pixmap *fz_render_stroked_glyph(fz_context *ctx, fz_font*, int, fz_matrix, fz_matrix, fz_stroke_state *stroke);
+void fz_render_t3_glyph_direct(fz_context *ctx, fz_device *dev, fz_font *font, int gid, fz_matrix trm, void *gstate);
/*
* Text buffer.
@@ -1288,12 +1292,22 @@ enum
FZ_IGNORE_SHADE = 2,
/* Flags */
- FZ_CHARPROC_MASK = 1,
- FZ_CHARPROC_COLOR = 2,
+ FZ_DEVFLAG_MASK = 1,
+ FZ_DEVFLAG_COLOR = 2,
+ FZ_DEVFLAG_UNCACHEABLE = 4,
+ FZ_DEVFLAG_FILLCOLOR_UNDEFINED = 8,
+ FZ_DEVFLAG_STROKECOLOR_UNDEFINED = 16,
+ FZ_DEVFLAG_STARTCAP_UNDEFINED = 32,
+ FZ_DEVFLAG_DASHCAP_UNDEFINED = 64,
+ FZ_DEVFLAG_ENDCAP_UNDEFINED = 128,
+ FZ_DEVFLAG_LINEJOIN_UNDEFINED = 256,
+ FZ_DEVFLAG_MITERLIMIT_UNDEFINED = 512,
+ FZ_DEVFLAG_LINEWIDTH_UNDEFINED = 1024,
+ /* Arguably we should have a bit for the dash pattern itself being
+ * undefined, but that causes problems; do we assume that it should
+ * always be set to non-dashing at the start of every glyph? */
};
-typedef struct fz_device_s fz_device;
-
struct fz_device_s
{
int hints;
diff --git a/fitz/res_font.c b/fitz/res_font.c
index 4a1c9dfa..6db1f07d 100644
--- a/fitz/res_font.c
+++ b/fitz/res_font.c
@@ -636,7 +636,15 @@ fz_bound_t3_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm)
ctm = fz_concat(font->t3matrix, trm);
dev = fz_new_bbox_device(ctx, &bbox);
- font->t3run(font->t3xref, font->t3resources, contents, dev, ctm);
+ dev->flags = FZ_DEVFLAG_FILLCOLOR_UNDEFINED |
+ FZ_DEVFLAG_STROKECOLOR_UNDEFINED |
+ FZ_DEVFLAG_STARTCAP_UNDEFINED |
+ FZ_DEVFLAG_DASHCAP_UNDEFINED |
+ FZ_DEVFLAG_ENDCAP_UNDEFINED |
+ FZ_DEVFLAG_LINEJOIN_UNDEFINED |
+ FZ_DEVFLAG_MITERLIMIT_UNDEFINED |
+ FZ_DEVFLAG_LINEWIDTH_UNDEFINED;
+ font->t3run(font->t3xref, font->t3resources, contents, dev, ctm, NULL);
font->t3flags[gid] = dev->flags;
fz_free_device(dev);
@@ -664,13 +672,13 @@ fz_render_t3_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm, fz_co
if (!contents)
return NULL;
- if (font->t3flags[gid] & FZ_CHARPROC_MASK)
+ if (font->t3flags[gid] & FZ_DEVFLAG_MASK)
{
- if (font->t3flags[gid] & FZ_CHARPROC_COLOR)
+ if (font->t3flags[gid] & FZ_DEVFLAG_COLOR)
fz_warn(ctx, "type3 glyph claims to be both masked and colored");
model = NULL;
}
- else if (font->t3flags[gid] & FZ_CHARPROC_COLOR)
+ else if (font->t3flags[gid] & FZ_DEVFLAG_COLOR)
{
if (!model)
fz_warn(ctx, "colored type3 glyph wanted in masked context");
@@ -692,7 +700,7 @@ fz_render_t3_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm, fz_co
ctm = fz_concat(font->t3matrix, trm);
dev = fz_new_draw_device_type3(ctx, glyph);
- font->t3run(font->t3xref, font->t3resources, contents, dev, ctm);
+ font->t3run(font->t3xref, font->t3resources, contents, dev, ctm, NULL);
/* RJW: "cannot draw type3 glyph" */
fz_free_device(dev);
@@ -708,6 +716,37 @@ fz_render_t3_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm, fz_co
}
void
+fz_render_t3_glyph_direct(fz_context *ctx, fz_device *dev, fz_font *font, int gid, fz_matrix trm, void *gstate)
+{
+ fz_matrix ctm;
+ fz_buffer *contents;
+
+ if (gid < 0 || gid > 255)
+ return;
+
+ contents = font->t3procs[gid];
+ if (!contents)
+ return;
+
+ if (font->t3flags[gid] & FZ_DEVFLAG_MASK)
+ {
+ if (font->t3flags[gid] & FZ_DEVFLAG_COLOR)
+ fz_warn(ctx, "type3 glyph claims to be both masked and colored");
+ }
+ else if (font->t3flags[gid] & FZ_DEVFLAG_COLOR)
+ {
+ }
+ else
+ {
+ fz_warn(ctx, "type3 glyph doesn't specify masked or colored");
+ }
+
+ ctm = fz_concat(font->t3matrix, trm);
+ font->t3run(font->t3xref, font->t3resources, contents, dev, ctm, gstate);
+ /* RJW: "cannot draw type3 glyph" */
+}
+
+void
fz_debug_font(fz_font *font)
{
printf("font '%s' {\n", font->name);
@@ -753,3 +792,10 @@ fz_bound_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm)
/* fall back to font bbox */
return fz_transform_rect(trm, font->bbox);
}
+
+int fz_glyph_cacheable(fz_font *font, int gid)
+{
+ if (!font->t3procs || !font->t3flags || gid < 0 || gid >= font->bbox_count)
+ return 1;
+ return (font->t3flags[gid] & FZ_DEVFLAG_UNCACHEABLE) == 0;
+}
diff --git a/pdf/mupdf.h b/pdf/mupdf.h
index fa7cd2f8..0e21f930 100644
--- a/pdf/mupdf.h
+++ b/pdf/mupdf.h
@@ -465,6 +465,6 @@ void pdf_free_page(fz_context *ctx, pdf_page *page);
void pdf_run_page_with_usage(pdf_xref *xref, pdf_page *page, fz_device *dev, fz_matrix ctm, char *event, fz_cookie *cookie);
void pdf_run_page(pdf_xref *xref, pdf_page *page, fz_device *dev, fz_matrix ctm, fz_cookie *cookie);
-void pdf_run_glyph(pdf_xref *xref, fz_obj *resources, fz_buffer *contents, fz_device *dev, fz_matrix ctm);
+void pdf_run_glyph(pdf_xref *xref, fz_obj *resources, fz_buffer *contents, fz_device *dev, fz_matrix ctm, void *gstate);
#endif
diff --git a/pdf/pdf_interpret.c b/pdf/pdf_interpret.c
index 2cfa5d99..7bb2da9c 100644
--- a/pdf/pdf_interpret.c
+++ b/pdf/pdf_interpret.c
@@ -88,6 +88,7 @@ struct pdf_csi_s
/* text object state */
fz_text *text;
+ fz_rect text_bbox;
fz_matrix tlm;
fz_matrix tm;
int text_mode;
@@ -432,6 +433,19 @@ pdf_show_path(pdf_csi *csi, int doclose, int dofill, int dostroke, int even_odd)
fz_path *path;
fz_rect bbox;
+ if (dostroke) {
+ if (csi->dev->flags & (FZ_DEVFLAG_STROKECOLOR_UNDEFINED | FZ_DEVFLAG_LINEJOIN_UNDEFINED | FZ_DEVFLAG_LINEWIDTH_UNDEFINED))
+ csi->dev->flags |= FZ_DEVFLAG_UNCACHEABLE;
+ else if (gstate->stroke_state.dash_len != 0 && csi->dev->flags & (FZ_DEVFLAG_STARTCAP_UNDEFINED | FZ_DEVFLAG_DASHCAP_UNDEFINED | FZ_DEVFLAG_ENDCAP_UNDEFINED))
+ csi->dev->flags |= FZ_DEVFLAG_UNCACHEABLE;
+ else if (gstate->stroke_state.linejoin == FZ_LINEJOIN_MITER && (csi->dev->flags & FZ_DEVFLAG_MITERLIMIT_UNDEFINED))
+ csi->dev->flags |= FZ_DEVFLAG_UNCACHEABLE;
+ }
+ if (dofill) {
+ if (csi->dev->flags & FZ_DEVFLAG_FILLCOLOR_UNDEFINED)
+ csi->dev->flags |= FZ_DEVFLAG_UNCACHEABLE;
+ }
+
path = csi->path;
csi->path = fz_new_path(ctx);
@@ -540,7 +554,6 @@ pdf_flush_text(pdf_csi *csi)
int dostroke = 0;
int doclip = 0;
int doinvisible = 0;
- fz_rect bbox;
fz_context *ctx = csi->dev->ctx;
if (!csi->text)
@@ -566,9 +579,7 @@ pdf_flush_text(pdf_csi *csi)
fz_try(ctx)
{
- bbox = fz_bound_text(ctx, text, gstate->ctm);
-
- pdf_begin_group(csi, bbox);
+ pdf_begin_group(csi, csi->text_bbox);
if (doinvisible)
fz_ignore_text(csi->dev, text, gstate->ctm);
@@ -595,7 +606,7 @@ pdf_flush_text(pdf_csi *csi)
if (gstate->fill.pattern)
{
fz_clip_text(csi->dev, text, gstate->ctm, 0);
- pdf_show_pattern(csi, gstate->fill.pattern, bbox, PDF_FILL);
+ pdf_show_pattern(csi, gstate->fill.pattern, csi->text_bbox, PDF_FILL);
fz_pop_clip(csi->dev);
}
break;
@@ -624,7 +635,7 @@ pdf_flush_text(pdf_csi *csi)
if (gstate->stroke.pattern)
{
fz_clip_stroke_text(csi->dev, text, &gstate->stroke_state, gstate->ctm);
- pdf_show_pattern(csi, gstate->stroke.pattern, bbox, PDF_STROKE);
+ pdf_show_pattern(csi, gstate->stroke.pattern, csi->text_bbox, PDF_STROKE);
fz_pop_clip(csi->dev);
}
break;
@@ -664,6 +675,8 @@ pdf_show_char(pdf_csi *csi, int cid)
int ucsbuf[8];
int ucslen;
int i;
+ fz_rect bbox;
+ int render_direct;
tsm.a = gstate->size * gstate->scale;
tsm.b = 0;
@@ -697,6 +710,15 @@ pdf_show_char(pdf_csi *csi, int cid)
trm = fz_concat(tsm, csi->tm);
+ bbox = fz_bound_glyph(ctx, fontdesc->font, gid, trm);
+ /* Compensate for the glyph cache limited positioning precision */
+ bbox.x0 -= 1;
+ bbox.y0 -= 1;
+ bbox.x1 += 1;
+ bbox.y1 += 1;
+
+ render_direct = !fz_glyph_cacheable(fontdesc->font, gid);
+
/* flush buffered text if face or matrix or rendermode has changed */
if (!csi->text ||
fontdesc->font != csi->text->font ||
@@ -705,7 +727,8 @@ pdf_show_char(pdf_csi *csi, int cid)
fabsf(trm.b - csi->text->trm.b) > FLT_EPSILON ||
fabsf(trm.c - csi->text->trm.c) > FLT_EPSILON ||
fabsf(trm.d - csi->text->trm.d) > FLT_EPSILON ||
- gstate->render != csi->text_mode)
+ gstate->render != csi->text_mode ||
+ render_direct)
{
pdf_flush_text(csi);
@@ -713,14 +736,28 @@ pdf_show_char(pdf_csi *csi, int cid)
csi->text->trm.e = 0;
csi->text->trm.f = 0;
csi->text_mode = gstate->render;
+ csi->text_bbox = fz_empty_rect;
}
- /* add glyph to textobject */
- fz_add_text(ctx, csi->text, gid, ucsbuf[0], trm.e, trm.f);
+ if (render_direct)
+ {
+ /* Render the glyph stream direct here (only happens for
+ * type3 glyphs that seem to inherit current graphics
+ * attributes) */
+ fz_matrix composed = fz_concat(trm, gstate->ctm);
+ fz_render_t3_glyph_direct(ctx, csi->dev, fontdesc->font, gid, composed, gstate);
+ }
+ else
+ {
+ csi->text_bbox = fz_union_rect(csi->text_bbox, bbox);
+
+ /* add glyph to textobject */
+ fz_add_text(ctx, csi->text, gid, ucsbuf[0], trm.e, trm.f);
- /* add filler glyphs for one-to-many unicode mapping */
- for (i = 1; i < ucslen; i++)
- fz_add_text(ctx, csi->text, -1, ucsbuf[i], trm.e, trm.f);
+ /* add filler glyphs for one-to-many unicode mapping */
+ for (i = 1; i < ucslen; i++)
+ fz_add_text(ctx, csi->text, -1, ucsbuf[i], trm.e, trm.f);
+ }
if (fontdesc->wmode == 0)
{
@@ -858,8 +895,49 @@ pdf_init_gstate(pdf_gstate *gs, fz_matrix ctm)
gs->luminosity = 0;
}
+static pdf_material *
+pdf_keep_material(pdf_material *mat)
+{
+ if (mat->colorspace)
+ fz_keep_colorspace(mat->colorspace);
+ if (mat->pattern)
+ pdf_keep_pattern(mat->pattern);
+ if (mat->shade)
+ fz_keep_shade(mat->shade);
+ return mat;
+}
+
+static pdf_material *
+pdf_drop_material(fz_context *ctx, pdf_material *mat)
+{
+ if (mat->colorspace)
+ fz_drop_colorspace(ctx, mat->colorspace);
+ if (mat->pattern)
+ pdf_drop_pattern(ctx, mat->pattern);
+ if (mat->shade)
+ fz_drop_shade(ctx, mat->shade);
+ return mat;
+}
+
+static void
+copy_state(pdf_gstate *gs, pdf_gstate *old)
+{
+ gs->stroke = old->stroke;
+ gs->fill = old->fill;
+ gs->font = old->font;
+ gs->softmask = old->softmask;
+
+ pdf_keep_material(&gs->stroke);
+ pdf_keep_material(&gs->fill);
+ if (gs->font)
+ pdf_keep_font(gs->font);
+ if (gs->softmask)
+ pdf_keep_xobject(gs->softmask);
+}
+
+
static pdf_csi *
-pdf_new_csi(pdf_xref *xref, fz_device *dev, fz_matrix ctm, char *event, fz_cookie *cookie)
+pdf_new_csi(pdf_xref *xref, fz_device *dev, fz_matrix ctm, char *event, fz_cookie *cookie, pdf_gstate *gstate)
{
pdf_csi *csi;
fz_context *ctx = dev->ctx;
@@ -896,6 +974,8 @@ pdf_new_csi(pdf_xref *xref, fz_device *dev, fz_matrix ctm, char *event, fz_cooki
csi->top_ctm = ctm;
pdf_init_gstate(&csi->gstate[0], ctm);
+ if (gstate)
+ copy_state(&csi->gstate[0], gstate);
csi->gtop = 0;
csi->cookie = cookie;
@@ -927,30 +1007,6 @@ pdf_clear_stack(pdf_csi *csi)
csi->top = 0;
}
-static pdf_material *
-pdf_keep_material(pdf_material *mat)
-{
- if (mat->colorspace)
- fz_keep_colorspace(mat->colorspace);
- if (mat->pattern)
- pdf_keep_pattern(mat->pattern);
- if (mat->shade)
- fz_keep_shade(mat->shade);
- return mat;
-}
-
-static pdf_material *
-pdf_drop_material(fz_context *ctx, pdf_material *mat)
-{
- if (mat->colorspace)
- fz_drop_colorspace(ctx, mat->colorspace);
- if (mat->pattern)
- pdf_drop_pattern(ctx, mat->pattern);
- if (mat->shade)
- fz_drop_shade(ctx, mat->shade);
- return mat;
-}
-
static void
pdf_gsave(pdf_csi *csi)
{
@@ -962,12 +1018,11 @@ pdf_gsave(pdf_csi *csi)
csi->gstate = fz_resize_array(ctx, csi->gstate, csi->gcap*2, sizeof(pdf_gstate));
csi->gcap *= 2;
}
- gs = csi->gstate + csi->gtop;
memcpy(&csi->gstate[csi->gtop + 1], &csi->gstate[csi->gtop], sizeof(pdf_gstate));
- csi->gtop ++;
-
+ csi->gtop++;
+ gs = &csi->gstate[csi->gtop];
pdf_keep_material(&gs->stroke);
pdf_keep_material(&gs->fill);
if (gs->font)
@@ -1419,16 +1474,26 @@ pdf_run_extgstate(pdf_csi *csi, fz_obj *rdb, fz_obj *extgstate)
else if (!strcmp(s, "LC"))
{
+ csi->dev->flags &= ~(FZ_DEVFLAG_STARTCAP_UNDEFINED | FZ_DEVFLAG_DASHCAP_UNDEFINED | FZ_DEVFLAG_ENDCAP_UNDEFINED);
gstate->stroke_state.start_cap = fz_to_int(val);
gstate->stroke_state.dash_cap = fz_to_int(val);
gstate->stroke_state.end_cap = fz_to_int(val);
}
else if (!strcmp(s, "LW"))
+ {
+ csi->dev->flags &= ~FZ_DEVFLAG_LINEWIDTH_UNDEFINED;
gstate->stroke_state.linewidth = fz_to_real(val);
+ }
else if (!strcmp(s, "LJ"))
+ {
+ csi->dev->flags &= ~FZ_DEVFLAG_LINEJOIN_UNDEFINED;
gstate->stroke_state.linejoin = fz_to_int(val);
+ }
else if (!strcmp(s, "ML"))
+ {
+ csi->dev->flags &= ~FZ_DEVFLAG_MITERLIMIT_UNDEFINED;
gstate->stroke_state.miterlimit = fz_to_real(val);
+ }
else if (!strcmp(s, "D"))
{
@@ -1655,12 +1720,16 @@ static void pdf_run_cs_imp(pdf_csi *csi, fz_obj *rdb, int what)
static void pdf_run_CS(pdf_csi *csi, fz_obj *rdb)
{
+ csi->dev->flags &= ~FZ_DEVFLAG_STROKECOLOR_UNDEFINED;
+
pdf_run_cs_imp(csi, rdb, PDF_STROKE);
/* RJW: "cannot set colorspace" */
}
static void pdf_run_cs(pdf_csi *csi, fz_obj *rdb)
{
+ csi->dev->flags &= ~FZ_DEVFLAG_FILLCOLOR_UNDEFINED;
+
pdf_run_cs_imp(csi, rdb, PDF_FILL);
/* RJW: "cannot set colorspace" */
}
@@ -1774,6 +1843,7 @@ static void pdf_run_F(pdf_csi *csi)
static void pdf_run_G(pdf_csi *csi)
{
+ csi->dev->flags &= ~FZ_DEVFLAG_STROKECOLOR_UNDEFINED;
pdf_set_colorspace(csi, PDF_STROKE, fz_device_gray);
pdf_set_color(csi, PDF_STROKE, csi->stack);
}
@@ -1781,6 +1851,7 @@ static void pdf_run_G(pdf_csi *csi)
static void pdf_run_J(pdf_csi *csi)
{
pdf_gstate *gstate = csi->gstate + csi->gtop;
+ csi->dev->flags &= ~(FZ_DEVFLAG_STARTCAP_UNDEFINED | FZ_DEVFLAG_DASHCAP_UNDEFINED | FZ_DEVFLAG_ENDCAP_UNDEFINED);
gstate->stroke_state.start_cap = csi->stack[0];
gstate->stroke_state.dash_cap = csi->stack[0];
gstate->stroke_state.end_cap = csi->stack[0];
@@ -1788,6 +1859,7 @@ static void pdf_run_J(pdf_csi *csi)
static void pdf_run_K(pdf_csi *csi)
{
+ csi->dev->flags &= ~FZ_DEVFLAG_STROKECOLOR_UNDEFINED;
pdf_set_colorspace(csi, PDF_STROKE, fz_device_cmyk);
pdf_set_color(csi, PDF_STROKE, csi->stack);
}
@@ -1795,6 +1867,7 @@ static void pdf_run_K(pdf_csi *csi)
static void pdf_run_M(pdf_csi *csi)
{
pdf_gstate *gstate = csi->gstate + csi->gtop;
+ csi->dev->flags &= ~FZ_DEVFLAG_MITERLIMIT_UNDEFINED;
gstate->stroke_state.miterlimit = csi->stack[0];
}
@@ -1809,6 +1882,7 @@ static void pdf_run_Q(pdf_csi *csi)
static void pdf_run_RG(pdf_csi *csi)
{
+ csi->dev->flags &= ~FZ_DEVFLAG_STROKECOLOR_UNDEFINED;
pdf_set_colorspace(csi, PDF_STROKE, fz_device_rgb);
pdf_set_color(csi, PDF_STROKE, csi->stack);
}
@@ -1880,6 +1954,7 @@ static void pdf_run_SC_imp(pdf_csi *csi, fz_obj *rdb, int what, pdf_material *ma
static void pdf_run_SC(pdf_csi *csi, fz_obj *rdb)
{
pdf_gstate *gstate = csi->gstate + csi->gtop;
+ csi->dev->flags &= ~FZ_DEVFLAG_STROKECOLOR_UNDEFINED;
pdf_run_SC_imp(csi, rdb, PDF_STROKE, &gstate->stroke);
/* RJW: "cannot set color and colorspace" */
}
@@ -1887,6 +1962,7 @@ static void pdf_run_SC(pdf_csi *csi, fz_obj *rdb)
static void pdf_run_sc(pdf_csi *csi, fz_obj *rdb)
{
pdf_gstate *gstate = csi->gstate + csi->gtop;
+ csi->dev->flags &= ~FZ_DEVFLAG_FILLCOLOR_UNDEFINED;
pdf_run_SC_imp(csi, rdb, PDF_FILL, &gstate->fill);
/* RJW: "cannot set color and colorspace" */
}
@@ -2070,12 +2146,20 @@ static void pdf_run_d(pdf_csi *csi)
static void pdf_run_d0(pdf_csi *csi)
{
- csi->dev->flags |= FZ_CHARPROC_COLOR;
+ csi->dev->flags |= FZ_DEVFLAG_COLOR;
}
static void pdf_run_d1(pdf_csi *csi)
{
- csi->dev->flags |= FZ_CHARPROC_MASK;
+ csi->dev->flags |= FZ_DEVFLAG_MASK;
+ csi->dev->flags &= ~(FZ_DEVFLAG_FILLCOLOR_UNDEFINED |
+ FZ_DEVFLAG_STROKECOLOR_UNDEFINED |
+ FZ_DEVFLAG_STARTCAP_UNDEFINED |
+ FZ_DEVFLAG_DASHCAP_UNDEFINED |
+ FZ_DEVFLAG_ENDCAP_UNDEFINED |
+ FZ_DEVFLAG_LINEJOIN_UNDEFINED |
+ FZ_DEVFLAG_MITERLIMIT_UNDEFINED |
+ FZ_DEVFLAG_LINEWIDTH_UNDEFINED);
}
static void pdf_run_f(pdf_csi *csi)
@@ -2090,6 +2174,7 @@ static void pdf_run_fstar(pdf_csi *csi)
static void pdf_run_g(pdf_csi *csi)
{
+ csi->dev->flags &= ~FZ_DEVFLAG_FILLCOLOR_UNDEFINED;
pdf_set_colorspace(csi, PDF_FILL, fz_device_gray);
pdf_set_color(csi, PDF_FILL, csi->stack);
}
@@ -2124,11 +2209,13 @@ static void pdf_run_i(pdf_csi *csi)
static void pdf_run_j(pdf_csi *csi)
{
pdf_gstate *gstate = csi->gstate + csi->gtop;
+ csi->dev->flags &= ~FZ_DEVFLAG_LINEJOIN_UNDEFINED;
gstate->stroke_state.linejoin = csi->stack[0];
}
static void pdf_run_k(pdf_csi *csi)
{
+ csi->dev->flags &= ~FZ_DEVFLAG_FILLCOLOR_UNDEFINED;
pdf_set_colorspace(csi, PDF_FILL, fz_device_cmyk);
pdf_set_color(csi, PDF_FILL, csi->stack);
}
@@ -2178,6 +2265,7 @@ static void pdf_run_re(pdf_csi *csi)
static void pdf_run_rg(pdf_csi *csi)
{
+ csi->dev->flags &= ~FZ_DEVFLAG_FILLCOLOR_UNDEFINED;
pdf_set_colorspace(csi, PDF_FILL, fz_device_rgb);
pdf_set_color(csi, PDF_FILL, csi->stack);
}
@@ -2237,6 +2325,7 @@ static void pdf_run_w(pdf_csi *csi)
{
pdf_gstate *gstate = csi->gstate + csi->gtop;
pdf_flush_text(csi); /* linewidth affects stroked text rendering mode */
+ csi->dev->flags &= ~FZ_DEVFLAG_LINEWIDTH_UNDEFINED;
gstate->stroke_state.linewidth = csi->stack[0];
}
@@ -2607,7 +2696,7 @@ pdf_run_page_with_usage(pdf_xref *xref, pdf_page *page, fz_device *dev, fz_matri
if (page->transparency)
fz_begin_group(dev, fz_transform_rect(ctm, page->mediabox), 1, 0, 0, 1);
- csi = pdf_new_csi(xref, dev, ctm, event, cookie);
+ csi = pdf_new_csi(xref, dev, ctm, event, cookie, NULL);
fz_try(ctx)
{
pdf_run_buffer(csi, page->resources, page->contents);
@@ -2649,7 +2738,7 @@ pdf_run_page_with_usage(pdf_xref *xref, pdf_page *page, fz_device *dev, fz_matri
if (!strcmp(event, "View") && (flags & (1 << 5))) /* NoView */
continue;
- csi = pdf_new_csi(xref, dev, ctm, event, cookie);
+ csi = pdf_new_csi(xref, dev, ctm, event, cookie, NULL);
if (!pdf_is_hidden_ocg(fz_dict_gets(annot->obj, "OC"), csi, page->resources))
{
fz_try(ctx)
@@ -2676,9 +2765,9 @@ pdf_run_page(pdf_xref *xref, pdf_page *page, fz_device *dev, fz_matrix ctm, fz_c
}
void
-pdf_run_glyph(pdf_xref *xref, fz_obj *resources, fz_buffer *contents, fz_device *dev, fz_matrix ctm)
+pdf_run_glyph(pdf_xref *xref, fz_obj *resources, fz_buffer *contents, fz_device *dev, fz_matrix ctm, void *gstate)
{
- pdf_csi *csi = pdf_new_csi(xref, dev, ctm, "View", NULL);
+ pdf_csi *csi = pdf_new_csi(xref, dev, ctm, "View", NULL, gstate);
fz_context *ctx = xref->ctx;
fz_try(ctx)
diff --git a/pdf/pdf_type3.c b/pdf/pdf_type3.c
index f43170c4..d9bf528e 100644
--- a/pdf/pdf_type3.c
+++ b/pdf/pdf_type3.c
@@ -2,9 +2,9 @@
#include "mupdf.h"
static void
-pdf_run_glyph_func(void *xref, fz_obj *rdb, fz_buffer *contents, fz_device *dev, fz_matrix ctm)
+pdf_run_glyph_func(void *xref, fz_obj *rdb, fz_buffer *contents, fz_device *dev, fz_matrix ctm, void *gstate)
{
- pdf_run_glyph(xref, rdb, contents, dev, ctm);
+ pdf_run_glyph(xref, rdb, contents, dev, ctm, gstate);
}
pdf_font_desc *