Fix for #124158. (always show both the Paint

and Select Tab). Also first attempt to split this hug file into
smaller pieces to make this plug-in a bit more manageable.
This commit is contained in:
Maurits Rijk 2003-10-19 09:44:46 +00:00
parent 9407ecba10
commit 416d2e2fdc
21 changed files with 5373 additions and 4807 deletions

View File

@ -1,3 +1,12 @@
2003-10-19 Maurits Rijk <lpeek.mrijk@consunet.nl>
* Makefile.am
* plug-ins/gfig/gfig_*.[ch]: new files split from gfig.c
* plug-ins/gfig/gfig.c: fix for #124158 (always show both the Paint
and Select Tab). Also first attempt to split this hug file into
smaller pieces to make this plug-in a bit more manageable.
2003-10-19 Sven Neumann <sven@gimp.org>
* app/config/Makefile.am

View File

@ -14,6 +14,23 @@ libexec_PROGRAMS = gfig
gfig_SOURCES = \
gfig.c \
gfig.h \
gfig_arc.c \
gfig_arc.h \
gfig_bezier.c \
gfig_bezier.h \
gfig_circle.c \
gfig_circle.h \
gfig_ellipse.c \
gfig_ellipse.h \
gfig_line.c \
gfig_line.h \
gfig_poly.c \
gfig_poly.h \
gfig_spiral.c \
gfig_spiral.h \
gfig_star.c \
gfig_star.h \
gfig-stock.c \
gfig-stock.h \
pix_data.h

File diff suppressed because it is too large Load Diff

213
plug-ins/gfig/gfig.h Normal file
View File

@ -0,0 +1,213 @@
/*
* 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.
*
*/
#ifndef __GFIG_H__
#define __GFIG_H__
#include "gfig_dobject.h"
#define MAX_LOAD_LINE 256
extern gint line_no;
extern gint preview_width, preview_height;
extern gint drawing_pic;
extern gint need_to_scale;
extern gint32 gfig_image;
extern gint32 gfig_drawable;
extern GdkGC *gfig_gc;
extern gdouble scale_x_factor, scale_y_factor;
extern GtkWidget *gfig_preview;
extern GtkWidget *pic_preview;
extern Dobject *tmp_line;
typedef enum
{
RECT_GRID = 0,
POLAR_GRID,
ISO_GRID
} GridType;
typedef struct
{
gint gridspacing;
GridType gridtype;
gboolean drawgrid;
gboolean snap2grid;
gboolean lockongrid;
gboolean showcontrol;
} GfigOpts;
typedef enum
{
ADD = 0,
SUBTRACT,
REPLACE,
INTERSECT
} SelectionType;
typedef enum
{
ARC_SEGMENT = 0,
ARC_SECTOR
} ArcType;
typedef enum
{
FILL_FOREGROUND = 0,
FILL_BACKGROUND,
FILL_PATTERN
} FillType;
typedef enum
{
FILL_EACH = 0,
FILL_AFTER
} FillWhen;
typedef struct
{
SelectionType type; /* ADD etc .. */
gint antia; /* Boolean for Antia */
gint feather; /* Feather it ? */
gdouble feather_radius; /* Radius to feather */
ArcType as_pie; /* Arc type selection segment/sector */
FillType fill_type; /* Fill type for selection */
FillWhen fill_when; /* Fill on each selection or after all? */
gdouble fill_opacity; /* You can guess this one */
} selection_option;
typedef enum
{
ORIGINAL_LAYER = 0,
SINGLE_LAYER,
MULTI_LAYER
} DrawonLayers;
typedef enum
{
LAYER_TRANS_BG = 0,
LAYER_BG_BG,
LAYER_FG_BG,
LAYER_WHITE_BG,
LAYER_COPY_BG
} LayersBGType;
typedef enum
{
PAINT_BRUSH_TYPE = 0,
PAINT_SELECTION_TYPE,
PAINT_SELECTION_FILL_TYPE
} PaintType;
typedef enum
{
BRUSH_BRUSH_TYPE = 0,
BRUSH_PENCIL_TYPE,
BRUSH_AIRBRUSH_TYPE,
BRUSH_PATTERN_TYPE
} BrushType;
typedef struct
{
GfigOpts opts;
gboolean showimage;
gint maxundo;
gboolean showpos;
gdouble brushfade;
gdouble brushgradient;
gdouble airbrushpressure;
DrawonLayers onlayers;
LayersBGType onlayerbg;
PaintType painttype;
gboolean reverselines;
gboolean scaletoimage;
gdouble scaletoimagefp;
gboolean approxcircles;
BrushType brshtype;
DobjType otype;
} SelectItVals;
typedef struct DAllObjs
{
struct DAllObjs *next;
Dobject *obj; /* Object on list */
} DAllObjs;
typedef struct DFigObj
{
gchar *name; /* Trailing name of file */
gchar *filename; /* Filename itself */
gchar *draw_name; /* Name of the drawing */
gfloat version; /* Version number of data file */
GfigOpts opts; /* Options enforced when fig saved */
DAllObjs *obj_list; /* Objects that make up this list */
gint obj_status; /* See above for possible values */
GtkWidget *list_item;
GtkWidget *label_widget;
GtkWidget *pixmap_widget;
} GFigObj;
extern GFigObj *current_obj;
extern selection_option selopt;
extern SelectItVals selvals;
void add_to_all_obj (GFigObj * fobj, Dobject *obj);
gchar *get_line (gchar *buf,
gint s,
FILE *from,
gint init);
gint gfig_scale_x (gint x);
gint gfig_scale_y (gint y);
void scale_to_xy (gdouble *list,
gint size);
void scale_to_original_xy (gdouble *list,
gint size);
gint adjust_pic_coords (gint coord,
gint ratio);
void reverse_pairs_list (gdouble *list,
gint size);
void gfig_paint (BrushType brush_type,
gint32 drawable_ID,
gint seg_count,
gdouble line_pnts[]);
void draw_circle (GdkPoint *p);
void draw_sqr (GdkPoint *p);
void num_sides_dialog (gchar *d_title,
gint *num_sides,
gint *which_way,
gint adj_min,
gint adj_max);
#endif /* __GFIG_H__ */

768
plug-ins/gfig/gfig_arc.c Normal file
View File

