@@ -8050,7 +8050,11 @@ fn get_surface_rects(
8050
8050
}
8051
8051
} ;
8052
8052
8053
+ // We need to put the clipped, unclipped and source rects in the chosen
8054
+ // raster spatial node if possible, so that it will be rendered at the
8055
+ // proper pixel scale with antialiasing, otherwise it would be blurry.
8053
8056
let ( mut clipped, mut unclipped, mut source) = if surface. raster_spatial_node_index != surface. surface_spatial_node_index {
8057
+ // Transform surface into the chosen raster spatial node
8054
8058
assert_eq ! ( surface. device_pixel_scale. 0 , 1.0 ) ;
8055
8059
8056
8060
let local_to_world = SpaceMapper :: new_with_target (
@@ -8060,21 +8064,32 @@ fn get_surface_rects(
8060
8064
spatial_tree,
8061
8065
) ;
8062
8066
8063
- let clipped = ( local_to_world. map ( & clipped_local. cast_unit ( ) ) . unwrap ( ) * surface. device_pixel_scale ) . round_out ( ) ;
8067
+ let clipped = local_to_world. map ( & clipped_local. cast_unit ( ) ) . unwrap ( ) * surface. device_pixel_scale ;
8064
8068
let unclipped = local_to_world. map ( & unclipped_local) . unwrap ( ) * surface. device_pixel_scale ;
8065
- let source = ( local_to_world. map ( & source_local. cast_unit ( ) ) . unwrap ( ) * surface. device_pixel_scale ) . round_out ( ) ;
8069
+ let source = local_to_world. map ( & source_local. cast_unit ( ) ) . unwrap ( ) * surface. device_pixel_scale ;
8066
8070
8067
8071
( clipped, unclipped, source)
8068
8072
} else {
8069
- let clipped = ( clipped_local. cast_unit ( ) * surface. device_pixel_scale ) . round_out ( ) ;
8073
+ // Surface is already in the chosen raster spatial node
8074
+ let clipped = clipped_local. cast_unit ( ) * surface. device_pixel_scale ;
8070
8075
let unclipped = unclipped_local. cast_unit ( ) * surface. device_pixel_scale ;
8071
- let source = ( source_local. cast_unit ( ) * surface. device_pixel_scale ) . round_out ( ) ;
8076
+ let source = source_local. cast_unit ( ) * surface. device_pixel_scale ;
8072
8077
8073
8078
( clipped, unclipped, source)
8074
8079
} ;
8075
8080
8076
- // Limit rendering extremely large pictures to something the hardware can
8077
- // handle, considering both clipped (target subregion) and source subregion.
8081
+ // We need to make sure the surface size does not exceed max_surface_size,
8082
+ // if it would exceed it we actually want to keep the surface in its local
8083
+ // space and stop worrying about it being a little blurry.
8084
+ //
8085
+ // Use slightly less than max_surface_size to be safe as we're not using the
8086
+ // rounded rect (which depending on subpixel alignment could add 1 or 2 to
8087
+ // width), and leave room for SVGFEGraph to add a 1 pixel inflate border on
8088
+ // all sides, so that it is less likely to have to do its own scaling on
8089
+ // intermediates which would just add more layers of blurriness.
8090
+ //
8091
+ // Since both clipped and source are subject to the same limit, we can just
8092
+ // pick the largest axis from all rects involved.
8078
8093
//
8079
8094
// If you change this, test with:
8080
8095
// ./mach crashtest layout/svg/crashtests/387290-1.svg
@@ -8084,28 +8099,36 @@ fn get_surface_rects(
8084
8099
source. width ( ) . max (
8085
8100
source. height ( )
8086
8101
) ) ) . ceil ( ) ;
8087
- if max_dimension > max_surface_size {
8102
+ let max_allowed_dimension = max_surface_size - 4.0 ;
8103
+ if max_dimension > max_allowed_dimension {
8104
+ // We have to recalculate max_dimension for the local space we'll be using
8088
8105
let max_dimension =
8089
8106
clipped_local. width ( ) . max (
8090
8107
clipped_local. height ( ) . max (
8091
8108
source_local. width ( ) . max (
8092
8109
source_local. height ( )
8093
8110
) ) ) . ceil ( ) ;
8094
8111
surface. raster_spatial_node_index = surface. surface_spatial_node_index ;
8095
- surface. device_pixel_scale = Scale :: new ( max_surface_size / max_dimension) ;
8112
+ surface. device_pixel_scale = Scale :: new ( max_allowed_dimension / max_dimension) ;
8096
8113
surface. local_scale = ( 1.0 , 1.0 ) ;
8097
8114
8098
- clipped = ( clipped_local. cast_unit ( ) * surface. device_pixel_scale ) . round ( ) ;
8115
+ clipped = clipped_local. cast_unit ( ) * surface. device_pixel_scale ;
8099
8116
unclipped = unclipped_local. cast_unit ( ) * surface. device_pixel_scale ;
8100
- source = ( source_local. cast_unit ( ) * surface. device_pixel_scale ) . round ( ) ;
8117
+ source = source_local. cast_unit ( ) * surface. device_pixel_scale ;
8101
8118
}
8102
8119
8103
- let task_size = clipped. size ( ) . to_i32 ( ) ;
8104
- debug_assert ! ( task_size. width <= max_surface_size as i32 ) ;
8105
- debug_assert ! ( task_size. height <= max_surface_size as i32 ) ;
8120
+ let source = source. round_out ( ) ;
8121
+ let clipped_snapped = clipped. round_out ( ) ;
8122
+ let task_size = clipped_snapped. size ( ) . to_i32 ( ) ;
8123
+ assert ! (
8124
+ task_size. width <= max_surface_size as i32 &&
8125
+ task_size. height <= max_surface_size as i32 ,
8126
+ "task_size {:?} must be within max_surface_size {}" ,
8127
+ task_size,
8128
+ max_surface_size) ;
8106
8129
8107
8130
let uv_rect_kind = calculate_uv_rect_kind (
8108
- clipped ,
8131
+ clipped_snapped ,
8109
8132
unclipped,
8110
8133
) ;
8111
8134
@@ -8125,7 +8148,7 @@ fn get_surface_rects(
8125
8148
Some ( SurfaceAllocInfo {
8126
8149
task_size,
8127
8150
needs_scissor_rect,
8128
- clipped,
8151
+ clipped : clipped_snapped ,
8129
8152
unclipped,
8130
8153
source,
8131
8154
clipped_local,
0 commit comments