summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2021-08-21 04:32:48 +0000
committerMatthias Clasen <mclasen@redhat.com>2021-08-21 04:32:48 +0000
commit1ac4f5d3dc9d88abb6f0a196291449c244f39b71 (patch)
tree5d0846958eaba2fa2d7f59b65968e458db15a19d
parentf72ff7d4752318b48e3dd0db83a2ef0300aa898f (diff)
parentb2c3b6a7ac43fbdedf1f13a240893159c329767f (diff)
downloadpango-1ac4f5d3dc9d88abb6f0a196291449c244f39b71.tar.gz
Merge branch 'text-transform-3' into 'main'
Add support for text transformation See merge request GNOME/pango!421
-rw-r--r--docs/pango_markup.md5
-rw-r--r--pango/pango-attributes.c26
-rw-r--r--pango/pango-attributes.h22
-rw-r--r--pango/pango-glyph.h9
-rw-r--r--pango/pango-layout.c10
-rw-r--r--pango/pango-markup.c14
-rw-r--r--pango/shape.c375
-rw-r--r--tests/markup-parse.c2
-rw-r--r--tests/markups/valid-24.expected19
-rw-r--r--tests/markups/valid-24.markup1
-rw-r--r--tests/test-common.c1
-rw-r--r--tests/testattributes.c1
12 files changed, 364 insertions, 121 deletions
diff --git a/docs/pango_markup.md b/docs/pango_markup.md
index 03718907..3a1cc311 100644
--- a/docs/pango_markup.md
+++ b/docs/pango_markup.md
@@ -196,6 +196,11 @@ line_height
of a point).
Available since Pango 1.50.
+text_transform
+: Specifies how characters are transformed during shaping. The values can be
+ 'none', 'lowercase', 'uppercase' or 'capitalize'. Support for text transformation
+ was added in Pango 1.50.
+
## Convenience Tags
`<b>`
diff --git a/pango/pango-attributes.c b/pango/pango-attributes.c
index 5690aeaa..f5d5104b 100644
--- a/pango/pango-attributes.c
+++ b/pango/pango-attributes.c
@@ -1411,6 +1411,32 @@ pango_attr_line_height_new_absolute (int height)
return pango_attr_int_new (&klass, height);
}
+
+/**
+ * pango_attr_text_transform_new:
+ * @transform: `PangoTextTransform` to apply
+ *
+ * Create a new attribute that influences how characters
+ * are transformed during shaping.
+ *
+ * Return value: (transfer full): the newly allocated
+ * `PangoAttribute`, which should be freed with
+ * [method@Pango.Attribute.destroy]
+ *
+ * Since: 1.50
+ */
+PangoAttribute *
+pango_attr_text_transform_new (PangoTextTransform transform)
+{
+ static const PangoAttrClass klass = {
+ PANGO_ATTR_TEXT_TRANSFORM,
+ pango_attr_int_copy,
+ pango_attr_int_destroy,
+ pango_attr_int_equal
+ };
+
+ return pango_attr_int_new (&klass, transform);
+}
/* }}} */
/* {{{ Binding helpers */
diff --git a/pango/pango-attributes.h b/pango/pango-attributes.h
index e3012008..ca0f74b8 100644
--- a/pango/pango-attributes.h
+++ b/pango/pango-attributes.h
@@ -120,6 +120,7 @@ typedef enum
PANGO_ATTR_OVERLINE_COLOR, /* PangoAttrColor */
PANGO_ATTR_LINE_HEIGHT, /* PangoAttrFloat */
PANGO_ATTR_ABSOLUTE_LINE_HEIGHT, /* PangoAttrInt */
+ PANGO_ATTR_TEXT_TRANSFORM, /* PangoAttrInt */
} PangoAttrType;
/**
@@ -203,6 +204,25 @@ typedef enum {
} PangoShowFlags;
/**
+ * PangoTextTransform:
+ * @PANGO_TEXT_TRANSFORM_NONE: Leave text unchanged
+ * @PANGO_TEXT_TRANSFORM_LOWERCASE: Display letters and numbers as lowercase
+ * @PANGO_TEXT_TRANSFORM_UPPERCASE: Display letters and numbers as uppercase
+ * @PANGO_TEXT_TRANSFORM_CAPITALIZE: Display the first character of a word
+ * in titlecase
+ *
+ * An enumeration that affects how Pango treats characters during shaping.
+ *
+ * Since: 1.50
+ */
+typedef enum {
+ PANGO_TEXT_TRANSFORM_NONE,
+ PANGO_TEXT_TRANSFORM_LOWERCASE,
+ PANGO_TEXT_TRANSFORM_UPPERCASE,
+ PANGO_TEXT_TRANSFORM_CAPITALIZE,
+} PangoTextTransform;
+
+/**
* PANGO_ATTR_INDEX_FROM_TEXT_BEGINNING:
*
* Value for @start_index in `PangoAttribute` that indicates
@@ -532,6 +552,8 @@ 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
+PangoAttribute * pango_attr_text_transform_new (PangoTextTransform transform);
PANGO_AVAILABLE_IN_1_50
PangoAttrString * pango_attribute_as_string (PangoAttribute *attr);
diff --git a/pango/pango-glyph.h b/pango/pango-glyph.h
index ae1f5fd7..4dc77fd1 100644
--- a/pango/pango-glyph.h
+++ b/pango/pango-glyph.h
@@ -228,6 +228,15 @@ void pango_shape_with_flags (const char
PangoShapeFlags flags);
+PANGO_AVAILABLE_IN_1_50
+void pango_shape_item (PangoItem *item,
+ const char *paragraph_text,
+ int paragraph_length,
+ PangoLogAttr *log_attrs,
+ PangoGlyphString *glyphs,
+ PangoShapeFlags flags);
+
+
G_END_DECLS
#endif /* __PANGO_GLYPH_H__ */
diff --git a/pango/pango-layout.c b/pango/pango-layout.c
index 669410ee..bf7a97e7 100644
--- a/pango/pango-layout.c
+++ b/pango/pango-layout.c
@@ -3540,10 +3540,11 @@ shape_run (PangoLayoutLine *line,
state->properties.shape_ink_rect, state->properties.shape_logical_rect,
glyphs);
else
- pango_shape_with_flags (layout->text + item->offset, item->length,
- layout->text, layout->length,
- &item->analysis, glyphs,
- shape_flags);
+ pango_shape_item (item,
+ layout->text, layout->length,
+ layout->log_attrs + state->start_offset,
+ glyphs,
+ shape_flags);
if (state->properties.letter_spacing)
{
@@ -4317,6 +4318,7 @@ affects_break_or_shape (PangoAttribute *attr,
case PANGO_ATTR_INSERT_HYPHENS:
case PANGO_ATTR_FONT_FEATURES:
case PANGO_ATTR_SHOW:
+ case PANGO_ATTR_TEXT_TRANSFORM:
return TRUE;
default:
return FALSE;
diff --git a/pango/pango-markup.c b/pango/pango-markup.c
index a897a52d..f82aacef 100644
--- a/pango/pango-markup.c
+++ b/pango/pango-markup.c
@@ -1226,6 +1226,7 @@ span_parse_func (MarkupData *md G_GNUC_UNUSED,
const char *insert_hyphens = NULL;
const char *show = NULL;
const char *line_height = NULL;
+ const char *text_transform = NULL;
g_markup_parse_context_get_position (context,
&line_number, &char_number);
@@ -1294,6 +1295,9 @@ span_parse_func (MarkupData *md G_GNUC_UNUSED,
CHECK_ATTRIBUTE (strikethrough_color);
CHECK_ATTRIBUTE (style);
break;
+ case 't':
+ CHECK_ATTRIBUTE (text_transform);
+ break;
case 'g':
CHECK_ATTRIBUTE (gravity);
CHECK_ATTRIBUTE (gravity_hint);
@@ -1637,6 +1641,16 @@ span_parse_func (MarkupData *md G_GNUC_UNUSED,
add_attribute (tag, pango_attr_show_new (flags));
}
+ if (G_UNLIKELY (text_transform))
+ {
+ PangoTextTransform tf;
+
+ if (!span_parse_enum ("text_transform", text_transform, PANGO_TYPE_TEXT_TRANSFORM, (int*)(void*)&tf, line_number, error))
+ goto error;
+
+ add_attribute (tag, pango_attr_text_transform_new (tf));
+ }
+
if (G_UNLIKELY (rise))
{
gint n = 0;
diff --git a/pango/shape.c b/pango/shape.c
index 8743fad3..aeb9aa47 100644
--- a/pango/shape.c
+++ b/pango/shape.c
@@ -31,8 +31,8 @@
#include "pango-font-private.h"
/* {{{ Harfbuzz shaping */
-
/* {{{{ Buffer handling */
+
static hb_buffer_t *cached_buffer = NULL; /* MT-safe */
G_LOCK_DEFINE_STATIC (cached_buffer);
@@ -70,6 +70,7 @@ release_buffer (hb_buffer_t *buffer,
else
hb_buffer_destroy (buffer);
}
+
/* }}}} */
/* {{{{ Use PangoFont with Harfbuzz */
@@ -234,6 +235,7 @@ pango_font_get_hb_font_for_context (PangoFont *font,
/* }}}} */
/* {{{{ Utilities */
+
static void
apply_extra_attributes (GSList *attrs,
hb_feature_t *features,
@@ -317,13 +319,31 @@ find_show_flags (const PangoAnalysis *analysis)
return flags;
}
+static PangoTextTransform
+find_text_transform (const PangoAnalysis *analysis)
+{
+ GSList *l;
+
+ for (l = analysis->extra_attrs; l; l = l->next)
+ {
+ PangoAttribute *attr = l->data;
+
+ if (attr->klass->type == PANGO_ATTR_TEXT_TRANSFORM)
+ return (PangoTextTransform) ((PangoAttrInt*)attr)->value;
+ }
+
+ return PANGO_TEXT_TRANSFORM_NONE;
+}
+
/* }}}} */
+
static void
pango_hb_shape (const char *item_text,
int item_length,
const char *paragraph_text,
int paragraph_length,
const PangoAnalysis *analysis,
+ PangoLogAttr *log_attrs,
PangoGlyphString *glyphs,
PangoShapeFlags flags)
{
@@ -341,6 +361,7 @@ pango_hb_shape (const char *item_text,
hb_feature_t features[32];
unsigned int num_features = 0;
PangoGlyphInfo *infos;
+ PangoTextTransform transform;
g_return_if_fail (analysis != NULL);
g_return_if_fail (analysis->font != NULL);
@@ -349,6 +370,8 @@ pango_hb_shape (const char *item_text,
hb_font = pango_font_get_hb_font_for_context (analysis->font, &context);
hb_buffer = acquire_buffer (&free_buffer);
+ transform = find_text_transform (analysis);
+
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);
@@ -369,7 +392,67 @@ pango_hb_shape (const char *item_text,
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 (transform == PANGO_TEXT_TRANSFORM_NONE)
+ {
+ hb_buffer_add_utf8 (hb_buffer, paragraph_text, paragraph_length, item_offset, item_length);
+ }
+ else
+ {
+ const char *p;
+ int i;
+
+ /* Add pre-context */
+ hb_buffer_add_utf8 (hb_buffer, paragraph_text, item_offset, item_offset, 0);
+
+ /* Transform the item text according to text transform.
+ * Note: we assume text transforms won't cross font boundaries
+ */
+ for (p = paragraph_text + item_offset, i = 0; p < paragraph_text + item_offset + item_length; p = g_utf8_next_char (p), i++)
+ {
+ int index = p - paragraph_text;
+ gunichar ch = g_utf8_get_char (p);
+ char *str = NULL;
+
+ switch (transform)
+ {
+ case PANGO_TEXT_TRANSFORM_LOWERCASE:
+ if (g_unichar_isalnum (ch))
+ str = g_utf8_strdown (p, g_utf8_next_char (p) - p);
+ break;
+
+ case PANGO_TEXT_TRANSFORM_UPPERCASE:
+ if (g_unichar_isalnum (ch))
+ str = g_utf8_strup (p, g_utf8_next_char (p) - p);
+ break;
+
+ case PANGO_TEXT_TRANSFORM_CAPITALIZE:
+ if (log_attrs[i].is_word_start)
+ ch = g_unichar_totitle (ch);
+ break;
+
+ case PANGO_TEXT_TRANSFORM_NONE:
+ default:
+ g_assert_not_reached ();
+ }
+
+ if (str)
+ {
+ for (const char *q = str; *q; q = g_utf8_next_char (q))
+ {
+ ch = g_utf8_get_char (q);
+ hb_buffer_add (hb_buffer, ch, index);
+ }
+ g_free (str);
+ }
+ else
+ hb_buffer_add (hb_buffer, ch, index);
+ }
+
+ /* Add post-context */
+ hb_buffer_add_utf8 (hb_buffer, paragraph_text + item_offset + item_length, paragraph_length - (item_offset + item_length),
+ item_offset + item_length, 0);
+ }
+
if (analysis->flags & PANGO_ANALYSIS_FLAG_NEED_HYPHEN)
{
/* Insert either a Unicode or ASCII hyphen. We may
@@ -379,6 +462,7 @@ pango_hb_shape (const char *item_text,
int last_char_len = p - g_utf8_prev_char (p);
hb_codepoint_t glyph;
+ /* Note: We rely on hb_buffer_add clearing existing post-context */
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))
@@ -485,121 +569,18 @@ fallback_shape (const char *text,
pango_glyph_string_reverse_range (glyphs, 0, glyphs->num_glyphs);
}
-/* }}} */
-/* {{{ Public API */
+/* }}} */
+/* {{{ Shaping implementation */
-/**
- * pango_shape:
- * @text: the text to process
- * @length: the length (in bytes) of @text
- * @analysis: `PangoAnalysis` structure from [func@itemize]
- * @glyphs: glyph string in which to store results
- *
- * Convert the characters in @text into glyphs.
- *
- * Given a segment of text and the corresponding `PangoAnalysis` structure
- * returned from [func@itemize], convert the characters into glyphs. You
- * may also pass in only a substring of the item from [func@itemize].
- *
- * It is recommended that you use [func@shape_full] instead, since
- * that API allows for shaping interaction happening across text item
- * boundaries.
- *
- * Note that the extra attributes in the @analyis that is returned from
- * [func@itemize] have indices that are relative to the entire paragraph,
- * so you need to subtract the item offset from their indices before
- * calling [func@shape].
- */
-void
-pango_shape (const char *text,
- int length,
- const PangoAnalysis *analysis,
- PangoGlyphString *glyphs)
-{
- pango_shape_full (text, length, text, length, analysis, glyphs);
-}
-
-/**
- * pango_shape_full:
- * @item_text: valid UTF-8 text to shape.
- * @item_length: the length (in bytes) of @item_text. -1 means nul-terminated text.
- * @paragraph_text: (nullable): text of the paragraph (see details). May be %NULL.
- * @paragraph_length: the length (in bytes) of @paragraph_text. -1 means nul-terminated text.
- * @analysis: `PangoAnalysis` structure from [func@itemize].
- * @glyphs: glyph string in which to store results.
- *
- * Convert the characters in @text into glyphs.
- *
- * Given a segment of text and the corresponding `PangoAnalysis` structure
- * returned from [func@itemize], convert the characters into glyphs. You may
- * also pass in only a substring of the item from [func@itemize].
- *
- * This is similar to [func@shape], except it also can optionally take
- * the full paragraph text as input, which will then be used to perform
- * certain cross-item shaping interactions. If you have access to the broader
- * text of which @item_text is part of, provide the broader text as
- * @paragraph_text. If @paragraph_text is %NULL, item text is used instead.
- *
- * Note that the extra attributes in the @analyis that is returned from
- * [func@itemize] have indices that are relative to the entire paragraph,
- * so you do not pass the full paragraph text as @paragraph_text, you need
- * to subtract the item offset from their indices before calling [func@shape_full].
- *
- * Since: 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_shape_with_flags (item_text, item_length,
- paragraph_text, paragraph_length,
- analysis,
- glyphs,
- PANGO_SHAPE_NONE);
-}
-
-/**
- * pango_shape_with_flags:
- * @item_text: valid UTF-8 text to shape
- * @item_length: the length (in bytes) of @item_text.
- * -1 means nul-terminated text.
- * @paragraph_text: (nullable): text of the paragraph (see details).
- * May be %NULL.
- * @paragraph_length: the length (in bytes) of @paragraph_text.
- * -1 means nul-terminated text.
- * @analysis: `PangoAnalysis` structure from [func@itemize]
- * @glyphs: glyph string in which to store results
- * @flags: flags influencing the shaping process
- *
- * Convert the characters in @text into glyphs.
- *
- * Given a segment of text and the corresponding `PangoAnalysis` structure
- * returned from [func@itemize], convert the characters into glyphs. You may
- * also pass in only a substring of the item from [func@itemize].
- *
- * This is similar to [func@shape_full], except it also takes flags that can
- * influence the shaping process.
- *
- * Note that the extra attributes in the @analyis that is returned from
- * [func@itemize] have indices that are relative to the entire paragraph,
- * so you do not pass the full paragraph text as @paragraph_text, you need
- * to subtract the item offset from their indices before calling
- * [func@shape_with_flags].
- *
- * Since: 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)
+static void
+pango_shape_internal (const char *item_text,
+ int item_length,
+ const char *paragraph_text,
+ int paragraph_length,
+ const PangoAnalysis *analysis,
+ PangoLogAttr *log_attrs,
+ PangoGlyphString *glyphs,
+ PangoShapeFlags flags)
{
int i;
int last_cluster;
@@ -625,6 +606,7 @@ pango_shape_with_flags (const char *item_text,
pango_hb_shape (item_text, item_length,
paragraph_text, paragraph_length,
analysis,
+ log_attrs,
glyphs,
flags);
@@ -768,5 +750,166 @@ pango_shape_with_flags (const char *item_text,
}
/* }}} */
+/* {{{ Public API */
+
+/**
+ * pango_shape:
+ * @text: the text to process
+ * @length: the length (in bytes) of @text
+ * @analysis: `PangoAnalysis` structure from [func@Pango.itemize]
+ * @glyphs: glyph string in which to store results
+ *
+ * Convert the characters in @text into glyphs.
+ *
+ * Given a segment of text and the corresponding `PangoAnalysis` structure
+ * returned from [func@Pango.itemize], convert the characters into glyphs. You
+ * may also pass in only a substring of the item from [func@Pango.itemize].
+ *
+ * It is recommended that you use [func@Pango.shape_full] instead, since
+ * that API allows for shaping interaction happening across text item
+ * boundaries.
+ *
+ * Note that the extra attributes in the @analyis that is returned from
+ * [func@Pango.itemize] have indices that are relative to the entire paragraph,
+ * so you need to subtract the item offset from their indices before
+ * calling [func@Pango.shape].
+ */
+void
+pango_shape (const char *text,
+ int length,
+ const PangoAnalysis *analysis,
+ PangoGlyphString *glyphs)
+{
+ pango_shape_full (text, length, text, length, analysis, glyphs);
+}
+
+/**
+ * pango_shape_full:
+ * @item_text: valid UTF-8 text to shape.
+ * @item_length: the length (in bytes) of @item_text. -1 means nul-terminated text.
+ * @paragraph_text: (nullable): text of the paragraph (see details).
+ * @paragraph_length: the length (in bytes) of @paragraph_text. -1 means nul-terminated text.
+ * @analysis: `PangoAnalysis` structure from [func@Pango.itemize].
+ * @glyphs: glyph string in which to store results.
+ *
+ * Convert the characters in @text into glyphs.
+ *
+ * Given a segment of text and the corresponding `PangoAnalysis` structure
+ * returned from [func@Pango.itemize], convert the characters into glyphs.
+ * You may also pass in only a substring of the item from [func@Pango.itemize].
+ *
+ * This is similar to [func@Pango.shape], except it also can optionally take
+ * the full paragraph text as input, which will then be used to perform
+ * certain cross-item shaping interactions. If you have access to the broader
+ * text of which @item_text is part of, provide the broader text as
+ * @paragraph_text. If @paragraph_text is %NULL, item text is used instead.
+ *
+ * Note that the extra attributes in the @analyis that is returned from
+ * [func@Pango.itemize] have indices that are relative to the entire paragraph,
+ * so you do not pass the full paragraph text as @paragraph_text, you need
+ * to subtract the item offset from their indices before calling
+ * [func@Pango.shape_full].
+ *
+ * Since: 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_shape_with_flags (item_text, item_length,
+ paragraph_text, paragraph_length,
+ analysis,
+ glyphs,
+ PANGO_SHAPE_NONE);
+}
+
+/**
+ * pango_shape_with_flags:
+ * @item_text: valid UTF-8 text to shape
+ * @item_length: the length (in bytes) of @item_text.
+ * -1 means nul-terminated text.
+ * @paragraph_text: (nullable): text of the paragraph (see details).
+ * @paragraph_length: the length (in bytes) of @paragraph_text.
+ * -1 means nul-terminated text.
+ * @analysis: `PangoAnalysis` structure from [func@Pango.itemize]
+ * @glyphs: glyph string in which to store results
+ * @flags: flags influencing the shaping process
+ *
+ * Convert the characters in @text into glyphs.
+ *
+ * Given a segment of text and the corresponding `PangoAnalysis` structure
+ * returned from [func@Pango.itemize], convert the characters into glyphs.
+ * You may also pass in only a substring of the item from [func@Pango.itemize].
+ *
+ * This is similar to [func@Pango.shape_full], except it also takes flags
+ * that can influence the shaping process.
+ *
+ * Note that the extra attributes in the @analyis that is returned from
+ * [func@Pango.itemize] have indices that are relative to the entire paragraph,
+ * so you do not pass the full paragraph text as @paragraph_text, you need
+ * to subtract the item offset from their indices before calling
+ * [func@Pango.shape_with_flags].
+ *
+ * Since: 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)
+{
+ pango_shape_internal (item_text, item_length,
+ paragraph_text, paragraph_length,
+ analysis, NULL,
+ glyphs, flags);
+}
+
+/**
+ * pango_shape_item:
+ * @item: `PangoItem` to shape
+ * @paragraph_text: (nullable): text of the paragraph (see details).
+ * @paragraph_length: the length (in bytes) of @paragraph_text.
+ * -1 means nul-terminated text.
+ * @log_attrs: (nullable): array of `PangoLogAttr` for @item
+ * @glyphs: glyph string in which to store results
+ * @flags: flags influencing the shaping process
+ *
+ * Convert the characters in @item into glyphs.
+ *
+ * This is similar to [func@Pango.shape_with_flags], except it takes a
+ * `PangoItem` instead of separate @item_text and @analysis arguments.
+ * It also takes @log_attrs, which may be used in implementing text
+ * transforms.
+ *
+ * Note that the extra attributes in the @analyis that is returned from
+ * [func@Pango.itemize] have indices that are relative to the entire paragraph,
+ * so you do not pass the full paragraph text as @paragraph_text, you need
+ * to subtract the item offset from their indices before calling
+ * [func@Pango.shape_with_flags].
+ *
+ * Since: 1.50
+ */
+void
+pango_shape_item (PangoItem *item,
+ const char *paragraph_text,
+ int paragraph_length,
+ PangoLogAttr *log_attrs,
+ PangoGlyphString *glyphs,
+ PangoShapeFlags flags)
+{
+ pango_shape_internal (paragraph_text + item->offset, item->length,
+ paragraph_text, paragraph_length,
+ &item->analysis, log_attrs,
+ glyphs, flags);
+}
+
+/* }}} */
/* vim:set foldmethod=marker expandtab: */
diff --git a/tests/markup-parse.c b/tests/markup-parse.c
index fbe14402..b3248671 100644
--- a/tests/markup-parse.c
+++ b/tests/markup-parse.c
@@ -261,7 +261,7 @@ main (int argc, char *argv[])
const gchar *name;
gchar *path;
- g_setenv ("LC_ALL", "C", TRUE);
+ g_setenv ("LC_ALL", "en_US.UTF8", TRUE);
setlocale (LC_ALL, "");
/* allow to easily generate expected output for new test cases */
diff --git a/tests/markups/valid-24.expected b/tests/markups/valid-24.expected
new file mode 100644
index 00000000..06eb6e0c
--- /dev/null
+++ b/tests/markups/valid-24.expected
@@ -0,0 +1,19 @@
+straße up, up and away
+
+
+---
+
+range 0 7
+[0,7]text-transform=2
+range 7 8
+range 8 23
+[8,23]text-transform=3
+range 23 2147483647
+
+
+---
+
+[0:7] (null) Normal
+[7:8] (null) Normal
+[8:23] (null) Normal
+[23:2147483647] (null) Normal
diff --git a/tests/markups/valid-24.markup b/tests/markups/valid-24.markup
new file mode 100644
index 00000000..d9a7edd5
--- /dev/null
+++ b/tests/markups/valid-24.markup
@@ -0,0 +1 @@
+<span text_transform='uppercase'>straße</span> <span text_transform='capitalize'>up, up and away</span>
diff --git a/tests/test-common.c b/tests/test-common.c
index 78ed722f..3df4015c 100644
--- a/tests/test-common.c
+++ b/tests/test-common.c
@@ -142,6 +142,7 @@ print_attribute (PangoAttribute *attr, GString *string)
case PANGO_ATTR_ALLOW_BREAKS:
case PANGO_ATTR_INSERT_HYPHENS:
case PANGO_ATTR_SHOW:
+ case PANGO_ATTR_TEXT_TRANSFORM:
g_string_append_printf (string, "%d", ((PangoAttrInt *)attr)->value);
break;
case PANGO_ATTR_FONT_DESC:
diff --git a/tests/testattributes.c b/tests/testattributes.c
index aaf270f5..79caf7b8 100644
--- a/tests/testattributes.c
+++ b/tests/testattributes.c
@@ -69,6 +69,7 @@ test_attributes_basic (void)
test_copy (pango_attr_allow_breaks_new (FALSE));
test_copy (pango_attr_show_new (PANGO_SHOW_SPACES));
test_copy (pango_attr_insert_hyphens_new (FALSE));
+ test_copy (pango_attr_text_transform_new (PANGO_TEXT_TRANSFORM_UPPERCASE));
}
static void