webrender/prim_store/gradient/
mod.rs1use api::{ColorF, ColorU, GradientStop};
6use api::units::{LayoutRect, LayoutSize, LayoutVector2D};
7use std::hash;
8
9mod linear;
10mod radial;
11mod conic;
12
13pub use linear::*;
14pub use radial::*;
15pub use conic::*;
16
17#[cfg_attr(feature = "capture", derive(Serialize))]
19#[cfg_attr(feature = "replay", derive(Deserialize))]
20#[derive(Debug, Copy, Clone, MallocSizeOf, PartialEq)]
21pub struct GradientStopKey {
22 pub offset: f32,
23 pub color: ColorU,
24}
25
26impl GradientStopKey {
27 pub fn empty() -> Self {
28 GradientStopKey {
29 offset: 0.0,
30 color: ColorU::new(0, 0, 0, 0),
31 }
32 }
33}
34
35impl Into<GradientStopKey> for GradientStop {
36 fn into(self) -> GradientStopKey {
37 GradientStopKey {
38 offset: self.offset,
39 color: self.color.into(),
40 }
41 }
42}
43
44fn stops_and_min_alpha(stop_keys: &[GradientStopKey]) -> (Vec<GradientStop>, f32) {
48 let mut min_alpha: f32 = 1.0;
49 let stops = stop_keys.iter().map(|stop_key| {
50 let color: ColorF = stop_key.color.into();
51 min_alpha = min_alpha.min(color.a);
52
53 GradientStop {
54 offset: stop_key.offset,
55 color,
56 }
57 }).collect();
58
59 (stops, min_alpha)
60}
61
62impl Eq for GradientStopKey {}
63
64impl hash::Hash for GradientStopKey {
65 fn hash<H: hash::Hasher>(&self, state: &mut H) {
66 self.offset.to_bits().hash(state);
67 self.color.hash(state);
68 }
69}
70
71pub fn apply_gradient_local_clip(
77 prim_rect: &mut LayoutRect,
78 stretch_size: &LayoutSize,
79 tile_spacing: &LayoutSize,
80 clip_rect: &LayoutRect,
81) -> LayoutVector2D {
82 let w = prim_rect.max.x.min(clip_rect.max.x) - prim_rect.min.x;
83 let h = prim_rect.max.y.min(clip_rect.max.y) - prim_rect.min.y;
84 let is_tiled_x = w > stretch_size.width + tile_spacing.width;
85 let is_tiled_y = h > stretch_size.height + tile_spacing.height;
86
87 let mut offset = LayoutVector2D::new(0.0, 0.0);
88
89 if !is_tiled_x {
90 let diff = (clip_rect.min.x - prim_rect.min.x).min(prim_rect.width());
91 if diff > 0.0 {
92 prim_rect.min.x += diff;
93 offset.x = -diff;
94 }
95
96 let diff = prim_rect.max.x - clip_rect.max.x;
97 if diff > 0.0 {
98 prim_rect.max.x -= diff;
99 }
100 }
101
102 if !is_tiled_y {
103 let diff = (clip_rect.min.y - prim_rect.min.y).min(prim_rect.height());
104 if diff > 0.0 {
105 prim_rect.min.y += diff;
106 offset.y = -diff;
107 }
108
109 let diff = prim_rect.max.y - clip_rect.max.y;
110 if diff > 0.0 {
111 prim_rect.max.y -= diff;
112 }
113 }
114
115 offset
116}
117
118#[test]
119#[cfg(target_pointer_width = "64")]
120fn test_struct_sizes() {
121 use std::mem;
122 assert_eq!(mem::size_of::<LinearGradient>(), 72, "LinearGradient size changed");
129 assert_eq!(mem::size_of::<LinearGradientTemplate>(), 80, "LinearGradientTemplate size changed");
130 assert_eq!(mem::size_of::<LinearGradientKey>(), 72, "LinearGradientKey size changed");
131
132 assert_eq!(mem::size_of::<RadialGradient>(), 72, "RadialGradient size changed");
133 assert_eq!(mem::size_of::<RadialGradientTemplate>(), 80, "RadialGradientTemplate size changed");
134 assert_eq!(mem::size_of::<RadialGradientKey>(), 72, "RadialGradientKey size changed");
135
136 assert_eq!(mem::size_of::<ConicGradient>(), 72, "ConicGradient size changed");
137 assert_eq!(mem::size_of::<ConicGradientTemplate>(), 80, "ConicGradientTemplate size changed");
138 assert_eq!(mem::size_of::<ConicGradientKey>(), 72, "ConicGradientKey size changed");
139}