Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions doc/project-doc/contributors/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ Metadata lifecycle:
- Node model remains backend-agnostic.
- Rendering is split into renderer + painters for separation of concerns.
- Layout uses chain-of-responsibility handlers to keep node-specific rules isolated.
- Context caches sub-backend interfaces (`text_backend()`, `shape_backend()`, etc.) to reduce repeated casts.
- Context caches sub-backend interfaces (`text_backend()`, `shape_backend()`, etc.) using backend composition getters (`edit_*()`).
- `DocraftDocument::render()` is the main orchestration point and intentionally centralizes pipeline sequencing.

## 5. Extension points
Expand All @@ -158,7 +158,7 @@ Primary extension points for contributors:
- Add a new backend primitive:
- extend interfaces + implement in backend + consume in painters.
- Add a new backend implementation:
- implement `IDocraftRenderingBackend` (and required inherited contracts).
- implement `IDocraftRenderingBackend` and expose composed interface objects through `edit_*()` getters.
- Add new templating capability:
- extend `DocraftTemplateEngine::template_node` + helper methods.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Important implication:

## 2. Interface contract you must implement

A backend must implement `IDocraftRenderingBackend`, which aggregates:
A backend must implement `IDocraftRenderingBackend`, which exposes composed edit-method objects for:

- text primitives,
- line/shape primitives,
Expand All @@ -27,7 +27,7 @@ A backend must implement `IDocraftRenderingBackend`, which aggregates:
- metadata application,
- font registration and font selection hooks.

In practice you implement one concrete class inheriting `IDocraftRenderingBackend`.
In practice you implement one concrete class inheriting `IDocraftRenderingBackend` and return small composed objects from the `edit_*()` getters.

## 3. External integration (recommended path)

Expand Down
4 changes: 2 additions & 2 deletions doc/project-doc/contributors/components/backend.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ The backend layer is the portability boundary for output targets.

## 1. Contract hierarchy

`IDocraftRenderingBackend` aggregates these contracts:
`IDocraftRenderingBackend` composes these contracts through getter methods:

- `IDocraftTextRenderingBackend`
- `IDocraftShapeRenderingBackend`
Expand All @@ -18,7 +18,7 @@ Plus lifecycle methods:
- font registration/selection helpers
- metadata application

This design lets renderers/painters consume only the primitives they need.
This design lets renderers/painters consume only the primitives they need while avoiding deep interface-inheritance chains.

## 2. Concrete implementation: Haru backend

Expand Down
28 changes: 23 additions & 5 deletions docraft/include/docraft/backend/docraft_rendering_backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#pragma once

#include "docraft/docraft_lib.h"
#include <memory>
#include <string>

