fix
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user