mirror of
https://github.com/kovidgoyal/kitty.git
synced 2026-08-04 14:46:03 +00:00
Store font related cell metrics in a single struct
This commit is contained in:
parent
8030cbd361
commit
8993386399
11 changed files with 138 additions and 132 deletions
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
109
kitty/fonts.c
109
kitty/fonts.c
|
|
@ -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*
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
16
kitty/glfw.c
16
kitty/glfw.c
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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, ¢ral, &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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue