Rev 498 | Rev 511 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
184 | dmarschall | 1 | /* |
247 | daniel-mar | 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 |
||
503 | daniel-mar | 4 | Copyright (C) 2018-2022 Daniel Marschall, ViaThinkSoft |
184 | dmarschall | 5 | |
247 | 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. |
||
184 | dmarschall | 10 | |
247 | 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. |
||
184 | dmarschall | 15 | |
247 | 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 |
||
184 | dmarschall | 19 | */ |
20 | |||
21 | #include <stddef.h> |
||
22 | #include <stdint.h> |
||
185 | dmarschall | 23 | #include <assert.h> |
184 | dmarschall | 24 | |
25 | #include "ff.h" |
||
26 | #include "symtab.h" |
||
27 | |||
210 | daniel-mar | 28 | #include "scripting.h" |
184 | dmarschall | 29 | #include "PIActions.h" |
30 | #include "PITerminology.h" |
||
31 | |||
32 | #include "compat_string.h" |
||
33 | |||
207 | daniel-mar | 34 | //#define PRINTABLE_HASH_FF16 |
212 | daniel-mar | 35 | #define ENABLE_APPLESCRIPT |
207 | daniel-mar | 36 | |
184 | dmarschall | 37 | /* |
207 | daniel-mar | 38 | Find a printable 4-character key, remembering (see Photoshop API guide): |
39 | - All IDs starting with an uppercase letter are reserved by Adobe. |
||
40 | - All IDs that are all uppercase are reserved by Apple. |
||
41 | - All IDs that are all lowercase are reserved by Apple. |
||
42 | - This leaves all IDs that begin with a lowercase letter and have at least |
||
43 | one uppercase letter for you and other plug-in developers. |
||
44 | Note: It is questionable if "a!!!" or "A!!!" are also reseved by Apple. We don't risk it. |
||
184 | dmarschall | 45 | */ |
46 | unsigned long printablehash(unsigned long hash) { |
||
268 | daniel-mar | 47 | #ifdef PRINTABLE_HASH_FF16 |
48 | |||
247 | daniel-mar | 49 | // FilterFoundry version 1.6 hashing by Toby Thain |
489 | daniel-mar | 50 | // Only accepts upper-case at the last character |
247 | daniel-mar | 51 | // 0 = 'a A' |
52 | // 6100899 = 'z~~Z' |
||
489 | daniel-mar | 53 | unsigned long key = 'a' + (hash % 26); hash /= 26; // first lower-case |
247 | daniel-mar | 54 | key = (key << 8) | (' ' + (hash % 95)); hash /= 95; // any printable |
55 | key = (key << 8) | (' ' + (hash % 95)); hash /= 95; // any printable |
||
489 | daniel-mar | 56 | return (key << 8) | ('A' + (hash % 26)); // last upper-case |
268 | daniel-mar | 57 | |
58 | #else |
||
59 | |||
247 | daniel-mar | 60 | // FilterFoundry version 1.7 hashing by Daniel Marschall |
489 | daniel-mar | 61 | // Accepts upper-case at character 2, 3 or 4 |
247 | daniel-mar | 62 | // Spaces are only set the right as padding to make a code shorter |
63 | // 0 = 'aA ' |
||
64 | // 13530139 = 'zZZZ' |
||
65 | // The key-space is ~2.22 times larger |
||
66 | long lowlim; |
||
67 | long uplim; |
||
68 | int upperCaseInfo; |
||
69 | int length; |
||
70 | int lastThreeCharInfo; |
||
71 | int firstChar; |
||
72 | unsigned long key; |
||
73 | int found; |
||
74 | int i,j,k; |
||
207 | daniel-mar | 75 | |
247 | daniel-mar | 76 | uplim = 0; |
77 | for (k=1; k<4; k++) { |
||
456 | daniel-mar | 78 | int mask = 0; |
247 | daniel-mar | 79 | if (k == 1) mask = 1;//0b1; |
80 | if (k == 2) mask = 2;//0b11; |
||
81 | if (k == 3) mask = 4;//0b111; |
||
82 | for (i=1; i<=mask; i++) { |
||
83 | // 'k' characters |
||
84 | long test = 1; |
||
85 | for (j=0; j<k; ++j) { |
||
86 | test *= ((i&(1<<j)) != 0) ? 26 : 94-26; |
||
87 | } |
||
88 | uplim += test; |
||
89 | } |
||
90 | } |
||
207 | daniel-mar | 91 | |
247 | daniel-mar | 92 | lastThreeCharInfo = hash % uplim; hash /= uplim; |
93 | firstChar = hash%26; hash /= 26; |
||
207 | daniel-mar | 94 | |
247 | daniel-mar | 95 | lowlim = 0; |
96 | uplim = 0; |
||
97 | found = 0; |
||
98 | length = -1; // avoid compiler warning |
||
99 | upperCaseInfo = -1; // avoid compiler warning |
||
100 | for (k=1; k<4; k++) { |
||
101 | int mask; |
||
102 | if (k == 1) mask = 1;//0b1; |
||
103 | if (k == 2) mask = 2;//0b11; |
||
104 | if (k == 3) mask = 4;//0b111; |
||
105 | if (!found) for (i=1; i<=mask; i++) { |
||
106 | // 'k' characters |
||
107 | long test = 1; |
||
108 | for (j=0; j<k; ++j) { |
||
109 | test *= ((i&(1<<j)) != 0) ? 26 : 94-26; |
||
110 | } |
||
111 | uplim += test; |
||
112 | if ((lastThreeCharInfo >= lowlim) && (lastThreeCharInfo < uplim)) { |
||
113 | lastThreeCharInfo -= lowlim; |
||
114 | found = 1; |
||
115 | length = k; |
||
116 | upperCaseInfo = i; |
||
117 | break; |
||
118 | } |
||
119 | lowlim = uplim; |
||
120 | } |
||
121 | } |
||
207 | daniel-mar | 122 | |
247 | daniel-mar | 123 | key = ('a' + firstChar) << 24; // first char is lower-case |
124 | for (i=0; i<length; ++i) { |
||
125 | char res; |
||
126 | if ((upperCaseInfo&(1<<i)) == 0) { |
||
127 | res = '!' + (lastThreeCharInfo % (94-26)); |
||
128 | if (res >= 'A') res += 26; |
||
129 | lastThreeCharInfo /= (94-26); |
||
130 | } else { |
||
131 | res = 'A' + (lastThreeCharInfo % 26); |
||
132 | lastThreeCharInfo /= 26; |
||
133 | } |
||
134 | key |= res << (8*(i+(4-length-1))); // 2nd, 3rd, 4th char are either upper-case or any printable char |
||
135 | } |
||
136 | if (length == 1) { |
||
137 | key &= 0xFFFF0000; |
||
138 | key |= ' ' << 8; |
||
139 | key |= ' '; |
||
140 | } |
||
141 | if (length == 2) { |
||
142 | key &= 0xFFFFFF00; |
||
143 | key |= ' '; |
||
144 | } |
||
145 | return key; |
||
268 | daniel-mar | 146 | |
147 | #endif |
||
184 | dmarschall | 148 | } |
149 | |||
238 | daniel-mar | 150 | size_t roundToNext4(size_t x) { |
247 | daniel-mar | 151 | int pad = 4 - (x % 4); |
152 | if (pad == 0) pad = 4; |
||
153 | return x + pad; |
||
184 | dmarschall | 154 | } |
155 | |||
393 | daniel-mar | 156 | size_t fixpipl(PIPropertyList *pipl, size_t origsize, char* title, long *event_id) { |
247 | daniel-mar | 157 | PIProperty *prop; |
158 | char *p; |
||
159 | struct hstm_data { |
||
160 | /* this structure must be 14+1 bytes long, to match PiPL structure */ |
||
161 | long version; /* = 0 */ |
||
162 | long class_id; |
||
163 | long event_id; |
||
164 | short aete_resid; |
||
165 | char scope[1]; |
||
166 | }; |
||
167 | struct hstm_data *hstm; |
||
168 | int scopelen; |
||
169 | unsigned long hash; |
||
170 | size_t realLength; |
||
171 | size_t roundedLength; |
||
424 | daniel-mar | 172 | char szScope[0x300]; |
184 | dmarschall | 173 | |
247 | daniel-mar | 174 | pipl->count += 3; // 3 more keys in PiPL: name, catg, hstm |
184 | dmarschall | 175 | |
247 | daniel-mar | 176 | p = (char*)pipl + origsize; |
177 | prop = (PIProperty*)p; |
||
184 | dmarschall | 178 | |
503 | daniel-mar | 179 | /* Important not about proptyLength: |
180 | |||
181 | In regards propertyLength, Adobe writes in SPPiPL.h: |
||
182 | "Number of characters in the data array. Rounded to a multiple of 4." |
||
183 | |||
184 | On the other hand, the 1997 PICA documentation(page 23) and |
||
185 | 1996 "Cross-Application Plug-in Development Resource Guide" describes : |
||
186 | "[propertyLength] contains the length of the propertyData field. It does not include any padding bytes after |
||
187 | propertyData to achieve four byte alignment.This field may be zero." |
||
188 | |||
189 | I think this is not correct, since even official plugins of Adobe(e.g. "3D Transform.8bf") and cnvtpipl |
||
190 | are rounding the length to a multiple of 4 (actually, rounding to the next possible multiple 4, |
||
191 | so that padding is always guaranteed). |
||
192 | Photoshop (tested with Photoshop 7) will crash if the propertyLength follows the definition of PICA. |
||
193 | */ |
||
194 | |||
247 | daniel-mar | 195 | /* add Title/Name property key */ |
184 | dmarschall | 196 | |
247 | daniel-mar | 197 | prop->vendorID = kPhotoshopSignature; |
198 | prop->propertyKey = PINameProperty; |
||
199 | prop->propertyID = 0; |
||
393 | daniel-mar | 200 | prop->propertyLength = (SPInt32)roundToNext4(strlen(title) + 1); |
247 | daniel-mar | 201 | memset(prop->propertyData, 0x00, prop->propertyLength); // fill padding with 00h bytes (cosmetics) |
393 | daniel-mar | 202 | myc2pstrcpy((StringPtr)prop->propertyData, title); |
184 | dmarschall | 203 | |
247 | daniel-mar | 204 | // skip past new property record, and any padding |
205 | p += offsetof(PIProperty, propertyData) + prop->propertyLength; |
||
206 | prop = (PIProperty*)p; |
||
184 | dmarschall | 207 | |
247 | daniel-mar | 208 | /* add Category property key */ |
184 | dmarschall | 209 | |
247 | daniel-mar | 210 | prop->vendorID = kPhotoshopSignature; |
211 | prop->propertyKey = PICategoryProperty; |
||
212 | prop->propertyID = 0; |
||
218 | daniel-mar | 213 | |
393 | daniel-mar | 214 | prop->propertyLength = (SPInt32)roundToNext4(strlen(gdata->parm.szCategory) + 1); |
247 | daniel-mar | 215 | memset(prop->propertyData, 0x00, prop->propertyLength); // fill padding with 00h bytes (cosmetics) |
393 | daniel-mar | 216 | myc2pstrcpy((StringPtr)prop->propertyData, gdata->parm.szCategory); |
184 | dmarschall | 217 | |
247 | daniel-mar | 218 | p += offsetof(PIProperty, propertyData) + prop->propertyLength; |
219 | prop = (PIProperty*)p; |
||
184 | dmarschall | 220 | |
247 | daniel-mar | 221 | /* add HasTerminology property key */ |
184 | dmarschall | 222 | |
247 | daniel-mar | 223 | hstm = (struct hstm_data*)prop->propertyData; |
212 | daniel-mar | 224 | |
424 | daniel-mar | 225 | sprintf(szScope, "%s %s", |
393 | daniel-mar | 226 | gdata->parm.szCategory, |
227 | title); |
||
228 | daniel-mar | 228 | |
247 | daniel-mar | 229 | #ifdef ENABLE_APPLESCRIPT |
230 | // If the uniqueString/scope is set, the plugin will only communicate with Photoshop. |
||
231 | // Otherwise it can be accessed with AppleScript, but the AETE keys need to be unique then. |
||
232 | // This is achieved with getAeteKey(). |
||
233 | scopelen = 0; |
||
234 | hstm->scope[0] = '\0'; |
||
235 | #else |
||
236 | // Construct scope string by concatenating Category and Title - hopefully unique! |
||
237 | // Note: In doresources() we malloc'ed 300h additional bytes, |
||
238 | // and in the build dialog, title and category are size-limited, |
||
239 | // so we can write here without malloc. |
||
424 | daniel-mar | 240 | scopelen = strlen(&szScope); |
241 | memcpy(&hstm->scope, &szScope, scopelen); |
||
247 | daniel-mar | 242 | #endif |
184 | dmarschall | 243 | |
247 | daniel-mar | 244 | /* make up a new event ID for this aete, based on printable base-95 hash of scope */ |
424 | daniel-mar | 245 | hash = djb2(szScope); |
247 | daniel-mar | 246 | *event_id = printablehash(hash); /* this is used by aete_generate() later... */ |
184 | dmarschall | 247 | |
247 | daniel-mar | 248 | prop->vendorID = kPhotoshopSignature; |
249 | prop->propertyKey = PIHasTerminologyProperty; |
||
250 | prop->propertyID = 0; |
||
184 | dmarschall | 251 | |
247 | daniel-mar | 252 | realLength = offsetof(struct hstm_data, scope) + scopelen + 1/*null-term*/; |
253 | roundedLength = roundToNext4(realLength); |
||
254 | prop->propertyLength = (SPInt32)roundedLength; |
||
255 | memset(prop->propertyData + realLength, 0x00, roundedLength - realLength); // fill padding with 00h bytes (cosmetics) |
||
218 | daniel-mar | 256 | |
247 | daniel-mar | 257 | hstm->version = 0; |
258 | hstm->class_id = plugInClassID; |
||
259 | hstm->event_id = *event_id; |
||
260 | hstm->aete_resid = AETE_ID; |
||
184 | dmarschall | 261 | |
247 | daniel-mar | 262 | p += offsetof(PIProperty, propertyData) + prop->propertyLength; |
184 | dmarschall | 263 | |
247 | daniel-mar | 264 | return p - (char*)pipl; // figure how many bytes were added |
184 | dmarschall | 265 | } |
266 | |||
187 | dmarschall | 267 | void _aete_write_byte(void** aeteptr, uint8_t val) { |
247 | daniel-mar | 268 | uint8_t* tmp = *((uint8_t**)aeteptr); |
269 | *tmp = val; |
||
270 | *aeteptr = (void*)((unsigned char*)tmp + 1); |
||
187 | dmarschall | 271 | } |
272 | #define AETE_WRITE_BYTE(i) _aete_write_byte(&aeteptr, (i)); |
||
184 | dmarschall | 273 | |
187 | dmarschall | 274 | void _aete_write_word(void** aeteptr, uint16_t val) { |
247 | daniel-mar | 275 | uint16_t* tmp = *((uint16_t**)aeteptr); |
276 | *tmp = val; |
||
277 | *aeteptr = (void*)((unsigned char*)tmp + 2); |
||
187 | dmarschall | 278 | } |
279 | #define AETE_WRITE_WORD(i) _aete_write_word(&aeteptr, (i)); |
||
280 | |||
281 | void _aete_write_dword(void** aeteptr, uint32_t val) { |
||
247 | daniel-mar | 282 | uint32_t* tmp = *((uint32_t**)aeteptr); |
283 | *tmp = val; |
||
284 | *aeteptr = (void*)((unsigned char*)tmp + 4); |
||
187 | dmarschall | 285 | } |
286 | #define AETE_WRITE_DWORD(i) _aete_write_dword(&aeteptr, (i)); |
||
287 | |||
229 | daniel-mar | 288 | void _aete_write_c2pstr(void** aeteptr, char* str) { |
247 | daniel-mar | 289 | char* tmp; |
187 | dmarschall | 290 | |
247 | daniel-mar | 291 | assert(strlen(str) <= 255); |
187 | dmarschall | 292 | |
247 | daniel-mar | 293 | _aete_write_byte(aeteptr, (uint8_t)strlen(str)); |
187 | dmarschall | 294 | |
247 | daniel-mar | 295 | tmp = *((char**)aeteptr); |
296 | strcpy(tmp, str); |
||
297 | *aeteptr = (void*)((unsigned char*)tmp + strlen(str)); |
||
187 | dmarschall | 298 | } |
498 | daniel-mar | 299 | #define AETE_WRITE_C2PSTR(s) _aete_write_c2pstr(&aeteptr, (char*)(s)); |
268 | daniel-mar | 300 | |
229 | daniel-mar | 301 | void _aete_write_p2pstr(void** aeteptr, char* str) { |
312 | daniel-mar | 302 | char* tmp; |
187 | dmarschall | 303 | |
312 | daniel-mar | 304 | if (strlen(str) == 0) { |
305 | _aete_write_byte(aeteptr, 0); |
||
306 | } else { |
||
307 | tmp = *((char**)aeteptr); |
||
308 | strcpy(tmp, str); |
||
309 | *aeteptr = (void*)((unsigned char*)tmp + strlen(str)); |
||
310 | } |
||
229 | daniel-mar | 311 | } |
312 | #define AETE_WRITE_P2PSTR(s) _aete_write_p2pstr(&aeteptr, (s)); |
||
313 | |||
187 | dmarschall | 314 | void _aete_align_word(void** aeteptr) { |
247 | daniel-mar | 315 | #ifdef MAC_ENV |
316 | unsigned char* tmp = *((unsigned char**)aeteptr); |
||
317 | tmp += (intptr_t)tmp & 1; |
||
318 | *aeteptr = (void*)tmp; |
||
433 | daniel-mar | 319 | #else |
320 | UNREFERENCED_PARAMETER(aeteptr); |
||
247 | daniel-mar | 321 | #endif |
187 | dmarschall | 322 | } |
323 | #define AETE_ALIGN_WORD() _aete_align_word(&aeteptr); |
||
324 | |||
185 | dmarschall | 325 | void* _aete_property(void* aeteptr, PARM_T *pparm, int ctlidx, int mapidx, OSType key) { |
247 | daniel-mar | 326 | char tmp[256]; |
185 | dmarschall | 327 | |
247 | daniel-mar | 328 | if (pparm->ctl_used[ctlidx] || pparm->map_used[mapidx]) { |
329 | if (pparm->map_used[mapidx]) { |
||
330 | if (ctlidx & 1) { |
||
393 | daniel-mar | 331 | sprintf(tmp, "... %s", pparm->szMap[mapidx]); |
247 | daniel-mar | 332 | } else { |
393 | daniel-mar | 333 | sprintf(tmp, "%s ...", pparm->szMap[mapidx]); |
247 | daniel-mar | 334 | } |
335 | AETE_WRITE_C2PSTR(tmp); |
||
336 | } else { |
||
393 | daniel-mar | 337 | AETE_WRITE_C2PSTR(pparm->szCtl[ctlidx]); |
247 | daniel-mar | 338 | } |
339 | AETE_ALIGN_WORD(); |
||
340 | AETE_WRITE_DWORD(key); |
||
341 | AETE_WRITE_DWORD(typeSInt32); |
||
498 | daniel-mar | 342 | AETE_WRITE_C2PSTR(""); |
247 | daniel-mar | 343 | AETE_ALIGN_WORD(); |
344 | AETE_WRITE_WORD(0x8000); /* FLAGS_1_OPT_PARAM / flagsOptionalSingleParameter */ |
||
345 | } |
||
185 | dmarschall | 346 | |
247 | daniel-mar | 347 | return aeteptr; |
185 | dmarschall | 348 | } |
349 | |||
208 | daniel-mar | 350 | size_t aete_generate(void* aeteptr, PARM_T *pparm, long event_id) { |
247 | daniel-mar | 351 | int numprops; |
352 | void *beginptr = aeteptr; |
||
228 | daniel-mar | 353 | |
247 | daniel-mar | 354 | // Attention! |
355 | // - On some systems (e.g. ARM based CPUs) this will cause an unaligned memory access exception. |
||
356 | // For X86, memory access just becomes slower. |
||
346 | daniel-mar | 357 | // - If you change something here, please also change it in scripting.rc (Windows) and scripting.r (Mac OS) |
184 | dmarschall | 358 | |
247 | daniel-mar | 359 | // Note: |
360 | // - The 'aete' resource for Mac OS has word alignments after strings (but not if the next element is also a string) |
||
361 | // see https://developer.apple.com/library/archive/documentation/mac/pdf/Interapplication_Communication/AE_Term_Resources.pdf page 8-9 |
||
184 | dmarschall | 362 | |
268 | daniel-mar | 363 | #ifdef WIN_ENV |
247 | daniel-mar | 364 | AETE_WRITE_WORD(0x0001); /* Reserved (for Photoshop) */ |
268 | daniel-mar | 365 | #endif |
366 | |||
247 | daniel-mar | 367 | AETE_WRITE_BYTE(0x01); /* aete version */ |
368 | AETE_WRITE_BYTE(0x00); /* aete version */ |
||
369 | AETE_WRITE_WORD(english); /* language specifiers */ |
||
370 | AETE_WRITE_WORD(roman); |
||
371 | AETE_WRITE_WORD(1); /* 1 suite */ |
||
372 | { |
||
393 | daniel-mar | 373 | AETE_WRITE_C2PSTR(pparm->szAuthor); /* vendor suite name */ |
498 | daniel-mar | 374 | AETE_WRITE_C2PSTR(""); /* optional description */ |
247 | daniel-mar | 375 | AETE_ALIGN_WORD(); |
376 | AETE_WRITE_DWORD(plugInSuiteID); /* suite ID */ |
||
377 | AETE_WRITE_WORD(1); /* suite code, must be 1. Attention: Filters like 'Pointillize' have set this to 0! */ |
||
378 | AETE_WRITE_WORD(1); /* suite level, must be 1. Attention: Filters like 'Pointillize' have set this to 0! */ |
||
379 | AETE_WRITE_WORD(1); /* 1 event (structure for filters) */ |
||
380 | { |
||
393 | daniel-mar | 381 | AETE_WRITE_C2PSTR(pparm->szTitle); /* event name */ |
498 | daniel-mar | 382 | AETE_WRITE_C2PSTR(""); /* event description */ |
247 | daniel-mar | 383 | AETE_ALIGN_WORD(); |
384 | AETE_WRITE_DWORD(plugInClassID); /* event class */ |
||
385 | AETE_WRITE_DWORD(/*plugInEventID*/event_id); /* event ID */ |
||
386 | /* NO_REPLY: */ |
||
387 | AETE_WRITE_DWORD(noReply); /* noReply='null' */ |
||
498 | daniel-mar | 388 | AETE_WRITE_C2PSTR(""); /* reply description */ |
247 | daniel-mar | 389 | AETE_ALIGN_WORD(); |
390 | AETE_WRITE_WORD(0); |
||
391 | /* IMAGE_DIRECT_PARAM: */ |
||
392 | AETE_WRITE_DWORD(typeImageReference); /* typeImageReference='#ImR' */ |
||
498 | daniel-mar | 393 | AETE_WRITE_C2PSTR(""); /* direct parm description */ |
247 | daniel-mar | 394 | AETE_ALIGN_WORD(); |
395 | AETE_WRITE_WORD(0xB000); |
||
184 | dmarschall | 396 | |
247 | daniel-mar | 397 | numprops = 0; |
398 | if (pparm->ctl_used[0] || pparm->map_used[0]) numprops++; |
||
399 | if (pparm->ctl_used[1] || pparm->map_used[0]) numprops++; |
||
400 | if (pparm->ctl_used[2] || pparm->map_used[1]) numprops++; |
||
401 | if (pparm->ctl_used[3] || pparm->map_used[1]) numprops++; |
||
402 | if (pparm->ctl_used[4] || pparm->map_used[2]) numprops++; |
||
403 | if (pparm->ctl_used[5] || pparm->map_used[2]) numprops++; |
||
404 | if (pparm->ctl_used[6] || pparm->map_used[3]) numprops++; |
||
405 | if (pparm->ctl_used[7] || pparm->map_used[3]) numprops++; |
||
406 | AETE_WRITE_WORD(numprops); |
||
407 | { |
||
408 | // Standalone filters don't need RGBA expressions |
||
409 | /* |
||
498 | daniel-mar | 410 | AETE_WRITE_C2PSTR("R"); |
247 | daniel-mar | 411 | AETE_ALIGN_WORD(); |
412 | AETE_WRITE_DWORD(PARAM_R_KEY); |
||
413 | AETE_WRITE_DWORD(typeText); |
||
498 | daniel-mar | 414 | AETE_WRITE_C2PSTR("R channel expression"); |
247 | daniel-mar | 415 | AETE_ALIGN_WORD(); |
416 | AETE_WRITE_WORD(0x8000); |
||
184 | dmarschall | 417 | |
498 | daniel-mar | 418 | AETE_WRITE_C2PSTR("G"); |
247 | daniel-mar | 419 | AETE_ALIGN_WORD(); |
420 | AETE_WRITE_DWORD(PARAM_G_KEY); |
||
421 | AETE_WRITE_DWORD(typeText); |
||
498 | daniel-mar | 422 | AETE_WRITE_C2PSTR("G channel expression"); |
247 | daniel-mar | 423 | AETE_ALIGN_WORD(); |
424 | AETE_WRITE_WORD(0x8000); |
||
184 | dmarschall | 425 | |
498 | daniel-mar | 426 | AETE_WRITE_C2PSTR("B"); |
247 | daniel-mar | 427 | AETE_ALIGN_WORD(); |
428 | AETE_WRITE_DWORD(PARAM_B_KEY); |
||
429 | AETE_WRITE_DWORD(typeText); |
||
498 | daniel-mar | 430 | AETE_WRITE_C2PSTR("B channel expression"); |
247 | daniel-mar | 431 | AETE_ALIGN_WORD(); |
432 | AETE_WRITE_WORD(0x8000); |
||
184 | dmarschall | 433 | |
498 | daniel-mar | 434 | AETE_WRITE_C2PSTR("A"); |
247 | daniel-mar | 435 | AETE_ALIGN_WORD(); |
436 | AETE_WRITE_DWORD(PARAM_A_KEY); |
||
437 | AETE_WRITE_DWORD(typeText); |
||
498 | daniel-mar | 438 | AETE_WRITE_C2PSTR("A channel expression"); |
247 | daniel-mar | 439 | AETE_ALIGN_WORD(); |
440 | AETE_WRITE_WORD(0x8000); |
||
441 | */ |
||
184 | dmarschall | 442 | |
247 | daniel-mar | 443 | aeteptr = _aete_property(aeteptr, pparm, 0, 0, getAeteKey('0', pparm)); |
444 | aeteptr = _aete_property(aeteptr, pparm, 1, 0, getAeteKey('1', pparm)); |
||
445 | aeteptr = _aete_property(aeteptr, pparm, 2, 1, getAeteKey('2', pparm)); |
||
446 | aeteptr = _aete_property(aeteptr, pparm, 3, 1, getAeteKey('3', pparm)); |
||
447 | aeteptr = _aete_property(aeteptr, pparm, 4, 2, getAeteKey('4', pparm)); |
||
448 | aeteptr = _aete_property(aeteptr, pparm, 5, 2, getAeteKey('5', pparm)); |
||
449 | aeteptr = _aete_property(aeteptr, pparm, 6, 3, getAeteKey('6', pparm)); |
||
450 | aeteptr = _aete_property(aeteptr, pparm, 7, 3, getAeteKey('7', pparm)); |
||
451 | } |
||
452 | } |
||
184 | dmarschall | 453 | |
247 | daniel-mar | 454 | /* non-filter plug-in class here */ |
455 | AETE_WRITE_WORD(0); /* 0 classes */ |
||
456 | {} |
||
457 | AETE_WRITE_WORD(0); /* 0 comparison ops (not supported) */ |
||
458 | {} |
||
459 | AETE_WRITE_WORD(0); /* 0 enumerations */ |
||
460 | {} |
||
461 | } |
||
462 | AETE_WRITE_DWORD(0); /* padding (FIXME: do we need that? Adobe's Windows filters don't) */ |
||
184 | dmarschall | 463 | |
247 | daniel-mar | 464 | return (unsigned char*)aeteptr - (unsigned char*)beginptr; // length of stuff written |
184 | dmarschall | 465 | } |