/* This file is part of "life", a Filter plugin for Adobe Photoshop Copyright (C) 2003-6 Toby Thain, toby@telegraphics.com.au 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 the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Photoshop filter implementing Conway's Life cellular automaton. */ #include "world.h" #include "PIFilter.h" #ifdef __SC__ #include #define malloc NewPtr #define free DisposePtr // we need to avoid global data in the 68K build. // so, all global references are indirected via the "data" parameter // that Photoshop maintains for the plugin, and passes to it. #define FAKEGLOBALS #define G(F) ((struct globals*)*data)->F #else #define G #endif #include "entry.h" #include "ui.h" #ifdef FAKEGLOBALS struct globals{ #endif int toprow,chunkrows; #ifdef FAKEGLOBALS }; #endif DLLEXPORT MACPASCAL void ENTRYPOINT(short selector,FilterRecordPtr epb,long *data,short *result); void DoPrepare (FilterRecordPtr epb,long *data); void DoStart (FilterRecordPtr epb,long *data); OSErr process(FilterRecordPtr pb); OSErr DoContinue (FilterRecordPtr epb,long *data); void DoFinish (FilterRecordPtr epb,long *data); void RequestNext (FilterRecordPtr epb,long*data); OSErr process(FilterRecordPtr pb); DLLEXPORT MACPASCAL void ENTRYPOINT(short selector,FilterRecordPtr pb,long *data,short *result){ OSErr e = noErr; #ifdef FAKEGLOBALS // allocate block for the globals struct // this is never freed, but re-used for future plugin invocations if( !*data && !( *data = (long)malloc(sizeof(struct globals)) ) ) e = memFullErr; else #endif switch (selector){ case filterSelectorAbout: DoAbout((AboutRecordPtr)pb); break; case filterSelectorParameters: break; case filterSelectorPrepare: DoPrepare(pb,data); break; case filterSelectorStart: DoStart(pb,data); break; case filterSelectorContinue: e = DoContinue(pb,data); break; case filterSelectorFinish: DoFinish(pb,data); break; default: e = filterBadParameters; } *result = e; } void DoPrepare(FilterRecordPtr pb,long *data){ G(chunkrows) = (pb->maxSpace/4) / ((pb->planes*pb->depth*(long)pb->imageSize.h + 7)/8); if(G(chunkrows) > (pb->filterRect.bottom - pb->filterRect.top)) G(chunkrows) = pb->filterRect.bottom - pb->filterRect.top; } void RequestNext(FilterRecordPtr pb,long *data){ /* Request next block of the image */ pb->inLoPlane = pb->outLoPlane = 0; pb->inHiPlane = pb->outHiPlane = pb->planes-1; pb->inRect.left = pb->outRect.left = pb->filterRect.left; pb->inRect.right = pb->outRect.right = pb->filterRect.right; pb->inRect.top = pb->outRect.top = G(toprow); pb->inRect.bottom = G(toprow) + G(chunkrows); if(pb->inRect.bottom > pb->filterRect.bottom) pb->inRect.bottom = pb->filterRect.bottom; pb->outRect.bottom = pb->inRect.bottom; // SPRINTF(s,"RequestNext inRect = %d,%d,%d,%d",pb->inRect.left,pb->inRect.top,pb->inRect.right,pb->inRect.bottom); dbg(s); } void DoStart (FilterRecordPtr pb,long *data){ G(toprow) = pb->filterRect.top; RequestNext(pb,data); } OSErr DoContinue (FilterRecordPtr pb,long *data){ OSErr e = process(pb); G(toprow) += G(chunkrows); if(G(toprow) < pb->filterRect.bottom) RequestNext(pb,data); else{ pb->inRect.left = pb->inRect.right = pb->inRect.top = pb->inRect.bottom = 0 ; pb->outRect = pb->maskRect = pb->inRect; } return e; } void DoFinish(FilterRecordPtr pb,long *data){ }