Creating plug-in modules for the Mac OS

Sections on this Page

Photoshop plug-in modules for the Macintosh can be created using any of the popular C compilers including Apple MPW, Symantec C++, or Metrowerks CodeWarrior. The example plug-ins in this toolkit include both MPW makefiles and CodeWarrior project files.

You can create plug-in modules for 680x0, PowerPC, or both (fat binaries). If your plug-in module uses floating point arithmetic, you can create plug-in code that is optimized for Macintosh systems with floating-point units (FPU). If you desire, you can also provide a version of your code that does not require an FPU, and Photoshop will execute the proper version depending on whether an FPU is present.

Plug-in modules use code resources on 680x0 Macs and shared libraries (the code fragment manager) on PowerPC systems.

When the user performs an action that causes a plug-in module to be called, Photoshop opens the resource fork of the file the module resides in, loads the code resource (68k) or shared library (PowerPC) into memory. On 680x0 systems, the entry point is assumed as the first byte of the resource.

Hardware and system software configuration

Adobe Photoshop plug-ins assume that the Macintosh has 128K or larger ROMs, System 6.0.2 or later. Photoshop 3.0 and later requires System 7.

Photoshop 5.0 and later are PPC only.

Many users still work with older versions of Photoshop. If you choose to support versions of Photoshop prior to 3.0, your plug-in may be called from machines as old as the Mac Plus. You should use the Gestalt routines to check for 68020 or 68030 processors, math co-processors, 256K ROMs, and Color or 32-Bit QuickDraw if they are required.

If your plug-in only runs with Photoshop 3.0, you can assume the features are present that are requirements of Photoshop 3.0: a 68020 or better, Color QuickDraw, and 32-Bit QuickDraw.

Resources in a plug-in module

Besides 680x0 code resources, a plug-in module may include a variety of resources for the plug-in’s user interface, stored preferences, and any other useful resource.

Every plug-in module must include either a complex data structure stored in a PiPL resource or a simpler structure in a PiMI resource. These resources provide information that Adobe Photoshop uses to identify plug-ins when Photoshop is first launched and when a plug-in is executed by the user. All the examples in this toolkit build both resources for downward- and cross-application compatibility.

PiMIs, PiPLs and other resources are discussed in detail in the Cross Application Plug-in Development Resource Guide which is included with this kit. This document discusses cross-application plug-in development and describes the different file and code resources recognized by Photoshop and other host applications.

Global variables

Most Macintosh applications reference global variables as negative offsets from register A5 on 680x0 processors. If a plug-in module declares any global variables, their location would overlap Photoshop’s global variable space. Using them generally results in a quick and spectacular crash.

Often you can end up using them without even realizing it. Explicit literal string assignments, for instance, take up global space when first initialized. One way around this is to store strings in a 'STR ' or 'STR#' resource and access them using the Macintosh toolbox calls GetString() and GetIndString().

CWA4Globals Metrowerks CodeWarrior A4-globals

Code resources can avoid the A5 problem by using the A4 register in place of the A5 register. The Metrowerks CodeWarrior C compiler contains header files (SetupA4.h, A4Stuff.h) and pre–compiled libraries designed for A4 register usage. The examples in this toolkit all initialize and set-up the A4 register, so you can refer to them for more detail.

If you are building a plug-in module to run on 680x0 systems you should not declare any global variables in your plug-in module code unless you specifically use the A4 support provided with your compiler. Refer to your compiler documentation for more details.

Plug-in modules that are compiled native for PowerPC systems do not have this limitation, since they use the code fragment manager (CFM) instead of code resources. If your plug-in module only runs on PowerPC, you may safely declare and use global variables. Refer to the appropriate Apple documentation for more information.

If you need global data in your 680x0 compatible plug-in module, one alternative to using A4 is to dynamically allocate a new block of memory at initialization time using the Photoshop Handle or Buffer suite routines, and return this to Photoshop in the data parameter. Photoshop will save this reference and return it to your plug-in each time it is called subsequently. The example plug-ins in this toolkit all use this approach.

Segmentation

