summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2018-07-03 15:07:25 +0200
committerTor Andersson <tor.andersson@artifex.com>2018-07-05 15:32:35 +0200
commit96cc776650a1845f4b3894c2311bee4d51d60f20 (patch)
treee3adedbb6577e9e0509b203c721c038f01019efe
parent2f698870f3ec77050694a9731a2a7ecc1b2962dd (diff)
downloadmupdf-96cc776650a1845f4b3894c2311bee4d51d60f20.tar.xz
Add fz_transform_page helper function.
Create a matrix that transforms a page with resolution and rotation, and grid fits the resulting bounding box.
-rw-r--r--include/mupdf/fitz/geometry.h8
-rw-r--r--platform/gl/gl-main.c16
-rw-r--r--platform/x11/pdfapp.c2
-rw-r--r--source/fitz/draw-device.c64
-rw-r--r--source/fitz/geometry.c23
5 files changed, 63 insertions, 50 deletions
diff --git a/include/mupdf/fitz/geometry.h b/include/mupdf/fitz/geometry.h
index 04abf5b9..0eb0f844 100644
--- a/include/mupdf/fitz/geometry.h
+++ b/include/mupdf/fitz/geometry.h
@@ -417,6 +417,14 @@ fz_matrix fz_translate(float tx, float ty);
fz_matrix fz_pre_translate(fz_matrix m, float tx, float ty);
/*
+ fz_transform_page: Create transform matrix to draw page
+ at a given resolution and rotation. Adjusts the scaling
+ factors so that the page covers whole number of
+ pixels and adjust the page origin to be at 0,0.
+*/
+fz_matrix fz_transform_page(fz_rect mediabox, float resolution, float rotate);
+
+/*
fz_invert_matrix: Create an inverse matrix.
inverse: Place to store inverse matrix.
diff --git a/platform/gl/gl-main.c b/platform/gl/gl-main.c
index 5c42c482..46566f2f 100644
--- a/platform/gl/gl-main.c
+++ b/platform/gl/gl-main.c
@@ -207,17 +207,7 @@ void update_title(void)
void transform_page(void)
{
- fz_rect rect;
- fz_matrix matrix;
-
- draw_page_ctm = fz_scale(currentzoom / 72, currentzoom / 72);
- draw_page_ctm = fz_pre_rotate(draw_page_ctm, -currentrotate);
-
- /* fix the page origin at 0,0 after rotation */
- rect = fz_transform_rect(page_bounds, draw_page_ctm);
- matrix = fz_translate(-rect.x0, -rect.y0);
- draw_page_ctm = fz_concat(draw_page_ctm, matrix);
-
+ draw_page_ctm = fz_transform_page(page_bounds, currentzoom, currentrotate);
draw_page_bounds = fz_transform_rect(page_bounds, draw_page_ctm);
}
@@ -846,8 +836,8 @@ static void do_app(void)
case 'z': set_zoom(number > 0 ? number : DEFRES, canvas_w/2, canvas_h/2); break;
case '+': set_zoom(zoom_in(currentzoom), ui.x, ui.y); break;
case '-': set_zoom(zoom_out(currentzoom), ui.x, ui.y); break;
- case '[': currentrotate += 90; break;
- case ']': currentrotate -= 90; break;
+ case '[': currentrotate -= 90; break;
+ case ']': currentrotate += 90; break;
case 'k': case KEY_UP: scroll_y -= 10; break;
case 'j': case KEY_DOWN: scroll_y += 10; break;
case 'h': case KEY_LEFT: scroll_x -= 10; break;
diff --git a/platform/x11/pdfapp.c b/platform/x11/pdfapp.c
index a12cb4c1..707fa689 100644
--- a/platform/x11/pdfapp.c
+++ b/platform/x11/pdfapp.c
@@ -605,7 +605,7 @@ int pdfapp_preclose(pdfapp_t *app)
static void pdfapp_viewctm(fz_matrix *mat, pdfapp_t *app)
{
- *mat = fz_pre_rotate(fz_scale(app->resolution/72.0f, app->resolution/72.0f), app->rotate);
+ *mat = fz_transform_page(app->page_bbox, app->resolution, app->rotate);
}
static void pdfapp_panview(pdfapp_t *app, int newx, int newy)
diff --git a/source/fitz/draw-device.c b/source/fitz/draw-device.c
index 21e898c0..37210af8 100644
--- a/source/fitz/draw-device.c
+++ b/source/fitz/draw-device.c
@@ -3217,52 +3217,44 @@ 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, fz_rect mediabox, fz_pixmap **pixmap)
{
+ fz_aa_context aa = *ctx->aa;
float x_zoom = opts->x_resolution / 72.0f;
float y_zoom = opts->y_resolution / 72.0f;
- int w = opts->width;
- int h = opts->height;
- fz_rect bounds;
- fz_irect ibounds;
+ float page_w = mediabox.x1 - mediabox.x0;
+ float page_h = mediabox.y1 - mediabox.y0;
+ float w = opts->width;
+ float h = opts->height;
+ float x_scale, y_scale;
fz_matrix transform;
- fz_device *dev = NULL;
- fz_aa_context aa = *ctx->aa;
+ fz_irect bbox;
+ fz_device *dev;
fz_set_rasterizer_graphics_aa_level(ctx, &aa, opts->graphics);
fz_set_rasterizer_text_aa_level(ctx, &aa, opts->text);
- transform = fz_pre_rotate(fz_scale(x_zoom, y_zoom), opts->rotate);
- bounds = mediabox;
- ibounds = fz_round_rect(fz_transform_rect(bounds, transform));
-
- /* If width or height are set, we may need to adjust the transform */
- if (w || h)
+ if (w > 0)
{
- float scalex = 1;
- float scaley = 1;
- if (w != 0)
- scalex = w / (bounds.x1 - bounds.x0);
- if (h != 0)
- scaley = h / (bounds.y1 - bounds.y0);
- if (scalex != scaley)
- {
- if (w == 0)
- scalex = scaley;
- else if (h == 0)
- scaley = scalex;
- else if (scalex > scaley)
- scalex = scaley;
- else
- scaley = scalex;
- }
- if (scalex != 1 || scaley != 1)
- {
- transform = fz_pre_scale(transform, scalex, scaley);
- bounds = mediabox;
- ibounds = fz_round_rect(fz_transform_rect(bounds, transform));
- }
+ x_scale = w / page_w;
+ if (h > 0)
+ y_scale = h / page_h;
+ else
+ y_scale = floorf(page_h * x_scale + 0.5f) / page_h;
+ }
+ else if (h > 0)
+ {
+ y_scale = h / page_h;
+ x_scale = floorf(page_w * y_scale + 0.5f) / page_w;
}
+ else
+ {
+ x_scale = floorf(page_w * x_zoom + 0.5f) / page_w;
+ y_scale = floorf(page_h * y_zoom + 0.5f) / page_h;
+ }
+
+ transform = fz_pre_rotate(fz_scale(x_scale, y_scale), opts->rotate);
+ bbox = fz_irect_from_rect(fz_transform_rect(mediabox, transform));
- *pixmap = fz_new_pixmap_with_bbox(ctx, opts->colorspace, ibounds, NULL/* FIXME */, opts->alpha);
+ *pixmap = fz_new_pixmap_with_bbox(ctx, opts->colorspace, bbox, NULL, opts->alpha);
fz_try(ctx)
{
fz_set_pixmap_resolution(ctx, *pixmap, opts->x_resolution, opts->y_resolution);
diff --git a/source/fitz/geometry.c b/source/fitz/geometry.c
index e31a9435..96a46102 100644
--- a/source/fitz/geometry.c
+++ b/source/fitz/geometry.c
@@ -211,6 +211,29 @@ fz_pre_translate(fz_matrix m, float tx, float ty)
}
fz_matrix
+fz_transform_page(fz_rect mediabox, float resolution, float rotate)
+{
+ float user_w, user_h, pixel_w, pixel_h;
+ fz_rect pixel_box;
+ fz_matrix matrix;
+
+ /* Adjust scaling factors to cover whole pixels */
+ user_w = mediabox.x1 - mediabox.x0;
+ user_h = mediabox.y1 - mediabox.y0;
+ pixel_w = floorf(user_w * resolution / 72 + 0.5f);
+ pixel_h = floorf(user_h * resolution / 72 + 0.5f);
+
+ matrix = fz_pre_rotate(fz_scale(pixel_w / user_w, pixel_h / user_h), rotate);
+
+ /* Adjust the page origin to sit at 0,0 after rotation */
+ pixel_box = fz_transform_rect(mediabox, matrix);
+ matrix.e -= pixel_box.x0;
+ matrix.f -= pixel_box.y0;
+
+ return matrix;
+}
+
+fz_matrix
fz_invert_matrix(fz_matrix src)
{
float a = src.a;