diff options
author | Owen Taylor <otaylor@redhat.com> | 2002-12-03 06:21:49 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@src.gnome.org> | 2002-12-03 06:21:49 +0000 |
commit | 891b984fc26e0f2422a6c5c13d5b310dc7c2f7e9 (patch) | |
tree | ef651ed3c746e47dd08fc1accf97d5649454d835 /pango/pango-glyph-item.c | |
parent | bbdb12a9e6894109259286050464da44904d21d8 (diff) | |
download | pango-891b984fc26e0f2422a6c5c13d5b310dc7c2f7e9.tar.gz |
Rename PangoLayoutRun to PangoGlyphItem (with a typedef for compat), add
Sun Nov 17 23:28:26 2002 Owen Taylor <otaylor@redhat.com>
* pango/pango-glyph-item.[ch] pango/pango-layout.h:
Rename PangoLayoutRun to PangoGlyphItem (with a
typedef for compat), add pango_glyph_item_split(),
pango_glyph_item_apply_attrs().
* pango/pango-attributes.[ch]: Add
pango_attr_list_filter(), pango_attr_iterator_get_attrs().
* pango/pango-layout.c: Remove attributes that don't
affect shaping before shaping, shape and then add
them back. Fixes the infamous "underscores break
arabic shaping" bug (#83058)
* pango/pango-item.h: Remove an extraneous include.
* pango/pango-layout.c (imposed_shape): Fix bytes/chars
problem for glyph->log_clusters.
* pango/pango-layout.c (cluster_end_index)
* pango/pango-layout.c (pango_layout_iter_next_cluster): Fix
confusion between global indices and run-relative indices.
* docs/tmpl/glyphs.sgml: Improve docs for log_clusters.
* docs/*: Document new API and PangoOTRuleset
Diffstat (limited to 'pango/pango-glyph-item.c')
-rw-r--r-- | pango/pango-glyph-item.c | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/pango/pango-glyph-item.c b/pango/pango-glyph-item.c new file mode 100644 index 00000000..0ea520ac --- /dev/null +++ b/pango/pango-glyph-item.c @@ -0,0 +1,208 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* Pango + * pango-glyph-item.c: Pair of PangoItem and a glyph string + * + * Copyright (C) 2002 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 <string.h> + +#include "pango-glyph-item.h" + +/** + * pango_glyph_item_split: + * @orig: a #PangoItem + * @text: text to which positions in @orig apply. + * @split_index: byte index of position to split item, relative to the start of the item + * + * Modifies @orig to cover only the text after @split_index, and + * returns a new item that covers the text before @split_index that + * used to be in @orig. You can think of @split_index as the length of + * the returned item. @split_index may not be 0, and it may not be + * greater than or equal to the length of @orig (that is, there must + * be at least one byte assigned to each item, you can't create a + * zero-length item). + * + * This function is similar in function to pango_item_split() (and uses + * it internally) + * + * Return value: new item representing text before @split_index + **/ +PangoGlyphItem * +pango_glyph_item_split (PangoGlyphItem *orig, + const char *text, + int split_index) +{ + PangoGlyphItem *new; + int i; + int num_glyphs; + int num_remaining; + int split_offset; + gboolean ltr = (orig->item->analysis.level % 2) == 0; + + g_return_val_if_fail (orig != NULL, NULL); + g_return_val_if_fail (orig->item->length > 0, NULL); + g_return_val_if_fail (split_index > 0, NULL); + g_return_val_if_fail (split_index < orig->item->length, NULL); + + if (ltr) + { + for (i = 0; i < orig->glyphs->num_glyphs; i++) + { + if (orig->glyphs->log_clusters[i] >= split_index) + break; + } + + if (i == orig->glyphs->num_glyphs) /* No splitting necessary */ + return NULL; + + split_index = orig->glyphs->log_clusters[i]; + num_glyphs = i; + } + else + { + for (i = orig->glyphs->num_glyphs - 1; i >= 0; i--) + { + if (orig->glyphs->log_clusters[i] >= split_index) + break; + } + + if (i < 0) /* No splitting necessary */ + return NULL; + + split_index = orig->glyphs->log_clusters[i]; + num_glyphs = orig->glyphs->num_glyphs - 1 - i; + } + + num_remaining = orig->glyphs->num_glyphs - num_glyphs; + + new = g_new (PangoGlyphItem, 1); + split_offset = g_utf8_pointer_to_offset (text + orig->item->offset, + text + orig->item->offset + split_index); + new->item = pango_item_split (orig->item, split_index, split_offset); + + new->glyphs = pango_glyph_string_new (); + pango_glyph_string_set_size (new->glyphs, num_glyphs); + + if (ltr) + { + memcpy (new->glyphs->glyphs, orig->glyphs->glyphs, num_glyphs * sizeof (PangoGlyphInfo)); + memcpy (new->glyphs->log_clusters, orig->glyphs->log_clusters, num_glyphs * sizeof (int)); + + memmove (orig->glyphs->glyphs, orig->glyphs->glyphs + num_glyphs, + num_remaining * sizeof (PangoGlyphInfo)); + for (i = num_glyphs; i < orig->glyphs->num_glyphs; i++) + orig->glyphs->log_clusters[i - num_glyphs] = orig->glyphs->log_clusters[i] - split_index; + } + else + { + memcpy (new->glyphs->glyphs, orig->glyphs->glyphs + num_remaining, num_glyphs * sizeof (PangoGlyphInfo)); + memcpy (new->glyphs->log_clusters, orig->glyphs->log_clusters + num_remaining, num_glyphs * sizeof (int)); + + for (i = 0; i < num_remaining; i++) + orig->glyphs->log_clusters[i] = orig->glyphs->log_clusters[i] - split_index; + } + + pango_glyph_string_set_size (orig->glyphs, orig->glyphs->num_glyphs - num_glyphs); + + return new; +} + +static void +append_attrs (PangoGlyphItem *glyph_item, + GSList *attrs) +{ + glyph_item->item->analysis.extra_attrs = + g_slist_concat (glyph_item->item->analysis.extra_attrs, attrs); +} + +/** + * pango_glyph_item_apply_attrs: + * @glyph_item: a shaped item + * @text: text that @list applies to + * @list: a #PangoAttrList + * + * Splits a shaped item (PangoGlyphItem) into multiple items based + * on an attribute list. The idea is that if you have attributes + * that don't affect shaping, such as color or underline, to avoid + * affecting shaping, you filter them out (pango_attr_list_filter()), + * apply the shaping process and then reapply them to the result using + * this function. + * + * This function takes ownership of @glyph_item; it will be reused + * as one of the elements in the list. + * + * Return value: a list of glyph items resulting from splitting + * @glyph_item. Free the elements using pango_glyph_item_free(), + * the list using g_slist_free(). + **/ +GSList * +pango_glyph_item_apply_attrs (PangoGlyphItem *glyph_item, + const char *text, + PangoAttrList *list) +{ + PangoAttrIterator *iter = pango_attr_list_get_iterator (list); + PangoGlyphItem *new; + GSList *result = NULL; + int start; + int end; + + gboolean ltr = (glyph_item->item->analysis.level % 2) == 0; + + while (TRUE) + { + pango_attr_iterator_range (iter, &start, &end); + + if (start > glyph_item->item->offset) + { + if (start >= glyph_item->item->offset + glyph_item->item->length) + break; + + new = pango_glyph_item_split (glyph_item, text, + start - glyph_item->item->offset); + + result = g_slist_prepend (result, new); + } + + if (end > glyph_item->item->offset) + { + if (end >= glyph_item->item->offset + glyph_item->item->length) + { + append_attrs (glyph_item, pango_attr_iterator_get_attrs (iter)); + break; + } + + new = pango_glyph_item_split (glyph_item, text, + end - glyph_item->item->offset); + + append_attrs (new, pango_attr_iterator_get_attrs (iter)); + + result = g_slist_prepend (result, new); + } + + if (!pango_attr_iterator_next (iter)) + break; + } + + result = g_slist_prepend (result, glyph_item); + + if (ltr) + result = g_slist_reverse (result); + + return result; +} |