Subversion Repositories filter_foundry

Rev

Rev 536 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
210 daniel-mar 1
/*
268 daniel-mar 2
    This file is part of "Filter Foundry", a filter plugin for Adobe Photoshop
536 daniel-mar 3
    Copyright (C) 2003-2009 Toby Thain, toby@telegraphics.net
550 daniel-mar 4
    Copyright (C) 2018-2023 Daniel Marschall, ViaThinkSoft
210 daniel-mar 5
 
312 daniel-mar 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.
210 daniel-mar 10
 
312 daniel-mar 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.
210 daniel-mar 15
 
312 daniel-mar 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
210 daniel-mar 19
*/
20
 
334 daniel-mar 21
/* Portions Copyright 1996 - 1999 Adobe Systems Incorporated */
22
/* All Rights Reserved.                                      */
210 daniel-mar 23
 
24
//#include <stdio.h>
25
 
26
//#include "world.h" // must come before Photoshop includes
27
 
28
#include "ff.h"
29
 
30
#include "scripting.h"
31
//#include "ui.h"
32
#include "dbg.h"
33
 
34
//extern FilterRecordPtr gpb;
35
 
217 daniel-mar 36
OSErr put_cstring(PIWriteDescriptor token, DescriptorKeyID key, char* s) {
37
        OSErr e;
38
        size_t n = strlen(s);
39
        Ptr p;
40
        Handle h = PINEWHANDLE((int32)n);
41
        p = PILOCKHANDLE(h, false);
42
        memcpy(p, s, n);
43
        PIUNLOCKHANDLE(h);
44
        e = PIPutText(token, key, h);
45
        PIDISPOSEHANDLE(h); /* Not 100% sure if we are supposed to dispose of handle. It doesn't crash though */
46
        return e;
210 daniel-mar 47
}
48
 
217 daniel-mar 49
char* get_cstring(PIReadDescriptor token) {
505 daniel-mar 50
        size_t n;
217 daniel-mar 51
        Ptr p;
52
        char* str = NULL;
53
        Handle h;
54
        OSErr e = PIGetText(token, &h);
210 daniel-mar 55
 
482 daniel-mar 56
        if ((e == noErr) && h) {
217 daniel-mar 57
                n = PIGETHANDLESIZE(h);
58
                p = PILOCKHANDLE(h, false);
59
                if ((str = (char*)malloc(n + 1))) {
60
                        memcpy(str, p, n);
61
                        str[n] = 0;
62
                }
63
                PIUNLOCKHANDLE(h);
64
                PIDISPOSEHANDLE(h); /* Not 100% sure if we are supposed to dispose of handle. It doesn't crash though */
65
        }
66
        return str;
210 daniel-mar 67
}
68
 
69
// If parm is NULL, then it is standalone, otherwise it is the main plugin
70
OSType getAeteKey(char c, PARM_T* parm) {
217 daniel-mar 71
        // To make our plugin compatible with AppleScript, each key must
72
        // be unique, since the namespace is global!
73
        // Furthermore, the "uniqueID/scope" hstm-field in the PIPL must be empty.
210 daniel-mar 74
 
217 daniel-mar 75
        if (parm != NULL) {
76
                unsigned long hash;
77
                char* data;
444 daniel-mar 78
                // char* debug = (char*)malloc(2000);
393 daniel-mar 79
                // sprintf(debug, "getAeteKey %c with title %s/%s in STANDALONE PLUGIN", c, parm->szTitle, parm->szCategory);
217 daniel-mar 80
                // simplealert(debug);
424 daniel-mar 81
                // free(debug);
210 daniel-mar 82
 
217 daniel-mar 83
                // Use random AETE keys, because AppleScript has a global namespace
84
                // and therefore requires unique AETE keys
85
                data = (char*)malloc(0x300);
86
                if (!data) return 0;
87
                sprintf(data, "%s %s %c",
393 daniel-mar 88
                        parm->szCategory,
89
                        parm->szTitle,
217 daniel-mar 90
                        c);
91
                hash = printablehash(djb2(data));
92
                free(data);
93
                return hash;
94
        }
95
        else {
444 daniel-mar 96
                // char* debug = (char*)malloc(2000);
217 daniel-mar 97
                // sprintf(debug, "getAeteKey %c in MAIN PLUGIN", c);
98
                // simplealert(debug);
424 daniel-mar 99
                // free(debug);
210 daniel-mar 100
 
217 daniel-mar 101
                // Attention: AETE keys (xpr#, cTl#) must be equal in scripting.r, scripting.rc and scripting.c(getAeteKey)!
102
                if (c == 'R') return 'xprR';
103
                if (c == 'G') return 'xprG';
104
                if (c == 'B') return 'xprB';
105
                if (c == 'A') return 'xprA';
106
                if ((c >= '0') && (c <= '9')) return 'cTl0' + (c - '0');
107
                return 0;
108
        }
210 daniel-mar 109
}
110
 
