summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2021-11-21 23:19:27 -0500
committerMatthias Clasen <mclasen@redhat.com>2021-11-24 19:57:58 -0500
commitb9ed027ed762f5ee384defcf4cfa5bc6c9279968 (patch)
tree214ec34f50b42261eefa45a56a5ebdf5f4811b25
parentc1f9c9f85bf9f400e44477304e5eb135f1183ac9 (diff)
downloadpango-b9ed027ed762f5ee384defcf4cfa5bc6c9279968.tar.gz
Allow serializing context information
Optionally include context information in the serialization and restore it. This will be useful for transporting for giving tests complete data that affects their output. Some tests included.
-rw-r--r--pango/pango-layout.h5
-rw-r--r--pango/serializer.c139
-rw-r--r--tests/testserialize.c45
3 files changed, 179 insertions, 10 deletions
diff --git a/pango/pango-layout.h b/pango/pango-layout.h
index e9b4710c..3c43c202 100644
--- a/pango/pango-layout.h
+++ b/pango/pango-layout.h
@@ -354,6 +354,7 @@ GSList * pango_layout_get_lines_readonly (PangoLayout *layout);
/**
* PangoLayoutSerializeFlags:
* @PANGO_LAYOUT_SERIALIZE_DEFAULT: Default behavior
+ * @PANGO_LAYOUT_SERIALIZE_CONTEXT: Include context information
*
* Flags that influence the behavior of [method@Pango.Layout.serialize].
*
@@ -361,6 +362,7 @@ GSList * pango_layout_get_lines_readonly (PangoLayout *layout);
*/
typedef enum {
PANGO_LAYOUT_SERIALIZE_DEFAULT = 0,
+ PANGO_LAYOUT_SERIALIZE_CONTEXT = 1 << 0,
} PangoLayoutSerializeFlags;
PANGO_AVAILABLE_IN_1_50
@@ -402,6 +404,8 @@ GQuark pango_layout_deserialize_error_quark (void);
/**
* PangoLayoutDeserializeFlags:
* @PANGO_LAYOUT_DESERIALIZE_DEFAULT: Default behavior
+ * @PANGO_LAYOUT_DESERIALIZE_CONTEXT: Apply context information
+ * from the serialization to the `PangoContext`
*
* Flags that influence the behavior of [method@Pango.Layout.deserialize].
*
@@ -409,6 +413,7 @@ GQuark pango_layout_deserialize_error_quark (void);
*/
typedef enum {
PANGO_LAYOUT_DESERIALIZE_DEFAULT = 0,
+ PANGO_LAYOUT_DESERIALIZE_CONTEXT = 1 << 0,
} PangoLayoutDeserializeFlags;
PANGO_AVAILABLE_IN_1_50
diff --git a/pango/serializer.c b/pango/serializer.c
index b9c24422..ca92eb21 100644
--- a/pango/serializer.c
+++ b/pango/serializer.c
@@ -23,6 +23,7 @@
#include <pango/pango-layout.h>
#include <pango/pango-layout-private.h>
+#include <pango/pango-context-private.h>
#include <pango/pango-enum-types.h>
#include <json-glib/json-glib.h>
@@ -211,8 +212,43 @@ add_tab_array (JsonBuilder *builder,
json_builder_end_object (builder);
}
+static void
+add_context (JsonBuilder *builder,
+ PangoContext *context)
+{
+ json_builder_begin_object (builder);
+
+ /* Note: since we don't create the context when deserializing,
+ * we don't strip out default values here to ensure that the
+ * context gets updated as expected.
+ */
+
+ if (context->set_language)
+ {
+ json_builder_set_member_name (builder, "language");
+ json_builder_add_string_value (builder, pango_language_to_string (context->set_language));
+ }
+
+ json_builder_set_member_name (builder, "base-gravity");
+ add_enum_value (builder, PANGO_TYPE_GRAVITY, context->base_gravity, FALSE);
+
+ json_builder_set_member_name (builder, "gravity-hint");
+ add_enum_value (builder, PANGO_TYPE_GRAVITY_HINT, context->gravity_hint, FALSE);
+
+ json_builder_set_member_name (builder, "direction");
+ add_enum_value (builder, PANGO_TYPE_DIRECTION, context->base_dir, FALSE);
+
+ json_builder_set_member_name (builder, "round-glyph-positions");
+ json_builder_add_boolean_value (builder, context->round_glyph_positions);
+
+ /* FIXME transform */
+
+ json_builder_end_object (builder);
+}
+
static JsonNode *
-layout_to_json (PangoLayout *layout)
+layout_to_json (PangoLayout *layout,
+ PangoLayoutSerializeFlags flags)
{
JsonBuilder *builder;
JsonNode *root;
@@ -221,6 +257,12 @@ layout_to_json (PangoLayout *layout)
json_builder_begin_object (builder);
+ if (flags & PANGO_LAYOUT_SERIALIZE_CONTEXT)
+ {
+ json_builder_set_member_name (builder, "context");
+ add_context (builder, layout->context);
+ }
+
json_builder_set_member_name (builder, "text");
json_builder_add_string_value (builder, layout->text);
@@ -663,16 +705,79 @@ fail:
return NULL;
}
+static gboolean
+apply_json_to_context (JsonReader *reader,
+ PangoContext *context,
+ GError **error)
+{
+ if (json_reader_read_member (reader, "language"))
+ {
+ const char *value;
+ PangoLanguage *language;
+
+ value = json_reader_get_string_value (reader);
+ language = pango_language_from_string (value);
+ pango_context_set_language (context, language);
+ }
+ json_reader_end_member (reader);
+
+ if (json_reader_read_member (reader, "base-gravity"))
+ {
+ PangoGravity gravity = get_enum_value (PANGO_TYPE_GRAVITY,
+ json_reader_get_string_value (reader),
+ FALSE,
+ error);
+ if (gravity == -1)
+ return FALSE;
+
+ pango_context_set_base_gravity (context, gravity);
+ }
+ json_reader_end_member (reader);
+
+ if (json_reader_read_member (reader, "gravity-hint"))
+ {
+ PangoGravityHint gravity_hint = get_enum_value (PANGO_TYPE_GRAVITY_HINT,
+ json_reader_get_string_value (reader),
+ FALSE,
+ error);
+ if (gravity_hint == -1)
+ return FALSE;
+
+ pango_context_set_gravity_hint (context, gravity_hint);
+ }
+ json_reader_end_member (reader);
+
+ if (json_reader_read_member (reader, "base-dir"))
+ {
+ PangoDirection direction = get_enum_value (PANGO_TYPE_DIRECTION,
+ json_reader_get_string_value (reader),
+ FALSE,
+ error);
+ if (direction == -1)
+ return FALSE;
+
+ pango_context_set_base_dir (context, direction);
+ }
+ json_reader_end_member (reader);
+
+ if (json_reader_read_member (reader, "round-glyph-positions"))
+ {
+ pango_context_set_round_glyph_positions (context, json_reader_get_boolean_value (reader));
+ }
+ json_reader_end_member (reader);
+
+ return TRUE;
+}
+
static PangoLayout *
-json_to_layout (PangoContext *context,
- JsonNode *node,
- GError **error)
+json_to_layout (PangoContext *context,
+ JsonNode *node,
+ PangoLayoutDeserializeFlags flags,
+ GError **error)
{
JsonReader *reader;
PangoLayout *layout;
- layout = pango_layout_new (context);
-
reader = json_reader_new (node);
if (!json_reader_is_object (reader))
{
@@ -683,6 +788,18 @@ json_to_layout (PangoContext *context,
goto fail;
}
+ if (flags & PANGO_LAYOUT_DESERIALIZE_CONTEXT)
+ {
+ if (json_reader_read_member (reader, "context"))
+ {
+ if (!apply_json_to_context (reader, context, error))
+ goto fail;
+ }
+ json_reader_end_member (reader);
+ }
+
+ layout = pango_layout_new (context);
+
if (json_reader_read_member (reader, "text"))
pango_layout_set_text (layout, json_reader_get_string_value (reader), -1);
json_reader_end_member (reader);
@@ -711,7 +828,8 @@ json_to_layout (PangoContext *context,
g_set_error (error,
PANGO_LAYOUT_DESERIALIZE_ERROR,
PANGO_LAYOUT_DESERIALIZE_INVALID_VALUE,
- "Could not parse \"font\" value: %s",
+ "Could not parse \"%s\" value: %s",
+ "font",
json_reader_get_string_value (reader));
goto fail;
}
@@ -820,7 +938,8 @@ json_to_layout (PangoContext *context,
fail:
g_object_unref (reader);
- g_object_unref (layout);
+ if (layout)
+ g_object_unref (layout);
return NULL;
}
@@ -856,7 +975,7 @@ pango_layout_serialize (PangoLayout *layout,
g_return_val_if_fail (PANGO_IS_LAYOUT (layout), NULL);
- node = layout_to_json (layout);
+ node = layout_to_json (layout, flags);
generator = json_generator_new ();
json_generator_set_pretty (generator, TRUE);
@@ -952,7 +1071,7 @@ pango_layout_deserialize (PangoContext *context,
}
node = json_parser_get_root (parser);
- layout = json_to_layout (context, node, error);
+ layout = json_to_layout (context, node, flags, error);
g_object_unref (parser);
diff --git a/tests/testserialize.c b/tests/testserialize.c
index d04ec7cf..43248777 100644
--- a/tests/testserialize.c
+++ b/tests/testserialize.c
@@ -243,6 +243,42 @@ test_serialize_layout_valid (void)
}
static void
+test_serialize_layout_context (void)
+{
+ const char *test =
+ "{\n"
+ " \"text\" : \"Some fun with layouts!\",\n"
+ " \"context\" : {\n"
+ " \"base-gravity\" : \"east\",\n"
+ " \"language\" : \"de-de\",\n"
+ " \"round-glyph-positions\" : \"false\"\n"
+ " }\n"
+ "}";
+
+ PangoContext *context;
+ GBytes *bytes;
+ PangoLayout *layout;
+ GError *error = NULL;
+
+ context = pango_font_map_create_context (pango_cairo_font_map_get_default ());
+
+ bytes = g_bytes_new_static (test, -1);
+
+ layout = pango_layout_deserialize (context, bytes, PANGO_LAYOUT_DESERIALIZE_CONTEXT, &error);
+ g_assert_no_error (error);
+ g_assert_true (PANGO_IS_LAYOUT (layout));
+ g_assert_cmpstr (pango_layout_get_text (layout), ==, "Some fun with layouts!");
+
+ g_assert_cmpint (pango_context_get_base_gravity (context), ==, PANGO_GRAVITY_EAST);
+ g_assert_true (pango_context_get_language (context) == pango_language_from_string ("de-de"));
+ g_assert_false (pango_context_get_round_glyph_positions (context));
+
+ g_object_unref (layout);
+ g_bytes_unref (bytes);
+ g_object_unref (context);
+}
+
+static void
test_serialize_layout_invalid (void)
{
struct {
@@ -285,6 +321,14 @@ test_serialize_layout_invalid (void)
" \"alignment\" : \"nonsense\"\n"
"}",
PANGO_LAYOUT_DESERIALIZE_INVALID_VALUE
+ },
+ {
+ "{\n"
+ " \"attributes\" : {\n"
+ " \"name\" : \"This is wrong\"\n"
+ " }\n"
+ "}",
+ PANGO_LAYOUT_DESERIALIZE_INVALID_SYNTAX
}
};
@@ -317,6 +361,7 @@ main (int argc, char *argv[])
g_test_add_func ("/serialize/tab-array", test_serialize_tab_array);
g_test_add_func ("/serialize/layout/minimal", test_serialize_layout_minimal);
g_test_add_func ("/serialize/layout/valid", test_serialize_layout_valid);
+ g_test_add_func ("/serialize/layout/context", test_serialize_layout_context);
g_test_add_func ("/serialize/layout/invalid", test_serialize_layout_invalid);
return g_test_run ();