Backed out 7 changesets (bug 1675375) for causing mochitest plain failures in test_group_hittest-2.html

CLOSED TREE

Backed out changeset e2e27cedd002 (bug 1675375)
Backed out changeset dba2861e4b53 (bug 1675375)
Backed out changeset 5dbfc7ce0a85 (bug 1675375)
Backed out changeset dd08dfba1dcd (bug 1675375)
Backed out changeset 5f8ae081f4ee (bug 1675375)
Backed out changeset 4d13e1221a79 (bug 1675375)
Backed out changeset 0e463f7857ea (bug 1675375)
This commit is contained in:
Alexandru Michis 2021-04-14 07:29:47 +03:00
Родитель 2a8e178211
Коммит c592078f73
22 изменённых файлов: 46 добавлений и 529 удалений

Просмотреть файл

@ -63,14 +63,9 @@ add_task(async function test_main() {
{ file: "helper_fission_large_subframe.html" },
// add additional tests here
];
// These tests are to ensure hit-testing works perfectly on the WR
// codepath. The layers codepath may need a main-thread fallback to get
// these working, but we can't use our synchronous hitTest(...) helpers
// for those anyway.
if (isWebRender) {
subtests = subtests.concat([
{ file: "helper_fission_inactivescroller_positionedcontent.html" },
{ file: "helper_fission_irregular_areas.html" },
// add WebRender-specific tests here
]);
} else {

Просмотреть файл

@ -1,101 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Ensure irregular areas on top of OOPIFs hit-test properly</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script src="/tests/SimpleTest/paint_listener.js"></script>
<script src="helper_fission_utils.js"></script>
<script src="apz_test_utils.js"></script>
<script src="apz_test_native_event_utils.js"></script>
<script>
fission_subtest_init();
FissionTestHelper.startTestPromise
.then(waitUntilApzStable)
.then(loadOOPIFrame("testframe", "helper_fission_empty.html"))
.then(waitUntilApzStable)
.then(test)
.then(FissionTestHelper.subtestDone, FissionTestHelper.subtestFailed);
let make_oopif_scrollable = function() {
// ensure the oopif is scrollable, and wait for the paint so that the
// compositor also knows it's scrollable.
document.body.style.height = "200vh";
promiseApzFlushedRepaints().then(() => {
let utils = SpecialPowers.getDOMWindowUtils(window);
let result = {
layersId: utils.getLayersId(),
viewId: utils.getViewId(document.scrollingElement)
};
dump(`OOPIF computed IDs ${JSON.stringify(result)}\n`);
FissionTestHelper.fireEventInEmbedder("OOPIF:Scrollable", result);
});
return true;
};
async function test() {
let iframe = document.getElementById("testframe");
let oopifScrollerIds = promiseOneEvent(window, "OOPIF:Scrollable", null);
ok(await FissionTestHelper.sendToOopif(iframe, `(${make_oopif_scrollable})()`),
"Ran code to make OOPIF scrollable");
oopifScrollerIds = (await oopifScrollerIds).data;
let utils = SpecialPowers.getDOMWindowUtils(window);
// The triangle_overlay div overlays a part of the iframe. We do 3 hit-tests:
// - one that hits the opaque part of the overlay
// - one that hits the clipped-away part of the overlay div but is still
// inside the bounding box
// - one that is not on the overlay at all, but on the part of the iframe not
// covered by the overlay.
// For the latter two, we expect the hit-test to hit the OOPIF.
checkHitResult(await fissionHitTest({x: 20, y: 100}, iframe),
APZHitResultFlags.VISIBLE | APZHitResultFlags.IRREGULAR_AREA,
utils.getViewId(document.scrollingElement),
utils.getLayersId(),
"opaque part of overlay should hit parent doc hosting the OOPIF");
checkHitResult(await fissionHitTest({x: 180, y: 100}, iframe),
APZHitResultFlags.VISIBLE,
oopifScrollerIds.viewId,
oopifScrollerIds.layersId,
"clipped-away part of overlay should hit OOPIF");
checkHitResult(await fissionHitTest({x: 250, y: 100}, iframe),
APZHitResultFlags.VISIBLE,
oopifScrollerIds.viewId,
oopifScrollerIds.layersId,
"part of OOPIF outside the overlay bounding rect should hit the OOPIF");
}
</script>
</head>
<body>
<style>
html, body {
margin: 0;
}
iframe {
position: absolute;
width: 300px;
height: 200px;
}
#triangle_overlay {
position: absolute;
top: 0;
left: 0;
width: 200px;
height: 200px;
background-color: green;
clip-path: polygon(0% 0%, 100% 100%, 0% 100%);
}
</style>
<iframe id="testframe"></iframe>
<div id="triangle_overlay"></div>
</body>
</html>

Просмотреть файл

@ -97,13 +97,13 @@ async function test() {
layersId,
"(complex) point in the iframe behind overlaying div, but outside the bounding box of the clip path");
checkHitResult(hitTest({ x: 160, y: 160 }),
APZHitResultFlags.VISIBLE,
iframeViewId,
APZHitResultFlags.VISIBLE | APZHitResultFlags.IRREGULAR_AREA,
rootViewId,
layersId,
"(complex) point in the iframe behind overlaying div, inside the bounding box of the clip path, but outside the actual clip shape");
checkHitResult(hitTest({ x: 300, y: 200 }),
APZHitResultFlags.VISIBLE,
iframeViewId,
APZHitResultFlags.VISIBLE | APZHitResultFlags.IRREGULAR_AREA,
rootViewId,
layersId,
"(complex) point inside the clip shape of the overlaying div");
}

