2.50: svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r18677...
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Tue, 17 Mar 2009 21:44:58 +0000 (21:44 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Tue, 17 Mar 2009 21:44:58 +0000 (21:44 +0000)
Notes:
* Sequence transform strip uses G.scene global, this is commented
  out now, should be fixed.
* Etch-a-ton code was most difficult to merge. The files already in
  2.5 got merged, but no new files were added. Calls to these files
  are commented out with "XXX etch-a-ton". editarmature.c and
  transform_snap.c were complex to merge. Martin, please check?
* Game engine compiles and links again here for scons/make/cmake
  (player still fails to link).

99 files changed:
1  2 
CMakeLists.txt
SConstruct
extern/SConscript
extern/bullet2/src/SConscript
extern/libopenjpeg/SConscript
intern/decimation/SConscript
intern/ghost/intern/GHOST_SystemX11.cpp
projectfiles_vc9/blender/imbuf/BL_imbuf.vcproj
projectfiles_vc9/blender/nodes/nodes.vcproj
projectfiles_vc9/gameengine/videotexture/TEX_Video.vcproj
source/Makefile
source/blender/Makefile
source/blender/blenkernel/BKE_node.h
source/blender/blenkernel/CMakeLists.txt
source/blender/blenkernel/SConscript
source/blender/blenkernel/intern/Makefile
source/blender/blenkernel/intern/modifier.c
source/blender/blenkernel/intern/node.c
source/blender/blenkernel/intern/object.c
source/blender/blenkernel/intern/particle_system.c
source/blender/blenkernel/intern/seqeffects.c
source/blender/blenkernel/intern/sequence.c
source/blender/blenkernel/intern/softbody.c
source/blender/blenlib/BLI_arithb.h
source/blender/blenlib/intern/arithb.c
source/blender/blenlib/intern/bpath.c
source/blender/blenlib/intern/graph.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/editors/CMakeLists.txt
source/blender/editors/armature/armature_intern.h
source/blender/editors/armature/editarmature.c
source/blender/editors/armature/reeb.h
source/blender/editors/curve/editcurve.c
source/blender/editors/gpencil/gpencil.c
source/blender/editors/include/BIF_transform.h
source/blender/editors/include/ED_armature.h
source/blender/editors/include/ED_view3d.h
source/blender/editors/interface/interface.c
source/blender/editors/sculpt_paint/paint_image.c
source/blender/editors/space_buttons/SConscript
source/blender/editors/space_file/Makefile
source/blender/editors/space_image/image_panels.c
source/blender/editors/space_info/SConscript
source/blender/editors/space_sequencer/sequencer_edit.c
source/blender/editors/space_view3d/drawmesh.c
source/blender/editors/space_view3d/drawobject.c
source/blender/editors/space_view3d/view3d_buttons.c
source/blender/editors/space_view3d/view3d_draw.c
source/blender/editors/space_view3d/view3d_header.c
source/blender/editors/space_view3d/view3d_view.c
source/blender/editors/transform/transform_conversions.c
source/blender/editors/transform/transform_snap.c
source/blender/editors/uvedit/uvedit_draw.c
source/blender/gpu/GPU_draw.h
source/blender/gpu/intern/gpu_draw.c
source/blender/imbuf/CMakeLists.txt
source/blender/imbuf/intern/cineon/cineon_dpx.c
source/blender/imbuf/intern/cineon/dpxlib.c
source/blender/makesdna/DNA_curve_types.h
source/blender/makesdna/DNA_object_types.h
source/blender/makesdna/DNA_scene_types.h
source/blender/makesdna/DNA_space_types.h
source/blender/nodes/intern/CMP_nodes/CMP_blur.c
source/blender/yafray/intern/export_ri.cpp
source/creator/CMakeLists.txt
source/creator/Makefile
source/creator/creator.c
source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
source/gameengine/BlenderRoutines/CMakeLists.txt
source/gameengine/BlenderRoutines/Makefile
source/gameengine/BlenderRoutines/SConscript
source/gameengine/Converter/BL_ActionActuator.cpp
source/gameengine/Converter/BL_BlenderDataConversion.cpp
source/gameengine/Converter/BL_ShapeActionActuator.cpp
source/gameengine/Converter/KX_BlenderSceneConverter.cpp
source/gameengine/Converter/KX_ConvertSensors.cpp
source/gameengine/Converter/SConscript
source/gameengine/Expressions/SConscript
source/gameengine/GameLogic/SConscript
source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
source/gameengine/GamePlayer/ghost/SConscript
source/gameengine/Ketsji/KXNetwork/SConscript
source/gameengine/Ketsji/KX_CameraActuator.cpp
source/gameengine/Ketsji/KX_PythonInit.cpp
source/gameengine/Ketsji/SConscript
source/gameengine/Physics/Bullet/SConscript
source/gameengine/Physics/common/SConscript
source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript
source/gameengine/Rasterizer/SConscript
source/gameengine/SConscript
source/gameengine/SceneGraph/SConscript
source/gameengine/VideoTexture/CMakeLists.txt
source/gameengine/VideoTexture/Makefile
source/gameengine/VideoTexture/SConscript
source/kernel/SConscript
source/nan_definitions.mk
tools/Blender.py
tools/btools.py

diff --cc CMakeLists.txt
@@@ -62,7 -63,7 +62,8 @@@ OPTION(WITH_QUICKTIME         "Enable Quicktim
  OPTION(WITH_OPENEXR           "Enable OpenEXR Support (http://www.openexr.com)"       ON)
  OPTION(WITH_DDS                       "Enable DDS Support"                                    ON)
  OPTION(WITH_FFMPEG            "Enable FFMPeg Support (http://ffmpeg.mplayerhq.hu/)"   OFF)
 +OPTION(WITH_PYTHON            "Enable Embedded Python API"                            ON)
+ OPTION(WITH_OPENJPEG          "Enable OpenJpeg Support (http://www.openjpeg.org/)"    OFF)
  OPTION(WITH_OPENAL            "Enable OpenAL Support (http://www.openal.org)"         ON)
  OPTION(WITH_OPENMP            "Enable OpenMP (has to be supported by the compiler)"   OFF)
  OPTION(WITH_WEBPLUGIN         "Enable Web Plugin (Unix only)"                         OFF)
diff --cc SConstruct
Simple merge
Simple merge
@@@ -7,10 -7,10 +7,10 @@@ Import('env'
  defs = 'USE_DOUBLES QHULL _LIB'
  cflags = []
  
 -if env['OURPLATFORM']=='win32-vc':
 +if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
      defs += ' WIN32 NDEBUG _WINDOWS _LIB'
      #cflags += ['/MT', '/W3', '/GX', '/O2', '/Op']
-     cflags += ['/MT', '/W3', '/GX', '/Og', '/Ot', '/Ob1', '/Op', '/G6']
+     cflags += ['/MT', '/W3', '/GX', '/Og', '/Ot', '/Ob1', '/Op', '/G6', '/O3']
  elif env['OURPLATFORM']=='win32-mingw':
      defs += ' NDEBUG'
      cflags += ['-O2']
Simple merge
@@@ -5,4 -5,4 +5,4 @@@ sources = env.Glob('intern/*.cpp'
  
  incs = '. ../moto/include ../container ../memutil'
  
- env.BlenderLib ('bf_decimation', sources, Split(incs) , [], libtype=['intern', 'player'], priority = [10, 20] )
 -env.BlenderLib ('bf_decimation', sources, Split(incs) , [], libtype=['core','common'], priority = [10, 20] )
++env.BlenderLib ('bf_decimation', sources, Split(incs) , [], libtype=['core'], priority = [10] )
@@@ -1025,9 -996,11 +1025,11 @@@ getClipboard(bool selectio
  
        clip_String = XInternAtom(m_display, "_BLENDER_STRING", False);
        compound_text = XInternAtom(m_display, "COMPOUND_TEXT", False);
+       a_text= XInternAtom(m_display, "TEXT", False);
+       a_string= XInternAtom(m_display, "STRING", False);
  
        //lets check the owner and if it is us then return the static buffer
 -      if(flag == 0) {
 +      if(!selection) {
                Primary_atom = XInternAtom(m_display, "CLIPBOARD", False);
                owner = XGetSelectionOwner(m_display, Primary_atom);
                if (owner == m_window) {
@@@ -42,7 -42,7 +42,7 @@@
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="0"\r
-                               AdditionalIncludeDirectories="..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\lib\windows\ffmpeg\include;..\..\..\source\gameengine\Ketsji;..\..\..\source\gameengine\Expressions;..\..\..\source\gameengine\GameLogic;..\..\..\source\gameengine\SceneGraph;..\..\..\source\gameengine\Rasterizer;..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer;..\..\..\source\gameengine\BlenderRoutines;..\..\..\source\blender\editors\include;..\..\..\source\blender\blenlib;..\..\..\source\blender\blenkernel;..\..\..\source\blender\makesdna;..\..\..\source\blender\imbuf;..\..\..\source\blender\python;..\..\..\source\blender\gpu;..\..\..\source\kernel\gen_system;..\..\..\intern\string;..\..\..\intern\moto\include;..\..\..\intern\guardedalloc;..\..\..\intern\SoundSystem;..\..\..\extern\glew\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include"\r
 -                              AdditionalIncludeDirectories="..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\lib\windows\ffmpeg\include;..\..\..\..\lib\windows\pthreads\include;..\..\..\source\gameengine\Ketsji;..\..\..\source\gameengine\Expressions;..\..\..\source\gameengine\GameLogic;..\..\..\source\gameengine\SceneGraph;..\..\..\source\gameengine\Rasterizer;..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer;..\..\..\source\gameengine\BlenderRoutines;..\..\..\source\blender\include;..\..\..\source\blender\blenlib;..\..\..\source\blender\blenkernel;..\..\..\source\blender\makesdna;..\..\..\source\blender\imbuf;..\..\..\source\blender\python;..\..\..\source\blender\gpu;..\..\..\source\kernel\gen_system;..\..\..\intern\string;..\..\..\intern\moto\include;..\..\..\intern\guardedalloc;..\..\..\intern\SoundSystem;..\..\..\extern\glew\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include"\r
++                              AdditionalIncludeDirectories="..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\lib\windows\ffmpeg\include;..\..\..\..\lib\windows\pthreads\include;..\..\..\source\gameengine\Ketsji;..\..\..\source\gameengine\Expressions;..\..\..\source\gameengine\GameLogic;..\..\..\source\gameengine\SceneGraph;..\..\..\source\gameengine\Rasterizer;..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer;..\..\..\source\gameengine\BlenderRoutines;..\..\..\source\blender\editors\include;..\..\..\source\blender\blenlib;..\..\..\source\blender\blenkernel;..\..\..\source\blender\makesdna;..\..\..\source\blender\imbuf;..\..\..\source\blender\python;..\..\..\source\blender\gpu;..\..\..\source\kernel\gen_system;..\..\..\intern\string;..\..\..\intern\moto\include;..\..\..\intern\guardedalloc;..\..\..\intern\SoundSystem;..\..\..\extern\glew\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include"\r
                                PreprocessorDefinitions="WIN32;_DEBUG;_LIB;WITH_FFMPEG;__STDC_CONSTANT_MACROS"\r
                                StringPooling="false"\r
                                BasicRuntimeChecks="3"\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                InlineFunctionExpansion="1"\r
-                               AdditionalIncludeDirectories="..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\lib\windows\ffmpeg\include;..\..\..\source\gameengine\Ketsji;..\..\..\source\gameengine\Expressions;..\..\..\source\gameengine\GameLogic;..\..\..\source\gameengine\SceneGraph;..\..\..\source\gameengine\Rasterizer;..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer;..\..\..\source\gameengine\BlenderRoutines;..\..\..\source\blender\editors\include;..\..\..\source\blender\blenlib;..\..\..\source\blender\blenkernel;..\..\..\source\blender\makesdna;..\..\..\source\blender\imbuf;..\..\..\source\blender\python;..\..\..\source\blender\gpu;..\..\..\source\kernel\gen_system;..\..\..\intern\string;..\..\..\intern\moto\include;..\..\..\intern\guardedalloc;..\..\..\intern\SoundSystem;..\..\..\extern\glew\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include"\r
 -                              AdditionalIncludeDirectories="..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\lib\windows\ffmpeg\include;..\..\..\..\lib\windows\pthreads\include;..\..\..\source\gameengine\Ketsji;..\..\..\source\gameengine\Expressions;..\..\..\source\gameengine\GameLogic;..\..\..\source\gameengine\SceneGraph;..\..\..\source\gameengine\Rasterizer;..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer;..\..\..\source\gameengine\BlenderRoutines;..\..\..\source\blender\include;..\..\..\source\blender\blenlib;..\..\..\source\blender\blenkernel;..\..\..\source\blender\makesdna;..\..\..\source\blender\imbuf;..\..\..\source\blender\python;..\..\..\source\blender\gpu;..\..\..\source\kernel\gen_system;..\..\..\intern\string;..\..\..\intern\moto\include;..\..\..\intern\guardedalloc;..\..\..\intern\SoundSystem;..\..\..\extern\glew\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include"\r
++                              AdditionalIncludeDirectories="..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\lib\windows\ffmpeg\include;..\..\..\..\lib\windows\pthreads\include;..\..\..\source\gameengine\Ketsji;..\..\..\source\gameengine\Expressions;..\..\..\source\gameengine\GameLogic;..\..\..\source\gameengine\SceneGraph;..\..\..\source\gameengine\Rasterizer;..\..\..\source\gameengine\Rasterizer\RAS_OpenGLRasterizer;..\..\..\source\gameengine\BlenderRoutines;..\..\..\source\blender\editors\include;..\..\..\source\blender\blenlib;..\..\..\source\blender\blenkernel;..\..\..\source\blender\makesdna;..\..\..\source\blender\imbuf;..\..\..\source\blender\python;..\..\..\source\blender\gpu;..\..\..\source\kernel\gen_system;..\..\..\intern\string;..\..\..\intern\moto\include;..\..\..\intern\guardedalloc;..\..\..\intern\SoundSystem;..\..\..\extern\glew\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include"\r
                                PreprocessorDefinitions="WIN32;NDEBUG;_LIB;WITH_FFMPEG;__STDC_CONSTANT_MACROS"\r
                                StringPooling="true"\r
                                RuntimeLibrary="0"\r
diff --cc source/Makefile
@@@ -99,15 -101,11 +98,13 @@@ COMLIB += $(OCGDIR)/blender/nodes/$(DEB
  COMLIB += $(OCGDIR)/blender/imbuf/$(DEBUG_DIR)libimbuf.a
  COMLIB += $(OCGDIR)/blender/blenlib/$(DEBUG_DIR)libblenlib.a
  COMLIB += $(NAN_IKSOLVER)/lib/libiksolver.a
- COMLIB += $(NAN_OPENNL)/lib/$(DEBUG_DIR)libopennl.a
 +COMLIB += $(NAN_MOTO)/lib/libmoto.a
  COMLIB += $(NAN_SUPERLU)/lib/$(DEBUG_DIR)libsuperlu.a 
  COMLIB += $(OCGDIR)/blender/avi/$(DEBUG_DIR)libavi.a
  COMLIB += $(NAN_JPEG)/lib/libjpeg.a
  COMLIB += $(OCGDIR)/blender/gpu/$(DEBUG_DIR)libgpu.a
  COMLIB += $(NAN_GLEW)/lib/libglew.a
- COMLIB += $(NAN_ELBEEM)/lib/$(DEBUG_DIR)libelbeem.a
 +COMLIB += $(OCGDIR)/blender/blenfont/$(DEBUG_DIR)libblenfont.a
  
  ifneq ($(NAN_NO_KETSJI),true)
      COMLIB += $(OCGDIR)/gameengine/bloutines/$(DEBUG_DIR)libbloutines.a
@@@ -218,44 -232,11 +219,47 @@@ ifeq ($(WITH_OPENEXR), true
      COMLIB += $(NAN_OPENEXR_LIBS)
  endif
  
 +# note: space_api.a in begin of editors, screen.a in end
  PULIB = $(NAN_MOTO)/lib/libmoto.a
 -PULIB += $(NAN_ELBEEM)/lib/$(DEBUG_DIR)libelbeem.a
+ PULIB += $(NAN_DECIMATION)/lib/libdecimation.a
  PULIB += $(OCGDIR)/blender/readblenfile/$(DEBUG_DIR)libreadblenfile.a
 -PULIB += $(OCGDIR)/blender/src/$(DEBUG_DIR)libsrcpublisher.a
 +PULIB += $(OCGDIR)/blender/ed_space/libed_space.a
 +PULIB += $(OCGDIR)/blender/ed_sound/libed_sound.a
 +PULIB += $(OCGDIR)/blender/ed_action/libed_action.a
 +PULIB += $(OCGDIR)/blender/ed_nla/libed_nla.a
 +PULIB += $(OCGDIR)/blender/ed_script/libed_script.a
 +PULIB += $(OCGDIR)/blender/ed_text/libed_text.a
 +PULIB += $(OCGDIR)/blender/ed_sequencer/libed_sequencer.a
 +PULIB += $(OCGDIR)/blender/ed_file/libed_file.a
 +PULIB += $(OCGDIR)/blender/ed_info/libed_info.a
 +PULIB += $(OCGDIR)/blender/ed_buttons/libed_buttons.a
 +PULIB += $(OCGDIR)/blender/ed_node/libed_node.a
 +PULIB += $(OCGDIR)/blender/ed_graph/libed_graph.a
 +PULIB += $(OCGDIR)/blender/ed_outliner/libed_outliner.a
 +PULIB += $(OCGDIR)/blender/ed_time/libed_time.a
 +PULIB += $(OCGDIR)/blender/ed_preview/libed_preview.a
 +PULIB += $(OCGDIR)/blender/ed_view3d/libed_view3d.a
 +PULIB += $(OCGDIR)/blender/ed_interface/libed_interface.a
 +PULIB += $(OCGDIR)/blender/ed_object/libed_object.a
 +PULIB += $(OCGDIR)/blender/ed_curve/libed_curve.a
 +PULIB += $(OCGDIR)/blender/ed_armature/libed_armature.a
 +PULIB += $(OCGDIR)/blender/ed_mesh/libed_mesh.a
 +PULIB += $(OCGDIR)/blender/ed_sculpt_paint/libed_sculpt_paint.a
 +PULIB += $(OCGDIR)/blender/ed_physics/libed_physics.a
 +PULIB += $(OCGDIR)/blender/ed_animation/libed_animation.a
 +PULIB += $(OCGDIR)/blender/ed_transform/libed_transform.a
 +PULIB += $(OCGDIR)/blender/ed_util/libed_util.a
 +PULIB += $(OCGDIR)/blender/ed_datafiles/libed_datafiles.a
 +PULIB += $(OCGDIR)/blender/ed_image/libed_image.a
 +PULIB += $(OCGDIR)/blender/ed_uvedit/libed_uvedit.a
 +PULIB += $(OCGDIR)/blender/ed_screen/libed_screen.a
 +PULIB += $(OCGDIR)/blender/windowmanager/libwindowmanager.a
 +PULIB += $(OCGDIR)/blender/python/$(DEBUG_DIR)libpython.a
 +PULIB += $(OCGDIR)/blender/makesrna/$(DEBUG_DIR)librna.a
 +# note, no idea but it suddenly doesn't compile :(
 +PULIB += $(OCGDIR)/blender/blenlib/$(DEBUG_DIR)libblenlib.a
++PULIB += $(NAN_OPENNL)/lib/$(DEBUG_DIR)libopennl.a
++PULIB += $(NAN_ELBEEM)/lib/$(DEBUG_DIR)libelbeem.a
  
  ifeq ($(NAN_NO_KETSJI),true)
      PULIB += $(NAN_MOTO)/lib/libmoto.a
@@@ -44,6 -43,6 +44,11 @@@ ifeq ($(WITH_QUICKTIME), true
        DIRS += quicktime
  endif
  
++ifeq ($(WITH_OPENJPEG), true)
++    CFLAGS += -DWITH_OPENJPEG -I../../../../extern/libopenjpeg
++endif
++
++
  DIR = $(OCGDIR)/blender
  SOURCEDIR = source/blender
  TESTDIRS = deflate streamglue
Simple merge
Simple merge
@@@ -6374,23 -6377,14 +6374,14 @@@ static DerivedMesh * particleInstanceMo
        maxvert=totvert*totpart;
        maxface=totface*totpart;
  
 -      psys->lattice=psys_get_lattice(ob, psys);
 +      psys->lattice=psys_get_lattice(md->scene, ob, psys);
  
        if(psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED)){
-               float co[3];
-               for(i=0; i< totvert; i++){
-                       dm->getVertCo(dm,i,co);
-                       if(i==0){
-                               min_co=max_co=co[track];
-                       }
-                       else{
-                               if(co[track]<min_co)
-                                       min_co=co[track];
  
-                               if(co[track]>max_co)
-                                       max_co=co[track];
-                       }
-               }
+               float min_r[3], max_r[3];
+               dm->getMinMax(dm, min_r, max_r);                
+               min_co=min_r[track];
+               max_co=max_r[track];
        }
  
        result = CDDM_from_template(dm, maxvert,dm->getNumEdges(dm)*totpart,maxface);
@@@ -4387,7 -4352,7 +4387,7 @@@ static void particles_fluid_step(Scene 
                        gzf = gzopen(filename, "rb");
                        if (!gzf) {
                                snprintf(debugStrBuffer,256,"readFsPartData::error - Unable to open file for reading '%s' \n", filename); 
-                               elbeemDebugOut(debugStrBuffer);
 -                              //elbeemDebugOut(debugStrBuffer);
++                              // XXX bad level call elbeemDebugOut(debugStrBuffer);
                                return;
                        }
        
index 11f8dfd,0000000..9ea1159
mode 100644,000000..100644
--- /dev/null
@@@ -1,3149 -1,0 +1,3155 @@@
-                                     char *rect1, 
-                                     char *rect2, 
-                                     char *out)
 +/**
 + * $Id$
 + *
 + * ***** BEGIN GPL LICENSE BLOCK *****
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software Foundation,
 + * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 + *
 + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
 + * All rights reserved.
 + *
 + * Contributor(s): 
 + * - Blender Foundation, 2003-2009
 + * - Peter Schlaile <peter [at] schlaile [dot] de> 2005/2006
 + *
 + * ***** END GPL LICENSE BLOCK *****
 + */
 +
 +#include <string.h>
 +#include <math.h>
 +#include <stdlib.h>
 +
 +#include "MEM_guardedalloc.h"
 +#include "PIL_dynlib.h"
 +
 +#include "DNA_scene_types.h"
 +#include "DNA_sequence_types.h"
 +
 +#include "BLI_blenlib.h"
 +#include "BLI_arithb.h"
 +
 +#include "BKE_global.h"
 +#include "BKE_plugin_types.h"
 +#include "BKE_sequence.h"
 +#include "BKE_texture.h"
 +#include "BKE_utildefines.h"
 +
 +#include "IMB_imbuf_types.h"
 +#include "IMB_imbuf.h"
 +
 +/* **** XXX **** */
 +static void error() {}
 +
 +#define INT   96
 +#define FLO   128
 +
 +/* **** XXX **** */
 +
 +/* Glow effect */
 +enum {
 +      GlowR=0,
 +      GlowG=1,
 +      GlowB=2,
 +      GlowA=3
 +};
 +
 +
 +/* **********************************************************************
 +   PLUGINS
 +   ********************************************************************** */
 +
 +static void open_plugin_seq(PluginSeq *pis, const char *seqname)
 +{
 +      int (*version)();
 +      void* (*alloc_private)();
 +      char *cp;
 +
 +      /* to be sure: (is tested for) */
 +      pis->doit= 0;
 +      pis->pname= 0;
 +      pis->varstr= 0;
 +      pis->cfra= 0;
 +      pis->version= 0;
 +      pis->instance_private_data = 0;
 +
 +      /* clear the error list */
 +      PIL_dynlib_get_error_as_string(NULL);
 +
 +      /* if(pis->handle) PIL_dynlib_close(pis->handle); */
 +      /* pis->handle= 0; */
 +
 +      /* open the needed object */
 +      pis->handle= PIL_dynlib_open(pis->name);
 +      if(test_dlerr(pis->name, pis->name)) return;
 +
 +      if (pis->handle != 0) {
 +              /* find the address of the version function */
 +              version= (int (*)())PIL_dynlib_find_symbol(pis->handle, "plugin_seq_getversion");
 +              if (test_dlerr(pis->name, "plugin_seq_getversion")) return;
 +
 +              if (version != 0) {
 +                      pis->version= version();
 +                      if (pis->version >= 2 && pis->version <= 6) {
 +                              int (*info_func)(PluginInfo *);
 +                              PluginInfo *info= (PluginInfo*) MEM_mallocN(sizeof(PluginInfo), "plugin_info");
 +
 +                              info_func= (int (*)(PluginInfo *))PIL_dynlib_find_symbol(pis->handle, "plugin_getinfo");
 +
 +                              if(info_func == NULL) error("No info func");
 +                              else {
 +                                      info_func(info);
 +
 +                                      pis->pname= info->name;
 +                                      pis->vars= info->nvars;
 +                                      pis->cfra= info->cfra;
 +
 +                                      pis->varstr= info->varstr;
 +
 +                                      pis->doit= (void(*)(void))info->seq_doit;
 +                                      if (info->init)
 +                                              info->init();
 +                              }
 +                              MEM_freeN(info);
 +
 +                              cp= PIL_dynlib_find_symbol(pis->handle, "seqname");
 +                              if(cp) strncpy(cp, seqname, 21);
 +                      } else {
 +                              printf ("Plugin returned unrecognized version number\n");
 +                              return;
 +                      }
 +              }
 +              alloc_private = (void* (*)())PIL_dynlib_find_symbol(
 +                      pis->handle, "plugin_seq_alloc_private_data");
 +              if (alloc_private) {
 +                      pis->instance_private_data = alloc_private();
 +              }
 +              
 +              pis->current_private_data = (void**) 
 +                      PIL_dynlib_find_symbol(
 +                              pis->handle, "plugin_private_data");
 +      }
 +}
 +
 +static PluginSeq *add_plugin_seq(const char *str, const char *seqname)
 +{
 +      PluginSeq *pis;
 +      VarStruct *varstr;
 +      int a;
 +
 +      pis= MEM_callocN(sizeof(PluginSeq), "PluginSeq");
 +
 +      strncpy(pis->name, str, FILE_MAXDIR+FILE_MAXFILE);
 +      open_plugin_seq(pis, seqname);
 +
 +      if(pis->doit==0) {
 +              if(pis->handle==0) error("no plugin: %s", str);
 +              else error("in plugin: %s", str);
 +              MEM_freeN(pis);
 +              return 0;
 +      }
 +
 +      /* default values */
 +      varstr= pis->varstr;
 +      for(a=0; a<pis->vars; a++, varstr++) {
 +              if( (varstr->type & FLO)==FLO)
 +                      pis->data[a]= varstr->def;
 +              else if( (varstr->type & INT)==INT)
 +                      *((int *)(pis->data+a))= (int) varstr->def;
 +      }
 +
 +      return pis;
 +}
 +
 +static void free_plugin_seq(PluginSeq *pis)
 +{
 +      if(pis==0) return;
 +
 +      /* no PIL_dynlib_close: same plugin can be opened multiple times with 1 handle */
 +
 +      if (pis->instance_private_data) {
 +              void (*free_private)(void *);
 +
 +              free_private = (void (*)(void *))PIL_dynlib_find_symbol(
 +                      pis->handle, "plugin_seq_free_private_data");
 +              if (free_private) {
 +                      free_private(pis->instance_private_data);
 +              }
 +      }
 +
 +      MEM_freeN(pis);
 +}
 +
 +static void init_plugin(Sequence * seq, const char * fname)
 +{
 +      seq->plugin= (PluginSeq *)add_plugin_seq(fname, seq->name+2);
 +}
 +
 +/* 
 + * FIXME: should query plugin! Could be generator, that needs zero inputs...
 + */
 +static int num_inputs_plugin()
 +{
 +      return 1;
 +}
 +
 +static void load_plugin(Sequence * seq)
 +{
 +      if (seq) {
 +              open_plugin_seq(seq->plugin, seq->name+2);
 +      }
 +}
 +
 +static void copy_plugin(Sequence * dst, Sequence * src)
 +{
 +      if(src->plugin) {
 +              dst->plugin= MEM_dupallocN(src->plugin);
 +              open_plugin_seq(dst->plugin, dst->name+2);
 +      }
 +}
 +
 +static ImBuf * IMB_cast_away_list(ImBuf * i)
 +{
 +      if (!i) {
 +              return 0;
 +      }
 +      return (ImBuf*) (((void**) i) + 2);
 +}
 +
 +static void do_plugin_effect(Sequence * seq,int cfra,
 +                           float facf0, float facf1, int x, int y, 
 +                           struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
 +                           struct ImBuf *ibuf3, struct ImBuf *out)
 +{
 +      char *cp;
 +      int float_rendering;
 +      int use_temp_bufs = 0; /* Are needed since blur.c (and maybe some other
 +                                old plugins) do very bad stuff
 +                                with imbuf-internals */
 +
 +      if(seq->plugin && seq->plugin->doit) {
 +              
 +              if(seq->plugin->cfra) 
 +                      *(seq->plugin->cfra)= cfra;
 +// XXX                        *(seq->plugin->cfra)= frame_to_float(scene, cfra);
 +              
 +              cp = PIL_dynlib_find_symbol(
 +                      seq->plugin->handle, "seqname");
 +
 +              if(cp) strncpy(cp, seq->name+2, 22);
 +
 +              if (seq->plugin->current_private_data) {
 +                      *seq->plugin->current_private_data 
 +                              = seq->plugin->instance_private_data;
 +              }
 +
 +              float_rendering = (out->rect_float != NULL);
 +
 +              if (seq->plugin->version<=3 && float_rendering) {
 +                      use_temp_bufs = 1;
 +
 +                      if (ibuf1) {
 +                              ibuf1 = IMB_dupImBuf(ibuf1);
 +                              IMB_rect_from_float(ibuf1);
 +                              imb_freerectfloatImBuf(ibuf1);
 +                              ibuf1->flags &= ~IB_rectfloat;
 +                      }
 +                      if (ibuf2) {
 +                              ibuf2 = IMB_dupImBuf(ibuf2);
 +                              IMB_rect_from_float(ibuf2);
 +                              imb_freerectfloatImBuf(ibuf2);
 +                              ibuf2->flags &= ~IB_rectfloat;
 +                      } 
 +                      if (ibuf3) {
 +                              ibuf3 = IMB_dupImBuf(ibuf3);
 +                              IMB_rect_from_float(ibuf3);
 +                              imb_freerectfloatImBuf(ibuf3);
 +                              ibuf3->flags &= ~IB_rectfloat;
 +                      } 
 +                      if (!out->rect) imb_addrectImBuf(out);
 +                      imb_freerectfloatImBuf(out);
 +                      out->flags &= ~IB_rectfloat;
 +              }
 +
 +              if (seq->plugin->version<=2) {
 +                      if(ibuf1) IMB_convert_rgba_to_abgr(ibuf1);
 +                      if(ibuf2) IMB_convert_rgba_to_abgr(ibuf2);
 +                      if(ibuf3) IMB_convert_rgba_to_abgr(ibuf3);
 +              }
 +
 +              if (seq->plugin->version<=4) {
 +                      ((SeqDoit)seq->plugin->doit)(
 +                              seq->plugin->data, facf0, facf1, x, y,
 +                              IMB_cast_away_list(ibuf1), 
 +                              IMB_cast_away_list(ibuf2), 
 +                              IMB_cast_away_list(out), 
 +                              IMB_cast_away_list(ibuf3));
 +              } else {
 +                      ((SeqDoit)seq->plugin->doit)(
 +                              seq->plugin->data, facf0, facf1, x, y,
 +                              ibuf1, ibuf2, out, ibuf3);
 +              }
 +
 +              if (seq->plugin->version<=2) {
 +                      if (!use_temp_bufs) {
 +                              if(ibuf1) IMB_convert_rgba_to_abgr(ibuf1);
 +                              if(ibuf2) IMB_convert_rgba_to_abgr(ibuf2);
 +                              if(ibuf3) IMB_convert_rgba_to_abgr(ibuf3);
 +                      }
 +                      IMB_convert_rgba_to_abgr(out);
 +              }
 +              if (seq->plugin->version<=3 && float_rendering) {
 +                      IMB_float_from_rect(out);
 +              }
 +
 +              if (use_temp_bufs) {
 +                      if (ibuf1) IMB_freeImBuf(ibuf1);
 +                      if (ibuf2) IMB_freeImBuf(ibuf2);
 +                      if (ibuf3) IMB_freeImBuf(ibuf3);
 +              }
 +      }
 +}
 +
 +static int do_plugin_early_out(struct Sequence *seq,
 +                             float facf0, float facf1)
 +{
 +      return 0;
 +}
 +
 +static void free_plugin(struct Sequence * seq)
 +{
 +      free_plugin_seq(seq->plugin);
 +      seq->plugin = 0;
 +}
 +
 +/* **********************************************************************
 +   ALPHA OVER
 +   ********************************************************************** */
 +
 +static void init_alpha_over_or_under(Sequence * seq)
 +{
 +      Sequence * seq1 = seq->seq1;
 +      Sequence * seq2 = seq->seq2;
 +
 +      seq->seq2= seq1;
 +      seq->seq1= seq2;
 +}
 +
 +static void do_alphaover_effect_byte(float facf0, float facf1, int x, int y, 
 +                                   char * rect1, char *rect2, char *out)
 +{
 +      int fac2, mfac, fac, fac4;
 +      int xo, tempc;
 +      char *rt1, *rt2, *rt;
 +
 +      xo= x;
 +      rt1= (char *)rect1;
 +      rt2= (char *)rect2;
 +      rt= (char *)out;
 +
 +      fac2= (int)(256.0*facf0);
 +      fac4= (int)(256.0*facf1);
 +
 +      while(y--) {
 +
 +              x= xo;
 +              while(x--) {
 +
 +                      /* rt = rt1 over rt2  (alpha from rt1) */
 +
 +                      fac= fac2;
 +                      mfac= 256 - ( (fac2*rt1[3])>>8 );
 +
 +                      if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
 +                      else if(mfac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt1);
 +                      else {
 +                              tempc= ( fac*rt1[0] + mfac*rt2[0])>>8;
 +                              if(tempc>255) rt[0]= 255; else rt[0]= tempc;
 +                              tempc= ( fac*rt1[1] + mfac*rt2[1])>>8;
 +                              if(tempc>255) rt[1]= 255; else rt[1]= tempc;
 +                              tempc= ( fac*rt1[2] + mfac*rt2[2])>>8;
 +                              if(tempc>255) rt[2]= 255; else rt[2]= tempc;
 +                              tempc= ( fac*rt1[3] + mfac*rt2[3])>>8;
 +                              if(tempc>255) rt[3]= 255; else rt[3]= tempc;
 +                      }
 +                      rt1+= 4; rt2+= 4; rt+= 4;
 +              }
 +
 +              if(y==0) break;
 +              y--;
 +
 +              x= xo;
 +              while(x--) {
 +
 +                      fac= fac4;
 +                      mfac= 256 - ( (fac4*rt1[3])>>8 );
 +
 +                      if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
 +                      else if(mfac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt1);
 +                      else {
 +                              tempc= ( fac*rt1[0] + mfac*rt2[0])>>8;
 +                              if(tempc>255) rt[0]= 255; else rt[0]= tempc;
 +                              tempc= ( fac*rt1[1] + mfac*rt2[1])>>8;
 +                              if(tempc>255) rt[1]= 255; else rt[1]= tempc;
 +                              tempc= ( fac*rt1[2] + mfac*rt2[2])>>8;
 +                              if(tempc>255) rt[2]= 255; else rt[2]= tempc;
 +                              tempc= ( fac*rt1[3] + mfac*rt2[3])>>8;
 +                              if(tempc>255) rt[3]= 255; else rt[3]= tempc;
 +                      }
 +                      rt1+= 4; rt2+= 4; rt+= 4;
 +              }
 +      }
 +}
 +
 +static void do_alphaover_effect_float(float facf0, float facf1, int x, int y, 
 +                                    float * rect1, float *rect2, float *out)
 +{
 +      float fac2, mfac, fac, fac4;
 +      int xo;
 +      float *rt1, *rt2, *rt;
 +
 +      xo= x;
 +      rt1= rect1;
 +      rt2= rect2;
 +      rt= out;
 +
 +      fac2= facf0;
 +      fac4= facf1;
 +
 +      while(y--) {
 +
 +              x= xo;
 +              while(x--) {
 +
 +                      /* rt = rt1 over rt2  (alpha from rt1) */
 +
 +                      fac= fac2;
 +                      mfac= 1.0 - (fac2*rt1[3]) ;
 +
 +                      if(fac <= 0.0) {
 +                              memcpy(rt, rt2, 4 * sizeof(float));
 +                      } else if(mfac <=0) {
 +                              memcpy(rt, rt1, 4 * sizeof(float));
 +                      } else {
 +                              rt[0] = fac*rt1[0] + mfac*rt2[0];
 +                              rt[1] = fac*rt1[1] + mfac*rt2[1];
 +                              rt[2] = fac*rt1[2] + mfac*rt2[2];
 +                              rt[3] = fac*rt1[3] + mfac*rt2[3];
 +                      }
 +                      rt1+= 4; rt2+= 4; rt+= 4;
 +              }
 +
 +              if(y==0) break;
 +              y--;
 +
 +              x= xo;
 +              while(x--) {
 +
 +                      fac= fac4;
 +                      mfac= 1.0 - (fac4*rt1[3]);
 +
 +                      if(fac <= 0.0) {
 +                              memcpy(rt, rt2, 4 * sizeof(float));
 +                      } else if(mfac <= 0.0) {
 +                              memcpy(rt, rt1, 4 * sizeof(float));
 +                      } else {
 +                              rt[0] = fac*rt1[0] + mfac*rt2[0];
 +                              rt[1] = fac*rt1[1] + mfac*rt2[1];
 +                              rt[2] = fac*rt1[2] + mfac*rt2[2];
 +                              rt[3] = fac*rt1[3] + mfac*rt2[3];
 +                      }
 +                      rt1+= 4; rt2+= 4; rt+= 4;
 +              }
 +      }
 +}
 +
 +static void do_alphaover_effect(Sequence * seq,int cfra,
 +                              float facf0, float facf1, int x, int y, 
 +                              struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
 +                              struct ImBuf *ibuf3, struct ImBuf *out)
 +{
 +      if (out->rect_float) {
 +              do_alphaover_effect_float(
 +                      facf0, facf1, x, y,
 +                      ibuf1->rect_float, ibuf2->rect_float,
 +                      out->rect_float);
 +      } else {
 +              do_alphaover_effect_byte(
 +                      facf0, facf1, x, y,
 +                      (char*) ibuf1->rect, (char*) ibuf2->rect,
 +                      (char*) out->rect);
 +      }
 +}
 +
 +
 +/* **********************************************************************
 +   ALPHA UNDER
 +   ********************************************************************** */
 +
 +void do_alphaunder_effect_byte(
 +      float facf0, float facf1, int x, int y, char *rect1, 
 +      char *rect2, char *out)
 +{
 +      int fac2, mfac, fac, fac4;
 +      int xo;
 +      char *rt1, *rt2, *rt;
 +
 +      xo= x;
 +      rt1= rect1;
 +      rt2= rect2;
 +      rt= out;
 +
 +      fac2= (int)(256.0*facf0);
 +      fac4= (int)(256.0*facf1);
 +
 +      while(y--) {
 +
 +              x= xo;
 +              while(x--) {
 +
 +                      /* rt = rt1 under rt2  (alpha from rt2) */
 +
 +                      /* this complex optimalisation is because the
 +                       * 'skybuf' can be crossed in
 +                       */
 +                      if(rt2[3]==0 && fac2==256) *( (unsigned int *)rt) = *( (unsigned int *)rt1);
 +                      else if(rt2[3]==255) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
 +                      else {
 +                              mfac= rt2[3];
 +                              fac= (fac2*(256-mfac))>>8;
 +
 +                              if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
 +                              else {
 +                                      rt[0]= ( fac*rt1[0] + mfac*rt2[0])>>8;
 +                                      rt[1]= ( fac*rt1[1] + mfac*rt2[1])>>8;
 +                                      rt[2]= ( fac*rt1[2] + mfac*rt2[2])>>8;
 +                                      rt[3]= ( fac*rt1[3] + mfac*rt2[3])>>8;
 +                              }
 +                      }
 +                      rt1+= 4; rt2+= 4; rt+= 4;
 +              }
 +
 +              if(y==0) break;
 +              y--;
 +
 +              x= xo;
 +              while(x--) {
 +
 +                      if(rt2[3]==0 && fac4==256) *( (unsigned int *)rt) = *( (unsigned int *)rt1);
 +                      else if(rt2[3]==255) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
 +                      else {
 +                              mfac= rt2[3];
 +                              fac= (fac4*(256-mfac))>>8;
 +
 +                              if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
 +                              else {
 +                                      rt[0]= ( fac*rt1[0] + mfac*rt2[0])>>8;
 +                                      rt[1]= ( fac*rt1[1] + mfac*rt2[1])>>8;
 +                                      rt[2]= ( fac*rt1[2] + mfac*rt2[2])>>8;
 +                                      rt[3]= ( fac*rt1[3] + mfac*rt2[3])>>8;
 +                              }
 +                      }
 +                      rt1+= 4; rt2+= 4; rt+= 4;
 +              }
 +      }
 +}
 +
 +
 +static void do_alphaunder_effect_float(float facf0, float facf1, int x, int y, 
 +                                     float *rect1, float *rect2, 
 +                                     float *out)
 +{
 +      float fac2, mfac, fac, fac4;
 +      int xo;
 +      float *rt1, *rt2, *rt;
 +
 +      xo= x;
 +      rt1= rect1;
 +      rt2= rect2;
 +      rt= out;
 +
 +      fac2= facf0;
 +      fac4= facf1;
 +
 +      while(y--) {
 +
 +              x= xo;
 +              while(x--) {
 +
 +                      /* rt = rt1 under rt2  (alpha from rt2) */
 +
 +                      /* this complex optimalisation is because the
 +                       * 'skybuf' can be crossed in
 +                       */
 +                      if( rt2[3]<=0 && fac2>=1.0) {
 +                              memcpy(rt, rt1, 4 * sizeof(float));
 +                      } else if(rt2[3]>=1.0) {
 +                              memcpy(rt, rt2, 4 * sizeof(float));
 +                      } else {
 +                              mfac = rt2[3];
 +                              fac = fac2 * (1.0 - mfac);
 +
 +                              if(fac == 0) {
 +                                      memcpy(rt, rt2, 4 * sizeof(float));
 +                              } else {
 +                                      rt[0]= fac*rt1[0] + mfac*rt2[0];
 +                                      rt[1]= fac*rt1[1] + mfac*rt2[1];
 +                                      rt[2]= fac*rt1[2] + mfac*rt2[2];
 +                                      rt[3]= fac*rt1[3] + mfac*rt2[3];
 +                              }
 +                      }
 +                      rt1+= 4; rt2+= 4; rt+= 4;
 +              }
 +
 +              if(y==0) break;
 +              y--;
 +
 +              x= xo;
 +              while(x--) {
 +
 +                      if(rt2[3]<=0 && fac4 >= 1.0) {
 +                              memcpy(rt, rt1, 4 * sizeof(float));
 + 
 +                      } else if(rt2[3]>=1.0) {
 +                              memcpy(rt, rt2, 4 * sizeof(float));
 +                      } else {
 +                              mfac= rt2[3];
 +                              fac= fac4*(1.0-mfac);
 +
 +                              if(fac == 0) {
 +                                      memcpy(rt, rt2, 4 * sizeof(float));
 +                              } else {
 +                                      rt[0]= fac * rt1[0] + mfac * rt2[0];
 +                                      rt[1]= fac * rt1[1] + mfac * rt2[1];
 +                                      rt[2]= fac * rt1[2] + mfac * rt2[2];
 +                                      rt[3]= fac * rt1[3] + mfac * rt2[3];
 +                              }
 +                      }
 +                      rt1+= 4; rt2+= 4; rt+= 4;
 +              }
 +      }
 +}
 +
 +static void do_alphaunder_effect(Sequence * seq,int cfra,
 +                              float facf0, float facf1, int x, int y, 
 +                              struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
 +                              struct ImBuf *ibuf3, struct ImBuf *out)
 +{
 +      if (out->rect_float) {
 +              do_alphaunder_effect_float(
 +                      facf0, facf1, x, y,
 +                      ibuf1->rect_float, ibuf2->rect_float,
 +                      out->rect_float);
 +      } else {
 +              do_alphaunder_effect_byte(
 +                      facf0, facf1, x, y,
 +                      (char*) ibuf1->rect, (char*) ibuf2->rect,
 +                      (char*) out->rect);
 +      }
 +}
 +
 +
 +/* **********************************************************************
 +   CROSS
 +   ********************************************************************** */
 +
 +void do_cross_effect_byte(float facf0, float facf1, int x, int y, 
 +                        char *rect1, char *rect2, 
 +                        char *out)
 +{
 +      int fac1, fac2, fac3, fac4;
 +      int xo;
 +      char *rt1, *rt2, *rt;
 +
 +      xo= x;
 +      rt1= rect1;
 +      rt2= rect2;
 +      rt= out;
 +
 +      fac2= (int)(256.0*facf0);
 +      fac1= 256-fac2;
 +      fac4= (int)(256.0*facf1);
 +      fac3= 256-fac4;
 +
 +      while(y--) {
 +
 +              x= xo;
 +              while(x--) {
 +
 +                      rt[0]= (fac1*rt1[0] + fac2*rt2[0])>>8;
 +                      rt[1]= (fac1*rt1[1] + fac2*rt2[1])>>8;
 +                      rt[2]= (fac1*rt1[2] + fac2*rt2[2])>>8;
 +                      rt[3]= (fac1*rt1[3] + fac2*rt2[3])>>8;
 +
 +                      rt1+= 4; rt2+= 4; rt+= 4;
 +              }
 +
 +              if(y==0) break;
 +              y--;
 +
 +              x= xo;
 +              while(x--) {
 +
 +                      rt[0]= (fac3*rt1[0] + fac4*rt2[0])>>8;
 +                      rt[1]= (fac3*rt1[1] + fac4*rt2[1])>>8;
 +                      rt[2]= (fac3*rt1[2] + fac4*rt2[2])>>8;
 +                      rt[3]= (fac3*rt1[3] + fac4*rt2[3])>>8;
 +
 +                      rt1+= 4; rt2+= 4; rt+= 4;
 +              }
 +
 +      }
 +}
 +
 +void do_cross_effect_float(float facf0, float facf1, int x, int y, 
 +                         float *rect1, float *rect2, float *out)
 +{
 +      float fac1, fac2, fac3, fac4;
 +      int xo;
 +      float *rt1, *rt2, *rt;
 +
 +      xo= x;
 +      rt1= rect1;
 +      rt2= rect2;
 +      rt= out;
 +
 +      fac2= facf0;
 +      fac1= 1.0 - fac2;
 +      fac4= facf1;
 +      fac3= 1.0 - fac4;
 +
 +      while(y--) {
 +
 +              x= xo;
 +              while(x--) {
 +
 +                      rt[0]= fac1*rt1[0] + fac2*rt2[0];
 +                      rt[1]= fac1*rt1[1] + fac2*rt2[1];
 +                      rt[2]= fac1*rt1[2] + fac2*rt2[2];
 +                      rt[3]= fac1*rt1[3] + fac2*rt2[3];
 +
 +                      rt1+= 4; rt2+= 4; rt+= 4;
 +              }
 +
 +              if(y==0) break;
 +              y--;
 +
 +              x= xo;
 +              while(x--) {
 +
 +                      rt[0]= fac3*rt1[0] + fac4*rt2[0];
 +                      rt[1]= fac3*rt1[1] + fac4*rt2[1];
 +                      rt[2]= fac3*rt1[2] + fac4*rt2[2];
 +                      rt[3]= fac3*rt1[3] + fac4*rt2[3];
 +
 +                      rt1+= 4; rt2+= 4; rt+= 4;
 +              }
 +
 +      }
 +}
 +
 +/* carefull: also used by speed effect! */
 +
 +static void do_cross_effect(Sequence * seq,int cfra,
 +                          float facf0, float facf1, int x, int y, 
 +                          struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
 +                          struct ImBuf *ibuf3, struct ImBuf *out)
 +{
 +      if (out->rect_float) {
 +              do_cross_effect_float(
 +                      facf0, facf1, x, y,
 +                      ibuf1->rect_float, ibuf2->rect_float,
 +                      out->rect_float);
 +      } else {
 +              do_cross_effect_byte(
 +                      facf0, facf1, x, y,
 +                      (char*) ibuf1->rect, (char*) ibuf2->rect,
 +                      (char*) out->rect);
 +      }
 +}
 +
 +
 +/* **********************************************************************
 +   GAMMA CROSS
 +   ********************************************************************** */
 +
 +/* copied code from initrender.c */
 +static unsigned short gamtab[65536];
 +static unsigned short igamtab1[256];
 +static int gamma_tabs_init = FALSE;
 +
 +#define RE_GAMMA_TABLE_SIZE 400
 +
 +static float gamma_range_table[RE_GAMMA_TABLE_SIZE + 1];
 +static float gamfactor_table[RE_GAMMA_TABLE_SIZE];
 +static float inv_gamma_range_table[RE_GAMMA_TABLE_SIZE + 1];
 +static float inv_gamfactor_table[RE_GAMMA_TABLE_SIZE];
 +static float color_domain_table[RE_GAMMA_TABLE_SIZE + 1]; 
 +static float color_step;
 +static float inv_color_step;
 +static float valid_gamma;
 +static float valid_inv_gamma;
 +
 +static void makeGammaTables(float gamma)
 +{
 +      /* we need two tables: one forward, one backward */
 +      int i;
 +
 +      valid_gamma        = gamma;
 +      valid_inv_gamma    = 1.0 / gamma;
 +      color_step        = 1.0 / RE_GAMMA_TABLE_SIZE;
 +      inv_color_step    = (float) RE_GAMMA_TABLE_SIZE; 
 +
 +      /* We could squeeze out the two range tables to gain some memory.        */     
 +      for (i = 0; i < RE_GAMMA_TABLE_SIZE; i++) {
 +              color_domain_table[i]   = i * color_step;
 +              gamma_range_table[i]     = pow(color_domain_table[i],
 +                                                                              valid_gamma);
 +              inv_gamma_range_table[i] = pow(color_domain_table[i],
 +                                                                              valid_inv_gamma);
 +      }
 +
 +      /* The end of the table should match 1.0 carefully. In order to avoid    */
 +      /* rounding errors, we just set this explicitly. The last segment may    */
 +      /* have a different lenght than the other segments, but our              */
 +      /* interpolation is insensitive to that.                                 */
 +      color_domain_table[RE_GAMMA_TABLE_SIZE]   = 1.0;
 +      gamma_range_table[RE_GAMMA_TABLE_SIZE]     = 1.0;
 +      inv_gamma_range_table[RE_GAMMA_TABLE_SIZE] = 1.0;
 +
 +      /* To speed up calculations, we make these calc factor tables. They are  */
 +      /* multiplication factors used in scaling the interpolation.             */
 +      for (i = 0; i < RE_GAMMA_TABLE_SIZE; i++ ) {
 +              gamfactor_table[i] = inv_color_step
 +                      * (gamma_range_table[i + 1] - gamma_range_table[i]) ;
 +              inv_gamfactor_table[i] = inv_color_step
 +                      * (inv_gamma_range_table[i + 1] - inv_gamma_range_table[i]) ;
 +      }
 +
 +} /* end of void makeGammaTables(float gamma) */
 +
 +
 +static float gammaCorrect(float c)
 +{
 +      int i;
 +      float res = 0.0;
 +      
 +      i = floor(c * inv_color_step);
 +      /* Clip to range [0,1]: outside, just do the complete calculation.       */
 +      /* We may have some performance problems here. Stretching up the LUT     */
 +      /* may help solve that, by exchanging LUT size for the interpolation.    */
 +      /* Negative colors are explicitly handled.                              */
 +      if (i < 0) res = -pow(abs(c), valid_gamma);
 +      else if (i >= RE_GAMMA_TABLE_SIZE ) res = pow(c, valid_gamma);
 +      else res = gamma_range_table[i] + 
 +                       ( (c - color_domain_table[i]) * gamfactor_table[i]); 
 +      
 +      return res;
 +} /* end of float gammaCorrect(float col) */
 +
 +/* ------------------------------------------------------------------------- */
 +
 +static float invGammaCorrect(float col)
 +{
 +      int i;
 +      float res = 0.0;
 +
 +      i = floor(col*inv_color_step);
 +      /* Negative colors are explicitly handled.                              */
 +      if (i < 0) res = -pow(abs(col), valid_inv_gamma);
 +      else if (i >= RE_GAMMA_TABLE_SIZE) res = pow(col, valid_inv_gamma);
 +      else res = inv_gamma_range_table[i] + 
 +                       ( (col - color_domain_table[i]) * inv_gamfactor_table[i]);
 + 
 +      return res;
 +} /* end of float invGammaCorrect(float col) */
 +
 +
 +static void gamtabs(float gamma)
 +{
 +      float val, igamma= 1.0f/gamma;
 +      int a;
 +      
 +      /* gamtab: in short, out short */
 +      for(a=0; a<65536; a++) {
 +              val= a;
 +              val/= 65535.0;
 +              
 +              if(gamma==2.0) val= sqrt(val);
 +              else if(gamma!=1.0) val= pow(val, igamma);
 +              
 +              gamtab[a]= (65535.99*val);
 +      }
 +      /* inverse gamtab1 : in byte, out short */
 +      for(a=1; a<=256; a++) {
 +              if(gamma==2.0) igamtab1[a-1]= a*a-1;
 +              else if(gamma==1.0) igamtab1[a-1]= 256*a-1;
 +              else {
 +                      val= a/256.0;
 +                      igamtab1[a-1]= (65535.0*pow(val, gamma)) -1 ;
 +              }
 +      }
 +
 +}
 +
 +static void build_gammatabs()
 +{
 +      if (gamma_tabs_init == FALSE) {
 +              gamtabs(2.0f);
 +              makeGammaTables(2.0f);
 +              gamma_tabs_init = TRUE;
 +      }
 +}
 +
 +static void init_gammacross(Sequence * seq)
 +{
 +}
 +
 +static void load_gammacross(Sequence * seq)
 +{
 +}
 +
 +static void free_gammacross(Sequence * seq)
 +{
 +}
 +
 +static void do_gammacross_effect_byte(float facf0, float facf1, 
 +                                    int x, int y, 
-       char *rt1, *rt2, *rt;
++                                    unsigned char *rect1, 
++                                    unsigned char *rect2, 
++                                    unsigned char *out)
 +{
 +      int fac1, fac2, col;
 +      int xo;
-       rt1= (signed char *)rect1;
-       rt2= (signed char *)rect2;
-       rt= (signed char *)out;
++      unsigned char *rt1, *rt2, *rt;
 +      
 +      xo= x;
-               tx = scale->xIni+(xo / 2.0f) + (scale->xFin-(xo / 2.0f) - scale->xIni+(xo / 2.0f)) * facf0;
-               ty = scale->yIni+(yo / 2.0f) + (scale->yFin-(yo / 2.0f) - scale->yIni+(yo / 2.0f)) * facf0;
++      rt1= (unsigned char *)rect1;
++      rt2= (unsigned char *)rect2;
++      rt= (unsigned char *)out;
 +
 +      fac2= (int)(256.0*facf0);
 +      fac1= 256-fac2;
 +
 +      while(y--) {
 +
 +              x= xo;
 +              while(x--) {
 +
 +                      col= (fac1*igamtab1[rt1[0]] + fac2*igamtab1[rt2[0]])>>8;
 +                      if(col>65535) rt[0]= 255; else rt[0]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
 +                      col=(fac1*igamtab1[rt1[1]] + fac2*igamtab1[rt2[1]])>>8;
 +                      if(col>65535) rt[1]= 255; else rt[1]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
 +                      col= (fac1*igamtab1[rt1[2]] + fac2*igamtab1[rt2[2]])>>8;
 +                      if(col>65535) rt[2]= 255; else rt[2]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
 +                      col= (fac1*igamtab1[rt1[3]] + fac2*igamtab1[rt2[3]])>>8;
 +                      if(col>65535) rt[3]= 255; else rt[3]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
 +
 +                      rt1+= 4; rt2+= 4; rt+= 4;
 +              }
 +
 +              if(y==0) break;
 +              y--;
 +
 +              x= xo;
 +              while(x--) {
 +
 +                      col= (fac1*igamtab1[rt1[0]] + fac2*igamtab1[rt2[0]])>>8;
 +                      if(col>65535) rt[0]= 255; else rt[0]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
 +                      col= (fac1*igamtab1[rt1[1]] + fac2*igamtab1[rt2[1]])>>8;
 +                      if(col>65535) rt[1]= 255; else rt[1]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
 +                      col= (fac1*igamtab1[rt1[2]] + fac2*igamtab1[rt2[2]])>>8;
 +                      if(col>65535) rt[2]= 255; else rt[2]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
 +                      col= (fac1*igamtab1[rt1[3]] + fac2*igamtab1[rt2[3]])>>8;
 +                      if(col>65535) rt[3]= 255; else rt[3]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
 +
 +                      rt1+= 4; rt2+= 4; rt+= 4;
 +              }
 +      }
 +
 +}
 +
 +static void do_gammacross_effect_float(float facf0, float facf1, 
 +                                     int x, int y, 
 +                                     float *rect1, float *rect2, 
 +                                     float *out)
 +{
 +      float fac1, fac2;
 +      int xo;
 +      float *rt1, *rt2, *rt;
 +
 +      xo= x;
 +      rt1= rect1;
 +      rt2= rect2;
 +      rt= out;
 +
 +      fac2= facf0;
 +      fac1= 1.0 - fac2;
 +
 +      while(y--) {
 +
 +              x= xo * 4;
 +              while(x--) {
 +
 +                      *rt= gammaCorrect(
 +                              fac1 * invGammaCorrect(*rt1) 
 +                              + fac2 * invGammaCorrect(*rt2));
 +                      rt1++; rt2++; rt++;
 +              }
 +
 +              if(y==0) break;
 +              y--;
 +
 +              x= xo * 4;
 +              while(x--) {
 +
 +                      *rt= gammaCorrect(
 +                              fac1*invGammaCorrect(*rt1) 
 +                              + fac2*invGammaCorrect(*rt2));
 +
 +                      rt1++; rt2++; rt++;
 +              }
 +      }
 +}
 +
 +static void do_gammacross_effect(Sequence * seq,int cfra,
 +                               float facf0, float facf1, int x, int y, 
 +                               struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
 +                               struct ImBuf *ibuf3, struct ImBuf *out)
 +{
 +      build_gammatabs();
 +
 +      if (out->rect_float) {
 +              do_gammacross_effect_float(
 +                      facf0, facf1, x, y,
 +                      ibuf1->rect_float, ibuf2->rect_float,
 +                      out->rect_float);
 +      } else {
 +              do_gammacross_effect_byte(
 +                      facf0, facf1, x, y,
 +                      (char*) ibuf1->rect, (char*) ibuf2->rect,
 +                      (char*) out->rect);
 +      }
 +}
 +
 +
 +/* **********************************************************************
 +   ADD
 +   ********************************************************************** */
 +
 +static void do_add_effect_byte(float facf0, float facf1, int x, int y, 
 +                             unsigned char *rect1, unsigned char *rect2, 
 +                             unsigned char *out)
 +{
 +      int col, xo, fac1, fac3;
 +      char *rt1, *rt2, *rt;
 +
 +      xo= x;
 +      rt1= (char *)rect1;
 +      rt2= (char *)rect2;
 +      rt= (char *)out;
 +
 +      fac1= (int)(256.0*facf0);
 +      fac3= (int)(256.0*facf1);
 +
 +      while(y--) {
 +
 +              x= xo;
 +              while(x--) {
 +
 +                      col= rt1[0]+ ((fac1*rt2[0])>>8);
 +                      if(col>255) rt[0]= 255; else rt[0]= col;
 +                      col= rt1[1]+ ((fac1*rt2[1])>>8);
 +                      if(col>255) rt[1]= 255; else rt[1]= col;
 +                      col= rt1[2]+ ((fac1*rt2[2])>>8);
 +                      if(col>255) rt[2]= 255; else rt[2]= col;
 +                      col= rt1[3]+ ((fac1*rt2[3])>>8);
 +                      if(col>255) rt[3]= 255; else rt[3]= col;
 +
 +                      rt1+= 4; rt2+= 4; rt+= 4;
 +              }
 +
 +              if(y==0) break;
 +              y--;
 +
 +              x= xo;
 +              while(x--) {
 +
 +                      col= rt1[0]+ ((fac3*rt2[0])>>8);
 +                      if(col>255) rt[0]= 255; else rt[0]= col;
 +                      col= rt1[1]+ ((fac3*rt2[1])>>8);
 +                      if(col>255) rt[1]= 255; else rt[1]= col;
 +                      col= rt1[2]+ ((fac3*rt2[2])>>8);
 +                      if(col>255) rt[2]= 255; else rt[2]= col;
 +                      col= rt1[3]+ ((fac3*rt2[3])>>8);
 +                      if(col>255) rt[3]= 255; else rt[3]= col;
 +
 +                      rt1+= 4; rt2+= 4; rt+= 4;
 +              }
 +      }
 +}
 +
 +static void do_add_effect_float(float facf0, float facf1, int x, int y, 
 +                              float *rect1, float *rect2, 
 +                              float *out)
 +{
 +      int xo;
 +      float fac1, fac3;
 +      float *rt1, *rt2, *rt;
 +
 +      xo= x;
 +      rt1= rect1;
 +      rt2= rect2;
 +      rt= out;
 +
 +      fac1= facf0;
 +      fac3= facf1;
 +
 +      while(y--) {
 +
 +              x= xo * 4;
 +              while(x--) {
 +                      *rt = *rt1 + fac1 * (*rt2);
 +
 +                      rt1++; rt2++; rt++;
 +              }
 +
 +              if(y==0) break;
 +              y--;
 +
 +              x= xo * 4;
 +              while(x--) {
 +                      *rt = *rt1 + fac3 * (*rt2);
 +
 +                      rt1++; rt2++; rt++;
 +              }
 +      }
 +}
 +
 +static void do_add_effect(Sequence * seq,int cfra,
 +                        float facf0, float facf1, int x, int y, 
 +                        struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
 +                        struct ImBuf *ibuf3, struct ImBuf *out)
 +{
 +      if (out->rect_float) {
 +              do_add_effect_float(
 +                      facf0, facf1, x, y,
 +                      ibuf1->rect_float, ibuf2->rect_float,
 +                      out->rect_float);
 +      } else {
 +              do_add_effect_byte(
 +                      facf0, facf1, x, y,
 +                      (unsigned char*) ibuf1->rect, (unsigned char*) ibuf2->rect,
 +                      (unsigned char*) out->rect);
 +      }
 +}
 +
 +
 +/* **********************************************************************
 +   SUB
 +   ********************************************************************** */
 +
 +static void do_sub_effect_byte(float facf0, float facf1, 
 +                             int x, int y, 
 +                             char *rect1, char *rect2, char *out)
 +{
 +      int col, xo, fac1, fac3;
 +      char *rt1, *rt2, *rt;
 +
 +      xo= x;
 +      rt1= (char *)rect1;
 +      rt2= (char *)rect2;
 +      rt= (char *)out;
 +
 +      fac1= (int)(256.0*facf0);
 +      fac3= (int)(256.0*facf1);
 +
 +      while(y--) {
 +
 +              x= xo;
 +              while(x--) {
 +
 +                      col= rt1[0]- ((fac1*rt2[0])>>8);
 +                      if(col<0) rt[0]= 0; else rt[0]= col;
 +                      col= rt1[1]- ((fac1*rt2[1])>>8);
 +                      if(col<0) rt[1]= 0; else rt[1]= col;
 +                      col= rt1[2]- ((fac1*rt2[2])>>8);
 +                      if(col<0) rt[2]= 0; else rt[2]= col;
 +                      col= rt1[3]- ((fac1*rt2[3])>>8);
 +                      if(col<0) rt[3]= 0; else rt[3]= col;
 +
 +                      rt1+= 4; rt2+= 4; rt+= 4;
 +              }
 +
 +              if(y==0) break;
 +              y--;
 +
 +              x= xo;
 +              while(x--) {
 +
 +                      col= rt1[0]- ((fac3*rt2[0])>>8);
 +                      if(col<0) rt[0]= 0; else rt[0]= col;
 +                      col= rt1[1]- ((fac3*rt2[1])>>8);
 +                      if(col<0) rt[1]= 0; else rt[1]= col;
 +                      col= rt1[2]- ((fac3*rt2[2])>>8);
 +                      if(col<0) rt[2]= 0; else rt[2]= col;
 +                      col= rt1[3]- ((fac3*rt2[3])>>8);
 +                      if(col<0) rt[3]= 0; else rt[3]= col;
 +
 +                      rt1+= 4; rt2+= 4; rt+= 4;
 +              }
 +      }
 +}
 +
 +static void do_sub_effect_float(float facf0, float facf1, int x, int y, 
 +                              float *rect1, float *rect2, 
 +                              float *out)
 +{
 +      int xo;
 +      float fac1, fac3;
 +      float *rt1, *rt2, *rt;
 +
 +      xo= x;
 +      rt1= rect1;
 +      rt2= rect2;
 +      rt= out;
 +
 +      fac1= facf0;
 +      fac3= facf1;
 +
 +      while(y--) {
 +
 +              x= xo * 4;
 +              while(x--) {
 +                      *rt = *rt1 - fac1 * (*rt2);
 +
 +                      rt1++; rt2++; rt++;
 +              }
 +
 +              if(y==0) break;
 +              y--;
 +
 +              x= xo * 4;
 +              while(x--) {
 +                      *rt = *rt1 - fac3 * (*rt2);
 +
 +                      rt1++; rt2++; rt++;
 +              }
 +      }
 +}
 +
 +static void do_sub_effect(Sequence * seq,int cfra,
 +                        float facf0, float facf1, int x, int y, 
 +                        struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
 +                        struct ImBuf *ibuf3, struct ImBuf *out)
 +{
 +      if (out->rect_float) {
 +              do_sub_effect_float(
 +                      facf0, facf1, x, y,
 +                      ibuf1->rect_float, ibuf2->rect_float,
 +                      out->rect_float);
 +      } else {
 +              do_sub_effect_byte(
 +                      facf0, facf1, x, y,
 +                      (char*) ibuf1->rect, (char*) ibuf2->rect,
 +                      (char*) out->rect);
 +      }
 +}
 +
 +/* **********************************************************************
 +   DROP
 +   ********************************************************************** */
 +
 +/* Must be > 0 or add precopy, etc to the function */
 +#define XOFF  8
 +#define YOFF  8
 +
 +static void do_drop_effect_byte(float facf0, float facf1, int x, int y, 
 +                              unsigned char *rect2i, unsigned char *rect1i, 
 +                              unsigned char *outi)
 +{
 +      int height, width, temp, fac, fac1, fac2;
 +      char *rt1, *rt2, *out;
 +      int field= 1;
 +
 +      width= x;
 +      height= y;
 +
 +      fac1= (int)(70.0*facf0);
 +      fac2= (int)(70.0*facf1);
 +
 +      rt2= (char*) (rect2i + YOFF*width);
 +      rt1= (char*) rect1i;
 +      out= (char*) outi;
 +      for (y=0; y<height-YOFF; y++) {
 +              if(field) fac= fac1;
 +              else fac= fac2;
 +              field= !field;
 +
 +              memcpy(out, rt1, sizeof(int)*XOFF);
 +              rt1+= XOFF*4;
 +              out+= XOFF*4;
 +
 +              for (x=XOFF; x<width; x++) {
 +                      temp= ((fac*rt2[3])>>8);
 +
 +                      *(out++)= MAX2(0, *rt1 - temp); rt1++;
 +                      *(out++)= MAX2(0, *rt1 - temp); rt1++;
 +                      *(out++)= MAX2(0, *rt1 - temp); rt1++;
 +                      *(out++)= MAX2(0, *rt1 - temp); rt1++;
 +                      rt2+=4;
 +              }
 +              rt2+=XOFF*4;
 +      }
 +      memcpy(out, rt1, sizeof(int)*YOFF*width);
 +}
 +
 +static void do_drop_effect_float(float facf0, float facf1, int x, int y, 
 +                               float *rect2i, float *rect1i, 
 +                               float *outi)
 +{
 +      int height, width;
 +      float temp, fac, fac1, fac2;
 +      float *rt1, *rt2, *out;
 +      int field= 1;
 +
 +      width= x;
 +      height= y;
 +
 +      fac1= 70.0*facf0;
 +      fac2= 70.0*facf1;
 +
 +      rt2=  (rect2i + YOFF*width);
 +      rt1=  rect1i;
 +      out=  outi;
 +      for (y=0; y<height-YOFF; y++) {
 +              if(field) fac= fac1;
 +              else fac= fac2;
 +              field= !field;
 +
 +              memcpy(out, rt1, 4 * sizeof(float)*XOFF);
 +              rt1+= XOFF*4;
 +              out+= XOFF*4;
 +
 +              for (x=XOFF; x<width; x++) {
 +                      temp= fac * rt2[3];
 +
 +                      *(out++)= MAX2(0.0, *rt1 - temp); rt1++;
 +                      *(out++)= MAX2(0.0, *rt1 - temp); rt1++;
 +                      *(out++)= MAX2(0.0, *rt1 - temp); rt1++;
 +                      *(out++)= MAX2(0.0, *rt1 - temp); rt1++;
 +                      rt2+=4;
 +              }
 +              rt2+=XOFF*4;
 +      }
 +      memcpy(out, rt1, 4 * sizeof(float)*YOFF*width);
 +}
 +
 +
 +static void do_drop_effect(Sequence * seq,int cfra,
 +                         float facf0, float facf1, int x, int y, 
 +                         struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
 +                         struct ImBuf * ibuf3,
 +                         struct ImBuf *out)
 +{
 +      if (out->rect_float) {
 +              do_drop_effect_float(
 +                      facf0, facf1, x, y,
 +                      ibuf1->rect_float, ibuf2->rect_float,
 +                      out->rect_float);
 +      } else {
 +              do_drop_effect_byte(
 +                      facf0, facf1, x, y,
 +                      (unsigned char*) ibuf1->rect, (unsigned char*) ibuf2->rect,
 +                      (unsigned char*) out->rect);
 +      }
 +}
 +
 +/* **********************************************************************
 +   MUL
 +   ********************************************************************** */
 +
 +static void do_mul_effect_byte(float facf0, float facf1, int x, int y, 
 +                             unsigned char *rect1, unsigned char *rect2, 
 +                             unsigned char *out)
 +{
 +      int xo, fac1, fac3;
 +      char *rt1, *rt2, *rt;
 +
 +      xo= x;
 +      rt1= (char *)rect1;
 +      rt2= (char *)rect2;
 +      rt= (char *)out;
 +
 +      fac1= (int)(256.0*facf0);
 +      fac3= (int)(256.0*facf1);
 +
 +      /* formula:
 +       *              fac*(a*b) + (1-fac)*a  => fac*a*(b-1)+axaux= c*px + py*s ;//+centx
 +                      yaux= -s*px + c*py;//+centy
 +       */
 +
 +      while(y--) {
 +
 +              x= xo;
 +              while(x--) {
 +
 +                      rt[0]= rt1[0] + ((fac1*rt1[0]*(rt2[0]-256))>>16);
 +                      rt[1]= rt1[1] + ((fac1*rt1[1]*(rt2[1]-256))>>16);
 +                      rt[2]= rt1[2] + ((fac1*rt1[2]*(rt2[2]-256))>>16);
 +                      rt[3]= rt1[3] + ((fac1*rt1[3]*(rt2[3]-256))>>16);
 +
 +                      rt1+= 4; rt2+= 4; rt+= 4;
 +              }
 +
 +              if(y==0) break;
 +              y--;
 +
 +              x= xo;
 +              while(x--) {
 +
 +                      rt[0]= rt1[0] + ((fac3*rt1[0]*(rt2[0]-256))>>16);
 +                      rt[1]= rt1[1] + ((fac3*rt1[1]*(rt2[1]-256))>>16);
 +                      rt[2]= rt1[2] + ((fac3*rt1[2]*(rt2[2]-256))>>16);
 +                      rt[3]= rt1[3] + ((fac3*rt1[3]*(rt2[3]-256))>>16);
 +
 +                      rt1+= 4; rt2+= 4; rt+= 4;
 +              }
 +      }
 +}
 +
 +static void do_mul_effect_float(float facf0, float facf1, int x, int y, 
 +                              float *rect1, float *rect2, 
 +                              float *out)
 +{
 +      int xo;
 +      float fac1, fac3;
 +      float *rt1, *rt2, *rt;
 +
 +      xo= x;
 +      rt1= rect1;
 +      rt2= rect2;
 +      rt= out;
 +
 +      fac1= facf0;
 +      fac3= facf1;
 +
 +      /* formula:
 +       *              fac*(a*b) + (1-fac)*a  => fac*a*(b-1)+a
 +       */
 +
 +      while(y--) {
 +
 +              x= xo;
 +              while(x--) {
 +
 +                      rt[0]= rt1[0] + fac1*rt1[0]*(rt2[0]-1.0);
 +                      rt[1]= rt1[1] + fac1*rt1[1]*(rt2[1]-1.0);
 +                      rt[2]= rt1[2] + fac1*rt1[2]*(rt2[2]-1.0);
 +                      rt[3]= rt1[3] + fac1*rt1[3]*(rt2[3]-1.0);
 +
 +                      rt1+= 4; rt2+= 4; rt+= 4;
 +              }
 +
 +              if(y==0) break;
 +              y--;
 +
 +              x= xo;
 +              while(x--) {
 +
 +                      rt[0]= rt1[0] + fac3*rt1[0]*(rt2[0]-1.0);
 +                      rt[1]= rt1[1] + fac3*rt1[1]*(rt2[1]-1.0);
 +                      rt[2]= rt1[2] + fac3*rt1[2]*(rt2[2]-1.0);
 +                      rt[3]= rt1[3] + fac3*rt1[3]*(rt2[3]-1.0);
 +
 +                      rt1+= 4; rt2+= 4; rt+= 4;
 +              }
 +      }
 +}
 +
 +static void do_mul_effect(Sequence * seq,int cfra,
 +                        float facf0, float facf1, int x, int y, 
 +                        struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
 +                        struct ImBuf *ibuf3, struct ImBuf *out)
 +{
 +      if (out->rect_float) {
 +              do_mul_effect_float(
 +                      facf0, facf1, x, y,
 +                      ibuf1->rect_float, ibuf2->rect_float,
 +                      out->rect_float);
 +      } else {
 +              do_mul_effect_byte(
 +                      facf0, facf1, x, y,
 +                      (unsigned char*) ibuf1->rect, (unsigned char*) ibuf2->rect,
 +                      (unsigned char*) out->rect);
 +      }
 +}
 +
 +/* **********************************************************************
 +   WIPE
 +   ********************************************************************** */
 +
 +typedef struct WipeZone {
 +      float angle;
 +      int flip;
 +      int xo, yo;
 +      int width;
 +      float invwidth;
 +      float pythangle;
 +} WipeZone;
 +
 +static void precalc_wipe_zone(WipeZone *wipezone, WipeVars *wipe, int xo, int yo)
 +{
 +      wipezone->flip = (wipe->angle < 0);
 +      wipezone->angle = pow(fabs(wipe->angle)/45.0f, log(xo)/log(2.0f));
 +      wipezone->xo = xo;
 +      wipezone->yo = yo;
 +      wipezone->width = (int)(wipe->edgeWidth*((xo+yo)/2.0f));
 +      wipezone->pythangle = 1.0f/sqrt(wipe->angle*wipe->angle + 1.0f);
 +
 +      if(wipe->wipetype == DO_SINGLE_WIPE)
 +              wipezone->invwidth = 1.0f/wipezone->width;
 +      else
 +              wipezone->invwidth = 1.0f/(0.5f*wipezone->width);
 +}
 +
 +// This function calculates the blur band for the wipe effects
 +static float in_band(WipeZone *wipezone,float width,float dist,float perc,int side,int dir)
 +{
 +      float t1,t2,alpha,percwidth;
 +
 +      if(width == 0)
 +              return (float)side;
 +
 +      if(side == 1)
 +              percwidth = width * perc;
 +      else
 +              percwidth = width * (1 - perc);
 +      
 +      if(width < dist)
 +              return side;
 +      
 +      t1 = dist * wipezone->invwidth;  //percentange of width that is
 +      t2 = wipezone->invwidth;  //amount of alpha per % point
 +      
 +      if(side == 1)
 +              alpha = (t1*t2*100) + (1-perc); // add point's alpha contrib to current position in wipe
 +      else
 +              alpha = (1-perc) - (t1*t2*100);
 +      
 +      if(dir == 0)
 +              alpha = 1-alpha;
 +
 +      return alpha;
 +}
 +
 +static float check_zone(WipeZone *wipezone, int x, int y,
 +      Sequence *seq, float facf0) 
 +{
 +      float posx, posy,hyp,hyp2,angle,hwidth,b1,b2,b3,pointdist;
 +/*some future stuff
 +float hyp3,hyp4,b4,b5    
 +*/
 +      float temp1,temp2,temp3,temp4; //some placeholder variables
 +      int xo = wipezone->xo;
 +      int yo = wipezone->yo;
 +      float halfx = xo*0.5f;
 +      float halfy = yo*0.5f;
 +      float widthf,output=0;
 +      WipeVars *wipe = (WipeVars *)seq->effectdata;
 +      int width;
 +
 +      if(wipezone->flip) x = xo - x;
 +      angle = wipezone->angle;
 +
 +      posy = facf0 * yo;
 +
 +      if(wipe->forward){
 +              posx = facf0 * xo;
 +              posy = facf0 * yo;
 +      } else{
 +              posx = xo - facf0 * xo;
 +              posy = yo - facf0 * yo;
 +      }
 +
 +      switch (wipe->wipetype) {
 +              case DO_SINGLE_WIPE:
 +                      width = wipezone->width;
 +                      hwidth = width*0.5f;
 +
 +                      if(angle == 0.0f) {
 +                              b1 = posy;
 +                              b2 = y;
 +                              hyp = fabs(y - posy);
 +                      }
 +                      else {
 +                              b1 = posy - (-angle)*posx;
 +                              b2 = y - (-angle)*x;
 +                              hyp = fabs(angle*x+y+(-posy-angle*posx))*wipezone->pythangle;
 +                      }
 +
 +                      if(angle < 0) {
 +                              temp1 = b1;
 +                              b1 = b2;
 +                              b2 = temp1;
 +                      }
 +
 +                      if(wipe->forward) {
 +                              if(b1 < b2)
 +                                      output = in_band(wipezone,width,hyp,facf0,1,1);
 +                              else
 +                                      output = in_band(wipezone,width,hyp,facf0,0,1);
 +                      }
 +                      else {
 +                              if(b1 < b2)
 +                                      output = in_band(wipezone,width,hyp,facf0,0,1);
 +                              else
 +                                      output = in_band(wipezone,width,hyp,facf0,1,1);
 +                      }
 +              break;
 +       
 +              case DO_DOUBLE_WIPE:
 +                      if(!wipe->forward)
 +                              facf0 = 1.0f-facf0;   // Go the other direction
 +
 +                      width = wipezone->width;  // calculate the blur width
 +                      hwidth = width*0.5f;
 +                      if (angle == 0) {
 +                              b1 = posy*0.5f;
 +                              b3 = yo-posy*0.5f;
 +                              b2 = y;
 +
 +                              hyp = abs(y - posy*0.5f);
 +                              hyp2 = abs(y - (yo-posy*0.5f));
 +                      }
 +                      else {
 +                              b1 = posy*0.5f - (-angle)*posx*0.5f;
 +                              b3 = (yo-posy*0.5f) - (-angle)*(xo-posx*0.5f);
 +                              b2 = y - (-angle)*x;
 +
 +                              hyp = abs(angle*x+y+(-posy*0.5f-angle*posx*0.5f))*wipezone->pythangle;
 +                              hyp2 = abs(angle*x+y+(-(yo-posy*0.5f)-angle*(xo-posx*0.5f)))*wipezone->pythangle;
 +                      }
 +
 +                      temp1 = xo*(1-facf0*0.5f)-xo*facf0*0.5f;
 +                      temp2 = yo*(1-facf0*0.5f)-yo*facf0*0.5f;
 +                      pointdist = sqrt(temp1*temp1 + temp2*temp2);
 +
 +                      if(b2 < b1 && b2 < b3 ){
 +                              if(hwidth < pointdist)
 +                                      output = in_band(wipezone,hwidth,hyp,facf0,0,1);
 +                      } else if(b2 > b1 && b2 > b3 ){
 +                              if(hwidth < pointdist)
 +                                      output = in_band(wipezone,hwidth,hyp2,facf0,0,1);       
 +                      } else {
 +                              if(  hyp < hwidth && hyp2 > hwidth )
 +                                      output = in_band(wipezone,hwidth,hyp,facf0,1,1);
 +                              else if( hyp > hwidth && hyp2 < hwidth )
 +                                       output = in_band(wipezone,hwidth,hyp2,facf0,1,1);
 +                              else
 +                                       output = in_band(wipezone,hwidth,hyp2,facf0,1,1) * in_band(wipezone,hwidth,hyp,facf0,1,1);
 +                      }
 +                      if(!wipe->forward)output = 1-output;
 +              break;
 +              case DO_CLOCK_WIPE:
 +                      /*
 +                              temp1: angle of effect center in rads
 +                              temp2: angle of line through (halfx,halfy) and (x,y) in rads
 +                              temp3: angle of low side of blur
 +                              temp4: angle of high side of blur
 +                      */
 +                      output = 1.0f - facf0;
 +                      widthf = wipe->edgeWidth*2.0f*(float)M_PI;
 +                      temp1 = 2.0f * (float)M_PI * facf0;
 +                      
 +                      if(wipe->forward){
 +                              temp1 = 2.0f*(float)M_PI - temp1;
 +                      }
 +                      
 +                      x = x - halfx;
 +                      y = y - halfy;
 +
 +                      temp2 = asin(abs(y)/sqrt(x*x + y*y));
 +                      if(x <= 0 && y >= 0) temp2 = (float)M_PI - temp2;
 +                      else if(x<=0 && y <= 0) temp2 += (float)M_PI;
 +                      else if(x >= 0 && y <= 0) temp2 = 2.0f*(float)M_PI - temp2;
 +
 +                      if(wipe->forward){
 +                              temp3 = temp1-(widthf*0.5f)*facf0;
 +                              temp4 = temp1+(widthf*0.5f)*(1-facf0);
 +                      } else{
 +                              temp3 = temp1-(widthf*0.5f)*(1-facf0);
 +                              temp4 = temp1+(widthf*0.5f)*facf0;
 +                      }
 +                      if (temp3 < 0) temp3 = 0;
 +                      if (temp4 > 2.0f*(float)M_PI) temp4 = 2.0f*(float)M_PI;
 +                      
 +                      
 +                      if(temp2 < temp3) output = 0;
 +                      else if (temp2 > temp4) output = 1;
 +                      else output = (temp2-temp3)/(temp4-temp3);
 +                      if(x == 0 && y == 0) output = 1;
 +                      if(output != output) output = 1;
 +                      if(wipe->forward) output = 1 - output;
 +              break;
 +      /* BOX WIPE IS NOT WORKING YET */
 +      /* case DO_CROSS_WIPE: */
 +      /* BOX WIPE IS NOT WORKING YET */
 +      /* 
 +              case DO_BOX_WIPE: 
 +                      if(invert)facf0 = 1-facf0;
 +
 +                      width = (int)(wipe->edgeWidth*((xo+yo)/2.0));
 +                      hwidth = (float)width/2.0;
 +                      if (angle == 0)angle = 0.000001;
 +                      b1 = posy/2 - (-angle)*posx/2;
 +                      b3 = (yo-posy/2) - (-angle)*(xo-posx/2);
 +                      b2 = y - (-angle)*x;
 +
 +                      hyp = abs(angle*x+y+(-posy/2-angle*posx/2))*wipezone->pythangle;
 +                      hyp2 = abs(angle*x+y+(-(yo-posy/2)-angle*(xo-posx/2)))*wipezone->pythangle;
 +
 +                      temp1 = xo*(1-facf0/2)-xo*facf0/2;
 +                      temp2 = yo*(1-facf0/2)-yo*facf0/2;
 +                      pointdist = sqrt(temp1*temp1 + temp2*temp2);
 +
 +                      if(b2 < b1 && b2 < b3 ){
 +                              if(hwidth < pointdist)
 +                                      output = in_band(wipezone,hwidth,hyp,facf0,0,1);
 +                      } else if(b2 > b1 && b2 > b3 ){
 +                              if(hwidth < pointdist)
 +                                      output = in_band(wipezone,hwidth,hyp2,facf0,0,1);       
 +                      } else {
 +                              if( hyp < hwidth && hyp2 > hwidth )
 +                                      output = in_band(wipezone,hwidth,hyp,facf0,1,1);
 +                              else if( hyp > hwidth && hyp2 < hwidth )
 +                                      output = in_band(wipezone,hwidth,hyp2,facf0,1,1);
 +                              else
 +                                      output = in_band(wipezone,hwidth,hyp2,facf0,1,1) * in_band(wipezone,hwidth,hyp,facf0,1,1);
 +                      }
 +
 +                      if(invert)facf0 = 1-facf0;
 +                      angle = -1/angle;
 +                      b1 = posy/2 - (-angle)*posx/2;
 +                      b3 = (yo-posy/2) - (-angle)*(xo-posx/2);
 +                      b2 = y - (-angle)*x;
 +
 +                      hyp = abs(angle*x+y+(-posy/2-angle*posx/2))*wipezone->pythangle;
 +                      hyp2 = abs(angle*x+y+(-(yo-posy/2)-angle*(xo-posx/2)))*wipezone->pythangle;
 +
 +                      if(b2 < b1 && b2 < b3 ){
 +                              if(hwidth < pointdist)
 +                                      output *= in_band(wipezone,hwidth,hyp,facf0,0,1);
 +                      } else if(b2 > b1 && b2 > b3 ){
 +                              if(hwidth < pointdist)
 +                                      output *= in_band(wipezone,hwidth,hyp2,facf0,0,1);      
 +                      } else {
 +                              if( hyp < hwidth && hyp2 > hwidth )
 +                                      output *= in_band(wipezone,hwidth,hyp,facf0,1,1);
 +                              else if( hyp > hwidth && hyp2 < hwidth )
 +                                      output *= in_band(wipezone,hwidth,hyp2,facf0,1,1);
 +                              else
 +                                      output *= in_band(wipezone,hwidth,hyp2,facf0,1,1) * in_band(wipezone,hwidth,hyp,facf0,1,1);
 +                      }
 +
 +              break;
 +*/
 +              case DO_IRIS_WIPE:
 +                      if(xo > yo) yo = xo;
 +                      else xo = yo;
 +
 +                      if(!wipe->forward) facf0 = 1-facf0;
 +
 +                      width = wipezone->width;
 +                      hwidth = width*0.5f;
 +
 +                      temp1 = (halfx-(halfx)*facf0);
 +                      pointdist = sqrt(temp1*temp1 + temp1*temp1);
 +               
 +                      temp2 = sqrt((halfx-x)*(halfx-x) + (halfy-y)*(halfy-y));
 +                      if(temp2 > pointdist) output = in_band(wipezone,hwidth,fabs(temp2-pointdist),facf0,0,1);
 +                      else output = in_band(wipezone,hwidth,fabs(temp2-pointdist),facf0,1,1);
 +               
 +                      if(!wipe->forward) output = 1-output;
 +                      
 +              break;
 +      }
 +      if (output < 0) output = 0;
 +      else if(output > 1) output = 1;
 +      return output;
 +}
 +
 +static void init_wipe_effect(Sequence *seq)
 +{
 +      if(seq->effectdata)MEM_freeN(seq->effectdata);
 +      seq->effectdata = MEM_callocN(sizeof(struct WipeVars), "wipevars");
 +}
 +
 +static int num_inputs_wipe()
 +{
 +      return 1;
 +}
 +
 +static void free_wipe_effect(Sequence *seq)
 +{
 +      if(seq->effectdata)MEM_freeN(seq->effectdata);
 +      seq->effectdata = 0;
 +}
 +
 +static void copy_wipe_effect(Sequence *dst, Sequence *src)
 +{
 +      dst->effectdata = MEM_dupallocN(src->effectdata);
 +}
 +
 +static void do_wipe_effect_byte(Sequence *seq, float facf0, float facf1, 
 +                              int x, int y, 
 +                              unsigned char *rect1, 
 +                              unsigned char *rect2, unsigned char *out)
 +{
 +      WipeZone wipezone;
 +      WipeVars *wipe = (WipeVars *)seq->effectdata;
 +      int xo, yo;
 +      char *rt1, *rt2, *rt;
 +
 +      precalc_wipe_zone(&wipezone, wipe, x, y);
 +
 +      rt1 = (char *)rect1;
 +      rt2 = (char *)rect2;
 +      rt = (char *)out;
 +
 +      xo = x;
 +      yo = y;
 +      for(y=0;y<yo;y++) {
 +              for(x=0;x<xo;x++) {
 +                      float check = check_zone(&wipezone,x,y,seq,facf0);
 +                      if (check) {
 +                              if (rt1) {
 +                                      rt[0] = (int)(rt1[0]*check)+ (int)(rt2[0]*(1-check));
 +                                      rt[1] = (int)(rt1[1]*check)+ (int)(rt2[1]*(1-check));
 +                                      rt[2] = (int)(rt1[2]*check)+ (int)(rt2[2]*(1-check));
 +                                      rt[3] = (int)(rt1[3]*check)+ (int)(rt2[3]*(1-check));
 +                              } else {
 +                                      rt[0] = 0;
 +                                      rt[1] = 0;
 +                                      rt[2] = 0;
 +                                      rt[3] = 255;
 +                              }
 +                      } else {
 +                              if (rt2) {
 +                                      rt[0] = rt2[0];
 +                                      rt[1] = rt2[1];
 +                                      rt[2] = rt2[2];
 +                                      rt[3] = rt2[3];
 +                              } else {
 +                                      rt[0] = 0;
 +                                      rt[1] = 0;
 +                                      rt[2] = 0;
 +                                      rt[3] = 255;
 +                              }
 +                      }
 +
 +                      rt+=4;
 +                      if(rt1 !=NULL){
 +                              rt1+=4;
 +                      }
 +                      if(rt2 !=NULL){
 +                              rt2+=4;
 +                      }
 +              }
 +      }
 +}
 +
 +static void do_wipe_effect_float(Sequence *seq, float facf0, float facf1, 
 +                               int x, int y, 
 +                               float *rect1, 
 +                               float *rect2, float *out)
 +{
 +      WipeZone wipezone;
 +      WipeVars *wipe = (WipeVars *)seq->effectdata;
 +      int xo, yo;
 +      float *rt1, *rt2, *rt;
 +
 +      precalc_wipe_zone(&wipezone, wipe, x, y);
 +
 +      rt1 = rect1;
 +      rt2 = rect2;
 +      rt = out;
 +
 +      xo = x;
 +      yo = y;
 +      for(y=0;y<yo;y++) {
 +              for(x=0;x<xo;x++) {
 +                      float check = check_zone(&wipezone,x,y,seq,facf0);
 +                      if (check) {
 +                              if (rt1) {
 +                                      rt[0] = rt1[0]*check+ rt2[0]*(1-check);
 +                                      rt[1] = rt1[1]*check+ rt2[1]*(1-check);
 +                                      rt[2] = rt1[2]*check+ rt2[2]*(1-check);
 +                                      rt[3] = rt1[3]*check+ rt2[3]*(1-check);
 +                              } else {
 +                                      rt[0] = 0;
 +                                      rt[1] = 0;
 +                                      rt[2] = 0;
 +                                      rt[3] = 1.0;
 +                              }
 +                      } else {
 +                              if (rt2) {
 +                                      rt[0] = rt2[0];
 +                                      rt[1] = rt2[1];
 +                                      rt[2] = rt2[2];
 +                                      rt[3] = rt2[3];
 +                              } else {
 +                                      rt[0] = 0;
 +                                      rt[1] = 0;
 +                                      rt[2] = 0;
 +                                      rt[3] = 1.0;
 +                              }
 +                      }
 +
 +                      rt+=4;
 +                      if(rt1 !=NULL){
 +                              rt1+=4;
 +                      }
 +                      if(rt2 !=NULL){
 +                              rt2+=4;
 +                      }
 +              }
 +      }
 +}
 +
 +static void do_wipe_effect(Sequence * seq,int cfra,
 +                         float facf0, float facf1, int x, int y, 
 +                         struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
 +                         struct ImBuf *ibuf3, struct ImBuf *out)
 +{
 +      if (out->rect_float) {
 +              do_wipe_effect_float(seq,
 +                                   facf0, facf1, x, y,
 +                                   ibuf1->rect_float, ibuf2->rect_float,
 +                                   out->rect_float);
 +      } else {
 +              do_wipe_effect_byte(seq,
 +                                  facf0, facf1, x, y,
 +                                  (unsigned char*) ibuf1->rect, (unsigned char*) ibuf2->rect,
 +                                  (unsigned char*) out->rect);
 +      }
 +}
 +/* **********************************************************************
 +   TRANSFORM
 +   ********************************************************************** */
 +static void init_transform_effect(Sequence *seq)
 +{
 +      TransformVars *scale;
 +
 +      if(seq->effectdata)MEM_freeN(seq->effectdata);
 +      seq->effectdata = MEM_callocN(sizeof(struct TransformVars), "transformvars");
 +
 +      scale = (TransformVars *)seq->effectdata;
 +      scale->ScalexIni = 1;
 +      scale->ScaleyIni = 1;
 +      scale->ScalexFin = 1;
 +      scale->ScaleyFin = 1;
 +      
 +      scale->xIni=0;
 +      scale->xFin=0;
 +      scale->yIni=0;
 +      scale->yFin=0;
 +      
 +      scale->rotIni=0;
 +      scale->rotFin=0;
 +      
 +      scale->interpolation=1;
 +      scale->percent=1;
 +}
 +
 +static int num_inputs_transform()
 +{
 +      return 1;
 +}
 +
 +static void free_transform_effect(Sequence *seq)
 +{
 +      if(seq->effectdata)MEM_freeN(seq->effectdata);
 +      seq->effectdata = 0;
 +}
 +
 +static void copy_transform_effect(Sequence *dst, Sequence *src)
 +{
 +      dst->effectdata = MEM_dupallocN(src->effectdata);
 +}
 +
 +static void do_transform(Sequence * seq,float facf0, int x, int y, 
 +                        struct ImBuf *ibuf1,struct ImBuf *out)
 +{
 +      int xo, yo, xi, yi;
 +      float xs,ys,factxScale,factyScale,tx,ty,rad,s,c,xaux,yaux,factRot,px,py;
 +      TransformVars *scale;
 +      
++      struct RenderData *rd = NULL; // XXX 2.5 global: &G.scene->r;
++
++
 +      scale = (TransformVars *)seq->effectdata;
 +      xo = x;
 +      yo = y;
 +
 +      //factor scale
 +      factxScale = scale->ScalexIni + (scale->ScalexFin - scale->ScalexIni) * facf0;
 +      factyScale = scale->ScaleyIni + (scale->ScaleyFin - scale->ScaleyIni) * facf0;
 +
 +      //Factor translate
 +      if(!scale->percent){
++              float rd_s = 0.0f; // XXX 2.5 global: (rd->size / 100.0f);
++
++              tx = scale->xIni * rd_s+(xo / 2.0f) + (scale->xFin * rd_s -(xo / 2.0f) - scale->xIni * rd_s +(xo / 2.0f)) * facf0;
++              ty = scale->yIni * rd_s+(yo / 2.0f) + (scale->yFin * rd_s -(yo / 2.0f) - scale->yIni * rd_s +(yo / 2.0f)) * facf0;
 +      }else{
 +              tx = xo*(scale->xIni/100.0f)+(xo / 2.0f) + (xo*(scale->xFin/100.0f)-(xo / 2.0f) - xo*(scale->xIni/100.0f)+(xo / 2.0f)) * facf0;
 +              ty = yo*(scale->yIni/100.0f)+(yo / 2.0f) + (yo*(scale->yFin/100.0f)-(yo / 2.0f) - yo*(scale->yIni/100.0f)+(yo / 2.0f)) * facf0;
 +      }
 +
 +      //factor Rotate
 +      factRot = scale->rotIni + (scale->rotFin - scale->rotIni) * facf0;
 +      rad = (M_PI * factRot) / 180.0f;
 +      s= sin(rad);
 +      c= cos(rad);
 +
++
 +      for (yi = 0; yi < yo; yi++) {
 +              for (xi = 0; xi < xo; xi++) {
 +                      //tranlate point
 +                      px = xi-tx;
 +                      py = yi-ty;
 +
 +                      //rotate point with center ref
 +                      xaux = c*px + py*s ;
 +                      yaux = -s*px + c*py;
 +
 +                      //scale point with center ref
 +                      xs = xaux / factxScale;
 +                      ys = yaux / factyScale;
 +
 +                      //undo reference center point 
 +                      xs += (xo / 2.0f);
 +                      ys += (yo / 2.0f);
 +
 +                      //interpolate
 +                      switch(scale->interpolation) {
 +                      case 0:
 +                              neareast_interpolation(ibuf1,out, xs,ys,xi,yi);
 +                              break;
 +                      case 1:
 +                              bilinear_interpolation(ibuf1,out, xs,ys,xi,yi);
 +                              break;
 +                      case 2:
 +                              bicubic_interpolation(ibuf1,out, xs,ys,xi,yi);
 +                              break;
 +                      }
 +              }
 +      }       
 +
 +}
 +static void do_transform_effect(Sequence * seq,int cfra,
 +                         float facf0, float facf1, int x, int y, 
 +                         struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
 +                         struct ImBuf *ibuf3, struct ImBuf *out)
 +{
 +      do_transform(seq, facf0, x, y, ibuf1, out);
 +}
 +
 +
 +/* **********************************************************************
 +   GLOW
 +   ********************************************************************** */
 +
 +static void RVBlurBitmap2_byte ( unsigned char* map, int width,int height,
 +                               float blur,
 +                               int quality)
 +/*    MUUUCCH better than the previous blur. */
 +/*    We do the blurring in two passes which is a whole lot faster. */
 +/*    I changed the math arount to implement an actual Gaussian */
 +/*    distribution. */
 +/* */
 +/*    Watch out though, it tends to misbehaven with large blur values on */
 +/*    a small bitmap.  Avoid avoid avoid. */
 +/*=============================== */
 +{
 +      unsigned char*  temp=NULL,*swap;
 +      float   *filter=NULL;
 +      int     x,y,i,fx,fy;
 +      int     index, ix, halfWidth;
 +      float   fval, k, curColor[3], curColor2[3], weight=0;
 +
 +      /*      If we're not really blurring, bail out */
 +      if (blur<=0)
 +              return;
 +
 +      /*      Allocate memory for the tempmap and the blur filter matrix */
 +      temp= MEM_mallocN( (width*height*4), "blurbitmaptemp");
 +      if (!temp)
 +              return;
 +
 +      /*      Allocate memory for the filter elements */
 +      halfWidth = ((quality+1)*blur);
 +      filter = (float *)MEM_mallocN(sizeof(float)*halfWidth*2, "blurbitmapfilter");
 +      if (!filter){
 +              MEM_freeN (temp);
 +              return;
 +      }
 +
 +      /*      Apparently we're calculating a bell curve */
 +      /*      based on the standard deviation (or radius) */
 +      /*      This code is based on an example */
 +      /*      posted to comp.graphics.algorithms by */
 +      /*      Blancmange (bmange@airdmhor.gen.nz) */
 +
 +      k = -1.0/(2.0*3.14159*blur*blur);
 +      fval=0;
 +      for (ix = 0;ix< halfWidth;ix++){
 +              weight = (float)exp(k*(ix*ix));
 +              filter[halfWidth - ix] = weight;
 +              filter[halfWidth + ix] = weight;
 +      }
 +      filter[0] = weight;
 +
 +      /*      Normalize the array */
 +      fval=0;
 +      for (ix = 0;ix< halfWidth*2;ix++)
 +              fval+=filter[ix];
 +
 +      for (ix = 0;ix< halfWidth*2;ix++)
 +              filter[ix]/=fval;
 +
 +      /*      Blur the rows */
 +      for (y=0;y<height;y++){
 +              /*      Do the left & right strips */
 +              for (x=0;x<halfWidth;x++){
 +                      index=(x+y*width)*4;
 +                      fx=0;
 +                      curColor[0]=curColor[1]=curColor[2]=0;
 +                      curColor2[0]=curColor2[1]=curColor2[2]=0;
 +
 +                      for (i=x-halfWidth;i<x+halfWidth;i++){
 +                              if ((i>=0)&&(i<width)){
 +                                      curColor[0]+=map[(i+y*width)*4+GlowR]*filter[fx];
 +                                      curColor[1]+=map[(i+y*width)*4+GlowG]*filter[fx];
 +                                      curColor[2]+=map[(i+y*width)*4+GlowB]*filter[fx];
 +
 +                                      curColor2[0]+=map[(width-1-i+y*width)*4+GlowR] *
 +                                              filter[fx];
 +                                      curColor2[1]+=map[(width-1-i+y*width)*4+GlowG] *
 +                                              filter[fx];
 +                                      curColor2[2]+=map[(width-1-i+y*width)*4+GlowB] *
 +                                              filter[fx];
 +                              }
 +                              fx++;
 +                      }
 +                      temp[index+GlowR]=curColor[0];
 +                      temp[index+GlowG]=curColor[1];
 +                      temp[index+GlowB]=curColor[2];
 +
 +                      temp[((width-1-x+y*width)*4)+GlowR]=curColor2[0];
 +                      temp[((width-1-x+y*width)*4)+GlowG]=curColor2[1];
 +                      temp[((width-1-x+y*width)*4)+GlowB]=curColor2[2];
 +
 +              }
 +              /*      Do the main body */
 +              for (x=halfWidth;x<width-halfWidth;x++){
 +                      index=(x+y*width)*4;
 +                      fx=0;
 +                      curColor[0]=curColor[1]=curColor[2]=0;
 +                      for (i=x-halfWidth;i<x+halfWidth;i++){
 +                              curColor[0]+=map[(i+y*width)*4+GlowR]*filter[fx];
 +                              curColor[1]+=map[(i+y*width)*4+GlowG]*filter[fx];
 +                              curColor[2]+=map[(i+y*width)*4+GlowB]*filter[fx];
 +                              fx++;
 +                      }
 +                      temp[index+GlowR]=curColor[0];
 +                      temp[index+GlowG]=curColor[1];
 +                      temp[index+GlowB]=curColor[2];
 +              }
 +      }
 +
 +      /*      Swap buffers */
 +      swap=temp;temp=map;map=swap;
 +
 +
 +      /*      Blur the columns */
 +      for (x=0;x<width;x++){
 +              /*      Do the top & bottom strips */
 +              for (y=0;y<halfWidth;y++){
 +                      index=(x+y*width)*4;
 +                      fy=0;
 +                      curColor[0]=curColor[1]=curColor[2]=0;
 +                      curColor2[0]=curColor2[1]=curColor2[2]=0;
 +                      for (i=y-halfWidth;i<y+halfWidth;i++){
 +                              if ((i>=0)&&(i<height)){
 +                                      /*      Bottom */
 +                                      curColor[0]+=map[(x+i*width)*4+GlowR]*filter[fy];
 +                                      curColor[1]+=map[(x+i*width)*4+GlowG]*filter[fy];
 +                                      curColor[2]+=map[(x+i*width)*4+GlowB]*filter[fy];
 +
 +                                      /*      Top */
 +                                      curColor2[0]+=map[(x+(height-1-i)*width) *
 +                                              4+GlowR]*filter[fy];
 +                                      curColor2[1]+=map[(x+(height-1-i)*width) *
 +                                              4+GlowG]*filter[fy];
 +                                      curColor2[2]+=map[(x+(height-1-i)*width) *
 +                                              4+GlowB]*filter[fy];
 +                              }
 +                              fy++;
 +                      }
 +                      temp[index+GlowR]=curColor[0];
 +                      temp[index+GlowG]=curColor[1];
 +                      temp[index+GlowB]=curColor[2];
 +                      temp[((x+(height-1-y)*width)*4)+GlowR]=curColor2[0];
 +                      temp[((x+(height-1-y)*width)*4)+GlowG]=curColor2[1];
 +                      temp[((x+(height-1-y)*width)*4)+GlowB]=curColor2[2];
 +              }
 +              /*      Do the main body */
 +              for (y=halfWidth;y<height-halfWidth;y++){
 +                      index=(x+y*width)*4;
 +                      fy=0;
 +                      curColor[0]=curColor[1]=curColor[2]=0;
 +                      for (i=y-halfWidth;i<y+halfWidth;i++){
 +                              curColor[0]+=map[(x+i*width)*4+GlowR]*filter[fy];
 +                              curColor[1]+=map[(x+i*width)*4+GlowG]*filter[fy];
 +                              curColor[2]+=map[(x+i*width)*4+GlowB]*filter[fy];
 +                              fy++;
 +                      }
 +                      temp[index+GlowR]=curColor[0];
 +                      temp[index+GlowG]=curColor[1];
 +                      temp[index+GlowB]=curColor[2];
 +              }
 +      }
 +
 +
 +      /*      Swap buffers */
 +      swap=temp;temp=map;map=swap;
 +
 +      /*      Tidy up  */
 +      MEM_freeN (filter);
 +      MEM_freeN (temp);
 +}
 +
 +static void RVBlurBitmap2_float ( float* map, int width,int height,
 +                                float blur,
 +                                int quality)
 +/*    MUUUCCH better than the previous blur. */
 +/*    We do the blurring in two passes which is a whole lot faster. */
 +/*    I changed the math arount to implement an actual Gaussian */
 +/*    distribution. */
 +/* */
 +/*    Watch out though, it tends to misbehaven with large blur values on */
 +/*    a small bitmap.  Avoid avoid avoid. */
 +/*=============================== */
 +{
 +      float*  temp=NULL,*swap;
 +      float   *filter=NULL;
 +      int     x,y,i,fx,fy;
 +      int     index, ix, halfWidth;
 +      float   fval, k, curColor[3], curColor2[3], weight=0;
 +
 +      /*      If we're not really blurring, bail out */
 +      if (blur<=0)
 +              return;
 +
 +      /*      Allocate memory for the tempmap and the blur filter matrix */
 +      temp= MEM_mallocN( (width*height*4*sizeof(float)), "blurbitmaptemp");
 +      if (!temp)
 +              return;
 +
 +      /*      Allocate memory for the filter elements */
 +      halfWidth = ((quality+1)*blur);
 +      filter = (float *)MEM_mallocN(sizeof(float)*halfWidth*2, "blurbitmapfilter");
 +      if (!filter){
 +              MEM_freeN (temp);
 +              return;
 +      }
 +
 +      /*      Apparently we're calculating a bell curve */
 +      /*      based on the standard deviation (or radius) */
 +      /*      This code is based on an example */
 +      /*      posted to comp.graphics.algorithms by */
 +      /*      Blancmange (bmange@airdmhor.gen.nz) */
 +
 +      k = -1.0/(2.0*3.14159*blur*blur);
 +      fval=0;
 +      for (ix = 0;ix< halfWidth;ix++){
 +              weight = (float)exp(k*(ix*ix));
 +              filter[halfWidth - ix] = weight;
 +              filter[halfWidth + ix] = weight;
 +      }
 +      filter[0] = weight;
 +
 +      /*      Normalize the array */
 +      fval=0;
 +      for (ix = 0;ix< halfWidth*2;ix++)
 +              fval+=filter[ix];
 +
 +      for (ix = 0;ix< halfWidth*2;ix++)
 +              filter[ix]/=fval;
 +
 +      /*      Blur the rows */
 +      for (y=0;y<height;y++){
 +              /*      Do the left & right strips */
 +              for (x=0;x<halfWidth;x++){
 +                      index=(x+y*width)*4;
 +                      fx=0;
 +                      curColor[0]=curColor[1]=curColor[2]=0.0f;
 +                      curColor2[0]=curColor2[1]=curColor2[2]=0.0f;
 +
 +                      for (i=x-halfWidth;i<x+halfWidth;i++){
 +                              if ((i>=0)&&(i<width)){
 +                                      curColor[0]+=map[(i+y*width)*4+GlowR]*filter[fx];
 +                                      curColor[1]+=map[(i+y*width)*4+GlowG]*filter[fx];
 +                                      curColor[2]+=map[(i+y*width)*4+GlowB]*filter[fx];
 +
 +                                      curColor2[0]+=map[(width-1-i+y*width)*4+GlowR] *
 +                                              filter[fx];
 +                                      curColor2[1]+=map[(width-1-i+y*width)*4+GlowG] *
 +                                              filter[fx];
 +                                      curColor2[2]+=map[(width-1-i+y*width)*4+GlowB] *
 +                                              filter[fx];
 +                              }
 +                              fx++;
 +                      }
 +                      temp[index+GlowR]=curColor[0];
 +                      temp[index+GlowG]=curColor[1];
 +                      temp[index+GlowB]=curColor[2];
 +
 +                      temp[((width-1-x+y*width)*4)+GlowR]=curColor2[0];
 +                      temp[((width-1-x+y*width)*4)+GlowG]=curColor2[1];
 +                      temp[((width-1-x+y*width)*4)+GlowB]=curColor2[2];
 +
 +              }
 +              /*      Do the main body */
 +              for (x=halfWidth;x<width-halfWidth;x++){
 +                      index=(x+y*width)*4;
 +                      fx=0;
 +                      curColor[0]=curColor[1]=curColor[2]=0;
 +                      for (i=x-halfWidth;i<x+halfWidth;i++){
 +                              curColor[0]+=map[(i+y*width)*4+GlowR]*filter[fx];
 +                              curColor[1]+=map[(i+y*width)*4+GlowG]*filter[fx];
 +                              curColor[2]+=map[(i+y*width)*4+GlowB]*filter[fx];
 +                              fx++;
 +                      }
 +                      temp[index+GlowR]=curColor[0];
 +                      temp[index+GlowG]=curColor[1];
 +                      temp[index+GlowB]=curColor[2];
 +              }
 +      }
 +
 +      /*      Swap buffers */
 +      swap=temp;temp=map;map=swap;
 +
 +
 +      /*      Blur the columns */
 +      for (x=0;x<width;x++){
 +              /*      Do the top & bottom strips */
 +              for (y=0;y<halfWidth;y++){
 +                      index=(x+y*width)*4;
 +                      fy=0;
 +                      curColor[0]=curColor[1]=curColor[2]=0;
 +                      curColor2[0]=curColor2[1]=curColor2[2]=0;
 +                      for (i=y-halfWidth;i<y+halfWidth;i++){
 +                              if ((i>=0)&&(i<height)){
 +                                      /*      Bottom */
 +                                      curColor[0]+=map[(x+i*width)*4+GlowR]*filter[fy];
 +                                      curColor[1]+=map[(x+i*width)*4+GlowG]*filter[fy];
 +                                      curColor[2]+=map[(x+i*width)*4+GlowB]*filter[fy];
 +
 +                                      /*      Top */
 +                                      curColor2[0]+=map[(x+(height-1-i)*width) *
 +                                              4+GlowR]*filter[fy];
 +                                      curColor2[1]+=map[(x+(height-1-i)*width) *
 +                                              4+GlowG]*filter[fy];
 +                                      curColor2[2]+=map[(x+(height-1-i)*width) *
 +                                              4+GlowB]*filter[fy];
 +                              }
 +                              fy++;
 +                      }
 +                      temp[index+GlowR]=curColor[0];
 +                      temp[index+GlowG]=curColor[1];
 +                      temp[index+GlowB]=curColor[2];
 +                      temp[((x+(height-1-y)*width)*4)+GlowR]=curColor2[0];
 +                      temp[((x+(height-1-y)*width)*4)+GlowG]=curColor2[1];
 +                      temp[((x+(height-1-y)*width)*4)+GlowB]=curColor2[2];
 +              }
 +              /*      Do the main body */
 +              for (y=halfWidth;y<height-halfWidth;y++){
 +                      index=(x+y*width)*4;
 +                      fy=0;
 +                      curColor[0]=curColor[1]=curColor[2]=0;
 +                      for (i=y-halfWidth;i<y+halfWidth;i++){
 +                              curColor[0]+=map[(x+i*width)*4+GlowR]*filter[fy];
 +                              curColor[1]+=map[(x+i*width)*4+GlowG]*filter[fy];
 +                              curColor[2]+=map[(x+i*width)*4+GlowB]*filter[fy];
 +                              fy++;
 +                      }
 +                      temp[index+GlowR]=curColor[0];
 +                      temp[index+GlowG]=curColor[1];
 +                      temp[index+GlowB]=curColor[2];
 +              }
 +      }
 +
 +
 +      /*      Swap buffers */
 +      swap=temp;temp=map;map=swap;
 +
 +      /*      Tidy up  */
 +      MEM_freeN (filter);
 +      MEM_freeN (temp);
 +}
 +
 +
 +/*    Adds two bitmaps and puts the results into a third map. */
 +/*    C must have been previously allocated but it may be A or B. */
 +/*    We clamp values to 255 to prevent weirdness */
 +/*=============================== */
 +static void RVAddBitmaps_byte (unsigned char* a, unsigned char* b, unsigned char* c, int width, int height)
 +{
 +      int     x,y,index;
 +
 +      for (y=0;y<height;y++){
 +              for (x=0;x<width;x++){
 +                      index=(x+y*width)*4;
 +                      c[index+GlowR]=MIN2(255,a[index+GlowR]+b[index+GlowR]);
 +                      c[index+GlowG]=MIN2(255,a[index+GlowG]+b[index+GlowG]);
 +                      c[index+GlowB]=MIN2(255,a[index+GlowB]+b[index+GlowB]);
 +                      c[index+GlowA]=MIN2(255,a[index+GlowA]+b[index+GlowA]);
 +              }
 +      }
 +}
 +
 +static void RVAddBitmaps_float (float* a, float* b, float* c, 
 +                              int width, int height)
 +{
 +      int     x,y,index;
 +
 +      for (y=0;y<height;y++){
 +              for (x=0;x<width;x++){
 +                      index=(x+y*width)*4;
 +                      c[index+GlowR]=MIN2(1.0,a[index+GlowR]+b[index+GlowR]);
 +                      c[index+GlowG]=MIN2(1.0,a[index+GlowG]+b[index+GlowG]);
 +                      c[index+GlowB]=MIN2(1.0,a[index+GlowB]+b[index+GlowB]);
 +                      c[index+GlowA]=MIN2(1.0,a[index+GlowA]+b[index+GlowA]);
 +              }
 +      }
 +}
 +
 +/*    For each pixel whose total luminance exceeds the threshold, */
 +/*    Multiply it's value by BOOST and add it to the output map */
 +static void RVIsolateHighlights_byte (unsigned char* in, unsigned char* out, 
 +                                    int width, int height, int threshold, 
 +                                    float boost, float clamp)
 +{
 +      int x,y,index;
 +      int     intensity;
 +
 +
 +      for(y=0;y< height;y++) {
 +              for (x=0;x< width;x++) {
 +                      index= (x+y*width)*4;
 +
 +                      /*      Isolate the intensity */
 +                      intensity=(in[index+GlowR]+in[index+GlowG]+in[index+GlowB]-threshold);
 +                      if (intensity>0){
 +                              out[index+GlowR]=MIN2(255*clamp, (in[index+GlowR]*boost*intensity)/255);
 +                              out[index+GlowG]=MIN2(255*clamp, (in[index+GlowG]*boost*intensity)/255);
 +                              out[index+GlowB]=MIN2(255*clamp, (in[index+GlowB]*boost*intensity)/255);
 +                              out[index+GlowA]=MIN2(255*clamp, (in[index+GlowA]*boost*intensity)/255);
 +                      } else{
 +                              out[index+GlowR]=0;
 +                              out[index+GlowG]=0;
 +                              out[index+GlowB]=0;
 +                              out[index+GlowA]=0;
 +                      }
 +              }
 +      }
 +}
 +
 +static void RVIsolateHighlights_float (float* in, float* out, 
 +                                    int width, int height, float threshold, 
 +                                    float boost, float clamp)
 +{
 +      int x,y,index;
 +      float   intensity;
 +
 +
 +      for(y=0;y< height;y++) {
 +              for (x=0;x< width;x++) {
 +                      index= (x+y*width)*4;
 +
 +                      /*      Isolate the intensity */
 +                      intensity=(in[index+GlowR]+in[index+GlowG]+in[index+GlowB]-threshold);
 +                      if (intensity>0){
 +                              out[index+GlowR]=MIN2(clamp, (in[index+GlowR]*boost*intensity));
 +                              out[index+GlowG]=MIN2(clamp, (in[index+GlowG]*boost*intensity));
 +                              out[index+GlowB]=MIN2(clamp, (in[index+GlowB]*boost*intensity));
 +                              out[index+GlowA]=MIN2(clamp, (in[index+GlowA]*boost*intensity));
 +                      } else{
 +                              out[index+GlowR]=0;
 +                              out[index+GlowG]=0;
 +                              out[index+GlowB]=0;
 +                              out[index+GlowA]=0;
 +                      }
 +              }
 +      }
 +}
 +
 +static void init_glow_effect(Sequence *seq)
 +{
 +      GlowVars *glow;
 +
 +      if(seq->effectdata)MEM_freeN(seq->effectdata);
 +      seq->effectdata = MEM_callocN(sizeof(struct GlowVars), "glowvars");
 +
 +      glow = (GlowVars *)seq->effectdata;
 +      glow->fMini = 0.25;
 +      glow->fClamp = 1.0;
 +      glow->fBoost = 0.5;
 +      glow->dDist = 3.0;
 +      glow->dQuality = 3;
 +      glow->bNoComp = 0;
 +}
 +
 +static int num_inputs_glow()
 +{
 +      return 1;
 +}
 +
 +static void free_glow_effect(Sequence *seq)
 +{
 +      if(seq->effectdata)MEM_freeN(seq->effectdata);
 +      seq->effectdata = 0;
 +}
 +
 +static void copy_glow_effect(Sequence *dst, Sequence *src)
 +{
 +      dst->effectdata = MEM_dupallocN(src->effectdata);
 +}
 +
 +//void do_glow_effect(Cast *cast, float facf0, float facf1, int xo, int yo, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *outbuf, ImBuf *use)
 +static void do_glow_effect_byte(Sequence *seq, float facf0, float facf1, 
 +                              int x, int y, char *rect1, 
 +                              char *rect2, char *out)
 +{
 +      unsigned char *outbuf=(unsigned char *)out;
 +      unsigned char *inbuf=(unsigned char *)rect1;
 +      GlowVars *glow = (GlowVars *)seq->effectdata;
 +      int size= 100; // renderdata XXX
 +      
 +      RVIsolateHighlights_byte(inbuf, outbuf , x, y, glow->fMini*765, glow->fBoost * facf0, glow->fClamp);
 +      RVBlurBitmap2_byte (outbuf, x, y, glow->dDist * (size / 100.0f),glow->dQuality);
 +      if (!glow->bNoComp)
 +              RVAddBitmaps_byte (inbuf , outbuf, outbuf, x, y);
 +}
 +
 +static void do_glow_effect_float(Sequence *seq, float facf0, float facf1, 
 +                               int x, int y, 
 +                               float *rect1, float *rect2, float *out)
 +{
 +      float *outbuf = out;
 +      float *inbuf = rect1;
 +      GlowVars *glow = (GlowVars *)seq->effectdata;
 +      int size= 100; // renderdata XXX
 +
 +      RVIsolateHighlights_float(inbuf, outbuf , x, y, glow->fMini*3.0f, glow->fBoost * facf0, glow->fClamp);
 +      RVBlurBitmap2_float (outbuf, x, y, glow->dDist * (size / 100.0f),glow->dQuality);
 +      if (!glow->bNoComp)
 +              RVAddBitmaps_float (inbuf , outbuf, outbuf, x, y);
 +}
 +
 +static void do_glow_effect(Sequence * seq,int cfra,
 +                         float facf0, float facf1, int x, int y, 
 +                         struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
 +                         struct ImBuf *ibuf3, struct ImBuf *out)
 +{
 +      if (out->rect_float) {
 +              do_glow_effect_float(seq,
 +                                   facf0, facf1, x, y,
 +                                   ibuf1->rect_float, ibuf2->rect_float,
 +                                   out->rect_float);
 +      } else {
 +              do_glow_effect_byte(seq,
 +                                  facf0, facf1, x, y,
 +                                  (char*) ibuf1->rect, (char*) ibuf2->rect,
 +                                  (char*) out->rect);
 +      }
 +}
 +
 +/* **********************************************************************
 +   SOLID COLOR
 +   ********************************************************************** */
 +
 +static void init_solid_color(Sequence *seq)
 +{
 +      SolidColorVars *cv;
 +      
 +      if(seq->effectdata)MEM_freeN(seq->effectdata);
 +      seq->effectdata = MEM_callocN(sizeof(struct SolidColorVars), "solidcolor");
 +      
 +      cv = (SolidColorVars *)seq->effectdata;
 +      cv->col[0] = cv->col[1] = cv->col[2] = 0.5;
 +}
 +
 +static int num_inputs_color()
 +{
 +      return 0;
 +}
 +
 +static void free_solid_color(Sequence *seq)
 +{
 +      if(seq->effectdata)MEM_freeN(seq->effectdata);
 +      seq->effectdata = 0;
 +}
 +
 +static void copy_solid_color(Sequence *dst, Sequence *src)
 +{
 +      dst->effectdata = MEM_dupallocN(src->effectdata);
 +}
 +
 +static int early_out_color(struct Sequence *seq,
 +                         float facf0, float facf1)
 +{
 +      return -1;
 +}
 +
 +static void do_solid_color(Sequence * seq,int cfra,
 +                         float facf0, float facf1, int x, int y, 
 +                         struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
 +                         struct ImBuf *ibuf3, struct ImBuf *out)
 +{
 +      SolidColorVars *cv = (SolidColorVars *)seq->effectdata;
 +
 +      unsigned char *rect;
 +      float *rect_float;
 +
 +      if (out->rect) {
 +              unsigned char col0[3];
 +              unsigned char col1[3];
 +
 +              col0[0] = facf0 * cv->col[0] * 255;
 +              col0[1] = facf0 * cv->col[1] * 255;
 +              col0[2] = facf0 * cv->col[2] * 255;
 +
 +              col1[0] = facf1 * cv->col[0] * 255;
 +              col1[1] = facf1 * cv->col[1] * 255;
 +              col1[2] = facf1 * cv->col[2] * 255;
 +
 +              rect = (unsigned char *)out->rect;
 +              
 +              for(y=0; y<out->y; y++) {       
 +                      for(x=0; x<out->x; x++, rect+=4) {
 +                              rect[0]= col0[0];
 +                              rect[1]= col0[1];
 +                              rect[2]= col0[2];
 +                              rect[3]= 255;
 +                      }
 +                      y++;
 +                      if (y<out->y) {
 +                              for(x=0; x<out->x; x++, rect+=4) {
 +                                      rect[0]= col1[0];
 +                                      rect[1]= col1[1];
 +                                      rect[2]= col1[2];
 +                                      rect[3]= 255;
 +                              }       
 +                      }
 +              }
 +
 +      } else if (out->rect_float) {
 +              float col0[3];
 +              float col1[3];
 +
 +              col0[0] = facf0 * cv->col[0];
 +              col0[1] = facf0 * cv->col[1];
 +              col0[2] = facf0 * cv->col[2];
 +
 +              col1[0] = facf1 * cv->col[0];
 +              col1[1] = facf1 * cv->col[1];
 +              col1[2] = facf1 * cv->col[2];
 +
 +              rect_float = out->rect_float;
 +              
 +              for(y=0; y<out->y; y++) {       
 +                      for(x=0; x<out->x; x++, rect_float+=4) {
 +                              rect_float[0]= col0[0];
 +                              rect_float[1]= col0[1];
 +                              rect_float[2]= col0[2];
 +                              rect_float[3]= 1.0;
 +                      }
 +                      y++;
 +                      if (y<out->y) {
 +                              for(x=0; x<out->x; x++, rect_float+=4) {
 +                                      rect_float[0]= col1[0];
 +                                      rect_float[1]= col1[1];
 +                                      rect_float[2]= col1[2];
 +                                      rect_float[3]= 1.0;
 +                              }
 +                      }
 +              }
 +      }
 +}
 +
 +/* **********************************************************************
 +   SPEED
 +   ********************************************************************** */
 +static void init_speed_effect(Sequence *seq)
 +{
 +      SpeedControlVars * v;
 +
 +      if(seq->effectdata) MEM_freeN(seq->effectdata);
 +      seq->effectdata = MEM_callocN(sizeof(struct SpeedControlVars), 
 +                                    "speedcontrolvars");
 +
 +      v = (SpeedControlVars *)seq->effectdata;
 +      v->globalSpeed = 1.0;
 +      v->frameMap = 0;
 +      v->flags = SEQ_SPEED_COMPRESS_IPO_Y;
 +      v->length = 0;
 +}
 +
 +static void load_speed_effect(Sequence * seq)
 +{
 +      SpeedControlVars * v = (SpeedControlVars *)seq->effectdata;
 +
 +      v->frameMap = 0;
 +      v->length = 0;
 +}
 +
 +static int num_inputs_speed()
 +{
 +      return 1;
 +}
 +
 +static void free_speed_effect(Sequence *seq)
 +{
 +      SpeedControlVars * v = (SpeedControlVars *)seq->effectdata;
 +      if(v->frameMap) MEM_freeN(v->frameMap);
 +      if(seq->effectdata) MEM_freeN(seq->effectdata);
 +      seq->effectdata = 0;
 +}
 +
 +static void copy_speed_effect(Sequence *dst, Sequence *src)
 +{
 +      SpeedControlVars * v;
 +      dst->effectdata = MEM_dupallocN(src->effectdata);
 +      v = (SpeedControlVars *)dst->effectdata;
 +      v->frameMap = 0;
 +      v->length = 0;
 +}
 +
 +static int early_out_speed(struct Sequence *seq,
 +                        float facf0, float facf1)
 +{
 +      return 1;
 +}
 +
 +static void store_icu_yrange_speed(struct Sequence * seq,
 +                                 short adrcode, float * ymin, float * ymax)
 +{
 +      SpeedControlVars * v = (SpeedControlVars *)seq->effectdata;
 +
 +      /* if not already done, load / initialize data */
 +      get_sequence_effect(seq);
 +
 +      if ((v->flags & SEQ_SPEED_INTEGRATE) != 0) {
 +              *ymin = -100.0;
 +              *ymax = 100.0;
 +      } else {
 +              if (v->flags & SEQ_SPEED_COMPRESS_IPO_Y) {
 +                      *ymin = 0.0;
 +                      *ymax = 1.0;
 +              } else {
 +                      *ymin = 0.0;
 +                      *ymax = seq->len;
 +              }
 +      }       
 +}
 +
 +void sequence_effect_speed_rebuild_map(Sequence * seq, int force)
 +{
 +      float facf0 = seq->facf0;
 +      //float ctime, div;
 +      int cfra;
 +      float fallback_fac;
 +      SpeedControlVars * v = (SpeedControlVars *)seq->effectdata;
 +
 +      /* if not already done, load / initialize data */
 +      get_sequence_effect(seq);
 +
 +      if (!(force || seq->len != v->length || !v->frameMap)) {
 +              return;
 +      }
 +
 +      if (!v->frameMap || v->length != seq->len) {
 +              if (v->frameMap) MEM_freeN(v->frameMap);
 +
 +              v->length = seq->len;
 +
 +              v->frameMap = MEM_callocN(sizeof(float) * v->length, 
 +                                        "speedcontrol frameMap");
 +      }
 +
 +      fallback_fac = 1.0;
 +      
 +      /* if there is no IPO, try to make retiming easy by stretching the
 +         strip */
 +      // XXX old animation system - seq
 +      if (/*!seq->ipo &&*/ seq->seq1 && seq->seq1->enddisp != seq->seq1->start
 +          && seq->seq1->len != 0) {
 +              fallback_fac = (float) seq->seq1->len / 
 +                      (float) (seq->seq1->enddisp - seq->seq1->start);
 +              /* FIXME: this strip stretching gets screwed by stripdata
 +                 handling one layer up.
 +                 
 +                 So it currently works by enlarging, never by shrinking!
 +
 +                 (IPOs still work, if used correctly)
 +              */
 +              if (fallback_fac > 1.0) {
 +                      fallback_fac = 1.0;
 +              }
 +      }
 +
 +      if ((v->flags & SEQ_SPEED_INTEGRATE) != 0) {
 +              float cursor = 0;
 +
 +              v->frameMap[0] = 0;
 +              v->lastValidFrame = 0;
 +
 +              for (cfra = 1; cfra < v->length; cfra++) {
 +#if 0 // XXX old animation system
 +                      if(seq->ipo) {
 +                              if((seq->flag & SEQ_IPO_FRAME_LOCKED) != 0) {
 +                                      ctime = frame_to_float(scene, seq->startdisp + cfra);
 +                                      div = 1.0;
 +                              } else {
 +                                      ctime= frame_to_float(scene, cfra);
 +                                      div= v->length / 100.0f;
 +                                      if(div==0.0) return;
 +                              }
 +              
 +                              calc_ipo(seq->ipo, ctime/div);
 +                              execute_ipo((ID *)seq, seq->ipo);
 +                      } else 
 +#endif // XXX old animation system
 +                      {
 +                              seq->facf0 = fallback_fac;
 +                      }
 +                      seq->facf0 *= v->globalSpeed;
 +
 +                      cursor += seq->facf0;
 +
 +                      if (cursor >= v->length) {
 +                              v->frameMap[cfra] = v->length - 1;
 +                      } else {
 +                              v->frameMap[cfra] = cursor;
 +                              v->lastValidFrame = cfra;
 +                      }
 +              }
 +      } else {
 +              v->lastValidFrame = 0;
 +              for (cfra = 0; cfra < v->length; cfra++) {
 +#if 0 // XXX old animation system
 +                      if(seq->ipo) {
 +                              if((seq->flag & SEQ_IPO_FRAME_LOCKED) != 0) {
 +                                      ctime = frame_to_float(scene, seq->startdisp + cfra);
 +                                      div = 1.0;
 +                              } else {
 +                                      ctime= frame_to_float(scene, cfra);
 +                                      div= v->length / 100.0f;
 +                                      if(div==0.0) return;
 +                              }
 +              
 +                              calc_ipo(seq->ipo, ctime/div);
 +                              execute_ipo((ID *)seq, seq->ipo);
 +                      }
 +#endif // XXX old animation system
 +                      
 +                      if (v->flags & SEQ_SPEED_COMPRESS_IPO_Y) {
 +                              seq->facf0 *= v->length;
 +                      }
 +                      if (/*!seq->ipo*/ 1) { // XXX old animation system - seq
 +                              seq->facf0 = (float) cfra * fallback_fac;
 +                      }
 +                      seq->facf0 *= v->globalSpeed;
 +                      if (seq->facf0 >= v->length) {
 +                              seq->facf0 = v->length - 1;
 +                      } else {
 +                              v->lastValidFrame = cfra;
 +                      }
 +                      v->frameMap[cfra] = seq->facf0;
 +              }
 +      }
 +      seq->facf0 = facf0;
 +}
 +
 +/*
 +  simply reuse do_cross_effect for blending...
 +
 +static void do_speed_effect(Sequence * seq,int cfra,
 +                         float facf0, float facf1, int x, int y, 
 +                         struct ImBuf *ibuf1, struct ImBuf *ibuf2, 
 +                         struct ImBuf *ibuf3, struct ImBuf *out)
 +{
 +
 +}
 +*/
 +
 +
 +/* **********************************************************************
 +   sequence effect factory
 +   ********************************************************************** */
 +
 +
 +static void init_noop(struct Sequence *seq)
 +{
 +
 +}
 +
 +static void load_noop(struct Sequence *seq)
 +{
 +
 +}
 +
 +static void init_plugin_noop(struct Sequence *seq, const char * fname)
 +{
 +
 +}
 +
 +static void free_noop(struct Sequence *seq)
 +{
 +
 +}
 +
 +static int num_inputs_default()
 +{
 +      return 2;
 +}
 +
 +static int early_out_noop(struct Sequence *seq,
 +                        float facf0, float facf1)
 +{
 +      return 0;
 +}
 +
 +static int early_out_fade(struct Sequence *seq,
 +                        float facf0, float facf1)
 +{
 +      if (facf0 == 0.0 && facf1 == 0.0) {
 +              return 1;
 +      } else if (facf0 == 1.0 && facf1 == 1.0) {
 +              return 2;
 +      }
 +      return 0;
 +}
 +
 +static int early_out_mul_input2(struct Sequence *seq,
 +                              float facf0, float facf1)
 +{
 +      if (facf0 == 0.0 && facf1 == 0.0) {
 +              return 1;
 +      }
 +      return 0;
 +}
 +
 +static void store_icu_yrange_noop(struct Sequence * seq,
 +                                short adrcode, float * ymin, float * ymax)
 +{
 +      /* defaults are fine */
 +}
 +
 +static void get_default_fac_noop(struct Sequence *seq, int cfra,
 +                               float * facf0, float * facf1)
 +{
 +      *facf0 = *facf1 = 1.0;
 +}
 +
 +static void get_default_fac_fade(struct Sequence *seq, int cfra,
 +                               float * facf0, float * facf1)
 +{
 +      *facf0 = (float)(cfra - seq->startdisp);
 +      *facf1 = (float)(*facf0 + 0.5);
 +      *facf0 /= seq->len;
 +      *facf1 /= seq->len;
 +}
 +
 +static void do_overdrop_effect(struct Sequence * seq, int cfra,
 +                             float fac, float facf, 
 +                             int x, int y, struct ImBuf * ibuf1, 
 +                             struct ImBuf * ibuf2, 
 +                             struct ImBuf * ibuf3, 
 +                             struct ImBuf * out)
 +{
 +      do_drop_effect(seq, cfra, fac, facf, x, y, 
 +                     ibuf1, ibuf2, ibuf3, out);
 +      do_alphaover_effect(seq, cfra, fac, facf, x, y, 
 +                          ibuf1, ibuf2, ibuf3, out);
 +}
 +
 +static struct SeqEffectHandle get_sequence_effect_impl(int seq_type)
 +{
 +      struct SeqEffectHandle rval;
 +      int sequence_type = seq_type;
 +
 +      rval.init = init_noop;
 +      rval.init_plugin = init_plugin_noop;
 +      rval.num_inputs = num_inputs_default;
 +      rval.load = load_noop;
 +      rval.free = free_noop;
 +      rval.early_out = early_out_noop;
 +      rval.get_default_fac = get_default_fac_noop;
 +      rval.store_icu_yrange = store_icu_yrange_noop;
 +      rval.execute = NULL;
 +      rval.copy = NULL;
 +
 +      switch (sequence_type) {
 +      case SEQ_CROSS:
 +              rval.execute = do_cross_effect;
 +              rval.early_out = early_out_fade;
 +              rval.get_default_fac = get_default_fac_fade;
 +              break;
 +      case SEQ_GAMCROSS:
 +              rval.init = init_gammacross;
 +              rval.load = load_gammacross;
 +              rval.free = free_gammacross;
 +              rval.early_out = early_out_fade;
 +              rval.get_default_fac = get_default_fac_fade;
 +              rval.execute = do_gammacross_effect;
 +              break;
 +      case SEQ_ADD:
 +              rval.execute = do_add_effect;
 +              rval.early_out = early_out_mul_input2;
 +              break;
 +      case SEQ_SUB:
 +              rval.execute = do_sub_effect;
 +              rval.early_out = early_out_mul_input2;
 +              break;
 +      case SEQ_MUL:
 +              rval.execute = do_mul_effect;
 +              rval.early_out = early_out_mul_input2;
 +              break;
 +      case SEQ_ALPHAOVER:
 +              rval.init = init_alpha_over_or_under;
 +              rval.execute = do_alphaover_effect;
 +              break;
 +      case SEQ_OVERDROP:
 +              rval.execute = do_overdrop_effect;
 +              break;
 +      case SEQ_ALPHAUNDER:
 +              rval.init = init_alpha_over_or_under;
 +              rval.execute = do_alphaunder_effect;
 +              break;
 +      case SEQ_WIPE:
 +              rval.init = init_wipe_effect;
 +              rval.num_inputs = num_inputs_wipe;
 +              rval.free = free_wipe_effect;
 +              rval.copy = copy_wipe_effect;
 +              rval.early_out = early_out_fade;
 +              rval.get_default_fac = get_default_fac_fade;
 +              rval.execute = do_wipe_effect;
 +              break;
 +      case SEQ_GLOW:
 +              rval.init = init_glow_effect;
 +              rval.num_inputs = num_inputs_glow;
 +              rval.free = free_glow_effect;
 +              rval.copy = copy_glow_effect;
 +              rval.execute = do_glow_effect;
 +              break;
 +      case SEQ_TRANSFORM:
 +              rval.init = init_transform_effect;
 +              rval.num_inputs = num_inputs_transform;
 +              rval.free = free_transform_effect;
 +              rval.copy = copy_transform_effect;
 +              rval.execute = do_transform_effect;
 +              break;
 +      case SEQ_SPEED:
 +              rval.init = init_speed_effect;
 +              rval.num_inputs = num_inputs_speed;
 +              rval.load = load_speed_effect;
 +              rval.free = free_speed_effect;
 +              rval.copy = copy_speed_effect;
 +              rval.execute = do_cross_effect;
 +              rval.early_out = early_out_speed;
 +              rval.store_icu_yrange = store_icu_yrange_speed;
 +              break;
 +      case SEQ_COLOR:
 +              rval.init = init_solid_color;
 +              rval.num_inputs = num_inputs_color;
 +              rval.early_out = early_out_color;
 +              rval.free = free_solid_color;
 +              rval.copy = copy_solid_color;
 +              rval.execute = do_solid_color;
 +              break;
 +      case SEQ_PLUGIN:
 +              rval.init_plugin = init_plugin;
 +              rval.num_inputs = num_inputs_plugin;
 +              rval.load = load_plugin;
 +              rval.free = free_plugin;
 +              rval.copy = copy_plugin;
 +              rval.execute = do_plugin_effect;
 +              rval.early_out = do_plugin_early_out;
 +              rval.get_default_fac = get_default_fac_fade;
 +              break;
 +      }
 +
 +      return rval;
 +}
 +
 +
 +struct SeqEffectHandle get_sequence_effect(Sequence * seq)
 +{
 +      struct SeqEffectHandle rval;
 +
 +      memset(&rval, 0, sizeof(struct SeqEffectHandle));
 +
 +      if (seq->type & SEQ_EFFECT) {
 +              rval = get_sequence_effect_impl(seq->type);
 +              if ((seq->flag & SEQ_EFFECT_NOT_LOADED) != 0) {
 +                      rval.load(seq);
 +                      seq->flag &= ~SEQ_EFFECT_NOT_LOADED;
 +              }
 +      }
 +
 +      return rval;
 +}
 +
 +struct SeqEffectHandle get_sequence_blend(Sequence * seq)
 +{
 +      struct SeqEffectHandle rval;
 +
 +      memset(&rval, 0, sizeof(struct SeqEffectHandle));
 +
 +      if (seq->blend_mode != 0) {
 +              rval = get_sequence_effect_impl(seq->blend_mode);
 +              if ((seq->flag & SEQ_EFFECT_NOT_LOADED) != 0) {
 +                      rval.load(seq);
 +                      seq->flag &= ~SEQ_EFFECT_NOT_LOADED;
 +              }
 +      }
 +
 +      return rval;
 +}
 +
 +int get_sequence_effect_num_inputs(int seq_type)
 +{
 +      struct SeqEffectHandle rval = get_sequence_effect_impl(seq_type);
 +
 +      int cnt = rval.num_inputs();
 +      if (rval.execute) {
 +              return cnt;
 +      }
 +      return 0;
 +}
index b32f1c7,0000000..121dfce
mode 100644,000000..100644
--- /dev/null
@@@ -1,3276 -1,0 +1,3295 @@@
 +/**
 +* $Id: sequence.c 17508 2008-11-20 00:34:24Z campbellbarton $
 + *
 + * ***** BEGIN GPL LICENSE BLOCK *****
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software Foundation,
 + * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 + *
 + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
 + * All rights reserved.
 + *
 + * Contributor(s): 
 + * - Blender Foundation, 2003-2009
 + * - Peter Schlaile <peter [at] schlaile [dot] de> 2005/2006
 + *
 + * ***** END GPL LICENSE BLOCK *****
 + */
 +
 +#include <stdlib.h>
 +#include <string.h>
 +#include <math.h>
 +
 +#include "MEM_guardedalloc.h"
 +
 +#include "DNA_listBase.h"
 +#include "DNA_sequence_types.h"
 +#include "DNA_scene_types.h"
 +
 +#include "BKE_global.h"
 +#include "BKE_image.h"
 +#include "BKE_main.h"
 +#include "BKE_sequence.h"
 +#include "BKE_utildefines.h"
 +
 +#include "BLI_blenlib.h"
 +
 +#include "IMB_imbuf.h"
 +#include "IMB_imbuf_types.h"
 +
 +#include "BLI_threads.h"
 +#include <pthread.h>
 +
 +#ifdef WIN32
 +#define snprintf _snprintf
 +#endif
 +
 +/* **** XXX ******** */
 +static int seqrectx= 0;       /* bad bad global! */
 +static int seqrecty= 0;
 +static void waitcursor() {}
 +static int blender_test_break() {return 0;}
 +
 +/* **** XXX ******** */
 +
 +
 +/* **********************************************************************
 +   alloc / free functions
 +   ********************************************************************** */
 +
 +static void free_tstripdata(int len, TStripElem *se)
 +{
 +      TStripElem *seo;
 +      int a;
 +
 +      seo= se;
 +      if (!se)
 +              return;
 +
 +      for(a=0; a<len; a++, se++) {
 +              if(se->ibuf) {
 +                      IMB_freeImBuf(se->ibuf);
 +                      se->ibuf = 0;
 +              }
 +              if(se->ibuf_comp) {
 +                      IMB_freeImBuf(se->ibuf_comp);
 +                      se->ibuf_comp = 0;
 +              }
 +      }
 +
 +      MEM_freeN(seo);
 +}
 +
 +
 +void new_tstripdata(Sequence *seq)
 +{
 +      if(seq->strip) {
 +              free_tstripdata(seq->strip->len, seq->strip->tstripdata);
 +              free_tstripdata(seq->strip->endstill, 
 +                              seq->strip->tstripdata_endstill);
 +              free_tstripdata(seq->strip->startstill, 
 +                              seq->strip->tstripdata_startstill);
 +
 +              seq->strip->tstripdata= 0;
 +              seq->strip->tstripdata_endstill= 0;
 +              seq->strip->tstripdata_startstill= 0;
 +
 +              if(seq->strip->ibuf_startstill) {
 +                      IMB_freeImBuf(seq->strip->ibuf_startstill);
 +                      seq->strip->ibuf_startstill = 0;
 +              }
 +
 +              if(seq->strip->ibuf_endstill) {
 +                      IMB_freeImBuf(seq->strip->ibuf_endstill);
 +                      seq->strip->ibuf_endstill = 0;
 +              }
 +
 +              seq->strip->len= seq->len;
 +      }
 +}
 +
 +
 +/* free */
 +
 +void seq_free_strip(Strip *strip)
 +{
 +      strip->us--;
 +      if(strip->us>0) return;
 +      if(strip->us<0) {
 +              printf("error: negative users in strip\n");
 +              return;
 +      }
 +
 +      if (strip->stripdata) {
 +              MEM_freeN(strip->stripdata);
 +      }
 +
 +      if (strip->proxy) {
 +              MEM_freeN(strip->proxy);
 +      }
 +      if (strip->crop) {
 +              MEM_freeN(strip->crop);
 +      }
 +      if (strip->transform) {
 +              MEM_freeN(strip->transform);
 +      }
 +      if (strip->color_balance) {
 +              MEM_freeN(strip->color_balance);
 +      }
 +
 +      free_tstripdata(strip->len, strip->tstripdata);
 +      free_tstripdata(strip->endstill, strip->tstripdata_endstill);
 +      free_tstripdata(strip->startstill, strip->tstripdata_startstill);
 +
 +      if(strip->ibuf_startstill) {
 +              IMB_freeImBuf(strip->ibuf_startstill);
 +              strip->ibuf_startstill = 0;
 +      }
 +
 +      if(strip->ibuf_endstill) {
 +              IMB_freeImBuf(strip->ibuf_endstill);
 +              strip->ibuf_endstill = 0;
 +      }
 +
 +      MEM_freeN(strip);
 +}
 +
 +void seq_free_sequence(Editing *ed, Sequence *seq)
 +{
 +      if(seq->strip) seq_free_strip(seq->strip);
 +
 +      if(seq->anim) IMB_free_anim(seq->anim);
 +      //XXX if(seq->hdaudio) sound_close_hdaudio(seq->hdaudio);
 +
 +      /* XXX if (seq->type & SEQ_EFFECT) {
 +              struct SeqEffectHandle sh = get_sequence_effect(seq);
 +
 +              sh.free(seq);
 +      }*/
 +
 +      if (ed->act_seq==seq)
 +              ed->act_seq= NULL;
 +
 +      MEM_freeN(seq);
 +}
 +
 +Editing *seq_give_editing(Scene *scene, int alloc)
 +{
 +      if (scene->ed == NULL && alloc) {
 +              Editing *ed;
 +
 +              ed= scene->ed= MEM_callocN( sizeof(Editing), "addseq");
 +              ed->seqbasep= &ed->seqbase;
 +      }
 +      return scene->ed;
 +}
 +
 +void seq_free_editing(Editing *ed)
 +{
 +      MetaStack *ms;
 +      Sequence *seq;
 +
 +      if(ed==NULL)
 +              return;
 +
 +      SEQ_BEGIN(ed, seq) {
 +              seq_free_sequence(ed, seq);
 +      }
 +      SEQ_END
 +
 +      while((ms= ed->metastack.first)) {
 +              BLI_remlink(&ed->metastack, ms);
 +              MEM_freeN(ms);
 +      }
 +
 +      MEM_freeN(ed);
 +}
 +
 +/* ************************* itterator ************************** */
 +/* *************** (replaces old WHILE_SEQ) ********************* */
 +/* **************** use now SEQ_BEGIN() SEQ_END ***************** */
 +
 +/* sequence strip iterator:
 + * - builds a full array, recursively into meta strips */
 +
 +static void seq_count(ListBase *seqbase, int *tot)
 +{
 +      Sequence *seq;
 +
 +      for(seq=seqbase->first; seq; seq=seq->next) {
 +              (*tot)++;
 +
 +              if(seq->seqbase.first)
 +                      seq_count(&seq->seqbase, tot);
 +      }
 +}
 +
 +static void seq_build_array(ListBase *seqbase, Sequence ***array, int depth)
 +{
 +      Sequence *seq;
 +
 +      for(seq=seqbase->first; seq; seq=seq->next) {
 +              seq->depth= depth;
 +
 +              if(seq->seqbase.first)
 +                      seq_build_array(&seq->seqbase, array, depth+1);
 +
 +              **array= seq;
 +              (*array)++;
 +      }
 +}
 +
 +void seq_array(Editing *ed, Sequence ***seqarray, int *tot, int use_pointer)
 +{
 +      Sequence **array;
 +
 +      *seqarray= NULL;
 +      *tot= 0;
 +
 +      if(ed == NULL)
 +              return;
 +
 +      if(use_pointer)
 +              seq_count(ed->seqbasep, tot);
 +      else
 +              seq_count(&ed->seqbase, tot);
 +
 +      if(*tot == 0)
 +              return;
 +
 +      *seqarray= array= MEM_mallocN(sizeof(Sequence *)*(*tot), "SeqArray");
 +      if(use_pointer)
 +              seq_build_array(ed->seqbasep, &array, 0);
 +      else
 +              seq_build_array(&ed->seqbase, &array, 0);
 +}
 +
 +void seq_begin(Editing *ed, SeqIterator *iter, int use_pointer)
 +{
 +      memset(iter, 0, sizeof(*iter));
 +      seq_array(ed, &iter->array, &iter->tot, use_pointer);
 +
 +      if(iter->tot) {
 +              iter->cur= 0;
 +              iter->seq= iter->array[iter->cur];
 +              iter->valid= 1;
 +      }
 +}
 +
 +void seq_next(SeqIterator *iter)
 +{
 +      if(++iter->cur < iter->tot)
 +              iter->seq= iter->array[iter->cur];
 +      else
 +              iter->valid= 0;
 +}
 +
 +void seq_end(SeqIterator *iter)
 +{
 +      if(iter->array)
 +              MEM_freeN(iter->array);
 +
 +      iter->valid= 0;
 +}
 +
 +/*
 +  **********************************************************************
 +  * build_seqar
 +  **********************************************************************
 +  * Build a complete array of _all_ sequencies (including those
 +  * in metastrips!)
 +  **********************************************************************
 +*/
 +
 +static void do_seq_count(ListBase *seqbase, int *totseq)
 +{
 +      Sequence *seq;
 +
 +      seq= seqbase->first;
 +      while(seq) {
 +              (*totseq)++;
 +              if(seq->seqbase.first) do_seq_count(&seq->seqbase, totseq);
 +              seq= seq->next;
 +      }
 +}
 +
 +static void do_build_seqar(ListBase *seqbase, Sequence ***seqar, int depth)
 +{
 +      Sequence *seq;
 +
 +      seq= seqbase->first;
 +      while(seq) {
 +              seq->depth= depth;
 +              if(seq->seqbase.first) do_build_seqar(&seq->seqbase, seqar, depth+1);
 +              **seqar= seq;
 +              (*seqar)++;
 +              seq= seq->next;
 +      }
 +}
 +
 +void build_seqar(ListBase *seqbase, Sequence  ***seqar, int *totseq)
 +{
 +      Sequence **tseqar;
 +
 +      *totseq= 0;
 +      do_seq_count(seqbase, totseq);
 +
 +      if(*totseq==0) {
 +              *seqar= 0;
 +              return;
 +      }
 +      *seqar= MEM_mallocN(sizeof(void *)* *totseq, "seqar");
 +      tseqar= *seqar;
 +
 +      do_build_seqar(seqbase, seqar, 0);
 +      *seqar= tseqar;
 +}
 +
 +static void do_seq_count_cb(ListBase *seqbase, int *totseq,
 +                          int (*test_func)(Sequence * seq))
 +{
 +      Sequence *seq;
 +
 +      seq= seqbase->first;
 +      while(seq) {
 +              int test = test_func(seq);
 +              if (test & BUILD_SEQAR_COUNT_CURRENT) {
 +                      (*totseq)++;
 +              }
 +              if(seq->seqbase.first && (test & BUILD_SEQAR_COUNT_CHILDREN)) {
 +                      do_seq_count_cb(&seq->seqbase, totseq, test_func);
 +              }
 +              seq= seq->next;
 +      }
 +}
 +
 +static void do_build_seqar_cb(ListBase *seqbase, Sequence ***seqar, int depth,
 +                            int (*test_func)(Sequence * seq))
 +{
 +      Sequence *seq;
 +
 +      seq= seqbase->first;
 +      while(seq) {
 +              int test = test_func(seq);
 +              seq->depth= depth;
 +
 +              if(seq->seqbase.first && (test & BUILD_SEQAR_COUNT_CHILDREN)) {
 +                      do_build_seqar_cb(&seq->seqbase, seqar, depth+1, 
 +                                        test_func);
 +              }
 +              if (test & BUILD_SEQAR_COUNT_CURRENT) {
 +                      **seqar= seq;
 +                      (*seqar)++;
 +              }
 +              seq= seq->next;
 +      }
 +}
 +
 +void build_seqar_cb(ListBase *seqbase, Sequence  ***seqar, int *totseq,
 +                  int (*test_func)(Sequence * seq))
 +{
 +      Sequence **tseqar;
 +
 +      *totseq= 0;
 +      do_seq_count_cb(seqbase, totseq, test_func);
 +
 +      if(*totseq==0) {
 +              *seqar= 0;
 +              return;
 +      }
 +      *seqar= MEM_mallocN(sizeof(void *)* *totseq, "seqar");
 +      tseqar= *seqar;
 +
 +      do_build_seqar_cb(seqbase, seqar, 0, test_func);
 +      *seqar= tseqar;
 +}
 +
 +
 +void calc_sequence_disp(Sequence *seq)
 +{
 +      if(seq->startofs && seq->startstill) seq->startstill= 0;
 +      if(seq->endofs && seq->endstill) seq->endstill= 0;
 +      
 +      seq->startdisp= seq->start + seq->startofs - seq->startstill;
 +      seq->enddisp= seq->start+seq->len - seq->endofs + seq->endstill;
 +      
 +      seq->handsize= 10.0;    /* 10 frames */
 +      if( seq->enddisp-seq->startdisp < 10 ) {
 +              seq->handsize= (float)(0.5*(seq->enddisp-seq->startdisp));
 +      }
 +      else if(seq->enddisp-seq->startdisp > 250) {
 +              seq->handsize= (float)((seq->enddisp-seq->startdisp)/25);
 +      }
 +}
 +
 +void calc_sequence(Sequence *seq)
 +{
 +      Sequence *seqm;
 +      int min, max;
 +
 +      /* check all metas recursively */
 +      seqm= seq->seqbase.first;
 +      while(seqm) {
 +              if(seqm->seqbase.first) calc_sequence(seqm);
 +              seqm= seqm->next;
 +      }
 +
 +      /* effects and meta: automatic start and end */
 +
 +      if(seq->type & SEQ_EFFECT) {
 +              /* pointers */
 +              if(seq->seq2==0) seq->seq2= seq->seq1;
 +              if(seq->seq3==0) seq->seq3= seq->seq1;
 +
 +              /* effecten go from seq1 -> seq2: test */
 +
 +              /* we take the largest start and smallest end */
 +
 +              // seq->start= seq->startdisp= MAX2(seq->seq1->startdisp, seq->seq2->startdisp);
 +              // seq->enddisp= MIN2(seq->seq1->enddisp, seq->seq2->enddisp);
 +
 +              if (seq->seq1) {
 +                      seq->start= seq->startdisp= MAX3(seq->seq1->startdisp, seq->seq2->startdisp, seq->seq3->startdisp);
 +                      seq->enddisp= MIN3(seq->seq1->enddisp, seq->seq2->enddisp, seq->seq3->enddisp);
 +                      seq->len= seq->enddisp - seq->startdisp;
 +              } else {
 +                      calc_sequence_disp(seq);
 +              }
 +
 +              if(seq->strip && seq->len!=seq->strip->len) {
 +                      new_tstripdata(seq);
 +              }
 +
 +      }
 +      else {
 +              if(seq->type==SEQ_META) {
 +                      seqm= seq->seqbase.first;
 +                      if(seqm) {
 +                              min= 1000000;
 +                              max= -1000000;
 +                              while(seqm) {
 +                                      if(seqm->startdisp < min) min= seqm->startdisp;
 +                                      if(seqm->enddisp > max) max= seqm->enddisp;
 +                                      seqm= seqm->next;
 +                              }
 +                              seq->start= min + seq->anim_startofs;
 +                              seq->len = max-min;
 +                              seq->len -= seq->anim_startofs;
 +                              seq->len -= seq->anim_endofs;
 +
 +                              if(seq->strip && seq->len!=seq->strip->len) {
 +                                      new_tstripdata(seq);
 +                              }
 +                      }
 +              }
 +              calc_sequence_disp(seq);
 +      }
 +}
 +
 +void reload_sequence_new_file(Scene *scene, Sequence * seq)
 +{
 +      char str[FILE_MAXDIR+FILE_MAXFILE];
 +
 +      if (!(seq->type == SEQ_MOVIE || seq->type == SEQ_IMAGE ||
 +            seq->type == SEQ_HD_SOUND || seq->type == SEQ_RAM_SOUND ||
 +            seq->type == SEQ_SCENE || seq->type == SEQ_META)) {
 +              return;
 +      }
 +
 +      new_tstripdata(seq);
 +
 +      if (seq->type != SEQ_SCENE && seq->type != SEQ_META &&
 +          seq->type != SEQ_IMAGE) {
 +              BLI_join_dirfile(str, seq->strip->dir, seq->strip->stripdata->name);
 +              BLI_convertstringcode(str, G.sce);
 +              BLI_convertstringframe(str, scene->r.cfra);
 +              
 +      }
 +
 +      if (seq->type == SEQ_IMAGE) {
 +              /* Hack? */
 +              int olen = MEM_allocN_len(seq->strip->stripdata)/sizeof(struct StripElem);
 +              seq->len = olen;
 +              seq->len -= seq->anim_startofs;
 +              seq->len -= seq->anim_endofs;
 +              if (seq->len < 0) {
 +                      seq->len = 0;
 +              }
 +              seq->strip->len = seq->len;
 +      } else if (seq->type == SEQ_MOVIE) {
 +              if(seq->anim) IMB_free_anim(seq->anim);
 +              seq->anim = openanim(str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0));
 +
 +              if (!seq->anim) {
 +                      return;
 +              }
 +      
 +              seq->len = IMB_anim_get_duration(seq->anim);
 +              
 +              seq->anim_preseek = IMB_anim_get_preseek(seq->anim);
 +
 +              seq->len -= seq->anim_startofs;
 +              seq->len -= seq->anim_endofs;
 +              if (seq->len < 0) {
 +                      seq->len = 0;
 +              }
 +              seq->strip->len = seq->len;
 +      } else if (seq->type == SEQ_HD_SOUND) {
 +// XXX                if(seq->hdaudio) sound_close_hdaudio(seq->hdaudio);
 +//            seq->hdaudio = sound_open_hdaudio(str);
 +
 +              if (!seq->hdaudio) {
 +                      return;
 +              }
 +
 +// XXX                seq->len = sound_hdaudio_get_duration(seq->hdaudio, FPS) - seq->anim_startofs - seq->anim_endofs;
 +              if (seq->len < 0) {
 +                      seq->len = 0;
 +              }
 +              seq->strip->len = seq->len;
 +      } else if (seq->type == SEQ_RAM_SOUND) {
 +              seq->len = (int) ( ((float)(seq->sound->streamlen-1)/
 +                                  ((float)scene->audio.mixrate*4.0 ))
 +                                 * FPS);
 +              seq->len -= seq->anim_startofs;
 +              seq->len -= seq->anim_endofs;
 +              if (seq->len < 0) {
 +                      seq->len = 0;
 +              }
 +              seq->strip->len = seq->len;
 +      } else if (seq->type == SEQ_SCENE) {
 +              Scene * sce = G.main->scene.first;
 +              int nr = 1;
 +              
 +              while(sce) {
 +                      if(nr == seq->scenenr) {
 +                              break;
 +                      }
 +                      nr++;
 +                      sce= sce->id.next;
 +              }
 +
 +              if (sce) {
 +                      seq->scene = sce;
 +              } else {
 +                      sce = seq->scene;
 +              }
 +
 +              strncpy(seq->name + 2, sce->id.name + 2, 
 +                      sizeof(seq->name) - 2);
 +
 +              seq->len= seq->scene->r.efra - seq->scene->r.sfra + 1;
 +              seq->len -= seq->anim_startofs;
 +              seq->len -= seq->anim_endofs;
 +              if (seq->len < 0) {
 +                      seq->len = 0;
 +              }
 +              seq->strip->len = seq->len;
 +      }
 +
 +      calc_sequence(seq);
 +}
 +
 +void sort_seq(Scene *scene)
 +{
 +      /* all strips together per kind, and in order of y location ("machine") */
 +      ListBase seqbase, effbase;
 +      Editing *ed= seq_give_editing(scene, FALSE);
 +      Sequence *seq, *seqt;
 +
 +      
 +      if(ed==NULL) return;
 +
 +      seqbase.first= seqbase.last= 0;
 +      effbase.first= effbase.last= 0;
 +
 +      while( (seq= ed->seqbasep->first) ) {
 +              BLI_remlink(ed->seqbasep, seq);
 +
 +              if(seq->type & SEQ_EFFECT) {
 +                      seqt= effbase.first;
 +                      while(seqt) {
 +                              if(seqt->machine>=seq->machine) {
 +                                      BLI_insertlinkbefore(&effbase, seqt, seq);
 +                                      break;
 +                              }
 +                              seqt= seqt->next;
 +                      }
 +                      if(seqt==0) BLI_addtail(&effbase, seq);
 +              }
 +              else {
 +                      seqt= seqbase.first;
 +                      while(seqt) {
 +                              if(seqt->machine>=seq->machine) {
 +                                      BLI_insertlinkbefore(&seqbase, seqt, seq);
 +                                      break;
 +                              }
 +                              seqt= seqt->next;
 +                      }
 +                      if(seqt==0) BLI_addtail(&seqbase, seq);
 +              }
 +      }
 +
 +      addlisttolist(&seqbase, &effbase);
 +      *(ed->seqbasep)= seqbase;
 +}
 +
 +
 +void clear_scene_in_allseqs(Scene *sce)
 +{
 +      Scene *sce1;
 +      Editing *ed;
 +      Sequence *seq;
 +
 +      /* when a scene is deleted: test all seqs */
 +
 +      sce1= G.main->scene.first;
 +      while(sce1) {
 +              if(sce1!=sce && sce1->ed) {
 +                      ed= sce1->ed;
 +
 +                      SEQ_BEGIN(ed, seq) {
 +
 +                              if(seq->scene==sce) seq->scene= 0;
 +
 +                      }
 +                      SEQ_END
 +              }
 +
 +              sce1= sce1->id.next;
 +      }
 +}
 +
 +char *give_seqname_by_type(int type)
 +{
 +      switch(type) {
 +      case SEQ_META:       return "Meta";
 +      case SEQ_IMAGE:      return "Image";
 +      case SEQ_SCENE:      return "Scene";
 +      case SEQ_MOVIE:      return "Movie";
 +      case SEQ_RAM_SOUND:  return "Audio (RAM)";
 +      case SEQ_HD_SOUND:   return "Audio (HD)";
 +      case SEQ_CROSS:      return "Cross";
 +      case SEQ_GAMCROSS:   return "Gamma Cross";
 +      case SEQ_ADD:        return "Add";
 +      case SEQ_SUB:        return "Sub";
 +      case SEQ_MUL:        return "Mul";
 +      case SEQ_ALPHAOVER:  return "Alpha Over";
 +      case SEQ_ALPHAUNDER: return "Alpha Under";
 +      case SEQ_OVERDROP:   return "Over Drop";
 +      case SEQ_WIPE:       return "Wipe";
 +      case SEQ_GLOW:       return "Glow";
 +      case SEQ_TRANSFORM:  return "Transform";
 +      case SEQ_COLOR:      return "Color";
 +      case SEQ_SPEED:      return "Speed";
 +      default:
 +              return 0;
 +      }
 +}
 +
 +char *give_seqname(Sequence *seq)
 +{
 +      char * name = give_seqname_by_type(seq->type);
 +
 +      if (!name) {
 +              if(seq->type<SEQ_EFFECT) {
 +                      return seq->strip->dir;
 +              } else if(seq->type==SEQ_PLUGIN) {
 +                      if(!(seq->flag & SEQ_EFFECT_NOT_LOADED) &&
 +                         seq->plugin && seq->plugin->doit) {
 +                              return seq->plugin->pname;
 +                      } else {
 +                              return "Plugin";
 +                      }
 +              } else {
 +                      return "Effect";
 +              }
 +      }
 +      return name;
 +}
 +
 +/* ***************** DO THE SEQUENCE ***************** */
 +
 +static void make_black_ibuf(ImBuf *ibuf)
 +{
 +      unsigned int *rect;
 +      float *rect_float;
 +      int tot;
 +
 +      if(ibuf==0 || (ibuf->rect==0 && ibuf->rect_float==0)) return;
 +
 +      tot= ibuf->x*ibuf->y;
 +
 +      rect= ibuf->rect;
 +      rect_float = ibuf->rect_float;
 +
 +      if (rect) {
 +              memset(rect,       0, tot * sizeof(char) * 4);
 +      }
 +
 +      if (rect_float) {
 +              memset(rect_float, 0, tot * sizeof(float) * 4);
 +      }
 +}
 +
 +static void multibuf(ImBuf *ibuf, float fmul)
 +{
 +      char *rt;
 +      float *rt_float;
 +
 +      int a, mul, icol;
 +
 +      mul= (int)(256.0*fmul);
 +      rt= (char *)ibuf->rect;
 +      rt_float = ibuf->rect_float;
 +
 +      if (rt) {
 +              a= ibuf->x*ibuf->y;
 +              while(a--) {
 +
 +                      icol= (mul*rt[0])>>8;
 +                      if(icol>254) rt[0]= 255; else rt[0]= icol;
 +                      icol= (mul*rt[1])>>8;
 +                      if(icol>254) rt[1]= 255; else rt[1]= icol;
 +                      icol= (mul*rt[2])>>8;
 +                      if(icol>254) rt[2]= 255; else rt[2]= icol;
 +                      icol= (mul*rt[3])>>8;
 +                      if(icol>254) rt[3]= 255; else rt[3]= icol;
 +                      
 +                      rt+= 4;
 +              }
 +      }
 +      if (rt_float) {
 +              a= ibuf->x*ibuf->y;
 +              while(a--) {
 +                      rt_float[0] *= fmul;
 +                      rt_float[1] *= fmul;
 +                      rt_float[2] *= fmul;
 +                      rt_float[3] *= fmul;
 +                      
 +                      rt_float += 4;
 +              }
 +      }
 +}
 +
 +static void do_effect(Scene *scene, int cfra, Sequence *seq, TStripElem * se)
 +{
 +      TStripElem *se1, *se2, *se3;
 +      float fac, facf;
 +      int x, y;
 +      int early_out;
 +      struct SeqEffectHandle sh = get_sequence_effect(seq);
 +
 +      if (!sh.execute) { /* effect not supported in this version... */
 +              make_black_ibuf(se->ibuf);
 +              return;
 +      }
 +
 +#if 0 // XXX old animation system
 +      if(seq->ipo && seq->ipo->curve.first) {
 +              do_seq_ipo(scene, seq, cfra);
 +              fac= seq->facf0;
 +              facf= seq->facf1;
 +      } else
 +#endif // XXX old animation system    
 +      {
 +              sh.get_default_fac(seq, cfra, &fac, &facf);
 +      }
 +
 +      if( !(scene->r.mode & R_FIELDS) ) facf = fac;
 +
 +      early_out = sh.early_out(seq, fac, facf);
 +
 +      if (early_out == -1) { /* no input needed */
 +              sh.execute(seq, cfra, fac, facf, 
 +                         se->ibuf->x, se->ibuf->y, 
 +                         0, 0, 0, se->ibuf);
 +              return;
 +      }
 +
 +      switch (early_out) {
 +      case 0:
 +              if (se->se1==0 || se->se2==0 || se->se3==0) {
 +                      make_black_ibuf(se->ibuf);
 +                      return;
 +              }
 +
 +              se1= se->se1;
 +              se2= se->se2;
 +              se3= se->se3;
 +
 +              if (   (se1==0 || se2==0 || se3==0)
 +                  || (se1->ibuf==0 || se2->ibuf==0 || se3->ibuf==0)) {
 +                      make_black_ibuf(se->ibuf);
 +                      return;
 +              }
 +
 +              break;
 +      case 1:
 +              if (se->se1 == 0) {
 +                      make_black_ibuf(se->ibuf);
 +                      return;
 +              }
 +
 +              se1= se->se1;
 +
 +              if (se1 == 0 || se1->ibuf == 0) {
 +                      make_black_ibuf(se->ibuf);
 +                      return;
 +              }
 +
 +              if (se->ibuf != se1->ibuf) {
 +                      IMB_freeImBuf(se->ibuf);
 +                      se->ibuf = se1->ibuf;
 +                      IMB_refImBuf(se->ibuf);
 +              }
 +              return;
 +      case 2:
 +              if (se->se2 == 0) {
 +                      make_black_ibuf(se->ibuf);
 +                      return;
 +              }
 +
 +              se2= se->se2;
 +
 +              if (se2 == 0 || se2->ibuf == 0) {
 +                      make_black_ibuf(se->ibuf);
 +                      return;
 +              }
 +              if (se->ibuf != se2->ibuf) {
 +                      IMB_freeImBuf(se->ibuf);
 +                      se->ibuf = se2->ibuf;
 +                      IMB_refImBuf(se->ibuf);
 +              }
 +              return;
 +      default:
 +              make_black_ibuf(se->ibuf);
 +              return;
 +      }
 +
 +      x= se2->ibuf->x;
 +      y= se2->ibuf->y;
 +
 +      if (!se1->ibuf->rect_float && se->ibuf->rect_float) {
 +              IMB_float_from_rect(se1->ibuf);
 +      }
 +      if (!se2->ibuf->rect_float && se->ibuf->rect_float) {
 +              IMB_float_from_rect(se2->ibuf);
 +      }
 +      if (!se3->ibuf->rect_float && se->ibuf->rect_float) {
 +              IMB_float_from_rect(se3->ibuf);
 +      }
 +      
 +      if (!se1->ibuf->rect && !se->ibuf->rect_float) {
 +              IMB_rect_from_float(se1->ibuf);
 +      }
 +      if (!se2->ibuf->rect && !se->ibuf->rect_float) {
 +              IMB_rect_from_float(se2->ibuf);
 +      }
 +      if (!se3->ibuf->rect && !se->ibuf->rect_float) {
 +              IMB_rect_from_float(se3->ibuf);
 +      }
 +
 +      sh.execute(seq, cfra, fac, facf, x, y, se1->ibuf, se2->ibuf, se3->ibuf,
 +                 se->ibuf);
 +}
 +
 +static int give_stripelem_index(Sequence *seq, int cfra)
 +{
 +      int nr;
 +
 +      if(seq->startdisp >cfra || seq->enddisp <= cfra) return -1;
 +      if(seq->len == 0) return -1;
 +      if(seq->flag&SEQ_REVERSE_FRAMES) {      
 +              /*reverse frame in this sequence */
 +              if(cfra <= seq->start) nr= seq->len-1;
 +              else if(cfra >= seq->start+seq->len-1) nr= 0;
 +              else nr= (seq->start + seq->len) - cfra;
 +      } else {
 +              if(cfra <= seq->start) nr= 0;
 +              else if(cfra >= seq->start+seq->len-1) nr= seq->len-1;
 +              else nr= cfra-seq->start;
 +      }
 +      if (seq->strobe < 1.0) seq->strobe = 1.0;
 +      if (seq->strobe > 1.0) {
 +              nr -= (int)fmod((double)nr, (double)seq->strobe);
 +      }
 +
 +      return nr;
 +}
 +
 +static TStripElem* alloc_tstripdata(int len, const char * name)
 +{
 +      int i;
 +      TStripElem *se = MEM_callocN(len * sizeof(TStripElem), name);
 +      for (i = 0; i < len; i++) {
 +              se[i].ok = STRIPELEM_OK;
 +      }
 +      return se;
 +}
 +
 +TStripElem *give_tstripelem(Sequence *seq, int cfra)
 +{
 +      TStripElem *se;
 +      int nr;
 +
 +      se = seq->strip->tstripdata;
 +      if (se == 0 && seq->len > 0) {
 +              se = seq->strip->tstripdata = alloc_tstripdata(seq->len,
 +                                                             "tstripelems");
 +      }
 +      nr = give_stripelem_index(seq, cfra);
 +
 +      if (nr == -1) return 0;
 +      if (se == 0) return 0;
 +
 +      se += nr; 
 +
 +      /* if there are IPOs with blend modes active, one has to watch out
 +         for startstill + endstill area: we can't use the same tstripelem
 +         here for all ibufs, since then, blending with IPOs won't work!
 +         
 +         Rather common case, if you use a single image and try to fade
 +         it in and out... or want to use your strip as a watermark in
 +         alpha over mode...
 +      */
 +      if (seq->blend_mode != SEQ_BLEND_REPLACE ||
 +          (/*seq->ipo && seq->ipo->curve.first &&*/ 
 +                 (!(seq->type & SEQ_EFFECT) || !seq->seq1))) {
 +              Strip * s = seq->strip;
 +              if (cfra < seq->start) {
 +                      se = s->tstripdata_startstill;
 +                      if (seq->startstill > s->startstill) {
 +                              free_tstripdata(s->startstill, 
 +                                              s->tstripdata_startstill);
 +                              se = 0;
 +                      }
 +
 +                      if (se == 0) {
 +                              s->startstill = seq->startstill;
 +                              se = seq->strip->tstripdata_startstill
 +                                      = alloc_tstripdata(
 +                                              s->startstill,
 +                                              "tstripelems_startstill");
 +                      }
 +                      se += seq->start - cfra - 1;
 +
 +              } else if (cfra > seq->start + seq->len-1) {
 +                      se = s->tstripdata_endstill;
 +                      if (seq->endstill > s->endstill) {
 +                              free_tstripdata(s->endstill, 
 +                                              s->tstripdata_endstill);
 +                              se = 0;
 +                      }
 +
 +                      if (se == 0) {
 +                              s->endstill = seq->endstill;
 +                              se = seq->strip->tstripdata_endstill
 +                                      = alloc_tstripdata(
 +                                              s->endstill,
 +                                              "tstripelems_endstill");
 +                      }
 +                      se += cfra - (seq->start + seq->len-1) - 1;
 +              }
 +      }
 +
 +      
 +      se->nr= nr;
 +
 +      return se;
 +}
 +
 +StripElem *give_stripelem(Sequence *seq, int cfra)
 +{
 +      StripElem *se;
 +      int nr;
 +
 +      se = seq->strip->stripdata;
 +      nr = give_stripelem_index(seq, cfra);
 +
 +      if (nr == -1) return 0;
 +      if (se == 0) return 0;
 +
 +      se += nr + seq->anim_startofs; 
 +      
 +      return se;
 +}
 +
 +static int evaluate_seq_frame_gen(Sequence ** seq_arr, ListBase *seqbase, int cfra)
 +{
 +      Sequence *seq;
 +      int totseq=0;
 +
 +      memset(seq_arr, 0, sizeof(Sequence*) * (MAXSEQ+1));
 +
 +      seq= seqbase->first;
 +      while(seq) {
 +              if(seq->startdisp <=cfra && seq->enddisp > cfra) {
 +                      seq_arr[seq->machine]= seq;
 +                      totseq++;
 +              }
 +              seq= seq->next;
 +      }
 +
 +      return totseq;
 +}
 +
 +int evaluate_seq_frame(Scene *scene, int cfra)
 +{
 +      Editing *ed= seq_give_editing(scene, FALSE);
 +      Sequence *seq_arr[MAXSEQ+1];
 +
 +      if(ed==NULL) return 0;
 +      return evaluate_seq_frame_gen(seq_arr, ed->seqbasep, cfra);
 +}
 +
 +static int video_seq_is_rendered(Sequence * seq)
 +{
 +      return (seq 
 +              && !(seq->flag & SEQ_MUTE) 
 +              && seq->type != SEQ_RAM_SOUND 
 +              && seq->type != SEQ_HD_SOUND);
 +}
 +
 +static int get_shown_sequences(       ListBase * seqbasep, int cfra, int chanshown, Sequence ** seq_arr_out)
 +{
 +      Sequence *seq_arr[MAXSEQ+1];
 +      int b = chanshown;
 +      int cnt = 0;
 +
 +      if (b > MAXSEQ) {
 +              return 0;
 +      }
 +
 +      if(evaluate_seq_frame_gen(seq_arr, seqbasep, cfra)) {
 +              if (b > 0) {
 +                      if (seq_arr[b] == 0) {
 +                              return 0;
 +                      }
 +              } else {
 +                      for (b = MAXSEQ; b > 0; b--) {
 +                              if (video_seq_is_rendered(seq_arr[b])) {
 +                                      break;
 +                              }
 +                      }
 +              }
 +      }
 +      
 +      chanshown = b;
 +
 +      for (;b > 0; b--) {
 +              if (video_seq_is_rendered(seq_arr[b])) {
 +                      if (seq_arr[b]->blend_mode == SEQ_BLEND_REPLACE) {
 +                              break;
 +                      }
 +              }
 +      }
 +
 +      for (;b <= chanshown; b++) {
 +              if (video_seq_is_rendered(seq_arr[b])) {
 +                      seq_arr_out[cnt++] = seq_arr[b];
 +              }
 +      }
 +
 +      return cnt;
 +}
 + 
 +
 +/* **********************************************************************
 +   proxy management
 +   ********************************************************************** */
 +
 +#define PROXY_MAXFILE (2*FILE_MAXDIR+FILE_MAXFILE)
 +
 +static int seq_proxy_get_fname(Scene *scene, Sequence * seq, int cfra, char * name)
 +{
 +      int frameno;
 +      char dir[FILE_MAXDIR];
 +
 +      if (!seq->strip->proxy) {
 +              return FALSE;
 +      }
 +
 +      if (seq->flag & SEQ_USE_PROXY_CUSTOM_DIR) {
 +              strcpy(dir, seq->strip->proxy->dir);
 +      } else {
 +              if (seq->type == SEQ_IMAGE || seq->type == SEQ_MOVIE) {
 +                      snprintf(dir, FILE_MAXDIR, "%s/BL_proxy", 
 +                               seq->strip->dir);
 +              } else {
 +                      return FALSE;
 +              }
 +      }
 +
 +      /* generate a seperate proxy directory for each preview size */
 +
 +      if (seq->type == SEQ_IMAGE) {
 +              StripElem * se = give_stripelem(seq, cfra);
 +              snprintf(name, PROXY_MAXFILE, "%s/images/%d/%s_proxy",
 +                       dir, scene->r.size, se->name);
 +              frameno = 1;
 +      } else if (seq->type == SEQ_MOVIE) {
 +              TStripElem * tse = give_tstripelem(seq, cfra);
 +
 +              frameno = tse->nr + seq->anim_startofs;
 +
 +              snprintf(name, PROXY_MAXFILE, "%s/%s/%d/####", dir,
 +                       seq->strip->stripdata->name,
 +                       scene->r.size);
 +      } else {
 +              TStripElem * tse = give_tstripelem(seq, cfra);
 +
 +              frameno = tse->nr + seq->anim_startofs;
 +
 +              snprintf(name, PROXY_MAXFILE, "%s/proxy_misc/%d/####", dir,
 +                       scene->r.size);
 +      }
 +
 +      BLI_convertstringcode(name, G.sce);
 +      BLI_convertstringframe(name, frameno);
 +      
 +
 +      strcat(name, ".jpg");
 +
 +      return TRUE;
 +}
 +
 +static struct ImBuf * seq_proxy_fetch(Scene *scene, Sequence * seq, int cfra)
 +{
 +      char name[PROXY_MAXFILE];
 +
 +      if (!(seq->flag & SEQ_USE_PROXY)) {
 +              return 0;
 +      }
 +
 +      /* rendering at 100% ? No real sense in proxy-ing, right? */
 +      if (scene->r.size == 100.0) {
 +              return 0;
 +      }
 +
 +      if (!seq_proxy_get_fname(scene, seq, cfra, name)) {
 +              return 0;
 +      }
 +
 +      if (BLI_exists(name)) {
 +              return IMB_loadiffname(name, IB_rect);
 +      } else {
 +              return 0;
 +      }
 +}
 +
 +static void do_build_seq_ibuf(Scene *scene, Sequence * seq, TStripElem *se, int cfra,
 +                            int build_proxy_run);
 +
 +static void seq_proxy_build_frame(Scene *scene, Sequence * seq, int cfra)
 +{
 +      char name[PROXY_MAXFILE];
 +      int quality;
 +      TStripElem * se;
 +      int ok;
 +      int rectx, recty;
 +      struct ImBuf * ibuf;
 +
 +      if (!(seq->flag & SEQ_USE_PROXY)) {
 +              return;
 +      }
 +
 +      /* rendering at 100% ? No real sense in proxy-ing, right? */
 +      if (scene->r.size == 100.0) {
 +              return;
 +      }
 +
 +      if (!seq_proxy_get_fname(scene, seq, cfra, name)) {
 +              return;
 +      }
 +
 +      se = give_tstripelem(seq, cfra);
 +      if (!se) {
 +              return;
 +      }
 +
 +      if(se->ibuf) {
 +              IMB_freeImBuf(se->ibuf);
 +              se->ibuf = 0;
 +      }
 +      
 +      do_build_seq_ibuf(scene, seq, se, cfra, TRUE);
 +
 +      if (!se->ibuf) {
 +              return;
 +      }
 +
 +      rectx= (scene->r.size*scene->r.xsch)/100;
 +      recty= (scene->r.size*scene->r.ysch)/100;
 +
 +      ibuf = se->ibuf;
 +
 +      if (ibuf->x != rectx || ibuf->y != recty) {
 +              IMB_scalefastImBuf(ibuf, (short)rectx, (short)recty);
 +      }
 +
 +      /* quality is fixed, otherwise one has to generate seperate
 +         directories for every quality...
 +
 +         depth = 32 is intentionally left in, otherwise ALPHA channels
 +         won't work... */
 +      quality = 90;
 +      ibuf->ftype= JPG | quality;
 +
 +      BLI_make_existing_file(name);
 +      
 +      ok = IMB_saveiff(ibuf, name, IB_rect | IB_zbuf | IB_zbuffloat);
 +      if (ok == 0) {
 +              perror(name);
 +      }
 +
 +      IMB_freeImBuf(ibuf);
 +      se->ibuf = 0;
 +}
 +
 +void seq_proxy_rebuild(Scene *scene, Sequence * seq)
 +{
 +      int cfra;
 +
 +      waitcursor(1);
 +
 +      G.afbreek = 0;
 +
 +      /* flag management tries to account for strobe and 
 +         other "non-linearities", that might come in the future...
 +         better way would be to "touch" the files, so that _really_
 +         no one is rebuild twice.
 +       */
 +
 +      for (cfra = seq->startdisp; cfra < seq->enddisp; cfra++) {
 +              TStripElem * tse = give_tstripelem(seq, cfra);
 +
 +              tse->flag &= ~STRIPELEM_PREVIEW_DONE;
 +      }
 +
 +      /* a _lot_ faster for movie files, if we read frames in
 +         sequential order */
 +      if (seq->flag & SEQ_REVERSE_FRAMES) {
 +              for (cfra = seq->enddisp-seq->endstill-1; 
 +                   cfra >= seq->startdisp + seq->startstill; cfra--) {
 +                      TStripElem * tse = give_tstripelem(seq, cfra);
 +
 +                      if (!(tse->flag & STRIPELEM_PREVIEW_DONE)) {
 +                              seq_proxy_build_frame(scene, seq, cfra);
 +                              tse->flag |= STRIPELEM_PREVIEW_DONE;
 +                      }
 +                      if (blender_test_break()) {
 +                              break;
 +                      }
 +              }
 +      } else {
 +              for (cfra = seq->startdisp + seq->startstill; 
 +                   cfra < seq->enddisp - seq->endstill; cfra++) {
 +                      TStripElem * tse = give_tstripelem(seq, cfra);
 +
 +                      if (!(tse->flag & STRIPELEM_PREVIEW_DONE)) {
 +                              seq_proxy_build_frame(scene, seq, cfra);
 +                              tse->flag |= STRIPELEM_PREVIEW_DONE;
 +                      }
 +                      if (blender_test_break()) {
 +                              break;
 +                      }
 +              }
 +      }
 +      waitcursor(0);
 +}
 +
 +
 +/* **********************************************************************
 +   color balance 
 +   ********************************************************************** */
 +
 +static StripColorBalance calc_cb(StripColorBalance * cb_)
 +{
 +      StripColorBalance cb = *cb_;
 +      int c;
 +
 +      if (cb.flag & SEQ_COLOR_BALANCE_INVERSE_LIFT) {
 +              for (c = 0; c < 3; c++) {
 +                      cb.lift[c] = 1.0 - cb.lift[c];
 +              }
 +      } else {
 +              for (c = 0; c < 3; c++) {
 +                      cb.lift[c] = -(1.0 - cb.lift[c]);
 +              }
 +      }
 +      if (cb.flag & SEQ_COLOR_BALANCE_INVERSE_GAIN) {
 +              for (c = 0; c < 3; c++) {
 +                      if (cb.gain[c] != 0.0) {
 +                              cb.gain[c] = 1.0/cb.gain[c];
 +                      } else {
 +                              cb.gain[c] = 1000000; /* should be enough :) */
 +                      }
 +              }
 +      }
 +
 +      if (!(cb.flag & SEQ_COLOR_BALANCE_INVERSE_GAMMA)) {
 +              for (c = 0; c < 3; c++) {
 +                      if (cb.gamma[c] != 0.0) {
 +                              cb.gamma[c] = 1.0/cb.gamma[c];
 +                      } else {
 +                              cb.gamma[c] = 1000000; /* should be enough :) */
 +                      }
 +              }
 +      }
 +
 +      return cb;
 +}
 +
 +static void make_cb_table_byte(float lift, float gain, float gamma,
 +                             unsigned char * table, float mul)
 +{
 +      int y;
 +
 +      for (y = 0; y < 256; y++) {
 +              float v = 1.0 * y / 255;
 +              v *= gain;
 +              v += lift; 
 +              v = pow(v, gamma);
 +              v *= mul;
 +              if ( v > 1.0) {
 +                      v = 1.0;
 +              } else if (v < 0.0) {
 +                      v = 0.0;
 +              }
 +              table[y] = v * 255;
 +      }
 +
 +}
 +
 +static void make_cb_table_float(float lift, float gain, float gamma,
 +                              float * table, float mul)
 +{
 +      int y;
 +
 +      for (y = 0; y < 256; y++) {
 +              float v = (float) y * 1.0 / 255.0;
 +              v *= gain;
 +              v += lift;
 +              v = pow(v, gamma);
 +              v *= mul;
 +              table[y] = v;
 +      }
 +}
 +
 +static void color_balance_byte_byte(Sequence * seq, TStripElem* se, float mul)
 +{
 +      unsigned char cb_tab[3][256];
 +      int c;
 +      unsigned char * p = (unsigned char*) se->ibuf->rect;
 +      unsigned char * e = p + se->ibuf->x * 4 * se->ibuf->y;
 +
 +      StripColorBalance cb = calc_cb(seq->strip->color_balance);
 +
 +      for (c = 0; c < 3; c++) {
 +              make_cb_table_byte(cb.lift[c], cb.gain[c], cb.gamma[c],
 +                                 cb_tab[c], mul);
 +      }
 +
 +      while (p < e) {
 +              p[0] = cb_tab[0][p[0]];
 +              p[1] = cb_tab[1][p[1]];
 +              p[2] = cb_tab[2][p[2]];
 +              
 +              p += 4;
 +      }
 +}
 +
 +static void color_balance_byte_float(Sequence * seq, TStripElem* se, float mul)
 +{
 +      float cb_tab[4][256];
 +      int c,i;
 +      unsigned char * p = (unsigned char*) se->ibuf->rect;
 +      unsigned char * e = p + se->ibuf->x * 4 * se->ibuf->y;
 +      float * o;
 +      StripColorBalance cb;
 +
 +      imb_addrectfloatImBuf(se->ibuf);
 +
 +      o = se->ibuf->rect_float;
 +
 +      cb = calc_cb(seq->strip->color_balance);
 +
 +      for (c = 0; c < 3; c++) {
 +              make_cb_table_float(cb.lift[c], cb.gain[c], cb.gamma[c],
 +                                  cb_tab[c], mul);
 +      }
 +
 +      for (i = 0; i < 256; i++) {
 +              cb_tab[3][i] = ((float)i)*(1.0f/255.0f);
 +      }
 +
 +      while (p < e) {
 +              o[0] = cb_tab[0][p[0]];
 +              o[1] = cb_tab[1][p[1]];
 +              o[2] = cb_tab[2][p[2]];
 +              o[3] = cb_tab[3][p[3]];
 +
 +              p += 4; o += 4;
 +      }
 +}
 +
 +static void color_balance_float_float(Sequence * seq, TStripElem* se, float mul)
 +{
 +      float * p = se->ibuf->rect_float;
 +      float * e = se->ibuf->rect_float + se->ibuf->x * 4* se->ibuf->y;
 +      StripColorBalance cb = calc_cb(seq->strip->color_balance);
 +
 +      while (p < e) {
 +              int c;
 +              for (c = 0; c < 3; c++) {
 +                      p[c] = pow(p[c] * cb.gain[c] + cb.lift[c], 
 +                                 cb.gamma[c]) * mul;
 +              }
 +              p += 4;
 +      }
 +}
 +
 +static void color_balance(Sequence * seq, TStripElem* se, float mul)
 +{
 +      if (se->ibuf->rect_float) {
 +              color_balance_float_float(seq, se, mul);
 +      } else if(seq->flag & SEQ_MAKE_FLOAT) {
 +              color_balance_byte_float(seq, se, mul);
 +      } else {
 +              color_balance_byte_byte(seq, se, mul);
 +      }
 +}
 +
 +/*
 +  input preprocessing for SEQ_IMAGE, SEQ_MOVIE and SEQ_SCENE
 +
 +  Do all the things you can't really do afterwards using sequence effects
 +  (read: before rescaling to render resolution has been done)
 +
 +  Order is important!
 +
 +  - Deinterlace
 +  - Crop and transform in image source coordinate space
 +  - Flip X + Flip Y (could be done afterwards, backward compatibility)
 +  - Promote image to float data (affects pipeline operations afterwards)
 +  - Color balance (is most efficient in the byte -> float 
 +    (future: half -> float should also work fine!)
 +    case, if done on load, since we can use lookup tables)
 +  - Premultiply
 +
 +*/
 +
 +static int input_have_to_preprocess(Scene *scene, Sequence * seq, TStripElem* se, int cfra)
 +{
 +      float mul;
 +
 +      if ((seq->flag & SEQ_FILTERY) || 
 +          (seq->flag & SEQ_USE_CROP) ||
 +          (seq->flag & SEQ_USE_TRANSFORM) ||
 +          (seq->flag & SEQ_FLIPX) ||
 +          (seq->flag & SEQ_FLIPY) ||
 +          (seq->flag & SEQ_USE_COLOR_BALANCE) ||
 +          (seq->flag & SEQ_MAKE_PREMUL) ||
 +          (se->ibuf->x != seqrectx || se->ibuf->y != seqrecty)) {
 +              return TRUE;
 +      }
 +
 +      mul = seq->mul;
 +
 +      if(seq->blend_mode == SEQ_BLEND_REPLACE) {
 +#if 0 // XXX old animation system
 +              if (seq->ipo && seq->ipo->curve.first) {
 +                      do_seq_ipo(scene, seq, cfra);
 +                      mul *= seq->facf0;
 +              }
 +#endif // XXX old animation system
 +              mul *= seq->blend_opacity / 100.0;
 +      }
 +
 +      if (mul != 1.0) {
 +              return TRUE;
 +      }
 +              
 +      return FALSE;
 +}
 +
 +static void input_preprocess(Scene *scene, Sequence *seq, TStripElem *se, int cfra)
 +{
 +      float mul;
 +
 +      seq->strip->orx= se->ibuf->x;
 +      seq->strip->ory= se->ibuf->y;
 +
 +      if((seq->flag & SEQ_FILTERY) && seq->type != SEQ_MOVIE) {
 +              IMB_filtery(se->ibuf);
 +      }
 +
 +      if(seq->flag & SEQ_USE_CROP || seq->flag & SEQ_USE_TRANSFORM) {
 +              StripCrop c;
 +              StripTransform t;
 +              int sx,sy,dx,dy;
 +
 +              memset(&c, 0, sizeof(StripCrop));
 +              memset(&t, 0, sizeof(StripTransform));
 +
 +              if(seq->flag & SEQ_USE_CROP && seq->strip->crop) {
 +                      c = *seq->strip->crop;
 +              }
 +              if(seq->flag & SEQ_USE_TRANSFORM && seq->strip->transform) {
 +                      t = *seq->strip->transform;
 +              }
 +
 +              sx = se->ibuf->x - c.left - c.right;
 +              sy = se->ibuf->y - c.top - c.bottom;
 +              dx = sx;
 +              dy = sy;
 +
 +              if (seq->flag & SEQ_USE_TRANSFORM) {
 +                      dx = scene->r.xsch;
 +                      dy = scene->r.ysch;
 +              }
 +
 +              if (c.top + c.bottom >= se->ibuf->y ||
 +                  c.left + c.right >= se->ibuf->x ||
 +                  t.xofs >= dx || t.yofs >= dy) {
 +                      make_black_ibuf(se->ibuf);
 +              } else {
 +                      ImBuf * i;
 +
 +                      if (se->ibuf->rect_float) {
 +                              i = IMB_allocImBuf(dx, dy,32, IB_rectfloat, 0);
 +                      } else {
 +                              i = IMB_allocImBuf(dx, dy,32, IB_rect, 0);
 +                      }
 +
 +                      IMB_rectcpy(i, se->ibuf, 
 +                                  t.xofs, t.yofs, 
 +                                  c.left, c.bottom, 
 +                                  sx, sy);
 +
 +                      IMB_freeImBuf(se->ibuf);
 +
 +                      se->ibuf = i;
 +              }
 +      } 
 +
 +      if(seq->flag & SEQ_FLIPX) {
 +              IMB_flipx(se->ibuf);
 +      }
 +      if(seq->flag & SEQ_FLIPY) {
 +              IMB_flipy(se->ibuf);
 +      }
 +
 +      if(seq->mul == 0.0) {
 +              seq->mul = 1.0;
 +      }
 +
 +      mul = seq->mul;
 +
 +      if(seq->blend_mode == SEQ_BLEND_REPLACE) {
 +#if 0 // XXX old animation system
 +              if (seq->ipo && seq->ipo->curve.first) {
 +                      do_seq_ipo(scene, seq, cfra);
 +                      mul *= seq->facf0;
 +              }
 +#endif // XXX old animation system
 +              mul *= seq->blend_opacity / 100.0;
 +      }
 +
 +      if(seq->flag & SEQ_USE_COLOR_BALANCE && seq->strip->color_balance) {
 +              color_balance(seq, se, mul);
 +              mul = 1.0;
 +      }
 +
 +      if(seq->flag & SEQ_MAKE_FLOAT) {
 +              if (!se->ibuf->rect_float) {
 +                      IMB_float_from_rect(se->ibuf);
 +              }
 +              if (se->ibuf->rect) {
 +                      imb_freerectImBuf(se->ibuf);
 +              }
 +      }
 +
 +      if(mul != 1.0) {
 +              multibuf(se->ibuf, mul);
 +      }
 +
 +      if(seq->flag & SEQ_MAKE_PREMUL) {
 +              if(se->ibuf->depth == 32 && se->ibuf->zbuf == 0) {
 +                      converttopremul(se->ibuf);
 +              }
 +      }
 +
 +
 +      if(se->ibuf->x != seqrectx || se->ibuf->y != seqrecty ) {
 +              if(scene->r.mode & R_OSA) {
 +                      IMB_scaleImBuf(se->ibuf, 
 +                                     (short)seqrectx, (short)seqrecty);
 +              } else {
 +                      IMB_scalefastImBuf(se->ibuf, 
 +                                         (short)seqrectx, (short)seqrecty);
 +              }
 +      }
 +}
 +
 +/* test if image too small or discarded from cache: reload */
 +
 +static void test_and_auto_discard_ibuf(TStripElem * se)
 +{
 +      if (se->ibuf) {
 +              if(se->ibuf->x != seqrectx || se->ibuf->y != seqrecty 
 +                 || !(se->ibuf->rect || se->ibuf->rect_float)) {
 +                      IMB_freeImBuf(se->ibuf);
 +
 +                      se->ibuf= 0;
 +                      se->ok= STRIPELEM_OK;
 +              }
 +      }
 +      if (se->ibuf_comp) {
 +              if(se->ibuf_comp->x != seqrectx || se->ibuf_comp->y != seqrecty 
 +                 || !(se->ibuf_comp->rect || se->ibuf_comp->rect_float)) {
 +                      IMB_freeImBuf(se->ibuf_comp);
 +
 +                      se->ibuf_comp = 0;
 +              }
 +      }
 +}
 +
 +static void test_and_auto_discard_ibuf_stills(Strip * strip)
 +{
 +      if (strip->ibuf_startstill) {
 +              if (!strip->ibuf_startstill->rect &&
 +                  !strip->ibuf_startstill->rect_float) {
 +                      IMB_freeImBuf(strip->ibuf_startstill);
 +                      strip->ibuf_startstill = 0;
 +              }
 +      }
 +      if (strip->ibuf_endstill) {
 +              if (!strip->ibuf_endstill->rect &&
 +                  !strip->ibuf_endstill->rect_float) {
 +                      IMB_freeImBuf(strip->ibuf_endstill);
 +                      strip->ibuf_endstill = 0;
 +              }
 +      }
 +}
 +
 +static void copy_from_ibuf_still(Sequence * seq, TStripElem * se)
 +{
 +      if (!se->ibuf) {
 +              if (se->nr == 0 && seq->strip->ibuf_startstill) {
 +                      IMB_cache_limiter_touch(seq->strip->ibuf_startstill);
 +
 +                      se->ibuf = IMB_dupImBuf(seq->strip->ibuf_startstill);
 +              }
 +              if (se->nr == seq->len - 1 
 +                  && (seq->len != 1)
 +                  && seq->strip->ibuf_endstill) {
 +                      IMB_cache_limiter_touch(seq->strip->ibuf_endstill);
 +
 +                      se->ibuf = IMB_dupImBuf(seq->strip->ibuf_endstill);
 +              }
 +      }
 +}
 +
 +static void copy_to_ibuf_still(Sequence * seq, TStripElem * se)
 +{
 +      if (se->ibuf) {
 +              if (se->nr == 0) {
 +                      seq->strip->ibuf_startstill = IMB_dupImBuf(se->ibuf);
 +
 +                      IMB_cache_limiter_insert(seq->strip->ibuf_startstill);
 +                      IMB_cache_limiter_touch(seq->strip->ibuf_startstill);
 +              }
 +              if (se->nr == seq->len - 1 && seq->len != 1) {
 +                      seq->strip->ibuf_endstill = IMB_dupImBuf(se->ibuf);
 +
 +                      IMB_cache_limiter_insert(seq->strip->ibuf_endstill);
 +                      IMB_cache_limiter_touch(seq->strip->ibuf_endstill);
 +              }
 +      }
 +}
 +
 +static void free_metastrip_imbufs(ListBase *seqbasep, int cfra, int chanshown)
 +{
 +      Sequence* seq_arr[MAXSEQ+1];
 +      int i;
 +      TStripElem* se = 0;
 +
 +      evaluate_seq_frame_gen(seq_arr, seqbasep, cfra);
 +
 +      for (i = 0; i < MAXSEQ; i++) {
 +              if (!video_seq_is_rendered(seq_arr[i])) {
 +                      continue;
 +              }
 +              se = give_tstripelem(seq_arr[i], cfra);
 +              if (se) {
 +                      if (se->ibuf) {
 +                              IMB_freeImBuf(se->ibuf);
 +
 +                              se->ibuf= 0;
 +                              se->ok= STRIPELEM_OK;
 +                      }
 +
 +                      if (se->ibuf_comp) {
 +                              IMB_freeImBuf(se->ibuf_comp);
 +
 +                              se->ibuf_comp = 0;
 +                      }
 +              }
 +      }
 +      
 +}
 +
 +static TStripElem* do_build_seq_array_recursively(Scene *scene,
 +                              ListBase *seqbasep, int cfra, int chanshown);
 +
 +static void do_build_seq_ibuf(Scene *scene, Sequence * seq, TStripElem *se, int cfra,
 +                            int build_proxy_run)
 +{
 +      char name[FILE_MAXDIR+FILE_MAXFILE];
 +      int use_limiter = TRUE;
 +
 +      test_and_auto_discard_ibuf(se);
 +      test_and_auto_discard_ibuf_stills(seq->strip);
 +
 +      if(seq->type == SEQ_META) {
 +              TStripElem * meta_se = 0;
 +              use_limiter = FALSE;
 +
 +              if (!build_proxy_run && se->ibuf == 0) {
 +                      se->ibuf = seq_proxy_fetch(scene, seq, cfra);
 +                      if (se->ibuf) {
 +                              use_limiter = TRUE;
 +                      }
 +              }
 +
 +              if(!se->ibuf && seq->seqbase.first) {
 +                      meta_se = do_build_seq_array_recursively(scene,
 +                              &seq->seqbase, seq->start + se->nr, 0);
 +              }
 +
 +              se->ok = STRIPELEM_OK;
 +
 +              if(!se->ibuf && meta_se) {
 +                      se->ibuf = meta_se->ibuf_comp;
 +                      if(se->ibuf &&
 +                         (!input_have_to_preprocess(scene, seq, se, cfra) ||
 +                          build_proxy_run)) {
 +                              IMB_refImBuf(se->ibuf);
 +                              if (build_proxy_run) {
 +                                      IMB_cache_limiter_unref(se->ibuf);
 +                              }
 +                      } else if (se->ibuf) {
 +                              struct ImBuf * i = IMB_dupImBuf(se->ibuf);
 +
 +                              IMB_cache_limiter_unref(se->ibuf);
 +
 +                              se->ibuf = i;
 +
 +                              use_limiter = TRUE;
 +                      }
 +              }
 +              if (meta_se) {
 +                      free_metastrip_imbufs(
 +                              &seq->seqbase, seq->start + se->nr, 0);
 +              }
 +
 +              if (use_limiter) {
 +                      input_preprocess(scene, seq, se, cfra);
 +              }
 +      } else if(seq->type & SEQ_EFFECT) {
 +              /* should the effect be recalculated? */
 +              
 +              if (!build_proxy_run && se->ibuf == 0) {
 +                      se->ibuf = seq_proxy_fetch(scene, seq, cfra);
 +              }
 +
 +              if(se->ibuf == 0) {
 +                      /* if any inputs are rectfloat, output is float too */
 +                      if((se->se1 && se->se1->ibuf && se->se1->ibuf->rect_float) ||
 +                         (se->se2 && se->se2->ibuf && se->se2->ibuf->rect_float) ||
 +                         (se->se3 && se->se3->ibuf && se->se3->ibuf->rect_float))
 +                              se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0);
 +                      else
 +                              se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0);
 +                      
 +                      do_effect(scene, cfra, seq, se);
 +              }
 +      } else if(seq->type == SEQ_IMAGE) {
 +              if(se->ok == STRIPELEM_OK && se->ibuf == 0) {
 +                      StripElem * s_elem = give_stripelem(seq, cfra);
 +                      BLI_join_dirfile(name, seq->strip->dir, s_elem->name);
 +                      BLI_convertstringcode(name, G.sce);
 +                      BLI_convertstringframe(name, scene->r.cfra);
 +                      if (!build_proxy_run) {
 +                              se->ibuf = seq_proxy_fetch(scene, seq, cfra);
 +                      }
 +                      copy_from_ibuf_still(seq, se);
 +
 +                      if (!se->ibuf) {
 +                              se->ibuf= IMB_loadiffname(
 +                                      name, IB_rect);
 +                              copy_to_ibuf_still(seq, se);
 +                      }
 +                      
 +                      if(se->ibuf == 0) {
 +                              se->ok = STRIPELEM_FAILED;
 +                      } else if (!build_proxy_run) {
 +                              input_preprocess(scene, seq, se, cfra);
 +                      }
 +              }
 +      } else if(seq->type == SEQ_MOVIE) {
 +              if(se->ok == STRIPELEM_OK && se->ibuf==0) {
 +                      if(!build_proxy_run) {
 +                              se->ibuf = seq_proxy_fetch(scene, seq, cfra);
 +                      }
 +                      copy_from_ibuf_still(seq, se);
 +
 +                      if (se->ibuf == 0) {
 +                              if(seq->anim==0) {
 +                                      BLI_join_dirfile(name, seq->strip->dir, seq->strip->stripdata->name);
 +                                      BLI_convertstringcode(name, G.sce);
 +                                      BLI_convertstringframe(name, scene->r.cfra);
 +                                      
 +                                      seq->anim = openanim(
 +                                              name, IB_rect | 
 +                                              ((seq->flag & SEQ_FILTERY) 
 +                                               ? IB_animdeinterlace : 0));
 +                              }
 +                              if(seq->anim) {
 +                                      IMB_anim_set_preseek(seq->anim, seq->anim_preseek);
 +                                      se->ibuf = IMB_anim_absolute(seq->anim, se->nr + seq->anim_startofs);
 +                              }
 +                              copy_to_ibuf_still(seq, se);
 +                      }
 +                      
 +                      if(se->ibuf == 0) {
 +                              se->ok = STRIPELEM_FAILED;
 +                      } else if (!build_proxy_run) {
 +                              input_preprocess(scene, seq, se, cfra);
 +                      }
 +              }
 +      } else if(seq->type == SEQ_SCENE) {     // scene can be NULL after deletions
 +#if 0
 +              /* XXX move entirely to render? */
 +              int oldcfra = CFRA;
 +              Sequence * oldseq = get_last_seq();
 +              Scene *sce= seq->scene, *oldsce= scene;
 +              Render *re;
 +              RenderResult rres;
 +              int doseq, rendering= G.rendering;
 +              char scenename[64];
 +              int sce_valid =sce&& (sce->camera || sce->r.scemode & R_DOSEQ);
 +                      
 +              if (se->ibuf == NULL && sce_valid && !build_proxy_run) {
 +                      se->ibuf = seq_proxy_fetch(scene, seq, cfra);
 +                      if (se->ibuf) {
 +                              input_preprocess(scene, seq, se, cfra);
 +                      }
 +              }
 +
 +              if (se->ibuf == NULL && sce_valid) {
 +                      copy_from_ibuf_still(seq, se);
 +                      if (se->ibuf) {
 +                              input_preprocess(scene, seq, se, cfra);
 +                      }
 +              }
 +              
 +              if (!sce_valid) {
 +                      se->ok = STRIPELEM_FAILED;
 +              } else if (se->ibuf==NULL && sce_valid) {
 +                      waitcursor(1);
 +                      
 +                      /* Hack! This function can be called from do_render_seq(), in that case
 +                         the seq->scene can already have a Render initialized with same name, 
 +                         so we have to use a default name. (compositor uses scene name to
 +                         find render).
 +                         However, when called from within the UI (image preview in sequencer)
 +                         we do want to use scene Render, that way the render result is defined
 +                         for display in render/imagewindow */
 +                      if(rendering) {
 +                              BLI_strncpy(scenename, sce->id.name+2, 64);
 +                              strcpy(sce->id.name+2, " do_build_seq_ibuf");
 +                      }
 +                      re= RE_NewRender(sce->id.name);
 +                      
 +                      /* prevent eternal loop */
 +                      doseq= scene->r.scemode & R_DOSEQ;
 +                      scene->r.scemode &= ~R_DOSEQ;
 +                      
 +                      BIF_init_render_callbacks(re, 0);       /* 0= no display callbacks */
 +                      
 +                      /* XXX hrms, set_scene still needed? work on that... */
 +                      if(sce!=oldsce) set_scene_bg(sce);
 +                      RE_BlenderFrame(re, sce,
 +                                      seq->sfra+se->nr+seq->anim_startofs);
 +                      if(sce!=oldsce) set_scene_bg(oldsce);
 +                      
 +                      /* UGLY WARNING, it is set to zero in  RE_BlenderFrame */
 +                      G.rendering= rendering;
 +                      if(rendering)
 +                              BLI_strncpy(sce->id.name+2, scenename, 64);
 +                      
 +                      RE_GetResultImage(re, &rres);
 +                      
 +                      if(rres.rectf) {
 +                              se->ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rectfloat, 0);
 +                              memcpy(se->ibuf->rect_float, rres.rectf, 4*sizeof(float)*rres.rectx*rres.recty);
 +                              if(rres.rectz) {
 +                                      addzbuffloatImBuf(se->ibuf);
 +                                      memcpy(se->ibuf->zbuf_float, rres.rectz, sizeof(float)*rres.rectx*rres.recty);
 +                              }
 +                      } else if (rres.rect32) {
 +                              se->ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rect, 0);
 +                              memcpy(se->ibuf->rect, rres.rect32, 4*rres.rectx*rres.recty);
 +                      }
 +                      
 +                      BIF_end_render_callbacks();
 +                      
 +                      /* restore */
 +                      scene->r.scemode |= doseq;
 +                      
 +                      CFRA = oldcfra;
 +                      set_last_seq(oldseq);
 +
 +                      copy_to_ibuf_still(seq, se);
 +
 +                      if (!build_proxy_run) {
 +                              if(se->ibuf == NULL) {
 +                                      se->ok = STRIPELEM_FAILED;
 +                              } else {
 +                                      input_preprocess(scene, seq, se, cfra);
 +                              }
 +                      }
 +
 +              }
 +#endif
 +      }
 +      if (!build_proxy_run) {
 +              if (se->ibuf && use_limiter) {
 +                      IMB_cache_limiter_insert(se->ibuf);
 +                      IMB_cache_limiter_ref(se->ibuf);
 +                      IMB_cache_limiter_touch(se->ibuf);
 +              }
 +      }
 +}
 +
 +static TStripElem* do_build_seq_recursively(Scene *scene, Sequence *seq, int cfra);
 +
 +static void do_effect_seq_recursively(Scene *scene, Sequence *seq, TStripElem *se, int cfra)
 +{
 +      float fac, facf;
 +      struct SeqEffectHandle sh = get_sequence_effect(seq);
 +      int early_out;
 +
 +      se->se1 = 0;
 +      se->se2 = 0;
 +      se->se3 = 0;
 +
 +#if 0 // XXX old animation system
 +      if(seq->ipo && seq->ipo->curve.first) {
 +              do_seq_ipo(scene, seq, cfra);
 +              fac= seq->facf0;
 +              facf= seq->facf1;
 +      } else 
 +#endif // XXX old animation system
 +      {
 +              sh.get_default_fac(seq, cfra, &fac, &facf);
 +      } 
 +
 +      if( scene->r.mode & R_FIELDS ); else facf= fac;
 +      
 +      early_out = sh.early_out(seq, fac, facf);
 +      switch (early_out) {
 +      case -1:
 +              /* no input needed */
 +              break;
 +      case 0:
 +              se->se1 = do_build_seq_recursively(scene, seq->seq1, cfra);
 +              se->se2 = do_build_seq_recursively(scene, seq->seq2, cfra);
 +              if (seq->seq3) {
 +                      se->se3 = do_build_seq_recursively(scene, seq->seq3, cfra);
 +              }
 +              break;
 +      case 1:
 +              se->se1 = do_build_seq_recursively(scene, seq->seq1, cfra);
 +              break;
 +      case 2:
 +              se->se2 = do_build_seq_recursively(scene, seq->seq2, cfra);
 +              break;
 +      }
 +
 +
 +      do_build_seq_ibuf(scene, seq, se, cfra, FALSE);
 +
 +      /* children are not needed anymore ... */
 +
 +      if (se->se1 && se->se1->ibuf) {
 +              IMB_cache_limiter_unref(se->se1->ibuf);
 +      }
 +      if (se->se2 && se->se2->ibuf) {
 +              IMB_cache_limiter_unref(se->se2->ibuf);
 +      }
 +      if (se->se3 && se->se3->ibuf) {
 +              IMB_cache_limiter_unref(se->se3->ibuf);
 +      }
 +}
 +
 +static TStripElem* do_build_seq_recursively_impl(Scene *scene, Sequence * seq, int cfra)
 +{
 +      TStripElem *se;
 +
 +      se = give_tstripelem(seq, cfra);
 +
 +      if(se) {
 +              if (seq->type & SEQ_EFFECT) {
 +                      do_effect_seq_recursively(scene, seq, se, cfra);
 +              } else {
 +                      do_build_seq_ibuf(scene, seq, se, cfra, FALSE);
 +              }
 +      }
 +      return se;
 +}
 +
 +/* FIXME:
 +   
 +If cfra was float throughout blender (especially in the render
 +pipeline) one could even _render_ with subframe precision
 +instead of faking using the blend code below...
 +
 +*/
 +
 +static TStripElem* do_handle_speed_effect(Scene *scene, Sequence * seq, int cfra)
 +{
 +      SpeedControlVars * s = (SpeedControlVars *)seq->effectdata;
 +      int nr = cfra - seq->start;
 +      float f_cfra;
 +      int cfra_left;
 +      int cfra_right;
 +      TStripElem * se = 0;
 +      TStripElem * se1 = 0;
 +      TStripElem * se2 = 0;
 +      
 +      sequence_effect_speed_rebuild_map(seq, 0);
 +      
 +      f_cfra = seq->start + s->frameMap[nr];
 +      
 +      cfra_left = (int) floor(f_cfra);
 +      cfra_right = (int) ceil(f_cfra);
 +
 +      se = give_tstripelem(seq, cfra);
 +
 +      if (!se) {
 +              return se;
 +      }
 +
 +      if (cfra_left == cfra_right || 
 +          (s->flags & SEQ_SPEED_BLEND) == 0) {
 +              test_and_auto_discard_ibuf(se);
 +
 +              if (se->ibuf == NULL) {
 +                      se1 = do_build_seq_recursively_impl(scene, seq->seq1, cfra_left);
 +
 +                      if((se1 && se1->ibuf && se1->ibuf->rect_float))
 +                              se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0);
 +                      else
 +                              se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0);
 +
 +                      if (se1 == 0 || se1->ibuf == 0) {
 +                              make_black_ibuf(se->ibuf);
 +                      } else {
 +                              if (se->ibuf != se1->ibuf) {
 +                                      if (se->ibuf) {
 +                                              IMB_freeImBuf(se->ibuf);
 +                                      }
 +
 +                                      se->ibuf = se1->ibuf;
 +                                      IMB_refImBuf(se->ibuf);
 +                              }
 +                      }
 +              }
 +      } else {
 +              struct SeqEffectHandle sh;
 +
 +              if(se->ibuf) {
 +                      if(se->ibuf->x < seqrectx || se->ibuf->y < seqrecty 
 +                         || !(se->ibuf->rect || se->ibuf->rect_float)) {
 +                              IMB_freeImBuf(se->ibuf);
 +                              se->ibuf= 0;
 +                      }
 +              }
 +
 +              if (se->ibuf == NULL) {
 +                      se1 = do_build_seq_recursively_impl(scene, seq->seq1, cfra_left);
 +                      se2 = do_build_seq_recursively_impl(scene, seq->seq1, cfra_right);
 +
 +                      if((se1 && se1->ibuf && se1->ibuf->rect_float))
 +                              se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0);
 +                      else
 +                              se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0);
 +                      
 +                      if (!se1 || !se2) {
 +                              make_black_ibuf(se->ibuf);
 +                      } else {
 +                              sh = get_sequence_effect(seq);
 +
 +                              sh.execute(seq, cfra, 
 +                                         f_cfra - (float) cfra_left, 
 +                                         f_cfra - (float) cfra_left, 
 +                                         se->ibuf->x, se->ibuf->y, 
 +                                         se1->ibuf, se2->ibuf, 0, se->ibuf);
 +                      }
 +              }
 +
 +      }
 +
 +      /* caller expects this to be referenced, so do it! */
 +      if (se->ibuf) {
 +              IMB_cache_limiter_insert(se->ibuf);
 +              IMB_cache_limiter_ref(se->ibuf);
 +              IMB_cache_limiter_touch(se->ibuf);
 +      }
 +
 +      /* children are no longer needed */
 +      if (se1 && se1->ibuf)
 +              IMB_cache_limiter_unref(se1->ibuf);
 +      if (se2 && se2->ibuf)
 +              IMB_cache_limiter_unref(se2->ibuf);
 +
 +      return se;
 +}
 +
 +/* 
 + * build all ibufs recursively
 + * 
 + * if successfull, the returned TStripElem contains the (referenced!) imbuf
 + * that means: you _must_ call 
 + *
 + * IMB_cache_limiter_unref(rval);
 + * 
 + * if rval != 0
 + * 
 + */
 +
 +static TStripElem* do_build_seq_recursively(Scene *scene, Sequence * seq, int cfra)
 +{
 +      if (seq->type == SEQ_SPEED) {
 +              return do_handle_speed_effect(scene, seq, cfra);
 +      } else {
 +              return do_build_seq_recursively_impl(scene, seq, cfra);
 +      }
 +}
 +
++/* Bug: 18209
++ * when dragging the mouse over a metastrip, on mouse-up for some unknown
++ * reason in some cases the metastrips TStripElem->ibuf->rect is NULL,
++ * This should be fixed but I had a look and couldnt work out why its
++ * happening so for now workaround with a NULL check - campbell */
++
++#define SEQ_SPECIAL_SEQ_UPDATE_WORKAROUND
++
 +static TStripElem* do_build_seq_array_recursively(Scene *scene,
 +      ListBase *seqbasep, int cfra, int chanshown)
 +{
 +      Sequence* seq_arr[MAXSEQ+1];
 +      int count;
 +      int i;
 +      TStripElem* se = 0;
 +
 +      count = get_shown_sequences(seqbasep, cfra, chanshown, (Sequence **)&seq_arr);
 +
 +      if (!count) {
 +              return 0;
 +      }
 +
 +      se = give_tstripelem(seq_arr[count - 1], cfra);
 +
 +      if (!se) {
 +              return 0;
 +      }
 +
 +      test_and_auto_discard_ibuf(se);
 +
 +      if (se->ibuf_comp != 0) {
 +              IMB_cache_limiter_insert(se->ibuf_comp);
 +              IMB_cache_limiter_ref(se->ibuf_comp);
 +              IMB_cache_limiter_touch(se->ibuf_comp);
 +              return se;
 +      }
 +
 +      
 +      if(count == 1) {
 +              se = do_build_seq_recursively(scene, seq_arr[0], cfra);
 +              if (se->ibuf) {
 +                      se->ibuf_comp = se->ibuf;
 +                      IMB_refImBuf(se->ibuf_comp);
 +              }
 +              return se;
 +      }
 +
 +
 +      for (i = count - 1; i >= 0; i--) {
 +              int early_out;
 +              Sequence * seq = seq_arr[i];
 +              struct SeqEffectHandle sh;
 +
 +              se = give_tstripelem(seq, cfra);
 +
 +              test_and_auto_discard_ibuf(se);
 +
 +              if (se->ibuf_comp != 0) {
 +                      break;
 +              }
 +              if (seq->blend_mode == SEQ_BLEND_REPLACE) {
 +                      do_build_seq_recursively(scene, seq, cfra);
 +                      if (se->ibuf) {
 +                              se->ibuf_comp = se->ibuf;
 +                              IMB_refImBuf(se->ibuf);
 +                      } else {
 +                              se->ibuf_comp = IMB_allocImBuf(
 +                                      (short)seqrectx, (short)seqrecty, 
 +                                      32, IB_rect, 0);
 +                      }
 +                      break;
 +              }
 +
 +              sh = get_sequence_blend(seq);
 +
 +              seq->facf0 = seq->facf1 = 1.0;
 +
 +#if 0 // XXX old animation system
 +              if(seq->ipo && seq->ipo->curve.first) {
 +                      do_seq_ipo(scene, seq, cfra);
 +              } 
 +#endif
 +
 +              if( scene->r.mode & R_FIELDS ); else seq->facf0 = seq->facf1;
 +
 +              seq->facf0 *= seq->blend_opacity / 100.0;
 +              seq->facf1 *= seq->blend_opacity / 100.0;
 +
 +              early_out = sh.early_out(seq, seq->facf0, seq->facf1);
 +
 +              switch (early_out) {
 +              case -1:
 +              case 2:
 +                      do_build_seq_recursively(scene, seq, cfra);
 +                      if (se->ibuf) {
 +                              se->ibuf_comp = se->ibuf;
 +                              IMB_refImBuf(se->ibuf_comp);
 +                      } else {
 +                              se->ibuf_comp = IMB_allocImBuf(
 +                                      (short)seqrectx, (short)seqrecty, 
 +                                      32, IB_rect, 0);
 +                      }
 +                      break;
 +              case 1:
 +                      if (i == 0) {
 +                              se->ibuf_comp = IMB_allocImBuf(
 +                                      (short)seqrectx, (short)seqrecty, 
 +                                      32, IB_rect, 0);
 +                              IMB_cache_limiter_insert(se->ibuf_comp);
 +                              IMB_cache_limiter_ref(se->ibuf_comp);
 +                              IMB_cache_limiter_touch(se->ibuf_comp);
 +                      }
 +                      break;
 +              case 0:
 +                      do_build_seq_recursively(scene, seq, cfra);
 +                      if (!se->ibuf) {
 +                              se->ibuf = IMB_allocImBuf(
 +                                      (short)seqrectx, (short)seqrecty, 
 +                                      32, IB_rect, 0);
 +                      }
 +                      if (i == 0) {
 +                              se->ibuf_comp = se->ibuf;
 +                              IMB_refImBuf(se->ibuf_comp);
 +                      }
 +                      break;
 +              }
 +      
 +              if (se->ibuf_comp) {
 +                      break;
 +              }
 +      }
 +
 +      i++;
 +
 +      for (; i < count; i++) {
 +              Sequence * seq = seq_arr[i];
 +              struct SeqEffectHandle sh = get_sequence_blend(seq);
 +              TStripElem* se1 = give_tstripelem(seq_arr[i-1], cfra);
 +              TStripElem* se2 = give_tstripelem(seq_arr[i], cfra);
 +      
 +              int early_out = sh.early_out(seq, seq->facf0, seq->facf1);
 +              switch (early_out) {
 +              case 0: {
 +                      int x= se2->ibuf->x;
 +                      int y= se2->ibuf->y;
 +                      int swap_input = FALSE;
 +
 +                      if (se1->ibuf_comp->rect_float ||
 +                          se2->ibuf->rect_float) {
 +                              se2->ibuf_comp = IMB_allocImBuf(
 +                                      (short)seqrectx, (short)seqrecty, 
 +                                      32, IB_rectfloat, 0);
 +                      } else {
 +                              se2->ibuf_comp = IMB_allocImBuf(
 +                                      (short)seqrectx, (short)seqrecty, 
 +                                      32, IB_rect, 0);
 +                      }
 +
 +
 +                      if (!se1->ibuf_comp->rect_float && 
 +                          se2->ibuf_comp->rect_float) {
 +                              IMB_float_from_rect(se1->ibuf_comp);
 +                      }
 +                      if (!se2->ibuf->rect_float && 
 +                          se2->ibuf_comp->rect_float) {
 +                              IMB_float_from_rect(se2->ibuf);
 +                      }
 +
 +                      if (!se1->ibuf_comp->rect && 
 +                          !se2->ibuf_comp->rect_float) {
 +                              IMB_rect_from_float(se1->ibuf_comp);
 +                      }
 +                      if (!se2->ibuf->rect && 
 +                          !se2->ibuf_comp->rect_float) {
 +                              IMB_rect_from_float(se2->ibuf);
 +                      }
++                      
++#ifdef SEQ_SPECIAL_SEQ_UPDATE_WORKAROUND
++                      if (se2->ibuf->rect==NULL && se2->ibuf->rect_float==NULL) {
++                              printf("ERROR: sequencer se2->ibuf missing buffer\n");
++                      } else if (se1->ibuf && se1->ibuf->rect==NULL && se1->ibuf->rect_float==NULL) {
++                              printf("ERROR: sequencer se1->ibuf missing buffer\n");
++                      } else {
++#endif
 +                      /* bad hack, to fix crazy input ordering of 
 +                         those two effects */
 +
 +                      if (seq->blend_mode == SEQ_ALPHAOVER ||
 +                          seq->blend_mode == SEQ_ALPHAUNDER ||
 +                          seq->blend_mode == SEQ_OVERDROP) {
 +                              swap_input = TRUE;
 +                      }
 +
 +                      if (swap_input) {
 +                              sh.execute(seq, cfra, 
 +                                         seq->facf0, seq->facf1, x, y, 
 +                                         se2->ibuf, se1->ibuf_comp, 0,
 +                                         se2->ibuf_comp);
 +                      } else {
 +                              sh.execute(seq, cfra, 
 +                                         seq->facf0, seq->facf1, x, y, 
 +                                         se1->ibuf_comp, se2->ibuf, 0,
 +                                         se2->ibuf_comp);
 +                      }
 +                      
++#ifdef SEQ_SPECIAL_SEQ_UPDATE_WORKAROUND
++                      }
++#endif
++                      
 +                      IMB_cache_limiter_insert(se2->ibuf_comp);
 +                      IMB_cache_limiter_ref(se2->ibuf_comp);
 +                      IMB_cache_limiter_touch(se2->ibuf_comp);
 +
 +                      IMB_cache_limiter_unref(se1->ibuf_comp);
 +                      IMB_cache_limiter_unref(se2->ibuf);
 +
 +                      break;
 +              }
 +              case 1: {
 +                      se2->ibuf_comp = se1->ibuf;
 +                      IMB_refImBuf(se2->ibuf_comp);
 +
 +                      break;
 +              }
 +              }
 +              se = se2;
 +      }
 +
 +      return se;
 +}
 +
 +/*
 + * returned ImBuf is refed!
 + * you have to unref after usage!
 + */
 +
 +static ImBuf *give_ibuf_seq_impl(Scene *scene, int rectx, int recty, int cfra, int chanshown)
 +{
 +      Editing *ed= seq_give_editing(scene, FALSE);
 +      int count;
 +      ListBase *seqbasep;
 +      TStripElem *se;
 +
 +      
 +      if(ed==NULL) return NULL;
 +
 +      count = BLI_countlist(&ed->metastack);
 +      if((chanshown < 0) && (count > 0)) {
 +              count = MAX2(count + chanshown, 0);
 +              seqbasep= ((MetaStack*)BLI_findlink(&ed->metastack, count))->oldbasep;
 +      } else {
 +              seqbasep= ed->seqbasep;
 +      }
 +
 +      seqrectx= rectx;        /* bad bad global! */
 +      seqrecty= recty;
 +
 +      se = do_build_seq_array_recursively(scene, seqbasep, cfra, chanshown);
 +
 +      if(!se) { 
 +              return 0;
 +      }
 +
 +      return se->ibuf_comp;
 +}
 +
 +ImBuf *give_ibuf_seq_direct(Scene *scene, int rectx, int recty, int cfra, Sequence *seq)
 +{
 +      TStripElem* se;
 +
 +      seqrectx= rectx;        /* bad bad global! */
 +      seqrecty= recty;
 +
 +      se = do_build_seq_recursively(scene, seq, cfra);
 +
 +      if(!se) { 
 +              return 0;
 +      }
 +
 +      if (se->ibuf) {
 +              IMB_cache_limiter_unref(se->ibuf);
 +      }
 +
 +      return se->ibuf;
 +}
 +
 +ImBuf *give_ibuf_seq(Scene *scene, int rectx, int recty, int cfra, int chanshown)
 +{
 +      ImBuf* i = give_ibuf_seq_impl(scene, rectx, recty, cfra, chanshown);
 +
 +      if (i) {
 +              IMB_cache_limiter_unref(i);
 +      }
 +      return i;
 +}
 +
 +/* check used when we need to change seq->blend_mode but not to effect or audio strips */
 +int seq_can_blend(Sequence *seq)
 +{
 +      if (ELEM4(seq->type, SEQ_IMAGE, SEQ_META, SEQ_SCENE, SEQ_MOVIE)) {
 +              return 1;
 +      } else {
 +              return 0;
 +      }
 +}
 +
 +/* *********************** threading api ******************* */
 +
 +static ListBase running_threads;
 +static ListBase prefetch_wait;
 +static ListBase prefetch_done;
 +
 +static pthread_mutex_t queue_lock          = PTHREAD_MUTEX_INITIALIZER;
 +static pthread_mutex_t wakeup_lock         = PTHREAD_MUTEX_INITIALIZER;
 +static pthread_cond_t  wakeup_cond         = PTHREAD_COND_INITIALIZER;
 +
 +static pthread_mutex_t prefetch_ready_lock = PTHREAD_MUTEX_INITIALIZER;
 +static pthread_cond_t  prefetch_ready_cond = PTHREAD_COND_INITIALIZER;
 +
 +static pthread_mutex_t frame_done_lock     = PTHREAD_MUTEX_INITIALIZER;
 +static pthread_cond_t  frame_done_cond     = PTHREAD_COND_INITIALIZER;
 +
 +static volatile int seq_thread_shutdown = FALSE;
 +static volatile int seq_last_given_monoton_cfra = 0;
 +static int monoton_cfra = 0;
 +
 +typedef struct PrefetchThread {
 +      struct PrefetchThread *next, *prev;
 +      
 +      Scene *scene;
 +      struct PrefetchQueueElem *current;
 +      pthread_t pthread;
 +      int running;
 +      
 +} PrefetchThread;
 +
 +typedef struct PrefetchQueueElem {
 +      struct PrefetchQueueElem *next, *prev;
 +      
 +      int rectx;
 +      int recty;
 +      int cfra;
 +      int chanshown;
 +
 +      int monoton_cfra;
 +
 +      struct ImBuf * ibuf;
 +} PrefetchQueueElem;
 +
 +static void *seq_prefetch_thread(void * This_)
 +{
 +      PrefetchThread * This = This_;
 +
 +      while (!seq_thread_shutdown) {
 +              PrefetchQueueElem *e;
 +              int s_last;
 +
 +              pthread_mutex_lock(&queue_lock);
 +              e = prefetch_wait.first;
 +              if (e) {
 +                      BLI_remlink(&prefetch_wait, e);
 +              }
 +              s_last = seq_last_given_monoton_cfra;
 +
 +              This->current = e;
 +
 +              pthread_mutex_unlock(&queue_lock);
 +
 +              if (!e) {
 +                      pthread_mutex_lock(&prefetch_ready_lock);
 +
 +                      This->running = FALSE;
 +
 +                      pthread_cond_signal(&prefetch_ready_cond);
 +                      pthread_mutex_unlock(&prefetch_ready_lock);
 +
 +                      pthread_mutex_lock(&wakeup_lock);
 +                      if (!seq_thread_shutdown) {
 +                              pthread_cond_wait(&wakeup_cond, &wakeup_lock);
 +                      }
 +                      pthread_mutex_unlock(&wakeup_lock);
 +                      continue;
 +              }
 +
 +              This->running = TRUE;
 +              
 +              if (e->cfra >= s_last) { 
 +                      e->ibuf = give_ibuf_seq_impl(This->scene, 
 +                              e->rectx, e->recty, e->cfra, e->chanshown);
 +              }
 +
 +              pthread_mutex_lock(&queue_lock);
 +
 +              BLI_addtail(&prefetch_done, e);
 +
 +              for (e = prefetch_wait.first; e; e = e->next) {
 +                      if (s_last > e->monoton_cfra) {
 +                              BLI_remlink(&prefetch_wait, e);
 +                              MEM_freeN(e);
 +                      }
 +              }
 +
 +              for (e = prefetch_done.first; e; e = e->next) {
 +                      if (s_last > e->monoton_cfra) {
 +                              if (e->ibuf) {
 +                                      IMB_cache_limiter_unref(e->ibuf);
 +                              }
 +                              BLI_remlink(&prefetch_done, e);
 +                              MEM_freeN(e);
 +                      }
 +              }
 +
 +              pthread_mutex_unlock(&queue_lock);
 +
 +              pthread_mutex_lock(&frame_done_lock);
 +              pthread_cond_signal(&frame_done_cond);
 +              pthread_mutex_unlock(&frame_done_lock);
 +      }
 +      return 0;
 +}
 +
 +void seq_start_threads(Scene *scene)
 +{
 +      int i;
 +
 +      running_threads.first = running_threads.last = NULL;
 +      prefetch_wait.first = prefetch_wait.last = NULL;
 +      prefetch_done.first = prefetch_done.last = NULL;
 +
 +      seq_thread_shutdown = FALSE;
 +      seq_last_given_monoton_cfra = monoton_cfra = 0;
 +
 +      /* since global structures are modified during the processing
 +         of one frame, only one render thread is currently possible... 
 +
 +         (but we code, in the hope, that we can remove this restriction
 +         soon...)
 +      */
 +
 +      fprintf(stderr, "SEQ-THREAD: seq_start_threads\n");
 +
 +      for (i = 0; i < 1; i++) {
 +              PrefetchThread *t = MEM_callocN(sizeof(PrefetchThread), "prefetch_thread");
 +              t->scene= scene;
 +              t->running = TRUE;
 +              BLI_addtail(&running_threads, t);
 +
 +              pthread_create(&t->pthread, NULL, seq_prefetch_thread, t);
 +      }
 +
 +      /* init malloc mutex */
 +      BLI_init_threads(0, 0, 0);
 +}
 +
 +void seq_stop_threads()
 +{
 +      PrefetchThread *tslot;
 +      PrefetchQueueElem *e;
 +
 +      fprintf(stderr, "SEQ-THREAD: seq_stop_threads()\n");
 +
 +      if (seq_thread_shutdown) {
 +              fprintf(stderr, "SEQ-THREAD: ... already stopped\n");
 +              return;
 +      }
 +      
 +      pthread_mutex_lock(&wakeup_lock);
 +
 +      seq_thread_shutdown = TRUE;
 +
 +        pthread_cond_broadcast(&wakeup_cond);
 +        pthread_mutex_unlock(&wakeup_lock);
 +
 +      for(tslot = running_threads.first; tslot; tslot= tslot->next) {
 +              pthread_join(tslot->pthread, NULL);
 +      }
 +
 +
 +      for (e = prefetch_wait.first; e; e = e->next) {
 +              BLI_remlink(&prefetch_wait, e);
 +              MEM_freeN(e);
 +      }
 +
 +      for (e = prefetch_done.first; e; e = e->next) {
 +              if (e->ibuf) {
 +                      IMB_cache_limiter_unref(e->ibuf);
 +              }
 +              BLI_remlink(&prefetch_done, e);
 +              MEM_freeN(e);
 +      }
 +
 +      BLI_freelistN(&running_threads);
 +
 +      /* deinit malloc mutex */
 +      BLI_end_threads(0);
 +}
 +
 +void give_ibuf_prefetch_request(int rectx, int recty, int cfra, int chanshown)
 +{
 +      PrefetchQueueElem *e;
 +      if (seq_thread_shutdown) {
 +              return;
 +      }
 +
 +      e = MEM_callocN(sizeof(PrefetchQueueElem), "prefetch_queue_elem");
 +      e->rectx = rectx;
 +      e->recty = recty;
 +      e->cfra = cfra;
 +      e->chanshown = chanshown;
 +      e->monoton_cfra = monoton_cfra++;
 +
 +      pthread_mutex_lock(&queue_lock);
 +      BLI_addtail(&prefetch_wait, e);
 +      pthread_mutex_unlock(&queue_lock);
 +      
 +      pthread_mutex_lock(&wakeup_lock);
 +      pthread_cond_signal(&wakeup_cond);
 +      pthread_mutex_unlock(&wakeup_lock);
 +}
 +
 +void seq_wait_for_prefetch_ready()
 +{
 +      PrefetchThread *tslot;
 +
 +      if (seq_thread_shutdown) {
 +              return;
 +      }
 +
 +      fprintf(stderr, "SEQ-THREAD: rendering prefetch frames...\n");
 +
 +      pthread_mutex_lock(&prefetch_ready_lock);
 +
 +      for(;;) {
 +              for(tslot = running_threads.first; tslot; tslot= tslot->next) {
 +                      if (tslot->running) {
 +                              break;
 +                      }
 +              }
 +              if (!tslot) {
 +                      break;
 +              }
 +              pthread_cond_wait(&prefetch_ready_cond, &prefetch_ready_lock);
 +      }
 +
 +      pthread_mutex_unlock(&prefetch_ready_lock);
 +
 +      fprintf(stderr, "SEQ-THREAD: prefetch done\n");
 +}
 +
 +ImBuf *give_ibuf_seq_threaded(Scene *scene, int rectx, int recty, int cfra, int chanshown)
 +{
 +      PrefetchQueueElem *e = NULL;
 +      int found_something = FALSE;
 +
 +      if (seq_thread_shutdown) {
 +              return give_ibuf_seq(scene, rectx, recty, cfra, chanshown);
 +      }
 +
 +      while (!e) {
 +              int success = FALSE;
 +              pthread_mutex_lock(&queue_lock);
 +
 +              for (e = prefetch_done.first; e; e = e->next) {
 +                      if (cfra == e->cfra &&
 +                          chanshown == e->chanshown &&
 +                          rectx == e->rectx && 
 +                          recty == e->recty) {
 +                              success = TRUE;
 +                              found_something = TRUE;
 +                              break;
 +                      }
 +              }
 +
 +              if (!e) {
 +                      for (e = prefetch_wait.first; e; e = e->next) {
 +                              if (cfra == e->cfra &&
 +                                  chanshown == e->chanshown &&
 +                                  rectx == e->rectx && 
 +                                  recty == e->recty) {
 +                                      found_something = TRUE;
 +                                      break;
 +                              }
 +                      }
 +              }
 +
 +              if (!e) {
 +                      PrefetchThread *tslot;
 +
 +                      for(tslot = running_threads.first; 
 +                          tslot; tslot= tslot->next) {
 +                              if (tslot->current &&
 +                                  cfra == tslot->current->cfra &&
 +                                  chanshown == tslot->current->chanshown &&
 +                                  rectx == tslot->current->rectx && 
 +                                  recty == tslot->current->recty) {
 +                                      found_something = TRUE;
 +                                      break;
 +                              }
 +                      }
 +              }
 +
 +              /* e->ibuf is unrefed by render thread on next round. */
 +
 +              if (e) {
 +                      seq_last_given_monoton_cfra = e->monoton_cfra;
 +              }
 +
 +              pthread_mutex_unlock(&queue_lock);
 +
 +              if (!success) {
 +                      e = NULL;
 +
 +                      if (!found_something) {
 +                              fprintf(stderr, 
 +                                      "SEQ-THREAD: Requested frame "
 +                                      "not in queue ???\n");
 +                              break;
 +                      }
 +                      pthread_mutex_lock(&frame_done_lock);
 +                      pthread_cond_wait(&frame_done_cond, &frame_done_lock);
 +                      pthread_mutex_unlock(&frame_done_lock);
 +              }
 +      }
 +      
 +      return e ? e->ibuf : 0;
 +}
 +
 +/* Functions to free imbuf and anim data on changes */
 +
 +static void free_imbuf_strip_elem(TStripElem *se)
 +{
 +      if(se->ibuf) {
 +              IMB_freeImBuf(se->ibuf);
 +      }
 +      if(se->ibuf_comp) {
 +              IMB_freeImBuf(se->ibuf_comp);
 +      }
 +      se->ibuf_comp = 0;
 +      se->ibuf= 0;
 +      se->ok= STRIPELEM_OK;
 +      se->se1= se->se2= se->se3= 0;
 +}
 +
 +static void free_anim_seq(Sequence *seq)
 +{
 +      if(seq->anim) {
 +              IMB_free_anim(seq->anim);
 +              seq->anim = 0;
 +      }
 +}
 +
 +void free_imbuf_seq_except(Scene *scene, int cfra)
 +{
 +      Editing *ed= seq_give_editing(scene, FALSE);
 +      Sequence *seq;
 +      TStripElem *se;
 +      int a;
 +
 +      if(ed==NULL) return;
 +
 +      SEQ_BEGIN(ed, seq) {
 +              if(seq->strip) {
 +                      TStripElem * curelem = give_tstripelem(seq, cfra);
 +
 +                      for(a = 0, se = seq->strip->tstripdata; 
 +                          a < seq->strip->len && se; a++, se++) {
 +                              if(se != curelem) {
 +                                      free_imbuf_strip_elem(se);
 +                              }
 +                      }
 +                      for(a = 0, se = seq->strip->tstripdata_startstill;
 +                          a < seq->strip->startstill && se; a++, se++) {
 +                              if(se != curelem) {
 +                                      free_imbuf_strip_elem(se);
 +                              }
 +                      }
 +                      for(a = 0, se = seq->strip->tstripdata_endstill;
 +                          a < seq->strip->endstill && se; a++, se++) {
 +                              if(se != curelem) {
 +                                      free_imbuf_strip_elem(se);
 +                              }
 +                      }
 +                      if(seq->strip->ibuf_startstill) {
 +                              IMB_freeImBuf(seq->strip->ibuf_startstill);
 +                              seq->strip->ibuf_startstill = 0;
 +                      }
 +
 +                      if(seq->strip->ibuf_endstill) {
 +                              IMB_freeImBuf(seq->strip->ibuf_endstill);
 +                              seq->strip->ibuf_endstill = 0;
 +                      }
 +
 +                      if(seq->type==SEQ_MOVIE)
 +                              if(seq->startdisp > cfra || seq->enddisp < cfra)
 +                                      free_anim_seq(seq);
 +              }
 +      }
 +      SEQ_END
 +}
 +
 +void free_imbuf_seq(ListBase * seqbase)
 +{
 +      Sequence *seq;
 +      TStripElem *se;
 +      int a;
 +      
 +      for(seq= seqbase->first; seq; seq= seq->next) {
 +              if(seq->strip) {
 +                      for(a = 0, se = seq->strip->tstripdata; 
 +                          a < seq->strip->len && se; a++, se++) {
 +                              free_imbuf_strip_elem(se);
 +                      }
 +                      for(a = 0, se = seq->strip->tstripdata_startstill; 
 +                          a < seq->strip->startstill && se; a++, se++) {
 +                              free_imbuf_strip_elem(se);
 +                      }
 +                      for(a = 0, se = seq->strip->tstripdata_endstill; 
 +                          a < seq->strip->endstill && se; a++, se++) {
 +                              free_imbuf_strip_elem(se);
 +                      }
 +                      if(seq->strip->ibuf_startstill) {
 +                              IMB_freeImBuf(seq->strip->ibuf_startstill);
 +                              seq->strip->ibuf_startstill = 0;
 +                      }
 +
 +                      if(seq->strip->ibuf_endstill) {
 +                              IMB_freeImBuf(seq->strip->ibuf_endstill);
 +                              seq->strip->ibuf_endstill = 0;
 +                      }
 +
 +                      if(seq->type==SEQ_MOVIE)
 +                              free_anim_seq(seq);
 +                      if(seq->type==SEQ_SPEED) {
 +                              sequence_effect_speed_rebuild_map(seq, 1);
 +                      }
 +              }
 +              if(seq->type==SEQ_META) {
 +                      free_imbuf_seq(&seq->seqbase);
 +              }
 +      }
 +      
 +}
 +
 +static int update_changed_seq_recurs(Scene *scene, Sequence *seq, Sequence *changed_seq, int len_change, int ibuf_change)
 +{
 +      Sequence *subseq;
 +      int a, free_imbuf = 0;
 +      TStripElem *se;
 +      
 +      /* recurs downwards to see if this seq depends on the changed seq */
 +      
 +      if(seq == NULL)
 +              return 0;
 +      
 +      if(seq == changed_seq)
 +              free_imbuf = 1;
 +      
 +      for(subseq=seq->seqbase.first; subseq; subseq=subseq->next)
 +              if(update_changed_seq_recurs(scene, subseq, changed_seq, len_change, ibuf_change))
 +                      free_imbuf = TRUE;
 +      
 +      if(seq->seq1)
 +              if(update_changed_seq_recurs(scene, seq->seq1, changed_seq, len_change, ibuf_change))
 +                      free_imbuf = TRUE;
 +      if(seq->seq2 && (seq->seq2 != seq->seq1))
 +              if(update_changed_seq_recurs(scene, seq->seq2, changed_seq, len_change, ibuf_change))
 +                      free_imbuf = TRUE;
 +      if(seq->seq3 && (seq->seq3 != seq->seq1) && (seq->seq3 != seq->seq2))
 +              if(update_changed_seq_recurs(scene, seq->seq3, changed_seq, len_change, ibuf_change))
 +                      free_imbuf = TRUE;
 +      
 +      if(free_imbuf) {
 +              if(ibuf_change) {
 +                      se= seq->strip->tstripdata;
 +                      if (se) {
 +                              for(a=0; a<seq->len; a++, se++)
 +                                      free_imbuf_strip_elem(se);
 +                      }
 +                      
 +                      if(seq->type == SEQ_MOVIE)
 +                              free_anim_seq(seq);
 +                      if(seq->type == SEQ_SPEED) {
 +                              sequence_effect_speed_rebuild_map(seq, 1);
 +                      }
 +              }
 +              
 +              if(len_change)
 +                      calc_sequence(seq);
 +      }
 +      
 +      return free_imbuf;
 +}
 +
 +void update_changed_seq_and_deps(Scene *scene, Sequence *changed_seq, int len_change, int ibuf_change)
 +{
 +      Editing *ed= seq_give_editing(scene, FALSE);
 +      Sequence *seq;
 +      
 +      if (ed==NULL) return;
 +      
 +      for (seq=ed->seqbase.first; seq; seq=seq->next)
 +              update_changed_seq_recurs(scene, seq, changed_seq, len_change, ibuf_change);
 +}
 +
 +void free_imbuf_seq_with_ipo(Scene *scene, struct Ipo *ipo)
 +{
 +      /* force update of all sequences with this ipo, on ipo changes */
 +      Editing *ed= seq_give_editing(scene, FALSE);
 +      Sequence *seq;
 +
 +      if(ed==NULL) return;
 +
 +      SEQ_BEGIN(ed, seq) {
 +              if(seq->ipo == ipo) {
 +                      update_changed_seq_and_deps(scene, seq, 0, 1);
 +                      if(seq->type == SEQ_SPEED) {
 +                              sequence_effect_speed_rebuild_map(seq, 1);
 +                      }
 +              }
 +      }
 +      SEQ_END
 +}
 +
 +#if 0
 +/* bad levell call... */
 +void do_render_seq(RenderResult *rr, int cfra)
 +{
 +      ImBuf *ibuf;
 +
 +      ibuf= give_ibuf_seq(scene, rr->rectx, rr->recty, cfra, 0);
 +      
 +      if(ibuf) {
 +              if(ibuf->rect_float) {
 +                      if (!rr->rectf)
 +                              rr->rectf= MEM_mallocN(4*sizeof(float)*rr->rectx*rr->recty, "render_seq rectf");
 +                      
 +                      memcpy(rr->rectf, ibuf->rect_float, 4*sizeof(float)*rr->rectx*rr->recty);
 +                      
 +                      /* TSK! Since sequence render doesn't free the *rr render result, the old rect32
 +                         can hang around when sequence render has rendered a 32 bits one before */
 +                      if(rr->rect32) {
 +                              MEM_freeN(rr->rect32);
 +                              rr->rect32= NULL;
 +                      }
 +              }
 +              else if(ibuf->rect) {
 +                      if (!rr->rect32)
 +                              rr->rect32= MEM_mallocN(sizeof(int)*rr->rectx*rr->recty, "render_seq rect");
 +
 +                      memcpy(rr->rect32, ibuf->rect, 4*rr->rectx*rr->recty);
 +
 +                      /* if (ibuf->zbuf) { */
 +                      /*      if (R.rectz) freeN(R.rectz); */
 +                      /*      R.rectz = BLI_dupallocN(ibuf->zbuf); */
 +                      /* } */
 +              }
 +              
 +              /* Let the cache limitor take care of this (schlaile) */
 +              /* While render let's keep all memory available for render 
 +                 (ton)
 +                 At least if free memory is tight...
 +                 This can make a big difference in encoding speed
 +                 (it is around 4 times(!) faster, if we do not waste time
 +                 on freeing _all_ buffers every time on long timelines...)
 +                 (schlaile)
 +              */
 +              {
 +                      uintptr_t mem_in_use;
 +                      uintptr_t mmap_in_use;
 +                      uintptr_t max;
 +
 +                      mem_in_use= MEM_get_memory_in_use();
 +                      mmap_in_use= MEM_get_mapped_memory_in_use();
 +                      max = MEM_CacheLimiter_get_maximum();
 +
 +                      if (max != 0 && mem_in_use + mmap_in_use > max) {
 +                              fprintf(stderr, "Memory in use > maximum memory\n");
 +                              fprintf(stderr, "Cleaning up, please wait...\n"
 +                                      "If this happens very often,\n"
 +                                      "consider "
 +                                      "raising the memcache limit in the "
 +                                      "user preferences.\n");
 +                              free_imbuf_seq();
 +                      }
 +              }
 +      }
 +      else {
 +              /* render result is delivered empty in most cases, nevertheless we handle all cases */
 +              if (rr->rectf)
 +                      memset(rr->rectf, 0, 4*sizeof(float)*rr->rectx*rr->recty);
 +              else if (rr->rect32)
 +                      memset(rr->rect32, 0, 4*rr->rectx*rr->recty);
 +              else
 +                      rr->rect32= MEM_callocN(sizeof(int)*rr->rectx*rr->recty, "render_seq rect");
 +      }
 +}
 +
 +#endif
 +
 +/* seq funcs's for transforming internally
 + notice the difference between start/end and left/right.
 +
 + left and right are the bounds at which the sequence is rendered,
 +start and end are from the start and fixed length of the sequence.
 +*/
 +int seq_tx_get_start(Sequence *seq) {
 +      return seq->start;
 +}
 +int seq_tx_get_end(Sequence *seq)
 +{
 +      return seq->start+seq->len;
 +}
 +
 +int seq_tx_get_final_left(Sequence *seq, int metaclip)
 +{
 +      if (metaclip && seq->tmp) {
 +              /* return the range clipped by the parents range */
 +              return MAX2( seq_tx_get_final_left(seq, 0), seq_tx_get_final_left((Sequence *)seq->tmp, 1) );
 +      } else {
 +              return (seq->start - seq->startstill) + seq->startofs;
 +      }
 +