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