{"id":32136872,"url":"https://github.com/plutoprint/plutobook","last_synced_at":"2026-01-17T07:27:02.243Z","repository":{"id":237534713,"uuid":"794825841","full_name":"plutoprint/plutobook","owner":"plutoprint","description":"Paged HTML Rendering Library","archived":false,"fork":false,"pushed_at":"2026-01-11T08:04:51.000Z","size":1793,"stargazers_count":292,"open_issues_count":21,"forks_count":15,"subscribers_count":8,"default_branch":"main","last_synced_at":"2026-01-11T14:19:54.878Z","etag":null,"topics":["c","cairo","cpp","css","html","html2pdf","html2png","pdf","png","svg"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/plutoprint.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"plutoprint","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"lfx_crowdfunding":null,"polar":null,"buy_me_a_coffee":null,"thanks_dev":null,"custom":null}},"created_at":"2024-05-02T03:09:03.000Z","updated_at":"2026-01-11T08:04:54.000Z","dependencies_parsed_at":"2024-05-17T11:28:50.907Z","dependency_job_id":null,"html_url":"https://github.com/plutoprint/plutobook","commit_stats":null,"previous_names":["plutoprint/plutobook"],"tags_count":16,"template":false,"template_full_name":null,"purl":"pkg:github/plutoprint/plutobook","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plutoprint%2Fplutobook","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plutoprint%2Fplutobook/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plutoprint%2Fplutobook/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plutoprint%2Fplutobook/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/plutoprint","download_url":"https://codeload.github.com/plutoprint/plutobook/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plutoprint%2Fplutobook/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28504103,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T06:57:29.758Z","status":"ssl_error","status_checked_at":"2026-01-17T06:56:03.931Z","response_time":85,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c","cairo","cpp","css","html","html2pdf","html2png","pdf","png","svg"],"created_at":"2025-10-21T04:46:18.677Z","updated_at":"2026-01-17T07:27:02.233Z","avatar_url":"https://github.com/plutoprint.png","language":"C++","funding_links":["https://github.com/sponsors/plutoprint"],"categories":[],"sub_categories":[],"readme":"[![Actions](https://img.shields.io/github/actions/workflow/status/plutoprint/plutobook/main.yml)](https://github.com/plutoprint/plutobook/actions)\n[![Releases](https://img.shields.io/github/v/release/plutoprint/plutobook)](https://github.com/plutoprint/plutobook/releases)\n[![License](https://img.shields.io/github/license/plutoprint/plutobook)](https://github.com/plutoprint/plutobook/blob/main/LICENSE)\n[![Sponsors](https://img.shields.io/github/sponsors/plutoprint)](https://github.com/sponsors/plutoprint)\n[![Packages](https://repology.org/badge/tiny-repos/plutobook.svg)](https://repology.org/project/plutobook/versions)\n\n\u003e Prefer Python? Try [PlutoPrint](https://github.com/plutoprint/plutoprint) — a Python library built on PlutoBook for easy paged HTML rendering.\n\n# PlutoBook\n\nPlutoBook is a robust HTML rendering library tailored for paged media. It takes HTML or XML as input, applies CSS stylesheets, and lays out elements across one or more pages, which can then be rendered as Bitmap images or PDF documents.\n\n\u003e [!NOTE]\n\u003e PlutoBook implements its own rendering engine and does **not** depend on rendering engines like Chromium, WebKit, or Gecko.  \n\u003e The engine is designed to be robust, lightweight, and memory-efficient, leveraging modern C++ features such as [`std::pmr::monotonic_buffer_resource`](https://en.cppreference.com/w/cpp/memory/monotonic_buffer_resource) to minimize memory fragmentation and optimize allocation performance.\n\n**Testimonial**  \n\u003e *\"PlutoBook is incredibly fast and lightweight. In my invoicing app (built in 2010), I replaced headless Chrome with PlutoBook and saw at least a **10× speed improvement** and **10× lower memory usage**, while achieving similar output quality.\"*  \n\u003e — **Nikola Radovanović**\n\n---\n\n## Basic Usage\n\nThis example creates a PDF from inline HTML using **plutobook**. It sets up a book with A4 page size and **narrow margins** (36 points or 0.5 inches on all sides), then writes the output to `hello.pdf`.\n\n```cpp\n#include \u003cplutobook.hpp\u003e\n\nstatic const char kHTMLContent[] = R\"HTML(\n\u003c!DOCTYPE html\u003e\n\u003chtml lang=\"la\"\u003e\n\u003chead\u003e\n  \u003cmeta charset=\"UTF-8\"\u003e\n  \u003ctitle\u003eMagnum Scopulum Corallinum\u003c/title\u003e\n  \u003cstyle\u003e\n    body { font-family: \"Segoe UI\", sans-serif; line-height: 1.6; margin: 40px auto; max-width: 800px; color: #222; }\n    h1 { font-size: 2.5em; margin-bottom: 20px; }\n    img { width: 100%; border-radius: 6px; margin-bottom: 20px; }\n    p { font-size: 1.05em; text-align: justify; }\n  \u003c/style\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n  \u003ch1\u003eMagnum Scopulum Corallinum\u003c/h1\u003e\n  \u003cimg src=\"https://picsum.photos/id/128/800/400\" alt=\"Magnum Scopulum Corallinum\"\u003e\n  \u003cp\u003eMagnum Scopulum Corallinum est maximum systema scopulorum corallinorum in mundo, quod per plus quam 2,300 chiliometra oram septentrionalem-orientalem Australiae extenditur. Ex milibus scopulorum individualium et centenis insularum constat, e spatio videri potest et inter mirabilia naturalia mundi numeratur.\u003c/p\u003e\n  \u003cp\u003eDomus est incredibili diversitati vitae marinae, cum plus quam 1,500 speciebus piscium, 400 generibus corallii, et innumerabilibus aliis organismis. Partem vitalem agit in salute oecosystematis marini conservanda et sustentat victum communitatum litoralium per otium et piscationem.\u003c/p\u003e\n  \u003cp\u003eQuamquam pulchritudinem ac significationem oecologicam praebet, Magnum Scopulum Corallinum minas continenter patitur ex mutatione climatis, pollutione, et nimia piscatione. Eventus albi corallii ex temperaturis marinis crescentibus magnam partem scopuli nuper laeserunt. Conatus conservatorii toto orbe suscipiuntur ad hunc magnificum oecosystema subaquaneum tuendum et restaurandum.\u003c/p\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n)HTML\";\n\nint main()\n{\n    plutobook::Book book(plutobook::PageSize::A4, plutobook::PageMargins::Narrow);\n    book.loadHtml(kHTMLContent);\n    book.writeToPdf(\"hello.pdf\");\n    return 0;\n}\n```\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eEquivalent in C\u003c/b\u003e\u003c/summary\u003e\n\n```c\n#include \u003cplutobook.h\u003e\n\nstatic const char kHTMLContent[] =\n    \"\u003c!DOCTYPE html\u003e\\n\"\n    \"\u003chtml lang=\\\"la\\\"\u003e\\n\"\n    \"\u003chead\u003e\\n\"\n    \"  \u003cmeta charset=\\\"UTF-8\\\"\u003e\\n\"\n    \"  \u003ctitle\u003eMagnum Scopulum Corallinum\u003c/title\u003e\\n\"\n    \"  \u003cstyle\u003e\\n\"\n    \"    body { font-family: \\\"Segoe UI\\\", sans-serif; line-height: 1.6; margin: 40px auto; max-width: 800px; color: #222; }\\n\"\n    \"    h1 { font-size: 2.5em; margin-bottom: 20px; }\\n\"\n    \"    img { width: 100%; border-radius: 6px; margin-bottom: 20px; }\\n\"\n    \"    p { font-size: 1.05em; text-align: justify; }\\n\"\n    \"  \u003c/style\u003e\\n\"\n    \"\u003c/head\u003e\\n\"\n    \"\u003cbody\u003e\\n\"\n    \"  \u003ch1\u003eMagnum Scopulum Corallinum\u003c/h1\u003e\\n\"\n    \"  \u003cimg src=\\\"https://picsum.photos/id/128/800/400\\\" alt=\\\"Magnum Scopulum Corallinum\\\"\u003e\\n\"\n    \"  \u003cp\u003eMagnum Scopulum Corallinum est maximum systema scopulorum corallinorum in mundo, quod per plus quam 2,300 chiliometra oram septentrionalem-orientalem Australiae extenditur. Ex milibus scopulorum individualium et centenis insularum constat, e spatio videri potest et inter mirabilia naturalia mundi numeratur.\u003c/p\u003e\\n\"\n    \"  \u003cp\u003eDomus est incredibili diversitati vitae marinae, cum plus quam 1,500 speciebus piscium, 400 generibus corallii, et innumerabilibus aliis organismis. Partem vitalem agit in salute oecosystematis marini conservanda et sustentat victum communitatum litoralium per otium et piscationem.\u003c/p\u003e\\n\"\n    \"  \u003cp\u003eQuamquam pulchritudinem ac significationem oecologicam praebet, Magnum Scopulum Corallinum minas continenter patitur ex mutatione climatis, pollutione, et nimia piscatione. Eventus albi corallii ex temperaturis marinis crescentibus magnam partem scopuli nuper laeserunt. Conatus conservatorii toto orbe suscipiuntur ad hunc magnificum oecosystema subaquaneum tuendum et restaurandum.\u003c/p\u003e\\n\"\n    \"\u003c/body\u003e\\n\"\n    \"\u003c/html\u003e\\n\";\n\nint main()\n{\n    plutobook_t* book = plutobook_create(\n        PLUTOBOOK_PAGE_SIZE_A4,\n        PLUTOBOOK_PAGE_MARGINS_NARROW,\n        PLUTOBOOK_MEDIA_TYPE_PRINT\n    );\n\n    plutobook_load_html(book, kHTMLContent, -1, \"\", \"\", \"\");\n    plutobook_write_to_pdf(book, \"hello.pdf\");\n    plutobook_destroy(book);\n    return 0;\n}\n```\n\n\u003c/details\u003e\n\nExample output:\n\n\u003cp align=\"center\"\u003e\u003cimg src=\"https://github.com/user-attachments/assets/dc069903-2dad-47a2-ac5a-9854a617f7ae\" alt=\"hello.pdf\" width=\"650\"\u003e\u003c/p\u003e\n\n---\n\n## Page Rendering\n\nPlutoBook supports precise page-level rendering, allowing individual pages to be drawn onto different canvas types, including bitmap canvases and PDF outputs. For custom rendering workflows, it integrates directly with Cairo, enabling advanced use cases like drawing onto custom surfaces or embedding within existing rendering pipelines. This page-specific approach improves efficiency by avoiding full document processing and is well-suited for previews, selective exports, and on-demand rendering.\n\nThis example loads [**Alice’s Adventures in Wonderland**](https://www.gutenberg.org/ebooks/11) from Project Gutenberg, renders the first three pages as PNG images, and also exports them as a PDF.\n\n```cpp\n#include \u003cplutobook.hpp\u003e\n#include \u003ccmath\u003e\n\nint main()\n{\n    // Create a plutobook instance with A4 page size, narrow margins, and print media type\n    plutobook::Book book(plutobook::PageSize::A4, plutobook::PageMargins::Narrow, plutobook::MediaType::Print);\n\n    // Load the HTML content from file\n    book.loadUrl(\"Alice’s Adventures in Wonderland.html\");\n\n    // Get page size in points and convert to pixel dimensions\n    const plutobook::PageSize\u0026 pageSize = book.pageSize();\n    int pageWidth = std::ceil(pageSize.width() / plutobook::units::px);\n    int pageHeight = std::ceil(pageSize.height() / plutobook::units::px);\n\n    // Create a canvas to render pages as images\n    plutobook::ImageCanvas canvas(pageWidth, pageHeight);\n\n    // Render the first 3 pages to PNG files\n    for(int pageIndex = 0; pageIndex \u003c 3; ++pageIndex) {\n        auto filename = \"page-\" + std::to_string(pageIndex + 1) + \".png\";\n\n        // Clear the canvas to white before rendering each page\n        canvas.clearSurface(1, 1, 1, 1);\n\n        // Render the page onto the canvas\n        book.renderPage(canvas, pageIndex);\n\n        // Save the canvas to a PNG file\n        canvas.writeToPng(filename);\n    }\n\n    // Export pages 1 to 3 (inclusive) to PDF with step=1 (every page in order)\n    book.writeToPdf(\"Alice’s Adventures in Wonderland.pdf\", 1, 3, 1);\n    return 0;\n}\n```\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eEquivalent in C\u003c/b\u003e\u003c/summary\u003e\n\n```c\n#include \u003cplutobook.h\u003e\n#include \u003cstdio.h\u003e\n#include \u003cmath.h\u003e\n\nint main()\n{\n    // Create a plutobook instance with A4 page size, narrow margins, and print media type\n    plutobook_t* book = plutobook_create(\n        PLUTOBOOK_PAGE_SIZE_A4,\n        PLUTOBOOK_PAGE_MARGINS_NARROW,\n        PLUTOBOOK_MEDIA_TYPE_PRINT\n    );\n\n    // Load the HTML content from file\n    plutobook_load_url(book, \"Alice’s Adventures in Wonderland.html\", \"\", \"\");\n\n    // Get page size in points and convert to pixel dimensions\n    plutobook_page_size_t page_size = plutobook_get_page_size(book);\n    int page_width = (int)ceilf(page_size.width / PLUTOBOOK_UNITS_PX);\n    int page_height = (int)ceilf(page_size.height / PLUTOBOOK_UNITS_PX);\n\n    // Create a canvas to render pages as images\n    plutobook_canvas_t* canvas = plutobook_image_canvas_create(\n        page_width,\n        page_height,\n        PLUTOBOOK_IMAGE_FORMAT_ARGB32\n    );\n\n    // Render the first 3 pages to PNG files\n    for(int page_index = 0; page_index \u003c 3; ++page_index) {\n        char filename[64];\n        sprintf(filename, \"page-%d.png\", page_index + 1);\n\n        // Clear the canvas to white before rendering each page\n        plutobook_canvas_clear_surface(canvas, 1, 1, 1, 1);\n\n        // Render the page onto the canvas\n        plutobook_render_page(book, canvas, page_index);\n\n        // Save the canvas to a PNG file\n        plutobook_image_canvas_write_to_png(canvas, filename);\n    }\n\n    // Export pages 1 to 3 (inclusive) to PDF with step=1 (every page in order)\n    plutobook_write_to_pdf_range(book, \"Alice’s Adventures in Wonderland.pdf\", 1, 3, 1);\n\n    // Clean up resources\n    plutobook_canvas_destroy(canvas);\n    plutobook_destroy(book);\n    return 0;\n}\n```\n\n\u003c/details\u003e\n\nExample output:\n\n| `page-1.png` | `page-2.png` | `page-3.png` |\n| --- | --- | --- |\n| ![page-1](https://github.com/user-attachments/assets/c9c26c07-e283-487e-a2e8-ab77c79bdbb5) | ![page-2](https://github.com/user-attachments/assets/43bdf6dc-21fc-427f-a9c6-e54510b88fbd) | ![page-3](https://github.com/user-attachments/assets/6bff4046-7877-4a89-9723-920bdb5799c0) |\n\n---\n\n## Document Rendering\n\nPlutoBook supports full-document rendering, drawing the entire content flow as a single continuous layout. This is ideal for generating scrollable previews, long-form visual exports, or cases where the overall structure needs to be viewed or processed at once. It also supports rendering specific rectangular regions of the document, which is useful for partial redraws or focused exports. Both full and partial rendering are available across all supported canvas types, including bitmap outputs, PDF surfaces, and Cairo contexts.\n\nThe example below demonstrates how to perform a full-document render of an HTML file into a bitmap image. The document's actual rendered dimensions are measured first, and then a canvas of that size is created to ensure the entire layout is captured without clipping. Finally, the rendered result is saved as a PNG image.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003eExplore Life Through Moments.html\u003c/code\u003e\u003c/summary\u003e\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml lang=\"en\"\u003e\n\u003chead\u003e\n  \u003cmeta charset=\"UTF-8\"\u003e\n  \u003ctitle\u003eExplore Life Through Moments\u003c/title\u003e\n  \u003cstyle\u003e\n    body {\n      display: flex;\n      background: #f7f7f7;\n      font-family: Arial, sans-serif;\n      margin: 0;\n    }\n\n    .section {\n      flex: 1;\n      display: flex;\n      flex-direction: column;\n      align-items: center;\n      justify-content: center;\n      padding: 32px;\n    }\n\n    .section h2 {\n      margin: 0 0 12px;\n      font-size: 2rem;\n      color: #333;\n    }\n\n    .section p {\n      margin: 0 0 24px;\n      font-size: 1.1rem;\n      color: #555;\n      text-align: center;\n      max-width: 400px;\n    }\n\n    .section img {\n      max-width: 100%;\n      max-height: 350px;\n      border-radius: 10px;\n      object-fit: cover;\n    }\n  \u003c/style\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n  \u003csection class=\"section\"\u003e\n    \u003ch2\u003eNature\u003c/h2\u003e\n    \u003cp\u003eRelax in the beauty of untouched landscapes and flourishing greenery. Nature inspires and calms the mind.\u003c/p\u003e\n    \u003cimg src=\"https://picsum.photos/id/190/500/350\" alt=\"Nature\"\u003e\n  \u003c/section\u003e\n  \u003csection class=\"section\"\u003e\n    \u003ch2\u003eCity Life\u003c/h2\u003e\n    \u003cp\u003eDiscover the energy and excitement of urban environments. Cities pulse with opportunity and culture.\u003c/p\u003e\n    \u003cimg src=\"https://picsum.photos/id/392/500/350\" alt=\"City\"\u003e\n  \u003c/section\u003e\n  \u003csection class=\"section\"\u003e\n    \u003ch2\u003eAdventure\u003c/h2\u003e\n    \u003cp\u003eSeek new horizons with every journey. Adventure is about embracing the unknown and living boldly.\u003c/p\u003e\n    \u003cimg src=\"https://picsum.photos/id/177/500/350\" alt=\"Adventure\"\u003e\n  \u003c/section\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\n\u003c/details\u003e\n\n```cpp\n#include \u003cplutobook.hpp\u003e\n#include \u003ccmath\u003e\n\nint main()\n{\n    // Define a custom page size in pixel units used as the viewport for layout\n    const plutobook::PageSize pageSize(1800 * plutobook::units::px, 600 * plutobook::units::px);\n\n    // Create a plutobook instance with the custom page size, no page margins, and screen media type\n    plutobook::Book book(pageSize, plutobook::PageMargins::None, plutobook::MediaType::Screen);\n\n    // Load the HTML content from file with a custom user style\n    book.loadUrl(\"Explore Life Through Moments.html\", /*userStyle=*/\"body { border: 1px solid gray }\");\n\n    // Compute the full document dimensions after layout\n    int width = std::ceil(book.documentWidth());\n    int height = std::ceil(book.documentHeight());\n\n    // Create a canvas large enough to render the entire document at once\n    plutobook::ImageCanvas canvas(width, height);\n\n    // Render the full document content to the canvas\n    book.renderDocument(canvas);\n\n    // Export the rendered canvas to a PNG file\n    canvas.writeToPng(\"Explore Life Through Moments.png\");\n    return 0;\n}\n```\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eEquivalent in C\u003c/b\u003e\u003c/summary\u003e\n\n```c\n#include \u003cplutobook.h\u003e\n#include \u003cmath.h\u003e\n\nint main()\n{\n    // Define a custom page size in pixel units used as the viewport for layout\n    const plutobook_page_size_t page_size = {1800 * PLUTOBOOK_UNITS_PX, 600 * PLUTOBOOK_UNITS_PX};\n\n    // Create a plutobook instance with the custom page size, no page margins, and screen media type\n    plutobook_t* book = plutobook_create(page_size, PLUTOBOOK_PAGE_MARGINS_NONE, PLUTOBOOK_MEDIA_TYPE_SCREEN);\n\n    // Load the HTML content from file with a custom user style\n    plutobook_load_url(book, \"Explore Life Through Moments.html\", /*user_style=*/\"body { border: 1px solid gray }\", \"\");\n\n    // Compute the full document dimensions after layout\n    int width = (int)ceilf(plutobook_get_document_width(book));\n    int height = (int)ceilf(plutobook_get_document_height(book));\n\n    // Create a canvas large enough to render the entire document at once\n    plutobook_canvas_t* canvas = plutobook_image_canvas_create(width, height, PLUTOBOOK_IMAGE_FORMAT_ARGB32);\n\n    // Render the full document content to the canvas\n    plutobook_render_document(book, canvas);\n\n    // Export the rendered canvas to a PNG file\n    plutobook_image_canvas_write_to_png(canvas, \"Explore Life Through Moments.png\");\n\n    // Clean up resources\n    plutobook_canvas_destroy(canvas);\n    plutobook_destroy(book);\n    return 0;\n}\n```\n\n\u003c/details\u003e\n\nExample output:\n\n\u003cimg width=\"1800\" height=\"550\" alt=\"Explore Life Through Moments.png\" src=\"https://github.com/user-attachments/assets/10c956c4-aa3b-4504-b9f2-b6e5f3cce25f\" /\u003e\n\n---\n\n## Features\n\n**PlutoBook** is a high-performance document renderer designed for static layout and print-ready output. It supports a broad set of modern web standards, including most of `CSS 3` and parts of `CSS 4`, with input from `HTML5`, `XHTML`, `SVG`, and common image formats like `JPG`, `PNG`, `WEBP`, `GIF`, `BMP`, and `TGA`. Output can be saved directly to `PDF`, image files, or any format supported by `Cairo` (e.g. `SVG`, `PostScript`). It includes robust support for international text layout via `ICU` and `HarfBuzz`, including Arabic, Hebrew, Hindi, and more. Emoji rendering (bitmap and vector) is fully supported. Font handling is powered by `Fontconfig` and `FreeType`, enabling access to all installed system fonts and major font formats. PlutoBook supports `file:` and `data:` URLs out of the box. Remote resources over `http`, `https`, and `ftp` are supported via `libcurl`, and you can plug in a custom fetcher for full control over resource loading.\n\nFor a full breakdown of supported features, see [`FEATURES.md`](FEATURES.md):\n\n* [Fonts](FEATURES.md#fonts)\n* [Color](FEATURES.md#color)\n* [Backgrounds and Borders](FEATURES.md#backgrounds-and-borders)\n* [Outlines](FEATURES.md#outlines)\n* [Box Model](FEATURES.md#box-model)\n* [Box Sizing](FEATURES.md#box-sizing)\n* [Display](FEATURES.md#display)\n* [Positioning](FEATURES.md#positioning)\n* [Floats](FEATURES.md#floats)\n* [Lists and Counters](FEATURES.md#lists-and-counters)\n* [Counter Styles](FEATURES.md#counter-styles)\n* [Tables](FEATURES.md#tables)\n* [Multiple Columns](FEATURES.md#multiple-columns)\n* [Flexible Box](FEATURES.md#flexible-box)\n* [Custom Properties](FEATURES.md#custom-properties)\n* [Values and Units](FEATURES.md#values-and-units)\n* [Transforms](FEATURES.md#transforms)\n* [Media Queries](FEATURES.md#media-queries)\n* [Paged Media](FEATURES.md#paged-media)\n* [Scalable Vector Graphics](FEATURES.md#scalable-vector-graphics)\n\n---\n\n## Roadmap\n\nPlutoBook is designed to grow into a powerful, flexible tool for static HTML rendering and high-quality print output. The following features are not yet available, but they are part of our long-term vision:\n\n* **JavaScript Support:** We plan to embed a lightweight JavaScript engine (like Duktape or QuickJS) so authors can use `\u003cscript\u003e` blocks to generate dynamic content such as charts, diagrams, or custom visuals with libraries like `Chart.js`.\n\n* **Accessibility Improvements:** We aim to support full PDF/UA compliance, allowing PlutoBook to automatically tag structure like headings, lists, and figures for screen readers and assistive technologies.\n\n* **CSS Grid Layout:** We plan to support full CSS Grid features including auto-placement, named lines, and implicit tracks. This will give authors greater control over page layout without extra markup or layout workarounds.\n\n* **CSS Logical Properties:** We intend to support logical CSS properties such as `margin-inline-start` and `padding-block-end`. These allow layouts to adapt more naturally to different writing modes, languages, and directions.\n\n* **CSS Exclusions:** We plan to support CSS Exclusions, which allow inline content to wrap around custom shapes defined by properties such as `shape-outside`. This makes it possible to flow text around non-rectangular elements, enabling more expressive and magazine-style layouts.\n\nYour support keeps PlutoBook moving forward as a fast, modern tool for static HTML rendering. If you’d like to help, consider becoming a sponsor: [https://github.com/sponsors/plutoprint](https://github.com/sponsors/plutoprint)\n\nEvery contribution, no matter the size, helps move the project forward.\n\n---\n\n## Practical Uses\nPlutoBook provides a robust HTML and CSS rendering engine that can be integrated into a wide range of workflows. The examples below illustrate how PlutoBook can be used in real-world scenarios.\n\n### Email Client HTML Renderer\n\nPlutoBook can render HTML content safely and consistently within an email client. With PlutoBook, developers can implement a custom rendering layer that displays email layouts and styles accurately, without needing a full web browser engine.\n\nFor example, the screenshot below shows PlutoBook rendering the first page of a **New York Times** newsletter:\n\n\u003cp align=\"center\"\u003e\u003cimg src=\"https://github.com/user-attachments/assets/72c644d6-0b95-4326-8ad4-ea7dd9afed51\" alt=\"New_York_Times_Newsletter\" width=\"500\"\u003e\u003c/p\u003e\n\n### Text Editor Print Renderer\n\nPlutoBook can be embedded in text editors such as **Sublime Text** to render HTML output for printing or print preview. This allows developers to generate clean, styled print layouts for their code, Markdown, or other text documents directly within the editor, without needing a separate browser or external PDF tool.\n\nFor example, the screenshot below shows PlutoBook rendering a **Sublime Text** document prepared for printing:\n\n\u003cp align=\"center\"\u003e\u003cimg src=\"https://github.com/user-attachments/assets/0340eca9-43ed-4fb6-8eb7-1d8b51c40d15\" alt=\"Sublime_Text_Print_Preview\" width=\"500\"\u003e\u003c/p\u003e\n\n### Automated Report Generation\n\nPlutoBook can be integrated into backend services to automatically generate high-quality PDFs or static HTML reports from dynamic data. This is useful for creating invoices, statements, or compliance documents on demand. Designers can style reports using familiar HTML and CSS, making templates easy to maintain.\n\n\u003cp align=\"center\"\u003e\u003cimg src=\"https://github.com/user-attachments/assets/49b0d5bf-ecd0-4c3e-b48a-7beefa09bd43\" alt=\"Invoice\" width=\"700\"\u003e\u003c/p\u003e\n\n### Custom E-Book or Document Viewer\n\nPlutoBook enables developers to build lightweight e-book readers or document viewers that display paginated, static HTML content with consistent styling, images, and fonts. This is ideal for publishing tools, educational apps, or offline manuals where predictable layout is important.\n\n\u003cp align=\"center\"\u003e\u003cimg src=\"https://github.com/user-attachments/assets/3e6b0768-43fd-4047-a3bc-903deed9c5ea\" alt=\"Alice’s Adventures in Wonderland\" width=\"800\"\u003e\u003c/p\u003e\n\n---\n\n## Installation Guide\n\nTo build and install **PlutoBook**, you will need [Meson](http://mesonbuild.com) and [Ninja](http://ninja-build.org) installed on your system.\n\n### Prerequisites\n\nPlutoBook depends on the following external libraries:\n\n- **Required:** `cairo`, `freetype`, `harfbuzz`, `fontconfig`, `expat`, `icu`\n- **Optional:** `curl`, `turbojpeg`, `webp` (enable additional features)\n\n\u003e [!NOTE]\n\u003e For faster builds, it is recommended to install precompiled versions of these libraries through your system's package manager. Otherwise, Meson will build them from source, which may significantly increase build time.\n\nFor **Ubuntu/Debian** users, use the following command to install both required and optional dependencies:\n\n```bash\nsudo apt-get install -y libcairo2-dev libexpat1-dev libicu-dev \\\n    libfreetype6-dev libfontconfig1-dev libharfbuzz-dev \\\n    libcurl4-openssl-dev libturbojpeg0-dev libwebp-dev \\\n    ninja-build meson\n```\n\n### Build and Installation\n\nClone the repository, then build and install the project using the following commands:\n\n```bash\ngit clone https://github.com/plutoprint/plutobook.git\ncd plutobook\nmeson setup build\nmeson compile -C build\nmeson install -C build\n```\n\nOn **macOS** and **Linux**, you can also install PlutoBook directly with [Homebrew](https://formulae.brew.sh/formula/plutobook):\n\n```bash\nbrew update\nbrew install plutobook\n```\n\n---\n\n## Packages\n\n[![Packaging status](https://repology.org/badge/vertical-allrepos/plutobook.svg)](https://repology.org/project/plutobook/versions)\n\n## API Documentation\n\nDetailed information on PlutoBook's functionalities can be found in the header files:\n\n* [plutobook.h](https://github.com/plutoprint/plutobook/blob/main/include/plutobook.h) (C API)\n* [plutobook.hpp](https://github.com/plutoprint/plutobook/blob/main/include/plutobook.hpp) (C++ API)\n\n## Contributions\n\nContributions to PlutoBook are welcome! Feel free to open issues for bug reports, feature requests, or submit pull requests with enhancements.\n\n## License\n\nPlutoBook is licensed under the [Mozilla Public License Version 2.0](https://github.com/plutoprint/plutobook/blob/main/LICENSE), allowing for both personal and commercial use.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fplutoprint%2Fplutobook","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fplutoprint%2Fplutobook","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fplutoprint%2Fplutobook/lists"}