mirror of
https://github.com/servo/servo.git
synced 2025-08-10 16:05:43 +01:00
auto merge of #4952 : bjwbell/servo/borders-txt-nodes, r=pcwalton
Inline fragments that are part of a text run don't have interior borders. So don't draw interior borders or include them when calculating positioning. Fixes https://github.com/servo/servo/issues/4658, where multiple text nodes that are adjacent have distinct borders. r? @Ms2ger, @pcwalton
This commit is contained in:
commit
b2f099026a
6 changed files with 74 additions and 9 deletions
|
@ -195,14 +195,17 @@ impl InlineFragmentsAccumulator {
|
|||
mut fragments,
|
||||
enclosing_style
|
||||
} = self;
|
||||
if let Some(enclosing_style) = enclosing_style {
|
||||
let frag_len = fragments.len();
|
||||
for (idx, frag) in fragments.iter_mut().enumerate() {
|
||||
|
||||
match enclosing_style {
|
||||
Some(enclosing_style) => {
|
||||
for frag in fragments.iter_mut() {
|
||||
frag.add_inline_context_style(enclosing_style.clone());
|
||||
}
|
||||
// frag is first inline fragment in the inline node
|
||||
let is_first = idx == 0;
|
||||
// frag is the last inline fragment in the inline node
|
||||
let is_last = idx == frag_len - 1;
|
||||
|
||||
frag.add_inline_context_style(enclosing_style.clone(), is_first, is_last);
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
fragments
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ use text;
|
|||
use util::OpaqueNodeMethods;
|
||||
use wrapper::{TLayoutNode, ThreadSafeLayoutNode};
|
||||
|
||||
use geom::num::Zero;
|
||||
use geom::{Point2D, Rect, Size2D};
|
||||
use gfx::display_list::{BOX_SHADOW_INFLATION_FACTOR, OpaqueNode};
|
||||
use gfx::text::glyph::CharIndex;
|
||||
|
@ -46,7 +47,7 @@ use std::str::FromStr;
|
|||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::mpsc::Sender;
|
||||
use string_cache::Atom;
|
||||
use style::properties::{ComputedValues, cascade_anonymous};
|
||||
use style::properties::{ComputedValues, cascade_anonymous, make_border};
|
||||
use style::node::{TElement, TNode};
|
||||
use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto, LengthOrPercentageOrNone};
|
||||
use style::computed_values::{clear, mix_blend_mode, overflow_wrap};
|
||||
|
@ -877,11 +878,31 @@ impl Fragment {
|
|||
|
||||
/// Adds a style to the inline context for this fragment. If the inline
|
||||
/// context doesn't exist yet, it will be created.
|
||||
pub fn add_inline_context_style(&mut self, style: Arc<ComputedValues>) {
|
||||
pub fn add_inline_context_style(&mut self,
|
||||
style: Arc<ComputedValues>,
|
||||
first_frag: bool,
|
||||
last_frag: bool) {
|
||||
|
||||
if self.inline_context.is_none() {
|
||||
self.inline_context = Some(InlineFragmentContext::new());
|
||||
}
|
||||
self.inline_context.as_mut().unwrap().styles.push(style.clone());
|
||||
let frag_style = if first_frag && last_frag {
|
||||
style.clone()
|
||||
} else {
|
||||
// Set the border width to zero and the border style to none on
|
||||
// border sides that are not the outermost for a node container.
|
||||
// Because with multiple inline fragments they don't have interior
|
||||
// borders separating each other.
|
||||
let mut border_width = style.logical_border_width();
|
||||
if !last_frag {
|
||||
border_width.set_right(style.writing_mode, Zero::zero());
|
||||
}
|
||||
if !first_frag {
|
||||
border_width.set_left(style.writing_mode, Zero::zero());
|
||||
}
|
||||
Arc::new(make_border(&*style, border_width))
|
||||
};
|
||||
self.inline_context.as_mut().unwrap().styles.push(frag_style);
|
||||
}
|
||||
|
||||
/// Determines which quantities (border/padding/margin/specified) should be included in the
|
||||
|
|
|
@ -17,6 +17,7 @@ use util::geometry::Au;
|
|||
use url::Url;
|
||||
use cssparser::{Parser, Color, RGBA, AtRuleParser, DeclarationParser,
|
||||
DeclarationListParser, parse_important, ToCss};
|
||||
use geom::num::Zero;
|
||||
use geom::SideOffsets2D;
|
||||
|
||||
use values::specified::BorderStyle;
|
||||
|
@ -3534,6 +3535,21 @@ pub fn make_inline(style: &ComputedValues) -> ComputedValues {
|
|||
style
|
||||
}
|
||||
|
||||
/// Sets `border_${side}_width` to the passed in values.
|
||||
/// If `border_${side}_width` == 0 also sets `border_${side}_style` = none.
|
||||
#[inline]
|
||||
pub fn make_border(style: &ComputedValues, border_width: LogicalMargin<Au>) -> ComputedValues {
|
||||
let mut style = (*style).clone();
|
||||
let physical_border = LogicalMargin::to_physical(&border_width, style.writing_mode);
|
||||
% for side in ["top", "right", "bottom", "left"]:
|
||||
style.border.make_unique().border_${side}_width = physical_border.${side};
|
||||
if physical_border.${side} == Zero::zero() {
|
||||
style.border.make_unique().border_${side}_style = BorderStyle::none;
|
||||
}
|
||||
% endfor
|
||||
style
|
||||
}
|
||||
|
||||
pub fn is_supported_property(property: &str) -> bool {
|
||||
match property {
|
||||
% for property in SHORTHANDS + LONGHANDS:
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
== img_dynamic_remove.html img_dynamic_remove_ref.html
|
||||
== upper_id_attr.html upper_id_attr_ref.html
|
||||
# inline_border_a.html inline_border_b.html
|
||||
== border_code_tag.html border_code_tag_ref.html
|
||||
== anon_block_inherit_a.html anon_block_inherit_b.html
|
||||
== attr_exists_selector.html attr_exists_selector_ref.html
|
||||
== attr_selector_case_sensitivity.html attr_selector_case_sensitivity_ref.html
|
||||
|
|
12
tests/ref/border_code_tag.html
Normal file
12
tests/ref/border_code_tag.html
Normal file
|
@ -0,0 +1,12 @@
|
|||
<html>
|
||||
<head>
|
||||
<style>
|
||||
code {
|
||||
border: 2px solid #ccc;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<code>Quotes: "".</code>
|
||||
</body>
|
||||
</html>
|
12
tests/ref/border_code_tag_ref.html
Normal file
12
tests/ref/border_code_tag_ref.html
Normal file
|
@ -0,0 +1,12 @@
|
|||
<html>
|
||||
<head>
|
||||
<style>
|
||||
code {
|
||||
border: 2px solid #ccc;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<code>Quotes: "".</code>
|
||||
</body>
|
||||
</html>
|
Loading…
Add table
Add a link
Reference in a new issue