Skip to main content

You are not logged in. Your edit will be placed in a queue until it is peer reviewed.

We welcome edits that make the post easier to understand and more valuable for readers. Because community members review edits, please try to make the post substantially better than how you found it, for example, by fixing grammar or adding additional resources and hyperlinks.

Required fields*

MetaPost: Get text width in a narrower environment

Background

Using MetaPost, I'd like to account for a \framed environment being nested inside of a \startnarrower environment. When outside the narrower environment, the MetaPost code renders as desired:

framed 1

Problem

When the \framed is wrapped inside a \startnarrower, unwanted padding is added to the right of the title (a.k.a. legend):

framed 2

The space occupied by the blue rectangle is the problem. This space is caused by the indentation, which is represented by the red rectangle. The blue and red rectangles are the same width. (The green rectangle shows the spacing at the start of a paragraph and isn't relevant to the problem.)

I'd like to subtract the red rectangle width (indentation) from the blue rectangle width (extraneous padding caused by shifting too far).

Code

There many technical details, but the problem is this snippet:

string legend;
legend := "\ConcurrentTextGet";

% For new text blocks, write the title.
picture p;
p := textext.rt( legend ) 
  shifted ulcorner multipars[ index ] 
  shifted (1cm, 0);

% Draw the horizontal rule only for the initial text block.
draw
  ulcorner multipars[ index ] shifted (xpart lrcorner p + 1mm, 0) --
  urcorner multipars[ index ];

% Draw the vertical rule for the initial text block.
draw
  llcorner multipars[ index ] --
  ulcorner multipars[ index ] --
  ulcorner multipars[ index ] shifted (9mm, 0);

draw p;

Specifically, this calculation:

xpart lrcorner p + 1mm

It needs to account for the amount of paragraph indentation. For example:

xpart lrcorner p + 1mm - \the\parindent

Question

How would you account for the current paragraph's indentation amount within an MP graphic being used as a text background?

Addendum

Although probably irrelevant, here's the framed setup, where GraphicConcurrent refers to the given code above:

\definetextbackground[TextConcurrentFrame][
  mp=GraphicConcurrent,
  frame=off,
  topoffset=1em,
  leftoffset=1em,
  before=\blank[2*big],
  after=\blank,
  location=paragraph,
]

Here are links to the code:

--

A complete, working example to show the problem (sorry, it's a bit long):

\definenumber[ConcurrentTextSetCounter][prefix=no]
\definenumber[ConcurrentTextGetCounter][prefix=no]

\setnumber[ConcurrentTextSetCounter][0]
\setnumber[ConcurrentTextGetCounter][0]

% Map each label as global key/value pairs.
\def\ConcurrentTextSet#1{%
  \incrementnumber[ConcurrentTextSetCounter]%
  \setxvariable
    {concurrent}
    {text:\rawcountervalue[ConcurrentTextSetCounter]}
    {#1}}

% Account for the counter incrementing twice and the index being 1-based.
\def\ConcurrentTextGet{%
  \incrementnumber[ConcurrentTextGetCounter]%
  \getvariable
    {concurrent}
    {text:\number\numexpr1+\rawcountervalue[ConcurrentTextGetCounter]/2\relax}}

\startuseMPgraphic{GraphicConcurrent}
  numeric index;
  index := 1;

  % Differentiate between new text blocks and those crossing pages.
  if (multikind[ index ] = "single") or (multikind[ index ] = "first"):
    string legend;
    legend := "\ConcurrentTextGet";

    % For new text blocks, write the title.
    picture p;
    p := textext.rt( legend )
      shifted ulcorner multipars[ index ]
      shifted (1cm, 0);

    % Draw the horizontal rule only for the initial text block.
    draw
      ulcorner multipars[ index ] shifted (1mm + xpart lrcorner p, 0) --
      urcorner multipars[ index ];

    % Draw the vertical rule for the initial text block.
    draw
      llcorner multipars[ index ] --
      ulcorner multipars[ index ] --
      ulcorner multipars[ index ] shifted (9mm, 0);

    draw p;
  else:
    % Draw only the vertical rule only when crossing page boundaries.
    draw
      llcorner multipars[ index ] --
      ulcorner multipars[ index ];
  fi
\stopuseMPgraphic

\definetextbackground[TextConcurrentFrame][
  mp=GraphicConcurrent,
  frame=off,
  topoffset=1em,
  leftoffset=1em,
  before=\blank[2*big],
  after=\blank,
  location=paragraph,
]

\startsetups concurrent:before
  \ConcurrentTextSet{Legend Title}
  \startTextConcurrentFrame
\stopsetups

\startsetups concurrent:after
  \stopTextConcurrentFrame
\stopsetups

\definestartstop[concurrent][
  before=\directsetup{concurrent:before},
  after=\directsetup{concurrent:after}
]

\starttext
  \startconcurrent
    as desired, padding is just right
  \stopconcurrent

  \startnarrower
    \startconcurrent
      text goes here, padding is too long
    \stopconcurrent
  \stopnarrower
\stoptext

Answer*

Cancel