[libgnomekbd] Multiple fixes: pango, subscripts etc
- From: Sergey V. Udaltsov <svu src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgnomekbd] Multiple fixes: pango, subscripts etc
- Date: Sun, 28 Mar 2010 23:00:26 +0000 (UTC)
commit 342b82bfd0308275618180652dc56e7d9b663642
Author: Sergey V. Udaltsov <svu gnome org>
Date: Sun Mar 28 23:56:40 2010 +0100
Multiple fixes: pango, subscripts etc
The label rendering changed from 'toy' API in cairo to proper
pango-cairo usage.
https://bugzilla.gnome.org/show_bug.cgi?id=612371 (partially, no change
handling yet)
The subscripts are used for variants of the same layout,
https://bugzilla.gnome.org/show_bug.cgi?id=613853
libgnomekbd/gkbd-indicator.c | 198 +++++++++++++++++++++++-------------------
libgnomekbd/gkbd-status.c | 168 ++++++++++++++++++++++++++---------
2 files changed, 234 insertions(+), 132 deletions(-)
---
diff --git a/libgnomekbd/gkbd-indicator.c b/libgnomekbd/gkbd-indicator.c
index 17162a6..5def369 100644
--- a/libgnomekbd/gkbd-indicator.c
+++ b/libgnomekbd/gkbd-indicator.c
@@ -273,6 +273,9 @@ flag_exposed (GtkWidget * flag, GdkEventExpose * event, GdkPixbuf * image)
int ih = gdk_pixbuf_get_height (image);
GtkAllocation allocation;
gboolean scaling_needed;
+ double xwiratio, ywiratio, wiratio;
+ int sw, sh, ox, oy;
+ GdkPixbuf *scaled;
gtk_widget_get_allocation (flag, &allocation);
scaling_needed =
@@ -281,19 +284,19 @@ flag_exposed (GtkWidget * flag, GdkEventExpose * event, GdkPixbuf * image)
(allocation.width >= iw && allocation.height == ih));
/* widget-to-image scales, X and Y */
- double xwiratio = 1.0 * allocation.width / iw;
- double ywiratio = 1.0 * allocation.height / ih;
- double wiratio = xwiratio < ywiratio ? xwiratio : ywiratio;
+ xwiratio = 1.0 * allocation.width / iw;
+ ywiratio = 1.0 * allocation.height / ih;
+ wiratio = xwiratio < ywiratio ? xwiratio : ywiratio;
/* scaled width and height */
- int sw = iw * wiratio;
- int sh = ih * wiratio;
+ sw = iw * wiratio;
+ sh = ih * wiratio;
/* offsets */
- int ox = (allocation.width - sw) >> 1;
- int oy = (allocation.height - sh) >> 1;
+ ox = (allocation.width - sw) >> 1;
+ oy = (allocation.height - sh) >> 1;
- GdkPixbuf *scaled =
+ scaled =
scaling_needed ? gdk_pixbuf_scale_simple (image, sw, sh,
GDK_INTERP_HYPER) :
image;
@@ -309,6 +312,89 @@ flag_exposed (GtkWidget * flag, GdkEventExpose * event, GdkPixbuf * image)
g_object_unref (G_OBJECT (scaled));
}
+gchar *
+gkbd_indicator_extract_layout_name (int group, XklEngine * engine,
+ GkbdKeyboardConfig * kbd_cfg,
+ gchar ** short_group_names,
+ gchar ** full_group_names)
+{
+ char *layout_name;
+ if (group < g_strv_length (short_group_names)) {
+ if (xkl_engine_get_features (engine) &
+ XKLF_MULTIPLE_LAYOUTS_SUPPORTED) {
+ char *full_layout_name = (char *)
+ g_slist_nth_data (kbd_cfg->layouts_variants,
+ group);
+ char *variant_name;
+ if (!gkbd_keyboard_config_split_items
+ (full_layout_name, &layout_name,
+ &variant_name))
+ /* just in case */
+ layout_name = full_layout_name;
+
+ /* make it freeable */
+ layout_name = g_strdup (layout_name);
+
+ if (short_group_names != NULL) {
+ char *short_group_name =
+ short_group_names[group];
+ if (short_group_name != NULL
+ && *short_group_name != '\0') {
+ /* drop the long name */
+ g_free (layout_name);
+ layout_name =
+ g_strdup (short_group_name);
+ }
+ }
+ } else {
+ layout_name = g_strdup (full_group_names[group]);
+ }
+ }
+
+ if (layout_name == NULL)
+ layout_name = g_strdup ("??");
+
+ return layout_name;
+}
+
+gchar *
+gkbd_indicator_create_label_title (int group, GHashTable ** ln2cnt_map,
+ gchar * layout_name)
+{
+ gpointer pcounter = NULL;
+ char *prev_layout_name = NULL;
+ char *lbl_title = NULL;
+ int counter = 0;
+
+ if (group == 0) {
+ *ln2cnt_map =
+ g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, NULL);
+ }
+
+ /* Process layouts with repeating description */
+ if (g_hash_table_lookup_extended
+ (*ln2cnt_map, layout_name, (gpointer *) & prev_layout_name,
+ &pcounter)) {
+ /* "next" same description */
+ gchar appendix[10] = "";
+ gint utf8length;
+ gunichar cidx;
+ counter = GPOINTER_TO_INT (pcounter);
+ /* Unicode subscript 2, 3, 4 */
+ cidx = 0x2081 + counter;
+ utf8length = g_unichar_to_utf8 (cidx, appendix);
+ appendix[utf8length] = '\0';
+ lbl_title = g_strconcat (layout_name, appendix, NULL);
+ } else {
+ /* "first" time this description */
+ lbl_title = g_strdup (layout_name);
+ }
+ g_hash_table_insert (*ln2cnt_map, layout_name,
+ GINT_TO_POINTER (counter + 1));
+ return lbl_title;
+}
+
static GtkWidget *
gkbd_indicator_prepare_drawing (GkbdIndicator * gki, int group)
{
@@ -331,96 +417,32 @@ gkbd_indicator_prepare_drawing (GkbdIndicator * gki, int group)
G_CALLBACK (flag_exposed), image);
gtk_container_add (GTK_CONTAINER (ebox), flag);
} else {
- gpointer pcounter = NULL;
- char *prev_layout_name = NULL, **ppln;
char *lbl_title = NULL;
- int counter = 0;
char *layout_name = NULL;
GtkWidget *align, *label;
- /**
- * Map "short desciption" ->
- * number of layouts in the configuration
- * having this short description
- */
- static GHashTable *short_descrs = NULL;
-
- if (group == 0)
- short_descrs =
- g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, NULL);
-
-
- if (group < g_strv_length (globals.short_group_names)) {
- if (xkl_engine_get_features (globals.engine) &
- XKLF_MULTIPLE_LAYOUTS_SUPPORTED) {
- char *full_layout_name = (char *)
- g_slist_nth_data (globals.kbd_cfg.
- layouts_variants,
- group);
- char *variant_name;
- if (!gkbd_keyboard_config_split_items
- (full_layout_name, &layout_name,
- &variant_name))
- /* just in case */
- layout_name = full_layout_name;
-
- /* make it freeable */
- layout_name = g_strdup (layout_name);
-
- if (globals.short_group_names != NULL) {
- char *short_group_name =
- globals.short_group_names
- [group];
- if (short_group_name != NULL
- && *short_group_name != '\0') {
- /* drop the long name */
- g_free (layout_name);
- layout_name =
- g_strdup
- (short_group_name);
- }
- }
- } else {
- layout_name =
- g_strdup (globals.full_group_names
- [group]);
- }
- }
+ static GHashTable *ln2cnt_map = NULL;
- if (layout_name == NULL)
- layout_name = g_strdup ("??");
-
- /* Process layouts with repeating description */
- ppln = &prev_layout_name;
- if (g_hash_table_lookup_extended
- (short_descrs, layout_name,
- (gpointer *) ppln, &pcounter)) {
- /* "next" same description */
- gchar appendix[10] = "";
- gint utf8length;
- gunichar cidx;
- counter = GPOINTER_TO_INT (pcounter);
- /* Unicode subscript 2, 3, 4 */
- cidx = 0x2081 + counter;
- utf8length = g_unichar_to_utf8 (cidx, appendix);
- appendix[utf8length] = '\0';
- lbl_title =
- g_strconcat (layout_name, appendix, NULL);
- } else {
- /* "first" time this description */
- lbl_title = g_strdup (layout_name);
- }
- g_hash_table_insert (short_descrs, layout_name,
- GINT_TO_POINTER (counter + 1));
+ layout_name =
+ gkbd_indicator_extract_layout_name (group,
+ globals.engine,
+ &globals.kbd_cfg,
+ globals.short_group_names,
+ globals.full_group_names);
+
+ lbl_title =
+ gkbd_indicator_create_label_title (group,
+ &ln2cnt_map,
+ layout_name);
align = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
label = gtk_label_new (lbl_title);
g_free (lbl_title);
gtk_label_set_angle (GTK_LABEL (label), gki->priv->angle);
- if (group == xkl_engine_get_num_groups (globals.engine)) {
- g_hash_table_destroy (short_descrs);
- short_descrs = NULL;
+ if (group + 1 ==
+ xkl_engine_get_num_groups (globals.engine)) {
+ g_hash_table_destroy (ln2cnt_map);
+ ln2cnt_map = NULL;
}
gtk_container_add (GTK_CONTAINER (align), label);
diff --git a/libgnomekbd/gkbd-status.c b/libgnomekbd/gkbd-status.c
index 2efb00f..eafdd17 100644
--- a/libgnomekbd/gkbd-status.c
+++ b/libgnomekbd/gkbd-status.c
@@ -43,7 +43,10 @@ typedef struct _gki_globals {
gchar **full_group_names;
gchar **short_group_names;
- gint current_size;
+ gint current_width;
+ gint current_height;
+ int real_width;
+
GSList *icons; /* list of GdkPixbuf */
GSList *widget_instances; /* list of GkbdStatus */
gulong state_changed_handler;
@@ -122,12 +125,31 @@ gkbd_status_activate (GkbdStatus * gki)
gkbd_desktop_config_lock_next_group (&globals.cfg);
}
+/* hackish xref */
+extern gchar *gkbd_indicator_extract_layout_name (int group,
+ XklEngine * engine,
+ GkbdKeyboardConfig *
+ kbd_cfg,
+ gchar **
+ short_group_names,
+ gchar **
+ full_group_names);
+
+extern gchar *gkbd_indicator_create_label_title (int group,
+ GHashTable **
+ ln2cnt_map,
+ gchar * layout_name);
+
static void
gkbd_status_render_cairo (cairo_t * cr, int group)
{
- cairo_text_extents_t te;
- gchar *lbl = globals.short_group_names[group];
double r, g, b;
+ PangoFontDescription *pfd;
+ PangoContext *pcc;
+ PangoLayout *pl;
+ int lwidth, lheight;
+ gchar *layout_name, *lbl_title;
+ static GHashTable *ln2cnt_map = NULL;
if (globals.ind_cfg.background_color != NULL &&
globals.ind_cfg.background_color[0] != 0) {
@@ -135,8 +157,8 @@ gkbd_status_render_cairo (cairo_t * cr, int group)
(globals.ind_cfg.background_color, "%lg %lg %lg", &r,
&g, &b) == 3) {
cairo_set_source_rgb (cr, r, g, b);
- cairo_rectangle (cr, 0, 0, globals.current_size,
- globals.current_size);
+ cairo_rectangle (cr, 0, 0, globals.current_width,
+ globals.current_height);
cairo_fill (cr);
}
}
@@ -157,19 +179,60 @@ gkbd_status_render_cairo (cairo_t * cr, int group)
CAIRO_FONT_WEIGHT_NORMAL);
}
- if (globals.ind_cfg.font_size > 0) {
- cairo_set_font_size (cr, globals.ind_cfg.font_size);
+ pfd = pango_font_description_new ();
+ pango_font_description_set_family (pfd,
+ globals.ind_cfg.font_family);
+ pango_font_description_set_style (pfd, PANGO_STYLE_NORMAL);
+ pango_font_description_set_weight (pfd, PANGO_WEIGHT_NORMAL);
+ pango_font_description_set_size (pfd,
+ globals.ind_cfg.font_size *
+ PANGO_SCALE);
+
+ pcc = pango_cairo_create_context (cr);
+ pango_cairo_context_set_font_options (pcc,
+ gdk_screen_get_font_options
+ (gdk_screen_get_default ()));
+
+ pl = pango_layout_new (pcc);
+
+ layout_name = gkbd_indicator_extract_layout_name (group,
+ globals.engine,
+ &globals.kbd_cfg,
+ globals.
+ short_group_names,
+ globals.
+ full_group_names);
+ lbl_title =
+ gkbd_indicator_create_label_title (group, &ln2cnt_map,
+ layout_name);
+
+ if (group + 1 == xkl_engine_get_num_groups (globals.engine)) {
+ g_hash_table_destroy (ln2cnt_map);
+ ln2cnt_map = NULL;
}
- cairo_text_extents (cr, lbl, &te);
+ pango_layout_set_text (pl, lbl_title, -1);
+
+ g_free(lbl_title);
+
+ pango_layout_set_font_description (pl, pfd);
+ pango_layout_get_size (pl, &lwidth, &lheight);
+
cairo_move_to (cr,
- (globals.current_size >> 1) - te.width / 2 -
- te.x_bearing,
- (globals.current_size >> 1) - te.height / 2 -
- te.y_bearing);
- cairo_show_text (cr, lbl);
+ (globals.current_width - lwidth / PANGO_SCALE) / 2,
+ (globals.current_height -
+ lheight / PANGO_SCALE) / 2);
+ pango_cairo_show_layout (cr, pl);
+
+ pango_font_description_free (pfd);
+ g_object_unref (pl);
+ g_object_unref (pcc);
cairo_destroy (cr);
+
+ globals.real_width = (lwidth / PANGO_SCALE) + 4;
+ if (globals.real_width > globals.current_width)
+ globals.real_width = globals.current_width;
}
static inline guint8
@@ -180,24 +243,34 @@ convert_color_channel (guint8 src, guint8 alpha)
static void
convert_bgra_to_rgba (guint8 const *src, guint8 * dst, int width,
- int height)
+ int height, int new_width)
{
- guint8 const *src_pixel = src;
+ int xoffset = width - new_width;
+
+ /* *4 */
+ int ptr_step = xoffset << 2;
+
+ /* / 2 * 4 */
+ guint8 const *src_pixel = src + ((xoffset >> 1) << 2);
+
guint8 *dst_pixel = dst;
int x, y;
- for (y = 0; y < height; y++) {
- for (x = 0; x < width; x++) {
+ for (y = height; --y >= 0; src_pixel += ptr_step) {
+ for (x = new_width; --x >= 0;) {
+ /* src is native-endian! */
+ gint isrc = *(gint *) src_pixel;
+ gint8 alpha = isrc >> 24;
+
dst_pixel[0] =
- convert_color_channel (src_pixel[2],
- src_pixel[3]);
+ convert_color_channel (isrc & 0xFF, alpha);
dst_pixel[1] =
- convert_color_channel (src_pixel[1],
- src_pixel[3]);
+ convert_color_channel ((isrc >> 8) & 0xFF,
+ alpha);
dst_pixel[2] =
- convert_color_channel (src_pixel[0],
- src_pixel[3]);
- dst_pixel[3] = src_pixel[3];
+ convert_color_channel ((isrc >> 16) & 0xFF,
+ alpha);
+ dst_pixel[3] = alpha;
dst_pixel += 4;
src_pixel += 4;
@@ -212,19 +285,20 @@ gkbd_status_prepare_drawing (GkbdStatus * gki, int group)
char *image_filename;
GdkPixbuf *image;
- if (globals.current_size == 0)
+ if (globals.current_width == 0)
return NULL;
if (globals.ind_cfg.show_flags) {
image_filename =
- (char *) g_slist_nth_data (globals.
- ind_cfg.image_filenames,
- group);
+ (char *) g_slist_nth_data (globals.ind_cfg.
+ image_filenames, group);
image = gdk_pixbuf_new_from_file_at_size (image_filename,
- globals.current_size,
- globals.current_size,
+ globals.
+ current_width,
+ globals.
+ current_height,
&gerror);
if (image == NULL) {
@@ -239,7 +313,8 @@ gkbd_status_prepare_drawing (GkbdStatus * gki, int group)
NULL ?
"Unknown"
:
- gerror->message);
+ gerror->
+ message);
g_signal_connect (G_OBJECT (dialog), "response",
G_CALLBACK (gtk_widget_destroy),
NULL);
@@ -263,19 +338,20 @@ gkbd_status_prepare_drawing (GkbdStatus * gki, int group)
} else {
cairo_surface_t *cs =
cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
- globals.current_size,
- globals.current_size);
+ globals.current_width,
+ globals.current_height);
unsigned char *cairo_data;
guchar *pixbuf_data;
gkbd_status_render_cairo (cairo_create (cs), group);
cairo_data = cairo_image_surface_get_data (cs);
pixbuf_data =
g_new0 (guchar,
- 4 * globals.current_size *
- globals.current_size);
+ 4 * globals.real_width *
+ globals.current_height);
convert_bgra_to_rgba (cairo_data, pixbuf_data,
- globals.current_size,
- globals.current_size);
+ globals.current_width,
+ globals.current_height,
+ globals.real_width);
#if 0
char pngfilename[20];
@@ -289,9 +365,10 @@ gkbd_status_prepare_drawing (GkbdStatus * gki, int group)
GDK_COLORSPACE_RGB,
TRUE,
8,
- globals.current_size,
- globals.current_size,
- globals.current_size * 4,
+ globals.real_width,
+ globals.current_height,
+ globals.real_width *
+ 4,
(GdkPixbufDestroyNotify)
g_free, NULL);
xkl_debug (150,
@@ -532,8 +609,9 @@ gkbd_status_stop_listen (void)
static void
gkbd_status_size_changed (GkbdStatus * gki, gint size)
{
- if (globals.current_size != size) {
- globals.current_size = size;
+ if (globals.current_height != size) {
+ globals.current_height = size;
+ globals.current_width = size * 3 / 2;
gkbd_status_reinit_ui (gki);
}
}
@@ -632,13 +710,15 @@ gkbd_status_global_term (void)
if (g_signal_handler_is_connected
(globals.engine, globals.state_changed_handler)) {
g_signal_handler_disconnect (globals.engine,
- globals.state_changed_handler);
+ globals.
+ state_changed_handler);
globals.state_changed_handler = 0;
}
if (g_signal_handler_is_connected
(globals.engine, globals.config_changed_handler)) {
g_signal_handler_disconnect (globals.engine,
- globals.config_changed_handler);
+ globals.
+ config_changed_handler);
globals.config_changed_handler = 0;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]