fop_render/pdf/document/
gradient.rs1use fop_types::{ColorStop, Gradient};
6
7pub(super) fn write_gradient_objects(
20 gradient: &Gradient,
21 function_obj_id: usize,
22 shading_obj_id: usize,
23 bytes: &mut Vec<u8>,
24 xref_offsets: &mut Vec<usize>,
25) {
26 match gradient {
27 Gradient::Linear {
28 start_point,
29 end_point,
30 color_stops,
31 } => {
32 if color_stops.len() < 2 {
36 return; }
38
39 write_gradient_function(function_obj_id, color_stops, bytes, xref_offsets);
42
43 xref_offsets.push(bytes.len());
45 bytes.extend_from_slice(format!("{} 0 obj\n", shading_obj_id).as_bytes());
46 bytes.extend_from_slice(b"<<\n");
47 bytes.extend_from_slice(b"/ShadingType 2\n"); bytes.extend_from_slice(b"/ColorSpace /DeviceRGB\n");
49
50 bytes.extend_from_slice(
53 format!(
54 "/Coords [{:.3} {:.3} {:.3} {:.3}]\n",
55 start_point.x.to_pt(),
56 start_point.y.to_pt(),
57 end_point.x.to_pt(),
58 end_point.y.to_pt()
59 )
60 .as_bytes(),
61 );
62
63 bytes.extend_from_slice(format!("/Function {} 0 R\n", function_obj_id).as_bytes());
64 bytes.extend_from_slice(b"/Extend [true true]\n"); bytes.extend_from_slice(b">>\n");
66 bytes.extend_from_slice(b"endobj\n");
67 }
68 Gradient::Radial {
69 center,
70 radius,
71 color_stops,
72 } => {
73 if color_stops.len() < 2 {
75 return;
76 }
77
78 write_gradient_function(function_obj_id, color_stops, bytes, xref_offsets);
80
81 xref_offsets.push(bytes.len());
83 bytes.extend_from_slice(format!("{} 0 obj\n", shading_obj_id).as_bytes());
84 bytes.extend_from_slice(b"<<\n");
85 bytes.extend_from_slice(b"/ShadingType 3\n"); bytes.extend_from_slice(b"/ColorSpace /DeviceRGB\n");
87
88 let center_x = center.x.to_pt();
91 let center_y = center.y.to_pt();
92 let end_radius = radius * 100.0; bytes.extend_from_slice(
95 format!(
96 "/Coords [{:.3} {:.3} 0 {:.3} {:.3} {:.3}]\n",
97 center_x, center_y, center_x, center_y, end_radius
98 )
99 .as_bytes(),
100 );
101
102 bytes.extend_from_slice(format!("/Function {} 0 R\n", function_obj_id).as_bytes());
103 bytes.extend_from_slice(b"/Extend [true true]\n");
104 bytes.extend_from_slice(b">>\n");
105 bytes.extend_from_slice(b"endobj\n");
106 }
107 }
108}
109
110fn write_gradient_function(
115 function_obj_id: usize,
116 color_stops: &[ColorStop],
117 bytes: &mut Vec<u8>,
118 xref_offsets: &mut Vec<usize>,
119) {
120 xref_offsets.push(bytes.len());
121 bytes.extend_from_slice(format!("{} 0 obj\n", function_obj_id).as_bytes());
122 bytes.extend_from_slice(b"<<\n");
123
124 if color_stops.len() == 2 {
125 bytes.extend_from_slice(b"/FunctionType 2\n");
127 bytes.extend_from_slice(b"/Domain [0 1]\n");
128 bytes.extend_from_slice(b"/N 1\n"); let c0 = &color_stops[0].color;
131 let c1 = &color_stops[1].color;
132
133 bytes.extend_from_slice(
134 format!(
135 "/C0 [{:.3} {:.3} {:.3}]\n",
136 c0.r_f32(),
137 c0.g_f32(),
138 c0.b_f32()
139 )
140 .as_bytes(),
141 );
142 bytes.extend_from_slice(
143 format!(
144 "/C1 [{:.3} {:.3} {:.3}]\n",
145 c1.r_f32(),
146 c1.g_f32(),
147 c1.b_f32()
148 )
149 .as_bytes(),
150 );
151 } else {
152 bytes.extend_from_slice(b"/FunctionType 3\n");
154 bytes.extend_from_slice(b"/Domain [0 1]\n");
155
156 bytes.extend_from_slice(b"/Bounds [");
158 for stop in color_stops.iter().skip(1).take(color_stops.len() - 2) {
159 bytes.extend_from_slice(format!("{:.3} ", stop.offset).as_bytes());
160 }
161 bytes.extend_from_slice(b"]\n");
162
163 bytes.extend_from_slice(b"/Encode [");
165 for _ in 0..color_stops.len() - 1 {
166 bytes.extend_from_slice(b"0 1 ");
167 }
168 bytes.extend_from_slice(b"]\n");
169
170 bytes.extend_from_slice(b"/Functions [\n");
172 for i in 0..color_stops.len() - 1 {
173 let c0 = &color_stops[i].color;
174 let c1 = &color_stops[i + 1].color;
175
176 bytes.extend_from_slice(b" <<\n");
177 bytes.extend_from_slice(b" /FunctionType 2\n");
178 bytes.extend_from_slice(b" /Domain [0 1]\n");
179 bytes.extend_from_slice(b" /N 1\n");
180 bytes.extend_from_slice(
181 format!(
182 " /C0 [{:.3} {:.3} {:.3}]\n",
183 c0.r_f32(),
184 c0.g_f32(),
185 c0.b_f32()
186 )
187 .as_bytes(),
188 );
189 bytes.extend_from_slice(
190 format!(
191 " /C1 [{:.3} {:.3} {:.3}]\n",
192 c1.r_f32(),
193 c1.g_f32(),
194 c1.b_f32()
195 )
196 .as_bytes(),
197 );
198 bytes.extend_from_slice(b" >>\n");
199 }
200 bytes.extend_from_slice(b"]\n");
201 }
202
203 bytes.extend_from_slice(b">>\n");
204 bytes.extend_from_slice(b"endobj\n");
205}