Migrate from Quick PDF Library and PdfiumViewer to sgcPDF

Foxit sunset Quick PDF Library on 13 December 2021, and the PdfiumViewer repository has been read only since 2 August 2019. sgcPDF replaces both: pure Pascal compiled into your Delphi exe, and managed C# for WinForms, with no PDF DLL to deploy. This kit maps the Quick PDF Library functions and the PdfiumViewer classes to sgcPDF, with code from two samples that compile and pass their self tests.

Applications Built on a PDF Library That No Longer Moves

Two common cases: a Delphi application that creates, merges, fills and renders PDF files with Quick PDF Library, and a WinForms application that shows PDF files with PdfiumViewer.

From Quick PDF Library (Delphi)

Quick PDF Library (Debenu Quick PDF Library, later Foxit Quick PDF Library) ships as a DLL, ActiveX or LIB with an unlock key, and works on one object with a "selected" document, page, font and image. sgcPDF is a set of Pascal units with an object model: TsgcPDFDocument, TsgcPDFPage, TsgcPDFEditor and TsgcPDFAcroForm, from Delphi 7 to Delphi 13.

From PdfiumViewer (WinForms)

PdfiumViewer wraps the native PDFium library in a PdfViewer control, a PdfRenderer and a PdfDocument. It shows, searches, renders and prints PDF files. sgcPDF replaces them with one managed control, TsgcPDFViewerControl, and adds what PdfiumViewer never had: creating PDF files, filling forms, adding annotations and saving changes.

Quick PDF Library. The Foxit notice (read on 2026-10-20) says: "From December 13th 2021, Foxit will be sunsetting the following products", and the first product in the list is Foxit Quick PDF Library (All Platforms). Customers with active Maintenance and Support contracts were supported until December 13th, 2022: "After that date, the product will go into end-of-support and you will not be supported any longer." The replacements Foxit names are its PDF SDKs for Windows, Mac, Linux, Android and iOS, its ActiveX SDK and its .NET SDK suite.

PdfiumViewer. The GitHub repository (read on 2026-10-20) shows: "This repository was archived by the owner on Aug 2, 2019. It is now read-only." Its README explains: "I haven't been able to spend any real time on this for a long time now", and "I'm not in a position to properly support this project." It also says: "The PdfiumViewer control requires native PDFium libraries. These are not included in the PdfiumViewer NuGet package." The NuGet package was last updated on 11/6/2017 (version 2.13.0) and targets net20.

One PDF Library, Source Code Included

sgcPDF is the PDF product of sgcUI. It creates, edits, fills, signs, encrypts, renders and shows PDF files in Delphi and in .NET.

No PDF DLL to ship

In Delphi the sgcPDF units compile into the exe: no DLL, ActiveX or LIB to deploy and register, and no unlock key call. In .NET sgcPDF is managed C#, so there is no pdfium.dll and no x86 or x64 native package to choose: the sample runs as AnyCPU.

An object model

Every call takes the page object or index, so the "selected" state of Quick PDF Library disappears. Imposition uses vector form XObjects (AddPageAsForm, DrawForm, DrawFormInRect), forms use AcroForm, and encryption goes up to AES-256 (emAES_256).

A viewer that edits

TsgcPDFViewerControl fits the width, the page or the height, rotates the view, searches and prints with a dialog, and in .NET it hands out a PrintDocument like PdfiumViewer. It also fills form fields (FormFilling), adds annotations with the mouse (AnnotationTool) and selects text. Side views: TsgcPDFThumbnailView, TsgcPDFOutlineView, TsgcPDFCommentsView.

sgcPDF is sold on its own, from €249 for a single developer in Delphi and C++ Builder and from €249 for .NET, with full source code and 1 year of updates, and it is part of sgcUI Enterprise and of the All-Access bundle. The .NET packages also ship as free Community packages on NuGet, esegece.sgcPDF.Community and esegece.sgcPDF.WinForms.Community, with the same features. See the sgcPDF product page.

Quick PDF Library Functions in sgcPDF

The units are sgcPDF_Types, sgcPDF_Fonts and sgcPDF_Document, plus sgcPDF_Editor, sgcPDF_Encryption, sgcPDF_Renderer_GDI and sgcPDF_Export where needed. sgcPDF page indexes are 0-based.

