\chapter[Figure]{插图}

在很多情境下，一图胜千言。\CONTEXT\ 在插图方面，除了支持常见的 JPEG，GIF 和 PNG 等位图格式，也支持 PDF 和 SVG 等矢量图格式，还支持 \METAPOST\ 代码形式的内部图形——代码即插图。

\section[figure]{外图}

无论是位图还是矢量图，对于 \CONTEXT\ 而言，都是外部图形，在文档中插入的方法是相同的，皆使用 \tex{externalfigure} 命令\index[externalfigure]{\tex{externalfigure}}。假设源文档所在目录存在位图文件 foo.png，用以下代码便可将其插入文档，例如插入于此处： \externalfigure[07/foo.png][width=1cm]。

\starttyping[option=TEX]
\externalfigure[foo.png]
\stoptyping

不过，这样的插图，很可能并非是你想要的插图形式。你想要的是，应该是独占一行且居中放置的插图。这个要求这并不难实现，见下例。

\startTEX
\midaligned{\externalfigure[foo.png]}
\stopTEX
\blank[line]
\midaligned{\externalfigure[07/foo.png][width=.3\textwidth]}
\blank[halfline]

\tex{externalfigure} 有第 2 个参数，用于设定插图的宽度（width）和高度（hight），但通常只需设定一个，另一个可由 \CONTEXT\ 根据图像的宽高比自动计算。下例将插图的宽度设定为正文宽度的 0.3 倍，其中 \tex{textwidth} 命令可获得正文版面宽度\index[textwidth]{\tex{textwidth}}。

\startTEX
\midaligned{\externalfigure[foo.png][width=.3\textwidth]}
\stopTEX
\blank[line]
\midaligned{\externalfigure[07/foo.png][width=.3\textwidth]}
\blank[halfline]

给插图加上标题也很容易，例如：

\startTEX
\midaligned{\externalfigure[07/foo.png][width=.3\textwidth]}
\midaligned{\tfx 这是插图的标题}
\stopTEX
\blank[line]
\midaligned{\externalfigure[07/foo.png][width=.3\textwidth]}
\midaligned{\tfx 这是插图的标题}

如果你想让插图标题能有序号，对于篇幅较小的文章，手工输入序号即可，见下例。建议在序号后，用 \tex{quad} 命令插入一个字宽的空白作为间隔\index[quad]{\tex{quad}}，因为用普通的空格，只有半个字宽，效果不好。

\startTEX
\midaligned{\externalfigure[07/foo.png][width=.3\textwidth]}
\midaligned{\tfx 图 1\quad 这是插图的标题}
\stopTEX
\blank[line]
\midaligned{\externalfigure[07/foo.png][width=.3\textwidth]}
\midaligned{\tfx 图 1\quad 这是插图的标题}

\section{标题}

倘若你担心插图太多，手工输入的插图序号难免会错乱，可以用 \CONTEXT\ 的计数器功能，让序号自动递增。首先，需要用 \tex{definenumber} 命令\index[definenumber]{\tex{definenumber}}定义一个计数器，给它取个名字，例如 \type{myfig}。

\startTEX
\definenumber[myfig]
\stopTEX

一开始，计数器没有值，需要用 \tex{incrementnumber} 命令\index[incrementnumber]{\tex{incrementnumber}}让它增 1，令其值为 1。要取得计数器的值，需要用 \tex{getnumber} 命令\index[getnumber]{\tex{getnumber}}。例如以下代码的排版效果是在文档页面里显示数字 1 和 2。

\startTEX
\incrementnumber[myfig]\getnumber[myfig]  % 1
\incrementnumber[myfig]\getnumber[myfig]  % 2
\stopTEX

知道上述计数器命令，便可为插图序号定义一个宏，每次从计数器取值，用作插图序号，然后将其增 1。在 \in[breaking-lines] 节里，我们曾经定义过一个宏 \tex{foo}：

\startTEX
\def\foo{\hskip 0pt plus 2pt minus 0pt}
\stopTEX

\noindent 在文档里使用 \tex{foo} 时，\CONTEXT\ 编译器会用这个宏的定义将其替换掉，亦即宏的使用，本质上是通过宏的名字引用其定义，这个过程通常称为{\bf 宏的展开}。下面用类似的办法，定义一个插图宏，以简化图片文件的插入过程。

\startTEX
\definenumber[myfignum] % 插图序号计数器

