mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
Auto merge of #19931 - pyfisch:float-bounds, r=mrobinson
Use LayoutRects for bounds and overflow in display lists Convert text runs to glyphs in display list builder. Remove ComplexClippingRegion and use the WebRender type. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/19931) <!-- Reviewable:end -->
This commit is contained in:
commit
03a1a014ae
6 changed files with 223 additions and 325 deletions
|
@ -14,8 +14,7 @@
|
||||||
//! They are therefore not exactly analogous to constructs like Skia pictures, which consist of
|
//! They are therefore not exactly analogous to constructs like Skia pictures, which consist of
|
||||||
//! low-level drawing primitives.
|
//! low-level drawing primitives.
|
||||||
|
|
||||||
use app_units::Au;
|
use euclid::{Transform3D, Vector2D, TypedRect, SideOffsets2D};
|
||||||
use euclid::{Transform3D, Point2D, Vector2D, Rect, Size2D, TypedRect, SideOffsets2D};
|
|
||||||
use euclid::num::{One, Zero};
|
use euclid::num::{One, Zero};
|
||||||
use gfx_traits::{self, StackingContextId};
|
use gfx_traits::{self, StackingContextId};
|
||||||
use gfx_traits::print_tree::PrintTree;
|
use gfx_traits::print_tree::PrintTree;
|
||||||
|
@ -24,18 +23,19 @@ use msg::constellation_msg::PipelineId;
|
||||||
use net_traits::image::base::{Image, PixelFormat};
|
use net_traits::image::base::{Image, PixelFormat};
|
||||||
use range::Range;
|
use range::Range;
|
||||||
use servo_geometry::MaxRect;
|
use servo_geometry::MaxRect;
|
||||||
use std::cmp::{self, Ordering};
|
use std::cmp::Ordering;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::f32;
|
use std::f32;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use text::TextRun;
|
use text::TextRun;
|
||||||
use text::glyph::ByteIndex;
|
use text::glyph::ByteIndex;
|
||||||
use webrender_api::{BorderRadius, BorderWidths, BoxShadowClipMode, ColorF, ExtendMode};
|
use webrender_api::{BorderRadius, BorderWidths, BoxShadowClipMode, ClipMode, ColorF};
|
||||||
use webrender_api::{ExternalScrollId, FilterOp, GradientStop, ImageBorder, ImageKey};
|
use webrender_api::{ComplexClipRegion, ExtendMode, ExternalScrollId, FilterOp, FontInstanceKey};
|
||||||
use webrender_api::{ImageRendering, LayoutPoint, LayoutRect, LayoutSize, LayoutVector2D};
|
use webrender_api::{GlyphInstance, GradientStop, ImageBorder, ImageKey, ImageRendering};
|
||||||
use webrender_api::{LineStyle, LocalClip, MixBlendMode, NormalBorder, ScrollPolicy};
|
use webrender_api::{LayoutPoint, LayoutRect, LayoutSize, LayoutVector2D, LineStyle, LocalClip};
|
||||||
use webrender_api::{ScrollSensitivity, StickyOffsetBounds, TransformStyle};
|
use webrender_api::{MixBlendMode, NormalBorder, ScrollPolicy, ScrollSensitivity};
|
||||||
|
use webrender_api::{StickyOffsetBounds, TransformStyle};
|
||||||
|
|
||||||
pub use style::dom::OpaqueNode;
|
pub use style::dom::OpaqueNode;
|
||||||
|
|
||||||
|
@ -96,22 +96,22 @@ pub struct DisplayList {
|
||||||
impl DisplayList {
|
impl DisplayList {
|
||||||
/// Return the bounds of this display list based on the dimensions of the root
|
/// Return the bounds of this display list based on the dimensions of the root
|
||||||
/// stacking context.
|
/// stacking context.
|
||||||
pub fn bounds(&self) -> Rect<Au> {
|
pub fn bounds(&self) -> LayoutRect {
|
||||||
match self.list.get(0) {
|
match self.list.get(0) {
|
||||||
Some(&DisplayItem::PushStackingContext(ref item)) => item.stacking_context.bounds,
|
Some(&DisplayItem::PushStackingContext(ref item)) => item.stacking_context.bounds,
|
||||||
Some(_) => unreachable!("Root element of display list not stacking context."),
|
Some(_) => unreachable!("Root element of display list not stacking context."),
|
||||||
None => Rect::zero(),
|
None => LayoutRect::zero(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the text index within a node for the point of interest.
|
// Returns the text index within a node for the point of interest.
|
||||||
pub fn text_index(&self, node: OpaqueNode, point_in_item: &Point2D<Au>) -> Option<usize> {
|
pub fn text_index(&self, node: OpaqueNode, point_in_item: LayoutPoint) -> Option<usize> {
|
||||||
for item in &self.list {
|
for item in &self.list {
|
||||||
match item {
|
match item {
|
||||||
&DisplayItem::Text(ref text) => {
|
&DisplayItem::Text(ref text) => {
|
||||||
let base = item.base();
|
let base = item.base();
|
||||||
if base.metadata.node == node {
|
if base.metadata.node == node {
|
||||||
let point = *point_in_item + item.base().bounds.origin.to_vector();
|
let point = point_in_item + item.base().bounds.origin.to_vector();
|
||||||
let offset = point - text.baseline_origin;
|
let offset = point - text.baseline_origin;
|
||||||
return Some(text.text_run.range_index_of_advance(&text.range, offset.x));
|
return Some(text.text_run.range_index_of_advance(&text.range, offset.x));
|
||||||
}
|
}
|
||||||
|
@ -194,10 +194,10 @@ pub struct StackingContext {
|
||||||
pub context_type: StackingContextType,
|
pub context_type: StackingContextType,
|
||||||
|
|
||||||
/// The position and size of this stacking context.
|
/// The position and size of this stacking context.
|
||||||
pub bounds: Rect<Au>,
|
pub bounds: LayoutRect,
|
||||||
|
|
||||||
/// The overflow rect for this stacking context in its coordinate system.
|
/// The overflow rect for this stacking context in its coordinate system.
|
||||||
pub overflow: Rect<Au>,
|
pub overflow: LayoutRect,
|
||||||
|
|
||||||
/// The `z-index` for this stacking context.
|
/// The `z-index` for this stacking context.
|
||||||
pub z_index: i32,
|
pub z_index: i32,
|
||||||
|
@ -229,8 +229,8 @@ impl StackingContext {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(id: StackingContextId,
|
pub fn new(id: StackingContextId,
|
||||||
context_type: StackingContextType,
|
context_type: StackingContextType,
|
||||||
bounds: &Rect<Au>,
|
bounds: LayoutRect,
|
||||||
overflow: &Rect<Au>,
|
overflow: LayoutRect,
|
||||||
z_index: i32,
|
z_index: i32,
|
||||||
filters: Vec<FilterOp>,
|
filters: Vec<FilterOp>,
|
||||||
mix_blend_mode: MixBlendMode,
|
mix_blend_mode: MixBlendMode,
|
||||||
|
@ -243,8 +243,8 @@ impl StackingContext {
|
||||||
StackingContext {
|
StackingContext {
|
||||||
id,
|
id,
|
||||||
context_type,
|
context_type,
|
||||||
bounds: *bounds,
|
bounds,
|
||||||
overflow: *overflow,
|
overflow,
|
||||||
z_index,
|
z_index,
|
||||||
filters,
|
filters,
|
||||||
mix_blend_mode,
|
mix_blend_mode,
|
||||||
|
@ -261,8 +261,8 @@ impl StackingContext {
|
||||||
StackingContext::new(
|
StackingContext::new(
|
||||||
StackingContextId::root(),
|
StackingContextId::root(),
|
||||||
StackingContextType::Real,
|
StackingContextType::Real,
|
||||||
&Rect::zero(),
|
LayoutRect::zero(),
|
||||||
&Rect::zero(),
|
LayoutRect::zero(),
|
||||||
0,
|
0,
|
||||||
vec![],
|
vec![],
|
||||||
MixBlendMode::Normal,
|
MixBlendMode::Normal,
|
||||||
|
@ -394,7 +394,7 @@ pub enum DisplayItem {
|
||||||
#[derive(Clone, Deserialize, MallocSizeOf, Serialize)]
|
#[derive(Clone, Deserialize, MallocSizeOf, Serialize)]
|
||||||
pub struct BaseDisplayItem {
|
pub struct BaseDisplayItem {
|
||||||
/// The boundaries of the display item, in layer coordinates.
|
/// The boundaries of the display item, in layer coordinates.
|
||||||
pub bounds: Rect<Au>,
|
pub bounds: LayoutRect,
|
||||||
|
|
||||||
/// Metadata attached to this display item.
|
/// Metadata attached to this display item.
|
||||||
pub metadata: DisplayItemMetadata,
|
pub metadata: DisplayItemMetadata,
|
||||||
|
@ -414,7 +414,7 @@ pub struct BaseDisplayItem {
|
||||||
|
|
||||||
impl BaseDisplayItem {
|
impl BaseDisplayItem {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn new(bounds: Rect<Au>,
|
pub fn new(bounds: LayoutRect,
|
||||||
metadata: DisplayItemMetadata,
|
metadata: DisplayItemMetadata,
|
||||||
local_clip: LocalClip,
|
local_clip: LocalClip,
|
||||||
section: DisplayListSection,
|
section: DisplayListSection,
|
||||||
|
@ -454,23 +454,12 @@ impl BaseDisplayItem {
|
||||||
#[derive(Clone, Deserialize, MallocSizeOf, PartialEq, Serialize)]
|
#[derive(Clone, Deserialize, MallocSizeOf, PartialEq, Serialize)]
|
||||||
pub struct ClippingRegion {
|
pub struct ClippingRegion {
|
||||||
/// The main rectangular region. This does not include any corners.
|
/// The main rectangular region. This does not include any corners.
|
||||||
pub main: Rect<Au>,
|
pub main: LayoutRect,
|
||||||
/// Any complex regions.
|
/// Any complex regions.
|
||||||
///
|
///
|
||||||
/// TODO(pcwalton): Atomically reference count these? Not sure if it's worth the trouble.
|
/// TODO(pcwalton): Atomically reference count these? Not sure if it's worth the trouble.
|
||||||
/// Measure and follow up.
|
/// Measure and follow up.
|
||||||
pub complex: Vec<ComplexClippingRegion>,
|
pub complex: Vec<ComplexClipRegion>,
|
||||||
}
|
|
||||||
|
|
||||||
/// A complex clipping region. These don't as easily admit arbitrary intersection operations, so
|
|
||||||
/// they're stored in a list over to the side. Currently a complex clipping region is just a
|
|
||||||
/// rounded rectangle, but the CSS WGs will probably make us throw more stuff in here eventually.
|
|
||||||
#[derive(Clone, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
|
|
||||||
pub struct ComplexClippingRegion {
|
|
||||||
/// The boundaries of the rectangle.
|
|
||||||
pub rect: Rect<Au>,
|
|
||||||
/// Border radii of this rectangle.
|
|
||||||
pub radii: BorderRadii<Au>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClippingRegion {
|
impl ClippingRegion {
|
||||||
|
@ -478,7 +467,7 @@ impl ClippingRegion {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn empty() -> ClippingRegion {
|
pub fn empty() -> ClippingRegion {
|
||||||
ClippingRegion {
|
ClippingRegion {
|
||||||
main: Rect::zero(),
|
main: LayoutRect::zero(),
|
||||||
complex: Vec::new(),
|
complex: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -487,16 +476,16 @@ impl ClippingRegion {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn max() -> ClippingRegion {
|
pub fn max() -> ClippingRegion {
|
||||||
ClippingRegion {
|
ClippingRegion {
|
||||||
main: Rect::max_rect(),
|
main: LayoutRect::max_rect(),
|
||||||
complex: Vec::new(),
|
complex: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a clipping region that represents the given rectangle.
|
/// Returns a clipping region that represents the given rectangle.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_rect(rect: &Rect<Au>) -> ClippingRegion {
|
pub fn from_rect(rect: LayoutRect) -> ClippingRegion {
|
||||||
ClippingRegion {
|
ClippingRegion {
|
||||||
main: *rect,
|
main: rect,
|
||||||
complex: Vec::new(),
|
complex: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -506,8 +495,8 @@ impl ClippingRegion {
|
||||||
/// TODO(pcwalton): This could more eagerly eliminate complex clipping regions, at the cost of
|
/// TODO(pcwalton): This could more eagerly eliminate complex clipping regions, at the cost of
|
||||||
/// complexity.
|
/// complexity.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn intersect_rect(&mut self, rect: &Rect<Au>) {
|
pub fn intersect_rect(&mut self, rect: &LayoutRect) {
|
||||||
self.main = self.main.intersection(rect).unwrap_or(Rect::zero())
|
self.main = self.main.intersection(rect).unwrap_or(LayoutRect::zero())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if this clipping region might be nonempty. This can return false positives,
|
/// Returns true if this clipping region might be nonempty. This can return false positives,
|
||||||
|
@ -520,7 +509,7 @@ impl ClippingRegion {
|
||||||
/// Returns true if this clipping region might contain the given point and false otherwise.
|
/// Returns true if this clipping region might contain the given point and false otherwise.
|
||||||
/// This is a quick, not a precise, test; it can yield false positives.
|
/// This is a quick, not a precise, test; it can yield false positives.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn might_intersect_point(&self, point: &Point2D<Au>) -> bool {
|
pub fn might_intersect_point(&self, point: &LayoutPoint) -> bool {
|
||||||
self.main.contains(point) &&
|
self.main.contains(point) &&
|
||||||
self.complex.iter().all(|complex| complex.rect.contains(point))
|
self.complex.iter().all(|complex| complex.rect.contains(point))
|
||||||
}
|
}
|
||||||
|
@ -528,14 +517,14 @@ impl ClippingRegion {
|
||||||
/// Returns true if this clipping region might intersect the given rectangle and false
|
/// Returns true if this clipping region might intersect the given rectangle and false
|
||||||
/// otherwise. This is a quick, not a precise, test; it can yield false positives.
|
/// otherwise. This is a quick, not a precise, test; it can yield false positives.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn might_intersect_rect(&self, rect: &Rect<Au>) -> bool {
|
pub fn might_intersect_rect(&self, rect: &LayoutRect) -> bool {
|
||||||
self.main.intersects(rect) &&
|
self.main.intersects(rect) &&
|
||||||
self.complex.iter().all(|complex| complex.rect.intersects(rect))
|
self.complex.iter().all(|complex| complex.rect.intersects(rect))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if this clipping region completely surrounds the given rect.
|
/// Returns true if this clipping region completely surrounds the given rect.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn does_not_clip_rect(&self, rect: &Rect<Au>) -> bool {
|
pub fn does_not_clip_rect(&self, rect: &LayoutRect) -> bool {
|
||||||
self.main.contains(&rect.origin) && self.main.contains(&rect.bottom_right()) &&
|
self.main.contains(&rect.origin) && self.main.contains(&rect.bottom_right()) &&
|
||||||
self.complex.iter().all(|complex| {
|
self.complex.iter().all(|complex| {
|
||||||
complex.rect.contains(&rect.origin) && complex.rect.contains(&rect.bottom_right())
|
complex.rect.contains(&rect.origin) && complex.rect.contains(&rect.bottom_right())
|
||||||
|
@ -544,7 +533,7 @@ impl ClippingRegion {
|
||||||
|
|
||||||
/// Returns a bounding rect that surrounds this entire clipping region.
|
/// Returns a bounding rect that surrounds this entire clipping region.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn bounding_rect(&self) -> Rect<Au> {
|
pub fn bounding_rect(&self) -> LayoutRect {
|
||||||
let mut rect = self.main;
|
let mut rect = self.main;
|
||||||
for complex in &*self.complex {
|
for complex in &*self.complex {
|
||||||
rect = rect.union(&complex.rect)
|
rect = rect.union(&complex.rect)
|
||||||
|
@ -554,10 +543,11 @@ impl ClippingRegion {
|
||||||
|
|
||||||
/// Intersects this clipping region with the given rounded rectangle.
|
/// Intersects this clipping region with the given rounded rectangle.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn intersect_with_rounded_rect(&mut self, rect: &Rect<Au>, radii: &BorderRadii<Au>) {
|
pub fn intersect_with_rounded_rect(&mut self, rect: LayoutRect, radii: BorderRadius) {
|
||||||
let new_complex_region = ComplexClippingRegion {
|
let new_complex_region = ComplexClipRegion {
|
||||||
rect: *rect,
|
rect,
|
||||||
radii: *radii,
|
radii,
|
||||||
|
mode: ClipMode::Clip,
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME(pcwalton): This is O(n²) worst case for disjoint clipping regions. Is that OK?
|
// FIXME(pcwalton): This is O(n²) worst case for disjoint clipping regions. Is that OK?
|
||||||
|
@ -576,21 +566,19 @@ impl ClippingRegion {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.complex.push(ComplexClippingRegion {
|
self.complex.push(new_complex_region);
|
||||||
rect: *rect,
|
|
||||||
radii: *radii,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Translates this clipping region by the given vector.
|
/// Translates this clipping region by the given vector.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn translate(&self, delta: &Vector2D<Au>) -> ClippingRegion {
|
pub fn translate(&self, delta: &LayoutVector2D) -> ClippingRegion {
|
||||||
ClippingRegion {
|
ClippingRegion {
|
||||||
main: self.main.translate(delta),
|
main: self.main.translate(delta),
|
||||||
complex: self.complex.iter().map(|complex| {
|
complex: self.complex.iter().map(|complex| {
|
||||||
ComplexClippingRegion {
|
ComplexClipRegion {
|
||||||
rect: complex.rect.translate(delta),
|
rect: complex.rect.translate(delta),
|
||||||
radii: complex.radii,
|
radii: complex.radii,
|
||||||
|
mode: complex.mode,
|
||||||
}
|
}
|
||||||
}).collect(),
|
}).collect(),
|
||||||
}
|
}
|
||||||
|
@ -598,7 +586,7 @@ impl ClippingRegion {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_max(&self) -> bool {
|
pub fn is_max(&self) -> bool {
|
||||||
self.main == Rect::max_rect() && self.complex.is_empty()
|
self.main == LayoutRect::max_rect() && self.complex.is_empty()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -608,7 +596,7 @@ impl fmt::Debug for ClippingRegion {
|
||||||
write!(f, "ClippingRegion::Max")
|
write!(f, "ClippingRegion::Max")
|
||||||
} else if *self == ClippingRegion::empty() {
|
} else if *self == ClippingRegion::empty() {
|
||||||
write!(f, "ClippingRegion::Empty")
|
write!(f, "ClippingRegion::Empty")
|
||||||
} else if self.main == Rect::max_rect() {
|
} else if self.main == LayoutRect::max_rect() {
|
||||||
write!(f, "ClippingRegion(Complex={:?})", self.complex)
|
write!(f, "ClippingRegion(Complex={:?})", self.complex)
|
||||||
} else {
|
} else {
|
||||||
write!(f, "ClippingRegion(Rect={:?}, Complex={:?})", self.main, self.complex)
|
write!(f, "ClippingRegion(Rect={:?}, Complex={:?})", self.main, self.complex)
|
||||||
|
@ -616,17 +604,21 @@ impl fmt::Debug for ClippingRegion {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ComplexClippingRegion {
|
pub trait CompletelyEncloses {
|
||||||
|
fn completely_encloses(&self, other: &Self) -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CompletelyEncloses for ComplexClipRegion {
|
||||||
// TODO(pcwalton): This could be more aggressive by considering points that touch the inside of
|
// TODO(pcwalton): This could be more aggressive by considering points that touch the inside of
|
||||||
// the border radius ellipse.
|
// the border radius ellipse.
|
||||||
fn completely_encloses(&self, other: &ComplexClippingRegion) -> bool {
|
fn completely_encloses(&self, other: &Self) -> bool {
|
||||||
let left = cmp::max(self.radii.top_left.width, self.radii.bottom_left.width);
|
let left = self.radii.top_left.width.max(self.radii.bottom_left.width);
|
||||||
let top = cmp::max(self.radii.top_left.height, self.radii.top_right.height);
|
let top = self.radii.top_left.height.max(self.radii.top_right.height);
|
||||||
let right = cmp::max(self.radii.top_right.width, self.radii.bottom_right.width);
|
let right = self.radii.top_right.width.max(self.radii.bottom_right.width);
|
||||||
let bottom = cmp::max(self.radii.bottom_left.height, self.radii.bottom_right.height);
|
let bottom = self.radii.bottom_left.height.max(self.radii.bottom_right.height);
|
||||||
let interior = Rect::new(Point2D::new(self.rect.origin.x + left, self.rect.origin.y + top),
|
let interior = LayoutRect::new(LayoutPoint::new(self.rect.origin.x + left, self.rect.origin.y + top),
|
||||||
Size2D::new(self.rect.size.width - left - right,
|
LayoutSize::new(self.rect.size.width - left - right,
|
||||||
self.rect.size.height - top - bottom));
|
self.rect.size.height - top - bottom));
|
||||||
interior.origin.x <= other.rect.origin.x && interior.origin.y <= other.rect.origin.y &&
|
interior.origin.x <= other.rect.origin.x && interior.origin.y <= other.rect.origin.y &&
|
||||||
interior.max_x() >= other.rect.max_x() && interior.max_y() >= other.rect.max_y()
|
interior.max_x() >= other.rect.max_x() && interior.max_y() >= other.rect.max_y()
|
||||||
}
|
}
|
||||||
|
@ -667,14 +659,14 @@ pub struct TextDisplayItem {
|
||||||
/// The range of text within the text run.
|
/// The range of text within the text run.
|
||||||
pub range: Range<ByteIndex>,
|
pub range: Range<ByteIndex>,
|
||||||
|
|
||||||
|
/// The position of the start of the baseline of this text.
|
||||||
|
pub baseline_origin: LayoutPoint,
|
||||||
|
/// A collection of (non-whitespace) glyphs to be displayed.
|
||||||
|
pub glyphs: Vec<GlyphInstance>,
|
||||||
|
/// Reference to the font to be used.
|
||||||
|
pub font_key: FontInstanceKey,
|
||||||
/// The color of the text.
|
/// The color of the text.
|
||||||
pub text_color: ColorF,
|
pub text_color: ColorF,
|
||||||
|
|
||||||
/// The position of the start of the baseline of this text.
|
|
||||||
pub baseline_origin: Point2D<Au>,
|
|
||||||
|
|
||||||
/// The orientation of the text: upright or sideways left/right.
|
|
||||||
pub orientation: TextOrientation,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Eq, MallocSizeOf, PartialEq, Serialize)]
|
#[derive(Clone, Deserialize, Eq, MallocSizeOf, PartialEq, Serialize)]
|
||||||
|
@ -826,68 +818,6 @@ pub struct BorderDisplayItem {
|
||||||
pub details: BorderDetails,
|
pub details: BorderDetails,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Information about the border radii.
|
|
||||||
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
|
|
||||||
pub struct BorderRadii<T> {
|
|
||||||
pub top_left: Size2D<T>,
|
|
||||||
pub top_right: Size2D<T>,
|
|
||||||
pub bottom_right: Size2D<T>,
|
|
||||||
pub bottom_left: Size2D<T>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Default for BorderRadii<T> where T: Default, T: Clone {
|
|
||||||
fn default() -> Self {
|
|
||||||
let top_left = Size2D::new(Default::default(),
|
|
||||||
Default::default());
|
|
||||||
let top_right = Size2D::new(Default::default(),
|
|
||||||
Default::default());
|
|
||||||
let bottom_left = Size2D::new(Default::default(),
|
|
||||||
Default::default());
|
|
||||||
let bottom_right = Size2D::new(Default::default(),
|
|
||||||
Default::default());
|
|
||||||
BorderRadii { top_left: top_left,
|
|
||||||
top_right: top_right,
|
|
||||||
bottom_left: bottom_left,
|
|
||||||
bottom_right: bottom_right }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BorderRadii<Au> {
|
|
||||||
// Scale the border radii by the specified factor
|
|
||||||
pub fn scale_by(&self, s: f32) -> BorderRadii<Au> {
|
|
||||||
BorderRadii { top_left: BorderRadii::scale_corner_by(self.top_left, s),
|
|
||||||
top_right: BorderRadii::scale_corner_by(self.top_right, s),
|
|
||||||
bottom_left: BorderRadii::scale_corner_by(self.bottom_left, s),
|
|
||||||
bottom_right: BorderRadii::scale_corner_by(self.bottom_right, s) }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scale the border corner radius by the specified factor
|
|
||||||
pub fn scale_corner_by(corner: Size2D<Au>, s: f32) -> Size2D<Au> {
|
|
||||||
Size2D::new(corner.width.scale_by(s), corner.height.scale_by(s))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> BorderRadii<T> where T: PartialEq + Zero {
|
|
||||||
/// Returns true if all the radii are zero.
|
|
||||||
pub fn is_square(&self) -> bool {
|
|
||||||
let zero = Zero::zero();
|
|
||||||
self.top_left == zero && self.top_right == zero && self.bottom_right == zero &&
|
|
||||||
self.bottom_left == zero
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> BorderRadii<T> where T: PartialEq + Zero + Clone {
|
|
||||||
/// Returns a set of border radii that all have the given value.
|
|
||||||
pub fn all_same(value: T) -> BorderRadii<T> {
|
|
||||||
BorderRadii {
|
|
||||||
top_left: Size2D::new(value.clone(), value.clone()),
|
|
||||||
top_right: Size2D::new(value.clone(), value.clone()),
|
|
||||||
bottom_right: Size2D::new(value.clone(), value.clone()),
|
|
||||||
bottom_left: Size2D::new(value.clone(), value.clone()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Paints a line segment.
|
/// Paints a line segment.
|
||||||
#[derive(Clone, Deserialize, MallocSizeOf, Serialize)]
|
#[derive(Clone, Deserialize, MallocSizeOf, Serialize)]
|
||||||
pub struct LineDisplayItem {
|
pub struct LineDisplayItem {
|
||||||
|
@ -1015,7 +945,7 @@ impl DisplayItem {
|
||||||
self.base().section
|
self.base().section
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bounds(&self) -> Rect<Au> {
|
pub fn bounds(&self) -> LayoutRect {
|
||||||
self.base().bounds
|
self.base().bounds
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1050,11 +980,7 @@ impl fmt::Debug for DisplayItem {
|
||||||
solid_color.color.g,
|
solid_color.color.g,
|
||||||
solid_color.color.b,
|
solid_color.color.b,
|
||||||
solid_color.color.a),
|
solid_color.color.a),
|
||||||
DisplayItem::Text(ref text) => {
|
DisplayItem::Text(_) => "Text".to_owned(),
|
||||||
format!("Text ({:?})",
|
|
||||||
&text.text_run.text[
|
|
||||||
text.range.begin().0 as usize..(text.range.begin().0 + text.range.length().0) as usize])
|
|
||||||
}
|
|
||||||
DisplayItem::Image(_) => "Image".to_owned(),
|
DisplayItem::Image(_) => "Image".to_owned(),
|
||||||
DisplayItem::Border(_) => "Border".to_owned(),
|
DisplayItem::Border(_) => "Border".to_owned(),
|
||||||
DisplayItem::Gradient(_) => "Gradient".to_owned(),
|
DisplayItem::Gradient(_) => "Gradient".to_owned(),
|
||||||
|
|
|
@ -333,10 +333,10 @@ impl<'a> TextRun {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the index in the range of the first glyph advancing over given advance
|
/// Returns the index in the range of the first glyph advancing over given advance
|
||||||
pub fn range_index_of_advance(&self, range: &Range<ByteIndex>, advance: Au) -> usize {
|
pub fn range_index_of_advance(&self, range: &Range<ByteIndex>, advance: f32) -> usize {
|
||||||
// TODO(Issue #199): alter advance direction for RTL
|
// TODO(Issue #199): alter advance direction for RTL
|
||||||
// TODO(Issue #98): using inter-char and inter-word spacing settings when measuring text
|
// TODO(Issue #98): using inter-char and inter-word spacing settings when measuring text
|
||||||
let mut remaining = advance;
|
let mut remaining = Au::from_f32_px(advance);
|
||||||
self.natural_word_slices_in_range(range)
|
self.natural_word_slices_in_range(range)
|
||||||
.map(|slice| {
|
.map(|slice| {
|
||||||
let (slice_index, slice_advance) =
|
let (slice_index, slice_advance) =
|
||||||
|
|
|
@ -17,8 +17,7 @@ use context::LayoutContext;
|
||||||
use display_list::ToLayout;
|
use display_list::ToLayout;
|
||||||
use display_list::background::{compute_background_image_size, tile_image_axis};
|
use display_list::background::{compute_background_image_size, tile_image_axis};
|
||||||
use display_list::background::{convert_linear_gradient, convert_radial_gradient};
|
use display_list::background::{convert_linear_gradient, convert_radial_gradient};
|
||||||
use display_list::webrender_helpers::ToBorderRadius;
|
use euclid::{Point2D, Rect, SideOffsets2D, Size2D, Transform3D, TypedSize2D, Vector2D, rect};
|
||||||
use euclid::{Point2D, Rect, SideOffsets2D, Size2D, Transform3D, TypedRect, TypedSize2D, Vector2D};
|
|
||||||
use flex::FlexFlow;
|
use flex::FlexFlow;
|
||||||
use flow::{BaseFlow, Flow, FlowFlags};
|
use flow::{BaseFlow, Flow, FlowFlags};
|
||||||
use flow_ref::FlowRef;
|
use flow_ref::FlowRef;
|
||||||
|
@ -27,7 +26,7 @@ use fragment::{CanvasFragmentSource, CoordinateSystem, Fragment, ScannedTextFrag
|
||||||
use fragment::SpecificFragmentInfo;
|
use fragment::SpecificFragmentInfo;
|
||||||
use gfx::display_list;
|
use gfx::display_list;
|
||||||
use gfx::display_list::{BaseDisplayItem, BorderDetails, BorderDisplayItem, BLUR_INFLATION_FACTOR};
|
use gfx::display_list::{BaseDisplayItem, BorderDetails, BorderDisplayItem, BLUR_INFLATION_FACTOR};
|
||||||
use gfx::display_list::{BorderRadii, BoxShadowDisplayItem, ClipScrollNode};
|
use gfx::display_list::{BoxShadowDisplayItem, ClipScrollNode};
|
||||||
use gfx::display_list::{ClipScrollNodeIndex, ClipScrollNodeType, ClippingAndScrolling};
|
use gfx::display_list::{ClipScrollNodeIndex, ClipScrollNodeType, ClippingAndScrolling};
|
||||||
use gfx::display_list::{ClippingRegion, DisplayItem, DisplayItemMetadata, DisplayList};
|
use gfx::display_list::{ClippingRegion, DisplayItem, DisplayItemMetadata, DisplayList};
|
||||||
use gfx::display_list::{DisplayListSection, GradientDisplayItem, IframeDisplayItem};
|
use gfx::display_list::{DisplayListSection, GradientDisplayItem, IframeDisplayItem};
|
||||||
|
@ -36,6 +35,8 @@ use gfx::display_list::{PopAllTextShadowsDisplayItem, PushTextShadowDisplayItem}
|
||||||
use gfx::display_list::{RadialGradientDisplayItem, SolidColorDisplayItem, StackingContext};
|
use gfx::display_list::{RadialGradientDisplayItem, SolidColorDisplayItem, StackingContext};
|
||||||
use gfx::display_list::{StackingContextType, StickyFrameData, TextDisplayItem, TextOrientation};
|
use gfx::display_list::{StackingContextType, StickyFrameData, TextDisplayItem, TextOrientation};
|
||||||
use gfx::display_list::WebRenderImageInfo;
|
use gfx::display_list::WebRenderImageInfo;
|
||||||
|
use gfx::text::TextRun;
|
||||||
|
use gfx::text::glyph::ByteIndex;
|
||||||
use gfx_traits::{combine_id_with_fragment_type, FragmentType, StackingContextId};
|
use gfx_traits::{combine_id_with_fragment_type, FragmentType, StackingContextId};
|
||||||
use inline::{InlineFlow, InlineFragmentNodeFlags};
|
use inline::{InlineFlow, InlineFragmentNodeFlags};
|
||||||
use ipc_channel::ipc;
|
use ipc_channel::ipc;
|
||||||
|
@ -47,8 +48,8 @@ use net_traits::image_cache::UsePlaceholder;
|
||||||
use range::Range;
|
use range::Range;
|
||||||
use servo_config::opts;
|
use servo_config::opts;
|
||||||
use servo_geometry::MaxRect;
|
use servo_geometry::MaxRect;
|
||||||
use std::{cmp, f32};
|
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
|
use std::f32;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use style::computed_values::background_attachment::single_value::T as BackgroundAttachment;
|
use style::computed_values::background_attachment::single_value::T as BackgroundAttachment;
|
||||||
|
@ -73,10 +74,11 @@ use style_traits::CSSPixel;
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
use style_traits::cursor::CursorKind;
|
use style_traits::cursor::CursorKind;
|
||||||
use table_cell::CollapsedBordersForCell;
|
use table_cell::CollapsedBordersForCell;
|
||||||
use webrender_api::{self, BorderSide, BoxShadowClipMode, ClipMode, ColorF, ComplexClipRegion};
|
use webrender_api::{self, BorderRadius, BorderSide, BoxShadowClipMode, ClipMode, ColorF};
|
||||||
use webrender_api::{ExternalScrollId, FilterOp, ImageBorder, ImageRendering, LayoutRect};
|
use webrender_api::{ComplexClipRegion, ExternalScrollId, FilterOp, GlyphInstance, ImageBorder};
|
||||||
use webrender_api::{LayoutSize, LayoutVector2D, LineStyle, LocalClip, NinePatchDescriptor};
|
use webrender_api::{ImageRendering, LayoutRect, LayoutSize, LayoutVector2D, LineStyle, LocalClip};
|
||||||
use webrender_api::{NormalBorder, ScrollPolicy, ScrollSensitivity, StickyOffsetBounds};
|
use webrender_api::{NinePatchDescriptor, NormalBorder, ScrollPolicy, ScrollSensitivity};
|
||||||
|
use webrender_api::StickyOffsetBounds;
|
||||||
|
|
||||||
trait ResolvePercentage {
|
trait ResolvePercentage {
|
||||||
fn resolve(&self, length: u32) -> u32;
|
fn resolve(&self, length: u32) -> u32;
|
||||||
|
@ -244,7 +246,7 @@ impl StackingContextCollectionState {
|
||||||
// takes care of adding this root node and it can be ignored during DL conversion.
|
// takes care of adding this root node and it can be ignored during DL conversion.
|
||||||
let root_node = ClipScrollNode {
|
let root_node = ClipScrollNode {
|
||||||
parent_index: ClipScrollNodeIndex(0),
|
parent_index: ClipScrollNodeIndex(0),
|
||||||
clip: ClippingRegion::from_rect(&TypedRect::zero()),
|
clip: ClippingRegion::from_rect(LayoutRect::zero()),
|
||||||
content_rect: LayoutRect::zero(),
|
content_rect: LayoutRect::zero(),
|
||||||
node_type: ClipScrollNodeType::ScrollFrame(
|
node_type: ClipScrollNodeType::ScrollFrame(
|
||||||
ScrollSensitivity::ScriptAndInputEvents,
|
ScrollSensitivity::ScriptAndInputEvents,
|
||||||
|
@ -389,7 +391,7 @@ impl<'a> DisplayListBuildState<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
BaseDisplayItem::new(
|
BaseDisplayItem::new(
|
||||||
*bounds,
|
bounds.to_layout(),
|
||||||
DisplayItemMetadata {
|
DisplayItemMetadata {
|
||||||
node,
|
node,
|
||||||
// Store cursor id in display list.
|
// Store cursor id in display list.
|
||||||
|
@ -708,16 +710,25 @@ pub trait FragmentDisplayListBuilding {
|
||||||
fn fragment_type(&self) -> FragmentType;
|
fn fragment_type(&self) -> FragmentType;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_overlapping_radii(size: &Size2D<Au>, radii: &BorderRadii<Au>) -> BorderRadii<Au> {
|
fn scale_border_radii(radii: BorderRadius, factor: f32) -> BorderRadius {
|
||||||
|
BorderRadius {
|
||||||
|
top_left: radii.top_left * factor,
|
||||||
|
top_right: radii.top_right * factor,
|
||||||
|
bottom_left: radii.bottom_left * factor,
|
||||||
|
bottom_right: radii.bottom_right * factor,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_overlapping_radii(size: LayoutSize, radii: BorderRadius) -> BorderRadius {
|
||||||
// No two corners' border radii may add up to more than the length of the edge
|
// No two corners' border radii may add up to more than the length of the edge
|
||||||
// between them. To prevent that, all radii are scaled down uniformly.
|
// between them. To prevent that, all radii are scaled down uniformly.
|
||||||
fn scale_factor(radius_a: Au, radius_b: Au, edge_length: Au) -> f32 {
|
fn scale_factor(radius_a: f32, radius_b: f32, edge_length: f32) -> f32 {
|
||||||
let required = radius_a + radius_b;
|
let required = radius_a + radius_b;
|
||||||
|
|
||||||
if required <= edge_length {
|
if required <= edge_length {
|
||||||
1.0
|
1.0
|
||||||
} else {
|
} else {
|
||||||
edge_length.to_f32_px() / required.to_f32_px()
|
edge_length / required
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -738,39 +749,39 @@ fn handle_overlapping_radii(size: &Size2D<Au>, radii: &BorderRadii<Au>) -> Borde
|
||||||
.min(left_factor)
|
.min(left_factor)
|
||||||
.min(right_factor);
|
.min(right_factor);
|
||||||
if min_factor < 1.0 {
|
if min_factor < 1.0 {
|
||||||
radii.scale_by(min_factor)
|
scale_border_radii(radii, min_factor)
|
||||||
} else {
|
} else {
|
||||||
*radii
|
radii
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_border_radius(
|
fn build_border_radius(
|
||||||
abs_bounds: &Rect<Au>,
|
abs_bounds: &Rect<Au>,
|
||||||
border_style: &style_structs::Border,
|
border_style: &style_structs::Border,
|
||||||
) -> BorderRadii<Au> {
|
) -> BorderRadius {
|
||||||
// TODO(cgaebel): Support border radii even in the case of multiple border widths.
|
// TODO(cgaebel): Support border radii even in the case of multiple border widths.
|
||||||
// This is an extension of supporting elliptical radii. For now, all percentage
|
// This is an extension of supporting elliptical radii. For now, all percentage
|
||||||
// radii will be relative to the width.
|
// radii will be relative to the width.
|
||||||
|
|
||||||
handle_overlapping_radii(
|
handle_overlapping_radii(
|
||||||
&abs_bounds.size,
|
abs_bounds.size.to_layout(),
|
||||||
&BorderRadii {
|
BorderRadius {
|
||||||
top_left: model::specified_border_radius(
|
top_left: model::specified_border_radius(
|
||||||
border_style.border_top_left_radius,
|
border_style.border_top_left_radius,
|
||||||
abs_bounds.size,
|
abs_bounds.size,
|
||||||
),
|
).to_layout(),
|
||||||
top_right: model::specified_border_radius(
|
top_right: model::specified_border_radius(
|
||||||
border_style.border_top_right_radius,
|
border_style.border_top_right_radius,
|
||||||
abs_bounds.size,
|
abs_bounds.size,
|
||||||
),
|
).to_layout(),
|
||||||
bottom_right: model::specified_border_radius(
|
bottom_right: model::specified_border_radius(
|
||||||
border_style.border_bottom_right_radius,
|
border_style.border_bottom_right_radius,
|
||||||
abs_bounds.size,
|
abs_bounds.size,
|
||||||
),
|
).to_layout(),
|
||||||
bottom_left: model::specified_border_radius(
|
bottom_left: model::specified_border_radius(
|
||||||
border_style.border_bottom_left_radius,
|
border_style.border_bottom_left_radius,
|
||||||
abs_bounds.size,
|
abs_bounds.size,
|
||||||
),
|
).to_layout(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -780,9 +791,9 @@ fn build_border_radius(
|
||||||
fn build_border_radius_for_inner_rect(
|
fn build_border_radius_for_inner_rect(
|
||||||
outer_rect: &Rect<Au>,
|
outer_rect: &Rect<Au>,
|
||||||
style: &ComputedValues,
|
style: &ComputedValues,
|
||||||
) -> BorderRadii<Au> {
|
) -> BorderRadius {
|
||||||
let radii = build_border_radius(&outer_rect, style.get_border());
|
let radii = build_border_radius(&outer_rect, style.get_border());
|
||||||
if radii.is_square() {
|
if radii.is_zero() {
|
||||||
return radii;
|
return radii;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -830,20 +841,23 @@ fn simple_normal_border(color: ColorF, style: webrender_api::BorderStyle) -> Nor
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calculate_inner_border_radii(
|
fn calculate_inner_border_radii(
|
||||||
mut radii: BorderRadii<Au>,
|
mut radii: BorderRadius,
|
||||||
offsets: SideOffsets2D<Au>,
|
offsets: SideOffsets2D<Au>,
|
||||||
) -> BorderRadii<Au> {
|
) -> BorderRadius {
|
||||||
radii.top_left.width = cmp::max(Au(0), radii.top_left.width - offsets.left);
|
fn inner_length(x: f32, offset: Au) -> f32 {
|
||||||
radii.bottom_left.width = cmp::max(Au(0), radii.bottom_left.width - offsets.left);
|
0.0_f32.max(x - offset.to_f32_px())
|
||||||
|
}
|
||||||
|
radii.top_left.width = inner_length(radii.top_left.width, offsets.left);
|
||||||
|
radii.bottom_left.width = inner_length(radii.bottom_left.width, offsets.left);
|
||||||
|
|
||||||
radii.top_right.width = cmp::max(Au(0), radii.top_right.width - offsets.right);
|
radii.top_right.width = inner_length(radii.top_right.width, offsets.right);
|
||||||
radii.bottom_right.width = cmp::max(Au(0), radii.bottom_right.width - offsets.right);
|
radii.bottom_right.width = inner_length(radii.bottom_right.width, offsets.right);
|
||||||
|
|
||||||
radii.top_left.height = cmp::max(Au(0), radii.top_left.height - offsets.top);
|
radii.top_left.height = inner_length(radii.top_left.height, offsets.top);
|
||||||
radii.top_right.height = cmp::max(Au(0), radii.top_right.height - offsets.top);
|
radii.top_right.height = inner_length(radii.top_right.height, offsets.top);
|
||||||
|
|
||||||
radii.bottom_left.height = cmp::max(Au(0), radii.bottom_left.height - offsets.bottom);
|
radii.bottom_left.height = inner_length(radii.bottom_left.height, offsets.bottom);
|
||||||
radii.bottom_right.height = cmp::max(Au(0), radii.bottom_right.height - offsets.bottom);
|
radii.bottom_right.height = inner_length(radii.bottom_right.height, offsets.bottom);
|
||||||
radii
|
radii
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -877,6 +891,35 @@ fn build_image_border_details(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn convert_text_run_to_glyphs(
|
||||||
|
text_run: Arc<TextRun>,
|
||||||
|
range: Range<ByteIndex>,
|
||||||
|
mut origin: Point2D<Au>,
|
||||||
|
) -> Vec<GlyphInstance> {
|
||||||
|
let mut glyphs = vec![];
|
||||||
|
|
||||||
|
for slice in text_run.natural_word_slices_in_visual_order(&range) {
|
||||||
|
for glyph in slice.glyphs.iter_glyphs_for_byte_range(&slice.range) {
|
||||||
|
let glyph_advance = if glyph.char_is_space() {
|
||||||
|
glyph.advance() + text_run.extra_word_spacing
|
||||||
|
} else {
|
||||||
|
glyph.advance()
|
||||||
|
};
|
||||||
|
if !slice.glyphs.is_whitespace() {
|
||||||
|
let glyph_offset = glyph.offset().unwrap_or(Point2D::zero());
|
||||||
|
let point = origin + glyph_offset.to_vector();
|
||||||
|
let glyph = GlyphInstance {
|
||||||
|
index: glyph.id(),
|
||||||
|
point: point.to_layout(),
|
||||||
|
};
|
||||||
|
glyphs.push(glyph);
|
||||||
|
}
|
||||||
|
origin.x += glyph_advance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return glyphs;
|
||||||
|
}
|
||||||
|
|
||||||
impl FragmentDisplayListBuilding for Fragment {
|
impl FragmentDisplayListBuilding for Fragment {
|
||||||
fn collect_stacking_contexts_for_blocklike_fragment(
|
fn collect_stacking_contexts_for_blocklike_fragment(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -946,14 +989,10 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
let clip = if !border_radii.is_square() {
|
let clip = if !border_radii.is_zero() {
|
||||||
LocalClip::RoundedRect(
|
LocalClip::RoundedRect(
|
||||||
bounds.to_layout(),
|
bounds.to_layout(),
|
||||||
ComplexClipRegion::new(
|
ComplexClipRegion::new(bounds.to_layout(), border_radii, ClipMode::Clip),
|
||||||
bounds.to_layout(),
|
|
||||||
border_radii.to_border_radius(),
|
|
||||||
ClipMode::Clip,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
LocalClip::Rect(bounds.to_layout())
|
LocalClip::Rect(bounds.to_layout())
|
||||||
|
@ -1325,7 +1364,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
),
|
),
|
||||||
blur_radius: box_shadow.base.blur.px(),
|
blur_radius: box_shadow.base.blur.px(),
|
||||||
spread_radius: box_shadow.spread.px(),
|
spread_radius: box_shadow.spread.px(),
|
||||||
border_radius: border_radius.to_border_radius(),
|
border_radius: border_radius,
|
||||||
clip_mode: if box_shadow.inset {
|
clip_mode: if box_shadow.inset {
|
||||||
BoxShadowClipMode::Inset
|
BoxShadowClipMode::Inset
|
||||||
} else {
|
} else {
|
||||||
|
@ -1420,7 +1459,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
color: style.resolve_color(colors.bottom).to_layout(),
|
color: style.resolve_color(colors.bottom).to_layout(),
|
||||||
style: border_style.bottom.to_layout(),
|
style: border_style.bottom.to_layout(),
|
||||||
},
|
},
|
||||||
radius: border_radius.to_border_radius(),
|
radius: border_radius,
|
||||||
})),
|
})),
|
||||||
Either::Second(Image::Gradient(ref gradient)) => {
|
Either::Second(Image::Gradient(ref gradient)) => {
|
||||||
Some(match gradient.kind {
|
Some(match gradient.kind {
|
||||||
|
@ -1653,27 +1692,19 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
let insertion_point_bounds;
|
let insertion_point_bounds;
|
||||||
let cursor;
|
let cursor;
|
||||||
if !self.style.writing_mode.is_vertical() {
|
if !self.style.writing_mode.is_vertical() {
|
||||||
insertion_point_bounds = Rect::new(
|
insertion_point_bounds = rect(
|
||||||
Point2D::new(
|
stacking_relative_border_box.origin.x + advance,
|
||||||
stacking_relative_border_box.origin.x + advance,
|
stacking_relative_border_box.origin.y,
|
||||||
stacking_relative_border_box.origin.y,
|
INSERTION_POINT_LOGICAL_WIDTH,
|
||||||
),
|
stacking_relative_border_box.size.height,
|
||||||
Size2D::new(
|
|
||||||
INSERTION_POINT_LOGICAL_WIDTH,
|
|
||||||
stacking_relative_border_box.size.height,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
cursor = CursorKind::Text;
|
cursor = CursorKind::Text;
|
||||||
} else {
|
} else {
|
||||||
insertion_point_bounds = Rect::new(
|
insertion_point_bounds = rect(
|
||||||
Point2D::new(
|
stacking_relative_border_box.origin.x,
|
||||||
stacking_relative_border_box.origin.x,
|
stacking_relative_border_box.origin.y + advance,
|
||||||
stacking_relative_border_box.origin.y + advance,
|
stacking_relative_border_box.size.width,
|
||||||
),
|
INSERTION_POINT_LOGICAL_WIDTH,
|
||||||
Size2D::new(
|
|
||||||
stacking_relative_border_box.size.width,
|
|
||||||
INSERTION_POINT_LOGICAL_WIDTH,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
cursor = CursorKind::VerticalText;
|
cursor = CursorKind::VerticalText;
|
||||||
};
|
};
|
||||||
|
@ -1842,12 +1873,12 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
// Adjust the clipping region as necessary to account for `border-radius`.
|
// Adjust the clipping region as necessary to account for `border-radius`.
|
||||||
let build_local_clip = |style: &ComputedValues| {
|
let build_local_clip = |style: &ComputedValues| {
|
||||||
let radii = build_border_radius_for_inner_rect(&stacking_relative_border_box, style);
|
let radii = build_border_radius_for_inner_rect(&stacking_relative_border_box, style);
|
||||||
if !radii.is_square() {
|
if !radii.is_zero() {
|
||||||
LocalClip::RoundedRect(
|
LocalClip::RoundedRect(
|
||||||
stacking_relative_border_box.to_layout(),
|
stacking_relative_border_box.to_layout(),
|
||||||
ComplexClipRegion::new(
|
ComplexClipRegion::new(
|
||||||
stacking_relative_content_box.to_layout(),
|
stacking_relative_content_box.to_layout(),
|
||||||
radii.to_border_radius(),
|
radii,
|
||||||
ClipMode::Clip,
|
ClipMode::Clip,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -1946,10 +1977,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
iframe: pipeline_id,
|
iframe: pipeline_id,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let size = Size2D::new(
|
let size = Size2D::new(item.bounds().size.width, item.bounds().size.height);
|
||||||
item.bounds().size.width.to_f32_px(),
|
|
||||||
item.bounds().size.height.to_f32_px(),
|
|
||||||
);
|
|
||||||
state
|
state
|
||||||
.iframe_sizes
|
.iframe_sizes
|
||||||
.push((browsing_context_id, TypedSize2D::from_untyped(&size)));
|
.push((browsing_context_id, TypedSize2D::from_untyped(&size)));
|
||||||
|
@ -2067,8 +2095,8 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
StackingContext::new(
|
StackingContext::new(
|
||||||
id,
|
id,
|
||||||
context_type,
|
context_type,
|
||||||
&border_box,
|
border_box.to_layout(),
|
||||||
&overflow,
|
overflow.to_layout(),
|
||||||
self.effective_z_index(),
|
self.effective_z_index(),
|
||||||
filters,
|
filters,
|
||||||
self.style().get_effects().mix_blend_mode.to_layout(),
|
self.style().get_effects().mix_blend_mode.to_layout(),
|
||||||
|
@ -2100,7 +2128,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Determine the orientation and cursor to use.
|
// Determine the orientation and cursor to use.
|
||||||
let (orientation, cursor) = if self.style.writing_mode.is_vertical() {
|
let (_orientation, cursor) = if self.style.writing_mode.is_vertical() {
|
||||||
// TODO: Distinguish between 'sideways-lr' and 'sideways-rl' writing modes in CSS
|
// TODO: Distinguish between 'sideways-lr' and 'sideways-rl' writing modes in CSS
|
||||||
// Writing Modes Level 4.
|
// Writing Modes Level 4.
|
||||||
(TextOrientation::SidewaysRight, CursorKind::VerticalText)
|
(TextOrientation::SidewaysRight, CursorKind::VerticalText)
|
||||||
|
@ -2181,14 +2209,22 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Text
|
// Text
|
||||||
state.add_display_item(DisplayItem::Text(Box::new(TextDisplayItem {
|
let glyphs = convert_text_run_to_glyphs(
|
||||||
base: base.clone(),
|
text_fragment.run.clone(),
|
||||||
text_run: text_fragment.run.clone(),
|
text_fragment.range,
|
||||||
range: text_fragment.range,
|
baseline_origin,
|
||||||
text_color: text_color.to_layout(),
|
);
|
||||||
orientation: orientation,
|
if !glyphs.is_empty() {
|
||||||
baseline_origin: baseline_origin,
|
state.add_display_item(DisplayItem::Text(Box::new(TextDisplayItem {
|
||||||
})));
|
base: base.clone(),
|
||||||
|
text_run: text_fragment.run.clone(),
|
||||||
|
range: text_fragment.range,
|
||||||
|
baseline_origin: baseline_origin.to_layout(),
|
||||||
|
glyphs: glyphs,
|
||||||
|
font_key: text_fragment.run.font_key,
|
||||||
|
text_color: text_color.to_layout(),
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(#17715): emit text-emphasis marks here.
|
// TODO(#17715): emit text-emphasis marks here.
|
||||||
// (just push another TextDisplayItem?)
|
// (just push another TextDisplayItem?)
|
||||||
|
@ -2435,25 +2471,20 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||||
Rect::max_rect()
|
Rect::max_rect()
|
||||||
},
|
},
|
||||||
Some(transform) => {
|
Some(transform) => {
|
||||||
let clip = Rect::new(
|
let clip = rect(
|
||||||
Point2D::new(
|
(clip.origin.x - origin.x).to_f32_px(),
|
||||||
(clip.origin.x - origin.x).to_f32_px(),
|
(clip.origin.y - origin.y).to_f32_px(),
|
||||||
(clip.origin.y - origin.y).to_f32_px(),
|
clip.size.width.to_f32_px(),
|
||||||
),
|
clip.size.height.to_f32_px(),
|
||||||
Size2D::new(clip.size.width.to_f32_px(), clip.size.height.to_f32_px()),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let clip = transform.transform_rect(&clip);
|
let clip = transform.transform_rect(&clip);
|
||||||
|
|
||||||
Rect::new(
|
rect(
|
||||||
Point2D::new(
|
Au::from_f32_px(clip.origin.x),
|
||||||
Au::from_f32_px(clip.origin.x),
|
Au::from_f32_px(clip.origin.y),
|
||||||
Au::from_f32_px(clip.origin.y),
|
Au::from_f32_px(clip.size.width),
|
||||||
),
|
Au::from_f32_px(clip.size.height),
|
||||||
Size2D::new(
|
|
||||||
Au::from_f32_px(clip.size.width),
|
|
||||||
Au::from_f32_px(clip.size.height),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
None => Rect::zero(),
|
None => Rect::zero(),
|
||||||
|
@ -2669,7 +2700,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||||
|
|
||||||
let new_clip_scroll_index = state.add_clip_scroll_node(ClipScrollNode {
|
let new_clip_scroll_index = state.add_clip_scroll_node(ClipScrollNode {
|
||||||
parent_index: self.clipping_and_scrolling().scrolling,
|
parent_index: self.clipping_and_scrolling().scrolling,
|
||||||
clip: ClippingRegion::from_rect(border_box),
|
clip: ClippingRegion::from_rect(border_box.to_layout()),
|
||||||
content_rect: LayoutRect::zero(),
|
content_rect: LayoutRect::zero(),
|
||||||
node_type: ClipScrollNodeType::StickyFrame(sticky_frame_data),
|
node_type: ClipScrollNodeType::StickyFrame(sticky_frame_data),
|
||||||
});
|
});
|
||||||
|
@ -2709,10 +2740,10 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||||
};
|
};
|
||||||
|
|
||||||
let clip_rect = build_inner_border_box_for_border_rect(&border_box, &self.fragment.style);
|
let clip_rect = build_inner_border_box_for_border_rect(&border_box, &self.fragment.style);
|
||||||
let mut clip = ClippingRegion::from_rect(&clip_rect);
|
let mut clip = ClippingRegion::from_rect(clip_rect.to_layout());
|
||||||
let radii = build_border_radius_for_inner_rect(&border_box, &self.fragment.style);
|
let radii = build_border_radius_for_inner_rect(&border_box, &self.fragment.style);
|
||||||
if !radii.is_square() {
|
if !radii.is_zero() {
|
||||||
clip.intersect_with_rounded_rect(&clip_rect, &radii)
|
clip.intersect_with_rounded_rect(clip_rect.to_layout(), radii)
|
||||||
}
|
}
|
||||||
|
|
||||||
let content_size = self.base.overflow.scroll.origin + self.base.overflow.scroll.size;
|
let content_size = self.base.overflow.scroll.origin + self.base.overflow.scroll.size;
|
||||||
|
@ -2776,7 +2807,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||||
|
|
||||||
let new_index = state.add_clip_scroll_node(ClipScrollNode {
|
let new_index = state.add_clip_scroll_node(ClipScrollNode {
|
||||||
parent_index: self.clipping_and_scrolling().scrolling,
|
parent_index: self.clipping_and_scrolling().scrolling,
|
||||||
clip: ClippingRegion::from_rect(&clip_rect),
|
clip: ClippingRegion::from_rect(clip_rect.to_layout()),
|
||||||
content_rect: LayoutRect::zero(), // content_rect isn't important for clips.
|
content_rect: LayoutRect::zero(), // content_rect isn't important for clips.
|
||||||
node_type: ClipScrollNodeType::Clip,
|
node_type: ClipScrollNodeType::Clip,
|
||||||
});
|
});
|
||||||
|
|
|
@ -7,14 +7,11 @@
|
||||||
// This might be achieved by sharing types between WR and Servo display lists, or
|
// This might be achieved by sharing types between WR and Servo display lists, or
|
||||||
// completely converting layout to directly generate WebRender display lists, for example.
|
// completely converting layout to directly generate WebRender display lists, for example.
|
||||||
|
|
||||||
use app_units::Au;
|
use gfx::display_list::{BorderDetails, ClipScrollNode};
|
||||||
use display_list::ToLayout;
|
use gfx::display_list::{ClipScrollNodeIndex, ClipScrollNodeType, DisplayItem};
|
||||||
use euclid::Point2D;
|
|
||||||
use gfx::display_list::{BorderDetails, BorderRadii, ClipScrollNode};
|
|
||||||
use gfx::display_list::{ClipScrollNodeIndex, ClipScrollNodeType, ClippingRegion, DisplayItem};
|
|
||||||
use gfx::display_list::{DisplayList, StackingContextType};
|
use gfx::display_list::{DisplayList, StackingContextType};
|
||||||
use msg::constellation_msg::PipelineId;
|
use msg::constellation_msg::PipelineId;
|
||||||
use webrender_api::{self, ClipAndScrollInfo, ClipId, ClipMode, ComplexClipRegion};
|
use webrender_api::{self, ClipAndScrollInfo, ClipId};
|
||||||
use webrender_api::{DisplayListBuilder, LayoutTransform};
|
use webrender_api::{DisplayListBuilder, LayoutTransform};
|
||||||
|
|
||||||
pub trait WebRenderDisplayListConverter {
|
pub trait WebRenderDisplayListConverter {
|
||||||
|
@ -32,26 +29,11 @@ trait WebRenderDisplayItemConverter {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ToBorderRadius {
|
|
||||||
fn to_border_radius(&self) -> webrender_api::BorderRadius;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToBorderRadius for BorderRadii<Au> {
|
|
||||||
fn to_border_radius(&self) -> webrender_api::BorderRadius {
|
|
||||||
webrender_api::BorderRadius {
|
|
||||||
top_left: self.top_left.to_layout(),
|
|
||||||
top_right: self.top_right.to_layout(),
|
|
||||||
bottom_left: self.bottom_left.to_layout(),
|
|
||||||
bottom_right: self.bottom_right.to_layout(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WebRenderDisplayListConverter for DisplayList {
|
impl WebRenderDisplayListConverter for DisplayList {
|
||||||
fn convert_to_webrender(&self, pipeline_id: PipelineId) -> DisplayListBuilder {
|
fn convert_to_webrender(&self, pipeline_id: PipelineId) -> DisplayListBuilder {
|
||||||
let mut builder = DisplayListBuilder::with_capacity(
|
let mut builder = DisplayListBuilder::with_capacity(
|
||||||
pipeline_id.to_webrender(),
|
pipeline_id.to_webrender(),
|
||||||
self.bounds().size.to_layout(),
|
self.bounds().size,
|
||||||
1024 * 1024,
|
1024 * 1024,
|
||||||
); // 1 MB of space
|
); // 1 MB of space
|
||||||
|
|
||||||
|
@ -81,7 +63,7 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
webrender_api::LayoutPrimitiveInfo {
|
webrender_api::LayoutPrimitiveInfo {
|
||||||
rect: self.base().bounds.to_layout(),
|
rect: self.base().bounds,
|
||||||
local_clip: self.base().local_clip,
|
local_clip: self.base().local_clip,
|
||||||
// TODO(gw): Make use of the WR backface visibility functionality.
|
// TODO(gw): Make use of the WR backface visibility functionality.
|
||||||
is_backface_visible: true,
|
is_backface_visible: true,
|
||||||
|
@ -121,42 +103,13 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
||||||
builder.push_rect(&self.prim_info(), item.color);
|
builder.push_rect(&self.prim_info(), item.color);
|
||||||
},
|
},
|
||||||
DisplayItem::Text(ref item) => {
|
DisplayItem::Text(ref item) => {
|
||||||
let mut origin = item.baseline_origin.clone();
|
builder.push_text(
|
||||||
let mut glyphs = vec![];
|
&self.prim_info(),
|
||||||
|
&item.glyphs,
|
||||||
for slice in item.text_run
|
item.font_key,
|
||||||
.natural_word_slices_in_visual_order(&item.range)
|
item.text_color,
|
||||||
{
|
None,
|
||||||
for glyph in slice.glyphs.iter_glyphs_for_byte_range(&slice.range) {
|
);
|
||||||
let glyph_advance = if glyph.char_is_space() {
|
|
||||||
glyph.advance() + item.text_run.extra_word_spacing
|
|
||||||
} else {
|
|
||||||
glyph.advance()
|
|
||||||
};
|
|
||||||
if !slice.glyphs.is_whitespace() {
|
|
||||||
let glyph_offset = glyph.offset().unwrap_or(Point2D::zero());
|
|
||||||
let x = (origin.x + glyph_offset.x).to_f32_px();
|
|
||||||
let y = (origin.y + glyph_offset.y).to_f32_px();
|
|
||||||
let point = webrender_api::LayoutPoint::new(x, y);
|
|
||||||
let glyph = webrender_api::GlyphInstance {
|
|
||||||
index: glyph.id(),
|
|
||||||
point: point,
|
|
||||||
};
|
|
||||||
glyphs.push(glyph);
|
|
||||||
}
|
|
||||||
origin.x = origin.x + glyph_advance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if glyphs.len() > 0 {
|
|
||||||
builder.push_text(
|
|
||||||
&self.prim_info(),
|
|
||||||
&glyphs,
|
|
||||||
item.text_run.font_key,
|
|
||||||
item.text_color,
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
DisplayItem::Image(ref item) => {
|
DisplayItem::Image(ref item) => {
|
||||||
if let Some(id) = item.webrender_image.key {
|
if let Some(id) = item.webrender_image.key {
|
||||||
|
@ -233,7 +186,7 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
||||||
builder.push_line(
|
builder.push_line(
|
||||||
&self.prim_info(),
|
&self.prim_info(),
|
||||||
// TODO(gw): Use a better estimate for wavy line thickness.
|
// TODO(gw): Use a better estimate for wavy line thickness.
|
||||||
(0.33 * item.base.bounds.size.height.to_f32_px()).ceil(),
|
(0.33 * item.base.bounds.size.height).ceil(),
|
||||||
webrender_api::LineOrientation::Horizontal,
|
webrender_api::LineOrientation::Horizontal,
|
||||||
&item.color,
|
&item.color,
|
||||||
item.style,
|
item.style,
|
||||||
|
@ -279,7 +232,7 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
||||||
.map(|perspective| LayoutTransform::from_untyped(&perspective));
|
.map(|perspective| LayoutTransform::from_untyped(&perspective));
|
||||||
|
|
||||||
builder.push_stacking_context(
|
builder.push_stacking_context(
|
||||||
&webrender_api::LayoutPrimitiveInfo::new(stacking_context.bounds.to_layout()),
|
&webrender_api::LayoutPrimitiveInfo::new(stacking_context.bounds),
|
||||||
stacking_context.scroll_policy,
|
stacking_context.scroll_policy,
|
||||||
transform,
|
transform,
|
||||||
stacking_context.transform_style,
|
stacking_context.transform_style,
|
||||||
|
@ -292,13 +245,13 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
||||||
DisplayItem::DefineClipScrollNode(ref item) => {
|
DisplayItem::DefineClipScrollNode(ref item) => {
|
||||||
let node = &clip_scroll_nodes[item.node_index.0];
|
let node = &clip_scroll_nodes[item.node_index.0];
|
||||||
let parent_id = get_id(clip_ids, node.parent_index);
|
let parent_id = get_id(clip_ids, node.parent_index);
|
||||||
let item_rect = node.clip.main.to_layout();
|
let item_rect = node.clip.main;
|
||||||
|
|
||||||
let webrender_id = match node.node_type {
|
let webrender_id = match node.node_type {
|
||||||
ClipScrollNodeType::Clip => builder.define_clip_with_parent(
|
ClipScrollNodeType::Clip => builder.define_clip_with_parent(
|
||||||
parent_id,
|
parent_id,
|
||||||
item_rect,
|
item_rect,
|
||||||
node.clip.get_complex_clips(),
|
node.clip.complex.clone(),
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
ClipScrollNodeType::ScrollFrame(scroll_sensitivity, external_id) => builder
|
ClipScrollNodeType::ScrollFrame(scroll_sensitivity, external_id) => builder
|
||||||
|
@ -306,8 +259,8 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
||||||
parent_id,
|
parent_id,
|
||||||
Some(external_id),
|
Some(external_id),
|
||||||
node.content_rect,
|
node.content_rect,
|
||||||
node.clip.main.to_layout(),
|
node.clip.main,
|
||||||
node.clip.get_complex_clips(),
|
node.clip.complex.clone(),
|
||||||
None,
|
None,
|
||||||
scroll_sensitivity,
|
scroll_sensitivity,
|
||||||
),
|
),
|
||||||
|
@ -331,22 +284,3 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait ToWebRenderClip {
|
|
||||||
fn get_complex_clips(&self) -> Vec<ComplexClipRegion>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToWebRenderClip for ClippingRegion {
|
|
||||||
fn get_complex_clips(&self) -> Vec<ComplexClipRegion> {
|
|
||||||
self.complex
|
|
||||||
.iter()
|
|
||||||
.map(|complex_clipping_region| {
|
|
||||||
ComplexClipRegion::new(
|
|
||||||
complex_clipping_region.rect.to_layout(),
|
|
||||||
complex_clipping_region.radii.to_border_radius(),
|
|
||||||
ClipMode::Clip,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -68,6 +68,7 @@ use layout::context::LayoutContext;
|
||||||
use layout::context::RegisteredPainter;
|
use layout::context::RegisteredPainter;
|
||||||
use layout::context::RegisteredPainters;
|
use layout::context::RegisteredPainters;
|
||||||
use layout::context::malloc_size_of_persistent_local_context;
|
use layout::context::malloc_size_of_persistent_local_context;
|
||||||
|
use layout::display_list::ToLayout;
|
||||||
use layout::display_list::WebRenderDisplayListConverter;
|
use layout::display_list::WebRenderDisplayListConverter;
|
||||||
use layout::flow::{Flow, GetBaseFlow, ImmutableFlowUtils, MutableOwnedFlowUtils};
|
use layout::flow::{Flow, GetBaseFlow, ImmutableFlowUtils, MutableOwnedFlowUtils};
|
||||||
use layout::flow_ref::FlowRef;
|
use layout::flow_ref::FlowRef;
|
||||||
|
@ -986,7 +987,7 @@ impl LayoutThread {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let origin = Rect::new(Point2D::new(Au(0), Au(0)), root_size);
|
let origin = Rect::new(Point2D::new(Au(0), Au(0)), root_size).to_layout();
|
||||||
build_state.root_stacking_context.bounds = origin;
|
build_state.root_stacking_context.bounds = origin;
|
||||||
build_state.root_stacking_context.overflow = origin;
|
build_state.root_stacking_context.overflow = origin;
|
||||||
|
|
||||||
|
@ -1364,7 +1365,7 @@ impl LayoutThread {
|
||||||
rw_data.display_list
|
rw_data.display_list
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.expect("Tried to hit test with no display list")
|
.expect("Tried to hit test with no display list")
|
||||||
.text_index(opaque_node, &point_in_node)
|
.text_index(opaque_node, point_in_node.to_layout())
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
ReflowGoal::NodeGeometryQuery(node) => {
|
ReflowGoal::NodeGeometryQuery(node) => {
|
||||||
|
|
|
@ -825,14 +825,20 @@ malloc_size_of_is_0!(webrender_api::ClipAndScrollInfo);
|
||||||
#[cfg(feature = "webrender_api")]
|
#[cfg(feature = "webrender_api")]
|
||||||
malloc_size_of_is_0!(webrender_api::ColorF);
|
malloc_size_of_is_0!(webrender_api::ColorF);
|
||||||
#[cfg(feature = "webrender_api")]
|
#[cfg(feature = "webrender_api")]
|
||||||
|
malloc_size_of_is_0!(webrender_api::ComplexClipRegion);
|
||||||
|
#[cfg(feature = "webrender_api")]
|
||||||
malloc_size_of_is_0!(webrender_api::ExtendMode);
|
malloc_size_of_is_0!(webrender_api::ExtendMode);
|
||||||
#[cfg(feature = "webrender_api")]
|
#[cfg(feature = "webrender_api")]
|
||||||
malloc_size_of_is_0!(webrender_api::FilterOp);
|
malloc_size_of_is_0!(webrender_api::FilterOp);
|
||||||
#[cfg(feature = "webrender_api")]
|
#[cfg(feature = "webrender_api")]
|
||||||
malloc_size_of_is_0!(webrender_api::ExternalScrollId);
|
malloc_size_of_is_0!(webrender_api::ExternalScrollId);
|
||||||
#[cfg(feature = "webrender_api")]
|
#[cfg(feature = "webrender_api")]
|
||||||
|
malloc_size_of_is_0!(webrender_api::FontInstanceKey);
|
||||||
|
#[cfg(feature = "webrender_api")]
|
||||||
malloc_size_of_is_0!(webrender_api::GradientStop);
|
malloc_size_of_is_0!(webrender_api::GradientStop);
|
||||||
#[cfg(feature = "webrender_api")]
|
#[cfg(feature = "webrender_api")]
|
||||||
|
malloc_size_of_is_0!(webrender_api::GlyphInstance);
|
||||||
|
#[cfg(feature = "webrender_api")]
|
||||||
malloc_size_of_is_0!(webrender_api::ImageBorder);
|
malloc_size_of_is_0!(webrender_api::ImageBorder);
|
||||||
#[cfg(feature = "webrender_api")]
|
#[cfg(feature = "webrender_api")]
|
||||||
malloc_size_of_is_0!(webrender_api::ImageKey);
|
malloc_size_of_is_0!(webrender_api::ImageKey);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue