1#[cfg(not(target_arch = "wasm32"))]
2use plotters::prelude::IntoDrawingArea;
3
4use crate::aes::Aes;
5use crate::annotate::Annotation;
6use crate::build::PlotBuilder;
7use crate::coord::cartesian::CoordCartesian;
8use crate::coord::fixed::CoordFixed;
9use crate::coord::flip::CoordFlip;
10use crate::coord::polar::CoordPolar;
11use crate::coord::Coord;
12use crate::data::{DataFrame, GGData};
13use crate::facet::{Facet, FacetLabeller, FacetScales, FacetSpace};
14use crate::geom::area::GeomArea;
15use crate::geom::bar::GeomBar;
16use crate::geom::bin2d::GeomBin2d;
17use crate::geom::blank::GeomBlank;
18use crate::geom::boxplot::GeomBoxplot;
19use crate::geom::col::GeomCol;
20use crate::geom::contour::GeomContour;
21use crate::geom::count::GeomCount;
22use crate::geom::crossbar::GeomCrossbar;
23use crate::geom::curve::GeomCurve;
24use crate::geom::density::GeomDensity;
25use crate::geom::density2d::GeomDensity2d;
26use crate::geom::dotplot::GeomDotplot;
27use crate::geom::errorbar::GeomErrorbar;
28use crate::geom::freqpoly::GeomFreqpoly;
29use crate::geom::hex::GeomHex;
30use crate::geom::histogram::GeomHistogram;
31use crate::geom::jitter::GeomJitter;
32use crate::geom::line::GeomLine;
33use crate::geom::linerange::GeomLinerange;
34use crate::geom::path::GeomPath;
35use crate::geom::point::GeomPoint;
36use crate::geom::pointrange::GeomPointrange;
37use crate::geom::polygon::GeomPolygon;
38use crate::geom::qq::{GeomQQ, GeomQQLine};
39use crate::geom::rect::GeomRect;
40use crate::geom::refline::{GeomAbline, GeomHline, GeomVline};
41use crate::geom::ribbon::GeomRibbon;
42use crate::geom::rug::GeomRug;
43use crate::geom::segment::GeomSegment;
44use crate::geom::smooth::GeomSmooth;
45use crate::geom::spoke::GeomSpoke;
46use crate::geom::step::GeomStep;
47use crate::geom::text::{GeomLabel, GeomText};
48use crate::geom::tile::GeomTile;
49use crate::geom::violin::GeomViolin;
50use crate::geom::{Geom, GeomParams};
51use crate::position::Position;
52use crate::render::layout::PlotLayout;
53#[cfg(not(target_arch = "wasm32"))]
54use crate::render::plotters_backend::PlottersAdapter;
55use crate::render::renderer::PlotRenderer;
56use crate::render::RenderError;
57use crate::scale::continuous::ScaleContinuous;
58use crate::scale::transform::ScaleTransform;
59use crate::scale::Scale;
60use crate::stat::Stat;
61use crate::theme::Theme;
62
63#[derive(Clone, Debug, Default)]
65pub struct Labels {
66 pub title: Option<String>,
67 pub subtitle: Option<String>,
68 pub x: Option<String>,
69 pub y: Option<String>,
70 pub caption: Option<String>,
71 pub tag: Option<String>,
73}
74
75pub struct Layer {
77 pub data: Option<DataFrame>,
78 pub mapping: Aes,
79 pub geom: Box<dyn Geom>,
80 pub stat: Box<dyn Stat>,
81 pub position: Box<dyn Position>,
82 pub params: GeomParams,
83 pub show_legend: Option<bool>,
84}
85
86pub struct GGPlot {
88 pub(crate) data: DataFrame,
89 pub(crate) mapping: Aes,
90 pub(crate) layers: Vec<Layer>,
91 pub(crate) scales: Vec<Box<dyn Scale>>,
92 pub(crate) coord: Box<dyn Coord>,
93 pub(crate) theme: Theme,
94 pub(crate) labels: Labels,
95 pub(crate) facet: Facet,
96 pub(crate) annotations: Vec<Annotation>,
97 pub(crate) guide_legend: crate::guide::config::GuideLegend,
98}
99
100impl GGPlot {
101 pub fn new(data: impl GGData) -> Self {
103 GGPlot {
104 data: data.into_dataframe(),
105 mapping: Aes::default(),
106 layers: Vec::new(),
107 scales: Vec::new(),
108 coord: Box::new(CoordCartesian::new()),
109 theme: Theme::default(),
110 labels: Labels::default(),
111 facet: Facet::default(),
112 annotations: Vec::new(),
113 guide_legend: crate::guide::config::GuideLegend::default(),
114 }
115 }
116
117 pub fn aes(mut self, mapping: Aes) -> Self {
119 self.mapping = mapping;
120 self
121 }
122
123 pub fn geom_point(self) -> Self {
126 self.add_geom(GeomPoint::default())
127 }
128
129 pub fn geom_point_with(self, geom: GeomPoint) -> Self {
130 self.add_geom(geom)
131 }
132
133 pub fn geom_line(self) -> Self {
134 self.add_geom(GeomLine::default())
135 }
136
137 pub fn geom_line_with(self, geom: GeomLine) -> Self {
138 self.add_geom(geom)
139 }
140
141 pub fn geom_bar(self) -> Self {
142 self.add_geom(GeomBar::default())
143 }
144
145 pub fn geom_bar_with(self, geom: GeomBar) -> Self {
146 self.add_geom(geom)
147 }
148
149 pub fn geom_histogram(self) -> Self {
150 self.add_geom(GeomHistogram::default())
151 }
152
153 pub fn geom_histogram_with(self, geom: GeomHistogram) -> Self {
154 self.add_geom(geom)
155 }
156
157 pub fn geom_boxplot(self) -> Self {
158 self.add_geom(GeomBoxplot::default())
159 }
160
161 pub fn geom_boxplot_with(self, geom: GeomBoxplot) -> Self {
162 self.add_geom(geom)
163 }
164
165 pub fn geom_smooth(self) -> Self {
166 self.add_geom(GeomSmooth::default())
167 }
168
169 pub fn geom_smooth_with(self, geom: GeomSmooth) -> Self {
170 self.add_geom(geom)
171 }
172
173 pub fn geom_col(self) -> Self {
174 self.add_geom(GeomCol::default())
175 }
176
177 pub fn geom_col_with(self, geom: GeomCol) -> Self {
178 self.add_geom(geom)
179 }
180
181 pub fn geom_hline(self, yintercept: f64) -> Self {
182 self.add_geom(GeomHline::new(yintercept))
183 }
184
185 pub fn geom_hline_with(self, geom: GeomHline) -> Self {
187 self.add_geom(geom)
188 }
189
190 pub fn geom_vline(self, xintercept: f64) -> Self {
191 self.add_geom(GeomVline::new(xintercept))
192 }
193
194 pub fn geom_vline_with(self, geom: GeomVline) -> Self {
196 self.add_geom(geom)
197 }
198
199 pub fn geom_abline(self, slope: f64, intercept: f64) -> Self {
200 self.add_geom(GeomAbline::new(slope, intercept))
201 }
202
203 pub fn geom_abline_with(self, geom: GeomAbline) -> Self {
205 self.add_geom(geom)
206 }
207
208 pub fn geom_text(self) -> Self {
209 self.add_geom(GeomText::default())
210 }
211
212 pub fn geom_text_with(self, geom: GeomText) -> Self {
213 self.add_geom(geom)
214 }
215
216 pub fn geom_label(self) -> Self {
217 self.add_geom(GeomLabel::default())
218 }
219
220 pub fn geom_label_with(self, geom: GeomLabel) -> Self {
221 self.add_geom(geom)
222 }
223
224 pub fn geom_area(self) -> Self {
225 self.add_geom(GeomArea::default())
226 }
227
228 pub fn geom_area_with(self, geom: GeomArea) -> Self {
229 self.add_geom(geom)
230 }
231
232 pub fn geom_ribbon(self) -> Self {
233 self.add_geom(GeomRibbon::default())
234 }
235
236 pub fn geom_ribbon_with(self, geom: GeomRibbon) -> Self {
237 self.add_geom(geom)
238 }
239
240 pub fn geom_errorbar(self) -> Self {
241 self.add_geom(GeomErrorbar::default())
242 }
243
244 pub fn geom_errorbar_with(self, geom: GeomErrorbar) -> Self {
245 self.add_geom(geom)
246 }
247
248 pub fn geom_segment(self) -> Self {
249 self.add_geom(GeomSegment::default())
250 }
251
252 pub fn geom_segment_with(self, geom: GeomSegment) -> Self {
253 self.add_geom(geom)
254 }
255
256 pub fn geom_density(self) -> Self {
257 self.add_geom(GeomDensity::default())
258 }
259
260 pub fn geom_density_with(self, geom: GeomDensity) -> Self {
261 self.add_geom(geom)
262 }
263
264 pub fn geom_rug(self) -> Self {
265 self.add_geom(GeomRug::default())
266 }
267
268 pub fn geom_rug_with(self, geom: GeomRug) -> Self {
269 self.add_geom(geom)
270 }
271
272 pub fn geom_jitter(self) -> Self {
273 self.add_geom(GeomJitter::default())
274 }
275
276 pub fn geom_jitter_with(self, geom: GeomJitter) -> Self {
277 self.add_geom(geom)
278 }
279
280 pub fn geom_path(self) -> Self {
281 self.add_geom(GeomPath::default())
282 }
283
284 pub fn geom_path_with(self, geom: GeomPath) -> Self {
285 self.add_geom(geom)
286 }
287
288 pub fn stat_ellipse(self) -> Self {
290 self.geom_path()
291 .stat(crate::stat::ellipse::StatEllipse::default())
292 }
293
294 pub fn stat_ellipse_level(self, level: f64) -> Self {
296 self.geom_path()
297 .stat(crate::stat::ellipse::StatEllipse::new(level))
298 }
299
300 #[cfg(feature = "regression")]
303 pub fn stat_quantile(mut self, taus: &[f64]) -> Self {
304 for &tau in taus {
305 self = self
306 .geom_path()
307 .stat(crate::stat::quantile::StatQuantile::new(tau));
308 }
309 self
310 }
311
312 #[cfg(feature = "regression")]
314 pub fn geom_quantile(self) -> Self {
315 self.stat_quantile(&[0.25, 0.5, 0.75])
316 }
317
318 pub fn geom_step(self) -> Self {
319 self.add_geom(GeomStep::default())
320 }
321
322 pub fn geom_step_with(self, geom: GeomStep) -> Self {
323 self.add_geom(geom)
324 }
325
326 pub fn geom_freqpoly(self) -> Self {
327 self.add_geom(GeomFreqpoly::default())
328 }
329
330 pub fn geom_freqpoly_with(self, geom: GeomFreqpoly) -> Self {
331 self.add_geom(geom)
332 }
333
334 pub fn geom_linerange(self) -> Self {
335 self.add_geom(GeomLinerange::default())
336 }
337
338 pub fn geom_linerange_with(self, geom: GeomLinerange) -> Self {
339 self.add_geom(geom)
340 }
341
342 pub fn geom_pointrange(self) -> Self {
343 self.add_geom(GeomPointrange::default())
344 }
345
346 pub fn geom_pointrange_with(self, geom: GeomPointrange) -> Self {
347 self.add_geom(geom)
348 }
349
350 pub fn geom_crossbar(self) -> Self {
351 self.add_geom(GeomCrossbar::default())
352 }
353
354 pub fn geom_crossbar_with(self, geom: GeomCrossbar) -> Self {
355 self.add_geom(geom)
356 }
357
358 pub fn geom_spoke(self) -> Self {
359 self.add_geom(GeomSpoke::default())
360 }
361
362 pub fn geom_spoke_with(self, geom: GeomSpoke) -> Self {
363 self.add_geom(geom)
364 }
365
366 pub fn geom_rect(self) -> Self {
367 self.add_geom(GeomRect::default())
368 }
369
370 pub fn geom_rect_with(self, geom: GeomRect) -> Self {
371 self.add_geom(geom)
372 }
373
374 pub fn geom_tile(self) -> Self {
375 self.add_geom(GeomTile::default())
376 }
377
378 pub fn geom_tile_with(self, geom: GeomTile) -> Self {
379 self.add_geom(geom)
380 }
381
382 pub fn geom_raster(self) -> Self {
384 self.add_geom(crate::geom::raster::GeomRaster::default())
385 }
386
387 pub fn geom_raster_with(self, geom: crate::geom::raster::GeomRaster) -> Self {
388 self.add_geom(geom)
389 }
390
391 pub fn geom_polygon(self) -> Self {
392 self.add_geom(GeomPolygon::default())
393 }
394
395 pub fn geom_polygon_with(self, geom: GeomPolygon) -> Self {
396 self.add_geom(geom)
397 }
398
399 #[cfg(feature = "sf")]
401 pub fn geom_sf(self) -> Self {
402 self.add_geom(crate::geom::sf::GeomSf::default())
403 }
404
405 #[cfg(feature = "sf")]
406 pub fn geom_sf_with(self, geom: crate::geom::sf::GeomSf) -> Self {
407 self.add_geom(geom)
408 }
409
410 pub fn geom_curve(self) -> Self {
411 self.add_geom(GeomCurve::default())
412 }
413
414 pub fn geom_curve_with(self, geom: GeomCurve) -> Self {
415 self.add_geom(geom)
416 }
417
418 pub fn geom_violin(self) -> Self {
419 self.add_geom(GeomViolin::default())
420 }
421
422 pub fn geom_violin_with(self, geom: GeomViolin) -> Self {
423 self.add_geom(geom)
424 }
425
426 pub fn geom_dotplot(self) -> Self {
427 self.add_geom(GeomDotplot::default())
428 }
429
430 pub fn geom_dotplot_with(self, geom: GeomDotplot) -> Self {
431 self.add_geom(geom)
432 }
433
434 pub fn geom_qq(self) -> Self {
435 self.add_geom(GeomQQ::default())
436 }
437
438 pub fn geom_qq_with(self, geom: GeomQQ) -> Self {
439 self.add_geom(geom)
440 }
441
442 pub fn geom_qq_line(self) -> Self {
443 self.add_geom(GeomQQLine::default())
444 }
445
446 pub fn geom_qq_line_with(self, geom: GeomQQLine) -> Self {
447 self.add_geom(geom)
448 }
449
450 pub fn geom_bin2d(self) -> Self {
451 self.add_geom(GeomBin2d::default())
452 }
453
454 pub fn geom_bin2d_with(self, geom: GeomBin2d) -> Self {
455 self.add_geom(geom)
456 }
457
458 pub fn geom_hex(self) -> Self {
459 self.add_geom(GeomHex::default())
460 }
461
462 pub fn geom_hex_with(self, geom: GeomHex) -> Self {
463 self.add_geom(geom)
464 }
465
466 pub fn geom_count(self) -> Self {
467 self.add_geom(GeomCount::default())
468 }
469
470 pub fn geom_count_with(self, geom: GeomCount) -> Self {
471 self.add_geom(geom)
472 }
473
474 pub fn geom_contour(self) -> Self {
475 self.add_geom(GeomContour::default())
476 }
477
478 pub fn geom_contour_with(self, geom: GeomContour) -> Self {
479 self.add_geom(geom)
480 }
481
482 pub fn geom_contour_filled(self) -> Self {
485 self.add_geom(GeomPolygon {
486 line_width: 0.0,
487 alpha: 1.0,
488 ..GeomPolygon::default()
489 })
490 .stat(crate::stat::contour_filled::StatContourFilled::default())
491 }
492
493 pub fn geom_density2d(self) -> Self {
494 self.add_geom(GeomDensity2d::default())
495 }
496
497 pub fn geom_density2d_with(self, geom: GeomDensity2d) -> Self {
498 self.add_geom(geom)
499 }
500
501 pub fn geom_blank(self) -> Self {
502 self.add_geom(GeomBlank)
503 }
504
505 fn add_geom(mut self, geom: impl Geom + 'static) -> Self {
506 let stat = geom.default_stat();
507 let position = geom.default_position();
508 let params = geom.default_params();
509 self.layers.push(Layer {
510 data: None,
511 mapping: Aes::default(),
512 geom: Box::new(geom),
513 stat,
514 position,
515 params,
516 show_legend: None,
517 });
518 self
519 }
520
521 pub fn stat(mut self, stat: impl Stat + 'static) -> Self {
525 if let Some(layer) = self.layers.last_mut() {
526 layer.stat = Box::new(stat);
527 }
528 self
529 }
530
531 pub fn position(mut self, pos: impl Position + 'static) -> Self {
533 if let Some(layer) = self.layers.last_mut() {
534 layer.position = Box::new(pos);
535 }
536 self
537 }
538
539 pub fn layer_data(mut self, data: impl GGData) -> Self {
541 if let Some(layer) = self.layers.last_mut() {
542 layer.data = Some(data.into_dataframe());
543 }
544 self
545 }
546
547 pub fn layer_aes(mut self, mapping: Aes) -> Self {
549 if let Some(layer) = self.layers.last_mut() {
550 layer.mapping = mapping;
551 }
552 self
553 }
554
555 pub fn show_legend(mut self, show: bool) -> Self {
558 if let Some(layer) = self.layers.last_mut() {
559 layer.show_legend = Some(show);
560 }
561 self
562 }
563
564 pub fn scale_x_continuous(mut self, s: ScaleContinuous) -> Self {
567 let s = s.for_aesthetic(crate::aes::Aesthetic::X);
568 self.scales.push(Box::new(s));
569 self
570 }
571
572 pub fn scale_y_continuous(mut self, s: ScaleContinuous) -> Self {
573 let s = s.for_aesthetic(crate::aes::Aesthetic::Y);
574 self.scales.push(Box::new(s));
575 self
576 }
577
578 pub fn scale_x_discrete(mut self, s: crate::scale::discrete::ScaleDiscrete) -> Self {
579 let s = s.for_aesthetic(crate::aes::Aesthetic::X);
580 self.scales.push(Box::new(s));
581 self
582 }
583
584 pub fn scale_y_discrete(mut self, s: crate::scale::discrete::ScaleDiscrete) -> Self {
585 let s = s.for_aesthetic(crate::aes::Aesthetic::Y);
586 self.scales.push(Box::new(s));
587 self
588 }
589
590 pub fn scale_color(mut self, s: impl Scale + 'static) -> Self {
591 self.scales.push(Box::new(s));
592 self
593 }
594
595 pub fn scale_fill(mut self, s: impl Scale + 'static) -> Self {
596 self.scales.push(Box::new(s));
597 self
598 }
599
600 pub fn scale_color_manual(self, values: Vec<(&str, crate::scale::color::RGBAColor)>) -> Self {
601 let s = crate::scale::manual::ScaleManual::new(crate::aes::Aesthetic::Color, values);
602 self.scale_color(s)
603 }
604
605 pub fn scale_fill_manual(self, values: Vec<(&str, crate::scale::color::RGBAColor)>) -> Self {
606 let s = crate::scale::manual::ScaleManual::new(crate::aes::Aesthetic::Fill, values);
607 self.scale_fill(s)
608 }
609
610 pub fn scale_color_viridis(self) -> Self {
611 use crate::scale::color::ScaleColorDiscrete;
612 use crate::scale::palettes::PaletteName;
613 let s = ScaleColorDiscrete::new(crate::aes::Aesthetic::Color)
614 .with_named_palette(&PaletteName::Viridis);
615 self.scale_color(s)
616 }
617
618 pub fn scale_color_brewer(self, name: crate::scale::palettes::PaletteName) -> Self {
619 use crate::scale::color::ScaleColorDiscrete;
620 let s = ScaleColorDiscrete::new(crate::aes::Aesthetic::Color).with_named_palette(&name);
621 self.scale_color(s)
622 }
623
624 pub fn scale_color_gradient(
625 self,
626 low: crate::scale::color::RGBAColor,
627 high: crate::scale::color::RGBAColor,
628 ) -> Self {
629 use crate::scale::color::ScaleColorContinuous;
630 let s = ScaleColorContinuous::new(crate::aes::Aesthetic::Color).with_colors(low, high);
631 self.scale_color(s)
632 }
633
634 pub fn scale_fill_gradient(
635 self,
636 low: crate::scale::color::RGBAColor,
637 high: crate::scale::color::RGBAColor,
638 ) -> Self {
639 use crate::scale::color::ScaleColorContinuous;
640 let s = ScaleColorContinuous::new(crate::aes::Aesthetic::Fill).with_colors(low, high);
641 self.scale_fill(s)
642 }
643
644 pub fn scale_color_gradient2(
645 self,
646 low: crate::scale::color::RGBAColor,
647 mid: crate::scale::color::RGBAColor,
648 high: crate::scale::color::RGBAColor,
649 ) -> Self {
650 use crate::scale::gradient::ScaleColorGradient2;
651 let s = ScaleColorGradient2::new(crate::aes::Aesthetic::Color).with_colors(low, mid, high);
652 self.scale_color(s)
653 }
654
655 pub fn scale_fill_gradient2(
656 self,
657 low: crate::scale::color::RGBAColor,
658 mid: crate::scale::color::RGBAColor,
659 high: crate::scale::color::RGBAColor,
660 ) -> Self {
661 use crate::scale::gradient::ScaleColorGradient2;
662 let s = ScaleColorGradient2::new(crate::aes::Aesthetic::Fill).with_colors(low, mid, high);
663 self.scale_fill(s)
664 }
665
666 pub fn scale_fill_viridis(self) -> Self {
667 use crate::scale::color::ScaleColorDiscrete;
668 use crate::scale::palettes::PaletteName;
669 let s = ScaleColorDiscrete::new(crate::aes::Aesthetic::Fill)
670 .with_named_palette(&PaletteName::Viridis);
671 self.scale_fill(s)
672 }
673
674 pub fn scale_color_viridis_c(self) -> Self {
676 use crate::scale::gradient_n::ScaleColorGradientN;
677 let s = ScaleColorGradientN::viridis(crate::aes::Aesthetic::Color);
678 self.scale_color(s)
679 }
680
681 pub fn scale_fill_viridis_c(self) -> Self {
683 use crate::scale::gradient_n::ScaleColorGradientN;
684 let s = ScaleColorGradientN::viridis(crate::aes::Aesthetic::Fill);
685 self.scale_fill(s)
686 }
687
688 pub fn scale_color_gradientn(self, stops: Vec<(f64, crate::scale::color::RGBAColor)>) -> Self {
690 use crate::scale::gradient_n::ScaleColorGradientN;
691 let s = ScaleColorGradientN::new(crate::aes::Aesthetic::Color, stops);
692 self.scale_color(s)
693 }
694
695 pub fn scale_fill_gradientn(self, stops: Vec<(f64, crate::scale::color::RGBAColor)>) -> Self {
697 use crate::scale::gradient_n::ScaleColorGradientN;
698 let s = ScaleColorGradientN::new(crate::aes::Aesthetic::Fill, stops);
699 self.scale_fill(s)
700 }
701
702 pub fn scale_color_steps(
705 self,
706 low: crate::scale::color::RGBAColor,
707 high: crate::scale::color::RGBAColor,
708 n_bins: usize,
709 ) -> Self {
710 let s = crate::scale::steps::ScaleColorSteps::two(
711 crate::aes::Aesthetic::Color,
712 (low.r, low.g, low.b),
713 (high.r, high.g, high.b),
714 n_bins,
715 );
716 self.scale_color(s)
717 }
718
719 pub fn scale_color_stepsn(
721 self,
722 stops: Vec<crate::scale::color::RGBAColor>,
723 n_bins: usize,
724 ) -> Self {
725 let s = crate::scale::steps::ScaleColorSteps::new(
726 crate::aes::Aesthetic::Color,
727 stops.iter().map(|c| (c.r, c.g, c.b)).collect(),
728 n_bins,
729 );
730 self.scale_color(s)
731 }
732
733 pub fn scale_color_fermenter(
735 self,
736 name: crate::scale::palettes::PaletteName,
737 n_bins: usize,
738 ) -> Self {
739 let stops = crate::scale::palettes::palette(&name)
740 .iter()
741 .map(|c| (c.r, c.g, c.b))
742 .collect();
743 let s =
744 crate::scale::steps::ScaleColorSteps::new(crate::aes::Aesthetic::Color, stops, n_bins);
745 self.scale_color(s)
746 }
747
748 pub fn scale_fill_steps(
750 self,
751 low: crate::scale::color::RGBAColor,
752 high: crate::scale::color::RGBAColor,
753 n_bins: usize,
754 ) -> Self {
755 let s = crate::scale::steps::ScaleColorSteps::two(
756 crate::aes::Aesthetic::Fill,
757 (low.r, low.g, low.b),
758 (high.r, high.g, high.b),
759 n_bins,
760 );
761 self.scale_fill(s)
762 }
763
764 pub fn scale_fill_fermenter(
766 self,
767 name: crate::scale::palettes::PaletteName,
768 n_bins: usize,
769 ) -> Self {
770 let stops = crate::scale::palettes::palette(&name)
771 .iter()
772 .map(|c| (c.r, c.g, c.b))
773 .collect();
774 let s =
775 crate::scale::steps::ScaleColorSteps::new(crate::aes::Aesthetic::Fill, stops, n_bins);
776 self.scale_fill(s)
777 }
778
779 pub fn scale_fill_brewer(self, name: crate::scale::palettes::PaletteName) -> Self {
780 use crate::scale::color::ScaleColorDiscrete;
781 let s = ScaleColorDiscrete::new(crate::aes::Aesthetic::Fill).with_named_palette(&name);
782 self.scale_fill(s)
783 }
784
785 pub fn scale_linetype_manual(
786 self,
787 values: Vec<(&str, crate::render::backend::Linetype)>,
788 ) -> Self {
789 let s = crate::scale::linetype_manual::ScaleLinetypeManual::new(values);
790 self.scale_color(s)
791 }
792
793 pub fn scale_shape_manual(
794 self,
795 values: Vec<(&str, crate::render::backend::PointShape)>,
796 ) -> Self {
797 let s = crate::scale::shape_manual::ScaleShapeManual::new(values);
798 self.scale_color(s)
799 }
800
801 pub fn scale_color_grey(self) -> Self {
802 let s = crate::scale::grey::ScaleColorGrey::new(crate::aes::Aesthetic::Color);
803 self.scale_color(s)
804 }
805
806 pub fn scale_fill_grey(self) -> Self {
807 let s = crate::scale::grey::ScaleColorGrey::new(crate::aes::Aesthetic::Fill);
808 self.scale_fill(s)
809 }
810
811 pub fn scale_color_grey_with(self, s: crate::scale::grey::ScaleColorGrey) -> Self {
812 self.scale_color(s)
813 }
814
815 pub fn scale_fill_grey_with(self, s: crate::scale::grey::ScaleColorGrey) -> Self {
816 self.scale_fill(s)
817 }
818
819 pub fn scale_x_reverse(self) -> Self {
820 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Reverse))
821 }
822
823 pub fn scale_y_reverse(self) -> Self {
824 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Reverse))
825 }
826
827 pub fn scale_x_datetime(mut self, s: crate::scale::datetime::ScaleDateTime) -> Self {
828 let s = s.for_aesthetic(crate::aes::Aesthetic::X);
829 self.scales.push(Box::new(s));
830 self
831 }
832
833 pub fn scale_y_datetime(mut self, s: crate::scale::datetime::ScaleDateTime) -> Self {
834 let s = s.for_aesthetic(crate::aes::Aesthetic::Y);
835 self.scales.push(Box::new(s));
836 self
837 }
838
839 pub fn scale_size(mut self, s: crate::scale::size::ScaleSizeContinuous) -> Self {
840 self.scales.push(Box::new(s));
841 self
842 }
843
844 pub fn scale_alpha(mut self, s: crate::scale::alpha::ScaleAlphaContinuous) -> Self {
845 self.scales.push(Box::new(s));
846 self
847 }
848
849 pub fn xlim(self, min: f64, max: f64) -> Self {
850 self.scale_x_continuous(ScaleContinuous::new().with_limits(min, max))
851 }
852
853 pub fn ylim(self, min: f64, max: f64) -> Self {
854 self.scale_y_continuous(ScaleContinuous::new().with_limits(min, max))
855 }
856
857 pub fn scale_x_log10(self) -> Self {
858 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Log10))
859 }
860
861 pub fn scale_y_log10(self) -> Self {
862 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Log10))
863 }
864
865 pub fn scale_x_sqrt(self) -> Self {
866 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Sqrt))
867 }
868
869 pub fn scale_y_sqrt(self) -> Self {
870 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Sqrt))
871 }
872
873 pub fn scale_x_log2(self) -> Self {
874 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Log2))
875 }
876
877 pub fn scale_y_log2(self) -> Self {
878 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Log2))
879 }
880
881 pub fn scale_x_ln(self) -> Self {
882 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Ln))
883 }
884
885 pub fn scale_y_ln(self) -> Self {
886 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Ln))
887 }
888
889 pub fn scale_x_logit(self) -> Self {
891 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Logit))
892 }
893
894 pub fn scale_y_logit(self) -> Self {
895 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Logit))
896 }
897
898 pub fn scale_x_probit(self) -> Self {
900 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Probit))
901 }
902
903 pub fn scale_y_probit(self) -> Self {
904 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Probit))
905 }
906
907 pub fn scale_x_pseudo_log(self) -> Self {
909 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::PseudoLog))
910 }
911
912 pub fn scale_y_pseudo_log(self) -> Self {
913 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::PseudoLog))
914 }
915
916 pub fn scale_x_reciprocal(self) -> Self {
918 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Reciprocal))
919 }
920
921 pub fn scale_y_reciprocal(self) -> Self {
922 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Reciprocal))
923 }
924
925 pub fn scale_x_exp(self) -> Self {
927 self.scale_x_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Exp))
928 }
929
930 pub fn scale_y_exp(self) -> Self {
931 self.scale_y_continuous(ScaleContinuous::new().with_transform(ScaleTransform::Exp))
932 }
933
934 pub fn scale_x_boxcox(self, lambda: f64) -> Self {
936 self.scale_x_continuous(
937 ScaleContinuous::new().with_transform(ScaleTransform::BoxCox(lambda)),
938 )
939 }
940
941 pub fn scale_y_boxcox(self, lambda: f64) -> Self {
942 self.scale_y_continuous(
943 ScaleContinuous::new().with_transform(ScaleTransform::BoxCox(lambda)),
944 )
945 }
946
947 pub fn facet_wrap(mut self, var: &str, ncol: Option<usize>) -> Self {
950 self.facet = Facet::Wrap {
951 var: var.to_string(),
952 ncol,
953 scales: FacetScales::Fixed,
954 labeller: FacetLabeller::default(),
955 };
956 self
957 }
958
959 pub fn facet_wrap_free(mut self, var: &str, ncol: Option<usize>, scales: FacetScales) -> Self {
960 self.facet = Facet::Wrap {
961 var: var.to_string(),
962 ncol,
963 scales,
964 labeller: FacetLabeller::default(),
965 };
966 self
967 }
968
969 pub fn facet_wrap_labeller(
970 mut self,
971 var: &str,
972 ncol: Option<usize>,
973 labeller: FacetLabeller,
974 ) -> Self {
975 self.facet = Facet::Wrap {
976 var: var.to_string(),
977 ncol,
978 scales: FacetScales::Fixed,
979 labeller,
980 };
981 self
982 }
983
984 pub fn facet_grid(mut self, row: Option<&str>, col: Option<&str>) -> Self {
985 self.facet = Facet::Grid {
986 row_var: row.map(String::from),
987 col_var: col.map(String::from),
988 scales: FacetScales::Fixed,
989 labeller: FacetLabeller::default(),
990 space: FacetSpace::Fixed,
991 };
992 self
993 }
994
995 pub fn facet_grid_free(
996 mut self,
997 row: Option<&str>,
998 col: Option<&str>,
999 scales: FacetScales,
1000 ) -> Self {
1001 self.facet = Facet::Grid {
1002 row_var: row.map(String::from),
1003 col_var: col.map(String::from),
1004 scales,
1005 labeller: FacetLabeller::default(),
1006 space: FacetSpace::Fixed,
1007 };
1008 self
1009 }
1010
1011 pub fn facet_grid_multi(
1015 mut self,
1016 row: Option<&str>,
1017 cols: &[&str],
1018 scales: FacetScales,
1019 space: FacetSpace,
1020 ) -> Self {
1021 let col_var = if cols.len() > 1 {
1022 let n = self.data.nrows();
1024 let mut combined = Vec::with_capacity(n);
1025 for i in 0..n {
1026 let parts: Vec<String> = cols
1027 .iter()
1028 .map(|c| {
1029 self.data
1030 .column(c)
1031 .and_then(|col| col.get(i))
1032 .map(|v| v.to_group_key())
1033 .unwrap_or_default()
1034 })
1035 .collect();
1036 combined.push(crate::data::Value::Str(parts.join(" . ")));
1037 }
1038 let name = "__facet_cols__".to_string();
1039 self.data.add_column(name.clone(), combined);
1040 Some(name)
1041 } else {
1042 cols.first().map(|s| s.to_string())
1043 };
1044 self.facet = Facet::Grid {
1045 row_var: row.map(String::from),
1046 col_var,
1047 scales,
1048 labeller: FacetLabeller::default(),
1049 space,
1050 };
1051 self
1052 }
1053
1054 pub fn facet_grid_space(
1057 mut self,
1058 row: Option<&str>,
1059 col: Option<&str>,
1060 scales: FacetScales,
1061 space: FacetSpace,
1062 ) -> Self {
1063 self.facet = Facet::Grid {
1064 row_var: row.map(String::from),
1065 col_var: col.map(String::from),
1066 scales,
1067 labeller: FacetLabeller::default(),
1068 space,
1069 };
1070 self
1071 }
1072
1073 pub fn facet_grid_labeller(
1074 mut self,
1075 row: Option<&str>,
1076 col: Option<&str>,
1077 labeller: FacetLabeller,
1078 ) -> Self {
1079 self.facet = Facet::Grid {
1080 row_var: row.map(String::from),
1081 col_var: col.map(String::from),
1082 scales: FacetScales::Fixed,
1083 labeller,
1084 space: FacetSpace::Fixed,
1085 };
1086 self
1087 }
1088
1089 pub fn coord_flip(mut self) -> Self {
1092 self.coord = Box::new(CoordFlip);
1093 self
1094 }
1095
1096 pub fn coord_fixed(mut self, ratio: f64) -> Self {
1097 self.coord = Box::new(CoordFixed::new(ratio));
1098 self
1099 }
1100
1101 #[cfg(feature = "sf")]
1105 pub fn coord_sf(mut self) -> Self {
1106 self.coord = Box::new(crate::coord::sf::CoordSf::new());
1107 self
1108 }
1109
1110 pub fn coord_trans(mut self, x: Option<ScaleTransform>, y: Option<ScaleTransform>) -> Self {
1115 self.coord = Box::new(crate::coord::trans::CoordTrans::new(x, y));
1116 self
1117 }
1118
1119 pub fn coord_trans_y(self, y: ScaleTransform) -> Self {
1121 self.coord_trans(None, Some(y))
1122 }
1123
1124 pub fn coord_trans_x(self, x: ScaleTransform) -> Self {
1126 self.coord_trans(Some(x), None)
1127 }
1128
1129 pub fn coord_cartesian_zoom(
1131 mut self,
1132 xlim: Option<(f64, f64)>,
1133 ylim: Option<(f64, f64)>,
1134 ) -> Self {
1135 let mut c = CoordCartesian::new();
1136 if let Some((min, max)) = xlim {
1137 c = c.xlim(min, max);
1138 }
1139 if let Some((min, max)) = ylim {
1140 c = c.ylim(min, max);
1141 }
1142 self.coord = Box::new(c);
1143 self
1144 }
1145
1146 pub fn coord_polar(mut self) -> Self {
1147 self.coord = Box::new(CoordPolar::new());
1148 self
1149 }
1150
1151 pub fn coord_polar_with(mut self, coord: CoordPolar) -> Self {
1152 self.coord = Box::new(coord);
1153 self
1154 }
1155
1156 pub fn theme(mut self, theme: Theme) -> Self {
1159 self.theme = theme;
1160 self
1161 }
1162
1163 pub fn axis_text_x_angle(mut self, degrees: f64) -> Self {
1167 self.theme.axis_text_x.angle = degrees;
1168 self
1169 }
1170
1171 pub fn axis_text_y_angle(mut self, degrees: f64) -> Self {
1173 self.theme.axis_text_y.angle = degrees;
1174 self
1175 }
1176
1177 pub fn axis_text_x_dodge(mut self, n: usize) -> Self {
1180 self.theme.axis_text_x_dodge = n.max(1);
1181 self
1182 }
1183
1184 pub fn aspect_ratio(mut self, ratio: f64) -> Self {
1187 self.theme.aspect_ratio = Some(ratio);
1188 self
1189 }
1190
1191 pub fn panel_ontop(mut self) -> Self {
1193 self.theme.panel_ontop = true;
1194 self
1195 }
1196
1197 pub fn axis_minor_ticks(mut self) -> Self {
1199 self.theme.axis_minor_ticks = true;
1200 self
1201 }
1202
1203 pub fn title_position(mut self, pos: crate::theme::TitlePosition) -> Self {
1206 self.theme.title_position = pos;
1207 self
1208 }
1209
1210 pub fn tag_position(mut self, pos: crate::theme::TagPosition) -> Self {
1212 self.theme.tag_position = pos;
1213 self
1214 }
1215
1216 pub fn legend_direction(mut self, dir: crate::theme::LegendDirection) -> Self {
1218 self.theme.legend_direction = Some(dir);
1219 self
1220 }
1221
1222 pub fn legend_position_inside(mut self, x: f64, y: f64) -> Self {
1229 self.theme.legend_position = crate::theme::LegendPosition::Inside(x, y);
1230 self
1231 }
1232
1233 pub fn primary_color(mut self, color: (u8, u8, u8)) -> Self {
1234 self.theme.primary = Some(color);
1235 self
1236 }
1237
1238 pub fn theme_minimal(mut self) -> Self {
1239 self.theme = crate::theme::presets::theme_minimal();
1240 self
1241 }
1242
1243 pub fn theme_bw(mut self) -> Self {
1244 self.theme = crate::theme::presets::theme_bw();
1245 self
1246 }
1247
1248 pub fn theme_gray(mut self) -> Self {
1249 self.theme = crate::theme::presets::theme_gray();
1250 self
1251 }
1252
1253 pub fn theme_classic(mut self) -> Self {
1254 self.theme = crate::theme::presets::theme_classic();
1255 self
1256 }
1257
1258 pub fn theme_linedraw(mut self) -> Self {
1259 self.theme = crate::theme::presets::theme_linedraw();
1260 self
1261 }
1262
1263 pub fn theme_light(mut self) -> Self {
1264 self.theme = crate::theme::presets::theme_light();
1265 self
1266 }
1267
1268 pub fn theme_dark(mut self) -> Self {
1269 self.theme = crate::theme::presets::theme_dark();
1270 self
1271 }
1272
1273 pub fn theme_void(mut self) -> Self {
1274 self.theme = crate::theme::presets::theme_void();
1275 self
1276 }
1277
1278 pub fn theme_update(mut self, update: crate::theme::ThemeUpdate) -> Self {
1281 self.theme = self.theme.update(update);
1282 self
1283 }
1284
1285 pub fn guides(mut self, guide: crate::guide::config::GuideLegend) -> Self {
1289 self.guide_legend = guide;
1290 self
1291 }
1292
1293 pub fn labs(mut self, labels: Labels) -> Self {
1296 if labels.title.is_some() {
1297 self.labels.title = labels.title;
1298 }
1299 if labels.subtitle.is_some() {
1300 self.labels.subtitle = labels.subtitle;
1301 }
1302 if labels.x.is_some() {
1303 self.labels.x = labels.x;
1304 }
1305 if labels.y.is_some() {
1306 self.labels.y = labels.y;
1307 }
1308 if labels.caption.is_some() {
1309 self.labels.caption = labels.caption;
1310 }
1311 if labels.tag.is_some() {
1312 self.labels.tag = labels.tag;
1313 }
1314 self
1315 }
1316
1317 pub fn title(mut self, title: &str) -> Self {
1318 self.labels.title = Some(title.to_string());
1319 self
1320 }
1321
1322 pub fn tag(mut self, tag: &str) -> Self {
1325 self.labels.tag = Some(tag.to_string());
1326 self
1327 }
1328
1329 pub fn subtitle(mut self, subtitle: &str) -> Self {
1330 self.labels.subtitle = Some(subtitle.to_string());
1331 self
1332 }
1333
1334 pub fn xlab(mut self, label: &str) -> Self {
1335 self.labels.x = Some(label.to_string());
1336 self
1337 }
1338
1339 pub fn ylab(mut self, label: &str) -> Self {
1340 self.labels.y = Some(label.to_string());
1341 self
1342 }
1343
1344 pub fn caption(mut self, caption: &str) -> Self {
1345 self.labels.caption = Some(caption.to_string());
1346 self
1347 }
1348
1349 pub fn annotate(mut self, annotation: Annotation) -> Self {
1353 self.annotations.push(annotation);
1354 self
1355 }
1356
1357 pub fn annotate_text(self, label: &str, x: f64, y: f64) -> Self {
1359 self.annotate(Annotation::text(label, x, y))
1360 }
1361
1362 pub fn annotate_rect(self, xmin: f64, xmax: f64, ymin: f64, ymax: f64) -> Self {
1364 self.annotate(Annotation::rect(xmin, xmax, ymin, ymax))
1365 }
1366
1367 pub fn annotate_segment(self, x: f64, y: f64, xend: f64, yend: f64) -> Self {
1369 self.annotate(Annotation::segment(x, y, xend, yend))
1370 }
1371
1372 pub fn try_build(self) -> Result<crate::build::BuiltPlot, GGError> {
1376 PlotBuilder::build(self)
1377 }
1378
1379 pub fn build(self) -> crate::build::BuiltPlot {
1383 self.try_build().expect("plot build failed")
1384 }
1385
1386 #[cfg(not(target_arch = "wasm32"))]
1389 pub fn save(self, path: &str) -> Result<(), GGError> {
1390 self.save_with_size(path, 800, 600)
1391 }
1392
1393 #[cfg(not(target_arch = "wasm32"))]
1395 pub fn save_with_size(self, path: &str, w: u32, h: u32) -> Result<(), GGError> {
1396 let (built, layout) = self.prepare(w, h)?;
1397
1398 let ext = path.rsplit('.').next().unwrap_or("svg").to_lowercase();
1400
1401 match ext.as_str() {
1402 "svg" => {
1403 let backend = plotters::prelude::SVGBackend::new(path, (w, h));
1404 Self::render_into(backend.into_drawing_area(), &built, &layout)?;
1405 }
1406 "png" | "bmp" | "gif" | "jpeg" | "jpg" | "tiff" => {
1407 let backend = plotters::prelude::BitMapBackend::new(path, (w, h));
1408 Self::render_into(backend.into_drawing_area(), &built, &layout)?;
1409 }
1410 _ => {
1411 return Err(GGError::UnsupportedFormat(ext));
1412 }
1413 }
1414
1415 Ok(())
1416 }
1417
1418 #[cfg(not(target_arch = "wasm32"))]
1423 pub fn render_svg(self) -> Result<String, GGError> {
1424 self.render_svg_with_size(800, 600)
1425 }
1426
1427 #[cfg(not(target_arch = "wasm32"))]
1430 pub fn render_svg_with_size(self, w: u32, h: u32) -> Result<String, GGError> {
1431 let (built, layout) = self.prepare(w, h)?;
1432 let mut buf = String::new();
1433 {
1434 let backend = plotters::prelude::SVGBackend::with_string(&mut buf, (w, h));
1435 Self::render_into(backend.into_drawing_area(), &built, &layout)?;
1436 }
1437 Ok(buf)
1438 }
1439
1440 pub fn render_svg_native(self) -> Result<String, GGError> {
1444 self.render_svg_native_with_size(800, 600)
1445 }
1446
1447 pub fn render_svg_native_with_size(self, w: u32, h: u32) -> Result<String, GGError> {
1449 let (built, layout) = self.prepare(w, h)?;
1450 let mut backend =
1451 crate::render::svg_backend::SvgBackend::new(w, h, layout.plot_area.clone());
1452 PlotRenderer::render(&built, &mut backend).map_err(GGError::Render)?;
1453 Ok(backend.finish())
1454 }
1455
1456 #[cfg(feature = "canvas")]
1461 pub fn render_rgba_with_size(self, w: u32, h: u32) -> Result<(u32, u32, Vec<u8>), GGError> {
1462 let (built, layout) = self.prepare(w, h)?;
1463 let mut backend =
1464 crate::render::pixel_backend::PixelBackend::new(w, h, layout.plot_area.clone());
1465 PlotRenderer::render(&built, &mut backend).map_err(GGError::Render)?;
1466 let (ow, oh) = backend.dimensions();
1467 Ok((ow, oh, backend.into_rgba()))
1468 }
1469
1470 #[cfg(feature = "canvas")]
1474 pub fn render_rgba_area_with_size(
1475 self,
1476 w: u32,
1477 h: u32,
1478 ) -> Result<(Vec<u8>, [f64; 4]), GGError> {
1479 let (built, layout) = self.prepare(w, h)?;
1480 let pa = layout.plot_area.clone();
1481 let mut backend = crate::render::pixel_backend::PixelBackend::new(w, h, pa.clone());
1482 PlotRenderer::render(&built, &mut backend).map_err(GGError::Render)?;
1483 Ok((backend.into_rgba(), [pa.x, pa.y, pa.width, pa.height]))
1484 }
1485
1486 #[cfg(feature = "canvas")]
1490 pub fn render_png_raster_with_size(self, w: u32, h: u32) -> Result<Vec<u8>, GGError> {
1491 let (built, layout) = self.prepare(w, h)?;
1492 let mut backend =
1493 crate::render::pixel_backend::PixelBackend::new(w, h, layout.plot_area.clone());
1494 PlotRenderer::render(&built, &mut backend).map_err(GGError::Render)?;
1495 backend.into_png().map_err(GGError::Render)
1496 }
1497
1498 #[cfg(not(target_arch = "wasm32"))]
1503 pub fn render_png(self) -> Result<Vec<u8>, GGError> {
1504 self.render_png_with_size(800, 600)
1505 }
1506
1507 #[cfg(not(target_arch = "wasm32"))]
1510 pub fn render_png_with_size(self, w: u32, h: u32) -> Result<Vec<u8>, GGError> {
1511 let (built, layout) = self.prepare(w, h)?;
1512
1513 let mut rgb = vec![0u8; (w as usize) * (h as usize) * 3];
1516 {
1517 let backend = plotters::prelude::BitMapBackend::with_buffer(&mut rgb, (w, h));
1518 Self::render_into(backend.into_drawing_area(), &built, &layout)?;
1519 }
1520
1521 let img = image::RgbImage::from_raw(w, h, rgb).ok_or_else(|| {
1522 GGError::Render(RenderError::BackendError(
1523 "PNG buffer size mismatch".to_string(),
1524 ))
1525 })?;
1526 let mut out = std::io::Cursor::new(Vec::new());
1527 img.write_to(&mut out, image::ImageOutputFormat::Png)
1528 .map_err(|e| GGError::Render(RenderError::BackendError(format!("{:?}", e))))?;
1529 Ok(out.into_inner())
1530 }
1531
1532 fn prepare(self, w: u32, h: u32) -> Result<(crate::build::BuiltPlot, PlotLayout), GGError> {
1534 let plot = self;
1535
1536 let has_title = plot.labels.title.is_some();
1537 let has_subtitle = plot.labels.subtitle.is_some();
1538 let has_caption = plot.labels.caption.is_some();
1539 let has_legend = plot.has_legend_mapping();
1540 let x_label = plot.labels.x.clone();
1541 let y_label = plot.labels.y.clone();
1542
1543 let mut built = PlotBuilder::build(plot)?;
1544
1545 built.theme.resolve_inheritance();
1547
1548 if let Some(ref label) = x_label {
1550 if let Some(s) = built.scales.get_mut(&crate::aes::Aesthetic::X) {
1551 s.set_name(label);
1552 }
1553 }
1554 if let Some(ref label) = y_label {
1555 if let Some(s) = built.scales.get_mut(&crate::aes::Aesthetic::Y) {
1556 s.set_name(label);
1557 }
1558 }
1559
1560 let x_axis_top = built
1561 .scales
1562 .get(&crate::aes::Aesthetic::X)
1563 .map(|s| s.axis_position_opposite())
1564 .unwrap_or(false);
1565
1566 let layout = PlotLayout::compute_full(
1567 w as f64,
1568 h as f64,
1569 &built.theme,
1570 has_title,
1571 has_subtitle,
1572 has_caption,
1573 has_legend,
1574 x_axis_top,
1575 );
1576
1577 Ok((built, layout))
1578 }
1579
1580 #[cfg(not(target_arch = "wasm32"))]
1583 fn render_into<DB>(
1584 area: plotters::drawing::DrawingArea<DB, plotters::coord::Shift>,
1585 built: &crate::build::BuiltPlot,
1586 layout: &PlotLayout,
1587 ) -> Result<(), GGError>
1588 where
1589 DB: plotters::prelude::DrawingBackend,
1590 DB::ErrorType: 'static,
1591 {
1592 area.fill(&plotters::prelude::WHITE)
1593 .map_err(|e| GGError::Render(RenderError::BackendError(format!("{:?}", e))))?;
1594 let mut adapter = PlottersAdapter::new(&area, layout.plot_area.clone());
1595 PlotRenderer::render(built, &mut adapter).map_err(GGError::Render)?;
1596 area.present()
1597 .map_err(|e| GGError::Render(RenderError::BackendError(format!("{:?}", e))))?;
1598 Ok(())
1599 }
1600
1601 #[cfg(not(target_arch = "wasm32"))]
1603 pub fn ggsave(
1604 self,
1605 path: &str,
1606 width_inches: f64,
1607 height_inches: f64,
1608 dpi: f64,
1609 ) -> Result<(), GGError> {
1610 let w = (width_inches * dpi) as u32;
1611 let h = (height_inches * dpi) as u32;
1612 self.save_with_size(path, w, h)
1613 }
1614
1615 fn has_legend_mapping(&self) -> bool {
1616 self.mapping.mappings.iter().any(|m| {
1617 matches!(
1618 m.aesthetic,
1619 crate::aes::Aesthetic::Color
1620 | crate::aes::Aesthetic::Fill
1621 | crate::aes::Aesthetic::Shape
1622 | crate::aes::Aesthetic::Linetype
1623 | crate::aes::Aesthetic::Size
1624 | crate::aes::Aesthetic::Alpha
1625 )
1626 })
1627 }
1628}
1629
1630#[derive(Debug)]
1632pub enum GGError {
1633 Render(RenderError),
1634 UnsupportedFormat(String),
1635 Io(std::io::Error),
1636 ValidationError(String),
1637}
1638
1639impl std::fmt::Display for GGError {
1640 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1641 match self {
1642 GGError::Render(e) => write!(f, "Render error: {e}"),
1643 GGError::UnsupportedFormat(ext) => write!(f, "Unsupported output format: {ext}"),
1644 GGError::Io(e) => write!(f, "IO error: {e}"),
1645 GGError::ValidationError(msg) => write!(f, "Validation error: {msg}"),
1646 }
1647 }
1648}
1649
1650impl std::error::Error for GGError {}