gnumeric r16867 - in trunk: . plugins/excel src
- From: jody svn gnome org
- To: svn-commits-list gnome org
- Subject: gnumeric r16867 - in trunk: . plugins/excel src
- Date: Thu, 9 Oct 2008 17:33:08 +0000 (UTC)
Author: jody
Date: Thu Oct 9 17:33:07 2008
New Revision: 16867
URL: http://svn.gnome.org/viewvc/gnumeric?rev=16867&view=rev
Log:
Support themed colours in xlsx. [#555687]
Modified:
trunk/ChangeLog
trunk/NEWS
trunk/plugins/excel/ChangeLog
trunk/plugins/excel/xlsx-read.c
trunk/src/mstyle.c
Modified: trunk/NEWS
==============================================================================
--- trunk/NEWS (original)
+++ trunk/NEWS Thu Oct 9 17:33:07 2008
@@ -35,6 +35,7 @@
* Extend ssgrep to search VBA too.
* Add column width doubling in 'display formula' mode.
* Fix OO.o style import. [#553506]
+ * Support XLSX themed colours. [#555687]
J.H.M. Dassen (Ray):
* Understand and ignore byte-order markers for CSV/stf probing and
Modified: trunk/plugins/excel/xlsx-read.c
==============================================================================
--- trunk/plugins/excel/xlsx-read.c (original)
+++ trunk/plugins/excel/xlsx-read.c Thu Oct 9 17:33:07 2008
@@ -147,6 +147,8 @@
GnmStyleBorderType border_style;
GnmColor *border_color;
+ GHashTable *theme_colors_by_name;
+
GPtrArray *collection; /* utility for the shared collection handlers */
unsigned count;
XLSXPanePos pane_pos;
@@ -194,8 +196,6 @@
GHashTable *by_obj;
XLSXAxisInfo *info;
} axis;
-
- GHashTable *theme_colors;
} XLSXReadState;
typedef struct {
GnmString *str;
@@ -570,8 +570,8 @@
{153, 51, 0}, {153, 51,102}, { 51, 51,153}, { 51, 51, 51}
};
-static GnmColor *
-indexed_color (gint idx)
+static GOColor
+indexed_color (XLSXReadState *state, gint idx)
{
/* NOTE: not documented but seems close
* If you find a normative reference please forward it.
@@ -588,26 +588,28 @@
*/
if (idx == 1 || idx == 65)
- return style_color_white ();
+ return RGBA_WHITE;
switch (idx) {
case 0: /* black */
case 64 : /* system text ? */
case 81 : /* tooltip text */
case 0x7fff : /* system text ? */
- return style_color_black ();
+ return RGBA_BLACK;
+
case 1 : /* white */
case 65 : /* system back ? */
- return style_color_white ();
+ return RGBA_WHITE;
case 80 : /* tooltip background */
- return style_color_new_gdk (&gs_yellow);
+ return RGBA_YELLOW;
+
+ case 2 : return RGBA_RED;
+ case 3 : return RGBA_GREEN;
+ case 4 : return RGBA_BLUE;
+ case 5 : return RGBA_YELLOW;
+ case 6 : return RGBA_VIOLET;
+ case 7 : return RGBA_CYAN;
- case 2 : return style_color_new_i8 (0xff, 0, 0); /* red */
- case 3 : return style_color_new_i8 ( 0, 0xff, 0); /* green */
- case 4 : return style_color_new_i8 ( 0, 0, 0xff); /* blue */
- case 5 : return style_color_new_i8 (0xff, 0xff, 0); /* yellow */
- case 6 : return style_color_new_i8 (0xff, 0, 0xff); /* magenta */
- case 7 : return style_color_new_i8 ( 0, 0xff, 0xff); /* cyan */
default :
break;
}
@@ -616,13 +618,47 @@
if (idx < 0 || (int) G_N_ELEMENTS (excel_default_palette_v8) <= idx) {
g_warning ("EXCEL: color index (%d) is out of range (8..%d). Defaulting to black",
idx + 8, (int)G_N_ELEMENTS (excel_default_palette_v8) + 8);
- return style_color_black ();
+ return RGBA_BLACK;
}
/* TODO cache and ref */
- return style_color_new_i8 (excel_default_palette_v8[idx].r,
- excel_default_palette_v8[idx].g,
- excel_default_palette_v8[idx].b);
+ return RGBA_TO_UINT (excel_default_palette_v8[idx].r,
+ excel_default_palette_v8[idx].g,
+ excel_default_palette_v8[idx].b, 0xff);
+}
+static GOColor
+themed_color (GsfXMLIn *xin, gint idx)
+{
+ static char const * const theme_elements [] = {
+ "lt1", "dk1", "lt2", "dk2",
+ "accent1", "accent2", "accent3", "accent4", "accent5", "accent6",
+ "hlink", "folHlink"
+ };
+ XLSXReadState *state = (XLSXReadState *)xin->user_state;
+
+ /* MAGIC :
+ * looks like the indicies map to hard coded names rather than the
+ * order in the file. Indeed the order in the file seems wrong
+ * it inverts the first to pairs
+ * 1,0,3,2, 4,5,6.....
+ * see: http://openxmldeveloper.org/forums/thread/1306.aspx
+ * OOo seems to do something similar
+ *
+ * I'll make the assumption we should work by name rather than
+ * index. */
+ if (idx >= 0 && idx < (int) G_N_ELEMENTS (theme_elements)) {
+ gpointer color = g_hash_table_lookup (state->theme_colors_by_name,
+ theme_elements [idx]);
+ if (NULL != color)
+ return GPOINTER_TO_UINT (color);
+
+ xlsx_warning (xin, _("Unknown theme color %d"), idx);
+ } else {
+ xlsx_warning (xin, "Color index (%d) is out of range (0..%d). Defaulting to black",
+ idx, (int) G_N_ELEMENTS (theme_elements));
+ }
+
+ return RGBA_BLACK;
}
static GOFormat *
@@ -1404,15 +1440,12 @@
XLSXReadState *state = (XLSXReadState *)xin->user_state;
gpointer val = NULL;
- if (NULL != state->theme_colors) {
- for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2)
- if (0 == strcmp (attrs[0], "val")) {
- val = g_hash_table_lookup (state->theme_colors, attrs[1]);
- if (NULL == val)
- xlsx_warning (xin, _("Unknown color '%s'"), attrs[1]);
- }
- } else
- xlsx_warning (xin, _("Missing theme"));
+ for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2)
+ if (0 == strcmp (attrs[0], "val")) {
+ val = g_hash_table_lookup (state->theme_colors_by_name, attrs[1]);
+ if (NULL == val)
+ xlsx_warning (xin, _("Unknown color '%s'"), attrs[1]);
+ }
state->gocolor = GPOINTER_TO_UINT (val);
}
@@ -2178,33 +2211,144 @@
/***********************************************************************/
+/* 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, float tint)
+{
+ int r = UINT_RGBA_R (orig);
+ int g = UINT_RGBA_G (orig);
+ int b = UINT_RGBA_B (orig);
+ int a = UINT_RGBA_A (orig);
+ int maxC = b, minC = b, delta, sum, h, 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 RGBA_TO_UINT(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 RGBA_TO_UINT(r,g,b,a);
+}
+
static GnmColor *
elem_color (GsfXMLIn *xin, xmlChar const **attrs)
{
+ XLSXReadState *state = (XLSXReadState *)xin->user_state;
int indx;
- guint a, r, g, b;
+ GOColor c;
+ double tint = 0.;
+ gboolean has_color = FALSE;
for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2) {
if (0 == strcmp (attrs[0], "rgb")) {
+ guint a, r, g, b;
if (4 != sscanf (attrs[1], "%02x%02x%02x%02x", &a, &r, &g, &b)) {
xlsx_warning (xin,
_("Invalid color '%s' for attribute rgb"),
attrs[1]);
return NULL;
}
+ has_color = TRUE;
+ c = RGBA_TO_UINT(r,g,b,a);
+ } else if (attr_int (xin, attrs, "indexed", &indx)) {
+ has_color = TRUE;
+ c = indexed_color (state, indx);
+ } else if (attr_int (xin, attrs, "theme", &indx)) {
+ has_color = TRUE;
+ c = themed_color (xin, indx);
+ } else if (attr_float (xin, attrs, "tint", &tint))
+ tint = CLAMP (tint, -1., 1.);
+ }
+
+ if (!has_color)
+ return NULL;
+ c = apply_tint (c, tint);
+ return style_color_new_go (c);
+}
- return style_color_new_i8 (r, g, b);
- } else if (attr_int (xin, attrs, "indexed", &indx))
- return indexed_color (indx);
-#if 0
- "type" opt rgb {auto, icv, rgb, theme }
- "val" opt ??
- "tint" opt 0.
-#endif
- }
+static GnmStyle *
+xlsx_get_style_xf (GsfXMLIn *xin, int xf)
+{
+ XLSXReadState *state = (XLSXReadState *)xin->user_state;
+ if (0 <= xf && NULL != state->style_xfs && xf < (int)state->style_xfs->len)
+ return g_ptr_array_index (state->style_xfs, xf);
+ xlsx_warning (xin, _("Undefined style record '%d'"), xf);
return NULL;
}
-
static GnmStyle *
xlsx_get_xf (GsfXMLIn *xin, int xf)
{
@@ -3359,7 +3503,7 @@
if (!defaultGridColor && grid_color_index >= 0)
sheet_style_set_auto_pattern_color (state->sheet,
- indexed_color (grid_color_index));
+ style_color_new_go (indexed_color (state, grid_color_index)));
if (tabSelected)
wb_view_sheet_focus (state->wb_view, state->sheet);
}
@@ -4118,7 +4262,6 @@
{
XLSXReadState *state = (XLSXReadState *)xin->user_state;
GnmColor *color = elem_color (xin, attrs);
-
if (NULL != color)
gnm_style_set_font_color (state->style_accum, color);
}
@@ -4206,27 +4349,16 @@
{
XLSXReadState *state = (XLSXReadState *)xin->user_state;
GnmColor *color = elem_color (xin, attrs);
-
- if (NULL != color) {
- if (gnm_style_is_element_set (state->style_accum, MSTYLE_COLOR_PATTERN) &&
- gnm_style_get_pattern (state->style_accum) == 1)
- gnm_style_set_back_color (state->style_accum, color);
- else
- gnm_style_set_pattern_color (state->style_accum, color);
- }
+ if (NULL != color)
+ gnm_style_set_back_color (state->style_accum, color);
}
static void
xlsx_pattern_bg (GsfXMLIn *xin, xmlChar const **attrs)
{
XLSXReadState *state = (XLSXReadState *)xin->user_state;
GnmColor *color = elem_color (xin, attrs);
- if (NULL != color) {
- if (!gnm_style_is_element_set (state->style_accum, MSTYLE_COLOR_PATTERN) ||
- gnm_style_get_pattern (state->style_accum) != 1)
- gnm_style_set_back_color (state->style_accum, color);
- else
- gnm_style_set_pattern_color (state->style_accum, color);
- }
+ if (NULL != color)
+ gnm_style_set_pattern_color (state->style_accum, color);
}
static void
@@ -4277,8 +4409,12 @@
xlsx_border_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
{
XLSXReadState *state = (XLSXReadState *)xin->user_state;
+ GnmBorder *border;
GnmStyleBorderLocation const loc = xin->node->user_data.v_int;
- GnmBorder *border = gnm_style_border_fetch (state->border_style,
+
+ if (NULL == state->border_color)
+ state->border_color = style_color_black ();
+ border = gnm_style_border_fetch (state->border_style,
state->border_color, gnm_style_border_get_orientation (loc));
gnm_style_set_border (state->style_accum,
GNM_STYLE_BORDER_LOCATION_TO_STYLE_ELEMENT (loc),
@@ -4299,7 +4435,9 @@
xlsx_xf_begin (GsfXMLIn *xin, xmlChar const **attrs)
{
XLSXReadState *state = (XLSXReadState *)xin->user_state;
- GnmStyle *style = gnm_style_new_default ();
+ GnmStyle *accum = gnm_style_new ();
+ GnmStyle *parent = NULL;
+ GnmStyle *result;
GPtrArray *elem = NULL;
int indx;
@@ -4307,30 +4445,42 @@
if (0 == strcmp (attrs[0], "numFmtId")) {
GOFormat *fmt = xlsx_get_num_fmt (xin, attrs[1]);
if (NULL != fmt)
- gnm_style_set_format (style, fmt);
+ gnm_style_set_format (accum, fmt);
} else if (attr_int (xin, attrs, "fontId", &indx))
elem = state->fonts;
else if (attr_int (xin, attrs, "fillId", &indx))
elem = state->fills;
else if (attr_int (xin, attrs, "borderId", &indx))
elem = state->borders;
+ else if (attr_int (xin, attrs, "xfId", &indx))
+ parent = xlsx_get_style_xf (xin, indx);
if (NULL != elem) {
- GnmStyle *existing = NULL;
+ GnmStyle const *component = NULL;
if (0 <= indx && indx < (int)elem->len)
- existing = g_ptr_array_index (elem, indx);
- if (NULL != existing) {
- GnmStyle *merged = gnm_style_new_merged (existing, style);
- gnm_style_unref (style);
- style = merged;
+ component = g_ptr_array_index (elem, indx);
+ if (NULL != component) {
+#if 0
+ gnm_style_merge (accum, component);
+#else
+ GnmStyle *merged = gnm_style_new_merged (accum, component);
+ gnm_style_unref (accum);
+ accum = merged;
+#endif
} else
- xlsx_warning (xin, _("Missing record '%d'"), indx);
+ xlsx_warning (xin, "Missing record '%d' for %s", indx, attrs[0]);
elem = NULL;
}
}
- state->style_accum = style;
+ if (NULL == parent) {
+ result = gnm_style_new_default ();
+ gnm_style_merge (result, accum);
+ } else
+ result = gnm_style_new_merged (parent, accum);
+ gnm_style_unref (accum);
+
+ state->style_accum = result;
#if 0
- "xfId" parent style ??
"quotePrefix" ??
"applyNumberFormat"
@@ -4422,7 +4572,7 @@
/* cellStyle name="Normal" xfId="0" builtinId="0" */
for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2)
if (attr_int (xin, attrs, "xfId", &tmp))
- style = xlsx_get_xf (xin, tmp);
+ style = xlsx_get_style_xf (xin, tmp);
else if (0 == strcmp (attrs[0], "name"))
name = attrs[1];
else if (0 == strcmp (attrs[0], "builtinId"))
@@ -4559,7 +4709,7 @@
GOColor c;
for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2)
if (attr_gocolor (xin, attrs, "lastClr", &c)) {
- g_hash_table_replace (state->theme_colors,
+ g_hash_table_replace (state->theme_colors_by_name,
g_strdup (((GsfXMLInNode *)xin->node_stack->data)->name),
GUINT_TO_POINTER (c));
}
@@ -4571,22 +4721,15 @@
GOColor c;
for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2)
if (attr_gocolor (xin, attrs, "val", &c)) {
- g_hash_table_replace (state->theme_colors,
+ g_hash_table_replace (state->theme_colors_by_name,
g_strdup (((GsfXMLInNode *)xin->node_stack->data)->name),
GUINT_TO_POINTER (c));
}
}
-static void
-xlsx_theme_start (GsfXMLIn *xin, xmlChar const **attrs)
-{
- XLSXReadState *state = (XLSXReadState *)xin->user_state;
- state->theme_colors = g_hash_table_new_full (g_str_hash, g_str_equal,
- (GDestroyNotify)g_free, NULL);
-}
static GsfXMLInNode const xlsx_theme_dtd[] = {
GSF_XML_IN_NODE_FULL (START, START, -1, NULL, GSF_XML_NO_CONTENT, FALSE, TRUE, NULL, NULL, 0),
-GSF_XML_IN_NODE_FULL (START, THEME, XL_NS_DRAW, "theme", GSF_XML_NO_CONTENT, FALSE, TRUE, &xlsx_theme_start, NULL, 0),
+GSF_XML_IN_NODE_FULL (START, THEME, XL_NS_DRAW, "theme", GSF_XML_NO_CONTENT, FALSE, TRUE, NULL, NULL, 0),
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),
@@ -4749,7 +4892,8 @@
state.num_fmts = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify)g_free, (GDestroyNotify) go_format_unref);
state.convs = xlsx_conventions_new ();
- state.theme_colors = NULL;
+ state.theme_colors_by_name = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify)g_free, NULL);
locale = gnm_push_C_locale ();
@@ -4766,13 +4910,13 @@
xlsx_parse_stream (&state, in, xlsx_shared_strings_dtd);
in = gsf_open_pkg_open_rel_by_type (wb_part,
- "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles", NULL);
- xlsx_parse_stream (&state, in, xlsx_styles_dtd);
-
- in = gsf_open_pkg_open_rel_by_type (wb_part,
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme", NULL);
xlsx_parse_stream (&state, in, xlsx_theme_dtd);
+ in = gsf_open_pkg_open_rel_by_type (wb_part,
+ "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles", NULL);
+ xlsx_parse_stream (&state, in, xlsx_styles_dtd);
+
xlsx_parse_stream (&state, wb_part, xlsx_workbook_dtd);
} else
go_cmd_context_error_import (GO_CMD_CONTEXT (context),
@@ -4804,8 +4948,7 @@
xlsx_style_array_free (state.style_xfs);
xlsx_style_array_free (state.dxfs);
xlsx_style_array_free (state.table_styles);
- if (state.theme_colors)
- g_hash_table_destroy (state.theme_colors);
+ g_hash_table_destroy (state.theme_colors_by_name);
workbook_set_saveinfo (state.wb, FILE_FL_AUTO,
go_file_saver_for_id ("Gnumeric_Excel:xlsx"));
@@ -4817,7 +4960,6 @@
* - column widths : Don't use hard coded font size
* - share colours
* - conditional formats
- * : why do we need to flip fg and bg for solid in xf but not for dxf
* : other condition types
* : check binary operators
*
Modified: trunk/src/mstyle.c
==============================================================================
--- trunk/src/mstyle.c (original)
+++ trunk/src/mstyle.c Thu Oct 9 17:33:07 2008
@@ -490,11 +490,11 @@
/**
* gnm_style_new_merged :
- * @src : #GnmStyle
+ * @base : #GnmStyle
* @overlay : #GnmStyle
*
* A new GnmStyle that contains any elements of @overlay that are set, and uses
- * @src for anything that is not set in @overlay.
+ * @base for anything that is not set in @overlay.
*
* Returns A ref to a new GnmStyle.
**/
@@ -506,7 +506,12 @@
new_style->ref_count = 1;
for (i = 0; i < MSTYLE_ELEMENT_MAX; i++) {
- elem_assign_contents (new_style, elem_is_set (overlay, i) ? overlay : base, i);
+ if (elem_is_set (overlay, i))
+ elem_assign_contents (new_style, overlay, i);
+ else if (elem_is_set (base, i))
+ elem_assign_contents (new_style, base, i);
+ else
+ continue;
elem_set (new_style, i);
elem_changed (new_style, i);
}
@@ -815,14 +820,17 @@
* @base : #GnmStyle
* @overlay : #GnmStyle
*
- * Applies any elements of @overlay that are set to @base.
+ * Applies all active elements of @overlay onto @base.
**/
void
gnm_style_merge (GnmStyle *base, GnmStyle const *overlay)
{
unsigned i;
+ if (base == overlay)
+ return;
for (i = 0; i < MSTYLE_ELEMENT_MAX; i++)
if (elem_is_set (overlay, i)) {
+ elem_clear_contents (base, i);
elem_assign_contents (base, overlay, i);
elem_changed (base, i);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]