text: Make :line-wrap actually work
When we paint a ClutterText we ask the actor for a PangoLayout that fits inside the actor's allocation - both width and height. Sadly, whenever a height is set on a PangoLayout, Pango will wrap its contents - regardless of whether the layout should actually wrap or not. This means that in certain easy to exploit cases, Clutter will paint a Text actor with its contents wrapping even if the :wrap property is set to FALSE. In order to fix this we need to encode some more cases inside the ::paint implementation of ClutterText, and ask the cache for a layout that is sized as the allocation's width, but not as its height; we also need to perform a clip if we detect that the PangoLayout's logical size is going to overflow the allocated size. This clip might cause some performance issue, given that clipping breaks batching in the Cogl journal; hopefully all clips for text are going to be screen-aligned, so at the end of the batch it'll just scissor them out. http://bugzilla.clutter-project.org/show_bug.cgi?id=2339
This commit is contained in:
parent
73d3026dd1
commit
359ed2b29f
@ -1975,9 +1975,37 @@ clutter_text_paint (ClutterActor *self)
|
||||
if (priv->editable && priv->single_line_mode)
|
||||
layout = clutter_text_create_layout (text, -1, -1);
|
||||
else
|
||||
layout = clutter_text_create_layout (text,
|
||||
alloc.x2 - alloc.x1,
|
||||
alloc.y2 - alloc.y1);
|
||||
{
|
||||
/* the only time when we create the PangoLayout using the full
|
||||
* width and height of the allocation is when we can both wrap
|
||||
* and ellipsize
|
||||
*/
|
||||
if (priv->wrap && priv->ellipsize)
|
||||
{
|
||||
layout = clutter_text_create_layout (text,
|
||||
alloc.x2 - alloc.x1,
|
||||
alloc.y2 - alloc.y1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* if we're not wrapping we cannot set the height of the
|
||||
* layout, otherwise Pango will happily wrap the text to
|
||||
* fit in the rectangle - thus making the :wrap property
|
||||
* useless
|
||||
*
|
||||
* see bug:
|
||||
*
|
||||
* http://bugzilla.clutter-project.org/show_bug.cgi?id=2339
|
||||
*
|
||||
* in order to fix this, we create a layout that would fit
|
||||
* in the assigned width, then we clip the actor if the
|
||||
* logical rectangle overflows the allocation.
|
||||
*/
|
||||
layout = clutter_text_create_layout (text,
|
||||
alloc.x2 - alloc.x1,
|
||||
-1);
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->editable && priv->cursor_visible)
|
||||
clutter_text_ensure_cursor_position (text);
|
||||
@ -2027,6 +2055,24 @@ clutter_text_paint (ClutterActor *self)
|
||||
text_x = TEXT_PADDING;
|
||||
}
|
||||
}
|
||||
else if (!priv->editable && !(priv->wrap && priv->ellipsize))
|
||||
{
|
||||
PangoRectangle logical_rect = { 0, };
|
||||
|
||||
pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
|
||||
|
||||
/* don't clip if the layout managed to fit inside our allocation */
|
||||
if (logical_rect.width > (alloc.x2 - alloc.x1) ||
|
||||
logical_rect.height > (alloc.y2 - alloc.y1))
|
||||
{
|
||||
cogl_clip_push_rectangle (0, 0,
|
||||
alloc.x2 - alloc.x1,
|
||||
alloc.y2 - alloc.y1);
|
||||
clip_set = TRUE;
|
||||
}
|
||||
|
||||
text_x = 0;
|
||||
}
|
||||
else
|
||||
text_x = 0;
|
||||
|
||||
@ -2053,7 +2099,6 @@ clutter_text_paint (ClutterActor *self)
|
||||
|
||||
if (clip_set)
|
||||
cogl_clip_pop ();
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
|
Loading…
Reference in New Issue
Block a user