Skip to main content

webrender/pattern/
box_shadow.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5use api::{BorderRadius, BoxShadowClipMode};
6use api::units::*;
7use api::ColorF;
8use crate::pattern::{Pattern, PatternBuilder, PatternBuilderContext, PatternBuilderState, PatternKind, PatternShaderInput, PatternTextureInput};
9use crate::render_task_graph::RenderTaskId;
10use crate::renderer::BlendMode;
11
12pub struct BoxShadowPatternData {
13    pub color: ColorF,
14    pub render_task: RenderTaskId,
15    /// Full blur alloc size in local pixels (= 2*blur_region + src_rect_size per axis).
16    /// Used as the UV denominator so shadow_pos/alloc_size maps 1:1 to texture position.
17    pub shadow_rect_alloc_size: LayoutSize,
18    /// Size of dest_rect in local pixels. For outset this equals shadow_rect_alloc_size
19    /// (prim_rect == dest_rect). For inset the prim is the element rect while dest_rect
20    /// is smaller (the shadow area), so these differ.
21    pub dest_rect_size: LayoutSize,
22    /// Offset of dest_rect.p0 relative to prim_rect.p0 in local pixels.
23    /// Zero for outset. For inset: dest_rect.min - element_rect.min.
24    pub dest_rect_offset: LayoutVector2D,
25    pub clip_mode: BoxShadowClipMode,
26    /// Offset of the element rect's min corner relative to prim_rect.p0.
27    /// Zero for inset (prim_rect IS the element rect). For outset: element_rect.min - dest_rect.min.
28    pub element_offset_rel_prim: LayoutVector2D,
29    pub element_size: LayoutSize,
30    pub element_radius: BorderRadius,
31}
32
33impl PatternBuilder for BoxShadowPatternData {
34    fn build(
35        &self,
36        _sub_rect: Option<DeviceRect>,
37        _offset: LayoutVector2D,
38        _ctx: &PatternBuilderContext,
39        state: &mut PatternBuilderState,
40    ) -> Pattern {
41        let mut writer = state.frame_gpu_data.f32.write_blocks(5);
42        writer.push_one([
43            self.shadow_rect_alloc_size.width,
44            self.shadow_rect_alloc_size.height,
45            self.dest_rect_size.width,
46            self.dest_rect_size.height,
47        ]);
48        writer.push_one([
49            self.dest_rect_offset.x,
50            self.dest_rect_offset.y,
51            if self.clip_mode == BoxShadowClipMode::Inset { 1.0 } else { 0.0 },
52            0.0,
53        ]);
54        writer.push_one([
55            self.element_offset_rel_prim.x,
56            self.element_offset_rel_prim.y,
57            self.element_size.width,
58            self.element_size.height,
59        ]);
60        writer.push_one([
61            self.element_radius.top_left.width,
62            self.element_radius.top_left.height,
63            self.element_radius.top_right.width,
64            self.element_radius.top_right.height,
65        ]);
66        writer.push_one([
67            self.element_radius.bottom_right.width,
68            self.element_radius.bottom_right.height,
69            self.element_radius.bottom_left.width,
70            self.element_radius.bottom_left.height,
71        ]);
72        let addr = writer.finish();
73
74        Pattern {
75            kind: PatternKind::BoxShadow,
76            shader_input: PatternShaderInput(addr.as_int(), 0),
77            texture_input: PatternTextureInput::new(self.render_task),
78            base_color: self.color,
79            is_opaque: false,
80            blend_mode: BlendMode::PremultipliedAlpha,
81        }
82    }
83}