\chapter{插图} 在很多情境下,一图胜千言。\CONTEXT\ 在插图方面,除了支持常见的 JPEG,GIF 和 PNG 等位图格式,也支持 PDF 和 SVG 等矢量图格式,还支持 \METAPOST\ 代码形式的内部图形——代码即插图。 \section[figure]{外图} 无论是位图还是矢量图,对于 \CONTEXT\ 而言,都是外部图形,在文档中插入的方法是相同的,皆使用 \tex{externalfigure} 命令\index[externalfigure]{\tex{externalfigure}}。假设 \CONTEXT\ 源文档所在目录存在位图文件 foo.png,用以下代码便可将其插入文档中该命令出现的地方,例如 \externalfigure[07/foo.png]。 \starttyping[option=TEX] \externalfigure[foo.png] \stoptyping 不过,这样的插图,很可能并非是你想要的插图形式。你想要的是,应该是独占一行且居中放置的插图。这个要求这并不难实现,见下例。 \startTEX \midaligned{\externalfigure[foo.png]} \stopTEX \blank[line] \midaligned{\externalfigure[07/foo.png]} \blank[halfline] \tex{externalfigure} 有第 2 个参数,用于设定插图的宽度(width)和高度(hight),但通常只需设定一个,另一个可由 \CONTEXT\ 根据图像的宽高比自动计算,下例将插图的宽度设定为正文宽度的 0.3 倍,其中 \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} 命令插入一个字宽的空白作为间隔,因为用普通的空格,只有半个字宽,效果不好。 \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[myfig]\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]} \myfigure{标题}{\externalfigure[07/foo.png]} \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] 类似表格,插图标题序号的前缀若要改为中文的\boxquote{图}而非默认的\boxquote{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 在上述例子里,想必你已经观察到了,\CONTEXT\ 的命令,当其参数里同时存在方括号形式和花括号形式时,对于前者而言,如果你不想设定它们,通常可以将其省略,亦即它们是{\bf 可选参数}。 可以在 \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} 命令也能构造图片阵列,不妨一试。 \section{路径} 上文所有示例,插图所用的图片文件皆需与 \CONTEXT\ 源文件位于统一目录。为了让目录更为整洁,在 \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, 3cm); 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{结语} 所谓插图,不过是个头大一些的文字罢了,而所谓文字,不过是个头小一些的插图罢了。我忽然有些好奇,用表音文字的民族,如果他们的先祖没有发明出像插图那样的文字,他们的语言像是从天而降的……这不科学。