Просмотреть файл

@ -21,7 +21,7 @@
<body>
<script type="application/javascript">
var SPAM_LIMIT = 200; // bigger numbers make the test run longer
var SPAM_LIMIT = 1000; // bigger numbers make the test run longer
// This function adds and removes a scrollable div very rapidly (via
// setTimeout(0) self-scheduling). This causes very frequent layer

Просмотреть файл

@ -86,7 +86,7 @@
toolkit == 'cocoa' # synthesized wheel smooth-scrolling not supported on OS X
xorigin # JavaScript error: http://mochi.test:8888/tests/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js, line 10: Error: Permission denied to access property "getResolution"
[test_wheel_scroll.html]
skip-if =
skip-if =
os == 'android' # wheel events not supported on mobile
xorigin # Hangs
[test_wheel_transactions.html]
@ -97,11 +97,7 @@
skip-if =
toolkit == 'android' # wheel events not supported on mobile
xorigin # Hangs
[test_group_hittest-1.html]
skip-if =
toolkit == 'android' # mouse events not supported on mobile
xorigin # Hangs
[test_group_hittest-2.html]
[test_group_hittest.html]
skip-if =
toolkit == 'android' # mouse events not supported on mobile
xorigin # Hangs

Просмотреть файл

@ -1,59 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Various hit-testing tests that spawn in new windows - Part 1</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="apz_test_utils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript">
var prefs = [
// Turn off displayport expiry so that we don't miss failures where the
// displayport is set and then expires before we get around to doing the
// hit-test inside the activated scrollframe.
["apz.displayport_expiry_ms", 0],
// Always layerize the scrollbar track, so as to get consistent results
// across platforms. Eventually we should probably get rid of this and make
// the tests more robust in terms of testing all the different cross-platform
// variations.
["layout.scrollbars.always-layerize-track", true],
// We need this pref to allow the synthetic mouse events to propagate to APZ,
// and to allow the MozMouseHittest event in particular to be dispatched to
// APZ as a MouseInput so the hit result is recorded.
["test.events.async.enabled", true],
// Turns on APZTestData logging which we use to obtain the hit test results.
["apz.test.logging_enabled", true],
];
var overscroll_prefs = [...prefs,
["apz.overscroll.enabled", true],
["apz.overscroll.test_async_scroll_offset.enabled", true],
];
var subtests = [
{"file": "helper_hittest_basic.html", "prefs": prefs},
{"file": "helper_hittest_fixed_in_scrolled_transform.html", "prefs": prefs},
{"file": "helper_hittest_float_bug1434846.html", "prefs": prefs},
{"file": "helper_hittest_float_bug1443518.html", "prefs": prefs},
{"file": "helper_hittest_checkerboard.html", "prefs": prefs},
{"file": "helper_hittest_backface_hidden.html", "prefs": prefs},
{"file": "helper_hittest_touchaction.html", "prefs": prefs},
{"file": "helper_hittest_nested_transforms_bug1459696.html", "prefs": prefs},
{"file": "helper_hittest_sticky_bug1478304.html", "prefs": prefs},
{"file": "helper_hittest_clipped_fixed_modal.html", "prefs": prefs},
];
if (isApzEnabled()) {
SimpleTest.waitForExplicitFinish();
window.onload = function() {
runSubtestsSeriallyInFreshWindows(subtests)
.then(SimpleTest.finish, SimpleTest.finishWithFailure);
};
}
</script>
</head>
<body>
</body>
</html>

Просмотреть файл

@ -2,7 +2,7 @@
<html>
<head>
<meta charset="utf-8">
<title>Various hit-testing tests that spawn in new windows - Part 2</title>
<title>Various hit-testing tests that spawn in new windows</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="apz_test_utils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
@ -32,14 +32,23 @@ var overscroll_prefs = [...prefs,
];
var subtests = [
{"file": "helper_hittest_basic.html", "prefs": prefs},
{"file": "helper_hittest_fixed_in_scrolled_transform.html", "prefs": prefs},
{"file": "helper_hittest_float_bug1434846.html", "prefs": prefs},
{"file": "helper_hittest_float_bug1443518.html", "prefs": prefs},
{"file": "helper_hittest_checkerboard.html", "prefs": prefs},
{"file": "helper_hittest_backface_hidden.html", "prefs": prefs},
{"file": "helper_hittest_touchaction.html", "prefs": prefs},
{"file": "helper_hittest_nested_transforms_bug1459696.html", "prefs": prefs},
{"file": "helper_hittest_sticky_bug1478304.html", "prefs": prefs},
{"file": "helper_hittest_clipped_fixed_modal.html", "prefs": prefs},
{"file": "helper_hittest_pointerevents_svg.html", "prefs": prefs},
{"file": "helper_hittest_clippath.html", "prefs": prefs},
{"file": "helper_hittest_hoisted_scrollinfo.html", "prefs": prefs},
{"file": "helper_hittest_spam.html", "prefs": prefs},
{"file": "helper_hittest_hidden_inactive_scrollframe.html", "prefs": prefs},
{"file": "helper_hittest_overscroll.html", "prefs": overscroll_prefs},
{"file": "helper_hittest_overscroll_subframe.html", "prefs": overscroll_prefs},
// This test should be at the end, because it's prone to timeout.
{"file": "helper_hittest_spam.html", "prefs": prefs},
];
function addConditionalTests(tests) {
@ -49,11 +58,9 @@ function addConditionalTests(tests) {
var utils = SpecialPowers.getDOMWindowUtils(window);
var isWebRender = utils.layerManagerType.startsWith("WebRender");
if (isWebRender) {
// Add new tests at the beginning, to ensure the final test remains in
// the final position.
tests = [
tests = tests.concat([
{"file": "helper_hittest_deep_scene_stack.html", "prefs": prefs},
].concat(tests);
]);
}
return tests;
}

Просмотреть файл

@ -1072,13 +1072,11 @@ wr::WrClipId DisplayListBuilder::DefineClip(
}
wr::WrClipId DisplayListBuilder::DefineImageMaskClip(
const wr::ImageMask& aMask, const nsTArray<wr::LayoutPoint>& aPoints,
wr::FillRule aFillRule) {
const wr::ImageMask& aMask) {
CancelGroup();
WrClipId clipId = wr_dp_define_image_mask_clip_with_parent_clip_chain(
mWrState, &mCurrentSpaceAndClipChain, aMask, aPoints.Elements(),
aPoints.Length(), aFillRule);
mWrState, &mCurrentSpaceAndClipChain, aMask);
return clipId;
}

