mirror of
https://github.com/brl/mutter.git
synced 2025-02-17 05:44:08 +00:00
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:
parent
2714397fd5
commit
e615b8cc6b
@ -61,6 +61,9 @@
|
|||||||
|
|
||||||
#define DEFAULT_FONT_NAME "Sans 10"
|
#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
|
/* We need at least three cached layouts to run the allocation without
|
||||||
* regenerating a new layout. First the layout will be generated at
|
* regenerating a new layout. First the layout will be generated at
|
||||||
* full width to get the preferred width, then it 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 */
|
/* Where to draw the cursor */
|
||||||
ClutterGeometry cursor_pos;
|
ClutterGeometry cursor_pos;
|
||||||
ClutterColor cursor_color;
|
ClutterColor cursor_color;
|
||||||
|
gint cursor_size;
|
||||||
|
|
||||||
gint max_length;
|
gint max_length;
|
||||||
|
|
||||||
@ -438,17 +442,30 @@ clutter_text_coords_to_position (ClutterText *text,
|
|||||||
py = y * PANGO_SCALE;
|
py = y * PANGO_SCALE;
|
||||||
|
|
||||||
pango_layout_xy_to_index (clutter_text_get_layout (text),
|
pango_layout_xy_to_index (clutter_text_get_layout (text),
|
||||||
px, py, &index_, &trailing);
|
px, py,
|
||||||
|
&index_, &trailing);
|
||||||
|
|
||||||
return 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
|
static gboolean
|
||||||
clutter_text_position_to_coords (ClutterText *self,
|
clutter_text_position_to_coords (ClutterText *self,
|
||||||
gint position,
|
gint position,
|
||||||
gint *x,
|
ClutterUnit *x,
|
||||||
gint *y,
|
ClutterUnit *y,
|
||||||
gint *cursor_height)
|
ClutterUnit *line_height)
|
||||||
{
|
{
|
||||||
ClutterTextPrivate *priv = self->priv;
|
ClutterTextPrivate *priv = self->priv;
|
||||||
PangoRectangle rect;
|
PangoRectangle rect;
|
||||||
@ -463,10 +480,14 @@ clutter_text_position_to_coords (ClutterText *self,
|
|||||||
if (position == -1)
|
if (position == -1)
|
||||||
{
|
{
|
||||||
if (priv->text_visible)
|
if (priv->text_visible)
|
||||||
index_ = strlen (priv->text);
|
index_ = priv->n_bytes;
|
||||||
else
|
else
|
||||||
index_ = priv->n_chars * priv_char_bytes;
|
index_ = priv->n_chars * priv_char_bytes;
|
||||||
}
|
}
|
||||||
|
else if (position == 0)
|
||||||
|
{
|
||||||
|
index_ = 0;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (priv->text_visible)
|
if (priv->text_visible)
|
||||||
@ -479,31 +500,33 @@ clutter_text_position_to_coords (ClutterText *self,
|
|||||||
&rect, NULL);
|
&rect, NULL);
|
||||||
|
|
||||||
if (x)
|
if (x)
|
||||||
*x = rect.x / PANGO_SCALE;
|
*x = CLUTTER_UNITS_FROM_PANGO_UNIT (rect.x);
|
||||||
|
|
||||||
if (y)
|
if (y)
|
||||||
*y = (rect.y + rect.height) / PANGO_SCALE;
|
*y = CLUTTER_UNITS_FROM_PANGO_UNIT (rect.y);
|
||||||
|
|
||||||
if (cursor_height)
|
if (line_height)
|
||||||
*cursor_height = rect.height / PANGO_SCALE;
|
*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
|
static inline void
|
||||||
clutter_text_ensure_cursor_position (ClutterText *self)
|
clutter_text_ensure_cursor_position (ClutterText *self)
|
||||||
{
|
{
|
||||||
ClutterTextPrivate *priv = self->priv;
|
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,
|
clutter_text_position_to_coords (self, priv->position,
|
||||||
&x, &y,
|
&x, &y,
|
||||||
&cursor_height);
|
&cursor_height);
|
||||||
|
|
||||||
priv->cursor_pos.x = x;
|
priv->cursor_pos.x = CLUTTER_UNITS_TO_DEVICE (x);
|
||||||
priv->cursor_pos.y = y - cursor_height;
|
priv->cursor_pos.y = CLUTTER_UNITS_TO_DEVICE (y);
|
||||||
priv->cursor_pos.width = 2;
|
priv->cursor_pos.width = priv->cursor_size;
|
||||||
priv->cursor_pos.height = cursor_height;
|
priv->cursor_pos.height = CLUTTER_UNITS_TO_DEVICE (cursor_height);
|
||||||
|
|
||||||
g_signal_emit (self, text_signals[CURSOR_EVENT], 0, &priv->cursor_pos);
|
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++)
|
for (line_no = 0; line_no < lines; line_no++)
|
||||||
{
|
{
|
||||||
PangoLayoutLine *line;
|
PangoLayoutLine *line;
|
||||||
gint n_ranges;
|
gint n_ranges;
|
||||||
gint *ranges;
|
gint *ranges;
|
||||||
gint i;
|
gint i;
|
||||||
gint y;
|
|
||||||
gint height;
|
|
||||||
gint index;
|
gint index;
|
||||||
gint maxindex;
|
gint maxindex;
|
||||||
|
ClutterUnit y, height;
|
||||||
|
|
||||||
line = pango_layout_get_line_readonly (layout, line_no);
|
line = pango_layout_get_line_readonly (layout, line_no);
|
||||||
pango_layout_line_x_to_index (line, G_MAXINT, &maxindex, NULL);
|
pango_layout_line_x_to_index (line, G_MAXINT, &maxindex, NULL);
|
||||||
@ -822,11 +844,20 @@ cursor_paint (ClutterText *self)
|
|||||||
NULL, &y, &height);
|
NULL, &y, &height);
|
||||||
|
|
||||||
for (i = 0; i < n_ranges; i++)
|
for (i = 0; i < n_ranges; i++)
|
||||||
cogl_rectangle (ranges[i * 2 + 0] / PANGO_SCALE,
|
{
|
||||||
y - height,
|
gint range_x;
|
||||||
((ranges[i * 2 + 1] - ranges[i * 2 + 0])
|
gint range_width;
|
||||||
/ PANGO_SCALE),
|
|
||||||
height);
|
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);
|
g_free (ranges);
|
||||||
|
|
||||||
@ -886,8 +917,9 @@ clutter_text_motion (ClutterActor *actor,
|
|||||||
|
|
||||||
clutter_actor_transform_stage_point (actor, x, y, &x, &y);
|
clutter_actor_transform_stage_point (actor, x, y, &x, &y);
|
||||||
|
|
||||||
index_ = clutter_text_coords_to_position (ttext, CLUTTER_UNITS_TO_INT (x),
|
index_ = clutter_text_coords_to_position (ttext,
|
||||||
CLUTTER_UNITS_TO_INT (y));
|
CLUTTER_UNITS_TO_INT (x),
|
||||||
|
CLUTTER_UNITS_TO_INT (y));
|
||||||
|
|
||||||
if (priv->selectable)
|
if (priv->selectable)
|
||||||
clutter_text_set_cursor_position (ttext, bytes_to_offset (text, index_));
|
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;
|
ClutterTextPrivate *priv = text->priv;
|
||||||
PangoRectangle logical_rect = { 0, };
|
PangoRectangle logical_rect = { 0, };
|
||||||
PangoLayout *layout;
|
PangoLayout *layout;
|
||||||
|
gint logical_width;
|
||||||
ClutterUnit layout_width;
|
ClutterUnit layout_width;
|
||||||
|
|
||||||
layout = clutter_text_create_layout (text, -1);
|
layout = clutter_text_create_layout (text, -1);
|
||||||
|
|
||||||
pango_layout_get_extents (layout, NULL, &logical_rect);
|
pango_layout_get_extents (layout, NULL, &logical_rect);
|
||||||
|
|
||||||
layout_width = logical_rect.width > 0
|
/* the X coordinate of the logical rectangle might be non-zero
|
||||||
? CLUTTER_UNITS_FROM_PANGO_UNIT (logical_rect.width)
|
* 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;
|
: 1;
|
||||||
|
|
||||||
if (min_width_p)
|
if (min_width_p)
|
||||||
@ -1065,18 +1104,26 @@ clutter_text_get_preferred_height (ClutterActor *self,
|
|||||||
{
|
{
|
||||||
PangoLayout *layout;
|
PangoLayout *layout;
|
||||||
PangoRectangle logical_rect = { 0, };
|
PangoRectangle logical_rect = { 0, };
|
||||||
ClutterUnit height;
|
gint logical_height;
|
||||||
|
ClutterUnit layout_height;
|
||||||
|
|
||||||
layout = clutter_text_create_layout (text, for_width);
|
layout = clutter_text_create_layout (text, for_width);
|
||||||
|
|
||||||
pango_layout_get_extents (layout, NULL, &logical_rect);
|
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)
|
if (min_height_p)
|
||||||
*min_height_p = height;
|
*min_height_p = layout_height;
|
||||||
|
|
||||||
if (natural_height_p)
|
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->priv_char = '*';
|
||||||
|
|
||||||
priv->max_length = 0;
|
priv->max_length = 0;
|
||||||
|
|
||||||
|
priv->cursor_size = DEFAULT_CURSOR_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClutterActor *
|
ClutterActor *
|
||||||
|
Loading…
x
Reference in New Issue
Block a user