summaryrefslogtreecommitdiff
path: root/crates/typst-library/src/text
diff options
context:
space:
mode:
authorPeng Guanwen <pg999w@outlook.com>2023-10-17 17:14:09 +0800
committerGitHub <noreply@github.com>2023-10-17 11:14:09 +0200
commite4d9db83ea4b7b9a3003c754c80b30b87d6cd119 (patch)
treea65e58179aa33adc4bf06732697a22da3dfb643b /crates/typst-library/src/text
parenta59666369b946c3a8b62db363659cbfca35f0a26 (diff)
Automatically add spacing between CJK and Latin characters (#2334)
Diffstat (limited to 'crates/typst-library/src/text')
-rw-r--r--crates/typst-library/src/text/mod.rs12
-rw-r--r--crates/typst-library/src/text/shaping.rs17
2 files changed, 26 insertions, 3 deletions
diff --git a/crates/typst-library/src/text/mod.rs b/crates/typst-library/src/text/mod.rs
index 748d71ad..4d2f5c63 100644
--- a/crates/typst-library/src/text/mod.rs
+++ b/crates/typst-library/src/text/mod.rs
@@ -19,6 +19,7 @@ pub use self::shift::*;
use rustybuzz::Tag;
use ttf_parser::Rect;
use typst::diag::{bail, error, SourceResult};
+use typst::eval::Never;
use typst::font::{Font, FontStretch, FontStyle, FontWeight, VerticalFontMetric};
use crate::layout::ParElem;
@@ -224,6 +225,17 @@ pub struct TextElem {
#[default(Rel::one())]
pub spacing: Rel<Length>,
+ /// Whether to automatically insert spacing between CJK and Latin characters.
+ ///
+ /// ```example
+ /// #set text(cjk-latin-spacing: auto)
+ /// 第4章介绍了基本的API。
+ ///
+ /// #set text(cjk-latin-spacing: none)
+ /// 第4章介绍了基本的API。
+ /// ```
+ pub cjk_latin_spacing: Smart<Option<Never>>,
+
/// An amount to shift the text baseline by.
///
/// ```example
diff --git a/crates/typst-library/src/text/shaping.rs b/crates/typst-library/src/text/shaping.rs
index df30a9c8..1b7d9e09 100644
--- a/crates/typst-library/src/text/shaping.rs
+++ b/crates/typst-library/src/text/shaping.rs
@@ -100,9 +100,7 @@ impl ShapedGlyph {
}
pub fn is_cjk_script(&self) -> bool {
- use Script::*;
- // U+30FC: Katakana-Hiragana Prolonged Sound Mark
- matches!(self.c.script(), Hiragana | Katakana | Han) || self.c == '\u{30FC}'
+ char_is_cjk_script(self.c)
}
pub fn is_cjk_punctuation(&self) -> bool {
@@ -151,6 +149,13 @@ impl ShapedGlyph {
matches!(self.c, '\u{30FB}')
}
+ /// Whether the glyph is a western letter or number.
+ pub fn is_letter_or_number(&self) -> bool {
+ matches!(self.c.script(), Script::Latin | Script::Greek | Script::Cyrillic)
+ || matches!(self.c, '#' | '$' | '%' | '&')
+ || self.c.is_ascii_digit()
+ }
+
pub fn base_adjustability(&self, gb_style: bool) -> Adjustability {
let width = self.x_advance;
if self.is_space() {
@@ -958,6 +963,12 @@ fn language(styles: StyleChain) -> rustybuzz::Language {
rustybuzz::Language::from_str(&bcp).unwrap()
}
+pub fn char_is_cjk_script(c: char) -> bool {
+ use Script::*;
+ // U+30FC: Katakana-Hiragana Prolonged Sound Mark
+ matches!(c.script(), Hiragana | Katakana | Han) || c == '\u{30FC}'
+}
+
/// Returns true if all glyphs in `glyphs` have ranges within the range `range`.
#[cfg(debug_assertions)]
fn assert_all_glyphs_in_range(glyphs: &[ShapedGlyph], text: &str, range: Range<usize>) {