123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086 |
- /* LIBGIMP - The GIMP Library
- * Copyright (C) 1995 Spencer Kimball and Peter Mattis
- *
- * gimpscanner.c
- * Copyright (C) 2002 Sven Neumann <sven@gimp.org>
- * Michael Natterer <mitch@gimp.org>
- *
- * This library is free software: you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <https://www.gnu.org/licenses/>.
- */
- #include "config.h"
- #include <string.h>
- #include <errno.h>
- #include <cairo.h>
- #include <gegl.h>
- #include <gdk-pixbuf/gdk-pixbuf.h>
- #include "libgimpbase/gimpbase.h"
- #include "libgimpcolor/gimpcolor.h"
- #include "libgimpmath/gimpmath.h"
- #include "gimpconfig-error.h"
- #include "gimpscanner.h"
- #include "libgimp/libgimp-intl.h"
- /**
- * SECTION: gimpscanner
- * @title: GimpScanner
- * @short_description: A wrapper around #GScanner with some convenience API.
- *
- * A wrapper around #GScanner with some convenience API.
- **/
- typedef struct
- {
- gint ref_count;
- gchar *name;
- GMappedFile *mapped;
- gchar *text;
- GError **error;
- } GimpScannerData;
- G_DEFINE_BOXED_TYPE (GimpScanner, gimp_scanner,
- gimp_scanner_ref, gimp_scanner_unref)
- /* local function prototypes */
- static GimpScanner * gimp_scanner_new (const gchar *name,
- GMappedFile *mapped,
- gchar *text,
- GError **error);
- static void gimp_scanner_message (GimpScanner *scanner,
- gchar *message,
- gboolean is_error);
- static GTokenType gimp_scanner_parse_deprecated_color (GimpScanner *scanner,
- GeglColor **color);
- /* public functions */
- /**
- * gimp_scanner_new_file:
- * @file: a #GFile
- * @error: return location for #GError, or %NULL
- *
- * Returns: (transfer full): The new #GimpScanner.
- *
- * Since: 2.10
- **/
- GimpScanner *
- gimp_scanner_new_file (GFile *file,
- GError **error)
- {
- GimpScanner *scanner;
- gchar *path;
- g_return_val_if_fail (G_IS_FILE (file), NULL);
- g_return_val_if_fail (error == NULL || *error == NULL, NULL);
- path = g_file_get_path (file);
- if (path)
- {
- GMappedFile *mapped;
- mapped = g_mapped_file_new (path, FALSE, error);
- g_free (path);
- if (! mapped)
- {
- if (error)
- {
- (*error)->domain = GIMP_CONFIG_ERROR;
- (*error)->code = ((*error)->code == G_FILE_ERROR_NOENT ?
- GIMP_CONFIG_ERROR_OPEN_ENOENT :
- GIMP_CONFIG_ERROR_OPEN);
- }
- return NULL;
- }
- /* gimp_scanner_new() takes a "name" for the scanner, not a filename */
- scanner = gimp_scanner_new (gimp_file_get_utf8_name (file),
- mapped, NULL, error);
- g_scanner_input_text (scanner,
- g_mapped_file_get_contents (mapped),
- g_mapped_file_get_length (mapped));
- }
- else
- {
- GInputStream *input;
- input = G_INPUT_STREAM (g_file_read (file, NULL, error));
- if (! input)
- {
- if (error)
- {
- (*error)->domain = GIMP_CONFIG_ERROR;
- (*error)->code = ((*error)->code == G_IO_ERROR_NOT_FOUND ?
- GIMP_CONFIG_ERROR_OPEN_ENOENT :
- GIMP_CONFIG_ERROR_OPEN);
- }
- return NULL;
- }
- g_object_set_data (G_OBJECT (input), "gimp-data", file);
- scanner = gimp_scanner_new_stream (input, error);
- g_object_unref (input);
- }
- return scanner;
- }
- /**
- * gimp_scanner_new_stream:
- * @input: a #GInputStream
- * @error: return location for #GError, or %NULL
- *
- * Returns: (transfer full): The new #GimpScanner.
- *
- * Since: 2.10
- **/
- GimpScanner *
- gimp_scanner_new_stream (GInputStream *input,
- GError **error)
- {
- GimpScanner *scanner;
- GFile *file;
- const gchar *path;
- GString *string;
- gchar buffer[4096];
- gsize bytes_read;
- g_return_val_if_fail (G_IS_INPUT_STREAM (input), NULL);
- g_return_val_if_fail (error == NULL || *error == NULL, NULL);
- file = g_object_get_data (G_OBJECT (input), "gimp-file");
- if (file)
- path = gimp_file_get_utf8_name (file);
- else
- path = "stream";
- string = g_string_new (NULL);
- do
- {
- GError *my_error = NULL;
- gboolean success;
- success = g_input_stream_read_all (input, buffer, sizeof (buffer),
- &bytes_read, NULL, &my_error);
- if (bytes_read > 0)
- g_string_append_len (string, buffer, bytes_read);
- if (! success)
- {
- if (string->len > 0)
- {
- g_printerr ("%s: read error in '%s', trying to scan "
- "partial content: %s",
- G_STRFUNC, path, my_error->message);
- g_clear_error (&my_error);
- break;
- }
- g_string_free (string, TRUE);
- g_propagate_error (error, my_error);
- return NULL;
- }
- }
- while (bytes_read == sizeof (buffer));
- /* gimp_scanner_new() takes a "name" for the scanner, not a filename */
- scanner = gimp_scanner_new (path, NULL, string->str, error);
- bytes_read = string->len;
- g_scanner_input_text (scanner, g_string_free (string, FALSE), bytes_read);
- return scanner;
- }
- /**
- * gimp_scanner_new_string:
- * @text: (array length=text_len):
- * @text_len: The length of @text, or -1 if NULL-terminated
- * @error: return location for #GError, or %NULL
- *
- * Returns: (transfer full): The new #GimpScanner.
- *
- * Since: 2.4
- **/
- GimpScanner *
- gimp_scanner_new_string (const gchar *text,
- gint text_len,
- GError **error)
- {
- GimpScanner *scanner;
- g_return_val_if_fail (text != NULL || text_len <= 0, NULL);
- g_return_val_if_fail (error == NULL || *error == NULL, NULL);
- if (text_len < 0)
- text_len = text ? strlen (text) : 0;
- scanner = gimp_scanner_new (NULL, NULL, NULL, error);
- g_scanner_input_text (scanner, text, text_len);
- return scanner;
- }
- static GimpScanner *
- gimp_scanner_new (const gchar *name,
- GMappedFile *mapped,
- gchar *text,
- GError **error)
- {
- GimpScanner *scanner;
- GimpScannerData *data;
- scanner = g_scanner_new (NULL);
- data = g_slice_new0 (GimpScannerData);
- data->ref_count = 1;
- data->name = g_strdup (name);
- data->mapped = mapped;
- data->text = text;
- data->error = error;
- scanner->user_data = data;
- scanner->msg_handler = gimp_scanner_message;
- scanner->config->cset_identifier_first = ( G_CSET_a_2_z G_CSET_A_2_Z );
- scanner->config->cset_identifier_nth = ( G_CSET_a_2_z G_CSET_A_2_Z
- G_CSET_DIGITS "-_" );
- scanner->config->scan_identifier_1char = TRUE;
- scanner->config->store_int64 = TRUE;
- return scanner;
- }
- /**
- * gimp_scanner_ref:
- * @scanner: #GimpScanner to ref
- *
- * Adds a reference to a #GimpScanner.
- *
- * Returns: the same @scanner.
- *
- * Since: 3.0
- */
- GimpScanner *
- gimp_scanner_ref (GimpScanner *scanner)
- {
- GimpScannerData *data;
- g_return_val_if_fail (scanner != NULL, NULL);
- data = scanner->user_data;
- data->ref_count++;
- return scanner;
- }
- /**
- * gimp_scanner_unref:
- * @scanner: A #GimpScanner created by gimp_scanner_new_file() or
- * gimp_scanner_new_string()
- *
- * Unref a #GimpScanner. If the reference count drops to zero, the
- * scanner is freed.
- *
- * Since: 3.0
- **/
- void
- gimp_scanner_unref (GimpScanner *scanner)
- {
- GimpScannerData *data;
- g_return_if_fail (scanner != NULL);
- data = scanner->user_data;
- data->ref_count--;
- if (data->ref_count < 1)
- {
- if (data->mapped)
- g_mapped_file_unref (data->mapped);
- if (data->text)
- g_free (data->text);
- g_free (data->name);
- g_slice_free (GimpScannerData, data);
- g_scanner_destroy (scanner);
- }
- }
- /**
- * gimp_scanner_parse_token:
- * @scanner: A #GimpScanner created by gimp_scanner_new_file() or
- * gimp_scanner_new_string()
- * @token: the #GTokenType expected as next token.
- *
- * Returns: %TRUE if the next token is @token, %FALSE otherwise.
- *
- * Since: 2.4
- **/
- gboolean
- gimp_scanner_parse_token (GimpScanner *scanner,
- GTokenType token)
- {
- if (g_scanner_peek_next_token (scanner) != token)
- return FALSE;
- g_scanner_get_next_token (scanner);
- return TRUE;
- }
- /**
- * gimp_scanner_parse_identifier:
- * @scanner: A #GimpScanner created by gimp_scanner_new_file() or
- * gimp_scanner_new_string()
- * @identifier: (out): the expected identifier.
- *
- * Returns: %TRUE if the next token is an identifier and if its
- * value matches @identifier.
- *
- * Since: 2.4
- **/
- gboolean
- gimp_scanner_parse_identifier (GimpScanner *scanner,
- const gchar *identifier)
- {
- if (g_scanner_peek_next_token (scanner) != G_TOKEN_IDENTIFIER)
- return FALSE;
- g_scanner_get_next_token (scanner);
- if (strcmp (scanner->value.v_identifier, identifier))
- return FALSE;
- return TRUE;
- }
- /**
- * gimp_scanner_parse_string:
- * @scanner: A #GimpScanner created by gimp_scanner_new_file() or
- * gimp_scanner_new_string()
- * @dest: (out): Return location for the parsed string
- *
- * Returns: %TRUE on success
- *
- * Since: 2.4
- **/
- gboolean
- gimp_scanner_parse_string (GimpScanner *scanner,
- gchar **dest)
- {
- if (g_scanner_peek_next_token (scanner) != G_TOKEN_STRING)
- return FALSE;
- g_scanner_get_next_token (scanner);
- if (*scanner->value.v_string)
- {
- if (! g_utf8_validate (scanner->value.v_string, -1, NULL))
- {
- g_scanner_warn (scanner, _("invalid UTF-8 string"));
- return FALSE;
- }
- *dest = g_strdup (scanner->value.v_string);
- }
- else
- {
- *dest = NULL;
- }
- return TRUE;
- }
- /**
- * gimp_scanner_parse_string_no_validate:
- * @scanner: A #GimpScanner created by gimp_scanner_new_file() or
- * gimp_scanner_new_string()
- * @dest: (out): Return location for the parsed string
- *
- * Returns: %TRUE on success
- *
- * Since: 2.4
- **/
- gboolean
- gimp_scanner_parse_string_no_validate (GimpScanner *scanner,
- gchar **dest)
- {
- if (g_scanner_peek_next_token (scanner) != G_TOKEN_STRING)
- return FALSE;
- g_scanner_get_next_token (scanner);
- if (*scanner->value.v_string)
- *dest = g_strdup (scanner->value.v_string);
- else
- *dest = NULL;
- return TRUE;
- }
- /**
- * gimp_scanner_parse_data:
- * @scanner: A #GimpScanner created by gimp_scanner_new_file() or
- * gimp_scanner_new_string()
- * @length: Length of the data to parse
- * @dest: (out) (array length=length): Return location for the parsed data
- *
- * Returns: %TRUE on success
- *
- * Since: 2.4
- **/
- gboolean
- gimp_scanner_parse_data (GimpScanner *scanner,
- gint length,
- guint8 **dest)
- {
- if (g_scanner_peek_next_token (scanner) != G_TOKEN_STRING)
- return FALSE;
- g_scanner_get_next_token (scanner);
- if (scanner->value.v_string)
- *dest = g_memdup2 (scanner->value.v_string, length);
- else
- *dest = NULL;
- return TRUE;
- }
- /**
- * gimp_scanner_parse_int:
- * @scanner: A #GimpScanner created by gimp_scanner_new_file() or
- * gimp_scanner_new_string()
- * @dest: (out): Return location for the parsed integer
- *
- * Returns: %TRUE on success
- *
- * Since: 2.4
- **/
- gboolean
- gimp_scanner_parse_int (GimpScanner *scanner,
- gint *dest)
- {
- gboolean negate = FALSE;
- if (g_scanner_peek_next_token (scanner) == '-')
- {
- negate = TRUE;
- g_scanner_get_next_token (scanner);
- }
- if (g_scanner_peek_next_token (scanner) != G_TOKEN_INT)
- return FALSE;
- g_scanner_get_next_token (scanner);
- if (negate)
- *dest = -scanner->value.v_int64;
- else
- *dest = scanner->value.v_int64;
- return TRUE;
- }
- /**
- * gimp_scanner_parse_int64:
- * @scanner: A #GimpScanner created by gimp_scanner_new_file() or
- * gimp_scanner_new_string()
- * @dest: (out): Return location for the parsed integer
- *
- * Returns: %TRUE on success
- *
- * Since: 2.8
- **/
- gboolean
- gimp_scanner_parse_int64 (GimpScanner *scanner,
- gint64 *dest)
- {
- gboolean negate = FALSE;
- if (g_scanner_peek_next_token (scanner) == '-')
- {
- negate = TRUE;
- g_scanner_get_next_token (scanner);
- }
- if (g_scanner_peek_next_token (scanner) != G_TOKEN_INT)
- return FALSE;
- g_scanner_get_next_token (scanner);
- if (negate)
- *dest = -scanner->value.v_int64;
- else
- *dest = scanner->value.v_int64;
- return TRUE;
- }
- /**
- * gimp_scanner_parse_float:
- * @scanner: A #GimpScanner created by gimp_scanner_new_file() or
- * gimp_scanner_new_string()
- * @dest: (out): Return location for the parsed float
- *
- * Returns: %TRUE on success
- *
- * Since: 2.4
- **/
- gboolean
- gimp_scanner_parse_float (GimpScanner *scanner,
- gdouble *dest)
- {
- gboolean negate = FALSE;
- if (g_scanner_peek_next_token (scanner) == '-')
- {
- negate = TRUE;
- g_scanner_get_next_token (scanner);
- }
- if (g_scanner_peek_next_token (scanner) == G_TOKEN_FLOAT)
- {
- g_scanner_get_next_token (scanner);
- if (negate)
- *dest = -scanner->value.v_float;
- else
- *dest = scanner->value.v_float;
- return TRUE;
- }
- else if (g_scanner_peek_next_token (scanner) == G_TOKEN_INT)
- {
- /* v_int is unsigned so we need to cast to
- *
- * gint64 first for negative values.
- */
- g_scanner_get_next_token (scanner);
- if (negate)
- *dest = - (gint64) scanner->value.v_int;
- else
- *dest = scanner->value.v_int;
- return TRUE;
- }
- return FALSE;
- }
- /**
- * gimp_scanner_parse_boolean:
- * @scanner: A #GimpScanner created by gimp_scanner_new_file() or
- * gimp_scanner_new_string()
- * @dest: (out): Return location for the parsed boolean
- *
- * Returns: %TRUE on success
- *
- * Since: 2.4
- **/
- gboolean
- gimp_scanner_parse_boolean (GimpScanner *scanner,
- gboolean *dest)
- {
- if (g_scanner_peek_next_token (scanner) != G_TOKEN_IDENTIFIER)
- return FALSE;
- g_scanner_get_next_token (scanner);
- if (! g_ascii_strcasecmp (scanner->value.v_identifier, "yes") ||
- ! g_ascii_strcasecmp (scanner->value.v_identifier, "true"))
- {
- *dest = TRUE;
- }
- else if (! g_ascii_strcasecmp (scanner->value.v_identifier, "no") ||
- ! g_ascii_strcasecmp (scanner->value.v_identifier, "false"))
- {
- *dest = FALSE;
- }
- else
- {
- g_scanner_error
- (scanner,
- /* please don't translate 'yes' and 'no' */
- _("expected 'yes' or 'no' for boolean token, got '%s'"),
- scanner->value.v_identifier);
- return FALSE;
- }
- return TRUE;
- }
- enum
- {
- COLOR_RGB = 1,
- COLOR_RGBA,
- COLOR_HSV,
- COLOR_HSVA,
- COLOR
- };
- /**
- * gimp_scanner_parse_color:
- * @scanner: A #GimpScanner created by gimp_scanner_new_file() or
- * gimp_scanner_new_string()
- * @color: (out callee-allocates): Pointer to a color to store the result
- *
- * Returns: %TRUE on success
- *
- * Since: 2.4
- **/
- gboolean
- gimp_scanner_parse_color (GimpScanner *scanner,
- GeglColor **color)
- {
- guint scope_id;
- guint old_scope_id;
- GTokenType token;
- gboolean success = TRUE;
- scope_id = g_quark_from_static_string ("gimp_scanner_parse_color");
- old_scope_id = g_scanner_set_scope (scanner, scope_id);
- if (! g_scanner_scope_lookup_symbol (scanner, scope_id, "color"))
- {
- g_scanner_scope_add_symbol (scanner, scope_id,
- "color", GINT_TO_POINTER (COLOR));
- /* Deprecated. Kept for backward compatibility. */
- g_scanner_scope_add_symbol (scanner, scope_id,
- "color-rgb", GINT_TO_POINTER (COLOR_RGB));
- g_scanner_scope_add_symbol (scanner, scope_id,
- "color-rgba", GINT_TO_POINTER (COLOR_RGBA));
- g_scanner_scope_add_symbol (scanner, scope_id,
- "color-hsv", GINT_TO_POINTER (COLOR_HSV));
- g_scanner_scope_add_symbol (scanner, scope_id,
- "color-hsva", GINT_TO_POINTER (COLOR_HSVA));
- }
- token = g_scanner_peek_next_token (scanner);
- if (token == G_TOKEN_IDENTIFIER)
- {
- g_scanner_get_next_token (scanner);
- if (g_ascii_strcasecmp (scanner->value.v_identifier, "null") != 0)
- /* Do not fail the whole color parsing. Just output to stderr and assume
- * a NULL color property.
- */
- g_printerr ("%s: expected NULL identifier for serialized color, got '%s'. "
- "Assuming NULL instead.\n",
- G_STRFUNC, scanner->value.v_identifier);
- *color = NULL;
- token = g_scanner_peek_next_token (scanner);
- if (token == G_TOKEN_RIGHT_PAREN)
- token = G_TOKEN_NONE;
- else
- token = G_TOKEN_RIGHT_PAREN;
- }
- else if (token == G_TOKEN_LEFT_PAREN)
- {
- g_scanner_get_next_token (scanner);
- token = g_scanner_peek_next_token (scanner);
- if (token == G_TOKEN_SYMBOL)
- {
- if (GPOINTER_TO_INT (scanner->next_value.v_symbol) != COLOR)
- {
- /* Support historical GimpRGB format which may be stored in various config
- * files, but even some data (such as GTP tool presets which contains
- * tool-options which are GimpContext).
- */
- if (gimp_scanner_parse_deprecated_color (scanner, color))
- token = G_TOKEN_RIGHT_PAREN;
- else
- success = FALSE;
- }
- else
- {
- const Babl *format;
- gchar *encoding;
- guint8 *data;
- gint data_length;
- gint profile_data_length;
- g_scanner_get_next_token (scanner);
- if (! gimp_scanner_parse_string (scanner, &encoding))
- {
- token = G_TOKEN_STRING;
- goto color_parsed;
- }
- if (! babl_format_exists (encoding))
- {
- g_scanner_error (scanner,
- "%s: format \"%s\" for serialized color is not a valid babl format.",
- G_STRFUNC, encoding);
- g_free (encoding);
- success = FALSE;
- goto color_parsed;
- }
- format = babl_format (encoding);
- g_free (encoding);
- if (! gimp_scanner_parse_int (scanner, &data_length))
- {
- token = G_TOKEN_INT;
- goto color_parsed;
- }
- if (data_length != babl_format_get_bytes_per_pixel (format))
- {
- g_scanner_error (scanner,
- "%s: format \"%s\" expects %d bpp but color was serialized with %d bpp.",
- G_STRFUNC, babl_get_name (format),
- babl_format_get_bytes_per_pixel (format),
- data_length);
- success = FALSE;
- goto color_parsed;
- }
- if (! gimp_scanner_parse_data (scanner, data_length, &data))
- {
- token = G_TOKEN_STRING;
- goto color_parsed;
- }
- if (! gimp_scanner_parse_int (scanner, &profile_data_length))
- {
- g_free (data);
- token = G_TOKEN_INT;
- goto color_parsed;
- }
- if (profile_data_length > 0)
- {
- const Babl *space = NULL;
- GimpColorProfile *profile;
- guint8 *profile_data;
- GError *error = NULL;
- if (! gimp_scanner_parse_data (scanner, profile_data_length, &profile_data))
- {
- g_free (data);
- token = G_TOKEN_STRING;
- goto color_parsed;
- }
- profile = gimp_color_profile_new_from_icc_profile (profile_data, profile_data_length, &error);
- if (profile)
- {
- space = gimp_color_profile_get_space (profile,
- GIMP_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC,
- &error);
- if (! space)
- {
- g_scanner_error (scanner,
- "%s: failed to create Babl space for serialized color from profile: %s\n",
- G_STRFUNC, error->message);
- g_clear_error (&error);
- }
- g_object_unref (profile);
- }
- else
- {
- g_scanner_error (scanner,
- "%s: invalid profile data for serialized color: %s",
- G_STRFUNC, error->message);
- g_error_free (error);
- }
- format = babl_format_with_space (babl_format_get_encoding (format), space);
- g_free (profile_data);
- }
- *color = gegl_color_new (NULL);
- gegl_color_set_pixel (*color, format, data);
- token = G_TOKEN_RIGHT_PAREN;
- g_free (data);
- }
- }
- else
- {
- token = G_TOKEN_SYMBOL;
- }
- if (success && token == G_TOKEN_RIGHT_PAREN)
- {
- token = g_scanner_peek_next_token (scanner);
- if (token == G_TOKEN_RIGHT_PAREN)
- {
- g_scanner_get_next_token (scanner);
- token = G_TOKEN_NONE;
- }
- else
- {
- g_clear_object (color);
- token = G_TOKEN_RIGHT_PAREN;
- }
- }
- }
- else
- {
- token = G_TOKEN_LEFT_PAREN;
- }
- color_parsed:
- if (success && token != G_TOKEN_NONE)
- {
- g_scanner_get_next_token (scanner);
- g_scanner_unexp_token (scanner, token, NULL, NULL, NULL,
- _("fatal parse error"), TRUE);
- }
- g_scanner_set_scope (scanner, old_scope_id);
- return (success && token == G_TOKEN_NONE);
- }
- /**
- * gimp_scanner_parse_matrix2:
- * @scanner: A #GimpScanner created by gimp_scanner_new_file() or
- * gimp_scanner_new_string()
- * @dest: (out caller-allocates): Pointer to a matrix to store the result
- *
- * Returns: %TRUE on success
- *
- * Since: 2.4
- **/
- gboolean
- gimp_scanner_parse_matrix2 (GimpScanner *scanner,
- GimpMatrix2 *dest)
- {
- guint scope_id;
- guint old_scope_id;
- GTokenType token;
- GimpMatrix2 matrix;
- scope_id = g_quark_from_static_string ("gimp_scanner_parse_matrix");
- old_scope_id = g_scanner_set_scope (scanner, scope_id);
- if (! g_scanner_scope_lookup_symbol (scanner, scope_id, "matrix"))
- g_scanner_scope_add_symbol (scanner, scope_id,
- "matrix", GINT_TO_POINTER (0));
- token = G_TOKEN_LEFT_PAREN;
- while (g_scanner_peek_next_token (scanner) == token)
- {
- token = g_scanner_get_next_token (scanner);
- switch (token)
- {
- case G_TOKEN_LEFT_PAREN:
- token = G_TOKEN_SYMBOL;
- break;
- case G_TOKEN_SYMBOL:
- {
- token = G_TOKEN_FLOAT;
- if (! gimp_scanner_parse_float (scanner, &matrix.coeff[0][0]))
- goto finish;
- if (! gimp_scanner_parse_float (scanner, &matrix.coeff[0][1]))
- goto finish;
- if (! gimp_scanner_parse_float (scanner, &matrix.coeff[1][0]))
- goto finish;
- if (! gimp_scanner_parse_float (scanner, &matrix.coeff[1][1]))
- goto finish;
- token = G_TOKEN_RIGHT_PAREN;
- }
- break;
- case G_TOKEN_RIGHT_PAREN:
- token = G_TOKEN_NONE; /* indicates success */
- goto finish;
- default: /* do nothing */
- break;
- }
- }
- finish:
- if (token != G_TOKEN_NONE)
- {
- g_scanner_get_next_token (scanner);
- g_scanner_unexp_token (scanner, token, NULL, NULL, NULL,
- _("fatal parse error"), TRUE);
- }
- else
- {
- *dest = matrix;
- }
- g_scanner_set_scope (scanner, old_scope_id);
- return (token == G_TOKEN_NONE);
- }
- /* private functions */
- static void
- gimp_scanner_message (GimpScanner *scanner,
- gchar *message,
- gboolean is_error)
- {
- GimpScannerData *data = scanner->user_data;
- /* we don't expect warnings */
- g_return_if_fail (is_error);
- if (data->name)
- g_set_error (data->error, GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_PARSE,
- _("Error while parsing '%s' in line %d: %s"),
- data->name, scanner->line, message);
- else
- /* should never happen, thus not marked for translation */
- g_set_error (data->error, GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_PARSE,
- "Error parsing internal buffer: %s", message);
- }
- static GTokenType
- gimp_scanner_parse_deprecated_color (GimpScanner *scanner,
- GeglColor **color)
- {
- guint scope_id;
- guint old_scope_id;
- GTokenType token;
- scope_id = g_quark_from_static_string ("gimp_scanner_parse_deprecated_color");
- old_scope_id = g_scanner_set_scope (scanner, scope_id);
- if (! g_scanner_scope_lookup_symbol (scanner, scope_id, "color-rgb"))
- {
- g_scanner_scope_add_symbol (scanner, scope_id,
- "color-rgb", GINT_TO_POINTER (COLOR_RGB));
- g_scanner_scope_add_symbol (scanner, scope_id,
- "color-rgba", GINT_TO_POINTER (COLOR_RGBA));
- g_scanner_scope_add_symbol (scanner, scope_id,
- "color-hsv", GINT_TO_POINTER (COLOR_HSV));
- g_scanner_scope_add_symbol (scanner, scope_id,
- "color-hsva", GINT_TO_POINTER (COLOR_HSVA));
- }
- token = G_TOKEN_SYMBOL;
- while (g_scanner_peek_next_token (scanner) == token)
- {
- token = g_scanner_get_next_token (scanner);
- switch (token)
- {
- case G_TOKEN_SYMBOL:
- {
- gdouble col[4] = { 0.0, 0.0, 0.0, 1.0 };
- gdouble col_f[4] = { 0.0, 0.0, 0.0, 1.0 };
- gint n_channels = 4;
- gboolean is_hsv = FALSE;
- gint i;
- switch (GPOINTER_TO_INT (scanner->value.v_symbol))
- {
- case COLOR_RGB:
- n_channels = 3;
- /* fallthrough */
- case COLOR_RGBA:
- break;
- case COLOR_HSV:
- n_channels = 3;
- /* fallthrough */
- case COLOR_HSVA:
- is_hsv = TRUE;
- break;
- }
- token = G_TOKEN_FLOAT;
- for (i = 0; i < n_channels; i++)
- {
- if (! gimp_scanner_parse_float (scanner, &col[i]))
- goto finish;
- col_f[i] = (gfloat) col[i];
- }
- *color = gegl_color_new (NULL);
- if (is_hsv)
- gegl_color_set_pixel (*color, babl_format ("HSVA float"), col_f);
- else
- gegl_color_set_pixel (*color, babl_format ("R'G'B'A double"), col);
- /* Indicates success. */
- token = G_TOKEN_NONE;
- }
- break;
- default: /* do nothing */
- break;
- }
- }
- finish:
- g_scanner_set_scope (scanner, old_scope_id);
- return token;
- }
|