/pango/pango-layout.c
C | 6471 lines | 3927 code | 970 blank | 1574 comment | 791 complexity | 5344e44b5d1f4418be39a12b6661480d MD5 | raw file
Possible License(s): LGPL-2.0
Large files files are truncated, but you can click here to view the full file
- /* Pango
- * pango-layout.c: High-level layout driver
- *
- * Copyright (C) 2000, 2001, 2006 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.
- */
- /**
- * SECTION:layout
- * @short_description:High-level layout driver objects
- * @title:Layout Objects
- *
- * While complete access to the layout capabilities of Pango is provided
- * using the detailed interfaces for itemization and shaping, using
- * that functionality directly involves writing a fairly large amount
- * of code. The objects and functions in this section provide a
- * high-level driver for formatting entire paragraphs of text
- * at once.
- */
- /**
- * PangoLayout:
- *
- * The #PangoLayout structure represents an entire paragraph
- * of text. It is initialized with a #PangoContext, UTF-8 string
- * and set of attributes for that string. Once that is done, the
- * set of formatted lines can be extracted from the object,
- * the layout can be rendered, and conversion between logical
- * character positions within the layout's text, and the physical
- * position of the resulting glyphs can be made.
- *
- * There are also a number of parameters to adjust the formatting
- * of a #PangoLayout, which are illustrated in <xref linkend="parameters"/>.
- * It is possible, as well, to ignore the 2-D setup, and simply
- * treat the results of a #PangoLayout as a list of lines.
- *
- * <figure id="parameters">
- * <title>Adjustable parameters for a PangoLayout</title>
- * <graphic fileref="layout.gif" format="GIF"></graphic>
- * </figure>
- *
- * The #PangoLayout structure is opaque, and has no user-visible
- * fields.
- */
- /**
- * PangoLayoutIter:
- *
- * A #PangoLayoutIter structure can be used to
- * iterate over the visual extents of a #PangoLayout.
- *
- * The #PangoLayoutIter structure is opaque, and
- * has no user-visible fields.
- */
- #include "config.h"
- #include "pango-glyph.h" /* For pango_shape() */
- #include "pango-break.h"
- #include "pango-item.h"
- #include "pango-engine.h"
- #include "pango-impl-utils.h"
- #include "pango-glyph-item.h"
- #include <string.h>
- #include "pango-layout-private.h"
- typedef struct _ItemProperties ItemProperties;
- typedef struct _ParaBreakState ParaBreakState;
- struct _ItemProperties
- {
- PangoUnderline uline;
- gboolean strikethrough;
- gint rise;
- gint letter_spacing;
- gboolean shape_set;
- PangoRectangle *shape_ink_rect;
- PangoRectangle *shape_logical_rect;
- };
- typedef struct _PangoLayoutLinePrivate PangoLayoutLinePrivate;
- struct _PangoLayoutLinePrivate
- {
- PangoLayoutLine line;
- guint ref_count;
- /* Extents cache status:
- *
- * LEAKED means that the user has access to this line structure or a
- * run included in this line, and so can change the glyphs/glyph-widths.
- * If this is true, extents caching will be disabled.
- */
- enum {
- NOT_CACHED,
- CACHED,
- LEAKED
- } cache_status;
- PangoRectangle ink_rect;
- PangoRectangle logical_rect;
- };
- struct _PangoLayoutClass
- {
- GObjectClass parent_class;
- };
- #define LINE_IS_VALID(line) ((line) && (line)->layout != NULL)
- #ifdef G_DISABLE_CHECKS
- #define ITER_IS_INVALID(iter) FALSE
- #else
- #define ITER_IS_INVALID(iter) G_UNLIKELY (check_invalid ((iter), G_STRLOC))
- static gboolean
- check_invalid (PangoLayoutIter *iter,
- const char *loc)
- {
- if (iter->line->layout == NULL)
- {
- g_warning ("%s: PangoLayout changed since PangoLayoutIter was created, iterator invalid", loc);
- return TRUE;
- }
- else
- {
- return FALSE;
- }
- }
- #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);
- static PangoAttrList *pango_layout_get_effective_attributes (PangoLayout *layout);
- static PangoLayoutLine * pango_layout_line_new (PangoLayout *layout);
- static void pango_layout_line_postprocess (PangoLayoutLine *line,
- ParaBreakState *state,
- gboolean wrapped);
- static int *pango_layout_line_get_log2vis_map (PangoLayoutLine *line,
- gboolean strong);
- static int *pango_layout_line_get_vis2log_map (PangoLayoutLine *line,
- gboolean strong);
- static void pango_layout_line_leaked (PangoLayoutLine *line);
- /* doesn't leak line */
- static PangoLayoutLine* _pango_layout_iter_get_line (PangoLayoutIter *iter);
- static void pango_layout_get_item_properties (PangoItem *item,
- ItemProperties *properties);
- static void pango_layout_get_empty_extents_at_index (PangoLayout *layout,
- int index,
- PangoRectangle *logical_rect);
- static void pango_layout_finalize (GObject *object);
- 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;
- layout->length = 0;
- layout->width = -1;
- layout->height = -1;
- layout->indent = 0;
- layout->spacing = 0;
- layout->alignment = PANGO_ALIGN_LEFT;
- layout->justify = FALSE;
- layout->auto_dir = TRUE;
- layout->log_attrs = NULL;
- layout->lines = NULL;
- layout->line_count = 0;
- layout->tab_width = -1;
- layout->unknown_glyphs_count = -1;
- layout->wrap = PANGO_WRAP_WORD;
- layout->is_wrapped = FALSE;
- layout->ellipsize = PANGO_ELLIPSIZE_NONE;
- layout->is_ellipsized = FALSE;
- }
- static void
- pango_layout_class_init (PangoLayoutClass *klass)
- {
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- object_class->finalize = pango_layout_finalize;
- }
- static void
- pango_layout_finalize (GObject *object)
- {
- PangoLayout *layout;
- layout = PANGO_LAYOUT (object);
- pango_layout_clear_lines (layout);
- if (layout->context)
- g_object_unref (layout->context);
- if (layout->attrs)
- pango_attr_list_unref (layout->attrs);
- g_free (layout->text);
- if (layout->font_desc)
- pango_font_description_free (layout->font_desc);
- if (layout->tabs)
- pango_tab_array_free (layout->tabs);
- G_OBJECT_CLASS (pango_layout_parent_class)->finalize (object);
- }
- /**
- * pango_layout_new:
- * @context: a #PangoContext
- *
- * Create a new #PangoLayout object with attributes initialized to
- * default values for a particular #PangoContext.
- *
- * Return value: the newly allocated #PangoLayout, with a reference
- * count of one, which should be freed with
- * g_object_unref().
- **/
- PangoLayout *
- pango_layout_new (PangoContext *context)
- {
- PangoLayout *layout;
- g_return_val_if_fail (context != NULL, NULL);
- 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;
- }
- /**
- * pango_layout_copy:
- * @src: a #PangoLayout
- *
- * Does a deep copy-by-value of the @src layout. The attribute list,
- * tab array, and text from the original layout are all copied by
- * value.
- *
- * Return value: (transfer full): the newly allocated #PangoLayout,
- * with a reference count of one, which should be freed
- * with g_object_unref().
- **/
- PangoLayout*
- pango_layout_copy (PangoLayout *src)
- {
- PangoLayout *layout;
- g_return_val_if_fail (PANGO_IS_LAYOUT (src), NULL);
- /* Copy referenced members */
- layout = pango_layout_new (src->context);
- if (src->attrs)
- layout->attrs = pango_attr_list_copy (src->attrs);
- if (src->font_desc)
- layout->font_desc = pango_font_description_copy (src->font_desc);
- if (src->tabs)
- layout->tabs = pango_tab_array_copy (src->tabs);
- /* Dupped */
- layout->text = g_strdup (src->text);
- /* Value fields */
- memcpy (&layout->copy_begin, &src->copy_begin,
- G_STRUCT_OFFSET (PangoLayout, copy_end) - G_STRUCT_OFFSET (PangoLayout, copy_begin));
- return layout;
- }
- /**
- * pango_layout_get_context:
- * @layout: a #PangoLayout
- *
- * Retrieves the #PangoContext used for this layout.
- *
- * Return value: (transfer none): the #PangoContext for the layout.
- * This does not have an additional refcount added, so if you want to
- * keep a copy of this around, you must reference it yourself.
- **/
- PangoContext *
- pango_layout_get_context (PangoLayout *layout)
- {
- g_return_val_if_fail (layout != NULL, NULL);
- return layout->context;
- }
- /**
- * pango_layout_set_width:
- * @layout: a #PangoLayout.
- * @width: the desired width in Pango units, or -1 to indicate that no
- * wrapping or ellipsization should be performed.
- *
- * Sets the width to which the lines of the #PangoLayout should wrap or
- * ellipsized. The default value is -1: no width set.
- **/
- void
- pango_layout_set_width (PangoLayout *layout,
- int width)
- {
- g_return_if_fail (layout != NULL);
- if (width < 0)
- width = -1;
- if (width != layout->width)
- {
- layout->width = width;
- layout_changed (layout);
- }
- }
- /**
- * pango_layout_get_width:
- * @layout: a #PangoLayout
- *
- * Gets the width to which the lines of the #PangoLayout should wrap.
- *
- * Return value: the width in Pango units, or -1 if no width set.
- **/
- int
- pango_layout_get_width (PangoLayout *layout)
- {
- g_return_val_if_fail (layout != NULL, 0);
- return layout->width;
- }
- /**
- * pango_layout_set_height:
- * @layout: a #PangoLayout.
- * @height: the desired height of the layout in Pango units if positive,
- * or desired number of lines if negative.
- *
- * Sets the height to which the #PangoLayout should be ellipsized at. There
- * are two different behaviors, based on whether @height is positive or
- * negative.
- *
- * If @height is positive, it will be the maximum height of the layout. Only
- * lines would be shown that would fit, and if there is any text omitted,
- * an ellipsis added. At least one line is included in each paragraph regardless
- * of how small the height value is. A value of zero will render exactly one
- * line for the entire layout.
- *
- * If @height is negative, it will be the (negative of) maximum number of lines per
- * paragraph. That is, the total number of lines shown may well be more than
- * this value if the layout contains multiple paragraphs of text.
- * The default value of -1 means that first line of each paragraph is ellipsized.
- * This behvaior may be changed in the future to act per layout instead of per
- * paragraph. File a bug against pango at <ulink
- * url="http://bugzilla.gnome.org/">http://bugzilla.gnome.org/</ulink> if your
- * code relies on this behavior.
- *
- * Height setting only has effect if a positive width is set on
- * @layout and ellipsization mode of @layout is not %PANGO_ELLIPSIZE_NONE.
- * The behavior is undefined if a height other than -1 is set and
- * ellipsization mode is set to %PANGO_ELLIPSIZE_NONE, and may change in the
- * future.
- *
- * Since: 1.20
- **/
- void
- pango_layout_set_height (PangoLayout *layout,
- int height)
- {
- g_return_if_fail (layout != NULL);
- if (height != layout->height)
- {
- layout->height = height;
- /* Do not invalidate if the number of lines requested is
- * larger than the total number of lines in layout.
- * Bug 549003
- */
- if (layout->ellipsize != PANGO_ELLIPSIZE_NONE &&
- !(layout->lines && layout->is_ellipsized == FALSE &&
- height < 0 && layout->line_count <= (guint) -height))
- layout_changed (layout);
- }
- }
- /**
- * pango_layout_get_height:
- * @layout: a #PangoLayout
- *
- * Gets the height of layout used for ellipsization. See
- * pango_layout_set_height() for details.
- *
- * Return value: the height, in Pango units if positive, or
- * number of lines if negative.
- *
- * Since: 1.20
- **/
- int
- pango_layout_get_height (PangoLayout *layout)
- {
- g_return_val_if_fail (layout != NULL, 0);
- return layout->height;
- }
- /**
- * pango_layout_set_wrap:
- * @layout: a #PangoLayout
- * @wrap: the wrap mode
- *
- * Sets the wrap mode; the wrap mode only has effect if a width
- * is set on the layout with pango_layout_set_width().
- * To turn off wrapping, set the width to -1.
- **/
- void
- pango_layout_set_wrap (PangoLayout *layout,
- PangoWrapMode wrap)
- {
- g_return_if_fail (PANGO_IS_LAYOUT (layout));
- if (layout->wrap != wrap)
- {
- layout->wrap = wrap;
- if (layout->width != -1)
- layout_changed (layout);
- }
- }
- /**
- * pango_layout_get_wrap:
- * @layout: a #PangoLayout
- *
- * Gets the wrap mode for the layout.
- *
- * Use pango_layout_is_wrapped() to query whether any paragraphs
- * were actually wrapped.
- *
- * Return value: active wrap mode.
- **/
- PangoWrapMode
- pango_layout_get_wrap (PangoLayout *layout)
- {
- g_return_val_if_fail (PANGO_IS_LAYOUT (layout), 0);
- return layout->wrap;
- }
- /**
- * pango_layout_is_wrapped:
- * @layout: a #PangoLayout
- *
- * Queries whether the layout had to wrap any paragraphs.
- *
- * This returns %TRUE if a positive width is set on @layout,
- * ellipsization mode of @layout is set to %PANGO_ELLIPSIZE_NONE,
- * and there are paragraphs exceeding the layout width that have
- * to be wrapped.
- *
- * Return value: %TRUE if any paragraphs had to be wrapped, %FALSE
- * otherwise.
- *
- * Since: 1.16
- */
- gboolean
- pango_layout_is_wrapped (PangoLayout *layout)
- {
- g_return_val_if_fail (layout != NULL, FALSE);
- pango_layout_check_lines (layout);
- return layout->is_wrapped;
- }
- /**
- * pango_layout_set_indent:
- * @layout: a #PangoLayout.
- * @indent: the amount by which to indent.
- *
- * Sets the width in Pango units to indent each paragraph. A negative value
- * of @indent will produce a hanging indentation. That is, the first line will
- * have the full width, and subsequent lines will be indented by the
- * absolute value of @indent.
- *
- * The indent setting is ignored if layout alignment is set to
- * %PANGO_ALIGN_CENTER.
- **/
- void
- pango_layout_set_indent (PangoLayout *layout,
- int indent)
- {
- g_return_if_fail (layout != NULL);
- if (indent != layout->indent)
- {
- layout->indent = indent;
- layout_changed (layout);
- }
- }
- /**
- * pango_layout_get_indent:
- * @layout: a #PangoLayout
- *
- * Gets the paragraph indent width in Pango units. A negative value
- * indicates a hanging indentation.
- *
- * Return value: the indent in Pango units.
- **/
- int
- pango_layout_get_indent (PangoLayout *layout)
- {
- g_return_val_if_fail (layout != NULL, 0);
- return layout->indent;
- }
- /**
- * pango_layout_set_spacing:
- * @layout: a #PangoLayout.
- * @spacing: the amount of spacing
- *
- * Sets the amount of spacing in Pango unit between the lines of the
- * layout.
- **/
- void
- pango_layout_set_spacing (PangoLayout *layout,
- int spacing)
- {
- g_return_if_fail (layout != NULL);
- if (spacing != layout->spacing)
- {
- layout->spacing = spacing;
- layout_changed (layout);
- }
- }
- /**
- * pango_layout_get_spacing:
- * @layout: a #PangoLayout
- *
- * Gets the amount of spacing between the lines of the layout.
- *
- * Return value: the spacing in Pango units.
- **/
- int
- pango_layout_get_spacing (PangoLayout *layout)
- {
- g_return_val_if_fail (layout != NULL, 0);
- return layout->spacing;
- }
- /**
- * pango_layout_set_attributes:
- * @layout: a #PangoLayout
- * @attrs: (allow-none) (transfer none): a #PangoAttrList, can be %NULL
- *
- * Sets the text attributes for a layout object.
- * References @attrs, so the caller can unref its reference.
- **/
- void
- pango_layout_set_attributes (PangoLayout *layout,
- PangoAttrList *attrs)
- {
- PangoAttrList *old_attrs;
- g_return_if_fail (layout != NULL);
- old_attrs = layout->attrs;
- /* We always clear lines such that this function can be called
- * whenever attrs changes.
- */
- layout->attrs = attrs;
- if (layout->attrs)
- pango_attr_list_ref (layout->attrs);
- layout_changed (layout);
- if (old_attrs)
- pango_attr_list_unref (old_attrs);
- layout->tab_width = -1;
- }
- /**
- * pango_layout_get_attributes:
- * @layout: a #PangoLayout
- *
- * Gets the attribute list for the layout, if any.
- *
- * Return value: (transfer none): a #PangoAttrList.
- **/
- PangoAttrList*
- pango_layout_get_attributes (PangoLayout *layout)
- {
- g_return_val_if_fail (PANGO_IS_LAYOUT (layout), NULL);
- return layout->attrs;
- }
- /**
- * pango_layout_set_font_description:
- * @layout: a #PangoLayout
- * @desc: (allow-none): the new #PangoFontDescription, or %NULL to unset the
- * current font description
- *
- * Sets the default font description for the layout. If no font
- * description is set on the layout, the font description from
- * the layout's context is used.
- **/
- void
- pango_layout_set_font_description (PangoLayout *layout,
- const PangoFontDescription *desc)
- {
- g_return_if_fail (layout != NULL);
- if (desc != layout->font_desc &&
- (!desc || !layout->font_desc || !pango_font_description_equal(desc, layout->font_desc)))
- {
- if (layout->font_desc)
- pango_font_description_free (layout->font_desc);
- layout->font_desc = desc ? pango_font_description_copy (desc) : NULL;
- layout_changed (layout);
- layout->tab_width = -1;
- }
- }
- /**
- * pango_layout_get_font_description:
- * @layout: a #PangoLayout
- *
- * Gets the font description for the layout, if any.
- *
- * Return value: (nullable): a pointer to the layout's font
- * description, or %NULL if the font description from the layout's
- * context is inherited. This value is owned by the layout and must
- * not be modified or freed.
- *
- * Since: 1.8
- **/
- const PangoFontDescription *
- pango_layout_get_font_description (PangoLayout *layout)
- {
- g_return_val_if_fail (PANGO_IS_LAYOUT (layout), NULL);
- return layout->font_desc;
- }
- /**
- * pango_layout_set_justify:
- * @layout: a #PangoLayout
- * @justify: whether the lines in the layout should be justified.
- *
- * Sets whether each complete line should be stretched to
- * fill the entire width of the layout. This stretching is typically
- * done by adding whitespace, but for some scripts (such as Arabic),
- * the justification may be done in more complex ways, like extending
- * the characters.
- *
- * Note that this setting is not implemented and so is ignored in Pango
- * older than 1.18.
- **/
- void
- pango_layout_set_justify (PangoLayout *layout,
- gboolean justify)
- {
- g_return_if_fail (layout != NULL);
- if (justify != layout->justify)
- {
- layout->justify = justify;
- if (layout->is_ellipsized || layout->is_wrapped)
- layout_changed (layout);
- }
- }
- /**
- * pango_layout_get_justify:
- * @layout: a #PangoLayout
- *
- * Gets whether each complete line should be stretched to fill the entire
- * width of the layout.
- *
- * Return value: the justify.
- **/
- gboolean
- pango_layout_get_justify (PangoLayout *layout)
- {
- g_return_val_if_fail (layout != NULL, FALSE);
- return layout->justify;
- }
- /**
- * pango_layout_set_auto_dir:
- * @layout: a #PangoLayout
- * @auto_dir: if %TRUE, compute the bidirectional base direction
- * from the layout's contents.
- *
- * Sets whether to calculate the bidirectional base direction
- * for the layout according to the contents of the layout;
- * when this flag is on (the default), then paragraphs in
- @layout that begin with strong right-to-left characters
- * (Arabic and Hebrew principally), will have right-to-left
- * layout, paragraphs with letters from other scripts will
- * have left-to-right layout. Paragraphs with only neutral
- * characters get their direction from the surrounding paragraphs.
- *
- * When %FALSE, the choice between left-to-right and
- * right-to-left layout is done according to the base direction
- * of the layout's #PangoContext. (See pango_context_set_base_dir()).
- *
- * When the auto-computed direction of a paragraph differs from the
- * base direction of the context, the interpretation of
- * %PANGO_ALIGN_LEFT and %PANGO_ALIGN_RIGHT are swapped.
- *
- * Since: 1.4
- **/
- void
- pango_layout_set_auto_dir (PangoLayout *layout,
- gboolean auto_dir)
- {
- g_return_if_fail (PANGO_IS_LAYOUT (layout));
- auto_dir = auto_dir != FALSE;
- if (auto_dir != layout->auto_dir)
- {
- layout->auto_dir = auto_dir;
- layout_changed (layout);
- }
- }
- /**
- * pango_layout_get_auto_dir:
- * @layout: a #PangoLayout
- *
- * Gets whether to calculate the bidirectional base direction
- * for the layout according to the contents of the layout.
- * See pango_layout_set_auto_dir().
- *
- * Return value: %TRUE if the bidirectional base direction
- * is computed from the layout's contents, %FALSE otherwise.
- *
- * Since: 1.4
- **/
- gboolean
- pango_layout_get_auto_dir (PangoLayout *layout)
- {
- g_return_val_if_fail (PANGO_IS_LAYOUT (layout), FALSE);
- return layout->auto_dir;
- }
- /**
- * pango_layout_set_alignment:
- * @layout: a #PangoLayout
- * @alignment: the alignment
- *
- * Sets the alignment for the layout: how partial lines are
- * positioned within the horizontal space available.
- **/
- void
- pango_layout_set_alignment (PangoLayout *layout,
- PangoAlignment alignment)
- {
- g_return_if_fail (layout != NULL);
- if (alignment != layout->alignment)
- {
- layout->alignment = alignment;
- layout_changed (layout);
- }
- }
- /**
- * pango_layout_get_alignment:
- * @layout: a #PangoLayout
- *
- * Gets the alignment for the layout: how partial lines are
- * positioned within the horizontal space available.
- *
- * Return value: the alignment.
- **/
- PangoAlignment
- pango_layout_get_alignment (PangoLayout *layout)
- {
- g_return_val_if_fail (layout != NULL, PANGO_ALIGN_LEFT);
- return layout->alignment;
- }
- /**
- * pango_layout_set_tabs:
- * @layout: a #PangoLayout
- * @tabs: (allow-none): a #PangoTabArray, or %NULL
- *
- * 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 (tabs != layout->tabs)
- {
- if (layout->tabs)
- pango_tab_array_free (layout->tabs);
- layout->tabs = tabs ? pango_tab_array_copy (tabs) : NULL;
- layout_changed (layout);
- }
- }
- /**
- * pango_layout_get_tabs:
- * @layout: a #PangoLayout
- *
- * Gets 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: (nullable): 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_single_paragraph_mode:
- * @layout: a #PangoLayout
- * @setting: new setting
- *
- * If @setting is %TRUE, do not treat newlines and similar characters
- * as paragraph separators; instead, keep all text in a single paragraph,
- * and display a glyph for paragraph separator characters. Used when
- * you want to allow editing of newlines on a single text line.
- **/
- void
- pango_layout_set_single_paragraph_mode (PangoLayout *layout,
- gboolean setting)
- {
- g_return_if_fail (PANGO_IS_LAYOUT (layout));
- setting = setting != FALSE;
- if (layout->single_paragraph != setting)
- {
- layout->single_paragraph = setting;
- layout_changed (layout);
- }
- }
- /**
- * pango_layout_get_single_paragraph_mode:
- * @layout: a #PangoLayout
- *
- * Obtains the value set by pango_layout_set_single_paragraph_mode().
- *
- * Return value: %TRUE if the layout does not break paragraphs at
- * paragraph separator characters, %FALSE otherwise.
- **/
- gboolean
- pango_layout_get_single_paragraph_mode (PangoLayout *layout)
- {
- g_return_val_if_fail (PANGO_IS_LAYOUT (layout), FALSE);
- return layout->single_paragraph;
- }
- /**
- * pango_layout_set_ellipsize:
- * @layout: a #PangoLayout
- * @ellipsize: the new ellipsization mode for @layout
- *
- * Sets the type of ellipsization being performed for @layout.
- * Depending on the ellipsization mode @ellipsize text is
- * removed from the start, middle, or end of text so they
- * fit within the width and height of layout set with
- * pango_layout_set_width() and pango_layout_set_height().
- *
- * If the layout contains characters such as newlines that
- * force it to be layed out in multiple paragraphs, then whether
- * each paragraph is ellipsized separately or the entire layout
- * is ellipsized as a whole depends on the set height of the layout.
- * See pango_layout_set_height() for details.
- *
- * Since: 1.6
- **/
- void
- pango_layout_set_ellipsize (PangoLayout *layout,
- PangoEllipsizeMode ellipsize)
- {
- g_return_if_fail (PANGO_IS_LAYOUT (layout));
- if (ellipsize != layout->ellipsize)
- {
- layout->ellipsize = ellipsize;
- if (layout->is_ellipsized || layout->is_wrapped)
- layout_changed (layout);
- }
- }
- /**
- * pango_layout_get_ellipsize:
- * @layout: a #PangoLayout
- *
- * Gets the type of ellipsization being performed for @layout.
- * See pango_layout_set_ellipsize()
- *
- * Return value: the current ellipsization mode for @layout.
- *
- * Use pango_layout_is_ellipsized() to query whether any paragraphs
- * were actually ellipsized.
- *
- * Since: 1.6
- **/
- PangoEllipsizeMode
- pango_layout_get_ellipsize (PangoLayout *layout)
- {
- g_return_val_if_fail (PANGO_IS_LAYOUT (layout), PANGO_ELLIPSIZE_NONE);
- return layout->ellipsize;
- }
- /**
- * pango_layout_is_ellipsized:
- * @layout: a #PangoLayout
- *
- * Queries whether the layout had to ellipsize any paragraphs.
- *
- * This returns %TRUE if the ellipsization mode for @layout
- * is not %PANGO_ELLIPSIZE_NONE, a positive width is set on @layout,
- * and there are paragraphs exceeding that width that have to be
- * ellipsized.
- *
- * Return value: %TRUE if any paragraphs had to be ellipsized, %FALSE
- * otherwise.
- *
- * Since: 1.16
- */
- gboolean
- pango_layout_is_ellipsized (PangoLayout *layout)
- {
- g_return_val_if_fail (layout != NULL, FALSE);
- pango_layout_check_lines (layout);
- return layout->is_ellipsized;
- }
- /**
- * pango_layout_set_text:
- * @layout: a #PangoLayout
- * @text: a valid UTF-8 string
- * @length: maximum length of @text, in bytes. -1 indicates that
- * the string is nul-terminated and the length should be
- * calculated. The text will also be truncated on
- * encountering a nul-termination even when @length is
- * positive.
- *
- * Sets the text of the layout.
- *
- * Note that if you have used
- * pango_layout_set_markup() or pango_layout_set_markup_with_accel() on
- * @layout before, you may want to call pango_layout_set_attributes() to clear
- * the attributes set on the layout from the markup as this function does not
- * clear attributes.
- **/
- void
- pango_layout_set_text (PangoLayout *layout,
- const char *text,
- int length)
- {
- char *old_text, *start, *end;
- g_return_if_fail (layout != NULL);
- g_return_if_fail (length == 0 || text != NULL);
- old_text = layout->text;
- if (length < 0)
- layout->text = g_strdup (text);
- else if (length > 0)
- /* This is not exactly what we want. We don't need the padding...
- */
- layout->text = g_strndup (text, length);
- else
- layout->text = g_malloc0 (1);
- layout->length = strlen (layout->text);
- /* validate it, and replace invalid bytes with '?'
- */
- start = layout->text;
- for (;;) {
- gboolean valid;
- valid = g_utf8_validate (start, -1, (const char **)&end);
- if (!*end)
- break;
- /* Replace invalid bytes with -1. The -1 will be converted to
- * ((gunichar) -1) by glib, and that in turn yields a glyph value of
- * ((PangoGlyph) -1) by PANGO_GET_UNKNOWN_GLYPH(-1),
- * and that's PANGO_GLYPH_INVALID_INPUT.
- */
- if (!valid)
- *end++ = -1;
- start = end;
- }
- if (start != layout->text)
- /* TODO: Write out the beginning excerpt of text? */
- g_warning ("Invalid UTF-8 string passed to pango_layout_set_text()");
- layout->n_chars = pango_utf8_strlen (layout->text, -1);
- layout_changed (layout);
- g_free (old_text);
- }
- /**
- * pango_layout_get_text:
- * @layout: a #PangoLayout
- *
- * Gets the text in the layout. The returned text should not
- * be freed or modified.
- *
- * Return value: the text in the @layout.
- **/
- const char*
- pango_layout_get_text (PangoLayout *layout)
- {
- g_return_val_if_fail (PANGO_IS_LAYOUT (layout), NULL);
- /* We don't ever want to return NULL as the text.
- */
- if (G_UNLIKELY (!layout->text))
- return "";
- return layout->text;
- }
- /**
- * pango_layout_get_character_count:
- * @layout: a #PangoLayout
- *
- * Returns the number of Unicode characters in the
- * the text of @layout.
- *
- * Return value: the number of Unicode characters
- * in the text of @layout
- *
- * Since: 1.30
- */
- gint
- pango_layout_get_character_count (PangoLayout *layout)
- {
- g_return_val_if_fail (PANGO_IS_LAYOUT (layout), 0);
- return layout->n_chars;
- }
- /**
- * pango_layout_set_markup:
- * @layout: a #PangoLayout
- * @markup: marked-up text
- * @length: length of marked-up text in bytes, or -1 if @markup is
- * null-terminated
- *
- * Same as pango_layout_set_markup_with_accel(), but
- * the markup text isn't scanned for accelerators.
- *
- **/
- void
- pango_layout_set_markup (PangoLayout *layout,
- const char *markup,
- int length)
- {
- pango_layout_set_markup_with_accel (layout, markup, length, 0, NULL);
- }
- /**
- * pango_layout_set_markup_with_accel:
- * @layout: a #PangoLayout
- * @markup: marked-up text
- * (see <link linkend="PangoMarkupFormat">markup format</link>)
- * @length: length of marked-up text in bytes, or -1 if @markup is
- * null-terminated
- * @accel_marker: marker for accelerators in the text
- * @accel_char: (out caller-allocates) (allow-none): return location
- * for first located accelerator, or %NULL
- *
- * Sets the layout text and attribute list from marked-up text (see
- * <link linkend="PangoMarkupFormat">markup format</link>). Replaces
- * the current text and attribute list.
- *
- * If @accel_marker is nonzero, the given character will mark the
- * character following it as an accelerator. For example, @accel_marker
- * might be an ampersand or underscore. All characters marked
- * as an accelerator will receive a %PANGO_UNDERLINE_LOW attribute,
- * and the first character so marked will be returned in @accel_char.
- * Two @accel_marker characters following each other produce a single
- * literal @accel_marker character.
- **/
- void
- pango_layout_set_markup_with_accel (PangoLayout *layout,
- const char *markup,
- int length,
- gunichar accel_marker,
- gunichar *accel_char)
- {
- PangoAttrList *list = NULL;
- char *text = NULL;
- GError *error;
- g_return_if_fail (PANGO_IS_LAYOUT (layout));
- g_return_if_fail (markup != NULL);
- error = NULL;
- if (!pango_parse_markup (markup, length,
- accel_marker,
- &list, &text,
- accel_char,
- &error))
- {
- g_warning ("pango_layout_set_markup_with_accel: %s", error->message);
- g_error_free (error);
- return;
- }
- pango_layout_set_text (layout, text, -1);
- pango_layout_set_attributes (layout, list);
- pango_attr_list_unref (list);
- g_free (text);
- }
- /**
- * pango_layout_get_unknown_glyphs_count:
- * @layout: a #PangoLayout
- *
- * Counts the number unknown glyphs in @layout. That is, zero if
- * glyphs for all characters in the layout text were found, or more
- * than zero otherwise.
- *
- * This function can be used to determine if there are any fonts
- * available to render all characters in a certain string, or when
- * used in combination with %PANGO_ATTR_FALLBACK, to check if a
- * certain font supports all the characters in the string.
- *
- * Return value: The number of unknown glyphs in @layout.
- *
- * Since: 1.16
- */
- int
- pango_layout_get_unknown_glyphs_count (PangoLayout *layout)
- {
- PangoLayoutLine *line;
- PangoLayoutRun *run;
- GSList *lines_list;
- GSList *runs_list;
- int i, count = 0;
- g_return_val_if_fail (PANGO_IS_LAYOUT (layout), 0);
- pango_layout_check_lines (layout);
- if (layout->unknown_glyphs_count >= 0)
- return layout->unknown_glyphs_count;
- lines_list = layout->lines;
- while (lines_list)
- {
- line = lines_list->data;
- runs_list = line->runs;
- while (runs_list)
- {
- run = runs_list->data;
- for (i = 0; i < run->glyphs->num_glyphs; i++)
- {
- if (run->glyphs->glyphs[i].glyph & PANGO_GLYPH_UNKNOWN_FLAG)
- count++;
- }
- runs_list = runs_list->next;
- }
- lines_list = lines_list->next;
- }
- layout->unknown_glyphs_count = count;
- return count;
- }
- static void
- check_context_changed (PangoLayout *layout)
- {
- guint 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
- *
- * Forces recomputation of any state in the #PangoLayout that
- * might depend on the layout's context. This function should
- * be called if you make changes to the context subsequent
- * to creating the layout.
- **/
- void
- pango_layout_context_changed (PangoLayout *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):
- * location to store a pointer to an array of logical attributes
- * This value must be freed with g_free().
- * @n_attrs: (out): location to store the number of the attributes in the
- * array. (The stored value will be one more than the total number
- * of characters in the layout, since there need to be attributes
- * corresponding to both the position before the first character
- * and the position after the last character.)
- *
- * Retrieves an array of logical attributes for each character in
- * the @layout.
- **/
- void
- pango_layout_get_log_attrs (PangoLayout *layout,
- PangoLogAttr **attrs,
- gint *n_attrs)
- {
- g_return_if_fail (layout != NULL);
- pango_layout_check_lines (layout);
- if (attrs)
- {
- *attrs = g_new (PangoLogAttr, layout->n_chars + 1);
- memcpy (*attrs, layout->log_attrs, sizeof(PangoLogAttr) * (layout->n_chars + 1));
- }
- if (n_attrs)
- *n_attrs = layout->n_chars + 1;
- }
- /**
- * pango_layout_get_log_attrs_readonly:
- * @layout: a #PangoLayout
- * @n_attrs: (out): location to store the number of the attributes in
- * the array
- *
- * Retrieves an array of logical attributes for each character in
- * the @layout.
- *
- * This is a faster alternative to pango_layout_get_log_attrs().
- * The returned array is part of @layout and must not be modified.
- * Modifying the layout will invalidate the returned array.
- *
- * The number of attributes returned in @n_attrs will be one more
- * than the total number of characters in the layout, since there
- * need to be attributes corresponding to both the position before
- * the first character and the position after the last character.
- *
- * Returns: (array length=n_attrs): an array of logical attributes
- *
- * Since: 1.30
- */
- const PangoLogAttr *
- pango_layout_get_log_attrs_readonly (PangoLayout *layout,
- gint *n_attrs)
- {
- if (n_attrs)
- *n_attrs = 0;
- g_return_val_if_fail (layout != NULL, NULL);
- pango_layout_check_lines (layout);
- if (n_attrs)
- *n_attrs = layout->n_chars + 1;
- return layout->log_attrs;
- }
- /**
- * pango_layout_get_line_count:
- * @layout: #PangoLayout
- *
- * Retrieves the count of lines for the @layout.
- *
- * Return value: the line count.
- **/
- int
- pango_layout_get_line_count (PangoLayout *layout)
- {
- g_return_val_if_fail (layout != NULL, 0);
- pango_layout_check_lines (layout);
- return layout->line_count;
- }
- /**
- * pango_layout_get_lines:
- * @layout: a #PangoLayout
- *
- * Returns the lines of the @layout as a list.
- *
- * Use the faster pango_layout_get_lines_readonly() if you do not plan
- * to modify the contents of the lines (glyphs, glyph widths, etc.).
- *
- * Return value: (element-type Pango.LayoutLine) (transfer none): a #GSList containing
- * the lines in the layout. This points to internal data of the #PangoLayout
- * and must be used with care. It will become invalid on any change to the layout's
- * text or properties.
- **/
- GSList *
- pango_layout_get_lines (PangoLayout *layout)
- {
- pango_layout_check_lines (layout);
- if (layout->lines)
- {
- GSList *tmp_list = layout->lines;
- while (tmp_list)
- {
- PangoLayoutLine *line = tmp_list->data;
- tmp_list = tmp_list->next;
- pango_layout_line_leaked (line);
- }
- }
- return layout->lines;
- }
- /**
- * pango_layout_get_lines_readonly:
- * @layout: a #PangoLayout
- *
- * Returns the lines of the @layout as a list.
- *
- * This is a faster alternative to pango_layout_get_lines(),
- * but the user is not expected
- * to modify the contents of the lines (glyphs, glyph widths, etc.).
- *
- * Return value: (element-type Pango.LayoutLine) (transfer none): a #GSList containing
- * the lines in the layout. This points to internal data of the #PangoLayout and
- * must be used with care. It will become invalid on any change to the layout's
- * text or properties. No changes should be made to the lines.
- *
- * Since: 1.16
- **/
- GSList *
- pango_layout_get_lines_readonly (PangoLayout *layout)
- {
- pango_layout_check_lines (layout);
- return layout->lines;
- }
- /**
- * pango_layout_get_line:
- * @layout: a #PangoLayout
- * @line: the index of a line, which must be between 0 and
- * <literal>pango_layout_get_line_count(layout) - 1</literal>, inclusive.
- *
- * Retrieves a particular line from a #PangoLayout.
- *
- * Use the faster pango_layout_get_line_readonly() if you do not plan
- * to modify the contents of the line (glyphs, glyph widths, etc.).
- *
- * Return value: (transfer none) (nullable): the requested
- * #PangoLayoutLine, or %NULL if the index is out of
- * range. This layout line can be ref'ed and retained,
- * but will become invalid if changes are made to the
- * #PangoLayout.
- **/
- PangoLayoutLine *
- pango_layout_get_line (PangoLayout *layout,
- int line)
- {
- GSList *list_item;
- g_return_val_if_fail (layout != NULL, NULL);
- if (line < 0)
- return NULL;
- pango_layout_check_lines (layout);
- list_item = g_slist_nth (layout->lines, line);
- if (list_item)
- {
- PangoLayoutLine *line = list_item->data;
- pango_layout_line_leaked (line);
- return line;
- }
- return NULL;
- }
- /**
- * pango_layout_get_line_readonly:
- * @layout: a #PangoLayout
- * @line: the index of a line, which must be between 0 and
- * <literal>pango_layout_get_line_count(layout) - 1</literal>, inclusive.
- *
- * Retrieves a particular line from a #PangoLayout.
- *
- * This is a faster alternative to pango_layout_get_line(),
- * but the user is not expected
- * to modify the contents of the line (glyphs, glyph widths, etc.).
- *
- * Return value: (transfer none) (nullable): the requested
- * #PangoLayoutLine, or %NULL if the index is out of
- * range. This layout line can be ref'ed and retained,
- * but will become invalid if changes are made to the
- * #PangoLayout. No changes should be made to the line.
- *
- * Since: 1.16
- **/
- PangoLayoutLine *
- pango_layout_get_line_readonly (PangoLayout *layout,
- int line)
- {
- GSList *list_item;
- g_return_val_if_fail (layout != NULL, NULL);
- if (line < 0)
- return NULL;
- pango_layout_check_lines (layout);
- list_item = g_slist_nth (layout->lines, line);
- if (list_item)
- {
- PangoLayoutLine *line = list_item->data;
- return line;
- }
- return NULL;
- }
- /**
- * pango_layout_line_index_to_x:
- * @line: a #PangoLayoutLine
- * @index_: byte offset of a grapheme within the layout
- * @trailing: an integer indicating the edge of the grapheme to retrieve
- * the position of. If > 0, the trailing edge of the grapheme,
- * if 0, the leading of the grapheme.
- * @x_pos: (out): location to store the x_offset (in Pango unit)
- *
- * Converts an index within a line to a X position.
- *
- **/
- void
- pango_layout_line_index_to_x (PangoLayoutLine *line,
- int index,
- int trailing,
- int *x_pos)
- {
- PangoLayout *layout = line->layout;
- GSList *run_list = line->runs;
- int width = 0;
- while (run_list)
- {
- PangoLayoutRun *run = run_list->data;
- ItemProperties properties;
- pango_layout_get_item_properties (run->item, &properties);
- if (run->item->offset <= index && run->item->offset + run->item->length > index)
- {
- int offset = g_utf8_pointer_to_offset (layout->text, layout->text + index);
- if (trailing)
- {
- while (index < line->start_index + line->length &&
- offset + 1 < layout->n_chars &&
- !layout->log_attrs[offset + 1].is_cursor_position)
- {
- offset++;
- index = g_utf8_next_char (layout->text + index) - layout->text;
- }
- }
- else
- {
- while (index > line->start_index &&
- !layout->log_attrs[offset].is_cursor_position)
- {
- offset--;
- index = g_utf8_prev_char (layout->text + index) - layout->text;
- }
- }
- pango_glyph_string_index_to_x (run->glyphs,
- layout->text + run->item->offset,
- run->item->length,
- &run->item->analysis,
- index - run->item->offset, trailing, x_pos);
- if (x_pos)
- *x_pos += width;
- return;
- }
- width += pango_glyph_string_get_width (run->glyphs);
- run_list = run_list->next;
- }
- if (x_pos)
- *x_pos = width;
- }
- static PangoLayoutLine *
- pango_layout_index_to_line (PangoLayout *layout,
- int index,
- int *line_nr,
- PangoLayoutLine **line_before,
- PangoLayoutLine **line_after)
- {
- GSList *tmp_list;
- GSList *line_list;
- PangoLayoutLine *line = NULL;
- PangoLayoutLine *prev_line = NULL;
- int i = -1;
- line_list = tmp_list = layout->lines;
- while (tmp_list)
- {
- PangoLayoutLine *tmp_line = tmp_list->data;
- if (tmp_line->start_index > index)
- break; /* index was in paragraph delimiters */
- prev_line = line;
- line = tmp_line;
- line_list = tmp_list;
- i++;
- if (line->start_index + line->length > index)
- break;
- tmp_list = tmp_list->next;
- }
- if (line_nr)
- *line_nr = i;
- if (line_before)
- *line_before = prev_line;
- if (line_after)
- *line_after = (line_list && line_list->next) ? line_list->next->data : NULL;
- return line;
- }
- static PangoLayoutLine *
- pango_layout_index_to_line_and_extents (PangoLayout *layout,
- int index,
- PangoRectangle *line_rect)
- {
- PangoLayoutIter iter;
- PangoLayoutLine *line = NULL;
- _pango_layout_get_iter (layout, &iter);
- if (!ITER_IS_INVALID (&iter))
- while (TRUE)
- {
- PangoLayoutLine *tmp_line = _pango_layout_iter_get_line (&iter);
- if (tmp_line->start_index > index)
- break; /* index was in paragraph delimiters */
- line = tmp_line;
- pango_layout_iter_get_line_extents (&iter, NULL, line_rect);
- if (line->start_index + line->length > index)
- break;
- if (!pango_layout_iter_next_line (&iter))
- break; /* Use end of last line */
- }
- _pango_layout_iter_destroy (&iter);
- return line;
- }
- /**
- * pango_layout_index_to_line_x:
- * @layout: a #PangoLayout
- * @index_: the byte index of a grapheme within the layout.
- * @trailing: an integer indicating the edge of the grapheme to retrieve the
- * position of. If > 0, the trailing edge of the grapheme, if 0,
- * the leading of the grapheme.
- * @line: (out) (allow-none): location to store resulting line index. (which will
- * between 0 and pango_layout_get_line_count(layout) - 1), or %NULL
- * @x_pos: (out) (allow-none): location to store resulting position within line
- * (%PANGO_SCALE units per device unit), or %NULL
- *
- * Converts from byte @index_ within the @layout to line and X position.
- * (X position is measured from the left edge of the line)
- */
- void
- pango_layout_index_to_line_x (PangoLayout *layout,
- int index,
- gboolean trailing,
- int *line,
- int *x_pos)
- {
- int line_num;
- PangoLayoutLine *layout_line = NULL;
- g_return_if_fail (layout != NULL);
- g_return_if_fail (index >= 0);
- g_return_if_fail (index <= layout->length);
- pango_layout_check_lines (layout);
- layout_line = pango_layout_index_to_line (layout, index,
- &line_num, NULL, NULL);
- if (layout_line)
- {
- /* use end of line if index was in the paragraph delimiters */
- if (index > layout_line->start_index + layout_line->length)
- index = layout_line->start_index + layout_line->length;
- if (line)
- *line = line_num;
- pango_layout_line_index_to_x (layout_line, index, trailing, x_pos);
- }
- else
- {
- if (line)
- *line = -1;
- if (x_pos)
- *x_pos = -1;
- }
- }
- /**
- * pango_layout_move_cursor_visually:
- * @layout: a #PangoLayout.
- * @strong: whether the moving cursor is the strong cursor or the
- * weak cursor. The strong cursor is the cursor corresponding
- * to text insertion in the base direction for the layout.
- * @old_index: the byte index of the grapheme for the old index
- * @old_trailing: if 0, the cursor was at the leading edge of the
- * grapheme indicated by @old_index, if > 0, the cursor
- * was at the trailing edge.
- * @direction: direction to move cursor. A negative
- * value indicates motion to the left.
- * @new_index: (out): location to store the new cursor byte index. A value of -1
- * indicates that the cursor has been moved off the beginning
- * of the layout. A value of %G_MAXINT indicates that
- * the cursor has been moved off the end of the layout.
- * @new_trailing: (out): number of characters to move forward from the
- * location returned for @new_index to get the position
- * where the cursor should be displayed. This allows
- * distinguishing the position at the beginning of one
- * line from the position at the end of the preceding
- * line. @new_index is always on the line where the
- * cursor should be displayed.
- *
- * Computes a new cursor position from an old position and
- * a count of positions to move visually. If @direction is positive,
- * then the new strong cursor position will be one position
- * to the right of the old cursor position. If @direction is negative,
- * then the new strong cursor position will be one position
- * to the left of the old cursor position.
- *
- * In the presence of bidirectional text, the correspondence
- * between logical and visual order will depend on the direction
- * of the current run, and there may be jumps when the cursor
- * is moved off of the end of a run.
- *
- * Motion here is in cursor positions, not in characters, so a
- * single call to pango_layout_move_cursor_visually() may move the
- * cursor over multiple characters when multiple characters combine
- * to form a single grapheme.
- **/
- void
- pango_layout_move_cursor_visually (PangoLayout *layout,
- gboolean strong,
- int old_index,
- int old_trailing,
- int direction,
- int *new_index,
- int *new_trailing)
- {
- PangoLayoutLine *line = NULL;
- PangoLayoutLine *prev_line;
- PangoLayoutLine *next_line;
- int *log2vis_map;
- int *vis2log_map;
- int n_vis;
- int vis_pos, vis_pos_old, log_pos;
- int start_offset;
- gboolean off_start = FALSE;
- gboolean off_end = FALSE;
- g_return_if_fail (layout != NULL);
- g_return_if_fail (old_index >= 0 && old_index <= layout->length);
- g_return_if_fail (old_index < layout->length || old_trailing == 0);
- g_return_if_fail (new_index != NULL);
- g_return_if_fail (new_trailing != NULL);
- direction = (direction >= 0 ? 1 : -1);
- pango_layout_check_lines (layout);
- /* Find the line the old cursor is on */
- line = pango_layout_index_to_line (layout, old_index,
- NULL, &prev…
Large files files are truncated, but you can click here to view the full file