diff --git a/doc/concept.md b/doc/concept.md index 51880867..b31ffecc 100644 --- a/doc/concept.md +++ b/doc/concept.md @@ -613,7 +613,7 @@ A truncated table describing style properties applied to the desired ranges is s ## Itemization -This stage breaks the paragraph into runs that are suitable for shaping, selects appropriate fonts and maps each character to its nominal glyph identifier. +This stage breaks the paragraph into runs that are suitable for shaping, selects appropriate fonts and maps each character to its nominal glyph identifier. The following table shows the sample text broken into items with assigned fonts and nominal glyph identifiers. Each item is identified by a number. @@ -1048,7 +1048,7 @@ The following table shows the sample text broken into items with assigned fonts ## Shaping -This stage applies font, script and language specific processing rules, transforming each glyph run using substitutions and positioning adjustments. +This stage applies font, script and language specific processing rules, transforming each glyph run using substitutions and positioning adjustments. The following table shows the results of shaping, including substitutions and computed advances. Substituted glyphs are underlined. These substitutions provide the appropriate forms for Arabic cursive joining. diff --git a/doc/design.md b/doc/design.md index 2a1bd7b0..d810307e 100644 --- a/doc/design.md +++ b/doc/design.md @@ -1,14 +1,14 @@ ## Typography is the new black High quality typography, once the domain of static layout generators such as TeX -and derivatives, has commanded increasing significance in the last decade among -real time text engines and as such has received long needed resources and +and derivatives, has commanded increasing significance in the last decade among +real time text engines and as such has received long needed resources and attention from specification groups, web browser developers and platform -vendors. These efforts have reinvigorated the landscape, producing more +vendors. These efforts have reinvigorated the landscape, producing more sophisticated text APIs, new OpenType specifications, increased investment in font production technologies and a wide corpus of beautiful, comprehensive fonts supporting modern features. Perhaps more importantly, there has been a strong -focus on extending global access to computing through both more robust font +focus on extending global access to computing through both more robust font fallback systems and Google's ever-expanding collection of Noto fonts supporting world-wide scripts and languages. @@ -19,17 +19,17 @@ limited to platform specific applications, requiring cross-platform code (or eve cross-platform toolkits) to specialize their text rendering implementations for each supported operating system. An increasingly popular option to side-step this problem is to use an abstraction wrapping an embedded web browser such as Electron. This -has advantages if your application is already using a wide range of web technologies, +has advantages if your application is already using a wide range of web technologies, but becomes a large, complicated, overbearing dependency otherwise. In addition, while platform specific text engines and web browsers consist of high quality, -well-tested code produced by incredibly talented developers, they are all ultimately large +well-tested code produced by incredibly talented developers, they are all ultimately large and complex codebases implemented in C++ which is a fundamentally unsafe language. The Rust language has proven to be a high performance, safe alternative to C++. Given the platform specific nature of current text engines, and the unsafe implementation language, the obvious course of action is to build a new, cross-platform, open source text -layout engine in Rust. +layout engine in Rust. ## Design overview @@ -43,8 +43,8 @@ domain. As the author of swash, a new crate providing font parsing and complex t my goal is to bridge the two, building a text layout engine that is based on the swash primitives and exposes the piet text API. -Rich text layout is a complex process involving cross-cutting concerns across a wide -swath of both the Unicode and OpenType specifications interleaved with design intent, +Rich text layout is a complex process involving cross-cutting concerns across a wide +swath of both the Unicode and OpenType specifications interleaved with design intent, available resources, internationalization considerations, and performance. Broadly, the process can be represented by a pipeline consisting of the following phases: @@ -56,16 +56,16 @@ runs later in the pipeline. * Itemization: splits a paragraph into runs that are appropriate for shaping. This takes Unicode scripts, locales, BiDi levels, fonts and other text attributes into account. -* Font selection/fallback: selects an appropriate font for each run based on desired +* Font selection/fallback: selects an appropriate font for each run based on desired font attributes, script, locale and character coverage. Ideally, this will select the font specified by the user, but will prioritize selecting for appropriate coverage and readable text (no tofu). This stage can break runs produced by itemization if necessary. -* Shaping: converts each run of characters into a sequence of positioned glyphs using +* Shaping: converts each run of characters into a sequence of positioned glyphs using the selected font and based on writing system rules and selected features. This will be provided by the swash crate. -* Line breaking: breaks runs to fit within some desired maximum extent based on the +* Line breaking: breaks runs to fit within some desired maximum extent based on the Unicode Line Breaking Algorithm (UAX #14). Reorders glyph runs per-line according to the previously computed BiDi levels. Computes final layout of lines and glyphs. @@ -96,7 +96,7 @@ colors for underline and strikeout strokes. ## Further considerations There exist some nice-to-have layout features that are out of scope for the current development -cycle of this project-- specifically, more sophisticated segmentation using a +cycle of this project-- specifically, more sophisticated segmentation using a dictionary based approach for languages such as Thai and shaper/dictionary driven hyphenation and justification. diff --git a/fontique/src/script.rs b/fontique/src/script.rs index 555a83d3..3bbb6d80 100644 --- a/fontique/src/script.rs +++ b/fontique/src/script.rs @@ -254,5 +254,5 @@ pub const SCRIPT_SAMPLES: &[(Script, &str)] = &[ (Script(*b"Xsux"), "𒀀𒀁𒀂𒀃𒀄𒀅𒀆𒀇𒀈𒀉𒀊𒀋𒀌𒀍𒀎𒀏"), (Script(*b"Yezi"), "𐺀𐺁𐺂𐺃𐺄𐺅𐺆𐺇𐺈𐺉𐺊𐺋𐺌𐺍𐺎𐺏"), (Script(*b"Yiii"), "ꀀꀁꀂꀃꀄꀅꀆꀇꀈꀉꀊꀋꀌꀍꀎꀏ"), - (Script(*b"Zanb"), "𑨀\u{11a01}\u{11a02}\u{11a03}\u{11a04}\u{11a05}\u{11a06}\u{11a07}\u{11a08}\u{11a09}\u{11a0a}𑨋𑨌𑨍𑨎𑨏"), + (Script(*b"Zanb"), "𑨀\u{11a01}\u{11a02}\u{11a03}\u{11a04}\u{11a05}\u{11a06}\u{11a07}\u{11a08}\u{11a09}\u{11a0a}𑨋𑨌𑨍𑨎𑨏"), ]; diff --git a/parley/src/layout/cursor.rs b/parley/src/layout/cursor.rs index ca3dd5c7..2d2c437a 100644 --- a/parley/src/layout/cursor.rs +++ b/parley/src/layout/cursor.rs @@ -531,7 +531,7 @@ impl Selection { /// visual order. /// /// If `extend` is `true` then the current anchor will be retained, - /// otherwise the new selection will be collapsed. + /// otherwise the new selection will be collapsed. #[must_use] pub fn previous_visual( &self, @@ -552,7 +552,7 @@ impl Selection { /// Returns a new selection with the focus moved to the next word. /// /// If `extend` is `true` then the current anchor will be retained, - /// otherwise the new selection will be collapsed. + /// otherwise the new selection will be collapsed. #[must_use] pub fn next_word(&self, layout: &Layout, extend: bool) -> Self { self.maybe_extend(self.focus.next_word(layout), extend) @@ -561,7 +561,7 @@ impl Selection { /// Returns a new selection with the focus moved to the previous word. /// /// If `extend` is `true` then the current anchor will be retained, - /// otherwise the new selection will be collapsed. + /// otherwise the new selection will be collapsed. #[must_use] pub fn previous_word(&self, layout: &Layout, extend: bool) -> Self { self.maybe_extend(self.focus.previous_word(layout), extend) @@ -583,7 +583,7 @@ impl Selection { /// current line. /// /// If `extend` is `true` then the current anchor will be retained, - /// otherwise the new selection will be collapsed. + /// otherwise the new selection will be collapsed. #[must_use] pub fn line_start(&self, layout: &Layout, extend: bool) -> Self { if let Some(line) = self.focus.path.line(layout) { @@ -600,7 +600,7 @@ impl Selection { /// current line. /// /// If `extend` is `true` then the current anchor will be retained, - /// otherwise the new selection will be collapsed. + /// otherwise the new selection will be collapsed. #[must_use] pub fn line_end(&self, layout: &Layout, extend: bool) -> Self { if let Some(line) = self.focus.path.line(layout) { @@ -621,7 +621,7 @@ impl Selection { /// current horizontal position will be maintained. /// /// If `extend` is `true` then the current anchor will be retained, - /// otherwise the new selection will be collapsed. + /// otherwise the new selection will be collapsed. #[must_use] pub fn next_line(&self, layout: &Layout, extend: bool) -> Self { self.move_lines(layout, 1, extend) @@ -631,7 +631,7 @@ impl Selection { /// current horizontal position will be maintained. /// /// If `extend` is `true` then the current anchor will be retained, - /// otherwise the new selection will be collapsed. + /// otherwise the new selection will be collapsed. #[must_use] pub fn previous_line(&self, layout: &Layout, extend: bool) -> Self { self.move_lines(layout, -1, extend) @@ -645,7 +645,7 @@ impl Selection { /// toward next lines. /// /// If `extend` is `true` then the current anchor will be retained, - /// otherwise the new selection will be collapsed. + /// otherwise the new selection will be collapsed. #[must_use] pub fn move_lines(&self, layout: &Layout, delta: isize, extend: bool) -> Self { if delta == 0 { diff --git a/parley/src/layout/line/mod.rs b/parley/src/layout/line/mod.rs index 5b7a2732..d574b791 100644 --- a/parley/src/layout/line/mod.rs +++ b/parley/src/layout/line/mod.rs @@ -110,12 +110,12 @@ pub struct LineMetrics { /// Minimum coordinate in the direction orthogonal to line /// direction. /// - /// For horizontal text, this would be the top of the line. + /// For horizontal text, this would be the top of the line. pub min_coord: f32, /// Maximum coordinate in the direction orthogonal to line /// direction. /// - /// For horizontal text, this would be the bottom of the line. + /// For horizontal text, this would be the bottom of the line. pub max_coord: f32, } diff --git a/parley/src/swash_convert.rs b/parley/src/swash_convert.rs index acf911ea..6f0530ea 100644 --- a/parley/src/swash_convert.rs +++ b/parley/src/swash_convert.rs @@ -47,22 +47,22 @@ pub fn synthesis_to_swash(synthesis: fontique::Synthesis) -> swash::Synthesis { #[rustfmt::skip] const SCRIPT_TAGS: [[u8; 4]; 157] = [ - *b"Adlm", *b"Aghb", *b"Ahom", *b"Arab", *b"Armi", *b"Armn", *b"Avst", *b"Bali", *b"Bamu", - *b"Bass", *b"Batk", *b"Beng", *b"Bhks", *b"Bopo", *b"Brah", *b"Brai", *b"Bugi", *b"Buhd", - *b"Cakm", *b"Cans", *b"Cari", *b"Cham", *b"Cher", *b"Chrs", *b"Copt", *b"Cprt", *b"Cyrl", - *b"Deva", *b"Diak", *b"Dogr", *b"Dsrt", *b"Dupl", *b"Egyp", *b"Elba", *b"Elym", *b"Ethi", - *b"Geor", *b"Glag", *b"Gong", *b"Gonm", *b"Goth", *b"Gran", *b"Grek", *b"Gujr", *b"Guru", - *b"Hang", *b"Hani", *b"Hano", *b"Hatr", *b"Hebr", *b"Hira", *b"Hluw", *b"Hmng", *b"Hmnp", - *b"Hung", *b"Ital", *b"Java", *b"Kali", *b"Kana", *b"Khar", *b"Khmr", *b"Khoj", *b"Kits", - *b"Knda", *b"Kthi", *b"Lana", *b"Laoo", *b"Latn", *b"Lepc", *b"Limb", *b"Lina", *b"Linb", - *b"Lisu", *b"Lyci", *b"Lydi", *b"Mahj", *b"Maka", *b"Mand", *b"Mani", *b"Marc", *b"Medf", - *b"Mend", *b"Merc", *b"Mero", *b"Mlym", *b"Modi", *b"Mong", *b"Mroo", *b"Mtei", *b"Mult", - *b"Mymr", *b"Nand", *b"Narb", *b"Nbat", *b"Newa", *b"Nkoo", *b"Nshu", *b"Ogam", *b"Olck", - *b"Orkh", *b"Orya", *b"Osge", *b"Osma", *b"Palm", *b"Pauc", *b"Perm", *b"Phag", *b"Phli", - *b"Phlp", *b"Phnx", *b"Plrd", *b"Prti", *b"Rjng", *b"Rohg", *b"Runr", *b"Samr", *b"Sarb", - *b"Saur", *b"Sgnw", *b"Shaw", *b"Shrd", *b"Sidd", *b"Sind", *b"Sinh", *b"Sogd", *b"Sogo", - *b"Sora", *b"Soyo", *b"Sund", *b"Sylo", *b"Syrc", *b"Tagb", *b"Takr", *b"Tale", *b"Talu", - *b"Taml", *b"Tang", *b"Tavt", *b"Telu", *b"Tfng", *b"Tglg", *b"Thaa", *b"Thai", *b"Tibt", - *b"Tirh", *b"Ugar", *b"Vaii", *b"Wara", *b"Wcho", *b"Xpeo", *b"Xsux", *b"Yezi", *b"Yiii", - *b"Zanb", *b"Zinh", *b"Zyyy", *b"Zzzz", + *b"Adlm", *b"Aghb", *b"Ahom", *b"Arab", *b"Armi", *b"Armn", *b"Avst", *b"Bali", *b"Bamu", + *b"Bass", *b"Batk", *b"Beng", *b"Bhks", *b"Bopo", *b"Brah", *b"Brai", *b"Bugi", *b"Buhd", + *b"Cakm", *b"Cans", *b"Cari", *b"Cham", *b"Cher", *b"Chrs", *b"Copt", *b"Cprt", *b"Cyrl", + *b"Deva", *b"Diak", *b"Dogr", *b"Dsrt", *b"Dupl", *b"Egyp", *b"Elba", *b"Elym", *b"Ethi", + *b"Geor", *b"Glag", *b"Gong", *b"Gonm", *b"Goth", *b"Gran", *b"Grek", *b"Gujr", *b"Guru", + *b"Hang", *b"Hani", *b"Hano", *b"Hatr", *b"Hebr", *b"Hira", *b"Hluw", *b"Hmng", *b"Hmnp", + *b"Hung", *b"Ital", *b"Java", *b"Kali", *b"Kana", *b"Khar", *b"Khmr", *b"Khoj", *b"Kits", + *b"Knda", *b"Kthi", *b"Lana", *b"Laoo", *b"Latn", *b"Lepc", *b"Limb", *b"Lina", *b"Linb", + *b"Lisu", *b"Lyci", *b"Lydi", *b"Mahj", *b"Maka", *b"Mand", *b"Mani", *b"Marc", *b"Medf", + *b"Mend", *b"Merc", *b"Mero", *b"Mlym", *b"Modi", *b"Mong", *b"Mroo", *b"Mtei", *b"Mult", + *b"Mymr", *b"Nand", *b"Narb", *b"Nbat", *b"Newa", *b"Nkoo", *b"Nshu", *b"Ogam", *b"Olck", + *b"Orkh", *b"Orya", *b"Osge", *b"Osma", *b"Palm", *b"Pauc", *b"Perm", *b"Phag", *b"Phli", + *b"Phlp", *b"Phnx", *b"Plrd", *b"Prti", *b"Rjng", *b"Rohg", *b"Runr", *b"Samr", *b"Sarb", + *b"Saur", *b"Sgnw", *b"Shaw", *b"Shrd", *b"Sidd", *b"Sind", *b"Sinh", *b"Sogd", *b"Sogo", + *b"Sora", *b"Soyo", *b"Sund", *b"Sylo", *b"Syrc", *b"Tagb", *b"Takr", *b"Tale", *b"Talu", + *b"Taml", *b"Tang", *b"Tavt", *b"Telu", *b"Tfng", *b"Tglg", *b"Thaa", *b"Thai", *b"Tibt", + *b"Tirh", *b"Ugar", *b"Vaii", *b"Wara", *b"Wcho", *b"Xpeo", *b"Xsux", *b"Yezi", *b"Yiii", + *b"Zanb", *b"Zinh", *b"Zyyy", *b"Zzzz", ];