diff --git a/src/export/pdf.rs b/src/export/pdf.rs
index cc84dbc3c..3063bf4c8 100644
--- a/src/export/pdf.rs
+++ b/src/export/pdf.rs
@@ -4,7 +4,6 @@ use std::cmp::Eq;
use std::collections::{BTreeMap, HashMap, HashSet};
use std::hash::Hash;
use std::io::Cursor;
-use std::sync::Arc;
use image::{DynamicImage, GenericImageView, ImageFormat, ImageResult, Rgba};
use pdf_writer::types::{
@@ -34,7 +33,7 @@ use crate::Context;
/// included in the PDF.
///
/// Returns the raw bytes making up the PDF file.
-pub fn pdf(ctx: &Context, frames: &[Arc]) -> Vec {
+pub fn pdf(ctx: &Context, frames: &[Frame]) -> Vec {
PdfExporter::new(ctx).export(frames)
}
@@ -84,7 +83,7 @@ impl<'a> PdfExporter<'a> {
}
}
- fn export(mut self, frames: &[Arc]) -> Vec {
+ fn export(mut self, frames: &[Frame]) -> Vec {
self.build_pages(frames);
self.write_fonts();
self.write_images();
@@ -100,7 +99,7 @@ impl<'a> PdfExporter<'a> {
self.writer.finish()
}
- fn build_pages(&mut self, frames: &[Arc]) {
+ fn build_pages(&mut self, frames: &[Frame]) {
for frame in frames {
let page_id = self.alloc.bump();
self.page_refs.push(page_id);
diff --git a/src/frame.rs b/src/frame.rs
index 628d8c5b9..6855e7ac2 100644
--- a/src/frame.rs
+++ b/src/frame.rs
@@ -11,7 +11,7 @@ use crate::geom::{
};
use crate::image::ImageId;
use crate::library::text::Lang;
-use crate::util::{EcoString, MaybeShared};
+use crate::util::EcoString;
/// A finished layout with elements at fixed positions.
#[derive(Default, Clone, Eq, PartialEq)]
@@ -24,7 +24,7 @@ pub struct Frame {
/// The semantic role of the frame.
role: Option,
/// The elements composing this layout.
- elements: Vec<(Point, Element)>,
+ elements: Arc>,
}
/// Accessors and setters.
@@ -39,7 +39,7 @@ impl Frame {
size,
baseline: None,
role: None,
- elements: vec![],
+ elements: Arc::new(vec![]),
}
}
@@ -92,7 +92,7 @@ impl Frame {
/// Recover the text inside of the frame and its children.
pub fn text(&self) -> EcoString {
let mut text = EcoString::new();
- for (_, element) in &self.elements {
+ for (_, element) in self.elements() {
match element {
Element::Text(content) => {
for glyph in &content.glyphs {
@@ -117,7 +117,19 @@ impl Frame {
/// Add an element at a position in the foreground.
pub fn push(&mut self, pos: Point, element: Element) {
- self.elements.push((pos, element));
+ Arc::make_mut(&mut self.elements).push((pos, element));
+ }
+
+ /// Add a frame.
+ ///
+ /// Automatically decides whether to inline the frame or to include it as a
+ /// group based on the number of elements in the frame.
+ pub fn push_frame(&mut self, pos: Point, frame: Frame) {
+ if self.should_inline(&frame) {
+ self.inline(self.layer(), pos, frame);
+ } else {
+ self.push(pos, Element::Group(Group::new(frame)));
+ }
}
/// Insert an element at the given layer in the frame.
@@ -125,51 +137,72 @@ impl Frame {
/// This panics if the layer is greater than the number of layers present.
#[track_caller]
pub fn insert(&mut self, layer: usize, pos: Point, element: Element) {
- self.elements.insert(layer, (pos, element));
- }
-
- /// Add a frame.
- ///
- /// Automatically decides whether to inline the frame or to include it as a
- /// group based on the number of elements in the frame.
- pub fn push_frame(&mut self, pos: Point, frame: impl FrameRepr) {
- if (self.elements.is_empty() || frame.as_ref().is_light())
- && frame.as_ref().role().map_or(true, Role::is_weak)
- {
- frame.inline(self, self.layer(), pos);
- } else {
- self.elements.push((pos, Element::Group(Group::new(frame.share()))));
- }
+ Arc::make_mut(&mut self.elements).insert(layer, (pos, element));
}
/// Add an element at a position in the background.
pub fn prepend(&mut self, pos: Point, element: Element) {
- self.elements.insert(0, (pos, element));
+ Arc::make_mut(&mut self.elements).insert(0, (pos, element));
}
/// Add multiple elements at a position in the background.
- pub fn prepend_multiple(&mut self, insert: I)
+ pub fn prepend_multiple(&mut self, elements: I)
where
I: IntoIterator- ,
{
- self.elements.splice(0 .. 0, insert);
+ Arc::make_mut(&mut self.elements).splice(0 .. 0, elements);
}
/// Add a frame at a position in the background.
- pub fn prepend_frame(&mut self, pos: Point, frame: impl FrameRepr) {
- if (self.elements.is_empty() || frame.as_ref().is_light())
- && frame.as_ref().role().map_or(true, Role::is_weak)
- {
- frame.inline(self, 0, pos);
+ pub fn prepend_frame(&mut self, pos: Point, frame: Frame) {
+ if self.should_inline(&frame) {
+ self.inline(0, pos, frame);
} else {
- self.elements
- .insert(0, (pos, Element::Group(Group::new(frame.share()))));
+ self.prepend(pos, Element::Group(Group::new(frame)));
}
}
- /// Whether the frame has comparatively few elements.
- fn is_light(&self) -> bool {
- self.elements.len() <= 5
+ /// Whether the given frame should be inlined.
+ pub fn should_inline(&self, frame: &Frame) -> bool {
+ (self.elements.is_empty() || frame.elements.len() <= 5)
+ && frame.role().map_or(true, |role| role.is_weak())
+ }
+
+ /// Inline a frame at the given layer.
+ pub fn inline(&mut self, layer: usize, pos: Point, frame: Frame) {
+ // Try to just reuse the elements.
+ if pos.is_zero() && self.elements.is_empty() {
+ self.elements = frame.elements;
+ return;
+ }
+
+ // Try to copy the elements without adjusting the positioned.
+ // Also try to reuse the elements if the Arc isn't shared.
+ let range = layer .. layer;
+ if pos.is_zero() {
+ let sink = Arc::make_mut(&mut self.elements);
+ match Arc::try_unwrap(frame.elements) {
+ Ok(elements) => {
+ sink.splice(range, elements);
+ }
+ Err(arc) => {
+ sink.splice(range, arc.iter().cloned());
+ }
+ }
+ return;
+ }
+
+ // We must adjust the element positioned.
+ // But still try to reuse the elements if the Arc isn't shared.
+ let sink = Arc::make_mut(&mut self.elements);
+ match Arc::try_unwrap(frame.elements) {
+ Ok(elements) => {
+ sink.splice(range, elements.into_iter().map(|(p, e)| (p + pos, e)));
+ }
+ Err(arc) => {
+ sink.splice(range, arc.iter().cloned().map(|(p, e)| (p + pos, e)));
+ }
+ }
}
}
@@ -177,7 +210,7 @@ impl Frame {
impl Frame {
/// Remove all elements from the frame.
pub fn clear(&mut self) {
- self.elements.clear();
+ self.elements = Arc::new(vec![]);
}
/// Resize the frame to a new size, distributing new space according to the
@@ -199,7 +232,7 @@ impl Frame {
if let Some(baseline) = &mut self.baseline {
*baseline += offset.y;
}
- for (point, _) in &mut self.elements {
+ for (point, _) in Arc::make_mut(&mut self.elements) {
*point += offset;
}
}
@@ -207,7 +240,7 @@ impl Frame {
/// Apply the given role to the frame if it doesn't already have one.
pub fn apply_role(&mut self, role: Role) {
- if self.role.map_or(true, Role::is_weak) {
+ if self.role.map_or(true, |prev| prev.is_weak() && !role.is_weak()) {
self.role = Some(role);
}
}
@@ -232,8 +265,9 @@ impl Frame {
where
F: FnOnce(&mut Group),
{
- let mut wrapper = Frame { elements: vec![], ..*self };
- let mut group = Group::new(Arc::new(std::mem::take(self)));
+ let mut wrapper = Frame::new(self.size);
+ wrapper.baseline = self.baseline;
+ let mut group = Group::new(std::mem::take(self));
f(&mut group);
wrapper.push(Point::zero(), Element::Group(group));
*self = wrapper;
@@ -252,76 +286,6 @@ impl Debug for Frame {
}
}
-impl AsRef for Frame {
- fn as_ref(&self) -> &Frame {
- self
- }
-}
-
-/// A representational form of a frame (owned, shared or maybe shared).
-pub trait FrameRepr: AsRef {
- /// Transform into a shared representation.
- fn share(self) -> Arc;
-
- /// Inline `self` into the sink frame.
- fn inline(self, sink: &mut Frame, layer: usize, offset: Point);
-}
-
-impl FrameRepr for Frame {
- fn share(self) -> Arc {
- Arc::new(self)
- }
-
- fn inline(self, sink: &mut Frame, layer: usize, offset: Point) {
- if offset.is_zero() {
- if sink.elements.is_empty() {
- sink.elements = self.elements;
- } else {
- sink.elements.splice(layer .. layer, self.elements);
- }
- } else {
- sink.elements.splice(
- layer .. layer,
- self.elements.into_iter().map(|(p, e)| (p + offset, e)),
- );
- }
- }
-}
-
-impl FrameRepr for Arc {
- fn share(self) -> Arc {
- self
- }
-
- fn inline(self, sink: &mut Frame, layer: usize, offset: Point) {
- match Arc::try_unwrap(self) {
- Ok(frame) => frame.inline(sink, layer, offset),
- Err(rc) => {
- sink.elements.splice(
- layer .. layer,
- rc.elements.iter().cloned().map(|(p, e)| (p + offset, e)),
- );
- }
- }
- }
-}
-
-impl FrameRepr for MaybeShared {
- fn share(self) -> Arc {
- match self {
- Self::Owned(owned) => owned.share(),
- Self::Shared(shared) => shared.share(),
- }
- }
-
- fn inline(self, sink: &mut Frame, layer: usize, offset: Point) {
- match self {
- Self::Owned(owned) => owned.inline(sink, layer, offset),
- Self::Shared(shared) => shared.inline(sink, layer, offset),
- }
- }
-}
-
/// The building block frames are composed of.
#[derive(Clone, Eq, PartialEq)]
pub enum Element {
@@ -357,7 +321,7 @@ impl Debug for Element {
#[derive(Clone, Eq, PartialEq)]
pub struct Group {
/// The group's frame.
- pub frame: Arc,
+ pub frame: Frame,
/// A transformation to apply to the group.
pub transform: Transform,
/// Whether the frame should be a clipping boundary.
@@ -366,7 +330,7 @@ pub struct Group {
impl Group {
/// Create a new group with default settings.
- pub fn new(frame: Arc) -> Self {
+ pub fn new(frame: Frame) -> Self {
Self {
frame,
transform: Transform::identity(),
diff --git a/src/lib.rs b/src/lib.rs
index f9416463f..25a41c358 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -72,7 +72,7 @@ use crate::source::{SourceId, SourceStore};
/// Returns either a vector of frames representing individual pages or
/// diagnostics in the form of a vector of error message with file and span
/// information.
-pub fn typeset(ctx: &mut Context, id: SourceId) -> TypResult>> {
+pub fn typeset(ctx: &mut Context, id: SourceId) -> TypResult> {
let module = eval::evaluate(ctx, id, vec![])?;
model::layout(ctx, &module.content)
}
diff --git a/src/library/graphics/hide.rs b/src/library/graphics/hide.rs
index c969ef760..0ed02d1b9 100644
--- a/src/library/graphics/hide.rs
+++ b/src/library/graphics/hide.rs
@@ -17,12 +17,12 @@ impl Layout for HideNode {
ctx: &mut Context,
regions: &Regions,
styles: StyleChain,
- ) -> TypResult>> {
+ ) -> TypResult> {
let mut frames = self.0.layout(ctx, regions, styles)?;
// Clear the frames.
for frame in &mut frames {
- Arc::make_mut(frame).clear();
+ frame.clear();
}
Ok(frames)
diff --git a/src/library/graphics/image.rs b/src/library/graphics/image.rs
index d0bcfa446..1781eb8aa 100644
--- a/src/library/graphics/image.rs
+++ b/src/library/graphics/image.rs
@@ -38,7 +38,7 @@ impl Layout for ImageNode {
ctx: &mut Context,
regions: &Regions,
styles: StyleChain,
- ) -> TypResult>> {
+ ) -> TypResult> {
let img = ctx.images.get(self.0);
let pxw = img.width() as f64;
let pxh = img.height() as f64;
@@ -90,7 +90,7 @@ impl Layout for ImageNode {
frame.link(url.clone());
}
- Ok(vec![Arc::new(frame)])
+ Ok(vec![frame])
}
}
diff --git a/src/library/graphics/line.rs b/src/library/graphics/line.rs
index 8e5ceae12..15c54f460 100644
--- a/src/library/graphics/line.rs
+++ b/src/library/graphics/line.rs
@@ -43,7 +43,7 @@ impl Layout for LineNode {
_: &mut Context,
regions: &Regions,
styles: StyleChain,
- ) -> TypResult>> {
+ ) -> TypResult> {
let stroke = styles.get(Self::STROKE).unwrap_or_default();
let origin = self
@@ -64,7 +64,7 @@ impl Layout for LineNode {
let shape = Geometry::Line(delta.to_point()).stroked(stroke);
frame.push(origin.to_point(), Element::Shape(shape));
- Ok(vec![Arc::new(frame)])
+ Ok(vec![frame])
}
}
diff --git a/src/library/graphics/shape.rs b/src/library/graphics/shape.rs
index 6c315c24f..bf5818155 100644
--- a/src/library/graphics/shape.rs
+++ b/src/library/graphics/shape.rs
@@ -79,7 +79,7 @@ impl Layout for ShapeNode
{
ctx: &mut Context,
regions: &Regions,
styles: StyleChain,
- ) -> TypResult>> {
+ ) -> TypResult> {
let mut frames;
if let Some(child) = &self.0 {
let mut inset = styles.get(Self::INSET);
@@ -94,7 +94,7 @@ impl Layout for ShapeNode {
frames = child.layout(ctx, &pod, styles)?;
for frame in frames.iter_mut() {
- Arc::make_mut(frame).apply_role(Role::GenericBlock);
+ frame.apply_role(Role::GenericBlock);
}
// Relayout with full expansion into square region to make sure
@@ -131,10 +131,10 @@ impl Layout for ShapeNode {
size = regions.expand.select(regions.first, size);
}
- frames = vec![Arc::new(Frame::new(size))];
+ frames = vec![Frame::new(size)];
}
- let frame = Arc::make_mut(&mut frames[0]);
+ let frame = &mut frames[0];
// Add fill and/or stroke.
let fill = styles.get(Self::FILL);
diff --git a/src/library/graphics/transform.rs b/src/library/graphics/transform.rs
index 7176a683d..2a0149bc8 100644
--- a/src/library/graphics/transform.rs
+++ b/src/library/graphics/transform.rs
@@ -28,13 +28,13 @@ impl Layout for MoveNode {
ctx: &mut Context,
regions: &Regions,
styles: StyleChain,
- ) -> TypResult>> {
+ ) -> TypResult> {
let mut frames = self.child.layout(ctx, regions, styles)?;
let delta = self.delta.resolve(styles);
for frame in &mut frames {
let delta = delta.zip(frame.size()).map(|(d, s)| d.relative_to(s));
- Arc::make_mut(frame).translate(delta.to_point());
+ frame.translate(delta.to_point());
}
Ok(frames)
@@ -89,7 +89,7 @@ impl Layout for TransformNode {
ctx: &mut Context,
regions: &Regions,
styles: StyleChain,
- ) -> TypResult>> {
+ ) -> TypResult> {
let origin = styles.get(Self::ORIGIN).unwrap_or(Align::CENTER_HORIZON);
let mut frames = self.child.layout(ctx, regions, styles)?;
@@ -99,7 +99,7 @@ impl Layout for TransformNode {
.pre_concat(self.transform)
.pre_concat(Transform::translate(-x, -y));
- Arc::make_mut(frame).transform(transform);
+ frame.transform(transform);
}
Ok(frames)
diff --git a/src/library/layout/align.rs b/src/library/layout/align.rs
index c5adcf9f9..e7a27c045 100644
--- a/src/library/layout/align.rs
+++ b/src/library/layout/align.rs
@@ -31,7 +31,7 @@ impl Layout for AlignNode {
ctx: &mut Context,
regions: &Regions,
styles: StyleChain,
- ) -> TypResult>> {
+ ) -> TypResult> {
// The child only needs to expand along an axis if there's no alignment.
let mut pod = regions.clone();
pod.expand &= self.aligns.map_is_none();
@@ -53,7 +53,7 @@ impl Layout for AlignNode {
.map(|align| align.resolve(styles))
.unwrap_or(Spec::new(Align::Left, Align::Top));
- Arc::make_mut(frame).resize(target, aligns);
+ frame.resize(target, aligns);
}
Ok(frames)
diff --git a/src/library/layout/columns.rs b/src/library/layout/columns.rs
index b9e308f2a..33ceab867 100644
--- a/src/library/layout/columns.rs
+++ b/src/library/layout/columns.rs
@@ -31,7 +31,7 @@ impl Layout for ColumnsNode {
ctx: &mut Context,
regions: &Regions,
styles: StyleChain,
- ) -> TypResult>> {
+ ) -> TypResult> {
// Separating the infinite space into infinite columns does not make
// much sense.
if !regions.first.x.is_finite() {
@@ -94,7 +94,7 @@ impl Layout for ColumnsNode {
cursor += width + gutter;
}
- finished.push(Arc::new(output));
+ finished.push(output);
}
Ok(finished)
diff --git a/src/library/layout/flow.rs b/src/library/layout/flow.rs
index b6844f552..c6d2999e5 100644
--- a/src/library/layout/flow.rs
+++ b/src/library/layout/flow.rs
@@ -28,7 +28,7 @@ impl Layout for FlowNode {
ctx: &mut Context,
regions: &Regions,
styles: StyleChain,
- ) -> TypResult>> {
+ ) -> TypResult> {
let mut layouter = FlowLayouter::new(regions);
for (child, map) in self.0.iter() {
@@ -92,7 +92,7 @@ pub struct FlowLayouter {
/// Spacing and layouted nodes.
items: Vec,
/// Finished frames for previous regions.
- finished: Vec>,
+ finished: Vec,
}
/// A prepared item in a flow layout.
@@ -102,9 +102,9 @@ enum FlowItem {
/// Fractional spacing between other items.
Fractional(Fraction),
/// A frame for a layouted child node and how to align it.
- Frame(Arc, Spec),
+ Frame(Frame, Spec),
/// An absolutely placed frame.
- Placed(Arc),
+ Placed(Frame),
}
impl FlowLayouter {
@@ -184,9 +184,7 @@ impl FlowLayouter {
let len = frames.len();
for (i, mut frame) in frames.into_iter().enumerate() {
// Set the generic block role.
- if frame.role().map_or(true, Role::is_weak) {
- Arc::make_mut(&mut frame).apply_role(Role::GenericBlock);
- }
+ frame.apply_role(Role::GenericBlock);
// Grow our size, shrink the region and save the frame for later.
let size = frame.size();
@@ -248,11 +246,11 @@ impl FlowLayouter {
self.full = self.regions.first;
self.used = Size::zero();
self.fr = Fraction::zero();
- self.finished.push(Arc::new(output));
+ self.finished.push(output);
}
/// Finish layouting and return the resulting frames.
- pub fn finish(mut self) -> Vec> {
+ pub fn finish(mut self) -> Vec {
if self.expand.y {
while self.regions.backlog.len() > 0 {
self.finish_region();
diff --git a/src/library/layout/grid.rs b/src/library/layout/grid.rs
index c04913a1c..c02662a61 100644
--- a/src/library/layout/grid.rs
+++ b/src/library/layout/grid.rs
@@ -36,7 +36,7 @@ impl Layout for GridNode {
ctx: &mut Context,
regions: &Regions,
styles: StyleChain,
- ) -> TypResult>> {
+ ) -> TypResult> {
// Prepare grid layout by unifying content and gutter tracks.
let layouter = GridLayouter::new(
ctx,
@@ -116,7 +116,7 @@ pub struct GridLayouter<'a> {
/// The sum of fractions in the current region.
fr: Fraction,
/// Frames for finished regions.
- finished: Vec>,
+ finished: Vec,
}
/// Produced by initial row layout, auto and relative rows are already finished,
@@ -203,7 +203,7 @@ impl<'a> GridLayouter<'a> {
}
/// Determines the columns sizes and then layouts the grid row-by-row.
- pub fn layout(mut self) -> TypResult>> {
+ pub fn layout(mut self) -> TypResult> {
self.ctx.pins.freeze();
self.measure_columns()?;
self.ctx.pins.unfreeze();
@@ -567,7 +567,7 @@ impl<'a> GridLayouter<'a> {
pos.y += height;
}
- self.finished.push(Arc::new(output));
+ self.finished.push(output);
self.regions.next();
self.full = self.regions.first.y;
self.used.y = Length::zero();
diff --git a/src/library/layout/pad.rs b/src/library/layout/pad.rs
index 29a72588f..dfd425bd1 100644
--- a/src/library/layout/pad.rs
+++ b/src/library/layout/pad.rs
@@ -31,7 +31,7 @@ impl Layout for PadNode {
ctx: &mut Context,
regions: &Regions,
styles: StyleChain,
- ) -> TypResult>> {
+ ) -> TypResult> {
// Layout child into padded regions.
let padding = self.padding.resolve(styles);
let pod = regions.map(|size| shrink(size, padding));
@@ -45,7 +45,6 @@ impl Layout for PadNode {
let offset = Point::new(padding.left, padding.top);
// Grow the frame and translate everything in the frame inwards.
- let frame = Arc::make_mut(frame);
frame.set_size(padded);
frame.translate(offset);
}
diff --git a/src/library/layout/page.rs b/src/library/layout/page.rs
index e22bb4f7a..e2f414ab4 100644
--- a/src/library/layout/page.rs
+++ b/src/library/layout/page.rs
@@ -60,7 +60,7 @@ impl PageNode {
ctx: &mut Context,
mut page: usize,
styles: StyleChain,
- ) -> TypResult>> {
+ ) -> TypResult> {
// When one of the lengths is infinite the page fits its content along
// that axis.
let width = styles.get(Self::WIDTH).unwrap_or(Length::inf());
@@ -129,12 +129,12 @@ impl PageNode {
if let Some(content) = marginal.resolve(ctx, page)? {
let pod = Regions::one(area, area, Spec::splat(true));
let mut sub = content.layout(ctx, &pod, styles)?.remove(0);
- Arc::make_mut(&mut sub).apply_role(role);
+ sub.apply_role(role);
if role == Role::Background {
- Arc::make_mut(frame).prepend_frame(pos, sub);
+ frame.prepend_frame(pos, sub);
} else {
- Arc::make_mut(frame).push_frame(pos, sub);
+ frame.push_frame(pos, sub);
}
}
}
diff --git a/src/library/layout/place.rs b/src/library/layout/place.rs
index 408ca1290..67e46d3bd 100644
--- a/src/library/layout/place.rs
+++ b/src/library/layout/place.rs
@@ -24,7 +24,7 @@ impl Layout for PlaceNode {
ctx: &mut Context,
regions: &Regions,
styles: StyleChain,
- ) -> TypResult>> {
+ ) -> TypResult> {
let out_of_flow = self.out_of_flow();
// The pod is the base area of the region because for absolute
@@ -41,7 +41,7 @@ impl Layout for PlaceNode {
// space in our parent. Otherwise, respect the expand settings.
let frame = &mut frames[0];
let target = regions.expand.select(regions.first, Size::zero());
- Arc::make_mut(frame).resize(target, Align::LEFT_TOP);
+ frame.resize(target, Align::LEFT_TOP);
Ok(frames)
}
diff --git a/src/library/layout/stack.rs b/src/library/layout/stack.rs
index 5d3e17865..b1268404a 100644
--- a/src/library/layout/stack.rs
+++ b/src/library/layout/stack.rs
@@ -30,7 +30,7 @@ impl Layout for StackNode {
ctx: &mut Context,
regions: &Regions,
styles: StyleChain,
- ) -> TypResult>> {
+ ) -> TypResult> {
let mut layouter = StackLayouter::new(self.dir, regions, styles);
// Spacing to insert before the next node.
@@ -107,7 +107,7 @@ pub struct StackLayouter<'a> {
/// fractional spacing.
items: Vec,
/// Finished frames for previous regions.
- finished: Vec>,
+ finished: Vec,
}
/// A prepared item in a stack layout.
@@ -117,7 +117,7 @@ enum StackItem {
/// Fractional spacing between other items.
Fractional(Fraction),
/// A frame for a layouted child node.
- Frame(Arc, Align),
+ Frame(Frame, Align),
}
impl<'a> StackLayouter<'a> {
@@ -196,9 +196,7 @@ impl<'a> StackLayouter<'a> {
let len = frames.len();
for (i, mut frame) in frames.into_iter().enumerate() {
// Set the generic block role.
- if frame.role().map_or(true, Role::is_weak) {
- Arc::make_mut(&mut frame).apply_role(Role::GenericBlock);
- }
+ frame.apply_role(Role::GenericBlock);
// Grow our size, shrink the region and save the frame for later.
let size = frame.size().to_gen(self.axis);
@@ -268,11 +266,11 @@ impl<'a> StackLayouter<'a> {
self.full = self.regions.first;
self.used = Gen::zero();
self.fr = Fraction::zero();
- self.finished.push(Arc::new(output));
+ self.finished.push(output);
}
/// Finish layouting and return the resulting frames.
- pub fn finish(mut self) -> Vec> {
+ pub fn finish(mut self) -> Vec {
self.finish_region();
self.finished
}
diff --git a/src/library/math/rex.rs b/src/library/math/rex.rs
index 930829dec..a8dbd764c 100644
--- a/src/library/math/rex.rs
+++ b/src/library/math/rex.rs
@@ -25,7 +25,7 @@ impl Layout for RexNode {
ctx: &mut Context,
_: &Regions,
styles: StyleChain,
- ) -> TypResult>> {
+ ) -> TypResult> {
// Load the font.
let span = self.tex.span;
let face_id = ctx
@@ -80,7 +80,7 @@ impl Layout for RexNode {
// Render into the frame.
renderer.render(&layout, &mut backend);
- Ok(vec![Arc::new(backend.frame)])
+ Ok(vec![backend.frame])
}
}
diff --git a/src/library/structure/doc.rs b/src/library/structure/doc.rs
index d3fc0b391..80472e243 100644
--- a/src/library/structure/doc.rs
+++ b/src/library/structure/doc.rs
@@ -7,11 +7,7 @@ pub struct DocNode(pub StyleVec);
impl DocNode {
/// Layout the document into a sequence of frames, one per page.
- pub fn layout(
- &self,
- ctx: &mut Context,
- styles: StyleChain,
- ) -> TypResult>> {
+ pub fn layout(&self, ctx: &mut Context, styles: StyleChain) -> TypResult> {
let mut frames = vec![];
for (page, map) in self.0.iter() {
let number = 1 + frames.len();
diff --git a/src/library/text/par.rs b/src/library/text/par.rs
index 7a656a30e..e40131638 100644
--- a/src/library/text/par.rs
+++ b/src/library/text/par.rs
@@ -1,5 +1,4 @@
use std::cmp::Ordering;
-use std::sync::Arc;
use unicode_bidi::{BidiInfo, Level};
use unicode_script::{Script, UnicodeScript};
@@ -9,7 +8,7 @@ use super::{shape, Lang, Quoter, Quotes, RepeatNode, ShapedText, TextNode};
use crate::font::FontStore;
use crate::library::layout::Spacing;
use crate::library::prelude::*;
-use crate::util::{EcoString, MaybeShared};
+use crate::util::EcoString;
/// Arrange text, spacing and inline-level nodes into a paragraph.
#[derive(Hash)]
@@ -71,7 +70,7 @@ impl Layout for ParNode {
ctx: &mut Context,
regions: &Regions,
styles: StyleChain,
- ) -> TypResult>> {
+ ) -> TypResult> {
// Collect all text into one string for BiDi analysis.
let (text, segments) = collect(self, &styles);
@@ -305,7 +304,7 @@ enum Item<'a> {
/// Fractional spacing between other items.
Fractional(Fraction),
/// A layouted child node.
- Frame(Arc),
+ Frame(Frame),
/// A repeating node.
Repeat(&'a RepeatNode, StyleChain<'a>),
/// A pin identified by index.
@@ -551,16 +550,9 @@ fn prepare<'a>(
} else {
let size = Size::new(regions.first.x, regions.base.y);
let pod = Regions::one(size, regions.base, Spec::splat(false));
-
let mut frame = node.layout(ctx, &pod, styles)?.remove(0);
- let shift = styles.get(TextNode::BASELINE);
-
- if !shift.is_zero() || frame.role().map_or(true, Role::is_weak) {
- let frame = Arc::make_mut(&mut frame);
- frame.translate(Point::with_y(shift));
- frame.apply_role(Role::GenericInline);
- }
-
+ frame.translate(Point::with_y(styles.get(TextNode::BASELINE)));
+ frame.apply_role(Role::GenericInline);
items.push(Item::Frame(frame));
}
}
@@ -1053,7 +1045,7 @@ fn stack(
ctx: &mut Context,
lines: &[Line],
regions: &Regions,
-) -> TypResult>> {
+) -> TypResult> {
// Determine the paragraph's width: Full width of the region if we
// should expand or there's fractional spacing, fit-to-width otherwise.
let mut width = regions.first.x;
@@ -1074,7 +1066,7 @@ fn stack(
let height = frame.size().y;
while !regions.first.y.fits(height) && !regions.in_last() {
- finished.push(Arc::new(output));
+ finished.push(output);
output = Frame::new(Size::with_x(width));
output.apply_role(Role::Paragraph);
regions.next();
@@ -1093,7 +1085,7 @@ fn stack(
first = false;
}
- finished.push(Arc::new(output));
+ finished.push(output);
Ok(finished)
}
@@ -1155,7 +1147,7 @@ fn commit(
// Build the frames and determine the height and baseline.
let mut frames = vec![];
for item in reordered {
- let mut push = |offset: &mut Length, frame: MaybeShared| {
+ let mut push = |offset: &mut Length, frame: Frame| {
let width = frame.width();
top.set_max(frame.baseline());
bottom.set_max(frame.size().y - frame.baseline());
@@ -1172,10 +1164,10 @@ fn commit(
}
Item::Text(shaped) => {
let frame = shaped.build(&mut ctx.fonts, justification);
- push(&mut offset, MaybeShared::Owned(frame));
+ push(&mut offset, frame);
}
Item::Frame(frame) => {
- push(&mut offset, MaybeShared::Shared(frame.clone()));
+ push(&mut offset, frame.clone());
}
Item::Repeat(node, styles) => {
let before = offset;
@@ -1192,7 +1184,7 @@ fn commit(
}
if width > Length::zero() {
for _ in 0 .. (count as usize).min(1000) {
- push(&mut offset, MaybeShared::Shared(frame.clone()));
+ push(&mut offset, frame.clone());
offset += apart;
}
}
@@ -1201,7 +1193,7 @@ fn commit(
Item::Pin(idx) => {
let mut frame = Frame::new(Size::zero());
frame.push(Point::zero(), Element::Pin(*idx));
- push(&mut offset, MaybeShared::Owned(frame));
+ push(&mut offset, frame);
}
}
}
diff --git a/src/library/text/repeat.rs b/src/library/text/repeat.rs
index 9ee8286b6..a3e83ac7f 100644
--- a/src/library/text/repeat.rs
+++ b/src/library/text/repeat.rs
@@ -17,7 +17,7 @@ impl Layout for RepeatNode {
ctx: &mut Context,
regions: &Regions,
styles: StyleChain,
- ) -> TypResult>> {
+ ) -> TypResult> {
// The actual repeating happens directly in the paragraph.
self.0.layout(ctx, regions, styles)
}
diff --git a/src/model/content.rs b/src/model/content.rs
index 3e27c02fd..d2af4595d 100644
--- a/src/model/content.rs
+++ b/src/model/content.rs
@@ -22,7 +22,7 @@ use crate::util::EcoString;
/// Layout content into a collection of pages.
///
/// Relayouts until all pinned locations are converged.
-pub fn layout(ctx: &mut Context, content: &Content) -> TypResult>> {
+pub fn layout(ctx: &mut Context, content: &Content) -> TypResult> {
let mut pass = 0;
let mut frames;
@@ -46,7 +46,7 @@ pub fn layout(ctx: &mut Context, content: &Content) -> TypResult>
}
/// Layout content into a collection of pages once.
-fn layout_once(ctx: &mut Context, content: &Content) -> TypResult>> {
+fn layout_once(ctx: &mut Context, content: &Content) -> TypResult> {
let copy = ctx.config.styles.clone();
let styles = StyleChain::with_root(©);
let scratch = Scratch::default();
@@ -263,7 +263,7 @@ impl Layout for Content {
ctx: &mut Context,
regions: &Regions,
styles: StyleChain,
- ) -> TypResult>> {
+ ) -> TypResult> {
let scratch = Scratch::default();
let mut builder = Builder::new(ctx, &scratch, false);
builder.accept(self, styles)?;
diff --git a/src/model/layout.rs b/src/model/layout.rs
index c971197aa..22797b482 100644
--- a/src/model/layout.rs
+++ b/src/model/layout.rs
@@ -28,7 +28,7 @@ pub trait Layout: 'static {
ctx: &mut Context,
regions: &Regions,
styles: StyleChain,
- ) -> TypResult>>;
+ ) -> TypResult>;
/// Convert to a packed node.
fn pack(self) -> LayoutNode
@@ -222,7 +222,7 @@ impl Layout for LayoutNode {
ctx: &mut Context,
regions: &Regions,
styles: StyleChain,
- ) -> TypResult>> {
+ ) -> TypResult> {
let prev = ctx.pins.dirty.replace(false);
let (result, at, fresh, dirty) = crate::memo::memoized(
@@ -238,7 +238,7 @@ impl Layout for LayoutNode {
if let Some(role) = styles.role() {
result = result.map(|mut frames| {
for frame in frames.iter_mut() {
- Arc::make_mut(frame).apply_role(role);
+ frame.apply_role(role);
}
frames
});
@@ -319,10 +319,10 @@ impl Layout for EmptyNode {
_: &mut Context,
regions: &Regions,
_: StyleChain,
- ) -> TypResult>> {
- Ok(vec![Arc::new(Frame::new(
+ ) -> TypResult> {
+ Ok(vec![Frame::new(
regions.expand.select(regions.first, Size::zero()),
- ))])
+ )])
}
}
@@ -341,7 +341,7 @@ impl Layout for SizedNode {
ctx: &mut Context,
regions: &Regions,
styles: StyleChain,
- ) -> TypResult>> {
+ ) -> TypResult> {
// The "pod" is the region into which the child will be layouted.
let pod = {
// Resolve the sizing to a concrete size.
@@ -367,7 +367,7 @@ impl Layout for SizedNode {
// Ensure frame size matches regions size if expansion is on.
let frame = &mut frames[0];
let target = regions.expand.select(regions.first, frame.size());
- Arc::make_mut(frame).resize(target, Align::LEFT_TOP);
+ frame.resize(target, Align::LEFT_TOP);
Ok(frames)
}
@@ -388,11 +388,11 @@ impl Layout for FillNode {
ctx: &mut Context,
regions: &Regions,
styles: StyleChain,
- ) -> TypResult>> {
+ ) -> TypResult> {
let mut frames = self.child.layout(ctx, regions, styles)?;
for frame in &mut frames {
let shape = Geometry::Rect(frame.size()).filled(self.fill);
- Arc::make_mut(frame).prepend(Point::zero(), Element::Shape(shape));
+ frame.prepend(Point::zero(), Element::Shape(shape));
}
Ok(frames)
}
@@ -413,11 +413,11 @@ impl Layout for StrokeNode {
ctx: &mut Context,
regions: &Regions,
styles: StyleChain,
- ) -> TypResult>> {
+ ) -> TypResult> {
let mut frames = self.child.layout(ctx, regions, styles)?;
for frame in &mut frames {
let shape = Geometry::Rect(frame.size()).stroked(self.stroke);
- Arc::make_mut(frame).prepend(Point::zero(), Element::Shape(shape));
+ frame.prepend(Point::zero(), Element::Shape(shape));
}
Ok(frames)
}
diff --git a/src/model/locate.rs b/src/model/locate.rs
index bda12ae9a..f6432d434 100644
--- a/src/model/locate.rs
+++ b/src/model/locate.rs
@@ -272,7 +272,7 @@ impl PinBoard {
}
/// Locate all pins in the frames.
- pub fn locate(&mut self, frames: &[Arc]) {
+ pub fn locate(&mut self, frames: &[Frame]) {
let mut flow = 0;
for (i, frame) in frames.iter().enumerate() {
locate_in_frame(
diff --git a/src/util/mod.rs b/src/util/mod.rs
index f762d88d5..df3858d6b 100644
--- a/src/util/mod.rs
+++ b/src/util/mod.rs
@@ -12,7 +12,7 @@ pub use prehashed::Prehashed;
use std::any::TypeId;
use std::cmp::Ordering;
use std::fmt::{self, Debug, Formatter};
-use std::ops::{Deref, Range};
+use std::ops::Range;
use std::path::{Component, Path, PathBuf};
use std::sync::Arc;
@@ -64,31 +64,6 @@ impl Debug for ReadableTypeId {
}
}
-/// Either owned or shared.
-pub enum MaybeShared {
- /// Owned data.
- Owned(T),
- /// Shared data.
- Shared(Arc),
-}
-
-impl AsRef for MaybeShared {
- fn as_ref(&self) -> &T {
- self
- }
-}
-
-impl Deref for MaybeShared {
- type Target = T;
-
- fn deref(&self) -> &Self::Target {
- match self {
- Self::Owned(owned) => owned,
- Self::Shared(shared) => shared,
- }
- }
-}
-
/// Extra methods for [`str`].
pub trait StrExt {
/// The number of code units this string would use if it was encoded in
diff --git a/tests/typeset.rs b/tests/typeset.rs
index 341a04c0a..31068656d 100644
--- a/tests/typeset.rs
+++ b/tests/typeset.rs
@@ -286,7 +286,7 @@ fn test_part(
line: usize,
print: &PrintConfig,
rng: &mut LinearShift,
-) -> (bool, bool, Vec>) {
+) -> (bool, bool, Vec) {
let mut ok = true;
let id = ctx.sources.provide(src_path, src);
@@ -532,7 +532,7 @@ fn test_spans_impl(node: &SyntaxNode, within: Range) -> bool {
}
/// Draw all frames into one image with padding in between.
-fn render(ctx: &mut Context, frames: &[Arc]) -> sk::Pixmap {
+fn render(ctx: &mut Context, frames: &[Frame]) -> sk::Pixmap {
let pixel_per_pt = 2.0;
let pixmaps: Vec<_> = frames
.iter()