2026-05-15 10:39:16 +05:30
|
|
|
#pragma once
|
|
|
|
|
|
2026-05-22 15:47:48 +05:30
|
|
|
#include <expected>
|
|
|
|
|
#include <memory>
|
|
|
|
|
#include <string>
|
|
|
|
|
#include <vector>
|
|
|
|
|
#include <cstdint>
|
|
|
|
|
|
2026-05-15 10:39:16 +05:30
|
|
|
namespace pdfengine {
|
|
|
|
|
|
2026-05-22 15:47:48 +05:30
|
|
|
enum class EngineError {
|
|
|
|
|
FileNotFound,
|
|
|
|
|
InvalidFormat,
|
|
|
|
|
PasswordRequired,
|
|
|
|
|
InvalidPassword,
|
|
|
|
|
PageOutOfBounds,
|
|
|
|
|
RenderFailed,
|
|
|
|
|
WriteFailed,
|
|
|
|
|
Unknown
|
|
|
|
|
};
|
2026-05-15 10:39:16 +05:30
|
|
|
|
2026-05-22 15:47:48 +05:30
|
|
|
struct DocumentMetadata {
|
|
|
|
|
std::string title;
|
|
|
|
|
std::string author;
|
|
|
|
|
std::string creator;
|
|
|
|
|
std::string producer;
|
|
|
|
|
std::string creationDate;
|
|
|
|
|
std::string modificationDate;
|
|
|
|
|
};
|
2026-05-15 10:39:16 +05:30
|
|
|
|
2026-06-12 15:04:09 +05:30
|
|
|
struct DocumentPermissions {
|
|
|
|
|
bool isEncrypted = false;
|
2026-06-18 16:48:29 +05:30
|
|
|
std::string encryption = "None";
|
|
|
|
|
int securityRevision = -1;
|
|
|
|
|
bool ownerUnlocked = false;
|
2026-06-12 15:04:09 +05:30
|
|
|
|
|
|
|
|
bool canPrint = true;
|
|
|
|
|
bool canPrintHighRes = true;
|
|
|
|
|
bool canModify = true;
|
2026-06-18 16:48:29 +05:30
|
|
|
bool canCopy = true;
|
|
|
|
|
bool canAnnotate = true;
|
2026-06-12 15:04:09 +05:30
|
|
|
bool canFillForms = true;
|
|
|
|
|
bool canExtractForAccessibility = true;
|
2026-06-18 16:48:29 +05:30
|
|
|
bool canAssemble = true;
|
2026-06-12 15:04:09 +05:30
|
|
|
};
|
|
|
|
|
|
2026-05-22 15:47:48 +05:30
|
|
|
struct PageImage {
|
|
|
|
|
int width;
|
|
|
|
|
int height;
|
|
|
|
|
std::vector<uint8_t> data;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct Point2D {
|
|
|
|
|
double x;
|
|
|
|
|
double y;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct DevicePoint {
|
|
|
|
|
int x;
|
|
|
|
|
int y;
|
|
|
|
|
};
|
|
|
|
|
|
2026-05-25 14:47:38 +05:30
|
|
|
struct GlyphBounds {
|
|
|
|
|
std::string text;
|
|
|
|
|
double x;
|
|
|
|
|
double y;
|
|
|
|
|
double w;
|
|
|
|
|
double h;
|
|
|
|
|
double fontSize;
|
|
|
|
|
};
|
|
|
|
|
|
2026-06-11 19:19:01 +05:30
|
|
|
struct HitResult {
|
2026-06-18 16:48:29 +05:30
|
|
|
int glyphIndex = -1;
|
|
|
|
|
int caret = 0;
|
|
|
|
|
int line = -1;
|
2026-06-11 19:19:01 +05:30
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct TextSelection {
|
2026-06-18 16:48:29 +05:30
|
|
|
int startGlyph = 0;
|
|
|
|
|
int endGlyph = 0;
|
2026-06-11 19:19:01 +05:30
|
|
|
std::string text;
|
2026-06-18 16:48:29 +05:30
|
|
|
std::vector<GlyphBounds> rects;
|
2026-06-11 19:19:01 +05:30
|
|
|
};
|
|
|
|
|
|
2026-05-26 15:55:48 +05:30
|
|
|
struct FontInfo {
|
|
|
|
|
std::string fontName;
|
2026-06-18 16:48:29 +05:30
|
|
|
std::string type;
|
2026-05-26 15:55:48 +05:30
|
|
|
bool isEmbedded = false;
|
|
|
|
|
bool isSubset = false;
|
|
|
|
|
bool isVertical = false;
|
|
|
|
|
|
2026-06-18 16:48:29 +05:30
|
|
|
std::string encoding;
|
|
|
|
|
bool hasToUnicode = false;
|
|
|
|
|
std::string cmapName;
|
|
|
|
|
std::string cidSystemInfo;
|
|
|
|
|
std::string subsetTag;
|
|
|
|
|
std::string sourceType;
|
|
|
|
|
std::string substitutedFrom;
|
|
|
|
|
std::string substitutedTo;
|
|
|
|
|
std::string normalizedFamily;
|
|
|
|
|
std::string internalFontId;
|
|
|
|
|
uint32_t flags = 0;
|
|
|
|
|
double ascent = 0.0;
|
|
|
|
|
double descent = 0.0;
|
|
|
|
|
double capHeight = 0.0;
|
2026-05-26 15:55:48 +05:30
|
|
|
};
|
|
|
|
|
|
2026-06-08 11:23:27 +05:30
|
|
|
struct Glyph {
|
|
|
|
|
std::string text;
|
|
|
|
|
uint32_t unicode = 0;
|
|
|
|
|
|
|
|
|
|
std::string fontName;
|
|
|
|
|
uint32_t flags = 0;
|
|
|
|
|
double fontSize = 0.0;
|
|
|
|
|
|
|
|
|
|
double originX = 0.0;
|
|
|
|
|
double originY = 0.0;
|
|
|
|
|
double bboxX = 0.0, bboxY = 0.0, bboxW = 0.0, bboxH = 0.0;
|
|
|
|
|
double angle = 0.0;
|
2026-06-11 18:19:26 +05:30
|
|
|
int pageObjectIndex = -1;
|
2026-06-24 10:42:05 +05:30
|
|
|
int srcIndex = 0;
|
2026-06-08 11:23:27 +05:30
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct TextRun {
|
|
|
|
|
std::string text;
|
|
|
|
|
std::string fontName;
|
|
|
|
|
uint32_t flags = 0;
|
|
|
|
|
double fontSize = 0.0;
|
|
|
|
|
std::string internalFontId;
|
2026-06-08 16:28:10 +05:30
|
|
|
bool isEmbedded = false;
|
|
|
|
|
std::string type;
|
2026-06-08 11:23:27 +05:30
|
|
|
std::vector<Glyph> glyphs;
|
2026-06-11 18:19:26 +05:30
|
|
|
std::vector<int> objectIndices;
|
2026-06-08 11:23:27 +05:30
|
|
|
double x = 0.0, y = 0.0, w = 0.0, h = 0.0;
|
2026-06-18 16:48:29 +05:30
|
|
|
std::string fillColor = "#000000";
|
|
|
|
|
std::string paraId;
|
2026-06-26 11:33:28 +05:30
|
|
|
std::string fontFidelity = "exact";
|
2026-06-08 11:23:27 +05:30
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct TextLine {
|
|
|
|
|
std::vector<TextRun> runs;
|
2026-06-08 16:28:10 +05:30
|
|
|
std::vector<Glyph> glyphs;
|
|
|
|
|
double angle = 0.0;
|
2026-06-08 11:23:27 +05:30
|
|
|
double baselineY = 0.0;
|
|
|
|
|
double x = 0.0, y = 0.0, w = 0.0, h = 0.0;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct Paragraph {
|
|
|
|
|
std::vector<TextLine> lines;
|
|
|
|
|
double x = 0.0, y = 0.0, w = 0.0, h = 0.0;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct PageModel {
|
|
|
|
|
std::vector<Paragraph> paragraphs;
|
|
|
|
|
double width = 0.0;
|
|
|
|
|
double height = 0.0;
|
|
|
|
|
int pageIndex = 0;
|
|
|
|
|
};
|
|
|
|
|
|
2026-05-22 15:47:48 +05:30
|
|
|
class PdfPage {
|
|
|
|
|
public:
|
|
|
|
|
virtual ~PdfPage() = default;
|
|
|
|
|
|
|
|
|
|
[[nodiscard]] virtual double width() const noexcept = 0;
|
|
|
|
|
[[nodiscard]] virtual double height() const noexcept = 0;
|
|
|
|
|
|
|
|
|
|
[[nodiscard]] virtual std::expected<PageImage, EngineError> render(int dpi = 96) const = 0;
|
|
|
|
|
|
2026-06-17 11:39:01 +05:30
|
|
|
[[nodiscard]] virtual std::expected<PageImage, EngineError>
|
|
|
|
|
renderRegionRaw(int dpi, double yTopPt, double heightPt) const {
|
|
|
|
|
(void)dpi; (void)yTopPt; (void)heightPt;
|
|
|
|
|
return std::unexpected(EngineError::Unknown);
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-22 15:47:48 +05:30
|
|
|
[[nodiscard]] virtual std::expected<std::string, EngineError> extractText() const = 0;
|
|
|
|
|
|
2026-05-25 14:47:38 +05:30
|
|
|
[[nodiscard]] virtual std::expected<std::vector<GlyphBounds>, EngineError> extractTextWithBounds() const = 0;
|
2026-06-11 19:19:01 +05:30
|
|
|
|
|
|
|
|
[[nodiscard]] std::expected<std::vector<GlyphBounds>, EngineError> orderedGlyphs() const;
|
|
|
|
|
|
|
|
|
|
[[nodiscard]] std::expected<HitResult, EngineError> hitGlyph(double x, double y) const;
|
|
|
|
|
|
|
|
|
|
[[nodiscard]] std::expected<TextSelection, EngineError>
|
|
|
|
|
selectRange(double ax, double ay, double bx, double by) const;
|
|
|
|
|
|
2026-06-08 11:23:27 +05:30
|
|
|
[[nodiscard]] virtual std::expected<PageModel, EngineError> extractDocumentModel() const = 0;
|
2026-05-25 14:47:38 +05:30
|
|
|
|
2026-05-26 15:55:48 +05:30
|
|
|
[[nodiscard]] virtual std::expected<std::vector<FontInfo>, EngineError> getFonts() const = 0;
|
2026-05-26 15:52:04 +05:30
|
|
|
[[nodiscard]] virtual std::expected<std::vector<std::string>, EngineError> extractAnnotationsText() const = 0;
|
2026-06-09 10:35:12 +05:30
|
|
|
|
|
|
|
|
struct AnnotationInfo {
|
|
|
|
|
std::string id;
|
2026-06-18 16:48:29 +05:30
|
|
|
std::string type;
|
2026-06-09 10:35:12 +05:30
|
|
|
double x = 0.0, y = 0.0, width = 0.0, height = 0.0;
|
|
|
|
|
std::string color;
|
|
|
|
|
std::string author;
|
|
|
|
|
std::string content;
|
|
|
|
|
std::string timestamp;
|
|
|
|
|
int pageIndex = 0;
|
|
|
|
|
std::vector<std::vector<Point2D>> paths;
|
2026-06-18 16:48:29 +05:30
|
|
|
|
2026-06-10 18:38:38 +05:30
|
|
|
std::string fieldName;
|
|
|
|
|
std::string fieldValue;
|
|
|
|
|
std::string fieldType;
|
|
|
|
|
int fieldFlags = 0;
|
|
|
|
|
std::vector<std::string> fieldOptions;
|
2026-06-09 10:35:12 +05:30
|
|
|
};
|
|
|
|
|
[[nodiscard]] virtual std::expected<std::vector<AnnotationInfo>, EngineError> extractAnnotations() const = 0;
|
2026-05-26 15:55:48 +05:30
|
|
|
|
2026-06-03 10:51:33 +05:30
|
|
|
[[nodiscard]] virtual std::expected<double, EngineError> getGlyphWidth(const std::string& fontName, uint32_t charcode, double fontSize) const = 0;
|
|
|
|
|
|
2026-05-22 15:47:48 +05:30
|
|
|
[[nodiscard]] virtual DevicePoint pageToDevice(const Point2D& pagePoint, int deviceWidth, int deviceHeight, int rotate = 0) const noexcept = 0;
|
|
|
|
|
[[nodiscard]] virtual Point2D deviceToPage(const DevicePoint& devicePoint, int deviceWidth, int deviceHeight, int rotate = 0) const noexcept = 0;
|
2026-06-22 16:23:59 +05:30
|
|
|
|
|
|
|
|
[[nodiscard]] virtual std::expected<std::string, EngineError> extractDisplayListJson() const = 0;
|
|
|
|
|
[[nodiscard]] virtual std::expected<std::vector<uint8_t>, EngineError> extractImageXObject(const std::string& name) const = 0;
|
2026-05-22 15:47:48 +05:30
|
|
|
};
|
|
|
|
|
|
2026-06-08 11:23:27 +05:30
|
|
|
namespace fonts::pdf_fonts { class Font; }
|
|
|
|
|
|
2026-05-22 15:47:48 +05:30
|
|
|
class PdfDocument {
|
|
|
|
|
public:
|
|
|
|
|
virtual ~PdfDocument() = default;
|
|
|
|
|
|
|
|
|
|
[[nodiscard]] static std::expected<std::shared_ptr<PdfDocument>, EngineError>
|
|
|
|
|
loadFromFile(const std::string& path, const std::string& password = "");
|
|
|
|
|
|
|
|
|
|
[[nodiscard]] static std::expected<std::shared_ptr<PdfDocument>, EngineError>
|
|
|
|
|
loadFromMemory(const std::vector<uint8_t>& data, const std::string& password = "");
|
|
|
|
|
|
|
|
|
|
[[nodiscard]] virtual int pageCount() const noexcept = 0;
|
|
|
|
|
[[nodiscard]] virtual DocumentMetadata metadata() const noexcept = 0;
|
2026-06-12 15:04:09 +05:30
|
|
|
[[nodiscard]] virtual DocumentPermissions permissions() const noexcept = 0;
|
2026-05-22 15:47:48 +05:30
|
|
|
|
2026-06-10 21:51:43 +05:30
|
|
|
struct OutlineItem {
|
|
|
|
|
std::string title;
|
2026-06-18 16:48:29 +05:30
|
|
|
int pageIndex = -1;
|
|
|
|
|
int level = 0;
|
2026-06-10 21:51:43 +05:30
|
|
|
};
|
|
|
|
|
[[nodiscard]] virtual std::expected<std::vector<OutlineItem>, EngineError> extractOutline() const = 0;
|
|
|
|
|
|
|
|
|
|
[[nodiscard]] virtual std::expected<std::shared_ptr<PdfPage>, EngineError>
|
2026-05-22 15:47:48 +05:30
|
|
|
getPage(int pageIndex) = 0;
|
|
|
|
|
|
2026-05-26 15:55:48 +05:30
|
|
|
[[nodiscard]] virtual std::expected<std::vector<FontInfo>, EngineError>
|
|
|
|
|
getFonts(int startPage = 0, int endPage = -1) const = 0;
|
|
|
|
|
|
2026-06-26 11:33:28 +05:30
|
|
|
[[nodiscard]] virtual std::expected<std::vector<uint8_t>, EngineError>
|
2026-06-06 11:21:31 +05:30
|
|
|
getFontData(const std::string& internalFontId) const = 0;
|
|
|
|
|
|
2026-06-26 11:33:28 +05:30
|
|
|
[[nodiscard]] virtual std::expected<std::vector<uint8_t>, EngineError>
|
|
|
|
|
getReconstructedFontData(const std::string& internalFontId) { (void)internalFontId; return std::unexpected(EngineError::Unknown); }
|
|
|
|
|
|
|
|
|
|
virtual void registerAuxFont(const std::string& internalFontId, const std::vector<uint8_t>& sfnt) { (void)internalFontId; (void)sfnt; }
|
|
|
|
|
|
2026-06-08 11:23:27 +05:30
|
|
|
[[nodiscard]] virtual std::expected<std::shared_ptr<fonts::pdf_fonts::Font>, std::string>
|
|
|
|
|
getResolvedFont(const FontInfo& fontInfo) = 0;
|
|
|
|
|
|
2026-05-22 15:47:48 +05:30
|
|
|
virtual std::expected<void, EngineError> applyEdits(const std::string& editsJson) = 0;
|
|
|
|
|
|
2026-06-16 10:56:08 +05:30
|
|
|
[[nodiscard]] virtual std::string lastReflowLayout() const { return {}; }
|
|
|
|
|
|
2026-06-18 16:48:29 +05:30
|
|
|
[[nodiscard]] virtual bool lastReflowOverflowed() const { return false; }
|
|
|
|
|
|
2026-05-22 15:47:48 +05:30
|
|
|
[[nodiscard]] virtual std::expected<std::vector<uint8_t>, EngineError>
|
|
|
|
|
saveIncremental() const = 0;
|
2026-06-08 16:53:02 +05:30
|
|
|
|
2026-06-30 21:18:46 +05:30
|
|
|
[[nodiscard]] virtual std::expected<std::vector<uint8_t>, EngineError>
|
2026-06-08 16:53:02 +05:30
|
|
|
saveFull() const = 0;
|
2026-06-30 21:18:46 +05:30
|
|
|
|
|
|
|
|
[[nodiscard]] virtual std::expected<std::vector<uint8_t>, EngineError>
|
|
|
|
|
saveFullForExport() const { return saveFull(); }
|
2026-05-22 15:47:48 +05:30
|
|
|
};
|
|
|
|
|
|
|
|
|
|
}
|