summaryrefslogtreecommitdiff
path: root/pango
diff options
context:
space:
mode:
authorHavoc Pennington <hp@redhat.com>2000-09-25 17:14:58 +0000
committerHavoc Pennington <hp@src.gnome.org>2000-09-25 17:14:58 +0000
commit40897ef056338e7c90b73948dd324443494eff1a (patch)
tree2742147ed7ff59b08810d89a6c8955222ee5f75c /pango
parentcd35aeb9b7d24b4956d908f36bc53259d26cf439 (diff)
downloadpango-40897ef056338e7c90b73948dd324443494eff1a.tar.gz
Add a tab array field to PangoLayout, and use it when laying out the text
2000-09-25 Havoc Pennington <hp@redhat.com> * pango/pango-layout.c: Add a tab array field to PangoLayout, and use it when laying out the text (if it's set, otherwise use default tabs-are-8-spaces thing) * pango/pango-tabs.c, pango/pango-tabs.h: tab-related data types
Diffstat (limited to 'pango')
-rw-r--r--pango/Makefile.am4
-rw-r--r--pango/pango-layout.c162
-rw-r--r--pango/pango-layout.h8
-rw-r--r--pango/pango-tabs.c349
-rw-r--r--pango/pango-tabs.h79
5 files changed, 573 insertions, 29 deletions
diff --git a/pango/Makefile.am b/pango/Makefile.am
index 53f2802e..e7e960ae 100644
--- a/pango/Makefile.am
+++ b/pango/Makefile.am
@@ -1,4 +1,4 @@
- ## Process this file with automake to create Makefile.in.
+## Process this file with automake to create Makefile.in.
INCLUDES = \
-DSYSCONFDIR=\"$(sysconfdir)\" \
@@ -22,6 +22,7 @@ libpango_la_SOURCES = \
pango-fontmap.c \
pango-item.c \
pango-layout.c \
+ pango-tabs.c \
pango-utils.c \
reorder-items.c \
shape.c
@@ -55,6 +56,7 @@ pangoinclude_HEADERS = \
pango-item.h \
pango-layout.h \
pango-modules.h \
+ pango-tabs.h \
pango-types.h \
pango-utils.h \
pangox.h
diff --git a/pango/pango-layout.c b/pango/pango-layout.c
index b8bfdecc..3f63bf37 100644
--- a/pango/pango-layout.c
+++ b/pango/pango-layout.c
@@ -55,6 +55,8 @@ struct _PangoLayout
int tab_width; /* Cached width of a tab. -1 == not yet calculated */
+ PangoTabArray *tabs;
+
GSList *lines;
};
@@ -164,6 +166,9 @@ pango_layout_finalize (GObject *object)
if (layout->font_desc)
pango_font_description_free (layout->font_desc);
+
+ if (layout->tabs)
+ pango_tab_array_free (layout->tabs);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@@ -442,6 +447,51 @@ pango_layout_get_alignment (PangoLayout *layout)
return layout->alignment;
}
+
+/**
+ * pango_layout_set_tabs:
+ * @layout: a #PangoLayout
+ * @tabs: a #PangoTabArray
+ *
+ * Sets the tabs to use for @layout, overriding the default tabs
+ * (by default, tabs are every 8 spaces). If @tabs is %NULL, the default
+ * tabs are reinstated. @tabs is copied into the layout; you must
+ * free your copy of @tabs yourself.
+ **/
+void
+pango_layout_set_tabs (PangoLayout *layout,
+ PangoTabArray *tabs)
+{
+ g_return_if_fail (PANGO_IS_LAYOUT (layout));
+
+ if (layout->tabs)
+ pango_tab_array_free (layout->tabs);
+
+ layout->tabs = tabs ? pango_tab_array_copy (tabs) : NULL;
+}
+
+/**
+ * pango_layout_get_tabs:
+ * @layout: a #PangoLayout
+ *
+ * Get the current #PangoTabArray used by this layout. If no
+ * #PangoTabArray has been set, then the default tabs are in use
+ * and %NULL is returned. Default tabs are every 8 spaces.
+ * The return value should be freed with pango_tab_array_free().
+ *
+ * Return value: a copy of the tabs for this layout, or %NULL
+ **/
+PangoTabArray*
+pango_layout_get_tabs (PangoLayout *layout)
+{
+ g_return_val_if_fail (PANGO_IS_LAYOUT (layout), NULL);
+
+ if (layout->tabs)
+ return pango_tab_array_copy (layout->tabs);
+ else
+ return NULL;
+}
+
/**
* pango_layout_set_text:
* @layout: a #PangoLayout
@@ -1677,46 +1727,104 @@ free_run (PangoLayoutRun *run, gboolean free_item)
g_free (run);
}
+/* For now we only need the tab position, we assume
+ * all tabs are left-aligned.
+ */
static int
get_tab_pos (PangoLayout *layout, int index)
{
- if (layout->tab_width == -1)
+ gint n_tabs;
+ gboolean in_pixels;
+
+ if (layout->tabs)
{
- /* Find out how wide 8 spaces are in the context's default font. Utter
- * performance killer. :-(
+ n_tabs = pango_tab_array_get_size (layout->tabs);
+ in_pixels = pango_tab_array_get_positions_in_pixels (layout->tabs);
+ }
+ else
+ {
+ n_tabs = 0;
+ in_pixels = FALSE;
+ }
+
+ if (index < n_tabs)
+ {
+ gint pos = 0;
+
+ pango_tab_array_get_tab (layout->tabs, index, NULL, &pos);
+
+ if (in_pixels)
+ return pos * PANGO_SCALE;
+ else
+ return pos;
+ }
+
+ if (n_tabs > 0)
+ {
+ /* Extrapolate tab position, repeating the last tab gap to
+ * infinity.
*/
- PangoGlyphString *glyphs = pango_glyph_string_new ();
- PangoItem *item;
- GList *items;
- int i;
+
+ gint last_pos = 0;
+ gint next_to_last_pos = 0;
+ gint pos;
+
+ pango_tab_array_get_tab (layout->tabs, n_tabs - 1, NULL, &last_pos);
- PangoAttrList *attrs = pango_attr_list_new ();
- if (layout->font_desc)
- {
- PangoAttribute *attr = pango_attr_font_desc_new (layout->font_desc);
- attr->start_index = 0;
- attr->end_index = layout->length;
+ if (n_tabs > 1)
+ pango_tab_array_get_tab (layout->tabs, n_tabs - 2, NULL, &next_to_last_pos);
+ else
+ next_to_last_pos = 0;
+
+ pos = last_pos + ((last_pos - next_to_last_pos) * (index - n_tabs + 1));
+
+ if (in_pixels)
+ return pos * PANGO_SCALE;
+ else
+ return pos;
+ }
+ else
+ {
+ /* No tab array set, so use default tab width */
+
+ if (layout->tab_width == -1)
+ {
+ /* Find out how wide 8 spaces are in the context's default
+ * font. Utter performance killer. :-(
+ */
+ PangoGlyphString *glyphs = pango_glyph_string_new ();
+ PangoItem *item;
+ GList *items;
+ int i;
+
+ PangoAttrList *attrs = pango_attr_list_new ();
+ if (layout->font_desc)
+ {
+ PangoAttribute *attr = pango_attr_font_desc_new (layout->font_desc);
+ attr->start_index = 0;
+ attr->end_index = layout->length;
- pango_attr_list_insert_before (attrs, attr);
- }
+ pango_attr_list_insert_before (attrs, attr);
+ }
- items = pango_itemize (layout->context, " ", 1, attrs);
- pango_attr_list_unref (attrs);
+ items = pango_itemize (layout->context, " ", 1, attrs);
+ pango_attr_list_unref (attrs);
- item = items->data;
- pango_shape (" ", 8, &item->analysis, glyphs);
+ item = items->data;
+ pango_shape (" ", 8, &item->analysis, glyphs);
- pango_item_free (item);
- g_list_free (items);
+ pango_item_free (item);
+ g_list_free (items);
+
+ layout->tab_width = 0;
+ for (i=0; i < glyphs->num_glyphs; i++)
+ layout->tab_width += glyphs->glyphs[i].geometry.width;
- layout->tab_width = 0;
- for (i=0; i < glyphs->num_glyphs; i++)
- layout->tab_width += glyphs->glyphs[i].geometry.width;
+ pango_glyph_string_free (glyphs);
+ }
- pango_glyph_string_free (glyphs);
+ return layout->tab_width * index;
}
-
- return layout->tab_width * index;
}
static void
diff --git a/pango/pango-layout.h b/pango/pango-layout.h
index bc3f53f9..6d60a66d 100644
--- a/pango/pango-layout.h
+++ b/pango/pango-layout.h
@@ -25,6 +25,7 @@
#include <pango/pango-attributes.h>
#include <pango/pango-context.h>
#include <pango/pango-glyph.h>
+#include <pango/pango-tabs.h>
#ifdef __cplusplus
extern "C" {
@@ -33,7 +34,7 @@ extern "C" {
typedef struct _PangoLayout PangoLayout;
typedef struct _PangoLayoutClass PangoLayoutClass;
typedef struct _PangoLayoutLine PangoLayoutLine;
-typedef struct _PangoLayoutRun PangoLayoutRun;
+typedef struct _PangoLayoutRun PangoLayoutRun;
typedef enum {
PANGO_ALIGN_LEFT,
@@ -95,6 +96,11 @@ void pango_layout_set_alignment (PangoLayout *la
PangoAlignment alignment);
PangoAlignment pango_layout_get_alignment (PangoLayout *layout);
+void pango_layout_set_tabs (PangoLayout *layout,
+ PangoTabArray *tabs);
+
+PangoTabArray* pango_layout_get_tabs (PangoLayout *layout);
+
void pango_layout_context_changed (PangoLayout *layout);
void pango_layout_get_log_attrs (PangoLayout *layout,
diff --git a/pango/pango-tabs.c b/pango/pango-tabs.c
new file mode 100644
index 00000000..c5bcb94e
--- /dev/null
+++ b/pango/pango-tabs.c
@@ -0,0 +1,349 @@
+/* Pango
+ * pango-tabs.c: Tab-related stuff
+ *
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "pango-tabs.h"
+#include <string.h>
+
+typedef struct _PangoTab PangoTab;
+
+struct _PangoTab
+{
+ gint location; /* Offset in pixels of this tab stop
+ * from the left margin of the text.
+ */
+ PangoTabAlign alignment; /* Where the tab stop appears relative
+ * to the text.
+ */
+};
+
+struct _PangoTabArray
+{
+ gint size;
+ gint allocated;
+ gboolean positions_in_pixels;
+ PangoTab *tabs;
+};
+
+static void
+init_tabs (PangoTabArray *array, gint start, gint end)
+{
+ while (start < end)
+ {
+ array->tabs[start].location = 0;
+ array->tabs[start].alignment = PANGO_TAB_LEFT;
+ ++start;
+ }
+}
+
+/**
+ * pango_tab_array_new:
+ * @initial_size: Initial number of tab stops to allocate, can be 0
+ * @positions_in_pixels: whether positions are in pixel units
+ *
+ * Creates an array of @initial_size tab stops. Tab stops are specified in
+ * pixel units if @positions_in_pixels is TRUE, otherwise in Pango
+ * units. All stops are initially at position 0.
+ *
+ * Return value: a #PangoTabArray
+ **/
+PangoTabArray*
+pango_tab_array_new (gint initial_size,
+ gboolean positions_in_pixels)
+{
+ PangoTabArray *array;
+
+ g_return_val_if_fail (initial_size >= 0, NULL);
+
+ /* alloc enough to treat array->tabs as an array of length
+ * size, though it's declared as an array of length 1.
+ * If we allowed tab array resizing we'd need to drop this
+ * optimization.
+ */
+ array = g_new (PangoTabArray, 1);
+ array->size = initial_size;
+ array->allocated = initial_size;
+
+ if (array->allocated > 0)
+ {
+ array->tabs = g_new (PangoTab, array->allocated);
+ init_tabs (array, 0, array->allocated);
+ }
+ else
+ array->tabs = NULL;
+
+ array->positions_in_pixels = positions_in_pixels;
+
+ return array;
+}
+
+/**
+ * pango_tab_array_new_with_defaults:
+ * @size: number of tab stops in the array
+ * @positions_in_pixels: whether positions are in pixel units
+ * @first_alignment: alignment of first tab stop
+ * @first_position: position of first tab stop
+ * @varargs: additional alignment/position pairs
+ *
+ * This is a convenience function that creates a #PangoTabArray
+ * and allows you to specify the alignment and position of each
+ * tab stop. You <emphasis>must</emphasis> provide an alignment
+ * and position for @size tab stops.
+ *
+ * Return value: a new #PangoTabArray
+ **/
+PangoTabArray *
+pango_tab_array_new_with_defaults (gint size,
+ gboolean positions_in_pixels,
+ PangoTabAlign first_alignment,
+ gint first_position,
+ ...)
+{
+ PangoTabArray *array;
+ va_list args;
+ int i;
+
+ g_return_val_if_fail (size >= 0, NULL);
+
+ array = pango_tab_array_new (size, positions_in_pixels);
+
+ if (size == 0)
+ return array;
+
+ array->tabs[0].alignment = first_alignment;
+ array->tabs[0].location = first_position;
+
+ if (size == 1)
+ return array;
+
+ va_start (args, first_position);
+
+ i = 1;
+ while (i < size)
+ {
+ PangoTabAlign align = va_arg (args, PangoTabAlign);
+ int pos = va_arg (args, int);
+
+ array->tabs[i].alignment = align;
+ array->tabs[i].location = pos;
+
+ ++i;
+ }
+
+ va_end (args);
+
+ return array;
+}
+
+/**
+ * pango_tab_array_copy:
+ * @src: #PangoTabArray to copy
+ *
+ * Copy a #PangoTabArray
+ *
+ * Return value: Newly-allocated #PangoTabArray
+ **/
+PangoTabArray*
+pango_tab_array_copy (PangoTabArray *src)
+{
+ PangoTabArray *copy;
+
+ g_return_val_if_fail (src != NULL, NULL);
+
+ copy = pango_tab_array_new (src->size, src->positions_in_pixels);
+
+ memcpy (copy->tabs, src->tabs, sizeof(PangoTab)*src->size);
+
+ return copy;
+}
+
+/**
+ * pango_tab_array_free:
+ * @tab_array: a #PangoTabArray
+ *
+ * Free a tab array and associated resources.
+ *
+ **/
+void
+pango_tab_array_free (PangoTabArray *tab_array)
+{
+ g_return_if_fail (tab_array != NULL);
+
+ g_free (tab_array);
+}
+
+/**
+ * pango_tab_array_get_size:
+ * @tab_array: a #PangoTabArray
+ *
+ * Get the number of tab stops in @tab_array.
+ *
+ * Return value: the number of tab stops in the array.
+ **/
+gint
+pango_tab_array_get_size (PangoTabArray *tab_array)
+{
+ g_return_val_if_fail (tab_array != NULL, 0);
+
+ return tab_array->size;
+}
+
+/**
+ * pango_tab_array_resize:
+ * @tab_array: a #PangoTabArray
+ * @new_size: new size of the array
+ *
+ * Resizes a tab array. You must subsequently initialize any tabs that
+ * were added as a result of growing the array.
+ **/
+void
+pango_tab_array_resize (PangoTabArray *tab_array,
+ gint new_size)
+{
+ if (new_size > tab_array->allocated)
+ {
+ gint current_end = tab_array->allocated;
+
+ /* Ratchet allocated size up above the index. */
+ if (tab_array->allocated == 0)
+ tab_array->allocated = 2;
+
+ while (new_size > tab_array->allocated)
+ tab_array->allocated = tab_array->allocated * 2;
+
+ tab_array->tabs = g_realloc (tab_array->tabs,
+ tab_array->allocated);
+
+ init_tabs (tab_array, current_end, tab_array->allocated);
+ }
+
+ tab_array->size = new_size;
+}
+
+/**
+ * pango_tab_array_set_tab:
+ * @tab_array: a #PangoTabArray
+ * @tab_index: the index of a tab stop
+ * @alignment: tab alignment
+ * @location: tab location in pango units
+ *
+ * Sets the alignment and location of a tab stop.
+ * @alignment must always be #PANGO_TAB_LEFT in the current
+ * implementation.
+ *
+ **/
+void
+pango_tab_array_set_tab (PangoTabArray *tab_array,
+ gint tab_index,
+ PangoTabAlign alignment,
+ gint location)
+{
+ g_return_if_fail (tab_array != NULL);
+ g_return_if_fail (tab_index >= 0);
+ g_return_if_fail (alignment == PANGO_TAB_LEFT);
+ g_return_if_fail (location >= 0);
+
+ if (tab_index >= tab_array->size)
+ pango_tab_array_resize (tab_array, tab_index + 1);
+
+ tab_array->tabs[tab_index].alignment = alignment;
+ tab_array->tabs[tab_index].location = location;
+}
+
+/**
+ * pango_tab_array_get_tab:
+ * @tab_array: a #PangoTabArray
+ * @tab_index: tab stop index
+ * @alignment: location to store alignment
+ * @location: location to store tab position
+ *
+ * Gets the alignment and position of a tab stop.
+ * @alignment or @location may be NULL if you aren't
+ * interested in their value.
+ *
+ **/
+void
+pango_tab_array_get_tab (PangoTabArray *tab_array,
+ gint tab_index,
+ PangoTabAlign *alignment,
+ gint *location)
+{
+ g_return_if_fail (tab_array != NULL);
+ g_return_if_fail (tab_index < tab_array->size);
+ g_return_if_fail (tab_index >= 0);
+
+ if (alignment)
+ *alignment = tab_array->tabs[tab_index].alignment;
+
+ if (location)
+ *location = tab_array->tabs[tab_index].location;
+}
+
+/**
+ * pango_tab_array_get_tabs:
+ * @tab_array: a #PangoTabArray
+ * @alignments: array to fill with tab stop alignments
+ * @locations: array to fill with tab stop positions
+ *
+ * @alignments and @locations must be arrays with
+ * one member for each tab stop in @tab_array (i.e. the
+ * size of @alignments and @locations should match
+ * the result of pango_tab_array_get_size()). The arrays
+ * will be filled with the alignment and location of
+ * each tab stop.
+ *
+ **/
+void
+pango_tab_array_get_tabs (PangoTabArray *tab_array,
+ PangoTabAlign *alignments,
+ gint *locations)
+{
+ gint i;
+
+ g_return_if_fail (tab_array != NULL);
+
+ i = 0;
+ while (i < tab_array->size)
+ {
+ if (alignments)
+ alignments[i] = tab_array->tabs[i].alignment;
+ if (locations)
+ locations[i] = tab_array->tabs[i].location;
+
+ ++i;
+ }
+}
+
+/**
+ * pango_tab_array_get_positions_in_pixels:
+ * @tab_array: a #PangoTabArray
+ *
+ * Returns TRUE if the tab positions are in pixels, FALSE if they are
+ * in Pango units.
+ *
+ * Return value: whether positions are in pixels
+ **/
+gboolean
+pango_tab_array_get_positions_in_pixels (PangoTabArray *tab_array)
+{
+ g_return_val_if_fail (tab_array != NULL, FALSE);
+
+ return tab_array->positions_in_pixels;
+}
diff --git a/pango/pango-tabs.h b/pango/pango-tabs.h
new file mode 100644
index 00000000..bba41488
--- /dev/null
+++ b/pango/pango-tabs.h
@@ -0,0 +1,79 @@
+/* Pango
+ * pango-tabs.h: Tab-related stuff
+ *
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PANGO_TABS_H__
+#define __PANGO_TABS_H__
+
+#include <pango/pango-types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _PangoTabArray PangoTabArray;
+
+typedef enum
+{
+ PANGO_TAB_LEFT
+
+ /* These are not supported now, but may be in the
+ * future.
+ *
+ * PANGO_TAB_RIGHT,
+ * PANGO_TAB_CENTER,
+ * PANGO_TAB_NUMERIC
+ */
+} PangoTabAlign;
+
+PangoTabArray *pango_tab_array_new (gint initial_size,
+ gboolean positions_in_pixels);
+PangoTabArray *pango_tab_array_new_with_positions (gint size,
+ gboolean positions_in_pixels,
+ PangoTabAlign first_alignment,
+ gint first_position,
+ ...);
+PangoTabArray *pango_tab_array_copy (PangoTabArray *src);
+void pango_tab_array_free (PangoTabArray *tab_array);
+gint pango_tab_array_get_size (PangoTabArray *tab_array);
+void pango_tab_array_resize (PangoTabArray *tab_array,
+ gint new_size);
+void pango_tab_array_set_tab (PangoTabArray *tab_array,
+ gint tab_index,
+ PangoTabAlign alignment,
+ gint location);
+void pango_tab_array_get_tab (PangoTabArray *tab_array,
+ gint tab_index,
+ PangoTabAlign *alignment,
+ gint *location);
+void pango_tab_array_get_tabs (PangoTabArray *tab_array,
+ PangoTabAlign *alignments,
+ gint *locations);
+
+gboolean pango_tab_array_get_positions_in_pixels (PangoTabArray *tab_array);
+
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __PANGO_TABS_H__ */