From 479215d0ee6d05a36faa01dff2116a44cf729f30 Mon Sep 17 00:00:00 2001 From: Carlos Pita Date: Fri, 25 Oct 2019 22:04:11 -0300 Subject: [PATCH] Support hidpi screens with cairo Add hidpi support for fringe bitmaps and images. Although the framework is general, this commit only implements support for cairo. * src/frame.h (struct frame): Add fields `scale_x' and `scale_y'. (FRAME_LEFT_FRINGE_WIDTH, FRAME_RIGHT_FRINGE_WIDTH): Scale widths. * src/fringe.c (draw_fringe_bitmap_1): Scale bitmap width and height. * src/image.c (lookup_image, xbm_load, xpm_load, pbm_load) (png_load_body, jpeg_load_body, tiff_load, gif_load) (imagemagick_load, svg_load, gs_load): Scale images width and height. * src/nsfns.m (Fx_create_frame): Initialize scale factors to 1. * src/w32fns.c (Fx_create_frame): Initialize scale factors using a base of 96dpi. * src/w32term.c (w32_get_scale_factor): Remove function. (w32_draw_underwave): Use new `scale_x' and `scale_y' fields. * src/window.h (WINDOW_LEFT_FRINGE_WIDTH, WINDOW_RIGHT_FRINGE_WIDTH): Scale widths. * src/xfns.c (Fx_create_frame): Initialize scale factors using a base of 96dpi. * src/xterm.c (x_cr_draw_image): Set surface scale before drawing. (x_get_scale_factor): Remove function. (x_draw_underwave): Use new `scale_x' and `scale_y' fields. --- src/frame.h | 7 +++++-- src/fringe.c | 4 ++-- src/image.c | 40 ++++++++++++++++++++++++++++++++++++++++ src/nsfns.m | 2 ++ src/w32fns.c | 3 +++ src/w32term.c | 19 +------------------ src/window.h | 12 ++++++------ src/xfns.c | 3 +++ src/xterm.c | 25 +++---------------------- 9 files changed, 65 insertions(+), 50 deletions(-) diff --git a/src/frame.h b/src/frame.h index f408f12394..aa3685c213 100644 --- a/src/frame.h +++ b/src/frame.h @@ -636,6 +636,9 @@ #define EMACS_FRAME_H unsigned long background_pixel; unsigned long foreground_pixel; + /* Factors used to scale pixel geometries. */ + double scale_x, scale_y; + #ifdef NS_IMPL_COCOA /* NSAppearance theme used on this frame. */ enum ns_appearance_type ns_appearance; @@ -1415,12 +1418,12 @@ FRAME_FRINGE_COLS (struct frame *f) INLINE int FRAME_LEFT_FRINGE_WIDTH (struct frame *f) { - return frame_dimension (f->left_fringe_width); + return frame_dimension (f->left_fringe_width) * f->scale_x; } INLINE int FRAME_RIGHT_FRINGE_WIDTH (struct frame *f) { - return frame_dimension (f->right_fringe_width); + return frame_dimension (f->right_fringe_width) * f->scale_x; } /* Total width of fringes in pixels. */ diff --git a/src/fringe.c b/src/fringe.c index d878d929cc..807c7803c8 100644 --- a/src/fringe.c +++ b/src/fringe.c @@ -602,9 +602,9 @@ draw_fringe_bitmap_1 (struct window *w, struct glyph_row *row, int left_p, int o p.which = which; p.bits = fb->bits; - p.wd = fb->width; + p.wd = fb->width * f->scale_x; - p.h = fb->height; + p.h = fb->height * f->scale_y; p.dh = (period > 0 ? (p.y % period) : 0); p.h -= p.dh; diff --git a/src/image.c b/src/image.c index 08e420837a..1a7324b406 100644 --- a/src/image.c +++ b/src/image.c @@ -2304,6 +2304,8 @@ lookup_image (struct frame *f, Lisp_Object spec) value = image_spec_value (spec, QCheight, NULL); img->height = (FIXNUMP (value) ? XFIXNAT (value) : DEFAULT_IMAGE_HEIGHT); + img->width *= f->scale_x; + img->height *= f->scale_y; } else { @@ -3792,6 +3794,9 @@ xbm_load (struct frame *f, struct image *img) } } + img->width *= f->scale_x; + img->height *= f->scale_y; + return success_p; } @@ -4472,6 +4477,10 @@ xpm_load (struct frame *f, struct image *img) xpm_free_color_cache (); #endif SAFE_FREE (); + + img->width *= f->scale_x; + img->height *= f->scale_y; + return rc == XpmSuccess; } @@ -4951,6 +4960,9 @@ xpm_load (struct frame *f, SSDATA (data) + SBYTES (data)); } + img->width *= f->scale_x; + img->height *= f->scale_y; + return success_p; } @@ -6168,6 +6180,10 @@ pbm_load (struct frame *f, struct image *img) img->height = height; */ xfree (contents); + + img->width *= f->scale_x; + img->height *= f->scale_y; + return 1; } @@ -6810,6 +6826,9 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c) image_put_x_image (f, img, mask_img, 1); } + img->width *= f->scale_x; + img->height *= f->scale_y; + return 1; } @@ -7383,6 +7402,10 @@ jpeg_load_body (struct frame *f, struct image *img, /* Put ximg into the image. */ image_put_x_image (f, img, ximg, 0); SAFE_FREE (); + + img->width *= f->scale_x; + img->height *= f->scale_y; + return 1; } @@ -7831,6 +7854,10 @@ tiff_load (struct frame *f, struct image *img) image_put_x_image (f, img, ximg, 0); xfree (buf); + + img->width *= f->scale_x; + img->height *= f->scale_y; + return 1; } @@ -8428,6 +8455,9 @@ gif_load (struct frame *f, struct image *img) /* Put ximg into the image. */ image_put_x_image (f, img, ximg, 0); + img->width *= f->scale_x; + img->height *= f->scale_y; + return 1; } @@ -9214,6 +9244,9 @@ imagemagick_load (struct frame *f, struct image *img) SBYTES (data), NULL); } + img->width *= f->scale_x; + img->height *= f->scale_y; + return success_p; } @@ -9538,6 +9571,9 @@ svg_load (struct frame *f, struct image *img) : SSDATA (original_filename))); } + img->width *= f->scale_x; + img->height *= f->scale_y; + return success_p; } @@ -9886,6 +9922,10 @@ gs_load (struct frame *f, struct image *img) make_fixnum (img->height), window_and_pixmap_id, pixel_colors); + + img->width *= f->scale_x; + img->height *= f->scale_y; + return PROCESSP (img->lisp_data); } diff --git a/src/nsfns.m b/src/nsfns.m index 184fd71678..028b0eaf13 100644 --- a/src/nsfns.m +++ b/src/nsfns.m @@ -1121,6 +1121,8 @@ Turn the input menu (an NSMenu) into a lisp list for tracking on lisp side. else f = make_frame (1); + f->scale_x = f->scale_y = 1; + XSETFRAME (frame, f); f->terminal = dpyinfo->terminal; diff --git a/src/w32fns.c b/src/w32fns.c index 4ef075f715..3f827be89c 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -5866,6 +5866,9 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, else f = make_frame (true); + f->scale_x = dpyinfo->resx / 96; + f->scale_y = dpyinfo->resy / 96; + XSETFRAME (frame, f); parent_frame = gui_display_get_arg (dpyinfo, parameters, Qparent_frame, diff --git a/src/w32term.c b/src/w32term.c index 888b7368d2..1d746500ee 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -304,22 +304,6 @@ w32_restore_glyph_string_clip (struct glyph_string *s) } } -static void -w32_get_scale_factor(struct w32_display_info *dpyinfo, int *scale_x, int *scale_y) -{ - const int base_res = 96; - - *scale_x = *scale_y = 1; - - if (dpyinfo) - { - if (dpyinfo->resx > base_res) - *scale_x = floor (dpyinfo->resx / base_res); - if (dpyinfo->resy > base_res) - *scale_y = floor (dpyinfo->resy / base_res); - } -} - /* Draw a wavy line under S. The wave fills wave_height pixels from y0. @@ -336,8 +320,7 @@ w32_draw_underwave (struct glyph_string *s, COLORREF color) { struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (s->f); - int scale_x, scale_y; - w32_get_scale_factor (dpyinfo, &scale_x, &scale_y); + double scale_x = s->f->scale_x, scale_y = s->f->scale_y; int wave_height = 3 * scale_y, wave_length = 2 * scale_x, thickness = scale_y; int dx, dy, x0, y0, width, x1, y1, x2, y2, odd, xmax; diff --git a/src/window.h b/src/window.h index 71946a5695..07e24551f0 100644 --- a/src/window.h +++ b/src/window.h @@ -828,14 +828,14 @@ #define WINDOW_MARGINS_WIDTH(W) \ + WINDOW_RIGHT_MARGIN_WIDTH (W)) /* Pixel-widths of fringes. */ -#define WINDOW_LEFT_FRINGE_WIDTH(W) \ - (W->left_fringe_width >= 0 \ - ? W->left_fringe_width \ +#define WINDOW_LEFT_FRINGE_WIDTH(W) \ + (W->left_fringe_width >= 0 \ + ? (W->left_fringe_width * WINDOW_XFRAME (W)->scale_x) \ : FRAME_LEFT_FRINGE_WIDTH (WINDOW_XFRAME (W))) -#define WINDOW_RIGHT_FRINGE_WIDTH(W) \ - (W->right_fringe_width >= 0 \ - ? W->right_fringe_width \ +#define WINDOW_RIGHT_FRINGE_WIDTH(W) \ + (W->right_fringe_width >= 0 \ + ? (W->right_fringe_width * WINDOW_XFRAME (W)->scale_x) \ : FRAME_RIGHT_FRINGE_WIDTH (WINDOW_XFRAME (W))) #define WINDOW_FRINGES_WIDTH(W) \ diff --git a/src/xfns.c b/src/xfns.c index 20e63a2650..3970fe3dda 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -3736,6 +3736,9 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, else f = make_frame (true); + f->scale_x = dpyinfo->resx / 96; + f->scale_y = dpyinfo->resy / 96; + parent_frame = gui_display_get_arg (dpyinfo, parms, Qparent_frame, diff --git a/src/xterm.c b/src/xterm.c index 05d6a214dd..c34670aba2 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -635,6 +635,7 @@ x_cr_draw_image (struct frame *f, GC gc, cairo_pattern_t *image, cairo_surface_t *surface; cairo_pattern_get_surface (image, &surface); + cairo_surface_set_device_scale (surface, 1. / f->scale_x, 1. / f->scale_y); cairo_format_t format = cairo_image_surface_get_format (surface); if (format != CAIRO_FORMAT_A8 && format != CAIRO_FORMAT_A1) { @@ -3663,23 +3664,6 @@ x_draw_stretch_glyph_string (struct glyph_string *s) s->background_filled_p = true; } -static void -x_get_scale_factor(Display *disp, int *scale_x, int *scale_y) -{ - const int base_res = 96; - struct x_display_info * dpyinfo = x_display_info_for_display (disp); - - *scale_x = *scale_y = 1; - - if (dpyinfo) - { - if (dpyinfo->resx > base_res) - *scale_x = floor (dpyinfo->resx / base_res); - if (dpyinfo->resy > base_res) - *scale_y = floor (dpyinfo->resy / base_res); - } -} - /* Draw a wavy line under S. The wave fills wave_height pixels from y0. @@ -3693,12 +3677,8 @@ x_get_scale_factor(Display *disp, int *scale_x, int *scale_y) static void x_draw_underwave (struct glyph_string *s) { - Display *display = FRAME_X_DISPLAY (s->f); - /* Adjust for scale/HiDPI. */ - int scale_x, scale_y; - - x_get_scale_factor (display, &scale_x, &scale_y); + double scale_x = s->f->scale_x, scale_y = s->f->scale_y; int wave_height = 3 * scale_y, wave_length = 2 * scale_x; @@ -3709,6 +3689,7 @@ x_draw_underwave (struct glyph_string *s) int dx, dy, x0, y0, width, x1, y1, x2, y2, xmax, thickness = scale_y;; bool odd; XRectangle wave_clip, string_clip, final_clip; + Display *display = FRAME_X_DISPLAY (s->f); dx = wave_length; dy = wave_height - 1; -- 2.20.1