@ -0,0 +1,768 @@
/*
* 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.
*
*/
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gtk/gtk.h>
#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>
#include "config.h"
#include "libgimp/stdplugins-intl.h"
#include "gfig.h"
#include "gfig_line.h"
static Dobject * d_new_arc (gint x, gint y);
/* Distance between two lines */
static gdouble
dist (gdouble x1,
gdouble y1,
gdouble x2,
gdouble y2)
{
double s1 = x1 - x2;
double s2 = y1 - y2;
return sqrt (s1 * s1 + s2 * s2);
}
/* Mid point of line returned */
static void
mid_point (gdouble x1,
gdouble y1,
gdouble x2,
gdouble y2,
gdouble *mx,
gdouble *my)
{
*mx = ((double) (x1 - x2))/2.0 + (double)x2;
*my = ((double) (y1 - y2))/2.0 + (double)y2;
}
/* Careful about infinite grads */
static gdouble
line_grad (gdouble x1,
gdouble y1,
gdouble x2,
gdouble y2)
{
double dx, dy;
dx = x1 - x2;
dy = y1 - y2;
return (dx == 0.0) ? 0.0 : dy / dx;
}
/* Constant of line that goes through x, y with grad lgrad */
static gdouble
line_cons (gdouble x,
gdouble y,
gdouble lgrad)
{
return y - lgrad * x;
}
/*Get grad & const for perpend. line to given points */
static void
line_definition (gdouble x1,
gdouble y1,
gdouble x2,
gdouble y2,
gdouble *lgrad,
gdouble *lconst)
{
double grad1;
double midx, midy;
grad1 = line_grad (x1, y1, x2, y2);
if (grad1 == 0.0)
{
#ifdef DEBUG
printf ("Infinite grad....\n");
#endif /* DEBUG */
return;
}
mid_point (x1, y1, x2, y2, &midx, &midy);
/* Invert grad for perpen gradient */
*lgrad = -1.0/grad1;
*lconst = line_cons (midx, midy,*lgrad);
}
/* Arch details
* Given three points get arc radius and the co-ords
* of center point.
*/
static void
arc_details (GdkPoint *vert_a,
GdkPoint *vert_b,
GdkPoint *vert_c,
GdkPoint *center_pnt,
gdouble *radius)
{
/* Only vertices are in whole numbers - everything else is in doubles */
double ax, ay;
double bx, by;
double cx, cy;
double len_a, len_b, len_c;
double sum_sides2;
double area;
double circumcircle_R;
double line1_grad, line1_const;
double line2_grad, line2_const;
double inter_x=0.0, inter_y=0.0;
int got_x=0, got_y=0;
ax = (double) (vert_a->x);
ay = (double) (vert_a->y);
bx = (double) (vert_b->x);
by = (double) (vert_b->y);
cx = (double) (vert_c->x);
cy = (double) (vert_c->y);
#ifdef DEBUG
printf ("Vertices (%f,%f), (%f,%f), (%f,%f)\n", ax, ay, bx, by, cx, cy);
#endif /* DEBUG */
len_a = dist (ax, ay, bx, by);
len_b = dist (bx, by, cx, cy);
len_c = dist (cx, cy, ax, ay);
#ifdef DEBUG
printf ("len_a = %f, len_b = %f, len_c = %f\n", len_a, len_b, len_c);
#endif /* DEBUG */
sum_sides2 = (fabs (len_a) + fabs (len_b) + fabs (len_c))/2;
#ifdef DEBUG
printf ("Sum sides / 2 = %f\n", sum_sides2);
#endif /* DEBUG */
/* Area */
area = sqrt (sum_sides2*(sum_sides2 - len_a)*(sum_sides2 - len_b)*(sum_sides2 - len_c));
#ifdef DEBUG
printf ("Area of triangle = %f\n", area);
#endif /* DEBUG */
/* Circumcircle */
circumcircle_R = len_a*len_b*len_c/(4*area);
*radius = circumcircle_R;
#ifdef DEBUG
printf ("Circumcircle radius = %f\n", circumcircle_R);
#endif /* DEBUG */
/* Deal with exceptions - I hate exceptions */
if (ax == bx || ax == cx || cx == bx)
{
/* vert line -> mid point gives inter_x */
if (ax == bx && bx == cx)
{
/* Straight line */
double miny = ay;
double maxy = ay;
if (by > maxy)
maxy = by;
if (by < miny)
miny = by;
if (cy > maxy)
maxy = cy;
if (cy < miny)
miny = cy;
inter_y = (maxy - miny)/2 + miny;
}
else if (ax == bx)
{
inter_y = (ay - by)/2 + by;
}
else if (bx == cx)
{
inter_y = (by - cy)/2 + cy;
}
else
{
inter_y = (cy - ay)/2 + ay;
}
got_y = 1;
}
if (ay == by || by == cy || ay == cy)
{
/* Horz line -> midpoint gives inter_y */
if (ax == bx && bx == cx)
{
/* Straight line */
double minx = ax;
double maxx = ax;
if (bx > maxx)
maxx = bx;
if (bx < minx)
minx = bx;
if (cx > maxx)
maxx = cx;
if (cx < minx)
minx = cx;
inter_x = (maxx - minx)/2 + minx;
}
else if (ay == by)
{
inter_x = (ax - bx)/2 + bx;
}
else if (by == cy)
{
inter_x = (bx - cx)/2 + cx;
}
else
{
inter_x = (cx - ax)/2 + ax;
}
got_x = 1;
}
if (!got_x || !got_y)
{
/* At least two of the lines are not parallel to the axis */
/*first line */
if (ax != bx && ay != by)
line_definition (ax, ay, bx, by, &line1_grad, &line1_const);
else
line_definition (ax, ay, cx, cy, &line1_grad, &line1_const);
/* second line */
if (bx != cx && by != cy)
line_definition (bx, by, cx, cy, &line2_grad, &line2_const);
else
line_definition (ax, ay, cx, cy, &line2_grad, &line2_const);
}
/* Intersection point */
if (!got_x)
inter_x = /*rint*/((line2_const - line1_const)/(line1_grad - line2_grad));
if (!got_y)
inter_y = /*rint*/((line1_grad * inter_x + line1_const));
#ifdef DEBUG
printf ("Intersection point is (%f,%f)\n", inter_x, inter_y);
#endif /* DEBUG */
center_pnt->x = (gint16)inter_x;
center_pnt->y = (gint16)inter_y;
}
static gdouble
arc_angle (GdkPoint *pnt,
GdkPoint *center)
{
/* Get angle (in degress) of point given origin of center */
gint16 shift_x;
gint16 shift_y;
gdouble offset_angle;
shift_x = pnt->x - center->x;
shift_y = -pnt->y + center->y;
offset_angle = atan2 (shift_y, shift_x);
#ifdef DEBUG
printf ("offset_ang = %f\n", offset_angle);
#endif /* DEBUG */
if (offset_angle < 0)
offset_angle += 2*G_PI;
return (offset_angle*360/(2*G_PI));
}
static void
d_save_arc (Dobject *obj,
FILE *to)
{
DobjPoints * spnt;
spnt = obj->points;
if (!spnt)
return;
fprintf (to, "<ARC>\n");
while (spnt)
{
fprintf (to, "%d %d\n",
spnt->pnt.x,
spnt->pnt.y);
spnt = spnt->next;
}
fprintf (to, "</ARC>\n");
}
Dobject *
d_load_arc (FILE *from)
{
Dobject *new_obj = NULL;
gint xpnt;
gint ypnt;
gchar buf[MAX_LOAD_LINE];
gint num_pnts = 0;
#ifdef DEBUG
printf ("Load arc called\n");
#endif /* DEBUG */
while (get_line (buf, MAX_LOAD_LINE, from, 0))
{
if (sscanf (buf, "%d %d", &xpnt, &ypnt) != 2)
{
/* Must be the end */
if (strcmp ("</ARC>", buf) || num_pnts != 3)
{
g_warning ("[%d] Internal load error while loading arc",
line_no);
return (NULL);
}
return (new_obj);
}
num_pnts++;
if (!new_obj)
new_obj = d_new_arc (xpnt, ypnt);
else
{
d_pnt_add_line (new_obj, xpnt, ypnt,-1);
}
}
g_warning ("[%d] Not enough points for arc", line_no);
return (NULL);
}
static void
arc_drawing_details (Dobject *obj,
gdouble *minang,
GdkPoint *center_pnt,
gdouble *arcang,
gdouble *radius,
gint draw_cnts,
gint do_scale)
{
DobjPoints * pnt1 = NULL;
DobjPoints * pnt2 = NULL;
DobjPoints * pnt3 = NULL;
DobjPoints dpnts[3];
gdouble ang1, ang2, ang3;
gdouble maxang;
pnt1 = obj->points;
if (!pnt1)
return; /* Not fully drawn */
pnt2 = pnt1->next;
if (!pnt2)
return; /* Not fully drawn */
pnt3 = pnt2->next;
if (!pnt3)
return; /* Still not fully drawn */
if (draw_cnts)
{
draw_sqr (&pnt1->pnt);
draw_sqr (&pnt2->pnt);
draw_sqr (&pnt3->pnt);
}
if (do_scale)
{
/* Adjust pnts for scaling */
/* Warning struct copies here! and casting to double <-> int */
/* Too complex fix me - to much hacking */
gdouble xy[2];
int j;
dpnts[0] = *pnt1;
dpnts[1] = *pnt2;
dpnts[2] = *pnt3;
pnt1 = &dpnts[0];
pnt2 = &dpnts[1];
pnt3 = &dpnts[2];
for (j = 0 ; j < 3; j++)
{
xy[0] = dpnts[j].pnt.x;
xy[1] = dpnts[j].pnt.y;
if (selvals.scaletoimage)
scale_to_original_xy (&xy[0], 1);
else
scale_to_xy (&xy[0], 1);
dpnts[j].pnt.x = xy[0];
dpnts[j].pnt.y = xy[1];
}
}
arc_details (&pnt1->pnt, &pnt2->pnt, &pnt3->pnt, center_pnt, radius);
ang1 = arc_angle (&pnt1->pnt, center_pnt);
ang2 = arc_angle (&pnt2->pnt, center_pnt);
ang3 = arc_angle (&pnt3->pnt, center_pnt);
/* Find min/max angle */
maxang = ang1;
if (ang3 > maxang)
maxang = ang3;
*minang = ang1;
if (ang3 < *minang)
*minang = ang3;
if (ang2 > *minang && ang2 < maxang)
*arcang = maxang - *minang;
else
*arcang = maxang - *minang - 360;
}
static void
d_draw_arc (Dobject * obj)
{
GdkPoint center_pnt;
gdouble radius, minang, arcang;
g_assert (obj != NULL);
if (!obj)
return;
arc_drawing_details (obj, &minang, &center_pnt, &arcang, &radius, TRUE, FALSE);
#ifdef DEBUG
printf ("Min ang = %f Arc ang = %f\n", minang, arcang);
#endif /* DEBUG */
if (drawing_pic)
{
gdk_draw_arc (pic_preview->window,
pic_preview->style->black_gc,
0,
adjust_pic_coords (center_pnt.x - (gint)radius,
preview_width),
adjust_pic_coords (center_pnt.y - (gint)radius,
preview_height),
adjust_pic_coords ((gint) (radius * 2),
preview_width),
adjust_pic_coords ((gint) (radius * 2),
preview_height),
(gint) (minang*64),
(gint) (arcang*64));
}
else
{
gdk_draw_arc (gfig_preview->window,
gfig_gc,
0,
gfig_scale_x (center_pnt.x - (gint)radius),
gfig_scale_y (center_pnt.y - (gint)radius),
gfig_scale_x ((gint) (radius * 2)),
gfig_scale_y ((gint) (radius * 2)),
(gint) (minang*64),
(gint) (arcang*64));
}
}
static void
d_paint_arc (Dobject *obj)
{
/* first point center */
/* Next point is radius */
gdouble *line_pnts;
gint seg_count = 0;
gint i = 0;
gdouble ang_grid;
gdouble ang_loop;
gdouble radius;
gint loop;
GdkPoint first_pnt, last_pnt;
gint first = 1;
GdkPoint center_pnt;
gdouble minang, arcang;
g_assert (obj != NULL);
if (!obj)
return;
/* No cnt pnts & must scale */
arc_drawing_details (obj, &minang, &center_pnt, &arcang, &radius, FALSE, TRUE);
#ifdef DEBUG
printf ("Paint Min ang = %f Arc ang = %f\n", minang, arcang);
#endif /* DEBUG */
seg_count = 360; /* Should make a smoth-ish curve */
/* +3 because we MIGHT do pie selection */
line_pnts = g_new0 (gdouble, 2 * seg_count + 3);
/* Lines */
ang_grid = 2*G_PI/(gdouble)360;
if (arcang < 0.0)
{
/* Swap - since we always draw anti-clock wise */
minang += arcang;
arcang = -arcang;
}
minang = minang * (2*G_PI/360); /* min ang is in degrees - need in rads*/
for (loop = 0 ; loop < abs ((gint)arcang) ; loop++)
{
gdouble lx, ly;
GdkPoint calc_pnt;
ang_loop = (gdouble)loop * ang_grid + minang;
lx = radius * cos (ang_loop);
ly = -radius * sin (ang_loop); /* y grows down screen and angs measured from x clockwise */
calc_pnt.x = RINT (lx + center_pnt.x);
calc_pnt.y = RINT (ly + center_pnt.y);
/* Miss out duped pnts */
if (!first)
{
if (calc_pnt.x == last_pnt.x && calc_pnt.y == last_pnt.y)
{
continue;
}
}
last_pnt.x = line_pnts[i++] = calc_pnt.x;
last_pnt.y = line_pnts[i++] = calc_pnt.y;
if (first)
{
first_pnt = calc_pnt;
first = 0;
}
}
/* Reverse line if approp */
if (selvals.reverselines)
reverse_pairs_list (&line_pnts[0], i/2);
/* One go */
if (selvals.painttype == PAINT_BRUSH_TYPE)
{
gfig_paint (selvals.brshtype,
gfig_drawable,
i, line_pnts);
}
else
{
if (selopt.as_pie)
{
/* Add center point - cause a pie like selection... */
line_pnts[i++] = center_pnt.x;
line_pnts[i++] = center_pnt.y;
}
gimp_free_select (gfig_image,
i, line_pnts,
selopt.type,
selopt.antia,
selopt.feather,
selopt.feather_radius);
}
g_free (line_pnts);
}
static Dobject *
d_copy_arc (Dobject * obj)
{
Dobject *nc;
if (!obj)
return NULL;
g_assert (obj->type == ARC);
nc = d_new_arc (obj->points->pnt.x, obj->points->pnt.y);
nc->points->next = d_copy_dobjpoints (obj->points->next);
#if DEBUG
printf ("Arc (%x,%x), (%x,%x), (%x,%x)\n",
nc->points->pnt.x, obj->points->pnt.y,
nc->points->next->pnt.x, obj->points->next->pnt.y,
nc->points->next->next->pnt.x, obj->points->next->next->pnt.y);
printf ("Done copy\n");
#endif /* DEBUG */
return nc;
}
static Dobject *
d_new_arc (gint x,
gint y)
{
Dobject *nobj;
DobjPoints *npnt;
/* Get new object and starting point */
/* Start point */
npnt = g_new0 (DobjPoints, 1);
#if DEBUG
printf ("New arc start at (%x,%x)\n", x, y);
#endif /* DEBUG */
npnt->pnt.x = x;
npnt->pnt.y = y;
nobj = g_new0 (Dobject, 1);
nobj->type = ARC;
nobj->points = npnt;
nobj->drawfunc = d_draw_arc;
nobj->loadfunc = d_load_arc;
nobj->savefunc = d_save_arc;
nobj->paintfunc = d_paint_arc;
nobj->copyfunc = d_copy_arc;
return (nobj);
}
void
d_update_arc (GdkPoint *pnt)
{
DobjPoints * pnt1 = NULL;
DobjPoints * pnt2 = NULL;
DobjPoints * pnt3 = NULL;
/* First two points as line only become arch when third
* point is placed on canvas.
*/
pnt1 = obj_creating->points;
if (!pnt1 ||
!(pnt2 = pnt1->next) ||
!(pnt3 = pnt2->next))
{
d_update_line (pnt);
return; /* Not fully drawn */
}
/* Update a real curve */
/* Nothing to be done ... */
}
void
d_arc_start (GdkPoint *pnt,
gint shift_down)
{
/* Draw lines to start with -- then convert to an arc */
if (!tmp_line)
draw_sqr (pnt);
d_line_start (pnt, TRUE); /* TRUE means multiple pointed line */
}
void
d_arc_end (GdkPoint *pnt,
gint shift_down)
{
/* Under contrl point */
if (!tmp_line ||
!tmp_line->points ||
!tmp_line->points->next)
{
/* No arc created - yet */
/* Must have three points */
#ifdef DEBUG
printf ("No arc created yet\n");
#endif /* DEBUG */
d_line_end (pnt, TRUE);
}
else
{
/* Complete arc */
/* Convert to an arc ... */
tmp_line->type = ARC;
tmp_line->drawfunc = d_draw_arc;
tmp_line->loadfunc = d_load_arc;
tmp_line->savefunc = d_save_arc;
tmp_line->paintfunc = d_paint_arc;
tmp_line->copyfunc = d_copy_arc;
d_line_end (pnt, FALSE);
/*d_draw_line (newarc); Should undraw line */
if (need_to_scale)
{
selvals.scaletoimage = 0;
}
/*d_draw_arc (newarc);*/
gtk_widget_queue_draw (gfig_preview);
if (need_to_scale)
{
selvals.scaletoimage = 1;
}
}
}

37
plug-ins/gfig/gfig_arc.h Normal file
View File

@ -0,0 +1,37 @@
/*
* 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.
*
*/
#ifndef __GFIG_ARC_H__
#define __GFIG_ARC_H__
Dobject *d_load_arc (FILE *from);
void d_update_arc (GdkPoint *pnt);
void d_arc_start (GdkPoint *pnt,
gint shift_down);
void d_arc_end (GdkPoint *pnt,
gint shift_down);
#endif /* __GFIG_ARC_H__ */

632
plug-ins/gfig/gfig_bezier.c Normal file
View File

