Skip to main content

ShapeProperties

Struct ShapeProperties 

Source
pub struct ShapeProperties {
    pub transform: Option<Transform2D>,
    pub geometry: Option<Geometry>,
    pub fill: Option<Fill>,
    pub line: Option<Line>,
    pub effects: Option<EffectList>,
    pub geometry_adjustments: Vec<GeometryAdjustment>,
}
Expand description

A shape’s visual properties (<a:spPr>, CT_ShapeProperties): local position/size, geometry, fill, and line. Everything about how a shape looks, independent of where it is anchored in its host document (that part is never modeled here — see the crate-level doc comment).

Not modeled: 3D (a:scene3d/a:sp3d) — EG_EffectProperties’s <a:effectLst> choice (shadow/glow/reflection/soft edge) is modeled, see EffectList, point 10; its sibling choice <a:effectDag> (an effect graph, letting effects reference each other’s output — a materially more complex, rarely-authored mechanism) is not. bwMode (black-and-white print override) is not modeled either — a rarely-used printing hint.

Fields§

§transform: Option<Transform2D>

<a:xfrm> — position, size, rotation, flipping.

§geometry: Option<Geometry>

EG_Geometry (<a:prstGeom>/<a:custGeom>) — the shape’s outline.

§fill: Option<Fill>

EG_FillProperties (<a:noFill>/<a:solidFill>/<a:gradFill>/ <a:pattFill>/<a:blipFill>/<a:grpFill>) — how the shape’s interior is painted.

§line: Option<Line>

<a:ln> — the shape’s outline stroke.

§effects: Option<EffectList>

<a:effectLst> — shadow/glow/reflection/soft-edge effects.

§geometry_adjustments: Vec<GeometryAdjustment>

<a:prstGeom>’s own <a:avLst> (CT_GeomGuideList) — adjustment handle values for a preset shape (a rounded rectangle’s corner radius, an arrow’s head size.). Only meaningful, and only ever written, when geometry is Some(Geometry::Preset(_)) — kept as a sibling field here (rather than inside Geometry::Preset itself) to avoid a breaking change to that enum’s existing tuple-variant shape, used at dozens of call sites across every host crate. Empty (the default) omits <a:avLst> entirely for a preset shape — schema- valid, meaning “use this preset’s own built-in default handles”. Grounded against a real fixture (a smiley-face preset with an explicit adj guide).

Implementations§

Source§

impl ShapeProperties

Source

pub fn new() -> ShapeProperties

Creates an empty set of shape properties (every field unset — a shape that inherits everything from its host’s defaults).

