+
+static void parse_style(gchar *tex, RrSurfaceColorType *grad,
+ RrReliefType *relief, RrBevelType *bevel,
+ gboolean *interlaced, gboolean *border,
+ gboolean allow_trans)
+{
+ gchar *t;
+
+ /* convert to all lowercase */
+ for (t = tex; *t != '\0'; ++t)
+ *t = g_ascii_tolower(*t);
+
+ if (allow_trans && strstr(tex, "parentrelative") != NULL) {
+ *grad = RR_SURFACE_PARENTREL;
+ } else {
+ if (strstr(tex, "gradient") != NULL) {
+ if (strstr(tex, "crossdiagonal") != NULL)
+ *grad = RR_SURFACE_CROSS_DIAGONAL;
+ else if (strstr(tex, "pyramid") != NULL)
+ *grad = RR_SURFACE_PYRAMID;
+ else if (strstr(tex, "mirrorhorizontal") != NULL)
+ *grad = RR_SURFACE_MIRROR_HORIZONTAL;
+ else if (strstr(tex, "horizontal") != NULL)
+ *grad = RR_SURFACE_HORIZONTAL;
+ else if (strstr(tex, "splitvertical") != NULL)
+ *grad = RR_SURFACE_SPLIT_VERTICAL;
+ else if (strstr(tex, "vertical") != NULL)
+ *grad = RR_SURFACE_VERTICAL;
+ else
+ *grad = RR_SURFACE_DIAGONAL;
+ } else {
+ *grad = RR_SURFACE_SOLID;
+ }
+
+ if (strstr(tex, "sunken") != NULL)
+ *relief = RR_RELIEF_SUNKEN;
+ else if (strstr(tex, "flat") != NULL)
+ *relief = RR_RELIEF_FLAT;
+ else
+ *relief = RR_RELIEF_RAISED;
+
+ *border = FALSE;
+ if (*relief == RR_RELIEF_FLAT) {
+ if (strstr(tex, "border") != NULL)
+ *border = TRUE;
+ } else {
+ if (strstr(tex, "bevel2") != NULL)
+ *bevel = RR_BEVEL_2;
+ else
+ *bevel = RR_BEVEL_1;
+ }
+
+ if (strstr(tex, "interlaced") != NULL)
+ *interlaced = TRUE;
+ else
+ *interlaced = FALSE;
+ }
+}
+
+static xmlNodePtr find_node(xmlNodePtr n, const gchar *names[])
+{
+ gint i;
+
+ for (i = 0; names[i] && n; ++i)
+ n = parse_find_node(names[i], n->children);
+ return n;
+}
+
+static gboolean find_int(ParseState *ps, xmlNodePtr n, const gchar *names[],
+ gint *integer, gint lower, gint upper)
+{
+ gint i;
+
+ if ((n = find_node(n, names))) {
+ i = parse_int(ps->doc, n);
+ if (i >= lower && i <= upper) {
+ *integer = i;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static gboolean find_string(ParseState *ps, xmlNodePtr n, const gchar *names[],
+ const gchar **string)
+{
+ if ((n = find_node(n, names))) {
+ *string = parse_string(ps->doc, n);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean find_color(ParseState *ps, xmlNodePtr n, const gchar *names[],
+ RrColor **color, gchar *alpha)
+{
+ if ((n = find_node(n, names))) {
+ int r,g,b,a;
+ if (parse_attr_int("r", n, &r) &&
+ parse_attr_int("g", n, &g) &&
+ parse_attr_int("b", n, &b) &&
+ parse_attr_int("a", n, &a) &&
+ r >= 0 && g >= 0 && b >= 0 && a >= 0 &&
+ r < 256 && g < 256 && b < 256 && a < 256)
+ {
+ *color = RrColorNew(ps->inst, r, g, b);
+ if (alpha) *alpha = a;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static gboolean find_point(ParseState *ps, xmlNodePtr n, const gchar *names[],
+ gint *x, gint *y,
+ gint lowx, gint upx, gint lowy, gint upy)
+{
+ if ((n = find_node(n, names))) {
+ gint a, b;
+ if (parse_attr_int("x", n, &a) &&
+ parse_attr_int("y", n, &b) &&
+ a >= lowx && a <= upx && b >= lowy && b <= upy)
+ {
+ *x = a; *y = b;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static gboolean find_shadow(ParseState *ps, xmlNodePtr n, const gchar *names[],
+ RrAppearance *a)
+{
+ return find_point(ps, n, names,
+ &a->texture[0].data.text.shadow_offset_x,
+ &a->texture[0].data.text.shadow_offset_y,
+ -20, 20, -20, 20);
+}
+
+static gboolean find_appearance(ParseState *ps, xmlNodePtr n, const gchar *names[],
+ RrAppearance *a, gboolean allow_trans)
+{
+ xmlNodePtr n2;
+
+ if (!(n = find_node(n, names)))
+ return FALSE;
+
+ if ((n2 = find_node(n, L("style")))) {
+ gchar *s = parse_string(ps->doc, n2);
+ parse_style(s, &a->surface.grad, &a->surface.relief,
+ &a->surface.bevel, &a->surface.interlaced,
+ &a->surface.border, allow_trans);
+ g_free(s);
+ } else
+ return FALSE;
+
+ if (!find_color(ps, n, L("primary"), &a->surface.primary, NULL))
+ a->surface.primary = RrColorNew(ps->inst, 0, 0, 0);
+ if (!find_color(ps, n, L("secondary"), &a->surface.secondary, NULL))
+ a->surface.secondary = RrColorNew(ps->inst, 0, 0, 0);
+ if (a->surface.border)
+ if (!find_color(ps, n, L("border"),
+ &a->surface.border_color, NULL))
+ a->surface.border_color = RrColorNew(ps->inst, 0, 0, 0);
+ if (a->surface.interlaced)
+ if (!find_color(ps, n, L("interlace"),
+ &a->surface.interlace_color, NULL))
+ a->surface.interlace_color = RrColorNew(ps->inst, 0, 0, 0);
+
+ return TRUE;
+}