[dia/dia-0-97] Bug 604474 - Outline blanking issue with e.g. Hash symbol
- From: Hans Breuer <hans src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [dia/dia-0-97] Bug 604474 - Outline blanking issue with e.g. Hash symbol
- Date: Sun, 27 Dec 2009 21:34:00 +0000 (UTC)
commit aaf3709de00eed67e25df5e4af7054df5d7a847c
Author: Hans Breuer <hans breuer org>
Date: Sun Dec 27 22:08:58 2009 +0100
Bug 604474 - Outline blanking issue with e.g. Hash symbol
outline.c : some insignificant off-by-one errors and typos
geometry.c(line_crosses_ray) : used by distance_bez_shape_point() but did not consistently count. Thus the detection of the point being inside of the given area did not work reliably.
(merged from master)
lib/geometry.c | 31 +-
objects/standard/outline.c | 1047 ++++++++++++++++++++++----------------------
2 files changed, 533 insertions(+), 545 deletions(-)
---
diff --git a/lib/geometry.c b/lib/geometry.c
index a590296..c6f649a 100644
--- a/lib/geometry.c
+++ b/lib/geometry.c
@@ -198,31 +198,18 @@ distance_line_point(const Point *line_start, const Point *line_end,
return perp_dist;
}
-/* returns 1 iff the line crosses the ray from (-Inf, rayend.y) to rayend */
-static guint
-line_crosses_ray(const Point *line_start,
+/* returns 1 if the line crosses the ray from (-Inf, rayend.y) to rayend */
+static int
+line_crosses_ray(const Point *line_start,
const Point *line_end, const Point *rayend)
{
- coord xpos;
-
- /* swap end points if necessary */
- if (line_start->y > line_end->y) {
- const Point *tmp;
-
- tmp = line_start;
- line_start = line_end;
- line_end = tmp;
- }
- /* if y coords of line do not include rayend.y */
- if (line_start->y > rayend->y || line_end->y < rayend->y)
- return 0;
- /* Avoid division by zero for horizontal case */
- if (line_end->y - line_start->y < 0.00000000001) {
- return (line_end->y - rayend->y < 0.00000000001);
+ if ((line_start->y <= rayend->y && line_end->y > rayend->y) || /* upward crossing */
+ (line_start->y > rayend->y && line_end->y <= rayend->y)) { /* downward crossing */
+ real vt = (rayend->y - line_start->y) / (line_end->y - line_start->y);
+ if (rayend->x < line_start->x + vt * (line_end->x - line_start->x)) /* intersect */
+ return 1;
}
- xpos = line_start->x + (rayend->y - line_start->y) *
- (line_end->x - line_start->x) / (line_end->y - line_start->y);
- return xpos <= rayend->x;
+ return 0;
}
real
diff --git a/objects/standard/outline.c b/objects/standard/outline.c
index 002ca21..cea4d4c 100644
--- a/objects/standard/outline.c
+++ b/objects/standard/outline.c
@@ -1,542 +1,543 @@
-/* Dia -- an diagram creation/manipulation program
- * Copyright (C) 1998 Alexander Larsson
- *
- * outline.c -- cairo based rotateable outline
- * Copyright (C) 2007, Hans Breuer, <Hans Breuer Org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/*!
- * A prototype for text effects with the standard renderer interface.
- * It should be possible to do all those fancy text effects like outline, rotate, ...
- * by converting text to pathes before rendering.
- */
-#include <config.h>
-
-#include "object.h"
-#include "diarenderer.h"
-#include "attributes.h"
-#include "properties.h"
-#include "boundingbox.h"
-
-#include "tool-icons.h"
+/* Dia -- an diagram creation/manipulation program
+ * Copyright (C) 1998 Alexander Larsson
+ *
+ * outline.c -- cairo based rotateable outline
+ * Copyright (C) 2007, Hans Breuer, <Hans Breuer Org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*!
+ * A prototype for text effects with the standard renderer interface.
+ * It should be possible to do all those fancy text effects like outline, rotate, ...
+ * by converting text to pathes before rendering.
+ */
+#include <config.h>
+
+#include "object.h"
+#include "diarenderer.h"
+#include "attributes.h"
+#include "properties.h"
+#include "boundingbox.h"
+
+#include "tool-icons.h"
#ifdef HAVE_CAIRO
#include <cairo.h>
-#ifdef CAIRO_HAS_SVG_SURFACE
+#ifdef CAIRO_HAS_SVG_SURFACE
#include <cairo-svg.h>
-#endif
-
-#define NUM_HANDLES 2
-/* Object definition */
-typedef struct _Outline {
- DiaObject object;
-
- char *name;
- real rotation;
-
- DiaFont *font;
- real font_height;
-
- Color line_color;
- Color fill_color;
- gboolean show_background;
- real line_width;
-
- Handle handles[NUM_HANDLES];
- /* calculated data */
+#endif
+
+#define NUM_HANDLES 2
+/* Object definition */
+typedef struct _Outline {
+ DiaObject object;
+
+ char *name;
+ real rotation;
+
+ DiaFont *font;
+ real font_height;
+
+ Color line_color;
+ Color fill_color;
+ gboolean show_background;
+ real line_width;
+
+ Handle handles[NUM_HANDLES];
+ /* calculated data */
Point ink_rect[4];
cairo_path_t *path;
- struct _Matrix
- {
- real xx;
- real xy;
- real yx;
- real yy;
- } mat;
-} Outline;
-
-/* Type definition */
-static DiaObject *outline_create (Point *startpoint,
- void *user_data,
- Handle **handle1,
- Handle **handle2);
-static DiaObject *
-outline_load(ObjectNode obj_node, int version, const char *filename);
-
-static ObjectTypeOps outline_type_ops =
-{
- (CreateFunc)outline_create,
- (LoadFunc) outline_load,
- (SaveFunc) object_save_using_properties, /* outline_save */
- (GetDefaultsFunc) NULL,
- (ApplyDefaultsFunc) NULL
-};
-
-static DiaObjectType outline_type =
-{
- "Standard - Outline", /* name */
- 0, /* version */
- (char **) outline_icon, /* pixmap */
-
- &outline_type_ops, /* ops */
- NULL, /* pixmap_file */
- 0 /* default_user_data */
-};
-
-/* make accesible from the outside for type regristation */
-DiaObjectType *_outline_type = (DiaObjectType *) &outline_type;
-
-/* Class definition */
-static ObjectChange* outline_move_handle (Outline *outline,
- Handle *handle,
- Point *to, ConnectionPoint *cp,
- HandleMoveReason reason, ModifierKeys modifiers);
-static ObjectChange* outline_move (Outline *outline, Point *to);
-static void outline_select(Outline *outline, Point *clicked_point,
- DiaRenderer *interactive_renderer);
-static void outline_draw(Outline *outline, DiaRenderer *renderer);
-static real outline_distance_from (Outline *outline, Point *point);
-static void outline_update_data (Outline *outline);
-static void outline_destroy (Outline *outline);
-static DiaObject *outline_copy (Outline *outline);
-static DiaMenu *outline_get_object_menu(Outline *outline,
- Point *clickedpoint);
-static PropDescription *outline_describe_props(Outline *outline);
-static void outline_get_props(Outline *outline, GPtrArray *props);
-static void outline_set_props(Outline *outline, GPtrArray *props);
-
-static ObjectOps outline_ops = {
- (DestroyFunc) outline_destroy,
- (DrawFunc) outline_draw,
- (DistanceFunc) outline_distance_from,
- (SelectFunc) outline_select,
- (CopyFunc) outline_copy,
- (MoveFunc) outline_move,
- (MoveHandleFunc) outline_move_handle,
- (GetPropertiesFunc) object_create_props_dialog,
- (ApplyPropertiesDialogFunc) object_apply_props_from_dialog,
- (ObjectMenuFunc) outline_get_object_menu,
- (DescribePropsFunc) outline_describe_props,
- (GetPropsFunc) outline_get_props,
- (SetPropsFunc) outline_set_props,
- (TextEditFunc) 0,
- (ApplyPropertiesListFunc) object_apply_props,
-};
-
-/* Type implementation */
-static void
-outline_init_handles (Outline *outline)
-{
- DiaObject *obj = &outline->object;
- int i;
-
- for (i = 0; i < NUM_HANDLES; ++i) {
- obj->handles[i] = &outline->handles[i];
- obj->handles[i]->type = HANDLE_MAJOR_CONTROL;
- obj->handles[i]->connect_type = HANDLE_CONNECTABLE;
- obj->handles[i]->connected_to = NULL;
- }
-}
-
-/*! Factory function - create default object */
-static DiaObject *
-outline_create (Point *startpoint,
- void *user_data,
- Handle **handle1,
- Handle **handle2)
-{
- Outline *outline;
- DiaObject *obj;
-
- outline = g_new0 (Outline,1);
- obj = &outline->object;
- obj->type = &outline_type;
- obj->ops = &outline_ops;
-
- object_init (obj, NUM_HANDLES, 0);
- obj->position = *startpoint;
-
- outline_init_handles (outline);
-
- attributes_get_default_font (&outline->font, &outline->font_height);
-
- outline->line_width = 0; /* Not: attributes_get_default_linewidth(); it looks ugly */
- outline->line_color = attributes_get_foreground();
- outline->fill_color = attributes_get_background();
- outline->show_background = FALSE;
- outline->name = g_strdup ("?");
- outline->rotation = 0;
-
- *handle1 = outline->object.handles[0];
- *handle2 = outline->object.handles[1];
-
- outline_update_data (outline);
-
- return obj;
-}
-static DiaObject *
-outline_load(ObjectNode obj_node, int version, const char *filename)
-{
- return object_load_using_properties(&outline_type,
- obj_node,version,filename);
-}
-
-/* Class/Object implementation */
-static PropNumData _rotation_range = { 0.0f, 360.0f, 1.0f };
-static PropDescription outline_props[] = {
- OBJECT_COMMON_PROPERTIES,
- { "name", PROP_TYPE_STRING,PROP_FLAG_VISIBLE|PROP_FLAG_DONT_MERGE,
- N_("Text content"),NULL },
- { "rotation", PROP_TYPE_REAL,PROP_FLAG_VISIBLE,
- N_("Rotation"), N_("Angle to rotate the outline"), &_rotation_range},
- /* the default PROP_STD_TEXT_FONT has PROP_FLAG_DONT_SAVE, we need saving */
- PROP_STD_TEXT_FONT_OPTIONS(PROP_FLAG_VISIBLE),
- PROP_STD_TEXT_HEIGHT_OPTIONS(PROP_FLAG_VISIBLE),
- PROP_STD_LINE_WIDTH,
- PROP_STD_LINE_COLOUR,
- PROP_STD_FILL_COLOUR,
- PROP_STD_SHOW_BACKGROUND,
- PROP_DESC_END
-};
-
-static PropOffset outline_offsets[] = {
- OBJECT_COMMON_PROPERTIES_OFFSETS,
- { "name", PROP_TYPE_STRING, offsetof(Outline, name) },
- { "rotation", PROP_TYPE_REAL, offsetof(Outline, rotation) },
- { "text_font",PROP_TYPE_FONT,offsetof(Outline,font) },
- { PROP_STDNAME_TEXT_HEIGHT,PROP_STDTYPE_TEXT_HEIGHT,offsetof(Outline, font_height) },
- { PROP_STDNAME_LINE_WIDTH, PROP_STDTYPE_LINE_WIDTH, offsetof(Outline, line_width) },
- { "line_colour", PROP_TYPE_COLOUR, offsetof(Outline, line_color) },
- { "fill_colour", PROP_TYPE_COLOUR, offsetof(Outline, fill_color) },
- { "show_background", PROP_TYPE_BOOL, offsetof(Outline, show_background) },
- { NULL, 0, 0 }
-};
+ struct _Matrix
+ {
+ real xx;
+ real xy;
+ real yx;
+ real yy;
+ } mat;
+} Outline;
+
+/* Type definition */
+static DiaObject *outline_create (Point *startpoint,
+ void *user_data,
+ Handle **handle1,
+ Handle **handle2);
+static DiaObject *
+outline_load(ObjectNode obj_node, int version, const char *filename);
+
+static ObjectTypeOps outline_type_ops =
+{
+ (CreateFunc)outline_create,
+ (LoadFunc) outline_load,
+ (SaveFunc) object_save_using_properties, /* outline_save */
+ (GetDefaultsFunc) NULL,
+ (ApplyDefaultsFunc) NULL
+};
+
+static DiaObjectType outline_type =
+{
+ "Standard - Outline", /* name */
+ 0, /* version */
+ (char **) outline_icon, /* pixmap */
+
+ &outline_type_ops, /* ops */
+ NULL, /* pixmap_file */
+ 0 /* default_user_data */
+};
+
+/* make accesible from the outside for type regristation */
+DiaObjectType *_outline_type = (DiaObjectType *) &outline_type;
+
+/* Class definition */
+static ObjectChange* outline_move_handle (Outline *outline,
+ Handle *handle,
+ Point *to, ConnectionPoint *cp,
+ HandleMoveReason reason, ModifierKeys modifiers);
+static ObjectChange* outline_move (Outline *outline, Point *to);
+static void outline_select(Outline *outline, Point *clicked_point,
+ DiaRenderer *interactive_renderer);
+static void outline_draw(Outline *outline, DiaRenderer *renderer);
+static real outline_distance_from (Outline *outline, Point *point);
+static void outline_update_data (Outline *outline);
+static void outline_destroy (Outline *outline);
+static DiaObject *outline_copy (Outline *outline);
+static DiaMenu *outline_get_object_menu(Outline *outline,
+ Point *clickedpoint);
+static PropDescription *outline_describe_props(Outline *outline);
+static void outline_get_props(Outline *outline, GPtrArray *props);
+static void outline_set_props(Outline *outline, GPtrArray *props);
+
+static ObjectOps outline_ops = {
+ (DestroyFunc) outline_destroy,
+ (DrawFunc) outline_draw,
+ (DistanceFunc) outline_distance_from,
+ (SelectFunc) outline_select,
+ (CopyFunc) outline_copy,
+ (MoveFunc) outline_move,
+ (MoveHandleFunc) outline_move_handle,
+ (GetPropertiesFunc) object_create_props_dialog,
+ (ApplyPropertiesDialogFunc) object_apply_props_from_dialog,
+ (ObjectMenuFunc) outline_get_object_menu,
+ (DescribePropsFunc) outline_describe_props,
+ (GetPropsFunc) outline_get_props,
+ (SetPropsFunc) outline_set_props,
+ (TextEditFunc) 0,
+ (ApplyPropertiesListFunc) object_apply_props,
+};
+
+/* Type implementation */
+static void
+outline_init_handles (Outline *outline)
+{
+ DiaObject *obj = &outline->object;
+ int i;
+
+ for (i = 0; i < NUM_HANDLES; ++i) {
+ obj->handles[i] = &outline->handles[i];
+ obj->handles[i]->type = HANDLE_MAJOR_CONTROL;
+ obj->handles[i]->connect_type = HANDLE_CONNECTABLE;
+ obj->handles[i]->connected_to = NULL;
+ }
+}
+
+/*! Factory function - create default object */
+static DiaObject *
+outline_create (Point *startpoint,
+ void *user_data,
+ Handle **handle1,
+ Handle **handle2)
+{
+ Outline *outline;
+ DiaObject *obj;
+
+ outline = g_new0 (Outline,1);
+ obj = &outline->object;
+ obj->type = &outline_type;
+ obj->ops = &outline_ops;
+
+ object_init (obj, NUM_HANDLES, 0);
+ obj->position = *startpoint;
+
+ outline_init_handles (outline);
+
+ attributes_get_default_font (&outline->font, &outline->font_height);
+
+ outline->line_width = 0; /* Not: attributes_get_default_linewidth(); it looks ugly */
+ outline->line_color = attributes_get_foreground();
+ outline->fill_color = attributes_get_background();
+ outline->show_background = FALSE;
+ outline->name = g_strdup ("?");
+ outline->rotation = 0;
+
+ *handle1 = outline->object.handles[0];
+ *handle2 = outline->object.handles[1];
+
+ outline_update_data (outline);
+
+ return obj;
+}
+static DiaObject *
+outline_load(ObjectNode obj_node, int version, const char *filename)
+{
+ return object_load_using_properties(&outline_type,
+ obj_node,version,filename);
+}
+
+/* Class/Object implementation */
+static PropNumData _rotation_range = { 0.0f, 360.0f, 1.0f };
+static PropDescription outline_props[] = {
+ OBJECT_COMMON_PROPERTIES,
+ { "name", PROP_TYPE_STRING,PROP_FLAG_VISIBLE|PROP_FLAG_DONT_MERGE,
+ N_("Text content"),NULL },
+ { "rotation", PROP_TYPE_REAL,PROP_FLAG_VISIBLE,
+ N_("Rotation"), N_("Angle to rotate the outline"), &_rotation_range},
+ /* the default PROP_STD_TEXT_FONT has PROP_FLAG_DONT_SAVE, we need saving */
+ PROP_STD_TEXT_FONT_OPTIONS(PROP_FLAG_VISIBLE),
+ PROP_STD_TEXT_HEIGHT_OPTIONS(PROP_FLAG_VISIBLE),
+ PROP_STD_LINE_WIDTH,
+ PROP_STD_LINE_COLOUR,
+ PROP_STD_FILL_COLOUR,
+ PROP_STD_SHOW_BACKGROUND,
+ PROP_DESC_END
+};
+
+static PropOffset outline_offsets[] = {
+ OBJECT_COMMON_PROPERTIES_OFFSETS,
+ { "name", PROP_TYPE_STRING, offsetof(Outline, name) },
+ { "rotation", PROP_TYPE_REAL, offsetof(Outline, rotation) },
+ { "text_font",PROP_TYPE_FONT,offsetof(Outline,font) },
+ { PROP_STDNAME_TEXT_HEIGHT,PROP_STDTYPE_TEXT_HEIGHT,offsetof(Outline, font_height) },
+ { PROP_STDNAME_LINE_WIDTH, PROP_STDTYPE_LINE_WIDTH, offsetof(Outline, line_width) },
+ { "line_colour", PROP_TYPE_COLOUR, offsetof(Outline, line_color) },
+ { "fill_colour", PROP_TYPE_COLOUR, offsetof(Outline, fill_color) },
+ { "show_background", PROP_TYPE_BOOL, offsetof(Outline, show_background) },
+ { NULL, 0, 0 }
+};
/* empty write function */
-static cairo_status_t
-write_nul (void *closure,
- const unsigned char *data,
- unsigned int length)
-{
- return CAIRO_STATUS_SUCCESS;
+static cairo_status_t
+write_nul (void *closure,
+ const unsigned char *data,
+ unsigned int length)
+{
+ return CAIRO_STATUS_SUCCESS;
}
-/*! Not in the object interface but still required */
-static void
-outine_update_handles(Outline *outline)
-{
- DiaObject *obj = &outline->object;
-
- g_return_if_fail (obj->handles != NULL);
- obj->handles[0]->id = HANDLE_RESIZE_NW;
- obj->handles[0]->pos = outline->ink_rect[0];
-
- obj->handles[1]->id = HANDLE_RESIZE_SE;
- obj->handles[1]->pos = outline->ink_rect[2];
-}
-/*! Not in the object interface but very important anyway. Used to recalculate the object data after a change */
-static void
-outline_update_data (Outline *outline)
-{
- DiaObject *obj = &outline->object;
+/*! Not in the object interface but still required */
+static void
+outine_update_handles(Outline *outline)
+{
+ DiaObject *obj = &outline->object;
+
+ g_return_if_fail (obj->handles != NULL);
+ obj->handles[0]->id = HANDLE_RESIZE_NW;
+ obj->handles[0]->pos = outline->ink_rect[0];
+
+ obj->handles[1]->id = HANDLE_RESIZE_SE;
+ obj->handles[1]->pos = outline->ink_rect[2];
+}
+/*! Not in the object interface but very important anyway. Used to recalculate the object data after a change */
+static void
+outline_update_data (Outline *outline)
+{
+ DiaObject *obj = &outline->object;
/* calculate the ink_rect from two points and the given rotation */
- cairo_t *cr;
- cairo_surface_t *surface;
- cairo_text_extents_t extents;
- real x, y;
- DiaFontStyle style;
-
- if (outline->path)
- cairo_path_destroy (outline->path);
- outline->path = NULL;
+ cairo_t *cr;
+ cairo_surface_t *surface;
+ cairo_text_extents_t extents;
+ real x, y;
+ DiaFontStyle style;
+
+ if (outline->path)
+ cairo_path_destroy (outline->path);
+ outline->path = NULL;
/* surface will not be used to render anything, it is just to create the cairo context */
-#ifdef CAIRO_HAS_SVG_SURFACE
+#ifdef CAIRO_HAS_SVG_SURFACE
surface = cairo_svg_surface_create_for_stream (write_nul, NULL, 100, 100);
#else
/* if only I could remember why I have choosen the svg surface in the first place */
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 100, 100);
-#endif
- cr = cairo_create (surface);
- cairo_surface_destroy (surface); /* in fact: unref() */
- style = dia_font_get_style (outline->font);
- /* not exact matching but almost the best we can do with the toy api */
- cairo_select_font_face (cr, dia_font_get_family (outline->font),
- DIA_FONT_STYLE_GET_SLANT (style) == DIA_FONT_NORMAL ? CAIRO_FONT_SLANT_NORMAL : CAIRO_FONT_SLANT_ITALIC,
- DIA_FONT_STYLE_GET_WEIGHT (style) < DIA_FONT_MEDIUM ? CAIRO_FONT_SLANT_NORMAL : CAIRO_FONT_WEIGHT_BOLD);
- cairo_set_font_size (cr, outline->font_height);
- cairo_text_extents (cr, outline->name, &extents);
-
- /* unfortunately this has no effect on the returned path? See below. */
- cairo_rotate (cr, outline->rotation/(2*G_PI));
-
- outline->mat.xx = cos(G_PI*outline->rotation/180);
- outline->mat.xy = sin(G_PI*outline->rotation/180);
- outline->mat.yx = -sin(G_PI*outline->rotation/180);
- outline->mat.yy = cos(G_PI*outline->rotation/180);
-
- /* fix point */
- outline->ink_rect[0].x = x = obj->position.x;
- outline->ink_rect[0].y = y = obj->position.y;
- /* handle rotation */
- outline->ink_rect[1].x = x + extents.width * outline->mat.xx;
- outline->ink_rect[1].y = y + extents.width * outline->mat.yx;
- outline->ink_rect[2].x = x + extents.width * outline->mat.xx + extents.height * outline->mat.xy;
- outline->ink_rect[2].y = y + extents.width * outline->mat.yx + extents.height * outline->mat.yy;
- outline->ink_rect[3].x = x + extents.height * outline->mat.xy;
- outline->ink_rect[3].y = y + extents.height * outline->mat.yy;
- /* x_advance? */
- /* calculate bounding box */
- {
- PolyBBExtras bbex = {0, 0, outline->line_width/2, 0, 0 };
- polyline_bbox (&outline->ink_rect[0], 4, &bbex, TRUE, &obj->bounding_box);
- }
-
- outine_update_handles (outline),
-
- cairo_move_to (cr, -extents.x_bearing, -extents.y_bearing);
-
-#if 0
- /* reset the matrix to not yet change the outline_draw method */
- outline->mat.xx = 1.0;
- outline->mat.xy = 0.0;
- outline->mat.yx = 0.0;
- outline->mat.yy = 1.0;
-#endif
-
- cairo_text_path (cr, outline->name);
- /* reset the rotation to not have the path rotated back and forth: no effect */
- cairo_rotate (cr, 0.0);
- outline->path = cairo_copy_path (cr);
- /* the cairo context is only used in this fuinction */
+#endif
+ cr = cairo_create (surface);
+ cairo_surface_destroy (surface); /* in fact: unref() */
+ style = dia_font_get_style (outline->font);
+ /* not exact matching but almost the best we can do with the toy api */
+ cairo_select_font_face (cr, dia_font_get_family (outline->font),
+ DIA_FONT_STYLE_GET_SLANT (style) == DIA_FONT_NORMAL ? CAIRO_FONT_SLANT_NORMAL : CAIRO_FONT_SLANT_ITALIC,
+ DIA_FONT_STYLE_GET_WEIGHT (style) < DIA_FONT_MEDIUM ? CAIRO_FONT_SLANT_NORMAL : CAIRO_FONT_WEIGHT_BOLD);
+ cairo_set_font_size (cr, outline->font_height);
+ cairo_text_extents (cr, outline->name, &extents);
+
+ /* unfortunately this has no effect on the returned path? See below. */
+ cairo_rotate (cr, outline->rotation/(2*G_PI));
+
+ outline->mat.xx = cos(G_PI*outline->rotation/180);
+ outline->mat.xy = sin(G_PI*outline->rotation/180);
+ outline->mat.yx = -sin(G_PI*outline->rotation/180);
+ outline->mat.yy = cos(G_PI*outline->rotation/180);
+
+ /* fix point */
+ outline->ink_rect[0].x = x = obj->position.x;
+ outline->ink_rect[0].y = y = obj->position.y;
+ /* handle rotation */
+ outline->ink_rect[1].x = x + extents.width * outline->mat.xx;
+ outline->ink_rect[1].y = y + extents.width * outline->mat.yx;
+ outline->ink_rect[2].x = x + extents.width * outline->mat.xx + extents.height * outline->mat.xy;
+ outline->ink_rect[2].y = y + extents.width * outline->mat.yx + extents.height * outline->mat.yy;
+ outline->ink_rect[3].x = x + extents.height * outline->mat.xy;
+ outline->ink_rect[3].y = y + extents.height * outline->mat.yy;
+ /* x_advance? */
+ /* calculate bounding box */
+ {
+ PolyBBExtras bbex = {0, 0, outline->line_width/2, 0, 0 };
+ polyline_bbox (&outline->ink_rect[0], 4, &bbex, TRUE, &obj->bounding_box);
+ }
+
+ outine_update_handles (outline),
+
+ cairo_move_to (cr, -extents.x_bearing, -extents.y_bearing);
+
+#if 0
+ /* reset the matrix to not yet change the outline_draw method */
+ outline->mat.xx = 1.0;
+ outline->mat.xy = 0.0;
+ outline->mat.yx = 0.0;
+ outline->mat.yy = 1.0;
+#endif
+
+ cairo_text_path (cr, outline->name);
+ /* reset the rotation to not have the path rotated back and forth: no effect */
+ cairo_rotate (cr, 0.0);
+ outline->path = cairo_copy_path (cr);
+ /* the cairo context is only used in this fuinction */
cairo_destroy (cr);
-}
-static void
-outline_draw(Outline *outline, DiaRenderer *renderer)
-{
- DiaObject *obj = &outline->object;
- int i, n = 0, total;
- BezPoint *pts;
- real x, y;
- Point ps = {0, 0}; /* silence gcc */
-
- if (!outline->path)
- return;
- DIA_RENDERER_GET_CLASS (renderer)->set_linewidth (renderer, outline->line_width);
- DIA_RENDERER_GET_CLASS (renderer)->set_linestyle (renderer, LINESTYLE_SOLID);
- DIA_RENDERER_GET_CLASS (renderer)->set_linejoin(renderer, LINEJOIN_MITER);
- DIA_RENDERER_GET_CLASS (renderer)->set_linecaps(renderer, LINECAPS_ROUND);
-
- /* the cairo text path is position independent, Dia's bezier are not */
- x = obj->position.x;
- y = obj->position.y;
-
- /* count Dia BezPoints required */
- total = 0;
- for (i=0; i < outline->path->num_data; i += outline->path->data[i].header.length) {
- ++total;
- }
-
- pts = g_alloca (sizeof(BezPoint)*(total));
- for (i=0; i < outline->path->num_data; i += outline->path->data[i].header.length) {
- cairo_path_data_t *data = &outline->path->data[i];
- if (CAIRO_PATH_MOVE_TO == data->header.type) {
- /* Dia can't handle moveto except at start: corrected below */
- pts[n].type = BEZ_MOVE_TO;
- ps.x = pts[n].p1.x = data[1].point.x * outline->mat.xx + data[1].point.y * outline->mat.xy + x;
- ps.y = pts[n].p1.y = data[1].point.x * outline->mat.yx + data[1].point.y * outline->mat.yy + y;
- ++n;
- } else if (CAIRO_PATH_LINE_TO == data->header.type) {
- pts[n].type = BEZ_LINE_TO;
- pts[n].p1.x = data[1].point.x * outline->mat.xx + data[1].point.y * outline->mat.xy + x;
- pts[n].p1.y = data[1].point.x * outline->mat.yx + data[1].point.y * outline->mat.yy + y;
- ++n;
- } else if (CAIRO_PATH_CURVE_TO == data->header.type) {
- pts[n].type = BEZ_CURVE_TO;
- pts[n].p1.x = data[1].point.x * outline->mat.xx + data[1].point.y * outline->mat.xy + x;
- pts[n].p1.y = data[1].point.x * outline->mat.yx + data[1].point.y * outline->mat.yy + y;
- pts[n].p2.x = data[2].point.x * outline->mat.xx + data[2].point.y * outline->mat.xy + x;
- pts[n].p2.y = data[2].point.x * outline->mat.yx + data[2].point.y * outline->mat.yy + y;
- pts[n].p3.x = data[3].point.x * outline->mat.xx + data[3].point.y * outline->mat.xy + x;
- pts[n].p3.y = data[3].point.x * outline->mat.yx + data[3].point.y * outline->mat.yy + y;
- ++n;
- } else if (CAIRO_PATH_CLOSE_PATH == data->header.type) {
- pts[n].type = BEZ_LINE_TO;
- pts[n].p1.x = ps.x;
- pts[n].p1.y = ps.y;
- ++n;
- }
- }
- /* split the path data into piece which can be handled by Dia's bezier rendering */
- if (outline->show_background) {
- /* first draw the fills */
- int s1 = 0, n1 = 0;
- int s2 = 0;
- for (i = 1; i < total; ++i) {
- if (BEZ_MOVE_TO == pts[i].type) {
- /* check wether any point of the second outline is within the first outline.
- * If so it need to be subtracted - currently blanked. */
- real dist = distance_bez_shape_point (&pts[s1],
- n1 > 0 ? n1 : i - s1 - 1, 0, &pts[i].p1);
- if (s2 > s1) { /* blanking the previous one */
- n = i - s2 - 1;
- DIA_RENDERER_GET_CLASS (renderer)->fill_bezier (renderer, &pts[s2], n, &color_white);
- } else { /* fill the outer shape */
- n1 = n = i - s1 - 1;
- DIA_RENDERER_GET_CLASS (renderer)->fill_bezier (renderer, &pts[s1], n, &outline->fill_color);
- }
- if (dist > 0) { /* remember as new outer outline */
- s1 = i;
- n1 = 0;
- s2 = 0;
- } else {
- s2 = i;
- }
- }
- }
- /* the last one is not drawn yet */
- if (s2 > s1) { /* blanking the previous one */
- if (s2 - i - 1 > 1) /* depending on the above we may be ready */
- DIA_RENDERER_GET_CLASS (renderer)->fill_bezier (renderer, &pts[s2], s2 - i - 1, &color_white);
- } else {
- if (s1 - i - 1 > 1)
- DIA_RENDERER_GET_CLASS (renderer)->fill_bezier (renderer, &pts[s1], s1 - i - 1, &outline->fill_color);
- }
- } /* show_background */
- n = 0;
- for (i = 1; i < total; ++i) {
- if (BEZ_MOVE_TO == pts[i].type) {
- DIA_RENDERER_GET_CLASS (renderer)->draw_bezier (renderer, &pts[n], i - n, &outline->line_color);
- n = i;
- }
- }
- /* the last one, if there is one */
- if (i - n - 1 > 0)
+}
+static void
+outline_draw(Outline *outline, DiaRenderer *renderer)
+{
+ DiaObject *obj = &outline->object;
+ int i, n = 0, total;
+ BezPoint *pts;
+ real x, y;
+ Point ps = {0, 0}; /* silence gcc */
+
+ if (!outline->path)
+ return;
+ DIA_RENDERER_GET_CLASS (renderer)->set_linewidth (renderer, outline->line_width);
+ DIA_RENDERER_GET_CLASS (renderer)->set_linestyle (renderer, LINESTYLE_SOLID);
+ DIA_RENDERER_GET_CLASS (renderer)->set_linejoin(renderer, LINEJOIN_MITER);
+ DIA_RENDERER_GET_CLASS (renderer)->set_linecaps(renderer, LINECAPS_ROUND);
+
+ /* the cairo text path is position independent, Dia's bezier are not */
+ x = obj->position.x;
+ y = obj->position.y;
+
+ /* count Dia BezPoints required */
+ total = 0;
+ for (i=0; i < outline->path->num_data; i += outline->path->data[i].header.length) {
+ ++total;
+ }
+
+ pts = g_alloca (sizeof(BezPoint)*(total));
+ for (i=0; i < outline->path->num_data; i += outline->path->data[i].header.length) {
+ cairo_path_data_t *data = &outline->path->data[i];
+ if (CAIRO_PATH_MOVE_TO == data->header.type) {
+ /* Dia can't handle moveto except at start: corrected below */
+ pts[n].type = BEZ_MOVE_TO;
+ ps.x = pts[n].p1.x = data[1].point.x * outline->mat.xx + data[1].point.y * outline->mat.xy + x;
+ ps.y = pts[n].p1.y = data[1].point.x * outline->mat.yx + data[1].point.y * outline->mat.yy + y;
+ ++n;
+ } else if (CAIRO_PATH_LINE_TO == data->header.type) {
+ pts[n].type = BEZ_LINE_TO;
+ pts[n].p1.x = data[1].point.x * outline->mat.xx + data[1].point.y * outline->mat.xy + x;
+ pts[n].p1.y = data[1].point.x * outline->mat.yx + data[1].point.y * outline->mat.yy + y;
+ ++n;
+ } else if (CAIRO_PATH_CURVE_TO == data->header.type) {
+ pts[n].type = BEZ_CURVE_TO;
+ pts[n].p1.x = data[1].point.x * outline->mat.xx + data[1].point.y * outline->mat.xy + x;
+ pts[n].p1.y = data[1].point.x * outline->mat.yx + data[1].point.y * outline->mat.yy + y;
+ pts[n].p2.x = data[2].point.x * outline->mat.xx + data[2].point.y * outline->mat.xy + x;
+ pts[n].p2.y = data[2].point.x * outline->mat.yx + data[2].point.y * outline->mat.yy + y;
+ pts[n].p3.x = data[3].point.x * outline->mat.xx + data[3].point.y * outline->mat.xy + x;
+ pts[n].p3.y = data[3].point.x * outline->mat.yx + data[3].point.y * outline->mat.yy + y;
+ ++n;
+ } else if (CAIRO_PATH_CLOSE_PATH == data->header.type) {
+ pts[n].type = BEZ_LINE_TO;
+ pts[n].p1.x = ps.x;
+ pts[n].p1.y = ps.y;
+ ++n;
+ }
+ }
+ /* split the path data into pieces which can be handled by Dia's bezier rendering */
+ if (outline->show_background) {
+ /* first draw the fills */
+ int s1 = 0, n1 = 0;
+ int s2 = 0;
+ for (i = 1; i < total; ++i) {
+ if (BEZ_MOVE_TO == pts[i].type) {
+ /* check whether the start point of the second outline is within the first outline.
+ * If so it need to be subtracted - currently blanked. */
+ real dist = distance_bez_shape_point (&pts[s1],
+ n1 > 0 ? n1 : i - s1, 0, &pts[i].p1);
+ if (s2 > s1) { /* blanking the previous one */
+ n = i - s2 - 1;
+ DIA_RENDERER_GET_CLASS (renderer)->fill_bezier (renderer, &pts[s2], n, &color_white);
+ } else { /* fill the outer shape */
+ n1 = n = i - s1;
+ DIA_RENDERER_GET_CLASS (renderer)->fill_bezier (renderer, &pts[s1], n, &outline->fill_color);
+ }
+ if (dist > 0) { /* remember as new outer outline */
+ s1 = i;
+ n1 = 0;
+ s2 = 0;
+ } else {
+ s2 = i;
+ }
+ }
+ }
+ /* the last one is not drawn yet */
+ if (s2 > s1) { /* blanking the previous one */
+ if (s2 - i - 1 > 1) /* depending on the above we may be ready */
+ DIA_RENDERER_GET_CLASS (renderer)->fill_bezier (renderer, &pts[s2], s2 - i - 1, &color_white);
+ } else {
+ if (s1 - i - 1 > 1)
+ DIA_RENDERER_GET_CLASS (renderer)->fill_bezier (renderer, &pts[s1], s1 - i - 1, &outline->fill_color);
+ }
+ } /* show_background */
+ n = 0;
+ for (i = 1; i < total; ++i) {
+ if (BEZ_MOVE_TO == pts[i].type) {
+ DIA_RENDERER_GET_CLASS (renderer)->draw_bezier (renderer, &pts[n], i - n, &outline->line_color);
+ n = i;
+ }
+ }
+ /* the last one, if there is one */
+ if (i - n - 1 > 0)
DIA_RENDERER_GET_CLASS (renderer)->draw_bezier (renderer, &pts[n], i - n - 1, &outline->line_color);
-}
-/* returning used to crash Dia, the method needed to be NULL if there is nothing to do */
-static DiaMenu *
-outline_get_object_menu(Outline *outline, Point *clickedpoint)
-{
- return NULL;
-}
-
-/*! A standard props compliant object needs to describe its parameters */
-static PropDescription *
-outline_describe_props (Outline *outline)
-{
- if (outline_props[0].quark == 0)
- prop_desc_list_calculate_quarks(outline_props);
- return outline_props;
-}
-static void
-outline_get_props (Outline *outline, GPtrArray *props)
-{
- object_get_props_from_offsets(&outline->object, outline_offsets, props);
-}
-static void
-outline_set_props (Outline *outline, GPtrArray *props)
-{
- object_set_props_from_offsets(&outline->object, outline_offsets, props);
- outline_update_data (outline);
-}
-static real
-outline_distance_from (Outline *outline, Point *point)
-{
- return distance_polygon_point (&outline->ink_rect[0], 4, outline->line_width, point);
-}
-static ObjectChange*
-outline_move_handle (Outline *outline,
- Handle *handle,
- Point *to, ConnectionPoint *cp,
- HandleMoveReason reason, ModifierKeys modifiers)
-{
- DiaObject *obj = &outline->object;
- Point start = obj->position;
- Point end = outline->ink_rect[2];
- real dist, old_dist = distance_point_point (&start, &end);
- Point norm = end;
- point_sub (&norm, &start);
- point_normalize (&norm);
- /* we use this to modify angle and scale */
- switch (handle->id) {
- case HANDLE_RESIZE_NW :
- start = *to;
- break;
- case HANDLE_RESIZE_SE :
- end = *to;
- break;
- default :
- g_warning ("Outline unknown handle");
- }
- dist = distance_point_point (&start, &end);
- /* disallow everything below a certain level, otherwise the font-size could become invalid */
- if (dist > 0.1) {
- obj->position = start;
-
- outline->font_height *= (dist / old_dist);
-
- outline_update_data (outline);
- }
- return NULL;
-}
-static ObjectChange*
-outline_move (Outline *outline, Point *to)
-{
- DiaObject *obj = &outline->object;
-
- obj->position = *to;
-
- outline_update_data (outline);
- return NULL;
-}
-static DiaObject *
-outline_copy (Outline *from)
-{
- Outline *to;
-
- to = g_new0 (Outline, 1);
- object_copy (&from->object, &to->object);
- outline_init_handles (to);
- to->name = g_strdup (from->name);
- to->rotation = from->rotation;
- to->font = dia_font_copy (from->font);
- to->font_height = from->font_height;
- to->line_width = from->line_width;
- to->line_color = from->line_color;
- to->fill_color = from->fill_color;
- to->show_background = from->show_background;
- /* the rest will be recalculated in update_data() */
- outline_update_data (to);
-
- return &to->object;
-}
-static void
-outline_destroy (Outline *outline)
-{
- if (outline->path)
+}
+/* returning used to crash Dia, the method needed to be NULL if there is nothing to do */
+static DiaMenu *
+outline_get_object_menu(Outline *outline, Point *clickedpoint)
+{
+ return NULL;
+}
+
+/*! A standard props compliant object needs to describe its parameters */
+static PropDescription *
+outline_describe_props (Outline *outline)
+{
+ if (outline_props[0].quark == 0)
+ prop_desc_list_calculate_quarks(outline_props);
+ return outline_props;
+}
+static void
+outline_get_props (Outline *outline, GPtrArray *props)
+{
+ object_get_props_from_offsets(&outline->object, outline_offsets, props);
+}
+static void
+outline_set_props (Outline *outline, GPtrArray *props)
+{
+ object_set_props_from_offsets(&outline->object, outline_offsets, props);
+ outline_update_data (outline);
+}
+static real
+outline_distance_from (Outline *outline, Point *point)
+{
+ return distance_polygon_point (&outline->ink_rect[0], 4, outline->line_width, point);
+}
+static ObjectChange*
+outline_move_handle (Outline *outline,
+ Handle *handle,
+ Point *to, ConnectionPoint *cp,
+ HandleMoveReason reason, ModifierKeys modifiers)
+{
+ DiaObject *obj = &outline->object;
+ Point start = obj->position;
+ Point end = outline->ink_rect[2];
+ real dist, old_dist = distance_point_point (&start, &end);
+ Point norm = end;
+ point_sub (&norm, &start);
+ point_normalize (&norm);
+ /* we use this to modify angle and scale */
+ switch (handle->id) {
+ case HANDLE_RESIZE_NW :
+ start = *to;
+ break;
+ case HANDLE_RESIZE_SE :
+ end = *to;
+ break;
+ default :
+ g_warning ("Outline unknown handle");
+ }
+ dist = distance_point_point (&start, &end);
+ /* disallow everything below a certain level, otherwise the font-size could become invalid */
+ if (dist > 0.1) {
+ obj->position = start;
+
+ outline->font_height *= (dist / old_dist);
+
+ outline_update_data (outline);
+ }
+ return NULL;
+}
+static ObjectChange*
+outline_move (Outline *outline, Point *to)
+{
+ DiaObject *obj = &outline->object;
+
+ obj->position = *to;
+
+ outline_update_data (outline);
+ return NULL;
+}
+static DiaObject *
+outline_copy (Outline *from)
+{
+ Outline *to;
+
+ to = g_new0 (Outline, 1);
+ object_copy (&from->object, &to->object);
+ outline_init_handles (to);
+ to->name = g_strdup (from->name);
+ to->rotation = from->rotation;
+ to->font = dia_font_copy (from->font);
+ to->font_height = from->font_height;
+ to->line_width = from->line_width;
+ to->line_color = from->line_color;
+ to->fill_color = from->fill_color;
+ to->show_background = from->show_background;
+ /* the rest will be recalculated in update_data() */
+ outline_update_data (to);
+
+ return &to->object;
+}
+static void
+outline_destroy (Outline *outline)
+{
+ if (outline->path)
cairo_path_destroy (outline->path);
- g_free (outline->name);
- object_destroy(&outline->object);
- /* but not the object itself? */
-}
-static void
-outline_select (Outline *outline, Point *clicked_point,
- DiaRenderer *interactive_renderer)
-{
- outine_update_handles (outline);
-}
-#endif /* HAVE_CAIRO */
+ g_free (outline->name);
+ object_destroy(&outline->object);
+ /* but not the object itself? */
+}
+static void
+outline_select (Outline *outline, Point *clicked_point,
+ DiaRenderer *interactive_renderer)
+{
+ outine_update_handles (outline);
+}
+
+#endif /* HAVE_CAIRO */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]