Merge branch 'main' into table-subheaders
7
Cargo.lock
generated
@ -1259,6 +1259,12 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "infer"
|
||||
version = "0.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a588916bfdfd92e71cacef98a63d9b1f0d74d6599980d11894290e7ddefffcf7"
|
||||
|
||||
[[package]]
|
||||
name = "inotify"
|
||||
version = "0.11.0"
|
||||
@ -3127,6 +3133,7 @@ dependencies = [
|
||||
"comemo",
|
||||
"ecow",
|
||||
"image",
|
||||
"infer",
|
||||
"krilla",
|
||||
"krilla-svg",
|
||||
"serde",
|
||||
|
@ -71,6 +71,7 @@ icu_segmenter = { version = "1.4", features = ["serde"] }
|
||||
if_chain = "1"
|
||||
image = { version = "0.25.5", default-features = false, features = ["png", "jpeg", "gif"] }
|
||||
indexmap = { version = "2", features = ["serde"] }
|
||||
infer = { version = "0.19.0", default-features = false }
|
||||
kamadak-exif = "0.6"
|
||||
krilla = { version = "0.4.0", default-features = false, features = ["raster-images", "comemo", "rayon"] }
|
||||
krilla-svg = "0.1.0"
|
||||
|
@ -690,13 +690,34 @@ fn breakpoints(p: &Preparation, mut f: impl FnMut(usize, Breakpoint)) {
|
||||
let breakpoint = if point == text.len() {
|
||||
Breakpoint::Mandatory
|
||||
} else {
|
||||
const OBJ_REPLACE: char = '\u{FFFC}';
|
||||
match lb.get(c) {
|
||||
// Fix for: https://github.com/unicode-org/icu4x/issues/4146
|
||||
LineBreak::Glue | LineBreak::WordJoiner | LineBreak::ZWJ => continue,
|
||||
LineBreak::MandatoryBreak
|
||||
| LineBreak::CarriageReturn
|
||||
| LineBreak::LineFeed
|
||||
| LineBreak::NextLine => Breakpoint::Mandatory,
|
||||
|
||||
// https://github.com/typst/typst/issues/5489
|
||||
//
|
||||
// OBJECT-REPLACEMENT-CHARACTERs provide Contingent Break
|
||||
// opportunities before and after by default. This behaviour
|
||||
// is however tailorable, see:
|
||||
// https://www.unicode.org/reports/tr14/#CB
|
||||
// https://www.unicode.org/reports/tr14/#TailorableBreakingRules
|
||||
// https://www.unicode.org/reports/tr14/#LB20
|
||||
//
|
||||
// Don't provide a line breaking opportunity between a LTR-
|
||||
// ISOLATE (or any other Combining Mark) and an OBJECT-
|
||||
// REPLACEMENT-CHARACTER representing an inline item, if the
|
||||
// LTR-ISOLATE could end up as the only character on the
|
||||
// previous line.
|
||||
LineBreak::CombiningMark
|
||||
if text[point..].starts_with(OBJ_REPLACE)
|
||||
&& last + c.len_utf8() == point =>
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
_ => Breakpoint::Normal,
|
||||
}
|
||||
};
|
||||
|
@ -20,7 +20,7 @@ use unicode_bidi::{BidiInfo, Level as BidiLevel};
|
||||
use unicode_script::{Script, UnicodeScript};
|
||||
|
||||
use super::{decorate, Item, Range, SpanMapper};
|
||||
use crate::modifiers::{FrameModifiers, FrameModify};
|
||||
use crate::modifiers::FrameModifyText;
|
||||
|
||||
/// The result of shaping text.
|
||||
///
|
||||
@ -327,7 +327,7 @@ impl<'a> ShapedText<'a> {
|
||||
offset += width;
|
||||
}
|
||||
|
||||
frame.modify(&FrameModifiers::get_in(self.styles));
|
||||
frame.modify_text(self.styles);
|
||||
frame
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
use typst_library::foundations::StyleChain;
|
||||
use typst_library::layout::{Fragment, Frame, FrameItem, HideElem, Point};
|
||||
use typst_library::model::{Destination, LinkElem};
|
||||
use typst_library::layout::{Abs, Fragment, Frame, FrameItem, HideElem, Point, Sides};
|
||||
use typst_library::model::{Destination, LinkElem, ParElem};
|
||||
|
||||
/// Frame-level modifications resulting from styles that do not impose any
|
||||
/// layout structure.
|
||||
@ -52,14 +52,7 @@ pub trait FrameModify {
|
||||
|
||||
impl FrameModify for Frame {
|
||||
fn modify(&mut self, modifiers: &FrameModifiers) {
|
||||
if let Some(dest) = &modifiers.dest {
|
||||
let size = self.size();
|
||||
self.push(Point::zero(), FrameItem::Link(dest.clone(), size));
|
||||
}
|
||||
|
||||
if modifiers.hidden {
|
||||
self.hide();
|
||||
}
|
||||
modify_frame(self, modifiers, None);
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,6 +75,41 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub trait FrameModifyText {
|
||||
/// Resolve and apply [`FrameModifiers`] for this text frame.
|
||||
fn modify_text(&mut self, styles: StyleChain);
|
||||
}
|
||||
|
||||
impl FrameModifyText for Frame {
|
||||
fn modify_text(&mut self, styles: StyleChain) {
|
||||
let modifiers = FrameModifiers::get_in(styles);
|
||||
let expand_y = 0.5 * ParElem::leading_in(styles);
|
||||
let outset = Sides::new(Abs::zero(), expand_y, Abs::zero(), expand_y);
|
||||
modify_frame(self, &modifiers, Some(outset));
|
||||
}
|
||||
}
|
||||
|
||||
fn modify_frame(
|
||||
frame: &mut Frame,
|
||||
modifiers: &FrameModifiers,
|
||||
link_box_outset: Option<Sides<Abs>>,
|
||||
) {
|
||||
if let Some(dest) = &modifiers.dest {
|
||||
let mut pos = Point::zero();
|
||||
let mut size = frame.size();
|
||||
if let Some(outset) = link_box_outset {
|
||||
pos.y -= outset.top;
|
||||
pos.x -= outset.left;
|
||||
size += outset.sum_by_axis();
|
||||
}
|
||||
frame.push(pos, FrameItem::Link(dest.clone(), size));
|
||||
}
|
||||
|
||||
if modifiers.hidden {
|
||||
frame.hide();
|
||||
}
|
||||
}
|
||||
|
||||
/// Performs layout and modification in one step.
|
||||
///
|
||||
/// This just runs `layout(styles).modified(&FrameModifiers::get_in(styles))`,
|
||||
|
@ -23,6 +23,7 @@ bytemuck = { workspace = true }
|
||||
comemo = { workspace = true }
|
||||
ecow = { workspace = true }
|
||||
image = { workspace = true }
|
||||
infer = { workspace = true }
|
||||
krilla = { workspace = true }
|
||||
krilla-svg = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
|
@ -34,6 +34,8 @@ pub(crate) fn embed_files(
|
||||
},
|
||||
};
|
||||
let data: Arc<dyn AsRef<[u8]> + Send + Sync> = Arc::new(embed.data.clone());
|
||||
// TODO: update when new krilla version lands (https://github.com/LaurenzV/krilla/pull/203)
|
||||
let compress = should_compress(&embed.data).unwrap_or(true);
|
||||
|
||||
let file = EmbeddedFile {
|
||||
path,
|
||||
@ -41,7 +43,7 @@ pub(crate) fn embed_files(
|
||||
description,
|
||||
association_kind,
|
||||
data: data.into(),
|
||||
compress: true,
|
||||
compress,
|
||||
location: Some(span.into_raw().get()),
|
||||
};
|
||||
|
||||
@ -52,3 +54,69 @@ pub(crate) fn embed_files(
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn should_compress(data: &[u8]) -> Option<bool> {
|
||||
let ty = infer::get(data)?;
|
||||
match ty.matcher_type() {
|
||||
infer::MatcherType::App => None,
|
||||
infer::MatcherType::Archive => match ty.mime_type() {
|
||||
#[rustfmt::skip]
|
||||
"application/zip"
|
||||
| "application/vnd.rar"
|
||||
| "application/gzip"
|
||||
| "application/x-bzip2"
|
||||
| "application/vnd.bzip3"
|
||||
| "application/x-7z-compressed"
|
||||
| "application/x-xz"
|
||||
| "application/vnd.ms-cab-compressed"
|
||||
| "application/vnd.debian.binary-package"
|
||||
| "application/x-compress"
|
||||
| "application/x-lzip"
|
||||
| "application/x-rpm"
|
||||
| "application/zstd"
|
||||
| "application/x-lz4"
|
||||
| "application/x-ole-storage" => Some(false),
|
||||
_ => None,
|
||||
},
|
||||
infer::MatcherType::Audio => match ty.mime_type() {
|
||||
#[rustfmt::skip]
|
||||
"audio/mpeg"
|
||||
| "audio/m4a"
|
||||
| "audio/opus"
|
||||
| "audio/ogg"
|
||||
| "audio/x-flac"
|
||||
| "audio/amr"
|
||||
| "audio/aac"
|
||||
| "audio/x-ape" => Some(false),
|
||||
_ => None,
|
||||
},
|
||||
infer::MatcherType::Book => None,
|
||||
infer::MatcherType::Doc => None,
|
||||
infer::MatcherType::Font => None,
|
||||
infer::MatcherType::Image => match ty.mime_type() {
|
||||
#[rustfmt::skip]
|
||||
"image/jpeg"
|
||||
| "image/jp2"
|
||||
| "image/png"
|
||||
| "image/webp"
|
||||
| "image/vnd.ms-photo"
|
||||
| "image/heif"
|
||||
| "image/avif"
|
||||
| "image/jxl"
|
||||
| "image/vnd.djvu" => None,
|
||||
_ => None,
|
||||
},
|
||||
infer::MatcherType::Text => None,
|
||||
infer::MatcherType::Video => match ty.mime_type() {
|
||||
#[rustfmt::skip]
|
||||
"video/mp4"
|
||||
| "video/x-m4v"
|
||||
| "video/x-matroska"
|
||||
| "video/webm"
|
||||
| "video/quicktime"
|
||||
| "video/x-flv" => Some(false),
|
||||
_ => None,
|
||||
},
|
||||
infer::MatcherType::Custom => None,
|
||||
}
|
||||
}
|
||||
|
@ -655,6 +655,7 @@ fn visit_grouping_rules<'a>(
|
||||
let matching = s.rules.iter().find(|&rule| (rule.trigger)(content, &s.kind));
|
||||
|
||||
// Try to continue or finish an existing grouping.
|
||||
let mut i = 0;
|
||||
while let Some(active) = s.groupings.last() {
|
||||
// Start a nested group if a rule with higher priority matches.
|
||||
if matching.is_some_and(|rule| rule.priority > active.rule.priority) {
|
||||
@ -670,6 +671,16 @@ fn visit_grouping_rules<'a>(
|
||||
}
|
||||
|
||||
finish_innermost_grouping(s)?;
|
||||
i += 1;
|
||||
if i > 512 {
|
||||
// It seems like this case is only hit when there is a cycle between
|
||||
// a show rule and a grouping rule. The show rule produces content
|
||||
// that is matched by a grouping rule, which is then again processed
|
||||
// by the show rule, and so on. The two must be at an equilibrium,
|
||||
// otherwise either the "maximum show rule depth" or "maximum
|
||||
// grouping depth" errors are triggered.
|
||||
bail!(content.span(), "maximum grouping depth exceeded");
|
||||
}
|
||||
}
|
||||
|
||||
// Start a new grouping.
|
||||
|
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.5 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 8.9 KiB |
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 920 B After Width: | Height: | Size: 947 B |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 841 B After Width: | Height: | Size: 869 B |
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 7.7 KiB |
Before Width: | Height: | Size: 395 B After Width: | Height: | Size: 417 B |
Before Width: | Height: | Size: 617 B After Width: | Height: | Size: 643 B |
Before Width: | Height: | Size: 833 B After Width: | Height: | Size: 867 B |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 7.4 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 5.9 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 699 B After Width: | Height: | Size: 739 B |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 515 B After Width: | Height: | Size: 547 B |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 749 B After Width: | Height: | Size: 772 B |
Before Width: | Height: | Size: 828 B After Width: | Height: | Size: 850 B |
Before Width: | Height: | Size: 524 B After Width: | Height: | Size: 558 B |
Before Width: | Height: | Size: 508 B After Width: | Height: | Size: 531 B |
Before Width: | Height: | Size: 981 B After Width: | Height: | Size: 989 B |
Before Width: | Height: | Size: 500 B After Width: | Height: | Size: 508 B |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 802 B After Width: | Height: | Size: 841 B |
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 796 B After Width: | Height: | Size: 820 B |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 448 B After Width: | Height: | Size: 475 B |
BIN
tests/ref/issue-5489-matrix-stray-linebreak.png
Normal file
After Width: | Height: | Size: 644 B |
Before Width: | Height: | Size: 399 B After Width: | Height: | Size: 409 B |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 399 B After Width: | Height: | Size: 409 B |
Before Width: | Height: | Size: 226 B After Width: | Height: | Size: 242 B |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 393 B After Width: | Height: | Size: 396 B |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 9.2 KiB After Width: | Height: | Size: 9.1 KiB |
Before Width: | Height: | Size: 524 B After Width: | Height: | Size: 567 B |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 5.9 KiB |
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 962 B After Width: | Height: | Size: 1013 B |
Before Width: | Height: | Size: 981 B After Width: | Height: | Size: 892 B |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 711 B After Width: | Height: | Size: 711 B |
Before Width: | Height: | Size: 729 B After Width: | Height: | Size: 726 B |
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 8.0 KiB |
Before Width: | Height: | Size: 403 B After Width: | Height: | Size: 434 B |
Before Width: | Height: | Size: 524 B After Width: | Height: | Size: 496 B |
Before Width: | Height: | Size: 795 B After Width: | Height: | Size: 811 B |
Before Width: | Height: | Size: 626 B After Width: | Height: | Size: 632 B |
@ -139,3 +139,11 @@ Some texts feature many longer
|
||||
words. Those are often exceedingly
|
||||
challenging to break in a visually
|
||||
pleasing way.
|
||||
|
||||
--- issue-5489-matrix-stray-linebreak ---
|
||||
#table(
|
||||
columns: (70pt,) * 1,
|
||||
align: horizon + center,
|
||||
stroke: 0.6pt,
|
||||
[$mat(2241/2210,-71/1105;-71/1105,147/1105)$],
|
||||
)
|
||||
|
@ -258,3 +258,11 @@ I am *strong*, I am _emphasized_, and I am #[special<special>].
|
||||
|
||||
= Hello
|
||||
*strong*
|
||||
|
||||
--- issue-5690-oom-par-box ---
|
||||
// Error: 3:6-5:1 maximum grouping depth exceeded
|
||||
#show par: box
|
||||
|
||||
Hello
|
||||
|
||||
World
|
||||
|