summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2016-06-16 16:32:08 +0200
committerTor Andersson <tor.andersson@artifex.com>2016-06-17 14:53:20 +0200
commitccaf716d6c3f20731aaed277653cf3b1be4e218b (patch)
tree3cb2f6e7776007a66dd74ccf1323c17a2c597c2f
parent27269d493d66e16bfd7a5b5a0b09c4f21693260b (diff)
downloadmupdf-ccaf716d6c3f20731aaed277653cf3b1be4e218b.tar.xz
Add device space transform state to draw device.
Allows us to remove the out parameter 'transform' from fz_begin_page.
-rw-r--r--docs/mutool/run.html10
-rw-r--r--include/mupdf/fitz/device.h16
-rw-r--r--include/mupdf/fitz/writer.h4
-rw-r--r--platform/x11/pdfapp.c4
-rw-r--r--source/fitz/draw-device.c143
-rw-r--r--source/fitz/font.c2
-rw-r--r--source/fitz/image.c4
-rw-r--r--source/fitz/output-cbz.c4
-rw-r--r--source/fitz/output-png.c4
-rw-r--r--source/fitz/util.c16
-rw-r--r--source/fitz/writer.c4
-rw-r--r--source/pdf/pdf-write.c3
-rw-r--r--source/tools/muconvert.c5
-rw-r--r--source/tools/mudraw.c4
-rw-r--r--source/tools/murun.c24
15 files changed, 129 insertions, 118 deletions
diff --git a/docs/mutool/run.html b/docs/mutool/run.html
index 3d8f2753..44eedec0 100644
--- a/docs/mutool/run.html
+++ b/docs/mutool/run.html
@@ -120,6 +120,9 @@ Matrices and Rectangles
</h2>
<p>
+All dimensions are in points unless otherwise specified.
+
+<p>
Matrices are simply 6-element arrays representing a 3-by-3 transformation matrix as
<pre>
@@ -183,6 +186,7 @@ MuPDF can open many document types (PDF, XPS, CBZ, EPUB, FB2 and a handful of im
<dt>Page#run(device, transform)
<dd>Calls device functions for all the contents on the page, using the specified transform matrix.
The device can be one of the built-in devices or a JavaScript object with methods for the device calls.
+The transform maps from user space points to device space pixels.
<dt>Page#toPixmap(transform, colorspace)
<dd>Render the page into a Pixmap, using the transform and colorspace.
<dt>Page#toDisplayList()
@@ -251,7 +255,7 @@ DrawDevice
The DrawDevice can be used to render to a Pixmap; either by running a Page with it or by calling its methods directly.
<dl>
-<dt>new DrawDevice(pixmap)
+<dt>new DrawDevice(transform, pixmap)
<dd>Create a device for drawing into a pixmap. The pixmap bounds used should match the transformed page bounds,
or you can adjust them to only draw a part of the page.
</dl>
@@ -481,10 +485,8 @@ Document writer objects are used to create new documents in several formats.
<dd>Create a new document writer to create a document with the specified format and output options.
If format is null it is inferred from the filename suffix. The options argument is a comma separated list
of flags and key-value pairs. See below for more details.
-<dt>DocumentWriter#beginPage(mediabox, transform)
+<dt>DocumentWriter#beginPage(mediabox)
<dd>Begin rendering a new page. Returns a Device that can be used to render the page graphics.
-The transform argument must be an empty array which is set to the transform matrix to be
-used with the device functions.
<dt>DocumentWriter#endPage(device)
<dd>Finish the page rendering.
The argument must be the same device object that was returned by the beginPage method.
diff --git a/include/mupdf/fitz/device.h b/include/mupdf/fitz/device.h
index 02f20ef6..99588075 100644
--- a/include/mupdf/fitz/device.h
+++ b/include/mupdf/fitz/device.h
@@ -338,8 +338,10 @@ enum
draw device, see fz_clear_pixmap* for how to clear it prior to
calling fz_new_draw_device. Free the device by calling
fz_drop_device.
+
+ transform: Transform from user space in points to device space in pixels.
*/
-fz_device *fz_new_draw_device(fz_context *ctx, fz_pixmap *dest);
+fz_device *fz_new_draw_device(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest);
/*
fz_new_draw_device_with_bbox: Create a device to draw on a pixmap.
@@ -350,12 +352,14 @@ fz_device *fz_new_draw_device(fz_context *ctx, fz_pixmap *dest);
calling fz_new_draw_device. Free the device by calling
fz_drop_device.
+ transform: Transform from user space in points to device space in pixels.
+
clip: Bounding box to restrict any marking operations of the
draw device.
*/
-fz_device *fz_new_draw_device_with_bbox(fz_context *ctx, fz_pixmap *dest, const fz_irect *clip);
+fz_device *fz_new_draw_device_with_bbox(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest, const fz_irect *clip);
-fz_device *fz_new_draw_device_type3(fz_context *ctx, fz_pixmap *dest);
+fz_device *fz_new_draw_device_type3(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest);
/*
struct fz_draw_options: Options for creating a pixmap and draw device.
@@ -382,10 +386,10 @@ fz_draw_options *fz_parse_draw_options(fz_context *ctx, fz_draw_options *options
/*
fz_new_draw_device_with_options: Create a new pixmap and draw device, using the specified options.
- mediabox: An in parameter containing the size of the page.
+ options: Options to configure the draw device, and choose the resolution and colorspace.
+ mediabox: The bounds of the page in points.
pixmap: An out parameter containing the newly created pixmap.
- transform: An out parameter containing the transform to be used when running the page.
*/
-fz_device *fz_new_draw_device_with_options(fz_context *ctx, const fz_draw_options *opts, const fz_rect *mediabox, fz_matrix *transform, fz_pixmap **pixmap);
+fz_device *fz_new_draw_device_with_options(fz_context *ctx, const fz_draw_options *options, const fz_rect *mediabox, fz_pixmap **pixmap);
#endif
diff --git a/include/mupdf/fitz/writer.h b/include/mupdf/fitz/writer.h
index 98b0824a..6f0f47be 100644
--- a/include/mupdf/fitz/writer.h
+++ b/include/mupdf/fitz/writer.h
@@ -11,7 +11,7 @@ typedef struct fz_document_writer_s fz_document_writer;
struct fz_document_writer_s
{
- fz_device *(*begin_page)(fz_context *ctx, fz_document_writer *wri, const fz_rect *mediabox, fz_matrix *ctm);
+ fz_device *(*begin_page)(fz_context *ctx, fz_document_writer *wri, const fz_rect *mediabox);
void (*end_page)(fz_context *ctx, fz_document_writer *wri, fz_device *dev);
void (*close)(fz_context *ctx, fz_document_writer *wri);
};
@@ -20,7 +20,7 @@ int fz_has_option(fz_context *ctx, const char *opts, const char *key, const char
fz_document_writer *fz_new_document_writer(fz_context *ctx, const char *path, const char *format, const char *options);
-fz_device *fz_begin_page(fz_context *ctx, fz_document_writer *wri, const fz_rect *mediabox, fz_matrix *ctm);
+fz_device *fz_begin_page(fz_context *ctx, fz_document_writer *wri, const fz_rect *mediabox);
void fz_end_page(fz_context *ctx, fz_document_writer *wri, fz_device *dev);
void fz_close_document_writer(fz_context *ctx, fz_document_writer *wri);
void fz_drop_document_writer(fz_context *ctx, fz_document_writer *wri);
diff --git a/platform/x11/pdfapp.c b/platform/x11/pdfapp.c
index 55d5b5e3..2b650442 100644
--- a/platform/x11/pdfapp.c
+++ b/platform/x11/pdfapp.c
@@ -793,7 +793,7 @@ static void pdfapp_updatepage(pdfapp_t *app)
fz_transform_rect(fz_bound_annot(app->ctx, annot, &bounds), &ctm);
fz_rect_from_irect(&bounds, fz_round_rect(&ibounds, &bounds));
fz_clear_pixmap_rect_with_value(app->ctx, app->image, 255, &ibounds);
- idev = fz_new_draw_device_with_bbox(app->ctx, app->image, &ibounds);
+ idev = fz_new_draw_device_with_bbox(app->ctx, NULL, app->image, &ibounds);
pdfapp_runpage(app, idev, &ctm, &bounds, NULL);
fz_drop_device(app->ctx, idev);
}
@@ -895,7 +895,7 @@ static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage, int repai
fz_clear_pixmap_with_value(app->ctx, app->image, 255);
if (app->page_list || app->annotations_list)
{
- idev = fz_new_draw_device(app->ctx, app->image);
+ idev = fz_new_draw_device(app->ctx, NULL, app->image);
pdfapp_runpage(app, idev, &ctm, &bounds, &cookie);
fz_drop_device(app->ctx, idev);
}
diff --git a/source/fitz/draw-device.c b/source/fitz/draw-device.c
index bdfa1085..44d0bfaf 100644
--- a/source/fitz/draw-device.c
+++ b/source/fitz/draw-device.c
@@ -62,19 +62,19 @@ fz_parse_draw_options(fz_context *ctx, fz_draw_options *opts, const char *args)
}
fz_device *
-fz_new_draw_device_with_options(fz_context *ctx, const fz_draw_options *opts, const fz_rect *mediabox,
- fz_matrix *transform, fz_pixmap **pixmap)
+fz_new_draw_device_with_options(fz_context *ctx, const fz_draw_options *opts, const fz_rect *mediabox, fz_pixmap **pixmap)
{
float zoom = opts->resolution / 72.0f;
int w = opts->width;
int h = opts->height;
fz_rect bounds;
fz_irect ibounds;
+ fz_matrix transform;
fz_device *dev;
- fz_pre_scale(fz_rotate(transform, opts->rotate), zoom, zoom);
+ fz_pre_scale(fz_rotate(&transform, opts->rotate), zoom, zoom);
bounds = *mediabox;
- fz_round_rect(&ibounds, fz_transform_rect(&bounds, transform));
+ fz_round_rect(&ibounds, fz_transform_rect(&bounds, &transform));
/* If width or height are set, we may need to adjust the transform */
if (w || h)
@@ -98,9 +98,9 @@ fz_new_draw_device_with_options(fz_context *ctx, const fz_draw_options *opts, co
}
if (scalex != 1 || scaley != 1)
{
- fz_pre_scale(transform, scalex, scaley);
+ fz_pre_scale(&transform, scalex, scaley);
bounds = *mediabox;
- fz_round_rect(&ibounds, fz_transform_rect(&bounds, transform));
+ fz_round_rect(&ibounds, fz_transform_rect(&bounds, &transform));
}
}
@@ -112,7 +112,7 @@ fz_new_draw_device_with_options(fz_context *ctx, const fz_draw_options *opts, co
else
fz_clear_pixmap_with_value(ctx, *pixmap, 255);
- dev = fz_new_draw_device(ctx, *pixmap);
+ dev = fz_new_draw_device(ctx, &transform, *pixmap);
}
fz_catch(ctx)
{
@@ -160,6 +160,7 @@ struct fz_draw_state_s {
struct fz_draw_device_s
{
fz_device super;
+ fz_matrix transform;
fz_gel *gel;
int flags;
int top;
@@ -386,14 +387,22 @@ static void fz_knockout_end(fz_context *ctx, fz_draw_device *dev)
#endif
}
+static inline fz_matrix concat(const fz_matrix *one, const fz_matrix *two)
+{
+ fz_matrix ctm;
+ fz_concat(&ctm, one, two);
+ return ctm;
+}
+
static void
-fz_draw_fill_path(fz_context *ctx, fz_device *devp, const fz_path *path, int even_odd, const fz_matrix *ctm,
+fz_draw_fill_path(fz_context *ctx, fz_device *devp, const fz_path *path, int even_odd, const fz_matrix *in_ctm,
fz_colorspace *colorspace, const float *color, float alpha)
{
fz_draw_device *dev = (fz_draw_device*)devp;
+ fz_matrix ctm = concat(in_ctm, &dev->transform);
fz_gel *gel = dev->gel;
- float expansion = fz_matrix_expansion(ctm);
+ float expansion = fz_matrix_expansion(&ctm);
float flatness = 0.3f / expansion;
unsigned char colorbv[FZ_MAX_COLORS + 1];
float colorfv[FZ_MAX_COLORS];
@@ -406,7 +415,7 @@ fz_draw_fill_path(fz_context *ctx, fz_device *devp, const fz_path *path, int eve
flatness = 0.001f;
fz_reset_gel(ctx, gel, &state->scissor);
- fz_flatten_fill_path(ctx, gel, path, ctm, flatness);
+ fz_flatten_fill_path(ctx, gel, path, &ctm, flatness);
fz_sort_gel(ctx, gel);
fz_intersect_irect(fz_bound_gel(ctx, gel, &bbox), &state->scissor);
@@ -427,7 +436,7 @@ fz_draw_fill_path(fz_context *ctx, fz_device *devp, const fz_path *path, int eve
if (state->shape)
{
fz_reset_gel(ctx, gel, &state->scissor);
- fz_flatten_fill_path(ctx, gel, path, ctm, flatness);
+ fz_flatten_fill_path(ctx, gel, path, &ctm, flatness);
fz_sort_gel(ctx, gel);
colorbv[0] = alpha * 255;
@@ -439,13 +448,14 @@ fz_draw_fill_path(fz_context *ctx, fz_device *devp, const fz_path *path, int eve
}
static void
-fz_draw_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path, const fz_stroke_state *stroke, const fz_matrix *ctm,
+fz_draw_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path, const fz_stroke_state *stroke, const fz_matrix *in_ctm,
fz_colorspace *colorspace, const float *color, float alpha)
{
fz_draw_device *dev = (fz_draw_device*)devp;
+ fz_matrix ctm = concat(in_ctm, &dev->transform);
fz_gel *gel = dev->gel;
- float expansion = fz_matrix_expansion(ctm);
+ float expansion = fz_matrix_expansion(&ctm);
float flatness = 0.3f / expansion;
float linewidth = stroke->linewidth;
unsigned char colorbv[FZ_MAX_COLORS + 1];
@@ -463,9 +473,9 @@ fz_draw_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path, const
fz_reset_gel(ctx, gel, &state->scissor);
if (stroke->dash_len > 0)
- fz_flatten_dash_path(ctx, gel, path, stroke, ctm, flatness, linewidth);
+ fz_flatten_dash_path(ctx, gel, path, stroke, &ctm, flatness, linewidth);
else
- fz_flatten_stroke_path(ctx, gel, path, stroke, ctm, flatness, linewidth);
+ fz_flatten_stroke_path(ctx, gel, path, stroke, &ctm, flatness, linewidth);
fz_sort_gel(ctx, gel);
fz_intersect_irect(fz_bound_gel(ctx, gel, &bbox), &state->scissor);
@@ -494,9 +504,9 @@ fz_draw_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path, const
{
fz_reset_gel(ctx, gel, &state->scissor);
if (stroke->dash_len > 0)
- fz_flatten_dash_path(ctx, gel, path, stroke, ctm, flatness, linewidth);
+ fz_flatten_dash_path(ctx, gel, path, stroke, &ctm, flatness, linewidth);
else
- fz_flatten_stroke_path(ctx, gel, path, stroke, ctm, flatness, linewidth);
+ fz_flatten_stroke_path(ctx, gel, path, stroke, &ctm, flatness, linewidth);
fz_sort_gel(ctx, gel);
colorbv[0] = 255;
@@ -515,12 +525,13 @@ fz_draw_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path, const
}
static void
-fz_draw_clip_path(fz_context *ctx, fz_device *devp, const fz_path *path, int even_odd, const fz_matrix *ctm, const fz_rect *scissor)
+fz_draw_clip_path(fz_context *ctx, fz_device *devp, const fz_path *path, int even_odd, const fz_matrix *in_ctm, const fz_rect *scissor)
{
fz_draw_device *dev = (fz_draw_device*)devp;
+ fz_matrix ctm = concat(in_ctm, &dev->transform);
fz_gel *gel = dev->gel;
- float expansion = fz_matrix_expansion(ctm);
+ float expansion = fz_matrix_expansion(&ctm);
float flatness = 0.3f / expansion;
fz_irect bbox;
fz_draw_state *state = &dev->stack[dev->top];
@@ -530,7 +541,7 @@ fz_draw_clip_path(fz_context *ctx, fz_device *devp, const fz_path *path, int eve
flatness = 0.001f;
fz_reset_gel(ctx, gel, &state->scissor);
- fz_flatten_fill_path(ctx, gel, path, ctm, flatness);
+ fz_flatten_fill_path(ctx, gel, path, &ctm, flatness);
fz_sort_gel(ctx, gel);
state = push_stack(ctx, dev);
@@ -588,12 +599,13 @@ fz_draw_clip_path(fz_context *ctx, fz_device *devp, const fz_path *path, int eve
}
static void
-fz_draw_clip_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path, const fz_stroke_state *stroke, const fz_matrix *ctm, const fz_rect *scissor)
+fz_draw_clip_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path, const fz_stroke_state *stroke, const fz_matrix *in_ctm, const fz_rect *scissor)
{
fz_draw_device *dev = (fz_draw_device*)devp;
+ fz_matrix ctm = concat(in_ctm, &dev->transform);
fz_gel *gel = dev->gel;
- float expansion = fz_matrix_expansion(ctm);
+ float expansion = fz_matrix_expansion(&ctm);
float flatness = 0.3f / expansion;
float linewidth = stroke->linewidth;
fz_irect bbox;
@@ -608,9 +620,9 @@ fz_draw_clip_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path,
fz_reset_gel(ctx, gel, &state->scissor);
if (stroke->dash_len > 0)
- fz_flatten_dash_path(ctx, gel, path, stroke, ctm, flatness, linewidth);
+ fz_flatten_dash_path(ctx, gel, path, stroke, &ctm, flatness, linewidth);
else
- fz_flatten_stroke_path(ctx, gel, path, stroke, ctm, flatness, linewidth);
+ fz_flatten_stroke_path(ctx, gel, path, stroke, &ctm, flatness, linewidth);
fz_sort_gel(ctx, gel);
state = push_stack(ctx, dev);
@@ -728,10 +740,11 @@ draw_glyph(unsigned char *colorbv, fz_pixmap *dst, fz_glyph *glyph,
}
static void
-fz_draw_fill_text(fz_context *ctx, fz_device *devp, const fz_text *text, const fz_matrix *ctm,
+fz_draw_fill_text(fz_context *ctx, fz_device *devp, const fz_text *text, const fz_matrix *in_ctm,
fz_colorspace *colorspace, const float *color, float alpha)
{
fz_draw_device *dev = (fz_draw_device*)devp;
+ fz_matrix ctm = concat(in_ctm, &dev->transform);
fz_draw_state *state = &dev->stack[dev->top];
fz_colorspace *model = state->dest->colorspace;
unsigned char colorbv[FZ_MAX_COLORS + 1];
@@ -766,7 +779,7 @@ fz_draw_fill_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f
tm.e = span->items[i].x;
tm.f = span->items[i].y;
- fz_concat(&trm, &tm, ctm);
+ fz_concat(&trm, &tm, &ctm);
glyph = fz_render_glyph(ctx, span->font, gid, &trm, model, &state->scissor, state->dest->alpha);
if (glyph)
@@ -794,7 +807,7 @@ fz_draw_fill_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f
fz_path *path = fz_outline_glyph(ctx, span->font, gid, &tm);
if (path)
{
- fz_draw_fill_path(ctx, devp, path, 0, ctm, colorspace, color, alpha);
+ fz_draw_fill_path(ctx, devp, path, 0, &ctm, colorspace, color, alpha);
fz_drop_path(ctx, path);
}
else
@@ -811,10 +824,11 @@ fz_draw_fill_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f
static void
fz_draw_stroke_text(fz_context *ctx, fz_device *devp, const fz_text *text, const fz_stroke_state *stroke,
- const fz_matrix *ctm, fz_colorspace *colorspace,
+ const fz_matrix *in_ctm, fz_colorspace *colorspace,
const float *color, float alpha)
{
fz_draw_device *dev = (fz_draw_device*)devp;
+ fz_matrix ctm = concat(in_ctm, &dev->transform);
fz_draw_state *state = &dev->stack[dev->top];
fz_colorspace *model = state->dest->colorspace;
unsigned char colorbv[FZ_MAX_COLORS + 1];
@@ -847,9 +861,9 @@ fz_draw_stroke_text(fz_context *ctx, fz_device *devp, const fz_text *text, const
tm.e = span->items[i].x;
tm.f = span->items[i].y;
- fz_concat(&trm, &tm, ctm);
+ fz_concat(&trm, &tm, &ctm);
- glyph = fz_render_stroked_glyph(ctx, span->font, gid, &trm, ctm, stroke, &state->scissor);
+ glyph = fz_render_stroked_glyph(ctx, span->font, gid, &trm, &ctm, stroke, &state->scissor);
if (glyph)
{
int x = (int)trm.e;
@@ -864,7 +878,7 @@ fz_draw_stroke_text(fz_context *ctx, fz_device *devp, const fz_text *text, const
fz_path *path = fz_outline_glyph(ctx, span->font, gid, &tm);
if (path)
{
- fz_draw_stroke_path(ctx, devp, path, stroke, ctm, colorspace, color, alpha);
+ fz_draw_stroke_path(ctx, devp, path, stroke, &ctm, colorspace, color, alpha);
fz_drop_path(ctx, path);
}
else
@@ -880,9 +894,10 @@ fz_draw_stroke_text(fz_context *ctx, fz_device *devp, const fz_text *text, const
}
static void
-fz_draw_clip_text(fz_context *ctx, fz_device *devp, const fz_text *text, const fz_matrix *ctm, const fz_rect *scissor)
+fz_draw_clip_text(fz_context *ctx, fz_device *devp, const fz_text *text, const fz_matrix *in_ctm, const fz_rect *scissor)
{
fz_draw_device *dev = (fz_draw_device*)devp;
+ fz_matrix ctm = concat(in_ctm, &dev->transform);
fz_irect bbox;
fz_pixmap *mask, *dest, *shape;
fz_matrix tm, trm;
@@ -898,7 +913,7 @@ fz_draw_clip_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f
model = state->dest->colorspace;
/* make the mask the exact size needed */
- fz_irect_from_rect(&bbox, fz_bound_text(ctx, text, NULL, ctm, &rect));
+ fz_irect_from_rect(&bbox, fz_bound_text(ctx, text, NULL, &ctm, &rect));
fz_intersect_irect(&bbox, &state->scissor);
if (scissor)
{
@@ -950,7 +965,7 @@ fz_draw_clip_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f
tm.e = span->items[i].x;
tm.f = span->items[i].y;
- fz_concat(&trm, &tm, ctm);
+ fz_concat(&trm, &tm, &ctm);
glyph = fz_render_glyph(ctx, span->font, gid, &trm, model, &state->scissor, state[1].dest->alpha);
if (glyph)
@@ -975,7 +990,7 @@ fz_draw_clip_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f
state[1].mask = NULL;
fz_try(ctx)
{
- fz_draw_fill_path(ctx, devp, path, 0, ctm, fz_device_gray(ctx), &white, 1);
+ fz_draw_fill_path(ctx, devp, path, 0, &ctm, fz_device_gray(ctx), &white, 1);
}
fz_always(ctx)
{
@@ -1005,9 +1020,10 @@ fz_draw_clip_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f
}
static void
-fz_draw_clip_stroke_text(fz_context *ctx, fz_device *devp, const fz_text *text, const fz_stroke_state *stroke, const fz_matrix *ctm, const fz_rect *scissor)
+fz_draw_clip_stroke_text(fz_context *ctx, fz_device *devp, const fz_text *text, const fz_stroke_state *stroke, const fz_matrix *in_ctm, const fz_rect *scissor)
{
fz_draw_device *dev = (fz_draw_device*)devp;
+ fz_matrix ctm = concat(in_ctm, &dev->transform);
fz_irect bbox;
fz_pixmap *mask, *dest, *shape;
fz_matrix tm, trm;
@@ -1020,7 +1036,7 @@ fz_draw_clip_stroke_text(fz_context *ctx, fz_device *devp, const fz_text *text,
STACK_PUSHED("clip stroke text");
/* make the mask the exact size needed */
- fz_irect_from_rect(&bbox, fz_bound_text(ctx, text, stroke, ctm, &rect));
+ fz_irect_from_rect(&bbox, fz_bound_text(ctx, text, stroke, &ctm, &rect));
fz_intersect_irect(&bbox, &state->scissor);
if (scissor)
{
@@ -1069,9 +1085,9 @@ fz_draw_clip_stroke_text(fz_context *ctx, fz_device *devp, const fz_text *text,
tm.e = span->items[i].x;
tm.f = span->items[i].y;
- fz_concat(&trm, &tm, ctm);
+ fz_concat(&trm, &tm, &ctm);
- glyph = fz_render_stroked_glyph(ctx, span->font, gid, &trm, ctm, stroke, &state->scissor);
+ glyph = fz_render_stroked_glyph(ctx, span->font, gid, &trm, &ctm, stroke, &state->scissor);
if (glyph)
{
int x = (int)trm.e;
@@ -1095,7 +1111,7 @@ fz_draw_clip_stroke_text(fz_context *ctx, fz_device *devp, const fz_text *text,
state[0].mask = NULL;
fz_try(ctx)
{
- fz_draw_stroke_path(ctx, devp, path, stroke, ctm, fz_device_gray(ctx), &white, 1);
+ fz_draw_stroke_path(ctx, devp, path, stroke, &ctm, fz_device_gray(ctx), &white, 1);
}
fz_always(ctx)
{
@@ -1129,9 +1145,10 @@ fz_draw_ignore_text(fz_context *ctx, fz_device *dev, const fz_text *text, const
}
static void
-fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_matrix *ctm, float alpha)
+fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_matrix *in_ctm, float alpha)
{
fz_draw_device *dev = (fz_draw_device*)devp;
+ fz_matrix ctm = concat(in_ctm, &dev->transform);
fz_rect bounds;
fz_irect bbox, scissor;
fz_pixmap *dest, *shape;
@@ -1140,7 +1157,7 @@ fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_m
fz_draw_state *state = &dev->stack[dev->top];
fz_colorspace *model = state->dest->colorspace;
- fz_bound_shade(ctx, shade, ctm, &bounds);
+ fz_bound_shade(ctx, shade, &ctm, &bounds);
scissor = state->scissor;
fz_intersect_irect(fz_irect_from_rect(&bbox, &bounds), &scissor);
@@ -1200,7 +1217,7 @@ fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_m
}
}
- fz_paint_shade(ctx, shade, ctm, dest, &bbox);
+ fz_paint_shade(ctx, shade, &ctm, dest, &bbox);
if (shape)
fz_clear_pixmap_rect_with_value(ctx, shape, 255, &bbox);
@@ -1292,9 +1309,10 @@ fz_default_image_scale(void *arg, int dst_w, int dst_h, int src_w, int src_h)
}
static void
-fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_matrix *ctm, float alpha)
+fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_matrix *in_ctm, float alpha)
{
fz_draw_device *dev = (fz_draw_device*)devp;
+ fz_matrix local_ctm = concat(in_ctm, &dev->transform);
fz_pixmap *converted = NULL;
fz_pixmap *scaled = NULL;
fz_pixmap *pixmap;
@@ -1304,7 +1322,6 @@ fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_m
fz_draw_state *state = &dev->stack[dev->top];
fz_colorspace *model = state->dest->colorspace;
fz_irect clip;
- fz_matrix local_ctm = *ctm;
fz_matrix inverse;
fz_irect src_area;
@@ -1428,10 +1445,11 @@ fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_m
}
static void
-fz_draw_fill_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const fz_matrix *ctm,
+fz_draw_fill_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const fz_matrix *in_ctm,
fz_colorspace *colorspace, const float *color, float alpha)
{
fz_draw_device *dev = (fz_draw_device*)devp;
+ fz_matrix local_ctm = concat(in_ctm, &dev->transform);
unsigned char colorbv[FZ_MAX_COLORS + 1];
float colorfv[FZ_MAX_COLORS];
fz_pixmap *scaled = NULL;
@@ -1442,7 +1460,6 @@ fz_draw_fill_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const
fz_draw_state *state = &dev->stack[dev->top];
fz_colorspace *model = state->dest->colorspace;
fz_irect clip;
- fz_matrix local_ctm = *ctm;
fz_matrix inverse;
fz_irect src_area;
@@ -1536,9 +1553,10 @@ fz_draw_fill_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const
}
static void
-fz_draw_clip_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const fz_matrix *ctm, const fz_rect *scissor)
+fz_draw_clip_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const fz_matrix *in_ctm, const fz_rect *scissor)
{
fz_draw_device *dev = (fz_draw_device*)devp;
+ fz_matrix local_ctm = concat(in_ctm, &dev->transform);
fz_irect bbox;
fz_pixmap *mask = NULL;
fz_pixmap *dest = NULL;
@@ -1550,7 +1568,6 @@ fz_draw_clip_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const
fz_draw_state *state = push_stack(ctx, dev);
fz_colorspace *model = state->dest->colorspace;
fz_irect clip;
- fz_matrix local_ctm = *ctm;
fz_rect urect;
STACK_PUSHED("clip image mask");
@@ -2067,9 +2084,10 @@ fz_tile_size(fz_context *ctx, tile_record *tile)
}
static int
-fz_draw_begin_tile(fz_context *ctx, fz_device *devp, const fz_rect *area, const fz_rect *view, float xstep, float ystep, const fz_matrix *ctm, int id)
+fz_draw_begin_tile(fz_context *ctx, fz_device *devp, const fz_rect *area, const fz_rect *view, float xstep, float ystep, const fz_matrix *in_ctm, int id)
{
fz_draw_device *dev = (fz_draw_device*)devp;
+ fz_matrix ctm = concat(in_ctm, &dev->transform);
fz_pixmap *dest = NULL;
fz_pixmap *shape;
fz_irect bbox;
@@ -2085,7 +2103,7 @@ fz_draw_begin_tile(fz_context *ctx, fz_device *devp, const fz_rect *area, const
state = push_stack(ctx, dev);
STACK_PUSHED("tile");
- fz_irect_from_rect(&bbox, fz_transform_rect(&local_view, ctm));
+ fz_irect_from_rect(&bbox, fz_transform_rect(&local_view, &ctm));
/* We should never have a bbox that entirely covers our destination.
* If we do, then the check for only 1 tile being visible above has
* failed. Actually, this *can* fail due to the round_rect, at extreme
@@ -2099,10 +2117,10 @@ fz_draw_begin_tile(fz_context *ctx, fz_device *devp, const fz_rect *area, const
{
tile_key tk;
tile_record *tile;
- tk.ctm[0] = ctm->a;
- tk.ctm[1] = ctm->b;
- tk.ctm[2] = ctm->c;
- tk.ctm[3] = ctm->d;
+ tk.ctm[0] = ctm.a;
+ tk.ctm[1] = ctm.b;
+ tk.ctm[2] = ctm.c;
+ tk.ctm[3] = ctm.d;
tk.id = id;
tile = fz_find_item(ctx, fz_drop_tile_record_imp, &tk, &fz_tile_store_type);
@@ -2115,7 +2133,7 @@ fz_draw_begin_tile(fz_context *ctx, fz_device *devp, const fz_rect *area, const
state[1].ystep = ystep;
state[1].id = id;
fz_irect_from_rect(&state[1].area, area);
- state[1].ctm = *ctm;
+ state[1].ctm = ctm;
#ifdef DUMP_GROUP_BLENDS
dump_spaces(dev->top-1, "Tile begin (cached)\n");
#endif
@@ -2142,7 +2160,7 @@ fz_draw_begin_tile(fz_context *ctx, fz_device *devp, const fz_rect *area, const
state[1].ystep = ystep;
state[1].id = id;
fz_irect_from_rect(&state[1].area, area);
- state[1].ctm = *ctm;
+ state[1].ctm = ctm;
#ifdef DUMP_GROUP_BLENDS
dump_spaces(dev->top-1, "Tile begin\n");
#endif
@@ -2354,7 +2372,7 @@ fz_draw_render_flags(fz_context *ctx, fz_device *devp, int set, int clear)
}
fz_device *
-fz_new_draw_device(fz_context *ctx, fz_pixmap *dest)
+fz_new_draw_device(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest)
{
fz_draw_device *dev = fz_new_device(ctx, sizeof *dev);
@@ -2388,6 +2406,7 @@ fz_new_draw_device(fz_context *ctx, fz_pixmap *dest)
dev->super.render_flags = fz_draw_render_flags;
+ dev->transform = transform ? *transform : fz_identity;
dev->flags = 0;
dev->top = 0;
dev->stack = &dev->init_stack[0];
@@ -2417,9 +2436,9 @@ fz_new_draw_device(fz_context *ctx, fz_pixmap *dest)
}
fz_device *
-fz_new_draw_device_with_bbox(fz_context *ctx, fz_pixmap *dest, const fz_irect *clip)
+fz_new_draw_device_with_bbox(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest, const fz_irect *clip)
{
- fz_draw_device *dev = (fz_draw_device*)fz_new_draw_device(ctx, dest);
+ fz_draw_device *dev = (fz_draw_device*)fz_new_draw_device(ctx, transform, dest);
if (clip->x0 > dev->stack[0].scissor.x0)
dev->stack[0].scissor.x0 = clip->x0;
@@ -2434,9 +2453,9 @@ fz_new_draw_device_with_bbox(fz_context *ctx, fz_pixmap *dest, const fz_irect *c
}
fz_device *
-fz_new_draw_device_type3(fz_context *ctx, fz_pixmap *dest)
+fz_new_draw_device_type3(fz_context *ctx, const fz_matrix *transform, fz_pixmap *dest)
{
- fz_draw_device *dev = (fz_draw_device*)fz_new_draw_device(ctx, dest);
+ fz_draw_device *dev = (fz_draw_device*)fz_new_draw_device(ctx, transform, dest);
dev->flags |= FZ_DRAWDEV_FLAGS_TYPE3;
return (fz_device*)dev;
}
diff --git a/source/fitz/font.c b/source/fitz/font.c
index cebccf03..d534212c 100644
--- a/source/fitz/font.c
+++ b/source/fitz/font.c
@@ -1248,7 +1248,7 @@ fz_render_t3_glyph_pixmap(fz_context *ctx, fz_font *font, int gid, const fz_matr
glyph = fz_new_pixmap_with_bbox(ctx, model, &bbox, 1);
fz_clear_pixmap(ctx, glyph);
- dev = fz_new_draw_device_type3(ctx, glyph);
+ dev = fz_new_draw_device_type3(ctx, NULL, glyph);
fz_try(ctx)
{
fz_run_t3_glyph(ctx, font, gid, trm, dev);
diff --git a/source/fitz/image.c b/source/fitz/image.c
index 6f840c38..a027b902 100644
--- a/source/fitz/image.c
+++ b/source/fitz/image.c
@@ -1057,8 +1057,8 @@ display_list_image_get_pixmap(fz_context *ctx, fz_image *image_, fz_irect *subar
fz_pre_scale(&ctm, w, h);
fz_clear_pixmap(ctx, pix); /* clear to transparent */
- dev = fz_new_draw_device(ctx, pix);
- fz_run_display_list(ctx, image->list, dev, &ctm, NULL, NULL);
+ dev = fz_new_draw_device(ctx, &ctm, pix);
+ fz_run_display_list(ctx, image->list, dev, &fz_identity, NULL, NULL);
fz_drop_device(ctx, dev);
/* Never do more subsampling, cos we've already given them the right size */
diff --git a/source/fitz/output-cbz.c b/source/fitz/output-cbz.c
index ba7ca196..80ef287c 100644
--- a/source/fitz/output-cbz.c
+++ b/source/fitz/output-cbz.c
@@ -16,10 +16,10 @@ struct fz_cbz_writer_s
const char *fz_cbz_write_options_usage = "";
static fz_device *
-cbz_begin_page(fz_context *ctx, fz_document_writer *wri_, const fz_rect *mediabox, fz_matrix *transform)
+cbz_begin_page(fz_context *ctx, fz_document_writer *wri_, const fz_rect *mediabox)
{
fz_cbz_writer *wri = (fz_cbz_writer*)wri_;
- return fz_new_draw_device_with_options(ctx, &wri->options, mediabox, transform, &wri->pixmap);
+ return fz_new_draw_device_with_options(ctx, &wri->options, mediabox, &wri->pixmap);
}
static void
diff --git a/source/fitz/output-png.c b/source/fitz/output-png.c
index 00eaeee8..5bd0737e 100644
--- a/source/fitz/output-png.c
+++ b/source/fitz/output-png.c
@@ -312,10 +312,10 @@ struct fz_png_writer_s
const char *fz_png_write_options_usage = "";
static fz_device *
-png_begin_page(fz_context *ctx, fz_document_writer *wri_, const fz_rect *mediabox, fz_matrix *transform)
+png_begin_page(fz_context *ctx, fz_document_writer *wri_, const fz_rect *mediabox)
{
fz_png_writer *wri = (fz_png_writer*)wri_;
- return fz_new_draw_device_with_options(ctx, &wri->options, mediabox, transform, &wri->pixmap);
+ return fz_new_draw_device_with_options(ctx, &wri->options, mediabox, &wri->pixmap);
}
static void
diff --git a/source/fitz/util.c b/source/fitz/util.c
index 01e52e91..425d2181 100644
--- a/source/fitz/util.c
+++ b/source/fitz/util.c
@@ -62,8 +62,8 @@ fz_new_pixmap_from_display_list(fz_context *ctx, fz_display_list *list, const fz
fz_try(ctx)
{
- dev = fz_new_draw_device(ctx, pix);
- fz_run_display_list(ctx, list, dev, ctm, NULL, NULL);
+ dev = fz_new_draw_device(ctx, ctm, pix);
+ fz_run_display_list(ctx, list, dev, &fz_identity, NULL, NULL);
}
fz_always(ctx)
{
@@ -95,8 +95,8 @@ fz_new_pixmap_from_page_contents(fz_context *ctx, fz_page *page, const fz_matrix
fz_try(ctx)
{
- dev = fz_new_draw_device(ctx, pix);
- fz_run_page_contents(ctx, page, dev, ctm, NULL);
+ dev = fz_new_draw_device(ctx, ctm, pix);
+ fz_run_page_contents(ctx, page, dev, &fz_identity, NULL);
}
fz_always(ctx)
{
@@ -128,8 +128,8 @@ fz_new_pixmap_from_annot(fz_context *ctx, fz_annot *annot, const fz_matrix *ctm,
fz_try(ctx)
{
- dev = fz_new_draw_device(ctx, pix);
- fz_run_annot(ctx, annot, dev, ctm, NULL);
+ dev = fz_new_draw_device(ctx, ctm, pix);
+ fz_run_annot(ctx, annot, dev, &fz_identity, NULL);
}
fz_always(ctx)
{
@@ -161,8 +161,8 @@ fz_new_pixmap_from_page(fz_context *ctx, fz_page *page, const fz_matrix *ctm, fz
fz_try(ctx)
{
- dev = fz_new_draw_device(ctx, pix);
- fz_run_page(ctx, page, dev, ctm, NULL);
+ dev = fz_new_draw_device(ctx, ctm, pix);
+ fz_run_page(ctx, page, dev, &fz_identity, NULL);
}
fz_always(ctx)
{
diff --git a/source/fitz/writer.c b/source/fitz/writer.c
index 5c82b1d7..556e01a8 100644
--- a/source/fitz/writer.c
+++ b/source/fitz/writer.c
@@ -81,9 +81,9 @@ fz_drop_document_writer(fz_context *ctx, fz_document_writer *wri)
}
fz_device *
-fz_begin_page(fz_context *ctx, fz_document_writer *wri, const fz_rect *mediabox, fz_matrix *ctm)
+fz_begin_page(fz_context *ctx, fz_document_writer *wri, const fz_rect *mediabox)
{
- return wri->begin_page(ctx, wri, mediabox, ctm);
+ return wri->begin_page(ctx, wri, mediabox);
}
void
diff --git a/source/pdf/pdf-write.c b/source/pdf/pdf-write.c
index 8d0f6f58..1dce7235 100644
--- a/source/pdf/pdf-write.c
+++ b/source/pdf/pdf-write.c
@@ -3204,11 +3204,10 @@ struct pdf_writer_s
};
static fz_device *
-pdf_writer_begin_page(fz_context *ctx, fz_document_writer *wri_, const fz_rect *mediabox, fz_matrix *ctm)
+pdf_writer_begin_page(fz_context *ctx, fz_document_writer *wri_, const fz_rect *mediabox)
{
pdf_writer *wri = (pdf_writer*)wri_;
wri->mediabox = *mediabox;
- *ctm = fz_identity;
return pdf_page_write(ctx, wri->pdf, &wri->mediabox, &wri->resources, &wri->contents);
}
diff --git a/source/tools/muconvert.c b/source/tools/muconvert.c
index 3fd97cfd..95f01c4a 100644
--- a/source/tools/muconvert.c
+++ b/source/tools/muconvert.c
@@ -54,15 +54,14 @@ static void usage(void)
static void runpage(int number)
{
- fz_matrix ctm;
fz_rect mediabox;
fz_page *page;
fz_device *dev;
page = fz_load_page(ctx, doc, number - 1);
fz_bound_page(ctx, page, &mediabox);
- dev = fz_begin_page(ctx, out, &mediabox, &ctm);
- fz_run_page(ctx, page, dev, &ctm, NULL);
+ dev = fz_begin_page(ctx, out, &mediabox);
+ fz_run_page(ctx, page, dev, &fz_identity, NULL);
fz_end_page(ctx, out, dev);
fz_drop_page(ctx, page);
}
diff --git a/source/tools/mudraw.c b/source/tools/mudraw.c
index 6c27fc28..20a6524d 100644
--- a/source/tools/mudraw.c
+++ b/source/tools/mudraw.c
@@ -545,13 +545,13 @@ static void drawband(fz_context *ctx, fz_page *page, fz_display_list *list, cons
else
fz_clear_pixmap_with_value(ctx, pix, 255);
- dev = fz_new_draw_device(ctx, pix);
+ dev = fz_new_draw_device(ctx, ctm, pix);
if (lowmemory)
fz_enable_device_hints(ctx, dev, FZ_NO_CACHE);
if (alphabits_graphics == 0)
fz_enable_device_hints(ctx, dev, FZ_DONT_INTERPOLATE_IMAGES);
if (list)
- fz_run_display_list(ctx, list, dev, ctm, tbounds, cookie);
+ fz_run_display_list(ctx, list, dev, &fz_identity, tbounds, cookie);
else
fz_run_page(ctx, page, dev, ctm, cookie);
fz_drop_device(ctx, dev);
diff --git a/source/tools/murun.c b/source/tools/murun.c
index 6d14f99f..e9d66742 100644
--- a/source/tools/murun.c
+++ b/source/tools/murun.c
@@ -306,16 +306,6 @@ static void ffi_pushmatrix(js_State *J, fz_matrix matrix)
js_pushnumber(J, matrix.f); js_setindex(J, -2, 5);
}
-static void ffi_setmatrix(js_State *J, int idx, fz_matrix matrix)
-{
- js_pushnumber(J, matrix.a); js_setindex(J, idx, 0);
- js_pushnumber(J, matrix.b); js_setindex(J, idx, 1);
- js_pushnumber(J, matrix.c); js_setindex(J, idx, 2);
- js_pushnumber(J, matrix.d); js_setindex(J, idx, 3);
- js_pushnumber(J, matrix.e); js_setindex(J, idx, 4);
- js_pushnumber(J, matrix.f); js_setindex(J, idx, 5);
-}
-
static fz_rect ffi_torect(js_State *J, int idx)
{
fz_rect rect;
@@ -2117,11 +2107,12 @@ static void ffi_new_DisplayListDevice(js_State *J)
static void ffi_new_DrawDevice(js_State *J)
{
fz_context *ctx = js_getcontext(J);
- fz_pixmap *pixmap = js_touserdata(J, 1, "fz_pixmap");
+ fz_matrix transform = ffi_tomatrix(J, 1);
+ fz_pixmap *pixmap = js_touserdata(J, 2, "fz_pixmap");
fz_device *device;
fz_try(ctx)
- device = fz_new_draw_device(ctx, pixmap);
+ device = fz_new_draw_device(ctx, &transform, pixmap);
fz_catch(ctx)
rethrow(J);
@@ -2151,16 +2142,13 @@ static void ffi_DocumentWriter_beginPage(js_State *J)
fz_context *ctx = js_getcontext(J);
fz_document_writer *wri = js_touserdata(J, 0, "fz_document_writer");
fz_rect mediabox = ffi_torect(J, 1);
- fz_matrix ctm = fz_identity;
fz_device *device;
fz_try(ctx)
- device = fz_begin_page(ctx, wri, &mediabox, &ctm);
+ device = fz_begin_page(ctx, wri, &mediabox);
fz_catch(ctx)
rethrow(J);
- ffi_setmatrix(J, 2, ctm);
-
js_getregistry(J, "fz_device");
js_newuserdata(J, "fz_device", fz_keep_device(ctx, device), ffi_gc_fz_device);
}
@@ -3253,7 +3241,7 @@ int murun_main(int argc, char **argv)
js_newobject(J);
{
- jsB_propfun(J, "DocumentWriter.beginPage", ffi_DocumentWriter_beginPage, 2);
+ jsB_propfun(J, "DocumentWriter.beginPage", ffi_DocumentWriter_beginPage, 1);
jsB_propfun(J, "DocumentWriter.endPage", ffi_DocumentWriter_endPage, 1);
jsB_propfun(J, "DocumentWriter.close", ffi_DocumentWriter_close, 1);
}
@@ -3335,7 +3323,7 @@ int murun_main(int argc, char **argv)
jsB_propcon(J, "fz_text", "Text", ffi_new_Text, 0);
jsB_propcon(J, "fz_path", "Path", ffi_new_Path, 0);
jsB_propcon(J, "fz_display_list", "DisplayList", ffi_new_DisplayList, 0);
- jsB_propcon(J, "fz_device", "DrawDevice", ffi_new_DrawDevice, 1);
+ jsB_propcon(J, "fz_device", "DrawDevice", ffi_new_DrawDevice, 2);
jsB_propcon(J, "fz_device", "DisplayListDevice", ffi_new_DisplayListDevice, 1);
jsB_propcon(J, "fz_document_writer", "DocumentWriter", ffi_new_DocumentWriter, 3);