Lines
56.16 %
Functions
67.16 %
Branches
29.19 %
/* ipuz-style.c
*
* Copyright 2022 Jonathan Blandford <jrb@gnome.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 2.1 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
* Lesser 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* SPDX-License-Identifier: (LGPL-2.1-or-later OR MIT)
*/
#include "libipuz-config.h"
#include "ipuz-style.h"
#include <glib/gi18n-lib.h>
struct _IPuzStyle
{
grefcount ref_count;
gchar *style_name; /* Internal name of the style, for shared styles */
IPuzStyleShape shapebg;
gboolean highlight;
gchar *named;
gint border;
IPuzStyleDivided divided;
gchar *label;
GHashTable *mark; /* Hashtable of strings indexed by IPUZ_STYLE_MARK_ */
gchar *image_url;
gchar *imagebg_url;
gchar *bg_color;
gchar *text_color;
gchar *border_color;
IPuzStyleSides barred;
IPuzStyleSides dotted;
IPuzStyleSides dashed;
IPuzStyleSides lessthan;
IPuzStyleSides greaterthan;
IPuzStyleSides equal;
};
G_DEFINE_BOXED_TYPE (IPuzStyle, ipuz_style, ipuz_style_ref, ipuz_style_unref);
static IPuzStyleShape parse_shapebg (const char *shapebg);
static IPuzStyleSides parse_sides (const char *val);
static char *sides_to_str (IPuzStyleSides sides);
static const char *shapebg_to_str (IPuzStyleShape shapebg);
static char *parse_color (JsonNode *node);
static void ipuz_style_parse_mark (IPuzStyle *style,
JsonNode *node);
IPuzStyle *
ipuz_style_new (void)
IPuzStyle *style;
style = (IPuzStyle *) g_new0 (IPuzStyle, 1);
g_ref_count_init (&style->ref_count);
return style;
}
static IPuzStyleSides
sides_from_json (JsonObject *obj, const char *prop_name)
JsonNode *element = json_object_get_member (obj, prop_name);
if (element)
const gchar *val = json_node_get_string (element);
return parse_sides (val);
else
return 0;
ipuz_style_new_from_json (JsonNode *node)
g_return_val_if_fail (node != NULL, NULL);
style = ipuz_style_new ();
if (JSON_NODE_HOLDS_OBJECT (node))
JsonObject *obj;
JsonNode *element;
obj = json_node_get_object (node);
element = json_object_get_member (obj, "shapebg");
const gchar *shapebg = json_node_get_string (element);
style->shapebg = parse_shapebg (shapebg);
element = json_object_get_member (obj, "highlight");
style->highlight = json_node_get_boolean (element);
element = json_object_get_member (obj, "named");
style->named = g_strdup (json_node_get_string (element));
element = json_object_get_member (obj, "border");
style->border = json_node_get_int (element);
element = json_object_get_member (obj, "divided");
const gchar *divided = json_node_get_string (element);
if (g_strcmp0 (divided, "-") == 0)
style->divided = IPUZ_STYLE_DIVIDED_HORIZ;
else if (g_strcmp0 (divided, "|") == 0)
style->divided = IPUZ_STYLE_DIVIDED_VERT;
else if (g_strcmp0 (divided, "/") == 0)
style->divided = IPUZ_STYLE_DIVIDED_UP_RIGHT;
else if (g_strcmp0 (divided, "\\") == 0)
style->divided = IPUZ_STYLE_DIVIDED_UP_LEFT;
else if (g_strcmp0 (divided, "+") == 0)
style->divided = IPUZ_STYLE_DIVIDED_PLUS;
else if (g_strcmp0 (divided, "x") == 0)
style->divided = IPUZ_STYLE_DIVIDED_CROSS;
style->divided = IPUZ_STYLE_DIVIDED_NONE;
element = json_object_get_member (obj, "label");
style->label = g_strdup (json_node_get_string (element));
element = json_object_get_member (obj, "mark");
ipuz_style_parse_mark (style, element);
element = json_object_get_member (obj, "image");
style->image_url = g_strdup (json_node_get_string (element));
element = json_object_get_member (obj, "imagebg");
style->imagebg_url = g_strdup (json_node_get_string (element));
element = json_object_get_member (obj, "color");
style->bg_color = parse_color (element);
element = json_object_get_member (obj, "colortext");
style->text_color = parse_color (element);
element = json_object_get_member (obj, "colorborder");
style->border_color = parse_color (element);
style->barred = sides_from_json (obj, "barred");
style->dotted = sides_from_json (obj, "dotted");
style->dashed = sides_from_json (obj, "dashed");
style->lessthan = sides_from_json (obj, "lessthan");
style->greaterthan = sides_from_json (obj, "greaterthan");
style->equal = sides_from_json (obj, "equal");
ipuz_style_ref (IPuzStyle *style)
g_return_val_if_fail (style != NULL, NULL);
g_ref_count_inc (&style->ref_count);
void
ipuz_style_unref (IPuzStyle *style)
if (style == NULL)
return;
if (!g_ref_count_dec (&style->ref_count))
/* Free */
if (style->mark)
g_hash_table_unref (style->mark);
g_free (style->style_name);
g_free (style->named);
g_free (style->label);
g_free (style->image_url);
g_free (style->imagebg_url);
g_free (style->bg_color);
g_free (style->text_color);
g_free (style->border_color);
g_free (style);
gboolean
ipuz_style_equal (IPuzStyle *a,
IPuzStyle *b)
if (a->mark)
GHashTableIter iter;
gpointer key, value;
if (b->mark == NULL)
return FALSE;
g_hash_table_iter_init (&iter, a->mark);
while (g_hash_table_iter_next (&iter, &key, &value))
if (g_strcmp0 (g_hash_table_lookup (b->mark, key), value) != 0)
else if (b->mark)
return (!g_strcmp0 (a->style_name, b->style_name)
&& a->shapebg == b->shapebg
&& a->highlight == b->highlight
&& !g_strcmp0 (a->named, b->named)
&& a->border == b->border
&& a->divided == b->divided
&& !g_strcmp0 (a->label, b->label)
&& !g_strcmp0 (a->image_url, b->image_url)
&& !g_strcmp0 (a->imagebg_url, b->imagebg_url)
&& !g_strcmp0 (a->bg_color, b->bg_color)
&& !g_strcmp0 (a->text_color, b->text_color)
&& !g_strcmp0 (a->border_color, b->border_color)
&& a->barred == b->barred
&& a->dotted == b->dotted
&& a->dashed == b->dashed
&& a->lessthan == b->lessthan
&& a->greaterthan == b->greaterthan
&& a->equal == b->equal);
static void
mark_copy_func (gpointer key,
const char *mark_label,
GHashTable *dest_marks)
g_hash_table_insert (dest_marks, key, g_strdup (mark_label));
ipuz_style_copy (IPuzStyle *style)
IPuzStyle *new_style;
return NULL;
new_style = ipuz_style_new ();
new_style->style_name = g_strdup (style->style_name);
new_style->named = g_strdup (style->named);
new_style->border = style->border;
new_style->shapebg = style->shapebg;
new_style->highlight = style->highlight;
new_style->divided = style->divided;
new_style->mark = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) g_free);
g_hash_table_foreach (style->mark, (GHFunc) mark_copy_func, new_style->mark);
new_style->label = g_strdup (style->label);
new_style->image_url = g_strdup (style->image_url);
new_style->imagebg_url = g_strdup (style->imagebg_url);
new_style->bg_color = g_strdup (style->bg_color);
new_style->text_color = g_strdup (style->text_color);
new_style->border_color = g_strdup (style->border_color);
new_style->barred = style->barred;
new_style->dotted = style->dotted;
new_style->dashed = style->dashed;
new_style->lessthan = style->lessthan;
new_style->greaterthan = style->greaterthan;
new_style->equal = style->equal;
return new_style;
/**
* ipuz_style_is_empty:
* @style: An `IPuzStyle`
* Returns #true if style doesn't have anything set, and makes no
* changes to the rendering of a cell it's associated with.
* Returns: #true if @style is empty
**/
ipuz_style_is_empty (IPuzStyle *style)
g_return_val_if_fail (style != NULL, TRUE);
return ((style->style_name == NULL)
&& (style->named == NULL)
&& (style->shapebg == IPUZ_STYLE_SHAPE_NONE)
&& (! style->highlight)
&& (style->border == 0)
&& (style->divided == IPUZ_STYLE_DIVIDED_NONE)
&& (style->label == NULL)
&& (style->mark == NULL)
&& (style->image_url == NULL)
&& (style->imagebg_url == NULL)
&& (style->bg_color == NULL)
&& (style->text_color == NULL)
&& (style->border_color == NULL)
&& (style->barred == 0)
&& (style->dotted == 0)
&& (style->dashed == 0)
&& (style->lessthan == 0)
&& (style->greaterthan == 0)
&& (style->equal == 0));
/* Internal function used by ipuz-barred.c */
_ipuz_style_is_empty_except_bars (IPuzStyle *style)
&& (style->barred != 0) /* The one difference between this and ipuz_style_is_empty */
build_mark_foreach_cb (IPuzStyleMark mark,
const gchar *label,
gpointer user_data)
JsonBuilder *builder = JSON_BUILDER (user_data);
switch (mark)
case IPUZ_STYLE_MARK_TL:
json_builder_set_member_name (builder, "TL");
break;
case IPUZ_STYLE_MARK_T:
json_builder_set_member_name (builder, "T");
case IPUZ_STYLE_MARK_TR:
json_builder_set_member_name (builder, "TR");
case IPUZ_STYLE_MARK_L:
json_builder_set_member_name (builder, "L");
case IPUZ_STYLE_MARK_C:
json_builder_set_member_name (builder, "C");
case IPUZ_STYLE_MARK_R:
json_builder_set_member_name (builder, "R");
case IPUZ_STYLE_MARK_BL:
json_builder_set_member_name (builder, "BL");
case IPUZ_STYLE_MARK_B:
json_builder_set_member_name (builder, "B");
case IPUZ_STYLE_MARK_BR:
json_builder_set_member_name (builder, "BR");
default:
g_warning ("STYLE as a bitfield is not supported");
json_builder_add_string_value (builder, label);
sides_to_json (JsonBuilder *builder, const char *prop_name, IPuzStyleSides sides)
if (sides != 0)
char *val = sides_to_str (sides);
json_builder_set_member_name (builder, prop_name);
json_builder_add_string_value (builder, val);
g_free (val);
ipuz_style_build (IPuzStyle *style,
JsonBuilder *builder)
g_return_if_fail (style != NULL);
json_builder_begin_object (builder);
if (style->shapebg != IPUZ_STYLE_SHAPE_NONE)
json_builder_set_member_name (builder, "shapebg");
json_builder_add_string_value (builder, shapebg_to_str (style->shapebg));
/* FIXME(parse): add highlight_set, or an enum */
if (style->highlight)
json_builder_set_member_name (builder, "highlight");
json_builder_add_boolean_value (builder, style->highlight);
if (style->named)
json_builder_set_member_name (builder, "named");
json_builder_add_string_value (builder, style->named);
/* FIXME(build): border needs a border-set variable. 0 is a valid value */
if (style->border != 0)
json_builder_set_member_name (builder, "border");
json_builder_add_int_value (builder, style->border);
if (style->divided != IPUZ_STYLE_DIVIDED_NONE)
json_builder_set_member_name (builder, "divided");
switch (style->divided)
case IPUZ_STYLE_DIVIDED_HORIZ:
json_builder_add_string_value (builder, "-");
case IPUZ_STYLE_DIVIDED_VERT:
json_builder_add_string_value (builder, "|");
case IPUZ_STYLE_DIVIDED_UP_RIGHT:
json_builder_add_string_value (builder, "/");
case IPUZ_STYLE_DIVIDED_UP_LEFT:
json_builder_add_string_value (builder, "\\");
case IPUZ_STYLE_DIVIDED_PLUS:
json_builder_add_string_value (builder, "+");
case IPUZ_STYLE_DIVIDED_CROSS:
json_builder_add_string_value (builder, "X");
g_warning ("unknown divided style");
json_builder_add_string_value (builder, "?");
if (style->label)
json_builder_set_member_name (builder, "label");
json_builder_add_string_value (builder, style->label);
json_builder_set_member_name (builder, "mark");
ipuz_style_mark_foreach (style, build_mark_foreach_cb, builder);
json_builder_end_object (builder);
if (style->imagebg_url)
json_builder_set_member_name (builder, "imagebg");
json_builder_add_string_value (builder, style->imagebg_url);
if (style->image_url)
json_builder_add_string_value (builder, style->image_url);
if (style->bg_color)
json_builder_set_member_name (builder, "color");
json_builder_add_string_value (builder, style->bg_color);
if (style->text_color)
json_builder_set_member_name (builder, "colortext");
json_builder_add_string_value (builder, style->text_color);
if (style->border_color)
json_builder_set_member_name (builder, "colorborder");
json_builder_add_string_value (builder, style->border_color);
sides_to_json (builder, "barred", style->barred);
sides_to_json (builder, "dotted", style->dotted);
sides_to_json (builder, "dashed", style->dashed);
sides_to_json (builder, "lessthan", style->lessthan);
sides_to_json (builder, "greaterthan", style->greaterthan);
sides_to_json (builder, "equal", style->equal);
/* Getters and Setters */
const gchar *
ipuz_style_get_style_name (IPuzStyle *style)
return style->style_name;
ipuz_style_set_style_name (IPuzStyle *style,
const gchar *style_name)
g_clear_pointer (&style->style_name, g_free);
style->style_name = g_strdup (style_name);
ipuz_style_get_named (IPuzStyle *style)
return style->named;
ipuz_style_set_named (IPuzStyle *style,
const gchar *named)
g_clear_pointer (&style->named, g_free);
style->named = g_strdup (named);
gint
ipuz_style_get_border (IPuzStyle *style)
g_return_val_if_fail (style != NULL, 0);
return style->border;
ipuz_style_set_border (IPuzStyle *style,
gint border)
style->border = border;
IPuzStyleShape
ipuz_style_get_shapebg (IPuzStyle *style)
g_return_val_if_fail (style != NULL, IPUZ_STYLE_SHAPE_NONE);
return style->shapebg;
ipuz_style_set_shapebg (IPuzStyle *style,
IPuzStyleShape shapebg)
style->shapebg = shapebg;
ipuz_style_get_highlight (IPuzStyle *style)
g_return_val_if_fail (style != NULL, FALSE);
return style->highlight;
ipuz_style_set_highlight (IPuzStyle *style,
gboolean highlight)
style->highlight = !!highlight;
IPuzStyleDivided
ipuz_style_get_divided (IPuzStyle *style)
g_return_val_if_fail (style != NULL, IPUZ_STYLE_DIVIDED_NONE);
return style->divided;
ipuz_style_set_divided (IPuzStyle *style,
IPuzStyleDivided divided)
style->divided = divided;
typedef struct
IPuzMarkFunc *func;
gpointer user_data;
} ForeachTuple;
mark_foreach (gpointer key,
gpointer value,
ForeachTuple *tuple = (ForeachTuple *)user_data;
(*tuple->func) (GPOINTER_TO_INT (key), (const char *) value, tuple->user_data);
ipuz_style_mark_foreach (IPuzStyle *style,
IPuzMarkFunc func,
ForeachTuple tuple;
g_return_if_fail (func != NULL);
tuple.func = &func;
tuple.user_data = user_data;
g_hash_table_foreach (style->mark, mark_foreach, &tuple);
ipuz_style_get_label (IPuzStyle *style)
return style->label;
ipuz_style_set_label (IPuzStyle *style,
const gchar *label)
g_clear_pointer (&style->label, g_free);
style->label = g_strdup (label);
ipuz_style_get_image_url (IPuzStyle *style)
return style->image_url;
ipuz_style_set_image_url (IPuzStyle *style,
const gchar *image_url)
g_clear_pointer (&style->image_url, g_free);
style->image_url = g_strdup (image_url);
ipuz_style_get_imagebg_url (IPuzStyle *style)
return style->imagebg_url;
ipuz_style_set_imagebg_url (IPuzStyle *style,
const gchar *imagebg_url)
g_clear_pointer (&style->imagebg_url, g_free);
style->imagebg_url = g_strdup (imagebg_url);
ipuz_style_get_bg_color (IPuzStyle *style)
return style->bg_color;
ipuz_style_set_bg_color (IPuzStyle *style,
const gchar *bg_color)
g_clear_pointer (&style->bg_color, g_free);
style->bg_color = g_strdup (bg_color);
ipuz_style_get_text_color (IPuzStyle *style)
return style->text_color;
ipuz_style_set_text_color (IPuzStyle *style,
const gchar *text_color)
g_clear_pointer (&style->text_color, g_free);
style->text_color = g_strdup (text_color);
ipuz_style_get_border_color (IPuzStyle *style)
return style->border_color;
ipuz_style_set_border_color (IPuzStyle *style,
const gchar *border_color)
g_clear_pointer (&style->border_color, g_free);
style->border_color = g_strdup (border_color);
IPuzStyleSides
ipuz_style_get_barred (IPuzStyle *style)
return style->barred;
ipuz_style_set_barred (IPuzStyle *style,
IPuzStyleSides barred)
style->barred = barred;
ipuz_style_get_dotted (IPuzStyle *style)
return style->dotted;
ipuz_style_set_dotted (IPuzStyle *style,
IPuzStyleSides dotted)
style->dotted = dotted;
ipuz_style_get_dashed (IPuzStyle *style)
return style->dashed;
ipuz_style_set_dashed (IPuzStyle *style,
IPuzStyleSides dashed)
style->dashed = dashed;
ipuz_style_get_lessthan (IPuzStyle *style)
return style->lessthan;
ipuz_style_set_lessthan (IPuzStyle *style,
IPuzStyleSides lessthan)
style->lessthan = lessthan;
ipuz_style_get_greaterthan (IPuzStyle *style)
return style->greaterthan;
ipuz_style_set_greaterthan (IPuzStyle *style,
IPuzStyleSides greaterthan)
style->greaterthan = greaterthan;
ipuz_style_get_equal (IPuzStyle *style)
return style->equal;
ipuz_style_set_equal (IPuzStyle *style,
IPuzStyleSides equal)
style->equal = equal;
static char *
parse_color (JsonNode *node)
GValue value = G_VALUE_INIT;
gchar *retval = NULL;
json_node_get_value (node, &value);
if (G_VALUE_HOLDS_STRING (&value))
retval = g_value_dup_string (&value);
else if (G_VALUE_HOLDS_INT (&value) || G_VALUE_HOLDS_INT64 (&value))
int number = json_node_get_int (node);
/* FIXME: pick a pallet */
if (number == 0)
retval = g_strdup ("black");
retval = NULL;
g_value_unset (&value);
return retval;
ipuz_style_parse_mark (IPuzStyle *style,
JsonNode *node)
if (style->mark == NULL)
style->mark = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) g_free);
const gchar *mark;
element = json_object_get_member (obj, "TL");
mark = json_node_get_string (element);
g_hash_table_insert (style->mark,
GINT_TO_POINTER (IPUZ_STYLE_MARK_TL),
g_strdup (mark));
element = json_object_get_member (obj, "T");
GINT_TO_POINTER (IPUZ_STYLE_MARK_T),
element = json_object_get_member (obj, "TR");
GINT_TO_POINTER (IPUZ_STYLE_MARK_TR),
element = json_object_get_member (obj, "L");
GINT_TO_POINTER (IPUZ_STYLE_MARK_L),
element = json_object_get_member (obj, "C");
GINT_TO_POINTER (IPUZ_STYLE_MARK_C),
element = json_object_get_member (obj, "R");
GINT_TO_POINTER (IPUZ_STYLE_MARK_R),
element = json_object_get_member (obj, "BL");
GINT_TO_POINTER (IPUZ_STYLE_MARK_BL),
element = json_object_get_member (obj, "B");
GINT_TO_POINTER (IPUZ_STYLE_MARK_B),
element = json_object_get_member (obj, "BR");
GINT_TO_POINTER (IPUZ_STYLE_MARK_BR),
/* Make sure we actually added something */
if (g_hash_table_size (style->mark) == 0)
style->mark = NULL;
struct shapebg_name {
const char *shapebg;
const char *display_name;
IPuzStyleShape value;
static const struct shapebg_name shapebg_names[] = {
{ "none", N_("None"), IPUZ_STYLE_SHAPE_NONE },
{ "circle", N_("Circle"), IPUZ_STYLE_SHAPE_CIRCLE },
{ "arrow-left", N_("Left Arrow"), IPUZ_STYLE_SHAPE_ARROW_LEFT },
{ "arrow-right", N_("Right Arrow"), IPUZ_STYLE_SHAPE_ARROW_RIGHT },
{ "arrow-up", N_("Up Arrow"), IPUZ_STYLE_SHAPE_ARROW_UP },
{ "arrow-down", N_("Down Arrow"), IPUZ_STYLE_SHAPE_ARROW_DOWN },
{ "triangle-left", N_("Left Triangle"), IPUZ_STYLE_SHAPE_TRIANGLE_LEFT },
{ "triangle-right", N_("Right Triangle"), IPUZ_STYLE_SHAPE_TRIANGLE_RIGHT },
{ "triangle-up", N_("Up Triangle"), IPUZ_STYLE_SHAPE_TRIANGLE_UP },
{ "triangle-down", N_("Down Triangle"), IPUZ_STYLE_SHAPE_TRIANGLE_DOWN },
{ "diamond", N_("Diamond"), IPUZ_STYLE_SHAPE_DIAMOND },
{ "club", N_("Club"), IPUZ_STYLE_SHAPE_CLUB },
{ "heart", N_("Heart"), IPUZ_STYLE_SHAPE_HEART },
{ "spade", N_("Spade"), IPUZ_STYLE_SHAPE_SPADE },
{ "star", N_("Star"), IPUZ_STYLE_SHAPE_STAR },
{ "square", N_("Square"), IPUZ_STYLE_SHAPE_SQUARE },
{ "rhombus", N_("Rhombus"), IPUZ_STYLE_SHAPE_RHOMBUS },
{ "/", N_("Slash"), IPUZ_STYLE_SHAPE_SLASH },
{ "\\", N_("Backslash"), IPUZ_STYLE_SHAPE_BACKSLASH },
{ "X", N_("X"), IPUZ_STYLE_SHAPE_X },
static IPuzStyleShape
parse_shapebg (const char *shapebg)
guint i;
for (i = 0; i < G_N_ELEMENTS (shapebg_names); i++)
if (g_strcmp0 (shapebg, shapebg_names[i].shapebg) == 0)
return shapebg_names[i].value;
return IPUZ_STYLE_SHAPE_NONE;
static const char *
shapebg_to_str (IPuzStyleShape shapebg)
if (shapebg == shapebg_names[i].value)
return shapebg_names[i].shapebg;
g_assert_not_reached ();
parse_sides (const char *val)
IPuzStyleSides sides = 0;
const char *p;
for (p = val; *p; p++)
switch (*p) {
case 'T':
sides |= IPUZ_STYLE_SIDES_TOP;
case 'R':
sides |= IPUZ_STYLE_SIDES_RIGHT;
case 'B':
sides |= IPUZ_STYLE_SIDES_BOTTOM;
case 'L':
sides |= IPUZ_STYLE_SIDES_LEFT;
return sides;
sides_to_str (IPuzStyleSides sides)
char val[5] = { 0 };
gsize i = 0;
if (sides & IPUZ_STYLE_SIDES_TOP)
val[i] = 'T';
i++;
if (sides & IPUZ_STYLE_SIDES_RIGHT)
val[i] = 'R';
if (sides & IPUZ_STYLE_SIDES_BOTTOM)
val[i] = 'B';
if (sides & IPUZ_STYLE_SIDES_LEFT)
val[i] = 'L';
g_assert (i < G_N_ELEMENTS(val));
val[i] = 0;
return g_strdup (val);
/* Public functions */
ipuz_style_side_opposite (IPuzStyleSides side)
g_return_val_if_fail ((side == IPUZ_STYLE_SIDES_LEFT ||
side == IPUZ_STYLE_SIDES_RIGHT ||
side == IPUZ_STYLE_SIDES_TOP ||
side == IPUZ_STYLE_SIDES_BOTTOM), 0);
if (side == IPUZ_STYLE_SIDES_LEFT)
return IPUZ_STYLE_SIDES_RIGHT;
else if (side == IPUZ_STYLE_SIDES_RIGHT)
return IPUZ_STYLE_SIDES_LEFT;
else if (side == IPUZ_STYLE_SIDES_TOP)
return IPUZ_STYLE_SIDES_BOTTOM;
else if (side == IPUZ_STYLE_SIDES_BOTTOM)
return IPUZ_STYLE_SIDES_TOP;
static int
swap_bits (guint n,
guint p1,
guint p2)
if (((n & (1 << p1)) >> p1) ^ ((n & (1 << p2)) >> p2))
n ^= 1 << p1;
n ^= 1 << p2;
return n;
ipuz_style_sides_rotate_180 (IPuzStyleSides sides)
guint n = (guint) sides << 2;
n = swap_bits (n, 0, 4);
n = swap_bits (n, 1, 5);
ipuz_style_sides_rotate_rt (IPuzStyleSides sides)
guint n = (guint) sides;
return swap_bits (n << 1, 0, 4);
ipuz_style_sides_rotate_lt (IPuzStyleSides sides)
return (swap_bits (n, 0, 4)) >> 1;
ipuz_style_sides_flip_horiz (IPuzStyleSides sides)
return (swap_bits (n, 1, 3));
ipuz_style_sides_flip_vert (IPuzStyleSides sides)
return (swap_bits (n, 0, 2));
ipuz_style_shape_get_display_name (IPuzStyleShape shapebg)
g_return_val_if_fail (shapebg >= IPUZ_STYLE_SHAPE_NONE, NULL);
g_return_val_if_fail (shapebg <= IPUZ_STYLE_SHAPE_X, NULL);
return _(shapebg_names [shapebg].display_name);