1
1
use rsvg::test_utils::reference_utils::{Compare, Evaluate, Reference};
2
use rsvg::test_utils::{load_svg, render_document, SurfaceSize};
3
use rsvg::{test_compare_render_output, test_svg_reference};
4

            
5
#[test]
6
2
fn simple_opacity_with_transform() {
7
1
    let svg = load_svg(
8
        br#"<?xml version="1.0" encoding="UTF-8"?>
9
<svg xmlns="http://www.w3.org/2000/svg" width="50" height="50">
10
  <g opacity="0.5">
11
    <rect x="10" y="10" width="30" height="30" fill="blue"/>
12
  </g>
13
</svg>
14
"#,
15
    )
16
    .unwrap();
17

            
18
1
    let output_surf = render_document(
19
        &svg,
20
1
        SurfaceSize(150, 150),
21
1
        |cr| cr.translate(50.0, 50.0),
22
1
        cairo::Rectangle::new(0.0, 0.0, 50.0, 50.0),
23
    )
24
    .unwrap();
25

            
26
1
    let reference_surf = cairo::ImageSurface::create(cairo::Format::ARgb32, 150, 150).unwrap();
27

            
28
    {
29
1
        let cr = cairo::Context::new(&reference_surf).expect("Failed to create a cairo context");
30

            
31
1
        cr.translate(50.0, 50.0);
32
1
        cr.rectangle(10.0, 10.0, 30.0, 30.0);
33
1
        cr.set_source_rgba(0.0, 0.0, 1.0, 0.5);
34
1
        cr.fill().unwrap();
35
1
    }
36

            
37
1
    Reference::from_surface(reference_surf)
38
        .compare(&output_surf)
39
1
        .evaluate(&output_surf, "simple_opacity_with_transform");
40
2
}
41

            
42
#[test]
43
2
fn simple_opacity_with_offset_viewport() {
44
1
    let svg = load_svg(
45
        br#"<?xml version="1.0" encoding="UTF-8"?>
46
<svg xmlns="http://www.w3.org/2000/svg" width="50" height="50">
47
  <g opacity="0.5">
48
    <rect x="10" y="10" width="30" height="30" fill="blue"/>
49
  </g>
50
</svg>
51
"#,
52
    )
53
    .unwrap();
54

            
55
1
    let output_surf = render_document(
56
        &svg,
57
1
        SurfaceSize(150, 150),
58
1
        |_cr| (),
59
1
        cairo::Rectangle::new(50.0, 50.0, 50.0, 50.0),
60
    )
61
    .unwrap();
62

            
63
1
    let reference_surf = cairo::ImageSurface::create(cairo::Format::ARgb32, 150, 150).unwrap();
64

            
65
    {
66
1
        let cr = cairo::Context::new(&reference_surf).expect("Failed to create a cairo context");
67

            
68
1
        cr.translate(50.0, 50.0);
69
1
        cr.rectangle(10.0, 10.0, 30.0, 30.0);
70
1
        cr.set_source_rgba(0.0, 0.0, 1.0, 0.5);
71
1
        cr.fill().unwrap();
72
1
    }
73

            
74
1
    Reference::from_surface(reference_surf)
75
        .compare(&output_surf)
76
1
        .evaluate(&output_surf, "simple_opacity_with_offset_viewport");
77
2
}
78

            
79
#[test]
80
// https://gitlab.gnome.org/GNOME/librsvg/issues/471
81
2
fn simple_opacity_with_scale() {
82
1
    let svg = load_svg(
83
        br#"<?xml version="1.0" encoding="UTF-8"?>
84
<svg xmlns="http://www.w3.org/2000/svg" width="50" height="50">
85
  <g opacity="0.5">
86
    <rect x="10" y="10" width="30" height="30" fill="blue"/>
87
  </g>
88
</svg>
89
"#,
90
    )
91
    .unwrap();
92

            
93
1
    let output_surf = render_document(
94
        &svg,
95
1
        SurfaceSize(500, 500),
96
1
        |cr| {
97
1
            cr.translate(50.0, 50.0);
98
1
            cr.scale(8.0, 8.0);
99
1
        },
100
1
        cairo::Rectangle::new(0.0, 0.0, 50.0, 50.0),
101
    )
102
    .unwrap();
103

            
104
1
    let reference_surf = cairo::ImageSurface::create(cairo::Format::ARgb32, 500, 500).unwrap();
105

            
106
    {
107
1
        let cr = cairo::Context::new(&reference_surf).expect("Failed to create a cairo context");
108

            
109
1
        cr.translate(50.0, 50.0);
110
1
        cr.scale(8.0, 8.0);
111
1
        cr.rectangle(10.0, 10.0, 30.0, 30.0);
112
1
        cr.set_source_rgba(0.0, 0.0, 1.0, 0.5);
113
1
        cr.fill().unwrap();
114
1
    }
115

            
116
1
    Reference::from_surface(reference_surf)
117
        .compare(&output_surf)
118
1
        .evaluate(&output_surf, "simple_opacity_with_scale");
119
2
}
120

            
121
#[test]
122
// https://gitlab.gnome.org/GNOME/librsvg/issues/471
123
2
fn markers_with_scale() {
124
1
    let svg = load_svg(
125
        br#"<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
126
    <marker id="marker1" refX="10" refY="10" markerWidth="20" markerHeight="20" orient="auto">
127
        <path id="marker-path" d="M 20 10 L 0 16 V 4 Z" fill="blue" opacity="0.5"/>
128
    </marker>
129
    <path d="M 30 100 L 170 100"
130
          fill="none" stroke="green"
131
          marker-start="url(#marker1)" marker-end="url(#marker1)"/>
132
</svg>
133

            
134
"#,
135
    )
136
    .unwrap();
137

            
138
1
    let output_surf = render_document(
139
        &svg,
140
1
        SurfaceSize(800, 800),
141
1
        |cr| {
142
1
            cr.scale(4.0, 4.0);
143
1
        },
144
1
        cairo::Rectangle::new(0.0, 0.0, 200.0, 200.0),
145
    )
146
    .unwrap();
147

            
148
1
    let reference_surf = cairo::ImageSurface::create(cairo::Format::ARgb32, 800, 800).unwrap();
149

            
150
    {
151
1
        let cr = cairo::Context::new(&reference_surf).expect("Failed to create a cairo context");
152

            
153
1
        cr.scale(4.0, 4.0);
154

            
155
1
        cr.move_to(30.0, 100.0);
156
1
        cr.line_to(170.0, 100.0);
157
1
        cr.set_source_rgb(0.0, 0.5, 0.0);
158
1
        cr.set_line_width(1.0);
159
1
        cr.stroke().unwrap();
160

            
161
3
        for (x, y) in &[(30.0, 100.0), (170.0, 100.0)] {
162
2
            cr.move_to(x + 20.0 - 10.0, y + 10.0 - 10.0);
163
2
            cr.line_to(x + 0.0 - 10.0, y + 16.0 - 10.0);
164
2
            cr.line_to(x + 0.0 - 10.0, y + 4.0 - 10.0);
165
2
            cr.set_source_rgba(0.0, 0.0, 1.0, 0.5);
166
2
            cr.fill().unwrap();
167
        }
168
1
    }
169

            
170
1
    Reference::from_surface(reference_surf)
171
        .compare(&output_surf)
172
1
        .evaluate(&output_surf, "markers_with_scale");
173
2
}
174

            
175
#[test]
176
2
fn opacity_inside_transformed_group() {
177
1
    let svg = load_svg(
178
        br#"<?xml version="1.0" encoding="UTF-8"?>
179
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
180
  <g transform="translate(20, 20)">
181
    <rect x="0" y="0" width="60" height="60" style="fill:blue; opacity:0.5;"/>
182
  </g>
183
</svg>
184
"#,
185
    )
186
    .unwrap();
187

            
188
1
    let output_surf = render_document(
189
        &svg,
190
1
        SurfaceSize(140, 140),
191
1
        |cr| cr.translate(20.0, 20.0),
192
1
        cairo::Rectangle::new(0.0, 0.0, 100.0, 100.0),
193
    )
194
    .unwrap();
195

            
196
1
    let reference_surf = cairo::ImageSurface::create(cairo::Format::ARgb32, 140, 140).unwrap();
197

            
198
    {
199
1
        let cr = cairo::Context::new(&reference_surf).expect("Failed to create a cairo context");
200

            
201
1
        cr.translate(20.0, 20.0);
202
1
        cr.rectangle(20.0, 20.0, 60.0, 60.0);
203
1
        cr.set_source_rgba(0.0, 0.0, 1.0, 0.5);
204
1
        cr.fill().unwrap();
205
1
    }
206

            
207
1
    Reference::from_surface(reference_surf)
208
        .compare(&output_surf)
209
1
        .evaluate(&output_surf, "opacity_inside_transformed_group");
210
2
}
211

            
212
#[test]
213
2
fn compound_opacity() {
214
1
    let svg = load_svg(
215
        br##"<?xml version="1.0" encoding="UTF-8"?>
216
<svg version="1.1" baseProfile="basic" id="svg-root"
217
  width="100%" height="100%" viewBox="0 0 480 360"
218
  xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
219
  <g>
220
    <g opacity="0.5">
221
      <rect x="60" y="230" width="80" height="40" fill="#0000ff" opacity=".5"/>
222
      <rect x="70" y="240" width="80" height="40" fill="#00ff00" opacity=".5"/>
223
    </g>
224
  </g>
225
</svg>
226
"##,
227
    )
228
    .unwrap();
229

            
230
1
    let output_surf = render_document(
231
        &svg,
232
1
        SurfaceSize(500, 380),
233
1
        |cr| cr.translate(10.0, 10.0),
234
1
        cairo::Rectangle::new(0.0, 0.0, 480.0, 360.0),
235
    )
236
    .unwrap();
237

            
238
1
    let reference_surf = cairo::ImageSurface::create(cairo::Format::ARgb32, 500, 380).unwrap();
239

            
240
    {
241
1
        let cr = cairo::Context::new(&reference_surf).expect("Failed to create a cairo context");
242

            
243
1
        cr.translate(10.0, 10.0);
244

            
245
1
        cr.push_group();
246

            
247
1
        cr.rectangle(60.0, 230.0, 80.0, 40.0);
248
1
        cr.set_source_rgba(0.0, 0.0, 1.0, 0.5);
249
1
        cr.fill().unwrap();
250

            
251
1
        cr.rectangle(70.0, 240.0, 80.0, 40.0);
252
1
        cr.set_source_rgba(0.0, 1.0, 0.0, 0.5);
253
1
        cr.fill().unwrap();
254

            
255
1
        cr.pop_group_to_source().unwrap();
256
1
        cr.paint_with_alpha(0.5).unwrap();
257
1
    }
258

            
259
1
    Reference::from_surface(reference_surf)
260
        .compare(&output_surf)
261
1
        .evaluate(&output_surf, "compound_opacity");
262
2
}
263

            
264
#[test]
265
2
fn nested_masks() {
266
1
    let svg = load_svg(
267
        br##"<?xml version="1.0" encoding="UTF-8"?>
268
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="321.00" height="27.00" viewBox="0 0 6420 540">
269
  <defs>
270
    <mask id="Mask_big_ex_small" maskUnits="userSpaceOnUse" x="0" y="0" width="6420" height="540">
271
      <g>
272
	<use xlink:href="#big" fill="white"/>
273
	<use xlink:href="#small" fill="black"/>
274
      </g>
275
    </mask>
276
    <g id="big_ex_small">
277
      <use xlink:href="#big" mask="url(#Mask_big_ex_small)"/>
278
    </g>
279
    <mask id="Region0" maskUnits="userSpaceOnUse" x="0" y="0" width="6420" height="540" fill-rule="nonzero">
280
      <use xlink:href="#big_ex_small" fill="white"/>
281
    </mask>
282
    <rect id="big" x="0" y="0" width="6420" height="540"/>
283
    <rect id="small" x="2760" y="20" width="900" height="480"/>
284
  </defs>
285
  <g mask="url(#Region0)">
286
    <g transform="matrix(1.66667 0 0 1.66667 0 0)">
287
      <rect x="0" y="0" width="6420" height="540" fill="black"/>
288
    </g>
289
  </g>
290
</svg>
291

            
292
"##,
293
    ).unwrap();
294

            
295
1
    let output_surf = render_document(
296
        &svg,
297
1
        SurfaceSize(321 + 20, 27 + 20),
298
1
        |cr| cr.translate(10.0, 10.0),
299
1
        cairo::Rectangle::new(0.0, 0.0, 321.0, 27.0),
300
    )
301
    .unwrap();
302

            
303
    let reference_surf =
304
1
        cairo::ImageSurface::create(cairo::Format::ARgb32, 321 + 20, 27 + 20).unwrap();
305

            
306
    {
307
1
        let cr = cairo::Context::new(&reference_surf).expect("Failed to create a cairo context");
308

            
309
1
        cr.translate(10.0, 10.0);
310
1
        cr.scale(321.0 / 6420.0, 27.0 / 540.0);
311

            
312
1
        cr.set_source_rgba(0.0, 0.0, 0.0, 1.0);
313
1
        cr.rectangle(0.0, 0.0, 6420.0, 540.0);
314
1
        cr.fill().unwrap();
315

            
316
1
        cr.set_operator(cairo::Operator::Clear);
317
1
        cr.rectangle(2760.0, 20.0, 900.0, 480.0);
318
1
        cr.fill().unwrap();
319
1
    }
320

            
321
1
    Reference::from_surface(reference_surf)
322
        .compare(&output_surf)
323
1
        .evaluate(&output_surf, "nested_masks");
324
2
}
325

            
326
test_compare_render_output!(
327
    image_element_with_no_href,
328
    30,
329
    30,
330
    br##"<?xml version="1.0" encoding="UTF-8"?>
331
    <svg xmlns="http://www.w3.org/2000/svg" width="30" height="30">
332
      <image x="10" y="10"/>
333
    </svg>"##,
334
    br##"<?xml version="1.0" encoding="UTF-8"?>
335
    <svg xmlns="http://www.w3.org/2000/svg" width="30" height="30">
336
    </svg>"##,
337
);
338

            
339
test_compare_render_output!(
340
    transform_property,
341
    100,
342
    100,
343
    br##"<?xml version="1.0" encoding="UTF-8"?>
344
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
345
  <rect x="50" y="50" width="20" height="20" fill="black"/>
346
</svg>"##,
347
    br##"<?xml version="1.0" encoding="UTF-8"?>
348
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
349
  <rect x="10" y="10" width="20" height="20" fill="black" style="transform: translate(40px, 40px);"/>
350
</svg>"##,
351
);
352

            
353
test_compare_render_output!(
354
    compound_transform_property,
355
    100,
356
    100,
357
    br##"<?xml version="1.0" encoding="UTF-8"?>
358
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="-30 -30 60 60">
359
  <rect x="0" y="0" width="20" height="20" fill="black" style="transform: translate(-10px, -20px) scale(2) rotate(45deg);"/>
360
</svg>"##,
361
    br##"<?xml version="1.0" encoding="UTF-8"?>
362
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="-30 -30 60 60">
363
  <rect x="0" y="0" width="20" height="20" fill="black" transform="translate(-10 -20) scale(2) rotate(45)"/>
364
</svg>"##,
365
);
366

            
367
test_svg_reference!(
368
    invalid_element_type_for_paint_server,
369
    "tests/fixtures/reftests/invalid-element-type-for-paint-server.svg",
370
    "tests/fixtures/reftests/invalid-element-type-for-paint-server-ref.svg"
371
);