summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/metapost/minim-mp/minim.mp
blob: 0bbaa2a27c4d54593eb0897fc996c67fc371943a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177

delimiters ();

message "Loading the minim extension macros";

% redefine some constants to work with the new numerical engines
numeric mm, cm, pt, pc, dd, cc;
pc = 12 pt; cc = 12 dd; cm = 10 mm;
803 pt = 800; 127 mm = 360; 1157 dd = 1238 pt;
eps := 1/2048; infinity := 64*64-epsilon;

% interaction with tex
vardef baseline expr o =
    fill if numeric o : (0,o) else: o fi
        -- cycle withprescript "BASELINE:"; enddef;
vardef boxresource expr nr = image(
    fill unitsquare withprescript "BOXRESOURCE:" & decimal nr ;
    setbounds currentpicture to unitsquare transformed runscript
        ("return { 'box_size', tex.getboxresourcedimensions(" & decimal nr & ") }");
    ) enddef;

primarydef t infont f = image( runscript(
    "return require('minim-mp').infont("&ditto&t&ditto&", "
    &if numeric f: decimal(f) else: ditto&f&ditto fi&")" ) ) enddef;

% even-odd rule
def nofill expr c = fill c withprescript "OTYPE:nofill" enddef;
def eofill expr c = fill c withprescript "OTYPE:eofill" enddef;
def eofilldraw expr c = filldraw c withprescript "OTYPE:eofilldraw" enddef;

def multidraw (text paths) text opts = draw image(
    for p = paths: ; nofill p opts endfor
    withprescript "OTYPE:outline";) enddef;
def multifill (text paths) text opts = draw image(
    for p = paths: ; nofill p opts endfor
    withprescript "OTYPE:fill";) enddef;
def multifilldraw (text paths) text opts = draw image(
    for p = paths: ; nofill p opts endfor
    withprescript "OTYPE:filldraw";) enddef;
def multieofill (text paths) text opts = draw image(
    for p = paths: ; nofill p opts endfor
    withprescript "OTYPE:eofill";) enddef;
def multieofilldraw (text paths) text opts = draw image(
    for p = paths: ; nofill p opts endfor
    withprescript "OTYPE:eofilldraw";) enddef;

vardef clipto text t =
    clip currentpicture to bbox currentpicture
        for c = t: -- c -- cycle endfor -- cycle enddef;
vardef clipout text t =
    clip currentpicture to
        for c = t: c -- cycle -- endfor cycle enddef;

vardef glyph expr c of f = image(for p =
    runscript("return require('minim-mp').get_"
    &if string c: "named_glyph("&ditto&c&ditto
    else: "glyph("& decimal c fi &", "
    &if numeric f: decimal(f) else: ditto&f&ditto fi
    & ")" ) : ; nofill p endfor
    withprescript "OTYPE:fill"; ) enddef;

def contours expr t of f =
    runscript("return require('minim-mp').get_contours("&ditto&t&ditto&", "
    &if numeric f: decimal(f) else: ditto&f&ditto fi& ")" ) enddef;

% interaction with lua
vardef hexadecimal expr n =
    % TODO: support other number systems
    save d, a, m; a = ASCII("a"); m := abs n;
    if n < 0: "-0x" else: "0x" fi
    for i = 1 upto 7: &
        hide(d := floor m div 256; m := 16(m - 256d);)
        if d < 10: decimal d else: char(a+d-10) fi
        if i = 3: & "." fi
    endfor enddef;
vardef scaledpoints expr n =
    % use the fact that 800bp = 803pt
    save a, m; m := abs n;
    a1 = m div (1025/1024); % 1025/1024 = 800epsilon * 82
    m := m mod (1025/1024);
    a2 = m div 800epsilon;  % max 82
    m := (m mod 800epsilon) div epsilon;
    a3 = floor(m*803/800 + 1/2);
    if n < 0: "-(" else: "(" fi
        & decimal(a1) & "*803*82 + "
        & decimal(a2) & "*803 + "
        & decimal(a3) & ")" enddef;

% reporting
def debug_pdf = runscript
    ("require('minim-mp').enable_debugging()") enddef;
def texmessage expr msg = runscript
    ("texio.write_nl("&ditto&msg&ditto&")") enddef;

% patterns
def withpattern(suffix s) = withprescript
    ("fillpattern: " & decimal(_patterns_.s)) enddef;
def beginpattern(suffix s) =
    begingroup clearxy; clearit;
    interim defaultcolormodel:=1;
    charcode:=incr _patterns_._last_;
    _patterns_.s:=charcode; drawoptions();
    pickup pencircle scaled 0.4pt;
    save painttype; painttype:=2;
    save _withcolor; let _withcolor = withcolor; save withcolor;
    def withcolor = hide(painttype:=1) _withcolor enddef;
    save matrix; transform matrix; enddef;
def endpattern (expr xstep, ystep) =
    if unknown matrix : matrix:=identity; fi
    special "definepattern:" for e = charcode, tilingtype, painttype,
        xstep, ystep, xxpart matrix, xypart matrix, yxpart matrix, yypart matrix:
        & " " & decimal(e) endfor;
    shipit; endgroup enddef;
newinternal tilingtype; tilingtype:=1;
_patterns_._last_ := 0;

message "Loading additional definitions";

% shorthands
primarydef p xshifted x = p shifted (x,0) enddef;
primarydef p yshifted y = p shifted (0,y) enddef;

% reverse paths to allow „p & vflip p”
def hflip primary p = if path p: reverse fi p xscaled -1 enddef;
def vflip primary p = if path p: reverse fi p yscaled -1 enddef;

% missing definitions
path fullsquare, unitcircle ;
fullsquare := unitsquare shifted - center unitsquare ;
unitcircle := fullcircle shifted urcorner fullcircle ;

% complement counterclockwise
vardef clockwise primary c =
    if turningnumber c > 0: reverse fi c enddef;

% cmyk colours
cmykcolor cyan, magenta, yellow, key;
cyan    = (1,0,0,0);
magenta = (0,1,0,0);
yellow  = (0,0,1,0);
key     = (0,0,0,1);

% constants
pi := 355/113;

% shorthands
def save_pair      text t = save t; pair      t; enddef;
def save_path      text t = save t; path      t; enddef;
def save_color     text t = save t; color     t; enddef;
def save_cmykcolor text t = save t; cmykcolor t; enddef;
def save_transform text t = save t; transform t; enddef;
def save_boolean   text t = save t; boolean   t; enddef;
def save_string    text t = save t; string    t; enddef;

% missing trigonometric functions
vardef tand    primary x = sind(x)/cosd(x) enddef;
vardef arcsind primary x = angle((1+-+x, x)) enddef;
vardef arccosd primary x = angle((x, 1+-+x)) enddef;
vardef arctand primary x = angle(1, x) enddef;

% segments of the circle (counterclockwise)
vardef arc (expr thetafrom, thetalen) =
    save n, d, l, theta; save_path a; save_pair p, c;
    n = ceiling(thetalen / 45); % number of segments (45° is max segment length)
    d = thetalen / n;           % angle of each segment
    l = 4/3 * tand(d/4);        % length of control points
    theta := thetafrom;
    p := (cosd theta, sind theta);
    c := l * (-sind theta, cosd theta);
    a := p for _ = 1 upto n:
        .. controls (p + c)
        hide(theta := theta + d;
            p := (cosd theta, sind theta);
            c := l * (-sind theta, cosd theta);)
        and (p - c) .. p
    endfor; a enddef;