[gnumeric] xlsx: apply colour modifiers when reading theme.



commit 280a4f768c8e953d12da392f49bc609d3377a883
Author: Morten Welinder <terra gnome org>
Date:   Tue Mar 31 21:50:39 2015 -0400

    xlsx: apply colour modifiers when reading theme.

 NEWS                              |    1 +
 plugins/excel/ChangeLog           |   10 +-
 plugins/excel/Makefile.am         |    1 +
 plugins/excel/xlsx-read-color.c   |  327 +++++++++++++++++++++++++++++++++++++
 plugins/excel/xlsx-read-drawing.c |  209 -----------------------
 plugins/excel/xlsx-read.c         |  145 ++++-------------
 6 files changed, 370 insertions(+), 323 deletions(-)
---
diff --git a/NEWS b/NEWS
index a89be5e..d5ffba2 100644
--- a/NEWS
+++ b/NEWS
@@ -22,6 +22,7 @@ Morten:
        * Fix RANDLOG.
        * Fix RANDGEOM to use same distribution as R.DGEOM.
        * Improve xlsx roundtrip of GOStyle.
+       * Improve reading of xlsx theme colours.
 
 --------------------------------------------------------------------------
 Gnumeric 1.12.21
diff --git a/plugins/excel/ChangeLog b/plugins/excel/ChangeLog
index d419312..18db0b4 100644
--- a/plugins/excel/ChangeLog
+++ b/plugins/excel/ChangeLog
@@ -1,3 +1,11 @@
+2015-03-31  Morten Welinder  <terra gnome org>
+
+       * xlsx-read-color.c: New file extracted from xlsx-read-drawing.c
+       and xlsx-read.c
+       (xlsx_draw_color_hsl_channel): Implement.
+
+       * xlsx-read.c (theme): Apply colour modifications.
+
 2015-03-30  Morten Welinder  <terra gnome org>
 
        * xlsx-read-drawing.c (xlsx_draw_color_rgba_channel): Rename from
@@ -187,7 +195,7 @@
        * xlsx-read-drawing.c (xlsx_chart_line_headtail): Improve arrow
        import with xls_arrow_from_xl.
 
-       * ms-excel-util.c (xls_arrow_from_xl): New function extrated...
+       * ms-excel-util.c (xls_arrow_from_xl): New function extracted...
        * ms-excel-read.c (handle_arrow_head): ...from here.
 
        * xlsx-write-drawing.c (xlsx_write_go_style_full): Improve arrow
diff --git a/plugins/excel/Makefile.am b/plugins/excel/Makefile.am
index aa41bc0..53229e3 100644
--- a/plugins/excel/Makefile.am
+++ b/plugins/excel/Makefile.am
@@ -83,6 +83,7 @@ EXTRA_DIST = $(xml_in_files)  \
        xlsx-write-docprops.c   \
        xlsx-read-pivot.c       \
        xlsx-write-pivot.c      \
+       xlsx-read-color.c       \
        xlsx-read-drawing.c     \
        xlsx-write-drawing.c
 
