Subversion Repositories filter_foundry

Rev

Rev 268 | Rev 334 | Go to most recent revision | 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
312 daniel-mar 3
    Copyright (C) 2003-2009 Toby Thain, toby@telegraphics.com.au
4
    Copyright (C) 2018-2021 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
 
21
/* Portions Copyright 1996 - 1999 Adobe Systems Incorporated                */
22
/* All Rights Reserved.                                            */
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) {
50
        int n;
51
        Ptr p;
52
        char* str = NULL;
53
        Handle h;
54
        OSErr e = PIGetText(token, &h);
210 daniel-mar 55
 
217 daniel-mar 56
        if (!e && h) {
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;
78
                // char* debug = malloc(2000);
79
                // sprintf(debug, "getAeteKey %c with title %s/%s in STANDALONE PLUGIN", c, INPLACEP2CSTR(parm->title), INPLACEP2CSTR(parm->category));
80
                // simplealert(debug);
210 daniel-mar 81
 
217 daniel-mar 82
                // Use random AETE keys, because AppleScript has a global namespace
83
                // and therefore requires unique AETE keys
84
                data = (char*)malloc(0x300);
85
                if (!data) return 0;
86
                sprintf(data, "%s %s %c",
87
                        INPLACEP2CSTR(parm->category),
88
                        INPLACEP2CSTR(parm->title),
89
                        c);
90
                hash = printablehash(djb2(data));
91
                free(data);
92
                return hash;
93
        }
94
        else {
95
                // char* debug = malloc(2000);
96
                // sprintf(debug, "getAeteKey %c in MAIN PLUGIN", c);
97
                // simplealert(debug);
210 daniel-mar 98
 
217 daniel-mar 99
                // Attention: AETE keys (xpr#, cTl#) must be equal in scripting.r, scripting.rc and scripting.c(getAeteKey)!
100
                if (c == 'R') return 'xprR';
101
                if (c == 'G') return 'xprG';
102
                if (c == 'B') return 'xprB';
103
                if (c == 'A') return 'xprA';
104
                if ((c >= '0') && (c <= '9')) return 'cTl0' + (c - '0');
105
                return 0;
106
        }
210 daniel-mar 107
}
108
 
109
/* return true if dialog should be shown */
110
enum ScriptingShowDialog ReadScriptParamsOnRead(void)
111
{
217 daniel-mar 112
        PIReadDescriptor token;
113
        DescriptorKeyID key;
114
        DescriptorTypeID type;
115
        DescriptorKeyIDArray array = { NULLID };
116
        int32 flags;
117
        //OSErr stickyError;
118
        int32 v;
210 daniel-mar 119
 
217 daniel-mar 120
        if (DescriptorAvailable(NULL)) { /* playing back.  Do our thing. */
121
                token = OpenReader(array);
122
                if (token) {
123
                        while (PIGetKey(token, &key, &type, &flags)) {
124
                                if (key == getAeteKey('R', gdata->standalone ? &gdata->parm : NULL)) {
125
                                        expr[0] = get_cstring(token);
126
                                }
127
                                else if (key == getAeteKey('G', gdata->standalone ? &gdata->parm : NULL)) {
128
                                        expr[1] = get_cstring(token);
129
                                }
130
                                else if (key == getAeteKey('B', gdata->standalone ? &gdata->parm : NULL)) {
131
                                        expr[2] = get_cstring(token);
132
                                }
133
                                else if (key == getAeteKey('A', gdata->standalone ? &gdata->parm : NULL)) {
134
                                        expr[3] = get_cstring(token);
135
                                }
136
                                else {
137
                                        int i;
138
                                        for (i = 0; i <= 7; ++i) {
139
                                                if (key == getAeteKey('0' + i, gdata->standalone ? &gdata->parm : NULL)) {
140
                                                        PIGetInt(token, &v);
141
                                                        slider[i] = v;
142
                                                }
143
                                        }
144
                                }
145
                        }
210 daniel-mar 146
 
217 daniel-mar 147
                        /*stickyError =*/ CloseReader(&token); // closes & disposes.
210 daniel-mar 148
 
217 daniel-mar 149
                        // all Filter Foundry parameters are optional,
150
                        // so we needn't worry if any are missing
151
                }
210 daniel-mar 152
 
217 daniel-mar 153
                return gpb->descriptorParameters->playInfo == plugInDialogDisplay ? SCR_SHOW_DIALOG : SCR_HIDE_DIALOG;
154
        }
155
        else {
156
                return SCR_NO_SCRIPT;
157
        }
210 daniel-mar 158
}
159
 
