custom_pdf_editor 0.4.0
custom_pdf_editor: ^0.4.0 copied to clipboard
Flutter PDF viewer and on-canvas text editor for iOS (native PDFKit), plus PDF↔Word conversion. Requires a companion self-hosted backend (included in server/).
0.4.0 - 2026-08-19 #
Added #
- Railway deployment support with improved production readiness
- Fixed OpenGL library dependencies for Docker deployment (
libgl1,libglib2.0-0,libgomp1) - Added comprehensive Railway configuration (
railway.toml,nixpacks.toml) - Improved healthcheck configuration with extended timeout for resource-intensive startup
- Fixed Gunicorn startup issues with proper temp directory initialization
- Fixed OpenGL library dependencies for Docker deployment (
Fixed #
- Backend deployment stability
- Resolved
cv2import errors caused by missing OpenGL system libraries - Fixed temp directory creation to work correctly under Gunicorn (moved outside
if __name__ == '__main__'block) - Improved error handling for production WSGI server deployment
- Resolved
Server #
- Enhanced Dockerfile with complete system dependencies documentation
- Added
WEB_CONCURRENCYenvironment variable for worker count configuration - Improved production deployment documentation for Railway and other platforms
- All deployments now use production-ready Gunicorn instead of Flask development server
0.3.0 #
Added #
- Image text editing — edit the text inside a screenshot, photo or scan
(
ImageTextEditorWidget,ImageEditService,ImageTextDocument).- Line-level OCR (RapidOCR / PP-OCR) with same-baseline run merging, so code and wide-tracked headings come back as lines rather than loose words.
- Per-line background reconstruction: flat-fill where the background is solid (pixel-exact), inpainting only where it is textured. Nothing outside a line's own box is touched, and nothing is resampled.
- Render-and-compare font matching against 14 bundled OFL/Apache families — 90% family accuracy, 96% on weight and slant, ±1.4% on size, no model weights.
- Per-word colour sampling, so headings, links and highlighted tokens keep their own colours.
- Live editing: analysis runs once on open; typing is a local repaint.
- Untouched lines keep their original pixels, so an OCR misread cannot corrupt text the user never edited.
- New endpoints:
POST /edit/image/extract,POST /edit/image/apply,GET /edit/image/fonts.
- Bundled Latin-subset font assets (
assets/fonts/) shared by the matcher and the client renderer, withfetch_fonts/subset_fontsto regenerate them.
Added #
- An image with no recognisable text now says so, instead of reporting "0 lines" — the editor can be opened on any image, so "nothing to edit here" is a real answer rather than a failure.
- Editable lines are outlined when a document opens, then fade out — a one-off cue for which text can be tapped, since nothing else on the page said so. They stay off afterwards rather than persisting: on a dense screenshot a permanent grid of boxes obscures the content the user is reading. An app-bar toggle brings them back for as long as wanted. Lines the pipeline was unsure about are drawn in the warning colour, so "check this one" is visible at a glance. The overlay lives outside the export boundary and is covered by a test that exports with and without it and compares the bytes.
Changed #
- The editor's chrome now follows the host app's theme instead of a hardcoded
dark palette, via the new
ImageTextEditorTheme— every field optional, with anything unset resolved from the ambientTheme. The old fixed dark surfaces clashed badly with a light-themed host. - Redesigned the loading, error and status-bar surfaces: the page sits on a neutral surround with a hairline and a soft lift, progress and error states are cards rather than bare text on black, and both scroll rather than overflow on short viewports.
- A page shorter than the viewport is centred vertically instead of pinned to the top.
Fixed #
- The editor canvas was being squashed to the viewport height on any page taller
than the screen (
InteractiveViewerdefaults toconstrained: true, which clamps its child). The background was then drawn at one vertical scale while the text, erase patches and hit-testing all used the horizontal one. That one bug produced three visible symptoms: the page looked vertically stretched, taps and the in-place field landed below the line they belonged to, and the erase patches missed the original glyphs so old text stayed visible under the replacement. It also shifted every time the keyboard resized the body. - The line being edited is now panned above the keyboard instead of being left underneath it.
- The in-place field pins its strut to the metrics its baseline was measured with, so it sits on the original baseline rather than below it.
- Erase padding now scales with the text height instead of a flat 2 px, so ascenders, descenders, italic overhang and the anti-aliased fringe are covered on large text.
Server #
- New dependency:
rapidocr-onnxruntime(Apache-2.0, CPU, ~60 MB). - OCR models are loaded on a background thread at startup. Left until the first request, that cost landed entirely on the first user to scan something (~40 s on a loaded machine vs ~2-4 s once warm).
- Fixed a crash on every deskewed scan (
deskew=1):cv2.HoughLinesPreturns(N, 1, 4)on OpenCV 4 but(N, 4)on 5, and the skew estimator indexed a middle axis that no longer exists. Covered bypython -m imgedit.selftest. - The font matcher falls back to
assets/fonts/(the Latin subsets the client already ships) whenserver/fonts/is absent, so a deployment carries one 5 MB font set rather than two. Accuracy is identical either way.
Changelog #
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
0.2.4 - 2026-07-14 #
Added #
- DigitalOcean deployment guides in
server/folderDEPLOY_DIGITALOCEAN.md- Complete deployment guide for App Platform and DropletsHOSTING_COMPARISON.md- Detailed comparison between Railway and DigitalOcean hosting options- Load balancing strategy for using multiple backends simultaneously
- Cost projections and migration strategies
Documentation #
- Enhanced backend deployment documentation with multiple hosting options
- Added troubleshooting guides for DigitalOcean deployments
- Included SSL/HTTPS setup instructions for Droplet deployments
0.2.3 - 2026-07-14 #
Added #
- HANDOFF.md - Comprehensive AI agent and developer onboarding documentation
- Complete project architecture and implementation details
- Step-by-step feature explanations (shrink-to-fit, font mapping, coordinate systems)
- Backend API documentation for all endpoints
- Development setup, testing strategies, and troubleshooting guide
- Roadmap for future features and monetization ideas
Added #
- An image with no recognisable text now says so, instead of reporting "0 lines" — the editor can be opened on any image, so "nothing to edit here" is a real answer rather than a failure.
- Editable lines are outlined when a document opens, then fade out — a one-off cue for which text can be tapped, since nothing else on the page said so. They stay off afterwards rather than persisting: on a dense screenshot a permanent grid of boxes obscures the content the user is reading. An app-bar toggle brings them back for as long as wanted. Lines the pipeline was unsure about are drawn in the warning colour, so "check this one" is visible at a glance. The overlay lives outside the export boundary and is covered by a test that exports with and without it and compares the bytes.
Changed #
- Updated documentation to reflect current feature status
0.2.2 - 2026-07-14 #
Added #
- An image with no recognisable text now says so, instead of reporting "0 lines" — the editor can be opened on any image, so "nothing to edit here" is a real answer rather than a failure.
- Editable lines are outlined when a document opens, then fade out — a one-off cue for which text can be tapped, since nothing else on the page said so. They stay off afterwards rather than persisting: on a dense screenshot a permanent grid of boxes obscures the content the user is reading. An app-bar toggle brings them back for as long as wanted. Lines the pipeline was unsure about are drawn in the warning colour, so "check this one" is visible at a glance. The overlay lives outside the export boundary and is covered by a test that exports with and without it and compares the bytes.
Changed #
- The editor's chrome now follows the host app's theme instead of a hardcoded
dark palette, via the new
ImageTextEditorTheme— every field optional, with anything unset resolved from the ambientTheme. The old fixed dark surfaces clashed badly with a light-themed host. - Redesigned the loading, error and status-bar surfaces: the page sits on a neutral surround with a hairline and a soft lift, progress and error states are cards rather than bare text on black, and both scroll rather than overflow on short viewports.
- A page shorter than the viewport is centred vertically instead of pinned to the top.
Fixed (paragraph editor) #
- Text now reflows correctly. The source PDF's visual line breaks are converted to spaces on import, so a paragraph wraps naturally at the editor's width/font instead of keeping the original wrap points (which left orphan words — e.g. one word alone on a line — when the font or box size changed).
- Word/range selection while editing. Scrolling is locked while a block is selected/edited so the scroll view no longer steals text-selection drags — double-tap a word, or long-press-drag, to select and restyle specific words. (The block is still kept above the keyboard via a programmatic scroll.)
0.2.1 - 2026-07-14 #
Added #
- An image with no recognisable text now says so, instead of reporting "0 lines" — the editor can be opened on any image, so "nothing to edit here" is a real answer rather than a failure.
- Editable lines are outlined when a document opens, then fade out — a one-off cue for which text can be tapped, since nothing else on the page said so. They stay off afterwards rather than persisting: on a dense screenshot a permanent grid of boxes obscures the content the user is reading. An app-bar toggle brings them back for as long as wanted. Lines the pipeline was unsure about are drawn in the warning colour, so "check this one" is visible at a glance. The overlay lives outside the export boundary and is covered by a test that exports with and without it and compares the bytes.
Changed #
- The editor's chrome now follows the host app's theme instead of a hardcoded
dark palette, via the new
ImageTextEditorTheme— every field optional, with anything unset resolved from the ambientTheme. The old fixed dark surfaces clashed badly with a light-themed host. - Redesigned the loading, error and status-bar surfaces: the page sits on a neutral surround with a hairline and a soft lift, progress and error states are cards rather than bare text on black, and both scroll rather than overflow on short viewports.
- A page shorter than the viewport is centred vertically instead of pinned to the top.
Fixed (paragraph editor) #
- Padding between a block's text and its outline (text no longer touches the edges) — the box is inflated and the text inset by a matching amount in the editor, the live preview, and the exported PDF.
- Text selection now works while editing — canvas gestures are deferred to the text field, so long-press / drag / double-tap select text (and the toolbar restyles just that selection). Tap outside the field to finish.
- Increasing the font size now grows the box instead of clipping the text — the box re-fits on any style change (size / bold / alignment), not just typing.
- Alignment changes no longer clip the text.
Requires redeploying the backend (the exported
<div>now has matching padding).
0.2.0 - 2026-07-13 #
Added #
PdfBackendService— one unified, UI-free client for every backend operation:wordToPdf,pptToPdf,excelToPdf,pdfToWord,pdfToPptx,pdfToExcel,compressPdf,repairPdf,ocrPdf(allbaseUrl-configurable).- Backend endpoints (
server/):/convert/office2pdf(LibreOffice, high fidelity),/convert/pdf2pptx,/convert/pdf2excel,/repair/pdf,/ocr/pdf. - Dockerfile for the backend bundling free/open-source tools: LibreOffice,
Tesseract (OCR), qpdf/ghostscript.
render.yamlswitched to the Docker runtime. ParagraphEditorWidget:onComplete(hand result back to a host editor, skipping the built-in preview) andappBarTitle.- Paragraph editor: rich (per-run) text editing — select a range and restyle it.
Added #
- An image with no recognisable text now says so, instead of reporting "0 lines" — the editor can be opened on any image, so "nothing to edit here" is a real answer rather than a failure.
- Editable lines are outlined when a document opens, then fade out — a one-off cue for which text can be tapped, since nothing else on the page said so. They stay off afterwards rather than persisting: on a dense screenshot a permanent grid of boxes obscures the content the user is reading. An app-bar toggle brings them back for as long as wanted. Lines the pipeline was unsure about are drawn in the warning colour, so "check this one" is visible at a glance. The overlay lives outside the export boundary and is covered by a test that exports with and without it and compares the bytes.
Changed #
- Word → PDF now uses LibreOffice (was a low-fidelity reportlab redraw).
- Dropped the
docx_to_textdependency; migrated toarchive: ^4.0.0.
Note #
- The conversion/repair/OCR features require redeploying the backend with the new Docker image (the old Python buildpack cannot install LibreOffice/Tesseract).
0.1.0 - 2026-07-10 #
Added #
Core Features
- Initial release of Custom PDF Editor plugin (iOS only)
- PDF viewing with zoom, pan, and navigation controls
- High-performance rendering using native PDFKit (iOS)
- On-canvas text editing (
AdvancedPdfEditorWidget): tap a line to edit it in place with the original font/size/colour; shrink-to-fit prevents overlap; edits are batched and applied in one backend call on save - PDF ↔ Word conversion (
PdfConversionService) - PDF compression (
PdfCompressionService) with low/medium/high levels - Paragraph editor (
ParagraphEditorWidget, beta): Acrobat-style block mode — drag/resize paragraphs, edit text, and change size/colour/bold/italic/alignment, baked with reflow via the backendinsert_htmlbox - Comprehensive PdfController for managing PDF operations
- Platform view integration for seamless Flutter embedding
Configuration
backendUrlis required onAdvancedPdfEditorWidget/DocxEditorWidgetandbaseUrlon the services — point them at your own self-hosted backend (server/). No backend URL is bundled.
iOS Features (PDFKit)
- Full PDF viewer implementation with PDFView
- Thumbnail navigation panel
- Text search with highlighting
- Page navigation (previous/next, go to page)
- Zoom controls with configurable min/max
- Dark mode support
- Toolbar with customizable tools
Annotation System
- Highlight annotations with customizable colors
- Ink/drawing annotations with PencilKit integration
- Shape annotations (squares, circles)
- Free text notes
- Stamps and signatures support
- Customizable annotation properties (color, opacity, border width)
- Add, remove, and update annotations
Text Editing
- Add text anywhere on PDF pages
- Custom text styling (font, size, color)
- Text alignment (left, center, right, justified)
- Bold and italic styles
Image Handling
- Insert images at any position
- Image resizing and positioning
- Support for common image formats
Document Management
- Load PDF from file path or bytes
- Save PDF to file or get as bytes
- Password-protected PDF support
- Document metadata extraction
Page Operations
- Delete and rotate pages
Platform Support #
- ✅ iOS 12.0+
- ❌ Android — not yet implemented
[Unreleased] #
Planned #
- Enhanced Android implementation
- Web and desktop support
- OCR and redaction tools
- Digital signatures
- Form builder UI