Macintosh 680x0 applications have a special code segment called the jump table. When a routine in one segment calls a routine in another segment, it actually calls a small glue routine in the jump table segment. This glue routine loads the routine’s segment into memory if needed, and jumps to its actual location.

The jump table is accessed using positive offsets from register A5. Since Photoshop is already using A5 for its jump table, the plug-in cannot use a jump table in the standard way.

The simplest way to solve this is to link all the plug-in’s code into a single segment. This usually requires setting optional compilation/link flags in your development environment if the resultant segment exceeds 32k.

Metrowerks CodeWarrior link flags for plug-ins over 32k

For over 32k length plug-ins under Metrowerks CodeWarrior, enable these processor preferences: code model: large; far data; far method tables; and far string constants:

Enable the linker preference link single segment:

Installing plug-in modules

To install a plug-in module, drag the module’s icon to either the same folder as the Adobe Photoshop application, or the plug-ins folder designated in your Photoshop preferences file. Photoshop 3.0 searches for plug-ins in the application folder, and throughout the tree of folders underneath the designated plug-ins folder. Aliases are followed during the search process. Folders with names beginning with "¬" (Option-L on the Macintosh keyboard) are ignored.

Finding the plug-in directory for the Mac OS

To find the plug-in directory on Mac OS in versions of Photoshop before 5.0 you have to search for the application and try to find a folder called Plug-ins.

In Photoshop 5.0 and later, in the System Folder, in the Preferences folder is a file with paths to the application and plug-ins folder.

Photoshop 5 Paths filenames
Application Paths filename
Adobe Photoshop 5.0 Adobe Photoshop 5 Paths
Adobe Photoshop 5.0 Limited Edition Adobe Photoshop LE Paths
Adobe Photoshop 5.0 Tryout/Demo Adobe Photoshop 5 Demo Paths
Note:
The Photoshop 5 Paths file contains two Macintosh FSSPec structures one right after the other. The first is to the application; the second is to the plug-in directory. There is no padding or sentinal characters.
The Photoshop CS3 Paths file contains the information above for Photoshop 5 paths. Following that are two Macintosh UTF8 string paths, one right after the other. The first is to the application; the second is to the plug-in directory.

What’s in this toolkit for the Mac OS?

This toolkit contains documentation, and literature on the Adobe Developers Association, and examples specifically written for the Mac OS.

Examples
The plug-ins included with this toolkit can be built using Apple MPW or Metrowerks CodeWarrior. They have been tested against the latest Metrowerks CodeWarrior. Version notes are in the SDK Readme file.

Sources.cpp and Headers.h
PIGeneral.h and PITypes.h contain definitions useful across multiple plug-ins. PIAbout.h contains the information for the about box call for all plug-in types. PIActions.h contains the information for the Actions suite callbacks for all plug-in types. PIAcquire.h, PIExport.h, PIFilter.h, PIFormat.h, PIPicker.h, and PISelection.h are the header files for the respective types of plug-in modules.

Utilities
DialogUtilities.c and DialogUtilities.h provide general support for doing things with dialogs including creating movable modal dialogs which make appropriate calls back to the host to update windows, as well as simple support for putting data back into the dialog for display, such as StuffNumber() and StuffText().

PIUtilities.c and PIUtilities.h contain various routines and macros to make it easier to use the host callbacks. The macros make assumptions about how global variables are being handled and declared; refer to the example source code to see how PIUtilities is used.

Documentation
Photoshop SDK Guide.pdf is this guide. Cross Application Plug-in Development Resource Guide is a reference tool for developing Photoshop plug-ins that work with all of Adobe’s major graphical applications.

It also includes information on host applications and their use of different code and file resources such as PiMI and PiPL resources. Actions Event Guide.pdf is a reference tool for developing a Photoshop 5.0 automation plug-in.

Developer Services
The Developer Services directory provides information and an application for the Adobe Developers Association, which provides not only support for this and the other Adobe toolkits, but marketing and business resources for third party developers.

Fat and PPC-only plug-ins and the cfrg resource

