Subversion Repositories filter_foundry

Rev

Rev 146 | Rev 159 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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