@ -0,0 +1,632 @@
/*
* 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.
*
*/
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <gtk/gtk.h>
#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>
#include "config.h"
#include "libgimp/stdplugins-intl.h"
#include "gfig.h"
static gint bezier_closed = 0; /* Closed curve 0 = false 1 = true */
static gint bezier_line_frame = 0; /* Show frame = false 1 = true */
Dobject *tmp_bezier; /* Neeed when drawing bezier curves */
static void d_paint_bezier (Dobject *obj);
static Dobject * d_copy_bezier (Dobject * obj);
static Dobject * d_new_bezier (gint x, gint y);
static void
d_save_bezier (Dobject *obj,
FILE *to)
{
DobjPoints *spnt;
spnt = obj->points;
if (!spnt)
return; /* End-of-line */
fprintf (to, "<BEZIER>\n");
while (spnt)
{
fprintf (to, "%d %d\n",
spnt->pnt.x,
spnt->pnt.y);
spnt = spnt->next;
}
fprintf (to, "<EXTRA>\n");
fprintf (to, "%d\n</EXTRA>\n", obj->type_data);
fprintf (to, "</BEZIER>\n");
}
/* Load a bezier from the specified stream */
Dobject *
d_load_bezier (FILE *from)
{
Dobject *new_obj = NULL;
gint xpnt;
gint ypnt;
gchar buf[MAX_LOAD_LINE];
#ifdef DEBUG
printf ("Load bezier called\n");
#endif /* DEBUG */
while (get_line (buf, MAX_LOAD_LINE, from, 0))
{
if (sscanf (buf, "%d %d", &xpnt, &ypnt) != 2)
{
/* Must be the end */
if (!strcmp ("<EXTRA>", buf))
{
gint nsides = 3;
/* Number of sides - data item */
if ( !new_obj)
{
g_message ("[%d] Internal load error while loading bezier "
"(extra area)", line_no);
return NULL;
}
get_line (buf, MAX_LOAD_LINE, from, 0);
if (sscanf (buf, "%d", &nsides) != 1)
{
g_message ("[%d] Internal load error while loading bezier "
"(extra area scanf)", line_no);
return NULL;
}
new_obj->type_data = nsides;
get_line (buf, MAX_LOAD_LINE, from, 0);
if (strcmp ("</EXTRA>", buf))
{
g_message ("[%d] Internal load error while loading bezier",
line_no);
return NULL;
}
/* Go around and read the last line */
continue;
}
else if (strcmp ("</BEZIER>", buf))
{
g_message ("[%d] Internal load error while loading bezier",
line_no);
return NULL;
}
return new_obj;
}
if (!new_obj)
new_obj = d_new_bezier (xpnt, ypnt);
else
d_pnt_add_line (new_obj, xpnt, ypnt, -1);
}
return new_obj;
}
#define FP_PNT_MAX 10
static int fp_pnt_cnt = 0;
static int fp_pnt_chunk = 0;
static gdouble *fp_pnt_pnts = NULL;
static void
fp_pnt_start (void)
{
fp_pnt_cnt = 0;
}
/* Add a line segment to collection array */
static void
fp_pnt_add (gdouble p1,
gdouble p2,
gdouble p3,
gdouble p4)
{
if (!fp_pnt_pnts)
{
fp_pnt_pnts = g_new0 (gdouble, FP_PNT_MAX);
fp_pnt_chunk = 1;
}
if (((fp_pnt_cnt + 4) / FP_PNT_MAX) >= fp_pnt_chunk)
{
/* more space pls */
fp_pnt_chunk++;
fp_pnt_pnts =
(gdouble *) g_realloc (fp_pnt_pnts,
sizeof (gdouble) * fp_pnt_chunk * FP_PNT_MAX);
}
fp_pnt_pnts[fp_pnt_cnt++] = p1;
fp_pnt_pnts[fp_pnt_cnt++] = p2;
fp_pnt_pnts[fp_pnt_cnt++] = p3;
fp_pnt_pnts[fp_pnt_cnt++] = p4;
}
static gdouble *
d_bz_get_array (gint *sz)
{
*sz = fp_pnt_cnt;
return fp_pnt_pnts;
}
static void
d_bz_line (void)
{
gint i, x0, y0, x1, y1;
g_assert ((fp_pnt_cnt % 4) == 0);
for (i = 0 ; i < fp_pnt_cnt; i += 4)
{
x0 = fp_pnt_pnts[i];
y0 = fp_pnt_pnts[i + 1];
x1 = fp_pnt_pnts[i + 2];
y1 = fp_pnt_pnts[i + 3];
if (drawing_pic)
{
gdk_draw_line (pic_preview->window,
pic_preview->style->black_gc,
adjust_pic_coords (x0, preview_width),
adjust_pic_coords (y0, preview_height),
adjust_pic_coords (x1, preview_width),
adjust_pic_coords (y1, preview_height));
}
else
{
gdk_draw_line (gfig_preview->window,
gfig_gc,
gfig_scale_x (x0),
gfig_scale_y (y0),
gfig_scale_x (x1),
gfig_scale_y (y1));
}
}
}
/* Return points to plot */
/* Terminate by point with DBL_MAX, DBL_MAX */
typedef gdouble (*fp_pnt)[2];
static void
DrawBezier (gdouble (*points)[2],
gint np,
gdouble mid,
gint depth)
{
gint i, j, x0 = 0, y0 = 0, x1, y1;
fp_pnt left;
fp_pnt right;
if (depth == 0) /* draw polyline */
{
for (i = 0; i < np; i++)
{
x1 = (int) points[i][0];
y1 = (int) points[i][1];
if (i > 0 && (x1 != x0 || y1 != y0))
{
/* Add pnts up */
fp_pnt_add ((gdouble) x0, (gdouble) y0,
(gdouble) x1, (gdouble) y1);
}
x0 = x1;
y0 = y1;
}
}
else /* subdivide control points at mid */
{
left = (fp_pnt) g_new (gdouble, np * 2);
right = (fp_pnt) g_new (gdouble, np * 2);
for (i = 0; i < np; i++)
{
right[i][0] = points[i][0];
right[i][1] = points[i][1];
}
left[0][0] = right[0][0];
left[0][1] = right[0][1];
for (j = np - 1; j >= 1; j--)
{
for (i = 0; i < j; i++)
{
right[i][0] = (1 - mid) * right[i][0] + mid * right[i + 1][0];
right[i][1] = (1 - mid) * right[i][1] + mid * right[i + 1][1];
}
left[np - j][0] = right[0][0];
left[np - j][1] = right[0][1];
}
if (depth > 0)
{
DrawBezier (left, np, mid, depth - 1);
DrawBezier (right, np, mid, depth - 1);
g_free (left);
g_free (right);
}
}
}
void
d_draw_bezier (Dobject *obj)
{
DobjPoints * spnt;
gint seg_count = 0;
gint i = 0;
gdouble (*line_pnts)[2];
spnt = obj->points;
/* First count the number of points */
for (spnt = obj->points; spnt; spnt = spnt->next)
seg_count++;
if (!seg_count)
return; /* no-line */
line_pnts = (fp_pnt) g_new0 (gdouble, 2 * seg_count + 1);
/* Go around all the points drawing a line from one to the next */
for (spnt = obj->points; spnt; spnt = spnt->next)
{
draw_sqr (&spnt->pnt);
line_pnts[i][0] = spnt->pnt.x;
line_pnts[i++][1] = spnt->pnt.y;
}
/* Generate an array of doubles which are the control points */
if (!drawing_pic && bezier_line_frame && tmp_bezier)
{
fp_pnt_start ();
DrawBezier (line_pnts, seg_count, 0.5, 0);
d_bz_line ();
}
fp_pnt_start ();
DrawBezier (line_pnts, seg_count, 0.5, 3);
d_bz_line ();
/*bezier4 (line_pnts, seg_count, 20);*/
g_free (line_pnts);
}
static void
d_paint_bezier (Dobject *obj)
{
gdouble *line_pnts;
gdouble (*bz_line_pnts)[2];
DobjPoints *spnt;
gint seg_count = 0;
gint i = 0;
/* First count the number of points */
for (spnt = obj->points; spnt; spnt = spnt->next)
seg_count++;
if (!seg_count)
return; /* no-line */
bz_line_pnts = (fp_pnt) g_new0 (gdouble, 2 * seg_count + 1);
/* Go around all the points drawing a line from one to the next */
for (spnt = obj->points; spnt; spnt = spnt->next)
{
bz_line_pnts[i][0] = spnt->pnt.x;
bz_line_pnts[i++][1] = spnt->pnt.y;
}
fp_pnt_start ();
DrawBezier (bz_line_pnts, seg_count, 0.5, 5);
line_pnts = d_bz_get_array (&i);
/* Reverse line if approp */
if (selvals.reverselines)
reverse_pairs_list (&line_pnts[0], i / 2);
/* Scale before drawing */
if (selvals.scaletoimage)
scale_to_original_xy (&line_pnts[0], i / 2);
else
scale_to_xy (&line_pnts[0], i / 2);
/* One go */
if (selvals.painttype == PAINT_BRUSH_TYPE)
{
gfig_paint (selvals.brshtype,
gfig_drawable,
i, line_pnts);
}
else
{
gimp_free_select (gfig_image,
i, line_pnts,
selopt.type,
selopt.antia,
selopt.feather,
selopt.feather_radius);
}
g_free (bz_line_pnts);
/* Don't free line_pnts - may need again */
}
static Dobject *
d_copy_bezier (Dobject * obj)
{
Dobject *np;
#if DEBUG
printf ("Copy bezier\n");
#endif /* DEBUG */
if (!obj)
return (NULL);
g_assert (obj->type == BEZIER);
np = d_new_bezier (obj->points->pnt.x, obj->points->pnt.y);
np->points->next = d_copy_dobjpoints (obj->points->next);
np->type_data = obj->type_data;
#if DEBUG
printf ("Done bezier copy\n");
#endif /* DEBUG */
return np;
}
static Dobject *
d_new_bezier (gint x, gint y)
{
Dobject *nobj;
DobjPoints *npnt;
/* Get new object and starting point */
/* Start point */
npnt = g_new0 (DobjPoints, 1);
#if DEBUG
printf ("New BEZIER start at (%x,%x)\n", x, y);
#endif /* DEBUG */
npnt->pnt.x = x;
npnt->pnt.y = y;
nobj = g_new0 (Dobject, 1);
nobj->type = BEZIER;
nobj->type_data = 4; /* Default to four turns */
nobj->points = npnt;
nobj->drawfunc = d_draw_bezier;
nobj->loadfunc = d_load_bezier;
nobj->savefunc = d_save_bezier;
nobj->paintfunc = d_paint_bezier;
nobj->copyfunc = d_copy_bezier;
return nobj;
}
void
d_update_bezier (GdkPoint *pnt)
{
DobjPoints *s_pnt, *l_pnt;
gint saved_cnt_pnt = selvals.opts.showcontrol;
g_assert (tmp_bezier != NULL);
/* Undraw last one then draw new one */
s_pnt = tmp_bezier->points;
if (!s_pnt)
return; /* No points */
/* Hack - turn off cnt points in draw routine
*/
if ((l_pnt = s_pnt->next))
{
/* Undraw */
while (l_pnt->next)
{
l_pnt = l_pnt->next;
}
draw_circle (&l_pnt->pnt);
selvals.opts.showcontrol = 0;
d_draw_bezier (tmp_bezier);
l_pnt->pnt.x = pnt->x;
l_pnt->pnt.y = pnt->y;
}
else
{
/* Radius is a few pixels away */
/* First edge point */
d_pnt_add_line (tmp_bezier, pnt->x, pnt->y,-1);
l_pnt = s_pnt->next;
}
/* draw it */
selvals.opts.showcontrol = 0;
d_draw_bezier (tmp_bezier);
selvals.opts.showcontrol = saved_cnt_pnt;
/* Realy draw the control points */
draw_circle (&l_pnt->pnt);
}
void
d_bezier_start (GdkPoint *pnt, gint shift_down)
{
gint16 x, y;
/* First is center point */
if (!tmp_bezier)
{
/* New curve */
tmp_bezier = obj_creating = d_new_bezier (x = pnt->x, y = pnt->y);
}
}
void
d_bezier_end (GdkPoint *pnt, gint shift_down)
{
DobjPoints *l_pnt;
if (!tmp_bezier)
{
tmp_bezier = obj_creating;
}
l_pnt = tmp_bezier->points->next;
if (!l_pnt)
return;
if (shift_down)
{
/* Undraw circle on last pnt */
while (l_pnt->next)
{
l_pnt = l_pnt->next;
}
if (l_pnt)
{
draw_circle (&l_pnt->pnt);
draw_sqr (&l_pnt->pnt);
if (bezier_closed)
{
gint tmp_frame = bezier_line_frame;
/* if closed then add first point */
d_draw_bezier (tmp_bezier);
d_pnt_add_line (tmp_bezier,
tmp_bezier->points->pnt.x,
tmp_bezier->points->pnt.y,-1);
/* Final has no frame */
bezier_line_frame = 0; /* False */
d_draw_bezier (tmp_bezier);
bezier_line_frame = tmp_frame; /* What is was */
}
else if (bezier_line_frame)
{
d_draw_bezier (tmp_bezier);
bezier_line_frame = 0; /* False */
d_draw_bezier (tmp_bezier);
bezier_line_frame = 1; /* What is was */
}
add_to_all_obj (current_obj, obj_creating);
}
/* small mem leak if !l_pnt ? */
tmp_bezier = NULL;
obj_creating = NULL;
}
else
{
if (!tmp_bezier->points->next)
{
draw_circle (&tmp_bezier->points->pnt);
draw_sqr (&tmp_bezier->points->pnt);
}
d_draw_bezier (tmp_bezier);
d_pnt_add_line (tmp_bezier, pnt->x, pnt->y,-1);
d_draw_bezier (tmp_bezier);
}
}
void
bezier_dialog (void)
{
static GtkWidget *window = NULL;
GtkWidget *vbox;
GtkWidget *toggle;
if (window)
{
gtk_window_present (GTK_WINDOW (window));
return;
}
window = gimp_dialog_new (_("Bezier Settings"), "gfig",
gimp_standard_help_func, "filters/gfig.html",
GTK_WIN_POS_MOUSE,
FALSE, FALSE, FALSE,
GTK_STOCK_CLOSE, gtk_widget_destroy,
NULL, 1, NULL, TRUE, TRUE,
NULL);
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed),
&window);
vbox = gtk_vbox_new (FALSE, 2);
gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox,
FALSE, FALSE, 0);
gtk_widget_show (vbox);
toggle = gtk_check_button_new_with_label (_("Closed"));
g_signal_connect (toggle, "toggled",
G_CALLBACK (gimp_toggle_button_update),
&bezier_closed);
gimp_help_set_help_data (toggle,
_("Close curve on completion"), NULL);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), bezier_closed);
gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
gtk_widget_show (toggle);
toggle = gtk_check_button_new_with_label (_("Show Line Frame"));
g_signal_connect (toggle, "toggled",
G_CALLBACK (gimp_toggle_button_update),
&bezier_line_frame);
gimp_help_set_help_data (toggle,
_("Draws lines between the control points. "
"Only during curve creation"), NULL);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), bezier_line_frame);
gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
gtk_widget_show (toggle);
gtk_widget_show (window);
}

View File

@ -0,0 +1,40 @@
/*
* 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.
*
*/
#ifndef __GFIG_BEZIER_H__
#define __GFIG_BEZIER_H__
extern Dobject *tmp_bezier;
Dobject * d_load_bezier (FILE *from);
void d_draw_bezier (Dobject *obj);
void d_update_bezier (GdkPoint *pnt);
void d_bezier_start (GdkPoint *pnt, gint shift_down);
void d_bezier_end (GdkPoint *pnt, gint shift_down);
void bezier_dialog (void);
#endif /* __GFIG_BEZIER_H__ */

358
plug-ins/gfig/gfig_circle.c Normal file
View File

@ -0,0 +1,358 @@
/*
* 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.
*
*/
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <gtk/gtk.h>
#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>
#include "config.h"
#include "libgimp/stdplugins-intl.h"
#include "gfig.h"
#include "gfig_poly.h"
static Dobject * d_new_circle (gint x, gint y);
static void
d_save_circle (Dobject *obj,
FILE *to)
{
DobjPoints *spnt;
spnt = obj->points;
if (!spnt)
return;
fprintf (to, "<CIRCLE>\n");
while (spnt)
{
fprintf (to, "%d %d\n",
spnt->pnt.x,
spnt->pnt.y);
spnt = spnt->next;
}
fprintf (to, "</CIRCLE>\n");
}
Dobject *
d_load_circle (FILE *from)
{
Dobject *new_obj = NULL;
gint xpnt;
gint ypnt;
gchar buf[MAX_LOAD_LINE];
while (get_line (buf, MAX_LOAD_LINE, from, 0))
{
if (sscanf (buf, "%d %d", &xpnt, &ypnt) != 2)
{
/* Must be the end */
if (strcmp ("</CIRCLE>", buf))
{
g_warning ("[%d] Internal load error while loading circle",
line_no);
return NULL;
}
return new_obj;
}
if (!new_obj)
new_obj = d_new_circle (xpnt, ypnt);
else
{
DobjPoints *edge_pnt;
/* Circles only have two points */
edge_pnt = g_new0 (DobjPoints, 1);
edge_pnt->pnt.x = xpnt;
edge_pnt->pnt.y = ypnt;
new_obj->points->next = edge_pnt;
}
}
g_warning ("[%d] Not enough points for circle", line_no);
return NULL;
}
static void
d_draw_circle (Dobject * obj)
{
DobjPoints *center_pnt;
DobjPoints *edge_pnt;
gdouble radius;
center_pnt = obj->points;
if (!center_pnt)
return; /* End-of-line */
edge_pnt = center_pnt->next;
if (!edge_pnt)
{
g_warning ("Internal error - circle no edge pnt");
}
radius = sqrt (((center_pnt->pnt.x - edge_pnt->pnt.x) *
(center_pnt->pnt.x - edge_pnt->pnt.x)) +
((center_pnt->pnt.y - edge_pnt->pnt.y) *
(center_pnt->pnt.y - edge_pnt->pnt.y)));
draw_sqr (&center_pnt->pnt);
draw_sqr (&edge_pnt->pnt);
if (drawing_pic)
{
gdk_draw_arc (pic_preview->window,
pic_preview->style->black_gc,
0,
adjust_pic_coords (center_pnt->pnt.x - radius,
preview_width),
adjust_pic_coords (center_pnt->pnt.y - radius,
preview_height),
adjust_pic_coords (radius * 2,
preview_width),
adjust_pic_coords (radius * 2,
preview_height),
0,
360 * 64);
}
else
{
gdk_draw_arc (gfig_preview->window,
gfig_gc,
0,
gfig_scale_x (center_pnt->pnt.x - (gint) RINT (radius)),
gfig_scale_y (center_pnt->pnt.y - (gint) RINT (radius)),
gfig_scale_x ((gint) RINT (radius) * 2),
gfig_scale_y ((gint) RINT (radius) * 2),
0,
360 * 64);
}
}
static void
d_paint_circle (Dobject *obj)
{
DobjPoints * center_pnt;
DobjPoints * edge_pnt;
gint radius;
gdouble dpnts[4];
g_assert (obj != NULL);
if (selvals.approxcircles)
{
obj->type_data = 600;
d_paint_poly (obj);
return;
}
/* Drawing circles is hard .
* 1) select circle
* 2) stroke it
*/
center_pnt = obj->points;
if (!center_pnt)
return; /* End-of-line */
edge_pnt = center_pnt->next;
if (!edge_pnt)
{
g_error ("Internal error - circle no edge pnt");
}
radius = (gint) sqrt (((center_pnt->pnt.x - edge_pnt->pnt.x) *
(center_pnt->pnt.x - edge_pnt->pnt.x)) +
((center_pnt->pnt.y - edge_pnt->pnt.y) *
(center_pnt->pnt.y - edge_pnt->pnt.y)));
dpnts[0] = (gdouble) center_pnt->pnt.x - radius;
dpnts[1] = (gdouble) center_pnt->pnt.y - radius;
dpnts[3] = dpnts[2] = (gdouble) radius * 2;
/* Scale before drawing */
if (selvals.scaletoimage)
scale_to_original_xy (&dpnts[0], 2);
else
scale_to_xy (&dpnts[0], 2);
gimp_ellipse_select (gfig_image,
dpnts[0], dpnts[1],
dpnts[2], dpnts[3],
selopt.type,
selopt.antia,
selopt.feather,
selopt.feather_radius);
/* Is selection all we need ? */
if (selvals.painttype == PAINT_SELECTION_TYPE)
return;
gimp_edit_stroke (gfig_drawable);
gimp_selection_clear (gfig_image);
}
static Dobject *
d_copy_circle (Dobject * obj)
{
Dobject *nc;
if (!obj)
return NULL;
g_assert (obj->type == CIRCLE);
nc = d_new_circle (obj->points->pnt.x, obj->points->pnt.y);
nc->points->next = d_copy_dobjpoints (obj->points->next);
return nc;
}
static Dobject *
d_new_circle (gint x,
gint y)
{
Dobject *nobj;
DobjPoints *npnt;
/* Get new object and starting point */
/* Start point */
npnt = g_new0 (DobjPoints, 1);
npnt->pnt.x = x;
npnt->pnt.y = y;
nobj = g_new0 (Dobject, 1);
nobj->type = CIRCLE;
nobj->points = npnt;
nobj->drawfunc = d_draw_circle;
nobj->loadfunc = d_load_circle;
nobj->savefunc = d_save_circle;
nobj->paintfunc = d_paint_circle;
nobj->copyfunc = d_copy_circle;
return nobj;
}
void
d_update_circle (GdkPoint *pnt)
{
DobjPoints *center_pnt, *edge_pnt;
gdouble radius;
/* Undraw last one then draw new one */
center_pnt = obj_creating->points;
if (!center_pnt)
return; /* No points */
if ((edge_pnt = center_pnt->next))
{
/* Undraw current */
draw_circle (&edge_pnt->pnt);
radius = sqrt (((center_pnt->pnt.x - edge_pnt->pnt.x) *
(center_pnt->pnt.x - edge_pnt->pnt.x)) +
((center_pnt->pnt.y - edge_pnt->pnt.y) *
(center_pnt->pnt.y - edge_pnt->pnt.y)));
gdk_draw_arc (gfig_preview->window,
gfig_gc,
0,
center_pnt->pnt.x - (gint) RINT (radius),
center_pnt->pnt.y - (gint) RINT (radius),
(gint) RINT (radius) * 2,
(gint) RINT (radius) * 2,
0,
360 * 64);
}
draw_circle (pnt);
edge_pnt = g_new0 (DobjPoints, 1);
edge_pnt->pnt.x = pnt->x;
edge_pnt->pnt.y = pnt->y;
radius = sqrt (((center_pnt->pnt.x - edge_pnt->pnt.x) *
(center_pnt->pnt.x - edge_pnt->pnt.x)) +
((center_pnt->pnt.y - edge_pnt->pnt.y) *
(center_pnt->pnt.y - edge_pnt->pnt.y)));
gdk_draw_arc (gfig_preview->window,
gfig_gc,
0,
center_pnt->pnt.x - (gint) RINT (radius),
center_pnt->pnt.y - (gint) RINT (radius),
(gint) RINT (radius) * 2,
(gint) RINT (radius) * 2,
0,
360 * 64);
center_pnt->next = edge_pnt;
}
void
d_circle_start (GdkPoint *pnt,
gint shift_down)
{
obj_creating = d_new_circle (pnt->x, pnt->y);
}
void
d_circle_end (GdkPoint *pnt,
gint shift_down)
{
/* Under contrl point */
if (!obj_creating->points->next)
{
/* No circle created */
free_one_obj (obj_creating);
}
else
{
draw_circle (pnt);
add_to_all_obj (current_obj, obj_creating);
}
obj_creating = NULL;
}

