/** * Glyph orientation in vertical text (`layout.writingMode: 'vertical-rl'`), * one helper shared by every renderer, so the canvas, the PDF and the HTML * output turn the same characters the same way. * * The flow of a vertical page is laid out as horizontal lines in a frame * turned a quarter turn clockwise (`VDTPage.flow`). Text painted there * "as is" comes out turned 90° clockwise — which is right for Latin words * and long numbers (sideways, UAX #50 `R`) and wrong for Chinese * characters, which stand upright, each in its own 1 em cell, turned back * about the cell's centre. Punctuation takes the font's vertical form * (OpenType `vert`) when a renderer can get it, else a fallback. * * Classes follow Unicode's `Vertical_Orientation` (UAX #50, data 18.0), * with the Chinese rules on top (clreq Appendix A, GB/T 15834—2011 §5.2): * - pause and stop marks (、。,.!?) are never turned. A Simplified * (mainland) font sets them in the upper right of the cell through * `vert` (、。,. in the top-right corner, !?:; in the right half); * Taiwan and Hong Kong fonts centre them and have no such form (their * U+FE10–FE16 are the mainland shapes, so the vertical presentation * forms must not be substituted there), and leave :; upright too. * Japanese text (the `japan` region) sets 、。,. in the corner as the * mainland does, !? upright in the centre of the cell (JLReq §3.1.10; * a Japanese font has no vertical form for them) and turns :; (UAX #50 * `Tr`, the vertical form of JIS X 4051). * - brackets and quotes take the vertical form, which is the horizontal * glyph turned about the em box's centre when the font gives none; * “ ” ‘ ’ in mainland text read as the corner brackets 『』「」 * (UAX #50 §3.2.4, the Hans vertical convention). Japanese “ ” are * horizontal marks: vertical text sets 〝 〟 in their place (JLReq * §3.1.1; ja-typography §5), whose vertical forms Japanese fonts have * where they have none for “ ”; ‘ ’ keep their own. * - small kana (ぁ っ ゃ ァ ッ ㇰ…, UAX #50 `Tu`) take their vertical form in * Japanese text, which sits up and to the right of the horizontal one * (JLReq §2.1.2), or move there without one; Chinese text leaves every * `Tu` character upright as it is. * - dashes, ellipses, the wave dash and the interpunct are turned about * the em box's centre (Noto CJK gives —— a vertical form only with * `fwid`): a dash is stretched to fill its cell. The mainland interpunct * takes half a cell (clreq §5.1), the Taiwan, Hong Kong and Japanese * one a whole cell (JLReq §3.1.2: ・ is a full em). * - an apostrophe or an interpunct inside a Latin word ("don’t", "l·l") * runs sideways with the word, as the composer keeps it in the word. * * The measurer and every renderer read the same runs ({@link * verticalRuns}): what stands in a cell advances its cell (one em, half an * em for the mainland interpunct), what runs sideways its horizontal width. * Japanese text also sets a pair of exclamation and question marks (!! !? * ?! ?? and !! !? ?! ??) side by side in one cell (JLReq §3.1.10). */ import type { CjkRegion } from './types.js'; /** How a character is set in a vertical line. * - `upright`: standing, centred in its cell (Han, kana, hangul, * fullwidth letters, and the pause marks of Taiwan and Hong Kong). * - `sideways`: turned 90° clockwise with the run it belongs to, keeping * its horizontal advance (Latin, digits, most symbols). * - `rotate`: turned 90° clockwise about the centre of its em box, in a * cell of its own (dashes, ellipses, the interpunct). * - `alternate`: the font's vertical form (`vert`); without one, the * `fallback`: `rotate` (brackets, quotes) or `corner` (a mainland * pause or stop mark moved to the top-right quadrant of its cell). * - `tcy`: tate-chu-yoko (縱中橫): a short number (`cjk.uprightDigits`) * or a `:tcy[…]` run set side by side in one upright cell, squeezed * across when wider than the cell. */ export type VerticalOrientationKind = 'upright' | 'sideways' | 'rotate' | 'alternate' | 'tcy'; export interface VerticalGlyph { orient: VerticalOrientationKind; /** `alternate` only: what a renderer without the font's vertical forms * does instead: turn the glyph (`rotate`), or move the upright glyph by * `offset` in its cell (`corner`: a mainland pause mark to the top * right, a Japanese small kana up and to the right). */ fallback?: 'rotate' | 'corner'; /** The character a fallback paints instead of this one (“ → 『 in * mainland text: the Hans vertical quote is the corner bracket). */ substitute?: string; /** The text every renderer paints in place of the grapheme (or of the * `tcy` cell's text), before it looks for the font's vertical form: * Japanese “ ” are set as 〝 〟; a Japanese pair of full-width !? in one * cell as the half-width !? that fit it. The text read and copied stays * the grapheme. Absent outside the `japan` region. */ paintAs?: string; /** `rotate`: stretch the turned glyph along the line to fill its cell * (a dash narrower than its em). */ stretch?: boolean; /** `corner` fallback: where the upright glyph moves in its cell, in ems * (`x` across the column, to the right; `y` along it, negative up). * {@link CORNER_OFFSET_EM} when absent. */ offset?: { x: number; y: number; }; } /** Unicode `Vertical_Orientation` (UAX #50): `U` upright, `R` rotated, * `Tu` / `Tr` a vertical glyph, else upright / rotated. */ export type UaxVerticalOrientation = 'U' | 'R' | 'Tu' | 'Tr'; /** A code point's Unicode `Vertical_Orientation`. */ export declare function uaxVerticalOrientation(cp: number): UaxVerticalOrientation; /** Whether `text` holds a mark a vertical line turns in a cell of its own * (`rotate`: a dash, an ellipsis, an interpunct, a wave dash), which a * browser setting the text vertically advances by its horizontal width. */ export declare function holdsTurnedMark(text: string): boolean; /** The dashes of `text` a vertical line stretches to fill their cell * (`VerticalGlyph.stretch`), each once. */ export declare function stretchedDashesOf(text: string): string[]; /** Where a Japanese small kana moves when the font gives no vertical form, * in ems of its cell (right and up): the shift of the `vert` glyphs' * ink from the horizontal ones in Noto Serif JP and Noto Sans JP, Shippori * Mincho, BIZ UDMincho and Zen Old Mincho: 0.09–0.25 em right and * 0.06–0.26 em up (0.15 and 0.14 in Noto Serif JP). */ export declare const SMALL_KANA_OFFSET_EM: { x: number; y: number; }; /** * How a grapheme is set in a vertical line of `region`'s Chinese or * Japanese (see the module comment). Reads the grapheme's first code * point; a sequence with a combining mark or a variation selector follows * its base. */ export declare function verticalOrientation(grapheme: string, region?: CjkRegion): VerticalGlyph; /** Whether a grapheme stands in a cell of its own in vertical text (every * orientation but `sideways`). */ export declare function isVerticalCell(grapheme: string, region?: CjkRegion): boolean; /** Where a mainland 、。,. moves when the font gives no vertical form, in * ems of the cell: right and up (a horizontal 。 sits in the bottom-left * quadrant, the vertical one in the top-right). Measured against the * `vert` glyphs of Noto Serif SC: within 0.07 em for 、。,.. !? and :; * carry their own `offset` (half an em to the right, 0.08 and 0.22 em up), * within 0.02 em of the font's. Japanese 、。,. use it too: the `vert` * glyphs of Noto Serif JP move 0.59–0.62 em right and 0.60–0.65 em up, * those of Shippori Mincho 0.61–0.65 and 0.62–0.66. */ export declare const CORNER_OFFSET_EM: { x: number; y: number; }; /** The size of a character's cell in a vertical line, in ems: half an em * for the mainland interpunct (· ・, clreq §5.1), one em for * every other character that stands in a cell (the Japanese ・ too, * JLReq §3.1.2). `cls`, when the caller has * it, is the grapheme's `cjkClassOf`. */ export declare function verticalCellEms(grapheme: string, region?: CjkRegion, cls?: import("./measure/cjkClasses.js").CjkClass): number; /** One run of a vertical line: consecutive graphemes set alike. A * `sideways` run holds a whole Latin word or number; every other run is * one grapheme in a cell `cell` ems long. */ export interface VerticalRun { text: string; glyph: VerticalGlyph; /** The cell's length along the line, in ems (not on a sideways run). */ cell?: number; } /** The numbers up to how many ASCII digits are set side by side in one * upright cell (tate-chu-yoko) in vertical text: `cjk.uprightDigits`, 0 * (none), 2 (the default), 3 or 4. */ export type UprightDigits = 0 | 2 | 3 | 4; /** * The short numbers of `graphemes` a vertical line may stand in one cell, * where they start, with their length: every run of at most `digits` ASCII * digits, whole (a longer run is set sideways, never split), that is not * part of a word (no Latin letter touches it: `A4`, `mp3`, `3D` stay * sideways) nor of a number with digit grouping or a decimal point * (`10,000`, `3.14`: a `,` or `.` between it and another digit). Empty * when `digits` is 0. {@link uprightDigitRuns} then leaves out those that * run with Latin text. */ export declare function uprightDigitCandidates(graphemes: readonly string[], digits: number): Map; /** * Whether the numbers of `graphemes` run with Latin text: `(from, to)` * tells it for the digits `graphemes[from, to)`, Latin text on both sides. * On each side the look goes past any spaces, digits (another number), * punctuation marks of a sideways run (UAX #50 `R`: `, . : ; ( ) ' " - /` * and the like) and the marks of {@link LOOKED_PAST}; the side is Latin * when the first other grapheme is a letter set sideways (Latin, Greek, * Cyrillic), and not when a Chinese character or mark, a sign that stands * upright (× © ℃) or the start or end of the text comes first: the colons * of `上午12:30:45开会` and the brackets of `见图(3)` lead to Chinese text, * those of `at 12:30 pm` and `said (7) of` to words. A text cut out of a * longer one so never reads a number as Latin that the whole text would * stand upright: its look stops sooner, on the same graphemes. Each side * is read once for the whole text (one pass each way). */ export declare function latinReader(graphemes: readonly string[], region?: CjkRegion): (from: number, to: number) => boolean; /** * Where the automatic tate-chu-yoko cells of `graphemes` start, with their * length: the short numbers of {@link uprightDigitCandidates} but those * that run with Latin text ({@link latinReader}): a number between two * Latin words (`printed in 49 and 32 copies`) follows the sentence it is * part of, which is set sideways (#222). A number next to a Chinese * character, or alone between Chinese text, stands upright. */ export declare function uprightDigitRuns(graphemes: readonly string[], digits: number, region?: CjkRegion): Map; /** * Whether `graphemes[i, i + 2)` is a pair of exclamation and question marks * Japanese vertical text sets side by side in one upright cell (JLReq * §3.1.10; ja-typography §8): !! !? ?! ?? or !! !? ?! ??, exactly two * (a third mark on either side leaves all of them as they are). Half-width * marks pair only outside a Latin run: no letter, digit or other mark set * sideways touches them (`Wow!!`, `(!?)` and `12!!` run sideways with their * text); a space may. The composer reads its units by the same rule * (`cjkCompose.ts`), so a line paints the cells it measured. */ export declare function isUprightMarkPair(graphemes: readonly string[], i: number, region: CjkRegion): boolean; /** The one-cell glyph of a mark pair (see {@link isUprightMarkPair}): a * full-width pair is painted with the half-width marks, which fit the * cell where the full-width ones would be squeezed to half their width. */ export declare function markPairGlyph(pair: string): VerticalGlyph; /** Cut `text` into the runs a vertical line paints and measures: sideways * graphemes joined into runs, every other grapheme a cell of its own. An * apostrophe or interpunct between two letters of a Latin word runs * sideways with it (see `isWordInnerMark`), as the composer measures it. * With `uprightDigits` (`cjk.uprightDigits`), each short number * ({@link uprightDigitRuns}) is one `tcy` cell; in Japanese text, so is * each pair of exclamation and question marks ({@link * isUprightMarkPair}). */ export declare function verticalRuns(graphemes: readonly string[], region?: CjkRegion, uprightDigits?: number): VerticalRun[]; /** How the author set a run of vertical text apart (`VDTLineSegment.tcy`, * `VDTLineSegment.orientation`): `'tcy'` (`:tcy[…]`), one upright cell; * `'upright'` (`:upright[…]`), every character upright in a cell of its * own; `'sideways'` (`:sideways[…]`), the whole run turned. */ export type ForcedOrientation = 'tcy' | 'upright' | 'sideways'; /** The runs of a text whose orientation the author forced (see * {@link ForcedOrientation}): one `tcy` cell, one upright cell per * grapheme, or one sideways run. A cell of two full-width !? in * Japanese text (`region`; the composer sets a pair in one, see {@link * isUprightMarkPair}) is painted with the half-width marks. */ export declare function forcedVerticalRuns(graphemes: readonly string[], orient: ForcedOrientation, region?: CjkRegion): VerticalRun[]; /** The orientation a segment's author forced, if any. */ export declare function segmentOrientation(seg: { tcy?: boolean; orientation?: 'upright' | 'sideways'; }): ForcedOrientation | undefined; /** Whether `text` holds a character that stands in a cell of its own in * vertical text (see {@link verticalRuns}), a short number included when * `uprightDigits` may set it in a cell (the measurer passes the document's * `cjk.uprightDigits`, as the painters do): any candidate of * {@link uprightDigitCandidates}, also one that runs with Latin text, so a * paragraph holding one is measured by the formatted path, which reads * each number with its paragraph (`sidewaysNumberSpans`). ASCII letters * never do; in Japanese text (`region`), a pair of half-width marks set * in one cell does ({@link isUprightMarkPair}). */ export declare function holdsVerticalCell(text: string, uprightDigits: number, region?: CjkRegion): boolean; //# sourceMappingURL=writingMode.d.ts.map