Skip to content

Releases: omonien/DX.Pdfium4D

v1.2.0 - VCL Support

23 Nov 08:04

Choose a tag to compare

🎉 Release v1.2.0 - VCL Support

Major Features

  • Full VCL support with TPdfViewer component 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 TPdfViewerCore base class
  • 🎨 Platform-specific renderers (DX.Pdf.Renderer.FMX and DX.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 information
  • 9d1a061 - chore: Remove obsolete StreamLoadingComparison example file
  • f26bfce - chore(VCL): Add artwork assets for VCL demo application
  • a7788bc - chore(VCL): Update VCL project configuration with artwork paths and platform support
  • f47e2b2 - chore(FMX): Add missing unit references to FMX demo project
  • 7d21508 - chore(VCL): Update VCL demo form with higher DPI settings
  • a5b74d4 - 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

21 Nov 23:47

Choose a tag to compare

🚀 New Features

Efficient Stream Loading with LoadFromStream

  • True streaming support using PDFium's FPDF_LoadCustomDocument API
  • Zero-copy streaming - PDFium reads data blocks on-demand via callbacks
  • Stream ownership management - optional automatic cleanup with AOwnsStream parameter
  • 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 access
  • TFPDFFileAccessGetBlock - Callback function type
  • FPDF_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 functionality
    • TestLoadFromStreamWithOwnership - Stream ownership transfer
    • TestLoadFromStreamSeekable - Multiple seeks verification
    • TestLoadFromStreamNoMemoryDuplication - Zero-copy verification
    • TestStreamAdapterCallback - 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-cleanup

Note: The new AOwnsStream parameter defaults to False for backwards compatibility.

🛠️ Internal Improvements

  • Removed FMemoryBuffer: TBytes field (no longer needed)
  • Added FStreamAdapter: TPdfStreamAdapter for streaming support
  • Implemented exception-safe callback mechanism
  • Proper cleanup in Close() method
  • Optimized build scripts (removed blocking pause commands)

📦 Technical Details

How it works

  1. TPdfStreamAdapter wraps a Delphi TStream
  2. Provides FPDF_FILEACCESS structure with callback function pointer
  3. PDFium calls GetBlockCallback to read data blocks on-demand
  4. Callback performs Seek + Read operations on the stream
  5. 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) ⚠️ Not recommended ✅ Efficient
Stream Ownership Manual only Manual or automatic
API Complexity Simple Simple + flexible

📝 Full Changelog

Commits:

  • dc1cf12 - Simplify API: Replace LoadFromStreamEx with improved LoadFromStream
  • ddfd028 - Implement true streaming support with FPDF_LoadCustomDocument

Files Changed:

  • src/DX.Pdf.API.pas - Added PDFium streaming API bindings
  • src/DX.Pdf.Document.pas - Implemented TPdfStreamAdapter and efficient LoadFromStream
  • src/DX.Pdf.Viewer.FMX.pas - Updated LoadFromStream signature
  • src/tests/DX.Pdf.Document.Tests.pas - Added 5 new streaming tests
  • examples/StreamLoadingComparison.pas - Updated examples
  • src/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

21 Nov 02:13
d065b5b

Choose a tag to compare

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