Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement `text-align` (except `justify`) #25203

Merged
merged 6 commits into from Dec 10, 2019
Prev

Implement `text-align` (except `justify`)

  • Loading branch information
SimonSapin committed Dec 7, 2019
commit 9f4b1a0f147de0d81d89862007aea4e6cce3a743
@@ -18,6 +18,7 @@ use gfx::text::text_run::GlyphRun;
use servo_arc::Arc;
use style::properties::ComputedValues;
use style::values::computed::{Length, LengthPercentage, Percentage};
use style::values::specified::text::TextAlignKeyword;
use style::Zero;
use webrender_api::FontInstanceKey;

@@ -260,8 +261,11 @@ impl InlineFormattingContext {
);
ifc.current_nesting_level = partial.parent_nesting_level
} else {
ifc.lines
.finish_line(&mut ifc.current_nesting_level, containing_block);
ifc.lines.finish_line(
&mut ifc.current_nesting_level,
containing_block,
ifc.inline_position,
);
return FlowLayout {
fragments: ifc.lines.fragments,
content_block_size: ifc.lines.next_line_block_position,
@@ -277,21 +281,62 @@ impl Lines {
&mut self,
top_nesting_level: &mut InlineNestingLevelState,
containing_block: &ContainingBlock,
line_content_inline_size: Length,
) {
let mut line_contents = std::mem::take(&mut top_nesting_level.fragments_so_far);
let line_block_size = std::mem::replace(
&mut top_nesting_level.max_block_size_of_fragments_so_far,
Length::zero(),
);
enum TextAlign {
Start,
Center,
End,
}
let line_left_is_inline_start = containing_block
.style
.writing_mode
.line_left_is_inline_start();
let text_align = match containing_block.style.clone_text_align() {
TextAlignKeyword::Start => TextAlign::Start,
TextAlignKeyword::Center => TextAlign::Center,
TextAlignKeyword::End => TextAlign::End,
TextAlignKeyword::Left => {
if line_left_is_inline_start {
TextAlign::Start
} else {
TextAlign::End
}
},
TextAlignKeyword::Right => {
if line_left_is_inline_start {
TextAlign::End
} else {
TextAlign::Start
}
},
};
let move_by = match text_align {
TextAlign::Start => Length::zero(),
TextAlign::Center => (containing_block.inline_size - line_content_inline_size) / 2.,
TextAlign::End => containing_block.inline_size - line_content_inline_size,
};
if move_by > Length::zero() {
for fragment in &mut line_contents {
fragment.position_mut().inline += move_by;
}
}
let start_corner = Vec2 {
inline: Length::zero(),
block: self.next_line_block_position,
};
let size = Vec2 {
inline: containing_block.inline_size,
block: std::mem::replace(
&mut top_nesting_level.max_block_size_of_fragments_so_far,
Length::zero(),
),
block: line_block_size,
};
self.next_line_block_position += size.block;
self.fragments.push(Fragment::Anonymous(AnonymousFragment {
children: std::mem::take(&mut top_nesting_level.fragments_so_far),
children: line_contents,
rect: Rect { start_corner, size },
mode: containing_block.style.writing_mode,
}))
@@ -639,7 +684,8 @@ impl TextRun {
partial.parent_nesting_level.inline_start = Length::zero();
nesting_level = &mut partial.parent_nesting_level;
}
ifc.lines.finish_line(nesting_level, ifc.containing_block);
ifc.lines
.finish_line(nesting_level, ifc.containing_block, ifc.inline_position);
ifc.inline_position = Length::zero();
}
}
@@ -2,7 +2,7 @@
* 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/. */

use crate::geom::flow_relative::{Rect, Sides};
use crate::geom::flow_relative::{Rect, Sides, Vec2};
use gfx::text::glyph::GlyphStore;
use servo_arc::Arc as ServoArc;
use std::sync::Arc;
@@ -68,6 +68,17 @@ pub(crate) struct ImageFragment {
pub image_key: ImageKey,
}

impl Fragment {
pub fn position_mut(&mut self) -> &mut Vec2<Length> {
match self {
Fragment::Box(f) => &mut f.content_rect.start_corner,
Fragment::Anonymous(f) => &mut f.rect.start_corner,
Fragment::Text(f) => &mut f.rect.start_corner,
Fragment::Image(f) => &mut f.rect.start_corner,
}
}
}

impl AnonymousFragment {
pub fn no_op(mode: WritingMode) -> Self {
Self {
@@ -206,6 +206,20 @@ impl WritingMode {
self.intersects(WritingMode::UPRIGHT)
}

/// https://drafts.csswg.org/css-writing-modes/#logical-to-physical
///
/// | Return | line-left is… | line-right is… |
/// |---------|---------------|----------------|
/// | `true` | inline-start | inline-end |
/// | `false` | inline-end | inline-start |
#[inline]
pub fn line_left_is_inline_start(&self) -> bool {
// https://drafts.csswg.org/css-writing-modes/#inline-start
// “For boxes with a used direction value of ltr, this means the line-left side.
// For boxes with a used direction value of rtl, this means the line-right side.”
self.is_bidi_ltr()
}

#[inline]
pub fn inline_start_physical_side(&self) -> PhysicalSide {
match (self.is_vertical(), self.is_inline_tb(), self.is_bidi_ltr()) {
@@ -156,7 +156,6 @@ ${helpers.predefined_type(
"TextAlign",
"computed::TextAlign::Start",
engines="gecko servo-2013 servo-2020",
servo_2020_pref="layout.2020.unimplemented",
animation_value_type="discrete",
spec="https://drafts.csswg.org/css-text/#propdef-text-align",
servo_restyle_damage = "reflow",
@@ -544,18 +544,19 @@ pub enum TextAlignKeyword {
Left,
Right,
Center,
#[cfg(any(feature = "gecko", feature = "servo-layout-2013"))]
Justify,
#[cfg(feature = "gecko")]
MozCenter,
#[cfg(feature = "gecko")]
MozLeft,
#[cfg(feature = "gecko")]
MozRight,
#[cfg(feature = "servo")]
#[cfg(feature = "servo-layout-2013")]
ServoCenter,
#[cfg(feature = "servo")]
#[cfg(feature = "servo-layout-2013")]
ServoLeft,
#[cfg(feature = "servo")]
#[cfg(feature = "servo-layout-2013")]
ServoRight,
#[css(skip)]
#[cfg(feature = "gecko")]
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.