summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--libgnomekbd/gkbd-keyboard-drawing.c438
-rw-r--r--libgnomekbd/gkbd-keyboard-drawing.h28
3 files changed, 302 insertions, 170 deletions
diff --git a/ChangeLog b/ChangeLog
index 56015c9..e9ee42c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2007-12-11 svu
+
+ * libgnomekbd/gkbd-keyboard-drawing.c,
+ libgnomekbd/gkbd-keyboard-drawing.h: draw to cairo, to make printing
+ possible, http://bugzilla.gnome.org/show_bug.cgi?id=502962
+
2007-12-05 svu
* libgnomekbd/Makefile.am: cygwin fixes,
diff --git a/libgnomekbd/gkbd-keyboard-drawing.c b/libgnomekbd/gkbd-keyboard-drawing.c
index e730cca..7572818 100644
--- a/libgnomekbd/gkbd-keyboard-drawing.c
+++ b/libgnomekbd/gkbd-keyboard-drawing.c
@@ -45,15 +45,15 @@ static void gkbd_keyboard_drawing_set_mods (GkbdKeyboardDrawing * drawing,
guint mods);
static gint
-xkb_to_pixmap_coord (GkbdKeyboardDrawing * drawing, gint n)
+xkb_to_pixmap_coord (GkbdKeyboardDrawingRenderContext * context, gint n)
{
- return n * drawing->scale_numerator / drawing->scale_denominator;
+ return n * context->scale_numerator / context->scale_denominator;
}
static gdouble
-xkb_to_pixmap_double (GkbdKeyboardDrawing * drawing, gdouble d)
+xkb_to_pixmap_double (GkbdKeyboardDrawingRenderContext * context, gdouble d)
{
- return d * drawing->scale_numerator / drawing->scale_denominator;
+ return d * context->scale_numerator / context->scale_denominator;
}
@@ -281,30 +281,24 @@ rounded_polygon (cairo_t * cr,
}
static void
-draw_polygon (GkbdKeyboardDrawing * drawing,
+draw_polygon (GkbdKeyboardDrawingRenderContext * context,
GdkColor * fill_color,
gint xkb_x,
gint xkb_y, XkbPointRec * xkb_points, guint num_points,
gdouble radius)
{
- GtkStateType state = GTK_WIDGET_STATE (GTK_WIDGET (drawing));
- cairo_t *cr;
GdkPoint *points;
gboolean filled;
gint i;
- if (drawing->pixmap == NULL)
- return;
-
if (fill_color) {
filled = TRUE;
} else {
- fill_color = &GTK_WIDGET (drawing)->style->dark[state];
+ fill_color = context->dark_color;
filled = FALSE;
}
- cr = gdk_cairo_create (GDK_DRAWABLE (drawing->pixmap));
- gdk_cairo_set_source_color (cr, fill_color);
+ gdk_cairo_set_source_color (context->cr, fill_color);
points = g_new (GdkPoint, num_points);
@@ -313,16 +307,16 @@ draw_polygon (GkbdKeyboardDrawing * drawing,
#endif
for (i = 0; i < num_points; i++) {
points[i].x =
- xkb_to_pixmap_coord (drawing, xkb_x + xkb_points[i].x);
+ xkb_to_pixmap_coord (context, xkb_x + xkb_points[i].x);
points[i].y =
- xkb_to_pixmap_coord (drawing, xkb_y + xkb_points[i].y);
+ xkb_to_pixmap_coord (context, xkb_y + xkb_points[i].y);
#ifdef KBDRAW_DEBUG
printf (" %d, %d\n", points[i].x, points[i].y);
#endif
}
- rounded_polygon (cr, filled,
- xkb_to_pixmap_double (drawing, radius),
+ rounded_polygon (context->cr, filled,
+ xkb_to_pixmap_double (context, radius),
points, num_points);
g_free (points);
@@ -358,14 +352,11 @@ curve_rectangle (cairo_t * cr,
}
static void
-draw_curve_rectangle (GdkPixmap * pixmap,
+draw_curve_rectangle (cairo_t *cr,
gboolean filled,
GdkColor * fill_color,
gint x, gint y, gint width, gint height, gint radius)
{
- cairo_t *cr;
-
- cr = gdk_cairo_create (GDK_DRAWABLE (pixmap));
curve_rectangle (cr, x, y, width, height, radius);
gdk_cairo_set_source_color (cr, fill_color);
@@ -374,45 +365,37 @@ draw_curve_rectangle (GdkPixmap * pixmap,
cairo_fill (cr);
else
cairo_stroke (cr);
-
- cairo_destroy (cr);
}
/* x, y, width, height are in the xkb coordinate system */
static void
-draw_rectangle (GkbdKeyboardDrawing * drawing,
+draw_rectangle (GkbdKeyboardDrawingRenderContext * context,
GdkColor * fill_color,
gint angle,
gint xkb_x, gint xkb_y, gint xkb_width, gint xkb_height,
gint radius)
-{
- if (drawing->pixmap == NULL)
- return;
-
+{
if (angle == 0) {
- GtkStateType state =
- GTK_WIDGET_STATE (GTK_WIDGET (drawing));
gint x, y, width, height;
gboolean filled;
if (fill_color) {
filled = TRUE;
} else {
- fill_color =
- &GTK_WIDGET (drawing)->style->dark[state];
+ fill_color = context->dark_color;
filled = FALSE;
}
- x = xkb_to_pixmap_coord (drawing, xkb_x);
- y = xkb_to_pixmap_coord (drawing, xkb_y);
+ x = xkb_to_pixmap_coord (context, xkb_x);
+ y = xkb_to_pixmap_coord (context, xkb_y);
width =
- xkb_to_pixmap_coord (drawing, xkb_x + xkb_width) - x;
+ xkb_to_pixmap_coord (context, xkb_x + xkb_width) - x;
height =
- xkb_to_pixmap_coord (drawing, xkb_y + xkb_height) - y;
+ xkb_to_pixmap_coord (context, xkb_y + xkb_height) - y;
- draw_curve_rectangle (drawing->pixmap, filled, fill_color,
+ draw_curve_rectangle (context->cr, filled, fill_color,
x, y, width, height,
- xkb_to_pixmap_double (drawing,
+ xkb_to_pixmap_double (context,
radius));
} else {
XkbPointRec points[4];
@@ -434,13 +417,13 @@ draw_rectangle (GkbdKeyboardDrawing * drawing,
points[3].y = y;
/* the points we've calculated are relative to 0,0 */
- draw_polygon (drawing, fill_color, 0, 0, points, 4,
+ draw_polygon (context, fill_color, 0, 0, points, 4,
radius);
}
}
static void
-draw_outline (GkbdKeyboardDrawing * drawing,
+draw_outline (GkbdKeyboardDrawingRenderContext * context,
XkbOutlineRec * outline,
GdkColor * color, gint angle, gint origin_x, gint origin_y)
{
@@ -450,7 +433,7 @@ draw_outline (GkbdKeyboardDrawing * drawing,
if (outline->num_points == 1) {
if (color)
- draw_rectangle (drawing, color, angle, origin_x,
+ draw_rectangle (context, color, angle, origin_x,
origin_y, outline->points[0].x,
outline->points[0].y,
outline->corner_radius);
@@ -460,7 +443,7 @@ draw_outline (GkbdKeyboardDrawing * drawing,
outline->points[0].y, outline->corner_radius);
#endif
- draw_rectangle (drawing, NULL, angle, origin_x, origin_y,
+ draw_rectangle (context, NULL, angle, origin_x, origin_y,
outline->points[0].x,
outline->points[0].y,
outline->corner_radius);
@@ -472,23 +455,23 @@ draw_outline (GkbdKeyboardDrawing * drawing,
origin_y + outline->points[0].y,
angle, &rotated_x0, &rotated_y0);
if (color)
- draw_rectangle (drawing, color, angle, rotated_x0,
+ draw_rectangle (context, color, angle, rotated_x0,
rotated_y0, outline->points[1].x,
outline->points[1].y,
outline->corner_radius);
- draw_rectangle (drawing, NULL, angle, rotated_x0,
+ draw_rectangle (context, NULL, angle, rotated_x0,
rotated_y0, outline->points[1].x,
outline->points[1].y,
outline->corner_radius);
} else {
if (color)
- draw_polygon (drawing, color, origin_x, origin_y,
+ draw_polygon (context, color, origin_x, origin_y,
outline->points,
outline->num_points,
outline->corner_radius);
- draw_polygon (drawing, NULL, origin_x, origin_y,
+ draw_polygon (context, NULL, origin_x, origin_y,
outline->points, outline->num_points,
outline->corner_radius);
}
@@ -623,11 +606,12 @@ find_keycode (GkbdKeyboardDrawing * drawing, gchar * key_name)
static void
-set_key_label_in_layout (GkbdKeyboardDrawing * drawing,
- PangoLayout * layout, guint keyval)
+set_key_label_in_layout (GkbdKeyboardDrawingRenderContext * context,
+ guint keyval)
{
gchar buf[5];
gunichar uc;
+ PangoLayout *layout = context->layout;
switch (keyval) {
case GDK_Scroll_Lock:
@@ -791,10 +775,11 @@ set_key_label_in_layout (GkbdKeyboardDrawing * drawing,
static void
-draw_pango_layout (GkbdKeyboardDrawing * drawing,
- gint angle, gint x, gint y, PangoLayout * layout)
+draw_pango_layout (GkbdKeyboardDrawingRenderContext * context,
+ GkbdKeyboardDrawing * drawing,
+ gint angle, gint x, gint y)
{
- GtkStateType state = GTK_WIDGET_STATE (GTK_WIDGET (drawing));
+ PangoLayout * layout = context->layout;
GdkColor *color;
PangoLayoutLine *line;
gint x_off, y_off;
@@ -804,23 +789,20 @@ draw_pango_layout (GkbdKeyboardDrawing * drawing,
drawing->colors + (drawing->xkb->geom->label_color -
drawing->xkb->geom->colors);
- if (drawing->pixmap == NULL)
- return;
-
- if (angle != drawing->angle) {
+ if (angle != context->angle) {
PangoMatrix matrix = PANGO_MATRIX_INIT;
pango_matrix_rotate (&matrix, -angle / 10.0);
- pango_context_set_matrix (gtk_widget_get_pango_context
- (GTK_WIDGET (drawing)), &matrix);
- pango_layout_context_changed (drawing->layout);
- drawing->angle = angle;
+ pango_context_set_matrix (pango_layout_get_context (layout),
+ &matrix);
+ pango_layout_context_changed (layout);
+ context->angle = angle;
}
i = 0;
y_off = 0;
- for (line = pango_layout_get_line (drawing->layout, i);
+ for (line = pango_layout_get_line (layout, i);
line != NULL;
- line = pango_layout_get_line (drawing->layout, ++i)) {
+ line = pango_layout_get_line (layout, ++i)) {
GSList *runp;
PangoRectangle line_extents;
@@ -842,18 +824,17 @@ draw_pango_layout (GkbdKeyboardDrawing * drawing,
pango_layout_line_get_extents (line, NULL, &line_extents);
y_off +=
- line_extents.height +
- pango_layout_get_spacing (drawing->layout);
+ line_extents.height + pango_layout_get_spacing (layout);
}
- gdk_draw_layout_with_colors (drawing->pixmap,
- GTK_WIDGET (drawing)->style->
- text_gc[state], x, y, drawing->layout,
- color, NULL);
+ cairo_move_to (context->cr, x, y);
+ gdk_cairo_set_source_color (context->cr, color);
+ pango_cairo_show_layout (context->cr, layout);
}
static void
-draw_key_label_helper (GkbdKeyboardDrawing * drawing,
+draw_key_label_helper (GkbdKeyboardDrawingRenderContext * context,
+ GkbdKeyboardDrawing * drawing,
KeySym keysym,
gint angle,
GkbdKeyboardDrawingGroupLevelPosition glp,
@@ -907,17 +888,22 @@ draw_key_label_helper (GkbdKeyboardDrawing * drawing,
default:
return;
}
- set_key_label_in_layout (drawing, drawing->layout, keysym);
- pango_layout_set_width (drawing->layout, label_max_width);
- label_y -= (pango_layout_get_line_count (drawing->layout) - 1) *
- (pango_font_description_get_size (drawing->font_desc) /
+ set_key_label_in_layout (context, keysym);
+ pango_layout_set_width (context->layout, label_max_width);
+ label_y -= (pango_layout_get_line_count (context->layout) - 1) *
+ (pango_font_description_get_size (context->font_desc) /
PANGO_SCALE);
- draw_pango_layout (drawing, angle, label_x, label_y,
- drawing->layout);
+ cairo_save (context->cr);
+ cairo_rectangle (context->cr, x + padding / 2, y + padding / 2,
+ width - padding, height - padding);
+ cairo_clip (context->cr);
+ draw_pango_layout (context, drawing, angle, label_x, label_y);
+ cairo_restore (context->cr);
}
static void
-draw_key_label (GkbdKeyboardDrawing * drawing,
+draw_key_label (GkbdKeyboardDrawingRenderContext * context,
+ GkbdKeyboardDrawing * drawing,
guint keycode,
gint angle,
gint xkb_origin_x,
@@ -930,14 +916,14 @@ draw_key_label (GkbdKeyboardDrawing * drawing,
if (!drawing->xkb)
return;
- padding = 23 * drawing->scale_numerator / drawing->scale_denominator; /* 2.3mm */
+ padding = 23 * context->scale_numerator / context->scale_denominator; /* 2.3mm */
- x = xkb_to_pixmap_coord (drawing, xkb_origin_x);
- y = xkb_to_pixmap_coord (drawing, xkb_origin_y);
+ x = xkb_to_pixmap_coord (context, xkb_origin_x);
+ y = xkb_to_pixmap_coord (context, xkb_origin_y);
width =
- xkb_to_pixmap_coord (drawing, xkb_origin_x + xkb_width) - x;
+ xkb_to_pixmap_coord (context, xkb_origin_x + xkb_width) - x;
height =
- xkb_to_pixmap_coord (drawing, xkb_origin_y + xkb_height) - y;
+ xkb_to_pixmap_coord (context, xkb_origin_y + xkb_height) - y;
for (glp = GKBD_KEYBOARD_DRAWING_POS_TOPLEFT;
glp < GKBD_KEYBOARD_DRAWING_POS_TOTAL; glp++) {
@@ -968,7 +954,7 @@ draw_key_label (GkbdKeyboardDrawing * drawing,
XkbBuildCoreState
(drawing->mods, g),
&mods_rtrn, &keysym)) {
- draw_key_label_helper (drawing, keysym,
+ draw_key_label_helper (context, drawing, keysym,
angle, glp, x, y,
width, height,
padding);
@@ -980,8 +966,8 @@ draw_key_label (GkbdKeyboardDrawing * drawing,
keysym =
XkbKeySymEntry (drawing->xkb, keycode, l, g);
- draw_key_label_helper (drawing, keysym, angle, glp,
- x, y, width, height,
+ draw_key_label_helper (context, drawing, keysym, angle,
+ glp, x, y, width, height,
padding);
/* reverse y order */
}
@@ -990,7 +976,9 @@ draw_key_label (GkbdKeyboardDrawing * drawing,
/* groups are from 0-3 */
static void
-draw_key (GkbdKeyboardDrawing * drawing, GkbdKeyboardDrawingKey * key)
+draw_key (GkbdKeyboardDrawingRenderContext * context,
+ GkbdKeyboardDrawing * drawing,
+ GkbdKeyboardDrawingKey * key)
{
XkbShapeRec *shape;
GdkColor *color;
@@ -1022,7 +1010,7 @@ draw_key (GkbdKeyboardDrawing * drawing, GkbdKeyboardDrawingKey * key)
#endif
/* draw the primary outline */
- draw_outline (drawing,
+ draw_outline (context,
shape->primary ? shape->primary : shape->outlines,
color, key->angle, key->origin_x, key->origin_y);
#if 0
@@ -1033,13 +1021,14 @@ draw_key (GkbdKeyboardDrawing * drawing, GkbdKeyboardDrawingKey * key)
if (shape->outlines + i == shape->approx ||
shape->outlines + i == shape->primary)
continue;
- draw_outline (drawing, shape->outlines + i, NULL,
+ draw_outline (context, shape->outlines + i, NULL,
key->angle, key->origin_x, key->origin_y);
}
#endif
- draw_key_label (drawing, key->keycode, key->angle, key->origin_x,
- key->origin_y, shape->bounds.x2, shape->bounds.y2);
+ draw_key_label (context, drawing, key->keycode, key->angle,
+ key->origin_x, key->origin_y,
+ shape->bounds.x2, shape->bounds.y2);
}
static void
@@ -1079,10 +1068,12 @@ invalidate_region (GkbdKeyboardDrawing * drawing,
MAX (MAX (points[0].y, points[1].y),
MAX (points[2].y, points[3].y));
- x = xkb_to_pixmap_coord (drawing, origin_x + x_min) - 6;
- y = xkb_to_pixmap_coord (drawing, origin_y + y_min) - 6;
- width = xkb_to_pixmap_coord (drawing, x_max - x_min) + 12;
- height = xkb_to_pixmap_coord (drawing, y_max - y_min) + 12;
+ x = xkb_to_pixmap_coord (drawing->renderContext, origin_x + x_min) - 6;
+ y = xkb_to_pixmap_coord (drawing->renderContext, origin_y + y_min) - 6;
+ width = xkb_to_pixmap_coord (drawing->renderContext,
+ x_max - x_min) + 12;
+ height = xkb_to_pixmap_coord (drawing->renderContext,
+ y_max - y_min) + 12;
gtk_widget_queue_draw_area (GTK_WIDGET (drawing), x, y, width,
height);
@@ -1122,7 +1113,8 @@ invalidate_key_region (GkbdKeyboardDrawing * drawing,
}
static void
-draw_text_doodad (GkbdKeyboardDrawing * drawing,
+draw_text_doodad (GkbdKeyboardDrawingRenderContext * context,
+ GkbdKeyboardDrawing * drawing,
GkbdKeyboardDrawingDoodad * doodad,
XkbTextDoodadRec * text_doodad)
{
@@ -1130,17 +1122,18 @@ draw_text_doodad (GkbdKeyboardDrawing * drawing,
if (!drawing->xkb)
return;
- x = xkb_to_pixmap_coord (drawing,
+ x = xkb_to_pixmap_coord (context,
doodad->origin_x + text_doodad->left);
- y = xkb_to_pixmap_coord (drawing,
+ y = xkb_to_pixmap_coord (context,
doodad->origin_y + text_doodad->top);
- pango_layout_set_text (drawing->layout, text_doodad->text, -1);
- draw_pango_layout (drawing, doodad->angle, x, y, drawing->layout);
+ pango_layout_set_text (context->layout, text_doodad->text, -1);
+ draw_pango_layout (context, drawing, doodad->angle, x, y);
}
static void
-draw_indicator_doodad (GkbdKeyboardDrawing * drawing,
+draw_indicator_doodad (GkbdKeyboardDrawingRenderContext * context,
+ GkbdKeyboardDrawing * drawing,
GkbdKeyboardDrawingDoodad * doodad,
XkbIndicatorDoodadRec * indicator_doodad)
{
@@ -1158,14 +1151,15 @@ draw_indicator_doodad (GkbdKeyboardDrawing * drawing,
indicator_doodad->off_color_ndx);
for (i = 0; i < 1; i++)
- draw_outline (drawing, shape->outlines + i, color,
+ draw_outline (context, shape->outlines + i, color,
doodad->angle,
doodad->origin_x + indicator_doodad->left,
doodad->origin_y + indicator_doodad->top);
}
static void
-draw_shape_doodad (GkbdKeyboardDrawing * drawing,
+draw_shape_doodad (GkbdKeyboardDrawingRenderContext * context,
+ GkbdKeyboardDrawing * drawing,
GkbdKeyboardDrawingDoodad * doodad,
XkbShapeDoodadRec * shape_doodad)
{
@@ -1180,7 +1174,7 @@ draw_shape_doodad (GkbdKeyboardDrawing * drawing,
color = drawing->colors + shape_doodad->color_ndx;
/* draw the primary outline filled */
- draw_outline (drawing,
+ draw_outline (context,
shape->primary ? shape->primary : shape->outlines,
color, doodad->angle,
doodad->origin_x + shape_doodad->left,
@@ -1191,7 +1185,7 @@ draw_shape_doodad (GkbdKeyboardDrawing * drawing,
if (shape->outlines + i == shape->approx ||
shape->outlines + i == shape->primary)
continue;
- draw_outline (drawing, shape->outlines + i, NULL,
+ draw_outline (context, shape->outlines + i, NULL,
doodad->angle,
doodad->origin_x + shape_doodad->left,
doodad->origin_y + shape_doodad->top);
@@ -1199,53 +1193,94 @@ draw_shape_doodad (GkbdKeyboardDrawing * drawing,
}
static void
-draw_doodad (GkbdKeyboardDrawing * drawing,
+draw_doodad (GkbdKeyboardDrawingRenderContext * context,
+ GkbdKeyboardDrawing * drawing,
GkbdKeyboardDrawingDoodad * doodad)
{
switch (doodad->doodad->any.type) {
case XkbOutlineDoodad:
case XkbSolidDoodad:
- draw_shape_doodad (drawing, doodad,
+ draw_shape_doodad (context, drawing, doodad,
&doodad->doodad->shape);
break;
case XkbTextDoodad:
- draw_text_doodad (drawing, doodad, &doodad->doodad->text);
+ draw_text_doodad (context, drawing, doodad,
+ &doodad->doodad->text);
break;
case XkbIndicatorDoodad:
- draw_indicator_doodad (drawing, doodad,
+ draw_indicator_doodad (context, drawing, doodad,
&doodad->doodad->indicator);
break;
case XkbLogoDoodad:
/* g_print ("draw_doodad: logo: %s\n", doodad->doodad->logo.logo_name); */
/* XkbLogoDoodadRec is essentially a subclass of XkbShapeDoodadRec */
- draw_shape_doodad (drawing, doodad,
+ draw_shape_doodad (context, drawing, doodad,
&doodad->doodad->shape);
break;
}
}
+typedef struct {
+ GkbdKeyboardDrawing * drawing;
+ GkbdKeyboardDrawingRenderContext * context;
+} DrawKeyboardItemData;
+
static void
draw_keyboard_item (GkbdKeyboardDrawingItem * item,
- GkbdKeyboardDrawing * drawing)
+ DrawKeyboardItemData *data)
{
+ GkbdKeyboardDrawing * drawing = data->drawing;
+ GkbdKeyboardDrawingRenderContext * context = data->context;
+
if (!drawing->xkb)
return;
switch (item->type) {
case GKBD_KEYBOARD_DRAWING_ITEM_TYPE_KEY:
- draw_key (drawing, (GkbdKeyboardDrawingKey *) item);
+ draw_key (context, drawing, (GkbdKeyboardDrawingKey *) item);
break;
case GKBD_KEYBOARD_DRAWING_ITEM_TYPE_DOODAD:
- draw_doodad (drawing, (GkbdKeyboardDrawingDoodad *) item);
+ draw_doodad (context, drawing,
+ (GkbdKeyboardDrawingDoodad *) item);
break;
}
}
static void
+draw_keyboard_to_context (GkbdKeyboardDrawingRenderContext * context,
+ GkbdKeyboardDrawing * drawing)
+{
+ DrawKeyboardItemData data = { drawing, context };
+#ifdef KBDRAW_DEBUG
+ printf ("mods: %d\n", drawing->mods);
+#endif
+ g_list_foreach (drawing->keyboard_items,
+ (GFunc) draw_keyboard_item, &data);
+}
+
+static void
+create_cairo (GkbdKeyboardDrawing * drawing)
+{
+ GtkStateType state = GTK_WIDGET_STATE (GTK_WIDGET (drawing));
+ drawing->renderContext->cr =
+ gdk_cairo_create (GDK_DRAWABLE (drawing->pixmap));
+ drawing->renderContext->dark_color =
+ &GTK_WIDGET (drawing)->style->dark[state];
+}
+
+static void
+destroy_cairo (GkbdKeyboardDrawing * drawing)
+{
+ cairo_destroy (drawing->renderContext->cr);
+ drawing->renderContext->cr = NULL;
+ drawing->renderContext->dark_color = NULL;
+}
+
+static void
draw_keyboard (GkbdKeyboardDrawing * drawing)
{
GtkStateType state = GTK_WIDGET_STATE (GTK_WIDGET (drawing));
@@ -1265,31 +1300,40 @@ draw_keyboard (GkbdKeyboardDrawing * drawing)
GTK_WIDGET (drawing)->style->base_gc[state],
TRUE, 0, 0, pixw, pixh);
- if (drawing->xkb == NULL)
- return;
-
-#ifdef KBDRAW_DEBUG
- printf ("mods: %d\n", drawing->mods);
-#endif
-
- g_list_foreach (drawing->keyboard_items,
- (GFunc) draw_keyboard_item, drawing);
+ create_cairo (drawing);
+ draw_keyboard_to_context (drawing->renderContext, drawing);
+ destroy_cairo (drawing);
}
static void
-alloc_pango_layout (GkbdKeyboardDrawing * drawing)
+alloc_render_context (GkbdKeyboardDrawing * drawing)
{
- PangoContext *context =
+ GkbdKeyboardDrawingRenderContext * context =
+ drawing->renderContext =
+ g_new0(GkbdKeyboardDrawingRenderContext, 1);
+
+ PangoContext *pangoContext =
gtk_widget_get_pango_context (GTK_WIDGET (drawing));
- drawing->layout = pango_layout_new (context);
- pango_layout_set_ellipsize (drawing->layout, PANGO_ELLIPSIZE_END);
+ context->layout = pango_layout_new (pangoContext);
+ pango_layout_set_ellipsize (context->layout, PANGO_ELLIPSIZE_END);
+
+ context->font_desc =
+ pango_font_description_copy (GTK_WIDGET (drawing)->style->
+ font_desc);
+ context->angle = 0;
+ context->scale_numerator = 1;
+ context->scale_denominator = 1;
}
static void
-free_pango_layout (GkbdKeyboardDrawing * drawing)
+free_render_context (GkbdKeyboardDrawing * drawing)
{
- g_object_unref (G_OBJECT (drawing->layout));
- drawing->layout = NULL;
+ GkbdKeyboardDrawingRenderContext * context = drawing->renderContext;
+ g_object_unref (G_OBJECT (context->layout));
+ pango_font_description_free (context->font_desc);
+
+ g_free (drawing->renderContext);
+ drawing->renderContext = NULL;
}
static gboolean
@@ -1333,42 +1377,59 @@ idle_redraw (gpointer user_data)
return FALSE;
}
-static void
-size_allocate (GtkWidget * widget,
- GtkAllocation * allocation, GkbdKeyboardDrawing * drawing)
+static gboolean
+context_setup_scaling (GkbdKeyboardDrawingRenderContext * context,
+ GkbdKeyboardDrawing * drawing,
+ gdouble width, gdouble height,
+ gdouble dpi_x, gdouble dpi_y)
{
if (!drawing->xkb)
- return;
-
- if (drawing->pixmap) {
- g_object_unref (drawing->pixmap);
- drawing->pixmap = NULL;
- }
+ return FALSE;
if (drawing->xkb->geom->width_mm <= 0
|| drawing->xkb->geom->height_mm <= 0) {
g_critical
("keyboard geometry reports width or height as zero!");
- return;
+ return FALSE;
}
- if (allocation->width * drawing->xkb->geom->height_mm <
- allocation->height * drawing->xkb->geom->width_mm) {
- drawing->scale_numerator = allocation->width;
- drawing->scale_denominator = drawing->xkb->geom->width_mm;
+ if (width * drawing->xkb->geom->height_mm <
+ height * drawing->xkb->geom->width_mm) {
+ context->scale_numerator = width;
+ context->scale_denominator = drawing->xkb->geom->width_mm;
} else {
- drawing->scale_numerator = allocation->height;
- drawing->scale_denominator = drawing->xkb->geom->height_mm;
+ context->scale_numerator = height;
+ context->scale_denominator = drawing->xkb->geom->height_mm;
}
- pango_font_description_set_size (drawing->font_desc,
- 36000 * drawing->scale_numerator /
- drawing->scale_denominator);
- pango_layout_set_spacing (drawing->layout,
- -8000 * drawing->scale_numerator /
- drawing->scale_denominator);
- pango_layout_set_font_description (drawing->layout,
- drawing->font_desc);
+ pango_font_description_set_size (context->font_desc,
+ 720 * dpi_x *
+ context->scale_numerator /
+ context->scale_denominator);
+ pango_layout_set_spacing (context->layout,
+ -160 * dpi_y * context->scale_numerator /
+ context->scale_denominator);
+ pango_layout_set_font_description (context->layout,
+ context->font_desc);
+
+ return TRUE;
+}
+
+static void
+size_allocate (GtkWidget * widget,
+ GtkAllocation * allocation, GkbdKeyboardDrawing * drawing)
+{
+ GkbdKeyboardDrawingRenderContext * context = drawing->renderContext;
+
+ if (drawing->pixmap) {
+ g_object_unref (drawing->pixmap);
+ drawing->pixmap = NULL;
+ }
+
+ if (!context_setup_scaling (context, drawing,
+ allocation->width, allocation->height,
+ 50, 50))
+ return;
if (!drawing->idle_redraw)
drawing->idle_redraw = g_idle_add (idle_redraw, drawing);
@@ -1400,7 +1461,9 @@ key_event (GtkWidget * widget,
key->pressed = (event->type == GDK_KEY_PRESS);
- draw_key (drawing, key);
+ create_cairo (drawing);
+ draw_key (drawing->renderContext, drawing, key);
+ destroy_cairo (drawing);
invalidate_key_region (drawing, key);
@@ -1426,13 +1489,16 @@ unpress_keys (GkbdKeyboardDrawing * drawing)
if (!drawing->xkb)
return FALSE;
+ create_cairo (drawing);
for (i = drawing->xkb->min_key_code;
i <= drawing->xkb->max_key_code; i++)
if (drawing->keys[i].pressed) {
drawing->keys[i].pressed = FALSE;
- draw_key (drawing, drawing->keys + i);
+ draw_key (drawing->renderContext, drawing,
+ drawing->keys + i);
invalidate_key_region (drawing, drawing->keys + i);
}
+ destroy_cairo (drawing);
return FALSE;
}
@@ -1792,7 +1858,9 @@ xkb_state_notify_event_filter (GdkXEvent * gdkxev,
[i]->on =
state;
draw_doodad
- (drawing,
+ (drawing->
+ renderContext,
+ drawing,
drawing->
physical_indicators
[i]);
@@ -1832,7 +1900,7 @@ xkb_state_notify_event_filter (GdkXEvent * gdkxev,
static void
destroy (GkbdKeyboardDrawing * drawing)
{
- free_pango_layout (drawing);
+ free_render_context (drawing);
gdk_window_remove_filter (NULL, (GdkFilterFunc)
xkb_state_notify_event_filter, drawing);
if (drawing->timeout > 0) {
@@ -1850,7 +1918,7 @@ destroy (GkbdKeyboardDrawing * drawing)
static void
style_changed (GkbdKeyboardDrawing * drawing)
{
- pango_layout_context_changed (drawing->layout);
+ pango_layout_context_changed (drawing->renderContext->layout);
}
static void
@@ -1882,16 +1950,10 @@ gkbd_keyboard_drawing_init (GkbdKeyboardDrawing * drawing)
gdk_screen_get_number (gdk_screen_get_default ());
drawing->pixmap = NULL;
- alloc_pango_layout (drawing);
+ alloc_render_context (drawing);
- drawing->font_desc =
- pango_font_description_copy (GTK_WIDGET (drawing)->style->
- font_desc);
drawing->keyboard_items = NULL;
drawing->colors = NULL;
- drawing->angle = 0;
- drawing->scale_numerator = 1;
- drawing->scale_denominator = 1;
drawing->track_modifiers = 0;
drawing->track_config = 0;
@@ -2038,23 +2100,71 @@ gkbd_keyboard_drawing_set_mods (GkbdKeyboardDrawing * drawing, guint mods)
GdkPixbuf *
gkbd_keyboard_drawing_get_pixbuf (GkbdKeyboardDrawing * drawing)
{
+ GkbdKeyboardDrawingRenderContext * context = drawing->renderContext;
+
if (drawing->pixmap == NULL)
draw_keyboard (drawing);
return gdk_pixbuf_get_from_drawable (NULL, drawing->pixmap, NULL,
0, 0, 0, 0,
- xkb_to_pixmap_coord (drawing,
+ xkb_to_pixmap_coord (context,
drawing->
xkb->
geom->
width_mm),
- xkb_to_pixmap_coord (drawing,
+ xkb_to_pixmap_coord (context,
drawing->
xkb->
geom->
height_mm));
}
+/**
+ * gkbd_keyboard_drawing_render:
+ * @drawing: keyboard layout to render
+ * @cr: Cairo context to render to
+ * @layout: Pango layout to use to render text
+ * @x: left coordinate (pixels) of region to render in
+ * @y: top coordinate (pixels) of region to render in
+ * @width: width (pixels) of region to render in
+ * @height: height (pixels) of region to render in
+ *
+ * Renders a keyboard layout to a cairo_t context. @cr and @layout can be got
+ * from e.g. a GtkWidget or a GtkPrintContext. @cr and @layout may be modified
+ * by the function but will not be unreffed.
+ *
+ * @returns: %TRUE on success, %FALSE on failure
+ */
+gboolean gkbd_keyboard_drawing_render (GkbdKeyboardDrawing * drawing,
+ cairo_t * cr,
+ PangoLayout * layout,
+ double x, double y,
+ double width, double height,
+ double dpi_x, double dpi_y)
+{
+ GkbdKeyboardDrawingRenderContext context = {
+ cr,
+ drawing->renderContext->angle,
+ layout,
+ pango_font_description_copy (GTK_WIDGET (drawing)->style->
+ font_desc),
+ 1, 1,
+ &GTK_WIDGET (drawing)->style->dark[GTK_WIDGET_STATE
+ (GTK_WIDGET (drawing))]
+ };
+
+ if (!context_setup_scaling (&context, drawing, width, height,
+ dpi_x, dpi_y))
+ return FALSE;
+ cairo_translate (cr, x, y);
+
+ draw_keyboard_to_context (&context, drawing);
+
+ pango_font_description_free (context.font_desc);
+
+ return TRUE;
+}
+
gboolean
gkbd_keyboard_drawing_set_keyboard (GkbdKeyboardDrawing * drawing,
XkbComponentNamesRec * names)
diff --git a/libgnomekbd/gkbd-keyboard-drawing.h b/libgnomekbd/gkbd-keyboard-drawing.h
index 2fd4a89..8e7cf81 100644
--- a/libgnomekbd/gkbd-keyboard-drawing.h
+++ b/libgnomekbd/gkbd-keyboard-drawing.h
@@ -38,6 +38,8 @@ typedef struct _GkbdKeyboardDrawingKey GkbdKeyboardDrawingKey;
typedef struct _GkbdKeyboardDrawingDoodad GkbdKeyboardDrawingDoodad;
typedef struct _GkbdKeyboardDrawingGroupLevel
GkbdKeyboardDrawingGroupLevel;
+typedef struct _GkbdKeyboardDrawingRenderContext
+ GkbdKeyboardDrawingRenderContext;
typedef enum {
GKBD_KEYBOARD_DRAWING_ITEM_TYPE_KEY,
@@ -101,6 +103,19 @@ struct _GkbdKeyboardDrawingGroupLevel {
gint level;
};
+struct _GkbdKeyboardDrawingRenderContext {
+ cairo_t * cr;
+
+ gint angle; /* current angle pango is set to draw at, in tenths of a degree */
+ PangoLayout *layout;
+ PangoFontDescription *font_desc;
+
+ gint scale_numerator;
+ gint scale_denominator;
+
+ GdkColor *dark_color;
+};
+
struct _GkbdKeyboardDrawing {
/*< private > */
@@ -111,12 +126,7 @@ struct _GkbdKeyboardDrawing {
gboolean xkbOnDisplay;
guint l3mod;
- gint angle; /* current angle pango is set to draw at, in tenths of a degree */
- PangoLayout *layout;
- PangoFontDescription *font_desc;
-
- gint scale_numerator;
- gint scale_denominator;
+ GkbdKeyboardDrawingRenderContext *renderContext;
GkbdKeyboardDrawingKey *keys;
@@ -158,6 +168,12 @@ GtkWidget *gkbd_keyboard_drawing_new (void);
GdkPixbuf *gkbd_keyboard_drawing_get_pixbuf (GkbdKeyboardDrawing *
kbdrawing);
+gboolean gkbd_keyboard_drawing_render (GkbdKeyboardDrawing * kbdrawing,
+ cairo_t * cr,
+ PangoLayout * layout,
+ double x, double y,
+ double width, double height,
+ gdouble dpi_x, gdouble dpi_y);
gboolean gkbd_keyboard_drawing_set_keyboard (GkbdKeyboardDrawing *
kbdrawing,
XkbComponentNamesRec * names);