Examples found in repository?
examples/hello_world_pptx.rs (line 19)
14fn main() -> office_toolkit::Result<()> {
15    let path = output_path("hello_world.pptx");
16
17    let text_box = AutoShape::new(2, "Hello box")
18        .with_properties(
19            ShapeProperties::new().with_transform(
20                Transform2D::new()
21                    .with_offset(838_200, 1_365_250)
22                    .with_extent(7_772_400, 1_200_150),
23            ),
24        )
25        .with_text_body(
26            TextBody::new()
27                .with_paragraph(TextParagraph::new().with_run(TextRun::text("Hello, world!"))),
28        );
29
30    // `Presentation` and `Slide` both come from `office_toolkit::prelude`.
31    let presentation =
32        Presentation::new().with_slide(Slide::new().with_shape(Shape::AutoShape(text_box)));
33    presentation.save_to_file(&path)?;
34    println!("Wrote {}", path.display());
35
36    // Read the file back to confirm it is a valid .pptx.
37    let reopened = Presentation::open_file(&path)?;
38    println!("Slide count: {}", reopened.slides.len());
39
40    Ok(())
41}
More examples
Hide additional examples
examples/pptx_notes_and_comments.rs (line 18)
12fn main() -> office_toolkit::Result<()> {
13    let path = output_path("pptx_notes_and_comments.pptx");
14
15    let title = |text: &str| {
16        AutoShape::new(2, "Title")
17            .with_properties(
18                ShapeProperties::new().with_transform(
19                    Transform2D::new()
20                        .with_offset(838_200, 838_200)
21                        .with_extent(8_000_000, 1_000_000),
22                ),
23            )
24            .with_text_body(
25                TextBody::new().with_paragraph(TextParagraph::new().with_run(TextRun::text(text))),
26            )
27    };
28
29    let notes_slide = Slide::new()
30        .with_shape(Shape::AutoShape(title("A slide with speaker notes")))
31        .with_notes(
32            TextBody::new().with_paragraph(
33                TextParagraph::new()
34                    .with_run(TextRun::text("Remember to mention the Q3 numbers here.")),
35            ),
36        );
37
38    let commented_slide = Slide::new()
39        .with_shape(Shape::AutoShape(title("A slide with reviewer comments")))
40        .with_comment(
41            SlideComment::new(
42                "Reviewer",
43                "RV",
44                "2026-07-21T10:00:00",
45                "This claim needs a source.",
46            )
47            .with_position(1_000_000, 2_000_000),
48        )
49        .with_comment(
50            SlideComment::new(
51                "Editor",
52                "ED",
53                "2026-07-21T11:30:00",
54                "Looks good otherwise.",
55            )
56            .with_position(3_000_000, 2_000_000),
57        );
58
59    let presentation = Presentation::new()
60        .with_slide(notes_slide)
61        .with_slide(commented_slide);
62
63    presentation.save_to_file(&path)?;
64    println!("Wrote {}", path.display());
65    Ok(())
66}
examples/pptx_shapes_and_placeholders.rs (line 19)
14fn main() -> office_toolkit::Result<()> {
15    let path = output_path("pptx_shapes_and_placeholders.pptx");
16
17    let plain_shape = AutoShape::new(2, "Plain autoshape")
18        .with_properties(
19            ShapeProperties::new().with_transform(
20                Transform2D::new()
21                    .with_offset(838_200, 838_200)
22                    .with_extent(5_000_000, 1_000_000),
23            ),
24        )
25        .with_text_body(
26            TextBody::new()
27                .with_paragraph(TextParagraph::new().with_run(TextRun::text("A plain autoshape."))),
28        );
29
30    let text_box = AutoShape::new(2, "Text box")
31        .with_text_box(true)
32        .with_properties(
33            ShapeProperties::new().with_transform(
34                Transform2D::new()
35                    .with_offset(838_200, 838_200)
36                    .with_extent(5_000_000, 1_000_000),
37            ),
38        )
39        .with_text_body(TextBody::new().with_paragraph(
40            TextParagraph::new().with_run(TextRun::text("A genuine text box (txBox=\"1\").")),
41        ));
42
43    let title = AutoShape::new(2, "Title placeholder")
44        .with_placeholder(Placeholder::new(PlaceholderKind::CenterTitle))
45        .with_properties(
46            ShapeProperties::new().with_transform(
47                Transform2D::new()
48                    .with_offset(838_200, 838_200)
49                    .with_extent(10_515_600, 1_325_563),
50            ),
51        )
52        .with_text_body(
53            TextBody::new()
54                .with_paragraph(TextParagraph::new().with_run(TextRun::text("Title placeholder"))),
55        );
56    let subtitle =
57        AutoShape::new(3, "Subtitle placeholder")
58            .with_placeholder(Placeholder::new(PlaceholderKind::SubTitle).with_index(1))
59            .with_properties(
60                ShapeProperties::new().with_transform(
61                    Transform2D::new()
62                        .with_offset(838_200, 2_400_000)
63                        .with_extent(10_515_600, 800_000),
64                ),
65            )
66            .with_text_body(TextBody::new().with_paragraph(
67                TextParagraph::new().with_run(TextRun::text("Subtitle placeholder")),
68            ));
69
70    let hyperlinked_shape = AutoShape::new(2, "Hyperlinked shape")
71        .with_hyperlink("https://www.rust-lang.org")
72        .with_properties(
73            ShapeProperties::new().with_transform(
74                Transform2D::new()
75                    .with_offset(838_200, 838_200)
76                    .with_extent(5_000_000, 1_000_000),
77            ),
78        )
79        .with_text_body(TextBody::new().with_paragraph(
80            TextParagraph::new().with_run(TextRun::text("Click this shape to open a link.")),
81        ));
82
83    let presentation = Presentation::new()
84        .with_slide(Slide::new().with_shape(Shape::AutoShape(plain_shape)))
85        .with_slide(Slide::new().with_shape(Shape::AutoShape(text_box)))
86        .with_slide(
87            Slide::new()
88                .with_shape(Shape::AutoShape(title))
89                .with_shape(Shape::AutoShape(subtitle)),
90        )
91        .with_slide(Slide::new().with_shape(Shape::AutoShape(hyperlinked_shape)));
92
93    presentation.save_to_file(&path)?;
94    println!("Wrote {}", path.display());
95    Ok(())
96}
examples/pptx_theme_and_metadata.rs (line 59)
19fn main() -> office_toolkit::Result<()> {
20    // A custom theme and an embedded font. `Theme`/`ColorScheme`/
21    // `FontScheme` have no `with_*` builders in this crate — only
22    // `office_default()` or plain struct literals.
23    let custom_theme = Theme {
24        name: "Custom Brand".to_string(),
25        colors: ColorScheme {
26            dark1: "1B1B1B".to_string(),
27            light1: "FFFFFF".to_string(),
28            dark2: "0A2540".to_string(),
29            light2: "F5F5F5".to_string(),
30            accent1: "0A2540".to_string(),
31            accent2: "E8622C".to_string(),
32            accent3: "2E86AB".to_string(),
33            accent4: "6FB98F".to_string(),
34            accent5: "F4A259".to_string(),
35            accent6: "8E4585".to_string(),
36            hyperlink: "1155CC".to_string(),
37            followed_hyperlink: "6B3FA0".to_string(),
38        },
39        fonts: FontScheme {
40            major_latin: "Georgia".to_string(),
41            minor_latin: "Verdana".to_string(),
42        },
43    };
44
45    // Placeholder bytes — a real .pptx would carry genuine TrueType/
46    // OpenType font data here.
47    let embedded_font = EmbeddedFont::new("Custom Sans")
48        .with_regular(vec![0u8; 16])
49        .with_bold(vec![0u8; 16]);
50
51    // A slide with no shapes at all renders as a blank page — nothing shows
52    // the custom theme actually took effect. `drawing::Color` has no
53    // scheme-relative variant yet (`<a:schemeClr>` isn't modeled, see that
54    // enum's own doc comment), so this can't reference the theme's accent1
55    // symbolically; it uses the same literal hex values the theme itself
56    // was built from, purely so the slide visibly matches the palette above.
57    let title_shape = AutoShape::new(2, "Title")
58        .with_properties(
59            ShapeProperties::new()
60                .with_transform(
61                    Transform2D::new()
62                        .with_offset(838_200, 838_200)
63                        .with_extent(6_000_000, 1_500_000),
64                )
65                .with_fill(Fill::Solid(Color::Rgb(custom_theme.colors.accent1.clone()))),
66        )
67        .with_text_body(
68            TextBody::new().with_paragraph(
69                TextParagraph::new().with_run(TextRun::text_with_properties(
70                    "Custom Brand theme — Georgia / Verdana, accent1 = #0A2540",
71                    TextRunProperties::new()
72                        .with_font_family(custom_theme.fonts.major_latin.clone())
73                        .with_font_size_points(24.0)
74                        .with_fill(Fill::Solid(Color::Rgb(custom_theme.colors.light1.clone()))),
75                )),
76            ),
77        );
78
79    let themed_presentation = Presentation::new()
80        .with_theme(custom_theme)
81        .with_embedded_font(embedded_font)
82        .with_slide(Slide::new().with_shape(Shape::AutoShape(title_shape)));
83    let theme_path = output_path("pptx_theme.pptx");
84    themed_presentation.save_to_file(&theme_path)?;
85    println!("Wrote {}", theme_path.display());
86
87    // Document metadata (docProps/core.xml, app.xml, and custom.xml).
88    let properties = DocumentProperties::new()
89        .with_title("Metadata example")
90        .with_author("Example Author")
91        .with_subject("Presentation-level features")
92        .with_custom_property(
93            "ProjectCode",
94            CustomPropertyValue::Text("PPTX-META".to_string()),
95        );
96    // Same reasoning as `title_shape` above: an empty slide would render
97    // blank, so a text shape spells out where the metadata actually lives.
98    let metadata_shape = AutoShape::new(2, "Note")
99        .with_properties(ShapeProperties::new().with_transform(Transform2D::new().with_offset(838_200, 838_200).with_extent(7_000_000, 1_000_000)))
100        .with_text_body(TextBody::new().with_paragraph(TextParagraph::new().with_run(TextRun::text(
101            "This presentation's metadata is in File > Info (title, author, subject, and a custom \"ProjectCode\" property) — not on this slide.",
102        ))));
103    let metadata_presentation = Presentation::new()
104        .with_properties(properties)
105        .with_slide(Slide::new().with_shape(Shape::AutoShape(metadata_shape)));
106    let metadata_path = output_path("pptx_metadata.pptx");
107    metadata_presentation.save_to_file(&metadata_path)?;
108    println!("Wrote {}", metadata_path.display());
109
110    Ok(())
111}
examples/pptx_grouping_and_connectors.rs (line 28)
16fn main() -> office_toolkit::Result<()> {
17    let path = output_path("pptx_grouping_and_connectors.pptx");
18
19    // Every shape below sets an explicit fill (and the connector an
20    // explicit line): with neither a fill/line nor a `<p:style>` theme
21    // reference, a shape has nothing to paint and renders as fully
22    // invisible — the slide then looks blank even though the shapes are
23    // there. `AutoShape`/`Connector` have no `<p:style>` support yet, so an
24    // explicit `Fill`/`Line` is the only way to make a shape actually show.
25    let circle_fill = || Fill::Solid(Color::Rgb("4472C4".to_string()));
26
27    let circle = AutoShape::new(11, "Circle").with_properties(
28        ShapeProperties::new()
29            .with_transform(
30                Transform2D::new()
31                    .with_offset(0, 0)
32                    .with_extent(1_000_000, 1_000_000),
33            )
34            .with_fill(circle_fill()),
35    );
36    let label = AutoShape::new(12, "Label")
37        .with_properties(
38            ShapeProperties::new()
39                .with_transform(
40                    Transform2D::new()
41                        .with_offset(1_200_000, 300_000)
42                        .with_extent(1_500_000, 400_000),
43                )
44                .with_fill(Fill::Solid(Color::Rgb("E8622C".to_string()))),
45        )
46        .with_text_body(
47            TextBody::new()
48                .with_paragraph(TextParagraph::new().with_run(TextRun::text("Grouped label"))),
49        );
50
51    let group = ShapeGroup::new(2, "Group")
52        .with_transform(
53            (838_200, 838_200),
54            (2_700_000, 1_000_000),
55            (0, 0),
56            (2_700_000, 1_000_000),
57        )
58        .with_shape(Shape::AutoShape(circle))
59        .with_shape(Shape::AutoShape(label));
60
61    let rotated_circle = AutoShape::new(11, "Circle").with_properties(
62        ShapeProperties::new()
63            .with_transform(
64                Transform2D::new()
65                    .with_offset(0, 0)
66                    .with_extent(1_000_000, 1_000_000),
67            )
68            .with_fill(circle_fill()),
69    );
70    let rotated_group = ShapeGroup::new(2, "Rotated and flipped group")
71        .with_transform(
72            (838_200, 838_200),
73            (1_000_000, 1_000_000),
74            (0, 0),
75            (1_000_000, 1_000_000),
76        )
77        .with_rotation_degrees(45.0)
78        .with_flip_horizontal(true)
79        .with_shape(Shape::AutoShape(rotated_circle));
80
81    let box_a = AutoShape::new(2, "Box A").with_properties(
82        ShapeProperties::new()
83            .with_transform(
84                Transform2D::new()
85                    .with_offset(838_200, 838_200)
86                    .with_extent(1_000_000, 1_000_000),
87            )
88            .with_fill(Fill::Solid(Color::Rgb("2E86AB".to_string()))),
89    );
90    let box_b = AutoShape::new(3, "Box B").with_properties(
91        ShapeProperties::new()
92            .with_transform(
93                Transform2D::new()
94                    .with_offset(3_500_000, 838_200)
95                    .with_extent(1_000_000, 1_000_000),
96            )
97            .with_fill(Fill::Solid(Color::Rgb("6FB98F".to_string()))),
98    );
99    // `Connector::new` leaves position/size unset, which the writer then
100    // emits as a zero-size `<a:xfrm>` (off 0,0 / ext 0,0) — a real point
101    // with no length, invisible regardless of line/fill. `stCxn`/`endCxn`
102    // alone don't supply geometry; PowerPoint only recomputes it once you
103    // drag one of the attached shapes. So this also sets an explicit
104    // transform spanning Box A's right edge to Box B's left edge.
105    let connector = Connector::new(4, "Connector")
106        .with_properties(
107            ShapeProperties::new()
108                .with_transform(
109                    Transform2D::new()
110                        .with_offset(1_838_200, 1_338_200)
111                        .with_extent(1_662_000, 0),
112                )
113                .with_line(
114                    Line::new()
115                        .with_width_emu(25_400)
116                        .with_fill(Fill::Solid(Color::Rgb("000000".to_string()))),
117                ),
118        )
119        .with_start_connection(2, 0)
120        .with_end_connection(3, 0);
121
122    let presentation = Presentation::new()
123        .with_slide(Slide::new().with_shape(Shape::Group(group)))
124        .with_slide(Slide::new().with_shape(Shape::Group(rotated_group)))
125        .with_slide(
126            Slide::new()
127                .with_shape(Shape::AutoShape(box_a))
128                .with_shape(Shape::AutoShape(box_b))
129                .with_shape(Shape::Connector(connector)),
130        );
131
132    presentation.save_to_file(&path)?;
133    println!("Wrote {}", path.display());
134    Ok(())
135}
examples/pptx_text_formatting.rs (line 24)
19fn main() -> office_toolkit::Result<()> {
20    let path = output_path("pptx_text_formatting.pptx");
21
22    let spacing_shape = AutoShape::new(2, "Spacing")
23        .with_properties(
24            ShapeProperties::new().with_transform(
25                Transform2D::new()
26                    .with_offset(838_200, 838_200)
27                    .with_extent(6_000_000, 1_500_000),
28            ),
29        )
30        .with_text_body(
31            TextBody::new().with_paragraph(
32                TextParagraph::new()
33                    .with_properties(
34                        TextParagraphProperties::new()
35                            .with_line_spacing(TextSpacing::Percent(150_000))
36                            .with_space_before(TextSpacing::Points(1200))
37                            .with_indent_emu(457_200)
38                            .with_level(1),
39                    )
40                    .with_run(TextRun::text(
41                        "Indented, 150% line spacing, 12pt space before.",
42                    )),
43            ),
44        );
45
46    let bullets_shape = AutoShape::new(2, "Bullets")
47        .with_properties(
48            ShapeProperties::new().with_transform(
49                Transform2D::new()
50                    .with_offset(838_200, 838_200)
51                    .with_extent(6_000_000, 1_800_000),
52            ),
53        )
54        .with_text_body(
55            TextBody::new()
56                .with_paragraph(
57                    TextParagraph::new()
58                        .with_properties(
59                            TextParagraphProperties::new()
60                                .with_bullet(BulletKind::Character("\u{2022}".to_string())),
61                        )
62                        .with_run(TextRun::text("Bulleted item")),
63                )
64                .with_paragraph(
65                    TextParagraph::new()
66                        .with_properties(TextParagraphProperties::new().with_bullet(
67                            BulletKind::AutoNumber {
68                                scheme: "arabicPeriod".to_string(),
69                                start_at: None,
70                            },
71                        ))
72                        .with_run(TextRun::text("Auto-numbered item")),
73                ),
74        );
75
76    let autofit_shape = AutoShape::new(2, "Autofit")
77        .with_text_box(true)
78        .with_properties(
79            ShapeProperties::new().with_transform(
80                Transform2D::new()
81                    .with_offset(838_200, 838_200)
82                    .with_extent(4_000_000, 1_000_000),
83            ),
84        )
85        .with_text_body(
86            TextBody::new()
87                .with_properties(
88                    TextBodyProperties::new()
89                        .with_autofit(TextAutofit::Shape)
90                        .with_anchor(TextAnchor::Center)
91                        .with_anchor_center(true),
92                )
93                .with_paragraph(TextParagraph::new().with_run(TextRun::text(
94                    "This shape resizes to fit its text, centered both ways.",
95                ))),
96        );
97
98    let casing_shape = AutoShape::new(2, "Casing")
99        .with_properties(
100            ShapeProperties::new().with_transform(
101                Transform2D::new()
102                    .with_offset(838_200, 838_200)
103                    .with_extent(6_000_000, 1_500_000),
104            ),
105        )
106        .with_text_body(
107            TextBody::new().with_paragraph(
108                TextParagraph::new()
109                    .with_run(TextRun::text_with_properties(
110                        "rendered in all caps, ",
111                        TextRunProperties::new().with_text_caps(TextCaps::All),
112                    ))
113                    .with_run(TextRun::text_with_properties(
114                        "widely spaced, ",
115                        TextRunProperties::new().with_character_spacing_points(3.0),
116                    ))
117                    .with_run(TextRun::text_with_properties(
118                        "highlighted",
119                        TextRunProperties::new().with_highlight(Color::Rgb("FFFF00".to_string())),
120                    ))
121                    .with_run(TextRun::text_with_properties(
122                        "2",
123                        TextRunProperties::new().with_baseline_percent(30.0),
124                    )),
125            ),
126        );
127
128    let field_shape = AutoShape::new(2, "Field")
129        .with_properties(
130            ShapeProperties::new().with_transform(
131                Transform2D::new()
132                    .with_offset(838_200, 838_200)
133                    .with_extent(3_000_000, 500_000),
134            ),
135        )
136        .with_text_body(
137            TextBody::new().with_paragraph(
138                TextParagraph::new()
139                    .with_run(TextRun::text("Slide "))
140                    .with_run(TextRun::field(
141                        "{7A9E3F10-4B6C-4D2E-9A1F-8C5D6E7F0123}",
142                        Some("slidenum".to_string()),
143                        "1",
144                    )),
145            ),
146        );
147
148    let presentation = Presentation::new()
149        .with_slide(Slide::new().with_shape(Shape::AutoShape(spacing_shape)))
150        .with_slide(Slide::new().with_shape(Shape::AutoShape(bullets_shape)))
151        .with_slide(Slide::new().with_shape(Shape::AutoShape(autofit_shape)))
152        .with_slide(Slide::new().with_shape(Shape::AutoShape(casing_shape)))
153        .with_slide(Slide::new().with_shape(Shape::AutoShape(field_shape)));
154
155    presentation.save_to_file(&path)?;
156    println!("Wrote {}", path.display());
157    Ok(())
158}
Source

