[gnumeric] xlsx: import of gradients.
- From: Morten Welinder <mortenw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnumeric] xlsx: import of gradients.
- Date: Thu, 19 Feb 2015 00:29:30 +0000 (UTC)
commit 43ded377229f25c879d85731e752a3f47f3f1c7f
Author: Morten Welinder <terra gnome org>
Date: Wed Feb 18 19:27:27 2015 -0500
xlsx: import of gradients.
Our reversed gradients are handled by an extension.
NEWS | 2 +-
plugins/excel/xlsx-read-drawing.c | 85 ++++++++++++++++++++++++++++-------
plugins/excel/xlsx-read.c | 1 +
plugins/excel/xlsx-utils.c | 53 +++++------------------
plugins/excel/xlsx-utils.h | 22 ++++++++-
plugins/excel/xlsx-write-drawing.c | 34 ++++++++-------
6 files changed, 119 insertions(+), 78 deletions(-)
---
diff --git a/NEWS b/NEWS
index 51b70cd..d708135 100644
--- a/NEWS
+++ b/NEWS
@@ -21,7 +21,7 @@ Morten:
* Arrow properties editor. [#158327]
* Fix xlsx export of line style None.
* Fix search-and-replace problem with text format.
- * xlsx export of gradients.
+ * xlsx import/export of gradients.
--------------------------------------------------------------------------
Gnumeric 1.12.20
diff --git a/plugins/excel/xlsx-read-drawing.c b/plugins/excel/xlsx-read-drawing.c
index 888bd99..aa85e50 100644
--- a/plugins/excel/xlsx-read-drawing.c
+++ b/plugins/excel/xlsx-read-drawing.c
@@ -1665,6 +1665,7 @@ xlsx_chart_grad_fill (GsfXMLIn *xin, G_GNUC_UNUSED xmlChar const **attrs)
if (!(state->sp_type & GO_STYLE_LINE)) {
state->cur_style->fill.type = GO_STYLE_FILL_GRADIENT;
state->cur_style->fill.auto_type = FALSE;
+ state->gradient_count = 0;
}
}
}
@@ -1673,12 +1674,36 @@ static void
xlsx_chart_grad_linear (GsfXMLIn *xin, xmlChar const **attrs)
{
XLSXReadState *state = (XLSXReadState *)xin->user_state;
- int ang;
+ int ang = 0, ang_deg;
+ GOGradientDirection dir;
+
g_return_if_fail (state->cur_style);
- for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2)
+
+ for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2) {
if (attr_int (xin, attrs, "ang", &ang))
- state->cur_style->fill.gradient.dir
- = xlsx_get_gradient_direction (ang / 60000.);
+ ; /* Nothing */
+ }
+
+ ang_deg = ((ang + 30000) / 60000);
+ for (dir = 0; dir < GO_GRADIENT_MAX; dir++) {
+ int this_ang = xlsx_gradient_info[dir].angle;
+ gboolean this_mirrored = xlsx_gradient_info[dir].mirrored;
+ int a;
+
+ if (state->gradient_count != (this_mirrored ? 3 : 2))
+ continue;
+ /* We cannot distinguish the reversed case */
+
+ /* Different angle convention. */
+ this_ang = (360 - this_ang) % (this_mirrored ? 180 : 360);
+ a = ang_deg % (this_mirrored ? 180 : 360);
+ if (this_ang != a)
+ continue;
+
+ state->cur_style->fill.gradient.dir = dir;
+ break;
+ }
+
/* FIXME: we do not support the "scaled" attribute */
}
@@ -1686,20 +1711,24 @@ static void
xlsx_chart_grad_stop (GsfXMLIn *xin, xmlChar const **attrs)
{
XLSXReadState *state = (XLSXReadState *)xin->user_state;
- int pos;
+ int pos = 0;
XLSXColorState s = XLSX_CS_NONE;
g_return_if_fail (state->cur_style);
- for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2)
- if (attr_int (xin, attrs, "pos", &pos)) {
- if (pos <= 50000) {
- /* FIXME: use betstate->auto_colorter gradients
- * for now, we only support stops at 0 and 1 */
- s = XLSX_CS_FILL_BACK;
- } else {
- s = XLSX_CS_FILL_FORE;
- }
- }
+ for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2) {
+ if (attr_int (xin, attrs, "pos", &pos))
+ ; /* Nothing */
+ }
+
+ state->gradient_count++;
+
+ if (state->gradient_count == 1 && pos == 0)
+ s = XLSX_CS_FILL_BACK;
+ else if (state->gradient_count == 2 && (pos == 50000 || pos == 100000))
+ s = XLSX_CS_FILL_FORE;
+ else
+ s = XLSX_CS_NONE; /* I.e., ignore. */
+
xlsx_chart_push_color_state (state, s);
}
@@ -2188,7 +2217,7 @@ GSF_XML_IN_NODE_FULL (START, CHART_SPACE, XL_NS_CHART, "chartSpace", GSF_XML_NO_
GSF_XML_IN_NODE (SHAPE_PR, FILL_GRAD, XL_NS_DRAW, "gradFill", GSF_XML_NO_CONTENT,
&xlsx_chart_grad_fill, NULL),
GSF_XML_IN_NODE (FILL_GRAD, GRAD_LIST, XL_NS_DRAW, "gsLst", GSF_XML_NO_CONTENT, NULL, NULL),
- GSF_XML_IN_NODE (GRAD_LIST, GRAD_LIST_ITEM, XL_NS_DRAW, "gs", GSF_XML_NO_CONTENT, NULL, NULL),
+ GSF_XML_IN_NODE (GRAD_LIST, GRAD_LIST_ITEM, XL_NS_DRAW, "gs", GSF_XML_NO_CONTENT,
xlsx_chart_grad_stop, xlsx_chart_grad_stop_end),
GSF_XML_IN_NODE (GRAD_LIST_ITEM, COLOR_RGB, XL_NS_DRAW, "srgbClr", GSF_XML_NO_CONTENT, NULL, NULL),
/* 2nd Def */
GSF_XML_IN_NODE (FILL_GRAD, GRAD_LINE, XL_NS_DRAW, "lin", GSF_XML_NO_CONTENT,
&xlsx_chart_grad_linear, NULL),
@@ -2959,6 +2988,7 @@ xlsx_ext_gostyle (GsfXMLIn *xin, xmlChar const **attrs)
GOArrow *start_arrow = NULL;
GOArrow *end_arrow = NULL;
gboolean has_arrow = IS_GNM_SO_LINE (state->so);
+ int rev_gradient = 0;
if (!style)
return;
@@ -2996,6 +3026,8 @@ xlsx_ext_gostyle (GsfXMLIn *xin, xmlChar const **attrs)
end_arrow->b = f;
} else if (end_arrow && attr_float (xin, attrs, "EndArrowShapeC", &f)) {
end_arrow->c = f;
+ } else if (attr_bool (xin, attrs, "reverse-gradient", &rev_gradient)) {
+ /* Nothing */
}
}
@@ -3004,6 +3036,25 @@ xlsx_ext_gostyle (GsfXMLIn *xin, xmlChar const **attrs)
g_free (start_arrow);
g_free (end_arrow);
}
+
+ if (rev_gradient) {
+ GOGradientDirection dir0 = style->fill.gradient.dir;
+ GOGradientDirection dir;
+ for (dir = 0; dir < GO_GRADIENT_MAX; dir++) {
+ if (xlsx_gradient_info[dir0].angle == xlsx_gradient_info[dir].angle &&
+ xlsx_gradient_info[dir0].mirrored == xlsx_gradient_info[dir].mirrored &&
+ xlsx_gradient_info[dir0].reversed == !xlsx_gradient_info[dir].reversed) {
+ GOColor c = style->fill.pattern.back;
+ gboolean a = style->fill.auto_back;
+ style->fill.gradient.dir = dir;
+ style->fill.pattern.back = style->fill.pattern.fore;
+ style->fill.pattern.fore = c;
+ style->fill.auto_back = style->fill.auto_fore;
+ style->fill.auto_fore = a;
+ break;
+ }
+ }
+ }
}
static GsfXMLInNode const xlsx_drawing_dtd[] = {
@@ -3079,7 +3130,7 @@ GSF_XML_IN_NODE_FULL (START, DRAWING, XL_NS_SS_DRAW, "wsDr", GSF_XML_NO_CONTENT,
GSF_XML_IN_NODE (FILL_GRAD, GRAD_LIST, XL_NS_DRAW, "gsLst", GSF_XML_NO_CONTENT, NULL, NULL),
GSF_XML_IN_NODE (GRAD_LIST, GRAD_LIST_ITEM, XL_NS_DRAW, "gs", GSF_XML_NO_CONTENT,
xlsx_chart_grad_stop, xlsx_chart_grad_stop_end),
GSF_XML_IN_NODE (GRAD_LIST_ITEM, COLOR_RGB, XL_NS_DRAW, "srgbClr", GSF_XML_NO_CONTENT, NULL,
NULL), /* 2nd Def */
- GSF_XML_IN_NODE (FILL_GRAD, GRAD_LINE, XL_NS_DRAW, "lin", GSF_XML_NO_CONTENT, NULL, NULL),
+ GSF_XML_IN_NODE (FILL_GRAD, GRAD_LINE, XL_NS_DRAW, "lin", GSF_XML_NO_CONTENT,
&xlsx_chart_grad_linear, NULL),
GSF_XML_IN_NODE (SHAPE_PR, FILL_PATT, XL_NS_DRAW, "pattFill", GSF_XML_NO_CONTENT,
&xlsx_chart_patt_fill, NULL),
GSF_XML_IN_NODE_FULL (FILL_PATT, FILL_PATT_BG, XL_NS_DRAW, "bgClr", GSF_XML_NO_CONTENT,
FALSE, TRUE, &xlsx_chart_patt_fill_clr, &xlsx_chart_patt_fill_clr_end, FALSE),
diff --git a/plugins/excel/xlsx-read.c b/plugins/excel/xlsx-read.c
index 41c6836..b91bd69 100644
--- a/plugins/excel/xlsx-read.c
+++ b/plugins/excel/xlsx-read.c
@@ -210,6 +210,7 @@ typedef struct {
GogObject *series_pt;
gboolean series_pt_has_index;
GOStyle *cur_style;
+ int gradient_count;
guint32 chart_color_state;
GOColor color;
GOMarker *marker;
diff --git a/plugins/excel/xlsx-utils.c b/plugins/excel/xlsx-utils.c
index a3c51b0..610c077 100644
--- a/plugins/excel/xlsx-utils.c
+++ b/plugins/excel/xlsx-utils.c
@@ -709,48 +709,6 @@ xlsx_pivot_date_fmt (void)
return go_format_new_from_XL ("yyyy-mm-dd\"T\"hh:mm:ss");
}
-/**
- * xlsx_get_direction :
- *
- * Returns a GOGradientDirection corresponding to the angle ang (0...360)
- **/
-GOGradientDirection
-xlsx_get_gradient_direction (double ang)
-{
- int ang_i;
- g_return_val_if_fail (ang >=-360. && ang <= 360., GO_GRADIENT_N_TO_S);
-
- ang_i = ang;
- while (ang_i < 0)
- ang_i += 360;
- while (ang_i >= 360)
- ang_i -= 360;
-
- ang_i = (ang_i + 22) / 45; /* now ang is between 0 and 8 */
-
- switch (ang_i) {
- case 1:
- return GO_GRADIENT_NW_TO_SE;
- case 2:
- return GO_GRADIENT_W_TO_E;
- case 3:
- return GO_GRADIENT_SW_TO_NE;
- case 4:
- return GO_GRADIENT_S_TO_N;
- case 5:
- return GO_GRADIENT_SE_TO_NW;
- case 6:
- return GO_GRADIENT_E_TO_W;
- case 7:
- return GO_GRADIENT_NE_TO_SW;
- case 0:
- case 8:
- default:
- return GO_GRADIENT_N_TO_S;
- }
-}
-
-
XLSXPlotType
xlsx_plottype_from_type_name (const char *type_name)
{
@@ -777,3 +735,14 @@ xlsx_plottype_from_type_name (const char *type_name)
return XLSX_PT_UNKNOWN;
}
+
+/*****************************************************************************/
+
+XLSXGradientInfo xlsx_gradient_info[GO_GRADIENT_MAX] = {
+ { 270, FALSE, FALSE }, { 90, FALSE, FALSE }, { 90, TRUE, FALSE }, { 90, TRUE, TRUE },
+ { 180, FALSE, FALSE }, { 0, FALSE, FALSE }, { 0, TRUE, FALSE }, { 0, TRUE, TRUE },
+ { 315, FALSE, FALSE }, { 135, FALSE, FALSE }, { 135, TRUE, FALSE }, { 135, TRUE, TRUE },
+ { 225, FALSE, FALSE }, { 45, FALSE, FALSE }, { 45, TRUE, FALSE }, { 45, TRUE, TRUE }
+};
+
+/*****************************************************************************/
diff --git a/plugins/excel/xlsx-utils.h b/plugins/excel/xlsx-utils.h
index 0faab42..f53c692 100644
--- a/plugins/excel/xlsx-utils.h
+++ b/plugins/excel/xlsx-utils.h
@@ -58,8 +58,6 @@ Workbook *xlsx_conventions_add_extern_ref (GnmConventions *conv,
char const *path);
GOFormat *xlsx_pivot_date_fmt (void);
-GOGradientDirection xlsx_get_gradient_direction (double ang);
-
typedef enum {
XLSX_PT_UNKNOWN,
XLSX_PT_GOGAREAPLOT,
@@ -76,5 +74,25 @@ typedef enum {
} XLSXPlotType;
XLSXPlotType xlsx_plottype_from_type_name (const char *type_name);
+/*****************************************************************************/
+
+typedef struct {
+ /*
+ * Angle in degrees for the starting point.
+ * 0 is west, 90 is north; 180 is east; 270 is south.
+ * range is [0-360[ normally, but [0;180[ for mirrored.
+ */
+ unsigned angle : 16;
+
+ /* Gradient has three stop like F to B to F. */
+ unsigned mirrored : 1;
+
+ /* Gradient goes from B to F to B. */
+ unsigned reversed : 1;
+} XLSXGradientInfo;
+
+extern XLSXGradientInfo xlsx_gradient_info[GO_GRADIENT_MAX];
+
+/*****************************************************************************/
#endif /* GNM_XLSX_UTILS_H */
diff --git a/plugins/excel/xlsx-write-drawing.c b/plugins/excel/xlsx-write-drawing.c
index f7d393e..f9e06d4 100644
--- a/plugins/excel/xlsx-write-drawing.c
+++ b/plugins/excel/xlsx-write-drawing.c
@@ -217,6 +217,7 @@ xlsx_write_go_style_full (GsfXMLOut *xml, GOStyle *style, const XLSXStyleContext
gboolean ext_fill_pattern = FALSE;
gboolean ext_start_arrow = FALSE;
gboolean ext_end_arrow = FALSE;
+ gboolean ext_gradient_rev = FALSE;
char *spPr_tag = g_strconcat (sctx->spPr_ns, ":spPr", NULL);
@@ -319,22 +320,16 @@ xlsx_write_go_style_full (GsfXMLOut *xml, GOStyle *style, const XLSXStyleContext
}
case GO_STYLE_FILL_GRADIENT: {
GOGradientDirection dir = style->fill.gradient.dir;
- static gint16 angles[GO_GRADIENT_MAX] = {
- 90, 270, 90, 90,
- 0, 180, 0, 0,
- 45, 225, 45, 45,
- 135, 315, 135, 135
- };
- static gint8 flags[GO_GRADIENT_MAX] = {
- 0, 0, 1, 3,
- 0, 0, 1, 3,
- 0, 0, 1, 3,
- 0, 0, 1, 3
- };
- int i, N = (flags[dir] & 1) ? 3 : 2;
- gboolean rev = (flags[dir] & 2) != 0;
+ gboolean mirrored = xlsx_gradient_info[dir].mirrored;
+ gboolean rev = xlsx_gradient_info[dir].reversed;
+ unsigned angle = xlsx_gradient_info[dir].angle;
+ int i, N = mirrored ? 3 : 2;
+
+ /* Different angle convention. */
+ angle = (360 - angle) % (mirrored ? 180 : 360);
/* FIXME: Unicolor? */
+
gsf_xml_out_start_element (xml, "a:gradFill");
gsf_xml_out_start_element (xml, "a:gsLst");
for (i = 0; i < N; i++) {
@@ -352,9 +347,12 @@ xlsx_write_go_style_full (GsfXMLOut *xml, GOStyle *style, const XLSXStyleContext
}
gsf_xml_out_end_element (xml); /* "a:gsLst" */
gsf_xml_out_start_element (xml, "a:lin");
- gsf_xml_out_add_uint (xml, "ang", 60000 * angles[dir]);
+ gsf_xml_out_add_uint (xml, "ang", 60000 * angle);
gsf_xml_out_end_element (xml);
gsf_xml_out_end_element (xml); /* "a:gradFill" */
+
+ if (rev)
+ ext_gradient_rev = TRUE;
break;
}
}
@@ -449,7 +447,8 @@ xlsx_write_go_style_full (GsfXMLOut *xml, GOStyle *style, const XLSXStyleContext
}
if (sctx->state->with_extension &&
- (ext_fill_pattern || ext_start_arrow || ext_end_arrow)) {
+ (ext_fill_pattern || ext_start_arrow || ext_end_arrow ||
+ ext_gradient_rev)) {
/* What namespace do we use? */
gsf_xml_out_start_element (xml, "a:extLst");
gsf_xml_out_start_element (xml, "a:ext");
@@ -472,6 +471,9 @@ xlsx_write_go_style_full (GsfXMLOut *xml, GOStyle *style, const XLSXStyleContext
gsf_xml_out_add_float (xml, "EndArrowShapeB", arrow->b, -1);
gsf_xml_out_add_float (xml, "EndArrowShapeC", arrow->c, -1);
}
+ if (ext_gradient_rev) {
+ gsf_xml_out_add_uint (xml, "reverse-gradient", 1);
+ }
gsf_xml_out_end_element (xml); /* "gnmx:gostyle" */
gsf_xml_out_end_element (xml); /* "a:ext" */
gsf_xml_out_end_element (xml); /* "a:extLst" */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]