mirror of https://github.com/GNOME/gimp.git
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:
parent
9407ecba10
commit
416d2e2fdc
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
4686
plug-ins/gfig/gfig.c
4686
plug-ins/gfig/gfig.c
File diff suppressed because it is too large
Load Diff
|
@ -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__ */
|
|
@ -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, ¢er_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, ¢er_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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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__ */
|
|
@ -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);
|
||||
}
|
|
@ -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__ */
|
|
@ -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 (¢er_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;
|
||||
}
|
||||
|
|
@ -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__ */
|
|
@ -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__ */
|
||||
|
||||
|
|
@ -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 (¢er_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;
|
||||
}
|
|
@ -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__ */
|
|
@ -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);*/
|
||||
}
|
|
@ -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__ */
|
|
@ -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 (¢er_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;
|
||||
}
|
|
@ -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__ */
|
|
@ -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 (¢er_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;
|
||||
}
|
|
@ -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__ */
|
|
@ -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 (¢er_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;
|
||||
}
|
||||
|
|
@ -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__ */
|
Loading…
Reference in New Issue