/*! \brief Create and add picture OBJECT to list. * \par Function Description * This function creates a new object representing a picture. * * The picture is described by its upper left corner - <B>x1</B>, <B>y1</B> - * and its lower right corner - <B>x2</B>, <B>y2</B>. * The <B>type</B> parameter must be equal to #OBJ_PICTURE. * * The #OBJECT structure is allocated with the #s_basic_init_object() * function. The structure describing the picture is allocated and * initialized with the parameters given to the function. * * \param [in] toplevel The TOPLEVEL object. * \param [in] pixbuf The GdkPixbuf picture to add. * A copy of this pixbuf is made. * \param [in] file_content Raw data of the image file. * NULL for non embedded loading. The object * object takes ownership of this buffer, and it * should not be free'd by the caller. * \param [in] file_length Length of raw data buffer * \param [in] filename File name backing this picture. * A copy of this string is made. * \param [in] ratio Picture height to width ratio. * \param [in] type Must be OBJ_PICTURE. * \param [in] x1 Upper x coordinate. * \param [in] y1 Upper y coordinate. * \param [in] x2 Lower x coordinate. * \param [in] y2 Lower y coordinate. * \param [in] angle Picture rotation angle. * \param [in] mirrored Whether the image should be mirrored or not. * \param [in] embedded Whether the embedded flag should be set or not. * \return A pointer to the new end of the object list. */ OBJECT *o_picture_new(TOPLEVEL *toplevel, GdkPixbuf *pixbuf, gchar *file_content, gsize file_length, char *filename, double ratio, char type, int x1, int y1, int x2, int y2, int angle, char mirrored, char embedded) { OBJECT *new_node; PICTURE *picture; /* create the object */ new_node = s_basic_new_object(type, "picture"); picture = (PICTURE *) g_malloc(sizeof(PICTURE)); new_node->picture = picture; /* describe the picture with its upper left and lower right corner */ picture->upper_x = x1; picture->upper_y = y1; picture->lower_x = x2; picture->lower_y = y2; picture->file_content = file_content; picture->file_length = file_length; picture->filename = g_strdup (filename); picture->ratio = ratio; picture->pixbuf = gdk_pixbuf_copy (pixbuf); picture->angle = angle; picture->mirrored = mirrored; picture->embedded = embedded; /* compute the bounding picture */ o_picture_recalc(toplevel, new_node); return new_node; }
/*! \brief Create a copy of a picture. * \par Function Description * This function creates a verbatim copy of the object pointed by * <B>o_current</B> describing a picture. * * \param [in] toplevel The TOPLEVEL object. * \param [in] object Picture OBJECT to copy. * \return The new OBJECT */ OBJECT *o_picture_copy(TOPLEVEL *toplevel, OBJECT *object) { OBJECT *new_node; PICTURE *picture; /* create the object */ new_node = s_basic_new_object(object->type, "picture"); picture = g_malloc(sizeof(PICTURE)); new_node->picture = picture; if (object->saved_color == -1) { new_node->color = object->color; } else { new_node->color = object->saved_color; } /* describe the picture with its upper left and lower right corner */ picture->upper_x = object->picture->upper_x; picture->upper_y = object->picture->upper_y; picture->lower_x = object->picture->lower_x; picture->lower_y = object->picture->lower_y; if (object->picture->file_content != NULL) { picture->file_content = g_malloc (object->picture->file_length); memcpy (picture->file_content, object->picture->file_content, object->picture->file_length); } else { picture->file_content = NULL; } picture->file_length = object->picture->file_length; picture->filename = g_strdup (object->picture->filename); picture->ratio = object->picture->ratio; picture->angle = object->picture->angle; picture->mirrored = object->picture->mirrored; picture->embedded = object->picture->embedded; /* Copy the picture data */ picture->original_picture = gdk_pixbuf_copy(object->picture->original_picture); picture->displayed_picture = gdk_pixbuf_copy(object->picture->displayed_picture); new_node->draw_func = object->draw_func; new_node->sel_func = object->sel_func; /* compute the bounding picture */ o_picture_recalc(toplevel, new_node); return new_node; }
/*! \brief Recalculate position of the given object. * \par Function Description * This function will take an object and recalculate its * position on the screen. * * \param [in] toplevel The TOPLEVEL object. * \param [in,out] o_current OBJECT to recalculate. * */ void o_recalc_single_object(TOPLEVEL *toplevel, OBJECT *o_current) { if (o_current != NULL) { switch(o_current->type) { case(OBJ_LINE): o_line_recalc(toplevel, o_current); break; case(OBJ_NET): o_net_recalc(toplevel, o_current); break; case(OBJ_BUS): o_bus_recalc(toplevel, o_current); break; case(OBJ_BOX): o_box_recalc(toplevel, o_current); break; case(OBJ_PATH): o_path_recalc(toplevel, o_current); break; case(OBJ_PICTURE): o_picture_recalc(toplevel, o_current); break; case(OBJ_CIRCLE): o_circle_recalc(toplevel, o_current); break; case(OBJ_COMPLEX): case(OBJ_PLACEHOLDER): o_complex_recalc(toplevel, o_current); break; case(OBJ_PIN): o_pin_recalc(toplevel, o_current); break; case(OBJ_ARC): o_arc_recalc(toplevel, o_current); break; case(OBJ_TEXT): o_text_recalc(toplevel, o_current); break; } } }
/*! \brief Translate a picture position in WORLD coordinates by a delta. * \par Function Description * This function applies a translation of (<B>x1</B>,<B>y1</B>) to the picture * described by <B>*object</B>. <B>x1</B> and <B>y1</B> are in world units. * * \param [in] toplevel The TOPLEVEL object. * \param [in] dx x distance to move. * \param [in] dy y distance to move. * \param [in,out] object Picture OBJECT to translate. */ void o_picture_translate_world(TOPLEVEL *toplevel, int dx, int dy, OBJECT *object) { if (object == NULL) printf("btw NO!\n"); /* Do world coords */ object->picture->upper_x = object->picture->upper_x + dx; object->picture->upper_y = object->picture->upper_y + dy; object->picture->lower_x = object->picture->lower_x + dx; object->picture->lower_y = object->picture->lower_y + dy; /* recalc the screen coords and the bounding picture */ o_picture_recalc(toplevel, object); }
/*! \brief Rotate picture OBJECT using WORLD coordinates. * \par Function Description * This function rotates the picture described by <B>*object</B> around * the (<B>world_centerx</B>, <B>world_centery</B>) point by <B>angle</B> * degrees. * The center of rotation is in world units. * * \param [in] toplevel The TOPLEVEL object. * \param [in] world_centerx Rotation center x coordinate in * WORLD units. * \param [in] world_centery Rotation center y coordinate in * WORLD units. * \param [in] angle Rotation angle in degrees (See note below). * \param [in,out] object Picture OBJECT to rotate. */ void o_picture_rotate_world(TOPLEVEL *toplevel, int world_centerx, int world_centery, int angle, OBJECT *object) { int newx1, newy1; int newx2, newy2; /* Only 90 degree multiple and positive angles are allowed. */ /* angle must be positive */ if(angle < 0) angle = -angle; /* angle must be a 90 multiple or no rotation performed */ if((angle % 90) != 0) return; object->picture->angle = ( object->picture->angle + angle ) % 360; /* The center of rotation (<B>world_centerx</B>, <B>world_centery</B>) is * translated to the origin. The rotation of the upper left and lower * right corner are then performed. Finally, the rotated picture is * translated back to its previous location. */ /* translate object to origin */ object->picture->upper_x -= world_centerx; object->picture->upper_y -= world_centery; object->picture->lower_x -= world_centerx; object->picture->lower_y -= world_centery; /* rotate the upper left corner of the picture */ rotate_point_90(object->picture->upper_x, object->picture->upper_y, angle, &newx1, &newy1); /* rotate the lower left corner of the picture */ rotate_point_90(object->picture->lower_x, object->picture->lower_y, angle, &newx2, &newy2); /* reorder the corners after rotation */ object->picture->upper_x = min(newx1,newx2); object->picture->upper_y = max(newy1,newy2); object->picture->lower_x = max(newx1,newx2); object->picture->lower_y = min(newy1,newy2); /* translate object back to normal position */ object->picture->upper_x += world_centerx; object->picture->upper_y += world_centery; object->picture->lower_x += world_centerx; object->picture->lower_y += world_centery; /* recalc boundings and screen coords */ o_picture_recalc(toplevel, object); }
/*! \brief Mirror a picture using WORLD coordinates. * \par Function Description * This function mirrors the picture from the point * (<B>world_centerx</B>,<B>world_centery</B>) in world unit. * * The picture is first translated to the origin, then mirrored and * finally translated back at its previous position. * * \param [in] toplevel The TOPLEVEL object. * \param [in] world_centerx Origin x coordinate in WORLD units. * \param [in] world_centery Origin y coordinate in WORLD units. * \param [in,out] object Picture OBJECT to mirror. */ void o_picture_mirror_world(TOPLEVEL *toplevel, int world_centerx, int world_centery, OBJECT *object) { int newx1, newy1; int newx2, newy2; /* Set info in object */ object->picture->mirrored = (object->picture->mirrored ^ 1) & 1; /* translate object to origin */ object->picture->upper_x -= world_centerx; object->picture->upper_y -= world_centery; object->picture->lower_x -= world_centerx; object->picture->lower_y -= world_centery; /* mirror the corners */ newx1 = -object->picture->upper_x; newy1 = object->picture->upper_y; newx2 = -object->picture->lower_x; newy2 = object->picture->lower_y; /* reorder the corners */ object->picture->upper_x = min(newx1,newx2); object->picture->upper_y = max(newy1,newy2); object->picture->lower_x = max(newx1,newx2); object->picture->lower_y = min(newy1,newy2); /* translate back in position */ object->picture->upper_x += world_centerx; object->picture->upper_y += world_centery; object->picture->lower_x += world_centerx; object->picture->lower_y += world_centery; /* recalc boundings and screen coords */ o_picture_recalc(toplevel, object); }
/*! \brief Modify the description of a picture OBJECT. * \par Function Description * This function modifies the coordinates of one of the four corner of * the picture. The new coordinates of the corner identified by * <B>whichone</B> are given by <B>x</B> and <B>y</B> in world unit. * * The coordinates of the corner is modified in the world coordinate system. * Screen coordinates and boundings are then updated. * * \param [in] toplevel The TOPLEVEL object. * \param [in,out] object Picture OBJECT to modify. * \param [in] x New x coordinate. * \param [in] y New y coordinate. * \param [in] whichone Which picture parameter to modify. * * <B>whichone</B> can have the following values: * <DL> * <DT>*</DT><DD>PICTURE_UPPER_LEFT * <DT>*</DT><DD>PICTURE_LOWER_LEFT * <DT>*</DT><DD>PICTURE_UPPER_RIGHT * <DT>*</DT><DD>PICTURE_LOWER_RIGHT * </DL> */ void o_picture_modify(TOPLEVEL *toplevel, OBJECT *object, int x, int y, int whichone) { int tmp; /* change the position of the selected corner */ switch(whichone) { case PICTURE_UPPER_LEFT: object->picture->upper_x = x; tmp = abs(object->picture->upper_x - object->picture->lower_x) / object->picture->ratio; if (y < object->picture->lower_y) { tmp = -tmp; } object->picture->upper_y = object->picture->lower_y + tmp; break; case PICTURE_LOWER_LEFT: object->picture->upper_x = x; tmp = abs(object->picture->upper_x - object->picture->lower_x) / object->picture->ratio; if (y > object->picture->upper_y) { tmp = -tmp; } object->picture->lower_y = object->picture->upper_y - tmp; break; case PICTURE_UPPER_RIGHT: object->picture->lower_x = x; tmp = abs(object->picture->upper_x - object->picture->lower_x) / object->picture->ratio; if (y < object->picture->lower_y) { tmp = -tmp; } object->picture->upper_y = object->picture->lower_y + tmp; break; case PICTURE_LOWER_RIGHT: object->picture->lower_x = x; tmp = abs(object->picture->upper_x - object->picture->lower_x) / object->picture->ratio; if (y > object->picture->upper_y) { tmp = -tmp; } object->picture->lower_y = object->picture->upper_y - tmp; break; default: return; } /* need to update the upper left and lower right corners */ if(object->picture->upper_x > object->picture->lower_x) { tmp = object->picture->upper_x; object->picture->upper_x = object->picture->lower_x; object->picture->lower_x = tmp; } if(object->picture->upper_y < object->picture->lower_y) { tmp = object->picture->upper_y; object->picture->upper_y = object->picture->lower_y; object->picture->lower_y = tmp; } /* recalculate the screen coords and the boundings */ o_picture_recalc(toplevel, object); }