diff --git a/plugins/excel/xlsx-read-color.c b/plugins/excel/xlsx-read-color.c
new file mode 100644
index 0000000..7ac7a37
--- /dev/null
+++ b/plugins/excel/xlsx-read-color.c
@@ -0,0 +1,327 @@
+
+/* RGBMAX, HSLMAX must each fit in a byte. */
+/* HSLMAX BEST IF DIVISIBLE BY 6 */
+#define  HSLMAX   240 /* H,L, and S vary over 0-HSLMAX */
+#define  RGBMAX   255 /* R,G, and B vary over 0-RGBMAX */
+
+/* Hue is undefined if Saturation is 0 (grey-scale) */
+/* This value determines where the Hue scrollbar is */
+/* initially set for achromatic colors */
+//#define UNDEFINED (HSLMAX*2/3)
+
+/* utility routine for HSLtoRGB */
+static int
+hue_to_color (int m1, int m2, int h)
+{
+       if (h < 0)
+               h += HSLMAX;
+       if (h > HSLMAX)
+               h -= HSLMAX;
+
+       /* return r,g, or b value from this tridrant */
+       if (h < HSLMAX / 6)
+               return m1 + (((m2 - m1) * h + HSLMAX / 12) / (HSLMAX / 6));
+       if (h < HSLMAX / 2)
+               return m2;
+       if (h < HSLMAX * 2 /3)
+               return m1 + ((m2 - m1) * ((HSLMAX * 2 / 3 - h) + HSLMAX / 12) / (HSLMAX / 6));
+
+       return m1;
+}
+
+static GOColor
+gnm_go_color_from_hsla (int h, int s, int l, int a)
+{
+       int m2 = (l <= HSLMAX / 2)
+               ? (l * (HSLMAX + s) + HSLMAX / 2) / HSLMAX
+               : l + s - (l * s + HSLMAX / 2) / HSLMAX;
+       int m1 = 2 * l - m2;
+       guint8 r = (hue_to_color (m1, m2, h + HSLMAX / 3) * RGBMAX + HSLMAX / 2) / HSLMAX;
+       guint8 g = (hue_to_color (m1, m2, h             ) * RGBMAX + HSLMAX / 2) / HSLMAX;
+       guint8 b = (hue_to_color (m1, m2, h - HSLMAX / 3) * RGBMAX + HSLMAX / 2) / HSLMAX;
+
+       return GO_COLOR_FROM_RGBA (r,g,b,a);
+}
+
+static void
+gnm_go_color_to_hsla (GOColor orig, int *ph, int *ps, int *pl, int *pa)
+{
+       int r = GO_COLOR_UINT_R (orig);
+       int g = GO_COLOR_UINT_G (orig);
+       int b = GO_COLOR_UINT_B (orig);
+       int a = GO_COLOR_UINT_A (orig);
+       int maxC = b, minC = b, delta, sum, h = 0, l, s;
+
+       maxC = MAX (MAX (r,g),b);
+       minC = MIN (MIN (r,g),b);
+       l = (((maxC + minC)*HSLMAX) + RGBMAX)/(2*RGBMAX);
+
+       delta = maxC - minC;
+       sum   = maxC + minC;
+       if (delta != 0) {
+               if (l <= (HSLMAX/2))
+                       s = ( (delta*HSLMAX) + (sum/2) ) / sum;
+               else
+                       s = ( (delta*HSLMAX) + ((2*RGBMAX - sum)/2) ) / (2*RGBMAX - sum);
+
+               if (r == maxC)
+                       h =                ((g - b) * HSLMAX) / (6 * delta);
+               else if (g == maxC)
+                       h = (  HSLMAX/3) + ((b - r) * HSLMAX) / (6 * delta);
+               else if (b == maxC)
+                       h = (2*HSLMAX/3) + ((r - g) * HSLMAX) / (6 * delta);
+
+               if (h < 0)
+                       h += HSLMAX;
+               else if (h >= HSLMAX)
+                       h -= HSLMAX;
+       } else {
+               h = 0;
+               s = 0;
+       }
+
+       *ph = h;
+       *ps = s;
+       *pl = l;
+       *pa = a;
+}
+
+/*
+ * Apply tinting or shading.
+ *  0 <= tint <= 1: tinting -- l is increased
+ * -1 <= tint <= 0: shading -- l is decreased
+ */
+
+static GOColor
+gnm_go_color_apply_tint (GOColor orig, double tint)
+{
+       int h, s, l, a;
+
+       if (fabs (tint) < .005)
+               return orig;
+
+       gnm_go_color_to_hsla (orig, &h, &s, &l, &a);
+
+       tint = CLAMP (tint, -1.0, +1.0);
+
+       if (tint < 0.)
+               l = l * (1. + tint);
+       else
+               l = l * (1. - tint) + (HSLMAX - HSLMAX * (1.0 - tint));
+
+       if (s == 0) {            /* achromatic case */
+               int g = (l * RGBMAX) / HSLMAX;
+               return GO_COLOR_FROM_RGBA (g, g, g, a);
+       }
+
+       return gnm_go_color_from_hsla (h, s, l, a);
+}
+
+typedef enum {
+       XLSX_CS_NONE = 0,
+       XLSX_CS_FONT = 1,
+       XLSX_CS_LINE = 2,
+       XLSX_CS_FILL_BACK = 3,
+       XLSX_CS_FILL_FORE = 4,
+       XLSX_CS_MARKER = 5,
+       XLSX_CS_MARKER_OUTLINE = 6,
+        XLSX_CS_ANY = 7 /* for pop */
+} XLSXColorState;
+
+static void
+color_set_helper (XLSXReadState *state)
+{
+#ifdef DEBUG_COLOR
+       g_printerr ("color: #%08x in state %d\n",
+                   state->color, state->chart_color_state & 7);
+#endif
+
+       switch (state->chart_color_state & 7) {
+       default:
+       case XLSX_CS_NONE:
+               break;
+       case XLSX_CS_FONT:
+               state->cur_style->font.color = state->color;
+               state->cur_style->font.auto_color = FALSE;
+               break;
+       case XLSX_CS_LINE:
+               state->cur_style->line.color = state->color;
+               state->cur_style->line.auto_color = FALSE;
+               break;
+       case XLSX_CS_FILL_BACK:
+               state->cur_style->fill.pattern.back = state->color;
+               state->cur_style->fill.auto_back = FALSE;
+               break;
+       case XLSX_CS_FILL_FORE:
+               state->cur_style->fill.pattern.fore = state->color;
+               state->cur_style->fill.auto_fore = FALSE;
+               break;
+       case XLSX_CS_MARKER:
+               go_marker_set_fill_color (state->marker, state->color);
+               state->cur_style->marker.auto_fill_color = FALSE;
+               break;
+       case XLSX_CS_MARKER_OUTLINE:
+               go_marker_set_outline_color (state->marker, state->color);
+               state->cur_style->marker.auto_outline_color = FALSE;
+               break;
+       }
+}
+
+static void
+xlsx_draw_color_rgba_channel (GsfXMLIn *xin, xmlChar const **attrs)
+{
+       XLSXReadState *state = (XLSXReadState *)xin->user_state;
+       guint action = xin->node->user_data.v_int & 3;
+       guint channel = xin->node->user_data.v_int >> 2; /* a=3, r=2, g=1, b=0 */
+       int val;
+       if (simple_int (xin, attrs, &val)) {
+               const double f = val / 100000.0;
+               int v;
+               double vf;
+
+               switch (channel) {
+               case 3: v = GO_COLOR_UINT_A (state->color); break;
+               case 2: v = GO_COLOR_UINT_R (state->color); break;
+               case 1: v = GO_COLOR_UINT_G (state->color); break;
+               case 0: v = GO_COLOR_UINT_B (state->color); break;
+               default: g_assert_not_reached ();
+               }
+               switch (action) {
+               case 0: vf = 256 * f; break;
+               case 1: vf = v + 256 * f; break;
+               case 2: vf = v * f; break;
+               default: g_assert_not_reached ();
+               }
+               v = CLAMP (vf, 0, 255);
+               switch (channel) {
+               case 3: state->color = GO_COLOR_CHANGE_A (state->color, v); break;
+               case 2: state->color = GO_COLOR_CHANGE_R (state->color, v); break;
+               case 1: state->color = GO_COLOR_CHANGE_G (state->color, v); break;
+               case 0: state->color = GO_COLOR_CHANGE_B (state->color, v); break;
+               default: g_assert_not_reached ();
+               }
+               color_set_helper (state);
+       }
+}
+
+static void
+xlsx_draw_color_gray (GsfXMLIn *xin, xmlChar const **attrs)
+{
+       XLSXReadState *state = (XLSXReadState *)xin->user_state;
+       int g = (22 * GO_COLOR_UINT_R (state->color) +
+                72 * GO_COLOR_UINT_G (state->color) +
+                06 * GO_COLOR_UINT_B (state->color)) / 100;
+       state->color = GO_COLOR_GREY (g);
+       color_set_helper (state);
+}
+
+static void
+xlsx_draw_color_comp (GsfXMLIn *xin, xmlChar const **attrs)
+{
+       XLSXReadState *state = (XLSXReadState *)xin->user_state;
+       g_warning ("Unhandled hsl complement of #%08x\n", state->color);
+}
+
+static void
+xlsx_draw_color_invert (GsfXMLIn *xin, xmlChar const **attrs)
+{
+       XLSXReadState *state = (XLSXReadState *)xin->user_state;
+       state->color = GO_COLOR_FROM_RGBA (0xff, 0xff, 0xff, 0) ^ state->color;
+       color_set_helper (state);
+}
+
+static void
+xlsx_draw_color_hsl_channel (GsfXMLIn *xin, xmlChar const **attrs)
+{
+       XLSXReadState *state = (XLSXReadState *)xin->user_state;
+       guint action = xin->node->user_data.v_int & 3;
+       guint channel = xin->node->user_data.v_int >> 2; /* hue=2, sat=1, lum=0 */
+       int val;
+       if (simple_int (xin, attrs, &val)) {
+               const double f = val / 100000.0;
+               int hsl[3], a, v;
+               double vf;
+
+               gnm_go_color_to_hsla (state->color, &hsl[2], &hsl[1], &hsl[0], &a);
+               v = hsl[channel];
+
+               switch (action) {
+               case 0: vf = (HSLMAX + 1) * f; break;
+               case 1: vf = v + (HSLMAX + 1) * f; break;
+               case 2: vf = v * f; break;
+               default: g_assert_not_reached ();
+               }
+
+               hsl[channel] = CLAMP (vf, 0, HSLMAX);
+               state->color = gnm_go_color_from_hsla (hsl[2], hsl[1], hsl[0], a);
+       }
+}
+
+static void
+xlsx_draw_color_gamma (GsfXMLIn *xin, xmlChar const **attrs)
+{
+       XLSXReadState *state = (XLSXReadState *)xin->user_state;
+       gboolean inv = xin->node->user_data.v_int;
+       g_warning ("Unhandled colour %d gamma transformation of #%08x\n", inv, state->color);
+}
+
+
+static void
+xlsx_draw_color_shade (GsfXMLIn *xin, xmlChar const **attrs)
+{
+       XLSXReadState *state = (XLSXReadState *)xin->user_state;
+       unsigned val;
+       if (simple_uint (xin, attrs, &val)) {
+               const double scale = 100000;
+               double f = val / scale;
+               state->color = gnm_go_color_apply_tint (state->color, -f);
+               color_set_helper (state);
+       }
+}
+
+static void
+xlsx_draw_color_tint (GsfXMLIn *xin, xmlChar const **attrs)
+{
+       XLSXReadState *state = (XLSXReadState *)xin->user_state;
+       unsigned val;
+       if (simple_uint (xin, attrs, &val)) {
+               const double scale = 100000;
+               double f = val / scale;
+               state->color = gnm_go_color_apply_tint (state->color, f);
+               color_set_helper (state);
+       }
+}
+
+
+#define COLOR_MODIFIER_NODE(parent,node,name,first,handler,user) \
+       GSF_XML_IN_NODE_FULL (parent, node, XL_NS_DRAW, name, (first ? GSF_XML_NO_CONTENT : GSF_XML_2ND), 
FALSE, FALSE, handler, NULL, user)
+
+#define COLOR_MODIFIER_NODES(parent,first)                             \
+       COLOR_MODIFIER_NODE(parent, COLOR_SHADE, "shade", first, &xlsx_draw_color_shade, 0), \
+       COLOR_MODIFIER_NODE(parent, COLOR_TINT, "tint", first, &xlsx_draw_color_tint, 0), \
+       COLOR_MODIFIER_NODE(parent, COLOR_COMP, "comp", first, &xlsx_draw_color_comp, 0), \
+       COLOR_MODIFIER_NODE(parent, COLOR_INV, "inv", first, &xlsx_draw_color_invert, 0), \
+       COLOR_MODIFIER_NODE(parent, COLOR_GRAY, "gray", first, &xlsx_draw_color_gray, 0), \
+       COLOR_MODIFIER_NODE(parent, COLOR_ALPHA, "alpha", first, &xlsx_draw_color_rgba_channel, 12), \
+       COLOR_MODIFIER_NODE(parent, COLOR_ALPHA_OFF, "alphaOff", first, &xlsx_draw_color_rgba_channel, 13), \
+       COLOR_MODIFIER_NODE(parent, COLOR_ALPHA_MOD, "alphaMod", first, &xlsx_draw_color_rgba_channel, 14), \
+       COLOR_MODIFIER_NODE(parent, COLOR_HUE, "hue", first, xlsx_draw_color_hsl_channel, 8), \
+       COLOR_MODIFIER_NODE(parent, COLOR_HUE_OFF, "hueOff", first, xlsx_draw_color_hsl_channel, 9), \
+       COLOR_MODIFIER_NODE(parent, COLOR_HUE_MOD, "hueMod", first, xlsx_draw_color_hsl_channel, 10), \
+       COLOR_MODIFIER_NODE(parent, COLOR_SAT, "sat", first, xlsx_draw_color_hsl_channel, 4), \
+       COLOR_MODIFIER_NODE(parent, COLOR_SAT_OFF, "satOff", first, xlsx_draw_color_hsl_channel, 5), \
+       COLOR_MODIFIER_NODE(parent, COLOR_SAT_MOD, "satMod", first, xlsx_draw_color_hsl_channel, 6), \
+       COLOR_MODIFIER_NODE(parent, COLOR_LUM, "lum", first, xlsx_draw_color_hsl_channel, 0), \
+       COLOR_MODIFIER_NODE(parent, COLOR_LUM_OFF, "lumOff", first, xlsx_draw_color_hsl_channel, 1), \
+       COLOR_MODIFIER_NODE(parent, COLOR_LUM_MOD, "lumMod", first, xlsx_draw_color_hsl_channel, 2), \
+       COLOR_MODIFIER_NODE(parent, COLOR_RED, "red", first, &xlsx_draw_color_rgba_channel, 8), \
+       COLOR_MODIFIER_NODE(parent, COLOR_RED_OFF, "redOff", first, &xlsx_draw_color_rgba_channel, 9), \
+       COLOR_MODIFIER_NODE(parent, COLOR_RED_MOD, "redMod", first, &xlsx_draw_color_rgba_channel, 10), \
+       COLOR_MODIFIER_NODE(parent, COLOR_GREEN, "green", first, &xlsx_draw_color_rgba_channel, 4), \
+       COLOR_MODIFIER_NODE(parent, COLOR_GREEN_OFF, "greenOff", first, &xlsx_draw_color_rgba_channel, 5), \
+       COLOR_MODIFIER_NODE(parent, COLOR_GREEN_MOD, "greenMod", first, &xlsx_draw_color_rgba_channel, 6), \
+       COLOR_MODIFIER_NODE(parent, COLOR_BLUE, "blue", first, &xlsx_draw_color_rgba_channel, 0), \
+       COLOR_MODIFIER_NODE(parent, COLOR_BLUE_OFF, "blueOff", first, &xlsx_draw_color_rgba_channel, 1), \
+       COLOR_MODIFIER_NODE(parent, COLOR_BLUE_MOD, "blueMod", first, &xlsx_draw_color_rgba_channel, 2), \
+       COLOR_MODIFIER_NODE(parent, COLOR_GAMMA, "gamma", first, &xlsx_draw_color_gamma, 0), \
+       COLOR_MODIFIER_NODE(parent, COLOR_INV_GAMMA, "invGamma", first, &xlsx_draw_color_gamma, 1)
diff --git a/plugins/excel/xlsx-read-drawing.c b/plugins/excel/xlsx-read-drawing.c
index e17ca7d..3565271 100644
--- a/plugins/excel/xlsx-read-drawing.c
+++ b/plugins/excel/xlsx-read-drawing.c
@@ -93,18 +93,6 @@ xlsx_push_text_object (XLSXReadState *state, const char *name)
        xlsx_chart_push_obj (state, label);
 }
 
