> For the complete documentation index, see [llms.txt](https://overleaf-pro.ayaka.space/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://overleaf-pro.ayaka.space/latex/zh-tw/shen-ru-wen-zhang/24-how-tex-calculates-glue-settings-in-an-hbox.md).

# TeX 如何在 \hbox 中計算 glue 設定

這是本系列的第三篇，也是最後一篇文章，探討 $$\mathrm \TeX$$ 方框與膠料。第一篇文章 [盒子與膠水：使用 LuaTeX 的簡短但具視覺化的介紹](/latex/zh-tw/shen-ru-wen-zhang/11-boxes-and-glue-a-brief-but-visual-introduction-using-luatex.md) 介紹了方框與膠料的概念，並接著介紹 [《潘朵拉的 \hbox：使用 LuaTeX 掀開 TeX 方框的蓋子》](/latex/zh-tw/shen-ru-wen-zhang/36-pandora-s-hbox-using-luatex-to-lift-the-lid-of-tex-boxes.md) 其中介紹了一個 [$$\text{Lua}\mathrm\TeX$$以……為基礎的 Overleaf 專案](https://www.overleaf.com/latex/examples/exploring-the-structure-of-tex-boxes-with-luatex/pwdrypmtdbgs) 以探索……更深層結構 $$\mathrm \TeX$$ 透過使用節點圖來研究方框更深層的結構。在這最後一篇中，我們將「深入探討」……的運作機制 $$\mathrm \TeX$$ 在一個……中如何計算膠料值 `\hbox`：這個過程稱為 *設定膠料*。我們大量使用節點圖（在本系列的 [《潘朵拉的 \hbox：使用 LuaTeX 掀開 TeX 方框的蓋子》](/latex/zh-tw/shen-ru-wen-zhang/36-pandora-s-hbox-using-luatex-to-lift-the-lid-of-tex-boxes.md) 一文中介紹過），並展示如何使用及解讀它們提供的一些資料： `glue_set`, `glue_sign` 和 `glue_order`.

我們提供一個完整演算的膠料計算範例，針對一個 `\hbox` 並涵蓋許多細節；然而，可能還有其他情況與考量，本文無法在此一一說明，感興趣的讀者可參閱……第 77 頁 $$\text{The } \mathrm \TeX \text{book}$$.

## 挑戰

假設我們有一個 `\hbox` 像這樣：

```latex
\hbox to100pt{%
A\hskip4pt plus3pt minus 2pt%
B\hskip 0pt plus 2fil%
C\hskip 0pt plus 2fill%
D\hskip 0pt plus 3fill%
}
```

這個方框看起來是這樣——為了清楚起見，這裡以放大且加上邊框的方式顯示：

![方框](/files/a594ba61090be426a082f2c3a75447dc9118a922)

問題是：最後的值是多少，以 $$\mathrm \TeX$$ 點為單位，以下各項之間的空間（膠料）：

* A 與 B
* B 與 C
* C 與 D
* D 與方框結尾之間

也就是說，我們要計算以下各項的值： $$\mathrm{g}*{1}, \mathrm{g}*{2}, \mathrm{g}*{3} \text{ and } \mathrm{g}*{4}:$$

![彈性間距](/files/fc5ae9373873d94f76f6426ac7ccec2441b70571)

這裡是一個表示上述方框的節點圖。特別值得注意的是「metadata」區段中的三個值：

* `glue_set`
* `glue_sign`
* `glue_order`

![節點圖](/files/e0831613ca242e34ee23ad6d31885b4f335ba732)

需要注意的是，某組特定的 `glue_set`, `glue_sign` 和 `glue_order` 只會影響最上層方框中的膠料：它們不會影響 *巢狀* 方框：每個巢狀方框（hlist 或 vlist 物件）都有這三個參數各自的值。以下是一個 `\hbox` 巢狀於外層 `\hbox`。在這個例子中，你可以清楚看到……不同的值 `glue_set`——當然，巢狀方框對於……也可以有不同的值 `glue_sign` 和 `glue_order`.

```latex
\hbox to 75pt{\hfill ABC\hbox to15pt{\hfill D}}
```

![節點圖](/files/8b4e0585a0efcec0b56ebe52f0f2d871b7845423)

## 膠料類型、無窮與階數：摘要

$$\mathrm \TeX$$ 提供了多個與膠料相關的基本指令，包括：

* 水平膠料： `\hskip`, `\hfil`, `\hfill`, `\hfilneg`, `\hss`;
* 垂直膠料：`\vskip`, `\vfil`, `\vfill`, `\vfilneg`, `\vss`;

以及 `\mskip` 用於在數學式中插入膠料。

一項膠料由三個值定義：

* **自然寬度**：若不拉伸或壓縮，它會占用多少空間；
* **拉伸分量**：膠料最多可拉伸多少；
* **壓縮分量**：膠料最多可壓縮多少。

我們接下來要討論的是在一個……內部使用膠料 `\hbox{...}` 以及用來計算 $$\mathrm \TeX$$ 用來決定膠料最終會占用多少空間的計算。接下來我們要用來建立一些 *水平* 膠料的指令是 `\hskip`，其形式如下：

`**\hskip** *<natural width>* **plus** *<amount to stretch>* **minus** *<amount to shrink>*`

對於 *垂直* 你會使用的膠料 `**\vskip** *<natural width>* **plus** *<amount to stretch>* **minus** *<amount to shrink>*`.

例如，某些典型的水平膠料可表示為 `\hskip 3pt plus 2pt minus 1pt`。你也可以使用其他實體單位：

* `\hskip 3mm plus 2mm minus 1mm`
* `\hskip 3in plus 2in minus 1in`
* `\hskip 1in plus 3cm minus 20mm`

## $$\mathrm \TeX$$ 膠料與「無窮」單位

對於膠料的壓縮或拉伸分量 $$\mathrm \TeX$$ 還引入另一種單位：所謂的「無窮」： $$\text{fil}$$, $$\text{fill}$$ 和 $$\text{filll}$$。這三個「無窮層級」的排列順序中，後一個都比前一個「更無窮」：

$$\text{fil} < \text{fill} < \text{filll}$$

也許「無窮」這個名稱對這些單位來說有點令人困惑——也可以把它們視為不同層級的 *優先順序*，因為，終究，它們有助於決定哪些膠料實際參與拉伸或壓縮的過程。透過讓膠料具有「無窮」的拉伸或壓縮分量， $$\mathrm \TeX$$ 就能建立可按任意所需量拉伸或壓縮的膠料。請注意，對於有限膠料， $$\mathrm \TeX$$ 會限制這類膠料可壓縮的幅度。以下是一個「無窮」膠料的例子：

`\hskip 3pt plus 2fil minus 1fill`

請注意，我們不能寫成例如 `\hskip 1fil` ，因為 $$\mathrm \TeX$$ 會回報錯誤，訊息為 `不合法的度量單位（已插入 pt）`。到這裡，這些「無窮層級」可能聽起來非常奇怪，但暫時請先照字面接受它，接下來我們很快就會看到 $$\mathrm \TeX$$ 在進行膠料計算時如何使用這些無窮。

### 無窮層級（「膠料階數」）

在內部，當 $$\mathrm \TeX$$ 執行膠料計算時，它認為每一個無窮層級都是一個「膠料階數」，範圍為 0–3，其中第 0 階用於具有實體單位（如 bp、pt、mm 等）的膠料。然而，對於 $$\text{Lua}\mathrm\TeX$$ 這裡有一點差異，因為它實際上多了一種在許多其他 $$\mathrm \TeX$$ 引擎中並不存在的無窮類型（階數）： $$\text{fi}$$ （見下方說明）。如果你閱讀 $$\text{The } \mathrm \TeX\text{book}$$ 你不會看到任何關於 $$\text{fi}$$ 無窮的提及——原因很簡單：它並未實作在 Knuth 原始的 $$\mathrm \TeX$$ 軟體中。因此，我們在……之間存在一點「脫節」 $$\text{Lua}\mathrm\TeX\text{'s}$$ 無窮的階數，以及你可能在……相關書籍中看到的那些階數 $$\mathrm \TeX$$. $$\text{Lua}\mathrm\TeX$$ 使用的無窮階數範圍是 0–4，但其他（常見） $$\mathrm \TeX$$ 引擎的範圍是 0–3。以下是一個表格，顯示每種膠料單位所對應的膠料階數。

|                           |                |     |     |      |       |
| ------------------------- | -------------- | --- | --- | ---- | ----- |
|                           | 實體單位（pt、mm、in） | fi  | fil | fill | filll |
| $$\text{Lua}\mathrm\TeX$$ | 0              | 1   | 2   | 3    | 4     |
| 其他引擎                      | 0              | 不適用 | 1   | 2    | 3     |

### 關於……的註解 $$\text{Lua}\mathrm\TeX$$：為何要多一個無窮？

$$\text{Lua}\mathrm\TeX$$ 是從多個專案與程式碼函式庫衍生而來的，其中包括一個名為 [Omega](https://en.wikipedia.org/wiki/Omega_\(TeX\)). $$\text{Lua}\mathrm\TeX$$ 納入了 Omega 程式碼的某些部分，其中包括一種稱為 $$\text{fi}$$的新型無窮膠料。摘自 Omega 手冊：

> 「新增了一個無窮層級 $$\text{fi}$$ 。它已被加入。它比 $$\text{fil}$$ 更小，但比任何有限量都大。它最初的用途是用於字母間拉伸：要麼補黑，正如阿拉伯文等書法文字所做的；要麼用於強調，如俄文；而且無須重寫現有的巨集套件。因此，新增了一個關鍵字， $$\text{fi}$$，以及兩個新的原始指令， `\hfi` 和 `\vfi`」。

## 回到我們的挑戰

依照 Knuth 的模型，我們先定義兩個量：

* 方框的目標寬度： $$\mathrm{W}\_{\mathrm{D}}$$——我們希望它有多寬；
* 方框的自然寬度： $$\mathrm{W}\_{\mathrm{N}}$$——在任何膠料被拉伸或壓縮之前，其構成元素所占據的總空間。

### 方框的自然寬度

方框的自然寬度是該方框中所有組成部分的總寬度：字元、kern、巢狀方框以及任何膠料。對於方框內的膠料，其自然寬度會忽略膠料的任何拉伸或壓縮：也就是說，在任何拉伸或壓縮發生之前的大小。

再一次，這裡是我們正在檢視的方框：

```latex
\hbox to100pt{%
A\hskip4pt plus3pt minus 2pt%
B\hskip 0pt plus 2fil%
C\hskip 0pt plus 2fill%
D\hskip 0pt plus 3fill%
}
```

顯然，我們希望方框寬度為 100pt，因此 $$\mathrm{W}*{\mathrm{D}}=100\mathrm{pt}$$ 但它的自然寬度呢， $$\mathrm{W}*{\mathrm{N}}$$？要計算自然寬度，很明顯我們需要四個字元（A、B、C 和 D）的寬度，加上四段膠料的自然寬度。

$$\eqalign{\mathrm{W}\_{\mathrm{N}} &= &\text{width(A)} + \text{width(B)} + \text{width(C)} + \text{width(D)} \ & &+ \text{width}(\verb\*\hskip 4pt plus3pt minus 2pt\*)\ & &+\text{width}(\verb\*\hskip 0pt plus 2fil\*)\ & &+\text{width}(\verb\*\hskip 0pt plus 2fill)*\ & &+\text{width}(\verb*\hskip 0pt plus 3fill\*)\ }$$

其中 $$\text{width}$$ 只是用來表示某個項目自然寬度的記號。我們可以從節點圖取得四個字元（A、B、C 和 D）的自然寬度：

![節點圖](/files/9fc821d1f731d38e66fd1ab8f3006d910fd0fac1)

從上面的節點圖可以看出：

$$\eqalign{ \text{width(A)} &= 7.50002\text{pt}\ \text{width(B)} &= 7.08336\text{pt}\ \text{width(C)} &= 7.22223\text{pt}\ \text{width(D)} &= 7.6389\text{pt}\ }$$

現在，我們只需要膠料的自然寬度，而這可透過忽略拉伸與壓縮分量輕易得到：

$$\eqalign{ &\text{width}(\verb\*\hskip 4pt plus3pt minus 2pt\*) & = 4\text{pt}\ &\text{width}(\verb\*\hskip 0pt plus 2fil\*) &=0\text{pt}\ &\text{width}(\verb\*\hskip 0pt plus 2fill)*&=0\text{pt}\ &\text{width}(\verb*\hskip 0pt plus 3fill\*)&=0\text{pt}\ }$$

因此：

$$\eqalign{ \mathrm{W}\_{\mathrm{N}} & = \text{widths of characters} + \text{width of all glues}\ &= 7.50002\text{pt}+ 7.08336\text{pt} + 7.22223\text{pt} + 7.6389\text{pt} + 4\text{pt}\space \text{(from }\verb\*\hskip\*\text{)}\ &=33.4445\text{pt}\ }$$

我們現在有兩個關鍵資訊：

$$\eqalign{ \mathrm{W}*{\mathrm{D}} & = 100\text{pt}\ \mathrm{W}*{\mathrm{N}} & = 33.4445\text{pt}\ }$$

顯然， $$\mathrm{W}*{\mathrm{D}} > \mathrm{W}*{\mathrm{N}}$$ 而其差值是 $$(100-33.4445)\text{pt}=66.5555\text{pt}$$；這些多餘的空間必須靠拉伸膠料來填滿——但要拉伸哪些，又要拉伸多少？

### 誰的拉伸量最多？

依照 Knuth 的方法（……第 77 頁） $$\text{The } \mathrm \TeX \text{book}$$），但允許加入額外的無窮類型（$$\text{fi}$$）由 $$\text{Lua}\mathrm \TeX$$提供 *總* 拉伸量，形式如下：

$$\text{total stretch} = y\_{0}+ y\_{1}\text{fi} +y\_{2}\text{fil} +y\_{3}\text{fill} +y\_{4}\text{filll}$$

首先，如果我們寫下 $$\text{total glue}$$:

$$\text{total glue } = (\verb*4pt plus3pt minus 2pt*) + (\verb*0pt plus 2fil*) + (\verb*0pt plus 2fill*) + (\verb*0pt plus 3fill*)$$

我們就可以看出 $$\text{total stretch}$$ 的一般形式如下：

$$\eqalign{ \text{total stretch} & = 3\text{pt}+ 0\text{fi} + (2\text{fil}) + (2\text{fill} + 3\text{fill}) + 0\text{filll}\ &=3\text{pt}+ 0\text{fi} + 2\text{fil} + 5\text{fill} + 0\text{filll}\ }$$

將這與……比較 $$\text{total stretch} = y\_{0}+ y\_{1}\text{fi} +y\_{2}\text{fil} +y\_{3}\text{fill} +y\_{4}\text{filll}\space$$我們可以看出：

$$\eqalign{ y\_0 &=3\text{pt}\ y\_1 &=0\ y\_2 &=2\ y\_3&=5\ y\_4&=0\ }$$

$$\mathrm\TeX$$ 接著會「問自己」：觀察 $$\text{total stretch}$$，哪個非零值所屬的無窮層級最高？檢視我們方框的 $$\text{total stretch}$$ 可以清楚看到，非零且「最無窮」的拉伸分量是 $$\text{fill}$$ 而我們有 $$y\_3=5$$ 個該單位：也就是具有 $$\text{fill}$$ 拉伸分量的膠料提供所有拉伸量。……的下標 3 $$y\_3$$ 告訴我們 `glue_order` 將被使用的膠料……在這個例子中是用於拉伸。現在，如果我們查看這個……的節點圖中的「metadata」區段 `\hbox` 我們現在就能理解另外兩個「metadata 值」（我們會在下一節討論 `glue_set` ）

![metadata](/files/cab2e219932cafb852052cf162430ec26a2de6ac)

* `glue_sign`：告訴你膠料是設定為自然長度、拉伸，還是壓縮：
* 0=設為自然寬度
* 1=拉伸
* 2=壓縮

在我們的例子中， `glue_sign` 的值為 `1`，表示參與的膠料要被拉伸。

* `glue_order` 告訴你涉及的是哪個「無窮」；對於 $$\text{Lua}\mathrm \TeX$$ 值為 3 表示具有……分量的膠料將參與膠料計算——在我們這裡，它們會被拉伸。 $$\text{fill}$$ 分量的膠料將參與膠料計算——在我們這裡，它們會被拉伸。

任何沒有以……單位定義拉伸分量的膠料 $$\text{fill}$$ 都會 **設為其自然長度**：也就是說，它在（本例中）完全不會拉伸。

### 要拉伸或壓縮多少：計算 glue\_set

總結我們目前的位置與已知內容：

1. 方框的目標寬度： $$\mathrm{W}\_{\mathrm{D}} = 100\text{pt}$$;
2. 方框的自然寬度： $$\mathrm{W}\_{\mathrm{N}} = 33.4445\text{pt}$$;
3. 膠料必須拉伸，但只有具有……的膠料 $$\text{fill}$$ 拉伸分量才能執行那個拉伸；
4. 我們總共有 $$(2+3)=5$$ 單位的 $$\text{fill}$$ 可用。

下一個問題是：那些膠料實際上會拉伸多少？這就要用到 *glue set 比率*——在我們的節點圖中稱為 `glue_set` 。 $$\mathrm \TeX$$ 它的作用是先算出需要填補多少空間，然後依據各自拉伸分量的大小，將這些空間按比例分配給適當的膠料。如果你回頭看我們實際的 `\hbox` 你就能清楚看到哪些膠料的拉伸分量包含……單位 $$\text{fill}$$:

```latex
\hbox to100pt{%
A\hskip4pt plus3pt minus 2pt%
B\hskip 0pt plus 2fil%
C\hskip 0pt plus 2fill%
D\hskip 0pt plus 3fill%
}
```

該 $$\textit{glue set ratio }(\text{or } \verb*glue\_set*)$$ 是這樣計算的：

$$\eqalign{ \text{glue set ratio}\space (\verb*glue\_set*) = & {\text{amount to stretch}}\over{\text{value of highest infinity}}\ =& {\mathrm{W}*{\mathrm{D}}-\mathrm{W}*{\mathrm{N}}}\over{y\_3}\ =& {(100-33.4445)}\over{5}\ =& {66.5555}\over{5}\ =& 13.3111\space (\text{to 4 decimal places})\ }$$

而現在是……中的最後一步 $$\mathrm\TeX$$ 演算法被套用：

1. 對於每一項其拉伸分量符合所需 `glue_order` （本例中為 3）的膠料，其長度將變成：

$$\text{stretched value} = \text{natural length} + (\verb*glue\_set* \times \text{value of stretch component})$$

3. 所有其他膠料都會設為其自然長度——也就是說，它們完全不拉伸。

看看我們方框中的膠料：

```latex
\hbox to100pt{%
A\hskip4pt plus3pt minus 2pt%
B\hskip 0pt plus 2fil%
C\hskip 0pt plus 2fill%
D\hskip 0pt plus 3fill%
}
```

我們可以逐一計算它們的最終值：

1. **A 與 B 之間**: `\hskip 4pt plus3pt minus 2pt`。拉伸分量是 `3pt`，其階數是 `0`。所需的 `glue_order` 是 `3`：拉伸分量會被忽略，而這段膠料採用其自然寬度 `4pt`.
2. **B 與 C 之間**: `\hskip 0pt plus 2fil`。拉伸分量是 `2fil`，其階數是 `2`。所需的 `glue_order` 是 `3`：拉伸分量會被忽略，而這段膠料採用其自然寬度 `0pt`.
3. **C 與 D 之間**: `\hskip 0pt plus 2fill`。拉伸分量是 `2fill`，其階數是 `3` 並符合所需的 `glue_order` 的 token 值 `3`。這段膠料將被拉伸為： $$\eqalign{ \text{stretched value}\space = & \text{natural width} + (\verb*glue\_set* \times \text{value of stretch component})\ = & 0\text{pt} + 13.3111 \times 2 \ = & 26.6222\text{pt}\ }$$5. **D 與方框結尾之間**: `\hskip 0pt plus 3fill`。拉伸分量是 `3fill`，其階數是 `3` 並符合所需的 `glue_order` 的 token 值 `3`。這段膠料將被拉伸為： $$\eqalign{ \text{stretched value}\space = &\text{natural width} + (\verb*glue\_set* \times \text{value of stretch component})\ =& 0\text{pt} + 13.3111 \times 3 \ = &39.9333\text{pt}\ }$$

## 最後：檢查總寬度

計算膠料實際占用空間的過程稱為 *設定膠料* 因此我們現在可以檢查是否已將方框填滿到所需寬度， $$(\mathrm{W}\_{\mathrm{D}} = \text{100pt})$$:

$$\eqalign{ \mathrm{W}\_{\mathrm{D}} & = \text{width of all characters} + \text{width of all }\textbf{set}\text{ glue values}\ & = \text{A:7.50002pt} + \text{B:7.08336pt} + \text{C:7.22223pt} + \text{D:7.6389pt}\ & + \text{4pt} + \text{0pt} + \text{26.6222pt} + \text{39.9333pt}\ & = \text{100.00pt} }$$

我們現在知道所有膠料的寬度，並可以準備一張圖來回答本篇文章開頭提出的問題：以下是我們的……中字元之間的膠料寬度 `\hbox`:

![彈性間距](/files/ccfffebc49b39c1757377f31e35580550a8c558b)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://overleaf-pro.ayaka.space/latex/zh-tw/shen-ru-wen-zhang/24-how-tex-calculates-glue-settings-in-an-hbox.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
