From 613c61abb44e49236a893376764eb21702c0ef32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 25 Jul 2023 15:56:30 +0200 Subject: [PATCH] scaling: always round the scaling factor when converting to int * In all calls to wl_subsurface_set_position() * (wp_viewport_set_destination() already does this) * Whenever we use the scale to calculate margins (search box, scrollback indicator etc) * Since the scaling factor is stored as a float (and not a double), use roundf() instead of round() --- csi.c | 12 +++--- render.c | 113 ++++++++++++++++++++++++++++++++--------------------- terminal.c | 28 ++++++++----- terminal.h | 1 + wayland.c | 30 +++++--------- 5 files changed, 104 insertions(+), 80 deletions(-) diff --git a/csi.c b/csi.c index 153a1099..959c913d 100644 --- a/csi.c +++ b/csi.c @@ -1208,8 +1208,8 @@ csi_dispatch(struct terminal *term, uint8_t final) char reply[64]; size_t n = xsnprintf( reply, sizeof(reply), "\033[4;%d;%dt", - (int)round(height / term->scale), - (int)(width / term->scale)); + (int)roundf(height / term->scale), + (int)roundf((width / term->scale))); term_to_slave(term, reply, n); } break; @@ -1233,8 +1233,8 @@ csi_dispatch(struct terminal *term, uint8_t final) char reply[64]; size_t n = xsnprintf( reply, sizeof(reply), "\033[6;%d;%dt", - (int)round(term->cell_height / term->scale), - (int)round(term->cell_width / term->scale)); + (int)roundf(term->cell_height / term->scale), + (int)roundf(term->cell_width / term->scale)); term_to_slave(term, reply, n); break; } @@ -1252,8 +1252,8 @@ csi_dispatch(struct terminal *term, uint8_t final) char reply[64]; size_t n = xsnprintf( reply, sizeof(reply), "\033[9;%d;%dt", - (int)round(it->item->dim.px_real.height / term->cell_height / term->scale), - (int)round(it->item->dim.px_real.width / term->cell_width / term->scale)); + (int)roundf(it->item->dim.px_real.height / term->cell_height / term->scale), + (int)roundf(it->item->dim.px_real.width / term->cell_width / term->scale)); term_to_slave(term, reply, n); break; } diff --git a/render.c b/render.c index 9c37f765..847e57e3 100644 --- a/render.c +++ b/render.c @@ -306,7 +306,7 @@ static void draw_unfocused_block(const struct terminal *term, pixman_image_t *pix, const pixman_color_t *color, int x, int y, int cell_cols) { - const int scale = round(term->scale); + const int scale = (int)roundf(term->scale); const int width = min(min(scale, term->cell_width), term->cell_height); pixman_image_fill_rectangles( @@ -2022,8 +2022,8 @@ render_csd_border(struct terminal *term, enum csd_surface surf_idx, */ float scale = term->scale; - int bwidth = round(term->conf->csd.border_width * scale); - int vwidth = round(term->conf->csd.border_width_visible * scale); /* Visible size */ + int bwidth = (int)roundf(term->conf->csd.border_width * scale); + int vwidth = (int)roundf(term->conf->csd.border_width_visible * scale); /* Visible size */ xassert(bwidth >= vwidth); @@ -2396,7 +2396,10 @@ render_csd(struct terminal *term) widths[i] = width; heights[i] = height; - wl_subsurface_set_position(sub, x / term->scale, y / term->scale); + wl_subsurface_set_position( + sub, + (int32_t)roundf(x / term->scale), + (int32_t)roundf(y / term->scale)); } struct buffer *bufs[CSD_SURF_COUNT]; @@ -2487,7 +2490,7 @@ render_scrollback_position(struct terminal *term) char lineno_str[64]; snprintf(lineno_str, sizeof(lineno_str), "%d", rebased_view + 1); mbstoc32(_text, lineno_str, ALEN(_text)); - cell_count = ceil(log10(term->grid->num_rows)); + cell_count = (int)ceilf(log10f(term->grid->num_rows)); break; } @@ -2497,13 +2500,16 @@ render_scrollback_position(struct terminal *term) break; } - const int scale = term->scale; - const int margin = 3 * scale; + const int iscale = (int)ceilf(term->scale); + const int margin = (int)roundf(3. * term->scale); - const int width = - (2 * margin + cell_count * term->cell_width + scale - 1) / scale * scale; - const int height = - (2 * margin + term->cell_height + scale - 1) / scale * scale; + int width = margin + cell_count * term->cell_width + margin; + int height = margin + term->cell_height + margin; + + if (!term_fractional_scaling(term)) { + width = (width + iscale - 1) / iscale * iscale; + height = (height + iscale - 1) / iscale * iscale; + } /* *Where* to render - parent relative coordinates */ int surf_top = 0; @@ -2531,8 +2537,13 @@ render_scrollback_position(struct terminal *term) } } - const int x = (term->width - margin - width) / scale * scale; - const int y = (term->margins.top + surf_top) / scale * scale; + int x = term->width - margin - width; + int y = term->margins.top + surf_top; + + if (!term_fractional_scaling(term)) { + x = (x + iscale - 1) / iscale * iscale; + y = (y + iscale - 1) / iscale * iscale; + } if (y + height > term->height) { wl_surface_attach(win->scrollback_indicator.surface.surf, NULL, 0, 0); @@ -2544,7 +2555,9 @@ render_scrollback_position(struct terminal *term) struct buffer *buf = shm_get_buffer(chain, width, height); wl_subsurface_set_position( - win->scrollback_indicator.sub, x / scale, y / scale); + win->scrollback_indicator.sub, + (int32_t)roundf(x / term->scale), + (int32_t)roundf(y / term->scale)); uint32_t fg = term->colors.table[0]; uint32_t bg = term->colors.table[8 + 4]; @@ -2573,21 +2586,25 @@ render_render_timer(struct terminal *term, struct timespec render_time) char32_t text[256]; mbstoc32(text, usecs_str, ALEN(text)); - const int scale = round(term->scale); + const int iscale = (int)ceilf(term->scale); const int cell_count = c32len(text); - const int margin = 3 * scale; - const int width = - (2 * margin + cell_count * term->cell_width + scale - 1) / scale * scale; - const int height = - (2 * margin + term->cell_height + scale - 1) / scale * scale; + const int margin = (int)roundf(3. * term->scale); + + int width = margin + cell_count * term->cell_width + margin; + int height = margin + term->cell_height + margin; + + if (!term_fractional_scaling(term)) { + width = (width + iscale - 1) / iscale * iscale; + height = (height + iscale - 1) / iscale * iscale; + } struct buffer_chain *chain = term->render.chains.render_timer; struct buffer *buf = shm_get_buffer(chain, width, height); wl_subsurface_set_position( win->render_timer.sub, - margin / term->scale, - (term->margins.top + term->cell_height - margin) / term->scale); + (int32_t)roundf(margin / term->scale), + (int32_t)roundf((term->margins.top + term->cell_height - margin) / term->scale)); render_osd( term, @@ -3132,19 +3149,24 @@ render_search_box(struct terminal *term) const size_t total_cells = c32swidth(text, text_len); const size_t wanted_visible_cells = max(20, total_cells); - xassert(term->scale >= 1); - const int rounded_scale = round(term->scale); - - const size_t margin = 3 * rounded_scale; + xassert(term->scale >= 1.); + const size_t margin = (size_t)roundf(3 * term->scale); const size_t width = term->width - 2 * margin; - const size_t visible_width = min( + size_t visible_width = min( term->width - 2 * margin, - (2 * margin + wanted_visible_cells * term->cell_width + rounded_scale - 1) / rounded_scale * rounded_scale); - const size_t height = min( - term->height - 2 * margin, - (2 * margin + 1 * term->cell_height + rounded_scale - 1) / rounded_scale * rounded_scale); + margin + wanted_visible_cells * term->cell_width + margin); + size_t height = min( + term->height - 2 * margin, + margin + 1 * term->cell_height + margin); + + if (!term_fractional_scaling(term)) { + const int iscale = (int)ceilf(term->scale); + visible_width = (visible_width + iscale - 1) / iscale * iscale; + height = (height + iscale - 1) / iscale * iscale; + } + const size_t visible_cells = (visible_width - 2 * margin) / term->cell_width; size_t glyph_offset = term->render.search_glyph_offset; @@ -3390,8 +3412,8 @@ render_search_box(struct terminal *term) /* TODO: this is only necessary on a window resize */ wl_subsurface_set_position( term->window->search.sub, - margin / term->scale, - max(0, (int32_t)term->height - height - margin) / term->scale); + (int32_t)roundf(margin / term->scale), + (int32_t)roundf(max(0, (int32_t)term->height - height - margin) / term->scale)); wayl_surface_scale(term->window, &term->window->search.surface, buf, term->scale); wl_surface_attach(term->window->search.surface.surf, buf->wl_buf, 0, 0); @@ -3420,9 +3442,8 @@ render_urls(struct terminal *term) struct wl_window *win = term->window; xassert(tll_length(win->urls) > 0); - const int scale = round(term->scale); - const int x_margin = 2 * scale; - const int y_margin = 1 * scale; + const int x_margin = (int)roundf(2 * term->scale); + const int y_margin = (int)roundf(1 * term->scale); /* Calculate view start, counted from the *current* scrollback start */ const int scrollback_end @@ -3592,10 +3613,14 @@ render_urls(struct terminal *term) if (cols == 0) continue; - const int width = - (2 * x_margin + cols * term->cell_width + scale - 1) / scale * scale; - const int height = - (2 * y_margin + term->cell_height + scale - 1) / scale * scale; + int width = x_margin + cols * term->cell_width + x_margin; + int height = y_margin + term->cell_height + y_margin; + + if (!term_fractional_scaling(term)) { + const int iscale = (int)ceilf(term->scale); + width = (width + iscale - 1) / iscale * iscale; + height = (height + iscale - 1) / iscale * iscale; + } info[render_count].url = &it->item; info[render_count].text = xc32dup(label); @@ -3631,8 +3656,8 @@ render_urls(struct terminal *term) wl_subsurface_set_position( sub_surf->sub, - (term->margins.left + x) / term->scale, - (term->margins.top + y) / term->scale); + (int32_t)roundf((term->margins.left + x) / term->scale), + (int32_t)roundf((term->margins.top + y) / term->scale)); render_osd( term, sub_surf, term->fonts[0], bufs[i], label, @@ -3909,8 +3934,8 @@ maybe_resize(struct terminal *term, int width, int height, bool force) * Ensure we can scale to logical size, and back to * pixels without truncating. */ - if (wayl_fractional_scaling(term->wl)) { - xassert((int)round(scale) == (int)scale); + if (!term_fractional_scaling(term)) { + xassert((int)ceilf(scale) == (int)scale); int iscale = scale; if (width % iscale) diff --git a/terminal.c b/terminal.c index 41dc3305..5736400b 100644 --- a/terminal.c +++ b/terminal.c @@ -784,8 +784,8 @@ term_set_fonts(struct terminal *term, struct fcft_font *fonts[static 4], /* Use force, since cell-width/height may have changed */ render_resize_force( term, - round(term->width / term->scale), - round(term->height / term->scale)); + (int)roundf(term->width / term->scale), + (int)roundf(term->height / term->scale)); } return true; } @@ -825,7 +825,7 @@ get_font_dpi(const struct terminal *term) ? tll_back(win->on_outputs) : &tll_front(term->wl->monitors); - if (wayl_fractional_scaling(term->wl)) + if (term_fractional_scaling(term)) return mon->dpi.physical; else return mon->dpi.scaled; @@ -880,12 +880,12 @@ int term_pt_or_px_as_pixels(const struct terminal *term, const struct pt_or_px *pt_or_px) { - double scale = !term->font_is_sized_by_dpi ? term->scale : 1.; - double dpi = term->font_is_sized_by_dpi ? term->font_dpi : 96.; + float scale = !term->font_is_sized_by_dpi ? term->scale : 1.; + float dpi = term->font_is_sized_by_dpi ? term->font_dpi : 96.; return pt_or_px->px == 0 - ? round(pt_or_px->pt * scale * dpi / 72) - : pt_or_px->px * scale; + ? (int)roundf(pt_or_px->pt * scale * dpi / 72) + : (int)roundf(pt_or_px->px * scale); } struct font_load_data { @@ -932,7 +932,7 @@ reload_fonts(struct terminal *term, bool resize_grid) if (use_px_size) snprintf(size, sizeof(size), ":pixelsize=%d", - (int)round(term->font_sizes[i][j].px_size * scale)); + (int)roundf(term->font_sizes[i][j].px_size * scale)); else snprintf(size, sizeof(size), ":size=%.2f", term->font_sizes[i][j].pt_size * scale); @@ -2077,6 +2077,16 @@ term_font_size_reset(struct terminal *term) return load_fonts_from_conf(term); } +bool +term_fractional_scaling(const struct terminal *term) +{ +#if defined(HAVE_FRACTIONAL_SCALE) + return term->wl->fractional_scale_manager != NULL && term->window->scale > 0.; +#else + return false; +#endif +} + bool term_update_scale(struct terminal *term) { @@ -2093,7 +2103,7 @@ term_update_scale(struct terminal *term) * - if there aren’t any outputs available, use 1.0 */ const float new_scale = - (wayl_fractional_scaling(term->wl) && win->scale > 0. + (term_fractional_scaling(term) ? win->scale : (tll_length(win->on_outputs) > 0 ? tll_back(win->on_outputs)->scale diff --git a/terminal.h b/terminal.h index 00cfcf31..25019ecd 100644 --- a/terminal.h +++ b/terminal.h @@ -736,6 +736,7 @@ bool term_to_slave(struct terminal *term, const void *data, size_t len); bool term_paste_data_to_slave( struct terminal *term, const void *data, size_t len); +bool term_fractional_scaling(const struct terminal *term); bool term_update_scale(struct terminal *term); bool term_font_size_increase(struct terminal *term); bool term_font_size_decrease(struct terminal *term); diff --git a/wayland.c b/wayland.c index a297c76a..acf078aa 100644 --- a/wayland.c +++ b/wayland.c @@ -57,7 +57,7 @@ csd_reload_font(struct wl_window *win, float old_scale) char pixelsize[32]; snprintf(pixelsize, sizeof(pixelsize), "pixelsize=%u", - (int)round(conf->csd.title_height * scale * 1 / 2)); + (int)roundf(conf->csd.title_height * scale * 1 / 2)); LOG_DBG("loading CSD font \"%s:%s\" (old-scale=%.2f, scale=%.2f)", patterns[0], pixelsize, old_scale, scale); @@ -416,7 +416,7 @@ update_term_for_output_change(struct terminal *term) * buffer dimensions may not have been updated (in which case * render_size() normally shortcuts and returns early). */ - render_resize_force(term, round(logical_width), round(logical_height)); + render_resize_force(term, (int)roundf(logical_width), (int)roundf(logical_height)); } else if (scale_updated) { @@ -425,7 +425,7 @@ update_term_for_output_change(struct terminal *term) * been updated, even though the window logical dimensions * haven’t changed. */ - render_resize(term, round(logical_width), round(logical_height)); + render_resize(term, (int)roundf(logical_width), (int)roundf(logical_height)); } } @@ -1528,7 +1528,7 @@ wayl_init(struct fdm *fdm, struct key_binding_manager *key_binding_manager, LOG_INFO( "%s: %dx%d+%dx%d@%dHz %s %.2f\" scale=%d, DPI=%.2f/%.2f (physical/scaled)", it->item.name, it->item.dim.px_real.width, it->item.dim.px_real.height, - it->item.x, it->item.y, (int)round(it->item.refresh), + it->item.x, it->item.y, (int)roundf(it->item.refresh), it->item.model != NULL ? it->item.model : it->item.description, it->item.inch, it->item.scale, it->item.dpi.physical, it->item.dpi.scaled); @@ -1996,24 +1996,12 @@ wayl_roundtrip(struct wayland *wayl) wayl_flush(wayl); } - -bool -wayl_fractional_scaling(const struct wayland *wayl) -{ -#if defined(HAVE_FRACTIONAL_SCALE) - return wayl->fractional_scale_manager != NULL; -#else - return false; -#endif -} - void wayl_surface_scale_explicit_width_height( const struct wl_window *win, const struct wayl_surface *surf, int width, int height, float scale) { - - if (wayl_fractional_scaling(win->term->wl) && win->scale > 0.) { + if (term_fractional_scaling(win->term)) { #if defined(HAVE_FRACTIONAL_SCALE) LOG_DBG("scaling by a factor of %.2f using fractional scaling " "(width=%d, height=%d) ", scale, width, height); @@ -2021,8 +2009,8 @@ wayl_surface_scale_explicit_width_height( wl_surface_set_buffer_scale(surf->surf, 1); wp_viewport_set_destination( surf->viewport, - round((float)width / scale), - round((float)height / scale)); + (int32_t)roundf((float)width / scale), + (int32_t)roundf((float)height / scale)); #else BUG("wayl_fraction_scaling() returned true, " "but fractional scaling was not available at compile time"); @@ -2031,9 +2019,9 @@ wayl_surface_scale_explicit_width_height( LOG_DBG("scaling by a factor of %.2f using legacy mode " "(width=%d, height=%d)", scale, width, height); - xassert(scale == floor(scale)); + xassert(scale == floorf(scale)); - const int iscale = (int)scale; + const int iscale = (int)floorf(scale); xassert(width % iscale == 0); xassert(height % iscale == 0);