Initial code to show window size in cells while resizing

This commit is contained in:
Kovid Goyal 2019-03-03 08:11:43 +05:30
parent bb97c589c1
commit 11522ccc92
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
11 changed files with 101 additions and 19 deletions

View file

@ -1076,7 +1076,7 @@ render_line(FONTS_DATA_HANDLE fg_, Line *line) {
StringCanvas
render_simple_text(FONTS_DATA_HANDLE fg_, const char *text) {
FontGroup *fg = (FontGroup*)fg_;
if (fg->fonts_count) return render_simple_text_impl(fg->fonts[0].face, text);
if (fg->fonts_count && fg->medium_font_idx) return render_simple_text_impl(fg->fonts[fg->medium_font_idx].face, text);
StringCanvas ans = {0};
return ans;
}

View file

@ -38,6 +38,7 @@ void render_line(FONTS_DATA_HANDLE, Line *line);
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);
StringCanvas render_simple_text(FONTS_DATA_HANDLE fg_, const char *text);
static inline void
right_shift_canvas(pixel *canvas, size_t width, size_t height, size_t amt) {

View file

@ -579,14 +579,14 @@ StringCanvas
render_simple_text_impl(PyObject *s, const char *text) {
Face *self = (Face*)s;
StringCanvas ans = {0};
size_t num_chars = strnlen(text, 20);
size_t num_chars = strnlen(text, 32);
int max_char_width = font_units_to_pixels_x(self, self->face->max_advance_width);
size_t canvas_width = max_char_width * (num_chars*2);
size_t canvas_height = font_units_to_pixels_y(self, self->face->height) + 8;
unsigned char *canvas = calloc(1, canvas_width * canvas_height);
if (!canvas) return ans;
size_t pen_x = 0;
for (size_t n = 0; n < num_chars; n++ ) {
for (size_t n = 0; n < num_chars; n++) {
FT_UInt glyph_index = FT_Get_Char_Index(self->face, text[n]);
int error = FT_Load_Glyph(self->face, glyph_index, FT_LOAD_DEFAULT);
if (error) continue;

View file

@ -58,6 +58,17 @@ update_os_window_viewport(OSWindow *window, bool notify_boss) {
}
}
static void
draw_resizing_window(OSWindow *w, unsigned int width, unsigned int height) {
char text[32] = {0};
blank_os_window(w);
snprintf(text, sizeof(text), "%u x %u cells", width / w->fonts_data->cell_width, height / w->fonts_data->cell_height);
StringCanvas rendered = render_simple_text(w->fonts_data, text);
if (rendered.canvas) {
draw_centered_alpha_mask(w->gvao_idx, width, height, rendered.width, rendered.height, rendered.canvas);
free(rendered.canvas);
}
}
// callbacks {{{
@ -153,7 +164,7 @@ framebuffer_size_callback(GLFWwindow *w, int width, int height) {
// you get partially rendered windows.
make_os_window_context_current(window);
update_surface_size(width, height, window->offscreen_texture_id);
blank_os_window(window);
draw_resizing_window(window, MAX(0, width), MAX(0, height));
swap_window_buffers(window);
request_tick_callback();
} else log_error("Ignoring resize request for tiny size: %dx%d", width, height);

View file

@ -522,6 +522,24 @@ cmp_by_zindex_and_image(const void *a_, const void *b_) {
return ans;
}
static inline void
set_vertex_data(ImageRenderData *rd, const ImageRef *ref, const ImageRect *source_rect) {
#define R(n, a, b) rd->vertices[n*4] = ref->src_rect.a; rd->vertices[n*4 + 1] = ref->src_rect.b; rd->vertices[n*4 + 2] = source_rect->a; rd->vertices[n*4 + 3] = source_rect->b;
R(0, right, top); R(1, right, bottom); R(2, left, bottom); R(3, left, top);
#undef R
}
void
gpu_data_for_centered_image(ImageRenderData *ans, unsigned int screen_width_px, unsigned int screen_height_px, unsigned int width, unsigned int height) {
static const ImageRef source_rect = { .src_rect = { .left=0, .top=0, .bottom=1, .right=1 }};
const ImageRef *ref = &source_rect;
float width_frac = width / (float)screen_width_px, height_frac = height / (float)screen_height_px;
float hmargin = MAX(0, 2 - width_frac) / 2;
float vmargin = MAX(0, 2 - height_frac) / 2;
const ImageRect r = { .left = -1 + hmargin, .right = -1 + hmargin + width_frac, .top = -1 + vmargin, .bottom = -1 + vmargin + height_frac };
set_vertex_data(ans, ref, &r);
}
bool
grman_update_layers(GraphicsManager *self, unsigned int scrolled_by, float screen_left, float screen_top, float dx, float dy, unsigned int num_cols, unsigned int num_rows, CellPixelSize cell) {
if (self->last_scrolled_by != scrolled_by) self->layers_dirty = true;
@ -553,9 +571,7 @@ grman_update_layers(GraphicsManager *self, unsigned int scrolled_by, float scree
if (ref->z_index < 0) self->num_of_negative_refs++; else self->num_of_positive_refs++;
ensure_space_for(self, render_data, ImageRenderData, self->count + 1, capacity, 64, true);
ImageRenderData *rd = self->render_data + self->count;
#define R(n, a, b) rd->vertices[n*4] = ref->src_rect.a; rd->vertices[n*4 + 1] = ref->src_rect.b; rd->vertices[n*4 + 2] = r.a; rd->vertices[n*4 + 3] = r.b;
R(0, right, top); R(1, right, bottom); R(2, left, bottom); R(3, left, top);
#undef R
set_vertex_data(rd, ref, &r);
self->count++;
rd->z_index = ref->z_index; rd->image_id = img->internal_id;
rd->texture_id = img->texture_id;

View file

@ -89,3 +89,4 @@ bool grman_update_layers(GraphicsManager *self, unsigned int scrolled_by, float
void grman_scroll_images(GraphicsManager *self, const ScrollData*, CellPixelSize fg);
void grman_resize(GraphicsManager*, index_type, index_type, index_type, index_type);
void grman_rescale(GraphicsManager *self, CellPixelSize fg);
void gpu_data_for_centered_image(ImageRenderData *ans, unsigned int screen_width_px, unsigned int screen_height_px, unsigned int width, unsigned int height);

View file

@ -2,15 +2,38 @@
#define ALPHA_TYPE
uniform sampler2D image;
#ifdef ALPHA_MASK
uniform uint fg;
#else
uniform float inactive_text_alpha;
#endif
in vec2 texcoord;
out vec4 color;
#ifdef ALPHA_MASK
const uint BYTE_MASK = uint(0xFF);
vec3 color_to_vec(uint c) {
uint r, g, b;
r = (c >> 16) & BYTE_MASK;
g = (c >> 8) & BYTE_MASK;
b = c & BYTE_MASK;
return vec3(float(r) / 255.0, float(g) / 255.0, float(b) / 255.0);
}
#endif
void main() {
#ifdef ALPHA_MASK
color = texture(image, texcoord);
vec3 fg_col = color_to_vec(fg);
color = vec4(color.r * fg_col.r, color.r * fg_col.g, color.r * fg_col.b, 1.0);
#else
color = texture(image, texcoord);
color.a *= inactive_text_alpha;
#ifdef PREMULT
color = vec4(color.rgb * color.a, color.a);
#endif
#endif
}

View file

@ -8,7 +8,7 @@
#include "fonts.h"
#include "gl.h"
enum { CELL_PROGRAM, CELL_BG_PROGRAM, CELL_SPECIAL_PROGRAM, CELL_FG_PROGRAM, BORDERS_PROGRAM, GRAPHICS_PROGRAM, GRAPHICS_PREMULT_PROGRAM, BLIT_PROGRAM, NUM_PROGRAMS };
enum { CELL_PROGRAM, CELL_BG_PROGRAM, CELL_SPECIAL_PROGRAM, CELL_FG_PROGRAM, BORDERS_PROGRAM, GRAPHICS_PROGRAM, GRAPHICS_PREMULT_PROGRAM, GRAPHICS_ALPHA_MASK_PROGRAM, BLIT_PROGRAM, NUM_PROGRAMS };
enum { SPRITE_MAP_UNIT, GRAPHICS_UNIT, BLIT_UNIT };
// Sprites {{{
@ -210,7 +210,8 @@ create_graphics_vao() {
struct CellUniformData {
bool constants_set;
GLint gploc, gpploc, cploc, cfploc;
bool alpha_mask_fg_set;
GLint gploc, gpploc, cploc, cfploc, fg_loc;
GLfloat prev_inactive_text_alpha;
};
@ -323,6 +324,27 @@ draw_graphics(int program, ssize_t vao_idx, ssize_t gvao_idx, ImageRenderData *d
bind_vertex_array(vao_idx);
}
void
draw_centered_alpha_mask(ssize_t gvao_idx, size_t screen_width, size_t screen_height, size_t width, size_t height, uint8_t *canvas) {
static ImageRenderData data = {.group_count=1};
gpu_data_for_centered_image(&data, screen_width, screen_height, width, height);
if (!data.texture_id) { glGenTextures(1, &data.texture_id); }
glBindTexture(GL_TEXTURE_2D, data.texture_id);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, canvas);
bind_program(GRAPHICS_ALPHA_MASK_PROGRAM);
if (!cell_uniform_data.alpha_mask_fg_set) {
cell_uniform_data.alpha_mask_fg_set = true;
glUniform1i(glGetUniformLocation(program_id(GRAPHICS_ALPHA_MASK_PROGRAM), "image"), GRAPHICS_UNIT);
glUniform1ui(glGetUniformLocation(program_id(GRAPHICS_ALPHA_MASK_PROGRAM), "fg"), OPT(foreground));
}
draw_graphics(GRAPHICS_ALPHA_MASK_PROGRAM, 0, gvao_idx, &data, 0, 1);
}
#define BLEND_ONTO_OPAQUE glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // blending onto opaque colors
#define BLEND_PREMULT glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // blending of pre-multiplied colors
@ -414,7 +436,8 @@ set_cell_uniforms(float current_inactive_text_alpha) {
cell_uniform_data.cploc = glGetUniformLocation(program_id(CELL_PROGRAM), "inactive_text_alpha");
cell_uniform_data.cfploc = glGetUniformLocation(program_id(CELL_FG_PROGRAM), "inactive_text_alpha");
#define S(prog, name, val, type) { bind_program(prog); glUniform##type(glGetUniformLocation(program_id(prog), #name), val); }
S(GRAPHICS_PROGRAM, image, GRAPHICS_UNIT, 1i); S(GRAPHICS_PREMULT_PROGRAM, image, GRAPHICS_UNIT, 1i);
S(GRAPHICS_PROGRAM, image, GRAPHICS_UNIT, 1i);
S(GRAPHICS_PREMULT_PROGRAM, image, GRAPHICS_UNIT, 1i);
S(CELL_PROGRAM, sprites, SPRITE_MAP_UNIT, 1i); S(CELL_FG_PROGRAM, sprites, SPRITE_MAP_UNIT, 1i);
S(CELL_PROGRAM, dim_opacity, OPT(dim_opacity), 1f); S(CELL_FG_PROGRAM, dim_opacity, OPT(dim_opacity), 1f);
#undef S
@ -632,7 +655,7 @@ static PyMethodDef module_methods[] = {
bool
init_shaders(PyObject *module) {
#define C(x) if (PyModule_AddIntConstant(module, #x, x) != 0) { PyErr_NoMemory(); return false; }
C(CELL_PROGRAM); C(CELL_BG_PROGRAM); C(CELL_SPECIAL_PROGRAM); C(CELL_FG_PROGRAM); C(BORDERS_PROGRAM); C(GRAPHICS_PROGRAM); C(GRAPHICS_PREMULT_PROGRAM); C(BLIT_PROGRAM);
C(CELL_PROGRAM); C(CELL_BG_PROGRAM); C(CELL_SPECIAL_PROGRAM); C(CELL_FG_PROGRAM); C(BORDERS_PROGRAM); C(GRAPHICS_PROGRAM); C(GRAPHICS_PREMULT_PROGRAM); C(GRAPHICS_ALPHA_MASK_PROGRAM); C(BLIT_PROGRAM);
C(GLSL_VERSION);
C(GL_VERSION);
C(GL_VENDOR);

View file

@ -81,6 +81,7 @@ add_os_window() {
memset(ans, 0, sizeof(OSWindow));
ans->id = ++global_state.os_window_id_counter;
ans->tab_bar_render_data.vao_idx = create_cell_vao();
ans->gvao_idx = create_graphics_vao();
ans->background_opacity = OPT(background_opacity);
ans->font_sz_in_pts = global_state.font_sz_in_pts;
END_WITH_OS_WINDOW_REFS
@ -180,6 +181,7 @@ destroy_os_window_item(OSWindow *w) {
Py_CLEAR(w->window_title); Py_CLEAR(w->tab_bar_render_data.screen);
if (w->offscreen_texture_id) free_texture(&w->offscreen_texture_id);
remove_vao(w->tab_bar_render_data.vao_idx);
remove_vao(w->gvao_idx);
free(w->tabs); w->tabs = NULL;
}
@ -384,6 +386,7 @@ PYWRAP1(set_options) {
S(click_interval, PyFloat_AsDouble);
S(url_color, color_as_int);
S(background, color_as_int);
S(foreground, color_as_int);
S(active_border_color, color_as_int);
S(inactive_border_color, color_as_int);
S(bell_border_color, color_as_int);

View file

@ -21,7 +21,7 @@ typedef struct {
unsigned int url_style;
unsigned int scrollback_pager_history_size;
char_type select_by_word_characters[256]; size_t select_by_word_characters_count;
color_type url_color, background, active_border_color, inactive_border_color, bell_border_color;
color_type url_color, background, foreground, active_border_color, inactive_border_color, bell_border_color;
double repaint_delay, input_delay;
bool focus_follows_mouse, hide_window_decorations;
bool macos_hide_from_tasks, macos_quit_when_last_window_closed, macos_window_resizable, macos_traditional_fullscreen, macos_show_window_title_in_menubar;
@ -144,6 +144,7 @@ typedef struct {
double pending_scroll_pixels;
enum RENDER_STATE render_state;
id_type last_focused_counter;
ssize_t gvao_idx;
} OSWindow;
@ -205,6 +206,7 @@ ssize_t create_graphics_vao();
ssize_t create_border_vao();
bool send_cell_data_to_gpu(ssize_t, ssize_t, float, float, float, float, Screen *, OSWindow *);
void draw_cells(ssize_t, ssize_t, float, float, float, float, Screen *, OSWindow *, bool, bool);
void draw_centered_alpha_mask(ssize_t gvao_idx, size_t screen_width, size_t screen_height, size_t width, size_t height, uint8_t *canvas);
void update_surface_size(int, int, uint32_t);
void free_texture(uint32_t*);
void send_image_to_gpu(uint32_t*, const void*, int32_t, int32_t, bool, bool);

View file

@ -16,14 +16,15 @@
)
from .fast_data_types import (
BLIT_PROGRAM, CELL_BG_PROGRAM, CELL_FG_PROGRAM, CELL_PROGRAM,
CELL_SPECIAL_PROGRAM, CSI, DCS, DECORATION, DIM, GRAPHICS_PREMULT_PROGRAM,
GRAPHICS_PROGRAM, OSC, REVERSE, SCROLL_FULL, SCROLL_LINE, SCROLL_PAGE,
STRIKETHROUGH, Screen, add_window, cell_size_for_window, compile_program,
get_clipboard_string, init_cell_program,
set_clipboard_string, set_titlebar_color, set_window_render_data,
update_window_title, update_window_visibility, viewport_for_window
CELL_SPECIAL_PROGRAM, CSI, DCS, DECORATION, DIM,
GRAPHICS_ALPHA_MASK_PROGRAM, GRAPHICS_PREMULT_PROGRAM, GRAPHICS_PROGRAM,
OSC, REVERSE, SCROLL_FULL, SCROLL_LINE, SCROLL_PAGE, STRIKETHROUGH, Screen,
add_window, cell_size_for_window, compile_program, get_clipboard_string,
init_cell_program, set_clipboard_string, set_titlebar_color,
set_window_render_data, update_window_title, update_window_visibility,
viewport_for_window
)
from .keys import keyboard_mode_name, extended_key_event, defines
from .keys import defines, extended_key_event, keyboard_mode_name
from .rgb import to_color
from .terminfo import get_capabilities
from .utils import (
@ -87,6 +88,7 @@ def color_as_vec3(x):
for which, p in {
'SIMPLE': GRAPHICS_PROGRAM,
'PREMULT': GRAPHICS_PREMULT_PROGRAM,
'ALPHA_MASK': GRAPHICS_ALPHA_MASK_PROGRAM,
}.items():
ff = f.replace('ALPHA_TYPE', which)
compile_program(p, v, ff)