home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / plug-ins / common / film.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-08-24  |  45.3 KB  |  1,547 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  * Film plug-in (C) 1997 Peter Kirchgessner
  4.  * e-mail: pkirchg@aol.com, WWW: http://members.aol.com/pkirchg
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2 of the License, or
  9.  * (at your option) any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program; if not, write to the Free Software
  18.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19.  */
  20.  
  21. /*
  22.  * This plug-in generates a film roll with several images
  23.  */
  24.  
  25. /* Event history:
  26.  * V 1.00, PK, 01-Jul-97, Creation
  27.  * V 1.01, PK, 24-Jul-97, Fix problem with previews on Irix
  28.  * V 1.02, PK, 24-Sep-97, Try different font sizes when inquire failed.
  29.  *                        Fit film height to images
  30.  * V 1.03, nn, 20-Dec-97, Initialize layers in film()
  31.  * V 1.04, PK, 08-Oct-99, Fix problem with image id zero
  32.  *                        Internationalization
  33.  */
  34. static char ident[] = "@(#) GIMP Film plug-in v1.04 1999-10-08";
  35.  
  36. #include "config.h"
  37.  
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include <string.h>
  41. #include <ctype.h>
  42.  
  43. #include <gtk/gtk.h>
  44.  
  45. #include <libgimp/gimp.h>
  46. #include <libgimp/gimpui.h>
  47.  
  48. #include "libgimp/stdplugins-intl.h"
  49.  
  50.  
  51. /* Maximum number of pictures per film */
  52. #define MAX_FILM_PICTURES   64
  53. #define COLOR_BUTTON_WIDTH  50
  54. #define COLOR_BUTTON_HEIGHT 20
  55.  
  56. /* Define how the plug-in works. Values marked (r) are with regard */
  57. /* to film_height (i.e. it should be a value from 0.0 to 1.0) */
  58. typedef struct
  59. {
  60.   gint     film_height;           /* height of the film */
  61.   guchar   film_color[3];         /* color of film */
  62.   gdouble  picture_height;        /* height of picture (r) */
  63.   gdouble  picture_space;         /* space between pictures (r) */
  64.   gdouble  hole_offset;           /* distance from hole to edge of film (r) */
  65.   gdouble  hole_width;            /* width of hole (r) */
  66.   gdouble  hole_height;           /* height of holes (r) */
  67.   gdouble  hole_space;            /* distance of holes (r) */
  68.   gdouble  number_height;         /* height of picture numbering (r) */
  69.   gint     number_start;          /* number for first picture */
  70.   guchar   number_color[3];       /* color of number */
  71.   gchar    number_fontf[256];     /* font family to use for numbering */
  72.   gint     number_pos[2];         /* flags where to draw numbers (top/bottom) */
  73.   gint     keep_height;           /* flag if to keep max. image height */
  74.   gint     num_images;            /* number of images */
  75.   gint32   image[MAX_FILM_PICTURES]; /* list of image IDs */
  76. } FilmVals;
  77.  
  78. /* Data to use for the dialog */
  79. typedef struct
  80. {
  81.   GtkWidget *font_entry;
  82.   GtkObject *advanced_adj[7];
  83.   GtkWidget *image_list_all;
  84.   GtkWidget *image_list_film;
  85.   gint       run;
  86. } FilmInterface;
  87.  
  88.  
  89. /* Declare local functions
  90.  */
  91. static void      query  (void);
  92. static void      run    (gchar     *name,
  93.              gint       nparams,
  94.              GimpParam    *param,
  95.              gint      *nreturn_vals,
  96.              GimpParam   **return_vals);
  97.  
  98.  
  99. static gint32    create_new_image   (gchar          *filename,
  100.                      guint           width,
  101.                      guint           height,
  102.                      GimpImageType   gdtype,
  103.                      gint32         *layer_ID,
  104.                      GimpDrawable     **drawable,
  105.                      GimpPixelRgn      *pixel_rgn);
  106.  
  107. static gchar   * compose_image_name (gint32          image_ID);
  108.  
  109. static gint32    film               (void);
  110.  
  111. static gint      check_filmvals     (void);
  112.  
  113. static void      convert_to_rgb     (GimpDrawable      *srcdrawable,
  114.                      gint            numpix,
  115.                      guchar         *src,
  116.                      guchar         *dst);
  117.  
  118. static void      set_pixels         (gint            numpix,
  119.                      guchar         *dst,
  120.                      guchar         *rgb);
  121.  
  122. static gint      scale_layer        (gint32          src_layer,
  123.                      gint            src_x0,
  124.                      gint            src_y0,
  125.                      gint            src_width,
  126.                      gint            src_height,
  127.                      gint32          dst_layer,
  128.                      gint            dst_x0,
  129.                      gint            dst_y0,
  130.                      gint            dst_width,
  131.                      gint            dst_height);
  132.  
  133. static guchar  * create_hole_rgb    (gint            width,
  134.                      gint            height);
  135.  
  136. static void      draw_hole_rgb      (GimpDrawable      *drw,
  137.                      gint            x,
  138.                      gint            y,
  139.                      gint            width,
  140.                      gint            height,
  141.                      guchar         *hole);
  142.  
  143. static void      draw_number        (gint32          layer_ID,
  144.                      gint            num,
  145.                      gint            x,
  146.                      gint            y,
  147.                      gint            height);
  148.  
  149.  
  150. static void        add_list_item_callback (GtkWidget *widget,
  151.                        GtkWidget *list);
  152. static void        del_list_item_callback (GtkWidget *widget,
  153.                        GtkWidget *list);
  154.  
  155. static GtkWidget * add_image_list         (gint       add_box_flag,
  156.                        gint       n,
  157.                        gint32    *image_id,
  158.                        GtkWidget *hbox);
  159.  
  160. static gint        film_dialog            (gint32     image_ID);
  161. static void        film_ok_callback       (GtkWidget *widget,
  162.                        gpointer   data);
  163. static void        film_reset_callback    (GtkWidget *widget,
  164.                        gpointer   data);
  165.  
  166.  
  167. GimpPlugInInfo PLUG_IN_INFO =
  168. {
  169.   NULL,  /* init_proc  */
  170.   NULL,  /* quit_proc  */
  171.   query, /* query_proc */
  172.   run,   /* run_proc   */
  173. };
  174.  
  175. static gdouble advanced_defaults[] =
  176. {
  177.   0.695,           /* Picture height */
  178.   0.040,           /* Picture spacing */
  179.   0.058,           /* Hole offset to edge of film */
  180.   0.052,           /* Hole width */
  181.   0.081,           /* Hole height */
  182.   0.081,           /* Hole distance */
  183.   0.052            /* Image number height */
  184. };
  185.  
  186. static FilmVals filmvals =
  187. {
  188.   256,             /* Height of film */
  189.   { 0, 0, 0 },     /* Color of film */
  190.   0.695,           /* Picture height */
  191.   0.040,           /* Picture spacing */
  192.   0.058,           /* Hole offset to edge of film */
  193.   0.052,           /* Hole width */
  194.   0.081,           /* Hole height */
  195.   0.081,           /* Hole distance */
  196.   0.052,           /* Image number height */
  197.   1,               /* Start index of numbering */
  198.   { 239, 159, 0 }, /* Color of number */
  199.   "courier",       /* Font family for numbering */
  200.   { TRUE, TRUE },  /* Numbering on top and bottom */
  201.   0,               /* Dont keep max. image height */
  202.   0,               /* Number of images */
  203.   { 0 }            /* Input image list */
  204. };
  205.  
  206.  
  207. static FilmInterface filmint =
  208. {
  209.   NULL,       /* font entry */
  210.   { NULL },   /* advanced adjustments */
  211.   NULL, NULL, /* image list widgets */
  212.   FALSE       /* run */
  213. };
  214.  
  215.  
  216. static GimpRunModeType run_mode;
  217.  
  218.  
  219. MAIN ()
  220.  
  221. static void
  222. query (void)
  223. {
  224.   static GimpParamDef args[] =
  225.   {
  226.     { GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
  227.     { GIMP_PDB_IMAGE, "image", "Input image (only used as default image in interactive mode)" },
  228.     { GIMP_PDB_DRAWABLE, "drawable", "Input drawable (not used)" },
  229.     { GIMP_PDB_INT32, "film_height", "Height of film (0: fit to images)" },
  230.     { GIMP_PDB_COLOR, "film_color", "Color of the film" },
  231.     { GIMP_PDB_INT32, "number_start", "Start index for numbering" },
  232.     { GIMP_PDB_STRING, "number_fontf", "Font family for drawing numbers" },
  233.     { GIMP_PDB_COLOR, "number_color", "Color for numbers" },
  234.     { GIMP_PDB_INT32, "at_top", "Flag for drawing numbers at top of film" },
  235.     { GIMP_PDB_INT32, "at_bottom", "Flag for drawing numbers at bottom of film" },
  236.     { GIMP_PDB_INT32, "num_images", "Number of images to be used for film" },
  237.     { GIMP_PDB_INT32ARRAY, "image_ids", "num_images image IDs to be used for film"}
  238.   };
  239.   static gint nargs = sizeof (args) / sizeof (args[0]);
  240.  
  241.   static GimpParamDef return_vals[] =
  242.   {
  243.     { GIMP_PDB_IMAGE, "new_image", "Output image" }
  244.   };
  245.   static gint nreturn_vals = sizeof (return_vals) / sizeof (return_vals[0]);
  246.  
  247.   gimp_install_procedure ("plug_in_film",
  248.               "Compose several images to a roll film",
  249.               "Compose several images to a roll film",
  250.               "Peter Kirchgessner",
  251.               "Peter Kirchgessner (peter@kirchgessner.net)",
  252.               "1997",
  253.               N_("<Image>/Filters/Combine/Film..."),
  254.               "INDEXED*, GRAY*, RGB*",
  255.               GIMP_PLUGIN,
  256.               nargs, nreturn_vals,
  257.               args, return_vals);
  258. }
  259.  
  260. static void
  261. run (gchar   *name,
  262.      gint     nparams,
  263.      GimpParam  *param,
  264.      gint    *nreturn_vals,
  265.      GimpParam **return_vals)
  266. {
  267.   static GimpParam values[2];
  268.   GimpPDBStatusType status = GIMP_PDB_SUCCESS;
  269.   gint32 image_ID;
  270.   gint k;
  271.  
  272.   INIT_I18N_UI();
  273.  
  274.   run_mode = param[0].data.d_int32;
  275.  
  276.   *nreturn_vals = 2;
  277.   *return_vals = values;
  278.  
  279.   values[0].type = GIMP_PDB_STATUS;
  280.   values[0].data.d_status = status;
  281.   values[1].type = GIMP_PDB_IMAGE;
  282.   values[1].data.d_int32 = -1;
  283.  
  284.   switch (run_mode)
  285.     {
  286.     case GIMP_RUN_INTERACTIVE:
  287.       /*  Possibly retrieve data  */
  288.       gimp_get_data ("plug_in_film", &filmvals);
  289.  
  290.       /*  First acquire information with a dialog  */
  291.       if (! film_dialog (param[1].data.d_int32))
  292.     return;
  293.       break;
  294.  
  295.     case GIMP_RUN_NONINTERACTIVE:
  296.       /*  Make sure all the arguments are there!  */
  297.       /* Also we want to have some images to compose */
  298.       if ((nparams != 12) || (param[10].data.d_int32 < 1))
  299.     {
  300.       status = GIMP_PDB_CALLING_ERROR;
  301.     }
  302.       else
  303.     {
  304.           filmvals.keep_height       = (param[3].data.d_int32 <= 0);
  305.           filmvals.film_height       = (filmvals.keep_height ?
  306.                     128 : param[3].data.d_int32);
  307.           filmvals.film_color[0]     = param[4].data.d_color.red;
  308.           filmvals.film_color[1]     = param[4].data.d_color.green;
  309.           filmvals.film_color[2]     = param[4].data.d_color.blue;
  310.           filmvals.number_start      = param[5].data.d_int32;
  311.           k = sizeof (filmvals.number_fontf);
  312.           strncpy (filmvals.number_fontf, param[6].data.d_string, k);
  313.           filmvals.number_fontf[k-1] = '\0';
  314.           filmvals.number_color[0]   = param[7].data.d_color.red;
  315.           filmvals.number_color[1]   = param[7].data.d_color.green;
  316.           filmvals.number_color[2]   = param[7].data.d_color.blue;
  317.           filmvals.number_pos[0]     = param[8].data.d_int32;
  318.           filmvals.number_pos[1]     = param[9].data.d_int32;
  319.           filmvals.num_images        = param[10].data.d_int32;
  320.           if (filmvals.num_images > MAX_FILM_PICTURES)
  321.             filmvals.num_images = MAX_FILM_PICTURES;
  322.           for (k = 0; k < filmvals.num_images; k++)
  323.             filmvals.image[k] = param[11].data.d_int32array[k];
  324.     }
  325.       break;
  326.  
  327.     case GIMP_RUN_WITH_LAST_VALS:
  328.       /*  Possibly retrieve data  */
  329.       gimp_get_data ("plug_in_film", &filmvals);
  330.       break;
  331.  
  332.     default:
  333.       break;
  334.     }
  335.  
  336.   if (check_filmvals () < 0)
  337.     status = GIMP_PDB_CALLING_ERROR;
  338.  
  339.   if (status == GIMP_PDB_SUCCESS)
  340.     {
  341.       if (run_mode != GIMP_RUN_NONINTERACTIVE)
  342.         gimp_progress_init (_("Composing Images..."));
  343.  
  344.       image_ID = film ();
  345.  
  346.       if (image_ID < 0)
  347.     {
  348.       status = GIMP_PDB_EXECUTION_ERROR;
  349.     }
  350.       else
  351.     {
  352.       values[1].data.d_int32 = image_ID;
  353.       gimp_image_undo_enable (image_ID);
  354.       gimp_image_clean_all (image_ID);
  355.       if (run_mode != GIMP_RUN_NONINTERACTIVE)
  356.         gimp_display_new (image_ID);
  357.     }
  358.  
  359.       /*  Store data  */
  360.       if (run_mode == GIMP_RUN_INTERACTIVE)
  361.         gimp_set_data ("plug_in_film", &filmvals, sizeof (FilmVals));
  362.     }
  363.  
  364.   values[0].data.d_status = status;
  365. }
  366.  
  367.  
  368. /* Compose a roll film image from several images */
  369. static gint32
  370. film (void)
  371. {
  372.   gint width, height, tile_height, scan_lines;
  373.   guchar *dst, *hole;
  374.   gint film_height, film_width;
  375.   gint picture_width, picture_height, picture_space, picture_x0, picture_y0;
  376.   gint hole_offset, hole_width, hole_height, hole_space, hole_x;
  377.   gint number_height, num_images, num_pictures;
  378.   gint i, j, k, picture_count;
  379.   gdouble f;
  380.   guchar f_red, f_green, f_blue;
  381.   gint num_layers;
  382.   gint32 *image_ID_src, image_ID_dst, layer_ID_src, layer_ID_dst;
  383.   gint32 *layers;
  384.   GimpDrawable *drawable_dst;
  385.   GimpPixelRgn pixel_rgn_dst;
  386.  
  387.   /* initialize */
  388.  
  389.   layers = NULL;
  390.  
  391.   num_images = filmvals.num_images;
  392.   image_ID_src = filmvals.image;
  393.  
  394.   if (num_images <= 0)
  395.     return (-1);
  396.  
  397.   tile_height = gimp_tile_height ();
  398.   /* Save foreground colour */
  399.   gimp_palette_get_foreground (&f_red, &f_green, &f_blue);
  400.  
  401.   if (filmvals.keep_height) /* Search maximum picture height */
  402.     {
  403.       picture_height = 0;
  404.       for (j = 0; j < num_images; j++)
  405.     {
  406.       height = gimp_image_height (image_ID_src[j]);
  407.       if (height > picture_height) picture_height = height;
  408.     }
  409.       film_height = (int)(picture_height / filmvals.picture_height + 0.5);
  410.       filmvals.film_height = film_height;
  411.     }
  412.   else
  413.     {
  414.       film_height = filmvals.film_height;
  415.       picture_height = (int)(film_height * filmvals.picture_height + 0.5);
  416.     }
  417.   picture_space = (int)(film_height * filmvals.picture_space + 0.5);
  418.   picture_y0 = (film_height - picture_height)/2;
  419.  
  420.   number_height = film_height * filmvals.number_height;
  421.  
  422.   /* Calculate total film width */
  423.   film_width = 0;
  424.   num_pictures = 0;
  425.   for (j = 0; j < num_images; j++)
  426.     {
  427.       layers = gimp_image_get_layers (image_ID_src[j], &num_layers);
  428.       /* Get scaled image size */
  429.       width = gimp_image_width (image_ID_src[j]);
  430.       height = gimp_image_height (image_ID_src[j]);
  431.       f = ((double)picture_height) / (double)height;
  432.       picture_width = width * f;
  433.  
  434.       for (k = 0; k < num_layers; k++)
  435.     {
  436.       if (gimp_layer_is_floating_selection (layers[k]))
  437.         continue;
  438.  
  439.       film_width += (picture_space/2);  /* Leading space */
  440.       film_width += picture_width;      /* Scaled image width */
  441.       film_width += (picture_space/2);  /* Trailing space */
  442.       num_pictures++;
  443.     }
  444.  
  445.       if (layers)
  446.     g_free (layers);
  447.     }
  448. #ifdef FILM_DEBUG
  449.   printf ("film_height = %d, film_width = %d\n", film_height, film_width);
  450.   printf ("picture_height = %d, picture_space = %d, picture_y0 = %d\n",
  451.       picture_height, picture_space, picture_y0);
  452.   printf ("Number of pictures = %d\n", num_pictures);
  453. #endif
  454.  
  455.   image_ID_dst = create_new_image (_("Untitled"),
  456.                    (guint) film_width, (guint) film_height,
  457.                    GIMP_RGB_IMAGE, &layer_ID_dst,
  458.                    &drawable_dst, &pixel_rgn_dst);
  459.  
  460.   dst = g_new (guchar, film_width * tile_height * 3);
  461.  
  462.   /* Fill film background */
  463.   i = 0;
  464.   while (i < film_height)
  465.     {
  466.       scan_lines =
  467.     (i + tile_height - 1 < film_height) ? tile_height : (film_height - i);
  468.  
  469.       set_pixels (film_width * scan_lines, dst, filmvals.film_color);
  470.  
  471.       gimp_pixel_rgn_set_rect (&pixel_rgn_dst, dst, 0, i,
  472.                    film_width, scan_lines);
  473.       i += scan_lines;
  474.     }
  475.   g_free (dst);
  476.  
  477.   /* Draw all the holes */
  478.   hole_offset = film_height * filmvals.hole_offset;
  479.   hole_width = film_height * filmvals.hole_width;
  480.   hole_height = film_height * filmvals.hole_height;
  481.   hole_space = film_height * filmvals.hole_space;
  482.   hole_x = hole_space / 2;
  483.  
  484. #ifdef FILM_DEBUG
  485.   printf ("hole_x %d hole_offset %d hole_width %d hole_height %d hole_space %d\n",
  486.       hole_x, hole_offset, hole_width, hole_height, hole_space );
  487. #endif
  488.  
  489.   hole = create_hole_rgb (hole_width, hole_height);
  490.   if (hole)
  491.     {
  492.       while (hole_x < film_width)
  493.     {
  494.       draw_hole_rgb (drawable_dst, hole_x,
  495.              hole_offset,
  496.              hole_width, hole_height, hole);
  497.       draw_hole_rgb (drawable_dst, hole_x,
  498.              film_height-hole_offset-hole_height,
  499.              hole_width, hole_height, hole);
  500.  
  501.       hole_x += hole_width + hole_space;
  502.     }
  503.       g_free (hole);
  504.     }
  505.   gimp_drawable_detach (drawable_dst);
  506.  
  507.   /* Compose all images and layers */
  508.   picture_x0 = 0;
  509.   picture_count = 0;
  510.   for (j = 0; j < num_images; j++)
  511.     {
  512.       width = gimp_image_width (image_ID_src[j]);
  513.       height = gimp_image_height (image_ID_src[j]);
  514.       f = ((gdouble) picture_height) / (gdouble) height;
  515.       picture_width = width * f;
  516.  
  517.       layers = gimp_image_get_layers (image_ID_src[j], &num_layers);
  518.  
  519.       for (k = 0; k < num_layers; k++)
  520.     {
  521.       if (gimp_layer_is_floating_selection (layers[k]))
  522.         continue;
  523.  
  524.       picture_x0 += (picture_space/2);
  525.  
  526.       layer_ID_src = layers[k];
  527.       /* Scale the layer and insert int new image */
  528.       if (scale_layer (layer_ID_src, 0, 0, width, height,
  529.                layer_ID_dst, picture_x0, picture_y0,
  530.                picture_width, picture_height) < 0)
  531.         {
  532.           printf ("film: error during scale_layer\n");
  533.           return -1;
  534.         }
  535.  
  536.       /* Draw picture numbers */
  537.       if ((number_height > 0) &&
  538.           (filmvals.number_pos[0] || filmvals.number_pos[1]))
  539.         {
  540.           gimp_palette_set_foreground (filmvals.number_color[0],
  541.                        filmvals.number_color[1],
  542.                        filmvals.number_color[2]);
  543.  
  544.           if (filmvals.number_pos[0])
  545.         draw_number (layer_ID_dst, filmvals.number_start + picture_count,
  546.                  picture_x0 + picture_width/2,
  547.                  (hole_offset-number_height)/2, number_height);
  548.           if (filmvals.number_pos[1])
  549.         draw_number (layer_ID_dst, filmvals.number_start + picture_count,
  550.                  picture_x0 + picture_width/2,
  551.                  film_height - (hole_offset + number_height)/2,
  552.                  number_height);
  553.  
  554.           gimp_palette_set_foreground (f_red, f_green, f_blue);
  555.         }
  556.  
  557.       picture_x0 += picture_width + (picture_space/2);
  558.  
  559.       if (run_mode != GIMP_RUN_NONINTERACTIVE)
  560.         gimp_progress_update (((gdouble) (picture_count + 1)) /
  561.                   (gdouble) num_pictures);
  562.  
  563.       picture_count++;
  564.     }
  565.     }
  566.  
  567.   if (layers)
  568.     g_free (layers);
  569.  
  570.   /* Drawing text/numbers leaves us with a floating selection. Stop it */
  571.   gimp_floating_sel_anchor (gimp_image_floating_selection (image_ID_dst));
  572.  
  573.   /* Restore foreground */
  574.   gimp_palette_set_foreground (f_red, f_green, f_blue);
  575.  
  576.   return image_ID_dst;
  577. }
  578.  
  579.  
  580. /* Check filmvals. Unreasonable values are reset to a default. */
  581. /* If this is not possible, -1 is returned. Otherwise 0 is returned. */
  582. static gint
  583. check_filmvals (void)
  584. {
  585.   if (filmvals.film_height < 10)
  586.     filmvals.film_height = 10;
  587.  
  588.   if (filmvals.number_start < 0)
  589.     filmvals.number_start = 0;
  590.  
  591.   if (filmvals.number_fontf[0] == '\0')
  592.     strcpy (filmvals.number_fontf, "courier");
  593.  
  594.   if (filmvals.num_images < 1)
  595.     return -1;
  596.  
  597.   return 0;
  598. }
  599.  
  600.  
  601. /* Converts numpix pixels from src to RGB at dst */
  602. static void
  603. convert_to_rgb (GimpDrawable *srcdrawable,
  604.         gint       numpix,
  605.         guchar    *src,
  606.         guchar    *dst)
  607.  
  608. {
  609.  register guchar *from = src, *to = dst;
  610.  register gint k;
  611.  register guchar *cmap, *colour;
  612.  gint ncols;
  613.  
  614.  switch (gimp_drawable_type (srcdrawable->id))
  615.    {
  616.    case GIMP_RGB_IMAGE:
  617.      memcpy ((char *)dst, (char *)src, numpix*3);
  618.      break;
  619.  
  620.    case GIMP_RGBA_IMAGE:
  621.      from = src;
  622.      to = dst;
  623.      k = numpix;
  624.      while (k-- > 0)
  625.        {
  626.      *(to++) = *(from++); *(to++) = *(from++); *(to++) = *(from++);
  627.      from++;
  628.        }
  629.      break;
  630.  
  631.    case GIMP_GRAY_IMAGE:
  632.      from = src;
  633.      to = dst;
  634.      k = numpix;
  635.      while (k-- > 0)
  636.        {
  637.      to[0] = to[1] = to[2] = *(from++);
  638.      to += 3;
  639.        }
  640.      break;
  641.  
  642.    case GIMP_GRAYA_IMAGE:
  643.      from = src;
  644.      to = dst;
  645.      k = numpix;
  646.      while (k-- > 0)
  647.        {
  648.      to[0] = to[1] = to[2] = *from;
  649.      from += 2;
  650.      to += 3;
  651.        }
  652.      break;
  653.  
  654.    case GIMP_INDEXED_IMAGE:
  655.    case GIMP_INDEXEDA_IMAGE:
  656.      cmap = gimp_image_get_cmap (gimp_drawable_image_id (srcdrawable->id),
  657.                                  &ncols);
  658.      if (cmap)
  659.        {
  660.      from = src;
  661.      to = dst;
  662.      k = numpix;
  663.      while (k-- > 0)
  664.        {
  665.          colour = cmap + 3*(int)(*from);
  666.          *(to++) = *(colour++);
  667.          *(to++) = *(colour++);
  668.          *(to++) = *(colour++);
  669.          from += srcdrawable->bpp;
  670.        }
  671.        }
  672.      break;
  673.  
  674.    default:
  675.      printf ("convert_to_rgb: unknown image type\n");
  676.      break;
  677.  }
  678. }
  679.  
  680.  
  681. /* Assigns numpix pixels starting at dst with color r,g,b */
  682. static void
  683. set_pixels (gint    numpix,
  684.             guchar *dst,
  685.             guchar *rgb)
  686. {
  687.   register gint k;
  688.   register guchar ur, ug, ub, *udest;
  689.  
  690.   if ((rgb[0] == rgb[1]) && (rgb[1] == rgb[2]))
  691.     {
  692.       memset (dst, (int)rgb[0], numpix*3);
  693.       return;
  694.     }
  695.  
  696.   ur = rgb[0];
  697.   ug = rgb[1];
  698.   ub = rgb[2];
  699.   k = numpix;
  700.   udest = dst;
  701.   while (k-- > 0)
  702.     {
  703.       *(udest++) = ur;
  704.       *(udest++) = ug;
  705.       *(udest++) = ub;
  706.     }
  707. }
  708.  
  709.  
  710. /* Scales a portion of a layer and places it in another layer. */
  711. /* On success, 0 is returned. Otherwise -1 is returned */
  712. static gint
  713. scale_layer (gint32  src_layer,
  714.          gint    src_x0,
  715.          gint    src_y0,
  716.          gint    src_width,
  717.          gint    src_height,
  718.          gint32  dst_layer,
  719.          gint    dst_x0,
  720.          gint    dst_y0,
  721.          gint    dst_width,
  722.          gint    dst_height)
  723. {
  724.   gint tile_height, i, scan_lines, numpix;
  725.   guchar *src, *tmp = (guchar *) ident; /* Just to satisfy gcc */
  726.   gint32 tmp_image, tmp_layer;
  727.   GimpDrawable *tmp_drawable, *src_drawable, *dst_drawable;
  728.   GimpPixelRgn tmp_pixel_rgn, src_pixel_rgn, dst_pixel_rgn;
  729.  
  730.   tile_height = gimp_tile_height ();
  731.  
  732.   src_drawable = gimp_drawable_get (src_layer);
  733.  
  734.   /*** Get a RGB copy of the source region ***/
  735.  
  736.   tmp_image = create_new_image (_("Temporary"), src_width, src_height,
  737.                 GIMP_RGB_IMAGE,
  738.                 &tmp_layer, &tmp_drawable, &tmp_pixel_rgn);
  739.  
  740.   src = g_new (guchar, src_width * tile_height * src_drawable->bpp);
  741.   tmp = g_new (guchar, src_width * tile_height * tmp_drawable->bpp);
  742.  
  743.   gimp_pixel_rgn_init (&src_pixel_rgn, src_drawable, src_x0, src_y0,
  744.                src_width, src_height, FALSE, FALSE);
  745.  
  746.   i = 0;
  747.   while (i < src_height)
  748.     {
  749.       scan_lines = (i+tile_height-1 < src_height) ? tile_height : (src_height-i);
  750.       numpix = scan_lines*src_width;
  751.  
  752.       /* Get part of source image */
  753.       gimp_pixel_rgn_get_rect (&src_pixel_rgn, src, src_x0, src_y0+i,
  754.                    src_width, scan_lines);
  755.  
  756.       convert_to_rgb (src_drawable, numpix, src, tmp);
  757.  
  758.       /* Set part of temporary image */
  759.       gimp_pixel_rgn_set_rect (&tmp_pixel_rgn, tmp, 0, i, src_width, scan_lines);
  760.  
  761.       i += scan_lines;
  762.     }
  763.  
  764.   /* Now we have an image that is a copy of the */
  765.   /* source region and has been converted to RGB. */
  766.   /* We dont need any more access to the source image. */
  767.   gimp_drawable_detach (src_drawable);
  768.   g_free (src);
  769.  
  770.   /*** Resize the temporary image if necessary ***/
  771.   if ((src_width != dst_width) || (src_height != dst_height))
  772.     {
  773.       gimp_drawable_detach (tmp_drawable);
  774.  
  775.       gimp_layer_scale (tmp_layer, dst_width, dst_height, 0);
  776.  
  777.       tmp_drawable = gimp_drawable_get (tmp_layer);
  778.     }
  779.  
  780.   /*** Copy temporary image to destination image */
  781.   gimp_pixel_rgn_init (&tmp_pixel_rgn, tmp_drawable, 0, 0,
  782.                dst_width, dst_height, FALSE, FALSE);
  783.   g_free (tmp);
  784.  
  785.   tmp = g_new (guchar, dst_width * tile_height * tmp_drawable->bpp);
  786.  
  787.   dst_drawable = gimp_drawable_get (dst_layer);
  788.   gimp_pixel_rgn_init (&dst_pixel_rgn, dst_drawable, dst_x0, dst_y0,
  789.                dst_width, dst_height, TRUE, FALSE);
  790.   i = 0;
  791.   while (i < dst_height)
  792.     {
  793.       scan_lines = (i+tile_height-1 < dst_height) ? tile_height : (dst_height-i);
  794.  
  795.       /* Get strip of temporary image */
  796.       gimp_pixel_rgn_get_rect (&tmp_pixel_rgn, tmp, 0, i,
  797.                    dst_width, scan_lines);
  798.  
  799.       /* Set strip of destination image */
  800.       gimp_pixel_rgn_set_rect (&dst_pixel_rgn, tmp, dst_x0, dst_y0+i,
  801.                    dst_width, scan_lines);
  802.       i += scan_lines;
  803.     }
  804.  
  805.   /* No more access to the temporary image */
  806.   gimp_drawable_detach (tmp_drawable);
  807.   g_free (tmp);
  808.   gimp_image_delete (tmp_image);
  809.  
  810.   gimp_drawable_detach (dst_drawable);
  811.  
  812.   return 0;
  813. }
  814.  
  815.  
  816. /* Create the RGB-pixels that make up the hole */
  817. static guchar *
  818. create_hole_rgb (gint width,
  819.          gint height)
  820. {
  821.   guchar *hole, *top, *bottom;
  822.   gint radius, length, k;
  823.  
  824.   hole = g_new (guchar, width * height * 3);
  825.  
  826.   /* Fill a rectangle with white */
  827.   memset (hole, 255, width * height * 3);
  828.   radius = height / 4;
  829.   if (radius > width / 2)
  830.     radius = width / 2;
  831.   top = hole;
  832.   bottom = hole + (height-1)*width*3;
  833.   for (k = radius-1; k > 0; k--)  /* Rounding corners */
  834.     {
  835.       length = (int)(radius - sqrt ((gdouble) (radius * radius - k * k)) - 0.5);
  836.       if (length > 0)
  837.     {
  838.       set_pixels (length, top, filmvals.film_color);
  839.       set_pixels (length, top+(width-length)*3, filmvals.film_color);
  840.       set_pixels (length, bottom, filmvals.film_color);
  841.       set_pixels (length, bottom+(width-length)*3, filmvals.film_color);
  842.     }
  843.       top += width*3;
  844.       bottom -= width*3;
  845.     }
  846.  
  847.   return hole;
  848. }
  849.  
  850.  
  851. /* Draw the hole at the specified position */
  852. static void
  853. draw_hole_rgb (GimpDrawable *drw,
  854.                gint       x,
  855.                gint       y,
  856.                gint       width,
  857.                gint       height,
  858.                guchar    *hole)
  859. {
  860.   GimpPixelRgn rgn;
  861.   guchar *data;
  862.   gint tile_height = gimp_tile_height ();
  863.   gint i, j, scan_lines, d_width = gimp_drawable_width (drw->id);
  864.   gint length;
  865.  
  866.   if ((width <= 0) || (height <= 0))
  867.     return;
  868.   if ((x+width <= 0) || (x >= d_width))
  869.     return;
  870.   length = width;   /* Check that we dont draw past the image */
  871.   if ((x+length) >= d_width)
  872.     length = d_width-x;
  873.  
  874.   data = g_new (guchar, length * tile_height * drw->bpp);
  875.  
  876.   gimp_pixel_rgn_init (&rgn, drw, x, y, length, height, TRUE, FALSE);
  877.  
  878.   i = 0;
  879.   while (i < height)
  880.     {
  881.       scan_lines = (i+tile_height-1 < height) ? tile_height : (height-i);
  882.       if (length == width)
  883.     {
  884.       memcpy (data, hole + 3*width*i, width*scan_lines*3);
  885.     }
  886.       else  /* We have to do some clipping */
  887.     {
  888.       for (j = 0; j < scan_lines; j++)
  889.         memcpy (data + j*length*3, hole + (i+j)*width*3, length*3);
  890.     }
  891.       gimp_pixel_rgn_set_rect (&rgn, data, x, y+i, length, scan_lines);
  892.  
  893.       i += scan_lines;
  894.     }
  895.  
  896.   g_free (data);
  897. }
  898.  
  899.  
  900. /* Draw the number of the picture onto the film */
  901. static void
  902. draw_number (gint32 layer_ID,
  903.              gint   num,
  904.              gint   x,
  905.              gint   y,
  906.              gint   height)
  907. {
  908.   gchar buf[32];
  909.   GimpDrawable *drw;
  910.   gint k, delta, max_delta;
  911.   gint32 image_ID;
  912.   gint32 text_layer_ID;
  913.   gint   text_width, text_height, text_ascent, descent;
  914.   gchar *family = filmvals.number_fontf;
  915.  
  916.   g_snprintf (buf, sizeof (buf), "%d", num);
  917.  
  918.   drw = gimp_drawable_get (layer_ID);
  919.   image_ID = gimp_drawable_image_id (layer_ID);
  920.  
  921.   max_delta = height / 10;
  922.   if (max_delta < 1)
  923.     max_delta = 1;
  924.  
  925.   /* Numbers dont need the descent. Inquire it and move the text down */
  926.   for (k = 0; k < max_delta*2 + 1; k++)
  927.     { /* Try different font sizes if inquire of extent failed */
  928.       delta = (k+1) / 2;
  929.       if ((k & 1) == 0) delta = -delta;
  930.       
  931.       gimp_text_get_extents (buf,
  932.                  height+delta,
  933.                  GIMP_PIXELS,
  934.                  "*",       /* foundry */
  935.                  family,    /* family */
  936.                  "*",       /* weight */
  937.                  "*",       /* slant */
  938.                  "*",       /* set_width */
  939.                  "*",       /* spacing */
  940.                  "*",
  941.                  "*",
  942.                  &text_width,
  943.                  &text_height,
  944.                  &text_ascent,
  945.                  &descent);
  946.  
  947.       if (text_width)   /*  FIXME:  use return_value of gimp_text_get_extens  */
  948.     {
  949.       height += delta;
  950.       break;
  951.     }
  952.     }
  953.  
  954.   text_layer_ID = gimp_text (image_ID,
  955.                  layer_ID,
  956.                  x,
  957.                  y+descent/2,
  958.                  buf,
  959.                  1,           /* border */
  960.                  FALSE,       /* antialias */
  961.                  height,
  962.                  GIMP_PIXELS, 
  963.                  "*",         /* foundry */
  964.                  family,      /* family */
  965.                  "*",         /* weight */
  966.                  "*",         /* slant */
  967.                  "*",         /* set_width */
  968.                  "*",         /* spacing */
  969.                  "*",
  970.                  "*");
  971.  
  972.   if (text_layer_ID == -1)
  973.     g_message ("draw_number: Error in drawing text\n");
  974.  
  975.   gimp_drawable_detach (drw);
  976. }
  977.  
  978.  
  979. /* Create an image. Sets layer_ID, drawable and rgn. Returns image_ID */
  980. static gint32
  981. create_new_image (gchar          *filename,
  982.                   guint           width,
  983.                   guint           height,
  984.                   GimpImageType   gdtype,
  985.                   gint32         *layer_ID,
  986.                   GimpDrawable     **drawable,
  987.                   GimpPixelRgn       *pixel_rgn)
  988. {
  989.   gint32 image_ID;
  990.   GimpImageBaseType gitype;
  991.  
  992.   if ((gdtype == GIMP_GRAY_IMAGE) || (gdtype == GIMP_GRAYA_IMAGE))
  993.     gitype = GIMP_GRAY;
  994.   else if ((gdtype == GIMP_INDEXED_IMAGE) || (gdtype == GIMP_INDEXEDA_IMAGE))
  995.     gitype = GIMP_INDEXED;
  996.   else
  997.     gitype = GIMP_RGB;
  998.  
  999.   image_ID = gimp_image_new (width, height, gitype);
  1000.   gimp_image_set_filename (image_ID, filename);
  1001.  
  1002.   *layer_ID = gimp_layer_new (image_ID, _("Background"), width, height,
  1003.                   gdtype, 100, GIMP_NORMAL_MODE);
  1004.   gimp_image_add_layer (image_ID, *layer_ID, 0);
  1005.  
  1006.   if (drawable != NULL)
  1007.     {
  1008.       *drawable = gimp_drawable_get (*layer_ID);
  1009.       if (pixel_rgn != NULL)
  1010.     gimp_pixel_rgn_init (pixel_rgn, *drawable, 0, 0, (*drawable)->width,
  1011.                  (*drawable)->height, TRUE, FALSE);
  1012.     }
  1013.  
  1014.   return image_ID;
  1015. }
  1016.  
  1017.  
  1018. static gchar *
  1019. compose_image_name (gint32 image_ID)
  1020. {
  1021.   static gchar buffer[256];
  1022.   gchar *filename, *basename;
  1023.  
  1024.   filename = gimp_image_get_filename (image_ID);
  1025.   if (filename == NULL)
  1026.     return "";
  1027.  
  1028.   /* Compose a name of the basename and the image-ID */
  1029.   basename = strrchr (filename, '/');
  1030.   if (basename == NULL)
  1031.     basename = filename;
  1032.   else
  1033.     basename++;
  1034.  
  1035.   g_snprintf (buffer, sizeof (buffer), "%s-%ld", basename, (long)image_ID);
  1036.  
  1037.   g_free (filename);
  1038.  
  1039.   return buffer;
  1040. }
  1041.  
  1042.  
  1043. static void
  1044. add_list_item_callback (GtkWidget *widget,
  1045.                         GtkWidget *list)
  1046. {
  1047.   GList     *tmp_list;
  1048.   GtkWidget *label;
  1049.   GtkWidget *list_item;
  1050.   gint32     image_ID;
  1051.  
  1052.   tmp_list = GTK_LIST (list)->selection;
  1053.  
  1054.   while (tmp_list)
  1055.     {
  1056.       if ((label = (GtkWidget *) tmp_list->data) != NULL)
  1057.     {
  1058.       image_ID = (gint32)gtk_object_get_user_data (GTK_OBJECT (label));
  1059.       list_item =
  1060.         gtk_list_item_new_with_label (compose_image_name (image_ID));
  1061.  
  1062.       gtk_object_set_user_data (GTK_OBJECT (list_item), (gpointer)image_ID);
  1063.       gtk_container_add (GTK_CONTAINER (filmint.image_list_film), list_item);
  1064.       gtk_widget_show (list_item);
  1065.     }
  1066.       tmp_list = tmp_list->next;
  1067.     }
  1068. }
  1069.  
  1070.  
  1071. static void
  1072. del_list_item_callback (GtkWidget *widget,
  1073.                         GtkWidget *list)
  1074. {
  1075.   GList *tmp_list;
  1076.   GList *clear_list;
  1077.  
  1078.   tmp_list = GTK_LIST (list)->selection;
  1079.   clear_list = NULL;
  1080.  
  1081.   while (tmp_list)
  1082.     {
  1083.       clear_list = g_list_prepend (clear_list, tmp_list->data);
  1084.       tmp_list = tmp_list->next;
  1085.     }
  1086.  
  1087.   clear_list = g_list_reverse (clear_list);
  1088.  
  1089.   gtk_list_remove_items (GTK_LIST (list), clear_list);
  1090.  
  1091.   g_list_free (clear_list);
  1092. }
  1093.  
  1094.  
  1095. static GtkWidget *
  1096. add_image_list (gint       add_box_flag,
  1097.                 gint       n,
  1098.                 gint32    *image_id,
  1099.                 GtkWidget *hbox)
  1100.  
  1101. {
  1102.   GtkWidget *vbox;
  1103.   GtkWidget *label;
  1104.   GtkWidget *scrolled_win;
  1105.   GtkWidget *list;
  1106.   GtkWidget *list_item;
  1107.   GtkWidget *button;
  1108.   gint       i;
  1109.  
  1110.   vbox = gtk_vbox_new (FALSE, 4);
  1111.   gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
  1112.   gtk_widget_show (vbox);
  1113.  
  1114.   label = gtk_label_new (add_box_flag ? _("Available Images:")
  1115.                                       : _("On Film:"));
  1116.   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
  1117.   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
  1118.   gtk_widget_show (label);
  1119.  
  1120.   scrolled_win = gtk_scrolled_window_new (NULL, NULL);
  1121.   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
  1122.                                   GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
  1123.   gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
  1124.   gtk_widget_show (scrolled_win);
  1125.  
  1126.   list = gtk_list_new ();
  1127.   gtk_list_set_selection_mode (GTK_LIST (list), GTK_SELECTION_BROWSE);
  1128.   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win),
  1129.                      list);
  1130.   gtk_widget_show (list);
  1131.  
  1132.   for (i = 0; i < n; i++)
  1133.     {
  1134.       list_item =
  1135.     gtk_list_item_new_with_label (compose_image_name (image_id[i]));
  1136.  
  1137.       gtk_object_set_user_data (GTK_OBJECT (list_item), (gpointer) image_id[i]);
  1138.       gtk_container_add (GTK_CONTAINER (list), list_item);
  1139.       gtk_widget_show (list_item);
  1140.     }
  1141.  
  1142.   button = gtk_button_new_with_label (add_box_flag ? _("Add >>"):_("Remove"));
  1143.   GTK_WIDGET_UNSET_FLAGS (button, GTK_CAN_FOCUS);
  1144.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  1145.                       add_box_flag ? (GtkSignalFunc) add_list_item_callback
  1146.                                    : (GtkSignalFunc) del_list_item_callback,
  1147.                       list);
  1148.   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
  1149.   gtk_widget_show (button);
  1150.  
  1151.   return list;
  1152. }
  1153.  
  1154.  
  1155. static gint
  1156. film_dialog (gint32 image_ID)
  1157.  
  1158. {
  1159.   GtkWidget *dlg;
  1160.   GtkWidget *main_vbox;
  1161.   GtkWidget *hbox;
  1162.   GtkWidget *table;
  1163.   GtkWidget *frame;
  1164.   GtkWidget *toggle;
  1165.   GtkWidget *vbox;
  1166.   GtkWidget *vbox2;
  1167.   GtkWidget *spinbutton;
  1168.   GtkObject *adj;
  1169.   GtkWidget *button;
  1170.   GtkWidget *entry;
  1171.   GtkWidget *sep;
  1172.   gint32 *image_id_list;
  1173.   gint    nimages, j, row;
  1174.  
  1175.   gimp_ui_init ("film", TRUE);
  1176.  
  1177.   dlg = gimp_dialog_new (_("Film"), "film",
  1178.              gimp_standard_help_func, "filters/film.html",
  1179.              GTK_WIN_POS_NONE,
  1180.              FALSE, TRUE, FALSE,
  1181.  
  1182.              _("OK"), film_ok_callback,
  1183.              NULL, NULL, NULL, TRUE, FALSE,
  1184.              _("Cancel"), gtk_widget_destroy,
  1185.              NULL, 1, NULL, FALSE, TRUE,
  1186.  
  1187.              NULL);
  1188.  
  1189.   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
  1190.                       GTK_SIGNAL_FUNC (gtk_main_quit),
  1191.                       NULL);
  1192.  
  1193.   main_vbox = gtk_vbox_new (FALSE, 4);
  1194.   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 6);
  1195.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), main_vbox,
  1196.               TRUE, TRUE, 0);
  1197.   gtk_widget_show (main_vbox);
  1198.  
  1199.   hbox = gtk_hbox_new (FALSE, 6);
  1200.   gtk_box_pack_start (GTK_BOX (main_vbox), hbox, TRUE, TRUE, 0);
  1201.   gtk_widget_show (hbox);
  1202.  
  1203.   /*** The frames on the left keep film options ***/
  1204.  
  1205.   vbox2 = gtk_vbox_new (FALSE, 4);
  1206.   gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, 0);
  1207.   gtk_widget_show (vbox2);
  1208.  
  1209.   /* Film height/colour */
  1210.   frame = gtk_frame_new (_("Film"));
  1211.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
  1212.   gtk_box_pack_start (GTK_BOX (vbox2), frame, FALSE, FALSE, 0);
  1213.  
  1214.   vbox = gtk_vbox_new (FALSE, 4);
  1215.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
  1216.   gtk_container_add (GTK_CONTAINER (frame), vbox);
  1217.  
  1218.   /* Keep maximum image height */
  1219.   toggle = gtk_check_button_new_with_label (_("Fit Height to Images"));
  1220.   gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
  1221.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  1222.                       GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  1223.                       &filmvals.keep_height);
  1224.   gtk_widget_show (toggle);
  1225.  
  1226.   table = gtk_table_new (2, 2, FALSE);
  1227.   gtk_table_set_row_spacings (GTK_TABLE (table), 4);
  1228.   gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  1229.   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
  1230.   gtk_widget_show (table);
  1231.  
  1232.   /* Film height */
  1233.   spinbutton = gimp_spin_button_new (&adj, filmvals.film_height, 10,
  1234.                      GIMP_MAX_IMAGE_SIZE, 1, 10, 0, 1, 0);
  1235.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  1236.               GTK_SIGNAL_FUNC (gimp_int_adjustment_update),
  1237.               &filmvals.film_height);
  1238.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
  1239.                  _("Height:"), 1.0, 0.5,
  1240.                  spinbutton, 1, TRUE);
  1241.  
  1242.   gtk_object_set_data (GTK_OBJECT (toggle), "inverse_sensitive", spinbutton);
  1243.   gtk_object_set_data
  1244.     (GTK_OBJECT (spinbutton), "inverse_sensitive",
  1245.      /* FIXME: eeeeeek */
  1246.      g_list_nth_data (gtk_container_children (GTK_CONTAINER (table)), 1));
  1247.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
  1248.                 filmvals.keep_height);
  1249.  
  1250.   /* Film color */
  1251.   button = gimp_color_button_new (_("Select Film Color"),
  1252.                   COLOR_BUTTON_WIDTH, COLOR_BUTTON_HEIGHT,
  1253.                   filmvals.film_color, 3);
  1254.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
  1255.                  _("Color:"), 1.0, 0.5,
  1256.                  button, 1, TRUE);
  1257.  
  1258.   gtk_widget_show (vbox);
  1259.   gtk_widget_show (frame);
  1260.  
  1261.   /* Film numbering: Startindex/Font/colour */
  1262.   frame = gtk_frame_new (_("Numbering"));
  1263.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
  1264.   gtk_box_pack_start (GTK_BOX (vbox2), frame, TRUE, TRUE, 0);
  1265.  
  1266.   vbox = gtk_vbox_new (FALSE, 4);
  1267.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
  1268.   gtk_container_add (GTK_CONTAINER (frame), vbox);
  1269.  
  1270.   table = gtk_table_new (3, 2, FALSE);
  1271.   gtk_table_set_row_spacings (GTK_TABLE (table), 4);
  1272.   gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  1273.   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
  1274.   gtk_widget_show (table);
  1275.  
  1276.   /* Startindex */
  1277.   spinbutton = gimp_spin_button_new (&adj, filmvals.number_start, 0,
  1278.                      G_MAXINT, 1, 10, 0, 1, 0);
  1279.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  1280.               GTK_SIGNAL_FUNC (gimp_int_adjustment_update),
  1281.               &filmvals.number_start);
  1282.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
  1283.                  _("Start Index:"), 1.0, 0.5,
  1284.                  spinbutton, 1, TRUE);
  1285.  
  1286.   /* Fontfamily for numbering */
  1287.   filmint.font_entry = entry = gtk_entry_new ();
  1288.   gtk_widget_set_usize (entry, 60, 0);
  1289.   gtk_entry_set_text (GTK_ENTRY (entry), filmvals.number_fontf);
  1290.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
  1291.                  _("Font:"), 1.0, 0.5,
  1292.                  entry, 1, FALSE);
  1293.  
  1294.   /* Numbering color */
  1295.   button = gimp_color_button_new (_("Select Number Color"),
  1296.                   COLOR_BUTTON_WIDTH, COLOR_BUTTON_HEIGHT,
  1297.                   filmvals.number_color, 3);
  1298.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 2,
  1299.                  _("Color:"), 1.0, 0.5,
  1300.                  button, 1, TRUE);
  1301.  
  1302.   for (j = 0; j < 2; j++)
  1303.     {
  1304.       toggle =
  1305.     gtk_check_button_new_with_label (j ? _("At Bottom") : _("At Top"));
  1306.       gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
  1307.       gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  1308.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  1309.               &(filmvals.number_pos[j]));
  1310.       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
  1311.                     filmvals.number_pos[j]);
  1312.       gtk_widget_show (toggle);
  1313.     }
  1314.  
  1315.   gtk_widget_show (vbox);
  1316.   gtk_widget_show (frame);
  1317.   gtk_widget_show (vbox2);
  1318.  
  1319.   /*** The right frame keeps the image selection ***/
  1320.   frame = gtk_frame_new (_("Image Selection"));
  1321.   gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
  1322.  
  1323.   hbox = gtk_hbox_new (TRUE, 6);
  1324.   gtk_container_set_border_width (GTK_CONTAINER (hbox), 4);
  1325.   gtk_container_add (GTK_CONTAINER (frame), hbox);
  1326.  
  1327.   /* Get a list of all image names */
  1328.   image_id_list = gimp_image_list (&nimages);
  1329.   filmint.image_list_all = add_image_list (1, nimages, image_id_list, hbox);
  1330.  
  1331.   /* Get a list of the images used for the film */
  1332.   filmint.image_list_film = add_image_list (0, 1, &image_ID, hbox);
  1333.  
  1334.   gtk_widget_show (frame);
  1335.   gtk_widget_show (hbox);
  1336.  
  1337.   frame = gtk_frame_new (_("Advanced Settings (All Values are Fractions "
  1338.                "of the Film Height)"));
  1339.   gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0);
  1340.   gtk_widget_show (frame);
  1341.  
  1342.   table = gtk_table_new (11, 3, FALSE);
  1343.   gtk_table_set_row_spacings (GTK_TABLE (table), 2);
  1344.   gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  1345.   gtk_container_set_border_width (GTK_CONTAINER (table), 4);
  1346.   gtk_container_add (GTK_CONTAINER (frame), table);
  1347.   gtk_widget_show (table);
  1348.  
  1349.   row = 0;
  1350.  
  1351.   filmint.advanced_adj[0] = adj =
  1352.     gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
  1353.               _("Image Height:"), 1.0, 0.5,
  1354.               filmvals.picture_height,
  1355.               0.0, 1.0, 0.001, 0.01, 3,
  1356.               TRUE, 0, 0,
  1357.               NULL, NULL);
  1358.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  1359.               GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  1360.               &filmvals.picture_height);
  1361.  
  1362.   gtk_spin_button_configure (GIMP_SCALE_ENTRY_SPINBUTTON (adj),
  1363.                  GIMP_SCALE_ENTRY_SPINBUTTON_ADJ (adj), 0.01, 3);
  1364.  
  1365.   filmint.advanced_adj[1] = adj =
  1366.     gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
  1367.               _("Image Spacing:"), 1.0, 0.5,
  1368.               filmvals.picture_space,
  1369.               0.0, 1.0, 0.001, 0.01, 3,
  1370.               TRUE, 0, 0,
  1371.               NULL, NULL);
  1372.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  1373.               GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  1374.               &filmvals.picture_space);
  1375.  
  1376.   gtk_spin_button_configure (GIMP_SCALE_ENTRY_SPINBUTTON (adj),
  1377.                  GIMP_SCALE_ENTRY_SPINBUTTON_ADJ (adj), 0.01, 3);
  1378.  
  1379.   sep = gtk_hseparator_new ();
  1380.   gtk_table_attach (GTK_TABLE (table), sep, 0, 3, row, row + 1,
  1381.             GTK_FILL, 0, 0, 2);
  1382.   gtk_widget_show (sep);
  1383.  
  1384.   row++;
  1385.  
  1386.   filmint.advanced_adj[2] = adj =
  1387.     gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
  1388.               _("Hole Offset:"), 1.0, 0.5,
  1389.               filmvals.hole_offset,
  1390.               0.0, 1.0, 0.001, 0.01, 3,
  1391.               TRUE, 0, 0,
  1392.               NULL, NULL);
  1393.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  1394.               GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  1395.               &filmvals.hole_offset);
  1396.  
  1397.   gtk_spin_button_configure (GIMP_SCALE_ENTRY_SPINBUTTON (adj),
  1398.                  GIMP_SCALE_ENTRY_SPINBUTTON_ADJ (adj), 0.01, 3);
  1399.  
  1400.   filmint.advanced_adj[3] = adj =
  1401.     gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
  1402.               _("Hole Width:"), 1.0, 0.5,
  1403.               filmvals.hole_width,
  1404.               0.0, 1.0, 0.001, 0.01, 3,
  1405.               TRUE, 0, 0,
  1406.               NULL, NULL);
  1407.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  1408.               GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  1409.               &filmvals.hole_width);
  1410.  
  1411.   gtk_spin_button_configure (GIMP_SCALE_ENTRY_SPINBUTTON (adj),
  1412.                  GIMP_SCALE_ENTRY_SPINBUTTON_ADJ (adj), 0.01, 3);
  1413.  
  1414.   filmint.advanced_adj[4] = adj =
  1415.     gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
  1416.               _("Hole Height:"), 1.0, 0.5,
  1417.               filmvals.hole_height,
  1418.               0.0, 1.0, 0.001, 0.01, 3,
  1419.               TRUE, 0, 0,
  1420.               NULL, NULL);
  1421.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  1422.               GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  1423.               &filmvals.hole_height);
  1424.  
  1425.   gtk_spin_button_configure (GIMP_SCALE_ENTRY_SPINBUTTON (adj),
  1426.                  GIMP_SCALE_ENTRY_SPINBUTTON_ADJ (adj), 0.01, 3);
  1427.  
  1428.   filmint.advanced_adj[5] = adj =
  1429.     gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
  1430.               _("Hole Spacing:"), 1.0, 0.5,
  1431.               filmvals.hole_space,
  1432.               0.0, 1.0, 0.001, 0.01, 3,
  1433.               TRUE, 0, 0,
  1434.               NULL, NULL);
  1435.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  1436.               GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  1437.               &filmvals.hole_space);
  1438.  
  1439.   gtk_spin_button_configure (GIMP_SCALE_ENTRY_SPINBUTTON (adj),
  1440.                  GIMP_SCALE_ENTRY_SPINBUTTON_ADJ (adj), 0.01, 3);
  1441.  
  1442.   sep = gtk_hseparator_new ();
  1443.   gtk_table_attach (GTK_TABLE (table), sep, 0, 3, row, row + 1,
  1444.             GTK_FILL, 0, 0, 2);
  1445.   gtk_widget_show (sep);
  1446.  
  1447.   row++;
  1448.  
  1449.   filmint.advanced_adj[6] = adj =
  1450.     gimp_scale_entry_new (GTK_TABLE (table), 0, row++,
  1451.               _("Number Height:"), 1.0, 0.5,
  1452.               filmvals.number_height,
  1453.               0.0, 1.0, 0.001, 0.01, 3,
  1454.               TRUE, 0, 0,
  1455.               NULL, NULL);
  1456.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  1457.               GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  1458.               &filmvals.number_height);
  1459.  
  1460.   gtk_spin_button_configure (GIMP_SCALE_ENTRY_SPINBUTTON (adj),
  1461.                  GIMP_SCALE_ENTRY_SPINBUTTON_ADJ (adj), 0.01, 3);
  1462.  
  1463.   sep = gtk_hseparator_new ();
  1464.   gtk_table_attach (GTK_TABLE (table), sep, 0, 3, row, row + 1,
  1465.             GTK_FILL, 0, 0, 2);
  1466.   gtk_widget_show (sep);
  1467.  
  1468.   row++;
  1469.  
  1470.   hbox = gtk_hbox_new (FALSE, 0);
  1471.   gtk_table_attach_defaults (GTK_TABLE (table), hbox, 0, 3, row, row + 1);
  1472.   gtk_widget_show (hbox);
  1473.  
  1474.   row++;
  1475.  
  1476.   button = gtk_button_new_with_label (_("Reset to Defaults"));
  1477.   gtk_misc_set_padding (GTK_MISC (GTK_BIN (button)->child), 4, 0);
  1478.   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
  1479.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  1480.               GTK_SIGNAL_FUNC (film_reset_callback),
  1481.               NULL);
  1482.   gtk_widget_show (button);
  1483.  
  1484.   gtk_widget_show (dlg);
  1485.  
  1486.   gtk_main ();
  1487.   gdk_flush ();
  1488.  
  1489.   return filmint.run;
  1490. }
  1491.  
  1492.  
  1493. static void
  1494. film_ok_callback (GtkWidget *widget,
  1495.                   gpointer   data)
  1496. {
  1497.   gint       num_images;
  1498.   gchar     *s;
  1499.   GtkWidget *label;
  1500.   GList     *tmp_list;
  1501.   gint32     image_ID;
  1502.  
  1503.   /* Read font family */
  1504.   s = gtk_entry_get_text (GTK_ENTRY (filmint.font_entry));
  1505.   if (strlen (s) > 0)
  1506.     {
  1507.       strncpy (filmvals.number_fontf, s, sizeof (filmvals.number_fontf));
  1508.       filmvals.number_fontf[sizeof (filmvals.number_fontf)-1] = '\0';
  1509.     }
  1510.  
  1511.   /* Read image list */
  1512.   num_images = 0;
  1513.   if (filmint.image_list_film != NULL)
  1514.     {
  1515.       
  1516.       for (tmp_list = GTK_LIST (filmint.image_list_film)->children;
  1517.        tmp_list;
  1518.        tmp_list = g_list_next (tmp_list))
  1519.     {
  1520.       if ((label = (GtkWidget *) tmp_list->data) != NULL)
  1521.         {
  1522.           image_ID = (gint32) gtk_object_get_user_data (GTK_OBJECT (label));
  1523.           if ((image_ID >= 0) && (num_images < MAX_FILM_PICTURES))
  1524.         filmvals.image[num_images++] = image_ID;
  1525.         }
  1526.     }
  1527.       filmvals.num_images = num_images;
  1528.     }
  1529.  
  1530.   filmint.run = TRUE;
  1531.  
  1532.   gtk_widget_destroy (GTK_WIDGET (data));
  1533. }
  1534.  
  1535. static void
  1536. film_reset_callback (GtkWidget *widget,
  1537.              gpointer   data)
  1538. {
  1539.   gint i, num;
  1540.  
  1541.   num = sizeof (advanced_defaults) / sizeof (advanced_defaults[0]);
  1542.  
  1543.   for (i = 0; i < num; i++)
  1544.     gtk_adjustment_set_value (GTK_ADJUSTMENT (filmint.advanced_adj[i]),
  1545.                   advanced_defaults[i]);
  1546. }
  1547.