2
2
* License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
4
5
- use app_units:: Au ;
5
+ use app_units:: { Au , MAX_AU } ;
6
6
use base:: id:: { BrowsingContextId , PipelineId } ;
7
7
use data_url:: DataUrl ;
8
8
use embedder_traits:: ViewportDetails ;
@@ -86,6 +86,16 @@ impl NaturalSizes {
86
86
}
87
87
}
88
88
89
+ pub ( crate ) fn from_natural_size_in_dots ( natural_size_in_dots : PhysicalSize < f64 > ) -> Self {
90
+ // FIXME: should 'image-resolution' (when implemented) be used *instead* of
91
+ // `script::dom::htmlimageelement::ImageRequest::current_pixel_density`?
92
+ // https://drafts.csswg.org/css-images-4/#the-image-resolution
93
+ let dppx = 1.0 ;
94
+ let width = natural_size_in_dots. width as f32 / dppx;
95
+ let height = natural_size_in_dots. height as f32 / dppx;
96
+ Self :: from_width_and_height ( width, height)
97
+ }
98
+
89
99
pub ( crate ) fn empty ( ) -> Self {
90
100
Self {
91
101
width : None ,
@@ -117,7 +127,7 @@ pub(crate) enum ReplacedContentKind {
117
127
IFrame ( IFrameInfo ) ,
118
128
Canvas ( CanvasInfo ) ,
119
129
Video ( Option < VideoInfo > ) ,
120
- SVGElement ( VectorImage ) ,
130
+ SVGElement ( Option < VectorImage > ) ,
121
131
}
122
132
123
133
impl ReplacedContents {
@@ -132,29 +142,30 @@ impl ReplacedContents {
132
142
}
133
143
}
134
144
135
- let ( kind, natural_size_in_dots ) = {
145
+ let ( kind, natural_size ) = {
136
146
if let Some ( ( image, natural_size_in_dots) ) = element. as_image ( ) {
137
147
(
138
148
ReplacedContentKind :: Image ( image) ,
139
- Some ( natural_size_in_dots) ,
149
+ NaturalSizes :: from_natural_size_in_dots ( natural_size_in_dots) ,
140
150
)
141
151
} else if let Some ( ( canvas_info, natural_size_in_dots) ) = element. as_canvas ( ) {
142
152
(
143
153
ReplacedContentKind :: Canvas ( canvas_info) ,
144
- Some ( natural_size_in_dots) ,
154
+ NaturalSizes :: from_natural_size_in_dots ( natural_size_in_dots) ,
145
155
)
146
156
} else if let Some ( ( pipeline_id, browsing_context_id) ) = element. as_iframe ( ) {
147
157
(
148
158
ReplacedContentKind :: IFrame ( IFrameInfo {
149
159
pipeline_id,
150
160
browsing_context_id,
151
161
} ) ,
152
- None ,
162
+ NaturalSizes :: empty ( ) ,
153
163
)
154
164
} else if let Some ( ( image_key, natural_size_in_dots) ) = element. as_video ( ) {
155
165
(
156
166
ReplacedContentKind :: Video ( image_key. map ( |key| VideoInfo { image_key : key } ) ) ,
157
- natural_size_in_dots,
167
+ natural_size_in_dots
168
+ . map_or_else ( NaturalSizes :: empty, NaturalSizes :: from_natural_size_in_dots) ,
158
169
)
159
170
} else if let Some ( svg_data) = element. as_svg ( ) {
160
171
let svg_source = match svg_data. source {
@@ -176,19 +187,18 @@ impl ReplacedContents {
176
187
let result = context
177
188
. image_resolver
178
189
. get_cached_image_for_url ( element. opaque ( ) , svg_source, UsePlaceholder :: No )
179
- . ok ( ) ?;
180
-
181
- let Image :: Vector ( vector_image) = result else {
182
- unreachable ! ( "SVG element can't contain a raster image." )
190
+ . ok ( ) ;
191
+
192
+ let vector_image = result. map ( |result| match result {
193
+ Image :: Vector ( vector_image) => vector_image,
194
+ _ => unreachable ! ( "SVG element can't contain a raster image." ) ,
195
+ } ) ;
196
+ let natural_size = NaturalSizes {
197
+ width : svg_data. width . map ( Au :: from_px) ,
198
+ height : svg_data. height . map ( Au :: from_px) ,
199
+ ratio : svg_data. ratio ,
183
200
} ;
184
- let physical_size = PhysicalSize :: new (
185
- vector_image. metadata . width as f64 ,
186
- vector_image. metadata . height as f64 ,
187
- ) ;
188
- (
189
- ReplacedContentKind :: SVGElement ( vector_image) ,
190
- Some ( physical_size) ,
191
- )
201
+ ( ReplacedContentKind :: SVGElement ( vector_image) , natural_size)
192
202
} else {
193
203
return None ;
194
204
}
@@ -200,18 +210,6 @@ impl ReplacedContents {
200
210
. handle_animated_image ( element. opaque ( ) , image. clone ( ) ) ;
201
211
}
202
212
203
- let natural_size = if let Some ( naturalc_size_in_dots) = natural_size_in_dots {
204
- // FIXME: should 'image-resolution' (when implemented) be used *instead* of
205
- // `script::dom::htmlimageelement::ImageRequest::current_pixel_density`?
206
- // https://drafts.csswg.org/css-images-4/#the-image-resolution
207
- let dppx = 1.0 ;
208
- let width = ( naturalc_size_in_dots. width as CSSFloat ) / dppx;
209
- let height = ( naturalc_size_in_dots. height as CSSFloat ) / dppx;
210
- NaturalSizes :: from_width_and_height ( width, height)
211
- } else {
212
- NaturalSizes :: empty ( )
213
- } ;
214
-
215
213
let base_fragment_info = BaseFragmentInfo :: new_for_node ( element. opaque ( ) ) ;
216
214
Some ( Self {
217
215
kind,
@@ -427,14 +425,33 @@ impl ReplacedContents {
427
425
} ) ) ]
428
426
} ,
429
427
ReplacedContentKind :: SVGElement ( vector_image) => {
428
+ let Some ( vector_image) = vector_image else {
429
+ return vec ! [ ] ;
430
+ } ;
430
431
let scale = layout_context. style_context . device_pixel_ratio ( ) ;
431
- let width = object_fit_size. width . scale_by ( scale. 0 ) . to_px ( ) ;
432
- let height = object_fit_size. height . scale_by ( scale. 0 ) . to_px ( ) ;
433
- let size = Size2D :: new ( width, height) ;
432
+ // TODO: This is incorrect if the SVG has a viewBox.
433
+ let size = PhysicalSize :: new (
434
+ vector_image
435
+ . metadata
436
+ . width
437
+ . try_into ( )
438
+ . map_or ( MAX_AU , Au :: from_px) ,
439
+ vector_image
440
+ . metadata
441
+ . height
442
+ . try_into ( )
443
+ . map_or ( MAX_AU , Au :: from_px) ,
444
+ ) ;
445
+ let rect = PhysicalRect :: from_size ( size) ;
446
+ let clip = rect. clone ( ) ;
447
+ let raster_size = Size2D :: new (
448
+ size. width . scale_by ( scale. 0 ) . to_px ( ) ,
449
+ size. height . scale_by ( scale. 0 ) . to_px ( ) ,
450
+ ) ;
434
451
let tag = self . base_fragment_info . tag . unwrap ( ) ;
435
452
layout_context
436
453
. image_resolver
437
- . rasterize_vector_image ( vector_image. id , size , tag. node )
454
+ . rasterize_vector_image ( vector_image. id , raster_size , tag. node )
438
455
. and_then ( |image| image. id )
439
456
. map ( |image_key| {
440
457
Fragment :: Image ( ArcRefCell :: new ( ImageFragment {
0 commit comments