pub fn with_transform(self, transform: Transform2D) -> ShapeProperties

Sets the shape’s position/size/rotation (<a:xfrm>).

Examples found in repository?
examples/hello_world_pptx.rs (lines 19-23)
14fn main() -> office_toolkit::Result<()> {
15    let path = output_path("hello_world.pptx");
16
17    let text_box = AutoShape::new(2, "Hello box")
18        .with_properties(
19            ShapeProperties::new().with_transform(
20                Transform2D::new()
21                    .with_offset(838_200, 1_365_250)
22                    .with_extent(7_772_400, 1_200_150),
23            ),
24        )
25        .with_text_body(
26            TextBody::new()
27                .with_paragraph(TextParagraph::new().with_run(TextRun::text("Hello, world!"))),
28        );
29
30    // `Presentation` and `Slide` both come from `office_toolkit::prelude`.
31    let presentation =
32        Presentation::new().with_slide(Slide::new().with_shape(Shape::AutoShape(text_box)));
33    presentation.save_to_file(&path)?;
34    println!("Wrote {}", path.display());
35
36    // Read the file back to confirm it is a valid .pptx.
37    let reopened = Presentation::open_file(&path)?;
38    println!("Slide count: {}", reopened.slides.len());
39
40    Ok(())
41}
More examples
Hide additional examples
examples/pptx_notes_and_comments.rs (lines 18-22)
12fn main() -> office_toolkit::Result<()> {
13    let path = output_path("pptx_notes_and_comments.pptx");
14
15    let title = |text: &str| {
16        AutoShape::new(2, "Title")
17            .with_properties(
18                ShapeProperties::new().with_transform(
19                    Transform2D::new()
20                        .with_offset(838_200, 838_200)
21                        .with_extent(8_000_000, 1_000_000),
22                ),
23            )
24            .with_text_body(
25                TextBody::new().with_paragraph(TextParagraph::new().with_run(TextRun::text(text))),
26            )
27    };
28
29    let notes_slide = Slide::new()
30        .with_shape(Shape::AutoShape(title("A slide with speaker notes")))
31        .with_notes(
32            TextBody::new().with_paragraph(
33                TextParagraph::new()
34                    .with_run(TextRun::text("Remember to mention the Q3 numbers here.")),
35            ),
36        );
37
38    let commented_slide = Slide::new()
39        .with_shape(Shape::AutoShape(title("A slide with reviewer comments")))
40        .with_comment(
41            SlideComment::new(
42                "Reviewer",
43                "RV",
44                "2026-07-21T10:00:00",
45                "This claim needs a source.",
46            )
47            .with_position(1_000_000, 2_000_000),
48        )
49        .with_comment(
50            SlideComment::new(
51                "Editor",
52                "ED",
53                "2026-07-21T11:30:00",
54                "Looks good otherwise.",
55            )
56            .with_position(3_000_000, 2_000_000),
57        );
58
59    let presentation = Presentation::new()
60        .with_slide(notes_slide)
61        .with_slide(commented_slide);
62
63    presentation.save_to_file(&path)?;
64    println!("Wrote {}", path.display());
65    Ok(())
66}
examples/pptx_shapes_and_placeholders.rs (lines 19-23)
14fn main() -> office_toolkit::Result<()> {
15    let path = output_path("pptx_shapes_and_placeholders.pptx");
16
17    let plain_shape = AutoShape::new(2, "Plain autoshape")
18        .with_properties(
19            ShapeProperties::new().with_transform(
20                Transform2D::new()
21                    .with_offset(838_200, 838_200)
22                    .with_extent(5_000_000, 1_000_000),
23            ),
24        )
25        .with_text_body(
26            TextBody::new()
27                .with_paragraph(TextParagraph::new().with_run(TextRun::text("A plain autoshape."))),
28        );
29
30    let text_box = AutoShape::new(2, "Text box")
31        .with_text_box(true)
32        .with_properties(
33            ShapeProperties::new().with_transform(
34                Transform2D::new()
35                    .with_offset(838_200, 838_200)
36                    .with_extent(5_000_000, 1_000_000),
37            ),
38        )
39        .with_text_body(TextBody::new().with_paragraph(
40            TextParagraph::new().with_run(TextRun::text("A genuine text box (txBox=\"1\").")),
41        ));
42
43    let title = AutoShape::new(2, "Title placeholder")
44        .with_placeholder(Placeholder::new(PlaceholderKind::CenterTitle))
45        .with_properties(
46            ShapeProperties::new().with_transform(
47                Transform2D::new()
48                    .with_offset(838_200, 838_200)
49                    .with_extent(10_515_600, 1_325_563),
50            ),
51        )
52        .with_text_body(
53            TextBody::new()
54                .with_paragraph(TextParagraph::new().with_run(TextRun::text("Title placeholder"))),
55        );
56    let subtitle =
57        AutoShape::new(3, "Subtitle placeholder")
58            .with_placeholder(Placeholder::new(PlaceholderKind::SubTitle).with_index(1))
59            .with_properties(
60                ShapeProperties::new().with_transform(
61                    Transform2D::new()
62                        .with_offset(838_200, 2_400_000)
63                        .with_extent(10_515_600, 800_000),
64                ),
65            )
66            .with_text_body(TextBody::new().with_paragraph(
67                TextParagraph::new().with_run(TextRun::text("Subtitle placeholder")),
68            ));
69
70    let hyperlinked_shape = AutoShape::new(2, "Hyperlinked shape")
71        .with_hyperlink("https://www.rust-lang.org")
72        .with_properties(
73            ShapeProperties::new().with_transform(
74                Transform2D::new()
75                    .with_offset(838_200, 838_200)
76                    .with_extent(5_000_000, 1_000_000),
77            ),
78        )
79        .with_text_body(TextBody::new().with_paragraph(
80            TextParagraph::new().with_run(TextRun::text("Click this shape to open a link.")),
81        ));
82
83    let presentation = Presentation::new()
84        .with_slide(Slide::new().with_shape(Shape::AutoShape(plain_shape)))
85        .with_slide(Slide::new().with_shape(Shape::AutoShape(text_box)))
86        .with_slide(
87            Slide::new()
88                .with_shape(Shape::AutoShape(title))
89                .with_shape(Shape::AutoShape(subtitle)),
90        )
91        .with_slide(Slide::new().with_shape(Shape::AutoShape(hyperlinked_shape)));
92
93    presentation.save_to_file(&path)?;
94    println!("Wrote {}", path.display());
95    Ok(())
96}
examples/pptx_theme_and_metadata.rs (lines 60-64)
19fn main() -> office_toolkit::Result<()> {
20    // A custom theme and an embedded font. `Theme`/`ColorScheme`/
21    // `FontScheme` have no `with_*` builders in this crate — only
22    // `office_default()` or plain struct literals.
23    let custom_theme = Theme {
24        name: "Custom Brand".to_string(),
25        colors: ColorScheme {
26            dark1: "1B1B1B".to_string(),
27            light1: "FFFFFF".to_string(),
28            dark2: "0A2540".to_string(),
29            light2: "F5F5F5".to_string(),
30            accent1: "0A2540".to_string(),
31            accent2: "E8622C".to_string(),
32            accent3: "2E86AB".to_string(),
33            accent4: "6FB98F".to_string(),
34            accent5: "F4A259".to_string(),
35            accent6: "8E4585".to_string(),
36            hyperlink: "1155CC".to_string(),
37            followed_hyperlink: "6B3FA0".to_string(),
38        },
39        fonts: FontScheme {
40            major_latin: "Georgia".to_string(),
41            minor_latin: "Verdana".to_string(),
42        },
43    };
44
45    // Placeholder bytes — a real .pptx would carry genuine TrueType/
46    // OpenType font data here.
47    let embedded_font = EmbeddedFont::new("Custom Sans")
48        .with_regular(vec![0u8; 16])
49        .with_bold(vec![0u8; 16]);
50
51    // A slide with no shapes at all renders as a blank page — nothing shows
52    // the custom theme actually took effect. `drawing::Color` has no
53    // scheme-relative variant yet (`<a:schemeClr>` isn't modeled, see that
54    // enum's own doc comment), so this can't reference the theme's accent1
55    // symbolically; it uses the same literal hex values the theme itself
56    // was built from, purely so the slide visibly matches the palette above.
57    let title_shape = AutoShape::new(2, "Title")
58        .with_properties(
59            ShapeProperties::new()
60                .with_transform(
61                    Transform2D::new()
62                        .with_offset(838_200, 838_200)
63                        .with_extent(6_000_000, 1_500_000),
64                )
65                .with_fill(Fill::Solid(Color::Rgb(custom_theme.colors.accent1.clone()))),
66        )
67        .with_text_body(
68            TextBody::new().with_paragraph(
69                TextParagraph::new().with_run(TextRun::text_with_properties(
70                    "Custom Brand theme — Georgia / Verdana, accent1 = #0A2540",
71                    TextRunProperties::new()
72                        .with_font_family(custom_theme.fonts.major_latin.clone())
73                        .with_font_size_points(24.0)
74                        .with_fill(Fill::Solid(Color::Rgb(custom_theme.colors.light1.clone()))),
75                )),
76            ),
77        );
78
79    let themed_presentation = Presentation::new()
80        .with_theme(custom_theme)
81        .with_embedded_font(embedded_font)
82        .with_slide(Slide::new().with_shape(Shape::AutoShape(title_shape)));
83    let theme_path = output_path("pptx_theme.pptx");
84    themed_presentation.save_to_file(&theme_path)?;
85    println!("Wrote {}", theme_path.display());
86
87    // Document metadata (docProps/core.xml, app.xml, and custom.xml).
88    let properties = DocumentProperties::new()
89        .with_title("Metadata example")
90        .with_author("Example Author")
91        .with_subject("Presentation-level features")
92        .with_custom_property(
93            "ProjectCode",
94            CustomPropertyValue::Text("PPTX-META".to_string()),
95        );
96    // Same reasoning as `title_shape` above: an empty slide would render
97    // blank, so a text shape spells out where the metadata actually lives.
98    let metadata_shape = AutoShape::new(2, "Note")
99        .with_properties(ShapeProperties::new().with_transform(Transform2D::new().with_offset(838_200, 838_200).with_extent(7_000_000, 1_000_000)))
100        .with_text_body(TextBody::new().with_paragraph(TextParagraph::new().with_run(TextRun::text(
101            "This presentation's metadata is in File > Info (title, author, subject, and a custom \"ProjectCode\" property) — not on this slide.",
102        ))));
103    let metadata_presentation = Presentation::new()
104        .with_properties(properties)
105        .with_slide(Slide::new().with_shape(Shape::AutoShape(metadata_shape)));
106    let metadata_path = output_path("pptx_metadata.pptx");
107    metadata_presentation.save_to_file(&metadata_path)?;
108    println!("Wrote {}", metadata_path.display());
109
110    Ok(())
111}
examples/pptx_grouping_and_connectors.rs (lines 29-33)
16fn main() -> office_toolkit::Result<()> {
17    let path = output_path("pptx_grouping_and_connectors.pptx");
18
19    // Every shape below sets an explicit fill (and the connector an
20    // explicit line): with neither a fill/line nor a `<p:style>` theme
21    // reference, a shape has nothing to paint and renders as fully
22    // invisible — the slide then looks blank even though the shapes are
23    // there. `AutoShape`/`Connector` have no `<p:style>` support yet, so an
24    // explicit `Fill`/`Line` is the only way to make a shape actually show.
25    let circle_fill = || Fill::Solid(Color::Rgb("4472C4".to_string()));
26
27    let circle = AutoShape::new(11, "Circle").with_properties(
28        ShapeProperties::new()
29            .with_transform(
30                Transform2D::new()
31                    .with_offset(0, 0)
32                    .with_extent(1_000_000, 1_000_000),
33            )
34            .with_fill(circle_fill()),
35    );
36    let label = AutoShape::new(12, "Label")
37        .with_properties(
38            ShapeProperties::new()
39                .with_transform(
40                    Transform2D::new()
41                        .with_offset(1_200_000, 300_000)
42                        .with_extent(1_500_000, 400_000),
43                )
44                .with_fill(Fill::Solid(Color::Rgb("E8622C".to_string()))),
45        )
46        .with_text_body(
47            TextBody::new()
48                .with_paragraph(TextParagraph::new().with_run(TextRun::text("Grouped label"))),
49        );
50
51    let group = ShapeGroup::new(2, "Group")
52        .with_transform(
53            (838_200, 838_200),
54            (2_700_000, 1_000_000),
55            (0, 0),
56            (2_700_000, 1_000_000),
57        )
58        .with_shape(Shape::AutoShape(circle))
59        .with_shape(Shape::AutoShape(label));
60
61    let rotated_circle = AutoShape::new(11, "Circle").with_properties(
62        ShapeProperties::new()
63            .with_transform(
64                Transform2D::new()
65                    .with_offset(0, 0)
66                    .with_extent(1_000_000, 1_000_000),
67            )
68            .with_fill(circle_fill()),
69    );
70    let rotated_group = ShapeGroup::new(2, "Rotated and flipped group")
71        .with_transform(
72            (838_200, 838_200),
73            (1_000_000, 1_000_000),
74            (0, 0),
75            (1_000_000, 1_000_000),
76        )
77        .with_rotation_degrees(45.0)
78        .with_flip_horizontal(true)
79        .with_shape(Shape::AutoShape(rotated_circle));
80
81    let box_a = AutoShape::new(2, "Box A").with_properties(
82        ShapeProperties::new()
83            .with_transform(
84                Transform2D::new()
85                    .with_offset(838_200, 838_200)
86                    .with_extent(1_000_000, 1_000_000),
87            )
88            .with_fill(Fill::Solid(Color::Rgb("2E86AB".to_string()))),
89    );
90    let box_b = AutoShape::new(3, "Box B").with_properties(
91        ShapeProperties::new()
92            .with_transform(
93                Transform2D::new()
94                    .with_offset(3_500_000, 838_200)
95                    .with_extent(1_000_000, 1_000_000),
96            )
97            .with_fill(Fill::Solid(Color::Rgb("6FB98F".to_string()))),
98    );
99    // `Connector::new` leaves position/size unset, which the writer then
100    // emits as a zero-size `<a:xfrm>` (off 0,0 / ext 0,0) — a real point
101    // with no length, invisible regardless of line/fill. `stCxn`/`endCxn`
102    // alone don't supply geometry; PowerPoint only recomputes it once you
103    // drag one of the attached shapes. So this also sets an explicit
104    // transform spanning Box A's right edge to Box B's left edge.
105    let connector = Connector::new(4, "Connector")
106        .with_properties(
107            ShapeProperties::new()
108                .with_transform(
109                    Transform2D::new()
110                        .with_offset(1_838_200, 1_338_200)
111                        .with_extent(1_662_000, 0),
112                )
113                .with_line(
114                    Line::new()
115                        .with_width_emu(25_400)
116                        .with_fill(Fill::Solid(Color::Rgb("000000".to_string()))),
117                ),
118        )
119        .with_start_connection(2, 0)
120        .with_end_connection(3, 0);
121
122    let presentation = Presentation::new()
123        .with_slide(Slide::new().with_shape(Shape::Group(group)))
124        .with_slide(Slide::new().with_shape(Shape::Group(rotated_group)))
125        .with_slide(
126            Slide::new()
127                .with_shape(Shape::AutoShape(box_a))
128                .with_shape(Shape::AutoShape(box_b))
129                .with_shape(Shape::Connector(connector)),
130        );
131
132    presentation.save_to_file(&path)?;
133    println!("Wrote {}", path.display());
134    Ok(())
135}
examples/pptx_text_formatting.rs (lines 24-28)
19fn main() -> office_toolkit::Result<()> {
20    let path = output_path("pptx_text_formatting.pptx");
21
22    let spacing_shape = AutoShape::new(2, "Spacing")
23        .with_properties(
24            ShapeProperties::new().with_transform(
25                Transform2D::new()
26                    .with_offset(838_200, 838_200)
27                    .with_extent(6_000_000, 1_500_000),
28            ),
29        )
30        .with_text_body(
31            TextBody::new().with_paragraph(
32                TextParagraph::new()
33                    .with_properties(
34                        TextParagraphProperties::new()
35                            .with_line_spacing(TextSpacing::Percent(150_000))
36                            .with_space_before(TextSpacing::Points(1200))
37                            .with_indent_emu(457_200)
38                            .with_level(1),
39                    )
40                    .with_run(TextRun::text(
41                        "Indented, 150% line spacing, 12pt space before.",
42                    )),
43            ),
44        );
45
46    let bullets_shape = AutoShape::new(2, "Bullets")
47        .with_properties(
48            ShapeProperties::new().with_transform(
49                Transform2D::new()
50                    .with_offset(838_200, 838_200)
51                    .with_extent(6_000_000, 1_800_000),
52            ),
53        )
54        .with_text_body(
55            TextBody::new()
56                .with_paragraph(
57                    TextParagraph::new()
58                        .with_properties(
59                            TextParagraphProperties::new()
60                                .with_bullet(BulletKind::Character("\u{2022}".to_string())),
61                        )
62                        .with_run(TextRun::text("Bulleted item")),
63                )
64                .with_paragraph(
65                    TextParagraph::new()
66                        .with_properties(TextParagraphProperties::new().with_bullet(
67                            BulletKind::AutoNumber {
68                                scheme: "arabicPeriod".to_string(),
69                                start_at: None,
70                            },
71                        ))
72                        .with_run(TextRun::text("Auto-numbered item")),
73                ),
74        );
75
76    let autofit_shape = AutoShape::new(2, "Autofit")
77        .with_text_box(true)
78        .with_properties(
79            ShapeProperties::new().with_transform(
80                Transform2D::new()
81                    .with_offset(838_200, 838_200)
82                    .with_extent(4_000_000, 1_000_000),
83            ),
84        )
85        .with_text_body(
86            TextBody::new()
87                .with_properties(
88                    TextBodyProperties::new()
89                        .with_autofit(TextAutofit::Shape)
90                        .with_anchor(TextAnchor::Center)
91                        .with_anchor_center(true),
92                )
93                .with_paragraph(TextParagraph::new().with_run(TextRun::text(
94                    "This shape resizes to fit its text, centered both ways.",
95                ))),
96        );
97
98    let casing_shape = AutoShape::new(2, "Casing")
99        .with_properties(
100            ShapeProperties::new().with_transform(
101                Transform2D::new()
102                    .with_offset(838_200, 838_200)
103                    .with_extent(6_000_000, 1_500_000),
104            ),
105        )
106        .with_text_body(
107            TextBody::new().with_paragraph(
108                TextParagraph::new()
109                    .with_run(TextRun::text_with_properties(
110                        "rendered in all caps, ",
111                        TextRunProperties::new().with_text_caps(TextCaps::All),
112                    ))
113                    .with_run(TextRun::text_with_properties(
114                        "widely spaced, ",
115                        TextRunProperties::new().with_character_spacing_points(3.0),
116                    ))
117                    .with_run(TextRun::text_with_properties(
118                        "highlighted",
119                        TextRunProperties::new().with_highlight(Color::Rgb("FFFF00".to_string())),
120                    ))
121                    .with_run(TextRun::text_with_properties(
122                        "2",
123                        TextRunProperties::new().with_baseline_percent(30.0),
124                    )),
125            ),
126        );
127
128    let field_shape = AutoShape::new(2, "Field")
129        .with_properties(
130            ShapeProperties::new().with_transform(
131                Transform2D::new()
132                    .with_offset(838_200, 838_200)
133                    .with_extent(3_000_000, 500_000),
134            ),
135        )
136        .with_text_body(
137            TextBody::new().with_paragraph(
138                TextParagraph::new()
139                    .with_run(TextRun::text("Slide "))
140                    .with_run(TextRun::field(
141                        "{7A9E3F10-4B6C-4D2E-9A1F-8C5D6E7F0123}",
142                        Some("slidenum".to_string()),
143                        "1",
144                    )),
145            ),
146        );
147
148    let presentation = Presentation::new()
149        .with_slide(Slide::new().with_shape(Shape::AutoShape(spacing_shape)))
150        .with_slide(Slide::new().with_shape(Shape::AutoShape(bullets_shape)))
151        .with_slide(Slide::new().with_shape(Shape::AutoShape(autofit_shape)))
152        .with_slide(Slide::new().with_shape(Shape::AutoShape(casing_shape)))
153        .with_slide(Slide::new().with_shape(Shape::AutoShape(field_shape)));
154
155    presentation.save_to_file(&path)?;
156    println!("Wrote {}", path.display());
157    Ok(())
158}
Source