#include "docraft/backend/docraft_image_rendering_backend.h"
Expand All @@ -32,15 +33,32 @@ namespace docraft::backend {
/**
* @brief Aggregated rendering backend interface.
*/
class DOCRAFT_LIB IDocraftRenderingBackend : public IDocraftTextRenderingBackend,
public IDocraftShapeRenderingBackend,
public IDocraftImageRenderingBackend,
public IDocraftPageRenderingBackend {
class DOCRAFT_LIB IDocraftRenderingBackend {
public:
/**
* @brief Virtual destructor.
*/
~IDocraftRenderingBackend() override = default;
virtual ~IDocraftRenderingBackend() = default;
/**
* @brief Returns line editing methods supported by this backend.
*/
[[nodiscard]] virtual const std::shared_ptr<IDocraftLineRenderingBackend>& edit_line() const = 0;
/**
* @brief Returns shape editing methods supported by this backend.
*/
[[nodiscard]] virtual const std::shared_ptr<IDocraftShapeRenderingBackend>& edit_shape() const = 0;
/**
* @brief Returns text editing methods supported by this backend.
*/
[[nodiscard]] virtual const std::shared_ptr<IDocraftTextRenderingBackend>& edit_text() const = 0;
/**
* @brief Returns image editing methods supported by this backend.
*/
[[nodiscard]] virtual const std::shared_ptr<IDocraftImageRenderingBackend>& edit_image() const = 0;
/**
* @brief Returns page editing/getter methods supported by this backend.
*/
[[nodiscard]] virtual const std::shared_ptr<IDocraftPageRenderingBackend>& edit_page() const = 0;
/**
* @brief Saves the document to a file path.
* @param path Output file path.
Expand Down
91 changes: 54 additions & 37 deletions docraft/include/docraft/backend/pdf/docraft_haru_backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ namespace docraft::backend::pdf {
*/
class DOCRAFT_LIB DocraftHaruBackend : public docraft::backend::IDocraftRenderingBackend {
public:
class LineHaruBackend;
class ShapeHaruBackend;
class TextHaruBackend;
class ImageHaruBackend;
class PageHaruBackend;

/**
* @brief Creates a Haru PDF backend with a new document and page.
*/
Expand All @@ -43,19 +49,19 @@ namespace docraft::backend::pdf {
/**
* @brief Begins a text object.
*/
void begin_text() const override;
void begin_text() const;
/**
* @brief Ends a text object.
*/
void end_text() const override;
void end_text() const;
/**
* @brief Draws text at the given coordinates.
*/
void draw_text(const std::string& text, float x, float y) const override;
void draw_text(const std::string& text, float x, float y) const;
/**
* @brief Sets text fill color.
*/
void set_text_color(float r, float g, float b) const override;
void set_text_color(float r, float g, float b) const;
/**
* @brief Draws text with a custom transformation matrix.
*/
Expand All @@ -66,71 +72,71 @@ namespace docraft::backend::pdf {
float skew_y,
float scale_y,
float translate_x,
float translate_y) const override;
float translate_y) const;
/**
* @brief Measures text width using current font settings.
*/
float measure_text_width(const std::string& text) const override;
float measure_text_width(const std::string& text) const;
#pragma endregion
#pragma region line rendering
/**
* @brief Sets stroke color for lines and shapes.
*/
void set_stroke_color(float r, float g, float b) const override;
void set_stroke_color(float r, float g, float b) const;
/**
* @brief Sets line width in points.
*/
void set_line_width(float thickness) const override;
void set_line_width(float thickness) const;
/**
* @brief Draws a line between two points.
*/
void draw_line(float x1, float y1, float x2, float y2) const override;
void draw_line(float x1, float y1, float x2, float y2) const;
#pragma endregion
#pragma region shape rendering
/**
* @brief Saves the current graphics state.
*/
void save_state() const override;
void save_state() const;
/**
* @brief Restores the previous graphics state.
*/
void restore_state() const override;
void restore_state() const;
/**
* @brief Sets fill color for shapes.
*/
void set_fill_color(float r, float g, float b) const override;
void set_fill_color(float r, float g, float b) const;
/**
* @brief Sets fill alpha for shapes.
*/
void set_fill_alpha(float alpha) const override;
void set_fill_alpha(float alpha) const;
/**
* @brief Sets stroke alpha for shapes.
*/
void set_stroke_alpha(float alpha) const override;
void set_stroke_alpha(float alpha) const;
/**
* @brief Adds a rectangle path.
*/
void draw_rectangle(float x, float y, float width, float height) const override;
void draw_rectangle(float x, float y, float width, float height) const;
/**
* @brief Adds a circle path.
*/
void draw_circle(float center_x, float center_y, float radius) const override;
void draw_circle(float center_x, float center_y, float radius) const;
/**
* @brief Adds a polygon path.
*/
void draw_polygon(const std::vector<model::DocraftPoint> &points) const override;
void draw_polygon(const std::vector<model::DocraftPoint> &points) const;
/**
* @brief Fills the current path.
*/
void fill() const override;
void fill() const;
/**
* @brief Strokes the current path.
*/
void stroke() const override;
void stroke() const;
/**
* @brief Fills and strokes the current path.
*/
void fill_stroke() const override;
void fill_stroke() const;
#pragma endregion
#pragma region image rendering
/**
Expand All @@ -141,7 +147,7 @@ namespace docraft::backend::pdf {
float x,
float y,
float width,
float height) const override;
float height) const;
/**
* @brief Draws a PNG image from memory.
*/
Expand All @@ -151,7 +157,7 @@ namespace docraft::backend::pdf {
float x,
float y,
float width,
float height) const override;
float height) const;
/**
* @brief Draws a JPEG image from file.
*/
Expand All @@ -160,7 +166,7 @@ namespace docraft::backend::pdf {
float x,
float y,
float width,
float height) const override;
float height) const;
/**
* @brief Draws a JPEG image from memory.
*/
Expand All @@ -170,7 +176,7 @@ namespace docraft::backend::pdf {
float x,
float y,
float width,
float height) const override;
float height) const;
/**
* @brief Draws a raw RGB image from file.
*/
Expand All @@ -181,7 +187,7 @@ namespace docraft::backend::pdf {
float x,
float y,
float width,
float height) const override;
float height) const;
/**
* @brief Draws a raw RGB image from memory.
*/
Expand All @@ -192,10 +198,16 @@ namespace docraft::backend::pdf {
float x,
float y,
float width,
float height) const override;
float height) const;
#pragma endregion
#pragma region backend lifecycle

