mirror of
https://github.com/kovidgoyal/kitty
synced 2026-06-09 15:08:13 +02:00
Pre-render the sprites for blank/underline/strikethrough
This commit is contained in:
@@ -54,13 +54,12 @@ class Boss(Thread):
|
||||
self.signal_fd = handle_unix_signals()
|
||||
self.readers = [self.child_fd, self.signal_fd, self.read_wakeup_fd]
|
||||
self.writers = [self.child_fd]
|
||||
self.queue_action(self.initialize)
|
||||
self.profile = args.profile
|
||||
self.window, self.opts = window, opts
|
||||
self.screen = Screen(self, 24, 80, opts.scrollback_lines)
|
||||
self.char_grid = CharGrid(self.screen, opts, window_width, window_height)
|
||||
self.read_bytes = partial(read_bytes_dump, print) if args.dump_commands else read_bytes
|
||||
self.write_buf = memoryview(b'')
|
||||
self.char_grid = CharGrid(self.screen, opts, window_width, window_height)
|
||||
glfw.glfwSetCharModsCallback(window, self.on_text_input)
|
||||
glfw.glfwSetKeyCallback(window, self.on_key)
|
||||
glfw.glfwSetMouseButtonCallback(window, self.on_mouse_button)
|
||||
@@ -95,10 +94,6 @@ class Boss(Thread):
|
||||
if signal.SIGINT in signals or signal.SIGTERM in signals:
|
||||
self.shutdown()
|
||||
|
||||
def initialize(self):
|
||||
self.char_grid.initialize()
|
||||
glfw.glfwPostEmptyEvent()
|
||||
|
||||
def on_focus(self, window, focused):
|
||||
if focused:
|
||||
if self.screen.enable_focus_tracking():
|
||||
|
||||
@@ -172,17 +172,14 @@ class CharGrid:
|
||||
self.render_queue.put(RenderData(
|
||||
viewport=Size(self.width, self.height), clear_color=color_as_int(self.original_bg),
|
||||
cursor=self.default_cursor))
|
||||
self.sprites.ensure_state()
|
||||
self.clear_count = 4
|
||||
|
||||
def destroy(self):
|
||||
self.sprites.destroy()
|
||||
|
||||
def initialize(self):
|
||||
self.default_bg = color_as_int(self.original_bg)
|
||||
self.default_fg = color_as_int(self.original_fg)
|
||||
self.apply_opts(self.opts)
|
||||
|
||||
def destroy(self):
|
||||
self.sprites.destroy()
|
||||
|
||||
def apply_opts(self, opts):
|
||||
self.dpix, self.dpiy = get_logical_dpi()
|
||||
self.opts = opts
|
||||
|
||||
@@ -42,7 +42,6 @@ class Renderer:
|
||||
self.color_profile = ColorProfile()
|
||||
self.program = ShaderProgram(*cell_shader)
|
||||
self.sprites = Sprites()
|
||||
self.sprites.initialize()
|
||||
self.do_layout()
|
||||
|
||||
def on_resize(self, window, w, h):
|
||||
|
||||
@@ -249,7 +249,7 @@ def add_curl(buf, position, thickness):
|
||||
buf[offset + x] = 255
|
||||
|
||||
|
||||
def render_cell(text, bold=False, italic=False, underline=0, strikeout=False):
|
||||
def render_cell(text=' ', bold=False, italic=False, underline=0, strikeout=False):
|
||||
# TODO: Handle non-normalizable combining chars. Probably need to use
|
||||
# harfbuzz for that
|
||||
text = unicodedata.normalize('NFC', text)[0]
|
||||
|
||||
@@ -46,11 +46,8 @@ class Sprites:
|
||||
self.texture_id = self.buffer_id = self.buffer_texture_id = None
|
||||
self.last_num_of_layers = 1
|
||||
self.last_ynum = -1
|
||||
|
||||
def initialize(self):
|
||||
self.texture_unit = GL_TEXTURE0
|
||||
self.backend = SpriteMap(glGetIntegerv(GL_MAX_TEXTURE_SIZE), glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS))
|
||||
self.do_layout(getattr(self, 'cell_width', 1), getattr(self, 'cell_height', 1))
|
||||
|
||||
def do_layout(self, cell_width=1, cell_height=1):
|
||||
self.cell_width, self.cell_height = cell_width, cell_height
|
||||
@@ -58,6 +55,25 @@ class Sprites:
|
||||
if self.texture_id is not None:
|
||||
glDeleteTexture(self.texture_id)
|
||||
self.texture_id = None
|
||||
self.ensure_state()
|
||||
self.pre_render()
|
||||
|
||||
def pre_render(self):
|
||||
# Pre-render the basic cells to ensure they have known sprite numbers
|
||||
|
||||
def send(*a, **kw):
|
||||
buf = render_cell(*a, **kw)[0]
|
||||
x, y, z = self.backend.increment()
|
||||
self.send_to_gpu(x, y, z, buf)
|
||||
return x
|
||||
|
||||
send() # blank
|
||||
send(underline=1)
|
||||
send(strikeout=True)
|
||||
send(underline=1, strikeout=True)
|
||||
send(underline=2)
|
||||
if send(underline=2, strikeout=True) != 5:
|
||||
raise RuntimeError('Available OpenGL texture size is too small')
|
||||
|
||||
@property
|
||||
def layout(self):
|
||||
@@ -82,12 +98,10 @@ class Sprites:
|
||||
glBindTexture(tgt, self.texture_id)
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
|
||||
x, y = x * self.cell_width, y * self.cell_height
|
||||
glTexSubImage3D(tgt, 0, x, y, self.backend.z, self.cell_width, self.cell_height, 1, GL_RED, GL_UNSIGNED_BYTE, addressof(buf))
|
||||
glTexSubImage3D(tgt, 0, x, y, z, self.cell_width, self.cell_height, 1, GL_RED, GL_UNSIGNED_BYTE, addressof(buf))
|
||||
glBindTexture(tgt, 0)
|
||||
|
||||
def realloc_texture(self):
|
||||
if self.texture_id is None:
|
||||
self.initialize()
|
||||
tgt = GL_TEXTURE_2D_ARRAY
|
||||
tex = glGenTextures(1)
|
||||
glBindTexture(tgt, tex)
|
||||
|
||||
@@ -46,6 +46,7 @@ layout(SpriteMap *self, PyObject *args) {
|
||||
self->xnum = MAX(1, self->max_texture_size / cell_width);
|
||||
self->max_y = MAX(1, self->max_texture_size / cell_height);
|
||||
self->ynum = 1;
|
||||
self->x = 0; self->y = 0; self->z = 0;
|
||||
|
||||
for (size_t i = 0; i < sizeof(self->cache)/sizeof(self->cache[0]); i++) {
|
||||
SpritePosition *s = &(self->cache[i]);
|
||||
@@ -62,7 +63,7 @@ layout(SpriteMap *self, PyObject *args) {
|
||||
}
|
||||
|
||||
static void
|
||||
increment(SpriteMap *self, int *error) {
|
||||
do_increment(SpriteMap *self, int *error) {
|
||||
self->x++;
|
||||
if (self->x >= self->xnum) {
|
||||
self->x = 0; self->y++;
|
||||
@@ -100,7 +101,7 @@ sprite_position_for(SpriteMap *self, char_type ch, combining_type cc, bool is_se
|
||||
s->filled = true;
|
||||
s->rendered = false;
|
||||
s->x = self->x; s->y = self->y; s->z = self->z;
|
||||
increment(self, error);
|
||||
do_increment(self, error);
|
||||
self->dirty = true;
|
||||
return s;
|
||||
}
|
||||
@@ -116,6 +117,16 @@ static void set_sprite_error(int error) {
|
||||
}
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
increment(SpriteMap *self) {
|
||||
#define increment_doc "Increment the current position and return the old (x, y, z) values"
|
||||
unsigned int x = self->x, y = self->y, z = self->z;
|
||||
int error = 0;
|
||||
do_increment(self, &error);
|
||||
if (error) { set_sprite_error(error); return NULL; }
|
||||
return Py_BuildValue("III", x, y, z);
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
position_for(SpriteMap *self, PyObject *args) {
|
||||
#define position_for_doc "position_for(ch, cc, is_second) -> x, y, z the sprite position for the specified text"
|
||||
@@ -217,6 +228,7 @@ static PyMethodDef methods[] = {
|
||||
METHOD(position_for, METH_VARARGS)
|
||||
METHOD(render_dirty_cells, METH_VARARGS)
|
||||
METHOD(update_cell_data, METH_VARARGS)
|
||||
METHOD(increment, METH_NOARGS)
|
||||
{NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user