2013-04-06 03:31:01 +04:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
2014-05-29 04:34:06 +04:00
|
|
|
//! Servo's experimental layout system builds a tree of `Flow` and `Fragment` objects and solves
|
2013-12-06 05:44:24 +04:00
|
|
|
//! layout constraints to obtain positions and display attributes of tree nodes. Positions are
|
|
|
|
//! computed in several tree traversals driven by the fundamental data dependencies required by
|
2015-08-04 01:46:12 +03:00
|
|
|
//! inline and block layout.
|
|
|
|
//!
|
|
|
|
//! Flows are interior nodes in the layout tree and correspond closely to *flow contexts* in the
|
|
|
|
//! CSS specification. Flows are responsible for positioning their child flow contexts and
|
|
|
|
//! fragments. Flows have purpose-specific fields, such as auxiliary line structs, out-of-flow
|
|
|
|
//! child lists, and so on.
|
|
|
|
//!
|
|
|
|
//! Currently, the important types of flows are:
|
|
|
|
//!
|
|
|
|
//! * `BlockFlow`: A flow that establishes a block context. It has several child flows, each of
|
|
|
|
//! which are positioned according to block formatting context rules (CSS block boxes). Block
|
|
|
|
//! flows also contain a single box to represent their rendered borders, padding, etc.
|
|
|
|
//! The BlockFlow at the root of the tree has special behavior: it stretches to the boundaries of
|
|
|
|
//! the viewport.
|
|
|
|
//!
|
|
|
|
//! * `InlineFlow`: A flow that establishes an inline context. It has a flat list of child
|
|
|
|
//! fragments/flows that are subject to inline layout and line breaking and structs to represent
|
|
|
|
//! line breaks and mapping to CSS boxes, for the purpose of handling `getClientRects()` and
|
|
|
|
//! similar methods.
|
2013-05-03 06:37:36 +04:00
|
|
|
|
2014-07-01 16:02:50 +04:00
|
|
|
use block::BlockFlow;
|
|
|
|
use context::LayoutContext;
|
2014-12-18 04:45:49 +03:00
|
|
|
use display_list_builder::DisplayListBuildingResult;
|
2014-07-01 16:02:50 +04:00
|
|
|
use floats::Floats;
|
2014-09-21 02:35:08 +04:00
|
|
|
use flow_list::{FlowList, FlowListIterator, MutFlowListIterator};
|
2015-03-16 22:16:03 +03:00
|
|
|
use flow_ref::{FlowRef, WeakFlowRef};
|
2015-03-03 23:16:24 +03:00
|
|
|
use fragment::{Fragment, FragmentBorderBoxIterator, SpecificFragmentInfo};
|
2015-03-10 08:24:47 +03:00
|
|
|
use incremental::{self, RECONSTRUCT_FLOW, REFLOW, REFLOW_OUT_OF_FLOW, RestyleDamage};
|
2014-07-01 16:02:50 +04:00
|
|
|
use inline::InlineFlow;
|
2015-03-10 08:24:47 +03:00
|
|
|
use model::{CollapsibleMargins, IntrinsicISizes, MarginCollapseInfo};
|
2014-07-01 16:02:50 +04:00
|
|
|
use parallel::FlowParallelInfo;
|
2014-12-12 04:06:53 +03:00
|
|
|
use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize, TableFlow};
|
2014-07-01 16:02:50 +04:00
|
|
|
use table_caption::TableCaptionFlow;
|
|
|
|
use table_cell::TableCellFlow;
|
2014-09-19 18:51:02 +04:00
|
|
|
use table_colgroup::TableColGroupFlow;
|
|
|
|
use table_row::TableRowFlow;
|
|
|
|
use table_rowgroup::TableRowGroupFlow;
|
|
|
|
use table_wrapper::TableWrapperFlow;
|
2015-04-29 03:48:45 +03:00
|
|
|
use multicol::MulticolFlow;
|
2015-08-07 07:11:04 +03:00
|
|
|
use wrapper::{PseudoElementType, ThreadSafeLayoutNode};
|
2013-10-29 00:31:44 +04:00
|
|
|
|
2015-06-19 05:50:22 +03:00
|
|
|
use euclid::{Point2D, Rect, Size2D};
|
2014-12-23 01:51:48 +03:00
|
|
|
use gfx::display_list::ClippingRegion;
|
2015-02-10 13:51:46 +03:00
|
|
|
use msg::compositor_msg::LayerId;
|
2015-04-27 20:29:15 +03:00
|
|
|
use msg::constellation_msg::ConstellationChan;
|
|
|
|
use rustc_serialize::{Encoder, Encodable};
|
2014-05-07 07:37:35 +04:00
|
|
|
use std::fmt;
|
2014-04-04 05:01:48 +04:00
|
|
|
use std::iter::Zip;
|
2015-04-27 20:29:15 +03:00
|
|
|
use std::mem;
|
2014-08-29 03:35:55 +04:00
|
|
|
use std::raw;
|
2015-01-28 04:15:50 +03:00
|
|
|
use std::slice::IterMut;
|
2015-04-15 02:14:11 +03:00
|
|
|
use std::sync::Arc;
|
|
|
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
2015-08-07 07:11:04 +03:00
|
|
|
use style::computed_values::{clear, display, empty_cells, float, position, text_align};
|
|
|
|
use style::properties::{self, ComputedValues};
|
2015-04-15 02:14:11 +03:00
|
|
|
use style::values::computed::LengthOrPercentageOrAuto;
|
2015-04-27 20:29:15 +03:00
|
|
|
use util::geometry::{Au, ZERO_RECT};
|
|
|
|
use util::logical_geometry::{LogicalRect, LogicalSize, WritingMode};
|
2012-11-12 07:42:44 +04:00
|
|
|
|
2013-10-29 00:31:44 +04:00
|
|
|
/// Virtual methods that make up a float context.
|
|
|
|
///
|
|
|
|
/// Note that virtual methods have a cost; we should not overuse them in Servo. Consider adding
|
|
|
|
/// methods to `ImmutableFlowUtils` or `MutableFlowUtils` before adding more methods here.
|
2015-02-12 03:24:45 +03:00
|
|
|
pub trait Flow: fmt::Debug + Sync {
|
2013-10-29 00:31:44 +04:00
|
|
|
// RTTI
|
|
|
|
//
|
|
|
|
// TODO(pcwalton): Use Rust's RTTI, once that works.
|
2012-09-22 03:23:30 +04:00
|
|
|
|
2013-10-29 00:31:44 +04:00
|
|
|
/// Returns the class of flow that this is.
|
|
|
|
fn class(&self) -> FlowClass;
|
2012-09-22 03:23:30 +04:00
|
|
|
|
2014-09-08 10:33:09 +04:00
|
|
|
/// If this is a block flow, returns the underlying object, borrowed immutably. Fails
|
|
|
|
/// otherwise.
|
|
|
|
fn as_immutable_block<'a>(&'a self) -> &'a BlockFlow {
|
2014-11-13 06:48:31 +03:00
|
|
|
panic!("called as_immutable_block() on a non-block flow")
|
2014-09-08 10:33:09 +04:00
|
|
|
}
|
|
|
|
|
2013-10-29 00:31:44 +04:00
|
|
|
/// If this is a block flow, returns the underlying object. Fails otherwise.
|
|
|
|
fn as_block<'a>(&'a mut self) -> &'a mut BlockFlow {
|
2015-01-28 04:15:50 +03:00
|
|
|
debug!("called as_block() on a flow of type {:?}", self.class());
|
2014-11-13 06:48:31 +03:00
|
|
|
panic!("called as_block() on a non-block flow")
|
2013-10-29 00:31:44 +04:00
|
|
|
}
|
2013-08-20 23:03:52 +04:00
|
|
|
|
2013-10-29 00:31:44 +04:00
|
|
|
/// If this is an inline flow, returns the underlying object, borrowed immutably. Fails
|
|
|
|
/// otherwise.
|
|
|
|
fn as_immutable_inline<'a>(&'a self) -> &'a InlineFlow {
|
2014-11-13 06:48:31 +03:00
|
|
|
panic!("called as_immutable_inline() on a non-inline flow")
|
2013-05-22 23:57:28 +04:00
|
|
|
}
|
2013-07-16 05:03:27 +04:00
|
|
|
|
2013-10-29 00:31:44 +04:00
|
|
|
/// If this is an inline flow, returns the underlying object. Fails otherwise.
|
|
|
|
fn as_inline<'a>(&'a mut self) -> &'a mut InlineFlow {
|
2014-11-13 06:48:31 +03:00
|
|
|
panic!("called as_inline() on a non-inline flow")
|
2013-10-29 00:31:44 +04:00
|
|
|
}
|
2013-07-16 05:03:27 +04:00
|
|
|
|
servo: Merge #1973 - Support fixed-layout table and a part of anonymous table object (from june0cho:table_rebase); r=larsbergstrom,metajack
This is a rebase of #1548 on recent master.
There have been many changes since #1548 is first uploaded, so I'm creating new PR.
This PR includes:
- construction of table-* flows (table-wrapper, table-caption, table, table-rowgroup, table-row, table-cell)
- fixed-layout table calculation
- a part of anonymous table object implementation
[CSS 2.1, 17.2.1](http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes) (Step 1-1, 1-2, Step 2)
Source-Repo: https://github.com/servo/servo
Source-Revision: fd5e5cd18b41f0ce2b33fb97fb4e3d75ddbbbceb
2014-03-25 21:40:47 +04:00
|
|
|
/// If this is a table wrapper flow, returns the underlying object. Fails otherwise.
|
|
|
|
fn as_table_wrapper<'a>(&'a mut self) -> &'a mut TableWrapperFlow {
|
2014-11-13 06:48:31 +03:00
|
|
|
panic!("called as_table_wrapper() on a non-tablewrapper flow")
|
servo: Merge #1973 - Support fixed-layout table and a part of anonymous table object (from june0cho:table_rebase); r=larsbergstrom,metajack
This is a rebase of #1548 on recent master.
There have been many changes since #1548 is first uploaded, so I'm creating new PR.
This PR includes:
- construction of table-* flows (table-wrapper, table-caption, table, table-rowgroup, table-row, table-cell)
- fixed-layout table calculation
- a part of anonymous table object implementation
[CSS 2.1, 17.2.1](http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes) (Step 1-1, 1-2, Step 2)
Source-Repo: https://github.com/servo/servo
Source-Revision: fd5e5cd18b41f0ce2b33fb97fb4e3d75ddbbbceb
2014-03-25 21:40:47 +04:00
|
|
|
}
|
|
|
|
|
2014-09-20 06:50:47 +04:00
|
|
|
/// If this is a table wrapper flow, returns the underlying object, borrowed immutably. Fails
|
|
|
|
/// otherwise.
|
|
|
|
fn as_immutable_table_wrapper<'a>(&'a self) -> &'a TableWrapperFlow {
|
2014-11-13 06:48:31 +03:00
|
|
|
panic!("called as_immutable_table_wrapper() on a non-tablewrapper flow")
|
2014-09-20 06:50:47 +04:00
|
|
|
}
|
|
|
|
|
servo: Merge #1973 - Support fixed-layout table and a part of anonymous table object (from june0cho:table_rebase); r=larsbergstrom,metajack
This is a rebase of #1548 on recent master.
There have been many changes since #1548 is first uploaded, so I'm creating new PR.
This PR includes:
- construction of table-* flows (table-wrapper, table-caption, table, table-rowgroup, table-row, table-cell)
- fixed-layout table calculation
- a part of anonymous table object implementation
[CSS 2.1, 17.2.1](http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes) (Step 1-1, 1-2, Step 2)
Source-Repo: https://github.com/servo/servo
Source-Revision: fd5e5cd18b41f0ce2b33fb97fb4e3d75ddbbbceb
2014-03-25 21:40:47 +04:00
|
|
|
/// If this is a table flow, returns the underlying object. Fails otherwise.
|
|
|
|
fn as_table<'a>(&'a mut self) -> &'a mut TableFlow {
|
2014-11-13 06:48:31 +03:00
|
|
|
panic!("called as_table() on a non-table flow")
|
servo: Merge #1973 - Support fixed-layout table and a part of anonymous table object (from june0cho:table_rebase); r=larsbergstrom,metajack
This is a rebase of #1548 on recent master.
There have been many changes since #1548 is first uploaded, so I'm creating new PR.
This PR includes:
- construction of table-* flows (table-wrapper, table-caption, table, table-rowgroup, table-row, table-cell)
- fixed-layout table calculation
- a part of anonymous table object implementation
[CSS 2.1, 17.2.1](http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes) (Step 1-1, 1-2, Step 2)
Source-Repo: https://github.com/servo/servo
Source-Revision: fd5e5cd18b41f0ce2b33fb97fb4e3d75ddbbbceb
2014-03-25 21:40:47 +04:00
|
|
|
}
|
|
|
|
|
2014-09-20 06:50:47 +04:00
|
|
|
/// If this is a table flow, returns the underlying object, borrowed immutably. Fails otherwise.
|
|
|
|
fn as_immutable_table<'a>(&'a self) -> &'a TableFlow {
|
2014-11-13 06:48:31 +03:00
|
|
|
panic!("called as_table() on a non-table flow")
|
2014-09-20 06:50:47 +04:00
|
|
|
}
|
|
|
|
|
servo: Merge #1973 - Support fixed-layout table and a part of anonymous table object (from june0cho:table_rebase); r=larsbergstrom,metajack
This is a rebase of #1548 on recent master.
There have been many changes since #1548 is first uploaded, so I'm creating new PR.
This PR includes:
- construction of table-* flows (table-wrapper, table-caption, table, table-rowgroup, table-row, table-cell)
- fixed-layout table calculation
- a part of anonymous table object implementation
[CSS 2.1, 17.2.1](http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes) (Step 1-1, 1-2, Step 2)
Source-Repo: https://github.com/servo/servo
Source-Revision: fd5e5cd18b41f0ce2b33fb97fb4e3d75ddbbbceb
2014-03-25 21:40:47 +04:00
|
|
|
/// If this is a table colgroup flow, returns the underlying object. Fails otherwise.
|
|
|
|
fn as_table_colgroup<'a>(&'a mut self) -> &'a mut TableColGroupFlow {
|
2014-11-13 06:48:31 +03:00
|
|
|
panic!("called as_table_colgroup() on a non-tablecolgroup flow")
|
servo: Merge #1973 - Support fixed-layout table and a part of anonymous table object (from june0cho:table_rebase); r=larsbergstrom,metajack
This is a rebase of #1548 on recent master.
There have been many changes since #1548 is first uploaded, so I'm creating new PR.
This PR includes:
- construction of table-* flows (table-wrapper, table-caption, table, table-rowgroup, table-row, table-cell)
- fixed-layout table calculation
- a part of anonymous table object implementation
[CSS 2.1, 17.2.1](http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes) (Step 1-1, 1-2, Step 2)
Source-Repo: https://github.com/servo/servo
Source-Revision: fd5e5cd18b41f0ce2b33fb97fb4e3d75ddbbbceb
2014-03-25 21:40:47 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/// If this is a table rowgroup flow, returns the underlying object. Fails otherwise.
|
|
|
|
fn as_table_rowgroup<'a>(&'a mut self) -> &'a mut TableRowGroupFlow {
|
2014-11-13 06:48:31 +03:00
|
|
|
panic!("called as_table_rowgroup() on a non-tablerowgroup flow")
|
servo: Merge #1973 - Support fixed-layout table and a part of anonymous table object (from june0cho:table_rebase); r=larsbergstrom,metajack
This is a rebase of #1548 on recent master.
There have been many changes since #1548 is first uploaded, so I'm creating new PR.
This PR includes:
- construction of table-* flows (table-wrapper, table-caption, table, table-rowgroup, table-row, table-cell)
- fixed-layout table calculation
- a part of anonymous table object implementation
[CSS 2.1, 17.2.1](http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes) (Step 1-1, 1-2, Step 2)
Source-Repo: https://github.com/servo/servo
Source-Revision: fd5e5cd18b41f0ce2b33fb97fb4e3d75ddbbbceb
2014-03-25 21:40:47 +04:00
|
|
|
}
|
|
|
|
|
2014-09-20 06:50:47 +04:00
|
|
|
/// If this is a table rowgroup flow, returns the underlying object, borrowed immutably. Fails
|
|
|
|
/// otherwise.
|
|
|
|
fn as_immutable_table_rowgroup<'a>(&'a self) -> &'a TableRowGroupFlow {
|
2014-11-13 06:48:31 +03:00
|
|
|
panic!("called as_table_rowgroup() on a non-tablerowgroup flow")
|
2014-09-20 06:50:47 +04:00
|
|
|
}
|
|
|
|
|
servo: Merge #1973 - Support fixed-layout table and a part of anonymous table object (from june0cho:table_rebase); r=larsbergstrom,metajack
This is a rebase of #1548 on recent master.
There have been many changes since #1548 is first uploaded, so I'm creating new PR.
This PR includes:
- construction of table-* flows (table-wrapper, table-caption, table, table-rowgroup, table-row, table-cell)
- fixed-layout table calculation
- a part of anonymous table object implementation
[CSS 2.1, 17.2.1](http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes) (Step 1-1, 1-2, Step 2)
Source-Repo: https://github.com/servo/servo
Source-Revision: fd5e5cd18b41f0ce2b33fb97fb4e3d75ddbbbceb
2014-03-25 21:40:47 +04:00
|
|
|
/// If this is a table row flow, returns the underlying object. Fails otherwise.
|
|
|
|
fn as_table_row<'a>(&'a mut self) -> &'a mut TableRowFlow {
|
2014-11-13 06:48:31 +03:00
|
|
|
panic!("called as_table_row() on a non-tablerow flow")
|
servo: Merge #1973 - Support fixed-layout table and a part of anonymous table object (from june0cho:table_rebase); r=larsbergstrom,metajack
This is a rebase of #1548 on recent master.
There have been many changes since #1548 is first uploaded, so I'm creating new PR.
This PR includes:
- construction of table-* flows (table-wrapper, table-caption, table, table-rowgroup, table-row, table-cell)
- fixed-layout table calculation
- a part of anonymous table object implementation
[CSS 2.1, 17.2.1](http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes) (Step 1-1, 1-2, Step 2)
Source-Repo: https://github.com/servo/servo
Source-Revision: fd5e5cd18b41f0ce2b33fb97fb4e3d75ddbbbceb
2014-03-25 21:40:47 +04:00
|
|
|
}
|
|
|
|
|
2014-09-20 06:50:47 +04:00
|
|
|
/// If this is a table row flow, returns the underlying object, borrowed immutably. Fails
|
|
|
|
/// otherwise.
|
|
|
|
fn as_immutable_table_row<'a>(&'a self) -> &'a TableRowFlow {
|
2014-11-13 06:48:31 +03:00
|
|
|
panic!("called as_table_row() on a non-tablerow flow")
|
2014-09-20 06:50:47 +04:00
|
|
|
}
|
|
|
|
|
servo: Merge #1973 - Support fixed-layout table and a part of anonymous table object (from june0cho:table_rebase); r=larsbergstrom,metajack
This is a rebase of #1548 on recent master.
There have been many changes since #1548 is first uploaded, so I'm creating new PR.
This PR includes:
- construction of table-* flows (table-wrapper, table-caption, table, table-rowgroup, table-row, table-cell)
- fixed-layout table calculation
- a part of anonymous table object implementation
[CSS 2.1, 17.2.1](http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes) (Step 1-1, 1-2, Step 2)
Source-Repo: https://github.com/servo/servo
Source-Revision: fd5e5cd18b41f0ce2b33fb97fb4e3d75ddbbbceb
2014-03-25 21:40:47 +04:00
|
|
|
/// If this is a table cell flow, returns the underlying object. Fails otherwise.
|
|
|
|
fn as_table_caption<'a>(&'a mut self) -> &'a mut TableCaptionFlow {
|
2014-11-13 06:48:31 +03:00
|
|
|
panic!("called as_table_caption() on a non-tablecaption flow")
|
servo: Merge #1973 - Support fixed-layout table and a part of anonymous table object (from june0cho:table_rebase); r=larsbergstrom,metajack
This is a rebase of #1548 on recent master.
There have been many changes since #1548 is first uploaded, so I'm creating new PR.
This PR includes:
- construction of table-* flows (table-wrapper, table-caption, table, table-rowgroup, table-row, table-cell)
- fixed-layout table calculation
- a part of anonymous table object implementation
[CSS 2.1, 17.2.1](http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes) (Step 1-1, 1-2, Step 2)
Source-Repo: https://github.com/servo/servo
Source-Revision: fd5e5cd18b41f0ce2b33fb97fb4e3d75ddbbbceb
2014-03-25 21:40:47 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/// If this is a table cell flow, returns the underlying object. Fails otherwise.
|
|
|
|
fn as_table_cell<'a>(&'a mut self) -> &'a mut TableCellFlow {
|
2014-11-13 06:48:31 +03:00
|
|
|
panic!("called as_table_cell() on a non-tablecell flow")
|
servo: Merge #1973 - Support fixed-layout table and a part of anonymous table object (from june0cho:table_rebase); r=larsbergstrom,metajack
This is a rebase of #1548 on recent master.
There have been many changes since #1548 is first uploaded, so I'm creating new PR.
This PR includes:
- construction of table-* flows (table-wrapper, table-caption, table, table-rowgroup, table-row, table-cell)
- fixed-layout table calculation
- a part of anonymous table object implementation
[CSS 2.1, 17.2.1](http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes) (Step 1-1, 1-2, Step 2)
Source-Repo: https://github.com/servo/servo
Source-Revision: fd5e5cd18b41f0ce2b33fb97fb4e3d75ddbbbceb
2014-03-25 21:40:47 +04:00
|
|
|
}
|
|
|
|
|
2015-04-29 03:48:45 +03:00
|
|
|
/// If this is a multicol flow, returns the underlying object. Fails otherwise.
|
|
|
|
fn as_multicol<'a>(&'a mut self) -> &'a mut MulticolFlow {
|
|
|
|
panic!("called as_multicol() on a non-multicol flow")
|
|
|
|
}
|
|
|
|
|
2014-09-20 06:50:47 +04:00
|
|
|
/// If this is a table cell flow, returns the underlying object, borrowed immutably. Fails
|
|
|
|
/// otherwise.
|
|
|
|
fn as_immutable_table_cell<'a>(&'a self) -> &'a TableCellFlow {
|
2014-11-13 06:48:31 +03:00
|
|
|
panic!("called as_table_cell() on a non-tablecell flow")
|
2014-09-20 06:50:47 +04:00
|
|
|
}
|
|
|
|
|
2014-12-12 04:06:53 +03:00
|
|
|
/// If this is a table row, table rowgroup, or table flow, returns column intrinsic
|
|
|
|
/// inline-sizes. Fails otherwise.
|
|
|
|
fn column_intrinsic_inline_sizes<'a>(&'a mut self) -> &'a mut Vec<ColumnIntrinsicInlineSize> {
|
|
|
|
panic!("called column_intrinsic_inline_sizes() on non-table flow")
|
|
|
|
}
|
|
|
|
|
|
|
|
/// If this is a table row, table rowgroup, or table flow, returns column computed
|
|
|
|
/// inline-sizes. Fails otherwise.
|
|
|
|
fn column_computed_inline_sizes<'a>(&'a mut self) -> &'a mut Vec<ColumnComputedInlineSize> {
|
|
|
|
panic!("called column_intrinsic_inline_sizes() on non-table flow")
|
2014-04-04 05:01:48 +04:00
|
|
|
}
|
|
|
|
|
2013-10-29 00:31:44 +04:00
|
|
|
// Main methods
|
2013-08-09 20:42:36 +04:00
|
|
|
|
2014-07-19 00:27:23 +04:00
|
|
|
/// Pass 1 of reflow: computes minimum and preferred inline-sizes.
|
2014-05-03 03:10:20 +04:00
|
|
|
///
|
2014-10-14 04:03:40 +04:00
|
|
|
/// Recursively (bottom-up) determine the flow's minimum and preferred inline-sizes. When
|
|
|
|
/// called on this flow, all child flows have had their minimum and preferred inline-sizes set.
|
|
|
|
/// This function must decide minimum/preferred inline-sizes based on its children's inline-
|
|
|
|
/// sizes and the dimensions of any boxes it is responsible for flowing.
|
2014-10-15 00:06:36 +04:00
|
|
|
fn bubble_inline_sizes(&mut self) {
|
2014-11-13 06:48:31 +03:00
|
|
|
panic!("bubble_inline_sizes not yet implemented")
|
2013-08-09 20:42:36 +04:00
|
|
|
}
|
2013-05-22 23:57:28 +04:00
|
|
|
|
2014-07-19 00:27:23 +04:00
|
|
|
/// Pass 2 of reflow: computes inline-size.
|
2014-08-11 16:20:07 +04:00
|
|
|
fn assign_inline_sizes(&mut self, _ctx: &LayoutContext) {
|
2014-11-13 06:48:31 +03:00
|
|
|
panic!("assign_inline_sizes not yet implemented")
|
2013-10-29 00:31:44 +04:00
|
|
|
}
|
2013-05-22 23:57:28 +04:00
|
|
|
|
2014-07-19 00:27:23 +04:00
|
|
|
/// Pass 3a of reflow: computes block-size.
|
2014-08-11 16:20:07 +04:00
|
|
|
fn assign_block_size<'a>(&mut self, _ctx: &'a LayoutContext<'a>) {
|
2014-11-13 06:48:31 +03:00
|
|
|
panic!("assign_block_size not yet implemented")
|
2013-10-29 00:31:44 +04:00
|
|
|
}
|
2013-05-22 23:57:28 +04:00
|
|
|
|
2014-11-19 02:39:25 +03:00
|
|
|
/// If this is a float, places it. The default implementation does nothing.
|
|
|
|
fn place_float_if_applicable<'a>(&mut self, _: &'a LayoutContext<'a>) {}
|
|
|
|
|
2014-07-19 00:27:23 +04:00
|
|
|
/// Assigns block-sizes in-order; or, if this is a float, places the float. The default
|
2014-10-14 04:03:40 +04:00
|
|
|
/// implementation simply assigns block-sizes if this flow is impacted by floats. Returns true
|
|
|
|
/// if this child was impacted by floats or false otherwise.
|
2015-02-21 09:06:48 +03:00
|
|
|
///
|
|
|
|
/// `parent_thread_id` is the thread ID of the parent. This is used for the layout tinting
|
|
|
|
/// debug mode; if the block size of this flow was determined by its parent, we should treat
|
|
|
|
/// it as laid out by its parent.
|
2014-10-14 04:03:40 +04:00
|
|
|
fn assign_block_size_for_inorder_child_if_necessary<'a>(&mut self,
|
2015-02-21 09:06:48 +03:00
|
|
|
layout_context: &'a LayoutContext<'a>,
|
|
|
|
parent_thread_id: u8)
|
2014-10-14 04:03:40 +04:00
|
|
|
-> bool {
|
2015-01-28 04:15:50 +03:00
|
|
|
let impacted = base(self).flags.impacted_by_floats();
|
2014-05-03 03:10:20 +04:00
|
|
|
if impacted {
|
2015-02-21 09:06:48 +03:00
|
|
|
mut_base(self).thread_id = parent_thread_id;
|
2014-07-19 00:27:23 +04:00
|
|
|
self.assign_block_size(layout_context);
|
2015-05-12 00:08:46 +03:00
|
|
|
self.store_overflow(layout_context);
|
2015-01-28 04:15:50 +03:00
|
|
|
mut_base(self).restyle_damage.remove(REFLOW_OUT_OF_FLOW | REFLOW);
|
2014-05-03 03:10:20 +04:00
|
|
|
}
|
|
|
|
impacted
|
|
|
|
}
|
|
|
|
|
2015-05-12 00:08:46 +03:00
|
|
|
/// Calculate and set overflow for current flow.
|
|
|
|
///
|
|
|
|
/// CSS Section 11.1
|
|
|
|
/// This is the union of rectangles of the flows for which we define the
|
|
|
|
/// Containing Block.
|
|
|
|
///
|
|
|
|
/// FIXME(pcwalton): This should not be a virtual method, but currently is due to a compiler
|
|
|
|
/// bug ("the trait `Sized` is not implemented for `self`").
|
|
|
|
///
|
|
|
|
/// Assumption: This is called in a bottom-up traversal, so kids' overflows have
|
|
|
|
/// already been set.
|
|
|
|
/// Assumption: Absolute descendants have had their overflow calculated.
|
|
|
|
fn store_overflow(&mut self, _: &LayoutContext) {
|
|
|
|
// Calculate overflow on a per-fragment basis.
|
|
|
|
let mut overflow = self.compute_overflow();
|
|
|
|
match self.class() {
|
|
|
|
FlowClass::Block |
|
|
|
|
FlowClass::TableCaption |
|
2015-08-17 11:33:28 +03:00
|
|
|
FlowClass::TableCell if !base(self).children.is_empty() => {
|
2015-05-12 00:08:46 +03:00
|
|
|
// FIXME(#2795): Get the real container size.
|
|
|
|
let container_size = Size2D::zero();
|
|
|
|
for kid in mut_base(self).children.iter_mut() {
|
|
|
|
if base(kid).flags.contains(IS_ABSOLUTELY_POSITIONED) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
let kid_overflow = base(kid).overflow;
|
|
|
|
let kid_position = base(kid).position.to_physical(base(kid).writing_mode,
|
|
|
|
container_size);
|
|
|
|
overflow = overflow.union(&kid_overflow.translate(&kid_position.origin))
|
|
|
|
}
|
|
|
|
|
|
|
|
for kid in mut_base(self).abs_descendants.iter() {
|
|
|
|
let kid_overflow = base(kid).overflow;
|
|
|
|
let kid_position = base(kid).position.to_physical(base(kid).writing_mode,
|
|
|
|
container_size);
|
|
|
|
overflow = overflow.union(&kid_overflow.translate(&kid_position.origin))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
mut_base(self).overflow = overflow;
|
|
|
|
}
|
|
|
|
|
2014-05-03 03:10:20 +04:00
|
|
|
/// Phase 4 of reflow: computes absolute positions.
|
2015-05-20 03:40:36 +03:00
|
|
|
fn compute_absolute_position(&mut self, _: &LayoutContext) {
|
2014-05-03 03:10:20 +04:00
|
|
|
// The default implementation is a no-op.
|
|
|
|
}
|
|
|
|
|
2014-10-22 20:54:35 +04:00
|
|
|
/// Phase 5 of reflow: builds display lists.
|
|
|
|
fn build_display_list(&mut self, layout_context: &LayoutContext);
|
|
|
|
|
2015-01-05 04:51:48 +03:00
|
|
|
/// Returns the union of all overflow rects of all of this flow's fragments.
|
|
|
|
fn compute_overflow(&self) -> Rect<Au>;
|
|
|
|
|
|
|
|
/// Iterates through border boxes of all of this flow's fragments.
|
2015-08-04 03:39:43 +03:00
|
|
|
/// Level provides a zero based index indicating the current
|
|
|
|
/// depth of the flow tree during fragment iteration.
|
2015-01-05 04:51:48 +03:00
|
|
|
fn iterate_through_fragment_border_boxes(&self,
|
|
|
|
iterator: &mut FragmentBorderBoxIterator,
|
2015-08-04 03:39:43 +03:00
|
|
|
level: i32,
|
2015-01-05 04:51:48 +03:00
|
|
|
stacking_context_position: &Point2D<Au>);
|
2014-11-03 22:03:37 +03:00
|
|
|
|
2015-03-10 08:24:47 +03:00
|
|
|
/// Mutably iterates through fragments in this flow.
|
|
|
|
fn mutate_fragments(&mut self, mutator: &mut FnMut(&mut Fragment));
|
|
|
|
|
|
|
|
fn compute_collapsible_block_start_margin(&mut self,
|
|
|
|
_layout_context: &mut LayoutContext,
|
|
|
|
_margin_collapse_info: &mut MarginCollapseInfo) {
|
|
|
|
// The default implementation is a no-op.
|
|
|
|
}
|
|
|
|
|
2013-11-18 23:54:00 +04:00
|
|
|
/// Marks this flow as the root flow. The default implementation is a no-op.
|
2015-07-31 11:10:40 +03:00
|
|
|
fn mark_as_root(&mut self) {
|
|
|
|
debug!("called mark_as_root() on a flow of type {:?}", self.class());
|
|
|
|
panic!("called mark_as_root() on an unhandled flow");
|
|
|
|
}
|
2013-11-18 23:54:00 +04:00
|
|
|
|
2014-03-03 22:37:33 +04:00
|
|
|
// Note that the following functions are mostly called using static method
|
|
|
|
// dispatch, so it's ok to have them in this trait. Plus, they have
|
|
|
|
// different behaviour for different types of Flow, so they can't go into
|
|
|
|
// the Immutable / Mutable Flow Utils traits without additional casts.
|
|
|
|
|
|
|
|
/// Return true if store overflow is delayed for this flow.
|
|
|
|
///
|
|
|
|
/// Currently happens only for absolutely positioned flows.
|
|
|
|
fn is_store_overflow_delayed(&mut self) -> bool {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
|
|
|
|
fn is_root(&self) -> bool {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
|
|
|
|
/// The 'position' property of this flow.
|
|
|
|
fn positioning(&self) -> position::T {
|
2015-01-08 18:00:57 +03:00
|
|
|
position::T::static_
|
2014-03-03 22:37:33 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Return true if this flow has position 'fixed'.
|
|
|
|
fn is_fixed(&self) -> bool {
|
2015-01-08 18:00:57 +03:00
|
|
|
self.positioning() == position::T::fixed
|
2014-03-03 22:37:33 +04:00
|
|
|
}
|
|
|
|
|
2015-05-13 22:27:21 +03:00
|
|
|
fn contains_positioned_fragments(&self) -> bool {
|
|
|
|
self.contains_relatively_positioned_fragments() ||
|
|
|
|
base(self).flags.contains(IS_ABSOLUTELY_POSITIONED)
|
2014-03-03 22:37:33 +04:00
|
|
|
}
|
|
|
|
|
2015-05-13 22:27:21 +03:00
|
|
|
fn contains_relatively_positioned_fragments(&self) -> bool {
|
2015-01-08 18:00:57 +03:00
|
|
|
self.positioning() == position::T::relative
|
2014-03-03 22:37:33 +04:00
|
|
|
}
|
|
|
|
|
2014-04-04 05:01:48 +04:00
|
|
|
/// Returns true if this is an absolute containing block.
|
|
|
|
fn is_absolute_containing_block(&self) -> bool {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
|
2014-10-02 05:36:25 +04:00
|
|
|
/// Updates the inline position of a child flow during the assign-height traversal. At present,
|
|
|
|
/// this is only used for absolutely-positioned inline-blocks.
|
|
|
|
fn update_late_computed_inline_position_if_necessary(&mut self, inline_position: Au);
|
|
|
|
|
|
|
|
/// Updates the block position of a child flow during the assign-height traversal. At present,
|
|
|
|
/// this is only used for absolutely-positioned inline-blocks.
|
|
|
|
fn update_late_computed_block_position_if_necessary(&mut self, block_position: Au);
|
|
|
|
|
2015-05-13 22:27:21 +03:00
|
|
|
/// Return the size of the containing block generated by this flow for the absolutely-
|
|
|
|
/// positioned descendant referenced by `for_flow`. For block flows, this is the padding box.
|
2014-12-13 01:57:46 +03:00
|
|
|
///
|
|
|
|
/// NB: Do not change this `&self` to `&mut self` under any circumstances! It has security
|
|
|
|
/// implications because this can be called on parents concurrently from descendants!
|
2015-05-13 22:27:21 +03:00
|
|
|
fn generated_containing_block_size(&self, _: OpaqueFlow) -> LogicalSize<Au>;
|
2014-03-03 22:37:33 +04:00
|
|
|
|
2014-04-04 05:01:48 +04:00
|
|
|
/// Returns a layer ID for the given fragment.
|
2015-03-21 14:12:45 +03:00
|
|
|
#[allow(unsafe_code)]
|
2015-03-28 22:58:02 +03:00
|
|
|
fn layer_id(&self, fragment_id: u32) -> LayerId {
|
|
|
|
let obj = unsafe { mem::transmute::<&&Self, &raw::TraitObject>(&self) };
|
|
|
|
LayerId(obj.data as usize, fragment_id)
|
2014-04-04 05:01:48 +04:00
|
|
|
}
|
2014-10-31 23:39:34 +03:00
|
|
|
|
|
|
|
/// Attempts to perform incremental fixup of this flow by replacing its fragment's style with
|
|
|
|
/// the new style. This can only succeed if the flow has exactly one fragment.
|
|
|
|
fn repair_style(&mut self, new_style: &Arc<ComputedValues>);
|
2015-03-04 01:12:45 +03:00
|
|
|
|
|
|
|
/// Remove any compositor layers associated with this flow
|
|
|
|
fn remove_compositor_layers(&self, _: ConstellationChan) {}
|
2013-05-22 23:57:28 +04:00
|
|
|
}
|
|
|
|
|
2013-10-29 00:31:44 +04:00
|
|
|
// Base access
|
|
|
|
|
|
|
|
#[inline(always)]
|
2015-03-21 14:12:45 +03:00
|
|
|
#[allow(unsafe_code)]
|
2015-01-28 04:15:50 +03:00
|
|
|
pub fn base<'a, T: ?Sized + Flow>(this: &'a T) -> &'a BaseFlow {
|
2013-10-29 00:31:44 +04:00
|
|
|
unsafe {
|
2015-01-28 04:15:50 +03:00
|
|
|
let obj = mem::transmute::<&&'a T, &'a raw::TraitObject>(&this);
|
2014-08-29 03:35:55 +04:00
|
|
|
mem::transmute::<*mut (), &'a BaseFlow>(obj.data)
|
2013-08-22 01:24:47 +04:00
|
|
|
}
|
2013-10-29 00:31:44 +04:00
|
|
|
}
|
2013-08-22 01:24:47 +04:00
|
|
|
|
2013-11-11 11:07:23 +04:00
|
|
|
/// Iterates over the children of this immutable flow.
|
2014-02-06 07:19:43 +04:00
|
|
|
pub fn imm_child_iter<'a>(flow: &'a Flow) -> FlowListIterator<'a> {
|
2013-11-11 11:07:23 +04:00
|
|
|
base(flow).children.iter()
|
|
|
|
}
|
|
|
|
|
2013-10-29 00:31:44 +04:00
|
|
|
#[inline(always)]
|
2015-03-21 14:12:45 +03:00
|
|
|
#[allow(unsafe_code)]
|
2015-01-28 04:15:50 +03:00
|
|
|
pub fn mut_base<'a, T: ?Sized + Flow>(this: &'a mut T) -> &'a mut BaseFlow {
|
2013-10-29 00:31:44 +04:00
|
|
|
unsafe {
|
2015-01-28 04:15:50 +03:00
|
|
|
let obj = mem::transmute::<&&'a mut T, &'a raw::TraitObject>(&this);
|
2014-08-29 03:35:55 +04:00
|
|
|
mem::transmute::<*mut (), &'a mut BaseFlow>(obj.data)
|
2013-05-08 00:44:45 +04:00
|
|
|
}
|
2013-10-29 00:31:44 +04:00
|
|
|
}
|
2013-08-20 23:03:52 +04:00
|
|
|
|
2013-10-29 00:31:44 +04:00
|
|
|
/// Iterates over the children of this flow.
|
2014-02-06 07:19:43 +04:00
|
|
|
pub fn child_iter<'a>(flow: &'a mut Flow) -> MutFlowListIterator<'a> {
|
2014-09-21 02:35:08 +04:00
|
|
|
mut_base(flow).children.iter_mut()
|
2013-10-29 00:31:44 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
pub trait ImmutableFlowUtils {
|
|
|
|
// Convenience functions
|
|
|
|
|
2015-04-27 20:29:15 +03:00
|
|
|
/// Returns true if this flow is a block flow or subclass thereof.
|
2013-10-29 00:31:44 +04:00
|
|
|
fn is_block_like(self) -> bool;
|
|
|
|
|
servo: Merge #1973 - Support fixed-layout table and a part of anonymous table object (from june0cho:table_rebase); r=larsbergstrom,metajack
This is a rebase of #1548 on recent master.
There have been many changes since #1548 is first uploaded, so I'm creating new PR.
This PR includes:
- construction of table-* flows (table-wrapper, table-caption, table, table-rowgroup, table-row, table-cell)
- fixed-layout table calculation
- a part of anonymous table object implementation
[CSS 2.1, 17.2.1](http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes) (Step 1-1, 1-2, Step 2)
Source-Repo: https://github.com/servo/servo
Source-Revision: fd5e5cd18b41f0ce2b33fb97fb4e3d75ddbbbceb
2014-03-25 21:40:47 +04:00
|
|
|
/// Returns true if this flow is a table flow.
|
|
|
|
fn is_table(self) -> bool;
|
|
|
|
|
|
|
|
/// Returns true if this flow is a table caption flow.
|
|
|
|
fn is_table_caption(self) -> bool;
|
|
|
|
|
|
|
|
/// Returns true if this flow is a proper table child.
|
|
|
|
fn is_proper_table_child(self) -> bool;
|
|
|
|
|
|
|
|
/// Returns true if this flow is a table row flow.
|
|
|
|
fn is_table_row(self) -> bool;
|
|
|
|
|
|
|
|
/// Returns true if this flow is a table cell flow.
|
|
|
|
fn is_table_cell(self) -> bool;
|
|
|
|
|
|
|
|
/// Returns true if this flow is a table colgroup flow.
|
|
|
|
fn is_table_colgroup(self) -> bool;
|
|
|
|
|
|
|
|
/// Returns true if this flow is a table rowgroup flow.
|
|
|
|
fn is_table_rowgroup(self) -> bool;
|
|
|
|
|
|
|
|
/// Returns true if this flow is one of table-related flows.
|
|
|
|
fn is_table_kind(self) -> bool;
|
|
|
|
|
|
|
|
/// Returns true if anonymous flow is needed between this flow and child flow.
|
|
|
|
fn need_anonymous_flow(self, child: &Flow) -> bool;
|
|
|
|
|
|
|
|
/// Generates missing child flow of this flow.
|
2014-06-04 09:25:28 +04:00
|
|
|
fn generate_missing_child_flow(self, node: &ThreadSafeLayoutNode) -> FlowRef;
|
servo: Merge #1973 - Support fixed-layout table and a part of anonymous table object (from june0cho:table_rebase); r=larsbergstrom,metajack
This is a rebase of #1548 on recent master.
There have been many changes since #1548 is first uploaded, so I'm creating new PR.
This PR includes:
- construction of table-* flows (table-wrapper, table-caption, table, table-rowgroup, table-row, table-cell)
- fixed-layout table calculation
- a part of anonymous table object implementation
[CSS 2.1, 17.2.1](http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes) (Step 1-1, 1-2, Step 2)
Source-Repo: https://github.com/servo/servo
Source-Revision: fd5e5cd18b41f0ce2b33fb97fb4e3d75ddbbbceb
2014-03-25 21:40:47 +04:00
|
|
|
|
2015-05-13 22:27:21 +03:00
|
|
|
/// Returns true if this flow contains fragments that are roots of an absolute flow tree.
|
|
|
|
fn contains_roots_of_absolute_flow_tree(&self) -> bool;
|
|
|
|
|
2013-10-29 00:31:44 +04:00
|
|
|
/// Returns true if this flow has no children.
|
|
|
|
fn is_leaf(self) -> bool;
|
|
|
|
|
2014-01-23 04:04:08 +04:00
|
|
|
/// Returns the number of children that this flow possesses.
|
2015-04-02 17:06:41 +03:00
|
|
|
fn child_count(self) -> usize;
|
2014-01-23 04:04:08 +04:00
|
|
|
|
2014-02-05 02:52:39 +04:00
|
|
|
/// Return true if this flow is a Block Container.
|
|
|
|
fn is_block_container(self) -> bool;
|
|
|
|
|
2014-02-19 01:17:07 +04:00
|
|
|
/// Returns true if this flow is a block flow.
|
|
|
|
fn is_block_flow(self) -> bool;
|
2013-10-29 00:31:44 +04:00
|
|
|
|
|
|
|
/// Returns true if this flow is an inline flow.
|
2014-02-19 01:17:07 +04:00
|
|
|
fn is_inline_flow(self) -> bool;
|
2013-10-29 00:31:44 +04:00
|
|
|
|
|
|
|
/// Dumps the flow tree for debugging.
|
|
|
|
fn dump(self);
|
2013-11-11 11:07:23 +04:00
|
|
|
|
|
|
|
/// Dumps the flow tree for debugging, with a prefix to indicate that we're at the given level.
|
2015-04-02 17:06:41 +03:00
|
|
|
fn dump_with_level(self, level: u32);
|
2013-10-29 00:31:44 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
pub trait MutableFlowUtils {
|
|
|
|
// Traversals
|
|
|
|
|
|
|
|
/// Traverses the tree in preorder.
|
2015-08-16 17:37:40 +03:00
|
|
|
fn traverse_preorder<T: PreorderFlowTraversal>(self, traversal: &T);
|
2013-10-29 00:31:44 +04:00
|
|
|
|
|
|
|
/// Traverses the tree in postorder.
|
2015-08-16 17:37:40 +03:00
|
|
|
fn traverse_postorder<T: PostorderFlowTraversal>(self, traversal: &T);
|
2013-10-29 00:31:44 +04:00
|
|
|
|
2015-05-13 22:27:21 +03:00
|
|
|
/// Traverse the Absolute flow tree in preorder.
|
|
|
|
///
|
|
|
|
/// Traverse all your direct absolute descendants, who will then traverse
|
|
|
|
/// their direct absolute descendants.
|
|
|
|
///
|
|
|
|
/// Return true if the traversal is to continue or false to stop.
|
|
|
|
fn traverse_preorder_absolute_flows<T>(&mut self, traversal: &mut T)
|
|
|
|
where T: PreorderFlowTraversal;
|
|
|
|
|
|
|
|
/// Traverse the Absolute flow tree in postorder.
|
|
|
|
///
|
|
|
|
/// Return true if the traversal is to continue or false to stop.
|
|
|
|
fn traverse_postorder_absolute_flows<T>(&mut self, traversal: &mut T)
|
|
|
|
where T: PostorderFlowTraversal;
|
|
|
|
|
2013-10-29 00:31:44 +04:00
|
|
|
// Mutators
|
|
|
|
|
2015-04-01 21:03:45 +03:00
|
|
|
/// Calls `repair_style` and `bubble_inline_sizes`. You should use this method instead of
|
|
|
|
/// calling them individually, since there is no reason not to perform both operations.
|
|
|
|
fn repair_style_and_bubble_inline_sizes(self, style: &Arc<ComputedValues>);
|
2013-10-29 00:31:44 +04:00
|
|
|
}
|
|
|
|
|
2014-01-23 04:04:08 +04:00
|
|
|
pub trait MutableOwnedFlowUtils {
|
2014-03-03 22:37:33 +04:00
|
|
|
/// Set absolute descendants for this flow.
|
|
|
|
///
|
|
|
|
/// Set this flow as the Containing Block for all the absolute descendants.
|
2014-09-19 18:51:02 +04:00
|
|
|
fn set_absolute_descendants(&mut self, abs_descendants: AbsDescendants);
|
2014-01-23 04:04:08 +04:00
|
|
|
}
|
|
|
|
|
2015-02-12 03:24:45 +03:00
|
|
|
#[derive(RustcEncodable, PartialEq, Debug)]
|
2013-10-29 00:31:44 +04:00
|
|
|
pub enum FlowClass {
|
2014-12-18 04:45:49 +03:00
|
|
|
Block,
|
|
|
|
Inline,
|
|
|
|
ListItem,
|
|
|
|
TableWrapper,
|
|
|
|
Table,
|
|
|
|
TableColGroup,
|
|
|
|
TableRowGroup,
|
|
|
|
TableRow,
|
|
|
|
TableCaption,
|
|
|
|
TableCell,
|
2015-04-29 03:48:45 +03:00
|
|
|
Multicol,
|
2013-08-20 23:03:52 +04:00
|
|
|
}
|
2013-08-17 02:46:03 +04:00
|
|
|
|
2013-10-29 00:31:44 +04:00
|
|
|
/// A top-down traversal.
|
|
|
|
pub trait PreorderFlowTraversal {
|
|
|
|
/// The operation to perform. Return true to continue or false to stop.
|
2014-10-15 05:33:28 +04:00
|
|
|
fn process(&self, flow: &mut Flow);
|
2013-10-29 00:31:44 +04:00
|
|
|
|
2014-10-09 21:21:32 +04:00
|
|
|
/// Returns true if this node must be processed in-order. If this returns false,
|
|
|
|
/// we skip the operation for this node, but continue processing the descendants.
|
|
|
|
/// This is called *after* parent nodes are visited.
|
2014-10-15 05:33:28 +04:00
|
|
|
fn should_process(&self, _flow: &mut Flow) -> bool {
|
2014-10-09 21:21:32 +04:00
|
|
|
true
|
|
|
|
}
|
2013-10-29 00:31:44 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/// A bottom-up traversal, with a optional in-order pass.
|
|
|
|
pub trait PostorderFlowTraversal {
|
|
|
|
/// The operation to perform. Return true to continue or false to stop.
|
2014-10-15 05:33:28 +04:00
|
|
|
fn process(&self, flow: &mut Flow);
|
2013-10-29 00:31:44 +04:00
|
|
|
|
|
|
|
/// Returns false if this node must be processed in-order. If this returns false, we skip the
|
2014-01-23 04:04:08 +04:00
|
|
|
/// operation for this node, but continue processing the ancestors. This is called *after*
|
2013-10-29 00:31:44 +04:00
|
|
|
/// child nodes are visited.
|
2014-10-15 05:33:28 +04:00
|
|
|
fn should_process(&self, _flow: &mut Flow) -> bool {
|
2013-10-29 00:31:44 +04:00
|
|
|
true
|
2013-08-17 02:46:03 +04:00
|
|
|
}
|
2013-05-08 00:44:45 +04:00
|
|
|
}
|
|
|
|
|
2015-03-10 08:24:47 +03:00
|
|
|
/// An in-order (sequential only) traversal.
|
|
|
|
pub trait InorderFlowTraversal {
|
|
|
|
/// The operation to perform. Returns the level of the tree we're at.
|
|
|
|
fn process(&mut self, flow: &mut Flow, level: u32);
|
|
|
|
|
|
|
|
/// Returns true if this node should be processed and false if neither this node nor its
|
|
|
|
/// descendants should be processed.
|
|
|
|
fn should_process(&mut self, flow: &mut Flow) -> bool;
|
|
|
|
}
|
|
|
|
|
2014-11-18 21:42:32 +03:00
|
|
|
bitflags! {
|
|
|
|
#[doc = "Flags used in flows."]
|
2015-03-10 08:24:47 +03:00
|
|
|
flags FlowFlags: u32 {
|
2014-11-18 21:42:32 +03:00
|
|
|
// floated descendants flags
|
|
|
|
#[doc = "Whether this flow has descendants that float left in the same block formatting"]
|
|
|
|
#[doc = "context."]
|
2015-03-10 08:24:47 +03:00
|
|
|
const HAS_LEFT_FLOATED_DESCENDANTS = 0b0000_0000_0000_0000_0001,
|
2014-11-18 21:42:32 +03:00
|
|
|
#[doc = "Whether this flow has descendants that float right in the same block formatting"]
|
|
|
|
#[doc = "context."]
|
2015-03-10 08:24:47 +03:00
|
|
|
const HAS_RIGHT_FLOATED_DESCENDANTS = 0b0000_0000_0000_0000_0010,
|
2014-11-18 21:42:32 +03:00
|
|
|
#[doc = "Whether this flow is impacted by floats to the left in the same block formatting"]
|
|
|
|
#[doc = "context (i.e. its height depends on some prior flows with `float: left`)."]
|
2015-03-10 08:24:47 +03:00
|
|
|
const IMPACTED_BY_LEFT_FLOATS = 0b0000_0000_0000_0000_0100,
|
2014-11-18 21:42:32 +03:00
|
|
|
#[doc = "Whether this flow is impacted by floats to the right in the same block"]
|
|
|
|
#[doc = "formatting context (i.e. its height depends on some prior flows with `float:"]
|
|
|
|
#[doc = "right`)."]
|
2015-03-10 08:24:47 +03:00
|
|
|
const IMPACTED_BY_RIGHT_FLOATS = 0b0000_0000_0000_0000_1000,
|
2014-11-18 21:42:32 +03:00
|
|
|
|
|
|
|
// text align flags
|
|
|
|
#[doc = "Whether this flow contains a flow that has its own layer within the same absolute"]
|
|
|
|
#[doc = "containing block."]
|
2015-03-10 08:24:47 +03:00
|
|
|
const LAYERS_NEEDED_FOR_DESCENDANTS = 0b0000_0000_0000_0001_0000,
|
2014-11-18 21:42:32 +03:00
|
|
|
#[doc = "Whether this flow must have its own layer. Even if this flag is not set, it might"]
|
|
|
|
#[doc = "get its own layer if it's deemed to be likely to overlap flows with their own"]
|
|
|
|
#[doc = "layer."]
|
2015-03-10 08:24:47 +03:00
|
|
|
const NEEDS_LAYER = 0b0000_0000_0000_0010_0000,
|
2014-11-18 21:42:32 +03:00
|
|
|
#[doc = "Whether this flow is absolutely positioned. This is checked all over layout, so a"]
|
|
|
|
#[doc = "virtual call is too expensive."]
|
2015-03-10 08:24:47 +03:00
|
|
|
const IS_ABSOLUTELY_POSITIONED = 0b0000_0000_0000_0100_0000,
|
2014-11-18 21:42:32 +03:00
|
|
|
#[doc = "Whether this flow clears to the left. This is checked all over layout, so a"]
|
|
|
|
#[doc = "virtual call is too expensive."]
|
2015-03-10 08:24:47 +03:00
|
|
|
const CLEARS_LEFT = 0b0000_0000_0000_1000_0000,
|
2014-11-18 21:42:32 +03:00
|
|
|
#[doc = "Whether this flow clears to the right. This is checked all over layout, so a"]
|
|
|
|
#[doc = "virtual call is too expensive."]
|
2015-03-10 08:24:47 +03:00
|
|
|
const CLEARS_RIGHT = 0b0000_0000_0001_0000_0000,
|
2014-11-18 21:42:32 +03:00
|
|
|
#[doc = "Whether this flow is left-floated. This is checked all over layout, so a"]
|
|
|
|
#[doc = "virtual call is too expensive."]
|
2015-03-10 08:24:47 +03:00
|
|
|
const FLOATS_LEFT = 0b0000_0000_0010_0000_0000,
|
2014-11-18 21:42:32 +03:00
|
|
|
#[doc = "Whether this flow is right-floated. This is checked all over layout, so a"]
|
|
|
|
#[doc = "virtual call is too expensive."]
|
2015-03-10 08:24:47 +03:00
|
|
|
const FLOATS_RIGHT = 0b0000_0000_0100_0000_0000,
|
2014-12-01 22:12:55 +03:00
|
|
|
#[doc = "Text alignment. \
|
|
|
|
|
|
|
|
NB: If you update this, update `TEXT_ALIGN_SHIFT` below."]
|
2015-03-10 08:24:47 +03:00
|
|
|
const TEXT_ALIGN = 0b0000_0111_1000_0000_0000,
|
|
|
|
#[doc = "Whether this flow has a fragment with `counter-reset` or `counter-increment` \
|
|
|
|
styles."]
|
|
|
|
const AFFECTS_COUNTERS = 0b0000_1000_0000_0000_0000,
|
|
|
|
#[doc = "Whether this flow's descendants have fragments that affect `counter-reset` or \
|
|
|
|
`counter-increment` styles."]
|
2015-04-15 02:14:11 +03:00
|
|
|
const HAS_COUNTER_AFFECTING_CHILDREN = 0b0001_0000_0000_0000_0000,
|
|
|
|
#[doc = "Whether this flow behaves as though it had `position: static` for the purposes \
|
|
|
|
of positioning in the inline direction. This is set for flows with `position: \
|
|
|
|
static` and `position: relative` as well as absolutely-positioned flows with \
|
|
|
|
unconstrained positions in the inline direction."]
|
|
|
|
const INLINE_POSITION_IS_STATIC = 0b0010_0000_0000_0000_0000,
|
|
|
|
#[doc = "Whether this flow behaves as though it had `position: static` for the purposes \
|
|
|
|
of positioning in the block direction. This is set for flows with `position: \
|
|
|
|
static` and `position: relative` as well as absolutely-positioned flows with \
|
|
|
|
unconstrained positions in the block direction."]
|
|
|
|
const BLOCK_POSITION_IS_STATIC = 0b0100_0000_0000_0000_0000,
|
2014-11-18 21:42:32 +03:00
|
|
|
}
|
|
|
|
}
|
2013-12-13 05:58:21 +04:00
|
|
|
|
2014-11-18 21:42:32 +03:00
|
|
|
// NB: If you update this field, you must update the the floated descendants flags.
|
2014-05-03 03:10:20 +04:00
|
|
|
/// The bitmask of flags that represent the `has_left_floated_descendants` and
|
|
|
|
/// `has_right_floated_descendants` fields.
|
|
|
|
|
2014-11-18 21:42:32 +03:00
|
|
|
static HAS_FLOATED_DESCENDANTS_BITMASK: FlowFlags = FlowFlags { bits: 0b0000_0011 };
|
|
|
|
|
2013-12-17 03:25:12 +04:00
|
|
|
/// The number of bits we must shift off to handle the text alignment field.
|
2014-12-01 22:12:55 +03:00
|
|
|
///
|
|
|
|
/// NB: If you update this, update `TEXT_ALIGN` above.
|
2015-04-02 17:06:41 +03:00
|
|
|
static TEXT_ALIGN_SHIFT: usize = 11;
|
2014-04-04 05:01:48 +04:00
|
|
|
|
2013-12-17 03:25:12 +04:00
|
|
|
impl FlowFlags {
|
2014-05-02 22:58:29 +04:00
|
|
|
/// Propagates text alignment flags from an appropriate parent flow per CSS 2.1.
|
|
|
|
///
|
|
|
|
/// FIXME(#2265, pcwalton): It would be cleaner and faster to make this a derived CSS property
|
|
|
|
/// `-servo-text-align-in-effect`.
|
|
|
|
pub fn propagate_text_alignment_from_parent(&mut self, parent_flags: FlowFlags) {
|
|
|
|
self.set_text_align_override(parent_flags);
|
|
|
|
}
|
|
|
|
|
2013-12-17 03:25:12 +04:00
|
|
|
#[inline]
|
|
|
|
pub fn text_align(self) -> text_align::T {
|
2015-05-05 17:11:30 +03:00
|
|
|
text_align::T::from_u32((self & TEXT_ALIGN).bits() >> TEXT_ALIGN_SHIFT).unwrap()
|
2013-12-17 03:25:12 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn set_text_align(&mut self, value: text_align::T) {
|
2014-12-01 22:12:55 +03:00
|
|
|
*self = (*self & !TEXT_ALIGN) |
|
2015-05-05 17:11:30 +03:00
|
|
|
FlowFlags::from_bits(value.to_u32() << TEXT_ALIGN_SHIFT).unwrap();
|
2013-12-17 03:25:12 +04:00
|
|
|
}
|
2014-01-23 05:13:03 +04:00
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn set_text_align_override(&mut self, parent: FlowFlags) {
|
2014-12-01 22:12:55 +03:00
|
|
|
self.insert(parent & TEXT_ALIGN);
|
2014-01-23 05:13:03 +04:00
|
|
|
}
|
2014-05-03 03:10:20 +04:00
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn union_floated_descendants_flags(&mut self, other: FlowFlags) {
|
2014-11-18 21:42:32 +03:00
|
|
|
self.insert(other & HAS_FLOATED_DESCENDANTS_BITMASK);
|
2014-05-03 03:10:20 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn impacted_by_floats(&self) -> bool {
|
2014-11-18 21:42:32 +03:00
|
|
|
self.contains(IMPACTED_BY_LEFT_FLOATS) || self.contains(IMPACTED_BY_RIGHT_FLOATS)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn set(&mut self, flags: FlowFlags, value: bool) {
|
|
|
|
if value {
|
|
|
|
self.insert(flags);
|
|
|
|
} else {
|
|
|
|
self.remove(flags);
|
|
|
|
}
|
2014-05-03 03:10:20 +04:00
|
|
|
}
|
2014-10-29 05:42:38 +03:00
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn float_kind(&self) -> float::T {
|
2014-11-18 21:42:32 +03:00
|
|
|
if self.contains(FLOATS_LEFT) {
|
2015-01-08 18:00:57 +03:00
|
|
|
float::T::left
|
2014-11-18 21:42:32 +03:00
|
|
|
} else if self.contains(FLOATS_RIGHT) {
|
2015-01-08 18:00:57 +03:00
|
|
|
float::T::right
|
2014-10-29 05:42:38 +03:00
|
|
|
} else {
|
2015-01-08 18:00:57 +03:00
|
|
|
float::T::none
|
2014-10-29 05:42:38 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-19 02:39:25 +03:00
|
|
|
#[inline]
|
|
|
|
pub fn is_float(&self) -> bool {
|
|
|
|
self.contains(FLOATS_LEFT) || self.contains(FLOATS_RIGHT)
|
|
|
|
}
|
|
|
|
|
2014-10-29 05:42:38 +03:00
|
|
|
#[inline]
|
|
|
|
pub fn clears_floats(&self) -> bool {
|
2014-11-18 21:42:32 +03:00
|
|
|
self.contains(CLEARS_LEFT) || self.contains(CLEARS_RIGHT)
|
2014-10-29 05:42:38 +03:00
|
|
|
}
|
2013-12-17 03:25:12 +04:00
|
|
|
}
|
|
|
|
|
2014-03-03 22:37:33 +04:00
|
|
|
/// The Descendants of a flow.
|
|
|
|
///
|
|
|
|
/// Also, details about their position wrt this flow.
|
2015-01-28 04:15:50 +03:00
|
|
|
#[derive(Clone)]
|
2014-03-03 22:37:33 +04:00
|
|
|
pub struct Descendants {
|
2014-06-04 09:25:28 +04:00
|
|
|
/// Links to every descendant. This must be private because it is unsafe to leak `FlowRef`s to
|
|
|
|
/// layout.
|
|
|
|
descendant_links: Vec<FlowRef>,
|
2014-03-03 22:37:33 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Descendants {
|
|
|
|
pub fn new() -> Descendants {
|
|
|
|
Descendants {
|
2014-05-06 05:01:24 +04:00
|
|
|
descendant_links: Vec::new(),
|
2014-03-03 22:37:33 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-02 17:06:41 +03:00
|
|
|
pub fn len(&self) -> usize {
|
2014-03-03 22:37:33 +04:00
|
|
|
self.descendant_links.len()
|
|
|
|
}
|
|
|
|
|
2014-10-23 04:48:31 +04:00
|
|
|
pub fn is_empty(&self) -> bool {
|
|
|
|
self.descendant_links.is_empty()
|
|
|
|
}
|
|
|
|
|
2014-06-04 09:25:28 +04:00
|
|
|
pub fn push(&mut self, given_descendant: FlowRef) {
|
2014-03-03 22:37:33 +04:00
|
|
|
self.descendant_links.push(given_descendant);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Push the given descendants on to the existing descendants.
|
|
|
|
///
|
|
|
|
/// Ignore any static y offsets, because they are None before layout.
|
2014-05-07 09:16:22 +04:00
|
|
|
pub fn push_descendants(&mut self, given_descendants: Descendants) {
|
2014-09-21 02:35:08 +04:00
|
|
|
for elem in given_descendants.descendant_links.into_iter() {
|
2014-03-03 22:37:33 +04:00
|
|
|
self.descendant_links.push(elem);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Return an iterator over the descendant flows.
|
|
|
|
pub fn iter<'a>(&'a mut self) -> DescendantIter<'a> {
|
2014-06-04 09:25:28 +04:00
|
|
|
DescendantIter {
|
2015-02-12 21:06:50 +03:00
|
|
|
iter: self.descendant_links.iter_mut(),
|
2014-06-04 09:25:28 +04:00
|
|
|
}
|
2014-03-03 22:37:33 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub type AbsDescendants = Descendants;
|
|
|
|
|
2014-06-04 09:25:28 +04:00
|
|
|
pub struct DescendantIter<'a> {
|
2015-01-28 04:15:50 +03:00
|
|
|
iter: IterMut<'a, FlowRef>,
|
2014-06-04 09:25:28 +04:00
|
|
|
}
|
|
|
|
|
2015-01-28 04:15:50 +03:00
|
|
|
impl<'a> Iterator for DescendantIter<'a> {
|
|
|
|
type Item = &'a mut (Flow + 'a);
|
2015-01-08 18:00:57 +03:00
|
|
|
fn next(&mut self) -> Option<&'a mut (Flow + 'a)> {
|
2014-12-16 18:54:51 +03:00
|
|
|
self.iter.next().map(|flow| &mut **flow)
|
2014-06-04 09:25:28 +04:00
|
|
|
}
|
|
|
|
}
|
2014-03-03 22:37:33 +04:00
|
|
|
|
2015-01-28 04:15:50 +03:00
|
|
|
pub type DescendantOffsetIter<'a> = Zip<DescendantIter<'a>, IterMut<'a, Au>>;
|
2014-03-03 22:37:33 +04:00
|
|
|
|
2014-05-03 03:10:20 +04:00
|
|
|
/// Information needed to compute absolute (i.e. viewport-relative) flow positions (not to be
|
|
|
|
/// confused with absolutely-positioned flows).
|
2015-04-29 01:52:49 +03:00
|
|
|
#[derive(RustcEncodable, Copy, Clone)]
|
2014-05-03 03:10:20 +04:00
|
|
|
pub struct AbsolutePositionInfo {
|
|
|
|
/// The size of the containing block for relatively-positioned descendants.
|
2014-07-19 00:27:23 +04:00
|
|
|
pub relative_containing_block_size: LogicalSize<Au>,
|
2014-10-14 10:42:35 +04:00
|
|
|
|
2015-03-10 00:54:51 +03:00
|
|
|
/// The writing mode for `relative_containing_block_size`.
|
|
|
|
pub relative_containing_block_mode: WritingMode,
|
|
|
|
|
2014-11-17 02:39:27 +03:00
|
|
|
/// The position of the absolute containing block relative to the nearest ancestor stacking
|
|
|
|
/// context. If the absolute containing block establishes the stacking context for this flow,
|
|
|
|
/// and this flow is not itself absolutely-positioned, then this is (0, 0).
|
|
|
|
pub stacking_relative_position_of_absolute_containing_block: Point2D<Au>,
|
2014-10-14 10:42:35 +04:00
|
|
|
|
2014-05-03 03:10:20 +04:00
|
|
|
/// Whether the absolute containing block forces positioned descendants to be layerized.
|
|
|
|
///
|
|
|
|
/// FIXME(pcwalton): Move into `FlowFlags`.
|
|
|
|
pub layers_needed_for_positioned_flows: bool,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl AbsolutePositionInfo {
|
2014-07-19 00:27:23 +04:00
|
|
|
pub fn new(writing_mode: WritingMode) -> AbsolutePositionInfo {
|
|
|
|
// FIXME(pcwalton): The initial relative containing block-size should be equal to the size
|
2014-05-03 03:10:20 +04:00
|
|
|
// of the root layer.
|
|
|
|
AbsolutePositionInfo {
|
2014-07-19 00:27:23 +04:00
|
|
|
relative_containing_block_size: LogicalSize::zero(writing_mode),
|
2015-03-10 00:54:51 +03:00
|
|
|
relative_containing_block_mode: writing_mode,
|
2014-12-18 14:42:50 +03:00
|
|
|
stacking_relative_position_of_absolute_containing_block: Point2D::zero(),
|
2014-05-03 03:10:20 +04:00
|
|
|
layers_needed_for_positioned_flows: false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-08 00:44:45 +04:00
|
|
|
/// Data common to all flows.
|
2014-01-14 02:43:05 +04:00
|
|
|
pub struct BaseFlow {
|
2014-06-04 09:25:28 +04:00
|
|
|
/// NB: Must be the first element.
|
|
|
|
///
|
|
|
|
/// The necessity of this will disappear once we have dynamically-sized types.
|
2015-03-20 20:00:54 +03:00
|
|
|
strong_ref_count: AtomicUsize,
|
2015-03-16 22:16:03 +03:00
|
|
|
|
2015-03-20 20:00:54 +03:00
|
|
|
weak_ref_count: AtomicUsize,
|
2014-06-04 09:25:28 +04:00
|
|
|
|
2014-04-28 02:52:39 +04:00
|
|
|
pub restyle_damage: RestyleDamage,
|
2013-05-03 06:37:36 +04:00
|
|
|
|
2013-12-13 05:58:21 +04:00
|
|
|
/// The children of this flow.
|
2014-04-28 02:52:39 +04:00
|
|
|
pub children: FlowList,
|
2014-09-19 18:51:02 +04:00
|
|
|
|
2014-09-26 03:48:35 +04:00
|
|
|
/// Intrinsic inline sizes for this flow.
|
2014-07-19 00:27:23 +04:00
|
|
|
pub intrinsic_inline_sizes: IntrinsicISizes,
|
2013-10-31 23:10:32 +04:00
|
|
|
|
2014-04-04 05:01:48 +04:00
|
|
|
/// The upper left corner of the box representing this flow, relative to the box representing
|
|
|
|
/// its parent flow.
|
|
|
|
///
|
|
|
|
/// For absolute flows, this represents the position with respect to its *containing block*.
|
|
|
|
///
|
|
|
|
/// This does not include margins in the block flow direction, because those can collapse. So
|
|
|
|
/// for the block direction (usually vertical), this represents the *border box*. For the
|
|
|
|
/// inline direction (usually horizontal), this represents the *margin box*.
|
2014-07-19 00:27:23 +04:00
|
|
|
pub position: LogicalRect<Au>,
|
2013-10-31 23:10:32 +04:00
|
|
|
|
|
|
|
/// The amount of overflow of this flow, relative to the containing block. Must include all the
|
|
|
|
/// pixels of all the display list items for correct invalidation.
|
2015-01-05 04:51:48 +03:00
|
|
|
pub overflow: Rect<Au>,
|
2013-10-31 23:10:32 +04:00
|
|
|
|
2014-01-23 04:04:08 +04:00
|
|
|
/// Data used during parallel traversals.
|
|
|
|
///
|
|
|
|
/// TODO(pcwalton): Group with other transient data to save space.
|
2014-04-28 02:52:39 +04:00
|
|
|
pub parallel: FlowParallelInfo,
|
2014-01-23 04:04:08 +04:00
|
|
|
|
2014-02-28 00:01:49 +04:00
|
|
|
/// The floats next to this flow.
|
2014-04-28 02:52:39 +04:00
|
|
|
pub floats: Floats,
|
2014-02-28 00:01:49 +04:00
|
|
|
|
2014-04-04 05:01:48 +04:00
|
|
|
/// The collapsible margins for this flow, if any.
|
2014-04-28 02:52:39 +04:00
|
|
|
pub collapsible_margins: CollapsibleMargins,
|
2014-04-04 05:01:48 +04:00
|
|
|
|
2014-11-17 02:39:27 +03:00
|
|
|
/// The position of this flow relative to the start of the nearest ancestor stacking context.
|
|
|
|
/// This is computed during the top-down pass of display list construction.
|
|
|
|
pub stacking_relative_position: Point2D<Au>,
|
2013-12-13 05:58:21 +04:00
|
|
|
|
2014-04-04 05:01:48 +04:00
|
|
|
/// Details about descendants with position 'absolute' or 'fixed' for which we are the
|
|
|
|
/// containing block. This is in tree order. This includes any direct children.
|
2014-04-28 02:52:39 +04:00
|
|
|
pub abs_descendants: AbsDescendants,
|
2014-03-03 22:37:33 +04:00
|
|
|
|
2014-10-14 04:03:40 +04:00
|
|
|
/// The inline-size of the block container of this flow. Used for computing percentage and
|
|
|
|
/// automatic values for `width`.
|
|
|
|
pub block_container_inline_size: Au,
|
|
|
|
|
2015-03-10 00:54:51 +03:00
|
|
|
/// The writing mode of the block container of this flow.
|
|
|
|
///
|
|
|
|
/// FIXME (mbrubeck): Combine this and block_container_inline_size and maybe
|
|
|
|
/// block_container_explicit_block_size into a struct, to guarantee they are set at the same
|
|
|
|
/// time? Or just store a link to the containing block flow.
|
|
|
|
pub block_container_writing_mode: WritingMode,
|
|
|
|
|
2014-09-20 10:05:55 +04:00
|
|
|
/// The block-size of the block container of this flow, if it is an explicit size (does not
|
|
|
|
/// depend on content heights). Used for computing percentage values for `height`.
|
|
|
|
pub block_container_explicit_block_size: Option<Au>,
|
|
|
|
|
2014-03-03 22:37:33 +04:00
|
|
|
/// Reference to the Containing Block, if this flow is absolutely positioned.
|
2014-05-02 22:58:29 +04:00
|
|
|
pub absolute_cb: ContainingBlockLink,
|
2014-03-03 22:37:33 +04:00
|
|
|
|
2014-05-03 03:10:20 +04:00
|
|
|
/// Information needed to compute absolute (i.e. viewport-relative) flow positions (not to be
|
|
|
|
/// confused with absolutely-positioned flows).
|
|
|
|
pub absolute_position_info: AbsolutePositionInfo,
|
|
|
|
|
2014-12-23 01:51:48 +03:00
|
|
|
/// The clipping region for this flow and its descendants, in layer coordinates.
|
|
|
|
pub clip: ClippingRegion,
|
2014-10-14 10:42:35 +04:00
|
|
|
|
2015-05-20 03:40:36 +03:00
|
|
|
/// The stacking-relative position of the display port.
|
|
|
|
///
|
|
|
|
/// FIXME(pcwalton): This might be faster as an Arc, since this varies only
|
|
|
|
/// per-stacking-context.
|
|
|
|
pub stacking_relative_position_of_display_port: Rect<Au>,
|
|
|
|
|
2014-11-17 02:39:27 +03:00
|
|
|
/// The results of display list building for this flow.
|
|
|
|
pub display_list_building_result: DisplayListBuildingResult,
|
2014-05-03 03:10:20 +04:00
|
|
|
|
2014-10-29 02:21:48 +03:00
|
|
|
/// The writing mode for this flow.
|
|
|
|
pub writing_mode: WritingMode,
|
|
|
|
|
2015-02-21 09:06:48 +03:00
|
|
|
/// For debugging and profiling, the identifier of the thread that laid out this fragment.
|
|
|
|
pub thread_id: u8,
|
|
|
|
|
2014-05-02 22:58:29 +04:00
|
|
|
/// Various flags for flows, tightly packed to save space.
|
|
|
|
pub flags: FlowFlags,
|
2012-10-10 20:39:40 +04:00
|
|
|
}
|
|
|
|
|
2015-03-21 14:12:45 +03:00
|
|
|
#[allow(unsafe_code)]
|
2015-01-28 04:15:50 +03:00
|
|
|
unsafe impl Send for BaseFlow {}
|
2015-03-21 14:12:45 +03:00
|
|
|
#[allow(unsafe_code)]
|
2015-01-28 04:15:50 +03:00
|
|
|
unsafe impl Sync for BaseFlow {}
|
|
|
|
|
2015-02-12 03:24:45 +03:00
|
|
|
impl fmt::Debug for BaseFlow {
|
2014-10-02 05:36:25 +04:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
write!(f,
|
2015-01-28 04:15:50 +03:00
|
|
|
"@ {:?}, CC {}, ADC {}",
|
2014-10-14 04:03:40 +04:00
|
|
|
self.position,
|
2015-01-22 18:06:50 +03:00
|
|
|
self.parallel.children_count.load(Ordering::SeqCst),
|
2014-10-14 10:42:35 +04:00
|
|
|
self.abs_descendants.len())
|
2014-10-02 05:36:25 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-28 04:15:50 +03:00
|
|
|
impl Encodable for BaseFlow {
|
|
|
|
fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
|
2014-09-08 10:33:09 +04:00
|
|
|
e.emit_struct("base", 0, |e| {
|
2015-01-28 04:15:50 +03:00
|
|
|
try!(e.emit_struct_field("id", 0, |e| self.debug_id().encode(e)));
|
2014-11-17 02:39:27 +03:00
|
|
|
try!(e.emit_struct_field("stacking_relative_position",
|
|
|
|
1,
|
2015-01-28 04:15:50 +03:00
|
|
|
|e| self.stacking_relative_position.encode(e)));
|
2014-11-17 02:39:27 +03:00
|
|
|
try!(e.emit_struct_field("intrinsic_inline_sizes",
|
|
|
|
2,
|
2015-01-28 04:15:50 +03:00
|
|
|
|e| self.intrinsic_inline_sizes.encode(e)));
|
|
|
|
try!(e.emit_struct_field("position", 3, |e| self.position.encode(e)));
|
2014-09-08 10:33:09 +04:00
|
|
|
e.emit_struct_field("children", 4, |e| {
|
|
|
|
e.emit_seq(self.children.len(), |e| {
|
|
|
|
for (i, c) in self.children.iter().enumerate() {
|
2014-11-13 06:48:31 +03:00
|
|
|
try!(e.emit_seq_elt(i, |e| {
|
|
|
|
try!(e.emit_struct("flow", 0, |e| {
|
2015-01-28 04:15:50 +03:00
|
|
|
try!(e.emit_struct_field("class", 0, |e| c.class().encode(e)));
|
2014-11-13 06:48:31 +03:00
|
|
|
e.emit_struct_field("data", 1, |e| {
|
|
|
|
match c.class() {
|
2014-12-18 04:45:49 +03:00
|
|
|
FlowClass::Block => c.as_immutable_block().encode(e),
|
|
|
|
FlowClass::Inline => c.as_immutable_inline().encode(e),
|
|
|
|
FlowClass::Table => c.as_immutable_table().encode(e),
|
2015-05-20 03:40:36 +03:00
|
|
|
FlowClass::TableWrapper => {
|
|
|
|
c.as_immutable_table_wrapper().encode(e)
|
|
|
|
}
|
|
|
|
FlowClass::TableRowGroup => {
|
|
|
|
c.as_immutable_table_rowgroup().encode(e)
|
|
|
|
}
|
|
|
|
FlowClass::TableRow => {
|
|
|
|
c.as_immutable_table_row().encode(e)
|
|
|
|
}
|
|
|
|
FlowClass::TableCell => {
|
|
|
|
c.as_immutable_table_cell().encode(e)
|
|
|
|
}
|
2014-11-13 06:48:31 +03:00
|
|
|
_ => { Ok(()) } // TODO: Support captions
|
|
|
|
}
|
|
|
|
})
|
2015-01-28 04:15:50 +03:00
|
|
|
}));
|
2014-11-13 06:48:31 +03:00
|
|
|
Ok(())
|
2015-01-28 04:15:50 +03:00
|
|
|
}));
|
2014-09-08 10:33:09 +04:00
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
})
|
|
|
|
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-24 22:41:25 +04:00
|
|
|
impl Drop for BaseFlow {
|
|
|
|
fn drop(&mut self) {
|
2015-03-16 22:16:03 +03:00
|
|
|
if self.strong_ref_count.load(Ordering::SeqCst) != 0 &&
|
|
|
|
self.weak_ref_count.load(Ordering::SeqCst) != 0 {
|
2014-11-13 06:48:31 +03:00
|
|
|
panic!("Flow destroyed before its ref count hit zero—this is unsafe!")
|
2014-01-24 22:41:25 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-19 02:39:25 +03:00
|
|
|
/// Whether a base flow should be forced to be nonfloated. This can affect e.g. `TableFlow`, which
|
|
|
|
/// is never floated because the table wrapper flow is the floated one.
|
2015-01-28 04:15:50 +03:00
|
|
|
#[derive(Clone, PartialEq)]
|
2014-11-19 02:39:25 +03:00
|
|
|
pub enum ForceNonfloatedFlag {
|
|
|
|
/// The flow should be floated if the node has a `float` property.
|
|
|
|
FloatIfNecessary,
|
|
|
|
/// The flow should be forced to be nonfloated.
|
|
|
|
ForceNonfloated,
|
|
|
|
}
|
|
|
|
|
2014-01-14 02:43:05 +04:00
|
|
|
impl BaseFlow {
|
2013-11-18 23:54:00 +04:00
|
|
|
#[inline]
|
2015-08-07 07:11:04 +03:00
|
|
|
pub fn new(style: Option<&ComputedValues>,
|
2014-11-19 02:39:25 +03:00
|
|
|
writing_mode: WritingMode,
|
|
|
|
force_nonfloated: ForceNonfloatedFlag)
|
|
|
|
-> BaseFlow {
|
2014-11-18 21:42:32 +03:00
|
|
|
let mut flags = FlowFlags::empty();
|
2015-08-07 07:11:04 +03:00
|
|
|
match style {
|
|
|
|
Some(style) => {
|
|
|
|
match style.get_box().position {
|
2015-04-15 02:14:11 +03:00
|
|
|
position::T::absolute | position::T::fixed => {
|
|
|
|
flags.insert(IS_ABSOLUTELY_POSITIONED);
|
|
|
|
|
2015-08-07 07:11:04 +03:00
|
|
|
let logical_position = style.logical_position();
|
2015-04-15 02:14:11 +03:00
|
|
|
if logical_position.inline_start == LengthOrPercentageOrAuto::Auto &&
|
|
|
|
logical_position.inline_end == LengthOrPercentageOrAuto::Auto {
|
|
|
|
flags.insert(INLINE_POSITION_IS_STATIC);
|
|
|
|
}
|
|
|
|
if logical_position.block_start == LengthOrPercentageOrAuto::Auto &&
|
|
|
|
logical_position.block_end == LengthOrPercentageOrAuto::Auto {
|
|
|
|
flags.insert(BLOCK_POSITION_IS_STATIC);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => flags.insert(BLOCK_POSITION_IS_STATIC | INLINE_POSITION_IS_STATIC),
|
2014-10-29 05:42:38 +03:00
|
|
|
}
|
2014-11-19 02:39:25 +03:00
|
|
|
|
2015-04-15 02:14:11 +03:00
|
|
|
if force_nonfloated == ForceNonfloatedFlag::FloatIfNecessary {
|
2015-08-07 07:11:04 +03:00
|
|
|
match style.get_box().float {
|
2015-04-15 02:14:11 +03:00
|
|
|
float::T::none => {}
|
|
|
|
float::T::left => flags.insert(FLOATS_LEFT),
|
|
|
|
float::T::right => flags.insert(FLOATS_RIGHT),
|
|
|
|
}
|
2014-10-29 05:42:38 +03:00
|
|
|
}
|
2014-11-19 02:39:25 +03:00
|
|
|
|
2015-08-07 07:11:04 +03:00
|
|
|
match style.get_box().clear {
|
2015-04-15 02:14:11 +03:00
|
|
|
clear::T::none => {}
|
|
|
|
clear::T::left => flags.insert(CLEARS_LEFT),
|
|
|
|
clear::T::right => flags.insert(CLEARS_RIGHT),
|
|
|
|
clear::T::both => {
|
|
|
|
flags.insert(CLEARS_LEFT);
|
|
|
|
flags.insert(CLEARS_RIGHT);
|
|
|
|
}
|
2014-10-29 05:42:38 +03:00
|
|
|
}
|
2015-03-10 08:24:47 +03:00
|
|
|
|
2015-08-07 07:11:04 +03:00
|
|
|
if !style.get_counters().counter_reset.0.is_empty() ||
|
|
|
|
!style.get_counters().counter_increment.0.is_empty() {
|
2015-04-15 02:14:11 +03:00
|
|
|
flags.insert(AFFECTS_COUNTERS)
|
|
|
|
}
|
2015-03-10 08:24:47 +03:00
|
|
|
}
|
2015-04-15 02:14:11 +03:00
|
|
|
None => flags.insert(BLOCK_POSITION_IS_STATIC | INLINE_POSITION_IS_STATIC),
|
2014-10-29 05:42:38 +03:00
|
|
|
}
|
|
|
|
|
2014-10-31 23:39:34 +03:00
|
|
|
// New flows start out as fully damaged.
|
2015-03-10 08:24:47 +03:00
|
|
|
let mut damage = incremental::rebuild_and_reflow();
|
2014-11-13 06:48:31 +03:00
|
|
|
damage.remove(RECONSTRUCT_FLOW);
|
2014-10-31 23:39:34 +03:00
|
|
|
|
2014-01-14 02:43:05 +04:00
|
|
|
BaseFlow {
|
2015-03-20 20:00:54 +03:00
|
|
|
strong_ref_count: AtomicUsize::new(1),
|
|
|
|
weak_ref_count: AtomicUsize::new(1),
|
2014-10-31 23:39:34 +03:00
|
|
|
restyle_damage: damage,
|
2014-02-06 07:19:43 +04:00
|
|
|
children: FlowList::new(),
|
2014-07-19 00:27:23 +04:00
|
|
|
intrinsic_inline_sizes: IntrinsicISizes::new(),
|
|
|
|
position: LogicalRect::zero(writing_mode),
|
2015-01-05 04:51:48 +03:00
|
|
|
overflow: ZERO_RECT,
|
2014-01-23 04:04:08 +04:00
|
|
|
parallel: FlowParallelInfo::new(),
|
2014-07-19 00:27:23 +04:00
|
|
|
floats: Floats::new(writing_mode),
|
2014-04-04 05:01:48 +04:00
|
|
|
collapsible_margins: CollapsibleMargins::new(),
|
2014-12-18 14:42:50 +03:00
|
|
|
stacking_relative_position: Point2D::zero(),
|
2014-03-03 22:37:33 +04:00
|
|
|
abs_descendants: Descendants::new(),
|
2014-10-14 04:03:40 +04:00
|
|
|
block_container_inline_size: Au(0),
|
2015-03-10 00:54:51 +03:00
|
|
|
block_container_writing_mode: writing_mode,
|
2014-09-20 10:05:55 +04:00
|
|
|
block_container_explicit_block_size: None,
|
2014-05-02 22:58:29 +04:00
|
|
|
absolute_cb: ContainingBlockLink::new(),
|
2014-12-18 04:45:49 +03:00
|
|
|
display_list_building_result: DisplayListBuildingResult::None,
|
2014-07-19 00:27:23 +04:00
|
|
|
absolute_position_info: AbsolutePositionInfo::new(writing_mode),
|
2014-12-23 01:51:48 +03:00
|
|
|
clip: ClippingRegion::max(),
|
2015-05-20 03:40:36 +03:00
|
|
|
stacking_relative_position_of_display_port: Rect::zero(),
|
2014-10-29 05:42:38 +03:00
|
|
|
flags: flags,
|
2014-07-19 00:27:23 +04:00
|
|
|
writing_mode: writing_mode,
|
2015-02-21 09:06:48 +03:00
|
|
|
thread_id: 0,
|
2013-05-03 06:37:36 +04:00
|
|
|
}
|
2012-10-10 20:39:40 +04:00
|
|
|
}
|
2013-08-20 23:03:52 +04:00
|
|
|
|
2014-02-06 07:19:43 +04:00
|
|
|
pub fn child_iter<'a>(&'a mut self) -> MutFlowListIterator<'a> {
|
2014-09-21 02:35:08 +04:00
|
|
|
self.children.iter_mut()
|
2013-08-20 23:03:52 +04:00
|
|
|
}
|
2014-06-04 09:25:28 +04:00
|
|
|
|
2015-03-21 14:12:45 +03:00
|
|
|
#[allow(unsafe_code)]
|
2015-03-20 20:00:54 +03:00
|
|
|
pub unsafe fn strong_ref_count<'a>(&'a self) -> &'a AtomicUsize {
|
2015-03-16 22:16:03 +03:00
|
|
|
&self.strong_ref_count
|
|
|
|
}
|
|
|
|
|
2015-03-21 14:12:45 +03:00
|
|
|
#[allow(unsafe_code)]
|
2015-03-20 20:00:54 +03:00
|
|
|
pub unsafe fn weak_ref_count<'a>(&'a self) -> &'a AtomicUsize {
|
2015-03-16 22:16:03 +03:00
|
|
|
&self.weak_ref_count
|
2014-06-04 09:25:28 +04:00
|
|
|
}
|
2014-09-08 10:33:09 +04:00
|
|
|
|
2015-03-29 12:49:01 +03:00
|
|
|
pub fn debug_id(&self) -> usize {
|
2014-10-17 22:15:23 +04:00
|
|
|
let p = self as *const _;
|
2015-03-29 12:49:01 +03:00
|
|
|
p as usize
|
2014-09-08 10:33:09 +04:00
|
|
|
}
|
2014-10-22 20:54:35 +04:00
|
|
|
|
2014-11-17 02:39:27 +03:00
|
|
|
/// Ensures that all display list items generated by this flow are within the flow's overflow
|
|
|
|
/// rect. This should only be used for debugging.
|
2014-10-22 20:54:35 +04:00
|
|
|
pub fn validate_display_list_geometry(&self) {
|
2015-01-05 04:51:48 +03:00
|
|
|
// FIXME(pcwalton, #2795): Get the real container size.
|
|
|
|
let container_size = Size2D::zero();
|
|
|
|
let position_with_overflow = self.position
|
|
|
|
.to_physical(self.writing_mode, container_size)
|
|
|
|
.union(&self.overflow);
|
2015-06-13 22:52:07 +03:00
|
|
|
let bounds = Rect::new(self.stacking_relative_position, position_with_overflow.size);
|
2014-10-22 20:54:35 +04:00
|
|
|
|
2014-11-17 02:39:27 +03:00
|
|
|
let all_items = match self.display_list_building_result {
|
2014-12-18 04:45:49 +03:00
|
|
|
DisplayListBuildingResult::None => Vec::new(),
|
|
|
|
DisplayListBuildingResult::StackingContext(ref stacking_context) => {
|
2014-11-17 02:39:27 +03:00
|
|
|
stacking_context.display_list.all_display_items()
|
|
|
|
}
|
2014-12-18 04:45:49 +03:00
|
|
|
DisplayListBuildingResult::Normal(ref display_list) => display_list.all_display_items(),
|
2014-11-17 02:39:27 +03:00
|
|
|
};
|
|
|
|
|
2015-08-15 12:03:21 +03:00
|
|
|
for item in &all_items {
|
2014-12-23 01:51:48 +03:00
|
|
|
let paint_bounds = item.base().clip.clone().intersect_rect(&item.base().bounds);
|
|
|
|
if !paint_bounds.might_be_nonempty() {
|
2014-10-22 20:54:35 +04:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2014-12-23 01:51:48 +03:00
|
|
|
if bounds.union(&paint_bounds.bounding_rect()) != bounds {
|
2015-01-28 04:15:50 +03:00
|
|
|
error!("DisplayList item {:?} outside of Flow overflow ({:?})", item, paint_bounds);
|
2014-10-22 20:54:35 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-10-10 20:39:40 +04:00
|
|
|
}
|
|
|
|
|
2015-01-08 18:00:57 +03:00
|
|
|
impl<'a> ImmutableFlowUtils for &'a (Flow + 'a) {
|
2015-03-10 08:24:47 +03:00
|
|
|
/// Returns true if this flow is a block flow or subclass thereof.
|
2013-10-29 00:31:44 +04:00
|
|
|
fn is_block_like(self) -> bool {
|
|
|
|
match self.class() {
|
2015-03-10 08:24:47 +03:00
|
|
|
FlowClass::Block | FlowClass::ListItem | FlowClass::Table | FlowClass::TableRowGroup |
|
|
|
|
FlowClass::TableRow | FlowClass::TableCaption | FlowClass::TableCell |
|
|
|
|
FlowClass::TableWrapper => true,
|
servo: Merge #1973 - Support fixed-layout table and a part of anonymous table object (from june0cho:table_rebase); r=larsbergstrom,metajack
This is a rebase of #1548 on recent master.
There have been many changes since #1548 is first uploaded, so I'm creating new PR.
This PR includes:
- construction of table-* flows (table-wrapper, table-caption, table, table-rowgroup, table-row, table-cell)
- fixed-layout table calculation
- a part of anonymous table object implementation
[CSS 2.1, 17.2.1](http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes) (Step 1-1, 1-2, Step 2)
Source-Repo: https://github.com/servo/servo
Source-Revision: fd5e5cd18b41f0ce2b33fb97fb4e3d75ddbbbceb
2014-03-25 21:40:47 +04:00
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns true if this flow is a proper table child.
|
|
|
|
/// 'Proper table child' is defined as table-row flow, table-rowgroup flow,
|
|
|
|
/// table-column-group flow, or table-caption flow.
|
|
|
|
fn is_proper_table_child(self) -> bool {
|
|
|
|
match self.class() {
|
2014-12-18 04:45:49 +03:00
|
|
|
FlowClass::TableRow | FlowClass::TableRowGroup |
|
|
|
|
FlowClass::TableColGroup | FlowClass::TableCaption => true,
|
servo: Merge #1973 - Support fixed-layout table and a part of anonymous table object (from june0cho:table_rebase); r=larsbergstrom,metajack
This is a rebase of #1548 on recent master.
There have been many changes since #1548 is first uploaded, so I'm creating new PR.
This PR includes:
- construction of table-* flows (table-wrapper, table-caption, table, table-rowgroup, table-row, table-cell)
- fixed-layout table calculation
- a part of anonymous table object implementation
[CSS 2.1, 17.2.1](http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes) (Step 1-1, 1-2, Step 2)
Source-Repo: https://github.com/servo/servo
Source-Revision: fd5e5cd18b41f0ce2b33fb97fb4e3d75ddbbbceb
2014-03-25 21:40:47 +04:00
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns true if this flow is a table row flow.
|
|
|
|
fn is_table_row(self) -> bool {
|
|
|
|
match self.class() {
|
2014-12-18 04:45:49 +03:00
|
|
|
FlowClass::TableRow => true,
|
servo: Merge #1973 - Support fixed-layout table and a part of anonymous table object (from june0cho:table_rebase); r=larsbergstrom,metajack
This is a rebase of #1548 on recent master.
There have been many changes since #1548 is first uploaded, so I'm creating new PR.
This PR includes:
- construction of table-* flows (table-wrapper, table-caption, table, table-rowgroup, table-row, table-cell)
- fixed-layout table calculation
- a part of anonymous table object implementation
[CSS 2.1, 17.2.1](http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes) (Step 1-1, 1-2, Step 2)
Source-Repo: https://github.com/servo/servo
Source-Revision: fd5e5cd18b41f0ce2b33fb97fb4e3d75ddbbbceb
2014-03-25 21:40:47 +04:00
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns true if this flow is a table cell flow.
|
|
|
|
fn is_table_cell(self) -> bool {
|
|
|
|
match self.class() {
|
2014-12-18 04:45:49 +03:00
|
|
|
FlowClass::TableCell => true,
|
servo: Merge #1973 - Support fixed-layout table and a part of anonymous table object (from june0cho:table_rebase); r=larsbergstrom,metajack
This is a rebase of #1548 on recent master.
There have been many changes since #1548 is first uploaded, so I'm creating new PR.
This PR includes:
- construction of table-* flows (table-wrapper, table-caption, table, table-rowgroup, table-row, table-cell)
- fixed-layout table calculation
- a part of anonymous table object implementation
[CSS 2.1, 17.2.1](http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes) (Step 1-1, 1-2, Step 2)
Source-Repo: https://github.com/servo/servo
Source-Revision: fd5e5cd18b41f0ce2b33fb97fb4e3d75ddbbbceb
2014-03-25 21:40:47 +04:00
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns true if this flow is a table colgroup flow.
|
|
|
|
fn is_table_colgroup(self) -> bool {
|
|
|
|
match self.class() {
|
2014-12-18 04:45:49 +03:00
|
|
|
FlowClass::TableColGroup => true,
|
servo: Merge #1973 - Support fixed-layout table and a part of anonymous table object (from june0cho:table_rebase); r=larsbergstrom,metajack
This is a rebase of #1548 on recent master.
There have been many changes since #1548 is first uploaded, so I'm creating new PR.
This PR includes:
- construction of table-* flows (table-wrapper, table-caption, table, table-rowgroup, table-row, table-cell)
- fixed-layout table calculation
- a part of anonymous table object implementation
[CSS 2.1, 17.2.1](http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes) (Step 1-1, 1-2, Step 2)
Source-Repo: https://github.com/servo/servo
Source-Revision: fd5e5cd18b41f0ce2b33fb97fb4e3d75ddbbbceb
2014-03-25 21:40:47 +04:00
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns true if this flow is a table flow.
|
|
|
|
fn is_table(self) -> bool {
|
|
|
|
match self.class() {
|
2014-12-18 04:45:49 +03:00
|
|
|
FlowClass::Table => true,
|
servo: Merge #1973 - Support fixed-layout table and a part of anonymous table object (from june0cho:table_rebase); r=larsbergstrom,metajack
This is a rebase of #1548 on recent master.
There have been many changes since #1548 is first uploaded, so I'm creating new PR.
This PR includes:
- construction of table-* flows (table-wrapper, table-caption, table, table-rowgroup, table-row, table-cell)
- fixed-layout table calculation
- a part of anonymous table object implementation
[CSS 2.1, 17.2.1](http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes) (Step 1-1, 1-2, Step 2)
Source-Repo: https://github.com/servo/servo
Source-Revision: fd5e5cd18b41f0ce2b33fb97fb4e3d75ddbbbceb
2014-03-25 21:40:47 +04:00
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns true if this flow is a table caption flow.
|
|
|
|
fn is_table_caption(self) -> bool {
|
|
|
|
match self.class() {
|
2014-12-18 04:45:49 +03:00
|
|
|
FlowClass::TableCaption => true,
|
servo: Merge #1973 - Support fixed-layout table and a part of anonymous table object (from june0cho:table_rebase); r=larsbergstrom,metajack
This is a rebase of #1548 on recent master.
There have been many changes since #1548 is first uploaded, so I'm creating new PR.
This PR includes:
- construction of table-* flows (table-wrapper, table-caption, table, table-rowgroup, table-row, table-cell)
- fixed-layout table calculation
- a part of anonymous table object implementation
[CSS 2.1, 17.2.1](http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes) (Step 1-1, 1-2, Step 2)
Source-Repo: https://github.com/servo/servo
Source-Revision: fd5e5cd18b41f0ce2b33fb97fb4e3d75ddbbbceb
2014-03-25 21:40:47 +04:00
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns true if this flow is a table rowgroup flow.
|
|
|
|
fn is_table_rowgroup(self) -> bool {
|
|
|
|
match self.class() {
|
2014-12-18 04:45:49 +03:00
|
|
|
FlowClass::TableRowGroup => true,
|
servo: Merge #1973 - Support fixed-layout table and a part of anonymous table object (from june0cho:table_rebase); r=larsbergstrom,metajack
This is a rebase of #1548 on recent master.
There have been many changes since #1548 is first uploaded, so I'm creating new PR.
This PR includes:
- construction of table-* flows (table-wrapper, table-caption, table, table-rowgroup, table-row, table-cell)
- fixed-layout table calculation
- a part of anonymous table object implementation
[CSS 2.1, 17.2.1](http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes) (Step 1-1, 1-2, Step 2)
Source-Repo: https://github.com/servo/servo
Source-Revision: fd5e5cd18b41f0ce2b33fb97fb4e3d75ddbbbceb
2014-03-25 21:40:47 +04:00
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns true if this flow is one of table-related flows.
|
|
|
|
fn is_table_kind(self) -> bool {
|
|
|
|
match self.class() {
|
2014-12-18 04:45:49 +03:00
|
|
|
FlowClass::TableWrapper | FlowClass::Table |
|
|
|
|
FlowClass::TableColGroup | FlowClass::TableRowGroup |
|
|
|
|
FlowClass::TableRow | FlowClass::TableCaption | FlowClass::TableCell => true,
|
servo: Merge #1973 - Support fixed-layout table and a part of anonymous table object (from june0cho:table_rebase); r=larsbergstrom,metajack
This is a rebase of #1548 on recent master.
There have been many changes since #1548 is first uploaded, so I'm creating new PR.
This PR includes:
- construction of table-* flows (table-wrapper, table-caption, table, table-rowgroup, table-row, table-cell)
- fixed-layout table calculation
- a part of anonymous table object implementation
[CSS 2.1, 17.2.1](http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes) (Step 1-1, 1-2, Step 2)
Source-Repo: https://github.com/servo/servo
Source-Revision: fd5e5cd18b41f0ce2b33fb97fb4e3d75ddbbbceb
2014-03-25 21:40:47 +04:00
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns true if anonymous flow is needed between this flow and child flow.
|
|
|
|
/// Spec: http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes
|
|
|
|
fn need_anonymous_flow(self, child: &Flow) -> bool {
|
|
|
|
match self.class() {
|
2014-12-18 04:45:49 +03:00
|
|
|
FlowClass::Table => !child.is_proper_table_child(),
|
|
|
|
FlowClass::TableRowGroup => !child.is_table_row(),
|
|
|
|
FlowClass::TableRow => !child.is_table_cell(),
|
servo: Merge #1973 - Support fixed-layout table and a part of anonymous table object (from june0cho:table_rebase); r=larsbergstrom,metajack
This is a rebase of #1548 on recent master.
There have been many changes since #1548 is first uploaded, so I'm creating new PR.
This PR includes:
- construction of table-* flows (table-wrapper, table-caption, table, table-rowgroup, table-row, table-cell)
- fixed-layout table calculation
- a part of anonymous table object implementation
[CSS 2.1, 17.2.1](http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes) (Step 1-1, 1-2, Step 2)
Source-Repo: https://github.com/servo/servo
Source-Revision: fd5e5cd18b41f0ce2b33fb97fb4e3d75ddbbbceb
2014-03-25 21:40:47 +04:00
|
|
|
_ => false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Generates missing child flow of this flow.
|
2015-08-07 07:11:04 +03:00
|
|
|
///
|
|
|
|
/// FIXME(pcwalton): This duplicates some logic in
|
|
|
|
/// `generate_anonymous_table_flows_if_necessary()`. We should remove this function eventually,
|
|
|
|
/// as it's harder to understand.
|
2014-06-04 09:25:28 +04:00
|
|
|
fn generate_missing_child_flow(self, node: &ThreadSafeLayoutNode) -> FlowRef {
|
2015-08-07 07:11:04 +03:00
|
|
|
let mut style = node.style().clone();
|
2014-06-04 09:25:28 +04:00
|
|
|
let flow = match self.class() {
|
2014-12-18 04:45:49 +03:00
|
|
|
FlowClass::Table | FlowClass::TableRowGroup => {
|
2015-08-07 07:11:04 +03:00
|
|
|
properties::modify_style_for_anonymous_table_object(
|
|
|
|
&mut style,
|
|
|
|
display::T::table_row);
|
|
|
|
let fragment = Fragment::from_opaque_node_and_style(
|
|
|
|
node.opaque(),
|
|
|
|
PseudoElementType::Normal,
|
|
|
|
style,
|
|
|
|
node.restyle_damage(),
|
|
|
|
SpecificFragmentInfo::TableRow);
|
|
|
|
box TableRowFlow::from_fragment(fragment) as Box<Flow>
|
servo: Merge #1973 - Support fixed-layout table and a part of anonymous table object (from june0cho:table_rebase); r=larsbergstrom,metajack
This is a rebase of #1548 on recent master.
There have been many changes since #1548 is first uploaded, so I'm creating new PR.
This PR includes:
- construction of table-* flows (table-wrapper, table-caption, table, table-rowgroup, table-row, table-cell)
- fixed-layout table calculation
- a part of anonymous table object implementation
[CSS 2.1, 17.2.1](http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes) (Step 1-1, 1-2, Step 2)
Source-Repo: https://github.com/servo/servo
Source-Revision: fd5e5cd18b41f0ce2b33fb97fb4e3d75ddbbbceb
2014-03-25 21:40:47 +04:00
|
|
|
},
|
2014-12-18 04:45:49 +03:00
|
|
|
FlowClass::TableRow => {
|
2015-08-07 07:11:04 +03:00
|
|
|
properties::modify_style_for_anonymous_table_object(
|
|
|
|
&mut style,
|
|
|
|
display::T::table_cell);
|
|
|
|
let fragment = Fragment::from_opaque_node_and_style(
|
|
|
|
node.opaque(),
|
|
|
|
PseudoElementType::Normal,
|
|
|
|
style,
|
|
|
|
node.restyle_damage(),
|
|
|
|
SpecificFragmentInfo::TableCell);
|
2015-01-08 18:00:57 +03:00
|
|
|
let hide = node.style().get_inheritedtable().empty_cells == empty_cells::T::hide;
|
2014-12-18 08:33:51 +03:00
|
|
|
box TableCellFlow::from_node_fragment_and_visibility_flag(node, fragment, !hide) as
|
|
|
|
Box<Flow>
|
servo: Merge #1973 - Support fixed-layout table and a part of anonymous table object (from june0cho:table_rebase); r=larsbergstrom,metajack
This is a rebase of #1548 on recent master.
There have been many changes since #1548 is first uploaded, so I'm creating new PR.
This PR includes:
- construction of table-* flows (table-wrapper, table-caption, table, table-rowgroup, table-row, table-cell)
- fixed-layout table calculation
- a part of anonymous table object implementation
[CSS 2.1, 17.2.1](http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes) (Step 1-1, 1-2, Step 2)
Source-Repo: https://github.com/servo/servo
Source-Revision: fd5e5cd18b41f0ce2b33fb97fb4e3d75ddbbbceb
2014-03-25 21:40:47 +04:00
|
|
|
},
|
|
|
|
_ => {
|
2014-11-13 06:48:31 +03:00
|
|
|
panic!("no need to generate a missing child")
|
servo: Merge #1973 - Support fixed-layout table and a part of anonymous table object (from june0cho:table_rebase); r=larsbergstrom,metajack
This is a rebase of #1548 on recent master.
There have been many changes since #1548 is first uploaded, so I'm creating new PR.
This PR includes:
- construction of table-* flows (table-wrapper, table-caption, table, table-rowgroup, table-row, table-cell)
- fixed-layout table calculation
- a part of anonymous table object implementation
[CSS 2.1, 17.2.1](http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes) (Step 1-1, 1-2, Step 2)
Source-Repo: https://github.com/servo/servo
Source-Revision: fd5e5cd18b41f0ce2b33fb97fb4e3d75ddbbbceb
2014-03-25 21:40:47 +04:00
|
|
|
}
|
2014-06-04 09:25:28 +04:00
|
|
|
};
|
|
|
|
FlowRef::new(flow)
|
2013-08-09 20:42:36 +04:00
|
|
|
}
|
|
|
|
|
2015-05-13 22:27:21 +03:00
|
|
|
/// Returns true if this flow contains fragments that are roots of an absolute flow tree.
|
|
|
|
fn contains_roots_of_absolute_flow_tree(&self) -> bool {
|
|
|
|
self.contains_relatively_positioned_fragments() || self.is_root()
|
|
|
|
}
|
|
|
|
|
2013-10-29 00:31:44 +04:00
|
|
|
/// Returns true if this flow has no children.
|
|
|
|
fn is_leaf(self) -> bool {
|
2015-08-14 09:51:59 +03:00
|
|
|
base(self).children.is_empty()
|
2012-09-27 05:17:44 +04:00
|
|
|
}
|
|
|
|
|
2014-01-23 04:04:08 +04:00
|
|
|
/// Returns the number of children that this flow possesses.
|
2015-04-02 17:06:41 +03:00
|
|
|
fn child_count(self) -> usize {
|
2014-01-23 04:04:08 +04:00
|
|
|
base(self).children.len()
|
|
|
|
}
|
|
|
|
|
2014-02-05 02:52:39 +04:00
|
|
|
/// Return true if this flow is a Block Container.
|
|
|
|
///
|
2014-05-29 04:34:06 +04:00
|
|
|
/// Except for table fragments and replaced elements, block-level fragments (`BlockFlow`) are
|
|
|
|
/// also block container fragments.
|
2014-02-05 02:52:39 +04:00
|
|
|
/// Non-replaced inline blocks and non-replaced table cells are also block
|
|
|
|
/// containers.
|
|
|
|
fn is_block_container(self) -> bool {
|
|
|
|
match self.class() {
|
|
|
|
// TODO: Change this when inline-blocks are supported.
|
2014-12-18 04:45:49 +03:00
|
|
|
FlowClass::Block | FlowClass::TableCaption | FlowClass::TableCell => {
|
2014-02-05 02:52:39 +04:00
|
|
|
// FIXME: Actually check the type of the node
|
|
|
|
self.child_count() != 0
|
|
|
|
}
|
servo: Merge #1973 - Support fixed-layout table and a part of anonymous table object (from june0cho:table_rebase); r=larsbergstrom,metajack
This is a rebase of #1548 on recent master.
There have been many changes since #1548 is first uploaded, so I'm creating new PR.
This PR includes:
- construction of table-* flows (table-wrapper, table-caption, table, table-rowgroup, table-row, table-cell)
- fixed-layout table calculation
- a part of anonymous table object implementation
[CSS 2.1, 17.2.1](http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes) (Step 1-1, 1-2, Step 2)
Source-Repo: https://github.com/servo/servo
Source-Revision: fd5e5cd18b41f0ce2b33fb97fb4e3d75ddbbbceb
2014-03-25 21:40:47 +04:00
|
|
|
_ => false,
|
2014-02-05 02:52:39 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-19 01:17:07 +04:00
|
|
|
/// Returns true if this flow is a block flow.
|
|
|
|
fn is_block_flow(self) -> bool {
|
2013-10-29 00:31:44 +04:00
|
|
|
match self.class() {
|
2014-12-18 04:45:49 +03:00
|
|
|
FlowClass::Block => true,
|
servo: Merge #1973 - Support fixed-layout table and a part of anonymous table object (from june0cho:table_rebase); r=larsbergstrom,metajack
This is a rebase of #1548 on recent master.
There have been many changes since #1548 is first uploaded, so I'm creating new PR.
This PR includes:
- construction of table-* flows (table-wrapper, table-caption, table, table-rowgroup, table-row, table-cell)
- fixed-layout table calculation
- a part of anonymous table object implementation
[CSS 2.1, 17.2.1](http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes) (Step 1-1, 1-2, Step 2)
Source-Repo: https://github.com/servo/servo
Source-Revision: fd5e5cd18b41f0ce2b33fb97fb4e3d75ddbbbceb
2014-03-25 21:40:47 +04:00
|
|
|
_ => false,
|
2013-08-20 23:03:52 +04:00
|
|
|
}
|
|
|
|
}
|
2013-08-02 02:42:26 +04:00
|
|
|
|
2014-02-19 01:17:07 +04:00
|
|
|
/// Returns true if this flow is an inline flow.
|
|
|
|
fn is_inline_flow(self) -> bool {
|
2013-10-29 00:31:44 +04:00
|
|
|
match self.class() {
|
2014-12-18 04:45:49 +03:00
|
|
|
FlowClass::Inline => true,
|
servo: Merge #1973 - Support fixed-layout table and a part of anonymous table object (from june0cho:table_rebase); r=larsbergstrom,metajack
This is a rebase of #1548 on recent master.
There have been many changes since #1548 is first uploaded, so I'm creating new PR.
This PR includes:
- construction of table-* flows (table-wrapper, table-caption, table, table-rowgroup, table-row, table-cell)
- fixed-layout table calculation
- a part of anonymous table object implementation
[CSS 2.1, 17.2.1](http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes) (Step 1-1, 1-2, Step 2)
Source-Repo: https://github.com/servo/servo
Source-Revision: fd5e5cd18b41f0ce2b33fb97fb4e3d75ddbbbceb
2014-03-25 21:40:47 +04:00
|
|
|
_ => false,
|
2013-05-03 06:37:36 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-29 00:31:44 +04:00
|
|
|
/// Dumps the flow tree for debugging.
|
|
|
|
fn dump(self) {
|
2013-11-11 11:07:23 +04:00
|
|
|
self.dump_with_level(0)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Dumps the flow tree for debugging, with a prefix to indicate that we're at the given level.
|
2015-04-02 17:06:41 +03:00
|
|
|
fn dump_with_level(self, level: u32) {
|
2014-06-05 21:58:44 +04:00
|
|
|
let mut indent = String::new();
|
2015-04-23 02:24:21 +03:00
|
|
|
for _ in 0..level {
|
2013-11-11 11:07:23 +04:00
|
|
|
indent.push_str("| ")
|
|
|
|
}
|
2014-10-17 22:15:23 +04:00
|
|
|
|
2015-02-21 06:12:55 +03:00
|
|
|
println!("{}+ {:?}", indent, self);
|
2014-10-17 22:15:23 +04:00
|
|
|
|
2013-11-11 11:07:23 +04:00
|
|
|
for kid in imm_child_iter(self) {
|
|
|
|
kid.dump_with_level(level + 1)
|
|
|
|
}
|
2012-09-27 05:17:44 +04:00
|
|
|
}
|
2013-10-29 00:31:44 +04:00
|
|
|
}
|
2012-09-27 05:17:44 +04:00
|
|
|
|
2015-01-08 18:00:57 +03:00
|
|
|
impl<'a> MutableFlowUtils for &'a mut (Flow + 'a) {
|
2013-10-29 00:31:44 +04:00
|
|
|
/// Traverses the tree in preorder.
|
2015-08-16 17:37:40 +03:00
|
|
|
fn traverse_preorder<T: PreorderFlowTraversal>(self, traversal: &T) {
|
2014-10-15 05:33:28 +04:00
|
|
|
if traversal.should_process(self) {
|
|
|
|
traversal.process(self);
|
2012-09-27 05:17:44 +04:00
|
|
|
}
|
2012-09-22 03:23:30 +04:00
|
|
|
|
2013-10-29 00:31:44 +04:00
|
|
|
for kid in child_iter(self) {
|
2014-10-15 05:33:28 +04:00
|
|
|
kid.traverse_preorder(traversal);
|
2012-09-22 03:23:30 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-29 00:31:44 +04:00
|
|
|
/// Traverses the tree in postorder.
|
2015-08-16 17:37:40 +03:00
|
|
|
fn traverse_postorder<T: PostorderFlowTraversal>(self, traversal: &T) {
|
2013-10-29 00:31:44 +04:00
|
|
|
for kid in child_iter(self) {
|
2014-10-15 05:33:28 +04:00
|
|
|
kid.traverse_postorder(traversal);
|
2012-09-22 03:23:30 +04:00
|
|
|
}
|
2013-07-16 05:03:27 +04:00
|
|
|
|
2014-10-15 05:33:28 +04:00
|
|
|
if traversal.should_process(self) {
|
|
|
|
traversal.process(self)
|
2013-08-09 20:42:36 +04:00
|
|
|
}
|
2012-09-26 03:07:38 +04:00
|
|
|
}
|
|
|
|
|
2013-10-31 23:10:32 +04:00
|
|
|
|
2015-04-01 21:03:45 +03:00
|
|
|
/// Calls `repair_style` and `bubble_inline_sizes`. You should use this method instead of
|
|
|
|
/// calling them individually, since there is no reason not to perform both operations.
|
|
|
|
fn repair_style_and_bubble_inline_sizes(self, style: &Arc<ComputedValues>) {
|
|
|
|
self.repair_style(style);
|
|
|
|
self.bubble_inline_sizes();
|
|
|
|
}
|
2015-05-13 22:27:21 +03:00
|
|
|
|
|
|
|
/// Traverse the Absolute flow tree in preorder.
|
|
|
|
///
|
|
|
|
/// Traverse all your direct absolute descendants, who will then traverse
|
|
|
|
/// their direct absolute descendants.
|
|
|
|
///
|
|
|
|
/// Return true if the traversal is to continue or false to stop.
|
|
|
|
fn traverse_preorder_absolute_flows<T>(&mut self, traversal: &mut T)
|
|
|
|
where T: PreorderFlowTraversal {
|
|
|
|
traversal.process(*self);
|
|
|
|
|
|
|
|
let descendant_offset_iter = mut_base(*self).abs_descendants.iter();
|
|
|
|
for ref mut descendant_link in descendant_offset_iter {
|
|
|
|
descendant_link.traverse_preorder_absolute_flows(traversal)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Traverse the Absolute flow tree in postorder.
|
|
|
|
///
|
|
|
|
/// Return true if the traversal is to continue or false to stop.
|
|
|
|
fn traverse_postorder_absolute_flows<T>(&mut self, traversal: &mut T)
|
|
|
|
where T: PostorderFlowTraversal {
|
|
|
|
for mut descendant_link in mut_base(*self).abs_descendants.iter() {
|
|
|
|
descendant_link.traverse_postorder_absolute_flows(traversal);
|
|
|
|
}
|
|
|
|
|
|
|
|
traversal.process(*self)
|
|
|
|
}
|
2012-09-22 03:23:30 +04:00
|
|
|
}
|
2013-05-03 06:37:36 +04:00
|
|
|
|
2014-06-04 09:25:28 +04:00
|
|
|
impl MutableOwnedFlowUtils for FlowRef {
|
2014-03-03 22:37:33 +04:00
|
|
|
/// Set absolute descendants for this flow.
|
|
|
|
///
|
|
|
|
/// Set yourself as the Containing Block for all the absolute descendants.
|
|
|
|
///
|
2014-06-04 09:25:28 +04:00
|
|
|
/// This is called during flow construction, so nothing else can be accessing the descendant
|
|
|
|
/// flows. This is enforced by the fact that we have a mutable `FlowRef`, which only flow
|
|
|
|
/// construction is allowed to possess.
|
2014-09-19 18:51:02 +04:00
|
|
|
fn set_absolute_descendants(&mut self, abs_descendants: AbsDescendants) {
|
2014-06-04 09:25:28 +04:00
|
|
|
let this = self.clone();
|
2015-05-13 22:27:21 +03:00
|
|
|
let base = mut_base(&mut **self);
|
|
|
|
base.abs_descendants = abs_descendants;
|
|
|
|
for descendant_link in base.abs_descendants.iter() {
|
|
|
|
let descendant_base = mut_base(descendant_link);
|
|
|
|
descendant_base.absolute_cb.set(this.clone());
|
2014-03-03 22:37:33 +04:00
|
|
|
}
|
|
|
|
}
|
2014-01-23 04:04:08 +04:00
|
|
|
}
|
2014-05-02 22:58:29 +04:00
|
|
|
|
|
|
|
/// A link to a flow's containing block.
|
|
|
|
///
|
|
|
|
/// This cannot safely be a `Flow` pointer because this is a pointer *up* the tree, not *down* the
|
|
|
|
/// tree. A pointer up the tree is unsafe during layout because it can be used to access a node
|
|
|
|
/// with an immutable reference while that same node is being laid out, causing possible iterator
|
|
|
|
/// invalidation and use-after-free.
|
2014-06-04 09:25:28 +04:00
|
|
|
///
|
|
|
|
/// FIXME(pcwalton): I think this would be better with a borrow flag instead of `unsafe`.
|
2014-05-02 22:58:29 +04:00
|
|
|
pub struct ContainingBlockLink {
|
2014-06-04 09:25:28 +04:00
|
|
|
/// The pointer up to the containing block.
|
2015-03-16 22:16:03 +03:00
|
|
|
link: Option<WeakFlowRef>,
|
2014-05-02 22:58:29 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
impl ContainingBlockLink {
|
|
|
|
fn new() -> ContainingBlockLink {
|
|
|
|
ContainingBlockLink {
|
2014-06-04 09:25:28 +04:00
|
|
|
link: None,
|
2014-05-02 22:58:29 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-04 09:25:28 +04:00
|
|
|
fn set(&mut self, link: FlowRef) {
|
2015-03-16 22:16:03 +03:00
|
|
|
self.link = Some(link.downgrade())
|
2014-05-02 22:58:29 +04:00
|
|
|
}
|
|
|
|
|
2015-03-21 14:12:45 +03:00
|
|
|
#[allow(unsafe_code)]
|
2015-03-16 22:16:03 +03:00
|
|
|
pub unsafe fn get<'a>(&'a mut self) -> &'a mut Option<WeakFlowRef> {
|
2014-06-04 09:25:28 +04:00
|
|
|
&mut self.link
|
2014-05-03 03:10:20 +04:00
|
|
|
}
|
|
|
|
|
2014-05-02 22:58:29 +04:00
|
|
|
#[inline]
|
2015-08-03 19:38:21 +03:00
|
|
|
pub fn generated_containing_block_size(&self, for_flow: OpaqueFlow) -> LogicalSize<Au> {
|
2014-06-04 09:25:28 +04:00
|
|
|
match self.link {
|
2015-05-13 22:27:21 +03:00
|
|
|
None => {
|
|
|
|
panic!("Link to containing block not established; perhaps you forgot to call \
|
|
|
|
`set_absolute_descendants`?")
|
|
|
|
}
|
2015-06-27 19:27:03 +03:00
|
|
|
Some(ref link) => link.upgrade().unwrap().generated_containing_block_size(for_flow),
|
2014-06-04 09:25:28 +04:00
|
|
|
}
|
2014-05-02 22:58:29 +04:00
|
|
|
}
|
2015-08-03 19:38:21 +03:00
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn explicit_block_containing_size(&self, layout_context: &LayoutContext) -> Option<Au> {
|
|
|
|
match self.link {
|
|
|
|
None => {
|
|
|
|
panic!("Link to containing block not established; perhaps you forgot to call \
|
|
|
|
`set_absolute_descendants`?")
|
|
|
|
}
|
|
|
|
Some(ref link) => {
|
|
|
|
let flow = link.upgrade().unwrap();
|
|
|
|
if flow.is_block_like() {
|
|
|
|
flow.as_immutable_block().explicit_block_containing_size(layout_context)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-05-02 22:58:29 +04:00
|
|
|
}
|
2015-05-13 22:27:21 +03:00
|
|
|
|
|
|
|
/// A wrapper for the pointer address of a flow. These pointer addresses may only be compared for
|
|
|
|
/// equality with other such pointer addresses, never dereferenced.
|
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
|
|
|
pub struct OpaqueFlow(pub usize);
|
|
|
|
|
|
|
|
impl OpaqueFlow {
|
|
|
|
#[allow(unsafe_code)]
|
|
|
|
pub fn from_flow(flow: &Flow) -> OpaqueFlow {
|
|
|
|
unsafe {
|
2015-08-16 17:37:40 +03:00
|
|
|
let object = mem::transmute::<&Flow, raw::TraitObject>(flow);
|
2015-05-13 22:27:21 +03:00
|
|
|
OpaqueFlow(object.data as usize)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn from_base_flow(base_flow: &BaseFlow) -> OpaqueFlow {
|
|
|
|
OpaqueFlow(base_flow as *const BaseFlow as usize)
|
|
|
|
}
|
|
|
|
}
|