Vertical Text
:orientation :vertical sets text in columns, read top to bottom, with the
columns running from right to left, as in traditional Chinese and Japanese.
(tr:with-font (cjk "/usr/share/fonts/truetype/droid/DroidSansFallbackFull.ttf" :size 16)
(tr:with-font (latin "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf" :size 16)
(let ((layout (tr:layout-text "日本語のLisp入門" (list cjk latin)
:orientation :vertical :width 64)))
(list (tr:layout-width layout)
(tr:layout-height layout)
(map 'list (lambda (column)
(list (subseq (tr:layout-string layout)
(tr:line-start column)
(tr:line-end column))
(tr:rect-x (tr:line-box column))
(tr:rect-width (tr:line-box column))
(tr:line-baseline column)))
(tr:layout-lines layout))))))
;; => (41.875 64.0
;; (("日本語の" 20.9375 20.9375 31.40625)
;; ("Lisp入門" 0.0 20.9375 10.46875)))
Each column's box is 64 units tall, the :width, and as wide as the line
height of the fonts on it, 20.94. The first column is on the right, from x
20.94. "Lisp" is set
sideways at the top of the second column.
Upright and sideways
How each character is set comes from its Unicode Vertical_Orientation
property (UTR #50):
- Upright. CJK ideographs, kana, hangul, full-width forms and other
characters whose orientation is upright stand upright. They are shaped
top to bottom, so the font's vertical forms (its
vertfeature) apply: the ideographic comma and full stop move to the top right, brackets turn. Their runs have the direction:ttb. - Sideways. Latin, Arabic, Hebrew and the other characters whose
orientation is rotated are turned 90° clockwise, and their glyphs have
glyph-rotated-ptrue. Their runs have the direction:ltr(or:rtl).
Fonts with vertical metrics (vhea and vmtx tables) and a vert feature
give the best results. Droid Sans Fallback and Noto Sans CJK have both.
Columns
In a vertical layout the roles of the axes swap:
| Horizontal text | Vertical text | |
|---|---|---|
| A line is | a line, stacked downwards | a column, stacked right to left |
:width is |
the line length | the column height |
layout-width |
the line length | the total width of the columns |
layout-height |
the total height of the lines | the column length |
line-box |
the layout's width by the line's height | the column: its width by the layout's height |
line-content |
the stretch along x the text takes up | the stretch along y the text takes up |
line-baseline |
the y of the baseline | the x of the column's central baseline |
run-box |
the run's stretch along x | the run's stretch along y |
glyph-advance |
along x | along y |
:align works along the column: :start and :left put text at the top,
:end and :right at the bottom, and :center in the middle. Columns read
top to bottom whatever the script, so line-direction is :ltr for every
column. Tabs, :max-lines and :ellipsis work as they do in horizontal
text, with columns counting as lines. The ellipsis is set upright, and
takes its fonts from the last character's fallback list: Droid Sans
Fallback has no "…", so give it a fallback that has one.
Drawing vertical text
An upright glyph is drawn like any glyph: its outline, in font orientation,
goes at glyph-x and glyph-y with y flipped. Its origin is placed so that
its horizontal advance is centered on the column's central baseline, and at
the height in its cell that the font's vertical metrics give it.
A rotated glyph is turned 90° clockwise about its origin: the font's x axis runs down the column and its y axis to the right. Its origin is on a baseline placed so the glyph's em box is centered in the column. Coordinates and Units has the formulas. The raster and atlas backends draw rotated glyphs turned; a distance-field or Slug renderer turns the glyph's quad.
Carets and selections
Hit testing works along the columns:
caret-positionreturns the caret's y and the column's left and right edges;caret-segmentreturns a horizontal bar across the column.hit-testpicks the column by x and the character by y.selection-rectanglesreturns pieces of columns.move-caretmoves along a column with:upand:down, and between columns with:leftand:right, keeping the height as its goal.
(tr:caret-position layout 2)
;; => 32.0, 20.9375, 41.875: y 32, across the first column
Not covered yet
- Characters whose orientation is "transformed rotated" (
Tr) are shaped upright. One the font has no vertical form for stands upright rather than turning. - Short horizontal runs inside a column (tate-chū-yoko), such as two-digit numbers, are not set specially; they turn sideways like other Latin text.