Merge branch 'text-actor-layout-height'

* text-actor-layout-height:
  [clutter-text] Fix ellipsizing
  Support pango_layout_set_height() in ClutterText

Conflicts:
	clutter/clutter-text.c
This commit is contained in:
Emmanuele Bassi 2009-04-15 18:08:14 +01:00
commit 425fa78a27

View File

@ -86,9 +86,12 @@ struct _LayoutCache
*/ */
PangoLayout *layout; PangoLayout *layout;
/* The width that used to generate this layout */ /* The width that was used to generate this layout */
ClutterUnit width; ClutterUnit width;
/* The height that was used to generate this layout */
ClutterUnit height;
/* A number representing the age of this cache (so that when a /* A number representing the age of this cache (so that when a
* new layout is needed the last used cache is replaced) * new layout is needed the last used cache is replaced)
*/ */
@ -237,7 +240,8 @@ clutter_text_clear_selection (ClutterText *self)
static PangoLayout * static PangoLayout *
clutter_text_create_layout_no_cache (ClutterText *text, clutter_text_create_layout_no_cache (ClutterText *text,
ClutterUnit allocation_width) ClutterUnit allocation_width,
ClutterUnit allocation_height)
{ {
ClutterTextPrivate *priv = text->priv; ClutterTextPrivate *priv = text->priv;
PangoLayout *layout; PangoLayout *layout;
@ -281,32 +285,35 @@ clutter_text_create_layout_no_cache (ClutterText *text,
pango_layout_set_single_paragraph_mode (layout, priv->single_line_mode); pango_layout_set_single_paragraph_mode (layout, priv->single_line_mode);
pango_layout_set_justify (layout, priv->justify); pango_layout_set_justify (layout, priv->justify);
if (allocation_width > 0 && /* Cases, assuming ellipsize != NONE on actor:
(priv->ellipsize != PANGO_ELLIPSIZE_NONE || priv->wrap)) *
{ * Width request: ellipsization can be set or not on layout,
int layout_width, layout_height; * doesn't matter.
*
pango_layout_get_size (layout, &layout_width, &layout_height); * Height request: ellipsization must never be set on layout
* if wrap=true, because we need to measure the wrapped
/* no need to set ellipsize or wrap if we already have enough * height. It must always be set if wrap=false.
* space, since we don't want to make the layout wider than it *
* would be otherwise. * Allocate: ellipsization must always be set.
*
* See http://bugzilla.gnome.org/show_bug.cgi?id=560931
*/ */
if (priv->ellipsize != PANGO_ELLIPSIZE_NONE)
if (CLUTTER_UNITS_FROM_PANGO_UNIT (layout_width) > allocation_width)
{ {
if (!priv->editable && priv->ellipsize != PANGO_ELLIPSIZE_NONE) if (allocation_height < 0 && priv->wrap)
; /* must not set ellipsization on wrap=true height request */
else
{ {
gint width; if (!priv->editable)
width = allocation_width > 0
? CLUTTER_UNITS_TO_PANGO_UNIT (allocation_width)
: -1;
pango_layout_set_ellipsize (layout, priv->ellipsize); pango_layout_set_ellipsize (layout, priv->ellipsize);
pango_layout_set_width (layout, width);
} }
else if (priv->wrap) }
/* we only limit the layout when in multi-line mode since the
* single line mode will take care of scrolling to accomodate
* the allocation width
*/
if (allocation_width > 0 && !priv->single_line_mode)
{ {
gint width; gint width;
@ -314,10 +321,30 @@ clutter_text_create_layout_no_cache (ClutterText *text,
? CLUTTER_UNITS_TO_PANGO_UNIT (allocation_width) ? CLUTTER_UNITS_TO_PANGO_UNIT (allocation_width)
: -1; : -1;
pango_layout_set_wrap (layout, priv->wrap_mode);
pango_layout_set_width (layout, width); pango_layout_set_width (layout, width);
} }
}
/* Pango only uses height if ellipsization is enabled, so don't set
* height if ellipsize isn't set. Pango implicitly enables wrapping
* if height is set, so don't set height if wrapping is disabled.
* In other words, only set height if we want to both wrap then
* ellipsize and we're not in single line mode.
*
* See http://bugzilla.gnome.org/show_bug.cgi?id=560931 if this
* seems odd.
*/
if (allocation_height > 0 &&
priv->wrap &&
priv->ellipsize != PANGO_ELLIPSIZE_NONE &&
!priv->single_line_mode)
{
gint height;
height = allocation_height > 0
? CLUTTER_UNITS_TO_PANGO_UNIT (allocation_height)
: -1;
pango_layout_set_height (layout, height);
} }
return layout; return layout;
@ -350,6 +377,7 @@ clutter_text_font_changed_cb (ClutterText *text)
* clutter_text_create_layout: * clutter_text_create_layout:
* @text: a #ClutterText * @text: a #ClutterText
* @allocation_width: the allocation width * @allocation_width: the allocation width
* @allocation_height: the allocation height
* *
* Like clutter_text_create_layout_no_cache(), but will also ensure * Like clutter_text_create_layout_no_cache(), but will also ensure
* the glyphs cache. If a previously cached layout generated using the * the glyphs cache. If a previously cached layout generated using the
@ -358,15 +386,17 @@ clutter_text_font_changed_cb (ClutterText *text)
*/ */
static PangoLayout * static PangoLayout *
clutter_text_create_layout (ClutterText *text, clutter_text_create_layout (ClutterText *text,
ClutterUnit allocation_width) ClutterUnit allocation_width,
ClutterUnit allocation_height)
{ {
ClutterTextPrivate *priv = text->priv; ClutterTextPrivate *priv = text->priv;
LayoutCache *oldest_cache = priv->cached_layouts; LayoutCache *oldest_cache = priv->cached_layouts;
gboolean found_free_cache = FALSE; gboolean found_free_cache = FALSE;
int i; int i;
/* Search for a cached layout with the same width and keep track of /* Search for a cached layout with the same width and keep
the oldest one */ * track of the oldest one
*/
for (i = 0; i < N_CACHED_LAYOUTS; i++) for (i = 0; i < N_CACHED_LAYOUTS; i++)
{ {
if (priv->cached_layouts[i].layout == NULL) if (priv->cached_layouts[i].layout == NULL)
@ -375,13 +405,16 @@ clutter_text_create_layout (ClutterText *text,
found_free_cache = TRUE; found_free_cache = TRUE;
oldest_cache = priv->cached_layouts + i; oldest_cache = priv->cached_layouts + i;
} }
/* If this cached layout is using the same width then we can else if (priv->cached_layouts[i].width == allocation_width &&
just return that directly */ priv->cached_layouts[i].height == allocation_height)
else if (priv->cached_layouts[i].width == allocation_width)
{ {
CLUTTER_NOTE (ACTOR, "ClutterText: %p: cache hit for width %i", /* If this cached layout is using the same size then we can
* just return that directly
*/
CLUTTER_NOTE (ACTOR, "ClutterText: %p: cache hit for size %i x %i",
text, text,
CLUTTER_UNITS_TO_DEVICE (allocation_width)); CLUTTER_UNITS_TO_DEVICE (allocation_width),
CLUTTER_UNITS_TO_DEVICE (allocation_height));
return priv->cached_layouts[i].layout; return priv->cached_layouts[i].layout;
} }
@ -392,9 +425,10 @@ clutter_text_create_layout (ClutterText *text,
} }
} }
CLUTTER_NOTE (ACTOR, "ClutterText: %p: cache miss for width %i", CLUTTER_NOTE (ACTOR, "ClutterText: %p: cache miss for size %i x %i",
text, text,
CLUTTER_UNITS_TO_DEVICE (allocation_width)); CLUTTER_UNITS_TO_DEVICE (allocation_width),
CLUTTER_UNITS_TO_DEVICE (allocation_height));
/* If we make it here then we didn't have a cached version so we /* If we make it here then we didn't have a cached version so we
need to recreate the layout */ need to recreate the layout */
@ -402,13 +436,16 @@ clutter_text_create_layout (ClutterText *text,
g_object_unref (oldest_cache->layout); g_object_unref (oldest_cache->layout);
oldest_cache->layout = oldest_cache->layout =
clutter_text_create_layout_no_cache (text, allocation_width); clutter_text_create_layout_no_cache (text,
allocation_width,
allocation_height);
cogl_pango_ensure_glyph_cache_for_layout (oldest_cache->layout); cogl_pango_ensure_glyph_cache_for_layout (oldest_cache->layout);
/* Mark the 'time' this cache was created and advance the time */ /* Mark the 'time' this cache was created and advance the time */
oldest_cache->age = priv->cache_age++; oldest_cache->age = priv->cache_age++;
oldest_cache->width = allocation_width; oldest_cache->width = allocation_width;
oldest_cache->height = allocation_height;
return oldest_cache->layout; return oldest_cache->layout;
} }
@ -1270,7 +1307,9 @@ clutter_text_paint (ClutterActor *self)
} }
clutter_actor_get_allocation_box (self, &alloc); clutter_actor_get_allocation_box (self, &alloc);
layout = clutter_text_create_layout (text, alloc.x2 - alloc.x1); layout = clutter_text_create_layout (text,
alloc.x2 - alloc.x1,
alloc.y2 - alloc.y1);
if (priv->editable && priv->cursor_visible) if (priv->editable && priv->cursor_visible)
clutter_text_ensure_cursor_position (text); clutter_text_ensure_cursor_position (text);
@ -1360,7 +1399,7 @@ clutter_text_get_preferred_width (ClutterActor *self,
gint logical_width; gint logical_width;
ClutterUnit layout_width; ClutterUnit layout_width;
layout = clutter_text_create_layout (text, -1); layout = clutter_text_create_layout (text, -1, -1);
pango_layout_get_extents (layout, NULL, &logical_rect); pango_layout_get_extents (layout, NULL, &logical_rect);
@ -1409,7 +1448,7 @@ clutter_text_get_preferred_height (ClutterActor *self,
gint logical_height; gint logical_height;
ClutterUnit layout_height; ClutterUnit layout_height;
layout = clutter_text_create_layout (text, for_width); layout = clutter_text_create_layout (text, for_width, -1);
pango_layout_get_extents (layout, NULL, &logical_rect); pango_layout_get_extents (layout, NULL, &logical_rect);
@ -1422,7 +1461,12 @@ clutter_text_get_preferred_height (ClutterActor *self,
layout_height = CLUTTER_UNITS_FROM_PANGO_UNIT (logical_height); layout_height = CLUTTER_UNITS_FROM_PANGO_UNIT (logical_height);
if (min_height_p) if (min_height_p)
{
if (text->priv->ellipsize)
*min_height_p = -1;
else
*min_height_p = layout_height; *min_height_p = layout_height;
}
if (natural_height_p) if (natural_height_p)
*natural_height_p = layout_height; *natural_height_p = layout_height;
@ -1440,7 +1484,9 @@ clutter_text_allocate (ClutterActor *self,
/* Ensure that there is a cached layout with the right width so /* Ensure that there is a cached layout with the right width so
* that we don't need to create the text during the paint run * that we don't need to create the text during the paint run
*/ */
clutter_text_create_layout (text, box->x2 - box->x1); clutter_text_create_layout (text,
box->x2 - box->x1,
box->y2 - box->y1);
parent_class = CLUTTER_ACTOR_CLASS (clutter_text_parent_class); parent_class = CLUTTER_ACTOR_CLASS (clutter_text_parent_class);
parent_class->allocate (self, box, origin_changed); parent_class->allocate (self, box, origin_changed);
@ -3219,13 +3265,13 @@ clutter_text_set_markup (ClutterText *self,
PangoLayout * PangoLayout *
clutter_text_get_layout (ClutterText *self) clutter_text_get_layout (ClutterText *self)
{ {
ClutterUnit width; ClutterUnit width, height;
g_return_val_if_fail (CLUTTER_IS_TEXT (self), NULL); g_return_val_if_fail (CLUTTER_IS_TEXT (self), NULL);
width = clutter_actor_get_widthu (CLUTTER_ACTOR (self)); clutter_actor_get_sizeu (CLUTTER_ACTOR (self), &width, &height);
return clutter_text_create_layout (self, width); return clutter_text_create_layout (self, width, height);
} }
/** /**