This commit is contained in:
saqib mir
2026-07-30 16:48:46 +05:30
parent 94b7f28d9c
commit ca3d124b0d
55 changed files with 5015 additions and 182 deletions
+93
View File
@@ -0,0 +1,93 @@
#pragma once
#include <string>
#include <vector>
#include <memory>
#include <expected>
#include <cstdint>
#include "pdfengine/pdf_document.hpp"
namespace pdfengine {
struct Rect {
double x = 0.0;
double y = 0.0;
double width = 0.0;
double height = 0.0;
};
using RectList = std::vector<Rect>;
struct ParagraphBounds {
Rect rect;
};
struct GlyphInfo {
uint32_t glyphId = 0;
uint32_t cluster = 0;
double x = 0.0;
double y = 0.0;
double advance = 0.0;
double width = 0.0;
double ascent = 0.0;
double descent = 0.0;
std::string text;
};
struct LineInfo {
int id = 0;
Rect rect;
double baselineY = 0.0;
};
struct CaretState {
int offset = 0;
Rect rect;
};
// Internal comprehensive layout state
struct LayoutResult {
ParagraphBounds bounds;
std::vector<LineInfo> lines;
std::vector<GlyphInfo> glyphs;
std::vector<Rect> selectionRects;
CaretState caret;
RectList dirtyRects;
};
// Stable, lightweight view for WASM export
struct LayoutView {
std::vector<LineInfo> lines;
std::vector<GlyphInfo> glyphs;
CaretState caret;
RectList dirtyRects;
};
class EditSession {
public:
virtual ~EditSession() = default;
static std::shared_ptr<EditSession> StartEditSession(
std::shared_ptr<PdfDocument> doc,
int pageIndex,
const std::string& paraId
);
// Returns a stable, lightweight view of the layout
virtual LayoutView GetLayoutView() const = 0;
// Geometry queries against the cached layout
// offset represents the caret insertion point (between glyphs)
virtual int HitTest(double x, double y) const = 0;
virtual Rect GetCaretRect(int offset) const = 0;
virtual std::vector<Rect> GetSelectionRects(int startOffset, int endOffset) const = 0;
// Mutates paragraph, marks cache dirty, recalculates
virtual void ApplyEdit(const std::string& editOpJson) = 0;
// Rendering & Lifecycle
virtual std::vector<uint8_t> RenderDirtyRegion(int dpi, const Rect& region) const = 0;
virtual bool CommitEdit() = 0;
virtual void CancelEdit() = 0;
};
} // namespace pdfengine
+11 -1
View File
@@ -1,12 +1,21 @@
#pragma once
#include <expected>
#include <memory>
#include <string>
#include <vector>
#include <cstdint>
#include <array>
#if __has_include(<expected>)
#include <expected>
#elif __has_include(<tl/expected.hpp>)
#include <tl/expected.hpp>
namespace std {
using tl::expected;
using tl::unexpected;
}
#endif
namespace pdfengine {
enum class EngineError {
@@ -276,6 +285,7 @@ public:
virtual std::expected<std::vector<InvalidatedRegion>, EngineError> applyEdits(const std::string& editsJson) = 0;
[[nodiscard]] virtual std::string validateLayout(int pageIndex, const std::string& jsonStr) { (void)pageIndex; (void)jsonStr; return "{}"; }
[[nodiscard]] virtual std::string lastReflowLayout() const { return {}; }
[[nodiscard]] virtual bool lastReflowOverflowed() const { return false; }
@@ -0,0 +1,66 @@
#pragma once
#include "pdfengine/edit_session.hpp"
#include "fonts/shaping/hb_shaper.hpp"
#include "fonts/face/font_face.hpp"
#include <string>
#include <vector>
#include <memory>
namespace pdfengine::text {
struct LayoutConstraints {
double columnLeft = 0.0;
double columnRight = 0.0;
double firstBaselineY = 0.0;
double leading = 0.0;
std::string align = "left";
double hangingIndent = 0.0;
};
class LineBreaker {
public:
LineBreaker(const LayoutConstraints& constraints);
// Processes a stream of shaped glyphs and applies line breaking
void ProcessRun(
const std::vector<fonts::ShapedGlyph>& shapedGlyphs,
const std::string& runText,
double fontSize,
const fonts::FontFace& face,
double scale
);
// Finalizes the layout and populates the LayoutResult
void Finalize(LayoutResult& outLayout);
private:
LayoutConstraints constraints_;
double currentX_;
double currentY_;
// Internal state for word wrapping
std::vector<GlyphInfo> currentLineGlyphs_;
std::vector<LineInfo> finishedLines_;
std::vector<GlyphInfo> allGlyphs_;
void CommitLine();
};
class TextLayoutEngine {
public:
TextLayoutEngine();
// Computes layout for a given text run (simplified for single font for now)
LayoutResult ComputeLayout(
const std::string& text,
const LayoutConstraints& constraints,
fonts::FontFace& fontFace,
double fontSize
);
private:
fonts::HbShaper shaper_;
};
} // namespace pdfengine::text