mirror of
https://github.com/storytold/figcraft.git
synced 2026-10-30 05:16:56 -06:00
M4: text behaviour suite: break classes as tables, rustfmt
This commit is contained in:
@@ -103,11 +103,23 @@ pub fn insert(s: &mut Session, text: &str) -> Result<()> {
|
||||
/// ends where the script changes (Han, hiragana, katakana and Hangul runs are words of their own in
|
||||
/// text without spaces). Combining marks and voicing marks belong to the char before them.
|
||||
fn word_class(chars: &[char], mut i: usize) -> u8 {
|
||||
while i > 0 && chars.get(i).is_some_and(|c| matches!(*c as u32, 0x0300..=0x036F | 0x1AB0..=0x1AFF | 0x1DC0..=0x1DFF | 0x20D0..=0x20FF | 0x3099..=0x309A | 0xFE20..=0xFE2F)) {
|
||||
while i > 0
|
||||
&& chars.get(i).is_some_and(
|
||||
|c| matches!(*c as u32, 0x0300..=0x036F | 0x1AB0..=0x1AFF | 0x1DC0..=0x1DFF | 0x20D0..=0x20FF | 0x3099..=0x309A | 0xFE20..=0xFE2F),
|
||||
)
|
||||
{
|
||||
i -= 1;
|
||||
}
|
||||
match chars.get(i).copied() {
|
||||
Some('\u{3005}' | '\u{3006}' | '\u{3007}' | '\u{3400}'..='\u{4DBF}' | '\u{4E00}'..='\u{9FFF}' | '\u{F900}'..='\u{FAFF}' | '\u{20000}'..='\u{3FFFF}') => 2,
|
||||
Some(
|
||||
'\u{3005}'
|
||||
| '\u{3006}'
|
||||
| '\u{3007}'
|
||||
| '\u{3400}'..='\u{4DBF}'
|
||||
| '\u{4E00}'..='\u{9FFF}'
|
||||
| '\u{F900}'..='\u{FAFF}'
|
||||
| '\u{20000}'..='\u{3FFFF}',
|
||||
) => 2,
|
||||
Some('\u{3041}'..='\u{309F}') => 3,
|
||||
Some('\u{30A0}'..='\u{30FF}' | '\u{31F0}'..='\u{31FF}' | '\u{FF66}'..='\u{FF9F}') => 4,
|
||||
Some('\u{1100}'..='\u{11FF}' | '\u{3130}'..='\u{318F}' | '\u{AC00}'..='\u{D7AF}') => 5,
|
||||
|
||||
@@ -340,4 +340,3 @@ fn a_cluster_is_shaped_with_one_face() {
|
||||
assert_eq!(faces.len(), 1, "{s:?}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+16
-11
@@ -21,19 +21,24 @@ enum Class {
|
||||
Other,
|
||||
}
|
||||
|
||||
/// Opening brackets and quotes (line-end prohibited).
|
||||
const OPEN: &str = "([{‘“〈《「『【〔〖〘〚〝([{「";
|
||||
/// Closing brackets, quotes and punctuation, iteration marks, small kana and the prolonged sound
|
||||
/// mark (line-start prohibited; the small katakana extensions U+31F0..U+31FF are a range below).
|
||||
const CLOSE: &str =
|
||||
")]},.:;!?’”‥…‼⁇⁈⁉、。々〉》」』】〕〗〙〛〜〞〟〻ぁぃぅぇぉっゃゅょゎゕゖゝゞ゠ァィゥェォッャュョヮヵヶ・ーヽヾ!),.:;?]}。」、・ー";
|
||||
|
||||
fn class(c: char) -> Class {
|
||||
if c.is_ascii_alphanumeric() {
|
||||
return Class::Other;
|
||||
}
|
||||
if OPEN.contains(c) {
|
||||
return Class::Open;
|
||||
}
|
||||
if CLOSE.contains(c) || ('\u{31F0}'..='\u{31FF}').contains(&c) {
|
||||
return Class::Close;
|
||||
}
|
||||
match c {
|
||||
'(' | '[' | '{' | '\u{2018}' | '\u{201C}' | '\u{3008}' | '\u{300A}' | '\u{300C}' | '\u{300E}' | '\u{3010}' | '\u{3014}'
|
||||
| '\u{3016}' | '\u{3018}' | '\u{301A}' | '\u{301D}' | '\u{FF08}' | '\u{FF3B}' | '\u{FF5B}' | '\u{FF62}' => Class::Open,
|
||||
')' | ']' | '}' | ',' | '.' | ':' | ';' | '!' | '?' | '\u{2019}' | '\u{201D}' | '\u{2025}' | '\u{2026}' | '\u{203C}'
|
||||
| '\u{2047}'..='\u{2049}' | '\u{3001}' | '\u{3002}' | '\u{3005}' | '\u{3009}' | '\u{300B}' | '\u{300D}' | '\u{300F}'
|
||||
| '\u{3011}' | '\u{3015}' | '\u{3017}' | '\u{3019}' | '\u{301B}' | '\u{301C}' | '\u{301E}' | '\u{301F}' | '\u{303B}'
|
||||
| '\u{3041}' | '\u{3043}' | '\u{3045}' | '\u{3047}' | '\u{3049}' | '\u{3063}' | '\u{3083}' | '\u{3085}' | '\u{3087}'
|
||||
| '\u{308E}' | '\u{3095}' | '\u{3096}' | '\u{309D}' | '\u{309E}' | '\u{30A0}' | '\u{30A1}' | '\u{30A3}' | '\u{30A5}'
|
||||
| '\u{30A7}' | '\u{30A9}' | '\u{30C3}' | '\u{30E3}' | '\u{30E5}' | '\u{30E7}' | '\u{30EE}' | '\u{30F5}' | '\u{30F6}'
|
||||
| '\u{30FB}' | '\u{30FC}' | '\u{30FD}' | '\u{30FE}' | '\u{31F0}'..='\u{31FF}' | '\u{FF01}' | '\u{FF09}' | '\u{FF0C}'
|
||||
| '\u{FF0E}' | '\u{FF1A}' | '\u{FF1B}' | '\u{FF1F}' | '\u{FF3D}' | '\u{FF5D}' | '\u{FF61}' | '\u{FF63}'..='\u{FF65}'
|
||||
| '\u{FF70}' => Class::Close,
|
||||
' ' | '\t' | '\u{3000}' | '\u{2002}'..='\u{200B}' => Class::Space,
|
||||
'-' | '/' | '\u{2010}' | '\u{2013}' | '\u{2014}' => Class::Hyphen,
|
||||
'\u{2E80}'..='\u{2FFF}'
|
||||
|
||||
@@ -6,17 +6,17 @@
|
||||
//! fills [`Glyph::path`]s and the editor uses [`TextLayout::caret`] / [`TextLayout::hit`].
|
||||
#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)]
|
||||
|
||||
mod breaks;
|
||||
pub mod display;
|
||||
pub mod fontdb;
|
||||
mod layout;
|
||||
mod breaks;
|
||||
mod onpath;
|
||||
|
||||
pub use breaks::grapheme_step;
|
||||
pub use fontdb::{
|
||||
Axis, CRAFT_FONTS, Coords, Face, FontDb, NamedInstance, axis_label, db, face_with_char, family_names, family_styles, find_face, no_coords,
|
||||
scan_system_fonts, system_fonts_scanned,
|
||||
};
|
||||
pub use breaks::grapheme_step;
|
||||
pub use layout::{Decoration, Glyph, Line, TextLayout, layout};
|
||||
pub use onpath::OnPath;
|
||||
|
||||
|
||||
@@ -439,7 +439,8 @@ fn type_settings(
|
||||
ui.add_space(6.0);
|
||||
let indent = common(doc, ids, |n| n.kind.text().map(|t| t.paragraph_indent.to_bits())).flatten().map(f64::from_bits);
|
||||
// Indent applies to start-aligned text only; elsewhere the field stays visible but off.
|
||||
let start_aligned = common(doc, ids, |n| n.kind.text().map(|t| t.align_h != TextAlignH::Center && t.align_h != TextAlignH::Justified)).flatten();
|
||||
let start_aligned =
|
||||
common(doc, ids, |n| n.kind.text().map(|t| t.align_h != TextAlignH::Center && t.align_h != TextAlignH::Justified)).flatten();
|
||||
ui.horizontal(|ui| {
|
||||
ui.add_enabled_ui(start_aligned != Some(false), |ui| {
|
||||
ui.add_sized(vec2(110.0, FIELD_H), egui::Label::new(egui::RichText::new(tr("Paragraph indent")).font(regular(11.0)).color(t.text)));
|
||||
|
||||
Reference in New Issue
Block a user