[goffice] Make GocPath work and use it in EMF import.
- From: Jean BrÃfort <jbrefort src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [goffice] Make GocPath work and use it in EMF import.
- Date: Fri, 2 Dec 2011 14:51:10 +0000 (UTC)
commit ab4dceceb1b50cb6697eed960a4f0283cf6690a6
Author: Jean Brefort <jean brefort normalesup org>
Date: Fri Dec 2 15:49:51 2011 +0100
Make GocPath work and use it in EMF import.
ChangeLog | 20 ++
goffice/canvas/goc-path.c | 17 +-
goffice/graph/gog-smoothed-curve.c | 2 +-
goffice/utils/go-emf.c | 613 ++++++++++++++++++++++++++++++++++--
goffice/utils/go-path.c | 5 +-
goffice/utils/go-path.h | 2 +-
plugins/plot_barcol/gog-1.5d.c | 4 +-
plugins/smoothing/gog-exp-smooth.c | 2 +-
8 files changed, 635 insertions(+), 30 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 5ee369c..4b60802 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2011-12-02 Jean Brefort <jean brefort normalesup org>
+
+ * goffice/canvas/goc-path.c (goc_path_set_property): make it properly
+ manage the path.
+ * goffice/utils/go-emf.c (go_wmf_read_spoint),
+ (go_wmf_read_lpoint), (go_wmf_read_gocolor), (go_emf_dc_free),
+ (go_emf_convert_coords), (go_emf_polygon), (go_emf_polyline),
+ (go_emf_polybezierto), (go_emf_polylineto), (go_emf_polypolyline),
+ (go_emf_setwindowextex), (go_emf_setwindoworgex),
+ (go_emf_setviewportextex), (go_emf_setviewportorgex),
+ (go_emf_movetoex), (go_emf_intersectcliprect), (go_emf_savedc),
+ (go_emf_restoredc), (go_emf_selectobject), (go_emf_createpen),
+ (go_emf_createbrushindirect), (go_emf_beginpath), (go_emf_endpath),
+ (go_emf_closefigure), (go_emf_fillpath),
+ (go_emf_strokeandfillpath), (go_emf_strokepath),
+ (go_emf_polygon16), (go_emf_polyline16), (go_emf_polybezierto16),
+ (go_emf_polylineto16), (go_emf_parse): implement more.
+ * goffice/utils/go-path.c (go_path_ref): fixed a crasher.
+ * goffice/utils/go-path.h: ditto.
+
2011-12-01 Morten Welinder <terra gnome org>
* goffice/goffice.c: Include generated embedded-ui.c here and call
diff --git a/goffice/canvas/goc-path.c b/goffice/canvas/goc-path.c
index 570ff83..9405745 100644
--- a/goffice/canvas/goc-path.c
+++ b/goffice/canvas/goc-path.c
@@ -33,6 +33,8 @@
* #GocPath implements path drawing in the canvas.
**/
+static GObjectClass *parent_class;
+
enum {
PATH_PROP_0,
PATH_PROP_X,
@@ -66,7 +68,9 @@ goc_path_set_property (GObject *gobject, guint param_id,
break;
case PATH_PROP_PATH:
- path->path = g_value_peek_pointer (value);
+ if (path->path)
+ go_path_free (pth->path);
+ path->path = go_path_ref (g_value_get_boxed (value));
break;
default: G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, param_id, pspec);
@@ -225,13 +229,24 @@ goc_path_init_style (G_GNUC_UNUSED GocStyledItem *item, GOStyle *style)
}
static void
+goc_path_finalize (GObject *obj)
+{
+ GocPpathe *path = GOC_PATH (obj);
+ if (path->path)
+ go_path_free (pth->path);
+ parent_class->finalize (obj);
+}
+
+static void
goc_path_class_init (GocItemClass *item_klass)
{
GObjectClass *obj_klass = (GObjectClass *) item_klass;
GocStyledItemClass *gsi_klass = (GocStyledItemClass *) item_klass;
+ parent_class = g_type_class_peek_parent (item_klass);
gsi_klass->init_style = goc_path_init_style;
+ obj_klass->finalize = goc_path_finalize;
obj_klass->get_property = goc_path_get_property;
obj_klass->set_property = goc_path_set_property;
g_object_class_install_property (obj_klass, PATH_PROP_X,
diff --git a/goffice/graph/gog-smoothed-curve.c b/goffice/graph/gog-smoothed-curve.c
index 6837e25..b367bb8 100644
--- a/goffice/graph/gog-smoothed-curve.c
+++ b/goffice/graph/gog-smoothed-curve.c
@@ -108,7 +108,7 @@ gog_smoothed_curve_class_init (GogObjectClass *gog_klass)
gog_klass->type_name = gog_smoothed_curve_type_name;
gog_klass->parent_changed = gog_smoothed_curve_parent_changed;
gog_klass->view_type = gog_smoothed_curve_view_get_type ();
-
+
#ifdef GOFFICE_WITH_GTK
gog_klass->populate_editor = gog_smoothed_curve_populate_editor;
#endif
diff --git a/goffice/utils/go-emf.c b/goffice/utils/go-emf.c
index 0846bc8..9cbe887 100644
--- a/goffice/utils/go-emf.c
+++ b/goffice/utils/go-emf.c
@@ -701,6 +701,33 @@ typedef struct {
guint16 flag;
} GOWmfPen;
+typedef enum {
+ GO_EMF_OBJ_TYPE_INVALID = 0,
+ GO_EMF_OBJ_TYPE_PEN,
+ GO_EMF_OBJ_TYPE_BRUSH,
+ GO_EMF_OBJ_TYPE_MAX
+} GOEmfObjType;
+
+typedef struct {
+ GOEmfObjType obj_type;
+ guint32 style;
+ double width;
+ GOColor clr;
+} GOEmfPen;
+
+typedef struct {
+ GOEmfObjType obj_type;
+ guint32 style;
+ guint32 hatch;
+ GOColor clr;
+} GOEmfBrush;
+
+typedef union {
+ GOEmfObjType obj_type;
+ GOEmfPen pen;
+
+} GOEmfObject;
+
typedef struct {
guint width;
guint height;
@@ -798,9 +825,13 @@ typedef struct {
GOWmfOperation op;
gboolean fill_bg;
GocGroup *group;
+ GOStyle *style;
+ GOPath *path;
+ gboolean closed_path;
} GOEmfDC;
typedef struct {
+ unsigned version;
GocCanvas *canvas;
GError **error;
guint8 const *data;
@@ -813,6 +844,7 @@ typedef struct {
gboolean is_emf; /* FIXME: might be EPS or WMF */
GOEmfDC *curDC;
GSList *dc_stack;
+ GHashTable *mfobjs;
} GOEmfState;
#define CMM2PTS(x) (((double) x) * 72. / 254.)
@@ -988,14 +1020,14 @@ go_wmf_mr_convcoord (double* x, double* y, GOWmfPage* pg)
}
static void
-go_wmf_read_spoint (guint8 const *src, double* y, double* x)
+go_wmf_read_spoint (guint8 const *src, double *x, double *y)
{
*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)
+go_wmf_read_lpoint (guint8 const *src, double *x, double *y)
{
*x = GSF_LE_GET_GINT32 (src);
*y = GSF_LE_GET_GINT32 (src + 4);
@@ -1123,6 +1155,12 @@ go_wmf_read_color (GsfInput* input, GOWmfColor* clr)
clr->b = *data;
}
+static GOColor
+go_wmf_read_gocolor (guint8 const *data)
+{
+ return GO_COLOR_FROM_RGB (data[0], data[1], data[2]);
+}
+
static int
go_wmf_find_obj (GOWmfPage* pg)
{
@@ -2363,6 +2401,20 @@ go_wmf_init_esc (void)
* EMF parsing code
*****************************************************************************/
+static void go_emf_dc_free (GOEmfDC *dc)
+{
+ if (dc->style)
+ g_object_unref (dc->style);
+ g_free (dc);
+}
+
+static void
+go_emf_convert_coords (GOEmfState *state, double *x, double *y)
+{
+ *x = (*x - state->dx) * state->dw / state->ww;
+ *y = (*y - state->dy) * state->dh / state->wh;
+}
+
static gboolean
go_emf_header (GOEmfState *state)
{
@@ -2398,35 +2450,140 @@ go_emf_polybezier (GOEmfState *state)
static gboolean
go_emf_polygon (GOEmfState *state)
{
+ unsigned nb_pts, n, offset;
+#ifdef DEBUG_EMF_SUPPORT
+ GOWmfRectL rect;
+#endif
+ GocPoints *points;
+ double x, y;
d_(("polygon\n"));
+#ifdef DEBUG_EMF_SUPPORT
+ go_wmf_read_rectl (&rect, state->data);
+#endif
+ d_(("\tbounds: left: %u; right: %u; top:%u bottom:%u\n",
+ rect.left,rect.right, rect.top, rect.bottom));
+ nb_pts = GSF_LE_GET_GUINT32 (state->data + 16);
+ d_(("\t%u points\n", nb_pts));
+ points = goc_points_new (nb_pts);
+ for (n = 0, offset = 20; n < nb_pts; n++, offset += 8) {
+ go_wmf_read_lpoint (state->data + offset, &x, &y);
+ go_emf_convert_coords (state, &x, &y);
+ points->points[n].x = x;
+ points->points[n].y = y;
+ d_(("\tpoint #%u at x=%g y=%g\n", n, x, y));
+ }
+ goc_item_new (state->curDC->group, GOC_TYPE_POLYGON,
+ "points", points,
+ "style", state->curDC->style,
+ NULL);
return TRUE;
}
static gboolean
go_emf_polyline (GOEmfState *state)
{
+ unsigned nb_pts, n, offset;
+#ifdef DEBUG_EMF_SUPPORT
+ GOWmfRectL rect;
+#endif
+ GocPoints *points;
+ double x, y;
d_(("polyline\n"));
+#ifdef DEBUG_EMF_SUPPORT
+ go_wmf_read_rectl (&rect, state->data);
+#endif
+ d_(("\tbounds: left: %u; right: %u; top:%u bottom:%u\n",
+ rect.left,rect.right, rect.top, rect.bottom));
+ nb_pts = GSF_LE_GET_GUINT32 (state->data + 16);
+ d_(("\t%u points\n", nb_pts));
+ points = goc_points_new (nb_pts);
+ for (n = 0, offset = 20; n < nb_pts; n++, offset += 8) {
+ go_wmf_read_lpoint (state->data + offset, &x, &y);
+ go_emf_convert_coords (state, &x, &y);
+ points->points[n].x = x;
+ points->points[n].y = y;
+ d_(("\tpoint #%u at x=%g y=%g\n", n, x, y));
+ }
+ goc_item_new (state->curDC->group, GOC_TYPE_POLYLINE,
+ "points", points,
+ "style", state->curDC->style,
+ NULL);
return TRUE;
}
static gboolean
go_emf_polybezierto (GOEmfState *state)
{
+ unsigned count, n, offset;
+ double x0, y0, x1, y1, x2, y2;
+#ifdef DEBUG_EMF_SUPPORT
+ GOWmfRectL rect;
+#endif
d_(("polybezierto\n"));
+#ifdef DEBUG_EMF_SUPPORT
+ go_wmf_read_rectl (&rect, state->data);
+#endif
+ d_(("\tbounds: left: %u; right: %u; top:%u bottom:%u\n",
+ rect.left,rect.right, rect.top, rect.bottom));
+ count = GSF_LE_GET_GUINT32 (state->data + 16);
+ d_(("\tfound %u points\n", count));
+ if (count % 3 != 0)
+ return FALSE;
+ count /= 3;
+ for (n = 0, offset = 20; n < count; n++, offset += 24) {
+ go_wmf_read_lpoint (state->data + offset, &x0, &y0);
+ go_emf_convert_coords (state, &x0, &y0);
+ go_wmf_read_lpoint (state->data + offset + 8, &x1, &y1);
+ go_emf_convert_coords (state, &x1, &y1);
+ go_wmf_read_lpoint (state->data + offset + 16, &x2, &y2);
+ go_emf_convert_coords (state, &x2, &y2);
+ go_path_curve_to (state->curDC->path, x0, y0, x1, y1, x2, y2);
+ d_(("\tcurve to x0=%g y0=%g x1=%g y1=%g x2=%g y2=%g\n", x0, y0, x1, y1, x2, y2));
+ }
return TRUE;
}
static gboolean
go_emf_polylineto (GOEmfState *state)
{
+ unsigned count, n, offset;
+ double x, y;
+#ifdef DEBUG_EMF_SUPPORT
+ GOWmfRectL rect;
+#endif
d_(("polylineto\n"));
+#ifdef DEBUG_EMF_SUPPORT
+ go_wmf_read_rectl (&rect, state->data);
+#endif
+ d_(("\tbounds: left: %u; right: %u; top:%u bottom:%u\n",
+ rect.left,rect.right, rect.top, rect.bottom));
+ count = GSF_LE_GET_GUINT32 (state->data + 16);
+ d_(("\tfound %u points\n", count));
+ for (n = 0, offset = 20; n < count; n++, offset += 8) {
+ go_wmf_read_lpoint (state->data + offset, &x, &y);
+ go_emf_convert_coords (state, &x, &y);
+ go_path_line_to (state->curDC->path, x, y);
+ d_(("\tline to x=%g y0=%g\n", x, y));
+ }
return TRUE;
}
static gboolean
go_emf_polypolyline (GOEmfState *state)
{
+ unsigned nb_lines, nb_pts;
+#ifdef DEBUG_EMF_SUPPORT
+ GOWmfRectL rect;
+#endif
d_(("polypolyline\n"));
+#ifdef DEBUG_EMF_SUPPORT
+ go_wmf_read_rectl (&rect, state->data);
+#endif
+ d_(("\tbounds: left: %u; right: %u; top:%u bottom:%u\n",
+ rect.left,rect.right, rect.top, rect.bottom));
+ nb_lines = GSF_LE_GET_GUINT32 (state->data + 16);
+ nb_pts = GSF_LE_GET_GUINT32 (state->data + 20);
+ d_(("\t%u points in %u lines\n", nb_pts, nb_lines));
return TRUE;
}
@@ -2440,40 +2597,36 @@ 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));
+ go_wmf_read_lpoint (state->data, &state->ww, &state->wh);
+ d_(("\twindow size: %g x %g\n", state->ww, state->wh));
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));
+ go_wmf_read_lpoint (state->data, &state->wx, &state->wy);
+ d_(("\twindow origin: %g x %g\n", state->wx, state->wy));
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));
+ go_wmf_read_lpoint (state->data, &state->dw, &state->dh);
+ d_(("\tview port size: %g x %g\n", state->dw, state->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));
+ go_wmf_read_lpoint (state->data, &state->dx, &state->dy);
+ d_(("\tview port origin: %g x %g\n", state->dx, state->dy));
return TRUE;
}
@@ -2617,7 +2770,14 @@ go_emf_offsetcliprgn (GOEmfState *state)
static gboolean
go_emf_movetoex (GOEmfState *state)
{
+ double x, y;
d_(("movetoex\n"));
+ if (state->curDC->path == NULL)
+ return FALSE;
+ go_wmf_read_lpoint (state->data, &x, &y);
+ go_emf_convert_coords (state, &x, &y);
+ go_path_move_to (state->curDC->path, x, y);
+ d_(("\tMove to x=%g y=%g\n", x, y));
return TRUE;
}
@@ -2642,7 +2802,7 @@ go_emf_intersectcliprect (GOEmfState *state)
GOPath *path;
d_(("intersectcliprect\n"));
go_wmf_read_rectl (&rect, state->data);
- d_(("clipping rectangle: left=%d top=%d right=%d bottom=%d\n",
+ d_(("\tclipping 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 ();
@@ -2674,6 +2834,7 @@ go_emf_savedc (GOEmfState *state)
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));
+ state->curDC->style = go_style_new ();
return TRUE;
}
@@ -2688,7 +2849,7 @@ go_emf_restoredc (GOEmfState *state)
while (n++ < 0) {
if (state->dc_stack == NULL)
return FALSE;
- g_free (state->curDC);
+ go_emf_dc_free (state->curDC);
state->curDC = state->dc_stack->data;
state->dc_stack = g_slist_delete_link (state->dc_stack, state->dc_stack);
}
@@ -2709,24 +2870,292 @@ go_emf_modifyworldtransform (GOEmfState *state)
return TRUE;
}
+enum {
+ GO_EMF_WHITE_BRUSH = 0x80000000,
+ GO_EMF_LTGRAY_BRUSH = 0x80000001,
+ GO_EMF_GRAY_BRUSH = 0x80000002,
+ GO_EMF_DKGRAY_BRUSH = 0x80000003,
+ GO_EMF_BLACK_BRUSH = 0x80000004,
+ GO_EMF_NULL_BRUSH = 0x80000005,
+ GO_EMF_WHITE_PEN = 0x80000006,
+ GO_EMF_BLACK_PEN = 0x80000007,
+ GO_EMF_NULL_PEN = 0x80000008,
+ GO_EMF_OEM_FIXED_FONT = 0x8000000A,
+ GO_EMF_ANSI_FIXED_FONT = 0x8000000B,
+ GO_EMF_ANSI_VAR_FONT = 0x8000000C,
+ GO_EMF_SYSTEM_FONT = 0x8000000D,
+ GO_EMF_DEVICE_DEFAULT_FONT = 0x8000000E,
+ GO_EMF_DEFAULT_PALETTE = 0x8000000F,
+ GO_EMF_SYSTEM_FIXED_FONT = 0x80000010,
+ GO_EMF_DEFAULT_GUI_FONT = 0x80000011,
+ GO_EMF_DC_BRUSH = 0x80000012,
+ GO_EMF_DC_PEN = 0x80000013
+};
+
static gboolean
go_emf_selectobject (GOEmfState *state)
{
+ GOEmfObject *tool;
+ unsigned index;
d_(("selectobject\n"));
+ index = GSF_LE_GET_GUINT32 (state->data);
+ if (index < 0x80000000) {
+ tool = g_hash_table_lookup (state->mfobjs, GUINT_TO_POINTER (index));
+ if (tool == NULL) {
+ d_(("\tinvalid object of index %u\n", index));
+ return FALSE;
+ }
+ switch (tool->obj_type) {
+ case GO_EMF_OBJ_TYPE_PEN: {
+ GOEmfPen *pen = (GOEmfPen *) tool;
+ state->curDC->style->interesting_fields |= GO_STYLE_LINE;
+ switch (pen->style & 0xff) {
+ case 0:
+ state->curDC->style->line.dash_type = GO_LINE_SOLID;
+ break;
+ case 1:
+ state->curDC->style->line.dash_type = GO_LINE_DASH;
+ break;
+ case 2:
+ state->curDC->style->line.dash_type = GO_LINE_DOT;
+ break;
+ case 3:
+ state->curDC->style->line.dash_type = GO_LINE_DASH_DOT;
+ break;
+ case 4:
+ state->curDC->style->line.dash_type = GO_LINE_DASH_DOT_DOT;
+ break;
+ case 5:
+ state->curDC->style->line.dash_type = GO_LINE_NONE;
+ break;
+ case 6: /* FIXME */
+ case 7: /* FIXME */
+ case 8: /* FIXME */
+ default:
+ state->curDC->style->line.dash_type = GO_LINE_NONE;
+ g_warning ("Invalid pen style");
+ break;
+ }
+ state->curDC->style->line.auto_dash = FALSE;
+ state->curDC->style->line.width = pen->width;
+ state->curDC->style->line.color = pen->clr;
+ state->curDC->style->line.auto_color = FALSE;
+ switch ((pen->style & 0xf00) >> 16) {
+ case 0:
+ state->curDC->style->line.cap = CAIRO_LINE_CAP_ROUND;
+ break;
+ case 1:
+ state->curDC->style->line.cap = CAIRO_LINE_CAP_SQUARE;
+ break;
+ case 2:
+ state->curDC->style->line.cap = CAIRO_LINE_CAP_BUTT;
+ break;
+ }
+ switch ((pen->style & 0xf000) >> 24) {
+ case 0:
+ state->curDC->style->line.join = CAIRO_LINE_JOIN_ROUND;
+ break;
+ case 1:
+ state->curDC->style->line.join = CAIRO_LINE_JOIN_BEVEL;
+ break;
+ case 2:
+ state->curDC->style->line.join = CAIRO_LINE_JOIN_MITER;
+ break;
+ }
+ d_(("\tselected pen #%u\n", index));
+ break;
+ }
+ case GO_EMF_OBJ_TYPE_BRUSH: {
+ GOEmfBrush *brush = (GOEmfBrush *) tool;
+ state->curDC->style->interesting_fields |= GO_STYLE_FILL;
+ state->curDC->style->fill.pattern.pattern = GO_PATTERN_FOREGROUND_SOLID;
+ state->curDC->style->fill.pattern.back = 0;
+ state->curDC->style->fill.pattern.fore = brush->clr;
+ state->curDC->style->fill.auto_back = FALSE;
+ state->curDC->style->fill.auto_fore = FALSE;
+ d_(("\tselected brush #%u\n", index));
+ break;
+ }
+ default:
+ d_(("\tinvalid object type %u\n", tool->obj_type));
+ return FALSE;
+ }
+ } else switch (index) {
+ case GO_EMF_WHITE_BRUSH:
+ d_(("\tWhite brush\n"));
+ break;
+ case GO_EMF_LTGRAY_BRUSH:
+ d_(("\tLight gray brush\n"));
+ break;
+ case GO_EMF_GRAY_BRUSH:
+ d_(("\tGray brush\n"));
+ break;
+ case GO_EMF_DKGRAY_BRUSH:
+ d_(("\tDark gray brush\n"));
+ break;
+ case GO_EMF_BLACK_BRUSH:
+ d_(("\tBlack brush\n"));
+ break;
+ case GO_EMF_NULL_BRUSH:
+ d_(("\tNull brush\n"));
+ break;
+ case GO_EMF_WHITE_PEN:
+ d_(("\tWhite pen\n"));
+ break;
+ case GO_EMF_BLACK_PEN:
+ d_(("\tWhite pen\n"));
+ break;
+ case GO_EMF_NULL_PEN:
+ d_(("\tWhite pen\n"));
+ break;
+ case GO_EMF_OEM_FIXED_FONT:
+ d_(("\tEOM fixed font\n"));
+ break;
+ case GO_EMF_ANSI_FIXED_FONT:
+ d_(("\tANSI fixed font\n"));
+ break;
+ case GO_EMF_ANSI_VAR_FONT:
+ d_(("\tANSI var font\n"));
+ break;
+ case GO_EMF_SYSTEM_FONT:
+ d_(("\tSystem font\n"));
+ break;
+ case GO_EMF_DEVICE_DEFAULT_FONT:
+ d_(("\tDevice default font\n"));
+ break;
+ case GO_EMF_DEFAULT_PALETTE:
+ d_(("\tDefault palette\n"));
+ break;
+ case GO_EMF_SYSTEM_FIXED_FONT:
+ d_(("\tSystem fixed font\n"));
+ break;
+ case GO_EMF_DEFAULT_GUI_FONT:
+ d_(("\tDefault GUI font\n"));
+ break;
+ case GO_EMF_DC_BRUSH:
+ d_(("\tDC brush\n"));
+ break;
+ case GO_EMF_DC_PEN:
+ d_(("\tDC pen\n"));
+ break;
+ default:
+ break;
+ }
return TRUE;
}
static gboolean
go_emf_createpen (GOEmfState *state)
{
+#ifdef DEBUG_EMF_SUPPORT
+char const *dashes[] = {
+"Solid",
+"Dash",
+"Dot",
+"Dash-dot",
+"Dash-dot-dot",
+"None",
+"Inside frame",
+"User style",
+"Alternate"
+};
+char const *join[]= {
+"round",
+"bevel",
+"mitter"
+};
+char const *cap[]= {
+"round",
+"square",
+"flat"
+};
+#endif
+ unsigned index;
+ GOEmfPen *pen = g_new0 (GOEmfPen, 1);
+ pen->obj_type = GO_EMF_OBJ_TYPE_PEN;
d_(("createpen\n"));
- return TRUE;
-}
+ index = GSF_LE_GET_GUINT32 (state->data);
+ pen->style = GSF_LE_GET_GUINT32 (state->data + 4);
+ pen->width = GSF_LE_GET_GUINT32 (state->data + 8);
+ pen->clr = go_wmf_read_gocolor (state->data + 16);
+ d_(("\tpen index=%u style=%s width=%g color=%08x join=%s cap=%s%s\n",index,
+ dashes[pen->style&0xf], pen->width, pen->clr,
+ join[(pen->style&0xf000)>>24], cap[(pen->style&0xf00)>>16],
+ pen->style&0x00010000? "Geometric": ""));
+ g_hash_table_replace (state->mfobjs, GUINT_TO_POINTER (index), pen);
+ return TRUE;
+}
+
+enum {
+ GO_EMF_HS_HORIZONTAL = 0x0000,
+ GO_EMF_HS_VERTICAL = 0x0001,
+ GO_EMF_HS_FDIAGONAL = 0x0002,
+ GO_EMF_HS_BDIAGONAL = 0x0003,
+ GO_EMF_HS_CROSS = 0x0004,
+ GO_EMF_HS_DIAGCROSS = 0x0005,
+ GO_EMF_HS_SOLIDCLR = 0x0006,
+ GO_EMF_HS_DITHEREDCLR = 0x0007,
+ GO_EMF_HS_SOLIDTEXTCLR = 0x0008,
+ GO_EMF_HS_DITHEREDTEXTCLR = 0x0009,
+ GO_EMF_HS_SOLIDBKCLR = 0x000A,
+ GO_EMF_HS_DITHEREDBKCLR = 0x000B
+};
+
+enum {
+ GO_EMF_BS_SOLID = 0x0000,
+ GO_EMF_BS_NULL = 0x0001,
+ GO_EMF_BS_HATCHED = 0x0002,
+ GO_EMF_BS_PATTERN = 0x0003,
+ GO_EMF_BS_INDEXED = 0x0004,
+ GO_EMF_BS_DIBPATTERN = 0x0005,
+ GO_EMF_BS_DIBPATTERNPT = 0x0006,
+ GO_EMF_BS_PATTERN8X8 = 0x0007,
+ GO_EMF_BS_DIBPATTERN8X8 = 0x0008,
+ GO_EMF_BS_MONOPATTERN = 0x0009
+};
static gboolean
go_emf_createbrushindirect (GOEmfState *state)
{
+#ifdef DEBUG_EMF_SUPPORT
+ char const *brushes[] = {
+"BS_SOLID",
+"BS_NULL",
+"BS_HATCHED",
+"BS_PATTERN",
+"BS_INDEXED",
+"BS_DIBPATTERN",
+"BS_DIBPATTERNPT",
+"BS_PATTERN8X8",
+"BS_DIBPATTERN8X8",
+"BS_MONOPATTERN"
+};
+char const *hatches[] = {
+"HORIZONTAL",
+"HS_VERTICAL",
+"HS_FDIAGONAL",
+"HS_BDIAGONAL",
+"HS_CROSS",
+"HS_DIAGCROSS",
+"HS_SOLIDCLR",
+"HS_DITHEREDCLR",
+"HS_SOLIDTEXTCLR",
+"HS_DITHEREDTEXTCLR",
+"HS_SOLIDBKCLR",
+"HS_DITHEREDBKCLR"
+};
+#endif
+ unsigned index;
+ GOEmfBrush *brush = g_new0 (GOEmfBrush, 1);
+ brush->obj_type = GO_EMF_OBJ_TYPE_BRUSH;
d_(("createbrushindirect\n"));
+ index = GSF_LE_GET_GUINT32 (state->data);
+ brush->style = GSF_LE_GET_GUINT32 (state->data + 4);
+ brush->clr = go_wmf_read_gocolor (state->data + 8);
+ brush->hatch = GSF_LE_GET_GUINT32 (state->data + 12);
+ g_hash_table_replace (state->mfobjs, GUINT_TO_POINTER (index), brush);
+ d_(("\tbrush index=%u style=%s color=%08x hatch=%s\n",index,
+ brushes[brush->style],brush->clr,hatches[brush->hatch]));
return TRUE;
}
@@ -2867,6 +3296,10 @@ static gboolean
go_emf_beginpath (GOEmfState *state)
{
d_(("beginpath\n"));
+ if (state->curDC->path != NULL)
+ return FALSE;
+ state->curDC->path = go_path_new ();
+ state->curDC->closed_path = FALSE;
return TRUE;
}
@@ -2874,20 +3307,37 @@ static gboolean
go_emf_endpath (GOEmfState *state)
{
d_(("endpath\n"));
- return TRUE;
+ return state->curDC->path != NULL;
}
static gboolean
go_emf_closefigure (GOEmfState *state)
{
d_(("closefigure\n"));
+ if (state->curDC->path == NULL)
+ return FALSE;
+ go_path_close (state->curDC->path);
+ state->curDC->closed_path = TRUE;
return TRUE;
}
static gboolean
go_emf_fillpath (GOEmfState *state)
{
+ GOStyle *style;
d_(("fillpath\n"));
+ if (state->curDC->path == NULL)
+ return FALSE;
+ style = go_style_dup (state->curDC->style);
+ style->interesting_fields = GO_STYLE_FILL;
+ goc_item_new (state->curDC->group, GOC_TYPE_PATH,
+ "path", state->curDC->path,
+ "style", style,
+ "closed", state->curDC->closed_path,
+ NULL);
+ g_object_unref (style);
+ go_path_free (state->curDC->path);
+ state->curDC->path = NULL;
return TRUE;
}
@@ -2895,13 +3345,34 @@ static gboolean
go_emf_strokeandfillpath (GOEmfState *state)
{
d_(("strokeandfillpath\n"));
+ if (state->curDC->path == NULL)
+ return FALSE;
+ goc_item_new (state->curDC->group, GOC_TYPE_PATH,
+ "path", state->curDC->path,
+ "style", state->curDC->style,
+ "closed", state->curDC->closed_path,
+ NULL);
+ go_path_free (state->curDC->path);
+ state->curDC->path = NULL;
return TRUE;
}
static gboolean
go_emf_strokepath (GOEmfState *state)
{
+ GOStyle *style;
d_(("strokepath\n"));
+ if (state->curDC->path == NULL)
+ return FALSE;
+ style = go_style_dup (state->curDC->style);
+ style->interesting_fields = GO_STYLE_LINE;
+ goc_item_new (state->curDC->group, GOC_TYPE_PATH,
+ "path", state->curDC->path,
+ "style", style,
+ NULL);
+ g_object_unref (style);
+ go_path_free (state->curDC->path);
+ state->curDC->path = NULL;
return TRUE;
}
@@ -3088,28 +3559,121 @@ go_emf_polybezier16 (GOEmfState *state)
static gboolean
go_emf_polygon16 (GOEmfState *state)
{
+ unsigned nb_pts, n, offset;
+#ifdef DEBUG_EMF_SUPPORT
+ GOWmfRectL rect;
+#endif
+ GocPoints *points;
+ double x, y;
d_(("polygon16\n"));
+#ifdef DEBUG_EMF_SUPPORT
+ go_wmf_read_rectl (&rect, state->data);
+#endif
+ d_(("\tbounds: left: %u; right: %u; top:%u bottom:%u\n",
+ rect.left,rect.right, rect.top, rect.bottom));
+ nb_pts = GSF_LE_GET_GUINT32 (state->data + 16);
+ d_(("\t%u points\n", nb_pts));
+ points = goc_points_new (nb_pts);
+ for (n = 0, offset = 20; n < nb_pts; n++, offset += 8) {
+ go_wmf_read_spoint (state->data + offset, &x, &y);
+ go_emf_convert_coords (state, &x, &y);
+ points->points[n].x = x;
+ points->points[n].y = y;
+ d_(("\tpoint #%u at x=%g y=%g\n", n, x, y));
+ }
+ goc_item_new (state->curDC->group, GOC_TYPE_POLYGON,
+ "points", points,
+ "style", state->curDC->style,
+ NULL);
return TRUE;
}
static gboolean
go_emf_polyline16 (GOEmfState *state)
{
+ unsigned nb_pts, n, offset;
+#ifdef DEBUG_EMF_SUPPORT
+ GOWmfRectL rect;
+#endif
+ GocPoints *points;
+ double x, y;
d_(("polyline16\n"));
+#ifdef DEBUG_EMF_SUPPORT
+ go_wmf_read_rectl (&rect, state->data);
+#endif
+ d_(("\tbounds: left: %u; right: %u; top:%u bottom:%u\n",
+ rect.left,rect.right, rect.top, rect.bottom));
+ nb_pts = GSF_LE_GET_GUINT32 (state->data + 16);
+ d_(("\t%u points\n", nb_pts));
+ points = goc_points_new (nb_pts);
+ for (n = 0, offset = 20; n < nb_pts; n++, offset += 8) {
+ go_wmf_read_spoint (state->data + offset, &x, &y);
+ go_emf_convert_coords (state, &x, &y);
+ points->points[n].x = x;
+ points->points[n].y = y;
+ d_(("\tpoint #%u at x=%g y=%g\n", n, x, y));
+ }
+ goc_item_new (state->curDC->group, GOC_TYPE_POLYLINE,
+ "points", points,
+ "style", state->curDC->style,
+ NULL);
return TRUE;
}
static gboolean
go_emf_polybezierto16 (GOEmfState *state)
{
+ unsigned count, n, offset;
+ double x0, y0, x1, y1, x2, y2;
+#ifdef DEBUG_EMF_SUPPORT
+ GOWmfRectL rect;
+#endif
d_(("polybezierto16\n"));
+#ifdef DEBUG_EMF_SUPPORT
+ go_wmf_read_rectl (&rect, state->data);
+#endif
+ d_(("\tbounds: left: %u; right: %u; top:%u bottom:%u\n",
+ rect.left,rect.right, rect.top, rect.bottom));
+ count = GSF_LE_GET_GUINT32 (state->data + 16);
+ d_(("\tfound %u points\n", count));
+ if (count % 3 != 0)
+ return FALSE;
+ count /= 3;
+ for (n = 0, offset = 20; n < count; n++, offset += 12) {
+ go_wmf_read_spoint (state->data + offset, &x0, &y0);
+ go_emf_convert_coords (state, &x0, &y0);
+ go_wmf_read_spoint (state->data + offset + 4, &x1, &y1);
+ go_emf_convert_coords (state, &x1, &y1);
+ go_wmf_read_spoint (state->data + offset + 8, &x2, &y2);
+ go_emf_convert_coords (state, &x2, &y2);
+ go_path_curve_to (state->curDC->path, x0, y0, x1, y1, x2, y2);
+ d_(("\tcurve to x0=%g y0=%g x1=%g y1=%g x2=%g y2=%g\n", x0, y0, x1, y1, x2, y2));
+ }
return TRUE;
}
static gboolean
go_emf_polylineto16 (GOEmfState *state)
{
+ unsigned count, n, offset;
+ double x, y;
+#ifdef DEBUG_EMF_SUPPORT
+ GOWmfRectL rect;
+#endif
d_(("polylineto16\n"));
+#ifdef DEBUG_EMF_SUPPORT
+ go_wmf_read_rectl (&rect, state->data);
+#endif
+ d_(("\tbounds: left: %u; right: %u; top:%u bottom:%u\n",
+ rect.left,rect.right, rect.top, rect.bottom));
+ count = GSF_LE_GET_GUINT32 (state->data + 16);
+ d_(("\tfound %u points\n", count));
+ for (n = 0, offset = 20; n < count; n++, offset += 4) {
+ go_wmf_read_spoint (state->data + offset, &x, &y);
+ go_emf_convert_coords (state, &x, &y);
+ go_path_line_to (state->curDC->path, x, y);
+ d_(("\tline to x=%g y0=%g\n", x, y));
+ }
return TRUE;
}
@@ -3411,12 +3975,16 @@ go_emf_parse (GOEmf *emf, GsfInput *input, GError **error)
return TRUE;
} else if (type == 3) {
GOEmfState state;
+ state.version = 3;
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;
+ state.curDC->style = go_style_new ();
+ state.curDC->group = state.canvas->root;
+ state.mfobjs = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+ NULL, g_free);
offset = 4;
while ((offset += 4) < fsize && rid != 0xe) { /* EOF */
data = gsf_input_read (input, 4, NULL);
@@ -3436,9 +4004,10 @@ go_emf_parse (GOEmf *emf, GsfInput *input, GError **error)
break;
rid = GSF_LE_GET_GUINT32 (data);
}
- g_free (state.curDC);
+ go_emf_dc_free (state.curDC);
+ g_hash_table_destroy (state.mfobjs);
if (state.dc_stack != NULL) {
- g_slist_free_full (state.dc_stack, g_free);
+ g_slist_free_full (state.dc_stack, (GDestroyNotify) go_emf_dc_free);
if (error)
if (*error == NULL)
*error = g_error_new (go_error_invalid (), 0,
diff --git a/goffice/utils/go-path.c b/goffice/utils/go-path.c
index 1922baf..cdbb33c 100644
--- a/goffice/utils/go-path.c
+++ b/goffice/utils/go-path.c
@@ -220,12 +220,13 @@ go_path_free (GOPath *path)
* Increments references count to @path.
**/
-void
+GOPath *
go_path_ref (GOPath *path)
{
- g_return_if_fail (path != NULL);
+ g_return_val_if_fail (path != NULL, NULL);
path->refs++;
+ return path;
}
GType
diff --git a/goffice/utils/go-path.h b/goffice/utils/go-path.h
index be909b9..2a14d23 100644
--- a/goffice/utils/go-path.h
+++ b/goffice/utils/go-path.h
@@ -65,7 +65,7 @@ GType go_path_get_type (void);
GOPath *go_path_new (void);
void go_path_clear (GOPath *path);
-void go_path_ref (GOPath *path);
+GOPath *go_path_ref (GOPath *path);
void go_path_free (GOPath *path);
void go_path_set_options (GOPath *path, GOPathOptions options);
diff --git a/plugins/plot_barcol/gog-1.5d.c b/plugins/plot_barcol/gog-1.5d.c
index 93fd016..8a06c26 100644
--- a/plugins/plot_barcol/gog-1.5d.c
+++ b/plugins/plot_barcol/gog-1.5d.c
@@ -394,7 +394,7 @@ GSF_DYNAMIC_CLASS_ABSTRACT (GogPlot1_5d, gog_plot1_5d,
GOG_TYPE_PLOT)
double _gog_plot1_5d_get_percent_value (GogPlot *plot, unsigned series, unsigned index)
-{
+{
GogPlot1_5d *model = GOG_PLOT1_5D (plot);
GogSeries1_5d const *ser = NULL, *cur;
GSList *ptr;
@@ -414,7 +414,7 @@ double _gog_plot1_5d_get_percent_value (GogPlot *plot, unsigned series, unsigned
for (j = 0; j < cur->base.num_elements; j++)
model->sums[j] += vals[j];
}
-
+
} else
for (ptr = plot->series ; ptr != NULL ; ptr = ptr->next)
if (0 == series--)
diff --git a/plugins/smoothing/gog-exp-smooth.c b/plugins/smoothing/gog-exp-smooth.c
index f8d8526..f6170c0 100644
--- a/plugins/smoothing/gog-exp-smooth.c
+++ b/plugins/smoothing/gog-exp-smooth.c
@@ -213,7 +213,7 @@ gog_exp_smooth_class_init (GogSmoothedCurveClass *curve_klass)
gog_object_klass->update = gog_exp_smooth_update;
gog_object_klass->type_name = gog_exp_smooth_type_name;
- curve_klass->max_dim = 0;
+ curve_klass->max_dim = 0;
g_object_class_install_property (gobject_klass, EXP_SMOOTH_PROP_STEPS,
g_param_spec_int ("steps",
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]