111
/* return true if dialog should be shown */
112
enum ScriptingShowDialog ReadScriptParamsOnRead(void)
113
{
217 daniel-mar 114
        PIReadDescriptor token;
115
        DescriptorKeyID key;
116
        DescriptorTypeID type;
117
        DescriptorKeyIDArray array = { NULLID };
118
        int32 flags;
119
        //OSErr stickyError;
120
        int32 v;
210 daniel-mar 121
 
217 daniel-mar 122
        if (DescriptorAvailable(NULL)) { /* playing back.  Do our thing. */
123
                token = OpenReader(array);
124
                if (token) {
125
                        while (PIGetKey(token, &key, &type, &flags)) {
550 daniel-mar 126
                                if (key == getAeteKey('R', gdata->parm.standalone ? &gdata->parm : NULL)) {
127
                                        char *tmp = get_cstring(token);
128
                                        strcpy(gdata->parm.szFormula[0], tmp);
129
                                        free(tmp);
217 daniel-mar 130
                                }
550 daniel-mar 131
                                else if (key == getAeteKey('G', gdata->parm.standalone ? &gdata->parm : NULL)) {
132
                                        char* tmp = get_cstring(token);
133
                                        strcpy(gdata->parm.szFormula[1], tmp);
134
                                        free(tmp);
217 daniel-mar 135
                                }
550 daniel-mar 136
                                else if (key == getAeteKey('B', gdata->parm.standalone ? &gdata->parm : NULL)) {
137
                                        char* tmp = get_cstring(token);
138
                                        strcpy(gdata->parm.szFormula[2], tmp);
139
                                        free(tmp);
217 daniel-mar 140
                                }
550 daniel-mar 141
                                else if (key == getAeteKey('A', gdata->parm.standalone ? &gdata->parm : NULL)) {
142
                                        char* tmp = get_cstring(token);
143
                                        strcpy(gdata->parm.szFormula[3], tmp);
144
                                        free(tmp);
217 daniel-mar 145
                                }
146
                                else {
147
                                        int i;
148
                                        for (i = 0; i <= 7; ++i) {
550 daniel-mar 149
                                                if (key == getAeteKey((char)('0'+i), gdata->parm.standalone ? &gdata->parm : NULL)) {
217 daniel-mar 150
                                                        PIGetInt(token, &v);
453 daniel-mar 151
                                                        if (v < 0) v = 0;
456 daniel-mar 152
                                                        else if (v > 255) v = 255;
550 daniel-mar 153
                                                        gdata->parm.val[i] = (uint8_t)v;
217 daniel-mar 154
                                                }
155
                                        }
156
                                }
157
                        }
210 daniel-mar 158
 
217 daniel-mar 159
                        /*stickyError =*/ CloseReader(&token); // closes & disposes.
210 daniel-mar 160
 
217 daniel-mar 161
                        // all Filter Foundry parameters are optional,
162
                        // so we needn't worry if any are missing
163
                }
210 daniel-mar 164
 
217 daniel-mar 165
                return gpb->descriptorParameters->playInfo == plugInDialogDisplay ? SCR_SHOW_DIALOG : SCR_HIDE_DIALOG;
166
        }
167
        else {
168
                return SCR_NO_SCRIPT;
169
        }
210 daniel-mar 170
}
171
 
