Subversion Repositories filter_foundry

Rev

Rev 289 | Rev 291 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*
  2.     This file is part of "Filter Foundry", a filter plugin for Adobe Photoshop
  3.     Copyright (C) 2003-2009 Toby Thain, toby@telegraphics.com.au
  4.     Copyright (C) 2018-2021 Daniel Marschall, ViaThinkSoft
  5.  
  6.     This program is free software; you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License as published by
  8.     the Free Software Foundation; either version 2 of the License, or
  9.     (at your option) any later version.
  10.  
  11.     This program is distributed in the hope that it will be useful,
  12.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.     GNU General Public License for more details.
  15.  
  16.     You should have received a copy of the GNU General Public License
  17.     along with this program; if not, write to the Free Software
  18.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19. */
  20.  
  21. #ifdef MAC_ENV
  22. #include <fp.h>
  23. #endif
  24.  
  25. #include <math.h>
  26. #include <stdlib.h>
  27.  
  28. #ifndef PARSERTEST
  29. #include "ff.h"
  30. #endif
  31.  
  32. #include "funcs.h"
  33. #include "y.tab.h"
  34.  
  35. #include "node.h" // for symbol "var[]"
  36.  
  37. #define RINT //no rounding for now
  38.  
  39. //#if TARGET_API_MAC_CARBON
  40. // this is another incompatibility between Classic stdclib and OS X stdclib
  41. // ***FIXME: need to access real OS X includes for Carbon build
  42. //#undef RAND_MAX
  43. //#define RAND_MAX    0x7fffffff
  44. //#endif
  45.  
  46. extern value_type slider[],cell[],var[],map[][0x100];
  47. extern unsigned char *image_ptr;
  48.  
  49. double costab[COSTABSIZE];
  50. double tantab[TANTABSIZE];
  51. void init_trigtab(){
  52.         int i;
  53.         for(i=0;i<COSTABSIZE;++i){
  54.                 costab[i] = cos(FFANGLE(i));
  55.         }
  56.         for(i=0;i<TANTABSIZE;++i){
  57.                 if (i>=TANTABSIZE/2) {
  58.                         /* the last '-1' in the expression '512-i-1' is for FilterFactory compatibility, and to avoid the undefined pi/2 area */
  59.                         tantab[i] = -tantab[TANTABSIZE-i-1];
  60.                 } else {
  61.                         tantab[i] = tan(FFANGLE(i));
  62.                 }
  63.         }
  64. }
  65.  
  66. /* Channel z for the input pixel at coordinates x,y.
  67.  * Coordinates are relative to the input image data (pb->inData) */
  68. static value_type rawsrc(value_type x,value_type y,value_type z){
  69.         if (HAS_BIG_DOC(gpb)) {
  70.                 if (x < BIGDOC_IN_RECT(gpb).left)
  71.                         x = BIGDOC_IN_RECT(gpb).left;
  72.                 else if (x >= BIGDOC_IN_RECT(gpb).right)
  73.                         x = BIGDOC_IN_RECT(gpb).right - 1;
  74.                 if (y < BIGDOC_IN_RECT(gpb).top)
  75.                         y = BIGDOC_IN_RECT(gpb).top;
  76.                 else if (y >= BIGDOC_IN_RECT(gpb).bottom)
  77.                         y = BIGDOC_IN_RECT(gpb).bottom - 1;
  78.                 return ((unsigned char*)gpb->inData)[(long)gpb->inRowBytes * (y - BIGDOC_IN_RECT(gpb).top)
  79.                         + (long)nplanes * (x - BIGDOC_IN_RECT(gpb).left) + z];
  80.         } else {
  81.                 if (x < IN_RECT(gpb).left)
  82.                         x = IN_RECT(gpb).left;
  83.                 else if (x >= IN_RECT(gpb).right)
  84.                         x = IN_RECT(gpb).right - 1;
  85.                 if (y < IN_RECT(gpb).top)
  86.                         y = IN_RECT(gpb).top;
  87.                 else if (y >= IN_RECT(gpb).bottom)
  88.                         y = IN_RECT(gpb).bottom - 1;
  89.                 return ((unsigned char*)gpb->inData)[(long)gpb->inRowBytes * (y - IN_RECT(gpb).top)
  90.                         + (long)nplanes * (x - IN_RECT(gpb).left) + z];
  91.         }
  92. }
  93.  
  94. /* src(x,y,z) Channel z for the pixel at coordinates x,y.
  95.  * Coordinates are relative to filtered area (selection). */
  96. value_type ff_src(value_type x,value_type y,value_type z){
  97.         #ifdef PARSERTEST
  98.         return 0;
  99.         #else
  100.         if(x < 0)
  101.                 x = 0;
  102.         else if(x >= var['X'])
  103.                 x = var['X']-1;
  104.         if(y < 0)
  105.                 y = 0;
  106.         else if(y >= var['Y'])
  107.                 y = var['Y']-1;
  108.         return z >= 0 && z < var['Z'] ?
  109.                 image_ptr[(long)gpb->inRowBytes*y + (long)nplanes*x + z] : 0;
  110.         #endif
  111. }
  112.  
  113. /* rad(d,m,z) Channel z in the source image, which is m units away,
  114.         at an angle of d, from the center of the image */
  115. value_type ff_rad(value_type d,value_type m,value_type z){
  116.         return ff_src(ff_r2x(d,m) + var['X']/2, ff_r2y(d,m) + var['Y']/2, z);
  117. }
  118.  
  119. /* ctl(i) Value of slider i, where i is an integer between 0 and 7, inclusive */
  120. value_type ff_ctl(value_type i){
  121.         return i>=0 && i<=7 ? slider[i] : 0;
  122. }
  123.  
  124. /* val(i,a,b) Value of slider i, mapped onto the range a to b */
  125. value_type ff_val(value_type i,value_type a,value_type b){
  126.         return ((long)ff_ctl(i)*(b-a))/255 + a;
  127. }
  128.  
  129. /* map(i,n) Item n from mapping table i, where i is an integer between
  130.         0 and 3, inclusive, and n is and integer between 0 and 255,
  131.         inclusive */
  132. value_type ff_map(value_type i,value_type n){
  133. /*
  134.         if( i>=0 && i<=3 && n>=0 && n<=255 ){
  135.                 int H = slider[i*2],L = slider[i*2+1];
  136.                 return n<=L || H==L ? 0 : ( n>=H ? 255 : ((n-L)*255L)/(H-L) );
  137.         }else
  138.                 return 0;
  139. */
  140.         // this code is from GIMP User Filter
  141.         value_type x = ff_ctl(i*2),
  142.                            y = ff_ctl(i*2+1);
  143.         return abs(((long)n*(y-x) / 255)+x);
  144. }
  145.  
  146. /* min(a,b) Lesser of a and b */
  147. value_type ff_min(value_type a,value_type b){
  148.         return a < b ? a : b;
  149. }
  150.  
  151. /* max(a,b) Greater of a and b */
  152. value_type ff_max(value_type a,value_type b){
  153.         return a > b ? a : b;
  154. }
  155.  
  156. /* abs(a) Absolute value of a */
  157. value_type ff_abs(value_type a){
  158.         return abs(a);
  159. }
  160.  
  161. /* add(a,b,c) Sum of a and b, or c, whichever is lesser */
  162. value_type ff_add(value_type a,value_type b,value_type c){
  163.         return ff_min(a+b,c);
  164. }
  165.  
  166. /* sub(a,b,c) Difference of a and b, or c, whichever is greater */
  167. value_type ff_sub(value_type a,value_type b,value_type c){
  168.         return ff_max(ff_dif(a,b),c);
  169. }
  170.  
  171. /* dif(a,b) Absolute value of the difference of a and b */
  172. value_type ff_dif(value_type a,value_type b){
  173.         return abs(a-b);
  174. }
  175.  
  176. struct factoryRngState {
  177.         uint16_t gFactoryRndIndexCounter1;
  178.         uint16_t gFactoryRndIndexCounter2;
  179.         uint32_t gFactoryRndLookup[56];
  180.         uint32_t gFactoryRndSeed;
  181.         uint32_t gFactoryRndSeedSave;
  182. } gRngState;
  183.  
  184. void factory_fill_rnd_lookup(uint32_t seed, struct factoryRngState* state) {
  185.         // Algorithm of Filter Factory
  186.         // Filter Factory uses Donald E.Knuth's subtractive
  187.         // random number generator algorithm ("ran3"), which has been published
  188.         // in Page 283 of "The Art of Computer Programming, volume 2: Seminumerical Algorithms",
  189.         // Addison-Wesley, Reading, MA, second edition, 1981.
  190.         // https://www.cec.uchile.cl/cinetica/pcordero/MC_libros/NumericalRecipesinC.pdf (PDF Page 307)
  191.  
  192.         long mj, mk;
  193.         int i, ii, k;
  194.  
  195.         // 161803398 = 1.61803398 * 10^8 ~= phi * 10^8
  196.         mj = 161803398 - (seed & 0x7fff);
  197.         state->gFactoryRndLookup[55] = mj;
  198.  
  199.         mk = 1;
  200.         ii = 0;
  201.         for (i=1; i<=54; ++i) {
  202.                 if ((ii += 21) >= 55) ii -= 55; // ii = (21*i)%55;
  203.                 state->gFactoryRndLookup[ii] = mk;
  204.                 mk = mj - mk;
  205.                 mj = state->gFactoryRndLookup[ii];
  206.         }
  207.  
  208.         for (k=1; k<=4; ++k) {
  209.                 ii = 30;
  210.                 for (i=1; i<=55; ++i) {
  211.                         if ((ii += 1) >= 55) ii -= 55;
  212.                         state->gFactoryRndLookup[i] -= state->gFactoryRndLookup[1 + ii]; // 1 + (i+30)%55
  213.                 }
  214.         }
  215.  
  216.         state->gFactoryRndSeedSave = seed;
  217.  
  218.         return;
  219. }
  220.  
  221. uint32_t factory_rnd(uint32_t a, uint32_t b, struct factoryRngState* state) {
  222.         uint32_t mj; // Note: This must be "uint32_t". With "long" (as described by Knuth), it won't match FilterFactory's algorithm
  223.         int range;
  224.  
  225.         if (state->gFactoryRndSeed != state->gFactoryRndSeedSave) {
  226.                 // (Intentional) behavior of Filter Foundry
  227.                 factory_fill_rnd_lookup(state->gFactoryRndSeed, &gRngState);
  228.                 state->gFactoryRndIndexCounter1 = 0;
  229.                 state->gFactoryRndIndexCounter2 = 31;
  230.         }
  231.  
  232.         // Algorithm of Filter Factory
  233.         // Filter Factory uses Donald E.Knuth's subtractive
  234.         // random number generator algorithm ("ran3"), which has been published
  235.         // in Page 283 of "The Art of Computer Programming, volume 2: Seminumerical Algorithms",
  236.         // Addison-Wesley, Reading, MA, second edition, 1981.
  237.         // https://www.cec.uchile.cl/cinetica/pcordero/MC_libros/NumericalRecipesinC.pdf (PDF Page 307)
  238.  
  239.         if (++state->gFactoryRndIndexCounter1 == 56) state->gFactoryRndIndexCounter1 = 1;
  240.         if (++state->gFactoryRndIndexCounter2 == 56) state->gFactoryRndIndexCounter2 = 1;
  241.  
  242.         mj = state->gFactoryRndLookup[state->gFactoryRndIndexCounter1] -
  243.              state->gFactoryRndLookup[state->gFactoryRndIndexCounter2];
  244.         state->gFactoryRndLookup[state->gFactoryRndIndexCounter1] = mj;
  245.  
  246.         // This is Filter Factory specific:
  247.         // Reduce result into interval [a..b] by applying (a + (mj % (b - a + 1))
  248.         // Try to avoid modulo in order to increase performance
  249.         range = b - a;
  250.         if (range < 0) return 0;
  251.         switch (range) {
  252.                 case 255:
  253.                         return a + (mj & 0xFF);
  254.                 case 127:
  255.                         return a + (mj & 0x7F);
  256.                 case 63:
  257.                         return a + (mj & 0x3F);
  258.                 case 31:
  259.                         return a + (mj & 0x1F);
  260.                 case 15:
  261.                         return a + (mj & 0xF);
  262.                 case 7:
  263.                         return a + (mj & 0x7);
  264.                 case 3:
  265.                         return a + (mj & 0x3);
  266.                 case 1:
  267.                         return a + (mj & 0x1);
  268.                 case 0:
  269.                         return a;
  270.                 default:
  271.                         return a + (mj % (range + 1));
  272.         }
  273. }
  274.  
  275. int32_t factory_rst(uint32_t seed, struct factoryRngState* state) {
  276.         // We implement rst(i) completely differently in Filter Foundry:
  277.         // Every call of rst() will renew the lookup table.
  278.         // In Filter Factory, there are strange/buggy things going
  279.         // on: rst(i) only sets a seed and the lookup table is renewed
  280.         // at the NEXT invocation of the filter. Furthermore, in FilterFactory,
  281.         // the state is not reset between invocations, therefore, the preview image
  282.         // will influence the PRNG state of the final image...
  283.         // More information at "Filter Factory Compatibility.md"
  284.  
  285.         state->gFactoryRndSeed = seed;
  286.  
  287.         // Force renewal of the PRNG state in the next rnd(a,b) call.
  288.         // This allows us to use:
  289.         //    (x==0?rst(1):0), rnd(0,255)
  290.         // But it is slower and this won't work anymore:
  291.         //    rst(0), rnd(0,255)
  292.         state->gFactoryRndSeedSave = seed+1;
  293.  
  294.         return 0;
  295. }
  296.  
  297. void factory_initialize_rnd_variables() {
  298.         gRngState.gFactoryRndSeed = 0; // default seed
  299.         gRngState.gFactoryRndSeedSave = gRngState.gFactoryRndSeed + 1; // force rnd() to call factory_fill_rnd_lookup()
  300. }
  301.  
  302. /* rnd(a,b) Random number between a and b, inclusive */
  303. value_type ff_rnd(value_type a,value_type b){
  304.         return factory_rnd(a,b,&gRngState);
  305. //      return (int)((abs(a-b)+1)*(rand()/(RAND_MAX+1.))) + ff_min(a,b);
  306. //      return ((unsigned)rand() % (ff_dif(a,b)+1)) + ff_min(a,b);
  307. }
  308.  
  309. /* mix(a,b,n,d) Mixture of a and b by fraction n/d, a*n/d+b*(d-n)/d */
  310. value_type ff_mix(value_type a,value_type b,value_type n,value_type d){
  311.         return d ? ((long)a*n)/d + ((long)b*(d-n))/d : 0;
  312. }
  313.  
  314. /* scl(a,il,ih,ol,oh) Scale a from input range (il to ih)
  315.                       to output range (ol to oh) */
  316. value_type ff_scl(value_type a,value_type il,value_type ih,
  317.                   value_type ol,value_type oh){
  318.         return ih==il ? 0 : ol + ((long)(oh-ol)*(a-il))/(ih-il);
  319. }
  320.  
  321. static uint32_t isqrt(uint32_t x) {
  322.         // based on https://gist.github.com/orlp/3481770
  323.  
  324.         static uint32_t lkpSquares[65535];
  325.         static int lkpInitialized = 0;
  326.         const uint32_t *p;
  327.         int i;
  328.  
  329.         while (lkpInitialized == 1) { /* If other thread is currently creating the lookup table, then wait */ }
  330.         if (!lkpInitialized) {
  331.                 lkpInitialized = 1;
  332.                 for (i = 0; i < 65535; ++i) {
  333.                         lkpSquares[i] = i * i;
  334.                 }
  335.                 lkpInitialized = 2;
  336.         }
  337.  
  338.         p = lkpSquares;
  339.  
  340.         if (p[32768] <= x) p += 32768;
  341.         if (p[16384] <= x) p += 16384;
  342.         if (p[8192] <= x) p += 8192;
  343.         if (p[4096] <= x) p += 4096;
  344.         if (p[2048] <= x) p += 2048;
  345.         if (p[1024] <= x) p += 1024;
  346.         if (p[512] <= x) p += 512;
  347.         if (p[256] <= x) p += 256;
  348.         if (p[128] <= x) p += 128;
  349.         if (p[64] <= x) p += 64;
  350.         if (p[32] <= x) p += 32;
  351.         if (p[16] <= x) p += 16;
  352.         if (p[8] <= x) p += 8;
  353.         if (p[4] <= x) p += 4;
  354.         if (p[2] <= x) p += 2;
  355.         if (p[1] <= x) p += 1;
  356.  
  357.         return (uint32_t)(p - lkpSquares);
  358. }
  359.  
  360. /* sqr(x) Square root of x */
  361. value_type ff_sqr(value_type x){
  362.         return x < 0 ? 0 : isqrt(x);
  363. }
  364.  
  365. /* sin(x) Sine function of x, where x is an integer between 0 and
  366.    1024, inclusive, and the value returned is an integer
  367.    between -512 and 512, inclusive (Windows) or -1024 and
  368.    1024, inclusive (Mac OS) */
  369. value_type ff_sin(value_type x){
  370.         //return RINT(TRIGAMP*sin(FFANGLE(x)));
  371.         return ff_cos(x-256);
  372. }
  373.  
  374. /* cos(x) Cosine function of x, where x is an integer between 0 and
  375.    1024, inclusive, and the value returned is an integer
  376.    between -512 and 512, inclusive (Windows) or -1024 and
  377.    1024, inclusive (Mac OS) */
  378. value_type ff_cos(value_type x){
  379.         //return RINT(TRIGAMP*cos(FFANGLE(x)));
  380.         return (value_type)RINT(TRIGAMP*costab[abs(x) % COSTABSIZE]);
  381. }
  382.  
  383. /* tan(x) Tangent function of x, where x is an integer
  384.    between -256 and 256, inclusive. Althought the Filter Factory manual
  385.    stated that the return value is bounded to -512 and 512, inclusive (Windows) or
  386.    -1024 and 1024, inclusive (Mac OS), the output is actually NOT bounded! */
  387. value_type ff_tan(value_type x){
  388.         // Following filter shows that the Filter Factory manual differs from the implementation.
  389.         //         R = cos(x) > 1024 || cos(x) < -1024 || cos(-x) > 1024 || cos(-x) < -1024 ? 255 : 0
  390.         //     G = tan(x) > 1024 || tan(x) < -1024 || tan(-x) > 1024 || tan(-x) < -1024 ? 255 : 0
  391.         //     B = sin(x) > 1024 || sin(x) < -1024 || sin(-x) > 1024 || sin(-x) < -1024 ? 255 : 0
  392.         // It outputs green stripes, showing that the output of tan() is not bounded.
  393.         // So, we do it the same way to stay compatible.
  394.         if (x < 0) x--; /* required for Filter Factory compatibility */
  395.         while (x < 0) x += TANTABSIZE;
  396.         return (value_type)RINT(2*TRIGAMP*tantab[x % TANTABSIZE]); // We need the x2 multiplicator for some reason
  397. }
  398.  
  399. /* r2x(d,m) x displacement of the pixel m units away, at an angle of d,
  400.    from an arbitrary center */
  401. value_type ff_r2x(value_type d,value_type m){
  402.         return (value_type)RINT(m*costab[abs(d) % COSTABSIZE]);
  403. }
  404.  
  405. /* r2y(d,m) y displacement of the pixel m units away, at an angle of d,
  406.    from an arbitrary center */
  407. value_type ff_r2y(value_type d,value_type m){
  408.         return (value_type)RINT(m*costab[abs(d-256) % COSTABSIZE]);
  409. }
  410.  
  411. /* Attention! This is NOT a function. It is internally used to calculate the variable "d". */
  412. value_type ff_c2d_negated(value_type x, value_type y) {
  413.         // NOTE: FilterFactory uses c2d(x,y):=atan2(y,x), but d:=atan2(-y,-x)
  414.         // Due to compatibility reasons, we implement it the same way!
  415.         // Sign of y difference is negated, as we are dealing with top-down coordinates angle is "observed"
  416.         return (value_type)RINT(TO_FFANGLE(atan2(-y,-x)));
  417. }
  418.  
  419. /* c2d(x,y) Angle displacement of the pixel at coordinates x,y */
  420. value_type ff_c2d(value_type x,value_type y){
  421.         // Behavior of FilterFoundry <1.7:
  422.         //return ff_c2d_negated(x,y);
  423.  
  424.         // Behavior in FilterFoundry 1.7+: Matches FilterFactory
  425.         return (value_type)RINT(TO_FFANGLE(atan2(y,x)));
  426. }
  427.  
  428. /* c2m(x,y) Magnitude displacement of the pixel at coordinates x,y */
  429. value_type ff_c2m(value_type x,value_type y){
  430.         return isqrt((long)x*x + (long)y*y);
  431. }
  432.  
  433. /* get(i) Returns the current cell value at i */
  434. value_type ff_get(value_type i){
  435.         // Filter Factory:
  436.         //return i>=0 && i<NUM_CELLS ? cell[i] : i;
  437.  
  438.         // Filter Foundry:
  439.         return i>=0 && i<NUM_CELLS ? cell[i] : 0;
  440. }
  441.  
  442. /* put(v,i) Puts the new value v into cell i */
  443. value_type ff_put(value_type v,value_type i){
  444.         if(i>=0 && i<NUM_CELLS)
  445.                 cell[i] = v;
  446.         return v;
  447. }
  448.  
  449. /* Convolve. Applies a convolution matrix and divides with d. */
  450. value_type ff_cnv(value_type m11,value_type m12,value_type m13,
  451.                                   value_type m21,value_type m22,value_type m23,
  452.                                   value_type m31,value_type m32,value_type m33,
  453.                                   value_type d)
  454. {
  455.         #ifdef PARSERTEST
  456.         return 0;
  457.         #else
  458.         long total;
  459.         int x, y, z;
  460.         // shift x,y from selection-relative to image relative
  461.         if (HAS_BIG_DOC(gpb)) {
  462.                 x = var['x'] + BIGDOC_FILTER_RECT(gpb).left;
  463.                 y = var['y'] + BIGDOC_FILTER_RECT(gpb).top;
  464.         } else {
  465.                 x = var['x'] + FILTER_RECT(gpb).left;
  466.                 y = var['y'] + FILTER_RECT(gpb).top;
  467.         }
  468.         z = var['z'];
  469.  
  470.         if(z >= 0 && z < var['Z'])
  471.                 total = m11*rawsrc(x-1,y-1,z) + m12*rawsrc(x,y-1,z) + m13*rawsrc(x+1,y-1,z)
  472.                           + m21*rawsrc(x-1,y,  z) + m22*rawsrc(x,y,  z) + m23*rawsrc(x+1,y,  z)
  473.                           + m31*rawsrc(x-1,y+1,z) + m32*rawsrc(x,y+1,z) + m33*rawsrc(x+1,y+1,z);
  474.         else
  475.                 total = 0;
  476.  
  477.         return d ? total/d : 0;
  478.         #endif
  479. }
  480.  
  481. /* rst(i) sets a random seed and returns 0. (undocumented Filter Factory function).
  482.    Added by DM, 18 Dec 2018 */
  483. value_type ff_rst(value_type seed){
  484.         factory_rst(seed,&gRngState);
  485. //      srand(seed);
  486.         return 0;
  487. }
  488.  
  489. value_type zero_val = 0;
  490. value_type one_val = 1;
  491. value_type max_channel_val = 255;
  492.  
  493. /* predefined symbols */
  494. struct sym_rec predefs[]={
  495.         /* functions */
  496.  
  497.         {0,TOK_FN3,"src", (pfunc_type)ff_src, 0},
  498.         {0,TOK_FN3,"rad", (pfunc_type)ff_rad, 0},
  499.         {0,TOK_FN1,"ctl", (pfunc_type)ff_ctl, 0},
  500.         {0,TOK_FN3,"val", (pfunc_type)ff_val, 0},
  501.         {0,TOK_FN2,"map", (pfunc_type)ff_map, 0},
  502.         {0,TOK_FN2,"min", (pfunc_type)ff_min, 0},
  503.         {0,TOK_FN2,"max", (pfunc_type)ff_max, 0},
  504.         {0,TOK_FN1,"abs", (pfunc_type)ff_abs, 0},
  505.         {0,TOK_FN3,"add", (pfunc_type)ff_add, 0},
  506.         {0,TOK_FN3,"sub", (pfunc_type)ff_sub, 0},
  507.         {0,TOK_FN2,"dif", (pfunc_type)ff_dif, 0},
  508.         {0,TOK_FN2,"rnd", (pfunc_type)ff_rnd, 0},
  509.         {0,TOK_FN4,"mix", (pfunc_type)ff_mix, 0},
  510.         {0,TOK_FN5,"scl", (pfunc_type)ff_scl, 0},
  511.         {0,TOK_FN1,"sqr", (pfunc_type)ff_sqr, 0},
  512.         {0,TOK_FN1,"sqrt", (pfunc_type)ff_sqr, 0}, // sqrt() is synonym to sqr() in Premiere
  513.         {0,TOK_FN1,"sin", (pfunc_type)ff_sin, 0},
  514.         {0,TOK_FN1,"cos", (pfunc_type)ff_cos, 0},
  515.         {0,TOK_FN1,"tan", (pfunc_type)ff_tan, 0},
  516.         {0,TOK_FN2,"r2x", (pfunc_type)ff_r2x, 0},
  517.         {0,TOK_FN2,"r2y", (pfunc_type)ff_r2y, 0},
  518.         {0,TOK_FN2,"c2d", (pfunc_type)ff_c2d, 0},
  519.         {0,TOK_FN2,"c2m", (pfunc_type)ff_c2m, 0},
  520.         {0,TOK_FN1,"get", (pfunc_type)ff_get, 0},
  521.         {0,TOK_FN2,"put", (pfunc_type)ff_put, 0},
  522.         {0,TOK_FN10,"cnv",(pfunc_type)ff_cnv, 0},
  523.         {0,TOK_FN1,"rst", (pfunc_type)ff_rst, 0}, // undocumented FilterFactory function
  524.  
  525.         /* predefined variables (names with more than 1 character); most of them are undocumented in FilterFactory */
  526.         /* the predefined variables with 1 character are defined in lexer.l and process.c */
  527.         /* in this table, you must not add TOK_VAR with only 1 character (since this case is not defined in parser.y) */
  528.  
  529.         {0,TOK_VAR,"rmax",0, &max_channel_val}, // alias of 'R' (defined in lexer.l, line 129)
  530.         {0,TOK_VAR,"gmax",0, &max_channel_val}, // alias of 'G' (defined in lexer.l, line 129)
  531.         {0,TOK_VAR,"bmax",0, &max_channel_val}, // alias of 'B' (defined in lexer.l, line 129)
  532.         {0,TOK_VAR,"amax",0, &max_channel_val}, // alias of 'A' (defined in lexer.l, line 129)
  533.         {0,TOK_VAR,"cmax",0, &max_channel_val}, // alias of 'C' (defined in lexer.l, line 129)
  534.         {0,TOK_VAR,"imax",0, &max_channel_val}, // alias of 'I' (defined in lexer.l, line 129)
  535.         {0,TOK_VAR,"umax",0, &max_channel_val}, // alias of 'U' (defined in lexer.l, line 129)
  536.         {0,TOK_VAR,"vmax",0, &max_channel_val}, // alias of 'V' (defined in lexer.l, line 129)
  537.         {0,TOK_VAR,"dmax",0, &var['D']},
  538.         {0,TOK_VAR,"mmax",0, &var['M']},
  539.         {0,TOK_VAR,"pmax",0, &var['Z']},
  540.         {0,TOK_VAR,"xmax",0, &var['X']},
  541.         {0,TOK_VAR,"ymax",0, &var['Y']},
  542.         {0,TOK_VAR,"zmax",0, &var['Z']},
  543.  
  544.         {0,TOK_VAR,"rmin",0, &zero_val},
  545.         {0,TOK_VAR,"gmin",0, &zero_val},
  546.         {0,TOK_VAR,"bmin",0, &zero_val},
  547.         {0,TOK_VAR,"amin",0, &zero_val},
  548.         {0,TOK_VAR,"cmin",0, &zero_val},
  549.         {0,TOK_VAR,"imin",0, &zero_val},
  550.         {0,TOK_VAR,"umin",0, &zero_val},
  551.         {0,TOK_VAR,"vmin",0, &zero_val},
  552.         {0,TOK_VAR,"dmin",0, &zero_val},
  553.         {0,TOK_VAR,"mmin",0, &zero_val},
  554.         {0,TOK_VAR,"pmin",0, &zero_val},
  555.         {0,TOK_VAR,"xmin",0, &zero_val},
  556.         {0,TOK_VAR,"ymin",0, &zero_val},
  557.         {0,TOK_VAR,"zmin",0, &zero_val},
  558.  
  559.         /* Undocumented synonyms of FilterFactory for compatibility with Premiere */
  560.         {0,TOK_FN10,"cnv0",(pfunc_type)ff_cnv, 0},
  561.         {0,TOK_FN3,"src0", (pfunc_type)ff_src, 0},
  562.         {0,TOK_FN3,"rad0", (pfunc_type)ff_rad, 0},
  563.         {0,TOK_FN10,"cnv1",(pfunc_type)ff_cnv, 0},
  564.         {0,TOK_FN3,"src1", (pfunc_type)ff_src, 0},
  565.         {0,TOK_FN3,"rad1", (pfunc_type)ff_rad, 0},
  566.         {0,TOK_VAR,"r0",0, &var['r']},
  567.         {0,TOK_VAR,"g0",0, &var['g']},
  568.         {0,TOK_VAR,"b0",0, &var['b']},
  569.         {0,TOK_VAR,"a0",0, &var['a']},
  570.         {0,TOK_VAR,"c0",0, &var['c']},
  571.         {0,TOK_VAR,"i0",0, &var['i']},
  572.         {0,TOK_VAR,"u0",0, &var['u']},
  573.         {0,TOK_VAR,"v0",0, &var['v']},
  574.         {0,TOK_VAR,"d0",0, &var['d']},
  575.         {0,TOK_VAR,"m0",0, &var['m']},
  576.         {0,TOK_VAR,"r1",0, &var['r']},
  577.         {0,TOK_VAR,"g1",0, &var['g']},
  578.         {0,TOK_VAR,"b1",0, &var['b']},
  579.         {0,TOK_VAR,"a1",0, &var['a']},
  580.         {0,TOK_VAR,"c1",0, &var['c']},
  581.         {0,TOK_VAR,"i1",0, &var['i']},
  582.         {0,TOK_VAR,"u1",0, &var['u']},
  583.         {0,TOK_VAR,"v1",0, &var['v']},
  584.         {0,TOK_VAR,"d1",0, &var['d']},
  585.         {0,TOK_VAR,"m1",0, &var['m']},
  586.         {0,TOK_VAR,"tmin",0, &zero_val},
  587.         {0,TOK_VAR,"tmax",0, &one_val},
  588.         {0,TOK_VAR,"total",0, &one_val},
  589.  
  590.         {0,0,0,0,0}
  591. };
  592.