160
OSErr WriteScriptParamsOnRead(void)
161
{
217 daniel-mar 162
        PIWriteDescriptor token;
163
        OSErr gotErr = noErr;
164
        extern int ctls[], maps[], nplanes;
165
        int i, allctls;
210 daniel-mar 166
 
217 daniel-mar 167
        if (DescriptorAvailable(NULL)) { /* recording.  Do our thing. */
168
                // 1. Call openWriteDescriptorProc which will return a PIWriteDescriptor token, such as writeToken.
169
                token = OpenWriter();
170
                if (token) {
171
                        // 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 172
 
217 daniel-mar 173
                        // write keys here
174
                        if (!gdata->standalone) {
175
                                if (nplanes > 0) put_cstring(token, getAeteKey('R', gdata->standalone ? &gdata->parm : NULL), expr[0]);
176
                                if (nplanes > 1) put_cstring(token, getAeteKey('G', gdata->standalone ? &gdata->parm : NULL), expr[1]);
177
                                if (nplanes > 2) put_cstring(token, getAeteKey('B', gdata->standalone ? &gdata->parm : NULL), expr[2]);
178
                                if (nplanes > 3) put_cstring(token, getAeteKey('A', gdata->standalone ? &gdata->parm : NULL), expr[3]);
179
                        }
210 daniel-mar 180
 
217 daniel-mar 181
                        /* only write values for the sliders that are actually used! */
182
                        allctls = checksliders(4, ctls, maps);
183
                        for (i = 0; i <= 7; ++i) {
184
                                if (allctls || ctls[i]) {
185
                                        PIPutInt(token, getAeteKey('0' + i, gdata->standalone ? &gdata->parm : NULL), slider[i]);
186
                                }
187
                        }
188
 
189
                        gotErr = CloseWriter(&token); /* closes and sets dialog optional */
190
                        /* done.  Now pass handle on to Photoshop */
191
                }
192
        }
193
        return gotErr;
210 daniel-mar 194
}
195
 
196
 
197
//-------------------------------------------------------------------------------
198
//
199
//      HostDescriptorAvailable
200
//
201
//      Determines whether the PIDescriptorParameters callback is available.
202
//
203
//      Check for valid suite version, routine suite version, and routine count.
204
//      Also check that the subset of routines we actually use is actually present.
205
//
206
//-------------------------------------------------------------------------------
207
 
217 daniel-mar 208
Boolean HostDescriptorAvailable(PIDescriptorParameters* procs,
209
        Boolean* outNewerVersion)
210 daniel-mar 210
{
217 daniel-mar 211
        if (outNewerVersion)
212
                *outNewerVersion = procs->descriptorParametersVersion > kCurrentDescriptorParametersVersion
213
                || procs->readDescriptorProcs->readDescriptorProcsVersion > kCurrentReadDescriptorProcsVersion
214
                || procs->writeDescriptorProcs->writeDescriptorProcsVersion > kCurrentWriteDescriptorProcsVersion;
210 daniel-mar 215
 
217 daniel-mar 216
        return procs != NULL
217
                && procs->descriptorParametersVersion == kCurrentDescriptorParametersVersion
210 daniel-mar 218
 
217 daniel-mar 219
                && procs->readDescriptorProcs != NULL
220
                && procs->readDescriptorProcs->readDescriptorProcsVersion == kCurrentReadDescriptorProcsVersion
221
                && (unsigned int)(procs->readDescriptorProcs->numReadDescriptorProcs) >= kCurrentReadDescriptorProcsCount
222
                && procs->readDescriptorProcs->openReadDescriptorProc != NULL
223
                && procs->readDescriptorProcs->closeReadDescriptorProc != NULL
224
                && procs->readDescriptorProcs->getKeyProc != NULL
225
                && procs->readDescriptorProcs->getTextProc != NULL
226
                && procs->readDescriptorProcs->getIntegerProc != NULL
210 daniel-mar 227
 
217 daniel-mar 228
                && procs->writeDescriptorProcs != NULL
229
                && procs->writeDescriptorProcs->writeDescriptorProcsVersion == kCurrentWriteDescriptorProcsVersion
230
                && (unsigned int)(procs->writeDescriptorProcs->numWriteDescriptorProcs) >= kCurrentWriteDescriptorProcsCount
231
                && procs->writeDescriptorProcs->openWriteDescriptorProc != NULL
232
                && procs->writeDescriptorProcs->closeWriteDescriptorProc != NULL
233
                && procs->writeDescriptorProcs->putTextProc != NULL
234
                && procs->writeDescriptorProcs->putIntegerProc != NULL;
210 daniel-mar 235
}
236
 
