Basic PDF
This example shows how to create a simple PDF file with rix/pdf.
The example uses the public Rix facade:
#include <rix.hpp>and accesses PDF through:
rix.pdfUse this example when you want the smallest complete PDF generation flow.
Create the file
mkdir -p ~/rix-pdf-basic-example
cd ~/rix-pdf-basic-example
touch basic.cppAdd:
#include <rix.hpp>
int main()
{
auto doc = rix.pdf.document();
auto &page = doc.add_page();
page.text(
page.x_left(),
page.y_top(),
"Hello from rix.pdf");
page.text(
page.x_left(),
page.y_top() - 30.0F,
"This PDF was generated through the unified Rix facade.");
auto saved = rix.pdf.save(doc, "rix_pdf_basic.pdf");
if (saved.failed())
{
rix.debug.eprint(
"pdf error:",
rix.pdf.error.to_string(saved.error()),
saved.error().message());
return 1;
}
rix.debug.print("created:", "rix_pdf_basic.pdf");
return 0;
}Run it:
vix run basic.cppIf Rix is not available yet for single-file usage:
vix install -g rix/rix
vix run basic.cppThis creates:
rix_pdf_basic.pdfWhat this example does
The example creates a PDF document:
auto doc = rix.pdf.document();It adds a page:
auto &page = doc.add_page();It writes two text lines:
page.text(
page.x_left(),
page.y_top(),
"Hello from rix.pdf");Then it saves the file:
auto saved = rix.pdf.save(doc, "rix_pdf_basic.pdf");Create a document
Use:
auto doc = rix.pdf.document();A document owns pages and metadata.
It does not create a file until you call:
rix.pdf.save(...)or generate bytes with:
rix.pdf.write(...)Add a page
Use:
auto &page = doc.add_page();A page is the drawing surface.
You can add text, paragraphs, headings, lines, rectangles, tables, and images.
Use margin helpers
The example uses:
page.x_left()
page.y_top()These helpers place content inside the page margins.
Common page helpers are:
page.x_left()
page.x_right()
page.y_top()
page.y_bottom()
page.content_width()
page.content_height()Use them instead of hardcoding positions when possible.
Draw text
Use:
page.text(
page.x_left(),
page.y_top(),
"Hello from rix.pdf");The first argument is the X position.
The second argument is the Y position.
The third argument is the text.
Draw another line
To draw lower on the page, subtract from the Y position:
page.text(
page.x_left(),
page.y_top() - 30.0F,
"This PDF was generated through the unified Rix facade.");PDF coordinates use points.
One inch is 72 points.
Save the PDF
Use:
auto saved = rix.pdf.save(doc, "rix_pdf_basic.pdf");save returns a status.
Always check it:
if (saved.failed())
{
rix.debug.eprint(
"pdf error:",
rix.pdf.error.to_string(saved.error()),
saved.error().message());
return 1;
}Print success
After a successful save:
rix.debug.print("created:", "rix_pdf_basic.pdf");This is useful for examples and small tools.
For real Vix application logging, prefer the Vix logging system.
Complete flow
The basic PDF flow is:
create document
add page
draw content
save file
check errorsIn code:
auto doc = rix.pdf.document();
auto &page = doc.add_page();
page.text(
page.x_left(),
page.y_top(),
"Hello from rix.pdf");
auto saved = rix.pdf.save(doc, "basic.pdf");Add a title
You can add document metadata:
auto doc = rix.pdf.document();
doc.set_title("Basic PDF")
.set_author("Rix");Then add visible content:
auto &page = doc.add_page();
page.text(
page.x_left(),
page.y_top(),
"Basic PDF");Metadata is not visible page content.
If you want a title visible on the page, draw it as text or heading.
Use a heading
auto y = page.heading(
page.x_left(),
page.y_top(),
"Basic PDF",
1);heading returns the next Y position after the heading.
You can continue below it:
y -= 10.0F;
page.text(
page.x_left(),
y,
"Generated with rix.pdf");Basic PDF with heading
#include <rix.hpp>
int main()
{
auto doc = rix.pdf.document();
doc.set_title("Basic PDF")
.set_author("Rix");
auto &page = doc.add_page();
auto y = page.heading(
page.x_left(),
page.y_top(),
"Basic PDF",
1);
y -= 10.0F;
page.text(
page.x_left(),
y,
"Generated through the public Rix facade.");
auto saved = rix.pdf.save(doc, "basic-heading.pdf");
if (saved.failed())
{
rix.debug.eprint(
"pdf error:",
rix.pdf.error.to_string(saved.error()),
saved.error().message());
return 1;
}
rix.debug.print("created:", "basic-heading.pdf");
return 0;
}Run:
vix run basic.cppWrite bytes instead of saving
If you want PDF bytes in memory, use:
auto bytes = rix.pdf.write(doc);Example:
auto bytes = rix.pdf.write(doc);
if (bytes.failed())
{
rix.debug.eprint(
"pdf error:",
rix.pdf.error.to_string(bytes.error()),
bytes.error().message());
return 1;
}
rix.debug.print("pdf bytes:", bytes.value().size());Use write for HTTP responses, storage adapters, or custom output handling.
Use save for writing directly to disk.
Use make_text for the shortest text PDF
For a very simple text PDF:
auto saved = rix.pdf.make_text(
"hello.pdf",
"Hello from rix.pdf",
"Rix PDF");Complete example:
#include <rix.hpp>
int main()
{
auto saved = rix.pdf.make_text(
"hello.pdf",
"Hello from rix.pdf",
"Rix PDF");
if (saved.failed())
{
rix.debug.eprint(
"pdf error:",
rix.pdf.error.to_string(saved.error()),
saved.error().message());
return 1;
}
rix.debug.print("created:", "hello.pdf");
return 0;
}Use make_text when you only need a simple text document.
Use document() when you need more control.
Save to another folder
Create the output folder first:
mkdir -p outputThen save:
auto saved = rix.pdf.save(doc, "output/basic.pdf");If the folder does not exist, saving can fail.
Use in a Vix project
Create a project:
vix new rix-pdf-basic --app
cd rix-pdf-basicAdd Rix:
vix add rix/rix
vix installMake sure vix.app contains:
deps = [
"rix/rix",
]A minimal vix.app can look like this:
name = "rix-pdf-basic"
type = "executable"
standard = "c++20"
output_dir = "bin"
sources = [
"src/main.cpp",
]
include_dirs = [
"include",
"src",
]
deps = [
"rix/rix",
]
packages = [
"vix",
]
links = [
"vix::vix",
]Put the example code in:
src/main.cppBuild and run:
vix build
vix runSingle-file usage
For examples, tests, and quick experiments:
vix run basic.cppIf needed:
vix install -g rix/rix
vix run basic.cppFor project usage, prefer:
vix add rix/rix
vix installand keep the dependency in vix.app:
deps = [
"rix/rix",
]Use only PDF with the facade
If you want the rix.* facade style but only want PDF mounted, define the feature macro before including rix.hpp:
#define RIX_ENABLE_PDF
#include <rix.hpp>
int main()
{
auto doc = rix.pdf.document();
auto &page = doc.add_page();
page.text(
page.x_left(),
page.y_top(),
"Hello from rix.pdf");
auto saved = rix.pdf.save(doc, "basic.pdf");
return saved.ok() ? 0 : 1;
}When at least one RIX_ENABLE_* macro is defined, only selected modules are mounted.
If you also want debug output:
#define RIX_ENABLE_PDF
#define RIX_ENABLE_DEBUG
#include <rix.hpp>
int main()
{
auto doc = rix.pdf.document();
auto &page = doc.add_page();
page.text(
page.x_left(),
page.y_top(),
"Hello from rix.pdf");
auto saved = rix.pdf.save(doc, "basic.pdf");
if (saved.failed())
{
rix.debug.eprint(
"pdf error:",
rix.pdf.error.to_string(saved.error()),
saved.error().message());
return 1;
}
rix.debug.print("created:", "basic.pdf");
return 0;
}Use the independent package
For independent usage, install:
vix add rix/pdf
vix installIn vix.app:
deps = [
"rix/pdf",
]Then include:
#include <rix/pdf.hpp>Example:
#include <rix/pdf.hpp>
int main()
{
auto pdf = rixlib::pdf::module();
auto doc = pdf.document();
auto &page = doc.add_page();
page.text(
page.x_left(),
page.y_top(),
"Hello from rix/pdf");
auto saved = pdf.save(doc, "basic.pdf");
return saved.ok() ? 0 : 1;
}The examples in this documentation prefer the public facade:
#include <rix.hpp>and:
rix.pdfCommon mistakes
Forgetting to install Rix
If rix.hpp is not found, install Rix first.
For a project:
vix add rix/rix
vix installFor single-file usage:
vix install -g rix/rixPutting Rix in packages
Wrong:
packages = [
"rix/rix",
]Correct:
deps = [
"rix/rix",
]deps is for Vix Registry packages.
packages is for CMake package discovery.
Forgetting to add a page
Wrong:
auto doc = rix.pdf.document();
doc.set_title("Basic PDF");
rix.pdf.save(doc, "basic.pdf");This can still produce a blank document, but most examples should add visible content:
auto &page = doc.add_page();Expecting metadata to be visible
This sets metadata:
doc.set_title("Basic PDF");This draws visible content:
page.heading(
page.x_left(),
page.y_top(),
"Basic PDF",
1);Use both when you want a document title and a visible title.
Not checking save errors
Wrong:
rix.pdf.save(doc, "basic.pdf");Correct:
auto saved = rix.pdf.save(doc, "basic.pdf");
if (saved.failed())
{
rix.debug.eprint(
"pdf error:",
rix.pdf.error.to_string(saved.error()),
saved.error().message());
return 1;
}Saving to a missing folder
This can fail:
rix.pdf.save(doc, "output/basic.pdf");Create the folder first:
mkdir -p outputWhat you should remember
Create a document:
auto doc = rix.pdf.document();Add a page:
auto &page = doc.add_page();Draw text:
page.text(
page.x_left(),
page.y_top(),
"Hello from rix.pdf");Save:
auto saved = rix.pdf.save(doc, "basic.pdf");Check errors:
if (saved.failed())
{
rix.debug.eprint(
"pdf error:",
rix.pdf.error.to_string(saved.error()),
saved.error().message());
}For project usage:
vix add rix/rix
vix installand keep:
deps = [
"rix/rix",
]Next step
Continue with PDF text.
Next: Text