我目前正在研究 ConTeXt,主要是为了尝试 MetaFun。我想了解一下它如何能够生成我脑海中的一些复杂图表。我很难理解一些概念,所以我将尝试从一个希望简单的问题开始:
假设我有一个包含三个字符串的列表:“短”、“稍长”、“长得多的字符串”。我想将这些字符串从上到下绘制在一起,每个字符串周围都有一个框。所有框的大小应相同,因此最长的字符串定义了所有框的大小。框中的字符串应居中。
显然,这需要最长字符串的大小来定义其他字符串的宽度。然后需要这些字符串的大小来使它们居中。
在 MetaFun 中可以实现吗?我不知道如何在 MetaFun 的“内部”解决这个问题,但是使用“外部”代码生成器,我无法预先确定渲染字符串的大小。Lua 是解决方案吗?
如果可能的话,有人可以给我指出一个例子或者文档中的一个好的起点吗?
答案1
以下是使用该包在 metapost 中绘制此类图形的另一种方法boxes
:
\startMPinclusions
input boxes;
\stopMPinclusions
\startMPpage[offset=2mm]
boxit.A("\strut short");
boxit.B("\strut a bit longer");
boxit.C("\strut a much longer string");
numeric maxwidth;
maxwidth := max(xpart lrcorner boxes_pic.A - xpart llcorner boxes_pic.A,
xpart lrcorner boxes_pic.B - xpart llcorner boxes_pic.B,
xpart lrcorner boxes_pic.C - xpart llcorner boxes_pic.C);
% Specify that all boxes have the same width
xpart A.e - xpart A.w = xpart B.e - xpart B.w
= xpart C.e - xpart C.w
= maxwidth + 10pt;
% Specify the boxes should be placed vertically
ypart A.s - ypart B.n = ypart B.s - ypart C.n = 5mm;
drawboxed(A,B,C);
\stopMPpage
答案2
我觉得有更好的方法可以做你想做的事情,但这里有一个简单的方法可以得到我猜你正在寻找的东西。
\startMPpage[offset=1dk]
picture a,b,c ;
numeric maxwidth ;
a = textext("\strut short") ;
b = textext("\strut a bit longer") ;
c = textext("\strut a much much longer string") ;
maxwidth = max(xpart lrcorner a - xpart llcorner a,
xpart lrcorner b - xpart llcorner b,
xpart lrcorner c - xpart llcorner c) ;
draw boundingbox a xysized (maxwidth, ypart ulcorner a - ypart llcorner a) ;
draw a ;
draw image(
draw boundingbox b xysized (maxwidth, ypart ulcorner b - ypart llcorner b) ;
draw b ;
) yshifted -1.5(ypart ulcorner b - ypart llcorner b) ;
draw image(
draw boundingbox c xysized (maxwidth, ypart ulcorner c - ypart llcorner c) ;
draw c ;
) yshifted -3(ypart ulcorner c - ypart llcorner c) ;
\stopMPpage
用 编译context
。
答案3
我们不必预先定义所有字符串然后绘制它们,而是可以边绘制边绘制字符串,并将最大宽度保存到文件中.tuc
。这需要多次传递,但大多数非平凡的 ConTeXt 文件无论如何都会这样做。我还将大部分逻辑封装在boxed_text
宏中,这使得添加额外的文本行变得更加容易。
\startMPpage[offset=1em]
% Constants
numeric inneroffset ; inneroffset = 6pt ;
numeric outeroffset ; outeroffset = 6pt ;
% Variables
numeric maxwidth ; maxwidth := lua(
"job.passes.getcollected('userdata').maxwidth or 0"
) ;
numeric vpos ; vpos := 0cm ;
% Define the boxed_text macro:
vardef boxed_text (text text) =
picture p ; p = textext("\strut " & text) ;
maxwidth := max(maxwidth, bbwidth(p)) ;
draw image(
draw boundingbox p xysized (
maxwidth + inneroffset, bbheight(p) + inneroffset
) ;
draw p ;
) yshifted vpos ;
vpos := vpos - bbheight(p) - inneroffset - outeroffset ;
enddef ;
% Add the boxes
boxed_text("short") ;
boxed_text("a bit longer") ;
boxed_text("a much much longer string") ;
boxed_text("short again") ;
% Must be last
lua("job.passes.define('userdata').maxwidth = " & decimal maxwidth) ;
\stopMPpage