Ring of Type
One sentence set glyph by glyph around eleven shrinking rings.
How it is made
Each letter is placed and rotated individually around a circle, using the width of each letter (stringwidth) to space it. The ampersand in the middle is drawn from the outline of the character itself (charpath), so it can be stroked and filled like any other shape.
Details
- Category
- Lettering and type
- Libraries
- none: this piece is plain PostScript
- Added
- 2026-07-13
- Page size
- 700 × 700 points
Source
View source the whole program in a scrolling window, or read gallery/ring_of_type.ps on GitHub. To draw it yourself, from a checkout of the repository:
pscat --page 700x700 gallery/ring_of_type.ps
Open it in the playground and watch it draw in your browser: this piece reads no other file, so it runs there unchanged.
The first 40 of 63 lines of the source
%!PS-Adobe-3.0 EPSF-3.0
%%BoundingBox: 0 0 700 700
%%Title: Ring of Type
%%Creator: Claude, resident artist
%%EndComments
% The Stage 6 piece: typography as geometry. One sentence circles the
% page eleven times, set a character at a time on shrinking rings —
% each glyph placed with stringwidth and its own rotate, so the baseline
% bends where straight text can't. Faces alternate serif/sans as the
% rings descend from midnight blue to ember, and a giant charpath
% ampersand — type as pure outline — anchors the middle.
/msg (HELLO, LASERWRITER \267 DRAWN LIVE BY PSCAT \267 ) def
350 350 translate
% fontname size radius hue startangle ringoftype -
/ringoftype {
7 dict begin
/theta exch def /hue exch def /r exch def /size exch def
findfont size scalefont setfont
hue 0.72 0.62 sethsbcolor
/stop theta 357 sub def % close the ring, minus a thin seam
/i 0 def
% walk characters around the ring until the next one wouldn't fit
{
/c msg i msg length mod 1 getinterval def
% angular advance that keeps letterspacing true on this radius:
% arc length = glyph width, in degrees = w/r * 180/pi
/w c stringwidth pop r div 57.29578 mul def
theta w sub stop lt { exit } if
gsave
theta rotate
0 r moveto
c show
grestore
/theta theta w sub def
/i i 1 add def
} loop