summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2012-12-05 14:04:20 +0100
committerAlexander Larsson <alexl@redhat.com>2012-12-06 16:36:19 +0100
commitd169449e7179ef0028fe8932ee4306bacb099fd2 (patch)
treec4715f0d3fab60877197591b52487284b1a5764e
parent3070717bc6e4c2a7bf83508ae5bf7a03eb77bf4b (diff)
downloadpango-d169449e7179ef0028fe8932ee4306bacb099fd2.tar.gz
Track changes in layout and dependencies via serials
We track changes in the PangoContext and automatically call pango_layout_context_changed() when needed, plus we track changes in the layout and let apps know via pango_layout_get_serial when the layout changed and needs to be redrawn. https://bugzilla.gnome.org/show_bug.cgi?id=340066
-rw-r--r--docs/pango-sections.txt1
-rw-r--r--docs/tmpl/layout.sgml9
-rw-r--r--pango/pango-context.c1
-rw-r--r--pango/pango-layout-private.h3
-rw-r--r--pango/pango-layout.c94
-rw-r--r--pango/pango-layout.h1
-rw-r--r--pango/pango.def1
7 files changed, 91 insertions, 19 deletions
diff --git a/docs/pango-sections.txt b/docs/pango-sections.txt
index ec004bdc..f22eadf1 100644
--- a/docs/pango-sections.txt
+++ b/docs/pango-sections.txt
@@ -443,6 +443,7 @@ pango_layout_copy
pango_layout_get_context
pango_layout_context_changed
+pango_layout_get_serial
pango_layout_set_text
pango_layout_get_text
diff --git a/docs/tmpl/layout.sgml b/docs/tmpl/layout.sgml
index 997507df..e0a6ebf4 100644
--- a/docs/tmpl/layout.sgml
+++ b/docs/tmpl/layout.sgml
@@ -100,6 +100,15 @@ has no user-visible fields.
@layout:
+<!-- ##### FUNCTION pango_layout_get_serial ##### -->
+<para>
+
+</para>
+
+@layout:
+@Returns:
+
+
<!-- ##### FUNCTION pango_layout_set_text ##### -->
<para>
diff --git a/pango/pango-context.c b/pango/pango-context.c
index 0477a957..b15f44d1 100644
--- a/pango/pango-context.c
+++ b/pango/pango-context.c
@@ -108,7 +108,6 @@ pango_context_finalize (GObject *object)
G_OBJECT_CLASS (pango_context_parent_class)->finalize (object);
}
-
/**
* pango_context_new:
*
diff --git a/pango/pango-layout-private.h b/pango/pango-layout-private.h
index dc4f3d4c..d0bf93eb 100644
--- a/pango/pango-layout-private.h
+++ b/pango/pango-layout-private.h
@@ -46,6 +46,9 @@ struct _PangoLayout
/* Value fields. These will be memcpy'd in _copy() */
int copy_begin;
+ guint serial;
+ guint context_serial;
+
int length; /* length of text in bytes */
int n_chars; /* number of characters in layout */
int width; /* wrap/ellipsize width, in device units, or -1 if not set */
diff --git a/pango/pango-layout.c b/pango/pango-layout.c
index 48168d82..b1f63461 100644
--- a/pango/pango-layout.c
+++ b/pango/pango-layout.c
@@ -155,6 +155,9 @@ check_invalid (PangoLayoutIter *iter,
}
#endif
+static void check_context_changed (PangoLayout *layout);
+static void layout_changed (PangoLayout *layout);
+
static void pango_layout_clear_lines (PangoLayout *layout);
static void pango_layout_check_lines (PangoLayout *layout);
@@ -188,6 +191,7 @@ G_DEFINE_TYPE (PangoLayout, pango_layout, G_TYPE_OBJECT)
static void
pango_layout_init (PangoLayout *layout)
{
+ layout->serial = 1;
layout->attrs = NULL;
layout->font_desc = NULL;
layout->text = NULL;
@@ -269,6 +273,7 @@ pango_layout_new (PangoContext *context)
layout = g_object_new (PANGO_TYPE_LAYOUT, NULL);
layout->context = context;
+ layout->context_serial = pango_context_get_serial (context);
g_object_ref (context);
return layout;
@@ -346,10 +351,13 @@ pango_layout_set_width (PangoLayout *layout,
{
g_return_if_fail (layout != NULL);
+ if (width < 0)
+ width = -1;
+
if (width != layout->width)
{
layout->width = width;
- pango_layout_clear_lines (layout);
+ layout_changed (layout);
}
}
@@ -418,7 +426,7 @@ pango_layout_set_height (PangoLayout *layout,
if (layout->ellipsize != PANGO_ELLIPSIZE_NONE &&
!(layout->lines && layout->is_ellipsized == FALSE &&
height < 0 && layout->line_count <= (guint) -height))
- pango_layout_clear_lines (layout);
+ layout_changed (layout);
}
}
@@ -461,7 +469,7 @@ pango_layout_set_wrap (PangoLayout *layout,
layout->wrap = wrap;
if (layout->width != -1)
- pango_layout_clear_lines (layout);
+ layout_changed (layout);
}
}
@@ -532,7 +540,7 @@ pango_layout_set_indent (PangoLayout *layout,
if (indent != layout->indent)
{
layout->indent = indent;
- pango_layout_clear_lines (layout);
+ layout_changed (layout);
}
}
@@ -569,7 +577,7 @@ pango_layout_set_spacing (PangoLayout *layout,
if (spacing != layout->spacing)
{
layout->spacing = spacing;
- pango_layout_clear_lines (layout);
+ layout_changed (layout);
}
}
@@ -612,7 +620,8 @@ pango_layout_set_attributes (PangoLayout *layout,
layout->attrs = attrs;
if (layout->attrs)
pango_attr_list_ref (layout->attrs);
- pango_layout_clear_lines (layout);
+
+ layout_changed (layout);
if (old_attrs)
pango_attr_list_unref (old_attrs);
@@ -659,7 +668,7 @@ pango_layout_set_font_description (PangoLayout *layout,
layout->font_desc = desc ? pango_font_description_copy (desc) : NULL;
- pango_layout_clear_lines (layout);
+ layout_changed (layout);
layout->tab_width = -1;
}
}
@@ -710,7 +719,7 @@ pango_layout_set_justify (PangoLayout *layout,
layout->justify = justify;
if (layout->is_ellipsized || layout->is_wrapped)
- pango_layout_clear_lines (layout);
+ layout_changed (layout);
}
}
@@ -766,7 +775,7 @@ pango_layout_set_auto_dir (PangoLayout *layout,
if (auto_dir != layout->auto_dir)
{
layout->auto_dir = auto_dir;
- pango_layout_clear_lines (layout);
+ layout_changed (layout);
}
}
@@ -808,7 +817,7 @@ pango_layout_set_alignment (PangoLayout *layout,
if (alignment != layout->alignment)
{
layout->alignment = alignment;
- pango_layout_clear_lines (layout);
+ layout_changed (layout);
}
}
@@ -853,7 +862,7 @@ pango_layout_set_tabs (PangoLayout *layout,
layout->tabs = tabs ? pango_tab_array_copy (tabs) : NULL;
- pango_layout_clear_lines (layout);
+ layout_changed (layout);
}
}
@@ -900,8 +909,7 @@ pango_layout_set_single_paragraph_mode (PangoLayout *layout,
if (layout->single_paragraph != setting)
{
layout->single_paragraph = setting;
-
- pango_layout_clear_lines (layout);
+ layout_changed (layout);
}
}
@@ -952,7 +960,7 @@ pango_layout_set_ellipsize (PangoLayout *layout,
layout->ellipsize = ellipsize;
if (layout->is_ellipsized || layout->is_wrapped)
- pango_layout_clear_lines (layout);
+ layout_changed (layout);
}
}
@@ -1073,7 +1081,7 @@ pango_layout_set_text (PangoLayout *layout,
layout->n_chars = pango_utf8_strlen (layout->text, -1);
- pango_layout_clear_lines (layout);
+ layout_changed (layout);
g_free (old_text);
}
@@ -1247,6 +1255,26 @@ pango_layout_get_unknown_glyphs_count (PangoLayout *layout)
return count;
}
+static void
+check_context_changed (PangoLayout *layout)
+{
+ int old_serial = layout->context_serial;
+
+ layout->context_serial = pango_context_get_serial (layout->context);
+
+ if (old_serial != layout->context_serial)
+ pango_layout_context_changed (layout);
+}
+
+static void
+layout_changed (PangoLayout *layout)
+{
+ layout->serial++;
+ if (layout->serial == 0)
+ layout->serial++;
+ pango_layout_clear_lines (layout);
+}
+
/**
* pango_layout_context_changed:
* @layout: a #PangoLayout
@@ -1259,11 +1287,39 @@ pango_layout_get_unknown_glyphs_count (PangoLayout *layout)
void
pango_layout_context_changed (PangoLayout *layout)
{
- pango_layout_clear_lines (layout);
+ g_return_if_fail (PANGO_IS_LAYOUT (layout));
+
+ layout_changed (layout);
layout->tab_width = -1;
}
/**
+ * pango_layout_get_serial:
+ * @layout: a #PangoLayout
+ *
+ * Returns the current serial number of @layout. The serial number is
+ * initialized to an small number larger than zero when a new layout
+ * is created and is increased whenever the layout is changed using any
+ * of the setter functions, or the #PangoContext it uses has changed.
+ * The serial may wrap, but will never have the value 0. Since it
+ * can wrap, never compare it with "less than", always use "not equals".
+ *
+ * This can be used to automatically detect changes to a #PangoLayout, and
+ * is useful for example to decide whether a layout needs redrawing.
+ * To force the serial to be increased, use pango_layout_context_changed().
+ *
+ * Return value: The current serial number of @layout.
+ *
+ * Since: 1.32.4
+ **/
+guint
+pango_layout_get_serial (PangoLayout *layout)
+{
+ check_context_changed (layout);
+ return layout->serial;
+}
+
+/**
* pango_layout_get_log_attrs:
* @layout: a #PangoLayout
* @attrs: (out)(array length=n_attrs)(transfer container):
@@ -2475,6 +2531,8 @@ pango_layout_get_extents_internal (PangoLayout *layout,
g_return_if_fail (layout != NULL);
+ pango_layout_check_lines (layout);
+
if (ink_rect && layout->ink_rect_cached)
{
*ink_rect = layout->ink_rect;
@@ -2488,8 +2546,6 @@ pango_layout_get_extents_internal (PangoLayout *layout,
if (!ink_rect && !logical_rect && !line_extents)
return;
- pango_layout_check_lines (layout);
-
/* When we are not wrapping, we need the overall width of the layout to
* figure out the x_offsets of each line. However, we only need the
* x_offsets if we are computing the ink_rect or individual line extents.
@@ -3799,6 +3855,8 @@ pango_layout_check_lines (PangoLayout *layout)
PangoDirection prev_base_dir = PANGO_DIRECTION_NEUTRAL, base_dir = PANGO_DIRECTION_NEUTRAL;
ParaBreakState state;
+ check_context_changed (layout);
+
if (G_LIKELY (layout->lines))
return;
diff --git a/pango/pango-layout.h b/pango/pango-layout.h
index 6bc50a6a..8177612c 100644
--- a/pango/pango-layout.h
+++ b/pango/pango-layout.h
@@ -163,6 +163,7 @@ gboolean pango_layout_is_ellipsized (PangoLayout *layout);
int pango_layout_get_unknown_glyphs_count (PangoLayout *layout);
void pango_layout_context_changed (PangoLayout *layout);
+guint pango_layout_get_serial (PangoLayout *layout);
void pango_layout_get_log_attrs (PangoLayout *layout,
PangoLogAttr **attrs,
diff --git a/pango/pango.def b/pango/pango.def
index 3b4252f3..77098e75 100644
--- a/pango/pango.def
+++ b/pango/pango.def
@@ -255,6 +255,7 @@ EXPORTS
pango_layout_get_log_attrs_readonly
pango_layout_get_pixel_extents
pango_layout_get_pixel_size
+ pango_layout_get_serial
pango_layout_get_single_paragraph_mode
pango_layout_get_size
pango_layout_get_spacing