Fix failing test

num_scaled_cells calculation was incorrect. Also optimize copying from
scratch when width is unchanged.
This commit is contained in:
Kovid Goyal 2026-02-24 09:53:06 +05:30
parent dfaec241d9
commit ced3a98aa8
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
2 changed files with 20 additions and 14 deletions

View file

@ -1159,6 +1159,7 @@ render_group(
) {
#define sp global_glyph_render_scratch.sprite_positions
const FontCellMetrics scaled_metrics = fg->fcm;
const Font *font = fg->fonts + rf.font_idx;
bool all_rendered = true;
unsigned num_scaled_cells = MAX(1u, (unsigned)ceil(num_cells / scale));
@ -1168,10 +1169,9 @@ render_group(
// scw might be 1 px less than scaled_metrics.cell_width because of rounding, but it is the correct value
// to use to determine the num of scaled cells
unsigned scw = (unsigned)(unscaled_metrics.cell_width * scale);
num_scaled_cells = unscaled_metrics.cell_width / scw;
num_scaled_cells = num_cells * unscaled_metrics.cell_width / scw;
}
unsigned scaled_canvas_width = num_scaled_cells * scaled_metrics.cell_width;
Font *font = fg->fonts + rf.font_idx;
#define failed { \
if (PyErr_Occurred()) PyErr_Print(); \
@ -1198,30 +1198,31 @@ render_group(
pixel *scratch = fg->canvas.buf + canvas_width * unscaled_metrics.cell_height;
text_in_cell(cpu_cells, tc, global_glyph_render_scratch.lc);
bool is_only_filled_boxes = false;
bool was_colored = has_emoji_presentation(cpu_cells, global_glyph_render_scratch.lc);
if (global_glyph_render_scratch.lc->chars[0] == 0x2588) {
glyph_index box_glyph_id = global_glyph_render_scratch.glyphs[0];
is_only_filled_boxes = true;
for (unsigned i = 1; i < num_glyphs && is_only_filled_boxes; i++) if (global_glyph_render_scratch.glyphs[i] != box_glyph_id) is_only_filled_boxes = false;
}
bool was_colored = !is_only_filled_boxes && has_emoji_presentation(cpu_cells, global_glyph_render_scratch.lc);
GlyphRenderInfo ri = {0};
pixel *canvas = rendering_in_smaller_area ? scratch : fg->canvas.buf;
pixel *canvas = rendering_in_smaller_area && canvas_width != scaled_canvas_width ? scratch : fg->canvas.buf;
if (is_only_filled_boxes) { // special case rendering of █ for tests
render_filled_sprite(canvas, num_glyphs, scaled_metrics, num_scaled_cells);
was_colored = false;
ri.canvas_width = canvas_width; ri.rendered_width = num_glyphs * scaled_metrics.cell_width;
/*dump_sprite(canvas, scaled_metrics.cell_width * num_scaled_cells, scaled_metrics.cell_height);*/
// dump_sprite(canvas, scaled_metrics.cell_width * num_scaled_cells, scaled_metrics.cell_height);
} else {
render_glyphs_in_cells(font->face, font->bold, font->italic, info, positions, num_glyphs, canvas, scaled_metrics.cell_width, scaled_metrics.cell_height, num_scaled_cells, scaled_metrics.baseline, &was_colored, (FONTS_DATA_HANDLE)fg, &ri);
ri.rendered_width = MIN(ri.rendered_width, ri.canvas_width);
}
// printf("num_cells: %u num_scaled_cells: %u num_glyphs: %u scale: %f unscaled: %ux%u scaled: %ux%u rendered_width: %d\n", num_cells, num_scaled_cells, num_glyphs, scale, unscaled_metrics.cell_width, unscaled_metrics.cell_height, scaled_metrics.cell_width, scaled_metrics.cell_height, ri.rendered_width);
if (rendering_in_smaller_area) { // expand into actual canvas width
unsigned stride = MIN(canvas_width, scaled_canvas_width);
for (unsigned y = 0; y < scaled_metrics.cell_height; y++) memcpy(
fg->canvas.buf + y * canvas_width, canvas + y * scaled_canvas_width, sizeof(pixel) * stride);
ri.canvas_width = canvas_width;
scaled_canvas_width = canvas_width;
if (canvas == scratch) {
if (canvas_width != scaled_canvas_width) {
unsigned stride = MIN(canvas_width, scaled_canvas_width);
for (unsigned y = 0; y < scaled_metrics.cell_height; y++) memcpy(
fg->canvas.buf + y * canvas_width, canvas + y * scaled_canvas_width, sizeof(pixel) * stride);
ri.canvas_width = canvas_width;
scaled_canvas_width = canvas_width;
} else memcpy(fg->canvas.buf, canvas, sizeof(pixel) * canvas_width * scaled_metrics.cell_height);
canvas = fg->canvas.buf;
}
apply_horizontal_alignment(
@ -1231,7 +1232,7 @@ render_group(
fg->fcm = unscaled_metrics; // needed for current_send_sprite_to_gpu()
if (num_cells == num_scaled_cells && scale == 1.f) {
if (num_cells == num_scaled_cells && scale == 1.f && !rendering_in_smaller_area) {
Region src = {.bottom=unscaled_metrics.cell_height, .right=unscaled_metrics.cell_width}, dest = src;
DecorationMetadata dm = index_for_decorations(fg, rf, src, dest, scaled_metrics);
for (unsigned i = 0; i < num_cells; i++) {

View file

@ -174,6 +174,8 @@ class Selection(BaseTest):
self.ae(face_from_descriptor(ff['bold']).applied_features(), {'dlig': 'dlig', 'test': 'test=3'})
def block_helpers(s, sprites, cell_width, cell_height):
mr = {}
actual = b''
block_size = cell_width * cell_height * 4
def full_block():
@ -216,7 +218,9 @@ def block_helpers(s, sprites, cell_width, cell_height):
return '\n'.join(row(y) for y in range(cell_height))
def assert_blocks(a, b, msg=''):
nonlocal mr, actual, full_block, half_block, quarter_block, block_test, empty_block
if a != b:
del mr, actual, full_block, half_block, quarter_block, block_test, empty_block
msg = msg or 'block not equal'
if len(a) != len(b):
assert_blocks.__msg = msg + f' block lengths not equal: {len(a)/4} != {len(b)/4}'
@ -237,13 +241,14 @@ def block_helpers(s, sprites, cell_width, cell_height):
return ans
def block_test(*expected, **kw):
nonlocal mr, actual
mr = multiline_render(kw.pop('text', ''), **kw)
try:
z = zip(expected, mr, strict=True)
except TypeError:
z = zip(expected, mr)
for i, (expected, actual) in enumerate(z):
assert_blocks(expected(), actual, f'Block {i} is not equal')
assert_blocks(expected(), actual, f'Block {i} expected != actual')
return full_block, empty_block, upper_half_block, lower_half_block, quarter_block, block_as_str, block_test