小白最近閑來無事,自學了一點metapost,主要用它來繪制拓撲圖或流程圖。小白最近在寫自己從工作以來的所學,寫成了一份PDF的電子文檔(小白不太會使用MS Word)。小白又不想使用JPEG或PNG格式的圖片作為插圖,因為它們不是矢量的圖形,放大后圖形就顯得不夠美觀。


好了,廢話不多說了,直接來個例子吧,這個插圖來自是小白上學時的一本書《操作系統教程》。附代碼如下:

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
#?cat?GnuLinux.mp
verbatimtex
\documentclass[10pt]{article}
\usepackage{CJK}
\AtBeginDocument{\begin{CJK}{UTF8}{gbsn}}
\AtEndDocument{\end{CJK}}
\begin{document}
etex
???
input?boxes;
%?system?variables
ahangle?:=?40;
%?fig0?is?linux?virtual?file?system?topo
outputtemplate?:=?"vfs.mps";
beginfig(0);
??boxit.a(btex?用戶進程?etex);
??boxit.b(btex?系統調用界面?etex);
??boxit.c(btex?VFS?etex);
??boxit.d(btex?Ext3?etex);
??boxit.e(btex?Buffer?Cache?etex);
??boxit.f(btex?設備驅動程序?etex);
??boxit.g(btex?硬盤控制器?etex);
??boxit.minix(btex?Minix?etex);
??boxit.nfs(btex?NFS?etex);
??boxit.sysv(btex?Sysv?etex);
??boxit.direc(btex?目錄cache?etex);
??boxit.inode(btex?Inode?cache?etex);
??boxit.hard(btex?etex);
???
??%?Len?is?the?box's?length
??%?Hig?is?the?box's?hight
??numeric?Len;
??numeric?Hig;
??Len?:=?65;
??Hig?:=?14pt;
??a.e?-?a.w?=?(Len,0);?a.n?-?a.s?=?(0,Hig);
??b.e?-?b.w?=?(Len,0);?b.n?-?b.s?=?(0,Hig);
??c.e?-?c.w?=?(Len,0);?c.n?-?c.s?=?(0,Hig);
??d.e?-?d.w?=?(35,0);?d.n?-?d.s?=?(0,Hig);
??minix.e?-?minix.w?=?(35,0);?minix.n?-?minix.s?=?(0,Hig);
??nfs.e?-?nfs.w?=?(35,0);?nfs.n?-?nfs.s?=?(0,Hig);
??sysv.e?-?sysv.w?=?(35,0);?sysv.n?-?sysv.s?=?(0,Hig);
??e.e?-?e.w?=?(Len,0);?e.n?-?e.s?=?(0,Hig);
??f.e?-?f.w?=?(Len,0);?f.n?-?f.s?=?(0,Hig);
??g.e?-?g.w?=?(Len,0);?g.n?-?g.s?=?(0,Hig);
??direc.e?-?direc.w?=?(Len,0);?direc.n?-?direc.s?=?(0,Hig);
??inode.e?-?inode.w?=?(Len,0);?inode.n?-?inode.s?=?(0,Hig);
???
??%?Dis?is?the?hight?between?the?boxes
??numeric?Dis;
??Dis?:=?20;
??a.s?-?b.n?=?(0,30);
??b.s?-?c.n?=?(0,Dis);
??c.s?-?d.ne?=?(5,Dis);
??d.se?-?e.n?=?(-5,Dis);
??c.s?-?nfs.nw?=?(-5,Dis);
??d.w?-?minix.e?=?(10,0);
??sysv.w?-?nfs.e?=?(10,0);
??e.s?-?f.n?=?(0,Dis);
??f.s?-?g.n?=?(0,30);
??c.w?-?direc.e?=?(Dis,0);
??c.e?-?inode.w?=?(-Dis,0);
??hard.c?=?g.c;
??hard.e?-?hard.w?=?(100,0);
??hard.n?-?hard.s?=?(0,34);
???
??drawboxed(a,b,c,d,e,f,g,minix,nfs,sysv,direc,inode,hard);
???
??%?draw?the?connectors
??drawarrow?a.s?--?b.n;
??drawarrow?b.s?--?c.n;
???
??drawarrow?c.s?--?minix.n;
??drawarrow?c.s?--?d.n;
??drawarrow?c.s?--?nfs.n;
??drawarrow?c.s?--?sysv.n;
??pair?A[];
??A[1]?=?1/5[e.nw,e.ne];
??A[2]?=?2/5[e.nw,e.ne];
??A[3]?=?3/5[e.nw,e.ne];
??A[4]?=?4/5[e.nw,e.ne];
??drawarrow?minix.s?--?A[1];
??drawarrow?d.s?--?A[2];
??drawarrow?nfs.s?--?A[3];
??drawarrow?sysv.s?--?A[4];
??drawarrow?e.s?--?f.n;
??drawarrow?f.s?--?g.n;
??drawarrow?c.w?--?direc.e;
??drawarrow?c.e?--?inode.w;
???
??%?draw?the?outline
??pair?B[];
??B[1]?=?direc.w?-?(5,-56);
??B[2]?=?inode.e?-?(-5,-56);
??B[3]?=?inode.e?-?(-5,119);
??B[4]?=?direc.w?-?(5,119);
??draw?B[1]?--?B[2]?--?B[3]?--?B[4]?--?cycle?dashed?evenly;
???
??label.rt(btex?硬件層?etex,hard.e);
??label.rt(btex?Linux內核層?etex,b.e+(15,0));
??label.rt(btex?系統調用?etex,a.se+(15,-5));
endfig;
end


小白覺得這些代碼有些臃腫,因為是剛學,所以小白也只能做到這樣了。后續還需多加練習,才能寫出比較緊湊、高效的代碼。


如何編譯呢,在windows或gnu/linux系統上(需要安裝相關TeX),

1
2
3
4
#?mpost?-tex=latex?GnuLinux
#?mpost?-tex=latex?GnuLinux.mp
#?mptopdf?vfs.mps


效果圖為:

wKioL1WZ-XihD8ORAAHeWyvwb8Y279.jpg