172
OSErr WriteScriptParamsOnRead(void)
173
{
217 daniel-mar 174
        PIWriteDescriptor token;
175
        OSErr gotErr = noErr;
550 daniel-mar 176
        extern int nplanes;
217 daniel-mar 177
        int i, allctls;
210 daniel-mar 178
 
217 daniel-mar 179
        if (DescriptorAvailable(NULL)) { /* recording.  Do our thing. */
180
                // 1. Call openWriteDescriptorProc which will return a PIWriteDescriptor token, such as writeToken.
181
                token = OpenWriter();
182
                if (token) {
183
                        // 2. Call various Put routines such as PutIntegerProc, PutFloatProc, etc., to add key/value pairs to writeToken. The keys and value types must correspond to those in your terminology resource.
210 daniel-mar 184
 
217 daniel-mar 185
                        // write keys here
550 daniel-mar 186
                        if (!gdata->parm.standalone) {
187
                                if (nplanes > 0) put_cstring(token, getAeteKey('R', gdata->parm.standalone ? &gdata->parm : NULL), gdata->parm.szFormula[0]);
188
                                if (nplanes > 1) put_cstring(token, getAeteKey('G', gdata->parm.standalone ? &gdata->parm : NULL), gdata->parm.szFormula[1]);
189
                                if (nplanes > 2) put_cstring(token, getAeteKey('B', gdata->parm.standalone ? &gdata->parm : NULL), gdata->parm.szFormula[2]);
190
                                if (nplanes > 3) put_cstring(token, getAeteKey('A', gdata->parm.standalone ? &gdata->parm : NULL), gdata->parm.szFormula[3]);
217 daniel-mar 191
                        }
210 daniel-mar 192
 
217 daniel-mar 193
                        /* only write values for the sliders that are actually used! */
550 daniel-mar 194
                        allctls = checksliders(4);
195
                        for (i = 0; i < 8; ++i) {
196
                                if (allctls || gdata->parm.ctl_used[i]) {
197
                                        PIPutInt(token, getAeteKey((char)('0'+i), gdata->parm.standalone ? &gdata->parm : NULL), gdata->parm.val[i]);
217 daniel-mar 198
                                }
199
                        }
200
 
201
                        gotErr = CloseWriter(&token); /* closes and sets dialog optional */
202
                        /* done.  Now pass handle on to Photoshop */
203
                }
204
        }
205
        return gotErr;
210 daniel-mar 206
}
207
 
208
 
209
//-------------------------------------------------------------------------------
210
//
211
//      HostDescriptorAvailable
212
//
213
//      Determines whether the PIDescriptorParameters callback is available.
214
//
215
//      Check for valid suite version, routine suite version, and routine count.
216
//      Also check that the subset of routines we actually use is actually present.
217
//
218
//-------------------------------------------------------------------------------
219
 
403 daniel-mar 220
Boolean HostDescriptorAvailable(PIDescriptorParameters* procs, Boolean* outNewerVersion)
210 daniel-mar 221
{
403 daniel-mar 222
        if (procs == NULL) return FALSE; // Photoshop < 4.0 don't has scripting
223
 
217 daniel-mar 224
        if (outNewerVersion)
225
                *outNewerVersion = procs->descriptorParametersVersion > kCurrentDescriptorParametersVersion
226
                || procs->readDescriptorProcs->readDescriptorProcsVersion > kCurrentReadDescriptorProcsVersion
227
                || procs->writeDescriptorProcs->writeDescriptorProcsVersion > kCurrentWriteDescriptorProcsVersion;
210 daniel-mar 228
 
217 daniel-mar 229
        return procs != NULL
230
                && procs->descriptorParametersVersion == kCurrentDescriptorParametersVersion
210 daniel-mar 231
 
217 daniel-mar 232
                && procs->readDescriptorProcs != NULL
233
                && procs->readDescriptorProcs->readDescriptorProcsVersion == kCurrentReadDescriptorProcsVersion
234
                && (unsigned int)(procs->readDescriptorProcs->numReadDescriptorProcs) >= kCurrentReadDescriptorProcsCount
235
                && procs->readDescriptorProcs->openReadDescriptorProc != NULL
236
                && procs->readDescriptorProcs->closeReadDescriptorProc != NULL
237
                && procs->readDescriptorProcs->getKeyProc != NULL
238
                && procs->readDescriptorProcs->getTextProc != NULL
239
                && procs->readDescriptorProcs->getIntegerProc != NULL
210 daniel-mar 240
 
217 daniel-mar 241
                && procs->writeDescriptorProcs != NULL
242
                && procs->writeDescriptorProcs->writeDescriptorProcsVersion == kCurrentWriteDescriptorProcsVersion
243
                && (unsigned int)(procs->writeDescriptorProcs->numWriteDescriptorProcs) >= kCurrentWriteDescriptorProcsCount
244
                && procs->writeDescriptorProcs->openWriteDescriptorProc != NULL
245
                && procs->writeDescriptorProcs->closeWriteDescriptorProc != NULL
246
                && procs->writeDescriptorProcs->putTextProc != NULL
247
                && procs->writeDescriptorProcs->putIntegerProc != NULL;
210 daniel-mar 248
}
249
 
