diff options
author | Owen Taylor <otaylor@redhat.com> | 2004-06-23 19:00:36 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@src.gnome.org> | 2004-06-23 19:00:36 +0000 |
commit | 3aabb8d5ce0720c9a22cdcf975380d1d0213c4c8 (patch) | |
tree | b6a641821de5c6e8643fb869c3950cd9d167ed61 | |
parent | 1939a027b1d4e6c7d83af9e42e191f1bfb0cf8a0 (diff) | |
download | pango-3aabb8d5ce0720c9a22cdcf975380d1d0213c4c8.tar.gz |
Add new letter_spacing attribute.
Wed Jun 23 11:17:51 2004 Owen Taylor <otaylor@redhat.com>
* pango/pango-attributes.[ch]: Add new letter_spacing
attribute.
* pango/pango-attributes.c (pango_attr_rise_new): Correct
description; rise is in Pango units, not em-relative.
* pango/pango-glyph-item.c: Break out iteration-over-clusters
from ApplyAttrsState into a separate GlyphItemIter.
* pango/pango-glyph-item.[ch]: New function
pango_glyph_item_letter_space() to add add letter spacing
to a single glyph item.
* pango/pango-markup.c: Add a letter_spacing attribute.
* pango/pango-layout.c: Use G_DEFINE_TYPE().
* pango/pango-layout.c (pango_layout_get_item_properties):
Switch to use a structure rather than a pile of out
parameters.
* pango/pango-layout.c (pango_run_get_extents): Remove
the unused shape_set out parameter.
* pango/pangofc-decoder.[ch] pango/pangofc-fontmap.[ch]:
Doc fixes.
* pango/pango-types.h: Deprecate pango_get_mirror_char()
* pango/pango-utils.c (pango_get_mirror_char): Add docs.
* docs/pango-sections.txt docs/pango-docs.sgml: Add
PangoFcDecoder and letter spacing.
-rw-r--r-- | ChangeLog | 36 | ||||
-rw-r--r-- | ChangeLog.pre-1-10 | 36 | ||||
-rw-r--r-- | ChangeLog.pre-1-6 | 36 | ||||
-rw-r--r-- | ChangeLog.pre-1-8 | 36 | ||||
-rw-r--r-- | docs/pango-docs.sgml | 2 | ||||
-rw-r--r-- | docs/pango-sections.txt | 21 | ||||
-rw-r--r-- | docs/pango.types | 1 | ||||
-rw-r--r-- | docs/tmpl/glyphs.sgml | 11 | ||||
-rw-r--r-- | docs/tmpl/pangofc-fontmap.sgml | 21 | ||||
-rw-r--r-- | docs/tmpl/text-attributes.sgml | 10 | ||||
-rw-r--r-- | pango/pango-attributes.c | 27 | ||||
-rw-r--r-- | pango/pango-attributes.h | 4 | ||||
-rw-r--r-- | pango/pango-glyph-item.c | 246 | ||||
-rw-r--r-- | pango/pango-glyph-item.h | 17 | ||||
-rw-r--r-- | pango/pango-layout.c | 380 | ||||
-rw-r--r-- | pango/pango-markup.c | 28 | ||||
-rw-r--r-- | pango/pango-types.h | 4 | ||||
-rw-r--r-- | pango/pango-utils.c | 15 | ||||
-rw-r--r-- | pango/pangofc-decoder.c | 45 | ||||
-rw-r--r-- | pango/pangofc-decoder.h | 20 | ||||
-rw-r--r-- | pango/pangofc-fontmap.c | 25 | ||||
-rw-r--r-- | pango/pangofc-fontmap.h | 10 |
22 files changed, 762 insertions, 269 deletions
@@ -1,3 +1,39 @@ +Wed Jun 23 11:17:51 2004 Owen Taylor <otaylor@redhat.com> + + * pango/pango-attributes.[ch]: Add new letter_spacing + attribute. + + * pango/pango-attributes.c (pango_attr_rise_new): Correct + description; rise is in Pango units, not em-relative. + + * pango/pango-glyph-item.c: Break out iteration-over-clusters + from ApplyAttrsState into a separate GlyphItemIter. + + * pango/pango-glyph-item.[ch]: New function + pango_glyph_item_letter_space() to add add letter spacing + to a single glyph item. + + * pango/pango-markup.c: Add a letter_spacing attribute. + + * pango/pango-layout.c: Use G_DEFINE_TYPE(). + + * pango/pango-layout.c (pango_layout_get_item_properties): + Switch to use a structure rather than a pile of out + parameters. + + * pango/pango-layout.c (pango_run_get_extents): Remove + the unused shape_set out parameter. + + * pango/pangofc-decoder.[ch] pango/pangofc-fontmap.[ch]: + Doc fixes. + + * pango/pango-types.h: Deprecate pango_get_mirror_char() + + * pango/pango-utils.c (pango_get_mirror_char): Add docs. + + * docs/pango-sections.txt docs/pango-docs.sgml: Add + PangoFcDecoder and letter spacing. + Tue Jun 22 14:10:41 2004 Owen Taylor <otaylor@redhat.com> * pango/break.c: Handle new Unicode-4.0 WORD_JOINER diff --git a/ChangeLog.pre-1-10 b/ChangeLog.pre-1-10 index 5e806cfe..77b8baba 100644 --- a/ChangeLog.pre-1-10 +++ b/ChangeLog.pre-1-10 @@ -1,3 +1,39 @@ +Wed Jun 23 11:17:51 2004 Owen Taylor <otaylor@redhat.com> + + * pango/pango-attributes.[ch]: Add new letter_spacing + attribute. + + * pango/pango-attributes.c (pango_attr_rise_new): Correct + description; rise is in Pango units, not em-relative. + + * pango/pango-glyph-item.c: Break out iteration-over-clusters + from ApplyAttrsState into a separate GlyphItemIter. + + * pango/pango-glyph-item.[ch]: New function + pango_glyph_item_letter_space() to add add letter spacing + to a single glyph item. + + * pango/pango-markup.c: Add a letter_spacing attribute. + + * pango/pango-layout.c: Use G_DEFINE_TYPE(). + + * pango/pango-layout.c (pango_layout_get_item_properties): + Switch to use a structure rather than a pile of out + parameters. + + * pango/pango-layout.c (pango_run_get_extents): Remove + the unused shape_set out parameter. + + * pango/pangofc-decoder.[ch] pango/pangofc-fontmap.[ch]: + Doc fixes. + + * pango/pango-types.h: Deprecate pango_get_mirror_char() + + * pango/pango-utils.c (pango_get_mirror_char): Add docs. + + * docs/pango-sections.txt docs/pango-docs.sgml: Add + PangoFcDecoder and letter spacing. + Tue Jun 22 14:10:41 2004 Owen Taylor <otaylor@redhat.com> * pango/break.c: Handle new Unicode-4.0 WORD_JOINER diff --git a/ChangeLog.pre-1-6 b/ChangeLog.pre-1-6 index 5e806cfe..77b8baba 100644 --- a/ChangeLog.pre-1-6 +++ b/ChangeLog.pre-1-6 @@ -1,3 +1,39 @@ +Wed Jun 23 11:17:51 2004 Owen Taylor <otaylor@redhat.com> + + * pango/pango-attributes.[ch]: Add new letter_spacing + attribute. + + * pango/pango-attributes.c (pango_attr_rise_new): Correct + description; rise is in Pango units, not em-relative. + + * pango/pango-glyph-item.c: Break out iteration-over-clusters + from ApplyAttrsState into a separate GlyphItemIter. + + * pango/pango-glyph-item.[ch]: New function + pango_glyph_item_letter_space() to add add letter spacing + to a single glyph item. + + * pango/pango-markup.c: Add a letter_spacing attribute. + + * pango/pango-layout.c: Use G_DEFINE_TYPE(). + + * pango/pango-layout.c (pango_layout_get_item_properties): + Switch to use a structure rather than a pile of out + parameters. + + * pango/pango-layout.c (pango_run_get_extents): Remove + the unused shape_set out parameter. + + * pango/pangofc-decoder.[ch] pango/pangofc-fontmap.[ch]: + Doc fixes. + + * pango/pango-types.h: Deprecate pango_get_mirror_char() + + * pango/pango-utils.c (pango_get_mirror_char): Add docs. + + * docs/pango-sections.txt docs/pango-docs.sgml: Add + PangoFcDecoder and letter spacing. + Tue Jun 22 14:10:41 2004 Owen Taylor <otaylor@redhat.com> * pango/break.c: Handle new Unicode-4.0 WORD_JOINER diff --git a/ChangeLog.pre-1-8 b/ChangeLog.pre-1-8 index 5e806cfe..77b8baba 100644 --- a/ChangeLog.pre-1-8 +++ b/ChangeLog.pre-1-8 @@ -1,3 +1,39 @@ +Wed Jun 23 11:17:51 2004 Owen Taylor <otaylor@redhat.com> + + * pango/pango-attributes.[ch]: Add new letter_spacing + attribute. + + * pango/pango-attributes.c (pango_attr_rise_new): Correct + description; rise is in Pango units, not em-relative. + + * pango/pango-glyph-item.c: Break out iteration-over-clusters + from ApplyAttrsState into a separate GlyphItemIter. + + * pango/pango-glyph-item.[ch]: New function + pango_glyph_item_letter_space() to add add letter spacing + to a single glyph item. + + * pango/pango-markup.c: Add a letter_spacing attribute. + + * pango/pango-layout.c: Use G_DEFINE_TYPE(). + + * pango/pango-layout.c (pango_layout_get_item_properties): + Switch to use a structure rather than a pile of out + parameters. + + * pango/pango-layout.c (pango_run_get_extents): Remove + the unused shape_set out parameter. + + * pango/pangofc-decoder.[ch] pango/pangofc-fontmap.[ch]: + Doc fixes. + + * pango/pango-types.h: Deprecate pango_get_mirror_char() + + * pango/pango-utils.c (pango_get_mirror_char): Add docs. + + * docs/pango-sections.txt docs/pango-docs.sgml: Add + PangoFcDecoder and letter spacing. + Tue Jun 22 14:10:41 2004 Owen Taylor <otaylor@redhat.com> * pango/break.c: Handle new Unicode-4.0 WORD_JOINER diff --git a/docs/pango-docs.sgml b/docs/pango-docs.sgml index a923b96c..ea014a5e 100644 --- a/docs/pango-docs.sgml +++ b/docs/pango-docs.sgml @@ -19,6 +19,7 @@ <!ENTITY pango-Xft-Fonts-and-Rendering SYSTEM "xml/xft-fonts.xml"> <!ENTITY PangoFcFontMap SYSTEM "xml/pangofc-fontmap.xml"> <!ENTITY PangoFcFont SYSTEM "xml/pangofc-font.xml"> +<!ENTITY PangoFcDecoder SYSTEM "xml/pangofc-decoder.xml"> <!ENTITY pango-OpenType-Font-Handling SYSTEM "xml/opentype.xml"> <!ENTITY markup-format SYSTEM "pango_markup.sgml"> <!ENTITY pango-querymodules SYSTEM "pango-querymodules.xml"> @@ -54,6 +55,7 @@ <title>Low Level Functionality</title> &PangoFcFontMap; &PangoFcFont; + &PangoFcDecoder; &pango-OpenType-Font-Handling; &pango-Coverage-Maps; &pango-Engines; diff --git a/docs/pango-sections.txt b/docs/pango-sections.txt index c3b73f90..d6eafa31 100644 --- a/docs/pango-sections.txt +++ b/docs/pango-sections.txt @@ -93,6 +93,7 @@ pango_glyph_string_x_to_index pango_glyph_string_get_logical_widths pango_glyph_item_split pango_glyph_item_apply_attrs +pango_glyph_item_letter_space <SUBSECTION Private> pango_glyph_string_get_type @@ -312,6 +313,7 @@ PANGO_SCALE_LARGE PANGO_SCALE_X_LARGE PANGO_SCALE_XX_LARGE pango_attr_rise_new +pango_attr_letter_spacing_new PangoColor PANGO_TYPE_COLOR pango_color_free @@ -697,6 +699,8 @@ pango_fc_font_description_from_pattern pango_fc_font_map_cache_clear pango_fc_font_map_create_context pango_fc_font_map_shutdown +pango_fc_font_map_add_decoder_find_func +PangoFcDecoderFindFunc <SUBSECTION Standard> PANGO_FC_FONT_MAP PANGO_IS_FC_FONT_MAP @@ -734,6 +738,23 @@ pango_fc_font_get_type </SECTION> <SECTION> +<FILE>pangofc-decoder</FILE> +<TITLE>PangoFcDecoder</TITLE> +PangoFcDecoder +PangoFcDecoderClass +pango_fc_decoder_get_charset +pango_fc_decoder_get_glyph +<SUBSECTION Standard> +PANGO_FC_DECODER +PANGO_IS_FC_DECODER +PANGO_TYPE_FC_DECODER +pango_fc_decoder_get_type +PANGO_FC_DECODER_CLASS +PANGO_IS_FC_DECODER_CLASS +PANGO_FC_DECODER_GET_CLASS +</SECTION> + +<SECTION> <TITLE>OpenType Font Handling</TITLE> <FILE>opentype</FILE> PangoOTTag diff --git a/docs/pango.types b/docs/pango.types index 4e54d55f..5cda42a7 100644 --- a/docs/pango.types +++ b/docs/pango.types @@ -16,6 +16,7 @@ pango_fontset_get_type pango_fontset_simple_get_type pango_fc_font_get_type pango_fc_font_map_get_type +pango_fc_decoder_get_type pango_ft2_font_map_get_type pango_xft_font_get_type diff --git a/docs/tmpl/glyphs.sgml b/docs/tmpl/glyphs.sgml index 952435a3..435d939d 100644 --- a/docs/tmpl/glyphs.sgml +++ b/docs/tmpl/glyphs.sgml @@ -393,3 +393,14 @@ The GObject type for #PangoGlyphString. @Returns: +<!-- ##### FUNCTION pango_glyph_item_letter_space ##### --> +<para> + +</para> + +@glyph_item: +@text: +@log_attrs: +@letter_spacing: + + diff --git a/docs/tmpl/pangofc-fontmap.sgml b/docs/tmpl/pangofc-fontmap.sgml index 7c505247..db72b732 100644 --- a/docs/tmpl/pangofc-fontmap.sgml +++ b/docs/tmpl/pangofc-fontmap.sgml @@ -84,3 +84,24 @@ Fontconfig-based backend involves deriving from both @fontmap: +<!-- ##### FUNCTION pango_fc_font_map_add_decoder_find_func ##### --> +<para> + +</para> + +@fcfontmap: +@findfunc: +@user_data: +@dnotify: + + +<!-- ##### USER_FUNCTION PangoFcDecoderFindFunc ##### --> +<para> + +</para> + +@pattern: +@user_data: +@Returns: + + diff --git a/docs/tmpl/text-attributes.sgml b/docs/tmpl/text-attributes.sgml index 907b2f0a..9690711f 100644 --- a/docs/tmpl/text-attributes.sgml +++ b/docs/tmpl/text-attributes.sgml @@ -44,6 +44,7 @@ attribute is listed in parentheses after the description. @PANGO_ATTR_SHAPE: shape (#PangoAttrShape) @PANGO_ATTR_SCALE: font size scale factor (#PangoAttrScale) @PANGO_ATTR_FALLBACK: whether fallback is enabled (#PangoAttrInt) +@PANGO_ATTR_LETTER_SPACING: <!-- ##### MACRO PANGO_TYPE_ATTR_TYPE ##### --> <para> @@ -421,6 +422,15 @@ The scale factor for three magnification steps (1.2 * 1.2 * 1.2). @Returns: +<!-- ##### FUNCTION pango_attr_letter_spacing_new ##### --> +<para> + +</para> + +@letter_spacing: +@Returns: + + <!-- ##### STRUCT PangoColor ##### --> <para> The <structname>PangoColor</structname> structure is used to diff --git a/pango/pango-attributes.c b/pango/pango-attributes.c index cd0af8bd..fd5be6fb 100644 --- a/pango/pango-attributes.c +++ b/pango/pango-attributes.c @@ -601,8 +601,7 @@ pango_attr_strikethrough_new (gboolean strikethrough) /** * pango_attr_rise_new: * @rise: the amount that the text should be displaced vertically, - * in 10'000ths of an em. Positive values displace the - * text upwards. + * in Pango units. Positive values displace the text upwards. * * Create a new baseline displacement attribute. * @@ -670,6 +669,30 @@ pango_attr_fallback_new (gboolean enable_fallback) return pango_attr_int_new (&klass, (int)enable_fallback); } +/** + * pango_attr_letter_spacing_new: + * @letter_spacing: amount of extra space to add between graphemes + * of the text, in Pango units. + * + * Create a new letter-spacing attribute. + * + * Return value: the new #PangoAttribute. + * + * Since: 1.6 + **/ +PangoAttribute * +pango_attr_letter_spacing_new (int letter_spacing) +{ + static const PangoAttrClass klass = { + PANGO_ATTR_LETTER_SPACING, + pango_attr_int_copy, + pango_attr_int_destroy, + pango_attr_int_equal + }; + + return pango_attr_int_new (&klass, letter_spacing); +} + static PangoAttribute * pango_attr_shape_copy (const PangoAttribute *attr) { diff --git a/pango/pango-attributes.h b/pango/pango-attributes.h index a9971fcb..04086c4e 100644 --- a/pango/pango-attributes.h +++ b/pango/pango-attributes.h @@ -81,7 +81,8 @@ typedef enum PANGO_ATTR_RISE, /* PangoAttrInt */ PANGO_ATTR_SHAPE, /* PangoAttrShape */ PANGO_ATTR_SCALE, /* PangoAttrFloat */ - PANGO_ATTR_FALLBACK /* PangoAttrInt */ + PANGO_ATTR_FALLBACK, /* PangoAttrInt */ + PANGO_ATTR_LETTER_SPACING /* PangoAttrInt */ } PangoAttrType; typedef enum { @@ -182,6 +183,7 @@ PangoAttribute *pango_attr_shape_new (const PangoRectangle *ink_re const PangoRectangle *logical_rect); PangoAttribute *pango_attr_scale_new (double scale_factor); PangoAttribute *pango_attr_fallback_new (gboolean enable_fallback); +PangoAttribute *pango_attr_letter_spacing_new (int letter_spacing); GType pango_attr_list_get_type (void) G_GNUC_CONST; PangoAttrList * pango_attr_list_new (void); diff --git a/pango/pango-glyph-item.c b/pango/pango-glyph-item.c index 087f0fa6..b62bf840 100644 --- a/pango/pango-glyph-item.c +++ b/pango/pango-glyph-item.c @@ -44,6 +44,8 @@ * it internally) * * Return value: new item representing text before @split_index + * + * Since: 1.2 **/ PangoGlyphItem * pango_glyph_item_split (PangoGlyphItem *orig, @@ -124,62 +126,41 @@ pango_glyph_item_split (PangoGlyphItem *orig, return new; } -/* Structure holding state when we're iterating over a GlyphItem for - * pango_glyph_item_apply_attrs(). cluster_start/cluster_end (and - * range_start/range_end in apply_attrs()) are offsets into the - * text, so note the difference of glyph_item->item->offset between - * them and clusters in the log_clusters[] array. +/* Structure holding state when we're iterating over a GlyphItem. + start_index/cluster_end (and range_start/range_end in + apply_attrs()) are offsets into the text, so note the difference + of glyph_item->item->offset between them and clusters in the + log_clusters[] array. */ -typedef struct +typedef struct { PangoGlyphItem *glyph_item; const gchar *text; - int glyph_index; - int cluster_start; - int cluster_end; - - GSList *segment_attrs; -} ApplyAttrsState; - -/* Tack @attrs onto the attributes of glyph_item - */ -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); -} - -/* Make a deep copy of a GSlist of PangoAttribute - */ -static GSList * -attr_slist_copy (GSList *attrs) -{ - GSList *tmp_list; - GSList *new_attrs; - - new_attrs = g_slist_copy (attrs); - - for (tmp_list = new_attrs; tmp_list; tmp_list = tmp_list->next) - tmp_list->data = pango_attribute_copy (tmp_list->data); + int start_glyph; + int start_index; + int start_char; - return new_attrs; -} + int end_glyph; + int end_index; + int end_char; +} GlyphItemIter; -/* Advance to the next logical cluster +/* Advance to the next cluster, returns FALSE if + * we were already on the last cluster */ static gboolean -next_cluster (ApplyAttrsState *state) +glyph_item_iter_next_cluster (GlyphItemIter *iter) { - int glyph_index = state->glyph_index; - PangoGlyphString *glyphs = state->glyph_item->glyphs; - PangoItem *item = state->glyph_item->item; + int glyph_index = iter->end_glyph; + PangoGlyphString *glyphs = iter->glyph_item->glyphs; + PangoItem *item = iter->glyph_item->item; - state->cluster_start = state->cluster_end; + iter->start_glyph = iter->end_glyph; + iter->start_index = iter->end_index; + iter->start_char = iter->end_char; - if (LTR (state->glyph_item)) + if (LTR (iter->glyph_item)) { if (glyph_index == glyphs->num_glyphs) return FALSE; @@ -190,13 +171,16 @@ next_cluster (ApplyAttrsState *state) if (glyph_index == glyphs->num_glyphs) { - state->cluster_end = item->offset + item->length; + iter->end_index = item->offset + item->length; + iter->end_char = item->num_chars; break; } - if (item->offset + glyphs->log_clusters[glyph_index] >= state->cluster_start) + if (item->offset + glyphs->log_clusters[glyph_index] >= iter->start_index) { - state->cluster_end = item->offset + glyphs->log_clusters[glyph_index]; + iter->end_index = item->offset + glyphs->log_clusters[glyph_index]; + iter->end_char += g_utf8_strlen (iter->text + iter->start_index, + iter->end_index - iter->start_index); break; } } @@ -212,37 +196,100 @@ next_cluster (ApplyAttrsState *state) if (glyph_index < 0) { - state->cluster_end = item->offset + item->length; + iter->end_index = item->offset + item->length; + iter->end_char = item->num_chars; break; } - if (item->offset + glyphs->log_clusters[glyph_index] >= state->cluster_start) + if (item->offset + glyphs->log_clusters[glyph_index] >= iter->start_index) { - state->cluster_end = item->offset + glyphs->log_clusters[glyph_index]; + iter->end_index = item->offset + glyphs->log_clusters[glyph_index]; + iter->end_char += g_utf8_strlen (iter->text + iter->start_index, + iter->end_index - iter->start_index); break; } } } - state->glyph_index = glyph_index; + iter->end_glyph = glyph_index; return TRUE; } +/* Returns FALSE if there are no clusters in the glyph item */ +static gboolean +glyph_item_iter_init (GlyphItemIter *iter, + PangoGlyphItem *glyph_item, + const char *text) +{ + iter->glyph_item = glyph_item; + iter->text = text; + + if (LTR (glyph_item)) + iter->end_glyph = 0; + else + iter->end_glyph = glyph_item->glyphs->num_glyphs - 1; + + iter->end_index = glyph_item->item->offset; + iter->end_char = 0; + + /* Advance onto the first cluster of the glyph item */ + return glyph_item_iter_next_cluster (iter); +} + +typedef struct +{ + GlyphItemIter iter; + + GSList *segment_attrs; +} ApplyAttrsState; + +/* Tack @attrs onto the attributes of glyph_item + */ +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); +} + +/* Make a deep copy of a GSlist of PangoAttribute + */ +static GSList * +attr_slist_copy (GSList *attrs) +{ + GSList *tmp_list; + GSList *new_attrs; + + new_attrs = g_slist_copy (attrs); + + for (tmp_list = new_attrs; tmp_list; tmp_list = tmp_list->next) + tmp_list->data = pango_attribute_copy (tmp_list->data); + + return new_attrs; +} + /* Split the glyph item at the start of the current cluster */ static PangoGlyphItem * split_before_cluster_start (ApplyAttrsState *state) { PangoGlyphItem *split_item; - int split_len = state->cluster_start - state->glyph_item->item->offset; + int split_len = state->iter.start_index - state->iter.glyph_item->item->offset; - split_item = pango_glyph_item_split (state->glyph_item, state->text, split_len); + split_item = pango_glyph_item_split (state->iter.glyph_item, state->iter.text, split_len); append_attrs (split_item, state->segment_attrs); /* Adjust iteration to account for the split */ - if (LTR (state->glyph_item)) - state->glyph_index -= split_item->glyphs->num_glyphs; + if (LTR (state->iter.glyph_item)) + { + state->iter.start_glyph -= split_item->glyphs->num_glyphs; + state->iter.end_glyph -= split_item->glyphs->num_glyphs; + } + + state->iter.start_char -= split_item->item->num_chars; + state->iter.end_char -= split_item->item->num_chars; return split_item; } @@ -273,6 +320,8 @@ split_before_cluster_start (ApplyAttrsState *state) * 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(). + * + * Since: 1.2 **/ GSList * pango_glyph_item_apply_attrs (PangoGlyphItem *glyph_item, @@ -283,6 +332,7 @@ pango_glyph_item_apply_attrs (PangoGlyphItem *glyph_item, GSList *result = NULL; ApplyAttrsState state; gboolean start_new_segment = FALSE; + gboolean have_cluster; int range_start, range_end; /* This routine works by iterating through the item cluster by @@ -290,30 +340,20 @@ pango_glyph_item_apply_attrs (PangoGlyphItem *glyph_item, * add to the next output item, and decide when to split * off an output item based on two criteria: * - * A) If cluster_start < attribute_start < cluster_end + * A) If start_index < attribute_start < end_index * (attribute starts within cluster) then we need * to split between the last cluster and this cluster. - * B) If cluster_start < attribute_end <= cluster_end, + * B) If start_index < attribute_end <= end_index, * (attribute ends within cluster) then we need to * split between this cluster and the next one. */ - state.glyph_item = glyph_item; - state.text = text; - - if (LTR (glyph_item)) - state.glyph_index = 0; - else - state.glyph_index = glyph_item->glyphs->num_glyphs - 1; - - state.cluster_end = glyph_item->item->offset; - /* Advance the attr iterator to the start of the item */ while (TRUE) { pango_attr_iterator_range (iter, &range_start, &range_end); - if (range_end > state.cluster_end) + if (range_end > glyph_item->item->offset) break; pango_attr_iterator_next (iter); @@ -327,14 +367,15 @@ pango_glyph_item_apply_attrs (PangoGlyphItem *glyph_item, if (range_start <= glyph_item->item->offset && range_end >= glyph_item->item->offset + glyph_item->item->length) goto out; - - while (TRUE) + + for (have_cluster = glyph_item_iter_init (&state.iter, glyph_item, text); + have_cluster; + have_cluster = glyph_item_iter_next_cluster (&state.iter)) { - /* Find the next logical cluster; [range_start,range_end] - * is the first range that intersects the new cluster. + + /* [range_start,range_end] is the first range that intersects + * the current cluster. */ - if (!next_cluster (&state)) - break; /* Split item into two, if this cluster isn't a continuation * of the last cluster @@ -357,29 +398,29 @@ pango_glyph_item_apply_attrs (PangoGlyphItem *glyph_item, /* If any ranges end in this cluster, then the next cluster * goes into a separate segment */ - if (range_end <= state.cluster_end) + if (range_end <= state.iter.end_index) start_new_segment = TRUE; - if (range_end > state.cluster_end) /* Range intersects next cluster */ + if (range_end > state.iter.end_index) /* Range intersects next cluster */ break; pango_attr_iterator_next (iter); pango_attr_iterator_range (iter, &range_start, &range_end); - if (range_start >= state.cluster_end) /* New range doesn't intersect this cluster */ + if (range_start >= state.iter.end_index) /* New range doesn't intersect this cluster */ { /* No gap between ranges, so previous range must of ended * at cluster boundary. */ - g_assert (range_start == state.cluster_end && start_new_segment); + g_assert (range_start == state.iter.end_index && start_new_segment); break; } /* If any ranges start *inside* this cluster, then we need * to split the previous cluster into a separate segment */ - if (range_start > state.cluster_start && - state.cluster_start != glyph_item->item->offset) + if (range_start > state.iter.start_index && + state.iter.start_index != glyph_item->item->offset) { GSList *new_attrs = attr_slist_copy (state.segment_attrs); result = g_slist_prepend (result, @@ -390,6 +431,9 @@ pango_glyph_item_apply_attrs (PangoGlyphItem *glyph_item, state.segment_attrs = g_slist_concat (state.segment_attrs, pango_attr_iterator_get_attrs (iter)); } + + if (!glyph_item_iter_next_cluster (&state.iter)) + break; } out: @@ -405,3 +449,45 @@ pango_glyph_item_apply_attrs (PangoGlyphItem *glyph_item, return result; } + +/** + * pango_glyph_item_letter_space: + * @glyph_item: a #PangoGlyphItem + * @text: text that @glyph_item corresponds to + * (glyph_item->item->offset is an offset from the + * start of @text) + * @log_attrs: logical attributes for the item (the + * first logical attribute refers to the position + * before the first character in the item) + * @letter_spacing: amount of letter spacing to add + * in Pango units. May be negative, though too large + * negative values will give ugly results. + * + * Adds spacing between the graphemes of @glyph_item to + * give the effect of typographic letter spacing.b + * + * Since: 1.6 + **/ +void +pango_glyph_item_letter_space (PangoGlyphItem *glyph_item, + const char *text, + PangoLogAttr *log_attrs, + int letter_spacing) +{ + GlyphItemIter iter; + gboolean have_cluster; + + for (have_cluster = glyph_item_iter_init (&iter, glyph_item, text); + have_cluster; + have_cluster = glyph_item_iter_next_cluster (&iter)) + { + if (iter.start_char > 0 && + log_attrs[iter.start_char].is_cursor_position) + { + if (iter.start_glyph < iter.end_glyph) /* LTR */ + glyph_item->glyphs->glyphs[iter.start_glyph - 1].geometry.width += letter_spacing; + else /* RTL */ + glyph_item->glyphs->glyphs[iter.start_glyph].geometry.width += letter_spacing; + } + } +} diff --git a/pango/pango-glyph-item.h b/pango/pango-glyph-item.h index c9849f47..01a57489 100644 --- a/pango/pango-glyph-item.h +++ b/pango/pango-glyph-item.h @@ -24,6 +24,7 @@ #define __PANGO_GLYPH_ITEM_H__ #include <pango/pango-attributes.h> +#include <pango/pango-break.h> #include <pango/pango-item.h> #include <pango/pango-glyph.h> @@ -37,12 +38,16 @@ struct _PangoGlyphItem PangoGlyphString *glyphs; }; -PangoGlyphItem *pango_glyph_item_split (PangoGlyphItem *orig, - const char *text, - int split_index); -GSList * pango_glyph_item_apply_attrs (PangoGlyphItem *glyph_item, - const char *text, - PangoAttrList *list); +PangoGlyphItem *pango_glyph_item_split (PangoGlyphItem *orig, + const char *text, + int split_index); +GSList * pango_glyph_item_apply_attrs (PangoGlyphItem *glyph_item, + const char *text, + PangoAttrList *list); +void pango_glyph_item_letter_space (PangoGlyphItem *glyph_item, + const char *text, + PangoLogAttr *log_attrs, + int letter_spacing); G_END_DECLS diff --git a/pango/pango-layout.c b/pango/pango-layout.c index 278c6766..108a8aaa 100644 --- a/pango/pango-layout.c +++ b/pango/pango-layout.c @@ -29,6 +29,7 @@ #define LINE_IS_VALID(line) ((line)->layout != NULL) typedef struct _Extents Extents; +typedef struct _ItemProperties ItemProperties; struct _Extents { @@ -40,6 +41,16 @@ struct _Extents PangoRectangle logical_rect; }; +struct _ItemProperties +{ + PangoUnderline uline; + gint rise; + gint letter_spacing; + gboolean shape_set; + PangoRectangle *shape_ink_rect; + PangoRectangle *shape_logical_rect; +}; + struct _PangoLayoutIter { PangoLayout *layout; @@ -63,9 +74,6 @@ struct _PangoLayoutIter /* X position of the current run */ int run_x; - /* Does the run have a shape attribute */ - gboolean run_is_shaped; - /* Extents of the current run */ PangoRectangle run_logical_rect; @@ -152,45 +160,13 @@ static int *pango_layout_line_get_vis2log_map (PangoLayoutLine *line, gboolean strong); static void pango_layout_get_item_properties (PangoItem *item, - PangoUnderline *uline, - gint *rise, - PangoRectangle *ink_rect, - PangoRectangle *logical_rect, - gboolean *shape_set); + ItemProperties *properties); static void pango_layout_init (PangoLayout *layout); static void pango_layout_class_init (PangoLayoutClass *klass); static void pango_layout_finalize (GObject *object); -static gpointer parent_class; - -GType -pango_layout_get_type (void) -{ - static GType object_type = 0; - - if (!object_type) - { - static const GTypeInfo object_info = - { - sizeof (PangoLayoutClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) pango_layout_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (PangoLayout), - 0, /* n_preallocs */ - (GInstanceInitFunc) pango_layout_init, - }; - - object_type = g_type_register_static (G_TYPE_OBJECT, - "PangoLayout", - &object_info, 0); - } - - return object_type; -} +G_DEFINE_TYPE (PangoLayout, pango_layout, G_TYPE_OBJECT) static void pango_layout_init (PangoLayout *layout) @@ -219,8 +195,6 @@ pango_layout_class_init (PangoLayoutClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - parent_class = g_type_class_peek_parent (klass); - object_class->finalize = pango_layout_finalize; } @@ -247,7 +221,7 @@ pango_layout_finalize (GObject *object) if (layout->tabs) pango_tab_array_free (layout->tabs); - G_OBJECT_CLASS (parent_class)->finalize (object); + G_OBJECT_CLASS (pango_layout_parent_class)->finalize (object); } @@ -1038,19 +1012,17 @@ pango_layout_line_index_to_x (PangoLayoutLine *line, while (run_list) { - PangoRectangle logical_rect; PangoLayoutRun *run = run_list->data; - gboolean shape_set; + ItemProperties properties; - pango_layout_get_item_properties (run->item, NULL, NULL, NULL, - &logical_rect, &shape_set); + pango_layout_get_item_properties (run->item, &properties); if (run->item->offset <= index && run->item->offset + run->item->length > index) { - if (shape_set) + if (properties.shape_set) { if (x_pos) - *x_pos = width + (trailing > 0 ? logical_rect.width : 0); + *x_pos = width + (trailing > 0 ? properties.shape_logical_rect->width : 0); } else { @@ -1088,11 +1060,18 @@ pango_layout_line_index_to_x (PangoLayoutLine *line, return; } - if (!shape_set) - pango_glyph_string_extents (run->glyphs, run->item->analysis.font, - NULL, &logical_rect); - - width += logical_rect.width; + if (!properties.shape_set) + { + PangoRectangle logical_rect; + + pango_glyph_string_extents (run->glyphs, run->item->analysis.font, + NULL, &logical_rect); + width += logical_rect.width; + } + else + { + width += properties.shape_logical_rect->width; + } run_list = run_list->next; } @@ -2603,15 +2582,57 @@ struct _ParaBreakState int start_offset; /* Character offset of first item in state->items in layout->text */ PangoGlyphString *glyphs; /* Glyphs for the first item in state->items */ + ItemProperties properties; /* Properties for the first item in state->items */ PangoGlyphUnit *log_widths; /* Logical widths for first item in state->items.. */ int log_widths_offset; /* Offset into log_widths to the point corresponding * to the remaining portion of the first item */ }; +static PangoGlyphString * +shape_run (PangoLayoutLine *line, + ParaBreakState *state, + PangoItem *item) +{ + PangoLayout *layout = line->layout; + PangoGlyphString *glyphs = pango_glyph_string_new (); + + if (layout->text[item->offset] == '\t') + shape_tab (line, glyphs); + else + { + if (state->properties.shape_set) + imposed_shape (layout->text + item->offset, item->num_chars, + state->properties.shape_ink_rect, state->properties.shape_logical_rect, + glyphs); + else + pango_shape (layout->text + item->offset, item->length, &item->analysis, glyphs); + + if (state->properties.letter_spacing) + { + PangoGlyphItem glyph_item; + + glyph_item.item = item; + glyph_item.glyphs = glyphs; + + pango_glyph_item_letter_space (&glyph_item, + layout->text, + layout->log_attrs + state->start_offset, + state->properties.letter_spacing); + + /* We put all the letter spacing after the last glyph, then + * will go back and redistribute it at the beginning and the + * end in a post-processing step over the whole line. + */ + glyphs->glyphs[glyphs->num_glyphs - 1].geometry.width += state->properties.letter_spacing; + } + } + + return glyphs; +} + static void insert_run (PangoLayoutLine *line, ParaBreakState *state, - const char *text, PangoItem *run_item, gboolean last_run) { @@ -2622,14 +2643,7 @@ insert_run (PangoLayoutLine *line, if (last_run && state->log_widths_offset == 0) run->glyphs = state->glyphs; else - { - run->glyphs = pango_glyph_string_new (); - - if (text[run_item->offset] == '\t') - shape_tab (line, run->glyphs); - else - pango_shape (text + run_item->offset, run_item->length, &run_item->analysis, run->glyphs); - } + run->glyphs = shape_run (line, state, run_item); if (last_run) { @@ -2668,8 +2682,6 @@ process_item (PangoLayout *layout, gboolean force_fit, gboolean no_break_at_end) { - PangoRectangle shape_ink; - PangoRectangle shape_logical; PangoItem *item = state->items->data; gboolean shape_set = FALSE; int width; @@ -2683,20 +2695,9 @@ process_item (PangoLayout *layout, if (!state->glyphs) { - state->glyphs = pango_glyph_string_new (); + pango_layout_get_item_properties (item, &state->properties); + state->glyphs = shape_run (line, state, item); - pango_layout_get_item_properties (item, NULL, NULL, - &shape_ink, - &shape_logical, - &shape_set); - - if (shape_set) - imposed_shape (layout->text + item->offset, item->num_chars, &shape_ink, &shape_logical, state->glyphs); - else if (layout->text[item->offset] == '\t') - shape_tab (line, state->glyphs); - else - pango_shape (layout->text + item->offset, item->length, &item->analysis, state->glyphs); - state->log_widths = NULL; state->log_widths_offset = 0; @@ -2705,14 +2706,14 @@ process_item (PangoLayout *layout, if (g_utf8_get_char (layout->text + item->offset) == LINE_SEPARATOR) { - insert_run (line, state, layout->text, item, TRUE); + insert_run (line, state, item, TRUE); state->log_widths_offset += item->num_chars; return BREAK_LINE_SEPARATOR; } if (state->remaining_width < 0 && !no_break_at_end) /* Wrapping off */ { - insert_run (line, state, layout->text, item, TRUE); + insert_run (line, state, item, TRUE); return BREAK_ALL_FIT; } @@ -2722,11 +2723,17 @@ process_item (PangoLayout *layout, { for (i = 0; i < state->glyphs->num_glyphs; i++) width += state->glyphs->glyphs[i].geometry.width; + + /* We'll add half the letter spacing to each side of the item */ + width += state->properties.letter_spacing; } else { for (i = 0; i < item->num_chars; i++) width += state->log_widths[state->log_widths_offset + i]; + + /* In this case, the letter spacing width has already been + * added to the last element in log_widths */ } if ((width <= state->remaining_width || (item->num_chars == 1 && !line->runs)) && @@ -2734,7 +2741,7 @@ process_item (PangoLayout *layout, { state->remaining_width -= width; state->remaining_width = MAX (state->remaining_width, 0); - insert_run (line, state, layout->text, item, TRUE); + insert_run (line, state, item, TRUE); return BREAK_ALL_FIT; } @@ -2752,6 +2759,13 @@ process_item (PangoLayout *layout, pango_glyph_string_get_logical_widths (state->glyphs, layout->text + item->offset, item->length, item->analysis.level, state->log_widths); + + /* The extra run letter spacing is actually divided after + * the last and and before the first, but it works to + * account it all on the last + */ + if (item->num_chars > 0) + state->log_widths[item->num_chars] += state->properties.letter_spacing; } retry_break: @@ -2794,7 +2808,7 @@ process_item (PangoLayout *layout, if (break_num_chars == item->num_chars) { - insert_run (line, state, layout->text, item, TRUE); + insert_run (line, state, item, TRUE); return BREAK_ALL_FIT; } @@ -2810,7 +2824,7 @@ process_item (PangoLayout *layout, new_item = pango_item_split (item, length, break_num_chars); - insert_run (line, state, layout->text, new_item, FALSE); + insert_run (line, state, new_item, FALSE); state->log_widths_offset += break_num_chars; @@ -3366,14 +3380,15 @@ pango_layout_line_x_to_index (PangoLayoutLine *line, tmp_list = line->runs; while (tmp_list) { - PangoRectangle logical_rect; PangoLayoutRun *run = tmp_list->data; - gboolean shape_set; + PangoRectangle logical_rect; + ItemProperties properties; - pango_layout_get_item_properties (run->item, NULL, NULL, - NULL, &logical_rect, &shape_set); + pango_layout_get_item_properties (run->item, &properties); - if (!shape_set) + if (properties.shape_set) + logical_rect = *properties.shape_logical_rect; + else pango_glyph_string_extents (run->glyphs, run->item->analysis.font, NULL, &logical_rect); if (x_pos >= start_pos && x_pos < start_pos + logical_rect.width) @@ -3388,7 +3403,7 @@ pango_layout_line_x_to_index (PangoLayoutLine *line, char_index = run->item->offset; - if (shape_set) + if (properties.shape_set) { *trailing = 0; } @@ -3697,28 +3712,22 @@ pango_layout_line_get_empty_extents (PangoLayoutLine *line, static void pango_layout_run_get_extents (PangoLayoutRun *run, - gboolean *shape_setp, PangoRectangle *run_ink, PangoRectangle *run_logical) { PangoUnderline uline = PANGO_UNDERLINE_NONE; - int rise = 0; - PangoRectangle shape_ink; - PangoRectangle shape_logical; + ItemProperties properties; PangoRectangle tmp_ink; - gboolean shape_set; gboolean need_ink; - pango_layout_get_item_properties (run->item, &uline, &rise, - &shape_ink, &shape_logical, &shape_set); - - if (shape_setp) - *shape_setp = shape_set; + pango_layout_get_item_properties (run->item, &properties); need_ink = run_ink || uline == PANGO_UNDERLINE_LOW; - if (shape_set) - imposed_extents (run->item->num_chars, &shape_ink, &shape_logical, + if (properties.shape_set) + imposed_extents (run->item->num_chars, + properties.shape_ink_rect, + properties.shape_logical_rect, need_ink ? &tmp_ink : NULL, run_logical); else pango_glyph_string_extents (run->glyphs, run->item->analysis.font, @@ -3728,7 +3737,7 @@ pango_layout_run_get_extents (PangoLayoutRun *run, if (run_ink) *run_ink = tmp_ink; - switch (uline) + switch (properties.uline) { case PANGO_UNDERLINE_NONE: break; @@ -3761,13 +3770,13 @@ pango_layout_run_get_extents (PangoLayoutRun *run, break; } - if (rise != 0) + if (properties.rise != 0) { if (run_ink) - run_ink->y -= rise; + run_ink->y -= properties.rise; if (run_logical) - run_logical->y -= rise; + run_logical->y -= properties.rise; } } @@ -3820,7 +3829,7 @@ pango_layout_line_get_extents (PangoLayoutLine *line, PangoRectangle run_ink; PangoRectangle run_logical; - pango_layout_run_get_extents (run, NULL, + pango_layout_run_get_extents (run, ink_rect ? &run_ink : NULL, &run_logical); @@ -3997,6 +4006,118 @@ pango_layout_line_reorder (PangoLayoutLine *line) g_slist_free (logical_runs); } +static int +get_item_letter_spacing (PangoItem *item) +{ + ItemProperties properties; + + pango_layout_get_item_properties (item, &properties); + + return properties.letter_spacing; +} + +static void +adjust_final_space (PangoGlyphString *glyphs, + int adjustment) +{ + glyphs->glyphs[glyphs->num_glyphs - 1].geometry.width += adjustment; +} + +static gboolean +is_tab_run (PangoLayout *layout, + PangoLayoutRun *run) +{ + return (layout->text[run->item->offset] == '\t'); +} + +/* When doing shaping, we add the letter spacing value for a + * run after every grapheme in the run. This produces ugly + * asymetrical results, so what this routine is redistributes + * that space to the beginning and the end of the run. + * + * We also trim the letter spacing from runs adjacent to + * tabs and from the outside runs of the lines so that things + * line up properly. The line breaking and tab positioning + * were computed without this trimming so they are no longer + * exactly correct, but this won't be very noticable in most + * cases. + */ +static void +adjust_line_letter_spacing (PangoLayoutLine *line) +{ + PangoLayout *layout = line->layout; + gboolean reversed; + PangoLayoutRun *last_run; + int tab_adjustment; + GSList *l; + + /* If we have tab stops and the resolved direction of the + * line is RTL, then we need to walk through the line + * in reverse direction to figure out the corrections for + * tab stops. + */ + reversed = FALSE; + if (line->resolved_dir == PANGO_DIRECTION_RTL) + { + for (l = line->runs; l; l = l->next) + if (is_tab_run (layout, l->data)) + { + line->runs = g_slist_reverse (line->runs); + reversed = TRUE; + break; + } + } + + /* Walk over the runs in the line, redistributing letter + * spacing from the end of the run to the start of the + * run and trimming letter spacing from the ends of the + * runs adjacent to the ends of the line or tab stops. + * + * We accumulate a correction factor from this trimming + * which we add onto the next tab stop space to keep the + * things properly aligned. + */ + + last_run = NULL; + tab_adjustment = 0; + for (l = line->runs; l; l = l->next) + { + PangoLayoutRun *run = l->data; + PangoLayoutRun *next_run = l->next ? l->next->data : NULL; + + if (is_tab_run (layout, run)) + { + adjust_final_space (run->glyphs, tab_adjustment); + tab_adjustment = 0; + } + else + { + PangoLayoutRun *visual_next_run = reversed ? last_run : next_run; + PangoLayoutRun *visual_last_run = reversed ? next_run : last_run; + int run_spacing = get_item_letter_spacing (run->item); + int adjustment = run_spacing / 2; + + if (visual_last_run && !is_tab_run (layout, visual_last_run)) + adjust_final_space (visual_last_run->glyphs, adjustment); + else + tab_adjustment += adjustment; + + if (visual_next_run && !is_tab_run (layout, visual_next_run)) + adjust_final_space (run->glyphs, - adjustment); + else + { + adjust_final_space (run->glyphs, - run_spacing); + tab_adjustment += run_spacing - adjustment; + } + } + + last_run = run; + } + + if (reversed) + line->runs = g_slist_reverse (line->runs); +} + static void pango_layout_line_postprocess (PangoLayoutLine *line) { @@ -4010,30 +4131,25 @@ pango_layout_line_postprocess (PangoLayoutLine *line) /* Now convert logical to visual order */ pango_layout_line_reorder (line); + + /* Fixup letter spacing between runs + */ + adjust_line_letter_spacing (line); } -/* This utility function is duplicated here and in pangox.c; should it be - * public? Trouble is - what is the appropriate set of properties? - */ static void pango_layout_get_item_properties (PangoItem *item, - PangoUnderline *uline, - gint *rise, - PangoRectangle *ink_rect, - PangoRectangle *logical_rect, - gboolean *shape_set) + ItemProperties *properties) { GSList *tmp_list = item->analysis.extra_attrs; - if (shape_set) - *shape_set = FALSE; - - if (rise) - *rise = 0; + properties->uline = PANGO_UNDERLINE_NONE; + properties->letter_spacing = 0; + properties->rise = 0; + properties->shape_set = FALSE; + properties->shape_ink_rect = NULL; + properties->shape_logical_rect = NULL; - if (uline) - *uline = PANGO_UNDERLINE_NONE; - while (tmp_list) { PangoAttribute *attr = tmp_list->data; @@ -4041,24 +4157,23 @@ pango_layout_get_item_properties (PangoItem *item, switch (attr->klass->type) { case PANGO_ATTR_UNDERLINE: - if (uline) - *uline = ((PangoAttrInt *)attr)->value; + properties->uline = ((PangoAttrInt *)attr)->value; break; case PANGO_ATTR_RISE: - if (rise) - *rise = ((PangoAttrInt *)attr)->value; + properties->rise = ((PangoAttrInt *)attr)->value; break; + case PANGO_ATTR_LETTER_SPACING: + properties->letter_spacing = ((PangoAttrInt *)attr)->value; + break; + case PANGO_ATTR_SHAPE: - if (shape_set) - *shape_set = TRUE; - if (logical_rect) - *logical_rect = ((PangoAttrShape *)attr)->logical_rect; - if (ink_rect) - *ink_rect = ((PangoAttrShape *)attr)->ink_rect; + properties->shape_set = TRUE; + properties->shape_logical_rect = &((PangoAttrShape *)attr)->logical_rect; + properties->shape_ink_rect = &((PangoAttrShape *)attr)->ink_rect; break; - + default: break; } @@ -4157,7 +4272,6 @@ update_run (PangoLayoutIter *iter, if (iter->run) { pango_layout_run_get_extents (iter->run, - &iter->run_is_shaped, NULL, &iter->run_logical_rect); @@ -4168,8 +4282,6 @@ update_run (PangoLayoutIter *iter, } else { - iter->run_is_shaped = FALSE; - iter->run_logical_rect.x = iter->run_x; iter->run_logical_rect.y = line_ext->logical_rect.y; iter->run_logical_rect.width = 0; @@ -4694,7 +4806,7 @@ pango_layout_iter_get_run_extents (PangoLayoutIter *iter, { if (iter->run) { - pango_layout_run_get_extents (iter->run, NULL, ink_rect, NULL); + pango_layout_run_get_extents (iter->run, ink_rect, NULL); offset_y (iter, &ink_rect->y); ink_rect->x += iter->run_x; } diff --git a/pango/pango-markup.c b/pango/pango-markup.c index a4bd108c..3b45cc73 100644 --- a/pango/pango-markup.c +++ b/pango/pango-markup.c @@ -857,6 +857,7 @@ span_parse_func (MarkupData *md, const char *underline = NULL; const char *strikethrough = NULL; const char *rise = NULL; + const char *letter_spacing = NULL; const char *lang = NULL; const char *fallback = NULL; @@ -928,6 +929,11 @@ span_parse_func (MarkupData *md, CHECK_DUPLICATE (rise); rise = values[i]; } + else if (strcmp (names[i], "letter_spacing") == 0) + { + CHECK_DUPLICATE (letter_spacing); + letter_spacing = values[i]; + } else if (strcmp (names[i], "lang") == 0) { CHECK_DUPLICATE (lang); @@ -1231,6 +1237,28 @@ span_parse_func (MarkupData *md, add_attribute (tag, pango_attr_rise_new (n)); } + if (letter_spacing) + { + char *end = NULL; + glong n; + + n = strtol (letter_spacing, &end, 10); + + if (*end != '\0') + { + g_set_error (error, + G_MARKUP_ERROR, + G_MARKUP_ERROR_INVALID_CONTENT, + _("Value of 'letter_spacing' attribute on <span> tag " + "on line %d could not be parsed; " + "should be an integer, not '%s'"), + line_number, letter_spacing); + goto error; + } + + add_attribute (tag, pango_attr_letter_spacing_new (n)); + } + if (lang) { add_attribute (tag, diff --git a/pango/pango-types.h b/pango/pango-types.h index 7e1259ab..e2168866 100644 --- a/pango/pango-types.h +++ b/pango/pango-types.h @@ -172,8 +172,12 @@ PangoLanguage *pango_language_from_string (const char *language); gboolean pango_language_matches (PangoLanguage *language, const char *range_list); +#ifndef PANGO_DISABLE_DEPRECATED gboolean pango_get_mirror_char (gunichar ch, gunichar *mirrored_ch); +#endif + + PangoDirection pango_unichar_direction (gunichar ch); PangoDirection pango_find_base_dir (const gchar *text, gint length); diff --git a/pango/pango-utils.c b/pango/pango-utils.c index 96378168..768ac8e6 100644 --- a/pango/pango-utils.c +++ b/pango/pango-utils.c @@ -1391,6 +1391,21 @@ pango_log2vis_get_embedding_levels (gunichar *str, #endif /* HAVE_FRIBIDI */ +/** + * pango_get_mirror_char: + * @ch: a unicode character + * @mirrored_ch: location to store the mirrored character + * + * If @ch has the Unicode mirrored property and there is another unicode + * character that typically has a glyph that is the mirror image of @ch's + * glyph, puts that character in the address pointed to by @mirrored_ch. + * + * Use g_unichar_get_mirror_char() instead; the docs for that function + * provide full details. + * + * Return value: %TRUE if @ch has a mirrored character and @mirrored_ch is + * filled in, %FALSE otherwise + **/ gboolean pango_get_mirror_char (gunichar ch, gunichar *mirrored_ch) diff --git a/pango/pangofc-decoder.c b/pango/pangofc-decoder.c index ff177b1e..118c17e8 100644 --- a/pango/pangofc-decoder.c +++ b/pango/pangofc-decoder.c @@ -41,19 +41,19 @@ pango_fc_decoder_class_init (PangoFcDecoderClass *klass) /** * pango_fc_decoder_get_charset: - * @decoder: A #PangoFcDecoder to use when querying the font for a - * supported #FcCharSet. - * @fcfont: The #PangoFcFont to query. + * @decoder: a #PangoFcDecoder + * @fcfont: the #PangoFcFont to query. * * Generates an #FcCharSet of supported characters for the fcfont - * given. The returned #FcCharSet should be a reference to an - * internal value stored by the #PangoFcDecoder and will not be freed - * by Pango. + * given. The returned #FcCharSet will be a reference to an + * internal value stored by the #PangoFcDecoder and must not + * be modified or freed. * - * Since: 1.6 + * Return value: the #FcCharset for @fcfont; must not be modified + * or freed. * - */ - + * Since: 1.6 + **/ FcCharSet * pango_fc_decoder_get_charset (PangoFcDecoder *decoder, PangoFcFont *fcfont) @@ -65,22 +65,25 @@ pango_fc_decoder_get_charset (PangoFcDecoder *decoder, /** * pango_fc_decoder_get_glyph: - * @decoder: A #PangoFcDecoder to use when querying the font. - * @fcfont: The #PangoFcFont to query. - * @wc: The unicode code point that you would like to see converted to - * a single #PangoGlyph. + * @decoder: a #PangoFcDecoder + * @fcfont: a #PangoFcFont to query. + * @wc: the unicode code point to convert to a single #PangoGlyph. * - * Generates a #PangoGlyph for the given unicode point with the custom - * decoder. + * Generates a #PangoGlyph for the given unicode point using the + * custom decoder. For complex scripts where there can be multiple + * glyphs for a single character, the decoder will return whatever + * glyph is most convenient for it. (Usually whatever glyph is directly + * in the fonts character map table.) * - * Since: 1.6 + * Return value: the glyph index, or 0 if the glyph isn't covered + * by the font. * - */ - + * Since: 1.6 + **/ PangoGlyph -pango_fc_decoder_get_glyph (PangoFcDecoder *decoder, - PangoFcFont *fcfont, - guint32 wc) +pango_fc_decoder_get_glyph (PangoFcDecoder *decoder, + PangoFcFont *fcfont, + guint32 wc) { g_return_val_if_fail (PANGO_IS_FC_DECODER (decoder), 0); diff --git a/pango/pangofc-decoder.h b/pango/pangofc-decoder.h index 0178ab1b..d5bb6818 100644 --- a/pango/pangofc-decoder.h +++ b/pango/pangofc-decoder.h @@ -46,37 +46,33 @@ typedef struct _PangoFcDecoderClass PangoFcDecoderClass; * function callback that was originally registered with * pango_fc_font_map_add_decoder_find_func(). Pango requires * information about the supported charset for a font as well as the - * indivdual character to glyph conversions. Pango gets that + * individual character to glyph conversions. Pango gets that * information via the #get_charset and #get_glyph callbacks into your * object implementation. * * Since: 1.6 - * **/ - struct _PangoFcDecoder { + /*< private >*/ GObject parent_instance; }; /** * PangoFcDecoderClass: - * * @get_charset: This returns an #FcCharset given a #PangoFcFont that - * includes a list of supported characters in the font. The - * #FcCharSet that is returned should be an internal reference to your - * code. Pango will not free this structure. It is also important - * that you make this callback very fast because this callback is also - * used to determine unicode coverage on a per-character basis. + * includes a list of supported characters in the font. The + * #FcCharSet that is returned should be an internal reference to your + * code. Pango will not free this structure. It is important that + * you make this callback fast because this callback is called + * separately for each character to determine unicode coverage. * @get_glyph: This returns a single #PangoGlyph for a given unicode - * code point. + * code point. * * Class structure for #PangoFcDecoder. * * Since: 1.6 - * **/ - struct _PangoFcDecoderClass { /*< private >*/ diff --git a/pango/pangofc-fontmap.c b/pango/pangofc-fontmap.c index 63c628a6..2fc88d50 100644 --- a/pango/pangofc-fontmap.c +++ b/pango/pangofc-fontmap.c @@ -343,28 +343,27 @@ pango_fc_clear_pattern_hashes (PangoFcFontMap *fcfontmap) } /** - * pango_fc_font_map_add_find_func: + * pango_fc_font_map_add_decoder_find_func: * @fcfontmap: The #PangoFcFontMap to add this method to. - * @factory: The #PangoFcDecoderFindFunc callback function + * @findfunc: The #PangoFcDecoderFindFunc callback function * @user_data: User data. * @dnotify: A #GDestroyNotify callback that will be called when the - * fontmap is finalized and the decoder is released. + * fontmap is finalized and the decoder is released. * * This function saves a callback method in the #PangoFcFontMap that - * will be called whenever new fonts are created. If the function - * returns a #PangoFcDecoder, that decoder will be used to determine - * both coverage via a #FcCharSet and a one-to-one mapping of + * will be called whenever new fonts are created. If the + * function returns a #PangoFcDecoder, that decoder will be used to + * determine both coverage via a #FcCharSet and a one-to-one mapping of * characters to glyphs. This will allow applications to have * application-specific encodings for various fonts. * * Since: 1.6. - * - */ - -void pango_fc_font_map_add_decoder_find_func (PangoFcFontMap *fcfontmap, - PangoFcDecoderFindFunc findfunc, - gpointer user_data, - GDestroyNotify dnotify) + **/ +void +pango_fc_font_map_add_decoder_find_func (PangoFcFontMap *fcfontmap, + PangoFcDecoderFindFunc findfunc, + gpointer user_data, + GDestroyNotify dnotify) { PangoFcFontMapPrivate *priv = fcfontmap->priv; PangoFcFindFuncInfo *info; diff --git a/pango/pangofc-fontmap.h b/pango/pangofc-fontmap.h index 3ad3430a..f5d193be 100644 --- a/pango/pangofc-fontmap.h +++ b/pango/pangofc-fontmap.h @@ -99,6 +99,16 @@ void pango_fc_font_map_shutdown (PangoFcFontMap *fcfontmap); GType pango_fc_font_map_get_type (void); +/** + * PangoFcDecoderFindFunc: + * @pattern: a fully resolved #FcPattern specifying the font on the system + * @user_data: user data passed to pango_fc_font_map_add_decoder_find_func() + * + * Callback function passed to pango_fc_font_map_add_decoder_find_func(). + * + * Return value: a new reference to a custom decoder for this pattern, + * or %NULL if the default decoder handling should be used. + **/ typedef PangoFcDecoder * (*PangoFcDecoderFindFunc) (FcPattern *pattern, gpointer user_data); |