ClutterTextPrivate *priv = text->priv;
PangoLayout *layout;
- layout = pango_layout_new (_context);
-
+ layout = clutter_actor_create_pango_layout (CLUTTER_ACTOR (text), NULL);
pango_layout_set_font_description (layout, priv->font_desc);
- if (priv->effective_attrs)
- pango_layout_set_attributes (layout, priv->effective_attrs);
-
- pango_layout_set_alignment (layout, priv->alignment);
- pango_layout_set_single_paragraph_mode (layout, priv->single_line_mode);
- pango_layout_set_justify (layout, priv->justify);
-
if (priv->text)
{
- if (!priv->use_markup)
+ if (G_LIKELY (priv->password_char == 0))
+ pango_layout_set_text (layout, priv->text, priv->n_bytes);
+ else
{
- if (priv->text_visible)
- pango_layout_set_text (layout, priv->text, priv->n_bytes);
- else
- {
- GString *str = g_string_sized_new (priv->n_bytes);
- gunichar invisible_char;
- gchar buf[7];
- gint char_len, i;
+ GString *str = g_string_sized_new (priv->n_bytes);
+ gunichar invisible_char;
+ gchar buf[7];
+ gint char_len, i;
- if (priv->priv_char != 0)
- invisible_char = priv->priv_char;
- else
- invisible_char = ' ';
+ invisible_char = priv->password_char;
- /* we need to convert the string built of invisible
- * characters into UTF-8 for it to be fed to the Pango
- * layout
- */
- memset (buf, 0, sizeof (buf));
- char_len = g_unichar_to_utf8 (invisible_char, buf);
+ /* we need to convert the string built of invisible
+ * characters into UTF-8 for it to be fed to the Pango
+ * layout
+ */
+ memset (buf, 0, sizeof (buf));
+ char_len = g_unichar_to_utf8 (invisible_char, buf);
- for (i = 0; i < priv->n_chars; i++)
- g_string_append_len (str, buf, char_len);
+ for (i = 0; i < priv->n_chars; i++)
+ g_string_append_len (str, buf, char_len);
- pango_layout_set_text (layout, str->str, str->len);
+ pango_layout_set_text (layout, str->str, str->len);
- g_string_free (str, TRUE);
- }
+ g_string_free (str, TRUE);
}
- else
- pango_layout_set_markup (layout, priv->text, -1);
}
- if (allocation_width > 0 &&
- (priv->ellipsize != PANGO_ELLIPSIZE_NONE || priv->wrap))
+ if (!priv->editable && priv->effective_attrs)
+ pango_layout_set_attributes (layout, priv->effective_attrs);
+
+ pango_layout_set_alignment (layout, priv->alignment);
+ pango_layout_set_single_paragraph_mode (layout, priv->single_line_mode);
+ pango_layout_set_justify (layout, priv->justify);
+
+ /* Cases, assuming ellipsize != NONE on actor:
+ *
+ * Width request: ellipsization can be set or not on layout,
+ * doesn't matter.
+ *
+ * Height request: ellipsization must never be set on layout
+ * if wrap=true, because we need to measure the wrapped
+ * height. It must always be set if wrap=false.
+ *
+ * Allocate: ellipsization must always be set.
+ *
+ * See http://bugzilla.gnome.org/show_bug.cgi?id=560931
+ */
+ if (priv->ellipsize != PANGO_ELLIPSIZE_NONE)
{
- int layout_width, layout_height;
+ if (allocation_height < 0 && priv->wrap)
+ ; /* must not set ellipsization on wrap=true height request */
+ else
- pango_layout_set_ellipsize (layout, priv->ellipsize);
++ {
++ if (!priv->editable)
++ pango_layout_set_ellipsize (layout, priv->ellipsize);
++ }
+ }
- pango_layout_get_size (layout, &layout_width, &layout_height);
- if (priv->wrap)
- pango_layout_set_wrap (layout, priv->wrap_mode);
-
- if (allocation_width > 0)
++ /* 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;
- /* no need to set ellipsize or wrap if we already have enough
- * space, since we don't want to make the layout wider than it
- * would be otherwise.
- */
+ width = allocation_width > 0
+ ? CLUTTER_UNITS_TO_PANGO_UNIT (allocation_width)
+ : -1;
- if (CLUTTER_UNITS_FROM_PANGO_UNIT (layout_width) > allocation_width)
- {
- if (!priv->editable && priv->ellipsize != PANGO_ELLIPSIZE_NONE)
- {
- gint width;
-
- width = allocation_width > 0
- ? CLUTTER_UNITS_TO_PANGO_UNIT (allocation_width)
- : -1;
+ pango_layout_set_width (layout, width);
+ }
- pango_layout_set_ellipsize (layout, priv->ellipsize);
- pango_layout_set_width (layout, width);
- }
- else if (priv->wrap)
- {
- gint 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.
++ * 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->ellipsize != PANGO_ELLIPSIZE_NONE &&
++ !priv->single_line_mode)
+ {
+ gint height;
- width = allocation_width > 0
- ? CLUTTER_UNITS_TO_PANGO_UNIT (allocation_width)
- : -1;
+ height = allocation_height > 0
+ ? CLUTTER_UNITS_TO_PANGO_UNIT (allocation_height)
+ : -1;
- pango_layout_set_wrap (layout, priv->wrap_mode);
- pango_layout_set_width (layout, width);
- }
- }
+ pango_layout_set_height (layout, height);
}
return layout;
return;
}
- cursor_paint (text);
-
- CLUTTER_NOTE (PAINT, "painting text (text:`%s')", priv->text);
-
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)
+ clutter_text_ensure_cursor_position (text);
+
+ if (priv->editable && priv->single_line_mode)
+ {
+ PangoRectangle logical_rect = { 0, };
+ gint actor_width, text_width;
+
+ pango_layout_get_extents (layout, NULL, &logical_rect);
+
+ cogl_clip_push (0, 0,
+ CLUTTER_UNITS_TO_FLOAT (alloc.x2 - alloc.x1),
+ CLUTTER_UNITS_TO_FLOAT (alloc.y2 - alloc.y1));
+ clip_set = TRUE;
+
+ actor_width = (CLUTTER_UNITS_TO_DEVICE (alloc.x2 - alloc.x1))
+ - 2 * TEXT_PADDING;
+ text_width = logical_rect.width / PANGO_SCALE;
+
+ if (actor_width < text_width)
+ {
+ gint cursor_x = priv->cursor_pos.x;
+
+ if (priv->position == -1)
+ {
+ text_x = actor_width - text_width;
+ priv->cursor_pos.x += text_x + TEXT_PADDING;
+ }
+ else if (priv->position == 0)
+ {
+ text_x = 0;
+ }
+ else
+ {
+ if (text_x <= 0)
+ {
+ gint diff = -1 * text_x;
+
+ if (cursor_x < diff)
+ text_x += diff - cursor_x;
+ else if (cursor_x > (diff + actor_width))
+ text_x -= cursor_x - (diff - actor_width);
+ }
+ }
+ }
+ else
+ {
+ text_x = 0;
+ priv->cursor_pos.x += text_x + TEXT_PADDING;
+ }
+ }
+ else
+ text_x = 0;
+
+ cursor_paint (text);
+
real_opacity = clutter_actor_get_paint_opacity (self)
* priv->text_color.alpha
/ 255;