[gnumeric] ODF: import/export gradient fills
- From: Andreas J. Guelzow <guelzow src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnumeric] ODF: import/export gradient fills
- Date: Wed, 1 Sep 2010 07:57:15 +0000 (UTC)
commit 09dee216e979e2800a4b50124988e959f5da79c4
Author: Andreas J Guelzow <aguelzow pyrshep ca>
Date: Wed Sep 1 01:55:27 2010 -0600
ODF: import/export gradient fills
2010-09-01 Andreas J. Guelzow <aguelzow pyrshep ca>
* openoffice-read.c (odf_apply_style_props): new gradient attributes
(oo_dash): add warning
(oo_gradient): new
(od_style_prop_chart): new gradient attributes
* openoffice-write.c (odf_write_gradient_info): new
(odf_match_gradient): new
(odf_get_gradient_name): new
(odf_write_gog_style_graphic): add gradients
plugins/openoffice/ChangeLog | 11 +++
plugins/openoffice/openoffice-read.c | 116 ++++++++++++++++++++++++++++--
plugins/openoffice/openoffice-write.c | 129 ++++++++++++++++++++++++++++++---
3 files changed, 240 insertions(+), 16 deletions(-)
---
diff --git a/plugins/openoffice/ChangeLog b/plugins/openoffice/ChangeLog
index 72bd306..5c9bb19 100644
--- a/plugins/openoffice/ChangeLog
+++ b/plugins/openoffice/ChangeLog
@@ -1,3 +1,14 @@
+2010-09-01 Andreas J. Guelzow <aguelzow pyrshep ca>
+
+ * openoffice-read.c (odf_apply_style_props): new gradient attributes
+ (oo_dash): add warning
+ (oo_gradient): new
+ (od_style_prop_chart): new gradient attributes
+ * openoffice-write.c (odf_write_gradient_info): new
+ (odf_match_gradient): new
+ (odf_get_gradient_name): new
+ (odf_write_gog_style_graphic): add gradients
+
2010-08-31 Andreas J. Guelzow <aguelzow pyrshep ca>
* openoffice-read.c (odf_apply_style_props): switch auto-colors off
diff --git a/plugins/openoffice/openoffice-read.c b/plugins/openoffice/openoffice-read.c
index ee77403..b533550 100644
--- a/plugins/openoffice/openoffice-read.c
+++ b/plugins/openoffice/openoffice-read.c
@@ -209,6 +209,7 @@ typedef struct {
GHashTable *graph_styles; /* contain links to OOChartStyle GSLists */
GHashTable *hatches;
GHashTable *dash_styles;
+ GHashTable *gradient_styles;
OOChartStyle *i_plot_styles[OO_CHART_STYLE_INHERITANCE];
/* currently active styles at plot-area, */
@@ -308,6 +309,13 @@ typedef struct {
gboolean debug;
} OOParseState;
+typedef struct {
+ GOColor from;
+ GOColor to;
+ gnm_float brightness;
+ unsigned int dir;
+} gradient_info_t;
+
/* Some prototypes */
static GsfXMLInNode const * get_dtd (void);
@@ -571,7 +579,8 @@ odf_apply_style_props (GsfXMLIn *xin, GSList *props, GOStyle *style)
GSList *l;
gboolean desc_changed = FALSE;
char const *hatch_name = NULL;
- gboolean has_hatch = FALSE;
+ char const *gradient_name = NULL;
+ gboolean has_hatch = FALSE, has_gradient = FALSE;
unsigned int gnm_hatch = 0;
int symbol_type = -1, symbol_name = GO_MARKER_DIAMOND;
GOMarker *m;
@@ -590,6 +599,10 @@ odf_apply_style_props (GsfXMLIn *xin, GSList *props, GOStyle *style)
style->fill.type = GO_STYLE_FILL_PATTERN;
style->fill.auto_type = FALSE;
has_hatch = TRUE;
+ } else if (0 == strcmp (val_string, "gradient")) {
+ style->fill.type = GO_STYLE_FILL_GRADIENT;
+ style->fill.auto_type = FALSE;
+ has_gradient = TRUE;
} else {
style->fill.type = GO_STYLE_FILL_NONE;
style->fill.auto_type = FALSE;
@@ -601,7 +614,9 @@ odf_apply_style_props (GsfXMLIn *xin, GSList *props, GOStyle *style)
style->fill.pattern.back = GO_COLOR_FROM_GDK (gdk_color);
style->fill.auto_back = FALSE;
}
- } else if (0 == strcmp (prop->name, "fill-hatch-name"))
+ } else if (0 == strcmp (prop->name, "fill-gradient-name"))
+ gradient_name = g_value_get_string (&prop->value);
+ else if (0 == strcmp (prop->name, "fill-hatch-name"))
hatch_name = g_value_get_string (&prop->value);
else if (0 == strcmp (prop->name, "gnm-pattern"))
gnm_hatch = g_value_get_int (&prop->value);
@@ -671,7 +686,7 @@ odf_apply_style_props (GsfXMLIn *xin, GSList *props, GOStyle *style)
GOPattern *pat = g_hash_table_lookup
(state->chart.hatches, hatch_name);
if (pat == NULL)
- oo_warning (xin, _("Unknown hatch name encountered!"));
+ oo_warning (xin, _("Unknown hatch name \'%s\' encountered!"), hatch_name);
else {
style->fill.pattern.fore = pat->fore;
style->fill.auto_fore = FALSE;
@@ -680,6 +695,24 @@ odf_apply_style_props (GsfXMLIn *xin, GSList *props, GOStyle *style)
}
} else oo_warning (xin, _("Hatch fill without hatch name encountered!"));
}
+ if (has_gradient) {
+ if (gradient_name != NULL) {
+ gradient_info_t *info = g_hash_table_lookup
+ (state->chart.gradient_styles, gradient_name);
+ if (info == NULL)
+ oo_warning (xin, _("Unknown gradient name \'%s\' encountered!"), gradient_name);
+ else {
+ style->fill.auto_fore = FALSE;
+ style->fill.auto_back = FALSE;
+ style->fill.pattern.back = info->from;
+ style->fill.pattern.fore = info->to;
+ style->fill.gradient.dir = info->dir;
+ style->fill.gradient.brightness = -1.0;
+ if (info->brightness >= 0)
+ go_style_set_fill_brightness (style, info->brightness);
+ }
+ } else oo_warning (xin, _("Gradient fill without gradient name encountered!"));
+ }
switch (symbol_type) {
case OO_SYMBOL_TYPE_AUTO:
@@ -1966,6 +1999,68 @@ oo_dash (GsfXMLIn *xin, xmlChar const **attrs)
if (name != NULL)
g_hash_table_replace (state->chart.dash_styles,
g_strdup (name), GUINT_TO_POINTER (t));
+ else
+ oo_warning (xin, _("Unnamed dash style encountered."));
+}
+
+static void
+oo_gradient (GsfXMLIn *xin, xmlChar const **attrs)
+{
+ OOParseState *state = (OOParseState *)xin->user_state;
+ gradient_info_t *info = g_new0 (gradient_info_t, 1);
+ char const *name = NULL;
+ int angle = 0;
+ char const *style = NULL;
+ unsigned int axial_types[] =
+ {GO_GRADIENT_S_TO_N_MIRRORED, GO_GRADIENT_SE_TO_NW_MIRRORED,
+ GO_GRADIENT_E_TO_W_MIRRORED, GO_GRADIENT_NE_TO_SW_MIRRORED,
+ GO_GRADIENT_N_TO_S_MIRRORED, GO_GRADIENT_NW_TO_SE_MIRRORED,
+ GO_GRADIENT_W_TO_E_MIRRORED, GO_GRADIENT_SW_TO_NE_MIRRORED};
+ unsigned int linear_types[] =
+ {GO_GRADIENT_S_TO_N, GO_GRADIENT_SE_TO_NW,
+ GO_GRADIENT_E_TO_W, GO_GRADIENT_NE_TO_SW,
+ GO_GRADIENT_N_TO_S, GO_GRADIENT_NW_TO_SE,
+ GO_GRADIENT_W_TO_E, GO_GRADIENT_SW_TO_NE};
+
+ info->brightness = -1.;
+
+ for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2)
+ if (gsf_xml_in_namecmp (xin, CXML2C (attrs[0]), OO_NS_DRAW, "name"))
+ name = CXML2C (attrs[1]);
+ else if (gsf_xml_in_namecmp (xin, CXML2C (attrs[0]), OO_NS_DRAW, "start-color")) {
+ GdkColor gdk_color;
+ if (gdk_color_parse (CXML2C (attrs[1]), &gdk_color))
+ info->from = GO_COLOR_FROM_GDK (gdk_color);
+ else
+ oo_warning (xin, _("Unable to parse gradient color: %s"), CXML2C (attrs[1]));
+ } else if (gsf_xml_in_namecmp (xin, CXML2C (attrs[0]), OO_NS_DRAW, "end-color")) {
+ GdkColor gdk_color;
+ if (gdk_color_parse (CXML2C (attrs[1]), &gdk_color))
+ info->to = GO_COLOR_FROM_GDK (gdk_color);
+ else
+ oo_warning (xin, _("Unable to parse gradient color: %s"), CXML2C (attrs[1]));
+ } else if (gsf_xml_in_namecmp (xin, CXML2C (attrs[0]), OO_NS_DRAW, "style"))
+ style = CXML2C (attrs[1]);
+ else if (oo_attr_float (xin, attrs, OO_GNUM_NS_EXT,
+ "brightness", &info->brightness));
+ else if (NULL != oo_attr_angle (xin, attrs, OO_NS_DRAW, "angle", &angle));
+
+ if (name != NULL) {
+ if (angle < 0)
+ angle += 360;
+ angle = ((angle + 22)/45) % 8; /* angle is now 0,1,2,...,7*/
+
+ if (style != NULL && 0 == strcmp (style, "axial"))
+ info->dir = axial_types[angle];
+ else /* linear */
+ info->dir = linear_types[angle];
+
+ g_hash_table_replace (state->chart.gradient_styles,
+ g_strdup (name), info);
+ } else {
+ oo_warning (xin, _("Unnamed gradient style encountered."));
+ g_free (info);
+ }
}
static void
@@ -3918,6 +4013,11 @@ od_style_prop_chart (GsfXMLIn *xin, xmlChar const **attrs)
(style->style_props,
oo_prop_new_string ("fill-hatch-name",
CXML2C(attrs[1])));
+ else if (gsf_xml_in_namecmp (xin, CXML2C (attrs[0]), OO_NS_DRAW, "fill-gradient-name"))
+ style->style_props = g_slist_prepend
+ (style->style_props,
+ oo_prop_new_string ("fill-gradient-name",
+ CXML2C(attrs[1])));
else if (oo_attr_bool (xin, attrs, OO_NS_CHART, "fill-hatch-solid", &btmp))
style->other_props = g_slist_prepend (style->other_props,
oo_prop_new_bool ("fill-hatch-solid", btmp));
@@ -3927,8 +4027,7 @@ od_style_prop_chart (GsfXMLIn *xin, xmlChar const **attrs)
style->style_props = g_slist_prepend
(style->style_props,
oo_prop_new_int ("gnm-pattern", tmp));
- else if (oo_attr_int (xin, attrs, OO_NS_STYLE, "text-rotation-angle", &tmp)) {
- tmp = tmp % 360;
+ else if (oo_attr_angle (xin, attrs, OO_NS_STYLE, "text-rotation-angle", &tmp)) {
style->style_props = g_slist_prepend
(style->style_props,
oo_prop_new_int ("text-rotation-angle", tmp));
@@ -4380,6 +4479,7 @@ od_draw_object (GsfXMLIn *xin, xmlChar const **attrs)
g_hash_table_remove_all (state->chart.graph_styles);
g_hash_table_remove_all (state->chart.hatches);
g_hash_table_remove_all (state->chart.dash_styles);
+ g_hash_table_remove_all (state->chart.gradient_styles);
}
static void
@@ -5560,6 +5660,7 @@ GSF_XML_IN_NODE (START, OFFICE_FONTS, OO_NS_OFFICE, "font-face-decls", GSF_XML_N
GSF_XML_IN_NODE (START, OFFICE_STYLES, OO_NS_OFFICE, "styles", GSF_XML_NO_CONTENT, NULL, NULL),
GSF_XML_IN_NODE (OFFICE_STYLES, DASH, OO_NS_DRAW, "stroke-dash", GSF_XML_NO_CONTENT, &oo_dash, NULL),
GSF_XML_IN_NODE (OFFICE_STYLES, HATCH, OO_NS_DRAW, "hatch", GSF_XML_NO_CONTENT, &oo_hatch, NULL),
+ GSF_XML_IN_NODE (OFFICE_STYLES, GRADIENT, OO_NS_DRAW, "gradient", GSF_XML_NO_CONTENT, &oo_gradient, NULL),
GSF_XML_IN_NODE (OFFICE_STYLES, MARKER, OO_NS_DRAW, "marker", GSF_XML_NO_CONTENT, NULL, NULL),
GSF_XML_IN_NODE (OFFICE_STYLES, STYLE, OO_NS_STYLE, "style", GSF_XML_NO_CONTENT, &oo_style, &oo_style_end),
GSF_XML_IN_NODE (STYLE, TABLE_CELL_PROPS, OO_NS_STYLE, "table-cell-properties", GSF_XML_NO_CONTENT, &oo_style_prop, NULL),
@@ -6876,6 +6977,10 @@ openoffice_file_open (GOFileOpener const *fo, GOIOContext *io_context,
(g_str_hash, g_str_equal,
(GDestroyNotify) g_free,
NULL);
+ state.chart.gradient_styles = g_hash_table_new_full
+ (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_free);
state.cur_style.cells = NULL;
state.cur_style.col_rows = NULL;
state.cur_style.sheets = NULL;
@@ -6979,6 +7084,7 @@ openoffice_file_open (GOFileOpener const *fo, GOIOContext *io_context,
g_hash_table_destroy (state.chart.graph_styles);
g_hash_table_destroy (state.chart.hatches);
g_hash_table_destroy (state.chart.dash_styles);
+ g_hash_table_destroy (state.chart.gradient_styles);
g_hash_table_destroy (state.formats);
g_object_unref (contents);
diff --git a/plugins/openoffice/openoffice-write.c b/plugins/openoffice/openoffice-write.c
index 176c296..7038338 100644
--- a/plugins/openoffice/openoffice-write.c
+++ b/plugins/openoffice/openoffice-write.c
@@ -114,6 +114,7 @@ typedef struct {
GHashTable *graphs;
GHashTable *graph_dashes;
GHashTable *graph_hatches;
+ GHashTable *graph_gradients;
GHashTable *chart_props_hash;
GHashTable *images;
gboolean with_extension;
@@ -3438,6 +3439,65 @@ odf_write_meta_graph (GnmOOExport *state, GsfOutput *child)
/*****************************************************************************/
static void
+odf_write_gradient_info (char const *name, gpointer data, GnmOOExport *state)
+{
+ GOStyle const *style = data;
+ char *color;
+ char const *type = "linear";
+ int angle = 0;
+ struct {
+ unsigned int dir;
+ char const *type;
+ int angle;
+ } gradients[] = {
+ {GO_GRADIENT_N_TO_S,"linear", 180},
+ {GO_GRADIENT_S_TO_N, "linear", 0},
+ {GO_GRADIENT_N_TO_S_MIRRORED, "axial", 180},
+ {GO_GRADIENT_S_TO_N_MIRRORED, "axial", 0},
+ {GO_GRADIENT_W_TO_E, "linear", -90},
+ {GO_GRADIENT_E_TO_W, "linear", 90},
+ {GO_GRADIENT_W_TO_E_MIRRORED, "axial", -90},
+ {GO_GRADIENT_E_TO_W_MIRRORED, "axial", 90},
+ {GO_GRADIENT_NW_TO_SE, "linear", -135},
+ {GO_GRADIENT_SE_TO_NW, "linear", 45},
+ {GO_GRADIENT_NW_TO_SE_MIRRORED, "axial", -135 },
+ {GO_GRADIENT_SE_TO_NW_MIRRORED, "axial", 45},
+ {GO_GRADIENT_NE_TO_SW, "linear", 135},
+ {GO_GRADIENT_SW_TO_NE, "linear", -45},
+ {GO_GRADIENT_SW_TO_NE_MIRRORED, "axial", -45},
+ {GO_GRADIENT_NE_TO_SW_MIRRORED, "axial", 135},
+ };
+ int i;
+
+ gsf_xml_out_start_element (state->xml, DRAW "gradient");
+ gsf_xml_out_add_cstr_unchecked (state->xml, DRAW "name", name);
+
+ color = odf_go_color_to_string (style->fill.pattern.back);
+ gsf_xml_out_add_cstr_unchecked (state->xml, DRAW "start-color", color);
+ g_free (color);
+
+ if (style->fill.gradient.brightness >= 0.0 && state->with_extension)
+ gsf_xml_out_add_float (state->xml, GNMSTYLE "brightness",
+ style->fill.gradient.brightness, -1);
+
+ color = odf_go_color_to_string (style->fill.pattern.fore);
+ gsf_xml_out_add_cstr_unchecked (state->xml, DRAW "end-color", color);
+ g_free (color);
+
+ for (i = 0; i < (int)G_N_ELEMENTS (gradients); i++) {
+ if (gradients[i].dir == style->fill.gradient.dir) {
+ type = gradients[i].type;
+ angle = gradients[i].angle;
+ break;
+ }
+ }
+ gsf_xml_out_add_cstr_unchecked (state->xml, DRAW "style", type);
+ gsf_xml_out_add_int (state->xml, DRAW "angle", angle);
+
+ gsf_xml_out_end_element (state->xml); /* </draw:gradient> */
+}
+
+static void
odf_write_hatch_info (char const *name, gpointer data, GnmOOExport *state)
{
struct {
@@ -3566,6 +3626,7 @@ odf_write_graph_styles (GnmOOExport *state, GsfOutput *child)
g_hash_table_foreach (state->graph_dashes, (GHFunc) odf_write_dash_info, state);
g_hash_table_foreach (state->graph_hatches, (GHFunc) odf_write_hatch_info, state);
+ g_hash_table_foreach (state->graph_gradients, (GHFunc) odf_write_gradient_info, state);
gsf_xml_out_end_element (state->xml); /* </office:styles> */
gsf_xml_out_end_element (state->xml); /* </office:document-styles> */
@@ -3574,7 +3635,6 @@ odf_write_graph_styles (GnmOOExport *state, GsfOutput *child)
state->xml = NULL;
}
-
/*****************************************************************************/
static void
@@ -4447,6 +4507,39 @@ odf_write_label (GnmOOExport *state, GogObject const *axis)
}
static gboolean
+odf_match_gradient (gchar const *key, GOStyle const *old, GOStyle const *new)
+{
+ gboolean result;
+
+ if (old->fill.gradient.brightness != new->fill.gradient.brightness)
+ return FALSE;
+
+ if (old->fill.gradient.brightness >= 0.)
+ result = (old->fill.gradient.brightness == new->fill.gradient.brightness);
+ else
+ result = (old->fill.pattern.fore == new->fill.pattern.fore);
+
+ return (result && (old->fill.gradient.dir == new->fill.gradient.dir) &&
+ (old->fill.pattern.back == new->fill.pattern.back));
+}
+
+static gchar *
+odf_get_gradient_name (GnmOOExport *state, GOStyle const* style)
+{
+ gchar const *grad = g_hash_table_find (state->graph_gradients,
+ (GHRFunc) odf_match_gradient,
+ (gpointer) style);
+ gchar *new_name;
+ if (grad != NULL)
+ return g_strdup (grad);
+
+ new_name = g_strdup_printf ("Gradient-%i", g_hash_table_size (state->graph_gradients));
+ g_hash_table_insert (state->graph_gradients, g_strdup (new_name),
+ (gpointer) style);
+ return new_name;
+}
+
+static gboolean
odf_match_pattern (gchar const *key, GOPattern const *old, GOPattern const *new)
{
return (old->pattern == new->pattern &&
@@ -4475,7 +4568,7 @@ static void
odf_write_gog_style_graphic (GnmOOExport *state, GOStyle const *style)
{
if (style != NULL) {
- char *color;
+ char *color = NULL;
switch (style->fill.type) {
case GO_STYLE_FILL_NONE:
@@ -4483,20 +4576,26 @@ odf_write_gog_style_graphic (GnmOOExport *state, GOStyle const *style)
break;
case GO_STYLE_FILL_PATTERN:
if (style->fill.pattern.pattern == GO_PATTERN_SOLID) {
- color = odf_go_color_to_string (style->fill.pattern.back);
gsf_xml_out_add_cstr (state->xml, DRAW "fill", "solid");
- gsf_xml_out_add_cstr (state->xml, DRAW "fill-color", color);
+ if (!style->fill.auto_back) {
+ color = odf_go_color_to_string (style->fill.pattern.back);
+ gsf_xml_out_add_cstr (state->xml, DRAW "fill-color", color);
+ }
} else if (style->fill.pattern.pattern == GO_PATTERN_FOREGROUND_SOLID) {
- color = odf_go_color_to_string (style->fill.pattern.fore);
gsf_xml_out_add_cstr (state->xml, DRAW "fill", "solid");
- gsf_xml_out_add_cstr (state->xml, DRAW "fill-color", color);
+ if (!style->fill.auto_fore) {
+ color = odf_go_color_to_string (style->fill.pattern.fore);
+ gsf_xml_out_add_cstr (state->xml, DRAW "fill-color", color);
+ }
} else {
gchar *hatch = odf_get_pattern_name (state, style);
- color = odf_go_color_to_string (style->fill.pattern.back);
gsf_xml_out_add_cstr (state->xml, DRAW "fill", "hatch");
gsf_xml_out_add_cstr (state->xml, DRAW "fill-hatch-name",
hatch);
- gsf_xml_out_add_cstr (state->xml, DRAW "fill-color", color);
+ if (!style->fill.auto_back) {
+ color = odf_go_color_to_string (style->fill.pattern.back);
+ gsf_xml_out_add_cstr (state->xml, DRAW "fill-color", color);
+ }
g_free (hatch);
odf_add_bool (state->xml, DRAW "fill-hatch-solid", TRUE);
if (state->with_extension)
@@ -4507,10 +4606,13 @@ odf_write_gog_style_graphic (GnmOOExport *state, GOStyle const *style)
}
g_free (color);
break;
- case GO_STYLE_FILL_GRADIENT:
- gsf_xml_out_add_cstr (state->xml, DRAW "fill", "none");
- /* gsf_xml_out_add_cstr (state->xml, DRAW "fill", "gradient"); */
+ case GO_STYLE_FILL_GRADIENT: {
+ gchar *grad = odf_get_gradient_name (state, style);
+ gsf_xml_out_add_cstr (state->xml, DRAW "fill", "gradient");
+ gsf_xml_out_add_cstr (state->xml, DRAW "fill-gradient-name", grad);
+ g_free (grad);
break;
+ }
case GO_STYLE_FILL_IMAGE:
gsf_xml_out_add_cstr (state->xml, DRAW "fill", "none");
/* gsf_xml_out_add_cstr (state->xml, DRAW "fill", "bitmap"); */
@@ -5311,6 +5413,9 @@ odf_write_graphs (SheetObject *graph, char const *name, GnmOOExport *state)
state->graph_hatches = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify) g_free,
NULL);
+ state->graph_gradients = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ NULL);
state->chart_props_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
NULL, NULL);
odf_fill_chart_props_hash (state);
@@ -5353,6 +5458,8 @@ odf_write_graphs (SheetObject *graph, char const *name, GnmOOExport *state)
state->graph_dashes = NULL;
g_hash_table_unref (state->graph_hatches);
state->graph_hatches = NULL;
+ g_hash_table_unref (state->graph_gradients);
+ state->graph_gradients = NULL;
g_hash_table_unref (state->chart_props_hash);
state->chart_props_hash = NULL;
odf_update_progress (state, state->graph_progress * (3./2.));
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]