/* 
 * splitb1.c
 * Split Screen with Border Plugin 0.1
 *
 * Original Split Screen by Stefan Gartner
 * Copyright (c) 1999 Stefan Gartner <Stefan.Gartner@fhs-hagenberg.ac.at>
 * Copyrleft (c) 2001 Michael P. Shimko shimko@maui.net
 *
 * 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. 
 *
 */

/* Modified: 6/01 by Michael Shimko. Added control of Split Location in x & y.
 * Added a border between screens, with rgb controls.
 */
#include <stdio.h>
#include <math.h>
#include "plugin.h"


/* ******************** GLOBAL VARIABLES ***************** */

char name[24]= "Split Border v.b1";	

/* structure for buttons, 
 *  butcode      name           default  min  max  0
 */

VarStruct varstr[]= {					/*------10--------20--------30--------40--------50--------60--------70------80*/
	{ LABEL,	 	"2 strips", 	0.0, 0.0, 0.0, 	""},
	{ NUMSLI|FLO,	"Offset: ",	0.5, 0.0, 1.0,	
	    "Offset (%) for split location" },
	{ NUMSLI|FLO,	"Mix f: ",	0.5, 0.0, 1.0,	
		"A % to mix strip 1 with strip 2: (1-f)Source1 + (f)Source2" },
	{ NUMSLI|FLO,	"Border: ",	0.5, 0.0, 1.0,	
		"Border width between screens. Can occupy 100% of screen1." },
	{ NUMSLI|INT,	"MixType: ",	3.0, 0.0, 4.0,	
		"Type of mixing to do" },
	{ NUMSLI|FLO,	"Red: ",	122.0, 0.0, 255.0,
		"Red value of border" },
	{ NUMSLI|FLO,	"Green: ",	34.0, 0.0, 255.0,
		"Green value of berder" },
	{ NUMSLI|FLO,	"Blue: ",	1.0, 0.0, 255.0,
		"Blue value of border" },
	{ TOG|INT, 	"Horizontal: ",	0.0, 0.0, 1.0, 	
		"Split screen horizontally" },
	};

/* The cast struct is for input in the main doit function
   Varstr and Cast must have the same variables in the same order */ 

typedef struct Cast {
	int dummy;	/* because of the 'label' button */
	float offset;	/* border offset */
	float f;	/* mix factor */
	float bw;	/* border width */
	int style;	/* mix type */
	float rf;	/* red */
	float bf;	/* green */
	float gf;	/* blue */
	int horiz;
} Cast;


/* cfra: the current frame */

float cfra;

enum { none, rgb, rgbshadow, fade, simple } mixtype;

void plugin_seq_doit(Cast *, float, float, int, int, ImBuf *, ImBuf *, 
	ImBuf *, ImBuf *);

static void use_ibuf(char src[], char dest[]);

void mixit (float rgba[], char c1[], char c2[], char dest[], float f, 
	int style, float p);


/* ******************** Fixed functions ***************** */

int plugin_seq_getversion(void) 
{
	return B_PLUGIN_VERSION;
}

void plugin_but_changed(int but) 
{
}

void plugin_init()
{
}

void plugin_getinfo(PluginInfo *info)
{
	info->name= name;
	info->nvars= sizeof(varstr)/sizeof(VarStruct);
	info->cfra= &cfra;

	info->varstr= varstr;

	info->init= plugin_init;
	info->seq_doit= (SeqDoit) plugin_seq_doit;
	info->callback= plugin_but_changed;
}
/************************ End Fixed Functions *******************************/

