Store font related cell metrics in a single struct

This commit is contained in:
Kovid Goyal 2024-12-03 11:57:09 +05:30
parent 8030cbd361
commit 8993386399
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
11 changed files with 138 additions and 132 deletions

View file

@ -793,7 +793,7 @@ draw_resizing_text(OSWindow *w) {
if (monotonic() - w->created_at > ms_to_monotonic_t(1000) && w->live_resize.num_of_resize_events > 1) {
char text[32] = {0};
unsigned int width = w->live_resize.width, height = w->live_resize.height;
snprintf(text, sizeof(text), "%u x %u cells", width / w->fonts_data->cell_width, height / w->fonts_data->cell_height);
snprintf(text, sizeof(text), "%u x %u cells", width / w->fonts_data->fcm.cell_width, height / w->fonts_data->fcm.cell_height);
StringCanvas rendered = render_simple_text(w->fonts_data, text);
if (rendered.canvas) {
draw_centered_alpha_mask(w, width, height, rendered.width, rendered.height, rendered.canvas, OPT(background_opacity));

View file

@ -579,10 +579,11 @@ harfbuzz_font_for_face(PyObject* s) {
return self->hb_font;
}
void
cell_metrics(PyObject *s, unsigned int* cell_width, unsigned int* cell_height, unsigned int* baseline, unsigned int* underline_position, unsigned int* underline_thickness, unsigned int* strikethrough_position, unsigned int* strikethrough_thickness) {
FontCellMetrics
cell_metrics(PyObject *s) {
// See https://developer.apple.com/library/content/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/TypoFeatures/TextSystemFeatures.html
CTFace *self = (CTFace*)s;
FontCellMetrics fcm = {0};
#define count (128 - 32)
unichar chars[count+1] = {0};
CGGlyph glyphs[count+1] = {0};
@ -596,9 +597,9 @@ cell_metrics(PyObject *s, unsigned int* cell_width, unsigned int* cell_height, u
if (w > width) width = w;
}
}
*cell_width = MAX(1u, width);
*underline_thickness = (unsigned int)ceil(MAX(0.1, self->underline_thickness));
*strikethrough_thickness = *underline_thickness;
fcm.cell_width = MAX(1u, width);
fcm.underline_thickness = (unsigned int)ceil(MAX(0.1, self->underline_thickness));
fcm.strikethrough_thickness = fcm.underline_thickness;
// float line_height = MAX(1, floor(self->ascent + self->descent + MAX(0, self->leading) + 0.5));
// Let CoreText's layout engine calculate the line height. Slower, but hopefully more accurate.
#define W "AQWMH_gyl "
@ -623,13 +624,13 @@ cell_metrics(PyObject *s, unsigned int* cell_width, unsigned int* cell_height, u
CGRect bounds_without_leading = CTLineGetBoundsWithOptions(line, kCTLineBoundsExcludeTypographicLeading);
CGFloat typographic_ascent, typographic_descent, typographic_leading;
CTLineGetTypographicBounds(line, &typographic_ascent, &typographic_descent, &typographic_leading);
*cell_height = MAX(4u, (unsigned int)ceilf(line_height));
fcm.cell_height = MAX(4u, (unsigned int)ceilf(line_height));
CGFloat bounds_ascent = bounds_without_leading.size.height + bounds_without_leading.origin.y;
*baseline = (unsigned int)floor(bounds_ascent + 0.5);
fcm.baseline = (unsigned int)floor(bounds_ascent + 0.5);
// Not sure if we should add this to bounds ascent and then round it or add
// it to already rounded baseline and round again.
*underline_position = (unsigned int)floor(bounds_ascent - self->underline_position + 0.5);
*strikethrough_position = (unsigned int)floor(*baseline * 0.65);
fcm.underline_position = (unsigned int)floor(bounds_ascent - self->underline_position + 0.5);
fcm.strikethrough_position = (unsigned int)floor(fcm.baseline * 0.65);
debug("Cell height calculation:\n");
debug("\tline height from line origins: %f\n", line_height);
@ -638,8 +639,9 @@ cell_metrics(PyObject *s, unsigned int* cell_width, unsigned int* cell_height, u
debug("\tbounds metrics: ascent: %f\n", bounds_ascent);
debug("\tline metrics: ascent: %f descent: %f leading: %f\n", typographic_ascent, typographic_descent, typographic_leading);
debug("\tfont metrics: ascent: %f descent: %f leading: %f underline_position: %f\n", self->ascent, self->descent, self->leading, self->underline_position);
debug("\tcell_height: %u baseline: %u underline_position: %u strikethrough_position: %u\n", *cell_height, *baseline, *underline_position, *strikethrough_position);
debug("\tcell_height: %u baseline: %u underline_position: %u strikethrough_position: %u\n", fcm.cell_height, fcm.baseline, fcm.underline_position, fcm.strikethrough_position);
CFRelease(test_frame); CFRelease(path); CFRelease(framesetter);
return fcm;
#undef count
}
@ -818,12 +820,11 @@ render_sample_text(CTFace *self, PyObject *args) {
CTFontRef font = self->ct_font;
PyObject *ptext;
if (!PyArg_ParseTuple(args, "Ukk|k", &ptext, &canvas_width, &canvas_height, &fg)) return NULL;
unsigned int cell_width, cell_height, baseline, underline_position, underline_thickness, strikethrough_position, strikethrough_thickness;
cell_metrics((PyObject*)self, &cell_width, &cell_height, &baseline, &underline_position, &underline_thickness, &strikethrough_position, &strikethrough_thickness);
if (!cell_width || !cell_height) return Py_BuildValue("yII", "", cell_width, cell_height);
FontCellMetrics fcm = cell_metrics((PyObject*)self);
if (!fcm.cell_width || !fcm.cell_height) return Py_BuildValue("yII", "", fcm.cell_width, fcm.cell_height);
size_t num_chars = PyUnicode_GET_LENGTH(ptext);
int num_chars_per_line = canvas_width / cell_width, num_of_lines = (int)ceil((float)num_chars / (float)num_chars_per_line);
canvas_height = MIN(canvas_height, num_of_lines * cell_height);
int num_chars_per_line = canvas_width / fcm.cell_width, num_of_lines = (int)ceil((float)num_chars / (float)num_chars_per_line);
canvas_height = MIN(canvas_height, num_of_lines * fcm.cell_height);
RAII_PyObject(pbuf, PyBytes_FromStringAndSize(NULL, sizeof(pixel) * canvas_width * canvas_height));
if (!pbuf) return NULL;
memset(PyBytes_AS_STRING(pbuf), 0, PyBytes_GET_SIZE(pbuf));
@ -842,7 +843,7 @@ render_sample_text(CTFace *self, PyObject *args) {
hb_glyph_position_t *positions = hb_buffer_get_glyph_positions(hb_buffer, NULL);
memset(PyBytes_AS_STRING(pbuf), 0, PyBytes_GET_SIZE(pbuf));
if (cell_width > canvas_width) goto end;
if (fcm.cell_width > canvas_width) goto end;
ensure_render_space(canvas_width, canvas_height, len);
float pen_x = 0, pen_y = 0;
@ -851,7 +852,7 @@ render_sample_text(CTFace *self, PyObject *args) {
for (unsigned int i = 0; i < len; i++) {
float advance = (float)positions[i].x_advance * scale;
if (pen_x + advance > canvas_width) {
pen_y += cell_height;
pen_y += fcm.cell_height;
pen_x = 0;
if (pen_y >= canvas_height) break;
}
@ -862,7 +863,7 @@ render_sample_text(CTFace *self, PyObject *args) {
buffers.glyphs[i] = info[i].codepoint;
num_glyphs++;
}
render_glyphs(font, canvas_width, canvas_height, baseline, num_glyphs);
render_glyphs(font, canvas_width, canvas_height, fcm.baseline, num_glyphs);
uint8_t r = (fg >> 16) & 0xff, g = (fg >> 8) & 0xff, b = fg & 0xff;
const uint8_t *last_pixel = (uint8_t*)PyBytes_AS_STRING(pbuf) + PyBytes_GET_SIZE(pbuf) - sizeof(pixel);
const uint8_t *s_limit = buffers.render_buf + canvas_width * canvas_height;
@ -874,7 +875,7 @@ render_sample_text(CTFace *self, PyObject *args) {
p[0] = r; p[1] = g; p[2] = b; p[3] = s[0];
}
end:
return Py_BuildValue("OII", pbuf, cell_width, cell_height);
return Py_BuildValue("OII", pbuf, fcm.cell_width, fcm.cell_height);
}

View file

@ -269,7 +269,11 @@ typedef struct {
} CellPixelSize;
typedef struct {int x;} *SPRITE_MAP_HANDLE;
#define FONTS_DATA_HEAD SPRITE_MAP_HANDLE sprite_map; double logical_dpi_x, logical_dpi_y, font_sz_in_pts; unsigned int cell_width, cell_height;
typedef struct FontCellMetrics {
unsigned int cell_width, cell_height, baseline, underline_position, underline_thickness, strikethrough_position, strikethrough_thickness;
} FontCellMetrics;
#define FONTS_DATA_HEAD SPRITE_MAP_HANDLE sprite_map; double logical_dpi_x, logical_dpi_y, font_sz_in_pts; FontCellMetrics fcm;
typedef struct {FONTS_DATA_HEAD} *FONTS_DATA_HANDLE;
#define clear_sprite_position(cell) (cell).sprite_x = 0; (cell).sprite_y = 0; (cell).sprite_z = 0;

View file

@ -62,11 +62,6 @@ typedef struct {
SpacerStrategy spacer_strategy;
} Font;
typedef struct RunFont {
unsigned scale, subscale_n, subscale_d, vertical_align, multicell_y;
ssize_t font_idx;
} RunFont;
typedef struct Canvas {
pixel *buf;
unsigned current_cells, alloced_cells, alloced_scale, current_scale;
@ -83,7 +78,6 @@ static void free_const(const void* x) { free((void*)x); }
typedef struct {
FONTS_DATA_HEAD
id_type id;
unsigned int baseline, underline_position, underline_thickness, strikethrough_position, strikethrough_thickness;
size_t fonts_capacity, fonts_count, fallback_fonts_count;
ssize_t medium_font_idx, bold_font_idx, italic_font_idx, bi_font_idx, first_symbol_font_idx, first_fallback_font_idx;
Font *fonts;
@ -100,7 +94,7 @@ static void initialize_font_group(FontGroup *fg);
static void
ensure_canvas_can_fit(FontGroup *fg, unsigned cells, unsigned scale) {
#define cs(cells, scale) (sizeof(fg->canvas.buf[0]) * 3u * cells * fg->cell_width * fg->cell_height * scale * scale)
#define cs(cells, scale) (sizeof(fg->canvas.buf[0]) * 3u * cells * fg->fcm.cell_width * fg->fcm.cell_height * scale * scale)
size_t size_in_bytes = cs(cells, scale);
if (size_in_bytes > fg->canvas.size_in_bytes) {
free(fg->canvas.buf);
@ -396,7 +390,7 @@ static void
python_send_to_gpu(FONTS_DATA_HANDLE fg, unsigned int x, unsigned int y, unsigned int z, pixel* buf) {
if (python_send_to_gpu_impl) {
if (!num_font_groups) fatal("Cannot call send to gpu with no font groups");
PyObject *ret = PyObject_CallFunction(python_send_to_gpu_impl, "IIIN", x, y, z, PyBytes_FromStringAndSize((const char*)buf, sizeof(pixel) * fg->cell_width * fg->cell_height));
PyObject *ret = PyObject_CallFunction(python_send_to_gpu_impl, "IIIN", x, y, z, PyBytes_FromStringAndSize((const char*)buf, sizeof(pixel) * fg->fcm.cell_width * fg->fcm.cell_height));
if (ret == NULL) PyErr_Print();
else Py_DECREF(ret);
}
@ -426,53 +420,50 @@ adjust_ypos(unsigned int pos, unsigned int cell_height, int adjustment) {
static void
calc_cell_metrics(FontGroup *fg) {
unsigned int cell_height, cell_width, baseline, underline_position, underline_thickness, strikethrough_position, strikethrough_thickness;
cell_metrics(fg->fonts[fg->medium_font_idx].face, &cell_width, &cell_height, &baseline, &underline_position, &underline_thickness, &strikethrough_position, &strikethrough_thickness);
if (!cell_width) fatal("Failed to calculate cell width for the specified font");
unsigned int before_cell_height = cell_height;
unsigned int cw = cell_width, ch = cell_height;
fg->fcm = cell_metrics(fg->fonts[fg->medium_font_idx].face);
if (!fg->fcm.cell_width) fatal("Failed to calculate cell width for the specified font");
unsigned int before_cell_height = fg->fcm.cell_height;
unsigned int cw = fg->fcm.cell_width, ch = fg->fcm.cell_height;
adjust_metric(&cw, OPT(cell_width).val, OPT(cell_width).unit, fg->logical_dpi_x);
adjust_metric(&ch, OPT(cell_height).val, OPT(cell_height).unit, fg->logical_dpi_y);
#define MAX_DIM 1000
#define MIN_WIDTH 2
#define MIN_HEIGHT 4
if (cw >= MIN_WIDTH && cw <= MAX_DIM) cell_width = cw;
if (cw >= MIN_WIDTH && cw <= MAX_DIM) fg->fcm.cell_width = cw;
else log_error("Cell width invalid after adjustment, ignoring modify_font cell_width");
if (ch >= MIN_HEIGHT && ch <= MAX_DIM) cell_height = ch;
if (ch >= MIN_HEIGHT && ch <= MAX_DIM) fg->fcm.cell_height = ch;
else log_error("Cell height invalid after adjustment, ignoring modify_font cell_height");
int line_height_adjustment = cell_height - before_cell_height;
if (cell_height < MIN_HEIGHT) fatal("Line height too small: %u", cell_height);
if (cell_height > MAX_DIM) fatal("Line height too large: %u", cell_height);
if (cell_width < MIN_WIDTH) fatal("Cell width too small: %u", cell_width);
if (cell_width > MAX_DIM) fatal("Cell width too large: %u", cell_width);
int line_height_adjustment = fg->fcm.cell_height - before_cell_height;
if (fg->fcm.cell_height < MIN_HEIGHT) fatal("Line height too small: %u", fg->fcm.cell_height);
if (fg->fcm.cell_height > MAX_DIM) fatal("Line height too large: %u", fg->fcm.cell_height);
if (fg->fcm.cell_width < MIN_WIDTH) fatal("Cell width too small: %u", fg->fcm.cell_width);
if (fg->fcm.cell_width > MAX_DIM) fatal("Cell width too large: %u", fg->fcm.cell_width);
#undef MIN_WIDTH
#undef MIN_HEIGHT
#undef MAX_DIM
unsigned int baseline_before = baseline;
#define A(which, dpi) adjust_metric(&which, OPT(which).val, OPT(which).unit, fg->logical_dpi_##dpi);
unsigned int baseline_before = fg->fcm.baseline;
#define A(which, dpi) adjust_metric(&fg->fcm.which, OPT(which).val, OPT(which).unit, fg->logical_dpi_##dpi);
A(underline_thickness, y); A(underline_position, y); A(strikethrough_thickness, y); A(strikethrough_position, y); A(baseline, y);
#undef A
if (baseline_before != baseline) {
int adjustment = baseline - baseline_before;
baseline = adjust_ypos(baseline_before, cell_height, adjustment);
underline_position = adjust_ypos(underline_position, cell_height, adjustment);
strikethrough_position = adjust_ypos(strikethrough_position, cell_height, adjustment);
if (baseline_before != fg->fcm.baseline) {
int adjustment = fg->fcm.baseline - baseline_before;
fg->fcm.baseline = adjust_ypos(baseline_before, fg->fcm.cell_height, adjustment);
fg->fcm.underline_position = adjust_ypos(fg->fcm.underline_position, fg->fcm.cell_height, adjustment);
fg->fcm.strikethrough_position = adjust_ypos(fg->fcm.strikethrough_position, fg->fcm.cell_height, adjustment);
}
underline_position = MIN(cell_height - 1, underline_position);
fg->fcm.underline_position = MIN(fg->fcm.cell_height - 1, fg->fcm.underline_position);
// ensure there is at least a couple of pixels available to render styled underlines
// there should be at least one pixel on either side of the underline_position
if (underline_position > baseline + 1 && underline_position > cell_height - 1)
underline_position = MAX(baseline + 1, cell_height - 1);
if (fg->fcm.underline_position > fg->fcm.baseline + 1 && fg->fcm.underline_position > fg->fcm.cell_height - 1)
fg->fcm.underline_position = MAX(fg->fcm.baseline + 1, fg->fcm.cell_height - 1);
if (line_height_adjustment > 1) {
baseline += MIN(cell_height - 1, (unsigned)line_height_adjustment / 2);
underline_position += MIN(cell_height - 1, (unsigned)line_height_adjustment / 2);
fg->fcm.baseline += MIN(fg->fcm.cell_height - 1, (unsigned)line_height_adjustment / 2);
fg->fcm.underline_position += MIN(fg->fcm.cell_height - 1, (unsigned)line_height_adjustment / 2);
}
sprite_tracker_set_layout(&fg->sprite_tracker, cell_width, cell_height);
fg->cell_width = cell_width; fg->cell_height = cell_height;
fg->baseline = baseline; fg->underline_position = underline_position; fg->underline_thickness = underline_thickness, fg->strikethrough_position = strikethrough_position, fg->strikethrough_thickness = strikethrough_thickness;
sprite_tracker_set_layout(&fg->sprite_tracker, fg->fcm.cell_width, fg->fcm.cell_height);
ensure_canvas_can_fit(fg, 8, 1);
}
@ -557,7 +548,7 @@ load_fallback_font(FontGroup *fg, const ListOfChars *lc, bool bold, bool italic,
if (face == Py_None) { Py_DECREF(face); return MISSING_FONT; }
if (global_state.debug_font_fallback) output_cell_fallback_data(lc, bold, italic, emoji_presentation, face);
if (PyLong_Check(face)) { ssize_t ans = fg->first_fallback_font_idx + PyLong_AsSsize_t(face); Py_DECREF(face); return ans; }
set_size_for_face(face, fg->cell_height, true, (FONTS_DATA_HANDLE)fg);
set_size_for_face(face, fg->fcm.cell_height, true, (FONTS_DATA_HANDLE)fg);
ensure_space_for(fg, fonts, Font, fg->fonts_count + 1, fonts_capacity, 5, true);
ssize_t ans = fg->first_fallback_font_idx + fg->fallback_fonts_count;
@ -740,10 +731,10 @@ scaled_cell_dimensions(RunFont rf, unsigned *width, unsigned *height) {
static pixel*
extract_cell_from_canvas(FontGroup *fg, unsigned int i, unsigned int num_cells) {
pixel *ans = fg->canvas.buf + (fg->canvas.size_in_bytes / sizeof(fg->canvas.buf[0]) - fg->cell_width * fg->cell_height);
pixel *dest = ans, *src = fg->canvas.buf + (i * fg->cell_width);
unsigned int stride = fg->cell_width * num_cells;
for (unsigned int r = 0; r < fg->cell_height; r++, dest += fg->cell_width, src += stride) memcpy(dest, src, fg->cell_width * sizeof(fg->canvas.buf[0]));
pixel *ans = fg->canvas.buf + (fg->canvas.size_in_bytes / sizeof(fg->canvas.buf[0]) - fg->fcm.cell_width * fg->fcm.cell_height);
pixel *dest = ans, *src = fg->canvas.buf + (i * fg->fcm.cell_width);
unsigned int stride = fg->fcm.cell_width * num_cells;
for (unsigned int r = 0; r < fg->fcm.cell_height; r++, dest += fg->fcm.cell_width, src += stride) memcpy(dest, src, fg->fcm.cell_width * sizeof(fg->canvas.buf[0]));
return ans;
}
@ -796,15 +787,15 @@ render_box_cell(FontGroup *fg, RunFont rf, CPUCell *cpu_cell, GPUCell *gpu_cell,
}
}
if (all_rendered) return;
unsigned width = fg->cell_width, height = fg->cell_height;
unsigned width = fg->fcm.cell_width, height = fg->fcm.cell_height;
scaled_cell_dimensions(rf, &width, &height);
RAII_PyObject(ret, PyObject_CallFunction(box_drawing_function, "IIId", (unsigned int)ch, width, height, (fg->logical_dpi_x + fg->logical_dpi_y) / 2.0));
if (ret == NULL) { PyErr_Print(); return; }
uint8_t *alpha_mask = PyLong_AsVoidPtr(PyTuple_GET_ITEM(ret, 0));
ensure_canvas_can_fit(fg, 2, rf.scale);
Region src = { .right = width, .bottom = height }, dest = src;
unsigned dest_stride = rf.scale * fg->cell_width, src_stride = width;
calculate_regions_for_line(rf, fg->cell_height, &src, &dest);
unsigned dest_stride = rf.scale * fg->fcm.cell_width, src_stride = width;
calculate_regions_for_line(rf, fg->fcm.cell_height, &src, &dest);
render_alpha_mask(alpha_mask, fg->canvas.buf, &src, &dest, src_stride, dest_stride, 0xffffff);
if (rf.scale == 1) {
current_send_sprite_to_gpu((FONTS_DATA_HANDLE)fg, sp[0]->x, sp[0]->y, sp[0]->z, fg->canvas.buf);
@ -868,7 +859,7 @@ render_group(FontGroup *fg, unsigned int num_cells, unsigned int num_glyphs, CPU
ensure_canvas_can_fit(fg, num_cells + 1, rf.scale);
text_in_cell(cpu_cells, tc, global_glyph_render_scratch.lc);
bool was_colored = has_emoji_presentation(cpu_cells, global_glyph_render_scratch.lc);
render_glyphs_in_cells(font->face, font->bold, font->italic, info, positions, num_glyphs, fg->canvas.buf, fg->cell_width, fg->cell_height, num_cells, fg->baseline, &was_colored, (FONTS_DATA_HANDLE)fg, center_glyph);
render_glyphs_in_cells(font->face, font->bold, font->italic, info, positions, num_glyphs, fg->canvas.buf, fg->fcm.cell_width, fg->fcm.cell_height, num_cells, fg->fcm.baseline, &was_colored, (FONTS_DATA_HANDLE)fg, center_glyph);
if (PyErr_Occurred()) PyErr_Print();
for (unsigned i = 0; i < num_cells; i++) {
@ -1278,7 +1269,8 @@ group_normal(Font *font, hb_font_t *hbf, const TextCache *tc) {
static void
shape_run(CPUCell *first_cpu_cell, GPUCell *first_gpu_cell, index_type num_cells, Font *font, bool disable_ligature, const TextCache *tc) {
shape_run(CPUCell *first_cpu_cell, GPUCell *first_gpu_cell, index_type num_cells, Font *font, RunFont rf, bool disable_ligature, const TextCache *tc) {
face_apply_scaling(font->face, rf);
hb_font_t *hbf = harfbuzz_font_for_face(font->face);
if (font->spacer_strategy == SPACER_STRATEGY_UNKNOWN) detect_spacer_strategy(hbf, font, tc);
shape(first_cpu_cell, first_gpu_cell, num_cells, hbf, font, disable_ligature, tc);
@ -1371,7 +1363,8 @@ test_shape(PyObject UNUSED *self, PyObject *args) {
FontGroup *fg = font_groups;
font = fg->fonts + fg->medium_font_idx;
}
shape_run(line->cpu_cells, line->gpu_cells, num, font, false, line->text_cache);
RunFont rf = {0};
shape_run(line->cpu_cells, line->gpu_cells, num, font, rf, false, line->text_cache);
PyObject *ans = PyList_New(0);
unsigned int idx = 0;
@ -1395,20 +1388,20 @@ static void
render_run(FontGroup *fg, CPUCell *first_cpu_cell, GPUCell *first_gpu_cell, index_type num_cells, RunFont rf, bool pua_space_ligature, bool center_glyph, int cursor_offset, DisableLigature disable_ligature_strategy, const TextCache *tc) {
switch(rf.font_idx) {
default:
shape_run(first_cpu_cell, first_gpu_cell, num_cells, &fg->fonts[rf.font_idx], disable_ligature_strategy == DISABLE_LIGATURES_ALWAYS, tc);
shape_run(first_cpu_cell, first_gpu_cell, num_cells, &fg->fonts[rf.font_idx], rf, disable_ligature_strategy == DISABLE_LIGATURES_ALWAYS, tc);
if (pua_space_ligature) collapse_pua_space_ligature(num_cells);
else if (cursor_offset > -1) { // false if DISABLE_LIGATURES_NEVER
index_type left, right;
split_run_at_offset(cursor_offset, &left, &right);
if (right > left) {
if (left) {
shape_run(first_cpu_cell, first_gpu_cell, left, &fg->fonts[rf.font_idx], false, tc);
shape_run(first_cpu_cell, first_gpu_cell, left, &fg->fonts[rf.font_idx], rf, false, tc);
render_groups(fg, rf, center_glyph, tc);
}
shape_run(first_cpu_cell + left, first_gpu_cell + left, right - left, &fg->fonts[rf.font_idx], true, tc);
shape_run(first_cpu_cell + left, first_gpu_cell + left, right - left, &fg->fonts[rf.font_idx], rf, true, tc);
render_groups(fg, rf, center_glyph, tc);
if (right < num_cells) {
shape_run(first_cpu_cell + right, first_gpu_cell + right, num_cells - right, &fg->fonts[rf.font_idx], false, tc);
shape_run(first_cpu_cell + right, first_gpu_cell + right, num_cells - right, &fg->fonts[rf.font_idx], rf, false, tc);
render_groups(fg, rf, center_glyph, tc);
}
break;
@ -1498,7 +1491,7 @@ render_line(FONTS_DATA_HANDLE fg_, Line *line, index_type lnum, Cursor *cursor,
glyph_index glyph_id = glyph_id_for_codepoint(font->face, first_ch);
int width = get_glyph_width(font->face, glyph_id);
desired_cells = (unsigned int)ceilf((float)width / fg->cell_width);
desired_cells = (unsigned int)ceilf((float)width / fg->fcm.cell_width);
}
desired_cells = MIN(desired_cells, cell_cap_for_codepoint(first_ch));
@ -1543,7 +1536,7 @@ render_line(FONTS_DATA_HANDLE fg_, Line *line, index_type lnum, Cursor *cursor,
StringCanvas
render_simple_text(FONTS_DATA_HANDLE fg_, const char *text) {
FontGroup *fg = (FontGroup*)fg_;
if (fg->fonts_count && fg->medium_font_idx) return render_simple_text_impl(fg->fonts[fg->medium_font_idx].face, text, fg->baseline);
if (fg->fonts_count && fg->medium_font_idx) return render_simple_text_impl(fg->fonts[fg->medium_font_idx].face, text, fg->fcm.baseline);
StringCanvas ans = {0};
return ans;
}
@ -1599,7 +1592,7 @@ send_prerendered_sprites(FontGroup *fg) {
current_send_sprite_to_gpu((FONTS_DATA_HANDLE)fg, x, y, z, fg->canvas.buf);
do_increment(fg, &error);
if (error != 0) { sprite_map_set_error(error); PyErr_Print(); fatal("Failed"); }
PyObject *args = PyObject_CallFunction(prerender_function, "IIIIIIIffdd", fg->cell_width, fg->cell_height, fg->baseline, fg->underline_position, fg->underline_thickness, fg->strikethrough_position, fg->strikethrough_thickness, OPT(cursor_beam_thickness), OPT(cursor_underline_thickness), fg->logical_dpi_x, fg->logical_dpi_y);
PyObject *args = PyObject_CallFunction(prerender_function, "IIIIIIIffdd", fg->fcm.cell_width, fg->fcm.cell_height, fg->fcm.baseline, fg->fcm.underline_position, fg->fcm.underline_thickness, fg->fcm.strikethrough_position, fg->fcm.strikethrough_thickness, OPT(cursor_beam_thickness), OPT(cursor_underline_thickness), fg->logical_dpi_x, fg->logical_dpi_y);
if (args == NULL) { PyErr_Print(); fatal("Failed to pre-render cells"); }
PyObject *cell_addresses = PyTuple_GET_ITEM(args, 0);
for (ssize_t i = 0; i < PyTuple_GET_SIZE(cell_addresses); i++) {
@ -1609,8 +1602,8 @@ send_prerendered_sprites(FontGroup *fg) {
if (error != 0) { sprite_map_set_error(error); PyErr_Print(); fatal("Failed"); }
uint8_t *alpha_mask = PyLong_AsVoidPtr(PyTuple_GET_ITEM(cell_addresses, i));
ensure_canvas_can_fit(fg, 1, 1); // clear canvas
Region r = { .right = fg->cell_width, .bottom = fg->cell_height };
render_alpha_mask(alpha_mask, fg->canvas.buf, &r, &r, fg->cell_width, fg->cell_width, 0xffffff);
Region r = { .right = fg->fcm.cell_width, .bottom = fg->fcm.cell_height };
render_alpha_mask(alpha_mask, fg->canvas.buf, &r, &r, fg->fcm.cell_width, fg->fcm.cell_width, 0xffffff);
current_send_sprite_to_gpu((FONTS_DATA_HANDLE)fg, x, y, z, fg->canvas.buf);
}
Py_CLEAR(args);
@ -1658,7 +1651,7 @@ initialize_font_group(FontGroup *fg) {
// rescale the symbol_map faces for the desired cell height, this is how fallback fonts are sized as well
for (size_t i = 0; i < descriptor_indices.num_symbol_fonts; i++) {
Font *font = fg->fonts + i + fg->first_symbol_font_idx;
set_size_for_face(font->face, fg->cell_height, true, (FONTS_DATA_HANDLE)fg);
set_size_for_face(font->face, fg->fcm.cell_height, true, (FONTS_DATA_HANDLE)fg);
}
}
@ -1667,7 +1660,7 @@ void
send_prerendered_sprites_for_window(OSWindow *w) {
FontGroup *fg = (FontGroup*)w->fonts_data;
if (!fg->sprite_map) {
fg->sprite_map = alloc_sprite_map(fg->cell_width, fg->cell_height);
fg->sprite_map = alloc_sprite_map(fg->fcm.cell_width, fg->fcm.cell_height);
send_prerendered_sprites(fg);
}
}
@ -1847,7 +1840,7 @@ create_test_font_group(PyObject *self UNUSED, PyObject *args) {
if (!PyArg_ParseTuple(args, "ddd", &sz, &dpix, &dpiy)) return NULL;
FontGroup *fg = font_group_for(sz, dpix, dpiy);
if (!fg->sprite_map) send_prerendered_sprites(fg);
return Py_BuildValue("II", fg->cell_width, fg->cell_height);
return Py_BuildValue("II", fg->fcm.cell_width, fg->fcm.cell_height);
}
static PyObject*

View file

@ -31,6 +31,12 @@ typedef struct ParsedFontFeature {
bool hash_computed;
} ParsedFontFeature;
typedef struct RunFont {
unsigned scale, subscale_n, subscale_d, vertical_align, multicell_y;
ssize_t font_idx;
} RunFont;
ParsedFontFeature* parse_font_feature(const char *spec);
// API that font backends need to implement
@ -39,7 +45,7 @@ int get_glyph_width(PyObject *, glyph_index);
bool is_glyph_empty(PyObject *, glyph_index);
hb_font_t* harfbuzz_font_for_face(PyObject*);
bool set_size_for_face(PyObject*, unsigned int, bool, FONTS_DATA_HANDLE);
void cell_metrics(PyObject*, unsigned int*, unsigned int*, unsigned int*, unsigned int*, unsigned int*, unsigned int*, unsigned int*);
FontCellMetrics cell_metrics(PyObject*);
bool render_glyphs_in_cells(PyObject *f, bool bold, bool italic, hb_glyph_info_t *info, hb_glyph_position_t *positions, unsigned int num_glyphs, pixel *canvas, unsigned int cell_width, unsigned int cell_height, unsigned int num_cells, unsigned int baseline, bool *was_colored, FONTS_DATA_HANDLE, bool center_glyph);
PyObject* create_fallback_face(PyObject *base_face, const ListOfChars *lc, bool bold, bool italic, bool emoji_presentation, FONTS_DATA_HANDLE fg);
PyObject* specialize_font_descriptor(PyObject *base_descriptor, double, double, double);
@ -56,6 +62,7 @@ void sprite_tracker_set_limits(size_t max_texture_size, size_t max_array_len);
typedef void (*free_extra_data_func)(void*);
StringCanvas render_simple_text_impl(PyObject *s, const char *text, unsigned int baseline);
StringCanvas render_simple_text(FONTS_DATA_HANDLE fg_, const char *text);
static inline void face_apply_scaling(PyObject*face, RunFont rf) {(void)face; (void)rf;}
bool
add_font_name_record(PyObject *table, uint16_t platform_id, uint16_t encoding_id, uint16_t language_id, uint16_t name_id, const char *string, uint16_t string_len);

View file

@ -194,7 +194,7 @@ set_size_for_face(PyObject *s, unsigned int desired_height, bool force, FONTS_DA
FT_UInt xdpi = (FT_UInt)fg->logical_dpi_x, ydpi = (FT_UInt)fg->logical_dpi_y;
if (!force && (self->char_width == w && self->char_height == w && self->xdpi == xdpi && self->ydpi == ydpi)) return true;
((Face*)self)->size_in_pts = (float)fg->font_sz_in_pts;
return set_font_size(self, w, w, xdpi, ydpi, desired_height, fg->cell_height);
return set_font_size(self, w, w, xdpi, ydpi, desired_height, fg->fcm.cell_height);
}
static PyObject*
@ -391,25 +391,27 @@ calc_cell_width(Face *self) {
}
void
cell_metrics(PyObject *s, unsigned int* cell_width, unsigned int* cell_height, unsigned int* baseline, unsigned int* underline_position, unsigned int* underline_thickness, unsigned int* strikethrough_position, unsigned int* strikethrough_thickness) {
FontCellMetrics
cell_metrics(PyObject *s) {
Face *self = (Face*)s;
*cell_width = calc_cell_width(self);
*cell_height = calc_cell_height(self, true);
*baseline = font_units_to_pixels_y(self, self->ascender);
*underline_position = MIN(*cell_height - 1, (unsigned int)font_units_to_pixels_y(self, MAX(0, self->ascender - self->underline_position)));
*underline_thickness = MAX(1, font_units_to_pixels_y(self, self->underline_thickness));
FontCellMetrics ans = {0};
ans.cell_width = calc_cell_width(self);
ans.cell_height = calc_cell_height(self, true);
ans.baseline = font_units_to_pixels_y(self, self->ascender);
ans.underline_position = MIN(ans.cell_height - 1, (unsigned int)font_units_to_pixels_y(self, MAX(0, self->ascender - self->underline_position)));
ans.underline_thickness = MAX(1, font_units_to_pixels_y(self, self->underline_thickness));
if (self->strikethrough_position != 0) {
*strikethrough_position = MIN(*cell_height - 1, (unsigned int)font_units_to_pixels_y(self, MAX(0, self->ascender - self->strikethrough_position)));
ans.strikethrough_position = MIN(ans.cell_height - 1, (unsigned int)font_units_to_pixels_y(self, MAX(0, self->ascender - self->strikethrough_position)));
} else {
*strikethrough_position = (unsigned int)floor(*baseline * 0.65);
ans.strikethrough_position = (unsigned int)floor(ans.baseline * 0.65);
}
if (self->strikethrough_thickness > 0) {
*strikethrough_thickness = MAX(1, font_units_to_pixels_y(self, self->strikethrough_thickness));
ans.strikethrough_thickness = MAX(1, font_units_to_pixels_y(self, self->strikethrough_thickness));
} else {
*strikethrough_thickness = *underline_thickness;
ans.strikethrough_thickness = ans.underline_thickness;
}
return ans;
}
unsigned int
@ -537,10 +539,10 @@ render_bitmap(Face *self, int glyph_id, ProcessedBitmap *ans, unsigned int cell_
} else if (rescale && self->is_scalable && extra > 1) {
FT_F26Dot6 char_width = self->char_width, char_height = self->char_height;
float ar = (float)max_width / (float)ans->width;
if (set_font_size(self, (FT_F26Dot6)((float)self->char_width * ar), (FT_F26Dot6)((float)self->char_height * ar), self->xdpi, self->ydpi, 0, fg->cell_height)) {
if (set_font_size(self, (FT_F26Dot6)((float)self->char_width * ar), (FT_F26Dot6)((float)self->char_height * ar), self->xdpi, self->ydpi, 0, fg->fcm.cell_height)) {
free_processed_bitmap(ans);
if (!render_bitmap(self, glyph_id, ans, cell_width, cell_height, num_cells, bold, italic, false, fg)) return false;
if (!set_font_size(self, char_width, char_height, self->xdpi, self->ydpi, 0, fg->cell_height)) return false;
if (!set_font_size(self, char_width, char_height, self->xdpi, self->ydpi, 0, fg->fcm.cell_height)) return false;
} else return false;
}
}
@ -976,14 +978,13 @@ render_sample_text(Face *self, PyObject *args) {
unsigned long fg = 0xffffff;
PyObject *ptext;
if (!PyArg_ParseTuple(args, "Ukk|k", &ptext, &canvas_width, &canvas_height, &fg)) return NULL;
unsigned int cell_width, cell_height, baseline, underline_position, underline_thickness, strikethrough_position, strikethrough_thickness;
cell_metrics((PyObject*)self, &cell_width, &cell_height, &baseline, &underline_position, &underline_thickness, &strikethrough_position, &strikethrough_thickness);
FontCellMetrics fcm = cell_metrics((PyObject*)self);
RAII_PyObject(pbuf, PyBytes_FromStringAndSize(NULL, sizeof(pixel) * canvas_width * canvas_height));
if (!pbuf) return NULL;
memset(PyBytes_AS_STRING(pbuf), 0, PyBytes_GET_SIZE(pbuf));
if (!cell_width || !cell_height) return Py_BuildValue("OII", pbuf, cell_width, cell_height);
int num_chars_per_line = canvas_width / cell_width, num_of_lines = (int)ceil((float)PyUnicode_GET_LENGTH(ptext) / (float)num_chars_per_line);
canvas_height = MIN(canvas_height, num_of_lines * cell_height);
if (!fcm.cell_width || !fcm.cell_height) return Py_BuildValue("OII", pbuf, fcm.cell_width, fcm.cell_height);
int num_chars_per_line = canvas_width / fcm.cell_width, num_of_lines = (int)ceil((float)PyUnicode_GET_LENGTH(ptext) / (float)num_chars_per_line);
canvas_height = MIN(canvas_height, num_of_lines * fcm.cell_height);
__attribute__((cleanup(destroy_hb_buffer))) hb_buffer_t *hb_buffer = hb_buffer_create();
if (!hb_buffer_pre_allocate(hb_buffer, 4*PyUnicode_GET_LENGTH(ptext))) { PyErr_NoMemory(); return NULL; }
@ -998,7 +999,7 @@ render_sample_text(Face *self, PyObject *args) {
hb_glyph_info_t *info = hb_buffer_get_glyph_infos(hb_buffer, NULL);
hb_glyph_position_t *positions = hb_buffer_get_glyph_positions(hb_buffer, NULL);
if (cell_width > canvas_width) goto end;
if (fcm.cell_width > canvas_width) goto end;
pixel *canvas = (pixel*)PyBytes_AS_STRING(pbuf);
int load_flags = get_load_flags(self->hinting, self->hintstyle, FT_LOAD_RENDER);
int error;
@ -1007,7 +1008,7 @@ render_sample_text(Face *self, PyObject *args) {
for (unsigned int i = 0; i < len; i++) {
float advance = (float)positions[i].x_advance / 64.0f;
if (pen_x + advance > canvas_width) {
pen_y += cell_height;
pen_y += fcm.cell_height;
pen_x = 0;
if (pen_y >= canvas_height) break;
}
@ -1019,7 +1020,7 @@ render_sample_text(Face *self, PyObject *args) {
FT_Bitmap *bitmap = &self->face->glyph->bitmap;
ProcessedBitmap pbm = EMPTY_PBM;
populate_processed_bitmap(self->face->glyph, bitmap, &pbm, false);
place_bitmap_in_canvas(canvas, &pbm, canvas_width, canvas_height, x, 0, baseline, 99999, fg, 0, y);
place_bitmap_in_canvas(canvas, &pbm, canvas_width, canvas_height, x, 0, fcm.baseline, 99999, fg, 0, y);
}
const uint8_t *last_pixel = (uint8_t*)PyBytes_AS_STRING(pbuf) + PyBytes_GET_SIZE(pbuf) - sizeof(pixel);
@ -1028,7 +1029,7 @@ render_sample_text(Face *self, PyObject *args) {
p[0] = r; p[1] = g; p[2] = b; p[3] = a;
}
end:
return Py_BuildValue("OII", pbuf, cell_width, cell_height);
return Py_BuildValue("OII", pbuf, fcm.cell_width, fcm.cell_height);
}

View file

@ -116,8 +116,8 @@ request_tick_callback(void) {
static void
min_size_for_os_window(OSWindow *window, int *min_width, int *min_height) {
*min_width = MAX(8u, window->fonts_data->cell_width + 1);
*min_height = MAX(8u, window->fonts_data->cell_height + 1);
*min_width = MAX(8u, window->fonts_data->fcm.cell_width + 1);
*min_height = MAX(8u, window->fonts_data->fcm.cell_height + 1);
}
@ -1067,21 +1067,21 @@ calculate_layer_shell_window_size(
if (!*height) *height = monitor_height;
double spacing = edge_spacing(GLFW_EDGE_LEFT) + edge_spacing(GLFW_EDGE_RIGHT);
spacing *= xdpi / 72.;
spacing += (fonts_data->cell_width * config->x_size_in_cells) / xscale;
spacing += (fonts_data->fcm.cell_width * config->x_size_in_cells) / xscale;
*width = (uint32_t)(1. + spacing);
} else if (config->edge == GLFW_EDGE_TOP || config->edge == GLFW_EDGE_BOTTOM) {
if (!*width) *width = monitor_width;
double spacing = edge_spacing(GLFW_EDGE_TOP) + edge_spacing(GLFW_EDGE_BOTTOM);
spacing *= ydpi / 72.;
spacing += (fonts_data->cell_height * config->y_size_in_cells) / yscale;
spacing += (fonts_data->fcm.cell_height * config->y_size_in_cells) / yscale;
*height = (uint32_t)(1. + spacing);
} else {
double spacing_x = edge_spacing(GLFW_EDGE_LEFT);
spacing_x *= xdpi / 72.;
spacing_x += (fonts_data->cell_width * config->x_size_in_cells) / xscale;
spacing_x += (fonts_data->fcm.cell_width * config->x_size_in_cells) / xscale;
double spacing_y = edge_spacing(GLFW_EDGE_TOP);
spacing_y *= ydpi / 72.;
spacing_y += (fonts_data->cell_height * config->y_size_in_cells) / yscale;
spacing_y += (fonts_data->fcm.cell_height * config->y_size_in_cells) / yscale;
*width = (uint32_t)(1. + spacing_x);
*height = (uint32_t)(1. + spacing_y);
}
@ -1213,7 +1213,7 @@ create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) {
get_window_content_scale(temp_window, &xscale, &yscale, &xdpi, &ydpi);
}
FONTS_DATA_HANDLE fonts_data = load_fonts_data(OPT(font_size), xdpi, ydpi);
PyObject *ret = PyObject_CallFunction(get_window_size, "IIddff", fonts_data->cell_width, fonts_data->cell_height, fonts_data->logical_dpi_x, fonts_data->logical_dpi_y, xscale, yscale);
PyObject *ret = PyObject_CallFunction(get_window_size, "IIddff", fonts_data->fcm.cell_width, fonts_data->fcm.cell_height, fonts_data->logical_dpi_x, fonts_data->logical_dpi_y, xscale, yscale);
if (ret == NULL) return NULL;
int width = PyLong_AsLong(PyTuple_GET_ITEM(ret, 0)), height = PyLong_AsLong(PyTuple_GET_ITEM(ret, 1));
Py_CLEAR(ret);
@ -1343,7 +1343,7 @@ void
os_window_update_size_increments(OSWindow *window) {
if (OPT(resize_in_steps)) {
if (window->handle && window->fonts_data) glfwSetWindowSizeIncrements(
window->handle, window->fonts_data->cell_width, window->fonts_data->cell_height);
window->handle, window->fonts_data->fcm.cell_width, window->fonts_data->fcm.cell_height);
} else {
if (window->handle) glfwSetWindowSizeIncrements(
window->handle, GLFW_DONT_CARE, GLFW_DONT_CARE);

View file

@ -124,7 +124,7 @@ update_ime_focus(OSWindow *osw, bool focused) {
void
prepare_ime_position_update_event(OSWindow *osw, Window *w, Screen *screen, GLFWIMEUpdateEvent *ev) {
unsigned int cell_width = osw->fonts_data->cell_width, cell_height = osw->fonts_data->cell_height;
unsigned int cell_width = osw->fonts_data->fcm.cell_width, cell_height = osw->fonts_data->fcm.cell_height;
unsigned int left = w->geometry.left, top = w->geometry.top;
if (screen_is_overlay_active(screen)) {
left += screen->overlay_line.cursor_x * cell_width;

View file

@ -245,13 +245,13 @@ cell_for_pos(Window *w, unsigned int *x, unsigned int *y, bool *in_left_half_of_
qx = screen->columns - 1;
in_left_half = false;
} else if (mouse_x >= g->left) {
double xval = (double)(mouse_x - g->left) / os_window->fonts_data->cell_width;
double xval = (double)(mouse_x - g->left) / os_window->fonts_data->fcm.cell_width;
double fxval = floor(xval);
qx = (unsigned int)fxval;
in_left_half = (xval - fxval <= 0.5) ? true : false;
}
if (mouse_y >= g->bottom) qy = screen->lines - 1;
else if (mouse_y >= g->top) qy = (unsigned int)((double)(mouse_y - g->top) / os_window->fonts_data->cell_height);
else if (mouse_y >= g->top) qy = (unsigned int)((double)(mouse_y - g->top) / os_window->fonts_data->fcm.cell_height);
if (qx < screen->columns && qy < screen->lines) {
*x = qx; *y = qy;
*in_left_half_of_cell = in_left_half;
@ -296,7 +296,7 @@ do_drag_scroll(Window *w, bool upwards) {
bool
drag_scroll(Window *w, OSWindow *frame) {
unsigned int margin = frame->fonts_data->cell_height / 2;
unsigned int margin = frame->fonts_data->fcm.cell_height / 2;
double y = frame->mouse_y;
bool upwards = y <= (w->geometry.top + margin);
if (upwards || y >= w->geometry.bottom - margin) {
@ -410,7 +410,7 @@ clear_click_queue(Window *w, int button) {
static double
radius_for_multiclick(void) {
return 0.5 * (global_state.callback_os_window ? global_state.callback_os_window->fonts_data->cell_height : 8);
return 0.5 * (global_state.callback_os_window ? global_state.callback_os_window->fonts_data->fcm.cell_height : 8);
}
static bool
@ -955,7 +955,7 @@ scroll_event(double xoffset, double yoffset, int flags, int modifiers) {
bool is_high_resolution = flags & 1;
if (yoffset != 0.0) {
s = scale_scroll(screen->modes.mouse_tracking_mode, yoffset, is_high_resolution, &screen->pending_scroll_pixels_y, global_state.callback_os_window->fonts_data->cell_height);
s = scale_scroll(screen->modes.mouse_tracking_mode, yoffset, is_high_resolution, &screen->pending_scroll_pixels_y, global_state.callback_os_window->fonts_data->fcm.cell_height);
if (s) {
bool upwards = s > 0;
if (screen->modes.mouse_tracking_mode) {
@ -976,7 +976,7 @@ scroll_event(double xoffset, double yoffset, int flags, int modifiers) {
}
}
if (xoffset != 0.0) {
s = scale_scroll(screen->modes.mouse_tracking_mode, xoffset, is_high_resolution, &screen->pending_scroll_pixels_x, global_state.callback_os_window->fonts_data->cell_width);
s = scale_scroll(screen->modes.mouse_tracking_mode, xoffset, is_high_resolution, &screen->pending_scroll_pixels_x, global_state.callback_os_window->fonts_data->fcm.cell_width);
if (s) {
if (screen->modes.mouse_tracking_mode) {
int sz = encode_mouse_scroll(w, s > 0 ? 6 : 7, modifiers);

View file

@ -674,7 +674,7 @@ static GLfloat
render_a_bar(OSWindow *os_window, Screen *screen, const CellRenderData *crd, WindowBarData *bar, PyObject *title, bool along_bottom) {
GLfloat left = os_window->viewport_width * (crd->gl.xstart + 1.f) / 2.f;
GLfloat right = left + os_window->viewport_width * crd->gl.width / 2.f;
unsigned bar_height = os_window->fonts_data->cell_height + 2;
unsigned bar_height = os_window->fonts_data->fcm.cell_height + 2;
if (!bar_height || right <= left) return 0;
unsigned bar_width = (unsigned)ceilf(right - left);
if (!bar->buf || bar->width != bar_width || bar->height != bar_height) {
@ -801,7 +801,7 @@ draw_window_number(OSWindow *os_window, Screen *screen, const CellRenderData *cr
GLfloat right = left + os_window->viewport_width * crd->gl.width / 2.f;
GLfloat title_bar_height = 0;
size_t requested_height = (size_t)(os_window->viewport_height * crd->gl.height / 2.f);
if (window->title && PyUnicode_Check(window->title) && (requested_height > (os_window->fonts_data->cell_height + 1) * 2)) {
if (window->title && PyUnicode_Check(window->title) && (requested_height > (os_window->fonts_data->fcm.cell_height + 1) * 2)) {
title_bar_height = render_a_bar(os_window, screen, crd, &window->title_bar_data, window->title, false);
}
GLfloat ystart = crd->gl.ystart, height = crd->gl.height, xstart = crd->gl.xstart, width = crd->gl.width;

View file

@ -418,8 +418,8 @@ detach_window(id_type os_window_id, id_type tab_id, id_type id) {
static void
resize_screen(OSWindow *os_window, Screen *screen, bool has_graphics) {
if (screen) {
screen->cell_size.width = os_window->fonts_data->cell_width;
screen->cell_size.height = os_window->fonts_data->cell_height;
screen->cell_size.width = os_window->fonts_data->fcm.cell_width;
screen->cell_size.height = os_window->fonts_data->fcm.cell_height;
screen_dirty_sprite_positions(screen);
if (has_graphics) screen_rescale_images(screen);
}
@ -438,8 +438,8 @@ attach_window(id_type os_window_id, id_type tab_id, id_type id) {
make_os_window_context_current(osw);
create_gpu_resources_for_window(w);
if (
w->render_data.screen->cell_size.width != osw->fonts_data->cell_width ||
w->render_data.screen->cell_size.height != osw->fonts_data->cell_height
w->render_data.screen->cell_size.width != osw->fonts_data->fcm.cell_width ||
w->render_data.screen->cell_size.height != osw->fonts_data->fcm.cell_height
) resize_screen(osw, w->render_data.screen, true);
else screen_dirty_sprite_positions(w->render_data.screen);
w->render_data.screen->reload_all_gpu_data = true;
@ -587,20 +587,20 @@ os_window_regions(OSWindow *os_window, Region *central, Region *tab_bar) {
switch(OPT(tab_bar_edge)) {
case TOP_EDGE:
central->left = 0; central->right = os_window->viewport_width - 1;
central->top = os_window->fonts_data->cell_height + margin_inner + margin_outer;
central->top = os_window->fonts_data->fcm.cell_height + margin_inner + margin_outer;
central->bottom = os_window->viewport_height - 1;
central->top = MIN(central->top, central->bottom);
tab_bar->top = margin_outer;
break;
default:
central->left = 0; central->top = 0; central->right = os_window->viewport_width - 1;
long bottom = os_window->viewport_height - os_window->fonts_data->cell_height - 1 - margin_inner - margin_outer;
long bottom = os_window->viewport_height - os_window->fonts_data->fcm.cell_height - 1 - margin_inner - margin_outer;
central->bottom = MAX(0, bottom);
tab_bar->top = central->bottom + 1 + margin_inner;
break;
}
tab_bar->left = central->left; tab_bar->right = central->right;
tab_bar->bottom = tab_bar->top + os_window->fonts_data->cell_height - 1;
tab_bar->bottom = tab_bar->top + os_window->fonts_data->fcm.cell_height - 1;
} else {
zero_at_ptr(tab_bar);
central->left = 0; central->top = 0; central->right = os_window->viewport_width - 1;
@ -789,8 +789,8 @@ PYWRAP1(set_ignore_os_keyboard_processing) {
static void
init_window_render_data(OSWindow *osw, const WindowGeometry *g, WindowRenderData *d) {
d->dx = gl_size(osw->fonts_data->cell_width, osw->viewport_width);
d->dy = gl_size(osw->fonts_data->cell_height, osw->viewport_height);
d->dx = gl_size(osw->fonts_data->fcm.cell_width, osw->viewport_width);
d->dy = gl_size(osw->fonts_data->fcm.cell_height, osw->viewport_height);
d->xstart = gl_pos_x(g->left, osw->viewport_width);
d->ystart = gl_pos_y(g->top, osw->viewport_height);
}
@ -839,7 +839,7 @@ PYWRAP1(viewport_for_window) {
WITH_OS_WINDOW(os_window_id)
os_window_regions(os_window, &central, &tab_bar);
vw = os_window->viewport_width; vh = os_window->viewport_height;
cell_width = os_window->fonts_data->cell_width; cell_height = os_window->fonts_data->cell_height;
cell_width = os_window->fonts_data->fcm.cell_width; cell_height = os_window->fonts_data->fcm.cell_height;
goto end;
END_WITH_OS_WINDOW
end:
@ -851,7 +851,7 @@ PYWRAP1(cell_size_for_window) {
unsigned int cell_width = 0, cell_height = 0;
PA("K", &os_window_id);
WITH_OS_WINDOW(os_window_id)
cell_width = os_window->fonts_data->cell_width; cell_height = os_window->fonts_data->cell_height;
cell_width = os_window->fonts_data->fcm.cell_width; cell_height = os_window->fonts_data->fcm.cell_height;
goto end;
END_WITH_OS_WINDOW
end:
@ -1112,7 +1112,7 @@ PYWRAP1(get_os_window_size) {
int width, height, fw, fh;
get_os_window_size(os_window, &width, &height, &fw, &fh);
get_os_window_content_scale(os_window, &xdpi, &ydpi, &xscale, &yscale);
unsigned int cell_width = os_window->fonts_data->cell_width, cell_height = os_window->fonts_data->cell_height;
unsigned int cell_width = os_window->fonts_data->fcm.cell_width, cell_height = os_window->fonts_data->fcm.cell_height;
return Py_BuildValue("{si si si si sf sf sd sd sI sI}",
"width", width, "height", height, "framebuffer_width", fw, "framebuffer_height", fh,
"xscale", xscale, "yscale", yscale, "xdpi", xdpi, "ydpi", ydpi,