Quick PDF Library sgcPDF
UnlockKeynothing to call in code
NewDocumentTsgcPDFDocument.Create, then AddPage (a new document has no page until you add one)
NewPage, SetPageDimensions, SetPageSizeTsgcPDFDocument.AddPage(AWidth, AHeight): TsgcPDFPage, InsertPage(AIndex, AWidth, AHeight)
LoadFromFile, LoadFromStringTsgcPDFDocument.LoadFromFile, LoadFromStream, LoadFromBytes
LoadFromFile with a passwordTsgcPDFDocument.SetPassword(APassword) before LoadFromFile
SaveToFile, SaveToStringTsgcPDFDocument.SaveToFile, SaveToStream, SaveIncremental
PageCountTsgcPDFDocument.PageCount; for a file only, sgcPDFGetPageCount(AFileName)
SelectPageTsgcPDFDocument.Pages[AIndex] (0-based, default property), GetPage(AIndex)
SetInformationTsgcPDFDocument.Info.Title, .Author, .Subject, .Keywords, .Creator, .Producer
AddStandardFont + SelectFont + SetTextSize + DrawTextTsgcPDFPage.DrawText(AText, X, Y, AFont, AFontSize) with a TsgcPDFStandardFont (sfHelvetica, sfTimesRoman, sfCourier and their bold and italic variants)
SetTextColor + DrawTextTsgcPDFPage.DrawTextColor(AText, X, Y, AFont, AFontSize, R, G, B) (components from 0 to 1)
AddTrueTypeFont + DrawTextTsgcPDFDocument.AddTrueTypeFont(AFontName, ABold, AItalic): Integer (or AddTrueTypeFontFromFile), then TsgcPDFPage.DrawTextTT
DrawLine, DrawBoxTsgcPDFPage.DrawLine(X1, Y1, X2, Y2, ALineWidth), DrawRectangle(X, Y, W, H, ALineWidth), DrawRectangleFill
AddImageFromFile + SelectImage + DrawImageTsgcPDFDocument.AddImage(AFileName): Integer + TsgcPDFPage.DrawImageFromIndex(AIndex, X, Y, W, H), or DrawImageFile(AFileName, X, Y, W, H)
GetPageTextTsgcPDFDocument.ExtractTextW(APageIndex), ExtractText, FindText; TsgcPDFEditor.ExtractAllText, SearchText
AddToFileList + MergeFileListsgcPDFMergeFiles([...], AOutputFile)
MergeDocumentTsgcPDFDocument.AppendDocument(ADoc), TsgcPDFEditor.MergeFrom(AFileName)
ExtractPageRanges, ExtractFilePagessgcPDFExtractPages(AInputFile, AOutputFile, ARange) (1-based range string such as '1,3,5-9'), TsgcPDFEditor.ExtractPages(ARange, AOutputFileName)
DeletePagesTsgcPDFDocument.DeletePages(ARange), DeletePage(AIndex)
RotatePageTsgcPDFEditor.RotatePage(AIndex, ADegrees)
SetTransparency + DrawText (watermark)TsgcPDFEditor.AddWatermarkAllPages(TsgcPDFWatermarkOptions), AddWatermark, AddTransparentText
DrawText on every page (stamp, header, footer)TsgcPDFEditor.AddTextColor, AddHeaderText, AddFooterText, AddPageNumbers
RenderPageToDCTsgcPDFRendererGDI.RenderPage(ADC, ADocument.Parser, APage.PageDict, AWidth, AHeight); in the VCL viewer TsgcPDFViewerControl.RenderPageToBitmap
RenderPageToFileTsgcPDFExporter.ExportPage(ADocument, APageIndex, AFileName) (BMP, PNG, JPEG), sgcPDFPageToImage(APDFFile, AImageFile, APageIndex, ADPI)
FormFieldCount, FindFormFieldByTitleTsgcPDFDocument.AcroForm.FieldCount, AcroForm.FindField(AName)
SetFormFieldValue, SetFormFieldValueByTitleAcroForm.FillField(AName, AValue), AcroForm.SetCheckBox(AName, AChecked), TsgcPDFEditor.FillFormField
GetFormFieldValueAcroForm.GetFieldValue(AName)
NewFormFieldAcroForm.AddTextField, AddCheckBox, AddComboBox, AddListBox, AddRadioGroup + AddRadioButton, AddButton, AddSignatureField
FlattenFormFieldAcroForm.FlattenFields, TsgcPDFEditor.FlattenForm
EncryptTsgcPDFDocument.SetEncryption(AMethod, AUserPassword, AOwnerPassword) with emAES_256, emAES_128, emRC4_128 or emRC4_40
CapturePageTsgcPDFDocument.AddPageAsForm(ASource, APageIndex): Integer (overloads with a page box, a rectangle or annotations)
DrawCapturedPageTsgcPDFPage.DrawForm(AFormIndex, X, Y, AScaleX, AScaleY, ARotation), DrawFormInRect(AFormIndex, ATarget, AKeepAspect, ARotation), DrawFormMatrix
GetPageBoxTsgcPDFPage.GetPageBox(ABox) (ppbTrimBox, ppbBleedBox, ...), TsgcPDFDocument.GetFormBBox
NewOutlineTsgcPDFEditor.AddBookmark(ATitle, APageIndex), AddBookmarkChild
AddLinkToPageTsgcPDFEditor.AddLinkAnnotation(APageIndex, ALeft, ABottom, ARight, ATop, ADestPage)
AddNoteAnnotationTsgcPDFEditor.AddTextAnnotation(APageIndex, ALeft, ABottom, ARight, ATop, AText)
SignFileTsgcPDFEditor.SignDocument(AOutputFile, ACertSubjectName, AReason, ALocation)
PrintDocumentVCL viewer TsgcPDFViewerControl.Print(AFromPage, AToPage, ATitle) prints without a dialog, PrintDialog(ATitle) shows the printer dialog (page range, copies) and prints. The FireMonkey viewer TsgcPDFViewerFMX has the same two methods on Windows and macOS.
SetMeasurementUnits(0), SetOrigin(0)the default and only coordinate system: points, origin at the bottom left; helpers sgcPDFMMToPoints, sgcPDFRectMM

