Make Your Own Designs
by Lionel E. Deimel
A number of people have asked me how to create
curve-stitch designs using PostScript. I have invariably given
fragmentary instructions with little expectation that my correspondents
would actually have the patience to produce designs of their own with
this arcane tool. A recent request from a teacher, however, led me to
think that, given a bit more guidance, a few dedicated souls might give
my technique a try. Rather than responding at length in a personalized
reply to everyone who contacts me, I thought it might be more efficient
to provide some instructions on my Web site once and for all. No doubt,
this, too, will generate questions, but it might also lead others to
produce some innovative designs.
Background. My earliest curve-stitch designs were done with pencil and paper. I
produced serious designs by trading my pencil for drafting pens and
India ink. All the designs shown on Lionel Deimel’s Farrago are
produced by computer using the PostScript Language, however. (PostScript is a
registered trademark of
Adobe Systems Incorporated.) PostScript is a so-called page
description language now widely used for desktop and commercial
publishing. It first achieved notoriety as the language interpreted by
Apple’s LaserWriter printer in 1985. PostScript only came along about 20
years after I had given up the tedium of drawing designs with pen and ink.
Although most of the PostScript code generated today is produced by computer
software to drive devices such as printers, PostScript is a full-blown
programming language that can be used by a human programmer. What makes
PostScript attractive for producing curve-stitch designs is its extensive
repertoire of graphics operators and the ability of PostScript interpreters to
reproduce lines, whether curved or straight, at high resolutions.
The downside of programming in PostScript, at least for the typical
programmer, is that PostScript is a highly idiosyncratic language. Programming
experience is certainly an asset for the person wanting to learn how to use
PostScript, but it is less helpful than one might expect. PostScript makes
extensive use of stacks (FIFO queues), which results in code likely not to seem
very natural to most programmers. For example, one might write the following
PostScript code to set the variable y to the value 3 (x + y)
+ 1:
/y 1 3 x y add mul add def
One could just have easily written
/y x y add 3 mul 1 add def
or some other variant.
Tools. The standard introduction to PostScript has always
been
PostScript Language Tutorial and Cookbook, which is available as a
PDF
here. Reading this book and following the exercises in it is a good way to
learn PostScript basics. Eventually, particularly for newer features that have
been incorporated into the PostScript language, one has to consult the
PostScript Language Reference. Happily, it should not be necessary to
read all of this 900+ page book.
PostScript is written in ordinary, printable
characters, so programs can be composed with an ordinary text editor, such as
Microsoft Notepad. (This discussion assumes the use of a Windows platform, but
the procedures I describe can be carried out in an analogous way on other
platforms.) Do not use a word processor, such as Microsoft Word, which saves
documents in a special format.
Being able to write a PostScript program is of
limited usefulness if you cannot display whatever it is the program is intended
to draw. A PostScript printer comes in handy here, although you can waste a lot
of paper while learning language basics. It is therefore helpful to have a viewer for
PostScript files, and, fortunately, there is a free multi-platform viewer
available. It is called GSView, and it provides a user-friendly interface to
another piece of software called Ghostscript, which does much of the real work
of translating PostScript into an image. These programs are easily
installed and can be downloaded from
here. Using
GSView, you can view your PostScript or encapsulated PostScript files. You can
also view PDF files or create PDF files from PostScript ones. (Adobe has a
helpful essay on the relationship between PostScript and Portable Document
Format, PDF,
here.
It isn’t essential to understand this relationship, but it does prevent
misconceptions.)
Curve-stitch designs can be distributed as PDF
files, but this is not necessarily the best format to use in certain contexts.
The curve-stitch designs on my Web site are mostly GIFs. Because I have
Adobe Acrobat
on my computer, I use it to save page images in graphic formats, such as JPG or
TIF. GSView cannot do this, and neither does the free
Adobe Reader.
In a pinch, one can take a screen shot of a design, displayed in GSView or Adobe
Reader, say, and paste it into Microsoft Paint or some other graphics program.
(The currently active window can be copied to the clipboard using Alt+Print
Screen. The Print Screen key alone copies the entire screen to the clipboard.)
In the graphics editor, the screen image can be cropped to show only the desired
design, and the result can be saved in any of several graphic formats.
An Example. I was asked to provide an example
curve-stitch design, along with the program that generates it. I chose a
relatively simple design:

