[goffice] Minor canvas enhancements.



commit 3a1ca4172dd30b6ab00ba85a2fce309d1de2c126
Author: Jean Brefort <jean brefort normalesup org>
Date:   Mon Dec 5 08:58:58 2011 +0100

    Minor canvas enhancements.

 ChangeLog                     |   26 +++
 goffice/canvas/goc-group.c    |    8 +-
 goffice/canvas/goc-group.h    |    4 +-
 goffice/canvas/goc-path.c     |   16 ++
 goffice/canvas/goc-path.h     |    1 +
 goffice/canvas/goc-polyline.c |   17 ++-
 goffice/utils/go-emf.c        |  476 ++++++++++++++++++++++++++++++-----------
 7 files changed, 420 insertions(+), 128 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 4e0b829..8be5762 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+2011-12-05  Jean Brefort  <jean brefort normalesup org>
+
+	* goffice/canvas/goc-group.c (goc_group_init): initialize the transform
+	matrix.
+	* goffice/canvas/goc-group.h: add a matrix.
+	* goffice/canvas/goc-path.c (goc_path_set_property),
+	(goc_path_get_property), (goc_path_prepare_draw),
+	(goc_path_class_init): add a fill rule.
+	* goffice/canvas/goc-path.h: ditto.
+	* goffice/canvas/goc-polyline.c (goc_polyline_prepare_draw): skip invalid
+	points so that it supports polypolyline.
+	* goffice/utils/go-emf.c (go_wmf_read_points),
+	(go_wmf_read_pointl), (go_emf_polygon), (go_emf_polyline),
+	(go_emf_polybezierto), (go_emf_polylineto), (go_emf_polypolyline),
+	(go_emf_polypolygon), (go_emf_setwindowextex),
+	(go_emf_setwindoworgex), (go_emf_setviewportextex),
+	(go_emf_setviewportorgex), (go_emf_setpolyfillmode),
+	(go_emf_settextalign), (go_emf_settextcolor), (go_emf_movetoex),
+	(go_emf_selectobject), (go_emf_ellipse), (go_emf_rectangle),
+	(go_emf_fillpath), (go_emf_strokeandfillpath),
+	(go_emf_extcreatefontindirectw), (go_emf_exttextoutw),
+	(go_emf_polygon16), (go_emf_polyline16), (go_emf_polybezierto16),
+	(go_emf_polylineto16), (go_emf_polypolyline16),
+	(go_emf_polypolygon16): more work.
+	
+
 2011-12-04  Morten Welinder  <terra gnome org>
 
 	* goffice/graph/gog-plot-engine.c: Add debug code.
diff --git a/goffice/canvas/goc-group.c b/goffice/canvas/goc-group.c
index f0f57d4..8258631 100644
--- a/goffice/canvas/goc-group.c
+++ b/goffice/canvas/goc-group.c
@@ -266,8 +266,14 @@ goc_group_class_init (GocItemClass *item_klass)
 	item_klass->notify_scrolled = goc_group_notify_scrolled;
 }
 
+static void
+goc_group_init (GocGroup *group)
+{
+	cairo_matrix_init_identity (&group->transform);
+}
+
 GSF_CLASS (GocGroup, goc_group,
-	   goc_group_class_init, NULL,
+	   goc_group_class_init, goc_group_init,
 	   GOC_TYPE_ITEM)
 
 /**
diff --git a/goffice/canvas/goc-group.h b/goffice/canvas/goc-group.h
index 20b51ac..15a1434 100644
--- a/goffice/canvas/goc-group.h
+++ b/goffice/canvas/goc-group.h
@@ -34,6 +34,8 @@ struct _GocGroup {
 	GList			*children;
 	GOPath			*clip_path;
 	cairo_fill_rule_t       clip_rule;
+	cairo_matrix_t		transform; /* not used for now */
+	gboolean		transformed; /* TRUE if the matrix is not identity */
 	gpointer		priv;
 };
 
@@ -45,7 +47,7 @@ struct _GocGroupClass
 	void (*reserved2) (void);
 	void (*reserved3) (void);
 	void (*reserved4) (void);
-};
+};																																																																																																																																																																								
 
 #define GOC_TYPE_GROUP	(goc_group_get_type ())
 #define GOC_GROUP(o)	(G_TYPE_CHECK_INSTANCE_CAST ((o), GOC_TYPE_GROUP, GocGroup))
diff --git a/goffice/canvas/goc-path.c b/goffice/canvas/goc-path.c
index e2fff21..7e5b6ff 100644
--- a/goffice/canvas/goc-path.c
+++ b/goffice/canvas/goc-path.c
@@ -41,6 +41,7 @@ enum {
 	PATH_PROP_Y,
 	PATH_PROP_ROTATION,
 	PATH_PROP_CLOSED,
+	PATH_PROP_FILL_RULE,
 	PATH_PROP_PATH,
 };
 
