Add comment for borrowed code.
This commit is contained in:
@ -1,4 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
|
* Copyright (C) 2006 Sergey V. Udaltsov <svu@gnome.org>
|
||||||
* Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
|
* Copyright (C) 2010 Daiki Ueno <ueno@unixuser.org>
|
||||||
* Copyright (C) 2010 Red Hat, Inc.
|
* Copyright (C) 2010 Red Hat, Inc.
|
||||||
*
|
*
|
||||||
@ -23,6 +24,8 @@
|
|||||||
* @short_description: Custom #ClutterActor drawing a key shape
|
* @short_description: Custom #ClutterActor drawing a key shape
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <cogl/cogl.h>
|
||||||
|
#include <cogl/cogl-pango.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
@ -30,8 +33,6 @@
|
|||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
#include "eek-clutter-key-actor.h"
|
#include "eek-clutter-key-actor.h"
|
||||||
#include "eek-keysym.h"
|
#include "eek-keysym.h"
|
||||||
#include <cogl/cogl.h>
|
|
||||||
#include <cogl/cogl-pango.h>
|
|
||||||
|
|
||||||
#define noKBDRAW_DEBUG
|
#define noKBDRAW_DEBUG
|
||||||
|
|
||||||
@ -66,6 +67,11 @@ static void draw_key_on_layout (EekKey *key,
|
|||||||
PangoLayout *layout);
|
PangoLayout *layout);
|
||||||
static void key_enlarge (ClutterActor *actor);
|
static void key_enlarge (ClutterActor *actor);
|
||||||
static void key_shrink (ClutterActor *actor);
|
static void key_shrink (ClutterActor *actor);
|
||||||
|
static void draw_rounded_polygon (cairo_t *cr,
|
||||||
|
gboolean filled,
|
||||||
|
gdouble radius,
|
||||||
|
EekPoint *points,
|
||||||
|
gint num_points);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
eek_clutter_key_actor_real_paint (ClutterActor *self)
|
eek_clutter_key_actor_real_paint (ClutterActor *self)
|
||||||
@ -101,7 +107,8 @@ eek_clutter_key_actor_real_paint (ClutterActor *self)
|
|||||||
/* FIXME: Color should be configurable through a property. */
|
/* FIXME: Color should be configurable through a property. */
|
||||||
cogl_color_set_from_4ub (&color, 0x80, 0x00, 0x00, 0xff);
|
cogl_color_set_from_4ub (&color, 0x80, 0x00, 0x00, 0xff);
|
||||||
clutter_actor_get_allocation_geometry (self, &geom);
|
clutter_actor_get_allocation_geometry (self, &geom);
|
||||||
cogl_pango_render_layout (layout,
|
cogl_pango_render_layout
|
||||||
|
(layout,
|
||||||
(geom.width - logical_rect.width / PANGO_SCALE) / 2,
|
(geom.width - logical_rect.width / PANGO_SCALE) / 2,
|
||||||
(geom.height - logical_rect.height / PANGO_SCALE) / 2,
|
(geom.height - logical_rect.height / PANGO_SCALE) / 2,
|
||||||
&color,
|
&color,
|
||||||
@ -302,6 +309,134 @@ key_shrink (ClutterActor *actor)
|
|||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ClutterActor *
|
||||||
|
create_texture_for_key (EekKey *key)
|
||||||
|
{
|
||||||
|
ClutterActor *texture;
|
||||||
|
cairo_t *cr;
|
||||||
|
cairo_pattern_t *pat;
|
||||||
|
EekOutline *outline;
|
||||||
|
EekBounds bounds;
|
||||||
|
|
||||||
|
outline = eek_key_get_outline (EEK_KEY(key));
|
||||||
|
eek_element_get_bounds (EEK_ELEMENT(key), &bounds);
|
||||||
|
|
||||||
|
texture = clutter_cairo_texture_new (bounds.width, bounds.height);
|
||||||
|
cr = clutter_cairo_texture_create (CLUTTER_CAIRO_TEXTURE(texture));
|
||||||
|
cairo_set_line_width (cr, 1);
|
||||||
|
cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
|
||||||
|
|
||||||
|
pat = cairo_pattern_create_linear (0.0, 0.0, 0.0, 256.0);
|
||||||
|
cairo_pattern_add_color_stop_rgba (pat, 1, 0.5, 0.5, 0.5, 1);
|
||||||
|
cairo_pattern_add_color_stop_rgba (pat, 0, 1, 1, 1, 1);
|
||||||
|
|
||||||
|
cairo_set_source (cr, pat);
|
||||||
|
|
||||||
|
draw_rounded_polygon (cr,
|
||||||
|
TRUE,
|
||||||
|
outline->corner_radius,
|
||||||
|
outline->points,
|
||||||
|
outline->num_points);
|
||||||
|
|
||||||
|
cairo_pattern_destroy (pat);
|
||||||
|
|
||||||
|
cairo_set_source_rgba (cr, 0.3, 0.3, 0.3, 0.5);
|
||||||
|
draw_rounded_polygon (cr,
|
||||||
|
FALSE,
|
||||||
|
outline->corner_radius,
|
||||||
|
outline->points,
|
||||||
|
outline->num_points);
|
||||||
|
cairo_destroy (cr);
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ClutterActor *
|
||||||
|
get_texture (EekClutterKeyActor *actor)
|
||||||
|
{
|
||||||
|
ClutterActor *texture;
|
||||||
|
EekOutline *outline;
|
||||||
|
|
||||||
|
if (!texture_cache.outline_textures)
|
||||||
|
texture_cache.outline_textures = g_hash_table_new_full (g_direct_hash,
|
||||||
|
g_direct_equal,
|
||||||
|
NULL,
|
||||||
|
g_free);
|
||||||
|
outline = eek_key_get_outline (actor->priv->key);
|
||||||
|
texture = g_hash_table_lookup (texture_cache.outline_textures, outline);
|
||||||
|
if (texture == NULL) {
|
||||||
|
texture = create_texture_for_key (actor->priv->key);
|
||||||
|
g_hash_table_insert (texture_cache.outline_textures, outline, texture);
|
||||||
|
} else
|
||||||
|
texture = clutter_clone_new (texture);
|
||||||
|
texture_cache.outline_textures_ref_count++;
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
draw_text_on_layout (PangoLayout *layout,
|
||||||
|
const gchar *text,
|
||||||
|
gdouble scale)
|
||||||
|
{
|
||||||
|
PangoFontDescription *font_desc;
|
||||||
|
|
||||||
|
#define FONT_SIZE (720 * 50)
|
||||||
|
/* FIXME: Font should be configurable through a property. */
|
||||||
|
font_desc = pango_font_description_from_string ("Sans");
|
||||||
|
pango_font_description_set_size (font_desc, FONT_SIZE * scale);
|
||||||
|
pango_layout_set_font_description (layout, font_desc);
|
||||||
|
pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
|
||||||
|
pango_layout_set_text (layout, text, -1);
|
||||||
|
pango_font_description_free (font_desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
draw_key_on_layout (EekKey *key,
|
||||||
|
PangoLayout *layout)
|
||||||
|
{
|
||||||
|
PangoLayout *buffer;
|
||||||
|
PangoRectangle logical_rect = { 0, };
|
||||||
|
EekBounds bounds;
|
||||||
|
guint keysym;
|
||||||
|
const gchar *label, *empty_label = "";
|
||||||
|
gdouble scale_x, scale_y;
|
||||||
|
|
||||||
|
eek_element_get_bounds (EEK_ELEMENT(key), &bounds);
|
||||||
|
keysym = eek_key_get_keysym (key);
|
||||||
|
if (keysym == EEK_INVALID_KEYSYM)
|
||||||
|
return;
|
||||||
|
label = eek_keysym_to_string (keysym);
|
||||||
|
if (!label)
|
||||||
|
label = empty_label;
|
||||||
|
|
||||||
|
/* Compute the layout extents. */
|
||||||
|
buffer = pango_layout_copy (layout);
|
||||||
|
draw_text_on_layout (buffer, label, 1.0);
|
||||||
|
pango_layout_get_extents (buffer, NULL, &logical_rect);
|
||||||
|
scale_x = scale_y = 1.0;
|
||||||
|
if (PANGO_PIXELS(logical_rect.width) > bounds.width)
|
||||||
|
scale_x = bounds.width / PANGO_PIXELS(logical_rect.width);
|
||||||
|
if (PANGO_PIXELS(logical_rect.height) > bounds.height)
|
||||||
|
scale_y = bounds.height / PANGO_PIXELS(logical_rect.height);
|
||||||
|
g_object_unref (buffer);
|
||||||
|
|
||||||
|
/* Actually draw on the layout */
|
||||||
|
draw_text_on_layout (layout,
|
||||||
|
label,
|
||||||
|
(scale_x < scale_y ? scale_x : scale_y) * 0.8);
|
||||||
|
if (label != empty_label)
|
||||||
|
g_free ((gpointer)label);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The functions below are borrowed from
|
||||||
|
* libgnomekbd/gkbd-keyboard-drawing.c.
|
||||||
|
* Copyright (C) 2006 Sergey V. Udaltsov <svu@gnome.org>
|
||||||
|
*
|
||||||
|
* length(), point_line_distance(), normal_form(), inverse(), multiply(),
|
||||||
|
* intersect(), rounded_corner(), draw_rounded_polygon()
|
||||||
|
*/
|
||||||
|
|
||||||
static gdouble
|
static gdouble
|
||||||
length (gdouble x, gdouble y)
|
length (gdouble x, gdouble y)
|
||||||
{
|
{
|
||||||
@ -469,7 +604,7 @@ rounded_corner (cairo_t * cr,
|
|||||||
cairo_line_to (cr, cx, cy);
|
cairo_line_to (cr, cx, cy);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
draw_rounded_polygon (cairo_t *cr,
|
draw_rounded_polygon (cairo_t *cr,
|
||||||
gboolean filled,
|
gboolean filled,
|
||||||
gdouble radius,
|
gdouble radius,
|
||||||
@ -508,121 +643,3 @@ draw_rounded_polygon (cairo_t *cr,
|
|||||||
else
|
else
|
||||||
cairo_stroke (cr);
|
cairo_stroke (cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ClutterActor *
|
|
||||||
create_texture_for_key (EekKey *key)
|
|
||||||
{
|
|
||||||
ClutterActor *texture;
|
|
||||||
cairo_t *cr;
|
|
||||||
cairo_pattern_t *pat;
|
|
||||||
EekOutline *outline;
|
|
||||||
EekBounds bounds;
|
|
||||||
|
|
||||||
outline = eek_key_get_outline (EEK_KEY(key));
|
|
||||||
eek_element_get_bounds (EEK_ELEMENT(key), &bounds);
|
|
||||||
|
|
||||||
texture = clutter_cairo_texture_new (bounds.width, bounds.height);
|
|
||||||
cr = clutter_cairo_texture_create (CLUTTER_CAIRO_TEXTURE(texture));
|
|
||||||
cairo_set_line_width (cr, 1);
|
|
||||||
cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
|
|
||||||
|
|
||||||
pat = cairo_pattern_create_linear (0.0, 0.0, 0.0, 256.0);
|
|
||||||
cairo_pattern_add_color_stop_rgba (pat, 1, 0.5, 0.5, 0.5, 1);
|
|
||||||
cairo_pattern_add_color_stop_rgba (pat, 0, 1, 1, 1, 1);
|
|
||||||
|
|
||||||
cairo_set_source (cr, pat);
|
|
||||||
|
|
||||||
draw_rounded_polygon (cr,
|
|
||||||
TRUE,
|
|
||||||
outline->corner_radius,
|
|
||||||
outline->points,
|
|
||||||
outline->num_points);
|
|
||||||
|
|
||||||
cairo_pattern_destroy (pat);
|
|
||||||
|
|
||||||
cairo_set_source_rgba (cr, 0.3, 0.3, 0.3, 0.5);
|
|
||||||
draw_rounded_polygon (cr,
|
|
||||||
FALSE,
|
|
||||||
outline->corner_radius,
|
|
||||||
outline->points,
|
|
||||||
outline->num_points);
|
|
||||||
cairo_destroy (cr);
|
|
||||||
return texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ClutterActor *
|
|
||||||
get_texture (EekClutterKeyActor *actor)
|
|
||||||
{
|
|
||||||
ClutterActor *texture;
|
|
||||||
EekOutline *outline;
|
|
||||||
|
|
||||||
if (!texture_cache.outline_textures)
|
|
||||||
texture_cache.outline_textures = g_hash_table_new_full (g_direct_hash,
|
|
||||||
g_direct_equal,
|
|
||||||
NULL,
|
|
||||||
g_free);
|
|
||||||
outline = eek_key_get_outline (actor->priv->key);
|
|
||||||
texture = g_hash_table_lookup (texture_cache.outline_textures, outline);
|
|
||||||
if (texture == NULL) {
|
|
||||||
texture = create_texture_for_key (actor->priv->key);
|
|
||||||
g_hash_table_insert (texture_cache.outline_textures, outline, texture);
|
|
||||||
} else
|
|
||||||
texture = clutter_clone_new (texture);
|
|
||||||
texture_cache.outline_textures_ref_count++;
|
|
||||||
return texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
draw_text_on_layout (PangoLayout *layout,
|
|
||||||
const gchar *text,
|
|
||||||
gdouble scale)
|
|
||||||
{
|
|
||||||
PangoFontDescription *font_desc;
|
|
||||||
|
|
||||||
#define FONT_SIZE (720 * 50)
|
|
||||||
/* FIXME: Font should be configurable through a property. */
|
|
||||||
font_desc = pango_font_description_from_string ("Sans");
|
|
||||||
pango_font_description_set_size (font_desc, FONT_SIZE * scale);
|
|
||||||
pango_layout_set_font_description (layout, font_desc);
|
|
||||||
pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
|
|
||||||
pango_layout_set_text (layout, text, -1);
|
|
||||||
pango_font_description_free (font_desc);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
draw_key_on_layout (EekKey *key,
|
|
||||||
PangoLayout *layout)
|
|
||||||
{
|
|
||||||
PangoLayout *buffer;
|
|
||||||
PangoRectangle logical_rect = { 0, };
|
|
||||||
EekBounds bounds;
|
|
||||||
guint keysym;
|
|
||||||
const gchar *label, *empty_label = "";
|
|
||||||
gdouble scale_x, scale_y;
|
|
||||||
|
|
||||||
eek_element_get_bounds (EEK_ELEMENT(key), &bounds);
|
|
||||||
keysym = eek_key_get_keysym (key);
|
|
||||||
if (keysym == EEK_INVALID_KEYSYM)
|
|
||||||
return;
|
|
||||||
label = eek_keysym_to_string (keysym);
|
|
||||||
if (!label)
|
|
||||||
label = empty_label;
|
|
||||||
|
|
||||||
/* Compute the layout extents. */
|
|
||||||
buffer = pango_layout_copy (layout);
|
|
||||||
draw_text_on_layout (buffer, label, 1.0);
|
|
||||||
pango_layout_get_extents (buffer, NULL, &logical_rect);
|
|
||||||
scale_x = scale_y = 1.0;
|
|
||||||
if (PANGO_PIXELS(logical_rect.width) > bounds.width)
|
|
||||||
scale_x = bounds.width / PANGO_PIXELS(logical_rect.width);
|
|
||||||
if (PANGO_PIXELS(logical_rect.height) > bounds.height)
|
|
||||||
scale_y = bounds.height / PANGO_PIXELS(logical_rect.height);
|
|
||||||
g_object_unref (buffer);
|
|
||||||
|
|
||||||
/* Actually draw on the layout */
|
|
||||||
draw_text_on_layout (layout,
|
|
||||||
label,
|
|
||||||
(scale_x < scale_y ? scale_x : scale_y) * 0.8);
|
|
||||||
if (label != empty_label)
|
|
||||||
g_free ((gpointer)label);
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user