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 / tileit.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-08-28  |  32.0 KB  |  1,252 lines

  1. /*
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This is a plug-in for the GIMP.
  5.  *
  6.  * Tileit - This plugin will take an image an make repeated
  7.  * copies of it the stepping is 1/(2**n); 1<=n<=6
  8.  *
  9.  * Copyright (C) 1997 Andy Thomas  alt@picnic.demon.co.uk
  10.  *
  11.  * This program is free software; you can redistribute it and/or modify
  12.  * it under the terms of the GNU General Public License as published by
  13.  * the Free Software Foundation; either version 2 of the License, or
  14.  * (at your option) any later version.
  15.  *
  16.  * This program is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  * GNU General Public License for more details.
  20.  *
  21.  * You should have received a copy of the GNU General Public License
  22.  * along with this program; if not, write to the Free Software
  23.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  24.  * 
  25.  * A fair proprotion of this code was taken from the Whirl plug-in
  26.  * which was copyrighted by Federico Mena Quintero (as below).
  27.  * 
  28.  * Whirl plug-in --- distort an image into a whirlpool
  29.  * Copyright (C) 1997 Federico Mena Quintero           
  30.  *
  31.  */
  32.  
  33. /* Change log:-
  34.  * 0.2  Added new functions to allow "editing" of the tile patten.
  35.  *
  36.  * 0.1 First version released.
  37.  */
  38.  
  39. #include "config.h"
  40.  
  41. #include <stdio.h>
  42. #include <stdlib.h>
  43. #include <signal.h>
  44. #include <string.h>
  45.  
  46. #include <gtk/gtk.h>
  47.  
  48. #include <libgimp/gimp.h>
  49. #include <libgimp/gimpui.h>
  50.  
  51. #include "libgimp/stdplugins-intl.h"
  52.  
  53.  
  54. /***** Magic numbers *****/
  55.  
  56. #define PREVIEW_SIZE 128 
  57. #define SCALE_WIDTH   80
  58. #define ENTRY_WIDTH   50
  59.  
  60. #define MAX_SEGS       6
  61.  
  62. #define PREVIEW_MASK   GDK_EXPOSURE_MASK | \
  63.                        GDK_BUTTON_PRESS_MASK | \
  64.                GDK_BUTTON_MOTION_MASK
  65.  
  66. /* Variables set in dialog box */
  67. typedef struct data
  68. {
  69.   gint numtiles;
  70. } TileItVals;
  71.  
  72. typedef struct
  73. {
  74.   GtkWidget *preview;
  75.   guchar     preview_row[PREVIEW_SIZE * 4];
  76.   gint       img_bpp;
  77.   guchar    *pv_cache;
  78.  
  79.   gint       run;
  80. } TileItInterface;
  81.  
  82. static TileItInterface tint =
  83. {
  84.   NULL,  /* Preview */
  85.   {
  86.     '4',
  87.     'u'
  88.   },     /* Preview_row */
  89.   4,     /* bpp of drawable */
  90.   NULL,
  91.   FALSE, /* run */
  92. };
  93.  
  94. static GimpDrawable *tileitdrawable;
  95. static gint       tile_width, tile_height;
  96. static GimpTile     *the_tile = NULL;
  97. static gint       img_width, img_height,img_bpp;
  98.  
  99. static void      query  (void);
  100. static void      run    (gchar    *name,
  101.              gint      nparams,
  102.              GimpParam   *param,
  103.              gint     *nreturn_vals,
  104.              GimpParam  **return_vals);
  105. /* static void      check  (GimpDrawable * drawable); */
  106.  
  107. static gint      tileit_dialog          (void);
  108.  
  109. static void      tileit_ok_callback     (GtkWidget     *widget,
  110.                      gpointer       data);
  111.  
  112. static void      tileit_scale_update    (GtkAdjustment *adjustment,
  113.                      gpointer       data);
  114.  
  115. static void      tileit_exp_update      (GtkWidget *widget, gpointer value);
  116. static void      tileit_exp_update_f    (GtkWidget *widget, gpointer value);
  117.  
  118. static void      tileit_reset           (GtkWidget *widget,
  119.                      gpointer   value);
  120. static void      tileit_radio_update    (GtkWidget *widget,
  121.                      gpointer   data);
  122. static void      tileit_hvtoggle_update (GtkWidget *widget,
  123.                      gpointer   data);
  124.  
  125. static void      do_tiles  (void);
  126. static gint      tiles_xy  (gint width, gint height,gint x,gint y,gint *nx,gint *ny);
  127. static void      all_update     (void);
  128. static void      alt_update     (void);
  129. static void      explict_update (gint);
  130.  
  131. static void      dialog_update_preview (void);
  132. static void     cache_preview         (void);
  133. static gint      tileit_preview_expose (GtkWidget *widget,
  134.                     GdkEvent  *event);
  135. static gint      tileit_preview_events (GtkWidget *widget,
  136.                     GdkEvent  *event);
  137.  
  138.  
  139. GimpPlugInInfo PLUG_IN_INFO =
  140. {
  141.   NULL,  /* init_proc  */
  142.   NULL,  /* quit_proc  */
  143.   query, /* query_proc */
  144.   run,   /* run_proc   */
  145. };
  146.  
  147. /* Values when first invoked */
  148. static TileItVals itvals =
  149. {
  150.   2
  151. };
  152.  
  153. /* Structures for call backs... */
  154. /* The "explict tile" & family */
  155. typedef enum
  156. {
  157.   ALL,
  158.   ALT,
  159.   EXPLICT
  160. } AppliedTo;
  161.  
  162. typedef struct
  163. {
  164.   AppliedTo  type;
  165.  
  166.   gint       x;        /* X - pos of tile   */
  167.   gint       y;        /* Y - pos of tile   */
  168.   GtkObject *r_adj;    /* row adjustment    */
  169.   GtkObject *c_adj;    /* column adjustment */
  170.   GtkWidget *applybut; /* The apply button  */
  171. } Exp_Call;
  172.  
  173. Exp_Call exp_call =
  174. {
  175.   ALL,
  176.   -1,
  177.   -1,
  178.   NULL,
  179.   NULL,
  180.   NULL,
  181. };
  182.  
  183. /* The reset button needs to know some toggle widgets.. */
  184.  
  185. typedef struct
  186. {
  187.   GtkWidget *htoggle;
  188.   GtkWidget *vtoggle;
  189. } Reset_Call;
  190.  
  191. Reset_Call res_call =
  192. {
  193.   NULL,
  194.   NULL,
  195. };
  196.   
  197. /* 2D - Array that holds the actions for each tile */
  198. /* Action type on cell */
  199. #define HORIZONTAL 0x1
  200. #define VERTICAL   0x2
  201.  
  202. gint tileactions[MAX_SEGS][MAX_SEGS];
  203.  
  204. /* What actions buttons toggled */
  205. static gint   do_horz = FALSE;
  206. static gint   do_vert = FALSE;
  207. static gint   opacity = 100;
  208.  
  209. /* Stuff for the preview bit */
  210. static gint   sel_x1, sel_y1, sel_x2, sel_y2;
  211. static gint   sel_width, sel_height;
  212. static gint   preview_width, preview_height;
  213. static gint   has_alpha;
  214.  
  215. MAIN ()
  216.  
  217. static void
  218. query (void)
  219. {
  220.   static GimpParamDef args[] =
  221.   {
  222.     { GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
  223.     { GIMP_PDB_IMAGE, "image", "Input image (unused)" },
  224.     { GIMP_PDB_DRAWABLE, "drawable", "Input drawable" },
  225.     { GIMP_PDB_INT32, "number_of_tiles", "Number of tiles to make" } 
  226.   };
  227.   static gint nargs = sizeof (args) / sizeof (args[0]);
  228.  
  229.   gimp_install_procedure ("plug_in_small_tiles",
  230.               "Tiles image into smaller versions of the orginal",
  231.               "More here later",
  232.               "Andy Thomas",
  233.               "Andy Thomas",
  234.               "1997",
  235.               N_("<Image>/Filters/Map/Small Tiles..."),
  236.               "RGB*, GRAY*",
  237.               GIMP_PLUGIN,
  238.               nargs, 0,
  239.               args, NULL);
  240. }
  241.  
  242. static void
  243. run (gchar    *name,
  244.      gint      nparams,
  245.      GimpParam   *param,
  246.      gint     *nreturn_vals,
  247.      GimpParam  **return_vals)
  248. {
  249.   static GimpParam values[1];
  250.   GimpDrawable *drawable;
  251.   GimpRunModeType run_mode;
  252.   GimpPDBStatusType status = GIMP_PDB_SUCCESS;
  253.  
  254.   gint pwidth, pheight;
  255.  
  256.   run_mode = param[0].data.d_int32;
  257.  
  258.   *nreturn_vals = 1;
  259.   *return_vals = values;
  260.  
  261.   values[0].type = GIMP_PDB_STATUS;
  262.   values[0].data.d_status = status;
  263.  
  264.   tileitdrawable = 
  265.     drawable = 
  266.     gimp_drawable_get (param[2].data.d_drawable);
  267.  
  268.   tile_width  = gimp_tile_width ();
  269.   tile_height = gimp_tile_height ();
  270.  
  271.   gimp_drawable_mask_bounds (drawable->id, &sel_x1, &sel_y1, &sel_x2, &sel_y2);
  272.  
  273.   sel_width  = sel_x2 - sel_x1;
  274.   sel_height = sel_y2 - sel_y1;
  275.   
  276.   /* Calculate preview size */
  277.   
  278.   if (sel_width > sel_height)
  279.     {
  280.       pwidth  = MIN (sel_width, PREVIEW_SIZE);
  281.       pheight = sel_height * pwidth / sel_width;
  282.     }
  283.   else
  284.     {
  285.       pheight = MIN (sel_height, PREVIEW_SIZE);
  286.       pwidth  = sel_width * pheight / sel_height;
  287.     }
  288.   
  289.   preview_width  = MAX (pwidth, 2);  /* Min size is 2 */
  290.   preview_height = MAX (pheight, 2); 
  291.  
  292.   switch (run_mode)
  293.     {
  294.     case GIMP_RUN_INTERACTIVE:
  295.       INIT_I18N_UI();
  296.       gimp_get_data ("plug_in_tileit", &itvals);
  297.       if (! tileit_dialog ())
  298.     {
  299.       gimp_drawable_detach (drawable);
  300.       return;
  301.     }
  302.       break;
  303.  
  304.     case GIMP_RUN_NONINTERACTIVE:
  305.       if (nparams != 4)
  306.     {
  307.       status = GIMP_PDB_CALLING_ERROR;
  308.     }
  309.       else
  310.     {
  311.       itvals.numtiles = param[3].data.d_int32;
  312.     }
  313.       INIT_I18N();
  314.       break;
  315.  
  316.     case GIMP_RUN_WITH_LAST_VALS:
  317.       INIT_I18N();
  318.       gimp_get_data ("plug_in_tileit", &itvals);
  319.       break;
  320.  
  321.     default:
  322.       break;
  323.     }
  324.  
  325.   if (gimp_drawable_is_rgb (drawable->id) ||
  326.       gimp_drawable_is_gray (drawable->id))
  327.     {
  328.       /* Set the tile cache size */
  329.  
  330.       gimp_tile_cache_ntiles ((drawable->width + gimp_tile_width () - 1) /
  331.                   gimp_tile_width ());
  332.  
  333.       gimp_progress_init (_("Tiling..."));
  334.  
  335.       do_tiles ();
  336.    
  337.       if (run_mode != GIMP_RUN_NONINTERACTIVE)
  338.     gimp_displays_flush ();
  339.  
  340.       if (run_mode == GIMP_RUN_INTERACTIVE)
  341.     gimp_set_data ("plug_in_tileit", &itvals, sizeof (TileItVals));
  342.     }
  343.   else
  344.     {
  345.       status = GIMP_PDB_EXECUTION_ERROR;
  346.     }
  347.  
  348.   values[0].data.d_status = status;
  349.  
  350.   gimp_drawable_detach (drawable);
  351. }
  352.  
  353. /* Build the dialog up. This was the hard part! */
  354. static gint
  355. tileit_dialog (void)
  356. {
  357.   GtkWidget *dlg;
  358.   GtkWidget *main_vbox;
  359.   GtkWidget *hbox;
  360.   GtkWidget *vbox;
  361.   GtkWidget *vbox2;
  362.   GtkWidget *frame;
  363.   GtkWidget *xframe;
  364.   GtkWidget *table;
  365.   GtkWidget *sep;
  366.   GtkWidget *table2;
  367.   GtkWidget *button;
  368.   GtkWidget *label;
  369.   GtkWidget *spinbutton;
  370.   GtkObject *adj;
  371.   GtkObject *size_data;
  372.   GtkObject *op_data;
  373.   GtkWidget *toggle;
  374.   GSList  *orientation_group = NULL;
  375.  
  376.   gimp_ui_init ("tileit", TRUE);
  377.  
  378.   cache_preview (); /* Get the preview image and store it also set has_alpha */
  379.  
  380.   /* Start buildng the dialog up */
  381.   dlg = gimp_dialog_new ( _("TileIt"), "tileit",
  382.              gimp_standard_help_func, "filters/tileit.html",
  383.              GTK_WIN_POS_MOUSE,
  384.              FALSE, TRUE, FALSE,
  385.  
  386.              _("OK"), tileit_ok_callback,
  387.              NULL, NULL, NULL, TRUE, FALSE,
  388.              _("Cancel"), gtk_widget_destroy,
  389.              NULL, 1, NULL, FALSE, TRUE,
  390.  
  391.              NULL);
  392.  
  393.   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
  394.               GTK_SIGNAL_FUNC (gtk_main_quit),
  395.               NULL);
  396.  
  397.   main_vbox = gtk_vbox_new (FALSE, 4);
  398.   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 6);
  399.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), main_vbox,
  400.               TRUE, TRUE, 0);
  401.   gtk_widget_show (main_vbox);
  402.  
  403.   hbox = gtk_hbox_new (FALSE, 6);
  404.   gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
  405.   gtk_widget_show (hbox);
  406.  
  407.   frame = gtk_frame_new ( _("Preview"));
  408.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
  409.   gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, FALSE, 0);
  410.   gtk_widget_show (frame);
  411.  
  412.   vbox2 = gtk_vbox_new (TRUE, 0);
  413.   gtk_container_set_border_width (GTK_CONTAINER (vbox2), 4);
  414.   gtk_container_add (GTK_CONTAINER (frame), vbox2);
  415.   gtk_widget_show (vbox2);
  416.  
  417.   xframe = gtk_frame_new (NULL);
  418.   gtk_frame_set_shadow_type (GTK_FRAME (xframe), GTK_SHADOW_IN);
  419.   gtk_box_pack_start (GTK_BOX (vbox2), xframe, TRUE, FALSE, 0);
  420.   gtk_widget_show (xframe);
  421.  
  422.   tint.preview = gtk_preview_new (GTK_PREVIEW_COLOR);
  423.   gtk_preview_size (GTK_PREVIEW (tint.preview), preview_width, preview_height);
  424.  
  425.   gtk_widget_set_events (GTK_WIDGET (tint.preview), PREVIEW_MASK);
  426.   gtk_signal_connect_after (GTK_OBJECT (tint.preview), "expose_event",
  427.                 GTK_SIGNAL_FUNC (tileit_preview_expose),
  428.                 NULL);
  429.   gtk_signal_connect (GTK_OBJECT (tint.preview), "event",
  430.               GTK_SIGNAL_FUNC (tileit_preview_events),
  431.               NULL);
  432.  
  433.   gtk_container_add (GTK_CONTAINER (xframe), tint.preview);
  434.  
  435.   /* Area for buttons etc */
  436.  
  437.   frame = gtk_frame_new (_("Flipping"));
  438.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
  439.   gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
  440.   gtk_widget_show (frame);
  441.  
  442.   vbox = gtk_vbox_new (FALSE, 4);
  443.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
  444.   gtk_container_add (GTK_CONTAINER (frame), vbox);
  445.   gtk_widget_show (vbox);
  446.  
  447.   hbox = gtk_hbox_new (TRUE, 4);
  448.   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
  449.   gtk_widget_show (hbox);
  450.  
  451.   toggle = gtk_check_button_new_with_label (_("Horizontal"));
  452.   gtk_box_pack_start (GTK_BOX (hbox), toggle, TRUE, TRUE, 0);
  453.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  454.               GTK_SIGNAL_FUNC (tileit_hvtoggle_update),
  455.               &do_horz);
  456.   gtk_widget_show (toggle);
  457.   res_call.htoggle = toggle;
  458.  
  459.   toggle = gtk_check_button_new_with_label (_("Vertical"));
  460.   gtk_box_pack_start (GTK_BOX (hbox), toggle, TRUE, TRUE, 0);
  461.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  462.               GTK_SIGNAL_FUNC (tileit_hvtoggle_update),
  463.               &do_vert);
  464.   gtk_widget_show (toggle);
  465.   res_call.vtoggle = toggle;
  466.  
  467.   button = gtk_button_new_with_label (_("Reset"));
  468.   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
  469.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  470.               GTK_SIGNAL_FUNC (tileit_reset),
  471.               &res_call);
  472.   gtk_widget_show (button);
  473.  
  474.   xframe = gtk_frame_new (_("Applied to Tile"));
  475.   gtk_frame_set_shadow_type (GTK_FRAME (xframe), GTK_SHADOW_ETCHED_IN);
  476.   gtk_box_pack_start (GTK_BOX (vbox), xframe, FALSE, FALSE, 0);
  477.   gtk_widget_show (xframe);
  478.  
  479.   /* Table for the inner widgets..*/
  480.   table = gtk_table_new (6, 4, FALSE);
  481.   gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  482.   gtk_table_set_row_spacings (GTK_TABLE (table), 2);
  483.   gtk_container_set_border_width (GTK_CONTAINER (table), 4);
  484.   gtk_container_add (GTK_CONTAINER (xframe), table);
  485.   gtk_widget_show (table);
  486.  
  487.   toggle = gtk_radio_button_new_with_label (orientation_group, _("All Tiles"));
  488.   orientation_group = gtk_radio_button_group (GTK_RADIO_BUTTON (toggle));
  489.   gtk_table_attach (GTK_TABLE (table), toggle, 0, 4, 0, 1,
  490.             GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
  491.   gtk_object_set_user_data (GTK_OBJECT (toggle), (gpointer) ALL);
  492.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  493.               GTK_SIGNAL_FUNC (tileit_radio_update),
  494.               &exp_call.type);
  495.   gtk_widget_show (toggle);
  496.  
  497.   toggle = gtk_radio_button_new_with_label (orientation_group,
  498.                         _("Alternate Tiles"));
  499.   orientation_group = gtk_radio_button_group (GTK_RADIO_BUTTON (toggle));
  500.   gtk_table_attach (GTK_TABLE (table), toggle, 0, 4, 1, 2,
  501.             GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
  502.   gtk_object_set_user_data (GTK_OBJECT (toggle), (gpointer) ALT);
  503.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  504.               GTK_SIGNAL_FUNC (tileit_radio_update),
  505.               &exp_call.type);
  506.   gtk_widget_show (toggle);
  507.  
  508.   toggle = gtk_radio_button_new_with_label (orientation_group,
  509.                                             _("Explicit Tile"));
  510.   orientation_group = gtk_radio_button_group (GTK_RADIO_BUTTON (toggle));  
  511.   gtk_table_attach (GTK_TABLE (table), toggle, 0, 1, 2, 4,
  512.             GTK_FILL | GTK_SHRINK, GTK_FILL, 0, 0);
  513.   gtk_widget_show (toggle);
  514.  
  515.   label = gtk_label_new (_("Row:"));
  516.   gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
  517.   gtk_table_attach (GTK_TABLE (table), label, 1, 2, 2, 3,
  518.             GTK_FILL | GTK_SHRINK , GTK_FILL, 0, 0);
  519.   gtk_widget_show (label); 
  520.  
  521.   gtk_widget_set_sensitive (label, FALSE);
  522.   gtk_object_set_data (GTK_OBJECT (toggle), "set_sensitive", label);
  523.  
  524.   spinbutton = gimp_spin_button_new (&adj, 2, 1, 6, 1, 1, 0, 1, 0);
  525.   gtk_widget_set_usize (spinbutton, ENTRY_WIDTH, -1);
  526.   gtk_table_attach (GTK_TABLE (table), spinbutton, 2, 3, 2, 3,
  527.             GTK_FILL | GTK_SHRINK, GTK_FILL, 0, 0);
  528.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  529.               GTK_SIGNAL_FUNC (tileit_exp_update_f),
  530.               &exp_call);
  531.   gtk_widget_show (spinbutton);
  532.   exp_call.r_adj = adj;
  533.  
  534.   gtk_widget_set_sensitive (spinbutton, FALSE);
  535.   gtk_object_set_data (GTK_OBJECT (label), "set_sensitive", spinbutton);
  536.  
  537.   label = gtk_label_new ( _("Column:"));
  538.   gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
  539.   gtk_widget_show (label); 
  540.   gtk_table_attach (GTK_TABLE (table), label, 1, 2, 3, 4,
  541.             GTK_FILL , GTK_FILL, 0, 0);
  542.  
  543.   gtk_widget_set_sensitive (label, FALSE);
  544.   gtk_object_set_data (GTK_OBJECT (spinbutton), "set_sensitive", label);
  545.  
  546.   spinbutton = gimp_spin_button_new (&adj, 2, 1, 6, 1, 1, 0, 1, 0);
  547.   gtk_widget_set_usize (spinbutton, ENTRY_WIDTH, -1);
  548.   gtk_table_attach (GTK_TABLE (table), spinbutton, 2, 3, 3, 4,
  549.             GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
  550.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  551.               GTK_SIGNAL_FUNC (tileit_exp_update_f),
  552.               &exp_call);
  553.   gtk_widget_show (spinbutton);
  554.   exp_call.c_adj = adj;
  555.  
  556.   gtk_widget_set_sensitive (spinbutton, FALSE);
  557.   gtk_object_set_data (GTK_OBJECT (label), "set_sensitive", spinbutton);
  558.  
  559.   gtk_object_set_user_data (GTK_OBJECT (toggle), (gpointer) EXPLICT);
  560.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  561.               GTK_SIGNAL_FUNC (tileit_radio_update),
  562.               &exp_call.type);
  563.  
  564.   button = gtk_button_new_with_label (_("Apply"));
  565.   gtk_table_attach (GTK_TABLE (table), button, 3, 4, 2, 4, 0, 0, 0, 0);
  566.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  567.               GTK_SIGNAL_FUNC (tileit_exp_update),
  568.               &exp_call);
  569.   gtk_widget_show (button);
  570.   exp_call.applybut = button;
  571.  
  572.   gtk_widget_set_sensitive (button, FALSE);
  573.   gtk_object_set_data (GTK_OBJECT (spinbutton), "set_sensitive", button);
  574.  
  575.   /* Widget for selecting the Opacity */
  576.   sep = gtk_hseparator_new ();
  577.   gtk_table_attach (GTK_TABLE (table), sep, 0, 4, 4, 5,
  578.             GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 1);
  579.   gtk_widget_show (sep);
  580.  
  581.   table2 = gtk_table_new (1, 3, FALSE);
  582.   gtk_table_set_col_spacings (GTK_TABLE (table2), 4);
  583.   gtk_table_attach_defaults (GTK_TABLE (table), table2, 0, 4, 5, 6);
  584.   gtk_widget_show (table2);
  585.  
  586.   op_data = gimp_scale_entry_new (GTK_TABLE (table2), 0, 0,
  587.                   _("Opacity:"), SCALE_WIDTH, ENTRY_WIDTH,
  588.                   opacity, 0, 100, 1, 10, 0,
  589.                   TRUE, 0, 0,
  590.                   NULL, NULL);
  591.   gtk_signal_connect (GTK_OBJECT (op_data), "value_changed",
  592.               GTK_SIGNAL_FUNC (tileit_scale_update),
  593.               &opacity);
  594.  
  595.   gtk_widget_show (frame); 
  596.  
  597.   /* Lower frame saying howmany segments */
  598.   frame = gtk_frame_new (_("Segment Setting"));
  599.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
  600.   gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0);
  601.   gtk_widget_show (frame);
  602.  
  603.   table = gtk_table_new (1, 3, FALSE);
  604.   gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  605.   gtk_container_set_border_width (GTK_CONTAINER (table), 4);
  606.   gtk_container_add (GTK_CONTAINER (frame), table);
  607.   gtk_widget_show (table);
  608.  
  609.   gtk_widget_set_sensitive (table2, has_alpha);
  610.  
  611.   size_data = gimp_scale_entry_new (GTK_TABLE (table), 0, 0,
  612.                     "1 / (2 ** n)", SCALE_WIDTH, ENTRY_WIDTH,
  613.                     itvals.numtiles, 2, MAX_SEGS, 1, 1, 0,
  614.                     TRUE, 0, 0,
  615.                     NULL, NULL);
  616.   gtk_signal_connect (GTK_OBJECT (size_data), "value_changed",
  617.               GTK_SIGNAL_FUNC (tileit_scale_update),
  618.               &itvals.numtiles);
  619.  
  620.   gtk_widget_show (tint.preview);
  621.  
  622.   gtk_widget_show (dlg);
  623.   dialog_update_preview ();
  624.  
  625.   gtk_main ();
  626.   gdk_flush ();
  627.  
  628.   return tint.run;
  629. }
  630.  
  631. static void
  632. tileit_ok_callback (GtkWidget *widget,
  633.               gpointer   data)
  634. {
  635.   tint.run = TRUE;
  636.  
  637.   gtk_widget_destroy (GTK_WIDGET (data));
  638. }
  639.  
  640. static void
  641. tileit_hvtoggle_update (GtkWidget *widget,
  642.             gpointer   data)
  643. {
  644.   gimp_toggle_button_update (widget, data);
  645.  
  646.   switch (exp_call.type)
  647.     {
  648.     case ALL:
  649.       /* Clear current settings */
  650.       memset (tileactions, 0, sizeof (tileactions));
  651.       all_update ();
  652.       break;
  653.  
  654.     case ALT:
  655.       /* Clear current settings */
  656.       memset (tileactions, 0, sizeof (tileactions));
  657.       alt_update ();
  658.       break;
  659.  
  660.     case EXPLICT:
  661.       break;
  662.     }
  663.  
  664.   dialog_update_preview ();
  665. }
  666.  
  667. static void 
  668. draw_explict_sel (void)
  669. {
  670.   if (exp_call.type == EXPLICT)
  671.     {
  672.       gdouble x,y;
  673.       gdouble width  = (gdouble) preview_width / (gdouble) itvals.numtiles;
  674.       gdouble height = (gdouble) preview_height / (gdouble) itvals.numtiles;
  675.  
  676.       x = width * (exp_call.x - 1);
  677.       y = height * (exp_call.y - 1);
  678.  
  679.       gdk_gc_set_function (tint.preview->style->black_gc, GDK_INVERT);
  680.  
  681.       gdk_draw_rectangle (tint.preview->window,
  682.               tint.preview->style->black_gc,
  683.               0,
  684.               (gint) x,
  685.               (gint) y,
  686.               (gint) width,
  687.               (gint) height);
  688.       gdk_draw_rectangle (tint.preview->window,
  689.               tint.preview->style->black_gc,
  690.               0,
  691.               (gint) x + 1,
  692.               (gint) y + 1,
  693.               (gint) width - 2,
  694.               (gint) height - 2);
  695.       gdk_draw_rectangle (tint.preview->window,
  696.               tint.preview->style->black_gc,
  697.               0,
  698.               (gint) x + 2,
  699.               (gint) y + 2,
  700.               (gint) width - 4,
  701.               (gint) height - 4);
  702.  
  703.       gdk_gc_set_function (tint.preview->style->black_gc, GDK_COPY);
  704.     }
  705. }
  706.  
  707. static gint
  708. tileit_preview_expose (GtkWidget *widget,
  709.                GdkEvent  *event)
  710. {
  711.   draw_explict_sel ();
  712.  
  713.   return FALSE;
  714. }
  715.  
  716. static void
  717. exp_need_update (gint nx,
  718.          gint ny)
  719. {
  720.   if (nx <= 0 || nx > itvals.numtiles || ny <= 0 || ny > itvals.numtiles)
  721.     return;
  722.  
  723.   if( nx != exp_call.x ||
  724.       ny != exp_call.y )
  725.     {
  726.       draw_explict_sel (); /* Clear old 'un */
  727.       exp_call.x = nx;
  728.       exp_call.y = ny;
  729.       draw_explict_sel ();
  730.  
  731.       gtk_signal_handler_block_by_data (GTK_OBJECT (exp_call.c_adj), &exp_call);
  732.       gtk_signal_handler_block_by_data (GTK_OBJECT (exp_call.r_adj), &exp_call);
  733.  
  734.       gtk_adjustment_set_value (GTK_ADJUSTMENT (exp_call.c_adj), nx);
  735.       gtk_adjustment_set_value (GTK_ADJUSTMENT (exp_call.r_adj), ny);
  736.  
  737.       gtk_signal_handler_unblock_by_data (GTK_OBJECT (exp_call.c_adj),
  738.                       &exp_call);
  739.       gtk_signal_handler_unblock_by_data (GTK_OBJECT (exp_call.r_adj),
  740.                       &exp_call);
  741.     }
  742. }
  743.  
  744. static gint
  745. tileit_preview_events (GtkWidget *widget,
  746.                GdkEvent  *event)
  747. {
  748.   GdkEventButton *bevent;
  749.   GdkEventMotion *mevent;
  750.   gint nx, ny;
  751.   gint twidth  = preview_width / itvals.numtiles;
  752.   gint theight = preview_height / itvals.numtiles;
  753.  
  754.   switch (event->type)
  755.     {
  756.     case GDK_EXPOSE:
  757.       break;
  758.  
  759.     case GDK_BUTTON_PRESS:
  760.       bevent = (GdkEventButton *) event;
  761.       nx = bevent->x/twidth + 1;
  762.       ny = bevent->y/theight + 1;
  763.       exp_need_update (nx, ny);
  764.       break;
  765.  
  766.     case GDK_MOTION_NOTIFY:
  767.       mevent = (GdkEventMotion *) event;
  768.       if ( !mevent->state ) 
  769.     break;
  770.       if(mevent->x < 0 || mevent->y < 0)
  771.     break;
  772.       nx = mevent->x/twidth + 1;
  773.       ny = mevent->y/theight + 1;
  774.       exp_need_update (nx, ny);
  775.       break;
  776.  
  777.     default:
  778.       break;
  779.     }
  780.  
  781.   return FALSE;
  782. }
  783.  
  784. static void 
  785. explict_update (gint settile)
  786. {
  787.   gint x,y;
  788.  
  789.   /* Make sure bounds are OK */
  790.   y = ROUND (GTK_ADJUSTMENT (exp_call.r_adj)->value);
  791.   if (y > itvals.numtiles || y <= 0)
  792.     {
  793.       y = itvals.numtiles;
  794.     }
  795.   x = ROUND (GTK_ADJUSTMENT (exp_call.c_adj)->value);
  796.   if (x > itvals.numtiles || x <= 0)
  797.     {
  798.       x = itvals.numtiles;
  799.     }
  800.  
  801.   /* Set it */
  802.   if (settile == TRUE)
  803.     tileactions[x-1][y-1] = (((do_horz) ? HORIZONTAL : 0) |
  804.                  ((do_vert) ? VERTICAL : 0));
  805.  
  806.   exp_call.x = x;
  807.   exp_call.y = y;
  808. }
  809.  
  810. static void 
  811. all_update (void)
  812. {
  813.   gint x,y;
  814.  
  815.   for (x = 0 ; x < MAX_SEGS; x++)
  816.     for (y = 0 ; y < MAX_SEGS; y++)
  817.       tileactions[x][y] |= (((do_horz) ? HORIZONTAL : 0) |
  818.                 ((do_vert) ? VERTICAL : 0));
  819. }
  820.  
  821. static void
  822. alt_update (void)
  823. {
  824.   gint x,y;
  825.  
  826.   for (x = 0 ; x < MAX_SEGS; x++)
  827.     for (y = 0 ; y < MAX_SEGS; y++)
  828.       if (!((x + y) % 2))
  829.     tileactions[x][y] |= (((do_horz) ? HORIZONTAL : 0) |
  830.                   ((do_vert) ? VERTICAL : 0));
  831. }
  832.  
  833. static void
  834. tileit_radio_update (GtkWidget *widget,
  835.              gpointer   data)
  836. {
  837.   gimp_radio_button_update (widget, data);
  838.  
  839.   if (GTK_TOGGLE_BUTTON (widget)->active)
  840.     {
  841.       switch (exp_call.type)
  842.     {
  843.     case ALL:
  844.       /* Clear current settings */
  845.       memset (tileactions, 0, sizeof (tileactions));
  846.       all_update ();
  847.       break;
  848.  
  849.     case ALT:
  850.       /* Clear current settings */
  851.       memset (tileactions, 0, sizeof (tileactions));
  852.       alt_update ();
  853.       break;
  854.  
  855.     case EXPLICT:
  856.       explict_update (FALSE);
  857.       break;
  858.     }
  859.  
  860.       dialog_update_preview ();
  861.     }
  862. }             
  863.  
  864.  
  865. static void
  866. tileit_scale_update (GtkAdjustment *adjustment,
  867.              gpointer       data)
  868. {
  869.   gimp_int_adjustment_update (adjustment, data);
  870.  
  871.   dialog_update_preview ();
  872.  
  873. static void
  874. tileit_reset (GtkWidget *widget,
  875.           gpointer   data)
  876. {
  877.   Reset_Call *r = (Reset_Call *) data;
  878.  
  879.   memset (tileactions, 0, sizeof (tileactions));
  880.  
  881.   gtk_signal_handler_block_by_data (GTK_OBJECT (r->htoggle), &do_horz);
  882.   gtk_signal_handler_block_by_data (GTK_OBJECT (r->vtoggle), &do_vert);
  883.  
  884.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (r->htoggle), FALSE);
  885.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (r->vtoggle), FALSE);
  886.  
  887.   gtk_signal_handler_unblock_by_data (GTK_OBJECT (r->htoggle), &do_horz);
  888.   gtk_signal_handler_unblock_by_data (GTK_OBJECT (r->vtoggle), &do_vert);
  889.  
  890.   do_horz = do_vert = FALSE; 
  891.  
  892.   dialog_update_preview ();
  893.  
  894.  
  895. /* Could avoid almost dup. functions by using a field in the data 
  896.  * passed.  Must still pass the data since used in sig blocking func.
  897.  */
  898.  
  899. static void
  900. tileit_exp_update (GtkWidget *widget,
  901.            gpointer   applied)
  902. {
  903.   explict_update (TRUE);
  904.   dialog_update_preview ();
  905. }
  906.  
  907. static void
  908. tileit_exp_update_f (GtkWidget *widget,
  909.              gpointer   applied)
  910. {
  911.   explict_update (FALSE);
  912.   dialog_update_preview ();
  913. }
  914.  
  915. /* Cache the preview image - updates are a lot faster. */
  916. /* The preview_cache will contain the small image */
  917.  
  918. static void
  919. cache_preview (void)
  920. {
  921.   GimpPixelRgn src_rgn;
  922.   gint y,x;
  923.   guchar *src_rows;
  924.   guchar *p;
  925.   gint isgrey = FALSE;
  926.  
  927.   gimp_pixel_rgn_init (&src_rgn, tileitdrawable,
  928.                sel_x1, sel_y1, sel_width, sel_height, FALSE, FALSE);
  929.  
  930.   src_rows = g_new (guchar, sel_width * 4); 
  931.   p = tint.pv_cache = g_new (guchar, preview_width * preview_height * 4);
  932.  
  933.   img_width  = gimp_drawable_width (tileitdrawable->id);
  934.   img_height = gimp_drawable_height (tileitdrawable->id);
  935.  
  936.   tint.img_bpp = gimp_drawable_bpp (tileitdrawable->id);   
  937.  
  938.   has_alpha = gimp_drawable_has_alpha (tileitdrawable->id);
  939.  
  940.   if (tint.img_bpp < 3)
  941.     {
  942.       tint.img_bpp = 3 + has_alpha;
  943.     }
  944.  
  945.   switch (gimp_drawable_type (tileitdrawable->id))
  946.     {
  947.     case GIMP_GRAYA_IMAGE:
  948.     case GIMP_GRAY_IMAGE:
  949.       isgrey = TRUE;
  950.       break;
  951.     default:
  952.       isgrey = FALSE;
  953.       break;
  954.     }
  955.  
  956.   for (y = 0; y < preview_height; y++)
  957.     {
  958.       gimp_pixel_rgn_get_row (&src_rgn,
  959.                   src_rows,
  960.                   sel_x1,
  961.                   sel_y1 + (y * sel_height) / preview_height,
  962.                   sel_width);
  963.  
  964.       for (x = 0; x < (preview_width); x ++)
  965.     {
  966.       /* Get the pixels of each col */
  967.       gint i;
  968.       for (i = 0 ; i < 3; i++)
  969.         p[x * tint.img_bpp + i] =
  970.           src_rows[((x * sel_width) / preview_width) * src_rgn.bpp +
  971.               ((isgrey) ? 0 : i)]; 
  972.       if (has_alpha)
  973.         p[x * tint.img_bpp + 3] =
  974.           src_rows[((x * sel_width) / preview_width) * src_rgn.bpp +
  975.               ((isgrey) ? 1 : 3)];
  976.     }
  977.       p += (preview_width * tint.img_bpp);
  978.     }
  979.   g_free (src_rows);
  980. }
  981.  
  982. static void
  983. tileit_get_pixel (gint    x,
  984.           gint    y,
  985.           guchar *pixel)
  986. {
  987.   static gint row  = -1;
  988.   static gint col  = -1;
  989.   
  990.   gint    newcol, newrow;
  991.   gint    newcoloff, newrowoff;
  992.   guchar *p;
  993.   int     i;
  994.   
  995.   if ((x < 0) || (x >= img_width) || (y < 0) || (y >= img_height)) {
  996.     pixel[0] = 0;
  997.     pixel[1] = 0;
  998.     pixel[2] = 0;
  999.     pixel[3] = 0;
  1000.     
  1001.     return;
  1002.   }
  1003.   
  1004.   newcol    = x / tile_width;
  1005.   newcoloff = x % tile_width;
  1006.   newrow    = y / tile_height;
  1007.   newrowoff = y % tile_height;
  1008.   
  1009.   if ((col != newcol) || (row != newrow) || (the_tile == NULL)) {
  1010.     if (the_tile != NULL)
  1011.       gimp_tile_unref(the_tile, FALSE);
  1012.     
  1013.     the_tile = gimp_drawable_get_tile(tileitdrawable, FALSE, newrow, newcol);
  1014.     gimp_tile_ref(the_tile);
  1015.     
  1016.     col = newcol;
  1017.     row = newrow;
  1018.   } 
  1019.   
  1020.   p = the_tile->data + the_tile->bpp * (the_tile->ewidth * newrowoff + newcoloff);
  1021.   
  1022.   for (i = img_bpp; i; i--)
  1023.     *pixel++ = *p++;
  1024. }
  1025.  
  1026.  
  1027. static void
  1028. do_tiles(void)
  1029. {
  1030.   GimpPixelRgn dest_rgn;
  1031.   gpointer  pr;
  1032.   gint      progress, max_progress;
  1033.   guchar   *dest_row;
  1034.   guchar   *dest;
  1035.   gint      row, col;
  1036.   guchar    pixel[4];
  1037.   int         nc,nr;
  1038.   int       i;
  1039.   
  1040.   /* Initialize pixel region */
  1041.   
  1042.   gimp_pixel_rgn_init(&dest_rgn, tileitdrawable, sel_x1, sel_y1, sel_width, sel_height, TRUE, TRUE);
  1043.   
  1044.   progress     = 0;
  1045.   max_progress = sel_width * sel_height;
  1046.   
  1047.   img_bpp = gimp_drawable_bpp(tileitdrawable->id);
  1048.   
  1049.   for (pr = gimp_pixel_rgns_register(1, &dest_rgn);
  1050.        pr != NULL; pr = gimp_pixel_rgns_process(pr)) {
  1051.     dest_row = dest_rgn.data;
  1052.     
  1053.     for (row = dest_rgn.y; row < (dest_rgn.y + dest_rgn.h); row++) {
  1054.       dest = dest_row;
  1055.       
  1056.       for (col = dest_rgn.x; col < (dest_rgn.x + dest_rgn.w); col++)
  1057.     {
  1058.       int an_action;
  1059.       
  1060.       an_action = 
  1061.         tiles_xy(sel_width,
  1062.              sel_height,
  1063.              col-sel_x1,row-sel_y1,
  1064.              &nc,&nr);
  1065.       tileit_get_pixel(nc+sel_x1,nr+sel_y1,pixel);
  1066.       for (i = 0; i < img_bpp; i++)
  1067.         *dest++ = pixel[i];
  1068.       
  1069.       if(an_action && has_alpha)
  1070.         {
  1071.           dest--;
  1072.           *dest = ((*dest)*opacity)/100;
  1073.           dest++;
  1074.         }
  1075.     }
  1076.       dest_row += dest_rgn.rowstride;
  1077.     } 
  1078.     
  1079.     progress += dest_rgn.w * dest_rgn.h;
  1080.     gimp_progress_update((double) progress / max_progress);
  1081.   }
  1082.   
  1083.   if (the_tile != NULL) {
  1084.     gimp_tile_unref(the_tile, FALSE);
  1085.     the_tile = NULL;
  1086.   }
  1087.   
  1088.   gimp_drawable_flush(tileitdrawable);
  1089.   gimp_drawable_merge_shadow(tileitdrawable->id, TRUE);
  1090.   gimp_drawable_update(tileitdrawable->id, sel_x1, sel_y1, sel_width, sel_height);
  1091.  
  1092.  
  1093. /* Get the xy pos and any action */
  1094. static gint
  1095. tiles_xy(gint width,
  1096.      gint height,
  1097.      gint x,
  1098.      gint y,
  1099.      gint *nx,
  1100.      gint *ny)
  1101. {
  1102.   gint px,py;
  1103.   gint rnum,cnum; 
  1104.   gint actiontype;
  1105.   gdouble rnd = 1 - (1.0/(gdouble)itvals.numtiles) +0.01;
  1106.  
  1107.   rnum = y*itvals.numtiles/height;
  1108.  
  1109.   py = (y*itvals.numtiles)%height;
  1110.   px = (x*itvals.numtiles)%width; 
  1111.   cnum = x*itvals.numtiles/width;
  1112.       
  1113.   if((actiontype = tileactions[cnum][rnum]))
  1114.     {
  1115.       if(actiontype & HORIZONTAL)
  1116.     {
  1117.       gdouble pyr;
  1118.       pyr =  height - y - 1 + rnd;
  1119.       py = ((int)(pyr*(gdouble)itvals.numtiles))%height;
  1120.     }
  1121.       
  1122.       if(actiontype & VERTICAL)
  1123.     {
  1124.       gdouble pxr;
  1125.       pxr = width - x - 1 + rnd;
  1126.       px = ((int)(pxr*(gdouble)itvals.numtiles))%width; 
  1127.     }
  1128.     }
  1129.   
  1130.   *nx = px;
  1131.   *ny = py;
  1132.  
  1133.   return(actiontype);
  1134. }
  1135.  
  1136.  
  1137. /* Given a row then srink it down a bit */
  1138. static void
  1139. do_tiles_preview(guchar *dest_row, 
  1140.         guchar *src_rows,
  1141.         gint width,
  1142.         gint dh,
  1143.         gint height,
  1144.         gint bpp)
  1145. {
  1146.   gint x;
  1147.   gint i;
  1148.   gint px,py;
  1149.   gint rnum,cnum; 
  1150.   gint actiontype;
  1151.   gdouble rnd = 1 - (1.0/(gdouble)itvals.numtiles) +0.01;
  1152.  
  1153.   rnum = dh*itvals.numtiles/height;
  1154.  
  1155.   for (x = 0; x < width; x ++) 
  1156.     {
  1157.       
  1158.       py = (dh*itvals.numtiles)%height;
  1159.       
  1160.       px = (x*itvals.numtiles)%width; 
  1161.       cnum = x*itvals.numtiles/width;
  1162.       
  1163.       if((actiontype = tileactions[cnum][rnum]))
  1164.     {
  1165.       if(actiontype & HORIZONTAL)
  1166.         {
  1167.           gdouble pyr;
  1168.           pyr =  height - dh - 1 + rnd;
  1169.           py = ((int)(pyr*(gdouble)itvals.numtiles))%height;
  1170.         }
  1171.       
  1172.       if(actiontype & VERTICAL)
  1173.         {
  1174.           gdouble pxr;
  1175.           pxr = width - x - 1 + rnd;
  1176.           px = ((int)(pxr*(gdouble)itvals.numtiles))%width; 
  1177.         }
  1178.     }
  1179.  
  1180.       for (i = 0 ; i < bpp; i++ )
  1181.     dest_row[x*tint.img_bpp+i] = 
  1182.       src_rows[(px + (py*width))*bpp+i]; 
  1183.  
  1184.       if(has_alpha && actiontype)
  1185.     dest_row[x*tint.img_bpp + (bpp - 1)] = 
  1186.       (dest_row[x*tint.img_bpp + (bpp - 1)]*opacity)/100;
  1187.  
  1188.     }
  1189. }
  1190.  
  1191. static void
  1192. dialog_update_preview (void)
  1193. {
  1194.   gint y;
  1195.   gint check, check_0, check_1;  
  1196.  
  1197.   for (y = 0; y < preview_height; y++)
  1198.     {
  1199.       if ((y / GIMP_CHECK_SIZE) & 1)
  1200.     {
  1201.       check_0 = GIMP_CHECK_DARK * 255;
  1202.       check_1 = GIMP_CHECK_LIGHT * 255;
  1203.     }
  1204.       else
  1205.     {
  1206.       check_0 = GIMP_CHECK_LIGHT * 255;
  1207.       check_1 = GIMP_CHECK_DARK * 255;
  1208.     }
  1209.  
  1210.       do_tiles_preview (tint.preview_row,
  1211.             tint.pv_cache,
  1212.             preview_width,
  1213.             y,
  1214.             preview_height,
  1215.             tint.img_bpp);
  1216.  
  1217.       if (tint.img_bpp > 3)
  1218.     {
  1219.       gint i, j;
  1220.  
  1221.       for (i = 0, j = 0 ; i < sizeof (tint.preview_row); i += 4, j += 3 )
  1222.         {
  1223.           gint alphaval;
  1224.  
  1225.           if (((i/4) / GIMP_CHECK_SIZE) & 1)
  1226.         check = check_0;
  1227.           else
  1228.         check = check_1;
  1229.  
  1230.           alphaval = tint.preview_row[i + 3];
  1231.  
  1232.           tint.preview_row[j] = 
  1233.         check + (((tint.preview_row[i] - check)*alphaval)/255);
  1234.           tint.preview_row[j + 1] = 
  1235.         check + (((tint.preview_row[i + 1] - check)*alphaval)/255);
  1236.           tint.preview_row[j + 2] = 
  1237.         check + (((tint.preview_row[i + 2] - check)*alphaval)/255);
  1238.         }
  1239.     }
  1240.  
  1241.       gtk_preview_draw_row (GTK_PREVIEW (tint.preview),
  1242.                 tint.preview_row, 0, y, preview_width);
  1243.     }
  1244.  
  1245.   draw_explict_sel ();
  1246.   gtk_widget_draw (tint.preview, NULL);
  1247.   gdk_flush ();
  1248. }
  1249.