pub fn with_geometry(self, geometry: Geometry) -> ShapeProperties

Sets the shape’s outline (EG_Geometry).

Source

pub fn with_fill(self, fill: Fill) -> ShapeProperties

Sets the shape’s interior fill (EG_FillProperties).

Examples found in repository?
examples/pptx_theme_and_metadata.rs (line 65)
19fn main() -> office_toolkit::Result<()> {
20    // A custom theme and an embedded font. `Theme`/`ColorScheme`/
21    // `FontScheme` have no `with_*` builders in this crate — only
22    // `office_default()` or plain struct literals.
23    let custom_theme = Theme {
24        name: "Custom Brand".to_string(),
25        colors: ColorScheme {
26            dark1: "1B1B1B".to_string(),
27            light1: "FFFFFF".to_string(),
28            dark2: "0A2540".to_string(),
29            light2: "F5F5F5".to_string(),
30            accent1: "0A2540".to_string(),
31            accent2: "E8622C".to_string(),
32            accent3: "2E86AB".to_string(),
33            accent4: "6FB98F".to_string(),
34            accent5: "F4A259".to_string(),
35            accent6: "8E4585".to_string(),
36            hyperlink: "1155CC".to_string(),
37            followed_hyperlink: "6B3FA0".to_string(),
38        },
39        fonts: FontScheme {
40            major_latin: "Georgia".to_string(),
41            minor_latin: "Verdana".to_string(),
42        },
43    };
44
45    // Placeholder bytes — a real .pptx would carry genuine TrueType/
46    // OpenType font data here.
47    let embedded_font = EmbeddedFont::new("Custom Sans")
48        .with_regular(vec![0u8; 16])
49        .with_bold(vec![0u8; 16]);
50
51    // A slide with no shapes at all renders as a blank page — nothing shows
52    // the custom theme actually took effect. `drawing::Color` has no
53    // scheme-relative variant yet (`<a:schemeClr>` isn't modeled, see that
54    // enum's own doc comment), so this can't reference the theme's accent1
55    // symbolically; it uses the same literal hex values the theme itself
56    // was built from, purely so the slide visibly matches the palette above.
57    let title_shape = AutoShape::new(2, "Title")
58        .with_properties(
59            ShapeProperties::new()
60                .with_transform(
61                    Transform2D::new()
62                        .with_offset(838_200, 838_200)
63                        .with_extent(6_000_000, 1_500_000),
64                )
65                .with_fill(Fill::Solid(Color::Rgb(custom_theme.colors.accent1.clone()))),
66        )
67        .with_text_body(
68            TextBody::new().with_paragraph(
69                TextParagraph::new().with_run(TextRun::text_with_properties(
70                    "Custom Brand theme — Georgia / Verdana, accent1 = #0A2540",
71                    TextRunProperties::new()
72                        .with_font_family(custom_theme.fonts.major_latin.clone())
73                        .with_font_size_points(24.0)
74                        .with_fill(Fill::Solid(Color::Rgb(custom_theme.colors.light1.clone()))),
75                )),
76            ),
77        );
78
79    let themed_presentation = Presentation::new()
80        .with_theme(custom_theme)
81        .with_embedded_font(embedded_font)
82        .with_slide(Slide::new().with_shape(Shape::AutoShape(title_shape)));
83    let theme_path = output_path("pptx_theme.pptx");
84    themed_presentation.save_to_file(&theme_path)?;
85    println!("Wrote {}", theme_path.display());
86
87    // Document metadata (docProps/core.xml, app.xml, and custom.xml).
88    let properties = DocumentProperties::new()
89        .with_title("Metadata example")
90        .with_author("Example Author")
91        .with_subject("Presentation-level features")
92        .with_custom_property(
93            "ProjectCode",
94            CustomPropertyValue::Text("PPTX-META".to_string()),
95        );
96    // Same reasoning as `title_shape` above: an empty slide would render
97    // blank, so a text shape spells out where the metadata actually lives.
98    let metadata_shape = AutoShape::new(2, "Note")
99        .with_properties(ShapeProperties::new().with_transform(Transform2D::new().with_offset(838_200, 838_200).with_extent(7_000_000, 1_000_000)))
100        .with_text_body(TextBody::new().with_paragraph(TextParagraph::new().with_run(TextRun::text(
101            "This presentation's metadata is in File > Info (title, author, subject, and a custom \"ProjectCode\" property) — not on this slide.",
102        ))));
103    let metadata_presentation = Presentation::new()
104        .with_properties(properties)
105        .with_slide(Slide::new().with_shape(Shape::AutoShape(metadata_shape)));
106    let metadata_path = output_path("pptx_metadata.pptx");
107    metadata_presentation.save_to_file(&metadata_path)?;
108    println!("Wrote {}", metadata_path.display());
109
110    Ok(())
111}
More examples
Hide additional examples
examples/pptx_grouping_and_connectors.rs (line 34)
16fn main() -> office_toolkit::Result<()> {
17    let path = output_path("pptx_grouping_and_connectors.pptx");
18
19    // Every shape below sets an explicit fill (and the connector an
20    // explicit line): with neither a fill/line nor a `<p:style>` theme
21    // reference, a shape has nothing to paint and renders as fully
22    // invisible — the slide then looks blank even though the shapes are
23    // there. `AutoShape`/`Connector` have no `<p:style>` support yet, so an
24    // explicit `Fill`/`Line` is the only way to make a shape actually show.
25    let circle_fill = || Fill::Solid(Color::Rgb("4472C4".to_string()));
26
27    let circle = AutoShape::new(11, "Circle").with_properties(
28        ShapeProperties::new()
29            .with_transform(
30                Transform2D::new()
31                    .with_offset(0, 0)
32                    .with_extent(1_000_000, 1_000_000),
33            )
34            .with_fill(circle_fill()),
35    );
36    let label = AutoShape::new(12, "Label")
37        .with_properties(
38            ShapeProperties::new()
39                .with_transform(
40                    Transform2D::new()
41                        .with_offset(1_200_000, 300_000)
42                        .with_extent(1_500_000, 400_000),
43                )
44                .with_fill(Fill::Solid(Color::Rgb("E8622C".to_string()))),
45        )
46        .with_text_body(
47            TextBody::new()
48                .with_paragraph(TextParagraph::new().with_run(TextRun::text("Grouped label"))),
49        );
50
51    let group = ShapeGroup::new(2, "Group")
52        .with_transform(
53            (838_200, 838_200),
54            (2_700_000, 1_000_000),
55            (0, 0),
56            (2_700_000, 1_000_000),
57        )
58        .with_shape(Shape::AutoShape(circle))
59        .with_shape(Shape::AutoShape(label));
60
61    let rotated_circle = AutoShape::new(11, "Circle").with_properties(
62        ShapeProperties::new()
63            .with_transform(
64                Transform2D::new()
65                    .with_offset(0, 0)
66                    .with_extent(1_000_000, 1_000_000),
67            )
68            .with_fill(circle_fill()),
69    );
70    let rotated_group = ShapeGroup::new(2, "Rotated and flipped group")
71        .with_transform(
72            (838_200, 838_200),
73            (1_000_000, 1_000_000),
74            (0, 0),
75            (1_000_000, 1_000_000),
76        )
77        .with_rotation_degrees(45.0)
78        .with_flip_horizontal(true)
79        .with_shape(Shape::AutoShape(rotated_circle));
80
81    let box_a = AutoShape::new(2, "Box A").with_properties(
82        ShapeProperties::new()
83            .with_transform(
84                Transform2D::new()
85                    .with_offset(838_200, 838_200)
86                    .with_extent(1_000_000, 1_000_000),
87            )
88            .with_fill(Fill::Solid(Color::Rgb("2E86AB".to_string()))),
89    );
90    let box_b = AutoShape::new(3, "Box B").with_properties(
91        ShapeProperties::new()
92            .with_transform(
93                Transform2D::new()
94                    .with_offset(3_500_000, 838_200)
95                    .with_extent(1_000_000, 1_000_000),
96            )
97            .with_fill(Fill::Solid(Color::Rgb("6FB98F".to_string()))),
98    );
99    // `Connector::new` leaves position/size unset, which the writer then
100    // emits as a zero-size `<a:xfrm>` (off 0,0 / ext 0,0) — a real point
101    // with no length, invisible regardless of line/fill. `stCxn`/`endCxn`
102    // alone don't supply geometry; PowerPoint only recomputes it once you
103    // drag one of the attached shapes. So this also sets an explicit
104    // transform spanning Box A's right edge to Box B's left edge.
105    let connector = Connector::new(4, "Connector")
106        .with_properties(
107            ShapeProperties::new()
108                .with_transform(
109                    Transform2D::new()
110                        .with_offset(1_838_200, 1_338_200)
111                        .with_extent(1_662_000, 0),
112                )
113                .with_line(
114                    Line::new()
115                        .with_width_emu(25_400)
116                        .with_fill(Fill::Solid(Color::Rgb("000000".to_string()))),
117                ),
118        )
119        .with_start_connection(2, 0)
120        .with_end_connection(3, 0);
121
122    let presentation = Presentation::new()
123        .with_slide(Slide::new().with_shape(Shape::Group(group)))
124        .with_slide(Slide::new().with_shape(Shape::Group(rotated_group)))
125        .with_slide(
126            Slide::new()
127                .with_shape(Shape::AutoShape(box_a))
128                .with_shape(Shape::AutoShape(box_b))
129                .with_shape(Shape::Connector(connector)),
130        );
131
132    presentation.save_to_file(&path)?;
133    println!("Wrote {}", path.display());
134    Ok(())
135}
Source