-
-typedef enum {
-       XLSX_CS_NONE = 0,
-       XLSX_CS_FONT = 1,
-       XLSX_CS_LINE = 2,
-       XLSX_CS_FILL_BACK = 3,
-       XLSX_CS_FILL_FORE = 4,
-       XLSX_CS_MARKER = 5,
-       XLSX_CS_MARKER_OUTLINE = 6,
-        XLSX_CS_ANY = 7 /* for pop */
-} XLSXColorState;
-
 static void
 xlsx_chart_push_color_state (XLSXReadState *state, XLSXColorState s)
 {
@@ -446,45 +434,6 @@ xlsx_sppr_xfrm (GsfXMLIn *xin, xmlChar const **attrs)
 }
 
 static void
-color_set_helper (XLSXReadState *state)
-{
-#ifdef DEBUG_COLOR
-       g_printerr ("color: #%08x in state %d\n",
-                   state->color, state->chart_color_state & 7);
-#endif
-
-       switch (state->chart_color_state & 7) {
-       default:
-       case XLSX_CS_NONE:
-               break;
-       case XLSX_CS_FONT:
-               state->cur_style->font.color = state->color;
-               state->cur_style->font.auto_color = FALSE;
-               break;
-       case XLSX_CS_LINE:
-               state->cur_style->line.color = state->color;
-               state->cur_style->line.auto_color = FALSE;
-               break;
-       case XLSX_CS_FILL_BACK:
-               state->cur_style->fill.pattern.back = state->color;
-               state->cur_style->fill.auto_back = FALSE;
-               break;
-       case XLSX_CS_FILL_FORE:
-               state->cur_style->fill.pattern.fore = state->color;
-               state->cur_style->fill.auto_fore = FALSE;
-               break;
-       case XLSX_CS_MARKER:
-               go_marker_set_fill_color (state->marker, state->color);
-               state->cur_style->marker.auto_fill_color = FALSE;
-               break;
-       case XLSX_CS_MARKER_OUTLINE:
-               go_marker_set_outline_color (state->marker, state->color);
-               state->cur_style->marker.auto_outline_color = FALSE;
-               break;
-       }
-}
-
-static void
 xlsx_draw_color_themed (GsfXMLIn *xin, xmlChar const **attrs)
 {
 #if 0
@@ -555,164 +504,6 @@ xlsx_draw_color_scrgb (GsfXMLIn *xin, xmlChar const **attrs)
        color_set_helper (state);
 }
 