Also in the Delphi viewers: fit height zoom (zmFitHeight on TsgcPDFViewerControl, fzmFitHeight on TsgcPDFViewerFMX, ZoomFitHeight on TsgcPDFViewer) and view rotation (ViewRotation, RotateLeft, RotateRight), which turns the view and leaves the document unchanged.

The Common Quick PDF Library Jobs in sgcPDF

Every excerpt is copied from the MigrateFromQuickPDF demo, which compiles with Delphi 7 (Win32) and Delphi 13 (Win32 and Win64) and passes its self test. The comments name the Quick PDF Library calls each line replaces.

The uses clause

The Quick PDF Library import unit and the DLL go away. These units cover every job of the demo:

frmMain.pas
uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls, ShellAPI,
  // sgc
  sgcPDF_Types, sgcPDF_Fonts, sgcPDF_Document, sgcPDF_Encryption,
  sgcPDF_Editor, sgcPDF_Renderer_GDI;

Create a document with text, a box and an image

Replaces NewDocument, SetInformation, AddStandardFont, SelectFont, SetTextSize, SetTextColor, DrawText, DrawBox, AddImageFromFile, SelectImage, DrawImage and SaveToFile.

frmMain.pas
oDoc := TsgcPDFDocument.Create;
try
  // SetInformation(1, ...) / SetInformation(2, ...)
  oDoc.Info.Title := 'Created with sgcPDF';
  oDoc.Info.Author := 'Migration sample';
  // NewDocument creates page 1, sgcPDF adds every page explicitly
  oPage := oDoc.AddPage(CS_A4_WIDTH, CS_A4_HEIGHT);
  // AddStandardFont(4) + SelectFont + SetTextSize(28) + DrawText
  oPage.DrawText('Hello from sgcPDF', 72, 760, sfHelveticaBold, 28);
  // SetTextColor(r, g, b) + DrawText
  oPage.DrawTextColor('No DLL, pure Pascal.', 72, 725, sfHelvetica, 14,
    0.1, 0.3, 0.7);
  // SetLineColor + SetLineWidth + DrawBox(x, y, w, h, 0)
  oPage.DrawRectangle(72, 520, 260, 120, 1.5);
  // AddImageFromFile + SelectImage + DrawImage(x, y, w, h)
  vImage := oDoc.AddImage(OutFile('logo.bmp'));
  oPage.DrawImageFromIndex(vImage, 102, 540, 200, 80);
  oDoc.SaveToFile(OutFile('created.pdf'));
finally
  oDoc.Free;
end;

Extract the text of a page

Replaces LoadFromFile, PageCount, SelectPage and GetPageText. Note the 0-based page index.

frmMain.pas
oDoc.LoadFromFile(OutFile('input_a.pdf'));
Log('Extract text: input_a.pdf has ' + IntToStr(oDoc.PageCount) +
  ' pages');
// SelectPage(2) + GetPageText(0): sgcPDF page indexes are 0-based
vText := string(oDoc.ExtractTextW(1));
Log(vText);

Merge and split

Replaces AddToFileList with MergeFileList, and ExtractPageRanges or ExtractFilePages. Range strings stay 1-based.

frmMain.pas
sgcPDFMergeFiles([OutFile('input_a.pdf'), OutFile('input_b.pdf')],
  OutFile('merged.pdf'));
frmMain.pas
// 1-based range string, the same syntax as Quick PDF Library
sgcPDFExtractPages(OutFile('merged.pdf'), OutFile('pages_2-3.pdf'), '2-3');
// one file per page: split
sgcPDFExtractPages(OutFile('merged.pdf'), OutFile('page_4.pdf'), '4');

Watermark and stamp every page

Replaces SelectPage, SetTransparency, SetTextColor and DrawText in a loop over the pages.