250
 
251
//-------------------------------------------------------------------------------
252
//
253
//      HostCloseReader
254
//
255
//      Closes a read token, disposes its handle, sets the token to NULL, and
256
//      sets the parameter blocks' descriptor to NULL.
257
//
258
//      The Descriptor Parameters suite are callbacks designed for
259
//      scripting and automation.  See PIActions.h.
260
//
261
//      Inputs:
262
//              PIDescriptorParameters *procs   Pointer to Descriptor Parameters suite.
263
//
264
//              HandleProcs *hProcs                             Pointer to HandleProcs callback.
265
//
266
//              PIReadDescriptor *token                 Pointer to token to close.
267
//
268
//              procs->descriptor                               Pointer to original read handle.
269
//
270
//      Outputs:
271
//              PIReadDescriptor *token                 Set to NULL.
272
//
273
//              procs->descriptor                               Disposed then set to NULL.
274
//
275
//              returns OSErr                                   noErr or error if one occurred.
276
//
277
//-------------------------------------------------------------------------------
278
 
217 daniel-mar 279
OSErr HostCloseReader(PIDescriptorParameters* procs,
280
        HandleProcs* hProcs,
281
        PIReadDescriptor* token)
210 daniel-mar 282
{
217 daniel-mar 283
        // Close token:
284
        OSErr err = procs->readDescriptorProcs->closeReadDescriptorProc(*token);
210 daniel-mar 285
 
217 daniel-mar 286
        // Dispose the parameter block descriptor:
287
        hProcs->disposeProc(procs->descriptor);
210 daniel-mar 288
 
217 daniel-mar 289
        // Set the descriptor and the read token to NULL:
290
        procs->descriptor = NULL;
291
        *token = NULL;
210 daniel-mar 292
 
217 daniel-mar 293
        return err;
210 daniel-mar 294
 
295
} // end HostCloseReader
296
 
297
//-------------------------------------------------------------------------------
298
//
299
//      HostCloseWriter
300
//
301
//      Closes a write token, stores its handle in the global parameter block for
302
//      the host to use, sets the token to NULL, and sets the recordInfo to
303
//      plugInDialogOptional (the default).
304
//
305
//      The Descriptor Parameters suite are callbacks designed for
306
//      scripting and automation.  See PIActions.h.
307
//
308
//      Inputs:
309
//              PIDescriptorParameters *procs   Pointer to Descriptor Parameters suite.
310
//
311
//              HandleProcs *hProcs                             Pointer to HandleProcs callback.
312
//
313
//              PIWriteDescriptor *token                Pointer to token to close and pass on.
314
//
315
//              procs->descriptor                               Should be NULL.  If not, its contents
316
//                                                                              will be disposed and replaced.
317
//
318
//      Outputs:
319
//              PIWriteDescriptor *token                Set to NULL.
320
//
321
//              procs->descriptor                               Set to descriptor handle.
322
//
323
//              returns OSErr                                   noErr or error if one occurred.
324
//
325
//-------------------------------------------------------------------------------
326
 
217 daniel-mar 327
OSErr   HostCloseWriter(PIDescriptorParameters* procs,
328
        HandleProcs* hProcs,
329
        PIWriteDescriptor* token)
210 daniel-mar 330
{
217 daniel-mar 331
        OSErr err = noErr; // assume no error
332
        PIDescriptorHandle h = NULL;
210 daniel-mar 333
 
217 daniel-mar 334
        if (procs->descriptor != NULL) // don't need descriptor passed to us
335
                hProcs->disposeProc(procs->descriptor); // dispose.
210 daniel-mar 336
 
217 daniel-mar 337
        // 3. Call CloseWriteDescriptorProc with writeToken, which will create a PIDescriptorHandle.
338
        procs->writeDescriptorProcs->closeWriteDescriptorProc(*token, &h);
210 daniel-mar 339
 
217 daniel-mar 340
        // 4. Place the PIDescriptorHandle into the descriptor field. The host will dispose of it when finished.
341
        procs->descriptor = h;
210 daniel-mar 342
 
217 daniel-mar 343
        // 5. Set recordInfo.  Options are: plugInDialogOptional,
344
        // plugInDialogRequire, plugInDialogNone:
345
        procs->recordInfo = plugInDialogOptional;
210 daniel-mar 346
 
217 daniel-mar 347
        *token = NULL;
348
 
349
        return err;
350
 
210 daniel-mar 351
} // end HostCloseWriter