summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2021-08-20 17:35:41 +0000
committerMatthias Clasen <mclasen@redhat.com>2021-08-20 17:35:41 +0000
commite756543935d415939e358d6d7cec094f7cd310a7 (patch)
tree6ca739b4439047fe0de0c16d38c6627a6d4feeee
parentdf6d8df3242d3e139df99dcccecf7ca9bbeed95d (diff)
parent5d36fc27baad02cf773ff9af1fb46cdc97c7788b (diff)
downloadpango-e756543935d415939e358d6d7cec094f7cd310a7.tar.gz
Merge branch 'code-reorg' into 'main'
Cosmetics: Clean up pango-context.h See merge request GNOME/pango!418
-rw-r--r--pango/break.c105
-rw-r--r--pango/itemize.c1151
-rw-r--r--pango/meson.build4
-rw-r--r--pango/pango-attributes-private.h2
-rw-r--r--pango/pango-attributes.c1041
-rw-r--r--pango/pango-attributes.h500
-rw-r--r--pango/pango-break.h57
-rw-r--r--pango/pango-color.h75
-rw-r--r--pango/pango-context-private.h63
-rw-r--r--pango/pango-context.c1153
-rw-r--r--pango/pango-context.h108
-rw-r--r--pango/pango-fontmap.h2
-rw-r--r--pango/pango-glyph.h129
-rw-r--r--pango/pango-item.h45
-rw-r--r--pango/pango-language.h41
-rw-r--r--pango/pango-markup.c2
-rw-r--r--pango/pango-markup.h52
-rw-r--r--pango/pango-types.h2
-rw-r--r--pango/pango-utils.c102
-rw-r--r--pango/pango-utils.h6
-rw-r--r--pango/pango.h3
-rw-r--r--pango/pangofc-shape.c425
-rw-r--r--pango/reorder-items.c11
-rw-r--r--pango/shape.c577
24 files changed, 2911 insertions, 2745 deletions
diff --git a/pango/break.c b/pango/break.c
index 9690d510..9eb4a291 100644
--- a/pango/break.c
+++ b/pango/break.c
@@ -30,7 +30,6 @@
#include <string.h>
#define PARAGRAPH_SEPARATOR 0x2029
-#define PARAGRAPH_SEPARATOR_STRING "\xE2\x80\xA9"
/* See http://www.unicode.org/unicode/reports/tr14/ if you hope
* to understand the line breaking code.
@@ -1655,110 +1654,6 @@ pango_break (const gchar *text,
}
/**
- * pango_find_paragraph_boundary:
- * @text: UTF-8 text
- * @length: length of @text in bytes, or -1 if nul-terminated
- * @paragraph_delimiter_index: (out): return location for index of
- * delimiter
- * @next_paragraph_start: (out): return location for start of next
- * paragraph
- *
- * Locates a paragraph boundary in @text.
- *
- * A boundary is caused by delimiter characters, such as
- * a newline, carriage return, carriage return-newline pair,
- * or Unicode paragraph separator character.
- *
- * The index of the run of delimiters is returned in
- * @paragraph_delimiter_index. The index of the start
- * of the paragrap (index after all delimiters) is stored
- * in @next_paragraph_start.
- *
- * If no delimiters are found, both @paragraph_delimiter_index
- * and @next_paragraph_start are filled with the length of @text
- * (an index one off the end).
- */
-void
-pango_find_paragraph_boundary (const gchar *text,
- gint length,
- gint *paragraph_delimiter_index,
- gint *next_paragraph_start)
-{
- const gchar *p = text;
- const gchar *end;
- const gchar *start = NULL;
- const gchar *delimiter = NULL;
-
- /* Only one character has type G_UNICODE_PARAGRAPH_SEPARATOR in
- * Unicode 5.0; update the following code if that changes.
- */
-
- /* prev_sep is the first byte of the previous separator. Since
- * the valid separators are \r, \n, and PARAGRAPH_SEPARATOR, the
- * first byte is enough to identify it.
- */
- gchar prev_sep;
-
-
- if (length < 0)
- length = strlen (text);
-
- end = text + length;
-
- if (paragraph_delimiter_index)
- *paragraph_delimiter_index = length;
-
- if (next_paragraph_start)
- *next_paragraph_start = length;
-
- if (length == 0)
- return;
-
- prev_sep = 0;
-
- while (p < end)
- {
- if (prev_sep == '\n' ||
- prev_sep == PARAGRAPH_SEPARATOR_STRING[0])
- {
- g_assert (delimiter);
- start = p;
- break;
- }
- else if (prev_sep == '\r')
- {
- /* don't break between \r and \n */
- if (*p != '\n')
- {
- g_assert (delimiter);
- start = p;
- break;
- }
- }
-
- if (*p == '\n' ||
- *p == '\r' ||
- !strncmp(p, PARAGRAPH_SEPARATOR_STRING,
- strlen(PARAGRAPH_SEPARATOR_STRING)))
- {
- if (delimiter == NULL)
- delimiter = p;
- prev_sep = *p;
- }
- else
- prev_sep = 0;
-
- p = g_utf8_next_char (p);
- }
-
- if (delimiter && paragraph_delimiter_index)
- *paragraph_delimiter_index = delimiter - text;
-
- if (start && next_paragraph_start)
- *next_paragraph_start = start - text;
-}
-
-/**
* pango_tailor_break:
* @text: text to process. Must be valid UTF-8
* @length: length in bytes of @text
diff --git a/pango/itemize.c b/pango/itemize.c
new file mode 100644
index 00000000..27a9865d
--- /dev/null
+++ b/pango/itemize.c
@@ -0,0 +1,1151 @@
+/* Pango
+ * itemize.c: Turning text into items
+ *
+ * Copyright (C) 2000, 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.
+ */
+
+#include "config.h"
+#include <string.h>
+#include <stdlib.h>
+
+#include "pango-context-private.h"
+#include "pango-impl-utils.h"
+
+#include "pango-font-private.h"
+#include "pango-fontset-private.h"
+#include "pango-fontmap-private.h"
+#include "pango-script-private.h"
+#include "pango-emoji-private.h"
+#include "pango-attributes-private.h"
+
+
+/* {{{ Font cache */
+
+/*
+ * We cache the results of character,fontset => font in a hash table
+ */
+
+typedef struct {
+ GHashTable *hash;
+} FontCache;
+
+typedef struct {
+ PangoFont *font;
+ int position; /* position of the font in the fontset */
+} FontElement;
+
+static void
+font_cache_destroy (FontCache *cache)
+{
+ g_hash_table_destroy (cache->hash);
+ g_slice_free (FontCache, cache);
+}
+
+static void
+font_element_destroy (FontElement *element)
+{
+ if (element->font)
+ g_object_unref (element->font);
+ g_slice_free (FontElement, element);
+}
+
+static FontCache *
+get_font_cache (PangoFontset *fontset)
+{
+ FontCache *cache;
+
+ static GQuark cache_quark = 0; /* MT-safe */
+ if (G_UNLIKELY (!cache_quark))
+ cache_quark = g_quark_from_static_string ("pango-font-cache");
+
+retry:
+ cache = g_object_get_qdata (G_OBJECT (fontset), cache_quark);
+ if (G_UNLIKELY (!cache))
+ {
+ cache = g_slice_new (FontCache);
+ cache->hash = g_hash_table_new_full (g_direct_hash, NULL,
+ NULL, (GDestroyNotify)font_element_destroy);
+ if (!g_object_replace_qdata (G_OBJECT (fontset), cache_quark, NULL,
+ cache, (GDestroyNotify)font_cache_destroy,
+ NULL))
+ {
+ font_cache_destroy (cache);
+ goto retry;
+ }
+ }
+
+ return cache;
+}
+
+static gboolean
+font_cache_get (FontCache *cache,
+ gunichar wc,
+ PangoFont **font,
+ int *position)
+{
+ FontElement *element;
+
+ element = g_hash_table_lookup (cache->hash, GUINT_TO_POINTER (wc));
+ if (element)
+ {
+ *font = element->font;
+ *position = element->position;
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+static void
+font_cache_insert (FontCache *cache,
+ gunichar wc,
+ PangoFont *font,
+ int position)
+{
+ FontElement *element = g_slice_new (FontElement);
+ element->font = font ? g_object_ref (font) : NULL;
+ element->position = position;
+
+ g_hash_table_insert (cache->hash, GUINT_TO_POINTER (wc), element);
+}
+
+/* }}} */
+/* {{{ Width Iter */
+
+typedef struct _PangoWidthIter PangoWidthIter;
+
+struct _PangoWidthIter
+{
+ const gchar *text_start;
+ const gchar *text_end;
+ const gchar *start;
+ const gchar *end;
+ gboolean upright;
+};
+
+static gboolean
+width_iter_is_upright (gunichar ch)
+{
+ /* https://www.unicode.org/Public/11.0.0/ucd/VerticalOrientation.txt
+ * VO=U or Tu table generated by tools/gen-vertical-orientation-U-table.py.
+ *
+ * FIXME: In the future, If GLib supports VerticalOrientation, please use it.
+ */
+ static const gunichar upright[][2] = {
+ {0x00A7, 0x00A7}, {0x00A9, 0x00A9}, {0x00AE, 0x00AE}, {0x00B1, 0x00B1},
+ {0x00BC, 0x00BE}, {0x00D7, 0x00D7}, {0x00F7, 0x00F7}, {0x02EA, 0x02EB},
+ {0x1100, 0x11FF}, {0x1401, 0x167F}, {0x18B0, 0x18FF}, {0x2016, 0x2016},
+ {0x2020, 0x2021}, {0x2030, 0x2031}, {0x203B, 0x203C}, {0x2042, 0x2042},
+ {0x2047, 0x2049}, {0x2051, 0x2051}, {0x2065, 0x2065}, {0x20DD, 0x20E0},
+ {0x20E2, 0x20E4}, {0x2100, 0x2101}, {0x2103, 0x2109}, {0x210F, 0x210F},
+ {0x2113, 0x2114}, {0x2116, 0x2117}, {0x211E, 0x2123}, {0x2125, 0x2125},
+ {0x2127, 0x2127}, {0x2129, 0x2129}, {0x212E, 0x212E}, {0x2135, 0x213F},
+ {0x2145, 0x214A}, {0x214C, 0x214D}, {0x214F, 0x2189}, {0x218C, 0x218F},
+ {0x221E, 0x221E}, {0x2234, 0x2235}, {0x2300, 0x2307}, {0x230C, 0x231F},
+ {0x2324, 0x2328}, {0x232B, 0x232B}, {0x237D, 0x239A}, {0x23BE, 0x23CD},
+ {0x23CF, 0x23CF}, {0x23D1, 0x23DB}, {0x23E2, 0x2422}, {0x2424, 0x24FF},
+ {0x25A0, 0x2619}, {0x2620, 0x2767}, {0x2776, 0x2793}, {0x2B12, 0x2B2F},
+ {0x2B50, 0x2B59}, {0x2BB8, 0x2BD1}, {0x2BD3, 0x2BEB}, {0x2BF0, 0x2BFF},
+ {0x2E80, 0x3007}, {0x3012, 0x3013}, {0x3020, 0x302F}, {0x3031, 0x309F},
+ {0x30A1, 0x30FB}, {0x30FD, 0xA4CF}, {0xA960, 0xA97F}, {0xAC00, 0xD7FF},
+ {0xE000, 0xFAFF}, {0xFE10, 0xFE1F}, {0xFE30, 0xFE48}, {0xFE50, 0xFE57},
+ {0xFE5F, 0xFE62}, {0xFE67, 0xFE6F}, {0xFF01, 0xFF07}, {0xFF0A, 0xFF0C},
+ {0xFF0E, 0xFF19}, {0xFF1F, 0xFF3A}, {0xFF3C, 0xFF3C}, {0xFF3E, 0xFF3E},
+ {0xFF40, 0xFF5A}, {0xFFE0, 0xFFE2}, {0xFFE4, 0xFFE7}, {0xFFF0, 0xFFF8},
+ {0xFFFC, 0xFFFD}, {0x10980, 0x1099F}, {0x11580, 0x115FF}, {0x11A00, 0x11AAF},
+ {0x13000, 0x1342F}, {0x14400, 0x1467F}, {0x16FE0, 0x18AFF}, {0x1B000, 0x1B12F},
+ {0x1B170, 0x1B2FF}, {0x1D000, 0x1D1FF}, {0x1D2E0, 0x1D37F}, {0x1D800, 0x1DAAF},
+ {0x1F000, 0x1F7FF}, {0x1F900, 0x1FA6F}, {0x20000, 0x2FFFD}, {0x30000, 0x3FFFD},
+ {0xF0000, 0xFFFFD}, {0x100000, 0x10FFFD}
+ };
+ static const int max = sizeof(upright) / sizeof(upright[0]);
+ int st = 0;
+ int ed = max;
+
+ if (ch < upright[0][0])
+ return FALSE;
+
+ while (st <= ed)
+ {
+ int mid = (st + ed) / 2;
+ if (upright[mid][0] <= ch && ch <= upright[mid][1])
+ return TRUE;
+ else
+ if (upright[mid][0] <= ch)
+ st = mid + 1;
+ else
+ ed = mid - 1;
+ }
+
+ return FALSE;
+}
+
+static void
+width_iter_next (PangoWidthIter *iter)
+{
+ gboolean met_joiner = FALSE;
+ iter->start = iter->end;
+
+ if (iter->end < iter->text_end)
+ {
+ gunichar ch = g_utf8_get_char (iter->end);
+ iter->upright = width_iter_is_upright (ch);
+ }
+
+ while (iter->end < iter->text_end)
+ {
+ gunichar ch = g_utf8_get_char (iter->end);
+
+ /* for zero width joiner */
+ if (ch == 0x200D)
+ {
+ iter->end = g_utf8_next_char (iter->end);
+ met_joiner = TRUE;
+ continue;
+ }
+
+ /* ignore the upright check if met joiner */
+ if (met_joiner)
+ {
+ iter->end = g_utf8_next_char (iter->end);
+ met_joiner = FALSE;
+ continue;
+ }
+
+ /* for variation selector, tag and emoji modifier. */
+ if (G_UNLIKELY (ch == 0xFE0EU || ch == 0xFE0FU ||
+ (ch >= 0xE0020 && ch <= 0xE007F) ||
+ (ch >= 0x1F3FB && ch <= 0x1F3FF)))
+ {
+ iter->end = g_utf8_next_char (iter->end);
+ continue;
+ }
+
+ if (width_iter_is_upright (ch) != iter->upright)
+ break;
+
+ iter->end = g_utf8_next_char (iter->end);
+ }
+}
+
+static void
+width_iter_init (PangoWidthIter *iter,
+ const char *text,
+ int length)
+{
+ iter->text_start = text;
+ iter->text_end = text + length;
+ iter->start = iter->end = text;
+
+ width_iter_next (iter);
+}
+
+static void
+width_iter_fini (PangoWidthIter *iter)
+{
+}
+
+/* }}} */
+/* {{{ Itemization */
+
+typedef struct _ItemizeState ItemizeState;
+
+
+typedef enum {
+ EMBEDDING_CHANGED = 1 << 0,
+ SCRIPT_CHANGED = 1 << 1,
+ LANG_CHANGED = 1 << 2,
+ FONT_CHANGED = 1 << 3,
+ DERIVED_LANG_CHANGED = 1 << 4,
+ WIDTH_CHANGED = 1 << 5,
+ EMOJI_CHANGED = 1 << 6,
+} ChangedFlags;
+
+
+struct _ItemizeState
+{
+ PangoContext *context;
+ const char *text;
+ const char *end;
+
+ const char *run_start;
+ const char *run_end;
+
+ GList *result;
+ PangoItem *item;
+
+ guint8 *embedding_levels;
+ int embedding_end_offset;
+ const char *embedding_end;
+ guint8 embedding;
+
+ PangoGravity gravity;
+ PangoGravityHint gravity_hint;
+ PangoGravity resolved_gravity;
+ PangoGravity font_desc_gravity;
+ gboolean centered_baseline;
+
+ PangoAttrIterator *attr_iter;
+ gboolean free_attr_iter;
+ const char *attr_end;
+ PangoFontDescription *font_desc;
+ PangoFontDescription *emoji_font_desc;
+ PangoLanguage *lang;
+ GSList *extra_attrs;
+ gboolean copy_extra_attrs;
+
+ ChangedFlags changed;
+
+ PangoScriptIter script_iter;
+ const char *script_end;
+ PangoScript script;
+
+ PangoWidthIter width_iter;
+ PangoEmojiIter emoji_iter;
+
+ PangoLanguage *derived_lang;
+
+ PangoFontset *current_fonts;
+ FontCache *cache;
+ PangoFont *base_font;
+ gboolean enable_fallback;
+
+ const char *first_space; /* first of a sequence of spaces we've seen */
+ int font_position; /* position of the current font in the fontset */
+};
+
+static void
+update_embedding_end (ItemizeState *state)
+{
+ state->embedding = state->embedding_levels[state->embedding_end_offset];
+ while (state->embedding_end < state->end &&
+ state->embedding_levels[state->embedding_end_offset] == state->embedding)
+ {
+ state->embedding_end_offset++;
+ state->embedding_end = g_utf8_next_char (state->embedding_end);
+ }
+
+ state->changed |= EMBEDDING_CHANGED;
+}
+
+static PangoAttribute *
+find_attribute (GSList *attr_list,
+ PangoAttrType type)
+{
+ GSList *node;
+
+ for (node = attr_list; node; node = node->next)
+ if (((PangoAttribute *) node->data)->klass->type == type)
+ return (PangoAttribute *) node->data;
+
+ return NULL;
+}
+
+static void
+update_attr_iterator (ItemizeState *state)
+{
+ PangoLanguage *old_lang;
+ PangoAttribute *attr;
+ int end_index;
+
+ pango_attr_iterator_range (state->attr_iter, NULL, &end_index);
+ if (end_index < state->end - state->text)
+ state->attr_end = state->text + end_index;
+ else
+ state->attr_end = state->end;
+
+ if (state->emoji_font_desc)
+ {
+ pango_font_description_free (state->emoji_font_desc);
+ state->emoji_font_desc = NULL;
+ }
+
+ old_lang = state->lang;
+ if (state->font_desc)
+ pango_font_description_free (state->font_desc);
+ state->font_desc = pango_font_description_copy_static (state->context->font_desc);
+ pango_attr_iterator_get_font (state->attr_iter, state->font_desc,
+ &state->lang, &state->extra_attrs);
+ if (pango_font_description_get_set_fields (state->font_desc) & PANGO_FONT_MASK_GRAVITY)
+ state->font_desc_gravity = pango_font_description_get_gravity (state->font_desc);
+ else
+ state->font_desc_gravity = PANGO_GRAVITY_AUTO;
+
+ state->copy_extra_attrs = FALSE;
+
+ if (!state->lang)
+ state->lang = state->context->language;
+
+ attr = find_attribute (state->extra_attrs, PANGO_ATTR_FALLBACK);
+ state->enable_fallback = (attr == NULL || ((PangoAttrInt *)attr)->value);
+
+ attr = find_attribute (state->extra_attrs, PANGO_ATTR_GRAVITY);
+ state->gravity = attr == NULL ? PANGO_GRAVITY_AUTO : ((PangoAttrInt *)attr)->value;
+
+ attr = find_attribute (state->extra_attrs, PANGO_ATTR_GRAVITY_HINT);
+ state->gravity_hint = attr == NULL ? state->context->gravity_hint : (PangoGravityHint)((PangoAttrInt *)attr)->value;
+
+ state->changed |= FONT_CHANGED;
+ if (state->lang != old_lang)
+ state->changed |= LANG_CHANGED;
+}
+
+static void
+update_end (ItemizeState *state)
+{
+ state->run_end = state->embedding_end;
+ if (state->attr_end < state->run_end)
+ state->run_end = state->attr_end;
+ if (state->script_end < state->run_end)
+ state->run_end = state->script_end;
+ if (state->width_iter.end < state->run_end)
+ state->run_end = state->width_iter.end;
+ if (state->emoji_iter.end < state->run_end)
+ state->run_end = state->emoji_iter.end;
+}
+
+
+static void
+itemize_state_init (ItemizeState *state,
+ PangoContext *context,
+ const char *text,
+ PangoDirection base_dir,
+ int start_index,
+ int length,
+ PangoAttrList *attrs,
+ PangoAttrIterator *cached_iter,
+ const PangoFontDescription *desc)
+{
+ state->context = context;
+ state->text = text;
+ state->end = text + start_index + length;
+
+ state->result = NULL;
+ state->item = NULL;
+
+ state->run_start = text + start_index;
+ state->changed = EMBEDDING_CHANGED | SCRIPT_CHANGED | LANG_CHANGED |
+ FONT_CHANGED | WIDTH_CHANGED | EMOJI_CHANGED;
+
+ /* First, apply the bidirectional algorithm to break
+ * the text into directional runs.
+ */
+ state->embedding_levels = pango_log2vis_get_embedding_levels (text + start_index, length, &base_dir);
+
+ state->embedding_end_offset = 0;
+ state->embedding_end = text + start_index;
+ update_embedding_end (state);
+
+ state->gravity = PANGO_GRAVITY_AUTO;
+ state->centered_baseline = PANGO_GRAVITY_IS_VERTICAL (state->context->resolved_gravity);
+ state->gravity_hint = state->context->gravity_hint;
+ state->resolved_gravity = PANGO_GRAVITY_AUTO;
+
+ /* Initialize the attribute iterator
+ */
+ if (cached_iter)
+ {
+ state->attr_iter = cached_iter;
+ state->free_attr_iter = FALSE;
+ }
+ else if (attrs)
+ {
+ state->attr_iter = pango_attr_list_get_iterator (attrs);
+ state->free_attr_iter = TRUE;
+ }
+ else
+ {
+ state->attr_iter = NULL;
+ state->free_attr_iter = FALSE;
+ }
+
+ state->emoji_font_desc = NULL;
+ if (state->attr_iter)
+ {
+ state->font_desc = NULL;
+ state->lang = NULL;
+
+ pango_attr_iterator_advance (state->attr_iter, start_index);
+ update_attr_iterator (state);
+ }
+ else
+ {
+ state->font_desc = pango_font_description_copy_static (desc ? desc : state->context->font_desc);
+ state->lang = state->context->language;
+ state->extra_attrs = NULL;
+ state->copy_extra_attrs = FALSE;
+
+ state->attr_end = state->end;
+ state->enable_fallback = TRUE;
+ }
+
+ /* Initialize the script iterator
+ */
+ _pango_script_iter_init (&state->script_iter, text + start_index, length);
+ pango_script_iter_get_range (&state->script_iter, NULL,
+ &state->script_end, &state->script);
+
+ width_iter_init (&state->width_iter, text + start_index, length);
+ _pango_emoji_iter_init (&state->emoji_iter, text + start_index, length);
+
+ if (!PANGO_GRAVITY_IS_VERTICAL (state->context->resolved_gravity))
+ state->width_iter.end = state->end;
+ else
+ if (state->emoji_iter.is_emoji)
+ state->width_iter.end = MAX (state->width_iter.end, state->emoji_iter.end);
+
+ update_end (state);
+
+ if (pango_font_description_get_set_fields (state->font_desc) & PANGO_FONT_MASK_GRAVITY)
+ state->font_desc_gravity = pango_font_description_get_gravity (state->font_desc);
+ else
+ state->font_desc_gravity = PANGO_GRAVITY_AUTO;
+
+ state->derived_lang = NULL;
+ state->current_fonts = NULL;
+ state->cache = NULL;
+ state->base_font = NULL;
+ state->first_space = NULL;
+ state->font_position = 0xffff;
+}
+
+static gboolean
+itemize_state_next (ItemizeState *state)
+{
+ if (state->run_end == state->end)
+ return FALSE;
+
+ state->changed = 0;
+
+ state->run_start = state->run_end;
+
+ if (state->run_end == state->embedding_end)
+ {
+ update_embedding_end (state);
+ }
+
+ if (state->run_end == state->attr_end)
+ {
+ pango_attr_iterator_next (state->attr_iter);
+ update_attr_iterator (state);
+ }
+
+ if (state->run_end == state->script_end)
+ {
+ pango_script_iter_next (&state->script_iter);
+ pango_script_iter_get_range (&state->script_iter, NULL,
+ &state->script_end, &state->script);
+ state->changed |= SCRIPT_CHANGED;
+ }
+ if (state->run_end == state->emoji_iter.end)
+ {
+ _pango_emoji_iter_next (&state->emoji_iter);
+ state->changed |= EMOJI_CHANGED;
+
+ if (state->emoji_iter.is_emoji)
+ state->width_iter.end = MAX (state->width_iter.end, state->emoji_iter.end);
+ }
+ if (state->run_end == state->width_iter.end)
+ {
+ width_iter_next (&state->width_iter);
+ state->changed |= WIDTH_CHANGED;
+ }
+
+ update_end (state);
+
+ return TRUE;
+}
+
+static GSList *
+copy_attr_slist (GSList *attr_slist)
+{
+ GSList *new_list = NULL;
+ GSList *l;
+
+ for (l = attr_slist; l; l = l->next)
+ new_list = g_slist_prepend (new_list, pango_attribute_copy (l->data));
+
+ return g_slist_reverse (new_list);
+}
+
+static void
+itemize_state_fill_font (ItemizeState *state,
+ PangoFont *font)
+{
+ GList *l;
+
+ for (l = state->result; l; l = l->next)
+ {
+ PangoItem *item = l->data;
+ if (item->analysis.font)
+ break;
+ if (font)
+ item->analysis.font = g_object_ref (font);
+ }
+}
+
+static void
+itemize_state_add_character (ItemizeState *state,
+ PangoFont *font,
+ int font_position,
+ gboolean force_break,
+ const char *pos,
+ gboolean is_space)
+{
+ const char *first_space = state->first_space;
+ int n_spaces = 0;
+
+ if (is_space)
+ {
+ if (state->first_space == NULL)
+ state->first_space = pos;
+ }
+ else
+ state->first_space = NULL;
+
+ if (state->item)
+ {
+ if (!state->item->analysis.font && font)
+ {
+ itemize_state_fill_font (state, font);
+ state->font_position = font_position;
+ }
+ else if (state->item->analysis.font && !font)
+ {
+ font = state->item->analysis.font;
+ font_position = state->font_position;
+ }
+
+ if (!force_break &&
+ state->item->analysis.font == font)
+ {
+ state->item->num_chars++;
+ return;
+ }
+
+ /* Font is changing, we are about to end the current item.
+ * If it ended in a sequence of spaces (but wasn't only spaces),
+ * check if we should move those spaces to the new item (since
+ * the font is less "fallback".
+ *
+ * See https://gitlab.gnome.org/GNOME/pango/-/issues/249
+ */
+ if (state->text + state->item->offset < first_space &&
+ font_position < state->font_position)
+ {
+ n_spaces = g_utf8_strlen (first_space, pos - first_space);
+ state->item->num_chars -= n_spaces;
+ pos = first_space;
+ }
+
+ state->item->length = (pos - state->text) - state->item->offset;
+ }
+
+ state->item = pango_item_new ();
+ state->item->offset = pos - state->text;
+ state->item->length = 0;
+ state->item->num_chars = n_spaces + 1;
+
+ if (font)
+ g_object_ref (font);
+ state->item->analysis.font = font;
+ state->font_position = font_position;
+
+ state->item->analysis.level = state->embedding;
+ state->item->analysis.gravity = state->resolved_gravity;
+
+ /* The level vs. gravity dance:
+ * - If gravity is SOUTH, leave level untouched.
+ * - If gravity is NORTH, step level one up, to
+ * not get mirrored upside-down text.
+ * - If gravity is EAST, step up to an even level, as
+ * it's a clockwise-rotated layout, so the rotated
+ * top is unrotated left.
+ * - If gravity is WEST, step up to an odd level, as
+ * it's a counter-clockwise-rotated layout, so the rotated
+ * top is unrotated right.
+ *
+ * A similar dance is performed in pango-layout.c:
+ * line_set_resolved_dir(). Keep in synch.
+ */
+ switch (state->item->analysis.gravity)
+ {
+ case PANGO_GRAVITY_SOUTH:
+ default:
+ break;
+ case PANGO_GRAVITY_NORTH:
+ state->item->analysis.level++;
+ break;
+ case PANGO_GRAVITY_EAST:
+ state->item->analysis.level += 1;
+ state->item->analysis.level &= ~1;
+ break;
+ case PANGO_GRAVITY_WEST:
+ state->item->analysis.level |= 1;
+ break;
+ }
+
+ state->item->analysis.flags = state->centered_baseline ? PANGO_ANALYSIS_FLAG_CENTERED_BASELINE : 0;
+
+ state->item->analysis.script = state->script;
+ state->item->analysis.language = state->derived_lang;
+
+ if (state->copy_extra_attrs)
+ {
+ state->item->analysis.extra_attrs = copy_attr_slist (state->extra_attrs);
+ }
+ else
+ {
+ state->item->analysis.extra_attrs = state->extra_attrs;
+ state->copy_extra_attrs = TRUE;
+ }
+
+ state->result = g_list_prepend (state->result, state->item);
+}
+
+typedef struct {
+ PangoLanguage *lang;
+ gunichar wc;
+ PangoFont *font;
+ int position;
+} GetFontInfo;
+
+static gboolean
+get_font_foreach (PangoFontset *fontset,
+ PangoFont *font,
+ gpointer data)
+{
+ GetFontInfo *info = data;
+
+ if (G_UNLIKELY (!font))
+ return FALSE;
+
+ if (pango_font_has_char (font, info->wc))
+ {
+ info->font = font;
+ return TRUE;
+ }
+
+ if (!fontset)
+ {
+ info->font = font;
+ return TRUE;
+ }
+
+ info->position++;
+
+ return FALSE;
+}
+
+static PangoFont *
+get_base_font (ItemizeState *state)
+{
+ if (!state->base_font)
+ state->base_font = pango_font_map_load_font (state->context->font_map,
+ state->context,
+ state->font_desc);
+ return state->base_font;
+}
+
+static gboolean
+get_font (ItemizeState *state,
+ gunichar wc,
+ PangoFont **font,
+ int *position)
+{
+ GetFontInfo info;
+
+ /* We'd need a separate cache when fallback is disabled, but since lookup
+ * with fallback disabled is faster anyways, we just skip caching */
+ if (state->enable_fallback && font_cache_get (state->cache, wc, font, position))
+ return TRUE;
+
+ info.lang = state->derived_lang;
+ info.wc = wc;
+ info.font = NULL;
+ info.position = 0;
+
+ if (state->enable_fallback)
+ pango_fontset_foreach (state->current_fonts, get_font_foreach, &info);
+ else
+ get_font_foreach (NULL, get_base_font (state), &info);
+
+ *font = info.font;
+ *position = info.position;
+
+ /* skip caching if fallback disabled (see above) */
+ if (state->enable_fallback)
+ font_cache_insert (state->cache, wc, *font, *position);
+
+ return TRUE;
+}
+
+static PangoLanguage *
+compute_derived_language (PangoLanguage *lang,
+ PangoScript script)
+{
+ PangoLanguage *derived_lang;
+
+ /* Make sure the language tag is consistent with the derived
+ * script. There is no point in marking up a section of
+ * Arabic text with the "en" language tag.
+ */
+ if (lang && pango_language_includes_script (lang, script))
+ derived_lang = lang;
+ else
+ {
+ derived_lang = pango_script_get_sample_language (script);
+ /* If we don't find a sample language for the script, we
+ * use a language tag that shouldn't actually be used
+ * anywhere. This keeps fontconfig (for the PangoFc*
+ * backend) from using the language tag to affect the
+ * sort order. I don't have a reference for 'xx' being
+ * safe here, though Keith Packard claims it is.
+ */
+ if (!derived_lang)
+ derived_lang = pango_language_from_string ("xx");
+ }
+
+ return derived_lang;
+}
+
+static void
+itemize_state_update_for_new_run (ItemizeState *state)
+{
+ /* This block should be moved to update_attr_iterator, but I'm too lazy to
+ * do it right now */
+ if (state->changed & (FONT_CHANGED | SCRIPT_CHANGED | WIDTH_CHANGED))
+ {
+ /* Font-desc gravity overrides everything */
+ if (state->font_desc_gravity != PANGO_GRAVITY_AUTO)
+ {
+ state->resolved_gravity = state->font_desc_gravity;
+ }
+ else
+ {
+ PangoGravity gravity = state->gravity;
+ PangoGravityHint gravity_hint = state->gravity_hint;
+
+ if (G_LIKELY (gravity == PANGO_GRAVITY_AUTO))
+ gravity = state->context->resolved_gravity;
+
+ state->resolved_gravity = pango_gravity_get_for_script_and_width (state->script,
+ state->width_iter.upright,
+ gravity,
+ gravity_hint);
+ }
+
+ if (state->font_desc_gravity != state->resolved_gravity)
+ {
+ pango_font_description_set_gravity (state->font_desc, state->resolved_gravity);
+ state->changed |= FONT_CHANGED;
+ }
+ }
+
+ if (state->changed & (SCRIPT_CHANGED | LANG_CHANGED))
+ {
+ PangoLanguage *old_derived_lang = state->derived_lang;
+ state->derived_lang = compute_derived_language (state->lang, state->script);
+ if (old_derived_lang != state->derived_lang)
+ state->changed |= DERIVED_LANG_CHANGED;
+ }
+
+ if (state->changed & (EMOJI_CHANGED))
+ {
+ state->changed |= FONT_CHANGED;
+ }
+
+ if (state->changed & (FONT_CHANGED | DERIVED_LANG_CHANGED) &&
+ state->current_fonts)
+ {
+ g_object_unref (state->current_fonts);
+ state->current_fonts = NULL;
+ state->cache = NULL;
+ }
+
+ if (!state->current_fonts)
+ {
+ gboolean is_emoji = state->emoji_iter.is_emoji;
+ if (is_emoji && !state->emoji_font_desc)
+ {
+ state->emoji_font_desc = pango_font_description_copy_static (state->font_desc);
+ pango_font_description_set_family_static (state->emoji_font_desc, "emoji");
+ }
+ state->current_fonts = pango_font_map_load_fontset (state->context->font_map,
+ state->context,
+ is_emoji ? state->emoji_font_desc : state->font_desc,
+ state->derived_lang);
+ state->cache = get_font_cache (state->current_fonts);
+ }
+
+ if ((state->changed & FONT_CHANGED) && state->base_font)
+ {
+ g_object_unref (state->base_font);
+ state->base_font = NULL;
+ }
+}
+
+static void
+itemize_state_process_run (ItemizeState *state)
+{
+ const char *p;
+ gboolean last_was_forced_break = FALSE;
+ gboolean is_space;
+
+ /* Only one character has type G_UNICODE_LINE_SEPARATOR in Unicode 4.0;
+ * update this if that changes. */
+#define LINE_SEPARATOR 0x2028
+
+ itemize_state_update_for_new_run (state);
+
+ /* We should never get an empty run */
+ g_assert (state->run_end != state->run_start);
+
+ for (p = state->run_start;
+ p < state->run_end;
+ p = g_utf8_next_char (p))
+ {
+ gunichar wc = g_utf8_get_char (p);
+ gboolean is_forced_break = (wc == '\t' || wc == LINE_SEPARATOR);
+ PangoFont *font;
+ int font_position;
+ GUnicodeType type;
+
+ /* We don't want space characters to affect font selection; in general,
+ * it's always wrong to select a font just to render a space.
+ * We assume that all fonts have the ASCII space, and for other space
+ * characters if they don't, HarfBuzz will compatibility-decompose them
+ * to ASCII space...
+ * See bugs #355987 and #701652.
+ *
+ * We don't want to change fonts just for variation selectors.
+ * See bug #781123.
+ *
+ * Finally, don't change fonts for line or paragraph separators.
+ *
+ * Note that we want spaces to use the 'better' font, comparing
+ * the font that is used before and after the space. This is handled
+ * in itemize_state_add_character().
+ */
+ type = g_unichar_type (wc);
+ if (G_UNLIKELY (type == G_UNICODE_CONTROL ||
+ type == G_UNICODE_FORMAT ||
+ type == G_UNICODE_SURROGATE ||
+ type == G_UNICODE_LINE_SEPARATOR ||
+ type == G_UNICODE_PARAGRAPH_SEPARATOR ||
+ (type == G_UNICODE_SPACE_SEPARATOR && wc != 0x1680u /* OGHAM SPACE MARK */) ||
+ (wc >= 0xfe00u && wc <= 0xfe0fu) ||
+ (wc >= 0xe0100u && wc <= 0xe01efu)))
+ {
+ font = NULL;
+ font_position = 0xffff;
+ is_space = TRUE;
+ }
+ else
+ {
+ get_font (state, wc, &font, &font_position);
+ is_space = FALSE;
+ }
+
+ itemize_state_add_character (state, font, font_position,
+ is_forced_break || last_was_forced_break,
+ p,
+ is_space);
+
+ last_was_forced_break = is_forced_break;
+ }
+
+ /* Finish the final item from the current segment */
+ state->item->length = (p - state->text) - state->item->offset;
+ if (!state->item->analysis.font)
+ {
+ PangoFont *font;
+ int position;
+
+ if (G_UNLIKELY (!get_font (state, ' ', &font, &position)))
+ {
+ /* If no font was found, warn once per fontmap/script pair */
+ PangoFontMap *fontmap = state->context->font_map;
+ char *script_tag = g_strdup_printf ("g-unicode-script-%d", state->script);
+
+ if (!g_object_get_data (G_OBJECT (fontmap), script_tag))
+ {
+ g_warning ("failed to choose a font, expect ugly output. script='%d'",
+ state->script);
+
+ g_object_set_data_full (G_OBJECT (fontmap), script_tag,
+ GINT_TO_POINTER (1), NULL);
+ }
+
+ g_free (script_tag);
+
+ font = NULL;
+ }
+ itemize_state_fill_font (state, font);
+ }
+ state->item = NULL;
+}
+
+static void
+itemize_state_finish (ItemizeState *state)
+{
+ g_free (state->embedding_levels);
+ if (state->free_attr_iter)
+ pango_attr_iterator_destroy (state->attr_iter);
+ _pango_script_iter_fini (&state->script_iter);
+ pango_font_description_free (state->font_desc);
+ pango_font_description_free (state->emoji_font_desc);
+ width_iter_fini (&state->width_iter);
+ _pango_emoji_iter_fini (&state->emoji_iter);
+
+ if (state->current_fonts)
+ g_object_unref (state->current_fonts);
+ if (state->base_font)
+ g_object_unref (state->base_font);
+}
+/* }}} */
+/* {{{ Public API */
+
+/* Like pango_itemize, but takes a font description */
+GList *
+pango_itemize_with_font (PangoContext *context,
+ const char *text,
+ int start_index,
+ int length,
+ const PangoFontDescription *desc)
+{
+ ItemizeState state;
+
+ if (length == 0)
+ return NULL;
+
+ itemize_state_init (&state, context, text, context->base_dir, start_index, length,
+ NULL, NULL, desc);
+
+ do
+ itemize_state_process_run (&state);
+ while (itemize_state_next (&state));
+
+ itemize_state_finish (&state);
+
+ return g_list_reverse (state.result);
+}
+
+/**
+ * pango_itemize_with_base_dir:
+ * @context: a structure holding information that affects
+ * the itemization process.
+ * @base_dir: base direction to use for bidirectional processing
+ * @text: the text to itemize.
+ * @start_index: first byte in @text to process
+ * @length: the number of bytes (not characters) to process
+ * after @start_index. This must be >= 0.
+ * @attrs: the set of attributes that apply to @text.
+ * @cached_iter: (nullable): Cached attribute iterator
+ *
+ * Like `pango_itemize()`, but with an explicitly specified base direction.
+ *
+ * The base direction is used when computing bidirectional levels.
+ * (see [method@Pango.Context.set_base_dir]). [func@itemize] gets the
+ * base direction from the `PangoContext`.
+ *
+ * Return value: (transfer full) (element-type Pango.Item): a `GList` of
+ * [struct@Pango.Item] structures. The items should be freed using
+ * [method@Pango.Item.free] probably in combination with g_list_free_full().
+ *
+ * Since: 1.4
+ */
+GList *
+pango_itemize_with_base_dir (PangoContext *context,
+ PangoDirection base_dir,
+ const char *text,
+ int start_index,
+ int length,
+ PangoAttrList *attrs,
+ PangoAttrIterator *cached_iter)
+{
+ ItemizeState state;
+
+ g_return_val_if_fail (context != NULL, NULL);
+ g_return_val_if_fail (start_index >= 0, NULL);
+ g_return_val_if_fail (length >= 0, NULL);
+ g_return_val_if_fail (length == 0 || text != NULL, NULL);
+
+ if (length == 0 || g_utf8_get_char (text + start_index) == '\0')
+ return NULL;
+
+ itemize_state_init (&state, context, text, base_dir, start_index, length,
+ attrs, cached_iter, NULL);
+
+ do
+ itemize_state_process_run (&state);
+ while (itemize_state_next (&state));
+
+ itemize_state_finish (&state);
+
+ return g_list_reverse (state.result);
+}
+
+/**
+ * pango_itemize:
+ * @context: a structure holding information that affects
+ * the itemization process.
+ * @text: the text to itemize. Must be valid UTF-8
+ * @start_index: first byte in @text to process
+ * @length: the number of bytes (not characters) to process
+ * after @start_index. This must be >= 0.
+ * @attrs: the set of attributes that apply to @text.
+ * @cached_iter: (nullable): Cached attribute iterator
+ *
+ * Breaks a piece of text into segments with consistent directional
+ * level and font.
+ *
+ * Each byte of @text will be contained in exactly one of the items in the
+ * returned list; the generated list of items will be in logical order (the
+ * start offsets of the items are ascending).
+ *
+ * @cached_iter should be an iterator over @attrs currently positioned
+ * at a range before or containing @start_index; @cached_iter will be
+ * advanced to the range covering the position just after
+ * @start_index + @length. (i.e. if itemizing in a loop, just keep passing
+ * in the same @cached_iter).
+ *
+ * Return value: (transfer full) (element-type Pango.Item): a `GList` of
+ * [struct@Pango.Item] structures. The items should be freed using
+ * [method@Pango.Item.free] probably in combination with g_list_free_full().
+ */
+GList *
+pango_itemize (PangoContext *context,
+ const char *text,
+ int start_index,
+ int length,
+ PangoAttrList *attrs,
+ PangoAttrIterator *cached_iter)
+{
+ g_return_val_if_fail (context != NULL, NULL);
+ g_return_val_if_fail (start_index >= 0, NULL);
+ g_return_val_if_fail (length >= 0, NULL);
+ g_return_val_if_fail (length == 0 || text != NULL, NULL);
+
+ return pango_itemize_with_base_dir (context, context->base_dir,
+ text, start_index, length, attrs, cached_iter);
+}
+
+/* }}} */
+
+/* vim:set foldmethod=marker expandtab: */
diff --git a/pango/meson.build b/pango/meson.build
index e5121bd8..084de229 100644
--- a/pango/meson.build
+++ b/pango/meson.build
@@ -3,6 +3,7 @@ pango_sources = [
'ellipsize.c',
'fonts.c',
'glyphstring.c',
+ 'itemize.c',
'modules.c',
'pango-attributes.c',
'pango-bidi-type.c',
@@ -26,7 +27,6 @@ pango_sources = [
'pango-utils.c',
'reorder-items.c',
'shape.c',
- 'pangofc-shape.c',
]
pango_headers = [
@@ -34,6 +34,7 @@ pango_headers = [
'pango-attributes.h',
'pango-bidi-type.h',
'pango-break.h',
+ 'pango-color.h',
'pango-context.h',
'pango-coverage.h',
'pango-direction.h',
@@ -48,6 +49,7 @@ pango_headers = [
'pango-language.h',
'pango-layout.h',
'pango-matrix.h',
+ 'pango-markup.h',
'pango-modules.h',
'pango-renderer.h',
'pango-script.h',
diff --git a/pango/pango-attributes-private.h b/pango/pango-attributes-private.h
index f7384fd0..4c427695 100644
--- a/pango/pango-attributes-private.h
+++ b/pango/pango-attributes-private.h
@@ -46,6 +46,8 @@ void _pango_attr_list_get_iterator (PangoAttrList *list,
PangoAttrIterator *iterator);
void _pango_attr_iterator_destroy (PangoAttrIterator *iterator);
+gboolean pango_attr_iterator_advance (PangoAttrIterator *iterator,
+ int index);
#endif
diff --git a/pango/pango-attributes.c b/pango/pango-attributes.c
index fdb37f56..5690aeaa 100644
--- a/pango/pango-attributes.c
+++ b/pango/pango-attributes.c
@@ -26,19 +26,8 @@
#include "pango-attributes-private.h"
#include "pango-impl-utils.h"
-static PangoAttribute *pango_attr_color_new (const PangoAttrClass *klass,
- guint16 red,
- guint16 green,
- guint16 blue);
-static PangoAttribute *pango_attr_string_new (const PangoAttrClass *klass,
- const char *str);
-static PangoAttribute *pango_attr_int_new (const PangoAttrClass *klass,
- int value);
-static PangoAttribute *pango_attr_float_new (const PangoAttrClass *klass,
- double value);
-static PangoAttribute *pango_attr_size_new_internal (int size,
- gboolean absolute);
+/* {{{ Generic attribute code */
G_LOCK_DEFINE_STATIC (attr_type);
static GHashTable *name_map = NULL; /* MT-safe */
@@ -204,6 +193,12 @@ pango_attribute_equal (const PangoAttribute *attr1,
return attr1->klass->equal (attr1, attr2);
}
+/* }}} */
+/* {{{ Attribute types */
+/* {{{ String attribute */
+static PangoAttribute *pango_attr_string_new (const PangoAttrClass *klass,
+ const char *str);
+
static PangoAttribute *
pango_attr_string_copy (const PangoAttribute *attr)
{
@@ -236,32 +231,8 @@ pango_attr_string_new (const PangoAttrClass *klass,
return (PangoAttribute *)result;
}
-
-/**
- * pango_attr_family_new:
- * @family: the family or comma-separated list of families
- *
- * Create a new font family attribute.
- *
- * Return value: (transfer full): the newly allocated
- * `PangoAttribute`, which should be freed with
- * [method@Pango.Attribute.destroy]
- */
-PangoAttribute *
-pango_attr_family_new (const char *family)
-{
- static const PangoAttrClass klass = {
- PANGO_ATTR_FAMILY,
- pango_attr_string_copy,
- pango_attr_string_destroy,
- pango_attr_string_equal
- };
-
- g_return_val_if_fail (family != NULL, NULL);
-
- return pango_attr_string_new (&klass, family);
-}
-
+ /* }}} */
+/* {{{ Language attribute */
static PangoAttribute *
pango_attr_language_copy (const PangoAttribute *attr)
{
@@ -282,35 +253,12 @@ pango_attr_language_equal (const PangoAttribute *attr1,
{
return ((PangoAttrLanguage *)attr1)->value == ((PangoAttrLanguage *)attr2)->value;
}
-
-/**
- * pango_attr_language_new:
- * @language: language tag
- *
- * Create a new language tag attribute.
- *
- * Return value: (transfer full): the newly allocated
- * `PangoAttribute`, which should be freed with
- * [method@Pango.Attribute.destroy]
- */
-PangoAttribute *
-pango_attr_language_new (PangoLanguage *language)
-{
- PangoAttrLanguage *result;
-
- static const PangoAttrClass klass = {
- PANGO_ATTR_LANGUAGE,
- pango_attr_language_copy,
- pango_attr_language_destroy,
- pango_attr_language_equal
- };
-
- result = g_slice_new (PangoAttrLanguage);
- pango_attribute_init (&result->attr, &klass);
- result->value = language;
-
- return (PangoAttribute *)result;
-}
+/* }}}} */
+/* {{{ Color attribute */
+static PangoAttribute *pango_attr_color_new (const PangoAttrClass *klass,
+ guint16 red,
+ guint16 green,
+ guint16 blue);
static PangoAttribute *
pango_attr_color_copy (const PangoAttribute *attr)
@@ -357,60 +305,10 @@ pango_attr_color_new (const PangoAttrClass *klass,
return (PangoAttribute *)result;
}
-
-/**
- * pango_attr_foreground_new:
- * @red: the red value (ranging from 0 to 65535)
- * @green: the green value
- * @blue: the blue value
- *
- * Create a new foreground color attribute.
- *
- * Return value: (transfer full): the newly allocated
- * `PangoAttribute`, which should be freed with
- * [method@Pango.Attribute.destroy]
- */
-PangoAttribute *
-pango_attr_foreground_new (guint16 red,
- guint16 green,
- guint16 blue)
-{
- static const PangoAttrClass klass = {
- PANGO_ATTR_FOREGROUND,
- pango_attr_color_copy,
- pango_attr_color_destroy,
- pango_attr_color_equal
- };
-
- return pango_attr_color_new (&klass, red, green, blue);
-}
-
-/**
- * pango_attr_background_new:
- * @red: the red value (ranging from 0 to 65535)
- * @green: the green value
- * @blue: the blue value
- *
- * Create a new background color attribute.
- *
- * Return value: (transfer full): the newly allocated
- * `PangoAttribute`, which should be freed with
- * [method@Pango.Attribute.destroy]
- */
-PangoAttribute *
-pango_attr_background_new (guint16 red,
- guint16 green,
- guint16 blue)
-{
- static const PangoAttrClass klass = {
- PANGO_ATTR_BACKGROUND,
- pango_attr_color_copy,
- pango_attr_color_destroy,
- pango_attr_color_equal
- };
-
- return pango_attr_color_new (&klass, red, green, blue);
-}
+/* }}}} */
+/* {{{ Integer attribute */
+static PangoAttribute *pango_attr_int_new (const PangoAttrClass *klass,
+ int value);
static PangoAttribute *
pango_attr_int_copy (const PangoAttribute *attr)
@@ -448,6 +346,10 @@ pango_attr_int_new (const PangoAttrClass *klass,
return (PangoAttribute *)result;
}
+/* }}} */
+/* {{{ Float attribute */
+static PangoAttribute *pango_attr_float_new (const PangoAttrClass *klass,
+ double value);
static PangoAttribute *
pango_attr_float_copy (const PangoAttribute *attr)
@@ -475,7 +377,7 @@ pango_attr_float_equal (const PangoAttribute *attr1,
return (float_attr1->value == float_attr2->value);
}
-static PangoAttribute*
+static PangoAttribute *
pango_attr_float_new (const PangoAttrClass *klass,
double value)
{
@@ -485,6 +387,10 @@ pango_attr_float_new (const PangoAttrClass *klass,
return (PangoAttribute *)result;
}
+/* }}} */
+/* {{{ Size attribute */
+static PangoAttribute *pango_attr_size_new_internal (int size,
+ gboolean absolute);
static PangoAttribute *
pango_attr_size_copy (const PangoAttribute *attr)
@@ -541,6 +447,192 @@ pango_attr_size_new_internal (int size,
return (PangoAttribute *)result;
}
+/* }}} */
+/* {{{ Font description attribute */
+static PangoAttribute *
+pango_attr_font_desc_copy (const PangoAttribute *attr)
+{
+ const PangoAttrFontDesc *desc_attr = (const PangoAttrFontDesc *)attr;
+
+ return pango_attr_font_desc_new (desc_attr->desc);
+}
+
+static void
+pango_attr_font_desc_destroy (PangoAttribute *attr)
+{
+ PangoAttrFontDesc *desc_attr = (PangoAttrFontDesc *)attr;
+
+ pango_font_description_free (desc_attr->desc);
+ g_slice_free (PangoAttrFontDesc, desc_attr);
+}
+
+static gboolean
+pango_attr_font_desc_equal (const PangoAttribute *attr1,
+ const PangoAttribute *attr2)
+{
+ const PangoAttrFontDesc *desc_attr1 = (const PangoAttrFontDesc *)attr1;
+ const PangoAttrFontDesc *desc_attr2 = (const PangoAttrFontDesc *)attr2;
+
+ return pango_font_description_get_set_fields (desc_attr1->desc) ==
+ pango_font_description_get_set_fields (desc_attr2->desc) &&
+ pango_font_description_equal (desc_attr1->desc, desc_attr2->desc);
+}
+/* }}} */
+/* {{{ Shape attribute */
+static PangoAttribute *
+pango_attr_shape_copy (const PangoAttribute *attr)
+{
+ const PangoAttrShape *shape_attr = (PangoAttrShape *)attr;
+ gpointer data;
+
+ if (shape_attr->copy_func)
+ data = shape_attr->copy_func (shape_attr->data);
+ else
+ data = shape_attr->data;
+
+ return pango_attr_shape_new_with_data (&shape_attr->ink_rect, &shape_attr->logical_rect,
+ data, shape_attr->copy_func, shape_attr->destroy_func);
+}
+
+static void
+pango_attr_shape_destroy (PangoAttribute *attr)
+{
+ PangoAttrShape *shape_attr = (PangoAttrShape *)attr;
+
+ if (shape_attr->destroy_func)
+ shape_attr->destroy_func (shape_attr->data);
+
+ g_slice_free (PangoAttrShape, shape_attr);
+}
+
+static gboolean
+pango_attr_shape_equal (const PangoAttribute *attr1,
+ const PangoAttribute *attr2)
+{
+ const PangoAttrShape *shape_attr1 = (const PangoAttrShape *)attr1;
+ const PangoAttrShape *shape_attr2 = (const PangoAttrShape *)attr2;
+
+ return (shape_attr1->logical_rect.x == shape_attr2->logical_rect.x &&
+ shape_attr1->logical_rect.y == shape_attr2->logical_rect.y &&
+ shape_attr1->logical_rect.width == shape_attr2->logical_rect.width &&
+ shape_attr1->logical_rect.height == shape_attr2->logical_rect.height &&
+ shape_attr1->ink_rect.x == shape_attr2->ink_rect.x &&
+ shape_attr1->ink_rect.y == shape_attr2->ink_rect.y &&
+ shape_attr1->ink_rect.width == shape_attr2->ink_rect.width &&
+ shape_attr1->ink_rect.height == shape_attr2->ink_rect.height &&
+ shape_attr1->data == shape_attr2->data);
+}
+/* }}} */
+/* }}} */
+/* {{{ Public API */
+
+/**
+ * pango_attr_family_new:
+ * @family: the family or comma-separated list of families
+ *
+ * Create a new font family attribute.
+ *
+ * Return value: (transfer full): the newly allocated
+ * `PangoAttribute`, which should be freed with
+ * [method@Pango.Attribute.destroy]
+ */
+PangoAttribute *
+pango_attr_family_new (const char *family)
+{
+ static const PangoAttrClass klass = {
+ PANGO_ATTR_FAMILY,
+ pango_attr_string_copy,
+ pango_attr_string_destroy,
+ pango_attr_string_equal
+ };
+
+ g_return_val_if_fail (family != NULL, NULL);
+
+ return pango_attr_string_new (&klass, family);
+}
+
+/**
+ * pango_attr_language_new:
+ * @language: language tag
+ *
+ * Create a new language tag attribute.
+ *
+ * Return value: (transfer full): the newly allocated
+ * `PangoAttribute`, which should be freed with
+ * [method@Pango.Attribute.destroy]
+ */
+PangoAttribute *
+pango_attr_language_new (PangoLanguage *language)
+{
+ PangoAttrLanguage *result;
+
+ static const PangoAttrClass klass = {
+ PANGO_ATTR_LANGUAGE,
+ pango_attr_language_copy,
+ pango_attr_language_destroy,
+ pango_attr_language_equal
+ };
+
+ result = g_slice_new (PangoAttrLanguage);
+ pango_attribute_init (&result->attr, &klass);
+ result->value = language;
+
+ return (PangoAttribute *)result;
+}
+
+/**
+ * pango_attr_foreground_new:
+ * @red: the red value (ranging from 0 to 65535)
+ * @green: the green value
+ * @blue: the blue value
+ *
+ * Create a new foreground color attribute.
+ *
+ * Return value: (transfer full): the newly allocated
+ * `PangoAttribute`, which should be freed with
+ * [method@Pango.Attribute.destroy]
+ */
+PangoAttribute *
+pango_attr_foreground_new (guint16 red,
+ guint16 green,
+ guint16 blue)
+{
+ static const PangoAttrClass klass = {
+ PANGO_ATTR_FOREGROUND,
+ pango_attr_color_copy,
+ pango_attr_color_destroy,
+ pango_attr_color_equal
+ };
+
+ return pango_attr_color_new (&klass, red, green, blue);
+}
+
+/**
+ * pango_attr_background_new:
+ * @red: the red value (ranging from 0 to 65535)
+ * @green: the green value
+ * @blue: the blue value
+ *
+ * Create a new background color attribute.
+ *
+ * Return value: (transfer full): the newly allocated
+ * `PangoAttribute`, which should be freed with
+ * [method@Pango.Attribute.destroy]
+ */
+PangoAttribute *
+pango_attr_background_new (guint16 red,
+ guint16 green,
+ guint16 blue)
+{
+ static const PangoAttrClass klass = {
+ PANGO_ATTR_BACKGROUND,
+ pango_attr_color_copy,
+ pango_attr_color_destroy,
+ pango_attr_color_equal
+ };
+
+ return pango_attr_color_new (&klass, red, green, blue);
+}
/**
* pango_attr_size_new:
@@ -667,35 +759,6 @@ pango_attr_stretch_new (PangoStretch stretch)
return pango_attr_int_new (&klass, (int)stretch);
}
-static PangoAttribute *
-pango_attr_font_desc_copy (const PangoAttribute *attr)
-{
- const PangoAttrFontDesc *desc_attr = (const PangoAttrFontDesc *)attr;
-
- return pango_attr_font_desc_new (desc_attr->desc);
-}
-
-static void
-pango_attr_font_desc_destroy (PangoAttribute *attr)
-{
- PangoAttrFontDesc *desc_attr = (PangoAttrFontDesc *)attr;
-
- pango_font_description_free (desc_attr->desc);
- g_slice_free (PangoAttrFontDesc, desc_attr);
-}
-
-static gboolean
-pango_attr_font_desc_equal (const PangoAttribute *attr1,
- const PangoAttribute *attr2)
-{
- const PangoAttrFontDesc *desc_attr1 = (const PangoAttrFontDesc *)attr1;
- const PangoAttrFontDesc *desc_attr2 = (const PangoAttrFontDesc *)attr2;
-
- return pango_font_description_get_set_fields (desc_attr1->desc) ==
- pango_font_description_get_set_fields (desc_attr2->desc) &&
- pango_font_description_equal (desc_attr1->desc, desc_attr2->desc);
-}
-
/**
* pango_attr_font_desc_new:
* @desc: the font description
@@ -726,7 +789,6 @@ pango_attr_font_desc_new (const PangoFontDescription *desc)
return (PangoAttribute *)result;
}
-
/**
* pango_attr_underline_new:
* @underline: the underline style
@@ -944,50 +1006,6 @@ pango_attr_letter_spacing_new (int letter_spacing)
return pango_attr_int_new (&klass, letter_spacing);
}
-static PangoAttribute *
-pango_attr_shape_copy (const PangoAttribute *attr)
-{
- const PangoAttrShape *shape_attr = (PangoAttrShape *)attr;
- gpointer data;
-
- if (shape_attr->copy_func)
- data = shape_attr->copy_func (shape_attr->data);
- else
- data = shape_attr->data;
-
- return pango_attr_shape_new_with_data (&shape_attr->ink_rect, &shape_attr->logical_rect,
- data, shape_attr->copy_func, shape_attr->destroy_func);
-}
-
-static void
-pango_attr_shape_destroy (PangoAttribute *attr)
-{
- PangoAttrShape *shape_attr = (PangoAttrShape *)attr;
-
- if (shape_attr->destroy_func)
- shape_attr->destroy_func (shape_attr->data);
-
- g_slice_free (PangoAttrShape, shape_attr);
-}
-
-static gboolean
-pango_attr_shape_equal (const PangoAttribute *attr1,
- const PangoAttribute *attr2)
-{
- const PangoAttrShape *shape_attr1 = (const PangoAttrShape *)attr1;
- const PangoAttrShape *shape_attr2 = (const PangoAttrShape *)attr2;
-
- return (shape_attr1->logical_rect.x == shape_attr2->logical_rect.x &&
- shape_attr1->logical_rect.y == shape_attr2->logical_rect.y &&
- shape_attr1->logical_rect.width == shape_attr2->logical_rect.width &&
- shape_attr1->logical_rect.height == shape_attr2->logical_rect.height &&
- shape_attr1->ink_rect.x == shape_attr2->ink_rect.x &&
- shape_attr1->ink_rect.y == shape_attr2->ink_rect.y &&
- shape_attr1->ink_rect.width == shape_attr2->ink_rect.width &&
- shape_attr1->ink_rect.height == shape_attr2->ink_rect.height &&
- shape_attr1->data == shape_attr2->data);
-}
-
/**
* pango_attr_shape_new_with_data:
* @ink_rect: ink rectangle to assign to each character
@@ -1393,9 +1411,265 @@ pango_attr_line_height_new_absolute (int height)
return pango_attr_int_new (&klass, height);
}
-/*
- * Attribute List
+/* }}} */
+/* {{{ Binding helpers */
+
+/**
+ * pango_attribute_as_int:
+ * @attr: A `PangoAttribute` such as weight
+ *
+ * Returns the attribute cast to `PangoAttrInt`.
+ *
+ * This is mainly useful for language bindings.
+ *
+ * Returns: (nullable) (transfer none): The attribute as `PangoAttrInt`,
+ * or %NULL if it's not an integer attribute
+ *
+ * Since: 1.50
+ */
+PangoAttrInt *
+pango_attribute_as_int (PangoAttribute *attr)
+{
+ switch (attr->klass->type)
+ {
+ case PANGO_ATTR_STYLE:
+ case PANGO_ATTR_WEIGHT:
+ case PANGO_ATTR_VARIANT:
+ case PANGO_ATTR_STRETCH:
+ case PANGO_ATTR_UNDERLINE:
+ case PANGO_ATTR_STRIKETHROUGH:
+ case PANGO_ATTR_RISE:
+ case PANGO_ATTR_FALLBACK:
+ case PANGO_ATTR_LETTER_SPACING:
+ case PANGO_ATTR_GRAVITY:
+ case PANGO_ATTR_GRAVITY_HINT:
+ case PANGO_ATTR_FOREGROUND_ALPHA:
+ case PANGO_ATTR_BACKGROUND_ALPHA:
+ case PANGO_ATTR_ALLOW_BREAKS:
+ case PANGO_ATTR_SHOW:
+ case PANGO_ATTR_INSERT_HYPHENS:
+ case PANGO_ATTR_OVERLINE:
+ return (PangoAttrInt *)attr;
+
+ default:
+ return NULL;
+ }
+}
+
+/**
+ * pango_attribute_as_float:
+ * @attr: A `PangoAttribute` such as scale
+ *
+ * Returns the attribute cast to `PangoAttrFloat`.
+ *
+ * This is mainly useful for language bindings.
+ *
+ * Returns: (nullable) (transfer none): The attribute as `PangoAttrFloat`,
+ * or %NULL if it's not a floating point attribute
+ *
+ * Since: 1.50
+ */
+PangoAttrFloat *
+pango_attribute_as_float (PangoAttribute *attr)
+{
+ switch (attr->klass->type)
+ {
+ case PANGO_ATTR_SCALE:
+ case PANGO_ATTR_LINE_HEIGHT:
+ return (PangoAttrFloat *)attr;
+
+ default:
+ return NULL;
+ }
+}
+
+/**
+ * pango_attribute_as_string:
+ * @attr: A `PangoAttribute` such as family
+ *
+ * Returns the attribute cast to `PangoAttrString`.
+ *
+ * This is mainly useful for language bindings.
+ *
+ * Returns: (nullable) (transfer none): The attribute as `PangoAttrString`,
+ * or %NULL if it's not a string attribute
*/
+PangoAttrString *
+pango_attribute_as_string (PangoAttribute *attr)
+{
+ switch (attr->klass->type)
+ {
+ case PANGO_ATTR_FAMILY:
+ return (PangoAttrString *)attr;
+
+ default:
+ return NULL;
+ }
+}
+
+/**
+ * pango_attribute_as_size:
+ * @attr: A `PangoAttribute` representing a size
+ *
+ * Returns the attribute cast to `PangoAttrSize`.
+ *
+ * This is mainly useful for language bindings.
+ *
+ * Returns: (nullable) (transfer none): The attribute as `PangoAttrSize`,
+ * or NULL if it's not a size attribute
+ *
+ * Since: 1.50
+ */
+PangoAttrSize *
+pango_attribute_as_size (PangoAttribute *attr)
+{
+ switch (attr->klass->type)
+ {
+ case PANGO_ATTR_SIZE:
+ case PANGO_ATTR_ABSOLUTE_SIZE:
+ return (PangoAttrSize *)attr;
+
+ default:
+ return NULL;
+ }
+}
+
+/**
+ * pango_attribute_as_color:
+ * @attr: A `PangoAttribute` such as foreground
+ *
+ * Returns the attribute cast to `PangoAttrColor`.
+ *
+ * This is mainly useful for language bindings.
+ *
+ * Returns: (nullable) (transfer none): The attribute as `PangoAttrColor`,
+ * or %NULL if it's not a color attribute
+ *
+ * Since: 1.50
+ */
+PangoAttrColor *
+pango_attribute_as_color (PangoAttribute *attr)
+{
+ switch (attr->klass->type)
+ {
+ case PANGO_ATTR_FOREGROUND:
+ case PANGO_ATTR_BACKGROUND:
+ case PANGO_ATTR_UNDERLINE_COLOR:
+ case PANGO_ATTR_STRIKETHROUGH_COLOR:
+ case PANGO_ATTR_OVERLINE_COLOR:
+ return (PangoAttrColor *)attr;
+
+ default:
+ return NULL;
+ }
+}
+
+/**
+ * pango_attribute_as_font_desc:
+ * @attr: A `PangoAttribute` representing a font description
+ *
+ * Returns the attribute cast to `PangoAttrFontDesc`.
+ *
+ * This is mainly useful for language bindings.
+ *
+ * Returns: (nullable) (transfer none): The attribute as `PangoAttrFontDesc`,
+ * or %NULL if it's not a font description attribute
+ *
+ * Since: 1.50
+ */
+PangoAttrFontDesc *
+pango_attribute_as_font_desc (PangoAttribute *attr)
+{
+ switch (attr->klass->type)
+ {
+ case PANGO_ATTR_FONT_DESC:
+ return (PangoAttrFontDesc *)attr;
+
+ default:
+ return NULL;
+ }
+}
+
+/**
+ * pango_attribute_as_font_features:
+ * @attr: A `PangoAttribute` representing font features
+ *
+ * Returns the attribute cast to `PangoAttrFontFeatures`.
+ *
+ * This is mainly useful for language bindings.
+ *
+ * Returns: (nullable) (transfer none): The attribute as `PangoAttrFontFeatures`,
+ * or %NULL if it's not a font features attribute
+ *
+ * Since: 1.50
+ */
+PangoAttrFontFeatures *
+pango_attribute_as_font_features (PangoAttribute *attr)
+{
+ switch (attr->klass->type)
+ {
+ case PANGO_ATTR_FONT_FEATURES:
+ return (PangoAttrFontFeatures *)attr;
+
+ default:
+ return NULL;
+ }
+}
+
+/**
+ * pango_attribute_as_language:
+ * @attr: A `PangoAttribute` representing a language
+ *
+ * Returns the attribute cast to `PangoAttrLanguage`.
+ *
+ * This is mainly useful for language bindings.
+ *
+ * Returns: (nullable) (transfer none): The attribute as `PangoAttrLanguage`,
+ * or %NULL if it's not a language attribute
+ *
+ * Since: 1.50
+ */
+PangoAttrLanguage *
+pango_attribute_as_language (PangoAttribute *attr)
+{
+ switch (attr->klass->type)
+ {
+ case PANGO_ATTR_LANGUAGE:
+ return (PangoAttrLanguage *)attr;
+
+ default:
+ return NULL;
+ }
+}
+
+/**
+ * pango_attribute_as_shape:
+ * @attr: A `PangoAttribute` representing a shape
+ *
+ * Returns the attribute cast to `PangoAttrShape`.
+ *
+ * This is mainly useful for language bindings.
+ *
+ * Returns: (nullable) (transfer none): The attribute as `PangoAttrShape`,
+ * or %NULL if it's not a shape attribute
+ *
+ * Since: 1.50
+ */
+PangoAttrShape *
+pango_attribute_as_shape (PangoAttribute *attr)
+{
+ switch (attr->klass->type)
+ {
+ case PANGO_ATTR_SHAPE:
+ return (PangoAttrShape *)attr;
+
+ default:
+ return NULL;
+ }
+}
+
+/* }}} */
+/* {{{ Attribute List */
G_DEFINE_BOXED_TYPE (PangoAttrList, pango_attr_list,
pango_attr_list_copy,
@@ -2043,6 +2317,63 @@ _pango_attr_list_has_attributes (const PangoAttrList *list)
return list && list->attributes != NULL && list->attributes->len > 0;
}
+/**
+ * pango_attr_list_filter:
+ * @list: a `PangoAttrList`
+ * @func: (scope call) (closure data): callback function;
+ * returns %TRUE if an attribute should be filtered out
+ * @data: (closure): Data to be passed to @func
+ *
+ * Given a `PangoAttrList` and callback function, removes
+ * any elements of @list for which @func returns %TRUE and
+ * inserts them into a new list.
+ *
+ * Return value: (transfer full) (nullable): the new
+ * `PangoAttrList` or %NULL if no attributes of the
+ * given types were found
+ *
+ * Since: 1.2
+ */
+PangoAttrList *
+pango_attr_list_filter (PangoAttrList *list,
+ PangoAttrFilterFunc func,
+ gpointer data)
+
+{
+ PangoAttrList *new = NULL;
+ guint i, p;
+
+ g_return_val_if_fail (list != NULL, NULL);
+
+ if (!list->attributes || list->attributes->len == 0)
+ return NULL;
+
+ for (i = 0, p = list->attributes->len; i < p; i++)
+ {
+ PangoAttribute *tmp_attr = g_ptr_array_index (list->attributes, i);
+
+ if ((*func) (tmp_attr, data))
+ {
+ g_ptr_array_remove_index (list->attributes, i);
+ i--; /* Need to look at this index again */
+ p--;
+
+ if (G_UNLIKELY (!new))
+ {
+ new = pango_attr_list_new ();
+ new->attributes = g_ptr_array_new ();
+ }
+
+ g_ptr_array_add (new->attributes, tmp_attr);
+ }
+ }
+
+ return new;
+}
+
+/* }}} */
+/* {{{ Attribute Iterator */
+
G_DEFINE_BOXED_TYPE (PangoAttrIterator,
pango_attr_iterator,
pango_attr_iterator_copy,
@@ -2448,60 +2779,6 @@ pango_attr_iterator_get_font (PangoAttrIterator *iterator,
}
/**
- * pango_attr_list_filter:
- * @list: a `PangoAttrList`
- * @func: (scope call) (closure data): callback function;
- * returns %TRUE if an attribute should be filtered out
- * @data: (closure): Data to be passed to @func
- *
- * Given a `PangoAttrList` and callback function, removes
- * any elements of @list for which @func returns %TRUE and
- * inserts them into a new list.
- *
- * Return value: (transfer full) (nullable): the new
- * `PangoAttrList` or %NULL if no attributes of the
- * given types were found
- *
- * Since: 1.2
- */
-PangoAttrList *
-pango_attr_list_filter (PangoAttrList *list,
- PangoAttrFilterFunc func,
- gpointer data)
-
-{
- PangoAttrList *new = NULL;
- guint i, p;
-
- g_return_val_if_fail (list != NULL, NULL);
-
- if (!list->attributes || list->attributes->len == 0)
- return NULL;
-
- for (i = 0, p = list->attributes->len; i < p; i++)
- {
- PangoAttribute *tmp_attr = g_ptr_array_index (list->attributes, i);
-
- if ((*func) (tmp_attr, data))
- {
- g_ptr_array_remove_index (list->attributes, i);
- i--; /* Need to look at this index again */
- p--;
-
- if (G_UNLIKELY (!new))
- {
- new = pango_attr_list_new ();
- new->attributes = g_ptr_array_new ();
- }
-
- g_ptr_array_add (new->attributes, tmp_attr);
- }
- }
-
- return new;
-}
-
-/**
* pango_attr_iterator_get_attrs:
* @iterator: a `PangoAttrIterator`
*
@@ -2549,257 +2826,27 @@ pango_attr_iterator_get_attrs (PangoAttrIterator *iterator)
return attrs;
}
-
-/**
- * pango_attribute_as_int:
- * @attr: A `PangoAttribute` such as weight
- *
- * Returns the attribute cast to `PangoAttrInt`.
- *
- * This is mainly useful for language bindings.
- *
- * Returns: (nullable) (transfer none): The attribute as `PangoAttrInt`,
- * or %NULL if it's not an integer attribute
- *
- * Since: 1.50
- */
-PangoAttrInt *
-pango_attribute_as_int (PangoAttribute *attr)
-{
- switch (attr->klass->type)
- {
- case PANGO_ATTR_STYLE:
- case PANGO_ATTR_WEIGHT:
- case PANGO_ATTR_VARIANT:
- case PANGO_ATTR_STRETCH:
- case PANGO_ATTR_UNDERLINE:
- case PANGO_ATTR_STRIKETHROUGH:
- case PANGO_ATTR_RISE:
- case PANGO_ATTR_FALLBACK:
- case PANGO_ATTR_LETTER_SPACING:
- case PANGO_ATTR_GRAVITY:
- case PANGO_ATTR_GRAVITY_HINT:
- case PANGO_ATTR_FOREGROUND_ALPHA:
- case PANGO_ATTR_BACKGROUND_ALPHA:
- case PANGO_ATTR_ALLOW_BREAKS:
- case PANGO_ATTR_SHOW:
- case PANGO_ATTR_INSERT_HYPHENS:
- case PANGO_ATTR_OVERLINE:
- return (PangoAttrInt *)attr;
-
- default:
- return NULL;
- }
-}
-
-/**
- * pango_attribute_as_float:
- * @attr: A `PangoAttribute` such as scale
- *
- * Returns the attribute cast to `PangoAttrFloat`.
- *
- * This is mainly useful for language bindings.
- *
- * Returns: (nullable) (transfer none): The attribute as `PangoAttrFloat`,
- * or %NULL if it's not a floating point attribute
- *
- * Since: 1.50
- */
-PangoAttrFloat *
-pango_attribute_as_float (PangoAttribute *attr)
-{
- switch (attr->klass->type)
- {
- case PANGO_ATTR_SCALE:
- case PANGO_ATTR_LINE_HEIGHT:
- return (PangoAttrFloat *)attr;
-
- default:
- return NULL;
- }
-}
-
-/**
- * pango_attribute_as_string:
- * @attr: A `PangoAttribute` such as family
- *
- * Returns the attribute cast to `PangoAttrString`.
- *
- * This is mainly useful for language bindings.
- *
- * Returns: (nullable) (transfer none): The attribute as `PangoAttrString`,
- * or %NULL if it's not a string attribute
- */
-PangoAttrString *
-pango_attribute_as_string (PangoAttribute *attr)
-{
- switch (attr->klass->type)
- {
- case PANGO_ATTR_FAMILY:
- return (PangoAttrString *)attr;
-
- default:
- return NULL;
- }
-}
-
-/**
- * pango_attribute_as_size:
- * @attr: A `PangoAttribute` representing a size
- *
- * Returns the attribute cast to `PangoAttrSize`.
- *
- * This is mainly useful for language bindings.
- *
- * Returns: (nullable) (transfer none): The attribute as `PangoAttrSize`,
- * or NULL if it's not a size attribute
- *
- * Since: 1.50
- */
-PangoAttrSize *
-pango_attribute_as_size (PangoAttribute *attr)
-{
- switch (attr->klass->type)
- {
- case PANGO_ATTR_SIZE:
- case PANGO_ATTR_ABSOLUTE_SIZE:
- return (PangoAttrSize *)attr;
-
- default:
- return NULL;
- }
-}
-
-/**
- * pango_attribute_as_color:
- * @attr: A `PangoAttribute` such as foreground
- *
- * Returns the attribute cast to `PangoAttrColor`.
- *
- * This is mainly useful for language bindings.
- *
- * Returns: (nullable) (transfer none): The attribute as `PangoAttrColor`,
- * or %NULL if it's not a color attribute
- *
- * Since: 1.50
- */
-PangoAttrColor *
-pango_attribute_as_color (PangoAttribute *attr)
+gboolean
+pango_attr_iterator_advance (PangoAttrIterator *iterator,
+ int index)
{
- switch (attr->klass->type)
- {
- case PANGO_ATTR_FOREGROUND:
- case PANGO_ATTR_BACKGROUND:
- case PANGO_ATTR_UNDERLINE_COLOR:
- case PANGO_ATTR_STRIKETHROUGH_COLOR:
- case PANGO_ATTR_OVERLINE_COLOR:
- return (PangoAttrColor *)attr;
+ int start_range, end_range;
- default:
- return NULL;
- }
-}
+ pango_attr_iterator_range (iterator, &start_range, &end_range);
-/**
- * pango_attribute_as_font_desc:
- * @attr: A `PangoAttribute` representing a font description
- *
- * Returns the attribute cast to `PangoAttrFontDesc`.
- *
- * This is mainly useful for language bindings.
- *
- * Returns: (nullable) (transfer none): The attribute as `PangoAttrFontDesc`,
- * or %NULL if it's not a font description attribute
- *
- * Since: 1.50
- */
-PangoAttrFontDesc *
-pango_attribute_as_font_desc (PangoAttribute *attr)
-{
- switch (attr->klass->type)
+ while (index >= end_range)
{
- case PANGO_ATTR_FONT_DESC:
- return (PangoAttrFontDesc *)attr;
-
- default:
- return NULL;
- }
-}
-
-/**
- * pango_attribute_as_font_features:
- * @attr: A `PangoAttribute` representing font features
- *
- * Returns the attribute cast to `PangoAttrFontFeatures`.
- *
- * This is mainly useful for language bindings.
- *
- * Returns: (nullable) (transfer none): The attribute as `PangoAttrFontFeatures`,
- * or %NULL if it's not a font features attribute
- *
- * Since: 1.50
- */
-PangoAttrFontFeatures *
-pango_attribute_as_font_features (PangoAttribute *attr)
-{
- switch (attr->klass->type)
- {
- case PANGO_ATTR_FONT_FEATURES:
- return (PangoAttrFontFeatures *)attr;
-
- default:
- return NULL;
+ if (!pango_attr_iterator_next (iterator))
+ return FALSE;
+ pango_attr_iterator_range (iterator, &start_range, &end_range);
}
-}
-/**
- * pango_attribute_as_language:
- * @attr: A `PangoAttribute` representing a language
- *
- * Returns the attribute cast to `PangoAttrLanguage`.
- *
- * This is mainly useful for language bindings.
- *
- * Returns: (nullable) (transfer none): The attribute as `PangoAttrLanguage`,
- * or %NULL if it's not a language attribute
- *
- * Since: 1.50
- */
-PangoAttrLanguage *
-pango_attribute_as_language (PangoAttribute *attr)
-{
- switch (attr->klass->type)
- {
- case PANGO_ATTR_LANGUAGE:
- return (PangoAttrLanguage *)attr;
+ if (start_range > index)
+ g_warning ("pango_attr_iterator_advance(): iterator had already "
+ "moved beyond the index");
- default:
- return NULL;
- }
+ return TRUE;
}
+/* }}} */
-/**
- * pango_attribute_as_shape:
- * @attr: A `PangoAttribute` representing a shape
- *
- * Returns the attribute cast to `PangoAttrShape`.
- *
- * This is mainly useful for language bindings.
- *
- * Returns: (nullable) (transfer none): The attribute as `PangoAttrShape`,
- * or %NULL if it's not a shape attribute
- *
- * Since: 1.50
- */
-PangoAttrShape *
-pango_attribute_as_shape (PangoAttribute *attr)
-{
- switch (attr->klass->type)
- {
- case PANGO_ATTR_SHAPE:
- return (PangoAttrShape *)attr;
-
- default:
- return NULL;
- }
-}
+/* vim:set foldmethod=marker expandtab: */
diff --git a/pango/pango-attributes.h b/pango/pango-attributes.h
index 35615bf3..e3012008 100644
--- a/pango/pango-attributes.h
+++ b/pango/pango-attributes.h
@@ -10,7 +10,7 @@
*
* 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
+ * 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
@@ -23,111 +23,26 @@
#define __PANGO_ATTRIBUTES_H__
#include <pango/pango-font.h>
+#include <pango/pango-color.h>
#include <glib-object.h>
G_BEGIN_DECLS
-/* PangoColor */
-typedef struct _PangoColor PangoColor;
+typedef struct _PangoAttribute PangoAttribute;
+typedef struct _PangoAttrClass PangoAttrClass;
-/**
- * PangoColor:
- * @red: value of red component
- * @green: value of green component
- * @blue: value of blue component
- *
- * The `PangoColor` structure is used to
- * represent a color in an uncalibrated RGB color-space.
- */
-struct _PangoColor
-{
- guint16 red;
- guint16 green;
- guint16 blue;
-};
-
-/**
- * PANGO_TYPE_COLOR:
- *
- * The `GObject` type for `PangoColor`.
- */
-#define PANGO_TYPE_COLOR pango_color_get_type ()
-PANGO_AVAILABLE_IN_ALL
-GType pango_color_get_type (void) G_GNUC_CONST;
-
-PANGO_AVAILABLE_IN_ALL
-GType pango_attribute_get_type (void) G_GNUC_CONST;
-
-PANGO_AVAILABLE_IN_ALL
-PangoColor *pango_color_copy (const PangoColor *src);
-PANGO_AVAILABLE_IN_ALL
-void pango_color_free (PangoColor *color);
-PANGO_AVAILABLE_IN_ALL
-gboolean pango_color_parse (PangoColor *color,
- const char *spec);
-PANGO_AVAILABLE_IN_1_46
-gboolean pango_color_parse_with_alpha
- (PangoColor *color,
- guint16 *alpha,
- const char *spec);
-PANGO_AVAILABLE_IN_1_16
-gchar *pango_color_to_string(const PangoColor *color);
-
-
-/* Attributes */
-
-typedef struct _PangoAttribute PangoAttribute;
-typedef struct _PangoAttrClass PangoAttrClass;
-
-typedef struct _PangoAttrString PangoAttrString;
-typedef struct _PangoAttrLanguage PangoAttrLanguage;
-typedef struct _PangoAttrInt PangoAttrInt;
-typedef struct _PangoAttrSize PangoAttrSize;
-typedef struct _PangoAttrFloat PangoAttrFloat;
-typedef struct _PangoAttrColor PangoAttrColor;
-typedef struct _PangoAttrFontDesc PangoAttrFontDesc;
-typedef struct _PangoAttrShape PangoAttrShape;
+typedef struct _PangoAttrString PangoAttrString;
+typedef struct _PangoAttrLanguage PangoAttrLanguage;
+typedef struct _PangoAttrInt PangoAttrInt;
+typedef struct _PangoAttrSize PangoAttrSize;
+typedef struct _PangoAttrFloat PangoAttrFloat;
+typedef struct _PangoAttrColor PangoAttrColor;
+typedef struct _PangoAttrFontDesc PangoAttrFontDesc;
+typedef struct _PangoAttrShape PangoAttrShape;
typedef struct _PangoAttrFontFeatures PangoAttrFontFeatures;
/**
- * PANGO_TYPE_ATTR_LIST:
- *
- * The `GObject` type for `PangoAttrList`.
- */
-#define PANGO_TYPE_ATTR_LIST pango_attr_list_get_type ()
-
-/**
- * PangoAttrIterator:
- *
- * A `PangoAttrIterator` is used to iterate through a `PangoAttrList`.
- *
- * A new iterator is created with [method@Pango.AttrList.get_iterator].
- * Once the iterator is created, it can be advanced through the style
- * changes in the text using [method@Pango.AttrIterator.next]. At each
- * style change, the range of the current style segment and the attributes
- * currently in effect can be queried.
- */
-
-/**
- * PangoAttrList:
- *
- * A `PangoAttrList` represents a list of attributes that apply to a section
- * of text.
- *
- * The attributes in a `PangoAttrList` are, in general, allowed to overlap in
- * an arbitrary fashion. However, if the attributes are manipulated only through
- * [method@Pango.AttrList.change], the overlap between properties will meet
- * stricter criteria.
- *
- * Since the `PangoAttrList` structure is stored as a linear list, it is not
- * suitable for storing attributes for large amounts of text. In general, you
- * should not use a single `PangoAttrList` for more than one paragraph of text.
- */
-typedef struct _PangoAttrList PangoAttrList;
-typedef struct _PangoAttrIterator PangoAttrIterator;
-
-/**
* PangoAttrType:
* @PANGO_ATTR_INVALID: does not happen
* @PANGO_ATTR_LANGUAGE: language ([struct@Pango.AttrLanguage])
@@ -173,37 +88,37 @@ typedef struct _PangoAttrIterator PangoAttrIterator;
typedef enum
{
PANGO_ATTR_INVALID, /* 0 is an invalid attribute type */
- PANGO_ATTR_LANGUAGE, /* PangoAttrLanguage */
- PANGO_ATTR_FAMILY, /* PangoAttrString */
- PANGO_ATTR_STYLE, /* PangoAttrInt */
- PANGO_ATTR_WEIGHT, /* PangoAttrInt */
- PANGO_ATTR_VARIANT, /* PangoAttrInt */
- PANGO_ATTR_STRETCH, /* PangoAttrInt */
- PANGO_ATTR_SIZE, /* PangoAttrSize */
- PANGO_ATTR_FONT_DESC, /* PangoAttrFontDesc */
- PANGO_ATTR_FOREGROUND, /* PangoAttrColor */
- PANGO_ATTR_BACKGROUND, /* PangoAttrColor */
- PANGO_ATTR_UNDERLINE, /* PangoAttrInt */
- PANGO_ATTR_STRIKETHROUGH, /* PangoAttrInt */
- PANGO_ATTR_RISE, /* PangoAttrInt */
- PANGO_ATTR_SHAPE, /* PangoAttrShape */
+ PANGO_ATTR_LANGUAGE, /* PangoAttrLanguage */
+ PANGO_ATTR_FAMILY, /* PangoAttrString */
+ PANGO_ATTR_STYLE, /* PangoAttrInt */
+ PANGO_ATTR_WEIGHT, /* PangoAttrInt */
+ PANGO_ATTR_VARIANT, /* PangoAttrInt */
+ PANGO_ATTR_STRETCH, /* PangoAttrInt */
+ PANGO_ATTR_SIZE, /* PangoAttrSize */
+ PANGO_ATTR_FONT_DESC, /* PangoAttrFontDesc */
+ PANGO_ATTR_FOREGROUND, /* PangoAttrColor */
+ PANGO_ATTR_BACKGROUND, /* PangoAttrColor */
+ PANGO_ATTR_UNDERLINE, /* PangoAttrInt */
+ PANGO_ATTR_STRIKETHROUGH, /* PangoAttrInt */
+ PANGO_ATTR_RISE, /* PangoAttrInt */
+ PANGO_ATTR_SHAPE, /* PangoAttrShape */
PANGO_ATTR_SCALE, /* PangoAttrFloat */
PANGO_ATTR_FALLBACK, /* PangoAttrInt */
PANGO_ATTR_LETTER_SPACING, /* PangoAttrInt */
- PANGO_ATTR_UNDERLINE_COLOR, /* PangoAttrColor */
+ PANGO_ATTR_UNDERLINE_COLOR, /* PangoAttrColor */
PANGO_ATTR_STRIKETHROUGH_COLOR,/* PangoAttrColor */
- PANGO_ATTR_ABSOLUTE_SIZE, /* PangoAttrSize */
- PANGO_ATTR_GRAVITY, /* PangoAttrInt */
- PANGO_ATTR_GRAVITY_HINT, /* PangoAttrInt */
- PANGO_ATTR_FONT_FEATURES, /* PangoAttrString */
- PANGO_ATTR_FOREGROUND_ALPHA, /* PangoAttrInt */
- PANGO_ATTR_BACKGROUND_ALPHA, /* PangoAttrInt */
- PANGO_ATTR_ALLOW_BREAKS, /* PangoAttrInt */
- PANGO_ATTR_SHOW, /* PangoAttrInt */
- PANGO_ATTR_INSERT_HYPHENS, /* PangoAttrInt */
- PANGO_ATTR_OVERLINE, /* PangoAttrInt */
- PANGO_ATTR_OVERLINE_COLOR, /* PangoAttrColor */
- PANGO_ATTR_LINE_HEIGHT, /* PangoAttrFloat */
+ PANGO_ATTR_ABSOLUTE_SIZE, /* PangoAttrSize */
+ PANGO_ATTR_GRAVITY, /* PangoAttrInt */
+ PANGO_ATTR_GRAVITY_HINT, /* PangoAttrInt */
+ PANGO_ATTR_FONT_FEATURES, /* PangoAttrString */
+ PANGO_ATTR_FOREGROUND_ALPHA, /* PangoAttrInt */
+ PANGO_ATTR_BACKGROUND_ALPHA, /* PangoAttrInt */
+ PANGO_ATTR_ALLOW_BREAKS, /* PangoAttrInt */
+ PANGO_ATTR_SHOW, /* PangoAttrInt */
+ PANGO_ATTR_INSERT_HYPHENS, /* PangoAttrInt */
+ PANGO_ATTR_OVERLINE, /* PangoAttrInt */
+ PANGO_ATTR_OVERLINE_COLOR, /* PangoAttrColor */
+ PANGO_ATTR_LINE_HEIGHT, /* PangoAttrFloat */
PANGO_ATTR_ABSOLUTE_LINE_HEIGHT, /* PangoAttrInt */
} PangoAttrType;
@@ -268,6 +183,26 @@ typedef enum {
} PangoOverline;
/**
+ * PangoShowFlags:
+ * @PANGO_SHOW_NONE: No special treatment for invisible characters
+ * @PANGO_SHOW_SPACES: Render spaces, tabs and newlines visibly
+ * @PANGO_SHOW_LINE_BREAKS: Render line breaks visibly
+ * @PANGO_SHOW_IGNORABLES: Render default-ignorable Unicode
+ * characters visibly
+ *
+ * These flags affect how Pango treats characters that are normally
+ * not visible in the output.
+ *
+ * Since: 1.44
+ */
+typedef enum {
+ PANGO_SHOW_NONE = 0,
+ PANGO_SHOW_SPACES = 1 << 0,
+ PANGO_SHOW_LINE_BREAKS = 1 << 1,
+ PANGO_SHOW_IGNORABLES = 1 << 2
+} PangoShowFlags;
+
+/**
* PANGO_ATTR_INDEX_FROM_TEXT_BEGINNING:
*
* Value for @start_index in `PangoAttribute` that indicates
@@ -292,7 +227,7 @@ typedef enum {
* @klass: the class structure holding information about the type of the attribute
* @start_index: the start index of the range (in bytes).
* @end_index: end index of the range (in bytes). The character at this index
- * is not included in the range.
+ * is not included in the range.
*
* The `PangoAttribute` structure represents the common portions of all
* attributes.
@@ -306,8 +241,8 @@ typedef enum {
struct _PangoAttribute
{
const PangoAttrClass *klass;
- guint start_index; /* in bytes */
- guint end_index; /* in bytes. The character at this index is not included */
+ guint start_index;
+ guint end_index;
};
/**
@@ -321,7 +256,7 @@ struct _PangoAttribute
* filtering, %FALSE otherwise.
*/
typedef gboolean (*PangoAttrFilterFunc) (PangoAttribute *attribute,
- gpointer user_data);
+ gpointer user_data);
/**
* PangoAttrDataCopyFunc:
@@ -498,234 +433,229 @@ struct _PangoAttrFontFeatures
};
PANGO_AVAILABLE_IN_ALL
-PangoAttrType pango_attr_type_register (const gchar *name);
-PANGO_AVAILABLE_IN_1_22
-const char * pango_attr_type_get_name (PangoAttrType type) G_GNUC_CONST;
+GType pango_attribute_get_type (void) G_GNUC_CONST;
+PANGO_AVAILABLE_IN_ALL
+PangoAttrType pango_attr_type_register (const char *name);
+PANGO_AVAILABLE_IN_1_22
+const char * pango_attr_type_get_name (PangoAttrType type) G_GNUC_CONST;
PANGO_AVAILABLE_IN_1_20
-void pango_attribute_init (PangoAttribute *attr,
- const PangoAttrClass *klass);
+void pango_attribute_init (PangoAttribute *attr,
+ const PangoAttrClass *klass);
PANGO_AVAILABLE_IN_ALL
-PangoAttribute * pango_attribute_copy (const PangoAttribute *attr);
+PangoAttribute * pango_attribute_copy (const PangoAttribute *attr);
PANGO_AVAILABLE_IN_ALL
-void pango_attribute_destroy (PangoAttribute *attr);
+void pango_attribute_destroy (PangoAttribute *attr);
PANGO_AVAILABLE_IN_ALL
-gboolean pango_attribute_equal (const PangoAttribute *attr1,
- const PangoAttribute *attr2) G_GNUC_PURE;
+gboolean pango_attribute_equal (const PangoAttribute *attr1,
+ const PangoAttribute *attr2) G_GNUC_PURE;
PANGO_AVAILABLE_IN_ALL
-PangoAttribute *pango_attr_language_new (PangoLanguage *language);
+PangoAttribute * pango_attr_language_new (PangoLanguage *language);
PANGO_AVAILABLE_IN_ALL
-PangoAttribute *pango_attr_family_new (const char *family);
+PangoAttribute * pango_attr_family_new (const char *family);
PANGO_AVAILABLE_IN_ALL
-PangoAttribute *pango_attr_foreground_new (guint16 red,
- guint16 green,
- guint16 blue);
+PangoAttribute * pango_attr_foreground_new (guint16 red,
+ guint16 green,
+ guint16 blue);
PANGO_AVAILABLE_IN_ALL
-PangoAttribute *pango_attr_background_new (guint16 red,
- guint16 green,
- guint16 blue);
+PangoAttribute * pango_attr_background_new (guint16 red,
+ guint16 green,
+ guint16 blue);
PANGO_AVAILABLE_IN_ALL
-PangoAttribute *pango_attr_size_new (int size);
+PangoAttribute * pango_attr_size_new (int size);
PANGO_AVAILABLE_IN_1_8
-PangoAttribute *pango_attr_size_new_absolute (int size);
+PangoAttribute * pango_attr_size_new_absolute (int size);
PANGO_AVAILABLE_IN_ALL
-PangoAttribute *pango_attr_style_new (PangoStyle style);
+PangoAttribute * pango_attr_style_new (PangoStyle style);
PANGO_AVAILABLE_IN_ALL
-PangoAttribute *pango_attr_weight_new (PangoWeight weight);
+PangoAttribute * pango_attr_weight_new (PangoWeight weight);
PANGO_AVAILABLE_IN_ALL
-PangoAttribute *pango_attr_variant_new (PangoVariant variant);
+PangoAttribute * pango_attr_variant_new (PangoVariant variant);
PANGO_AVAILABLE_IN_ALL
-PangoAttribute *pango_attr_stretch_new (PangoStretch stretch);
+PangoAttribute * pango_attr_stretch_new (PangoStretch stretch);
PANGO_AVAILABLE_IN_ALL
-PangoAttribute *pango_attr_font_desc_new (const PangoFontDescription *desc);
+PangoAttribute * pango_attr_font_desc_new (const PangoFontDescription *desc);
PANGO_AVAILABLE_IN_ALL
-PangoAttribute *pango_attr_underline_new (PangoUnderline underline);
+PangoAttribute * pango_attr_underline_new (PangoUnderline underline);
PANGO_AVAILABLE_IN_1_8
-PangoAttribute *pango_attr_underline_color_new (guint16 red,
- guint16 green,
- guint16 blue);
+PangoAttribute * pango_attr_underline_color_new (guint16 red,
+ guint16 green,
+ guint16 blue);
PANGO_AVAILABLE_IN_ALL
-PangoAttribute *pango_attr_strikethrough_new (gboolean strikethrough);
+PangoAttribute * pango_attr_strikethrough_new (gboolean strikethrough);
PANGO_AVAILABLE_IN_1_8
-PangoAttribute *pango_attr_strikethrough_color_new (guint16 red,
- guint16 green,
- guint16 blue);
-
+PangoAttribute * pango_attr_strikethrough_color_new (guint16 red,
+ guint16 green,
+ guint16 blue);
PANGO_AVAILABLE_IN_ALL
-PangoAttribute *pango_attr_rise_new (int rise);
+PangoAttribute * pango_attr_rise_new (int rise);
PANGO_AVAILABLE_IN_ALL
-PangoAttribute *pango_attr_scale_new (double scale_factor);
+PangoAttribute * pango_attr_scale_new (double scale_factor);
PANGO_AVAILABLE_IN_1_4
-PangoAttribute *pango_attr_fallback_new (gboolean enable_fallback);
+PangoAttribute * pango_attr_fallback_new (gboolean enable_fallback);
PANGO_AVAILABLE_IN_1_6
-PangoAttribute *pango_attr_letter_spacing_new (int letter_spacing);
-
+PangoAttribute * pango_attr_letter_spacing_new (int letter_spacing);
PANGO_AVAILABLE_IN_ALL
-PangoAttribute *pango_attr_shape_new (const PangoRectangle *ink_rect,
- const PangoRectangle *logical_rect);
+PangoAttribute * pango_attr_shape_new (const PangoRectangle *ink_rect,
+ const PangoRectangle *logical_rect);
PANGO_AVAILABLE_IN_1_8
-PangoAttribute *pango_attr_shape_new_with_data (const PangoRectangle *ink_rect,
- const PangoRectangle *logical_rect,
- gpointer data,
- PangoAttrDataCopyFunc copy_func,
- GDestroyNotify destroy_func);
-
+PangoAttribute * pango_attr_shape_new_with_data (const PangoRectangle *ink_rect,
+ const PangoRectangle *logical_rect,
+ gpointer data,
+ PangoAttrDataCopyFunc copy_func,
+ GDestroyNotify destroy_func);
PANGO_AVAILABLE_IN_1_16
-PangoAttribute *pango_attr_gravity_new (PangoGravity gravity);
+PangoAttribute * pango_attr_gravity_new (PangoGravity gravity);
PANGO_AVAILABLE_IN_1_16
-PangoAttribute *pango_attr_gravity_hint_new (PangoGravityHint hint);
+PangoAttribute * pango_attr_gravity_hint_new (PangoGravityHint hint);
PANGO_AVAILABLE_IN_1_38
-PangoAttribute *pango_attr_font_features_new (const gchar *features);
+PangoAttribute * pango_attr_font_features_new (const char *features);
PANGO_AVAILABLE_IN_1_38
-PangoAttribute *pango_attr_foreground_alpha_new (guint16 alpha);
+PangoAttribute * pango_attr_foreground_alpha_new (guint16 alpha);
PANGO_AVAILABLE_IN_1_38
-PangoAttribute *pango_attr_background_alpha_new (guint16 alpha);
+PangoAttribute * pango_attr_background_alpha_new (guint16 alpha);
PANGO_AVAILABLE_IN_1_44
-PangoAttribute *pango_attr_allow_breaks_new (gboolean allow_breaks);
+PangoAttribute * pango_attr_allow_breaks_new (gboolean allow_breaks);
PANGO_AVAILABLE_IN_1_44
-PangoAttribute *pango_attr_insert_hyphens_new (gboolean insert_hyphens);
-
+PangoAttribute * pango_attr_insert_hyphens_new (gboolean insert_hyphens);
PANGO_AVAILABLE_IN_1_46
-PangoAttribute *pango_attr_overline_new (PangoOverline overline);
+PangoAttribute * pango_attr_overline_new (PangoOverline overline);
PANGO_AVAILABLE_IN_1_46
-PangoAttribute *pango_attr_overline_color_new (guint16 red,
- guint16 green,
- guint16 blue);
+PangoAttribute * pango_attr_overline_color_new (guint16 red,
+ guint16 green,
+ guint16 blue);
+PANGO_AVAILABLE_IN_1_44
+PangoAttribute * pango_attr_show_new (PangoShowFlags flags);
+PANGO_AVAILABLE_IN_1_50
+PangoAttribute * pango_attr_line_height_new (double factor);
+PANGO_AVAILABLE_IN_1_50
+PangoAttribute * pango_attr_line_height_new_absolute (int height);
+
+PANGO_AVAILABLE_IN_1_50
+PangoAttrString * pango_attribute_as_string (PangoAttribute *attr);
+PANGO_AVAILABLE_IN_1_50
+PangoAttrLanguage * pango_attribute_as_language (PangoAttribute *attr);
+PANGO_AVAILABLE_IN_1_50
+PangoAttrInt * pango_attribute_as_int (PangoAttribute *attr);
+PANGO_AVAILABLE_IN_1_50
+PangoAttrSize * pango_attribute_as_size (PangoAttribute *attr);
+PANGO_AVAILABLE_IN_1_50
+PangoAttrFloat * pango_attribute_as_float (PangoAttribute *attr);
+PANGO_AVAILABLE_IN_1_50
+PangoAttrColor * pango_attribute_as_color (PangoAttribute *attr);
+PANGO_AVAILABLE_IN_1_50
+PangoAttrFontDesc * pango_attribute_as_font_desc (PangoAttribute *attr);
+PANGO_AVAILABLE_IN_1_50
+PangoAttrShape * pango_attribute_as_shape (PangoAttribute *attr);
+PANGO_AVAILABLE_IN_1_50
+PangoAttrFontFeatures * pango_attribute_as_font_features (PangoAttribute *attr);
+
+/* Attribute lists */
+
+typedef struct _PangoAttrList PangoAttrList;
+typedef struct _PangoAttrIterator PangoAttrIterator;
+
+#define PANGO_TYPE_ATTR_LIST pango_attr_list_get_type ()
/**
- * PangoShowFlags:
- * @PANGO_SHOW_NONE: No special treatment for invisible characters
- * @PANGO_SHOW_SPACES: Render spaces, tabs and newlines visibly
- * @PANGO_SHOW_LINE_BREAKS: Render line breaks visibly
- * @PANGO_SHOW_IGNORABLES: Render default-ignorable Unicode
- * characters visibly
+ * PangoAttrIterator:
*
- * These flags affect how Pango treats characters that are normally
- * not visible in the output.
+ * A `PangoAttrIterator` is used to iterate through a `PangoAttrList`.
+ *
+ * A new iterator is created with [method@Pango.AttrList.get_iterator].
+ * Once the iterator is created, it can be advanced through the style
+ * changes in the text using [method@Pango.AttrIterator.next]. At each
+ * style change, the range of the current style segment and the attributes
+ * currently in effect can be queried.
*/
-typedef enum {
- PANGO_SHOW_NONE = 0,
- PANGO_SHOW_SPACES = 1 << 0,
- PANGO_SHOW_LINE_BREAKS = 1 << 1,
- PANGO_SHOW_IGNORABLES = 1 << 2
-} PangoShowFlags;
-PANGO_AVAILABLE_IN_1_44
-PangoAttribute *pango_attr_show_new (PangoShowFlags flags);
-
-PANGO_AVAILABLE_IN_1_50
-PangoAttribute *pango_attr_line_height_new (double factor);
-PANGO_AVAILABLE_IN_1_50
-PangoAttribute *pango_attr_line_height_new_absolute (int height);
+/**
+ * PangoAttrList:
+ *
+ * A `PangoAttrList` represents a list of attributes that apply to a section
+ * of text.
+ *
+ * The attributes in a `PangoAttrList` are, in general, allowed to overlap in
+ * an arbitrary fashion. However, if the attributes are manipulated only through
+ * [method@Pango.AttrList.change], the overlap between properties will meet
+ * stricter criteria.
+ *
+ * Since the `PangoAttrList` structure is stored as a linear list, it is not
+ * suitable for storing attributes for large amounts of text. In general, you
+ * should not use a single `PangoAttrList` for more than one paragraph of text.
+ */
PANGO_AVAILABLE_IN_ALL
-GType pango_attr_list_get_type (void) G_GNUC_CONST;
+GType pango_attr_list_get_type (void) G_GNUC_CONST;
+
PANGO_AVAILABLE_IN_ALL
-PangoAttrList * pango_attr_list_new (void);
+PangoAttrList * pango_attr_list_new (void);
PANGO_AVAILABLE_IN_1_10
-PangoAttrList * pango_attr_list_ref (PangoAttrList *list);
+PangoAttrList * pango_attr_list_ref (PangoAttrList *list);
PANGO_AVAILABLE_IN_ALL
-void pango_attr_list_unref (PangoAttrList *list);
+void pango_attr_list_unref (PangoAttrList *list);
PANGO_AVAILABLE_IN_ALL
-PangoAttrList * pango_attr_list_copy (PangoAttrList *list);
+PangoAttrList * pango_attr_list_copy (PangoAttrList *list);
PANGO_AVAILABLE_IN_ALL
-void pango_attr_list_insert (PangoAttrList *list,
- PangoAttribute *attr);
+void pango_attr_list_insert (PangoAttrList *list,
+ PangoAttribute *attr);
PANGO_AVAILABLE_IN_ALL
-void pango_attr_list_insert_before (PangoAttrList *list,
- PangoAttribute *attr);
+void pango_attr_list_insert_before (PangoAttrList *list,
+ PangoAttribute *attr);
PANGO_AVAILABLE_IN_ALL
-void pango_attr_list_change (PangoAttrList *list,
- PangoAttribute *attr);
+void pango_attr_list_change (PangoAttrList *list,
+ PangoAttribute *attr);
PANGO_AVAILABLE_IN_ALL
-void pango_attr_list_splice (PangoAttrList *list,
- PangoAttrList *other,
- gint pos,
- gint len);
+void pango_attr_list_splice (PangoAttrList *list,
+ PangoAttrList *other,
+ int pos,
+ int len);
PANGO_AVAILABLE_IN_1_44
-void pango_attr_list_update (PangoAttrList *list,
- int pos,
- int remove,
- int add);
+void pango_attr_list_update (PangoAttrList *list,
+ int pos,
+ int remove,
+ int add);
PANGO_AVAILABLE_IN_1_2
-PangoAttrList *pango_attr_list_filter (PangoAttrList *list,
- PangoAttrFilterFunc func,
- gpointer data);
+PangoAttrList * pango_attr_list_filter (PangoAttrList *list,
+ PangoAttrFilterFunc func,
+ gpointer data);
PANGO_AVAILABLE_IN_1_44
-GSList *pango_attr_list_get_attributes (PangoAttrList *list);
+GSList * pango_attr_list_get_attributes (PangoAttrList *list);
PANGO_AVAILABLE_IN_1_46
-gboolean pango_attr_list_equal (PangoAttrList *list,
- PangoAttrList *other_list);
+gboolean pango_attr_list_equal (PangoAttrList *list,
+ PangoAttrList *other_list);
PANGO_AVAILABLE_IN_1_44
-GType pango_attr_iterator_get_type (void) G_GNUC_CONST;
+GType pango_attr_iterator_get_type (void) G_GNUC_CONST;
PANGO_AVAILABLE_IN_ALL
-PangoAttrIterator *pango_attr_list_get_iterator (PangoAttrList *list);
+PangoAttrIterator * pango_attr_list_get_iterator (PangoAttrList *list);
PANGO_AVAILABLE_IN_ALL
-void pango_attr_iterator_range (PangoAttrIterator *iterator,
- gint *start,
- gint *end);
+void pango_attr_iterator_range (PangoAttrIterator *iterator,
+ int *start,
+ int *end);
PANGO_AVAILABLE_IN_ALL
-gboolean pango_attr_iterator_next (PangoAttrIterator *iterator);
+gboolean pango_attr_iterator_next (PangoAttrIterator *iterator);
PANGO_AVAILABLE_IN_ALL
-PangoAttrIterator *pango_attr_iterator_copy (PangoAttrIterator *iterator);
+PangoAttrIterator * pango_attr_iterator_copy (PangoAttrIterator *iterator);
PANGO_AVAILABLE_IN_ALL
-void pango_attr_iterator_destroy (PangoAttrIterator *iterator);
+void pango_attr_iterator_destroy (PangoAttrIterator *iterator);
PANGO_AVAILABLE_IN_ALL
-PangoAttribute * pango_attr_iterator_get (PangoAttrIterator *iterator,
- PangoAttrType type);
+PangoAttribute * pango_attr_iterator_get (PangoAttrIterator *iterator,
+ PangoAttrType type);
PANGO_AVAILABLE_IN_ALL
-void pango_attr_iterator_get_font (PangoAttrIterator *iterator,
- PangoFontDescription *desc,
- PangoLanguage **language,
- GSList **extra_attrs);
+void pango_attr_iterator_get_font (PangoAttrIterator *iterator,
+ PangoFontDescription *desc,
+ PangoLanguage **language,
+ GSList **extra_attrs);
PANGO_AVAILABLE_IN_1_2
-GSList * pango_attr_iterator_get_attrs (PangoAttrIterator *iterator);
-
-
-PANGO_AVAILABLE_IN_ALL
-gboolean pango_parse_markup (const char *markup_text,
- int length,
- gunichar accel_marker,
- PangoAttrList **attr_list,
- char **text,
- gunichar *accel_char,
- GError **error);
-
-PANGO_AVAILABLE_IN_1_32
-GMarkupParseContext * pango_markup_parser_new (gunichar accel_marker);
-PANGO_AVAILABLE_IN_1_32
-gboolean pango_markup_parser_finish (GMarkupParseContext *context,
- PangoAttrList **attr_list,
- char **text,
- gunichar *accel_char,
- GError **error);
-
-PANGO_AVAILABLE_IN_1_50
-PangoAttrString *pango_attribute_as_string (PangoAttribute *attr);
-PANGO_AVAILABLE_IN_1_50
-PangoAttrLanguage *pango_attribute_as_language (PangoAttribute *attr);
-PANGO_AVAILABLE_IN_1_50
-PangoAttrInt *pango_attribute_as_int (PangoAttribute *attr);
-PANGO_AVAILABLE_IN_1_50
-PangoAttrSize *pango_attribute_as_size (PangoAttribute *attr);
-PANGO_AVAILABLE_IN_1_50
-PangoAttrFloat *pango_attribute_as_float (PangoAttribute *attr);
-PANGO_AVAILABLE_IN_1_50
-PangoAttrColor *pango_attribute_as_color (PangoAttribute *attr);
-PANGO_AVAILABLE_IN_1_50
-PangoAttrFontDesc *pango_attribute_as_font_desc (PangoAttribute *attr);
-PANGO_AVAILABLE_IN_1_50
-PangoAttrShape *pango_attribute_as_shape (PangoAttribute *attr);
-PANGO_AVAILABLE_IN_1_50
-PangoAttrFontFeatures *pango_attribute_as_font_features (PangoAttribute *attr);
+GSList * pango_attr_iterator_get_attrs (PangoAttrIterator *iterator);
G_END_DECLS
diff --git a/pango/pango-break.h b/pango/pango-break.h
index 16f3918c..81526e9a 100644
--- a/pango/pango-break.h
+++ b/pango/pango-break.h
@@ -10,7 +10,7 @@
*
* 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
+ * 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
@@ -94,45 +94,34 @@ struct _PangoLogAttr
};
PANGO_DEPRECATED_IN_1_44
-void pango_break (const gchar *text,
- int length,
- PangoAnalysis *analysis,
- PangoLogAttr *attrs,
- int attrs_len);
+void pango_break (const char *text,
+ int length,
+ PangoAnalysis *analysis,
+ PangoLogAttr *attrs,
+ int attrs_len);
PANGO_AVAILABLE_IN_ALL
-void pango_find_paragraph_boundary (const gchar *text,
- gint length,
- gint *paragraph_delimiter_index,
- gint *next_paragraph_start);
+void pango_get_log_attrs (const char *text,
+ int length,
+ int level,
+ PangoLanguage *language,
+ PangoLogAttr *log_attrs,
+ int attrs_len);
PANGO_AVAILABLE_IN_ALL
-void pango_get_log_attrs (const char *text,
- int length,
- int level,
- PangoLanguage *language,
- PangoLogAttr *log_attrs,
- int attrs_len);
-
-/* This is the default break algorithm, used if no language
- * engine overrides it. Normally you should use pango_break()
- * instead; this function is mostly useful for chaining up
- * from a language engine override.
- */
-PANGO_AVAILABLE_IN_ALL
-void pango_default_break (const gchar *text,
- int length,
- PangoAnalysis *analysis,
- PangoLogAttr *attrs,
- int attrs_len);
+void pango_default_break (const char *text,
+ int length,
+ PangoAnalysis *analysis,
+ PangoLogAttr *attrs,
+ int attrs_len);
PANGO_AVAILABLE_IN_1_44
-void pango_tailor_break (const char *text,
- int length,
- PangoAnalysis *analysis,
- int offset,
- PangoLogAttr *log_attrs,
- int log_attrs_len);
+void pango_tailor_break (const char *text,
+ int length,
+ PangoAnalysis *analysis,
+ int offset,
+ PangoLogAttr *log_attrs,
+ int log_attrs_len);
G_END_DECLS
diff --git a/pango/pango-color.h b/pango/pango-color.h
new file mode 100644
index 00000000..675d8e82
--- /dev/null
+++ b/pango/pango-color.h
@@ -0,0 +1,75 @@
+/* Pango
+ * pango-color.h: A color struct
+ *
+ * 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_COLOR_H__
+#define __PANGO_COLOR_H__
+
+#include <pango/pango-types.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _PangoColor PangoColor;
+
+/**
+ * PangoColor:
+ * @red: value of red component
+ * @green: value of green component
+ * @blue: value of blue component
+ *
+ * The `PangoColor` structure is used to
+ * represent a color in an uncalibrated RGB color-space.
+ */
+struct _PangoColor
+{
+ guint16 red;
+ guint16 green;
+ guint16 blue;
+};
+
+#define PANGO_TYPE_COLOR (pango_color_get_type ())
+
+PANGO_AVAILABLE_IN_ALL
+GType pango_color_get_type (void) G_GNUC_CONST;
+
+PANGO_AVAILABLE_IN_ALL
+PangoColor *pango_color_copy (const PangoColor *src);
+
+PANGO_AVAILABLE_IN_ALL
+void pango_color_free (PangoColor *color);
+
+PANGO_AVAILABLE_IN_ALL
+gboolean pango_color_parse (PangoColor *color,
+ const char *spec);
+
+PANGO_AVAILABLE_IN_1_46
+gboolean pango_color_parse_with_alpha (PangoColor *color,
+ guint16 *alpha,
+ const char *spec);
+
+PANGO_AVAILABLE_IN_1_16
+char *pango_color_to_string (const PangoColor *color);
+
+
+G_END_DECLS
+
+#endif /* __PANGO_COLOR_H__ */
diff --git a/pango/pango-context-private.h b/pango/pango-context-private.h
new file mode 100644
index 00000000..240c07d4
--- /dev/null
+++ b/pango/pango-context-private.h
@@ -0,0 +1,63 @@
+/* Pango
+ * pango-context-private.h: Internal structures of PangoContext
+ *
+ * Copyright (C) 2004 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_CONTEXT_PRIVATE_H__
+#define __PANGO_CONTEXT_PRIVATE_H__
+
+#include <pango/pango-context.h>
+
+G_BEGIN_DECLS
+
+struct _PangoContext
+{
+ GObject parent_instance;
+ guint serial;
+ guint fontmap_serial;
+
+ PangoLanguage *set_language;
+ PangoLanguage *language;
+ PangoDirection base_dir;
+ PangoGravity base_gravity;
+ PangoGravity resolved_gravity;
+ PangoGravityHint gravity_hint;
+
+ PangoFontDescription *font_desc;
+
+ PangoMatrix *matrix;
+
+ PangoFontMap *font_map;
+
+ PangoFontMetrics *metrics;
+
+ gboolean round_glyph_positions;
+};
+
+GList * pango_itemize_with_font (PangoContext *context,
+ const char *text,
+ int start_index,
+ int length,
+ const PangoFontDescription *desc);
+
+
+G_END_DECLS
+
+#endif /* __PANGO_CONTEXT_PRIVATE_H__ */
+
diff --git a/pango/pango-context.c b/pango/pango-context.c
index 2cb3304c..d76b0ae2 100644
--- a/pango/pango-context.c
+++ b/pango/pango-context.c
@@ -24,6 +24,7 @@
#include <stdlib.h>
#include "pango-context.h"
+#include "pango-context-private.h"
#include "pango-impl-utils.h"
#include "pango-font-private.h"
@@ -44,29 +45,6 @@
*
* To obtain a `PangoContext`, use [method@Pango.FontMap.create_context].
*/
-struct _PangoContext
-{
- GObject parent_instance;
- guint serial;
- guint fontmap_serial;
-
- PangoLanguage *set_language;
- PangoLanguage *language;
- PangoDirection base_dir;
- PangoGravity base_gravity;
- PangoGravity resolved_gravity;
- PangoGravityHint gravity_hint;
-
- PangoFontDescription *font_desc;
-
- PangoMatrix *matrix;
-
- PangoFontMap *font_map;
-
- PangoFontMetrics *metrics;
-
- gboolean round_glyph_positions;
-};
struct _PangoContextClass
{
@@ -595,1133 +573,6 @@ pango_context_get_gravity_hint (PangoContext *context)
return context->gravity_hint;
}
-/**********************************************************************/
-
-static gboolean
-advance_attr_iterator_to (PangoAttrIterator *iterator,
- int start_index)
-{
- int start_range, end_range;
-
- pango_attr_iterator_range (iterator, &start_range, &end_range);
-
- while (start_index >= end_range)
- {
- if (!pango_attr_iterator_next (iterator))
- return FALSE;
- pango_attr_iterator_range (iterator, &start_range, &end_range);
- }
-
- if (start_range > start_index)
- g_warning ("In pango_itemize(), the cached iterator passed in "
- "had already moved beyond the start_index");
-
- return TRUE;
-}
-
-/***************************************************************************
- * We cache the results of character,fontset => font in a hash table
- ***************************************************************************/
-
-typedef struct {
- GHashTable *hash;
-} FontCache;
-
-typedef struct {
- PangoFont *font;
- int position; /* position of the font in the fontset */
-} FontElement;
-
-static void
-font_cache_destroy (FontCache *cache)
-{
- g_hash_table_destroy (cache->hash);
- g_slice_free (FontCache, cache);
-}
-
-static void
-font_element_destroy (FontElement *element)
-{
- if (element->font)
- g_object_unref (element->font);
- g_slice_free (FontElement, element);
-}
-
-static FontCache *
-get_font_cache (PangoFontset *fontset)
-{
- FontCache *cache;
-
- static GQuark cache_quark = 0; /* MT-safe */
- if (G_UNLIKELY (!cache_quark))
- cache_quark = g_quark_from_static_string ("pango-font-cache");
-
-retry:
- cache = g_object_get_qdata (G_OBJECT (fontset), cache_quark);
- if (G_UNLIKELY (!cache))
- {
- cache = g_slice_new (FontCache);
- cache->hash = g_hash_table_new_full (g_direct_hash, NULL,
- NULL, (GDestroyNotify)font_element_destroy);
- if (!g_object_replace_qdata (G_OBJECT (fontset), cache_quark, NULL,
- cache, (GDestroyNotify)font_cache_destroy,
- NULL))
- {
- font_cache_destroy (cache);
- goto retry;
- }
- }
-
- return cache;
-}
-
-static gboolean
-font_cache_get (FontCache *cache,
- gunichar wc,
- PangoFont **font,
- int *position)
-{
- FontElement *element;
-
- element = g_hash_table_lookup (cache->hash, GUINT_TO_POINTER (wc));
- if (element)
- {
- *font = element->font;
- *position = element->position;
- return TRUE;
- }
- else
- return FALSE;
-}
-
-static void
-font_cache_insert (FontCache *cache,
- gunichar wc,
- PangoFont *font,
- int position)
-{
- FontElement *element = g_slice_new (FontElement);
- element->font = font ? g_object_ref (font) : NULL;
- element->position = position;
-
- g_hash_table_insert (cache->hash, GUINT_TO_POINTER (wc), element);
-}
-
-/**********************************************************************/
-
-typedef enum {
- EMBEDDING_CHANGED = 1 << 0,
- SCRIPT_CHANGED = 1 << 1,
- LANG_CHANGED = 1 << 2,
- FONT_CHANGED = 1 << 3,
- DERIVED_LANG_CHANGED = 1 << 4,
- WIDTH_CHANGED = 1 << 5,
- EMOJI_CHANGED = 1 << 6,
-} ChangedFlags;
-
-
-
-typedef struct _PangoWidthIter PangoWidthIter;
-
-struct _PangoWidthIter
-{
- const gchar *text_start;
- const gchar *text_end;
- const gchar *start;
- const gchar *end;
- gboolean upright;
-};
-
-typedef struct _ItemizeState ItemizeState;
-
-
-
-struct _ItemizeState
-{
- PangoContext *context;
- const char *text;
- const char *end;
-
- const char *run_start;
- const char *run_end;
-
- GList *result;
- PangoItem *item;
-
- guint8 *embedding_levels;
- int embedding_end_offset;
- const char *embedding_end;
- guint8 embedding;
-
- PangoGravity gravity;
- PangoGravityHint gravity_hint;
- PangoGravity resolved_gravity;
- PangoGravity font_desc_gravity;
- gboolean centered_baseline;
-
- PangoAttrIterator *attr_iter;
- gboolean free_attr_iter;
- const char *attr_end;
- PangoFontDescription *font_desc;
- PangoFontDescription *emoji_font_desc;
- PangoLanguage *lang;
- GSList *extra_attrs;
- gboolean copy_extra_attrs;
-
- ChangedFlags changed;
-
- PangoScriptIter script_iter;
- const char *script_end;
- PangoScript script;
-
- PangoWidthIter width_iter;
- PangoEmojiIter emoji_iter;
-
- PangoLanguage *derived_lang;
-
- PangoFontset *current_fonts;
- FontCache *cache;
- PangoFont *base_font;
- gboolean enable_fallback;
-
- const char *first_space; /* first of a sequence of spaces we've seen */
- int font_position; /* position of the current font in the fontset */
-};
-
-static void
-update_embedding_end (ItemizeState *state)
-{
- state->embedding = state->embedding_levels[state->embedding_end_offset];
- while (state->embedding_end < state->end &&
- state->embedding_levels[state->embedding_end_offset] == state->embedding)
- {
- state->embedding_end_offset++;
- state->embedding_end = g_utf8_next_char (state->embedding_end);
- }
-
- state->changed |= EMBEDDING_CHANGED;
-}
-
-static PangoAttribute *
-find_attribute (GSList *attr_list,
- PangoAttrType type)
-{
- GSList *node;
-
- for (node = attr_list; node; node = node->next)
- if (((PangoAttribute *) node->data)->klass->type == type)
- return (PangoAttribute *) node->data;
-
- return NULL;
-}
-
-static void
-update_attr_iterator (ItemizeState *state)
-{
- PangoLanguage *old_lang;
- PangoAttribute *attr;
- int end_index;
-
- pango_attr_iterator_range (state->attr_iter, NULL, &end_index);
- if (end_index < state->end - state->text)
- state->attr_end = state->text + end_index;
- else
- state->attr_end = state->end;
-
- if (state->emoji_font_desc)
- {
- pango_font_description_free (state->emoji_font_desc);
- state->emoji_font_desc = NULL;
- }
-
- old_lang = state->lang;
- if (state->font_desc)
- pango_font_description_free (state->font_desc);
- state->font_desc = pango_font_description_copy_static (state->context->font_desc);
- pango_attr_iterator_get_font (state->attr_iter, state->font_desc,
- &state->lang, &state->extra_attrs);
- if (pango_font_description_get_set_fields (state->font_desc) & PANGO_FONT_MASK_GRAVITY)
- state->font_desc_gravity = pango_font_description_get_gravity (state->font_desc);
- else
- state->font_desc_gravity = PANGO_GRAVITY_AUTO;
-
- state->copy_extra_attrs = FALSE;
-
- if (!state->lang)
- state->lang = state->context->language;
-
- attr = find_attribute (state->extra_attrs, PANGO_ATTR_FALLBACK);
- state->enable_fallback = (attr == NULL || ((PangoAttrInt *)attr)->value);
-
- attr = find_attribute (state->extra_attrs, PANGO_ATTR_GRAVITY);
- state->gravity = attr == NULL ? PANGO_GRAVITY_AUTO : ((PangoAttrInt *)attr)->value;
-
- attr = find_attribute (state->extra_attrs, PANGO_ATTR_GRAVITY_HINT);
- state->gravity_hint = attr == NULL ? state->context->gravity_hint : (PangoGravityHint)((PangoAttrInt *)attr)->value;
-
- state->changed |= FONT_CHANGED;
- if (state->lang != old_lang)
- state->changed |= LANG_CHANGED;
-}
-
-static void
-update_end (ItemizeState *state)
-{
- state->run_end = state->embedding_end;
- if (state->attr_end < state->run_end)
- state->run_end = state->attr_end;
- if (state->script_end < state->run_end)
- state->run_end = state->script_end;
- if (state->width_iter.end < state->run_end)
- state->run_end = state->width_iter.end;
- if (state->emoji_iter.end < state->run_end)
- state->run_end = state->emoji_iter.end;
-}
-
-static gboolean
-width_iter_is_upright (gunichar ch)
-{
- /* https://www.unicode.org/Public/11.0.0/ucd/VerticalOrientation.txt
- * VO=U or Tu table generated by tools/gen-vertical-orientation-U-table.py.
- *
- * FIXME: In the future, If GLib supports VerticalOrientation, please use it.
- */
- static const gunichar upright[][2] = {
- {0x00A7, 0x00A7}, {0x00A9, 0x00A9}, {0x00AE, 0x00AE}, {0x00B1, 0x00B1},
- {0x00BC, 0x00BE}, {0x00D7, 0x00D7}, {0x00F7, 0x00F7}, {0x02EA, 0x02EB},
- {0x1100, 0x11FF}, {0x1401, 0x167F}, {0x18B0, 0x18FF}, {0x2016, 0x2016},
- {0x2020, 0x2021}, {0x2030, 0x2031}, {0x203B, 0x203C}, {0x2042, 0x2042},
- {0x2047, 0x2049}, {0x2051, 0x2051}, {0x2065, 0x2065}, {0x20DD, 0x20E0},
- {0x20E2, 0x20E4}, {0x2100, 0x2101}, {0x2103, 0x2109}, {0x210F, 0x210F},
- {0x2113, 0x2114}, {0x2116, 0x2117}, {0x211E, 0x2123}, {0x2125, 0x2125},
- {0x2127, 0x2127}, {0x2129, 0x2129}, {0x212E, 0x212E}, {0x2135, 0x213F},
- {0x2145, 0x214A}, {0x214C, 0x214D}, {0x214F, 0x2189}, {0x218C, 0x218F},
- {0x221E, 0x221E}, {0x2234, 0x2235}, {0x2300, 0x2307}, {0x230C, 0x231F},
- {0x2324, 0x2328}, {0x232B, 0x232B}, {0x237D, 0x239A}, {0x23BE, 0x23CD},
- {0x23CF, 0x23CF}, {0x23D1, 0x23DB}, {0x23E2, 0x2422}, {0x2424, 0x24FF},
- {0x25A0, 0x2619}, {0x2620, 0x2767}, {0x2776, 0x2793}, {0x2B12, 0x2B2F},
- {0x2B50, 0x2B59}, {0x2BB8, 0x2BD1}, {0x2BD3, 0x2BEB}, {0x2BF0, 0x2BFF},
- {0x2E80, 0x3007}, {0x3012, 0x3013}, {0x3020, 0x302F}, {0x3031, 0x309F},
- {0x30A1, 0x30FB}, {0x30FD, 0xA4CF}, {0xA960, 0xA97F}, {0xAC00, 0xD7FF},
- {0xE000, 0xFAFF}, {0xFE10, 0xFE1F}, {0xFE30, 0xFE48}, {0xFE50, 0xFE57},
- {0xFE5F, 0xFE62}, {0xFE67, 0xFE6F}, {0xFF01, 0xFF07}, {0xFF0A, 0xFF0C},
- {0xFF0E, 0xFF19}, {0xFF1F, 0xFF3A}, {0xFF3C, 0xFF3C}, {0xFF3E, 0xFF3E},
- {0xFF40, 0xFF5A}, {0xFFE0, 0xFFE2}, {0xFFE4, 0xFFE7}, {0xFFF0, 0xFFF8},
- {0xFFFC, 0xFFFD}, {0x10980, 0x1099F}, {0x11580, 0x115FF}, {0x11A00, 0x11AAF},
- {0x13000, 0x1342F}, {0x14400, 0x1467F}, {0x16FE0, 0x18AFF}, {0x1B000, 0x1B12F},
- {0x1B170, 0x1B2FF}, {0x1D000, 0x1D1FF}, {0x1D2E0, 0x1D37F}, {0x1D800, 0x1DAAF},
- {0x1F000, 0x1F7FF}, {0x1F900, 0x1FA6F}, {0x20000, 0x2FFFD}, {0x30000, 0x3FFFD},
- {0xF0000, 0xFFFFD}, {0x100000, 0x10FFFD}
- };
- static const int max = sizeof(upright) / sizeof(upright[0]);
- int st = 0;
- int ed = max;
-
- if (ch < upright[0][0])
- return FALSE;
-
- while (st <= ed)
- {
- int mid = (st + ed) / 2;
- if (upright[mid][0] <= ch && ch <= upright[mid][1])
- return TRUE;
- else
- if (upright[mid][0] <= ch)
- st = mid + 1;
- else
- ed = mid - 1;
- }
-
- return FALSE;
-}
-
-static void
-width_iter_next (PangoWidthIter *iter)
-{
- gboolean met_joiner = FALSE;
- iter->start = iter->end;
-
- if (iter->end < iter->text_end)
- {
- gunichar ch = g_utf8_get_char (iter->end);
- iter->upright = width_iter_is_upright (ch);
- }
-
- while (iter->end < iter->text_end)
- {
- gunichar ch = g_utf8_get_char (iter->end);
-
- /* for zero width joiner */
- if (ch == 0x200D)
- {
- iter->end = g_utf8_next_char (iter->end);
- met_joiner = TRUE;
- continue;
- }
-
- /* ignore the upright check if met joiner */
- if (met_joiner)
- {
- iter->end = g_utf8_next_char (iter->end);
- met_joiner = FALSE;
- continue;
- }
-
- /* for variation selector, tag and emoji modifier. */
- if (G_UNLIKELY (ch == 0xFE0EU || ch == 0xFE0FU ||
- (ch >= 0xE0020 && ch <= 0xE007F) ||
- (ch >= 0x1F3FB && ch <= 0x1F3FF)))
- {
- iter->end = g_utf8_next_char (iter->end);
- continue;
- }
-
- if (width_iter_is_upright (ch) != iter->upright)
- break;
-
- iter->end = g_utf8_next_char (iter->end);
- }
-}
-
-static void
-width_iter_init (PangoWidthIter *iter,
- const char *text,
- int length)
-{
- iter->text_start = text;
- iter->text_end = text + length;
- iter->start = iter->end = text;
-
- width_iter_next (iter);
-}
-
-static void
-width_iter_fini (PangoWidthIter* iter)
-{
-}
-
-static void
-itemize_state_init (ItemizeState *state,
- PangoContext *context,
- const char *text,
- PangoDirection base_dir,
- int start_index,
- int length,
- PangoAttrList *attrs,
- PangoAttrIterator *cached_iter,
- const PangoFontDescription *desc)
-{
- state->context = context;
- state->text = text;
- state->end = text + start_index + length;
-
- state->result = NULL;
- state->item = NULL;
-
- state->run_start = text + start_index;
- state->changed = EMBEDDING_CHANGED | SCRIPT_CHANGED | LANG_CHANGED |
- FONT_CHANGED | WIDTH_CHANGED | EMOJI_CHANGED;
-
- /* First, apply the bidirectional algorithm to break
- * the text into directional runs.
- */
- state->embedding_levels = pango_log2vis_get_embedding_levels (text + start_index, length, &base_dir);
-
- state->embedding_end_offset = 0;
- state->embedding_end = text + start_index;
- update_embedding_end (state);
-
- state->gravity = PANGO_GRAVITY_AUTO;
- state->centered_baseline = PANGO_GRAVITY_IS_VERTICAL (state->context->resolved_gravity);
- state->gravity_hint = state->context->gravity_hint;
- state->resolved_gravity = PANGO_GRAVITY_AUTO;
-
- /* Initialize the attribute iterator
- */
- if (cached_iter)
- {
- state->attr_iter = cached_iter;
- state->free_attr_iter = FALSE;
- }
- else if (attrs)
- {
- state->attr_iter = pango_attr_list_get_iterator (attrs);
- state->free_attr_iter = TRUE;
- }
- else
- {
- state->attr_iter = NULL;
- state->free_attr_iter = FALSE;
- }
-
- state->emoji_font_desc = NULL;
- if (state->attr_iter)
- {
- state->font_desc = NULL;
- state->lang = NULL;
-
- advance_attr_iterator_to (state->attr_iter, start_index);
- update_attr_iterator (state);
- }
- else
- {
- state->font_desc = pango_font_description_copy_static (desc ? desc : state->context->font_desc);
- state->lang = state->context->language;
- state->extra_attrs = NULL;
- state->copy_extra_attrs = FALSE;
-
- state->attr_end = state->end;
- state->enable_fallback = TRUE;
- }
-
- /* Initialize the script iterator
- */
- _pango_script_iter_init (&state->script_iter, text + start_index, length);
- pango_script_iter_get_range (&state->script_iter, NULL,
- &state->script_end, &state->script);
-
- width_iter_init (&state->width_iter, text + start_index, length);
- _pango_emoji_iter_init (&state->emoji_iter, text + start_index, length);
-
- if (!PANGO_GRAVITY_IS_VERTICAL (state->context->resolved_gravity))
- state->width_iter.end = state->end;
- else
- if (state->emoji_iter.is_emoji)
- state->width_iter.end = MAX (state->width_iter.end, state->emoji_iter.end);
-
- update_end (state);
-
- if (pango_font_description_get_set_fields (state->font_desc) & PANGO_FONT_MASK_GRAVITY)
- state->font_desc_gravity = pango_font_description_get_gravity (state->font_desc);
- else
- state->font_desc_gravity = PANGO_GRAVITY_AUTO;
-
- state->derived_lang = NULL;
- state->current_fonts = NULL;
- state->cache = NULL;
- state->base_font = NULL;
- state->first_space = NULL;
- state->font_position = 0xffff;
-}
-
-static gboolean
-itemize_state_next (ItemizeState *state)
-{
- if (state->run_end == state->end)
- return FALSE;
-
- state->changed = 0;
-
- state->run_start = state->run_end;
-
- if (state->run_end == state->embedding_end)
- {
- update_embedding_end (state);
- }
-
- if (state->run_end == state->attr_end)
- {
- pango_attr_iterator_next (state->attr_iter);
- update_attr_iterator (state);
- }
-
- if (state->run_end == state->script_end)
- {
- pango_script_iter_next (&state->script_iter);
- pango_script_iter_get_range (&state->script_iter, NULL,
- &state->script_end, &state->script);
- state->changed |= SCRIPT_CHANGED;
- }
- if (state->run_end == state->emoji_iter.end)
- {
- _pango_emoji_iter_next (&state->emoji_iter);
- state->changed |= EMOJI_CHANGED;
-
- if (state->emoji_iter.is_emoji)
- state->width_iter.end = MAX (state->width_iter.end, state->emoji_iter.end);
- }
- if (state->run_end == state->width_iter.end)
- {
- width_iter_next (&state->width_iter);
- state->changed |= WIDTH_CHANGED;
- }
-
- update_end (state);
-
- return TRUE;
-}
-
-static GSList *
-copy_attr_slist (GSList *attr_slist)
-{
- GSList *new_list = NULL;
- GSList *l;
-
- for (l = attr_slist; l; l = l->next)
- new_list = g_slist_prepend (new_list, pango_attribute_copy (l->data));
-
- return g_slist_reverse (new_list);
-}
-
-static void
-itemize_state_fill_font (ItemizeState *state,
- PangoFont *font)
-{
- GList *l;
-
- for (l = state->result; l; l = l->next)
- {
- PangoItem *item = l->data;
- if (item->analysis.font)
- break;
- if (font)
- item->analysis.font = g_object_ref (font);
- }
-}
-
-static void
-itemize_state_add_character (ItemizeState *state,
- PangoFont *font,
- int font_position,
- gboolean force_break,
- const char *pos,
- gboolean is_space)
-{
- const char *first_space = state->first_space;
- int n_spaces = 0;
-
- if (is_space)
- {
- if (state->first_space == NULL)
- state->first_space = pos;
- }
- else
- state->first_space = NULL;
-
- if (state->item)
- {
- if (!state->item->analysis.font && font)
- {
- itemize_state_fill_font (state, font);
- state->font_position = font_position;
- }
- else if (state->item->analysis.font && !font)
- {
- font = state->item->analysis.font;
- font_position = state->font_position;
- }
-
- if (!force_break &&
- state->item->analysis.font == font)
- {
- state->item->num_chars++;
- return;
- }
-
- /* Font is changing, we are about to end the current item.
- * If it ended in a sequence of spaces (but wasn't only spaces),
- * check if we should move those spaces to the new item (since
- * the font is less "fallback".
- *
- * See https://gitlab.gnome.org/GNOME/pango/-/issues/249
- */
- if (state->text + state->item->offset < first_space &&
- font_position < state->font_position)
- {
- n_spaces = g_utf8_strlen (first_space, pos - first_space);
- state->item->num_chars -= n_spaces;
- pos = first_space;
- }
-
- state->item->length = (pos - state->text) - state->item->offset;
- }
-
- state->item = pango_item_new ();
- state->item->offset = pos - state->text;
- state->item->length = 0;
- state->item->num_chars = n_spaces + 1;
-
- if (font)
- g_object_ref (font);
- state->item->analysis.font = font;
- state->font_position = font_position;
-
- state->item->analysis.level = state->embedding;
- state->item->analysis.gravity = state->resolved_gravity;
-
- /* The level vs. gravity dance:
- * - If gravity is SOUTH, leave level untouched.
- * - If gravity is NORTH, step level one up, to
- * not get mirrored upside-down text.
- * - If gravity is EAST, step up to an even level, as
- * it's a clockwise-rotated layout, so the rotated
- * top is unrotated left.
- * - If gravity is WEST, step up to an odd level, as
- * it's a counter-clockwise-rotated layout, so the rotated
- * top is unrotated right.
- *
- * A similar dance is performed in pango-layout.c:
- * line_set_resolved_dir(). Keep in synch.
- */
- switch (state->item->analysis.gravity)
- {
- case PANGO_GRAVITY_SOUTH:
- default:
- break;
- case PANGO_GRAVITY_NORTH:
- state->item->analysis.level++;
- break;
- case PANGO_GRAVITY_EAST:
- state->item->analysis.level += 1;
- state->item->analysis.level &= ~1;
- break;
- case PANGO_GRAVITY_WEST:
- state->item->analysis.level |= 1;
- break;
- }
-
- state->item->analysis.flags = state->centered_baseline ? PANGO_ANALYSIS_FLAG_CENTERED_BASELINE : 0;
-
- state->item->analysis.script = state->script;
- state->item->analysis.language = state->derived_lang;
-
- if (state->copy_extra_attrs)
- {
- state->item->analysis.extra_attrs = copy_attr_slist (state->extra_attrs);
- }
- else
- {
- state->item->analysis.extra_attrs = state->extra_attrs;
- state->copy_extra_attrs = TRUE;
- }
-
- state->result = g_list_prepend (state->result, state->item);
-}
-
-typedef struct {
- PangoLanguage *lang;
- gunichar wc;
- PangoFont *font;
- int position;
-} GetFontInfo;
-
-static gboolean
-get_font_foreach (PangoFontset *fontset,
- PangoFont *font,
- gpointer data)
-{
- GetFontInfo *info = data;
-
- if (G_UNLIKELY (!font))
- return FALSE;
-
- if (pango_font_has_char (font, info->wc))
- {
- info->font = font;
- return TRUE;
- }
-
- if (!fontset)
- {
- info->font = font;
- return TRUE;
- }
-
- info->position++;
-
- return FALSE;
-}
-
-static PangoFont *
-get_base_font (ItemizeState *state)
-{
- if (!state->base_font)
- state->base_font = pango_font_map_load_font (state->context->font_map,
- state->context,
- state->font_desc);
- return state->base_font;
-}
-
-static gboolean
-get_font (ItemizeState *state,
- gunichar wc,
- PangoFont **font,
- int *position)
-{
- GetFontInfo info;
-
- /* We'd need a separate cache when fallback is disabled, but since lookup
- * with fallback disabled is faster anyways, we just skip caching */
- if (state->enable_fallback && font_cache_get (state->cache, wc, font, position))
- return TRUE;
-
- info.lang = state->derived_lang;
- info.wc = wc;
- info.font = NULL;
- info.position = 0;
-
- if (state->enable_fallback)
- pango_fontset_foreach (state->current_fonts, get_font_foreach, &info);
- else
- get_font_foreach (NULL, get_base_font (state), &info);
-
- *font = info.font;
- *position = info.position;
-
- /* skip caching if fallback disabled (see above) */
- if (state->enable_fallback)
- font_cache_insert (state->cache, wc, *font, *position);
-
- return TRUE;
-}
-
-static PangoLanguage *
-compute_derived_language (PangoLanguage *lang,
- PangoScript script)
-{
- PangoLanguage *derived_lang;
-
- /* Make sure the language tag is consistent with the derived
- * script. There is no point in marking up a section of
- * Arabic text with the "en" language tag.
- */
- if (lang && pango_language_includes_script (lang, script))
- derived_lang = lang;
- else
- {
- derived_lang = pango_script_get_sample_language (script);
- /* If we don't find a sample language for the script, we
- * use a language tag that shouldn't actually be used
- * anywhere. This keeps fontconfig (for the PangoFc*
- * backend) from using the language tag to affect the
- * sort order. I don't have a reference for 'xx' being
- * safe here, though Keith Packard claims it is.
- */
- if (!derived_lang)
- derived_lang = pango_language_from_string ("xx");
- }
-
- return derived_lang;
-}
-
-static void
-itemize_state_update_for_new_run (ItemizeState *state)
-{
- /* This block should be moved to update_attr_iterator, but I'm too lazy to
- * do it right now */
- if (state->changed & (FONT_CHANGED | SCRIPT_CHANGED | WIDTH_CHANGED))
- {
- /* Font-desc gravity overrides everything */
- if (state->font_desc_gravity != PANGO_GRAVITY_AUTO)
- {
- state->resolved_gravity = state->font_desc_gravity;
- }
- else
- {
- PangoGravity gravity = state->gravity;
- PangoGravityHint gravity_hint = state->gravity_hint;
-
- if (G_LIKELY (gravity == PANGO_GRAVITY_AUTO))
- gravity = state->context->resolved_gravity;
-
- state->resolved_gravity = pango_gravity_get_for_script_and_width (state->script,
- state->width_iter.upright,
- gravity,
- gravity_hint);
- }
-
- if (state->font_desc_gravity != state->resolved_gravity)
- {
- pango_font_description_set_gravity (state->font_desc, state->resolved_gravity);
- state->changed |= FONT_CHANGED;
- }
- }
-
- if (state->changed & (SCRIPT_CHANGED | LANG_CHANGED))
- {
- PangoLanguage *old_derived_lang = state->derived_lang;
- state->derived_lang = compute_derived_language (state->lang, state->script);
- if (old_derived_lang != state->derived_lang)
- state->changed |= DERIVED_LANG_CHANGED;
- }
-
- if (state->changed & (EMOJI_CHANGED))
- {
- state->changed |= FONT_CHANGED;
- }
-
- if (state->changed & (FONT_CHANGED | DERIVED_LANG_CHANGED) &&
- state->current_fonts)
- {
- g_object_unref (state->current_fonts);
- state->current_fonts = NULL;
- state->cache = NULL;
- }
-
- if (!state->current_fonts)
- {
- gboolean is_emoji = state->emoji_iter.is_emoji;
- if (is_emoji && !state->emoji_font_desc)
- {
- state->emoji_font_desc = pango_font_description_copy_static (state->font_desc);
- pango_font_description_set_family_static (state->emoji_font_desc, "emoji");
- }
- state->current_fonts = pango_font_map_load_fontset (state->context->font_map,
- state->context,
- is_emoji ? state->emoji_font_desc : state->font_desc,
- state->derived_lang);
- state->cache = get_font_cache (state->current_fonts);
- }
-
- if ((state->changed & FONT_CHANGED) && state->base_font)
- {
- g_object_unref (state->base_font);
- state->base_font = NULL;
- }
-}
-
-static void
-itemize_state_process_run (ItemizeState *state)
-{
- const char *p;
- gboolean last_was_forced_break = FALSE;
- gboolean is_space;
-
- /* Only one character has type G_UNICODE_LINE_SEPARATOR in Unicode 4.0;
- * update this if that changes. */
-#define LINE_SEPARATOR 0x2028
-
- itemize_state_update_for_new_run (state);
-
- /* We should never get an empty run */
- g_assert (state->run_end != state->run_start);
-
- for (p = state->run_start;
- p < state->run_end;
- p = g_utf8_next_char (p))
- {
- gunichar wc = g_utf8_get_char (p);
- gboolean is_forced_break = (wc == '\t' || wc == LINE_SEPARATOR);
- PangoFont *font;
- int font_position;
- GUnicodeType type;
-
- /* We don't want space characters to affect font selection; in general,
- * it's always wrong to select a font just to render a space.
- * We assume that all fonts have the ASCII space, and for other space
- * characters if they don't, HarfBuzz will compatibility-decompose them
- * to ASCII space...
- * See bugs #355987 and #701652.
- *
- * We don't want to change fonts just for variation selectors.
- * See bug #781123.
- *
- * Finally, don't change fonts for line or paragraph separators.
- *
- * Note that we want spaces to use the 'better' font, comparing
- * the font that is used before and after the space. This is handled
- * in itemize_state_add_character().
- */
- type = g_unichar_type (wc);
- if (G_UNLIKELY (type == G_UNICODE_CONTROL ||
- type == G_UNICODE_FORMAT ||
- type == G_UNICODE_SURROGATE ||
- type == G_UNICODE_LINE_SEPARATOR ||
- type == G_UNICODE_PARAGRAPH_SEPARATOR ||
- (type == G_UNICODE_SPACE_SEPARATOR && wc != 0x1680u /* OGHAM SPACE MARK */) ||
- (wc >= 0xfe00u && wc <= 0xfe0fu) ||
- (wc >= 0xe0100u && wc <= 0xe01efu)))
- {
- font = NULL;
- font_position = 0xffff;
- is_space = TRUE;
- }
- else
- {
- get_font (state, wc, &font, &font_position);
- is_space = FALSE;
- }
-
- itemize_state_add_character (state, font, font_position,
- is_forced_break || last_was_forced_break,
- p,
- is_space);
-
- last_was_forced_break = is_forced_break;
- }
-
- /* Finish the final item from the current segment */
- state->item->length = (p - state->text) - state->item->offset;
- if (!state->item->analysis.font)
- {
- PangoFont *font;
- int position;
-
- if (G_UNLIKELY (!get_font (state, ' ', &font, &position)))
- {
- /* If no font was found, warn once per fontmap/script pair */
- PangoFontMap *fontmap = state->context->font_map;
- char *script_tag = g_strdup_printf ("g-unicode-script-%d", state->script);
-
- if (!g_object_get_data (G_OBJECT (fontmap), script_tag))
- {
- g_warning ("failed to choose a font, expect ugly output. script='%d'",
- state->script);
-
- g_object_set_data_full (G_OBJECT (fontmap), script_tag,
- GINT_TO_POINTER (1), NULL);
- }
-
- g_free (script_tag);
-
- font = NULL;
- }
- itemize_state_fill_font (state, font);
- }
- state->item = NULL;
-}
-
-static void
-itemize_state_finish (ItemizeState *state)
-{
- g_free (state->embedding_levels);
- if (state->free_attr_iter)
- pango_attr_iterator_destroy (state->attr_iter);
- _pango_script_iter_fini (&state->script_iter);
- pango_font_description_free (state->font_desc);
- pango_font_description_free (state->emoji_font_desc);
- width_iter_fini (&state->width_iter);
- _pango_emoji_iter_fini (&state->emoji_iter);
-
- if (state->current_fonts)
- g_object_unref (state->current_fonts);
- if (state->base_font)
- g_object_unref (state->base_font);
-}
-
-/**
- * pango_itemize_with_base_dir:
- * @context: a structure holding information that affects
- * the itemization process.
- * @base_dir: base direction to use for bidirectional processing
- * @text: the text to itemize.
- * @start_index: first byte in @text to process
- * @length: the number of bytes (not characters) to process
- * after @start_index. This must be >= 0.
- * @attrs: the set of attributes that apply to @text.
- * @cached_iter: (nullable): Cached attribute iterator
- *
- * Like `pango_itemize()`, but with an explicitly specified base direction.
- *
- * The base direction is used when computing bidirectional levels.
- * (see [method@Pango.Context.set_base_dir]). [func@itemize] gets the
- * base direction from the `PangoContext`.
- *
- * Return value: (transfer full) (element-type Pango.Item): a `GList` of
- * [struct@Pango.Item] structures. The items should be freed using
- * [method@Pango.Item.free] probably in combination with g_list_free_full().
- *
- * Since: 1.4
- */
-GList *
-pango_itemize_with_base_dir (PangoContext *context,
- PangoDirection base_dir,
- const char *text,
- int start_index,
- int length,
- PangoAttrList *attrs,
- PangoAttrIterator *cached_iter)
-{
- ItemizeState state;
-
- g_return_val_if_fail (context != NULL, NULL);
- g_return_val_if_fail (start_index >= 0, NULL);
- g_return_val_if_fail (length >= 0, NULL);
- g_return_val_if_fail (length == 0 || text != NULL, NULL);
-
- if (length == 0 || g_utf8_get_char (text + start_index) == '\0')
- return NULL;
-
- itemize_state_init (&state, context, text, base_dir, start_index, length,
- attrs, cached_iter, NULL);
-
- do
- itemize_state_process_run (&state);
- while (itemize_state_next (&state));
-
- itemize_state_finish (&state);
-
- return g_list_reverse (state.result);
-}
-
-static GList *
-itemize_with_font (PangoContext *context,
- const char *text,
- int start_index,
- int length,
- const PangoFontDescription *desc)
-{
- ItemizeState state;
-
- if (length == 0)
- return NULL;
-
- itemize_state_init (&state, context, text, context->base_dir, start_index, length,
- NULL, NULL, desc);
-
- do
- itemize_state_process_run (&state);
- while (itemize_state_next (&state));
-
- itemize_state_finish (&state);
-
- return g_list_reverse (state.result);
-}
-
-/**
- * pango_itemize:
- * @context: a structure holding information that affects
- * the itemization process.
- * @text: the text to itemize. Must be valid UTF-8
- * @start_index: first byte in @text to process
- * @length: the number of bytes (not characters) to process
- * after @start_index. This must be >= 0.
- * @attrs: the set of attributes that apply to @text.
- * @cached_iter: (nullable): Cached attribute iterator
- *
- * Breaks a piece of text into segments with consistent directional
- * level and font.
- *
- * Each byte of @text will be contained in exactly one of the items in the
- * returned list; the generated list of items will be in logical order (the
- * start offsets of the items are ascending).
- *
- * @cached_iter should be an iterator over @attrs currently positioned
- * at a range before or containing @start_index; @cached_iter will be
- * advanced to the range covering the position just after
- * @start_index + @length. (i.e. if itemizing in a loop, just keep passing
- * in the same @cached_iter).
- *
- * Return value: (transfer full) (element-type Pango.Item): a `GList` of
- * [struct@Pango.Item] structures. The items should be freed using
- * [method@Pango.Item.free] probably in combination with g_list_free_full().
- */
-GList *
-pango_itemize (PangoContext *context,
- const char *text,
- int start_index,
- int length,
- PangoAttrList *attrs,
- PangoAttrIterator *cached_iter)
-{
- g_return_val_if_fail (context != NULL, NULL);
- g_return_val_if_fail (start_index >= 0, NULL);
- g_return_val_if_fail (length >= 0, NULL);
- g_return_val_if_fail (length == 0 || text != NULL, NULL);
-
- return pango_itemize_with_base_dir (context, context->base_dir,
- text, start_index, length, attrs, cached_iter);
-}
static gboolean
get_first_metrics_foreach (PangoFontset *fontset,
@@ -1861,7 +712,7 @@ pango_context_get_metrics (PangoContext *context,
sample_str = pango_language_get_sample_string (language);
text_len = strlen (sample_str);
- items = itemize_with_font (context, sample_str, 0, text_len, desc);
+ items = pango_itemize_with_font (context, sample_str, 0, text_len, desc);
update_metrics_from_items (metrics, language, sample_str, text_len, items);
diff --git a/pango/pango-context.h b/pango/pango-context.h
index b44bd623..3ad63f80 100644
--- a/pango/pango-context.h
+++ b/pango/pango-context.h
@@ -10,7 +10,7 @@
*
* 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
+ * 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
@@ -22,6 +22,7 @@
#ifndef __PANGO_CONTEXT_H__
#define __PANGO_CONTEXT_H__
+#include <pango/pango-types.h>
#include <pango/pango-font.h>
#include <pango/pango-fontmap.h>
#include <pango/pango-attributes.h>
@@ -29,11 +30,6 @@
G_BEGIN_DECLS
-/* Sort of like a GC - application set information about how
- * to handle scripts
- */
-
-/* PangoContext typedefed in pango-fontmap.h */
typedef struct _PangoContextClass PangoContextClass;
#define PANGO_TYPE_CONTEXT (pango_context_get_type ())
@@ -44,96 +40,76 @@ typedef struct _PangoContextClass PangoContextClass;
#define PANGO_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_CONTEXT, PangoContextClass))
-/* The PangoContext and PangoContextClass structs are private; if you
- * need to create a subclass of these, file a bug.
- */
-
PANGO_AVAILABLE_IN_ALL
-GType pango_context_get_type (void) G_GNUC_CONST;
+GType pango_context_get_type (void) G_GNUC_CONST;
PANGO_AVAILABLE_IN_ALL
-PangoContext *pango_context_new (void);
+PangoContext * pango_context_new (void);
PANGO_AVAILABLE_IN_1_32
-void pango_context_changed (PangoContext *context);
+void pango_context_changed (PangoContext *context);
PANGO_AVAILABLE_IN_ALL
-void pango_context_set_font_map (PangoContext *context,
- PangoFontMap *font_map);
+void pango_context_set_font_map (PangoContext *context,
+ PangoFontMap *font_map);
PANGO_AVAILABLE_IN_1_6
-PangoFontMap *pango_context_get_font_map (PangoContext *context);
+PangoFontMap * pango_context_get_font_map (PangoContext *context);
PANGO_AVAILABLE_IN_1_32
-guint pango_context_get_serial (PangoContext *context);
+guint pango_context_get_serial (PangoContext *context);
PANGO_AVAILABLE_IN_ALL
-void pango_context_list_families (PangoContext *context,
- PangoFontFamily ***families,
- int *n_families);
+void pango_context_list_families (PangoContext *context,
+ PangoFontFamily ***families,
+ int *n_families);
PANGO_AVAILABLE_IN_ALL
-PangoFont * pango_context_load_font (PangoContext *context,
- const PangoFontDescription *desc);
+PangoFont * pango_context_load_font (PangoContext *context,
+ const PangoFontDescription *desc);
PANGO_AVAILABLE_IN_ALL
-PangoFontset *pango_context_load_fontset (PangoContext *context,
- const PangoFontDescription *desc,
- PangoLanguage *language);
+PangoFontset * pango_context_load_fontset (PangoContext *context,
+ const PangoFontDescription *desc,
+ PangoLanguage *language);
PANGO_AVAILABLE_IN_ALL
-PangoFontMetrics *pango_context_get_metrics (PangoContext *context,
- const PangoFontDescription *desc,
- PangoLanguage *language);
+PangoFontMetrics * pango_context_get_metrics (PangoContext *context,
+ const PangoFontDescription *desc,
+ PangoLanguage *language);
PANGO_AVAILABLE_IN_ALL
-void pango_context_set_font_description (PangoContext *context,
- const PangoFontDescription *desc);
+void pango_context_set_font_description (PangoContext *context,
+ const PangoFontDescription *desc);
PANGO_AVAILABLE_IN_ALL
-PangoFontDescription * pango_context_get_font_description (PangoContext *context);
+PangoFontDescription * pango_context_get_font_description (PangoContext *context);
PANGO_AVAILABLE_IN_ALL
-PangoLanguage *pango_context_get_language (PangoContext *context);
+PangoLanguage * pango_context_get_language (PangoContext *context);
PANGO_AVAILABLE_IN_ALL
-void pango_context_set_language (PangoContext *context,
- PangoLanguage *language);
+void pango_context_set_language (PangoContext *context,
+ PangoLanguage *language);
PANGO_AVAILABLE_IN_ALL
-void pango_context_set_base_dir (PangoContext *context,
- PangoDirection direction);
+void pango_context_set_base_dir (PangoContext *context,
+ PangoDirection direction);
PANGO_AVAILABLE_IN_ALL
-PangoDirection pango_context_get_base_dir (PangoContext *context);
+PangoDirection pango_context_get_base_dir (PangoContext *context);
PANGO_AVAILABLE_IN_1_16
-void pango_context_set_base_gravity (PangoContext *context,
- PangoGravity gravity);
+void pango_context_set_base_gravity (PangoContext *context,
+ PangoGravity gravity);
PANGO_AVAILABLE_IN_1_16
-PangoGravity pango_context_get_base_gravity (PangoContext *context);
+PangoGravity pango_context_get_base_gravity (PangoContext *context);
PANGO_AVAILABLE_IN_1_16
-PangoGravity pango_context_get_gravity (PangoContext *context);
+PangoGravity pango_context_get_gravity (PangoContext *context);
PANGO_AVAILABLE_IN_1_16
-void pango_context_set_gravity_hint (PangoContext *context,
- PangoGravityHint hint);
+void pango_context_set_gravity_hint (PangoContext *context,
+ PangoGravityHint hint);
PANGO_AVAILABLE_IN_1_16
-PangoGravityHint pango_context_get_gravity_hint (PangoContext *context);
+PangoGravityHint pango_context_get_gravity_hint (PangoContext *context);
PANGO_AVAILABLE_IN_1_6
-void pango_context_set_matrix (PangoContext *context,
- const PangoMatrix *matrix);
+void pango_context_set_matrix (PangoContext *context,
+ const PangoMatrix *matrix);
PANGO_AVAILABLE_IN_1_6
-const PangoMatrix * pango_context_get_matrix (PangoContext *context);
+const PangoMatrix * pango_context_get_matrix (PangoContext *context);
PANGO_AVAILABLE_IN_1_44
-void pango_context_set_round_glyph_positions (PangoContext *context,
- gboolean round_positions);
+void pango_context_set_round_glyph_positions (PangoContext *context,
+ gboolean round_positions);
PANGO_AVAILABLE_IN_1_44
-gboolean pango_context_get_round_glyph_positions (PangoContext *context);
-
-PANGO_AVAILABLE_IN_ALL
-GList *pango_itemize (PangoContext *context,
- const char *text,
- int start_index,
- int length,
- PangoAttrList *attrs,
- PangoAttrIterator *cached_iter);
-PANGO_AVAILABLE_IN_1_4
-GList *pango_itemize_with_base_dir (PangoContext *context,
- PangoDirection base_dir,
- const char *text,
- int start_index,
- int length,
- PangoAttrList *attrs,
- PangoAttrIterator *cached_iter);
+gboolean pango_context_get_round_glyph_positions (PangoContext *context);
G_END_DECLS
diff --git a/pango/pango-fontmap.h b/pango/pango-fontmap.h
index aec18eeb..0e0edd43 100644
--- a/pango/pango-fontmap.h
+++ b/pango/pango-fontmap.h
@@ -22,6 +22,7 @@
#ifndef __PANGO_FONTMAP_H__
#define __PANGO_FONTMAP_H__
+#include <pango/pango-types.h>
#include <pango/pango-font.h>
#include <pango/pango-fontset.h>
@@ -35,7 +36,6 @@ G_BEGIN_DECLS
#define PANGO_FONT_MAP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_FONT_MAP, PangoFontMapClass))
typedef struct _PangoFontMapClass PangoFontMapClass;
-typedef struct _PangoContext PangoContext;
/**
* PangoFontMap:
diff --git a/pango/pango-glyph.h b/pango/pango-glyph.h
index 67302bfd..ae1f5fd7 100644
--- a/pango/pango-glyph.h
+++ b/pango/pango-glyph.h
@@ -10,7 +10,7 @@
*
* 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
+ * 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
@@ -120,83 +120,72 @@ struct _PangoGlyphInfo
* which simplifies memory management.
*/
struct _PangoGlyphString {
- gint num_glyphs;
+ int num_glyphs;
PangoGlyphInfo *glyphs;
- gint *log_clusters;
+ int *log_clusters;
/*< private >*/
- gint space;
+ int space;
};
#define PANGO_TYPE_GLYPH_STRING (pango_glyph_string_get_type ())
PANGO_AVAILABLE_IN_ALL
-PangoGlyphString *pango_glyph_string_new (void);
+GType pango_glyph_string_get_type (void) G_GNUC_CONST;
+
PANGO_AVAILABLE_IN_ALL
-void pango_glyph_string_set_size (PangoGlyphString *string,
- gint new_len);
+PangoGlyphString * pango_glyph_string_new (void);
PANGO_AVAILABLE_IN_ALL
-GType pango_glyph_string_get_type (void) G_GNUC_CONST;
+void pango_glyph_string_set_size (PangoGlyphString *string,
+ int new_len);
+
PANGO_AVAILABLE_IN_ALL
-PangoGlyphString *pango_glyph_string_copy (PangoGlyphString *string);
+PangoGlyphString * pango_glyph_string_copy (PangoGlyphString *string);
PANGO_AVAILABLE_IN_ALL
-void pango_glyph_string_free (PangoGlyphString *string);
+void pango_glyph_string_free (PangoGlyphString *string);
+
PANGO_AVAILABLE_IN_ALL
-void pango_glyph_string_extents (PangoGlyphString *glyphs,
- PangoFont *font,
- PangoRectangle *ink_rect,
- PangoRectangle *logical_rect);
+void pango_glyph_string_extents (PangoGlyphString *glyphs,
+ PangoFont *font,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect);
PANGO_AVAILABLE_IN_1_14
-int pango_glyph_string_get_width(PangoGlyphString *glyphs);
+int pango_glyph_string_get_width (PangoGlyphString *glyphs);
PANGO_AVAILABLE_IN_ALL
-void pango_glyph_string_extents_range (PangoGlyphString *glyphs,
- int start,
- int end,
- PangoFont *font,
- PangoRectangle *ink_rect,
- PangoRectangle *logical_rect);
+void pango_glyph_string_extents_range (PangoGlyphString *glyphs,
+ int start,
+ int end,
+ PangoFont *font,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect);
PANGO_AVAILABLE_IN_ALL
-void pango_glyph_string_get_logical_widths (PangoGlyphString *glyphs,
- const char *text,
- int length,
- int embedding_level,
- int *logical_widths);
+void pango_glyph_string_get_logical_widths (PangoGlyphString *glyphs,
+ const char *text,
+ int length,
+ int embedding_level,
+ int *logical_widths);
PANGO_AVAILABLE_IN_ALL
-void pango_glyph_string_index_to_x (PangoGlyphString *glyphs,
- const char *text,
- int length,
- PangoAnalysis *analysis,
- int index_,
- gboolean trailing,
- int *x_pos);
+void pango_glyph_string_index_to_x (PangoGlyphString *glyphs,
+ const char *text,
+ int length,
+ PangoAnalysis *analysis,
+ int index_,
+ gboolean trailing,
+ int *x_pos);
PANGO_AVAILABLE_IN_ALL
-void pango_glyph_string_x_to_index (PangoGlyphString *glyphs,
- const char *text,
- int length,
- PangoAnalysis *analysis,
- int x_pos,
- int *index_,
- int *trailing);
-
-/* Turn a string of characters into a string of glyphs
- */
-PANGO_AVAILABLE_IN_ALL
-void pango_shape (const char *text,
- int length,
- const PangoAnalysis *analysis,
- PangoGlyphString *glyphs);
+void pango_glyph_string_x_to_index (PangoGlyphString *glyphs,
+ const char *text,
+ int length,
+ PangoAnalysis *analysis,
+ int x_pos,
+ int *index_,
+ int *trailing);
-PANGO_AVAILABLE_IN_1_32
-void pango_shape_full (const char *item_text,
- int item_length,
- const char *paragraph_text,
- int paragraph_length,
- const PangoAnalysis *analysis,
- PangoGlyphString *glyphs);
+/* Shaping */
/**
* PangoShapeFlags:
@@ -215,17 +204,29 @@ typedef enum {
PANGO_SHAPE_ROUND_POSITIONS = 1 << 0,
} PangoShapeFlags;
+PANGO_AVAILABLE_IN_ALL
+void pango_shape (const char *text,
+ int length,
+ const PangoAnalysis *analysis,
+ PangoGlyphString *glyphs);
+
+PANGO_AVAILABLE_IN_1_32
+void pango_shape_full (const char *item_text,
+ int item_length,
+ const char *paragraph_text,
+ int paragraph_length,
+ const PangoAnalysis *analysis,
+ PangoGlyphString *glyphs);
+
PANGO_AVAILABLE_IN_1_44
-void pango_shape_with_flags (const char *item_text,
- int item_length,
- const char *paragraph_text,
- int paragraph_length,
- const PangoAnalysis *analysis,
- PangoGlyphString *glyphs,
- PangoShapeFlags flags);
+void pango_shape_with_flags (const char *item_text,
+ int item_length,
+ const char *paragraph_text,
+ int paragraph_length,
+ const PangoAnalysis *analysis,
+ PangoGlyphString *glyphs,
+ PangoShapeFlags flags);
-PANGO_AVAILABLE_IN_ALL
-GList *pango_reorder_items (GList *logical_items);
G_END_DECLS
diff --git a/pango/pango-item.h b/pango/pango-item.h
index a1e95086..9e0596f2 100644
--- a/pango/pango-item.h
+++ b/pango/pango-item.h
@@ -10,7 +10,7 @@
*
* 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
+ * 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
@@ -118,21 +118,46 @@ struct _PangoItem
#define PANGO_TYPE_ITEM (pango_item_get_type ())
PANGO_AVAILABLE_IN_ALL
-GType pango_item_get_type (void) G_GNUC_CONST;
+GType pango_item_get_type (void) G_GNUC_CONST;
PANGO_AVAILABLE_IN_ALL
-PangoItem *pango_item_new (void);
+PangoItem * pango_item_new (void);
PANGO_AVAILABLE_IN_ALL
-PangoItem *pango_item_copy (PangoItem *item);
+PangoItem * pango_item_copy (PangoItem *item);
PANGO_AVAILABLE_IN_ALL
-void pango_item_free (PangoItem *item);
+void pango_item_free (PangoItem *item);
+
PANGO_AVAILABLE_IN_ALL
-PangoItem *pango_item_split (PangoItem *orig,
- int split_index,
- int split_offset);
+PangoItem * pango_item_split (PangoItem *orig,
+ int split_index,
+ int split_offset);
+
PANGO_AVAILABLE_IN_1_44
-void pango_item_apply_attrs (PangoItem *item,
- PangoAttrIterator *iter);
+void pango_item_apply_attrs (PangoItem *item,
+ PangoAttrIterator *iter);
+
+PANGO_AVAILABLE_IN_ALL
+GList * pango_reorder_items (GList *items);
+
+/* Itemization */
+
+PANGO_AVAILABLE_IN_ALL
+GList * pango_itemize (PangoContext *context,
+ const char *text,
+ int start_index,
+ int length,
+ PangoAttrList *attrs,
+ PangoAttrIterator *cached_iter);
+
+PANGO_AVAILABLE_IN_1_4
+GList * pango_itemize_with_base_dir (PangoContext *context,
+ PangoDirection base_dir,
+ const char *text,
+ int start_index,
+ int length,
+ PangoAttrList *attrs,
+ PangoAttrIterator *cached_iter);
+
G_END_DECLS
diff --git a/pango/pango-language.h b/pango/pango-language.h
index b000c5b8..a71316dd 100644
--- a/pango/pango-language.h
+++ b/pango/pango-language.h
@@ -10,7 +10,7 @@
*
* 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
+ * 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
@@ -25,44 +25,45 @@
#include <glib.h>
#include <glib-object.h>
+#include <pango/pango-types.h>
#include <pango/pango-version-macros.h>
+#include <pango/pango-script.h>
G_BEGIN_DECLS
-typedef struct _PangoLanguage PangoLanguage;
-
#define PANGO_TYPE_LANGUAGE (pango_language_get_type ())
PANGO_AVAILABLE_IN_ALL
-GType pango_language_get_type (void) G_GNUC_CONST;
+GType pango_language_get_type (void) G_GNUC_CONST;
+
+PANGO_AVAILABLE_IN_1_16
+PangoLanguage * pango_language_get_default (void) G_GNUC_CONST;
+
+PANGO_AVAILABLE_IN_1_48
+PangoLanguage ** pango_language_get_preferred (void) G_GNUC_CONST;
+
PANGO_AVAILABLE_IN_ALL
-PangoLanguage *pango_language_from_string (const char *language);
+PangoLanguage * pango_language_from_string (const char *language);
PANGO_AVAILABLE_IN_ALL
-const char *pango_language_to_string (PangoLanguage *language) G_GNUC_CONST;
+const char * pango_language_to_string (PangoLanguage *language) G_GNUC_CONST;
+
/* For back compat. Will have to keep indefinitely. */
#define pango_language_to_string(language) ((const char *)language)
PANGO_AVAILABLE_IN_ALL
-const char *pango_language_get_sample_string (PangoLanguage *language) G_GNUC_CONST;
-PANGO_AVAILABLE_IN_1_16
-PangoLanguage *pango_language_get_default (void) G_GNUC_CONST;
-
-PANGO_AVAILABLE_IN_1_48
-PangoLanguage **pango_language_get_preferred (void) G_GNUC_CONST;
+const char * pango_language_get_sample_string (PangoLanguage *language) G_GNUC_CONST;
PANGO_AVAILABLE_IN_ALL
-gboolean pango_language_matches (PangoLanguage *language,
- const char *range_list) G_GNUC_PURE;
-
-#include <pango/pango-script.h>
+gboolean pango_language_matches (PangoLanguage *language,
+ const char *range_list) G_GNUC_PURE;
PANGO_AVAILABLE_IN_1_4
-gboolean pango_language_includes_script (PangoLanguage *language,
- PangoScript script) G_GNUC_PURE;
+gboolean pango_language_includes_script (PangoLanguage *language,
+ PangoScript script) G_GNUC_PURE;
PANGO_AVAILABLE_IN_1_22
-const PangoScript *pango_language_get_scripts (PangoLanguage *language,
- int *num_scripts);
+const PangoScript * pango_language_get_scripts (PangoLanguage *language,
+ int *num_scripts);
G_END_DECLS
diff --git a/pango/pango-markup.c b/pango/pango-markup.c
index d4421711..a897a52d 100644
--- a/pango/pango-markup.c
+++ b/pango/pango-markup.c
@@ -24,6 +24,8 @@
#include <stdlib.h>
#include <errno.h>
+#include "pango-markup.h"
+
#include "pango-attributes.h"
#include "pango-font.h"
#include "pango-enum-types.h"
diff --git a/pango/pango-markup.h b/pango/pango-markup.h
new file mode 100644
index 00000000..92ac509d
--- /dev/null
+++ b/pango/pango-markup.h
@@ -0,0 +1,52 @@
+/* Pango
+ * pango-markup.h: Parser for attributed text
+ *
+ * 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_MARKUP_H__
+#define __PANGO_MARKUP_H__
+
+#include <pango-attributes.h>
+
+G_BEGIN_DECLS
+
+
+PANGO_AVAILABLE_IN_1_32
+GMarkupParseContext * pango_markup_parser_new (gunichar accel_marker);
+
+PANGO_AVAILABLE_IN_1_32
+gboolean pango_markup_parser_finish (GMarkupParseContext *context,
+ PangoAttrList **attr_list,
+ char **text,
+ gunichar *accel_char,
+ GError **error);
+
+PANGO_AVAILABLE_IN_ALL
+gboolean pango_parse_markup (const char *markup_text,
+ int length,
+ gunichar accel_marker,
+ PangoAttrList **attr_list,
+ char **text,
+ gunichar *accel_char,
+ GError **error);
+
+
+G_END_DECLS
+
+#endif /* __PANGO_MARKUP_H__ */
diff --git a/pango/pango-types.h b/pango/pango-types.h
index a7bcd747..f18225ba 100644
--- a/pango/pango-types.h
+++ b/pango/pango-types.h
@@ -41,7 +41,9 @@ typedef struct _PangoFontMap PangoFontMap;
typedef struct _PangoRectangle PangoRectangle;
+typedef struct _PangoContext PangoContext;
+typedef struct _PangoLanguage PangoLanguage;
/* A index of a glyph into a font. Rendering system dependent */
/**
diff --git a/pango/pango-utils.c b/pango/pango-utils.c
index 894935e7..412f417a 100644
--- a/pango/pango-utils.c
+++ b/pango/pango-utils.c
@@ -1154,3 +1154,105 @@ _pango_shape_get_extents (gint n_chars,
}
}
+/**
+ * pango_find_paragraph_boundary:
+ * @text: UTF-8 text
+ * @length: length of @text in bytes, or -1 if nul-terminated
+ * @paragraph_delimiter_index: (out): return location for index of
+ * delimiter
+ * @next_paragraph_start: (out): return location for start of next
+ * paragraph
+ *
+ * Locates a paragraph boundary in @text.
+ *
+ * A boundary is caused by delimiter characters, such as
+ * a newline, carriage return, carriage return-newline pair,
+ * or Unicode paragraph separator character.
+ *
+ * The index of the run of delimiters is returned in
+ * @paragraph_delimiter_index. The index of the start
+ * of the paragrap (index after all delimiters) is stored
+ * in @next_paragraph_start.
+ *
+ * If no delimiters are found, both @paragraph_delimiter_index
+ * and @next_paragraph_start are filled with the length of @text
+ * (an index one off the end).
+ */
+void
+pango_find_paragraph_boundary (const char *text,
+ int length,
+ int *paragraph_delimiter_index,
+ int *next_paragraph_start)
+{
+ const char *p = text;
+ const char *end;
+ const char *start = NULL;
+ const char *delimiter = NULL;
+
+ /* Only one character has type G_UNICODE_PARAGRAPH_SEPARATOR in
+ * Unicode 5.0; update the following code if that changes.
+ */
+
+ /* prev_sep is the first byte of the previous separator. Since
+ * the valid separators are \r, \n, and PARAGRAPH_SEPARATOR, the
+ * first byte is enough to identify it.
+ */
+ char prev_sep;
+
+#define PARAGRAPH_SEPARATOR_STRING "\xE2\x80\xA9"
+
+ if (length < 0)
+ length = strlen (text);
+
+ end = text + length;
+
+ if (paragraph_delimiter_index)
+ *paragraph_delimiter_index = length;
+
+ if (next_paragraph_start)
+ *next_paragraph_start = length;
+
+ if (length == 0)
+ return;
+
+ prev_sep = 0;
+ while (p < end)
+ {
+ if (prev_sep == '\n' ||
+ prev_sep == PARAGRAPH_SEPARATOR_STRING[0])
+ {
+ g_assert (delimiter);
+ start = p;
+ break;
+ }
+ else if (prev_sep == '\r')
+ {
+ /* don't break between \r and \n */
+ if (*p != '\n')
+ {
+ g_assert (delimiter);
+ start = p;
+ break;
+ }
+ }
+
+ if (*p == '\n' ||
+ *p == '\r' ||
+ !strncmp(p, PARAGRAPH_SEPARATOR_STRING, strlen (PARAGRAPH_SEPARATOR_STRING)))
+ {
+ if (delimiter == NULL)
+ delimiter = p;
+ prev_sep = *p;
+ }
+ else
+ prev_sep = 0;
+
+ p = g_utf8_next_char (p);
+ }
+
+ if (delimiter && paragraph_delimiter_index)
+ *paragraph_delimiter_index = delimiter - text;
+
+ if (start && next_paragraph_start)
+ *next_paragraph_start = start - text;
+}
diff --git a/pango/pango-utils.h b/pango/pango-utils.h
index 04452eb4..49566cf8 100644
--- a/pango/pango-utils.h
+++ b/pango/pango-utils.h
@@ -99,6 +99,12 @@ guint8 * pango_log2vis_get_embedding_levels (const gchar *text,
PANGO_AVAILABLE_IN_1_10
gboolean pango_is_zero_width (gunichar ch) G_GNUC_CONST;
+PANGO_AVAILABLE_IN_ALL
+void pango_find_paragraph_boundary (const char *text,
+ int length,
+ int *paragraph_delimiter_index,
+ int *next_paragraph_start);
+
/* Pango version checking */
/* Encode a Pango version as an integer */
diff --git a/pango/pango.h b/pango/pango.h
index 7a00f925..8dc86b13 100644
--- a/pango/pango.h
+++ b/pango/pango.h
@@ -25,6 +25,7 @@
#include <pango/pango-attributes.h>
#include <pango/pango-bidi-type.h>
#include <pango/pango-break.h>
+#include <pango/pango-color.h>
#include <pango/pango-context.h>
#include <pango/pango-coverage.h>
#include <pango/pango-direction.h>
@@ -38,8 +39,10 @@
#include <pango/pango-glyph-item.h>
#include <pango/pango-gravity.h>
#include <pango/pango-item.h>
+#include <pango/pango-language.h>
#include <pango/pango-layout.h>
#include <pango/pango-matrix.h>
+#include <pango/pango-markup.h>
#include <pango/pango-renderer.h>
#include <pango/pango-script.h>
#include <pango/pango-tabs.h>
diff --git a/pango/pangofc-shape.c b/pango/pangofc-shape.c
deleted file mode 100644
index 0a5ce7f9..00000000
--- a/pango/pangofc-shape.c
+++ /dev/null
@@ -1,425 +0,0 @@
-/* Pango
- * pangofc-shape.c: Basic shaper for FreeType-based backends
- *
- * Copyright (C) 2000, 2007, 2009 Red Hat Software
- * Authors:
- * Owen Taylor <otaylor@redhat.com>
- * Behdad Esfahbod <behdad@behdad.org>
- *
- * 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 "config.h"
-#include <string.h>
-#include <math.h>
-
-#include "pangohb-private.h"
-#include "pango-impl-utils.h"
-
-#include <glib.h>
-
-/* cache a single hb_buffer_t */
-static hb_buffer_t *cached_buffer = NULL; /* MT-safe */
-G_LOCK_DEFINE_STATIC (cached_buffer);
-
-static hb_buffer_t *
-acquire_buffer (gboolean *free_buffer)
-{
- hb_buffer_t *buffer;
-
- if (G_LIKELY (G_TRYLOCK (cached_buffer)))
- {
- if (G_UNLIKELY (!cached_buffer))
- cached_buffer = hb_buffer_create ();
-
- buffer = cached_buffer;
- *free_buffer = FALSE;
- }
- else
- {
- buffer = hb_buffer_create ();
- *free_buffer = TRUE;
- }
-
- return buffer;
-}
-
-static void
-release_buffer (hb_buffer_t *buffer, gboolean free_buffer)
-{
- if (G_LIKELY (!free_buffer))
- {
- hb_buffer_reset (buffer);
- G_UNLOCK (cached_buffer);
- }
- else
- hb_buffer_destroy (buffer);
-}
-
-static void
-apply_extra_attributes (GSList *attrs,
- hb_feature_t *features,
- guint length,
- guint *num_features)
-{
- GSList *l;
-
- for (l = attrs; l && *num_features < length; l = l->next)
- {
- PangoAttribute *attr = l->data;
- if (attr->klass->type == PANGO_ATTR_FONT_FEATURES)
- {
- PangoAttrFontFeatures *fattr = (PangoAttrFontFeatures *) attr;
- const gchar *feat;
- const gchar *end;
- int len;
-
- feat = fattr->features;
-
- while (feat != NULL && *num_features < length)
- {
- end = strchr (feat, ',');
- if (end)
- len = end - feat;
- else
- len = -1;
- if (hb_feature_from_string (feat, len, &features[*num_features]))
- {
- features[*num_features].start = attr->start_index;
- features[*num_features].end = attr->end_index;
- (*num_features)++;
- }
-
- if (end == NULL)
- break;
-
- feat = end + 1;
- }
- }
- }
-
- /* Turn off ligatures when letterspacing */
- for (l = attrs; l && *num_features < length; l = l->next)
- {
- PangoAttribute *attr = l->data;
- if (attr->klass->type == PANGO_ATTR_LETTER_SPACING)
- {
- hb_tag_t tags[] = {
- HB_TAG('l','i','g','a'),
- HB_TAG('c','l','i','g'),
- HB_TAG('d','l','i','g'),
- };
- int i;
- for (i = 0; i < G_N_ELEMENTS (tags); i++)
- {
- features[*num_features].tag = tags[i];
- features[*num_features].value = 0;
- features[*num_features].start = attr->start_index;
- features[*num_features].end = attr->end_index;
- (*num_features)++;
- }
- }
- }
-}
-
-typedef struct
-{
- PangoFont *font;
- hb_font_t *parent;
- PangoShowFlags show_flags;
-} PangoHbShapeContext;
-
-static hb_bool_t
-pango_hb_font_get_nominal_glyph (hb_font_t *font,
- void *font_data,
- hb_codepoint_t unicode,
- hb_codepoint_t *glyph,
- void *user_data G_GNUC_UNUSED)
-{
- PangoHbShapeContext *context = (PangoHbShapeContext *) font_data;
-
- if (context->show_flags != 0)
- {
- if ((context->show_flags & PANGO_SHOW_SPACES) != 0 &&
- g_unichar_type (unicode) == G_UNICODE_SPACE_SEPARATOR)
- {
- /* Replace 0x20 by visible space, since we
- * don't draw a hex box for 0x20
- */
- if (unicode == 0x20)
- *glyph = PANGO_GET_UNKNOWN_GLYPH (0x2423);
- else
- *glyph = PANGO_GET_UNKNOWN_GLYPH (unicode);
- return TRUE;
- }
-
- if ((context->show_flags & PANGO_SHOW_IGNORABLES) != 0 &&
- pango_get_ignorable (unicode))
- {
- *glyph = PANGO_GET_UNKNOWN_GLYPH (unicode);
- return TRUE;
- }
-
- if ((context->show_flags & PANGO_SHOW_LINE_BREAKS) != 0 &&
- unicode == 0x2028)
- {
- /* Always mark LS as unknown. If it ends up
- * at the line end, PangoLayout takes care of
- * hiding them, and if they end up in the middle
- * of a line, we are in single paragraph mode
- * and want to show the LS
- */
- *glyph = PANGO_GET_UNKNOWN_GLYPH (unicode);
- return TRUE;
- }
- }
-
- if (hb_font_get_nominal_glyph (context->parent, unicode, glyph))
- return TRUE;
-
- *glyph = PANGO_GET_UNKNOWN_GLYPH (unicode);
-
- /* We draw our own invalid-Unicode shape, so prevent HarfBuzz
- * from using REPLACEMENT CHARACTER. */
- if (unicode > 0x10FFFF)
- return TRUE;
-
- return FALSE;
-}
-
-static hb_position_t
-pango_hb_font_get_glyph_h_advance (hb_font_t *font,
- void *font_data,
- hb_codepoint_t glyph,
- void *user_data G_GNUC_UNUSED)
-{
- PangoHbShapeContext *context = (PangoHbShapeContext *) font_data;
-
- if (glyph & PANGO_GLYPH_UNKNOWN_FLAG)
- {
- PangoRectangle logical;
-
- pango_font_get_glyph_extents (context->font, glyph, NULL, &logical);
- return logical.width;
- }
-
- return hb_font_get_glyph_h_advance (context->parent, glyph);
-}
-
-static hb_position_t
-pango_hb_font_get_glyph_v_advance (hb_font_t *font,
- void *font_data,
- hb_codepoint_t glyph,
- void *user_data G_GNUC_UNUSED)
-{
- PangoHbShapeContext *context = (PangoHbShapeContext *) font_data;
-
- if (glyph & PANGO_GLYPH_UNKNOWN_FLAG)
- {
- PangoRectangle logical;
-
- pango_font_get_glyph_extents (context->font, glyph, NULL, &logical);
- return logical.height;
- }
-
- return hb_font_get_glyph_v_advance (context->parent, glyph);
-}
-
-static hb_bool_t
-pango_hb_font_get_glyph_extents (hb_font_t *font,
- void *font_data,
- hb_codepoint_t glyph,
- hb_glyph_extents_t *extents,
- void *user_data G_GNUC_UNUSED)
-{
- PangoHbShapeContext *context = (PangoHbShapeContext *) font_data;
-
- if (glyph & PANGO_GLYPH_UNKNOWN_FLAG)
- {
- PangoRectangle ink;
-
- pango_font_get_glyph_extents (context->font, glyph, &ink, NULL);
-
- extents->x_bearing = ink.x;
- extents->y_bearing = ink.y;
- extents->width = ink.width;
- extents->height = ink.height;
-
- return TRUE;
- }
-
- return hb_font_get_glyph_extents (context->parent, glyph, extents);
-}
-
-static hb_font_t *
-pango_font_get_hb_font_for_context (PangoFont *font,
- PangoHbShapeContext *context)
-{
- hb_font_t *hb_font;
- static hb_font_funcs_t *funcs;
-
- hb_font = pango_font_get_hb_font (font);
-
- if (G_UNLIKELY (!funcs))
- {
- funcs = hb_font_funcs_create ();
-
- hb_font_funcs_set_nominal_glyph_func (funcs, pango_hb_font_get_nominal_glyph, NULL, NULL);
- hb_font_funcs_set_glyph_h_advance_func (funcs, pango_hb_font_get_glyph_h_advance, NULL, NULL);
- hb_font_funcs_set_glyph_v_advance_func (funcs, pango_hb_font_get_glyph_v_advance, NULL, NULL);
- hb_font_funcs_set_glyph_extents_func (funcs, pango_hb_font_get_glyph_extents, NULL, NULL);
-
- hb_font_funcs_make_immutable (funcs);
- }
-
- context->font = font;
- context->parent = hb_font;
-
- hb_font = hb_font_create_sub_font (hb_font);
- hb_font_set_funcs (hb_font, funcs, context, NULL);
-
- return hb_font;
-}
-
-static PangoShowFlags
-find_show_flags (const PangoAnalysis *analysis)
-{
- GSList *l;
- PangoShowFlags flags = 0;
-
- for (l = analysis->extra_attrs; l; l = l->next)
- {
- PangoAttribute *attr = l->data;
-
- if (attr->klass->type == PANGO_ATTR_SHOW)
- flags |= ((PangoAttrInt*)attr)->value;
- }
-
- return flags;
-}
-
-void
-pango_hb_shape (PangoFont *font,
- const char *item_text,
- unsigned int item_length,
- const PangoAnalysis *analysis,
- PangoGlyphString *glyphs,
- const char *paragraph_text,
- unsigned int paragraph_length)
-{
- PangoHbShapeContext context = { 0, };
- hb_buffer_flags_t hb_buffer_flags;
- hb_font_t *hb_font;
- hb_buffer_t *hb_buffer;
- hb_direction_t hb_direction;
- gboolean free_buffer;
- hb_glyph_info_t *hb_glyph;
- hb_glyph_position_t *hb_position;
- int last_cluster;
- guint i, num_glyphs;
- unsigned int item_offset = item_text - paragraph_text;
- hb_feature_t features[32];
- unsigned int num_features = 0;
- PangoGlyphInfo *infos;
-
- g_return_if_fail (font != NULL);
- g_return_if_fail (analysis != NULL);
-
- context.show_flags = find_show_flags (analysis);
- hb_font = pango_font_get_hb_font_for_context (font, &context);
- hb_buffer = acquire_buffer (&free_buffer);
-
- hb_direction = PANGO_GRAVITY_IS_VERTICAL (analysis->gravity) ? HB_DIRECTION_TTB : HB_DIRECTION_LTR;
- if (analysis->level % 2)
- hb_direction = HB_DIRECTION_REVERSE (hb_direction);
- if (PANGO_GRAVITY_IS_IMPROPER (analysis->gravity))
- hb_direction = HB_DIRECTION_REVERSE (hb_direction);
-
- hb_buffer_flags = HB_BUFFER_FLAG_BOT | HB_BUFFER_FLAG_EOT;
-
- if (context.show_flags & PANGO_SHOW_IGNORABLES)
- hb_buffer_flags |= HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES;
-
- /* setup buffer */
-
- hb_buffer_set_direction (hb_buffer, hb_direction);
- hb_buffer_set_script (hb_buffer, (hb_script_t) g_unicode_script_to_iso15924 (analysis->script));
- hb_buffer_set_language (hb_buffer, hb_language_from_string (pango_language_to_string (analysis->language), -1));
- hb_buffer_set_cluster_level (hb_buffer, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
- hb_buffer_set_flags (hb_buffer, hb_buffer_flags);
- hb_buffer_set_invisible_glyph (hb_buffer, PANGO_GLYPH_EMPTY);
-
- hb_buffer_add_utf8 (hb_buffer, paragraph_text, paragraph_length, item_offset, item_length);
- if (analysis->flags & PANGO_ANALYSIS_FLAG_NEED_HYPHEN)
- {
- /* Insert either a Unicode or ASCII hyphen. We may
- * want to look for script-specific hyphens here.
- */
- const char *p = paragraph_text + item_offset + item_length;
- int last_char_len = p - g_utf8_prev_char (p);
- hb_codepoint_t glyph;
-
- if (hb_font_get_nominal_glyph (hb_font, 0x2010, &glyph))
- hb_buffer_add (hb_buffer, 0x2010, item_offset + item_length - last_char_len);
- else if (hb_font_get_nominal_glyph (hb_font, '-', &glyph))
- hb_buffer_add (hb_buffer, '-', item_offset + item_length - last_char_len);
- }
-
- pango_font_get_features (font, features, G_N_ELEMENTS (features), &num_features);
- apply_extra_attributes (analysis->extra_attrs, features, G_N_ELEMENTS (features), &num_features);
-
- hb_shape (hb_font, hb_buffer, features, num_features);
-
- if (PANGO_GRAVITY_IS_IMPROPER (analysis->gravity))
- hb_buffer_reverse (hb_buffer);
-
- /* buffer output */
- num_glyphs = hb_buffer_get_length (hb_buffer);
- hb_glyph = hb_buffer_get_glyph_infos (hb_buffer, NULL);
- pango_glyph_string_set_size (glyphs, num_glyphs);
- infos = glyphs->glyphs;
- last_cluster = -1;
- for (i = 0; i < num_glyphs; i++)
- {
- infos[i].glyph = hb_glyph->codepoint;
- glyphs->log_clusters[i] = hb_glyph->cluster - item_offset;
- infos[i].attr.is_cluster_start = glyphs->log_clusters[i] != last_cluster;
- hb_glyph++;
- last_cluster = glyphs->log_clusters[i];
- }
-
- hb_position = hb_buffer_get_glyph_positions (hb_buffer, NULL);
- if (PANGO_GRAVITY_IS_VERTICAL (analysis->gravity))
- for (i = 0; i < num_glyphs; i++)
- {
- /* 90 degrees rotation counter-clockwise. */
- infos[i].geometry.width = - hb_position->y_advance;
- infos[i].geometry.x_offset = - hb_position->y_offset;
- infos[i].geometry.y_offset = - hb_position->x_offset;
- hb_position++;
- }
- else /* horizontal */
- for (i = 0; i < num_glyphs; i++)
- {
- infos[i].geometry.width = hb_position->x_advance;
- infos[i].geometry.x_offset = hb_position->x_offset;
- infos[i].geometry.y_offset = - hb_position->y_offset;
- hb_position++;
- }
-
- release_buffer (hb_buffer, free_buffer);
- hb_font_destroy (hb_font);
-}
diff --git a/pango/reorder-items.c b/pango/reorder-items.c
index e5ceeb6f..c30d003b 100644
--- a/pango/reorder-items.c
+++ b/pango/reorder-items.c
@@ -20,7 +20,7 @@
*/
#include "config.h"
-#include "pango-glyph.h"
+#include "pango-item.h"
/*
* NB: The contents of the file implement the exact same algorithm
@@ -31,7 +31,7 @@ static GList *reorder_items_recurse (GList *items, int n_items);
/**
* pango_reorder_items:
- * @logical_items: (element-type Pango.Item): a `GList` of `PangoItem`
+ * @items: (element-type Pango.Item): a `GList` of `PangoItem`
* in logical order.
*
* Reorder items from logical order to visual order.
@@ -47,13 +47,14 @@ static GList *reorder_items_recurse (GList *items, int n_items);
* of `PangoItem` structures in visual order.
*/
GList *
-pango_reorder_items (GList *logical_items)
+pango_reorder_items (GList *items)
{
- return reorder_items_recurse (logical_items, g_list_length (logical_items));
+ return reorder_items_recurse (items, g_list_length (items));
}
static GList *
-reorder_items_recurse (GList *items, int n_items)
+reorder_items_recurse (GList *items,
+ int n_items)
{
GList *tmp_list, *level_start_node;
int i, level_start_i;
diff --git a/pango/shape.c b/pango/shape.c
index afb1db0d..f10bd5c9 100644
--- a/pango/shape.c
+++ b/pango/shape.c
@@ -10,7 +10,7 @@
*
* 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
+ * 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
@@ -21,13 +21,473 @@
#include "config.h"
+#include <string.h>
+#include <math.h>
+#include <glib.h>
+
#include "pango-impl-utils.h"
#include "pango-glyph.h"
#include "pangohb-private.h"
#include "pango-font-private.h"
-#include <string.h>
+/* {{{ Harfbuzz shaping */
+
+/* {{{{ Buffer handling */
+static hb_buffer_t *cached_buffer = NULL; /* MT-safe */
+G_LOCK_DEFINE_STATIC (cached_buffer);
+
+static hb_buffer_t *
+acquire_buffer (gboolean *free_buffer)
+{
+ hb_buffer_t *buffer;
+
+ if (G_LIKELY (G_TRYLOCK (cached_buffer)))
+ {
+ if (G_UNLIKELY (!cached_buffer))
+ cached_buffer = hb_buffer_create ();
+
+ buffer = cached_buffer;
+ *free_buffer = FALSE;
+ }
+ else
+ {
+ buffer = hb_buffer_create ();
+ *free_buffer = TRUE;
+ }
+
+ return buffer;
+}
+
+static void
+release_buffer (hb_buffer_t *buffer,
+ gboolean free_buffer)
+{
+ if (G_LIKELY (!free_buffer))
+ {
+ hb_buffer_reset (buffer);
+ G_UNLOCK (cached_buffer);
+ }
+ else
+ hb_buffer_destroy (buffer);
+}
+/* }}}} */
+/* {{{{ Use PangoFont with Harfbuzz */
+
+typedef struct
+{
+ PangoFont *font;
+ hb_font_t *parent;
+ PangoShowFlags show_flags;
+} PangoHbShapeContext;
+
+static hb_bool_t
+pango_hb_font_get_nominal_glyph (hb_font_t *font,
+ void *font_data,
+ hb_codepoint_t unicode,
+ hb_codepoint_t *glyph,
+ void *user_data G_GNUC_UNUSED)
+{
+ PangoHbShapeContext *context = (PangoHbShapeContext *) font_data;
+
+ if (context->show_flags != 0)
+ {
+ if ((context->show_flags & PANGO_SHOW_SPACES) != 0 &&
+ g_unichar_type (unicode) == G_UNICODE_SPACE_SEPARATOR)
+ {
+ /* Replace 0x20 by visible space, since we
+ * don't draw a hex box for 0x20
+ */
+ if (unicode == 0x20)
+ *glyph = PANGO_GET_UNKNOWN_GLYPH (0x2423);
+ else
+ *glyph = PANGO_GET_UNKNOWN_GLYPH (unicode);
+ return TRUE;
+ }
+
+ if ((context->show_flags & PANGO_SHOW_IGNORABLES) != 0 &&
+ pango_get_ignorable (unicode))
+ {
+ *glyph = PANGO_GET_UNKNOWN_GLYPH (unicode);
+ return TRUE;
+ }
+
+ if ((context->show_flags & PANGO_SHOW_LINE_BREAKS) != 0 &&
+ unicode == 0x2028)
+ {
+ /* Always mark LS as unknown. If it ends up
+ * at the line end, PangoLayout takes care of
+ * hiding them, and if they end up in the middle
+ * of a line, we are in single paragraph mode
+ * and want to show the LS
+ */
+ *glyph = PANGO_GET_UNKNOWN_GLYPH (unicode);
+ return TRUE;
+ }
+ }
+
+ if (hb_font_get_nominal_glyph (context->parent, unicode, glyph))
+ return TRUE;
+
+ *glyph = PANGO_GET_UNKNOWN_GLYPH (unicode);
+
+ /* We draw our own invalid-Unicode shape, so prevent HarfBuzz
+ * from using REPLACEMENT CHARACTER. */
+ if (unicode > 0x10FFFF)
+ return TRUE;
+
+ return FALSE;
+}
+
+static hb_position_t
+pango_hb_font_get_glyph_h_advance (hb_font_t *font,
+ void *font_data,
+ hb_codepoint_t glyph,
+ void *user_data G_GNUC_UNUSED)
+{
+ PangoHbShapeContext *context = (PangoHbShapeContext *) font_data;
+
+ if (glyph & PANGO_GLYPH_UNKNOWN_FLAG)
+ {
+ PangoRectangle logical;
+
+ pango_font_get_glyph_extents (context->font, glyph, NULL, &logical);
+ return logical.width;
+ }
+
+ return hb_font_get_glyph_h_advance (context->parent, glyph);
+}
+
+static hb_position_t
+pango_hb_font_get_glyph_v_advance (hb_font_t *font,
+ void *font_data,
+ hb_codepoint_t glyph,
+ void *user_data G_GNUC_UNUSED)
+{
+ PangoHbShapeContext *context = (PangoHbShapeContext *) font_data;
+
+ if (glyph & PANGO_GLYPH_UNKNOWN_FLAG)
+ {
+ PangoRectangle logical;
+
+ pango_font_get_glyph_extents (context->font, glyph, NULL, &logical);
+ return logical.height;
+ }
+
+ return hb_font_get_glyph_v_advance (context->parent, glyph);
+}
+
+static hb_bool_t
+pango_hb_font_get_glyph_extents (hb_font_t *font,
+ void *font_data,
+ hb_codepoint_t glyph,
+ hb_glyph_extents_t *extents,
+ void *user_data G_GNUC_UNUSED)
+{
+ PangoHbShapeContext *context = (PangoHbShapeContext *) font_data;
+
+ if (glyph & PANGO_GLYPH_UNKNOWN_FLAG)
+ {
+ PangoRectangle ink;
+
+ pango_font_get_glyph_extents (context->font, glyph, &ink, NULL);
+
+ extents->x_bearing = ink.x;
+ extents->y_bearing = ink.y;
+ extents->width = ink.width;
+ extents->height = ink.height;
+
+ return TRUE;
+ }
+
+ return hb_font_get_glyph_extents (context->parent, glyph, extents);
+}
+
+static hb_font_t *
+pango_font_get_hb_font_for_context (PangoFont *font,
+ PangoHbShapeContext *context)
+{
+ hb_font_t *hb_font;
+ static hb_font_funcs_t *funcs;
+
+ hb_font = pango_font_get_hb_font (font);
+
+ if (G_UNLIKELY (!funcs))
+ {
+ funcs = hb_font_funcs_create ();
+
+ hb_font_funcs_set_nominal_glyph_func (funcs, pango_hb_font_get_nominal_glyph, NULL, NULL);
+ hb_font_funcs_set_glyph_h_advance_func (funcs, pango_hb_font_get_glyph_h_advance, NULL, NULL);
+ hb_font_funcs_set_glyph_v_advance_func (funcs, pango_hb_font_get_glyph_v_advance, NULL, NULL);
+ hb_font_funcs_set_glyph_extents_func (funcs, pango_hb_font_get_glyph_extents, NULL, NULL);
+
+ hb_font_funcs_make_immutable (funcs);
+ }
+
+ context->font = font;
+ context->parent = hb_font;
+
+ hb_font = hb_font_create_sub_font (hb_font);
+ hb_font_set_funcs (hb_font, funcs, context, NULL);
+
+ return hb_font;
+}
+
+/* }}}} */
+/* {{{{ Utilities */
+static void
+apply_extra_attributes (GSList *attrs,
+ hb_feature_t *features,
+ guint length,
+ guint *num_features)
+{
+ GSList *l;
+
+ for (l = attrs; l && *num_features < length; l = l->next)
+ {
+ PangoAttribute *attr = l->data;
+ if (attr->klass->type == PANGO_ATTR_FONT_FEATURES)
+ {
+ PangoAttrFontFeatures *fattr = (PangoAttrFontFeatures *) attr;
+ const gchar *feat;
+ const gchar *end;
+ int len;
+
+ feat = fattr->features;
+
+ while (feat != NULL && *num_features < length)
+ {
+ end = strchr (feat, ',');
+ if (end)
+ len = end - feat;
+ else
+ len = -1;
+ if (hb_feature_from_string (feat, len, &features[*num_features]))
+ {
+ features[*num_features].start = attr->start_index;
+ features[*num_features].end = attr->end_index;
+ (*num_features)++;
+ }
+
+ if (end == NULL)
+ break;
+
+ feat = end + 1;
+ }
+ }
+ }
+
+ /* Turn off ligatures when letterspacing */
+ for (l = attrs; l && *num_features < length; l = l->next)
+ {
+ PangoAttribute *attr = l->data;
+ if (attr->klass->type == PANGO_ATTR_LETTER_SPACING)
+ {
+ hb_tag_t tags[] = {
+ HB_TAG('l','i','g','a'),
+ HB_TAG('c','l','i','g'),
+ HB_TAG('d','l','i','g'),
+ };
+ int i;
+ for (i = 0; i < G_N_ELEMENTS (tags); i++)
+ {
+ features[*num_features].tag = tags[i];
+ features[*num_features].value = 0;
+ features[*num_features].start = attr->start_index;
+ features[*num_features].end = attr->end_index;
+ (*num_features)++;
+ }
+ }
+ }
+}
+
+static PangoShowFlags
+find_show_flags (const PangoAnalysis *analysis)
+{
+ GSList *l;
+ PangoShowFlags flags = 0;
+
+ for (l = analysis->extra_attrs; l; l = l->next)
+ {
+ PangoAttribute *attr = l->data;
+
+ if (attr->klass->type == PANGO_ATTR_SHOW)
+ flags |= ((PangoAttrInt*)attr)->value;
+ }
+
+ return flags;
+}
+
+/* }}}} */
+void
+pango_hb_shape (PangoFont *font,
+ const char *item_text,
+ unsigned int item_length,
+ const PangoAnalysis *analysis,
+ PangoGlyphString *glyphs,
+ const char *paragraph_text,
+ unsigned int paragraph_length)
+{
+ PangoHbShapeContext context = { 0, };
+ hb_buffer_flags_t hb_buffer_flags;
+ hb_font_t *hb_font;
+ hb_buffer_t *hb_buffer;
+ hb_direction_t hb_direction;
+ gboolean free_buffer;
+ hb_glyph_info_t *hb_glyph;
+ hb_glyph_position_t *hb_position;
+ int last_cluster;
+ guint i, num_glyphs;
+ unsigned int item_offset = item_text - paragraph_text;
+ hb_feature_t features[32];
+ unsigned int num_features = 0;
+ PangoGlyphInfo *infos;
+
+ g_return_if_fail (font != NULL);
+ g_return_if_fail (analysis != NULL);
+
+ context.show_flags = find_show_flags (analysis);
+ hb_font = pango_font_get_hb_font_for_context (font, &context);
+ hb_buffer = acquire_buffer (&free_buffer);
+
+ hb_direction = PANGO_GRAVITY_IS_VERTICAL (analysis->gravity) ? HB_DIRECTION_TTB : HB_DIRECTION_LTR;
+ if (analysis->level % 2)
+ hb_direction = HB_DIRECTION_REVERSE (hb_direction);
+ if (PANGO_GRAVITY_IS_IMPROPER (analysis->gravity))
+ hb_direction = HB_DIRECTION_REVERSE (hb_direction);
+
+ hb_buffer_flags = HB_BUFFER_FLAG_BOT | HB_BUFFER_FLAG_EOT;
+
+ if (context.show_flags & PANGO_SHOW_IGNORABLES)
+ hb_buffer_flags |= HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES;
+
+ /* setup buffer */
+
+ hb_buffer_set_direction (hb_buffer, hb_direction);
+ hb_buffer_set_script (hb_buffer, (hb_script_t) g_unicode_script_to_iso15924 (analysis->script));
+ hb_buffer_set_language (hb_buffer, hb_language_from_string (pango_language_to_string (analysis->language), -1));
+ hb_buffer_set_cluster_level (hb_buffer, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
+ hb_buffer_set_flags (hb_buffer, hb_buffer_flags);
+ hb_buffer_set_invisible_glyph (hb_buffer, PANGO_GLYPH_EMPTY);
+
+ hb_buffer_add_utf8 (hb_buffer, paragraph_text, paragraph_length, item_offset, item_length);
+ if (analysis->flags & PANGO_ANALYSIS_FLAG_NEED_HYPHEN)
+ {
+ /* Insert either a Unicode or ASCII hyphen. We may
+ * want to look for script-specific hyphens here.
+ */
+ const char *p = paragraph_text + item_offset + item_length;
+ int last_char_len = p - g_utf8_prev_char (p);
+ hb_codepoint_t glyph;
+
+ if (hb_font_get_nominal_glyph (hb_font, 0x2010, &glyph))
+ hb_buffer_add (hb_buffer, 0x2010, item_offset + item_length - last_char_len);
+ else if (hb_font_get_nominal_glyph (hb_font, '-', &glyph))
+ hb_buffer_add (hb_buffer, '-', item_offset + item_length - last_char_len);
+ }
+
+ pango_font_get_features (font, features, G_N_ELEMENTS (features), &num_features);
+ apply_extra_attributes (analysis->extra_attrs, features, G_N_ELEMENTS (features), &num_features);
+
+ hb_shape (hb_font, hb_buffer, features, num_features);
+
+ if (PANGO_GRAVITY_IS_IMPROPER (analysis->gravity))
+ hb_buffer_reverse (hb_buffer);
+
+ /* buffer output */
+ num_glyphs = hb_buffer_get_length (hb_buffer);
+ hb_glyph = hb_buffer_get_glyph_infos (hb_buffer, NULL);
+ pango_glyph_string_set_size (glyphs, num_glyphs);
+ infos = glyphs->glyphs;
+ last_cluster = -1;
+ for (i = 0; i < num_glyphs; i++)
+ {
+ infos[i].glyph = hb_glyph->codepoint;
+ glyphs->log_clusters[i] = hb_glyph->cluster - item_offset;
+ infos[i].attr.is_cluster_start = glyphs->log_clusters[i] != last_cluster;
+ hb_glyph++;
+ last_cluster = glyphs->log_clusters[i];
+ }
+
+ hb_position = hb_buffer_get_glyph_positions (hb_buffer, NULL);
+ if (PANGO_GRAVITY_IS_VERTICAL (analysis->gravity))
+ for (i = 0; i < num_glyphs; i++)
+ {
+ /* 90 degrees rotation counter-clockwise. */
+ infos[i].geometry.width = - hb_position->y_advance;
+ infos[i].geometry.x_offset = - hb_position->y_offset;
+ infos[i].geometry.y_offset = - hb_position->x_offset;
+ hb_position++;
+ }
+ else /* horizontal */
+ for (i = 0; i < num_glyphs; i++)
+ {
+ infos[i].geometry.width = hb_position->x_advance;
+ infos[i].geometry.x_offset = hb_position->x_offset;
+ infos[i].geometry.y_offset = - hb_position->y_offset;
+ hb_position++;
+ }
+
+ release_buffer (hb_buffer, free_buffer);
+ hb_font_destroy (hb_font);
+}
+
+/* }}} */
+/* {{{ Fallback shaping */
+
+/* This is not meant to produce reasonable results */
+
+static void
+fallback_shape (const char *text,
+ unsigned int length,
+ const PangoAnalysis *analysis,
+ PangoGlyphString *glyphs)
+{
+ int n_chars;
+ const char *p;
+ int cluster = 0;
+ int i;
+
+ n_chars = text ? pango_utf8_strlen (text, length) : 0;
+
+ pango_glyph_string_set_size (glyphs, n_chars);
+
+ p = text;
+ for (i = 0; i < n_chars; i++)
+ {
+ gunichar wc;
+ PangoGlyph glyph;
+ PangoRectangle logical_rect;
+
+ wc = g_utf8_get_char (p);
+
+ if (g_unichar_type (wc) != G_UNICODE_NON_SPACING_MARK)
+ cluster = p - text;
+
+ if (pango_is_zero_width (wc))
+ glyph = PANGO_GLYPH_EMPTY;
+ else
+ glyph = PANGO_GET_UNKNOWN_GLYPH (wc);
+
+ pango_font_get_glyph_extents (analysis->font, glyph, NULL, &logical_rect);
+
+ glyphs->glyphs[i].glyph = glyph;
+
+ glyphs->glyphs[i].geometry.x_offset = 0;
+ glyphs->glyphs[i].geometry.y_offset = 0;
+ glyphs->glyphs[i].geometry.width = logical_rect.width;
+
+ glyphs->log_clusters[i] = cluster;
+
+ p = g_utf8_next_char (p);
+ }
+
+ if (analysis->level & 1)
+ pango_glyph_string_reverse_range (glyphs, 0, glyphs->num_glyphs);
+}
+
+/* }}} */
+/* {{{ Public API */
/**
* pango_shape:
@@ -52,10 +512,10 @@
* calling [func@shape].
*/
void
-pango_shape (const gchar *text,
- gint length,
- const PangoAnalysis *analysis,
- PangoGlyphString *glyphs)
+pango_shape (const char *text,
+ int length,
+ const PangoAnalysis *analysis,
+ PangoGlyphString *glyphs)
{
pango_shape_full (text, length, text, length, analysis, glyphs);
}
@@ -103,55 +563,6 @@ pango_shape_full (const char *item_text,
PANGO_SHAPE_NONE);
}
-static void
-fallback_shape (const char *text,
- unsigned int length,
- const PangoAnalysis *analysis,
- PangoGlyphString *glyphs)
-{
- int n_chars;
- const char *p;
- int cluster = 0;
- int i;
-
- n_chars = text ? pango_utf8_strlen (text, length) : 0;
-
- pango_glyph_string_set_size (glyphs, n_chars);
-
- p = text;
- for (i = 0; i < n_chars; i++)
- {
- gunichar wc;
- PangoGlyph glyph;
- PangoRectangle logical_rect;
-
- wc = g_utf8_get_char (p);
-
- if (g_unichar_type (wc) != G_UNICODE_NON_SPACING_MARK)
- cluster = p - text;
-
- if (pango_is_zero_width (wc))
- glyph = PANGO_GLYPH_EMPTY;
- else
- glyph = PANGO_GET_UNKNOWN_GLYPH (wc);
-
- pango_font_get_glyph_extents (analysis->font, glyph, NULL, &logical_rect);
-
- glyphs->glyphs[i].glyph = glyph;
-
- glyphs->glyphs[i].geometry.x_offset = 0;
- glyphs->glyphs[i].geometry.y_offset = 0;
- glyphs->glyphs[i].geometry.width = logical_rect.width;
-
- glyphs->log_clusters[i] = cluster;
-
- p = g_utf8_next_char (p);
- }
-
- if (analysis->level & 1)
- pango_glyph_string_reverse_range (glyphs, 0, glyphs->num_glyphs);
-}
-
/**
* pango_shape_with_flags:
* @item_text: valid UTF-8 text to shape
@@ -183,10 +594,10 @@ fallback_shape (const char *text,
* Since: 1.44
*/
void
-pango_shape_with_flags (const gchar *item_text,
- gint item_length,
- const gchar *paragraph_text,
- gint paragraph_length,
+pango_shape_with_flags (const char *item_text,
+ int item_length,
+ const char *paragraph_text,
+ int paragraph_length,
const PangoAnalysis *analysis,
PangoGlyphString *glyphs,
PangoShapeFlags flags)
@@ -218,19 +629,19 @@ pango_shape_with_flags (const gchar *item_text,
paragraph_text, paragraph_length);
if (G_UNLIKELY (glyphs->num_glyphs == 0))
- {
- /* If a font has been correctly chosen, but no glyphs are output,
- * there's probably something wrong with the font.
- *
- * Trying to be informative, we print out the font description,
- * and the text, but to not flood the terminal with
- * zillions of the message, we set a flag to only err once per
- * font.
- */
+ {
+ /* If a font has been correctly chosen, but no glyphs are output,
+ * there's probably something wrong with the font.
+ *
+ * Trying to be informative, we print out the font description,
+ * and the text, but to not flood the terminal with
+ * zillions of the message, we set a flag to only err once per
+ * font.
+ */
GQuark warned_quark = g_quark_from_static_string ("pango-shape-fail-warned");
- if (!g_object_get_qdata (G_OBJECT (analysis->font), warned_quark))
- {
+ if (!g_object_get_qdata (G_OBJECT (analysis->font), warned_quark))
+ {
PangoFontDescription *desc;
char *font_name;
@@ -246,7 +657,7 @@ pango_shape_with_flags (const gchar *item_text,
g_object_set_qdata (G_OBJECT (analysis->font), warned_quark,
GINT_TO_POINTER (1));
}
- }
+ }
}
else
glyphs->num_glyphs = 0;
@@ -264,12 +675,12 @@ pango_shape_with_flags (const gchar *item_text,
{
/* Set glyphs[i].attr.is_cluster_start based on log_clusters[] */
if (glyphs->log_clusters[i] != last_cluster)
- {
- glyphs->glyphs[i].attr.is_cluster_start = TRUE;
- last_cluster = glyphs->log_clusters[i];
- }
+ {
+ glyphs->glyphs[i].attr.is_cluster_start = TRUE;
+ last_cluster = glyphs->log_clusters[i];
+ }
else
- glyphs->glyphs[i].attr.is_cluster_start = FALSE;
+ glyphs->glyphs[i].attr.is_cluster_start = FALSE;
/* Shift glyph if width is negative, and negate width.
@@ -277,15 +688,15 @@ pango_shape_with_flags (const gchar *item_text,
* harm in normal cases.
*/
if (glyphs->glyphs[i].geometry.width < 0)
- {
- glyphs->glyphs[i].geometry.width = -glyphs->glyphs[i].geometry.width;
- glyphs->glyphs[i].geometry.x_offset += glyphs->glyphs[i].geometry.width;
- }
+ {
+ glyphs->glyphs[i].geometry.width = -glyphs->glyphs[i].geometry.width;
+ glyphs->glyphs[i].geometry.x_offset += glyphs->glyphs[i].geometry.width;
+ }
}
/* Make sure glyphstring direction conforms to analysis->level */
if (G_UNLIKELY ((analysis->level & 1) &&
- glyphs->log_clusters[0] < glyphs->log_clusters[glyphs->num_glyphs - 1]))
+ glyphs->log_clusters[0] < glyphs->log_clusters[glyphs->num_glyphs - 1]))
{
g_warning ("Expected RTL run but got LTR. Fixing.");
@@ -355,3 +766,7 @@ pango_shape_with_flags (const gchar *item_text,
}
}
}
+
+/* }}} */
+
+/* vim:set foldmethod=marker expandtab: */