summaryrefslogtreecommitdiff
path: root/objects
diff options
context:
space:
mode:
authorHans Breuer <hans@breuer.org>2014-11-02 14:33:03 +0100
committerHans Breuer <hans@breuer.org>2014-11-02 15:04:31 +0100
commit127663095853a7fa06e245d3a686fd71db859645 (patch)
tree093a9ffedff91ce78fc2d3421680aa686da66ea2 /objects
parent4c01794c872d73c4f2f3d05cb43c659206340ea4 (diff)
downloaddia-127663095853a7fa06e245d3a686fd71db859645.tar.xz
[transform] initial rotation support for "Standard - Image"
Introduce DiaRenderer::draw_rotated_image() and move some code to helper functions for reuse. Implement DiaCairoRenderer::draw_rotated_image() for testing the new functionality (mainly with transform-variations.svg). Give "Standard - Image" an angle property: copy, load, save it. Set Image::angle in image_transform(). Unrelated: use element_update_connections_rectangle() to ensure proper directions initialization with less code. Open issues: - for now only the cairo renderer implements draw_image_rotated() - either the angle should be limited like for "Standard - Box" or the connection point directions for angles outside [-45...45deg] must be fixed
Diffstat (limited to 'objects')
-rw-r--r--objects/standard/image.c89
1 files changed, 58 insertions, 31 deletions
diff --git a/objects/standard/image.c b/objects/standard/image.c
index 712190cc..8d7c9a85 100644
--- a/objects/standard/image.c
+++ b/objects/standard/image.c
@@ -72,6 +72,8 @@ struct _Image {
gboolean draw_border;
gboolean keep_aspect;
+ real angle;
+
time_t mtime;
};
@@ -113,6 +115,8 @@ static ObjectTypeOps image_type_ops =
(ApplyDefaultsFunc) NULL
};
+static PropNumData _image_angle_range = { -180.0, 180.0, 5.0 };
+
static PropDescription image_props[] = {
ELEMENT_COMMON_PROPERTIES,
{ "image_file", PROP_TYPE_FILE, PROP_FLAG_VISIBLE,
@@ -125,6 +129,8 @@ static PropDescription image_props[] = {
N_("Draw border"), NULL, NULL},
{ "keep_aspect", PROP_TYPE_BOOL, PROP_FLAG_VISIBLE,
N_("Keep aspect ratio"), NULL, NULL},
+ { "angle", PROP_TYPE_REAL, PROP_FLAG_VISIBLE | PROP_FLAG_OPTIONAL,
+ N_("Angle"), NULL, &_image_angle_range },
PROP_STD_LINE_WIDTH,
PROP_STD_LINE_COLOUR,
PROP_STD_LINE_STYLE,
@@ -171,6 +177,7 @@ static PropOffset image_offsets[] = {
{ "pixbuf", PROP_TYPE_PIXBUF, offsetof(Image, pixbuf) },
{ "show_border", PROP_TYPE_BOOL, offsetof(Image, draw_border) },
{ "keep_aspect", PROP_TYPE_BOOL, offsetof(Image, keep_aspect) },
+ { "angle", PROP_TYPE_REAL, offsetof(Image,angle)},
{ PROP_STDNAME_LINE_WIDTH, PROP_STDTYPE_LINE_WIDTH, offsetof(Image, border_width) },
{ "line_colour", PROP_TYPE_COLOUR, offsetof(Image, border_color) },
{ "line_style", PROP_TYPE_LINESTYLE,
@@ -302,6 +309,11 @@ image_distance_from(Image *image, Point *point)
Rectangle rect;
real bw = image->draw_border ? image->border_width : 0;
+ if (image->angle != 0.0) {
+ Point corners[4];
+ element_get_poly (elem, image->angle, corners);
+ return distance_polygon_point (corners, 4, bw, point);
+ }
rect.left = elem->corner.x - bw;
rect.right = elem->corner.x + elem->width + bw;
rect.top = elem->corner.y - bw;
@@ -446,20 +458,30 @@ image_draw(Image *image, DiaRenderer *renderer)
renderer_ops->set_linewidth(renderer, image->border_width);
renderer_ops->set_linestyle(renderer, image->line_style, image->dashlength);
renderer_ops->set_linejoin(renderer, LINEJOIN_MITER);
-
- renderer_ops->draw_rect(renderer,
- &ul_corner,
- &lr_corner,
- NULL,
- &image->border_color);
+
+ if (image->angle != 0.0) {
+ Point poly[4];
+ element_get_poly (elem, image->angle, poly);
+ /* need to grow the poly, XXX: done here by growing the border width */
+ renderer_ops->set_linewidth(renderer, image->border_width * 2);
+ renderer_ops->draw_polygon (renderer, poly, 4, NULL, &image->border_color);
+ } else {
+ renderer_ops->draw_rect (renderer,
+ &ul_corner, &lr_corner,
+ NULL, &image->border_color);
+ }
}
/* Draw the image */
if (image->image) {
- renderer_ops->draw_image(renderer, &elem->corner, elem->width,
- elem->height, image->image);
+ if (image->angle == 0.0)
+ renderer_ops->draw_image (renderer, &elem->corner, elem->width,
+ elem->height, image->image);
+ else
+ renderer_ops->draw_rotated_image (renderer, &elem->corner, elem->width,
+ elem->height, image->angle, image->image);
} else {
DiaImage *broken = dia_image_get_broken();
- renderer_ops->draw_image(renderer, &elem->corner, elem->width,
+ renderer_ops->draw_image (renderer, &elem->corner, elem->width,
elem->height, broken);
dia_image_unref(broken);
}
@@ -484,9 +506,9 @@ image_transform(Image *image, const DiaMatrix *m)
/* rotation is invariant to the center */
transform_point (&c, m);
- /* XXX: implement image rotate! */
elem->width = width;
elem->height = height;
+ image->angle = angle;
elem->corner.x = c.x - width / 2.0;
elem->corner.y = c.y - height / 2.0;
}
@@ -512,30 +534,26 @@ image_update_data(Image *image)
}
/* Update connections: */
- image->connections[0].pos = elem->corner;
- image->connections[1].pos.x = elem->corner.x + elem->width / 2.0;
- image->connections[1].pos.y = elem->corner.y;
- image->connections[2].pos.x = elem->corner.x + elem->width;
- image->connections[2].pos.y = elem->corner.y;
- image->connections[3].pos.x = elem->corner.x;
- image->connections[3].pos.y = elem->corner.y + elem->height / 2.0;
- image->connections[4].pos.x = elem->corner.x + elem->width;
- image->connections[4].pos.y = elem->corner.y + elem->height / 2.0;
- image->connections[5].pos.x = elem->corner.x;
- image->connections[5].pos.y = elem->corner.y + elem->height;
- image->connections[6].pos.x = elem->corner.x + elem->width / 2.0;
- image->connections[6].pos.y = elem->corner.y + elem->height;
- image->connections[7].pos.x = elem->corner.x + elem->width;
- image->connections[7].pos.y = elem->corner.y + elem->height;
- image->connections[8].pos.x = elem->corner.x + elem->width / 2.0;
- image->connections[8].pos.y = elem->corner.y + elem->height / 2.0;
-
+ element_update_connections_rectangle (elem, image->connections);
+
+ if (image->angle != 0) {
+ real cx = elem->corner.x + elem->width / 2.0;
+ real cy = elem->corner.y + elem->height / 2.0;
+ DiaMatrix m = { 1.0, 0.0, 0.0, 1.0, cx, cy };
+ DiaMatrix t = { 1.0, 0.0, 0.0, 1.0, -cx, -cy };
+ int i;
+
+ dia_matrix_set_angle_and_scales (&m, G_PI*image->angle/180, 1.0, 1.0);
+ dia_matrix_multiply (&m, &t, &m);
+ for (i = 0; i < 8; ++i)
+ transform_point (&image->connections[i].pos, &m);
+ }
+
/* the image border is drawn vompletely outside of the image, so no /2.0 on border width */
extra->border_trans = (image->draw_border ? image->border_width : 0.0);
element_update_boundingbox(elem);
obj->position = elem->corner;
- image->connections[8].directions = DIR_ALL;
element_update_handles(elem);
}
@@ -633,6 +651,7 @@ image_copy(Image *image)
newimage->border_width = image->border_width;
newimage->border_color = image->border_color;
newimage->line_style = image->line_style;
+ newimage->angle = image->angle;
for (i=0;i<NUM_CONNECTIONS;i++) {
newobj->connections[i] = &newimage->connections[i];
@@ -647,8 +666,8 @@ image_copy(Image *image)
dia_image_add_ref(image->image);
newimage->image = image->image;
- /* not sure if we only want a reference, but it would be safe when
- * someday editing doe not work inplace, but creates new pixbufs
+ /* not sure if we only want a reference, but it would be safe when someday
+ * editing does not work inplace anymore and instead creates new pixbufs
* for every single undoable step */
newimage->inline_data = image->inline_data;
if (image->pixbuf)
@@ -720,6 +739,9 @@ image_save(Image *image, ObjectNode obj_node, DiaContext *ctx)
data_add_boolean(new_attribute(obj_node, "draw_border"), image->draw_border, ctx);
data_add_boolean(new_attribute(obj_node, "keep_aspect"), image->keep_aspect, ctx);
+ if (image->angle != 0.0)
+ data_add_real(new_attribute(obj_node, "angle"), image->angle, ctx);
+
if (image->file != NULL) {
if (g_path_is_absolute(image->file)) { /* Absolute pathname */
diafile_dir = get_directory(dia_context_get_filename (ctx));
@@ -804,6 +826,11 @@ image_load(ObjectNode obj_node, int version, DiaContext *ctx)
if (attr != NULL)
image->keep_aspect = data_boolean(attribute_first_data(attr), ctx);
+ image->angle = 0.0;
+ attr = object_find_attribute(obj_node, "angle");
+ if (attr != NULL)
+ image->angle = data_real(attribute_first_data(attr), ctx);
+
attr = object_find_attribute(obj_node, "file");
if (attr != NULL) {
image->file = data_filename(attribute_first_data(attr), ctx);