Releases: omonien/DX.Pdfium4D
Releases · omonien/DX.Pdfium4D
v1.2.0 - VCL Support
🎉 Release v1.2.0 - VCL Support
Major Features
- ✅ Full VCL support with
TPdfViewercomponent for Windows - ✅ Separate renderer architecture for FMX and VCL
- ✅ VCL demo application with drag-and-drop support
VCL Improvements
- 🎨 Proper aspect ratio preservation in PDF rendering
- 🎯 Centered display with light gray background for better visibility
- 🔄 Smooth resizing without artifacts
- ⚡ Background rendering with loading indicator
- 📐 High DPI support for modern displays
Technical Changes
- 🏗️ Refactored core viewer logic into shared
TPdfViewerCorebase class - 🎨 Platform-specific renderers (
DX.Pdf.Renderer.FMXandDX.Pdf.Renderer.VCL) - 🔒 Improved thread safety with
TThread.Synchronize - 🛡️ Better error handling in rendering pipeline
Demo Applications
- 📱 FMX PDF Viewer - Cross-platform (Windows, macOS, Android, iOS)
- 🖥️ VCL PDF Viewer - Windows-native with VCL controls
- ⌨️ Both with keyboard navigation and drag-and-drop support
Documentation
- 📖 Updated README with FMX and VCL support details
- 📝 Clarified resource management (automatic cleanup, not reference counting)
- ✅ Added tested Delphi versions (12.3 Athens, 13 Florence)
⚠️ Minimum Delphi 10.0 (not tested, no guarantee)
Commits in this Release
748dbaa- docs: Update README with FMX and VCL support information9d1a061- chore: Remove obsolete StreamLoadingComparison example filef26bfce- chore(VCL): Add artwork assets for VCL demo applicationa7788bc- chore(VCL): Update VCL project configuration with artwork paths and platform supportf47e2b2- chore(FMX): Add missing unit references to FMX demo project7d21508- chore(VCL): Update VCL demo form with higher DPI settingsa5b74d4- feat(VCL): Improve PDF rendering with proper aspect ratio and centered display
Full Changelog: v1.1.0...v1.2.0
v1.1.0 - Efficient Stream Loading Support
🚀 New Features
Efficient Stream Loading with LoadFromStream
- True streaming support using PDFium's
FPDF_LoadCustomDocumentAPI - Zero-copy streaming - PDFium reads data blocks on-demand via callbacks
- Stream ownership management - optional automatic cleanup with
AOwnsStreamparameter - Memory efficient - no duplication of PDF data in memory
- Ideal for large PDFs, network streams, and memory-constrained scenarios
📊 Performance Improvements
- ~50% memory reduction for stream-based loading compared to previous implementation
- Stream data is read on-demand, not loaded entirely into memory
- Efficient for large PDF files (100+ MB)
🔧 API Changes
New Stream Loading API
procedure LoadFromStream(AStream: TStream; AOwnsStream: Boolean = False; const APassword: string = '');New in TPdfDocument:
LoadFromStream- Now uses efficient streaming (replaces old memory-based implementation)TPdfStreamAdapter- New adapter class bridging TStream to PDFium callbacks
New in TPdfViewer:
LoadFromStream- Updated to use efficient streaming
New in DX.Pdf.API:
FPDF_FILEACCESS- Structure for custom file accessTFPDFFileAccessGetBlock- Callback function typeFPDF_LoadCustomDocument- PDFium API binding for streaming
📚 Documentation & Examples
Usage Examples
Option A: Keep stream ownership (manual cleanup)
LStream := TMemoryStream.Create;
try
LStream.LoadFromFile('document.pdf');
PdfViewer.LoadFromStream(LStream, False); // You manage the stream
// Stream must remain valid until document is closed!
finally
LStream.Free; // You free the stream
end;Option B: Transfer ownership (recommended)
LStream := TMemoryStream.Create;
LStream.LoadFromFile('document.pdf');
PdfViewer.LoadFromStream(LStream, True); // Viewer owns the stream
// Viewer will free the stream automatically on Close()
// DO NOT free LStream yourself!Real-world scenarios
- HTTP downloads - Stream PDF directly from web without saving to disk
- Database BLOBs - Load PDFs from database fields
- Encrypted containers - Decrypt on-the-fly while streaming
- Large files - Handle 100+ MB PDFs efficiently
✅ Testing
- 19 unit tests - All passing ✅
- 5 new streaming tests:
TestLoadFromStreamBasic- Basic streaming functionalityTestLoadFromStreamWithOwnership- Stream ownership transferTestLoadFromStreamSeekable- Multiple seeks verificationTestLoadFromStreamNoMemoryDuplication- Zero-copy verificationTestStreamAdapterCallback- Callback execution verification
- No memory leaks - Verified with DUnitX memory leak detection
- Proper cleanup - Stream adapter lifecycle managed by TPdfDocument
🔄 Migration Guide
Before (v1.0.0)
LStream := TMemoryStream.Create;
try
LStream.LoadFromFile('document.pdf');
PdfViewer.LoadFromStream(LStream); // Loaded entire PDF into memory
finally
LStream.Free;
end;After (v1.1.0)
// Same code works, but now with efficient streaming!
LStream := TMemoryStream.Create;
try
LStream.LoadFromFile('document.pdf');
PdfViewer.LoadFromStream(LStream, False); // Efficient streaming
finally
LStream.Free;
end;
// Or use ownership transfer for cleaner code:
LStream := TMemoryStream.Create;
LStream.LoadFromFile('document.pdf');
PdfViewer.LoadFromStream(LStream, True); // Auto-cleanupNote: The new AOwnsStream parameter defaults to False for backwards compatibility.
🛠️ Internal Improvements
- Removed
FMemoryBuffer: TBytesfield (no longer needed) - Added
FStreamAdapter: TPdfStreamAdapterfor streaming support - Implemented exception-safe callback mechanism
- Proper cleanup in
Close()method - Optimized build scripts (removed blocking
pausecommands)
📦 Technical Details
How it works
TPdfStreamAdapterwraps a DelphiTStream- Provides
FPDF_FILEACCESSstructure with callback function pointer - PDFium calls
GetBlockCallbackto read data blocks on-demand - Callback performs
Seek+Readoperations on the stream - No memory duplication - PDFium reads directly from stream
Callback Implementation
class function TPdfStreamAdapter.GetBlockCallback(param: Pointer;
position: Cardinal; pBuf: PByte; size: Cardinal): Integer; cdecl;
var
LAdapter: TPdfStreamAdapter;
LBytesRead: Integer;
begin
Result := 0;
if param = nil then Exit;
LAdapter := TPdfStreamAdapter(param);
try
LAdapter.FStream.Position := position;
LBytesRead := LAdapter.FStream.Read(pBuf^, size);
if LBytesRead = Integer(size) then
Result := 1 // Success
else
Result := 0; // Failure
except
Result := 0; // Error
end;
end;🔗 Comparison: v1.0.0 vs v1.1.0
| Aspect | v1.0.0 | v1.1.0 |
|---|---|---|
| Stream Loading | Entire PDF in memory | On-demand streaming |
| Memory Usage (100MB PDF) | ~200 MB (2x during load) | ~100 MB (1x) |
| Large PDFs (>100MB) | ✅ Efficient | |
| Stream Ownership | Manual only | Manual or automatic |
| API Complexity | Simple | Simple + flexible |
📝 Full Changelog
Commits:
dc1cf12- Simplify API: Replace LoadFromStreamEx with improved LoadFromStreamddfd028- Implement true streaming support with FPDF_LoadCustomDocument
Files Changed:
src/DX.Pdf.API.pas- Added PDFium streaming API bindingssrc/DX.Pdf.Document.pas- Implemented TPdfStreamAdapter and efficient LoadFromStreamsrc/DX.Pdf.Viewer.FMX.pas- Updated LoadFromStream signaturesrc/tests/DX.Pdf.Document.Tests.pas- Added 5 new streaming testsexamples/StreamLoadingComparison.pas- Updated examplessrc/tests/build-and-run-tests.bat- Removed blocking pause commands
Statistics:
- Lines added: +43
- Lines removed: -180
- Net change: -137 lines (simpler, cleaner code!)
Full Changelog: v1.0.0...v1.1.0
v1.0.0 - Initial Public Release
DX Pdfium4D v1.0.0 - Initial Public Release
🎉 First stable release of DX Pdfium4D - A comprehensive Delphi wrapper for Google's PDFium library!
🚀 Features
Core Wrapper
- ✅ Object-oriented API - High-level Delphi classes wrapping PDFium C-API
- ✅ Automatic resource management - Reference counting prevents memory leaks
- ✅ Type-safe error handling - Exception-based error handling
- ✅ Cross-platform support - Windows, macOS, Android, iOS
PDF Document Support
- 📄 Load PDF documents from files or memory
- 📋 Extract metadata (title, author, subject, keywords)
- 🎯 PDF/A compliance detection
- 📏 Page count and dimensions
- 🎨 High-quality bitmap rendering with configurable DPI
Components & Tools
- 🖼️ FMX Visual Component - Ready-to-use PDF viewer component
- 📱 Example Application - DX PDF Viewer with drag & drop support
- ✅ Unit Tests - Comprehensive test suite using DUnitX
- 📚 Sample PDF Files - Test files from PDF Association
📦 What's Included
- DX.Pdf.API.pas - Low-level PDFium C-API bindings
- DX.Pdf.Document.pas - High-level document/page classes
- DX.Pdf.Viewer.FMX.pas - FMX visual component
- DX PDF Viewer - Complete example application
- Unit Tests - DUnitX test suite
- Sample PDFs - Example files for testing
- Documentation - Comprehensive README and usage guide
🎯 Getting Started
uses
DX.Pdf.Document;
var
LDocument: TPdfDocument;
LPage: TPdfPage;
LBitmap: TBitmap;
begin
LDocument := TPdfDocument.Create('document.pdf');
try
LPage := LDocument.Pages[0];
LBitmap := LPage.RenderToBitmap(96); // 96 DPI
try
// Use the bitmap
finally
LBitmap.Free;
end;
finally
LDocument.Free;
end;
end;📋 Requirements
- Delphi 12 or later (tested with Delphi 12.2 Athens)
- Minimum: Delphi XE2 (for FireMonkey support)
- Recommended: Delphi 10.x or later
📖 Documentation
See USING_DX_PDF.md for detailed usage instructions.
🙏 Acknowledgments
- Google - PDFium library
- Benoît Blanchon - PDFium binaries
- PDF Association - Sample PDF files
- VSoft Technologies - DUnitX testing framework
📄 License
MIT License - Free for commercial and open-source projects
Full Changelog: https://github.com/omonien/DX.Pdfium4D/commits/v1.0.0