1984 | pic | wiki doc | ps | Brian Kernighan(42) |
1995 | gpic | source pdf html | png | James J. Clark |
2008 | dpic | home source doc online | svg | Dwight Aplevich |
2020 | pikchr | home source doc online | svg | Richard Hipp |
- 1984 (in unix v8), 1988 (released)
- a troff preprocessor, it passes most of its input untouched
- a procedural programming language
- "intended for the comfort of non-programmers"
- inspired by ideal, PICTURE, v(iewgraph), grap
cli
$ pic foo.pic | groff -ms | ps2es | gs -dBATCH -sOutputFile ... $ pic foo.pic | groff -ms > hello.ps $ pic -p foo.pic > hello.ps $ dpic -v foo.pic > foo.svg
- -ms on groff will use defaults of .PS/.PE, will center drawing
-t | LaTeX output |
language
Eat: ellipse "eat" arc -> Work: ellipse "work" move down from Eat.sw then right Sleep: ellipse "sleep" arc cw -> from Work.s to Sleep.e arc cw -> rad 0 from Sleep.w to Eat.s
- by default draws from left to right
- changes when you put a direction (up/down/left/right)
- from then on it becomes the new one
- with the entrypoint of the new one attached to the exitpoint of the last
- use {} to preserve/restore position and direction after the block is finished
- optional ";" to end statements
- use "#" to start comments
- one line statements, can be separated into multiple lines with "\"
- coordinates: x=rightward y=upward
- first object put at 0,0
- default unit is inches
- use
scale=2.54
to change it to centimeters - use
scale=25.5
to change it to millimiters
- use
blocks
- use [] to defines a
block
, which can be later threated as a single object- defines a "bounding box" for its content
- referenced as just "[]"
- labels & variables are local to it
- internal labels can be used
- in "with" positioning outside
- or directly "[].A"
roff commands
.PS | [W] [H] | start of pic, with optional width and height |
.PS | <file.pic | |
.PE | end of pic | |
.ft | [RBIP] | switch font shape, P=previous |
.ps | , N, +N | change font size, thickness, previous, new, or relative |
.fam | [TH] | changes font family T=Times, H=Helvetica |
labels
- start with upper-case
- a object can be labeled
- refers the center of the object
a position can be labeled
A: ( 0, sqrt(3/4) )
can be reset
Box1: Box1 + 1,1
control flow
if i == 0 then { } if i == 0 then { } else { } for i=0 to 5 do { } for i=0 to 5 by 0.1 do { } for i=0 to 5 by *0.1 do { }
macros
- non existing arguments are replaced by nulls strings
- remove a definition with
undef
- arguments inside macro replaced with $1,$2,…
define treecolor % color "green" % define smiley { r0 = $3 r1 = 0.4*r0 r2 = 0.04*r0 ... } pi2 = 2*atan2( 0, -1 ) for x=0.1 to 1.3 by 0.08 do { smiley( 1.5*x*cos(x*pi2), 1.1*x*sin(x*pi2), 0.23*x ) }
commands
primitive objects - planar & linear
box | 0.75 x 0.5 | |
circle | 0.25 r | |
ellipse | 0.75 x 0.5 | |
oval | pikchr | |
diamond | pikchr | |
file | pikchr | |
cylinder | pikchr | |
dot | pikchr | |
line | 1/2" | a/t/b |
arrow | 1/2" | a/t/b - synonym for "line ->" |
spline | ||
arc | 1/2"R | 90° anti-clockwise |
arc cw | 1/2"R | 90° clockwise |
move | 1/2" | moves in current direction |
"foo" | troff text |
a/t/b = above top below, where the given strings will be put
attributes - cosmetic
above | - | for text, can stack |
below | - | for text, can stack |
[rl]just | - | for text, can stack |
h[eigh]t | 1 | |
wid[th] | 1 | |
same | - | same dimensions as previous one |
rad | 1 | box with rounded corners |
dotted | 0/1 | for line/box |
dashed | 0/1 | for line/box |
<-> | - | double arrow for line/arc |
-> | - | sinle arrow for line/arc |
fill | 1 | gray intensity for box/circle/ellipse |
color | 1 | |
invis | - | invisible |
shaded | 1 | DPIC, take a rgbstring() |
outlined | 1 | DPIC, take a rgbstring() |
thick[ness] | 1 | DPIC + GPIC |
l[ine]thick | 1 | DPIC + GPIC |
italic | - | pikchr |
bold | - | pikchr |
small | - | pikchr |
big | - | pikchr |
object dot(.) modifiers
.[x¦y] | |
.[ns][we] | objects corners / compass points |
.wid[th]/.h[eigh]t | |
.rad[ius]/.diameter | |
.start/.center/.end | for line,arrow,spline |
a position can be
(X,Y) | a coordinate |
(POS1,POS2) | sugar for (POS1.x,POS2.y) |
OBJ + (X,Y) | relative to another object |
Here | literal for the current position |
[1st¦2nd] [last] ASHAPE | |
ALABEL | if object, it refers to its .center |
f<p1,p2> | interpolation by "f" between "p1" and "p2" |
f [of the way] between p1 and p2 | " |
attributes - others
- reset - reset all variables or given ones
- sh {CMD} - runs arbitrary shell command, supports redirections
- copy "file.txt" [thru MACRO] - includes pic file, ignores .PS/.PE lines
- eg: a file with lines like "A: (0.2,0.5)"
- thru MACRO makes it runs given macro with each line field as argument
- copy "file.txt" thru { … }
- you can give a literal macro
- copy thru MACRO
- runs it with all the following lines (me: a "here strings" of sorts)
- up 0.1 right 0.2 == + 0.2,0.1
- top/bottom/left/right - same as north/south/west/east
- "\D'P 1 1 1 -1'" - drawing a filled (P) triangle with troff
- LINEAR
- [udlr] DIST [ [udlr] DIST ] [then…]
- from POSITION [then…] to POSITION [chop [N] [chop N]]
- "[then]" defines segments of a path
- [udlr] DIST [ [udlr] DIST ] [then…]
- chop - chops line by radius around object
- "[then]" defines segments of a path
- PLANAR & LINEAR
- [with .[ns][we]] at POSITION - define where to put the center of shape
- move
- NUMBER - inches in the current default direction
- same - uses the same argument of last "move"
- to POSITION
- [udlr] DIST [ [udlr] DIST ] [then…]
- then [udlr] N [ [udlr] N ] - define a path
by POSITION - attachment positionUNDOCUMENTED
stdlib functions
sin(E) | in radians | cos(E) | in radians |
atan2(y,x) | in radians | sqrt(E) | - |
log(E) | in base 10 | exp(E) | in base 10 |
max(E,E) | - | min(E,E) | - |
int(E) | - | sprintf(F,..) | F=format |
- E=expr
default variables sizes
boxwid | 0.75 | boxht | 0.5 |
linewid | 0.75 | lineht | 0.5 |
circlerad | 0.25 | arcrad | 0.25 |
ellipsewid | 0.75 | ellispseht | 0.5 |
movewid | 0.75 | moveht | 0.5 |
textwid | 0 | textht | 0 |
arrowwid | 0.05 | arrowht | 0.1 |
dashwid | 0.05 | arrowhead | 2 |
maxpswid | 11 | maxpsht | 8.5 |
fillval | 0.3 | scale | 1 |
- maxps*, for max picture dimensions
- arrowhead, changes the head style
- use fillval command, smaller values are darker
- use reset command, to reset all variables values, or given ones
snippets
tree drawing macro
define tree % line down 0.25i { line right 0.15i; move right 0.2i; "$1" ljust } %
tools
ps2eps | converts postscript to encapsulated postscript | |
eps[to]pdf | converts eps to pdf | |
pic2svg | source | |
org-mode | source |
pic2graph
$ pic2graph < foo.me > foo.png
$ sed '1d,$d' foo.pic | pic2graph -background white -alpha remove -alpha off -border 10 -bordercolor white > foo.png
- converts a PIC given in stdin program to PNG
- must NOT have a .PS/.PE
- flags are passed down to ImageMagick's convert
remove transparency by default
-background white -alpha remove -alpha off
add additional border space
-border 10 -bordercolor white
use the full page canvas
-flatten
implementations
pikchr
- https://pikchr.org/home/doc/trunk/doc/differences.md
- modern pic's replacement
- drops support for loops
- drops support for conditionals
- emacs org mode for pikchr https://github.com/kljohann/pikchr-mode
dpic

articles
[ ]
?? Turning pic into HTML[ ]
86 Little Languages by Jon Bentley[ ]
87 Drawing Pictures by Dale Dougherty[X]
17 Drawing with Pic[X]
19 Compile pictures with gnu pic- use-case: document something for posterity, cleaner than a handrawn sketch
[X]
22 In Praise of Pic (and pikchr)- originally posted in 2007
[ ]
22 gopikchr: a yakshave[ ]
22 Generating CRC Diagrams with Pikchr and Bash[ ]
23 Phasor Diagrams and Z-Plane Plots with Pikchr
videos
[X]
20 Christmas Cards The Unix Way - with pic and troff by Gavin Freeborn[X]
20 drawing pictures with pic and troff by Gavin Freeborn[X]
22 Pictures on the Terminal with pic! by Bryce Vandegrift