This document has a standard, validated CSS2 stylesheet, which your browser does not seem to display properly. In a browser supporting web standards, this table of contents would be fixed at the side of the page for easy reference.
anastigmatix home
Packager
is a pure PostScript procedure-set resource used
for packaging PostScript resources in the
form described in my earlier
survey of PostScript resource packaging.
It replaces an earlier implementation that required Ghostscript and a
hodge-podge of Unix tools and was never packaged for easy use by others.
Packager
, as a pure PostScript implementation, can be used
anywhere there is a conformant language-level 2 or 3 PostScript interpreter
with a filesystem—even, in a pinch, on a printer with a hard drive.
It has, of course, been used to package itself.
The remainder of this page is a reference for the capabilities provided
by Packager
. For a more conceptual view of what it does and
why you would want to, please see the links above.
A resource that uses Packager
for packaging
is a staged program.
Its source form is a PostScript program that runs, at
“packaging time”, imports
net.anastigmatix.Packager
, and generates another
PostScript program—the next stage. That file can be saved on
a printer's disk or compactly included in PostScript documents, and
when it runs—at “load time”—it
generates the final stage, the in-memory form of the resource.
Staged programming can involve a good deal of design flexibility, such as
the chance to move computations out of later stages into earlier ones if
they do not depend on late-stage data, or to delay computations to later
stages if the run-time cost would be outweighed by a smaller intermediate
file size.
The typical source form of a resource using Packager
will resemble this outline:
Packager
procedure set with
/net.anastigmatix.Packager /ProcSet findresource begin
and then push a writable dictionary above it.
//
) form
in the code to be packed and should be dereferenced at load time rather
than at packaging time.
Because the source form is a complete PostScript program that runs at packaging time to package itself, it need not be organized rigidly as outlined above, but can do whatever is natural and efficient. The packaging survey describes some important issues and techniques.
Packager is a ProcSet resource. To make it available to your own code, include in the setup section of your file:
/net.anastigmatix.Packager /ProcSet findresource begin
The findresource
will succeed if you have made
the
Packager
resource file [download]
available in any of the
usual ways.
However, because this resource is really a development tool for other
resources, not all of those deployment methods make equal sense. You will
probably be using this resource with a PostScript interpreter on a computer
with a filesystem (though with determination you could use it on a printer
with a filesystem), and will save this resource file (and the others it
depends on)
on the filesystem under the expected names.
Packager
relies on other resources, and you will need
those files also. If you intend to use it by directly including resources in
your file's prolog, the prolog has to contain all of the needed resources, in
any order so long as no resource comes before one it depends on, and
categories come before resources that belong in them. Other methods
should just work as long as all the files are where they need to be. These are
the resources you will need:
Resource | Category | Description |
---|---|---|
net.anastigmatix.MetaPre | ProcSet | Staged-programming extensions for PostScript |
net.anastigmatix.filter | Category | Category to contain filter resources usable with StreamIO. |
DSCDataEncode | net.anastigmatix.filter |
Filter for writing arbitrary data properly
enclosed in %%BeginData/%%EndData DSC comments.
|
DSCDecode | net.anastigmatix.filter | Filter for scanning DSC-conformant input. |
WSMarkEncode | net.anastigmatix.filter |
Filter for embedding a small bitmap as a
whitespace “watermark” in a block of ASCII85
or hex data.
|
InUPathDecode | net.anastigmatix.filter | Filter for extracting a small bitmap from a figure defined as a user path. |
net.anastigmatix.StreamIO | ProcSet | Additional I/O functions and extensible filters. |
net.anastigmatix.BinaryIO | ProcSet | Binary input and output of integers, reals, and arrays. |
net.anastigmatix.Markup | ProcSet | A minimalist PostScript front-end for text markup. |
The resource file is in a compact form. That is for efficiency, not to keep you from viewing it; there is a script for that on the resource packaging page.
The Packager dictionary is read-only. Before creating any definitions, you
will want eitheruserdict begin
or your own dict
begin
so that you have a writable dictionary on top of the
dictionary stack.
This section describes the contents of the read-only dictionary that is
returned by /net.anastigmatix.Packager /ProcSet findresource
.
The array contains names that will be referenced in immediately-evaluated (//) form in the code to be packaged, but which should be dereferenced at the time the packaged code is loaded, not at the time it is packaged. The array and the names in it can be either literal or executable; executable notation can be more concise, as the leading slashes can be left off the names.
A dict is returned that maps each name in array to a literal name spelled the same but with a leading slash. If this dictionary is on the lookup stack while the code to be packaged is tokenized, the immediately-evaluated names will be replaced with the slashified literal names, which will be prefixed with another slash (like any literal name) when written in the output, and will therefore appear as immediately-evaluated name references at load time.
Given a file object open for writing, return a proc (obj proc –) that can be used to write PostScript objects one by one onto file. The intended use is with objects produced by the token operator, so not all PostScript object types are supported (though literal arrays and booleans are, as a convenience, even though token can't produce one except from an immediately-evaluated name or a binary token). A net.anastigmatix.UnsupportedType error will be signalled if proc is given an object of a type not supported.
Integers and strings are written in the most compact binary token form that fits. Names that have system name encodings in the binary token form use the encoding. A boolean object is written in the binary boolean token form (the simplest way to get a boolean object is to use //true and //false in the code to be packaged; by contrast true and false are normal executable names and will appear full length in the output because they do not have name encodings in the binary token form). Reals are written in IEEE format.
Literal arrays are written in the most compact homogeneous-number-array format that fits, if any, otherwise in the usual form of a [ followed by recursive application of proc to each object in the array, followed by ]. Executable arrays get the same recursive handling except with { and }.
If an object passed to proc has different attributes (readonly, for example) than objects of that type normally produced by token, those attribues will not be preserved. The object at load time will have the attributes normally supplied by token, and any necessary modifiers must appear explicitly in the code being packaged to modify those attributes at load time. A non-writable array, or non-readable packed array (neither of which can be produced by token except via an immediately-evaluated name) will incur a net.anastigmatix.UndeclaredImmediate error—because it will most often indicate a mistake where an immediately-evaluated name meant for load time has not been declared with atload.
Given a proc produced by tokenwriter, an input file object, and dict produced by atload, read tokens from file and write them with proc until the token operator reports EOD on file. The token operator is invoked with dict pushed on the lookup stack so that immediately-evaluated names declared with atload are properly deferred to load time.
Return a dict for use with \markup to write text into the current path in the graphics state using true charpath. The initial spacing between consecutive text baselines is given by num. The dictionary, and what can be done with it, is otherwise as described for Basic markup but without the implied glyphshow for embedded PostScript that returns a name (there is no “glyphcharpath” operator).
Capture the current path in the graphics state as userpath
and clear the current path. Construct a filter dictionary dict
with default settings that will work with the InUPathDecode
filter for reading the path back as a bitmap. ImageMatrix
is set up for unity scaling but a top-down row order (vertical scale -1),
translated so the first pixel maps to the upper left of the path's
bounding box. Width and Height are computed from the
bounding box and rounded up to the nearest integers. Half the amount
of any rounding is included in the translation component of
ImageMatrix. PathMatrix is set to a fixed
[ 6 0 0 6 0 0 ]
, which often gives good results.
(See InUPathDecode
for the role of PathMatrix.)
The default values in the dictionary can be modified for desired effects such as shifting the position of a watermark image. The same effect can sometimes be achieved more simply by using setbbox during construction of the path. The rectangle given to setbbox is always enlarged to include the pre-existing extents of the path, and the resulting bounds are enforced on later additions to the path (excursions generate rangecheck errors). Therefore a setbbox at the start of path construction can be used to ensure the figure stays within a certain size, or a setbbox after path construction can be used to enlarge the final bounding box in one or both dimensions, influencing pathprep's calculated bounds.
For example, a watermark image of right-justified text could be created
using cpath in RagLeft mode, placing the vertical alignment
at x=72 with 72 0 moveto
. The leftmost extent of
the resulting text could be well to the right of zero, reducing the
image width computed by pathprep and causing the watermark to
appear shifted left. A simple 0 0 0 0 setbbox
after building
the path will solve the problem by enlarging the reported bounding box
to include 0,0.
From a userpath and InUPathDecode filter parameter dictionary dict as could have been obtained from pathprep (and possibly modified to change the default dimensions, position, or orientation), construct a parameter dictionary for the WSMarkEncode filter. Width and Height are copied from the input dict, and DataSource is set to an InUPathDecode filter opened on userpath and dict. Other keys are left to default, but can be added to the result dict if desired before creating a WSMarkEncode filter.
Return a dict for use with \markup to write text onto the given file object open for writing. Formatting features are minimal: lines of text are written as lines of text; strings produced by embedded PostScript are written where the embedded PostScript appears. An executable object produced by embedded PostScript is executed after pushing file on the stack.
Build a stack of encoding filters over an output file as specified by array, returning a file object for the last filter created, and a proc to be used (instead of closefile) to close the filter stack. The array must have a multiple of four elements, forming dict filter pre post groups. Each filter is the name of a filter and dict is a (mandatory, but possibly empty) parameter dictionary for that filter. Before the filter is created, pre will be written on the immediately lower-level file (or, if pre is executable, it will be executed with the lower-level file object on the stack).
The filters in the stack will not be given the language-level 3 CloseTarget parameter. The filter stack should be closed by executing the returned proc, which will tear down the filter stack by closing the filters in reverse order. After each filter is closed, its post is written to the immediately underlying file object (or, if executable, executed with that object on the stack). The bool specifies whether proc should end by closing the original file object supplied to fstack.
Add to a stack of encoding filters. The input proc and file are a closing-procedure and file object as might be produced by fstack, and dict filter pre post are exactly as used in the specification array for fstack. Returns proc and file representing the new top of the filter stack.
Queries the PostScript interpreter for the name that the resource being packaged would be expected to have on the filesystem, if any. Requires that a dictionary in scope define Category and Key as described under macros.
Once DSC-conformant resource packages have been made, they can be manipulated in useful ways that make use of the DSC comments. Using the procedures in this section, resource files can be combined with the other resources they require in a workable total order, such as to combine them into a single distribution file, or to generate a query for the incremental VM usage of a single resource after loading those it depends on. Other tasks that could be automated include installing all or a subset of a collection of resources onto a printer filesystem or into initial VM. A document manager in pure PostScript could be built.
This section's procedures are documented in a bit lower level than usual, to ensure it is clear how to adapt or imitate them for tasks that do not yet have an implementation supplied in this resource.
Queries the PostScript interpreter for the name of an existing file corresponding to the resource named by key and category. Uses ResourceFileName from the category implementation dictionary, then confirms with status that such a file exists.
If not, and the system parameter GenericResourceDir can be altered without a password, saves the current parameter value and retries with an empty string for this parameter, restoring the original value after. If the interpreter in use is GhostScript and a path of multiple resource directory roots has been configured, this step will cause the path to be searched rather than just the single GenericResourceDir. With such a setup, a staging directory can be put first on the path, into which all newly packaged files will be written when ExpectedFileName is used, but ExistingFileName can be used to retrieve already-packaged resources and will find newly-built ones in the staging area and the rest in the installed location.
While the code that does this is pure PostScript and will run without error on other interpreters, it will not have this useful effect on interpreters that lack the notion of a resource path. Setting up a convenient build environment may then require a bit more cleverness.
Returns string with any leading spaces, HT
,
and LF
characters removed.
Apply trimleft to string, then attempt to parse the
<text>
production from TN 5001, namely either a
string terminating at the first whitespace, or a string in PostScript
parenthesized form. Return the string so parsed (or the empty string
if the parse failed) as text, and the remainder of the original
string as post. If text is empty on return, post
is simply the result of trimleft on the original string.
Apply trimleft to string, then attempt to parse a version
qualifier in the <version> <revision>
form specified
in TN 5001 for both <procname>
and the
%%Version:
keyword: a real and a uint.
Return in qual the entire span of text so matched (or the empty
string if not matched), and the remainder of the original string in
post.
For string a single line (i.e., treating %%+
continuations as separate lines) in the format of
%%DocumentNeededResources:
or
%%DocumentSuppliedResources:
, where a category keyword
is followed by one or more resource keys in that category, possibly
with version qualifiers, invoke proc once per resource name
encountered.
proc is executed with category key qualifier pushed on the stack above whatever was below string and proc, and is allowed to have other stack effects than simply consuming category key qualifier as long as that's ok with the caller of DSCresources.
Any key is allowed to be followed by a version qualifier. After parsing a key, if what follows can be parsed as a qualifier it will be, otherwise the qualifier is taken to be the empty string and what follows is parsed as another key.
Given file open for reading and dict a parameter dictionary for the DSCDecode filter with the additional Callbacks entry described below, create a DSCDecode filter on file and read and discard data until the filter signals EOD, either on occurrence of a DSC keyword for which a callback was specified, or on another EOD condition. If the cause was a keyword with a specified callback, invoke the callback, create a new DSCDecode filter to resume reading file, and repeat, until a filter signals EOD on a condition other than a keyword with a callback. dict must be writable; Keywords, Pushback, and Status entries may be created in it. Any code that resumes reading file after DSCscan completes must consult the Pushback entry in dict upon completion for up to three bytes to be treated as preceding the next read from file. The DSCDecode link above describes the use of the pushback buffer.
The Callbacks entry in dict must be a dictionary. Keys are the keyword strings of interest, just as for the Keywords entry in an ordinary DSCDecode filter dictionary. Values are three element arrays containing two bools and a proc.
The first element, if true, indicates that only the first occurrence of
the associated keyword in file should be processed. This is the
proper treatment for most DSC header comments, of which the first one
encountered is the truth. (The reverse convention is needed for
(atend)
comments, which are not yet supported.) Of course
the first occurrence may have any number of %%+
continuation
lines; only later new occurrences of the keyword will be suppressed.
If this element is false, the keyword will be processed as often as
it occurs.
The second element, if true, indicates that the logical content
returned by the DSCDecode filter, which may cover several
%%+
continuation lines, should be handled by invoking
proc once for the content of each line. If this element is
false, proc will be invoked once on the logical content as a
single string, a single LF
byte indicating each continuation.
The third element, proc, is executed with one string pushed on the stack above whatever was below file and dict. It will usually consume the string, but may have other stack effects that are ok with the caller of DSCscan.
Given two arrays where the first entry of each
(index OR_FOLQ
) is a queue and the second
(index OR_NPREQ
) is an integer, register an
ordering constraint that array1 precedes array2.
That is, increment the OR_NPREQ
count of
array2, and enqueue array2 on array1's
OR_FOLQ
so its prerequisite count can be decremented
when array1 is Released.
Given go-queue a queue as used by
enq and deq, and
array in the form described for Precedes,
decrement the OR_NPREQ
count in every other array found
on the queue at OR_FOLQ
in array. Enqueue on
go-queue every other array whose OR_NPREQ
was
decremented to zero.
Consult dict and return a resource descriptor for key and category, creating it if not already present. Return array (the descriptor), and a bool, true if the descriptor was newly created.
The resource descriptor is an array of length RD_LEN
whose elements (and their symbolic indices) are:
OR_FOLQ |
Queue of resources this resource must precede |
OR_NPREQ |
Count of resources that must precede this one |
RD_KEY |
key |
RD_CAT |
category |
RD_NQUAL |
Qualifier of needed version of this resource, initially the empty
string, and updated by ResourceAddPrereq from
%%DocumentNeededResources: comments referring to
this resource.
|
RD_SQUAL |
Qualifier of supplied version of this resource, if any.
Initially null, and updated by ResourceSupply from a
%%DocumentSuppliedResources: comment in
this resource.
|
Given dict a repository of resource descriptors,
queue of descriptors for resources yet to be scanned
for dependencies, proc a process to check whether one version
qualifier satisfies another, rd the descriptor for a resource
being scanned, and category key qualifier for a
resource named in %%DocumentNeededResources:
for the resource
being scanned, retrieve or create the descriptor for
category key, register it as preceding rd and,
if it was newly created, enqueue it to be scanned.
If the descriptor was not newly created, compare qualifier
to the RD_NQUAL
already recorded. Retain the already
recorded qualifier if it satisfies qualifier according to
proc. Otherwise, if qualifier satisfies the earlier
recorded qualifier, record qualifier in its place. Depending
on how the comparison proc is defined, it can be possible for
neither qualifier to satisfy the other (for example, if changes in the
major revision are considered incompatible). In that case, report
net.anastigmatix.QualifierMismatch. That case cannot occur when
proc is QualifierSatisfies.
If an RD_SQUAL
is already recorded for the needed resource
and would not satisfy qualifier according to proc, report
net.anastigmatix.QualifierMismatch.
Given dict a repository of resource descriptors,
queue of descriptors for resources yet to be scanned
for dependencies, proc a process to check whether one version
qualifier satisfies another, rd the descriptor for a resource
being scanned, and category key qualifier for a
resource named in %%DocumentSuppliedResources:
for the
resource being scanned, save qualifier as RD_SQUAL
in rd if RD_CAT
and RD_KEY
match
category and key, otherwise do nothing.
If RD_SQUAL
is already non-null, report
net.anastigmatix.ResourceMultiplySupplied. If qualifier
would not satisfy a recorded RD_NQUAL
according
to proc, report net.anastigmatix.QualifierMismatch.
Given go-queue a (probably empty) queue, dict repository of resource descriptors, scan-queue a queue on which one or more resource descriptors of interest have already been enqueued, and proc a comparison defining when one version qualifier can satisfy another, repeat as long as scan-queue is nonempty:
%%DocumentNeededResources:
and
%%DocumentSuppliedResources
.
This procedure is called ReadNeededFromFS because it assumes the resources to be scanned have been installed on the file system where they can simply be opened as needed under the names used by ExistingFileName. It will not work where the files are not randomly accessible, such as when inlined into a distribution file.
Readonly prototype of a DSCScan dictionary for use in scanning for resource dependencies. Must be copied to a writable dictionary.
Return true if the version qualifier represented by string1
is considered to satisfy the one represented by string2. This
procedure parses the strings according to the
<version> <revision>
form specified
in TN 5001 for both <procname>
and the
%%Version:
keyword (a real and a uint)
and compares them numerically.
The result is true if the <version>
in
string1 is greater than that in string2, or if
the <version>
s are equal and the
<revision>
in string1 is greater than or equal to
that in string2. (This condition in less conservative than the
one in TN 5001, which considers a <version>
bump to
indicate incompatibility.)
Generate on file, which must be open for writing, PostScript
code to determine the VM usage for the resource identified by
key and category. It must be possible to use
ExistingFileName to find readable files for the resource and all
others (transitively) referred to in
%%DocumentNeededResources:
comments.
The qualifier comparison proc is not necessary except as a sanity
check on installed versions; a version that unconditionally returns
true could be used. If proc is omitted, it defaults to
QualifierSatisfies.
The output consists of true setglobal
followed by the
concatenation of all prerequisite resources, a forced garbage collection,
and code to disable GC and record the current VM usage as the baseline.
Next is the requested resource and code to take the current VM usage and
subtract the baseline to obtain the first figure needed for a
%%VMusage:
comment, then force another GC and measure the
usage after GC (not required by TN 5001, but more useful than the numbers
that are). Next is a second copy of the resource and code to measure its
incremental VM usage over the first copy, giving the second figure for
a %%VMusage:
comment.
The generated code will report the results by writing definitions of the form:
/VMusage (int int) def /VMafterGC (int) def
The generated code can be run on whatever interpreter is chosen for measuring VM usage. For example, it could be sent over a bidirectional link to a printer with an Adobe interpreter to produce results meaningful for that implementation.
Several macros can be used within a text \markup
block
to generate parts of the DSC header boilerplate. Some or all of the
following names must be defined in a dictionary in scope before the
macros can be used. (The description of each macro will indicate which
of these values it needs.)
The available macros are described next. Each macro is a procedure that places a procedure on the stack. The markup dictionary produced by text has a HandleResult entry that, if an embedded PostScript token produces a procedure, will execute that procedure with the output file on top of the stack.
%!PS-Adobe
line that must begin the file.
Uses Category.
%%DocumentNeededResources:
lines for the DSC header.
Uses NeededResources. Produces no output if that is undefined or an
empty array.
%%DocumentSuppliedResources:
lines for the DSC header.
Uses SuppliedResources or, if that is not defined,
Category, Key, and Qualifier.
%%IncludeResource:
lines, which belong after the
DSC %%BeginProlog
.
Uses NeededResources. Produces no output if that is undefined or an
empty array.
%%BeginResource:
line that should precede the
resource code. Uses Category, Key, Qualifier, and
VMusage. This macro won't be much help in a file that supplies
several resources, unless those four definitions are changed between uses.
A string constant that is a PostScript comment containing the resource
name and version of Packager
itself, surrounded by newlines.
A suggested use is as the post string for the WSMarkEncode
layer of the filter stack.
While this is arguably way too specific and single-purpose, a procedure that converts an int to a two-digit, zero-filled decimal string just came in handy.
Translate a resource category key to a string as the category name
should appear in the DSC <resource>
syntax specified
in TN 5001 section 4.6, that is, unchanged except for the five
categories treated specially in that section, whose names get lowercased.
Translate a resource category key as it appears in DSC
<resource>
syntax (TN 5001 section 4.6) to the form it
should have everywhere else, that is, unchanged except for the five
categories treated specially in that section, which are converted from
their lowercased DSC form to their actual mixed-case form.
Most version-control systems have a way to automatically update strings in a versioned file to reflect its version. Here are some aids for working with those strings.
Given a string in the form $RCSfile: foo.ps,v $
as
produced by RCS or CVS, returns foo.ps
.
Given a string in the form $Revision: 1.2 $
as
produced by RCS or CVS, returns 1.2
.
Implements a scheme for mapping the major.minor revision
numbers of RCS or CVS into the a.b c form specified for
procset versioning on TN 5001 p. 35. The idea is you supply an
int representing the most major version component a,
incrementing it manually in the file for truly colossal changes.
The RCS major.minor get mapped to b and c.
So, for example, 0 (1.123) Major+RCS
produces
(0.1 123)
.
This resource re-exports extfilter and \markup
(from
net.anastigmatix.StreamIO
and
net.anastigmatix.Markup
,
respectively), so your packaging-time source can use them and need only one
findresource for Packager
itself.
The following filters are available as individual resource files.
Wraps a stream of arbitrary data in the Document Structure Convention
%%BeginData: n ASCII|Binary|Hex Bytes|Lines
and %%EndData comments with n matching the data written.
The target must be a positionable file; n is written by leaving enough
space after the %%BeginData: , repositioning to that spot and
writing n after writing all the data, then repositioning again to
just after the %%EndData line. The parameter dictionary may contain
the following parameters.
Key | Type | Semantics |
---|---|---|
Type | string | (Optional) One of the values ASCII, Binary, or Hex. The default is Binary. The string is copied to the %%BeginData: line, but the filter does not verify that the data stream conforms to the type. |
Count | string | (Optional) What to count, either Bytes or Lines. If Lines and the data stream does not end with a newline, the filter will add one so that the %%EndData comment begins a new line. If Bytes, the %%EndData will immediately follow the last data byte. The default is Bytes. |
A stream of ASCII85 or ASCIIHex data can be written through this filter to apply a "watermark" by inserting white space (which PostScript ignores when reading ASCII85 or hex data). The watermark is supplied as a small 1-bit-per-pixel image in the same data format that the image operator accepts.
All original white space (in fact, every character below ! in ASCII) is stripped from the stream, which is reformatted in lines of the specified length containing spaces where indicated by the image data. The watermark image can be repeated through the data block vertically, horizontally, or both.
Two small distortions to the image may be made. Regardless of the image data, no space will ever be added between the ~ and > that signal the end of ASCII85 data, and a space will always be added before a % that would otherwise begin a line, to eliminate the risk that random ASCII85 data could be picked up by naïve software as a Document Structure Convention comment.
The parameter dictionary may contain the following parameters.
Key | Type | Semantics |
---|---|---|
DataSource | various | (Required) A procedure, file, or string supplying 1-bit-per-pixel image data just as for image. The entire image will be read into VM at the time the filter is opened. |
Width, Height | integer | (Required) The dimensions of the watermark image. |
ImageMatrix | array | (Optional) As for image, a mapping from “user space” (here, the character columns and rows in the ASCII85 data) to the image source space. Unlike for image, the “user space” is oriented so that rows increase downward, and as long as the image bits are presented in a top-down order (as they often are), the identity matrix is a usable default. So this parameter is optional and defaults to the identity. |
Decode | array | (Optional) As for image, allows for inverting the sense of the image bits. The default is [0 1], which causes spaces in the output to correspond to 1 bits in the image data. |
LineLength | integer | (Optional) The length to which output lines will be formatted. The default is 74 characters. |
XStep, YStep | integer | (Optional) Nonzero values cause the watermark to repeat in the output every XStep columns, every YStep lines, or both. Both parameters default to zero, for a watermark that appears only once. |
CloseTarget | boolean | (Optional) If true, the underlying file will be closed when the filter is closed. The default is false. |
This filter can produce a small, crude bitmap image by rasterizing a user path. In producing a watermark, for example, the userpath could be constructed by upath after applying charpath to a watermark text in a simple (and unprotected) font.
The filter's “source”—rather than an arbitrary file, procedure, or string—is a user path. Reading from the filter retrieves a 1-bit-per-pixel data stream in the format accepted by image. Each 1-bit sample is determined by inufill testing a single point at the center of the sample region. Blindingly fast it is not.
The parameter dictionary may contain the following parameters.
Key | Type | Semantics |
---|---|---|
Width, Height | integer | (Required) The dimensions of the bitmap to be returned. |
ImageMatrix | array | (Optional) As for image, a mapping from user space to the image source space. Negative scaling and translation in the vertical dimension can be used to read the image in a top-down row order. The identity matrix is the default. |
PathMatrix | array | (Optional) A mapping from user space (in which the user path is defined) to any arbitrarily chosen “device space”. This matrix does not affect the size or position of the user path figure in the result image (see ImageMatrix for that), but can affect the fineness of detail in the image. Each image sample is determined by applying inufill to a single point at the center of the sample region, and inufill returns whether the “device pixel” containing that point would be painted. This matrix determines the size of the “device pixel” used in that test. Pixels much smaller than samples can leave fine detail missing, but pixels too close in size to samples will give blocky results. Side ratios of 3 to 6 (9 to 36 by area) seem to give good results. |
Packager
provides tools that can be used in many ways, but
here are some ways of using it that work for me.
There is nothing in Packager
that is specific to ghostscript
or any other PostScript interpreter. However, I do use it in a way that
takes advantage of a ghostscript feature. Ghostscript extends the notion
of a Resource
directory on disk to allow a path of
such directories, as a colon-separated list in the GS_LIB
environment variable.
A findresource will load a resource file from the first place it finds one, but the default ResourceFileName procedure in category dictionaries will come back with the first location on the path, and therefore ExpectedFileName in this procset will too.
That means I can have $HOME/postscript/Resource
first in the
path, and if my source files open ExpectedFileName as the output file,
they will always write in that directory. Testing is easy because the versions
in that directory are loaded first. Known good versions can be moved to the
system location. If a bad version is created, it can just be removed to revert
to the known good version. That's important as
Packager
can't build itself without working built versions
of itself and several other resources.
Caveat: the ghostscript people don't seem to be sure how they want this path feature to work, and in some versions it doesn't seem to behave as I have described.
The source files for filters that Packager
itself depends on
turn out to need this code placed before the opening of the output file
(which would not hurt in any case):
% if I am already built, and used in the build process, % I'd better be in memory before opening the output file. Key Category resourcestatus { pop 2 eq { Key Category findresource pop } if } if