Просмотреть файл

@ -460,9 +460,7 @@ class DisplayListBuilder final {
const Maybe<wr::WrSpaceAndClip>& aParent, const wr::LayoutRect& aClipRect,
const nsTArray<wr::ComplexClipRegion>* aComplex = nullptr);
wr::WrClipId DefineImageMaskClip(const wr::ImageMask& aMask,
const nsTArray<wr::LayoutPoint>&,
wr::FillRule);
wr::WrClipId DefineImageMaskClip(const wr::ImageMask& aMask);
wr::WrClipId DefineRoundedRectClip(const wr::ComplexClipRegion& aComplex);
wr::WrClipId DefineRectClip(wr::LayoutRect aClipRect);

Просмотреть файл

@ -16,11 +16,9 @@ namespaces = ["mozilla", "wr"]
[export]
item_types = ["globals", "enums", "structs", "unions", "typedefs", "opaque", "functions", "constants"]
include = ["POLYGON_CLIP_VERTEX_MAX"]
[parse]
parse_deps = true
extra_bindings = ["webrender_api"]
include = ["log", "euclid", "webrender", "webrender_api"]
[fn]

Просмотреть файл

@ -2554,7 +2554,7 @@ pub extern "C" fn wr_dp_push_stacking_context(
let reference_frame_kind = match params.reference_frame_kind {
WrReferenceFrameKind::Transform => ReferenceFrameKind::Transform {
is_2d_scale_translation,
should_snap,
should_snap
},
WrReferenceFrameKind::Perspective => ReferenceFrameKind::Perspective { scrolling_relative_to },
};
@ -2685,21 +2685,13 @@ pub extern "C" fn wr_dp_define_image_mask_clip_with_parent_clip_chain(
state: &mut WrState,
parent: &WrSpaceAndClipChain,
mask: ImageMask,
points: *const LayoutPoint,
point_count: usize,
fill_rule: FillRule,
) -> WrClipId {
debug_assert!(unsafe { is_in_main_thread() });
let c_points = unsafe { make_slice(points, point_count) };
let points: Vec<LayoutPoint> = c_points.iter().copied().collect();
let clip_id = state.frame_builder.dl_builder.define_clip_image_mask(
&parent.to_webrender(state.pipeline_id),
mask,
&points,
fill_rule,
);
let clip_id = state
.frame_builder
.dl_builder
.define_clip_image_mask(&parent.to_webrender(state.pipeline_id), mask);
WrClipId::from_webrender(clip_id)
}

Просмотреть файл

@ -221,8 +221,6 @@ impl Example for App {
let mask_clip_id = builder.define_clip_image_mask(
&root_space_and_clip,
mask,
&vec![],
FillRule::Nonzero,
);
let clip_id = builder.define_clip_rounded_rect(
&SpaceAndClipInfo {

Просмотреть файл

@ -93,7 +93,7 @@
//!
use api::{BorderRadius, ClipMode, ComplexClipRegion, ImageMask};
use api::{BoxShadowClipMode, ClipId, FillRule, ImageKey, ImageRendering, PipelineId};
use api::{BoxShadowClipMode, ClipId, ImageKey, ImageRendering, PipelineId};
use api::units::*;
use crate::image_tiling::{self, Repetition};
use crate::border::{ensure_no_corner_overlap, BorderRadiusAu};
@ -105,7 +105,7 @@ use crate::gpu_types::{BoxShadowStretchMode};
use crate::intern::{self, ItemUid};
use crate::internal_types::{FastHashMap, FastHashSet};
use crate::prim_store::{VisibleMaskImageTile};
use crate::prim_store::{PointKey, SizeKey, RectangleKey, PolygonKey};
use crate::prim_store::{PointKey, SizeKey, RectangleKey};
use crate::render_task_cache::to_cache_size;
use crate::resource_cache::{ImageRequest, ResourceCache};
use crate::space::SpaceMapper;
@ -398,12 +398,11 @@ impl From<ClipItemKey> for ClipNode {
mode,
}
}
ClipItemKeyKind::ImageMask(rect, image, repeat, polygon) => {
ClipItemKeyKind::ImageMask(rect, image, repeat) => {
ClipItemKind::Image {
image,
rect: rect.into(),
repeat,
polygon,
}
}
ClipItemKeyKind::BoxShadow(shadow_rect_fract_offset, shadow_rect_size, shadow_radius, prim_shadow_rect, blur_radius, clip_mode) => {
@ -610,7 +609,7 @@ impl ClipNodeInfo {
let mut visible_tiles = None;
if let ClipItemKind::Image { rect, image, repeat, .. } = node.item.kind {
if let ClipItemKind::Image { rect, image, repeat } = node.item.kind {
let request = ImageRequest {
key: image,
rendering: ImageRendering::Auto,
@ -1379,7 +1378,7 @@ impl ClipRegion<Option<ComplexClipRegion>> {
pub enum ClipItemKeyKind {
Rectangle(RectangleKey, ClipMode),
RoundedRectangle(RectangleKey, BorderRadiusAu, ClipMode),
ImageMask(RectangleKey, ImageKey, bool, PolygonKey),
ImageMask(RectangleKey, ImageKey, bool),
BoxShadow(PointKey, SizeKey, BorderRadiusAu, RectangleKey, Au, BoxShadowClipMode),
}
@ -1401,13 +1400,11 @@ impl ClipItemKeyKind {
}
}
pub fn image_mask(image_mask: &ImageMask, mask_rect: LayoutRect,
points: Vec<LayoutPoint>, fill_rule: FillRule) -> Self {
pub fn image_mask(image_mask: &ImageMask, mask_rect: LayoutRect) -> Self {
ClipItemKeyKind::ImageMask(
mask_rect.into(),
image_mask.image,
image_mask.repeat,
PolygonKey::new(&points, fill_rule)
)
}
@ -1489,7 +1486,6 @@ pub enum ClipItemKind {
image: ImageKey,
rect: LayoutRect,
repeat: bool,
polygon: PolygonKey,
},
BoxShadow {
source: BoxShadowClipSource,
@ -1940,64 +1936,6 @@ fn rounded_rectangle_contains_rect_quick(
true
}
/// Test where point p is relative to the infinite line that passes through the segment
/// defined by p0 and p1. Point p is on the "left" of the line if the triangle (p0, p1, p)
/// forms a counter-clockwise triangle.
/// > 0 is left of the line
/// < 0 is right of the line
/// == 0 is on the line
pub fn is_left_of_line(
p_x: f32,
p_y: f32,
p0_x: f32,
p0_y: f32,
p1_x: f32,
p1_y: f32,
) -> f32 {
(p1_x - p0_x) * (p_y - p0_y) - (p_x - p0_x) * (p1_y - p0_y)
}
pub fn polygon_contains_point(
point: &LayoutPoint,
rect: &LayoutRect,
polygon: &PolygonKey,
) -> bool {
if !rect.contains(*point) {
return false;
}
// p is a LayoutPoint that we'll be comparing to dimensionless PointKeys,
// which were created from LayoutPoints, so it all works out.
let p = LayoutPoint::new(point.x - rect.origin.x, point.y - rect.origin.y);
// Calculate a winding number for this point.
let mut winding_number: i32 = 0;
let count = polygon.point_count as usize;
for i in 0..count {
let p0 = polygon.points[i];
let p1 = polygon.points[(i + 1) % count];
if p0.y <= p.y {
if p1.y > p.y {
if is_left_of_line(p.x, p.y, p0.x, p0.y, p1.x, p1.y) > 0.0 {
winding_number = winding_number + 1;
}
}
} else if p1.y <= p.y {
if is_left_of_line(p.x, p.y, p0.x, p0.y, p1.x, p1.y) < 0.0 {
winding_number = winding_number - 1;
}
}
}
match polygon.fill_rule {
FillRule::Nonzero => winding_number != 0,
FillRule::Evenodd => winding_number.abs() % 2 == 1,
}
}
pub fn projected_rect_contains(
source_rect: &LayoutRect,
transform: &LayoutToWorldTransform,

Просмотреть файл

@ -6,8 +6,6 @@ use api::{BorderRadius, ClipMode, HitTestItem, HitTestResult, ItemTag, Primitive
use api::{PipelineId, ApiHitTester, ClipId};
use api::units::*;
use crate::clip::{ClipItemKind, ClipStore, ClipNode, rounded_rectangle_contains_point};
use crate::clip::{polygon_contains_point};
use crate::prim_store::PolygonKey;
use crate::spatial_tree::{SpatialNodeIndex, SpatialTree};
use crate::internal_types::{FastHashMap, LayoutPrimitiveInfo};
use std::ops;
@ -88,12 +86,8 @@ impl HitTestClipNode {
ClipItemKind::RoundedRectangle { rect, radius, mode } => {
HitTestRegion::RoundedRectangle(rect, radius, mode)
}
ClipItemKind::Image { rect, polygon, .. } => {
if polygon.point_count > 0 {
HitTestRegion::Polygon(rect, polygon)
} else {
HitTestRegion::Rectangle(rect, ClipMode::Clip)
}
ClipItemKind::Image { rect, .. } => {
HitTestRegion::Rectangle(rect, ClipMode::Clip)
}
ClipItemKind::BoxShadow { .. } => HitTestRegion::Invalid,
};
@ -279,7 +273,6 @@ enum HitTestRegion {
Invalid,
Rectangle(LayoutRect, ClipMode),
RoundedRectangle(LayoutRect, BorderRadius, ClipMode),
Polygon(LayoutRect, PolygonKey),
}
impl HitTestRegion {
@ -293,8 +286,6 @@ impl HitTestRegion {
rounded_rectangle_contains_point(point, &rect, &radii),
HitTestRegion::RoundedRectangle(rect, radii, ClipMode::ClipOut) =>
!rounded_rectangle_contains_point(point, &rect, &radii),
HitTestRegion::Polygon(rect, polygon) =>
polygon_contains_point(point, &rect, &polygon),
HitTestRegion::Invalid => true,
}
}

Просмотреть файл

@ -268,9 +268,6 @@ pub struct TileCoordinate;
// Geometry types for tile coordinates.
pub type TileOffset = Point2D<i32, TileCoordinate>;
// TileSize type is also used in used in lib.rs and cbindgen picks the wrong one when
// generating headers.
/// cbindgen:ignore
pub type TileSize = Size2D<i32, TileCoordinate>;
pub type TileRect = Rect<i32, TileCoordinate>;
@ -6307,7 +6304,7 @@ impl PicturePrimitive {
}
// Map the cluster bounding rect into the space of the surface, and
// include it in the surface bounding rect.
// include it in the surface bounding rect.
surface.map_local_to_surface.set_target_spatial_node(
cluster.spatial_node_index,
frame_context.spatial_tree,

Просмотреть файл

@ -5,7 +5,7 @@
use api::{BorderRadius, ClipMode, ColorF, ColorU, RasterSpace};
use api::{ImageRendering, RepeatMode, PrimitiveFlags};
use api::{PremultipliedColorF, PropertyBinding, Shadow};
use api::{PrimitiveKeyKind, FillRule, POLYGON_CLIP_VERTEX_MAX};
use api::{PrimitiveKeyKind};
use api::units::*;
use euclid::{SideOffsets2D, Size2D};
use malloc_size_of::MallocSizeOf;
@ -210,46 +210,6 @@ impl From<WorldRect> for RectangleKey {
}
}
/// To create a fixed-size representation of a polygon, we use a fixed
/// number of points. Our initialization method restricts us to values
/// <= 32. If our constant POLYGON_CLIP_VERTEX_MAX is > 32, the Rust
/// compiler will complain.
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Copy, Debug, Clone, Hash, MallocSizeOf, PartialEq)]
pub struct PolygonKey {
pub point_count: u8,
pub points: [PointKey; POLYGON_CLIP_VERTEX_MAX],
pub fill_rule: FillRule,
}
impl PolygonKey {
pub fn new(
points_layout: &Vec<LayoutPoint>,
fill_rule: FillRule,
) -> Self {
// We have to fill fixed-size arrays with data from a Vec.
// We'll do this by initializing the arrays to known-good
// values then overwriting those values as long as our
// iterator provides values.
let mut points: [PointKey; POLYGON_CLIP_VERTEX_MAX] = [PointKey { x: 0.0, y: 0.0}; POLYGON_CLIP_VERTEX_MAX];
let mut point_count: u8 = 0;
for (src, dest) in points_layout.iter().zip(points.iter_mut()) {
*dest = (*src as LayoutPoint).into();
point_count = point_count + 1;
}
PolygonKey {
point_count,
points,
fill_rule,
}
}
}
impl Eq for PolygonKey {}
/// A hashable SideOffset2D that can be used in primitive keys.
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]

Просмотреть файл

@ -44,7 +44,7 @@ use api::{LineOrientation, LineStyle, NinePatchBorderSource, PipelineId, MixBlen
use api::{PropertyBinding, ReferenceFrameKind, ScrollFrameDisplayItem, ScrollSensitivity};
use api::{Shadow, SpaceAndClipInfo, SpatialId, StickyFrameDisplayItem, ImageMask, ItemTag};
use api::{ClipMode, PrimitiveKeyKind, TransformStyle, YuvColorSpace, ColorRange, YuvData, TempFilterData};
use api::{ReferenceTransformBinding, Rotation, FillRule};
use api::{ReferenceTransformBinding, Rotation};
use api::units::*;
use crate::image_tiling::simplify_repeated_primitive;
use crate::clip::{ClipChainId, ClipRegion, ClipItemKey, ClipStore, ClipItemKeyKind};
@ -1387,8 +1387,6 @@ impl<'a> SceneBuilder<'a> {
info.id,
&info.parent_space_and_clip,
&image_mask,
info.fill_rule,
item.points(),
);
}
DisplayItem::RoundedRectClip(ref info) => {
@ -1491,8 +1489,7 @@ impl<'a> SceneBuilder<'a> {
DisplayItem::SetGradientStops |
DisplayItem::SetFilterOps |
DisplayItem::SetFilterData |
DisplayItem::SetFilterPrimitives |
DisplayItem::SetPoints => {}
DisplayItem::SetFilterPrimitives => {}
// Special items that are handled in the parent method
DisplayItem::PushStackingContext(..) |
@ -2328,8 +2325,6 @@ impl<'a> SceneBuilder<'a> {
new_node_id: ClipId,
space_and_clip: &SpaceAndClipInfo,
image_mask: &ImageMask,
fill_rule: FillRule,
points_range: ItemRange<LayoutPoint>,
) {
let spatial_node_index = self.id_to_index_mapper.get_spatial_node_index(space_and_clip.spatial_id);
@ -2337,9 +2332,8 @@ impl<'a> SceneBuilder<'a> {
&image_mask.rect,
spatial_node_index,
);
let points = points_range.iter().collect();
let item = ClipItemKey {
kind: ClipItemKeyKind::image_mask(image_mask, snapped_mask_rect, points, fill_rule),
kind: ClipItemKeyKind::image_mask(image_mask, snapped_mask_rect),
};
let handle = self

Просмотреть файл

@ -499,7 +499,7 @@ impl<Src, Dst> MatrixHelpers<Src, Dst> for Transform3D<f32, Src, Dst> {
* a b 0 1
*/
fn is_2d_scale_translation(&self) -> bool {
(self.m33 - 1.0).abs() < NEARLY_ZERO &&
(self.m33 - 1.0).abs() < NEARLY_ZERO &&
(self.m44 - 1.0).abs() < NEARLY_ZERO &&
self.m12.abs() < NEARLY_ZERO && self.m13.abs() < NEARLY_ZERO && self.m14.abs() < NEARLY_ZERO &&
self.m21.abs() < NEARLY_ZERO && self.m23.abs() < NEARLY_ZERO && self.m24.abs() < NEARLY_ZERO &&
@ -667,9 +667,6 @@ pub mod test {
use euclid::default::{Point2D, Rect, Size2D, Transform3D};
use euclid::{Angle, approxeq::ApproxEq};
use std::f32::consts::PI;
use crate::clip::{is_left_of_line, polygon_contains_point};
use crate::prim_store::PolygonKey;
use api::FillRule;
#[test]
fn inverse_project() {
@ -841,84 +838,6 @@ pub mod test {
assert_eq!(origin, Point2D::new(1.0, 0.5));
assert_eq!(m.transform_point2d(origin), Some(Point2D::zero()));
}
#[test]
fn polygon_clip_is_left_of_point() {
// Define points of a line through (1, -3) and (-2, 6) to test against.
// If the triplet consisting of these two points and the test point
// form a counter-clockwise triangle, then the test point is on the
// left. The easiest way to visualize this is with an "ascending"
// line from low-Y to high-Y.
let p0_x = 1.0;
let p0_y = -3.0;
let p1_x = -2.0;
let p1_y = 6.0;
// Test some points to the left of the line.
assert!(is_left_of_line(-9.0, 0.0, p0_x, p0_y, p1_x, p1_y) > 0.0);
assert!(is_left_of_line(-1.0, 1.0, p0_x, p0_y, p1_x, p1_y) > 0.0);
assert!(is_left_of_line(1.0, -4.0, p0_x, p0_y, p1_x, p1_y) > 0.0);
// Test some points on the line.
assert!(is_left_of_line(-3.0, 9.0, p0_x, p0_y, p1_x, p1_y) == 0.0);
assert!(is_left_of_line(0.0, 0.0, p0_x, p0_y, p1_x, p1_y) == 0.0);
assert!(is_left_of_line(100.0, -300.0, p0_x, p0_y, p1_x, p1_y) == 0.0);
// Test some points to the right of the line.
assert!(is_left_of_line(0.0, 1.0, p0_x, p0_y, p1_x, p1_y) < 0.0);
assert!(is_left_of_line(-4.0, 13.0, p0_x, p0_y, p1_x, p1_y) < 0.0);
assert!(is_left_of_line(5.0, -12.0, p0_x, p0_y, p1_x, p1_y) < 0.0);
}
#[test]
fn polygon_clip_contains_point() {
// We define the points of a self-overlapping polygon, which we will
// use to create polygons with different windings and fill rules.
let p0 = LayoutPoint::new(4.0, 4.0);
let p1 = LayoutPoint::new(6.0, 4.0);
let p2 = LayoutPoint::new(4.0, 7.0);
let p3 = LayoutPoint::new(2.0, 1.0);
let p4 = LayoutPoint::new(8.0, 1.0);
let p5 = LayoutPoint::new(6.0, 7.0);
let poly_clockwise_nonzero = PolygonKey::new(
&[p5, p4, p3, p2, p1, p0].to_vec(), FillRule::Nonzero
);
let poly_clockwise_evenodd = PolygonKey::new(
&[p5, p4, p3, p2, p1, p0].to_vec(), FillRule::Evenodd
);
let poly_counter_clockwise_nonzero = PolygonKey::new(
&[p0, p1, p2, p3, p4, p5].to_vec(), FillRule::Nonzero
);
let poly_counter_clockwise_evenodd = PolygonKey::new(
&[p0, p1, p2, p3, p4, p5].to_vec(), FillRule::Evenodd
);
// We define a rect that provides a bounding clip area of
// the polygon.
let rect = LayoutRect::new(LayoutPoint::new(0.0, 0.0),
LayoutSize::new(10.0, 10.0));
// And we'll test three points of interest.
let p_inside_once = LayoutPoint::new(5.0, 3.0);
let p_inside_twice = LayoutPoint::new(5.0, 5.0);
let p_outside = LayoutPoint::new(9.0, 9.0);
// We should get the same results for both clockwise and
// counter-clockwise polygons.
// For nonzero polygons, the inside twice point is considered inside.
for poly_nonzero in vec![poly_clockwise_nonzero, poly_counter_clockwise_nonzero].iter() {
assert_eq!(polygon_contains_point(&p_inside_once, &rect, &poly_nonzero), true);
assert_eq!(polygon_contains_point(&p_inside_twice, &rect, &poly_nonzero), true);
assert_eq!(polygon_contains_point(&p_outside, &rect, &poly_nonzero), false);
}
// For evenodd polygons, the inside twice point is considered outside.
for poly_evenodd in vec![poly_clockwise_evenodd, poly_counter_clockwise_evenodd].iter() {
assert_eq!(polygon_contains_point(&p_inside_once, &rect, &poly_evenodd), true);
assert_eq!(polygon_contains_point(&p_inside_twice, &rect, &poly_evenodd), false);
assert_eq!(polygon_contains_point(&p_outside, &rect, &poly_evenodd), false);
}
}
}
pub trait MaxRect {

Просмотреть файл

@ -155,7 +155,6 @@ pub enum DisplayItem {
SetFilterOps,
SetFilterData,
SetFilterPrimitives,
SetPoints,
// These marker items terminate a scope introduced by a previous item.
PopReferenceFrame,
@ -204,7 +203,6 @@ pub enum DebugDisplayItem {
SetFilterOps(Vec<FilterOp>),
SetFilterData(FilterData),
SetFilterPrimitives(Vec<FilterPrimitive>),
SetPoints(Vec<LayoutPoint>),
PopReferenceFrame,
PopStackingContext,
@ -216,8 +214,7 @@ pub struct ImageMaskClipDisplayItem {
pub id: ClipId,
pub parent_space_and_clip: SpaceAndClipInfo,
pub image_mask: ImageMask,
pub fill_rule: FillRule,
} // IMPLICIT points: Vec<LayoutPoint>
}
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct RectClipDisplayItem {
@ -1491,34 +1488,6 @@ impl ComplexClipRegion {
}
}
pub const POLYGON_CLIP_VERTEX_MAX: usize = 16;
#[repr(u8)]
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Eq, Hash, PeekPoke)]
pub enum FillRule {
Nonzero = 0x1, // Behaves as the SVG fill-rule definition for nonzero.
Evenodd = 0x2, // Behaves as the SVG fill-rule definition for evenodd.
}
impl From<u8> for FillRule {
fn from(fill_rule: u8) -> Self {
match fill_rule {
0x1 => FillRule::Nonzero,
0x2 => FillRule::Evenodd,
_ => panic!("Unexpected FillRule value."),
}
}
}
impl From<FillRule> for u8 {
fn from(fill_rule: FillRule) -> Self {
match fill_rule {
FillRule::Nonzero => 0x1,
FillRule::Evenodd => 0x2,
}
}
}
#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, Hash, PartialEq, Serialize, PeekPoke)]
pub struct ClipChainId(pub u64, pub PipelineId);
@ -1646,7 +1615,6 @@ impl DisplayItem {
DisplayItem::SetFilterOps => "set_filter_ops",
DisplayItem::SetFilterData => "set_filter_data",
DisplayItem::SetFilterPrimitives => "set_filter_primitives",
DisplayItem::SetPoints => "set_points",
DisplayItem::RadialGradient(..) => "radial_gradient",
DisplayItem::Rectangle(..) => "rectangle",
DisplayItem::ScrollFrame(..) => "scroll_frame",
@ -1688,7 +1656,6 @@ impl_default_for_enums! {
FilterOp => Identity,
ComponentTransferFuncType => Identity,
ClipMode => Clip,
FillRule => Nonzero,
ClipId => ClipId::invalid(),
ReferenceFrameKind => Transform {
is_2d_scale_translation: false,

Просмотреть файл

@ -227,7 +227,6 @@ pub struct BuiltDisplayListIter<'a> {
cur_filter_primitives: ItemRange<'a, di::FilterPrimitive>,
cur_clip_chain_items: ItemRange<'a, di::ClipId>,
cur_complex_clip: ItemRange<'a, di::ComplexClipRegion>,
cur_points: ItemRange<'a, LayoutPoint>,
peeking: Peek,
/// Should just be initialized but never populated in release builds
debug_stats: DebugStats,
@ -325,10 +324,6 @@ impl<'a, 'b> DisplayItemRef<'a, 'b> {
self.iter.cur_complex_clip
}
pub fn points(&self) -> ItemRange<LayoutPoint> {
self.iter.cur_points
}
pub fn glyphs(&self) -> ItemRange<GlyphInstance> {
self.iter.glyphs()
}
@ -484,9 +479,6 @@ impl BuiltDisplayList {
Real::SetGradientStops => Debug::SetGradientStops(
item.iter.cur_stops.iter().collect()
),
Real::SetPoints => Debug::SetPoints(
item.iter.cur_points.iter().collect()
),
Real::RectClip(v) => Debug::RectClip(v),
Real::RoundedRectClip(v) => Debug::RoundedRectClip(v),
Real::ImageMaskClip(v) => Debug::ImageMaskClip(v),
@ -556,7 +548,6 @@ impl<'a> BuiltDisplayListIter<'a> {
cur_filter_primitives: ItemRange::default(),
cur_clip_chain_items: ItemRange::default(),
cur_complex_clip: ItemRange::default(),
cur_points: ItemRange::default(),
peeking: Peek::NotPeeking,
debug_stats: DebugStats {
last_addr: data.as_ptr() as usize,
@ -625,7 +616,6 @@ impl<'a> BuiltDisplayListIter<'a> {
self.cur_stops = ItemRange::default();
self.cur_complex_clip = ItemRange::default();
self.cur_clip_chain_items = ItemRange::default();
self.cur_points = ItemRange::default();
self.cur_filters = ItemRange::default();
self.cur_filter_primitives = ItemRange::default();
self.cur_filter_data.clear();
@ -636,8 +626,7 @@ impl<'a> BuiltDisplayListIter<'a> {
SetGradientStops |
SetFilterOps |
SetFilterData |
SetFilterPrimitives |
SetPoints => {
SetFilterPrimitives => {
// These are marker items for populating other display items, don't yield them.
continue;
}
@ -699,10 +688,6 @@ impl<'a> BuiltDisplayListIter<'a> {
self.cur_filter_primitives = skip_slice::<di::FilterPrimitive>(&mut self.data);
self.debug_stats.log_slice("set_filter_primitives.primitives", &self.cur_filter_primitives);
}
SetPoints => {
self.cur_points = skip_slice::<LayoutPoint>(&mut self.data);
self.debug_stats.log_slice("set_points.points", &self.cur_points);
}
ClipChain(_) => {
self.cur_clip_chain_items = skip_slice::<di::ClipId>(&mut self.data);
self.debug_stats.log_slice("clip_chain.clip_ids", &self.cur_clip_chain_items);
@ -916,10 +901,6 @@ impl<'de> Deserialize<'de> for BuiltDisplayList {
DisplayListBuilder::push_iter_impl(&mut temp, stops);
Real::SetGradientStops
},
Debug::SetPoints(points) => {
DisplayListBuilder::push_iter_impl(&mut temp, points);
Real::SetPoints
},
Debug::RectClip(v) => Real::RectClip(v),
Debug::RoundedRectClip(v) => Real::RoundedRectClip(v),
Debug::ImageMaskClip(v) => Real::ImageMaskClip(v),
@ -1800,19 +1781,14 @@ impl DisplayListBuilder {
&mut self,
parent_space_and_clip: &di::SpaceAndClipInfo,
image_mask: di::ImageMask,
points: &[LayoutPoint],
fill_rule: di::FillRule,
) -> di::ClipId {
let id = self.generate_clip_index();
let item = di::DisplayItem::ImageMaskClip(di::ImageMaskClipDisplayItem {
id,
parent_space_and_clip: *parent_space_and_clip,
image_mask,
fill_rule,
});
self.push_item(&di::DisplayItem::SetPoints);
self.push_iter(points);
self.push_item(&item);
id
}

Просмотреть файл

@ -17,7 +17,6 @@ use std::usize;
use webrender::api::*;
use webrender::render_api::*;
use webrender::api::units::*;
use webrender::api::FillRule;
use crate::wrench::{FontDescriptor, Wrench, WrenchThing};
use crate::yaml_helper::{StringEnum, YamlHelper, make_perspective};
use yaml_rust::{Yaml, YamlLoader};
@ -1983,8 +1982,6 @@ impl YamlFrameReader {
space_and_clip.clip_id = dl.define_clip_image_mask(
&space_and_clip,
image_mask,
&vec![],
FillRule::Nonzero,
);
}

Просмотреть файл

@ -9514,43 +9514,6 @@ static Maybe<wr::WrClipId> CreateSimpleClipRegion(
return Some(clipId);
}
static void FillPolygonDataForDisplayItem(
const nsDisplayMasksAndClipPaths& aDisplayItem,
nsTArray<wr::LayoutPoint>& aPoints, wr::FillRule& aFillRule) {
nsIFrame* frame = aDisplayItem.Frame();
const auto* style = frame->StyleSVGReset();
bool isPolygon = style->HasClipPath() && style->mClipPath.IsShape() &&
style->mClipPath.AsShape()._0->IsPolygon();
if (!isPolygon) {
return;
}
const auto& clipPath = style->mClipPath;
const auto& shape = *clipPath.AsShape()._0;
const nsRect refBox =
nsLayoutUtils::ComputeGeometryBox(frame, clipPath.AsShape()._1);
// We only fill polygon data for polygons that are below a complexity
// limit.
nsTArray<nsPoint> vertices =
ShapeUtils::ComputePolygonVertices(shape, refBox);
if (vertices.Length() > wr::POLYGON_CLIP_VERTEX_MAX) {
return;
}
auto appUnitsPerDevPixel = frame->PresContext()->AppUnitsPerDevPixel();
for (size_t i = 0; i < vertices.Length(); ++i) {
wr::LayoutPoint point = wr::ToLayoutPoint(
LayoutDevicePoint::FromAppUnits(vertices[i], appUnitsPerDevPixel));
aPoints.AppendElement(point);
}
aFillRule = (shape.AsPolygon().fill == StyleFillRule::Nonzero)
? wr::FillRule::Nonzero
: wr::FillRule::Evenodd;
}
static Maybe<wr::WrClipId> CreateWRClipPathAndMasks(
nsDisplayMasksAndClipPaths* aDisplayItem, const LayoutDeviceRect& aBounds,
wr::IpcResourceUpdateQueue& aResources, wr::DisplayListBuilder& aBuilder,
@ -9566,14 +9529,7 @@ static Maybe<wr::WrClipId> CreateWRClipPathAndMasks(
return Nothing();
}
// We couldn't create a simple clip region, but before we create an image
// mask clip, see if we can get a polygon clip to add to it.
nsTArray<wr::LayoutPoint> points;
wr::FillRule fillRule = wr::FillRule::Nonzero;
FillPolygonDataForDisplayItem(*aDisplayItem, points, fillRule);
wr::WrClipId clipId =
aBuilder.DefineImageMaskClip(mask.ref(), points, fillRule);
wr::WrClipId clipId = aBuilder.DefineImageMaskClip(mask.ref());
return Some(clipId);
}