diff --git a/Example/MainFrm.dfm b/Example/MainFrm.dfm index 026a67d..5026fbd 100644 --- a/Example/MainFrm.dfm +++ b/Example/MainFrm.dfm @@ -3,92 +3,134 @@ object frmMain: TfrmMain Top = 0 Caption = 'PDFium Test' ClientHeight = 647 - ClientWidth = 655 + ClientWidth = 780 Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'Tahoma' Font.Style = [] - OldCreateOrder = False + OldCreateOrder = True OnCreate = FormCreate PixelsPerInch = 96 TextHeight = 13 - object btnPrev: TButton + object ListViewAttachments: TListView Left = 0 - Top = 0 - Width = 75 - Height = 25 - Caption = '<' + Top = 600 + Width = 780 + Height = 47 + Align = alBottom + Columns = <> TabOrder = 0 - OnClick = btnPrevClick + ViewStyle = vsList + Visible = False + OnDblClick = ListViewAttachmentsDblClick end - object btnNext: TButton - Left = 72 + object pnlButtons: TPanel + Left = 0 Top = 0 - Width = 75 + Width = 780 Height = 25 - Caption = '>' + Align = alTop + BevelOuter = bvNone TabOrder = 1 - OnClick = btnNextClick - end - object btnCopy: TButton - Left = 153 - Top = 0 - Width = 75 - Height = 25 - Caption = 'Highlight' - TabOrder = 2 - OnClick = btnCopyClick - end - object btnScale: TButton - Left = 225 - Top = 0 - Width = 75 - Height = 25 - Caption = 'Scale' - TabOrder = 3 - OnClick = btnScaleClick - end - object chkLCDOptimize: TCheckBox - Left = 378 - Top = 4 - Width = 79 - Height = 17 - Caption = 'LCDOptimize' - TabOrder = 4 - OnClick = chkLCDOptimizeClick - end - object chkSmoothScroll: TCheckBox - Left = 458 - Top = 4 - Width = 87 - Height = 17 - Caption = 'SmoothScroll' - TabOrder = 5 - OnClick = chkSmoothScrollClick - end - object edtZoom: TSpinEdit - Left = 544 - Top = 2 - Width = 49 - Height = 22 - MaxValue = 10000 - MinValue = 1 - TabOrder = 6 - Value = 100 - OnChange = edtZoomChange - end - object btnPrint: TButton - Left = 297 - Top = 0 - Width = 75 - Height = 25 - Caption = 'Print' - TabOrder = 7 - OnClick = btnPrintClick + object btnAddAnnotation: TButton + Left = 318 + Top = 0 + Width = 50 + Height = 25 + Caption = 'Annot' + TabOrder = 5 + OnClick = btnAddAnnotationClick + end + object btnHighlight: TButton + Left = 156 + Top = 0 + Width = 56 + Height = 25 + Caption = 'Highlight' + TabOrder = 2 + OnClick = btnHighlightClick + end + object btnNext: TButton + Left = 75 + Top = 0 + Width = 75 + Height = 25 + Caption = '>' + TabOrder = 0 + OnClick = btnNextClick + end + object btnPrev: TButton + Left = 0 + Top = 0 + Width = 75 + Height = 25 + Caption = '<' + TabOrder = 1 + OnClick = btnPrevClick + end + object btnPrint: TButton + Left = 268 + Top = 0 + Width = 50 + Height = 25 + Caption = 'Print' + TabOrder = 4 + OnClick = btnPrintClick + end + object btnScale: TButton + Left = 212 + Top = 0 + Width = 56 + Height = 25 + Caption = 'Scale' + TabOrder = 3 + OnClick = btnScaleClick + end + object chkChangePageOnMouseScrolling: TCheckBox + Left = 599 + Top = 4 + Width = 162 + Height = 17 + Caption = 'ChangePageOnMouseScrolling' + TabOrder = 9 + OnClick = chkChangePageOnMouseScrollingClick + end + object chkLCDOptimize: TCheckBox + Left = 378 + Top = 4 + Width = 79 + Height = 17 + Caption = 'LCDOptimize' + TabOrder = 6 + OnClick = chkLCDOptimizeClick + end + object chkSmoothScroll: TCheckBox + Left = 458 + Top = 4 + Width = 87 + Height = 17 + Caption = 'SmoothScroll' + TabOrder = 7 + OnClick = chkSmoothScrollClick + end + object edtZoom: TSpinEdit + Left = 544 + Top = 2 + Width = 49 + Height = 22 + MaxValue = 10000 + MinValue = 1 + TabOrder = 8 + Value = 100 + OnChange = edtZoomChange + end end object PrintDialog1: TPrintDialog + MinPage = 1 + MaxPage = 10 + Options = [poPageNums] Left = 96 Top = 32 end @@ -99,4 +141,10 @@ object frmMain: TfrmMain Left = 32 Top = 32 end + object SaveDialog1: TSaveDialog + Options = [ofOverwritePrompt, ofHideReadOnly, ofPathMustExist, ofCreatePrompt, ofEnableSizing] + Title = 'Save attachment' + Left = 160 + Top = 32 + end end diff --git a/Example/MainFrm.pas b/Example/MainFrm.pas index 22914c1..74f0386 100644 --- a/Example/MainFrm.pas +++ b/Example/MainFrm.pas @@ -5,13 +5,13 @@ interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, PdfiumCore, Vcl.ExtCtrls, Vcl.StdCtrls, PdfiumCtrl, - Vcl.Samples.Spin; + Vcl.Samples.Spin, Vcl.ComCtrls; type TfrmMain = class(TForm) btnPrev: TButton; btnNext: TButton; - btnCopy: TButton; + btnHighlight: TButton; btnScale: TButton; chkLCDOptimize: TCheckBox; chkSmoothScroll: TCheckBox; @@ -19,19 +19,30 @@ TfrmMain = class(TForm) btnPrint: TButton; PrintDialog1: TPrintDialog; OpenDialog1: TOpenDialog; + ListViewAttachments: TListView; + SaveDialog1: TSaveDialog; + chkChangePageOnMouseScrolling: TCheckBox; + btnAddAnnotation: TButton; + pnlButtons: TPanel; procedure FormCreate(Sender: TObject); procedure btnPrevClick(Sender: TObject); procedure btnNextClick(Sender: TObject); - procedure btnCopyClick(Sender: TObject); + procedure btnHighlightClick(Sender: TObject); procedure btnScaleClick(Sender: TObject); procedure chkLCDOptimizeClick(Sender: TObject); procedure chkSmoothScrollClick(Sender: TObject); procedure edtZoomChange(Sender: TObject); procedure btnPrintClick(Sender: TObject); + procedure ListViewAttachmentsDblClick(Sender: TObject); + procedure chkChangePageOnMouseScrollingClick(Sender: TObject); + procedure btnAddAnnotationClick(Sender: TObject); private { Private-Deklarationen } FCtrl: TPdfControl; procedure WebLinkClick(Sender: TObject; Url: string); + procedure AnnotationLinkClick(Sender: TObject; LinkInfo: TPdfLinkInfo; var Handled: Boolean); + procedure PrintDocument(Sender: TObject); + procedure ListAttachments; public { Public-Deklarationen } end; @@ -49,8 +60,10 @@ implementation procedure TfrmMain.FormCreate(Sender: TObject); begin {$IFDEF CPUX64} + //PDFiumDllDir := ExtractFilePath(ParamStr(0)) + 'x64\V8XFA'; PDFiumDllDir := ExtractFilePath(ParamStr(0)) + 'x64'; {$ELSE} + //PDFiumDllDir := ExtractFilePath(ParamStr(0)) + 'x86\V8XFA'; PDFiumDllDir := ExtractFilePath(ParamStr(0)) + 'x86'; {$ENDIF CPUX64} @@ -59,9 +72,15 @@ procedure TfrmMain.FormCreate(Sender: TObject); FCtrl.Parent := Self; FCtrl.SendToBack; // put the control behind the buttons FCtrl.Color := clGray; + //FCtrl.Color := clWhite; + //FCtrl.PageBorderColor := clBlack; + //FCtrl.PageShadowColor := clDkGray; FCtrl.ScaleMode := smFitWidth; - FCtrl.PageColor := RGB(255, 255, 200); - FCtrl.OnWebLinkClick := WebLinkClick; + //FCtrl.PageColor := RGB(255, 255, 200); + FCtrl.OnWebLinkClick := WebLinkClick; // disabled due to loTreatWebLinkAsUriAnnotationLink + loAutoOpenURI + FCtrl.OnAnnotationLinkClick := AnnotationLinkClick; + FCtrl.LinkOptions := FCtrl.LinkOptions - [loAutoOpenURI] {+ cPdfControlAllAutoLinkOptions}; + FCtrl.OnPrintDocument := PrintDocument; edtZoom.Value := FCtrl.ZoomPercentage; @@ -74,6 +93,32 @@ procedure TfrmMain.FormCreate(Sender: TObject); Application.ShowMainForm := False; Application.Terminate; end; + + ListAttachments; +end; + +procedure TfrmMain.ListAttachments; +var + I: Integer; + Att: TPdfAttachment; + ListItem: TListItem; +begin + if (FCtrl.Document <> nil) and FCtrl.Document.Active then + begin + ListViewAttachments.Visible := FCtrl.Document.Attachments.Count > 0; + + ListViewAttachments.Items.BeginUpdate; + try + for I := 0 to FCtrl.Document.Attachments.Count - 1 do + begin + Att := FCtrl.Document.Attachments[I]; + ListItem := ListViewAttachments.Items.Add; + ListItem.Caption := Format('%s (%d Bytes)', [Att.Name, Att.ContentSize]); + end; + finally + ListViewAttachments.Items.EndUpdate; + end; + end; end; procedure TfrmMain.btnPrevClick(Sender: TObject); @@ -86,9 +131,11 @@ procedure TfrmMain.btnNextClick(Sender: TObject); FCtrl.GotoNextPage; end; -procedure TfrmMain.btnCopyClick(Sender: TObject); +procedure TfrmMain.btnHighlightClick(Sender: TObject); begin - FCtrl.HightlightText('Delphi 2010', False, False); + FCtrl.ClearHighlightText; + FCtrl.AddHightlightText('the', False, True); + FCtrl.AddHightlightText('in', False, True); end; procedure TfrmMain.btnScaleClick(Sender: TObject); @@ -105,6 +152,33 @@ procedure TfrmMain.WebLinkClick(Sender: TObject; Url: string); ShowMessage(Url); end; +procedure TfrmMain.AnnotationLinkClick(Sender: TObject; LinkInfo: TPdfLinkInfo; var Handled: Boolean); +begin + Handled := True; + case LinkInfo.LinkType of + //altURI: + // ShowMessage('URL: ' + LinkAnnotation.LinkUri); + + //altLaunch: + // ShowMessage('Launch: ' + LinkAnnotation.LinkFileName); + + altEmbeddedGoto: + ShowMessage('EmbeddedGoto: ' + LinkInfo.LinkUri); + else + Handled := False; + end; +end; + +procedure TfrmMain.PrintDocument(Sender: TObject); +begin + TPdfDocumentVclPrinter.PrintDocument(FCtrl.Document, ExtractFileName(FCtrl.Document.FileName)); +end; + +procedure TfrmMain.chkChangePageOnMouseScrollingClick(Sender: TObject); +begin + FCtrl.ChangePageOnMouseScrolling := chkChangePageOnMouseScrolling.Checked; +end; + procedure TfrmMain.chkLCDOptimizeClick(Sender: TObject); begin if chkLCDOptimize.Checked then @@ -124,16 +198,53 @@ procedure TfrmMain.edtZoomChange(Sender: TObject); end; procedure TfrmMain.btnPrintClick(Sender: TObject); +{var + PdfPrinter: TPdfDocumentPrinter;} begin + FCtrl.PrintDocument; // calls OnPrintDocument->PrintDocument + //TPdfDocumentVclPrinter.PrintDocument(FCtrl.Document, 'PDF Example Print Job'); + +{ PrintDialog1.MinPage := 1; + PrintDialog1.MaxPage := FCtrl.Document.PageCount; + if PrintDialog1.Execute(Handle) then begin - Printer.BeginDoc; + PdfPrinter := TPdfDocumentVclPrinter.Create; try - FCtrl.CurrentPage.Draw(Printer.Canvas.Handle, 0, 0, Printer.PageWidth, Printer.PageHeight, prNormal, [proAnnotations, proPrinting]); + //PdfPrinter.FitPageToPrintArea := False; + + if PrintDialog1.PrintRange = prAllPages then + PdfPrinter.Print(FCtrl.Document) + else + PdfPrinter.Print(FCtrl.Document, PrintDialog1.FromPage - 1, PrintDialog1.ToPage - 1); // zero-based PageIndex finally - Printer.EndDoc; + PdfPrinter.Free; end; + end;} +end; + +procedure TfrmMain.ListViewAttachmentsDblClick(Sender: TObject); +var + Att: TPdfAttachment; +begin + if ListViewAttachments.Selected <> nil then + begin + Att := FCtrl.Document.Attachments[ListViewAttachments.Selected.Index]; + SaveDialog1.FileName := Att.Name; + if SaveDialog1.Execute(Handle) then + Att.SaveToFile(SaveDialog1.FileName); end; end; +procedure TfrmMain.btnAddAnnotationClick(Sender: TObject); +begin + // Add a new annotation and make it persistent, so that it can be shown and saved to a file. + FCtrl.CurrentPage.Annotations.NewTextAnnotation('My Annotation Text', TPdfRect.New(200, 750, 250, 700)); + FCtrl.CurrentPage.ApplyChanges; +// FCtrl.Document.SaveToFile(ExtractFileDir(ParamStr(0)) + PathDelim + 'Test_annot.pdf'); + + // Invalid the buffered image of the page + FCtrl.InvalidatePage; +end; + end. diff --git a/README.md b/README.md index 67334ed..d066727 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,10 @@ Example of a PDF VCL Control using PDFium ## Requirements pdfium.dll (x86/x64) from the [pdfium-binaries](https://github.com/bblanchon/pdfium-binaries) +Binary release: [chromium/7857](https://github.com/bblanchon/pdfium-binaries/releases/tag/chromium%2F7857) + ## Required pdfium.dll version -chromium/4047 +chromium/7857 / PDFium 150.0.7857.0 ## Features - Multiple PDF load functions: @@ -13,11 +15,15 @@ chromium/4047 - TBytes - TStream - Active buffer (buffer must not be released before the PDF document is closed) - - Active TSteam (stream must not be released before the PDF document is closed) + - Active TStream (stream must not be released before the PDF document is closed) - Callback -- PDF rotation (normal, 90° counter clockwise, 180°, 90° clockwise) +- File Attachments +- Import pages into other PDF documents +- Forms +- PDF rotation (normal, 90° counter clockwise, 180°, 90° clockwise) - Highlighted text (e.g. for search results) -- WebLink click support +- WebLink/URI-Annotation-Link click event +- Optional automatic Goto/RemoteGoto/EmbeddedGoto/Launch/URL Annotation-Link handling - Flicker-free and optimized painting (only changed parts are painted) - Optional buffered page rendering (improves repainting of complex PDF pages) - Optional text selection by the user (mouse and Ctrl+A) diff --git a/Source/PdfiumCore.pas b/Source/PdfiumCore.pas index 548c528..5e0b1d9 100644 --- a/Source/PdfiumCore.pas +++ b/Source/PdfiumCore.pas @@ -1,12 +1,34 @@ -{$A8,B-,E-,F-,G+,H+,I+,J-,K-,M-,N-,P+,Q-,R-,S-,T-,U-,V+,X+,Z1} -{$STRINGCHECKS OFF} - unit PdfiumCore; +{$IFDEF FPC} + {$MODE DelphiUnicode} +{$ENDIF FPC} + +{$IFNDEF FPC} + {$A8,B-,E-,F-,G+,H+,I+,J-,K-,M-,N-,P+,Q-,R-,S-,T-,U-,V+,X+,Z1} + {$STRINGCHECKS OFF} +{$ENDIF ~FPC} + interface +{.$UNDEF MSWINDOWS} + uses - Windows, Types, SysUtils, Classes, Contnrs, PdfiumLib, Graphics; + {$IFDEF MSWINDOWS} + Windows, //WinSpool, + {$ELSE} + {$IFDEF FPC} + LCLType, + {$ENDIF FPC} + ExtCtrls, // for TTimer + {$ENDIF MSWINDOWS} + Types, SysUtils, Classes, Contnrs, + PdfiumLib; + +const + // DIN A4 + PdfDefaultPageWidth = 595; + PdfDefaultPageHeight = 842; type EPdfException = class(Exception); @@ -17,6 +39,10 @@ EPdfArgumentOutOfRange = class(EPdfException); TPdfDocument = class; TPdfPage = class; + TPdfAttachmentList = class; + TPdfAnnotationList = class; + TPdfFormField = class; + TPdfAnnotation = class; TPdfPoint = record X, Y: Double; @@ -34,7 +60,9 @@ TPdfRect = record property Width: Double read GetWidth write SetWidth; property Height: Double read GetHeight write SetHeight; procedure Offset(XOffset, YOffset: Double); + function PtIn(const Pt: TPdfPoint): Boolean; + class function New(Left, Top, Right, Bottom: Double): TPdfRect; static; class function Empty: TPdfRect; static; public case Integer of @@ -43,9 +71,18 @@ TPdfRect = record end; TPdfRectArray = array of TPdfRect; + TPdfFloatArray = array of FS_FLOAT; TPdfDocumentCustomReadProc = function(Param: Pointer; Position: LongWord; Buffer: PByte; Size: LongWord): Boolean; + TPdfNamedActionType = ( + naPrint, + naNextPage, + naPrevPage, + naFirstPage, + naLastPage + ); + TPdfPageRenderOptionType = ( proAnnotations, // Set if annotations are to be rendered. proLCDOptimized, // Set if using text rendering optimized for LCD display. @@ -72,6 +109,7 @@ TPdfRect = record ); TPdfDocumentLoadOption = ( + dloDefault, // load the file by using PDFium's file load mechanism (file stays open) dloMemory, // load the whole file into memory dloMMF, // load the file by using a memory mapped file (file stays open) dloOnDemand // load the file using the custom load function (file stays open) @@ -88,12 +126,20 @@ TPdfRect = record ); TPdfPrintMode = ( - pmEMF = 0, - pmTextMode = 1, - pmPostScript2 = 2, - pmPostScript3 = 3, - pmPostScriptPassThrough2 = 4, - pmPostScriptPassThrough3 = 5 + pmEMF = FPDF_PRINTMODE_EMF, + pmTextMode = FPDF_PRINTMODE_TEXTONLY, + pmPostScript2 = FPDF_PRINTMODE_POSTSCRIPT2, + pmPostScript3 = FPDF_PRINTMODE_POSTSCRIPT3, + pmPostScriptPassThrough2 = FPDF_PRINTMODE_POSTSCRIPT2_PASSTHROUGH, + pmPostScriptPassThrough3 = FPDF_PRINTMODE_POSTSCRIPT3_PASSTHROUGH, + pmEMFImageMasks = FPDF_PRINTMODE_EMF_IMAGE_MASKS, + pmPostScript3Type42 = FPDF_PRINTMODE_POSTSCRIPT3_TYPE42, + pmPostScript3Type42PassThrough = FPDF_PRINTMODE_POSTSCRIPT3_TYPE42_PASSTHROUGH + ); + + TPdfFileIdType = ( + pfiPermanent = 0, + pfiChanging = 1 ); TPdfBitmapFormat = ( @@ -104,19 +150,79 @@ TPdfRect = record ); TPdfFormFieldType = ( - fftUnknown, - fftPushButton, - fftCheckBox, - fftRadioButton, - fftComboBox, - fftListBox, - fftTextField, - fftSignature + fftUnknown = FPDF_FORMFIELD_UNKNOWN, + fftPushButton = FPDF_FORMFIELD_PUSHBUTTON, + fftCheckBox = FPDF_FORMFIELD_CHECKBOX, + fftRadioButton = FPDF_FORMFIELD_RADIOBUTTON, + fftComboBox = FPDF_FORMFIELD_COMBOBOX, + fftListBox = FPDF_FORMFIELD_LISTBOX, + fftTextField = FPDF_FORMFIELD_TEXTFIELD, + fftSignature = FPDF_FORMFIELD_SIGNATURE, + + fftXFA = FPDF_FORMFIELD_XFA, + fftXFACheckBox = FPDF_FORMFIELD_XFA_CHECKBOX, + fftXFAComboBox = FPDF_FORMFIELD_XFA_COMBOBOX, + fftXFAImageField = FPDF_FORMFIELD_XFA_IMAGEFIELD, + fftXFAListBox = FPDF_FORMFIELD_XFA_LISTBOX, + fftXFAPushButton = FPDF_FORMFIELD_XFA_PUSHBUTTON, + fftXFASignature = FPDF_FORMFIELD_XFA_SIGNATURE, + fftXfaTextField = FPDF_FORMFIELD_XFA_TEXTFIELD + ); + + TPdfFormFieldFlagsType = ( + fffReadOnly, + fffRequired, + fffNoExport, + + fffTextMultiLine, + fffTextPassword, + + fffChoiceCombo, + fffChoiceEdit, + fffChoiceMultiSelect + ); + TPdfFormFieldFlags = set of TPdfFormFieldFlagsType; + + TPdfObjectType = ( + otUnknown = FPDF_OBJECT_UNKNOWN, + otBoolean = FPDF_OBJECT_BOOLEAN, + otNumber = FPDF_OBJECT_NUMBER, + otString = FPDF_OBJECT_STRING, + otName = FPDF_OBJECT_NAME, + otArray = FPDF_OBJECT_ARRAY, + otDictinary = FPDF_OBJECT_DICTIONARY, + otStream = FPDF_OBJECT_STREAM, + otNullObj = FPDF_OBJECT_NULLOBJ, + otReference = FPDF_OBJECT_REFERENCE + ); + + TPdfAnnotationLinkType = ( + altUnsupported = PDFACTION_UNSUPPORTED, // Unsupported action type. + altGoto = PDFACTION_GOTO, // Go to a destination within current document. + altRemoteGoto = PDFACTION_REMOTEGOTO, // Go to a destination within another document. + altURI = PDFACTION_URI, // Universal Resource Identifier, including web pages and + // other Internet based resources. + altLaunch = PDFACTION_LAUNCH, // Launch an application or open a file. + altEmbeddedGoto = PDFACTION_EMBEDDEDGOTO // Go to a destination in an embedded file. + ); + + TPdfLinkGotoDestinationViewKind = ( + lgdvUnknown = PDFDEST_VIEW_UNKNOWN_MODE, + lgdvXYZ = PDFDEST_VIEW_XYZ, + lgdvFit = PDFDEST_VIEW_FIT, + lgdvFitH = PDFDEST_VIEW_FITH, + lgdvFitV = PDFDEST_VIEW_FITV, + lgdvFitR = PDFDEST_VIEW_FITR, + lgdvFitB = PDFDEST_VIEW_FITB, + lgdvFitBH = PDFDEST_VIEW_FITBH, + lgdvFitBV = PDFDEST_VIEW_FITBV ); + // Make the TObject.Create constructor private to hide it, so that the TPdfBitmap.Create + // overloads won't allow calling TObject.Create. _TPdfBitmapHideCtor = class(TObject) private - procedure Create; + constructor Create; end; TPdfBitmap = class(_TPdfBitmapHideCtor) @@ -148,6 +254,216 @@ TPdfFormFillHandler = record Document: TPdfDocument; end; + TPdfFormField = class(TObject) + private + FPage: TPdfPage; + FHandle: FPDF_ANNOTATION; + FAnnotation: TPdfAnnotation; + function GetFlags: TPdfFormFieldFlags; + function GetReadOnly: Boolean; + function GetName: string; + function GetAlternateName: string; + function GetFieldType: TPdfFormFieldType; + function GetValue: string; + function GetExportValue: string; + function GetOptionCount: Integer; + function GetOptionLabel(Index: Integer): string; + function GetChecked: Boolean; + function GetControlIndex: Integer; + function GetControlCount: Integer; + + procedure SetValue(const Value: string); + procedure SetChecked(const Value: Boolean); + procedure SetFlags(const Value: TPdfFormFieldFlags); + protected + constructor Create(AAnnotation: TPdfAnnotation); + + function BeginEditFormField: FPDF_ANNOTATION; + procedure EndEditFormField(LastFocusedAnnot: FPDF_ANNOTATION); + public + destructor Destroy; override; + + function IsXFAFormField: Boolean; + + function IsOptionSelected(OptionIndex: Integer): Boolean; + function SelectComboBoxOption(OptionIndex: Integer): Boolean; + function SelectListBoxOption(OptionIndex: Integer; Selected: Boolean = True): Boolean; + + property Flags: TPdfFormFieldFlags read GetFlags write SetFlags; + property ReadOnly: Boolean read GetReadOnly; + property Name: string read GetName; + property AlternateName: string read GetAlternateName; + property FieldType: TPdfFormFieldType read GetFieldType; + property Value: string read GetValue write SetValue; + property ExportValue: string read GetExportValue; + + // ComboBox/ListBox + property OptionCount: Integer read GetOptionCount; + property OptionLabels[Index: Integer]: string read GetOptionLabel; + + // CheckBox/RadioButton + property Checked: Boolean read GetChecked write SetChecked; + property ControlIndex: Integer read GetControlIndex; + property ControlCount: Integer read GetControlCount; + + property Annotation: TPdfAnnotation read FAnnotation; + property Handle: FPDF_ANNOTATION read FHandle; + end; + + TPdfFormFieldList = class(TObject) + private + FItems: TList; + function GetCount: Integer; + function GetItem(Index: Integer): TPdfFormField; + protected + procedure DestroyingItem(Item: TPdfFormField); + public + constructor Create(AAnnotations: TPdfAnnotationList); + destructor Destroy; override; + + property Count: Integer read GetCount; + property Items[Index: Integer]: TPdfFormField read GetItem; default; + end; + + TPdfLinkGotoDestination = class(TObject) + private + FPageIndex: Integer; + FXValid: Boolean; + FYValid: Boolean; + FZoomValid: Boolean; + FX: Single; + FY: Single; + FZoom: Single; + FViewKind: TPdfLinkGotoDestinationViewKind; + FViewParams: TPdfFloatArray; + public + constructor Create(APageIndex: Integer; AXValid, AYValid, AZoomValid: Boolean; AX, AY, AZoom: Single; + AViewKind: TPdfLinkGotoDestinationViewKind; const AViewParams: TPdfFloatArray); + + property PageIndex: Integer read FPageIndex; + + property XValid: Boolean read FXValid; + property YValid: Boolean read FYValid; + property ZoomValid: Boolean read FZoomValid; + + property X: Single read FX; + property Y: Single read FY; + property Zoom: Single read FZoom; + + property ViewKind: TPdfLinkGotoDestinationViewKind read FViewKind; + property ViewParams: TPdfFloatArray read FViewParams; + end; + + TPdfAnnotation = class(TObject) + private + FPage: TPdfPage; + FHandle: FPDF_ANNOTATION; + FFormField: TPdfFormField; + FSubType: FPDF_ANNOTATION_SUBTYPE; + FLinkDest: FPDF_DEST; + FLinkType: TPdfAnnotationLinkType; + + function GetPdfLinkAction: FPDF_ACTION; + function GetFormField: TPdfFormField; + function GetLinkUri: string; + function GetAnnotationRect: TPdfRect; + function GetLinkFileName: string; + protected + constructor Create(APage: TPdfPage; AHandle: FPDF_ANNOTATION); + public + destructor Destroy; override; + + function IsFormField: Boolean; + function IsLink: Boolean; + + function GetLinkGotoDestination(var LinkGotoDestination: TPdfLinkGotoDestination; ARemoteDocument: TPdfDocument = nil): Boolean; + + // IsFormField: + property FormField: TPdfFormField read GetFormField; + // IsLink: + property LinkType: TPdfAnnotationLinkType read FLinkType; + property LinkUri: string read GetLinkUri; + property LinkFileName: string read GetLinkFileName; + + property AnnotationRect: TPdfRect read GetAnnotationRect; + property Handle: FPDF_ANNOTATION read FHandle; + end; + + TPdfAnnotationList = class(TObject) + private + FPage: TPdfPage; + FItems: TObjectList; + FFormFields: TPdfFormFieldList; + function GetCount: Integer; + function GetItem(Index: Integer): TPdfAnnotation; + function GetFormFields: TPdfFormFieldList; + function GetAnnotationsLoaded: Boolean; + protected + procedure DestroyingItem(Item: TPdfAnnotation); + procedure DestroyingFormField(FormField: TPdfFormField); + function FindLink(Link: FPDF_LINK): TPdfAnnotation; + public + constructor Create(APage: TPdfPage); + destructor Destroy; override; + procedure CloseAnnotations; + { NewTextAnnotation creates a new text annotation on the page. After adding one or more + annotations you must call Page.ApplyChanges to show them and make the persist before + saving the file. R is in page coordinates. } + function NewTextAnnotation(const Text: string; const R: TPdfRect): Boolean; {experimental;} + + property AnnotationsLoaded: Boolean read GetAnnotationsLoaded; + + property Count: Integer read GetCount; + property Items[Index: Integer]: TPdfAnnotation read GetItem; default; + + { A list of all form field annotations } + property FormFields: TPdfFormFieldList read GetFormFields; + end; + + TPdfLinkInfo = class(TObject) + private + FLinkAnnotation: TPdfAnnotation; + FWebLinkUrl: string; + function GetLinkFileName: string; + function GetLinkType: TPdfAnnotationLinkType; + function GetLinkUri: string; + public + constructor Create(ALinkAnnotation: TPdfAnnotation; const AWebLinkUrl: string); + function GetLinkGotoDestination(var LinkGotoDestination: TPdfLinkGotoDestination; ARemoteDocument: TPdfDocument = nil): Boolean; + + function IsAnnontation: Boolean; + function IsWebLink: Boolean; + + property LinkType: TPdfAnnotationLinkType read GetLinkType; + property LinkUri: string read GetLinkUri; + property LinkFileName: string read GetLinkFileName; + + property LinkAnnotation: TPdfAnnotation read FLinkAnnotation; + end; + + { TPdfPageWebLinksInfo caches all the WebLinks for one page. This makes the IsWebLinkAt() methods + much faster than always calling into the PDFium library. The URLs are not cached. } + TPdfPageWebLinksInfo = class(TObject) + private + FPage: TPdfPage; + FWebLinksRects: array of TPdfRectArray; + procedure GetPageWebLinks; + function GetWebLinkIndex(X, Y: Double): Integer; + + function GetCount: Integer; + function GetRect(Index: Integer): TPdfRectArray; + function GetURL(Index: Integer): string; + public + constructor Create(APage: TPdfPage); + + function IsWebLinkAt(X, Y: Double): Boolean; overload; + function IsWebLinkAt(X, Y: Double; var Url: string): Boolean; overload; + + property Count: Integer read GetCount; + property URLs[Index: Integer]: string read GetURL; + property Rects[Index: Integer]: TPdfRectArray read GetRect; + end; + TPdfPage = class(TObject) private FDocument: TPdfDocument; @@ -156,9 +472,10 @@ TPdfPage = class(TObject) FHeight: Single; FTransparency: Boolean; FRotation: TPdfPageRotation; + FAnnotations: TPdfAnnotationList; FTextHandle: FPDF_TEXTPAGE; FSearchHandle: FPDF_SCHHANDLE; - FLinkHandle: FPDF_PAGELINK; + FPageLinkHandle: FPDF_PAGELINK; constructor Create(ADocument: TPdfDocument; APage: FPDF_PAGE); procedure UpdateMetrics; procedure Open; @@ -168,18 +485,31 @@ TPdfPage = class(TObject) class function GetDrawFlags(const Options: TPdfPageRenderOptions): Integer; static; procedure AfterOpen; function IsValidForm: Boolean; - function GetMouseModifier(const Shift: TShiftState): Integer; - function GetKeyModifier(KeyData: LPARAM): Integer; + function ShiftStateToModifier(const Shift: TShiftState): Integer; function GetHandle: FPDF_PAGE; + function GetTextHandle: FPDF_TEXTPAGE; + function GetFormFields: TPdfFormFieldList; + protected + function GetPdfActionFilePath(Action: FPDF_ACTION): string; + function GetPdfActionUriPath(Action: FPDF_ACTION): string; public destructor Destroy; override; procedure Close; function IsLoaded: Boolean; + {$IFDEF MSWINDOWS} + // Draw the PDF page and the form into the device context. procedure Draw(DC: HDC; X, Y, Width, Height: Integer; Rotate: TPdfPageRotation = prNormal; - const Options: TPdfPageRenderOptions = []); + const Options: TPdfPageRenderOptions = []; PageBackground: TColorRef = $FFFFFF); overload; + {$ENDIF MSWINDOWS} + // Draw the PDF page and the form into the bitmap. + procedure Draw(APdfBitmap: TPdfBitmap; X, Y, Width, Height: Integer; Rotate: TPdfPageRotation = prNormal; + const Options: TPdfPageRenderOptions = []; PageBackground: TColorRef = $FFFFFF); overload; + + // Draw the PDF page without the form field values into the bitmap. procedure DrawToPdfBitmap(APdfBitmap: TPdfBitmap; X, Y, Width, Height: Integer; Rotate: TPdfPageRotation = prNormal; const Options: TPdfPageRenderOptions = []); + // Draw the PDF form field values into the bitmap. procedure DrawFormToPdfBitmap(APdfBitmap: TPdfBitmap; X, Y, Width, Height: Integer; Rotate: TPdfPageRotation = prNormal; const Options: TPdfPageRenderOptions = []); @@ -189,17 +519,28 @@ TPdfPage = class(TObject) function PageToDevice(X, Y, Width, Height: Integer; const R: TPdfRect; Rotate: TPdfPageRotation = prNormal): TRect; overload; procedure ApplyChanges; + procedure Flatten(AFlatPrint: Boolean); function FormEventFocus(const Shift: TShiftState; PageX, PageY: Double): Boolean; + function FormEventMouseWheel(const Shift: TShiftState; WheelDelta: Integer; PageX, PageY: Double): Boolean; function FormEventMouseMove(const Shift: TShiftState; PageX, PageY: Double): Boolean; function FormEventLButtonDown(const Shift: TShiftState; PageX, PageY: Double): Boolean; function FormEventLButtonUp(const Shift: TShiftState; PageX, PageY: Double): Boolean; function FormEventRButtonDown(const Shift: TShiftState; PageX, PageY: Double): Boolean; function FormEventRButtonUp(const Shift: TShiftState; PageX, PageY: Double): Boolean; - function FormEventKeyDown(KeyCode: Word; KeyData: LPARAM): Boolean; - function FormEventKeyUp(KeyCode: Word; KeyData: LPARAM): Boolean; - function FormEventKeyPress(Key: Word; KeyData: LPARAM): Boolean; - procedure FormEventKillFocus; + function FormEventKeyDown(KeyCode: Word; const Shift: TShiftState): Boolean; + function FormEventKeyUp(KeyCode: Word; const Shift: TShiftState): Boolean; + function FormEventKeyPress(Key: Word; const Shift: TShiftState): Boolean; + function FormEventKillFocus: Boolean; + function FormGetFocusedText: string; + function FormGetSelectedText: string; + function FormReplaceSelection(const ANewText: string): Boolean; + function FormReplaceAndKeepSelection(const ANewText: string): Boolean; + function FormSelectAllText: Boolean; + function FormCanUndo: Boolean; + function FormCanRedo: Boolean; + function FormUndo: Boolean; + function FormRedo: Boolean; function BeginFind(const SearchString: string; MatchCase, MatchWholeWord: Boolean; FromEnd: Boolean): Boolean; function FindNext(var CharIndex, Count: Integer): Boolean; @@ -220,21 +561,103 @@ TPdfPage = class(TObject) function HasFormFieldAtPoint(X, Y: Double): TPdfFormFieldType; + { IsUriLinkAtPoint returns true if a Link annotation is at the specified coordinates. + X, Y are in page coordinates. } + function IsUriLinkAtPoint(X, Y: Double): Boolean; overload; + { IsUriLinkAtPoint returns true if a Link annotation is at the specified coordinates. If one is found + the Uri parameter is set to the link's URI. + X, Y are in page coordinates. } + function IsUriLinkAtPoint(X, Y: Double; var Uri: string): Boolean; overload; + { GetLinkAtPoint returns the link annotation for the specified coordinates. If no link annotation + was found it return nil. It not only returns Uri but also Goto, RemoteGoto, Launch, EmbeddedGoto + link annotations. } + function GetLinkAtPoint(X, Y: Double): TPdfAnnotation; + + { WebLinks are URLs that are parsed from the PDFs text content. No link annotation exists + for them, so the IsUriLinkAtPoint and GetLinkAtPoint methods don't work for them. } function GetWebLinkCount: Integer; function GetWebLinkURL(LinkIndex: Integer): string; function GetWebLinkRectCount(LinkIndex: Integer): Integer; function GetWebLinkRect(LinkIndex, RectIndex: Integer): TPdfRect; + function IsWebLinkAtPoint(X, Y: Double): Boolean; overload; + function IsWebLinkAtPoint(X, Y: Double; var URL: string): Boolean; overload; property Handle: FPDF_PAGE read GetHandle; + property TextHandle: FPDF_TEXTPAGE read GetTextHandle; + property Width: Single read FWidth; property Height: Single read FHeight; property Transparency: Boolean read FTransparency; property Rotation: TPdfPageRotation read FRotation write SetRotation; + + property Annotations: TPdfAnnotationList read FAnnotations; + property FormFields: TPdfFormFieldList read GetFormFields; end; TPdfFormInvalidateEvent = procedure(Document: TPdfDocument; Page: TPdfPage; const PageRect: TPdfRect) of object; TPdfFormOutputSelectedRectEvent = procedure(Document: TPdfDocument; Page: TPdfPage; const PageRect: TPdfRect) of object; - TPdfFormGetCurrentPage = procedure(Document: TPdfDocument; var CurrentPage: TPdfPage) of object; + TPdfFormGetCurrentPageEvent = procedure(Document: TPdfDocument; var CurrentPage: TPdfPage) of object; + TPdfFormFieldFocusEvent = procedure(Document: TPdfDocument; Value: PWideChar; ValueLen: Integer; FieldFocused: Boolean) of object; + TPdfExecuteNamedActionEvent = procedure(Document: TPdfDocument; NamedAction: TPdfNamedActionType) of object; + + TPdfAttachment = record + private + FDocument: TPdfDocument; + FHandle: FPDF_ATTACHMENT; + procedure CheckValid; + + function GetName: string; + function GetKeyValue(const Key: string): string; + procedure SetKeyValue(const Key, Value: string); + function GetContentSize: Integer; + public + // SetContent/LoadFromXxx clears the Values[] dictionary. + procedure SetContent(const ABytes: TBytes); overload; + procedure SetContent(const ABytes: TBytes; Index: NativeInt; Count: Integer); overload; + procedure SetContent(ABytes: PByte; Count: Integer); overload; + procedure SetContent(const Value: RawByteString); overload; + procedure SetContent(const Value: string; Encoding: TEncoding = nil); overload; // Default-encoding is UTF-8 + procedure LoadFromStream(Stream: TStream); + procedure LoadFromFile(const FileName: string); + + procedure GetContent(var ABytes: TBytes); overload; + procedure GetContent(Buffer: PByte); overload; // use ContentSize to allocate enough memory + procedure GetContent(var Value: RawByteString); overload; + procedure GetContent(var Value: string; Encoding: TEncoding = nil); overload; + function GetContentAsBytes: TBytes; + function GetContentAsRawByteString: RawByteString; + function GetContentAsString(Encoding: TEncoding = nil): string; // Default-encoding is UTF-8 + + procedure SaveToStream(Stream: TStream); + procedure SaveToFile(const FileName: string); + + function HasContent: Boolean; + + function HasKey(const Key: string): Boolean; + function GetValueType(const Key: string): TPdfObjectType; + + property Name: string read GetName; + property Values[const Key: string]: string read GetKeyValue write SetKeyValue; + property ContentSize: Integer read GetContentSize; + + property Handle: FPDF_ATTACHMENT read FHandle; + end; + + TPdfAttachmentList = class(TObject) + private + FDocument: TPdfDocument; + function GetCount: Integer; + function GetItem(Index: Integer): TPdfAttachment; + public + constructor Create(ADocument: TPdfDocument); + + function Add(const Name: string): TPdfAttachment; + procedure Delete(Index: Integer); + function IndexOf(const Name: string): Integer; + + property Count: Integer read GetCount; + property Items[Index: Integer]: TPdfAttachment read GetItem; default; + end; TPdfDocument = class(TObject) private type @@ -247,9 +670,14 @@ TCustomLoadDataRec = record private FDocument: FPDF_DOCUMENT; FPages: TObjectList; + FAttachments: TPdfAttachmentList; FFileName: string; + {$IFDEF MSWINDOWS} FFileHandle: THandle; FFileMapping: THandle; + {$ELSE} + FFileStream: TFileStream; + {$ENDIF MSWINDOWS} FBuffer: PByte; FBytes: TBytes; FClosing: Boolean; @@ -257,17 +685,25 @@ TCustomLoadDataRec = record FCustomLoadData: PCustomLoadDataRec; FForm: FPDF_FORMHANDLE; + FJSPlatform: IPDF_JsPlatform; FFormFillHandler: TPdfFormFillHandler; - FFormFieldHighlightColor: TColor; + FFormFieldHighlightColor: TColorRef; FFormFieldHighlightAlpha: Integer; FPrintHidesFormFieldHighlight: Boolean; FFormModified: Boolean; + FOnFormInvalidate: TPdfFormInvalidateEvent; FOnFormOutputSelectedRect: TPdfFormOutputSelectedRectEvent; - FOnFormGetCurrentPage: TPdfFormGetCurrentPage; - - procedure InternLoadFromMem(Buffer: PByte; Size: Integer; const APassword: AnsiString); - procedure InternLoadFromCustom(ReadFunc: TPdfDocumentCustomReadProc; ASize: LongWord; AParam: Pointer; const APassword: AnsiString); + FOnFormGetCurrentPage: TPdfFormGetCurrentPageEvent; + FOnFormFieldFocus: TPdfFormFieldFocusEvent; + FOnExecuteNamedAction: TPdfExecuteNamedActionEvent; + + procedure InternLoadFromFile(const FileName: string; const Password: UTF8String); + procedure InternLoadFromMem(Buffer: PByte; Size: NativeInt; const Password: UTF8String); + procedure InternLoadFromCustom(ReadFunc: TPdfDocumentCustomReadProc; Size: LongWord; + Param: Pointer; const Password: UTF8String); + function InternImportPages(Source: TPdfDocument; PageIndices: PInteger; PageIndicesCount: Integer; + const Range: AnsiString; Index: Integer; ImportByRange: Boolean): Boolean; function GetPage(Index: Integer): TPdfPage; function GetPageCount: Integer; procedure ExtractPage(APage: TPdfPage); @@ -283,20 +719,20 @@ TCustomLoadDataRec = record function GetNumCopies: Integer; procedure DocumentLoaded; procedure SetFormFieldHighlightAlpha(Value: Integer); - procedure SetFormFieldHighlightColor(const Value: TColor); + procedure SetFormFieldHighlightColor(const Value: TColorRef); function FindPage(Page: FPDF_PAGE): TPdfPage; procedure UpdateFormFieldHighlight; public constructor Create; destructor Destroy; override; - procedure LoadFromCustom(ReadFunc: TPdfDocumentCustomReadProc; ASize: LongWord; AParam: Pointer; const APassword: AnsiString = ''); - procedure LoadFromActiveStream(Stream: TStream; const APassword: AnsiString = ''); // Stream must not be released until the document is closed - procedure LoadFromActiveBuffer(Buffer: Pointer; Size: Integer; const APassword: AnsiString = ''); // Buffer must not be released until the document is closed - procedure LoadFromBytes(const ABytes: TBytes; const APassword: AnsiString = ''); overload; - procedure LoadFromBytes(const ABytes: TBytes; AIndex: Integer; ACount: Integer; const APassword: AnsiString = ''); overload; - procedure LoadFromStream(AStream: TStream; const APassword: AnsiString = ''); - procedure LoadFromFile(const AFileName: string; const APassword: AnsiString = ''; ALoadOptions: TPdfDocumentLoadOption = dloMMF); + procedure LoadFromCustom(ReadFunc: TPdfDocumentCustomReadProc; Size: LongWord; Param: Pointer; const Password: UTF8String = ''); + procedure LoadFromActiveStream(Stream: TStream; const Password: UTF8String = ''); // Stream must not be released until the document is closed + procedure LoadFromActiveBuffer(Buffer: Pointer; Size: NativeInt; const Password: UTF8String = ''); // Buffer must not be released until the document is closed + procedure LoadFromBytes(const Bytes: TBytes; const Password: UTF8String = ''); overload; + procedure LoadFromBytes(const Bytes: TBytes; Index: NativeInt; Count: NativeInt; const Password: UTF8String = ''); overload; + procedure LoadFromStream(Stream: TStream; const Password: UTF8String = ''); + procedure LoadFromFile(const FileName: string; const Password: UTF8String = ''; LoadOption: TPdfDocumentLoadOption = dloDefault); procedure Close; procedure SaveToFile(const AFileName: string; Option: TPdfDocumentSaveOption = dsoRemoveSecurity; FileVersion: Integer = -1); @@ -304,13 +740,21 @@ TCustomLoadDataRec = record procedure SaveToBytes(var Bytes: TBytes; Option: TPdfDocumentSaveOption = dsoRemoveSecurity; FileVersion: Integer = -1); function NewDocument: Boolean; + class function CreateNPagesOnOnePageDocument(Source: TPdfDocument; NewPageWidth, NewPageHeight: Double; NumPagesXAxis, NumPagesYAxis: Integer): TPdfDocument; overload; + class function CreateNPagesOnOnePageDocument(Source: TPdfDocument; NumPagesXAxis, NumPagesYAxis: Integer): TPdfDocument; overload; + function ImportAllPages(Source: TPdfDocument; Index: Integer = -1): Boolean; function ImportPages(Source: TPdfDocument; const Range: string = ''; Index: Integer = -1): Boolean; + function ImportPageRange(Source: TPdfDocument; PageIndex: Integer; Count: Integer = -1; Index: Integer = -1): Boolean; + function ImportPagesByIndex(Source: TPdfDocument; const PageIndices: array of Integer; Index: Integer = -1): Boolean; procedure DeletePage(Index: Integer); - function NewPage(Width, Height: Double; Index: Integer = -1): TPdfPage; + function NewPage(Width, Height: Double; Index: Integer = -1): TPdfPage; overload; + function NewPage(Index: Integer = -1): TPdfPage; overload; function ApplyViewerPreferences(Source: TPdfDocument): Boolean; function IsPageLoaded(PageIndex: Integer): Boolean; + function GetFileIdentifier(IdType: TPdfFileIdType): string; function GetMetaText(const TagName: string): string; + class function SetPrintMode(PrintMode: TPdfPrintMode): Boolean; static; property FileName: string read FFileName; @@ -318,6 +762,8 @@ TCustomLoadDataRec = record property Pages[Index: Integer]: TPdfPage read GetPage; property PageSizes[Index: Integer]: TPdfPoint read GetPageSize; + property Attachments: TPdfAttachmentList read FAttachments; + property Active: Boolean read GetActive; property PrintScaling: Boolean read GetPrintScaling; property NumCopies: Integer read GetNumCopies; @@ -332,56 +778,144 @@ TCustomLoadDataRec = record property Handle: FPDF_DOCUMENT read FDocument; property FormHandle: FPDF_FORMHANDLE read FForm; - property FormFieldHighlightColor: TColor read FFormFieldHighlightColor write SetFormFieldHighlightColor default $FFE4DD; + property FormFieldHighlightColor: TColorRef read FFormFieldHighlightColor write SetFormFieldHighlightColor default $FFE4DD; property FormFieldHighlightAlpha: Integer read FFormFieldHighlightAlpha write SetFormFieldHighlightAlpha default 100; property PrintHidesFormFieldHighlight: Boolean read FPrintHidesFormFieldHighlight write FPrintHidesFormFieldHighlight default True; property FormModified: Boolean read FFormModified write FFormModified; property OnFormInvalidate: TPdfFormInvalidateEvent read FOnFormInvalidate write FOnFormInvalidate; property OnFormOutputSelectedRect: TPdfFormOutputSelectedRectEvent read FOnFormOutputSelectedRect write FOnFormOutputSelectedRect; - property OnFormGetCurrentPage: TPdfFormGetCurrentPage read FOnFormGetCurrentPage write FOnFormGetCurrentPage; + property OnFormGetCurrentPage: TPdfFormGetCurrentPageEvent read FOnFormGetCurrentPage write FOnFormGetCurrentPage; + property OnFormFieldFocus: TPdfFormFieldFocusEvent read FOnFormFieldFocus write FOnFormFieldFocus; + property OnExecuteNamedAction: TPdfExecuteNamedActionEvent read FOnExecuteNamedAction write FOnExecuteNamedAction; end; + {$IFDEF MSWINDOWS} + TPdfDocumentPrinterStatusEvent = procedure(Sender: TObject; CurrentPageNum, PageCount: Integer) of object; + + TPdfDocumentPrinter = class(TObject) + private + FBeginPrintCounter: Integer; + + FPrinterDC: HDC; + FPrintPortraitOrientation: Boolean; + FPaperSize: TSize; + FPrintArea: TSize; + FMargins: TPoint; + + FFitPageToPrintArea: Boolean; + FOnPrintStatus: TPdfDocumentPrinterStatusEvent; + + function IsPortraitOrientation(AWidth, AHeight: Integer): Boolean; + procedure GetPrinterBounds; + protected + function PrinterStartDoc(const AJobTitle: string): Boolean; virtual; abstract; + procedure PrinterEndDoc; virtual; abstract; + procedure PrinterStartPage; virtual; abstract; + procedure PrinterEndPage; virtual; abstract; + function GetPrinterDC: HDC; virtual; abstract; + + procedure InternPrintPage(APage: TPdfPage; X, Y, Width, Height: Double); + public + constructor Create; + + { BeginPrint must be called before printing multiple documents. + Returns false if the printer can't print. (e.g. The user aborted the PDF Printer's FileDialog) } + function BeginPrint(const AJobTitle: string = ''): Boolean; + { EndPrint must be called after printing multiple documents were printed. } + procedure EndPrint; + + { Prints a range of PDF document pages (0..PageCount-1) } + function Print(ADocument: TPdfDocument; AFromPageIndex, AToPageIndex: Integer): Boolean; overload; + { Prints all pages of the PDF document. } + function Print(ADocument: TPdfDocument): Boolean; overload; + + + { If FitPageToPrintArea is true the page fill be scaled to fit into the printable area. } + property FitPageToPrintArea: Boolean read FFitPageToPrintArea write FFitPageToPrintArea default True; + + { OnPrintStatus is triggered after every printed page } + property OnPrintStatus: TPdfDocumentPrinterStatusEvent read FOnPrintStatus write FOnPrintStatus; + end; + {$ENDIF MSWINDOWS} + function SetThreadPdfUnsupportedFeatureHandler(const Handler: TPdfUnsupportedFeatureHandler): TPdfUnsupportedFeatureHandler; var PDFiumDllDir: string = ''; PDFiumDllFileName: string = ''; // use this instead of PDFiumDllDir if you want to change the DLLs file name - {$IF declared(FPDF_InitEmbeddedLibraries)} - PDFiumResDir: string = ''; - {$IFEND} implementation resourcestring RsUnsupportedFeature = 'Function %s not supported'; - RsArgumentsOutOfRange = 'Functions argument "%s" out of range'; + RsArgumentsOutOfRange = 'Function argument "%s" (%d) out of range'; RsDocumentNotActive = 'PDF document is not open'; + {$IFNDEF CPUX64} RsFileTooLarge = 'PDF file "%s" is too large'; - - RsPdfErrorSuccess = 'No error'; - RsPdfErrorUnknown = 'Unknown error'; - RsPdfErrorFile = 'File not found or can''t be opened'; - RsPdfErrorFormat = 'File is not a PDF document or is corrupted'; - RsPdfErrorPassword = 'Password required oder invalid password'; - RsPdfErrorSecurity = 'Security schema is not support'; - RsPdfErrorPage = 'Page does not exist or data error'; + {$ENDIF ~CPUX64} + + RsPdfCannotDeleteAttachmnent = 'Cannot delete the PDF attachment %d'; + RsPdfCannotAddAttachmnent = 'Cannot add the PDF attachment "%s"'; + RsPdfCannotSetAttachmentContent = 'Cannot set the PDF attachment content'; + RsPdfAttachmentContentNotSet = 'Content must be set before accessing string PDF attachmemt values'; + + RsPdfAnnotationNotAFormFieldError = 'The annotation is not a form field'; + RsPdfAnnotationLinkRemoteGotoRequiresRemoteDocument = 'A remote goto annotation link requires a remote document'; + + RsPdfErrorSuccess = 'No error'; + RsPdfErrorUnknown = 'Unknown error'; + RsPdfErrorFile = 'File not found or can''t be opened'; + RsPdfErrorFormat = 'File is not a PDF document or is corrupted'; + RsPdfErrorPassword = 'Password required oder invalid password'; + RsPdfErrorSecurity = 'Security schema is not support'; + RsPdfErrorPage = 'Page does not exist or data error'; + RsPdfErrorXFALoad = 'Load XFA error'; + RsPdfErrorXFALayout = 'Layout XFA error'; threadvar ThreadPdfUnsupportedFeatureHandler: TPdfUnsupportedFeatureHandler; UnsupportedFeatureCurrentDocument: TPdfDocument; +type + { We don't want to use a TBytes temporary array if we can convert directly into the destination + buffer. } + TEncodingAccess = class(TEncoding) + public + function GetMemCharCount(Bytes: PByte; ByteCount: Integer): Integer; + function GetMemChars(Bytes: PByte; ByteCount: Integer; Chars: PWideChar; CharCount: Integer): Integer; + end; + +function TEncodingAccess.GetMemCharCount(Bytes: PByte; ByteCount: Integer): Integer; +begin + Result := GetCharCount(Bytes, ByteCount); +end; + +function TEncodingAccess.GetMemChars(Bytes: PByte; ByteCount: Integer; Chars: PWideChar; CharCount: Integer): Integer; +begin + Result := GetChars(Bytes, ByteCount, Chars, CharCount); +end; + function SetThreadPdfUnsupportedFeatureHandler(const Handler: TPdfUnsupportedFeatureHandler): TPdfUnsupportedFeatureHandler; begin Result := ThreadPdfUnsupportedFeatureHandler; ThreadPdfUnsupportedFeatureHandler := Handler; end; -{$IF not declared(GetFileSizeEx)} -function GetFileSizeEx(hFile: THandle; var lpFileSize: Int64): Boolean; stdcall; +{$IF defined(MSWINDOWS) and not declared(GetFileSizeEx)} +function GetFileSizeEx(hFile: THandle; var lpFileSize: Int64): BOOL; stdcall; external kernel32 name 'GetFileSizeEx'; {$IFEND} +procedure SwapInts(var X, Y: Integer); +var + Tmp: Integer; +begin + Tmp := X; + X := Y; + Y := Tmp; +end; + function GetUnsupportedFeatureName(nType: Integer): string; begin case nType of @@ -460,9 +994,9 @@ procedure InitLib; if Initialized = 0 then begin if PDFiumDllFileName <> '' then - InitPDFiumEx(PDFiumDllFileName {$IF declared(FPDF_InitEmbeddedLibraries)}, PDFiumResDir{$ENDIF}) + InitPDFiumEx(PDFiumDllFileName) else - InitPDFium(PDFiumDllDir {$IF declared(FPDF_InitEmbeddedLibraries)}, PDFiumResDir{$ENDIF}); + InitPDFium(PDFiumDllDir); FSDK_SetUnSpObjProcessHandler(@UnsupportInfo); Initialized := 1; end; @@ -474,7 +1008,7 @@ procedure InitLib; procedure RaiseLastPdfError; begin - case FPDF_GetLastError of + case FPDF_GetLastError() of FPDF_ERR_SUCCESS: raise EPdfException.CreateRes(@RsPdfErrorSuccess); FPDF_ERR_FILE: @@ -487,6 +1021,12 @@ procedure RaiseLastPdfError; raise EPdfException.CreateRes(@RsPdfErrorSecurity); FPDF_ERR_PAGE: raise EPdfException.CreateRes(@RsPdfErrorPage); + {$IF declared(FPDF_ERR_XFALOAD)} + FPDF_ERR_XFALOAD: + raise EPdfException.CreateRes(@RsPdfErrorXFALoad); + FPDF_ERR_XFALAYOUT: + raise EPdfException.CreateRes(@RsPdfErrorXFALayout); + {$IFEND} else raise EPdfException.CreateRes(@RsPdfErrorUnknown); end; @@ -542,11 +1082,15 @@ procedure FFI_OutputSelectedRect(pThis: PFPDF_FORMFILLINFO; page: FPDF_PAGE; lef end; end; -var - FFITimers: array of record +{$IFDEF MSWINDOWS} +type + TFFITimer = record Id: UINT; Proc: TFPDFTimerCallback; end; + +var + FFITimers: array of TFFITimer; FFITimersCritSect: TRTLCriticalSection; procedure FormTimerProc(hwnd: HWND; uMsg: UINT; timerId: UINT; dwTime: DWORD); stdcall; @@ -625,14 +1169,100 @@ procedure FFI_KillTimer(pThis: PFPDF_FORMFILLINFO; nTimerID: Integer); cdecl; I := Length(FFITimers) - 1; while (I >= 0) and (FFITimers[I].Id = 0) do Dec(I); - SetLength(FFITimers, I + 1); + if Length(FFITimers) <> I + 1 then + SetLength(FFITimers, I + 1); + finally + LeaveCriticalSection(FFITimersCritSect); + end; + end; +end; +{$ELSE} +type + TFFITimer = class(TTimer) + public + FId: Integer; + FTimerFunc: TFPDFTimerCallback; + procedure DoTimerEvent(Sender: TObject); + end; + +var + FFITimers: array of TFFITimer; + FFITimersCritSect: TRTLCriticalSection; + +{ TFFITimer } + +procedure TFFITimer.DoTimerEvent(Sender: TObject); +begin + FTimerFunc(FId); +end; + +function FFI_SetTimer(pThis: PFPDF_FORMFILLINFO; uElapse: Integer; lpTimerFunc: TFPDFTimerCallback): Integer; cdecl; +var + I: Integer; + Id: Integer; + Timer: TFFITimer; +begin + // Find highest Id + EnterCriticalSection(FFITimersCritSect); + try + Id := 0; + for I := 0 to Length(FFITimers) - 1 do + if (FFITimers[I] <> nil) and (FFITimers[I].FId > Id) then + Id := FFITimers[I].FId; + Inc(Id); + + Timer := TFFITimer.Create(nil); + Timer.FId := Id; + Timer.FTimerFunc:= lpTimerFunc; + Timer.OnTimer := Timer.DoTimerEvent; + Timer.Interval := uElapse; + + Result := Id; + for I := 0 to Length(FFITimers) - 1 do + begin + if FFITimers[I] = nil then + begin + FFITimers[I] := Timer; + Exit; + end; + end; + I := Length(FFITimers); + SetLength(FFITimers, I + 1); + FFITimers[I] := Timer; + finally + LeaveCriticalSection(FFITimersCritSect); + end; +end; + +procedure FFI_KillTimer(pThis: PFPDF_FORMFILLINFO; nTimerID: Integer); cdecl; +var + I: Integer; +begin + if nTimerID <> 0 then + begin + EnterCriticalSection(FFITimersCritSect); + try + for I := 0 to Length(FFITimers) - 1 do + if (FFITimers[I] <> nil) and (FFITimers[I].FId = nTimerID) then + FreeAndNil(FFITimers[I]); + + I := Length(FFITimers) - 1; + while (I >= 0) and (FFITimers[I] = nil) do + Dec(I); + if Length(FFITimers) <> I + 1 then + SetLength(FFITimers, I + 1); finally LeaveCriticalSection(FFITimersCritSect); end; end; end; +{$ENDIF MSWINDOWS} function FFI_GetLocalTime(pThis: PFPDF_FORMFILLINFO): FPDF_SYSTEMTIME; cdecl; +{$IF not declared(PSystemTime)} +type + PSystemTime = ^TSystemTime; +{$IFEND} begin GetLocalTime(PSystemTime(@Result)^); end; @@ -672,11 +1302,50 @@ function FFI_GetRotation(pThis: PFPDF_FORMFILLINFO; page: FPDF_PAGE): Integer; c Result := 0; end; +procedure FFI_ExecuteNamedAction(pThis: PFPDF_FORMFILLINFO; namedAction: FPDF_BYTESTRING); cdecl; +var + Handler: PPdfFormFillHandler; + NamedActionType: TPdfNamedActionType; + S: UTF8String; +begin + Handler := PPdfFormFillHandler(pThis); + if Assigned(Handler.Document.OnExecuteNamedAction) then + begin + S := namedAction; + + if S = 'Print' then + NamedActionType := naPrint + else if S = 'NextPage' then + NamedActionType := naNextPage + else if S = 'PrevPage' then + NamedActionType := naPrevPage + else if S = 'FirstPage' then + NamedActionType := naFirstPage + else if S = 'LastPage' then + NamedActionType := naLastPage + else + Exit; + + Handler.Document.OnExecuteNamedAction(Handler.Document, NamedActionType); + end; +end; + procedure FFI_SetCursor(pThis: PFPDF_FORMFILLINFO; nCursorType: Integer); cdecl; begin + // A better solution is to check what form field type is under the mouse cursor in the + // MoveMove event. Chrome/Edge doesn't rely on SetCursor either. end; procedure FFI_SetTextFieldFocus(pThis: PFPDF_FORMFILLINFO; value: FPDF_WIDESTRING; valueLen: FPDF_DWORD; is_focus: FPDF_BOOL); cdecl; +var + Handler: PPdfFormFillHandler; +begin + Handler := PPdfFormFillHandler(pThis); + if (Handler.Document <> nil) and Assigned(Handler.Document.OnFormFieldFocus) then + Handler.Document.OnFormFieldFocus(Handler.Document, value, valueLen, is_focus <> 0); +end; + +procedure FFI_FocusChange(param: PFPDF_FORMFILLINFO; annot: FPDF_ANNOTATION; page_index: Integer); cdecl; begin end; @@ -719,13 +1388,38 @@ procedure TPdfRect.SetWidth(const Value: Double); Right := Left + Value; end; +class function TPdfRect.New(Left, Top, Right, Bottom: Double): TPdfRect; +begin + Result.Left := Left; + Result.Top := Top; + Result.Right := Right; + Result.Bottom := Bottom; +end; + +function TPdfRect.PtIn(const Pt: TPdfPoint): Boolean; +begin + Result := (Pt.X >= Left) and (Pt.X < Right); + if Result then + begin + // Page coordinates are upside down. + if Top > Bottom then + Result := (Pt.Y >= Bottom) and (Pt.Y < Top) + else + Result := (Pt.Y >= Top) and (Pt.Y < Bottom) + end; +end; + + { TPdfDocument } constructor TPdfDocument.Create; begin inherited Create; FPages := TObjectList.Create; + FAttachments := TPdfAttachmentList.Create(Self); + {$IFDEF MSWINDOWS} FFileHandle := INVALID_HANDLE_VALUE; + {$ENDIF MSWINDOWS} FFormFieldHighlightColor := $FFE4DD; FFormFieldHighlightAlpha := 100; FPrintHidesFormFieldHighlight := True; @@ -736,6 +1430,7 @@ constructor TPdfDocument.Create; destructor TPdfDocument.Destroy; begin Close; + FAttachments.Free; FPages.Free; inherited Destroy; end; @@ -766,6 +1461,7 @@ procedure TPdfDocument.Close; FCustomLoadData := nil; end; + {$IFDEF MSWINDOWS} if FFileMapping <> 0 then begin if FBuffer <> nil then @@ -776,18 +1472,24 @@ procedure TPdfDocument.Close; CloseHandle(FFileMapping); FFileMapping := 0; end - else if FBuffer <> nil then + else + {$ENDIF MSWINDOWS} + if FBuffer <> nil then begin FreeMem(FBuffer); FBuffer := nil; end; FBytes := nil; + {$IFDEF MSWINDOWS} if FFileHandle <> INVALID_HANDLE_VALUE then begin CloseHandle(FFileHandle); FFileHandle := INVALID_HANDLE_VALUE; end; + {$ELSE} + FreeAndNil(FFileStream); + {$ENDIF MSWINDOWS} FFileName := ''; FFormModified := False; @@ -796,7 +1498,8 @@ procedure TPdfDocument.Close; end; end; -function ReadFromActiveFile(Param: Pointer; Position: LongWord; Buffer: PByte; Size: LongWord): Boolean; +{$IFDEF MSWINDOWS} +function ReadFromActiveFileHandle(Param: Pointer; Position: LongWord; Buffer: PByte; Size: LongWord): Boolean; var NumRead: DWORD; begin @@ -808,27 +1511,44 @@ function ReadFromActiveFile(Param: Pointer; Position: LongWord; Buffer: PByte; S else Result := Size = 0; end; +{$ENDIF MSWINDOWS} -procedure TPdfDocument.LoadFromFile(const AFileName: string; const APassword: AnsiString; ALoadOptions: TPdfDocumentLoadOption); +procedure TPdfDocument.LoadFromFile(const FileName: string; const Password: UTF8String; LoadOption: TPdfDocumentLoadOption); +{$IFDEF MSWINDOWS} var Size: Int64; Offset: NativeInt; NumRead: DWORD; LastError: DWORD; +{$ENDIF MSWINDOWS} begin Close; - // We don't use FPDF_LoadDocument because it is limited to ANSI file names and dloOnDemand emulates it + if LoadOption = dloDefault then + begin + InternLoadFromFile(FileName, Password); + FFileName := FileName; + Exit; + end; - FFileHandle := CreateFile(PChar(AFileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + {$IFDEF MSWINDOWS} + FFileHandle := CreateFileW(PWideChar(FileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if FFileHandle = INVALID_HANDLE_VALUE then RaiseLastOSError; try if not GetFileSizeEx(FFileHandle, Size) then RaiseLastOSError; - if Size > High(Integer) then // PDFium can only handle PDFS us to 2 GB (FX_FILESIZE in core/fxcrt/fx_system.h) - raise EPdfException.CreateResFmt(@RsFileTooLarge, [ExtractFileName(AFileName)]); + if Size > High(Integer) then // PDFium LoadCustomDocument() can only handle PDFs up to 2 GB (see FPDF_FILEACCESS) + begin + {$IFDEF CPUX64} + // FPDF_LoadCustomDocument wasn't updated to load larger files, so we fall back to MMF. + if LoadOption = dloOnDemand then + LoadOption := dloMMF; + {$ELSE} + raise EPdfException.CreateResFmt(@RsFileTooLarge, [ExtractFileName(FileName)]); + {$ENDIF CPUX64} + end; - case ALoadOptions of + case LoadOption of dloMemory: begin if Size > 0 then @@ -857,44 +1577,64 @@ procedure TPdfDocument.LoadFromFile(const AFileName: string; const APassword: An FFileHandle := INVALID_HANDLE_VALUE; end; - InternLoadFromMem(FBuffer, Size, APassword); + InternLoadFromMem(FBuffer, Size, Password); end; end; dloMMF: begin - FFileMapping := CreateFileMapping(FFileHandle, nil, PAGE_READONLY, 0, Size, nil); + FFileMapping := CreateFileMapping(FFileHandle, nil, PAGE_READONLY, 0, 0, nil); if FFileMapping = 0 then RaiseLastOSError; FBuffer := MapViewOfFile(FFileMapping, FILE_MAP_READ, 0, 0, Size); if FBuffer = nil then RaiseLastOSError; - InternLoadFromMem(FBuffer, Size, APassword); + InternLoadFromMem(FBuffer, Size, Password); end; dloOnDemand: - InternLoadFromCustom(ReadFromActiveFile, Size, Pointer(FFileHandle), APassword); + InternLoadFromCustom(ReadFromActiveFileHandle, Size, Pointer(FFileHandle), Password); end; except Close; raise; end; - FFileName := AFileName; + {$ELSE} + FFileStream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite); + try + case LoadOption of + dloMemory, dloMMF: + begin + try + LoadFromStream(FFileStream, Password); + finally + FreeAndNil(FFileStream); + end; + end; + dloOnDemand: + LoadFromActiveStream(FFileStream, Password); + end; + except + FreeAndNil(FFileStream); + raise; + end; + {$ENDIF MSWINDOWS} + FFileName := FileName; end; -procedure TPdfDocument.LoadFromStream(AStream: TStream; const APassword: AnsiString); +procedure TPdfDocument.LoadFromStream(Stream: TStream; const Password: UTF8String); var Size: NativeInt; begin Close; - Size := AStream.Size; + Size := Stream.Size; if Size > 0 then begin GetMem(FBuffer, Size); try - AStream.ReadBuffer(FBuffer^, Size); - InternLoadFromMem(FBuffer, Size, APassword); + Stream.ReadBuffer(FBuffer^, Size); + InternLoadFromMem(FBuffer, Size, Password); except Close; raise; @@ -902,32 +1642,32 @@ procedure TPdfDocument.LoadFromStream(AStream: TStream; const APassword: AnsiStr end; end; -procedure TPdfDocument.LoadFromActiveBuffer(Buffer: Pointer; Size: Integer; const APassword: AnsiString); +procedure TPdfDocument.LoadFromActiveBuffer(Buffer: Pointer; Size: NativeInt; const Password: UTF8String); begin Close; - InternLoadFromMem(Buffer, Size, APassword); + InternLoadFromMem(Buffer, Size, Password); end; -procedure TPdfDocument.LoadFromBytes(const ABytes: TBytes; const APassword: AnsiString); +procedure TPdfDocument.LoadFromBytes(const Bytes: TBytes; const Password: UTF8String); begin - LoadFromBytes(ABytes, 0, Length(ABytes), APassword); + LoadFromBytes(Bytes, 0, Length(Bytes), Password); end; -procedure TPdfDocument.LoadFromBytes(const ABytes: TBytes; AIndex, ACount: Integer; - const APassword: AnsiString); +procedure TPdfDocument.LoadFromBytes(const Bytes: TBytes; Index, Count: NativeInt; + const Password: UTF8String); var - Len: Integer; + Len: NativeInt; begin Close; - Len := Length(ABytes); - if AIndex >= Len then - raise EPdfArgumentOutOfRange.CreateResFmt(@RsArgumentsOutOfRange, ['Index']); - if AIndex + ACount > Len then - raise EPdfArgumentOutOfRange.CreateResFmt(@RsArgumentsOutOfRange, ['Count']); + Len := Length(Bytes); + if Index >= Len then + raise EPdfArgumentOutOfRange.CreateResFmt(@RsArgumentsOutOfRange, ['Index', Index]); + if Index + Count > Len then + raise EPdfArgumentOutOfRange.CreateResFmt(@RsArgumentsOutOfRange, ['Count', Count]); - FBytes := ABytes; // keep alive after return - InternLoadFromMem(@ABytes[AIndex], ACount, APassword); + FBytes := Bytes; // keep alive after return + InternLoadFromMem(@Bytes[Index], Count, Password); end; function ReadFromActiveStream(Param: Pointer; Position: LongWord; Buffer: PByte; Size: LongWord): Boolean; @@ -941,19 +1681,19 @@ function ReadFromActiveStream(Param: Pointer; Position: LongWord; Buffer: PByte; Result := Size = 0; end; -procedure TPdfDocument.LoadFromActiveStream(Stream: TStream; const APassword: AnsiString); +procedure TPdfDocument.LoadFromActiveStream(Stream: TStream; const Password: UTF8String); begin if Stream = nil then Close else - LoadFromCustom(ReadFromActiveStream, Stream.Size, Stream, APassword); + LoadFromCustom(ReadFromActiveStream, Stream.Size, Stream, Password); end; -procedure TPdfDocument.LoadFromCustom(ReadFunc: TPdfDocumentCustomReadProc; ASize: LongWord; - AParam: Pointer; const APassword: AnsiString); +procedure TPdfDocument.LoadFromCustom(ReadFunc: TPdfDocumentCustomReadProc; Size: LongWord; + Param: Pointer; const Password: UTF8String); begin Close; - InternLoadFromCustom(ReadFunc, ASize, AParam, APassword); + InternLoadFromCustom(ReadFunc, Size, Param, Password); end; function GetLoadFromCustomBlock(Param: Pointer; Position: LongWord; Buffer: PByte; Size: LongWord): Integer; cdecl; @@ -964,32 +1704,32 @@ function GetLoadFromCustomBlock(Param: Pointer; Position: LongWord; Buffer: PByt Result := Ord(Data.GetBlock(Data.Param, Position, Buffer, Size)); end; -procedure TPdfDocument.InternLoadFromCustom(ReadFunc: TPdfDocumentCustomReadProc; ASize: LongWord; - AParam: Pointer; const APassword: AnsiString); +procedure TPdfDocument.InternLoadFromCustom(ReadFunc: TPdfDocumentCustomReadProc; Size: LongWord; + Param: Pointer; const Password: UTF8String); var OldCurDoc: TPdfDocument; begin if Assigned(ReadFunc) then begin New(FCustomLoadData); - FCustomLoadData.Param := AParam; + FCustomLoadData.Param := Param; FCustomLoadData.GetBlock := ReadFunc; - FCustomLoadData.FileAccess.m_FileLen := ASize; + FCustomLoadData.FileAccess.m_FileLen := Size; FCustomLoadData.FileAccess.m_GetBlock := GetLoadFromCustomBlock; FCustomLoadData.FileAccess.m_Param := Self; OldCurDoc := UnsupportedFeatureCurrentDocument; try UnsupportedFeatureCurrentDocument := Self; - FDocument := FPDF_LoadCustomDocument(@FCustomLoadData.FileAccess, PAnsiChar(APassword)); - DocumentLoaded; + FDocument := FPDF_LoadCustomDocument(@FCustomLoadData.FileAccess, PAnsiChar(Pointer(Password))); finally UnsupportedFeatureCurrentDocument := OldCurDoc; end; + DocumentLoaded; end; end; -procedure TPdfDocument.InternLoadFromMem(Buffer: PByte; Size: Integer; const APassword: AnsiString); +procedure TPdfDocument.InternLoadFromMem(Buffer: PByte; Size: NativeInt; const Password: UTF8String); var OldCurDoc: TPdfDocument; begin @@ -998,7 +1738,7 @@ procedure TPdfDocument.InternLoadFromMem(Buffer: PByte; Size: Integer; const APa OldCurDoc := UnsupportedFeatureCurrentDocument; try UnsupportedFeatureCurrentDocument := Self; - FDocument := FPDF_LoadMemDocument(Buffer, Size, PAnsiChar(Pointer(APassword))); + FDocument := FPDF_LoadMemDocument64(Buffer, Size, PAnsiChar(Pointer(Password))); finally UnsupportedFeatureCurrentDocument := OldCurDoc; end; @@ -1006,6 +1746,24 @@ procedure TPdfDocument.InternLoadFromMem(Buffer: PByte; Size: Integer; const APa end; end; +procedure TPdfDocument.InternLoadFromFile(const FileName: string; const Password: UTF8String); +var + OldCurDoc: TPdfDocument; + Utf8FileName: UTF8String; +begin + Utf8FileName := UTF8Encode(FileName); + OldCurDoc := UnsupportedFeatureCurrentDocument; + try + UnsupportedFeatureCurrentDocument := Self; + // UTF8 now works with LoadDocument and it can handle large PDF files (2 GB+) what + // FPDF_LoadCustomDocument can't because of the data types in FPDF_FILEACCESS. + FDocument := FPDF_LoadDocument(PAnsiChar(Utf8FileName), PAnsiChar(Pointer(Password))); + finally + UnsupportedFeatureCurrentDocument := OldCurDoc; + end; + DocumentLoaded; +end; + procedure TPdfDocument.DocumentLoaded; begin FFormModified := False; @@ -1026,11 +1784,20 @@ procedure TPdfDocument.DocumentLoaded; FFormFillHandler.FormFillInfo.FFI_GetPage := FFI_GetPage; FFormFillHandler.FormFillInfo.FFI_GetCurrentPage := FFI_GetCurrentPage; FFormFillHandler.FormFillInfo.FFI_GetRotation := FFI_GetRotation; + FFormFillHandler.FormFillInfo.FFI_ExecuteNamedAction := FFI_ExecuteNamedAction; FFormFillHandler.FormFillInfo.FFI_SetCursor := FFI_SetCursor; FFormFillHandler.FormFillInfo.FFI_SetTextFieldFocus := FFI_SetTextFieldFocus; + FFormFillHandler.FormFillInfo.FFI_OnFocusChange := FFI_FocusChange; +// FFormFillHandler.FormFillInfo.FFI_DoURIAction := FFI_DoURIAction; +// FFormFillHandler.FormFillInfo.FFI_DoGoToAction := FFI_DoGoToAction; if PDF_USE_XFA then begin + FJSPlatform.version := 3; + // FJSPlatform callbacks not implemented + + FFormFillHandler.FormFillInfo.m_pJsPlatform := @FJSPlatform; + FFormFillHandler.FormFillInfo.version := 2; FFormFillHandler.FormFillInfo.xfa_disabled := 1; // Disable XFA support for now end; @@ -1038,6 +1805,8 @@ procedure TPdfDocument.DocumentLoaded; FForm := FPDFDOC_InitFormFillEnvironment(FDocument, @FFormFillHandler.FormFillInfo); if FForm <> nil then begin + if PDF_USE_XFA and (FFormFillHandler.FormFillInfo.xfa_disabled = 0) then + FPDF_LoadXFA(FDocument); UpdateFormFieldHighlight; FORM_DoDocumentJSAction(FForm); @@ -1047,7 +1816,7 @@ procedure TPdfDocument.DocumentLoaded; procedure TPdfDocument.UpdateFormFieldHighlight; begin - FPDF_SetFormFieldHighlightColor(FForm, 0, {ColorToRGB}(FFormFieldHighlightColor)); + FPDF_SetFormFieldHighlightColor(FForm, 0, FFormFieldHighlightColor); FPDF_SetFormFieldHighlightAlpha(FForm, FFormFieldHighlightAlpha); end; @@ -1113,9 +1882,47 @@ procedure TPdfDocument.CheckActive; raise EPdfException.CreateRes(@RsDocumentNotActive); end; -function TPdfDocument.ImportPages(Source: TPdfDocument; const Range: string; Index: Integer): Boolean; +class function TPdfDocument.CreateNPagesOnOnePageDocument(Source: TPdfDocument; + NumPagesXAxis, NumPagesYAxis: Integer): TPdfDocument; +begin + if Source.PageCount > 0 then + Result := CreateNPagesOnOnePageDocument(Source, Source.PageSizes[0].X, Source.PageSizes[0].Y, NumPagesXAxis, NumPagesYAxis) + else + Result := CreateNPagesOnOnePageDocument(Source, PdfDefaultPageWidth, PdfDefaultPageHeight, NumPagesXAxis, NumPagesYAxis); // DIN A4 page +end; + +class function TPdfDocument.CreateNPagesOnOnePageDocument(Source: TPdfDocument; + NewPageWidth, NewPageHeight: Double; NumPagesXAxis, NumPagesYAxis: Integer): TPdfDocument; +var + OldCurDoc: TPdfDocument; +begin + Result := TPdfDocument.Create; + try + if (Source = nil) or not Source.Active then + Result.NewDocument + else + begin + OldCurDoc := UnsupportedFeatureCurrentDocument; + try + UnsupportedFeatureCurrentDocument := Result; + Result.FDocument := FPDF_ImportNPagesToOne(Source.FDocument, NewPageWidth, NewPageHeight, NumPagesXAxis, NumPagesYAxis); + finally + UnsupportedFeatureCurrentDocument := OldCurDoc; + end; + if Result.FDocument <> nil then + Result.DocumentLoaded + else + Result.NewDocument; + end; + except + Result.Free; + raise; + end; +end; + +function TPdfDocument.InternImportPages(Source: TPdfDocument; PageIndices: PInteger; PageIndicesCount: Integer; + const Range: AnsiString; Index: Integer; ImportByRange: Boolean): Boolean; var - A: AnsiString; I, NewCount, OldCount, InsertCount: Integer; begin CheckActive; @@ -1124,8 +1931,12 @@ function TPdfDocument.ImportPages(Source: TPdfDocument; const Range: string; Ind OldCount := FPDF_GetPageCount(FDocument); if Index < 0 then Index := OldCount; - A := AnsiString(Range); - Result := FPDF_ImportPages(FDocument, Source.FDocument, PAnsiChar(Pointer(A)), Index) <> 0; + + if ImportByRange then // Range = '' => Import all pages + Result := FPDF_ImportPages(FDocument, Source.FDocument, PAnsiChar(Pointer(Range)), Index) <> 0 + else + Result := FPDF_ImportPagesByIndex(FDocument, Source.FDocument, PageIndices, PageIndicesCount, Index) <> 0; + NewCount := FPDF_GetPageCount(FDocument); InsertCount := NewCount - OldCount; if InsertCount > 0 then @@ -1140,6 +1951,50 @@ function TPdfDocument.ImportPages(Source: TPdfDocument; const Range: string; Ind end; end; +function TPdfDocument.ImportAllPages(Source: TPdfDocument; Index: Integer): Boolean; +begin + Result := InternImportPages(Source, nil, 0, '', Index, False); +end; + +function TPdfDocument.ImportPages(Source: TPdfDocument; const Range: string; Index: Integer): Boolean; +begin + Result := InternImportPages(Source, nil, 0, AnsiString(Range), Index, True) +end; + +function TPdfDocument.ImportPageRange(Source: TPdfDocument; PageIndex, Count, Index: Integer): Boolean; +begin + Result := False; + if (Source <> nil) and (PageIndex >= 0) then + begin + if Count = -1 then + Count := Source.PageCount - PageIndex + else if Count < 0 then + Exit; + + if Count > 0 then + begin + if PageIndex + Count > Source.PageCount then + begin + Count := Source.PageCount - PageIndex; + if Count = 0 then + Exit; + end; + if (PageIndex = 0) and (Count = Source.PageCount) then + Result := ImportAllPages(Source, Index) + else + Result := ImportPages(Source, Format('%d-%d', [PageIndex, PageIndex + Count - 1])); + end; + end; +end; + +function TPdfDocument.ImportPagesByIndex(Source: TPdfDocument; const PageIndices: array of Integer; Index: Integer = -1): Boolean; +begin + if Length(PageIndices) > 0 then + Result := InternImportPages(Source, @PageIndices[0], Length(PageIndices), '', Index, False) + else + Result := ImportAllPages(Source, Index); +end; + procedure TPdfDocument.SaveToFile(const AFileName: string; Option: TPdfDocumentSaveOption; FileVersion: Integer); var Stream: TFileStream; @@ -1175,12 +2030,18 @@ procedure TPdfDocument.SaveToStream(Stream: TStream; Option: TPdfDocumentSaveOpt FileWriteInfo.Stream := Stream; if FForm <> nil then + begin FORM_ForceToKillFocus(FForm); // also save the form field data that is currently focused + FORM_DoDocumentAAction(FForm, FPDFDOC_AACTION_WS); // BeforeSave + end; if FileVersion <> -1 then FPDF_SaveWithVersion(FDocument, @FileWriteInfo, Ord(Option), FileVersion) else FPDF_SaveAsCopy(FDocument, @FileWriteInfo, Ord(Option)); + + if FForm <> nil then + FORM_DoDocumentAAction(FForm, FPDFDOC_AACTION_DS); // AfterSave end; procedure TPdfDocument.SaveToBytes(var Bytes: TBytes; Option: TPdfDocumentSaveOption; FileVersion: Integer); @@ -1224,7 +2085,7 @@ function TPdfDocument.NewPage(Width, Height: Double; Index: Integer): TPdfPage; begin CheckActive; if Index < 0 then - Index := FPages.Count; + Index := FPages.Count; // append new page LPage := FPDFPage_New(FDocument, Index, Width, Height); if LPage <> nil then begin @@ -1235,6 +2096,11 @@ function TPdfDocument.NewPage(Width, Height: Double; Index: Integer): TPdfPage; Result := nil; end; +function TPdfDocument.NewPage(Index: Integer = -1): TPdfPage; +begin + Result := NewPage(PdfDefaultPageWidth, PdfDefaultPageHeight, Index); +end; + function TPdfDocument.ApplyViewerPreferences(Source: TPdfDocument): Boolean; begin CheckActive; @@ -1242,6 +2108,23 @@ function TPdfDocument.ApplyViewerPreferences(Source: TPdfDocument): Boolean; Result := FPDF_CopyViewerPreferences(FDocument, Source.FDocument) <> 0; end; +function TPdfDocument.GetFileIdentifier(IdType: TPdfFileIdType): string; +var + Len: Integer; + A: AnsiString; +begin + CheckActive; + Len := FPDF_GetFileIdentifier(FDocument, FPDF_FILEIDTYPE(IdType), nil, 0) div SizeOf(AnsiChar) - 1; + if Len > 0 then + begin + SetLength(A, Len); + FPDF_GetFileIdentifier(FDocument, FPDF_FILEIDTYPE(IdType), PAnsiChar(A), (Len + 1) * SizeOf(AnsiChar)); + Result := string(A); + end + else + Result := ''; +end; + function TPdfDocument.GetMetaText(const TagName: string): string; var Len: Integer; @@ -1249,11 +2132,11 @@ function TPdfDocument.GetMetaText(const TagName: string): string; begin CheckActive; A := AnsiString(TagName); - Len := (FPDF_GetMetaText(FDocument, PAnsiChar(A), nil, 0) div SizeOf(WideChar)) - 1; + Len := FPDF_GetMetaText(FDocument, PAnsiChar(A), nil, 0) div SizeOf(WideChar) - 1; if Len > 0 then begin SetLength(Result, Len); - FPDF_GetMetaText(FDocument, PAnsiChar(A), PChar(Result), (Len + 1) * SizeOf(WideChar)); + FPDF_GetMetaText(FDocument, PAnsiChar(A), PWideChar(Result), (Len + 1) * SizeOf(WideChar)); end else Result := ''; @@ -1279,12 +2162,16 @@ function TPdfDocument.GetFileVersion: Integer; end; function TPdfDocument.GetPageSize(Index: Integer): TPdfPoint; +var + SizeF: TFSSizeF; begin CheckActive; - if FPDF_GetPageSizeByIndex(FDocument, Index, Result.X, Result.Y) = 0 then + Result.X := 0; + Result.Y := 0; + if FPDF_GetPageSizeByIndexF(FDocument, Index, @SizeF) <> 0 then begin - Result.X := 0; - Result.Y := 0; + Result.X := SizeF.width; + Result.Y := SizeF.height; end; end; @@ -1303,7 +2190,11 @@ function TPdfDocument.GetNumCopies: Integer; class function TPdfDocument.SetPrintMode(PrintMode: TPdfPrintMode): Boolean; begin InitLib; + {$IFDEF MSWINDOWS} Result := FPDF_SetPrintMode(Ord(PrintMode)) <> 0; + {$ELSE} + Result := False; + {$ENDIF MSWINDOWS} end; procedure TPdfDocument.SetFormFieldHighlightAlpha(Value: Integer); @@ -1321,13 +2212,13 @@ procedure TPdfDocument.SetFormFieldHighlightAlpha(Value: Integer); end; end; -procedure TPdfDocument.SetFormFieldHighlightColor(const Value: TColor); +procedure TPdfDocument.SetFormFieldHighlightColor(const Value: TColorRef); begin if Value <> FFormFieldHighlightColor then begin FFormFieldHighlightColor := Value; if Active then - FPDF_SetFormFieldHighlightColor(FForm, 0, {ColorToRGB}(FFormFieldHighlightColor)); + FPDF_SetFormFieldHighlightColor(FForm, 0, FFormFieldHighlightColor); end; end; @@ -1345,6 +2236,7 @@ function TPdfDocument.FindPage(Page: FPDF_PAGE): TPdfPage; Result := nil; end; + { TPdfPage } constructor TPdfPage.Create(ADocument: TPdfDocument; APage: FPDF_PAGE); @@ -1352,6 +2244,7 @@ constructor TPdfPage.Create(ADocument: TPdfDocument; APage: FPDF_PAGE); inherited Create; FDocument := ADocument; FPage := APage; + FAnnotations := TPdfAnnotationList.Create(Self); AfterOpen; end; @@ -1360,6 +2253,7 @@ destructor TPdfPage.Destroy; begin Close; FDocument.ExtractPage(Self); + FreeAndNil(FAnnotations); inherited Destroy; end; @@ -1389,16 +2283,18 @@ procedure TPdfPage.AfterOpen; procedure TPdfPage.Close; begin + FAnnotations.CloseAnnotations; + if IsValidForm then begin FORM_DoPageAAction(FPage, FDocument.FForm, FPDFPAGE_AACTION_CLOSE); FORM_OnBeforeClosePage(FPage, FDocument.FForm); end; - if FLinkHandle <> nil then + if FPageLinkHandle <> nil then begin - FPDFLink_CloseWebLinks(FLinkHandle); - FLinkHandle := nil; + FPDFLink_CloseWebLinks(FPageLinkHandle); + FPageLinkHandle := nil; end; if FSearchHandle <> nil then begin @@ -1426,6 +2322,56 @@ procedure TPdfPage.Open; end; end; +function TPdfPage.GetPdfActionFilePath(Action: FPDF_ACTION): string; +var + ByteSize: Integer; + Buf: UTF8String; +begin + Result := ''; + if Action <> nil then + begin + case FPDFAction_GetType(Action) of + PDFACTION_LAUNCH, + PDFACTION_REMOTEGOTO: + begin + ByteSize := FPDFAction_GetFilePath(Action, nil, 0); + if ByteSize > 0 then + begin + SetLength(Buf, ByteSize); // we could optimize this with "SetLength(Buf, ByteSize - 1)" and use already existing #0 terminator + ByteSize := FPDFAction_GetFilePath(Action, PAnsiChar(Buf), Length(Buf)); + end; + if ByteSize > 0 then + begin + SetLength(Buf, ByteSize - 1); // ByteSize includes #0 + Result := UTF8ToString(Buf); + end; + end; + end; + end; +end; + +function TPdfPage.GetPdfActionUriPath(Action: FPDF_ACTION): string; +var + ByteSize: Integer; + Buf: UTF8String; +begin + Result := ''; + if Action <> nil then + begin + ByteSize := FPDFAction_GetURIPath(FDocument.Handle, Action, nil, 0); + if ByteSize > 0 then + begin + SetLength(Buf, ByteSize); // we could optimize this with "SetLength(Buf, ByteSize - 1)" and use already existing #0 terminator + ByteSize := FPDFAction_GetURIPath(FDocument.Handle, Action, PAnsiChar(Buf), Length(Buf)); + end; + if ByteSize > 0 then + begin + SetLength(Buf, ByteSize - 1); // ByteSize includes #0 + Result := UTF8ToString(Buf); + end; + end; +end; + class function TPdfPage.GetDrawFlags(const Options: TPdfPageRenderOptions): Integer; begin Result := 0; @@ -1447,7 +2393,9 @@ class function TPdfPage.GetDrawFlags(const Options: TPdfPageRenderOptions): Inte Result := Result or FPDF_REVERSE_BYTE_ORDER; end; -procedure TPdfPage.Draw(DC: HDC; X, Y, Width, Height: Integer; Rotate: TPdfPageRotation; const Options: TPdfPageRenderOptions); +{$IFDEF MSWINDOWS} +procedure TPdfPage.Draw(DC: HDC; X, Y, Width, Height: Integer; Rotate: TPdfPageRotation; + const Options: TPdfPageRenderOptions; PageBackground: TColorRef); var BitmapInfo: TBitmapInfo; Bmp, OldBmp: HBITMAP; @@ -1459,15 +2407,22 @@ procedure TPdfPage.Draw(DC: HDC; X, Y, Width, Height: Integer; Rotate: TPdfPageR if proPrinting in Options then begin + if IsValidForm and (FPDFPage_GetAnnotCount(FPage) > 0) then + begin + // Form content isn't printed unless it was flattend and the page was reloaded. + ApplyChanges; + Flatten(True); + Close; + Open; + end; FPDF_RenderPage(DC, FPage, X, Y, Width, Height, Ord(Rotate), GetDrawFlags(Options)); Exit; end; - FillChar(BitmapInfo, SizeOf(BitmapInfo), 0); BitmapInfo.bmiHeader.biSize := SizeOf(BitmapInfo); BitmapInfo.bmiHeader.biWidth := Width; - BitmapInfo.bmiHeader.biHeight := -Height; + BitmapInfo.bmiHeader.biHeight := -Height; // negative Height means top to bottom for Y values BitmapInfo.bmiHeader.biPlanes := 1; BitmapInfo.bmiHeader.biBitCount := 32; BitmapInfo.bmiHeader.biCompression := BI_RGB; @@ -1476,14 +2431,10 @@ procedure TPdfPage.Draw(DC: HDC; X, Y, Width, Height: Integer; Rotate: TPdfPageR if Bmp <> 0 then begin try + // Use the Windows Bitmap's bits for the PdfBmp PdfBmp := TPdfBitmap.Create(Width, Height, bfBGRA, BmpBits, Width * 4); try - if Transparency then - PdfBmp.FillRect(0, 0, Width, Height, $00FFFFFF) - else - PdfBmp.FillRect(0, 0, Width, Height, $FFFFFFFF); - DrawToPdfBitmap(PdfBmp, 0, 0, Width, Height, Rotate, Options); - DrawFormToPdfBitmap(PdfBmp, 0, 0, Width, Height, Rotate, Options); + Draw(PdfBmp, 0, 0, Width, Height, Rotate, Options, PageBackground); finally PdfBmp.Free; end; @@ -1498,6 +2449,15 @@ procedure TPdfPage.Draw(DC: HDC; X, Y, Width, Height: Integer; Rotate: TPdfPageR end; end; end; +{$ENDIF MSWINDOWS} + +procedure TPdfPage.Draw(APdfBitmap: TPdfBitmap; X, Y, Width, Height: Integer; Rotate: TPdfPageRotation = prNormal; + const Options: TPdfPageRenderOptions = []; PageBackground: TColorRef = $FFFFFF); +begin + APdfBitmap.FillRect(X, Y, Width, Height, $FF000000 or PageBackground); + DrawToPdfBitmap(APdfBitmap, X, Y, Width, Height, Rotate, Options); + DrawFormToPdfBitmap(APdfBitmap, X, Y, Width, Height, Rotate, Options); +end; procedure TPdfPage.DrawToPdfBitmap(APdfBitmap: TPdfBitmap; X, Y, Width, Height: Integer; Rotate: TPdfPageRotation; const Options: TPdfPageRenderOptions); @@ -1534,6 +2494,8 @@ procedure TPdfPage.UpdateMetrics; FHeight := FPDF_GetPageHeightF(FPage); FTransparency := FPDFPage_HasTransparency(FPage) <> 0; FRotation := TPdfPageRotation(FPDFPage_GetRotation(FPage)); + if Ord(FRotation) = -1 then + FRotation := prNormal; end; function TPdfPage.DeviceToPage(X, Y, Width, Height: Integer; DeviceX, DeviceY: Integer; Rotate: TPdfPageRotation): TPdfPoint; @@ -1561,6 +2523,7 @@ function TPdfPage.PageToDevice(X, Y, Width, Height: Integer; const R: TPdfRect; begin Result.TopLeft := PageToDevice(X, Y, Width, Height, R.Left, R.Top, Rotate); Result.BottomRight := PageToDevice(X, Y, Width, Height, R.Right, R.Bottom, Rotate); + // Page coordinales are upside down, but device coordinates aren't. if Result.Top > Result.Bottom then begin T := Result.Top; @@ -1574,12 +2537,35 @@ procedure TPdfPage.SetRotation(const Value: TPdfPageRotation); Open; FPDFPage_SetRotation(FPage, Ord(Value)); FRotation := TPdfPageRotation(FPDFPage_GetRotation(FPage)); + if Ord(FRotation) = -1 then + FRotation := prNormal; end; procedure TPdfPage.ApplyChanges; begin if FPage <> nil then + begin FPDFPage_GenerateContent(FPage); + + // Newly added text annotations will not show the text popup unless the page is notified. + FAnnotations.CloseAnnotations; + if IsValidForm then + begin + FORM_DoPageAAction(FPage, FDocument.FForm, FPDFPAGE_AACTION_CLOSE); + FORM_OnBeforeClosePage(FPage, FDocument.FForm); + + FORM_OnAfterLoadPage(FPage, FDocument.FForm); + FORM_DoPageAAction(FPage, FDocument.FForm, FPDFPAGE_AACTION_OPEN); + end; + end; +end; + +procedure TPdfPage.Flatten(AFlatPrint: Boolean); +const + Flags: array[Boolean] of Integer = (FLAT_NORMALDISPLAY, FLAT_PRINT); +begin + if FPage <> nil then + FPDFPage_Flatten(FPage, Flags[AFlatPrint]); end; function TPdfPage.BeginText: Boolean; @@ -1594,9 +2580,11 @@ function TPdfPage.BeginText: Boolean; function TPdfPage.BeginWebLinks: Boolean; begin - if (FLinkHandle = nil) and BeginText then - FLinkHandle := FPDFLink_LoadWebLinks(FTextHandle); - Result := FLinkHandle <> nil; + // WebLinks are not stored in the PDF but are created by parsing the page's text for URLs. + // They are accessed differently than annotation links, which are stored in the PDF. + if (FPageLinkHandle = nil) and BeginText then + FPageLinkHandle := FPDFLink_LoadWebLinks(FTextHandle); + Result := FPageLinkHandle <> nil; end; function TPdfPage.BeginFind(const SearchString: string; MatchCase, MatchWholeWord, @@ -1618,7 +2606,7 @@ function TPdfPage.BeginFind(const SearchString: string; MatchCase, MatchWholeWor else StartIndex := 0; - FSearchHandle := FPDFText_FindStart(FTextHandle, PChar(SearchString), Flags, StartIndex); + FSearchHandle := FPDFText_FindStart(FTextHandle, PWideChar(SearchString), Flags, StartIndex); end; Result := FSearchHandle <> nil; end; @@ -1713,7 +2701,7 @@ function TPdfPage.ReadText(CharIndex, Count: Integer): string; if (Count > 0) and BeginText then begin SetLength(Result, Count); // we let GetText overwrite our #0 terminator with its #0 - Len := FPDFText_GetText(FTextHandle, CharIndex, Count, PChar(Result)) - 1; // returned length includes the #0 + Len := FPDFText_GetText(FTextHandle, CharIndex, Count, PWideChar(Result)) - 1; // returned length includes the #0 if Len <= 0 then Result := '' else if Len < Count then @@ -1732,7 +2720,7 @@ function TPdfPage.GetTextAt(Left, Top, Right, Bottom: Double): string; Len := FPDFText_GetBoundedText(FTextHandle, Left, Top, Right, Bottom, nil, 0); // excluding #0 terminator SetLength(Result, Len); if Len > 0 then - FPDFText_GetBoundedText(FTextHandle, Left, Top, Right, Bottom, PChar(Result), Len); + FPDFText_GetBoundedText(FTextHandle, Left, Top, Right, Bottom, PWideChar(Result), Len); end else Result := ''; @@ -1759,11 +2747,62 @@ function TPdfPage.GetTextRect(RectIndex: Integer): TPdfRect; Result := TPdfRect.Empty; end; +function TPdfPage.IsUriLinkAtPoint(X, Y: Double): Boolean; +var + Link: FPDF_LINK; + Action: FPDF_ACTION; +begin + Result := False; + Link := FPDFLink_GetLinkAtPoint(Handle, X, Y); + if Link <> nil then + begin + Action := FPDFLink_GetAction(Link); + if (Action <> nil) and (FPDFAction_GetType(Action) = PDFACTION_URI) then + Result := True; + end; +end; + +function TPdfPage.IsUriLinkAtPoint(X, Y: Double; var Uri: string): Boolean; +var + Link: FPDF_LINK; + Action: FPDF_ACTION; +begin + Action := nil; + Result := False; + Link := FPDFLink_GetLinkAtPoint(Handle, X, Y); + if Link <> nil then + begin + Action := FPDFLink_GetAction(Link); + if (Action <> nil) and (FPDFAction_GetType(Action) = PDFACTION_URI) then + Result := True; + end; + + if Result then + Uri := GetPdfActionUriPath(Action) + else + Uri := ''; +end; + +function TPdfPage.GetLinkAtPoint(X, Y: Double): TPdfAnnotation; +var + Link: FPDF_LINK; +begin + Link := FPDFLink_GetLinkAtPoint(Handle, X, Y); + if Link <> nil then + begin + Result := Annotations.FindLink(Link); + if (Result <> nil) and (Result.LinkType = altUnsupported) then + Result := nil; + end + else + Result := nil; +end; + function TPdfPage.GetWebLinkCount: Integer; begin if BeginWebLinks then begin - Result := FPDFLink_CountWebLinks(FLinkHandle); + Result := FPDFLink_CountWebLinks(FPageLinkHandle); if Result < 0 then Result := 0; end @@ -1778,11 +2817,11 @@ function TPdfPage.GetWebLinkURL(LinkIndex: Integer): string; Result := ''; if BeginWebLinks then begin - Len := FPDFLink_GetURL(FLinkHandle, LinkIndex, nil, 0) - 1; // including #0 terminator + Len := FPDFLink_GetURL(FPageLinkHandle, LinkIndex, nil, 0) - 1; // including #0 terminator if Len > 0 then begin SetLength(Result, Len); - FPDFLink_GetURL(FLinkHandle, LinkIndex, PChar(Result), Len + 1); // including #0 terminator + FPDFLink_GetURL(FPageLinkHandle, LinkIndex, PWideChar(Result), Len + 1); // including #0 terminator end; end; end; @@ -1790,7 +2829,7 @@ function TPdfPage.GetWebLinkURL(LinkIndex: Integer): string; function TPdfPage.GetWebLinkRectCount(LinkIndex: Integer): Integer; begin if BeginWebLinks then - Result := FPDFLink_CountRects(FLinkHandle, LinkIndex) + Result := FPDFLink_CountRects(FPageLinkHandle, LinkIndex) else Result := 0; end; @@ -1798,12 +2837,49 @@ function TPdfPage.GetWebLinkRectCount(LinkIndex: Integer): Integer; function TPdfPage.GetWebLinkRect(LinkIndex, RectIndex: Integer): TPdfRect; begin if BeginWebLinks then - FPDFLink_GetRect(FLinkHandle, LinkIndex, RectIndex, Result.Left, Result.Top, Result.Right, Result.Bottom) + FPDFLink_GetRect(FPageLinkHandle, LinkIndex, RectIndex, Result.Left, Result.Top, Result.Right, Result.Bottom) else Result := TPdfRect.Empty; end; -function TPdfPage.GetMouseModifier(const Shift: TShiftState): Integer; +function TPdfPage.IsWebLinkAtPoint(X, Y: Double): Boolean; +var + LinkIndex, RectIndex: Integer; + Pt: TPdfPoint; +begin + Result := True; + Pt.X := X; + Pt.Y := Y; + for LinkIndex := 0 to GetWebLinkCount - 1 do + for RectIndex := 0 to GetWebLinkRectCount(LinkIndex) - 1 do + if GetWebLinkRect(LinkIndex, RectIndex).PtIn(Pt) then + Exit; + Result := False; +end; + +function TPdfPage.IsWebLinkAtPoint(X, Y: Double; var URL: string): Boolean; +var + LinkIndex, RectIndex: Integer; + Pt: TPdfPoint; +begin + Result := True; + Pt.X := X; + Pt.Y := Y; + for LinkIndex := 0 to GetWebLinkCount - 1 do + begin + for RectIndex := 0 to GetWebLinkRectCount(LinkIndex) - 1 do + begin + if GetWebLinkRect(LinkIndex, RectIndex).PtIn(Pt) then + begin + URL := GetWebLinkURL(LinkIndex); + Exit; + end; + end; + end; + Result := False; +end; + +function TPdfPage.ShiftStateToModifier(const Shift: TShiftState): Integer; begin Result := 0; if ssShift in Shift then @@ -1820,23 +2896,31 @@ function TPdfPage.GetMouseModifier(const Shift: TShiftState): Integer; Result := Result or FWL_EVENTFLAG_RightButtonDown; end; -function TPdfPage.GetKeyModifier(KeyData: LPARAM): Integer; -const - AltMask = $20000000; +function TPdfPage.FormEventFocus(const Shift: TShiftState; PageX, PageY: Double): Boolean; begin - Result := 0; - if GetKeyState(VK_SHIFT) < 0 then - Result := Result or FWL_EVENTFLAG_ShiftKey; - if GetKeyState(VK_CONTROL) < 0 then - Result := Result or FWL_EVENTFLAG_ControlKey; - if KeyData and AltMask <> 0 then - Result := Result or FWL_EVENTFLAG_AltKey; + if IsValidForm then + Result := FORM_OnFocus(FDocument.FForm, FPage, ShiftStateToModifier(Shift), PageX, PageY) <> 0 + else + Result := False; end; -function TPdfPage.FormEventFocus(const Shift: TShiftState; PageX, PageY: Double): Boolean; +function TPdfPage.FormEventMouseWheel(const Shift: TShiftState; WheelDelta: Integer; PageX, PageY: Double): Boolean; +var + Pt: TFSPointF; + WheelX, WheelY: Integer; begin if IsValidForm then - Result := FORM_OnFocus(FDocument.FForm, FPage, GetMouseModifier(Shift), PageX, PageY) <> 0 + begin + Pt.X := PageX; + Pt.Y := PageY; + WheelX := 0; + WheelY := 0; + if ssShift in Shift then + WheelX := WheelDelta + else + WheelY := WheelDelta; + Result := FORM_OnMouseWheel(FDocument.FForm, FPage, ShiftStateToModifier(Shift), @Pt, WheelX, WheelY) <> 0; + end else Result := False; end; @@ -1844,7 +2928,7 @@ function TPdfPage.FormEventFocus(const Shift: TShiftState; PageX, PageY: Double) function TPdfPage.FormEventMouseMove(const Shift: TShiftState; PageX, PageY: Double): Boolean; begin if IsValidForm then - Result := FORM_OnMouseMove(FDocument.FForm, FPage, GetMouseModifier(Shift), PageX, PageY) <> 0 + Result := FORM_OnMouseMove(FDocument.FForm, FPage, ShiftStateToModifier(Shift), PageX, PageY) <> 0 else Result := False; end; @@ -1852,7 +2936,7 @@ function TPdfPage.FormEventMouseMove(const Shift: TShiftState; PageX, PageY: Dou function TPdfPage.FormEventLButtonDown(const Shift: TShiftState; PageX, PageY: Double): Boolean; begin if IsValidForm then - Result := FORM_OnLButtonDown(FDocument.FForm, FPage, GetMouseModifier(Shift), PageX, PageY) <> 0 + Result := FORM_OnLButtonDown(FDocument.FForm, FPage, ShiftStateToModifier(Shift), PageX, PageY) <> 0 else Result := False; end; @@ -1860,7 +2944,7 @@ function TPdfPage.FormEventLButtonDown(const Shift: TShiftState; PageX, PageY: D function TPdfPage.FormEventLButtonUp(const Shift: TShiftState; PageX, PageY: Double): Boolean; begin if IsValidForm then - Result := FORM_OnLButtonUp(FDocument.FForm, FPage, GetMouseModifier(Shift), PageX, PageY) <> 0 + Result := FORM_OnLButtonUp(FDocument.FForm, FPage, ShiftStateToModifier(Shift), PageX, PageY) <> 0 else Result := False; end; @@ -1868,7 +2952,7 @@ function TPdfPage.FormEventLButtonUp(const Shift: TShiftState; PageX, PageY: Dou function TPdfPage.FormEventRButtonDown(const Shift: TShiftState; PageX, PageY: Double): Boolean; begin if IsValidForm then - Result := FORM_OnRButtonDown(FDocument.FForm, FPage, GetMouseModifier(Shift), PageX, PageY) <> 0 + Result := FORM_OnRButtonDown(FDocument.FForm, FPage, ShiftStateToModifier(Shift), PageX, PageY) <> 0 else Result := False; end; @@ -1876,61 +2960,148 @@ function TPdfPage.FormEventRButtonDown(const Shift: TShiftState; PageX, PageY: D function TPdfPage.FormEventRButtonUp(const Shift: TShiftState; PageX, PageY: Double): Boolean; begin if IsValidForm then - Result := FORM_OnRButtonUp(FDocument.FForm, FPage, GetMouseModifier(Shift), PageX, PageY) <> 0 + Result := FORM_OnRButtonUp(FDocument.FForm, FPage, ShiftStateToModifier(Shift), PageX, PageY) <> 0 + else + Result := False; +end; + +function TPdfPage.FormEventKeyDown(KeyCode: Word; const Shift: TShiftState): Boolean; +begin + if IsValidForm then + Result := FORM_OnKeyDown(FDocument.FForm, FPage, KeyCode, ShiftStateToModifier(Shift)) <> 0 else Result := False; end; -function TPdfPage.FormEventKeyDown(KeyCode: Word; KeyData: LPARAM): Boolean; +function TPdfPage.FormEventKeyUp(KeyCode: Word; const Shift: TShiftState): Boolean; begin if IsValidForm then - Result := FORM_OnKeyDown(FDocument.FForm, FPage, KeyCode, GetKeyModifier(KeyData)) <> 0 + Result := FORM_OnKeyUp(FDocument.FForm, FPage, KeyCode, ShiftStateToModifier(Shift)) <> 0 else Result := False; end; -function TPdfPage.FormEventKeyUp(KeyCode: Word; KeyData: LPARAM): Boolean; +function TPdfPage.FormEventKeyPress(Key: Word; const Shift: TShiftState): Boolean; begin if IsValidForm then - Result := FORM_OnKeyUp(FDocument.FForm, FPage, KeyCode, GetKeyModifier(KeyData)) <> 0 + Result := FORM_OnChar(FDocument.FForm, FPage, Key, ShiftStateToModifier(Shift)) <> 0 else Result := False; end; -function TPdfPage.FormEventKeyPress(Key: Word; KeyData: LPARAM): Boolean; +function TPdfPage.FormEventKillFocus: Boolean; begin if IsValidForm then - Result := FORM_OnChar(FDocument.FForm, FPage, Key, GetKeyModifier(KeyData)) <> 0 + Result := FORM_ForceToKillFocus(FDocument.FForm) <> 0 else Result := False; end; -procedure TPdfPage.FormEventKillFocus; +function TPdfPage.FormGetFocusedText: string; +var + ByteLen: LongWord; begin if IsValidForm then - FORM_ForceToKillFocus(FDocument.FForm); + begin + ByteLen := FORM_GetFocusedText(FDocument.FForm, FPage, nil, 0); // UTF 16 including #0 terminator in byte size + if ByteLen <= 2 then // WideChar(#0) => empty string + Result := '' + else + begin + SetLength(Result, ByteLen div SizeOf(WideChar) - 1); + FORM_GetFocusedText(FDocument.FForm, FPage, PWideChar(Result), ByteLen); + end; + end + else + Result := ''; end; -function TPdfPage.HasFormFieldAtPoint(X, Y: Double): TPdfFormFieldType; +function TPdfPage.FormGetSelectedText: string; +var + ByteLen: LongWord; +begin + if IsValidForm then + begin + ByteLen := FORM_GetSelectedText(FDocument.FForm, FPage, nil, 0); // UTF 16 including #0 terminator in byte size + if ByteLen <= 2 then // WideChar(#0) => empty string + Result := '' + else + begin + SetLength(Result, ByteLen div SizeOf(WideChar) - 1); + FORM_GetSelectedText(FDocument.FForm, FPage, PWideChar(Result), ByteLen); + end; + end + else + Result := ''; +end; + +function TPdfPage.FormReplaceSelection(const ANewText: string): Boolean; +begin + if IsValidForm then + begin + FORM_ReplaceSelection(FDocument.FForm, FPage, PWideChar(ANewText)); + Result := True; + end + else + Result := False; +end; + +function TPdfPage.FormReplaceAndKeepSelection(const ANewText: string): Boolean; +begin + if IsValidForm then + begin + FORM_ReplaceAndKeepSelection(FDocument.FForm, FPage, PWideChar(ANewText)); + Result := True; + end + else + Result := False; +end; + +function TPdfPage.FormSelectAllText: Boolean; +begin + if IsValidForm then + Result := FORM_SelectAllText(FDocument.FForm, FPage) <> 0 + else + Result := False; +end; + +function TPdfPage.FormCanUndo: Boolean; +begin + if IsValidForm then + Result := FORM_CanUndo(FDocument.FForm, FPage) <> 0 + else + Result := False; +end; + +function TPdfPage.FormCanRedo: Boolean; +begin + if IsValidForm then + Result := FORM_CanRedo(FDocument.FForm, FPage) <> 0 + else + Result := False; +end; + +function TPdfPage.FormUndo: Boolean; +begin + if IsValidForm then + Result := FORM_Undo(FDocument.FForm, FPage) <> 0 + else + Result := False; +end; + +function TPdfPage.FormRedo: Boolean; begin - case FPDFPage_HasFormFieldAtPoint(FDocument.FForm, FPage, X, Y) of - FPDF_FORMFIELD_PUSHBUTTON: - Result := fftPushButton; - FPDF_FORMFIELD_CHECKBOX: - Result := fftCheckBox; - FPDF_FORMFIELD_RADIOBUTTON: - Result := fftRadioButton; - FPDF_FORMFIELD_COMBOBOX: - Result := fftComboBox; - FPDF_FORMFIELD_LISTBOX: - Result := fftListBox; - FPDF_FORMFIELD_TEXTFIELD: - Result := fftTextField; - FPDF_FORMFIELD_SIGNATURE: - Result := fftSignature; + if IsValidForm then + Result := FORM_Redo(FDocument.FForm, FPage) <> 0 else + Result := False; +end; + +function TPdfPage.HasFormFieldAtPoint(X, Y: Double): TPdfFormFieldType; +begin + Result := TPdfFormFieldType(FPDFPage_HasFormFieldAtPoint(FDocument.FForm, FPage, X, Y)); + if (Result < Low(TPdfFormFieldType)) or (Result > High(TPdfFormFieldType)) then Result := fftUnknown; - end; end; function TPdfPage.GetHandle: FPDF_PAGE; @@ -1944,13 +3115,28 @@ function TPdfPage.IsLoaded: Boolean; Result := FPage <> nil; end; +function TPdfPage.GetTextHandle: FPDF_TEXTPAGE; +begin + if BeginText then + Result := FTextHandle + else + Result := nil; +end; + +function TPdfPage.GetFormFields: TPdfFormFieldList; +begin + Result := Annotations.FormFields; +end; + + { _TPdfBitmapHideCtor } -procedure _TPdfBitmapHideCtor.Create; +constructor _TPdfBitmapHideCtor.Create; begin inherited Create; end; + { TPdfBitmap } constructor TPdfBitmap.Create(ABitmap: FPDF_BITMAP; AOwnsBitmap: Boolean); @@ -2017,12 +3203,1351 @@ class function TPdfPoint.Empty: TPdfPoint; Result.Y := 0; end; + +{ TPdfAttachmentList } + +constructor TPdfAttachmentList.Create(ADocument: TPdfDocument); +begin + inherited Create; + FDocument := ADocument; +end; + +function TPdfAttachmentList.GetCount: Integer; +begin + FDocument.CheckActive; + Result := FPDFDoc_GetAttachmentCount(FDocument.Handle); +end; + +function TPdfAttachmentList.GetItem(Index: Integer): TPdfAttachment; +var + Attachment: FPDF_ATTACHMENT; +begin + FDocument.CheckActive; + Attachment := FPDFDoc_GetAttachment(FDocument.Handle, Index); + if Attachment = nil then + raise EPdfArgumentOutOfRange.CreateResFmt(@RsArgumentsOutOfRange, ['Index']); + Result.FDocument := FDocument; + Result.FHandle := Attachment; +end; + +procedure TPdfAttachmentList.Delete(Index: Integer); +begin + FDocument.CheckActive; + if FPDFDoc_DeleteAttachment(FDocument.Handle, Index) = 0 then + raise EPdfException.CreateResFmt(@RsPdfCannotDeleteAttachmnent, [Index]); +end; + +function TPdfAttachmentList.Add(const Name: string): TPdfAttachment; +begin + FDocument.CheckActive; + Result.FDocument := FDocument; + Result.FHandle := FPDFDoc_AddAttachment(FDocument.Handle, PWideChar(Name)); + if Result.FHandle = nil then + raise EPdfException.CreateResFmt(@RsPdfCannotAddAttachmnent, [Name]); +end; + +function TPdfAttachmentList.IndexOf(const Name: string): Integer; +begin + for Result := 0 to Count - 1 do + if Items[Result].Name = Name then + Exit; + Result := -1; +end; + + +{ TPdfAttachment } + +function TPdfAttachment.GetName: string; +var + ByteLen: LongWord; +begin + CheckValid; + ByteLen := FPDFAttachment_GetName(Handle, nil, 0); // UTF 16 including #0 terminator in byte size + if ByteLen <= 2 then + Result := '' + else + begin + SetLength(Result, ByteLen div SizeOf(WideChar) - 1); + FPDFAttachment_GetName(FHandle, PWideChar(Result), ByteLen); + end; +end; + +procedure TPdfAttachment.CheckValid; +begin + if FDocument <> nil then + FDocument.CheckActive; +end; + +procedure TPdfAttachment.SetContent(ABytes: PByte; Count: Integer); +begin + CheckValid; + if FPDFAttachment_SetFile(FHandle, FDocument.Handle, ABytes, Count) = 0 then + raise EPdfException.CreateResFmt(@RsPdfCannotSetAttachmentContent, [Name]); +end; + +procedure TPdfAttachment.SetContent(const Value: RawByteString); +begin + if Value = '' then + SetContent(nil, 0) + else + SetContent(PByte(PAnsiChar(Value)), Length(Value) * SizeOf(AnsiChar)); +end; + +procedure TPdfAttachment.SetContent(const Value: string; Encoding: TEncoding = nil); +begin + CheckValid; + if Value = '' then + SetContent(nil, 0) + else if (Encoding = nil) or (Encoding = TEncoding.UTF8) then + SetContent(UTF8Encode(Value)) + else + SetContent(Encoding.GetBytes(Value)); +end; + +procedure TPdfAttachment.SetContent(const ABytes: TBytes; Index: NativeInt; Count: Integer); +var + Len: NativeInt; +begin + CheckValid; + + Len := Length(ABytes); + if Index >= Len then + raise EPdfArgumentOutOfRange.CreateResFmt(@RsArgumentsOutOfRange, ['Index', Index]); + if Index + Count > Len then + raise EPdfArgumentOutOfRange.CreateResFmt(@RsArgumentsOutOfRange, ['Count', Count]); + + if Count = 0 then + SetContent(nil, 0) + else + SetContent(@ABytes[Index], Count); +end; + +procedure TPdfAttachment.SetContent(const ABytes: TBytes); +begin + SetContent(ABytes, 0, Length(ABytes)); +end; + +procedure TPdfAttachment.LoadFromStream(Stream: TStream); +var + StreamPos, StreamSize: Int64; + Buf: PByte; + Count: Integer; +begin + CheckValid; + + StreamPos := Stream.Position; + StreamSize := Stream.Size; + Count := StreamSize - StreamPos; + if Count = 0 then + SetContent(nil, 0) + else + begin + if Stream is TCustomMemoryStream then // direct access to the memory + begin + SetContent(PByte(TCustomMemoryStream(Stream).Memory) + StreamPos, Count); + Stream.Position := StreamSize; // simulate the ReadBuffer call + end + else + begin + if Count = 0 then + SetContent(nil, 0) + else + begin + GetMem(Buf, Count); + try + Stream.ReadBuffer(Buf^, Count); + SetContent(Buf, Count); + finally + FreeMem(Buf); + end; + end; + end; + end; +end; + +procedure TPdfAttachment.LoadFromFile(const FileName: string); +var + Stream: TFileStream; +begin + CheckValid; + + Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite); + try + LoadFromStream(Stream); + finally + Stream.Free; + end; +end; + +function TPdfAttachment.HasKey(const Key: string): Boolean; +begin + CheckValid; + Result := FPDFAttachment_HasKey(FHandle, PAnsiChar(UTF8Encode(Key))) <> 0; +end; + +function TPdfAttachment.GetValueType(const Key: string): TPdfObjectType; +begin + CheckValid; + Result := TPdfObjectType(FPDFAttachment_GetValueType(FHandle, PAnsiChar(UTF8Encode(Key)))); +end; + +procedure TPdfAttachment.SetKeyValue(const Key, Value: string); +begin + CheckValid; + if FPDFAttachment_SetStringValue(FHandle, PAnsiChar(UTF8Encode(Key)), PWideChar(Value)) = 0 then + raise EPdfException.CreateRes(@RsPdfAttachmentContentNotSet); +end; + +function TPdfAttachment.GetKeyValue(const Key: string): string; +var + ByteLen: LongWord; + Utf8Key: UTF8String; +begin + CheckValid; + Utf8Key := UTF8Encode(Key); + ByteLen := FPDFAttachment_GetStringValue(FHandle, PAnsiChar(Utf8Key), nil, 0); + if ByteLen = 0 then + raise EPdfException.CreateRes(@RsPdfAttachmentContentNotSet); + + if ByteLen <= 2 then + Result := '' + else + begin + SetLength(Result, (ByteLen div SizeOf(WideChar) - 1)); + FPDFAttachment_GetStringValue(FHandle, PAnsiChar(Utf8Key), PWideChar(Result), ByteLen); + end; +end; + +function TPdfAttachment.GetContentSize: Integer; +var + OutBufLen: LongWord; +begin + CheckValid; + if FPDFAttachment_GetFile(FHandle, nil, 0, OutBufLen) = 0 then + Result := 0 + else + Result := Integer(OutBufLen); +end; + +function TPdfAttachment.HasContent: Boolean; +var + OutBufLen: LongWord; +begin + CheckValid; + Result := FPDFAttachment_GetFile(FHandle, nil, 0, OutBufLen) <> 0; +end; + +procedure TPdfAttachment.SaveToFile(const FileName: string); +var + Stream: TStream; +begin + CheckValid; + + Stream := TFileStream.Create(FileName, fmCreate or fmShareDenyWrite); + try + SaveToStream(Stream); + finally + Stream.Free; + end; +end; + +procedure TPdfAttachment.SaveToStream(Stream: TStream); +var + Size: Integer; + OutBufLen: LongWord; + StreamPos: Int64; + Buf: PByte; +begin + Size := ContentSize; + + if Size > 0 then + begin + if Stream is TCustomMemoryStream then // direct access to the memory + begin + StreamPos := Stream.Position; + if StreamPos + Size > Stream.Size then + Stream.Size := StreamPos + Size; // allocate enough memory + Stream.Position := StreamPos; + + FPDFAttachment_GetFile(FHandle, PByte(TCustomMemoryStream(Stream).Memory) + StreamPos, Size, OutBufLen); + Stream.Position := StreamPos + Size; // simulate Stream.WriteBuffer + end + else + begin + GetMem(Buf, Size); + try + FPDFAttachment_GetFile(FHandle, Buf, Size, OutBufLen); + Stream.WriteBuffer(Buf^, Size); + finally + FreeMem(Buf); + end; + end; + end; +end; + +procedure TPdfAttachment.GetContent(var Value: string; Encoding: TEncoding); +var + Size: Integer; + OutBufLen: LongWord; + Buf: PByte; +begin + Size := ContentSize; + if Size <= 0 then + Value := '' + else if Encoding = TEncoding.Unicode then // no conversion needed + begin + SetLength(Value, Size div SizeOf(WideChar)); + FPDFAttachment_GetFile(FHandle, PWideChar(Value), Size, OutBufLen); + end + else + begin + if Encoding = nil then + Encoding := TEncoding.UTF8; + + GetMem(Buf, Size); + try + FPDFAttachment_GetFile(FHandle, Buf, Size, OutBufLen); + SetLength(Value, TEncodingAccess(Encoding).GetMemCharCount(Buf, Size)); + if Value <> '' then + TEncodingAccess(Encoding).GetMemChars(Buf, Size, PWideChar(Value), Length(Value)); + finally + FreeMem(Buf); + end; + end; +end; + +procedure TPdfAttachment.GetContent(var Value: RawByteString); +var + Size: Integer; + OutBufLen: LongWord; +begin + Size := ContentSize; + + if Size <= 0 then + Value := '' + else + begin + SetLength(Value, Size); + FPDFAttachment_GetFile(FHandle, PAnsiChar(Value), Size, OutBufLen); + end; +end; + +procedure TPdfAttachment.GetContent(Buffer: PByte); +var + OutBufLen: LongWord; +begin + FPDFAttachment_GetFile(FHandle, Buffer, ContentSize, OutBufLen); +end; + +procedure TPdfAttachment.GetContent(var ABytes: TBytes); +var + Size: Integer; + OutBufLen: LongWord; +begin + Size := ContentSize; + + if Size <= 0 then + ABytes := nil + else + begin + SetLength(ABytes, Size); + FPDFAttachment_GetFile(FHandle, @ABytes[0], Size, OutBufLen); + end; +end; + +function TPdfAttachment.GetContentAsBytes: TBytes; +begin + GetContent(Result); +end; + +function TPdfAttachment.GetContentAsRawByteString: RawByteString; +begin + GetContent(Result); +end; + +function TPdfAttachment.GetContentAsString(Encoding: TEncoding): string; +begin + GetContent(Result, Encoding); +end; + + +{ TPdfAnnotationList } + +constructor TPdfAnnotationList.Create(APage: TPdfPage); +begin + inherited Create; + FPage := APage; + FItems := TObjectList.Create; +end; + +destructor TPdfAnnotationList.Destroy; +begin + FreeAndNil(FFormFields); + FreeAndNil(FItems); // closes all annotations + inherited Destroy; +end; + +procedure TPdfAnnotationList.CloseAnnotations; +begin + FreeAndNil(FFormFields); + FreeAndNil(FItems); // closes all annotations + FItems := TObjectList.Create; +end; + +function TPdfAnnotationList.GetCount: Integer; +begin + Result := FPDFPage_GetAnnotCount(FPage.Handle); +end; + +function TPdfAnnotationList.GetItem(Index: Integer): TPdfAnnotation; +var + Annot: FPDF_ANNOTATION; +begin + FPage.FDocument.CheckActive; + + if (Index < 0) or (Index >= FItems.Count) or (FItems[Index] = nil) then + begin + Annot := FPDFPage_GetAnnot(FPage.Handle, Index); + if Annot = nil then + raise EPdfArgumentOutOfRange.CreateResFmt(@RsArgumentsOutOfRange, ['Index']); + + while FItems.Count <= Index do + FItems.Add(nil); + FItems[Index] := TPdfAnnotation.Create(FPage, Annot); + end; + Result := FItems[Index] as TPdfAnnotation; +end; + +procedure TPdfAnnotationList.DestroyingItem(Item: TPdfAnnotation); +var + Index: Integer; +begin + if (Item <> nil) and (FItems <> nil) then + begin + Index := FItems.IndexOf(Item); + if Index <> -1 then + FItems.List[Index] := nil; // Bypass the Items[] setter to not destroy the Item twice + end; +end; + +procedure TPdfAnnotationList.DestroyingFormField(FormField: TPdfFormField); +begin + if FFormFields <> nil then + FFormFields.DestroyingItem(FormField); +end; + +function TPdfAnnotationList.GetFormFields: TPdfFormFieldList; +begin + if FFormFields = nil then + FFormFields := TPdfFormFieldList.Create(Self); + Result := FFormFields; +end; + +function TPdfAnnotationList.GetAnnotationsLoaded: Boolean; +begin + Result := FItems.Count > 0; +end; + +function TPdfAnnotationList.NewTextAnnotation(const Text: string; const R: TPdfRect): Boolean; +var + Annot: FPDF_ANNOTATION; + SingleR: FS_RECTF; +begin + FPage.FDocument.CheckActive; + SingleR.left := R.Left; + SingleR.right := R.Right; + // Page coordinates are upside down + if R.Top < R.Bottom then + begin + SingleR.top := R.Bottom; + SingleR.bottom := R.Top; + end + else + begin + SingleR.top := R.Top; + SingleR.bottom := R.Bottom; + end; + + + Annot := FPDFPage_CreateAnnot(FPage.Handle, FPDF_ANNOT_TEXT); + Result := Annot <> nil; + if Result then + begin + FPDFAnnot_SetRect(Annot, @SingleR); + FPDFAnnot_SetStringValue(Annot, 'Contents', PWideChar(Text)); + end; +end; + +function TPdfAnnotationList.FindLink(Link: FPDF_LINK): TPdfAnnotation; +var + I: Integer; +begin + for I := 0 to Count - 1 do + begin + Result := Items[I]; + if (Result.IsLink) and (FPDFAnnot_GetLink(Result.Handle) = Link) then + Exit; + end; + Result := nil; +end; + + +{ TPdfFormFieldList } + +constructor TPdfFormFieldList.Create(AAnnotations: TPdfAnnotationList); +var + I: Integer; +begin + inherited Create; + FItems := TList.Create; + + for I := 0 to AAnnotations.Count - 1 do + if AAnnotations[I].IsFormField then + FItems.Add(AAnnotations[I].FormField); +end; + +destructor TPdfFormFieldList.Destroy; +begin + FItems.Free; + inherited Destroy; +end; + +function TPdfFormFieldList.GetCount: Integer; +begin + Result := FItems.Count; +end; + +function TPdfFormFieldList.GetItem(Index: Integer): TPdfFormField; +begin + Result := TObject(FItems[Index]) as TPdfFormField; +end; + +procedure TPdfFormFieldList.DestroyingItem(Item: TPdfFormField); +begin + if (Item <> nil) and (FItems <> nil) then + FItems.Extract(Item); +end; + + +{ TPdfAnnotation } + +constructor TPdfAnnotation.Create(APage: TPdfPage; AHandle: FPDF_ANNOTATION); +var + Action: FPDF_ACTION; +begin + inherited Create; + FPage := APage; + FHandle := AHandle; + + FSubType := FPDFAnnot_GetSubtype(FHandle); + FLinkType := altUnsupported; + case FSubType of + FPDF_ANNOT_WIDGET, + FPDF_ANNOT_XFAWIDGET: + FFormField := TPdfFormField.Create(Self); + + FPDF_ANNOT_LINK: + begin + Action := GetPdfLinkAction; + if Action <> nil then + FLinkType := TPdfAnnotationLinkType(FPDFAction_GetType(Action)) + else + begin + // If we have a Dest-Link then we treat it like a Goto Action-Link (see GetLinkGotoDestination) + FLinkDest := FPDFLink_GetDest(FPage.FDocument.Handle, FPDFAnnot_GetLink(Handle)); + if FLinkDest <> nil then + FLinkType := altGoto; + end; + end; + end; +end; + +destructor TPdfAnnotation.Destroy; +begin + FreeAndNil(FFormField); + if FHandle <> nil then + begin + FPDFPage_CloseAnnot(FHandle); + FHandle := nil; + end; + if FPage.FAnnotations <> nil then + FPage.FAnnotations.DestroyingItem(Self); + inherited Destroy; +end; + +function TPdfAnnotation.GetPdfLinkAction: FPDF_ACTION; +var + Link: FPDF_LINK; +begin + Result := nil; + if FSubType = FPDF_ANNOT_LINK then + begin + Link := FPDFAnnot_GetLink(Handle); + if Link <> nil then + Result := FPDFLink_GetAction(Link); + end; +end; + +function TPdfAnnotation.IsLink: Boolean; +begin + Result := FSubType = FPDF_ANNOT_LINK; +end; + +function TPdfAnnotation.IsFormField: Boolean; +begin + Result := FFormField <> nil; +end; + +function TPdfAnnotation.GetFormField: TPdfFormField; +begin + if FFormField = nil then + raise EPdfException.CreateRes(@RsPdfAnnotationNotAFormFieldError); + Result := FFormField; +end; + +function TPdfAnnotation.GetAnnotationRect: TPdfRect; +var + R: FS_RECTF; +begin + if FPDFAnnot_GetRect(Handle, @R) <> 0 then + Result := TPdfRect.New(R.left, R.top, R.right, R.bottom) + else + Result := TPdfRect.Empty; +end; + +function TPdfAnnotation.GetLinkUri: string; +begin + if LinkType = altURI then + Result := FPage.GetPdfActionUriPath(GetPdfLinkAction) + else + Result := ''; +end; + +function TPdfAnnotation.GetLinkFileName: string; +begin + if LinkType in [altRemoteGoto, altLaunch, altEmbeddedGoto] then // PDFium documentation is missing the PDFACTION_EMBEDDEDGOTO part. + Result := FPage.GetPdfActionFilePath(GetPdfLinkAction) + else + Result := ''; +end; + +function TPdfAnnotation.GetLinkGotoDestination(var LinkGotoDestination: TPdfLinkGotoDestination; ARemoteDocument: TPdfDocument): Boolean; +var + Action: FPDF_ACTION; + Dest: FPDF_DEST; + Doc: TPdfDocument; + PageIndex: Integer; + HasXVal, HasYVal, HasZoomVal: FPDF_BOOL; + X, Y, Zoom: FS_FLOAT; + ViewKind: TPdfLinkGotoDestinationViewKind; + NumViewParams: LongWord; + ViewParams: TPdfFloatArray; +begin + Result := False; + + Action := GetPdfLinkAction; + if ((Action <> nil) or (FLinkDest <> nil)) and (LinkType in [altGoto, altRemoteGoto, altEmbeddedGoto]) then + begin + Doc := FPage.FDocument; + if LinkType = altRemoteGoto then + begin + // For RemoteGoto the FPDFAction_GetDest function must be called with the remote document + if ARemoteDocument <> nil then + raise EPdfException.CreateRes(@RsPdfAnnotationLinkRemoteGotoRequiresRemoteDocument); + ARemoteDocument.CheckActive; + + Doc := ARemoteDocument; + end; + + // If we have a Dest-Link instead of a Goto Action-Link we treat it as if it was a Goto Action-Link + if FLinkDest <> nil then + Dest := FLinkDest + else + Dest := FPDFAction_GetDest(Doc.Handle, Action); + + // Extract the information + if Dest <> nil then + begin + PageIndex := FPDFDest_GetDestPageIndex(Doc.Handle, Dest); + if PageIndex <> -1 then + begin + if FPDFDest_GetLocationInPage(Dest, HasXVal, HasYVal, HasZoomVal, X, Y, Zoom) <> 0 then + begin + SetLength(ViewParams, 4); // max. 4 params + NumViewParams := 4; + ViewKind := TPdfLinkGotoDestinationViewKind(FPDFDest_GetView(Dest, @NumViewParams, @ViewParams[0])); + if NumViewParams > 4 then // range check + NumViewParams := 4; + SetLength(ViewParams, NumViewParams); + + LinkGotoDestination := TPdfLinkGotoDestination.Create( + PageIndex, + HasXVal <> 0, HasYVal <> 0, HasZoomVal <> 0, + X, Y, Zoom, + ViewKind, ViewParams + ); + Result := True; + end; + end; + end; + end; +end; + + +{ TPdfFormField } + +constructor TPdfFormField.Create(AAnnotation: TPdfAnnotation); +begin + inherited Create; + FAnnotation := AAnnotation; + FPage := FAnnotation.FPage; + FHandle := FAnnotation.Handle; +end; + +destructor TPdfFormField.Destroy; +begin + FAnnotation.FFormField := nil; + FAnnotation.FPage.Annotations.DestroyingFormField(Self); + inherited Destroy; +end; + +function TPdfFormField.IsXFAFormField: Boolean; +begin + Result := IS_XFA_FORMFIELD(FPDFAnnot_GetFormFieldType(FPage.FDocument.FormHandle, Handle)); +end; + +function TPdfFormField.GetReadOnly: Boolean; +begin + Result := fffReadOnly in Flags; +end; + +function TPdfFormField.GetFlags: TPdfFormFieldFlags; +var + FormFlags: Integer; +begin + FormFlags := FPDFAnnot_GetFormFieldFlags(FPage.FDocument.FormHandle, Handle); + + Result := []; + if FormFlags <> FPDF_FORMFLAG_NONE then + begin + if FormFlags and FPDF_FORMFLAG_READONLY <> 0 then + Include(Result, fffReadOnly); + if FormFlags and FPDF_FORMFLAG_REQUIRED <> 0 then + Include(Result, fffRequired); + if FormFlags and FPDF_FORMFLAG_NOEXPORT <> 0 then + Include(Result, fffNoExport); + + if FormFlags and FPDF_FORMFLAG_TEXT_MULTILINE <> 0 then + Include(Result, fffTextMultiLine); + if FormFlags and FPDF_FORMFLAG_TEXT_PASSWORD <> 0 then + Include(Result, fffTextPassword); + + if FormFlags and FPDF_FORMFLAG_CHOICE_COMBO <> 0 then + Include(Result, fffChoiceCombo); + if FormFlags and FPDF_FORMFLAG_CHOICE_EDIT <> 0 then + Include(Result, fffChoiceEdit); + if FormFlags and FPDF_FORMFLAG_CHOICE_MULTI_SELECT <> 0 then + Include(Result, fffChoiceMultiSelect); + end; +end; + +function TPdfFormField.GetName: string; +var + Len: Integer; +begin + Len := FPDFAnnot_GetFormFieldName(FPage.FDocument.FormHandle, Handle, nil, 0) div SizeOf(WideChar) - 1; + if Len > 0 then + begin + SetLength(Result, Len); + FPDFAnnot_GetFormFieldName(FPage.FDocument.FormHandle, Handle, PWideChar(Result), (Len + 1) * SizeOf(WideChar)); + end + else + Result := ''; +end; + +function TPdfFormField.GetAlternateName: string; +var + Len: Integer; +begin + Len := FPDFAnnot_GetFormFieldAlternateName(FPage.FDocument.FormHandle, Handle, nil, 0) div SizeOf(WideChar) - 1; + if Len > 0 then + begin + SetLength(Result, Len); + FPDFAnnot_GetFormFieldAlternateName(FPage.FDocument.FormHandle, Handle, PWideChar(Result), (Len + 1) * SizeOf(WideChar)); + end + else + Result := ''; +end; + +function TPdfFormField.GetFieldType: TPdfFormFieldType; +begin + Result := TPdfFormFieldType(FPDFAnnot_GetFormFieldType(FPage.FDocument.FormHandle, Handle)); + if (Result < Low(TPdfFormFieldType)) or (Result > High(TPdfFormFieldType)) then + Result := fftUnknown; +end; + +function TPdfFormField.GetValue: string; +var + Len: Integer; +begin + Len := FPDFAnnot_GetFormFieldValue(FPage.FDocument.FormHandle, Handle, nil, 0) div SizeOf(WideChar) - 1; + if Len > 0 then + begin + SetLength(Result, Len); + FPDFAnnot_GetFormFieldValue(FPage.FDocument.FormHandle, Handle, PWideChar(Result), (Len + 1) * SizeOf(WideChar)); + end + else + Result := ''; +end; + +function TPdfFormField.GetExportValue: string; +var + Len: Integer; +begin + Len := FPDFAnnot_GetFormFieldExportValue(FPage.FDocument.FormHandle, Handle, nil, 0) div SizeOf(WideChar) - 1; + if Len > 0 then + begin + SetLength(Result, Len); + FPDFAnnot_GetFormFieldExportValue(FPage.FDocument.FormHandle, Handle, PWideChar(Result), (Len + 1) * SizeOf(WideChar)); + end + else + Result := ''; +end; + +function TPdfFormField.GetOptionCount: Integer; +begin + Result := FPDFAnnot_GetOptionCount(FPage.FDocument.FormHandle, Handle); + if Result < 0 then // annotation types that don't support options will return -1 + Result := 0; +end; + +function TPdfFormField.GetOptionLabel(Index: Integer): string; +var + Len: Integer; +begin + Len := FPDFAnnot_GetOptionLabel(FPage.FDocument.FormHandle, Handle, Index, nil, 0) div SizeOf(WideChar) - 1; + if Len > 0 then + begin + SetLength(Result, Len); + FPDFAnnot_GetOptionLabel(FPage.FDocument.FormHandle, Handle, Index, PWideChar(Result), (Len + 1) * SizeOf(WideChar)); + end + else + Result := ''; +end; + +function TPdfFormField.IsOptionSelected(OptionIndex: Integer): Boolean; +begin + Result := FPDFAnnot_IsOptionSelected(FPage.FDocument.FormHandle, Handle, OptionIndex) <> 0; +end; + +function TPdfFormField.GetChecked: Boolean; +begin + Result := FPDFAnnot_IsChecked(FPage.FDocument.FormHandle, Handle) <> 0; +end; + +function TPdfFormField.GetControlCount: Integer; +begin + Result := FPDFAnnot_GetFormControlCount(FPage.FDocument.FormHandle, Handle); +end; + +function TPdfFormField.GetControlIndex: Integer; +begin + Result := FPDFAnnot_GetFormControlIndex(FPage.FDocument.FormHandle, Handle); +end; + +function TPdfFormField.BeginEditFormField: FPDF_ANNOTATION; +var + AnnotPageIndex: Integer; +begin + FPage.FDocument.CheckActive; + + // Obtain the currently focused form field/annotation so that we can restore the focus after + // editing our form field. + if FORM_GetFocusedAnnot(FPage.FDocument.FormHandle, AnnotPageIndex, Result) = 0 then + Result := nil; +end; + +procedure TPdfFormField.EndEditFormField(LastFocusedAnnot: FPDF_ANNOTATION); +begin + // Restore the focus to the form field/annotation that had the focus before changing our form field. + // If no previous form field was focused, kill the focus. + if LastFocusedAnnot <> nil then + begin + if FORM_SetFocusedAnnot(FPage.FDocument.FormHandle, Handle) = 0 then + FORM_ForceToKillFocus(FPage.FDocument.FormHandle); + FPDFPage_CloseAnnot(LastFocusedAnnot); + end + else + FORM_ForceToKillFocus(FPage.FDocument.FormHandle); +end; + +procedure TPdfFormField.SetValue(const Value: string); +var + LastFocusedAnnot: FPDF_ANNOTATION; +begin + FPage.FDocument.CheckActive; + + if not ReadOnly then + begin + LastFocusedAnnot := BeginEditFormField(); + try + if FORM_SetFocusedAnnot(FPage.FDocument.FormHandle, Handle) <> 0 then + begin + FORM_SelectAllText(FPage.FDocument.FormHandle, FPage.Handle); + FORM_ReplaceSelection(FPage.FDocument.FormHandle, FPage.Handle, PWideChar(Value)); + end; + finally + EndEditFormField(LastFocusedAnnot); + end; + end; +end; + +function TPdfFormField.SelectComboBoxOption(OptionIndex: Integer): Boolean; +begin + Result := SelectListBoxOption(OptionIndex, True); +end; + +function TPdfFormField.SelectListBoxOption(OptionIndex: Integer; Selected: Boolean): Boolean; +var + LastFocusedAnnot: FPDF_ANNOTATION; +begin + FPage.FDocument.CheckActive; + + Result := False; + if not ReadOnly then + begin + LastFocusedAnnot := BeginEditFormField(); + try + if FORM_SetFocusedAnnot(FPage.FDocument.FormHandle, Handle) <> 0 then + Result := FORM_SetIndexSelected(FPage.FDocument.FormHandle, FPage.Handle, OptionIndex, Ord(Selected <> False)) <> 0; + finally + EndEditFormField(LastFocusedAnnot); + end; + end; +end; + +procedure TPdfFormField.SetChecked(const Value: Boolean); +var + LastFocusedAnnot: FPDF_ANNOTATION; +begin + FPage.FDocument.CheckActive; + + if not ReadOnly and (FieldType in [fftCheckBox, fftRadioButton, fftXFACheckBox]) then + begin + if Value <> Checked then + begin + LastFocusedAnnot := BeginEditFormField(); + try + if FORM_SetFocusedAnnot(FPage.FDocument.FormHandle, Handle) <> 0 then + begin + // Toggle the RadioButton/Checkbox by emulating "pressing the space bar". + FORM_OnKeyDown(FPage.FDocument.FormHandle, FPage.Handle, Ord(' '), 0); + FORM_OnChar(FPage.FDocument.FormHandle, FPage.Handle, Ord(' '), 0); + FORM_OnKeyUp(FPage.FDocument.FormHandle, FPage.Handle, Ord(' '), 0); + end; + finally + EndEditFormField(LastFocusedAnnot); + end; + end; + end; +end; + +procedure TPdfFormField.SetFlags(const Value: TPdfFormFieldFlags); +var + FormFlags: Integer; +begin + FPage.FDocument.CheckActive; + + FormFlags := FPDF_FORMFLAG_NONE; + if Value <> [] then + begin + if fffReadOnly in Value then + FormFlags := FormFlags or FPDF_FORMFLAG_READONLY; + if fffRequired in Value then + FormFlags := FormFlags or FPDF_FORMFLAG_REQUIRED; + if fffNoExport in Value then + FormFlags := FormFlags or FPDF_FORMFLAG_NOEXPORT; + + if fffTextMultiLine in Value then + FormFlags := FormFlags or FPDF_FORMFLAG_TEXT_MULTILINE; + if fffTextPassword in Value then + FormFlags := FormFlags or FPDF_FORMFLAG_TEXT_PASSWORD; + + if fffChoiceCombo in Value then + FormFlags := FormFlags or FPDF_FORMFLAG_CHOICE_COMBO; + if fffChoiceEdit in Value then + FormFlags := FormFlags or FPDF_FORMFLAG_CHOICE_EDIT; + if fffChoiceMultiSelect in Value then + FormFlags := FormFlags or FPDF_FORMFLAG_CHOICE_MULTI_SELECT; + end; + + FPDFAnnot_SetFormFieldFlags(FPage.FDocument.FormHandle, Handle, FormFlags); +end; + +{ TPdfLinkGotoDestination } + +constructor TPdfLinkGotoDestination.Create(APageIndex: Integer; AXValid, AYValid, AZoomValid: Boolean; + AX, AY, AZoom: Single; AViewKind: TPdfLinkGotoDestinationViewKind; const AViewParams: TPdfFloatArray); +begin + inherited Create; + FPageIndex := APageIndex; + + FXValid := AXValid; + FYValid := AYValid; + FZoomValid := AZoomValid; + + FX := AX; + FY := AY; + FZoom := AZoom; + + FViewKind := AViewKind; + FViewParams := AViewParams; +end; + + +{ TPdfLinkInfo } + +constructor TPdfLinkInfo.Create(ALinkAnnotation: TPdfAnnotation; const AWebLinkUrl: string); +begin + inherited Create; + FLinkAnnotation := ALinkAnnotation; + FWebLinkUrl := AWebLinkUrl; +end; + +function TPdfLinkInfo.IsAnnontation: Boolean; +begin + Result := FLinkAnnotation <> nil; +end; + +function TPdfLinkInfo.IsWebLink: Boolean; +begin + Result := FLinkAnnotation = nil; +end; + +function TPdfLinkInfo.GetLinkFileName: string; +begin + if FLinkAnnotation <> nil then + Result := FLinkAnnotation.LinkFileName; +end; + +function TPdfLinkInfo.GetLinkType: TPdfAnnotationLinkType; +begin + if FLinkAnnotation <> nil then + Result := FLinkAnnotation.LinkType + else if FWebLinkUrl <> '' then + Result := altURI + else + Result := altUnsupported; +end; + +function TPdfLinkInfo.GetLinkUri: string; +begin + if FLinkAnnotation <> nil then + Result := FLinkAnnotation.LinkUri + else + Result := FWebLinkUrl; +end; + +function TPdfLinkInfo.GetLinkGotoDestination(var LinkGotoDestination: TPdfLinkGotoDestination; + ARemoteDocument: TPdfDocument): Boolean; +begin + if FLinkAnnotation <> nil then + Result := FLinkAnnotation.GetLinkGotoDestination(LinkGotoDestination, ARemoteDocument) + else + Result := False; +end; + + +{ TPdfPageWebLinksInfo } + +constructor TPdfPageWebLinksInfo.Create(APage: TPdfPage); +begin + inherited Create; + FPage := APage; + GetPageWebLinks; +end; + +procedure TPdfPageWebLinksInfo.GetPageWebLinks; +var + LinkIndex, LinkCount: Integer; + RectIndex, RectCount: Integer; +begin + if FPage <> nil then + begin + LinkCount := FPage.GetWebLinkCount; + SetLength(FWebLinksRects, LinkCount); + for LinkIndex := 0 to LinkCount - 1 do + begin + RectCount := FPage.GetWebLinkRectCount(LinkIndex); + SetLength(FWebLinksRects[LinkIndex], RectCount); + for RectIndex := 0 to RectCount - 1 do + FWebLinksRects[LinkIndex][RectIndex] := FPage.GetWebLinkRect(LinkIndex, RectIndex); + end; + end; +end; + +function TPdfPageWebLinksInfo.GetWebLinkIndex(X, Y: Double): Integer; +var + RectIndex: Integer; + Pt: TPdfPoint; +begin + if FPage <> nil then + begin + Pt.X := X; + Pt.Y := Y; + for Result := 0 to Length(FWebLinksRects) - 1 do + for RectIndex := 0 to Length(FWebLinksRects[Result]) - 1 do + if FWebLinksRects[Result][RectIndex].PtIn(Pt) then + Exit; + end; + Result := -1; +end; + +function TPdfPageWebLinksInfo.GetCount: Integer; +begin + Result := Length(FWebLinksRects); +end; + +function TPdfPageWebLinksInfo.GetRect(Index: Integer): TPdfRectArray; +begin + Result := FWebLinksRects[Index]; +end; + +function TPdfPageWebLinksInfo.GetURL(Index: Integer): string; +begin + Result := FPage.GetWebLinkURL(Index); +end; + +function TPdfPageWebLinksInfo.IsWebLinkAt(X, Y: Double): Boolean; +begin + Result := GetWebLinkIndex(X, Y) <> -1; +end; + +function TPdfPageWebLinksInfo.IsWebLinkAt(X, Y: Double; var Url: string): Boolean; +var + Index: Integer; +begin + Index := GetWebLinkIndex(X, Y); + Result := Index <> -1; + if Result then + Url := FPage.GetWebLinkURL(Index) + else + Url := ''; +end; + +{$IFDEF MSWINDOWS} +{ TPdfDocumentPrinter } + +constructor TPdfDocumentPrinter.Create; +begin + inherited Create; + FFitPageToPrintArea := True; +end; + +function TPdfDocumentPrinter.IsPortraitOrientation(AWidth, AHeight: Integer): Boolean; +begin + Result := AHeight > AWidth; +end; + +procedure TPdfDocumentPrinter.GetPrinterBounds; +begin + FPaperSize.cx := GetDeviceCaps(FPrinterDC, PHYSICALWIDTH); + FPaperSize.cy := GetDeviceCaps(FPrinterDC, PHYSICALHEIGHT); + + FPrintArea.cx := GetDeviceCaps(FPrinterDC, HORZRES); + FPrintArea.cy := GetDeviceCaps(FPrinterDC, VERTRES); + + FMargins.X := GetDeviceCaps(FPrinterDC, PHYSICALOFFSETX); + FMargins.Y := GetDeviceCaps(FPrinterDC, PHYSICALOFFSETY); +end; + +function TPdfDocumentPrinter.BeginPrint(const AJobTitle: string): Boolean; +begin + Inc(FBeginPrintCounter); + if FBeginPrintCounter = 1 then + begin + Result := PrinterStartDoc(AJobTitle); + if Result then + begin + FPrinterDC := GetPrinterDC; + + GetPrinterBounds; + FPrintPortraitOrientation := IsPortraitOrientation(FPaperSize.cx, FPaperSize.cy); + end + else + begin + FPrinterDC := 0; + Dec(FBeginPrintCounter); + end; + end + else + Result := True; +end; + +procedure TPdfDocumentPrinter.EndPrint; +begin + Dec(FBeginPrintCounter); + if FBeginPrintCounter = 0 then + begin + if FPrinterDC <> 0 then + begin + FPrinterDC := 0; + PrinterEndDoc; + end; + end; +end; + +function TPdfDocumentPrinter.Print(ADocument: TPdfDocument): Boolean; +begin + if ADocument <> nil then + Result := Print(ADocument, 0, ADocument.PageCount - 1) + else + Result := False; +end; + +function TPdfDocumentPrinter.Print(ADocument: TPdfDocument; AFromPageIndex, AToPageIndex: Integer): Boolean; +var + PageIndex: Integer; + WasPageLoaded: Boolean; + PdfPage: TPdfPage; + PagePortraitOrientation: Boolean; + X, Y, W, H: Integer; + PrintedPageNum, PrintPageCount: Integer; +begin + Result := False; + if ADocument = nil then + Exit; + + if AFromPageIndex < 0 then + raise EPdfArgumentOutOfRange.CreateResFmt(@RsArgumentsOutOfRange, ['FromPage', AFromPageIndex]); + if (AToPageIndex < AFromPageIndex) or (AToPageIndex >= ADocument.PageCount) then + raise EPdfArgumentOutOfRange.CreateResFmt(@RsArgumentsOutOfRange, ['ToPage', AToPageIndex]); + + PrintedPageNum := 0; + PrintPageCount := AToPageIndex - AFromPageIndex + 1; + + if BeginPrint then + begin + try + if ADocument.FForm <> nil then + FORM_DoDocumentAAction(ADocument.FForm, FPDFDOC_AACTION_WP); // BeforePrint + + for PageIndex := AFromPageIndex to AToPageIndex do + begin + PdfPage := nil; + WasPageLoaded := ADocument.IsPageLoaded(PageIndex); + try + PdfPage := ADocument.Pages[PageIndex]; + PagePortraitOrientation := IsPortraitOrientation(Trunc(PdfPage.Width), Trunc(PdfPage.Height)); + + if FitPageToPrintArea then + begin + X := 0; + Y := 0; + W := FPrintArea.cx; + H := FPrintArea.cy; + end + else + begin + X := -FMargins.X; + Y := -FMargins.Y; + W := FPaperSize.cx; + H := FPaperSize.cy; + end; + + if PagePortraitOrientation <> FPrintPortraitOrientation then + begin + SwapInts(X, Y); + SwapInts(W, H); + end; + + // Print page + PrinterStartPage; + try + if (W > 0) and (H > 0) then + InternPrintPage(PdfPage, X, Y, W, H); + finally + PrinterEndPage; + end; + Inc(PrintedPageNum); + if Assigned(OnPrintStatus) then + OnPrintStatus(Self, PrintedPageNum, PrintPageCount); + finally + if not WasPageLoaded and (PdfPage <> nil) then + PdfPage.Close; // release memory + end; + if ADocument.FForm <> nil then + FORM_DoDocumentAAction(ADocument.FForm, FPDFDOC_AACTION_DP); // AfterPrint + end; + finally + EndPrint; + end; + Result := True; + end; +end; + +procedure TPdfDocumentPrinter.InternPrintPage(APage: TPdfPage; X, Y, Width, Height: Double); + + function RoundToInt(Value: Double): Integer; + var + F: Double; + begin + Result := Trunc(Value); + F := Frac(Value); + if F < 0 then + begin + if F <= -0.5 then + Result := Result - 1; + end + else if F >= 0.5 then + Result := Result + 1; + end; + +var + PageWidth, PageHeight: Double; + PageScale, PrintScale: Double; + ScaledWidth, ScaledHeight: Double; +begin + PageWidth := APage.Width; + PageHeight := APage.Height; + + PageScale := PageHeight / PageWidth; + PrintScale := Height / Width; + + ScaledWidth := Width; + ScaledHeight := Height; + if PageScale > PrintScale then + ScaledWidth := Width * (PrintScale / PageScale) + else + ScaledHeight := Height * (PageScale / PrintScale); + + X := X + (Width - ScaledWidth) / 2; + Y := Y + (Height - ScaledHeight) / 2; + + APage.Draw( + FPrinterDC, + RoundToInt(X), RoundToInt(Y), RoundToInt(ScaledWidth), RoundToInt(ScaledHeight), + prNormal, [proPrinting, proAnnotations] + ); +end; +{$ENDIF MSWINDOWS} + initialization + {$IFDEF FPC} + InitCriticalSection(PDFiumInitCritSect); + InitCriticalSection(FFITimersCritSect); + {$ELSE} InitializeCriticalSectionAndSpinCount(PDFiumInitCritSect, 4000); InitializeCriticalSectionAndSpinCount(FFITimersCritSect, 4000); + {$ENDIF FPC} finalization + {$IFDEF FPC} + DoneCriticalSection(FFITimersCritSect); + DoneCriticalSection(PDFiumInitCritSect); + {$ELSE} DeleteCriticalSection(FFITimersCritSect); DeleteCriticalSection(PDFiumInitCritSect); + {$ENDIF FPC} end. diff --git a/Source/PdfiumCtrl.pas b/Source/PdfiumCtrl.pas index 0036f6b..4c4ab80 100644 --- a/Source/PdfiumCtrl.pas +++ b/Source/PdfiumCtrl.pas @@ -1,3 +1,7 @@ +{$IFDEF FPC} + {$MODE DelphiUnicode} +{$ENDIF FPC} + {$A8,B-,E-,F-,G+,H+,I+,J-,K-,M-,N-,P+,Q-,R-,S-,T-,U-,V+,X+,Z1} {$STRINGCHECKS OFF} @@ -6,13 +10,44 @@ // Show invalidated paint regions. Don't enable this if you aren't trying to optimize the repainting {.$DEFINE REPAINTTEST} +{$IFDEF FPC} + {$DEFINE USE_PRINTCLIENT_WORKAROUND} +{$ELSE} + {$IF CompilerVersion <= 20.0} // 2009 and older + {$DEFINE USE_PRINTCLIENT_WORKAROUND} + {$IFEND} + {$IF CompilerVersion >= 21.0} // 2010+ + {$DEFINE VCL_HAS_TOUCH} + {$IFEND} +{$ENDIF FPC} + interface uses - Windows, Messages, Types, SysUtils, Classes, Graphics, Controls, Forms, PdfiumCore; + {$IFDEF FPC} + LCLType, PrintersDlgs, Win32Extra, + {$ENDIF FPC} + Windows, Messages, ShellAPI, Types, SysUtils, Classes, Contnrs, Graphics, Controls, + Forms, Dialogs, PdfiumCore; + +type + TPdfControlLinkOptionType = ( + loAutoGoto, // Jumps in the document are allowed and automatically handled + loAutoRemoteGotoReplaceDocument, // Jumps to a remote document are allowed and automatically handled by replacing the loaded document + loAutoOpenURI, // Jumps to URI are allowed and automatically handled by using ShellExecuteEx. Disables OnWebLinkClick if loTreatWebLinkAsUriAnnotationLink is set + loAutoLaunch, // Allow executing/opening a program/file automatically by using ShellExecuteEx + loAutoEmbeddedGotoReplaceDocument, // Jumps to an attached PDF document are allowed and automatically handled by replacing the loaded document + + loTreatWebLinkAsUriAnnotationLink, // OnAnnotationLinkClick also handles WebLinks + loAlwaysDetectWebAndUriLink // If if OnWebLinkClick and OnAnnotationLinkClick aren't assigned, URI and WebLinks are detected + ); + TPdfControlLinkOptions = set of TPdfControlLinkOptionType; const - cPdfControlDefaultDrawOptions = []; + cPdfControlDefaultDrawOptions = [proAnnotations]; + cPdfControlDefaultLinkOptions = [loAutoGoto, loTreatWebLinkAsUriAnnotationLink, loAlwaysDetectWebAndUriLink]; + cPdfControlAllAutoLinkOptions = [loAutoGoto, loAutoRemoteGotoReplaceDocument, loAutoOpenURI, + loAutoLaunch, loAutoEmbeddedGotoReplaceDocument]; type TPdfControlScaleMode = ( @@ -23,8 +58,8 @@ interface ); TPdfControlWebLinkClickEvent = procedure(Sender: TObject; Url: string) of object; + TPdfControlAnnotationLinkClickEvent = procedure(Sender: TObject; LinkInfo: TPdfLinkInfo; var Handled: Boolean) of object; TPdfControlRectArray = array of TRect; - TPdfControlPdfRectArray = array of TPdfRect; TPdfControl = class(TCustomControl) private @@ -37,9 +72,9 @@ TPdfControl = class(TCustomControl) FDrawWidth: Integer; FDrawHeight: Integer; FRotation: TPdfPageRotation; - {$IF CompilerVersion <= 20.0} // 2009 + {$IFDEF USE_PRINTCLIENT_WORKAROUND} FPrintClient: Boolean; - {$IFEND} + {$ENDIF USE_PRINTCLIENT_WORKAROUND} FMousePressed: Boolean; FSelectionActive: Boolean; FAllowUserTextSelection: Boolean; @@ -49,24 +84,32 @@ TPdfControl = class(TCustomControl) FSmoothScroll: Boolean; FScrollTimerActive: Boolean; FScrollTimer: Boolean; + FChangePageOnMouseScrolling: Boolean; FSelStartCharIndex: Integer; FSelStopCharIndex: Integer; FMouseDownPt: TPoint; FCheckForTrippleClick: Boolean; - FWebLinksRects: array of TPdfControlPdfRectArray; + FWebLinkInfo: TPdfPageWebLinksInfo; FDrawOptions: TPdfPageRenderOptions; FScaleMode: TPdfControlScaleMode; FZoomPercentage: Integer; FPageColor: TColor; FScrollMousePos: TPoint; - FHighlightTextRects: TPdfControlPdfRectArray; - FHighlightText: string; - FHighlightMatchCase: Boolean; - FHighlightMatchWholeWord: Boolean; + FLinkOptions: TPdfControlLinkOptions; + FHighlightTextRects: TPdfRectArray; + FHighlightTexts: TObjectList; + FFormOutputSelectedRects: TPdfRectArray; + FFormFieldFocused: Boolean; + FPageShadowSize: Integer; + FPageShadowColor: TColor; + FPageShadowPadding: Integer; + FPageBorderColor: TColor; + FOnWebLinkClick: TPdfControlWebLinkClickEvent; + FOnAnnotationLinkClick: TPdfControlAnnotationLinkClickEvent; FOnPageChange: TNotifyEvent; FOnPaint: TNotifyEvent; - FFormOutputSelectedRects: TPdfRectArray; + FOnPrintDocument: TNotifyEvent; procedure WMTimer(var Message: TWMTimer); message WM_TIMER; procedure WMVScroll(var Message: TWMVScroll); message WM_VSCROLL; @@ -74,16 +117,16 @@ TPdfControl = class(TCustomControl) procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND; procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE; procedure CMColorchanged(var Message: TMessage); message CM_COLORCHANGED; - {$IF CompilerVersion <= 20.0} // 2009 + {$IFDEF USE_PRINTCLIENT_WORKAROUND} procedure WMPrintClient(var Message: TWMPrintClient); message WM_PRINTCLIENT; - {$IFEND} + {$ENDIF USE_PRINTCLIENT_WORKAROUND} procedure CMMouseleave(var Message: TMessage); message CM_MOUSELEAVE; procedure GetPageWebLinks; function GetCurrentPage: TPdfPage; function GetPageCount: Integer; procedure SetPageIndex(Value: Integer); - function InternSetPageIndex(Value: Integer; ScrollTransition, InversScrollTransition: Boolean): Boolean; + function InternSetPageIndex(Value: Integer; ScrollTransition, InverseScrollTransition: Boolean): Boolean; procedure SetRotation(const Value: TPdfPageRotation); function SetSelStopCharIndex(X, Y: Integer): Boolean; function GetSelText: string; @@ -91,25 +134,36 @@ TPdfControl = class(TCustomControl) function GetSelStart: Integer; procedure SetSelection(Active: Boolean; StartIndex, StopIndex: Integer); procedure SetScaleMode(const Value: TPdfControlScaleMode); + procedure SetPageBorderColor(const Value: TColor); + procedure SetPageShadowColor(const Value: TColor); + procedure SetPageShadowPadding(const Value: Integer); + procedure SetPageShadowSize(const Value: Integer); procedure AdjustDrawPos; procedure UpdatePageDrawInfo; procedure SetPageColor(const Value: TColor); procedure SetDrawOptions(const Value: TPdfPageRenderOptions); procedure InvalidateRectDiffs(const OldRects, NewRects: TPdfControlRectArray); - procedure InvalidatePdfRectDiffs(const OldRects, NewRects: TPdfControlPdfRectArray); + procedure InvalidatePdfRectDiffs(const OldRects, NewRects: TPdfRectArray); procedure StopScrollTimer; procedure DocumentLoaded; procedure DrawSelection(DC: HDC; Page: TPdfPage); procedure DrawHighlightText(DC: HDC; Page: TPdfPage); - function InternPageToDevice(Page: TPdfPage; PageRect: TPdfRect): TRect; + procedure DrawBorderAndShadow(DC: HDC); + function InternPageToDevice(Page: TPdfPage; PageRect: TPdfRect; ANormalize: Boolean): TRect; procedure SetZoomPercentage(Value: Integer); procedure DrawPage(DC: HDC; Page: TPdfPage; DirectDrawPage: Boolean); procedure CalcHighlightTextRects; + procedure InitDocument; + function ShellOpenFileName(const FileName: string; Launch: Boolean): Boolean; procedure FormInvalidate(Document: TPdfDocument; Page: TPdfPage; const PageRect: TPdfRect); procedure FormOutputSelectedRect(Document: TPdfDocument; Page: TPdfPage; const PageRect: TPdfRect); procedure FormGetCurrentPage(Document: TPdfDocument; var Page: TPdfPage); - procedure DrawAlphaSelection(DC: HDC; Page: TPdfPage; const ARects: TPdfRectArray); + procedure FormFieldFocus(Document: TPdfDocument; Value: PWideChar; ValueLen: Integer; FieldFocused: Boolean); + procedure ExecuteNamedAction(Document: TPdfDocument; NamedAction: TPdfNamedActionType); + + procedure DrawAlphaRects(DC: HDC; Page: TPdfPage; const Rects: TPdfRectArray; Color: TColor); + procedure DrawAlphaSelection(DC: HDC; Page: TPdfPage; const Rects: TPdfRectArray); procedure DrawFormOutputSelectedRects(DC: HDC; Page: TPdfPage); protected procedure Paint; override; @@ -119,19 +173,20 @@ TPdfControl = class(TCustomControl) procedure MouseMove(Shift: TShiftState; X: Integer; Y: Integer); override; function DoMouseWheel(Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint): Boolean; override; procedure KeyDown(var Key: Word; Shift: TShiftState); override; - procedure WMKeyDown(var Message: TWMKeyDown); message WM_KEYDOWN; - procedure WMKeyUp(var Message: TWMKeyUp); message WM_KEYUP; - procedure WMChar(var Message: TWMChar); message WM_CHAR; + procedure WMKeyDown(var Message: TWMKeyDown); message {$IFDEF FPC}CN_KEYDOWN{$ELSE}WM_KEYDOWN{$ENDIF}; + procedure WMKeyUp(var Message: TWMKeyUp); message {$IFDEF FPC}CN_KEYUP{$ELSE}WM_KEYUP{$ENDIF}; + procedure WMChar(var Message: TWMChar); message {$IFDEF FPC}CN_CHAR{$ELSE}WM_CHAR{$ENDIF}; procedure WMKillFocus(var Message: TWMKillFocus); message WM_KILLFOCUS; - procedure WebLinkClick(Url: string); virtual; + function LinkHandlingNeeded: Boolean; + function IsClickableLinkAt(X, Y: Integer): Boolean; + procedure WebLinkClick(const Url: string); virtual; + procedure AnnotationLinkClick(LinkInfo: TPdfLinkInfo); virtual; procedure PageChange; virtual; procedure PageContentChanged(Closing: Boolean); procedure PageLayoutChanged; function IsPageValid: Boolean; - procedure InvalidatePage; function GetSelectionRects: TPdfControlRectArray; - function GetWebLinkIndex(X, Y: Integer): Integer; procedure DestroyWnd; override; property DrawX: Integer read FDrawX; @@ -142,13 +197,19 @@ TPdfControl = class(TCustomControl) constructor Create(AOwner: TComponent); override; destructor Destroy; override; - procedure LoadFromCustom(ReadFunc: TPdfDocumentCustomReadProc; ASize: LongWord; AParam: Pointer; const APassword: AnsiString = ''); - procedure LoadFromActiveStream(Stream: TStream; const APassword: AnsiString = ''); // Stream must not be released until the document is closed - procedure LoadFromActiveBuffer(Buffer: Pointer; Size: Integer; const APassword: AnsiString = ''); // Buffer must not be released until the document is closed - procedure LoadFromBytes(const ABytes: TBytes; const APassword: AnsiString = ''); overload; // The content of the Bytes array must not be changed until the document is closed - procedure LoadFromBytes(const ABytes: TBytes; AIndex: Integer; ACount: Integer; const APassword: AnsiString = ''); overload; // The content of the Bytes array must not be changed until the document is closed - procedure LoadFromStream(AStream: TStream; const APassword: AnsiString = ''); - procedure LoadFromFile(const AFileName: string; const APassword: AnsiString = ''; ALoadOptions: TPdfDocumentLoadOption = dloMMF); + { InvalidatePage forces the page to be rendered again and invalidates the control. } + procedure InvalidatePage; + { PrintDocument uses OnPrintDocument to print. If OnPrintDocument is not assigned it does nothing. } + procedure PrintDocument; + + procedure OpenWithDocument(Document: TPdfDocument); // takes ownership + procedure LoadFromCustom(ReadFunc: TPdfDocumentCustomReadProc; Size: LongWord; Param: Pointer; const Password: UTF8String = ''); + procedure LoadFromActiveStream(Stream: TStream; const Password: UTF8String = ''); // Stream must not be released until the document is closed + procedure LoadFromActiveBuffer(Buffer: Pointer; Size: Int64; const Password: UTF8String = ''); // Buffer must not be released until the document is closed + procedure LoadFromBytes(const Bytes: TBytes; const Password: UTF8String = ''); overload; // The content of the Bytes array must not be changed until the document is closed + procedure LoadFromBytes(const Bytes: TBytes; Index: Integer; Count: Integer; const Password: UTF8String = ''); overload; // The content of the Bytes array must not be changed until the document is closed + procedure LoadFromStream(Stream: TStream; const Password: UTF8String = ''); + procedure LoadFromFile(const FileName: string; const Password: UTF8String = ''; LoadOption: TPdfDocumentLoadOption = dloDefault); procedure Close; function DeviceToPage(DeviceX, DeviceY: Integer): TPdfPoint; overload; @@ -157,6 +218,11 @@ TPdfControl = class(TCustomControl) function PageToDevice(PageRect: TPdfRect): TRect; overload; function GetPageRect: TRect; + procedure CopyFormTextToClipboard; + procedure CutFormTextToClipboard; + procedure PasteFormTextFromClipboard; + procedure SelectAllFormText; + procedure CopyToClipboard; procedure ClearSelection; procedure SelectAll; @@ -165,16 +231,25 @@ TPdfControl = class(TCustomControl) function SelectLine(CharIndex: Integer): Boolean; function GetTextInRect(const R: TRect): string; + { HightlightText() highlights all occurences of the specified text and clears previously + hightlighted texts. } procedure HightlightText(const SearchText: string; MatchCase, MatchWholeWord: Boolean); + { AddHightlightText() highlights all occurences of the specified text but keeps previously + hightlighted texts. } + procedure AddHightlightText(const SearchText: string; MatchCase, MatchWholeWord: Boolean); procedure ClearHighlightText; function IsWebLinkAt(X, Y: Integer): Boolean; overload; function IsWebLinkAt(X, Y: Integer; var Url: string): Boolean; overload; + function IsUriAnnotationLinkAt(X, Y: Integer): Boolean; + function IsAnnotationLinkAt(X, Y: Integer): Boolean; + function GetAnnotationLinkAt(X, Y: Integer): TPdfAnnotation; function GotoNextPage(ScrollTransition: Boolean = False): Boolean; function GotoPrevPage(ScrollTransition: Boolean = False): Boolean; function ScrollContent(XOffset, YOffset: Integer; Smooth: Boolean = False): Boolean; virtual; function ScrollContentTo(X, Y: Integer; Smooth: Boolean = False): Boolean; + function GotoDestination(const LinkGotoDestination: TPdfLinkGotoDestination): Boolean; property Document: TPdfDocument read FDocument; property CurrentPage: TPdfPage read GetCurrentPage; @@ -198,8 +273,23 @@ TPdfControl = class(TCustomControl) property DrawOptions: TPdfPageRenderOptions read FDrawOptions write SetDrawOptions default cPdfControlDefaultDrawOptions; property SmoothScroll: Boolean read FSmoothScroll write FSmoothScroll default False; property ScrollTimer: Boolean read FScrollTimer write FScrollTimer default True; + property ChangePageOnMouseScrolling: Boolean read FChangePageOnMouseScrolling write FChangePageOnMouseScrolling default False; + property LinkOptions: TPdfControlLinkOptions read FLinkOptions write FLinkOptions default cPdfControlDefaultLinkOptions; + + property PageBorderColor: TColor read FPageBorderColor write SetPageBorderColor default clNone; + property PageShadowColor: TColor read FPageShadowColor write SetPageShadowColor default clNone; + property PageShadowSize: Integer read FPageShadowSize write SetPageShadowSize default 4; + property PageShadowPadding: Integer read FPageShadowPadding write SetPageShadowPadding default 44; + + { OnWebLinkClick is only called for WebLinks (URLs parsed from the document text). If OnAnnotationLinkClick is + not assigned, OnWebLinkClick is also called URI link annontations for backward compatibility reasons. } property OnWebLinkClick: TPdfControlWebLinkClickEvent read FOnWebLinkClick write FOnWebLinkClick; + { OnAnnotationLinkClick is called for all link annotation but not for WebLinks. } + property OnAnnotationLinkClick: TPdfControlAnnotationLinkClickEvent read FOnAnnotationLinkClick write FOnAnnotationLinkClick; + { OnPageChange is called if the current page is switched. } property OnPageChange: TNotifyEvent read FOnPageChange write FOnPageChange; + { OnPrintDocument is called from PrintDocument } + property OnPrintDocument: TNotifyEvent read FOnPrintDocument write FOnPrintDocument; property Align; property Anchors; @@ -229,7 +319,9 @@ TPdfControl = class(TCustomControl) property OnKeyDown; property OnKeyPress; property OnKeyUp; + {$IFNDEF FPC} property OnMouseActivate; + {$ENDIF ~FPC} property OnMouseDown; property OnMouseEnter; property OnMouseLeave; @@ -238,16 +330,36 @@ TPdfControl = class(TCustomControl) property OnPaint: TNotifyEvent read FOnPaint write FOnPaint; property OnStartDock; property OnStartDrag; - {$IF CompilerVersion >= 21.0} // 2010+ + {$IFDEF VCL_HAS_TOUCH} property Touch; property OnGesture; - {$IFEND} + {$ENDIF VCL_HAS_TOUCH} + end; + + TPdfDocumentVclPrinter = class(TPdfDocumentPrinter) + private + FBeginDocCalled: Boolean; + FPagePrinted: Boolean; + protected + function PrinterStartDoc(const AJobTitle: string): Boolean; override; + procedure PrinterEndDoc; override; + procedure PrinterStartPage; override; + procedure PrinterEndPage; override; + function GetPrinterDC: HDC; override; + public + { If AShowPrintDialog is false PrintDocument prints the document to the default printer. + If AShowPrintDialog is true the print dialog is shown and the user can select the + printer, page range and number of copies (if supported by the printer driver). + Returns true if the page was send to the printer driver. } + class function PrintDocument(ADocument: TPdfDocument; const AJobTitle: string; + AShowPrintDialog: Boolean = True; AllowPageRange: Boolean = True; + AParentWnd: HWND = 0): Boolean; static; end; implementation uses - Math, Clipbrd, Character, PdfiumLib; + Math, Clipbrd, Character, Printers; const cScrollTimerId = 1; @@ -255,15 +367,180 @@ implementation cScrollTimerInterval = 50; cDefaultScrollOffset = 25; +type + THighlightTextInfo = class(TObject) + private + FText: string; + FMatchCase: Boolean; + FMatchWholeWord: Boolean; + public + constructor Create(const AText: string; AMatchCase, AMatchWholeWord: Boolean); + function IsSame(const AText: string; AMatchCase, AMatchWholeWord: Boolean): Boolean; + + property Text: string read FText; + property MatchCase: Boolean read FMatchCase; + property MatchWholeWord: Boolean read FMatchWholeWord; + end; + function IsWhitespace(Ch: Char): Boolean; begin - {$IF CompilerVersion >= 25.0} // XE4 - Result := Ch.IsWhiteSpace; + {$IFDEF FPC} + Result := TCharacter.IsWhiteSpace(Ch); {$ELSE} + {$IF CompilerVersion >= 25.0} // XE4 + Result := Ch.IsWhiteSpace; + {$ELSE} Result := TCharacter.IsWhiteSpace(Ch); - {$IFEND} + {$IFEND} + {$ENDIF FPC} +end; + +function VclAbortProc(Prn: HDC; Error: Integer): Bool; stdcall; +begin + Application.ProcessMessages; + Result := not Printer.Aborted; +end; + +function FastVclAbortProc(Prn: HDC; Error: Integer): Bool; stdcall; +begin + Result := not Printer.Aborted; +end; + + +{ THighlightTextInfo } + +constructor THighlightTextInfo.Create(const AText: string; AMatchCase, AMatchWholeWord: Boolean); +begin + inherited Create; + FText := AText; + FMatchCase := AMatchCase; + FMatchWholeWord := AMatchWholeWord; end; +function THighlightTextInfo.IsSame(const AText: string; AMatchCase, AMatchWholeWord: Boolean): Boolean; +begin + Result := (AMatchCase = FMatchCase) and + (AMatchWholeWord = FMatchWholeWord) and + (AText = FText); +end; + +{ TPdfDocumentVclPrinter } + +function TPdfDocumentVclPrinter.PrinterStartDoc(const AJobTitle: string): Boolean; +begin + Result := False; + FPagePrinted := False; + if not Printer.Printing then + begin + if AJobTitle <> '' then + Printer.Title := AJobTitle; + Printer.BeginDoc; + FBeginDocCalled := Printer.Printing; + Result := FBeginDocCalled; + end; + if Result and Printer.Printing then + begin + // The Printers.AbortProc function calls ProcessMessages. That not only slows down the performance + // but it also allows the user to do things in the UI. + SetAbortProc(GetPrinterDC, @FastVclAbortProc); + end; +end; + +procedure TPdfDocumentVclPrinter.PrinterEndDoc; +begin + if Printer.Printing then + begin + SetAbortProc(GetPrinterDC, @VclAbortProc); // restore default behavior + if FBeginDocCalled then + Printer.EndDoc; + end; +end; + +procedure TPdfDocumentVclPrinter.PrinterStartPage; +begin + // Printer has only "NewPage" and the very first page doesn't need a NewPage call because + // Printer.BeginDoc already called Windows.StartPage. + if (Printer.PageNumber > 1) or FPagePrinted then + Printer.NewPage; +end; + +procedure TPdfDocumentVclPrinter.PrinterEndPage; +begin + FPagePrinted := True; + // The VCL uses "NewPage". For the very last page Printer.EndDoc calls Windows.EndPage. +end; + +function TPdfDocumentVclPrinter.GetPrinterDC: HDC; +begin + Result := Printer.Canvas.Handle; +end; + +class function TPdfDocumentVclPrinter.PrintDocument(ADocument: TPdfDocument; + const AJobTitle: string; AShowPrintDialog, AllowPageRange: Boolean; AParentWnd: HWND): Boolean; +var + PdfPrinter: TPdfDocumentVclPrinter; + Dlg: TPrintDialog; + FromPage, ToPage: Integer; +begin + Result := False; + if ADocument = nil then + Exit; + + FromPage := 1; + ToPage := ADocument.PageCount; + + if AShowPrintDialog then + begin + Dlg := TPrintDialog.Create(nil); + try + // Set the PrintDialog options + if AllowPageRange then + begin + Dlg.MinPage := 1; + Dlg.MaxPage := ADocument.PageCount; + Dlg.Options := Dlg.Options + [poPageNums]; + end; + + // Show the PrintDialog + {$IFDEF FPC} + Result := Dlg.Execute; + {$ELSE} + if (AParentWnd = 0) or not IsWindow(AParentWnd) then + Result := Dlg.Execute + else + Result := Dlg.Execute(AParentWnd); + {$ENDIF FPC} + + if not Result then + Exit; + + // Adjust print options + if AllowPageRange and (Dlg.PrintRange = prPageNums) then + begin + FromPage := Dlg.FromPage; + ToPage := Dlg.ToPage; + end; + finally + Dlg.Free; + end; + end; + + PdfPrinter := TPdfDocumentVclPrinter.Create; + try + if PdfPrinter.BeginPrint(AJobTitle) then + begin + try + Result := PdfPrinter.Print(ADocument, FromPage - 1, ToPage - 1); + finally + PdfPrinter.EndPrint; + end; + end; + finally + PdfPrinter.Free; + end; +end; + + { TPdfControl } constructor TPdfControl.Create(AOwner: TComponent); @@ -281,11 +558,15 @@ constructor TPdfControl.Create(AOwner: TComponent); FDrawOptions := cPdfControlDefaultDrawOptions; FScrollTimer := True; FBufferedPageDraw := True; + FLinkOptions := cPdfControlDefaultLinkOptions; + + FPageBorderColor := clNone; + FPageShadowColor := clNone; + FPageShadowSize := 4; + FPageShadowPadding := 44; FDocument := TPdfDocument.Create; - FDocument.OnFormInvalidate := FormInvalidate; - FDocument.OnFormOutputSelectedRect := FormOutputSelectedRect; - FDocument.OnFormGetCurrentPage := FormGetCurrentPage; + InitDocument; ParentDoubleBuffered := False; ParentBackground := False; @@ -300,10 +581,20 @@ destructor TPdfControl.Destroy; begin if FPageBitmap <> 0 then DeleteObject(FPageBitmap); + FreeAndNil(FWebLinkInfo); FDocument.Free; inherited Destroy; end; +procedure TPdfControl.InitDocument; +begin + FDocument.OnFormInvalidate := FormInvalidate; + FDocument.OnFormOutputSelectedRect := FormOutputSelectedRect; + FDocument.OnFormGetCurrentPage := FormGetCurrentPage; + FDocument.OnFormFieldFocus := FormFieldFocus; + FDocument.OnExecuteNamedAction := ExecuteNamedAction; +end; + procedure TPdfControl.DestroyWnd; begin StopScrollTimer; @@ -312,9 +603,9 @@ procedure TPdfControl.DestroyWnd; inherited DestroyWnd; end; -{$IF CompilerVersion <= 20.0} // 2009 +{$IFDEF USE_PRINTCLIENT_WORKAROUND} procedure TPdfControl.WMPrintClient(var Message: TWMPrintClient); -// emulate Delphi 2010' TControlState.csPrintClient +// Emulate Delphi 2010's TControlState.csPrintClient var LastPrintClient: Boolean; begin @@ -326,14 +617,19 @@ procedure TPdfControl.WMPrintClient(var Message: TWMPrintClient); FPrintClient := LastPrintClient; end; end; -{$IFEND} +{$ENDIF USE_PRINTCLIENT_WORKAROUND} procedure TPdfControl.WMEraseBkgnd(var Message: TWMEraseBkgnd); begin Message.Result := 1; end; -procedure TPdfControl.DrawAlphaSelection(DC: HDC; Page: TPdfPage; const ARects: TPdfRectArray); +procedure TPdfControl.DrawAlphaSelection(DC: HDC; Page: TPdfPage; const Rects: TPdfRectArray); +begin + DrawAlphaRects(DC, Page, Rects, RGB(50, 142, 254)); +end; + +procedure TPdfControl.DrawAlphaRects(DC: HDC; Page: TPdfPage; const Rects: TPdfRectArray; Color: TColor); var Count: Integer; I: Integer; @@ -342,13 +638,17 @@ procedure TPdfControl.DrawAlphaSelection(DC: HDC; Page: TPdfPage; const ARects: SelBmp: TBitmap; BlendFunc: TBlendFunction; begin - Count := Length(ARects); + Count := Length(Rects); if Count > 0 then begin SelBmp := TBitmap.Create; try - SelBmp.Canvas.Brush.Color := RGB(50, 142, 254); + SelBmp.Canvas.Brush.Color := Color; SelBmp.SetSize(100, 50); + {$IFDEF FPC} + // Delphi fills the bitmap with the brush if it is resized, FPC doesn't + SelBmp.Canvas.FillRect(0, 0, SelBmp.Width, SelBmp.Height); + {$ENDIF FPC} BlendFunc.BlendOp := AC_SRC_OVER; BlendFunc.BlendFlags := 0; BlendFunc.SourceConstantAlpha := 127; @@ -356,7 +656,7 @@ procedure TPdfControl.DrawAlphaSelection(DC: HDC; Page: TPdfPage; const ARects: BmpDC := SelBmp.Canvas.Handle; for I := 0 to Count - 1 do begin - R := InternPageToDevice(Page, ARects[I]); + R := InternPageToDevice(Page, Rects[I], True); if RectVisible(DC, R) then AlphaBlend(DC, R.Left, R.Top, R.Right - R.Left, R.Bottom - R.Top, BmpDC, 0, 0, SelBmp.Width, SelBmp.Height, @@ -387,40 +687,39 @@ procedure TPdfControl.DrawSelection(DC: HDC; Page: TPdfPage); procedure TPdfControl.DrawFormOutputSelectedRects(DC: HDC; Page: TPdfPage); begin DrawAlphaSelection(DC, Page, FFormOutputSelectedRects); - FFormOutputSelectedRects := nil; end; procedure TPdfControl.DrawHighlightText(DC: HDC; Page: TPdfPage); +begin + DrawAlphaRects(DC, Page, FHighlightTextRects, RGB(254, 142, 50)); +end; + +procedure TPdfControl.DrawBorderAndShadow(DC: HDC); var - I: Integer; - R: TRect; - BmpDC: HDC; - SelBmp: TBitmap; - BlendFunc: TBlendFunction; + BorderBrush, ShadowBrush: HBRUSH; begin - if FHighlightTextRects <> nil then + // Draw page borders + if PageBorderColor <> clNone then begin - SelBmp := TBitmap.Create; - try - SelBmp.Canvas.Brush.Color := RGB(254, 142, 50); - SelBmp.SetSize(100, 50); - BlendFunc.BlendOp := AC_SRC_OVER; - BlendFunc.BlendFlags := 0; - BlendFunc.SourceConstantAlpha := 127; - BlendFunc.AlphaFormat := 0; - BmpDC := SelBmp.Canvas.Handle; + BorderBrush := CreateSolidBrush(ColorToRGB(PageBorderColor)); + FillRect(DC, Rect(FDrawX, FDrawY, FDrawX + FDrawWidth, FDrawY + 1), BorderBrush); // top border + FillRect(DC, Rect(FDrawX, FDrawY, FDrawX + 1, FDrawY + FDrawHeight), BorderBrush); // left border + FillRect(DC, Rect(FDrawX + FDrawWidth - 1, FDrawY, FDrawX + FDrawWidth, FDrawY + FDrawHeight), BorderBrush); // right border + FillRect(DC, Rect(FDrawX, FDrawY + FDrawHeight - 1, FDrawX + FDrawWidth, FDrawY + FDrawHeight), BorderBrush); // bottom border + DeleteObject(BorderBrush); + end; - for I := 0 to Length(FHighlightTextRects) - 1 do - begin - R := InternPageToDevice(Page, FHighlightTextRects[I]); - if RectVisible(DC, R) then - AlphaBlend(DC, R.Left, R.Top, R.Right - R.Left, R.Bottom - R.Top, - BmpDC, 0, 0, SelBmp.Width, SelBmp.Height, - BlendFunc); - end; - finally - SelBmp.Free; - end; + // Draw page shadow + if (PageShadowColor <> clNone) and (PageShadowSize > 0) then + begin + ShadowBrush := CreateSolidBrush(ColorToRGB(PageShadowColor)); + FillRect(DC, Rect(FDrawX + FDrawWidth, FDrawY + PageShadowSize, + FDrawX + FDrawWidth + PageShadowSize, FDrawY + FDrawHeight + PageShadowSize), + ShadowBrush); // right shadow + FillRect(DC, Rect(FDrawX + PageShadowSize, FDrawY + FDrawHeight, + FDrawX + FDrawWidth + PageShadowSize, FDrawY + FDrawHeight + PageShadowSize), + ShadowBrush); // bottom shadow + DeleteObject(ShadowBrush); end; end; @@ -429,15 +728,22 @@ procedure TPdfControl.DrawPage(DC: HDC; Page: TPdfPage; DirectDrawPage: Boolean) procedure Draw(DC: HDC; X, Y: Integer; Page: TPdfPage); var PageBrush: HBRUSH; + ColorRef: TColorRef; begin if PageColor = clDefault then - PageBrush := CreateSolidBrush(ColorToRGB(Color)) + ColorRef := ColorToRGB(Color) else - PageBrush := CreateSolidBrush(ColorToRGB(PageColor)); - FillRect(DC, Rect(X, Y, X + FDrawWidth, Y + FDrawHeight), PageBrush); - DeleteObject(PageBrush); + ColorRef := ColorToRGB(PageColor); - Page.Draw(DC, X, Y, FDrawWidth, FDrawHeight, Rotation, FDrawOptions); + // Page.Draw doesn't paint the background if proPrinting is enabled. + if proPrinting in FDrawOptions then + begin + PageBrush := CreateSolidBrush(ColorRef); + FillRect(DC, Rect(X, Y, X + FDrawWidth, Y + FDrawHeight), PageBrush); + DeleteObject(PageBrush); + end; + + Page.Draw(DC, X, Y, FDrawWidth, FDrawHeight, Rotation, FDrawOptions, ColorRef); end; var @@ -536,11 +842,11 @@ procedure TPdfControl.Paint; // copy the clipping region and adjust to the bitmap's device units Rgn := CreateRectRgn(0, 0, 1, 1); - {$IF CompilerVersion >= 21.0} // 2010+ - if csPrintClient in ControlState then - {$ELSE} + {$IFDEF USE_PRINTCLIENT_WORKAROUND} if FPrintClient then - {$IFEND} + {$ELSE} + if csPrintClient in ControlState then + {$ENDIF USE_PRINTCLIENT_WORKAROUND} begin if GetClipRgn(DC, Rgn) = 1 then // application clip region begin @@ -588,6 +894,8 @@ procedure TPdfControl.Paint; // Draw the highlighted text overlay DrawHighlightText(DrawDC, Page); + DrawBorderAndShadow(DrawDC); + // User painting if Assigned(FOnPaint) then begin @@ -620,6 +928,7 @@ procedure TPdfControl.Paint; FPageBitmap := 0; end; FillRect(DC, Rect(0, 0, Width, Height), Brush.Handle); + DrawBorderAndShadow(DC); if Assigned(FOnPaint) then FOnPaint(Self); end; @@ -656,6 +965,17 @@ procedure TPdfControl.InvalidatePage; end; end; +procedure TPdfControl.PrintDocument; +begin + if Document.Active then + begin + if Assigned(FOnPrintDocument) then + FOnPrintDocument(Self) + else + TPdfDocumentVclPrinter.PrintDocument(Document, ExtractFileName(Document.FileName)); + end; +end; + function TPdfControl.GetCurrentPage: TPdfPage; begin if IsPageValid then @@ -674,13 +994,13 @@ procedure TPdfControl.SetPageIndex(Value: Integer); InternSetPageIndex(Value, False, False); end; -function TPdfControl.InternSetPageIndex(Value: Integer; ScrollTransition, InversScrollTransition: Boolean): Boolean; +function TPdfControl.InternSetPageIndex(Value: Integer; ScrollTransition, InverseScrollTransition: Boolean): Boolean; var ScrollInfo: TScrollInfo; ScrollY: Integer; OldPageIndex: Integer; begin - if Value > PageCount then + if Value >= PageCount then Value := PageCount - 1; if Value < 0 then Value := 0; @@ -689,8 +1009,11 @@ function TPdfControl.InternSetPageIndex(Value: Integer; ScrollTransition, Invers begin ClearSelection; // Close the previous page to keep memory usage low (especially for large PDF files) - if (FPageIndex >= 0) and (FPageIndex < PageCount) and FDocument.IsPageLoaded(FPageIndex) then + if (FPageIndex >= 0) and (FPageIndex < PageCount) and FDocument.IsPageLoaded(FPageIndex) and + not FDocument.Pages[FPageIndex].Annotations.AnnotationsLoaded then // Issue #28: Don't close the page if annotations are loaded + begin FDocument.Pages[FPageIndex].Close; + end; OldPageIndex := FPageIndex; FPageIndex := Value; ScrollInfo.cbSize := SizeOf(ScrollInfo); @@ -702,7 +1025,7 @@ function TPdfControl.InternSetPageIndex(Value: Integer; ScrollTransition, Invers ScrollInfo.fMask := SIF_RANGE or SIF_PAGE or SIF_POS; if GetScrollInfo(Handle, SB_VERT, ScrollInfo) then begin - if InversScrollTransition then + if InverseScrollTransition then begin if FPageIndex < OldPageIndex then ScrollY := 0 @@ -769,67 +1092,78 @@ procedure TPdfControl.DocumentLoaded; PageContentChanged(False); end; -procedure TPdfControl.LoadFromCustom(ReadFunc: TPdfDocumentCustomReadProc; ASize: LongWord; - AParam: Pointer; const APassword: AnsiString); +procedure TPdfControl.OpenWithDocument(Document: TPdfDocument); +begin + Close; + if Document = nil then + Exit; + + FreeAndNil(FDocument); + FDocument := Document; + InitDocument; +end; + +procedure TPdfControl.LoadFromCustom(ReadFunc: TPdfDocumentCustomReadProc; Size: LongWord; + Param: Pointer; const Password: UTF8String); begin try - FDocument.LoadFromCustom(ReadFunc, ASize, AParam, APassword); + FDocument.LoadFromCustom(ReadFunc, Size, Param, Password); finally DocumentLoaded; end; end; -procedure TPdfControl.LoadFromActiveStream(Stream: TStream; const APassword: AnsiString); +procedure TPdfControl.LoadFromActiveStream(Stream: TStream; const Password: UTF8String); begin try - FDocument.LoadFromActiveStream(Stream, APassword); + FDocument.LoadFromActiveStream(Stream, Password); finally DocumentLoaded; end; end; -procedure TPdfControl.LoadFromActiveBuffer(Buffer: Pointer; Size: Integer; const APassword: AnsiString); +procedure TPdfControl.LoadFromActiveBuffer(Buffer: Pointer; Size: Int64; const Password: UTF8String); begin try - FDocument.LoadFromActiveBuffer(Buffer, Size, APassword); + FDocument.LoadFromActiveBuffer(Buffer, Size, Password); finally DocumentLoaded; end; end; -procedure TPdfControl.LoadFromBytes(const ABytes: TBytes; AIndex, ACount: Integer; - const APassword: AnsiString); +procedure TPdfControl.LoadFromBytes(const Bytes: TBytes; Index, Count: Integer; + const Password: UTF8String); begin try - FDocument.LoadFromBytes(ABytes, AIndex, ACount, APassword); + FDocument.LoadFromBytes(Bytes, Index, Count, Password); finally DocumentLoaded; end; end; -procedure TPdfControl.LoadFromBytes(const ABytes: TBytes; const APassword: AnsiString); +procedure TPdfControl.LoadFromBytes(const Bytes: TBytes; const Password: UTF8String); begin try - FDocument.LoadFromBytes(ABytes, APassword); + FDocument.LoadFromBytes(Bytes, Password); finally DocumentLoaded; end; end; -procedure TPdfControl.LoadFromStream(AStream: TStream; const APassword: AnsiString); +procedure TPdfControl.LoadFromStream(Stream: TStream; const Password: UTF8String); begin try - FDocument.LoadFromStream(AStream, APassword); + FDocument.LoadFromStream(Stream, Password); finally DocumentLoaded; end; end; -procedure TPdfControl.LoadFromFile(const AFileName: string; const APassword: AnsiString; - ALoadOptions: TPdfDocumentLoadOption); +procedure TPdfControl.LoadFromFile(const FileName: string; const Password: UTF8String; + LoadOption: TPdfDocumentLoadOption); begin try - FDocument.LoadFromFile(AFileName, APassword, ALoadOptions); + FDocument.LoadFromFile(FileName, Password, LoadOption); finally DocumentLoaded; end; @@ -839,6 +1173,7 @@ procedure TPdfControl.Close; begin FDocument.Close; FPageIndex := 0; + FFormFieldFocused := False; PageContentChanged(True); end; @@ -907,6 +1242,42 @@ procedure TPdfControl.SetRotation(const Value: TPdfPageRotation); end; end; +procedure TPdfControl.SetPageBorderColor(const Value: TColor); +begin + if Value <> FPageBorderColor then + begin + FPageBorderColor := Value; + InvalidatePage; + end; +end; + +procedure TPdfControl.SetPageShadowColor(const Value: TColor); +begin + if Value <> FPageShadowColor then + begin + FPageShadowColor := Value; + InvalidatePage; + end; +end; + +procedure TPdfControl.SetPageShadowPadding(const Value: Integer); +begin + if Value <> FPageShadowPadding then + begin + FPageShadowPadding := Value; + InvalidatePage; + end; +end; + +procedure TPdfControl.SetPageShadowSize(const Value: Integer); +begin + if Value <> FPageShadowSize then + begin + FPageShadowSize := Value; + InvalidatePage; + end; +end; + function TPdfControl.GetPageRect: TRect; begin Result := Rect(FDrawX, FDrawY, FDrawX + FDrawWidth, FDrawY + FDrawHeight); @@ -929,7 +1300,7 @@ function TPdfControl.DeviceToPage(DeviceRect: TRect): TPdfRect; begin Page := CurrentPage; if Page <> nil then - Result := CurrentPage.DeviceToPage(FDrawX, FDrawY, FDrawWidth, FDrawHeight, DeviceRect, Rotation) + Result := Page.DeviceToPage(FDrawX, FDrawY, FDrawWidth, FDrawHeight, DeviceRect, Rotation) else Result := TPdfRect.Empty; end; @@ -940,7 +1311,7 @@ function TPdfControl.PageToDevice(PageX, PageY: Double): TPoint; begin Page := CurrentPage; if Page <> nil then - Result := CurrentPage.PageToDevice(FDrawX, FDrawY, FDrawWidth, FDrawHeight, PageX, PageY, Rotation) + Result := Page.PageToDevice(FDrawX, FDrawY, FDrawWidth, FDrawHeight, PageX, PageY, Rotation) else Result := Point(0, 0); end; @@ -951,14 +1322,31 @@ function TPdfControl.PageToDevice(PageRect: TPdfRect): TRect; begin Page := CurrentPage; if Page <> nil then - Result := CurrentPage.PageToDevice(FDrawX, FDrawY, FDrawWidth, FDrawHeight, PageRect, Rotation) + Result := Page.PageToDevice(FDrawX, FDrawY, FDrawWidth, FDrawHeight, PageRect, Rotation) else Result := Rect(0, 0, 0, 0); end; -function TPdfControl.InternPageToDevice(Page: TPdfPage; PageRect: TPdfRect): TRect; +function TPdfControl.InternPageToDevice(Page: TPdfPage; PageRect: TPdfRect; ANormalize: Boolean): TRect; +var + Value: Integer; begin Result := Page.PageToDevice(FDrawX, FDrawY, FDrawWidth, FDrawHeight, PageRect, Rotation); + if ANormalize then + begin + if Result.Left > Result.Right then + begin + Value := Result.Right; + Result.Right := Result.Left; + Result.Left := Value; + end; + if Result.Top > Result.Bottom then + begin + Value := Result.Bottom; + Result.Bottom := Result.Top; + Result.Top := Value; + end; + end; end; function TPdfControl.SetSelStopCharIndex(X, Y: Integer): Boolean; @@ -967,27 +1355,35 @@ function TPdfControl.SetSelStopCharIndex(X, Y: Integer): Boolean; CharIndex: Integer; Active: Boolean; R: TRect; + Page: TPdfPage; begin - PagePt := DeviceToPage(X, Y); - CharIndex := CurrentPage.GetCharIndexAt(PagePt.X, PagePt.Y, MAXWORD, MAXWORD); - Result := CharIndex >= 0; - if not Result then - CharIndex := FSelStopCharIndex; + Page := CurrentPage; + if Page <> nil then + begin + PagePt := DeviceToPage(X, Y); + CharIndex := Page.GetCharIndexAt(PagePt.X, PagePt.Y, MAXWORD, MAXWORD); + Result := CharIndex >= 0; + if not Result then + CharIndex := FSelStopCharIndex; - if FSelStartCharIndex <> CharIndex then - Active := True + if FSelStartCharIndex <> CharIndex then + Active := True + else + begin + R := PageToDevice(Page.GetCharBox(FSelStartCharIndex)); + Active := PtInRect(R, FMouseDownPt) xor PtInRect(R, Point(X, Y)); + end; + SetSelection(Active, FSelStartCharIndex, CharIndex); + end else - begin - R := PageToDevice(CurrentPage.GetCharBox(FSelStartCharIndex)); - Active := PtInRect(R, FMouseDownPt) xor PtInRect(R, Point(X, Y)); - end; - SetSelection(Active, FSelStartCharIndex, CharIndex); + Result := False; end; procedure TPdfControl.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var PagePt: TPdfPoint; CharIndex: Integer; + Page: TPdfPage; begin inherited MouseDown(Button, Shift, X, Y); if Button = mbLeft then @@ -998,31 +1394,32 @@ procedure TPdfControl.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: FMouseDownPt := Point(X, Y); // used to find out if the selection must be cleared or not end; - if IsPageValid then + Page := CurrentPage; + if Page <> nil then begin if AllowFormEvents then begin PagePt := DeviceToPage(X, Y); if Button = mbLeft then begin - if CurrentPage.FormEventLButtonDown(Shift, PagePt.X, PagePt.Y) then + if Page.FormEventLButtonDown(Shift, PagePt.X, PagePt.Y) then Exit; end else if Button = mbRight then begin - if CurrentPage.FormEventFocus(Shift, PagePt.X, PagePt.Y) then + if Page.FormEventFocus(Shift, PagePt.X, PagePt.Y) then Exit; - if CurrentPage.FormEventRButtonDown(Shift, PagePt.X, PagePt.Y) then + if Page.FormEventRButtonDown(Shift, PagePt.X, PagePt.Y) then Exit; end; end; - if AllowUserTextSelection then + if AllowUserTextSelection and not FFormFieldFocused then begin if Button = mbLeft then begin PagePt := DeviceToPage(X, Y); - CharIndex := CurrentPage.GetCharIndexAt(PagePt.X, PagePt.Y, MAXWORD, MAXWORD); + CharIndex := Page.GetCharIndexAt(PagePt.X, PagePt.Y, MAXWORD, MAXWORD); if FCheckForTrippleClick and (CharIndex >= SelStart) and (CharIndex < SelStart + SelLength) then begin FMousePressed := False; @@ -1051,13 +1448,17 @@ procedure TPdfControl.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: In var PagePt: TPdfPoint; Url: string; + Page: TPdfPage; + LinkAnnotation: TPdfAnnotation; + LinkInfo: TPdfLinkInfo; begin inherited MouseUp(Button, Shift, X, Y); if AllowFormEvents and IsPageValid then begin PagePt := DeviceToPage(X, Y); - if (Button = mbLeft) and CurrentPage.FormEventLButtonUp(Shift, PagePt.X, PagePt.Y) then + Page := CurrentPage; + if (Button = mbLeft) and Page.FormEventLButtonUp(Shift, PagePt.X, PagePt.Y) then begin if FMousePressed and (Button = mbLeft) then begin @@ -1066,7 +1467,7 @@ procedure TPdfControl.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: In end; Exit; end; - if (Button = mbRight) and CurrentPage.FormEventRButtonUp(Shift, PagePt.X, PagePt.Y) then + if (Button = mbRight) and Page.FormEventRButtonUp(Shift, PagePt.X, PagePt.Y) then Exit; end; @@ -1076,10 +1477,33 @@ procedure TPdfControl.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: In begin FMousePressed := False; StopScrollTimer; - if AllowUserTextSelection then + if AllowUserTextSelection and not FFormFieldFocused then SetSelStopCharIndex(X, Y); - if not FSelectionActive and IsWebLinkAt(X, Y, Url) then - WebLinkClick(Url); + if not FSelectionActive then + begin + if LinkHandlingNeeded then + begin + LinkAnnotation := GetAnnotationLinkAt(X, Y); + LinkInfo := nil; + if LinkAnnotation <> nil then + LinkInfo := TPdfLinkInfo.Create(LinkAnnotation, '') + else if IsWebLinkAt(X, Y, Url) then // If we have a Link Annotation and a WebLink, then the link annotation is prefered + begin + if loTreatWebLinkAsUriAnnotationLink in LinkOptions then + LinkInfo := TPdfLinkInfo.Create(nil, Url) + else + WebLinkClick(Url); + end; + if LinkInfo <> nil then + begin + try + AnnotationLinkClick(LinkInfo); + finally + LinkInfo.Free; + end; + end; + end; + end; end; end; end; @@ -1089,6 +1513,8 @@ procedure TPdfControl.MouseMove(Shift: TShiftState; X, Y: Integer); PagePt: TPdfPoint; Style: NativeInt; NewCursor: TCursor; + Page: TPdfPage; + Proceed: Boolean; begin inherited MouseMove(Shift, X, Y); NewCursor := Cursor; @@ -1096,23 +1522,30 @@ procedure TPdfControl.MouseMove(Shift: TShiftState; X, Y: Integer); if AllowFormEvents and IsPageValid then begin PagePt := DeviceToPage(X, Y); - if CurrentPage.FormEventMouseMove(Shift, PagePt.X, PagePt.Y) then + Page := CurrentPage; + if Page.FormEventMouseMove(Shift, PagePt.X, PagePt.Y) then begin - case CurrentPage.HasFormFieldAtPoint(PagePt.X, PagePt.Y) of + Proceed := False; + case Page.HasFormFieldAtPoint(PagePt.X, PagePt.Y) of + fftUnknown: + // Could be an annotation link with a URL + Proceed := True; fftTextField: NewCursor := crIBeam; + fftComboBox, fftSignature: NewCursor := crHandPoint; else NewCursor := crDefault; end; - Exit; + if not Proceed then + Exit; end; end; if AllowUserTextSelection then begin - if FMousePressed then + if FMousePressed and not FFormFieldFocused then begin // Auto scroll FScrollMousePos := Point(X, Y); @@ -1144,7 +1577,7 @@ procedure TPdfControl.MouseMove(Shift: TShiftState; X, Y: Integer); if IsPageValid then begin PagePt := DeviceToPage(X, Y); - if Assigned(FOnWebLinkClick) and IsWebLinkAt(X, Y) then + if IsClickableLinkAt(X, Y) then NewCursor := crHandPoint else if CurrentPage.GetCharIndexAt(PagePt.X, PagePt.Y, 5, 5) >= 0 then NewCursor := crIBeam @@ -1163,7 +1596,7 @@ procedure TPdfControl.CMMouseleave(var Message: TMessage); begin if (Cursor = crIBeam) or (Cursor = crHandPoint) then begin - if AllowUserTextSelection or Assigned(FOnWebLinkClick) then + if AllowUserTextSelection or Assigned(FOnWebLinkClick) or Assigned(FOnAnnotationLinkClick) or (LinkOptions <> []) then Cursor := crDefault; end; inherited; @@ -1182,6 +1615,47 @@ procedure TPdfControl.CopyToClipboard; Clipboard.AsText := GetSelText; end; +procedure TPdfControl.CopyFormTextToClipboard; +var + S: string; +begin + if FFormFieldFocused and IsPageValid then + begin + S := CurrentPage.FormGetSelectedText; + if S <> '' then + Clipboard.AsText := S; + end; +end; + +procedure TPdfControl.CutFormTextToClipboard; +begin + if FFormFieldFocused and IsPageValid then + begin + CopyFormTextToClipboard; + CurrentPage.FormReplaceSelection(''); + end; +end; + +procedure TPdfControl.PasteFormTextFromClipboard; +begin + if FFormFieldFocused and IsPageValid then + begin + Clipboard.Open; + try + if Clipboard.HasFormat(CF_UNICODETEXT) or Clipboard.HasFormat(CF_TEXT) then + CurrentPage.FormReplaceSelection(Clipboard.AsText); + finally + Clipboard.Close; + end; + end; +end; + +procedure TPdfControl.SelectAllFormText; +begin + if FFormFieldFocused and IsPageValid then + CurrentPage.FormSelectAllText; +end; + function TPdfControl.GetSelText: string; begin if FSelectionActive and IsPageValid then @@ -1217,10 +1691,10 @@ function TPdfControl.GetSelectionRects: TPdfControlRectArray; Page := CurrentPage; if Page <> nil then begin - Count := CurrentPage.GetTextRectCount(SelStart, SelLength); + Count := Page.GetTextRectCount(SelStart, SelLength); SetLength(Result, Count); for I := 0 to Count - 1 do - Result[I] := InternPageToDevice(Page, Page.GetTextRect(I)); + Result[I] := InternPageToDevice(Page, Page.GetTextRect(I), True); Exit; end; end; @@ -1255,7 +1729,7 @@ procedure TPdfControl.InvalidateRectDiffs(const OldRects, NewRects: TPdfControlR end; end; -procedure TPdfControl.InvalidatePdfRectDiffs(const OldRects, NewRects: TPdfControlPdfRectArray); +procedure TPdfControl.InvalidatePdfRectDiffs(const OldRects, NewRects: TPdfRectArray); var I: Integer; OldRs, NewRs: TPdfControlRectArray; @@ -1266,11 +1740,11 @@ procedure TPdfControl.InvalidatePdfRectDiffs(const OldRects, NewRects: TPdfContr begin SetLength(OldRs, Length(OldRects)); for I := 0 to Length(OldRects) - 1 do - OldRs[I] := InternPageToDevice(Page, OldRects[I]); + OldRs[I] := InternPageToDevice(Page, OldRects[I], True); SetLength(NewRs, Length(NewRects)); for I := 0 to Length(NewRects) - 1 do - NewRs[I] := InternPageToDevice(Page, NewRects[I]); + NewRs[I] := InternPageToDevice(Page, NewRects[I], True); InvalidateRectDiffs(OldRs, NewRs); end; @@ -1330,7 +1804,7 @@ function TPdfControl.SelectWord(CharIndex: Integer): Boolean; CharCount := Page.GetCharCount; if (CharIndex >= 0) and (CharIndex < CharCount) then begin - while (CharIndex < CharCount) and IsWhiteSpace(CurrentPage.ReadChar(CharIndex)) do + while (CharIndex < CharCount) and IsWhiteSpace(Page.ReadChar(CharIndex)) do Inc(CharIndex); if CharIndex < CharCount then @@ -1338,7 +1812,7 @@ function TPdfControl.SelectWord(CharIndex: Integer): Boolean; StartCharIndex := CharIndex - 1; while StartCharIndex >= 0 do begin - Ch := CurrentPage.ReadChar(StartCharIndex); + Ch := Page.ReadChar(StartCharIndex); if IsWhiteSpace(Ch) then Break; Dec(StartCharIndex); @@ -1348,7 +1822,7 @@ function TPdfControl.SelectWord(CharIndex: Integer): Boolean; StopCharIndex := CharIndex + 1; while StopCharIndex < CharCount do begin - Ch := CurrentPage.ReadChar(StopCharIndex); + Ch := Page.ReadChar(StopCharIndex); if IsWhiteSpace(Ch) then Break; Inc(StopCharIndex); @@ -1379,7 +1853,7 @@ function TPdfControl.SelectLine(CharIndex: Integer): Boolean; StartCharIndex := CharIndex - 1; while StartCharIndex >= 0 do begin - Ch := CurrentPage.ReadChar(StartCharIndex); + Ch := Page.ReadChar(StartCharIndex); case Ch of #10, #13: Break; @@ -1391,7 +1865,7 @@ function TPdfControl.SelectLine(CharIndex: Integer): Boolean; StopCharIndex := CharIndex + 1; while StopCharIndex < CharCount do begin - Ch := CurrentPage.ReadChar(StopCharIndex); + Ch := Page.ReadChar(StopCharIndex); case Ch of #10, #13: Break; @@ -1421,7 +1895,7 @@ procedure TPdfControl.KeyDown(var Key: Word; Shift: TShiftState); XOffset := 0; YOffset := 0; case Key of - VK_INSERT, Ord('C'): + Ord('C'), VK_INSERT: if AllowUserTextSelection then begin if Shift = [ssCtrl] then @@ -1538,22 +2012,58 @@ procedure TPdfControl.KeyDown(var Key: Word; Shift: TShiftState); end; procedure TPdfControl.WMKeyDown(var Message: TWMKeyDown); +var + Shift: TShiftState; begin - if AllowFormEvents and IsPageValid and CurrentPage.FormEventKeyDown(Message.CharCode, Message.KeyData) then - Exit; + if AllowFormEvents and IsPageValid then + begin + Shift := KeyDataToShiftState(Message.KeyData); + if CurrentPage.FormEventKeyDown(Message.CharCode, Shift) then + begin + // PDFium doesn't handle Copy&Paste&Cut keyboard shortcuts in form fields + case Message.CharCode of + Ord('C'), Ord('X'), Ord('V'), VK_INSERT, VK_DELETE: + begin + if Shift = [ssCtrl] then + begin + case Message.CharCode of + Ord('C'), VK_INSERT: + CopyFormTextToClipboard; + Ord('X'): + CutFormTextToClipboard; + Ord('V'): + PasteFormTextFromClipboard; + end; + end + else if Shift = [ssShift] then + begin + case Message.CharCode of + VK_INSERT: + PasteFormTextFromClipboard; + VK_DELETE: + CutFormTextToClipboard; + end; + end; + end; + end; + Exit; + end; + end; inherited; end; procedure TPdfControl.WMKeyUp(var Message: TWMKeyUp); begin - if AllowFormEvents and IsPageValid and CurrentPage.FormEventKeyUp(Message.CharCode, Message.KeyData) then + if AllowFormEvents and IsPageValid + and CurrentPage.FormEventKeyUp(Message.CharCode, KeyDataToShiftState(Message.KeyData)) then Exit; inherited; end; procedure TPdfControl.WMChar(var Message: TWMChar); begin - if AllowFormEvents and IsPageValid and CurrentPage.FormEventKeyPress(Message.CharCode, Message.KeyData) then + if AllowFormEvents and IsPageValid + and CurrentPage.FormEventKeyPress(Message.CharCode, KeyDataToShiftState(Message.KeyData)) then Exit; inherited; end; @@ -1567,68 +2077,272 @@ procedure TPdfControl.WMKillFocus(var Message: TWMKillFocus); procedure TPdfControl.GetPageWebLinks; var - LinkIndex, LinkCount: Integer; - RectIndex, RectCount: Integer; Page: TPdfPage; begin + FreeAndNil(FWebLinkInfo); Page := CurrentPage; if Page <> nil then + FWebLinkInfo := TPdfPageWebLinksInfo.Create(Page); +end; + +function TPdfControl.LinkHandlingNeeded: Boolean; +begin + // If an event handler is assigned, we need link handling + Result := Assigned(FOnAnnotationLinkClick) or Assigned(FOnWebLinkClick); + if not Result then begin - LinkCount := Page.GetWebLinkCount; - SetLength(FWebLinksRects, LinkCount); - for LinkIndex := 0 to LinkCount - 1 do + // If no event handler is assigned, we may need link handling depending on the loAutoXXX options. + Result := LinkOptions * cPdfControlAllAutoLinkOptions <> []; + end; +end; + +function TPdfControl.IsClickableLinkAt(X, Y: Integer): Boolean; +var + LinkAnnotation: TPdfAnnotation; +begin + Result := False; + if LinkHandlingNeeded then + begin + LinkAnnotation := GetAnnotationLinkAt(X, Y); + if LinkAnnotation <> nil then begin - RectCount := Page.GetWebLinkRectCount(LinkIndex); - SetLength(FWebLinksRects[LinkIndex], RectCount); - for RectIndex := 0 to RectCount - 1 do - FWebLinksRects[LinkIndex][RectIndex] := Page.GetWebLinkRect(LinkIndex, RectIndex); + if Assigned(FOnAnnotationLinkClick) then + Result := True + else + begin + case LinkAnnotation.LinkType of + altGoto: + Result := loAutoGoto in LinkOptions; + altRemoteGoto: + Result := loAutoRemoteGotoReplaceDocument in LinkOptions; + altURI: + Result := (loAutoOpenURI in LinkOptions) or (loAlwaysDetectWebAndUriLink in LinkOptions) or Assigned(FOnWebLinkClick); // Fallback to OnWebLinkClick for URIs + altLaunch: + Result := loAutoLaunch in LinkOptions; + altEmbeddedGoto: + Result := loAutoEmbeddedGotoReplaceDocument in LinkOptions; + else + Result := False; + end; + end; + end + else if IsWebLinkAt(X, Y) then + begin + if Assigned(FOnWebLinkClick) or (loAlwaysDetectWebAndUriLink in LinkOptions) then + Result := True + else if Assigned(FOnAnnotationLinkClick) and (loTreatWebLinkAsUriAnnotationLink in LinkOptions) then + Result := True + else if not Assigned(FOnAnnotationLinkClick) and (loTreatWebLinkAsUriAnnotationLink in LinkOptions) and (loAutoOpenURI in LinkOptions) then + Result := True; end; + end; +end; + +function TPdfControl.IsWebLinkAt(X, Y: Integer): Boolean; +var + PdfPt: TPdfPoint; +begin + if (FWebLinkInfo <> nil) and IsPageValid then + begin + PdfPt := DeviceToPage(X, Y); + Result := FWebLinkInfo.IsWebLinkAt(PdfPt.X, PdfPt.Y); end else - FWebLinksRects := nil; + Result := False; end; -function TPdfControl.GetWebLinkIndex(X, Y: Integer): Integer; +function TPdfControl.IsWebLinkAt(X, Y: Integer; var Url: string): Boolean; var - RectIndex: Integer; - Pt: TPoint; - Page: TPdfPage; + PdfPt: TPdfPoint; begin - Pt := Point(X, Y); - Page := CurrentPage; - if Page <> nil then + Url := ''; + if (FWebLinkInfo <> nil) and IsPageValid then begin - for Result := 0 to Length(FWebLinksRects) - 1 do - for RectIndex := 0 to Length(FWebLinksRects[Result]) - 1 do - if PtInRect(InternPageToDevice(Page, FWebLinksRects[Result][RectIndex]), Pt) then - Exit; - end; - Result := -1; + PdfPt := DeviceToPage(X, Y); + Result := FWebLinkInfo.IsWebLinkAt(PdfPt.X, PdfPt.Y, Url); + end + else + Result := False; end; -function TPdfControl.IsWebLinkAt(X, Y: Integer): Boolean; +function TPdfControl.IsUriAnnotationLinkAt(X, Y: Integer): Boolean; +var + PdfPt: TPdfPoint; +begin + if IsPageValid then + begin + PdfPt := DeviceToPage(X, Y); + Result := CurrentPage.IsUriLinkAtPoint(PdfPt.X, PdfPt.Y); + end + else + Result := False; +end; + +function TPdfControl.IsAnnotationLinkAt(X, Y: Integer): Boolean; begin - Result := GetWebLinkIndex(X, Y) <> -1; + Result := GetAnnotationLinkAt(X, Y) <> nil; end; -function TPdfControl.IsWebLinkAt(X, Y: Integer; var Url: string): Boolean; +function TPdfControl.GetAnnotationLinkAt(X, Y: Integer): TPdfAnnotation; var - Index: Integer; + PdfPt: TPdfPoint; begin - Index := GetWebLinkIndex(X, Y); - Result := Index <> -1; - if Result then - Url := CurrentPage.GetWebLinkURL(Index) + if IsPageValid then + begin + PdfPt := DeviceToPage(X, Y); + Result := CurrentPage.GetLinkAtPoint(PdfPt.X, PdfPt.Y); + end + else + Result := nil; +end; + +function TPdfControl.ShellOpenFileName(const FileName: string; Launch: Boolean): Boolean; +var + Info: TShellExecuteInfoW; +begin + FillChar(Info, SizeOf(Info), 0); + Info.cbSize := SizeOf(Info); + if HandleAllocated then + Info.Wnd := Handle; + if Launch then + Info.lpVerb := nil else - Url := ''; + Info.lpVerb := 'open'; + Info.lpFile := PChar(FileName); + Info.lpDirectory := PChar(ExtractFileDir(Document.FileName)); + Info.nShow := SW_NORMAL; + Result := ShellExecuteExW(@Info); end; -procedure TPdfControl.WebLinkClick(Url: string); +procedure TPdfControl.WebLinkClick(const Url: string); begin if Assigned(FOnWebLinkClick) then FOnWebLinkClick(Self, Url); end; +function TPdfControl.GotoDestination(const LinkGotoDestination: TPdfLinkGotoDestination): Boolean; +var + X, Y: Double; + //Zoom: Integer; + Pt: TPoint; +begin + Result := False; + if Document.Active then + begin + X := 0; + Y := 0; + //Zoom := 100; + if LinkGotoDestination.XValid then + X := LinkGotoDestination.X; + if LinkGotoDestination.YValid then + Y := LinkGotoDestination.Y; + //if Dest.ZoomValid then + // Zoom := Int(Dest.Zoom); + + if (LinkGotoDestination.PageIndex >= 0) and (LinkGotoDestination.PageIndex < Document.PageCount) then + begin + Pt := PageToDevice(X, Y); + + PageIndex := LinkGotoDestination.PageIndex; + //ZoomPercentage := Zoom; + ScrollContentTo(Pt.X, Pt.Y); + Result := True; + end; + end; +end; + +procedure TPdfControl.AnnotationLinkClick(LinkInfo: TPdfLinkInfo); +var + Handled: Boolean; + Dest: TPdfLinkGotoDestination; + FileName: string; + RemoteDoc: TPdfDocument; + DestValid: Boolean; + AttachmentIndex: Integer; +begin + Handled := False; + if not Document.Active then + Exit; + + if Assigned(FOnAnnotationLinkClick) then + FOnAnnotationLinkClick(Self, LinkInfo, Handled) + else if Assigned(FOnWebLinkClick) and (LinkInfo.LinkType = altURI) and not (loAutoOpenURI in LinkOptions) then + begin + WebLinkClick(LinkInfo.LinkUri); + Exit; + end; + + if not Handled and Document.Active then + begin + case LinkInfo.LinkType of + altGoto: + if loAutoGoto in LinkOptions then + begin + if LinkInfo.GetLinkGotoDestination(Dest) then + GotoDestination(Dest); + end; + + altRemoteGoto: + if loAutoRemoteGotoReplaceDocument in LinkOptions then + begin + Dest := nil; + RemoteDoc := TPdfDocument.Create; + try + // Open the remote document + RemoteDoc.LoadFromFile(LinkInfo.LinkFileName); + // Get the link destination from the remote document + DestValid := LinkInfo.GetLinkGotoDestination(Dest, RemoteDoc); + except + RemoteDoc.Free; + raise; + end; + if DestValid then + begin + // Replace the current document with the remote document + OpenWithDocument(RemoteDoc); + GotoDestination(Dest); + end; + end; + + altURI: + if loAutoOpenURI in LinkOptions then + ShellOpenFileName(LinkInfo.LinkUri, False); + + altLaunch: + if loAutoLaunch in LinkOptions then + ShellOpenFileName(LinkInfo.LinkFileName, True); + + altEmbeddedGoto: + if loAutoEmbeddedGotoReplaceDocument in LinkOptions then + begin + FileName := LinkInfo.LinkFileName; + AttachmentIndex := Document.Attachments.IndexOf(FileName); + if AttachmentIndex <> -1 then + begin + // Same as RemoteGoto but with a byte array + Dest := nil; + RemoteDoc := TPdfDocument.Create; + try + // Open the embedded document + RemoteDoc.LoadFromBytes(Document.Attachments[AttachmentIndex].GetContentAsBytes); + // Get the link destination from the remote document + DestValid := LinkInfo.GetLinkGotoDestination(Dest, RemoteDoc); + except + RemoteDoc.Free; + raise; + end; + if DestValid then + begin + // Replace the current document with the remote document + OpenWithDocument(RemoteDoc); + GotoDestination(Dest); + end; + end; + end; + end; + end; +end; + procedure TPdfControl.UpdatePageDrawInfo; procedure GetWidthHeight(PageWidth, PageHeight: Double; DpiX, DpiY, MaxWidth, MaxHeight: Integer; var W, H: Integer); @@ -1663,6 +2377,12 @@ procedure TPdfControl.UpdatePageDrawInfo; H := Round(PageHeight / 72 * DpiY * (ZoomPercentage / 100)); end; end; + + if (PageShadowColor <> clNone) and (PageShadowSize > 0) and (PageShadowPadding > 0) then + begin + W := W - (PageShadowPadding + PageShadowSize); + H := H - (PageShadowPadding + PageShadowSize); + end; end; var @@ -1918,10 +2638,20 @@ procedure TPdfControl.WMHScroll(var Message: TWMHScroll); function TPdfControl.DoMouseWheel(Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint): Boolean; +var + PagePt: TPdfPoint; begin Result := inherited DoMouseWheel(Shift, WheelDelta, MousePos); + if not Result then begin + if IsPageValid and AllowFormEvents then + begin + PagePt := DeviceToPage(MousePos.X, MousePos.Y); + if CurrentPage.FormEventMouseWheel(Shift, WheelDelta, PagePt.X, PagePt.Y) then + Exit; + end; + if ssCtrl in Shift then begin if ScaleMode = smZoom then @@ -1933,10 +2663,22 @@ function TPdfControl.DoMouseWheel(Shift: TShiftState; WheelDelta: Integer; else begin if ssShift in Shift then - ScrollContent(-WheelDelta, 0, SmoothScroll) + Result := ScrollContent(-WheelDelta, 0, SmoothScroll) else - ScrollContent(0, -WheelDelta, SmoothScroll); - Result := True; + Result := ScrollContent(0, -WheelDelta, SmoothScroll); + + if not Result and FChangePageOnMouseScrolling then + begin + if WheelDelta < 0 then + GotoNextPage() + else if PageIndex > 0 then + begin + GotoPrevPage(); + ScrollContentTo(0, MaxInt); + end; + end + else + Result := True; end; end; end; @@ -1987,41 +2729,70 @@ procedure TPdfControl.StopScrollTimer; procedure TPdfControl.HightlightText(const SearchText: string; MatchCase, MatchWholeWord: Boolean); begin - FHighlightText := SearchText; - FHighlightMatchCase := MatchCase; - FHighlightMatchWholeWord := MatchWholeWord; + if FHighlightTexts <> nil then + FHighlightTexts.Clear; + AddHightlightText(SearchText, MatchCase, MatchWholeWord); +end; + +procedure TPdfControl.AddHightlightText(const SearchText: string; MatchCase, MatchWholeWord: Boolean); +var + HLTextInfo: THighlightTextInfo; + I: Integer; +begin + if SearchText = '' then + Exit; + + // Prevent duplicates + if FHighlightTexts <> nil then + for I := 0 to FHighlightTexts.Count - 1 do + if (FHighlightTexts[I] as THighlightTextInfo).IsSame(SearchText, MatchCase, MatchWholeWord) then + Exit; + + if FHighlightTexts = nil then + FHighlightTexts := TObjectList.Create; + HLTextInfo := THighlightTextInfo.Create(SearchText, MatchCase, MatchWholeWord); + FHighlightTexts.Add(HLTextInfo); + CalcHighlightTextRects; end; procedure TPdfControl.CalcHighlightTextRects; var - OldHighlightTextRects: TPdfControlPdfRectArray; + OldHighlightTextRects: TPdfRectArray; + HLTextInfo: THighlightTextInfo; Page: TPdfPage; - CharIndex, CharCount, I, Count: Integer; + CharIndex, CharCount, I, Count, TextsIndex: Integer; Num: Integer; begin OldHighlightTextRects := FHighlightTextRects; FHighlightTextRects := nil; - if IsPageValid and (FHighlightText <> '') then + if (FHighlightTexts <> nil) and (FHighlightTexts.Count > 0) and IsPageValid then begin Page := CurrentPage; Num := 0; - if Page.BeginFind(FHighlightText, FHighlightMatchCase, FHighlightMatchWholeWord, False) then + for TextsIndex := 0 to FHighlightTexts.Count - 1 do begin - try - while Page.FindNext(CharIndex, CharCount) do + HLTextInfo := FHighlightTexts[TextsIndex] as THighlightTextInfo; + if HLTextInfo.Text <> '' then // prevent infinite loop in FPDFText_FindNext() + begin + if Page.BeginFind(HLTextInfo.Text, HLTextInfo.MatchCase, HLTextInfo.MatchWholeWord, False) then begin - Count := Page.GetTextRectCount(CharIndex, CharCount); - if Num + Count > Length(FHighlightTextRects) then - SetLength(FHighlightTextRects, (Num + Count) * 2); - for I := 0 to Count - 1 do - begin - FHighlightTextRects[Num] := Page.GetTextRect(I); - Inc(Num); + try + while Page.FindNext(CharIndex, CharCount) do + begin + Count := Page.GetTextRectCount(CharIndex, CharCount); + if Num + Count > Length(FHighlightTextRects) then + SetLength(FHighlightTextRects, (Num + Count) * 2); + for I := 0 to Count - 1 do + begin + FHighlightTextRects[Num] := Page.GetTextRect(I); + Inc(Num); + end; + end; + finally + Page.EndFind; end; end; - finally - Page.EndFind; end; end; @@ -2034,7 +2805,7 @@ procedure TPdfControl.CalcHighlightTextRects; procedure TPdfControl.ClearHighlightText; begin - FHighlightText := ''; + FreeAndNil(FHighlightTexts); InvalidatePdfRectDiffs(FHighlightTextRects, nil); FHighlightTextRects := nil; end; @@ -2045,9 +2816,10 @@ procedure TPdfControl.FormInvalidate(Document: TPdfDocument; Page: TPdfPage; R: TRect; begin FRenderedPageIndex := -1; // content has changed => render into the background bitmap + FFormOutputSelectedRects := nil; if HandleAllocated then begin - R := InternPageToDevice(Page, PageRect); + R := InternPageToDevice(Page, PageRect, True); InvalidateRect(Handle, @R, True); end; end; @@ -2067,5 +2839,28 @@ procedure TPdfControl.FormGetCurrentPage(Document: TPdfDocument; var Page: TPdfP Page := CurrentPage; end; +procedure TPdfControl.FormFieldFocus(Document: TPdfDocument; Value: PWideChar; + ValueLen: Integer; FieldFocused: Boolean); +begin + ClearSelection; + FFormFieldFocused := FieldFocused; +end; + +procedure TPdfControl.ExecuteNamedAction(Document: TPdfDocument; NamedAction: TPdfNamedActionType); +begin + case NamedAction of + naPrint: + PrintDocument; + naNextPage: + PageIndex := PageIndex + 1; + naPrevPage: + PageIndex := PageIndex - 1; + naFirstPage: + PageIndex := 0; + naLastPage: + PageIndex := Document.PageCount - 1; + end; +end; + end. diff --git a/Source/PdfiumLib.pas b/Source/PdfiumLib.pas index 7d941fb..6096ec6 100644 --- a/Source/PdfiumLib.pas +++ b/Source/PdfiumLib.pas @@ -1,41 +1,61 @@ -{$A8,B-,E-,F-,G+,H+,I+,J-,K-,M-,N-,P+,Q-,R-,S-,T-,U-,V+,X+,Z1} -{$STRINGCHECKS OFF} // It only slows down Delphi strings in Delphi 2009/2010 - // Use DLLs (x64, x86) from https://github.com/bblanchon/pdfium-binaries // -// DLL Version: chromium/4047 +// DLL Version: chromium/7857 unit PdfiumLib; - +{$IFDEF FPC} + {$MODE DelphiUnicode} +{$ENDIF FPC} + +{$IFNDEF FPC} + {$A8,B-,E-,F-,G+,H+,I+,J-,K-,M-,N-,P+,Q-,R-,S-,T-,U-,V+,X+,Z1} + {$STRINGCHECKS OFF} // It only slows down Delphi strings in Delphi 2009 and 2010 +{$ENDIF ~FPC} {$SCOPEDENUMS ON} {.$DEFINE DLLEXPORT} // stdcall in WIN32 instead of CDECL in WIN32 (The library switches between those from release to release) -{$DEFINE PDFIUM_PRINT_TEXT_WITH_GDI} -{.$DEFINE _SKIA_SUPPORT_} +{$DEFINE PDF_USE_SKIA} {$DEFINE PDF_ENABLE_XFA} {$DEFINE PDF_ENABLE_V8} interface uses - {$IF CompilerVersion >= 23.0} // XE2+ - WinApi.Windows; + {$IFDEF FPC} + {$IFDEF MSWINDOWS} + Windows; + {$ELSE} + dynlibs; + {$ENDIF MSWINDOWS} {$ELSE} + {$IF CompilerVersion >= 23.0} // XE2+ + WinApi.Windows; + {$ELSE} Windows; - {$IFEND} + {$IFEND} + {$ENDIF FPC} type - // Delphi version compatibility types + // Delphi/FPC version compatibility types {$IF not declared(SIZE_T)} SIZE_T = LongWord; {$IFEND} {$IF not declared(DWORD)} DWORD = UInt32; {$IFEND} + {$IF not declared(UINT)} + UINT = LongWord; + {$IFEND} + {$IF not declared(PUINT)} + PUINT = ^UINT; + {$IFEND} TIME_T = Longint; PTIME_T = ^TIME_T; +// Returns True if the pdfium.dll supports Skia. +function PDF_IsSkiaAvailable: Boolean; + // *** _FPDFVIEW_H_ *** @@ -80,31 +100,37 @@ __FPDF_PTRREC = record end; PFPDF_LINK = ^FPDF_LINK; // array PFPDF_PAGE = ^FPDF_PAGE; // array - // PDF types - use incomplete types (never completed) just for API type safety. - FPDF_ACTION = type __PFPDF_PTRREC; - FPDF_ANNOTATION = type __PFPDF_PTRREC; - FPDF_ATTACHMENT = type __PFPDF_PTRREC; - FPDF_BITMAP = type __PFPDF_PTRREC; - FPDF_BOOKMARK = type __PFPDF_PTRREC; - FPDF_CLIPPATH = type __PFPDF_PTRREC; - FPDF_DEST = type __PFPDF_PTRREC; - FPDF_DOCUMENT = type __PFPDF_PTRREC; - FPDF_FONT = type __PFPDF_PTRREC; - FPDF_FORMHANDLE = type __PFPDF_PTRREC; - FPDF_JAVASCRIPT_ACTION = type __PFPDF_PTRREC; - FPDF_LINK = type __PFPDF_PTRREC; - FPDF_PAGE = type __PFPDF_PTRREC; - FPDF_PAGELINK = type __PFPDF_PTRREC; - FPDF_PAGEOBJECT = type __PFPDF_PTRREC; // (text, path, etc.) - FPDF_PAGEOBJECTMARK = type __PFPDF_PTRREC; - FPDF_PAGERANGE = type __PFPDF_PTRREC; - FPDF_PATHSEGMENT = type __PFPDF_PTRREC; - FPDF_RECORDER = type Pointer; // Passed into skia. - FPDF_SCHHANDLE = type __PFPDF_PTRREC; - FPDF_STRUCTELEMENT = type __PFPDF_PTRREC; - FPDF_STRUCTTREE = type __PFPDF_PTRREC; - FPDF_TEXTPAGE = type __PFPDF_PTRREC; - FPDF_WIDGET = type __PFPDF_PTRREC; + // PDF types - use incomplete types (never completed) to force API type safety. + FPDF_ACTION = type __PFPDF_PTRREC; + FPDF_ANNOTATION = type __PFPDF_PTRREC; + FPDF_ATTACHMENT = type __PFPDF_PTRREC; + FPDF_AVAIL = type __PFPDF_PTRREC; + FPDF_BITMAP = type __PFPDF_PTRREC; + FPDF_BOOKMARK = type __PFPDF_PTRREC; + FPDF_CLIPPATH = type __PFPDF_PTRREC; + FPDF_DEST = type __PFPDF_PTRREC; + FPDF_DOCUMENT = type __PFPDF_PTRREC; + FPDF_FONT = type __PFPDF_PTRREC; + FPDF_FORMHANDLE = type __PFPDF_PTRREC; + FPDF_GLYPHPATH = type __PFPDF_PTRREC; + FPDF_JAVASCRIPT_ACTION = type __PFPDF_PTRREC; + FPDF_LINK = type __PFPDF_PTRREC; + FPDF_PAGE = type __PFPDF_PTRREC; + FPDF_PAGELINK = type __PFPDF_PTRREC; + FPDF_PAGEOBJECT = type __PFPDF_PTRREC; // (text, path, etc.) + FPDF_PAGEOBJECTMARK = type __PFPDF_PTRREC; + FPDF_PAGERANGE = type __PFPDF_PTRREC; + FPDF_PATHSEGMENT = type __PFPDF_PTRREC; + FPDF_SCHHANDLE = type __PFPDF_PTRREC; + FPDF_SIGNATURE = type __PFPDF_PTRREC; + FPDF_SKIA_CANVAS = type Pointer; // Passed into Skia as an SkCanvas. + FPDF_STRUCTELEMENT = type __PFPDF_PTRREC; + FPDF_STRUCTELEMENT_ATTR = type __PFPDF_PTRREC; + FPDF_STRUCTELEMENT_ATTR_VALUE = type __PFPDF_PTRREC; + FPDF_STRUCTTREE = type __PFPDF_PTRREC; + FPDF_TEXTPAGE = type __PFPDF_PTRREC; + FPDF_WIDGET = type __PFPDF_PTRREC; + FPDF_XOBJECT = type __PFPDF_PTRREC; // Basic data types FPDF_BOOL = Integer; @@ -125,13 +151,15 @@ __FPDF_PTRREC = record end; PFPDF_WCHAR = PWideChar; FPDF_WCHAR = WideChar; - // FPDFSDK may use three types of strings: byte string, wide string (UTF-16LE - // encoded), and platform dependent string + // The public PDFium API uses three types of strings: byte string, wide string + // (UTF-16LE encoded), and platform dependent string. + + // Public PDFium API type for byte strings. FPDF_BYTESTRING = PAnsiChar; - // FPDFSDK always uses UTF-16LE encoded wide strings, each character uses 2 - // bytes (except surrogation), with the low byte first. - FPDF_WIDESTRING = PWideChar; + // The public PDFium API always uses UTF-16LE encoded wide strings, each + // character uses 2 bytes (except surrogation), with the low byte first. + FPDF_WIDESTRING = PFPDF_WCHAR; // Structure for persisting a string beyond the duration of a callback. // Note: although represented as a char*, string may be interpreted as @@ -211,25 +239,47 @@ FS_POINTF = record // Const Pointer to FS_POINTF structure. FS_LPCPOINTF = ^FS_POINTF; + PFS_QUADPOINTSF = ^FS_QUADPOINTSF; + FS_QUADPOINTSF = record + x1: FS_FLOAT; + y1: FS_FLOAT; + x2: FS_FLOAT; + y2: FS_FLOAT; + x3: FS_FLOAT; + y3: FS_FLOAT; + x4: FS_FLOAT; + y4: FS_FLOAT; + end; + PFSQuadPointsF = ^TFSQuadPointsF; + TFSQuadPointsF = FS_QUADPOINTSF; + // Annotation enums. FPDF_ANNOTATION_SUBTYPE = Integer; + PFPDF_ANNOTATION_SUBTYPE = ^FPDF_ANNOTATION_SUBTYPE; FPDF_ANNOT_APPEARANCEMODE = Integer; // Dictionary value types. FPDF_OBJECT_TYPE = Integer; -// Function: FPDF_InitLibrary -// Initialize the FPDFSDK library -// Parameters: -// None -// Return value: -// None. -// Comments: -// Convenience function to call FPDF_InitLibraryWithConfig() for -// backwards compatibility purposes. This will be deprecated in the -// future. -var - FPDF_InitLibrary: procedure(); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// PDF renderer types - Experimental. +// Selection of 2D graphics library to use for rendering to FPDF_BITMAPs. +type + FPDF_RENDERER_TYPE = Integer; +const + // Anti-Grain Geometry - https://sourceforge.net/projects/agg/ + FPDF_RENDERERTYPE_AGG = 0; + // Skia - https://skia.org/ + FPDF_RENDERERTYPE_SKIA = 1; + +// PDF font library types - Experimental. +// Selection of font backend library to use. +type + FPDF_FONT_BACKEND_TYPE = Integer; +const + // FreeType - https://freetype.org/ + FPDF_FONTBACKENDTYPE_FREETYPE = 0; + // Fontations - https://github.com/googlefonts/fontations/ + FPDF_FONTBACKENDTYPE_FONTATIONS = 1; type // Process-wide options for initializing the library. @@ -247,7 +297,7 @@ FPDF_LIBRARY_CONFIG = record // Version 2. - // pointer to the v8::Isolate to use, or NULL to force PDFium to create one. + // Pointer to the v8::Isolate to use, or NULL to force PDFium to create one. m_pIsolate: Pointer; // The embedder data slot to use in the v8::Isolate to store PDFium's @@ -255,12 +305,40 @@ FPDF_LIBRARY_CONFIG = record // [0, |v8::Internals::kNumIsolateDataLots|). Note that 0 is fine for most // embedders. m_v8EmbedderSlot: Cardinal; + + // Version 3 - Experimental. + + // Pointer to the V8::Platform to use. + m_pPlatform: Pointer; + + // Version 4 - Experimental. + + // Explicit specification of 2D graphics rendering library to use. + // |m_RendererType| must be a valid value for |FPDF_LIBRARY_CONFIG| versions + // of this level or higher, or else the initialization will fail with an + // immediate crash. + // Note that use of a specified |FPDF_RENDERER_TYPE| value for which the + // corresponding 2D graphics rendering library is not included in the build + // will similarly fail with an immediate crash. + m_RendererType: FPDF_RENDERER_TYPE; + + // Version 5 - Experimental. + + // Explicit specification of font library to use when |m_RendererType| is set + // to |FPDF_RENDERERTYPE_SKIA|. + // |m_FontLibraryType| must be a valid value for |FPDF_LIBRARY_CONFIG| + // versions of this level or higher, or else the initialization will fail with + // an immediate crash. + // Note that use of a specified |FPDF_FONT_BACKEND_TYPE| value for which the + // corresponding font library is not included in the build will similarly fail + // with an immediate crash. + m_FontLibraryType: FPDF_FONT_BACKEND_TYPE; end; PFPdfLibraryConfig = ^TFPdfLibraryConfig; TFPdfLibraryConfig = FPDF_LIBRARY_CONFIG; // Function: FPDF_InitLibraryWithConfig -// Initialize the FPDFSDK library +// Initialize the PDFium library and allocate global resources for it. // Parameters: // config - configuration information as above. // Return value: @@ -271,15 +349,34 @@ FPDF_LIBRARY_CONFIG = record var FPDF_InitLibraryWithConfig: procedure(config: PFPDF_LIBRARY_CONFIG); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Function: FPDF_InitLibrary +// Initialize the PDFium library (alternative form). +// Parameters: +// None +// Return value: +// None. +// Comments: +// Convenience function to call FPDF_InitLibraryWithConfig() with a +// default configuration for backwards compatibility purposes. New +// code should call FPDF_InitLibraryWithConfig() instead. This will +// be deprecated in the future. +var + FPDF_InitLibrary: procedure(); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // Function: FPDF_DestroyLibary -// Release all resources allocated by the FPDFSDK library. +// Release global resources allocated to the PDFium library by +// FPDF_InitLibrary() or FPDF_InitLibraryWithConfig(). // Parameters: // None. // Return value: // None. // Comments: -// You can call this function to release all memory blocks allocated by the library. -// After this function is called, you should not call any PDF processing functions. +// After this function is called, you must not call any PDF +// processing functions. +// +// Calling this function does not automatically close other +// objects. It is recommended to close other objects before +// closing the library with this function. var FPDF_DestroyLibrary: procedure(); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; @@ -299,44 +396,29 @@ FPDF_LIBRARY_CONFIG = record FPDF_SetSandBoxPolicy: procedure(policy: FPDF_DWORD; enable: FPDF_BOOL); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; {$IFDEF MSWINDOWS} - {$IFDEF PDFIUM_PRINT_TEXT_WITH_GDI} -// Pointer to a helper function to make |font| with |text| of |text_length| -// accessible when printing text with GDI. This is useful in sandboxed -// environments where PDFium's access to GDI may be restricted. -type - TPDFiumEnsureTypefaceCharactersAccessible = procedure(font: PLogFont; text: PWideChar; text_length: SIZE_T); cdecl; - -// Function: FPDF_SetTypefaceAccessibleFunc -// Set the function pointer that makes GDI fonts available in sandboxed -// environments. Experimental API. -// Parameters: -// func - A function pointer. See description above. -// Return value: -// None. -var - FPDF_SetTypefaceAccessibleFunc: procedure(func: TPDFiumEnsureTypefaceCharactersAccessible); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; - -// Function: FPDF_SetPrintTextWithGDI -// Set whether to use GDI to draw fonts when printing on Windows. -// Experimental API. -// Parameters: -// use_gdi - Set to true to enable printing text with GDI. -// Return value: -// None. -var - FPDF_SetPrintTextWithGDI: procedure(use_gdi: FPDF_BOOL); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; - {$ENDIF PDFIUM_PRINT_TEXT_WITH_GDI} - +// Experimental API. // Function: FPDF_SetPrintMode // Set printing mode when printing on Windows. -// Experimental API. // Parameters: // mode - FPDF_PRINTMODE_EMF to output EMF (default) -// FPDF_PRINTMODE_TEXTONLY to output text only (for charstream devices) -// FPDF_PRINTMODE_POSTSCRIPT2 to output level 2 PostScript into EMF as a series of GDI comments. -// FPDF_PRINTMODE_POSTSCRIPT3 to output level 3 PostScript into EMF as a series of GDI comments. -// FPDF_PRINTMODE_POSTSCRIPT2_PASSTHROUGH to output level 2 PostScript via ExtEscape() in PASSTHROUGH mode. -// FPDF_PRINTMODE_POSTSCRIPT3_PASSTHROUGH to output level 3 PostScript via ExtEscape() in PASSTHROUGH mode. +// FPDF_PRINTMODE_TEXTONLY to output text only (for charstream +// devices) +// FPDF_PRINTMODE_POSTSCRIPT2 to output level 2 PostScript into +// EMF as a series of GDI comments. +// FPDF_PRINTMODE_POSTSCRIPT3 to output level 3 PostScript into +// EMF as a series of GDI comments. +// FPDF_PRINTMODE_POSTSCRIPT2_PASSTHROUGH to output level 2 +// PostScript via ExtEscape() in PASSTHROUGH mode. +// FPDF_PRINTMODE_POSTSCRIPT3_PASSTHROUGH to output level 3 +// PostScript via ExtEscape() in PASSTHROUGH mode. +// FPDF_PRINTMODE_EMF_IMAGE_MASKS to output EMF, with more +// efficient processing of documents containing image masks. +// FPDF_PRINTMODE_POSTSCRIPT3_TYPE42 to output level 3 +// PostScript with embedded Type 42 fonts, when applicable, into +// EMF as a series of GDI comments. +// FPDF_PRINTMODE_POSTSCRIPT3_TYPE42_PASSTHROUGH to output level +// 3 PostScript with embedded Type 42 fonts, when applicable, +// via ExtEscape() in PASSTHROUGH mode. // Return value: // True if successful, false if unsuccessful (typically invalid input). var @@ -357,6 +439,8 @@ FPDF_LIBRARY_CONFIG = record // If this function fails, you can use FPDF_GetLastError() to retrieve // the reason why it failed. // +// The encoding for |file_path| is UTF-8. +// // The encoding for |password| can be either UTF-8 or Latin-1. PDFs, // depending on the security handler revision, will only accept one or // the other encoding. If |password|'s encoding and the PDF's expected @@ -389,6 +473,31 @@ FPDF_LIBRARY_CONFIG = record var FPDF_LoadMemDocument: function(data_buf: Pointer; size: Integer; password: FPDF_BYTESTRING): FPDF_DOCUMENT; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Experimental API. +// Function: FPDF_LoadMemDocument64 +// Open and load a PDF document from memory. +// Parameters: +// data_buf - Pointer to a buffer containing the PDF document. +// size - Number of bytes in the PDF document. +// password - A string used as the password for the PDF file. +// If no password is needed, empty or NULL can be used. +// Return value: +// A handle to the loaded document, or NULL on failure. +// Comments: +// The memory buffer must remain valid when the document is open. +// The loaded document can be closed by FPDF_CloseDocument. +// If this function fails, you can use FPDF_GetLastError() to retrieve +// the reason why it failed. +// +// See the comments for FPDF_LoadDocument() regarding the encoding for +// |password|. +// Notes: +// If PDFium is built with the XFA module, the application should call +// FPDF_LoadXFA() function after the PDF document loaded to support XFA +// fields defined in the fpdfformfill.h file. +var + FPDF_LoadMemDocument64: function(data_buf: Pointer; size: SIZE_T; password: FPDF_BYTESTRING): FPDF_DOCUMENT; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // Structure for custom file access. type PFPDF_FILEACCESS = ^FPDF_FILEACCESS; @@ -400,7 +509,7 @@ FPDF_FILEACCESS = record // Position is specified by byte offset from the beginning of the file. // The pointer to the buffer is never NULL and the size is never 0. // The position and size will never go out of range of the file length. - // It may be possible for FPDFSDK to call this function multiple times for + // It may be possible for PDFium to call this function multiple times for // the same position. // Return value: should be non-zero if successful, zero for error. m_GetBlock: function(param: Pointer; position: LongWord; pBuf: PByte; size: LongWord): Integer; cdecl; @@ -412,88 +521,79 @@ FPDF_FILEACCESS = record PFPdfFileAccess = ^TFPdfFileAccess; TFPdfFileAccess = FPDF_FILEACCESS; - //* - //* Structure for file reading or writing (I/O). - //* - //* Note: This is a handler and should be implemented by callers, - //* + // Structure for file reading or writing (I/O). + // + // Note: This is a handler and should be implemented by callers, + // and is only used from XFA. PFPDF_FILEHANDLER = ^FPDF_FILEHANDLER; FPDF_FILEHANDLER = record - //* - //* User-defined data. - //* Node: Callers can use this field to track controls. - //* + // User-defined data. + // Note: Callers can use this field to track controls. clientData: Pointer; - //* - //* Callback function to release the current file stream object. - //* - //* Parameters: - //* clientData - Pointer to user-defined data. - //* Returns: - //* None. - //* + + // Callback function to release the current file stream object. + // + // Parameters: + // clientData - Pointer to user-defined data. + // Returns: + // None. Release: procedure(clientData: Pointer); cdecl; - //* - //* Callback function to retrieve the current file stream size. - //* - //* Parameters: - //* clientData - Pointer to user-defined data. - //* Returns: - //* Size of file stream. - //* + + // Callback function to retrieve the current file stream size. + // + // Parameters: + // clientData - Pointer to user-defined data. + // Returns: + // Size of file stream. GetSize: function(clientData: Pointer): FPDF_DWORD; cdecl; - //* - //* Callback function to read data from the current file stream. - //* - //* Parameters: - //* clientData - Pointer to user-defined data. - //* offset - Offset position starts from the beginning of file - //* stream. This parameter indicates reading position. - //* buffer - Memory buffer to store data which are read from - //* file stream. This parameter should not be NULL. - //* size - Size of data which should be read from file stream, - //* in bytes. The buffer indicated by |buffer| must be - //* large enough to store specified data. - //* Returns: - //* 0 for success, other value for failure. - //* + + // Callback function to read data from the current file stream. + // + // Parameters: + // clientData - Pointer to user-defined data. + // offset - Offset position starts from the beginning of file + // stream. This parameter indicates reading position. + // buffer - Memory buffer to store data which are read from + // file stream. This parameter should not be NULL. + // size - Size of data which should be read from file stream, + // in bytes. The buffer indicated by |buffer| must be + // large enough to store specified data. + // Returns: + // 0 for success, other value for failure. ReadBlock: function(clientData: Pointer; offset: FPDF_DWORD; buffer: Pointer; size: FPDF_DWORD): FPDF_RESULT; cdecl; - //* - //* Callback function to write data into the current file stream. - //* - //* Parameters: - //* clientData - Pointer to user-defined data. - //* offset - Offset position starts from the beginning of file - //* stream. This parameter indicates writing position. - //* buffer - Memory buffer contains data which is written into - //* file stream. This parameter should not be NULL. - //* size - Size of data which should be written into file - //* stream, in bytes. - //* Returns: - //* 0 for success, other value for failure. - //* + + // Callback function to write data into the current file stream. + // + // Parameters: + // clientData - Pointer to user-defined data. + // offset - Offset position starts from the beginning of file + // stream. This parameter indicates writing position. + // buffer - Memory buffer contains data which is written into + // file stream. This parameter should not be NULL. + // size - Size of data which should be written into file + // stream, in bytes. + // Returns: + // 0 for success, other value for failure. WriteBlock: function(clientData: Pointer; offset: FPDF_DWORD; const buffer: Pointer; size: FPDF_DWORD): FPDF_RESULT; cdecl; - //** - //* Callback function to flush all internal accessing buffers. - //* - //* Parameters: - //* clientData - Pointer to user-defined data. - //* Returns: - //* 0 for success, other value for failure. - //* + + // Callback function to flush all internal accessing buffers. + // + // Parameters: + // clientData - Pointer to user-defined data. + // Returns: + // 0 for success, other value for failure. Flush: function(clientData: Pointer): FPDF_RESULT; cdecl; - //** - //* Callback function to change file size. - //* - //* Description: - //* This function is called under writing mode usually. Implementer - //* can determine whether to realize it based on application requests. - //* Parameters: - //* clientData - Pointer to user-defined data. - //* size - New size of file stream, in bytes. - //* Returns: - //* 0 for success, other value for failure. - //* + + // Callback function to change file size. + // + // Description: + // This function is called under writing mode usually. Implementer + // can determine whether to realize it based on application requests. + // Parameters: + // clientData - Pointer to user-defined data. + // size - New size of file stream, in bytes. + // Returns: + // 0 for success, other value for failure. Truncate: function(clientData: Pointer; size: FPDF_DWORD): FPDF_RESULT; cdecl; end; PFPdfFileHandler = ^TFPdfFileHandler; @@ -556,13 +656,14 @@ FPDF_FILEHANDLER = record // A 32-bit integer indicating error code as defined above. // Comments: // If the previous SDK call succeeded, the return value of this -// function is not defined. +// function is not defined. This function only works in conjunction +// with APIs that mention FPDF_GetLastError() in their documentation. var FPDF_GetLastError: function(): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Experimental API. // Function: FPDF_DocumentHasValidCrossReferenceTable // Whether the document's cross reference table is valid or not. -// Experimental API. // Parameters: // document - Handle to a document. Returned by FPDF_LoadDocument. // Return value: @@ -575,17 +676,45 @@ FPDF_FILEHANDLER = record var FPDF_DocumentHasValidCrossReferenceTable: function(document: FPDF_DOCUMENT): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -// Function: FPDF_GetDocPermission +// Experimental API. +// Function: FPDF_GetTrailerEnds +// Get the byte offsets of trailer ends. +// Parameters: +// document - Handle to document. Returned by FPDF_LoadDocument(). +// buffer - The address of a buffer that receives the +// byte offsets. +// length - The size, in ints, of |buffer|. +// Return value: +// Returns the number of ints in the buffer on success, 0 on error. +// +// |buffer| is an array of integers that describes the exact byte offsets of the +// trailer ends in the document. If |length| is less than the returned length, +// or |document| or |buffer| is NULL, |buffer| will not be modified. +var + FPDF_GetTrailerEnds: function(document: FPDF_DOCUMENT; buffer: PUINT; length: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Function: FPDF_GetDocPermissions // Get file permission flags of the document. // Parameters: // document - Handle to a document. Returned by FPDF_LoadDocument. // Return value: // A 32-bit integer indicating permission flags. Please refer to the // PDF Reference for detailed descriptions. If the document is not -// protected, 0xffffffff will be returned. +// protected or was unlocked by the owner, 0xffffffff will be returned. var FPDF_GetDocPermissions: function(document: FPDF_DOCUMENT): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Function: FPDF_GetDocUserPermissions +// Get user file permission flags of the document. +// Parameters: +// document - Handle to a document. Returned by FPDF_LoadDocument. +// Return value: +// A 32-bit integer indicating permission flags. Please refer to the +// PDF Reference for detailed descriptions. If the document is not +// protected, 0xffffffff will be returned. Always returns user +// permissions, even if the document was unlocked by the owner. +var + FPDF_GetDocUserPermissions: function(document: FPDF_DOCUMENT): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; // Function: FPDF_GetSecurityHandlerRevision // Get the revision for the security handler. @@ -628,6 +757,8 @@ FPDF_FILEHANDLER = record // Return value: // Page width (excluding non-displayable area) measured in points. // One point is 1/72 inch (around 0.3528 mm). +// Comments: +// Changing the rotation of |page| affects the return value. var FPDF_GetPageWidthF: function(page: FPDF_PAGE): Single; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; @@ -642,6 +773,8 @@ FPDF_FILEHANDLER = record // Note: // Prefer FPDF_GetPageWidthF() above. This will be deprecated in the // future. +// Comments: +// Changing the rotation of |page| affects the return value. var FPDF_GetPageWidth: function(page: FPDF_PAGE): Double; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; @@ -653,6 +786,8 @@ FPDF_FILEHANDLER = record // Return value: // Page height (excluding non-displayable area) measured in points. // One point is 1/72 inch (around 0.3528 mm) +// Comments: +// Changing the rotation of |page| affects the return value. var FPDF_GetPageHeightF: function(page: FPDF_PAGE): Single; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; @@ -666,6 +801,8 @@ FPDF_FILEHANDLER = record // Note: // Prefer FPDF_GetPageHeightF() above. This will be deprecated in the // future. +// Comments: +// Changing the rotation of |page| affects the return value. var FPDF_GetPageHeight: function(page: FPDF_PAGE): Double; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; @@ -715,7 +852,7 @@ FPDF_FILEHANDLER = record // Page rendering flags. They can be combined with bit-wise OR. const FPDF_ANNOT = $01; // Set if annotations are to be rendered. - FPDF_LCD_TEXT = $02; // Set if using text rendering optimized for LCD display. + FPDF_LCD_TEXT = $02; // Set if using text rendering optimized for LCD display. This flag will only take effect if anti-aliasing is enabled for text. FPDF_NO_NATIVETEXT = $04; // Don't use the native text output available on some platforms FPDF_GRAYSCALE = $08 deprecated; // Obsolete, has no effect, retained for compatibility. FPDF_DEBUG_INFO = $80 deprecated; // Obsolete, has no effect, retained for compatibility. @@ -723,12 +860,30 @@ FPDF_FILEHANDLER = record FPDF_RENDER_LIMITEDIMAGECACHE = $200; // Limit image cache size. FPDF_RENDER_FORCEHALFTONE = $400; // Always use halftone for image stretching. FPDF_PRINTING = $800; // Render for printing. - FPDF_RENDER_NO_SMOOTHTEXT = $1000; // Set to disable anti-aliasing on text. + FPDF_RENDER_NO_SMOOTHTEXT = $1000; // Set to disable anti-aliasing on text. This flag will also disable LCD optimization for text rendering. FPDF_RENDER_NO_SMOOTHIMAGE = $2000; // Set to disable anti-aliasing on images. FPDF_RENDER_NO_SMOOTHPATH = $4000; // Set to disable anti-aliasing on paths. // Set whether to render in a reverse Byte order, this flag is only used when // rendering to a bitmap. FPDF_REVERSE_BYTE_ORDER = $10; + // Set whether fill paths need to be stroked. This flag is only used when + // FPDF_COLORSCHEME is passed in, since with a single fill color for paths the + // boundaries of adjacent fill paths are less visible. + FPDF_CONVERT_FILL_TO_STROKE = $20; + +type + // Struct for color scheme. + // Each should be a 32-bit value specifying the color, in 8888 ARGB format. + + PFPDF_COLORSCHEME = ^FPDF_COLORSCHEME; + FPDF_COLORSCHEME = record + path_fill_color: FPDF_DWORD; + path_stroke_color: FPDF_DWORD; + text_fill_color: FPDF_DWORD; + text_stroke_color: FPDF_DWORD; + end; + PFPdfColorScheme = ^TFPdfColorScheme; + TFPdfColorScheme = FPDF_COLORSCHEME; {$IFDEF MSWINDOWS} // Function: FPDF_RenderPage @@ -751,10 +906,10 @@ FPDF_FILEHANDLER = record // flags - 0 for normal display, or combination of flags // defined above. // Return value: -// None. +// Returns true if the page is rendered successfully, false otherwise. var - FPDF_RenderPage: procedure(DC: HDC; page: FPDF_PAGE; start_x, start_y, size_x, size_y: Integer; - rotate: Integer; flags: Integer); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + FPDF_RenderPage: function(DC: HDC; page: FPDF_PAGE; start_x, start_y, size_x, size_y: Integer; + rotate: Integer; flags: Integer): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; {$ENDIF MSWINDOWS} // Function: FPDF_RenderPageBitmap @@ -809,10 +964,19 @@ FPDF_FILEHANDLER = record FPDF_RenderPageBitmapWithMatrix: procedure(bitmap: FPDF_BITMAP; page: FPDF_PAGE; matrix: PFS_MATRIX; clipping: PFS_RECTF; flags: Integer); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -{$IFDEF _SKIA_SUPPORT_} +{$IFDEF PDF_USE_SKIA} +// Function: FPDF_RenderPageSkia +// Render contents of a page to a Skia SkCanvas. +// Parameters: +// canvas - SkCanvas to render to. +// page - Handle to the page. +// size_x - Horizontal size (in pixels) for displaying the page. +// size_y - Vertical size (in pixels) for displaying the page. +// Return value: +// None. var - FPDF_RenderPageSkp: function(page: FPDF_PAGE; size_x, size_y: Integer): FPDF_RECORDER; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -{$ENDIF _SKIA_SUPPORT_} + FPDF_RenderPageSkia: procedure(canvas: FPDF_SKIA_CANVAS; page: FPDF_PAGE; size_x, size_y: Integer); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +{$ENDIF PDF_USE_SKIA} // Function: FPDF_ClosePage // Close a loaded PDF page. @@ -942,11 +1106,17 @@ FPDF_FILEHANDLER = record const // More DIB formats - FPDFBitmap_Unknown = 0; // Unknown or unsupported format. - FPDFBitmap_Gray = 1; // Gray scale bitmap, one byte per pixel. - FPDFBitmap_BGR = 2; // 3 bytes per pixel, byte order: blue, green, red. - FPDFBitmap_BGRx = 3; // 4 bytes per pixel, byte order: blue, green, red, unused. - FPDFBitmap_BGRA = 4; // 4 bytes per pixel, byte order: blue, green, red, alpha. + FPDFBitmap_Unknown = 0; // Unknown or unsupported format. + // All of the colors are listed in order of LSB to MSB. + FPDFBitmap_Gray = 1; // Gray scale bitmap, one byte per pixel. + FPDFBitmap_BGR = 2; // 3 bytes per pixel, byte order: blue, green, red. + FPDFBitmap_BGRx = 3; // 4 bytes per pixel, byte order: blue, green, red, unused. + FPDFBitmap_BGRA = 4; // 4 bytes per pixel, byte order: blue, green, red, alpha. + // Pixel components are independent of alpha. + FPDFBitmap_BGRA_Premul = 5; // 4 bytes per pixel, byte order: blue, green, red, alpha. + // Pixel components are premultiplied by alpha. + // Note that this is experimental and only supported when rendering with + // |FPDF_RENDERER_TYPE| is set to |FPDF_RENDERERTYPE_SKIA|. // Function: FPDFBitmap_CreateEx // Create a device independent bitmap (FXDIB) @@ -960,8 +1130,15 @@ FPDF_FILEHANDLER = record // first_scan - A pointer to the first byte of the first line if // using an external buffer. If this parameter is NULL, // then the a new buffer will be created. -// stride - Number of bytes for each scan line, for external -// buffer only. +// then a new buffer will be created. +// stride - Number of bytes for each scan line. The value must +// be 0 or greater. When the value is 0, +// FPDFBitmap_CreateEx() will automatically calculate +// the appropriate value using |width| and |format|. +// When using an external buffer, it is recommended for +// the caller to pass in the value. +// When not using an external buffer, it is recommended +// for the caller to pass in 0. // Return value: // The bitmap handle, or NULL if parameter error or out of memory. // Comments: @@ -970,9 +1147,11 @@ FPDF_FILEHANDLER = record // function can be used in any place that a FPDF_BITMAP handle is // required. // -// If an external buffer is used, then the application should destroy -// the buffer by itself. FPDFBitmap_Destroy function will not destroy -// the buffer. +// If an external buffer is used, then the caller should destroy the +// buffer. FPDFBitmap_Destroy() will not destroy the buffer. +// +// It is recommended to use FPDFBitmap_GetStride() to get the stride +// value. var FPDFBitmap_CreateEx: function(width, height: Integer; format: Integer; first_scan: Pointer; stride: Integer): FPDF_BITMAP; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; @@ -1004,7 +1183,7 @@ FPDF_FILEHANDLER = record // color - A 32-bit value specifing the color, in 8888 ARGB // format. // Return value: -// None. +// Returns whether the operation succeeded or not. // Comments: // This function sets the color and (optionally) alpha value in the // specified region of the bitmap. @@ -1015,7 +1194,7 @@ FPDF_FILEHANDLER = record // // If the alpha channel is not used, the alpha parameter is ignored. var - FPDFBitmap_FillRect: procedure(bitmap: FPDF_BITMAP; left, top, width, height: Integer; color: FPDF_DWORD); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + FPDFBitmap_FillRect: function(bitmap: FPDF_BITMAP; left, top, width, height: Integer; color: FPDF_DWORD): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; // Function: FPDFBitmap_GetBuffer // Get data buffer of a bitmap. @@ -1031,8 +1210,7 @@ FPDF_FILEHANDLER = record // then manipulate any color and/or alpha values for any pixels in the // bitmap. // -// The data is in BGRA format. Where the A maybe unused if alpha was -// not specified. +// Use FPDFBitmap_GetFormat() to find out the format of the data. var FPDFBitmap_GetBuffer: function(bitmap: FPDF_BITMAP): Pointer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; @@ -1108,9 +1286,9 @@ FPDF_FILEHANDLER = record var FPDF_VIEWERREF_GetPrintPageRange: function(document: FPDF_DOCUMENT): FPDF_PAGERANGE; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Experimental API. // Function: FPDF_VIEWERREF_GetPrintPageRangeCount // Returns the number of elements in a FPDF_PAGERANGE. -// Experimental API. // Parameters: // pagerange - Handle to the page range. // Return value: @@ -1118,9 +1296,9 @@ FPDF_FILEHANDLER = record var FPDF_VIEWERREF_GetPrintPageRangeCount: function(pagerange: FPDF_PAGERANGE): SIZE_T; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Experimental API. // Function: FPDF_VIEWERREF_GetPrintPageRangeElement // Returns an element from a FPDF_PAGERANGE. -// Experimental API. // Parameters: // pagerange - Handle to the page range. // index - Index of the element. @@ -1147,14 +1325,15 @@ FPDF_FILEHANDLER = record // document - Handle to the loaded document. // key - Name of the key in the viewer pref dictionary, // encoded in UTF-8. -// buffer - A string to write the contents of the key to. +// buffer - Caller-allocate buffer to receive the key, or NULL +// - to query the required length. // length - Length of the buffer. // Return value: // The number of bytes in the contents, including the NULL terminator. // Thus if the return value is 0, then that indicates an error, such // as when |document| is invalid or |buffer| is NULL. If |length| is -// less than the returned length, or |buffer| is NULL, |buffer| will -// not be modified. +// as when |document| is invalid. If |length| is less than the required +// length, or |buffer| is NULL, |buffer| will not be modified. var FPDF_VIEWERREF_GetName: function(document: FPDF_DOCUMENT; key: FPDF_BYTESTRING; buffer: PAnsiChar; length: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; @@ -1202,6 +1381,60 @@ FPDF_FILEHANDLER = record var FPDF_GetNamedDest: function(document: FPDF_DOCUMENT; index: Integer; buffer: Pointer; var buflen: LongWord): FPDF_DEST; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Experimental API. +// Function: FPDF_GetXFAPacketCount +// Get the number of valid packets in the XFA entry. +// Parameters: +// document - Handle to the document. +// Return value: +// The number of valid packets, or -1 on error. +var + FPDF_GetXFAPacketCount: function(document: FPDF_DOCUMENT): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Function: FPDF_GetXFAPacketName +// Get the name of a packet in the XFA array. +// Parameters: +// document - Handle to the document. +// index - Index number of the packet. 0 for the first packet. +// buffer - Buffer for holding the name of the XFA packet. +// buflen - Length of |buffer| in bytes. +// Return value: +// The length of the packet name in bytes, or 0 on error. +// +// |document| must be valid and |index| must be in the range [0, N), where N is +// the value returned by FPDF_GetXFAPacketCount(). +// |buffer| is only modified if it is non-NULL and |buflen| is greater than or +// equal to the length of the packet name. The packet name includes a +// terminating NUL character. |buffer| is unmodified on error. +var + FPDF_GetXFAPacketName: function(document: FPDF_DOCUMENT; index: Integer; buffer: Pointer; buflen: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Function: FPDF_GetXFAPacketContent +// Get the content of a packet in the XFA array. +// Parameters: +// document - Handle to the document. +// index - Index number of the packet. 0 for the first packet. +// buffer - Buffer for holding the content of the XFA packet. +// buflen - Length of |buffer| in bytes. +// out_buflen - Pointer to the variable that will receive the minimum +// buffer size needed to contain the content of the XFA +// packet. +// Return value: +// Whether the operation succeeded or not. +// +// |document| must be valid and |index| must be in the range [0, N), where N is +// the value returned by FPDF_GetXFAPacketCount(). |out_buflen| must not be +// NULL. When the aforementioned arguments are valid, the operation succeeds, +// and |out_buflen| receives the content size. |buffer| is only modified if +// |buffer| is non-null and long enough to contain the content. Callers must +// check both the return value and the input |buflen| is no less than the +// returned |out_buflen| before using the data in |buffer|. +var + FPDF_GetXFAPacketContent: function(document: FPDF_DOCUMENT; index: Integer; buffer: Pointer; + buflen: LongWord; var out_buflen: LongWord): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + {$IFDEF PDF_ENABLE_V8} // Function: FPDF_GetRecommendedV8Flags // Returns a space-separated string of command line flags that are @@ -1214,6 +1447,25 @@ FPDF_FILEHANDLER = record // The caller must not attempt to modify or free the result. var FPDF_GetRecommendedV8Flags: function: PAnsiChar; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Function: FPDF_GetArrayBufferAllocatorSharedInstance() +// Helper function for initializing V8 isolates that will +// use PDFium's internal memory management. +// Parameters: +// None. +// Return Value: +// Pointer to a suitable v8::ArrayBuffer::Allocator, returned +// as void for C compatibility. +// Notes: +// Use is optional, but allows external creation of isolates +// matching the ones PDFium will make when none is provided +// via |FPDF_LIBRARY_CONFIG::m_pIsolate|. +// +// Can only be called when the library is in an uninitialized or +// destroyed state. +var + FPDF_GetArrayBufferAllocatorSharedInstance: function: Pointer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; {$ENDIF PDF_ENABLE_V8} {$IFDEF PDF_ENABLE_XFA} @@ -1287,12 +1539,16 @@ function FPDF_GetAValue(argb: DWORD): Byte; inline; FPDF_LINEJOIN_ROUND = 1; FPDF_LINEJOIN_BEVEL = 2; + // See FPDF_SetPrintMode() for descriptions. FPDF_PRINTMODE_EMF = 0; FPDF_PRINTMODE_TEXTONLY = 1; FPDF_PRINTMODE_POSTSCRIPT2 = 2; FPDF_PRINTMODE_POSTSCRIPT3 = 3; FPDF_PRINTMODE_POSTSCRIPT2_PASSTHROUGH = 4; FPDF_PRINTMODE_POSTSCRIPT3_PASSTHROUGH = 5; + FPDF_PRINTMODE_EMF_IMAGE_MASKS = 6; + FPDF_PRINTMODE_POSTSCRIPT3_TYPE42 = 7; + FPDF_PRINTMODE_POSTSCRIPT3_TYPE42_PASSTHROUGH= 8; type PFPDF_IMAGEOBJ_METADATA = ^FPDF_IMAGEOBJ_METADATA; @@ -1345,6 +1601,36 @@ FPDF_IMAGEOBJ_METADATA = record var FPDFPage_Delete: procedure(document: FPDF_DOCUMENT; page_index: Integer); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Experimental API. +// Move the given pages to a new index position. +// +// page_indices - the ordered list of pages to move. No duplicates allowed. +// page_indices_len - the number of elements in |page_indices| +// dest_page_index - the new index position to which the pages in +// |page_indices| are moved. +// +// Returns TRUE on success. If it returns FALSE, the document may be left in an +// indeterminate state. +// +// Example: The PDF document starts out with pages [A, B, C, D], with indices +// [0, 1, 2, 3]. +// +// > Move(doc, [3, 2], 2, 1); // returns true +// > // The document has pages [A, D, C, B]. +// > +// > Move(doc, [0, 4, 3], 3, 1); // returns false +// > // Returned false because index 4 is out of range. +// > +// > Move(doc, [0, 3, 1], 3, 2); // returns false +// > // Returned false because index 2 is out of range for 3 page indices. +// > +// > Move(doc, [2, 2], 2, 0); // returns false +// > // Returned false because [2, 2] contains duplicates. +// +var + FPDF_MovePages: function(document: FPDF_DOCUMENT; page_indices: PInteger; page_indices_len: LongWord; + dest_page_index: Integer): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // Get the rotation of |page|. // // page - handle to a page @@ -1354,6 +1640,8 @@ FPDF_IMAGEOBJ_METADATA = record // 1 - Rotated 90 degrees clockwise. // 2 - Rotated 180 degrees clockwise. // 3 - Rotated 270 degrees clockwise. +// +// Or returns -1 on error. var FPDFPage_GetRotation: function(page: FPDF_PAGE): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; @@ -1368,26 +1656,48 @@ FPDF_IMAGEOBJ_METADATA = record var FPDFPage_SetRotation: procedure(page: FPDF_PAGE; rotate: Integer); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -// Insert |page_obj| into |page|. +// Insert |page_object| into |page|. +// +// page - Handle to a page. +// page_object - Handle to a page object. FPDFPage_InsertObject() takes +// ownership. Ownership of |page_object| transfers to |page| on +// success. |page_object| is freed on failure. Null +// |page_object| causes a failure. +// +// Returns true if successful. +var + FPDFPage_InsertObject: function(page: FPDF_PAGE; page_object: FPDF_PAGEOBJECT): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Insert |page_object| into |page| at the specified |index|. // -// page - handle to a page -// page_obj - handle to a page object. The |page_obj| will be automatically -// freed. +// page - handle to a page +// page_object - handle to a page object as previously obtained by +// FPDFPageObj_CreateNew{Path|Rect}() or +// FPDFPageObj_New{Text|Image}Obj(). Ownership of the object +// is transferred back to PDFium. +// index - the index position to insert the object at. If index equals +// the current object count, the object will be appended to the +// end. If index is greater than the object count, the function +// will fail and return false. +// +// Returns true if successful. var - FPDFPage_InsertObject: procedure(page: FPDF_PAGE; page_obj: FPDF_PAGEOBJECT); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + FPDFPage_InsertObjectAtIndex: function(page: FPDF_PAGE; page_object: FPDF_PAGEOBJECT; index: SIZE_T): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; // Experimental API. -// Remove |page_obj| from |page|. +// Remove |page_object| from |page|. // -// page - handle to a page -// page_obj - handle to a page object to be removed. +// page - handle to a page +// page_object - handle to a page object to be removed. // // Returns TRUE on success. // // Ownership is transferred to the caller. Call FPDFPageObj_Destroy() to free // it. +// Note that when removing a |page_object| of type FPDF_PAGEOBJ_TEXT, all +// FPDF_TEXTPAGE handles for |page| are no longer valid. var - FPDFPage_RemoveObject: function(page: FPDF_PAGE; page_obj: FPDF_PAGEOBJECT): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + FPDFPage_RemoveObject: function(page: FPDF_PAGE; page_object: FPDF_PAGEOBJECT): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; // Get number of page objects inside |page|. // @@ -1425,13 +1735,13 @@ FPDF_IMAGEOBJ_METADATA = record var FPDFPage_GenerateContent: function(page: FPDF_PAGE): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -// Destroy |page_obj| by releasing its resources. |page_obj| must have been -// created by FPDFPageObj_CreateNew{Path|Rect}() or +// Destroy |page_object| by releasing its resources. |page_object| must have +// been created by FPDFPageObj_CreateNew{Path|Rect}() or // FPDFPageObj_New{Text|Image}Obj(). This function must be called on // newly-created objects if they are not added to a page through // FPDFPage_InsertObject() or to an annotation through FPDFAnnot_AppendObject(). // -// page_obj - handle to a page object. +// page_object - handle to a page object. var FPDFPageObj_Destroy: procedure(page_obj: FPDF_PAGEOBJECT); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; @@ -1452,6 +1762,38 @@ FPDF_IMAGEOBJ_METADATA = record var FPDFPageObj_GetType: function(page_object: FPDF_PAGEOBJECT): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Experimental API. +// Gets active state for |page_object| within page. +// +// page_object - handle to a page object. +// active - pointer to variable that will receive if the page object is +// active. This is a required parameter. Not filled if FALSE +// is returned. +// +// For page objects where |active| is filled with FALSE, the |page_object| is +// treated as if it wasn't in the document even though it is still held +// internally. +// +// Returns TRUE if the operation succeeded, FALSE if it failed. +var + FPDFPageObj_GetIsActive: function(page_object: FPDF_PAGEOBJECT; var active: FPDF_BOOL): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Sets if |page_object| is active within page. +// +// page_object - handle to a page object. +// active - a boolean specifying if the object is active. +// +// Returns TRUE on success. +// +// Page objects all start in the active state by default, and remain in that +// state unless this function is called. +// +// When |active| is false, this makes the |page_object| be treated as if it +// wasn't in the document even though it is still held internally. +var + FPDFPageObj_SetIsActive: function(page_object: FPDF_PAGEOBJECT; active: FPDF_BOOL): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // Transform |page_object| by the given matrix. // // page_object - handle to a page object. @@ -1469,6 +1811,56 @@ FPDF_IMAGEOBJ_METADATA = record var FPDFPageObj_Transform: procedure(page_object: FPDF_PAGEOBJECT; a, b, c, d, e, f: Double); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Experimental API. +// Transform |page_object| by the given matrix. +// +// page_object - handle to a page object. +// matrix - the transform matrix. +// +// Returns TRUE on success. +// +// This can be used to scale, rotate, shear and translate the |page_object|. +// It is an improved version of FPDFPageObj_Transform() that does not do +// unnecessary double to float conversions, and only uses 1 parameter for the +// matrix. It also returns whether the operation succeeded or not. +var + FPDFPageObj_TransformF: function(page_object: FPDF_PAGEOBJECT; matrix: PFS_MATRIX): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Get the transform matrix of a page object. +// +// page_object - handle to a page object. +// matrix - pointer to struct to receive the matrix value. +// +// The matrix is composed as: +// |a c e| +// |b d f| +// and used to scale, rotate, shear and translate the page object. +// +// For page objects outside form objects, the matrix values are relative to the +// page that contains it. +// For page objects inside form objects, the matrix values are relative to the +// form that contains it. +// +// Returns TRUE on success. +var + FPDFPageObj_GetMatrix: function(page_object: FPDF_PAGEOBJECT; matrix: PFS_MATRIX): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Set the transform matrix of a page object. +// +// page_object - handle to a page object. +// matrix - pointer to struct with the matrix value. +// +// The matrix is composed as: +// |a c e| +// |b d f| +// and can be used to scale, rotate, shear and translate the page object. +// +// Returns TRUE on success. +var + FPDFPageObj_SetMatrix: function(page_object: FPDF_PAGEOBJECT; const matrix: PFS_MATRIX): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // Transform all annotations in |page|. // // page - handle to a page. @@ -1494,6 +1886,15 @@ FPDF_IMAGEOBJ_METADATA = record var FPDFPageObj_NewImageObj: function(document: FPDF_DOCUMENT): FPDF_PAGEOBJECT; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Experimental API. +// Get the marked content ID for the object. +// +// page_object - handle to a page object. +// +// Returns the page object's marked content ID, or -1 on error. +var + FPDFPageObj_GetMarkedContentID: function(page_object: FPDF_PAGEOBJECT): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // Experimental API. // Get number of content marks in |page_object|. // @@ -1546,17 +1947,18 @@ FPDF_IMAGEOBJ_METADATA = record // // mark - handle to a content mark. // buffer - buffer for holding the returned name in UTF-16LE. This is only -// modified if |buflen| is longer than the length of the name. +// modified if |buflen| is large enough to store the name. // Optional, pass null to just retrieve the size of the buffer // needed. -// buflen - length of the buffer. +// buflen - length of the buffer in bytes. // out_buflen - pointer to variable that will receive the minimum buffer size -// to contain the name. Not filled if FALSE is returned. +// in bytes to contain the name. This is a required parameter. +// Not filled if FALSE is returned. // // Returns TRUE if the operation succeeded, FALSE if it failed. var - FPDFPageObjMark_GetName: function(mark: FPDF_PAGEOBJECTMARK; buffer: Pointer; buflen: LongWord; - out_buflen: PLongWord): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + FPDFPageObjMark_GetName: function(mark: FPDF_PAGEOBJECTMARK; buffer: PFPDF_WCHAR; buflen: LongWord; + var out_buflen: LongWord): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; // Experimental API. // Get the number of key/value pair parameters in |mark|. @@ -1574,17 +1976,18 @@ FPDF_IMAGEOBJ_METADATA = record // mark - handle to a content mark. // index - index of the property. // buffer - buffer for holding the returned key in UTF-16LE. This is only -// modified if |buflen| is longer than the length of the key. +// modified if |buflen| is large enough to store the key. // Optional, pass null to just retrieve the size of the buffer // needed. -// buflen - length of the buffer. +// buflen - length of the buffer in bytes. // out_buflen - pointer to variable that will receive the minimum buffer size -// to contain the key. Not filled if FALSE is returned. +// in bytes to contain the name. This is a required parameter. +// Not filled if FALSE is returned. // // Returns TRUE if the operation was successful, FALSE otherwise. var - FPDFPageObjMark_GetParamKey: function(mark: FPDF_PAGEOBJECTMARK; index: LongWord; buffer: Pointer; buflen: LongWord; - out_buflen: PLongWord): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + FPDFPageObjMark_GetParamKey: function(mark: FPDF_PAGEOBJECTMARK; index: LongWord; buffer: PFPDF_WCHAR; buflen: LongWord; + var out_buflen: LongWord): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; // Experimental API. // Get the type of the value of a property in a content mark by key. @@ -1612,24 +2015,39 @@ FPDF_IMAGEOBJ_METADATA = record FPDFPageObjMark_GetParamIntValue: function(mark: FPDF_PAGEOBJECTMARK; key: FPDF_BYTESTRING; out_value: PInteger): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Experimental API. +// Get the value of a number property in a content mark by key as float. +// FPDFPageObjMark_GetParamValueType() should have returned FPDF_OBJECT_NUMBER +// for this property. +// +// mark - handle to a content mark. +// key - string key of the property. +// out_value - pointer to variable that will receive the value. Not filled if +// false is returned. +// +// Returns TRUE if the key maps to a number value, FALSE otherwise. +var + FPDFPageObjMark_GetParamFloatValue: function(mark: FPDF_PAGEOBJECTMARK; key: FPDF_BYTESTRING; + out_value: PSingle): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // Experimental API. // Get the value of a string property in a content mark by key. // // mark - handle to a content mark. // key - string key of the property. // buffer - buffer for holding the returned value in UTF-16LE. This is -// only modified if |buflen| is longer than the length of the -// value. +// only modified if |buflen| is large enough to store the value. // Optional, pass null to just retrieve the size of the buffer // needed. -// buflen - length of the buffer. +// buflen - length of the buffer in bytes. // out_buflen - pointer to variable that will receive the minimum buffer size -// to contain the value. Not filled if FALSE is returned. +// in bytes to contain the name. This is a required parameter. +// Not filled if FALSE is returned. // // Returns TRUE if the key maps to a string/blob value, FALSE otherwise. var - FPDFPageObjMark_GetParamStringValue: function(mark: FPDF_PAGEOBJECTMARK; key: FPDF_BYTESTRING; buffer: Pointer; - buflen: LongWord; out_buflen: PLongWord): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + FPDFPageObjMark_GetParamStringValue: function(mark: FPDF_PAGEOBJECTMARK; key: FPDF_BYTESTRING; buffer: PFPDF_WCHAR; + buflen: LongWord; var out_buflen: LongWord): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; // Experimental API. // Get the value of a blob property in a content mark by key. @@ -1637,17 +2055,18 @@ FPDF_IMAGEOBJ_METADATA = record // mark - handle to a content mark. // key - string key of the property. // buffer - buffer for holding the returned value. This is only modified -// if |buflen| is at least as long as the length of the value. +// if |buflen| is large enough to store the value. // Optional, pass null to just retrieve the size of the buffer // needed. -// buflen - length of the buffer. +// buflen - length of the buffer in bytes. // out_buflen - pointer to variable that will receive the minimum buffer size -// to contain the value. Not filled if FALSE is returned. +// in bytes to contain the name. This is a required parameter. +// Not filled if FALSE is returned. // // Returns TRUE if the key maps to a string/blob value, FALSE otherwise. var - FPDFPageObjMark_GetParamBlobValue: function(mark: FPDF_PAGEOBJECTMARK; key: FPDF_BYTESTRING; buffer: Pointer; - buflen: LongWord; out_buflen: PLongWord): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + FPDFPageObjMark_GetParamBlobValue: function(mark: FPDF_PAGEOBJECTMARK; key: FPDF_BYTESTRING; buffer: PByte; + buflen: LongWord; var out_buflen: LongWord): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; // Experimental API. // Set the value of an int property in a content mark by key. If a parameter @@ -1665,6 +2084,22 @@ FPDF_IMAGEOBJ_METADATA = record FPDFPageObjMark_SetIntParam: function(document: FPDF_DOCUMENT; page_object: FPDF_PAGEOBJECT; mark: FPDF_PAGEOBJECTMARK; key: FPDF_BYTESTRING; value: Integer): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Experimental API. +// Set the value of a float property in a content mark by key. If a parameter +// with key |key| exists, its value is set to |value|. Otherwise, it is added as +// a new parameter. +// +// document - handle to the document. +// page_object - handle to the page object with the mark. +// mark - handle to a content mark. +// key - string key of the property. +// value - float value to set. +// +// Returns TRUE if the operation succeeded, FALSE otherwise. +var + FPDFPageObjMark_SetFloatParam: function(document: FPDF_DOCUMENT; page_object: FPDF_PAGEOBJECT; + mark: FPDF_PAGEOBJECTMARK; key: FPDF_BYTESTRING; value: Single): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // Experimental API. // Set the value of a string property in a content mark by key. If a parameter // with key |key| exists, its value is set to |value|. Otherwise, it is added as @@ -1696,7 +2131,7 @@ FPDF_IMAGEOBJ_METADATA = record // Returns TRUE if the operation succeeded, FALSE otherwise. var FPDFPageObjMark_SetBlobParam: function(document: FPDF_DOCUMENT; page_object: FPDF_PAGEOBJECT; - mark: FPDF_PAGEOBJECTMARK; key: FPDF_BYTESTRING; value: Pointer; value_len: LongWord): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + mark: FPDF_PAGEOBJECTMARK; key: FPDF_BYTESTRING; value: PByte; value_len: LongWord): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; // Experimental API. // Removes a property from a content mark by key. @@ -1748,26 +2183,7 @@ FPDF_IMAGEOBJ_METADATA = record FPDFImageObj_LoadJpegFileInline: function(pages: PFPDF_PAGE; count: Integer; image_object: FPDF_PAGEOBJECT; file_access: PFPDF_FILEACCESS): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -// Experimental API. -// Get the transform matrix of an image object. -// -// image_object - handle to an image object. -// a - matrix value. -// b - matrix value. -// c - matrix value. -// d - matrix value. -// e - matrix value. -// f - matrix value. -// -// The matrix is composed as: -// |a c e| -// |b d f| -// and used to scale, rotate, shear and translate the image. -// -// Returns TRUE on success. -var - FPDFImageObj_GetMatrix: function(image_object: FPDF_PAGEOBJECT; var a, b, c, d, e, f: Double): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; - +// TODO(thestig): Start deprecating this once FPDFPageObj_SetMatrix() is stable. // Set the transform matrix of |image_object|. // // image_object - handle to an image object. @@ -1799,9 +2215,11 @@ FPDF_IMAGEOBJ_METADATA = record FPDFImageObj_SetBitmap: function(pages: PFPDF_PAGE; nCount: Integer; image_object: FPDF_PAGEOBJECT; bitmap: FPDF_BITMAP): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -// Get a bitmap rasterisation of |image_object|. The returned bitmap will be -// owned by the caller, and FPDFBitmap_Destroy() must be called on the returned -// bitmap when it is no longer needed. +// Get a bitmap rasterization of |image_object|. FPDFImageObj_GetBitmap() only +// operates on |image_object| and does not take the associated image mask into +// account. It also ignores the matrix for |image_object|. +// The returned bitmap will be owned by the caller, and FPDFBitmap_Destroy() +// must be called on the returned bitmap when it is no longer needed. // // image_object - handle to an image object. // @@ -1809,6 +2227,23 @@ FPDF_IMAGEOBJ_METADATA = record var FPDFImageObj_GetBitmap: function(image_object: FPDF_PAGEOBJECT): FPDF_BITMAP; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Experimental API. +// Get a bitmap rasterization of |image_object| that takes the image mask and +// image matrix into account. To render correctly, the caller must provide the +// |document| associated with |image_object|. If there is a |page| associated +// with |image_object|, the caller should provide that as well. +// The returned bitmap will be owned by the caller, and FPDFBitmap_Destroy() +// must be called on the returned bitmap when it is no longer needed. +// +// document - handle to a document associated with |image_object|. +// page - handle to an optional page associated with |image_object|. +// image_object - handle to an image object. +// +// Returns the bitmap or NULL on failure. +var + FPDFImageObj_GetRenderedBitmap: function(document: FPDF_DOCUMENT; page: FPDF_PAGE; + image_object: FPDF_PAGEOBJECT): FPDF_BITMAP; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // Get the decoded image data of |image_object|. The decoded data is the // uncompressed image data, i.e. the raw image data after having all filters // applied. |buffer| is only modified if |buflen| is longer than the length of @@ -1874,6 +2309,39 @@ FPDF_IMAGEOBJ_METADATA = record FPDFImageObj_GetImageMetadata: function(image_object: FPDF_PAGEOBJECT; page: FPDF_PAGE; metadata: PFPDF_IMAGEOBJ_METADATA): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Experimental API. +// Get the image size in pixels. Faster method to get only image size. +// +// image_object - handle to an image object. +// width - receives the image width in pixels; must not be NULL. +// height - receives the image height in pixels; must not be NULL. +// +// Returns true if successful. +var + FPDFImageObj_GetImagePixelSize: function(image_object: FPDF_PAGEOBJECT; var width, height: UInt32): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Get ICC profile decoded data of |image_object|. If the |image_object| is not +// an image object or if it does not have an image, then the return value will +// be false. It also returns false if the |image_object| has no ICC profile. +// |buffer| is only modified if ICC profile exists and |buflen| is longer than +// the length of the ICC profile decoded data. +// +// image_object - handle to an image object; must not be NULL. +// page - handle to the page containing |image_object|; must not be +// NULL. Required for retrieving the image's colorspace. +// buffer - Buffer to receive ICC profile data; may be NULL if querying +// required size via |out_buflen|. +// buflen - Length of the buffer in bytes. Ignored if |buffer| is NULL. +// out_buflen - Pointer to receive the ICC profile data size in bytes; must +// not be NULL. Will be set if this API returns true. +// +// Returns true if |out_buflen| is not null and an ICC profile exists for the +// given |image_object|. +var + FPDFImageObj_GetIccProfileDataDecoded: function(image_object: FPDF_PAGEOBJECT; page: FPDF_PAGE; buffer: PByte; + buflen: SIZE_T; var out_buflen: SIZE_T): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // Create a new path object at an initial position. // // x - initial horizontal position. @@ -1902,10 +2370,28 @@ FPDF_IMAGEOBJ_METADATA = record // right - pointer where the right coordinate will be stored // top - pointer where the top coordinate will be stored // -// Returns TRUE on success. +// On success, returns TRUE and fills in the 4 coordinates. var FPDFPageObj_GetBounds: function(page_object: FPDF_PAGEOBJECT; var left, bottom, right, top: Single): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Experimental API. +// Get the quad points that bounds |page_object|. +// +// page_object - handle to a page object. +// quad_points - pointer where the quadrilateral points will be stored. +// +// On success, returns TRUE and fills in |quad_points|. +// +// Similar to FPDFPageObj_GetBounds(), this returns the bounds of a page +// object. When the object is rotated by a non-multiple of 90 degrees, this API +// returns a tighter bound that cannot be represented with just the 4 sides of +// a rectangle. +// +// Currently only works the following |page_object| types: FPDF_PAGEOBJ_TEXT and +// FPDF_PAGEOBJ_IMAGE. +var + FPDFPageObj_GetRotatedBounds: function(page_object: FPDF_PAGEOBJECT; quad_points: PFS_QUADPOINTSF): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // Set the blend mode of |page_object|. // // page_object - handle to a page object. @@ -1950,7 +2436,6 @@ FPDF_IMAGEOBJ_METADATA = record var FPDFPageObj_SetStrokeWidth: function(page_object: FPDF_PAGEOBJECT; width: Single): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -// Experimental API. // Get the stroke width of a page object. // // path - the handle to the page object. @@ -2024,6 +2509,58 @@ FPDF_IMAGEOBJ_METADATA = record var FPDFPageObj_GetFillColor: function(page_object: FPDF_PAGEOBJECT; var R, G, B, A: Cardinal): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Get the line dash |phase| of |page_object|. +// +// page_object - handle to a page object. +// phase - pointer where the dashing phase will be stored. +// +// Returns TRUE on success. +var + FPDFPageObj_GetDashPhase: function(page_object: FPDF_PAGEOBJECT; var phase: Single): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Set the line dash phase of |page_object|. +// +// page_object - handle to a page object. +// phase - line dash phase. +// +// Returns TRUE on success. +var + FPDFPageObj_SetDashPhase: function(page_object: FPDF_PAGEOBJECT; phase: Single): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Get the line dash array of |page_object|. +// +// page_object - handle to a page object. +// +// Returns the line dash array size or -1 on failure. +var + FPDFPageObj_GetDashCount: function(page_object: FPDF_PAGEOBJECT): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Get the line dash array of |page_object|. +// +// page_object - handle to a page object. +// dash_array - pointer where the dashing array will be stored. +// dash_count - number of elements in |dash_array|. +// +// Returns TRUE on success. +var + FPDFPageObj_GetDashArray: function(page_object: FPDF_PAGEOBJECT; dash_array: PSingle; dash_count: SIZE_T): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Set the line dash array of |page_object|. +// +// page_object - handle to a page object. +// dash_array - the dash array. +// dash_count - number of elements in |dash_array|. +// phase - the line dash phase. +// +// Returns TRUE on success. +var + FPDFPageObj_SetDashArray: function(page_object: FPDF_PAGEOBJECT; const dash_array: PSingle; dash_count: SIZE_T; + phase: Single): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // Experimental API. // Get number of segments inside |path|. // @@ -2036,7 +2573,6 @@ FPDF_IMAGEOBJ_METADATA = record var FPDFPath_CountSegments: function(path: FPDF_PAGEOBJECT): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -// Experimental API. // Get segment in |path| at |index|. // // path - handle to a path. @@ -2046,7 +2582,6 @@ FPDF_IMAGEOBJ_METADATA = record var FPDFPath_GetPathSegment: function(path: FPDF_PAGEOBJECT; index: Integer): FPDF_PATHSEGMENT; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -// Experimental API. // Get coordinates of |segment|. // // segment - handle to a segment. @@ -2057,7 +2592,6 @@ FPDF_IMAGEOBJ_METADATA = record var FPDFPathSegment_GetPoint: function(segment: FPDF_PATHSEGMENT; var x, y: Single): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -// Experimental API. // Get type of |segment|. // // segment - handle to a segment. @@ -2067,7 +2601,6 @@ FPDF_IMAGEOBJ_METADATA = record var FPDFPathSegment_GetType: function(segment: FPDF_PATHSEGMENT): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -// Experimental API. // Gets if the |segment| closes the current subpath of a given path. // // segment - handle to a segment. @@ -2136,7 +2669,6 @@ FPDF_IMAGEOBJ_METADATA = record var FPDFPath_SetDrawMode: function(path: FPDF_PAGEOBJECT; fillmode: Integer; stoke: FPDF_BOOL): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -// Experimental API. // Get the drawing mode of a path. // // path - the handle to the path object. @@ -2147,68 +2679,70 @@ FPDF_IMAGEOBJ_METADATA = record var FPDFPath_GetDrawMode: function(path: FPDF_PAGEOBJECT; var fillmode: Integer; var stoke: FPDF_BOOL): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -// Experimental API. -// Get the transform matrix of a path. -// -// path - handle to a path. -// matrix - pointer to struct to receive the matrix value. +// Create a new text object using one of the standard PDF fonts. // -// The matrix is composed as: -// |a c e| -// |b d f| -// and used to scale, rotate, shear and translate the path. +// document - handle to the document. +// font - string containing the font name, without spaces. +// font_size - the font size for the new text object. // -// Returns TRUE on success. +// Returns a handle to a new text object, or NULL on failure var - FPDFPath_GetMatrix: function(path: FPDF_PAGEOBJECT; matrix: PFS_MATRIX): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + FPDFPageObj_NewTextObj: function(document: FPDF_DOCUMENT; font: FPDF_BYTESTRING; font_size: Single): FPDF_PAGEOBJECT; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -// Experimental API. -// Set the transform matrix of a path. -// -// path - handle to a path. -// matrix - pointer to struct with the matrix value. +// Set the text for a text object. If it had text, it will be replaced. // -// The matrix is composed as: -// |a c e| -// |b d f| -// and can be used to scale, rotate, shear and translate the path. +// text_object - handle to the text object. +// text - the UTF-16LE encoded string containing the text to be added. // -// Returns TRUE on success. +// Returns TRUE on success. Fails if |text_object| is null or if |text| is +// empty. var - FPDFPath_SetMatrix: function(path: FPDF_PAGEOBJECT; const matrix: PFS_MATRIX): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + FPDFText_SetText: function(text_object: FPDF_PAGEOBJECT; text: FPDF_WIDESTRING): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; - // Create a new text object using one of the standard PDF fonts. +// Experimental API. +// Set the text using charcodes for a text object. If it had text, it will be +// replaced. // -// document - handle to the document. -// font - string containing the font name, without spaces. -// font_size - the font size for the new text object. +// text_object - handle to the text object. +// charcodes - pointer to an array of charcodes to be added. +// count - number of elements in |charcodes|. // -// Returns a handle to a new text object, or NULL on failure +// Returns TRUE on success. Fails if |text_object| or |charcodes| is null, or +// |count| is 0. var - FPDFPageObj_NewTextObj: function(document: FPDF_DOCUMENT; font: FPDF_BYTESTRING; font_size: Single): FPDF_PAGEOBJECT; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + FPDFText_SetCharcodes: function(text_object: FPDF_PAGEOBJECT; const charcodes: PUINT; count: SIZE_T): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -// Set the text for a textobject. If it had text, it will be replaced. +// Experimental API. +// Set the character positions for a text object. // // text_object - handle to the text object. -// text - the UTF-16LE encoded string containing the text to be added. +// positions - pointer to an array of character positions to be set. +// count - number of elements in |positions|. // -// Returns TRUE on success +// The |positions| array specifies the position in points for each character +// except the first one. The first character has an implied position value of 0. +// All positions are relative to the origin of the text object. The direction is +// either horizontal or vertical, depending on the direction of text in +// |text_object|. +// +// For a text object with N characters, |count| must be N - 1. Therefore this +// API fails when N <= 1. +// +// Returns TRUE on success. var - FPDFText_SetText: function(text_object: FPDF_PAGEOBJECT; text: FPDF_WIDESTRING): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + FPDFText_SetPositions: function(text_object: FPDF_PAGEOBJECT; const positions: PSingle; count: SIZE_T): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; // Returns a font object loaded from a stream of data. The font is loaded -// into the document. +// into the document. Various font data structures, such as the ToUnicode data, +// are auto-generated based on the inputs. // -// document - handle to the document. -// data - the stream of data, which will be copied by the font object. -// size - size of the stream, in bytes. -// font_type - FPDF_FONT_TYPE1 or FPDF_FONT_TRUETYPE depending on the font -// type. -// cid - a boolean specifying if the font is a CID font or not. -// -// The loaded font can be closed using FPDFFont_Close. +// document - handle to the document. +// data - the stream of font data, which will be copied by the font object. +// size - the size of the font data, in bytes. +// font_type - FPDF_FONT_TYPE1 or FPDF_FONT_TRUETYPE depending on the font type. +// cid - a boolean specifying if the font is a CID font or not. // -// Returns NULL on failure +// The loaded font can be closed using FPDFFont_Close(). var FPDFText_LoadFont: function(document: FPDF_DOCUMENT; data: PByte; size: DWORD; font_type: Integer; cid: FPDF_BOOL): FPDF_FONT; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; @@ -2221,36 +2755,42 @@ FPDF_IMAGEOBJ_METADATA = record // document - handle to the document. // font - string containing the font name, without spaces. // -// The loaded font can be closed using FPDFFont_Close. +// The loaded font can be closed using FPDFFont_Close(). // // Returns NULL on failure. var FPDFText_LoadStandardFont: function(document: FPDF_DOCUMENT; font: FPDF_BYTESTRING): FPDF_FONT; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; // Experimental API. -// Get the transform matrix of a text object. +// Returns a font object loaded from a stream of data for a type 2 CID font. The +// font is loaded into the document. Unlike FPDFText_LoadFont(), the ToUnicode +// data and the CIDToGIDMap data are caller provided, instead of auto-generated. // -// text - handle to a text. -// matrix - pointer to struct with the matrix value. +// document - handle to the document. +// font_data - the stream of font data, which will be copied by +// the font object. +// font_data_size - the size of the font data, in bytes. +// to_unicode_cmap - the ToUnicode data. +// cid_to_gid_map_data - the stream of CIDToGIDMap data. +// cid_to_gid_map_data_size - the size of the CIDToGIDMap data, in bytes. // -// The matrix is composed as: -// |a c e| -// |b d f| -// and used to scale, rotate, shear and translate the text. +// The loaded font can be closed using FPDFFont_Close(). // -// Returns TRUE on success. +// Returns NULL on failure. var - FPDFTextObj_GetMatrix: function(text: FPDF_PAGEOBJECT; matrix: PFS_MATRIX): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + FPDFText_LoadCidType2Font: function(document: FPDF_DOCUMENT; font_data: PByte; font_data_size: DWORD; + to_unicode_cmap: FPDF_BYTESTRING; cid_to_gid_map_data: PByte; cid_to_gid_map_data_size: DWORD): FPDF_FONT; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -// Experimental API. // Get the font size of a text object. // // text - handle to a text. // -// Returns the font size of the text object, measured in points (about 1/72 -// inch) on success; 0 on failure. +// size - pointer to the font size of the text object, measured in points +// (about 1/72 inch) +// +// Returns TRUE on success. var - FPDFTextObj_GetFontSize: function(text: FPDF_PAGEOBJECT): Single; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + FPDFTextObj_GetFontSize: function(text: FPDF_PAGEOBJECT; var size: Single): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; // Close a loaded PDF font. // @@ -2268,7 +2808,6 @@ FPDF_IMAGEOBJ_METADATA = record var FPDFPageObj_CreateTextObj: function(document: FPDF_DOCUMENT; font: FPDF_FONT; font_size: Single): FPDF_PAGEOBJECT; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -// Experimental API. // Get the text rendering mode of a text object. // // text - the handle to the text object. @@ -2289,41 +2828,219 @@ FPDF_IMAGEOBJ_METADATA = record var FPDFTextObj_SetTextRenderMode: function(text: FPDF_PAGEOBJECT; render_mode: FPDF_TEXT_RENDERMODE): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -// Experimental API. -// Get the font name of a text object. +// Get the text of a text object. // -// text - the handle to the text object. -// buffer - the address of a buffer that receives the font name. +// text_object - the handle to the text object. +// text_page - the handle to the text page. +// buffer - the address of a buffer that receives the text. // length - the size, in bytes, of |buffer|. // -// Returns the number of bytes in the font name (including the trailing NUL +// Returns the number of bytes in the text (including the trailing NUL // character) on success, 0 on error. // +// Regardless of the platform, the |buffer| is always in UTF-16LE encoding. +// If |length| is less than the returned length, or |buffer| is NULL, |buffer| +// will not be modified. +var + FPDFTextObj_GetText: function(text_object: FPDF_PAGEOBJECT; text_page: FPDF_TEXTPAGE; buffer: PFPDF_WCHAR; + length: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Get a bitmap rasterization of |text_object|. To render correctly, the caller +// must provide the |document| associated with |text_object|. If there is a +// |page| associated with |text_object|, the caller should provide that as well. +// The returned bitmap will be owned by the caller, and FPDFBitmap_Destroy() +// must be called on the returned bitmap when it is no longer needed. +// +// document - handle to a document associated with |text_object|. +// page - handle to an optional page associated with |text_object|. +// text_object - handle to a text object. +// scale - the scaling factor, which must be greater than 0. +// +// Returns the bitmap or NULL on failure. +var + FPDFTextObj_GetRenderedBitmap: function(document: FPDF_DOCUMENT; page: FPDF_PAGE; text_object: FPDF_PAGEOBJECT; + scale: Single): FPDF_BITMAP; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Get the font of a text object. +// +// text - the handle to the text object. +// +// Returns a handle to the font object held by |text| which retains ownership. +var + FPDFTextObj_GetFont: function(text: FPDF_PAGEOBJECT): FPDF_FONT; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Get the base name of a font. +// +// font - the handle to the font object. +// buffer - the address of a buffer that receives the base font name. +// length - the size, in bytes, of |buffer|. +// +// Returns the number of bytes in the base name (including the trailing NUL +// character) on success, 0 on error. The base name is typically the font's +// PostScript name. See descriptions of "BaseFont" in ISO 32000-1:2008 spec. +// // Regardless of the platform, the |buffer| is always in UTF-8 encoding. // If |length| is less than the returned length, or |buffer| is NULL, |buffer| // will not be modified. var - FPDFTextObj_GetFontName: function(text: FPDF_PAGEOBJECT; buffer: Pointer; length: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + FPDFFont_GetBaseFontName: function(font: FPDF_FONT; buffer: PAnsiChar; length: SIZE_T): SIZE_T; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; // Experimental API. -// Get the text of a text object. +// Get the family name of a font. // -// text_object - the handle to the text object. -// text_page - the handle to the text page. -// buffer - the address of a buffer that receives the text. -// length - the size, in bytes, of |buffer|. +// font - the handle to the font object. +// buffer - the address of a buffer that receives the font name. +// length - the size, in bytes, of |buffer|. // -// Returns the number of bytes in the text (including the trailing NUL +// Returns the number of bytes in the family name (including the trailing NUL // character) on success, 0 on error. // -// Regardless of the platform, the |buffer| is always in UTF-16LE encoding. +// Regardless of the platform, the |buffer| is always in UTF-8 encoding. // If |length| is less than the returned length, or |buffer| is NULL, |buffer| // will not be modified. var - FPDFTextObj_GetText: function(text_object: FPDF_PAGEOBJECT; text_page: FPDF_TEXTPAGE; buffer: Pointer; - length: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + FPDFFont_GetFamilyName: function(font: FPDF_FONT; buffer: PAnsiChar; length: SIZE_T): SIZE_T; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Get the decoded data from the |font| object. +// +// font - The handle to the font object. (Required) +// buffer - The address of a buffer that receives the font data. +// buflen - Length of the buffer. +// out_buflen - Pointer to variable that will receive the minimum buffer size +// to contain the font data. Not filled if the return value is +// FALSE. (Required) +// +// Returns TRUE on success. In which case, |out_buflen| will be filled, and +// |buffer| will be filled if it is large enough. Returns FALSE if any of the +// required parameters are null. +// +// The decoded data is the uncompressed font data. i.e. the raw font data after +// having all stream filters applied, when the data is embedded. +// +// If the font is not embedded, then this API will instead return the data for +// the substitution font it is using. +var + FPDFFont_GetFontData: function(font: FPDF_FONT; buffer: PByte; buflen: SIZE_T; var out_buflen: SIZE_T): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Get whether |font| is embedded or not. +// +// font - the handle to the font object. +// +// Returns 1 if the font is embedded, 0 if it not, and -1 on failure. +var + FPDFFont_GetIsEmbedded: function(font: FPDF_FONT): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Get the descriptor flags of a font. +// +// font - the handle to the font object. +// +// Returns the bit flags specifying various characteristics of the font as +// defined in ISO 32000-1:2008, table 123, -1 on failure. +var + FPDFFont_GetFlags: function(font: FPDF_FONT): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; // Experimental API. +// Get the font weight of a font. +// +// font - the handle to the font object. +// +// Returns the font weight, -1 on failure. +// Typical values are 400 (normal) and 700 (bold). +var + FPDFFont_GetWeight: function(font: FPDF_FONT): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Get the italic angle of a font. +// +// font - the handle to the font object. +// angle - pointer where the italic angle will be stored +// +// The italic angle of a |font| is defined as degrees counterclockwise +// from vertical. For a font that slopes to the right, this will be negative. +// +// Returns TRUE on success; |angle| unmodified on failure. +var + FPDFFont_GetItalicAngle: function(font: FPDF_FONT; var angle: Integer): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Get ascent distance of a font. +// +// font - the handle to the font object. +// font_size - the size of the |font|. +// ascent - pointer where the font ascent will be stored +// +// Ascent is the maximum distance in points above the baseline reached by the +// glyphs of the |font|. One point is 1/72 inch (around 0.3528 mm). +// +// Returns TRUE on success; |ascent| unmodified on failure. +var + FPDFFont_GetAscent: function(font: FPDF_FONT; font_size: Single; var ascent: Single): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Get descent distance of a font. +// +// font - the handle to the font object. +// font_size - the size of the |font|. +// descent - pointer where the font descent will be stored +// +// Descent is the maximum distance in points below the baseline reached by the +// glyphs of the |font|. One point is 1/72 inch (around 0.3528 mm). +// +// Returns TRUE on success; |descent| unmodified on failure. +var + FPDFFont_GetDescent: function(font: FPDF_FONT; font_size: Single; var descent: Single): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Get the width of a glyph in a font. +// +// font - the handle to the font object. +// glyph - the glyph. +// font_size - the size of the font. +// width - pointer where the glyph width will be stored +// +// Glyph width is the distance from the end of the prior glyph to the next +// glyph. This will be the vertical distance for vertical writing. +// +// Returns TRUE on success; |width| unmodified on failure. +var + FPDFFont_GetGlyphWidth: function(font: FPDF_FONT; glyph: UINT; font_size: Single; var width: Single): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Get the glyphpath describing how to draw a font glyph. +// +// font - the handle to the font object. +// glyph - the glyph being drawn. +// font_size - the size of the font. +// +// Returns the handle to the segment, or NULL on faiure. +var + FPDFFont_GetGlyphPath: function(font: FPDF_FONT; glyph: UINT; font_size: Single): FPDF_GLYPHPATH; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Get number of segments inside glyphpath. +// +// glyphpath - handle to a glyph path. +// +// Returns the number of objects in |glyphpath| or -1 on failure. +var + FPDFGlyphPath_CountGlyphSegments: function(glyphpath: FPDF_GLYPHPATH): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Get segment in glyphpath at index. +// +// glyphpath - handle to a glyph path. +// index - the index of a segment. +// +// Returns the handle to the segment, or NULL on faiure. +var + FPDFGlyphPath_GetGlyphPathSegment: function(glyphpath: FPDF_GLYPHPATH; index: Integer): FPDF_PATHSEGMENT; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // Get number of page objects inside |form_object|. // // form_object - handle to a form object. @@ -2332,7 +3049,6 @@ FPDF_IMAGEOBJ_METADATA = record var FPDFFormObj_CountObjects: function(form_object: FPDF_PAGEOBJECT): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -// Experimental API. // Get page object in |form_object| at |index|. // // form_object - handle to a form object. @@ -2343,32 +3059,50 @@ FPDF_IMAGEOBJ_METADATA = record FPDFFormObj_GetObject: function(form_object: FPDF_PAGEOBJECT; index: LongWord): FPDF_PAGEOBJECT; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; // Experimental API. -// Get the transform matrix of a form object. // -// form_object - handle to a form. -// matrix - pointer to struct to receive the matrix value. +// Remove |page_object| from |form_object|. // -// The matrix is composed as: -// |a c e| -// |b d f| -// and used to scale, rotate, shear and translate the form object. +// form_object - handle to a form object. +// page_object - handle to a page object to be removed from the form. // // Returns TRUE on success. +// +// Ownership of the removed |page_object| is transferred to the caller. +// Call FPDFPageObj_Destroy() on the removed page_object to free it. var - FPDFFormObj_GetMatrix: function(form_object: FPDF_PAGEOBJECT; matrix: PFS_MATRIX): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; - + FPDFFormObj_RemoveObject: function(form_object: FPDF_PAGEOBJECT; page_object: FPDF_PAGEOBJECT): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; // *** _FPDF_PPO_H_ *** +// Experimental API. +// Import pages to a FPDF_DOCUMENT. +// +// dest_doc - The destination document for the pages. +// src_doc - The document to be imported. +// page_indices - An array of page indices to be imported. The first page is +// zero. If |page_indices| is NULL, all pages from |src_doc| +// are imported. +// length - The length of the |page_indices| array. +// index - The page index at which to insert the first imported page +// into |dest_doc|. The first page is zero. +// +// Returns TRUE on success. Returns FALSE if any pages in |page_indices| is +// invalid. +var + FPDF_ImportPagesByIndex: function(dest_doc, src_doc: FPDF_DOCUMENT; page_indices: PInteger; + length: LongWord; index: Integer): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // Import pages to a FPDF_DOCUMENT. // // dest_doc - The destination document for the pages. // src_doc - The document to be imported. -// pagerange - A page range string, Such as "1,3,5-7". If |pagerange| is NULL, -// all pages from |src_doc| are imported. -// index - The page index to insert at. +// pagerange - A page range string, Such as "1,3,5-7". The first page is one. +// If |pagerange| is NULL, all pages from |src_doc| are imported. +// index - The page index at which to insert the first imported page into +// |dest_doc|. The first page is zero. // -// Returns TRUE on success. +// Returns TRUE on success. Returns FALSE if any pages in |pagerange| is +// invalid or if |pagerange| cannot be read. var FPDF_ImportPages: function(dest_doc, src_doc: FPDF_DOCUMENT; pagerange: FPDF_BYTESTRING; index: Integer): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; @@ -2393,10 +3127,34 @@ FPDF_IMAGEOBJ_METADATA = record FPDF_ImportNPagesToOne: function(src_doc: FPDF_DOCUMENT; output_width, output_height: Single; num_pages_on_x_axis, num_pages_on_y_axis: SIZE_T): FPDF_DOCUMENT; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -// Copy the viewer preferences from |src_doc| into |dest_doc|. +// Experimental API. +// Create a template to generate form xobjects from |src_doc|'s page at +// |src_page_index|, for use in |dest_doc|. // -// dest_doc - Document to write the viewer preferences into. -// src_doc - Document to read the viewer preferences from. +// Returns a handle on success, or NULL on failure. Caller owns the newly +// created object. The returned handle's lifetime is tied to |dest_doc| and not +// |src_doc|. It must be closed before |dest_doc|. +var + FPDF_NewXObjectFromPage: function(dest_doc, src_doc: FPDF_DOCUMENT; src_page_index: Integer): FPDF_XOBJECT; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Close an FPDF_XOBJECT handle created by FPDF_NewXObjectFromPage(). +// FPDF_PAGEOBJECTs created from the FPDF_XOBJECT handle are not affected. +var + FPDF_CloseXObject: procedure(xobject: FPDF_XOBJECT); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Create a new form object from an FPDF_XOBJECT object. +// +// Returns a new form object on success, or NULL on failure. Caller owns the +// newly created object. +var + FPDF_NewFormObjectFromXObject: function(xobject: FPDF_XOBJECT): FPDF_PAGEOBJECT; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Copy the viewer preferences from |src_doc| into |dest_doc|. +// +// dest_doc - Document to write the viewer preferences into. +// src_doc - Document to read the viewer preferences from. // // Returns TRUE on success. var @@ -2424,50 +3182,59 @@ FPDF_FILEWRITE = record // Comments: // Called by function FPDF_SaveDocument // Parameters: - // pThis - Pointer to the structure itself - // pData - Pointer to a buffer to output + // self - Pointer to the structure itself + // data - Pointer to a buffer to output // size - The size of the buffer. // Return value: // Should be non-zero if successful, zero for error. // - WriteBlock: function(pThis: PFPDF_FILEWRITE; pData: Pointer; size: LongWord): Integer; cdecl; + WriteBlock: function(self: PFPDF_FILEWRITE; data: Pointer; size: LongWord): Integer; cdecl; end; PFPdfFileWrite = ^TFPdfFileWrite; TFPdfFileWrite = FPDF_FILEWRITE; const - // Flags for FPDF_SaveAsCopy() - FPDF_INCREMENTAL = 1; - FPDF_NO_INCREMENTAL = 2; - FPDF_REMOVE_SECURITY = 3; + // Flags for FPDF_SaveAsCopy(). + // FPDF_INCREMENTAL and FPDF_NO_INCREMENTAL cannot be used together. + FPDF_INCREMENTAL = 1 shl 0; + FPDF_NO_INCREMENTAL = 1 shl 1; + // Deprecated. Use FPDF_REMOVE_SECURITY instead. + // TODO(crbug.com/42270430): Remove FPDF_REMOVE_SECURITY_DEPRECATED. + FPDF_REMOVE_SECURITY_DEPRECATED = 3; + FPDF_REMOVE_SECURITY = 1 shl 2; + // Experimental. Subsets any embedded font files for new text objects added to + // the document. + FPDF_SUBSET_NEW_FONTS = 1 shl 3; // Function: FPDF_SaveAsCopy // Saves the copy of specified document in custom way. // Parameters: // document - Handle to document, as returned by // FPDF_LoadDocument() or FPDF_CreateNewDocument(). -// pFileWrite - A pointer to a custom file write structure. -// flags - The creating flags. +// file_write - A pointer to a custom file write structure. +// flags - Flags above that affect how the PDF gets saved. +// Pass in 0 when there are no flags. // Return value: // TRUE for succeed, FALSE for failed. // var - FPDF_SaveAsCopy: function(document: FPDF_DOCUMENT; pFileWrite: PFPDF_FILEWRITE; flags: FPDF_DWORD): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + FPDF_SaveAsCopy: function(document: FPDF_DOCUMENT; file_write: PFPDF_FILEWRITE; flags: FPDF_DWORD): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; // Function: FPDF_SaveWithVersion // Same as FPDF_SaveAsCopy(), except the file version of the // saved document can be specified by the caller. // Parameters: // document - Handle to document. -// pFileWrite - A pointer to a custom file write structure. +// file_write - A pointer to a custom file write structure. // flags - The creating flags. -// fileVersion - The PDF file version. File version: 14 for 1.4, 15 for 1.5, ... +// file_version - The PDF file version. File version: 14 for 1.4, +// 15 for 1.5, ... // Return value: // TRUE if succeed, FALSE if failed. // var - FPDF_SaveWithVersion: function(document: FPDF_DOCUMENT; pFileWrite: PFPDF_FILEWRITE; - flags: FPDF_DWORD; fileVersion: Integer): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + FPDF_SaveWithVersion: function(document: FPDF_DOCUMENT; file_write: PFPDF_FILEWRITE; + flags: FPDF_DWORD; file_version: Integer): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; // *** _FPDF_FLATTEN_H_ *** @@ -2477,6 +3244,9 @@ FPDF_FILEWRITE = record FLATTEN_SUCCESS = 1; // Flatten operation succeed. FLATTEN_NOTINGTODO = 2; // Nothing to be flattened. + FLAT_NORMALDISPLAY = 0; // Flatten for normal display. + FLAT_PRINT = 1; // Flatten for print. + // Flatten annotations and form fields into the page contents. // // page - handle to the page. @@ -2545,6 +3315,66 @@ FPDF_FILEWRITE = record var FPDFText_GetUnicode: function(text_page: FPDF_TEXTPAGE; index: Integer): WideChar; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Experimental API. +// Function: FPDFText_GetTextObject +// Get the FPDF_PAGEOBJECT associated with a given character. +// Parameters: +// text_page - Handle to a text page information structure. +// Returned by FPDFText_LoadPage function. +// index - Zero-based index of the character. +// Return value: +// The associated text object for the character at |index|, or NULL on +// error. The returned text object, if non-null, is of type +// |FPDF_PAGEOBJ_TEXT|. The caller does not own the returned object. +// +var + FPDFText_GetTextObject: function(text_page: FPDF_TEXTPAGE; index: Integer): FPDF_PAGEOBJECT; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Function: FPDFText_IsGenerated +// Get if a character in a page is generated by PDFium. +// Parameters: +// text_page - Handle to a text page information structure. +// Returned by FPDFText_LoadPage function. +// index - Zero-based index of the character. +// Return value: +// 1 if the character is generated by PDFium. +// 0 if the character is not generated by PDFium. +// -1 if there was an error. +// +var + FPDFText_IsGenerated: function(text_page: FPDF_TEXTPAGE; index: Integer): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Function: FPDFText_IsHyphen +// Get if a character in a page is a hyphen. +// Parameters: +// text_page - Handle to a text page information structure. +// Returned by FPDFText_LoadPage function. +// index - Zero-based index of the character. +// Return value: +// 1 if the character is a hyphen. +// 0 if the character is not a hyphen. +// -1 if there was an error. +// +var + FPDFText_IsHyphen: function(text_page: FPDF_TEXTPAGE; index: Integer): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Function: FPDFText_HasUnicodeMapError +// Get if a character in a page has an invalid unicode mapping. +// Parameters: +// text_page - Handle to a text page information structure. +// Returned by FPDFText_LoadPage function. +// index - Zero-based index of the character. +// Return value: +// 1 if the character has an invalid unicode mapping. +// 0 if the character has no known unicode mapping issues. +// -1 if there was an error. +// +var + FPDFText_HasUnicodeMapError: function(text_page: FPDF_TEXTPAGE; index: Integer): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // Function: FPDFText_GetFontSize // Get the font size of a particular character. // Parameters: @@ -2597,22 +3427,6 @@ FPDF_FILEWRITE = record var FPDFText_GetFontWeight: function(text_page: FPDF_TEXTPAGE; index: Integer): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -// Experimental API. -// Function: FPDFText_GetTextRenderMode -// Get text rendering mode of character. -// Parameters: -// text_page - Handle to a text page information structure. -// Returned by FPDFText_LoadPage function. -// index - Zero-based index of the character. -// Return Value: -// On success, return the render mode value. A valid value is of type -// FPDF_TEXT_RENDERMODE. If |text_page| is invalid, if |index| is out -// of bounds, or if the text object is undefined, then return -// FPDF_TEXTRENDERMODE_UNKNOWN. -// -var - FPDFText_GetTextRenderMode: function(text_page: FPDF_TEXTPAGE; index: Integer): FPDF_TEXT_RENDERMODE; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; - // Experimental API. // Function: FPDFText_GetFillColor // Get the fill color of a particular character. @@ -2772,35 +3586,40 @@ FPDF_FILEWRITE = record // text_page - Handle to a text page information structure. // Returned by FPDFText_LoadPage function. // start_index - Index for the start characters. -// count - Number of characters to be extracted. +// count - Number of UCS-2 values to be extracted. // result - A buffer (allocated by application) receiving the -// extracted unicodes. The size of the buffer must be -// able to hold the number of characters plus a -// terminator. +// extracted UCS-2 values. The buffer must be able to +// hold `count` UCS-2 values plus a terminator. // Return Value: // Number of characters written into the result buffer, including the // trailing terminator. // Comments: -// This function ignores characters without unicode information. +// This function ignores characters without UCS-2 representations. +// It considers all characters on the page, even those that are not +// visible when the page has a cropbox. To filter out the characters +// outside of the cropbox, use FPDF_GetPageBoundingBox() and +// FPDFText_GetCharBox(). // var FPDFText_GetText: function(text_page: FPDF_TEXTPAGE; start_index, count: Integer; result: PWideChar): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; // Function: FPDFText_CountRects -// Count number of rectangular areas occupied by a segment of texts. +// Counts number of rectangular areas occupied by a segment of text, +// and caches the result for subsequent FPDFText_GetRect() calls. // Parameters: // text_page - Handle to a text page information structure. // Returned by FPDFText_LoadPage function. -// start_index - Index for the start characters. -// count - Number of characters. +// start_index - Index for the start character. +// count - Number of characters, or -1 for all remaining. // Return value: -// Number of rectangles. Zero for error. +// Number of rectangles, 0 if text_page is null, or -1 on bad +// start_index. // Comments: // This function, along with FPDFText_GetRect can be used by // applications to detect the position on the page for a text segment, -// so proper areas can be highlighted. FPDFTEXT will automatically -// merge small character boxes into bigger one if those characters -// are on the same line and use same font settings. +// so proper areas can be highlighted. The FPDFText_* functions will +// automatically merge small character boxes into bigger one if those +// characters are on the same line and use same font settings. // var FPDFText_CountRects: function(text_page: FPDF_TEXTPAGE; start_index, count: Integer): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; @@ -2839,20 +3658,20 @@ FPDF_FILEWRITE = record // top - Top boundary. // right - Right boundary. // bottom - Bottom boundary. -// buffer - A unicode buffer. -// buflen - Number of characters (not bytes) for the buffer, -// excluding an additional terminator. +// buffer - Caller-allocated buffer to receive UTF-16 values. +// buflen - Number of UTF-16 values (not bytes) that `buffer` +// is capable of holding. // Return Value: -// If buffer is NULL or buflen is zero, return number of characters -// (not bytes) of text present within the rectangle, excluding a -// terminating NUL. Generally you should pass a buffer at least one +// If buffer is NULL or buflen is zero, return number of UTF-16 +// values (not bytes) of text present within the rectangle, excluding +// a terminating NUL. Generally you should pass a buffer at least one // larger than this if you want a terminating NUL, which will be -// provided if space is available. Otherwise, return number of -// characters copied into the buffer, including the terminating NUL -// when space for it is available. +// provided if space is available. Otherwise, return number of UTF-16 +// values copied into the buffer, including the terminating NUL when +// space for it is available. // Comment: // If the buffer is too small, as much text as will fit is copied into -// it. +// it. May return a split surrogate in that case. // var FPDFText_GetBoundedText: function(text_page: FPDF_TEXTPAGE; left, top, right, bottom: Double; @@ -3083,24 +3902,19 @@ FPDF_FILEWRITE = record type PIFSDK_PAUSE = ^IFSDK_PAUSE; IFSDK_PAUSE = record - //* - //* Version number of the interface. Currently must be 1. - //* + // Version number of the interface. Currently must be 1. version: Integer; - //* - //* Method: NeedToPauseNow - //* Check if we need to pause a progressive process now. - //* Interface Version: - //* 1 - //* Implementation Required: - //* yes - //* Parameters: - //* pThis - Pointer to the interface structure itself - //* Return Value: - //* Non-zero for pause now, 0 for continue. - //* - //* + // Method: NeedToPauseNow + // Check if we need to pause a progressive process now. + // Interface Version: + // 1 + // Implementation Required: + // yes + // Parameters: + // pThis - Pointer to the interface structure itself + // Return Value: + // Non-zero for pause now, 0 for continue. NeedToPauseNow: function(pThis: PIFSDK_PAUSE): FPDF_BOOL; cdecl; // A user defined data pointer, used by user's application. Can be NULL. @@ -3109,6 +3923,44 @@ IFSDK_PAUSE = record PIFSDKPause = ^TIFSDKPause; TIFSDKPause = IFSDK_PAUSE; +// Experimental API. +// Function: FPDF_RenderPageBitmapWithColorScheme_Start +// Start to render page contents to a device independent bitmap +// progressively with a specified color scheme for the content. +// Parameters: +// bitmap - Handle to the device independent bitmap (as the +// output buffer). Bitmap handle can be created by +// FPDFBitmap_Create function. +// page - Handle to the page as returned by FPDF_LoadPage +// function. +// start_x - Left pixel position of the display area in the +// bitmap coordinate. +// start_y - Top pixel position of the display area in the +// bitmap coordinate. +// size_x - Horizontal size (in pixels) for displaying the +// page. +// size_y - Vertical size (in pixels) for displaying the page. +// rotate - Page orientation: 0 (normal), 1 (rotated 90 +// degrees clockwise), 2 (rotated 180 degrees), +// 3 (rotated 90 degrees counter-clockwise). +// flags - 0 for normal display, or combination of flags +// defined in fpdfview.h. With FPDF_ANNOT flag, it +// renders all annotations that does not require +// user-interaction, which are all annotations except +// widget and popup annotations. +// color_scheme - Color scheme to be used in rendering the |page|. +// If null, this function will work similar to +// FPDF_RenderPageBitmap_Start(). +// pause - The IFSDK_PAUSE interface. A callback mechanism +// allowing the page rendering process. +// Return value: +// Rendering Status. See flags for progressive process status for the +// details. +var + FPDF_RenderPageBitmapWithColorScheme_Start: function(bitmap: FPDF_BITMAP; page: FPDF_PAGE; + start_x, start_y, size_x, size_y: Integer; rotate: Integer; flags: Integer; + const color_scheme: PFPDF_COLORSCHEME; pause: PIFSDK_PAUSE): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // Function: FPDF_RenderPageBitmap_Start // Start to render page contents to a device independent bitmap // progressively. @@ -3136,7 +3988,6 @@ IFSDK_PAUSE = record // Return value: // Rendering Status. See flags for progressive process status for the // details. -// var FPDF_RenderPageBitmap_Start: function(bitmap: FPDF_BITMAP; page: FPDF_PAGE; start_x, start_y, size_x, size_y: Integer; rotate: Integer; flags: Integer; @@ -3168,15 +4019,145 @@ IFSDK_PAUSE = record FPDF_RenderPage_Close: procedure(page: FPDF_PAGE); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// *** _FPDF_SIGNATURE_H_ *** + +// Experimental API. +// Function: FPDF_GetSignatureCount +// Get total number of signatures in the document. +// Parameters: +// document - Handle to document. Returned by FPDF_LoadDocument(). +// Return value: +// Total number of signatures in the document on success, -1 on error. +var + FPDF_GetSignatureCount: function(document: FPDF_DOCUMENT): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Function: FPDF_GetSignatureObject +// Get the Nth signature of the document. +// Parameters: +// document - Handle to document. Returned by FPDF_LoadDocument(). +// index - Index into the array of signatures of the document. +// Return value: +// Returns the handle to the signature, or NULL on failure. The caller +// does not take ownership of the returned FPDF_SIGNATURE. Instead, it +// remains valid until FPDF_CloseDocument() is called for the document. +var + FPDF_GetSignatureObject: function(document: FPDF_DOCUMENT; index: Integer): FPDF_SIGNATURE; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Function: FPDFSignatureObj_GetContents +// Get the contents of a signature object. +// Parameters: +// signature - Handle to the signature object. Returned by +// FPDF_GetSignatureObject(). +// buffer - The address of a buffer that receives the contents. +// length - The size, in bytes, of |buffer|. +// Return value: +// Returns the number of bytes in the contents on success, 0 on error. +// +// For public-key signatures, |buffer| is either a DER-encoded PKCS#1 binary or +// a DER-encoded PKCS#7 binary. If |length| is less than the returned length, or +// |buffer| is NULL, |buffer| will not be modified. +var + FPDFSignatureObj_GetContents: function(signature: FPDF_SIGNATURE; buffer: Pointer; length: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Function: FPDFSignatureObj_GetByteRange +// Get the byte range of a signature object. +// Parameters: +// signature - Handle to the signature object. Returned by +// FPDF_GetSignatureObject(). +// buffer - The address of a buffer that receives the +// byte range. +// length - The size, in ints, of |buffer|. +// Return value: +// Returns the number of ints in the byte range on +// success, 0 on error. +// +// |buffer| is an array of pairs of integers (starting byte offset, +// length in bytes) that describes the exact byte range for the digest +// calculation. If |length| is less than the returned length, or +// |buffer| is NULL, |buffer| will not be modified. +var + FPDFSignatureObj_GetByteRange: function(signature: FPDF_SIGNATURE; buffer: PInteger; length: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Function: FPDFSignatureObj_GetSubFilter +// Get the encoding of the value of a signature object. +// Parameters: +// signature - Handle to the signature object. Returned by +// FPDF_GetSignatureObject(). +// buffer - The address of a buffer that receives the encoding. +// length - The size, in bytes, of |buffer|. +// Return value: +// Returns the number of bytes in the encoding name (including the +// trailing NUL character) on success, 0 on error. +// +// The |buffer| is always encoded in 7-bit ASCII. If |length| is less than the +// returned length, or |buffer| is NULL, |buffer| will not be modified. +var + FPDFSignatureObj_GetSubFilter: function(signature: FPDF_SIGNATURE; buffer: PAnsiChar; length: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Function: FPDFSignatureObj_GetReason +// Get the reason (comment) of the signature object. +// Parameters: +// signature - Handle to the signature object. Returned by +// FPDF_GetSignatureObject(). +// buffer - The address of a buffer that receives the reason. +// length - The size, in bytes, of |buffer|. +// Return value: +// Returns the number of bytes in the reason on success, 0 on error. +// +// Regardless of the platform, the |buffer| is always in UTF-16LE encoding. The +// string is terminated by a UTF16 NUL character. If |length| is less than the +// returned length, or |buffer| is NULL, |buffer| will not be modified. +var + FPDFSignatureObj_GetReason: function(signature: FPDF_SIGNATURE; buffer: Pointer; length: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Function: FPDFSignatureObj_GetTime +// Get the time of signing of a signature object. +// Parameters: +// signature - Handle to the signature object. Returned by +// FPDF_GetSignatureObject(). +// buffer - The address of a buffer that receives the time. +// length - The size, in bytes, of |buffer|. +// Return value: +// Returns the number of bytes in the encoding name (including the +// trailing NUL character) on success, 0 on error. +// +// The |buffer| is always encoded in 7-bit ASCII. If |length| is less than the +// returned length, or |buffer| is NULL, |buffer| will not be modified. +// +// The format of time is expected to be D:YYYYMMDDHHMMSS+XX'YY', i.e. it's +// percision is seconds, with timezone information. This value should be used +// only when the time of signing is not available in the (PKCS#7 binary) +// signature. +var + FPDFSignatureObj_GetTime: function(signature: FPDF_SIGNATURE; buffer: PAnsiChar; length: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Function: FPDFSignatureObj_GetDocMDPPermission +// Get the DocMDP permission of a signature object. +// Parameters: +// signature - Handle to the signature object. Returned by +// FPDF_GetSignatureObject(). +// Return value: +// Returns the permission (1, 2 or 3) on success, 0 on error. +var + FPDFSignatureObj_GetDocMDPPermission: function(signature: FPDF_SIGNATURE): UInt32; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // *** _FPDF_DOC_H_ *** const - PDFACTION_UNSUPPORTED = 0; // Unsupported action type. - PDFACTION_GOTO = 1; // Go to a destination within current document. - PDFACTION_REMOTEGOTO = 2; // Go to a destination within another document. - PDFACTION_URI = 3; // Universal Resource Identifier, including web pages and - // other Internet based resources. - PDFACTION_LAUNCH = 4; // Launch an application or open a file. + PDFACTION_UNSUPPORTED = 0; // Unsupported action type. + PDFACTION_GOTO = 1; // Go to a destination within current document. + PDFACTION_REMOTEGOTO = 2; // Go to a destination within another document. + PDFACTION_URI = 3; // Universal Resource Identifier, including web pages and + // other Internet based resources. + PDFACTION_LAUNCH = 4; // Launch an application or open a file. + PDFACTION_EMBEDDEDGOTO = 5; // Go to a destination in an embedded file. // View destination fit types. See pdfmark reference v9, page 48. PDFDEST_VIEW_UNKNOWN_MODE = 0; @@ -3189,21 +4170,13 @@ IFSDK_PAUSE = record PDFDEST_VIEW_FITBH = 7; PDFDEST_VIEW_FITBV = 8; -// _FS_DEF_STRUCTURE_QUADPOINTSF_ +// The file identifier entry type. See section 14.4 "File Identifiers" of the +// ISO 32000-1:2008 spec. type - PFS_QUADPOINTSF = ^FS_QUADPOINTSF; - FS_QUADPOINTSF = record - x1: FS_FLOAT; - y1: FS_FLOAT; - x2: FS_FLOAT; - y2: FS_FLOAT; - x3: FS_FLOAT; - y3: FS_FLOAT; - x4: FS_FLOAT; - y4: FS_FLOAT; - end; - PFSQuadPointsF = ^TFSQuadPointsF; - TFSQuadPointsF = FS_QUADPOINTSF; + FPDF_FILEIDTYPE = ( + FILEIDTYPE_PERMANENT = 0, + FILEIDTYPE_CHANGING = 1 + ); // Get the first child of |bookmark|, or the first top-level bookmark item. // @@ -3213,6 +4186,8 @@ FS_QUADPOINTSF = record // // Returns a handle to the first child of |bookmark| or the first top-level // bookmark item. NULL if no child or top-level bookmark found. +// Note that another name for the bookmarks is the document outline, as +// described in ISO 32000-1:2008, section 12.3.3. var FPDFBookmark_GetFirstChild: function(document: FPDF_DOCUMENT; bookmark: FPDF_BOOKMARK): FPDF_BOOKMARK; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; @@ -3223,6 +4198,9 @@ FS_QUADPOINTSF = record // // Returns a handle to the next sibling of |bookmark|, or NULL if this is the // last bookmark at this level. +// +// Note that the caller is responsible for handling circular bookmark +// references, as may arise from malformed documents. var FPDFBookmark_GetNextSibling: function(document: FPDF_DOCUMENT; bookmark: FPDF_BOOKMARK): FPDF_BOOKMARK; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; @@ -3242,6 +4220,19 @@ FS_QUADPOINTSF = record var FPDFBookmark_GetTitle: function(bookmark: FPDF_BOOKMARK; buffer: Pointer; buflen: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Experimental API. +// Get the number of chlidren of |bookmark|. +// +// bookmark - handle to the bookmark. +// +// Returns a signed integer that represents the number of sub-items the given +// bookmark has. If the value is positive, child items shall be shown by default +// (open state). If the value is negative, child items shall be hidden by +// default (closed state). Please refer to PDF 32000-1:2008, Table 153. +// Returns 0 if the bookmark has no children or is invalid. +var + FPDFBookmark_GetCount: function(bookmark: FPDF_BOOKMARK): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // Find the bookmark with |title| in |document|. // // document - handle to the document. @@ -3259,7 +4250,7 @@ FS_QUADPOINTSF = record // document - handle to the document. // bookmark - handle to the bookmark. // -// Returns the handle to the destination data, NULL if no destination is +// Returns the handle to the destination data, or NULL if no destination is // associated with |bookmark|. var FPDFBookmark_GetDest: function(document: FPDF_DOCUMENT; bookmark: FPDF_BOOKMARK): FPDF_DEST; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; @@ -3269,8 +4260,11 @@ FS_QUADPOINTSF = record // bookmark - handle to the bookmark. // // Returns the handle to the action data, or NULL if no action is associated -// with |bookmark|. When NULL is returned, FPDFBookmark_GetDest() should be -// called to get the |bookmark| destination data. +// with |bookmark|. +// If this function returns a valid handle, it is valid as long as |bookmark| is +// valid. +// If this function returns NULL, FPDFBookmark_GetDest() should be called to get +// the |bookmark| destination data. var FPDFBookmark_GetAction: function(bookmark: FPDF_BOOKMARK): FPDF_ACTION; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; @@ -3330,8 +4324,18 @@ FS_QUADPOINTSF = record // character, or 0 on error, typically because the arguments were bad or the // action was of the wrong type. // -// The |buffer| is always encoded in 7-bit ASCII. If |buflen| is less than the -// returned length, or |buffer| is NULL, |buffer| will not be modified. +// The |buffer| may contain badly encoded data. The caller should validate the +// output. e.g. Check to see if it is UTF-8. +// +// If |buflen| is less than the returned length, or |buffer| is NULL, |buffer| +// will not be modified. +// +// Historically, the documentation for this API claimed |buffer| is always +// encoded in 7-bit ASCII, but did not actually enforce it. +// https://pdfium.googlesource.com/pdfium.git/+/d609e84cee2e14a18333247485af91df48a40592 +// added that enforcement, but that did not work well for real world PDFs that +// used UTF-8. As of this writing, this API reverted back to its original +// behavior prior to commit d609e84cee. var FPDFAction_GetURIPath: function(document: FPDF_DOCUMENT; action: FPDF_ACTION; buffer: Pointer; buflen: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; @@ -3344,8 +4348,8 @@ FS_QUADPOINTSF = record var FPDFDest_GetDestPageIndex: function(document: FPDF_DOCUMENT; dest: FPDF_DEST): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Experimental API. // Get the view (fit type) specified by |dest|. -// Experimental API. Subject to change. // // dest - handle to the destination. // pNumParams - receives the number of view parameters, which is at most 4. @@ -3417,6 +4421,8 @@ FS_QUADPOINTSF = record // link - handle to the link. // // Returns a handle to the action associated to |link|, or NULL if no action. +// If this function returns a valid handle, it is valid as long as |link| is +// valid. var FPDFLink_GetAction: function(link: FPDF_LINK): FPDF_ACTION; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; @@ -3431,6 +4437,17 @@ FS_QUADPOINTSF = record var FPDFLink_Enumerate: function(page: FPDF_PAGE; var start_pos: Integer; link_annot: PFPDF_LINK): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Experimental API. +// Gets FPDF_ANNOTATION object for |link_annot|. +// +// page - handle to the page in which FPDF_LINK object is present. +// link_annot - handle to link annotation. +// +// Returns FPDF_ANNOTATION from the FPDF_LINK and NULL on failure, +// if the input link annot or page is NULL. +var + FPDFLink_GetAnnot: function(page: FPDF_PAGE; link_annot: FPDF_LINK): FPDF_ANNOTATION; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // Get the rectangle for |link_annot|. // // link_annot - handle to the link annotation. @@ -3458,6 +4475,38 @@ FS_QUADPOINTSF = record var FPDFLink_GetQuadPoints: function(link_annot: FPDF_LINK; quad_index: Integer; quad_points: PFS_QUADPOINTSF): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Experimental API. +// Gets an additional-action from |page|. +// +// page - handle to the page, as returned by FPDF_LoadPage(). +// aa_type - the type of the page object's addtional-action, defined +// in public/fpdf_formfill.h +// +// Returns the handle to the action data, or NULL if there is no +// additional-action of type |aa_type|. +// If this function returns a valid handle, it is valid as long as |page| is +// valid. +var + FPDF_GetPageAAction: function(page: FPDF_PAGE; aa_type: Integer): FPDF_ACTION; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Get the file identifer defined in the trailer of |document|. +// +// document - handle to the document. +// id_type - the file identifier type to retrieve. +// buffer - a buffer for the file identifier. May be NULL. +// buflen - the length of the buffer, in bytes. May be 0. +// +// Returns the number of bytes in the file identifier, including the NUL +// terminator. +// +// The |buffer| is always a byte string. The |buffer| is followed by a NUL +// terminator. If |buflen| is less than the returned length, or |buffer| is +// NULL, |buffer| will not be modified. +var + FPDF_GetFileIdentifier: function(document: FPDF_DOCUMENT; id_type: FPDF_FILEIDTYPE; buffer: Pointer; + buflen: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // Get meta-data |tag| content from |document|. // // document - handle to the document. @@ -3509,8 +4558,12 @@ FS_QUADPOINTSF = record FXFONT_HANGEUL_CHARSET = 129; FXFONT_GB2312_CHARSET = 134; FXFONT_CHINESEBIG5_CHARSET = 136; + FXFONT_GREEK_CHARSET = 161; + FXFONT_VIETNAMESE_CHARSET = 163; + FXFONT_HEBREW_CHARSET = 177; FXFONT_ARABIC_CHARSET = 178; FXFONT_CYRILLIC_CHARSET = 204; + FXFONT_THAI_CHARSET = 222; FXFONT_EASTERNEUROPEAN_CHARSET = 238; @@ -3523,184 +4576,171 @@ FS_QUADPOINTSF = record FXFONT_FW_NORMAL = 400; FXFONT_FW_BOLD = 700; -//* -//* Interface: FPDF_SYSFONTINFO -//* Interface for getting system font information and font mapping -//* +// Interface: FPDF_SYSFONTINFO +// Interface for getting system font information and font mapping type PFPDF_SYSFONTINFO = ^FPDF_SYSFONTINFO; FPDF_SYSFONTINFO = record - //* - //* Version number of the interface. Currently must be 1. - //* + // Version number of the interface. Currently must be 1 or 2. + // Version 1: Traditional behavior - calls EnumFonts during initialization. + // Version 2: Per-request behavior - skips EnumFonts, relies on MapFont. + // Experimental: Subject to change based on feedback. version: Integer; - //* - //* Method: Release - //* Give implementation a chance to release any data after the - //* interface is no longer used - //* Interface Version: - //* 1 - //* Implementation Required: - //* No - //* Comments: - //* Called by Foxit SDK during the final cleanup process. - //* Parameters: - //* pThis - Pointer to the interface structure itself - //* Return Value: - //* None - //* + // Method: Release + // Give implementation a chance to release any data after the + // interface is no longer used. + // Interface Version: + // 1 and 2 + // Implementation Required: + // No + // Parameters: + // pThis - Pointer to the interface structure itself + // Return Value: + // None + // Comments: + // Called by PDFium during the final cleanup process. + // NOTE: This method will not be called when version is set to 2. + // Version 2 relies entirely on MapFont() for per-request matching. Release: procedure(pThis: PFPDF_SYSFONTINFO); cdecl; - //* - //* Method: EnumFonts - //* Enumerate all fonts installed on the system - //* Interface Version: - //* 1 - //* Implementation Required: - //* No - //* Parameters: - //* pThis - Pointer to the interface structure itself - //* pMapper - An opaque pointer to internal font mapper, used - //* when calling FPDF_AddInstalledFont(). - //* Return Value: - //* None - //* Comments: - //* Implementations should call FPDF_AddIntalledFont() function for - //* each font found. Only TrueType/OpenType and Type1 fonts are accepted - //* by PDFium. - //* + // Method: EnumFonts + // Enumerate all fonts installed on the system + // Interface Version: + // 1 and 2 + // Implementation Required: + // No + // Parameters: + // pThis - Pointer to the interface structure itself + // pMapper - An opaque pointer to internal font mapper, used + // when calling FPDF_AddInstalledFont(). + // Return Value: + // None + // Comments: + // Implementations should call FPDF_AddInstalledFont() function for + // each font found. Only TrueType/OpenType and Type1 fonts are + // accepted by PDFium. EnumFonts: procedure(pThis: PFPDF_SYSFONTINFO; pMapper: Pointer); cdecl; - //* - //* Method: MapFont - //* Use the system font mapper to get a font handle from requested - //* parameters. - //* Interface Version: - //* 1 - //* Implementation Required: - //* Required if GetFont method is not implemented. - //* Parameters: - //* pThis - Pointer to the interface structure itself - //* weight - Weight of the requested font. 400 is normal and - //* 700 is bold. - //* bItalic - Italic option of the requested font, TRUE or - //* FALSE. - //* charset - Character set identifier for the requested font. - //* See above defined constants. - //* pitch_family - A combination of flags. See above defined - //* constants. - //* face - Typeface name. Currently use system local encoding - //* only. - //* bExact - Obsolete: this parameter is now ignored. - //* Return Value: - //* An opaque pointer for font handle, or NULL if system mapping is - //* not supported. - //* Comments: - //* If the system supports native font mapper (like Windows), - //* implementation can implement this method to get a font handle. - //* Otherwise, PDFium will do the mapping and then call GetFont - //* method. Only TrueType/OpenType and Type1 fonts are accepted - //* by PDFium. - //* + // Method: MapFont + // Use the system font mapper to get a font handle from requested + // parameters. + // Interface Version: + // 1 + // Implementation Required: + // Required if GetFont method is not implemented. + // Parameters: + // pThis - Pointer to the interface structure itself + // weight - Weight of the requested font. 400 is normal and + // 700 is bold. + // bItalic - Italic option of the requested font, TRUE or + // FALSE. + // charset - Character set identifier for the requested font. + // See above defined constants. + // pitch_family - A combination of flags. See above defined + // constants. + // face - Typeface name. Currently use system local encoding + // only. + // bExact - Obsolete: this parameter is now ignored. + // Return Value: + // An opaque pointer for font handle, or NULL if system mapping is + // not supported. + // Comments: + // If the system supports native font mapper (like Windows), + // implementation can implement this method to get a font handle. + // Otherwise, PDFium will do the mapping and then call GetFont + // method. Only TrueType/OpenType and Type1 fonts are accepted + // by PDFium. MapFont: function(pThis: PFPDF_SYSFONTINFO; weight, bItalic, charset, pitch_family: Integer; face: PAnsiChar; bExact: PInteger): Pointer; cdecl; - //* - //* Method: GetFont - //* Get a handle to a particular font by its internal ID - //* Interface Version: - //* 1 - //* Implementation Required: - //* Required if MapFont method is not implemented. - //* Return Value: - //* An opaque pointer for font handle. - //* Parameters: - //* pThis - Pointer to the interface structure itself - //* face - Typeface name in system local encoding. - //* Comments: - //* If the system mapping not supported, PDFium will do the font - //* mapping and use this method to get a font handle. - //* + // Method: GetFont + // Get a handle to a particular font by its internal ID + // Interface Version: + // 1 and 2 + // Implementation Required: + // Required if MapFont method is not implemented. + // Return Value: + // An opaque pointer for font handle. + // Parameters: + // pThis - Pointer to the interface structure itself + // face - Typeface name in system local encoding. + // Comments: + // If the system mapping not supported, PDFium will do the font + // mapping and use this method to get a font handle. GetFont: function(pThis: PFPDF_SYSFONTINFO; face: PAnsiChar): Pointer; cdecl; - //* - //* Method: GetFontData - //* Get font data from a font - //* Interface Version: - //* 1 - //* Implementation Required: - //* Yes - //* Parameters: - //* pThis - Pointer to the interface structure itself - //* hFont - Font handle returned by MapFont or GetFont method - //* table - TrueType/OpenType table identifier (refer to - //* TrueType specification), or 0 for the whole file. - //* buffer - The buffer receiving the font data. Can be NULL if - //* not provided. - //* buf_size - Buffer size, can be zero if not provided. - //* Return Value: - //* Number of bytes needed, if buffer not provided or not large - //* enough, or number of bytes written into buffer otherwise. - //* Comments: - //* Can read either the full font file, or a particular - //* TrueType/OpenType table. - //* + // Method: GetFontData + // Get font data from a font + // Interface Version: + // 1 and 2 + // Implementation Required: + // Yes + // Parameters: + // pThis - Pointer to the interface structure itself + // hFont - Font handle returned by MapFont or GetFont method + // table - TrueType/OpenType table identifier (refer to + // TrueType specification), or 0 for the whole file. + // buffer - The buffer receiving the font data. Can be NULL if + // not provided. + // buf_size - Buffer size, can be zero if not provided. + // Return Value: + // Number of bytes needed, if buffer not provided or not large + // enough, or number of bytes written into buffer otherwise. + // Comments: + // Can read either the full font file, or a particular + // TrueType/OpenType table. GetFontData: function(pThis: PFPDF_SYSFONTINFO; hFont: Pointer; table: LongWord; buffer: PWideChar; buf_size: LongWord): LongWord; cdecl; - //* - //* Method: GetFaceName - //* Get face name from a font handle - //* Interface Version: - //* 1 - //* Implementation Required: - //* No - //* Parameters: - //* pThis - Pointer to the interface structure itself - //* hFont - Font handle returned by MapFont or GetFont method - //* buffer - The buffer receiving the face name. Can be NULL if - //* not provided - //* buf_size - Buffer size, can be zero if not provided - //* Return Value: - //* Number of bytes needed, if buffer not provided or not large - //* enough, or number of bytes written into buffer otherwise. - //* + // Method: GetFaceName + // Get face name from a font handle + // Interface Version: + // 1 and 2 + // Implementation Required: + // No + // Parameters: + // pThis - Pointer to the interface structure itself + // hFont - Font handle returned by MapFont or GetFont method + // buffer - The buffer receiving the face name. Can be NULL if + // not provided + // buf_size - Buffer size, can be zero if not provided + // Return Value: + // Number of bytes needed, if buffer not provided or not large + // enough, or number of bytes written into buffer otherwise. GetFaceName: function(pThis: PFPDF_SYSFONTINFO; hFont: Pointer; buffer: PAnsiChar; buf_size: LongWord): LongWord; cdecl; - //* - //* Method: GetFontCharset - //* Get character set information for a font handle - //* Interface Version: - //* 1 - //* Implementation Required: - //* No - //* Parameters: - //* pThis - Pointer to the interface structure itself - //* hFont - Font handle returned by MapFont or GetFont method - //* Return Value: - //* Character set identifier. See defined constants above. - //* + // Method: GetFontCharset + // Get character set information for a font handle + // Interface Version: + // 1 and 2 + // Implementation Required: + // No + // Parameters: + // pThis - Pointer to the interface structure itself + // hFont - Font handle returned by MapFont or GetFont method + // Return Value: + // Character set identifier. See defined constants above. GetFontCharset: function(pThis: PFPDF_SYSFONTINFO; hFont: Pointer): Integer; cdecl; - //* - //* Method: DeleteFont - //* Delete a font handle - //* Interface Version: - //* 1 - //* Implementation Required: - //* Yes - //* Parameters: - //* pThis - Pointer to the interface structure itself - //* hFont - Font handle returned by MapFont or GetFont method - //* Return Value: - //* None - //* + // Method: DeleteFont + // Delete a font handle + // Interface Version: + // 1 and 2 + // Implementation Required: + // Yes + // Parameters: + // pThis - Pointer to the interface structure itself + // hFont - Font handle returned by MapFont or GetFont method + // Return Value: + // None DeleteFont: procedure(pThis: PFPDF_SYSFONTINFO; hFont: Pointer); cdecl; end; PFPdfSysFontInfo = ^TFPdfSysFontInfo; TFPdfSysFontInfo = FPDF_SYSFONTINFO; + // Struct: FPDF_CharsetFontMap + // Provides the name of a font to use for a given charset value. PFPDF_CharsetFontMap = ^FPDF_CharsetFontMap; FPDF_CharsetFontMap = record charset: Integer; // Character Set Enum value, see FXFONT_*_CHARSET above. @@ -3709,81 +4749,102 @@ FPDF_CharsetFontMap = record PFPdfCharsetFontMap = ^TFPdfCharsetFontMap; TFPdfCharsetFontMap = FPDF_CharsetFontMap; -//* -//* Function: FPDF_GetDefaultTTFMap -//* Returns a pointer to the default character set to TT Font name map. The -//* map is an array of FPDF_CharsetFontMap structs, with its end indicated -//* by a { -1, NULL } entry. -//* Parameters: -//* None. -//* Return Value: -//* Pointer to the Charset Font Map. -//* +// Function: FPDF_GetDefaultTTFMap +// Returns a pointer to the default character set to TT Font name map. The +// map is an array of FPDF_CharsetFontMap structs, with its end indicated +// by a { -1, NULL } entry. +// Parameters: +// None. +// Return Value: +// Pointer to the Charset Font Map. +// Note: +// Once FPDF_GetDefaultTTFMapCount() and FPDF_GetDefaultTTFMapEntry() are no +// longer experimental, this API will be marked as deprecated. +// See https://crbug.com/348468114 var FPDF_GetDefaultTTFMap: function: PFPDF_CharsetFontMap; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//* -//* Function: FPDF_AddInstalledFont -//* Add a system font to the list in PDFium. -//* Comments: -//* This function is only called during the system font list building -//* process. -//* Parameters: -//* mapper - Opaque pointer to Foxit font mapper -//* face - The font face name -//* charset - Font character set. See above defined constants. -//* Return Value: -//* None. -//* +// Experimental API. +// +// Function: FPDF_GetDefaultTTFMapCount +// Returns the number of entries in the default character set to TT Font name +// map. +// Parameters: +// None. +// Return Value: +// The number of entries in the map. +var + FPDF_GetDefaultTTFMapCount: function(): SIZE_T; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// +// Function: FPDF_GetDefaultTTFMapEntry +// Returns an entry in the default character set to TT Font name map. +// Parameters: +// index - The index to the entry in the map to retrieve. +// Return Value: +// A pointer to the entry, if it is in the map, or NULL if the index is out +// of bounds. +var + FPDF_GetDefaultTTFMapEntry: function(index: SIZE_T): PFPDF_CharsetFontMap; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Function: FPDF_AddInstalledFont +// Add a system font to the list in PDFium. +// Comments: +// This function is only called during the system font list building +// process. +// Parameters: +// mapper - Opaque pointer to Foxit font mapper +// face - The font face name +// charset - Font character set. See above defined constants. +// Return Value: +// None. var FPDF_AddInstalledFont: procedure(mapper: Pointer; face: PAnsiChar; charset: Integer); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//* -//* Function: FPDF_SetSystemFontInfo -//* Set the system font info interface into PDFium -//* Parameters: -//* pFontInfo - Pointer to a FPDF_SYSFONTINFO structure -//* Return Value: -//* None -//* Comments: -//* Platform support implementation should implement required methods of -//* FFDF_SYSFONTINFO interface, then call this function during PDFium -//* initialization process. -//* -var - FPDF_SetSystemFontInfo: procedure(pFontInfo: PFPDF_SYSFONTINFO); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; - -//* -//* Function: FPDF_GetDefaultSystemFontInfo -//* Get default system font info interface for current platform -//* Parameters: -//* None -//* Return Value: -//* Pointer to a FPDF_SYSFONTINFO structure describing the default -//* interface, or NULL if the platform doesn't have a default interface. -//* Application should call FPDF_FreeDefaultSystemFontInfo to free the -//* returned pointer. -//* Comments: -//* For some platforms, PDFium implements a default version of system -//* font info interface. The default implementation can be passed to -//* FPDF_SetSystemFontInfo(). -//* +// Function: FPDF_SetSystemFontInfo +// Set the system font info interface into PDFium +// Parameters: +// font_info - Pointer to a FPDF_SYSFONTINFO structure +// Return Value: +// None +// Comments: +// Platform support implementation should implement required methods of +// FFDF_SYSFONTINFO interface, then call this function during PDFium +// initialization process. +// +// Call this with NULL to tell PDFium to stop using a previously set +// |FPDF_SYSFONTINFO|. +var + FPDF_SetSystemFontInfo: procedure(font_info: PFPDF_SYSFONTINFO); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Function: FPDF_GetDefaultSystemFontInfo +// Get default system font info interface for current platform +// Parameters: +// None +// Return Value: +// Pointer to a FPDF_SYSFONTINFO structure describing the default +// interface, or NULL if the platform doesn't have a default interface. +// Application should call FPDF_FreeDefaultSystemFontInfo to free the +// returned pointer. +// Comments: +// For some platforms, PDFium implements a default version of system +// font info interface. The default implementation can be passed to +// FPDF_SetSystemFontInfo(). var FPDF_GetDefaultSystemFontInfo: function(): FPDF_SYSFONTINFO; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//* -//* Function: FPDF_FreeDefaultSystemFontInfo -//* Free a default system font info interface -//* Parameters: -//* pFontInfo - Pointer to a FPDF_SYSFONTINFO structure -//* Return Value: -//* None -//* Comments: -//* This function should be called on the output from -//* FPDF_SetSystemFontInfo() once it is no longer needed. -//* +// Function: FPDF_FreeDefaultSystemFontInfo +// Free a default system font info interface +// Parameters: +// font_info - Pointer to a FPDF_SYSFONTINFO structure +// Return Value: +// None +// Comments: +// This function should be called on the output from +// FPDF_GetDefaultSystemFontInfo() once it is no longer needed. var - FPDF_FreeDefaultSystemFontInfo: procedure(pFontInfo: PFPDF_SYSFONTINFO); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + FPDF_FreeDefaultSystemFontInfo: procedure(font_info: PFPDF_SYSFONTINFO); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; // *** _FPDF_EXT_H_ *** @@ -3929,8 +4990,6 @@ FX_FILEAVAIL = record PFXFileAvail = ^TFXFileAvail; TFXFileAvail = FX_FILEAVAIL; - FPDF_AVAIL = ^__FPDF_PTRREC; - // Create a document availability provider. // // file_avail - pointer to file availability interface. @@ -4120,243 +5179,224 @@ FX_DOWNLOADHINTS = record type PIPDF_JsPlatform = ^IPDF_JsPlatform; IPDF_JsPlatform = record - //* - //* Version number of the interface. Currently must be 2. - //* + // Version number of the interface. Currently must be 2. version: Integer; - //* Version 1. - - //* - //* Method: app_alert - //* Pop up a dialog to show warning or hint. - //* Interface Version: - //* 1 - //* Implementation Required: - //* yes - //* Parameters: - //* pThis - Pointer to the interface structure itself. - //* Msg - A string containing the message to be displayed. - //* Title - The title of the dialog. - //* Type - The type of button group, one of the - //* JSPLATFORM_ALERT_BUTTON_* values above. - //* nIcon - The type of the icon, one of the - //* JSPLATFORM_ALERT_ICON_* above. - //* Return Value: - //* Option selected by user in dialogue, one of the - //* JSPLATFORM_ALERT_RETURN_* values above. - //* + // Version 1. + + // Method: app_alert + // Pop up a dialog to show warning or hint. + // Interface Version: + // 1 + // Implementation Required: + // yes + // Parameters: + // pThis - Pointer to the interface structure itself. + // Msg - A string containing the message to be displayed. + // Title - The title of the dialog. + // Type - The type of button group, one of the + // JSPLATFORM_ALERT_BUTTON_* values above. + // nIcon - The type of the icon, one of the + // JSPLATFORM_ALERT_ICON_* above. + // Return Value: + // Option selected by user in dialogue, one of the + // JSPLATFORM_ALERT_RETURN_* values above. app_alert: function(pThis: PIPDF_JsPlatform; Msg, Title: FPDF_WIDESTRING; nType: Integer; Icon: Integer): Integer; cdecl; - //* - //* Method: app_beep - //* Causes the system to play a sound. - //* Interface Version: - //* 1 - //* Implementation Required: - //* yes - //* Parameters: - //* pThis - Pointer to the interface structure itself - //* nType - The sound type, see JSPLATFORM_BEEP_TYPE_* - //* above. - //* Return Value: - //* None - //* + // Method: app_beep + // Causes the system to play a sound. + // Interface Version: + // 1 + // Implementation Required: + // yes + // Parameters: + // pThis - Pointer to the interface structure itself + // nType - The sound type, see JSPLATFORM_BEEP_TYPE_* + // above. + // Return Value: + // None app_beep: procedure(pThis: PIPDF_JsPlatform; nType: Integer); cdecl; - //* - //* Method: app_response - //* Displays a dialog box containing a question and an entry field for - //* the user to reply to the question. - //* Interface Version: - //* 1 - //* Implementation Required: - //* yes - //* Parameters: - //* pThis - Pointer to the interface structure itself - //* Question - The question to be posed to the user. - //* Title - The title of the dialog box. - //* Default - A default value for the answer to the question. If - //* not specified, no default value is presented. - //* cLabel - A short string to appear in front of and on the - //* same line as the edit text field. - //* bPassword - If true, indicates that the user's response should - //* be shown as asterisks (*) or bullets (?) to mask - //* the response, which might be sensitive information. - //* response - A string buffer allocated by PDFium, to receive the - //* user's response. - //* length - The length of the buffer in bytes. Currently, it is - //* always 2048. - //* Return Value: - //* Number of bytes the complete user input would actually require, not - //* including trailing zeros, regardless of the value of the length - //* parameter or the presence of the response buffer. - //* Comments: - //* No matter on what platform, the response buffer should be always - //* written using UTF-16LE encoding. If a response buffer is - //* present and the size of the user input exceeds the capacity of the - //* buffer as specified by the length parameter, only the - //* first "length" bytes of the user input are to be written to the - //* buffer. - //* + // Method: app_response + // Displays a dialog box containing a question and an entry field for + // the user to reply to the question. + // Interface Version: + // 1 + // Implementation Required: + // yes + // Parameters: + // pThis - Pointer to the interface structure itself + // Question - The question to be posed to the user. + // Title - The title of the dialog box. + // Default - A default value for the answer to the question. If + // not specified, no default value is presented. + // cLabel - A short string to appear in front of and on the + // same line as the edit text field. + // bPassword - If true, indicates that the user's response should + // be shown as asterisks (*) or bullets (?) to mask + // the response, which might be sensitive information. + // response - A string buffer allocated by PDFium, to receive the + // user's response. + // length - The length of the buffer in bytes. Currently, it is + // always 2048. + // Return Value: + // Number of bytes the complete user input would actually require, not + // including trailing zeros, regardless of the value of the length + // parameter or the presence of the response buffer. + // Comments: + // No matter on what platform, the response buffer should be always + // written using UTF-16LE encoding. If a response buffer is + // present and the size of the user input exceeds the capacity of the + // buffer as specified by the length parameter, only the + // first "length" bytes of the user input are to be written to the + // buffer. app_response: function(pThis: PIPDF_JsPlatform; Question, Title, Default, cLabel: FPDF_WIDESTRING; bPassword: FPDF_BOOL; response: Pointer; length: Integer): Integer; cdecl; - //* - //* Method: Doc_getFilePath - //* Get the file path of the current document. - //* Interface Version: - //* 1 - //* Implementation Required: - //* yes - //* Parameters: - //* pThis - Pointer to the interface structure itself - //* filePath - The string buffer to receive the file path. Can - //* be NULL. - //* length - The length of the buffer, number of bytes. Can - //* be 0. - //* Return Value: - //* Number of bytes the filePath consumes, including trailing zeros. - //* Comments: - //* The filePath should always be provided in the local encoding. - //* The return value always indicated number of bytes required for - //* the buffer, even when there is no buffer specified, or the buffer - //* size is less than required. In this case, the buffer will not - //* be modified. - //* + // Method: Doc_getFilePath + // Get the file path of the current document. + // Interface Version: + // 1 + // Implementation Required: + // yes + // Parameters: + // pThis - Pointer to the interface structure itself + // filePath - The string buffer to receive the file path. Can + // be NULL. + // length - The length of the buffer, number of bytes. Can + // be 0. + // Return Value: + // Number of bytes the filePath consumes, including trailing zeros. + // Comments: + // The filePath should always be provided in the local encoding. + // The return value always indicated number of bytes required for + // the buffer, even when there is no buffer specified, or the buffer + // size is less than required. In this case, the buffer will not + // be modified. Doc_getFilePath: function(pThis: PIPDF_JsPlatform; filePath: Pointer; length: Integer): Integer; cdecl; - //* - //* Method: Doc_mail - //* Mails the data buffer as an attachment to all recipients, with or - //* without user interaction. - //* Interface Version: - //* 1 - //* Implementation Required: - //* yes - //* Parameters: - //* pThis - Pointer to the interface structure itself - //* mailData - Pointer to the data buffer to be sent. Can be NULL. - //* length - The size,in bytes, of the buffer pointed by - //* mailData parameter. Can be 0. - //* bUI - If true, the rest of the parameters are used in a - //* compose-new-message window that is displayed to the - //* user. If false, the cTo parameter is required and - //* all others are optional. - //* To - A semicolon-delimited list of recipients for the - //* message. - //* Subject - The subject of the message. The length limit is - //* 64 KB. - //* CC - A semicolon-delimited list of CC recipients for - //* the message. - //* BCC - A semicolon-delimited list of BCC recipients for - //* the message. - //* Msg - The content of the message. The length limit is - //* 64 KB. - //* Return Value: - //* None. - //* Comments: - //* If the parameter mailData is NULL or length is 0, the current - //* document will be mailed as an attachment to all recipients. - //* + // Method: Doc_mail + // Mails the data buffer as an attachment to all recipients, with or + // without user interaction. + // Interface Version: + // 1 + // Implementation Required: + // yes + // Parameters: + // pThis - Pointer to the interface structure itself + // mailData - Pointer to the data buffer to be sent. Can be NULL. + // length - The size,in bytes, of the buffer pointed by + // mailData parameter. Can be 0. + // bUI - If true, the rest of the parameters are used in a + // compose-new-message window that is displayed to the + // user. If false, the cTo parameter is required and + // all others are optional. + // To - A semicolon-delimited list of recipients for the + // message. + // Subject - The subject of the message. The length limit is + // 64 KB. + // CC - A semicolon-delimited list of CC recipients for + // the message. + // BCC - A semicolon-delimited list of BCC recipients for + // the message. + // Msg - The content of the message. The length limit is + // 64 KB. + // Return Value: + // None. + // Comments: + // If the parameter mailData is NULL or length is 0, the current + // document will be mailed as an attachment to all recipients. Doc_mail: procedure(pThis: PIPDF_JsPlatform; mailData: Pointer; length: Integer; bUI: FPDF_BOOL; sTo, subject, CC, BCC, Msg: FPDF_WIDESTRING); cdecl; - //* - //* Method: Doc_print - //* Prints all or a specific number of pages of the document. - //* Interface Version: - //* 1 - //* Implementation Required: - //* yes - //* Parameters: - //* pThis - Pointer to the interface structure itself. - //* bUI - If true, will cause a UI to be presented to the - //* user to obtain printing information and confirm - //* the action. - //* nStart - A 0-based index that defines the start of an - //* inclusive range of pages. - //* nEnd - A 0-based index that defines the end of an - //* inclusive page range. - //* bSilent - If true, suppresses the cancel dialog box while - //* the document is printing. The default is false. - //* bShrinkToFit - If true, the page is shrunk (if necessary) to - //* fit within the imageable area of the printed page. - //* bPrintAsImage - If true, print pages as an image. - //* bReverse - If true, print from nEnd to nStart. - //* bAnnotations - If true (the default), annotations are - //* printed. - //* Return Value: - //* None. - //* + // Method: Doc_print + // Prints all or a specific number of pages of the document. + // Interface Version: + // 1 + // Implementation Required: + // yes + // Parameters: + // pThis - Pointer to the interface structure itself. + // bUI - If true, will cause a UI to be presented to the + // user to obtain printing information and confirm + // the action. + // nStart - A 0-based index that defines the start of an + // inclusive range of pages. + // nEnd - A 0-based index that defines the end of an + // inclusive page range. + // bSilent - If true, suppresses the cancel dialog box while + // the document is printing. The default is false. + // bShrinkToFit - If true, the page is shrunk (if necessary) to + // fit within the imageable area of the printed page. + // bPrintAsImage - If true, print pages as an image. + // bReverse - If true, print from nEnd to nStart. + // bAnnotations - If true (the default), annotations are + // printed. + // Return Value: + // None. Doc_print: procedure(pThis: PIPDF_JsPlatform; bUI: FPDF_BOOKMARK; nStart, nEnd: Integer; bSilent, bShrinkToFit, bPrintAsImage, bReverse, bAnnotations: FPDF_BOOL); cdecl; - //* - //* Method: Doc_submitForm - //* Send the form data to a specified URL. - //* Interface Version: - //* 1 - //* Implementation Required: - //* yes - //* Parameters: - //* pThis - Pointer to the interface structure itself - //* formData - Pointer to the data buffer to be sent. - //* length - The size,in bytes, of the buffer pointed by - //* formData parameter. - //* URL - The URL to send to. - //* Return Value: - //* None. - //* + // Method: Doc_submitForm + // Send the form data to a specified URL. + // Interface Version: + // 1 + // Implementation Required: + // yes + // Parameters: + // pThis - Pointer to the interface structure itself + // formData - Pointer to the data buffer to be sent. + // length - The size,in bytes, of the buffer pointed by + // formData parameter. + // URL - The URL to send to. + // Return Value: + // None. Doc_submitForm: procedure(pThis: PIPDF_JsPlatform; formData: Pointer; length: Integer; URL: FPDF_WIDESTRING); cdecl; - //* - //* Method: Doc_gotoPage - //* Jump to a specified page. - //* Interface Version: - //* 1 - //* Implementation Required: - //* yes - //* Parameters: - //* pThis - Pointer to the interface structure itself - //* nPageNum - The specified page number, zero for the first page. - //* Return Value: - //* None. - //* + // Method: Doc_gotoPage + // Jump to a specified page. + // Interface Version: + // 1 + // Implementation Required: + // yes + // Parameters: + // pThis - Pointer to the interface structure itself + // nPageNum - The specified page number, zero for the first page. + // Return Value: + // None. Doc_gotoPage: procedure(pThis: PIPDF_JsPlatform; nPageNum: Integer); cdecl; - //* - //* Method: Field_browse - //* Show a file selection dialog, and return the selected file path. - //* Interface Version: - //* 1 - //* Implementation Required: - //* yes - //* Parameters: - //* pThis - Pointer to the interface structure itself. - //* filePath - Pointer to the data buffer to receive the file - //* path. Can be NULL. - //* length - The length of the buffer, in bytes. Can be 0. - //* Return Value: - //* Number of bytes the filePath consumes, including trailing zeros. - //* Comments: - //* The filePath shoule always be provided in local encoding. - //* + // Method: Field_browse + // Show a file selection dialog, and return the selected file path. + // Interface Version: + // 1 + // Implementation Required: + // yes + // Parameters: + // pThis - Pointer to the interface structure itself. + // filePath - Pointer to the data buffer to receive the file + // path. Can be NULL. + // length - The length of the buffer, in bytes. Can be 0. + // Return Value: + // Number of bytes the filePath consumes, including trailing zeros. + // Comments: + // The filePath should always be provided in local encoding. Field_browse: function(pThis: PIPDF_JsPlatform; filePath: Pointer; length: Integer): Integer; cdecl; - //* - //* Pointer to FPDF_FORMFILLINFO interface. - //* + + // Pointer for embedder-specific data. Unused by PDFium, and despite + // its name, can be any data the embedder desires, though traditionally + // a FPDF_FORMFILLINFO interface. m_pFormfillinfo: Pointer; - //* Version 2. + // Version 2. m_isolate: Pointer; // Unused in v3, retain for compatibility. m_v8EmbedderSlot: DWORD; // Unused in v3, retain for compatibility. - //* Version 3. - //* Version 3 moves m_Isolate and m_v8EmbedderSlot to FPDF_LIBRARY_CONFIG. + // Version 3. + // Version 3 moves m_Isolate and m_v8EmbedderSlot to FPDF_LIBRARY_CONFIG. end; PIPDFJsPlatform = ^TIPDFJsPlatform; TIPDFJsPlatform = IPDF_JSPLATFORM; @@ -4370,21 +5410,17 @@ IPDF_JsPlatform = record FXCT_HBEAM = 4; FXCT_HAND = 5; -//* -//* Function signature for the callback function passed to the FFI_SetTimer -//* method. -//* Parameters: -//* idEvent - Identifier of the timer. -//* Return value: -//* None. -//* +// Function signature for the callback function passed to the FFI_SetTimer +// method. +// Parameters: +// idEvent - Identifier of the timer. +// Return value: +// None. type TFPDFTimerCallback = procedure(idEvent: Integer); cdecl; type - //* - //* Declares of a struct type to the local system time. - //* + // Declares of a struct type to the local system time. {$IFDEF MSWINDOWS} PFPDF_SYSTEMTIME = PSystemTime; FPDF_SYSTEMTIME = TSystemTime; @@ -4427,735 +5463,710 @@ FPDF_SYSTEMTIME = record type PFPDF_FORMFILLINFO = ^FPDF_FORMFILLINFO; FPDF_FORMFILLINFO = record - //* - //* Version number of the interface. Currently must be 1 (when PDFium is built - //* without the XFA module) or must be 2 (when built with the XFA module). - //* + // Version number of the interface. + // Version 1 contains stable interfaces. Version 2 has additional + // experimental interfaces. + // When PDFium is built without the XFA module, version can be 1 or 2. + // With version 1, only stable interfaces are called. With version 2, + // additional experimental interfaces are also called. + // When PDFium is built with the XFA module, version must be 2. + // All the XFA related interfaces are experimental. If PDFium is built with + // the XFA module and version 1 then none of the XFA related interfaces + // would be called. When PDFium is built with XFA module then the version + // must be 2. version: Integer; - //* Version 1. - - //* - //* Method: Release - //* Give the implementation a chance to release any resources after the - //* interface is no longer used. - //* Interface Version: - //* 1 - //* Implementation Required: - //* No - //* Comments: - //* Called by PDFium during the final cleanup process. - //* Parameters: - //* pThis - Pointer to the interface structure itself - //* Return Value: - //* None - //* + // Version 1. + + // Method: Release + // Give the implementation a chance to release any resources after the + // interface is no longer used. + // Interface Version: + // 1 + // Implementation Required: + // No + // Comments: + // Called by PDFium during the final cleanup process. + // Parameters: + // pThis - Pointer to the interface structure itself + // Return Value: + // None Release: procedure(pThis: PFPDF_FORMFILLINFO); cdecl; - //* - //* Method: FFI_Invalidate - //* Invalidate the client area within the specified rectangle. - //* Interface Version: - //* 1 - //* Implementation Required: - //* yes - //* Parameters: - //* pThis - Pointer to the interface structure itself. - //* page - Handle to the page. Returned by FPDF_LoadPage(). - //* left - Left position of the client area in PDF page - //* coordinates. - //* top - Top position of the client area in PDF page - //* coordinates. - //* right - Right position of the client area in PDF page - //* coordinates. - //* bottom - Bottom position of the client area in PDF page - //* coordinates. - //* Return Value: - //* None. - //* - //* Comments: - //* All positions are measured in PDF "user space". - //* Implementation should call FPDF_RenderPageBitmap() for repainting - //* the specified page area. - //* + // Method: FFI_Invalidate + // Invalidate the client area within the specified rectangle. + // Interface Version: + // 1 + // Implementation Required: + // yes + // Parameters: + // pThis - Pointer to the interface structure itself. + // page - Handle to the page. Returned by FPDF_LoadPage(). + // left - Left position of the client area in PDF page + // coordinates. + // top - Top position of the client area in PDF page + // coordinates. + // right - Right position of the client area in PDF page + // coordinates. + // bottom - Bottom position of the client area in PDF page + // coordinates. + // Return Value: + // None. + // Comments: + // All positions are measured in PDF "user space". + // Implementation should call FPDF_RenderPageBitmap() for repainting + // the specified page area. FFI_Invalidate: procedure(pThis: PFPDF_FORMFILLINFO; page: FPDF_PAGE; left, top, right, bottom: Double); cdecl; - //* - //* Method: FFI_OutputSelectedRect - //* When the user selects text in form fields with the mouse, this - //* callback function will be invoked with the selected areas. - //* - //* Interface Version: - //* 1 - //* Implementation Required: - //* No - //* Parameters: - //* pThis - Pointer to the interface structure itself. - //* page - Handle to the page. Returned by FPDF_LoadPage()/ - //* left - Left position of the client area in PDF page - //* coordinates. - //* top - Top position of the client area in PDF page - //* coordinates. - //* right - Right position of the client area in PDF page - //* coordinates. - //* bottom - Bottom position of the client area in PDF page - //* coordinates. - //* Return Value: - //* None. - //* - //* Comments: - //* This callback function is useful for implementing special text - //* selection effects. An implementation should first record the - //* returned rectangles, then draw them one by one during the next - //* painting period. Lastly, it should remove all the recorded - //* rectangles when finished painting. - //* + // Method: FFI_OutputSelectedRect + // When the user selects text in form fields with the mouse, this + // callback function will be invoked with the selected areas. + // Interface Version: + // 1 + // Implementation Required: + // No + // Parameters: + // pThis - Pointer to the interface structure itself. + // page - Handle to the page. Returned by FPDF_LoadPage()/ + // left - Left position of the client area in PDF page + // coordinates. + // top - Top position of the client area in PDF page + // coordinates. + // right - Right position of the client area in PDF page + // coordinates. + // bottom - Bottom position of the client area in PDF page + // coordinates. + // Return Value: + // None. + // Comments: + // This callback function is useful for implementing special text + // selection effects. An implementation should first record the + // returned rectangles, then draw them one by one during the next + // painting period. Lastly, it should remove all the recorded + // rectangles when finished painting. FFI_OutputSelectedRect: procedure(pThis: PFPDF_FORMFILLINFO; page: FPDF_PAGE; left, top, right, bottom: Double); cdecl; - //* - //* Method: FFI_SetCursor - //* Set the Cursor shape. - //* Interface Version: - //* 1 - //* Implementation Required: - //* yes - //* Parameters: - //* pThis - Pointer to the interface structure itself. - //* nCursorType - Cursor type, see Flags for Cursor type for details. - //* Return value: - //* None. - //* + // Method: FFI_SetCursor + // Set the Cursor shape. + // Interface Version: + // 1 + // Implementation Required: + // yes + // Parameters: + // pThis - Pointer to the interface structure itself. + // nCursorType - Cursor type, see Flags for Cursor type for details. + // Return value: + // None. FFI_SetCursor: procedure(pThis: PFPDF_FORMFILLINFO; nCursorType: Integer); cdecl; - //* - //* Method: FFI_SetTimer - //* This method installs a system timer. An interval value is specified, - //* and every time that interval elapses, the system must call into the - //* callback function with the timer ID as returned by this function. - //* Interface Version: - //* 1 - //* Implementation Required: - //* yes - //* Parameters: - //* pThis - Pointer to the interface structure itself. - //* uElapse - Specifies the time-out value, in milliseconds. - //* lpTimerFunc - A pointer to the callback function-TimerCallback. - //* Return value: - //* The timer identifier of the new timer if the function is successful. - //* An application passes this value to the FFI_KillTimer method to kill - //* the timer. Nonzero if it is successful; otherwise, it is zero. - //* + // Method: FFI_SetTimer + // This method installs a system timer. An interval value is specified, + // and every time that interval elapses, the system must call into the + // callback function with the timer ID as returned by this function. + // Interface Version: + // 1 + // Implementation Required: + // yes + // Parameters: + // pThis - Pointer to the interface structure itself. + // uElapse - Specifies the time-out value, in milliseconds. + // lpTimerFunc - A pointer to the callback function-TimerCallback. + // Return value: + // The timer identifier of the new timer if the function is successful. + // An application passes this value to the FFI_KillTimer method to kill + // the timer. Nonzero if it is successful; otherwise, it is zero. FFI_SetTimer: function(pThis: PFPDF_FORMFILLINFO; uElapse: Integer; lpTimerFunc: TFPDFTimerCallback): Integer; cdecl; - //* - //* Method: FFI_KillTimer - //* This method uninstalls a system timer, as set by an earlier call to - //* FFI_SetTimer. - //* Interface Version: - //* 1 - //* Implementation Required: - //* yes - //* Parameters: - //* pThis - Pointer to the interface structure itself. - //* nTimerID - The timer ID returned by FFI_SetTimer function. - //* Return value: - //* None. - //* - + // Method: FFI_KillTimer + // This method uninstalls a system timer, as set by an earlier call to + // FFI_SetTimer. + // Interface Version: + // 1 + // Implementation Required: + // yes + // Parameters: + // pThis - Pointer to the interface structure itself. + // nTimerID - The timer ID returned by FFI_SetTimer function. + // Return value: + // None. FFI_KillTimer: procedure(pThis: PFPDF_FORMFILLINFO; nTimerID: Integer); cdecl; - //* - //* Method: FFI_GetLocalTime - //* This method receives the current local time on the system. - //* Interface Version: - //* 1 - //* Implementation Required: - //* yes - //* Parameters: - //* pThis - Pointer to the interface structure itself. - //* Return value: - //* The local time. See FPDF_SYSTEMTIME above for details. - //* Note: Unused. - //* + // Method: FFI_GetLocalTime + // This method receives the current local time on the system. + // Interface Version: + // 1 + // Implementation Required: + // yes + // Parameters: + // pThis - Pointer to the interface structure itself. + // Return value: + // The local time. See FPDF_SYSTEMTIME above for details. + // Note: Unused. FFI_GetLocalTime: function(pThis: PFPDF_FORMFILLINFO): FPDF_SYSTEMTIME; cdecl; - //* - //* Method: FFI_OnChange - //* This method will be invoked to notify the implementation when the - //* value of any FormField on the document had been changed. - //* Interface Version: - //* 1 - //* Implementation Required: - //* no - //* Parameters: - //* pThis - Pointer to the interface structure itself. - //* Return value: - //* None. - //* + // Method: FFI_OnChange + // This method will be invoked to notify the implementation when the + // value of any FormField on the document had been changed. + // Interface Version: + // 1 + // Implementation Required: + // no + // Parameters: + // pThis - Pointer to the interface structure itself. + // Return value: + // None. FFI_OnChange: procedure(pThis: PFPDF_FORMFILLINFO); cdecl; - //* - //* Method: FFI_GetPage - //* This method receives the page handle associated with a specified - //* page index. - //* Interface Version: - //* 1 - //* Implementation Required: - //* yes - //* Parameters: - //* pThis - Pointer to the interface structure itself. - //* document - Handle to document. Returned by FPDF_LoadDocument(). - //* nPageIndex - Index number of the page. 0 for the first page. - //* Return value: - //* Handle to the page, as previously returned to the implementation by - //* FPDF_LoadPage(). - //* Comments: - //* The implementation is expected to keep track of the page handles it - //* receives from PDFium, and their mappings to page numbers. In some - //* cases, the document-level JavaScript action may refer to a page - //* which hadn't been loaded yet. To successfully run the Javascript - //* action, the implementation needs to load the page. - //* + // Method: FFI_GetPage + // This method receives the page handle associated with a specified + // page index. + // Interface Version: + // 1 + // Implementation Required: + // yes + // Parameters: + // pThis - Pointer to the interface structure itself. + // document - Handle to document. Returned by FPDF_LoadDocument(). + // nPageIndex - Index number of the page. 0 for the first page. + // Return value: + // Handle to the page, as previously returned to the implementation by + // FPDF_LoadPage(). + // Comments: + // The implementation is expected to keep track of the page handles it + // receives from PDFium, and their mappings to page numbers. In some + // cases, the document-level JavaScript action may refer to a page + // which hadn't been loaded yet. To successfully run the Javascript + // action, the implementation needs to load the page. FFI_GetPage: function(pThis: PFPDF_FORMFILLINFO; document: FPDF_DOCUMENT; nPageIndex: Integer): FPDF_PAGE; cdecl; - //* - //* Method: FFI_GetCurrentPage - //* This method receives the handle to the current page. - //* Interface Version: - //* 1 - //* Implementation Required: - //* yes - //* Parameters: - //* pThis - Pointer to the interface structure itself. - //* document - Handle to document. Returned by FPDF_LoadDocument(). - //* Return value: - //* Handle to the page. Returned by FPDF_LoadPage(). - //* Comments: - //* The implementation is expected to keep track of the current page, - //* e.g. the current page can be the one that is most visible on screen. - //* + // Method: FFI_GetCurrentPage + // This method receives the handle to the current page. + // Interface Version: + // 1 + // Implementation Required: + // Yes when V8 support is present, otherwise unused. + // Parameters: + // pThis - Pointer to the interface structure itself. + // document - Handle to document. Returned by FPDF_LoadDocument(). + // Return value: + // Handle to the page. Returned by FPDF_LoadPage(). + // Comments: + // PDFium doesn't keep keep track of the "current page" (e.g. the one + // that is most visible on screen), so it must ask the embedder for + // this information. FFI_GetCurrentPage: function(pThis: PFPDF_FORMFILLINFO; document: FPDF_DOCUMENT): FPDF_PAGE; cdecl; - //* - //* Method: FFI_GetRotation - //* This method receives currently rotation of the page view. - //* Interface Version: - //* 1 - //* Implementation Required: - //* yes - //* Parameters: - //* pThis - Pointer to the interface structure itself. - //* page - Handle to page, as returned by FPDF_LoadPage(). - //* Return value: - //* A number to indicate the page rotation in 90 degree increments - //* in a clockwise direction: - //* 0 - 0 degrees - //* 1 - 90 degrees - //* 2 - 180 degrees - //* 3 - 270 degrees - //* Note: Unused. - //* + // Method: FFI_GetRotation + // This method receives currently rotation of the page view. + // Interface Version: + // 1 + // Implementation Required: + // yes + // Parameters: + // pThis - Pointer to the interface structure itself. + // page - Handle to page, as returned by FPDF_LoadPage(). + // Return value: + // A number to indicate the page rotation in 90 degree increments + // in a clockwise direction: + // 0 - 0 degrees + // 1 - 90 degrees + // 2 - 180 degrees + // 3 - 270 degrees + // Note: Unused. FFI_GetRotation: function(pThis: PFPDF_FORMFILLINFO; page: FPDF_PAGE): Integer; cdecl; - //* - //* Method: FFI_ExecuteNamedAction - //* This method will execute a named action. - //* Interface Version: - //* 1 - //* Implementation Required: - //* yes - //* Parameters: - //* pThis - Pointer to the interface structure itself. - //* namedAction - A byte string which indicates the named action, - //* terminated by 0. - //* Return value: - //* None. - //* Comments: - //* See the named actions description of <> - //* for more details. - //* + // Method: FFI_ExecuteNamedAction + // This method will execute a named action. + // Interface Version: + // 1 + // Implementation Required: + // yes + // Parameters: + // pThis - Pointer to the interface structure itself. + // namedAction - A byte string which indicates the named action, + // terminated by 0. + // Return value: + // None. + // Comments: + // See ISO 32000-1:2008, section 12.6.4.11 for descriptions of the + // standard named actions, but note that a document may supply any + // name of its choosing. FFI_ExecuteNamedAction: procedure(pThis: PFPDF_FORMFILLINFO; namedAction: FPDF_BYTESTRING); cdecl; - //* - //* Method: FFI_SetTextFieldFocus - //* Called when a text field is getting or losing focus. - //* Interface Version: - //* 1 - //* Implementation Required: - //* no - //* Parameters: - //* pThis - Pointer to the interface structure itself. - //* value - The string value of the form field, in UTF-16LE - //* format. - //* valueLen - The length of the string value. This is the - //* number of characters, not bytes. - //* is_focus - True if the form field is getting focus, false - //* if the form field is losing focus. - //* Return value: - //* None. - //* Comments: - //* Only supports text fields and combobox fields. - //* + // Method: FFI_SetTextFieldFocus + // Called when a text field is getting or losing focus. + // Interface Version: + // 1 + // Implementation Required: + // no + // Parameters: + // pThis - Pointer to the interface structure itself. + // value - The string value of the form field, in UTF-16LE + // format. + // valueLen - The length of the string value. This is the + // number of characters, not bytes. + // is_focus - True if the form field is getting focus, false + // if the form field is losing focus. + // Return value: + // None. + // Comments: + // Only supports text fields and combobox fields. FFI_SetTextFieldFocus: procedure(pThis: PFPDF_FORMFILLINFO; value: FPDF_WIDESTRING; valueLen: FPDF_DWORD; is_focus: FPDF_BOOL); cdecl; - //* - //* Method: FFI_DoURIAction - //* Ask the implementation to navigate to a uniform resource identifier. - //* Interface Version: - //* 1 - //* Implementation Required: - //* No - //* Parameters: - //* pThis - Pointer to the interface structure itself. - //* bsURI - A byte string which indicates the uniform - //* resource identifier, terminated by 0. - //* Return value: - //* None. - //* Comments: - //* See the URI actions description of <> - //* for more details. - //* + // Method: FFI_DoURIAction + // Ask the implementation to navigate to a uniform resource identifier. + // Interface Version: + // 1 + // Implementation Required: + // No + // Parameters: + // pThis - Pointer to the interface structure itself. + // bsURI - A byte string which indicates the uniform + // resource identifier, terminated by 0. + // Return value: + // None. + // Comments: + // If the embedder is version 2 or higher and have implementation for + // FFI_DoURIActionWithKeyboardModifier, then + // FFI_DoURIActionWithKeyboardModifier takes precedence over + // FFI_DoURIAction. + // See the URI actions description of <> + // for more details. FFI_DoURIAction: procedure(pThis: PFPDF_FORMFILLINFO; bsURI: FPDF_WIDESTRING); cdecl; - //* - //* Method: FFI_DoGoToAction - //* This action changes the view to a specified destination. - //* Interface Version: - //* 1 - //* Implementation Required: - //* No - //* Parameters: - //* pThis - Pointer to the interface structure itself. - //* nPageIndex - The index of the PDF page. - //* zoomMode - The zoom mode for viewing page. See below. - //* fPosArray - The float array which carries the position info. - //* sizeofArray - The size of float array. - //* PDFZoom values: - //* - XYZ = 1 - //* - FITPAGE = 2 - //* - FITHORZ = 3 - //* - FITVERT = 4 - //* - FITRECT = 5 - //* - FITBBOX = 6 - //* - FITBHORZ = 7 - //* - FITBVERT = 8 - //* Return value: - //* None. - //* Comments: - //* See the Destinations description of <> - //* in 8.2.1 for more details. - //* + // Method: FFI_DoGoToAction + // This action changes the view to a specified destination. + // Interface Version: + // 1 + // Implementation Required: + // No + // Parameters: + // pThis - Pointer to the interface structure itself. + // nPageIndex - The index of the PDF page. + // zoomMode - The zoom mode for viewing page. See below. + // fPosArray - The float array which carries the position info. + // sizeofArray - The size of float array. + // PDFZoom values: + // - XYZ = 1 + // - FITPAGE = 2 + // - FITHORZ = 3 + // - FITVERT = 4 + // - FITRECT = 5 + // - FITBBOX = 6 + // - FITBHORZ = 7 + // - FITBVERT = 8 + // Return value: + // None. + // Comments: + // See the Destinations description of <> + // in 8.2.1 for more details. FFI_DoGoToAction: procedure(pThis: PFPDF_FORMFILLINFO; nPageIndex, zoomMode: Integer; fPosArray: PSingle; sizeofArray: Integer); cdecl; - //* - //* Pointer to IPDF_JSPLATFORM interface. - //* Unused if PDFium is built without V8 support. Otherwise, if NULL, then - //* JavaScript will be prevented from executing while rendering the document. - //* + // Pointer to IPDF_JSPLATFORM interface. + // Unused if PDFium is built without V8 support. Otherwise, if NULL, then + // JavaScript will be prevented from executing while rendering the document. m_pJsPlatform: PIPDF_JSPLATFORM; - {$IFDEF PDF_ENABLE_XFA} - //* Version 2 - Experimental. - //* - //* Whether the XFA module is disabled when built with the XFA module. - //* Interface Version: - //* Ignored if |version| < 2. - //* + // Version 2 - Experimental. + + // Whether the XFA module is disabled when built with the XFA module. + // Interface Version: + // Ignored if |version| < 2. xfa_disabled: FPDF_BOOL; - //* - //* Method: FFI_DisplayCaret - //* This method will show the caret at specified position. - //* Interface Version: - //* Ignored if |version| < 2. - //* Implementation Required: - //* Required for XFA, otherwise set to NULL. - //* Parameters: - //* pThis - Pointer to the interface structure itself. - //* page - Handle to page. Returned by FPDF_LoadPage(). - //* left - Left position of the client area in PDF page - //* coordinates. - //* top - Top position of the client area in PDF page - //* coordinates. - //* right - Right position of the client area in PDF page - //* coordinates. - //* bottom - Bottom position of the client area in PDF page - //* coordinates. - //* Return value: - //* None. - //* + // Method: FFI_DisplayCaret + // This method will show the caret at specified position. + // Interface Version: + // Ignored if |version| < 2. + // Implementation Required: + // Required for XFA, otherwise set to NULL. + // Parameters: + // pThis - Pointer to the interface structure itself. + // page - Handle to page. Returned by FPDF_LoadPage(). + // left - Left position of the client area in PDF page + // coordinates. + // top - Top position of the client area in PDF page + // coordinates. + // right - Right position of the client area in PDF page + // coordinates. + // bottom - Bottom position of the client area in PDF page + // coordinates. + // Return value: + // None. FFI_DisplayCaret: procedure(pThis: PFPDF_FORMFILLINFO; page: FPDF_PAGE; bVisible: FPDF_BOOL; left, top, right, bottom: Double); cdecl; - //* - //* Method: FFI_GetCurrentPageIndex - //* This method will get the current page index. - //* Interface Version: - //* Ignored if |version| < 2. - //* Implementation Required: - //* Required for XFA, otherwise set to NULL. - //* Parameters: - //* pThis - Pointer to the interface structure itself. - //* document - Handle to document from FPDF_LoadDocument(). - //* Return value: - //* The index of current page. - //* + // Method: FFI_GetCurrentPageIndex + // This method will get the current page index. + // Interface Version: + // Ignored if |version| < 2. + // Implementation Required: + // Required for XFA, otherwise set to NULL. + // Parameters: + // pThis - Pointer to the interface structure itself. + // document - Handle to document from FPDF_LoadDocument(). + // Return value: + // The index of current page. FFI_GetCurrentPageIndex: function(pThis: PFPDF_FORMFILLINFO; document: FPDF_DOCUMENT): Integer; cdecl; - //* - //* Method: FFI_SetCurrentPage - //* This method will set the current page. - //* Interface Version: - //* Ignored if |version| < 2. - //* Implementation Required: - //* Required for XFA, otherwise set to NULL. - //* Parameters: - //* pThis - Pointer to the interface structure itself. - //* document - Handle to document from FPDF_LoadDocument(). - //* iCurPage - The index of the PDF page. - //* Return value: - //* None. - //* + // Method: FFI_SetCurrentPage + // This method will set the current page. + // Interface Version: + // Ignored if |version| < 2. + // Implementation Required: + // Required for XFA, otherwise set to NULL. + // Parameters: + // pThis - Pointer to the interface structure itself. + // document - Handle to document from FPDF_LoadDocument(). + // iCurPage - The index of the PDF page. + // Return value: + // None. FFI_SetCurrentPage: procedure(pThis: PFPDF_FORMFILLINFO; document: FPDF_DOCUMENT; iCurPage: Integer); cdecl; - //* - //* Method: FFI_GotoURL - //* This method will navigate to the specified URL. - //* Interface Version: - //* Ignored if |version| < 2. - //* Implementation Required: - //* Required for XFA, otherwise set to NULL. - //* Parameters: - //* pThis - Pointer to the interface structure itself. - //* document - Handle to document from FPDF_LoadDocument(). - //* wsURL - The string value of the URL, in UTF-16LE format. - //* Return value: - //* None. - //* + // Method: FFI_GotoURL + // This method will navigate to the specified URL. + // Interface Version: + // Ignored if |version| < 2. + // Implementation Required: + // Required for XFA, otherwise set to NULL. + // Parameters: + // pThis - Pointer to the interface structure itself. + // document - Handle to document from FPDF_LoadDocument(). + // wsURL - The string value of the URL, in UTF-16LE format. + // Return value: + // None. FFI_GotoURL: procedure(pThis: PFPDF_FORMFILLINFO; document: FPDF_DOCUMENT; wsURL: FPDF_WIDESTRING); cdecl; - //* - //* Method: FFI_GetPageViewRect - //* This method will get the current page view rectangle. - //* Interface Version: - //* Ignored if |version| < 2. - //* Implementation Required: - //* Required for XFA, otherwise set to NULL. - //* Parameters: - //* pThis - Pointer to the interface structure itself. - //* page - Handle to page. Returned by FPDF_LoadPage(). - //* left - The pointer to receive left position of the page - //* view area in PDF page coordinates. - //* top - The pointer to receive top position of the page - //* view area in PDF page coordinates. - //* right - The pointer to receive right position of the - //* page view area in PDF page coordinates. - //* bottom - The pointer to receive bottom position of the - //* page view area in PDF page coordinates. - //* Return value: - //* None. - //* + // Method: FFI_GetPageViewRect + // This method will get the current page view rectangle. + // Interface Version: + // Ignored if |version| < 2. + // Implementation Required: + // Required for XFA, otherwise set to NULL. + // Parameters: + // pThis - Pointer to the interface structure itself. + // page - Handle to page. Returned by FPDF_LoadPage(). + // left - The pointer to receive left position of the page + // view area in PDF page coordinates. + // top - The pointer to receive top position of the page + // view area in PDF page coordinates. + // right - The pointer to receive right position of the + // page view area in PDF page coordinates. + // bottom - The pointer to receive bottom position of the + // page view area in PDF page coordinates. + // Return value: + // None. FFI_GetPageViewRect: procedure(pThis: PFPDF_FORMFILLINFO; page: FPDF_PAGE; var left, top, right, bottom: Double); cdecl; - //* - //* Method: FFI_PageEvent - //* This method fires when pages have been added to or deleted from - //* the XFA document. - //* Interface Version: - //* Ignored if |version| < 2. - //* Implementation Required: - //* Required for XFA, otherwise set to NULL. - //* Parameters: - //* pThis - Pointer to the interface structure itself. - //* page_count - The number of pages to be added or deleted. - //* event_type - See FXFA_PAGEVIEWEVENT_* above. - //* Return value: - //* None. - //* Comments: - //* The pages to be added or deleted always start from the last page - //* of document. This means that if parameter page_count is 2 and - //* event type is FXFA_PAGEVIEWEVENT_POSTADDED, 2 new pages have been - //* appended to the tail of document; If page_count is 2 and - //* event type is FXFA_PAGEVIEWEVENT_POSTREMOVED, the last 2 pages - //* have been deleted. - //* + // Method: FFI_PageEvent + // This method fires when pages have been added to or deleted from + // the XFA document. + // Interface Version: + // Ignored if |version| < 2. + // Implementation Required: + // Required for XFA, otherwise set to NULL. + // Parameters: + // pThis - Pointer to the interface structure itself. + // page_count - The number of pages to be added or deleted. + // event_type - See FXFA_PAGEVIEWEVENT_* above. + // Return value: + // None. + // Comments: + // The pages to be added or deleted always start from the last page + // of document. This means that if parameter page_count is 2 and + // event type is FXFA_PAGEVIEWEVENT_POSTADDED, 2 new pages have been + // appended to the tail of document; If page_count is 2 and + // event type is FXFA_PAGEVIEWEVENT_POSTREMOVED, the last 2 pages + // have been deleted. FFI_PageEvent: procedure(pThis: PFPDF_FORMFILLINFO; page_count: Integer; event_type: FPDF_DWORD); cdecl; - //* - //* Method: FFI_PopupMenu - //* This method will track the right context menu for XFA fields. - //* Interface Version: - //* Ignored if |version| < 2. - //* Implementation Required: - //* Required for XFA, otherwise set to NULL. - //* Parameters: - //* pThis - Pointer to the interface structure itself. - //* page - Handle to page. Returned by FPDF_LoadPage(). - //* hWidget - Always null, exists for compatibility. - //* menuFlag - The menu flags. Please refer to macro definition - //* of FXFA_MENU_XXX and this can be one or a - //* combination of these macros. - //* x - X position of the client area in PDF page - //* coordinates. - //* y - Y position of the client area in PDF page - //* coordinates. - //* Return value: - //* TRUE indicates success; otherwise false. - //* + // Method: FFI_PopupMenu + // This method will track the right context menu for XFA fields. + // Interface Version: + // Ignored if |version| < 2. + // Implementation Required: + // Required for XFA, otherwise set to NULL. + // Parameters: + // pThis - Pointer to the interface structure itself. + // page - Handle to page. Returned by FPDF_LoadPage(). + // hWidget - Always null, exists for compatibility. + // menuFlag - The menu flags. Please refer to macro definition + // of FXFA_MENU_XXX and this can be one or a + // combination of these macros. + // x - X position of the client area in PDF page + // coordinates. + // y - Y position of the client area in PDF page + // coordinates. + // Return value: + // TRUE indicates success; otherwise false. FFI_PopupMenu: function(pThis: PFPDF_FORMFILLINFO; page: FPDF_PAGE; hWidget: FPDF_WIDGET; menuFlag: Integer; x, y: Single): FPDF_BOOL; cdecl; - //* - //* Method: FFI_OpenFile - //* This method will open the specified file with the specified mode. - //* Interface Version: - //* Ignored if |version| < 2. - //* Implementation Required: - //* Required for XFA, otherwise set to NULL. - //* Parameters: - //* pThis - Pointer to the interface structure itself. - //* fileFlag - The file flag. Please refer to macro definition - //* of FXFA_SAVEAS_XXX and use one of these macros. - //* wsURL - The string value of the file URL, in UTF-16LE - //* format. - //* mode - The mode for open file, e.g. "rb" or "wb". - //* Return value: - //* The handle to FPDF_FILEHANDLER. - //** + // Method: FFI_OpenFile + // This method will open the specified file with the specified mode. + // Interface Version: + // Ignored if |version| < 2. + // Implementation Required: + // Required for XFA, otherwise set to NULL. + // Parameters: + // pThis - Pointer to the interface structure itself. + // fileFlag - The file flag. Please refer to macro definition + // of FXFA_SAVEAS_XXX and use one of these macros. + // wsURL - The string value of the file URL, in UTF-16LE + // format. + // mode - The mode for open file, e.g. "rb" or "wb". + // Return value: + // The handle to FPDF_FILEHANDLER. FFI_OpenFile: function(pThis: PFPDF_FORMFILLINFO; fileFlag: Integer; wsURL: FPDF_WIDESTRING; mode: PAnsiChar): PFPDF_FILEHANDLER; cdecl; - //* - //* Method: FFI_EmailTo - //* This method will email the specified file stream to the specified - //* contact. - //* Interface Version: - //* Ignored if |version| < 2. - //* Implementation Required: - //* Required for XFA, otherwise set to NULL. - //* Parameters: - //* pThis - Pointer to the interface structure itself. - //* pFileHandler - Handle to the FPDF_FILEHANDLER. - //* pTo - A semicolon-delimited list of recipients for the - //* message,in UTF-16LE format. - //* pSubject - The subject of the message,in UTF-16LE format. - //* pCC - A semicolon-delimited list of CC recipients for - //* the message,in UTF-16LE format. - //* pBcc - A semicolon-delimited list of BCC recipients for - //* the message,in UTF-16LE format. - //* pMsg - Pointer to the data buffer to be sent.Can be - //* NULL,in UTF-16LE format. - //* Return value: - //* None. - //* + // Method: FFI_EmailTo + // This method will email the specified file stream to the specified + // contact. + // Interface Version: + // Ignored if |version| < 2. + // Implementation Required: + // Required for XFA, otherwise set to NULL. + // Parameters: + // pThis - Pointer to the interface structure itself. + // pFileHandler - Handle to the FPDF_FILEHANDLER. + // pTo - A semicolon-delimited list of recipients for the + // message,in UTF-16LE format. + // pSubject - The subject of the message,in UTF-16LE format. + // pCC - A semicolon-delimited list of CC recipients for + // the message,in UTF-16LE format. + // pBcc - A semicolon-delimited list of BCC recipients for + // the message,in UTF-16LE format. + // pMsg - Pointer to the data buffer to be sent.Can be + // NULL,in UTF-16LE format. + // Return value: + // None. FFI_EmailTo: procedure(pThis: PFPDF_FORMFILLINFO; fileHandler: PFPDF_FILEHANDLER; pTo, pSubject, pCC, pBcc, pMsg: FPDF_WIDESTRING); cdecl; - //* - //* Method: FFI_UploadTo - //* This method will upload the specified file stream to the - //* specified URL. - //* Interface Version: - //* Ignored if |version| < 2. - //* Implementation Required: - //* Required for XFA, otherwise set to NULL. - //* Parameters: - //* pThis - Pointer to the interface structure itself. - //* pFileHandler - Handle to the FPDF_FILEHANDLER. - //* fileFlag - The file flag. Please refer to macro definition - //* of FXFA_SAVEAS_XXX and use one of these macros. - //* uploadTo - Pointer to the URL path, in UTF-16LE format. - //* Return value: - //* None. - //* + // Method: FFI_UploadTo + // This method will upload the specified file stream to the + // specified URL. + // Interface Version: + // Ignored if |version| < 2. + // Implementation Required: + // Required for XFA, otherwise set to NULL. + // Parameters: + // pThis - Pointer to the interface structure itself. + // pFileHandler - Handle to the FPDF_FILEHANDLER. + // fileFlag - The file flag. Please refer to macro definition + // of FXFA_SAVEAS_XXX and use one of these macros. + // uploadTo - Pointer to the URL path, in UTF-16LE format. + // Return value: + // None. FFI_UploadTo: procedure(pThis: PFPDF_FORMFILLINFO; fileHandler: PFPDF_FILEHANDLER; fileFlag: Integer; uploadTo: FPDF_WIDESTRING); cdecl; - //* - //* Method: FFI_GetPlatform - //* This method will get the current platform. - //* Interface Version: - //* Ignored if |version| < 2. - //* Implementation Required: - //* Required for XFA, otherwise set to NULL. - //* Parameters: - //* pThis - Pointer to the interface structure itself. - //* platform - Pointer to the data buffer to receive the - //* platform,in UTF-16LE format. Can be NULL. - //* length - The length of the buffer in bytes. Can be - //* 0 to query the required size. - //* Return value: - //* The length of the buffer, number of bytes. - //* + // Method: FFI_GetPlatform + // This method will get the current platform. + // Interface Version: + // Ignored if |version| < 2. + // Implementation Required: + // Required for XFA, otherwise set to NULL. + // Parameters: + // pThis - Pointer to the interface structure itself. + // platform - Pointer to the data buffer to receive the + // platform,in UTF-16LE format. Can be NULL. + // length - The length of the buffer in bytes. Can be + // 0 to query the required size. + // Return value: + // The length of the buffer, number of bytes. FFI_GetPlatform: function(pThis: PFPDF_FORMFILLINFO; platform_: Pointer; length: Integer): Integer; cdecl; - //* - //* Method: FFI_GetLanguage - //* This method will get the current language. - //* Interface Version: - //* Ignored if |version| < 2. - //* Implementation Required: - //* Required for XFA, otherwise set to NULL. - //* Parameters: - //* pThis - Pointer to the interface structure itself. - //* language - Pointer to the data buffer to receive the - //* current language. Can be NULL. - //* length - The length of the buffer in bytes. Can be - //* 0 to query the required size. - //* Return value: - //* The length of the buffer, number of bytes. - //* + // Method: FFI_GetLanguage + // This method will get the current language. + // Interface Version: + // Ignored if |version| < 2. + // Implementation Required: + // Required for XFA, otherwise set to NULL. + // Parameters: + // pThis - Pointer to the interface structure itself. + // language - Pointer to the data buffer to receive the + // current language. Can be NULL. + // length - The length of the buffer in bytes. Can be + // 0 to query the required size. + // Return value: + // The length of the buffer, number of bytes. FFI_GetLanguage: function(pThis: PFPDF_FORMFILLINFO; language: Pointer; length: Integer): Integer; cdecl; - //* - //* Method: FFI_DownloadFromURL - //* This method will download the specified file from the URL. - //* Interface Version: - //* Ignored if |version| < 2. - //* Implementation Required: - //* Required for XFA, otherwise set to NULL. - //* Parameters: - //* pThis - Pointer to the interface structure itself. - //* URL - The string value of the file URL, in UTF-16LE - //* format. - //* Return value: - //* The handle to FPDF_FILEHANDLER. - //* + // Method: FFI_DownloadFromURL + // This method will download the specified file from the URL. + // Interface Version: + // Ignored if |version| < 2. + // Implementation Required: + // Required for XFA, otherwise set to NULL. + // Parameters: + // pThis - Pointer to the interface structure itself. + // URL - The string value of the file URL, in UTF-16LE + // format. + // Return value: + // The handle to FPDF_FILEHANDLER. FFI_DownloadFromURL: function(pThis: PFPDF_FORMFILLINFO; URL: FPDF_WIDESTRING): PFPDF_FILEHANDLER; cdecl; - //* - //* Method: FFI_PostRequestURL - //* This method will post the request to the server URL. - //* Interface Version: - //* Ignored if |version| < 2. - //* Implementation Required: - //* Required for XFA, otherwise set to NULL. - //* Parameters: - //* pThis - Pointer to the interface structure itself. - //* wsURL - The string value of the server URL, in UTF-16LE - //* format. - //* wsData - The post data,in UTF-16LE format. - //* wsContentType - The content type of the request data, in - //* UTF-16LE format. - //* wsEncode - The encode type, in UTF-16LE format. - //* wsHeader - The request header,in UTF-16LE format. - //* response - Pointer to the FPDF_BSTR to receive the response - //* data from the server, in UTF-16LE format. - //* Return value: - //* TRUE indicates success, otherwise FALSE. - //* + // Method: FFI_PostRequestURL + // This method will post the request to the server URL. + // Interface Version: + // Ignored if |version| < 2. + // Implementation Required: + // Required for XFA, otherwise set to NULL. + // Parameters: + // pThis - Pointer to the interface structure itself. + // wsURL - The string value of the server URL, in UTF-16LE + // format. + // wsData - The post data,in UTF-16LE format. + // wsContentType - The content type of the request data, in + // UTF-16LE format. + // wsEncode - The encode type, in UTF-16LE format. + // wsHeader - The request header,in UTF-16LE format. + // response - Pointer to the FPDF_BSTR to receive the response + // data from the server, in UTF-16LE format. + // Return value: + // TRUE indicates success, otherwise FALSE. FFI_PostRequestURL: function(pThis: PFPDF_FORMFILLINFO; wsURL, wsData, wsContentType, wsEncode, wsHeader: FPDF_WIDESTRING; respone: PFPDF_BSTR): FPDF_BOOL; cdecl; - //* - //* Method: FFI_PutRequestURL - //* This method will put the request to the server URL. - //* Interface Version: - //* Ignored if |version| < 2. - //* Implementation Required: - //* Required for XFA, otherwise set to NULL. - //* Parameters: - //* pThis - Pointer to the interface structure itself. - //* wsURL - The string value of the server URL, in UTF-16LE - //* format. - //* wsData - The put data, in UTF-16LE format. - //* wsEncode - The encode type, in UTR-16LE format. - //* Return value: - //* TRUE indicates success, otherwise FALSE. - //* + // Method: FFI_PutRequestURL + // This method will put the request to the server URL. + // Interface Version: + // Ignored if |version| < 2. + // Implementation Required: + // Required for XFA, otherwise set to NULL. + // Parameters: + // pThis - Pointer to the interface structure itself. + // wsURL - The string value of the server URL, in UTF-16LE + // format. + // wsData - The put data, in UTF-16LE format. + // wsEncode - The encode type, in UTR-16LE format. + // Return value: + // TRUE indicates success, otherwise FALSE. FFI_PutRequestURL: function(pThis: PFPDF_FORMFILLINFO; wsURL, wsData, wsEncode: FPDF_WIDESTRING): FPDF_BOOL; cdecl; - {$ENDIF PDF_ENABLE_XFA} + + // Method: FFI_OnFocusChange + // Called when the focused annotation is updated. + // Interface Version: + // Ignored if |version| < 2. + // Implementation Required: + // No + // Parameters: + // param - Pointer to the interface structure itself. + // annot - The focused annotation. + // page_index - Index number of the page which contains the + // focused annotation. 0 for the first page. + // Return value: + // None. + // Comments: + // This callback function is useful for implementing any view based + // action such as scrolling the annotation rect into view. The + // embedder should not copy and store the annot as its scope is + // limited to this call only. + FFI_OnFocusChange: procedure(param: PFPDF_FORMFILLINFO; annot: FPDF_ANNOTATION; page_index: Integer); cdecl; + + // Method: FFI_DoURIActionWithKeyboardModifier + // Ask the implementation to navigate to a uniform resource identifier + // with the specified modifiers. + // Interface Version: + // Ignored if |version| < 2. + // Implementation Required: + // No + // Parameters: + // param - Pointer to the interface structure itself. + // uri - A byte string which indicates the uniform + // resource identifier, terminated by 0. + // modifiers - Keyboard modifier that indicates which of + // the virtual keys are down, if any. + // Return value: + // None. + // Comments: + // If the embedder who is version 2 and does not implement this API, + // then a call will be redirected to FFI_DoURIAction. + // See the URI actions description of <> + // for more details. + FFI_DoURIActionWithKeyboardModifier: procedure(param: PFPDF_FORMFILLINFO; uri: FPDF_BYTESTRING; modifiers: Integer); cdecl; end; PFPDFFormFillInfo = ^TFPDFFormFillInfo; TFPDFFormFillInfo = FPDF_FORMFILLINFO; - -//* -//* Function: FPDFDOC_InitFormFillEnvironment -//* Initialize form fill environment. -//* Parameters: -//* document - Handle to document from FPDF_LoadDocument(). -//* pFormFillInfo - Pointer to a FPDF_FORMFILLINFO structure. -//* Return Value: -//* Handle to the form fill module, or NULL on failure. -//* Comments: -//* This function should be called before any form fill operation. -//* +// Function: FPDFDOC_InitFormFillEnvironment +// Initialize form fill environment. +// Parameters: +// document - Handle to document from FPDF_LoadDocument(). +// formInfo - Pointer to a FPDF_FORMFILLINFO structure. +// Return Value: +// Handle to the form fill module, or NULL on failure. +// Comments: +// This function should be called before any form fill operation. +// The FPDF_FORMFILLINFO passed in via |formInfo| must remain valid until +// the returned FPDF_FORMHANDLE is closed. var FPDFDOC_InitFormFillEnvironment: function(document: FPDF_DOCUMENT; formInfo: PFPDF_FORMFILLINFO): FPDF_FORMHANDLE; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//* -//* Function: FPDFDOC_ExitFormFillEnvironment -//* Take ownership of |hHandle| and exit form fill environment. -//* Parameters: -//* hHandle - Handle to the form fill module, as returned by -//* FPDFDOC_InitFormFillEnvironment(). -//* Return Value: -//* None. -//* Comments: -//* This function is a no-op when |hHandle| is null. -//* +// Function: FPDFDOC_ExitFormFillEnvironment +// Take ownership of |hHandle| and exit form fill environment. +// Parameters: +// hHandle - Handle to the form fill module, as returned by +// FPDFDOC_InitFormFillEnvironment(). +// Return Value: +// None. +// Comments: +// This function is a no-op when |hHandle| is null. var FPDFDOC_ExitFormFillEnvironment: procedure(hHandle: FPDF_FORMHANDLE); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//* -//* Function: FORM_OnAfterLoadPage -//* This method is required for implementing all the form related -//* functions. Should be invoked after user successfully loaded a -//* PDF page, and FPDFDOC_InitFormFillEnvironment() has been invoked. -//* Parameters: -//* hHandle - Handle to the form fill module, as eturned by -//* FPDFDOC_InitFormFillEnvironment(). -//* Return Value: -//* None. -//* +// Function: FORM_OnAfterLoadPage +// This method is required for implementing all the form related +// functions. Should be invoked after user successfully loaded a +// PDF page, and FPDFDOC_InitFormFillEnvironment() has been invoked. +// Parameters: +// hHandle - Handle to the form fill module, as returned by +// FPDFDOC_InitFormFillEnvironment(). +// Return Value: +// None. var FORM_OnAfterLoadPage: procedure(page: FPDF_PAGE; hHandle: FPDF_FORMHANDLE); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//* -//* Function: FORM_OnBeforeClosePage -//* This method is required for implementing all the form related -//* functions. Should be invoked before user closes the PDF page. -//* Parameters: -//* page - Handle to the page, as returned by FPDF_LoadPage(). -//* hHandle - Handle to the form fill module, as returned by -//* FPDFDOC_InitFormFillEnvironment(). -//* Return Value: -//* None. -//* +// Function: FORM_OnBeforeClosePage +// This method is required for implementing all the form related +// functions. Should be invoked before user closes the PDF page. +// Parameters: +// page - Handle to the page, as returned by FPDF_LoadPage(). +// hHandle - Handle to the form fill module, as returned by +// FPDFDOC_InitFormFillEnvironment(). +// Return Value: +// None. var FORM_OnBeforeClosePage: procedure(page: FPDF_PAGE; hHandle: FPDF_FORMHANDLE); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//* -//* Function: FORM_DoDocumentJSAction -//* This method is required for performing document-level JavaScript -//* actions. It should be invoked after the PDF document has been loaded. -//* Parameters: -//* hHandle - Handle to the form fill module, as returned by -//* FPDFDOC_InitFormFillEnvironment(). -//* Return Value: -//* None. -//* Comments: -//* If there is document-level JavaScript action embedded in the -//* document, this method will execute the JavaScript action. Otherwise, -//* the method will do nothing. -//* +// Function: FORM_DoDocumentJSAction +// This method is required for performing document-level JavaScript +// actions. It should be invoked after the PDF document has been loaded. +// Parameters: +// hHandle - Handle to the form fill module, as returned by +// FPDFDOC_InitFormFillEnvironment(). +// Return Value: +// None. +// Comments: +// If there is document-level JavaScript action embedded in the +// document, this method will execute the JavaScript action. Otherwise, +// the method will do nothing. var FORM_DoDocumentJSAction: procedure(hHandle: FPDF_FORMHANDLE); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//* -//* Function: FORM_DoDocumentOpenAction -//* This method is required for performing open-action when the document -//* is opened. -//* Parameters: -//* hHandle - Handle to the form fill module, as returned by -//* FPDFDOC_InitFormFillEnvironment(). -//* Return Value: -//* None. -//* Comments: -//* This method will do nothing if there are no open-actions embedded -//* in the document. -//* +// Function: FORM_DoDocumentOpenAction +// This method is required for performing open-action when the document +// is opened. +// Parameters: +// hHandle - Handle to the form fill module, as returned by +// FPDFDOC_InitFormFillEnvironment(). +// Return Value: +// None. +// Comments: +// This method will do nothing if there are no open-actions embedded +// in the document. var FORM_DoDocumentOpenAction: procedure(hHandle: FPDF_FORMHANDLE); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; @@ -5172,21 +6183,19 @@ FPDF_FORMFILLINFO = record FPDFDOC_AACTION_WP = $13; FPDFDOC_AACTION_DP = $14; -//* -//* Function: FORM_DoDocumentAAction -//* This method is required for performing the document's -//* additional-action. -//* Parameters: -//* hHandle - Handle to the form fill module. Returned by -//* FPDFDOC_InitFormFillEnvironment. -//* aaType - The type of the additional-actions which defined -//* above. -//* Return Value: -//* None. -//* Comments: -//* This method will do nothing if there is no document -//* additional-action corresponding to the specified |aaType|. -//* +// Function: FORM_DoDocumentAAction +// This method is required for performing the document's +// additional-action. +// Parameters: +// hHandle - Handle to the form fill module. Returned by +// FPDFDOC_InitFormFillEnvironment. +// aaType - The type of the additional-actions which defined +// above. +// Return Value: +// None. +// Comments: +// This method will do nothing if there is no document +// additional-action corresponding to the specified |aaType|. var FORM_DoDocumentAAction: procedure(hHandle: FPDF_FORMHANDLE; aaType: Integer); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; @@ -5197,320 +6206,385 @@ FPDF_FORMFILLINFO = record FPDFPAGE_AACTION_OPEN = 0; FPDFPAGE_AACTION_CLOSE = 1; -//* -//* Function: FORM_DoPageAAction -//* This method is required for performing the page object's -//* additional-action when opened or closed. -//* Parameters: -//* page - Handle to the page, as returned by FPDF_LoadPage(). -//* hHandle - Handle to the form fill module, as returned by -//* FPDFDOC_InitFormFillEnvironment(). -//* aaType - The type of the page object's additional-actions -//* which defined above. -//* Return Value: -//* None. -//* Comments: -//* This method will do nothing if no additional-action corresponding -//* to the specified |aaType| exists. -//* +// Function: FORM_DoPageAAction +// This method is required for performing the page object's +// additional-action when opened or closed. +// Parameters: +// page - Handle to the page, as returned by FPDF_LoadPage(). +// hHandle - Handle to the form fill module, as returned by +// FPDFDOC_InitFormFillEnvironment(). +// aaType - The type of the page object's additional-actions +// which defined above. +// Return Value: +// None. +// Comments: +// This method will do nothing if no additional-action corresponding +// to the specified |aaType| exists. var FORM_DoPageAAction: procedure(page: FPDF_PAGE; hHandle: FPDF_FORMHANDLE; aaType: Integer); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//* -//* Function: FORM_OnMouseMove -//* Call this member function when the mouse cursor moves. -//* Parameters: -//* hHandle - Handle to the form fill module, as returned by -//* FPDFDOC_InitFormFillEnvironment(). -//* page - Handle to the page, as returned by FPDF_LoadPage(). -//* modifier - Indicates whether various virtual keys are down. -//* page_x - Specifies the x-coordinate of the cursor in PDF user -//* space. -//* page_y - Specifies the y-coordinate of the cursor in PDF user -//* space. -//* Return Value: -//* True indicates success; otherwise false. -//* +// Function: FORM_OnMouseMove +// Call this member function when the mouse cursor moves. +// Parameters: +// hHandle - Handle to the form fill module, as returned by +// FPDFDOC_InitFormFillEnvironment(). +// page - Handle to the page, as returned by FPDF_LoadPage(). +// modifier - Indicates whether various virtual keys are down. +// page_x - Specifies the x-coordinate of the cursor in PDF user +// space. +// page_y - Specifies the y-coordinate of the cursor in PDF user +// space. +// Return Value: +// True indicates success; otherwise false. var FORM_OnMouseMove: function(hHandle: FPDF_FORMHANDLE; page: FPDF_PAGE; modifier: Integer; page_x, page_y: Double): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//* -//* Function: FORM_OnFocus -//* This function focuses the form annotation at a given point. If the -//* annotation at the point already has focus, nothing happens. If there -//* is no annotation at the point, removes form focus. -//* Parameters: -//* hHandle - Handle to the form fill module, as returned by -//* FPDFDOC_InitFormFillEnvironment(). -//* page - Handle to the page, as returned by FPDF_LoadPage(). -//* modifier - Indicates whether various virtual keys are down. -//* page_x - Specifies the x-coordinate of the cursor in PDF user -//* space. -//* page_y - Specifies the y-coordinate of the cursor in PDF user -//* space. -//* Return Value: -//* True if there is an annotation at the given point and it has focus. -//* +// Experimental API +// Function: FORM_OnMouseWheel +// Call this member function when the user scrolls the mouse wheel. +// Parameters: +// hHandle - Handle to the form fill module, as returned by +// FPDFDOC_InitFormFillEnvironment(). +// page - Handle to the page, as returned by FPDF_LoadPage(). +// modifier - Indicates whether various virtual keys are down. +// page_coord - Specifies the coordinates of the cursor in PDF user +// space. +// delta_x - Specifies the amount of wheel movement on the x-axis, +// in units of platform-agnostic wheel deltas. Negative +// values mean left. +// delta_y - Specifies the amount of wheel movement on the y-axis, +// in units of platform-agnostic wheel deltas. Negative +// values mean down. +// Return Value: +// True indicates success; otherwise false. +// Comments: +// For |delta_x| and |delta_y|, the caller must normalize +// platform-specific wheel deltas. e.g. On Windows, a delta value of 240 +// for a WM_MOUSEWHEEL event normalizes to 2, since Windows defines +// WHEEL_DELTA as 120. +var + FORM_OnMouseWheel: function(hHandle: FPDF_FORMHANDLE; page: FPDF_PAGE; modifier: Integer; + const page_coord: PFS_POINTF; delta_x, delta_y: Integer): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Function: FORM_OnFocus +// This function focuses the form annotation at a given point. If the +// annotation at the point already has focus, nothing happens. If there +// is no annotation at the point, removes form focus. +// Parameters: +// hHandle - Handle to the form fill module, as returned by +// FPDFDOC_InitFormFillEnvironment(). +// page - Handle to the page, as returned by FPDF_LoadPage(). +// modifier - Indicates whether various virtual keys are down. +// page_x - Specifies the x-coordinate of the cursor in PDF user +// space. +// page_y - Specifies the y-coordinate of the cursor in PDF user +// space. +// Return Value: +// True if there is an annotation at the given point and it has focus. var FORM_OnFocus: function(hHandle: FPDF_FORMHANDLE; page: FPDF_PAGE; modifier: Integer; page_x, page_y: Double): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//* -//* Function: FORM_OnLButtonDown -//* Call this member function when the user presses the left -//* mouse button. -//* Parameters: -//* hHandle - Handle to the form fill module. as returned by -//* FPDFDOC_InitFormFillEnvironment(). -//* page - Handle to the page, as returned by FPDF_LoadPage(). -//* modifier - Indicates whether various virtual keys are down. -//* page_x - Specifies the x-coordinate of the cursor in PDF user -//* space. -//* page_y - Specifies the y-coordinate of the cursor in PDF user -//* space. -//* Return Value: -//* True indicates success; otherwise false. -//* +// Function: FORM_OnLButtonDown +// Call this member function when the user presses the left +// mouse button. +// Parameters: +// hHandle - Handle to the form fill module, as returned by +// FPDFDOC_InitFormFillEnvironment(). +// page - Handle to the page, as returned by FPDF_LoadPage(). +// modifier - Indicates whether various virtual keys are down. +// page_x - Specifies the x-coordinate of the cursor in PDF user +// space. +// page_y - Specifies the y-coordinate of the cursor in PDF user +// space. +// Return Value: +// True indicates success; otherwise false. var FORM_OnLButtonDown: function(hHandle: FPDF_FORMHANDLE; page: FPDF_PAGE; modifier: Integer; page_x, page_y: Double): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//* -//* Function: FORM_OnRButtonDown -//* Same as above, execpt for the right mouse button. -//* Comments: -//* At the present time, has no effect except in XFA builds, but is -//* included for the sake of symmetry. -//* +// Function: FORM_OnRButtonDown +// Same as above, execpt for the right mouse button. +// Comments: +// At the present time, has no effect except in XFA builds, but is +// included for the sake of symmetry. var FORM_OnRButtonDown: function(hHandle: FPDF_FORMHANDLE; page: FPDF_PAGE; modifier: Integer; page_x, page_y: Double): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//* -//* Function: FORM_OnLButtonUp -//* Call this member function when the user releases the left -//* mouse button. -//* Parameters: -//* hHandle - Handle to the form fill module, as returned by -//* FPDFDOC_InitFormFillEnvironment(). -//* page - Handle to the page. as returned by FPDF_LoadPage(). -//* modifier - Indicates whether various virtual keys are down. -//* page_x - Specifies the x-coordinate of the cursor in device. -//* page_y - Specifies the y-coordinate of the cursor in device. -//* Return Value: -//* True indicates success; otherwise false. -//* +// Function: FORM_OnLButtonUp +// Call this member function when the user releases the left +// mouse button. +// Parameters: +// hHandle - Handle to the form fill module, as returned by +// FPDFDOC_InitFormFillEnvironment(). +// page - Handle to the page, as returned by FPDF_LoadPage(). +// modifier - Indicates whether various virtual keys are down. +// page_x - Specifies the x-coordinate of the cursor in device. +// page_y - Specifies the y-coordinate of the cursor in device. +// Return Value: +// True indicates success; otherwise false. var FORM_OnLButtonUp: function(hHandle: FPDF_FORMHANDLE; page: FPDF_PAGE; modifier: Integer; page_x, page_y: Double): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//* -//* Function: FORM_OnRButtonUp -//* Same as above, execpt for the right mouse button. -//* Comments: -//* At the present time, has no effect except in XFA builds, but is -//* included for the sake of symmetry. -//* +// Function: FORM_OnRButtonUp +// Same as above, execpt for the right mouse button. +// Comments: +// At the present time, has no effect except in XFA builds, but is +// included for the sake of symmetry. var FORM_OnRButtonUp: function(hHandle: FPDF_FORMHANDLE; page: FPDF_PAGE; modifier: Integer; page_x, page_y: Double): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//* -//* Function: FORM_OnLButtonDoubleClick -//* Call this member function when the user double clicks the -//* left mouse button. -//* Parameters: -//* hHandle - Handle to the form fill module, as returned by -//* FPDFDOC_InitFormFillEnvironment(). -//* page - Handle to the page, as returned by FPDF_LoadPage(). -//* modifier - Indicates whether various virtual keys are down. -//* page_x - Specifies the x-coordinate of the cursor in PDF user -//* space. -//* page_y - Specifies the y-coordinate of the cursor in PDF user -//* space. -//* Return Value: -//* True indicates success; otherwise false. -//* +// Function: FORM_OnLButtonDoubleClick +// Call this member function when the user double clicks the +// left mouse button. +// Parameters: +// hHandle - Handle to the form fill module, as returned by +// FPDFDOC_InitFormFillEnvironment(). +// page - Handle to the page, as returned by FPDF_LoadPage(). +// modifier - Indicates whether various virtual keys are down. +// page_x - Specifies the x-coordinate of the cursor in PDF user +// space. +// page_y - Specifies the y-coordinate of the cursor in PDF user +// space. +// Return Value: +// True indicates success; otherwise false. var FORM_OnLButtonDoubleClick: function(hHandle: FPDF_FORMHANDLE; page: FPDF_PAGE; modifier: Integer; page_x, page_y: Double): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//* -//* Function: FORM_OnKeyDown -//* Call this member function when a nonsystem key is pressed. -//* Parameters: -//* hHandle - Handle to the form fill module, aseturned by -//* FPDFDOC_InitFormFillEnvironment(). -//* page - Handle to the page, as returned by FPDF_LoadPage(). -//* nKeyCode - Indicates whether various virtual keys are down. -//* modifier - Contains the scan code, key-transition code, -//* previous key state, and context code. -//* Return Value: -//* True indicates success; otherwise false. -//* +// Function: FORM_OnKeyDown +// Call this member function when a nonsystem key is pressed. +// Parameters: +// hHandle - Handle to the form fill module, aseturned by +// FPDFDOC_InitFormFillEnvironment(). +// page - Handle to the page, as returned by FPDF_LoadPage(). +// nKeyCode - The virtual-key code of the given key (see +// fpdf_fwlevent.h for virtual key codes). +// modifier - Mask of key flags (see fpdf_fwlevent.h for key +// flag values). +// Return Value: +// True indicates success; otherwise false. var FORM_OnKeyDown: function(hHandle: FPDF_FORMHANDLE; page: FPDF_PAGE; nKeyCode, modifier: Integer): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//* -//* Function: FORM_OnKeyUp -//* Call this member function when a nonsystem key is released. -//* Parameters: -//* hHandle - Handle to the form fill module, as returned by -//* FPDFDOC_InitFormFillEnvironment(). -//* page - Handle to the page, as returned by FPDF_LoadPage(). -//* nKeyCode - The virtual-key code of the given key. -//* modifier - Contains the scan code, key-transition code, -//* previous key state, and context code. -//* Return Value: -//* True indicates success; otherwise false. -//* +// Function: FORM_OnKeyUp +// Call this member function when a nonsystem key is released. +// Parameters: +// hHandle - Handle to the form fill module, as returned by +// FPDFDOC_InitFormFillEnvironment(). +// page - Handle to the page, as returned by FPDF_LoadPage(). +// nKeyCode - The virtual-key code of the given key (see +// fpdf_fwlevent.h for virtual key codes). +// modifier - Mask of key flags (see fpdf_fwlevent.h for key +// flag values). +// Return Value: +// True indicates success; otherwise false. +// Comments: +// Currently unimplemented and always returns false. PDFium reserves this +// API and may implement it in the future on an as-needed basis. var FORM_OnKeyUp: function(hHandle: FPDF_FORMHANDLE; page: FPDF_PAGE; nKeyCode, modifier: Integer): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//* -//* Function: FORM_OnChar -//* Call this member function when a keystroke translates to a -//* nonsystem character. -//* Parameters: -//* hHandle - Handle to the form fill module, as returned by -//* FPDFDOC_InitFormFillEnvironment(). -//* page - Handle to the page, as returned by FPDF_LoadPage(). -//* nChar - The character code value of the key. -//* modifier - Contains the scan code, key-transition code, -//* previous key state, and context code. -//* Return Value: -//* True indicates success; otherwise false. -//* +// Function: FORM_OnChar +// Call this member function when a keystroke translates to a +// nonsystem character. +// Parameters: +// hHandle - Handle to the form fill module, as returned by +// FPDFDOC_InitFormFillEnvironment(). +// page - Handle to the page, as returned by FPDF_LoadPage(). +// nChar - The character code value itself. +// modifier - Mask of key flags (see fpdf_fwlevent.h for key +// flag values). +// Return Value: +// True indicates success; otherwise false. var FORM_OnChar: function(hHandle: FPDF_FORMHANDLE; page: FPDF_PAGE; nChar, modifier: Integer): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//* -//* Experimental API -//* Function: FORM_GetFocusedText -//* Call this function to obtain the text within the current focused -//* field, if any. -//* Parameters: -//* hHandle - Handle to the form fill module, as returned by -//* FPDFDOC_InitFormFillEnvironment(). -//* page - Handle to the page, as returned by FPDF_LoadPage(). -//* buffer - Buffer for holding the form text, encoded in -//* UTF-16LE. If NULL, |buffer| is not modified. -//* buflen - Length of |buffer| in bytes. If |buflen| is less -//* than the length of the form text string, |buffer| is -//* not modified. -//* Return Value: -//* Length in bytes for the text in the focused field. -//* +// Experimental API +// Function: FORM_GetFocusedText +// Call this function to obtain the text within the current focused +// field, if any. +// Parameters: +// hHandle - Handle to the form fill module, as returned by +// FPDFDOC_InitFormFillEnvironment(). +// page - Handle to the page, as returned by FPDF_LoadPage(). +// buffer - Buffer for holding the form text, encoded in +// UTF-16LE. If NULL, |buffer| is not modified. +// buflen - Length of |buffer| in bytes. If |buflen| is less +// than the length of the form text string, |buffer| is +// not modified. +// Return Value: +// Length in bytes for the text in the focused field. var FORM_GetFocusedText: function(hHandle: FPDF_FORMHANDLE; page: FPDF_PAGE; buffer: Pointer; buflen: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//* -//* Function: FORM_GetSelectedText -//* Call this function to obtain selected text within a form text -//* field or form combobox text field. -//* Parameters: -//* hHandle - Handle to the form fill module, asr eturned by -//* FPDFDOC_InitFormFillEnvironment(). -//* page - Handle to the page, as returned by FPDF_LoadPage(). -//* buffer - Buffer for holding the selected text, encoded in -//* UTF-16LE. If NULL, |buffer| is not modified. -//* buflen - Length of |buffer| in bytes. If |buflen| is less -//* than the length of the selected text string, -//* |buffer| is not modified. -//* Return Value: -//* Length in bytes of selected text in form text field or form combobox -//* text field. -//* +// Function: FORM_GetSelectedText +// Call this function to obtain selected text within a form text +// field or form combobox text field. +// Parameters: +// hHandle - Handle to the form fill module, as returned by +// FPDFDOC_InitFormFillEnvironment(). +// page - Handle to the page, as returned by FPDF_LoadPage(). +// buffer - Buffer for holding the selected text, encoded in +// UTF-16LE. If NULL, |buffer| is not modified. +// buflen - Length of |buffer| in bytes. If |buflen| is less +// than the length of the selected text string, +// |buffer| is not modified. +// Return Value: +// Length in bytes of selected text in form text field or form combobox +// text field. var FORM_GetSelectedText: function(hHandle: FPDF_FORMHANDLE; page: FPDF_PAGE; buffer: Pointer; buflen: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//* -//* Function: FORM_ReplaceSelection -//* Call this function to replace the selected text in a form -//* text field or user-editable form combobox text field with another -//* text string (which can be empty or non-empty). If there is no -//* selected text, this function will append the replacement text after -//* the current caret position. -//* Parameters: -//* hHandle - Handle to the form fill module, as returned by -//* FPDFDOC_InitFormFillEnvironment(). -//* page - Handle to the page, as Returned by FPDF_LoadPage(). -//* wsText - The text to be inserted, in UTF-16LE format. -//* Return Value: -//* None. -//* +// Experimental API +// Function: FORM_ReplaceAndKeepSelection +// Call this function to replace the selected text in a form +// text field or user-editable form combobox text field with another +// text string (which can be empty or non-empty). If there is no +// selected text, this function will append the replacement text after +// the current caret position. After the insertion, the inserted text +// will be selected. +// Parameters: +// hHandle - Handle to the form fill module, as returned by +// FPDFDOC_InitFormFillEnvironment(). +// page - Handle to the page, as Returned by FPDF_LoadPage(). +// wsText - The text to be inserted, in UTF-16LE format. +// Return Value: +// None. +var + FORM_ReplaceAndKeepSelection: procedure(hHandle: FPDF_FORMHANDLE; page: FPDF_PAGE; wsText: FPDF_WIDESTRING); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Function: FORM_ReplaceSelection +// Call this function to replace the selected text in a form +// text field or user-editable form combobox text field with another +// text string (which can be empty or non-empty). If there is no +// selected text, this function will append the replacement text after +// the current caret position. After the insertion, the selection range +// will be set to empty. +// Parameters: +// hHandle - Handle to the form fill module, as returned by +// FPDFDOC_InitFormFillEnvironment(). +// page - Handle to the page, as Returned by FPDF_LoadPage(). +// wsText - The text to be inserted, in UTF-16LE format. +// Return Value: +// None. var FORM_ReplaceSelection: procedure(hHandle: FPDF_FORMHANDLE; page: FPDF_PAGE; wsText: FPDF_WIDESTRING); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//* -//* Function: FORM_CanUndo -//* Find out if it is possible for the current focused widget in a given -//* form to perform an undo operation. -//* Parameters: -//* hHandle - Handle to the form fill module, as returned by -//* FPDFDOC_InitFormFillEnvironment(). -//* page - Handle to the page, as returned by FPDF_LoadPage(). -//* Return Value: -//* True if it is possible to undo. -//* +// Experimental API +// Function: FORM_SelectAllText +// Call this function to select all the text within the currently focused +// form text field or form combobox text field. +// Parameters: +// hHandle - Handle to the form fill module, as returned by +// FPDFDOC_InitFormFillEnvironment(). +// page - Handle to the page, as returned by FPDF_LoadPage(). +// Return Value: +// Whether the operation succeeded or not. +var + FORM_SelectAllText: function(hHandle: FPDF_FORMHANDLE; page: FPDF_PAGE): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Function: FORM_CanUndo +// Find out if it is possible for the current focused widget in a given +// form to perform an undo operation. +// Parameters: +// hHandle - Handle to the form fill module, as returned by +// FPDFDOC_InitFormFillEnvironment(). +// page - Handle to the page, as returned by FPDF_LoadPage(). +// Return Value: +// True if it is possible to undo. var FORM_CanUndo: function(hHandle: FPDF_FORMHANDLE; page: FPDF_PAGE): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//* -//* Function: FORM_CanRedo -//* Find out if it is possible for the current focused widget in a given -//* form to perform a redo operation. -//* Parameters: -//* hHandle - Handle to the form fill module, as returned by -//* FPDFDOC_InitFormFillEnvironment(). -//* page - Handle to the page, as returned by FPDF_LoadPage(). -//* Return Value: -//* True if it is possible to redo. -//* +// Function: FORM_CanRedo +// Find out if it is possible for the current focused widget in a given +// form to perform a redo operation. +// Parameters: +// hHandle - Handle to the form fill module, as returned by +// FPDFDOC_InitFormFillEnvironment(). +// page - Handle to the page, as returned by FPDF_LoadPage(). +// Return Value: +// True if it is possible to redo. var FORM_CanRedo: function(hHandle: FPDF_FORMHANDLE; page: FPDF_PAGE): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//* -//* Function: FORM_Undo -//* Make the current focussed widget perform an undo operation. -//* Parameters: -//* hHandle - Handle to the form fill module. as returned by -//* FPDFDOC_InitFormFillEnvironment(). -//* page - Handle to the page, as returned by FPDF_LoadPage(). -//* Return Value: -//* True if the undo operation succeeded. -//* +// Function: FORM_Undo +// Make the current focused widget perform an undo operation. +// Parameters: +// hHandle - Handle to the form fill module, as returned by +// FPDFDOC_InitFormFillEnvironment(). +// page - Handle to the page, as returned by FPDF_LoadPage(). +// Return Value: +// True if the undo operation succeeded. var FORM_Undo: function(hHandle: FPDF_FORMHANDLE; page: FPDF_PAGE): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//* -//* Function: FORM_Undo -//* Make the current focussed widget perform an undo operation. -//* Parameters: -//* hHandle - Handle to the form fill module. as returned by -//* FPDFDOC_InitFormFillEnvironment(). -//* page - Handle to the page, as returned by FPDF_LoadPage(). -//* Return Value: -//* True if the undo operation succeeded. -//* +// Function: FORM_Redo +// Make the current focused widget perform a redo operation. +// Parameters: +// hHandle - Handle to the form fill module, as returned by +// FPDFDOC_InitFormFillEnvironment(). +// page - Handle to the page, as returned by FPDF_LoadPage(). +// Return Value: +// True if the redo operation succeeded. var FORM_Redo: function(hHandle: FPDF_FORMHANDLE; page: FPDF_PAGE): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//* -//* Function: FORM_ForceToKillFocus. -//* Call this member function to force to kill the focus of the form -//* field which has focus. If it would kill the focus of a form field, -//* save the value of form field if was changed by theuser. -//* Parameters: -//* hHandle - Handle to the form fill module, as returned by -//* FPDFDOC_InitFormFillEnvironment(). -//* Return Value: -//* True indicates success; otherwise false. -//* +// Function: FORM_ForceToKillFocus. +// Call this member function to force to kill the focus of the form +// field which has focus. If it would kill the focus of a form field, +// save the value of form field if was changed by theuser. +// Parameters: +// hHandle - Handle to the form fill module, as returned by +// FPDFDOC_InitFormFillEnvironment(). +// Return Value: +// True indicates success; otherwise false. var FORM_ForceToKillFocus: function(hHandle: FPDF_FORMHANDLE): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Experimental API. +// Function: FORM_GetFocusedAnnot. +// Call this member function to get the currently focused annotation. +// Parameters: +// handle - Handle to the form fill module, as returned by +// FPDFDOC_InitFormFillEnvironment(). +// page_index - Buffer to hold the index number of the page which +// contains the focused annotation. 0 for the first page. +// Can't be NULL. +// annot - Buffer to hold the focused annotation. Can't be NULL. +// Return Value: +// On success, return true and write to the out parameters. Otherwise +// return false and leave the out parameters unmodified. +// Comments: +// Not currently supported for XFA forms - will report no focused +// annotation. +// Must call FPDFPage_CloseAnnot() when the annotation returned in |annot| +// by this function is no longer needed. +// This will return true and set |page_index| to -1 and |annot| to NULL, +// if there is no focused annotation. +var + FORM_GetFocusedAnnot: function(handle: FPDF_FORMHANDLE; var page_index: Integer; + var annot: FPDF_ANNOTATION): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Function: FORM_SetFocusedAnnot. +// Call this member function to set the currently focused annotation. +// Parameters: +// handle - Handle to the form fill module, as returned by +// FPDFDOC_InitFormFillEnvironment(). +// annot - Handle to an annotation. +// Return Value: +// True indicates success; otherwise false. +// Comments: +// |annot| can't be NULL. To kill focus, use FORM_ForceToKillFocus() +// instead. +var + FORM_SetFocusedAnnot: function(handle: FPDF_FORMHANDLE; annot: FPDF_ANNOTATION): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // Form Field Types // The names of the defines are stable, but the specific values associated with // them are not, so do not hardcode their values. @@ -5545,215 +6619,196 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; {$ENDIF PDF_ENABLE_XFA} -//* -//* Function: FPDFPage_HasFormFieldAtPoint -//* Get the form field type by point. -//* Parameters: -//* hHandle - Handle to the form fill module. Returned by -//* FPDFDOC_InitFormFillEnvironment(). -//* page - Handle to the page. Returned by FPDF_LoadPage(). -//* page_x - X position in PDF "user space". -//* page_y - Y position in PDF "user space". -//* Return Value: -//* Return the type of the form field; -1 indicates no field. -//* See field types above. -//* + +// Function: FPDFPage_HasFormFieldAtPoint +// Get the form field type by point. +// Parameters: +// hHandle - Handle to the form fill module. Returned by +// FPDFDOC_InitFormFillEnvironment(). +// page - Handle to the page. Returned by FPDF_LoadPage(). +// page_x - X position in PDF "user space". +// page_y - Y position in PDF "user space". +// Return Value: +// Return the type of the form field; -1 indicates no field. +// See field types above. var FPDFPage_HasFormFieldAtPoint: function(hHandle: FPDF_FORMHANDLE; page: FPDF_PAGE; page_x, page_y: Double): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//* -//* Function: FPDFPage_FormFieldZOrderAtPoint -//* Get the form field z-order by point. -//* Parameters: -//* hHandle - Handle to the form fill module. Returned by -//* FPDFDOC_InitFormFillEnvironment(). -//* page - Handle to the page. Returned by FPDF_LoadPage(). -//* page_x - X position in PDF "user space". -//* page_y - Y position in PDF "user space". -//* Return Value: -//* Return the z-order of the form field; -1 indicates no field. -//* Higher numbers are closer to the front. -//* +// Function: FPDFPage_FormFieldZOrderAtPoint +// Get the form field z-order by point. +// Parameters: +// hHandle - Handle to the form fill module. Returned by +// FPDFDOC_InitFormFillEnvironment(). +// page - Handle to the page. Returned by FPDF_LoadPage(). +// page_x - X position in PDF "user space". +// page_y - Y position in PDF "user space". +// Return Value: +// Return the z-order of the form field; -1 indicates no field. +// Higher numbers are closer to the front. var FPDFPage_FormFieldZOrderAtPoint: function(hHandle: FPDF_FORMHANDLE; page: FPDF_PAGE; page_x, page_y: Double): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//* -//* Function: FPDF_SetFormFieldHighlightColor -//* Set the highlight color of the specified (or all) form fields -//* in the document. -//* Parameters: -//* hHandle - Handle to the form fill module, as returned by -//* FPDFDOC_InitFormFillEnvironment(). -//* doc - Handle to the document, as returned by -//* FPDF_LoadDocument(). -//* fieldType - A 32-bit integer indicating the type of a form -//* field (defined above). -//* color - The highlight color of the form field. Constructed by -//* 0xxxrrggbb. -//* Return Value: -//* None. -//* Comments: -//* When the parameter fieldType is set to FPDF_FORMFIELD_UNKNOWN, the -//* highlight color will be applied to all the form fields in the -//* document. -//* Please refresh the client window to show the highlight immediately -//* if necessary. -//* +// Function: FPDF_SetFormFieldHighlightColor +// Set the highlight color of the specified (or all) form fields +// in the document. +// Parameters: +// hHandle - Handle to the form fill module, as returned by +// FPDFDOC_InitFormFillEnvironment(). +// doc - Handle to the document, as returned by +// FPDF_LoadDocument(). +// fieldType - A 32-bit integer indicating the type of a form +// field (defined above). +// color - The highlight color of the form field. Constructed by +// 0xxxrrggbb. +// Return Value: +// None. +// Comments: +// When the parameter fieldType is set to FPDF_FORMFIELD_UNKNOWN, the +// highlight color will be applied to all the form fields in the +// document. +// Please refresh the client window to show the highlight immediately +// if necessary. var FPDF_SetFormFieldHighlightColor: procedure(hHandle: FPDF_FORMHANDLE; fieldType: Integer; Color: LongWord); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//* -//* Function: FPDF_SetFormFieldHighlightAlpha -//* Set the transparency of the form field highlight color in the -//* document. -//* Parameters: -//* hHandle - Handle to the form fill module, as returned by -//* FPDFDOC_InitFormFillEnvironment(). -//* doc - Handle to the document, as returaned by -//* FPDF_LoadDocument(). -//* alpha - The transparency of the form field highlight color, -//* between 0-255. -//* Return Value: -//* None. -//* +// Function: FPDF_SetFormFieldHighlightAlpha +// Set the transparency of the form field highlight color in the +// document. +// Parameters: +// hHandle - Handle to the form fill module, as returned by +// FPDFDOC_InitFormFillEnvironment(). +// doc - Handle to the document, as returaned by +// FPDF_LoadDocument(). +// alpha - The transparency of the form field highlight color, +// between 0-255. +// Return Value: +// None. var FPDF_SetFormFieldHighlightAlpha: procedure(hHandle: FPDF_FORMHANDLE; alpha: Byte); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//* -//* Function: FPDF_RemoveFormFieldHighlight -//* Remove the form field highlight color in the document. -//* Parameters: -//* hHandle - Handle to the form fill module, as returned by -//* FPDFDOC_InitFormFillEnvironment(). -//* Return Value: -//* None. -//* Comments: -//* Please refresh the client window to remove the highlight immediately -//* if necessary. -//* +// Function: FPDF_RemoveFormFieldHighlight +// Remove the form field highlight color in the document. +// Parameters: +// hHandle - Handle to the form fill module, as returned by +// FPDFDOC_InitFormFillEnvironment(). +// Return Value: +// None. +// Comments: +// Please refresh the client window to remove the highlight immediately +// if necessary. var FPDF_RemoveFormFieldHighlight: procedure(hHandle: FPDF_FORMHANDLE); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//* -//* Function: FPDF_FFLDraw -//* Render FormFields and popup window on a page to a device independent -//* bitmap. -//* Parameters: -//* hHandle - Handle to the form fill module, as returned by -//* FPDFDOC_InitFormFillEnvironment(). -//* bitmap - Handle to the device independent bitmap (as the -//* output buffer). Bitmap handles can be created by -//* FPDFBitmap_Create(). -//* page - Handle to the page, as returned by FPDF_LoadPage(). -//* start_x - Left pixel position of the display area in the -//* device coordinates. -//* start_y - Top pixel position of the display area in the device -//* coordinates. -//* size_x - Horizontal size (in pixels) for displaying the page. -//* size_y - Vertical size (in pixels) for displaying the page. -//* rotate - Page orientation: 0 (normal), 1 (rotated 90 degrees -//* clockwise), 2 (rotated 180 degrees), 3 (rotated 90 -//* degrees counter-clockwise). -//* flags - 0 for normal display, or combination of flags -//* defined above. -//* Return Value: -//* None. -//* Comments: -//* This function is designed to render annotations that are -//* user-interactive, which are widget annotations (for FormFields) and -//* popup annotations. -//* With the FPDF_ANNOT flag, this function will render a popup annotation -//* when users mouse-hover on a non-widget annotation. Regardless of -//* FPDF_ANNOT flag, this function will always render widget annotations -//* for FormFields. -//* In order to implement the FormFill functions, implementation should -//* call this function after rendering functions, such as -//* FPDF_RenderPageBitmap() or FPDF_RenderPageBitmap_Start(), have -//* finished rendering the page contents. -//* +// Function: FPDF_FFLDraw +// Render FormFields and popup window on a page to a device independent +// bitmap. +// Parameters: +// hHandle - Handle to the form fill module, as returned by +// FPDFDOC_InitFormFillEnvironment(). +// bitmap - Handle to the device independent bitmap (as the +// output buffer). Bitmap handles can be created by +// FPDFBitmap_Create(). +// page - Handle to the page, as returned by FPDF_LoadPage(). +// start_x - Left pixel position of the display area in the +// device coordinates. +// start_y - Top pixel position of the display area in the device +// coordinates. +// size_x - Horizontal size (in pixels) for displaying the page. +// size_y - Vertical size (in pixels) for displaying the page. +// rotate - Page orientation: 0 (normal), 1 (rotated 90 degrees +// clockwise), 2 (rotated 180 degrees), 3 (rotated 90 +// degrees counter-clockwise). +// flags - 0 for normal display, or combination of flags +// defined above. +// Return Value: +// None. +// Comments: +// This function is designed to render annotations that are +// user-interactive, which are widget annotations (for FormFields) and +// popup annotations. +// With the FPDF_ANNOT flag, this function will render a popup annotation +// when users mouse-hover on a non-widget annotation. Regardless of +// FPDF_ANNOT flag, this function will always render widget annotations +// for FormFields. +// In order to implement the FormFill functions, implementation should +// call this function after rendering functions, such as +// FPDF_RenderPageBitmap() or FPDF_RenderPageBitmap_Start(), have +// finished rendering the page contents. var FPDF_FFLDraw: procedure(hHandle: FPDF_FORMHANDLE; bitmap: FPDF_BITMAP; page: FPDF_PAGE; start_x, start_y, size_x, size_y, rotate, flags: Integer); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -{$IFDEF _SKIA_SUPPORT_} +{$IFDEF PDF_USE_SKIA} var - FPDF_FFLRecord: procedure(hHandle: FPDF_FORMHANDLE; recorder: FPDF_RECORDER; page: FPDF_PAGE; + FPDF_FFLDrawSkia: procedure(hHandle: FPDF_FORMHANDLE; canvas: FPDF_SKIA_CANVAS; page: FPDF_PAGE; start_x, start_y, size_x, size_y, rotate, flags: Integer); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -{$ENDIF _SKIA_SUPPORT_} - -//* -//* Experimental API -//* Function: FPDF_GetFormType -//* Returns the type of form contained in the PDF document. -//* Parameters: -//* document - Handle to document. -//* Return Value: -//* Integer value representing one of the FORMTYPE_ values. -//* Comments: -//* If |document| is NULL, then the return value is FORMTYPE_NONE. -//* +{$ENDIF PDF_USE_SKIA} + +// Experimental API +// Function: FPDF_GetFormType +// Returns the type of form contained in the PDF document. +// Parameters: +// document - Handle to document. +// Return Value: +// Integer value representing one of the FORMTYPE_ values. +// Comments: +// If |document| is NULL, then the return value is FORMTYPE_NONE. var FPDF_GetFormType: function(document: FPDF_DOCUMENT): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//* -//* Experimental API -//* Function: FORM_SetIndexSelected -//* Selects/deselects the value at the given |index| of the focused -//* annotation. -//* Parameters: -//* hHandle - Handle to the form fill module. Returned by -//* FPDFDOC_InitFormFillEnvironment. -//* page - Handle to the page. Returned by FPDF_LoadPage -//* index - 0-based index of value to be set as -//* selected/unselected -//* selected - true to select, false to deselect -//* Return Value: -//* TRUE if the operation succeeded. -//* FALSE if the operation failed or widget is not a supported type. -//* Comments: -//* Intended for use with listbox/combobox widget types. Comboboxes -//* have at most a single value selected at a time which cannot be -//* deselected. Deselect on a combobox is a no-op that returns false. -//* Default implementation is a no-op that will return false for -//* other types. -//* Not currently supported for XFA forms - will return false. -//* +// Experimental API +// Function: FORM_SetIndexSelected +// Selects/deselects the value at the given |index| of the focused +// annotation. +// Parameters: +// hHandle - Handle to the form fill module. Returned by +// FPDFDOC_InitFormFillEnvironment. +// page - Handle to the page. Returned by FPDF_LoadPage +// index - 0-based index of value to be set as +// selected/unselected +// selected - true to select, false to deselect +// Return Value: +// TRUE if the operation succeeded. +// FALSE if the operation failed or widget is not a supported type. +// Comments: +// Intended for use with listbox/combobox widget types. Comboboxes +// have at most a single value selected at a time which cannot be +// deselected. Deselect on a combobox is a no-op that returns false. +// Default implementation is a no-op that will return false for +// other types. +// Not currently supported for XFA forms - will return false. var FORM_SetIndexSelected: function(hHandle: FPDF_FORMHANDLE; page: FPDF_PAGE; index: Integer; selected: FPDF_BOOL): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//* -//* Experimental API -//* Function: FORM_IsIndexSelected -//* Returns whether or not the value at |index| of the focused -//* annotation is currently selected. -//* Parameters: -//* hHandle - Handle to the form fill module. Returned by -//* FPDFDOC_InitFormFillEnvironment. -//* page - Handle to the page. Returned by FPDF_LoadPage -//* index - 0-based Index of value to check -//* Return Value: -//* TRUE if value at |index| is currently selected. -//* FALSE if value at |index| is not selected or widget is not a -//* supported type. -//* Comments: -//* Intended for use with listbox/combobox widget types. Default -//* implementation is a no-op that will return false for other types. -//* Not currently supported for XFA forms - will return false. -//* +// Experimental API +// Function: FORM_IsIndexSelected +// Returns whether or not the value at |index| of the focused +// annotation is currently selected. +// Parameters: +// hHandle - Handle to the form fill module. Returned by +// FPDFDOC_InitFormFillEnvironment. +// page - Handle to the page. Returned by FPDF_LoadPage +// index - 0-based Index of value to check +// Return Value: +// TRUE if value at |index| is currently selected. +// FALSE if value at |index| is not selected or widget is not a +// supported type. +// Comments: +// Intended for use with listbox/combobox widget types. Default +// implementation is a no-op that will return false for other types. +// Not currently supported for XFA forms - will return false. var FORM_IsIndexSelected: function(hHandle: FPDF_FORMHANDLE; page: FPDF_PAGE; index: Integer): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//* -//* Function: FPDF_LoadXFA -//* If the document consists of XFA fields, call this method to -//* attempt to load XFA fields. -//* Parameters: -//* document - Handle to document from FPDF_LoadDocument(). -//* Return Value: -//* TRUE upon success, otherwise FALSE. If XFA support is not built -//* into PDFium, performs no action and always returns FALSE. -//* +// Function: FPDF_LoadXFA +// If the document consists of XFA fields, call this method to +// attempt to load XFA fields. +// Parameters: +// document - Handle to document from FPDF_LoadDocument(). +// Return Value: +// TRUE upon success, otherwise FALSE. If XFA support is not built +// into PDFium, performs no action and always returns FALSE. var FPDF_LoadXFA: function(document: FPDF_DOCUMENT): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; @@ -5789,6 +6844,7 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; FPDF_ANNOT_THREED = 25; FPDF_ANNOT_RICHMEDIA = 26; FPDF_ANNOT_XFAWIDGET = 27; + FPDF_ANNOT_REDACT = 28; // Refer to PDF Reference (6th edition) table 8.16 for all annotation flags. FPDF_ANNOT_FLAG_NONE = 0; @@ -5823,6 +6879,17 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; // interactive form choice fields. FPDF_FORMFLAG_CHOICE_COMBO = (1 shl 17); FPDF_FORMFLAG_CHOICE_EDIT = (1 shl 18); + FPDF_FORMFLAG_CHOICE_MULTI_SELECT = (1 shl 21); + + // Additional actions type of form field: + // K, on key stroke, JavaScript action. + // F, on format, JavaScript action. + // V, on validate, JavaScript action. + // C, on calculate, JavaScript action. + FPDF_ANNOT_AACTION_KEY_STROKE = 12; + FPDF_ANNOT_AACTION_FORMAT = 13; + FPDF_ANNOT_AACTION_VALIDATE = 14; + FPDF_ANNOT_AACTION_CALCULATE = 15; type FPDFANNOT_COLORTYPE = ( @@ -5832,8 +6899,20 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; // Experimental API. // Check if an annotation subtype is currently supported for creation. -// Currently supported subtypes: circle, highlight, ink, popup, square, -// squiggly, stamp, strikeout, text, and underline. +// Currently supported subtypes: +// - circle +// - fileattachment +// - freetext +// - highlight +// - ink +// - link +// - popup +// - square, +// - squiggly +// - stamp +// - strikeout +// - text +// - underline // // subtype - the subtype to be checked. // @@ -5938,6 +7017,33 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; var FPDFAnnot_UpdateObject: function(annot: FPDF_ANNOTATION; obj: FPDF_PAGEOBJECT): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Experimental API. +// Add a new InkStroke, represented by an array of points, to the InkList of +// |annot|. The API creates an InkList if one doesn't already exist in |annot|. +// This API works only for ink annotations. Please refer to ISO 32000-1:2008 +// spec, section 12.5.6.13. +// +// annot - handle to an annotation. +// points - pointer to a FS_POINTF array representing input points. +// point_count - number of elements in |points| array. This should not exceed +// the maximum value that can be represented by an int32_t). +// +// Returns the 0-based index at which the new InkStroke is added in the InkList +// of the |annot|. Returns -1 on failure. +var + FPDFAnnot_AddInkStroke: function(annot: FPDF_ANNOTATION; const points: PFS_POINTF; point_count: SIZE_T): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Removes an InkList in |annot|. +// This API works only for ink annotations. +// +// annot - handle to an annotation. +// +// Return true on successful removal of /InkList entry from context of the +// non-null ink |annot|. Returns false on failure. +var + FPDFAnnot_RemoveInkList: function(annot: FPDF_ANNOTATION): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // Experimental API. // Add |obj| to |annot|. |obj| must have been created by // FPDFPageObj_CreateNew{Path|Rect}() or FPDFPageObj_New{Text|Image}Obj(), and @@ -5985,7 +7091,7 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; // Experimental API. // Set the color of an annotation. Fails when called on annotations with // appearance streams already defined; instead use -// FPDFPath_Set{Stroke|Fill}Color(). +// FPDFPageObj_Set{Stroke|Fill}Color(). // // annot - handle to an annotation. // type - type of the color to be set. @@ -6000,7 +7106,7 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; // Get the color of an annotation. If no color is specified, default to yellow // for highlight annotation, black for all else. Fails when called on // annotations with appearance streams already defined; instead use -// FPDFPath_Get{Stroke|Fill}Color(). +// FPDFPageObj_Get{Stroke|Fill}Color(). // // annot - handle to an annotation. // type - type of the color requested. @@ -6098,6 +7204,108 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; var FPDFAnnot_GetRect: function(annot: FPDF_ANNOTATION; rect: PFS_RECTF): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Experimental API. +// Get the vertices of a polygon or polyline annotation. |buffer| is an array of +// points of the annotation. If |length| is less than the returned length, or +// |annot| or |buffer| is NULL, |buffer| will not be modified. +// +// annot - handle to an annotation, as returned by e.g. FPDFPage_GetAnnot() +// buffer - buffer for holding the points. +// length - length of the buffer in points. +// +// Returns the number of points if the annotation is of type polygon or +// polyline, 0 otherwise. +var + FPDFAnnot_GetVertices: function(annot: FPDF_ANNOTATION; buffer: PFS_POINTF; length: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Get the number of paths in the ink list of an ink annotation. +// +// annot - handle to an annotation, as returned by e.g. FPDFPage_GetAnnot() +// +// Returns the number of paths in the ink list if the annotation is of type ink, +// 0 otherwise. +var + FPDFAnnot_GetInkListCount: function(annot: FPDF_ANNOTATION): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Get a path in the ink list of an ink annotation. |buffer| is an array of +// points of the path. If |length| is less than the returned length, or |annot| +// or |buffer| is NULL, |buffer| will not be modified. +// +// annot - handle to an annotation, as returned by e.g. FPDFPage_GetAnnot() +// path_index - index of the path +// buffer - buffer for holding the points. +// length - length of the buffer in points. +// +// Returns the number of points of the path if the annotation is of type ink, 0 +// otherwise. +var + FPDFAnnot_GetInkListPath: function(annot: FPDF_ANNOTATION; path_index: LongWord; buffer: PFS_POINTF; + length: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Get the starting and ending coordinates of a line annotation. +// +// annot - handle to an annotation, as returned by e.g. FPDFPage_GetAnnot() +// start - starting point +// end - ending point +// +// Returns true if the annotation is of type line, |start| and |end| are not +// NULL, false otherwise. +var + FPDFAnnot_GetLine: function(annot: FPDF_ANNOTATION; start, end_: PFS_POINTF): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Set the characteristics of the annotation's border (rounded rectangle). +// +// annot - handle to an annotation +// horizontal_radius - horizontal corner radius, in default user space units +// vertical_radius - vertical corner radius, in default user space units +// border_width - border width, in default user space units +// +// Returns true if setting the border for |annot| succeeds, false otherwise. +// +// If |annot| contains an appearance stream that overrides the border values, +// then the appearance stream will be removed on success. +var + FPDFAnnot_SetBorder: function(annot: FPDF_ANNOTATION; horizontal_radius, vertical_radius, border_width: Single): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Get the characteristics of the annotation's border (rounded rectangle). +// +// annot - handle to an annotation +// horizontal_radius - horizontal corner radius, in default user space units +// vertical_radius - vertical corner radius, in default user space units +// border_width - border width, in default user space units +// +// Returns true if |horizontal_radius|, |vertical_radius| and |border_width| are +// not NULL, false otherwise. +var + FPDFAnnot_GetBorder: function(annot: FPDF_ANNOTATION; var horizontal_radius, vertical_radius, border_width: Single): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Get the JavaScript of an event of the annotation's additional actions. +// |buffer| is only modified if |buflen| is large enough to hold the whole +// JavaScript string. If |buflen| is smaller, the total size of the JavaScript +// is still returned, but nothing is copied. If there is no JavaScript for +// |event| in |annot|, an empty string is written to |buf| and 2 is returned, +// denoting the size of the null terminator in the buffer. On other errors, +// nothing is written to |buffer| and 0 is returned. +// +// hHandle - handle to the form fill module, returned by +// FPDFDOC_InitFormFillEnvironment(). +// annot - handle to an interactive form annotation. +// event - event type, one of the FPDF_ANNOT_AACTION_* values. +// buffer - buffer for holding the value string, encoded in UTF-16LE. +// buflen - length of the buffer in bytes. +// +// Returns the length of the string value in bytes, including the 2-byte +// null terminator. +var + FPDFAnnot_GetFormAdditionalActionJavaScript: function(hHandle: FPDF_FORMHANDLE; annot: FPDF_ANNOTATION; + event: Integer; buffer: PFPDF_WCHAR; buflen: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // Experimental API. // Check if |annot|'s dictionary has |key| as a key. // @@ -6244,6 +7452,18 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; var FPDFAnnot_GetFormFieldFlags: function(hHandle: FPDF_FORMHANDLE; annot: FPDF_ANNOTATION): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Experimental API. +// Sets the form field flags for an interactive form annotation. +// +// handle - the handle to the form fill module, returned by +// FPDFDOC_InitFormFillEnvironment(). +// annot - handle to an interactive form annotation. +// flags - the form field flags to be set. +// +// Returns true if successful. +var + FPDFAnnot_SetFormFieldFlags: function(handle: FPDF_FORMHANDLE; annot: FPDF_ANNOTATION; flags: Integer): FPDF_BOOL {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // Experimental API. // Retrieves an interactive form annotation whose rectangle contains a given // point on a page. Must call FPDFPage_CloseAnnot() when the annotation returned @@ -6278,6 +7498,24 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; FPDFAnnot_GetFormFieldName: function(hHandle: FPDF_FORMHANDLE; annot: FPDF_ANNOTATION; buffer: PFPDF_WCHAR; buflen: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Experimental API. +// Gets the alternate name of |annot|, which is an interactive form annotation. +// |buffer| is only modified if |buflen| is longer than the length of contents. +// In case of error, nothing will be added to |buffer| and the return value will +// be 0. Note that return value of empty string is 2 for "\0\0". +// +// hHandle - handle to the form fill module, returned by +// FPDFDOC_InitFormFillEnvironment(). +// annot - handle to an interactive form annotation. +// buffer - buffer for holding the alternate name string, encoded in +// UTF-16LE. +// buflen - length of the buffer in bytes. +// +// Returns the length of the string value in bytes. +var + FPDFAnnot_GetFormFieldAlternateName: function(hHandle: FPDF_FORMHANDLE; annot: FPDF_ANNOTATION; buffer: PFPDF_WCHAR; + buflen: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // Experimental API. // Gets the form field type of |annot|, which is an interactive form annotation. // @@ -6343,6 +7581,20 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; FPDFAnnot_GetOptionLabel: function(hHandle: FPDF_FORMHANDLE; annot: FPDF_ANNOTATION; index: Integer; buffer: PFPDF_WCHAR; buflen: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Experimental API. +// Determine whether or not the option at |index| in |annot|'s "Opt" dictionary +// is selected. Intended for use with listbox and combobox widget annotations. +// +// handle - handle to the form fill module, returned by +// FPDFDOC_InitFormFillEnvironment. +// annot - handle to an annotation. +// index - numeric index of the option in the "Opt" array. +// +// Returns true if the option at |index| in |annot|'s "Opt" dictionary is +// selected, false otherwise. +var + FPDFAnnot_IsOptionSelected: function(handle: FPDF_FORMHANDLE; annot: FPDF_ANNOTATION; index: Integer): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // Experimental API. // Get the float value of the font size for an |annot| with variable text. // If 0, the font is to be auto-sized: its size is computed as a function of @@ -6353,41 +7605,227 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; // annot - handle to an annotation. // value - Required. Float which will be set to font size on success. // -// Returns true if the font size was set in |value|, false on error or if -// |value| not provided. +// Returns true if the font size was set in |value|, false on error or if +// |value| not provided. +var + FPDFAnnot_GetFontSize: function(hHandle: FPDF_FORMHANDLE; annot: FPDF_ANNOTATION; var value: Single): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Set the text color of an annotation. +// +// handle - handle to the form fill module, returned by +// FPDFDOC_InitFormFillEnvironment. +// annot - handle to an annotation. +// R - the red component for the text color. +// G - the green component for the text color. +// B - the blue component for the text color. +// +// Returns true if successful. +// +// Currently supported subtypes: freetext. +// The range for the color components is 0 to 255. +var + FPDFAnnot_SetFontColor: function(handle: FPDF_FORMHANDLE; annot: FPDF_ANNOTATION; R, G, B: Cardinal): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Get the RGB value of the font color for an |annot| with variable text. +// +// hHandle - handle to the form fill module, returned by +// FPDFDOC_InitFormFillEnvironment. +// annot - handle to an annotation. +// R, G, B - buffer to hold the RGB value of the color. Ranges from 0 to 255. +// +// Returns true if the font color was set, false on error or if the font +// color was not provided. +var + FPDFAnnot_GetFontColor: function(hHandle: FPDF_FORMHANDLE; annot: FPDF_ANNOTATION; var R, G, B: Cardinal): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Determine if |annot| is a form widget that is checked. Intended for use with +// checkbox and radio button widgets. +// +// hHandle - handle to the form fill module, returned by +// FPDFDOC_InitFormFillEnvironment. +// annot - handle to an annotation. +// +// Returns true if |annot| is a form widget and is checked, false otherwise. +var + FPDFAnnot_IsChecked: function(hHandle: FPDF_FORMHANDLE; annot: FPDF_ANNOTATION): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Set the list of focusable annotation subtypes. Annotations of subtype +// FPDF_ANNOT_WIDGET are by default focusable. New subtypes set using this API +// will override the existing subtypes. +// +// hHandle - handle to the form fill module, returned by +// FPDFDOC_InitFormFillEnvironment. +// subtypes - list of annotation subtype which can be tabbed over. +// count - total number of annotation subtype in list. +// Returns true if list of annotation subtype is set successfully, false +// otherwise. +var + FPDFAnnot_SetFocusableSubtypes: function(hHandle: FPDF_FORMHANDLE; const subtypes: PFPDF_ANNOTATION_SUBTYPE; + count: SIZE_T): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Get the count of focusable annotation subtypes as set by host +// for a |hHandle|. +// +// hHandle - handle to the form fill module, returned by +// FPDFDOC_InitFormFillEnvironment. +// Returns the count of focusable annotation subtypes or -1 on error. +// Note : Annotations of type FPDF_ANNOT_WIDGET are by default focusable. +var + FPDFAnnot_GetFocusableSubtypesCount: function(hHandle: FPDF_FORMHANDLE): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Get the list of focusable annotation subtype as set by host. +// +// hHandle - handle to the form fill module, returned by +// FPDFDOC_InitFormFillEnvironment. +// subtypes - receives the list of annotation subtype which can be tabbed +// over. Caller must have allocated |subtypes| more than or +// equal to the count obtained from +// FPDFAnnot_GetFocusableSubtypesCount() API. +// count - size of |subtypes|. +// Returns true on success and set list of annotation subtype to |subtypes|, +// false otherwise. +// Note : Annotations of type FPDF_ANNOT_WIDGET are by default focusable. +var + FPDFAnnot_GetFocusableSubtypes: function(hHandle: FPDF_FORMHANDLE; subtypes: PFPDF_ANNOTATION_SUBTYPE; + count: SIZE_T): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Gets FPDF_LINK object for |annot|. Intended to use for link annotations. +// +// annot - handle to an annotation. +// +// Returns FPDF_LINK from the FPDF_ANNOTATION and NULL on failure, +// if the input annot is NULL or input annot's subtype is not link. +var + FPDFAnnot_GetLink: function(annot: FPDF_ANNOTATION): FPDF_LINK; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Gets the count of annotations in the |annot|'s control group. +// A group of interactive form annotations is collectively called a form +// control group. Here, |annot|, an interactive form annotation, should be +// either a radio button or a checkbox. +// +// hHandle - handle to the form fill module, returned by +// FPDFDOC_InitFormFillEnvironment. +// annot - handle to an annotation. +// +// Returns number of controls in its control group or -1 on error. +var + FPDFAnnot_GetFormControlCount: function(hHandle: FPDF_FORMHANDLE; annot: FPDF_ANNOTATION): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Gets the index of |annot| in |annot|'s control group. +// A group of interactive form annotations is collectively called a form +// control group. Here, |annot|, an interactive form annotation, should be +// either a radio button or a checkbox. +// +// hHandle - handle to the form fill module, returned by +// FPDFDOC_InitFormFillEnvironment. +// annot - handle to an annotation. +// +// Returns index of a given |annot| in its control group or -1 on error. +var + FPDFAnnot_GetFormControlIndex: function(hHandle: FPDF_FORMHANDLE; annot: FPDF_ANNOTATION): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Gets the export value of |annot| which is an interactive form annotation. +// Intended for use with radio button and checkbox widget annotations. +// |buffer| is only modified if |buflen| is longer than the length of contents. +// In case of error, nothing will be added to |buffer| and the return value +// will be 0. Note that return value of empty string is 2 for "\0\0". +// +// hHandle - handle to the form fill module, returned by +// FPDFDOC_InitFormFillEnvironment(). +// annot - handle to an interactive form annotation. +// buffer - buffer for holding the value string, encoded in UTF-16LE. +// buflen - length of the buffer in bytes. +// +// Returns the length of the string value in bytes. +var + FPDFAnnot_GetFormFieldExportValue: function(hHandle: FPDF_FORMHANDLE; annot: FPDF_ANNOTATION; + buffer: PFPDF_WCHAR; buflen: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Add a URI action to |annot|, overwriting the existing action, if any. +// +// annot - handle to a link annotation. +// uri - the URI to be set, encoded in 7-bit ASCII. +// +// Returns true if successful. +var + FPDFAnnot_SetURI: function(annot: FPDF_ANNOTATION; uri: PAnsiChar): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Get the attachment from |annot|. +// +// annot - handle to a file annotation. +// +// Returns the handle to the attachment object, or NULL on failure. +var + FPDFAnnot_GetFileAttachment: function(annot: FPDF_ANNOTATION): FPDF_ATTACHMENT; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Add an embedded file with |name| to |annot|. +// +// annot - handle to a file annotation. +// name - name of the new attachment. +// +// Returns a handle to the new attachment object, or NULL on failure. +var + FPDFAnnot_AddFileAttachment: function(annot: FPDF_ANNOTATION; name: FPDF_WIDESTRING): FPDF_ATTACHMENT; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// *** _FPDF_CATALOG_H_ *** + +// Experimental API. +// +// Determine if |document| represents a tagged PDF. +// +// For the definition of tagged PDF, See (see 10.7 "Tagged PDF" in PDF +// Reference 1.7). +// +// document - handle to a document. +// +// Returns |true| iff |document| is a tagged PDF. var - FPDFAnnot_GetFontSize: function(hHandle: FPDF_FORMHANDLE; annot: FPDF_ANNOTATION; var value: Single): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + FPDFCatalog_IsTagged: function(document: FPDF_DOCUMENT): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // Experimental API. -// Determine if |annot| is a form widget that is checked. Intended for use with -// checkbox and radio button widgets. +// Gets the language of |document| from the catalog's /Lang entry. // -// hHandle - handle to the form fill module, returned by -// FPDFDOC_InitFormFillEnvironment. -// annot - handle to an annotation. +// document - handle to a document. +// buffer - a buffer for the language string. May be NULL. +// buflen - the length of the buffer, in bytes. May be 0. // -// Returns true if |annot| is a form widget and is checked, false otherwise. +// Returns the number of bytes in the language string, including the +// trailing NUL character. The number of bytes is returned regardless of the +// |buffer| and |buflen| parameters. +// +// Regardless of the platform, the |buffer| is always in UTF-16LE +// encoding. The string is terminated by a UTF16 NUL character. If +// |buflen| is less than the required length, or |buffer| is NULL, +// |buffer| will not be modified. +// +// If |document| has no /Lang entry, an empty string is written to |buffer| and +// 2 is returned. On error, nothing is written to |buffer| and 0 is returned. var - FPDFAnnot_IsChecked: function(hHandle: FPDF_FORMHANDLE; annot: FPDF_ANNOTATION): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + FPDFCatalog_GetLanguage: function(document: FPDF_DOCUMENT; buffer: PFPDF_WCHAR; buflen: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; - - -// *** _FPDF_CATALOG_H_ *** - -//** -//* Experimental API. -//* -//* Determine if |document| represents a tagged PDF. -//* -//* For the definition of tagged PDF, See (see 10.7 "Tagged PDF" in PDF -//* Reference 1.7). -//* -//* document - handle to a document. -//* -//* Returns |true| iff |document| is a tagged PDF. -//* +// Experimental API. +// Sets the language of |document| to |language|. +// +// document - handle to a document. +// language - the language to set to. +// +// Returns TRUE on success. var - FPDFCatalog_IsTagged: function(document: FPDF_DOCUMENT): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + FPDFCatalog_SetLanguage: function(document: FPDF_DOCUMENT; language: FPDF_WIDESTRING): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; // *** _FPDF_ATTACHMENT_H_ *** @@ -6519,20 +7957,44 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; // Returns true if successful. var FPDFAttachment_SetFile: function(attachment: FPDF_ATTACHMENT; document: FPDF_DOCUMENT; - contents: Pointer; const len: LongWord): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + contents: Pointer; len: LongWord): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // Experimental API. -// Get the file data of |attachment|. |buffer| is only modified if |buflen| is -// longer than the length of the file. On errors, |buffer| is unmodified and the -// returned length is 0. +// Get the file data of |attachment|. +// When the attachment file data is readable, true is returned, and |out_buflen| +// is updated to indicate the file data size. |buffer| is only modified if +// |buflen| is non-null and long enough to contain the entire file data. Callers +// must check both the return value and the input |buflen| is no less than the +// returned |out_buflen| before using the data. +// +// Otherwise, when the attachment file data is unreadable or when |out_buflen| +// is null, false is returned and |buffer| and |out_buflen| remain unmodified. // // attachment - handle to an attachment. // buffer - buffer for holding the file data from |attachment|. // buflen - length of the buffer in bytes. +// out_buflen - pointer to the variable that will receive the minimum buffer +// size to contain the file data of |attachment|. // -// Returns the length of the file. +// Returns true on success, false otherwise. var - FPDFAttachment_GetFile: function(attachment: FPDF_ATTACHMENT; buffer: Pointer; buflen: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + FPDFAttachment_GetFile: function(attachment: FPDF_ATTACHMENT; buffer: Pointer; buflen: LongWord; + var out_buflen: LongWord): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Experimental API. +// Get the MIME type (Subtype) of the embedded file |attachment|. |buffer| is +// only modified if |buflen| is longer than the length of the MIME type string. +// If the Subtype is not found or if there is no file stream, an empty string +// would be copied to |buffer| and the return value would be 2. On other errors, +// nothing would be added to |buffer| and the return value would be 0. +// +// attachment - handle to an attachment. +// buffer - buffer for holding the MIME type string encoded in UTF-16LE. +// buflen - length of the buffer in bytes. +// +// Returns the length of the MIME type string in bytes. +var + FPDFAttachment_GetSubtype: function(attachment: FPDF_ATTACHMENT; buffer: PFPDF_WCHAR; buflen: LongWord): Cardinal; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; // *** _FPDF_FWLEVENT_H_ *** @@ -6556,173 +8018,147 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; // *** _FPDF_TRANSFORMPAGE_H_ *** -//** -//* Set "MediaBox" entry to the page dictionary. -//* -//* page - Handle to a page. -//* left - The left of the rectangle. -//* bottom - The bottom of the rectangle. -//* right - The right of the rectangle. -//* top - The top of the rectangle. -//* +// Set "MediaBox" entry to the page dictionary. +// +// page - Handle to a page. +// left - The left of the rectangle. +// bottom - The bottom of the rectangle. +// right - The right of the rectangle. +// top - The top of the rectangle. var FPDFPage_SetMediaBox: procedure(page: FPDF_PAGE; left, bottom, right, top: Single); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//** -//* Set "CropBox" entry to the page dictionary. -//* -//* page - Handle to a page. -//* left - The left of the rectangle. -//* bottom - The bottom of the rectangle. -//* right - The right of the rectangle. -//* top - The top of the rectangle. -//* +// Set "CropBox" entry to the page dictionary. +// +// page - Handle to a page. +// left - The left of the rectangle. +// bottom - The bottom of the rectangle. +// right - The right of the rectangle. +// top - The top of the rectangle. var FPDFPage_SetCropBox: procedure(page: FPDF_PAGE; left, bottom, right, top: Single); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//** -//* Set "BleedBox" entry to the page dictionary. -//* -//* page - Handle to a page. -//* left - The left of the rectangle. -//* bottom - The bottom of the rectangle. -//* right - The right of the rectangle. -//* top - The top of the rectangle. -//* +// Set "BleedBox" entry to the page dictionary. +// +// page - Handle to a page. +// left - The left of the rectangle. +// bottom - The bottom of the rectangle. +// right - The right of the rectangle. +// top - The top of the rectangle. var FPDFPage_SetBleedBox: procedure(page: FPDF_PAGE; left, bottom, right, top: Single); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; - -//** -//* Set "TrimBox" entry to the page dictionary. -//* -//* page - Handle to a page. -//* left - The left of the rectangle. -//* bottom - The bottom of the rectangle. -//* right - The right of the rectangle. -//* top - The top of the rectangle. -//* +// Set "TrimBox" entry to the page dictionary. +// +// page - Handle to a page. +// left - The left of the rectangle. +// bottom - The bottom of the rectangle. +// right - The right of the rectangle. +// top - The top of the rectangle. var FPDFPage_SetTrimBox: procedure(page: FPDF_PAGE; left, bottom, right, top: Single); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; - -//** -//* Set "ArtBox" entry to the page dictionary. -//* -//* page - Handle to a page. -//* left - The left of the rectangle. -//* bottom - The bottom of the rectangle. -//* right - The right of the rectangle. -//* top - The top of the rectangle. -//* +// Set "ArtBox" entry to the page dictionary. +// +// page - Handle to a page. +// left - The left of the rectangle. +// bottom - The bottom of the rectangle. +// right - The right of the rectangle. +// top - The top of the rectangle. var FPDFPage_SetArtBox: procedure(page: FPDF_PAGE; left, bottom, right, top: Single); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//** -//* Get "MediaBox" entry from the page dictionary. -//* -//* page - Handle to a page. -//* left - Pointer to a float value receiving the left of the rectangle. -//* bottom - Pointer to a float value receiving the bottom of the rectangle. -//* right - Pointer to a float value receiving the right of the rectangle. -//* top - Pointer to a float value receiving the top of the rectangle. -//* -//* On success, return true and write to the out parameters. Otherwise return -//* false and leave the out parameters unmodified. -//* +// Get "MediaBox" entry from the page dictionary. +// +// page - Handle to a page. +// left - Pointer to a float value receiving the left of the rectangle. +// bottom - Pointer to a float value receiving the bottom of the rectangle. +// right - Pointer to a float value receiving the right of the rectangle. +// top - Pointer to a float value receiving the top of the rectangle. +// +// On success, return true and write to the out parameters. Otherwise return +// false and leave the out parameters unmodified. var FPDFPage_GetMediaBox: procedure(page: FPDF_PAGE; var left, bottom, right, top: Single); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//** -//* Get "CropBox" entry from the page dictionary. -//* -//* page - Handle to a page. -//* left - Pointer to a float value receiving the left of the rectangle. -//* bottom - Pointer to a float value receiving the bottom of the rectangle. -//* right - Pointer to a float value receiving the right of the rectangle. -//* top - Pointer to a float value receiving the top of the rectangle. -//* -//* On success, return true and write to the out parameters. Otherwise return -//* false and leave the out parameters unmodified. -//* +// Get "CropBox" entry from the page dictionary. +// +// page - Handle to a page. +// left - Pointer to a float value receiving the left of the rectangle. +// bottom - Pointer to a float value receiving the bottom of the rectangle. +// right - Pointer to a float value receiving the right of the rectangle. +// top - Pointer to a float value receiving the top of the rectangle. +// +// On success, return true and write to the out parameters. Otherwise return +// false and leave the out parameters unmodified. var FPDFPage_GetCropBox: procedure(page: FPDF_PAGE; var left, bottom, right, top: Single); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//** -//* Get "BleedBox" entry from the page dictionary. -//* -//* page - Handle to a page. -//* left - Pointer to a float value receiving the left of the rectangle. -//* bottom - Pointer to a float value receiving the bottom of the rectangle. -//* right - Pointer to a float value receiving the right of the rectangle. -//* top - Pointer to a float value receiving the top of the rectangle. -//* -//* On success, return true and write to the out parameters. Otherwise return -//* false and leave the out parameters unmodified. -//* +// Get "BleedBox" entry from the page dictionary. +// +// page - Handle to a page. +// left - Pointer to a float value receiving the left of the rectangle. +// bottom - Pointer to a float value receiving the bottom of the rectangle. +// right - Pointer to a float value receiving the right of the rectangle. +// top - Pointer to a float value receiving the top of the rectangle. +// +// On success, return true and write to the out parameters. Otherwise return +// false and leave the out parameters unmodified. var FPDFPage_GetBleedBox: procedure(page: FPDF_PAGE; var left, bottom, right, top: Single); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//** -//* Get "TrimBox" entry from the page dictionary. -//* -//* page - Handle to a page. -//* left - Pointer to a float value receiving the left of the rectangle. -//* bottom - Pointer to a float value receiving the bottom of the rectangle. -//* right - Pointer to a float value receiving the right of the rectangle. -//* top - Pointer to a float value receiving the top of the rectangle. -//* -//* On success, return true and write to the out parameters. Otherwise return -//* false and leave the out parameters unmodified. -//* +// Get "TrimBox" entry from the page dictionary. +// +// page - Handle to a page. +// left - Pointer to a float value receiving the left of the rectangle. +// bottom - Pointer to a float value receiving the bottom of the rectangle. +// right - Pointer to a float value receiving the right of the rectangle. +// top - Pointer to a float value receiving the top of the rectangle. +// +// On success, return true and write to the out parameters. Otherwise return +// false and leave the out parameters unmodified. var FPDFPage_GetTrimBox: procedure(page: FPDF_PAGE; var left, bottom, right, top: Single); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//** -//* Get "ArtBox" entry from the page dictionary. -//* -//* page - Handle to a page. -//* left - Pointer to a float value receiving the left of the rectangle. -//* bottom - Pointer to a float value receiving the bottom of the rectangle. -//* right - Pointer to a float value receiving the right of the rectangle. -//* top - Pointer to a float value receiving the top of the rectangle. -//* -//* On success, return true and write to the out parameters. Otherwise return -//* false and leave the out parameters unmodified. -//* +// Get "ArtBox" entry from the page dictionary. +// +// page - Handle to a page. +// left - Pointer to a float value receiving the left of the rectangle. +// bottom - Pointer to a float value receiving the bottom of the rectangle. +// right - Pointer to a float value receiving the right of the rectangle. +// top - Pointer to a float value receiving the top of the rectangle. +// +// On success, return true and write to the out parameters. Otherwise return +// false and leave the out parameters unmodified. var FPDFPage_GetArtBox: procedure(page: FPDF_PAGE; var left, bottom, right, top: Single); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//** -//* Apply transforms to |page|. -//* -//* If |matrix| is provided it will be applied to transform the page. -//* If |clipRect| is provided it will be used to clip the resulting page. -//* If neither |matrix| or |clipRect| are provided this method returns |false|. -//* Returns |true| if transforms are applied. -//* -//* This function will transform the whole page, and would take effect to all the -//* objects in the page. -//* -//* page - Page handle. -//* matrix - Transform matrix. -//* clipRect - Clipping rectangle. -//* +// Apply transforms to |page|. +// +// If |matrix| is provided it will be applied to transform the page. +// If |clipRect| is provided it will be used to clip the resulting page. +// If neither |matrix| or |clipRect| are provided this method returns |false|. +// Returns |true| if transforms are applied. +// +// This function will transform the whole page, and would take effect to all the +// objects in the page. +// +// page - Page handle. +// matrix - Transform matrix. +// clipRect - Clipping rectangle. var FPDFPage_TransFormWithClip: function(page: FPDF_PAGE; matrix: PFS_MATRIX; clipRect: PFS_RECTF): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//** -//* Transform (scale, rotate, shear, move) the clip path of page object. -//* page_object - Handle to a page object. Returned by -//* FPDFPageObj_NewImageObj(). -//* -//* a - The coefficient "a" of the matrix. -//* b - The coefficient "b" of the matrix. -//* c - The coefficient "c" of the matrix. -//* d - The coefficient "d" of the matrix. -//* e - The coefficient "e" of the matrix. -//* f - The coefficient "f" of the matrix. -//* +// Transform (scale, rotate, shear, move) the clip path of page object. +// page_object - Handle to a page object. Returned by +// FPDFPageObj_NewImageObj(). +// +// a - The coefficient "a" of the matrix. +// b - The coefficient "b" of the matrix. +// c - The coefficient "c" of the matrix. +// d - The coefficient "d" of the matrix. +// e - The coefficient "e" of the matrix. +// f - The coefficient "f" of the matrix. var FPDFPageObj_TransformClipPath: procedure(page_object: FPDF_PAGEOBJECT; a, b, c, d, e, f: Double); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; @@ -6732,9 +8168,9 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; // page object - Handle to a page object. Returned by e.g. // FPDFPage_GetObject(). // -// Caller does not take ownership of the returned FPDF_CLIPPATH. Instead, it -// remains valid until FPDF_ClosePage() is called for the page containing -// page_object. +// Returns the handle to the clip path, or NULL on failure. The caller does not +// take ownership of the returned FPDF_CLIPPATH. Instead, it remains valid until +// FPDF_ClosePage() is called for the page containing |page_object|. var FPDFPageObj_GetClipPath: function(page_object: FPDF_PAGEOBJECT): FPDF_CLIPPATH; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; @@ -6764,44 +8200,38 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; // path_index - the index of a path. // segment_index - the index of a segment. // -// Returns the handle to the segment, or NULL on failure. The caller does not -// take ownership of the returned FPDF_CLIPPATH. Instead, it remains valid until -// FPDF_ClosePage() is called for the page containing page_object. +// Returns the handle to the segment, or NULL on failure. The caller does not +// take ownership of the returned FPDF_PATHSEGMENT. Instead, it remains valid +// until FPDF_ClosePage() is called for the page containing |clip_path|. var FPDFClipPath_GetPathSegment: function(clip_path: FPDF_CLIPPATH; path_index, segment_index: Integer): FPDF_PATHSEGMENT; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//** -//* Create a new clip path, with a rectangle inserted. -//* -//* Caller takes ownership of the returned FPDF_CLIPPATH. It should be freed with -//* FPDF_DestroyClipPath(). -//* -//* left - The left of the clip box. -//* bottom - The bottom of the clip box. -//* right - The right of the clip box. -//* top - The top of the clip box. -//* +// Create a new clip path, with a rectangle inserted. +// +// Caller takes ownership of the returned FPDF_CLIPPATH. It should be freed with +// FPDF_DestroyClipPath(). +// +// left - The left of the clip box. +// bottom - The bottom of the clip box. +// right - The right of the clip box. +// top - The top of the clip box. var FPDF_CreateClipPath: function(page_object: FPDF_PAGEOBJECT; left, bottom, right, top: Single): FPDF_CLIPPATH; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//** -//* Destroy the clip path. -//* -//* clipPath - A handle to the clip path. It will be invalid after this call. -//* +// Destroy the clip path. +// +// clipPath - A handle to the clip path. It will be invalid after this call. var FPDF_DestroyClipPath: procedure(clipPath: FPDF_CLIPPATH); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -//** -//* Clip the page content, the page content that outside the clipping region -//* become invisible. -//* -//* A clip path will be inserted before the page content stream or content array. -//* In this way, the page content will be clipped by this clip path. -//* -//* page - A page handle. -//* clipPath - A handle to the clip path. (Does not take ownership.) -//* +// Clip the page content, the page content that outside the clipping region +// become invisible. +// +// A clip path will be inserted before the page content stream or content array. +// In this way, the page content will be clipped by this clip path. +// +// page - A page handle. +// clipPath - A handle to the clip path. (Does not take ownership.) var FPDFPage_InsertClipPath: procedure(page: FPDF_PAGE; clipPath: FPDF_CLIPPATH); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; @@ -6813,7 +8243,9 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; // Parameters: // page - Handle to the page, as returned by FPDF_LoadPage(). // Return value: -// A handle to the structure tree or NULL on error. +// A handle to the structure tree or NULL on error. The caller owns the +// returned handle and must use FPDF_StructTree_Close() to release it. +// The handle should be released before |page| gets released. var FPDF_StructTree_GetForPage: function(page: FPDF_PAGE): FPDF_STRUCTTREE; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; @@ -6844,7 +8276,12 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; // FPDF_StructTree_LoadPage(). // index - The index for the child, 0-based. // Return value: -// The child at the n-th index or NULL on error. +// The child at the n-th index or NULL on error. The caller does not +// own the handle. The handle remains valid as long as |struct_tree| +// remains valid. +// Comments: +// The |index| must be less than the FPDF_StructTree_CountChildren() +// return value. var FPDF_StructTree_GetChildAtIndex: function(struct_tree: FPDF_STRUCTTREE; index: Integer): FPDF_STRUCTELEMENT; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; @@ -6855,7 +8292,7 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; // buffer - A buffer for output the alt text. May be NULL. // buflen - The length of the buffer, in bytes. May be 0. // Return value: -// The number of bytes in the title, including the terminating NUL +// The number of bytes in the alt text, including the terminating NUL // character. The number of bytes is returned regardless of the // |buffer| and |buflen| parameters. // Comments: @@ -6866,6 +8303,103 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; var FPDF_StructElement_GetAltText: function(struct_element: FPDF_STRUCTELEMENT; buffer: Pointer; buflen: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Experimental API. +// Function: FPDF_StructElement_GetActualText +// Get the actual text for a given element. +// Parameters: +// struct_element - Handle to the struct element. +// buffer - A buffer for output the actual text. May be NULL. +// buflen - The length of the buffer, in bytes. May be 0. +// Return value: +// The number of bytes in the actual text, including the terminating +// NUL character. The number of bytes is returned regardless of the +// |buffer| and |buflen| parameters. +// Comments: +// Regardless of the platform, the |buffer| is always in UTF-16LE +// encoding. The string is terminated by a UTF16 NUL character. If +// |buflen| is less than the required length, or |buffer| is NULL, +// |buffer| will not be modified. +var + FPDF_StructElement_GetActualText: function(struct_element: FPDF_STRUCTELEMENT; buffer: Pointer; buflen: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Function: FPDF_StructElement_GetExpansion +// Get the expansion of an abbreviation or acronym for a given element. +// Parameters: +// struct_element - Handle to the struct element. +// buffer - A buffer for output the expansion text. May be +// NULL. +// buflen - The length of the buffer, in bytes. May be 0. +// Return value: +// The number of bytes in the expansion text, including the terminating +// NUL character. The number of bytes is returned regardless of the +// |buffer| and |buflen| parameters. +// Comments: +// Regardless of the platform, the |buffer| is always in UTF-16LE +// encoding. The string is terminated by a UTF16 NUL character. If +// |buflen| is less than the required length, or |buffer| is NULL, +// |buffer| will not be modified. +var + FPDF_StructElement_GetExpansion: function(struct_element: FPDF_STRUCTELEMENT; buffer: Pointer; buflen: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Function: FPDF_StructElement_GetID +// Get the ID for a given element. +// Parameters: +// struct_element - Handle to the struct element. +// buffer - A buffer for output the ID string. May be NULL. +// buflen - The length of the buffer, in bytes. May be 0. +// Return value: +// The number of bytes in the ID string, including the terminating NUL +// character. The number of bytes is returned regardless of the +// |buffer| and |buflen| parameters. +// Comments: +// Regardless of the platform, the |buffer| is always in UTF-16LE +// encoding. The string is terminated by a UTF16 NUL character. If +// |buflen| is less than the required length, or |buffer| is NULL, +// |buffer| will not be modified. +var + FPDF_StructElement_GetID: function(struct_element: FPDF_STRUCTELEMENT; buffer: Pointer; buflen: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Function: FPDF_StructElement_GetLang +// Get the case-insensitive IETF BCP 47 language code for an element. +// Parameters: +// struct_element - Handle to the struct element. +// buffer - A buffer for output the lang string. May be NULL. +// buflen - The length of the buffer, in bytes. May be 0. +// Return value: +// The number of bytes in the ID string, including the terminating NUL +// character. The number of bytes is returned regardless of the +// |buffer| and |buflen| parameters. +// Comments: +// Regardless of the platform, the |buffer| is always in UTF-16LE +// encoding. The string is terminated by a UTF16 NUL character. If +// |buflen| is less than the required length, or |buffer| is NULL, +// |buffer| will not be modified. +var + FPDF_StructElement_GetLang: function(struct_element: FPDF_STRUCTELEMENT; buffer: Pointer; buflen: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Function: FPDF_StructElement_GetStringAttribute +// Get a struct element attribute of type "name" or "string". +// Parameters: +// struct_element - Handle to the struct element. +// attr_name - The name of the attribute to retrieve. +// buffer - A buffer for output. May be NULL. +// buflen - The length of the buffer, in bytes. May be 0. +// Return value: +// The number of bytes in the attribute value, including the +// terminating NUL character. The number of bytes is returned +// regardless of the |buffer| and |buflen| parameters. +// Comments: +// Regardless of the platform, the |buffer| is always in UTF-16LE +// encoding. The string is terminated by a UTF16 NUL character. If +// |buflen| is less than the required length, or |buffer| is NULL, +// |buffer| will not be modified. +var + FPDF_StructElement_GetStringAttribute: function(struct_element: FPDF_STRUCTELEMENT; + attr_name: FPDF_BYTESTRING; buffer: Pointer; buflen: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // Function: FPDF_StructElement_GetMarkedContentID // Get the marked content ID for a given element. // Parameters: @@ -6873,6 +8407,10 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; // Return value: // The marked content ID of the element. If no ID exists, returns // -1. +// Comments: +// FPDF_StructElement_GetMarkedContentIdAtIndex() may be able to +// extract more marked content IDs out of |struct_element|. This API +// may be deprecated in the future. var FPDF_StructElement_GetMarkedContentID: function(struct_element: FPDF_STRUCTELEMENT): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; @@ -6880,8 +8418,8 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; // Get the type (/S) for a given element. // Parameters: // struct_element - Handle to the struct element. -// buffer - A buffer for output. May be NULL. -// buflen - The length of the buffer, in bytes. May be 0. +// buffer - A buffer for output. May be NULL. +// buflen - The length of the buffer, in bytes. May be 0. // Return value: // The number of bytes in the type, including the terminating NUL // character. The number of bytes is returned regardless of the @@ -6894,6 +8432,25 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; var FPDF_StructElement_GetType: function(struct_element: FPDF_STRUCTELEMENT; buffer: Pointer; buflen: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Experimental API. +// Function: FPDF_StructElement_GetObjType +// Get the object type (/Type) for a given element. +// Parameters: +// struct_element - Handle to the struct element. +// buffer - A buffer for output. May be NULL. +// buflen - The length of the buffer, in bytes. May be 0. +// Return value: +// The number of bytes in the object type, including the terminating +// NUL character. The number of bytes is returned regardless of the +// |buffer| and |buflen| parameters. +// Comments: +// Regardless of the platform, the |buffer| is always in UTF-16LE +// encoding. The string is terminated by a UTF16 NUL character. If +// |buflen| is less than the required length, or |buffer| is NULL, +// |buffer| will not be modified. +var + FPDF_StructElement_GetObjType: function(struct_element: FPDF_STRUCTELEMENT; buffer: Pointer; buflen: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // Function: FPDF_StructElement_GetTitle // Get the title (/T) for a given element. // Parameters: @@ -6924,34 +8481,259 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; // Function: FPDF_StructElement_GetChildAtIndex // Get a child in the structure element. // Parameters: -// struct_tree - Handle to the struct element. -// index - The index for the child, 0-based. +// struct_element - Handle to the struct element. +// index - The index for the child, 0-based. // Return value: // The child at the n-th index or NULL on error. // Comments: // If the child exists but is not an element, then this function will // return NULL. This will also return NULL for out of bounds indices. +// The |index| must be less than the FPDF_StructElement_CountChildren() +// return value. var FPDF_StructElement_GetChildAtIndex: function(struct_element: FPDF_STRUCTELEMENT; index: Integer): FPDF_STRUCTELEMENT; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Experimental API. +// Function: FPDF_StructElement_GetChildMarkedContentID +// Get the child's content id +// Parameters: +// struct_element - Handle to the struct element. +// index - The index for the child, 0-based. +// Return value: +// The marked content ID of the child. If no ID exists, returns -1. +// Comments: +// If the child exists but is not a stream or object, then this +// function will return -1. This will also return -1 for out of bounds +// indices. Compared to FPDF_StructElement_GetMarkedContentIdAtIndex, +// it is scoped to the current page. +// The |index| must be less than the FPDF_StructElement_CountChildren() +// return value. +var + FPDF_StructElement_GetChildMarkedContentID: function(struct_element: FPDF_STRUCTELEMENT; index: Integer): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -// *** _FPDF_LIBS_H_ *** +// Experimental API. +// Function: FPDF_StructElement_GetParent +// Get the parent of the structure element. +// Parameters: +// struct_element - Handle to the struct element. +// Return value: +// The parent structure element or NULL on error. +// Comments: +// If structure element is StructTreeRoot, then this function will +// return NULL. +var + FPDF_StructElement_GetParent: function(struct_element: FPDF_STRUCTELEMENT): FPDF_STRUCTELEMENT; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -{$IFDEF PDF_ENABLE_V8} +// Function: FPDF_StructElement_GetAttributeCount +// Count the number of attributes for the structure element. +// Parameters: +// struct_element - Handle to the struct element. +// Return value: +// The number of attributes, or -1 on error. +var + FPDF_StructElement_GetAttributeCount: function(struct_element: FPDF_STRUCTELEMENT): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -// Function: FPDF_InitEmbeddedLibraries -// Initialize embedded libraries (v8, iuctl) included in pdfium +// Experimental API. +// Function: FPDF_StructElement_GetAttributeAtIndex +// Get an attribute object in the structure element. // Parameters: -// resourcePath - a path to v8 resources (snapshot_blob.bin, icudtl.dat, ...) +// struct_element - Handle to the struct element. +// index - The index for the attribute object, 0-based. // Return value: -// None. +// The attribute object at the n-th index or NULL on error. // Comments: -// This function must be called before calling FPDF_InitLibrary() -// if v8 suppport is enabled +// If the attribute object exists but is not a dict, then this +// function will return NULL. This will also return NULL for out of +// bounds indices. The caller does not own the handle. The handle +// remains valid as long as |struct_element| remains valid. +// The |index| must be less than the +// FPDF_StructElement_GetAttributeCount() return value. var - FPDF_InitEmbeddedLibraries: procedure(const resourcePath: PAnsiChar); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -{$ENDIF PDF_ENABLE_V8} + FPDF_StructElement_GetAttributeAtIndex: function(struct_element: FPDF_STRUCTELEMENT; index: Integer): FPDF_STRUCTELEMENT_ATTR; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Function: FPDF_StructElement_Attr_GetCount +// Count the number of attributes in a structure element attribute map. +// Parameters: +// struct_attribute - Handle to the struct element attribute. +// Return value: +// The number of attributes, or -1 on error. +var + FPDF_StructElement_Attr_GetCount: function(struct_attribute: FPDF_STRUCTELEMENT_ATTR): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + + +// Experimental API. +// Function: FPDF_StructElement_Attr_GetName +// Get the name of an attribute in a structure element attribute map. +// Parameters: +// struct_attribute - Handle to the struct element attribute. +// index - The index of attribute in the map. +// buffer - A buffer for output. May be NULL. This is only +// modified if |buflen| is longer than the length +// of the key. Optional, pass null to just +// retrieve the size of the buffer needed. +// buflen - The length of the buffer. +// out_buflen - A pointer to variable that will receive the +// minimum buffer size to contain the key. Not +// filled if FALSE is returned. +// Return value: +// TRUE if the operation was successful, FALSE otherwise. +var + FPDF_StructElement_Attr_GetName: function(struct_attribute: FPDF_STRUCTELEMENT_ATTR; index: Integer; buffer: Pointer; + buflen: LongWord; var out_buflen: LongWord): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Function: FPDF_StructElement_Attr_GetValue +// Get a handle to a value for an attribute in a structure element +// attribute map. +// Parameters: +// struct_attribute - Handle to the struct element attribute. +// name - The attribute name. +// Return value: +// Returns a handle to the value associated with the input, if any. +// Returns NULL on failure. The caller does not own the handle. +// The handle remains valid as long as |struct_attribute| remains +// valid. +var + FPDF_StructElement_Attr_GetValue: function(struct_attribute: FPDF_STRUCTELEMENT_ATTR; + name: FPDF_BYTESTRING): FPDF_STRUCTELEMENT_ATTR_VALUE; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Function: FPDF_StructElement_Attr_GetType +// Get the type of an attribute in a structure element attribute map. +// Parameters: +// value - Handle to the value. +// Return value: +// Returns the type of the value, or FPDF_OBJECT_UNKNOWN in case of +// failure. Note that this will never return FPDF_OBJECT_REFERENCE, as +// references are always dereferenced. +var + FPDF_StructElement_Attr_GetType: function(struct_attribute: FPDF_STRUCTELEMENT_ATTR_VALUE): FPDF_OBJECT_TYPE; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Function: FPDF_StructElement_Attr_GetBooleanValue +// Get the value of a boolean attribute in an attribute map as +// FPDF_BOOL. FPDF_StructElement_Attr_GetType() should have returned +// FPDF_OBJECT_BOOLEAN for this property. +// Parameters: +// value - Handle to the value. +// out_value - A pointer to variable that will receive the value. Not +// filled if false is returned. +// Return value: +// Returns TRUE if the attribute maps to a boolean value, FALSE +// otherwise. +var + FPDF_StructElement_Attr_GetBooleanValue: function(value: FPDF_STRUCTELEMENT_ATTR_VALUE; + var out_value: FPDF_BOOL): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Function: FPDF_StructElement_Attr_GetNumberValue +// Get the value of a number attribute in an attribute map as float. +// FPDF_StructElement_Attr_GetType() should have returned +// FPDF_OBJECT_NUMBER for this property. +// Parameters: +// value - Handle to the value. +// out_value - A pointer to variable that will receive the value. Not +// filled if false is returned. +// Return value: +// Returns TRUE if the attribute maps to a number value, FALSE +// otherwise. +var + FPDF_StructElement_Attr_GetNumberValue: function(value: FPDF_STRUCTELEMENT_ATTR_VALUE; + var out_value: Single): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Function: FPDF_StructElement_Attr_GetStringValue +// Get the value of a string attribute in an attribute map as string. +// FPDF_StructElement_Attr_GetType() should have returned +// FPDF_OBJECT_STRING or FPDF_OBJECT_NAME for this property. +// Parameters: +// value - Handle to the value. +// buffer - A buffer for holding the returned key in UTF-16LE. +// This is only modified if |buflen| is longer than the +// length of the key. Optional, pass null to just +// retrieve the size of the buffer needed. +// buflen - The length of the buffer. +// out_buflen - A pointer to variable that will receive the minimum +// buffer size to contain the key. Not filled if FALSE is +// returned. +// Return value: +// Returns TRUE if the attribute maps to a string value, FALSE +// otherwise. +var + FPDF_StructElement_Attr_GetStringValue: function(value: FPDF_STRUCTELEMENT_ATTR; buffer: Pointer; buflen: LongWord; + var out_buflen: LongWord): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Function: FPDF_StructElement_Attr_GetBlobValue +// Get the value of a blob attribute in an attribute map as string. +// Parameters: +// value - Handle to the value. +// buffer - A buffer for holding the returned value. This is only +// modified if |buflen| is at least as long as the length +// of the value. Optional, pass null to just retrieve the +// size of the buffer needed. +// buflen - The length of the buffer. +// out_buflen - A pointer to variable that will receive the minimum +// buffer size to contain the key. Not filled if FALSE is +// returned. +// Return value: +// Returns TRUE if the attribute maps to a string value, FALSE +// otherwise. +var + FPDF_StructElement_Attr_GetBlobValue: function(value: FPDF_STRUCTELEMENT_ATTR; buffer: Pointer; buflen: LongWord; + var out_buflen: LongWord): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Function: FPDF_StructElement_Attr_CountChildren +// Count the number of children values in an attribute. +// Parameters: +// value - Handle to the value. +// Return value: +// The number of children, or -1 on error. +var + FPDF_StructElement_Attr_CountChildren: function(value: FPDF_STRUCTELEMENT_ATTR_VALUE): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Function: FPDF_StructElement_Attr_GetChildAtIndex +// Get a child from an attribute. +// Parameters: +// value - Handle to the value. +// index - The index for the child, 0-based. +// Return value: +// The child at the n-th index or NULL on error. +// Comments: +// The |index| must be less than the +// FPDF_StructElement_Attr_CountChildren() return value. +var + FPDF_StructElement_Attr_GetChildAtIndex: function(value: FPDF_STRUCTELEMENT_ATTR_VALUE; + index: Integer): FPDF_STRUCTELEMENT_ATTR_VALUE; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Function: FPDF_StructElement_GetMarkedContentIdCount +// Get the count of marked content ids for a given element. +// Parameters: +// struct_element - Handle to the struct element. +// Return value: +// The count of marked content ids or -1 if none exists. +var + FPDF_StructElement_GetMarkedContentIdCount: function(struct_element: FPDF_STRUCTELEMENT): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Experimental API. +// Function: FPDF_StructElement_GetMarkedContentIdAtIndex +// Get the marked content id at a given index for a given element. +// Parameters: +// struct_element - Handle to the struct element. +// index - The index of the marked content id, 0-based. +// Return value: +// The marked content ID of the element. If no ID exists, returns +// -1. +// Comments: +// The |index| must be less than the +// FPDF_StructElement_GetMarkedContentIdCount() return value. +// This will likely supersede FPDF_StructElement_GetMarkedContentID(). +var + FPDF_StructElement_GetMarkedContentIdAtIndex: function(struct_element: FPDF_STRUCTELEMENT; index: Integer): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; // *** _FPDF_JAVASCRIPT_H_ *** @@ -7051,8 +8833,8 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; // *********************************************************************** -procedure InitPDFium(const DllPath: string = '' {$IFDEF PDF_ENABLE_V8}; const ResPath: string = ''{$ENDIF}); -procedure InitPDFiumEx(const DllFileName: string{$IFDEF PDF_ENABLE_V8}; const ResPath: string{$ENDIF}); +procedure InitPDFium(const DllPath: string = ''); +procedure InitPDFiumEx(const DllFileName: string); implementation @@ -7115,433 +8897,553 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; type TImportFuncRec = record P: PPointer; + {$IF defined(FPC) and not defined(MSWINDOWS)} + N: AnsiString; // The "dynlibs" unit's GetProcAddress uses an AnsiString instead of PAnsiChar + {$ELSE} N: PAnsiChar; - Quirk: Boolean; // True: if the symbol can't be found, no exception is raised + {$IFEND} + Quirk: Boolean; // True: if the symbol can't be found, no exception is raised. If both Quirk + // and Optional are True and the symbol can't be found, it will be mapped + // to FunctionNotSupported. // (used if the symbol's name has changed and both DLL versions should be supported) Optional: Boolean; // True: If the symbol can't be found, it is set to nil. // (used for optional exported features like V8 and XFA) end; const - ImportFuncs: array[0..338 - {$IFDEF MSWINDOWS} - + 2 - {$IFDEF PDFIUM_PRINT_TEXT_WITH_GDI} + 2 {$ENDIF} - {$IFDEF _SKIA_SUPPORT_ } + 2 {$ENDIF} - {$IFDEF PDF_ENABLE_V8 } + 2 {$ENDIF} - {$IFDEF PDF_ENABLE_XFA } + 3 {$ENDIF} - {$ENDIF} + {$IFDEF FPC} + {$WARN 3175 off : Some fields coming before "$1" were not initialized} + {$WARN 3177 off : Some fields coming after "$1" were not initialized} + {$ENDIF FPC} + ImportFuncs: array[0..453 + {$IFDEF MSWINDOWS } + 2 {$ENDIF} + {$IFDEF PDF_USE_SKIA } + 2 {$ENDIF} + {$IFDEF PDF_ENABLE_V8 } + 2 {$ENDIF} + {$IFDEF PDF_ENABLE_XFA} + 3 {$ENDIF} ] of TImportFuncRec = ( // *** _FPDFVIEW_H_ *** - (P: @@FPDF_InitLibrary; N: 'FPDF_InitLibrary'), - (P: @@FPDF_InitLibraryWithConfig; N: 'FPDF_InitLibraryWithConfig'), - (P: @@FPDF_DestroyLibrary; N: 'FPDF_DestroyLibrary'), - (P: @@FPDF_SetSandBoxPolicy; N: 'FPDF_SetSandBoxPolicy'), + (P: @@FPDF_InitLibraryWithConfig; N: 'FPDF_InitLibraryWithConfig'), + (P: @@FPDF_InitLibrary; N: 'FPDF_InitLibrary'), + (P: @@FPDF_DestroyLibrary; N: 'FPDF_DestroyLibrary'), + (P: @@FPDF_SetSandBoxPolicy; N: 'FPDF_SetSandBoxPolicy'), {$IFDEF MSWINDOWS} - {$IFDEF PDFIUM_PRINT_TEXT_WITH_GDI} - (P: @@FPDF_SetTypefaceAccessibleFunc; N: 'FPDF_SetTypefaceAccessibleFunc'), - (P: @@FPDF_SetPrintTextWithGDI; N: 'FPDF_SetPrintTextWithGDI'), - {$ENDIF PDFIUM_PRINT_TEXT_WITH_GDI} - (P: @@FPDF_SetPrintMode; N: 'FPDF_SetPrintMode'), + (P: @@FPDF_SetPrintMode; N: 'FPDF_SetPrintMode'), {$ENDIF MSWINDOWS} - (P: @@FPDF_LoadDocument; N: 'FPDF_LoadDocument'), - (P: @@FPDF_LoadMemDocument; N: 'FPDF_LoadMemDocument'), - (P: @@FPDF_LoadCustomDocument; N: 'FPDF_LoadCustomDocument'), - (P: @@FPDF_GetFileVersion; N: 'FPDF_GetFileVersion'), - (P: @@FPDF_GetLastError; N: 'FPDF_GetLastError'), - (P: @@FPDF_DocumentHasValidCrossReferenceTable; N: 'FPDF_DocumentHasValidCrossReferenceTable'), - (P: @@FPDF_GetDocPermissions; N: 'FPDF_GetDocPermissions'), - (P: @@FPDF_GetSecurityHandlerRevision; N: 'FPDF_GetSecurityHandlerRevision'), - (P: @@FPDF_GetPageCount; N: 'FPDF_GetPageCount'), - (P: @@FPDF_LoadPage; N: 'FPDF_LoadPage'), - (P: @@FPDF_GetPageWidthF; N: 'FPDF_GetPageWidthF'), - (P: @@FPDF_GetPageWidth; N: 'FPDF_GetPageWidth'), - (P: @@FPDF_GetPageHeightF; N: 'FPDF_GetPageHeightF'), - (P: @@FPDF_GetPageHeight; N: 'FPDF_GetPageHeight'), - (P: @@FPDF_GetPageBoundingBox; N: 'FPDF_GetPageBoundingBox'), - (P: @@FPDF_GetPageSizeByIndexF; N: 'FPDF_GetPageSizeByIndexF'), - (P: @@FPDF_GetPageSizeByIndex; N: 'FPDF_GetPageSizeByIndex'), + (P: @@FPDF_LoadDocument; N: 'FPDF_LoadDocument'), + (P: @@FPDF_LoadMemDocument; N: 'FPDF_LoadMemDocument'), + (P: @@FPDF_LoadMemDocument64; N: 'FPDF_LoadMemDocument64'), + (P: @@FPDF_LoadCustomDocument; N: 'FPDF_LoadCustomDocument'), + (P: @@FPDF_GetFileVersion; N: 'FPDF_GetFileVersion'), + (P: @@FPDF_GetLastError; N: 'FPDF_GetLastError'), + (P: @@FPDF_DocumentHasValidCrossReferenceTable; N: 'FPDF_DocumentHasValidCrossReferenceTable'), + (P: @@FPDF_GetTrailerEnds; N: 'FPDF_GetTrailerEnds'), + (P: @@FPDF_GetDocPermissions; N: 'FPDF_GetDocPermissions'), + (P: @@FPDF_GetDocUserPermissions; N: 'FPDF_GetDocUserPermissions'), + (P: @@FPDF_GetSecurityHandlerRevision; N: 'FPDF_GetSecurityHandlerRevision'), + (P: @@FPDF_GetPageCount; N: 'FPDF_GetPageCount'), + (P: @@FPDF_LoadPage; N: 'FPDF_LoadPage'), + (P: @@FPDF_GetPageWidthF; N: 'FPDF_GetPageWidthF'), + (P: @@FPDF_GetPageWidth; N: 'FPDF_GetPageWidth'), + (P: @@FPDF_GetPageHeightF; N: 'FPDF_GetPageHeightF'), + (P: @@FPDF_GetPageHeight; N: 'FPDF_GetPageHeight'), + (P: @@FPDF_GetPageBoundingBox; N: 'FPDF_GetPageBoundingBox'), + (P: @@FPDF_GetPageSizeByIndexF; N: 'FPDF_GetPageSizeByIndexF'), + (P: @@FPDF_GetPageSizeByIndex; N: 'FPDF_GetPageSizeByIndex'), {$IFDEF MSWINDOWS} - (P: @@FPDF_RenderPage; N: 'FPDF_RenderPage'), + (P: @@FPDF_RenderPage; N: 'FPDF_RenderPage'), {$ENDIF MSWINDOWS} - (P: @@FPDF_RenderPageBitmap; N: 'FPDF_RenderPageBitmap'), - (P: @@FPDF_RenderPageBitmapWithMatrix; N: 'FPDF_RenderPageBitmapWithMatrix'), - {$IFDEF _SKIA_SUPPORT_} - (P: @@FPDF_RenderPageSkp; N: 'FPDF_RenderPageSkp'), - {$ENDIF _SKIA_SUPPORT_} - (P: @@FPDF_ClosePage; N: 'FPDF_ClosePage'), - (P: @@FPDF_CloseDocument; N: 'FPDF_CloseDocument'), - (P: @@FPDF_DeviceToPage; N: 'FPDF_DeviceToPage'), - (P: @@FPDF_PageToDevice; N: 'FPDF_PageToDevice'), - (P: @@FPDFBitmap_Create; N: 'FPDFBitmap_Create'), - (P: @@FPDFBitmap_CreateEx; N: 'FPDFBitmap_CreateEx'), - (P: @@FPDFBitmap_GetFormat; N: 'FPDFBitmap_GetFormat'), - (P: @@FPDFBitmap_FillRect; N: 'FPDFBitmap_FillRect'), - (P: @@FPDFBitmap_GetBuffer; N: 'FPDFBitmap_GetBuffer'), - (P: @@FPDFBitmap_GetWidth; N: 'FPDFBitmap_GetWidth'), - (P: @@FPDFBitmap_GetHeight; N: 'FPDFBitmap_GetHeight'), - (P: @@FPDFBitmap_GetStride; N: 'FPDFBitmap_GetStride'), - (P: @@FPDFBitmap_Destroy; N: 'FPDFBitmap_Destroy'), - (P: @@FPDF_VIEWERREF_GetPrintScaling; N: 'FPDF_VIEWERREF_GetPrintScaling'), - (P: @@FPDF_VIEWERREF_GetNumCopies; N: 'FPDF_VIEWERREF_GetNumCopies'), - (P: @@FPDF_VIEWERREF_GetPrintPageRange; N: 'FPDF_VIEWERREF_GetPrintPageRange'), - (P: @@FPDF_VIEWERREF_GetPrintPageRangeCount; N: 'FPDF_VIEWERREF_GetPrintPageRangeCount'), - (P: @@FPDF_VIEWERREF_GetPrintPageRangeElement; N: 'FPDF_VIEWERREF_GetPrintPageRangeElement'), - (P: @@FPDF_VIEWERREF_GetDuplex; N: 'FPDF_VIEWERREF_GetDuplex'), - (P: @@FPDF_VIEWERREF_GetName; N: 'FPDF_VIEWERREF_GetName'), - (P: @@FPDF_CountNamedDests; N: 'FPDF_CountNamedDests'), - (P: @@FPDF_GetNamedDestByName; N: 'FPDF_GetNamedDestByName'), - (P: @@FPDF_GetNamedDest; N: 'FPDF_GetNamedDest'), + (P: @@FPDF_RenderPageBitmap; N: 'FPDF_RenderPageBitmap'), + (P: @@FPDF_RenderPageBitmapWithMatrix; N: 'FPDF_RenderPageBitmapWithMatrix'), + {$IFDEF PDF_USE_SKIA} + (P: @@FPDF_RenderPageSkia; N: 'FPDF_RenderPageSkia'; Quirk: True; Optional: True), + {$ENDIF PDF_USE_SKIA} + (P: @@FPDF_ClosePage; N: 'FPDF_ClosePage'), + (P: @@FPDF_CloseDocument; N: 'FPDF_CloseDocument'), + (P: @@FPDF_DeviceToPage; N: 'FPDF_DeviceToPage'), + (P: @@FPDF_PageToDevice; N: 'FPDF_PageToDevice'), + (P: @@FPDFBitmap_Create; N: 'FPDFBitmap_Create'), + (P: @@FPDFBitmap_CreateEx; N: 'FPDFBitmap_CreateEx'), + (P: @@FPDFBitmap_GetFormat; N: 'FPDFBitmap_GetFormat'), + (P: @@FPDFBitmap_FillRect; N: 'FPDFBitmap_FillRect'), + (P: @@FPDFBitmap_GetBuffer; N: 'FPDFBitmap_GetBuffer'), + (P: @@FPDFBitmap_GetWidth; N: 'FPDFBitmap_GetWidth'), + (P: @@FPDFBitmap_GetHeight; N: 'FPDFBitmap_GetHeight'), + (P: @@FPDFBitmap_GetStride; N: 'FPDFBitmap_GetStride'), + (P: @@FPDFBitmap_Destroy; N: 'FPDFBitmap_Destroy'), + (P: @@FPDF_VIEWERREF_GetPrintScaling; N: 'FPDF_VIEWERREF_GetPrintScaling'), + (P: @@FPDF_VIEWERREF_GetNumCopies; N: 'FPDF_VIEWERREF_GetNumCopies'), + (P: @@FPDF_VIEWERREF_GetPrintPageRange; N: 'FPDF_VIEWERREF_GetPrintPageRange'), + (P: @@FPDF_VIEWERREF_GetPrintPageRangeCount; N: 'FPDF_VIEWERREF_GetPrintPageRangeCount'), + (P: @@FPDF_VIEWERREF_GetPrintPageRangeElement; N: 'FPDF_VIEWERREF_GetPrintPageRangeElement'), + (P: @@FPDF_VIEWERREF_GetDuplex; N: 'FPDF_VIEWERREF_GetDuplex'), + (P: @@FPDF_VIEWERREF_GetName; N: 'FPDF_VIEWERREF_GetName'), + (P: @@FPDF_CountNamedDests; N: 'FPDF_CountNamedDests'), + (P: @@FPDF_GetNamedDestByName; N: 'FPDF_GetNamedDestByName'), + (P: @@FPDF_GetNamedDest; N: 'FPDF_GetNamedDest'), + (P: @@FPDF_GetXFAPacketCount; N: 'FPDF_GetXFAPacketCount'), + (P: @@FPDF_GetXFAPacketName; N: 'FPDF_GetXFAPacketName'), + (P: @@FPDF_GetXFAPacketContent; N: 'FPDF_GetXFAPacketContent'), {$IFDEF PDF_ENABLE_V8} - (P: @@FPDF_GetRecommendedV8Flags; N: 'FPDF_GetRecommendedV8Flags'; Quirk: True; Optional: True), + (P: @@FPDF_GetRecommendedV8Flags; N: 'FPDF_GetRecommendedV8Flags'; Quirk: True; Optional: True), + (P: @@FPDF_GetArrayBufferAllocatorSharedInstance; N: 'FPDF_GetArrayBufferAllocatorSharedInstance'; Quirk: True; Optional: True), {$ENDIF PDF_ENABLE_V8} {$IFDEF PDF_ENABLE_XFA} - (P: @@FPDF_BStr_Init; N: 'FPDF_BStr_Init'; Quirk: True; Optional: True), - (P: @@FPDF_BStr_Set; N: 'FPDF_BStr_Set'; Quirk: True; Optional: True), - (P: @@FPDF_BStr_Clear; N: 'FPDF_BStr_Clear'; Quirk: True; Optional: True), + (P: @@FPDF_BStr_Init; N: 'FPDF_BStr_Init'; Quirk: True; Optional: True), + (P: @@FPDF_BStr_Set; N: 'FPDF_BStr_Set'; Quirk: True; Optional: True), + (P: @@FPDF_BStr_Clear; N: 'FPDF_BStr_Clear'; Quirk: True; Optional: True), {$ENDIF PDF_ENABLE_XFA} // *** _FPDF_EDIT_H_ *** - (P: @@FPDF_CreateNewDocument; N: 'FPDF_CreateNewDocument'), - (P: @@FPDFPage_New; N: 'FPDFPage_New'), - (P: @@FPDFPage_Delete; N: 'FPDFPage_Delete'), - (P: @@FPDFPage_GetRotation; N: 'FPDFPage_GetRotation'), - (P: @@FPDFPage_SetRotation; N: 'FPDFPage_SetRotation'), - (P: @@FPDFPage_InsertObject; N: 'FPDFPage_InsertObject'), - (P: @@FPDFPage_RemoveObject; N: 'FPDFPage_RemoveObject'), - (P: @@FPDFPage_CountObjects; N: 'FPDFPage_CountObjects'), - (P: @@FPDFPage_GetObject; N: 'FPDFPage_GetObject'), - (P: @@FPDFPage_HasTransparency; N: 'FPDFPage_HasTransparency'), - (P: @@FPDFPage_GenerateContent; N: 'FPDFPage_GenerateContent'), - (P: @@FPDFPageObj_Destroy; N: 'FPDFPageObj_Destroy'), - (P: @@FPDFPageObj_HasTransparency; N: 'FPDFPageObj_HasTransparency'), - (P: @@FPDFPageObj_GetType; N: 'FPDFPageObj_GetType'), - (P: @@FPDFPageObj_Transform; N: 'FPDFPageObj_Transform'), - (P: @@FPDFPage_TransformAnnots; N: 'FPDFPage_TransformAnnots'), - (P: @@FPDFPageObj_NewImageObj; N: 'FPDFPageObj_NewImageObj'), - (P: @@FPDFPageObj_CountMarks; N: 'FPDFPageObj_CountMarks'), - (P: @@FPDFPageObj_GetMark; N: 'FPDFPageObj_GetMark'), - (P: @@FPDFPageObj_AddMark; N: 'FPDFPageObj_AddMark'), - (P: @@FPDFPageObj_RemoveMark; N: 'FPDFPageObj_RemoveMark'), - (P: @@FPDFPageObjMark_GetName; N: 'FPDFPageObjMark_GetName'), - (P: @@FPDFPageObjMark_CountParams; N: 'FPDFPageObjMark_CountParams'), - (P: @@FPDFPageObjMark_GetParamKey; N: 'FPDFPageObjMark_GetParamKey'), - (P: @@FPDFPageObjMark_GetParamValueType; N: 'FPDFPageObjMark_GetParamValueType'), - (P: @@FPDFPageObjMark_GetParamIntValue; N: 'FPDFPageObjMark_GetParamIntValue'), - (P: @@FPDFPageObjMark_GetParamStringValue; N: 'FPDFPageObjMark_GetParamStringValue'), - (P: @@FPDFPageObjMark_GetParamBlobValue; N: 'FPDFPageObjMark_GetParamBlobValue'), - (P: @@FPDFPageObjMark_SetIntParam; N: 'FPDFPageObjMark_SetIntParam'), - (P: @@FPDFPageObjMark_SetStringParam; N: 'FPDFPageObjMark_SetStringParam'), - (P: @@FPDFPageObjMark_SetBlobParam; N: 'FPDFPageObjMark_SetBlobParam'), - (P: @@FPDFPageObjMark_RemoveParam; N: 'FPDFPageObjMark_RemoveParam'), - (P: @@FPDFImageObj_LoadJpegFile; N: 'FPDFImageObj_LoadJpegFile'), - (P: @@FPDFImageObj_LoadJpegFileInline; N: 'FPDFImageObj_LoadJpegFileInline'), - (P: @@FPDFImageObj_GetMatrix; N: 'FPDFImageObj_GetMatrix'), - (P: @@FPDFImageObj_SetMatrix; N: 'FPDFImageObj_SetMatrix'), - (P: @@FPDFImageObj_SetBitmap; N: 'FPDFImageObj_SetBitmap'), - (P: @@FPDFImageObj_GetBitmap; N: 'FPDFImageObj_GetBitmap'), - (P: @@FPDFImageObj_GetImageDataDecoded; N: 'FPDFImageObj_GetImageDataDecoded'), - (P: @@FPDFImageObj_GetImageDataRaw; N: 'FPDFImageObj_GetImageDataRaw'), - (P: @@FPDFImageObj_GetImageFilterCount; N: 'FPDFImageObj_GetImageFilterCount'), - (P: @@FPDFImageObj_GetImageFilter; N: 'FPDFImageObj_GetImageFilter'), - (P: @@FPDFImageObj_GetImageMetadata; N: 'FPDFImageObj_GetImageMetadata'), - (P: @@FPDFPageObj_CreateNewPath; N: 'FPDFPageObj_CreateNewPath'), - (P: @@FPDFPageObj_CreateNewRect; N: 'FPDFPageObj_CreateNewRect'), - (P: @@FPDFPageObj_GetBounds; N: 'FPDFPageObj_GetBounds'), - (P: @@FPDFPageObj_SetBlendMode; N: 'FPDFPageObj_SetBlendMode'), - (P: @@FPDFPageObj_SetStrokeColor; N: 'FPDFPageObj_SetStrokeColor'), - (P: @@FPDFPageObj_GetStrokeColor; N: 'FPDFPageObj_GetStrokeColor'), - (P: @@FPDFPageObj_SetStrokeWidth; N: 'FPDFPageObj_SetStrokeWidth'), - (P: @@FPDFPageObj_GetStrokeWidth; N: 'FPDFPageObj_GetStrokeWidth'), - (P: @@FPDFPageObj_GetLineJoin; N: 'FPDFPageObj_GetLineJoin'), - (P: @@FPDFPageObj_SetLineJoin; N: 'FPDFPageObj_SetLineJoin'), - (P: @@FPDFPageObj_GetLineCap; N: 'FPDFPageObj_GetLineCap'), - (P: @@FPDFPageObj_SetLineCap; N: 'FPDFPageObj_SetLineCap'), - (P: @@FPDFPageObj_SetFillColor; N: 'FPDFPageObj_SetFillColor'), - (P: @@FPDFPageObj_GetFillColor; N: 'FPDFPageObj_GetFillColor'), - (P: @@FPDFPath_CountSegments; N: 'FPDFPath_CountSegments'), - (P: @@FPDFPath_GetPathSegment; N: 'FPDFPath_GetPathSegment'), - (P: @@FPDFPathSegment_GetPoint; N: 'FPDFPathSegment_GetPoint'), - (P: @@FPDFPathSegment_GetType; N: 'FPDFPathSegment_GetType'), - (P: @@FPDFPathSegment_GetClose; N: 'FPDFPathSegment_GetClose'), - (P: @@FPDFPath_MoveTo; N: 'FPDFPath_MoveTo'), - (P: @@FPDFPath_LineTo; N: 'FPDFPath_LineTo'), - (P: @@FPDFPath_BezierTo; N: 'FPDFPath_BezierTo'), - (P: @@FPDFPath_Close; N: 'FPDFPath_Close'), - (P: @@FPDFPath_SetDrawMode; N: 'FPDFPath_SetDrawMode'), - (P: @@FPDFPath_GetDrawMode; N: 'FPDFPath_GetDrawMode'), - (P: @@FPDFPath_GetMatrix; N: 'FPDFPath_GetMatrix'), - (P: @@FPDFPath_SetMatrix; N: 'FPDFPath_SetMatrix'), - (P: @@FPDFPageObj_NewTextObj; N: 'FPDFPageObj_NewTextObj'), - (P: @@FPDFText_SetText; N: 'FPDFText_SetText'), - (P: @@FPDFText_LoadFont; N: 'FPDFText_LoadFont'), - (P: @@FPDFText_LoadStandardFont; N: 'FPDFText_LoadStandardFont'), - (P: @@FPDFTextObj_GetMatrix; N: 'FPDFTextObj_GetMatrix'), - (P: @@FPDFTextObj_GetFontSize; N: 'FPDFTextObj_GetFontSize'), - (P: @@FPDFFont_Close; N: 'FPDFFont_Close'), - (P: @@FPDFPageObj_CreateTextObj; N: 'FPDFPageObj_CreateTextObj'), - (P: @@FPDFTextObj_GetTextRenderMode; N: 'FPDFTextObj_GetTextRenderMode'), - (P: @@FPDFTextObj_SetTextRenderMode; N: 'FPDFTextObj_SetTextRenderMode'), - (P: @@FPDFTextObj_GetFontName; N: 'FPDFTextObj_GetFontName'), - (P: @@FPDFTextObj_GetText; N: 'FPDFTextObj_GetText'), - (P: @@FPDFFormObj_CountObjects; N: 'FPDFFormObj_CountObjects'), - (P: @@FPDFFormObj_GetObject; N: 'FPDFFormObj_GetObject'), - (P: @@FPDFFormObj_GetMatrix; N: 'FPDFFormObj_GetMatrix'), + (P: @@FPDF_CreateNewDocument; N: 'FPDF_CreateNewDocument'), + (P: @@FPDFPage_New; N: 'FPDFPage_New'), + (P: @@FPDFPage_Delete; N: 'FPDFPage_Delete'), + (P: @@FPDF_MovePages; N: 'FPDF_MovePages'), + (P: @@FPDFPage_GetRotation; N: 'FPDFPage_GetRotation'), + (P: @@FPDFPage_SetRotation; N: 'FPDFPage_SetRotation'), + (P: @@FPDFPage_InsertObject; N: 'FPDFPage_InsertObject'), + (P: @@FPDFPage_InsertObjectAtIndex; N: 'FPDFPage_InsertObjectAtIndex'), + (P: @@FPDFPage_RemoveObject; N: 'FPDFPage_RemoveObject'), + (P: @@FPDFPage_CountObjects; N: 'FPDFPage_CountObjects'), + (P: @@FPDFPage_GetObject; N: 'FPDFPage_GetObject'), + (P: @@FPDFPage_HasTransparency; N: 'FPDFPage_HasTransparency'), + (P: @@FPDFPage_GenerateContent; N: 'FPDFPage_GenerateContent'), + (P: @@FPDFPageObj_Destroy; N: 'FPDFPageObj_Destroy'), + (P: @@FPDFPageObj_HasTransparency; N: 'FPDFPageObj_HasTransparency'), + (P: @@FPDFPageObj_GetType; N: 'FPDFPageObj_GetType'), + (P: @@FPDFPageObj_GetIsActive; N: 'FPDFPageObj_GetIsActive'), + (P: @@FPDFPageObj_SetIsActive; N: 'FPDFPageObj_SetIsActive'), + (P: @@FPDFPageObj_Transform; N: 'FPDFPageObj_Transform'), + (P: @@FPDFPageObj_TransformF; N: 'FPDFPageObj_TransformF'), + (P: @@FPDFPageObj_GetMatrix; N: 'FPDFPageObj_GetMatrix'), + (P: @@FPDFPageObj_SetMatrix; N: 'FPDFPageObj_SetMatrix'), + (P: @@FPDFPage_TransformAnnots; N: 'FPDFPage_TransformAnnots'), + (P: @@FPDFPageObj_NewImageObj; N: 'FPDFPageObj_NewImageObj'), + (P: @@FPDFPageObj_GetMarkedContentID; N: 'FPDFPageObj_GetMarkedContentID'), + (P: @@FPDFPageObj_CountMarks; N: 'FPDFPageObj_CountMarks'), + (P: @@FPDFPageObj_GetMark; N: 'FPDFPageObj_GetMark'), + (P: @@FPDFPageObj_AddMark; N: 'FPDFPageObj_AddMark'), + (P: @@FPDFPageObj_RemoveMark; N: 'FPDFPageObj_RemoveMark'), + (P: @@FPDFPageObjMark_GetName; N: 'FPDFPageObjMark_GetName'), + (P: @@FPDFPageObjMark_CountParams; N: 'FPDFPageObjMark_CountParams'), + (P: @@FPDFPageObjMark_GetParamKey; N: 'FPDFPageObjMark_GetParamKey'), + (P: @@FPDFPageObjMark_GetParamValueType; N: 'FPDFPageObjMark_GetParamValueType'), + (P: @@FPDFPageObjMark_GetParamIntValue; N: 'FPDFPageObjMark_GetParamIntValue'), + (P: @@FPDFPageObjMark_GetParamFloatValue; N: 'FPDFPageObjMark_GetParamFloatValue'), + (P: @@FPDFPageObjMark_GetParamStringValue; N: 'FPDFPageObjMark_GetParamStringValue'), + (P: @@FPDFPageObjMark_GetParamBlobValue; N: 'FPDFPageObjMark_GetParamBlobValue'), + (P: @@FPDFPageObjMark_SetIntParam; N: 'FPDFPageObjMark_SetIntParam'), + (P: @@FPDFPageObjMark_SetFloatParam; N: 'FPDFPageObjMark_SetFloatParam'), + (P: @@FPDFPageObjMark_SetStringParam; N: 'FPDFPageObjMark_SetStringParam'), + (P: @@FPDFPageObjMark_SetBlobParam; N: 'FPDFPageObjMark_SetBlobParam'), + (P: @@FPDFPageObjMark_RemoveParam; N: 'FPDFPageObjMark_RemoveParam'), + (P: @@FPDFImageObj_LoadJpegFile; N: 'FPDFImageObj_LoadJpegFile'), + (P: @@FPDFImageObj_LoadJpegFileInline; N: 'FPDFImageObj_LoadJpegFileInline'), + (P: @@FPDFImageObj_SetMatrix; N: 'FPDFImageObj_SetMatrix'), + (P: @@FPDFImageObj_SetBitmap; N: 'FPDFImageObj_SetBitmap'), + (P: @@FPDFImageObj_GetBitmap; N: 'FPDFImageObj_GetBitmap'), + (P: @@FPDFImageObj_GetRenderedBitmap; N: 'FPDFImageObj_GetRenderedBitmap'), + (P: @@FPDFImageObj_GetImageDataDecoded; N: 'FPDFImageObj_GetImageDataDecoded'), + (P: @@FPDFImageObj_GetImageDataRaw; N: 'FPDFImageObj_GetImageDataRaw'), + (P: @@FPDFImageObj_GetImageFilterCount; N: 'FPDFImageObj_GetImageFilterCount'), + (P: @@FPDFImageObj_GetImageFilter; N: 'FPDFImageObj_GetImageFilter'), + (P: @@FPDFImageObj_GetImageMetadata; N: 'FPDFImageObj_GetImageMetadata'), + (P: @@FPDFImageObj_GetImagePixelSize; N: 'FPDFImageObj_GetImagePixelSize'), + (P: @@FPDFImageObj_GetIccProfileDataDecoded; N: 'FPDFImageObj_GetIccProfileDataDecoded'), + (P: @@FPDFPageObj_CreateNewPath; N: 'FPDFPageObj_CreateNewPath'), + (P: @@FPDFPageObj_CreateNewRect; N: 'FPDFPageObj_CreateNewRect'), + (P: @@FPDFPageObj_GetBounds; N: 'FPDFPageObj_GetBounds'), + (P: @@FPDFPageObj_GetRotatedBounds; N: 'FPDFPageObj_GetRotatedBounds'), + (P: @@FPDFPageObj_SetBlendMode; N: 'FPDFPageObj_SetBlendMode'), + (P: @@FPDFPageObj_SetStrokeColor; N: 'FPDFPageObj_SetStrokeColor'), + (P: @@FPDFPageObj_GetStrokeColor; N: 'FPDFPageObj_GetStrokeColor'), + (P: @@FPDFPageObj_SetStrokeWidth; N: 'FPDFPageObj_SetStrokeWidth'), + (P: @@FPDFPageObj_GetStrokeWidth; N: 'FPDFPageObj_GetStrokeWidth'), + (P: @@FPDFPageObj_GetLineJoin; N: 'FPDFPageObj_GetLineJoin'), + (P: @@FPDFPageObj_SetLineJoin; N: 'FPDFPageObj_SetLineJoin'), + (P: @@FPDFPageObj_GetLineCap; N: 'FPDFPageObj_GetLineCap'), + (P: @@FPDFPageObj_SetLineCap; N: 'FPDFPageObj_SetLineCap'), + (P: @@FPDFPageObj_SetFillColor; N: 'FPDFPageObj_SetFillColor'), + (P: @@FPDFPageObj_GetFillColor; N: 'FPDFPageObj_GetFillColor'), + (P: @@FPDFPageObj_GetDashPhase; N: 'FPDFPageObj_GetDashPhase'), + (P: @@FPDFPageObj_SetDashPhase; N: 'FPDFPageObj_SetDashPhase'), + (P: @@FPDFPageObj_GetDashCount; N: 'FPDFPageObj_GetDashCount'), + (P: @@FPDFPageObj_GetDashArray; N: 'FPDFPageObj_GetDashArray'), + (P: @@FPDFPageObj_SetDashArray; N: 'FPDFPageObj_SetDashArray'), + (P: @@FPDFPath_CountSegments; N: 'FPDFPath_CountSegments'), + (P: @@FPDFPath_GetPathSegment; N: 'FPDFPath_GetPathSegment'), + (P: @@FPDFPathSegment_GetPoint; N: 'FPDFPathSegment_GetPoint'), + (P: @@FPDFPathSegment_GetType; N: 'FPDFPathSegment_GetType'), + (P: @@FPDFPathSegment_GetClose; N: 'FPDFPathSegment_GetClose'), + (P: @@FPDFPath_MoveTo; N: 'FPDFPath_MoveTo'), + (P: @@FPDFPath_LineTo; N: 'FPDFPath_LineTo'), + (P: @@FPDFPath_BezierTo; N: 'FPDFPath_BezierTo'), + (P: @@FPDFPath_Close; N: 'FPDFPath_Close'), + (P: @@FPDFPath_SetDrawMode; N: 'FPDFPath_SetDrawMode'), + (P: @@FPDFPath_GetDrawMode; N: 'FPDFPath_GetDrawMode'), + (P: @@FPDFPageObj_NewTextObj; N: 'FPDFPageObj_NewTextObj'), + (P: @@FPDFText_SetText; N: 'FPDFText_SetText'), + (P: @@FPDFText_SetCharcodes; N: 'FPDFText_SetCharcodes'), + (P: @@FPDFText_SetPositions; N: 'FPDFText_SetPositions'), + (P: @@FPDFText_LoadFont; N: 'FPDFText_LoadFont'), + (P: @@FPDFText_LoadStandardFont; N: 'FPDFText_LoadStandardFont'), + (P: @@FPDFText_LoadCidType2Font; N: 'FPDFText_LoadCidType2Font'), + (P: @@FPDFTextObj_GetFontSize; N: 'FPDFTextObj_GetFontSize'), + (P: @@FPDFFont_Close; N: 'FPDFFont_Close'), + (P: @@FPDFPageObj_CreateTextObj; N: 'FPDFPageObj_CreateTextObj'), + (P: @@FPDFTextObj_GetTextRenderMode; N: 'FPDFTextObj_GetTextRenderMode'), + (P: @@FPDFTextObj_SetTextRenderMode; N: 'FPDFTextObj_SetTextRenderMode'), + (P: @@FPDFTextObj_GetText; N: 'FPDFTextObj_GetText'), + (P: @@FPDFTextObj_GetRenderedBitmap; N: 'FPDFTextObj_GetRenderedBitmap'), + (P: @@FPDFTextObj_GetFont; N: 'FPDFTextObj_GetFont'), + (P: @@FPDFFont_GetBaseFontName; N: 'FPDFFont_GetBaseFontName'), + (P: @@FPDFFont_GetFamilyName; N: 'FPDFFont_GetFamilyName'), + (P: @@FPDFFont_GetFontData; N: 'FPDFFont_GetFontData'), + (P: @@FPDFFont_GetIsEmbedded; N: 'FPDFFont_GetIsEmbedded'), + (P: @@FPDFFont_GetFlags; N: 'FPDFFont_GetFlags'), + (P: @@FPDFFont_GetWeight; N: 'FPDFFont_GetWeight'), + (P: @@FPDFFont_GetItalicAngle; N: 'FPDFFont_GetItalicAngle'), + (P: @@FPDFFont_GetAscent; N: 'FPDFFont_GetAscent'), + (P: @@FPDFFont_GetDescent; N: 'FPDFFont_GetDescent'), + (P: @@FPDFFont_GetGlyphWidth; N: 'FPDFFont_GetGlyphWidth'), + (P: @@FPDFFont_GetGlyphPath; N: 'FPDFFont_GetGlyphPath'), + (P: @@FPDFGlyphPath_CountGlyphSegments; N: 'FPDFGlyphPath_CountGlyphSegments'), + (P: @@FPDFGlyphPath_GetGlyphPathSegment; N: 'FPDFGlyphPath_GetGlyphPathSegment'), + (P: @@FPDFFormObj_CountObjects; N: 'FPDFFormObj_CountObjects'), + (P: @@FPDFFormObj_GetObject; N: 'FPDFFormObj_GetObject'), + (P: @@FPDFFormObj_RemoveObject; N: 'FPDFFormObj_RemoveObject'), // *** _FPDF_PPO_H_ *** - (P: @@FPDF_ImportPages; N: 'FPDF_ImportPages'), - (P: @@FPDF_ImportNPagesToOne; N: 'FPDF_ImportNPagesToOne'), - (P: @@FPDF_CopyViewerPreferences; N: 'FPDF_CopyViewerPreferences'), + (P: @@FPDF_ImportPagesByIndex; N: 'FPDF_ImportPagesByIndex'), + (P: @@FPDF_ImportPages; N: 'FPDF_ImportPages'), + (P: @@FPDF_ImportNPagesToOne; N: 'FPDF_ImportNPagesToOne'), + (P: @@FPDF_NewXObjectFromPage; N: 'FPDF_NewXObjectFromPage'), + (P: @@FPDF_CloseXObject; N: 'FPDF_CloseXObject'), + (P: @@FPDF_NewFormObjectFromXObject; N: 'FPDF_NewFormObjectFromXObject'), + (P: @@FPDF_CopyViewerPreferences; N: 'FPDF_CopyViewerPreferences'), // *** _FPDF_SAVE_H_ *** - (P: @@FPDF_SaveAsCopy; N: 'FPDF_SaveAsCopy'), - (P: @@FPDF_SaveWithVersion; N: 'FPDF_SaveWithVersion'), + (P: @@FPDF_SaveAsCopy; N: 'FPDF_SaveAsCopy'), + (P: @@FPDF_SaveWithVersion; N: 'FPDF_SaveWithVersion'), // *** _FPDFTEXT_H_ *** - (P: @@FPDFText_LoadPage; N: 'FPDFText_LoadPage'), - (P: @@FPDFText_ClosePage; N: 'FPDFText_ClosePage'), - (P: @@FPDFText_CountChars; N: 'FPDFText_CountChars'), - (P: @@FPDFText_GetUnicode; N: 'FPDFText_GetUnicode'), - (P: @@FPDFText_GetFontSize; N: 'FPDFText_GetFontSize'), - (P: @@FPDFText_GetFontInfo; N: 'FPDFText_GetFontInfo'), - (P: @@FPDFText_GetFontWeight; N: 'FPDFText_GetFontWeight'), - (P: @@FPDFText_GetTextRenderMode; N: 'FPDFText_GetTextRenderMode'), - (P: @@FPDFText_GetFillColor; N: 'FPDFText_GetFillColor'), - (P: @@FPDFText_GetStrokeColor; N: 'FPDFText_GetStrokeColor'), - (P: @@FPDFText_GetCharAngle; N: 'FPDFText_GetCharAngle'), - (P: @@FPDFText_GetCharBox; N: 'FPDFText_GetCharBox'), - (P: @@FPDFText_GetLooseCharBox; N: 'FPDFText_GetLooseCharBox'), - (P: @@FPDFText_GetMatrix; N: 'FPDFText_GetMatrix'), - (P: @@FPDFText_GetCharOrigin; N: 'FPDFText_GetCharOrigin'), - (P: @@FPDFText_GetCharIndexAtPos; N: 'FPDFText_GetCharIndexAtPos'), - (P: @@FPDFText_GetText; N: 'FPDFText_GetText'), - (P: @@FPDFText_CountRects; N: 'FPDFText_CountRects'), - (P: @@FPDFText_GetRect; N: 'FPDFText_GetRect'), - (P: @@FPDFText_GetBoundedText; N: 'FPDFText_GetBoundedText'), - (P: @@FPDFText_FindStart; N: 'FPDFText_FindStart'), - (P: @@FPDFText_FindNext; N: 'FPDFText_FindNext'), - (P: @@FPDFText_FindPrev; N: 'FPDFText_FindPrev'), - (P: @@FPDFText_GetSchResultIndex; N: 'FPDFText_GetSchResultIndex'), - (P: @@FPDFText_GetSchCount; N: 'FPDFText_GetSchCount'), - (P: @@FPDFText_FindClose; N: 'FPDFText_FindClose'), - (P: @@FPDFLink_LoadWebLinks; N: 'FPDFLink_LoadWebLinks'), - (P: @@FPDFLink_CountWebLinks; N: 'FPDFLink_CountWebLinks'), - (P: @@FPDFLink_GetURL; N: 'FPDFLink_GetURL'), - (P: @@FPDFLink_CountRects; N: 'FPDFLink_CountRects'), - (P: @@FPDFLink_GetRect; N: 'FPDFLink_GetRect'), - (P: @@FPDFLink_GetTextRange; N: 'FPDFLink_GetTextRange'), - (P: @@FPDFLink_CloseWebLinks; N: 'FPDFLink_CloseWebLinks'), + (P: @@FPDFText_LoadPage; N: 'FPDFText_LoadPage'), + (P: @@FPDFText_ClosePage; N: 'FPDFText_ClosePage'), + (P: @@FPDFText_CountChars; N: 'FPDFText_CountChars'), + (P: @@FPDFText_GetUnicode; N: 'FPDFText_GetUnicode'), + (P: @@FPDFText_GetTextObject; N: 'FPDFText_GetTextObject'), + (P: @@FPDFText_IsGenerated; N: 'FPDFText_IsGenerated'), + (P: @@FPDFText_IsHyphen; N: 'FPDFText_IsHyphen'), + (P: @@FPDFText_HasUnicodeMapError; N: 'FPDFText_HasUnicodeMapError'), + (P: @@FPDFText_GetFontSize; N: 'FPDFText_GetFontSize'), + (P: @@FPDFText_GetFontInfo; N: 'FPDFText_GetFontInfo'), + (P: @@FPDFText_GetFontWeight; N: 'FPDFText_GetFontWeight'), + (P: @@FPDFText_GetFillColor; N: 'FPDFText_GetFillColor'), + (P: @@FPDFText_GetStrokeColor; N: 'FPDFText_GetStrokeColor'), + (P: @@FPDFText_GetCharAngle; N: 'FPDFText_GetCharAngle'), + (P: @@FPDFText_GetCharBox; N: 'FPDFText_GetCharBox'), + (P: @@FPDFText_GetLooseCharBox; N: 'FPDFText_GetLooseCharBox'), + (P: @@FPDFText_GetMatrix; N: 'FPDFText_GetMatrix'), + (P: @@FPDFText_GetCharOrigin; N: 'FPDFText_GetCharOrigin'), + (P: @@FPDFText_GetCharIndexAtPos; N: 'FPDFText_GetCharIndexAtPos'), + (P: @@FPDFText_GetText; N: 'FPDFText_GetText'), + (P: @@FPDFText_CountRects; N: 'FPDFText_CountRects'), + (P: @@FPDFText_GetRect; N: 'FPDFText_GetRect'), + (P: @@FPDFText_GetBoundedText; N: 'FPDFText_GetBoundedText'), + (P: @@FPDFText_FindStart; N: 'FPDFText_FindStart'), + (P: @@FPDFText_FindNext; N: 'FPDFText_FindNext'), + (P: @@FPDFText_FindPrev; N: 'FPDFText_FindPrev'), + (P: @@FPDFText_GetSchResultIndex; N: 'FPDFText_GetSchResultIndex'), + (P: @@FPDFText_GetSchCount; N: 'FPDFText_GetSchCount'), + (P: @@FPDFText_FindClose; N: 'FPDFText_FindClose'), + (P: @@FPDFLink_LoadWebLinks; N: 'FPDFLink_LoadWebLinks'), + (P: @@FPDFLink_CountWebLinks; N: 'FPDFLink_CountWebLinks'), + (P: @@FPDFLink_GetURL; N: 'FPDFLink_GetURL'), + (P: @@FPDFLink_CountRects; N: 'FPDFLink_CountRects'), + (P: @@FPDFLink_GetRect; N: 'FPDFLink_GetRect'), + (P: @@FPDFLink_GetTextRange; N: 'FPDFLink_GetTextRange'), + (P: @@FPDFLink_CloseWebLinks; N: 'FPDFLink_CloseWebLinks'), // *** _FPDF_SEARCHEX_H_ *** - (P: @@FPDFText_GetCharIndexFromTextIndex; N: 'FPDFText_GetCharIndexFromTextIndex'), - (P: @@FPDFText_GetTextIndexFromCharIndex; N: 'FPDFText_GetTextIndexFromCharIndex'), + (P: @@FPDFText_GetCharIndexFromTextIndex; N: 'FPDFText_GetCharIndexFromTextIndex'), + (P: @@FPDFText_GetTextIndexFromCharIndex; N: 'FPDFText_GetTextIndexFromCharIndex'), // *** _FPDF_PROGRESSIVE_H_ *** - (P: @@FPDF_RenderPageBitmap_Start; N: 'FPDF_RenderPageBitmap_Start'), - (P: @@FPDF_RenderPage_Continue; N: 'FPDF_RenderPage_Continue'), - (P: @@FPDF_RenderPage_Close; N: 'FPDF_RenderPage_Close'), + (P: @@FPDF_RenderPageBitmapWithColorScheme_Start; N: 'FPDF_RenderPageBitmapWithColorScheme_Start'), + (P: @@FPDF_RenderPageBitmap_Start; N: 'FPDF_RenderPageBitmap_Start'), + (P: @@FPDF_RenderPage_Continue; N: 'FPDF_RenderPage_Continue'), + (P: @@FPDF_RenderPage_Close; N: 'FPDF_RenderPage_Close'), + + // *** _FPDF_SIGNATURE_H_ *** + (P: @@FPDF_GetSignatureCount; N: 'FPDF_GetSignatureCount'), + (P: @@FPDF_GetSignatureObject; N: 'FPDF_GetSignatureObject'), + (P: @@FPDFSignatureObj_GetContents; N: 'FPDFSignatureObj_GetContents'), + (P: @@FPDFSignatureObj_GetByteRange; N: 'FPDFSignatureObj_GetByteRange'), + (P: @@FPDFSignatureObj_GetSubFilter; N: 'FPDFSignatureObj_GetSubFilter'), + (P: @@FPDFSignatureObj_GetReason; N: 'FPDFSignatureObj_GetReason'), + (P: @@FPDFSignatureObj_GetTime; N: 'FPDFSignatureObj_GetTime'), + (P: @@FPDFSignatureObj_GetDocMDPPermission; N: 'FPDFSignatureObj_GetDocMDPPermission'), // *** _FPDF_FLATTEN_H_ *** - (P: @@FPDFPage_Flatten; N: 'FPDFPage_Flatten'), + (P: @@FPDFPage_Flatten; N: 'FPDFPage_Flatten'), // *** _FPDF_DOC_H_ *** - (P: @@FPDFBookmark_GetFirstChild; N: 'FPDFBookmark_GetFirstChild'), - (P: @@FPDFBookmark_GetNextSibling; N: 'FPDFBookmark_GetNextSibling'), - (P: @@FPDFBookmark_GetTitle; N: 'FPDFBookmark_GetTitle'), - (P: @@FPDFBookmark_Find; N: 'FPDFBookmark_Find'), - (P: @@FPDFBookmark_GetDest; N: 'FPDFBookmark_GetDest'), - (P: @@FPDFBookmark_GetAction; N: 'FPDFBookmark_GetAction'), - (P: @@FPDFAction_GetDest; N: 'FPDFAction_GetDest'), - (P: @@FPDFAction_GetFilePath; N: 'FPDFAction_GetFilePath'), - (P: @@FPDFAction_GetURIPath; N: 'FPDFAction_GetURIPath'), - (P: @@FPDFDest_GetDestPageIndex; N: 'FPDFDest_GetDestPageIndex'), - (P: @@FPDFDest_GetView; N: 'FPDFDest_GetView'), - (P: @@FPDFDest_GetLocationInPage; N: 'FPDFDest_GetLocationInPage'), - (P: @@FPDFLink_GetLinkAtPoint; N: 'FPDFLink_GetLinkAtPoint'), - (P: @@FPDFLink_GetLinkZOrderAtPoint; N: 'FPDFLink_GetLinkZOrderAtPoint'), - (P: @@FPDFLink_GetDest; N: 'FPDFLink_GetDest'), - (P: @@FPDFLink_GetAction; N: 'FPDFLink_GetAction'), - (P: @@FPDFLink_Enumerate; N: 'FPDFLink_Enumerate'), - (P: @@FPDFLink_GetAnnotRect; N: 'FPDFLink_GetAnnotRect'), - (P: @@FPDFLink_CountQuadPoints; N: 'FPDFLink_CountQuadPoints'), - (P: @@FPDFLink_GetQuadPoints; N: 'FPDFLink_GetQuadPoints'), - (P: @@FPDF_GetMetaText; N: 'FPDF_GetMetaText'), - (P: @@FPDF_GetPageLabel; N: 'FPDF_GetPageLabel'), + (P: @@FPDFBookmark_GetFirstChild; N: 'FPDFBookmark_GetFirstChild'), + (P: @@FPDFBookmark_GetNextSibling; N: 'FPDFBookmark_GetNextSibling'), + (P: @@FPDFBookmark_GetTitle; N: 'FPDFBookmark_GetTitle'), + (P: @@FPDFBookmark_GetCount; N: 'FPDFBookmark_GetCount'), + (P: @@FPDFBookmark_Find; N: 'FPDFBookmark_Find'), + (P: @@FPDFBookmark_GetDest; N: 'FPDFBookmark_GetDest'), + (P: @@FPDFBookmark_GetAction; N: 'FPDFBookmark_GetAction'), + (P: @@FPDFAction_GetDest; N: 'FPDFAction_GetDest'), + (P: @@FPDFAction_GetType; N: 'FPDFAction_GetType'), + (P: @@FPDFAction_GetFilePath; N: 'FPDFAction_GetFilePath'), + (P: @@FPDFAction_GetURIPath; N: 'FPDFAction_GetURIPath'), + (P: @@FPDFDest_GetDestPageIndex; N: 'FPDFDest_GetDestPageIndex'), + (P: @@FPDFDest_GetView; N: 'FPDFDest_GetView'), + (P: @@FPDFDest_GetLocationInPage; N: 'FPDFDest_GetLocationInPage'), + (P: @@FPDFLink_GetLinkAtPoint; N: 'FPDFLink_GetLinkAtPoint'), + (P: @@FPDFLink_GetLinkZOrderAtPoint; N: 'FPDFLink_GetLinkZOrderAtPoint'), + (P: @@FPDFLink_GetDest; N: 'FPDFLink_GetDest'), + (P: @@FPDFLink_GetAction; N: 'FPDFLink_GetAction'), + (P: @@FPDFLink_Enumerate; N: 'FPDFLink_Enumerate'), + (P: @@FPDFLink_GetAnnot; N: 'FPDFLink_GetAnnot'), + (P: @@FPDFLink_GetAnnotRect; N: 'FPDFLink_GetAnnotRect'), + (P: @@FPDFLink_CountQuadPoints; N: 'FPDFLink_CountQuadPoints'), + (P: @@FPDFLink_GetQuadPoints; N: 'FPDFLink_GetQuadPoints'), + (P: @@FPDF_GetPageAAction; N: 'FPDF_GetPageAAction'), + (P: @@FPDF_GetFileIdentifier; N: 'FPDF_GetFileIdentifier'), + (P: @@FPDF_GetMetaText; N: 'FPDF_GetMetaText'), + (P: @@FPDF_GetPageLabel; N: 'FPDF_GetPageLabel'), // *** _FPDF_SYSFONTINFO_H_ *** - (P: @@FPDF_GetDefaultTTFMap; N: 'FPDF_GetDefaultTTFMap'), - (P: @@FPDF_AddInstalledFont; N: 'FPDF_AddInstalledFont'), - (P: @@FPDF_SetSystemFontInfo; N: 'FPDF_SetSystemFontInfo'), - (P: @@FPDF_GetDefaultSystemFontInfo; N: 'FPDF_GetDefaultSystemFontInfo'), - (P: @@FPDFDoc_GetPageMode; N: 'FPDFDoc_GetPageMode'), + (P: @@FPDF_GetDefaultTTFMap; N: 'FPDF_GetDefaultTTFMap'), + (P: @@FPDF_GetDefaultTTFMapCount; N: 'FPDF_GetDefaultTTFMapCount'), + (P: @@FPDF_GetDefaultTTFMapEntry; N: 'FPDF_GetDefaultTTFMapEntry'), + (P: @@FPDF_AddInstalledFont; N: 'FPDF_AddInstalledFont'), + (P: @@FPDF_SetSystemFontInfo; N: 'FPDF_SetSystemFontInfo'), + (P: @@FPDF_GetDefaultSystemFontInfo; N: 'FPDF_GetDefaultSystemFontInfo'), + (P: @@FPDFDoc_GetPageMode; N: 'FPDFDoc_GetPageMode'), // *** _FPDF_EXT_H_ *** - (P: @@FSDK_SetUnSpObjProcessHandler; N: 'FSDK_SetUnSpObjProcessHandler'), - (P: @@FSDK_SetTimeFunction; N: 'FSDK_SetTimeFunction'), - (P: @@FSDK_SetLocaltimeFunction; N: 'FSDK_SetLocaltimeFunction'), + (P: @@FSDK_SetUnSpObjProcessHandler; N: 'FSDK_SetUnSpObjProcessHandler'), + (P: @@FSDK_SetTimeFunction; N: 'FSDK_SetTimeFunction'), + (P: @@FSDK_SetLocaltimeFunction; N: 'FSDK_SetLocaltimeFunction'), // *** _FPDF_DATAAVAIL_H_ *** - (P: @@FPDFAvail_Create; N: 'FPDFAvail_Create'), - (P: @@FPDFAvail_Destroy; N: 'FPDFAvail_Destroy'), - (P: @@FPDFAvail_IsDocAvail; N: 'FPDFAvail_IsDocAvail'), - (P: @@FPDFAvail_GetDocument; N: 'FPDFAvail_GetDocument'), - (P: @@FPDFAvail_GetFirstPageNum; N: 'FPDFAvail_GetFirstPageNum'), - (P: @@FPDFAvail_IsPageAvail; N: 'FPDFAvail_IsPageAvail'), - (P: @@FPDFAvail_IsFormAvail; N: 'FPDFAvail_IsFormAvail'), - (P: @@FPDFAvail_IsLinearized; N: 'FPDFAvail_IsLinearized'), + (P: @@FPDFAvail_Create; N: 'FPDFAvail_Create'), + (P: @@FPDFAvail_Destroy; N: 'FPDFAvail_Destroy'), + (P: @@FPDFAvail_IsDocAvail; N: 'FPDFAvail_IsDocAvail'), + (P: @@FPDFAvail_GetDocument; N: 'FPDFAvail_GetDocument'), + (P: @@FPDFAvail_GetFirstPageNum; N: 'FPDFAvail_GetFirstPageNum'), + (P: @@FPDFAvail_IsPageAvail; N: 'FPDFAvail_IsPageAvail'), + (P: @@FPDFAvail_IsFormAvail; N: 'FPDFAvail_IsFormAvail'), + (P: @@FPDFAvail_IsLinearized; N: 'FPDFAvail_IsLinearized'), // *** _FPD_FORMFILL_H *** - (P: @@FPDFDOC_InitFormFillEnvironment; N: 'FPDFDOC_InitFormFillEnvironment'), - (P: @@FPDFDOC_ExitFormFillEnvironment; N: 'FPDFDOC_ExitFormFillEnvironment'), - (P: @@FORM_OnAfterLoadPage; N: 'FORM_OnAfterLoadPage'), - (P: @@FORM_OnBeforeClosePage; N: 'FORM_OnBeforeClosePage'), - (P: @@FORM_DoDocumentJSAction; N: 'FORM_DoDocumentJSAction'), - (P: @@FORM_DoDocumentOpenAction; N: 'FORM_DoDocumentOpenAction'), - (P: @@FORM_DoDocumentAAction; N: 'FORM_DoDocumentAAction'), - (P: @@FORM_DoPageAAction; N: 'FORM_DoPageAAction'), - (P: @@FORM_OnMouseMove; N: 'FORM_OnMouseMove'), - (P: @@FORM_OnFocus; N: 'FORM_OnFocus'), - (P: @@FORM_OnLButtonDown; N: 'FORM_OnLButtonDown'), - (P: @@FORM_OnRButtonDown; N: 'FORM_OnRButtonDown'), - (P: @@FORM_OnLButtonUp; N: 'FORM_OnLButtonUp'), - (P: @@FORM_OnRButtonUp; N: 'FORM_OnRButtonUp'), - (P: @@FORM_OnLButtonDoubleClick; N: 'FORM_OnLButtonDoubleClick'), - (P: @@FORM_OnKeyDown; N: 'FORM_OnKeyDown'), - (P: @@FORM_OnKeyUp; N: 'FORM_OnKeyUp'), - (P: @@FORM_OnChar; N: 'FORM_OnChar'), - (P: @@FORM_GetFocusedText; N: 'FORM_GetFocusedText'), - (P: @@FORM_GetSelectedText; N: 'FORM_GetSelectedText'), - (P: @@FORM_ReplaceSelection; N: 'FORM_ReplaceSelection'), - (P: @@FORM_CanUndo; N: 'FORM_CanUndo'), - (P: @@FORM_CanRedo; N: 'FORM_CanRedo'), - (P: @@FORM_Undo; N: 'FORM_Undo'), - (P: @@FORM_Redo; N: 'FORM_Redo'), - (P: @@FORM_ForceToKillFocus; N: 'FORM_ForceToKillFocus'), - (P: @@FPDFPage_HasFormFieldAtPoint; N: 'FPDFPage_HasFormFieldAtPoint'), - (P: @@FPDFPage_FormFieldZOrderAtPoint; N: 'FPDFPage_FormFieldZOrderAtPoint'), - (P: @@FPDF_SetFormFieldHighlightColor; N: 'FPDF_SetFormFieldHighlightColor'), - (P: @@FPDF_SetFormFieldHighlightAlpha; N: 'FPDF_SetFormFieldHighlightAlpha'), - (P: @@FPDF_RemoveFormFieldHighlight; N: 'FPDF_RemoveFormFieldHighlight'), - (P: @@FPDF_FFLDraw; N: 'FPDF_FFLDraw'), - {$IFDEF _SKIA_SUPPORT_} - (P: @@FPDF_FFLRecord; N: 'FPDF_FFLRecord'), - {$ENDIF _SKIA_SUPPORT_} - - (P: @@FPDF_GetFormType; N: 'FPDF_GetFormType'), - (P: @@FORM_SetIndexSelected; N: 'FORM_SetIndexSelected'), - (P: @@FORM_IsIndexSelected; N: 'FORM_IsIndexSelected'), - (P: @@FPDF_LoadXFA; N: 'FPDF_LoadXFA'), + (P: @@FPDFDOC_InitFormFillEnvironment; N: 'FPDFDOC_InitFormFillEnvironment'), + (P: @@FPDFDOC_ExitFormFillEnvironment; N: 'FPDFDOC_ExitFormFillEnvironment'), + (P: @@FORM_OnAfterLoadPage; N: 'FORM_OnAfterLoadPage'), + (P: @@FORM_OnBeforeClosePage; N: 'FORM_OnBeforeClosePage'), + (P: @@FORM_DoDocumentJSAction; N: 'FORM_DoDocumentJSAction'), + (P: @@FORM_DoDocumentOpenAction; N: 'FORM_DoDocumentOpenAction'), + (P: @@FORM_DoDocumentAAction; N: 'FORM_DoDocumentAAction'), + (P: @@FORM_DoPageAAction; N: 'FORM_DoPageAAction'), + (P: @@FORM_OnMouseMove; N: 'FORM_OnMouseMove'), + (P: @@FORM_OnMouseWheel; N: 'FORM_OnMouseWheel'), + (P: @@FORM_OnFocus; N: 'FORM_OnFocus'), + (P: @@FORM_OnLButtonDown; N: 'FORM_OnLButtonDown'), + (P: @@FORM_OnRButtonDown; N: 'FORM_OnRButtonDown'), + (P: @@FORM_OnLButtonUp; N: 'FORM_OnLButtonUp'), + (P: @@FORM_OnRButtonUp; N: 'FORM_OnRButtonUp'), + (P: @@FORM_OnLButtonDoubleClick; N: 'FORM_OnLButtonDoubleClick'), + (P: @@FORM_OnKeyDown; N: 'FORM_OnKeyDown'), + (P: @@FORM_OnKeyUp; N: 'FORM_OnKeyUp'), + (P: @@FORM_OnChar; N: 'FORM_OnChar'), + (P: @@FORM_GetFocusedText; N: 'FORM_GetFocusedText'), + (P: @@FORM_GetSelectedText; N: 'FORM_GetSelectedText'), + (P: @@FORM_ReplaceAndKeepSelection; N: 'FORM_ReplaceAndKeepSelection'), + (P: @@FORM_ReplaceSelection; N: 'FORM_ReplaceSelection'), + (P: @@FORM_SelectAllText; N: 'FORM_SelectAllText'), + (P: @@FORM_CanUndo; N: 'FORM_CanUndo'), + (P: @@FORM_CanRedo; N: 'FORM_CanRedo'), + (P: @@FORM_Undo; N: 'FORM_Undo'), + (P: @@FORM_Redo; N: 'FORM_Redo'), + (P: @@FORM_ForceToKillFocus; N: 'FORM_ForceToKillFocus'), + (P: @@FORM_GetFocusedAnnot; N: 'FORM_GetFocusedAnnot'), + (P: @@FORM_SetFocusedAnnot; N: 'FORM_SetFocusedAnnot'), + (P: @@FPDFPage_HasFormFieldAtPoint; N: 'FPDFPage_HasFormFieldAtPoint'), + (P: @@FPDFPage_FormFieldZOrderAtPoint; N: 'FPDFPage_FormFieldZOrderAtPoint'), + (P: @@FPDF_SetFormFieldHighlightColor; N: 'FPDF_SetFormFieldHighlightColor'), + (P: @@FPDF_SetFormFieldHighlightAlpha; N: 'FPDF_SetFormFieldHighlightAlpha'), + (P: @@FPDF_RemoveFormFieldHighlight; N: 'FPDF_RemoveFormFieldHighlight'), + (P: @@FPDF_FFLDraw; N: 'FPDF_FFLDraw'), + {$IFDEF PDF_USE_SKIA} + (P: @@FPDF_FFLDrawSkia; N: 'FPDF_FFLDrawSkia'; Quirk: True; Optional: True), + {$ENDIF PDF_USE_SKIA} + + (P: @@FPDF_GetFormType; N: 'FPDF_GetFormType'), + (P: @@FORM_SetIndexSelected; N: 'FORM_SetIndexSelected'), + (P: @@FORM_IsIndexSelected; N: 'FORM_IsIndexSelected'), + (P: @@FPDF_LoadXFA; N: 'FPDF_LoadXFA'), // *** _FPDF_CATALOG_H_ *** - (P: @@FPDFCatalog_IsTagged; N: 'FPDFCatalog_IsTagged'), + (P: @@FPDFCatalog_IsTagged; N: 'FPDFCatalog_IsTagged'), + (P: @@FPDFCatalog_GetLanguage; N: 'FPDFCatalog_GetLanguage'), + (P: @@FPDFCatalog_SetLanguage; N: 'FPDFCatalog_SetLanguage'), // *** _FPDF_ATTACHMENT_H_ *** - (P: @@FPDFDoc_GetAttachmentCount; N: 'FPDFDoc_GetAttachmentCount'), - (P: @@FPDFDoc_AddAttachment; N: 'FPDFDoc_AddAttachment'), - (P: @@FPDFDoc_GetAttachment; N: 'FPDFDoc_GetAttachment'), - (P: @@FPDFDoc_DeleteAttachment; N: 'FPDFDoc_DeleteAttachment'), - (P: @@FPDFAttachment_GetName; N: 'FPDFAttachment_GetName'), - (P: @@FPDFAttachment_HasKey; N: 'FPDFAttachment_HasKey'), - (P: @@FPDFAttachment_GetValueType; N: 'FPDFAttachment_GetValueType'), - (P: @@FPDFAttachment_SetStringValue; N: 'FPDFAttachment_SetStringValue'), - (P: @@FPDFAttachment_GetStringValue; N: 'FPDFAttachment_GetStringValue'), - (P: @@FPDFAttachment_SetFile; N: 'FPDFAttachment_SetFile'), - (P: @@FPDFAttachment_GetFile; N: 'FPDFAttachment_GetFile'), + (P: @@FPDFDoc_GetAttachmentCount; N: 'FPDFDoc_GetAttachmentCount'), + (P: @@FPDFDoc_AddAttachment; N: 'FPDFDoc_AddAttachment'), + (P: @@FPDFDoc_GetAttachment; N: 'FPDFDoc_GetAttachment'), + (P: @@FPDFDoc_DeleteAttachment; N: 'FPDFDoc_DeleteAttachment'), + (P: @@FPDFAttachment_GetName; N: 'FPDFAttachment_GetName'), + (P: @@FPDFAttachment_HasKey; N: 'FPDFAttachment_HasKey'), + (P: @@FPDFAttachment_GetValueType; N: 'FPDFAttachment_GetValueType'), + (P: @@FPDFAttachment_SetStringValue; N: 'FPDFAttachment_SetStringValue'), + (P: @@FPDFAttachment_GetStringValue; N: 'FPDFAttachment_GetStringValue'), + (P: @@FPDFAttachment_SetFile; N: 'FPDFAttachment_SetFile'), + (P: @@FPDFAttachment_GetFile; N: 'FPDFAttachment_GetFile'), + (P: @@FPDFAttachment_GetSubtype; N: 'FPDFAttachment_GetSubtype'), // *** _FPDF_TRANSFORMPAGE_H_ *** - (P: @@FPDFPage_SetMediaBox; N: 'FPDFPage_SetMediaBox'), - (P: @@FPDFPage_SetCropBox; N: 'FPDFPage_SetCropBox'), - (P: @@FPDFPage_SetBleedBox; N: 'FPDFPage_SetBleedBox'), - (P: @@FPDFPage_SetTrimBox; N: 'FPDFPage_SetTrimBox'), - (P: @@FPDFPage_SetArtBox; N: 'FPDFPage_SetArtBox'), - (P: @@FPDFPage_GetMediaBox; N: 'FPDFPage_GetMediaBox'), - (P: @@FPDFPage_GetCropBox; N: 'FPDFPage_GetCropBox'), - (P: @@FPDFPage_GetBleedBox; N: 'FPDFPage_GetBleedBox'), - (P: @@FPDFPage_GetTrimBox; N: 'FPDFPage_GetTrimBox'), - (P: @@FPDFPage_GetArtBox; N: 'FPDFPage_GetArtBox'), - (P: @@FPDFPage_TransFormWithClip; N: 'FPDFPage_TransFormWithClip'), - (P: @@FPDFPageObj_TransformClipPath; N: 'FPDFPageObj_TransformClipPath'), - (P: @@FPDFPageObj_GetClipPath; N: 'FPDFPageObj_GetClipPath'), - (P: @@FPDFClipPath_CountPaths; N: 'FPDFClipPath_CountPaths'), - (P: @@FPDFClipPath_CountPathSegments; N: 'FPDFClipPath_CountPathSegments'), - (P: @@FPDFClipPath_GetPathSegment; N: 'FPDFClipPath_GetPathSegment'), - (P: @@FPDF_CreateClipPath; N: 'FPDF_CreateClipPath'), - (P: @@FPDF_DestroyClipPath; N: 'FPDF_DestroyClipPath'), - (P: @@FPDFPage_InsertClipPath; N: 'FPDFPage_InsertClipPath'), + (P: @@FPDFPage_SetMediaBox; N: 'FPDFPage_SetMediaBox'), + (P: @@FPDFPage_SetCropBox; N: 'FPDFPage_SetCropBox'), + (P: @@FPDFPage_SetBleedBox; N: 'FPDFPage_SetBleedBox'), + (P: @@FPDFPage_SetTrimBox; N: 'FPDFPage_SetTrimBox'), + (P: @@FPDFPage_SetArtBox; N: 'FPDFPage_SetArtBox'), + (P: @@FPDFPage_GetMediaBox; N: 'FPDFPage_GetMediaBox'), + (P: @@FPDFPage_GetCropBox; N: 'FPDFPage_GetCropBox'), + (P: @@FPDFPage_GetBleedBox; N: 'FPDFPage_GetBleedBox'), + (P: @@FPDFPage_GetTrimBox; N: 'FPDFPage_GetTrimBox'), + (P: @@FPDFPage_GetArtBox; N: 'FPDFPage_GetArtBox'), + (P: @@FPDFPage_TransFormWithClip; N: 'FPDFPage_TransFormWithClip'), + (P: @@FPDFPageObj_TransformClipPath; N: 'FPDFPageObj_TransformClipPath'), + (P: @@FPDFPageObj_GetClipPath; N: 'FPDFPageObj_GetClipPath'), + (P: @@FPDFClipPath_CountPaths; N: 'FPDFClipPath_CountPaths'), + (P: @@FPDFClipPath_CountPathSegments; N: 'FPDFClipPath_CountPathSegments'), + (P: @@FPDFClipPath_GetPathSegment; N: 'FPDFClipPath_GetPathSegment'), + (P: @@FPDF_CreateClipPath; N: 'FPDF_CreateClipPath'), + (P: @@FPDF_DestroyClipPath; N: 'FPDF_DestroyClipPath'), + (P: @@FPDFPage_InsertClipPath; N: 'FPDFPage_InsertClipPath'), // *** _FPDF_STRUCTTREE_H_ *** - (P: @@FPDF_StructTree_GetForPage; N: 'FPDF_StructTree_GetForPage'), - (P: @@FPDF_StructTree_Close; N: 'FPDF_StructTree_Close'), - (P: @@FPDF_StructTree_CountChildren; N: 'FPDF_StructTree_CountChildren'), - (P: @@FPDF_StructTree_GetChildAtIndex; N: 'FPDF_StructTree_GetChildAtIndex'), - (P: @@FPDF_StructElement_GetAltText; N: 'FPDF_StructElement_GetAltText'), - (P: @@FPDF_StructElement_GetMarkedContentID; N: 'FPDF_StructElement_GetMarkedContentID'), - (P: @@FPDF_StructElement_GetType; N: 'FPDF_StructElement_GetType'), - (P: @@FPDF_StructElement_GetTitle; N: 'FPDF_StructElement_GetTitle'), - (P: @@FPDF_StructElement_CountChildren; N: 'FPDF_StructElement_CountChildren'), - (P: @@FPDF_StructElement_GetChildAtIndex; N: 'FPDF_StructElement_GetChildAtIndex'), - - (P: @@FPDFAnnot_IsSupportedSubtype; N: 'FPDFAnnot_IsSupportedSubtype'), - (P: @@FPDFPage_CreateAnnot; N: 'FPDFPage_CreateAnnot'), - (P: @@FPDFPage_GetAnnotCount; N: 'FPDFPage_GetAnnotCount'), - (P: @@FPDFPage_GetAnnot; N: 'FPDFPage_GetAnnot'), - (P: @@FPDFPage_GetAnnotIndex; N: 'FPDFPage_GetAnnotIndex'), - (P: @@FPDFPage_CloseAnnot; N: 'FPDFPage_CloseAnnot'), - (P: @@FPDFPage_RemoveAnnot; N: 'FPDFPage_RemoveAnnot'), - (P: @@FPDFAnnot_GetSubtype; N: 'FPDFAnnot_GetSubtype'), - (P: @@FPDFAnnot_IsObjectSupportedSubtype; N: 'FPDFAnnot_IsObjectSupportedSubtype'), - (P: @@FPDFAnnot_UpdateObject; N: 'FPDFAnnot_UpdateObject'), - (P: @@FPDFAnnot_AppendObject; N: 'FPDFAnnot_AppendObject'), - (P: @@FPDFAnnot_GetObjectCount; N: 'FPDFAnnot_GetObjectCount'), - (P: @@FPDFAnnot_GetObject; N: 'FPDFAnnot_GetObject'), - (P: @@FPDFAnnot_RemoveObject; N: 'FPDFAnnot_RemoveObject'), - (P: @@FPDFAnnot_SetColor; N: 'FPDFAnnot_SetColor'), - (P: @@FPDFAnnot_GetColor; N: 'FPDFAnnot_GetColor'), - (P: @@FPDFAnnot_HasAttachmentPoints; N: 'FPDFAnnot_HasAttachmentPoints'), - (P: @@FPDFAnnot_SetAttachmentPoints; N: 'FPDFAnnot_SetAttachmentPoints'), - (P: @@FPDFAnnot_AppendAttachmentPoints; N: 'FPDFAnnot_AppendAttachmentPoints'), - (P: @@FPDFAnnot_CountAttachmentPoints; N: 'FPDFAnnot_CountAttachmentPoints'), - (P: @@FPDFAnnot_GetAttachmentPoints; N: 'FPDFAnnot_GetAttachmentPoints'), - (P: @@FPDFAnnot_SetRect; N: 'FPDFAnnot_SetRect'), - (P: @@FPDFAnnot_GetRect; N: 'FPDFAnnot_GetRect'), - (P: @@FPDFAnnot_HasKey; N: 'FPDFAnnot_HasKey'), - (P: @@FPDFAnnot_GetValueType; N: 'FPDFAnnot_GetValueType'), - (P: @@FPDFAnnot_SetStringValue; N: 'FPDFAnnot_SetStringValue'), - (P: @@FPDFAnnot_GetStringValue; N: 'FPDFAnnot_GetStringValue'), - (P: @@FPDFAnnot_GetNumberValue; N: 'FPDFAnnot_GetNumberValue'), - (P: @@FPDFAnnot_SetAP; N: 'FPDFAnnot_SetAP'), - (P: @@FPDFAnnot_GetAP; N: 'FPDFAnnot_GetAP'), - (P: @@FPDFAnnot_GetLinkedAnnot; N: 'FPDFAnnot_GetLinkedAnnot'), - (P: @@FPDFAnnot_GetFlags; N: 'FPDFAnnot_GetFlags'), - (P: @@FPDFAnnot_SetFlags; N: 'FPDFAnnot_SetFlags'), - (P: @@FPDFAnnot_GetFormFieldFlags; N: 'FPDFAnnot_GetFormFieldFlags'), - (P: @@FPDFAnnot_GetFormFieldAtPoint; N: 'FPDFAnnot_GetFormFieldAtPoint'), - (P: @@FPDFAnnot_GetFormFieldName; N: 'FPDFAnnot_GetFormFieldName'), - (P: @@FPDFAnnot_GetFormFieldType; N: 'FPDFAnnot_GetFormFieldType'), - (P: @@FPDFAnnot_GetOptionCount; N: 'FPDFAnnot_GetOptionCount'), - (P: @@FPDFAnnot_GetOptionLabel; N: 'FPDFAnnot_GetOptionLabel'), - (P: @@FPDFAnnot_GetFontSize; N: 'FPDFAnnot_GetFontSize'), - (P: @@FPDFAnnot_IsChecked; N: 'FPDFAnnot_IsChecked'), - - {$IFDEF PDF_ENABLE_V8} - // *** _FPDF_LIBS_H_ *** - (P: @@FPDF_InitEmbeddedLibraries; N: 'FPDF_InitEmbeddedLibraries'; Optional: True), - {$ENDIF PDF_ENABLE_V8} + (P: @@FPDF_StructTree_GetForPage; N: 'FPDF_StructTree_GetForPage'), + (P: @@FPDF_StructTree_Close; N: 'FPDF_StructTree_Close'), + (P: @@FPDF_StructTree_CountChildren; N: 'FPDF_StructTree_CountChildren'), + (P: @@FPDF_StructTree_GetChildAtIndex; N: 'FPDF_StructTree_GetChildAtIndex'), + (P: @@FPDF_StructElement_GetAltText; N: 'FPDF_StructElement_GetAltText'), + (P: @@FPDF_StructElement_GetActualText; N: 'FPDF_StructElement_GetActualText'), + (P: @@FPDF_StructElement_GetExpansion; N: 'FPDF_StructElement_GetExpansion'), + (P: @@FPDF_StructElement_GetID; N: 'FPDF_StructElement_GetID'), + (P: @@FPDF_StructElement_GetLang; N: 'FPDF_StructElement_GetLang'), + (P: @@FPDF_StructElement_GetStringAttribute; N: 'FPDF_StructElement_GetStringAttribute'), + (P: @@FPDF_StructElement_GetMarkedContentID; N: 'FPDF_StructElement_GetMarkedContentID'), + (P: @@FPDF_StructElement_GetType; N: 'FPDF_StructElement_GetType'), + (P: @@FPDF_StructElement_GetObjType; N: 'FPDF_StructElement_GetObjType'), + (P: @@FPDF_StructElement_GetTitle; N: 'FPDF_StructElement_GetTitle'), + (P: @@FPDF_StructElement_CountChildren; N: 'FPDF_StructElement_CountChildren'), + (P: @@FPDF_StructElement_GetChildAtIndex; N: 'FPDF_StructElement_GetChildAtIndex'), + (P: @@FPDF_StructElement_GetChildMarkedContentID; N: 'FPDF_StructElement_GetChildMarkedContentID'), + (P: @@FPDF_StructElement_GetParent; N: 'FPDF_StructElement_GetParent'), + (P: @@FPDF_StructElement_GetAttributeCount; N: 'FPDF_StructElement_GetAttributeCount'), + (P: @@FPDF_StructElement_GetAttributeAtIndex; N: 'FPDF_StructElement_GetAttributeAtIndex'), + (P: @@FPDF_StructElement_Attr_GetCount; N: 'FPDF_StructElement_Attr_GetCount'), + (P: @@FPDF_StructElement_Attr_GetName; N: 'FPDF_StructElement_Attr_GetName'), + (P: @@FPDF_StructElement_Attr_GetType; N: 'FPDF_StructElement_Attr_GetType'), + (P: @@FPDF_StructElement_Attr_GetBooleanValue; N: 'FPDF_StructElement_Attr_GetBooleanValue'), + (P: @@FPDF_StructElement_Attr_GetNumberValue; N: 'FPDF_StructElement_Attr_GetNumberValue'), + (P: @@FPDF_StructElement_Attr_GetStringValue; N: 'FPDF_StructElement_Attr_GetStringValue'), + (P: @@FPDF_StructElement_Attr_GetBlobValue; N: 'FPDF_StructElement_Attr_GetBlobValue'), + (P: @@FPDF_StructElement_Attr_CountChildren; N: 'FPDF_StructElement_Attr_CountChildren'), + (P: @@FPDF_StructElement_Attr_GetChildAtIndex; N: 'FPDF_StructElement_Attr_GetChildAtIndex'), + (P: @@FPDF_StructElement_GetMarkedContentIdCount; N: 'FPDF_StructElement_GetMarkedContentIdCount'), + (P: @@FPDF_StructElement_GetMarkedContentIdAtIndex; N: 'FPDF_StructElement_GetMarkedContentIdAtIndex'), + + (P: @@FPDFAnnot_IsSupportedSubtype; N: 'FPDFAnnot_IsSupportedSubtype'), + (P: @@FPDFPage_CreateAnnot; N: 'FPDFPage_CreateAnnot'), + (P: @@FPDFPage_GetAnnotCount; N: 'FPDFPage_GetAnnotCount'), + (P: @@FPDFPage_GetAnnot; N: 'FPDFPage_GetAnnot'), + (P: @@FPDFPage_GetAnnotIndex; N: 'FPDFPage_GetAnnotIndex'), + (P: @@FPDFPage_CloseAnnot; N: 'FPDFPage_CloseAnnot'), + (P: @@FPDFPage_RemoveAnnot; N: 'FPDFPage_RemoveAnnot'), + (P: @@FPDFAnnot_GetSubtype; N: 'FPDFAnnot_GetSubtype'), + (P: @@FPDFAnnot_IsObjectSupportedSubtype; N: 'FPDFAnnot_IsObjectSupportedSubtype'), + (P: @@FPDFAnnot_UpdateObject; N: 'FPDFAnnot_UpdateObject'), + (P: @@FPDFAnnot_AddInkStroke; N: 'FPDFAnnot_AddInkStroke'), + (P: @@FPDFAnnot_RemoveInkList; N: 'FPDFAnnot_RemoveInkList'), + (P: @@FPDFAnnot_AppendObject; N: 'FPDFAnnot_AppendObject'), + (P: @@FPDFAnnot_GetObjectCount; N: 'FPDFAnnot_GetObjectCount'), + (P: @@FPDFAnnot_GetObject; N: 'FPDFAnnot_GetObject'), + (P: @@FPDFAnnot_RemoveObject; N: 'FPDFAnnot_RemoveObject'), + (P: @@FPDFAnnot_SetColor; N: 'FPDFAnnot_SetColor'), + (P: @@FPDFAnnot_GetColor; N: 'FPDFAnnot_GetColor'), + (P: @@FPDFAnnot_HasAttachmentPoints; N: 'FPDFAnnot_HasAttachmentPoints'), + (P: @@FPDFAnnot_SetAttachmentPoints; N: 'FPDFAnnot_SetAttachmentPoints'), + (P: @@FPDFAnnot_AppendAttachmentPoints; N: 'FPDFAnnot_AppendAttachmentPoints'), + (P: @@FPDFAnnot_CountAttachmentPoints; N: 'FPDFAnnot_CountAttachmentPoints'), + (P: @@FPDFAnnot_GetAttachmentPoints; N: 'FPDFAnnot_GetAttachmentPoints'), + (P: @@FPDFAnnot_SetRect; N: 'FPDFAnnot_SetRect'), + (P: @@FPDFAnnot_GetRect; N: 'FPDFAnnot_GetRect'), + (P: @@FPDFAnnot_GetVertices; N: 'FPDFAnnot_GetVertices'), + (P: @@FPDFAnnot_GetInkListCount; N: 'FPDFAnnot_GetInkListCount'), + (P: @@FPDFAnnot_GetInkListPath; N: 'FPDFAnnot_GetInkListPath'), + (P: @@FPDFAnnot_GetLine; N: 'FPDFAnnot_GetLine'), + (P: @@FPDFAnnot_SetBorder; N: 'FPDFAnnot_SetBorder'), + (P: @@FPDFAnnot_GetBorder; N: 'FPDFAnnot_GetBorder'), + (P: @@FPDFAnnot_GetFormAdditionalActionJavaScript; N: 'FPDFAnnot_GetFormAdditionalActionJavaScript'), + (P: @@FPDFAnnot_HasKey; N: 'FPDFAnnot_HasKey'), + (P: @@FPDFAnnot_GetValueType; N: 'FPDFAnnot_GetValueType'), + (P: @@FPDFAnnot_SetStringValue; N: 'FPDFAnnot_SetStringValue'), + (P: @@FPDFAnnot_GetStringValue; N: 'FPDFAnnot_GetStringValue'), + (P: @@FPDFAnnot_GetNumberValue; N: 'FPDFAnnot_GetNumberValue'), + (P: @@FPDFAnnot_SetAP; N: 'FPDFAnnot_SetAP'), + (P: @@FPDFAnnot_GetAP; N: 'FPDFAnnot_GetAP'), + (P: @@FPDFAnnot_GetLinkedAnnot; N: 'FPDFAnnot_GetLinkedAnnot'), + (P: @@FPDFAnnot_GetFlags; N: 'FPDFAnnot_GetFlags'), + (P: @@FPDFAnnot_SetFlags; N: 'FPDFAnnot_SetFlags'), + (P: @@FPDFAnnot_GetFormFieldFlags; N: 'FPDFAnnot_GetFormFieldFlags'), + (P: @@FPDFAnnot_SetFormFieldFlags; N: 'FPDFAnnot_SetFormFieldFlags'), + (P: @@FPDFAnnot_GetFormFieldAtPoint; N: 'FPDFAnnot_GetFormFieldAtPoint'), + (P: @@FPDFAnnot_GetFormFieldName; N: 'FPDFAnnot_GetFormFieldName'), + (P: @@FPDFAnnot_GetFormFieldAlternateName; N: 'FPDFAnnot_GetFormFieldAlternateName'), + (P: @@FPDFAnnot_GetFormFieldType; N: 'FPDFAnnot_GetFormFieldType'), + (P: @@FPDFAnnot_GetFormFieldValue; N: 'FPDFAnnot_GetFormFieldValue'), + (P: @@FPDFAnnot_GetOptionCount; N: 'FPDFAnnot_GetOptionCount'), + (P: @@FPDFAnnot_GetOptionLabel; N: 'FPDFAnnot_GetOptionLabel'), + (P: @@FPDFAnnot_IsOptionSelected; N: 'FPDFAnnot_IsOptionSelected'), + (P: @@FPDFAnnot_GetFontSize; N: 'FPDFAnnot_GetFontSize'), + (P: @@FPDFAnnot_GetFontColor; N: 'FPDFAnnot_GetFontColor'), + (P: @@FPDFAnnot_SetFontColor; N: 'FPDFAnnot_SetFontColor'), + (P: @@FPDFAnnot_IsChecked; N: 'FPDFAnnot_IsChecked'), + + (P: @@FPDFAnnot_SetFocusableSubtypes; N: 'FPDFAnnot_SetFocusableSubtypes'), + (P: @@FPDFAnnot_GetFocusableSubtypesCount; N: 'FPDFAnnot_GetFocusableSubtypesCount'), + (P: @@FPDFAnnot_GetFocusableSubtypes; N: 'FPDFAnnot_GetFocusableSubtypes'), + (P: @@FPDFAnnot_GetLink; N: 'FPDFAnnot_GetLink'), + (P: @@FPDFAnnot_GetFormControlCount; N: 'FPDFAnnot_GetFormControlCount'), + (P: @@FPDFAnnot_GetFormControlIndex; N: 'FPDFAnnot_GetFormControlIndex'), + (P: @@FPDFAnnot_GetFormFieldExportValue; N: 'FPDFAnnot_GetFormFieldExportValue'), + (P: @@FPDFAnnot_SetURI; N: 'FPDFAnnot_SetURI'), + (P: @@FPDFAnnot_GetFileAttachment; N: 'FPDFAnnot_GetFileAttachment'), + (P: @@FPDFAnnot_AddFileAttachment; N: 'FPDFAnnot_AddFileAttachment'), // *** _FPDF_JAVASCRIPT_H_ *** - - (P: @@FPDFDoc_GetJavaScriptActionCount; N: 'FPDFDoc_GetJavaScriptActionCount'), - (P: @@FPDFDoc_GetJavaScriptAction; N: 'FPDFDoc_GetJavaScriptAction'), - (P: @@FPDFDoc_CloseJavaScriptAction; N: 'FPDFDoc_CloseJavaScriptAction'), - (P: @@FPDFJavaScriptAction_GetName; N: 'FPDFJavaScriptAction_GetName'), - (P: @@FPDFJavaScriptAction_GetScript; N: 'FPDFJavaScriptAction_GetScript'), + (P: @@FPDFDoc_GetJavaScriptActionCount; N: 'FPDFDoc_GetJavaScriptActionCount'), + (P: @@FPDFDoc_GetJavaScriptAction; N: 'FPDFDoc_GetJavaScriptAction'), + (P: @@FPDFDoc_CloseJavaScriptAction; N: 'FPDFDoc_CloseJavaScriptAction'), + (P: @@FPDFJavaScriptAction_GetName; N: 'FPDFJavaScriptAction_GetName'), + (P: @@FPDFJavaScriptAction_GetScript; N: 'FPDFJavaScriptAction_GetScript'), // *** _FPDF_THUMBNAIL_H_ *** - (P: @@FPDFPage_GetDecodedThumbnailData; N: 'FPDFPage_GetDecodedThumbnailData'), - (P: @@FPDFPage_GetRawThumbnailData; N: 'FPDFPage_GetRawThumbnailData'), - (P: @@FPDFPage_GetThumbnailAsBitmap; N: 'FPDFPage_GetThumbnailAsBitmap') + (P: @@FPDFPage_GetDecodedThumbnailData; N: 'FPDFPage_GetDecodedThumbnailData'), + (P: @@FPDFPage_GetRawThumbnailData; N: 'FPDFPage_GetRawThumbnailData'), + (P: @@FPDFPage_GetThumbnailAsBitmap; N: 'FPDFPage_GetThumbnailAsBitmap') ); + {$IFDEF FPC} + {$WARN 3175 on : Some fields coming before "$1" were not initialized} + {$WARN 3177 on : Some fields coming after "$1" were not initialized} + {$ENDIF FPC} const pdfium_dll = 'pdfium.dll'; @@ -7568,6 +9470,16 @@ function PDF_USE_XFA: Boolean; {$ENDIF PDF_ENABLE_XFA} end; +function PDF_IsSkiaAvailable: Boolean; +begin + {$IFDEF PDF_USE_SKIA} + Result := Assigned(FPDF_RenderPageSkia) and (@FPDF_RenderPageSkia <> @NotLoaded) and (@FPDF_RenderPageSkia <> @FunctionNotSupported) + and Assigned(FPDF_FFLDrawSkia) and (@FPDF_FFLDrawSkia <> @NotLoaded) and (@FPDF_FFLDrawSkia <> @FunctionNotSupported); + {$ELSE} + Result := False; + {$ENDIF PDF_USE_SKIA} +end; + procedure Init; var I: Integer; @@ -7576,26 +9488,30 @@ procedure Init; ImportFuncs[I].P^ := @NotLoaded; end; -procedure InitPDFium(const DllPath: string{$IFDEF PDF_ENABLE_V8}; const ResPath: string{$ENDIF}); +procedure InitPDFium(const DllPath: string); begin if DllPath <> '' then - InitPDFiumEx(IncludeTrailingPathDelimiter(DllPath) + pdfium_dll{$IFDEF PDF_ENABLE_V8}, ResPath{$ENDIF}) + InitPDFiumEx(IncludeTrailingPathDelimiter(DllPath) + pdfium_dll) else - InitPDFiumEx(''{$IFDEF PDF_ENABLE_V8}, ResPath{$ENDIF}); + InitPDFiumEx(''); end; -procedure InitPDFiumEx(const DllFileName: string{$IFDEF PDF_ENABLE_V8}; const ResPath: string{$ENDIF}); +procedure InitPDFiumEx(const DllFileName: string); var I: Integer; - Path: string; + LibraryConfig: FPDF_LIBRARY_CONFIG; begin if PdfiumModule <> 0 then Exit; {$IFDEF CPUX64} + {$IFDEF FPC} + SetExceptionMask([exInvalidOp, exDenormalized, exZeroDivide, exOverflow, exUnderflow, exPrecision]); + {$ELSE} // Pdfium requires all arithmetic exceptions to be masked in 64bit mode if GetExceptionMask <> exAllArithmeticExceptions then SetExceptionMask(exAllArithmeticExceptions); + {$ENDIF FPC} {$ENDIF CPUX64} if DllFileName <> '' then @@ -7605,7 +9521,7 @@ procedure InitPDFiumEx(const DllFileName: string{$IFDEF PDF_ENABLE_V8}; const Re if PdfiumModule = 0 then begin - {$IF CompilerVersion >= 24.0} // XE3+ + {$IF not defined(FPC) and (CompilerVersion >= 24.0)} // XE3+ if DllFileName <> '' then RaiseLastOSError(GetLastError, '.'#10#10 + DllFileName) else @@ -7615,6 +9531,7 @@ procedure InitPDFiumEx(const DllFileName: string{$IFDEF PDF_ENABLE_V8}; const Re {$IFEND} end; + // Import the pdfium.dll functions for I := 0 to Length(ImportFuncs) - 1 do begin if ImportFuncs[I].P^ = @NotLoaded then @@ -7642,34 +9559,15 @@ procedure InitPDFiumEx(const DllFileName: string{$IFDEF PDF_ENABLE_V8}; const Re end; end; - {$IFDEF PDF_ENABLE_V8} - // Initialize the V8 engine if available - if Assigned(FPDF_InitEmbeddedLibraries) then - begin - if ResPath <> '' then - Path := IncludeTrailingPathDelimiter(ResPath) - else if DllFileName <> '' then - begin - Path := ExtractFileDir(DllFileName); - if Path <> '' then - Path := IncludeTrailingPathDelimiter(Path); - end; - - if Path = '' then - begin - // If the DLL was already loaded we can use its path - Path := GetModuleName(PdfiumModule); - if Path <> '' then - Path := IncludeTrailingPathDelimiter(ExtractFilePath(Path)); - end; - - FPDF_InitEmbeddedLibraries(PAnsiChar(AnsiString(Path))); // requires trailing path delimiter - end - else - @FPDF_InitEmbeddedLibraries := @FunctionNotSupported; - {$ENDIF PDF_ENABLE_V8} - - FPDF_InitLibrary; + // Initialize the pdfium library + {$IFDEF FPC} {$WARN 5057 off : Local variable "$1" does not seem to be initialized} {$ENDIF FPC} + FillChar(LibraryConfig, SizeOf(LibraryConfig), 0); + {$IFDEF FPC} {$WARN 5057 on} {$ENDIF FPC} + LibraryConfig.version := 2; + LibraryConfig.m_RendererType := FPDF_RENDERERTYPE_AGG; + {if IsSkiaAvailable and SkiaRendererEnabled then + LibraryConfig.m_RendererType := FPDF_RENDERERTYPE_SKIA;} + FPDF_InitLibraryWithConfig(@LibraryConfig); end; initialization