From b791aede82cc1424ba38b74200193096390ceecd Mon Sep 17 00:00:00 2001 From: PgBiel <9021226+PgBiel@users.noreply.github.com> Date: Wed, 2 Oct 2024 07:17:36 -0300 Subject: [PATCH] Adjust line number clearance (#5093) Co-authored-by: Laurenz --- crates/typst/src/layout/flow/compose.rs | 22 +++++++----- crates/typst/src/layout/flow/mod.rs | 28 +++++++++++++-- crates/typst/src/model/par.rs | 35 ++++++++++++++----- tests/ref/line-numbers-default-alignment.png | Bin 1359 -> 1362 bytes tests/ref/line-numbers-enable.png | Bin 929 -> 910 bytes tests/ref/line-numbers-page-scope.png | Bin 2206 -> 1866 bytes tests/ref/line-numbers-rtl.png | Bin 1369 -> 1365 bytes tests/ref/line-numbers-start-alignment.png | Bin 470 -> 464 bytes tests/suite/layout/line-numbers.typ | 10 +++--- 9 files changed, 69 insertions(+), 26 deletions(-) diff --git a/crates/typst/src/layout/flow/compose.rs b/crates/typst/src/layout/flow/compose.rs index 003e4e72c..6f14618ee 100644 --- a/crates/typst/src/layout/flow/compose.rs +++ b/crates/typst/src/layout/flow/compose.rs @@ -1,6 +1,8 @@ use std::num::NonZeroUsize; -use super::{distribute, Config, FlowResult, PlacedChild, Skip, Stop, Work}; +use super::{ + distribute, Config, FlowResult, LineNumberConfig, PlacedChild, Skip, Stop, Work, +}; use crate::diag::SourceResult; use crate::engine::Engine; use crate::foundations::{Content, NativeElement, Packed, Resolve, Smart}; @@ -13,7 +15,7 @@ use crate::layout::{ OuterHAlignment, PlacementScope, Point, Region, Regions, Rel, Size, }; use crate::model::{ - FootnoteElem, FootnoteEntry, LineNumberingScope, Numbering, ParLine, ParLineMarker, + FootnoteElem, FootnoteEntry, LineNumberingScope, Numbering, ParLineMarker, }; use crate::syntax::Span; use crate::utils::NonZeroExt; @@ -198,10 +200,11 @@ impl<'a, 'b> Composer<'a, 'b, '_, '_> { let mut output = insertions.finalize(self.work, self.config, inner); // Lay out per-column line numbers. - if self.config.root { + if let Some(line_config) = &self.config.line_numbers { layout_line_numbers( self.engine, self.config, + line_config, locator, self.column, &mut output, @@ -647,6 +650,7 @@ impl<'a, 'b> Insertions<'a, 'b> { fn layout_line_numbers( engine: &mut Engine, config: &Config, + line_config: &LineNumberConfig, locator: Locator, column: usize, output: &mut Frame, @@ -654,9 +658,7 @@ fn layout_line_numbers( let mut locator = locator.split(); // Reset page-scoped line numbers if currently at the first column. - if column == 0 - && ParLine::numbering_scope_in(config.shared) == LineNumberingScope::Page - { + if column == 0 && line_config.scope == LineNumberingScope::Page { let reset = layout_line_number_reset(engine, config, &mut locator)?; output.push_frame(Point::zero(), reset); } @@ -711,9 +713,11 @@ fn layout_line_numbers( .resolve(config.shared) }; - // Compute the marker's horizontal position. Will be adjusted based on - // the maximum number width later. - let clearance = marker.number_clearance.resolve(config.shared); + // Determine how much space to leave between the column and the number. + let clearance = match marker.number_clearance { + Smart::Auto => line_config.default_clearance, + Smart::Custom(rel) => rel.resolve(config.shared), + }; // Compute the base X position. let x = match margin { diff --git a/crates/typst/src/layout/flow/mod.rs b/crates/typst/src/layout/flow/mod.rs index 8a10b05dd..5db70ecb2 100644 --- a/crates/typst/src/layout/flow/mod.rs +++ b/crates/typst/src/layout/flow/mod.rs @@ -19,14 +19,14 @@ use self::compose::{compose, Composer}; use self::distribute::distribute; use crate::diag::{bail, At, SourceDiagnostic, SourceResult}; use crate::engine::{Engine, Route, Sink, Traced}; -use crate::foundations::{Content, Packed, StyleChain}; +use crate::foundations::{Content, Packed, Resolve, StyleChain}; use crate::introspection::{ Introspector, Location, Locator, LocatorLink, SplitLocator, Tag, }; use crate::layout::{ - Abs, Dir, Fragment, Frame, PlacementScope, Region, Regions, Rel, Size, + Abs, Dir, Em, Fragment, Frame, PageElem, PlacementScope, Region, Regions, Rel, Size, }; -use crate::model::{FootnoteElem, FootnoteEntry}; +use crate::model::{FootnoteElem, FootnoteEntry, LineNumberingScope, ParLine}; use crate::realize::{realize, Arenas, Pair, RealizationKind}; use crate::text::TextElem; use crate::utils::{NonZeroExt, Numeric}; @@ -187,6 +187,18 @@ pub(crate) fn layout_flow( gap: FootnoteEntry::gap_in(shared), expand: regions.expand.x, }, + line_numbers: root.then(|| LineNumberConfig { + scope: ParLine::numbering_scope_in(shared), + default_clearance: { + let width = if PageElem::flipped_in(shared) { + PageElem::height_in(shared) + } else { + PageElem::width_in(shared) + }; + (0.026 * width.unwrap_or_default()) + .clamp(Em::new(0.75).resolve(shared), Em::new(2.5).resolve(shared)) + }, + }), }; // Collect the elements into pre-processed children. These are much easier @@ -311,6 +323,8 @@ struct Config<'x> { columns: ColumnConfig, /// Settings for footnotes. footnote: FootnoteConfig, + /// Settings for line numbers. + line_numbers: Option, } /// Configuration of footnotes. @@ -338,6 +352,14 @@ struct ColumnConfig { dir: Dir, } +/// Configuration of line numbers. +struct LineNumberConfig { + /// Where line numbers are reset. + scope: LineNumberingScope, + /// The default clearance for `auto`. + default_clearance: Abs, +} + /// The result type for flow layout. /// /// The `Err(_)` variant incorporate control flow events for finishing and diff --git a/crates/typst/src/model/par.rs b/crates/typst/src/model/par.rs index 2e23bd74c..b50fca8bf 100644 --- a/crates/typst/src/model/par.rs +++ b/crates/typst/src/model/par.rs @@ -7,7 +7,7 @@ use crate::foundations::{ StyleVec, Unlabellable, }; use crate::introspection::{Count, CounterUpdate, Locatable}; -use crate::layout::{Abs, Em, HAlignment, Length, OuterHAlignment}; +use crate::layout::{Em, HAlignment, Length, OuterHAlignment}; use crate::model::Numbering; use crate::utils::singleton; @@ -219,17 +219,27 @@ impl Unlabellable for Packed {} /// /// This element is exclusively used for line number configuration and cannot /// be placed. -#[elem(name = "line", title = "Paragraph Line", Construct, Locatable)] +/// +/// ```example +/// >>> #set page(margin: (left: 3em)) +/// #set par.line(numbering: "1") +/// +/// Roses are red. \ +/// Violets are blue. \ +/// Typst is there for you. +/// ``` +#[elem(name = "line", title = "Paragraph Line", keywords = ["line numbering"], Construct, Locatable)] pub struct ParLine { /// How to number each line. Accepts a /// [numbering pattern or function]($numbering). /// /// ```example - /// #set par.line(numbering: "1") + /// >>> #set page(margin: (left: 3em)) + /// #set par.line(numbering: "I") /// /// Roses are red. \ /// Violets are blue. \ - /// Typst is awesome. + /// Typst is there for you. /// ``` #[ghost] pub numbering: Option, @@ -241,6 +251,7 @@ pub struct ParLine { /// the current text direction. /// /// ```example + /// >>> #set page(margin: (left: 3em)) /// #set par.line(numbering: "I", number-align: left) /// /// Hello world! \ @@ -253,6 +264,7 @@ pub struct ParLine { /// The margin at which line numbers appear. /// /// ```example + /// >>> #set page(margin: (right: 3em)) /// #set par.line(numbering: "1", number-margin: right) /// /// = Report @@ -265,10 +277,14 @@ pub struct ParLine { /// The distance between line numbers and text. /// + /// The default value of `{auto}` results in a clearance that is adaptive to + /// the page width and yields reasonable results in most cases. + /// /// ```example + /// >>> #set page(margin: (left: 3em)) /// #set par.line( /// numbering: "1", - /// number-clearance: 0.5pt + /// number-clearance: 4pt /// ) /// /// Typesetting \ @@ -276,8 +292,8 @@ pub struct ParLine { /// Layout /// ``` #[ghost] - #[default(Length::from(Abs::cm(1.0)))] - pub number_clearance: Length, + #[default] + pub number_clearance: Smart, /// Controls when to reset line numbering. /// @@ -285,8 +301,9 @@ pub struct ParLine { /// is never reset, or `"page"`, indicating it is reset on every page. /// /// ```example + /// >>> #set page(margin: (left: 3em)) /// #set par.line( - /// numbering: "1.", + /// numbering: "1", /// numbering-scope: "page" /// ) /// @@ -339,7 +356,7 @@ pub struct ParLineMarker { #[internal] #[required] - pub number_clearance: Length, + pub number_clearance: Smart, } impl Construct for ParLineMarker { diff --git a/tests/ref/line-numbers-default-alignment.png b/tests/ref/line-numbers-default-alignment.png index 4445ddf30c7a4846184345f81b5d49a848768176..c2e9f3d4b3fcc04f5ac17f5c6160223502a2e58d 100644 GIT binary patch delta 1343 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 N002ovPDHLkV1maRv(Nwl delta 907 zcmV;619be32cZX$B!6g0L_t(|+U?g_PZLoX24H`N7seQ)#Kc(j!VvXBjWrs#D7ay3 zgeq=Sst`pAw2A~pR8WBmv_jF=g+knswHOu&k*#GZvQ#3apwQMrp;D%=Q?_`aLzfUE z&ZPM=XU>~E`8sFLWai;79rI|IhH3b}hfS|7p2K~Olu@1U!GFZfJtD)@m~fmKR_W}q z9>TTERO)O(GPIq<^iU*m)IE9-o_72&jXHbpj`2kwySePt&Gh!v(Eg*GvT?Y81HMGa zwnFh#GD|QgJqG?N%aUg zQd!ue-_JBHCW~ePOlj`G+@b4o%B(N&{0~#!lV!vm_q6RCDB+vayWz0OSN?#Rt=N z95H|~0c#FH$RFEges@W=zrp_pP9Cs6*js@S diff --git a/tests/ref/line-numbers-page-scope.png b/tests/ref/line-numbers-page-scope.png index 0cdffd28dd69c0c0bb00649df273fafc4015302b..4b29cd4b8c5ad96d441c21fb9db4cab68b467bd3 100644 GIT binary patch delta 1864 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 Ef_egiK>z>% delta 1350 zcmV-M1-bgw3fT&fB!3`DL_t(|+U?tWQ&e>v$8jG^kDwW+nVeCXYOKu3VhYLotD+J44*!}bjzUL2qKaS&k z-%sE*=lt>c&iUgkgGnu8m|=z)em&ut9&=zl*(L?Glc(5d00hxUOGT;xwm+hdc{4HKC1Flprr3FBAYV)QF9uS5Z7Sp4L=D^nHX)Q8f z->v)wP`!xkcz-MdE}OI81lbRt_Q`<9%F`6k-QFkz{y2Ee4yrlS9h3p9igRxOMEMoD zb37mnGb||Iyg6{_oo6!OKvOa3oXJw)f|;CVda1j&$$8?-21jDc<&|n&0{q#l>*qk_ z_a*g00(`=ew>~A&ur_L z0f%bRRM0i-kpU?n`{E1kRl2Gx_*sUaEg zOuyv1i)Fwk+YFAxmxz5N1OBkVx;X%%Q-9uiw+uL_FZ>I#(ODi4h8Y&qXla%v z1)iAzS>p4lO)}sL?-mVI@4mot8Swa+r5IGLdt6esTCKaTfbQ6@GT`^`97vf4QOx0j z40z&Bup3m9ejX5p85ULRPe9kzD&g=#7-afU8{+F=9S{sxdp0~X{HIMzLWxr_JP=4P zGk=8J_Q9Pm7_O|WQVikY4Y+VyFr1)gq|JeAPy5~pGcylU!LRs>X6 zcK}%bi)i>!m0mRmBEQR}p~rP;fd_mD?D1j8N0-O4nG{Hk4> z$;;0h=K*1u;YByu3Fx(*OAhNBZJ0WQ6*0l^eUD|@crxRS84wKL3af5o*mri#tbbs* z%XvgGh5>7}V0d-JnG3Rp{RlnA+9AQPx1jlS07U+r<61h8bRTv426}?u{$crW}dGwbfC<@aWC#2*`f70a=59VAwV9 z@E9M7@`^QK!SHZtx?&6iDPFMsh5IWc@8lGr89|Kvt4fwVfqT!<1+(yH#o_hOY%7kF}r7KM_gg<*zP-qtn zubch(9LUWzfH2H3!*2xqKikw4VOCg*=l}o!07*qo IM6N<$g4XMfbN~PV diff --git a/tests/ref/line-numbers-start-alignment.png b/tests/ref/line-numbers-start-alignment.png index 3f7a652344a74d48ae3484f60d6049960a024d38..9df2c6ef095cbe88c1888540058f370bdd851822 100644 GIT binary patch delta 438 zcmV;n0ZIPW1JDDIB!8DlL_t(|+U?lCO9EjW$MOCdhqe+z`UeWJEulrEC_BQ4D4dE4 zF@unhC<{_aq97t98loEHmX0$ce&jX(h z=u`*83^UB|AHp8JU_~cbvO=rAzm%eaVT9Jr{oNQDY=YLSKYwB&gALGHxP0uVf@4lm zJ7nGGGY@=$FwF2z;Z>CPbb%W{Ll0OI5L}1a=aIKS1)~eH05v(4nIL>5k^t*Jg_m$@UP)eO((bk zec*~SzcX2nF4GTe_VhQGG%(nng9R*07*qoM6N<$g3|HC-2eap delta 444 zcmV;t0Ym=K1J(nOB!8VrL_t(|+U?juOTu6r$MIfKw~$J_WDrCzp?U$8N`zn_nUO}A zMv9u2#Hd)Mp>_x&I&_JMm=J_S7YRCO2jDNP8>%04{VN3@9xBZU>o|Z+i?)$KCo5XdC?;U{Vf{U2qyT? za8$DhmSGKCosok+q;mWRHkS7vA@~fCByA%3EEdVQo;BZow#_u3j4rWAiu%RyDQkT*h#?F?tSGV`?^SIE=s- mScT)U1v(@MCYa#9f`0(^;T}(oQuDk30000