void mixit (float c[4], char c1[4], char c2[4], char dest[4], float f, 
	int style, float p) {

   switch (style) {
      case none:
   	dest[0] = c1[0];
   	dest[1] = c1[1]; 
   	dest[2] = c1[2]; 
   	dest[3] = c1[3]; 
	break;

      case rgb:
   	dest[0] = p * c[0];  	/* A */
   	dest[1] = p * c[1]; 	/* B */
   	dest[2] = p * c[2]; 	/* G */
   	dest[3] = p * c[3]; 	/* R */
        break;

      case rgbshadow: 
   	dest[0] = (1 - p) * c[0]; /* A */
   	dest[1] = (1 - p) * c[1]; /* B */
   	dest[2] = (1 - p) * c[2]; /* G */
   	dest[3] = (1 - p) * c[3]; /* R */
        break;

     case fade:
   	dest[0] = (1 - p) * c1[0] + p * c2[0]; 
	if (dest[0] > 255) dest[0] = c[0]; /* A */
   	dest[1] = (1 - p) * c1[1] + p * c2[1]; 
	if (dest[1] > 255) dest[1] = c[1]; /* B */	
   	dest[2] = (1 - p) * c1[2] + p * c2[2]; 
	if (dest[2] > 255) dest[2] = c[2]; /* G */
   	dest[3] = (1 - p) * c1[3] + p * c2[3]; 
	if (dest[3] > 255) dest[3] = c[3]; /* R */ 
        break;

      case simple: 
   	dest[0] = (1 - f) * c1[0] + f * c2[0]; 
	if (dest[0] > 255) dest[0] = f * (1 - p) * c1[0]; /* A */
   	dest[1] = (1 - f) * c1[1] + f * c2[1]; 
	if (dest[1] > 255) dest[1] = f * (1 - p) * c1[1]; /* B */
   	dest[2] = (1 - f) * c1[2] + f * c2[2]; 
	if (dest[2] > 255) dest[2] = f * (1 - p) * c1[2]; /* G */
   	dest[3] = (1 - f) * c1[3] + f * c2[3]; 
	if (dest[3] > 255) dest[3] = f * (1 - p) * c1[3]; /* R */ 
        break;

   } /* switch */
}

static void use_ibuf(char src[3], char dest[3]) {
   int i;
   for (i=0; i<=3; i++) dest[i]= src[i];
}

void plugin_seq_doit(Cast *cast, float facf0, float facf1, int x, int y, 
	ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *out, ImBuf *use)
{
   char *in1_row, *in2_row, *dest_row;
   int row, col, h, style; 
   float  mx, bw, b1, b2, offset, f, c[4];	/* rgb[0] = red, 
				rgba[1] = green, rgb[2] = blue rgb[3] = alpha */

   if (!ibuf1 || !ibuf2 || ibuf2==ibuf1) return;

   h = cast->horiz;
   offset = cast->offset;

   if(h) offset = offset * ibuf1->y ;
   else offset = offset * ibuf1->x;

   bw = cast->bw * offset;
   b1 = offset - bw;
   b2 = offset;

   f = cast->f;
   style = cast->style;
   /* Acording to blender documentation the array is ABGR */
   c[0] = 0; /* Alpha */
   c[1] = cast->bf; /* Blue */
   c[2] = cast->gf; /* Green */
   c[3] = cast->rf;  /* Red */
   
   dest_row = (char *) out->rect;
   in1_row  = (char *) ibuf1->rect;
   in2_row = (char *) ibuf2->rect;

   for (row = 0; row < ibuf1->y; row++) {

      for (col = 0; col < ibuf1->x; col++) 
      {	
        
	if (h) {
	   if (row < b1)
               use_ibuf (in1_row, dest_row);
	   else if (row >= b1 && row <= b2) {
              mx = (float)(row - b1) / (float)bw;
	      mixit (c, in1_row, in2_row, dest_row, f, style, mx);
	   }
	   else
               use_ibuf (in2_row, dest_row);
	}
 	else {
	   if (col < b1)
	      use_ibuf (in1_row, dest_row);
	   else if (col >= b1 && col <= b2) {
              mx = (float)(col - b1) /(float) bw;
	      mixit (c, in1_row, in2_row, dest_row, f, style, mx);
           }
	   else
	      use_ibuf (in2_row, dest_row);
	}
	dest_row += 4;
	in1_row += 4;
	in2_row += 4;
      }

   }		
} /* plugin_seq_doit */			 