View File

@ -0,0 +1,37 @@
/*
* 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.
*
*/
#ifndef __GFIG_CIRCLE_H__
#define __GFIG_CIRCLE_H__
Dobject * d_load_circle (FILE *from);
void d_update_circle (GdkPoint *pnt);
void d_circle_start (GdkPoint *pnt,
gint shift_down);
void d_circle_end (GdkPoint *pnt,
gint shift_down);
#endif /* __GFIG_CIRCLE_H__ */

View File

@ -0,0 +1,91 @@
/*
* 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.
*/
#ifndef __GFIG_DOBJECT_H__
#define __GFIG_DOBJECT_H__
struct Dobject; /* fwd declaration for DobjFunc */
typedef void (*DobjFunc) (struct Dobject *);
typedef struct Dobject *(*DobjGenFunc) (struct Dobject *);
typedef struct Dobject *(*DobjLoadFunc) (FILE *);
typedef void (*DobjSaveFunc) (struct Dobject *, FILE *);
typedef enum
{
LINE,
CIRCLE,
ELLIPSE,
ARC,
POLY,
STAR,
SPIRAL,
BEZIER,
MOVE_OBJ,
MOVE_POINT,
COPY_OBJ,
MOVE_COPY_OBJ,
DEL_OBJ,
NULL_OPER
} DobjType;
typedef struct DobjPoints
{
struct DobjPoints *next;
GdkPoint pnt;
gint found_me;
} DobjPoints;
/* The object itself */
typedef struct Dobject
{
DobjType type; /* What is the type? */
gint type_data; /* Extra data needed by the object */
DobjPoints *points; /* List of points */
DobjFunc drawfunc; /* How do I draw myself */
DobjFunc paintfunc; /* Draw me on canvas */
DobjGenFunc copyfunc; /* copy */
DobjLoadFunc loadfunc; /* Load this type of object */
DobjSaveFunc savefunc; /* Save me out */
} Dobject;
/* States of the object */
#define GFIG_OK 0x0
#define GFIG_MODIFIED 0x1
#define GFIG_READONLY 0x2
extern Dobject *obj_creating;
void d_pnt_add_line (Dobject *obj,
gint x,
gint y,
gint pos);
DobjPoints *d_copy_dobjpoints (DobjPoints * pnts);
void free_one_obj (Dobject *obj);
void d_delete_dobjpoints (DobjPoints * pnts);
#endif /* __GFIG_DOBJECT_H__ */

View File

@ -0,0 +1,519 @@
/*
* 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.
*
*/
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gtk/gtk.h>
#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>
#include "config.h"
#include "libgimp/stdplugins-intl.h"
#include "gfig.h"
#include "gfig_poly.h"
static Dobject * d_new_ellipse (gint x, gint y);
static void
d_save_ellipse (Dobject *obj,
FILE *to)
{
DobjPoints *spnt;
spnt = obj->points;
if (!spnt)
return;
fprintf (to, "<ELLIPSE>\n");
for (; spnt; spnt = spnt->next)
fprintf (to, "%d %d\n", spnt->pnt.x, spnt->pnt.y);
fprintf (to, "</ELLIPSE>\n");
}
Dobject *
d_load_ellipse (FILE *from)
{
Dobject *new_obj = NULL;
gint xpnt;
gint ypnt;
gchar buf[MAX_LOAD_LINE];
#ifdef DEBUG
printf ("Load ellipse called\n");
#endif /* DEBUG */
while (get_line (buf, MAX_LOAD_LINE, from, 0))
{
if (sscanf (buf, "%d %d", &xpnt, &ypnt) != 2)
{
/* Must be the end */
if (strcmp ("</ELLIPSE>", buf))
{
g_message ("[%d] Internal load error while loading ellipse",
line_no);
return NULL;
}
return new_obj;
}
if (!new_obj)
new_obj = d_new_ellipse (xpnt, ypnt);
else
{
DobjPoints *edge_pnt;
/* Circles only have two points */
edge_pnt = g_new0 (DobjPoints, 1);
edge_pnt->pnt.x = xpnt;
edge_pnt->pnt.y = ypnt;
new_obj->points->next = edge_pnt;
}
}
g_message ("[%d] Not enough points for ellipse", line_no);
return NULL;
}
static void
d_draw_ellipse (Dobject * obj)
{
DobjPoints *center_pnt;
DobjPoints *edge_pnt;
gint bound_wx;
gint bound_wy;
gint top_x;
gint top_y;
center_pnt = obj->points;
if (!center_pnt)
return; /* End-of-line */
edge_pnt = center_pnt->next;
if (!edge_pnt)
{
g_warning ("Internal error - ellipse no edge pnt");
}
draw_sqr (&center_pnt->pnt);
draw_sqr (&edge_pnt->pnt);
bound_wx = abs (center_pnt->pnt.x - edge_pnt->pnt.x) * 2;
bound_wy = abs (center_pnt->pnt.y - edge_pnt->pnt.y) * 2;
if (edge_pnt->pnt.x > center_pnt->pnt.x)
top_x = 2 * center_pnt->pnt.x - edge_pnt->pnt.x;
else
top_x = edge_pnt->pnt.x;
if (edge_pnt->pnt.y > center_pnt->pnt.y)
top_y = 2 * center_pnt->pnt.y - edge_pnt->pnt.y;
else
top_y = edge_pnt->pnt.y;
if (drawing_pic)
{
gdk_draw_arc (pic_preview->window,
pic_preview->style->black_gc,
0,
adjust_pic_coords (top_x,
preview_width),
adjust_pic_coords (top_y,
preview_height),
adjust_pic_coords (bound_wx,
preview_width),
adjust_pic_coords (bound_wy,
preview_height),
0,
360 * 64);
}
else
{
gdk_draw_arc (gfig_preview->window,
gfig_gc,
0,
gfig_scale_x (top_x),
gfig_scale_y (top_y),
gfig_scale_x (bound_wx),
gfig_scale_y (bound_wy),
0,
360 * 64);
}
}
static void
d_paint_approx_ellipse (Dobject *obj)
{
/* first point center */
/* Next point is radius */
gdouble *line_pnts;
gint seg_count = 0;
gint i = 0;
DobjPoints * center_pnt;
DobjPoints * radius_pnt;
gdouble a_axis;
gdouble b_axis;
gdouble ang_grid;
gdouble ang_loop;
gdouble radius;
gint loop;
GdkPoint first_pnt, last_pnt;
gint first = 1;
g_assert (obj != NULL);
/* count - add one to close polygon */
seg_count = 600;
center_pnt = obj->points;
if (!center_pnt || !seg_count)
return; /* no-line */
line_pnts = g_new0 (gdouble, 2 * seg_count + 1);
/* Go around all the points drawing a line from one to the next */
radius_pnt = center_pnt->next; /* this defines the vetices */
/* Have center and radius - get lines */
a_axis = ((gdouble) (radius_pnt->pnt.x - center_pnt->pnt.x));
b_axis = ((gdouble) (radius_pnt->pnt.y - center_pnt->pnt.y));
/* Lines */
ang_grid = 2 * G_PI / (gdouble) 600;
for (loop = 0; loop < 600; loop++)
{
gdouble lx, ly;
GdkPoint calc_pnt;
ang_loop = (gdouble)loop * ang_grid;
radius = (a_axis * b_axis /
(sqrt (cos (ang_loop) * cos (ang_loop) *
(b_axis * b_axis - a_axis * a_axis) + a_axis * a_axis)));
lx = radius * cos (ang_loop);
ly = radius * sin (ang_loop);
calc_pnt.x = RINT (lx + center_pnt->pnt.x);
calc_pnt.y = RINT (ly + center_pnt->pnt.y);
/* Miss out duped pnts */
if (!first)
{
if (calc_pnt.x == last_pnt.x && calc_pnt.y == last_pnt.y)
{
continue;
}
}
last_pnt.x = line_pnts[i++] = calc_pnt.x;
last_pnt.y = line_pnts[i++] = calc_pnt.y;
if (first)
{
first_pnt = calc_pnt;
first = 0;
}
}
line_pnts[i++] = first_pnt.x;
line_pnts[i++] = first_pnt.y;
/* Reverse line if approp */
if (selvals.reverselines)
reverse_pairs_list (&line_pnts[0], i / 2);
/* Scale before drawing */
if (selvals.scaletoimage)
scale_to_original_xy (&line_pnts[0], i / 2);
else
scale_to_xy (&line_pnts[0], i / 2);
/* One go */
if (selvals.painttype == PAINT_BRUSH_TYPE)
{
gfig_paint (selvals.brshtype,
gfig_drawable,
i, line_pnts);
}
else
{
gimp_free_select (gfig_image,
i, line_pnts,
selopt.type,
selopt.antia,
selopt.feather,
selopt.feather_radius);
}
g_free (line_pnts);
}
static void
d_paint_ellipse (Dobject *obj)
{
DobjPoints * center_pnt;
DobjPoints * edge_pnt;
gint bound_wx;
gint bound_wy;
gint top_x;
gint top_y;
gdouble dpnts[4];
/* Drawing ellipse is hard .
* 1) select circle
* 2) stroke it
*/
g_assert (obj != NULL);
if (selvals.approxcircles)
{
#ifdef DEBUG
printf ("Painting ellipse as polygon\n");
#endif /* DEBUG */
d_paint_approx_ellipse (obj);
return;
}
center_pnt = obj->points;
if (!center_pnt)
return; /* End-of-line */
edge_pnt = center_pnt->next;
if (!edge_pnt)
{
g_error ("Internal error - ellipse no edge pnt");
}
bound_wx = abs (center_pnt->pnt.x - edge_pnt->pnt.x)*2;
bound_wy = abs (center_pnt->pnt.y - edge_pnt->pnt.y)*2;
if (edge_pnt->pnt.x > center_pnt->pnt.x)
top_x = 2*center_pnt->pnt.x - edge_pnt->pnt.x;
else
top_x = edge_pnt->pnt.x;
if (edge_pnt->pnt.y > center_pnt->pnt.y)
top_y = 2*center_pnt->pnt.y - edge_pnt->pnt.y;
else
top_y = edge_pnt->pnt.y;
dpnts[0] = (gdouble)top_x;
dpnts[1] = (gdouble)top_y;
dpnts[2] = (gdouble)bound_wx;
dpnts[3] = (gdouble)bound_wy;
/* Scale before drawing */
if (selvals.scaletoimage)
scale_to_original_xy (&dpnts[0], 2);
else
scale_to_xy (&dpnts[0], 2);
gimp_ellipse_select (gfig_image,
dpnts[0], dpnts[1],
dpnts[2], dpnts[3],
selopt.type,
selopt.antia,
selopt.feather,
selopt.feather_radius);
/* Is selection all we need ? */
if (selvals.painttype == PAINT_SELECTION_TYPE)
return;
gimp_edit_stroke (gfig_drawable);
gimp_selection_clear (gfig_image);
}
static Dobject *
d_copy_ellipse (Dobject * obj)
{
Dobject *nc;
if (!obj)
return (NULL);
g_assert (obj->type == ELLIPSE);
nc = d_new_ellipse (obj->points->pnt.x, obj->points->pnt.y);
nc->points->next = d_copy_dobjpoints (obj->points->next);
return nc;
}
static Dobject *
d_new_ellipse (gint x, gint y)
{
Dobject *nobj;
DobjPoints *npnt;
/* Get new object and starting point */
/* Start point */
npnt = g_new0 (DobjPoints, 1);
#if DEBUG
printf ("New ellipse start at (%x,%x)\n", x, y);
#endif /* DEBUG */
npnt->pnt.x = x;
npnt->pnt.y = y;
nobj = g_new0 (Dobject, 1);
nobj->type = ELLIPSE;
nobj->points = npnt;
nobj->drawfunc = d_draw_ellipse;
nobj->loadfunc = d_load_ellipse;
nobj->savefunc = d_save_ellipse;
nobj->paintfunc = d_paint_ellipse;
nobj->copyfunc = d_copy_ellipse;
return (nobj);
}
void
d_update_ellipse (GdkPoint *pnt)
{
DobjPoints *center_pnt, *edge_pnt;
gint bound_wx;
gint bound_wy;
gint top_x;
gint top_y;
/* Undraw last one then draw new one */
center_pnt = obj_creating->points;
if (!center_pnt)
return; /* No points */
if ((edge_pnt = center_pnt->next))
{
/* Undraw current */
bound_wx = abs (center_pnt->pnt.x - edge_pnt->pnt.x)*2;
bound_wy = abs (center_pnt->pnt.y - edge_pnt->pnt.y)*2;
if (edge_pnt->pnt.x > center_pnt->pnt.x)
top_x = 2*center_pnt->pnt.x - edge_pnt->pnt.x;
else
top_x = edge_pnt->pnt.x;
if (edge_pnt->pnt.y > center_pnt->pnt.y)
top_y = 2*center_pnt->pnt.y - edge_pnt->pnt.y;
else
top_y = edge_pnt->pnt.y;
draw_circle (&edge_pnt->pnt);
gdk_draw_arc (gfig_preview->window,
gfig_gc,
0,
top_x,
top_y,
bound_wx,
bound_wy,
0,
360*64);
}
draw_circle (pnt);
edge_pnt = g_new0 (DobjPoints, 1);
edge_pnt->pnt.x = pnt->x;
edge_pnt->pnt.y = pnt->y;
bound_wx = abs (center_pnt->pnt.x - edge_pnt->pnt.x)*2;
bound_wy = abs (center_pnt->pnt.y - edge_pnt->pnt.y)*2;
if (edge_pnt->pnt.x > center_pnt->pnt.x)
top_x = 2*center_pnt->pnt.x - edge_pnt->pnt.x;
else
top_x = edge_pnt->pnt.x;
if (edge_pnt->pnt.y > center_pnt->pnt.y)
top_y = 2* center_pnt->pnt.y - edge_pnt->pnt.y;
else
top_y = edge_pnt->pnt.y;
gdk_draw_arc (gfig_preview->window,
gfig_gc,
0,
top_x,
top_y,
bound_wx,
bound_wy,
0,
360*64);
center_pnt->next = edge_pnt;
}
void
d_ellipse_start (GdkPoint *pnt, gint shift_down)
{
obj_creating = d_new_ellipse (pnt->x, pnt->y);
}
void
d_ellipse_end (GdkPoint *pnt, gint shift_down)
{
/* Under contrl point */
if (!obj_creating->points->next)
{
/* No circle created */
free_one_obj (obj_creating);
}
else
{
draw_circle (pnt);
add_to_all_obj (current_obj, obj_creating);
}
obj_creating = NULL;
}