-static void
-xlsx_draw_color_rgba_channel (GsfXMLIn *xin, xmlChar const **attrs)
-{
-       XLSXReadState *state = (XLSXReadState *)xin->user_state;
-       guint action = xin->node->user_data.v_int & 3;
-       guint channel = xin->node->user_data.v_int >> 2; /* a=3, r=2, g=1, b=0 */
-       int val;
-       if (simple_int (xin, attrs, &val)) {
-               const double f = val / 100000.0;
-               int v;
-               double vf;
-
-               switch (channel) {
-               case 3: v = GO_COLOR_UINT_A (state->color); break;
-               case 2: v = GO_COLOR_UINT_R (state->color); break;
-               case 1: v = GO_COLOR_UINT_G (state->color); break;
-               case 0: v = GO_COLOR_UINT_B (state->color); break;
-               default: g_assert_not_reached ();
-               }
-               switch (action) {
-               case 0: vf = 256 * f; break;
-               case 1: vf = v + 256 * f; break;
-               case 2: vf = v * f; break;
-               default: g_assert_not_reached ();
-               }
-               v = CLAMP (vf, 0, 255);
-               switch (channel) {
-               case 3: state->color = GO_COLOR_CHANGE_A (state->color, v); break;
-               case 2: state->color = GO_COLOR_CHANGE_R (state->color, v); break;
-               case 1: state->color = GO_COLOR_CHANGE_G (state->color, v); break;
-               case 0: state->color = GO_COLOR_CHANGE_B (state->color, v); break;
-               default: g_assert_not_reached ();
-               }
-               color_set_helper (state);
-       }
-}
-
-static void
-xlsx_draw_color_gray (GsfXMLIn *xin, xmlChar const **attrs)
-{
-       XLSXReadState *state = (XLSXReadState *)xin->user_state;
-       int g = (22 * GO_COLOR_UINT_R (state->color) +
-                72 * GO_COLOR_UINT_G (state->color) +
-                06 * GO_COLOR_UINT_B (state->color)) / 100;
-       state->color = GO_COLOR_GREY (g);
-       color_set_helper (state);
-}
-
-static void
-xlsx_draw_color_comp (GsfXMLIn *xin, xmlChar const **attrs)
-{
-       XLSXReadState *state = (XLSXReadState *)xin->user_state;
-       g_warning ("Unhandled hsl complement of #%08x\n", state->color);
-}
-
-static void
-xlsx_draw_color_invert (GsfXMLIn *xin, xmlChar const **attrs)
-{
-       XLSXReadState *state = (XLSXReadState *)xin->user_state;
-       state->color = GO_COLOR_FROM_RGBA (0xff, 0xff, 0xff, 0) ^ state->color;
-       color_set_helper (state);
-}
-
-static void
-xlsx_draw_color_hsl_channel (GsfXMLIn *xin, xmlChar const **attrs)
-{
-       XLSXReadState *state = (XLSXReadState *)xin->user_state;
-       guint action = xin->node->user_data.v_int & 3;
-       guint channel = xin->node->user_data.v_int >> 2; /* hue=2, sat=1, lum=0 */
-       int val;
-       if (simple_int (xin, attrs, &val)) {
-               g_warning ("Unhandling hsl colour modification %d %d for #%08x",
-                          action, channel, state->color);
-       }
-}
-
-static void
-xlsx_draw_color_gamma (GsfXMLIn *xin, xmlChar const **attrs)
-{
-       XLSXReadState *state = (XLSXReadState *)xin->user_state;
-       gboolean inv = xin->node->user_data.v_int;
-       g_warning ("Unhandled colour %d gamma transformation of #%08x\n", inv, state->color);
-}
-
-
-static void
-xlsx_draw_color_shade (GsfXMLIn *xin, xmlChar const **attrs)
-{
-       XLSXReadState *state = (XLSXReadState *)xin->user_state;
-       unsigned val;
-       if (simple_uint (xin, attrs, &val)) {
-               const unsigned scale = 100000u;
-               double f = CLAMP (val, 0u, scale) / (double)scale;
-               /*
-                * FIXME: Wrong RGB colour space, see
-                * 
https://social.msdn.microsoft.com/forums/office/en-US/f6d26f2c-114f-4a0d-8bca-a27442aec4d0/tint-and-shade-elements
-                */
-               state->color = GO_COLOR_CHANGE_R(state->color, (guint8)(f*GO_COLOR_UINT_R(state->color)));
-               state->color = GO_COLOR_CHANGE_G(state->color, (guint8)(f*GO_COLOR_UINT_G(state->color)));
-               state->color = GO_COLOR_CHANGE_B(state->color, (guint8)(f*GO_COLOR_UINT_B(state->color)));
-               color_set_helper (state);
-       }
-}
-
-static void
-xlsx_draw_color_tint (GsfXMLIn *xin, xmlChar const **attrs)
-{
-       XLSXReadState *state = (XLSXReadState *)xin->user_state;
-       unsigned val;
-       if (simple_uint (xin, attrs, &val)) {
-               const unsigned scale = 100000u;
-               double f = CLAMP (val, 0u, scale) / (double)scale;
-               /*
-                * FIXME: Wrong RGB colour space, see
-                * 
https://social.msdn.microsoft.com/forums/office/en-US/f6d26f2c-114f-4a0d-8bca-a27442aec4d0/tint-and-shade-elements
-                */
-               state->color = GO_COLOR_CHANGE_R(state->color, (guint8)(f * 255 + (1 - f) * 
GO_COLOR_UINT_R(state->color)));
-               state->color = GO_COLOR_CHANGE_G(state->color, (guint8)(f * 255 + (1 - f) * 
GO_COLOR_UINT_G(state->color)));
-               state->color = GO_COLOR_CHANGE_B(state->color, (guint8)(f * 255 + (1 - f) * 
GO_COLOR_UINT_B(state->color)));
-               color_set_helper (state);
-       }
-}
-
-
-#define COLOR_MODIFIER_NODE(parent,node,name,first,handler,user) \
-       GSF_XML_IN_NODE_FULL (parent, node, XL_NS_DRAW, name, (first ? GSF_XML_NO_CONTENT : GSF_XML_2ND), 
FALSE, FALSE, handler, NULL, user)
-
-#define COLOR_MODIFIER_NODES(parent,first)                             \
-       COLOR_MODIFIER_NODE(parent, COLOR_SHADE, "shade", first, &xlsx_draw_color_shade, 0), \
-       COLOR_MODIFIER_NODE(parent, COLOR_TINT, "tint", first, &xlsx_draw_color_tint, 0), \
-       COLOR_MODIFIER_NODE(parent, COLOR_COMP, "comp", first, &xlsx_draw_color_comp, 0), \
-       COLOR_MODIFIER_NODE(parent, COLOR_INV, "inv", first, &xlsx_draw_color_invert, 0), \
-       COLOR_MODIFIER_NODE(parent, COLOR_GRAY, "gray", first, &xlsx_draw_color_gray, 0), \
-       COLOR_MODIFIER_NODE(parent, COLOR_ALPHA, "alpha", first, &xlsx_draw_color_rgba_channel, 12), \
-       COLOR_MODIFIER_NODE(parent, COLOR_ALPHA_OFF, "alphaOff", first, &xlsx_draw_color_rgba_channel, 13), \
-       COLOR_MODIFIER_NODE(parent, COLOR_ALPHA_MOD, "alphaMod", first, &xlsx_draw_color_rgba_channel, 14), \
-       COLOR_MODIFIER_NODE(parent, COLOR_HUE, "hue", first, xlsx_draw_color_hsl_channel, 8), \
-       COLOR_MODIFIER_NODE(parent, COLOR_HUE_OFF, "hueOff", first, xlsx_draw_color_hsl_channel, 9), \
-       COLOR_MODIFIER_NODE(parent, COLOR_HUE_MOD, "hueMod", first, xlsx_draw_color_hsl_channel, 10), \
-       COLOR_MODIFIER_NODE(parent, COLOR_SAT, "sat", first, xlsx_draw_color_hsl_channel, 4), \
-       COLOR_MODIFIER_NODE(parent, COLOR_SAT_OFF, "satOff", first, xlsx_draw_color_hsl_channel, 5), \
-       COLOR_MODIFIER_NODE(parent, COLOR_SAT_MOD, "satMod", first, xlsx_draw_color_hsl_channel, 6), \
-       COLOR_MODIFIER_NODE(parent, COLOR_LUM, "lum", first, xlsx_draw_color_hsl_channel, 0), \
-       COLOR_MODIFIER_NODE(parent, COLOR_LUM_OFF, "lumOff", first, xlsx_draw_color_hsl_channel, 1), \
-       COLOR_MODIFIER_NODE(parent, COLOR_LUM_MOD, "lumMod", first, xlsx_draw_color_hsl_channel, 2), \
-       COLOR_MODIFIER_NODE(parent, COLOR_RED, "red", first, &xlsx_draw_color_rgba_channel, 8), \
-       COLOR_MODIFIER_NODE(parent, COLOR_RED_OFF, "redOff", first, &xlsx_draw_color_rgba_channel, 9), \
-       COLOR_MODIFIER_NODE(parent, COLOR_RED_MOD, "redMod", first, &xlsx_draw_color_rgba_channel, 10), \
-       COLOR_MODIFIER_NODE(parent, COLOR_GREEN, "green", first, &xlsx_draw_color_rgba_channel, 4), \
-       COLOR_MODIFIER_NODE(parent, COLOR_GREEN_OFF, "greenOff", first, &xlsx_draw_color_rgba_channel, 5), \
-       COLOR_MODIFIER_NODE(parent, COLOR_GREEN_MOD, "greenMod", first, &xlsx_draw_color_rgba_channel, 6), \
-       COLOR_MODIFIER_NODE(parent, COLOR_BLUE, "blue", first, &xlsx_draw_color_rgba_channel, 0), \
-       COLOR_MODIFIER_NODE(parent, COLOR_BLUE_OFF, "blueOff", first, &xlsx_draw_color_rgba_channel, 1), \
-       COLOR_MODIFIER_NODE(parent, COLOR_BLUE_MOD, "blueMod", first, &xlsx_draw_color_rgba_channel, 2), \
-       COLOR_MODIFIER_NODE(parent, COLOR_GAMMA, "gamma", first, &xlsx_draw_color_gamma, 0), \
-       COLOR_MODIFIER_NODE(parent, COLOR_INV_GAMMA, "invGamma", first, &xlsx_draw_color_gamma, 1)
-
-
 static GsfXMLInNode const xlsx_chart_drawing_dtd[] =
 {
 GSF_XML_IN_NODE_FULL (START, START, -1, NULL, GSF_XML_NO_CONTENT, FALSE, TRUE, NULL, NULL, 0),
diff --git a/plugins/excel/xlsx-read.c b/plugins/excel/xlsx-read.c
index 7ccb369..d0005f6 100644
--- a/plugins/excel/xlsx-read.c
+++ b/plugins/excel/xlsx-read.c
@@ -1201,103 +1201,11 @@ xlsx_parse_sqref (GsfXMLIn *xin, xmlChar const *refs)
 static void xlsx_ext_begin (GsfXMLIn *xin, xmlChar const **attrs);
 static void xlsx_ext_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob);
 
