home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / plug-ins / gap / gap_mov_exec.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-10  |  51.0 KB  |  1,593 lines

  1. /* gap_mov_exec.c
  2.  * 1997.11.06 hof (Wolfgang Hofer)
  3.  *
  4.  * GAP ... Gimp Animation Plugins
  5.  *
  6.  * Move : procedures for copying source layer(s) to multiple frames
  7.  * (varying Koordinates, opacity, size ...)
  8.  *
  9.  */
  10. /* The GIMP -- an image manipulation program
  11.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  12.  *
  13.  * This program is free software; you can redistribute it and/or modify
  14.  * it under the terms of the GNU General Public License as published by
  15.  * the Free Software Foundation; either version 2 of the License, or
  16.  * (at your option) any later version.
  17.  *
  18.  * This program is distributed in the hope that it will be useful,
  19.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21.  * GNU General Public License for more details.
  22.  *
  23.  * You should have received a copy of the GNU General Public License
  24.  * along with this program; if not, write to the Free Software
  25.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  26.  */
  27.  
  28. /* revision history:
  29.  * gimp    1.1.29b; 2000/11/20  hof: FRAME based Stepmodes, bugfixes for path calculation
  30.  * gimp    1.1.23a; 2000/06/03  hof: bugfix anim_preview < 100% did not work
  31.  *                                   (the layer tattoos in a duplicated image may differ from the original !!)
  32.  * gimp    1.1.20a; 2000/04/25  hof: support for keyframes, anim_preview
  33.  * version 0.93.04              hof: Window with Info Message if no Source Image was selected in MovePath
  34.  * version 0.90.00;             hof: 1.st (pre) release 14.Dec.1997
  35.  */
  36. #include "config.h"
  37.  
  38. /* SYTEM (UNIX) includes */ 
  39. #include <stdio.h>
  40. #include <stdlib.h>
  41. #include <string.h>
  42. #include <sys/types.h>
  43. #include <errno.h>
  44. #ifdef HAVE_UNISTD_H
  45. #include <unistd.h>
  46. #endif
  47.  
  48. /* GIMP includes */
  49. #include "gtk/gtk.h"
  50. #include "config.h"
  51. #include "libgimp/stdplugins-intl.h"
  52. #include "libgimp/gimp.h"
  53.  
  54. /* GAP includes */
  55. #include "gap_layer_copy.h"
  56. #include "gap_lib.h"
  57. #include "gap_mov_dialog.h"
  58. #include "gap_mov_exec.h"
  59. #include "gap_pdb_calls.h"
  60.  
  61. extern      int gap_debug; /* ==0  ... dont print debug infos */
  62.  
  63. static gint p_mov_call_render(t_mov_data *mov_ptr, t_mov_current *cur_ptr, gint apv_layerstack);
  64. static void p_mov_advance_src_layer(t_mov_current *cur_ptr, int src_stepmode);
  65. static void p_mov_advance_src_frame(t_mov_current *cur_ptr, t_mov_values  *pvals);
  66. static long   p_mov_execute(t_mov_data *mov_ptr);
  67. static gdouble  p_calc_angle(gint p1x, gint p1y, gint p2x, gint p2y);
  68. static gdouble  p_rotatate_less_than_180(gdouble angle, gdouble angle_new, gint *turns);
  69.  
  70. /* ============================================================================
  71.  * p_mov_call_render
  72.  *  load current frame, render and save back to disk
  73.  *  for animted_preview
  74.  * ============================================================================
  75.  */
  76.  
  77. gint
  78. p_mov_call_render(t_mov_data *mov_ptr, t_mov_current *cur_ptr, gint apv_layerstack)
  79. {
  80.   t_anim_info *ainfo_ptr;
  81.   gint32  l_tmp_image_id;
  82.   gint32  l_layer_id;
  83.   int     l_rc;
  84.   char    *l_fname;
  85.   char    *l_name;
  86.  
  87.   l_rc = 0;
  88.   ainfo_ptr = mov_ptr->dst_ainfo_ptr;
  89.  
  90.  
  91.   if(mov_ptr->val_ptr->apv_mlayer_image < 0)
  92.   {
  93.     /* We are generating the Animation on the ORIGINAL FRAMES */
  94.     if(ainfo_ptr->new_filename != NULL) g_free(ainfo_ptr->new_filename);
  95.     ainfo_ptr->new_filename = p_alloc_fname(ainfo_ptr->basename,
  96.                                     cur_ptr->dst_frame_nr,
  97.                                     ainfo_ptr->extension);
  98.     if(ainfo_ptr->new_filename == NULL)
  99.        return -1;
  100.  
  101.     /* load next frame to render */
  102.     l_tmp_image_id = p_load_image(ainfo_ptr->new_filename);
  103.     if(l_tmp_image_id < 0)
  104.       return -1;
  105.  
  106.     /* call render procedure for current image */
  107.     if(0 == p_mov_render(l_tmp_image_id, mov_ptr->val_ptr, cur_ptr))
  108.     {
  109.       /* if OK: save the rendered frame back to disk */
  110.       if(p_save_named_frame(l_tmp_image_id, ainfo_ptr->new_filename) < 0)
  111.     l_rc = -1;
  112.     }
  113.     else l_rc = -1;
  114.   }
  115.   else
  116.   {
  117.     /* We are generating an ANIMATED PREVIEW multilayer image */
  118.     if(mov_ptr->val_ptr->apv_src_frame >= 0)
  119.     {
  120.        /* anim preview uses one constant (prescaled) frame */
  121.        l_tmp_image_id = p_gimp_channel_ops_duplicate(mov_ptr->val_ptr->apv_src_frame);
  122.     }
  123.     else
  124.     {
  125.        /* anim preview exact mode uses original frames */
  126.        if(ainfo_ptr->new_filename != NULL) g_free(ainfo_ptr->new_filename);
  127.        ainfo_ptr->new_filename = p_alloc_fname(ainfo_ptr->basename,
  128.                                        cur_ptr->dst_frame_nr,
  129.                                        ainfo_ptr->extension);
  130.        l_tmp_image_id = p_load_image(ainfo_ptr->new_filename);
  131.        if(l_tmp_image_id < 0)
  132.      return -1;
  133.  
  134.        if((mov_ptr->val_ptr->apv_scalex != 100.0) || (mov_ptr->val_ptr->apv_scaley != 100.0))
  135.        {
  136.          GimpParam     *l_params;
  137.          gint        l_retvals;
  138.      gint32      l_size_x, l_size_y;
  139.        
  140.          l_size_x = (gimp_image_width(l_tmp_image_id) * mov_ptr->val_ptr->apv_scalex) / 100;
  141.          l_size_y = (gimp_image_height(l_tmp_image_id) * mov_ptr->val_ptr->apv_scaley) / 100;
  142.        
  143.          l_params = gimp_run_procedure ("gimp_image_scale",
  144.                      &l_retvals,
  145.                      GIMP_PDB_IMAGE,    l_tmp_image_id,
  146.                      GIMP_PDB_INT32,    l_size_x,
  147.                      GIMP_PDB_INT32,    l_size_y,
  148.                      GIMP_PDB_END);
  149.        }
  150.     }
  151.     
  152.     /* call render procedure for current image */
  153.     if(0 == p_mov_render(l_tmp_image_id, mov_ptr->val_ptr, cur_ptr))
  154.     {
  155.       /* if OK and optional save to gap_paste-buffer */
  156.       if(mov_ptr->val_ptr->apv_gap_paste_buff != NULL)
  157.       {
  158.          l_fname = p_alloc_fname(mov_ptr->val_ptr->apv_gap_paste_buff,
  159.                                  cur_ptr->dst_frame_nr,
  160.                                  ".xcf");
  161.          p_save_named_frame(l_tmp_image_id, l_fname);
  162.       }
  163.       
  164.       /* flatten the rendered frame */
  165.       l_layer_id = gimp_image_flatten(l_tmp_image_id);
  166.       if(l_layer_id < 0)
  167.       {
  168.         if(gap_debug) printf("p_mov_call_render: flattened layer_id:%d\n", (int)l_layer_id);
  169.         /* hof:
  170.      * if invisible layers are flattened on an empty image
  171.      * we do not get a resulting layer (returned l_layer_id == -1)
  172.      *
  173.      *  I'm not sure if is this a bug, but here is a workaround:
  174.      *
  175.      * In that case I add a dummy layer 1x1 pixel (at offest -1,-1)
  176.      * and flatten again, and it works (tested with gimp-1.1.19)
  177.      */
  178.         l_layer_id = gimp_layer_new(l_tmp_image_id, "dummy",
  179.                                  1, 
  180.                  1,
  181.                  ((gint)(gimp_image_base_type(l_tmp_image_id)) * 2),
  182.                                  100.0,     /* Opacity full opaque */     
  183.                                  0);        /* NORMAL */
  184.          gimp_image_add_layer(l_tmp_image_id, l_layer_id, 0);
  185.      gimp_layer_set_offsets(l_layer_id, -1, -1);
  186.         l_layer_id = gimp_image_flatten(l_tmp_image_id);
  187.     
  188.       }
  189.       gimp_layer_add_alpha(l_layer_id);
  190.       
  191.       if(gap_debug)
  192.       {
  193.         printf("p_mov_call_render: flattened layer_id:%d\n", (int)l_layer_id);
  194.         printf("p_mov_call_render: tmp_image_id:%d  apv_mlayer_image:%d\n",
  195.             (int)l_tmp_image_id, (int)mov_ptr->val_ptr->apv_mlayer_image);
  196.       }
  197.  
  198.       /* set layername (including delay for the framerate) */
  199.       l_name = g_strdup_printf("frame_%04d (%dms)"
  200.                               , (int) cur_ptr->dst_frame_nr
  201.                               , (int)(1000/mov_ptr->val_ptr->apv_framerate));
  202.       gimp_layer_set_name(l_layer_id, l_name);
  203.       g_free(l_name);
  204.       
  205.       /* remove (its only) layer from source */
  206.       gimp_image_remove_layer(l_tmp_image_id, l_layer_id);
  207.  
  208.       /* and set the dst_image as it's new Master */
  209.       p_gimp_drawable_set_image(l_layer_id, mov_ptr->val_ptr->apv_mlayer_image);
  210.  
  211.       /* add the layer to the anim preview multilayer image */
  212.       gimp_image_add_layer (mov_ptr->val_ptr->apv_mlayer_image, l_layer_id, apv_layerstack);
  213.     }
  214.     else l_rc = -1;
  215.   }
  216.     
  217.  
  218.   /* destroy the tmp image */
  219.   gimp_image_delete(l_tmp_image_id);
  220.  
  221.   return l_rc;
  222. }    /* end p_mov_call_render */
  223.  
  224.  
  225. /* ============================================================================
  226.  * p_mov_advance_src_layer
  227.  * advance layer index according to stepmode
  228.  * ============================================================================
  229.  */
  230. void p_mov_advance_src_layer(t_mov_current *cur_ptr, int src_stepmode)
  231. {
  232.   static int l_ping = -1;
  233.  
  234.   if(gap_debug) printf("p_mov_advance_src_layer: stepmode=%d last_layer=%d idx=%d\n",
  235.                        (int)src_stepmode,
  236.                        (int)cur_ptr->src_last_layer,
  237.                        (int)cur_ptr->src_layer_idx
  238.                       ); 
  239.  
  240.   /* note: top layer has index 0
  241.    *       therfore reverse loops have to count up
  242.    */
  243.   if((cur_ptr->src_last_layer > 0 ) && (src_stepmode != GAP_STEP_NONE))
  244.   {
  245.     switch(src_stepmode)
  246.     {
  247.       case GAP_STEP_ONCE_REV:
  248.         cur_ptr->src_layer_idx++;
  249.         if(cur_ptr->src_layer_idx > cur_ptr->src_last_layer)
  250.         {
  251.            cur_ptr->src_layer_idx = cur_ptr->src_last_layer;
  252.         }
  253.         break;
  254.       case GAP_STEP_ONCE:
  255.         cur_ptr->src_layer_idx--;
  256.         if(cur_ptr->src_layer_idx < 0)
  257.         {
  258.            cur_ptr->src_layer_idx = 0;
  259.         }
  260.         break;
  261.       case GAP_STEP_PING_PONG:
  262.         cur_ptr->src_layer_idx += l_ping;
  263.         if(l_ping < 0)
  264.         {
  265.           if(cur_ptr->src_layer_idx < 0)
  266.           {
  267.              cur_ptr->src_layer_idx = 1;
  268.              l_ping = 1;
  269.           }
  270.         }
  271.         else
  272.         {
  273.           if(cur_ptr->src_layer_idx > cur_ptr->src_last_layer)
  274.           {
  275.              cur_ptr->src_layer_idx = cur_ptr->src_last_layer - 1;
  276.              l_ping = -1;
  277.           }
  278.         }
  279.  
  280.         break;
  281.       case GAP_STEP_LOOP_REV:
  282.         cur_ptr->src_layer_idx++;
  283.         if(cur_ptr->src_layer_idx > cur_ptr->src_last_layer)
  284.         {
  285.            cur_ptr->src_layer_idx = 0;
  286.         }
  287.         break;
  288.       case GAP_STEP_LOOP:
  289.       default:
  290.         cur_ptr->src_layer_idx--;
  291.         if(cur_ptr->src_layer_idx < 0)
  292.         {
  293.            cur_ptr->src_layer_idx = cur_ptr->src_last_layer;
  294.         }
  295.         break;
  296.  
  297.     }
  298.   }
  299. }    /* end  p_advance_src_layer */
  300.  
  301.  
  302.  
  303. /* ============================================================================
  304.  * p_mov_advance_src_frame
  305.  *   advance chached image to next source frame according to FRAME based pvals->stepmode
  306.  * ============================================================================
  307.  */
  308. static void
  309. p_mov_advance_src_frame(t_mov_current *cur_ptr, t_mov_values  *pvals)
  310. {
  311.   static int l_ping = 1;
  312.  
  313.   if(pvals->src_stepmode != GAP_STEP_FRAME_NONE)
  314.   {
  315.     if(pvals->cache_ainfo_ptr == NULL )
  316.     {
  317.       pvals->cache_ainfo_ptr =  p_alloc_ainfo(pvals->src_image_id, GIMP_RUN_NONINTERACTIVE);
  318.     }
  319.  
  320.     if(pvals->cache_ainfo_ptr->first_frame_nr < 0)
  321.     {
  322.        p_dir_ainfo(pvals->cache_ainfo_ptr);
  323.     }
  324.   }
  325.  
  326.   if(gap_debug) printf("p_mov_advance_src_frame: stepmode=%d frame_cnt=%d first_frame=%d last_frame=%d idx=%d\n",
  327.                        (int)pvals->src_stepmode,
  328.                        (int)pvals->cache_ainfo_ptr->frame_cnt,
  329.                        (int)pvals->cache_ainfo_ptr->first_frame_nr,
  330.                        (int)pvals->cache_ainfo_ptr->last_frame_nr,
  331.                        (int)cur_ptr->src_frame_idx
  332.                       ); 
  333.  
  334.   if((pvals->cache_ainfo_ptr->frame_cnt > 1 ) && (pvals->src_stepmode != GAP_STEP_FRAME_NONE))
  335.   {
  336.     switch(pvals->src_stepmode)
  337.     {
  338.       case GAP_STEP_FRAME_ONCE_REV:
  339.         cur_ptr->src_frame_idx--;
  340.         if(cur_ptr->src_frame_idx < pvals->cache_ainfo_ptr->first_frame_nr)
  341.         {
  342.            cur_ptr->src_frame_idx = pvals->cache_ainfo_ptr->first_frame_nr;
  343.         }
  344.         break;
  345.       case GAP_STEP_FRAME_ONCE:
  346.         cur_ptr->src_frame_idx++;
  347.         if(cur_ptr->src_frame_idx > pvals->cache_ainfo_ptr->last_frame_nr)
  348.         {
  349.            cur_ptr->src_frame_idx = pvals->cache_ainfo_ptr->last_frame_nr;
  350.         }
  351.         break;
  352.       case GAP_STEP_FRAME_PING_PONG:
  353.         cur_ptr->src_frame_idx += l_ping;
  354.         if(l_ping < 0)
  355.         {
  356.           if(cur_ptr->src_frame_idx < pvals->cache_ainfo_ptr->first_frame_nr)
  357.           {
  358.              cur_ptr->src_frame_idx = pvals->cache_ainfo_ptr->first_frame_nr + 1;
  359.              l_ping = 1;
  360.           }
  361.         }
  362.         else
  363.         {
  364.           if(cur_ptr->src_frame_idx > pvals->cache_ainfo_ptr->last_frame_nr)
  365.           {
  366.              cur_ptr->src_frame_idx = pvals->cache_ainfo_ptr->last_frame_nr - 1;
  367.              l_ping = -1;
  368.           }
  369.         }
  370.         break;
  371.       case GAP_STEP_FRAME_LOOP_REV:
  372.         cur_ptr->src_frame_idx--;
  373.         if(cur_ptr->src_frame_idx < pvals->cache_ainfo_ptr->first_frame_nr)
  374.         {
  375.            cur_ptr->src_frame_idx = pvals->cache_ainfo_ptr->last_frame_nr;
  376.         }
  377.         break;
  378.       case GAP_STEP_FRAME_LOOP:
  379.       default:
  380.         cur_ptr->src_frame_idx++;
  381.         if(cur_ptr->src_frame_idx > pvals->cache_ainfo_ptr->last_frame_nr)
  382.         {
  383.            cur_ptr->src_frame_idx = pvals->cache_ainfo_ptr->first_frame_nr;
  384.         }
  385.         break;
  386.  
  387.     }
  388.     
  389.     p_fetch_src_frame(pvals, cur_ptr->src_frame_idx);
  390.   }
  391. }    /* end  p_advance_src_frame */
  392.  
  393.  
  394. /* ============================================================================
  395.  * p_mov_execute
  396.  * Copy layer(s) from Sourceimage to given destination frame range,
  397.  * varying koordinates and opacity of the copied layer.
  398.  * To each affected destination frame exactly one copy of a source layer is added.
  399.  * The source layer is iterated through all layers of the sourceimage
  400.  * according to stemmode parameter.
  401.  * For the placement the layers act as if their size is equal to their
  402.  * Sourceimages size.
  403.  * ============================================================================
  404.  */
  405.  
  406. /* TODO: add keyframe support */
  407.  
  408. long
  409. p_mov_execute(t_mov_data *mov_ptr)
  410. {
  411. /* MIX_VALUE  0.0 <= factor <= 1.0
  412.  *  result is a  for factor 0.0
  413.  *            b  for factor 1.0
  414.  *            mix for factors inbetween
  415.  */
  416. #define MIX_VALUE(factor, a, b) ((a * (1.0 - factor)) +  (b * factor))
  417.   gint l_idx;
  418.    t_mov_current l_current_data;
  419.    t_mov_current *cur_ptr;
  420.    t_mov_values  *val_ptr;
  421.  
  422.    gdouble  l_percentage;  
  423.    gdouble  l_fpl;             /* frames_per_line */
  424.    gdouble  l_flt_posfactor;
  425.    long     l_frame_step;
  426.    gdouble  l_frames;
  427.    long     l_cnt;
  428.    long     l_points;
  429.    long     l_ptidx;
  430.    long     l_prev_keyptidx;
  431.    long     l_fridx;
  432.    gdouble  l_flt_count;
  433.    gint     l_rc;
  434.    gint     l_nlayers;
  435.    gint     l_idk;
  436.    gint     l_prev_keyframe;
  437.    gint     l_apv_layerstack;
  438.    gdouble  l_flt_timing[GAP_MOV_MAX_POINT];   /* timing table in relative frame numbers (0.0 == the first handled frame) */
  439.    
  440.    
  441.    if(mov_ptr->val_ptr->src_image_id < 0)
  442.    {
  443.       p_msg_win(mov_ptr->dst_ainfo_ptr->run_mode,
  444.         _("No Source Image was selected.\n"
  445.       "Please open a 2nd Image of the same type before opening Move Path."));
  446.       return -1;
  447.    }
  448.  
  449.   l_apv_layerstack = 0;
  450.   l_percentage = 0.0;  
  451.   if(mov_ptr->dst_ainfo_ptr->run_mode == GIMP_RUN_INTERACTIVE)
  452.   { 
  453.     if(mov_ptr->val_ptr->apv_mlayer_image < 0)
  454.     {
  455.       gimp_progress_init( _("Copying Layers into Frames..."));
  456.     }
  457.     else
  458.     {
  459.       gimp_progress_init( _("Generating Animated Preview..."));
  460.     }
  461.   }
  462.  
  463.   if(gap_debug)
  464.   {
  465.     printf("p_mov_execute: values got from dialog:\n");
  466.     printf("apv_mlayer_image: %ld\n", (long)mov_ptr->val_ptr->apv_mlayer_image);
  467.     printf("apv_mode: %ld\n", (long)mov_ptr->val_ptr->apv_mode);
  468.     printf("apv_scale x: %f y:%f\n", (float)mov_ptr->val_ptr->apv_scalex, (float)mov_ptr->val_ptr->apv_scaley);
  469.     if(mov_ptr->val_ptr->apv_gap_paste_buff)
  470.     {
  471.       printf("apv_gap_paste_buf: %s\n", mov_ptr->val_ptr->apv_gap_paste_buff);
  472.     }
  473.     else
  474.     {
  475.       printf("apv_gap_paste_buf: ** IS NULL ** (do not copy to paste buffer)\n");
  476.     }
  477.     printf("src_image_id :%ld\n", (long)mov_ptr->val_ptr->src_image_id);
  478.     printf("src_layer_id :%ld\n", (long)mov_ptr->val_ptr->src_layer_id);
  479.     printf("src_handle :%d\n", mov_ptr->val_ptr->src_handle);
  480.     printf("src_stepmode :%d\n", mov_ptr->val_ptr->src_stepmode);
  481.     printf("src_paintmode :%d\n", mov_ptr->val_ptr->src_paintmode);
  482.     printf("clip_to_img :%d\n", mov_ptr->val_ptr->clip_to_img);
  483.     printf("dst_range_start :%d\n", (int)mov_ptr->val_ptr->dst_range_start);
  484.     printf("dst_range_end :%d\n", (int)mov_ptr->val_ptr->dst_range_end);
  485.     printf("dst_layerstack :%d\n", (int)mov_ptr->val_ptr->dst_layerstack);
  486.     for(l_idx = 0; l_idx <= mov_ptr->val_ptr->point_idx_max; l_idx++)
  487.     {
  488.       printf("p_x[%d] :%d\n", l_idx, mov_ptr->val_ptr->point[l_idx].p_x);
  489.       printf("p_y[%d] : :%d\n", l_idx, mov_ptr->val_ptr->point[l_idx].p_y);
  490.       printf("opacity[%d] :%d\n", l_idx, mov_ptr->val_ptr->point[l_idx].opacity);
  491.       printf("w_resize[%d] :%d\n", l_idx, mov_ptr->val_ptr->point[l_idx].w_resize);
  492.       printf("h_resize[%d] :%d\n", l_idx, mov_ptr->val_ptr->point[l_idx].h_resize);
  493.       printf("rotation[%d] :%d\n", l_idx, mov_ptr->val_ptr->point[l_idx].rotation);
  494.       printf("keyframe[%d] :%d\n", l_idx, mov_ptr->val_ptr->point[l_idx].keyframe);
  495.       printf("keyframe_abs[%d] :%d\n", l_idx, mov_ptr->val_ptr->point[l_idx].keyframe_abs);
  496.     }
  497.     printf("\n");
  498.   }
  499.  
  500.    l_rc    = 0;
  501.    cur_ptr = &l_current_data;
  502.    val_ptr = mov_ptr->val_ptr;
  503.  
  504.    /* set offsets (in cur_ptr)  according to handle mode and src_img dimension */
  505.    p_set_handle_offsets(val_ptr, cur_ptr);
  506.     
  507.    
  508.    /* test for invers range */
  509.    if(val_ptr->dst_range_start > val_ptr->dst_range_end)
  510.    {
  511.       /* step down */
  512.       l_frame_step = -1;
  513.       l_cnt = 1 + (val_ptr->dst_range_start - val_ptr->dst_range_end);
  514.    }
  515.    else
  516.    {
  517.       l_frame_step = 1;
  518.       l_cnt = 1 + (val_ptr->dst_range_end - val_ptr->dst_range_start);
  519.    }
  520.  
  521.    l_frames = (gdouble)l_cnt;              /* nr. of affected frames */
  522.    l_points = val_ptr->point_idx_max +1;   /* nr. of available points */
  523.    
  524.    if(l_points > l_frames)
  525.    {
  526.       /* cut off some points if we got more than frames */
  527.       l_points = l_cnt;
  528.    }
  529.  
  530.    if(l_points < 2)
  531.    {
  532.       /* copy point[0] to point [1] because we need at least 2
  533.        * points for the algorithms below to work. 
  534.        * (simulates a line with lenght 0, to move along)
  535.        */
  536.       if(gap_debug) printf("p_mov_execute: added a 2nd Point\n");
  537.       val_ptr->point[1].p_x = val_ptr->point[0].p_x;
  538.       val_ptr->point[1].p_y = val_ptr->point[0].p_y;
  539.       val_ptr->point[1].opacity = val_ptr->point[0].opacity;
  540.       val_ptr->point[1].w_resize = val_ptr->point[0].w_resize;
  541.       val_ptr->point[1].h_resize = val_ptr->point[0].h_resize;
  542.       val_ptr->point[1].rotation = val_ptr->point[0].rotation;
  543.       l_points = 2;
  544.    }
  545.    
  546.    
  547.    cur_ptr->dst_frame_nr = val_ptr->dst_range_start;
  548.    cur_ptr->src_layers = NULL;
  549.  
  550.    if(mov_ptr->val_ptr->src_stepmode < GAP_STEP_FRAME)
  551.    {   
  552.      cur_ptr->src_layers = gimp_image_get_layers (val_ptr->src_image_id, &l_nlayers);
  553.      if(cur_ptr->src_layers == NULL)
  554.      {
  555.        printf("ERROR (in p_mov_execute): Got no layers from SrcImage\n");
  556.        return -1;
  557.      }
  558.      if(l_nlayers < 1)
  559.      {
  560.        printf("ERROR (in p_mov_execute): Source Image has no layers\n");
  561.        return -1;
  562.      }
  563.      cur_ptr->src_last_layer = l_nlayers -1;
  564.  
  565.      /* findout index of src_layer_id */
  566.      for(cur_ptr->src_layer_idx = 0; 
  567.      cur_ptr->src_layer_idx  < l_nlayers;
  568.      cur_ptr->src_layer_idx++)
  569.      {
  570.     if(cur_ptr->src_layers[cur_ptr->src_layer_idx] == val_ptr->src_layer_id)
  571.            break;
  572.      }
  573.      cur_ptr->src_last_layer = l_nlayers -1;   /* index of last layer */
  574.      }
  575.    else
  576.    {
  577.      /* for FRAME stepmodes we use flattened Sorce frames
  578.       * (instead of one multilayer source image )
  579.       */
  580.      p_fetch_src_frame (val_ptr, -1);  /* negative value fetches the selected frame number */
  581.      cur_ptr->src_frame_idx = val_ptr->cache_ainfo_ptr->curr_frame_nr;
  582.      
  583.      if((val_ptr->cache_ainfo_ptr->first_frame_nr < 0)
  584.      && (val_ptr->src_stepmode != GAP_STEP_FRAME_NONE))
  585.      {
  586.         p_dir_ainfo(val_ptr->cache_ainfo_ptr);
  587.      }
  588.  
  589.      /* set offsets (in cur_ptr)  according to handle mode and cache_tmp_img dimension */
  590.      p_set_handle_offsets(val_ptr, cur_ptr);
  591.    }
  592.    
  593.    cur_ptr->currX   = (gdouble)val_ptr->point[0].p_x;
  594.    cur_ptr->currY   = (gdouble)val_ptr->point[0].p_y;
  595.    cur_ptr->currOpacity  = (gdouble)val_ptr->point[0].opacity;
  596.    cur_ptr->currWidth    = (gdouble)val_ptr->point[0].w_resize;
  597.    cur_ptr->currHeight   = (gdouble)val_ptr->point[0].h_resize;
  598.    cur_ptr->currRotation = (gdouble)val_ptr->point[0].rotation;
  599.  
  600.    /* RENDER add current src_layer to current frame */
  601.    l_rc = p_mov_call_render(mov_ptr, cur_ptr, l_apv_layerstack);
  602.  
  603.    if(gap_debug) printf("p_mov_execute: l_points=%d\n", (int)l_points);
  604.    
  605.    /* how many frames are affected from one line of the moving path */   
  606.    l_fpl = ((gdouble)l_frames - 1.0) / ((gdouble)(l_points -1));
  607.    if(gap_debug) printf("p_mov_execute: initial l_fpl=%f\n", l_fpl);
  608.  
  609.    /* calculate l_flt_timing controlpoint timing table considering keyframes */
  610.    l_prev_keyptidx = 0;
  611.    l_prev_keyframe = 0;
  612.    l_flt_timing[0] = 0.0;
  613.    l_flt_timing[l_points -1] = l_frames -1;
  614.    l_flt_count = 0.0;
  615.    for(l_ptidx=1;  l_ptidx < l_points - 1; l_ptidx++)
  616.    {
  617.      /* search for keyframes */
  618.      if(l_ptidx > l_prev_keyptidx)
  619.      {
  620.        for(l_idk = l_ptidx; l_idk < l_points; l_idk++)
  621.        {
  622.           if(l_idk == l_points -1)
  623.       {
  624.         /* last point is always an implicite  keyframe */
  625.             l_fpl = ((gdouble)((l_frames -1) - l_prev_keyframe)) / ((gdouble)((l_idk -  l_ptidx) +1));
  626.             l_prev_keyframe = l_frames -1;
  627.  
  628.             l_prev_keyptidx = l_idk;
  629.             if(gap_debug) printf("p_mov_execute: last point is implicite keyframe l_fpl=%f\n", l_fpl);
  630.             break;
  631.       }
  632.       else
  633.       {
  634.         if (val_ptr->point[l_idk].keyframe > 0)
  635.         {
  636.           /* found a keyframe, have to recalculate frames_per_line */
  637.               l_fpl = ((gdouble)(val_ptr->point[l_idk].keyframe - l_prev_keyframe)) / ((gdouble)((l_idk -  l_ptidx) +1));
  638.               l_prev_keyframe = val_ptr->point[l_idk].keyframe;
  639.  
  640.               l_prev_keyptidx = l_idk;
  641.               if(gap_debug) printf("p_mov_execute: keyframe l_fpl=%f\n", l_fpl);
  642.               break;
  643.         }
  644.       }
  645.        }
  646.      }
  647.      l_flt_count += l_fpl;
  648.      l_flt_timing[l_ptidx] = l_flt_count;
  649.  
  650.      if(l_fpl < 1.0)
  651.      {
  652.     printf("p_mov_execute: ** Error frames per line at point[%d] = %f  (is less than 1.0 !!)\n",
  653.       (int)l_ptidx, (float)l_fpl);
  654.      }
  655.    }
  656.  
  657.    if(gap_debug)
  658.    {
  659.      printf("p_mov_execute: --- CONTROLPOINT relative frametiming TABLE -----\n");
  660.      for(l_ptidx=0;  l_ptidx < l_points; l_ptidx++)
  661.      {
  662.        printf("p_mov_execute: l_flt_timing[%02d] = %f\n", (int)l_ptidx, (float)l_flt_timing[l_ptidx]);
  663.      }
  664.    }
  665.  
  666.     
  667.   /* loop for each frame within the range (may step up or down) */
  668.   l_ptidx = 1;
  669.   cur_ptr->dst_frame_nr = val_ptr->dst_range_start;
  670.   for(l_fridx = 1; l_fridx < l_cnt; l_fridx++)
  671.   {
  672.      
  673.      if(gap_debug) printf("\np_mov_execute: l_fridx=%ld, l_flt_timing[l_ptidx]=%f, l_rc=%d l_ptidx=%d, l_prev_keyptidx=%d\n",
  674.                            l_fridx, (float)l_flt_timing[l_ptidx], (int)l_rc, (int)l_ptidx, (int)l_prev_keyptidx);
  675.  
  676.      if(l_rc != 0) break;
  677.  
  678.       /* advance frame_nr, (1st frame was done outside this loop) */
  679.       cur_ptr->dst_frame_nr += l_frame_step;  /* +1  or -1 */
  680.  
  681.       if((gdouble)l_fridx > l_flt_timing[l_ptidx])
  682.       {
  683.          /* change deltas for next line of the move path */
  684.      if(l_ptidx < l_points-1)
  685.      {
  686.            l_ptidx++;
  687.        if(gap_debug)
  688.        {
  689.           printf("p_mov_execute: advance to controlpoint l_ptidx=%d, l_flt_timing[l_ptidx]=%f\n"
  690.                  , (int)l_ptidx, (float)l_flt_timing[l_ptidx]);
  691.        }
  692.      }
  693.      else
  694.      {
  695.        if(gap_debug) printf("p_mov_execute: ** ERROR overflow l_ptidx=%d\n", (int)l_ptidx);
  696.      }
  697.       }
  698.       
  699.       l_fpl = (l_flt_timing[l_ptidx] - l_flt_timing[l_ptidx -1]); /* float frames per line */
  700.       if(l_fpl != 0.0)
  701.       {
  702.         l_flt_posfactor  = ((gdouble)l_fridx - l_flt_timing[l_ptidx -1]) / l_fpl;
  703.       }
  704.       else
  705.       {
  706.          l_flt_posfactor = 1.0;
  707.          if(gap_debug) printf("p_mov_execute: ** ERROR l_fpl is 0.0 frames per line\n");
  708.       }
  709.       
  710.  
  711.       if(gap_debug) printf("p_mov_execute: l_fpl=%f, l_flt_posfactor=%f\n", (float)l_fpl, (float)l_flt_posfactor);
  712.  
  713.       l_flt_posfactor = CLAMP (l_flt_posfactor, 0.0, 1.0);
  714.      
  715.       cur_ptr->currX  =       MIX_VALUE(l_flt_posfactor, (gdouble)val_ptr->point[l_ptidx -1].p_x,      (gdouble)val_ptr->point[l_ptidx].p_x);
  716.       cur_ptr->currY  =       MIX_VALUE(l_flt_posfactor, (gdouble)val_ptr->point[l_ptidx -1].p_y,      (gdouble)val_ptr->point[l_ptidx].p_y);
  717.       cur_ptr->currOpacity =  MIX_VALUE(l_flt_posfactor, (gdouble)val_ptr->point[l_ptidx -1].opacity,  (gdouble)val_ptr->point[l_ptidx].opacity);
  718.       cur_ptr->currWidth =    MIX_VALUE(l_flt_posfactor, (gdouble)val_ptr->point[l_ptidx -1].w_resize, (gdouble)val_ptr->point[l_ptidx].w_resize);
  719.       cur_ptr->currHeight =   MIX_VALUE(l_flt_posfactor, (gdouble)val_ptr->point[l_ptidx -1].h_resize, (gdouble)val_ptr->point[l_ptidx].h_resize);
  720.       cur_ptr->currRotation = MIX_VALUE(l_flt_posfactor, (gdouble)val_ptr->point[l_ptidx -1].rotation, (gdouble)val_ptr->point[l_ptidx].rotation);
  721.  
  722.       if(gap_debug)
  723.       {
  724.           printf("ROTATE [%02d] %d    [%02d] %d       MIX: %f\n"
  725.           , (int)l_ptidx-1,  (int)val_ptr->point[l_ptidx -1].rotation
  726.           , (int)l_ptidx,    (int)val_ptr->point[l_ptidx].rotation
  727.       , (float)cur_ptr->currRotation);
  728.       }
  729.  
  730.        if(val_ptr->src_stepmode < GAP_STEP_FRAME )
  731.        {
  732.          /* advance settings for next src layer */
  733.          p_mov_advance_src_layer(cur_ptr, val_ptr->src_stepmode);
  734.        }
  735.  
  736.        else
  737.        {
  738.          /* advance settings for next source frame */
  739.          p_mov_advance_src_frame(cur_ptr, val_ptr);
  740.        }
  741.  
  742.        if(l_frame_step < 0)
  743.        {
  744.          /* if we step down, we have to insert the layer
  745.       * as lowest layer in the existing layerstack
  746.       * of the animated preview multilayer image.
  747.       * (if we step up, we always use 0 as l_apv_layerstack,
  748.       *  that means always insert on top of the layerstack)
  749.       */
  750.          l_apv_layerstack++;
  751.        }
  752.        /* RENDER add current src_layer to current frame */
  753.        l_rc = p_mov_call_render(mov_ptr, cur_ptr, l_apv_layerstack);
  754.  
  755.        /* show progress */
  756.        if(mov_ptr->dst_ainfo_ptr->run_mode == GIMP_RUN_INTERACTIVE)
  757.        { 
  758.          l_percentage = (gdouble)l_fridx / (gdouble)(l_cnt -1);
  759.          gimp_progress_update (l_percentage);
  760.        }
  761.            
  762.    }
  763.  
  764.    if(cur_ptr->src_layers != NULL) g_free(cur_ptr->src_layers);
  765.    
  766.    cur_ptr->src_layers = NULL;
  767.    
  768.    
  769.    return l_rc;  
  770.  
  771. }    /* end p_mov_execute */
  772.  
  773.  
  774. /* ============================================================================
  775.  * p_mov_anim_preview
  776.  *   Generate an animate preview for the move path
  777.  * ============================================================================
  778.  */
  779. gint32 
  780. p_mov_anim_preview(t_mov_values *pvals_orig, t_anim_info *ainfo_ptr, gint preview_frame_nr)
  781. {
  782.   t_mov_data    apv_mov_data;
  783.   t_mov_values  apv_mov_vals;
  784.   t_mov_data    *l_mov_ptr;
  785.   t_mov_values  *l_pvals;
  786.   gint        l_idx;
  787.   gint32      l_size_x, l_size_y;
  788.   gint32      l_tmp_image_id;
  789.   gint32      l_tmp_frame_id;
  790.   gint32      l_mlayer_image_id;
  791.   GimpParam     *l_params;
  792.   gint        l_retvals;
  793.   GimpImageBaseType  l_type;
  794.   guint       l_width, l_height;
  795.   gint32      l_stackpos;
  796.   gint        l_nlayers;
  797.   gint32     *l_src_layers;
  798.   gint        l_rc;
  799.   
  800.   l_mov_ptr = &apv_mov_data;
  801.   l_pvals = &apv_mov_vals;
  802.   
  803.   /* copy settings */
  804.   memcpy(l_pvals, pvals_orig, sizeof(t_mov_values));
  805.   l_mov_ptr->val_ptr = l_pvals;
  806.   l_mov_ptr->dst_ainfo_ptr = ainfo_ptr;
  807.   
  808.   /* init local cached src image for anim preview generation.
  809.    * (never mix cached src image for normal and anim preview
  810.    *  because anim previews are often scaled down)
  811.    */
  812.   l_pvals->cache_src_image_id  = -1;  
  813.   l_pvals->cache_tmp_image_id  = -1;
  814.   l_pvals->cache_tmp_layer_id  = -1;
  815.   l_pvals->cache_frame_number  = -1;
  816.   l_pvals->cache_ainfo_ptr = NULL;
  817.  
  818.   /* -1 assume no tmp_image (use unscaled original source) */
  819.   l_tmp_image_id = -1;
  820.   l_stackpos = 0;
  821.  
  822.   /* Scale (down) needed ? */
  823.   if((l_pvals->apv_scalex != 100.0) || (l_pvals->apv_scaley != 100.0))
  824.   {
  825.     /* scale the controlpoint koords */
  826.     for(l_idx = 0; l_idx <= l_pvals->point_idx_max; l_idx++)
  827.     {
  828.       l_pvals->point[l_idx].p_x  = (l_pvals->point[l_idx].p_x * l_pvals->apv_scalex) / 100;
  829.       l_pvals->point[l_idx].p_y  = (l_pvals->point[l_idx].p_y * l_pvals->apv_scaley) / 100;
  830.     }
  831.  
  832.     /* for the FRAME based step modes we cant Scale here,
  833.      * we have to scale later (at fetch time of the frame)
  834.      */
  835.     if(l_pvals->src_stepmode < GAP_STEP_FRAME)
  836.     {
  837.       /* copy and scale the source object image */
  838.       l_tmp_image_id = p_gimp_channel_ops_duplicate(pvals_orig->src_image_id);
  839.       l_pvals->src_image_id = l_tmp_image_id;
  840.  
  841.       l_size_x = MAX(1, (gimp_image_width(l_tmp_image_id) * l_pvals->apv_scalex) / 100);
  842.       l_size_y = MAX(1, (gimp_image_height(l_tmp_image_id) * l_pvals->apv_scaley) / 100);
  843.       l_params = gimp_run_procedure ("gimp_image_scale",
  844.                              &l_retvals,
  845.                        GIMP_PDB_IMAGE,    l_tmp_image_id,
  846.                        GIMP_PDB_INT32,    l_size_x,
  847.                        GIMP_PDB_INT32,    l_size_y,
  848.                        GIMP_PDB_END);
  849.  
  850.        /* findout the src_layer id in the scaled copy by stackpos index */
  851.        l_pvals->src_layer_id = -1;
  852.        l_src_layers = gimp_image_get_layers (pvals_orig->src_image_id, &l_nlayers);
  853.        if(l_src_layers == NULL)
  854.        {
  855.      printf("ERROR: p_mov_anim_preview GOT no src_layers (original image_id %d)\n",
  856.              (int)pvals_orig->src_image_id);
  857.        }
  858.        else
  859.        {
  860.      for(l_stackpos = 0; 
  861.          l_stackpos  < l_nlayers;
  862.          l_stackpos++)
  863.      {
  864.         if(l_src_layers[l_stackpos] == pvals_orig->src_layer_id)
  865.                break;
  866.      }
  867.      g_free(l_src_layers);
  868.  
  869.      l_src_layers = gimp_image_get_layers (l_tmp_image_id, &l_nlayers);
  870.      if(l_src_layers == NULL)
  871.      {
  872.            printf("ERROR: p_mov_anim_preview GOT no src_layers (scaled copy image_id %d)\n",
  873.               (int)l_tmp_image_id);
  874.      }
  875.      else
  876.      {
  877.             l_pvals->src_layer_id = l_src_layers[l_stackpos];
  878.             g_free(l_src_layers);
  879.      }
  880.  
  881.        }
  882.  
  883.       if(gap_debug)
  884.       {
  885.     printf("p_mov_anim_preview: orig  src_image_id:%d src_layer:%d, stackpos:%d\n"
  886.                ,(int)pvals_orig->src_image_id
  887.            ,(int)pvals_orig->src_layer_id
  888.            ,(int)l_stackpos);
  889.     printf("   Scaled src_image_id:%d scaled_src_layer:%d\n"
  890.                ,(int)l_tmp_image_id
  891.            ,(int)l_pvals->src_layer_id );
  892.       }
  893.     }
  894.  
  895.     
  896.   }
  897.  
  898.  
  899.   if(gap_debug)
  900.   {
  901.     printf("p_mov_anim_preview: src_image_id %d (orig:%d)\n"
  902.            , (int) l_pvals->src_image_id
  903.        , (int) pvals_orig->src_image_id);
  904.   }
  905.   
  906.   /* create the animated preview multilayer image in (scaled) framesize */
  907.   l_width  = (gimp_image_width(ainfo_ptr->image_id) * l_pvals->apv_scalex) / 100;
  908.   l_height = (gimp_image_height(ainfo_ptr->image_id) * l_pvals->apv_scaley) / 100;
  909.   l_type   = gimp_image_base_type(ainfo_ptr->image_id);
  910.   
  911.   l_mlayer_image_id = gimp_image_new(l_width, l_height,l_type);
  912.   l_pvals->apv_mlayer_image = l_mlayer_image_id;
  913.  
  914.   if(gap_debug)
  915.   {
  916.     printf("p_mov_anim_preview: apv_mlayer_image %d\n"
  917.            , (int) l_pvals->apv_mlayer_image);
  918.   }
  919.   
  920.   /* APV_MODE (Wich frames to use in the preview?)  */
  921.   switch(l_pvals->apv_mode)
  922.   {
  923.     gchar *l_filename;
  924.     
  925.     case GAP_APV_QUICK:
  926.       /* use an empty dummy frame for all frames */    
  927.       l_tmp_frame_id = gimp_image_new(l_width, l_height,l_type);
  928.       break;
  929.     case GAP_APV_ONE_FRAME:
  930.       /* use only one frame in the preview */    
  931.       l_filename = p_alloc_fname(ainfo_ptr->basename,
  932.                                  preview_frame_nr,
  933.                                  ainfo_ptr->extension);
  934.       l_tmp_frame_id =  p_load_image(l_filename);
  935.       if((l_pvals->apv_scalex != 100.0) || (l_pvals->apv_scaley != 100.0))
  936.       {
  937.     l_size_x = (gimp_image_width(l_tmp_frame_id) * l_pvals->apv_scalex) / 100;
  938.     l_size_y = (gimp_image_height(l_tmp_frame_id) * l_pvals->apv_scaley) / 100;
  939.     l_params = gimp_run_procedure ("gimp_image_scale",
  940.                              &l_retvals,
  941.                        GIMP_PDB_IMAGE,    l_tmp_frame_id,
  942.                        GIMP_PDB_INT32,    l_size_x,
  943.                        GIMP_PDB_INT32,    l_size_y,
  944.                        GIMP_PDB_END);
  945.       }
  946.       g_free(l_filename);
  947.       break;
  948.     default:  /* GAP_APV_EXACT */
  949.       /* read the original frames for the preview (slow) */
  950.       l_tmp_frame_id = -1; 
  951.       break;
  952.   }
  953.   l_pvals->apv_src_frame = l_tmp_frame_id;
  954.  
  955.   if(gap_debug)
  956.   {
  957.     printf("p_mov_anim_preview: apv_src_frame %d\n"
  958.            , (int) l_pvals->apv_src_frame);
  959.   }
  960.  
  961.  
  962.   /* EXECUTE move path in preview Mode */ 
  963.   /* --------------------------------- */ 
  964.   l_rc = p_mov_execute(l_mov_ptr);
  965.  
  966.   if(l_pvals->cache_tmp_image_id >= 0)
  967.   {
  968.      if(gap_debug)
  969.      {
  970.     printf("p_mov_anim_preview: DELETE cache_tmp_image_id:%d\n",
  971.              (int)l_pvals->cache_tmp_image_id);
  972.      }
  973.      /* destroy the cached frame image */
  974.      gimp_image_delete(l_pvals->cache_tmp_image_id);
  975.      l_pvals->cache_tmp_image_id = -1;
  976.   }
  977.   
  978.   if(l_rc < 0)
  979.   {
  980.     return(-1);
  981.   }
  982.   
  983.   /* add a display for the animated preview multilayer image */
  984.   gimp_display_new(l_mlayer_image_id);
  985.  
  986.   /* delete the scaled copy of the src image (if there is one) */
  987.   if(l_tmp_image_id >= 0)
  988.   { 
  989.     gimp_image_delete(l_tmp_image_id);
  990.   }
  991.   /* delete the (scaled) dummy frames (if there is one) */
  992.   if(l_tmp_frame_id >= 0)
  993.   { 
  994.     gimp_image_delete(l_tmp_frame_id);
  995.   }
  996.  
  997.   return(l_mlayer_image_id);
  998. }    /* end p_mov_anim_preview */
  999.  
  1000. /* ============================================================================
  1001.  * p_con_keyframe
  1002.  * ============================================================================
  1003.  */
  1004.  
  1005. gint
  1006. p_conv_keyframe_to_rel(gint abs_keyframe, t_mov_values *pvals)
  1007. {
  1008.     if(pvals->dst_range_start <= pvals->dst_range_end)
  1009.     {
  1010.        return (abs_keyframe -  pvals->dst_range_start);
  1011.     }
  1012.     return (pvals->dst_range_start - abs_keyframe);
  1013. }
  1014.  
  1015. gint
  1016. p_conv_keyframe_to_abs(gint rel_keyframe, t_mov_values *pvals)
  1017. {
  1018.     if(pvals->dst_range_start <= pvals->dst_range_end)
  1019.     {
  1020.       return(rel_keyframe + pvals->dst_range_start);
  1021.     }
  1022.     return(pvals->dst_range_start - rel_keyframe);
  1023. }
  1024.  
  1025. /* ============================================================================
  1026.  * p_gap_save_pointfile
  1027.  * ============================================================================
  1028.  */
  1029. gint
  1030. p_gap_save_pointfile(char *filename, t_mov_values *pvals)
  1031. {
  1032.   FILE *l_fp;
  1033.   gint l_idx;
  1034.   
  1035.   if(filename == NULL) return -1;
  1036.   
  1037.   l_fp = fopen(filename, "w+");
  1038.   if(l_fp != NULL)
  1039.   {
  1040.     fprintf(l_fp, "# GAP file contains saved Move Path Point Table\n");
  1041.     fprintf(l_fp, "%d  %d  # current_point  points\n",
  1042.                   (int)pvals->point_idx,
  1043.                   (int)pvals->point_idx_max + 1);
  1044.     fprintf(l_fp, "# x  y   width height opacity rotation [rel_keyframe]\n");
  1045.     for(l_idx = 0; l_idx <= pvals->point_idx_max; l_idx++)
  1046.     {
  1047.       if((l_idx > 0) 
  1048.       && (l_idx < pvals->point_idx_max)
  1049.       && ((int)pvals->point[l_idx].keyframe > 0))
  1050.       {
  1051.     fprintf(l_fp, "%04d %04d  %03d %03d  %03d %d %d\n",
  1052.                      (int)pvals->point[l_idx].p_x,
  1053.                      (int)pvals->point[l_idx].p_y,
  1054.                      (int)pvals->point[l_idx].w_resize,
  1055.                      (int)pvals->point[l_idx].h_resize,
  1056.                      (int)pvals->point[l_idx].opacity,
  1057.                      (int)pvals->point[l_idx].rotation,
  1058.                      (int)p_conv_keyframe_to_rel(pvals->point[l_idx].keyframe_abs, pvals));
  1059.       }
  1060.       else
  1061.       {
  1062.     fprintf(l_fp, "%04d %04d  %03d %03d  %03d %d\n",
  1063.                      (int)pvals->point[l_idx].p_x,
  1064.                      (int)pvals->point[l_idx].p_y,
  1065.                      (int)pvals->point[l_idx].w_resize,
  1066.                      (int)pvals->point[l_idx].h_resize,
  1067.                      (int)pvals->point[l_idx].opacity,
  1068.                      (int)pvals->point[l_idx].rotation);
  1069.       }
  1070.     }
  1071.      
  1072.     fclose(l_fp);
  1073.     return 0;
  1074.   }
  1075.   return -1;
  1076. }
  1077.  
  1078. /* ============================================================================
  1079.  * p_gap_load_pointfile
  1080.  * ============================================================================
  1081.  */
  1082. gint
  1083. p_gap_load_pointfile(char *filename, t_mov_values *pvals)
  1084. {
  1085. #define POINT_REC_MAX 128
  1086.  
  1087.   FILE *l_fp;
  1088.   gint   l_idx;
  1089.   char  l_buff[POINT_REC_MAX +1 ];
  1090.   char *l_ptr;
  1091.   gint   l_cnt;
  1092.   gint   l_rc;
  1093.   gint   l_v1, l_v2, l_v3, l_v4, l_v5, l_v6, l_v7;
  1094.  
  1095.   l_rc = -1;
  1096.   if(filename == NULL) return(l_rc);
  1097.   
  1098.   l_fp = fopen(filename, "r");
  1099.   if(l_fp != NULL)
  1100.   {
  1101.     l_idx = -1;
  1102.     while (NULL != fgets (l_buff, POINT_REC_MAX, l_fp))
  1103.     {
  1104.        /* skip leading blanks */
  1105.        l_ptr = l_buff;
  1106.        while(*l_ptr == ' ') { l_ptr++; }
  1107.        
  1108.        /* check if line empty or comment only (starts with '#') */
  1109.        if((*l_ptr != '#') && (*l_ptr != '\n') && (*l_ptr != '\0'))
  1110.        {
  1111.          l_cnt = sscanf(l_ptr, "%d%d%d%d%d%d%d", &l_v1, &l_v2, &l_v3, &l_v4, &l_v5, &l_v6, &l_v7);
  1112.          if(l_idx == -1)
  1113.          {
  1114.            if((l_cnt < 2) || (l_v2 > GAP_MOV_MAX_POINT) || (l_v1 > l_v2))
  1115.            {
  1116.              break;
  1117.             }
  1118.            pvals->point_idx     = l_v1;
  1119.            pvals->point_idx_max = l_v2 -1;
  1120.            l_idx = 0;
  1121.          }
  1122.          else
  1123.          {
  1124.            if((l_cnt != 6) && (l_cnt != 7))
  1125.            {
  1126.              l_rc = -2;  /* have to call p_reset_points() when called from dialog window */
  1127.              break;
  1128.            }
  1129.            pvals->point[l_idx].p_x      = l_v1;
  1130.            pvals->point[l_idx].p_y      = l_v2;
  1131.            pvals->point[l_idx].w_resize = l_v3;
  1132.            pvals->point[l_idx].h_resize = l_v4;
  1133.            pvals->point[l_idx].opacity  = l_v5;
  1134.            pvals->point[l_idx].rotation = l_v6;
  1135.            if((l_cnt == 7) && (l_idx > 0))
  1136.        {
  1137.              pvals->point[l_idx].keyframe = l_v7;
  1138.              pvals->point[l_idx].keyframe_abs = p_conv_keyframe_to_abs(l_v7, pvals);
  1139.        }
  1140.        else
  1141.        {
  1142.              pvals->point[l_idx].keyframe_abs = 0;
  1143.              pvals->point[l_idx].keyframe = 0;
  1144.        }
  1145.            l_idx ++;
  1146.          }
  1147.  
  1148.          if(l_idx > pvals->point_idx_max) break;
  1149.        }
  1150.     }
  1151.      
  1152.     fclose(l_fp);
  1153.     if(l_idx >= 0)
  1154.     {
  1155.        l_rc = 0;  /* OK if we found at least one valid Controlpoint in the file */
  1156.     }
  1157.   }
  1158.   return (l_rc);
  1159. }
  1160.  
  1161.  
  1162. /* ============================================================================
  1163.  * procedured for calculating angels
  1164.  *   (used in rotate_follow option)
  1165.  * ============================================================================
  1166.  */
  1167.  
  1168. static gdouble
  1169. p_calc_angle(gint p1x, gint p1y, gint p2x, gint p2y)
  1170. {
  1171.   /* calculate angle in degree
  1172.    * how to rotate an object that follows the line between p1 and p2
  1173.    */
  1174.   gdouble l_a;
  1175.   gdouble l_b;
  1176.   gdouble l_angle_rad;
  1177.   gdouble l_angle;
  1178.   
  1179.   l_a = p2x - p1x;
  1180.   l_b = (p2y - p1y) * (-1.0);
  1181.   
  1182.   if(l_a == 0)
  1183.   {
  1184.     if(l_b < 0)  { l_angle = 90.0; }
  1185.     else         { l_angle = 270.0; }
  1186.   }
  1187.   else
  1188.   {
  1189.     l_angle_rad = atan(l_b/l_a);
  1190.     l_angle = (l_angle_rad * 180.0) / 3.14159;
  1191.  
  1192.     if(l_a < 0)
  1193.     {
  1194.       l_angle = 180 - l_angle;
  1195.     }
  1196.     else
  1197.     {
  1198.       l_angle = l_angle * (-1.0);
  1199.     }
  1200.   }  
  1201.  
  1202.   if(gap_debug)
  1203.   {
  1204.      printf("p_calc_angle: p1(%d/%d) p2(%d/%d)  a=%f, b=%f, angle=%f\n"
  1205.          , (int)p1x, (int)p1y, (int)p2x, (int)p2y
  1206.          , (float)l_a, (float)l_b, (float)l_angle);
  1207.   }
  1208.   return(l_angle);
  1209. }
  1210.  
  1211. static gdouble
  1212. p_rotatate_less_than_180(gdouble angle, gdouble angle_new, gint *turns)
  1213. {
  1214.   /* if an object  follows a circular path and does more than one turn
  1215.    * there comes a point where it flips from say 265 degree to -85 degree.
  1216.    *
  1217.    * if there are more (say 3) frames between the controlpoints,
  1218.    * the object performs an unexpected rotation effect because the iteration
  1219.    * from 265 to -85  is done  in a sequence like this: 265.0, 148.6, 32.3, -85.0
  1220.    *
  1221.    * we can avoid this by preventing angle changes of more than 180 degree.
  1222.    * in such a case this procedure adjusts the new_angle from -85 to 275
  1223.    * that results in oterations like this: 265.0, 268.3, 271.6, 275.0
  1224.    */
  1225.   gint l_diff;
  1226.   gint l_turns;
  1227.  
  1228.   l_diff = angle - (angle_new + (*turns * 360));
  1229.   if((l_diff >= -180) && (l_diff < 180))
  1230.   {
  1231.       return(angle_new + (*turns * 360));
  1232.   }
  1233.  
  1234.   l_diff = (angle - angle_new);
  1235.   if(l_diff < 0)
  1236.   {
  1237.      l_turns = (l_diff / 360) -1;
  1238.   }
  1239.   else
  1240.   {
  1241.      l_turns = (l_diff / 360) +1;
  1242.   }
  1243.  
  1244.   *turns = l_turns;
  1245.  
  1246.   if(gap_debug)
  1247.   {
  1248.      printf("p_rotatate_less_than_180: turns %d angle_new:%f\n"
  1249.              , (int)l_turns, (float)angle_new);
  1250.   }
  1251.  
  1252.   return( angle_new + (l_turns * 360));
  1253. }
  1254.  
  1255.  
  1256. /* ============================================================================
  1257.  * p_calculate_rotate_follow
  1258.  * ============================================================================
  1259.  */
  1260. void
  1261. p_calculate_rotate_follow(t_mov_values *pvals, gint32 startangle)
  1262. {
  1263.   gint l_idx;
  1264.   gdouble l_startangle;
  1265.   gdouble l_angle_1;
  1266.   gdouble l_angle_2;
  1267.   gdouble l_angle_new;
  1268.   gdouble l_angle;
  1269.   gint    l_turns;
  1270.  
  1271.   l_startangle = startangle;
  1272.   
  1273.   if(pvals->point_idx_max > 1)
  1274.   {
  1275.     l_angle = 0.0;
  1276.     l_turns = 0;
  1277.  
  1278.     for(l_idx = 0; l_idx <= pvals->point_idx_max; l_idx++)
  1279.     {
  1280.       if(l_idx == 0)
  1281.       {
  1282.         l_angle = p_calc_angle(pvals->point[l_idx].p_x,
  1283.                            pvals->point[l_idx].p_y,
  1284.                            pvals->point[l_idx +1].p_x,
  1285.                            pvals->point[l_idx +1].p_y);
  1286.       }
  1287.       else
  1288.       {
  1289.         if(l_idx == pvals->point_idx_max)
  1290.     {
  1291.           l_angle_new = p_calc_angle(pvals->point[l_idx -1].p_x,
  1292.                          pvals->point[l_idx -1].p_y,
  1293.                          pvals->point[l_idx].p_x,
  1294.                          pvals->point[l_idx].p_y);
  1295.     }
  1296.     else
  1297.     {
  1298.            l_angle_1 = p_calc_angle(pvals->point[l_idx -1].p_x,
  1299.                           pvals->point[l_idx -1].p_y,
  1300.                           pvals->point[l_idx].p_x,
  1301.                           pvals->point[l_idx].p_y);
  1302.                   
  1303.            l_angle_2 = p_calc_angle(pvals->point[l_idx].p_x,
  1304.                               pvals->point[l_idx].p_y,
  1305.                               pvals->point[l_idx +1].p_x,
  1306.                               pvals->point[l_idx +1].p_y);
  1307.  
  1308.            if((l_angle_1 == 0) && (l_angle_2 == 180))
  1309.        {
  1310.                l_angle_new = 270;
  1311.        }
  1312.        else
  1313.        {
  1314.              if((l_angle_1 == 90) && (l_angle_2 == 270))
  1315.          {
  1316.                l_angle_new = 0;
  1317.          }
  1318.          else
  1319.          {
  1320.                l_angle_new = (l_angle_1 + l_angle_2) / 2;
  1321.          }
  1322.        }
  1323.        if(((l_angle_1 < 0) && (l_angle_2 >= 180))
  1324.        || ((l_angle_2 < 0) && (l_angle_1 >= 180)))
  1325.        {
  1326.           l_angle_new += 180;
  1327.        }
  1328.     }
  1329.     l_angle = p_rotatate_less_than_180(l_angle, l_angle_new, &l_turns);
  1330.       }
  1331.  
  1332.       if(gap_debug)
  1333.       {
  1334.         printf("ROT Follow [%03d] angle = %f\n", (int)l_idx, (float)l_angle);
  1335.       }
  1336.  
  1337.       pvals->point[l_idx].rotation = l_startangle + l_angle;
  1338.     }
  1339.   }
  1340. }    /* end p_calculate_rotate_follow */
  1341.  
  1342.  
  1343. /* ============================================================================
  1344.  * p_gap_chk_keyframes
  1345.  *   check if controlpoints and keyframe settings are OK
  1346.  *   return pointer to errormessage on Errors
  1347.  *      contains "\0" if no errors are found
  1348.  * ============================================================================
  1349.  */
  1350. gchar *p_gap_chk_keyframes(t_mov_values *pvals)
  1351. {
  1352.   gint   l_affected_frames;
  1353.   gint   l_idx;
  1354.   gint   l_errcount;
  1355.   gint   l_prev_keyframe;
  1356.   gint   l_prev_frame;
  1357.   gchar *l_err;
  1358.   gchar *l_err_lbltext;
  1359.  
  1360.   l_affected_frames = 1 + MAX(pvals->dst_range_start, pvals->dst_range_end)
  1361.                     - MIN(pvals->dst_range_start, pvals->dst_range_end);
  1362.   
  1363.   l_errcount = 0;
  1364.   l_prev_keyframe = 0;
  1365.   l_prev_frame = 0;
  1366.   l_err_lbltext = g_strdup("\0");
  1367.   
  1368.   for(l_idx = 0; l_idx < pvals->point_idx_max; l_idx++ )
  1369.   {
  1370.      if(pvals->point[l_idx].keyframe_abs != 0)
  1371.      {
  1372.          pvals->point[l_idx].keyframe = p_conv_keyframe_to_rel(pvals->point[l_idx].keyframe_abs, pvals);
  1373.  
  1374.          if(pvals->point[l_idx].keyframe > l_affected_frames - 2)
  1375.      {
  1376.         l_err = g_strdup_printf(_("\nError: Keyframe %d at point [%d] higher or equal than last handled frame")
  1377.                                   , pvals->point[l_idx].keyframe_abs,  l_idx+1);
  1378.         l_err_lbltext = g_strdup_printf("%s%s", l_err_lbltext, l_err);
  1379.         g_free(l_err);
  1380.         l_errcount++;
  1381.      }
  1382.          if(pvals->point[l_idx].keyframe < l_prev_frame)
  1383.      {
  1384.         l_err = g_strdup_printf(_("\nError: Keyframe %d at point [%d] leaves not enough space (frames)"
  1385.                                   "\nfor the previous controlpoints")
  1386.                       , pvals->point[l_idx].keyframe_abs, l_idx+1);
  1387.         l_err_lbltext = g_strdup_printf("%s%s", l_err_lbltext, l_err);
  1388.         g_free(l_err);
  1389.         l_errcount++;
  1390.      }
  1391.      
  1392.          if(pvals->point[l_idx].keyframe <= l_prev_keyframe)
  1393.      {
  1394.         l_err = g_strdup_printf(_("\nError: Keyframe %d is not in sequence at point [%d]")
  1395.                                  , pvals->point[l_idx].keyframe_abs, l_idx+1);
  1396.         l_err_lbltext = g_strdup_printf("%s%s", l_err_lbltext, l_err);
  1397.         g_free(l_err);
  1398.         l_errcount++;
  1399.      }
  1400.  
  1401.          l_prev_keyframe = pvals->point[l_idx].keyframe;
  1402.      if(l_prev_keyframe > l_prev_frame)
  1403.      {
  1404.        l_prev_frame = l_prev_keyframe +1;
  1405.      }
  1406.      }
  1407.      else
  1408.      {
  1409.     l_prev_frame++;
  1410.     if(l_prev_frame +1 > l_affected_frames)
  1411.     {
  1412.         l_err = g_strdup_printf(_("\nError: controlpoint [%d] is out of handled framerange"), l_idx+1);
  1413.         l_err_lbltext = g_strdup_printf("%s%s", l_err_lbltext, l_err);
  1414.         g_free(l_err);
  1415.         l_errcount++;
  1416.     }
  1417.      }
  1418.      if(l_errcount > 10)
  1419.      {
  1420.        break;
  1421.      }
  1422.   }
  1423.  
  1424.   if(pvals->point_idx_max + 1 > l_affected_frames)
  1425.   {
  1426.     l_err = g_strdup_printf(_("\nError: more controlpoints (%d) than handled frames (%d)"
  1427.                               "\nplease reduce controlpoints or select more frames"),
  1428.                               (int)pvals->point_idx_max+1, (int)l_affected_frames);
  1429.     l_err_lbltext = g_strdup_printf("%s%s", l_err_lbltext, l_err);
  1430.     g_free(l_err);
  1431.   }
  1432.  
  1433.   return(l_err_lbltext);
  1434. }    /* end p_gap_chk_keyframes */
  1435.  
  1436.  
  1437. /* ============================================================================
  1438.  * p_check_move_path_params
  1439.  *   check the parameters for noninteractive call of MovePath
  1440.  *   return 0 (OK)  or -1 (Error)
  1441.  * ============================================================================
  1442.  */
  1443. static gint
  1444. p_check_move_path_params(t_mov_data *mov_data)
  1445. {
  1446.   gchar *l_err_lbltext;
  1447.   gint   l_rc;
  1448.  
  1449.   l_rc = 0;  /* assume OK */
  1450.  
  1451.   /* range params valid ? */
  1452.   if(MIN(mov_data->val_ptr->dst_range_start, mov_data->val_ptr->dst_range_end)
  1453.       < mov_data->dst_ainfo_ptr->first_frame_nr)
  1454.   {
  1455.      printf("Error: Range starts before first frame number %d\n",
  1456.              (int)mov_data->dst_ainfo_ptr->first_frame_nr);
  1457.      l_rc = -1;
  1458.   }
  1459.  
  1460.   if(MAX(mov_data->val_ptr->dst_range_start, mov_data->val_ptr->dst_range_end)
  1461.       > mov_data->dst_ainfo_ptr->last_frame_nr)
  1462.   {
  1463.      printf("Error: Range ends after last frame number %d\n",
  1464.              (int)mov_data->dst_ainfo_ptr->last_frame_nr);
  1465.      l_rc = -1;
  1466.   }
  1467.   
  1468.   /* is there a valid source object ? */
  1469.   if(mov_data->val_ptr->src_layer_id < 0)
  1470.   {
  1471.      printf("Error: the passed src_layer_id %d  is invalid\n",
  1472.              (int)mov_data->val_ptr->src_layer_id);
  1473.      l_rc = -1;
  1474.   }
  1475.   else if(gimp_drawable_is_layer(mov_data->val_ptr->src_layer_id))
  1476.   {
  1477.      mov_data->val_ptr->src_image_id = gimp_layer_get_image_id(mov_data->val_ptr->src_layer_id);
  1478.   }
  1479.   else
  1480.   {
  1481.      printf("Error: the passed src_layer_id %d  is no Layer\n",
  1482.              (int)mov_data->val_ptr->src_layer_id);
  1483.      l_rc = -1;
  1484.   }
  1485.   
  1486.   /* keyframes OK ? */
  1487.   l_err_lbltext = p_gap_chk_keyframes(mov_data->val_ptr);
  1488.   if (*l_err_lbltext != '\0')
  1489.   {
  1490.      printf("Error in Keyframe settings: %s\n", l_err_lbltext);
  1491.      l_rc = -1;
  1492.   }
  1493.   g_free(l_err_lbltext);
  1494.   
  1495.   return (l_rc);
  1496. }    /* end p_check_move_path_params */
  1497.  
  1498.  
  1499. /* ============================================================================
  1500.  * gap_move_path
  1501.  * ============================================================================
  1502.  */
  1503. int
  1504. gap_move_path(GimpRunModeType run_mode, gint32 image_id, t_mov_values *pvals, gchar *pointfile
  1505.              , gint rotation_follow , gint32 startangle)
  1506. {
  1507.   int l_rc;
  1508.   t_anim_info *ainfo_ptr;
  1509.   t_mov_data  l_mov_data;
  1510.  
  1511.   l_rc = -1;
  1512.   ainfo_ptr = p_alloc_ainfo(image_id, run_mode);
  1513.   if(ainfo_ptr != NULL)
  1514.   {
  1515.     l_mov_data.val_ptr = pvals;
  1516.     if(NULL != l_mov_data.val_ptr)
  1517.     {
  1518.       if (0 == p_dir_ainfo(ainfo_ptr))
  1519.       {
  1520.         if(0 != p_chk_framerange(ainfo_ptr))   return -1;
  1521.  
  1522.         l_mov_data.val_ptr->cache_src_image_id = -1;
  1523.         l_mov_data.dst_ainfo_ptr = ainfo_ptr;
  1524.         if(run_mode == GIMP_RUN_NONINTERACTIVE)
  1525.         {
  1526.            l_rc = 0;
  1527.  
  1528.        /* get controlpoints from pointfile */
  1529.        if (pointfile != NULL)
  1530.        {
  1531.          l_rc = p_gap_load_pointfile(pointfile, pvals);
  1532.          if (l_rc < 0)
  1533.          {
  1534.            printf("Execution Error: could not load MovePath controlpoints from file: %s\n",
  1535.                    pointfile);
  1536.          }
  1537.        }
  1538.        
  1539.        if(l_rc >= 0)
  1540.        {
  1541.           l_rc = p_check_move_path_params(&l_mov_data);
  1542.        }
  1543.        
  1544.        /* Automatic calculation of rotation values */
  1545.        if((rotation_follow > 0) && (l_rc == 0))
  1546.        {
  1547.               p_calculate_rotate_follow(pvals, startangle);
  1548.        }
  1549.         }
  1550.         else
  1551.         {
  1552.        /* Dialog for GIMP_RUN_INTERACTIVE 
  1553.         * (and for GIMP_RUN_WITH_LAST_VALS that is not really supported here)
  1554.         */
  1555.            l_rc = p_move_dialog (&l_mov_data);
  1556.            if(0 != p_chk_framechange(ainfo_ptr))
  1557.            {
  1558.               l_rc = -1;
  1559.            }
  1560.         }
  1561.  
  1562.         if(l_rc >= 0)
  1563.         {
  1564.            l_rc = p_save_named_frame(ainfo_ptr->image_id, ainfo_ptr->old_filename);
  1565.            if(l_rc >= 0)
  1566.            {
  1567.               l_rc = p_mov_execute(&l_mov_data);
  1568.            
  1569.               /* go back to the frame_nr where move operation was started from */
  1570.               p_load_named_frame(ainfo_ptr->image_id, ainfo_ptr->old_filename);
  1571.            }
  1572.         }
  1573.  
  1574.         if(l_mov_data.val_ptr->cache_tmp_image_id >= 0)
  1575.         {
  1576.        if(gap_debug)
  1577.        {
  1578.           printf("gap_move: DELETE cache_tmp_image_id:%d\n",
  1579.                    (int)l_mov_data.val_ptr->cache_tmp_image_id);
  1580.            }
  1581.            /* destroy the cached frame image */
  1582.            gimp_image_delete(l_mov_data.val_ptr->cache_tmp_image_id);
  1583.         }
  1584.       }
  1585.  
  1586.     }
  1587.  
  1588.     p_free_ainfo(&ainfo_ptr);
  1589.   }
  1590.   
  1591.   return(l_rc);    
  1592. }    /* end gap_move_path */
  1593.