View File

@ -0,0 +1,35 @@
/*
* 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.
*
*/
#ifndef __GFIG_ELLIPSE_H__
#define __GFIG_ELLIPSE_H__
Dobject *d_load_ellipse (FILE *from);
void d_update_ellipse (GdkPoint *pnt);
void d_ellipse_start (GdkPoint *pnt, gint shift_down);
void d_ellipse_end (GdkPoint *pnt, gint shift_down);
#endif /* __GFIG_CIRCLE_H__ */

421
plug-ins/gfig/gfig_line.c Normal file
View File

@ -0,0 +1,421 @@
/*
* 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.
*
*/
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <gtk/gtk.h>
#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>
#include "config.h"
#include "libgimp/stdplugins-intl.h"
#include "gfig.h"
static Dobject * d_new_line (gint x, gint y);
void
d_save_line (Dobject *obj,
FILE *to)
{
DobjPoints * spnt;
spnt = obj->points;
if (!spnt)
return; /* End-of-line */
fprintf (to, "<LINE>\n");
while (spnt)
{
fprintf (to, "%d %d\n",
spnt->pnt.x,
spnt->pnt.y);
spnt = spnt->next;
}
fprintf (to, "</LINE>\n");
}
Dobject *
d_load_line (FILE *from)
{
Dobject *new_obj = NULL;
gint xpnt;
gint ypnt;
gchar buf[MAX_LOAD_LINE];
while (get_line (buf, MAX_LOAD_LINE, from, 0))
{
if (sscanf (buf, "%d %d", &xpnt, &ypnt) != 2)
{
/* Must be the end */
if (strcmp ("</LINE>", buf))
{
g_warning ("[%d] Internal load error while loading line",
line_no);
return NULL;
}
return new_obj;
}
if (!new_obj)
new_obj = d_new_line (xpnt, ypnt);
else
d_pnt_add_line (new_obj, xpnt, ypnt, -1);
}
return new_obj;
}
Dobject *
d_copy_line (Dobject *obj)
{
Dobject *nl;
if (!obj)
return NULL;
g_assert (obj->type == LINE);
nl = d_new_line (obj->points->pnt.x, obj->points->pnt.y);
nl->points->next = d_copy_dobjpoints (obj->points->next);
return nl;
}
void
d_draw_line (Dobject *obj)
{
DobjPoints *spnt;
DobjPoints *epnt;
spnt = obj->points;
if (!spnt)
return; /* End-of-line */
epnt = spnt->next;
while (spnt && epnt)
{
draw_sqr (&spnt->pnt);
/* Go around all the points drawing a line from one to the next */
if (drawing_pic)
{
gdk_draw_line (pic_preview->window,
pic_preview->style->black_gc,
adjust_pic_coords (spnt->pnt.x, preview_width),
adjust_pic_coords (spnt->pnt.y, preview_height),
adjust_pic_coords (epnt->pnt.x, preview_width),
adjust_pic_coords (epnt->pnt.y, preview_height));
}
else
{
gdk_draw_line (gfig_preview->window,
gfig_gc,
gfig_scale_x (spnt->pnt.x),
gfig_scale_y (spnt->pnt.y),
gfig_scale_x (epnt->pnt.x),
gfig_scale_y (epnt->pnt.y));
}
spnt = epnt;
epnt = epnt->next;
}
draw_sqr (&spnt->pnt);
}
void
d_paint_line (Dobject *obj)
{
DobjPoints * spnt;
gdouble *line_pnts;
gint seg_count = 0;
gint i = 0;
for (spnt = obj->points; spnt; spnt = spnt->next)
seg_count++;
if (!seg_count)
return; /* no-line */
line_pnts = g_new0 (gdouble, 2 * seg_count + 1);
/* Go around all the points drawing a line from one to the next */
for (spnt = obj->points; spnt; spnt = spnt->next)
{
line_pnts[i++] = spnt->pnt.x;
line_pnts[i++] = spnt->pnt.y;
}
/* Reverse line if approp */
if (selvals.reverselines)
reverse_pairs_list (&line_pnts[0], i/2);
/* Scale before drawing */
if (selvals.scaletoimage)
scale_to_original_xy (&line_pnts[0], i/2);
else
scale_to_xy (&line_pnts[0], i/2);
/* One go */
if (selvals.painttype == PAINT_BRUSH_TYPE)
{
gfig_paint (selvals.brshtype,
gfig_drawable,
seg_count * 2, line_pnts);
}
else
{
gimp_free_select (gfig_image,
seg_count * 2, line_pnts,
selopt.type,
selopt.antia,
selopt.feather,
selopt.feather_radius);
}
g_free (line_pnts);
}
/* Create a new line object. starting at the x, y point might add styles
* later.
*/
static Dobject *
d_new_line (gint x,
gint y)
{
Dobject *nobj;
DobjPoints *npnt;
/* Get new object and starting point */
/* Start point */
npnt = g_new0 (DobjPoints, 1);
npnt->pnt.x = x;
npnt->pnt.y = y;
nobj = g_new0 (Dobject, 1);
nobj->type = LINE;
nobj->points = npnt;
nobj->drawfunc = d_draw_line;
nobj->loadfunc = d_load_line;
nobj->savefunc = d_save_line;
nobj->paintfunc = d_paint_line;
nobj->copyfunc = d_copy_line;
return nobj;
}
/* You guessed it delete the object !*/
/*
static void
d_delete_line (Dobject *obj)
{
g_assert (obj != NULL);
* First free the list of points - then the object itself *
d_delete_dobjpoints (obj->points);
g_free (obj);
}
*/
/* Add a point to a line (given x, y)
* pos = 0 = head
* pos = -1 = tail
* 0 < pos = nth position
*/
void
d_pnt_add_line (Dobject *obj,
gint x,
gint y,
gint pos)
{
DobjPoints *npnts = g_new0 (DobjPoints, 1);
g_assert (obj != NULL);
npnts->pnt.x = x;
npnts->pnt.y = y;
if (!pos)
{
/* Add to head */
npnts->next = obj->points;
obj->points = npnts;
}
else
{
DobjPoints *pnt = obj->points;
/* Go down chain until the end if pos */
while (pos < 0 || pos-- > 0)
{
if (!(pnt->next) || !pos)
{
npnts->next = pnt->next;
pnt->next = npnts;
break;
}
else
{
pnt = pnt->next;
}
}
}
}
/* Update end point of line */
void
d_update_line (GdkPoint *pnt)
{
DobjPoints *spnt, *epnt;
/* Get last but one segment and undraw it -
* Then draw new segment in.
* always dealing with the static object.
*/
/* Get start of segments */
spnt = obj_creating->points;
if (!spnt)
return; /* No points */
if ((epnt = spnt->next))
{
/* undraw current */
/* Draw square on point */
draw_circle (&epnt->pnt);
gdk_draw_line (gfig_preview->window,
/*gfig_preview->style->bg_gc[GTK_STATE_NORMAL],*/
gfig_gc,
spnt->pnt.x,
spnt->pnt.y,
epnt->pnt.x,
epnt->pnt.y);
g_free (epnt);
}
/* draw new */
/* Draw circle on point */
draw_circle (pnt);
epnt = g_new0 (DobjPoints, 1);
epnt->pnt.x = pnt->x;
epnt->pnt.y = pnt->y;
gdk_draw_line (gfig_preview->window,
/*gfig_preview->style->bg_gc[GTK_STATE_NORMAL],*/
gfig_gc,
spnt->pnt.x,
spnt->pnt.y,
epnt->pnt.x,
epnt->pnt.y);
spnt->next = epnt;
}
void
d_line_start (GdkPoint *pnt,
gint shift_down)
{
if (!obj_creating || !shift_down)
{
/* Draw square on point */
/* Must delete obj_creating if we have one */
obj_creating = d_new_line (pnt->x, pnt->y);
}
else
{
/* Contniuation */
d_update_line (pnt);
}
}
void
d_line_end (GdkPoint *pnt,
gint shift_down)
{
/* Undraw the last circle */
draw_circle (pnt);
if (shift_down)
{
if (tmp_line)
{
GdkPoint tmp_pnt = *pnt;
if (need_to_scale)
{
tmp_pnt.x = (pnt->x * scale_x_factor);
tmp_pnt.y = (pnt->y * scale_y_factor);
}
d_pnt_add_line (tmp_line, tmp_pnt.x, tmp_pnt.y, -1);
free_one_obj (obj_creating);
/* Must free obj_creating */
}
else
{
tmp_line = obj_creating;
add_to_all_obj (current_obj, obj_creating);
}
obj_creating = d_new_line (pnt->x, pnt->y);
}
else
{
if (tmp_line)
{
GdkPoint tmp_pnt = *pnt;
if (need_to_scale)
{
tmp_pnt.x = (pnt->x * scale_x_factor);
tmp_pnt.y = (pnt->y * scale_y_factor);
}
d_pnt_add_line (tmp_line, tmp_pnt.x, tmp_pnt.y, -1);
free_one_obj (obj_creating);
/* Must free obj_creating */
}
else
{
add_to_all_obj (current_obj, obj_creating);
}
obj_creating = NULL;
tmp_line = NULL;
}
/*gtk_widget_queue_draw (gfig_preview);*/
}

43
plug-ins/gfig/gfig_line.h Normal file
View File

@ -0,0 +1,43 @@
/*
* 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.
*
*/
#ifndef __GFIG_LINE_H__
#define __GFIG_LINE_H__
Dobject * d_load_line (FILE *from);
void d_save_line (Dobject *obj,
FILE *to);
void d_draw_line (Dobject *obj);
void d_paint_line (Dobject *obj);
Dobject *d_copy_line (Dobject *obj);
void d_update_line (GdkPoint *pnt);
void d_line_start (GdkPoint *pnt,
gint shift_down);
void d_line_end (GdkPoint *pnt,
gint shift_down);
#endif /* __GFIG_LINE_H__ */

722
plug-ins/gfig/gfig_poly.c Normal file
View File

