Bug 1565039. In PicturePrimitive::take_context do calculation in float in case the unclipped rect is too big for int. r=gw

The final clipped result should hopefully not overflow.

Differential Revision: https://phabricator.services.mozilla.com/D37813

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Timothy Nikkel 2019-07-30 09:06:31 +00:00
Родитель 71cf2ae4e8
Коммит e4f60aaea0
3 изменённых файлов: 45 добавлений и 6 удалений

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

@ -2316,7 +2316,7 @@ impl PicturePrimitive {
blur_std_deviation * scale_factors.1
);
let inflation_factor = frame_state.surfaces[raster_config.surface_index.0].inflation_factor;
let inflation_factor = (inflation_factor * device_pixel_scale.0).ceil() as i32;
let inflation_factor = (inflation_factor * device_pixel_scale.0).ceil();
// The clipped field is the part of the picture that is visible
// on screen. The unclipped field is the screen-space rect of
@ -2326,10 +2326,20 @@ impl PicturePrimitive {
// blur results, inflate that clipped area by the blur range, and
// then intersect with the total screen rect, to minimize the
// allocation size.
let mut device_rect = clipped
// 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)
.intersection(&unclipped.to_i32())
.intersection(&unclipped)
.unwrap();
let mut device_rect = match device_rect.try_cast::<i32>() {
Some(rect) => rect,
None => {
return None
}
};
// Adjust the size to avoid introducing sampling errors during the down-scaling passes.
// what would be even better is to rasterize the picture at the down-scaled size
// directly.
@ -2379,10 +2389,21 @@ impl PicturePrimitive {
}
max_std_deviation = max_std_deviation.round();
let max_blur_range = (max_std_deviation * BLUR_SAMPLE_SCALE).ceil() as i32;
let mut device_rect = clipped.inflate(max_blur_range, max_blur_range)
.intersection(&unclipped.to_i32())
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)
.intersection(&unclipped)
.unwrap();
let mut device_rect = match device_rect.try_cast::<i32>() {
Some(rect) => rect,
None => {
return None
}
};
device_rect.size = RenderTask::adjusted_blur_source_size(
device_rect.size,
DeviceSize::new(max_std_deviation, max_std_deviation),

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

@ -0,0 +1,17 @@
# Don't crash on large blur radius with large transform!
---
root:
items:
- type: stacking-context
bounds: [0, 0, 1000, 1000]
items:
- type: stacking-context
bounds: [0, 0, 1000, 1000]
transform: scale-y(999999.25)
items:
- type: stacking-context
bounds: [0, 0, 1000, 1000]
filters: drop-shadow([999999, 999999], 999999, [255, 0, 0, 1])
items:
- image: checkerboard(2, 16, 16)
bounds: [0, 0, 1000, 1000]

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

@ -42,6 +42,7 @@ skip_on(android) == filter-mix-blend-mode.yaml filter-mix-blend-mode-ref.yaml #
!= srgb-to-linear-2.yaml srgb-to-linear-ref.yaml
!= filter-blur-huge.yaml blank.yaml
!= filter-drop-shadow-huge.yaml blank.yaml
!= filter-drop-shadow-transform-huge.yaml blank.yaml
== filter-blur-scaled.yaml filter-blur-scaled-ref.yaml
skip_on(android) == filter-blur-scaled-xonly.yaml filter-blur-scaled-xonly.png # fails on Android emulator and Pixel2
skip_on(android,emulator) == svg-filter-component-transfer.yaml filter-component-transfer-ref.yaml # fails on Android emulator