+#include "xlsx-read-color.c"
 #include "xlsx-read-drawing.c"
 
 /***********************************************************************/
 
-/* RGBMAX, HLSMAX must each fit in a byte. */
-/* HLSMAX BEST IF DIVISIBLE BY 6 */
-#define  HLSMAX   240 /* H,L, and S vary over 0-HLSMAX */
-#define  RGBMAX   255 /* R,G, and B vary over 0-RGBMAX */
-
-/* Hue is undefined if Saturation is 0 (grey-scale) */
-/* This value determines where the Hue scrollbar is */
-/* initially set for achromatic colors */
-#define UNDEFINED (HLSMAX*2/3)
-
-/* utility routine for HLStoRGB */
-static int
-hue_to_color (int m1, int m2, int h)
-{
-       if (h < 0)
-               h += HLSMAX;
-       if (h > HLSMAX)
-               h -= HLSMAX;
-
-       /* return r,g, or b value from this tridrant */
-       if (h < (HLSMAX/6))
-               return m1 + (((m2 - m1)*h + (HLSMAX/12))/(HLSMAX/6));
-       if (h < (HLSMAX/2))
-               return m2;
-       if (h < ((HLSMAX*2)/3))
-               return m1 + (((m2 - m1)*(((HLSMAX*2)/3)-h)+(HLSMAX/12))/(HLSMAX/6));
-
-       return m1;
-}
-
-static GOColor
-apply_tint (GOColor orig, double tint)
-{
-       int r = GO_COLOR_UINT_R (orig);
-       int g = GO_COLOR_UINT_G (orig);
-       int b = GO_COLOR_UINT_B (orig);
-       int a = GO_COLOR_UINT_A (orig);
-       int maxC = b, minC = b, delta, sum, h = 0, l, s, m1, m2;
-
-       if (fabs (tint) < .005)
-               return orig;
-
-       maxC = MAX (MAX (r,g),b);
-       minC = MIN (MIN (r,g),b);
-       l = (((maxC + minC)*HLSMAX) + RGBMAX)/(2*RGBMAX);
-
-       delta = maxC - minC;
-       sum   = maxC + minC;
-       if (delta != 0) {
-               if (l <= (HLSMAX/2))
-                       s = ( (delta*HLSMAX) + (sum/2) ) / sum;
-               else
-                       s = ( (delta*HLSMAX) + ((2*RGBMAX - sum)/2) ) / (2*RGBMAX - sum);
-
-               if (r == maxC)
-                       h =                ((g - b) * HLSMAX) / (6 * delta);
-               else if (g == maxC)
-                       h = (  HLSMAX/3) + ((b - r) * HLSMAX) / (6 * delta);
-               else if (b == maxC)
-                       h = (2*HLSMAX/3) + ((r - g) * HLSMAX) / (6 * delta);
-
-               if (h < 0)
-                       h += HLSMAX;
-               else if (h >= HLSMAX)
-                       h -= HLSMAX;
-       } else {
-               h = 0;
-               s = 0;
-       }
-
-       if (tint < 0.)
-               l = l * (1. + tint);
-       else
-               l = l * (1. - tint) + (HLSMAX - HLSMAX * (1.0 - tint));
-
-       if (s == 0) {            /* achromatic case */
-               r = (l * RGBMAX) / HLSMAX;
-               return GO_COLOR_FROM_RGBA (r, r, r, a);
-       }
-
-       if (l <= (HLSMAX/2))
-               m2 = (l*(HLSMAX + s) + (HLSMAX/2))/HLSMAX;
-       else
-               m2 = l + s - ((l*s) + (HLSMAX/2))/HLSMAX;
-       m1 = 2*l - m2;
-
-       r = (hue_to_color (m1, m2, h + (HLSMAX/3))*RGBMAX + (HLSMAX/2)) / HLSMAX;
-       g = (hue_to_color (m1, m2, h             )*RGBMAX + (HLSMAX/2)) / HLSMAX;
-       b = (hue_to_color (m1, m2, h - (HLSMAX/3))*RGBMAX + (HLSMAX/2)) / HLSMAX;
-
-       return GO_COLOR_FROM_RGBA (r,g,b,a);
-}
-
 static GnmColor *
 elem_color (GsfXMLIn *xin, xmlChar const **attrs, gboolean allow_alpha)
 {
@@ -1325,14 +1233,14 @@ elem_color (GsfXMLIn *xin, xmlChar const **attrs, gboolean allow_alpha)
                        has_color = TRUE;
                        c = themed_color (xin, indx);
                } else if (attr_float (xin, attrs, "tint", &tint))
-                       tint = CLAMP (tint, -1., 1.);
+                       ; /* Nothing */
        }
 
        if (!has_color)
                return NULL;
-       c = apply_tint (c, tint);
+       c = gnm_go_color_apply_tint (c, tint);
        if (!allow_alpha)
-               c |= 0xFF;
+               c = GO_COLOR_CHANGE_A (c, 0xFF);
        return gnm_color_new_go (c);
 }
 
@@ -4874,25 +4782,38 @@ static void
 xlsx_theme_color_sys (GsfXMLIn *xin, xmlChar const **attrs)
 {
        XLSXReadState   *state = (XLSXReadState *)xin->user_state;
-       GOColor c;
-       for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2)
+       GOColor c = GO_COLOR_BLACK;
+
+       for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2) {
                if (attr_gocolor (xin, attrs, "lastClr", &c)) {
-                       g_hash_table_replace (state->theme_colors_by_name,
-                               g_strdup (((GsfXMLInNode *)xin->node_stack->data)->name),
-                               GUINT_TO_POINTER (c));
                }
+       }
+
+       state->color = c;
 }
 static void
 xlsx_theme_color_rgb (GsfXMLIn *xin, xmlChar const **attrs)
 {
        XLSXReadState   *state = (XLSXReadState *)xin->user_state;
-       GOColor c;
-       for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2)
+       GOColor c = GO_COLOR_BLACK;
+
+       for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2) {
                if (attr_gocolor (xin, attrs, "val", &c)) {
-                       g_hash_table_replace (state->theme_colors_by_name,
-                               g_strdup (((GsfXMLInNode *)xin->node_stack->data)->name),
-                               GUINT_TO_POINTER (c));
                }
+       }
+
+       state->color = c;
+}
+
+static void
+xlsx_theme_color_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
+{
+       XLSXReadState *state = (XLSXReadState *)xin->user_state;
+       const char *name = ((GsfXMLInNode *)xin->node_stack->data)->name;
+
+       g_hash_table_replace (state->theme_colors_by_name,
+                             g_strdup (name),
+                             GUINT_TO_POINTER (state->color));
 }
 
 static GsfXMLInNode const xlsx_theme_dtd[] = {
@@ -4901,9 +4822,10 @@ GSF_XML_IN_NODE_FULL (START, THEME, XL_NS_DRAW, "theme", GSF_XML_NO_CONTENT, FAL
   GSF_XML_IN_NODE (THEME, ELEMENTS, XL_NS_DRAW, "themeElements", GSF_XML_NO_CONTENT, NULL, NULL),
     GSF_XML_IN_NODE (ELEMENTS, COLOR_SCHEME, XL_NS_DRAW, "clrScheme", GSF_XML_NO_CONTENT, NULL, NULL),
       GSF_XML_IN_NODE (COLOR_SCHEME, dk1, XL_NS_DRAW, "dk1", GSF_XML_NO_CONTENT, NULL, NULL),
-        GSF_XML_IN_NODE (dk1, SYS_COLOR, XL_NS_DRAW, "sysClr", GSF_XML_NO_CONTENT, &xlsx_theme_color_sys, 
NULL),
-        GSF_XML_IN_NODE (dk1, RGB_COLOR, XL_NS_DRAW, "srgbClr", GSF_XML_NO_CONTENT, &xlsx_theme_color_rgb, 
NULL),
-          GSF_XML_IN_NODE (RGB_COLOR, COLOR_ALPHA, XL_NS_DRAW, "alpha", GSF_XML_NO_CONTENT, NULL, NULL),
+        GSF_XML_IN_NODE (dk1, SYS_COLOR, XL_NS_DRAW, "sysClr", GSF_XML_NO_CONTENT, &xlsx_theme_color_sys, 
&xlsx_theme_color_end),
+          COLOR_MODIFIER_NODES(SYS_COLOR,TRUE),
+        GSF_XML_IN_NODE (dk1, RGB_COLOR, XL_NS_DRAW, "srgbClr", GSF_XML_NO_CONTENT, &xlsx_theme_color_rgb, 
&xlsx_theme_color_end),
+          COLOR_MODIFIER_NODES(RGB_COLOR,FALSE),
       GSF_XML_IN_NODE (COLOR_SCHEME, lt1, XL_NS_DRAW, "lt1", GSF_XML_NO_CONTENT, NULL, NULL),
         GSF_XML_IN_NODE (lt1, SYS_COLOR, XL_NS_DRAW, "sysClr", GSF_XML_2ND, NULL, NULL),
         GSF_XML_IN_NODE (lt1, RGB_COLOR, XL_NS_DRAW, "srgbClr", GSF_XML_2ND, NULL, NULL),
@@ -4954,10 +4876,7 @@ GSF_XML_IN_NODE_FULL (START, THEME, XL_NS_DRAW, "theme", GSF_XML_NO_CONTENT, FAL
       GSF_XML_IN_NODE (FORMAT_SCHEME, FILL_STYLE_LIST, XL_NS_DRAW, "fillStyleLst", GSF_XML_NO_CONTENT, NULL, 
NULL),
         GSF_XML_IN_NODE (FILL_STYLE_LIST,  SOLID_FILL, XL_NS_DRAW, "solidFill", GSF_XML_NO_CONTENT, NULL, 
NULL),
           GSF_XML_IN_NODE (SOLID_FILL, SCHEME_COLOR, XL_NS_DRAW, "schemeClr", GSF_XML_NO_CONTENT, NULL, 
NULL),
-           GSF_XML_IN_NODE (SCHEME_COLOR, COLOR_TINT, XL_NS_DRAW, "tint", GSF_XML_NO_CONTENT, NULL, NULL),
-           GSF_XML_IN_NODE (SCHEME_COLOR, COLOR_LUM, XL_NS_DRAW, "lumMod", GSF_XML_NO_CONTENT, NULL, NULL),
-           GSF_XML_IN_NODE (SCHEME_COLOR, COLOR_SAT, XL_NS_DRAW, "satMod", GSF_XML_NO_CONTENT, NULL, NULL),
-           GSF_XML_IN_NODE (SCHEME_COLOR, COLOR_SHADE, XL_NS_DRAW, "shade", GSF_XML_NO_CONTENT, NULL, NULL),
+           COLOR_MODIFIER_NODES(SCHEME_COLOR,FALSE),
         GSF_XML_IN_NODE (FILL_STYLE_LIST,  GRAD_FILL, XL_NS_DRAW, "gradFill", GSF_XML_NO_CONTENT, NULL, 
NULL),
           GSF_XML_IN_NODE (GRAD_FILL, GRAD_PATH, XL_NS_DRAW, "path", GSF_XML_NO_CONTENT, NULL, NULL),
             GSF_XML_IN_NODE (GRAD_PATH, GRAD_PATH_RECT, XL_NS_DRAW, "fillToRect", GSF_XML_NO_CONTENT, NULL, 
NULL),


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]