зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1618000: Part 2: Clamp blur radius based on scale factors r=gfx-reviewers,nical
Differential Revision: https://phabricator.services.mozilla.com/D65805 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
0c74db8b9e
Коммит
34e8ddc337
|
@ -4,7 +4,6 @@
|
|||
|
||||
use api::{BorderRadius, BoxShadowClipMode, ClipMode, ColorF, PrimitiveKeyKind};
|
||||
use api::PropertyBinding;
|
||||
use api::MAX_BLUR_RADIUS;
|
||||
use api::units::*;
|
||||
use crate::clip::{ClipItemKey, ClipItemKeyKind};
|
||||
use crate::scene_building::SceneBuilder;
|
||||
|
@ -51,6 +50,10 @@ pub struct BoxShadowClipSource {
|
|||
// The blur shader samples BLUR_SAMPLE_SCALE * blur_radius surrounding texels.
|
||||
pub const BLUR_SAMPLE_SCALE: f32 = 3.0;
|
||||
|
||||
// Maximum blur radius for box-shadows (different than blur filters).
|
||||
// Taken from nsCSSRendering.cpp in Gecko.
|
||||
pub const MAX_BLUR_RADIUS: f32 = 300.;
|
||||
|
||||
// A cache key that uniquely identifies a minimally sized
|
||||
// and blurred box-shadow rect that can be stored in the
|
||||
// texture cache and applied to clip-masks.
|
||||
|
|
|
@ -323,6 +323,7 @@ impl FrameBuilder {
|
|||
global_screen_world_rect,
|
||||
&scene.spatial_tree,
|
||||
global_device_pixel_scale,
|
||||
(1.0, 1.0),
|
||||
);
|
||||
surfaces.push(root_surface);
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use api::{ColorF, DebugCommand, DocumentId, ExternalImageData, ExternalImageId, PrimitiveFlags};
|
||||
use api::{ImageFormat, ItemTag, NotificationRequest, Shadow, FilterOp, MAX_BLUR_RADIUS};
|
||||
use api::{ImageFormat, ItemTag, NotificationRequest, Shadow, FilterOp};
|
||||
use api::units::*;
|
||||
use api;
|
||||
use crate::composite::NativeSurfaceOperation;
|
||||
|
@ -86,22 +86,6 @@ pub enum Filter {
|
|||
}
|
||||
|
||||
impl Filter {
|
||||
/// Ensure that the parameters for a filter operation
|
||||
/// are sensible.
|
||||
pub fn sanitize(&mut self) {
|
||||
match self {
|
||||
Filter::Blur(ref mut radius) => {
|
||||
*radius = radius.min(MAX_BLUR_RADIUS);
|
||||
}
|
||||
Filter::DropShadows(ref mut stack) => {
|
||||
for shadow in stack {
|
||||
shadow.blur_radius = shadow.blur_radius.min(MAX_BLUR_RADIUS);
|
||||
}
|
||||
}
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_visible(&self) -> bool {
|
||||
match *self {
|
||||
Filter::Identity |
|
||||
|
|
|
@ -96,9 +96,9 @@
|
|||
|
||||
use api::{MixBlendMode, PipelineId, PremultipliedColorF, FilterPrimitiveKind};
|
||||
use api::{PropertyBinding, PropertyBindingId, FilterPrimitive, FontRenderMode};
|
||||
use api::{DebugFlags, RasterSpace, ImageKey, ColorF, ColorU, PrimitiveFlags, MAX_BLUR_RADIUS};
|
||||
use api::{DebugFlags, RasterSpace, ImageKey, ColorF, ColorU, PrimitiveFlags};
|
||||
use api::units::*;
|
||||
use crate::box_shadow::{BLUR_SAMPLE_SCALE};
|
||||
use crate::box_shadow::BLUR_SAMPLE_SCALE;
|
||||
use crate::clip::{ClipStore, ClipChainInstance, ClipDataHandle, ClipChainId};
|
||||
use crate::spatial_tree::{ROOT_SPATIAL_NODE_INDEX,
|
||||
SpatialTree, CoordinateSpaceMapping, SpatialNodeIndex, VisibleFace
|
||||
|
@ -133,7 +133,7 @@ use smallvec::SmallVec;
|
|||
use std::{mem, u8, marker, u32};
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use crate::texture_cache::TextureCacheHandle;
|
||||
use crate::util::{MaxRect, scale_factors, VecHelper, RectHelpers, MatrixHelpers};
|
||||
use crate::util::{MaxRect, VecHelper, RectHelpers, MatrixHelpers};
|
||||
use crate::filterdata::{FilterDataHandle};
|
||||
#[cfg(any(feature = "capture", feature = "replay"))]
|
||||
use ron;
|
||||
|
@ -170,6 +170,10 @@ use crate::scene_building::{SliceFlags};
|
|||
// used by tileview so don't use an internal_types FastHashMap
|
||||
use std::collections::HashMap;
|
||||
|
||||
// Maximum blur radius for blur filter (different than box-shadow blur).
|
||||
// Taken from FilterNodeSoftware.cpp in Gecko.
|
||||
pub const MAX_BLUR_RADIUS: f32 = 100.;
|
||||
|
||||
/// Specify whether a surface allows subpixel AA text rendering.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum SubpixelMode {
|
||||
|
@ -399,6 +403,20 @@ fn clampf(value: f32, low: f32, high: f32) -> f32 {
|
|||
value.max(low).min(high)
|
||||
}
|
||||
|
||||
/// Clamps the blur radius depending on scale factors.
|
||||
fn clamp_blur_radius(blur_radius: f32, scale_factors: (f32, f32)) -> f32 {
|
||||
// Clamping must occur after scale factors are applied, but scale factors are not applied
|
||||
// until later on. To clamp the blur radius, we first apply the scale factors and then clamp
|
||||
// and finally revert the scale factors.
|
||||
|
||||
// TODO: the clamping should be done on a per-axis basis, but WR currently only supports
|
||||
// having a single value for both x and y blur.
|
||||
let largest_scale_factor = f32::max(scale_factors.0, scale_factors.1);
|
||||
let adjusted_blur_radius = blur_radius * largest_scale_factor;
|
||||
let clamped_blur_radius = f32::min(adjusted_blur_radius, MAX_BLUR_RADIUS);
|
||||
clamped_blur_radius / largest_scale_factor
|
||||
}
|
||||
|
||||
/// An index into the prims array in a TileDescriptor.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
|
@ -3764,6 +3782,8 @@ pub struct SurfaceInfo {
|
|||
pub inflation_factor: f32,
|
||||
/// The device pixel ratio specific to this surface.
|
||||
pub device_pixel_scale: DevicePixelScale,
|
||||
/// The scale factors of the surface to raster transform.
|
||||
pub scale_factors: (f32, f32),
|
||||
}
|
||||
|
||||
impl SurfaceInfo {
|
||||
|
@ -3774,6 +3794,7 @@ impl SurfaceInfo {
|
|||
world_rect: WorldRect,
|
||||
spatial_tree: &SpatialTree,
|
||||
device_pixel_scale: DevicePixelScale,
|
||||
scale_factors: (f32, f32),
|
||||
) -> Self {
|
||||
let map_surface_to_world = SpaceMapper::new_with_target(
|
||||
ROOT_SPATIAL_NODE_INDEX,
|
||||
|
@ -3799,6 +3820,7 @@ impl SurfaceInfo {
|
|||
surface_spatial_node_index,
|
||||
inflation_factor,
|
||||
device_pixel_scale,
|
||||
scale_factors,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3861,19 +3883,20 @@ pub enum PictureCompositeMode {
|
|||
}
|
||||
|
||||
impl PictureCompositeMode {
|
||||
pub fn inflate_picture_rect(&self, picture_rect: PictureRect, inflation_factor: f32) -> PictureRect {
|
||||
pub fn inflate_picture_rect(&self, picture_rect: PictureRect, scale_factors: (f32, f32)) -> PictureRect {
|
||||
let mut result_rect = picture_rect;
|
||||
match self {
|
||||
PictureCompositeMode::Filter(filter) => match filter {
|
||||
Filter::Blur(_) => {
|
||||
Filter::Blur(blur_radius) => {
|
||||
let inflation_factor = clamp_blur_radius(*blur_radius, scale_factors).ceil() * BLUR_SAMPLE_SCALE;
|
||||
result_rect = picture_rect.inflate(inflation_factor, inflation_factor);
|
||||
},
|
||||
Filter::DropShadows(shadows) => {
|
||||
let mut max_inflation: f32 = 0.0;
|
||||
for shadow in shadows {
|
||||
let inflation_factor = shadow.blur_radius.ceil() * BLUR_SAMPLE_SCALE;
|
||||
max_inflation = max_inflation.max(inflation_factor);
|
||||
max_inflation = max_inflation.max(shadow.blur_radius);
|
||||
}
|
||||
max_inflation = clamp_blur_radius(max_inflation, scale_factors).ceil() * BLUR_SAMPLE_SCALE;
|
||||
result_rect = picture_rect.inflate(max_inflation, max_inflation);
|
||||
},
|
||||
_ => {}
|
||||
|
@ -4544,6 +4567,10 @@ impl PicturePrimitive {
|
|||
.surfaces[raster_config.surface_index.0]
|
||||
.device_pixel_scale;
|
||||
|
||||
let scale_factors = frame_state
|
||||
.surfaces[raster_config.surface_index.0]
|
||||
.scale_factors;
|
||||
|
||||
let (mut clipped, mut unclipped) = match get_raster_rects(
|
||||
pic_rect,
|
||||
&map_pic_to_raster,
|
||||
|
@ -4617,15 +4644,14 @@ impl PicturePrimitive {
|
|||
|
||||
let dep_info = match raster_config.composite_mode {
|
||||
PictureCompositeMode::Filter(Filter::Blur(blur_radius)) => {
|
||||
let blur_std_deviation = blur_radius * device_pixel_scale.0;
|
||||
let scale_factors = scale_factors(&transform);
|
||||
let blur_std_deviation = clamp_blur_radius(blur_radius, scale_factors) * device_pixel_scale.0;
|
||||
let mut blur_std_deviation = DeviceSize::new(
|
||||
blur_std_deviation * scale_factors.0,
|
||||
blur_std_deviation * scale_factors.1
|
||||
);
|
||||
let mut device_rect = if self.options.inflate_if_required {
|
||||
let inflation_factor = frame_state.surfaces[raster_config.surface_index.0].inflation_factor;
|
||||
let inflation_factor = (inflation_factor * device_pixel_scale.0).ceil();
|
||||
let inflation_factor = inflation_factor * device_pixel_scale.0;
|
||||
|
||||
// The clipped field is the part of the picture that is visible
|
||||
// on screen. The unclipped field is the screen-space rect of
|
||||
|
@ -4638,7 +4664,7 @@ impl PicturePrimitive {
|
|||
// We cast clipped to f32 instead of casting unclipped to i32
|
||||
// because unclipped can overflow an i32.
|
||||
let device_rect = clipped.to_f32()
|
||||
.inflate(inflation_factor, inflation_factor)
|
||||
.inflate(inflation_factor * scale_factors.0, inflation_factor * scale_factors.1)
|
||||
.intersection(&unclipped)
|
||||
.unwrap();
|
||||
|
||||
|
@ -4711,14 +4737,15 @@ impl PicturePrimitive {
|
|||
for shadow in shadows {
|
||||
// TODO(nical) presumably we should compute the clipped rect for each shadow
|
||||
// and compute the union of them to determine what we need to rasterize and blur?
|
||||
max_std_deviation = f32::max(max_std_deviation, shadow.blur_radius * device_pixel_scale.0);
|
||||
max_std_deviation = f32::max(max_std_deviation, shadow.blur_radius);
|
||||
}
|
||||
max_std_deviation = clamp_blur_radius(max_std_deviation, scale_factors) * device_pixel_scale.0;
|
||||
let max_blur_range = max_std_deviation * BLUR_SAMPLE_SCALE;
|
||||
|
||||
let max_blur_range = (max_std_deviation * BLUR_SAMPLE_SCALE).ceil();
|
||||
// We cast clipped to f32 instead of casting unclipped to i32
|
||||
// because unclipped can overflow an i32.
|
||||
let device_rect = clipped.to_f32()
|
||||
.inflate(max_blur_range, max_blur_range)
|
||||
.inflate(max_blur_range * scale_factors.0, max_blur_range * scale_factors.1)
|
||||
.intersection(&unclipped)
|
||||
.unwrap();
|
||||
|
||||
|
@ -4731,7 +4758,10 @@ impl PicturePrimitive {
|
|||
|
||||
device_rect.size = RenderTask::adjusted_blur_source_size(
|
||||
device_rect.size,
|
||||
DeviceSize::new(max_std_deviation, max_std_deviation),
|
||||
DeviceSize::new(
|
||||
max_std_deviation * scale_factors.0,
|
||||
max_std_deviation * scale_factors.1
|
||||
),
|
||||
);
|
||||
|
||||
if let Some(scale) = adjust_scale_for_max_surface_size(
|
||||
|
@ -4775,14 +4805,12 @@ impl PicturePrimitive {
|
|||
self.extra_gpu_data_handles.resize(shadows.len(), GpuCacheHandle::new());
|
||||
|
||||
let mut blur_render_task_id = picture_task_id;
|
||||
let scale_factors = scale_factors(&transform);
|
||||
for shadow in shadows {
|
||||
// TODO(cbrewster): We should take the scale factors into account when clamping the max
|
||||
// std deviation for the blur earlier so that we don't overinflate.
|
||||
let blur_radius = clamp_blur_radius(shadow.blur_radius, scale_factors) * device_pixel_scale.0;
|
||||
blur_render_task_id = RenderTask::new_blur(
|
||||
DeviceSize::new(
|
||||
f32::min(shadow.blur_radius * scale_factors.0, MAX_BLUR_RADIUS) * device_pixel_scale.0,
|
||||
f32::min(shadow.blur_radius * scale_factors.1, MAX_BLUR_RADIUS) * device_pixel_scale.0,
|
||||
blur_radius * scale_factors.0,
|
||||
blur_radius * scale_factors.1,
|
||||
),
|
||||
picture_task_id,
|
||||
frame_state.render_tasks,
|
||||
|
@ -5602,33 +5630,6 @@ impl PicturePrimitive {
|
|||
let parent_raster_node_index = state.current_surface().raster_spatial_node_index;
|
||||
let surface_spatial_node_index = self.spatial_node_index;
|
||||
|
||||
// This inflation factor is to be applied to all primitives within the surface.
|
||||
let inflation_factor = match composite_mode {
|
||||
PictureCompositeMode::Filter(Filter::Blur(blur_radius)) => {
|
||||
// Only inflate if the caller hasn't already inflated
|
||||
// the bounding rects for this filter.
|
||||
if self.options.inflate_if_required {
|
||||
// The amount of extra space needed for primitives inside
|
||||
// this picture to ensure the visibility check is correct.
|
||||
BLUR_SAMPLE_SCALE * blur_radius
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
}
|
||||
PictureCompositeMode::SvgFilter(ref primitives, _) if self.options.inflate_if_required => {
|
||||
let mut max = 0.0;
|
||||
for primitive in primitives {
|
||||
if let FilterPrimitiveKind::Blur(ref blur) = primitive.kind {
|
||||
max = f32::max(max, blur.radius * BLUR_SAMPLE_SCALE);
|
||||
}
|
||||
}
|
||||
max
|
||||
}
|
||||
_ => {
|
||||
0.0
|
||||
}
|
||||
};
|
||||
|
||||
// Filters must be applied before transforms, to do this, we can mark this picture as establishing a raster root.
|
||||
let has_svg_filter = if let PictureCompositeMode::SvgFilter(..) = composite_mode {
|
||||
true
|
||||
|
@ -5642,17 +5643,49 @@ impl PicturePrimitive {
|
|||
.get_relative_transform(surface_spatial_node_index, parent_raster_node_index)
|
||||
.is_perspective();
|
||||
|
||||
let raster_spatial_node_index = if establishes_raster_root {
|
||||
surface_spatial_node_index
|
||||
} else {
|
||||
parent_raster_node_index
|
||||
};
|
||||
|
||||
let scale_factors = frame_context
|
||||
.spatial_tree
|
||||
.get_relative_transform(surface_spatial_node_index, raster_spatial_node_index)
|
||||
.scale_factors();
|
||||
|
||||
// This inflation factor is to be applied to all primitives within the surface.
|
||||
// Only inflate if the caller hasn't already inflated the bounding rects for this filter.
|
||||
let mut inflation_factor = 0.0;
|
||||
if self.options.inflate_if_required {
|
||||
match composite_mode {
|
||||
PictureCompositeMode::Filter(Filter::Blur(blur_radius)) => {
|
||||
let blur_radius = clamp_blur_radius(blur_radius, scale_factors);
|
||||
// The amount of extra space needed for primitives inside
|
||||
// this picture to ensure the visibility check is correct.
|
||||
inflation_factor = blur_radius * BLUR_SAMPLE_SCALE;
|
||||
}
|
||||
PictureCompositeMode::SvgFilter(ref primitives, _) => {
|
||||
let mut max = 0.0;
|
||||
for primitive in primitives {
|
||||
if let FilterPrimitiveKind::Blur(ref blur) = primitive.kind {
|
||||
max = f32::max(max, blur.radius);
|
||||
}
|
||||
}
|
||||
inflation_factor = clamp_blur_radius(max, scale_factors) * BLUR_SAMPLE_SCALE;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
let surface = SurfaceInfo::new(
|
||||
surface_spatial_node_index,
|
||||
if establishes_raster_root {
|
||||
surface_spatial_node_index
|
||||
} else {
|
||||
parent_raster_node_index
|
||||
},
|
||||
raster_spatial_node_index,
|
||||
inflation_factor,
|
||||
frame_context.global_screen_world_rect,
|
||||
&frame_context.spatial_tree,
|
||||
frame_context.global_device_pixel_scale,
|
||||
scale_factors,
|
||||
);
|
||||
|
||||
self.raster_config = Some(RasterConfig {
|
||||
|
@ -5786,7 +5819,7 @@ impl PicturePrimitive {
|
|||
// Inflate the local bounding rect if required by the filter effect.
|
||||
// This inflaction factor is to be applied to the surface itself.
|
||||
if self.options.inflate_if_required {
|
||||
surface.rect = raster_config.composite_mode.inflate_picture_rect(surface.rect, surface.inflation_factor);
|
||||
surface.rect = raster_config.composite_mode.inflate_picture_rect(surface.rect, surface.scale_factors);
|
||||
|
||||
// The picture's local rect is calculated as the union of the
|
||||
// snapped primitive rects, which should result in a snapped
|
||||
|
|
|
@ -2384,7 +2384,8 @@ impl PrimitiveStore {
|
|||
surface.device_pixel_scale,
|
||||
frame_context.spatial_tree,
|
||||
);
|
||||
surface_rect = rc.composite_mode.inflate_picture_rect(surface_rect, surface.inflation_factor);
|
||||
|
||||
surface_rect = rc.composite_mode.inflate_picture_rect(surface_rect, surface.scale_factors);
|
||||
surface_rect = snap_pic_to_raster.snap_rect(&surface_rect);
|
||||
}
|
||||
|
||||
|
|
|
@ -2567,8 +2567,7 @@ impl<'a> SceneBuilder<'a> {
|
|||
// blur radius is 0, the code in Picture::prepare_for_render will
|
||||
// detect this and mark the picture to be drawn directly into the
|
||||
// parent picture, which avoids an intermediate surface and blur.
|
||||
let mut blur_filter = Filter::Blur(std_deviation);
|
||||
blur_filter.sanitize();
|
||||
let blur_filter = Filter::Blur(std_deviation);
|
||||
let composite_mode = PictureCompositeMode::Filter(blur_filter);
|
||||
let composite_mode_key = Some(composite_mode.clone()).into();
|
||||
|
||||
|
@ -3475,8 +3474,6 @@ impl<'a> SceneBuilder<'a> {
|
|||
// For each filter, create a new image with that composite mode.
|
||||
let mut current_filter_data_index = 0;
|
||||
for filter in &mut filter_ops {
|
||||
filter.sanitize();
|
||||
|
||||
let composite_mode = Some(match *filter {
|
||||
Filter::ComponentTransfer => {
|
||||
let filter_data =
|
||||
|
|
|
@ -12,10 +12,6 @@ use crate::color::ColorF;
|
|||
use crate::image::{ColorDepth, ImageKey};
|
||||
use crate::units::*;
|
||||
|
||||
// Maximum blur radius.
|
||||
// Taken from nsCSSRendering.cpp in Gecko.
|
||||
pub const MAX_BLUR_RADIUS: f32 = 300.;
|
||||
|
||||
// ******************************************************************
|
||||
// * NOTE: some of these structs have an "IMPLICIT" comment. *
|
||||
// * This indicates that the BuiltDisplayList will have serialized *
|
||||
|
@ -871,12 +867,6 @@ pub struct BlurPrimitive {
|
|||
pub radius: f32,
|
||||
}
|
||||
|
||||
impl BlurPrimitive {
|
||||
pub fn sanitize(&mut self) {
|
||||
self.radius = self.radius.min(MAX_BLUR_RADIUS);
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
pub struct OpacityPrimitive {
|
||||
|
@ -905,12 +895,6 @@ pub struct DropShadowPrimitive {
|
|||
pub shadow: Shadow,
|
||||
}
|
||||
|
||||
impl DropShadowPrimitive {
|
||||
pub fn sanitize(&mut self) {
|
||||
self.shadow.blur_radius = self.shadow.blur_radius.min(MAX_BLUR_RADIUS);
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
pub struct ComponentTransferPrimitive {
|
||||
|
@ -968,9 +952,7 @@ impl FilterPrimitiveKind {
|
|||
pub fn sanitize(&mut self) {
|
||||
match self {
|
||||
FilterPrimitiveKind::Flood(flood) => flood.sanitize(),
|
||||
FilterPrimitiveKind::Blur(blur) => blur.sanitize(),
|
||||
FilterPrimitiveKind::Opacity(opacity) => opacity.sanitize(),
|
||||
FilterPrimitiveKind::DropShadow(drop_shadow) => drop_shadow.sanitize(),
|
||||
|
||||
// No sanitization needed.
|
||||
FilterPrimitiveKind::Identity(..) |
|
||||
|
@ -978,6 +960,8 @@ impl FilterPrimitiveKind {
|
|||
FilterPrimitiveKind::ColorMatrix(..) |
|
||||
FilterPrimitiveKind::Offset(..) |
|
||||
FilterPrimitiveKind::Composite(..) |
|
||||
FilterPrimitiveKind::Blur(..) |
|
||||
FilterPrimitiveKind::DropShadow(..) |
|
||||
// Component transfer's filter data is sanitized separately.
|
||||
FilterPrimitiveKind::ComponentTransfer(..) => {}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
# Ensures that blur clamping happens after scale factors are applied
|
||||
---
|
||||
root:
|
||||
items:
|
||||
- type: stacking-context
|
||||
bounds: [100, 100, 300, 300]
|
||||
filters: blur(100)
|
||||
items:
|
||||
- type: rect
|
||||
bounds: [0, 0, 100, 100]
|
||||
color: 0 255 0 1.0
|
||||
- type: stacking-context
|
||||
bounds: [400, 100, 300, 300]
|
||||
filters: blur(50)
|
||||
items:
|
||||
- type: rect
|
||||
bounds: [0, 0, 100, 100]
|
||||
color: 255 0 0 1.0
|
|
@ -0,0 +1,30 @@
|
|||
# Ensures that blur clamping happens after scale factors are applied
|
||||
---
|
||||
root:
|
||||
items:
|
||||
- type: stacking-context
|
||||
bounds: [100, 100, 300, 300]
|
||||
transform: scale(10)
|
||||
items:
|
||||
- type: stacking-context
|
||||
bounds: [0, 0, 300, 300]
|
||||
# Blur will be 20 * 10(scale) = 200 and it should then be clamped to 100
|
||||
filters: blur(20)
|
||||
items:
|
||||
- type: rect
|
||||
bounds: [0, 0, 10, 10]
|
||||
color: 0 255 0 1.0
|
||||
- type: stacking-context
|
||||
bounds: [400, 100, 300, 300]
|
||||
transform: scale(0.1)
|
||||
items:
|
||||
- type: stacking-context
|
||||
bounds: [0, 0, 300, 300]
|
||||
# Blur should be 500 * 0.1(scale) = 50. This tests to make sure clamping
|
||||
# does not occur before applying scale factors, otherwise 500 would be
|
||||
# clamped to 100.
|
||||
filters: blur(500)
|
||||
items:
|
||||
- type: rect
|
||||
bounds: [0, 0, 1000, 1000]
|
||||
color: 255 0 0 1.0
|
|
@ -0,0 +1,18 @@
|
|||
# Ensures that blur clamping happens after scale factors are applied
|
||||
---
|
||||
root:
|
||||
items:
|
||||
- type: stacking-context
|
||||
bounds: [100, 100, 300, 300]
|
||||
filters: drop-shadow([0, 0], 100, blue)
|
||||
items:
|
||||
- type: rect
|
||||
bounds: [0, 0, 100, 100]
|
||||
color: 0 255 0 1.0
|
||||
- type: stacking-context
|
||||
bounds: [400, 100, 300, 300]
|
||||
filters: drop-shadow([0, 0], 50, green)
|
||||
items:
|
||||
- type: rect
|
||||
bounds: [0, 0, 100, 100]
|
||||
color: 255 0 0 1.0
|
|
@ -0,0 +1,30 @@
|
|||
# Ensures that blur clamping happens after scale factors are applied
|
||||
---
|
||||
root:
|
||||
items:
|
||||
- type: stacking-context
|
||||
bounds: [100, 100, 300, 300]
|
||||
transform: scale(10)
|
||||
items:
|
||||
- type: stacking-context
|
||||
bounds: [0, 0, 300, 300]
|
||||
# Blur will be 20 * 10(scale) = 200 and it should then be clamped to 100
|
||||
filters: drop-shadow([0, 0], 20, blue)
|
||||
items:
|
||||
- type: rect
|
||||
bounds: [0, 0, 10, 10]
|
||||
color: 0 255 0 1.0
|
||||
- type: stacking-context
|
||||
bounds: [400, 100, 300, 300]
|
||||
transform: scale(0.1)
|
||||
items:
|
||||
- type: stacking-context
|
||||
bounds: [0, 0, 300, 300]
|
||||
# Blur should be 500 * 0.1(scale) = 50. This tests to make sure clamping
|
||||
# does not occur before applying scale factors, otherwise 500 would be
|
||||
# clamped to 100.
|
||||
filters: drop-shadow([0, 0], 500, green)
|
||||
items:
|
||||
- type: rect
|
||||
bounds: [0, 0, 1000, 1000]
|
||||
color: 255 0 0 1.0
|
|
@ -7,11 +7,11 @@ root:
|
|||
items:
|
||||
- type: stacking-context
|
||||
bounds: [0, 0, 1000, 1000]
|
||||
transform: scale-y(999999.25)
|
||||
transform: scale-y(100)
|
||||
items:
|
||||
- type: stacking-context
|
||||
bounds: [0, 0, 1000, 1000]
|
||||
filters: drop-shadow([999999, 999999], 999999, [255, 0, 0, 1])
|
||||
filters: drop-shadow([0, 0], 999999, [255, 0, 0, 1])
|
||||
items:
|
||||
- image: checkerboard(2, 16, 16)
|
||||
bounds: [0, 0, 1000, 1000]
|
||||
|
|
|
@ -45,7 +45,9 @@ skip_on(android,device) == filter-mix-blend-mode.yaml filter-mix-blend-mode-ref.
|
|||
!= filter-blur-huge.yaml blank.yaml
|
||||
!= filter-drop-shadow-huge.yaml blank.yaml
|
||||
!= filter-drop-shadow-transform-huge.yaml blank.yaml
|
||||
== filter-drop-shadow-blur-clamping.yaml filter-drop-shadow-blur-clamping-ref.yaml
|
||||
== filter-blur-scaled.yaml filter-blur-scaled-ref.yaml
|
||||
== filter-blur-clamping.yaml filter-blur-clamping-ref.yaml
|
||||
skip_on(android,device) fuzzy(1,104) == filter-blur-scaled-xonly.yaml filter-blur-scaled-xonly.png # fails on Pixel2
|
||||
== svg-filter-component-transfer.yaml filter-component-transfer-ref.yaml
|
||||
== svg-filter-flood.yaml svg-filter-flood-ref.yaml
|
||||
|
|
|
@ -43,7 +43,7 @@ fuzzy(0-1,0-6400) fuzzy-if(skiaContent,0-1,0-6404) fuzzy-if(webrender,178-178,30
|
|||
fuzzy-if(webrender,0-2,0-304) == feGaussianBlur-2.svg feGaussianBlur-2-ref.svg
|
||||
# != feGaussianBlur-3.svg feGaussianBlur-3-ref.svg
|
||||
fuzzy-if(webrender,3-5,5500-8168) == feGaussianBlur-4.svg feGaussianBlur-4-ref.svg
|
||||
== feGaussianBlur-5.svg feGaussianBlur-5-ref.svg
|
||||
fuzzy-if(geckoview&&webrender,0-4,0-7) == feGaussianBlur-5.svg feGaussianBlur-5-ref.svg
|
||||
== feGaussianBlur-6.svg feGaussianBlur-6-ref.svg
|
||||
skip-if(d2d) == feGaussianBlur-cap-large-directional-radius-on-software.html feGaussianBlur-cap-large-directional-radius-on-software-ref.html
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче