From 96cc776650a1845f4b3894c2311bee4d51d60f20 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Tue, 3 Jul 2018 15:07:25 +0200 Subject: Add fz_transform_page helper function. Create a matrix that transforms a page with resolution and rotation, and grid fits the resulting bounding box. --- include/mupdf/fitz/geometry.h | 8 ++++++ platform/gl/gl-main.c | 16 ++--------- platform/x11/pdfapp.c | 2 +- source/fitz/draw-device.c | 64 +++++++++++++++++++------------------------ source/fitz/geometry.c | 23 ++++++++++++++++ 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 @@ -416,6 +416,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. 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 @@ -210,6 +210,29 @@ fz_pre_translate(fz_matrix m, float tx, float ty) return m; } +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) { -- cgit v1.2.3