frmMain.pas
oEditor.LoadFromFile(OutFile('input_a.pdf'));
vOptions.Text := 'CONFIDENTIAL';
vOptions.Font := sfHelveticaBold;
vOptions.FontSize := 72;
vOptions.Rotation := 45;
vOptions.Opacity := 0.3;
vOptions.R := 0.8;
vOptions.G := 0.1;
vOptions.B := 0.1;
oEditor.AddWatermarkAllPages(vOptions);
// a stamp in the top right corner of every page
for i := 0 to oEditor.Document.PageCount - 1 do
  oEditor.AddTextColor(i, 'APPROVED', 440, 800, sfHelveticaBold, 16,
    0.0, 0.5, 0.0);
oEditor.SaveToFile(OutFile('watermarked.pdf'));

Render a page to a device context

Replaces RenderPageToDC. The renderer takes the loaded document's Parser and the page's PageDict.

frmMain.pas
oDoc.LoadFromFile(OutFile('created.pdf'));
oPage := oDoc.Pages[0];
// 96 DPI: points are 1/72 inch
vScale := 96 / 72;
vW := Round(oPage.Width * vScale);
vH := Round(oPage.Height * vScale);
oBitmap.PixelFormat := pf24bit;
oBitmap.Width := vW;
oBitmap.Height := vH;
oBitmap.Canvas.Brush.Color := clWhite;
oBitmap.Canvas.FillRect(Rect(0, 0, vW, vH));
oRenderer.RenderPage(oBitmap.Canvas.Handle, oDoc.Parser, oPage.PageDict,
  vW, vH);
GdiFlush;
oBitmap.SaveToFile(OutFile('created_page1.bmp'));

Fill a form

Replaces FormFieldCount, FindFormFieldByTitle and SetFormFieldValue.

frmMain.pas
oDoc.LoadFromFile(OutFile('form.pdf'));
Log('Fill form: form.pdf has ' + IntToStr(oDoc.AcroForm.FieldCount) +
  ' fields');
oDoc.AcroForm.FillField('Customer', 'ACME Corporation');
oDoc.AcroForm.FillField('Amount', '1250.00');
oDoc.AcroForm.SetCheckBox('Paid', True);
oDoc.SaveToFile(OutFile('form_filled.pdf'));

Encrypt with AES-256 and open with the password

Replaces Encrypt, and LoadFromFile with a password.

frmMain.pas
oDoc.LoadFromFile(OutFile('input_a.pdf'));
oDoc.SetEncryption(emAES_256, CS_USER_PASSWORD, CS_OWNER_PASSWORD);
oDoc.SaveToFile(OutFile('encrypted.pdf'));
frmMain.pas
oDoc.SetPassword(CS_USER_PASSWORD);
oDoc.LoadFromFile(OutFile('encrypted.pdf'));
vText := string(oDoc.ExtractTextW(0));

2-up imposition

Replaces CapturePage, NewPage, SetPageDimensions and DrawCapturedPage. AddPageAsForm keeps each source page as a form XObject, so the text stays vector and selectable.

frmMain.pas
oSource.LoadFromFile(OutFile('merged.pdf'));
vHalf := CS_A4_HEIGHT / 2;
oSheet := nil;
for i := 0 to oSource.PageCount - 1 do
begin
  // a landscape A4 sheet for every 2 source pages
  if i mod 2 = 0 then
    oSheet := oTarget.AddPage(CS_A4_HEIGHT, CS_A4_WIDTH);
  // CapturePage
  vForm := oTarget.AddPageAsForm(oSource, i);
  // DrawCapturedPage, scaled to fit the left or the right half
  oSheet.DrawFormInRect(vForm, sgcPDFRect((i mod 2) * vHalf, 0,
    (i mod 2) * vHalf + vHalf, CS_A4_WIDTH), True);
end;
oTarget.SaveToFile(OutFile('imposed_2up.pdf'));

PdfiumViewer Classes in sgcPDF

Namespace esegece.sgcPDF, package esegece.sgcPDF.WinForms. Page indexes are 0-based in both libraries.