Adobe Photoshop 4.0 and 5.0 use the PiPL resource (see Plug-in Resource Guide.pdf) to identify the type of processor for which the plug-in module was compiled: 680x0, PowerPC or both. The Macintosh OS uses a different resource, 'cfrg', to indicate the presence of code for the PowerPC microprocessor. The cfrg resource is automatically generated by the Metrowerks CodeWarrior development environment.

Normally, this is not a problem. It could become a problem, however, if you or a user of your plug-in run an application to reduce a fat binary (680x0 and PowerPC) plug-in to 680x0 only. Fat stripper applications search for cfrg resources and when found remove any PowerPC code and the cfrg resource. These applications are not aware of the PiPL resource; the resulting 680x0-only plug-in will still indicate that it contains PowerPC code.

After you create a PowerPC plug-in module, you should manually remove the cfrg resource with a resource editor to prevent someone from accidently deleting the PowerPC code by stripping.

You should always be sure to specify the correct PiPL code descriptors when building a plug-in. All of the plug-ins in the examples folder have PiPL resources with both code descriptors, as follows:

#if Macintosh
    Code68K { '8BIF', $$ID },
    CodePowerPC { 0, 0, "" },
#endif

If your plug-in module includes code only for the 680x0 or only for the PowerPC, remove the other code descriptor before compiling the .r file. For instance, a PowerPC-only plug-in module’s PiPL source file would have these lines in the PiPL descriptor:

#if Macintosh
    CodePowerPC { 0, 0, "" },
#endif

Building your plug-in in older IDE than CodeWarrior Pro
Metrowerks CodeWarrior Pro introduced multiple targets. You can now build 68K and PPC code from within one project.

Building your plug-ins with Metrowerks CodeWarrior in older IDEs is a two-step process. Open and build the 680x0 project to create the .rsrc and 68k code for the plug-in. Then, you must open and build the PowerPC project to create the actual plug-in module and roll the 68k and PPC resources together in the plug-in.

If you do not build the 680x0 project, the initial .rsrc resource file with the appropriate dialog and PiPL resources will not be built. If you do not build the PowerPC project, the actual plug-in file will not be created. To build from one project file (68k-only) see the following information for CodeWarrior Bronze users.

Building 680x0-only plug-ins

The sample CodeWarrior project files in this toolkit are designed for CodeWarrior Gold to create "fat" binaries. If you use CodeWarrior to build 680x0-only plug-in modules, you should make two changes to the sample files.

First, you should change the Project preferences to output a plug-in file with the correct file name, creator, and type. (The 68K project files included in the toolkit output resource files which are then used by the PPC project files, as explained above.)

For example, the 680x0 project in the Filters sample is set to output a code resource named Dissolve.rsrc with creator 'Doug' and type 'RSRC'. You should change these to Dissolve, '8BIM', and '8BFM' respectively.

Second, you should recompile the PiPL resource after removing the PowerPC code descriptor. The PiPL statement:

#if Macintosh
    Code68K { '8BIF', $$ID },
    CodePowerPC { 0, 0, "" },
#endif

should be changed to:

#if Macintosh
    Code68K { '8BIF', $$ID },
#endif

See Plug-in Resource Guide.pdf for more information about PiPL resources.

Debugging code resources in Metrowerks CodeWarrior

  1. Drag the .SYM file out of the development directory where it is linked to the .rsrc file. The desktop is fine.
  2. Double-click the .SYM file to run the Metrowerks Debugger.
  3. When it asks "Where is my resource?" select your plug-in in the Photoshop plug-in folder. Even if your plug-in is an alias, select the one that is in Photoshop’s Plug-ins folder, not the one that may be sitting in your development directory (next to your .rsrc file).
  4. Drag the Photoshop icon on top of the Metrowerks Debugger to link Photoshop to the debugger.
  5. Double-click the Photoshop icon to launch the application.
  6. Set your breakpoints in your .SYM window in the debugger.
  7. Bring the Photoshop debugger window to the front and choose Run.
  8. In Photoshop, run your plug-in. You should hit your break-point and go back to the debugger automatically.
Note:
Your variables may not read their true values correctly as you step through your code. They may be valid only at your breakpoints.