Subversion Repositories filter_foundry

Rev

Rev 18 | Rev 48 | 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
2 toby 3
    Copyright (C) 2003-5 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 <stddef.h>
21
 
22
#include "ff.h"
23
#include "symtab.h"
24
 
25
#include "PIActions.h"
26
 
27
#include "compat_string.h"
28
 
29
long event_id;
30
 
31
/*
32
Find a printable 4-character key, remembering (see PS API guide):
33
All IDŐs starting with an uppercase letter are reserved by Adobe.
34
All IDŐs that are all uppercase are reserved by Apple.
35
All IDŐs that are all lowercase are reserved by Apple.
36
This leaves all IDŐs that begin with a lowercase letter and have at least
37
one uppercase letter for you and other plug-in developers.
38
*/
39
unsigned long printablehash(unsigned long hash){
40
        unsigned long key = 'a' + (hash % 26); hash /= 26; // first lower case
41
        key <<= 8;   key |= ' ' + (hash % 95); hash /= 95; // second and third any printable
42
        key <<= 8;   key |= ' ' + (hash % 95); hash /= 95;
43
        return  (key<<8) | ('A' + (hash % 26));                    // last upper case
44
}
45
 
46
/* original version with any four printables
47
unsigned long printablehash(unsigned long hash){
48
        unsigned long key;
49
        int i;
50
 
51
        for(key=0,i=4;i--;){
52
                key <<= 8;
53
                key |= ' ' + (hash % 95); // get a printable character from hash
54
                hash /= 95;
55
        }
56
        return key;
57
}
58
*/
59
 
60
long fixpipl(PIPropertyList *pipl,long origsize,StringPtr title){
61
        PIProperty *prop;
23 toby 62
        char *p;
2 toby 63
        struct hstm_data{
64
                /* this structure must be 14+1 bytes long, to match PiPL structure */
65
                long version; /* = 0 */
66
                long class_id;
67
                long event_id;
68
                short aete_resid;
69
                char scope[1];
70
        };
71
        struct hstm_data *hstm;
72
        int scopelen;
73
        unsigned long hash;
74
 
75
        pipl->count += 3; // more keys in PiPL
76
 
23 toby 77
        p = (char*)pipl + origsize;
78
        prop = (PIProperty*)p;
2 toby 79
 
80
        /* add Title/Name property key */
81
 
82
        prop->vendorID = kPhotoshopSignature;
83
        prop->propertyKey = PINameProperty;
84
        prop->propertyID = 0;
85
        prop->propertyLength = title[0]+1;
86
        PLstrcpy((StringPtr)prop->propertyData,title);
87
 
23 toby 88
        // skip past new property record, and any padding
89
        p += (offsetof(PIProperty,propertyData) + prop->propertyLength + 3) & -4;
90
        prop = (PIProperty*)p;
91
 
2 toby 92
        /* add Category property key */
93
 
94
        prop->vendorID = kPhotoshopSignature;
95
        prop->propertyKey = PICategoryProperty;
96
        prop->propertyID = 0;
97
        prop->propertyLength = gdata->parm.category[0]+1;
98
        PLstrcpy((StringPtr)prop->propertyData,gdata->parm.category);
23 toby 99
 
100
        p += (offsetof(PIProperty,propertyData) + prop->propertyLength + 3) & -4;
101
        prop = (PIProperty*)p;
2 toby 102
 
103
        /* add HasTerminology property key */  
104
 
105
        /* construct scope string by concatenating Category and Title - hopefully unique! */
106
        hstm = (struct hstm_data*)prop->propertyData;
107
        scopelen = sprintf(hstm->scope,"%s %s",
108
                                           INPLACEP2CSTR(gdata->parm.category),
109
                                           INPLACEP2CSTR(title));
110
 
111
        /* make up a new event ID for this aete, based on printable base-95 hash of scope */
112
        hash = djb2(hstm->scope);
113
        event_id = printablehash(hash); /* this is used by fix_aete later... */
114
 
115
        prop->vendorID = kPhotoshopSignature;
116
        prop->propertyKey = PIHasTerminologyProperty;
117
        prop->propertyID = 0;
118
        prop->propertyLength = offsetof(struct hstm_data,scope) + scopelen + 1;
119
        hstm->version = 0;
120
        hstm->class_id = plugInClassID;
121
        hstm->event_id = event_id;
122
        hstm->aete_resid = AETE_ID;
123
 
23 toby 124
        p += (16+prop->propertyLength+3) & -4;
2 toby 125
 
23 toby 126
        return p - (char*)pipl;  // figure how many bytes were added
2 toby 127
}
128
 
129
/* Mac aete resources include word alignments after string pairs; Windows ones apparently don't */
130
#ifdef MAC_ENV
131
        #define ALIGNWORD(j) (j += j & 1)
132
#else
133
        #define ALIGNWORD(j)
134
#endif
135
#define SKIP_PSTR(j) (j += 1+aete[j])
136
 
137
long fixaete(unsigned char *aete,long origsize,StringPtr title){
138
        int offset,oldlen,newlen,desclen,oldpad,newpad;
139
        Str255 desc;
140
 
141
        offset = 8; /* point at suite name */
142
 
143
        SKIP_PSTR(offset); /* skip suite name (vendor) [maybe this should become author??] */
144
        SKIP_PSTR(offset); /* skip suite description [set this from dialog field??] */
145
        ALIGNWORD(offset);
146
        offset += 4+2+2+2; /* offset now points to filter name. */
147
 
148
        oldlen = aete[offset];
149
        newlen = title[0];
150
 
151
        /* shift aete data taking into account new title string */
152
        desclen = aete[offset+1+oldlen];
153
        PLstrcpy(desc,(StringPtr)(aete+offset+1+oldlen));  /* save description string... */
154
#ifdef MAC_ENV
155
        /* see if alignment padding is necessary */
156
        oldpad = (oldlen + desclen) & 1;
157
        newpad = (newlen + desclen) & 1;
158
#else
159
        oldpad = newpad = 0;
160
#endif
161
        /* shift latter part of aete data, taking into account new string lengths */
162
        memcpy(aete+offset+1+newlen+newpad,
163
                         aete+offset+1+oldlen+oldpad,
164
                         origsize-offset-1-oldlen-oldpad); /* phew! */
165
        /* copy in new title string */
166
        PLstrcpy((StringPtr)(aete+offset),title);
167
        /* copy description string into right place... [this could be new description from dialog field??] */
168
        PLstrcpy((StringPtr)(aete+offset+1+newlen),desc);
169
 
170
        SKIP_PSTR(offset); /* skip (new) event name */
171
        SKIP_PSTR(offset); /* skip event description */
172
        ALIGNWORD(offset);
173
 
174
        /* set event ID */
175
        *(unsigned long*)(aete+offset+4) = event_id; /* FIXME: this might be unaligned access on some platforms?? */
176
 
177
        return origsize-oldlen-oldpad+newlen+newpad;
178
}