PdfiumViewer sgcPDF .NET
PdfViewer (UserControl with a toolbar and a bookmarks pane)TsgcPDFViewerControl; build your own toolbar, bookmarks in TsgcPDFOutlineView
PdfRenderer (PdfViewer.Renderer)the same TsgcPDFViewerControl
PdfViewer.Document = PdfDocument.Load(path)TsgcPDFViewerControl.LoadFromFile(path) (the viewer owns the document), LoadFromStream, or Document = vDoc (you dispose it)
PdfDocument.Load(path, password)TsgcPDFDocument.SetPassword before LoadFromFile, then TsgcPDFViewerControl.Document = vDoc
PdfDocument.PageCountTsgcPDFViewerControl.PageCount (property), TsgcPDFDocument.PageCount() (method)
PdfDocument.PageSizesTsgcPDFDocument.GetPage(i).Width and .Height (points)
PdfRenderer.PageTsgcPDFViewerControl.PageIndex, GotoPage, NextPage, PrevPage, FirstPage, LastPage, event OnPageChange
PdfViewerZoomMode.FitWidthZoomMode = TsgcPDFViewerZoomMode.zmFitWidth
PdfViewerZoomMode.FitHeightTsgcPDFViewerZoomMode.zmFitHeight
PdfViewerZoomMode.FitBestTsgcPDFViewerZoomMode.zmFitPage
Zoom (a factor, 1.0 = 100%)TsgcPDFViewerControl.Zoom (a percentage, 100 = 100%, sets zmCustom), ZoomIn, ZoomOut, zmActualSize, ZoomToRect
PdfRenderer.RotateLeft(), RotateRight()TsgcPDFViewerControl.RotateLeft(), RotateRight()
PdfRenderer.RotationTsgcPDFViewerControl.ViewRotation (TsgcPDFViewerRotation: pvr0, pvr90, pvr180, pvr270); PageRotation(i) returns the rotation shown
PdfDocument.Search(text, matchCase, wholeWord) + PdfRenderer.MarkersTsgcPDFViewerControl.FindText(AText, ACaseSensitive, AWholeWord) (highlights and scrolls), FindNext, FindPrevious, SearchResults, GetSearchMatch(i), ClearSearch
PdfDocument.CreatePrintDocument() + PrintDialog or PrintPreviewDialogTsgcPDFViewerControl.CreatePrintDocument() returns a System.Drawing.Printing.PrintDocument for the same PrintDialog and PrintPreviewDialog code. In one call: PrintDialog(ATitle); without a dialog: Print(AFromPage, AToPage, ATitle)
PdfDocument.Render(page, dpiX, dpiY, forPrinting)TsgcPDFViewerControl.RenderPageToBitmap(APageIndex, ref Bitmap, AZoomPercent, ADPI); without a viewer sgcPDF_Export.sgcPDFPageToImage or TsgcPDFExporter.ExportPage
PdfDocument.GetPdfText(page)TsgcPDFDocument.ExtractTextW(APageIndex); with character positions TsgcPDFViewerControl.PageText(i); mouse selection SelectedText, CopyToClipboard
PdfDocument.BookmarksTsgcPDFOutlineView
PdfViewer.LinkClickTsgcPDFViewerControl.OnLinkClick, OpenLinksInBrowser
PdfDocument.Save(path)TsgcPDFDocument.SaveToFile, SaveIncremental(AFileName) (keeps the original bytes and appends the changes)
no equivalent: form fillingTsgcPDFViewerControl.FormFilling = true, OnFieldChange; in code AcroForm.FillField, SetCheckBox, GetFieldValue, FindField
no equivalent: annotationsTsgcPDFDocument.Annotations.AddText, AddFreeText, AddHighlight, AddStamp, AddLine, AddSquare, AddCircle, then AnnotationsChanged(); with the mouse AnnotationTool and AnnotationEditing
no equivalent: create a PDFTsgcPDFDocument.AddPage, TsgcPDFPage.DrawText, DrawRectangle, AcroForm.AddTextField, AddCheckBox, SaveToFile

A PdfiumViewer Form With the sgcPDF Viewer

Every excerpt is copied from the MigrateFromPdfiumViewer demo, which compiles in Release and passes its self test. The comments quote the PdfiumViewer code each block replaces.

One control instead of PdfViewer and PdfRenderer

MainForm.cs
// PdfiumViewer: PdfViewer (UserControl with toolbar) and its PdfRenderer (the page
// surface, PdfViewer.Renderer) -> one control, TsgcPDFViewerControl
private TsgcPDFViewerControl FViewer;
MainForm.cs
FViewer = new TsgcPDFViewerControl();
FViewer.Parent = pnlViewer;
FViewer.Dock = DockStyle.Fill;
// PdfiumViewer: PdfRenderer.DisplayRectangleChanged / polling PdfRenderer.Page -> OnPageChange
FViewer.OnPageChange = DoPageChange;
// PdfiumViewer: none, PdfiumViewer renders form fields but cannot edit them.
// sgcPDF: the user types into text fields and toggles check boxes in the viewer
FViewer.FormFilling = true;
FViewer.OnFieldChange = DoFieldChange;
// PdfiumViewer: none. sgcPDF: AnnotationTool adds notes, highlights, shapes, ink
// and stamps with the mouse; AnnotationEditing moves, resizes and deletes them
FViewer.AnnotationAuthor = "sgcPDF demo";

Open a file

