1,7 → 1,7 |
/* |
This file is part of "Filter Foundry", a filter plugin for Adobe Photoshop |
Copyright (C) 2003-2009 Toby Thain, toby@telegraphics.net |
Copyright (C) 2018-2022 Daniel Marschall, ViaThinkSoft |
Copyright (C) 2018-2023 Daniel Marschall, ViaThinkSoft |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
42,8 → 42,6 |
struct node *tree[4]; |
TCHAR *err[4]; |
int errpos[4],errstart[4],nplanes,cnvused,chunksize,toprow; |
uint8_t slider[8]; // this is the "working data". We cannot always use gdata->parm, because parm will not be loaded if a AFS file is read |
char* expr[4]; // this is the "working data". We cannot always use gdata->parm, because parm will not be loaded if a AFS file is read |
value_type cell[NUM_CELLS]; |
|
// this is the only memory area that keeps preserved by Photoshop: |
68,7 → 66,7 |
DLLEXPORT MACPASCAL |
void ENTRYPOINT(short selector,FilterRecordPtr pb,intptr_t *data,short *result); |
|
unsigned long get_parm_hash(PARM_T *parm) { |
unsigned long parm_hash(PARM_T *parm) { |
unsigned long hash; |
int i; |
|
103,7 → 101,7 |
if (xstrlen(out) > 0) xstrcat(out, TEXT("/")); |
#endif |
|
hash = (isStandalone) ? get_parm_hash(parm) : 0; |
hash = (isStandalone) ? parm_hash(parm) : 0; |
|
// sprintf(outfilename, "%sFilterFoundry%d.afs", atempdir, hash); |
xstrcat(out, TEXT("FilterFoundry")); |
314,7 → 312,6 |
|
if (selector != filterSelectorAbout && !*data) { |
// The filter was never called before. We allocate (zeroed) memory now. |
// Note: gdata->standalone and gdata->parmloaded will be set later |
CreateDataPointer(data); |
if (!*data) { |
*result = memFullErr; |
329,13 → 326,16 |
switch (selector){ |
case filterSelectorAbout: |
if (!gdata) { |
Boolean parmReadOk; |
// This is a temporary gdata structure just for the About dialog! |
// Not to be confused with the "real" gdata during the filter invocation (containing more data). |
gdata = (globals_t*)malloc(sizeof(globals_t)); |
if (!gdata) break; |
gdata->hWndMainDlg = (HWND)((PlatformData*)((AboutRecordPtr)pb)->platformData)->hwnd; // so that simplealert() works |
gdata->standalone = gdata->parmloaded = readPARMresource((HMODULE)hDllInstance, NULL); |
if (gdata->parmloaded && (gdata->parm.cbSize != PARM_SIZE) && (gdata->parm.cbSize != PARM_SIZE_PREMIERE) && (gdata->parm.cbSize != PARM_SIG_MAC)) { |
parmReadOk = readPARMresource((HMODULE)hDllInstance, NULL); |
if (!parmReadOk) gdata->parm.standalone = false; |
if (parmReadOk && (gdata->parm.cbSize != PARM_SIZE) && (gdata->parm.cbSize != PARM_SIZE_PREMIERE) && (gdata->parm.cbSize != PARM_SIG_MAC)) { |
parm_reset(true, true, true, true); |
if (gdata->obfusc) { |
simplealert_id(MSG_INCOMPATIBLE_OBFUSCATION_ID); |
} |
381,7 → 381,7 |
wantdialog |= checkandinitparams(pb->parameters); |
|
/* wantdialog = false means that we never got a Parameters call, so we're not supposed to ask user */ |
if (wantdialog && (!gdata->standalone || gdata->parm.popDialog)) { |
if (wantdialog && (!gdata->parm.standalone || gdata->parm.popDialog)) { |
if (maindialog(pb)) { |
if (!host_preserves_parameters()) { |
/* Workaround for GIMP/PSPI, to avoid that formulas vanish when you re-open the main window. |
393,14 → 393,13 |
// Workaround: Save settings in "FilterFoundryXX.afs" if the host does not preserve pb->parameters |
TCHAR outfilename[MAX_PATH + 1]; |
StandardFileReply sfr; |
char* bakexpr[4]; |
int i; |
InternalState tmpState; |
|
sfr.sfGood = true; |
sfr.sfReplacing = true; |
sfr.sfType = PS_FILTER_FILETYPE; |
|
get_temp_afs(&outfilename[0], gdata->standalone, &gdata->parm); |
get_temp_afs(&outfilename[0], gdata->parm.standalone, &gdata->parm); |
|
xstrcpy(sfr.sfFile.szName, outfilename); |
#ifdef WIN_ENV |
410,26 → 409,18 |
|
// We only want the parameters (ctl,map) in the temporary .afs file |
// It is important to remove the expressions, otherwise they would be |
// revealed in the temporary files. |
for (i = 0; i < 4; i++) { |
bakexpr[i] = expr[i]; // moved out of the if-definition to make the compiler happy |
// revealed in the temporary files (That might be bad for obfuscated filters). |
if (gdata->parm.standalone) { |
tmpState = saveInternalState(); |
parm_reset(false, false, false, true); |
} |
if (gdata->standalone) { |
expr[0] = _strdup("r"); |
expr[1] = _strdup("g"); |
expr[2] = _strdup("b"); |
expr[3] = _strdup("a"); |
} |
|
savefile_afs_pff_picotxt_guf(&sfr); |
|
if (gdata->standalone) { |
for (i = 0; i < 4; i++) { |
if (expr[i]) free(expr[i]); |
expr[i] = bakexpr[i]; |
if (gdata->parm.standalone) { |
restoreInternalState(tmpState); |
} |
} |
} |
else { |
/* update stored parameters from new user settings */ |
if (pb->parameters) |
471,27 → 462,114 |
ExitCodeResource(); |
} |
|
void parm_reset(Boolean resetMetadata, Boolean resetSliderValues, Boolean resetSliderNames, Boolean resetFormulas) { |
gdata->parm.cbSize = PARM_SIZE; |
if (resetMetadata) { |
strcpy(gdata->parm.szCategory, "Filter Foundry"); |
strcpy(gdata->parm.szTitle, "Untitled"); |
strcpy(gdata->parm.szCopyright, ""); //"Filter Foundry Copyright (C) 2003-2009 Toby Thain, 2018-" RELEASE_YEAR " Daniel Marschall" |
strcpy(gdata->parm.szAuthor, "Anonymous"); |
} |
if (resetSliderValues) { |
int i; |
for (i = 0; i < 8; ++i) { |
gdata->parm.val[i] = (uint8_t)(i * 10 + 100); |
} |
} |
if (resetSliderNames) { |
int i; |
for (i = 0; i < 8; ++i) { |
strcpy(gdata->parm.szCtl[i], "ctl(X)"); |
gdata->parm.szCtl[i][4] = '0' + i; |
} |
for (i = 0; i < 4; ++i) { |
strcpy(gdata->parm.szMap[i], "Map X"); |
gdata->parm.szMap[i][4] = '0' + i; |
} |
} |
if (resetFormulas) { |
if (gpb->imageMode == plugInModeRGBColor) { |
strcpy(gdata->parm.szFormula[0], "r"); |
strcpy(gdata->parm.szFormula[1], "g"); |
strcpy(gdata->parm.szFormula[2], "b"); |
strcpy(gdata->parm.szFormula[3], "a"); |
} |
else { |
strcpy(gdata->parm.szFormula[0], "c"); |
strcpy(gdata->parm.szFormula[1], "c"); |
strcpy(gdata->parm.szFormula[2], "c"); |
strcpy(gdata->parm.szFormula[3], "c"); |
} |
} |
} |
|
void parm_cleanup() { |
// Cleanup "PARM" resource by removing stuff after the null terminators, to avoid that parts of confidential formulas are leaked |
int i; |
|
{ |
char tmp[256]; |
|
strcpy(tmp, gdata->parm.szCategory); |
memset(gdata->parm.szCategory, 0, sizeof(gdata->parm.szCategory)); |
strcpy(gdata->parm.szCategory, tmp); |
|
strcpy(tmp, gdata->parm.szTitle); |
memset(gdata->parm.szTitle, 0, sizeof(gdata->parm.szTitle)); |
strcpy(gdata->parm.szTitle, tmp); |
|
strcpy(tmp, gdata->parm.szCopyright); |
memset(gdata->parm.szCopyright, 0, sizeof(gdata->parm.szCopyright)); |
strcpy(gdata->parm.szCopyright, tmp); |
|
strcpy(tmp, gdata->parm.szAuthor); |
memset(gdata->parm.szAuthor, 0, sizeof(gdata->parm.szAuthor)); |
strcpy(gdata->parm.szAuthor, tmp); |
} |
|
for (i = 0; i < 4; i++) { |
char tmp[256]; |
strcpy(tmp, gdata->parm.szMap[i]); |
memset(gdata->parm.szMap[i], 0, sizeof(gdata->parm.szMap[i])); |
strcpy(gdata->parm.szMap[i], tmp); |
} |
|
for (i = 0; i < 8; i++) { |
char tmp[256]; |
strcpy(tmp, gdata->parm.szCtl[i]); |
memset(gdata->parm.szCtl[i], 0, sizeof(gdata->parm.szCtl[i])); |
strcpy(gdata->parm.szCtl[i], tmp); |
} |
|
for (i = 0; i < 4; i++) { |
char tmp[1024]; |
strcpy(tmp, gdata->parm.szFormula[i]); |
memset(gdata->parm.szFormula[i], 0, sizeof(gdata->parm.szFormula[i])); |
strcpy(gdata->parm.szFormula[i], tmp); |
} |
} |
|
int checkandinitparams(Handle params){ |
int i; |
Boolean bUninitializedParams; |
Boolean showdialog; |
InternalState tmpState; |
|
if (!host_preserves_parameters()) { |
// Workaround: Load settings in "FilterFoundryXX.afs" if host does not preserve pb->parameters |
TCHAR outfilename[MAX_PATH + 1]; |
Boolean isStandalone; |
Boolean parmReadOk; |
StandardFileReply sfr; |
char* bakexpr[4]; |
char bakexpr[4][MAXEXPR]; |
|
sfr.sfGood = true; |
sfr.sfReplacing = true; |
sfr.sfType = PS_FILTER_FILETYPE; |
|
// We need to set gdata->standalone after loadfile(), but we must call readPARMresource() before loadfile() |
// Reason: readPARMresource() reads parameters from the DLL while loadfile() reads parameters from the AFS file |
// But loadfile() will reset gdata->standalone ... |
isStandalone = readPARMresource((HMODULE)hDllInstance, NULL); |
if (isStandalone && (gdata->parm.cbSize != PARM_SIZE) && (gdata->parm.cbSize != PARM_SIZE_PREMIERE) && (gdata->parm.cbSize != PARM_SIG_MAC)) { |
parmReadOk = readPARMresource((HMODULE)hDllInstance, NULL); |
if (!parmReadOk) gdata->parm.standalone = false; |
if (parmReadOk && (gdata->parm.cbSize != PARM_SIZE) && (gdata->parm.cbSize != PARM_SIZE_PREMIERE) && (gdata->parm.cbSize != PARM_SIG_MAC)) { |
parm_reset(true, true, true, true); |
if (gdata->obfusc) { |
simplealert_id(MSG_INCOMPATIBLE_OBFUSCATION_ID); |
} |
498,11 → 576,10 |
else { |
simplealert_id(MSG_INVALID_PARAMETER_DATA_ID); |
} |
gdata->parmloaded = false; |
return false; |
} |
|
get_temp_afs(&outfilename[0], isStandalone, &gdata->parm); |
get_temp_afs(&outfilename[0], parmReadOk, &gdata->parm); |
|
xstrcpy(sfr.sfFile.szName, outfilename); |
#ifdef WIN_ENV |
510,22 → 587,22 |
#endif |
sfr.sfScript = smSystemScript; |
|
// We only want the parameters (ctl,map) in the temporary .afs file |
if (isStandalone) { |
for (i = 0; i < 4; i++) { |
bakexpr[i] = my_strdup(expr[i]); |
if (parmReadOk) { |
tmpState = saveInternalState(); |
} |
} |
|
if (loadfile(&sfr, NULL)) { |
gdata->standalone = gdata->parmloaded = isStandalone; |
|
if (isStandalone) { |
if (parmReadOk) { |
// In the standalone filter, we only want the parameters (ctl,map) in the temporary .afs file, not the formulas |
// We do not need to care about the metadata, because the AFS does not touch the metadata anyway |
for (i = 0; i < 4; i++) { |
if (expr[i]) free(expr[i]); |
expr[i] = bakexpr[i]; |
strcpy(bakexpr[i], gdata->parm.szFormula[i]); |
} |
restoreInternalState(tmpState); |
for (i = 0; i < 4; i++) { |
strcpy(gdata->parm.szFormula[i],bakexpr[i]); |
} |
} |
|
return true; |
} |
535,9 → 612,13 |
/* either the parameter handle was uninitialised, |
or the parameter data couldn't be read; set default values */ |
|
Boolean parmReadOk; |
|
// see if saved parameters exist |
gdata->standalone = gdata->parmloaded = readPARMresource((HMODULE)hDllInstance, NULL); |
if (gdata->parmloaded && (gdata->parm.cbSize != PARM_SIZE) && (gdata->parm.cbSize != PARM_SIZE_PREMIERE) && (gdata->parm.cbSize != PARM_SIG_MAC)) { |
parmReadOk = readPARMresource((HMODULE)hDllInstance, NULL); |
if (!parmReadOk) gdata->parm.standalone = false; |
if (parmReadOk && (gdata->parm.cbSize != PARM_SIZE) && (gdata->parm.cbSize != PARM_SIZE_PREMIERE) && (gdata->parm.cbSize != PARM_SIG_MAC)) { |
parm_reset(true, true, true, true); |
if (gdata->obfusc) { |
simplealert_id(MSG_INCOMPATIBLE_OBFUSCATION_ID); |
} |
544,30 → 625,14 |
else { |
simplealert_id(MSG_INVALID_PARAMETER_DATA_ID); |
} |
gdata->parmloaded = false; |
return false; |
} |
|
if(!gdata->standalone){ |
if(!gdata->parm.standalone){ |
// no saved settings (not standalone) |
for(i = 0; i < 8; ++i) |
slider[i] = (uint8_t)(i*10+100); |
for(i = 0; i < 4; ++i) |
if(expr[i]) |
free(expr[i]); |
if(gpb->imageMode == plugInModeRGBColor){ |
expr[0] = _strdup("r"); |
expr[1] = _strdup("g"); |
expr[2] = _strdup("b"); |
expr[3] = _strdup("a"); |
}else{ |
expr[0] = _strdup("c"); |
expr[1] = _strdup("c"); |
expr[2] = _strdup("c"); |
expr[3] = _strdup("c"); |
parm_reset(true, true, true, true); |
} |
} |
} |
|
// let scripting system change parameters, if we're scripted; |
// user may want to force display of dialog during scripting playback |
639,7 → 704,6 |
int i; |
|
for(i = 4; i--;){ |
expr[i] = NULL; |
tree[i] = NULL; |
err[i] = NULL; |
} |
838,35 → 902,18 |
|
for(i = 4; i--;){ |
freetree(tree[i]); |
if(expr[i]) free(expr[i]); |
} |
} |
|
InternalState saveInternalState(void) { |
InternalState ret; |
int i; |
|
ret.bak_obfusc = gdata->obfusc; |
ret.bak_standalone = gdata->standalone; |
ret.bak_parmloaded = gdata->parmloaded; |
memcpy(&ret.bak_parm, &gdata->parm, sizeof(PARM_T)); |
for (i = 0; i < 4; i++) ret.bak_expr[i] = my_strdup(expr[i]); |
for (i = 0; i < 8; i++) ret.bak_slider[i] = slider[i]; |
|
return ret; |
} |
|
void restoreInternalState(InternalState state) { |
int i; |
gdata->obfusc = state.bak_obfusc; |
gdata->standalone = state.bak_standalone; |
gdata->parmloaded = state.bak_parmloaded; |
memcpy(&gdata->parm, &state.bak_parm, sizeof(PARM_T)); |
for (i = 0; i < 4; i++) { |
if (expr[i]) free(expr[i]); |
expr[i] = state.bak_expr[i]; |
} |
for (i = 0; i < 8; i++) { |
slider[i] = state.bak_slider[i]; |
} |
} |