Curve-stitch Designs

Previous ] Home ] Up ]

      

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 prominence as the language interpreted by Apple’s LaserWriter printer in 1985. PostScript 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 long 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 GIF, JPEG, or PNG files. 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.

I recently discovered another program that is quite helpful. That program is Inkscape, a free program that generates SVG (Scalable Vector Graphics) files. Its normal output is similar in function to that of PostScript; it can be rendered as high-quality images with sharp lines. (Some modern browsers, Firefox for example, can display SVG files. Try out your browser on this file, and be sure to zoom in and out to see how the image is rendered.)

One can actually produce designs directly with Inkscape, though this can be even more tedious than hand-coding PostScript. Inkscape, however, can generate SVG or PNG (Portable Network Graphics) files from a PDF file. If the PDF file has come from a hand-coded PostScript file, vector information is preserved, and the SVG file from Inkscape will be as good as one drawn in Inkscape directly. I have found that PNG files generated by Inkscape are very good.

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:

Example design

 

The PostScript code to produce this design is the following:

%! Adobe-PostScript
			
%%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.1 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. Also, cropping the image can be done later in the production process, in Inkscape, for example.

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, rev. 3/19/2009

Previous Home Up

 
Send mail to Lionel Deimel with questions or comments about Lionel Deimel’s Farrago.
Copyright © 2000-2017 by Lionel Deimel. All rights reserved.