MainForm.cs
// PdfiumViewer: pdfViewer1.Document = PdfDocument.Load(AFileName)
// sgcPDF: the viewer loads and owns the document; to share a document you load
// yourself, assign it: FViewer.Document = vDoc (you dispose it)
FViewer.LoadFromFile(AFileName);
// PdfiumViewer: PdfViewer.ZoomMode = PdfViewerZoomMode.FitWidth
FViewer.ZoomMode = TsgcPDFViewerZoomMode.zmFitWidth;
// PdfiumViewer: PdfDocument.PageCount -> TsgcPDFViewerControl.PageCount
// (or TsgcPDFDocument.PageCount(), a method)
Log("Opened " + Path.GetFileName(AFileName) + ", " + sgcPDF_RTL.IntToStr(FViewer.PageCount) + " pages");

Zoom modes and view rotation

Fit width, fit page and fit height map one to one. The zoom is a percentage instead of a factor.

MainForm.cs
internal void FitWidth()
{
    // PdfiumViewer: PdfViewerZoomMode.FitWidth -> TsgcPDFViewerZoomMode.zmFitWidth
    FViewer.ZoomMode = TsgcPDFViewerZoomMode.zmFitWidth;
}

internal void FitPage()
{
    // PdfiumViewer: PdfViewerZoomMode.FitBest -> TsgcPDFViewerZoomMode.zmFitPage
    FViewer.ZoomMode = TsgcPDFViewerZoomMode.zmFitPage;
}

internal void FitHeight()
{
    // PdfiumViewer: PdfViewerZoomMode.FitHeight -> TsgcPDFViewerZoomMode.zmFitHeight
    FViewer.ZoomMode = TsgcPDFViewerZoomMode.zmFitHeight;
}

internal void RotateLeft()
{
    // PdfiumViewer: PdfRenderer.RotateLeft() -> TsgcPDFViewerControl.RotateLeft()
    // (ViewRotation turns the view only, the document is not changed)
    FViewer.RotateLeft();
}

internal void RotateRight()
{
    // PdfiumViewer: PdfRenderer.RotateRight() -> TsgcPDFViewerControl.RotateRight()
    FViewer.RotateRight();
}

internal void SetZoomPercent(double APercent)
{
    // PdfiumViewer: PdfRenderer.Zoom is a factor (1.0 = 100%);
    // TsgcPDFViewerControl.Zoom is a percentage (100 = 100%) and sets ZoomMode to zmCustom
    FViewer.Zoom = APercent;
}
MainForm.cs
// PdfiumViewer: PdfDocument.Search(text, matchCase, wholeWord) returns PdfMatches
// and the app adds PdfMarker objects to PdfRenderer.Markers to highlight them.
// sgcPDF: FindText highlights every match and scrolls to the first one,
// FindNext / FindPrevious move between them, GetSearchMatch(i) gives page and chars
if (!FViewer.FindText(AText, false, false))
{
    Log("Not found: " + AText);
    return 0;
}
for (int i = 0; i < FViewer.SearchResults; i++)
{
    TsgcPDFViewerSearchMatch vMatch = FViewer.GetSearchMatch(i);
    Log("Match " + sgcPDF_RTL.IntToStr(i + 1) + ": page " + sgcPDF_RTL.IntToStr(vMatch.PageIndex + 1) +
      ", char " + sgcPDF_RTL.IntToStr(vMatch.FirstChar));
}
return FViewer.SearchResults;

The PdfiumViewer printing code keeps its shape: CreatePrintDocument() returns a PrintDocument for a PrintDialog or a PrintPreviewDialog.

MainForm.cs
// PdfiumViewer: using (PrintDocument d = PdfDocument.CreatePrintDocument())
//   { PrintDialog dlg = new PrintDialog(); dlg.Document = d; if (dlg.ShowDialog() == OK) d.Print(); }
// sgcPDF: TsgcPDFViewerControl.CreatePrintDocument() returns the same kind of
// System.Drawing.Printing.PrintDocument, so the PdfiumViewer code stays as it is. It honours
// the page range (all, some pages, current page), copies and collate of its PrinterSettings.
// A shorter way: FViewer.PrintDialog(title) shows the dialog and prints in one call, and
// FViewer.Print(from, to, title) prints without a dialog (0-based pages, -1 = last page).
if (FViewer.PageCount == 0)
    return;
