MetaFun:对齐不同长度的字符串的“边界框”

MetaFun:对齐不同长度的字符串的“边界框”

我目前正在研究 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

结果

相关内容