From 8f1de463815ac9edf735891e98b6644fbeedb4f6 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Tue, 30 Jul 2019 14:14:15 +0000 Subject: [PATCH] Simplify layout and rendering Remove pre-scaling of the bounds for the keyboard and its contents. Calculate the scale factor based on the allocation and the desired width and height of each keyboard, using the lower value of the horizontal and vertical scale factors. Apply scaling in the renderer and prepare to perform centering there. --- eek/eek-gtk-keyboard.c | 32 ++++---------- eek/eek-layout.c | 52 ----------------------- eek/eek-layout.h | 2 - eek/eek-renderer.c | 96 ++++++++++++++++++++---------------------- eek/eek-xml-layout.c | 24 ----------- 5 files changed, 54 insertions(+), 152 deletions(-) diff --git a/eek/eek-gtk-keyboard.c b/eek/eek-gtk-keyboard.c index 20718597..9fcdf537 100644 --- a/eek/eek-gtk-keyboard.c +++ b/eek/eek-gtk-keyboard.c @@ -57,9 +57,6 @@ typedef struct _EekGtkKeyboardPrivate EekKeyboard *keyboard; EekTheme *theme; - int origin_x; - int origin_y; - GdkEventSequence *sequence; // unowned reference } EekGtkKeyboardPrivate; @@ -111,9 +108,6 @@ eek_gtk_keyboard_real_draw (GtkWidget *self, gtk_widget_get_allocation (self, &allocation); - cairo_save (cr); - cairo_translate (cr, priv->origin_x, priv->origin_y); - if (!priv->renderer) { PangoContext *pcontext; @@ -131,8 +125,6 @@ eek_gtk_keyboard_real_draw (GtkWidget *self, eek_renderer_render_keyboard (priv->renderer, cr); - cairo_restore (cr); - /* redraw pressed key */ list = eek_keyboard_get_pressed_keys (priv->keyboard); for (head = list; head; head = g_list_next (head)) { @@ -157,9 +149,6 @@ eek_gtk_keyboard_real_size_allocate (GtkWidget *self, EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self)); - priv->origin_x = (allocation->width - 360) / 2; - priv->origin_y = 0; - if (priv->renderer) eek_renderer_set_allocation_size (priv->renderer, allocation->width, @@ -172,8 +161,7 @@ eek_gtk_keyboard_real_size_allocate (GtkWidget *self, static void depress(EekGtkKeyboard *self, gdouble x, gdouble y, guint32 time) { EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self); - EekKey *key = eek_renderer_find_key_by_position (priv->renderer, - x - priv->origin_x, y - priv->origin_y); + EekKey *key = eek_renderer_find_key_by_position (priv->renderer, x, y); if (key) { eek_keyboard_press_key(priv->keyboard, key, time); @@ -184,8 +172,7 @@ static void depress(EekGtkKeyboard *self, static void drag(EekGtkKeyboard *self, gdouble x, gdouble y, guint32 time) { EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self); - EekKey *key = eek_renderer_find_key_by_position (priv->renderer, - x - priv->origin_x, y - priv->origin_y); + EekKey *key = eek_renderer_find_key_by_position (priv->renderer, x, y); if (key) { GList *list, *head; @@ -501,13 +488,13 @@ render_pressed_key (GtkWidget *widget, cairo_region_t *region = gdk_window_get_clip_region (window); GdkDrawingContext *context = gdk_window_begin_draw_frame (window, region); cairo_t *cr = gdk_drawing_context_get_cairo_context (context); - - cairo_translate (cr, priv->origin_x, priv->origin_y); + gdouble scale = eek_renderer_get_scale (priv->renderer); eek_renderer_get_key_bounds (priv->renderer, key, &bounds, TRUE); magnify_bounds (widget, &bounds, &large_bounds, 1.5); cairo_save (cr); + cairo_scale (cr, scale, scale); cairo_translate (cr, bounds.x, bounds.y); eek_renderer_render_key (priv->renderer, cr, key, 1.0, TRUE); cairo_restore (cr); @@ -534,13 +521,15 @@ render_locked_key (GtkWidget *widget, cairo_region_t *region = gdk_window_get_clip_region (window); GdkDrawingContext *context = gdk_window_begin_draw_frame (window, region); cairo_t *cr = gdk_drawing_context_get_cairo_context (context); - - cairo_translate (cr, priv->origin_x, priv->origin_y); + gdouble scale = eek_renderer_get_scale (priv->renderer); eek_renderer_get_key_bounds (priv->renderer, key, &bounds, TRUE); + cairo_save (cr); + cairo_scale (cr, scale, scale); cairo_translate (cr, bounds.x, bounds.y); eek_renderer_render_key (priv->renderer, cr, key, 1.0, TRUE); + cairo_restore (cr); gdk_window_end_draw_frame (window, context); @@ -560,11 +549,6 @@ render_released_key (GtkWidget *widget, GdkDrawingContext *context = gdk_window_begin_draw_frame (window, region); cairo_t *cr = gdk_drawing_context_get_cairo_context (context); - cairo_translate (cr, priv->origin_x, priv->origin_y); - - eek_renderer_get_key_bounds (priv->renderer, key, &bounds, TRUE); - magnify_bounds (widget, &bounds, &large_bounds, 1.5); - eek_renderer_render_keyboard (priv->renderer, cr); gdk_window_end_draw_frame (window, context); diff --git a/eek/eek-layout.c b/eek/eek-layout.c index ba36637e..8337450c 100644 --- a/eek/eek-layout.c +++ b/eek/eek-layout.c @@ -129,60 +129,8 @@ eek_layout_place_sections(EekKeyboard *keyboard) eek_element_set_bounds(EEK_ELEMENT(keyboard), &keyboard_bounds); } -static void scale_bounds_callback (EekElement *element, - gpointer user_data); - -static void -scale_bounds (EekElement *element, - gdouble scale) -{ - EekBounds bounds; - - eek_element_get_bounds (element, &bounds); - bounds.x *= scale; - bounds.y *= scale; - bounds.width *= scale; - bounds.height *= scale; - eek_element_set_bounds (element, &bounds); - - if (EEK_IS_CONTAINER(element)) - eek_container_foreach_child (EEK_CONTAINER(element), - scale_bounds_callback, - &scale); -} - -static void -scale_bounds_callback (EekElement *element, - gpointer user_data) -{ - scale_bounds (element, *(gdouble *)user_data); -} - -void -eek_layout_scale_keyboard(EekKeyboard *keyboard, gdouble scale) -{ - gsize n_outlines; - - scale_bounds (EEK_ELEMENT(keyboard), scale); - - n_outlines = eek_keyboard_get_n_outlines (keyboard); - for (guint i = 0; i < n_outlines; i++) { - EekOutline *outline = eek_keyboard_get_outline (keyboard, i); - gint j; - - for (j = 0; j < outline->num_points; j++) { - outline->points[j].x *= scale; - outline->points[j].y *= scale; - } - } - - keyboard->scale = scale; -} - void eek_layout_update_layout(EekKeyboard *keyboard) { - eek_layout_scale_keyboard(keyboard, 1.0 / keyboard->scale); eek_layout_place_sections(keyboard); - eek_layout_scale_keyboard(keyboard, 1.0 / keyboard->scale); } diff --git a/eek/eek-layout.h b/eek/eek-layout.h index c93046a2..746adbe3 100644 --- a/eek/eek-layout.h +++ b/eek/eek-layout.h @@ -57,8 +57,6 @@ GType eek_layout_get_type (void) G_GNUC_CONST; void eek_layout_place_sections(EekKeyboard *keyboard); -void eek_layout_scale_keyboard(EekKeyboard *keyboard, gdouble scale); - void eek_layout_update_layout(EekKeyboard *keyboard); G_END_DECLS diff --git a/eek/eek-renderer.c b/eek/eek-renderer.c index a395454c..6a168e69 100644 --- a/eek/eek-renderer.c +++ b/eek/eek-renderer.c @@ -49,6 +49,8 @@ typedef struct _EekRendererPrivate gdouble allocation_height; gdouble scale; gint scale_factor; /* the outputs scale factor */ + gint origin_x; + gint origin_y; PangoFontDescription *ascii_font; PangoFontDescription *font; @@ -111,12 +113,12 @@ create_keyboard_surface_key_callback (EekElement *element, cairo_save (data->cr); eek_element_get_bounds (element, &bounds); - cairo_translate (data->cr, bounds.x * priv->scale, bounds.y * priv->scale); + cairo_translate (data->cr, bounds.x, bounds.y); cairo_rectangle (data->cr, 0.0, 0.0, - bounds.width * priv->scale + 100, - bounds.height * priv->scale + 100); + bounds.width + 100, + bounds.height + 100); cairo_clip (data->cr); render_key (data->renderer, data->cr, EEK_KEY(element), FALSE); @@ -135,7 +137,7 @@ create_keyboard_surface_section_callback (EekElement *element, cairo_save (data->cr); eek_element_get_bounds (element, &bounds); - cairo_translate (data->cr, bounds.x * priv->scale, bounds.y * priv->scale); + cairo_translate (data->cr, bounds.x, bounds.y); angle = eek_section_get_angle (EEK_SECTION(element)); cairo_rotate (data->cr, angle * G_PI / 180); @@ -167,7 +169,9 @@ render_keyboard_surface (EekRenderer *renderer) data.cr = cairo_create (priv->keyboard_surface); data.renderer = renderer; - cairo_translate (data.cr, bounds.x * priv->scale, bounds.y * priv->scale); + cairo_save (data.cr); + cairo_scale (data.cr, priv->scale, priv->scale); + cairo_translate (data.cr, bounds.x, bounds.y); /* blank background */ cairo_set_source_rgba (data.cr, @@ -187,6 +191,8 @@ render_keyboard_surface (EekRenderer *renderer) eek_container_foreach_child (EEK_CONTAINER(priv->keyboard), create_keyboard_surface_section_callback, &data); + cairo_restore (data.cr); + cairo_destroy (data.cr); } @@ -243,14 +249,7 @@ render_key_outline (EekRenderer *renderer, eek_element_get_bounds(EEK_ELEMENT(key), &bounds); outline = eek_outline_copy (outline); - for (guint i = 0; i < outline->num_points; i++) { - outline->points[i].x *= priv->scale; - outline->points[i].y *= priv->scale; - } - - cairo_translate (cr, - border_width * priv->scale, - border_width * priv->scale); + cairo_translate (cr, border_width, border_width); if (gradient_type != EEK_GRADIENT_NONE) { cairo_pattern_t *pat; @@ -261,17 +260,17 @@ render_key_outline (EekRenderer *renderer, pat = cairo_pattern_create_linear (0.0, 0.0, 0.0, - bounds.height * priv->scale); + bounds.height); break; case EEK_GRADIENT_HORIZONTAL: pat = cairo_pattern_create_linear (0.0, 0.0, - bounds.width * priv->scale, + bounds.width, 0.0); break; case EEK_GRADIENT_RADIAL: - cx = bounds.width / 2 * priv->scale; - cy = bounds.height / 2 * priv->scale; + cx = bounds.width / 2; + cy = bounds.height / 2; pat = cairo_pattern_create_radial (cx, cy, 0, @@ -328,9 +327,7 @@ render_key_outline (EekRenderer *renderer, outline->num_points); cairo_stroke (cr); - cairo_translate (cr, - -border_width * priv->scale, - -border_width * priv->scale); + cairo_translate (cr, -border_width, -border_width); eek_outline_free (outline); } @@ -447,8 +444,6 @@ render_key (EekRenderer *self, /* render outline */ eek_element_get_bounds (EEK_ELEMENT(key), &bounds); - bounds.width *= priv->scale; - bounds.height *= priv->scale; if (active) outline_surface_cache = priv->active_outline_surface_cache; @@ -644,7 +639,7 @@ eek_renderer_real_render_key_label (EekRenderer *self, priv->font); pango_font_description_set_size (font, pango_font_description_get_size (font) * - prop->scale * priv->scale * scale); + prop->scale * scale); pango_layout_set_font_description (layout, font); pango_font_description_free (font); @@ -653,7 +648,7 @@ eek_renderer_real_render_key_label (EekRenderer *self, if (line->resolved_dir == PANGO_DIRECTION_RTL) pango_layout_set_alignment (layout, PANGO_ALIGN_RIGHT); pango_layout_set_width (layout, - PANGO_SCALE * bounds.width * priv->scale * scale); + PANGO_SCALE * bounds.width * scale); if (prop->ellipses) pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END); } @@ -678,7 +673,10 @@ eek_renderer_real_render_key (EekRenderer *self, gdouble scale, gboolean rotate) { + EekRendererPrivate *priv = eek_renderer_get_instance_private (self); + cairo_save (cr); + cairo_translate (cr, priv->origin_x, priv->origin_y); eek_renderer_apply_transformation_for_key (self, cr, key, scale, rotate); render_key (self, cr, key, eek_key_is_pressed (key) || eek_key_is_locked (key)); cairo_restore (cr); @@ -695,6 +693,10 @@ eek_renderer_real_render_keyboard (EekRenderer *self, g_return_if_fail (priv->allocation_width > 0.0); g_return_if_fail (priv->allocation_height > 0.0); + cairo_save (cr); + + cairo_translate (cr, priv->origin_x, priv->origin_y); + if (priv->keyboard_surface) cairo_surface_destroy (priv->keyboard_surface); @@ -708,6 +710,8 @@ eek_renderer_real_render_keyboard (EekRenderer *self, source = cairo_get_source (cr); cairo_pattern_set_extend (source, CAIRO_EXTEND_PAD); cairo_paint (cr); + + cairo_restore (cr); } static void @@ -923,21 +927,19 @@ eek_renderer_set_allocation_size (EekRenderer *renderer, priv->allocation_width = width; priv->allocation_height = height; + /* Calculate a scale factor to use when rendering the keyboard into the + available space. */ eek_element_get_bounds (EEK_ELEMENT(priv->keyboard), &bounds); - if (bounds.height * width / bounds.width <= height) - scale = width / bounds.width; - else if (bounds.width * height / bounds.height <= width) - scale = height / bounds.height; - else { - if (bounds.width * height < bounds.height * width) - scale = bounds.width / width; - else - scale = bounds.height / height; - } + gdouble w = (bounds.x * 2) + bounds.width; + gdouble h = (bounds.y * 2) + bounds.height; + + scale = MIN(width / w, height / h); if (scale != priv->scale) { priv->scale = scale; + priv->origin_x = 0; + priv->origin_y = 0; invalidate (renderer); } } @@ -955,9 +957,9 @@ eek_renderer_get_size (EekRenderer *renderer, eek_element_get_bounds (EEK_ELEMENT(priv->keyboard), &bounds); if (width) - *width = bounds.width * priv->scale; + *width = bounds.width; if (height) - *height = bounds.height * priv->scale; + *height = bounds.height; } void @@ -988,10 +990,6 @@ eek_renderer_get_key_bounds (EekRenderer *renderer, if (!rotate) { bounds->x += keyboard_bounds.x + section_bounds.x; bounds->y += keyboard_bounds.y + section_bounds.y; - bounds->x *= priv->scale; - bounds->y *= priv->scale; - bounds->width *= priv->scale; - bounds->height *= priv->scale; return; } points[0].x = bounds->x; @@ -1023,10 +1021,6 @@ eek_renderer_get_key_bounds (EekRenderer *renderer, bounds->y = keyboard_bounds.y + section_bounds.y + min.y; bounds->width = (max.x - min.x); bounds->height = (max.y - min.y); - bounds->x *= priv->scale; - bounds->y *= priv->scale; - bounds->width *= priv->scale; - bounds->height *= priv->scale; } gdouble @@ -1274,8 +1268,6 @@ find_key_by_position_key_callback (EekElement *element, eek_point_rotate (&points[i], data->angle); points[i].x += data->origin.x; points[i].y += data->origin.y; - points[i].x *= priv->scale; - points[i].y *= priv->scale; } b1 = sign (&data->point, &points[0], &points[1]) < 0.0; @@ -1331,13 +1323,17 @@ eek_renderer_find_key_by_position (EekRenderer *renderer, g_return_val_if_fail (EEK_IS_RENDERER(renderer), NULL); EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer); + x /= priv->scale; + y /= priv->scale; + x -= priv->origin_x; + y -= priv->origin_y; eek_element_get_bounds (EEK_ELEMENT(priv->keyboard), &bounds); - if (x < bounds.x * priv->scale || - y < bounds.y * priv->scale || - x > bounds.width * priv->scale || - y > bounds.height * priv->scale) + if (x < bounds.x || + y < bounds.y || + x > bounds.width || + y > bounds.height) return NULL; data.point.x = x; diff --git a/eek/eek-xml-layout.c b/eek/eek-xml-layout.c index f3d527b9..404d6834 100644 --- a/eek/eek-xml-layout.c +++ b/eek/eek-xml-layout.c @@ -79,10 +79,6 @@ static gboolean parse_symbols (const gchar *path, EekKeyboard *keyboard, GError **error); -static void scale_keyboard (EekKeyboard *keyboard, - gdouble width, - gdouble height); - static gboolean validate (const gchar **valid_path_list, gsize valid_path_list_len, const gchar *element_name, @@ -946,9 +942,6 @@ eek_xml_layout_real_create_keyboard (EekboardContextService *manager, eek_layout_place_sections(keyboard); - /* Fit keyboard in the given width and height. */ - scale_keyboard (keyboard, initial_width, initial_height); - /* Use pre-defined modifier mask here. */ eek_keyboard_set_num_lock_mask (keyboard, EEK_MOD2_MASK); eek_keyboard_set_alt_gr_mask (keyboard, EEK_BUTTON1_MASK); @@ -1358,23 +1351,6 @@ parse_keyboards (const gchar *path, GError **error) return keyboards; } -static void scale_keyboard (EekKeyboard *keyboard, - gdouble width, - gdouble height) -{ - gdouble scale; - EekBounds bounds; - - eek_element_get_bounds (EEK_ELEMENT(keyboard), &bounds); - - if (width * bounds.height < height * bounds.width) - scale = width / bounds.width; - else - scale = height / bounds.height; - - eek_layout_scale_keyboard(keyboard, scale); -} - static gboolean validate (const gchar **valid_path_list, gsize valid_path_list_len,