237
 
238
//-------------------------------------------------------------------------------
239
//
240
//      HostCloseReader
241
//
242
//      Closes a read token, disposes its handle, sets the token to NULL, and
243
//      sets the parameter blocks' descriptor to NULL.
244
//
245
//      The Descriptor Parameters suite are callbacks designed for
246
//      scripting and automation.  See PIActions.h.
247
//
248
//      Inputs:
249
//              PIDescriptorParameters *procs   Pointer to Descriptor Parameters suite.
250
//
251
//              HandleProcs *hProcs                             Pointer to HandleProcs callback.
252
//
253
//              PIReadDescriptor *token                 Pointer to token to close.
254
//
255
//              procs->descriptor                               Pointer to original read handle.
256
//
257
//      Outputs:
258
//              PIReadDescriptor *token                 Set to NULL.
259
//
260
//              procs->descriptor                               Disposed then set to NULL.
261
//
262
//              returns OSErr                                   noErr or error if one occurred.
263
//
264
//-------------------------------------------------------------------------------
265
 
217 daniel-mar 266
OSErr HostCloseReader(PIDescriptorParameters* procs,
267
        HandleProcs* hProcs,
268
        PIReadDescriptor* token)
210 daniel-mar 269
{
217 daniel-mar 270
        // Close token:
271
        OSErr err = procs->readDescriptorProcs->closeReadDescriptorProc(*token);
210 daniel-mar 272
 
217 daniel-mar 273
        // Dispose the parameter block descriptor:
274
        hProcs->disposeProc(procs->descriptor);
210 daniel-mar 275
 
217 daniel-mar 276
        // Set the descriptor and the read token to NULL:
277
        procs->descriptor = NULL;
278
        *token = NULL;
210 daniel-mar 279
 
217 daniel-mar 280
        return err;
210 daniel-mar 281
 
282
} // end HostCloseReader
283
 
284
//-------------------------------------------------------------------------------
285
//
286
//      HostCloseWriter
287
//
288
//      Closes a write token, stores its handle in the global parameter block for
289
//      the host to use, sets the token to NULL, and sets the recordInfo to
290
//      plugInDialogOptional (the default).
291
//
292
//      The Descriptor Parameters suite are callbacks designed for
293
//      scripting and automation.  See PIActions.h.
294
//
295
//      Inputs:
296
//              PIDescriptorParameters *procs   Pointer to Descriptor Parameters suite.
297
//
298
//              HandleProcs *hProcs                             Pointer to HandleProcs callback.
299
//
300
//              PIWriteDescriptor *token                Pointer to token to close and pass on.
301
//
302
//              procs->descriptor                               Should be NULL.  If not, its contents
303
//                                                                              will be disposed and replaced.
304
//
305
//      Outputs:
306
//              PIWriteDescriptor *token                Set to NULL.
307
//
308
//              procs->descriptor                               Set to descriptor handle.
309
//
310
//              returns OSErr                                   noErr or error if one occurred.
311
//
312
//-------------------------------------------------------------------------------
313
 
217 daniel-mar 314
OSErr   HostCloseWriter(PIDescriptorParameters* procs,
315
        HandleProcs* hProcs,
316
        PIWriteDescriptor* token)
210 daniel-mar 317
{
217 daniel-mar 318
        OSErr err = noErr; // assume no error
319
        PIDescriptorHandle h = NULL;
210 daniel-mar 320
 
217 daniel-mar 321
        if (procs->descriptor != NULL) // don't need descriptor passed to us
322
                hProcs->disposeProc(procs->descriptor); // dispose.
210 daniel-mar 323
 
217 daniel-mar 324
        // 3. Call CloseWriteDescriptorProc with writeToken, which will create a PIDescriptorHandle.
325
        procs->writeDescriptorProcs->closeWriteDescriptorProc(*token, &h);
210 daniel-mar 326
 
217 daniel-mar 327
        // 4. Place the PIDescriptorHandle into the descriptor field. The host will dispose of it when finished.
328
        procs->descriptor = h;
210 daniel-mar 329
 
217 daniel-mar 330
        // 5. Set recordInfo.  Options are: plugInDialogOptional,
331
        // plugInDialogRequire, plugInDialogNone:
332
        procs->recordInfo = plugInDialogOptional;
210 daniel-mar 333
 
217 daniel-mar 334
        *token = NULL;
335
 
336
        return err;
337
 
210 daniel-mar 338
} // end HostCloseWriter