[[nodiscard]] const std::shared_ptr<docraft::backend::IDocraftLineRenderingBackend>& edit_line() const override;
[[nodiscard]] const std::shared_ptr<docraft::backend::IDocraftShapeRenderingBackend>& edit_shape() const override;
[[nodiscard]] const std::shared_ptr<docraft::backend::IDocraftTextRenderingBackend>& edit_text() const override;
[[nodiscard]] const std::shared_ptr<docraft::backend::IDocraftImageRenderingBackend>& edit_image() const override;
[[nodiscard]] const std::shared_ptr<docraft::backend::IDocraftPageRenderingBackend>& edit_page() const override;

void save_to_file(const std::string& path) const override;
[[nodiscard]] std::string file_extension() const override;
/**
Expand All @@ -219,52 +231,52 @@ namespace docraft::backend::pdf {
/**
* @brief Returns the current page width in points.
*/
float page_width() const override;
float page_width() const;
/**
* @brief Returns the current page height in points.
*/
float page_height() const override;
float page_height() const;
/**
* @brief Adds a new page to the document and makes it the current page.
*/
void add_new_page() override;
void add_new_page();
/**
* @brief Moves the cursor to the next page if it exists.
* @throws std::runtime_error if already at the last page.
*/
void move_to_next_page() override;
void move_to_next_page();
/**
* @brief Navigates to a specific page (0-based index).
* @param page_number Destination page index.
* @throws std::runtime_error if the page number is out of range.
*/
void go_to_page(std::size_t page_number) override;
void go_to_page(std::size_t page_number);
/**
* @brief Navigates to the first page.
*/
void go_to_first_page() override;
void go_to_first_page();
/**
* @brief Navigates to the previous page.
* @throws std::runtime_error if already at the first page.
*/
void go_to_previous_page() override;
void go_to_previous_page();
/**
* @brief Navigates to the last page.
*/
void go_to_last_page() override;
void go_to_last_page();
/**
* @brief Sets the page size and orientation.
*/
void set_page_format(model::DocraftPageSize size,
model::DocraftPageOrientation orientation) override;
model::DocraftPageOrientation orientation);
/**
* @brief Returns the current page number (1-based index).
*/
std::size_t current_page_number() const override;
std::size_t current_page_number() const;
/**
* @brief Returns the total number of pages in the document.
*/
std::size_t total_page_count() const override;
std::size_t total_page_count() const;
#pragma endregion
private:
/**
Expand All @@ -290,5 +302,10 @@ namespace docraft::backend::pdf {
size_t current_page_number_ = 0;
mutable float fill_alpha_ = 1.0F;
mutable float stroke_alpha_ = 1.0F;
std::shared_ptr<docraft::backend::IDocraftLineRenderingBackend> edit_line_;
std::shared_ptr<docraft::backend::IDocraftShapeRenderingBackend> edit_shape_;
std::shared_ptr<docraft::backend::IDocraftTextRenderingBackend> edit_text_;
std::shared_ptr<docraft::backend::IDocraftImageRenderingBackend> edit_image_;
std::shared_ptr<docraft::backend::IDocraftPageRenderingBackend> edit_page_;
};
} // docraft
Loading