pub fn with_line(self, line: Line) -> ShapeProperties

Sets the shape’s outline stroke (<a:ln>).

Examples found in repository?
examples/pptx_grouping_and_connectors.rs (lines 113-117)
16fn main() -> office_toolkit::Result<()> {
17    let path = output_path("pptx_grouping_and_connectors.pptx");
18
19    // Every shape below sets an explicit fill (and the connector an
20    // explicit line): with neither a fill/line nor a `<p:style>` theme
21    // reference, a shape has nothing to paint and renders as fully
22    // invisible — the slide then looks blank even though the shapes are
23    // there. `AutoShape`/`Connector` have no `<p:style>` support yet, so an
24    // explicit `Fill`/`Line` is the only way to make a shape actually show.
25    let circle_fill = || Fill::Solid(Color::Rgb("4472C4".to_string()));
26
27    let circle = AutoShape::new(11, "Circle").with_properties(
28        ShapeProperties::new()
29            .with_transform(
30                Transform2D::new()
31                    .with_offset(0, 0)
32                    .with_extent(1_000_000, 1_000_000),
33            )
34            .with_fill(circle_fill()),
35    );
36    let label = AutoShape::new(12, "Label")
37        .with_properties(
38            ShapeProperties::new()
39                .with_transform(
40                    Transform2D::new()
41                        .with_offset(1_200_000, 300_000)
42                        .with_extent(1_500_000, 400_000),
43                )
44                .with_fill(Fill::Solid(Color::Rgb("E8622C".to_string()))),
45        )
46        .with_text_body(
47            TextBody::new()
48                .with_paragraph(TextParagraph::new().with_run(TextRun::text("Grouped label"))),
49        );
50
51    let group = ShapeGroup::new(2, "Group")
52        .with_transform(
53            (838_200, 838_200),
54            (2_700_000, 1_000_000),
55            (0, 0),
56            (2_700_000, 1_000_000),
57        )
58        .with_shape(Shape::AutoShape(circle))
59        .with_shape(Shape::AutoShape(label));
60
61    let rotated_circle = AutoShape::new(11, "Circle").with_properties(
62        ShapeProperties::new()
63            .with_transform(
64                Transform2D::new()
65                    .with_offset(0, 0)
66                    .with_extent(1_000_000, 1_000_000),
67            )
68            .with_fill(circle_fill()),
69    );
70    let rotated_group = ShapeGroup::new(2, "Rotated and flipped group")
71        .with_transform(
72            (838_200, 838_200),
73            (1_000_000, 1_000_000),
74            (0, 0),
75            (1_000_000, 1_000_000),
76        )
77        .with_rotation_degrees(45.0)
78        .with_flip_horizontal(true)
79        .with_shape(Shape::AutoShape(rotated_circle));
80
81    let box_a = AutoShape::new(2, "Box A").with_properties(
82        ShapeProperties::new()
83            .with_transform(
84                Transform2D::new()
85                    .with_offset(838_200, 838_200)
86                    .with_extent(1_000_000, 1_000_000),
87            )
88            .with_fill(Fill::Solid(Color::Rgb("2E86AB".to_string()))),
89    );
90    let box_b = AutoShape::new(3, "Box B").with_properties(
91        ShapeProperties::new()
92            .with_transform(
93                Transform2D::new()
94                    .with_offset(3_500_000, 838_200)
95                    .with_extent(1_000_000, 1_000_000),
96            )
97            .with_fill(Fill::Solid(Color::Rgb("6FB98F".to_string()))),
98    );
99    // `Connector::new` leaves position/size unset, which the writer then
100    // emits as a zero-size `<a:xfrm>` (off 0,0 / ext 0,0) — a real point
101    // with no length, invisible regardless of line/fill. `stCxn`/`endCxn`
102    // alone don't supply geometry; PowerPoint only recomputes it once you
103    // drag one of the attached shapes. So this also sets an explicit
104    // transform spanning Box A's right edge to Box B's left edge.
105    let connector = Connector::new(4, "Connector")
106        .with_properties(
107            ShapeProperties::new()
108                .with_transform(
109                    Transform2D::new()
110                        .with_offset(1_838_200, 1_338_200)
111                        .with_extent(1_662_000, 0),
112                )
113                .with_line(
114                    Line::new()
115                        .with_width_emu(25_400)
116                        .with_fill(Fill::Solid(Color::Rgb("000000".to_string()))),
117                ),
118        )
119        .with_start_connection(2, 0)
120        .with_end_connection(3, 0);
121
122    let presentation = Presentation::new()
123        .with_slide(Slide::new().with_shape(Shape::Group(group)))
124        .with_slide(Slide::new().with_shape(Shape::Group(rotated_group)))
125        .with_slide(
126            Slide::new()
127                .with_shape(Shape::AutoShape(box_a))
128                .with_shape(Shape::AutoShape(box_b))
129                .with_shape(Shape::Connector(connector)),
130        );
131
132    presentation.save_to_file(&path)?;
133    println!("Wrote {}", path.display());
134    Ok(())
135}
Source

pub fn with_effects(self, effects: EffectList) -> ShapeProperties

Sets the shape’s visual effects (<a:effectLst>).

Source

pub fn with_geometry_adjustments( self, adjustments: Vec<GeometryAdjustment>, ) -> ShapeProperties

Sets a preset shape’s adjustment handle values (<a:avLst>); no effect unless geometry is also Some(Geometry::Preset(_)).

Trait Implementations§

Source§

impl Clone for ShapeProperties

Source§

fn clone(&self) -> ShapeProperties

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ShapeProperties

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Default for ShapeProperties

Source§

fn default() -> ShapeProperties

Returns the “default value” for a type. Read more
Source§

impl PartialEq for ShapeProperties

Source§

fn eq(&self, other: &ShapeProperties) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for ShapeProperties

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.