home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / path_bezier.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-09  |  6.8 KB  |  275 lines

  1. /* The GIMP -- an image manipulation program
  2.  *
  3.  * This file Copyright (C) 1999 Simon Budig
  4.  *
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2 of the License, or
  8.  * (at your option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18.  */
  19.  
  20. #include <math.h>
  21.  
  22. #include "path_bezier.h"
  23.  
  24. #define HANDLE_HALFWIDTH 3
  25. #define HANDLE_WIDTH 6
  26.  
  27. /*
  28.  * This function is to get a set of npoints different coordinates for
  29.  * the range from start to end (each in the range from 0 to 1 and
  30.  * start < end.
  31.  * returns the number of created coords. Make sure that the points-
  32.  * Array is allocated.
  33.  */
  34.  
  35. guint
  36. path_bezier_get_points (PathTool *path_tool,
  37.                         PathSegment *segment,
  38.             GdkPoint *points,
  39.             guint npoints,
  40.             gdouble start,
  41.             gdouble end)
  42. {
  43.    return 0;
  44. }
  45.  
  46. void
  47. path_bezier_get_point (PathTool *path_tool,
  48.                PathSegment *segment,
  49.                gdouble pos,
  50.                gdouble *x,
  51.                gdouble *y)
  52. {
  53.    PathBezierData *data = (PathBezierData *) segment->data;
  54.    
  55.    if (segment->next) {
  56.  
  57.       *x = (1-pos) * (1-pos) * (1-pos) * segment->x
  58.      + 3 * pos * (1-pos) * (1-pos) * (segment->x + data->x1)
  59.      + 3 * pos * pos * (1-pos) * (segment->next->x + data->x2)
  60.      + pos * pos * pos * (segment->next->x);
  61.  
  62.       *y = (1-pos) * (1-pos) * (1-pos) * segment->y
  63.      + 3 * pos * (1-pos) * (1-pos) * (segment->y + data->y1)
  64.      + 3 * pos * pos * (1-pos) * (segment->next->y + data->y2)
  65.      + pos * pos * pos * (segment->next->y);
  66.    }
  67. #ifdef PATH_TOOL_DEBUG
  68.    else fprintf (stderr, "FIXME: path_bezier_get_point called with endpoint-segment!!!\n");
  69. #endif
  70.              
  71.    return;
  72. }
  73.  
  74. void
  75. path_bezier_draw_handles (Tool *tool,
  76.               PathSegment *segment)
  77. {
  78.    PathTool *path_tool = (PathTool *) (tool->private);
  79.    PathBezierData *data = (PathBezierData *) segment->data;
  80.    GDisplay * gdisp = tool->gdisp_ptr;
  81.  
  82.    gint sx, sy, hx, hy;
  83.    
  84.    if (segment->next) {
  85.       if (segment->flags & SEGMENT_ACTIVE) {
  86.      gdisplay_transform_coords (gdisp,
  87.            (gint) (segment->x), (gint) (segment->y), &sx, &sy, FALSE);
  88.      gdisplay_transform_coords (gdisp,
  89.            (gint) (segment->x + data->x1),
  90.            (gint) (segment->y + data->y1), &hx, &hy, FALSE);
  91.  
  92.      gdk_draw_line (path_tool->core->win,
  93.            path_tool->core->gc, hx, hy, sx, sy);
  94.  
  95.      gdk_draw_rectangle (path_tool->core->win, path_tool->core->gc, 0,
  96.            hx - HANDLE_HALFWIDTH, hy - HANDLE_HALFWIDTH,
  97.            HANDLE_WIDTH, HANDLE_WIDTH);
  98.       }
  99.  
  100.       if (segment->next->flags & SEGMENT_ACTIVE) { 
  101.      gdisplay_transform_coords (gdisp,
  102.            (gint) (segment->next->x), (gint) (segment->next->y), &sx, &sy, FALSE);
  103.      gdisplay_transform_coords (gdisp,
  104.            (gint) (segment->next->x + data->x2),
  105.            (gint) (segment->next->y + data->y2), &hx, &hy, FALSE);
  106.  
  107.      gdk_draw_line (path_tool->core->win,
  108.            path_tool->core->gc, hx, hy, sx, sy);
  109.  
  110.      gdk_draw_rectangle (path_tool->core->win, path_tool->core->gc, 0,
  111.            hx - HANDLE_HALFWIDTH, hy - HANDLE_HALFWIDTH,
  112.            HANDLE_WIDTH, HANDLE_WIDTH);
  113.       }
  114.    }
  115. }
  116.  
  117. void
  118. path_bezier_draw_segment (Tool *tool,
  119.               PathSegment *segment)
  120. {
  121.    return;
  122. }
  123.  
  124.  
  125. gdouble
  126. path_bezier_on_segment (Tool *tool,
  127.             PathSegment *segment,
  128.             gint x,
  129.             gint y,
  130.             gint halfwidth,
  131.             gint *distance)
  132. {
  133.    return -1;
  134. }
  135.  
  136. void
  137. path_bezier_drag_segment (PathTool *path_tool,
  138.               PathSegment *segment,
  139.               gdouble pos,
  140.               gdouble dx,
  141.               gdouble dy)
  142. {
  143.    PathBezierData *data = (PathBezierData *) segment->data;
  144.    gdouble feel_good;
  145.  
  146.    if (pos <= 0.5)
  147.       feel_good = (pow(2 * pos, 3)) / 2;
  148.    else
  149.       feel_good = (1 - pow((1-pos)*2, 3)) / 2 + 0.5;
  150.    
  151.    data->x1 += (dx / (3*pos*(1-pos)*(1-pos)))*(1-feel_good);
  152.    data->y1 += (dy / (3*pos*(1-pos)*(1-pos)))*(1-feel_good);
  153.    data->x2 += (dx / (3*pos*pos*(1-pos)))*feel_good;
  154.    data->y2 += (dy / (3*pos*pos*(1-pos)))*feel_good;
  155.  
  156.    return;
  157. }
  158.  
  159. gint
  160. path_bezier_on_handles (PathTool *path_tool,
  161.             PathSegment *segment,
  162.             gdouble x,
  163.             gdouble y,
  164.             gdouble halfwidth)
  165. {
  166.    PathBezierData *data = (PathBezierData *) segment->data;
  167.        
  168.    if (segment->flags & SEGMENT_ACTIVE &&
  169.        fabs(segment->x + data->x1 - x) <= halfwidth &&
  170.        fabs(segment->y + data->y1 - y) <= halfwidth)
  171.       return 1;
  172.  
  173.    if (segment->next && segment->next->flags & SEGMENT_ACTIVE &&
  174.        fabs(segment->next->x + data->x2 - x) <= halfwidth &&
  175.        fabs(segment->next->y + data->y2 - y) <= halfwidth)
  176.      return 2;
  177.  
  178.    return 0;
  179. }
  180.  
  181. void
  182. path_bezier_drag_handles (PathTool *path_tool,
  183.               PathSegment *segment,
  184.               gdouble dx,
  185.               gdouble dy,
  186.               gint handle_id)
  187. {
  188.    PathBezierData *data = (PathBezierData *) segment->data;
  189.    
  190.    if (handle_id == 1) {
  191.       data->x1 += dx;
  192.       data->y1 += dy;
  193.    } else {
  194.       data->x2 += dx;
  195.       data->y2 += dy;
  196.    }
  197. }
  198.  
  199.             
  200. PathSegment *
  201. path_bezier_insert_anchor (PathTool *path_tool,
  202.                PathSegment *segment,
  203.                gdouble position)
  204. {
  205.    return NULL;
  206. }
  207.  
  208. void
  209. path_bezier_update_segment (PathTool *path_tool,
  210.                 PathSegment *segment)
  211. {
  212.    return;
  213. }
  214.  
  215.  
  216. void
  217. path_bezier_flip_segment (PathSegment *segment)
  218. {
  219.    PathBezierData *data = (PathBezierData *) segment->data;
  220.    gdouble swap;
  221.    
  222.    swap = data->x1;
  223.    data->x1 = data->x2;
  224.    data->x2 = swap;
  225.    
  226.    swap = data->y1;
  227.    data->y1 = data->y2;
  228.    data->y2 = swap;
  229.  
  230.    return;
  231. }
  232.  
  233.  
  234. void
  235. path_bezier_init_segment (PathSegment *segment)
  236. {
  237.    PathBezierData *data, *neardata;
  238.    
  239.    data = g_new(PathBezierData, 1);
  240.    data->x1 = 0;
  241.    data->y1 = 0;
  242.    data->x2 = 0;
  243.    data->y2 = 0;
  244.    if (segment->prev && segment->prev->type == SEGMENT_BEZIER) {
  245.       neardata = (PathBezierData *) segment->prev->data;
  246.       data->x1 = - neardata->x2;
  247.       data->y1 = - neardata->y2;
  248.    }
  249.    if (segment->next && segment->next->type == SEGMENT_BEZIER) {
  250.       neardata = (PathBezierData *) segment->next->data;
  251.       data->x2 = - neardata->x1;
  252.       data->y2 = - neardata->y1;
  253.    }
  254.  
  255. #ifdef PATH_TOOL_DEBUG
  256.    if (segment->data)
  257.       fprintf(stderr, "Warning: path_bezier_init_segment called with already initialized segment\n");
  258. #endif
  259.    segment->data = data;
  260.  
  261.    return;
  262. }
  263.  
  264.  
  265. void
  266. path_bezier_cleanup_segment (PathSegment *segment)
  267. {
  268.    g_free(segment->data);
  269.    segment->data = NULL;
  270.  
  271.    return;
  272. }
  273.  
  274.  
  275.