Use units in position_to_coords()

We loose precision with a direct conversion for PangoUnits to
pixels, so we should do the conversion as needed, inside the
callers of clutter_text_position_to_coords().
This commit is contained in:
Emmanuele Bassi 2008-12-15 18:24:42 +00:00
parent 2714397fd5
commit e615b8cc6b

View File

@ -61,6 +61,9 @@
#define DEFAULT_FONT_NAME "Sans 10"
/* cursor width in pixels */
#define DEFAULT_CURSOR_SIZE 2
/* We need at least three cached layouts to run the allocation without
* regenerating a new layout. First the layout will be generated at
* full width to get the preferred width, then it will be generated at
@ -150,6 +153,7 @@ struct _ClutterTextPrivate
/* Where to draw the cursor */
ClutterGeometry cursor_pos;
ClutterColor cursor_color;
gint cursor_size;
gint max_length;
@ -438,17 +442,30 @@ clutter_text_coords_to_position (ClutterText *text,
py = y * PANGO_SCALE;
pango_layout_xy_to_index (clutter_text_get_layout (text),
px, py, &index_, &trailing);
px, py,
&index_, &trailing);
return index_ + trailing;
}
/*
* clutter_text_position_to_coords:
* @self: a #ClutterText
* @position: position in characters
* @x: return location for the X coordinate, or %NULL
* @y: return location for the Y coordinate, or %NULL
* @line_height: return location for the line height, or %NULL
*
* Retrieves the coordinates of the given @position.
*
* Return value: %TRUE if the conversion was successful
*/
static gboolean
clutter_text_position_to_coords (ClutterText *self,
gint position,
gint *x,
gint *y,
gint *cursor_height)
ClutterUnit *x,
ClutterUnit *y,
ClutterUnit *line_height)
{
ClutterTextPrivate *priv = self->priv;
PangoRectangle rect;
@ -463,10 +480,14 @@ clutter_text_position_to_coords (ClutterText *self,
if (position == -1)
{
if (priv->text_visible)
index_ = strlen (priv->text);
index_ = priv->n_bytes;
else
index_ = priv->n_chars * priv_char_bytes;
}
else if (position == 0)
{
index_ = 0;
}
else
{
if (priv->text_visible)
@ -479,31 +500,33 @@ clutter_text_position_to_coords (ClutterText *self,
&rect, NULL);
if (x)
*x = rect.x / PANGO_SCALE;
*x = CLUTTER_UNITS_FROM_PANGO_UNIT (rect.x);
if (y)
*y = (rect.y + rect.height) / PANGO_SCALE;
*y = CLUTTER_UNITS_FROM_PANGO_UNIT (rect.y);
if (cursor_height)
*cursor_height = rect.height / PANGO_SCALE;
if (line_height)
*line_height = CLUTTER_UNITS_FROM_PANGO_UNIT (rect.height);
return TRUE; /* FIXME: should return false if coords were outside text */
/* FIXME: should return false if coords were outside text */
return TRUE;
}
static inline void
clutter_text_ensure_cursor_position (ClutterText *self)
{
ClutterTextPrivate *priv = self->priv;
gint x, y, cursor_height;
ClutterUnit x, y, cursor_height;
x = y = cursor_height = 0;
clutter_text_position_to_coords (self, priv->position,
&x, &y,
&cursor_height);
priv->cursor_pos.x = x;
priv->cursor_pos.y = y - cursor_height;
priv->cursor_pos.width = 2;
priv->cursor_pos.height = cursor_height;
priv->cursor_pos.x = CLUTTER_UNITS_TO_DEVICE (x);
priv->cursor_pos.y = CLUTTER_UNITS_TO_DEVICE (y);
priv->cursor_pos.width = priv->cursor_size;
priv->cursor_pos.height = CLUTTER_UNITS_TO_DEVICE (cursor_height);
g_signal_emit (self, text_signals[CURSOR_EVENT], 0, &priv->cursor_pos);
}
@ -799,13 +822,12 @@ cursor_paint (ClutterText *self)
for (line_no = 0; line_no < lines; line_no++)
{
PangoLayoutLine *line;
gint n_ranges;
gint n_ranges;
gint *ranges;
gint i;
gint y;
gint height;
gint i;
gint index;
gint maxindex;
ClutterUnit y, height;
line = pango_layout_get_line_readonly (layout, line_no);
pango_layout_line_x_to_index (line, G_MAXINT, &maxindex, NULL);
@ -822,11 +844,20 @@ cursor_paint (ClutterText *self)
NULL, &y, &height);
for (i = 0; i < n_ranges; i++)
cogl_rectangle (ranges[i * 2 + 0] / PANGO_SCALE,
y - height,
((ranges[i * 2 + 1] - ranges[i * 2 + 0])
/ PANGO_SCALE),
height);
{
gint range_x;
gint range_width;
range_x = ranges[i * 2]
/ PANGO_SCALE;
range_width = (ranges[i * 2 + 1] - ranges[i * 2])
/ PANGO_SCALE;
cogl_rectangle (range_x,
CLUTTER_UNITS_TO_DEVICE (y),
range_width,
CLUTTER_UNITS_TO_DEVICE (height));
}
g_free (ranges);
@ -886,8 +917,9 @@ clutter_text_motion (ClutterActor *actor,
clutter_actor_transform_stage_point (actor, x, y, &x, &y);
index_ = clutter_text_coords_to_position (ttext, CLUTTER_UNITS_TO_INT (x),
CLUTTER_UNITS_TO_INT (y));
index_ = clutter_text_coords_to_position (ttext,
CLUTTER_UNITS_TO_INT (x),
CLUTTER_UNITS_TO_INT (y));
if (priv->selectable)
clutter_text_set_cursor_position (ttext, bytes_to_offset (text, index_));
@ -1023,14 +1055,21 @@ clutter_text_get_preferred_width (ClutterActor *self,
ClutterTextPrivate *priv = text->priv;
PangoRectangle logical_rect = { 0, };
PangoLayout *layout;
gint logical_width;
ClutterUnit layout_width;
layout = clutter_text_create_layout (text, -1);
pango_layout_get_extents (layout, NULL, &logical_rect);
layout_width = logical_rect.width > 0
? CLUTTER_UNITS_FROM_PANGO_UNIT (logical_rect.width)
/* the X coordinate of the logical rectangle might be non-zero
* according to the Pango documentation; hence, we need to offset
* the width accordingly
*/
logical_width = logical_rect.x + logical_rect.width;
layout_width = logical_width > 0
? CLUTTER_UNITS_FROM_PANGO_UNIT (logical_width)
: 1;
if (min_width_p)
@ -1065,18 +1104,26 @@ clutter_text_get_preferred_height (ClutterActor *self,
{
PangoLayout *layout;
PangoRectangle logical_rect = { 0, };
ClutterUnit height;
gint logical_height;
ClutterUnit layout_height;
layout = clutter_text_create_layout (text, for_width);
pango_layout_get_extents (layout, NULL, &logical_rect);
height = CLUTTER_UNITS_FROM_PANGO_UNIT (logical_rect.height);
/* the Y coordinate of the logical rectangle might be non-zero
* according to the Pango documentation; hence, we need to offset
* the height accordingly
*/
logical_height = logical_rect.y + logical_rect.height;
layout_height = CLUTTER_UNITS_FROM_PANGO_UNIT (logical_height);
if (min_height_p)
*min_height_p = height;
*min_height_p = layout_height;
if (natural_height_p)
*natural_height_p = height;
*natural_height_p = layout_height;
}
}
@ -1881,6 +1928,8 @@ clutter_text_init (ClutterText *self)
priv->priv_char = '*';
priv->max_length = 0;
priv->cursor_size = DEFAULT_CURSOR_SIZE;
}
ClutterActor *