1extern crate proc_macro;
2use proc_macro::TokenStream;
3use quote::quote;
4use syn::DeriveInput;
5
6#[proc_macro_derive(Chart)]
7pub fn my_default(input: TokenStream) -> TokenStream {
8 let ast: DeriveInput = syn::parse(input).unwrap();
9 let id = ast.ident;
10
11 let gen = quote! {
12 impl #id {
13 fn fill_theme(&mut self, t: Arc<Theme>) {
15 self.font_family = t.font_family.clone();
16 self.margin = t.margin.clone();
17 self.width = t.width;
18 self.height = t.height;
19 self.background_color = t.background_color;
20 self.is_light = t.is_light;
21
22 self.title_font_color = t.title_font_color;
23 self.title_font_size = t.title_font_size;
24 self.title_font_weight = t.title_font_weight.clone();
25 self.title_margin = t.title_margin.clone();
26 self.title_align = t.title_align.clone();
27 self.title_height = t.title_height;
28
29 self.sub_title_font_color = t.sub_title_font_color;
30 self.sub_title_font_size = t.sub_title_font_size;
31 self.sub_title_margin = t.sub_title_margin.clone();
32 self.sub_title_align = t.sub_title_align.clone();
33 self.sub_title_height = t.sub_title_height;
34
35 self.legend_font_color = t.legend_font_color;
36 self.legend_font_size = t.legend_font_size;
37 self.legend_align = t.legend_align.clone();
38 self.legend_margin = t.legend_margin.clone();
39
40 self.x_axis_font_size = t.x_axis_font_size;
41 self.x_axis_font_color = t.x_axis_font_color;
42 self.x_axis_stroke_color = t.x_axis_stroke_color;
43 self.x_axis_name_gap = t.x_axis_name_gap;
44 self.x_axis_height = t.x_axis_height;
45
46 self.y_axis_configs = vec![
47 YAxisConfig{
48 axis_font_size: t.y_axis_font_size,
49 axis_font_color: t.y_axis_font_color,
50 axis_stroke_color: t.y_axis_stroke_color,
51 axis_split_number: t.y_axis_split_number,
52 axis_name_gap: t.y_axis_name_gap,
53 ..Default::default()
54 }
55 ];
56
57 self.grid_stroke_color = t.grid_stroke_color;
58 self.grid_stroke_width = t.grid_stroke_width;
59
60 self.series_colors = t.series_colors.clone();
61 self.series_label_font_color = t.series_label_font_color;
62 self.series_label_font_size = t.series_label_font_size;
63 self.series_stroke_width = t.series_stroke_width;
64
65 self.series_symbol = Some(Symbol::Circle(
66 self.series_stroke_width,
67 Some(self.background_color),
68 ));
69 }
70 fn fill_option(&mut self, data: &str) -> canvas::Result<serde_json::Value> {
72 let data: serde_json::Value = serde_json::from_str(data)?;
73 let series_list = get_series_list_from_value(&data).unwrap_or_default();
74 let theme = get_string_from_value(&data, "theme").unwrap_or_default();
75 let theme = get_theme(&theme);
76 self.fill_theme(theme.clone());
77 self.series_list = series_list;
78
79 if let Some(width) = get_f32_from_value(&data, "width") {
80 self.width = width;
81 }
82 if let Some(height) = get_f32_from_value(&data, "height") {
83 self.height = height;
84 }
85 if let Some(x) = get_f32_from_value(&data, "x") {
86 self.x = x;
87 }
88 if let Some(y) = get_f32_from_value(&data, "y") {
89 self.y = y;
90 }
91 if let Some(margin) = get_margin_from_value(&data, "margin") {
92 self.margin = margin;
93 }
94 if let Some(font_family) = get_string_from_value(&data, "font_family") {
95 self.font_family = font_family;
96 }
97 if let Some(title_text) = get_string_from_value(&data, "title_text") {
98 self.title_text = title_text;
99 }
100 if let Some(title_font_size) = get_f32_from_value(&data, "title_font_size") {
101 self.title_font_size = title_font_size;
102 }
103 if let Some(title_font_color) = get_color_from_value(&data, "title_font_color") {
104 self.title_font_color = title_font_color;
105 }
106 if let Some(title_font_weight) = get_string_from_value(&data, "title_font_weight") {
107 self.title_font_weight = Some(title_font_weight);
108 }
109 if let Some(title_margin) = get_margin_from_value(&data, "title_margin") {
110 self.title_margin = Some(title_margin);
111 }
112 if let Some(title_align) = get_align_from_value(&data, "title_align") {
113 self.title_align = title_align;
114 }
115 if let Some(title_height) = get_f32_from_value(&data, "title_height") {
116 self.title_height = title_height;
117 }
118
119 if let Some(sub_title_text) = get_string_from_value(&data, "sub_title_text") {
120 self.sub_title_text = sub_title_text;
121 }
122 if let Some(sub_title_font_size) = get_f32_from_value(&data, "sub_title_font_size") {
123 self.sub_title_font_size = sub_title_font_size;
124 }
125 if let Some(sub_title_font_color) = get_color_from_value(&data, "sub_title_font_color") {
126 self.sub_title_font_color = sub_title_font_color;
127 }
128 if let Some(sub_title_font_weight) = get_string_from_value(&data, "sub_title_font_weight") {
129 self.sub_title_font_weight = Some(sub_title_font_weight);
130 }
131 if let Some(sub_title_margin) = get_margin_from_value(&data, "sub_title_margin") {
132 self.sub_title_margin = Some(sub_title_margin);
133 }
134 if let Some(sub_title_align) = get_align_from_value(&data, "sub_title_align") {
135 self.sub_title_align = sub_title_align;
136 }
137 if let Some(sub_title_height) = get_f32_from_value(&data, "sub_title_height") {
138 self.sub_title_height = sub_title_height;
139 }
140
141 if let Some(legend_font_size) = get_f32_from_value(&data, "legend_font_size") {
142 self.legend_font_size = legend_font_size;
143 }
144 if let Some(legend_font_color) = get_color_from_value(&data, "legend_font_color") {
145 self.legend_font_color = legend_font_color;
146 }
147 if let Some(legend_font_weight) = get_string_from_value(&data, "legend_font_weight") {
148 self.legend_font_weight = Some(legend_font_weight);
149 }
150 if let Some(legend_align) = get_align_from_value(&data, "legend_align") {
151 self.legend_align = legend_align;
152 }
153 if let Some(legend_margin) = get_margin_from_value(&data, "legend_margin") {
154 self.legend_margin = Some(legend_margin);
155 }
156 if let Some(legend_category) = get_legend_category_from_value(&data, "legend_category") {
157 self.legend_category = legend_category;
158 }
159 if let Some(legend_show) = get_bool_from_value(&data, "legend_show") {
160 self.legend_show = Some(legend_show);
161 }
162
163 if let Some(x_axis_data) = get_string_slice_from_value(&data, "x_axis_data") {
164 self.x_axis_data = x_axis_data;
165 }
166 if let Some(x_axis_height) = get_f32_from_value(&data, "x_axis_height") {
167 self.x_axis_height = x_axis_height;
168 }
169 if let Some(x_axis_stroke_color) = get_color_from_value(&data, "x_axis_stroke_color") {
170 self.x_axis_stroke_color = x_axis_stroke_color;
171 }
172 if let Some(x_axis_font_size) = get_f32_from_value(&data, "x_axis_font_size") {
173 self.x_axis_font_size = x_axis_font_size;
174 }
175 if let Some(x_axis_font_color) = get_color_from_value(&data, "x_axis_font_color") {
176 self.x_axis_font_color = x_axis_font_color;
177 }
178 if let Some(x_axis_font_weight) = get_string_from_value(&data, "x_axis_font_weight") {
179 self.x_axis_font_weight = Some(x_axis_font_weight);
180 }
181 if let Some(x_axis_name_gap) = get_f32_from_value(&data, "x_axis_name_gap") {
182 self.x_axis_name_gap = x_axis_name_gap;
183 }
184 if let Some(x_axis_name_rotate) = get_f32_from_value(&data, "x_axis_name_rotate") {
185 self.x_axis_name_rotate = x_axis_name_rotate;
186 }
187 if let Some(x_axis_margin) = get_margin_from_value(&data, "x_axis_margin") {
188 self.x_axis_margin = Some(x_axis_margin);
189 }
190 if let Some(x_boundary_gap) = get_bool_from_value(&data, "x_boundary_gap") {
191 self.x_boundary_gap = Some(x_boundary_gap);
192 }
193
194 if let Some(y_axis_configs) = get_y_axis_configs_from_value(theme.clone(), &data, "y_axis_configs") {
195 self.y_axis_configs = y_axis_configs;
196 }
197
198 if let Some(grid_stroke_color) = get_color_from_value(&data, "grid_stroke_color") {
199 self.grid_stroke_color = grid_stroke_color;
200 }
201 if let Some(grid_stroke_width) = get_f32_from_value(&data, "grid_stroke_width") {
202 self.grid_stroke_width = grid_stroke_width;
203 }
204
205 if let Some(series_stroke_width) = get_f32_from_value(&data, "series_stroke_width") {
206 self.series_stroke_width = series_stroke_width;
207 }
208 if let Some(series_label_font_color) =
209 get_color_from_value(&data, "series_label_font_color")
210 {
211 self.series_label_font_color = series_label_font_color;
212 }
213 if let Some(series_label_font_size) = get_f32_from_value(&data, "series_label_font_size") {
214 self.series_label_font_size = series_label_font_size;
215 }
216 if let Some(series_label_font_weight) = get_string_from_value(&data, "series_label_font_weight") {
217 self.series_label_font_weight = Some(series_label_font_weight);
218 }
219 if let Some(series_label_formatter) = get_string_from_value(&data, "series_label_formatter") {
220 self.series_label_formatter = series_label_formatter;
221 }
222
223 if let Some(series_colors) = get_color_slice_from_value(&data, "series_colors") {
224 self.series_colors = series_colors;
225 }
226 if let Some(series_symbol) = get_series_symbol_from_value(&data, "series_symbol") {
227 self.series_symbol = Some(series_symbol);
228 }
229 if let Some(series_smooth) = get_bool_from_value(&data, "series_smooth") {
230 self.series_smooth = series_smooth;
231 }
232 if let Some(series_fill) = get_bool_from_value(&data, "series_fill") {
233 self.series_fill = series_fill;
234 }
235
236 Ok(data)
237 }
238 fn get_y_axis_config(&self, index: usize) -> YAxisConfig {
240 let size = self.y_axis_configs.len();
241 if size == 0 {
242 YAxisConfig::default()
243 } else if index < size {
244 self.y_axis_configs[index].clone()
245 } else {
246 self.y_axis_configs[0].clone()
247 }
248 }
249 fn get_y_axis_values(&self, y_axis_index: usize) -> (AxisValues, f32) {
251 let y_axis_config = self.get_y_axis_config(y_axis_index);
252 let mut data_list = vec![];
253 for series in self.series_list.iter() {
254 if series.y_axis_index == y_axis_index {
255 data_list.append(series.data.clone().as_mut());
256 }
257 }
258 if data_list.is_empty() {
259 return (AxisValues::default(), 0.0);
260 }
261 let mut thousands_format = false;
262 if let Some(ref value) = y_axis_config.axis_formatter {
263 thousands_format = value.contains(THOUSANDS_FORMAT_LABEL);
264 }
265 let y_axis_values = get_axis_values(AxisValueParams {
266 data_list,
267 split_number: y_axis_config.axis_split_number,
268 reverse: Some(true),
269 min: y_axis_config.axis_min,
270 max: y_axis_config.axis_max,
271 thousands_format,
272 });
273 let y_axis_width = if let Some(value) = y_axis_config.axis_width {
274 value
275 } else {
276 let y_axis_formatter = &y_axis_config.axis_formatter.clone().unwrap_or_default();
277 let mut longest_item: &str = "";
278 for item in &y_axis_values.data {
279 if item.chars().count() > longest_item.chars().count() { longest_item = item }
280 }
281 let value = format_string(longest_item, y_axis_formatter);
282 if let Ok(b) = measure_text_width_family(&self.font_family, y_axis_config.axis_font_size, &value)
283 {
284 b.width() + 5.0
285 } else {
286 DEFAULT_Y_AXIS_WIDTH
287 }
288 };
289 (y_axis_values, y_axis_width)
290 }
291 fn render_background(&self, c: Canvas) {
293 if self.background_color.is_transparent() {
294 return;
295 }
296 let mut c1 = c;
297 c1.rect(Rect {
298 fill: Some(self.background_color),
299 left: 0.0,
300 top: 0.0,
301 width: self.width,
302 height: self.height,
303 ..Default::default()
304 });
305 }
306 fn render_title(&self, c: Canvas) -> f32 {
308 let mut title_height = 0.0;
309
310 if !self.title_text.is_empty() {
311 let title_margin = self.title_margin.clone().unwrap_or_default();
312 let mut x = 0.0;
313 if let Ok(title_box) =
314 measure_text_width_family(&self.font_family, self.title_font_size, &self.title_text)
315 {
316 x = match self.title_align {
317 Align::Center => (c.width() - title_box.width()) / 2.0,
318 Align::Right => c.width() - title_box.width(),
319 _ => 0.0,
320 }
321 }
322 let title_margin_bottom = title_margin.bottom;
323 let b = c.child(title_margin).text(Text {
324 text: self.title_text.clone(),
325 font_family: Some(self.font_family.clone()),
326 font_size: Some(self.title_font_size),
327 font_weight: self.title_font_weight.clone(),
328 font_color: Some(self.title_font_color),
329 line_height: Some(self.title_height),
330 x: Some(x),
331 ..Default::default()
332 });
333 title_height = b.outer_height() + title_margin_bottom;
334 }
335 if !self.sub_title_text.is_empty() {
336 let mut sub_title_margin = self.sub_title_margin.clone().unwrap_or_default();
337 let mut x = 0.0;
338 if let Ok(sub_title_box) = measure_text_width_family(
339 &self.font_family,
340 self.sub_title_font_size,
341 &self.sub_title_text,
342 ) {
343 x = match self.sub_title_align {
344 Align::Center => (c.width() - sub_title_box.width()) / 2.0,
345 Align::Right => c.width() - sub_title_box.width(),
346 _ => 0.0,
347 }
348 }
349 let sub_title_margin_bottom = sub_title_margin.bottom;
350 sub_title_margin.top += self.title_height;
351 let b = c.child(sub_title_margin).text(Text {
352 text: self.sub_title_text.clone(),
353 font_family: Some(self.font_family.clone()),
354 font_size: Some(self.sub_title_font_size),
355 font_color: Some(self.sub_title_font_color),
356 line_height: Some(self.sub_title_height),
357 font_weight: self.sub_title_font_weight.clone(),
358 x: Some(x),
359 ..Default::default()
360 });
361 title_height = b.outer_height() + sub_title_margin_bottom;
362 }
363 title_height
364 }
365 fn render_legend(&self, c: Canvas) -> f32 {
367 if !self.legend_show.unwrap_or(true) || self.series_list.is_empty() {
368 return 0.0
369 }
370 let legends: Vec<&str> = self
371 .series_list
372 .iter()
373 .map(|item| item.name.as_str())
374 .collect();
375 let legend_margin = self.legend_margin.clone().unwrap_or_default();
376 let legend_margin_value = legend_margin.top + legend_margin.bottom;
377 let mut legend_canvas = c.child(legend_margin);
378 let legend_canvas_width = legend_canvas.width();
379 let rows = wrap_legends_to_rows(&self.font_family, self.legend_font_size, &legends, legend_canvas_width);
380 let mut current_legend_index = 0;
381 let legend_unit_height = self.legend_font_size + LEGEND_MARGIN;
382 let mut legend_top = 0.0;
383 let row_count = rows.len();
384 for (row_index, (legend_width, legend_texts)) in rows.iter().enumerate() {
385 let mut legend_left = match self.legend_align {
386 Align::Right => legend_canvas_width - legend_width,
387 Align::Left => 0.0,
388 Align::Center => (legend_canvas_width - legend_width) / 2.0,
389 };
390 if legend_left < 0.0 {
391 legend_left = 0.0;
392 }
393 for text in legend_texts.iter() {
394 let index = current_legend_index;
395 current_legend_index += 1;
396 let Some(series) = &self.series_list.get(index) else {
397 continue;
398 };
399 if series.name.is_empty() {
400 continue;
401 }
402 let color = get_color(&self.series_colors, series.index.unwrap_or(index));
403 let fill = if self.is_light {
404 Some(self.background_color)
405 } else {
406 Some(color)
407 };
408 let b = legend_canvas.legend(Legend {
409 text: series.name.to_string(),
410 font_size: self.legend_font_size,
411 font_family: self.font_family.clone(),
412 font_color: Some(self.legend_font_color),
413 font_weight: self.legend_font_weight.clone(),
414 stroke_color: Some(color),
415 fill,
416 left: legend_left,
417 top: legend_top,
418 category: self.legend_category.clone(),
419 });
420 legend_left += b.width() + LEGEND_MARGIN;
421 }
422 if row_index < row_count - 1 {
424 legend_top += legend_unit_height;
425 }
426 }
427 legend_unit_height + legend_top + legend_margin_value
428 }
429 fn render_grid(&self, c: Canvas, axis_width: f32, axis_height: f32) {
432 let mut c1 = c;
433 let y_axis_config = self.get_y_axis_config(0);
434 let axis_split_number = y_axis_config.axis_split_number;
435 c1.grid(Grid {
436 right: axis_width,
437 bottom: axis_height,
438 color: Some(self.grid_stroke_color),
439 stroke_width: self.grid_stroke_width,
440 horizontals: axis_split_number,
441 hidden_horizontals: vec![axis_split_number],
442 ..Default::default()
443 });
444 }
445 fn render_y_axis(&self, c: Canvas, data: Vec<String>, axis_height: f32, axis_width: f32, axis_index: usize) {
447 let mut c1 = c;
448 let y_axis_config = &self.get_y_axis_config(axis_index);
449 let mut position = Position::Left;
450 if axis_index > 0 {
451 position = Position::Right;
452 }
453 let mut name_align = Align::Left;
454 if let Some(value) = &y_axis_config.axis_name_align {
455 name_align = value.clone();
456 }
457 let margin = y_axis_config.axis_margin.clone().unwrap_or_default();
458 c1.child(margin).axis(Axis {
459 position,
460 height: axis_height,
461 width: axis_width,
462 split_number: y_axis_config.axis_split_number,
463 font_family: self.font_family.clone(),
464 stroke_color: Some(y_axis_config.axis_stroke_color),
465 name_align,
466 name_gap: y_axis_config.axis_name_gap,
467 font_color: Some(y_axis_config.axis_font_color),
468 font_size: y_axis_config.axis_font_size,
469 font_weight: y_axis_config.axis_font_weight.clone(),
470 data,
471 formatter: y_axis_config.axis_formatter.clone(),
472 ..Default::default()
473 });
474 }
475 fn render_x_axis(&self, c: Canvas, data: Vec<String>, axis_width: f32) {
478 let mut c1 = c;
479
480 let mut split_number = data.len();
481 let name_align = if self.x_boundary_gap.unwrap_or(true) {
482 Align::Center
483 } else {
484 split_number -= 1;
485 Align::Left
486 };
487 let margin = self.x_axis_margin.clone().unwrap_or_default();
488 c1.child(margin).axis(Axis {
489 height: self.x_axis_height,
490 width: axis_width,
491 split_number,
492 font_family: self.font_family.clone(),
493 data,
494 font_color: Some(self.x_axis_font_color),
495 font_weight: self.x_axis_font_weight.clone(),
496 stroke_color: Some(self.x_axis_stroke_color),
497 font_size: self.x_axis_font_size,
498 name_gap: self.x_axis_name_gap,
499 name_rotate: self.x_axis_name_rotate,
500 name_align,
501 ..Default::default()
502 });
503 }
504 fn render_series_label(&self, c:Canvas, series_labels_list: Vec<Vec<SeriesLabel>>) {
506 if series_labels_list.is_empty() {
507 return;
508 }
509 let mut c1 = c;
510 for series_labels in series_labels_list.iter() {
511 for series_label in series_labels.iter() {
512 let mut dx = None;
513 if let Ok(value) = measure_text_width_family(
514 &self.font_family,
515 self.series_label_font_size,
516 &series_label.text,
517 ) {
518 dx = Some(-value.width() / 2.0);
519 }
520 c1.text(Text {
521 text: series_label.text.clone(),
522 dy: Some(-8.0),
523 dx,
524 font_family: Some(self.font_family.clone()),
525 font_color: Some(self.series_label_font_color),
526 font_size: Some(self.series_label_font_size),
527 font_weight: self.series_label_font_weight.clone(),
528 x: Some(series_label.point.x),
529 y: Some(series_label.point.y),
530 ..Default::default()
531 });
532 }
533 }
534 }
535 fn render_bar(
537 &self,
538 c: Canvas,
539 series_list: &[&Series],
540 y_axis_values_list: &[&AxisValues],
541 max_height: f32,
542 series_data_count: usize,
543 radius: Option<f32>,
544 ) -> Vec<Vec<SeriesLabel>> {
545 if series_list.is_empty() {
546 return vec![];
547 }
548 let mut c1 = c;
549
550 let unit_width = c1.width() / series_data_count as f32;
551 let bar_chart_margin = 5.0_f32;
552 let bar_chart_gap = 3.0_f32;
553
554 let bar_chart_margin_width = bar_chart_margin * 2.0;
555 let bar_chart_gap_width = bar_chart_gap * (series_list.len() - 1) as f32;
556 let bar_width = (unit_width - bar_chart_margin_width - bar_chart_gap_width) / series_list.len() as f32;
557 let half_bar_width = bar_width / 2.0;
558
559 let mut series_labels_list = vec![];
560 let get_bar_color = |colors: &Option<Vec<Option<Color>>>, index: usize| -> Option<Color> {
561 if let Some(colors) = &colors {
562 if colors.len() <= index {
563 return None;
564 }
565 if let Some(color) = colors[index] {
566 return Some(color);
567 }
568 }
569 None
570 };
571 for (index, series) in series_list.iter().enumerate() {
572 let y_axis_values = if index >= y_axis_values_list.len() {
573 y_axis_values_list[0]
574 } else {
575 y_axis_values_list[series.y_axis_index]
576 };
577 let color = get_color(&self.series_colors, series.index.unwrap_or(index));
578 let mut series_labels = vec![];
579 for (i, p) in series.data.iter().enumerate() {
580 let value = p.to_owned();
581 if value == NIL_VALUE {
583 continue;
584 }
585 let mut left = unit_width * (i + series.start_index) as f32 + bar_chart_margin;
586 left += (bar_width + bar_chart_gap) * index as f32;
587
588 let y = y_axis_values.get_offset_height(value, max_height);
589
590 let mut fill = get_bar_color(&series.colors, i);
591 if fill.is_none() {
592 fill = Some(color);
593 }
594
595 c1.rect(Rect {
596 fill,
597 left,
598 top: y,
599 width: bar_width,
600 height: max_height - y,
601 rx: radius,
602 ry: radius,
603 ..Default::default()
604 });
605 series_labels.push(SeriesLabel{
606 point: (left + half_bar_width, y).into(),
607 text: format_series_value(p.to_owned(), &self.series_label_formatter),
608 })
609 }
610 if series.label_show {
611 series_labels_list.push(series_labels);
612 }
613 }
614 series_labels_list
615 }
616 fn render_line(
618 &self,
619 c: Canvas,
620 series_list: &[&Series],
621 y_axis_values_list: &[&AxisValues],
622 max_height: f32,
623 axis_height: f32,
624 series_data_count: usize,
625 ) -> Vec<Vec<SeriesLabel>> {
626 if series_list.is_empty() {
627 return vec![];
628 }
629 let mut c1 = c;
630 let x_boundary_gap = self.x_boundary_gap.unwrap_or(true);
631 let mut split_unit_offset = 0.0;
632 if !x_boundary_gap {
633 split_unit_offset = 1.0;
634 }
635 let mut series_labels_list = vec![];
636
637 for (index, series) in series_list.iter().enumerate() {
638 let y_axis_values = if series.y_axis_index >= y_axis_values_list.len() {
639 y_axis_values_list[0]
640 } else {
641 y_axis_values_list[series.y_axis_index]
642 };
643 let split_unit_count = series_data_count as f32 - split_unit_offset;
644 let unit_width = c1.width() / split_unit_count;
645 let mut points: Vec<Point> = vec![];
646 let mut points_list: Vec<Vec<Point>> = vec![];
647 let mut series_labels = vec![];
648
649 let mut max_value = f32::MIN;
650 let mut min_value = f32::MAX;
651 let mut max_index = 0;
652 let mut min_index = 0;
653 for (i, p) in series.data.iter().enumerate() {
654 let value = p.to_owned();
655 if value == NIL_VALUE {
656 if !points.is_empty() {
657 points_list.push(points);
658 points = vec![];
659 }
660 continue;
661 }
662 if value > max_value {
663 max_value = value;
664 max_index = i;
665 }
666 if value < min_value {
667 min_value = value;
668 min_index = i;
669 }
670 let mut x = unit_width * (i + series.start_index) as f32;
672 if x_boundary_gap {
673 x += unit_width / 2.0;
674 }
675 let y = y_axis_values.get_offset_height(value, max_height);
676 points.push((x, y).into());
677 series_labels.push(SeriesLabel{
678 point: (x, y).into(),
679 text: format_series_value(value, &self.series_label_formatter),
680 })
681 }
682 if series.label_show {
683 series_labels_list.push(series_labels.clone());
684 }
685 if !points.is_empty() {
686 points_list.push(points);
687 }
688
689 let color = get_color(&self.series_colors, series.index.unwrap_or(index));
690
691 let fill = color.with_alpha(100);
692 let series_fill = self.series_fill;
693 for points in points_list.iter() {
694 if self.series_smooth {
695 if series_fill {
696 c1.smooth_line_fill(SmoothLineFill {
697 fill,
698 points: points.clone(),
699 bottom: axis_height,
700 });
701 }
702 c1.smooth_line(SmoothLine {
703 points: points.clone(),
704 color: Some(color),
705 stroke_width: self.series_stroke_width,
706 symbol: self.series_symbol.clone(),
707 stroke_dash_array: series.stroke_dash_array.clone(),
708 });
709 } else {
710 if series_fill {
711 c1.straight_line_fill(StraightLineFill {
712 fill,
713 points: points.clone(),
714 bottom: axis_height,
715 ..Default::default()
716 });
717 }
718 c1.straight_line(StraightLine {
719 points: points.clone(),
720 color: Some(color),
721 stroke_width: self.series_stroke_width,
722 symbol: self.series_symbol.clone(),
723 stroke_dash_array: series.stroke_dash_array.clone(),
724 ..Default::default()
725 });
726 }
727 }
728 for mark_point in series.mark_points.iter() {
729 let index = match mark_point.category {
730 MarkPointCategory::Max => max_index,
731 MarkPointCategory::Min => min_index,
732 };
733 if let Some(ref label) = series_labels.get(index) {
734 let r = 15.0;
735 let y = label.point.y - r * 2.0;
736 c1.bubble(Bubble{
737 x: label.point.x,
738 y,
739 r,
740 fill: color,
741 });
742 let mut dx = None;
743 if let Ok(value) = measure_text_width_family(
744 &self.font_family,
745 self.series_label_font_size,
746 &label.text,
747 ) {
748 dx = Some(-value.width() / 2.0 + 1.0);
749 }
750 let font_color = if color.is_light() {
751 "#464646".into()
752 } else {
753 "#D8D9DA".into()
754 };
755 c1.text(Text {
756 text: label.text.clone(),
757 line_height: Some(r) ,
758 dx,
759 font_color: Some(font_color),
760 font_family: Some(self.font_family.clone()),
761 font_size: Some(self.series_label_font_size),
762 x: Some(label.point.x),
763 y: Some(y - r * 0.5 + 2.0),
764 ..Default::default()
765 });
766 }
767 }
768
769 }
770 series_labels_list
771 }
772 }
773 };
774 gen.into()
775}