using (PrintDocument vDoc = FViewer.CreatePrintDocument())
using (PrintDialog vDialog = new PrintDialog())
{
    vDoc.DocumentName = "PdfiumViewer migration sample";
    vDialog.Document = vDoc;
    vDialog.AllowSomePages = true;
    vDialog.AllowCurrentPage = true;
    vDialog.UseEXDialog = true;
    vDoc.PrinterSettings.MinimumPage = 1;
    vDoc.PrinterSettings.MaximumPage = FViewer.PageCount;
    vDoc.PrinterSettings.FromPage = 1;
    vDoc.PrinterSettings.ToPage = FViewer.PageCount;
    if (vDialog.ShowDialog(this) == DialogResult.OK)
        vDoc.Print();
}
MainForm.cs
// PdfiumViewer: PrintPreviewDialog with PdfDocument.CreatePrintDocument()
// sgcPDF: the same with TsgcPDFViewerControl.CreatePrintDocument()
if (FViewer.PageCount == 0)
    return;
using (PrintDocument vDoc = FViewer.CreatePrintDocument())
using (PrintPreviewDialog vPreview = new PrintPreviewDialog())
{
    vPreview.Document = vDoc;
    vPreview.Width = 900;
    vPreview.Height = 700;
    vPreview.ShowDialog(this);
}

Render a page to a bitmap

MainForm.cs
// PdfiumViewer: Image img = PdfDocument.Render(page, dpiX, dpiY, forPrinting)
// sgcPDF: RenderPageToBitmap(page, ref bitmap, zoomPercent, dpi); the bitmap passed
// in is disposed and replaced
Bitmap vBitmap = null;
FViewer.RenderPageToBitmap(APageIndex, ref vBitmap, 100, 150);
try
{
    vBitmap.Save(AFileName, ImageFormat.Png);
    Log("Page " + sgcPDF_RTL.IntToStr(APageIndex + 1) + " rendered at 150 dpi: " +
      sgcPDF_RTL.IntToStr(vBitmap.Width) + " x " + sgcPDF_RTL.IntToStr(vBitmap.Height) + " px, " +
      AFileName);
}
finally
{
    vBitmap.Dispose();
}
// without a viewer (server, batch): one call from file to image
sgcPDF_Export.sgcPDFPageToImage(FViewer.FileName, Path.ChangeExtension(AFileName, null) + "_file.png",
  APageIndex, 72);

Page text

MainForm.cs
// PdfiumViewer: PdfDocument.GetPdfText(page) returns the plain text of a page.
// sgcPDF: TsgcPDFDocument.ExtractTextW(page) is the same plain text, and
// TsgcPDFViewerControl.PageText(page) returns a TsgcPDFTextExtractor with the
// characters and their positions (GetTextWithPositions); the user can also select
// text with the mouse and copy it (SelectedText, CopyToClipboard)
string vText = FViewer.Document.ExtractTextW(APageIndex);
Log("Text of page " + sgcPDF_RTL.IntToStr(APageIndex + 1) + ": " + vText.Trim());
TsgcPDFTextExtractor vExtractor = FViewer.PageText(APageIndex);
if (vExtractor != null)
    Log("Characters with positions: " + sgcPDF_RTL.IntToStr(vExtractor.GetCharCount()));
return vText;

Beyond PdfiumViewer: fill a form and add a note

MainForm.cs
// PdfiumViewer: none (no AcroForm API). sgcPDF: AcroForm.FillField / SetCheckBox,
// then an incremental save keeps the original bytes and appends the change
TsgcPDFDocument vDoc = FViewer.Document;
if (vDoc.AcroForm.FindField("CustomerName") == null)
{
    Log("This document has no CustomerName field, open the generated sample");
    return;
}
vDoc.AcroForm.FillField("CustomerName", "ACME Ltd.");
vDoc.AcroForm.SetCheckBox("Approved", true);
FViewer.ClearCache();
FViewer.Invalidate();
vDoc.SaveIncremental(AFileName);
Log("Form filled and saved: " + AFileName);
MainForm.cs
// PdfiumViewer: none (annotations are only rendered). sgcPDF: the document's
// Annotations manager adds notes, free text, highlights, stamps, lines, shapes and
// ink; the viewer shows them after AnnotationsChanged
TsgcPDFDocument vDoc = FViewer.Document;
int vPage = FViewer.PageIndex;
TsgcPDFTextAnnotation vNote = vDoc.Annotations.AddText(vPage, 420, 760, 444, 784,
  "Migrated from PdfiumViewer to sgcPDF.");
vNote.Author = "sgcPDF demo";
vNote.SetColor(1.0, 0.9, 0.2);
vDoc.Annotations.AddHighlight(vPage, 72, 728, 330, 728, 72, 742, 330, 742);
FViewer.AnnotationsChanged();
vDoc.SaveIncremental(AFileName);
Log("Note and highlight added on page " + sgcPDF_RTL.IntToStr(vPage + 1) + ", saved: " + AFileName);

Step by Step

Port one job or one form at a time, and compare the output files before and after.

Delphi: from Quick PDF Library

1

Add the units

