Render Presentation Slides as SVG Images in C++
Overview
SVG is a scalable XML-based image format that works well for web publishing, slide viewers, accessibility workflows, and automated post-processing. Aspose.Slides for C++ exports each slide to a separate SVG file and lets you control how text, fonts, pictures, and SVG elements are written.
Use SVGOptions when the exported SVG must be compact, predictable across browsers, or ready for interactive use.
Export a Slide as SVG
Create a Presentation, select a slide, and write it to a stream. The following example exports every slide in a presentation as a separate SVG file.
#include <DOM/ISlide.h>
#include <DOM/Presentation.h>
#include <system/io/file.h>
#include <system/string.h>
using namespace Aspose::Slides;
using namespace System;
using namespace System::IO;
auto presentation = MakeObject<Presentation>(u"presentation.pptx");
auto slideCount = presentation->get_Slides()->get_Count();
for (int slideIndex = 0; slideIndex < slideCount; slideIndex++)
{
auto slide = presentation->get_Slide(slideIndex);
auto svgFileName = String::Format(u"slide-{0}.svg", slide->get_SlideNumber());
auto svgStream = File::Create(svgFileName);
slide->WriteAsSvg(svgStream);
svgStream->Dispose();
}
presentation->Dispose();
The filename uses ISlide::get_SlideNumber rather than the loop index. You can also export an individual shape with IShape::WriteAsSvg when a slide viewer or web page needs only that shape.
Configure SVG Output
SVGOptions controls SVG rendering. For text frames, SVGOptions::set_UseFrameSize includes the text frame in the rendering area, and SVGOptions::set_UseFrameRotation determines whether the frame rotation is applied. Set SVGOptions::set_DisableFontLigatures to true when text must be rendered without ligatures.
#include <DOM/ISlide.h>
#include <DOM/Presentation.h>
#include <Export/SVGOptions.h>
#include <system/io/file.h>
using namespace Aspose::Slides;
using namespace Aspose::Slides::Export;
using namespace System;
using namespace System::IO;
auto presentation = MakeObject<Presentation>(u"presentation.pptx");
auto svgOptions = MakeObject<SVGOptions>();
svgOptions->set_DisableFontLigatures(true);
svgOptions->set_UseFrameSize(true);
svgOptions->set_UseFrameRotation(false);
auto slide = presentation->get_Slide(0);
auto svgStream = File::Create(u"slide-with-custom-options.svg");
slide->WriteAsSvg(svgStream, svgOptions);
svgStream->Dispose();
presentation->Dispose();
Control Line-End Cropping at Arrowheads
SVG 1.1 has no marker inset setting to specify where a line should stop beneath an arrowhead. By default, Aspose.Slides shortens the exported line so its stroke does not protrude through the marker. Set SVGOptions::set_DisableLineEndCropping to true to draw the stroke all the way to the line’s original endpoint. This setting affects only the SVG output. The line keeps its position and length on the slide.
The example draws triangle and diamond arrowheads on lines 2 and 10 points wide. It exports the same slide twice, changing only the cropping option.
#include <DOM/IAutoShape.h>
#include <DOM/IColorFormat.h>
#include <DOM/IFillFormat.h>
#include <DOM/ILineFormat.h>
#include <DOM/IShapeCollection.h>
#include <DOM/ISlide.h>
#include <DOM/Presentation.h>
#include <DOM/FillType.h>
#include <DOM/LineArrowheadStyle.h>
#include <DOM/ShapeType.h>
#include <Export/SVGOptions.h>
#include <drawing/color.h>
#include <system/io/file.h>
using namespace Aspose::Slides;
using namespace Aspose::Slides::Export;
using namespace System;
using namespace System::Drawing;
using namespace System::IO;
auto presentation = MakeObject<Presentation>();
auto slide = presentation->get_Slide(0);
auto y = 40;
const LineArrowheadStyle styles[] = { LineArrowheadStyle::Triangle, LineArrowheadStyle::Diamond };
const int widths[] = { 2, 10 };
for (auto style : styles)
{
for (auto width : widths)
{
auto line = slide->get_Shapes()->AddAutoShape(ShapeType::Line, 40, y, 200, 0);
auto format = line->get_LineFormat();
format->get_FillFormat()->set_FillType(FillType::Solid);
format->get_FillFormat()->get_SolidFillColor()->set_Color(Color::get_DarkBlue());
format->set_Width(width);
format->set_EndArrowheadStyle(style);
y += 50;
}
}
auto options = MakeObject<SVGOptions>();
options->set_DisableLineEndCropping(false);
auto cropped = File::Create(u"cropped.svg");
slide->WriteAsSvg(cropped, options);
cropped->Dispose();
options->set_DisableLineEndCropping(true);
auto uncropped = File::Create(u"uncropped.svg");
slide->WriteAsSvg(uncropped, options);
uncropped->Dispose();
presentation->Dispose();
The comparison shows the triangular arrowhead on the 10-point line. With cropping enabled, the tip is sharp. With cropping disabled, the stroke protrudes through the sloping sides of the marker and leaves a flat end.

