2003-10-19 21:03:21 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
|
|
*
|
|
|
|
* This is a plug-in for the GIMP.
|
|
|
|
*
|
|
|
|
* Generates images containing vector type drawings.
|
|
|
|
*
|
|
|
|
* Copyright (C) 1997 Andy Thomas alt@picnic.demon.co.uk
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2003-10-24 13:28:46 +00:00
|
|
|
#include "config.h"
|
|
|
|
|
2003-10-19 21:03:21 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
|
|
|
|
#include "gfig.h"
|
2003-10-24 13:28:46 +00:00
|
|
|
#include "gfig-arc.h"
|
|
|
|
#include "gfig-bezier.h"
|
|
|
|
#include "gfig-circle.h"
|
|
|
|
#include "gfig-dobject.h"
|
|
|
|
#include "gfig-ellipse.h"
|
|
|
|
#include "gfig-line.h"
|
|
|
|
#include "gfig-poly.h"
|
|
|
|
#include "gfig-spiral.h"
|
|
|
|
#include "gfig-star.h"
|
|
|
|
|
|
|
|
#include "libgimp/stdplugins-intl.h"
|
2003-10-19 21:03:21 +00:00
|
|
|
|
|
|
|
static Dobject *operation_obj;
|
|
|
|
static GdkPoint *move_all_pnt; /* Point moving all from */
|
|
|
|
|
2003-10-24 13:28:46 +00:00
|
|
|
static void draw_one_obj (Dobject *obj);
|
|
|
|
static void do_move_obj (Dobject *obj,
|
|
|
|
GdkPoint *to_pnt);
|
2003-10-19 21:03:21 +00:00
|
|
|
static void do_move_all_obj (GdkPoint *to_pnt);
|
|
|
|
static void do_move_obj_pnt (Dobject *obj,
|
|
|
|
GdkPoint *to_pnt);
|
|
|
|
static void remove_obj_from_list (GFigObj *obj,
|
|
|
|
Dobject *del_obj);
|
|
|
|
static gint scan_obj_points (DobjPoints *opnt,
|
|
|
|
GdkPoint *pnt);
|
|
|
|
|
|
|
|
/* Delete a list of points */
|
|
|
|
void
|
|
|
|
d_delete_dobjpoints (DobjPoints * pnts)
|
|
|
|
{
|
|
|
|
DobjPoints *next;
|
|
|
|
DobjPoints *pnt2del = pnts;
|
|
|
|
|
|
|
|
while (pnt2del)
|
|
|
|
{
|
|
|
|
next = pnt2del->next;
|
|
|
|
g_free (pnt2del);
|
|
|
|
pnt2del = next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DobjPoints*
|
|
|
|
new_dobjpoint (gint x, gint y)
|
|
|
|
{
|
|
|
|
DobjPoints *npnt = g_new0 (DobjPoints, 1);
|
|
|
|
|
|
|
|
npnt->pnt.x = x;
|
|
|
|
npnt->pnt.y = y;
|
|
|
|
|
|
|
|
return npnt;
|
|
|
|
}
|
|
|
|
|
|
|
|
DobjPoints *
|
2003-10-24 13:28:46 +00:00
|
|
|
d_copy_dobjpoints (DobjPoints *pnts)
|
2003-10-19 21:03:21 +00:00
|
|
|
{
|
|
|
|
DobjPoints *ret = NULL;
|
|
|
|
DobjPoints *head = NULL;
|
|
|
|
DobjPoints *newpnt;
|
2003-10-24 13:28:46 +00:00
|
|
|
DobjPoints *pnt2copy;
|
2003-10-19 21:03:21 +00:00
|
|
|
|
2003-10-24 13:28:46 +00:00
|
|
|
for (pnt2copy = pnts; pnt2copy; pnt2copy = pnt2copy->next)
|
2003-10-19 21:03:21 +00:00
|
|
|
{
|
2003-10-24 13:28:46 +00:00
|
|
|
newpnt = new_dobjpoint (pnt2copy->pnt.x, pnt2copy->pnt.y);
|
2003-10-19 21:03:21 +00:00
|
|
|
|
|
|
|
if (!ret)
|
2003-10-24 13:28:46 +00:00
|
|
|
{
|
|
|
|
head = ret = newpnt;
|
|
|
|
}
|
2003-10-19 21:03:21 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
head->next = newpnt;
|
|
|
|
head = newpnt;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static DobjPoints *
|
|
|
|
get_diffs (Dobject *obj,
|
2003-10-24 13:28:46 +00:00
|
|
|
gint *xdiff,
|
|
|
|
gint *ydiff,
|
2003-10-19 21:03:21 +00:00
|
|
|
GdkPoint *to_pnt)
|
|
|
|
{
|
|
|
|
DobjPoints *spnt;
|
|
|
|
|
|
|
|
g_assert (obj != NULL);
|
|
|
|
|
|
|
|
for (spnt = obj->points; spnt; spnt = spnt->next)
|
|
|
|
{
|
|
|
|
if (spnt->found_me)
|
|
|
|
{
|
|
|
|
*xdiff = spnt->pnt.x - to_pnt->x;
|
|
|
|
*ydiff = spnt->pnt.y - to_pnt->y;
|
|
|
|
return spnt;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
inside_sqr (GdkPoint *cpnt,
|
|
|
|
GdkPoint *testpnt)
|
|
|
|
{
|
|
|
|
/* Return TRUE if testpnt is near cpnt */
|
2003-10-24 13:28:46 +00:00
|
|
|
gint x = cpnt->x;
|
|
|
|
gint y = cpnt->y;
|
|
|
|
gint tx = testpnt->x;
|
|
|
|
gint ty = testpnt->y;
|
2003-10-19 21:03:21 +00:00
|
|
|
|
|
|
|
return (abs (x - tx) <= SQ_SIZE && abs (y - ty) < SQ_SIZE);
|
|
|
|
}
|
|
|
|
|
2003-10-24 13:28:46 +00:00
|
|
|
static gboolean
|
2003-10-19 21:03:21 +00:00
|
|
|
scan_obj_points (DobjPoints *opnt,
|
|
|
|
GdkPoint *pnt)
|
|
|
|
{
|
|
|
|
while (opnt)
|
|
|
|
{
|
|
|
|
if (inside_sqr (&opnt->pnt, pnt))
|
|
|
|
{
|
|
|
|
opnt->found_me = TRUE;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
opnt->found_me = FALSE;
|
|
|
|
opnt = opnt->next;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Dobject *
|
|
|
|
get_nearest_objs (GFigObj *obj,
|
|
|
|
GdkPoint *pnt)
|
|
|
|
{
|
|
|
|
/* Nearest object to given point or NULL */
|
|
|
|
DAllObjs *all;
|
|
|
|
Dobject *test_obj;
|
|
|
|
gint count = 0;
|
|
|
|
|
|
|
|
if (!obj)
|
|
|
|
return NULL;
|
|
|
|
|
2003-10-24 13:28:46 +00:00
|
|
|
for (all = obj->obj_list; all; all = all->next)
|
2003-10-19 21:03:21 +00:00
|
|
|
{
|
|
|
|
test_obj = all->obj;
|
|
|
|
|
|
|
|
if (count == obj_show_single || obj_show_single == -1)
|
|
|
|
if (scan_obj_points (test_obj->points, pnt))
|
|
|
|
{
|
|
|
|
return test_obj;
|
|
|
|
}
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
object_operation_start (GdkPoint *pnt,
|
|
|
|
gint shift_down)
|
|
|
|
{
|
|
|
|
Dobject *new_obj;
|
|
|
|
|
|
|
|
/* Find point in given object list */
|
|
|
|
operation_obj = get_nearest_objs (current_obj, pnt);
|
|
|
|
|
|
|
|
/* Special case if shift down && move obj then moving all objs */
|
|
|
|
|
|
|
|
if (shift_down && selvals.otype == MOVE_OBJ)
|
|
|
|
{
|
|
|
|
move_all_pnt = g_malloc0 (sizeof (*move_all_pnt));
|
|
|
|
*move_all_pnt = *pnt; /* Structure copy */
|
|
|
|
setup_undo ();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!operation_obj)
|
|
|
|
return;/* None to work on */
|
|
|
|
|
|
|
|
setup_undo ();
|
|
|
|
|
|
|
|
switch (selvals.otype)
|
|
|
|
{
|
|
|
|
case MOVE_OBJ:
|
|
|
|
if (operation_obj->type == BEZIER)
|
|
|
|
{
|
|
|
|
d_draw_bezier (operation_obj);
|
|
|
|
tmp_bezier = operation_obj;
|
|
|
|
d_draw_bezier (operation_obj);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MOVE_POINT:
|
|
|
|
if (operation_obj->type == BEZIER)
|
|
|
|
{
|
|
|
|
d_draw_bezier (operation_obj);
|
|
|
|
tmp_bezier = operation_obj;
|
|
|
|
d_draw_bezier (operation_obj);
|
|
|
|
}
|
|
|
|
/* If shift is down the break into sep lines */
|
|
|
|
if ((operation_obj->type == POLY
|
|
|
|
|| operation_obj->type == STAR)
|
|
|
|
&& shift_down)
|
|
|
|
{
|
|
|
|
switch (operation_obj->type)
|
|
|
|
{
|
|
|
|
case POLY:
|
|
|
|
d_poly2lines (operation_obj);
|
|
|
|
break;
|
|
|
|
case STAR:
|
|
|
|
d_star2lines (operation_obj);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* Re calc which object point we are lookin at */
|
|
|
|
scan_obj_points (operation_obj->points, pnt);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case COPY_OBJ:
|
|
|
|
/* Copy the "operation object" */
|
|
|
|
/* Then bung us into "copy/move" mode */
|
|
|
|
|
2003-10-24 13:28:46 +00:00
|
|
|
new_obj = (Dobject*) operation_obj->copyfunc (operation_obj);
|
2003-10-19 21:03:21 +00:00
|
|
|
if (new_obj)
|
|
|
|
{
|
|
|
|
scan_obj_points (new_obj->points, pnt);
|
|
|
|
add_to_all_obj (current_obj, new_obj);
|
|
|
|
operation_obj = new_obj;
|
|
|
|
selvals.otype = MOVE_COPY_OBJ;
|
|
|
|
new_obj->drawfunc (new_obj);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case DEL_OBJ:
|
|
|
|
remove_obj_from_list (current_obj, operation_obj);
|
|
|
|
break;
|
|
|
|
case MOVE_COPY_OBJ: /* Never when button down */
|
|
|
|
default:
|
|
|
|
g_warning ("Internal error selvals.otype object operation start");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
object_operation_end (GdkPoint *pnt,
|
|
|
|
gint shift_down)
|
|
|
|
{
|
|
|
|
if (selvals.otype != DEL_OBJ && operation_obj &&
|
|
|
|
operation_obj->type == BEZIER)
|
|
|
|
{
|
|
|
|
d_draw_bezier (operation_obj);
|
|
|
|
tmp_bezier = NULL; /* use as switch */
|
|
|
|
d_draw_bezier (operation_obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
operation_obj = NULL;
|
|
|
|
|
|
|
|
if (move_all_pnt)
|
|
|
|
{
|
|
|
|
g_free (move_all_pnt);
|
|
|
|
move_all_pnt = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Special case - if copying mode MUST be copy when button up received */
|
|
|
|
if (selvals.otype == MOVE_COPY_OBJ)
|
|
|
|
selvals.otype = COPY_OBJ;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Move object around */
|
|
|
|
void
|
|
|
|
object_operation (GdkPoint *to_pnt,
|
|
|
|
gint shift_down)
|
|
|
|
{
|
|
|
|
/* Must do diffent things depending on object type */
|
|
|
|
/* but must have object to operate on! */
|
|
|
|
|
|
|
|
/* Special case - if shift own and move_obj then move ALL objects */
|
|
|
|
if (move_all_pnt && shift_down && selvals.otype == MOVE_OBJ)
|
|
|
|
{
|
|
|
|
do_move_all_obj (to_pnt);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!operation_obj)
|
|
|
|
return;
|
|
|
|
|
|
|
|
switch (selvals.otype)
|
|
|
|
{
|
|
|
|
case MOVE_OBJ:
|
|
|
|
case MOVE_COPY_OBJ:
|
|
|
|
switch (operation_obj->type)
|
|
|
|
{
|
|
|
|
case LINE:
|
|
|
|
case CIRCLE:
|
|
|
|
case ELLIPSE:
|
|
|
|
case POLY:
|
|
|
|
case ARC:
|
|
|
|
case STAR:
|
|
|
|
case SPIRAL:
|
|
|
|
case BEZIER:
|
|
|
|
do_move_obj (operation_obj, to_pnt);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* Internal error */
|
|
|
|
g_warning ("Internal error in operation_obj->type");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MOVE_POINT:
|
|
|
|
switch (operation_obj->type)
|
|
|
|
{
|
|
|
|
case LINE:
|
|
|
|
case CIRCLE:
|
|
|
|
case ELLIPSE:
|
|
|
|
case POLY:
|
|
|
|
case ARC:
|
|
|
|
case STAR:
|
|
|
|
case SPIRAL:
|
|
|
|
case BEZIER:
|
|
|
|
do_move_obj_pnt (operation_obj, to_pnt);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* Internal error */
|
|
|
|
g_warning ("Internal error in operation_obj->type");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case DEL_OBJ:
|
|
|
|
break;
|
|
|
|
case COPY_OBJ: /* Should have been changed to MOVE_COPY_OBJ */
|
|
|
|
default:
|
|
|
|
g_warning ("Internal error selvals.otype");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
update_pnts (Dobject *obj,
|
2003-10-24 13:28:46 +00:00
|
|
|
gint xdiff,
|
|
|
|
gint ydiff)
|
2003-10-19 21:03:21 +00:00
|
|
|
{
|
|
|
|
DobjPoints *spnt;
|
|
|
|
|
|
|
|
g_assert (obj != NULL);
|
|
|
|
|
|
|
|
/* Update all pnts */
|
|
|
|
for (spnt = obj->points; spnt; spnt = spnt->next)
|
|
|
|
{
|
|
|
|
spnt->pnt.x -= xdiff;
|
|
|
|
spnt->pnt.y -= ydiff;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
remove_obj_from_list (GFigObj *obj,
|
|
|
|
Dobject *del_obj)
|
|
|
|
{
|
|
|
|
/* Nearest object to given point or NULL */
|
|
|
|
DAllObjs *all;
|
|
|
|
DAllObjs *prev_all = NULL;
|
|
|
|
|
|
|
|
g_assert (del_obj != NULL);
|
|
|
|
|
|
|
|
all = obj->obj_list;
|
|
|
|
|
|
|
|
while (all)
|
|
|
|
{
|
|
|
|
if (all->obj == del_obj)
|
|
|
|
{
|
|
|
|
/* Found the one to delete */
|
|
|
|
if (prev_all)
|
|
|
|
prev_all->next = all->next;
|
|
|
|
else
|
|
|
|
obj->obj_list = all->next;
|
|
|
|
|
|
|
|
/* Draw obj (which will actually undraw it! */
|
|
|
|
del_obj->drawfunc (del_obj);
|
|
|
|
|
|
|
|
free_one_obj (del_obj);
|
|
|
|
g_free (all);
|
|
|
|
|
|
|
|
if (obj_show_single != -1)
|
|
|
|
{
|
|
|
|
/* We've just deleted the only visible one */
|
|
|
|
draw_grid_clear ();
|
|
|
|
obj_show_single = -1; /* Show all again */
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
prev_all = all;
|
|
|
|
all = all->next;
|
|
|
|
}
|
|
|
|
g_warning (_("Hey where has the object gone ?"));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
do_move_all_obj (GdkPoint *to_pnt)
|
|
|
|
{
|
|
|
|
/* Move all objects in one go */
|
|
|
|
/* Undraw/then draw in new pos */
|
2003-10-24 13:28:46 +00:00
|
|
|
gint xdiff = move_all_pnt->x - to_pnt->x;
|
|
|
|
gint ydiff = move_all_pnt->y - to_pnt->y;
|
2003-10-19 21:03:21 +00:00
|
|
|
|
|
|
|
if (xdiff || ydiff)
|
|
|
|
{
|
|
|
|
DAllObjs *all;
|
|
|
|
|
|
|
|
for (all = current_obj->obj_list; all; all = all->next)
|
|
|
|
{
|
|
|
|
Dobject *obj = all->obj;
|
|
|
|
|
|
|
|
/* undraw ! */
|
|
|
|
draw_one_obj (obj);
|
|
|
|
|
|
|
|
update_pnts (obj, xdiff, ydiff);
|
|
|
|
|
|
|
|
/* Draw in new pos */
|
|
|
|
draw_one_obj (obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
*move_all_pnt = *to_pnt;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
do_save_obj (Dobject *obj, FILE *to)
|
|
|
|
{
|
|
|
|
DobjPoints *spnt;
|
|
|
|
|
|
|
|
for (spnt = obj->points; spnt; spnt = spnt->next)
|
|
|
|
{
|
|
|
|
fprintf (to, "%d %d\n", spnt->pnt.x, spnt->pnt.y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
do_move_obj (Dobject *obj,
|
|
|
|
GdkPoint *to_pnt)
|
|
|
|
{
|
|
|
|
/* Move the whole line - undraw the line to start with */
|
|
|
|
/* Then draw in new pos */
|
2003-10-24 13:28:46 +00:00
|
|
|
gint xdiff = 0;
|
|
|
|
gint ydiff = 0;
|
2003-10-19 21:03:21 +00:00
|
|
|
|
|
|
|
get_diffs (obj, &xdiff, &ydiff, to_pnt);
|
|
|
|
|
|
|
|
if (xdiff || ydiff)
|
|
|
|
{
|
|
|
|
/* undraw ! */
|
|
|
|
draw_one_obj (obj);
|
|
|
|
|
|
|
|
update_pnts (obj, xdiff, ydiff);
|
|
|
|
|
|
|
|
/* Draw in new pos */
|
|
|
|
draw_one_obj (obj);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
do_move_obj_pnt (Dobject *obj,
|
|
|
|
GdkPoint *to_pnt)
|
|
|
|
{
|
|
|
|
/* Move the whole line - undraw the line to start with */
|
|
|
|
/* Then draw in new pos */
|
|
|
|
DobjPoints *spnt;
|
2003-10-24 13:28:46 +00:00
|
|
|
gint xdiff = 0;
|
|
|
|
gint ydiff = 0;
|
2003-10-19 21:03:21 +00:00
|
|
|
|
|
|
|
spnt = get_diffs (obj, &xdiff, &ydiff, to_pnt);
|
|
|
|
|
|
|
|
if ((!xdiff && !ydiff) || !spnt)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* undraw ! */
|
|
|
|
draw_one_obj (obj);
|
|
|
|
|
|
|
|
spnt->pnt.x = spnt->pnt.x - xdiff;
|
|
|
|
spnt->pnt.y = spnt->pnt.y - ydiff;
|
|
|
|
|
|
|
|
/* Draw in new pos */
|
|
|
|
draw_one_obj (obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* copy objs */
|
|
|
|
DAllObjs *
|
|
|
|
copy_all_objs (DAllObjs *objs)
|
|
|
|
{
|
|
|
|
DAllObjs *nobj;
|
|
|
|
DAllObjs *new_all_objs = NULL;
|
|
|
|
DAllObjs *ret = NULL;
|
|
|
|
|
|
|
|
while (objs)
|
|
|
|
{
|
|
|
|
nobj = g_new0 (DAllObjs, 1);
|
|
|
|
|
|
|
|
if (!ret)
|
|
|
|
{
|
|
|
|
ret = new_all_objs = nobj;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
new_all_objs->next = nobj;
|
|
|
|
new_all_objs = nobj;
|
|
|
|
}
|
|
|
|
|
|
|
|
nobj->obj = (Dobject *) objs->obj->copyfunc (objs->obj);
|
|
|
|
|
|
|
|
objs = objs->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Screen refresh */
|
|
|
|
static void
|
|
|
|
draw_one_obj (Dobject * obj)
|
|
|
|
{
|
|
|
|
obj->drawfunc (obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
draw_objects (DAllObjs *objs,
|
|
|
|
gint show_single)
|
|
|
|
{
|
|
|
|
/* Show_single - only one object to draw Unless shift
|
|
|
|
* is down in which case show all.
|
|
|
|
*/
|
|
|
|
|
|
|
|
gint count = 0;
|
|
|
|
|
|
|
|
while (objs)
|
|
|
|
{
|
|
|
|
if (!show_single || count == obj_show_single || obj_show_single == -1)
|
|
|
|
draw_one_obj (objs->obj);
|
|
|
|
|
|
|
|
objs = objs->next;
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
prepend_to_all_obj (GFigObj *fobj,
|
|
|
|
DAllObjs *nobj)
|
|
|
|
{
|
|
|
|
DAllObjs *cobj;
|
|
|
|
|
|
|
|
setup_undo (); /* Remember ME */
|
|
|
|
|
|
|
|
if (!fobj->obj_list)
|
|
|
|
{
|
|
|
|
fobj->obj_list = nobj;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
cobj = fobj->obj_list;
|
|
|
|
|
|
|
|
while (cobj->next)
|
|
|
|
{
|
|
|
|
cobj = cobj->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
cobj->next = nobj;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
scale_obj_points (DobjPoints *opnt,
|
|
|
|
gdouble scale_x,
|
|
|
|
gdouble scale_y)
|
|
|
|
{
|
|
|
|
while (opnt)
|
|
|
|
{
|
|
|
|
opnt->pnt.x = (gint) (opnt->pnt.x * scale_x);
|
|
|
|
opnt->pnt.y = (gint) (opnt->pnt.y * scale_y);
|
|
|
|
opnt = opnt->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
add_to_all_obj (GFigObj *fobj,
|
|
|
|
Dobject *obj)
|
|
|
|
{
|
|
|
|
DAllObjs *nobj;
|
|
|
|
|
|
|
|
nobj = g_new0 (DAllObjs, 1);
|
|
|
|
|
|
|
|
nobj->obj = obj;
|
|
|
|
|
|
|
|
if (need_to_scale)
|
|
|
|
scale_obj_points (obj->points, scale_x_factor, scale_y_factor);
|
|
|
|
|
|
|
|
prepend_to_all_obj (fobj, nobj);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* First button press -- start drawing object */
|
|
|
|
void
|
|
|
|
object_start (GdkPoint *pnt,
|
|
|
|
gint shift_down)
|
|
|
|
{
|
|
|
|
/* start for the current object */
|
|
|
|
if (!selvals.scaletoimage)
|
|
|
|
{
|
|
|
|
need_to_scale = 1;
|
|
|
|
selvals.scaletoimage = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
need_to_scale = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (selvals.otype)
|
|
|
|
{
|
|
|
|
case LINE:
|
|
|
|
/* Shift means we are still drawing */
|
|
|
|
if (!shift_down || !obj_creating)
|
|
|
|
draw_sqr (pnt);
|
|
|
|
d_line_start (pnt, shift_down);
|
|
|
|
break;
|
|
|
|
case CIRCLE:
|
|
|
|
draw_sqr (pnt);
|
|
|
|
d_circle_start (pnt, shift_down);
|
|
|
|
break;
|
|
|
|
case ELLIPSE:
|
|
|
|
draw_sqr (pnt);
|
|
|
|
d_ellipse_start (pnt, shift_down);
|
|
|
|
break;
|
|
|
|
case POLY:
|
|
|
|
draw_sqr (pnt);
|
|
|
|
d_poly_start (pnt, shift_down);
|
|
|
|
break;
|
|
|
|
case ARC:
|
|
|
|
d_arc_start (pnt, shift_down);
|
|
|
|
break;
|
|
|
|
case STAR:
|
|
|
|
draw_sqr (pnt);
|
|
|
|
d_star_start (pnt, shift_down);
|
|
|
|
break;
|
|
|
|
case SPIRAL:
|
|
|
|
draw_sqr (pnt);
|
|
|
|
d_spiral_start (pnt, shift_down);
|
|
|
|
break;
|
|
|
|
case BEZIER:
|
|
|
|
if (!tmp_bezier)
|
|
|
|
draw_sqr (pnt);
|
|
|
|
d_bezier_start (pnt, shift_down);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* Internal error */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
object_end (GdkPoint *pnt,
|
|
|
|
gint shift_down)
|
|
|
|
{
|
|
|
|
/* end for the current object */
|
|
|
|
/* Add onto global object list */
|
|
|
|
|
|
|
|
/* If shift is down may carry on drawing */
|
|
|
|
switch (selvals.otype)
|
|
|
|
{
|
|
|
|
case LINE:
|
|
|
|
d_line_end (pnt, shift_down);
|
|
|
|
draw_sqr (pnt);
|
|
|
|
break;
|
|
|
|
case CIRCLE:
|
|
|
|
draw_sqr (pnt);
|
|
|
|
d_circle_end (pnt, shift_down);
|
|
|
|
break;
|
|
|
|
case ELLIPSE:
|
|
|
|
draw_sqr (pnt);
|
|
|
|
d_ellipse_end (pnt, shift_down);
|
|
|
|
break;
|
|
|
|
case POLY:
|
|
|
|
draw_sqr (pnt);
|
|
|
|
d_poly_end (pnt, shift_down);
|
|
|
|
break;
|
|
|
|
case STAR:
|
|
|
|
draw_sqr (pnt);
|
|
|
|
d_star_end (pnt, shift_down);
|
|
|
|
break;
|
|
|
|
case ARC:
|
|
|
|
draw_sqr (pnt);
|
|
|
|
d_arc_end (pnt, shift_down);
|
|
|
|
break;
|
|
|
|
case SPIRAL:
|
|
|
|
draw_sqr (pnt);
|
|
|
|
d_spiral_end (pnt, shift_down);
|
|
|
|
break;
|
|
|
|
case BEZIER:
|
|
|
|
d_bezier_end (pnt, shift_down);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* Internal error */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (need_to_scale)
|
|
|
|
{
|
|
|
|
need_to_scale = 0;
|
|
|
|
selvals.scaletoimage = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
object_update (GdkPoint *pnt)
|
|
|
|
{
|
|
|
|
/* update for the current object */
|
|
|
|
/* New position xy */
|
|
|
|
switch (selvals.otype)
|
|
|
|
{
|
|
|
|
case LINE:
|
|
|
|
d_update_line (pnt);
|
|
|
|
break;
|
|
|
|
case CIRCLE:
|
|
|
|
d_update_circle (pnt);
|
|
|
|
break;
|
|
|
|
case ELLIPSE:
|
|
|
|
d_update_ellipse (pnt);
|
|
|
|
break;
|
|
|
|
case POLY:
|
|
|
|
d_update_poly (pnt);
|
|
|
|
break;
|
|
|
|
case STAR:
|
|
|
|
d_update_star (pnt);
|
|
|
|
break;
|
|
|
|
case ARC:
|
|
|
|
d_update_arc (pnt);
|
|
|
|
break;
|
|
|
|
case SPIRAL:
|
|
|
|
d_update_spiral (pnt);
|
|
|
|
break;
|
|
|
|
case BEZIER:
|
|
|
|
d_update_bezier (pnt);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* Internal error */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|