The PostScript code to produce this design is the
following:
%%Copyright 2007 by Lionel Deimel. All rights reserved.
% Procedure square2
% This procedure creates a square with generalized curve-stitch
% parabolas drawn inside. The following variables are used:
%
% sidelength: length of side of square (all measurements in points)
% segments: # of equal-length segments into which each side of square is
% to be divided
% seglength: length of each segment
% offset: distance around perimeter of square in counterclockwise
% direction (measured in # of segments) betweeen points to be
% connected in design
% xcoord: array of x-coordinates of (4 x segments) points on square
% perimeter
% ycoord: array of y-coordinates of (4 x segments) points on square
% perimeter
% index: loop index representing current point on square perimeter
% being processed
%
% This procedure expects the following arguments on the stack when
% invoked(the top of stack is at the right):
%
% segments sidelength offset
%
% The procedure draws the design and strokes it.
%
% NOTES: When segments is a even number and offset is segments / 2,
% this procedure draws a square with four standard-construction,
% non-overlapping curve-stitch parabolas inscribed in the corners of
% the square. Other designs result from manipulating the values of
% segments and offset. The value of segments should be positive, but it
% need not be even. The value of offset should be non-negative. Values
% greater than 2 x segments repeat designs achievable with smaller
% offsets.
/square2 {
% Save entered and computed parameters in dictionary
/offset exch def
/sidelength exch def
/segments exch def
/points segments 4 mul def
/xcoord points array def
/ycoord points array def
/seglength sidelength segments div def
% Save coordinates of segment endpoints in arrays xcoord and
% ycoord. The points are numbered, beginning with 0 at the
% origin and moving counterclockwise around the square.
0 1 segments 1 sub {
dup
/index exch def
seglength mul /dist exch def
xcoord index dist put
xcoord index segments add sidelength put
xcoord index segments 2 mul add sidelength dist sub put
xcoord index segments 3 mul add 0 put
ycoord index 0 put
ycoord index segments add dist put
ycoord index segments 2 mul add sidelength put
ycoord index segments 3 mul add sidelength dist sub put }
for
% Draw square
0 0 moveto
sidelength 0 lineto
sidelength sidelength lineto
0 sidelength lineto
0 0 lineto
closepath
% Draw internal lines
0 1 points 1 sub {
/index exch def
xcoord index get
ycoord index get
moveto
xcoord index offset add points mod get
ycoord index offset add points mod get
lineto }
for
% Paint path
stroke }
def % square2
% Main program starts here
% Set color for background
0.2 0.4 .8 setrgbcolor
% Translate origin to allow for entire picture in upper right quadrant
1 1 translate
% Define dimensions of square and area around square.
% side: width of square
% matwidth: width of background around square
% picwidth: with of entire figure, ignoring framing border
/side 300 def
/matwidth 50 def
/picwidth side matwidth matwidth add add def
% Draw and fill square for curve-stitch design background
0 0 moveto
picwidth 0 lineto
picwidth picwidth lineto
0 picwidth lineto
0 0 lineto
closepath
fill
% Draw black border around just-completed square
0 0 0 setrgbcolor
2 setlinewidth
0 0 moveto
picwidth 0 lineto
picwidth picwidth lineto
0 picwidth lineto
0 0 lineto
closepath
% Paint path
stroke
% Set color and line width for design
1 1 0 setrgbcolor
0.75 setlinewidth
% Translate origin to lower left corner of design
matwidth matwidth translate
% Draw design
24 side 18 square2
% Display page
showpage
%%EOF |
I wrote the program in Notepad. I previewed it using GSView 4.8. I used Acrobat 8 Professional to convert the program into a
PDF. Before doing this, however, I added this line at the top of the file:
<< /PageSize [402 402] >> setpagedevice
Effectively, this made the page size the same size as the figure drawn by the
program. Without this line, the figure would have appeared at the lower left of a letter-size page.
From Acrobat, I saved the PDF as a JPG file, which, reduced in size, appears
above. I could also have used GSView to generate a PDF. In this case, one has to
define the page size under User Defined on the Media menu. (Click
here to see the PDF file produced
by GSView.) Alternative ways of producing a graphic file from the PostScript
source are described above.
GSView can also generate an encapsulated PostScript file, which is a PostScript
file intended for incorporation into other documents. At least one graphics
editor on my computer, Microsoft’s PhotoDraw 2000, version 2, can import an EPS
file directly and generate a JPG or GIF file. (Readers may have this or another
graphics editor having this capability.) Acrobat can also output an EPS
file. Whereas GSView simply adds a few lines to the original PostScript file,
however, the output from Acrobat is a large file best described as
inscrutable. The EPS file generated by GSView, with a little editing, is the
following:
%!PS-Adobe-3.0 EPSF-3.0
%%BoundingBox: 0 0 402 402
%%Title: Curve-stitch design example for Lionel Deimel's Farrago
%%Creator: GSview from file web_example.ps
%%CreationDate: Thu Nov 08 13:30:09 2007
%%Copyright 2007 by Lionel Deimel. All rights reserved.
%%Pages: 1
%%EndComments
%%Page: 1 1
%%BeginDocument: Curve-stitch design example for Lionel Deimel's Farrago
% Procedure square2
% This procedure creates a square with generalized curve-stitch
% parabolas drawn inside. The following variables are used:
%
% sidelength: length of side of square (all measurements in points)
% segments: # of equal-length segments into which each side of square is
% to be divided
% seglength: length of each segment
% offset: distance around perimeter of square in counterclockwise
% direction (measured in # of segments) betweeen points to be
% connected in design
% xcoord: array of x-coordinates of (4 x segments) points on square
% perimeter
% ycoord: array of y-coordinates of (4 x segments) points on square
% perimeter
% index: loop index representing current point on square perimeter
% being processed
%
% This procedure expects the following arguments on the stack when
% invoked(the top of stack is at the right):
%
% segments sidelength offset
%
% The procedure draws the design and strokes it.
%
% NOTES: When segments is a even number and offset is segments / 2,
% this procedure draws a square with four standard-construction,
% non-overlapping curve-stitch parabolas inscribed in the corners of
% the square. Other designs result from manipulating the values of
% segments and offset. The value of segments should be positive, but it
% need not be even. The value of offset should be non-negative. Values
% greater than 2 x segments repeat designs achievable with smaller
% offsets.
/square2 {
% Save entered and computed parameters in dictionary
/offset exch def
/sidelength exch def
/segments exch def
/points segments 4 mul def
/xcoord points array def
/ycoord points array def
/seglength sidelength segments div def
% Save coordinates of segment endpoints in arrays xcoord and
% ycoord. The points are numbered, beginning with 0 at the
% origin and moving counterclockwise around the square.
0 1 segments 1 sub {
dup
/index exch def
seglength mul /dist exch def
xcoord index dist put
xcoord index segments add sidelength put
xcoord index segments 2 mul add sidelength dist sub put
xcoord index segments 3 mul add 0 put
ycoord index 0 put
ycoord index segments add dist put
ycoord index segments 2 mul add sidelength put
ycoord index segments 3 mul add sidelength dist sub put }
for
% Draw square
0 0 moveto
sidelength 0 lineto
sidelength sidelength lineto
0 sidelength lineto
0 0 lineto
closepath
% Draw internal lines
0 1 points 1 sub {
/index exch def
xcoord index get
ycoord index get
moveto
xcoord index offset add points mod get
ycoord index offset add points mod get
lineto }
for
% Paint path
stroke }
def % square2
% Main program starts here
% Set color for background
0.2 0.4 .8 setrgbcolor
% Translate origin to allow for entire picture in upper right quadrant
1 1 translate
% Define dimensions of square and area around square.
% side: width of square
% matwidth: width of background around square
% picwidth: with of entire figure, ignoring framing border
/side 300 def
/matwidth 50 def
/picwidth side matwidth matwidth add add def
% Draw and fill square for curve-stitch design background
0 0 moveto
picwidth 0 lineto
picwidth picwidth lineto
0 picwidth lineto
0 0 lineto
closepath
fill
% Draw black border around just-completed square
0 0 0 setrgbcolor
2 setlinewidth
0 0 moveto
picwidth 0 lineto
picwidth picwidth lineto
0 picwidth lineto
0 0 lineto
closepath
% Paint path
stroke
% Set color and line width for design
1 1 0 setrgbcolor
0.75 setlinewidth
% Translate origin to lower left corner of design
matwidth matwidth translate
% Draw design
24 side 18 square2
% Display page
showpage
%%EOF
%%EndDocument
%%Trailer |
I hope that this discussion will discourage the fainthearted
and encourage the bold. I have no intention of established a Famous
PostScript Programmers’ School, but I will try to help any serious student
get unstuck if he or she tries to use PostScript and runs into the
proverbial brick wall. My e-mail address is below.
Happy coding!
— LED, 11/8/2007
|