\def\myfigure#1#2{
  \midaligned{#2}
  \incrementnumber[myfignum]
  \midaligned{\tfx 图 \getnumber[myfignum]\quad #1}
}
\stopTEX

\tex{myfigure} 宏和其他排版命令在形式上并无区别，后者也无非是 \TEX\ 和 \CONTEXT\ 开发者定义的宏而已。使用 \tex{myfigure} 需要向其提供两个参数，例如

\startTEX
\myfigure{插图的标题}{\externalfigure[foo.png]}
\stopTEX

\noindent \CONTEXT\ 编译器遇到上述语句，会自动将其替换为

\startTEX
\midaligned{\externalfigure[foo.png]}
\midaligned{\tfx 图 \getnumber[myfignum]\quad 插图的标题}
\incrementnumber[myfignum] % 插图序号增 1
\stopTEX

下例演示了 \tex{myfigure} 的用法并给出了排版结果，插图和标题都是重复的，区别仅在于它们的序号。

\startTEX
\myfigure{标题}{\externalfigure[foo.png]}
\myfigure{标题}{\externalfigure[foo.png]}
\stopTEX

\definenumber[myfignum] % 插图序号计数器
\def\myfigure#1#2{
  \midaligned{#2}
  \incrementnumber[myfignum]
  \midaligned{\tfx 图 \getnumber[myfignum]\quad #1}
}
\myfigure{标题}{\externalfigure[07/foo.png][width=.3\textwidth]}
\myfigure{标题}{\externalfigure[07/foo.png][width=.3\textwidth]}

\indentation 不过，\CONTEXT\ 已经为插图提供了像 \tex{placetable} 那样的命令，即 \tex{placefigure}\index[placefigure]{\tex{placefigure}}。这个命令不仅能提供插图的序号，也能控制插图出现的位置，其用法与 \tex{placetable} 大致相似，可参考以下示例。

\startTEX
\placefigure[here][引用]{标题}
            {\externalfigure[foo.png][width=.3\textwidth]}
\stopTEX
\mainlanguage[en]
\setupcaption[figure][headstyle=bold, style=\tf]
\placefigure
  [here][引用]
  {标题}
  {\externalfigure[07/foo.png][width=.3\textwidth]}
\mainlanguage[cn]

类似表格，插图标题序号的前缀若要改为中文的「图」而非默认的「Figure」，需要使用 \tex{mainlanguage[cn]} 将界面切换为中文环境。插图标题的样式，也是通过 \tex{setupcaption} 设定，只是该命令的第 1 个参数是 \type{figure}。下例设定了符合中文排版惯例的插图标题样式。

\startTEX
\mainlanguage[cn]
\setupcaption[figure][headstyle=\rm, style=\tfx, align=center]
\stopTEX
\setupcaption[figure][headstyle=\rm, style=\tfx, align=center]

\section{阵列}

有时，为了节省页面空间，会将一组图片并排放置，形成一个阵列，该需求可基于 \type{floatcombination} 实现\index[floatcombination]{\type{floatcombination} 环境}，例如以下代码可构造一行三列的插图阵列。

\startexample
\startfloatcombination[nx=2,ny=1]
\placefigure{}{}
\placefigure{}{}
\stopfloatcombination
\stopexample
\simpleexample[option=TEX]{\null}
\blank[halfline]
\midaligned{\getexample}

用 \type{floatcombination} 环境构造的阵列，类似于 \tex{externalfigure}，创造的都是行内对象，可以用 \tex{midaligned} 令其居中，也可以将其作为 \tex{placefigure} 命令中的插图对象，见下例。

\startexample
\placefigure[force,none]{}{
  \startfloatcombination[nx=2,ny=1]
  \placefigure{}{} \placefigure{}{}
  \stopfloatcombination
}
\stopexample
\simpleexample[option=TEX]{\null}
\getexample

可以在 \tex{placefigure} 命令的第一个参数里用 \type{nonumber} 将插图标题的序号部分关闭，见下例，这个技巧可用于构造由一组子图构成的插图。

\startexample
\placefigure[force]{}{
  \startfloatcombination[nx=2,ny=1]
  \placefigure[nonumber]{a\quad 子图}{} \placefigure[nonumber]{b\quad 子图}{}
  \stopfloatcombination
}
\stopexample
\simpleexample[option=TEX]{\null}
\getexample

如果你从未听闻上述的 \type{floatcombination} 环境，单纯用你已掌握的 \type{tabulate} 环境和 \tex{externalfigure} 命令也能构造图片阵列，不妨一试。另外，在上述例子里，想必你已经观察到了，\CONTEXT\ 的命令，当其参数里同时存在方括号形式和花括号形式时，对于前者而言，如果你不想设定它们，通常可以将其省略，亦即它们是{\bf 可选参数}。

\section{路径}

上文所有示例，插图所用的图片文件皆需与 \CONTEXT\ 源文件位于同一目录。为了让目录中的文件更为整洁，可在源文件所在目录下建立专用于存放文档插图的子目录，例如 figures。为了让 \CONTEXT\ 编译器在编译源文件时能够找到图片文件，可以在 \tex{externalfigure} 命令里设定图片文件的相对路径，例如

\startTEX
\externalfigure[figures/foo.png]
\stopTEX

\noindent 如果插图较多，不想每次都要重复输入 \type{figures/}，可以在文档的样式文件里设定图片文件所在目录，例如

\startTEX
\setupexternalfigures[directory=figures]
\stopTEX

\section{内图}

还有一种插图，它是 \METAPOST\ 绘图代码。这些代码可以嵌入在一些绘图环境里。之前在 \in[drawing-sym] 节，已经见过了嵌入在 \type{uniqueMPgraphic} 环境里的 \METAPOST\ 代码所画的正方形。下例，在另一个常用的绘图环境 \type{useMPgraphic} 里画一个扭曲的深红色矩形。

\startexample
\startuseMPgraphic{foo}
path p; p := fullsquare randomized (.1, .3) xyscaled (7cm, 2cm);
draw p withpen pencircle scaled 4pt withcolor darkred;
\stopuseMPgraphic
\placefigure[here, nonumber]{\METAFUN\ 示例}{\useMPgraphic{foo}}
\stopexample
\simpleexample[option=TEX]{\null}
\getexample

此刻，也许你对 \METAPOST\ 依然一无所知，但是，我还是希望我的介绍能够让你对它产生一些好奇。\METAPOST\ 和 \in[lua] 节用于构造带圈数字的 Lua 编程语言，二者可谓是现代 \CONTEXT\ 飞天之双翼。

\subject{结语}

所谓插图，不过是个头大一些的文字罢了，而所谓文字，不过是个头小一些的插图罢了。我忽然有些好奇，用表音文字的民族，如果他们的先祖没有发明出像插图那样的文字，他们的语言像是从天而降的……这不科学。
