In Asymptote
, pens provide a context for the four basic drawing
commands (see Drawing commands). They are used to specify the
following drawing attributes: color, line type, line width, line cap,
line join, fill rule, text alignment, font, font size, pattern,
overwrite mode, and calligraphic transforms on the pen nib. The
default pen used by the drawing routines is called
currentpen
. This provides the same functionality as the
MetaPost
command pickup
.
The implicit initializer for pens is defaultpen
.
Pens may be added together with the nonassociative binary
operator +
. This will add the colors of the two pens.
All other non-default attributes of the rightmost pen will
override those of the leftmost pen. Thus, one can obtain a yellow
dashed pen by saying dashed+red+green
or red+green+dashed
or red+dashed+green
. The binary operator *
can be used to scale the color of a pen by a real number, until it
saturates with one or more color components equal to 1.
pen gray(real g);
¶This produces a grayscale color, where the intensity g
lies in the
interval [0,1], with 0.0 denoting black and 1.0 denoting white.
pen rgb(real r, real g, real b);
¶This produces an RGB color, where each of the red, green,
and blue intensities r
, g
, b
, lies in the interval [0,1].
pen RGB(int r, int g, int b);
¶This produces an RGB color, where each of the red, green,
and blue intensities r
, g
, b
, lies in the
interval [0,255].
pen cmyk(real c, real m, real y, real k);
¶This produces a CMYK color, where each of the cyan, magenta,
yellow, and black intensities c
, m
, y
, k
,
lies in the interval [0,1].
pen invisible;
¶This special pen writes in invisible ink, but adjusts the bounding
box as if something had been drawn (like the \phantom
command in TeX). The function bool invisible(pen)
can be used
to test whether a pen is invisible.
The default color is black
; this may be changed with the routine
defaultpen(pen)
. The function colorspace(pen p)
returns
the colorspace of pen p
as a string ("gray"
, "rgb"
,
"cmyk"
, or ""
).
The function real[] colors(pen)
returns the color components of a pen.
The functions pen gray(pen)
, pen rgb(pen)
, and
pen cmyk(pen)
return new pens obtained by converting their
arguments to the respective color spaces.
The function colorless(pen=currentpen)
returns a copy of its argument
with the color attributes stripped (to avoid color mixing).
A 6-character RGB hexadecimal string can be converted to a pen with the routine
pen rgb(string s);
string hex(pen p);
Various shades and mixtures of the grayscale primary colors
black
and white
, RGB primary colors
red
, green
, and blue
, and
RGB secondary colors cyan
, magenta
, and yellow
are defined as named colors, along with the CMYK primary
colors Cyan
, Magenta
, Yellow
, and Black
, in
the module plain
:
The standard 140 RGB X11
colors can be imported with
the command
import x11colors;
and the standard 68 CMYK TeX colors can be imported with the command
import texcolors;
Note that there is some overlap between these two standards
and the definitions of some colors (e.g. Green
) actually disagree.
Asymptote
also comes with a asycolors.sty
LaTeX
package
that defines to LaTeX
CMYK versions of
Asymptote
’s predefined colors, so that they can be used
directly within LaTeX
strings. Normally, such colors are
passed to LaTeX
via a pen argument; however, to change the
color of only a portion of a string, say for a slide presentation,
(see slide
) it may be desirable to specify the color directly to
LaTeX
. This file can be passed to LaTeX
with the
Asymptote
command
usepackage("asycolors");
The structure hsv
defined in plain_pens.asy
may be used
to convert between HSV and RGB spaces, where
the hue h
is an angle in [0,360) and the saturation
s
and value v
lie in [0,1]
:
pen p=hsv(180,0.5,0.75); write(p); // ([default], red=0.375, green=0.75, blue=0.75) hsv q=p; write(q.h,q.s,q.v); // 180 0.5 0.75
pen linetype(real[] a, real offset=0, bool scale=true, bool adjust=true)
,
where a
is an array of real array numbers.
The optional parameter offset
specifies where in the pattern
to begin. The first number specifies how far (if scale
is
true
, in units of the pen line width; otherwise in
PostScript
units) to draw with the pen on, the second number
specifies how far to draw with the pen off, and so on. If
adjust
is true
, these spacings are automatically
adjusted by Asymptote
to fit the arclength of the path. Here
are the predefined line types:
pen solid=linetype(new real[]); pen dotted=linetype(new real[] {0,4}); pen dashed=linetype(new real[] {8,8}); pen longdashed=linetype(new real[] {24,8}); pen dashdotted=linetype(new real[] {8,8,0,8}); pen longdashdotted=linetype(new real[] {24,8,0,8}); pen Dotted(pen p=currentpen) {return linetype(new real[] {0,3})+2*linewidth(p);} pen Dotted=Dotted();
The default line type is solid
; this may be changed with
defaultpen(pen)
.
The line type of a pen can be determined with the functions
real[] linetype(pen p=currentpen)
,
real offset(pen p)
, bool scale(pen p)
, and
bool adjust(pen p)
.
PostScript
units with
pen linewidth(real)
. The default line width is 0.5 bp; this value
may be changed with defaultpen(pen)
. The line width of a pen
is returned by real linewidth(pen p=currentpen)
.
For convenience, in the module plain_pens
we define
void defaultpen(real w) {defaultpen(linewidth(w));} pen operator +(pen p, real w) {return p+linewidth(w);} pen operator +(real w, pen p) {return linewidth(w)+p;}
so that one may set the line width like this:
defaultpen(2); pen p=red+0.5;
PostScript
line cap is returned on
calling linecap
with an integer argument:
pen squarecap=linecap(0); pen roundcap=linecap(1); pen extendcap=linecap(2);
The default line cap, roundcap
, may be changed with
defaultpen(pen)
. The line cap of a pen is returned by
int linecap(pen p=currentpen)
.
PostScript
join style is returned on
calling linejoin
with an integer argument:
pen miterjoin=linejoin(0); pen roundjoin=linejoin(1); pen beveljoin=linejoin(2);
The default join style, roundjoin
, may be changed with
defaultpen(pen)
.The join style of a pen is returned by
int linejoin(pen p=currentpen)
.
PostScript
miter limit is returned by
calling miterlimit(real)
.
The default miterlimit, 10.0
, may be changed with
defaultpen(pen)
. The miter limit of a pen is returned by
real miterlimit(pen p=currentpen)
.
PostScript
fill rule is returned on
calling fillrule
with an integer argument:
pen zerowinding=fillrule(0); pen evenodd=fillrule(1);
The fill rule, which identifies the algorithm used to determine the
insideness of a path or array of paths, only affects the clip
,
fill
, and inside
functions. For the zerowinding
fill rule, a point z
is outside the region bounded by a path if
the number of upward intersections of the path with the horizontal
line z--z+infinity
minus the number of downward intersections
is zero. For the evenodd
fill rule, z
is considered to
be outside the region if the total number of such intersections is even.
The default fill rule, zerowinding
, may be changed with
defaultpen(pen)
. The fill rule of a pen is returned by
int fillrule(pen p=currentpen)
.
basealign
with an integer argument:
pen nobasealign=basealign(0); pen basealign=basealign(1);
The default setting, nobasealign
, which may be changed with
defaultpen(pen)
, causes the label alignment routines to use the
full label bounding box for alignment. In contrast, basealign
requests that the TeX baseline be respected.
The base align setting of a pen is returned by
int basealign(pen p=currentpen)
.
For example, in the following image, the baselines of green \pi and \gamma are aligned, while the bottom border of red -\pi and -\gamma are aligned.
import fontsize; import three; settings.autobillboard=false; settings.embed=false; currentprojection=orthographic(Z); defaultpen(fontsize(100pt)); dot(O); label("acg",O,align=N,basealign); label("ace",O,align=N,red); label("acg",O,align=S,basealign); label("ace",O,align=S,red); label("acg",O,align=E,basealign); label("ace",O,align=E,red); label("acg",O,align=W,basealign); label("ace",O,align=W,red); picture pic; dot(pic,(labelmargin(),0,0),blue); dot(pic,(-labelmargin(),0,0),blue); dot(pic,(0,labelmargin(),0),blue); dot(pic,(0,-labelmargin(),0),blue); add(pic,O); dot((0,0)); label("acg",(0,0),align=N,basealign); label("ace",(0,0),align=N,red); label("acg",(0,0),align=S,basealign); label("ace",(0,0),align=S,red); label("acg",(0,0),align=E,basealign); label("ace",(0,0),align=E,red); label("acg",(0,0),align=W,basealign); label("ace",(0,0),align=W,red); picture pic; dot(pic,(labelmargin(),0),blue); dot(pic,(-labelmargin(),0),blue); dot(pic,(0,labelmargin()),blue); dot(pic,(0,-labelmargin()),blue); add(pic,(0,0));
Another method for aligning baselines is provided by the baseline
function (see baseline).
pen fontsize(real size, real lineskip=1.2*size)
.
The default font size, 12pt, may be changed with defaultpen(pen)
.
Nonstandard font sizes may require inserting
import fontsize;
at the beginning of the file (this requires the type1cm
package
available from
and included in recent LaTeX
distributions). The font size and line
skip of a pen can be examined with the routines
real fontsize(pen p=currentpen)
and
real lineskip(pen p=currentpen)
, respectively.
pen font(string encoding, string family,
string series, string shape)
. The default setting,
font("OT1","cmr","m","n")
, corresponds to 12pt Computer Modern Roman;
this may be changed with defaultpen(pen)
.
The font setting of a pen is returned by
string font(pen p=currentpen)
.
Alternatively, one may select a fixed-size TeX font (on which
fontsize
has no effect) like "cmr12"
(12pt Computer Modern
Roman) or "pcrr"
(Courier) using the function pen font(string
name)
. An optional size argument can also be given to scale the font
to the requested size: pen font(string name, real size)
.
A nonstandard font command can be generated with
pen fontcommand(string)
.
A convenient interface to the following standard PostScript
fonts is also provided:
pen AvantGarde(string series="m", string shape="n"); pen Bookman(string series="m", string shape="n"); pen Courier(string series="m", string shape="n"); pen Helvetica(string series="m", string shape="n"); pen NewCenturySchoolBook(string series="m", string shape="n"); pen Palatino(string series="m", string shape="n"); pen TimesRoman(string series="m", string shape="n"); pen ZapfChancery(string series="m", string shape="n"); pen Symbol(string series="m", string shape="n"); pen ZapfDingbats(string series="m", string shape="n");
cp1251
and Russian language in Cyrillic script
(font encoding T2A
):
texpreamble("\usepackage[math]{anttor}"); texpreamble("\usepackage[T2A]{fontenc}"); texpreamble("\usepackage[cp1251]{inputenc}"); texpreamble("\usepackage[russian]{babel}");
Support for Chinese, Japanese, and Korean fonts is provided by the CJK package:
The following commands enable the CJK song family (within a label, you
can also temporarily switch to another family, say kai, by prepending
"\CJKfamily{kai}"
to the label string):
texpreamble("\usepackage{CJK} \AtBeginDocument{\begin{CJK*}{GBK}{song}} \AtEndDocument{\clearpage\end{CJK*}}");
pen opacity(real opacity=1, string blend="Compatible");
The opacity can be varied from 0
(fully transparent) to the default
value of 1
(opaque), and blend
specifies one of the
following foreground–background blending operations:
"Compatible","Normal","Multiply","Screen","Overlay","SoftLight", "HardLight","ColorDodge","ColorBurn","Darken","Lighten","Difference", "Exclusion","Hue","Saturation","Color","Luminosity",
as described in
https://www.adobe.com/content/dam/acom/en/devnet/pdf/pdfs/PDF32000_2008.pdf.
Since PostScript
does not support transparency, this feature is
only effective with the -f pdf
output format option; other
formats can be produced from the resulting PDF file with the
ImageMagick
magick
program.
Labels are always drawn with an opacity
of 1.
A simple example of transparent filling is provided in the example file
transparency.asy
.
PostScript
commands within a picture
may be used
to create a tiling pattern, identified by the string name
, for
fill
and draw
operations by adding it to the
global PostScript
frame currentpatterns
,
with optional left-bottom margin lb
and right-top margin rt
.
import patterns; void add(string name, picture pic, pair lb=0, pair rt=0);
To fill
or draw
using pattern name
, use
the pen pattern("name")
. For example, rectangular tilings
can be constructed using the routines
picture tile(real Hx=5mm, real Hy=0, pen p=currentpen,
filltype filltype=NoFill)
,
picture checker(real Hx=5mm, real Hy=0, pen p=currentpen)
, and
picture brick(real Hx=5mm, real Hy=0, pen p=currentpen)
defined in
module patterns
:
size(0,90); import patterns; add("tile",tile()); add("filledtilewithmargin",tile(6mm,4mm,red,Fill),(1mm,1mm),(1mm,1mm)); add("checker",checker()); add("brick",brick()); real s=2.5; filldraw(unitcircle,pattern("tile")); filldraw(shift(s,0)*unitcircle,pattern("filledtilewithmargin")); filldraw(shift(2s,0)*unitcircle,pattern("checker")); filldraw(shift(3s,0)*unitcircle,pattern("brick"));
Hatch patterns can be generated with the routines
picture hatch(real H=5mm, pair dir=NE, pen p=currentpen)
,
picture crosshatch(real H=5mm, pen p=currentpen)
:
size(0,100); import patterns; add("hatch",hatch()); add("hatchback",hatch(NW)); add("crosshatch",crosshatch(3mm)); real s=1.25; filldraw(unitsquare,pattern("hatch")); filldraw(shift(s,0)*unitsquare,pattern("hatchback")); filldraw(shift(2s,0)*unitsquare,pattern("crosshatch"));
You may need to turn off aliasing in your PostScript
viewer for
patterns to appear correctly. Custom patterns can easily be constructed,
following the examples in module patterns
. The tiled pattern can
even incorporate shading (see gradient shading), as illustrated
in this example (not included in the manual because not all printers support
PostScript
3):
size(0,100); import patterns; real d=4mm; picture tiling; path square=scale(d)*unitsquare; axialshade(tiling,square,white,(0,0),black,(d,d)); fill(tiling,shift(d,d)*square,blue); add("shadedtiling",tiling); filldraw(unitcircle,pattern("shadedtiling"));
pen makepen(path)
; this path represents the mark to be
drawn for paths containing a single point. This pen nib path can be
recovered from a pen with path nib(pen)
. Unlike in
MetaPost
, the path need not be convex:
size(200); pen convex=makepen(scale(10)*polygon(8))+grey; draw((1,0.4),convex); draw((0,0)---(1,1)..(2,0)--cycle,convex); pen nonconvex=scale(10)* makepen((0,0)--(0.25,-1)--(0.5,0.25)--(1,0)--(0.5,1.25)--cycle)+red; draw((0.5,-1.5),nonconvex); draw((0,-1.5)..(1,-0.5)..(2,-1.5),nonconvex);
The value nullpath
represents a circular pen nib (the default);
an elliptical pen can be achieved simply by multiplying the pen by a
transform: yscale(2)*currentpen
.
overwrite
, which takes a single argument:
Allow
¶Allow labels to overwrite one another. This is the default behavior (unless
overridden with defaultpen(pen)
.
Suppress
¶Suppress, with a warning, each label that would overwrite another label.
SuppressQuiet
¶Suppress, without warning, each label that would overwrite another label.
Move
¶Move a label that would overwrite another out of the way and issue a warning.
As this adjustment is during the final output phase (in PostScript
coordinates) it could result in a larger figure than requested.
MoveQuiet
¶Move a label that would overwrite another out of the way, without warning.
As this adjustment is during the final output phase (in PostScript
coordinates) it could result in a larger figure than requested.
The routine defaultpen()
returns the current default pen attributes.
Calling the routine resetdefaultpen()
resets all pen default
attributes to their initial values.