[goffice] Add new component helper functions.
- From: Jean BrÃfort <jbrefort src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [goffice] Add new component helper functions.
- Date: Sun, 27 Nov 2011 16:34:24 +0000 (UTC)
commit b0606abbbba32178e7ba161bf862ed29a5c3d75d
Author: Jean Brefort <jean brefort normalesup org>
Date: Sun Nov 27 17:33:30 2011 +0100
Add new component helper functions.
ChangeLog | 12 +++
goffice/component/go-component.c | 60 ++++++++++++++++
goffice/component/go-component.h | 4 +
goffice/utils/go-emf.c | 145 ++++++++++++++++++++++++++++++++++++++
4 files changed, 221 insertions(+), 0 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 468ac4b..ff136f6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2011-11-27 Jean Brefort <jean brefort normalesup org>
+
+ * goffice/component/go-component.c (go_component_export_image),
+ (go_component_duplicate): new functions.
+ * goffice/component/go-component.h: ditto.
+ * goffice/utils/go-emf.c (go_wmf_read_spoint),
+ (go_wmf_read_lpoint), (go_emf_setwindowextex),
+ (go_emf_setwindoworgex), (go_emf_setviewportextex),
+ (go_emf_setviewportorgex), (go_emf_setmapmode), (go_emf_setbkmode),
+ (go_emf_setrop2), (go_emf_intersectcliprect), (go_emf_savedc),
+ (go_emf_restoredc), (go_emf_parse): implement some callbacks.
+
2011-11-25 Morten Welinder <terra gnome org>
* goffice/math/go-rangefunc.c (go_range_sumsq, go_range_devsq):
diff --git a/goffice/component/go-component.c b/goffice/component/go-component.c
index 222e4f5..b4d08dd 100644
--- a/goffice/component/go-component.c
+++ b/goffice/component/go-component.c
@@ -796,3 +796,63 @@ void go_component_set_font (GOComponent *component, PangoFontDescription *desc)
if (klass->set_font)
klass->set_font (component, desc);
}
+
+/**
+ * go_component_export_image:
+ * @component: a #GOComponent
+ * @format: image format for export
+ * @output: a #GsfOutput stream
+ * @x_dpi: x resolution of exported graph
+ * @y_dpi: y resolution of exported graph
+ *
+ * Exports an image of @graph in given @format, writing results in a #GsfOutput stream.
+ * If export format type is a bitmap one, it computes image size with x_dpi, y_dpi and
+ * @graph size (see @gog_graph_get_size()).
+ *
+ * returns: %TRUE if export succeed.
+ **/
+
+gboolean
+go_component_export_image (GOComponent *component, GOImageFormat format, GsfOutput *output,
+ double x_dpi, double y_dpi)
+{
+ return FALSE;
+}
+
+GOComponent *
+go_component_duplicate (GOComponent const *component)
+{
+ GOComponent *res;
+ char *buf;
+ int length;
+ void (*clearfunc) (gpointer) = NULL;
+ gpointer user_data = NULL;
+ GValue value;
+ guint i, nbprops;
+ GType prop_type;
+ GParamSpec **specs;
+
+ g_return_val_if_fail (GO_IS_COMPONENT (component), NULL);
+
+ res = go_component_new_by_mime_type (component->mime_type);
+ res->width = component->width;
+ res->height = component->height;
+ /* first copy needed component specific properties */
+ specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (component), &nbprops);
+ for (i = 0; i < nbprops; i++)
+ if (specs[i]->flags & GO_PARAM_PERSISTENT) {
+ prop_type = G_PARAM_SPEC_VALUE_TYPE (specs[i]);
+ memset (&value, 0, sizeof (value));
+ g_value_init (&value, prop_type);
+ g_object_get_property (G_OBJECT (component), specs[i]->name, &value);
+ if (!g_param_value_defaults (specs[i], &value))
+ g_object_set_property (G_OBJECT (res), specs[i]->name, &value);
+ g_value_unset (&value);
+ }
+ /* and now the data */
+ go_component_get_data ((GOComponent *) component, (gpointer) &buf, &length, &clearfunc, &user_data);
+ go_component_set_data (res, buf, length);
+ if (clearfunc)
+ clearfunc ((user_data)? user_data: buf);
+ return res;
+}
diff --git a/goffice/component/go-component.h b/goffice/component/go-component.h
index 26f159a..7a8935d 100644
--- a/goffice/component/go-component.h
+++ b/goffice/component/go-component.h
@@ -121,6 +121,10 @@ void go_component_sax_push_parser (GsfXMLIn *xin, xmlChar const **attrs,
GOSnapshotType go_component_build_snapshot (GOComponent *component);
void const *go_component_get_snapshot (GOComponent *component, GOSnapshotType *type, size_t *length);
+gboolean go_component_export_image (GOComponent *component, GOImageFormat format,
+ GsfOutput *output, double x_dpi, double y_dpi);
+GOComponent *go_component_duplicate (GOComponent const *component);
+
G_END_DECLS
#endif /* GOFFICE_COMPONENT_H */
diff --git a/goffice/utils/go-emf.c b/goffice/utils/go-emf.c
index a6cc9d8..0846bc8 100644
--- a/goffice/utils/go-emf.c
+++ b/goffice/utils/go-emf.c
@@ -763,6 +763,43 @@ go_wmf_read_rectl (GOWmfRectL *rect, guint8 const *data)
rect->bottom = GSF_LE_GET_GINT32 (data + 12);
}
+typedef enum {
+MM_TEXT = 0x01,
+MM_LOMETRIC = 0x02,
+MM_HIMETRIC = 0x03,
+MM_LOENGLISH = 0x04,
+MM_HIENGLISH = 0x05,
+MM_TWIPS = 0x06,
+MM_ISOTROPIC = 0x07,
+MM_ANISOTROPIC = 0x08
+} GOEmfMapMode;
+
+typedef enum
+{
+R2_BLACK = 0x0001,
+R2_NOTMERGEPEN = 0x0002,
+R2_MASKNOTPEN = 0x0003,
+R2_NOTCOPYPEN = 0x0004,
+R2_MASKPENNOT = 0x0005,
+R2_NOT = 0x0006,
+R2_XORPEN = 0x0007,
+R2_NOTMASKPEN = 0x0008,
+R2_MASKPEN = 0x0009,
+R2_NOTXORPEN = 0x000A,
+R2_NOP = 0x000B,
+R2_MERGENOTPEN = 0x000C,
+R2_COPYPEN = 0x000D,
+R2_MERGEPENNOT = 0x000E,
+R2_MERGEPEN = 0x000F,
+R2_WHITE = 0x0010
+} GOWmfOperation;
+
+typedef struct {
+ GOWmfOperation op;
+ gboolean fill_bg;
+ GocGroup *group;
+} GOEmfDC;
+
typedef struct {
GocCanvas *canvas;
GError **error;
@@ -770,9 +807,15 @@ typedef struct {
unsigned length;
GOWmfRectL dubounds; /* bounds in device units */
GOWmfRectL mmbounds; /* bounds in mm/100 */
+ double dx, dy, dw, dh; /* view port in device units */
+ double wx, wy, ww, wh; /* window rectangle in logical unit */
+ GOEmfMapMode map_mode;
gboolean is_emf; /* FIXME: might be EPS or WMF */
+ GOEmfDC *curDC;
+ GSList *dc_stack;
} GOEmfState;
+#define CMM2PTS(x) (((double) x) * 72. / 254.)
static char *
go_wmf_mtextra_to_utf (char *txt)
@@ -945,6 +988,20 @@ go_wmf_mr_convcoord (double* x, double* y, GOWmfPage* pg)
}
static void
+go_wmf_read_spoint (guint8 const *src, double* y, double* x)
+{
+ *x = GSF_LE_GET_GINT16 (src);
+ *y = GSF_LE_GET_GINT16 (src + 2);
+}
+
+static void
+go_wmf_read_lpoint (guint8 const *src, double* y, double* x)
+{
+ *x = GSF_LE_GET_GINT32 (src);
+ *y = GSF_LE_GET_GINT32 (src + 4);
+}
+
+static void
go_wmf_read_point (GsfInput* input, double* y, double* x)
{
const guint8 *data = {0};
@@ -2383,28 +2440,40 @@ go_emf_polypolygon (GOEmfState *state)
static gboolean
go_emf_setwindowextex (GOEmfState *state)
{
+ double dw, dh;
d_(("setwindowextex\n"));
+ go_wmf_read_lpoint (state->data, &dw, &dh);
+ d_(("\twindow size: %g x %g\n", dw, dh));
return TRUE;
}
static gboolean
go_emf_setwindoworgex (GOEmfState *state)
{
+ double dw, dh;
d_(("setwindoworgex\n"));
+ go_wmf_read_lpoint (state->data, &dw, &dh);
+ d_(("\twindow origin: %g x %g\n", dw, dh));
return TRUE;
}
static gboolean
go_emf_setviewportextex (GOEmfState *state)
{
+ double dw, dh;
d_(("setviewportextex\n"));
+ go_wmf_read_lpoint (state->data, &dw, &dh);
+ d_(("\tview port size: %g x %g\n", dw, dh));
return TRUE;
}
static gboolean
go_emf_setviewportorgex (GOEmfState *state)
{
+ double dw, dh;
d_(("setviewportorgex\n"));
+ go_wmf_read_lpoint (state->data, &dw, &dh);
+ d_(("\tview port origin: %g x %g\n", dw, dh));
return TRUE;
}
@@ -2439,7 +2508,21 @@ go_emf_setmapperflags (GOEmfState *state)
static gboolean
go_emf_setmapmode (GOEmfState *state)
{
+#ifdef DEBUG_EMF_SUPPORT
+char const *map_modes[] = {
+ "MM_TEXT",
+"MM_LOMETRIC",
+"MM_HIMETRIC",
+"MM_LOENGLISH",
+"MM_HIENGLISH",
+"MM_TWIPS",
+"MM_ISOTROPIC",
+"MM_ANISOTROPIC"
+};
+#endif
d_(("setmapmode\n"));
+ state->map_mode = GSF_LE_GET_GUINT32 (state->data);
+ d_(("\tmap mode is %s\n", map_modes[state->map_mode-1]));
return TRUE;
}
@@ -2447,6 +2530,8 @@ static gboolean
go_emf_setbkmode (GOEmfState *state)
{
d_(("setbkmode\n"));
+ state->curDC->fill_bg = GSF_LE_GET_GINT32 (state->data) - 1;
+ d_(("\tbackground is %s\n", state->curDC->fill_bg? "filled": "transparent"));
return TRUE;
}
@@ -2460,7 +2545,30 @@ go_emf_setpolyfillmode (GOEmfState *state)
static gboolean
go_emf_setrop2 (GOEmfState *state)
{
+#ifdef DEBUG_EMF_SUPPORT
+char const *ops[] = {
+NULL,
+"R2_BLACK",
+"R2_NOTMERGEPEN",
+"R2_MASKNOTPEN",
+"R2_NOTCOPYPEN",
+"R2_MASKPENNOT",
+"R2_NOT",
+"R2_XORPEN",
+"R2_NOTMASKPEN",
+"R2_MASKPEN",
+"R2_NOTXORPEN",
+"R2_NOP",
+"R2_MERGENOTPEN",
+"R2_COPYPEN",
+"R2_MERGEPENNOT",
+"R2_MERGEPEN",
+"R2_WHITE"
+};
+#endif
d_(("setrop2\n"));
+ state->curDC->op = GSF_LE_GET_GINT32 (state->data);
+ d_(("\toperator is %x i.e. %s\n", state->curDC->op, ops[state->curDC->op]));
return TRUE;
}
@@ -2530,7 +2638,18 @@ go_emf_excludecliprect (GOEmfState *state)
static gboolean
go_emf_intersectcliprect (GOEmfState *state)
{
+ GOWmfRectL rect;
+ GOPath *path;
d_(("intersectcliprect\n"));
+ go_wmf_read_rectl (&rect, state->data);
+ d_(("clipping rectangle: left=%d top=%d right=%d bottom=%d\n",
+ rect.left, rect.top, rect.right, rect.bottom));
+ state->curDC->group = GOC_GROUP (goc_item_new (state->curDC->group, GOC_TYPE_GROUP, NULL));
+ path = state->curDC->group->clip_path = go_path_new ();
+ /* FIXME adjust the coordinates */
+ go_path_rectangle (path, CMM2PTS(rect.left), CMM2PTS(rect.top),
+ CMM2PTS(rect.right - rect.left),
+ CMM2PTS(rect.bottom - rect.top));
return TRUE;
}
@@ -2552,13 +2671,27 @@ static gboolean
go_emf_savedc (GOEmfState *state)
{
d_(("savedc\n"));
+ state->dc_stack = g_slist_prepend (state->dc_stack, state->curDC);
+ state->curDC = g_new (GOEmfDC, 1);
+ memcpy (state->curDC, state->dc_stack->data, sizeof (GOEmfDC));
return TRUE;
}
static gboolean
go_emf_restoredc (GOEmfState *state)
{
+ int n = GSF_LE_GET_GINT32 (state->data);
d_(("restoredc\n"));
+ d_(("\tpoping %d %s\n", -n, n == -1? "context": "contexts"));
+ if (n >= 0)
+ return FALSE;
+ while (n++ < 0) {
+ if (state->dc_stack == NULL)
+ return FALSE;
+ g_free (state->curDC);
+ state->curDC = state->dc_stack->data;
+ state->dc_stack = g_slist_delete_link (state->dc_stack, state->dc_stack);
+ }
return TRUE;
}
@@ -3280,6 +3413,10 @@ go_emf_parse (GOEmf *emf, GsfInput *input, GError **error)
GOEmfState state;
state.canvas = emf->canvas;
state.error = error;
+ state.map_mode = 0;
+ state.dc_stack = NULL;
+ state.curDC = g_new0 (GOEmfDC, 1);
+ state.curDC->group = state.canvas->root;
offset = 4;
while ((offset += 4) < fsize && rid != 0xe) { /* EOF */
data = gsf_input_read (input, 4, NULL);
@@ -3299,6 +3436,14 @@ go_emf_parse (GOEmf *emf, GsfInput *input, GError **error)
break;
rid = GSF_LE_GET_GUINT32 (data);
}
+ g_free (state.curDC);
+ if (state.dc_stack != NULL) {
+ g_slist_free_full (state.dc_stack, g_free);
+ if (error)
+ if (*error == NULL)
+ *error = g_error_new (go_error_invalid (), 0,
+ _("Invalid image data\n"));
+ }
if (rid != 0xe) {
if (error) {
if (*error == NULL)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]