summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2022-11-18 14:39:47 +0000
committerMatthias Clasen <mclasen@redhat.com>2022-11-18 14:39:47 +0000
commit29a72d39debea8f84eada42914aaa7d78b9d9fdc (patch)
treed71ca47383473cd5099a63926a7a000167f451a3
parentd616f88dbb6dd5360eebf8ab42884fb90583218b (diff)
parent81fcb4d2c1050c5c34cbaa03896a2adfba562872 (diff)
downloadpango-29a72d39debea8f84eada42914aaa7d78b9d9fdc.tar.gz
Merge branch 'matthiasc/for-main' into 'main'
Improve PangoAttrList serialization See merge request GNOME/pango!656
-rw-r--r--pango/break-thai.c4
-rw-r--r--pango/pango-attributes.c70
-rw-r--r--tests/markups/valid-19.expected2
-rw-r--r--tests/markups/valid-4.expected4
-rw-r--r--tests/testserialize.c16
5 files changed, 79 insertions, 17 deletions
diff --git a/pango/break-thai.c b/pango/break-thai.c
index 02a18cc5..3da0e3c6 100644
--- a/pango/break-thai.c
+++ b/pango/break-thai.c
@@ -84,8 +84,8 @@ break_thai (const char *text,
G_LOCK (thai_brk);
#ifdef HAVE_TH_BRK_FIND_BREAKS
if (thai_brk == NULL)
- thai_brk = th_brk_new(NULL);
- len = th_brk_find_breaks(thai_brk, tis_text, brk_pnts, cnt);
+ thai_brk = th_brk_new (NULL);
+ len = th_brk_find_breaks (thai_brk, tis_text, brk_pnts, cnt);
#else
len = th_brk (tis_text, brk_pnts, cnt);
#endif
diff --git a/pango/pango-attributes.c b/pango/pango-attributes.c
index 20809afc..47aa0aad 100644
--- a/pango/pango-attributes.c
+++ b/pango/pango-attributes.c
@@ -2644,7 +2644,11 @@ attr_print (GString *str,
attr->klass->type == PANGO_ATTR_FALLBACK)
g_string_append (str, ((PangoAttrInt *)attr)->value ? " true" : " false");
else if ((string = pango_attribute_as_string (attr)) != NULL)
- g_string_append_printf (str, " %s", string->value);
+ {
+ char *s = g_strescape (string->value, NULL);
+ g_string_append_printf (str, " \"%s\"", s);
+ g_free (s);
+ }
else if ((lang = pango_attribute_as_language (attr)) != NULL)
g_string_append_printf (str, " %s", pango_language_to_string (lang->value));
else if ((integer = pango_attribute_as_int (attr)) != NULL)
@@ -2658,7 +2662,9 @@ attr_print (GString *str,
else if ((font = pango_attribute_as_font_desc (attr)) != NULL)
{
char *s = pango_font_description_to_string (font->desc);
- g_string_append_printf (str, " \"%s\"", s);
+ char *s2 = g_strescape (s, NULL);
+ g_string_append_printf (str, " \"%s\"", s2);
+ g_free (s2);
g_free (s);
}
else if ((color = pango_attribute_as_color (attr)) != NULL)
@@ -2683,12 +2689,38 @@ attr_print (GString *str,
*
* Serializes a `PangoAttrList` to a string.
*
- * No guarantees are made about the format of the string,
- * it may change between Pango versions.
+ * In the resulting string, serialized attributes are separated by newlines or commas.
+ * Individual attributes are serialized to a string of the form
+ *
+ * START END TYPE VALUE
+ *
+ * Where START and END are the indices (with -1 being accepted in place
+ * of MAXUINT), TYPE is the nickname of the attribute value type, e.g.
+ * _weight_ or _stretch_, and the value is serialized according to its type:
+ *
+ * - enum values as nick or numeric value
+ * - boolean values as _true_ or _false_
+ * - integers and floats as numbers
+ * - strings as string, optionally quoted
+ * - font features as quoted string
+ * - PangoLanguage as string
+ * - PangoFontDescription as serialized by [method@Pango.FontDescription.to_string], quoted
+ * - PangoColor as serialized by [method@Pango.Color.to_string]
+ *
+ * Examples:
+ *
+ * ```
+ * 0 10 foreground red, 5 15 weight bold, 0 200 font-desc "Sans 10"
+ * ```
*
- * The intended use of this function is testing and
- * debugging. The format is not meant as a permanent
- * storage format.
+ * ```
+ * 0 -1 weight 700
+ * 0 100 family Times
+ * ```
+ *
+ * To parse the returned value, use [func@Pango.AttrList.from_string].
+ *
+ * Note that shape attributes can not be serialized.
*
* Returns: (transfer full): a newly allocated string
* Since: 1.50
@@ -2807,6 +2839,7 @@ pango_attr_list_from_string (const char *text)
PangoFontDescription *desc;
PangoColor color;
double num;
+ int len;
start_index = g_ascii_strtoll (p, &endp, 10);
if (*endp != ' ')
@@ -2852,7 +2885,10 @@ pango_attr_list_from_string (const char *text)
#define ENUM_ATTR(name, type, min, max) \
endp = (char *)p + strcspn (p, ",\n"); \
- integer = get_attr_value (attr_type, p, endp - p); \
+ len = endp - p; \
+ while (len > 0 && p[len - 1] == ' ') \
+ len--; \
+ integer = get_attr_value (attr_type, p, len); \
attr = pango_attr_##name##_new ((type) CLAMP (integer, min, max));
#define FLOAT_ATTR(name) \
@@ -2890,7 +2926,22 @@ pango_attr_list_from_string (const char *text)
case PANGO_ATTR_FAMILY:
endp = (char *)p + strcspn (p, ",\n");
if (!is_valid_end_char (*endp)) goto fail;
- str = g_strndup (p, endp - p);
+ if (p[0] == '"')
+ {
+ char *str2;
+
+ len = endp - p;
+ while (len > 0 && p[len - 1] == ' ')
+ len--;
+
+ if (p[len - 1] != '"') goto fail;
+
+ str2 = g_strndup (p + 1, len - 2);
+ str = g_strcompress (str2);
+ g_free (str2);
+ }
+ else
+ str = g_strndup (p, endp - p);
attr = pango_attr_family_new (str);
g_free (str);
break;
@@ -2916,6 +2967,7 @@ pango_attr_list_from_string (const char *text)
break;
case PANGO_ATTR_FONT_DESC:
+ if (*p != '"') goto fail;
p++;
endp = strchr (p, '"');
if (!endp) goto fail;
diff --git a/tests/markups/valid-19.expected b/tests/markups/valid-19.expected
index 5b84133f..9de3df07 100644
--- a/tests/markups/valid-19.expected
+++ b/tests/markups/valid-19.expected
@@ -4,7 +4,7 @@ test
---
range 0 4
-0 4 family Times
+0 4 family "Times"
0 4 weight bold
0 4 foreground #ffff00000000
0 4 letter-spacing 1024
diff --git a/tests/markups/valid-4.expected b/tests/markups/valid-4.expected
index 345e8699..11ecfab1 100644
--- a/tests/markups/valid-4.expected
+++ b/tests/markups/valid-4.expected
@@ -31,9 +31,9 @@ range 38 41
38 41 baseline-shift superscript
range 41 42
range 42 45
-42 54 family Monospace
+42 54 family "Monospace"
range 45 54
-42 54 family Monospace
+42 54 family "Monospace"
45 54 underline single
range 54 2147483647
diff --git a/tests/testserialize.c b/tests/testserialize.c
index e480da31..0021ffe0 100644
--- a/tests/testserialize.c
+++ b/tests/testserialize.c
@@ -30,6 +30,11 @@ test_serialize_attr_list (void)
{
const char *valid[] = {
"5 16 style italic",
+ " 5 16 style italic ",
+ "0 -1 language de ",
+ "0 1 family Times",
+ "0 1 family \"Times\" ",
+ "0 1 family \"Times\\n\\\"New\\\" Roman\" ",
"0 10 foreground red, 5 15 weight bold, 0 200 font-desc \"Sans Small-Caps 10\"",
"0 10 foreground red\n5 15 weight bold\n0 200 font-desc \"Sans Small-Caps 10\"",
" 0 10 fallback false,\n 5 15 weight semilight\n\n \n \n",
@@ -37,18 +42,23 @@ test_serialize_attr_list (void)
"0 -1 size 10",
"0 1 weight 700, 2 4 weight book",
"0 200 rise 100\n5 15 family Times\n10 11 size 10240\n11 100 fallback 0\n30 60 stretch 2\n",
- ""
+ "",
};
const char *roundtripped[] = {
"5 16 style italic",
+ "5 16 style italic",
+ "0 4294967295 language de",
+ "0 1 family \"Times\"",
+ "0 1 family \"Times\"",
+ "0 1 family \"Times\\n\\\"New\\\" Roman\"",
"0 10 foreground #ffff00000000\n5 15 weight bold\n0 200 font-desc \"Sans Small-Caps 10\"",
"0 10 foreground #ffff00000000\n5 15 weight bold\n0 200 font-desc \"Sans Small-Caps 10\"",
"0 10 fallback false\n5 15 weight semilight",
"0 100 font-desc \"Cantarell,Sans Ultra-Light Italic 64\"\n10 11 weight thin",
"0 4294967295 size 10",
"0 1 weight bold\n2 4 weight book",
- "0 200 rise 100\n5 15 family Times\n10 11 size 10240\n11 100 fallback false\n30 60 stretch condensed",
- ""
+ "0 200 rise 100\n5 15 family \"Times\"\n10 11 size 10240\n11 100 fallback false\n30 60 stretch condensed",
+ "",
};
const char *invalid[] = {
"not an attr list",