Add the sgcPDF Source folder or the installed package, and replace the Quick PDF Library import with sgcPDF_Types, sgcPDF_Fonts and sgcPDF_Document, plus sgcPDF_Editor, sgcPDF_Encryption and sgcPDF_Renderer_GDI where needed.

2

Drop the DLL

Remove the DLL or ActiveX from the deployment and the UnlockKey call from the code.

3

One object per document

Replace the TQuickPDF object with a TsgcPDFDocument per document, or a TsgcPDFEditor for load, edit and save jobs.

4

Pages are objects

Replace SelectPage and the drawing calls with calls on the TsgcPDFPage from AddPage or Pages[i], and subtract 1 from every page number.

5

Map the calls

Use the table above. Standard fonts are an argument of DrawText; TrueType fonts are added once with AddTrueTypeFont and drawn with DrawTextTT.

6

Imposition

Replace CapturePage and DrawCapturedPage with AddPageAsForm and DrawForm or DrawFormInRect.

7

Compare the output

Run the converted job and check the files. The demo's self test is a template: it reopens each output and checks page counts, text and form values.

WinForms: from PdfiumViewer

1

Remove the native parts

Remove the PdfiumViewer package, every PdfiumViewer.Native.* package and any pdfium.dll copied by hand, the x86 and x64 folders included. The project can go back to AnyCPU.

2

Add sgcPDF

Add esegece.sgcPDF.WinForms (or esegece.sgcPDF.WinForms.Community), which brings esegece.sgcPDF, and add using esegece.sgcPDF;.

3

Swap the control

Replace the PdfViewer or PdfRenderer with a TsgcPDFViewerControl (Dock = Fill) and rebuild the toolbar buttons you used as calls on the control.

4

Load the document

Replace PdfDocument.Load and Document = with LoadFromFile, or load a TsgcPDFDocument yourself and assign Document.

5

Map the members

Page becomes PageIndex or GotoPage, the zoom modes map to TsgcPDFViewerZoomMode, the zoom factor is multiplied by 100, Search becomes FindText, Render becomes RenderPageToBitmap.

6

Keep the print code

Call CreatePrintDocument() on the viewer instead of the PdfiumViewer document; the PrintDialog and PrintPreviewDialog code stays. Or use PrintDialog(ATitle).

7

Turn on the new parts

Optionally: FormFilling = true, AnnotationTool and SaveIncremental, which PdfiumViewer could not offer.

What Does Not Map One to One

Read this before you plan the move.

Quick PDF Library

PdfiumViewer

MigrateFromQuickPDF and MigrateFromPdfiumViewer

Both demos generate their own input files, so no external PDF is needed, and both have a self test.

Delphi: where it is

The sgcUI installer puts it in Demos\PDF\Delphi\MigrateFromQuickPDF: sgcPDF_Demo_MigrateFromQuickPDF.dpr, frmMain.pas, frmMain.dfm and a readme.html.

Delphi: how to run it

Open the .dpr in any Delphi from 7 to 13 (VCL, Win32 or Win64), click Generate sample inputs, then any button, or Run all. The output goes to the output folder next to the exe.

Delphi: self test

sgcPDF_Demo_MigrateFromQuickPDF.exe /selftest [folder] runs every job, checks the results and writes selftest.log, which ends in SELFTEST OK.

.NET: where it is

In the sgcUI .NET demos, folder PDF\MigrateFromPdfiumViewer of the sgcUI_Demos.sln solution: sgcPDF_Demo_MigrateFromPdfiumViewer.csproj, Program.cs and MainForm.cs.

.NET: how to run it

dotnet run --project demos\PDF\MigrateFromPdfiumViewer (add -p:SgcCommunity=true for the Community edition), click Generate sample, which writes and opens output\sample.pdf, then any button.

.NET: self test

sgcPDF_Demo_MigrateFromPdfiumViewer.exe /selftest [folder] opens the sample, navigates, zooms, fits the height, rotates, searches, renders, counts the pages of a print preview, extracts text, fills the form, adds a note and reopens the saved files. It writes selftest.log ending in SELFTEST OK.

To be fair to both libraries: an application built on Quick PDF Library or PdfiumViewer keeps working where it is deployed today, and Foxit names its own PDF SDKs as the successors of Quick PDF Library. sgcPDF is the path when you want the PDF code in Pascal or C# source that compiles into your application, with no native PDF library to ship, and one API that also creates, fills, annotates, signs and encrypts the files your viewer shows. For the components and editions see the sgcPDF product page.

Best value: All-AccessEvery eSeGeCe product, Premium Support included, from €1,059/year.
See All-Access pricing

Port Your First PDF Job Today

Download sgcUI with sgcPDF, or add the free Community packages from NuGet, and port your first job or form with the MigrateFromQuickPDF and MigrateFromPdfiumViewer demos next to it.