Subversion Repositories filter_foundry

Rev

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