[dia] [custom] Fix some subshape cases and add svg:rect:(rx|ry)
- From: Hans Breuer <hans src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [dia] [custom] Fix some subshape cases and add svg:rect:(rx|ry)
- Date: Sun, 9 Sep 2012 11:09:44 +0000 (UTC)
commit b27a03ffe36e94f1a492cf817e9d25d5f37f1040
Author: Hans Breuer <hans breuer org>
Date: Sun Sep 9 12:59:49 2012 +0200
[custom] Fix some subshape cases and add svg:rect:(rx|ry)
svg:image and svg:ellipse were not properly handles as subshapes:
only the position was transformed, but not the size.
Additionally there is <can-parent/> and some robustness improvement
for broken <svg:image/> definitions.
doc/custom-shapes | 9 +++++-
objects/custom/custom_object.c | 60 ++++++++++++++++++++++++++++++----------
objects/custom/shape_info.c | 29 ++++++++++++++++--
objects/custom/shape_info.h | 2 +
4 files changed, 80 insertions(+), 20 deletions(-)
---
diff --git a/doc/custom-shapes b/doc/custom-shapes
index 9edf286..02085c4 100644
--- a/doc/custom-shapes
+++ b/doc/custom-shapes
@@ -91,6 +91,10 @@ distorted. The three possibilities are:
The last option allows you to specify a range of allowable amounts of
distortion, which may be useful in some cases.
+The can-parent element allows to enable parenting for a shape. This is
+only useful for rectangular shapes, which should work as a container
+of other shapes or objects. So typical shapes wont have it.
+
The textbox element allows you to associate some text with
the shape. The syntax is:
<textbox x1="left" y1="top" x2="right" y2="bottom"/>
@@ -178,9 +182,12 @@ The recognised drawing elements are:
This is a polygon. The points argument has the same format as the
polyline.
-<svg:rect x1="..." y1="..." width="..." height="..."/>
+<svg:rect x1="..." y1="..." width="..." height="..." rx="..." ry="..."/>
This is a rectangle. The upper left corner is (x1,y1), and the lower
right corner is (x1+width,y1+height).
+ To get rounded corners either rx or ry or both can be given for the
+ single supported corner radius. If both are given the average gets
+ used.
<svg:image x1="..." y1="..." width="..." height="..." xlink:href="..." />
This is an external image. The upper left corner is (x1,y1), and the
diff --git a/objects/custom/custom_object.c b/objects/custom/custom_object.c
index dc709b8..72a80cb 100644
--- a/objects/custom/custom_object.c
+++ b/objects/custom/custom_object.c
@@ -518,6 +518,24 @@ transform_length(Custom *custom, real length)
}
static void
+transform_size(Custom *custom, real w1, real h1, real *w2, real *h2)
+{
+ if (custom->current_subshape != NULL) {
+ GraphicElementSubShape* subshape = custom->current_subshape;
+ g_assert (custom->subscale > 0.0 && subshape->default_scale > 0.0);
+ if (w2)
+ *w2 = w1 * custom->subscale * subshape->default_scale;
+ if (h2)
+ *h2 = h1 * custom->subscale * subshape->default_scale;
+ } else {
+ if (w2)
+ *w2 = w1 * fabs(custom->xscale);
+ if (h2)
+ *h2 = h1 * fabs(custom->yscale);
+ }
+}
+
+static void
transform_coord(Custom *custom, const Point *p1, Point *out)
{
if (custom->current_subshape != NULL) {
@@ -906,9 +924,11 @@ custom_draw_element(GraphicElement* el, Custom *custom, DiaRenderer *renderer,
{
DiaRendererClass *renderer_ops = DIA_RENDERER_GET_CLASS (renderer);
Point p1, p2;
+ real width, height;
real coord;
int i;
-
+ real radius;
+
if (el->any.s.line_width != (*cur_line)) {
(*cur_line) = el->any.s.line_width;
renderer_ops->set_linewidth(renderer,
@@ -975,6 +995,7 @@ custom_draw_element(GraphicElement* el, Custom *custom, DiaRenderer *renderer,
case GE_RECT:
transform_coord(custom, &el->rect.corner1, &p1);
transform_coord(custom, &el->rect.corner2, &p2);
+ radius = transform_length(custom, el->rect.corner_radius);
if (p1.x > p2.x) {
coord = p1.x;
p1.x = p2.x;
@@ -985,10 +1006,11 @@ custom_draw_element(GraphicElement* el, Custom *custom, DiaRenderer *renderer,
p1.y = p2.y;
p2.y = coord;
}
+ /* the renderer implementation will use simple rect with a small enough radius */
if (custom->show_background && el->any.s.fill != DIA_SVG_COLOUR_NONE)
- renderer_ops->fill_rect(renderer, &p1, &p2, bg);
+ renderer_ops->fill_rounded_rect(renderer, &p1, &p2, bg, radius);
if (el->any.s.stroke != DIA_SVG_COLOUR_NONE)
- renderer_ops->draw_rect(renderer, &p1, &p2, fg);
+ renderer_ops->draw_rounded_rect(renderer, &p1, &p2, fg, radius);
break;
case GE_TEXT:
text_set_height (el->text.object, transform_length (custom, el->text.s.font_height));
@@ -999,23 +1021,19 @@ custom_draw_element(GraphicElement* el, Custom *custom, DiaRenderer *renderer,
break;
case GE_ELLIPSE:
transform_coord(custom, &el->ellipse.center, &p1);
+ transform_size(custom, el->ellipse.width, el->ellipse.height, &width, &height);
if (custom->show_background && el->any.s.fill != DIA_SVG_COLOUR_NONE)
- renderer_ops->fill_ellipse(renderer, &p1,
- el->ellipse.width * fabs(custom->xscale),
- el->ellipse.height * fabs(custom->yscale),
- bg);
+ renderer_ops->fill_ellipse(renderer, &p1, width, height, bg);
if (el->any.s.stroke != DIA_SVG_COLOUR_NONE)
- renderer_ops->draw_ellipse(renderer, &p1,
- el->ellipse.width * fabs(custom->xscale),
- el->ellipse.height * fabs(custom->yscale),
- fg);
+ renderer_ops->draw_ellipse(renderer, &p1, width, height, fg);
break;
case GE_IMAGE:
transform_coord(custom, &el->image.topleft, &p1);
+ /* to scale correctly also for subshape some extra hoops */
+ transform_size(custom, el->image.width, el->image.height, &width, &height);
renderer_ops->draw_image(renderer, &p1,
- el->image.width * fabs(custom->xscale),
- el->image.height * fabs(custom->yscale),
- el->image.image);
+ width, height,
+ el->image.image);
break;
case GE_PATH:
g_array_set_size(barr, el->path.npoints);
@@ -1351,7 +1369,16 @@ custom_update_data(Custom *custom, AnchorShape horiz, AnchorShape vert)
for (tmp = custom->info->display_list; tmp != NULL; tmp = tmp->next) {
GraphicElement *el = tmp->data;
Rectangle rect;
+ /* Line width handling/behavior for custom objects is special. Instead of
+ * directly using the given width some ratio with the shape global custom
+ * border_width gets calculated - to allow influencing all line width used
+ * in a complex shape (and not brea backward compatibility). With
real lwfactor = custom->border_width / 2;
+ * we get traces in the diagram at high zoom levels, so use something more
+ * safe for the bounding box calculation
+ */
+ real lwfactor = el->any.s.line_width == custom->border_width
+ ? 1.0 : custom->border_width;
switch(el->type) {
case GE_SUBSHAPE :
@@ -1540,7 +1567,7 @@ custom_create(Point *startpoint,
custom = g_new0_ext (Custom, info->ext_attr_size);
elem = &custom->element;
obj = &elem->object;
-
+
obj->type = info->object_type;
obj->ops = &custom_ops;
@@ -1552,6 +1579,8 @@ custom_create(Point *startpoint,
custom->info = info;
+ obj->flags |= info->object_flags;
+
custom->old_subscale = 1.0;
custom->subscale = 1.0;
custom->current_subshape = NULL;
@@ -1638,6 +1667,7 @@ custom_copy(Custom *custom)
element_copy(elem, newelem);
newcustom->info = custom->info;
+ newobj->flags = custom->element.object.flags;
newcustom->padding = custom->padding;
newcustom->current_subshape = NULL; /* it's temporary state, don't copy from wrong object */
diff --git a/objects/custom/shape_info.c b/objects/custom/shape_info.c
index d120a01..bdc0a72 100644
--- a/objects/custom/shape_info.c
+++ b/objects/custom/shape_info.c
@@ -315,6 +315,7 @@ parse_svg_node(ShapeInfo *info, xmlNodePtr node, xmlNsPtr svg_ns,
g_array_free(arr, TRUE);
} else if (!xmlStrcmp(node->name, (const xmlChar *)"rect")) {
GraphicElementRect *rect = g_new0(GraphicElementRect, 1);
+ real corner_radius = 0.0;
el = (GraphicElement *)rect;
rect->type = GE_RECT;
@@ -338,6 +339,22 @@ parse_svg_node(ShapeInfo *info, xmlNodePtr node, xmlNsPtr svg_ns,
rect->corner2.y = rect->corner1.y + g_ascii_strtod((gchar *) str, NULL);
xmlFree(str);
}
+ str = xmlGetProp(node, (const xmlChar *)"rx");
+ if (str) {
+ corner_radius = g_ascii_strtod((gchar *) str, NULL);
+ xmlFree(str);
+ }
+ str = xmlGetProp(node, (const xmlChar *)"ry");
+ if (str) {
+ if(corner_radius != 0.0) {
+ /* calculate the mean value of rx and ry */
+ corner_radius = (corner_radius+g_ascii_strtod((gchar *) str, NULL))/2;
+ } else {
+ corner_radius = g_ascii_strtod((gchar *) str, NULL);
+ }
+ xmlFree(str);
+ }
+ rect->corner_radius = corner_radius;
} else if (!xmlStrcmp(node->name, (const xmlChar *)"text")) {
GraphicElementText *text = g_new(GraphicElementText, 1);
@@ -465,14 +482,14 @@ parse_svg_node(ShapeInfo *info, xmlNodePtr node, xmlNsPtr svg_ns,
image->image = dia_image_load(imgfn);
}
- /* w/o the image we would crash later */
- if (!image->image) {
+ if (!image->image)
g_warning("failed to load image file %s", imgfn ? imgfn : "(data:)");
- image->image = dia_image_get_broken();
- }
g_free(imgfn);
xmlFree(str);
}
+ /* w/o the image we would crash later */
+ if (!image->image)
+ image->image = dia_image_get_broken();
} else if (!xmlStrcmp(node->name, (const xmlChar *)"g")) {
if (!is_subshape(node)) {
/* add elements from the group element */
@@ -586,6 +603,7 @@ update_bounds(ShapeInfo *info)
case GE_RECT:
check_point(info, &(el->rect.corner1));
check_point(info, &(el->rect.corner2));
+ /* el->rect.corner_radius has no infulence on the bounding rectangle */
break;
case GE_TEXT:
check_point(info, &(el->text.anchor));
@@ -693,6 +711,7 @@ load_shape_info(const gchar *filename, ShapeInfo *preload)
info->default_width = 0.0;
info->default_height = 0.0;
info->main_cp = -1;
+ info->object_flags = 0;
i = 0;
for (node = root->xmlChildrenNode; node != NULL; node = node->next) {
@@ -760,6 +779,8 @@ load_shape_info(const gchar *filename, ShapeInfo *preload)
info->nconnections = arr->len;
info->connections = (Point *)arr->data;
g_array_free(arr, FALSE);
+ } else if (node->ns == shape_ns && !xmlStrcmp(node->name, (const xmlChar *)"can-parent")) {
+ info->object_flags |= DIA_OBJECT_CAN_PARENT;
} else if (node->ns == shape_ns && !xmlStrcmp(node->name, (const xmlChar *)"textbox")) {
xmlChar *str;
diff --git a/objects/custom/shape_info.h b/objects/custom/shape_info.h
index 7971792..870fbae 100644
--- a/objects/custom/shape_info.h
+++ b/objects/custom/shape_info.h
@@ -80,6 +80,7 @@ struct _GraphicElementPoly {
struct _GraphicElementRect {
SHAPE_INFO_COMMON;
Point corner1, corner2;
+ real corner_radius;
};
struct _GraphicElementEllipse {
@@ -176,6 +177,7 @@ struct _ShapeInfo {
int nconnections;
Point *connections;
int main_cp; /* The cp that gets connections from the whole object */
+ int object_flags;
Rectangle shape_bounds;
gboolean has_text;
gboolean resize_with_text;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]