@ -0,0 +1,722 @@
/*
* 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.
*
*/
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <gtk/gtk.h>
#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>
#include "config.h"
#include "libgimp/stdplugins-intl.h"
#include "gfig.h"
#include "gfig_line.h"
static gint poly_num_sides = 3; /* Default to three sided object */
static void d_save_poly (Dobject * obj, FILE *to);
static void d_draw_poly (Dobject *obj);
static Dobject * d_copy_poly (Dobject * obj);
static Dobject * d_new_poly (gint x, gint y);
gboolean
poly_button_press (GtkWidget *widget,
GdkEventButton *event,
gpointer data)
{
if ((event->type == GDK_2BUTTON_PRESS) &&
(event->button == 1))
num_sides_dialog (_("Regular Polygon Number of Sides"),
&poly_num_sides, NULL, 3, 200);
return FALSE;
}
static void
d_save_poly (Dobject * obj, FILE *to)
{
DobjPoints * spnt;
spnt = obj->points;
if (!spnt)
return; /* End-of-line */
fprintf (to, "<POLY>\n");
while (spnt)
{
fprintf (to, "%d %d\n",
spnt->pnt.x,
spnt->pnt.y);
spnt = spnt->next;
}
fprintf (to, "<EXTRA>\n");
fprintf (to, "%d\n</EXTRA>\n", obj->type_data);
fprintf (to, "</POLY>\n");
}
Dobject *
d_load_poly (FILE *from)
{
Dobject *new_obj = NULL;
gint xpnt;
gint ypnt;
gchar buf[MAX_LOAD_LINE];
while (get_line (buf, MAX_LOAD_LINE, from, 0))
{
if (sscanf (buf, "%d %d", &xpnt, &ypnt) != 2)
{
/* Must be the end */
if (!strcmp ("<EXTRA>", buf))
{
gint nsides = 3;
/* Number of sides - data item */
if (!new_obj)
{
g_warning ("[%d] Internal load error while loading poly (extra area)",
line_no);
return (NULL);
}
get_line (buf, MAX_LOAD_LINE, from, 0);
if (sscanf (buf, "%d", &nsides) != 1)
{
g_warning ("[%d] Internal load error while loading poly (extra area scanf)",
line_no);
return (NULL);
}
new_obj->type_data = nsides;
get_line (buf, MAX_LOAD_LINE, from, 0);
if (strcmp ("</EXTRA>", buf))
{
g_warning ("[%d] Internal load error while loading poly",
line_no);
return (NULL);
}
/* Go around and read the last line */
continue;
}
else if (strcmp ("</POLY>", buf))
{
g_warning ("[%d] Internal load error while loading poly",
line_no);
return (NULL);
}
return (new_obj);
}
if (!new_obj)
new_obj = d_new_poly (xpnt, ypnt);
else
d_pnt_add_line (new_obj, xpnt, ypnt, -1);
}
return (new_obj);
}
static void
d_draw_poly (Dobject *obj)
{
DobjPoints * center_pnt;
DobjPoints * radius_pnt;
gint16 shift_x;
gint16 shift_y;
gdouble ang_grid;
gdouble ang_loop;
gdouble radius;
gdouble offset_angle;
gint loop;
GdkPoint start_pnt;
GdkPoint first_pnt;
gint do_line = 0;
center_pnt = obj->points;
if (!center_pnt)
return; /* End-of-line */
/* First point is the center */
/* Just draw a control point around it */
draw_sqr (&center_pnt->pnt);
/* Next point defines the radius */
radius_pnt = center_pnt->next; /* this defines the vertices */
if (!radius_pnt)
{
#ifdef DEBUG
g_warning ("Internal error in polygon - no vertice point \n");
#endif /* DEBUG */
return;
}
/* Other control point */
draw_sqr (&radius_pnt->pnt);
/* Have center and radius - draw polygon */
shift_x = radius_pnt->pnt.x - center_pnt->pnt.x;
shift_y = radius_pnt->pnt.y - center_pnt->pnt.y;
radius = sqrt ((shift_x*shift_x) + (shift_y*shift_y));
/* Lines */
ang_grid = 2 * G_PI / (gdouble) obj->type_data;
offset_angle = atan2 (shift_y, shift_x);
for (loop = 0 ; loop < obj->type_data ; loop++)
{
gdouble lx, ly;
GdkPoint calc_pnt;
ang_loop = (gdouble)loop * ang_grid + offset_angle;
lx = radius * cos (ang_loop);
ly = radius * sin (ang_loop);
calc_pnt.x = RINT (lx + center_pnt->pnt.x);
calc_pnt.y = RINT (ly + center_pnt->pnt.y);
if (do_line)
{
/* Miss out points that come to the same location */
if (calc_pnt.x == start_pnt.x && calc_pnt.y == start_pnt.y)
continue;
if (drawing_pic)
{
gdk_draw_line (pic_preview->window,
pic_preview->style->black_gc,
adjust_pic_coords (calc_pnt.x,
preview_width),
adjust_pic_coords (calc_pnt.y,
preview_height),
adjust_pic_coords (start_pnt.x,
preview_width),
adjust_pic_coords (start_pnt.y,
preview_height));
}
else
{
gdk_draw_line (gfig_preview->window,
gfig_gc,
gfig_scale_x (calc_pnt.x),
gfig_scale_y (calc_pnt.y),
gfig_scale_x (start_pnt.x),
gfig_scale_y (start_pnt.y));
}
}
else
{
do_line = 1;
first_pnt.x = calc_pnt.x;
first_pnt.y = calc_pnt.y;
}
start_pnt.x = calc_pnt.x;
start_pnt.y = calc_pnt.y;
}
/* Join up */
if (drawing_pic)
{
gdk_draw_line (pic_preview->window,
pic_preview->style->black_gc,
adjust_pic_coords (first_pnt.x, preview_width),
adjust_pic_coords (first_pnt.y, preview_width),
adjust_pic_coords (start_pnt.x, preview_width),
adjust_pic_coords (start_pnt.y, preview_width));
}
else
{
gdk_draw_line (gfig_preview->window,
gfig_gc,
gfig_scale_x (first_pnt.x),
gfig_scale_y (first_pnt.y),
gfig_scale_x (start_pnt.x),
gfig_scale_y (start_pnt.y));
}
}
void
d_paint_poly (Dobject *obj)
{
/* first point center */
/* Next point is radius */
gdouble *line_pnts;
gint seg_count = 0;
gint i = 0;
DobjPoints * center_pnt;
DobjPoints * radius_pnt;
gint16 shift_x;
gint16 shift_y;
gdouble ang_grid;
gdouble ang_loop;
gdouble radius;
gdouble offset_angle;
gint loop;
GdkPoint first_pnt, last_pnt;
gint first = 1;
g_assert (obj != NULL);
/* count - add one to close polygon */
seg_count = obj->type_data + 1;
center_pnt = obj->points;
if (!center_pnt || !seg_count || !center_pnt->next)
return; /* no-line */
line_pnts = g_new0 (gdouble, 2 * seg_count + 1);
/* Go around all the points drawing a line from one to the next */
radius_pnt = center_pnt->next; /* this defines the vetices */
/* Have center and radius - get lines */
shift_x = radius_pnt->pnt.x - center_pnt->pnt.x;
shift_y = radius_pnt->pnt.y - center_pnt->pnt.y;
radius = sqrt ((shift_x*shift_x) + (shift_y*shift_y));
/* Lines */
ang_grid = 2*G_PI/(gdouble) obj->type_data;
offset_angle = atan2 (shift_y, shift_x);
for (loop = 0 ; loop < obj->type_data ; loop++)
{
gdouble lx, ly;
GdkPoint calc_pnt;
ang_loop = (gdouble)loop * ang_grid + offset_angle;
lx = radius * cos (ang_loop);
ly = radius * sin (ang_loop);
calc_pnt.x = RINT (lx + center_pnt->pnt.x);
calc_pnt.y = RINT (ly + center_pnt->pnt.y);
/* Miss out duped pnts */
if (!first)
{
if (calc_pnt.x == last_pnt.x && calc_pnt.y == last_pnt.y)
{
continue;
}
}
last_pnt.x = line_pnts[i++] = calc_pnt.x;
last_pnt.y = line_pnts[i++] = calc_pnt.y;
if (first)
{
first_pnt.x = calc_pnt.x;
first_pnt.y = calc_pnt.y;
first = 0;
}
}
line_pnts[i++] = first_pnt.x;
line_pnts[i++] = first_pnt.y;
/* Reverse line if approp */
if (selvals.reverselines)
reverse_pairs_list (&line_pnts[0], i/2);
/* Scale before drawing */
if (selvals.scaletoimage)
scale_to_original_xy (&line_pnts[0], i/2);
else
scale_to_xy (&line_pnts[0], i/2);
/* One go */
if (selvals.painttype == PAINT_BRUSH_TYPE)
{
gfig_paint (selvals.brshtype,
gfig_drawable,
i, line_pnts);
}
else
{
gimp_free_select (gfig_image,
i, line_pnts,
selopt.type,
selopt.antia,
selopt.feather,
selopt.feather_radius);
}
g_free (line_pnts);
}
void
d_poly2lines (Dobject *obj)
{
/* first point center */
/* Next point is radius */
gint seg_count = 0;
DobjPoints * center_pnt;
DobjPoints * radius_pnt;
gint16 shift_x;
gint16 shift_y;
gdouble ang_grid;
gdouble ang_loop;
gdouble radius;
gdouble offset_angle;
gint loop;
GdkPoint first_pnt, last_pnt;
gint first = 1;
g_assert (obj != NULL);
/* count - add one to close polygon */
seg_count = obj->type_data + 1;
center_pnt = obj->points;
if (!center_pnt)
return; /* no-line */
/* Undraw it to start with - removes control points */
obj->drawfunc (obj);
/* NULL out these points free later */
obj->points = NULL;
/* Go around all the points creating line points */
radius_pnt = center_pnt->next; /* this defines the vertices */
/* Have center and radius - get lines */
shift_x = radius_pnt->pnt.x - center_pnt->pnt.x;
shift_y = radius_pnt->pnt.y - center_pnt->pnt.y;
radius = sqrt ((shift_x*shift_x) + (shift_y*shift_y));
/* Lines */
ang_grid = 2*G_PI/(gdouble) obj->type_data;
offset_angle = atan2 (shift_y, shift_x);
for (loop = 0 ; loop < obj->type_data ; loop++)
{
gdouble lx, ly;
GdkPoint calc_pnt;
ang_loop = (gdouble)loop * ang_grid + offset_angle;
lx = radius * cos (ang_loop);
ly = radius * sin (ang_loop);
calc_pnt.x = RINT (lx + center_pnt->pnt.x);
calc_pnt.y = RINT (ly + center_pnt->pnt.y);
if (!first)
{
if (calc_pnt.x == last_pnt.x && calc_pnt.y == last_pnt.y)
{
continue;
}
}
d_pnt_add_line (obj, calc_pnt.x, calc_pnt.y, 0);
last_pnt.x = calc_pnt.x;
last_pnt.y = calc_pnt.y;
if (first)
{
first_pnt.x = calc_pnt.x;
first_pnt.y = calc_pnt.y;
first = 0;
}
}
d_pnt_add_line (obj, first_pnt.x, first_pnt.y, 0);
/* Free old pnts */
d_delete_dobjpoints (center_pnt);
/* hey we're a line now */
obj->type = LINE;
obj->drawfunc = d_draw_line;
obj->loadfunc = d_load_line;
obj->savefunc = d_save_line;
obj->paintfunc = d_paint_line;
obj->copyfunc = d_copy_line;
/* draw it + control pnts */
obj->drawfunc (obj);
}
void
d_star2lines (Dobject *obj)
{
/* first point center */
/* Next point is radius */
gint seg_count = 0;
DobjPoints * center_pnt;
DobjPoints * outer_radius_pnt;
DobjPoints * inner_radius_pnt;
gint16 shift_x;
gint16 shift_y;
gdouble ang_grid;
gdouble ang_loop;
gdouble outer_radius;
gdouble inner_radius;
gdouble offset_angle;
gint loop;
GdkPoint first_pnt, last_pnt;
gint first = 1;
g_assert (obj != NULL);
/* count - add one to close polygon */
seg_count = 2*obj->type_data + 1;
center_pnt = obj->points;
if (!center_pnt)
return; /* no-line */
/* Undraw it to start with - removes control points */
obj->drawfunc (obj);
/* NULL out these points free later */
obj->points = NULL;
/* Go around all the points creating line points */
/* Next point defines the radius */
outer_radius_pnt = center_pnt->next; /* this defines the vetices */
if (!outer_radius_pnt)
{
#ifdef DEBUG
g_warning ("Internal error in star - no outer vertice point \n");
#endif /* DEBUG */
return;
}
inner_radius_pnt = outer_radius_pnt->next; /* this defines the vetices */
if (!inner_radius_pnt)
{
#ifdef DEBUG
g_warning ("Internal error in star - no inner vertice point \n");
#endif /* DEBUG */
return;
}
shift_x = outer_radius_pnt->pnt.x - center_pnt->pnt.x;
shift_y = outer_radius_pnt->pnt.y - center_pnt->pnt.y;
outer_radius = sqrt ((shift_x*shift_x) + (shift_y*shift_y));
/* Lines */
ang_grid = 2*G_PI/(2.0*(gdouble) obj->type_data);
offset_angle = atan2 (shift_y, shift_x);
shift_x = inner_radius_pnt->pnt.x - center_pnt->pnt.x;
shift_y = inner_radius_pnt->pnt.y - center_pnt->pnt.y;
inner_radius = sqrt ((shift_x*shift_x) + (shift_y*shift_y));
for (loop = 0 ; loop < 2*obj->type_data ; loop++)
{
gdouble lx, ly;
GdkPoint calc_pnt;
ang_loop = (gdouble)loop * ang_grid + offset_angle;
if (loop%2)
{
lx = inner_radius * cos (ang_loop);
ly = inner_radius * sin (ang_loop);
}
else
{
lx = outer_radius * cos (ang_loop);
ly = outer_radius * sin (ang_loop);
}
calc_pnt.x = RINT (lx + center_pnt->pnt.x);
calc_pnt.y = RINT (ly + center_pnt->pnt.y);
if (!first)
{
if (calc_pnt.x == last_pnt.x && calc_pnt.y == last_pnt.y)
{
continue;
}
}
d_pnt_add_line (obj, calc_pnt.x, calc_pnt.y, 0);
last_pnt.x = calc_pnt.x;
last_pnt.y = calc_pnt.y;
if (first)
{
first_pnt.x = calc_pnt.x;
first_pnt.y = calc_pnt.y;
first = 0;
}
}
d_pnt_add_line (obj, first_pnt.x, first_pnt.y, 0);
/* Free old pnts */
d_delete_dobjpoints (center_pnt);
/* hey we're a line now */
obj->type = LINE;
obj->drawfunc = d_draw_line;
obj->loadfunc = d_load_line;
obj->savefunc = d_save_line;
obj->paintfunc = d_paint_line;
obj->copyfunc = d_copy_line;
/* draw it + control pnts */
obj->drawfunc (obj);
}
static Dobject *
d_copy_poly (Dobject * obj)
{
Dobject *np;
if (!obj)
return (NULL);
g_assert (obj->type == POLY);
np = d_new_poly (obj->points->pnt.x, obj->points->pnt.y);
np->points->next = d_copy_dobjpoints (obj->points->next);
np->type_data = obj->type_data;
return np;
}
static Dobject *
d_new_poly (gint x, gint y)
{
Dobject *nobj;
DobjPoints *npnt;
/* Get new object and starting point */
/* Start point */
npnt = g_new0 (DobjPoints, 1);
npnt->pnt.x = x;
npnt->pnt.y = y;
nobj = g_new0 (Dobject, 1);
nobj->type = POLY;
nobj->type_data = 3; /* Default to three sides */
nobj->points = npnt;
nobj->drawfunc = d_draw_poly;
nobj->loadfunc = d_load_poly;
nobj->savefunc = d_save_poly;
nobj->paintfunc = d_paint_poly;
nobj->copyfunc = d_copy_poly;
return nobj;
}
void
d_update_poly (GdkPoint *pnt)
{
DobjPoints *center_pnt, *edge_pnt;
gint saved_cnt_pnt = selvals.opts.showcontrol;
/* Undraw last one then draw new one */
center_pnt = obj_creating->points;
if (!center_pnt)
return; /* No points */
/* Leave the first pnt alone -
* Edge point defines "radius"
* Only undraw if already have edge point.
*/
/* Hack - turn off cnt points in draw routine
* Looking back over the other update routines I could
* use this trick again and cut down on code size!
*/
if ((edge_pnt = center_pnt->next))
{
/* Undraw */
draw_circle (&edge_pnt->pnt);
selvals.opts.showcontrol = 0;
d_draw_poly (obj_creating);
edge_pnt->pnt.x = pnt->x;
edge_pnt->pnt.y = pnt->y;
}
else
{
/* Radius is a few pixels away */
/* First edge point */
d_pnt_add_line (obj_creating, pnt->x, pnt->y, -1);
edge_pnt = center_pnt->next;
}
/* draw it */
selvals.opts.showcontrol = 0;
d_draw_poly (obj_creating);
selvals.opts.showcontrol = saved_cnt_pnt;
/* Realy draw the control points */
draw_circle (&edge_pnt->pnt);
}
void
d_poly_start (GdkPoint *pnt,
gint shift_down)
{
gint16 x, y;
/* First is center point */
obj_creating = d_new_poly (x = pnt->x, y = pnt->y);
obj_creating->type_data = poly_num_sides;
}
void
d_poly_end (GdkPoint *pnt,
gint shift_down)
{
draw_circle (pnt);
add_to_all_obj (current_obj, obj_creating);
obj_creating = NULL;
}