@@ -67,6 +68,10 @@ goc_path_set_property (GObject *gobject, guint param_id,
 		path->closed = g_value_get_boolean (value);
 		break;
 
+	case PATH_PROP_FILL_RULE:
+		path->fill_rule = g_value_get_boolean (value);
+		break;
+
 	case PATH_PROP_PATH:
 		if (path->path)
 			go_path_free (path->path);
@@ -102,6 +107,10 @@ goc_path_get_property (GObject *gobject, guint param_id,
 		g_value_set_boolean (value, path->closed);
 		break;
 
+	case PATH_PROP_FILL_RULE:
+		g_value_set_boolean (value, path->fill_rule);
+		break;
+
 	case PATH_PROP_PATH:
 		g_value_set_boxed (value, &path->path);
 		break;
@@ -119,6 +128,7 @@ goc_path_prepare_draw (GocItem const *item, cairo_t *cr, gboolean flag)
 	double rsign = sign;
 
 	cairo_save (cr);
+	cairo_set_fill_rule (cr, path->fill_rule);
 	if (1 == flag) {
 		goc_group_cairo_transform (item->parent, cr, path->x , path->y);
 		sign = 1;
@@ -273,6 +283,12 @@ goc_path_class_init (GocItemClass *item_klass)
 			_("The flag for closed path"),
 			FALSE,
 			GSF_PARAM_STATIC | G_PARAM_READWRITE));
+	g_object_class_install_property (obj_klass, PATH_PROP_FILL_RULE,
+		g_param_spec_boolean ("fill-rule",
+				      _("Fill rule"),
+				      _("Set fill rule to winding or even/odd"),
+				      FALSE,
+				      GSF_PARAM_STATIC | G_PARAM_READWRITE));
 	g_object_class_install_property (obj_klass, PATH_PROP_PATH,
 		g_param_spec_boxed ("path",
 			_("Path"),
diff --git a/goffice/canvas/goc-path.h b/goffice/canvas/goc-path.h
index 0df6175..320f210 100644
--- a/goffice/canvas/goc-path.h
+++ b/goffice/canvas/goc-path.h
@@ -32,6 +32,7 @@ struct _GocPath {
 
 	double rotation, x, y;
 	gboolean closed;
+	gboolean fill_rule;
 	GOPath *path;
 	gpointer priv;
 };
diff --git a/goffice/canvas/goc-polyline.c b/goffice/canvas/goc-polyline.c
index e8c58e4..61794cd 100644
--- a/goffice/canvas/goc-polyline.c
+++ b/goffice/canvas/goc-polyline.c
@@ -131,9 +131,20 @@ goc_polyline_prepare_draw (GocItem const *item, cairo_t *cr, gboolean flag)
 			cairo_restore (cr);
 		} else {
 			double sign = (goc_canvas_get_direction (item->canvas) == GOC_DIRECTION_RTL)? -1: 1;
-			for (i = 1; i < polyline->nb_points; i++)
-				cairo_line_to (cr, (polyline->points[i].x - polyline->points[0].x * flag) * sign,
-					polyline->points[i].y - polyline->points[0].y * flag);
+			gboolean prev_valid = TRUE;
+			for (i = 1; i < polyline->nb_points; i++) {
+				if (go_finite (polyline->points[i].x)) {
+					if (prev_valid)
+						cairo_line_to (cr, (polyline->points[i].x - polyline->points[0].x * flag) * sign,
+							polyline->points[i].y - polyline->points[0].y * flag);
+					else {
+						cairo_move_to (cr, (polyline->points[i].x - polyline->points[0].x * flag) * sign,
+							polyline->points[i].y - polyline->points[0].y * flag);
+						prev_valid = TRUE;
+					}
+				} else
+				    prev_valid = FALSE;
+			}
 		}
 
 		return TRUE;
diff --git a/goffice/utils/go-emf.c b/goffice/utils/go-emf.c
index 9cbe887..2de263f 100644
--- a/goffice/utils/go-emf.c
+++ b/goffice/utils/go-emf.c
@@ -705,6 +705,7 @@ typedef enum {
 	GO_EMF_OBJ_TYPE_INVALID = 0,
 	GO_EMF_OBJ_TYPE_PEN,
 	GO_EMF_OBJ_TYPE_BRUSH,
+	GO_EMF_OBJ_TYPE_FONT,
 	GO_EMF_OBJ_TYPE_MAX
 } GOEmfObjType;
 
@@ -722,10 +723,29 @@ typedef struct {
 	GOColor clr;
 } GOEmfBrush;
 
+typedef struct {
+	GOEmfObjType obj_type;
+	int size;
+	int width;
+	int escape;
+	int orient;
+	int weight;
+	gboolean italic;
+	gboolean under;
+	gboolean strike;
+	unsigned charset;
+	unsigned outprec;
+	unsigned clipprec;
+	unsigned quality;
+	unsigned pitch_and_family;
+	char facename[64];
+} GOEmfFont;
+
 typedef union {
 	GOEmfObjType obj_type;
 	GOEmfPen pen;
-
+	GOEmfBrush brush;
+	GOEmfFont font;
 } GOEmfObject;
 
 typedef struct {
@@ -755,10 +775,11 @@ typedef struct {
 
 typedef struct {
 	gpointer name;
-	gint16 size;
-	gint16 weight;
+	double size;
+	gint16 width;
 	gint16 escape;
 	gint16 orient;
+	gint16 weight;
 	gint italic;
 	gint under;
 	gint strike;
@@ -828,6 +849,9 @@ typedef struct {
 	GOStyle *style;
 	GOPath *path;
 	gboolean closed_path;
+	gboolean PolygonFillMode; /* TRUE: winding, FALSE: alternate */
+	unsigned text_align;
+	GOColor text_color;
 } GOEmfDC;
 
 typedef struct {
@@ -1020,14 +1044,14 @@ go_wmf_mr_convcoord (double* x, double* y, GOWmfPage* pg)
 }
 
 static void
-go_wmf_read_spoint (guint8 const *src, double *x, double *y)
+go_wmf_read_points (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 *x, double *y)
+go_wmf_read_pointl (guint8 const *src, double *x, double *y)
 {
 	*x = GSF_LE_GET_GINT32 (src);
 	*y = GSF_LE_GET_GINT32 (src + 4);
@@ -2466,7 +2490,7 @@ go_emf_polygon (GOEmfState *state)
 	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_wmf_read_pointl (state->data + offset, &x, &y);
 		go_emf_convert_coords (state, &x, &y);
 		points->points[n].x = x;
 		points->points[n].y = y;
@@ -2498,7 +2522,7 @@ go_emf_polyline (GOEmfState *state)
 	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_wmf_read_pointl (state->data + offset, &x, &y);
 		go_emf_convert_coords (state, &x, &y);
 		points->points[n].x = x;
 		points->points[n].y = y;
@@ -2531,11 +2555,11 @@ go_emf_polybezierto (GOEmfState *state)
 		return FALSE;
 	count /= 3;
 	for (n = 0, offset = 20; n < count; n++, offset += 24) {
-		go_wmf_read_lpoint (state->data + offset, &x0, &y0);
+		go_wmf_read_pointl (state->data + offset, &x0, &y0);
 		go_emf_convert_coords (state, &x0, &y0);
-		go_wmf_read_lpoint (state->data + offset + 8, &x1, &y1);
+		go_wmf_read_pointl (state->data + offset + 8, &x1, &y1);
 		go_emf_convert_coords (state, &x1, &y1);
-		go_wmf_read_lpoint (state->data + offset + 16, &x2, &y2);
+		go_wmf_read_pointl (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));
@@ -2560,7 +2584,7 @@ go_emf_polylineto (GOEmfState *state)
 	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_wmf_read_pointl (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));
@@ -2571,7 +2595,9 @@ go_emf_polylineto (GOEmfState *state)
 static gboolean
 go_emf_polypolyline (GOEmfState *state)
 {
-	unsigned nb_lines, nb_pts;
+	unsigned nb_lines, nb_pts, n, l, i, nm, offset, loffset;
+	double x, y;
+	GocPoints *points;
 #ifdef DEBUG_EMF_SUPPORT
 	GOWmfRectL rect;
 #endif
@@ -2584,13 +2610,75 @@ go_emf_polypolyline (GOEmfState *state)
 	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));
+	points = goc_points_new (nb_pts + nb_lines - 1);
+	offset = 24 + 4 * nb_lines;
+	loffset = 24;
+	i = 0;
+	l = 0;
+	while (1) {
+		nm = GSF_LE_GET_GUINT32 (state->data + loffset);
+		loffset += 4;
+		for (n = 0; n < nm; n++) {
+			go_wmf_read_pointl (state->data + offset, &x, &y);
+			go_emf_convert_coords (state, &x, &y);
+			points->points[i].x = x;
+			points->points[i++].y = y;
+			d_(("\tpoint #%u at x=%g y=%g\n", n, x, y));
+		}
+		l++;
+		if (l == nb_lines)
+			break;
+		points->points[i].x = go_nan;
+		points->points[i++].y = go_nan;
+	}
+	goc_item_new (state->curDC->group, GOC_TYPE_POLYGON,
+	              "points", points,
+	              "style", state->curDC->style,
+	              NULL);
+	goc_points_unref (points);
 	return TRUE;
 }
 
 static gboolean
 go_emf_polypolygon (GOEmfState *state)
 {
+	unsigned nb_polygons, nb_pts, n, offset;
+	GocPoints *points;
+	GocIntArray *sizes;
+	double x, y;
+#ifdef DEBUG_EMF_SUPPORT
+	GOWmfRectL rect;
+#endif
 	d_(("polypolygon\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_polygons = GSF_LE_GET_GUINT32 (state->data + 16);
+	nb_pts = GSF_LE_GET_GUINT32 (state->data + 20);
+	d_(("\t%u points in %u polygons\n", nb_pts, nb_polygons));
+	sizes = goc_int_array_new (nb_polygons);
+	points = goc_points_new (nb_pts);
+	for (n = 0, offset = 24; n < nb_polygons; n++, offset += 4) {
+		sizes->vals[n] = GSF_LE_GET_GUINT32 (state->data + offset);
+		d_(("\tfound size %u\n", sizes->vals[n]));
+	}
+	for (n = 0; n < nb_pts; n++, offset += 8) {
+		go_wmf_read_pointl (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,
+	              "sizes", sizes,
+	              "fill-rule", !state->curDC->PolygonFillMode,
+	              "style", state->curDC->style,
+	              NULL);
+	goc_int_array_unref (sizes);
+	goc_points_unref (points);
 	return TRUE;
 }
 
@@ -2598,7 +2686,7 @@ static gboolean
 go_emf_setwindowextex (GOEmfState *state)
 {
 	d_(("setwindowextex\n"));
-	go_wmf_read_lpoint (state->data, &state->ww, &state->wh);
+	go_wmf_read_pointl (state->data, &state->ww, &state->wh);
 	d_(("\twindow size: %g x %g\n", state->ww, state->wh));
 	return TRUE;
 }
@@ -2607,7 +2695,7 @@ static gboolean
 go_emf_setwindoworgex (GOEmfState *state)
 {
 	d_(("setwindoworgex\n"));
-	go_wmf_read_lpoint (state->data, &state->wx, &state->wy);
+	go_wmf_read_pointl (state->data, &state->wx, &state->wy);
 	d_(("\twindow origin: %g x %g\n", state->wx, state->wy));
 	return TRUE;
 }
@@ -2616,7 +2704,7 @@ static gboolean
 go_emf_setviewportextex (GOEmfState *state)
 {
 	d_(("setviewportextex\n"));
-	go_wmf_read_lpoint (state->data, &state->dw, &state->dh);
+	go_wmf_read_pointl (state->data, &state->dw, &state->dh);
 	d_(("\tview port size: %g x %g\n", state->dw, state->dh));
 	return TRUE;
 }
@@ -2625,7 +2713,7 @@ static gboolean
 go_emf_setviewportorgex (GOEmfState *state)
 {
 	d_(("setviewportorgex\n"));
-	go_wmf_read_lpoint (state->data, &state->dx, &state->dy);
+	go_wmf_read_pointl (state->data, &state->dx, &state->dy);
 	d_(("\tview port origin: %g x %g\n", state->dx, state->dy));
 	return TRUE;
 }
@@ -2692,6 +2780,8 @@ static gboolean
 go_emf_setpolyfillmode (GOEmfState *state)
 {
 	d_(("setpolyfillmode\n"));
+	state->curDC->PolygonFillMode = GSF_LE_GET_GUINT32 (state->data) != 0;
+	d_(("\tpolygon fill mode is %s\n", state->curDC->PolygonFillMode? "alternate": "winding"));
 	return TRUE;
 }
 
@@ -2736,6 +2826,8 @@ static gboolean
 go_emf_settextalign (GOEmfState *state)
 {
 	d_(("settextalign\n"));
+	state->curDC->text_align = GSF_LE_GET_GUINT32 (state->data);
+	d_(("\talignment=%04x\n", state->curDC->text_align));
 	return TRUE;
 }
 
@@ -2750,6 +2842,8 @@ static gboolean
 go_emf_settextcolor (GOEmfState *state)
 {
 	d_(("settextcolor\n"));
+	state->curDC->text_color = go_wmf_read_gocolor (state->data);
+	d_(("\ttext color=%08x\n", state->curDC->text_color));
 	return TRUE;
 }
 
@@ -2774,7 +2868,7 @@ go_emf_movetoex (GOEmfState *state)
 	d_(("movetoex\n"));
 	if (state->curDC->path == NULL)
 		return FALSE;
-	go_wmf_read_lpoint (state->data, &x, &y);
+	go_wmf_read_pointl (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));
@@ -2976,6 +3070,9 @@ go_emf_selectobject (GOEmfState *state)
 			d_(("\tselected brush #%u\n", index));
 			break;
 		}
+		case GO_EMF_OBJ_TYPE_FONT: {
+			break;
+		}
 		default:
 			d_(("\tinvalid object type %u\n", tool->obj_type));
 			return FALSE;
@@ -3176,14 +3273,40 @@ go_emf_anglearc (GOEmfState *state)
 static gboolean
 go_emf_ellipse (GOEmfState *state)
 {
+	GOWmfRectL rect;
+	double x, y, h, w;
 	d_(("ellipse\n"));
+	go_wmf_read_rectl (&rect, state->data);
+	d_(("\tleft: %u; right: %u; top:%u bottom:%u\n",
+	    rect.left, rect.right, rect.top, rect.bottom));
+	x = rect.left;
+	y = rect.top;
+	go_emf_convert_coords (state, &x, &y);
+	w = rect.right;
+	h = rect.bottom;
+	go_emf_convert_coords (state, &w, &h);
+	goc_item_new (state->curDC->group, GOC_TYPE_ELLIPSE,
+		      "x", x, "y", y, "width", w - x, "height", h - y, NULL);
 	return TRUE;
 }
 
 static gboolean
 go_emf_rectangle (GOEmfState *state)
 {
+	GOWmfRectL rect;
+	double x, y, h, w;
 	d_(("rectangle\n"));
+	go_wmf_read_rectl (&rect, state->data);
+	d_(("\tleft: %u; right: %u; top:%u bottom:%u\n",
+	    rect.left, rect.right, rect.top, rect.bottom));
+	x = rect.left;
+	y = rect.top;
+	go_emf_convert_coords (state, &x, &y);
+	w = rect.right;
+	h = rect.bottom;
+	go_emf_convert_coords (state, &w, &h);
+	goc_item_new (state->curDC->group, GOC_TYPE_RECTANGLE,
+		      "x", x, "y", y, "width", w - x, "height", h - y, NULL);
 	return TRUE;
 }
 
@@ -3334,6 +3457,7 @@ go_emf_fillpath (GOEmfState *state)
 	              "path", state->curDC->path,
 	              "style", style,
 	              "closed", state->curDC->closed_path,
+	              "fill-rule", !state->curDC->PolygonFillMode,
 	              NULL);
 	g_object_unref (style);
 	go_path_free (state->curDC->path);
@@ -3351,6 +3475,7 @@ go_emf_strokeandfillpath (GOEmfState *state)
 	              "path", state->curDC->path,
 	              "style", state->curDC->style,
 	              "closed", state->curDC->closed_path,
+	              "fill-rule", !state->curDC->PolygonFillMode,
 	              NULL);
 	go_path_free (state->curDC->path);
 	state->curDC->path = NULL;
@@ -3531,7 +3656,33 @@ go_emf_stretchdibits (GOEmfState *state)
 static gboolean
 go_emf_extcreatefontindirectw (GOEmfState *state)
 {
+	unsigned index;
+	char *buf;
+	GOEmfFont *font = g_new0 (GOEmfFont, 1);
+	font->obj_type = GO_EMF_OBJ_TYPE_FONT;
 	d_(("extcreatefontindirectw\n"));
+	index = GSF_LE_GET_GUINT32 (state->data);
+	if (state->length > 332) {
+	} else {
+		font->size = GSF_LE_GET_GINT32 (state->data + 4) * state->dh / state->wh;
+		font->width = GSF_LE_GET_GINT32 (state->data + 8);
+		font->escape = GSF_LE_GET_GINT32 (state->data + 12);
+		font->orient = GSF_LE_GET_GINT32 (state->data + 16);
+		font->weight = GSF_LE_GET_GINT32 (state->data + 20);
+		font->italic = GSF_LE_GET_GUINT8 (state->data + 24);
+		font->under = GSF_LE_GET_GUINT8 (state->data + 25);
+		font->strike = GSF_LE_GET_GUINT8 (state->data + 26);
+		font->charset = GSF_LE_GET_GUINT8 (state->data + 27);
+		font->outprec = GSF_LE_GET_GUINT8 (state->data + 28);
+		font->clipprec = GSF_LE_GET_GUINT8 (state->data + 29);
+		font->quality = GSF_LE_GET_GUINT8 (state->data + 30);
+		font->pitch_and_family = GSF_LE_GET_GUINT8 (state->data + 31);
+		buf = g_utf16_to_utf8 ((gunichar2 const *) (state->data + 32), 32, NULL, NULL, NULL);
+		strncpy (font->facename, buf, 64);
+		g_free (buf);
+	}
+	g_hash_table_replace (state->mfobjs, GUINT_TO_POINTER (index), font);
+	d_(("\tfont index=%u face=%s size=%d\n",index,font->facename, font->size));
 	return TRUE;
 }
 
@@ -3545,7 +3696,10 @@ go_emf_exttextouta (GOEmfState *state)
 static gboolean
 go_emf_exttextoutw (GOEmfState *state)
 {
+	unsigned mode;
 	d_(("exttextoutw\n"));
+	mode = GSF_LE_GET_GUINT32 (state->data + 16);
+	d_(("\t graphic mode is %s\n", mode == 1? "compatible": "advanced"));
 	return TRUE;
 }
 
@@ -3575,7 +3729,7 @@ go_emf_polygon16 (GOEmfState *state)
 	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_wmf_read_points (state->data + offset, &x, &y);
 		go_emf_convert_coords (state, &x, &y);
 		points->points[n].x = x;
 		points->points[n].y = y;
@@ -3607,7 +3761,7 @@ go_emf_polyline16 (GOEmfState *state)
 	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_wmf_read_points (state->data + offset, &x, &y);
 		go_emf_convert_coords (state, &x, &y);
 		points->points[n].x = x;
 		points->points[n].y = y;
@@ -3640,11 +3794,11 @@ go_emf_polybezierto16 (GOEmfState *state)
 		return FALSE;
 	count /= 3;
 	for (n = 0, offset = 20; n < count; n++, offset += 12) {
-		go_wmf_read_spoint (state->data + offset, &x0, &y0);
+		go_wmf_read_points (state->data + offset, &x0, &y0);
 		go_emf_convert_coords (state, &x0, &y0);
-		go_wmf_read_spoint (state->data + offset + 4, &x1, &y1);
+		go_wmf_read_points (state->data + offset + 4, &x1, &y1);
 		go_emf_convert_coords (state, &x1, &y1);
-		go_wmf_read_spoint (state->data + offset + 8, &x2, &y2);
+		go_wmf_read_points (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));
@@ -3669,7 +3823,7 @@ go_emf_polylineto16 (GOEmfState *state)
 	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_wmf_read_points (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));
@@ -3680,14 +3834,90 @@ go_emf_polylineto16 (GOEmfState *state)
 static gboolean
 go_emf_polypolyline16 (GOEmfState *state)
 {
+	unsigned nb_lines, nb_pts, n, l, i, nm, offset, loffset;
+	double x, y;
+	GocPoints *points;
+#ifdef DEBUG_EMF_SUPPORT
+	GOWmfRectL rect;
+#endif
 	d_(("polypolyline16\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));
+	points = goc_points_new (nb_pts + nb_lines - 1);
+	offset = 24 + 4 * nb_lines;
+	loffset = 24;
+	i = 0;
+	l = 0;
+	while (1) {
+		nm = GSF_LE_GET_GUINT32 (state->data + loffset);
+		loffset += 4;
+		for (n = 0; n < nm; n++) {
+			go_wmf_read_points (state->data + offset, &x, &y);
+			go_emf_convert_coords (state, &x, &y);
+			points->points[i].x = x;
+			points->points[i++].y = y;
+			d_(("\tpoint #%u at x=%g y=%g\n", n, x, y));
+		}
+		l++;
+		if (l == nb_lines)
+			break;
+		points->points[i].x = go_nan;
+		points->points[i++].y = go_nan;
+	}
+	goc_item_new (state->curDC->group, GOC_TYPE_POLYGON,
+	              "points", points,
+	              "style", state->curDC->style,
+	              NULL);
+	goc_points_unref (points);
 	return TRUE;
 }
 
 static gboolean
 go_emf_polypolygon16 (GOEmfState *state)
 {
+	unsigned nb_polygons, nb_pts, n, offset;
+	GocPoints *points;
+	GocIntArray *sizes;
+	double x, y;
+#ifdef DEBUG_EMF_SUPPORT
+	GOWmfRectL rect;
+#endif
 	d_(("polypolygon16\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_polygons = GSF_LE_GET_GUINT32 (state->data + 16);
+	nb_pts = GSF_LE_GET_GUINT32 (state->data + 20);
+	d_(("\t%u points in %u polygons\n", nb_pts, nb_polygons));
+	sizes = goc_int_array_new (nb_polygons);
+	points = goc_points_new (nb_pts);
+	for (n = 0, offset = 24; n < nb_polygons; n++, offset += 4) {
+		sizes->vals[n] = GSF_LE_GET_GUINT32 (state->data + offset);
+		d_(("\tfound size %u\n", sizes->vals[n]));
+	}
+	for (n = 0; n < nb_pts; n++, offset += 8) {
+		go_wmf_read_points (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,
+	              "sizes", sizes,
+	              "fill-rule", !state->curDC->PolygonFillMode,
+	              "style", state->curDC->style,
+	              NULL);
+	goc_int_array_unref (sizes);
+	goc_points_unref (points);
 	return TRUE;
 }
 
@@ -3765,107 +3995,107 @@ typedef gboolean (*GOEmfHandler) (GOEmfState* state);
 
 static  GOEmfHandler go_emf_handlers[] = {
 	NULL,
-	go_emf_header,			/* 0x0001 */
-	go_emf_polybezier,		/* 0x0002 */
-	go_emf_polygon,			/* 0x0003 */
-	go_emf_polyline,		/* 0x0004 */
-	go_emf_polybezierto,		/* 0x0005 */
-	go_emf_polylineto,		/* 0x0006 */
-	go_emf_polypolyline,		/* 0x0007 */
-	go_emf_polypolygon,		/* 0x0008 */
-	go_emf_setwindowextex,		/* 0x0009 */
-	go_emf_setwindoworgex,		/* 0x000A */
-	go_emf_setviewportextex,	/* 0x000B */
-	go_emf_setviewportorgex,	/* 0x000C */
-	go_emf_setbrushorgex,		/* 0x000D */
-	go_emf_eof,			/* 0x000E */
-	go_emf_setpixelv,		/* 0x000F */
-	go_emf_setmapperflags,		/* 0x0010 */
-	go_emf_setmapmode,		/* 0x0011 */
-	go_emf_setbkmode,		/* 0x0012 */
-	go_emf_setpolyfillmode,		/* 0x0013 */
-	go_emf_setrop2,			/* 0x0014 */
-	go_emf_setstretchbltmode,       /* 0x0015 */
-	go_emf_settextalign,		/* 0x0016 */
-	go_emf_setcoloradjustment,	/* 0x0017 */
-	go_emf_settextcolor,		/* 0x0018 */
-	go_emf_setbkcolor,		/* 0x0019 */
-	go_emf_offsetcliprgn,		/* 0x001A */
-	go_emf_movetoex,		/* 0x001B */
-	go_emf_setmetargn,		/* 0x001C */
-	go_emf_excludecliprect,		/* 0x001D */
-	go_emf_intersectcliprect,	/* 0x001E */
-	go_emf_scaleviewportextex,	/* 0x001F */
-	go_emf_scalewindowextex,	/* 0x0020 */
-	go_emf_savedc,			/* 0x0021 */
-	go_emf_restoredc,		/* 0x0022 */
-	go_emf_setworldtransform,	/* 0x0023 */
-	go_emf_modifyworldtransform,	/* 0x0024 */
-	go_emf_selectobject,		/* 0x0025 */
-	go_emf_createpen,		/* 0x0026 */
-	go_emf_createbrushindirect,	/* 0x0027 */
-	go_emf_deleteobject,		/* 0x0028 */
-	go_emf_anglearc,		/* 0x0029 */
-	go_emf_ellipse,			/* 0x002A */
-	go_emf_rectangle,		/* 0x002B */
-	go_emf_roundrect,		/* 0x002C */
-	go_emf_arc,			/* 0x002D */
-	go_emf_chord,			/* 0x002E */
-	go_emf_pie,			/* 0x002F */
-	go_emf_selectpalette,		/* 0x0030 */
-	go_emf_createpalette,		/* 0x0031 */
-	go_emf_setpaletteentries,	/* 0x0032 */
-	go_emf_resizepalette,		/* 0x0033 */
-	go_emf_realizepalette,		/* 0x0034 */
-	go_emf_extfloodfill,		/* 0x0035 */
-	go_emf_lineto,			/* 0x0036 */
-	go_emf_arcto,			/* 0x0037 */
-	go_emf_polydraw,		/* 0x0038 */
-	go_emf_setarcdirection,		/* 0x0039 */
-	go_emf_setmiterlimit,		/* 0x003A */
-	go_emf_beginpath,		/* 0x003B */
-	go_emf_endpath,			/* 0x003C */
-	go_emf_closefigure,		/* 0x003D */
-	go_emf_fillpath,		/* 0x003E */
-	go_emf_strokeandfillpath,	/* 0x003F */
-	go_emf_strokepath,		/* 0x0040 */
-	go_emf_flattenpath,		/* 0x0041 */
-	go_emf_widenpath,		/* 0x0042 */
-	go_emf_selectclippath,		/* 0x0043 */
-	go_emf_abortpath,		/* 0x0044 */
+	go_emf_header,			/* 0x0001 ok */
+	go_emf_polybezier,		/* 0x0002 todo */
+	go_emf_polygon,			/* 0x0003 ok */
+	go_emf_polyline,		/* 0x0004 ok */
+	go_emf_polybezierto,		/* 0x0005 ok */
+	go_emf_polylineto,		/* 0x0006 ok */
+	go_emf_polypolyline,		/* 0x0007 untested */
+	go_emf_polypolygon,		/* 0x0008 ok */
+	go_emf_setwindowextex,		/* 0x0009 ok */
+	go_emf_setwindoworgex,		/* 0x000A ok */
+	go_emf_setviewportextex,	/* 0x000B ok */
+	go_emf_setviewportorgex,	/* 0x000C ok */
+	go_emf_setbrushorgex,		/* 0x000D todo */
+	go_emf_eof,			/* 0x000E ok */
+	go_emf_setpixelv,		/* 0x000F todo */
+	go_emf_setmapperflags,		/* 0x0010 todo */
+	go_emf_setmapmode,		/* 0x0011 todo */
+	go_emf_setbkmode,		/* 0x0012 todo */
+	go_emf_setpolyfillmode,		/* 0x0013 ok */
+	go_emf_setrop2,			/* 0x0014 todo */
+	go_emf_setstretchbltmode,       /* 0x0015 todo */
+	go_emf_settextalign,		/* 0x0016 ok */
+	go_emf_setcoloradjustment,	/* 0x0017 todo */
+	go_emf_settextcolor,		/* 0x0018 ok */
+	go_emf_setbkcolor,		/* 0x0019 todo */
+	go_emf_offsetcliprgn,		/* 0x001A todo */
+	go_emf_movetoex,		/* 0x001B ok */
+	go_emf_setmetargn,		/* 0x001C todo */
+	go_emf_excludecliprect,		/* 0x001D todo */
+	go_emf_intersectcliprect,	/* 0x001E todo */
+	go_emf_scaleviewportextex,	/* 0x001F todo */
+	go_emf_scalewindowextex,	/* 0x0020 todo */
+	go_emf_savedc,			/* 0x0021 ok */
+	go_emf_restoredc,		/* 0x0022 ok */
+	go_emf_setworldtransform,	/* 0x0023 todo */
+	go_emf_modifyworldtransform,	/* 0x0024 todo */
+	go_emf_selectobject,		/* 0x0025 partial */
+	go_emf_createpen,		/* 0x0026 ok */
+	go_emf_createbrushindirect,	/* 0x0027 ok */
+	go_emf_deleteobject,		/* 0x0028 todo (if needed?) */
+	go_emf_anglearc,		/* 0x0029 todo */
+	go_emf_ellipse,			/* 0x002A untested */
+	go_emf_rectangle,		/* 0x002B untested */
+	go_emf_roundrect,		/* 0x002C todo */
+	go_emf_arc,			/* 0x002D todo */
+	go_emf_chord,			/* 0x002E todo */
+	go_emf_pie,			/* 0x002F todo */
+	go_emf_selectpalette,		/* 0x0030 todo */
+	go_emf_createpalette,		/* 0x0031 todo */
+	go_emf_setpaletteentries,	/* 0x0032 todo */
+	go_emf_resizepalette,		/* 0x0033 todo */
+	go_emf_realizepalette,		/* 0x0034 todo */
+	go_emf_extfloodfill,		/* 0x0035 todo */
+	go_emf_lineto,			/* 0x0036 ok */
+	go_emf_arcto,			/* 0x0037 todo */
+	go_emf_polydraw,		/* 0x0038 todo */
+	go_emf_setarcdirection,		/* 0x0039 todo */
+	go_emf_setmiterlimit,		/* 0x003A todo */
+	go_emf_beginpath,		/* 0x003B ok */
+	go_emf_endpath,			/* 0x003C ok */
+	go_emf_closefigure,		/* 0x003D ok */
+	go_emf_fillpath,		/* 0x003E ok */
+	go_emf_strokeandfillpath,	/* 0x003F ok */
+	go_emf_strokepath,		/* 0x0040 ok */
+	go_emf_flattenpath,		/* 0x0041 todo */
+	go_emf_widenpath,		/* 0x0042 todo */
+	go_emf_selectclippath,		/* 0x0043 todo */
+	go_emf_abortpath,		/* 0x0044 todo */
 	NULL,
-	go_emf_comment,			/* 0x0046 */
-	go_emf_fillrgn,			/* 0x0047 */
-	go_emf_framergn,		/* 0x0048 */
-	go_emf_invertrgn,		/* 0x0049 */
-	go_emf_paintrgn,		/* 0x004A */
-	go_emf_extselectcliprgn,	/* 0x004B */
-	go_emf_bitblt,			/* 0x004C */
-	go_emf_stretchblt,		/* 0x004D */
-	go_emf_maskblt,			/* 0x004E */
-	go_emf_plgblt,			/* 0x004F */
-	go_emf_setdibitstodevice,	/* 0x0050 */
-	go_emf_stretchdibits,		/* 0x0051 */
-	go_emf_extcreatefontindirectw,	/* 0x0052 */
-	go_emf_exttextouta,		/* 0x0053 */
-	go_emf_exttextoutw,		/* 0x0054 */
-	go_emf_polybezier16,		/* 0x0055 */
-	go_emf_polygon16,		/* 0x0056 */
-	go_emf_polyline16,		/* 0x0057 */
-	go_emf_polybezierto16,		/* 0x0058 */
-	go_emf_polylineto16,		/* 0x0059 */
-	go_emf_polypolyline16,		/* 0x005A */
-	go_emf_polypolygon16,		/* 0x005B */
-	go_emf_polydraw16,		/* 0x005C */
-	go_emf_createmonobrush,		/* 0x005D */
-	go_emf_createdibpatternbrushpt,	/* 0x005E */
-	go_emf_extcreatepen,		/* 0x005F */
-	go_emf_polytextouta,		/* 0x0060 */
-	go_emf_polytextoutw,		/* 0x0051 */
-	go_emf_seticmmode,		/* 0x0062 */
-	go_emf_createcolorspace,	/* 0x0063 */
-	go_emf_setcolorspace,		/* 0x0064 */
-	go_emf_deletecolorspace		/* 0x0065 */
+	go_emf_comment,			/* 0x0046 todo (if needed?) */
+	go_emf_fillrgn,			/* 0x0047 todo */
+	go_emf_framergn,		/* 0x0048 todo */
+	go_emf_invertrgn,		/* 0x0049 todo */
+	go_emf_paintrgn,		/* 0x004A todo */
+	go_emf_extselectcliprgn,	/* 0x004B todo */
+	go_emf_bitblt,			/* 0x004C todo */
+	go_emf_stretchblt,		/* 0x004D todo */
+	go_emf_maskblt,			/* 0x004E todo */
+	go_emf_plgblt,			/* 0x004F todo */
+	go_emf_setdibitstodevice,	/* 0x0050 todo */
+	go_emf_stretchdibits,		/* 0x0051 partial */
+	go_emf_extcreatefontindirectw,	/* 0x0052 partial */
+	go_emf_exttextouta,		/* 0x0053 todo */
+	go_emf_exttextoutw,		/* 0x0054 todo */
+	go_emf_polybezier16,		/* 0x0055 todo */
+	go_emf_polygon16,		/* 0x0056 untested */
+	go_emf_polyline16,		/* 0x0057 untested */
+	go_emf_polybezierto16,		/* 0x0058 untested */
+	go_emf_polylineto16,		/* 0x0059 untested */
+	go_emf_polypolyline16,		/* 0x005A untested */
+	go_emf_polypolygon16,		/* 0x005B untested */
+	go_emf_polydraw16,		/* 0x005C todo */
+	go_emf_createmonobrush,		/* 0x005D todo */
+	go_emf_createdibpatternbrushpt,	/* 0x005E todo */
+	go_emf_extcreatepen,		/* 0x005F todo */
+	go_emf_polytextouta,		/* 0x0060 todo */
+	go_emf_polytextoutw,		/* 0x0051 todo */
+	go_emf_seticmmode,		/* 0x0062 todo */
+	go_emf_createcolorspace,	/* 0x0063 todo */
+	go_emf_setcolorspace,		/* 0x0064 todo */
+	go_emf_deletecolorspace		/* 0x0065 todo */
 };
 
 /*****************************************************************************



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]