mirror of
https://github.com/servo/servo.git
synced 2025-10-13 06:50:28 +01:00
* layout: Implement support for `line-height` and `vertical-align` This is an initial implementation of proper `line-height` and `vertical-align` support. While this change includes the bulk of the work there are still many missing pieces for full support. In particular some big missing things are: - Flex containers do not properly compute their baselines. The idea is to tackle this in a followup change. This causes various flex tests to start failing because everything used to be top aligned. - The implementation of the line-height quirks (only active in quirks mode) are incomplete. While the quirk works in many cases, there are still some cases where it is handled incorrectly. This requires more redesign and refinement, better suited for a followup. - Most of the features are CSS 3 such as precision control of the baseline and first and last baselines are not implemented. This change gets us close to CSS 2.x support. While there are many new test passes with this change some tests are starting to fail. An accounting of new failures: Tests failing also in Layout 2013: - /css/css2/positioning/toogle-abspos-on-relpos-inline-child.html (only passes in Chrome) - /css/CSS2/fonts/font-applies-to-001.xht (potentially an issue with font size) Invalid tests: - /css/CSS2/visudet/inline-block-baseline-003.xht - /css/CSS2/visudet/inline-block-baseline-004.xht - These are are failing in all browsers. See https://bugs.chromium.org/p/chromium/issues/detail?id=1222151. Missing table support: - /_mozilla/mozilla/table_valign_middle.html Missing `font-size-adjust` support : - /css/css-fonts/font-size-adjust-zero-2.html (also failing in 2013) Incomplete form field support : - /html/rendering/widgets/the-select-element/option-add-label-quirks.html (label isn't rendered so button isn't the right size in quirks mode due to line height quirk) Need support for calculating flexbox baseline: - /css/css-flexbox/fieldset-baseline-alignment.html - /css/css-flexbox/flex-inline.html - /css/css-flexbox/flexbox-baseline-multi-line-horiz-001.html - /css/css-flexbox/flexbox-baseline-single-item-001a.html - /css/css-flexbox/flexbox-baseline-single-item-001b.html Failing because we don't create anonymous inline boxes for text children of blocks: - /css/CSS2/linebox/anonymous-inline-inherit-001.html Passes locally (potentially related to fonts): - /css/CSS2/css1/c414-flt-fit-004.xht - /css/css-transforms/transform-input-017.html - /html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-min-intrinsic-size.html - /css/css-fonts/first-available-font-005.html - /css/css-fonts/first-available-font-006.html * Some cleanups after live review with @mukilan Also update results.
119 lines
3.7 KiB
Rust
119 lines
3.7 KiB
Rust
/* 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 https://mozilla.org/MPL/2.0/. */
|
|
|
|
//! Table layout.
|
|
//! See https://html.spec.whatwg.org/multipage/table-processing-model.
|
|
|
|
mod construct;
|
|
|
|
pub(crate) use construct::AnonymousTableContent;
|
|
pub use construct::TableBuilder;
|
|
use euclid::{Point2D, UnknownUnit, Vector2D};
|
|
use serde::Serialize;
|
|
use style::values::computed::Length;
|
|
|
|
use super::flow::BlockFormattingContext;
|
|
use crate::context::LayoutContext;
|
|
use crate::flow::BlockContainer;
|
|
use crate::formatting_contexts::IndependentLayout;
|
|
use crate::positioned::PositioningContext;
|
|
use crate::sizing::ContentSizes;
|
|
use crate::ContainingBlock;
|
|
|
|
#[derive(Debug, Default, Serialize)]
|
|
pub struct Table {
|
|
pub slots: Vec<Vec<TableSlot>>,
|
|
}
|
|
|
|
impl Table {
|
|
pub(crate) fn inline_content_sizes(&self) -> ContentSizes {
|
|
ContentSizes::zero()
|
|
}
|
|
|
|
pub(crate) fn layout(
|
|
&self,
|
|
_layout_context: &LayoutContext,
|
|
_positioning_context: &mut PositioningContext,
|
|
_containing_block: &ContainingBlock,
|
|
) -> IndependentLayout {
|
|
IndependentLayout {
|
|
fragments: Vec::new(),
|
|
content_block_size: Length::new(0.),
|
|
last_inflow_baseline_offset: None,
|
|
}
|
|
}
|
|
}
|
|
|
|
type TableSlotCoordinates = Point2D<usize, UnknownUnit>;
|
|
pub type TableSlotOffset = Vector2D<usize, UnknownUnit>;
|
|
|
|
#[derive(Debug, Serialize)]
|
|
pub struct TableSlotCell {
|
|
/// The contents of this cell, with its own layout.
|
|
contents: BlockFormattingContext,
|
|
|
|
/// Number of columns that the cell is to span. Must be greater than zero.
|
|
colspan: usize,
|
|
|
|
/// Number of rows that the cell is to span. Zero means that the cell is to span all
|
|
/// the remaining rows in the row group.
|
|
rowspan: usize,
|
|
|
|
// An id used for testing purposes.
|
|
pub id: u8,
|
|
}
|
|
|
|
impl TableSlotCell {
|
|
pub fn mock_for_testing(id: u8, colspan: usize, rowspan: usize) -> Self {
|
|
Self {
|
|
contents: BlockFormattingContext {
|
|
contents: BlockContainer::BlockLevelBoxes(Vec::new()),
|
|
contains_floats: false,
|
|
},
|
|
colspan,
|
|
rowspan,
|
|
id,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Serialize)]
|
|
/// A single table slot. It may be an actual cell, or a reference
|
|
/// to a previous cell that is spanned here
|
|
///
|
|
/// In case of table model errors, it may be multiple references
|
|
pub enum TableSlot {
|
|
/// A table cell, with a colspan and a rowspan.
|
|
Cell(TableSlotCell),
|
|
|
|
/// This slot is spanned by one or more multiple cells earlier in the table, which are
|
|
/// found at the given negative coordinate offsets. The vector is in the order of most
|
|
/// recent to earliest cell.
|
|
///
|
|
/// If there is more than one cell that spans a slot, this is a table model error, but
|
|
/// we still keep track of it. See
|
|
/// https://html.spec.whatwg.org/multipage/#table-model-error
|
|
Spanned(Vec<TableSlotOffset>),
|
|
|
|
/// An empty spot in the table. This can happen when there is a gap in columns between
|
|
/// cells that are defined and one which should exist because of cell with a rowspan
|
|
/// from a previous row.
|
|
Empty,
|
|
}
|
|
|
|
impl std::fmt::Debug for TableSlot {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
Self::Cell(_) => f.debug_tuple("Cell").finish(),
|
|
Self::Spanned(spanned) => f.debug_tuple("Spanned").field(spanned).finish(),
|
|
Self::Empty => write!(f, "Empty"),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TableSlot {
|
|
fn new_spanned(offset: TableSlotOffset) -> Self {
|
|
Self::Spanned(vec![offset])
|
|
}
|
|
}
|