44
plug-ins/gfig/gfig_poly.h Normal file
View File

@ -0,0 +1,44 @@
/*
* 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.
*
*/
#ifndef __GFIG_POLY_H__
#define __GFIG_POLY_H__
gboolean poly_button_press (GtkWidget *widget,
GdkEventButton *event,
gpointer data);
Dobject *d_load_poly (FILE *from);
void d_update_poly (GdkPoint *pnt);
void d_poly_start (GdkPoint *pnt, gint shift_down);
void d_poly_end (GdkPoint *pnt, gint shift_down);
void d_paint_poly (Dobject *obj);
void d_poly2lines (Dobject *obj);
void d_star2lines (Dobject *obj);
#endif /* __GFIG_POLY_H__ */

507
plug-ins/gfig/gfig_spiral.c Normal file
View File

@ -0,0 +1,507 @@
/*
* 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.
*
*/
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gtk/gtk.h>
#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>
#include "config.h"
#include "libgimp/stdplugins-intl.h"
#include "gfig.h"
static void d_draw_spiral (Dobject *obj);
static void d_paint_spiral (Dobject *obj);
static Dobject * d_copy_spiral (Dobject * obj);
static Dobject * d_new_spiral (gint x, gint y);
static gint spiral_num_turns = 4; /* Default to 4 turns */
static gint spiral_toggle = 0; /* 0 = clockwise -1 = anti-clockwise */
gint
spiral_button_press (GtkWidget *widget,
GdkEventButton *event,
gpointer data)
{
if ((event->type == GDK_2BUTTON_PRESS) &&
(event->button == 1))
num_sides_dialog (_("Spiral Number of Points"),
&spiral_num_turns, &spiral_toggle, 1, 20);
return FALSE;
}
static void
d_save_spiral (Dobject *obj,
FILE *to)
{
DobjPoints * spnt;
spnt = obj->points;
if (!spnt)
return; /* End-of-line */
fprintf (to, "<SPIRAL>\n");
while (spnt)
{
fprintf (to, "%d %d\n",
spnt->pnt.x,
spnt->pnt.y);
spnt = spnt->next;
}
fprintf (to, "<EXTRA>\n");
fprintf (to, "%d\n</EXTRA>\n", obj->type_data);
fprintf (to, "</SPIRAL>\n");
}
/* Load a spiral from the specified stream */
Dobject *
d_load_spiral (FILE *from)
{
Dobject *new_obj = NULL;
gint xpnt;
gint ypnt;
gchar buf[MAX_LOAD_LINE];
#ifdef DEBUG
printf ("Load spiral called\n");
#endif /* DEBUG */
while (get_line (buf, MAX_LOAD_LINE, from, 0))
{
if (sscanf (buf, "%d %d", &xpnt, &ypnt) != 2)
{
/* Must be the end */
if (!strcmp ("<EXTRA>", buf))
{
gint nsides = 3;
/* Number of sides - data item */
if (!new_obj)
{
g_warning ("[%d] Internal load error while loading spiral (extra area)",
line_no);
return (NULL);
}
get_line (buf, MAX_LOAD_LINE, from, 0);
if (sscanf (buf, "%d", &nsides) != 1)
{
g_warning ("[%d] Internal load error while loading spiral (extra area scanf)",
line_no);
return (NULL);
}
new_obj->type_data = nsides;
get_line (buf, MAX_LOAD_LINE, from, 0);
if (strcmp ("</EXTRA>", buf))
{
g_warning ("[%d] Internal load error while loading spiral",
line_no);
return (NULL);
}
/* Go around and read the last line */
continue;
}
else if (strcmp ("</SPIRAL>", buf))
{
g_warning ("[%d] Internal load error while loading spiral",
line_no);
return (NULL);
}
return (new_obj);
}
if (!new_obj)
new_obj = d_new_spiral (xpnt, ypnt);
else
d_pnt_add_line (new_obj, xpnt, ypnt,-1);
}
return (new_obj);
}
static void
d_draw_spiral (Dobject *obj)
{
DobjPoints * center_pnt;
DobjPoints * radius_pnt;
gint16 shift_x;
gint16 shift_y;
gdouble ang_grid;
gdouble ang_loop;
gdouble radius;
gdouble offset_angle;
gdouble sp_cons;
gint loop;
GdkPoint start_pnt;
GdkPoint first_pnt;
gint do_line = 0;
gint clock_wise = 1;
center_pnt = obj->points;
if (!center_pnt)
return; /* End-of-line */
/* First point is the center */
/* Just draw a control point around it */
draw_sqr (&center_pnt->pnt);
/* Next point defines the radius */
radius_pnt = center_pnt->next; /* this defines the vetices */
if (!radius_pnt)
{
#ifdef DEBUG
g_warning ("Internal error in spiral - no vertice point \n");
#endif /* DEBUG */
return;
}
/* Other control point */
draw_sqr (&radius_pnt->pnt);
/* Have center and radius - draw spiral */
shift_x = radius_pnt->pnt.x - center_pnt->pnt.x;
shift_y = radius_pnt->pnt.y - center_pnt->pnt.y;
radius = sqrt ((shift_x*shift_x) + (shift_y*shift_y));
offset_angle = atan2 (shift_y, shift_x);
clock_wise = obj->type_data / abs (obj->type_data);
if (offset_angle < 0)
offset_angle += 2*G_PI;
sp_cons = radius/(obj->type_data * 2 * G_PI + offset_angle);
/* Lines */
ang_grid = 2.0*G_PI/(gdouble)180;
for (loop = 0 ; loop <= abs (obj->type_data * 180) + clock_wise*(gint)RINT (offset_angle/ang_grid) ; loop++)
{
gdouble lx, ly;
GdkPoint calc_pnt;
ang_loop = (gdouble)loop * ang_grid;
lx = sp_cons * ang_loop * cos (ang_loop)*clock_wise;
ly = sp_cons * ang_loop * sin (ang_loop);
calc_pnt.x = RINT (lx + center_pnt->pnt.x);
calc_pnt.y = RINT (ly + center_pnt->pnt.y);
if (do_line)
{
/* Miss out points that come to the same location */
if (calc_pnt.x == start_pnt.x && calc_pnt.y == start_pnt.y)
continue;
if (drawing_pic)
{
gdk_draw_line (pic_preview->window,
pic_preview->style->black_gc,
adjust_pic_coords (calc_pnt.x,
preview_width),
adjust_pic_coords (calc_pnt.y,
preview_height),
adjust_pic_coords (start_pnt.x,
preview_width),
adjust_pic_coords (start_pnt.y,
preview_height));
}
else
{
gdk_draw_line (gfig_preview->window,
gfig_gc,
gfig_scale_x (calc_pnt.x),
gfig_scale_y (calc_pnt.y),
gfig_scale_x (start_pnt.x),
gfig_scale_y (start_pnt.y));
}
}
else
{
do_line = 1;
first_pnt.x = calc_pnt.x;
first_pnt.y = calc_pnt.y;
}
start_pnt.x = calc_pnt.x;
start_pnt.y = calc_pnt.y;
}
}
static void
d_paint_spiral (Dobject *obj)
{
/* first point center */
/* Next point is radius */
gdouble *line_pnts;
gint seg_count = 0;
gint i = 0;
DobjPoints * center_pnt;
DobjPoints * radius_pnt;
gint16 shift_x;
gint16 shift_y;
gdouble ang_grid;
gdouble ang_loop;
gdouble radius;
gdouble offset_angle;
gdouble sp_cons;
gint loop;
GdkPoint last_pnt;
gint clock_wise = 1;
g_assert (obj != NULL);
center_pnt = obj->points;
if (!center_pnt || !center_pnt->next)
return; /* no-line */
/* Go around all the points drawing a line from one to the next */
radius_pnt = center_pnt->next; /* this defines the vetices */
/* Have center and radius - get lines */
shift_x = radius_pnt->pnt.x - center_pnt->pnt.x;
shift_y = radius_pnt->pnt.y - center_pnt->pnt.y;
radius = sqrt ((shift_x*shift_x) + (shift_y*shift_y));
clock_wise = obj->type_data / abs (obj->type_data);
offset_angle = atan2 (shift_y, shift_x);
if (offset_angle < 0)
offset_angle += 2*G_PI;
sp_cons = radius/(obj->type_data * 2 * G_PI + offset_angle);
/* Lines */
ang_grid = 2.0*G_PI/(gdouble)180;
/* count - */
seg_count = abs (obj->type_data * 180) + clock_wise*(gint)RINT (offset_angle/ang_grid);
line_pnts = g_new0 (gdouble, 2 * seg_count + 3);
for (loop = 0 ; loop <= seg_count; loop++)
{
gdouble lx, ly;
GdkPoint calc_pnt;
ang_loop = (gdouble)loop * ang_grid;
lx = sp_cons * ang_loop * cos (ang_loop)*clock_wise;
ly = sp_cons * ang_loop * sin (ang_loop);
calc_pnt.x = RINT (lx + center_pnt->pnt.x);
calc_pnt.y = RINT (ly + center_pnt->pnt.y);
/* Miss out duped pnts */
if (!loop)
{
if (calc_pnt.x == last_pnt.x && calc_pnt.y == last_pnt.y)
{
continue;
}
}
last_pnt.x = line_pnts[i++] = calc_pnt.x;
last_pnt.y = line_pnts[i++] = calc_pnt.y;
}
/* Reverse line if approp */
if (selvals.reverselines)
reverse_pairs_list (&line_pnts[0], i/2);
/* Scale before drawing */
if (selvals.scaletoimage)
scale_to_original_xy (&line_pnts[0], i/2);
else
scale_to_xy (&line_pnts[0], i/2);
/* One go */
if (selvals.painttype == PAINT_BRUSH_TYPE)
{
gfig_paint (selvals.brshtype,
gfig_drawable,
i, line_pnts);
}
else
{
gimp_free_select (gfig_image,
i, line_pnts,
selopt.type,
selopt.antia,
selopt.feather,
selopt.feather_radius);
}
g_free (line_pnts);
}
static Dobject *
d_copy_spiral (Dobject * obj)
{
Dobject *np;
#if DEBUG
printf ("Copy spiral\n");
#endif /* DEBUG */
if (!obj)
return (NULL);
g_assert (obj->type == SPIRAL);
np = d_new_spiral (obj->points->pnt.x, obj->points->pnt.y);
np->points->next = d_copy_dobjpoints (obj->points->next);
np->type_data = obj->type_data;
#if DEBUG
printf ("Done spiral copy\n");
#endif /* DEBUG */
return (np);
}
static Dobject *
d_new_spiral (gint x,
gint y)
{
Dobject *nobj;
DobjPoints *npnt;
/* Get new object and starting point */
/* Start point */
npnt = g_new0 (DobjPoints, 1);
#if DEBUG
printf ("New SPIRAL start at (%x,%x)\n", x, y);
#endif /* DEBUG */
npnt->pnt.x = x;
npnt->pnt.y = y;
nobj = g_new0 (Dobject, 1);
nobj->type = SPIRAL;
nobj->type_data = 4; /* Default to four turns */
nobj->points = npnt;
nobj->drawfunc = d_draw_spiral;
nobj->loadfunc = d_load_spiral;
nobj->savefunc = d_save_spiral;
nobj->paintfunc = d_paint_spiral;
nobj->copyfunc = d_copy_spiral;
return (nobj);
}
void
d_update_spiral (GdkPoint *pnt)
{
DobjPoints *center_pnt, *edge_pnt;
gint saved_cnt_pnt = selvals.opts.showcontrol;
/* Undraw last one then draw new one */
center_pnt = obj_creating->points;
if (!center_pnt)
return; /* No points */
/* Leave the first pnt alone -
* Edge point defines "radius"
* Only undraw if already have edge point.
*/
/* Hack - turn off cnt points in draw routine
* Looking back over the other update routines I could
* use this trick again and cut down on code size!
*/
if ((edge_pnt = center_pnt->next))
{
/* Undraw */
draw_circle (&edge_pnt->pnt);
selvals.opts.showcontrol = 0;
d_draw_spiral (obj_creating);
edge_pnt->pnt.x = pnt->x;
edge_pnt->pnt.y = pnt->y;
}
else
{
/* Radius is a few pixels away */
/* First edge point */
d_pnt_add_line (obj_creating, pnt->x, pnt->y, -1);
edge_pnt = center_pnt->next;
}
/* draw it */
selvals.opts.showcontrol = 0;
d_draw_spiral (obj_creating);
selvals.opts.showcontrol = saved_cnt_pnt;
/* Realy draw the control points */
draw_circle (&edge_pnt->pnt);
}
/* first point is center
* next defines the radius
*/
void
d_spiral_start (GdkPoint *pnt,
gint shift_down)
{
gint16 x, y;
/* First is center point */
obj_creating = d_new_spiral (x = pnt->x, y = pnt->y);
obj_creating->type_data = spiral_num_turns * ((spiral_toggle == 0) ? 1 : -1);
}
void
d_spiral_end (GdkPoint *pnt,
gint shift_down)
{
draw_circle (pnt);
add_to_all_obj (current_obj, obj_creating);
obj_creating = NULL;
}

View File

@ -0,0 +1,39 @@
/*
* 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.
*
*/
#ifndef __GFIG_SPIRAL_H__
#define __GFIG_SPIRAL_H__
gint spiral_button_press (GtkWidget *widget,
GdkEventButton *event,
gpointer data);
void d_update_spiral (GdkPoint *pnt);
void d_spiral_start (GdkPoint *pnt, gint shift_down);
void d_spiral_end (GdkPoint *pnt, gint shift_down);
Dobject * d_load_spiral (FILE *from);
#endif /* __GFIG_SPIRAL_H__ */