In the other lines from the example, the protruding stroke is less visible on the 2-point triangle. The filled diamond covers the end of the stroke at both widths.
Control Text and Fonts
When exporting slides to SVG, you can control whether text remains as text or is converted to vector graphics, and how external fonts are included or referenced. The following options help you balance visual consistency, text selection, and font dependencies in the exported SVG.
Vectorize All Text
Set SVGOptions::set_VectorizeText to true to write all slide text as vector graphics. This eliminates font dependencies and makes the visual result more consistent across browsers, but the text is no longer selectable or searchable as SVG text.
#include <DOM/ISlide.h>
#include <DOM/Presentation.h>
#include <Export/SVGOptions.h>
#include <system/io/file.h>
using namespace Aspose::Slides;
using namespace Aspose::Slides::Export;
using namespace System;
using namespace System::IO;
auto presentation = MakeObject<Presentation>(u"presentation.pptx");
auto svgOptions = MakeObject<SVGOptions>();
svgOptions->set_VectorizeText(true);
auto slide = presentation->get_Slide(0);
auto svgStream = File::Create(u"slide-with-vectorized-text.svg");
slide->WriteAsSvg(svgStream, svgOptions);
svgStream->Dispose();
presentation->Dispose();
Choose How External Fonts Are Handled
SVGOptions::set_ExternalFontsHandling uses a SvgExternalFontsHandling value for fonts that are loaded externally. Choose AddLinksToFontFiles to reference separate font files, Embed to include font data in the SVG, or Vectorize to render only text that uses external fonts as graphics. Verify font licensing before embedding fonts.
#include <DOM/ISlide.h>
#include <DOM/Presentation.h>
#include <Export/SVGOptions.h>
#include <Export/SvgExternalFontsHandling.h>
#include <system/io/file.h>
using namespace Aspose::Slides;
using namespace Aspose::Slides::Export;
using namespace System;
using namespace System::IO;
auto presentation = MakeObject<Presentation>(u"presentation.pptx");
auto slide = presentation->get_Slide(0);
auto linkedFontsOptions = MakeObject<SVGOptions>();
linkedFontsOptions->set_ExternalFontsHandling(SvgExternalFontsHandling::AddLinksToFontFiles);
auto linkedFontsStream = File::Create(u"slide-with-font-links.svg");
slide->WriteAsSvg(linkedFontsStream, linkedFontsOptions);
linkedFontsStream->Dispose();
auto embeddedFontsOptions = MakeObject<SVGOptions>();
embeddedFontsOptions->set_ExternalFontsHandling(SvgExternalFontsHandling::Embed);
auto embeddedFontsStream = File::Create(u"slide-with-embedded-fonts.svg");
slide->WriteAsSvg(embeddedFontsStream, embeddedFontsOptions);
embeddedFontsStream->Dispose();
auto vectorizedExternalFontsOptions = MakeObject<SVGOptions>();
vectorizedExternalFontsOptions->set_ExternalFontsHandling(SvgExternalFontsHandling::Vectorize);
auto vectorizedExternalFontsStream = File::Create(u"slide-with-vectorized-external-fonts.svg");
slide->WriteAsSvg(vectorizedExternalFontsStream, vectorizedExternalFontsOptions);
vectorizedExternalFontsStream->Dispose();
presentation->Dispose();
Reduce Embedded Image Size
Use SVGOptions::set_PicturesCompression to reduce the resolution of embedded pictures, SVGOptions::set_DeletePicturesCroppedAreas to omit cropped source areas, and SVGOptions::set_JpegQuality to control JPEG encoding quality. These settings reduce file size at the cost of image fidelity or retained image data.
#include <DOM/ISlide.h>
#include <DOM/Presentation.h>
#include <Export/PicturesCompression.h>
#include <Export/SVGOptions.h>
#include <system/io/file.h>
using namespace Aspose::Slides;
using namespace Aspose::Slides::Export;
using namespace System;
using namespace System::IO;
auto presentation = MakeObject<Presentation>(u"presentation.pptx");
auto svgOptions = MakeObject<SVGOptions>();
svgOptions->set_PicturesCompression(PicturesCompression::Dpi150);
svgOptions->set_DeletePicturesCroppedAreas(true);
svgOptions->set_JpegQuality(80);
auto slide = presentation->get_Slide(0);
auto svgStream = File::Create(u"compressed-slide.svg");
slide->WriteAsSvg(svgStream, svgOptions);
svgStream->Dispose();
presentation->Dispose();
Control Metafile Rasterization Resolution
SVGOptions::set_MetafileRasterizationDpi sets the lower resolution limit for rasterizing metafiles during SVG export. Use it to balance detail and file size when an EMF or WMF image is rasterized. It does not define a global DPI for the SVG or force every object on the slide to become a raster image.
Download metafile-rasterization.pptx, which contains an EMF image with closely spaced diagonal lines. The following example exports its first slide at three rasterization resolutions through ISlide::WriteAsSvg. All other export settings remain identical so that the results can be compared.
#include <DOM/ISlide.h>
#include <DOM/Presentation.h>
#include <Export/PicturesCompression.h>
#include <Export/SVGOptions.h>
#include <system/io/file.h>
#include <system/string.h>
using namespace Aspose::Slides;
using namespace Aspose::Slides::Export;
using namespace System;
using namespace System::IO;
auto presentation = MakeObject<Presentation>(u"metafile-rasterization.pptx");
auto slide = presentation->get_Slide(0);
const int resolutions[] = { 72, 150, 300 };
for (auto dpi : resolutions)
{
auto svgOptions = MakeObject<SVGOptions>();
svgOptions->set_MetafileRasterizationDpi(dpi);
svgOptions->set_PicturesCompression(PicturesCompression::Dpi330);
svgOptions->set_JpegQuality(90);
auto svgFileName = String::Format(u"slide-{0}.svg", dpi);
auto svgStream = File::Create(svgFileName);
slide->WriteAsSvg(svgStream, svgOptions);
svgStream->Dispose();
}
presentation->Dispose();
In the output, the EMF became one embedded PNG in each SVG. The following measurements are for the supplied presentation; they are not a general formula for converting DPI to pixel dimensions.
| Metafile rasterization DPI | Embedded PNG dimensions | SVG file size (bytes) |
|---|---|---|
| 72 | 1196 × 596 | 170,221 |
| 150 | 2492 × 1242 | 423,149 |
| 300 | 4983 × 2483 | 1,027,169 |
The comparison below shows the same area of the embedded raster at the same enlarged display size. The diagonal lines show visible pixelation at 72 DPI and smoother edges at higher resolutions, while the SVG file grows. Increasing the value does not necessarily improve every detail or change every exported image.

SVGOptions::set_PicturesCompression controls image resolution reduction and can mask the effect of changing the metafile rasterization resolution. SVGOptions::set_JpegQuality controls JPEG encoding quality, not metafile rasterization resolution.
Assign Stable IDs to Shapes and Text
Use ISvgShapeFormattingController to set ISvgShape::set_Id for each SVG shape. To set ISvgTSpan::set_Id values on text tspan elements as well, implement ISvgShapeAndTextFormattingController. Assign either controller with SVGOptions::set_ShapeFormattingController.
The following controller uses IShape::get_OfficeInteropShapeId, which is stable for the lifetime of the shape, and a repeatable counter for its text spans. This makes the generated IDs suitable for post-processing an unchanged presentation.
#include <DOM/IPortion.h>
#include <DOM/IShape.h>
#include <DOM/ISlide.h>
#include <DOM/ITextFrame.h>
#include <DOM/Presentation.h>
#include <Export/ISvgShape.h>
#include <Export/ISvgShapeAndTextFormattingController.h>
#include <Export/ISvgTSpan.h>
#include <Export/SVGOptions.h>
#include <system/io/file.h>
#include <system/string.h>
using namespace Aspose::Slides;
using namespace Aspose::Slides::Export;
using namespace System;
using namespace System::IO;
class StableSvgIdController : public ISvgShapeAndTextFormattingController
{
private:
String m_currentShapeId;
int m_textSpanIndex = 0;
public:
void FormatShape(SharedPtr<ISvgShape> svgShape, SharedPtr<IShape> shape) override
{
m_currentShapeId = String::Format(u"shape-{0}", shape->get_OfficeInteropShapeId());
m_textSpanIndex = 0;
svgShape->set_Id(m_currentShapeId);
}
void FormatText(SharedPtr<ISvgTSpan> svgTSpan, SharedPtr<IPortion> portion,
SharedPtr<ITextFrame> textFrame) override
{
auto currentTextSpanIndex = m_textSpanIndex;
m_textSpanIndex++;
svgTSpan->set_Id(String::Format(u"{0}-text-{1}", m_currentShapeId, currentTextSpanIndex));
}
};
auto presentation = MakeObject<Presentation>(u"presentation.pptx");
auto svgOptions = MakeObject<SVGOptions>();
svgOptions->set_ShapeFormattingController(MakeObject<StableSvgIdController>());
auto slide = presentation->get_Slide(0);
auto svgStream = File::Create(u"slide-with-stable-ids.svg");
slide->WriteAsSvg(svgStream, svgOptions);
svgStream->Dispose();
presentation->Dispose();
Add SVG Event Handlers
In an ISvgShapeFormattingController, call ISvgShape::SetEventHandler with a SvgEvent value to add a JavaScript event handler to an exported shape. Assign the controller with SVGOptions::set_ShapeFormattingController and define the JavaScript function in the page or SVG document that hosts the result.
#include <DOM/IShape.h>
#include <DOM/ISlide.h>
#include <DOM/Presentation.h>
#include <Export/ISvgShape.h>
#include <Export/ISvgShapeFormattingController.h>
#include <Export/SVGOptions.h>
#include <Export/SvgEvent.h>
#include <system/io/file.h>
using namespace Aspose::Slides;
using namespace Aspose::Slides::Export;
using namespace System;
using namespace System::IO;
class SvgEventController : public ISvgShapeFormattingController
{
public:
void FormatShape(SharedPtr<ISvgShape> svgShape, SharedPtr<IShape> shape) override
{
if (shape->get_Name() == u"ActionButton")
{
svgShape->set_Id(u"action-button");
svgShape->SetEventHandler(SvgEvent::OnClick, u"handleShapeClick(event)");
}
}
};
auto presentation = MakeObject<Presentation>(u"presentation.pptx");
auto svgOptions = MakeObject<SVGOptions>();
svgOptions->set_ShapeFormattingController(MakeObject<SvgEventController>());
auto slide = presentation->get_Slide(0);
auto svgStream = File::Create(u"interactive-slide.svg");
slide->WriteAsSvg(svgStream, svgOptions);
svgStream->Dispose();
presentation->Dispose();
The host page can define the JavaScript function referenced by the handler. Assigning IDs and event handlers enables slide viewers, accessibility enhancements, and other interactive SVG workflows.
FAQ
When should I use SVGOptions::set_VectorizeText instead of SvgExternalFontsHandling::Vectorize?
Use SVGOptions::set_VectorizeText when all text must be independent of fonts. Use SvgExternalFontsHandling::Vectorize when only text that uses external fonts should be converted to graphics.
What is the best way to make an SVG smaller?
Start by compressing embedded pictures, deleting cropped image areas, and choosing linked font files when the target environment can serve them. Test the result because lower image resolution, lower JPEG quality, and vectorized text each have different quality and size tradeoffs.
Can I modify exported SVG elements after export?
Yes. Assign IDs through a formatting controller, then select the matching SVG elements in your post-processing tool or browser script.