Bug 1675375 Part 2: Add a polygon clips to image masks. r=gw

This patch augments the pushing of an image mask to allow a polygon clip
region to be attached to it.

Differential Revision: https://phabricator.services.mozilla.com/D105397
This commit is contained in:
Brad Werth 2021-04-13 19:42:36 +00:00
Родитель 4f7272a107
Коммит 8e27bc2b02
10 изменённых файлов: 80 добавлений и 14 удалений

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

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

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

@ -460,7 +460,9 @@ 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);
wr::WrClipId DefineImageMaskClip(const wr::ImageMask& aMask,
const nsTArray<wr::LayoutPoint>&,
wr::FillRule);
wr::WrClipId DefineRoundedRectClip(const wr::ComplexClipRegion& aComplex);
wr::WrClipId DefineRectClip(wr::LayoutRect aClipRect);

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

@ -16,9 +16,11 @@ 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,13 +2685,21 @@ 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 clip_id = state
.frame_builder
.dl_builder
.define_clip_image_mask(&parent.to_webrender(state.pipeline_id), mask);
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,
);
WrClipId::from_webrender(clip_id)
}

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

@ -221,6 +221,8 @@ 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 {

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

@ -268,6 +268,9 @@ 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>;
@ -6185,7 +6188,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,

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

@ -1491,6 +1491,8 @@ 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 {

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

@ -1800,11 +1800,9 @@ impl DisplayListBuilder {
&mut self,
parent_space_and_clip: &di::SpaceAndClipInfo,
image_mask: di::ImageMask,
points: &Vec<LayoutPoint>,
fill_rule: di::FillRule,
) -> di::ClipId {
// TODO(bradwerth): get points and fill_rule as parameters.
let points = Vec::<LayoutPoint>::new();
let fill_rule = di::FillRule::Nonzero;
let id = self.generate_clip_index();
let item = di::DisplayItem::ImageMaskClip(di::ImageMaskClipDisplayItem {
id,

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

@ -17,6 +17,7 @@ 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};
@ -1982,6 +1983,8 @@ impl YamlFrameReader {
space_and_clip.clip_id = dl.define_clip_image_mask(
&space_and_clip,
image_mask,
&vec![],
FillRule::Nonzero,
);
}

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

@ -9514,6 +9514,43 @@ 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,
@ -9529,7 +9566,14 @@ static Maybe<wr::WrClipId> CreateWRClipPathAndMasks(
return Nothing();
}
wr::WrClipId clipId = aBuilder.DefineImageMaskClip(mask.ref());
// 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);
return Some(clipId);
}