563
plug-ins/gfig/gfig_star.c Normal file
View File

@ -0,0 +1,563 @@
/*
* 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.
*
*/
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <gtk/gtk.h>
#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>
#include "config.h"
#include "libgimp/stdplugins-intl.h"
#include "gfig.h"
static gint star_num_sides = 3; /* Default to three sided object */
static void d_save_star (Dobject * obj, FILE *to);
static void d_draw_star (Dobject *obj);
static void d_paint_star (Dobject *obj);
static Dobject * d_copy_star (Dobject * obj);
static Dobject * d_new_star (gint x, gint y);
gint
star_button_press (GtkWidget *widget,
GdkEventButton *event,
gpointer data)
{
if ((event->type == GDK_2BUTTON_PRESS) &&
(event->button == 1))
num_sides_dialog (_("Star Number of Points"),
&star_num_sides, NULL, 3, 200);
return FALSE;
}
static void
d_save_star (Dobject *obj,
FILE *to)
{
DobjPoints *spnt;
spnt = obj->points;
if (!spnt)
return; /* End-of-line */
fprintf (to, "<STAR>\n");
while (spnt)
{
fprintf (to, "%d %d\n",
spnt->pnt.x,
spnt->pnt.y);
spnt = spnt->next;
}
fprintf (to, "<EXTRA>\n");
fprintf (to, "%d\n</EXTRA>\n", obj->type_data);
fprintf (to, "</STAR>\n");
}
Dobject *
d_load_star (FILE *from)
{
Dobject *new_obj = NULL;
gint xpnt;
gint ypnt;
gchar buf[MAX_LOAD_LINE];
while (get_line (buf, MAX_LOAD_LINE, from, 0))
{
if (sscanf (buf, "%d %d", &xpnt, &ypnt) != 2)
{
/* Must be the end */
if (!strcmp ("<EXTRA>", buf))
{
gint nsides = 3;
/* Number of sides - data item */
if (!new_obj)
{
g_warning ("[%d] Internal load error while loading star (extra area)",
line_no);
return (NULL);
}
get_line (buf, MAX_LOAD_LINE, from, 0);
if (sscanf (buf, "%d", &nsides) != 1)
{
g_warning ("[%d] Internal load error while loading star (extra area scanf)",
line_no);
return (NULL);
}
new_obj->type_data = nsides;
get_line (buf, MAX_LOAD_LINE, from, 0);
if (strcmp ("</EXTRA>", buf))
{
g_warning ("[%d] Internal load error while loading star",
line_no);
return NULL;
}
/* Go around and read the last line */
continue;
}
else if (strcmp ("</STAR>", buf))
{
g_warning ("[%d] Internal load error while loading star",
line_no);
return NULL;
}
return new_obj;
}
if (!new_obj)
new_obj = d_new_star (xpnt, ypnt);
else
d_pnt_add_line (new_obj, xpnt, ypnt,-1);
}
return new_obj;
}
static void
d_draw_star (Dobject *obj)
{
DobjPoints * center_pnt;
DobjPoints * outer_radius_pnt;
DobjPoints * inner_radius_pnt;
gint16 shift_x;
gint16 shift_y;
gdouble ang_grid;
gdouble ang_loop;
gdouble outer_radius;
gdouble inner_radius;
gdouble offset_angle;
gint loop;
GdkPoint start_pnt;
GdkPoint first_pnt;
gint do_line = 0;
center_pnt = obj->points;
if (!center_pnt)
return; /* End-of-line */
/* First point is the center */
/* Just draw a control point around it */
draw_sqr (&center_pnt->pnt);
/* Next point defines the radius */
outer_radius_pnt = center_pnt->next; /* this defines the vetices */
if (!outer_radius_pnt)
{
#ifdef DEBUG
g_warning ("Internal error in star - no outer vertice point \n");
#endif /* DEBUG */
return;
}
inner_radius_pnt = outer_radius_pnt->next; /* this defines the vetices */
if (!inner_radius_pnt)
{
#ifdef DEBUG
g_warning ("Internal error in star - no inner vertice point \n");
#endif /* DEBUG */
return;
}
/* Other control points */
draw_sqr (&outer_radius_pnt->pnt);
draw_sqr (&inner_radius_pnt->pnt);
/* Have center and radius - draw star */
shift_x = outer_radius_pnt->pnt.x - center_pnt->pnt.x;
shift_y = outer_radius_pnt->pnt.y - center_pnt->pnt.y;
outer_radius = sqrt ((shift_x*shift_x) + (shift_y*shift_y));
/* Lines */
ang_grid = 2*G_PI/(2.0*(gdouble) obj->type_data);
offset_angle = atan2 (shift_y, shift_x);
shift_x = inner_radius_pnt->pnt.x - center_pnt->pnt.x;
shift_y = inner_radius_pnt->pnt.y - center_pnt->pnt.y;
inner_radius = sqrt ((shift_x*shift_x) + (shift_y*shift_y));
for (loop = 0 ; loop < 2 * obj->type_data ; loop++)
{
gdouble lx, ly;
GdkPoint calc_pnt;
ang_loop = (gdouble)loop * ang_grid + offset_angle;
if (loop%2)
{
lx = inner_radius * cos (ang_loop);
ly = inner_radius * sin (ang_loop);
}
else
{
lx = outer_radius * cos (ang_loop);
ly = outer_radius * sin (ang_loop);
}
calc_pnt.x = RINT (lx + center_pnt->pnt.x);
calc_pnt.y = RINT (ly + center_pnt->pnt.y);
if (do_line)
{
/* Miss out points that come to the same location */
if (calc_pnt.x == start_pnt.x && calc_pnt.y == start_pnt.y)
continue;
if (drawing_pic)
{
gdk_draw_line (pic_preview->window,
pic_preview->style->black_gc,
adjust_pic_coords (calc_pnt.x,
preview_width),
adjust_pic_coords (calc_pnt.y,
preview_height),
adjust_pic_coords (start_pnt.x,
preview_width),
adjust_pic_coords (start_pnt.y,
preview_height));
}
else
{
gdk_draw_line (gfig_preview->window,
gfig_gc,
gfig_scale_x (calc_pnt.x),
gfig_scale_y (calc_pnt.y),
gfig_scale_x (start_pnt.x),
gfig_scale_y (start_pnt.y));
}
}
else
{
do_line = 1;
first_pnt.x = calc_pnt.x;
first_pnt.y = calc_pnt.y;
}
start_pnt.x = calc_pnt.x;
start_pnt.y = calc_pnt.y;
}
/* Join up */
if (drawing_pic)
{
gdk_draw_line (pic_preview->window,
pic_preview->style->black_gc,
adjust_pic_coords (first_pnt.x, preview_width),
adjust_pic_coords (first_pnt.y, preview_width),
adjust_pic_coords (start_pnt.x, preview_width),
adjust_pic_coords (start_pnt.y, preview_width));
}
else
{
gdk_draw_line (gfig_preview->window,
gfig_gc,
gfig_scale_x (first_pnt.x),
gfig_scale_y (first_pnt.y),
gfig_scale_x (start_pnt.x),
gfig_scale_y (start_pnt.y));
}
}
static void
d_paint_star (Dobject *obj)
{
/* first point center */
/* Next point is radius */
gdouble *line_pnts;
gint seg_count = 0;
gint i = 0;
DobjPoints * center_pnt;
DobjPoints * outer_radius_pnt;
DobjPoints * inner_radius_pnt;
gint16 shift_x;
gint16 shift_y;
gdouble ang_grid;
gdouble ang_loop;
gdouble outer_radius;
gdouble inner_radius;
gdouble offset_angle;
gint loop;
GdkPoint first_pnt, last_pnt;
gint first = 1;
g_assert (obj != NULL);
/* count - add one to close polygon */
seg_count = 2 * obj->type_data + 1;
center_pnt = obj->points;
if (!center_pnt || !seg_count)
return; /* no-line */
line_pnts = g_new0 (gdouble, 2 * seg_count + 1);
/* Go around all the points drawing a line from one to the next */
/* Next point defines the radius */
outer_radius_pnt = center_pnt->next; /* this defines the vetices */
if (!outer_radius_pnt)
{
#ifdef DEBUG
g_warning ("Internal error in star - no outer vertice point \n");
#endif /* DEBUG */
return;
}
inner_radius_pnt = outer_radius_pnt->next; /* this defines the vetices */
if (!inner_radius_pnt)
{
#ifdef DEBUG
g_warning ("Internal error in star - no inner vertice point \n");
#endif /* DEBUG */
return;
}
shift_x = outer_radius_pnt->pnt.x - center_pnt->pnt.x;
shift_y = outer_radius_pnt->pnt.y - center_pnt->pnt.y;
outer_radius = sqrt ((shift_x*shift_x) + (shift_y*shift_y));
/* Lines */
ang_grid = 2*G_PI/(2.0*(gdouble) obj->type_data);
offset_angle = atan2 (shift_y, shift_x);
shift_x = inner_radius_pnt->pnt.x - center_pnt->pnt.x;
shift_y = inner_radius_pnt->pnt.y - center_pnt->pnt.y;
inner_radius = sqrt ((shift_x*shift_x) + (shift_y*shift_y));
for (loop = 0 ; loop < 2*obj->type_data ; loop++)
{
gdouble lx, ly;
GdkPoint calc_pnt;
ang_loop = (gdouble)loop * ang_grid + offset_angle;
if (loop%2)
{
lx = inner_radius * cos (ang_loop);
ly = inner_radius * sin (ang_loop);
}
else
{
lx = outer_radius * cos (ang_loop);
ly = outer_radius * sin (ang_loop);
}
calc_pnt.x = RINT (lx + center_pnt->pnt.x);
calc_pnt.y = RINT (ly + center_pnt->pnt.y);
/* Miss out duped pnts */
if (!first)
{
if (calc_pnt.x == last_pnt.x && calc_pnt.y == last_pnt.y)
{
continue;
}
}
last_pnt.x = line_pnts[i++] = calc_pnt.x;
last_pnt.y = line_pnts[i++] = calc_pnt.y;
if (first)
{
first_pnt = calc_pnt;
first = 0;
}
}
line_pnts[i++] = first_pnt.x;
line_pnts[i++] = first_pnt.y;
/* Reverse line if approp */
if (selvals.reverselines)
reverse_pairs_list (&line_pnts[0], i/2);
/* Scale before drawing */
if (selvals.scaletoimage)
scale_to_original_xy (&line_pnts[0], i/2);
else
scale_to_xy (&line_pnts[0], i/2);
/* One go */
if (selvals.painttype == PAINT_BRUSH_TYPE)
{
gfig_paint (selvals.brshtype,
gfig_drawable,
i, line_pnts);
}
else
{
gimp_free_select (gfig_image,
i, line_pnts,
selopt.type,
selopt.antia,
selopt.feather,
selopt.feather_radius);
}
g_free (line_pnts);
}
static Dobject *
d_copy_star (Dobject * obj)
{
Dobject *np;
if (!obj)
return (NULL);
g_assert (obj->type == STAR);
np = d_new_star (obj->points->pnt.x, obj->points->pnt.y);
np->points->next = d_copy_dobjpoints (obj->points->next);
np->type_data = obj->type_data;
return np;
}
static Dobject *
d_new_star (gint x,
gint y)
{
Dobject *nobj;
DobjPoints *npnt;
/* Get new object and starting point */
/* Start point */
npnt = g_new0 (DobjPoints, 1);
npnt->pnt.x = x;
npnt->pnt.y = y;
nobj = g_new0 (Dobject, 1);
nobj->type = STAR;
nobj->type_data = 3; /* Default to three sides 6 points*/
nobj->points = npnt;
nobj->drawfunc = d_draw_star;
nobj->loadfunc = d_load_star;
nobj->savefunc = d_save_star;
nobj->paintfunc = d_paint_star;
nobj->copyfunc = d_copy_star;
return nobj;
}
void
d_update_star (GdkPoint *pnt)
{
DobjPoints *center_pnt, *inner_pnt, *outer_pnt;
gint saved_cnt_pnt = selvals.opts.showcontrol;
/* Undraw last one then draw new one */
center_pnt = obj_creating->points;
if (!center_pnt)
return; /* No points */
/* Leave the first pnt alone -
* Edge point defines "radius"
* Only undraw if already have edge point.
*/
/* Hack - turn off cnt points in draw routine
* Looking back over the other update routines I could
* use this trick again and cut down on code size!
*/
if ((outer_pnt = center_pnt->next))
{
/* Undraw */
inner_pnt = outer_pnt->next;
draw_circle (&inner_pnt->pnt);
draw_circle (&outer_pnt->pnt);
selvals.opts.showcontrol = 0;
d_draw_star (obj_creating);
outer_pnt->pnt.x = pnt->x;
outer_pnt->pnt.y = pnt->y;
inner_pnt->pnt.x = pnt->x + (2*(center_pnt->pnt.x - pnt->x))/3;
inner_pnt->pnt.y = pnt->y + (2*(center_pnt->pnt.y - pnt->y))/3;
}
else
{
/* Radius is a few pixels away */
/* First edge point */
d_pnt_add_line (obj_creating, pnt->x, pnt->y,-1);
outer_pnt = center_pnt->next;
/* Inner radius */
d_pnt_add_line (obj_creating,
pnt->x + (2*(center_pnt->pnt.x - pnt->x))/3,
pnt->y + (2*(center_pnt->pnt.y - pnt->y))/3,
-1);
inner_pnt = outer_pnt->next;
}
/* draw it */
selvals.opts.showcontrol = 0;
d_draw_star (obj_creating);
selvals.opts.showcontrol = saved_cnt_pnt;
/* Realy draw the control points */
draw_circle (&outer_pnt->pnt);
draw_circle (&inner_pnt->pnt);
}
void
d_star_start (GdkPoint *pnt,
gint shift_down)
{
obj_creating = d_new_star ((gint) pnt->x, (gint) pnt->y);
obj_creating->type_data = star_num_sides;
}
void
d_star_end (GdkPoint *pnt,
gint shift_down)
{
draw_circle (pnt);
add_to_all_obj (current_obj, obj_creating);
obj_creating = NULL;
}

39
plug-ins/gfig/gfig_star.h Normal file
View File

@ -0,0 +1,39 @@
/*
* 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.
*
*/
#ifndef __GFIG_STAR_H__
#define __GFIG_STAR_H__
gint star_button_press (GtkWidget *widget,
GdkEventButton *event,
gpointer data);
void d_update_star (GdkPoint *pnt);
void d_star_start (GdkPoint *pnt, gint shift_down);
void d_star_end (GdkPoint *pnt, gint shift_down);
Dobject * d_load_star (FILE *from);
#endif /* __GFIG_STAR_H__ */