Commit b9ed027e authored by Matthias Clasen's avatar Matthias Clasen
Browse files

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.
parent c1f9c9f8
......@@ -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
......
......@@ -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);
......
......@@ -242,6 +242,42 @@ test_serialize_layout_valid (void)
g_object_unref (context);
}
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)
{
......@@ -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 ();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment