English | 简体中文
- Chapter 1 Introduction
- Chapter 2 Quick Start
- Chapter 3 Text Styling
- Chapter 4 Tables
- Chapter 5 Images and SVG
- Chapter 6 Page Layout
- Chapter 7 Advanced Features
- Chapter 8 API Reference
- Chapter 9 FAQ
- Project File Structure
webpdf is a lightweight HTML‑to‑PDF library written in C++. It renders HTML content into high‑quality PDF documents without relying on a browser engine. It parses HTML and CSS directly and generates PDF commands, so it starts fast and uses little memory.
This library is especially suitable for:
- Server‑side batch generation of PDF reports and documents
- PDF generation in embedded systems
- Applications that need precise control over PDF output
- Environments where startup speed and memory footprint matter
| Feature | Description |
|---|---|
| HTML parsing | Supports common HTML tags and CSS styles |
| Chinese support | Full TrueType font support for Chinese characters |
| SVG rendering | Supports vector graphics and gradient fills |
| Automatic pagination | Smart page breaking; table headers repeat across pages |
| Headers & footers | Custom headers/footers with page number placeholders |
| TOC generation | Auto‑generates clickable table of contents with page numbers |
| Full‑page images | class="pagefull" renders an image to fill the entire page |
Note: webpdf is not a browser engine. It is a dedicated HTML/CSS renderer that supports only commonly used tags and styles. For complex web applications, consider browser‑based solutions.
The project uses Makefile. Make sure g++ and make are installed. In the project root:
cd webpdf
makeAfter a successful build, the executable test_html is generated.
Run the test program. By default it reads content.html and outputs output.pdf:
./test_htmlYou can also specify input and output files:
./test_html input.html output.pdfHere is a minimal HTML file with a title and a paragraph:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello</title>
<style>
body {
font-family: msyh;
font-size: 24px;
}
</style>
</head>
<body>
<h1>Hello, webpdf!</h1>
<p>This is my first PDF document.</p>
</body>
</html>Tip: Make sure your HTML file is UTF‑8 encoded, otherwise Chinese characters may appear garbled.
webpdf supports setting fonts and sizes via CSS. Before using a font, you must register the font file with the C++ API method AddFont().
Example:
body {
font-family: "Microsoft YaHei";
font-size: 24px;
}Use <b> or <strong> for bold text, and <i> or <em> for italic text. You can combine them for bold italics.
Use <u> for underlined text. Use <font color="..."> to set text color, e.g. red, green, blue.
- Left:
text-align: left - Center:
text-align: center - Right:
text-align: right
Line‑height controls the vertical spacing between lines. A good value is 1.2 to 1.5 times the font size for comfortable reading.
Use <table> to create a table. Add border="1" to show borders.
<table border="1" style="width: 100%;">
<thead>
<tr>
<th>Product</th>
<th>Price</th>
<th>Stock</th>
</tr>
</thead>
<tbody>
<tr>
<td>Web Framework</td>
<td>¥299</td>
<td>128</td>
</tr>
<tr>
<td>Mobile Component Library</td>
<td>¥499</td>
<td>56</td>
</tr>
<tr>
<td>Enterprise Management System</td>
<td>¥1999</td>
<td>12</td>
</tr>
</tbody>
</table>Cell content can be aligned horizontally and vertically:
| Alignment | CSS value |
|---|---|
| Horizontal left | text-align: left |
| Horizontal center | text-align: center |
| Horizontal right | text-align: right |
| Vertical top | vertical-align: top |
| Vertical middle | vertical-align: middle |
| Vertical bottom | vertical-align: bottom |
Use colspan to merge columns, and rowspan to merge rows.
<table border="1" style="width: 100%;">
<thead>
<tr>
<th colspan="2">Product Info</th>
<th>Price</th>
</tr>
</thead>
<tbody>
<tr>
<td rowspan="3">Software</td>
<td>Basic</td>
<td>¥99</td>
</tr>
<tr>
<td>Pro</td>
<td>¥299</td>
</tr>
<tr>
<td>Enterprise</td>
<td>¥999</td>
</tr>
</tbody>
</table>When a table is long and spans multiple pages, add style="position: fixed" to the <table> tag. This makes the header repeat automatically on every page.
<table border="1" style="width: 100%; position: fixed;">
<thead>
<tr>
<th>Feature</th>
<th>Basic</th>
<th>Pro</th>
</tr>
</thead>
<tfoot>
<tr>
<td style="text-align: right;">Total features</td>
<td>12</td>
<td>28</td>
</tr>
</tfoot>
<tbody>
<tr>
<td>User management</td>
<td>✓</td>
<td>✓</td>
</tr>
<!-- more rows -->
</tbody>
</table>webpdf supports PNG, JPG and other common raster formats. Use <img> to insert an image:
<img src="images/cover.jpg">SVG (Scalable Vector Graphics) scale without losing quality and are great for charts and icons. You can reference an SVG file via <img> or embed the SVG code directly.
<img src="images/diagram.svg">Embedding SVG code directly gives you more control:
<svg width="300" height="200" xmlns="http://www.w3.org/2000/svg">
<rect x="10" y="10" width="280" height="180" fill="#f8f9fa" stroke="#dee2e6" stroke-width="2" rx="8"/>
<rect x="30" y="50" width="60" height="120" fill="#4285f4"/>
<rect x="110" y="80" width="60" height="90" fill="#ea4335"/>
<rect x="190" y="30" width="60" height="140" fill="#fbbc05"/>
<text x="60" y="185" font-size="12" text-anchor="middle">Jan</text>
<text x="140" y="185" font-size="12" text-anchor="middle">Feb</text>
<text x="220" y="185" font-size="12" text-anchor="middle">Mar</text>
<text x="150" y="35" font-size="14" text-anchor="middle">Quarterly Sales</text>
</svg>webpdf supports both linear and radial gradients.
Linear gradients change color along a straight line:
<svg width="400" height="50" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="rainbow" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#FF0000"/>
<stop offset="17%" stop-color="#FF7F00"/>
<stop offset="33%" stop-color="#FFFF00"/>
<stop offset="50%" stop-color="#00FF00"/>
<stop offset="67%" stop-color="#0000FF"/>
<stop offset="83%" stop-color="#4B0082"/>
<stop offset="100%" stop-color="#9400D3"/>
</linearGradient>
</defs>
<rect x="0" y="0" width="400" height="50" fill="url(#rainbow)"/>
</svg>Radial gradients radiate from a center point, good for spheres and glow effects:
<svg width="300" height="120" xmlns="http://www.w3.org/2000/svg">
<defs>
<radialGradient id="ball" cx="35%" cy="35%" r="60%">
<stop offset="0%" stop-color="#ffffff"/>
<stop offset="100%" stop-color="#2c5aa0"/>
</radialGradient>
</defs>
<circle cx="60" cy="60" r="50" fill="url(#ball)"/>
<ellipse cx="180" cy="60" rx="80" ry="50" fill="url(#ball)"/>
</svg>SVG supports many basic shapes and paths:
| Element | Description |
|---|---|
<line> |
Straight line |
<polyline> |
Polyline (connected segments) |
<polygon> |
Polygon |
<path> |
Arbitrary path |
<ellipse> |
Ellipse |
To force a page break at a specific position, use page-break-before: always:
<div style="page-break-before: always;"></div>This empty div produces no visible content but triggers a page break.
Use class="pagefull" to make an image fill the entire page – no headers, footers, or margins. The image is scaled proportionally and centered.
<p class="pagefull"><img src="images/fullpage.png"></p>Tip: You can put
pagefullon any container. The first<img>inside it will be used for the full‑page render; the container and other children are hidden.
Use <div> to create block containers with background, border, border‑radius, etc.:
<div style="background-color: #e3f2fd; padding: 20px; border-radius: 10px; border: 1px solid #2196f3;">
<strong style="color: #1565c0;">Info Box</strong>
<p>This is a blue‑themed notice box.</p>
</div>Use <a> to create clickable links in the PDF:
<a href="https://www.example.com">Example Website</a>Long links wrap correctly across lines.
Use <hr> to insert horizontal separators:
<hr>
<hr style="border-color: #f44336; border-width: 3px;">
<hr style="border-color: #4caf50; border-style: dashed; border-width: 2px;">
<hr style="border-color: #2196f3; border-style: dotted; border-width: 2px; width: 50%; margin: 0 auto;">Use class="pageheader" and class="pagefooter" to define custom headers and footers on every page.
<div class="pageheader" style="height: 30px;">
<div style="text-align: right; margin-right: 100px;">
<img src="images/logo.svg" style="padding-right: 20px;">
<span>Page {pagenum} / {pagetotal}</span>
</div>
</div>
<div class="pagefooter" style="height: 20px;">
<div style="text-align:center;">— Page {pagenum} / {pagetotal} —</div>
</div>Two special placeholders are available:
| Placeholder | Description |
|---|---|
{pagenum} |
Current page number |
{pagetotal} |
Total number of pages |
Note: By default, cover pages and TOC pages do not show headers/footers. Full‑page images (
pagefull) also suppress them.
webpdf can auto‑generate a table of contents. Add class="catalogue1", catalogue2, or catalogue3 to headings to include them in the TOC.
| Class | TOC Level | Corresponding Headings |
|---|---|---|
catalogue1 |
Level 1 | h1 ~ h3 |
catalogue2 |
Level 2 | h4 ~ h5 |
catalogue3 |
Level 3 | h5 ~ h6 |
The generated TOC includes page numbers and clickable links to the sections.
Use class="pagecover" to create a cover page – no headers/footers, content starts at the top of the page.
Use class="pagecatalogue" for a TOC background, together with class="cataloguecontent" to auto‑insert the TOC.
<!-- Cover -->
<div class="pagecover" style="background-image:url(images/cover.jpg);">
<h1 style="padding-top: 260px; text-align: center;">Document Title</h1>
</div>
<!-- TOC background -->
<div class="pagecatalogue" style="background-image:url(images/mulu.jpeg);">
<h3 style="padding-top: 200px; text-align: center;">Table of Contents</h3>
</div>
<!-- Auto‑generated TOC content -->
<div class="cataloguecontent" title="Table of Contents"></div>FPDF is the core PDF document class.
| Method | Description |
|---|---|
FPDF() |
Constructor, creates a new PDF document |
AddPage() |
Adds a new page |
AddFont(family, style, file, dir) |
Registers a font file |
SetFont(family, style, size) |
Sets the current font |
WriteHTML(html, line_height) |
Renders HTML content to the PDF |
Output(dest, name) |
Outputs the PDF file |
SetShowHeader(show) |
Enables/disables header display |
SetShowFooter(show) |
Enables/disables footer display |
SetShowHeaderFooter(show) |
Enables/disables both header and footer |
PageNo() |
Returns the current page number |
SetPageNumberOffset(offset) |
Sets the page number offset |
SetLeftMargin(margin) |
Sets the left margin |
SetRightMargin(margin) |
Sets the right margin |
SetTopMargin(margin) |
Sets the top margin |
SetAutoPageBreak(auto, margin) |
Configures automatic page breaking |
GetPageWidth() |
Returns page width |
GetPageHeight() |
Returns page height |
GetX() / GetY() |
Returns current drawing position |
SetXY(x, y) |
Sets current drawing position |
Image(file, x, y, w, h) |
Inserts an image |
Rect(x, y, w, h, style) |
Draws a rectangle |
SetFillColor(r, g, b) |
Sets fill color |
SetDrawColor(r, g, b) |
Sets stroke color |
SetTextColor(r, g, b) |
Sets text color |
SetLineWidth(width) |
Sets line width |
AddAxialShading(...) |
Adds an axial (linear) gradient |
ShadeFill(x, y, w, h, id) |
Fills a rectangle with a gradient |
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include "fpdf.h"
std::string read_file(const std::string& path) {
std::ifstream f(path);
if (!f.is_open())
throw std::runtime_error("Cannot open file: " + path);
std::stringstream ss;
ss << f.rdbuf();
return ss.str();
}
int main(int argc, char* argv[]) {
try {
std::string html_file = "content.html";
std::string pdf_file = "output.pdf";
if (argc > 1) html_file = argv[1];
if (argc > 2) pdf_file = argv[2];
std::string html = read_file(html_file);
webpdf::FPDF pdf;
pdf.AddPage();
pdf.AddFont("msyh", "", "msyh.ttf", "font/");
pdf.SetFont("msyh", "", 14);
pdf.WriteHTML(html);
pdf.Output("F", pdf_file);
std::cout << "PDF generated: " << pdf_file << std::endl;
return 0;
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
return 1;
}
}| Problem | Solution |
|---|---|
| Chinese characters show as boxes or garbled | Make sure you registered the font with AddFont() and the CSS font-family matches exactly. |
| Bold/italic not working | You need to register the corresponding font file; webpdf does not fake bold/italic. |
| Wrong line breaks | Check for special characters or extra spaces; CJK characters are broken by character width. |
| Problem | Solution |
|---|---|
| Image not showing | Verify the path is correct relative to the working directory. |
| SVG renders black | Check SVG syntax; gradients must be defined inside <defs>. |
| SVG gradient wrong | Ensure the gradient ID is correct and referenced with url(#id). |
| Problem | Solution |
|---|---|
| Blank page before page break | Use an empty div with page-break-before: always and no content inside. |
| Table header not repeating across pages | Add style="position: fixed" to the <table> tag. |
pagefull image still shows header/footer |
Make sure class="pagefull" is on a container that has an <img> child. |
| Problem | Solution |
|---|---|
| TOC page numbers are off | TOC page numbers are estimated; complex layouts may cause small deviations. |
| Some CSS styles ignored | webpdf supports only common CSS properties; check the supported list in this tutorial. |
| Generated PDF is too large | Use compressed images and avoid large bitmaps where possible. |
webpdf/
├── .github/workflows/ # CI/CD workflows
│ ├── ci.yml
│ └── release.yml
├── cmake/ # CMake configuration templates
│ ├── webpdf.pc.in
│ └── webpdfConfig.cmake.in
├── example/ # Example programs and tutorials
│ ├── font/ # Font files for examples
│ │ ├── AlibabaPuHuiTi-Light.otf/ttf
│ │ ├── AlibabaSans-Regular.otf/ttf
│ │ └── *.json (font configs)
│ ├── images/ # Sample images
│ │ ├── cover.jpg
│ │ ├── mulu.jpeg
│ │ └── *.png/*.svg
│ ├── hello.cpp # Minimal example
│ ├── render_html.cpp # HTML rendering example
│ ├── webpdf_tutorial.html # Chinese tutorial
│ ├── webpdf_tutorial_en.html # English tutorial
│ └── TUTORIAL.md # Markdown tutorial
├── include/webpdf/ # Public header files
│ ├── webpdf.h # Main API header
│ ├── parsecss.h # CSS parser
│ ├── parsehtml.h # HTML parser
│ ├── parsesvg.h # SVG parser
│ ├── ttfparser.h # TrueType font parser
│ ├── gzip.h # GZIP compression
│ └── request.h # HTTP request utilities
├── ports/webpdf/ # vcpkg port configuration
│ ├── portfile.cmake
│ └── vcpkg.json
├── src/ # Source files
│ ├── webpdf.cpp
│ ├── parsecss.cpp
│ ├── parsehtml.cpp
│ ├── parsesvg.cpp
│ ├── ttfparser.cpp
│ ├── gzip.cpp
│ └── request.cpp
├── CMakeLists.txt # CMake build configuration
├── LICENSE # MIT License
├── Makefile # Make build system
├── README.md # English README
├── README_CN.md # Chinese README
├── vcpkg.json # vcpkg manifest
├── webpdf.pc # pkg-config file
├── webpdf.rb # Homebrew formula
└── brew.sh # Brew installation script
Final note: webpdf is an ongoing project hosted at https://github.com/hggq/webpdf. If you run into issues or need new features, feedback and contributions are welcome. We hope this tutorial helps you get started quickly and produce beautiful PDF documents!