Subversion Repositories filter_foundry

Rev

Rev 158 | Rev 164 | 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-9 Toby Thain, toby@telegraphics.com.au
  4.  
  5.     This program is free software; you can redistribute it and/or modify
  6.     it under the terms of the GNU General Public License as published by
  7.     the Free Software Foundation; either version 2 of the License, or
  8.     (at your option) any later version.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License
  16.     along with this program; if not, write to the Free Software
  17.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18. */
  19.  
  20. //#include <stdio.h>
  21. //#include <sound.h>
  22.  
  23. #include "ff.h"
  24.  
  25. #include "node.h"
  26. #include "y.tab.h"
  27. #include "scripting.h"
  28.  
  29. struct node *tree[4];
  30. char *err[4];
  31. int errpos[4],errstart[4],nplanes,cnvused,chunksize,toprow;
  32. value_type slider[8],cell[NUM_CELLS],map[4][0x100];
  33. char *expr[4];
  34. // long maxSpace;
  35. globals_t *gdata;
  36. FilterRecordPtr gpb;
  37.  
  38. #ifdef MAC_ENV
  39.         #define hDllInstance NULL /* fake this Windows-only global */
  40. #endif
  41.  
  42. #ifdef WIN_ENV
  43. #include "manifest.h"
  44. #endif
  45.  
  46. extern struct sym_rec predefs[];
  47. extern int nplanes,varused[];
  48.  
  49. int checkandinitparams(Handle params);
  50.  
  51. // MPW MrC requires prototype
  52. DLLEXPORT MACPASCAL
  53. void ENTRYPOINT(short selector,FilterRecordPtr pb,intptr_t *data,short *result);
  54.  
  55. DLLEXPORT MACPASCAL
  56. void ENTRYPOINT(short selector, FilterRecordPtr pb, intptr_t *data, short *result){
  57.         static Boolean wantdialog = false;
  58.         OSErr e = noErr;
  59.         char *reason;
  60.  
  61. #ifdef WIN_ENV
  62.         // For Windows, we use an activation context to enforce that our Manifest resource will
  63.         // be used. This allows us to use Visual Styles, even if the host application does not
  64.         // support it.
  65.         ManifestActivationCtx manifestVars;
  66.         BOOL activationContextUsed;
  67.  
  68.         activationContextUsed = ActivateManifest(hDllInstance, 1, &manifestVars);
  69.  
  70.         __try {
  71. #endif
  72.  
  73.         if(selector != filterSelectorAbout && !*data){
  74.                 BufferID tempId;
  75.                 if( (*result = PS_BUFFER_ALLOC(sizeof(globals_t), &tempId)) )
  76.                         return;
  77.                 *data = (intptr_t)PS_BUFFER_LOCK(tempId, true);
  78.                 gdata = (globals_t*)*data;
  79.                 gdata->standalone = gdata->parmloaded = false;
  80.         }else
  81.                 gdata = (globals_t*)*data;
  82.  
  83.         EnterCodeResource();
  84.  
  85.         gpb = pb;
  86.  
  87.         nplanes = MIN(pb->planes,4);
  88.  
  89.         switch (selector){
  90.         case filterSelectorAbout:
  91.                 if(gdata && !gdata->parmloaded)
  92.                         gdata->standalone = gdata->parmloaded = readPARMresource(hDllInstance,&reason,1);
  93.                 DoAbout((AboutRecordPtr)pb);
  94.                 break;
  95.         case filterSelectorParameters:
  96.                 wantdialog = true;
  97.                 break;
  98.         case filterSelectorPrepare:
  99.                 DoPrepare(pb);
  100.                 init_symtab(predefs); // ready for parser calls
  101.                 init_trigtab();
  102.                 break;
  103.         case filterSelectorStart:
  104.                 /* initialise the parameter handle that Photoshop keeps for us */
  105.                 if(!pb->parameters)
  106.                         pb->parameters = PINEWHANDLE(0);
  107.  
  108.                 wantdialog |= checkandinitparams(pb->parameters);
  109.  
  110.                 /* wantdialog = false means that we never got a Parameters call, so we're not supposed to ask user */
  111.                 if( wantdialog && (!gdata->standalone || gdata->parm.popDialog) ){
  112.                         if( maindialog(pb) ){
  113.                                 /* update stored parameters from new user settings */
  114.                                 saveparams(pb->parameters);
  115.                         }else
  116.                                 e = userCanceledErr;
  117.                 }
  118.                 wantdialog = false;
  119.  
  120.                 if(!e){
  121.                         if(setup(pb)){
  122.                                 DoStart(pb);
  123.                         }else{
  124.                                 SYSBEEP(1);
  125.                                 e = filterBadParameters;
  126.                         }
  127.                 }
  128.                 break;
  129.         case filterSelectorContinue:
  130.                 e = DoContinue(pb);
  131.                 break;
  132.         case filterSelectorFinish:
  133.                 DoFinish(pb);
  134.                 break;
  135.         default:
  136.                 e = filterBadParameters;
  137.         }
  138.  
  139.         *result = e;
  140.  
  141.         ExitCodeResource();
  142.  
  143. #ifdef WIN_ENV
  144.         } __finally {
  145.                 if (activationContextUsed) DeactivateManifest(&manifestVars);
  146.         }
  147. #endif
  148. }
  149.  
  150. int checkandinitparams(Handle params){
  151.         char *reasonstr,*reason;
  152.         int i,f,showdialog;
  153.  
  154.         if( (f = !(params && readparams(params,false,&reasonstr))) ){
  155.                 /* either the parameter handle was uninitialised,
  156.                    or the parameter data couldn't be read; set default values */
  157.  
  158.                 // see if saved parameters exist
  159.                 gdata->standalone = gdata->parmloaded = readPARMresource(hDllInstance,&reason,1);
  160.  
  161.                 if(!gdata->standalone){
  162.                         // no saved settings (not standalone)
  163.                         for(i = 0; i < 8; ++i)
  164.                                 slider[i] = i*10+100;
  165.                         for(i = 0; i < 4; ++i)
  166.                                 if(expr[i])
  167.                                         free(expr[i]);
  168.                         if(gpb->imageMode == plugInModeRGBColor){
  169.                                 expr[0] = my_strdup("r");
  170.                                 expr[1] = my_strdup("g");
  171.                                 expr[2] = my_strdup("b");
  172.                                 expr[3] = my_strdup("a");
  173.                         }else{
  174.                                 expr[0] = my_strdup("c");
  175.                                 expr[1] = my_strdup("c");
  176.                                 expr[2] = my_strdup("c");
  177.                                 expr[3] = my_strdup("c");
  178.                         }
  179.                 }
  180.         }
  181.  
  182.         // let scripting system change parameters, if we're scripted;
  183.         // user may want to force display of dialog during scripting playback
  184.         showdialog = ReadScriptParamsOnRead();
  185.  
  186.         saveparams(params);
  187.         return f || showdialog;
  188. }
  189.  
  190. void DoPrepare(FilterRecordPtr pb){
  191.         int i;
  192.  
  193.         for(i = 4; i--;){
  194.                 if(expr[i]||tree[i]) DBG("expr[] or tree[] non-NULL in Prepare!");
  195.                 expr[i] = NULL;
  196.                 tree[i] = NULL;
  197.         }
  198.  
  199.         // Commented out by DM, 18 Dec 2018:
  200.         // This code did not work on systems with 8 GB RAM:
  201.         /*
  202.         long space = (pb->maxSpace*9)/10; // don't ask for more than 90% of available memory
  203.  
  204.         maxSpace = 512L<<10; // this is a wild guess, actually
  205.         if(maxSpace > space)
  206.                 maxSpace = space;
  207.         pb->maxSpace = maxSpace;
  208.         */
  209.  
  210.         // New variant:
  211.         // TODO: Programmatically test if host supports pb->maxSpace64, and if it does so, use this value instead.
  212.         pb->maxSpace = ((double)pb->maxSpace/10)*9; // don't ask for more than 90% of available memory
  213. }
  214.  
  215. void RequestNext(FilterRecordPtr pb,long toprow){
  216.         /* Request next block of the image */
  217.  
  218.         pb->inLoPlane = pb->outLoPlane = 0;
  219.         pb->inHiPlane = pb->outHiPlane = nplanes-1;
  220.  
  221.         // if any of the formulae involve random access to image pixels,
  222.         // ask for the entire image
  223.         if(needall){
  224.                 SETRECT(pb->inRect,0,0,pb->imageSize.h,pb->imageSize.v);
  225.         }else{
  226.                 // otherwise, process the filtered area, by chunksize parts
  227.                 pb->inRect.left = pb->filterRect.left;
  228.                 pb->inRect.right = pb->filterRect.right;
  229.                 pb->inRect.top = toprow;
  230.                 pb->inRect.bottom = MIN(toprow + chunksize,pb->filterRect.bottom);
  231.  
  232.                 if(cnvused){
  233.                         // cnv() needs one extra pixel in each direction
  234.                         if(pb->inRect.left > 0)
  235.                                 --pb->inRect.left;
  236.                         if(pb->inRect.right < pb->imageSize.h)
  237.                                 ++pb->inRect.right;
  238.                         if(pb->inRect.top > 0)
  239.                                 --pb->inRect.top;
  240.                         if(pb->inRect.bottom < pb->imageSize.v)
  241.                                 ++pb->inRect.bottom;
  242.                 }
  243.         }
  244.         pb->outRect = pb->filterRect;
  245. /*
  246. {char s[0x100];sprintf(s,"RequestNext needall=%d inRect=(%d,%d,%d,%d) filterRect=(%d,%d,%d,%d)",
  247.         needall,
  248.         pb->inRect.left,pb->inRect.top,pb->inRect.right,pb->inRect.bottom,
  249.         pb->filterRect.left,pb->filterRect.top,pb->filterRect.right,pb->filterRect.bottom);dbg(s);}
  250. */
  251. }
  252.  
  253. void DoStart(FilterRecordPtr pb){
  254. //dbg("DoStart");
  255.         /* if src() or rad() functions are used, random access to the image data is required,
  256.            so we must request the entire image in a single chunk. */
  257.         chunksize = needall ? (pb->filterRect.bottom - pb->filterRect.top) : CHUNK_ROWS;
  258.         toprow = pb->filterRect.top;
  259.         RequestNext(pb,toprow);
  260. }
  261.  
  262. OSErr DoContinue(FilterRecordPtr pb){
  263.         OSErr e = noErr;
  264.         Rect fr;
  265.         long outoffset;
  266.  
  267.         if(needall)
  268.                 fr = pb->filterRect;  // filter whole selection at once
  269.         else if(cnvused){
  270.                 // we've requested one pixel extra all around
  271.                 // (see RequestNext()), just for access purposes. But filter
  272.                 // original selection only.
  273.                 fr.left = pb->filterRect.left;
  274.                 fr.right = pb->filterRect.right;
  275.                 fr.top = toprow;
  276.                 fr.bottom = MIN(toprow + chunksize,pb->filterRect.bottom);
  277.         }else  // filter whatever portion we've been given
  278.                 fr = pb->inRect;
  279.  
  280.         outoffset = (long)pb->outRowBytes*(fr.top - pb->outRect.top)
  281.                                 + (long)nplanes*(fr.left - pb->outRect.left);
  282.  
  283.         if(!(e = process_scaled(pb, true, &fr, &fr,
  284.                                 (Ptr)pb->outData+outoffset, pb->outRowBytes, 1.)))
  285.         {
  286.                 toprow += chunksize;
  287.                 if(toprow < pb->filterRect.bottom)
  288.                         RequestNext(pb,toprow);
  289.                 else{
  290.                         SETRECT(pb->inRect,0,0,0,0);
  291.                         pb->outRect = pb->maskRect = pb->inRect;
  292.                 }
  293.         }
  294.         return e;
  295. }
  296.  
  297. void DoFinish(FilterRecordPtr pb){
  298.         int i;
  299.  
  300.         WriteScriptParamsOnRead();
  301.  
  302.         for(i = 4; i--;){
  303.                 freetree(tree[i]);
  304.                 if(expr[i]) free(expr[i]);
  305.         }
  306. }
  307.