📄 ntfbox.mp
字号:
%
% Parameters:
% pair: e, ne, n, nw, w, sw, s, se: the eight corners and midpoints
% off: vector from centre of box to centre of contents
% numeric: rt, top, lft, bot: the four side coordinates
% height, width: triv.
% drt, dtop, dlft, dbot: distance of box to contents
% corner_radius: radius of corners, default = 0;
bx.defaultdx = 3bp;
bx.defaultdy = 3bp;
def bound_upper( suffix a )(expr b ) =
if a > b: a := b; fi
enddef;
def declarebx( text self ) =
pair self.e, self.ne, self.n, self.nw, self.w, self.sw, self.s, self.se, self.c,
self.off, self.pic_size;
numeric self.rt, self.top, self.lft, self.bot, self.height, self.width,
self.drt, self.dtop, self.dlft, self.dbot,
self.corner_radius;
boolean self.hideborder;
picture self.pic, self.dash_pattern;
% self.hideborder = false;
enddef;
def fixsizebx( suffix self ) =
% We use an order we think is the best priority.
if unknown self.dtop and unknown self.dbot: self.dtop = self.dbot; fi;
if unknown self.dlft and unknown self.drt : self.dlft = self.drt; fi;
if unknown self.dtop: self.dtop = bx.defaultdy; fi;
if unknown self.dlft: self.dlft = bx.defaultdx; fi;
if unknown self.dbot: self.dbot = bx.defaultdx; fi;
if unknown self.drt : self.drt = bx.defaultdx; fi;
if unknown self.corner_radius: self.corner_radius = 0; fi;
if unknown self.hideborder: self.hideborder = false; fi;
% to avoid crooked path, we bound the radius, and leave a little room
% otherwise, roundoff errors result in very strange path.
bound_upper( self.corner_radius, self.width/2 - eps );
bound_upper( self.corner_radius, self.height/2 - eps );
enddef;
def makebx( suffix self)( text contents ) =
if unknown self.c: declarebx( self ); fi;
self.e = (self.rt , self.vmid );
self.ne = (self.rt , self.top );
self.n = (self.hmid, self.top );
self.nw = (self.lft , self.top );
self.w = (self.lft , self.vmid );
self.sw = (self.lft , self.bot );
self.s = (self.hmid, self.bot );
self.se = (self.rt , self.bot );
self.c = (self.hmid, self.vmid );
% unknown: 6 (lft, hmid, rt, top, vmid, bot)
% Next we make sure that the center is in the middle. This leaves 4 degrees of freedom.
self.c = .5[self.se, self.nw];
% unknown: 4 (lft, rt, top, bot)
% And we define the height and width
(self.width, self.height) = self.ne - self.sw;
for c = contents:
if picture c:
self.pic := c;
else:
self.pic := c infont defaultfont scaled defaultscale;
fi;
endfor
self.pic_size = urcorner self.pic - llcorner self.pic;
self.sw + (self.dlft, self.dbot) + self.pic_size + (self.drt, self.dtop) = self.ne;
% unknown: 6 (box and position of picture within box)
% Define self.off as offset from centre of box.
self.sw + (self.dlft, self.dbot) + self.off = llcorner self.pic;
enddef;
def dashbx( suffix self )( expr s ) =
self.dash_pattern := dashpattern( on s/2 off s on s/2 );
enddef;
def hideborderbx( suffix self ) =
self.hideborder = true;
enddef;
def bx_bbox( suffix self ) =
begingroup save r; r = self.corner_radius;
self.se + (0,r){up} ..
self.ne - (0,r){up} ..
self.ne - (r,0){left} ..
self.nw + (r,0){left} ..
self.nw - (0,r){down} ..
self.sw + (0,r){down} ..
self.sw + (r,0){right} ..
self.se - (r,0){right} .. cycle
endgroup
enddef;
def drawbx( suffix self ) =
begingroup
fixsizebx( self );
draw self.pic shifted -self.off;
if not self.hideborder:
save p;
path p;
p := bx_bbox( self );
% We draw each of the parts dashed, top down, left to right.
% This allows nice dash patterns with nice corners too.
drawbx_dashed( self, reverse (subpath ( 7.5, 8 ) of p & subpath (0, 1.5 ) of p) );
drawbx_dashed( self, reverse subpath (1.5, 3.5 ) of p );
drawbx_dashed( self, subpath (3.5, 5.5 ) of p );
drawbx_dashed( self, subpath (5.5, 7.5 ) of p );
fi;
endgroup
enddef;
def drawbx_dashed( suffix self )( expr p ) =
if unknown self.dash_pattern:
draw p;
else:
begingroup
save s, n, nr;
s = ypart( urcorner self.dash_pattern );
n = arclength p / s;
nr = round n;
% If nr = 0, the side is too small for dashing, we draw it solid.
draw p if nr > 0: dashed (self.dash_pattern scaled (n/nr) ) fi;
endgroup
fi;
enddef;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -