mirror of
https://github.com/servo/servo.git
synced 2025-08-04 13:10:20 +01:00
Implement text-align
(except justify
)
This commit is contained in:
parent
6d91d77fba
commit
9f4b1a0f14
5 changed files with 84 additions and 13 deletions
|
@ -18,6 +18,7 @@ use gfx::text::text_run::GlyphRun;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use style::properties::ComputedValues;
|
use style::properties::ComputedValues;
|
||||||
use style::values::computed::{Length, LengthPercentage, Percentage};
|
use style::values::computed::{Length, LengthPercentage, Percentage};
|
||||||
|
use style::values::specified::text::TextAlignKeyword;
|
||||||
use style::Zero;
|
use style::Zero;
|
||||||
use webrender_api::FontInstanceKey;
|
use webrender_api::FontInstanceKey;
|
||||||
|
|
||||||
|
@ -260,8 +261,11 @@ impl InlineFormattingContext {
|
||||||
);
|
);
|
||||||
ifc.current_nesting_level = partial.parent_nesting_level
|
ifc.current_nesting_level = partial.parent_nesting_level
|
||||||
} else {
|
} else {
|
||||||
ifc.lines
|
ifc.lines.finish_line(
|
||||||
.finish_line(&mut ifc.current_nesting_level, containing_block);
|
&mut ifc.current_nesting_level,
|
||||||
|
containing_block,
|
||||||
|
ifc.inline_position,
|
||||||
|
);
|
||||||
return FlowLayout {
|
return FlowLayout {
|
||||||
fragments: ifc.lines.fragments,
|
fragments: ifc.lines.fragments,
|
||||||
content_block_size: ifc.lines.next_line_block_position,
|
content_block_size: ifc.lines.next_line_block_position,
|
||||||
|
@ -277,21 +281,62 @@ impl Lines {
|
||||||
&mut self,
|
&mut self,
|
||||||
top_nesting_level: &mut InlineNestingLevelState,
|
top_nesting_level: &mut InlineNestingLevelState,
|
||||||
containing_block: &ContainingBlock,
|
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 {
|
let start_corner = Vec2 {
|
||||||
inline: Length::zero(),
|
inline: Length::zero(),
|
||||||
block: self.next_line_block_position,
|
block: self.next_line_block_position,
|
||||||
};
|
};
|
||||||
let size = Vec2 {
|
let size = Vec2 {
|
||||||
inline: containing_block.inline_size,
|
inline: containing_block.inline_size,
|
||||||
block: std::mem::replace(
|
block: line_block_size,
|
||||||
&mut top_nesting_level.max_block_size_of_fragments_so_far,
|
|
||||||
Length::zero(),
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
self.next_line_block_position += size.block;
|
self.next_line_block_position += size.block;
|
||||||
self.fragments.push(Fragment::Anonymous(AnonymousFragment {
|
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 },
|
rect: Rect { start_corner, size },
|
||||||
mode: containing_block.style.writing_mode,
|
mode: containing_block.style.writing_mode,
|
||||||
}))
|
}))
|
||||||
|
@ -639,7 +684,8 @@ impl TextRun {
|
||||||
partial.parent_nesting_level.inline_start = Length::zero();
|
partial.parent_nesting_level.inline_start = Length::zero();
|
||||||
nesting_level = &mut partial.parent_nesting_level;
|
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();
|
ifc.inline_position = Length::zero();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* 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 gfx::text::glyph::GlyphStore;
|
||||||
use servo_arc::Arc as ServoArc;
|
use servo_arc::Arc as ServoArc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -68,6 +68,17 @@ pub(crate) struct ImageFragment {
|
||||||
pub image_key: ImageKey,
|
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 {
|
impl AnonymousFragment {
|
||||||
pub fn no_op(mode: WritingMode) -> Self {
|
pub fn no_op(mode: WritingMode) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|
|
@ -206,6 +206,20 @@ impl WritingMode {
|
||||||
self.intersects(WritingMode::UPRIGHT)
|
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]
|
#[inline]
|
||||||
pub fn inline_start_physical_side(&self) -> PhysicalSide {
|
pub fn inline_start_physical_side(&self) -> PhysicalSide {
|
||||||
match (self.is_vertical(), self.is_inline_tb(), self.is_bidi_ltr()) {
|
match (self.is_vertical(), self.is_inline_tb(), self.is_bidi_ltr()) {
|
||||||
|
|
|
@ -156,7 +156,6 @@ ${helpers.predefined_type(
|
||||||
"TextAlign",
|
"TextAlign",
|
||||||
"computed::TextAlign::Start",
|
"computed::TextAlign::Start",
|
||||||
engines="gecko servo-2013 servo-2020",
|
engines="gecko servo-2013 servo-2020",
|
||||||
servo_2020_pref="layout.2020.unimplemented",
|
|
||||||
animation_value_type="discrete",
|
animation_value_type="discrete",
|
||||||
spec="https://drafts.csswg.org/css-text/#propdef-text-align",
|
spec="https://drafts.csswg.org/css-text/#propdef-text-align",
|
||||||
servo_restyle_damage = "reflow",
|
servo_restyle_damage = "reflow",
|
||||||
|
|
|
@ -544,6 +544,7 @@ pub enum TextAlignKeyword {
|
||||||
Left,
|
Left,
|
||||||
Right,
|
Right,
|
||||||
Center,
|
Center,
|
||||||
|
#[cfg(any(feature = "gecko", feature = "servo-layout-2013"))]
|
||||||
Justify,
|
Justify,
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
MozCenter,
|
MozCenter,
|
||||||
|
@ -551,11 +552,11 @@ pub enum TextAlignKeyword {
|
||||||
MozLeft,
|
MozLeft,
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
MozRight,
|
MozRight,
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo-layout-2013")]
|
||||||
ServoCenter,
|
ServoCenter,
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo-layout-2013")]
|
||||||
ServoLeft,
|
ServoLeft,
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo-layout-2013")]
|
||||||
ServoRight,
|
ServoRight,
|
||||||
#[css(skip)]
|
#[css(skip)]
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue