From 92f997e98cf7df61ae24b2c006818ef7cecdb864 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Sat, 22 Aug 2020 21:46:39 +0200 Subject: [PATCH 01/59] * Update to chromium/4194 * Support for Attachments --- Example/MainFrm.dfm | 18 + Example/MainFrm.pas | 46 +- README.md | 4 +- Source/PdfiumCore.pas | 668 ++++++++++++++++++++- Source/PdfiumCtrl.pas | 22 +- Source/PdfiumLib.pas | 1291 ++++++++++++++++++++++++++++------------- 6 files changed, 1622 insertions(+), 427 deletions(-) diff --git a/Example/MainFrm.dfm b/Example/MainFrm.dfm index 026a67d..bfe22e7 100644 --- a/Example/MainFrm.dfm +++ b/Example/MainFrm.dfm @@ -88,6 +88,18 @@ object frmMain: TfrmMain TabOrder = 7 OnClick = btnPrintClick end + object ListViewAttachments: TListView + Left = 0 + Top = 600 + Width = 655 + Height = 47 + Align = alBottom + Columns = <> + TabOrder = 8 + ViewStyle = vsList + Visible = False + OnDblClick = ListViewAttachmentsDblClick + end object PrintDialog1: TPrintDialog Left = 96 Top = 32 @@ -99,4 +111,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..56b0597 100644 --- a/Example/MainFrm.pas +++ b/Example/MainFrm.pas @@ -5,7 +5,7 @@ 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) @@ -19,6 +19,8 @@ TfrmMain = class(TForm) btnPrint: TButton; PrintDialog1: TPrintDialog; OpenDialog1: TOpenDialog; + ListViewAttachments: TListView; + SaveDialog1: TSaveDialog; procedure FormCreate(Sender: TObject); procedure btnPrevClick(Sender: TObject); procedure btnNextClick(Sender: TObject); @@ -28,10 +30,12 @@ TfrmMain = class(TForm) procedure chkSmoothScrollClick(Sender: TObject); procedure edtZoomChange(Sender: TObject); procedure btnPrintClick(Sender: TObject); + procedure ListViewAttachmentsDblClick(Sender: TObject); private { Private-Deklarationen } FCtrl: TPdfControl; procedure WebLinkClick(Sender: TObject; Url: string); + procedure ListAttachments; public { Public-Deklarationen } end; @@ -74,6 +78,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); @@ -129,6 +159,7 @@ procedure TfrmMain.btnPrintClick(Sender: TObject); begin Printer.BeginDoc; try + TPdfDocument.SetPrintTextWithGDI(True); // Print text as text and not as vectors (allows white on white printing) FCtrl.CurrentPage.Draw(Printer.Canvas.Handle, 0, 0, Printer.PageWidth, Printer.PageHeight, prNormal, [proAnnotations, proPrinting]); finally Printer.EndDoc; @@ -136,4 +167,17 @@ procedure TfrmMain.btnPrintClick(Sender: TObject); 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; + end. diff --git a/README.md b/README.md index 67334ed..de28cef 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Example of a PDF VCL Control using PDFium pdfium.dll (x86/x64) from the [pdfium-binaries](https://github.com/bblanchon/pdfium-binaries) ## Required pdfium.dll version -chromium/4047 +chromium/4194 ## Features - Multiple PDF load functions: @@ -15,6 +15,8 @@ chromium/4047 - 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) - Callback +- File Attachments +- Forms - PDF rotation (normal, 90° counter clockwise, 180°, 90° clockwise) - Highlighted text (e.g. for search results) - WebLink click support diff --git a/Source/PdfiumCore.pas b/Source/PdfiumCore.pas index 548c528..65b7cf1 100644 --- a/Source/PdfiumCore.pas +++ b/Source/PdfiumCore.pas @@ -17,6 +17,7 @@ EPdfArgumentOutOfRange = class(EPdfException); TPdfDocument = class; TPdfPage = class; + TPdfAttachmentList = class; TPdfPoint = record X, Y: Double; @@ -93,7 +94,13 @@ TPdfRect = record pmPostScript2 = 2, pmPostScript3 = 3, pmPostScriptPassThrough2 = 4, - pmPostScriptPassThrough3 = 5 + pmPostScriptPassThrough3 = 5, + pmEMFImageMasks = 6 + ); + + TPdfFileIdType = ( + pfiPermanent = 0, + pfiChanging = 1 ); TPdfBitmapFormat = ( @@ -114,6 +121,19 @@ TPdfRect = record fftSignature ); + 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 + ); + _TPdfBitmapHideCtor = class(TObject) private procedure Create; @@ -191,6 +211,7 @@ TPdfPage = class(TObject) procedure ApplyChanges; 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; @@ -199,7 +220,15 @@ TPdfPage = class(TObject) function FormEventKeyDown(KeyCode: Word; KeyData: LPARAM): Boolean; function FormEventKeyUp(KeyCode: Word; KeyData: LPARAM): Boolean; function FormEventKeyPress(Key: Word; KeyData: LPARAM): Boolean; - procedure FormEventKillFocus; + function FormEventKillFocus: Boolean; + function FormGetFocusedText: string; + function FormGetSelectedText: string; + function FormReplaceSelection(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; @@ -236,6 +265,64 @@ TPdfPage = class(TObject) TPdfFormOutputSelectedRectEvent = procedure(Document: TPdfDocument; Page: TPdfPage; const PageRect: TPdfRect) of object; TPdfFormGetCurrentPage = procedure(Document: TPdfDocument; var CurrentPage: TPdfPage) 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); + + property Count: Integer read GetCount; + property Items[Index: Integer]: TPdfAttachment read GetItem; default; + end; + TPdfDocument = class(TObject) private type PCustomLoadDataRec = ^TCustomLoadDataRec; @@ -247,6 +334,7 @@ TCustomLoadDataRec = record private FDocument: FPDF_DOCUMENT; FPages: TObjectList; + FAttachments: TPdfAttachmentList; FFileName: string; FFileHandle: THandle; FFileMapping: THandle; @@ -266,7 +354,7 @@ TCustomLoadDataRec = record FOnFormOutputSelectedRect: TPdfFormOutputSelectedRectEvent; FOnFormGetCurrentPage: TPdfFormGetCurrentPage; - procedure InternLoadFromMem(Buffer: PByte; Size: Integer; const APassword: AnsiString); + procedure InternLoadFromMem(Buffer: PByte; Size: NativeInt; const APassword: AnsiString); procedure InternLoadFromCustom(ReadFunc: TPdfDocumentCustomReadProc; ASize: LongWord; AParam: Pointer; const APassword: AnsiString); function GetPage(Index: Integer): TPdfPage; function GetPageCount: Integer; @@ -292,11 +380,11 @@ TCustomLoadDataRec = record 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 LoadFromActiveBuffer(Buffer: Pointer; Size: NativeInt; 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 LoadFromBytes(const ABytes: TBytes; AIndex: NativeInt; ACount: NativeInt; const APassword: AnsiString = ''); overload; procedure LoadFromStream(AStream: TStream; const APassword: AnsiString = ''); - procedure LoadFromFile(const AFileName: string; const APassword: AnsiString = ''; ALoadOptions: TPdfDocumentLoadOption = dloMMF); + procedure LoadFromFile(const AFileName: string; const APassword: AnsiString = ''; ALoadOption: TPdfDocumentLoadOption = dloMMF); procedure Close; procedure SaveToFile(const AFileName: string; Option: TPdfDocumentSaveOption = dsoRemoveSecurity; FileVersion: Integer = -1); @@ -310,14 +398,19 @@ TCustomLoadDataRec = record 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; + class procedure SetPrintTextWithGDI(UseGdi: Boolean); static; property FileName: string read FFileName; property PageCount: Integer read GetPageCount; 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; @@ -355,10 +448,15 @@ 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'; RsFileTooLarge = 'PDF file "%s" is too large'; + 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'; + RsPdfErrorSuccess = 'No error'; RsPdfErrorUnknown = 'Unknown error'; RsPdfErrorFile = 'File not found or can''t be opened'; @@ -371,6 +469,25 @@ implementation 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: PChar; 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: PChar; CharCount: Integer): Integer; +begin + Result := GetChars(Bytes, ByteCount, Chars, CharCount); +end; + function SetThreadPdfUnsupportedFeatureHandler(const Handler: TPdfUnsupportedFeatureHandler): TPdfUnsupportedFeatureHandler; begin Result := ThreadPdfUnsupportedFeatureHandler; @@ -680,6 +797,11 @@ procedure FFI_SetTextFieldFocus(pThis: PFPDF_FORMFILLINFO; value: FPDF_WIDESTRIN begin end; +procedure FFI_FocusChange(param: PFPDF_FORMFILLINFO; annot: FPDF_ANNOTATION; page_index: Integer); cdecl; +begin +end; + + { TPdfRect } @@ -725,6 +847,7 @@ constructor TPdfDocument.Create; begin inherited Create; FPages := TObjectList.Create; + FAttachments := TPdfAttachmentList.Create(Self); FFileHandle := INVALID_HANDLE_VALUE; FFormFieldHighlightColor := $FFE4DD; FFormFieldHighlightAlpha := 100; @@ -736,6 +859,7 @@ constructor TPdfDocument.Create; destructor TPdfDocument.Destroy; begin Close; + FAttachments.Free; FPages.Free; inherited Destroy; end; @@ -809,7 +933,7 @@ function ReadFromActiveFile(Param: Pointer; Position: LongWord; Buffer: PByte; S Result := Size = 0; end; -procedure TPdfDocument.LoadFromFile(const AFileName: string; const APassword: AnsiString; ALoadOptions: TPdfDocumentLoadOption); +procedure TPdfDocument.LoadFromFile(const AFileName: string; const APassword: AnsiString; ALoadOption: TPdfDocumentLoadOption); var Size: Int64; Offset: NativeInt; @@ -825,10 +949,18 @@ procedure TPdfDocument.LoadFromFile(const AFileName: string; const APassword: An 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) + if Size > High(Integer) then // PDFium can only handle PDFs up to 2 GB (FX_FILESIZE in core/fxcrt/fx_system.h) + begin + {$IFDEF CPUX64} + // FPDF_LoadCustomDocument wasn't updated to load larger files, so we fall back to MMF. + if ALoadOption = dloOnDemand then + ALoadOption := dloMMF; + {$ELSE} raise EPdfException.CreateResFmt(@RsFileTooLarge, [ExtractFileName(AFileName)]); + {$ENDIF CPUX64} + end; - case ALoadOptions of + case ALoadOption of dloMemory: begin if Size > 0 then @@ -863,7 +995,7 @@ procedure TPdfDocument.LoadFromFile(const AFileName: string; const APassword: An 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); @@ -902,7 +1034,7 @@ 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 APassword: AnsiString); begin Close; InternLoadFromMem(Buffer, Size, APassword); @@ -913,18 +1045,18 @@ procedure TPdfDocument.LoadFromBytes(const ABytes: TBytes; const APassword: Ansi LoadFromBytes(ABytes, 0, Length(ABytes), APassword); end; -procedure TPdfDocument.LoadFromBytes(const ABytes: TBytes; AIndex, ACount: Integer; +procedure TPdfDocument.LoadFromBytes(const ABytes: TBytes; AIndex, ACount: NativeInt; const APassword: AnsiString); var - Len: Integer; + Len: NativeInt; begin Close; Len := Length(ABytes); if AIndex >= Len then - raise EPdfArgumentOutOfRange.CreateResFmt(@RsArgumentsOutOfRange, ['Index']); + raise EPdfArgumentOutOfRange.CreateResFmt(@RsArgumentsOutOfRange, ['Index', AIndex]); if AIndex + ACount > Len then - raise EPdfArgumentOutOfRange.CreateResFmt(@RsArgumentsOutOfRange, ['Count']); + raise EPdfArgumentOutOfRange.CreateResFmt(@RsArgumentsOutOfRange, ['Count', ACount]); FBytes := ABytes; // keep alive after return InternLoadFromMem(@ABytes[AIndex], ACount, APassword); @@ -989,7 +1121,7 @@ procedure TPdfDocument.InternLoadFromCustom(ReadFunc: TPdfDocumentCustomReadProc end; end; -procedure TPdfDocument.InternLoadFromMem(Buffer: PByte; Size: Integer; const APassword: AnsiString); +procedure TPdfDocument.InternLoadFromMem(Buffer: PByte; Size: NativeInt; const APassword: AnsiString); var OldCurDoc: TPdfDocument; begin @@ -998,7 +1130,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(APassword))); finally UnsupportedFeatureCurrentDocument := OldCurDoc; end; @@ -1028,6 +1160,7 @@ procedure TPdfDocument.DocumentLoaded; FFormFillHandler.FormFillInfo.FFI_GetRotation := FFI_GetRotation; FFormFillHandler.FormFillInfo.FFI_SetCursor := FFI_SetCursor; FFormFillHandler.FormFillInfo.FFI_SetTextFieldFocus := FFI_SetTextFieldFocus; + FFormFillHandler.FormFillInfo.FFI_OnFocusChange := FFI_FocusChange; if PDF_USE_XFA then begin @@ -1242,6 +1375,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,7 +1399,7 @@ 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); @@ -1306,6 +1456,12 @@ class function TPdfDocument.SetPrintMode(PrintMode: TPdfPrintMode): Boolean; Result := FPDF_SetPrintMode(Ord(PrintMode)) <> 0; end; +class procedure TPdfDocument.SetPrintTextWithGDI(UseGdi: Boolean); +begin + InitLib; + FPDF_SetPrintTextWithGDI(Ord(UseGdi)); +end; + procedure TPdfDocument.SetFormFieldHighlightAlpha(Value: Integer); begin if Value < 0 then @@ -1841,6 +1997,27 @@ function TPdfPage.FormEventFocus(const Shift: TShiftState; PageX, PageY: Double) Result := False; end; +function TPdfPage.FormEventMouseWheel(const Shift: TShiftState; WheelDelta: Integer; PageX, PageY: Double): Boolean; +var + Pt: TFSPointF; + WheelX, WheelY: Integer; +begin + if IsValidForm then + 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, GetMouseModifier(Shift), @Pt, WheelX, WheelY) <> 0; + end + else + Result := False; +end; + function TPdfPage.FormEventMouseMove(const Shift: TShiftState; PageX, PageY: Double): Boolean; begin if IsValidForm then @@ -1905,10 +2082,101 @@ function TPdfPage.FormEventKeyPress(Key: Word; KeyData: LPARAM): Boolean; Result := False; end; -procedure TPdfPage.FormEventKillFocus; +function TPdfPage.FormEventKillFocus: Boolean; +begin + if IsValidForm then + Result := FORM_ForceToKillFocus(FDocument.FForm) <> 0 + else + Result := False; +end; + +function TPdfPage.FormGetFocusedText: string; +var + ByteLen: LongWord; +begin + if IsValidForm then + 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.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.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 - FORM_ForceToKillFocus(FDocument.FForm); + Result := FORM_Undo(FDocument.FForm, FPage) <> 0 + else + Result := False; +end; + +function TPdfPage.FormRedo: Boolean; +begin + if IsValidForm then + Result := FORM_Redo(FDocument.FForm, FPage) <> 0 + else + Result := False; end; function TPdfPage.HasFormFieldAtPoint(X, Y: Double): TPdfFormFieldType; @@ -2017,6 +2285,364 @@ 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; + +{ 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; + initialization InitializeCriticalSectionAndSpinCount(PDFiumInitCritSect, 4000); InitializeCriticalSectionAndSpinCount(FFITimersCritSect, 4000); diff --git a/Source/PdfiumCtrl.pas b/Source/PdfiumCtrl.pas index 0036f6b..b458f85 100644 --- a/Source/PdfiumCtrl.pas +++ b/Source/PdfiumCtrl.pas @@ -144,11 +144,11 @@ TPdfControl = class(TCustomControl) 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 LoadFromActiveBuffer(Buffer: Pointer; Size: Int64; 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); + procedure LoadFromFile(const AFileName: string; const APassword: AnsiString = ''; ALoadOption: TPdfDocumentLoadOption = dloMMF); procedure Close; function DeviceToPage(DeviceX, DeviceY: Integer): TPdfPoint; overload; @@ -247,7 +247,7 @@ TPdfControl = class(TCustomControl) implementation uses - Math, Clipbrd, Character, PdfiumLib; + Math, Clipbrd, Character; const cScrollTimerId = 1; @@ -788,7 +788,7 @@ procedure TPdfControl.LoadFromActiveStream(Stream: TStream; const APassword: Ans end; end; -procedure TPdfControl.LoadFromActiveBuffer(Buffer: Pointer; Size: Integer; const APassword: AnsiString); +procedure TPdfControl.LoadFromActiveBuffer(Buffer: Pointer; Size: Int64; const APassword: AnsiString); begin try FDocument.LoadFromActiveBuffer(Buffer, Size, APassword); @@ -826,10 +826,10 @@ procedure TPdfControl.LoadFromStream(AStream: TStream; const APassword: AnsiStri end; procedure TPdfControl.LoadFromFile(const AFileName: string; const APassword: AnsiString; - ALoadOptions: TPdfDocumentLoadOption); + ALoadOption: TPdfDocumentLoadOption); begin try - FDocument.LoadFromFile(AFileName, APassword, ALoadOptions); + FDocument.LoadFromFile(AFileName, APassword, ALoadOption); finally DocumentLoaded; end; @@ -1918,10 +1918,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 diff --git a/Source/PdfiumLib.pas b/Source/PdfiumLib.pas index 7d941fb..b3862f9 100644 --- a/Source/PdfiumLib.pas +++ b/Source/PdfiumLib.pas @@ -3,7 +3,7 @@ // Use DLLs (x64, x86) from https://github.com/bblanchon/pdfium-binaries // -// DLL Version: chromium/4047 +// DLL Version: chromium/4194 unit PdfiumLib; @@ -101,6 +101,7 @@ __FPDF_PTRREC = record end; FPDF_PATHSEGMENT = type __PFPDF_PTRREC; FPDF_RECORDER = type Pointer; // Passed into skia. FPDF_SCHHANDLE = type __PFPDF_PTRREC; + FPDF_SIGNATURE = type __PFPDF_PTRREC; FPDF_STRUCTELEMENT = type __PFPDF_PTRREC; FPDF_STRUCTTREE = type __PFPDF_PTRREC; FPDF_TEXTPAGE = type __PFPDF_PTRREC; @@ -213,6 +214,7 @@ FS_POINTF = record // Annotation enums. FPDF_ANNOTATION_SUBTYPE = Integer; + PFPDF_ANNOTATION_SUBTYPE = ^FPDF_ANNOTATION_SUBTYPE; FPDF_ANNOT_APPEARANCEMODE = Integer; // Dictionary value types. @@ -247,7 +249,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,6 +257,11 @@ FPDF_LIBRARY_CONFIG = record // [0, |v8::Internals::kNumIsolateDataLots|). Note that 0 is fine for most // embedders. m_v8EmbedderSlot: Cardinal; + + // Version 3 - Experimantal, + + // Pointer to the V8::Platform to use. + m_pPlatform: Pointer; end; PFPdfLibraryConfig = ^TFPdfLibraryConfig; TFPdfLibraryConfig = FPDF_LIBRARY_CONFIG; @@ -332,11 +339,18 @@ FPDF_LIBRARY_CONFIG = record // 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. // Return value: // True if successful, false if unsuccessful (typically invalid input). var @@ -389,6 +403,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}; +// Function: FPDF_LoadMemDocument64 +// Open and load a PDF document from memory. +// Experimental API. +// 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; @@ -715,7 +754,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 +762,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 @@ -1214,6 +1271,22 @@ 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|. +var + FPDF_GetArrayBufferAllocatorSharedInstance: function: Pointer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; {$ENDIF PDF_ENABLE_V8} {$IFDEF PDF_ENABLE_XFA} @@ -1287,12 +1360,14 @@ 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; type PFPDF_IMAGEOBJ_METADATA = ^FPDF_IMAGEOBJ_METADATA; @@ -3109,6 +3184,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 +3249,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,6 +3280,32 @@ 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}; + + // *** _FPDF_DOC_H_ *** const @@ -3189,6 +3327,14 @@ IFSDK_PAUSE = record PDFDEST_VIEW_FITBH = 7; PDFDEST_VIEW_FITBV = 8; +// The file identifier entry type. See section 14.4 "File Identifiers" of the +// ISO 32000-1 standard. +type + FPDF_FILEIDTYPE = ( + FILEIDTYPE_PERMANENT = 0, + FILEIDTYPE_CHANGING = 1 + ); + // _FS_DEF_STRUCTURE_QUADPOINTSF_ type PFS_QUADPOINTSF = ^FS_QUADPOINTSF; @@ -3431,6 +3577,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 +3615,24 @@ 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}; +// Get the file identifer defined in the trailer of |document|. +// Experimental API. Subject to change. +// +// 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. @@ -4428,8 +4603,17 @@ FPDF_SYSTEMTIME = record 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; @@ -4620,19 +4804,20 @@ FPDF_FORMFILLINFO = record //* //* Method: FFI_GetCurrentPage - //* This method receives the handle to the current page. + //* This method receives the handle to the current page. //* Interface Version: - //* 1 + //* 1 //* Implementation Required: - //* yes + //* Yes when V8 support is present, otherwise unused. //* Parameters: - //* pThis - Pointer to the interface structure itself. - //* document - Handle to document. Returned by FPDF_LoadDocument(). + //* 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(). + //* 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. + //* 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; @@ -4712,6 +4897,10 @@ FPDF_FORMFILLINFO = record //* 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. //* @@ -4754,7 +4943,6 @@ FPDF_FORMFILLINFO = record //* m_pJsPlatform: PIPDF_JSPLATFORM; - {$IFDEF PDF_ENABLE_XFA} //* Version 2 - Experimental. //* //* Whether the XFA module is disabled when built with the XFA module. @@ -5064,7 +5252,52 @@ FPDF_FORMFILLINFO = record //* 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; @@ -5104,7 +5337,7 @@ FPDF_FORMFILLINFO = record //* 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 +//* hHandle - Handle to the form fill module, as returned by //* FPDFDOC_InitFormFillEnvironment(). //* Return Value: //* None. @@ -5235,6 +5468,35 @@ FPDF_FORMFILLINFO = record FORM_OnMouseMove: function(hHandle: FPDF_FORMHANDLE; page: FPDF_PAGE; modifier: Integer; page_x, page_y: Double): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +//* +//* 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 @@ -5261,7 +5523,7 @@ FPDF_FORMFILLINFO = record //* Call this member function when the user presses the left //* mouse button. //* Parameters: -//* hHandle - Handle to the form fill module. as returned by +//* 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. @@ -5294,7 +5556,7 @@ FPDF_FORMFILLINFO = record //* Parameters: //* hHandle - Handle to the form fill module, as returned by //* FPDFDOC_InitFormFillEnvironment(). -//* page - Handle to the page. as returned by FPDF_LoadPage(). +//* 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. @@ -5410,7 +5672,7 @@ FPDF_FORMFILLINFO = record //* 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 +//* 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 @@ -5443,6 +5705,21 @@ FPDF_FORMFILLINFO = record var FORM_ReplaceSelection: procedure(hHandle: FPDF_FORMHANDLE; page: FPDF_PAGE; wsText: FPDF_WIDESTRING); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +//* +//* 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 @@ -5475,7 +5752,7 @@ FPDF_FORMFILLINFO = record //* Function: FORM_Undo //* Make the current focussed widget perform an undo operation. //* Parameters: -//* hHandle - Handle to the form fill module. as returned by +//* hHandle - Handle to the form fill module, as returned by //* FPDFDOC_InitFormFillEnvironment(). //* page - Handle to the page, as returned by FPDF_LoadPage(). //* Return Value: @@ -5485,14 +5762,14 @@ FPDF_FORMFILLINFO = record 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. +//* Function: FORM_Redo +//* Make the current focussed widget perform a redo operation. //* Parameters: -//* hHandle - Handle to the form fill module. as returned by +//* 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. +//* True if the redo operation succeeded. //* var FORM_Redo: function(hHandle: FPDF_FORMHANDLE; page: FPDF_PAGE): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; @@ -5511,6 +5788,49 @@ FPDF_FORMFILLINFO = record 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. @@ -5823,6 +6143,7 @@ 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); type FPDFANNOT_COLORTYPE = ( @@ -5938,6 +6259,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 section 12.5.6.13 in +// PDF 32000-1:2008 Specification. +// +// 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 @@ -6343,6 +6691,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 @@ -6370,6 +6732,104 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; 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}; // *** _FPDF_CATALOG_H_ *** @@ -6519,19 +6979,29 @@ 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}; // *** _FPDF_FWLEVENT_H_ *** @@ -6732,9 +7202,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,9 +7234,9 @@ 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}; @@ -7116,431 +7586,456 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; TImportFuncRec = record P: PPointer; N: PAnsiChar; - Quirk: Boolean; // True: if the symbol can't be found, no exception is raised + 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 + ImportFuncs: array[0..358 {$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_V8 } + 3 {$ENDIF} {$IFDEF PDF_ENABLE_XFA } + 3 {$ENDIF} {$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_InitLibrary; N: 'FPDF_InitLibrary'), + (P: @@FPDF_InitLibraryWithConfig; N: 'FPDF_InitLibraryWithConfig'), + (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'), + (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_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'), {$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'), + (P: @@FPDF_RenderPageBitmap; N: 'FPDF_RenderPageBitmap'), + (P: @@FPDF_RenderPageBitmapWithMatrix; N: 'FPDF_RenderPageBitmapWithMatrix'), {$IFDEF _SKIA_SUPPORT_} - (P: @@FPDF_RenderPageSkp; N: 'FPDF_RenderPageSkp'), + (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_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'), {$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: @@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'), // *** _FPDF_PPO_H_ *** - (P: @@FPDF_ImportPages; N: 'FPDF_ImportPages'), - (P: @@FPDF_ImportNPagesToOne; N: 'FPDF_ImportNPagesToOne'), - (P: @@FPDF_CopyViewerPreferences; N: 'FPDF_CopyViewerPreferences'), + (P: @@FPDF_ImportPages; N: 'FPDF_ImportPages'), + (P: @@FPDF_ImportNPagesToOne; N: 'FPDF_ImportNPagesToOne'), + (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_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'), // *** _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'), // *** _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_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_GetAnnot; N: 'FPDFLink_GetAnnot'), + (P: @@FPDFLink_GetAnnotRect; N: 'FPDFLink_GetAnnotRect'), + (P: @@FPDFLink_CountQuadPoints; N: 'FPDFLink_CountQuadPoints'), + (P: @@FPDFLink_GetQuadPoints; N: 'FPDFLink_GetQuadPoints'), + (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_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'), + (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_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 _SKIA_SUPPORT_} - (P: @@FPDF_FFLRecord; N: 'FPDF_FFLRecord'), + (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: @@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'), // *** _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'), // *** _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'), + (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_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_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_IsOptionSelected; N: 'FPDFAnnot_IsOptionSelected'), + (P: @@FPDFAnnot_GetFontSize; N: 'FPDFAnnot_GetFontSize'), + (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'), {$IFDEF PDF_ENABLE_V8} // *** _FPDF_LIBS_H_ *** - (P: @@FPDF_InitEmbeddedLibraries; N: 'FPDF_InitEmbeddedLibraries'; Optional: True), + (P: @@FPDF_InitEmbeddedLibraries; N: 'FPDF_InitEmbeddedLibraries'; Optional: True), {$ENDIF PDF_ENABLE_V8} // *** _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') ); const From d7df697dde9776d4134d532e93febc341f5d16aa Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Wed, 26 Aug 2020 20:01:46 +0200 Subject: [PATCH 02/59] * Update to chromium/4243 --- Source/PdfiumLib.pas | 292 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 272 insertions(+), 20 deletions(-) diff --git a/Source/PdfiumLib.pas b/Source/PdfiumLib.pas index b3862f9..6d220b7 100644 --- a/Source/PdfiumLib.pas +++ b/Source/PdfiumLib.pas @@ -3,7 +3,7 @@ // Use DLLs (x64, x86) from https://github.com/bblanchon/pdfium-binaries // -// DLL Version: chromium/4194 +// DLL Version: chromium/4243 unit PdfiumLib; @@ -313,9 +313,10 @@ FPDF_LIBRARY_CONFIG = record type TPDFiumEnsureTypefaceCharactersAccessible = procedure(font: PLogFont; text: PWideChar; text_length: SIZE_T); cdecl; +// Experimental API. // Function: FPDF_SetTypefaceAccessibleFunc // Set the function pointer that makes GDI fonts available in sandboxed -// environments. Experimental API. +// environments. // Parameters: // func - A function pointer. See description above. // Return value: @@ -323,9 +324,9 @@ FPDF_LIBRARY_CONFIG = record var FPDF_SetTypefaceAccessibleFunc: procedure(func: TPDFiumEnsureTypefaceCharactersAccessible); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Experimental API. // 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: @@ -334,9 +335,9 @@ FPDF_LIBRARY_CONFIG = record 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 @@ -403,9 +404,9 @@ 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. -// Experimental API. // Parameters: // data_buf - Pointer to a buffer containing the PDF document. // size - Number of bytes in the PDF document. @@ -599,9 +600,9 @@ FPDF_FILEHANDLER = record 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: @@ -1165,9 +1166,9 @@ FPDF_COLORSCHEME = 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: @@ -1175,9 +1176,9 @@ FPDF_COLORSCHEME = 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. @@ -1259,6 +1260,60 @@ FPDF_COLORSCHEME = 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 @@ -1874,9 +1929,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. // @@ -1884,6 +1941,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. +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 @@ -3305,16 +3379,110 @@ IFSDK_PAUSE = record 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}; + // *** _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; @@ -3490,8 +3658,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. @@ -3615,8 +3783,20 @@ 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|. +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|. -// Experimental API. Subject to change. // // document - handle to the document. // id_type - the file identifier type to retrieve. @@ -7336,6 +7516,65 @@ 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_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: @@ -7595,7 +7834,7 @@ TImportFuncRec = record end; const - ImportFuncs: array[0..358 + ImportFuncs: array[0..371 {$IFDEF MSWINDOWS} + 2 {$IFDEF PDFIUM_PRINT_TEXT_WITH_GDI} + 2 {$ENDIF} @@ -7666,6 +7905,9 @@ TImportFuncRec = record (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_GetArrayBufferAllocatorSharedInstance; N: 'FPDF_GetArrayBufferAllocatorSharedInstance'; Quirk: True; Optional: True), @@ -7715,6 +7957,7 @@ TImportFuncRec = record (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'), @@ -7820,6 +8063,11 @@ TImportFuncRec = record // *** _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'), // *** _FPDF_FLATTEN_H_ *** (P: @@FPDFPage_Flatten; N: 'FPDFPage_Flatten'), @@ -7846,6 +8094,7 @@ TImportFuncRec = record (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'), @@ -7961,6 +8210,9 @@ TImportFuncRec = record (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_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_GetTitle; N: 'FPDF_StructElement_GetTitle'), From 2ea24d348106b3e95274db711446ce44cc17fa45 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Wed, 9 Sep 2020 10:37:21 +0200 Subject: [PATCH 03/59] Fixed #10 --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index de28cef..631c445 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Example of a PDF VCL Control using PDFium pdfium.dll (x86/x64) from the [pdfium-binaries](https://github.com/bblanchon/pdfium-binaries) ## Required pdfium.dll version -chromium/4194 +chromium/4243 ## Features - Multiple PDF load functions: @@ -17,7 +17,7 @@ chromium/4194 - Callback - File Attachments - Forms -- PDF rotation (normal, 90° counter clockwise, 180°, 90° clockwise) +- PDF rotation (normal, 90° counter clockwise, 180°, 90° clockwise) - Highlighted text (e.g. for search results) - WebLink click support - Flicker-free and optimized painting (only changed parts are painted) From cdbd92f7cb0049b63ba7b4f6348f5de766208b55 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Thu, 22 Oct 2020 21:57:37 +0200 Subject: [PATCH 04/59] Added TPdfDocumentVclPrinter class to print PDF documents --- Example/MainFrm.dfm | 3 + Example/MainFrm.pas | 18 ++- Source/PdfiumCore.pas | 247 +++++++++++++++++++++++++++++++++++++++++- Source/PdfiumCtrl.pas | 72 +++++++++++- 4 files changed, 332 insertions(+), 8 deletions(-) diff --git a/Example/MainFrm.dfm b/Example/MainFrm.dfm index bfe22e7..d512c3a 100644 --- a/Example/MainFrm.dfm +++ b/Example/MainFrm.dfm @@ -101,6 +101,9 @@ object frmMain: TfrmMain OnDblClick = ListViewAttachmentsDblClick end object PrintDialog1: TPrintDialog + MinPage = 1 + MaxPage = 10 + Options = [poPageNums] Left = 96 Top = 32 end diff --git a/Example/MainFrm.pas b/Example/MainFrm.pas index 56b0597..b0f3c55 100644 --- a/Example/MainFrm.pas +++ b/Example/MainFrm.pas @@ -154,15 +154,25 @@ procedure TfrmMain.edtZoomChange(Sender: TObject); end; procedure TfrmMain.btnPrintClick(Sender: TObject); +var + PdfPrinter: TPdfDocumentPrinter; begin + PrintDialog1.MinPage := 1; + PrintDialog1.MaxPage := FCtrl.Document.PageCount; + if PrintDialog1.Execute(Handle) then begin - Printer.BeginDoc; + PdfPrinter := TPdfDocumentVclPrinter.Create; try - TPdfDocument.SetPrintTextWithGDI(True); // Print text as text and not as vectors (allows white on white printing) - FCtrl.CurrentPage.Draw(Printer.Canvas.Handle, 0, 0, Printer.PageWidth, Printer.PageHeight, prNormal, [proAnnotations, proPrinting]); + //PdfPrinter.PrintTextWithGDI := True; + //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; diff --git a/Source/PdfiumCore.pas b/Source/PdfiumCore.pas index 65b7cf1..fe71efe 100644 --- a/Source/PdfiumCore.pas +++ b/Source/PdfiumCore.pas @@ -6,7 +6,7 @@ interface uses - Windows, Types, SysUtils, Classes, Contnrs, PdfiumLib, Graphics; + Windows, WinSpool, Types, SysUtils, Classes, Contnrs, PdfiumLib, Graphics; type EPdfException = class(Exception); @@ -435,6 +435,57 @@ TCustomLoadDataRec = record property OnFormGetCurrentPage: TPdfFormGetCurrentPage read FOnFormGetCurrentPage write FOnFormGetCurrentPage; end; + 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; + + FPrintTextWithGDI: Boolean; + FFitPageToPrintArea: Boolean; + FOnPrintStatus: TPdfDocumentPrinterStatusEvent; + + function IsPortraitOrientation(AWidth, AHeight: Integer): Boolean; + procedure GetPrinterBounds(var APaperSize, APrintArea: TSize; AMargins: TPoint); + protected + procedure BeginDoc; virtual; abstract; + procedure EndDoc; virtual; abstract; + procedure StartPage; virtual; abstract; + procedure EndPage; 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. } + procedure BeginPrint; + { EndPrint must be called after printing multiple documents were printed. } + procedure EndPrint; + + { Prints a range of PDF document pages (0..PageCount-1) } + procedure Print(ADocument: TPdfDocument; AFromPageIndex, AToPageIndex: Integer); overload; + { Prints all pages of the PDF document. } + procedure Print(ADocument: TPdfDocument); overload; + + + { If PrintTextWithGDI is true the text on PDF pages are printed with GDI if the font is + installed on the system. Otherwise the text is converted to vectors. } + property PrintTextWithGDI: Boolean read FPrintTextWithGDI write FPrintTextWithGDI default False; + + { 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; + function SetThreadPdfUnsupportedFeatureHandler(const Handler: TPdfUnsupportedFeatureHandler): TPdfUnsupportedFeatureHandler; var @@ -499,6 +550,15 @@ function GetFileSizeEx(hFile: THandle; var lpFileSize: Int64): Boolean; 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 @@ -577,9 +637,9 @@ procedure InitLib; if Initialized = 0 then begin if PDFiumDllFileName <> '' then - InitPDFiumEx(PDFiumDllFileName {$IF declared(FPDF_InitEmbeddedLibraries)}, PDFiumResDir{$ENDIF}) + InitPDFiumEx(PDFiumDllFileName {$IF declared(FPDF_InitEmbeddedLibraries)}, PDFiumResDir{$IFEND}) else - InitPDFium(PDFiumDllDir {$IF declared(FPDF_InitEmbeddedLibraries)}, PDFiumResDir{$ENDIF}); + InitPDFium(PDFiumDllDir {$IF declared(FPDF_InitEmbeddedLibraries)}, PDFiumResDir{$IFEND}); FSDK_SetUnSpObjProcessHandler(@UnsupportInfo); Initialized := 1; end; @@ -2643,6 +2703,187 @@ function TPdfAttachment.GetContentAsString(Encoding: TEncoding): string; GetContent(Result, Encoding); end; +{ TPdfDocumentPrinter } + +constructor TPdfDocumentPrinter.Create; +begin + inherited Create; + FPrintTextWithGDI := False; + FFitPageToPrintArea := True; +end; + +function TPdfDocumentPrinter.IsPortraitOrientation(AWidth, AHeight: Integer): Boolean; +begin + Result := AHeight > AWidth; +end; + +procedure TPdfDocumentPrinter.GetPrinterBounds(var APaperSize, APrintArea: TSize; AMargins: TPoint); +var + DC: HDC; +begin + DC := GetPrinterDC; + + APaperSize.cx := GetDeviceCaps(DC, PHYSICALWIDTH); + APaperSize.cy := GetDeviceCaps(DC, PHYSICALHEIGHT); + + APrintArea.cx := GetDeviceCaps(DC, HORZRES); + APrintArea.cy := GetDeviceCaps(DC, VERTRES); + + AMargins.X := GetDeviceCaps(DC, PHYSICALOFFSETX); + AMargins.Y := GetDeviceCaps(DC, PHYSICALOFFSETY); +end; + +procedure TPdfDocumentPrinter.BeginPrint; +begin + Inc(FBeginPrintCounter); + if FBeginPrintCounter = 1 then + begin + GetPrinterBounds(FPaperSize, FPrintArea, FMargins); + FPrintPortraitOrientation := IsPortraitOrientation(FPaperSize.cx, FPaperSize.cy); + + BeginDoc; + FPrinterDC := GetPrinterDC; + + TPdfDocument.SetPrintTextWithGDI(FPrintTextWithGDI); + end; +end; + +procedure TPdfDocumentPrinter.EndPrint; +begin + Dec(FBeginPrintCounter); + if FBeginPrintCounter = 0 then + begin + if FPrinterDC <> 0 then + begin + EndDoc; + FPrinterDC := 0; + end; + end; +end; + +procedure TPdfDocumentPrinter.Print(ADocument: TPdfDocument); +begin + if ADocument <> nil then + Print(ADocument, 0, ADocument.PageCount - 1); +end; + +procedure TPdfDocumentPrinter.Print(ADocument: TPdfDocument; AFromPageIndex, AToPageIndex: Integer); +var + PageIndex: Integer; + WasPageLoaded: Boolean; + PdfPage: TPdfPage; + PagePortraitOrientation: Boolean; + X, Y, W, H: Integer; + PrintedPageNum, PrintPageCount: Integer; +begin + 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; + + BeginPrint; + try + 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 + StartPage; + try + if (W > 0) and (H > 0) then + InternPrintPage(PdfPage, X, Y, W, H); + finally + EndPage; + end; + Inc(PrintedPageNum); + if Assigned(OnPrintStatus) then + OnPrintStatus(Self, PrintedPageNum, PrintPageCount); + finally + if not WasPageLoaded and (PdfPage <> nil) then + PdfPage.Close; // release memory + end; + end; + finally + EndPrint; + 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; + initialization InitializeCriticalSectionAndSpinCount(PDFiumInitCritSect, 4000); InitializeCriticalSectionAndSpinCount(FFITimersCritSect, 4000); diff --git a/Source/PdfiumCtrl.pas b/Source/PdfiumCtrl.pas index b458f85..26ee85f 100644 --- a/Source/PdfiumCtrl.pas +++ b/Source/PdfiumCtrl.pas @@ -244,10 +244,22 @@ TPdfControl = class(TCustomControl) {$IFEND} end; + TPdfDocumentVclPrinter = class(TPdfDocumentPrinter) + private + FBeginDocCalled: Boolean; + FPagePrinted: Boolean; + protected + procedure BeginDoc; override; + procedure EndDoc; override; + procedure StartPage; override; + procedure EndPage; override; + function GetPrinterDC: HDC; override; + end; + implementation uses - Math, Clipbrd, Character; + Math, Clipbrd, Character, Printers; const cScrollTimerId = 1; @@ -264,6 +276,64 @@ function IsWhitespace(Ch: Char): Boolean; {$IFEND} 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; + +{ TPdfDocumentVclPrinter } + +procedure TPdfDocumentVclPrinter.BeginDoc; +begin + FPagePrinted := False; + if not Printer.Printing then + begin + Printer.BeginDoc; + FBeginDocCalled := Printer.Printing; + end; + if 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.EndDoc; +begin + if Printer.Printing then + begin + if FBeginDocCalled then + Printer.EndDoc; + end; + SetAbortProc(GetPrinterDC, @VclAbortProc); // restore (dangerous) default behavior +end; + +procedure TPdfDocumentVclPrinter.StartPage; +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.EndPage; +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.Handle; +end; + { TPdfControl } constructor TPdfControl.Create(AOwner: TComponent); From 29eb1f71a1a84f9d52706be890a083b13673f18e Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Fri, 23 Oct 2020 20:39:21 +0200 Subject: [PATCH 05/59] - PrintTextWithGDI handling changed - Handle aborted print (e.g. user canceled the PDF Printer's FileDialog) --- Source/PdfiumCore.pas | 189 ++++++++++++++++++++++++------------------ Source/PdfiumCtrl.pas | 22 ++--- 2 files changed, 121 insertions(+), 90 deletions(-) diff --git a/Source/PdfiumCore.pas b/Source/PdfiumCore.pas index fe71efe..fc7a921 100644 --- a/Source/PdfiumCore.pas +++ b/Source/PdfiumCore.pas @@ -402,7 +402,8 @@ TCustomLoadDataRec = record function GetMetaText(const TagName: string): string; class function SetPrintMode(PrintMode: TPdfPrintMode): Boolean; static; - class procedure SetPrintTextWithGDI(UseGdi: Boolean); static; + class function SetPrintTextWithGDI(UseGdi: Boolean): Boolean; static; + class function GetPrintTextWithGDI: Boolean; static; property FileName: string read FFileName; property PageCount: Integer read GetPageCount; @@ -452,27 +453,28 @@ TPdfDocumentPrinter = class(TObject) FOnPrintStatus: TPdfDocumentPrinterStatusEvent; function IsPortraitOrientation(AWidth, AHeight: Integer): Boolean; - procedure GetPrinterBounds(var APaperSize, APrintArea: TSize; AMargins: TPoint); + procedure GetPrinterBounds; protected - procedure BeginDoc; virtual; abstract; - procedure EndDoc; virtual; abstract; - procedure StartPage; virtual; abstract; - procedure EndPage; virtual; abstract; + function PrinterStartDoc: 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. } - procedure BeginPrint; + { 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: Boolean; { EndPrint must be called after printing multiple documents were printed. } procedure EndPrint; { Prints a range of PDF document pages (0..PageCount-1) } - procedure Print(ADocument: TPdfDocument; AFromPageIndex, AToPageIndex: Integer); overload; + function Print(ADocument: TPdfDocument; AFromPageIndex, AToPageIndex: Integer): Boolean; overload; { Prints all pages of the PDF document. } - procedure Print(ADocument: TPdfDocument); overload; + function Print(ADocument: TPdfDocument): Boolean; overload; { If PrintTextWithGDI is true the text on PDF pages are printed with GDI if the font is @@ -520,6 +522,9 @@ implementation ThreadPdfUnsupportedFeatureHandler: TPdfUnsupportedFeatureHandler; UnsupportedFeatureCurrentDocument: TPdfDocument; +var + GPrintTextWithGDI: Boolean = False; + type { We don't want to use a TBytes temporary array if we can convert directly into the destination buffer. } @@ -1516,10 +1521,17 @@ class function TPdfDocument.SetPrintMode(PrintMode: TPdfPrintMode): Boolean; Result := FPDF_SetPrintMode(Ord(PrintMode)) <> 0; end; -class procedure TPdfDocument.SetPrintTextWithGDI(UseGdi: Boolean); +class function TPdfDocument.SetPrintTextWithGDI(UseGdi: Boolean): Boolean; begin InitLib; FPDF_SetPrintTextWithGDI(Ord(UseGdi)); + Result := GPrintTextWithGDI; + GPrintTextWithGDI := UseGdi; +end; + +class function TPdfDocument.GetPrintTextWithGDI: Boolean; +begin + Result := GPrintTextWithGDI; end; procedure TPdfDocument.SetFormFieldHighlightAlpha(Value: Integer); @@ -2717,35 +2729,37 @@ function TPdfDocumentPrinter.IsPortraitOrientation(AWidth, AHeight: Integer): Bo Result := AHeight > AWidth; end; -procedure TPdfDocumentPrinter.GetPrinterBounds(var APaperSize, APrintArea: TSize; AMargins: TPoint); -var - DC: HDC; +procedure TPdfDocumentPrinter.GetPrinterBounds; begin - DC := GetPrinterDC; + FPaperSize.cx := GetDeviceCaps(FPrinterDC, PHYSICALWIDTH); + FPaperSize.cy := GetDeviceCaps(FPrinterDC, PHYSICALHEIGHT); - APaperSize.cx := GetDeviceCaps(DC, PHYSICALWIDTH); - APaperSize.cy := GetDeviceCaps(DC, PHYSICALHEIGHT); + FPrintArea.cx := GetDeviceCaps(FPrinterDC, HORZRES); + FPrintArea.cy := GetDeviceCaps(FPrinterDC, VERTRES); - APrintArea.cx := GetDeviceCaps(DC, HORZRES); - APrintArea.cy := GetDeviceCaps(DC, VERTRES); - - AMargins.X := GetDeviceCaps(DC, PHYSICALOFFSETX); - AMargins.Y := GetDeviceCaps(DC, PHYSICALOFFSETY); + FMargins.X := GetDeviceCaps(FPrinterDC, PHYSICALOFFSETX); + FMargins.Y := GetDeviceCaps(FPrinterDC, PHYSICALOFFSETY); end; -procedure TPdfDocumentPrinter.BeginPrint; +function TPdfDocumentPrinter.BeginPrint: Boolean; begin Inc(FBeginPrintCounter); if FBeginPrintCounter = 1 then begin - GetPrinterBounds(FPaperSize, FPrintArea, FMargins); - FPrintPortraitOrientation := IsPortraitOrientation(FPaperSize.cx, FPaperSize.cy); - - BeginDoc; FPrinterDC := GetPrinterDC; - TPdfDocument.SetPrintTextWithGDI(FPrintTextWithGDI); - end; + GetPrinterBounds; + FPrintPortraitOrientation := IsPortraitOrientation(FPaperSize.cx, FPaperSize.cy); + + Result := PrinterStartDoc; + if not Result then + begin + FPrinterDC := 0; + Dec(FBeginPrintCounter); + end; + end + else + Result := True; end; procedure TPdfDocumentPrinter.EndPrint; @@ -2755,19 +2769,21 @@ procedure TPdfDocumentPrinter.EndPrint; begin if FPrinterDC <> 0 then begin - EndDoc; FPrinterDC := 0; + PrinterEndDoc; end; end; end; -procedure TPdfDocumentPrinter.Print(ADocument: TPdfDocument); +function TPdfDocumentPrinter.Print(ADocument: TPdfDocument): Boolean; begin if ADocument <> nil then - Print(ADocument, 0, ADocument.PageCount - 1); + Result := Print(ADocument, 0, ADocument.PageCount - 1) + else + Result := False; end; -procedure TPdfDocumentPrinter.Print(ADocument: TPdfDocument; AFromPageIndex, AToPageIndex: Integer); +function TPdfDocumentPrinter.Print(ADocument: TPdfDocument; AFromPageIndex, AToPageIndex: Integer): Boolean; var PageIndex: Integer; WasPageLoaded: Boolean; @@ -2776,6 +2792,7 @@ procedure TPdfDocumentPrinter.Print(ADocument: TPdfDocument; AFromPageIndex, ATo X, Y, W, H: Integer; PrintedPageNum, PrintPageCount: Integer; begin + Result := False; if ADocument = nil then Exit; @@ -2787,55 +2804,58 @@ procedure TPdfDocumentPrinter.Print(ADocument: TPdfDocument; AFromPageIndex, ATo PrintedPageNum := 0; PrintPageCount := AToPageIndex - AFromPageIndex + 1; - BeginPrint; - try - 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 BeginPrint then + begin + try + 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 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; + if PagePortraitOrientation <> FPrintPortraitOrientation then + begin + SwapInts(X, Y); + SwapInts(W, H); + end; - // Print page - StartPage; - try - if (W > 0) and (H > 0) then - InternPrintPage(PdfPage, X, Y, W, H); + // 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 - EndPage; + if not WasPageLoaded and (PdfPage <> nil) then + PdfPage.Close; // release memory end; - Inc(PrintedPageNum); - if Assigned(OnPrintStatus) then - OnPrintStatus(Self, PrintedPageNum, PrintPageCount); - finally - if not WasPageLoaded and (PdfPage <> nil) then - PdfPage.Close; // release memory end; + finally + EndPrint; end; - finally - EndPrint; + Result := True; end; end; @@ -2860,6 +2880,7 @@ procedure TPdfDocumentPrinter.InternPrintPage(APage: TPdfPage; X, Y, Width, Heig PageWidth, PageHeight: Double; PageScale, PrintScale: Double; ScaledWidth, ScaledHeight: Double; + OldPrintTextWithGDI: Boolean; begin PageWidth := APage.Width; PageHeight := APage.Height; @@ -2877,11 +2898,19 @@ procedure TPdfDocumentPrinter.InternPrintPage(APage: TPdfPage; X, Y, Width, Heig X := X + (Width - ScaledWidth) / 2; Y := Y + (Height - ScaledHeight) / 2; - APage.Draw( - FPrinterDC, - RoundToInt(X), RoundToInt(Y), RoundToInt(ScaledWidth), RoundToInt(ScaledHeight), - prNormal, [proPrinting, proAnnotations] - ); + // PrintTextWithGDI is a global setting in PDFium so we set it only temporary and restore it after + // printing the page. + OldPrintTextWithGDI := TPdfDocument.SetPrintTextWithGDI(FPrintTextWithGDI); + try + APage.Draw( + FPrinterDC, + RoundToInt(X), RoundToInt(Y), RoundToInt(ScaledWidth), RoundToInt(ScaledHeight), + prNormal, [proPrinting, proAnnotations] + ); + finally + if OldPrintTextWithGDI <> FPrintTextWithGDI then + TPdfDocument.SetPrintTextWithGDI(OldPrintTextWithGDI); + end; end; initialization diff --git a/Source/PdfiumCtrl.pas b/Source/PdfiumCtrl.pas index 26ee85f..0c5be93 100644 --- a/Source/PdfiumCtrl.pas +++ b/Source/PdfiumCtrl.pas @@ -249,10 +249,10 @@ TPdfDocumentVclPrinter = class(TPdfDocumentPrinter) FBeginDocCalled: Boolean; FPagePrinted: Boolean; protected - procedure BeginDoc; override; - procedure EndDoc; override; - procedure StartPage; override; - procedure EndPage; override; + function PrinterStartDoc: Boolean; override; + procedure PrinterEndDoc; override; + procedure PrinterStartPage; override; + procedure PrinterEndPage; override; function GetPrinterDC: HDC; override; end; @@ -289,15 +289,17 @@ function FastVclAbortProc(Prn: HDC; Error: Integer): Bool; stdcall; { TPdfDocumentVclPrinter } -procedure TPdfDocumentVclPrinter.BeginDoc; +function TPdfDocumentVclPrinter.PrinterStartDoc: Boolean; begin + Result := False; FPagePrinted := False; if not Printer.Printing then begin Printer.BeginDoc; FBeginDocCalled := Printer.Printing; + Result := FBeginDocCalled; end; - if Printer.Printing then + if Result 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. @@ -305,17 +307,17 @@ procedure TPdfDocumentVclPrinter.BeginDoc; end; end; -procedure TPdfDocumentVclPrinter.EndDoc; +procedure TPdfDocumentVclPrinter.PrinterEndDoc; begin if Printer.Printing then begin if FBeginDocCalled then Printer.EndDoc; end; - SetAbortProc(GetPrinterDC, @VclAbortProc); // restore (dangerous) default behavior + SetAbortProc(GetPrinterDC, @VclAbortProc); // restore default behavior end; -procedure TPdfDocumentVclPrinter.StartPage; +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. @@ -323,7 +325,7 @@ procedure TPdfDocumentVclPrinter.StartPage; Printer.NewPage; end; -procedure TPdfDocumentVclPrinter.EndPage; +procedure TPdfDocumentVclPrinter.PrinterEndPage; begin FPagePrinted := True; // The VCL uses "NewPage". For the very last page Printer.EndDoc calls Windows.EndPage. From 7f88c1e39ddc23d3efd422ae60747c133b1f8a19 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Fri, 23 Oct 2020 20:52:40 +0200 Subject: [PATCH 06/59] Fixed #13 --- Source/PdfiumCtrl.pas | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/PdfiumCtrl.pas b/Source/PdfiumCtrl.pas index 0c5be93..35a5d8f 100644 --- a/Source/PdfiumCtrl.pas +++ b/Source/PdfiumCtrl.pas @@ -83,7 +83,7 @@ TPdfControl = class(TCustomControl) 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; @@ -746,13 +746,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; @@ -774,7 +774,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 From 338250b47ae6a348493bbb3b24573ee7398422c9 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Mon, 26 Oct 2020 09:23:05 +0100 Subject: [PATCH 07/59] Call GetPrinterDC after PrinterStartDoc, otherwise we get a different DC and print empty pages. --- Source/PdfiumCore.pas | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Source/PdfiumCore.pas b/Source/PdfiumCore.pas index fc7a921..8bedb85 100644 --- a/Source/PdfiumCore.pas +++ b/Source/PdfiumCore.pas @@ -2746,13 +2746,15 @@ function TPdfDocumentPrinter.BeginPrint: Boolean; Inc(FBeginPrintCounter); if FBeginPrintCounter = 1 then begin - FPrinterDC := GetPrinterDC; - - GetPrinterBounds; - FPrintPortraitOrientation := IsPortraitOrientation(FPaperSize.cx, FPaperSize.cy); - Result := PrinterStartDoc; - if not Result then + if Result then + begin + FPrinterDC := GetPrinterDC; + + GetPrinterBounds; + FPrintPortraitOrientation := IsPortraitOrientation(FPaperSize.cx, FPaperSize.cy); + end + else begin FPrinterDC := 0; Dec(FBeginPrintCounter); From 66f585f7eaf3ae47614ee58514fbc315895f4a5f Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Fri, 30 Oct 2020 22:15:09 +0100 Subject: [PATCH 08/59] Added TPdfDocumentVclPrinter.PrintDocument helper function --- Example/MainFrm.pas | 10 +++--- Source/PdfiumCore.pas | 8 ++--- Source/PdfiumCtrl.pas | 79 ++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 85 insertions(+), 12 deletions(-) diff --git a/Example/MainFrm.pas b/Example/MainFrm.pas index b0f3c55..00cb00d 100644 --- a/Example/MainFrm.pas +++ b/Example/MainFrm.pas @@ -154,10 +154,12 @@ procedure TfrmMain.edtZoomChange(Sender: TObject); end; procedure TfrmMain.btnPrintClick(Sender: TObject); -var - PdfPrinter: TPdfDocumentPrinter; +{var + PdfPrinter: TPdfDocumentPrinter;} begin - PrintDialog1.MinPage := 1; + TPdfDocumentVclPrinter.PrintDocument(FCtrl.Document, 'PDF Example Print Job'); + +{ PrintDialog1.MinPage := 1; PrintDialog1.MaxPage := FCtrl.Document.PageCount; if PrintDialog1.Execute(Handle) then @@ -174,7 +176,7 @@ procedure TfrmMain.btnPrintClick(Sender: TObject); finally PdfPrinter.Free; end; - end; + end;} end; procedure TfrmMain.ListViewAttachmentsDblClick(Sender: TObject); diff --git a/Source/PdfiumCore.pas b/Source/PdfiumCore.pas index 8bedb85..cfb36c4 100644 --- a/Source/PdfiumCore.pas +++ b/Source/PdfiumCore.pas @@ -455,7 +455,7 @@ TPdfDocumentPrinter = class(TObject) function IsPortraitOrientation(AWidth, AHeight: Integer): Boolean; procedure GetPrinterBounds; protected - function PrinterStartDoc: Boolean; virtual; abstract; + function PrinterStartDoc(const AJobTitle: string): Boolean; virtual; abstract; procedure PrinterEndDoc; virtual; abstract; procedure PrinterStartPage; virtual; abstract; procedure PrinterEndPage; virtual; abstract; @@ -467,7 +467,7 @@ TPdfDocumentPrinter = class(TObject) { 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: Boolean; + function BeginPrint(const AJobTitle: string = ''): Boolean; { EndPrint must be called after printing multiple documents were printed. } procedure EndPrint; @@ -2741,12 +2741,12 @@ procedure TPdfDocumentPrinter.GetPrinterBounds; FMargins.Y := GetDeviceCaps(FPrinterDC, PHYSICALOFFSETY); end; -function TPdfDocumentPrinter.BeginPrint: Boolean; +function TPdfDocumentPrinter.BeginPrint(const AJobTitle: string): Boolean; begin Inc(FBeginPrintCounter); if FBeginPrintCounter = 1 then begin - Result := PrinterStartDoc; + Result := PrinterStartDoc(AJobTitle); if Result then begin FPrinterDC := GetPrinterDC; diff --git a/Source/PdfiumCtrl.pas b/Source/PdfiumCtrl.pas index 35a5d8f..56c6f69 100644 --- a/Source/PdfiumCtrl.pas +++ b/Source/PdfiumCtrl.pas @@ -9,7 +9,7 @@ interface uses - Windows, Messages, Types, SysUtils, Classes, Graphics, Controls, Forms, PdfiumCore; + Windows, Messages, Types, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, PdfiumCore; const cPdfControlDefaultDrawOptions = []; @@ -249,11 +249,19 @@ TPdfDocumentVclPrinter = class(TPdfDocumentPrinter) FBeginDocCalled: Boolean; FPagePrinted: Boolean; protected - function PrinterStartDoc: Boolean; override; + 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 @@ -289,12 +297,14 @@ function FastVclAbortProc(Prn: HDC; Error: Integer): Bool; stdcall; { TPdfDocumentVclPrinter } -function TPdfDocumentVclPrinter.PrinterStartDoc: Boolean; +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; @@ -336,6 +346,67 @@ function TPdfDocumentVclPrinter.GetPrinterDC: HDC; Result := Printer.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 + if (AParentWnd = 0) or not IsWindow(AParentWnd) then + Result := Dlg.Execute + else + Result := Dlg.Execute(AParentWnd); + + 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); @@ -386,7 +457,7 @@ procedure TPdfControl.DestroyWnd; {$IF CompilerVersion <= 20.0} // 2009 procedure TPdfControl.WMPrintClient(var Message: TWMPrintClient); -// emulate Delphi 2010' TControlState.csPrintClient +// Emulate Delphi 2010's TControlState.csPrintClient var LastPrintClient: Boolean; begin From 2e04d23c3a082efd13e1a8f6ee16d6ed23e52c0e Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Fri, 30 Oct 2020 22:36:23 +0100 Subject: [PATCH 09/59] Fix painting bug with selected text in a form field --- Source/PdfiumCtrl.pas | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/PdfiumCtrl.pas b/Source/PdfiumCtrl.pas index 56c6f69..1003bb3 100644 --- a/Source/PdfiumCtrl.pas +++ b/Source/PdfiumCtrl.pas @@ -530,7 +530,6 @@ 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); @@ -2198,6 +2197,7 @@ 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); From 429c57d9aa4cc944c45831f0eb604b46678e9db0 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Fri, 30 Oct 2020 22:49:14 +0100 Subject: [PATCH 10/59] Chrome/Edge use crHandPoint for ComboBox --- Source/PdfiumCtrl.pas | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/PdfiumCtrl.pas b/Source/PdfiumCtrl.pas index 1003bb3..69fdee3 100644 --- a/Source/PdfiumCtrl.pas +++ b/Source/PdfiumCtrl.pas @@ -1243,6 +1243,7 @@ procedure TPdfControl.MouseMove(Shift: TShiftState; X, Y: Integer); case CurrentPage.HasFormFieldAtPoint(PagePt.X, PagePt.Y) of fftTextField: NewCursor := crIBeam; + fftComboBox, fftSignature: NewCursor := crHandPoint; else From f3092f28ce09191c0a131b96f6fd1a8cd68b2ee7 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Fri, 30 Oct 2020 23:37:29 +0100 Subject: [PATCH 11/59] Fixed: Text selection wasn't disabled while selecting in a form field --- Source/PdfiumCore.pas | 16 +++++++++++++--- Source/PdfiumCtrl.pas | 17 ++++++++++++++--- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/Source/PdfiumCore.pas b/Source/PdfiumCore.pas index cfb36c4..6e5e704 100644 --- a/Source/PdfiumCore.pas +++ b/Source/PdfiumCore.pas @@ -263,7 +263,8 @@ TPdfPage = class(TObject) 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; TPdfAttachment = record private @@ -352,7 +353,8 @@ TCustomLoadDataRec = record FFormModified: Boolean; FOnFormInvalidate: TPdfFormInvalidateEvent; FOnFormOutputSelectedRect: TPdfFormOutputSelectedRectEvent; - FOnFormGetCurrentPage: TPdfFormGetCurrentPage; + FOnFormGetCurrentPage: TPdfFormGetCurrentPageEvent; + FOnFormFieldFocus: TPdfFormFieldFocusEvent; procedure InternLoadFromMem(Buffer: PByte; Size: NativeInt; const APassword: AnsiString); procedure InternLoadFromCustom(ReadFunc: TPdfDocumentCustomReadProc; ASize: LongWord; AParam: Pointer; const APassword: AnsiString); @@ -433,7 +435,8 @@ TCustomLoadDataRec = record 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; end; TPdfDocumentPrinterStatusEvent = procedure(Sender: TObject; CurrentPageNum, PageCount: Integer) of object; @@ -856,10 +859,17 @@ function FFI_GetRotation(pThis: PFPDF_FORMFILLINFO; page: FPDF_PAGE): Integer; c procedure FFI_SetCursor(pThis: PFPDF_FORMFILLINFO; nCursorType: Integer); cdecl; begin + // A better solution is to use check what form field type is under the mouse cursor in the + // MoveMove event. Chrome/Edge don'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; diff --git a/Source/PdfiumCtrl.pas b/Source/PdfiumCtrl.pas index 69fdee3..a2859b1 100644 --- a/Source/PdfiumCtrl.pas +++ b/Source/PdfiumCtrl.pas @@ -67,6 +67,7 @@ TPdfControl = class(TCustomControl) FOnPageChange: TNotifyEvent; FOnPaint: TNotifyEvent; FFormOutputSelectedRects: TPdfRectArray; + FFormFieldFocused: Boolean; procedure WMTimer(var Message: TWMTimer); message WM_TIMER; procedure WMVScroll(var Message: TWMVScroll); message WM_VSCROLL; @@ -109,6 +110,7 @@ TPdfControl = class(TCustomControl) 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 FormFieldFocus(Document: TPdfDocument; Value: PWideChar; ValueLen: Integer; FieldFocused: Boolean); procedure DrawAlphaSelection(DC: HDC; Page: TPdfPage; const ARects: TPdfRectArray); procedure DrawFormOutputSelectedRects(DC: HDC; Page: TPdfPage); protected @@ -429,6 +431,7 @@ constructor TPdfControl.Create(AOwner: TComponent); FDocument.OnFormInvalidate := FormInvalidate; FDocument.OnFormOutputSelectedRect := FormOutputSelectedRect; FDocument.OnFormGetCurrentPage := FormGetCurrentPage; + FDocument.OnFormFieldFocus := FormFieldFocus; ParentDoubleBuffered := False; ParentBackground := False; @@ -981,6 +984,7 @@ procedure TPdfControl.Close; begin FDocument.Close; FPageIndex := 0; + FFormFieldFocused := False; PageContentChanged(True); end; @@ -1159,7 +1163,7 @@ procedure TPdfControl.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: end; end; - if AllowUserTextSelection then + if AllowUserTextSelection and not FFormFieldFocused then begin if Button = mbLeft then begin @@ -1218,7 +1222,7 @@ 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); @@ -1253,7 +1257,7 @@ procedure TPdfControl.MouseMove(Shift: TShiftState; X, Y: Integer); end; end; - if AllowUserTextSelection then + if AllowUserTextSelection and not FFormFieldFocused then begin if FMousePressed then begin @@ -2221,5 +2225,12 @@ 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; + end. From 4ceeb7128a7e6a0795fc022bce60dd0516d2f860 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Fri, 30 Oct 2020 23:47:28 +0100 Subject: [PATCH 12/59] Fixed: Copy&Paste&Cut keyboard shortcuts didn't work in form fields. --- Source/PdfiumCtrl.pas | 79 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/Source/PdfiumCtrl.pas b/Source/PdfiumCtrl.pas index a2859b1..e300401 100644 --- a/Source/PdfiumCtrl.pas +++ b/Source/PdfiumCtrl.pas @@ -159,6 +159,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; @@ -1329,6 +1334,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 @@ -1568,7 +1614,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 @@ -1685,9 +1731,40 @@ procedure TPdfControl.KeyDown(var Key: Word; Shift: TShiftState); end; procedure TPdfControl.WMKeyDown(var Message: TWMKeyDown); +var + ShiftState: TShiftState; begin if AllowFormEvents and IsPageValid and CurrentPage.FormEventKeyDown(Message.CharCode, Message.KeyData) 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 + ShiftState := KeyDataToShiftState(Message.KeyData); + if ShiftState = [ssCtrl] then + begin + case Message.CharCode of + Ord('C'), VK_INSERT: + CopyFormTextToClipboard; + Ord('X'): + CutFormTextToClipboard; + Ord('V'): + PasteFormTextFromClipboard; + end; + end + else if ShiftState = [ssShift] then + begin + case Message.CharCode of + VK_INSERT: + PasteFormTextFromClipboard; + VK_DELETE: + CutFormTextToClipboard; + end; + end; + end; + end; Exit; + end; inherited; end; From 419f1b8b3d5f4abf93866bc18d716ad72c9cb789 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Sat, 7 Nov 2020 01:20:04 +0100 Subject: [PATCH 13/59] Use new FPDF_GetPageSizeByIndexF instead of old FPDF_GetPageSizeByIndex --- Source/PdfiumCore.pas | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Source/PdfiumCore.pas b/Source/PdfiumCore.pas index 6e5e704..8c5b8f3 100644 --- a/Source/PdfiumCore.pas +++ b/Source/PdfiumCore.pas @@ -1504,12 +1504,14 @@ 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 + 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; From 0737d17756506242346aa0fa3d0317dfa8a928f5 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Thu, 24 Dec 2020 15:06:22 +0100 Subject: [PATCH 14/59] Added missing "PDF events" for save and print --- Source/PdfiumCore.pas | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Source/PdfiumCore.pas b/Source/PdfiumCore.pas index 8c5b8f3..5d53321 100644 --- a/Source/PdfiumCore.pas +++ b/Source/PdfiumCore.pas @@ -1383,12 +1383,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); @@ -2821,6 +2827,9 @@ function TPdfDocumentPrinter.Print(ADocument: TPdfDocument; AFromPageIndex, AToP 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; @@ -2865,6 +2874,8 @@ function TPdfDocumentPrinter.Print(ADocument: TPdfDocument; AFromPageIndex, AToP 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; From 2596e8af66c51909bae942c90ae91dc181ca3e48 Mon Sep 17 00:00:00 2001 From: Graham Murt Date: Fri, 24 Sep 2021 09:14:32 +0100 Subject: [PATCH 15/59] Added page border and drop shadow. --- Source/PdfiumCtrl.pas | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Source/PdfiumCtrl.pas b/Source/PdfiumCtrl.pas index e300401..d2e9c5e 100644 --- a/Source/PdfiumCtrl.pas +++ b/Source/PdfiumCtrl.pas @@ -738,6 +738,20 @@ procedure TPdfControl.Paint; // Draw the highlighted text overlay DrawHighlightText(DrawDC, Page); + // draw page borders + Brush.Color := clBlack; + FillRect(DrawDC, Rect(FDrawX, FDrawY, FDrawX+FDrawWidth, FDrawY+1), Brush.Handle); // top border + FillRect(DrawDC, Rect(FDrawX, FDrawY, FDrawX+1, FDrawY + FDrawHeight), Brush.Handle); // left border + FillRect(DrawDC, Rect(FDrawX + FDrawWidth-1, FDrawY, FDrawX+FDrawWidth, FDrawY + FDrawHeight), Brush.Handle); // right border + FillRect(DrawDC, Rect(FDrawX, FDrawY + FDrawHeight-1, FDrawX+FDrawWidth, FDrawY+FDrawHeight), Brush.Handle); // bottom bar + + // draw page shadow + Brush.Color := clDkGray; + FillRect(DrawDC, Rect(FDrawX + FDrawWidth, FDrawY+4, FDrawX + FDrawWidth+4, FDrawY + FDrawHeight+4), Brush.Handle); // right border + FillRect(DrawDC, Rect(FDrawX+4, FDrawY + FDrawHeight, FDrawX+FDrawWidth+4, FDrawY+FDrawHeight+4), Brush.Handle); // bottom bar + Brush.Color := Color; + + // User painting if Assigned(FOnPaint) then begin @@ -1887,6 +1901,8 @@ procedure TPdfControl.UpdatePageDrawInfo; H := Round(PageHeight / 72 * DpiY * (ZoomPercentage / 100)); end; end; + w := w - 48; + h := h - 48; end; var From f9be25c366f4b44e4e31a170a6fc5b935de1aa87 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Fri, 24 Sep 2021 20:11:21 +0200 Subject: [PATCH 16/59] Moved border and shadow code to own method and made it optional with default off. --- Example/MainFrm.pas | 3 ++ Source/PdfiumCtrl.pas | 108 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 96 insertions(+), 15 deletions(-) diff --git a/Example/MainFrm.pas b/Example/MainFrm.pas index 00cb00d..ef937f4 100644 --- a/Example/MainFrm.pas +++ b/Example/MainFrm.pas @@ -63,6 +63,9 @@ 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; diff --git a/Source/PdfiumCtrl.pas b/Source/PdfiumCtrl.pas index d2e9c5e..c72fa51 100644 --- a/Source/PdfiumCtrl.pas +++ b/Source/PdfiumCtrl.pas @@ -68,6 +68,10 @@ TPdfControl = class(TCustomControl) FOnPaint: TNotifyEvent; FFormOutputSelectedRects: TPdfRectArray; FFormFieldFocused: Boolean; + FPageShadowSize: Integer; + FPageShadowColor: TColor; + FPageShadowPadding: Integer; + FPageBorderColor: TColor; procedure WMTimer(var Message: TWMTimer); message WM_TIMER; procedure WMVScroll(var Message: TWMVScroll); message WM_VSCROLL; @@ -92,6 +96,10 @@ 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); @@ -102,6 +110,7 @@ TPdfControl = class(TCustomControl) procedure DocumentLoaded; procedure DrawSelection(DC: HDC; Page: TPdfPage); procedure DrawHighlightText(DC: HDC; Page: TPdfPage); + procedure DrawBorderAndShadow(DC: HDC); function InternPageToDevice(Page: TPdfPage; PageRect: TPdfRect): TRect; procedure SetZoomPercentage(Value: Integer); procedure DrawPage(DC: HDC; Page: TPdfPage; DirectDrawPage: Boolean); @@ -205,6 +214,12 @@ 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 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; + property OnWebLinkClick: TPdfControlWebLinkClickEvent read FOnWebLinkClick write FOnWebLinkClick; property OnPageChange: TNotifyEvent read FOnPageChange write FOnPageChange; @@ -432,6 +447,11 @@ constructor TPdfControl.Create(AOwner: TComponent); FScrollTimer := True; FBufferedPageDraw := True; + FPageBorderColor := clNone; + FPageShadowColor := clNone; + FPageShadowSize := 4; + FPageShadowPadding := 44; + FDocument := TPdfDocument.Create; FDocument.OnFormInvalidate := FormInvalidate; FDocument.OnFormOutputSelectedRect := FormOutputSelectedRect; @@ -574,6 +594,35 @@ procedure TPdfControl.DrawHighlightText(DC: HDC; Page: TPdfPage); end; end; +procedure TPdfControl.DrawBorderAndShadow(DC: HDC); +var + BorderBrush, ShadowBrush: HBRUSH; +begin + // Draw page borders + if PageBorderColor <> clNone then + begin + 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; + + // 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; + procedure TPdfControl.DrawPage(DC: HDC; Page: TPdfPage; DirectDrawPage: Boolean); procedure Draw(DC: HDC; X, Y: Integer; Page: TPdfPage); @@ -738,19 +787,7 @@ procedure TPdfControl.Paint; // Draw the highlighted text overlay DrawHighlightText(DrawDC, Page); - // draw page borders - Brush.Color := clBlack; - FillRect(DrawDC, Rect(FDrawX, FDrawY, FDrawX+FDrawWidth, FDrawY+1), Brush.Handle); // top border - FillRect(DrawDC, Rect(FDrawX, FDrawY, FDrawX+1, FDrawY + FDrawHeight), Brush.Handle); // left border - FillRect(DrawDC, Rect(FDrawX + FDrawWidth-1, FDrawY, FDrawX+FDrawWidth, FDrawY + FDrawHeight), Brush.Handle); // right border - FillRect(DrawDC, Rect(FDrawX, FDrawY + FDrawHeight-1, FDrawX+FDrawWidth, FDrawY+FDrawHeight), Brush.Handle); // bottom bar - - // draw page shadow - Brush.Color := clDkGray; - FillRect(DrawDC, Rect(FDrawX + FDrawWidth, FDrawY+4, FDrawX + FDrawWidth+4, FDrawY + FDrawHeight+4), Brush.Handle); // right border - FillRect(DrawDC, Rect(FDrawX+4, FDrawY + FDrawHeight, FDrawX+FDrawWidth+4, FDrawY+FDrawHeight+4), Brush.Handle); // bottom bar - Brush.Color := Color; - + DrawBorderAndShadow(DrawDC); // User painting if Assigned(FOnPaint) then @@ -784,6 +821,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; @@ -1072,6 +1110,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); @@ -1901,8 +1975,12 @@ procedure TPdfControl.UpdatePageDrawInfo; H := Round(PageHeight / 72 * DpiY * (ZoomPercentage / 100)); end; end; - w := w - 48; - h := h - 48; + + if (PageShadowColor <> clNone) and (PageShadowSize > 0) and (PageShadowPadding > 0) then + begin + W := W - (PageShadowPadding + PageShadowSize); + H := H - (PageShadowPadding + PageShadowSize); + end; end; var From 37685d42da1de7462df82ac488cace4faf63a22a Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Thu, 7 Oct 2021 20:10:17 +0200 Subject: [PATCH 17/59] Fixed #19. CurrentPage could return NIL causing an access violation --- Source/PdfiumCtrl.pas | 77 +++++++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 32 deletions(-) diff --git a/Source/PdfiumCtrl.pas b/Source/PdfiumCtrl.pas index c72fa51..ca16843 100644 --- a/Source/PdfiumCtrl.pas +++ b/Source/PdfiumCtrl.pas @@ -1168,7 +1168,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; @@ -1179,7 +1179,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; @@ -1190,7 +1190,7 @@ 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; @@ -1206,27 +1206,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 @@ -1237,21 +1245,22 @@ 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; @@ -1261,7 +1270,7 @@ procedure TPdfControl.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: 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; @@ -1290,13 +1299,15 @@ procedure TPdfControl.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: In var PagePt: TPdfPoint; Url: string; + Page: TPdfPage; 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 @@ -1305,7 +1316,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; @@ -1328,6 +1339,7 @@ procedure TPdfControl.MouseMove(Shift: TShiftState; X, Y: Integer); PagePt: TPdfPoint; Style: NativeInt; NewCursor: TCursor; + Page: TPdfPage; begin inherited MouseMove(Shift, X, Y); NewCursor := Cursor; @@ -1335,9 +1347,10 @@ 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 + case Page.HasFormFieldAtPoint(PagePt.X, PagePt.Y) of fftTextField: NewCursor := crIBeam; fftComboBox, @@ -1498,7 +1511,7 @@ 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)); @@ -1611,7 +1624,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 @@ -1619,7 +1632,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); @@ -1629,7 +1642,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); @@ -1660,7 +1673,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; @@ -1672,7 +1685,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; @@ -1929,7 +1942,7 @@ function TPdfControl.IsWebLinkAt(X, Y: Integer; var Url: string): Boolean; begin Index := GetWebLinkIndex(X, Y); Result := Index <> -1; - if Result then + if Result and IsPageValid then Url := CurrentPage.GetWebLinkURL(Index) else Url := ''; @@ -2330,7 +2343,7 @@ procedure TPdfControl.CalcHighlightTextRects; begin OldHighlightTextRects := FHighlightTextRects; FHighlightTextRects := nil; - if IsPageValid and (FHighlightText <> '') then + if (FHighlightText <> '') and IsPageValid then begin Page := CurrentPage; Num := 0; From a546dcf862370f73263123ee717dd2a9f31c9c9e Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Thu, 7 Oct 2021 22:18:14 +0200 Subject: [PATCH 18/59] Updated to chromium/4660 --- README.md | 5 +- Source/PdfiumLib.pas | 611 +++++++++++++++++++++++++++++++++---------- 2 files changed, 477 insertions(+), 139 deletions(-) diff --git a/README.md b/README.md index 631c445..30be7e6 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/4660](https://github.com/bblanchon/pdfium-binaries/releases/tag/chromium%2F4660) + ## Required pdfium.dll version -chromium/4243 +chromium/4660 ## Features - Multiple PDF load functions: @@ -16,6 +18,7 @@ chromium/4243 - Active TSteam (stream must not be released before the PDF document is closed) - Callback - 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) diff --git a/Source/PdfiumLib.pas b/Source/PdfiumLib.pas index 6d220b7..e08ccc7 100644 --- a/Source/PdfiumLib.pas +++ b/Source/PdfiumLib.pas @@ -3,7 +3,7 @@ // Use DLLs (x64, x86) from https://github.com/bblanchon/pdfium-binaries // -// DLL Version: chromium/4243 +// DLL Version: chromium/4660 unit PdfiumLib; @@ -80,10 +80,11 @@ __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. + // 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; @@ -91,6 +92,7 @@ __FPDF_PTRREC = record end; 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; @@ -106,6 +108,7 @@ __FPDF_PTRREC = record end; 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; @@ -352,6 +355,12 @@ FPDF_LIBRARY_CONFIG = record // 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 @@ -615,6 +624,23 @@ FPDF_FILEHANDLER = record var FPDF_DocumentHasValidCrossReferenceTable: function(document: FPDF_DOCUMENT): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// 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_GetDocPermission // Get file permission flags of the document. // Parameters: @@ -1423,6 +1449,8 @@ function FPDF_GetAValue(argb: DWORD): Byte; inline; 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; @@ -1599,6 +1627,36 @@ 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. +// 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. +// +// 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(path: FPDF_PAGEOBJECT; const matrix: PFS_MATRIX): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // Transform all annotations in |page|. // // page - handle to a page. @@ -1878,26 +1936,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. @@ -2099,7 +2138,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. @@ -2173,6 +2211,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|. // @@ -2185,7 +2275,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. @@ -2195,7 +2284,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. @@ -2206,7 +2294,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. @@ -2216,7 +2303,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. @@ -2285,7 +2371,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. @@ -2296,37 +2381,7 @@ 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. -// -// The matrix is composed as: -// |a c e| -// |b d f| -// and used to scale, rotate, shear and translate the path. -// -// Returns TRUE on success. -var - FPDFPath_GetMatrix: function(path: FPDF_PAGEOBJECT; matrix: PFS_MATRIX): FPDF_BOOL; {$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. -// -// The matrix is composed as: -// |a c e| -// |b d f| -// and can be used to scale, rotate, shear and translate the path. -// -// Returns TRUE on success. -var - FPDFPath_SetMatrix: function(path: FPDF_PAGEOBJECT; const matrix: PFS_MATRIX): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; - - // Create a new text object using one of the standard PDF fonts. +// Create a new text object using one of the standard PDF fonts. // // document - handle to the document. // font - string containing the font name, without spaces. @@ -2336,7 +2391,7 @@ FPDF_IMAGEOBJ_METADATA = record var FPDFPageObj_NewTextObj: function(document: FPDF_DOCUMENT; font: FPDF_BYTESTRING; font_size: Single): FPDF_PAGEOBJECT; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -// Set the text for a textobject. If it had text, it will be replaced. +// Set the text for a text object. If it had text, it will be replaced. // // text_object - handle to the text object. // text - the UTF-16LE encoded string containing the text to be added. @@ -2345,6 +2400,18 @@ FPDF_IMAGEOBJ_METADATA = record var FPDFText_SetText: function(text_object: FPDF_PAGEOBJECT; text: FPDF_WIDESTRING): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Experimental API. +// Set the text using charcodes for a text object. If it had text, it will be +// replaced. +// +// text_object - handle to the text object. +// charcodes - pointer to an array of charcodes to be added. +// count - number of elements in |charcodes|. +// +// Returns TRUE on success +var + FPDFText_SetCharcodes: function(text_object: FPDF_PAGEOBJECT; const charcodes: PUINT; 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. // @@ -2376,30 +2443,16 @@ FPDF_IMAGEOBJ_METADATA = record 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. +// Get the font size of a text object. // // text - handle to a text. -// matrix - pointer to struct with the matrix value. // -// The matrix is composed as: -// |a c e| -// |b d f| -// and used to scale, rotate, shear and translate the text. +// size - pointer to the font size of the text object, measured in points +// (about 1/72 inch) // // Returns TRUE on success. var - FPDFTextObj_GetMatrix: function(text: FPDF_PAGEOBJECT; matrix: PFS_MATRIX): FPDF_BOOL; {$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. -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. // @@ -2417,7 +2470,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. @@ -2438,41 +2490,154 @@ 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-8 encoding. +// 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_GetFontName: function(text: FPDF_PAGEOBJECT; buffer: Pointer; length: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + FPDFTextObj_GetText: function(text_object: FPDF_PAGEOBJECT; text_page: FPDF_TEXTPAGE; buffer: FPDF_WCHAR; + length: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; // Experimental API. -// Get the text of a text object. +// Get the font of a text object. // -// 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|. +// text - the handle to the text object. // -// Returns the number of bytes in the text (including the trailing NUL +// 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 font name of a font. +// +// 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 font 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_GetFontName: function(font: FPDF_FONT; buffer: PAnsiChar; length: LongWord): LongWord; {$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 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. @@ -2481,7 +2646,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. @@ -2491,33 +2655,37 @@ FPDF_IMAGEOBJ_METADATA = record var FPDFFormObj_GetObject: function(form_object: FPDF_PAGEOBJECT; index: LongWord): FPDF_PAGEOBJECT; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// *** _FPDF_PPO_H_ *** + // Experimental API. -// Get the transform matrix of a form object. +// Import pages to a FPDF_DOCUMENT. // -// form_object - handle to a form. -// matrix - pointer to struct to receive the matrix value. +// 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. // -// The matrix is composed as: -// |a c e| -// |b d f| -// and used to scale, rotate, shear and translate the form object. -// -// Returns TRUE on success. +// Returns TRUE on success. Returns FALSE if any pages in |page_indices| is +// invalid. var - FPDFFormObj_GetMatrix: function(form_object: FPDF_PAGEOBJECT; matrix: PFS_MATRIX): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; - - -// *** _FPDF_PPO_H_ *** + 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}; @@ -2542,6 +2710,29 @@ 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}; +// Experimental API. +// Create a template to generate form xobjects from |src_doc|'s page at +// |src_page_index|, for use in |dest_doc|. +// +// Returns a handle on success, or NULL on failure. Caller owns the newly +// created object. +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. @@ -3472,6 +3663,16 @@ IFSDK_PAUSE = record 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_ *** @@ -3573,7 +3774,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}; @@ -3583,8 +3784,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}; @@ -3731,6 +3935,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}; @@ -3792,6 +3998,8 @@ FS_QUADPOINTSF = record // // 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}; @@ -4284,8 +4492,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. @@ -5785,9 +5991,10 @@ FPDF_FORMFILLINFO = record //* 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. +//* 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. //* @@ -5801,9 +6008,10 @@ FPDF_FORMFILLINFO = record //* 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. +//* 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. //* @@ -5815,12 +6023,12 @@ FPDF_FORMFILLINFO = record //* Call this member function when a keystroke translates to a //* nonsystem character. //* Parameters: -//* hHandle - Handle to the form fill module, as returned by +//* 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. +//* 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. //* @@ -6289,6 +6497,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; @@ -6333,8 +6542,19 @@ 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 +// - freetext +// - highlight +// - ink +// - link +// - popup +// - square, +// - squiggly +// - stamp +// - strikeout +// - text +// - underline // // subtype - the subtype to be checked. // @@ -6626,6 +6846,86 @@ 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. // Check if |annot|'s dictionary has |key| as a key. // @@ -7011,6 +7311,15 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; 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}; // *** _FPDF_CATALOG_H_ *** @@ -7834,7 +8143,7 @@ TImportFuncRec = record end; const - ImportFuncs: array[0..371 + ImportFuncs: array[0..397 {$IFDEF MSWINDOWS} + 2 {$IFDEF PDFIUM_PRINT_TEXT_WITH_GDI} + 2 {$ENDIF} @@ -7863,6 +8172,7 @@ TImportFuncRec = record (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_GetSecurityHandlerRevision; N: 'FPDF_GetSecurityHandlerRevision'), (P: @@FPDF_GetPageCount; N: 'FPDF_GetPageCount'), @@ -7934,6 +8244,8 @@ TImportFuncRec = record (P: @@FPDFPageObj_HasTransparency; N: 'FPDFPageObj_HasTransparency'), (P: @@FPDFPageObj_GetType; N: 'FPDFPageObj_GetType'), (P: @@FPDFPageObj_Transform; N: 'FPDFPageObj_Transform'), + (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_CountMarks; N: 'FPDFPageObj_CountMarks'), @@ -7953,7 +8265,6 @@ TImportFuncRec = record (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'), @@ -7977,6 +8288,11 @@ TImportFuncRec = record (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'), @@ -7988,27 +8304,38 @@ TImportFuncRec = record (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_SetCharcodes; N: 'FPDFText_SetCharcodes'), (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: @@FPDFTextObj_GetFont; N: 'FPDFTextObj_GetFont'), + (P: @@FPDFFont_GetFontName; N: 'FPDFFont_GetFontName'), + (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_GetMatrix; N: 'FPDFFormObj_GetMatrix'), // *** _FPDF_PPO_H_ *** + (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_ *** @@ -8068,6 +8395,7 @@ TImportFuncRec = record (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'), @@ -8244,6 +8572,12 @@ TImportFuncRec = record (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_HasKey; N: 'FPDFAnnot_HasKey'), (P: @@FPDFAnnot_GetValueType; N: 'FPDFAnnot_GetValueType'), (P: @@FPDFAnnot_SetStringValue; N: 'FPDFAnnot_SetStringValue'), @@ -8271,6 +8605,7 @@ TImportFuncRec = record (P: @@FPDFAnnot_GetFormControlCount; N: 'FPDFAnnot_GetFormControlCount'), (P: @@FPDFAnnot_GetFormControlIndex; N: 'FPDFAnnot_GetFormControlIndex'), (P: @@FPDFAnnot_GetFormFieldExportValue; N: 'FPDFAnnot_GetFormFieldExportValue'), + (P: @@FPDFAnnot_SetURI; N: 'FPDFAnnot_SetURI'), {$IFDEF PDF_ENABLE_V8} // *** _FPDF_LIBS_H_ *** From c3e924c8312bd331139fe4be46c323a8936e24e2 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Thu, 7 Oct 2021 22:21:33 +0200 Subject: [PATCH 19/59] Added TPdfDocument.CreateNPagesOnOnePageDocument, ImportAllPages, ImportPagesByIndex Fixed: TPdfDocument.PageSizes[] returned invalid values --- Source/PdfiumCore.pas | 104 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 89 insertions(+), 15 deletions(-) diff --git a/Source/PdfiumCore.pas b/Source/PdfiumCore.pas index 5d53321..d04ffba 100644 --- a/Source/PdfiumCore.pas +++ b/Source/PdfiumCore.pas @@ -8,6 +8,11 @@ interface uses Windows, WinSpool, Types, SysUtils, Classes, Contnrs, PdfiumLib, Graphics; +const + // DIN A4 + PdfDefaultPageWidth = 595; + PdfDefaultPageHeight = 842; + type EPdfException = class(Exception); EPdfUnsupportedFeatureException = class(EPdfException); @@ -89,13 +94,15 @@ TPdfRect = record ); TPdfPrintMode = ( - pmEMF = 0, - pmTextMode = 1, - pmPostScript2 = 2, - pmPostScript3 = 3, - pmPostScriptPassThrough2 = 4, - pmPostScriptPassThrough3 = 5, - pmEMFImageMasks = 6 + 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 = ( @@ -357,7 +364,10 @@ TCustomLoadDataRec = record FOnFormFieldFocus: TPdfFormFieldFocusEvent; procedure InternLoadFromMem(Buffer: PByte; Size: NativeInt; const APassword: AnsiString); - procedure InternLoadFromCustom(ReadFunc: TPdfDocumentCustomReadProc; ASize: LongWord; AParam: Pointer; const APassword: AnsiString); + procedure InternLoadFromCustom(ReadFunc: TPdfDocumentCustomReadProc; ASize: LongWord; + AParam: Pointer; const APassword: AnsiString); + 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); @@ -394,9 +404,14 @@ 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 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; @@ -1321,9 +1336,39 @@ 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; +begin + Result := TPdfDocument.Create; + try + if (Source = nil) or not Source.Active then + Result.NewDocument + else + begin + Result.FDocument := FPDF_ImportNPagesToOne(Source.FDocument, NewPageWidth, NewPageHeight, NumPagesXAxis, NumPagesYAxis); + 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; @@ -1332,8 +1377,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 @@ -1348,6 +1397,24 @@ 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.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; @@ -1438,7 +1505,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 @@ -1449,6 +1516,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; @@ -1514,7 +1586,9 @@ function TPdfDocument.GetPageSize(Index: Integer): TPdfPoint; SizeF: TFSSizeF; begin CheckActive; - if FPDF_GetPageSizeByIndexF(FDocument, Index, @SizeF) = 0 then + Result.X := 0; + Result.Y := 0; + if FPDF_GetPageSizeByIndexF(FDocument, Index, @SizeF) <> 0 then begin Result.X := SizeF.width; Result.Y := SizeF.height; From 612104fdcb4297f5d1434957d823beeb7ee3e9eb Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Sat, 5 Mar 2022 23:59:44 +0100 Subject: [PATCH 20/59] Updated to chromium/4915 --- Example/MainFrm.pas | 1 - Source/PdfiumCore.pas | 93 ++-- Source/PdfiumCtrl.pas | 28 +- Source/PdfiumLib.pas | 1175 ++++++++++++++++++++++++----------------- 4 files changed, 739 insertions(+), 558 deletions(-) diff --git a/Example/MainFrm.pas b/Example/MainFrm.pas index ef937f4..1148863 100644 --- a/Example/MainFrm.pas +++ b/Example/MainFrm.pas @@ -169,7 +169,6 @@ procedure TfrmMain.btnPrintClick(Sender: TObject); begin PdfPrinter := TPdfDocumentVclPrinter.Create; try - //PdfPrinter.PrintTextWithGDI := True; //PdfPrinter.FitPageToPrintArea := False; if PrintDialog1.PrintRange = prAllPages then diff --git a/Source/PdfiumCore.pas b/Source/PdfiumCore.pas index d04ffba..44872ba 100644 --- a/Source/PdfiumCore.pas +++ b/Source/PdfiumCore.pas @@ -198,6 +198,7 @@ TPdfPage = class(TObject) function GetMouseModifier(const Shift: TShiftState): Integer; function GetKeyModifier(KeyData: LPARAM): Integer; function GetHandle: FPDF_PAGE; + function GetTextHandle: FPDF_TEXTPAGE; public destructor Destroy; override; procedure Close; @@ -262,6 +263,8 @@ TPdfPage = class(TObject) function GetWebLinkRect(LinkIndex, RectIndex: Integer): TPdfRect; 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; @@ -363,9 +366,9 @@ TCustomLoadDataRec = record FOnFormGetCurrentPage: TPdfFormGetCurrentPageEvent; FOnFormFieldFocus: TPdfFormFieldFocusEvent; - procedure InternLoadFromMem(Buffer: PByte; Size: NativeInt; const APassword: AnsiString); + procedure InternLoadFromMem(Buffer: PByte; Size: NativeInt; const APassword: UTF8String); procedure InternLoadFromCustom(ReadFunc: TPdfDocumentCustomReadProc; ASize: LongWord; - AParam: Pointer; const APassword: AnsiString); + AParam: Pointer; const APassword: UTF8String); function InternImportPages(Source: TPdfDocument; PageIndices: PInteger; PageIndicesCount: Integer; const Range: AnsiString; Index: Integer; ImportByRange: Boolean): Boolean; function GetPage(Index: Integer): TPdfPage; @@ -390,13 +393,13 @@ TCustomLoadDataRec = record 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: NativeInt; 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: NativeInt; ACount: NativeInt; const APassword: AnsiString = ''); overload; - procedure LoadFromStream(AStream: TStream; const APassword: AnsiString = ''); - procedure LoadFromFile(const AFileName: string; const APassword: AnsiString = ''; ALoadOption: TPdfDocumentLoadOption = dloMMF); + procedure LoadFromCustom(ReadFunc: TPdfDocumentCustomReadProc; ASize: LongWord; AParam: Pointer; const APassword: UTF8String = ''); + procedure LoadFromActiveStream(Stream: TStream; const APassword: UTF8String = ''); // Stream must not be released until the document is closed + procedure LoadFromActiveBuffer(Buffer: Pointer; Size: NativeInt; const APassword: UTF8String = ''); // Buffer must not be released until the document is closed + procedure LoadFromBytes(const ABytes: TBytes; const APassword: UTF8String = ''); overload; + procedure LoadFromBytes(const ABytes: TBytes; AIndex: NativeInt; ACount: NativeInt; const APassword: UTF8String = ''); overload; + procedure LoadFromStream(AStream: TStream; const APassword: UTF8String = ''); + procedure LoadFromFile(const AFileName: string; const APassword: UTF8String = ''; ALoadOption: TPdfDocumentLoadOption = dloMMF); procedure Close; procedure SaveToFile(const AFileName: string; Option: TPdfDocumentSaveOption = dsoRemoveSecurity; FileVersion: Integer = -1); @@ -419,8 +422,6 @@ TCustomLoadDataRec = record function GetMetaText(const TagName: string): string; class function SetPrintMode(PrintMode: TPdfPrintMode): Boolean; static; - class function SetPrintTextWithGDI(UseGdi: Boolean): Boolean; static; - class function GetPrintTextWithGDI: Boolean; static; property FileName: string read FFileName; property PageCount: Integer read GetPageCount; @@ -466,7 +467,6 @@ TPdfDocumentPrinter = class(TObject) FPrintArea: TSize; FMargins: TPoint; - FPrintTextWithGDI: Boolean; FFitPageToPrintArea: Boolean; FOnPrintStatus: TPdfDocumentPrinterStatusEvent; @@ -495,10 +495,6 @@ TPdfDocumentPrinter = class(TObject) function Print(ADocument: TPdfDocument): Boolean; overload; - { If PrintTextWithGDI is true the text on PDF pages are printed with GDI if the font is - installed on the system. Otherwise the text is converted to vectors. } - property PrintTextWithGDI: Boolean read FPrintTextWithGDI write FPrintTextWithGDI default False; - { If FitPageToPrintArea is true the page fill be scaled to fit into the printable area. } property FitPageToPrintArea: Boolean read FFitPageToPrintArea write FFitPageToPrintArea default True; @@ -540,9 +536,6 @@ implementation ThreadPdfUnsupportedFeatureHandler: TPdfUnsupportedFeatureHandler; UnsupportedFeatureCurrentDocument: TPdfDocument; -var - GPrintTextWithGDI: Boolean = False; - type { We don't want to use a TBytes temporary array if we can convert directly into the destination buffer. } @@ -1023,7 +1016,7 @@ function ReadFromActiveFile(Param: Pointer; Position: LongWord; Buffer: PByte; S Result := Size = 0; end; -procedure TPdfDocument.LoadFromFile(const AFileName: string; const APassword: AnsiString; ALoadOption: TPdfDocumentLoadOption); +procedure TPdfDocument.LoadFromFile(const AFileName: string; const APassword: UTF8String; ALoadOption: TPdfDocumentLoadOption); var Size: Int64; Offset: NativeInt; @@ -1105,7 +1098,7 @@ procedure TPdfDocument.LoadFromFile(const AFileName: string; const APassword: An FFileName := AFileName; end; -procedure TPdfDocument.LoadFromStream(AStream: TStream; const APassword: AnsiString); +procedure TPdfDocument.LoadFromStream(AStream: TStream; const APassword: UTF8String); var Size: NativeInt; begin @@ -1124,19 +1117,19 @@ procedure TPdfDocument.LoadFromStream(AStream: TStream; const APassword: AnsiStr end; end; -procedure TPdfDocument.LoadFromActiveBuffer(Buffer: Pointer; Size: NativeInt; const APassword: AnsiString); +procedure TPdfDocument.LoadFromActiveBuffer(Buffer: Pointer; Size: NativeInt; const APassword: UTF8String); begin Close; InternLoadFromMem(Buffer, Size, APassword); end; -procedure TPdfDocument.LoadFromBytes(const ABytes: TBytes; const APassword: AnsiString); +procedure TPdfDocument.LoadFromBytes(const ABytes: TBytes; const APassword: UTF8String); begin LoadFromBytes(ABytes, 0, Length(ABytes), APassword); end; procedure TPdfDocument.LoadFromBytes(const ABytes: TBytes; AIndex, ACount: NativeInt; - const APassword: AnsiString); + const APassword: UTF8String); var Len: NativeInt; begin @@ -1163,7 +1156,7 @@ 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 APassword: UTF8String); begin if Stream = nil then Close @@ -1172,7 +1165,7 @@ procedure TPdfDocument.LoadFromActiveStream(Stream: TStream; const APassword: An end; procedure TPdfDocument.LoadFromCustom(ReadFunc: TPdfDocumentCustomReadProc; ASize: LongWord; - AParam: Pointer; const APassword: AnsiString); + AParam: Pointer; const APassword: UTF8String); begin Close; InternLoadFromCustom(ReadFunc, ASize, AParam, APassword); @@ -1187,7 +1180,7 @@ function GetLoadFromCustomBlock(Param: Pointer; Position: LongWord; Buffer: PByt end; procedure TPdfDocument.InternLoadFromCustom(ReadFunc: TPdfDocumentCustomReadProc; ASize: LongWord; - AParam: Pointer; const APassword: AnsiString); + AParam: Pointer; const APassword: UTF8String); var OldCurDoc: TPdfDocument; begin @@ -1203,7 +1196,7 @@ procedure TPdfDocument.InternLoadFromCustom(ReadFunc: TPdfDocumentCustomReadProc OldCurDoc := UnsupportedFeatureCurrentDocument; try UnsupportedFeatureCurrentDocument := Self; - FDocument := FPDF_LoadCustomDocument(@FCustomLoadData.FileAccess, PAnsiChar(APassword)); + FDocument := FPDF_LoadCustomDocument(@FCustomLoadData.FileAccess, PAnsiChar(Pointer(APassword))); DocumentLoaded; finally UnsupportedFeatureCurrentDocument := OldCurDoc; @@ -1211,7 +1204,7 @@ procedure TPdfDocument.InternLoadFromCustom(ReadFunc: TPdfDocumentCustomReadProc end; end; -procedure TPdfDocument.InternLoadFromMem(Buffer: PByte; Size: NativeInt; const APassword: AnsiString); +procedure TPdfDocument.InternLoadFromMem(Buffer: PByte; Size: NativeInt; const APassword: UTF8String); var OldCurDoc: TPdfDocument; begin @@ -1613,19 +1606,6 @@ class function TPdfDocument.SetPrintMode(PrintMode: TPdfPrintMode): Boolean; Result := FPDF_SetPrintMode(Ord(PrintMode)) <> 0; end; -class function TPdfDocument.SetPrintTextWithGDI(UseGdi: Boolean): Boolean; -begin - InitLib; - FPDF_SetPrintTextWithGDI(Ord(UseGdi)); - Result := GPrintTextWithGDI; - GPrintTextWithGDI := UseGdi; -end; - -class function TPdfDocument.GetPrintTextWithGDI: Boolean; -begin - Result := GPrintTextWithGDI; -end; - procedure TPdfDocument.SetFormFieldHighlightAlpha(Value: Integer); begin if Value < 0 then @@ -2376,6 +2356,14 @@ function TPdfPage.IsLoaded: Boolean; Result := FPage <> nil; end; +function TPdfPage.GetTextHandle: FPDF_TEXTPAGE; +begin + if BeginText then + Result := FTextHandle + else + Result := nil; +end; + { _TPdfBitmapHideCtor } procedure _TPdfBitmapHideCtor.Create; @@ -2529,7 +2517,6 @@ procedure TPdfAttachment.SetContent(const Value: RawByteString); SetContent(PByte(PAnsiChar(Value)), Length(Value) * SizeOf(AnsiChar)); end; - procedure TPdfAttachment.SetContent(const Value: string; Encoding: TEncoding = nil); begin CheckValid; @@ -2812,7 +2799,6 @@ function TPdfAttachment.GetContentAsString(Encoding: TEncoding): string; constructor TPdfDocumentPrinter.Create; begin inherited Create; - FPrintTextWithGDI := False; FFitPageToPrintArea := True; end; @@ -2979,7 +2965,6 @@ procedure TPdfDocumentPrinter.InternPrintPage(APage: TPdfPage; X, Y, Width, Heig PageWidth, PageHeight: Double; PageScale, PrintScale: Double; ScaledWidth, ScaledHeight: Double; - OldPrintTextWithGDI: Boolean; begin PageWidth := APage.Width; PageHeight := APage.Height; @@ -2997,19 +2982,11 @@ procedure TPdfDocumentPrinter.InternPrintPage(APage: TPdfPage; X, Y, Width, Heig X := X + (Width - ScaledWidth) / 2; Y := Y + (Height - ScaledHeight) / 2; - // PrintTextWithGDI is a global setting in PDFium so we set it only temporary and restore it after - // printing the page. - OldPrintTextWithGDI := TPdfDocument.SetPrintTextWithGDI(FPrintTextWithGDI); - try - APage.Draw( - FPrinterDC, - RoundToInt(X), RoundToInt(Y), RoundToInt(ScaledWidth), RoundToInt(ScaledHeight), - prNormal, [proPrinting, proAnnotations] - ); - finally - if OldPrintTextWithGDI <> FPrintTextWithGDI then - TPdfDocument.SetPrintTextWithGDI(OldPrintTextWithGDI); - end; + APage.Draw( + FPrinterDC, + RoundToInt(X), RoundToInt(Y), RoundToInt(ScaledWidth), RoundToInt(ScaledHeight), + prNormal, [proPrinting, proAnnotations] + ); end; initialization diff --git a/Source/PdfiumCtrl.pas b/Source/PdfiumCtrl.pas index ca16843..58f6d92 100644 --- a/Source/PdfiumCtrl.pas +++ b/Source/PdfiumCtrl.pas @@ -153,13 +153,13 @@ 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: Int64; 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 = ''; ALoadOption: TPdfDocumentLoadOption = dloMMF); + procedure LoadFromCustom(ReadFunc: TPdfDocumentCustomReadProc; ASize: LongWord; AParam: Pointer; const APassword: UTF8String = ''); + procedure LoadFromActiveStream(Stream: TStream; const APassword: UTF8String = ''); // Stream must not be released until the document is closed + procedure LoadFromActiveBuffer(Buffer: Pointer; Size: Int64; const APassword: UTF8String = ''); // Buffer must not be released until the document is closed + procedure LoadFromBytes(const ABytes: TBytes; const APassword: UTF8String = ''); 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: UTF8String = ''); overload; // The content of the Bytes array must not be changed until the document is closed + procedure LoadFromStream(AStream: TStream; const APassword: UTF8String = ''); + procedure LoadFromFile(const AFileName: string; const APassword: UTF8String = ''; ALoadOption: TPdfDocumentLoadOption = dloMMF); procedure Close; function DeviceToPage(DeviceX, DeviceY: Integer): TPdfPoint; overload; @@ -972,7 +972,7 @@ procedure TPdfControl.DocumentLoaded; end; procedure TPdfControl.LoadFromCustom(ReadFunc: TPdfDocumentCustomReadProc; ASize: LongWord; - AParam: Pointer; const APassword: AnsiString); + AParam: Pointer; const APassword: UTF8String); begin try FDocument.LoadFromCustom(ReadFunc, ASize, AParam, APassword); @@ -981,7 +981,7 @@ procedure TPdfControl.LoadFromCustom(ReadFunc: TPdfDocumentCustomReadProc; ASize end; end; -procedure TPdfControl.LoadFromActiveStream(Stream: TStream; const APassword: AnsiString); +procedure TPdfControl.LoadFromActiveStream(Stream: TStream; const APassword: UTF8String); begin try FDocument.LoadFromActiveStream(Stream, APassword); @@ -990,7 +990,7 @@ procedure TPdfControl.LoadFromActiveStream(Stream: TStream; const APassword: Ans end; end; -procedure TPdfControl.LoadFromActiveBuffer(Buffer: Pointer; Size: Int64; const APassword: AnsiString); +procedure TPdfControl.LoadFromActiveBuffer(Buffer: Pointer; Size: Int64; const APassword: UTF8String); begin try FDocument.LoadFromActiveBuffer(Buffer, Size, APassword); @@ -1000,7 +1000,7 @@ procedure TPdfControl.LoadFromActiveBuffer(Buffer: Pointer; Size: Int64; const A end; procedure TPdfControl.LoadFromBytes(const ABytes: TBytes; AIndex, ACount: Integer; - const APassword: AnsiString); + const APassword: UTF8String); begin try FDocument.LoadFromBytes(ABytes, AIndex, ACount, APassword); @@ -1009,7 +1009,7 @@ procedure TPdfControl.LoadFromBytes(const ABytes: TBytes; AIndex, ACount: Intege end; end; -procedure TPdfControl.LoadFromBytes(const ABytes: TBytes; const APassword: AnsiString); +procedure TPdfControl.LoadFromBytes(const ABytes: TBytes; const APassword: UTF8String); begin try FDocument.LoadFromBytes(ABytes, APassword); @@ -1018,7 +1018,7 @@ procedure TPdfControl.LoadFromBytes(const ABytes: TBytes; const APassword: AnsiS end; end; -procedure TPdfControl.LoadFromStream(AStream: TStream; const APassword: AnsiString); +procedure TPdfControl.LoadFromStream(AStream: TStream; const APassword: UTF8String); begin try FDocument.LoadFromStream(AStream, APassword); @@ -1027,7 +1027,7 @@ procedure TPdfControl.LoadFromStream(AStream: TStream; const APassword: AnsiStri end; end; -procedure TPdfControl.LoadFromFile(const AFileName: string; const APassword: AnsiString; +procedure TPdfControl.LoadFromFile(const AFileName: string; const APassword: UTF8String; ALoadOption: TPdfDocumentLoadOption); begin try diff --git a/Source/PdfiumLib.pas b/Source/PdfiumLib.pas index e08ccc7..48a14f3 100644 --- a/Source/PdfiumLib.pas +++ b/Source/PdfiumLib.pas @@ -3,7 +3,7 @@ // Use DLLs (x64, x86) from https://github.com/bblanchon/pdfium-binaries // -// DLL Version: chromium/4660 +// DLL Version: chromium/4915 unit PdfiumLib; @@ -11,7 +11,6 @@ {.$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_ENABLE_XFA} {$DEFINE PDF_ENABLE_V8} @@ -81,34 +80,35 @@ __FPDF_PTRREC = record end; PFPDF_PAGE = ^FPDF_PAGE; // array // 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_RECORDER = type Pointer; // Passed into skia. - FPDF_SCHHANDLE = type __PFPDF_PTRREC; - FPDF_SIGNATURE = type __PFPDF_PTRREC; - FPDF_STRUCTELEMENT = type __PFPDF_PTRREC; - FPDF_STRUCTTREE = type __PFPDF_PTRREC; - FPDF_TEXTPAGE = type __PFPDF_PTRREC; - FPDF_WIDGET = type __PFPDF_PTRREC; - FPDF_XOBJECT = type __PFPDF_PTRREC; + 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_RECORDER = type Pointer; // Passed into skia. + FPDF_SCHHANDLE = type __PFPDF_PTRREC; + FPDF_SIGNATURE = type __PFPDF_PTRREC; + FPDF_STRUCTELEMENT = type __PFPDF_PTRREC; + FPDF_STRUCTELEMENT_ATTR = 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; @@ -309,35 +309,6 @@ 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; - -// Experimental API. -// Function: FPDF_SetTypefaceAccessibleFunc -// Set the function pointer that makes GDI fonts available in sandboxed -// environments. -// Parameters: -// func - A function pointer. See description above. -// Return value: -// None. -var - FPDF_SetTypefaceAccessibleFunc: procedure(func: TPDFiumEnsureTypefaceCharactersAccessible); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; - -// Experimental API. -// Function: FPDF_SetPrintTextWithGDI -// Set whether to use GDI to draw fonts when printing on Windows. -// 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. @@ -381,6 +352,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 @@ -2504,7 +2477,7 @@ FPDF_IMAGEOBJ_METADATA = record // 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: FPDF_WCHAR; + 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. @@ -2538,7 +2511,7 @@ FPDF_IMAGEOBJ_METADATA = record // font - the handle to the font object. // // Returns the bit flags specifying various characteristics of the font as -// defined in ISO 32000-1 Table 123, -1 on failure. +// 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}; @@ -3697,7 +3670,7 @@ IFSDK_PAUSE = record PDFDEST_VIEW_FITBV = 8; // The file identifier entry type. See section 14.4 "File Identifiers" of the -// ISO 32000-1 standard. +// ISO 32000-1:2008 spec. type FPDF_FILEIDTYPE = ( FILEIDTYPE_PERMANENT = 0, @@ -3738,6 +3711,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}; @@ -4072,8 +4048,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; @@ -6662,8 +6642,8 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; // 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 section 12.5.6.13 in -// PDF 32000-1:2008 Specification. +// 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. @@ -7814,7 +7794,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: @@ -7826,6 +7806,24 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; 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}; + // Function: FPDF_StructElement_GetID // Get the ID for a given element. // Parameters: @@ -7898,8 +7896,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 @@ -7912,6 +7910,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: @@ -7942,8 +7959,8 @@ 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: @@ -7952,6 +7969,185 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; var FPDF_StructElement_GetChildAtIndex: function(struct_element: FPDF_STRUCTELEMENT; index: Integer): FPDF_STRUCTELEMENT; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// 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}; + +// 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}; + +// Experimental API. +// Function: FPDF_StructElement_GetAttributeAtIndex +// Get an attribute object in the structure element. +// Parameters: +// struct_element - Handle to the struct element. +// index - The index for the attribute object, 0-based. +// Return value: +// The attribute object at the n-th index or NULL on error. +// Comments: +// 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. +var + 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_GetType +// Get the type of an attribute in a structure element attribute map. +// Parameters: +// struct_attribute - Handle to the struct element attribute. +// name - The attribute name. +// Return value: +// Returns the type of the value, or FPDF_OBJECT_UNKNOWN in case of +// failure. +var + FPDF_StructElement_Attr_GetType: function(struct_attribute: FPDF_STRUCTELEMENT_ATTR; name: FPDF_BYTESTRING): 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 by name as +// FPDF_BOOL. FPDF_StructElement_Attr_GetType() should have returned +// FPDF_OBJECT_BOOLEAN for this property. +// Parameters: +// struct_attribute - Handle to the struct element attribute. +// name - The attribute name. +// out_value - A pointer to variable that will receive the +// value. Not filled if false is returned. +// Return value: +// Returns TRUE if the name maps to a boolean value, FALSE otherwise. +var + FPDF_StructElement_Attr_GetBooleanValue: function(struct_attribute: FPDF_STRUCTELEMENT_ATTR; name: FPDF_BYTESTRING; + 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 by name as +// float. FPDF_StructElement_Attr_GetType() should have returned +// FPDF_OBJECT_NUMBER for this property. +// Parameters: +// struct_attribute - Handle to the struct element attribute. +// name - The attribute name. +// out_value - A pointer to variable that will receive the +// value. Not filled if false is returned. +// Return value: +// Returns TRUE if the name maps to a number value, FALSE otherwise. +var + FPDF_StructElement_Attr_GetNumberValue: function(struct_attribute: FPDF_STRUCTELEMENT_ATTR; name: FPDF_BYTESTRING; + 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 by name as +// string. FPDF_StructElement_Attr_GetType() should have returned +// FPDF_OBJECT_STRING or FPDF_OBJECT_NAME for this property. +// Parameters: +// struct_attribute - Handle to the struct element attribute. +// name - The attribute name. +// 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 name maps to a string value, FALSE otherwise. +var + FPDF_StructElement_Attr_GetStringValue: function(struct_attribute: FPDF_STRUCTELEMENT_ATTR; name: FPDF_BYTESTRING; + 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 by name as +// string. +// Parameters: +// struct_attribute - Handle to the struct element attribute. +// name - The attribute name. +// 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 name maps to a string value, FALSE otherwise. +var + FPDF_StructElement_Attr_GetBlobValue: function(struct_attribute: FPDF_STRUCTELEMENT_ATTR; name: FPDF_BYTESTRING; + buffer: Pointer; buflen: LongWord; var out_buflen: LongWord): FPDF_BOOL; {$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. +var + FPDF_StructElement_GetMarkedContentIdAtIndex: function(struct_element: FPDF_STRUCTELEMENT; index: Integer): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // *** _FPDF_LIBS_H_ *** @@ -8143,10 +8339,9 @@ TImportFuncRec = record end; const - ImportFuncs: array[0..397 + ImportFuncs: array[0..411 {$IFDEF MSWINDOWS} + 2 - {$IFDEF PDFIUM_PRINT_TEXT_WITH_GDI} + 2 {$ENDIF} {$IFDEF _SKIA_SUPPORT_ } + 2 {$ENDIF} {$IFDEF PDF_ENABLE_V8 } + 3 {$ENDIF} {$IFDEF PDF_ENABLE_XFA } + 3 {$ENDIF} @@ -8154,475 +8349,485 @@ TImportFuncRec = record ] 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_InitLibrary; N: 'FPDF_InitLibrary'), + (P: @@FPDF_InitLibraryWithConfig; N: 'FPDF_InitLibraryWithConfig'), + (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_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_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_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'), + (P: @@FPDF_RenderPageBitmap; N: 'FPDF_RenderPageBitmap'), + (P: @@FPDF_RenderPageBitmapWithMatrix; N: 'FPDF_RenderPageBitmapWithMatrix'), {$IFDEF _SKIA_SUPPORT_} - (P: @@FPDF_RenderPageSkp; N: 'FPDF_RenderPageSkp'), + (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_GetXFAPacketCount; N: 'FPDF_GetXFAPacketCount'), - (P: @@FPDF_GetXFAPacketName; N: 'FPDF_GetXFAPacketName'), - (P: @@FPDF_GetXFAPacketContent; N: 'FPDF_GetXFAPacketContent'), + (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_GetArrayBufferAllocatorSharedInstance; N: 'FPDF_GetArrayBufferAllocatorSharedInstance'; 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: @@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_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_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: @@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: @@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_LoadFont; N: 'FPDFText_LoadFont'), - (P: @@FPDFText_LoadStandardFont; N: 'FPDFText_LoadStandardFont'), - (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_GetFont; N: 'FPDFTextObj_GetFont'), - (P: @@FPDFFont_GetFontName; N: 'FPDFFont_GetFontName'), - (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: @@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: @@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_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_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: @@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: @@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_LoadFont; N: 'FPDFText_LoadFont'), + (P: @@FPDFText_LoadStandardFont; N: 'FPDFText_LoadStandardFont'), + (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_GetFont; N: 'FPDFTextObj_GetFont'), + (P: @@FPDFFont_GetFontName; N: 'FPDFFont_GetFontName'), + (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'), // *** _FPDF_PPO_H_ *** - (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'), + (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_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'), // *** _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_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'), + (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'), + (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_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'), + (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_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_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_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_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'), + (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_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 _SKIA_SUPPORT_} - (P: @@FPDF_FFLRecord; N: 'FPDF_FFLRecord'), + (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: @@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'), // *** _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'), // *** _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_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_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_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_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_IsOptionSelected; N: 'FPDFAnnot_IsOptionSelected'), - (P: @@FPDFAnnot_GetFontSize; N: 'FPDFAnnot_GetFontSize'), - (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: @@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_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_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_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_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_IsOptionSelected; N: 'FPDFAnnot_IsOptionSelected'), + (P: @@FPDFAnnot_GetFontSize; N: 'FPDFAnnot_GetFontSize'), + (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'), {$IFDEF PDF_ENABLE_V8} // *** _FPDF_LIBS_H_ *** - (P: @@FPDF_InitEmbeddedLibraries; N: 'FPDF_InitEmbeddedLibraries'; Optional: True), + (P: @@FPDF_InitEmbeddedLibraries; N: 'FPDF_InitEmbeddedLibraries'; Optional: True), {$ENDIF PDF_ENABLE_V8} // *** _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') ); const From 97f4913ef84d20c0b22a6c0fd838fdbc80621fc6 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Sun, 6 Mar 2022 00:01:08 +0100 Subject: [PATCH 21/59] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 30be7e6..e8c6676 100644 --- a/README.md +++ b/README.md @@ -4,10 +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/4660](https://github.com/bblanchon/pdfium-binaries/releases/tag/chromium%2F4660) +Binary release: [chromium/4915](https://github.com/bblanchon/pdfium-binaries/releases/tag/chromium%2F4915) ## Required pdfium.dll version -chromium/4660 +chromium/4915 ## Features - Multiple PDF load functions: From 3cb976344c10e4a36b503432f68379639158154a Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Tue, 10 May 2022 20:55:40 +0200 Subject: [PATCH 22/59] * Updated to chromium/5052 * Flatten page before printing form fields to a printer --- README.md | 4 ++-- Source/PdfiumCore.pas | 44 +++++++++++++++++++++++++++++++++++++++++++ Source/PdfiumLib.pas | 35 ++++++++++++++++++++++------------ 3 files changed, 69 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index e8c6676..790222b 100644 --- a/README.md +++ b/README.md @@ -4,10 +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/4915](https://github.com/bblanchon/pdfium-binaries/releases/tag/chromium%2F4915) +Binary release: [chromium/5052](https://github.com/bblanchon/pdfium-binaries/releases/tag/chromium%2F5052) ## Required pdfium.dll version -chromium/4915 +chromium/5052 ## Features - Multiple PDF load functions: diff --git a/Source/PdfiumCore.pas b/Source/PdfiumCore.pas index 44872ba..764a7e7 100644 --- a/Source/PdfiumCore.pas +++ b/Source/PdfiumCore.pas @@ -217,6 +217,7 @@ 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; @@ -411,6 +412,7 @@ TCustomLoadDataRec = record 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; overload; @@ -1400,6 +1402,32 @@ function TPdfDocument.ImportPages(Source: TPdfDocument; const Range: string; Ind 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 @@ -1759,6 +1787,14 @@ 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; @@ -1882,6 +1918,14 @@ procedure TPdfPage.ApplyChanges; FPDFPage_GenerateContent(FPage); 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; begin if FTextHandle = nil then diff --git a/Source/PdfiumLib.pas b/Source/PdfiumLib.pas index 48a14f3..95822d5 100644 --- a/Source/PdfiumLib.pas +++ b/Source/PdfiumLib.pas @@ -3,7 +3,7 @@ // Use DLLs (x64, x86) from https://github.com/bblanchon/pdfium-binaries // -// DLL Version: chromium/4915 +// DLL Version: chromium/5052 unit PdfiumLib; @@ -135,7 +135,7 @@ __FPDF_PTRREC = record end; // FPDFSDK always uses UTF-16LE encoded wide strings, each character uses 2 // bytes (except surrogation), with the low byte first. - FPDF_WIDESTRING = PWideChar; + 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 @@ -2790,6 +2790,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. @@ -3100,20 +3103,22 @@ FPDF_FILEWRITE = record 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}; @@ -4887,7 +4892,9 @@ IPDF_JsPlatform = record 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; @@ -5222,8 +5229,9 @@ FPDF_FORMFILLINFO = record //* Return value: //* None. //* Comments: - //* See the named actions description of <> - //* for more details. + //* 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; @@ -5994,6 +6002,9 @@ FPDF_FORMFILLINFO = record //* 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}; From 7455f8e71bebbb59bc1c981c3347afaf520b080d Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Fri, 5 May 2023 23:21:29 +0200 Subject: [PATCH 23/59] * Updated to chromium/5744 --- Source/PdfiumCore.pas | 12 ++ Source/PdfiumLib.pas | 355 +++++++++++++++++++++++++++++++++++++----- 2 files changed, 327 insertions(+), 40 deletions(-) diff --git a/Source/PdfiumCore.pas b/Source/PdfiumCore.pas index 764a7e7..9ee0af2 100644 --- a/Source/PdfiumCore.pas +++ b/Source/PdfiumCore.pas @@ -233,6 +233,7 @@ TPdfPage = class(TObject) 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; @@ -2327,6 +2328,17 @@ function TPdfPage.FormReplaceSelection(const ANewText: string): Boolean; 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 diff --git a/Source/PdfiumLib.pas b/Source/PdfiumLib.pas index 95822d5..f7a08c1 100644 --- a/Source/PdfiumLib.pas +++ b/Source/PdfiumLib.pas @@ -1,9 +1,9 @@ {$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 +{$STRINGCHECKS OFF} // It only slows down Delphi strings in Delphi 2009 and 2010 // Use DLLs (x64, x86) from https://github.com/bblanchon/pdfium-binaries // -// DLL Version: chromium/5052 +// DLL Version: chromium/5744 unit PdfiumLib; @@ -11,7 +11,7 @@ {.$DEFINE DLLEXPORT} // stdcall in WIN32 instead of CDECL in WIN32 (The library switches between those from release to release) -{.$DEFINE _SKIA_SUPPORT_} +{$DEFINE _SKIA_SUPPORT_} {$DEFINE PDF_ENABLE_XFA} {$DEFINE PDF_ENABLE_V8} @@ -35,6 +35,9 @@ interface TIME_T = Longint; PTIME_T = ^TIME_T; +// Returns True if the pdfium.dll supports Skia. +function IsSkiaAvailable: Boolean; + // *** _FPDFVIEW_H_ *** @@ -100,7 +103,7 @@ __FPDF_PTRREC = record end; FPDF_PAGEOBJECTMARK = type __PFPDF_PTRREC; FPDF_PAGERANGE = type __PFPDF_PTRREC; FPDF_PATHSEGMENT = type __PFPDF_PTRREC; - FPDF_RECORDER = type Pointer; // Passed into skia. + FPDF_RECORDER = type Pointer; // Passed into Skia as a SkPictureRecorder. FPDF_SCHHANDLE = type __PFPDF_PTRREC; FPDF_SIGNATURE = type __PFPDF_PTRREC; FPDF_STRUCTELEMENT = type __PFPDF_PTRREC; @@ -215,6 +218,20 @@ 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; @@ -236,6 +253,16 @@ FS_POINTF = record 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; + type // Process-wide options for initializing the library. PFPDF_LIBRARY_CONFIG = ^FPDF_LIBRARY_CONFIG; @@ -261,10 +288,20 @@ FPDF_LIBRARY_CONFIG = record // embedders. m_v8EmbedderSlot: Cardinal; - // Version 3 - Experimantal, + // Version 3 - Experimental. // Pointer to the V8::Platform to use. m_pPlatform: Pointer; + + // Version 4 - Experimental. + + // Explicit specification of core renderer 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 render library is not included in the build will similarly + // fail with an immediate crash. + m_RendererType: FPDF_RENDERER_TYPE; end; PFPdfLibraryConfig = ^TFPdfLibraryConfig; TFPdfLibraryConfig = FPDF_LIBRARY_CONFIG; @@ -578,7 +615,8 @@ 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}; @@ -867,6 +905,16 @@ FPDF_COLORSCHEME = record clipping: PFS_RECTF; flags: Integer); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; {$IFDEF _SKIA_SUPPORT_} +// Experimental API. +// Function: FPDF_RenderPageSkp +// Render contents of a page to a Skia SkPictureRecorder. +// Parameters: +// 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: +// The SkPictureRecorder that holds the rendering of the page, or NULL +// on failure. Caller takes ownership of the returned result. var FPDF_RenderPageSkp: function(page: FPDF_PAGE; size_x, size_y: Integer): FPDF_RECORDER; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; {$ENDIF _SKIA_SUPPORT_} @@ -1017,8 +1065,15 @@ FPDF_COLORSCHEME = 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: @@ -1027,9 +1082,11 @@ FPDF_COLORSCHEME = 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}; @@ -1088,8 +1145,7 @@ FPDF_COLORSCHEME = 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}; @@ -1957,7 +2013,7 @@ FPDF_IMAGEOBJ_METADATA = record // 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. +// 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. // @@ -1965,7 +2021,7 @@ FPDF_IMAGEOBJ_METADATA = record // page - handle to an optional page associated with |image_object|. // image_object - handle to an image object. // -// Returns the bitmap. +// 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}; @@ -2035,6 +2091,17 @@ 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}; + // Create a new path object at an initial position. // // x - initial horizontal position. @@ -2063,10 +2130,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. @@ -2480,6 +2565,23 @@ FPDF_IMAGEOBJ_METADATA = record 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. // @@ -2505,6 +2607,37 @@ FPDF_IMAGEOBJ_METADATA = record var FPDFFont_GetFontName: function(font: FPDF_FONT; buffer: PAnsiChar; length: LongWord): LongWord; {$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. // @@ -2861,6 +2994,36 @@ FPDF_FILEWRITE = record var FPDFText_GetUnicode: function(text_page: FPDF_TEXTPAGE; index: Integer): WideChar; {$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_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: @@ -3098,6 +3261,10 @@ FPDF_FILEWRITE = record // trailing terminator. // Comments: // This function ignores characters without unicode information. +// It returns 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}; @@ -3682,22 +3849,6 @@ IFSDK_PAUSE = record FILEIDTYPE_CHANGING = 1 ); -// _FS_DEF_STRUCTURE_QUADPOINTSF_ -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; - // Get the first child of |bookmark|, or the first top-level bookmark item. // // document - handle to the document. @@ -3738,6 +3889,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. @@ -3829,8 +3993,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}; @@ -5682,11 +5856,13 @@ FPDF_FORMFILLINFO = record //* Initialize form fill environment. //* Parameters: //* document - Handle to document from FPDF_LoadDocument(). -//* pFormFillInfo - Pointer to a FPDF_FORMFILLINFO structure. +//* 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}; @@ -6066,13 +6242,33 @@ FPDF_FORMFILLINFO = record var FORM_GetSelectedText: function(hHandle: FPDF_FORMHANDLE; page: FPDF_PAGE; buffer: Pointer; buflen: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +//* 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. +//* 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(). @@ -6525,6 +6721,16 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; 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 = ( FPDFANNOT_COLORTYPE_Color = 0, @@ -6917,6 +7123,28 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; 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. // @@ -7097,6 +7325,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. // @@ -8350,7 +8596,7 @@ TImportFuncRec = record end; const - ImportFuncs: array[0..411 + ImportFuncs: array[0..422 {$IFDEF MSWINDOWS} + 2 {$IFDEF _SKIA_SUPPORT_ } + 2 {$ENDIF} @@ -8392,7 +8638,7 @@ TImportFuncRec = record (P: @@FPDF_RenderPageBitmap; N: 'FPDF_RenderPageBitmap'), (P: @@FPDF_RenderPageBitmapWithMatrix; N: 'FPDF_RenderPageBitmapWithMatrix'), {$IFDEF _SKIA_SUPPORT_} - (P: @@FPDF_RenderPageSkp; N: 'FPDF_RenderPageSkp'), + (P: @@FPDF_RenderPageSkp; N: 'FPDF_RenderPageSkp'; Quirk: True; Optional: True), {$ENDIF _SKIA_SUPPORT_} (P: @@FPDF_ClosePage; N: 'FPDF_ClosePage'), (P: @@FPDF_CloseDocument; N: 'FPDF_CloseDocument'), @@ -8476,9 +8722,11 @@ TImportFuncRec = record (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: @@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'), @@ -8517,8 +8765,11 @@ TImportFuncRec = record (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_GetFontName; N: 'FPDFFont_GetFontName'), + (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'), @@ -8549,6 +8800,8 @@ TImportFuncRec = record (P: @@FPDFText_ClosePage; N: 'FPDFText_ClosePage'), (P: @@FPDFText_CountChars; N: 'FPDFText_CountChars'), (P: @@FPDFText_GetUnicode; N: 'FPDFText_GetUnicode'), + (P: @@FPDFText_IsGenerated; N: 'FPDFText_IsGenerated'), + (P: @@FPDFText_HasUnicodeMapError; N: 'FPDFText_HasUnicodeMapError'), (P: @@FPDFText_GetFontSize; N: 'FPDFText_GetFontSize'), (P: @@FPDFText_GetFontInfo; N: 'FPDFText_GetFontInfo'), (P: @@FPDFText_GetFontWeight; N: 'FPDFText_GetFontWeight'), @@ -8606,6 +8859,7 @@ TImportFuncRec = record (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'), @@ -8673,6 +8927,7 @@ TImportFuncRec = record (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'), @@ -8689,7 +8944,7 @@ TImportFuncRec = record (P: @@FPDF_RemoveFormFieldHighlight; N: 'FPDF_RemoveFormFieldHighlight'), (P: @@FPDF_FFLDraw; N: 'FPDF_FFLDraw'), {$IFDEF _SKIA_SUPPORT_} - (P: @@FPDF_FFLRecord; N: 'FPDF_FFLRecord'), + (P: @@FPDF_FFLRecord; N: 'FPDF_FFLRecord'; Quirk: True; Optional: True), {$ENDIF _SKIA_SUPPORT_} (P: @@FPDF_GetFormType; N: 'FPDF_GetFormType'), @@ -8794,6 +9049,7 @@ TImportFuncRec = record (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'), @@ -8807,6 +9063,7 @@ TImportFuncRec = record (P: @@FPDFAnnot_GetFormFieldFlags; N: 'FPDFAnnot_GetFormFieldFlags'), (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_GetOptionCount; N: 'FPDFAnnot_GetOptionCount'), (P: @@FPDFAnnot_GetOptionLabel; N: 'FPDFAnnot_GetOptionLabel'), @@ -8866,6 +9123,16 @@ function PDF_USE_XFA: Boolean; {$ENDIF PDF_ENABLE_XFA} end; +function IsSkiaAvailable: Boolean; +begin + {$IFDEF _SKIA_SUPPORT_} + Result := Assigned(FPDF_RenderPageSkp) and (@FPDF_RenderPageSkp <> @NotLoaded) and (@FPDF_RenderPageSkp <> @FunctionNotSupported) + and Assigned(FPDF_FFLRecord) and (@FPDF_FFLRecord <> @NotLoaded) and (@FPDF_FFLRecord <> @FunctionNotSupported); + {$ELSE} + Result := False; + {$ENDIF _SKIA_SUPPORT_} +end; + procedure Init; var I: Integer; @@ -8886,6 +9153,7 @@ procedure InitPDFiumEx(const DllFileName: string{$IFDEF PDF_ENABLE_V8}; const Re var I: Integer; Path: string; + LibraryConfig: FPDF_LIBRARY_CONFIG; begin if PdfiumModule <> 0 then Exit; @@ -8913,6 +9181,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 @@ -8967,7 +9236,13 @@ procedure InitPDFiumEx(const DllFileName: string{$IFDEF PDF_ENABLE_V8}; const Re @FPDF_InitEmbeddedLibraries := @FunctionNotSupported; {$ENDIF PDF_ENABLE_V8} - FPDF_InitLibrary; + // Initialize the pdfium library + FillChar(LibraryConfig, SizeOf(LibraryConfig), 0); + LibraryConfig.version := 4; + LibraryConfig.m_RendererType := FPDF_RENDERERTYPE_AGG; + {if IsSkiaAvailable and SkiaRendererEnabled then + LibraryConfig.m_RendererType := FPDF_RENDERERTYPE_SKIA;} + FPDF_InitLibraryWithConfig(@LibraryConfig); end; initialization From 6e9fb9a08fbdf0e53487bf2753fd1abdfd5b7a82 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Fri, 5 May 2023 23:22:00 +0200 Subject: [PATCH 24/59] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 790222b..aa9fa19 100644 --- a/README.md +++ b/README.md @@ -4,10 +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/5052](https://github.com/bblanchon/pdfium-binaries/releases/tag/chromium%2F5052) +Binary release: [chromium/5744](https://github.com/bblanchon/pdfium-binaries/releases/tag/chromium%2F5052) ## Required pdfium.dll version -chromium/5052 +chromium/5744 ## Features - Multiple PDF load functions: From 1de38e3ff26e2badbef2ad34a91ffe2fe35512f6 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Fri, 5 May 2023 23:24:39 +0200 Subject: [PATCH 25/59] Fixed pdfium download link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index aa9fa19..255744d 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ 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/5744](https://github.com/bblanchon/pdfium-binaries/releases/tag/chromium%2F5052) +Binary release: [chromium/5744](https://github.com/bblanchon/pdfium-binaries/releases/tag/chromium%2F5744) ## Required pdfium.dll version chromium/5744 From bb57335861f1a8f9e06265e57bd428d4ad7a0806 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Sun, 7 May 2023 23:48:59 +0200 Subject: [PATCH 26/59] Fix missing function import --- Source/PdfiumLib.pas | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/PdfiumLib.pas b/Source/PdfiumLib.pas index f7a08c1..acbd22b 100644 --- a/Source/PdfiumLib.pas +++ b/Source/PdfiumLib.pas @@ -8596,7 +8596,7 @@ TImportFuncRec = record end; const - ImportFuncs: array[0..422 + ImportFuncs: array[0..423 {$IFDEF MSWINDOWS} + 2 {$IFDEF _SKIA_SUPPORT_ } + 2 {$ENDIF} @@ -9065,6 +9065,7 @@ TImportFuncRec = record (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'), From dfda36edefe0415d8ab358a74cbd4ad1f6479331 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Sun, 7 May 2023 23:49:28 +0200 Subject: [PATCH 27/59] FormField Annotations --- Source/PdfiumCore.pas | 598 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 573 insertions(+), 25 deletions(-) diff --git a/Source/PdfiumCore.pas b/Source/PdfiumCore.pas index 9ee0af2..f1047aa 100644 --- a/Source/PdfiumCore.pas +++ b/Source/PdfiumCore.pas @@ -23,6 +23,9 @@ EPdfArgumentOutOfRange = class(EPdfException); TPdfDocument = class; TPdfPage = class; TPdfAttachmentList = class; + TPdfAnnotationList = class; + TPdfFormField = class; + TPdfAnnotation = class; TPdfPoint = record X, Y: Double; @@ -118,16 +121,39 @@ 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, @@ -175,6 +201,116 @@ 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); + 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; + 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; + + TPdfAnnotation = class(TObject) + private + FPage: TPdfPage; + FHandle: FPDF_ANNOTATION; + FFormField: TPdfFormField; + function GetFormField: TPdfFormField; + protected + constructor Create(APage: TPdfPage; AHandle: FPDF_ANNOTATION); + public + destructor Destroy; override; + function IsFormField: Boolean; + + property FormField: TPdfFormField read GetFormField; + + 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; + protected + procedure DestroyingItem(Item: TPdfAnnotation); + procedure DestroyingFormField(FormField: TPdfFormField); + public + constructor Create(APage: TPdfPage); + destructor Destroy; override; + procedure CloseAnnotations; + + property Count: Integer read GetCount; + property Items[Index: Integer]: TPdfAnnotation read GetItem; default; + + { A list of all form fields annotations } + property FormFields: TPdfFormFieldList read GetFormFields; + end; + TPdfPage = class(TObject) private FDocument: TPdfDocument; @@ -183,6 +319,7 @@ TPdfPage = class(TObject) FHeight: Single; FTransparency: Boolean; FRotation: TPdfPageRotation; + FAnnotations: TPdfAnnotationList; FTextHandle: FPDF_TEXTPAGE; FSearchHandle: FPDF_SCHHANDLE; FLinkHandle: FPDF_PAGELINK; @@ -199,6 +336,7 @@ TPdfPage = class(TObject) function GetKeyModifier(KeyData: LPARAM): Integer; function GetHandle: FPDF_PAGE; function GetTextHandle: FPDF_TEXTPAGE; + function GetFormFields: TPdfFormFieldList; public destructor Destroy; override; procedure Close; @@ -271,6 +409,9 @@ TPdfPage = class(TObject) 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; @@ -527,6 +668,8 @@ implementation 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'; + RsPdfErrorSuccess = 'No error'; RsPdfErrorUnknown = 'Unknown error'; RsPdfErrorFile = 'File not found or can''t be opened'; @@ -1681,6 +1824,7 @@ constructor TPdfPage.Create(ADocument: TPdfDocument; APage: FPDF_PAGE); inherited Create; FDocument := ADocument; FPage := APage; + FAnnotations := TPdfAnnotationList.Create(Self); AfterOpen; end; @@ -1689,6 +1833,7 @@ destructor TPdfPage.Destroy; begin Close; FDocument.ExtractPage(Self); + FreeAndNil(FAnnotations); inherited Destroy; end; @@ -1718,6 +1863,8 @@ procedure TPdfPage.AfterOpen; procedure TPdfPage.Close; begin + FAnnotations.CloseAnnotations; + if IsValidForm then begin FORM_DoPageAAction(FPage, FDocument.FForm, FPDFPAGE_AACTION_CLOSE); @@ -2381,24 +2528,9 @@ function TPdfPage.FormRedo: Boolean; function TPdfPage.HasFormFieldAtPoint(X, Y: Double): TPdfFormFieldType; 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; - else + 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; @@ -2420,6 +2552,11 @@ function TPdfPage.GetTextHandle: FPDF_TEXTPAGE; Result := nil; end; +function TPdfPage.GetFormFields: TPdfFormFieldList; +begin + Result := Annotations.FormFields; +end; + { _TPdfBitmapHideCtor } procedure _TPdfBitmapHideCtor.Create; @@ -2850,6 +2987,417 @@ function TPdfAttachment.GetContentAsString(Encoding: TEncoding): string; 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; + +{ 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); +begin + inherited Create; + FPage := APage; + FHandle := AHandle; +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.IsFormField: Boolean; +begin + case FPDFAnnot_GetSubtype(Handle) of + FPDF_ANNOT_WIDGET, + FPDF_ANNOT_XFAWIDGET: + Result := True; + else + Result := False; + end; +end; + +function TPdfAnnotation.GetFormField: TPdfFormField; +begin + if FFormField = nil then + begin + if not IsFormField then + raise EPdfException.CreateRes(@RsPdfAnnotationNotAFormFieldError); + FFormField := TPdfFormField.Create(Self); + end; + Result := FFormField; +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; + { TPdfDocumentPrinter } constructor TPdfDocumentPrinter.Create; From 54ae707a69a0d825be652a141deaaa0cb26b1189 Mon Sep 17 00:00:00 2001 From: Sven Harazim Date: Tue, 9 May 2023 08:27:38 +0200 Subject: [PATCH 28/59] Change page on mousescrolling --- Example/MainFrm.dfm | 15 +++++++++++---- Example/MainFrm.pas | 7 +++++++ Source/PdfiumCtrl.pas | 19 ++++++++++++++++--- 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/Example/MainFrm.dfm b/Example/MainFrm.dfm index d512c3a..781e600 100644 --- a/Example/MainFrm.dfm +++ b/Example/MainFrm.dfm @@ -3,16 +3,14 @@ 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 OnCreate = FormCreate - PixelsPerInch = 96 TextHeight = 13 object btnPrev: TButton Left = 0 @@ -91,7 +89,7 @@ object frmMain: TfrmMain object ListViewAttachments: TListView Left = 0 Top = 600 - Width = 655 + Width = 780 Height = 47 Align = alBottom Columns = <> @@ -100,6 +98,15 @@ object frmMain: TfrmMain Visible = False OnDblClick = ListViewAttachmentsDblClick end + object chkChangePageOnMouseScrolling: TCheckBox + Left = 599 + Top = 4 + Width = 162 + Height = 17 + Caption = 'ChangePageOnMouseScrolling' + TabOrder = 9 + OnClick = chkChangePageOnMouseScrollingClick + end object PrintDialog1: TPrintDialog MinPage = 1 MaxPage = 10 diff --git a/Example/MainFrm.pas b/Example/MainFrm.pas index 1148863..16ca77c 100644 --- a/Example/MainFrm.pas +++ b/Example/MainFrm.pas @@ -21,6 +21,7 @@ TfrmMain = class(TForm) OpenDialog1: TOpenDialog; ListViewAttachments: TListView; SaveDialog1: TSaveDialog; + chkChangePageOnMouseScrolling: TCheckBox; procedure FormCreate(Sender: TObject); procedure btnPrevClick(Sender: TObject); procedure btnNextClick(Sender: TObject); @@ -31,6 +32,7 @@ TfrmMain = class(TForm) procedure edtZoomChange(Sender: TObject); procedure btnPrintClick(Sender: TObject); procedure ListViewAttachmentsDblClick(Sender: TObject); + procedure chkChangePageOnMouseScrollingClick(Sender: TObject); private { Private-Deklarationen } FCtrl: TPdfControl; @@ -138,6 +140,11 @@ procedure TfrmMain.WebLinkClick(Sender: TObject; Url: string); ShowMessage(Url); end; +procedure TfrmMain.chkChangePageOnMouseScrollingClick(Sender: TObject); +begin + FCtrl.ChangePageOnMouseScrolling := chkChangePageOnMouseScrolling.Checked; +end; + procedure TfrmMain.chkLCDOptimizeClick(Sender: TObject); begin if chkLCDOptimize.Checked then diff --git a/Source/PdfiumCtrl.pas b/Source/PdfiumCtrl.pas index 58f6d92..4ea0a47 100644 --- a/Source/PdfiumCtrl.pas +++ b/Source/PdfiumCtrl.pas @@ -72,6 +72,7 @@ TPdfControl = class(TCustomControl) FPageShadowColor: TColor; FPageShadowPadding: Integer; FPageBorderColor: TColor; + FChangePageOnMouseScrolling: Boolean; procedure WMTimer(var Message: TWMTimer); message WM_TIMER; procedure WMVScroll(var Message: TWMVScroll); message WM_VSCROLL; @@ -214,6 +215,7 @@ 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 PageBorderColor: TColor read FPageBorderColor write SetPageBorderColor default clNone; property PageShadowColor: TColor read FPageShadowColor write SetPageShadowColor default clNone; @@ -2274,10 +2276,21 @@ 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 + Self.GotoNextPage() + else + if Self.PageIndex>0 then + begin + Self.GotoPrevPage(); + Self.ScrollContentTo(0,999999999); + end; + end else + Result := true; end; end; end; From 31e87d5a6c1009e0e442d3197633e34389c3b3c3 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Wed, 10 May 2023 11:46:38 +0200 Subject: [PATCH 29/59] - Adjusted code style - Removed magic number --- Source/PdfiumCtrl.pas | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/Source/PdfiumCtrl.pas b/Source/PdfiumCtrl.pas index 4ea0a47..fb342f4 100644 --- a/Source/PdfiumCtrl.pas +++ b/Source/PdfiumCtrl.pas @@ -49,6 +49,7 @@ TPdfControl = class(TCustomControl) FSmoothScroll: Boolean; FScrollTimerActive: Boolean; FScrollTimer: Boolean; + FChangePageOnMouseScrolling: Boolean; FSelStartCharIndex: Integer; FSelStopCharIndex: Integer; FMouseDownPt: TPoint; @@ -72,7 +73,6 @@ TPdfControl = class(TCustomControl) FPageShadowColor: TColor; FPageShadowPadding: Integer; FPageBorderColor: TColor; - FChangePageOnMouseScrolling: Boolean; procedure WMTimer(var Message: TWMTimer); message WM_TIMER; procedure WMVScroll(var Message: TWMVScroll); message WM_VSCROLL; @@ -2279,18 +2279,19 @@ function TPdfControl.DoMouseWheel(Shift: TShiftState; WheelDelta: Integer; Result := ScrollContent(-WheelDelta, 0, SmoothScroll) else Result := ScrollContent(0, -WheelDelta, SmoothScroll); - if (not Result) and (FChangePageOnMouseScrolling) then + + if not Result and FChangePageOnMouseScrolling then begin if WheelDelta < 0 then - Self.GotoNextPage() - else - if Self.PageIndex>0 then + GotoNextPage() + else if PageIndex > 0 then begin - Self.GotoPrevPage(); - Self.ScrollContentTo(0,999999999); + GotoPrevPage(); + ScrollContentTo(0, MaxInt); end; - end else - Result := true; + end + else + Result := True; end; end; end; From 5b68775bd222ace86ea88e9310666ebbfc2f212e Mon Sep 17 00:00:00 2001 From: Benito Kropp <10219110+DoctorChicky@users.noreply.github.com> Date: Thu, 6 Jul 2023 09:31:00 +0200 Subject: [PATCH 30/59] Add missing pointer for FPDFAction_GetType to ImportFuncs --- Source/PdfiumLib.pas | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/PdfiumLib.pas b/Source/PdfiumLib.pas index acbd22b..fbf855b 100644 --- a/Source/PdfiumLib.pas +++ b/Source/PdfiumLib.pas @@ -8596,7 +8596,7 @@ TImportFuncRec = record end; const - ImportFuncs: array[0..423 + ImportFuncs: array[0..424 {$IFDEF MSWINDOWS} + 2 {$IFDEF _SKIA_SUPPORT_ } + 2 {$ENDIF} @@ -8864,6 +8864,7 @@ TImportFuncRec = record (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'), From b2399548c0f6624b970684a56b007c18b974694c Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Tue, 3 Oct 2023 11:12:24 +0200 Subject: [PATCH 31/59] Fix #28 If Annotations/FormFields were accessed/used on a page, the page will not be unloaded when switching to a different page. --- Source/PdfiumCtrl.pas | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Source/PdfiumCtrl.pas b/Source/PdfiumCtrl.pas index fb342f4..7b72342 100644 --- a/Source/PdfiumCtrl.pas +++ b/Source/PdfiumCtrl.pas @@ -893,8 +893,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); From 0cc1544e67a0a913757828afc7169a1826f44ea6 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Tue, 3 Oct 2023 11:33:36 +0200 Subject: [PATCH 32/59] Fix #28 If Annotations/FormFields were accessed/used on a page, the page will not be unloaded when switching to a different page. --- Source/PdfiumCore.pas | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Source/PdfiumCore.pas b/Source/PdfiumCore.pas index f1047aa..a24420d 100644 --- a/Source/PdfiumCore.pas +++ b/Source/PdfiumCore.pas @@ -296,6 +296,7 @@ TPdfAnnotationList = class(TObject) function GetCount: Integer; function GetItem(Index: Integer): TPdfAnnotation; function GetFormFields: TPdfFormFieldList; + function GetAnnotationsLoaded: Boolean; protected procedure DestroyingItem(Item: TPdfAnnotation); procedure DestroyingFormField(FormField: TPdfFormField); @@ -303,6 +304,7 @@ TPdfAnnotationList = class(TObject) constructor Create(APage: TPdfPage); destructor Destroy; override; procedure CloseAnnotations; + property AnnotationsLoaded: Boolean read GetAnnotationsLoaded; property Count: Integer read GetCount; property Items[Index: Integer]: TPdfAnnotation read GetItem; default; @@ -3059,6 +3061,11 @@ function TPdfAnnotationList.GetFormFields: TPdfFormFieldList; Result := FFormFields; end; +function TPdfAnnotationList.GetAnnotationsLoaded: Boolean; +begin + Result := FItems.Count > 0; +end; + { TPdfFormFieldList } constructor TPdfFormFieldList.Create(AAnnotations: TPdfAnnotationList); From e94f594aa9737c2c3172d568c0d45a6244bdfd7e Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Tue, 3 Oct 2023 11:49:47 +0200 Subject: [PATCH 33/59] Fix issue #35 Always paint the background (ignore the PDF's transparency flag) --- Source/PdfiumCore.pas | 10 ++++------ Source/PdfiumCtrl.pas | 17 ++++++++++++----- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/Source/PdfiumCore.pas b/Source/PdfiumCore.pas index a24420d..83a4c42 100644 --- a/Source/PdfiumCore.pas +++ b/Source/PdfiumCore.pas @@ -345,7 +345,7 @@ TPdfPage = class(TObject) function IsLoaded: Boolean; procedure Draw(DC: HDC; X, Y, Width, Height: Integer; Rotate: TPdfPageRotation = prNormal; - const Options: TPdfPageRenderOptions = []); + const Options: TPdfPageRenderOptions = []; PageBackground: TColorRef = $FFFFFF); procedure DrawToPdfBitmap(APdfBitmap: TPdfBitmap; X, Y, Width, Height: Integer; Rotate: TPdfPageRotation = prNormal; const Options: TPdfPageRenderOptions = []); procedure DrawFormToPdfBitmap(APdfBitmap: TPdfBitmap; X, Y, Width, Height: Integer; Rotate: TPdfPageRotation = prNormal; @@ -1925,7 +1925,8 @@ 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); +procedure TPdfPage.Draw(DC: HDC; X, Y, Width, Height: Integer; Rotate: TPdfPageRotation; + const Options: TPdfPageRenderOptions; PageBackground: TColorRef); var BitmapInfo: TBitmapInfo; Bmp, OldBmp: HBITMAP; @@ -1964,10 +1965,7 @@ procedure TPdfPage.Draw(DC: HDC; X, Y, Width, Height: Integer; Rotate: TPdfPageR try 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); + PdfBmp.FillRect(0, 0, Width, Height, $FF000000 or PageBackground); DrawToPdfBitmap(PdfBmp, 0, 0, Width, Height, Rotate, Options); DrawFormToPdfBitmap(PdfBmp, 0, 0, Width, Height, Rotate, Options); finally diff --git a/Source/PdfiumCtrl.pas b/Source/PdfiumCtrl.pas index 7b72342..9c11a65 100644 --- a/Source/PdfiumCtrl.pas +++ b/Source/PdfiumCtrl.pas @@ -630,15 +630,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 From 20eae518865b4e7b51c3b1827c5acc148971d8b0 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Tue, 3 Oct 2023 12:27:21 +0200 Subject: [PATCH 34/59] Use default (white) background in the example --- Example/MainFrm.pas | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Example/MainFrm.pas b/Example/MainFrm.pas index 16ca77c..688bf14 100644 --- a/Example/MainFrm.pas +++ b/Example/MainFrm.pas @@ -69,7 +69,7 @@ procedure TfrmMain.FormCreate(Sender: TObject); //FCtrl.PageBorderColor := clBlack; //FCtrl.PageShadowColor := clDkGray; FCtrl.ScaleMode := smFitWidth; - FCtrl.PageColor := RGB(255, 255, 200); + //FCtrl.PageColor := RGB(255, 255, 200); FCtrl.OnWebLinkClick := WebLinkClick; edtZoom.Value := FCtrl.ZoomPercentage; From 93c59bc436f088c12f9dfdc33f83c7dda55b964a Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Tue, 3 Oct 2023 12:38:43 +0200 Subject: [PATCH 35/59] Initial FreePascal/LCL support (Windows only) --- Source/PdfiumCore.pas | 217 ++++++++++++++++++++++++++++++++++++------ Source/PdfiumCtrl.pas | 60 ++++++++---- Source/PdfiumLib.pas | 64 ++++++++++--- 3 files changed, 279 insertions(+), 62 deletions(-) diff --git a/Source/PdfiumCore.pas b/Source/PdfiumCore.pas index 83a4c42..8ca9edf 100644 --- a/Source/PdfiumCore.pas +++ b/Source/PdfiumCore.pas @@ -1,12 +1,29 @@ -{$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, WinSpool, Types, SysUtils, Classes, Contnrs, PdfiumLib, Graphics; + {$IFDEF MSWINDOWS} + Windows, //WinSpool, + {$ELSE} + {$IFDEF FPC} + LCLType, + {$ENDIF FPC} + ExtCtrls, + {$ENDIF MSWINDOWS} + Types, SysUtils, Classes, Contnrs, + PdfiumLib; const // DIN A4 @@ -492,8 +509,10 @@ TCustomLoadDataRec = record FPages: TObjectList; FAttachments: TPdfAttachmentList; FFileName: string; + {$IFDEF MSWINDOWS} FFileHandle: THandle; FFileMapping: THandle; + {$ENDIF MSWINDOWS} FBuffer: PByte; FBytes: TBytes; FClosing: Boolean; @@ -502,7 +521,7 @@ TCustomLoadDataRec = record FForm: FPDF_FORMHANDLE; FFormFillHandler: TPdfFormFillHandler; - FFormFieldHighlightColor: TColor; + FFormFieldHighlightColor: TColorRef; FFormFieldHighlightAlpha: Integer; FPrintHidesFormFieldHighlight: Boolean; FFormModified: Boolean; @@ -531,7 +550,7 @@ 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 @@ -590,7 +609,7 @@ 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; @@ -663,7 +682,9 @@ implementation RsUnsupportedFeature = 'Function %s not supported'; RsArgumentsOutOfRange = 'Function argument "%s" (%d) out of range'; RsDocumentNotActive = 'PDF document is not open'; + {$IFNDEF CPUX64} RsFileTooLarge = 'PDF file "%s" is too large'; + {$ENDIF ~CPUX64} RsPdfCannotDeleteAttachmnent = 'Cannot delete the PDF attachment %d'; RsPdfCannotAddAttachmnent = 'Cannot add the PDF attachment "%s"'; @@ -672,13 +693,15 @@ implementation RsPdfAnnotationNotAFormFieldError = 'The annotation is not a form field'; - 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'; + 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; @@ -690,7 +713,7 @@ implementation TEncodingAccess = class(TEncoding) public function GetMemCharCount(Bytes: PByte; ByteCount: Integer): Integer; - function GetMemChars(Bytes: PByte; ByteCount: Integer; Chars: PChar; CharCount: Integer): Integer; + function GetMemChars(Bytes: PByte; ByteCount: Integer; Chars: PWideChar; CharCount: Integer): Integer; end; function TEncodingAccess.GetMemCharCount(Bytes: PByte; ByteCount: Integer): Integer; @@ -698,7 +721,7 @@ function TEncodingAccess.GetMemCharCount(Bytes: PByte; ByteCount: Integer): Inte Result := GetCharCount(Bytes, ByteCount); end; -function TEncodingAccess.GetMemChars(Bytes: PByte; ByteCount: Integer; Chars: PChar; CharCount: Integer): Integer; +function TEncodingAccess.GetMemChars(Bytes: PByte; ByteCount: Integer; Chars: PWideChar; CharCount: Integer): Integer; begin Result := GetChars(Bytes, ByteCount, Chars, CharCount); end; @@ -709,8 +732,8 @@ function SetThreadPdfUnsupportedFeatureHandler(const Handler: TPdfUnsupportedFea 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} @@ -815,7 +838,7 @@ procedure InitLib; procedure RaiseLastPdfError; begin - case FPDF_GetLastError of + case FPDF_GetLastError() of FPDF_ERR_SUCCESS: raise EPdfException.CreateRes(@RsPdfErrorSuccess); FPDF_ERR_FILE: @@ -828,6 +851,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; @@ -883,6 +912,7 @@ procedure FFI_OutputSelectedRect(pThis: PFPDF_FORMFILLINFO; page: FPDF_PAGE; lef end; end; +{$IFDEF MSWINDOWS} var FFITimers: array of record Id: UINT; @@ -966,14 +996,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 MSWINDOWS} +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 + 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; + EnterCriticalSection(FFITimersCritSect); + try + 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; @@ -1033,7 +1149,6 @@ procedure FFI_FocusChange(param: PFPDF_FORMFILLINFO; annot: FPDF_ANNOTATION; pag end; - { TPdfRect } procedure TPdfRect.Offset(XOffset, YOffset: Double); @@ -1079,7 +1194,9 @@ constructor TPdfDocument.Create; inherited Create; FPages := TObjectList.Create; FAttachments := TPdfAttachmentList.Create(Self); + {$IFDEF MSWINDOWS} FFileHandle := INVALID_HANDLE_VALUE; + {$ENDIF MSWINDOWS} FFormFieldHighlightColor := $FFE4DD; FFormFieldHighlightAlpha := 100; FPrintHidesFormFieldHighlight := True; @@ -1121,6 +1238,7 @@ procedure TPdfDocument.Close; FCustomLoadData := nil; end; + {$IFDEF MSWINDOWS} if FFileMapping <> 0 then begin if FBuffer <> nil then @@ -1131,18 +1249,22 @@ 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; + {$ENDIF MSWINDOWS} FFileName := ''; FFormModified := False; @@ -1151,6 +1273,7 @@ procedure TPdfDocument.Close; end; end; +{$IFDEF MSWINDOWS} function ReadFromActiveFile(Param: Pointer; Position: LongWord; Buffer: PByte; Size: LongWord): Boolean; var NumRead: DWORD; @@ -1163,18 +1286,24 @@ function ReadFromActiveFile(Param: Pointer; Position: LongWord; Buffer: PByte; S else Result := Size = 0; end; +{$ENDIF MSWINDOWS} procedure TPdfDocument.LoadFromFile(const AFileName: string; const APassword: UTF8String; ALoadOption: TPdfDocumentLoadOption); var + {$IFDEF MSWINDOWS} Size: Int64; Offset: NativeInt; NumRead: DWORD; LastError: DWORD; + {$ELSE} + Stream: TFileStream; + {$ENDIF MSWINDOWS} begin Close; // We don't use FPDF_LoadDocument because it is limited to ANSI file names and dloOnDemand emulates it - FFileHandle := CreateFile(PChar(AFileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + {$IFDEF MSWINDOWS} + FFileHandle := CreateFileW(PWideChar(AFileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if FFileHandle = INVALID_HANDLE_VALUE then RaiseLastOSError; try @@ -1243,6 +1372,14 @@ procedure TPdfDocument.LoadFromFile(const AFileName: string; const APassword: UT Close; raise; end; + {$ELSE} + Stream := TFileStream.Create(AFileName, fmOpenRead or fmShareDenyWrite); + try + LoadFromStream(Stream, APassword); + finally + Stream.Free; + end; + {$ENDIF MSWINDOWS} FFileName := AFileName; end; @@ -1411,7 +1548,7 @@ procedure TPdfDocument.DocumentLoaded; procedure TPdfDocument.UpdateFormFieldHighlight; begin - FPDF_SetFormFieldHighlightColor(FForm, 0, {ColorToRGB}(FFormFieldHighlightColor)); + FPDF_SetFormFieldHighlightColor(FForm, 0, FFormFieldHighlightColor); FPDF_SetFormFieldHighlightAlpha(FForm, FFormFieldHighlightAlpha); end; @@ -1723,7 +1860,7 @@ function TPdfDocument.GetMetaText(const TagName: string): string; 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 := ''; @@ -1777,7 +1914,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); @@ -1795,13 +1936,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; @@ -1936,6 +2077,7 @@ procedure TPdfPage.Draw(DC: HDC; X, Y, Width, Height: Integer; Rotate: TPdfPageR begin Open; + {$IFDEF MSWINDOWS} if proPrinting in Options then begin if IsValidForm and (FPDFPage_GetAnnotCount(FPage) > 0) then @@ -1949,6 +2091,7 @@ procedure TPdfPage.Draw(DC: HDC; X, Y, Width, Height: Integer; Rotate: TPdfPageR FPDF_RenderPage(DC, FPage, X, Y, Width, Height, Ord(Rotate), GetDrawFlags(Options)); Exit; end; + {$ENDIF MSWINDOWS} FillChar(BitmapInfo, SizeOf(BitmapInfo), 0); @@ -2110,7 +2253,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; @@ -2205,7 +2348,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 @@ -2224,7 +2367,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 := ''; @@ -2274,7 +2417,7 @@ function TPdfPage.GetWebLinkURL(LinkIndex: Integer): string; if Len > 0 then begin SetLength(Result, Len); - FPDFLink_GetURL(FLinkHandle, LinkIndex, PChar(Result), Len + 1); // including #0 terminator + FPDFLink_GetURL(FLinkHandle, LinkIndex, PWideChar(Result), Len + 1); // including #0 terminator end; end; end; @@ -2317,10 +2460,12 @@ function TPdfPage.GetKeyModifier(KeyData: LPARAM): Integer; AltMask = $20000000; begin Result := 0; + {$IFDEF MSWINDOWS} if GetKeyState(VK_SHIFT) < 0 then Result := Result or FWL_EVENTFLAG_ShiftKey; if GetKeyState(VK_CONTROL) < 0 then Result := Result or FWL_EVENTFLAG_ControlKey; + {$ENDIF MSWINDOWS} if KeyData and AltMask <> 0 then Result := Result or FWL_EVENTFLAG_AltKey; end; @@ -3599,11 +3744,21 @@ procedure TPdfDocumentPrinter.InternPrintPage(APage: TPdfPage; X, Y, Width, Heig end; 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 9c11a65..aa7ea06 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,9 +10,23 @@ // 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 + {$IFDEF FPC} + LCLType, PrintersDlgs, Win32Extra, + {$ENDIF FPC} Windows, Messages, Types, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, PdfiumCore; const @@ -37,9 +55,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; @@ -80,9 +98,9 @@ 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; @@ -253,7 +271,9 @@ TPdfControl = class(TCustomControl) property OnKeyDown; property OnKeyPress; property OnKeyUp; + {$IFNDEF FPC} property OnMouseActivate; + {$ENDIF ~FPC} property OnMouseDown; property OnMouseEnter; property OnMouseLeave; @@ -262,10 +282,10 @@ 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) @@ -301,11 +321,15 @@ implementation 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; @@ -367,7 +391,7 @@ procedure TPdfDocumentVclPrinter.PrinterEndPage; function TPdfDocumentVclPrinter.GetPrinterDC: HDC; begin - Result := Printer.Handle; + Result := Printer.Canvas.Handle; end; class function TPdfDocumentVclPrinter.PrintDocument(ADocument: TPdfDocument; @@ -397,10 +421,14 @@ class function TPdfDocumentVclPrinter.PrintDocument(ADocument: TPdfDocument; 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; @@ -485,7 +513,7 @@ procedure TPdfControl.DestroyWnd; inherited DestroyWnd; end; -{$IF CompilerVersion <= 20.0} // 2009 +{$IFDEF USE_PRINTCLIENT_WORKAROUND} procedure TPdfControl.WMPrintClient(var Message: TWMPrintClient); // Emulate Delphi 2010's TControlState.csPrintClient var @@ -499,7 +527,7 @@ procedure TPdfControl.WMPrintClient(var Message: TWMPrintClient); FPrintClient := LastPrintClient; end; end; -{$IFEND} +{$ENDIF USE_PRINTCLIENT_WORKAROUND} procedure TPdfControl.WMEraseBkgnd(var Message: TWMEraseBkgnd); begin @@ -744,11 +772,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 diff --git a/Source/PdfiumLib.pas b/Source/PdfiumLib.pas index fbf855b..537bcc1 100644 --- a/Source/PdfiumLib.pas +++ b/Source/PdfiumLib.pas @@ -1,12 +1,16 @@ -{$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 - // Use DLLs (x64, x86) from https://github.com/bblanchon/pdfium-binaries // // DLL Version: chromium/5744 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) @@ -18,20 +22,34 @@ 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; @@ -8586,7 +8604,11 @@ 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; + {$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. @@ -8596,13 +8618,15 @@ TImportFuncRec = record end; const + {$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..424 - {$IFDEF MSWINDOWS} - + 2 - {$IFDEF _SKIA_SUPPORT_ } + 2 {$ENDIF} - {$IFDEF PDF_ENABLE_V8 } + 3 {$ENDIF} - {$IFDEF PDF_ENABLE_XFA } + 3 {$ENDIF} - {$ENDIF} + {$IFDEF MSWINDOWS } + 2 {$ENDIF} + {$IFDEF _SKIA_SUPPORT_} + 2 {$ENDIF} + {$IFDEF PDF_ENABLE_V8 } + 3 {$ENDIF} + {$IFDEF PDF_ENABLE_XFA} + 3 {$ENDIF} ] of TImportFuncRec = ( // *** _FPDFVIEW_H_ *** @@ -9099,6 +9123,10 @@ TImportFuncRec = record (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'; @@ -9161,9 +9189,13 @@ procedure InitPDFiumEx(const DllFileName: string{$IFDEF PDF_ENABLE_V8}; const Re 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 @@ -9173,7 +9205,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 @@ -9239,7 +9271,9 @@ procedure InitPDFiumEx(const DllFileName: string{$IFDEF PDF_ENABLE_V8}; const Re {$ENDIF PDF_ENABLE_V8} // 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 := 4; LibraryConfig.m_RendererType := FPDF_RENDERERTYPE_AGG; {if IsSkiaAvailable and SkiaRendererEnabled then From bb9f9ce630ff8005484ad7a501bc7caaf99a6537 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Tue, 3 Oct 2023 13:33:22 +0200 Subject: [PATCH 36/59] Updated to chromium/6043 --- README.md | 4 +- Source/PdfiumCore.pas | 8 +++ Source/PdfiumLib.pas | 148 ++++++++++++++++++++++++++++++------------ 3 files changed, 117 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index 255744d..24ce23c 100644 --- a/README.md +++ b/README.md @@ -4,10 +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/5744](https://github.com/bblanchon/pdfium-binaries/releases/tag/chromium%2F5744) +Binary release: [chromium/6043](https://github.com/bblanchon/pdfium-binaries/releases/tag/chromium%2F6043) ## Required pdfium.dll version -chromium/5744 +chromium/6043 ## Features - Multiple PDF load functions: diff --git a/Source/PdfiumCore.pas b/Source/PdfiumCore.pas index 8ca9edf..1f327fe 100644 --- a/Source/PdfiumCore.pas +++ b/Source/PdfiumCore.pas @@ -520,6 +520,7 @@ TCustomLoadDataRec = record FCustomLoadData: PCustomLoadDataRec; FForm: FPDF_FORMHANDLE; + FJSPlatform: IPDF_JsPlatform; FFormFillHandler: TPdfFormFillHandler; FFormFieldHighlightColor: TColorRef; FFormFieldHighlightAlpha: Integer; @@ -1532,6 +1533,11 @@ procedure TPdfDocument.DocumentLoaded; 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; @@ -1539,6 +1545,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); diff --git a/Source/PdfiumLib.pas b/Source/PdfiumLib.pas index 537bcc1..121dc71 100644 --- a/Source/PdfiumLib.pas +++ b/Source/PdfiumLib.pas @@ -1,6 +1,6 @@ // Use DLLs (x64, x86) from https://github.com/bblanchon/pdfium-binaries // -// DLL Version: chromium/5744 +// DLL Version: chromium/6043 unit PdfiumLib; {$IFDEF FPC} @@ -54,7 +54,7 @@ interface PTIME_T = ^TIME_T; // Returns True if the pdfium.dll supports Skia. -function IsSkiaAvailable: Boolean; +function PDF_IsSkiaAvailable: Boolean; // *** _FPDFVIEW_H_ *** @@ -121,9 +121,9 @@ __FPDF_PTRREC = record end; FPDF_PAGEOBJECTMARK = type __PFPDF_PTRREC; FPDF_PAGERANGE = type __PFPDF_PTRREC; FPDF_PATHSEGMENT = type __PFPDF_PTRREC; - FPDF_RECORDER = type Pointer; // Passed into Skia as a SkPictureRecorder. 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_STRUCTTREE = type __PFPDF_PTRREC; @@ -150,12 +150,14 @@ __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. + // 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. @@ -258,19 +260,6 @@ FS_QUADPOINTSF = record // 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 @@ -325,7 +314,7 @@ FPDF_LIBRARY_CONFIG = record 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: @@ -336,15 +325,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}; @@ -477,7 +485,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; @@ -670,17 +678,28 @@ FPDF_FILEHANDLER = record var FPDF_GetTrailerEnds: function(document: FPDF_DOCUMENT; buffer: PUINT; length: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -// Function: FPDF_GetDocPermission +// 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. @@ -923,18 +942,17 @@ FPDF_COLORSCHEME = record clipping: PFS_RECTF; flags: Integer); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; {$IFDEF _SKIA_SUPPORT_} -// Experimental API. -// Function: FPDF_RenderPageSkp -// Render contents of a page to a Skia SkPictureRecorder. +// 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: -// The SkPictureRecorder that holds the rendering of the page, or NULL -// on failure. Caller takes ownership of the returned result. +// None. var - FPDF_RenderPageSkp: function(page: FPDF_PAGE; size_x, size_y: Integer): FPDF_RECORDER; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + FPDF_RenderPageSkia: procedure(canvas: FPDF_SKIA_CANVAS; page: FPDF_PAGE; size_x, size_y: Integer); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; {$ENDIF _SKIA_SUPPORT_} // Function: FPDF_ClosePage @@ -1550,6 +1568,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 @@ -3027,6 +3075,21 @@ FPDF_FILEWRITE = record 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. @@ -6590,7 +6653,7 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; {$IFDEF _SKIA_SUPPORT_} 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_} @@ -8622,7 +8685,7 @@ TImportFuncRec = record {$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..424 + ImportFuncs: array[0..427 {$IFDEF MSWINDOWS } + 2 {$ENDIF} {$IFDEF _SKIA_SUPPORT_} + 2 {$ENDIF} {$IFDEF PDF_ENABLE_V8 } + 3 {$ENDIF} @@ -8630,8 +8693,8 @@ TImportFuncRec = record ] of TImportFuncRec = ( // *** _FPDFVIEW_H_ *** - (P: @@FPDF_InitLibrary; N: 'FPDF_InitLibrary'), (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} @@ -8646,6 +8709,7 @@ TImportFuncRec = record (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'), @@ -8662,7 +8726,7 @@ TImportFuncRec = record (P: @@FPDF_RenderPageBitmap; N: 'FPDF_RenderPageBitmap'), (P: @@FPDF_RenderPageBitmapWithMatrix; N: 'FPDF_RenderPageBitmapWithMatrix'), {$IFDEF _SKIA_SUPPORT_} - (P: @@FPDF_RenderPageSkp; N: 'FPDF_RenderPageSkp'; Quirk: True; Optional: True), + (P: @@FPDF_RenderPageSkia; N: 'FPDF_RenderPageSkia'; Quirk: True; Optional: True), {$ENDIF _SKIA_SUPPORT_} (P: @@FPDF_ClosePage; N: 'FPDF_ClosePage'), (P: @@FPDF_CloseDocument; N: 'FPDF_CloseDocument'), @@ -8704,6 +8768,7 @@ TImportFuncRec = record (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'), @@ -8825,6 +8890,7 @@ TImportFuncRec = record (P: @@FPDFText_CountChars; N: 'FPDFText_CountChars'), (P: @@FPDFText_GetUnicode; N: 'FPDFText_GetUnicode'), (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'), @@ -8969,7 +9035,7 @@ TImportFuncRec = record (P: @@FPDF_RemoveFormFieldHighlight; N: 'FPDF_RemoveFormFieldHighlight'), (P: @@FPDF_FFLDraw; N: 'FPDF_FFLDraw'), {$IFDEF _SKIA_SUPPORT_} - (P: @@FPDF_FFLRecord; N: 'FPDF_FFLRecord'; Quirk: True; Optional: True), + (P: @@FPDF_FFLDrawSkia; N: 'FPDF_FFLDrawSkia'; Quirk: True; Optional: True), {$ENDIF _SKIA_SUPPORT_} (P: @@FPDF_GetFormType; N: 'FPDF_GetFormType'), @@ -9153,11 +9219,11 @@ function PDF_USE_XFA: Boolean; {$ENDIF PDF_ENABLE_XFA} end; -function IsSkiaAvailable: Boolean; +function PDF_IsSkiaAvailable: Boolean; begin {$IFDEF _SKIA_SUPPORT_} - Result := Assigned(FPDF_RenderPageSkp) and (@FPDF_RenderPageSkp <> @NotLoaded) and (@FPDF_RenderPageSkp <> @FunctionNotSupported) - and Assigned(FPDF_FFLRecord) and (@FPDF_FFLRecord <> @NotLoaded) and (@FPDF_FFLRecord <> @FunctionNotSupported); + 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 _SKIA_SUPPORT_} From 8f346d015a24acffc25c73e3abe1b15cc74879e4 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Sat, 23 Dec 2023 19:32:43 +0100 Subject: [PATCH 37/59] Fixed #36 - Annotation Links have to be accessed differently that WebLinks - Renamed OnWebLinkClick to OnLinkClick as it is now called for WebLinks and AnnotationsLinks --- Example/MainFrm.pas | 6 +-- Source/PdfiumCore.pas | 102 +++++++++++++++++++++++++++++++++++++----- Source/PdfiumCtrl.pas | 67 +++++++++++++++++---------- 3 files changed, 136 insertions(+), 39 deletions(-) diff --git a/Example/MainFrm.pas b/Example/MainFrm.pas index 688bf14..38a07f3 100644 --- a/Example/MainFrm.pas +++ b/Example/MainFrm.pas @@ -36,7 +36,7 @@ TfrmMain = class(TForm) private { Private-Deklarationen } FCtrl: TPdfControl; - procedure WebLinkClick(Sender: TObject; Url: string); + procedure LinkClick(Sender: TObject; Url: string); procedure ListAttachments; public { Public-Deklarationen } @@ -70,7 +70,7 @@ procedure TfrmMain.FormCreate(Sender: TObject); //FCtrl.PageShadowColor := clDkGray; FCtrl.ScaleMode := smFitWidth; //FCtrl.PageColor := RGB(255, 255, 200); - FCtrl.OnWebLinkClick := WebLinkClick; + FCtrl.OnLinkClick := LinkClick; edtZoom.Value := FCtrl.ZoomPercentage; @@ -135,7 +135,7 @@ procedure TfrmMain.btnScaleClick(Sender: TObject); Caption := GetEnumName(TypeInfo(TPdfControlScaleMode), Ord(FCtrl.ScaleMode)); end; -procedure TfrmMain.WebLinkClick(Sender: TObject; Url: string); +procedure TfrmMain.LinkClick(Sender: TObject; Url: string); begin ShowMessage(Url); end; diff --git a/Source/PdfiumCore.pas b/Source/PdfiumCore.pas index 1f327fe..28b85c7 100644 --- a/Source/PdfiumCore.pas +++ b/Source/PdfiumCore.pas @@ -60,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 @@ -341,7 +343,7 @@ TPdfPage = class(TObject) 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; @@ -415,6 +417,8 @@ TPdfPage = class(TObject) function GetTextRect(RectIndex: Integer): TPdfRect; function HasFormFieldAtPoint(X, Y: Double): TPdfFormFieldType; + function IsLinkAtPoint(X, Y: Double): Boolean; overload; + function IsLinkAtPoint(X, Y: Double; var Uri: string): Boolean; overload; function GetWebLinkCount: Integer; function GetWebLinkURL(LinkIndex: Integer): string; @@ -1188,6 +1192,27 @@ 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; @@ -2022,10 +2047,10 @@ procedure TPdfPage.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 @@ -2185,9 +2210,18 @@ function TPdfPage.PageToDevice(X, Y, Width, Height: Integer; PageX, PageY: Doubl end; function TPdfPage.DeviceToPage(X, Y, Width, Height: Integer; const R: TRect; Rotate: TPdfPageRotation): TPdfRect; +var + T: Double; begin Result.TopLeft := DeviceToPage(X, Y, Width, Height, R.Left, R.Top, Rotate); Result.BottomRight := DeviceToPage(X, Y, Width, Height, R.Right, R.Bottom, Rotate); +{ // Page coordinales are upside down, but device coordinates aren't. So we need to swap Top and Bottom. + if Result.Top < Result.Bottom then + begin + T := Result.Top; + Result.Top := Result.Bottom; + Result.Bottom := T; + end;} end; function TPdfPage.PageToDevice(X, Y, Width, Height: Integer; const R: TPdfRect; Rotate: TPdfPageRotation): TRect; @@ -2196,6 +2230,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; @@ -2237,9 +2272,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, @@ -2402,11 +2439,52 @@ function TPdfPage.GetTextRect(RectIndex: Integer): TPdfRect; Result := TPdfRect.Empty; end; +function TPdfPage.IsLinkAtPoint(X, Y: Double): Boolean; +var + Link: FPDF_LINK; +begin + Link := FPDFLink_GetLinkAtPoint(Handle, X, Y); + Result := (Link <> nil) and (FPDFLink_GetAction(Link) <> nil); +end; + +function TPdfPage.IsLinkAtPoint(X, Y: Double; var Uri: string): Boolean; +var + Link: FPDF_LINK; + Action: FPDF_ACTION; + Buf: UTF8String; + ByteSize: Integer; +begin + Result := False; + Action := nil; + Link := FPDFLink_GetLinkAtPoint(Handle, X, Y); + if Link <> nil then + Action := FPDFLink_GetAction(Link); + if Action <> nil then + Result := True; + + Uri := ''; + if Result then + begin + // Get required ByteSize + 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 + Uri := UTF8ToString(Buf); + end; + end; +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 @@ -2421,11 +2499,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, PWideChar(Result), Len + 1); // including #0 terminator + FPDFLink_GetURL(FPageLinkHandle, LinkIndex, PWideChar(Result), Len + 1); // including #0 terminator end; end; end; @@ -2433,7 +2511,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; @@ -2441,7 +2519,7 @@ 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; diff --git a/Source/PdfiumCtrl.pas b/Source/PdfiumCtrl.pas index aa7ea06..f3fe6d1 100644 --- a/Source/PdfiumCtrl.pas +++ b/Source/PdfiumCtrl.pas @@ -30,7 +30,7 @@ interface Windows, Messages, Types, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, PdfiumCore; const - cPdfControlDefaultDrawOptions = []; + cPdfControlDefaultDrawOptions = [proAnnotations]; type TPdfControlScaleMode = ( @@ -40,7 +40,7 @@ interface smZoom ); - TPdfControlWebLinkClickEvent = procedure(Sender: TObject; Url: string) of object; + TPdfControlLinkClickEvent = procedure(Sender: TObject; Url: string) of object; TPdfControlRectArray = array of TRect; TPdfControlPdfRectArray = array of TPdfRect; @@ -82,7 +82,7 @@ TPdfControl = class(TCustomControl) FHighlightText: string; FHighlightMatchCase: Boolean; FHighlightMatchWholeWord: Boolean; - FOnWebLinkClick: TPdfControlWebLinkClickEvent; + FOnLinkClick: TPdfControlLinkClickEvent; FOnPageChange: TNotifyEvent; FOnPaint: TNotifyEvent; FFormOutputSelectedRects: TPdfRectArray; @@ -154,7 +154,7 @@ TPdfControl = class(TCustomControl) procedure WMChar(var Message: TWMChar); message WM_CHAR; procedure WMKillFocus(var Message: TWMKillFocus); message WM_KILLFOCUS; - procedure WebLinkClick(Url: string); virtual; + procedure LinkClick(const Url: string); virtual; procedure PageChange; virtual; procedure PageContentChanged(Closing: Boolean); procedure PageLayoutChanged; @@ -203,8 +203,8 @@ TPdfControl = class(TCustomControl) procedure HightlightText(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 IsLinkAt(X, Y: Integer): Boolean; overload; + function IsLinkAt(X, Y: Integer; var Url: string): Boolean; overload; function GotoNextPage(ScrollTransition: Boolean = False): Boolean; function GotoPrevPage(ScrollTransition: Boolean = False): Boolean; @@ -240,7 +240,7 @@ TPdfControl = class(TCustomControl) property PageShadowSize: Integer read FPageShadowSize write SetPageShadowSize default 4; property PageShadowPadding: Integer read FPageShadowPadding write SetPageShadowPadding default 44; - property OnWebLinkClick: TPdfControlWebLinkClickEvent read FOnWebLinkClick write FOnWebLinkClick; + property OnLinkClick: TPdfControlLinkClickEvent read FOnLinkClick write FOnLinkClick; property OnPageChange: TNotifyEvent read FOnPageChange write FOnPageChange; property Align; @@ -311,7 +311,7 @@ TPdfDocumentVclPrinter = class(TPdfDocumentPrinter) implementation uses - Math, Clipbrd, Character, Printers; + Math, Clipbrd, Character, Printers, PdfiumLib; const cScrollTimerId = 1; @@ -1368,8 +1368,8 @@ procedure TPdfControl.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: In StopScrollTimer; if AllowUserTextSelection and not FFormFieldFocused then SetSelStopCharIndex(X, Y); - if not FSelectionActive and IsWebLinkAt(X, Y, Url) then - WebLinkClick(Url); + if not FSelectionActive and IsLinkAt(X, Y, Url) then + LinkClick(Url); end; end; end; @@ -1380,6 +1380,7 @@ procedure TPdfControl.MouseMove(Shift: TShiftState; X, Y: Integer); Style: NativeInt; NewCursor: TCursor; Page: TPdfPage; + Proceed: Boolean; begin inherited MouseMove(Shift, X, Y); NewCursor := Cursor; @@ -1390,7 +1391,11 @@ procedure TPdfControl.MouseMove(Shift: TShiftState; X, Y: Integer); Page := CurrentPage; if Page.FormEventMouseMove(Shift, PagePt.X, PagePt.Y) then begin + Proceed := False; case Page.HasFormFieldAtPoint(PagePt.X, PagePt.Y) of + fftUnknown: + // Could be a annotation link with a URL + Proceed := True; fftTextField: NewCursor := crIBeam; fftComboBox, @@ -1399,7 +1404,8 @@ procedure TPdfControl.MouseMove(Shift: TShiftState; X, Y: Integer); else NewCursor := crDefault; end; - Exit; + if not Proceed then + Exit; end; end; @@ -1437,7 +1443,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 Assigned(FOnLinkClick) and IsLinkAt(X, Y) then NewCursor := crHandPoint else if CurrentPage.GetCharIndexAt(PagePt.X, PagePt.Y, 5, 5) >= 0 then NewCursor := crIBeam @@ -1456,7 +1462,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(FOnLinkClick) then Cursor := crDefault; end; inherited; @@ -1956,42 +1962,55 @@ procedure TPdfControl.GetPageWebLinks; function TPdfControl.GetWebLinkIndex(X, Y: Integer): Integer; var RectIndex: Integer; - Pt: TPoint; + Pt: TPdfPoint; Page: TPdfPage; begin - Pt := Point(X, Y); Page := CurrentPage; if Page <> nil then begin + Pt := DeviceToPage(X, Y); 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 + if FWebLinksRects[Result][RectIndex].PtIn(Pt) then Exit; end; Result := -1; end; -function TPdfControl.IsWebLinkAt(X, Y: Integer): Boolean; +function TPdfControl.IsLinkAt(X, Y: Integer): Boolean; +var + PdfPt: TPdfPoint; begin Result := GetWebLinkIndex(X, Y) <> -1; + if not Result and IsPageValid then + begin + // Annotation Links cannot be found with the WebLink interface + PdfPt := DeviceToPage(X, Y); + Result := CurrentPage.IsLinkAtPoint(PdfPt.X, PdfPt.Y); + end; end; -function TPdfControl.IsWebLinkAt(X, Y: Integer; var Url: string): Boolean; +function TPdfControl.IsLinkAt(X, Y: Integer; var Url: string): Boolean; var Index: Integer; + PdfPt: TPdfPoint; begin Index := GetWebLinkIndex(X, Y); Result := Index <> -1; - if Result and IsPageValid then + Url := ''; + if Result then Url := CurrentPage.GetWebLinkURL(Index) - else - Url := ''; + else if IsPageValid then + begin + PdfPt := DeviceToPage(X, Y); + Result := CurrentPage.IsLinkAtPoint(PdfPt.X, PdfPt.Y, Url); + end; end; -procedure TPdfControl.WebLinkClick(Url: string); +procedure TPdfControl.LinkClick(const Url: string); begin - if Assigned(FOnWebLinkClick) then - FOnWebLinkClick(Self, Url); + if Assigned(FOnLinkClick) then + FOnLinkClick(Self, Url); end; procedure TPdfControl.UpdatePageDrawInfo; From 8650bdc54ff1881bbc0c9236886d30f5f6f4e2f4 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Sat, 23 Dec 2023 20:27:33 +0100 Subject: [PATCH 38/59] Fixed #29: Added experimental Page.Annotations.NewTextAnnotation() method --- Example/MainFrm.dfm | 19 +++++++++++---- Example/MainFrm.pas | 13 ++++++++++ Source/PdfiumCore.pas | 57 ++++++++++++++++++++++++++++++++++++------- Source/PdfiumCtrl.pas | 4 ++- 4 files changed, 78 insertions(+), 15 deletions(-) diff --git a/Example/MainFrm.dfm b/Example/MainFrm.dfm index 781e600..4373bd0 100644 --- a/Example/MainFrm.dfm +++ b/Example/MainFrm.dfm @@ -33,16 +33,16 @@ object frmMain: TfrmMain object btnCopy: TButton Left = 153 Top = 0 - Width = 75 + Width = 56 Height = 25 Caption = 'Highlight' TabOrder = 2 OnClick = btnCopyClick end object btnScale: TButton - Left = 225 + Left = 209 Top = 0 - Width = 75 + Width = 56 Height = 25 Caption = 'Scale' TabOrder = 3 @@ -78,9 +78,9 @@ object frmMain: TfrmMain OnChange = edtZoomChange end object btnPrint: TButton - Left = 297 + Left = 265 Top = 0 - Width = 75 + Width = 50 Height = 25 Caption = 'Print' TabOrder = 7 @@ -107,6 +107,15 @@ object frmMain: TfrmMain TabOrder = 9 OnClick = chkChangePageOnMouseScrollingClick end + object btnAddAnnotation: TButton + Left = 315 + Top = 0 + Width = 50 + Height = 25 + Caption = 'Annot' + TabOrder = 10 + OnClick = btnAddAnnotationClick + end object PrintDialog1: TPrintDialog MinPage = 1 MaxPage = 10 diff --git a/Example/MainFrm.pas b/Example/MainFrm.pas index 38a07f3..1923f6d 100644 --- a/Example/MainFrm.pas +++ b/Example/MainFrm.pas @@ -22,6 +22,7 @@ TfrmMain = class(TForm) ListViewAttachments: TListView; SaveDialog1: TSaveDialog; chkChangePageOnMouseScrolling: TCheckBox; + btnAddAnnotation: TButton; procedure FormCreate(Sender: TObject); procedure btnPrevClick(Sender: TObject); procedure btnNextClick(Sender: TObject); @@ -33,6 +34,7 @@ TfrmMain = class(TForm) procedure btnPrintClick(Sender: TObject); procedure ListViewAttachmentsDblClick(Sender: TObject); procedure chkChangePageOnMouseScrollingClick(Sender: TObject); + procedure btnAddAnnotationClick(Sender: TObject); private { Private-Deklarationen } FCtrl: TPdfControl; @@ -201,4 +203,15 @@ procedure TfrmMain.ListViewAttachmentsDblClick(Sender: TObject); end; end; +procedure TfrmMain.btnAddAnnotationClick(Sender: TObject); +begin + // Add a new annotation and make it persietent so that is 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/Source/PdfiumCore.pas b/Source/PdfiumCore.pas index 28b85c7..5d4abde 100644 --- a/Source/PdfiumCore.pas +++ b/Source/PdfiumCore.pas @@ -323,6 +323,11 @@ TPdfAnnotationList = class(TObject) 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; @@ -2210,18 +2215,9 @@ function TPdfPage.PageToDevice(X, Y, Width, Height: Integer; PageX, PageY: Doubl end; function TPdfPage.DeviceToPage(X, Y, Width, Height: Integer; const R: TRect; Rotate: TPdfPageRotation): TPdfRect; -var - T: Double; begin Result.TopLeft := DeviceToPage(X, Y, Width, Height, R.Left, R.Top, Rotate); Result.BottomRight := DeviceToPage(X, Y, Width, Height, R.Right, R.Bottom, Rotate); -{ // Page coordinales are upside down, but device coordinates aren't. So we need to swap Top and Bottom. - if Result.Top < Result.Bottom then - begin - T := Result.Top; - Result.Top := Result.Bottom; - Result.Bottom := T; - end;} end; function TPdfPage.PageToDevice(X, Y, Width, Height: Integer; const R: TPdfRect; Rotate: TPdfPageRotation): TRect; @@ -2249,7 +2245,20 @@ procedure TPdfPage.SetRotation(const Value: TPdfPageRotation); 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); @@ -3295,6 +3304,36 @@ function TPdfAnnotationList.GetAnnotationsLoaded: Boolean; 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; + { TPdfFormFieldList } constructor TPdfFormFieldList.Create(AAnnotations: TPdfAnnotationList); diff --git a/Source/PdfiumCtrl.pas b/Source/PdfiumCtrl.pas index f3fe6d1..fd302ec 100644 --- a/Source/PdfiumCtrl.pas +++ b/Source/PdfiumCtrl.pas @@ -159,7 +159,6 @@ TPdfControl = class(TCustomControl) procedure PageContentChanged(Closing: Boolean); procedure PageLayoutChanged; function IsPageValid: Boolean; - procedure InvalidatePage; function GetSelectionRects: TPdfControlRectArray; function GetWebLinkIndex(X, Y: Integer): Integer; procedure DestroyWnd; override; @@ -172,6 +171,9 @@ TPdfControl = class(TCustomControl) constructor Create(AOwner: TComponent); override; destructor Destroy; override; + { InvalidatePage forces the page to be rendered again and invalidates the control. } + procedure InvalidatePage; + procedure LoadFromCustom(ReadFunc: TPdfDocumentCustomReadProc; ASize: LongWord; AParam: Pointer; const APassword: UTF8String = ''); procedure LoadFromActiveStream(Stream: TStream; const APassword: UTF8String = ''); // Stream must not be released until the document is closed procedure LoadFromActiveBuffer(Buffer: Pointer; Size: Int64; const APassword: UTF8String = ''); // Buffer must not be released until the document is closed From cbb9273abe24e3c9edc00b4b127070c8b279984d Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Sun, 24 Dec 2023 00:35:13 +0100 Subject: [PATCH 39/59] - Added link annotation handling (URI, Goto, RemoteGoto, Launch, EmbeddedGoto). OnAnnotationLinkClick must be used to handle annotation links. - WebLinks are handled by OnWebLinkClick. If OnAnnotationLinkClick is not assigned, then URI link annotations are also handled by OnWebLinkClick (backward compatibility). - TPdfAnnotation was extended with link annotation methods - With the new class TPdfPageWebLinkInfo, the WebLinks cache code was moved from the PdfiumCtrl.pas to PdfiumCore.pas. --- Example/MainFrm.dfm | 193 ++++++++------- Example/MainFrm.pas | 55 ++++- Source/PdfiumCore.pas | 540 ++++++++++++++++++++++++++++++++++++++---- Source/PdfiumCtrl.pas | 156 +++++++----- 4 files changed, 748 insertions(+), 196 deletions(-) diff --git a/Example/MainFrm.dfm b/Example/MainFrm.dfm index 4373bd0..41e7e45 100644 --- a/Example/MainFrm.dfm +++ b/Example/MainFrm.dfm @@ -10,82 +10,10 @@ object frmMain: TfrmMain Font.Height = -11 Font.Name = 'Tahoma' Font.Style = [] + OldCreateOrder = True OnCreate = FormCreate + PixelsPerInch = 96 TextHeight = 13 - object btnPrev: TButton - Left = 0 - Top = 0 - Width = 75 - Height = 25 - Caption = '<' - TabOrder = 0 - OnClick = btnPrevClick - end - object btnNext: TButton - Left = 72 - Top = 0 - Width = 75 - Height = 25 - Caption = '>' - TabOrder = 1 - OnClick = btnNextClick - end - object btnCopy: TButton - Left = 153 - Top = 0 - Width = 56 - Height = 25 - Caption = 'Highlight' - TabOrder = 2 - OnClick = btnCopyClick - end - object btnScale: TButton - Left = 209 - Top = 0 - Width = 56 - 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 = 265 - Top = 0 - Width = 50 - Height = 25 - Caption = 'Print' - TabOrder = 7 - OnClick = btnPrintClick - end object ListViewAttachments: TListView Left = 0 Top = 600 @@ -93,28 +21,113 @@ object frmMain: TfrmMain Height = 47 Align = alBottom Columns = <> - TabOrder = 8 + TabOrder = 0 ViewStyle = vsList Visible = False OnDblClick = ListViewAttachmentsDblClick end - object chkChangePageOnMouseScrolling: TCheckBox - Left = 599 - Top = 4 - Width = 162 - Height = 17 - Caption = 'ChangePageOnMouseScrolling' - TabOrder = 9 - OnClick = chkChangePageOnMouseScrollingClick - end - object btnAddAnnotation: TButton - Left = 315 + object pnlButtons: TPanel + Left = 0 Top = 0 - Width = 50 + Width = 780 Height = 25 - Caption = 'Annot' - TabOrder = 10 - OnClick = btnAddAnnotationClick + Align = alTop + BevelOuter = bvNone + TabOrder = 1 + ExplicitLeft = 8 + ExplicitTop = 144 + 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 diff --git a/Example/MainFrm.pas b/Example/MainFrm.pas index 1923f6d..91bae58 100644 --- a/Example/MainFrm.pas +++ b/Example/MainFrm.pas @@ -11,7 +11,7 @@ interface TfrmMain = class(TForm) btnPrev: TButton; btnNext: TButton; - btnCopy: TButton; + btnHighlight: TButton; btnScale: TButton; chkLCDOptimize: TCheckBox; chkSmoothScroll: TCheckBox; @@ -23,10 +23,11 @@ TfrmMain = class(TForm) 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); @@ -38,7 +39,8 @@ TfrmMain = class(TForm) private { Private-Deklarationen } FCtrl: TPdfControl; - procedure LinkClick(Sender: TObject; Url: string); + procedure WebLinkClick(Sender: TObject; Url: string); + procedure AnnotationLinkClick(Sender: TObject; LinkAnnotation: TPdfAnnotation); procedure ListAttachments; public { Public-Deklarationen } @@ -72,7 +74,8 @@ procedure TfrmMain.FormCreate(Sender: TObject); //FCtrl.PageShadowColor := clDkGray; FCtrl.ScaleMode := smFitWidth; //FCtrl.PageColor := RGB(255, 255, 200); - FCtrl.OnLinkClick := LinkClick; + FCtrl.OnWebLinkClick := WebLinkClick; + FCtrl.OnAnnotationLinkClick := AnnotationLinkClick; edtZoom.Value := FCtrl.ZoomPercentage; @@ -123,7 +126,7 @@ 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); end; @@ -137,11 +140,51 @@ procedure TfrmMain.btnScaleClick(Sender: TObject); Caption := GetEnumName(TypeInfo(TPdfControlScaleMode), Ord(FCtrl.ScaleMode)); end; -procedure TfrmMain.LinkClick(Sender: TObject; Url: string); +procedure TfrmMain.WebLinkClick(Sender: TObject; Url: string); begin ShowMessage(Url); end; +procedure TfrmMain.AnnotationLinkClick(Sender: TObject; LinkAnnotation: TPdfAnnotation); +var + Dest: TPdfLinkGotoDestination; + X, Y{, Zoom}: Double; + Pt: TPoint; +begin + case LinkAnnotation.LinkType of + altGoto: + begin + Dest := LinkAnnotation.GetLinkGotoDestination(); + FCtrl.PageIndex := Dest.PageIndex; + X := 0; + Y := 0; + //Zoom := 0; + if Dest.XValid then + X := Dest.X; + if Dest.YValid then + Y := Dest.Y; + {if Dest.ZoomValid then + Zoom := Dest.Zoom; + FCtrl.ZoomPercentage := Int(Zoom);} + + Pt := FCtrl.PageToDevice(X, Y); + FCtrl.ScrollContentTo(Pt.X, Pt.Y); + end; + + altRemoteGoto: + ShowMessage('Remote Goto: ' + LinkAnnotation.LinkFileName); + + altURI: + ShowMessage('URL: ' + LinkAnnotation.LinkUri); + + altLaunch: + ShowMessage('Launch: ' + LinkAnnotation.LinkFileName); + + altEmbeddedGoto: + ShowMessage('EmbeddedGoto: ' + LinkAnnotation.LinkUri); + end; +end; + procedure TfrmMain.chkChangePageOnMouseScrollingClick(Sender: TObject); begin FCtrl.ChangePageOnMouseScrolling := chkChangePageOnMouseScrolling.Checked; diff --git a/Source/PdfiumCore.pas b/Source/PdfiumCore.pas index 5d4abde..b40eb94 100644 --- a/Source/PdfiumCore.pas +++ b/Source/PdfiumCore.pas @@ -71,6 +71,7 @@ TPdfRect = record end; TPdfRectArray = array of TPdfRect; + TPdfFloatArray = array of FS_FLOAT; TPdfDocumentCustomReadProc = function(Param: Pointer; Position: LongWord; Buffer: PByte; Size: LongWord): Boolean; @@ -174,18 +175,40 @@ TPdfRect = record 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, + 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, + 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 + ); + _TPdfBitmapHideCtor = class(TObject) private procedure Create; @@ -290,20 +313,67 @@ TPdfFormFieldList = class(TObject) 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; + FLinkGotoDest: TPdfLinkGotoDestination; + + 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; + // IsFormField: property FormField: TPdfFormField read GetFormField; + // IsLink: + property LinkType: TPdfAnnotationLinkType read FLinkType; + property LinkUri: string read GetLinkUri; + property LinkFileName: string read GetLinkFileName; + function GetLinkGotoDestination(ARemoteDocument: TPdfDocument = nil): TPdfLinkGotoDestination; + property AnnotationRect: TPdfRect read GetAnnotationRect; property Handle: FPDF_ANNOTATION read FHandle; end; @@ -319,6 +389,7 @@ TPdfAnnotationList = class(TObject) protected procedure DestroyingItem(Item: TPdfAnnotation); procedure DestroyingFormField(FormField: TPdfFormField); + function FindLink(Link: FPDF_LINK): TPdfAnnotation; public constructor Create(APage: TPdfPage); destructor Destroy; override; @@ -333,10 +404,33 @@ TPdfAnnotationList = class(TObject) property Count: Integer read GetCount; property Items[Index: Integer]: TPdfAnnotation read GetItem; default; - { A list of all form fields annotations } + { A list of all form field annotations } property FormFields: TPdfFormFieldList read GetFormFields; end; + { TPdfPageWebLinkInfo 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. } + TPdfPageWebLinkInfo = 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; @@ -363,6 +457,9 @@ TPdfPage = class(TObject) 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; @@ -422,13 +519,27 @@ TPdfPage = class(TObject) function GetTextRect(RectIndex: Integer): TPdfRect; function HasFormFieldAtPoint(X, Y: Double): TPdfFormFieldType; - function IsLinkAtPoint(X, Y: Double): Boolean; overload; - function IsLinkAtPoint(X, Y: Double; var Uri: string): Boolean; overload; + { 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; @@ -500,6 +611,7 @@ TPdfAttachmentList = class(TObject) 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; @@ -702,6 +814,7 @@ implementation 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'; @@ -2083,6 +2196,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; @@ -2448,45 +2611,55 @@ function TPdfPage.GetTextRect(RectIndex: Integer): TPdfRect; Result := TPdfRect.Empty; end; -function TPdfPage.IsLinkAtPoint(X, Y: Double): Boolean; +function TPdfPage.IsUriLinkAtPoint(X, Y: Double): Boolean; var Link: FPDF_LINK; + Action: FPDF_ACTION; begin + Result := False; Link := FPDFLink_GetLinkAtPoint(Handle, X, Y); - Result := (Link <> nil) and (FPDFLink_GetAction(Link) <> nil); + 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.IsLinkAtPoint(X, Y: Double; var Uri: string): Boolean; +function TPdfPage.IsUriLinkAtPoint(X, Y: Double; var Uri: string): Boolean; var Link: FPDF_LINK; Action: FPDF_ACTION; - Buf: UTF8String; - ByteSize: Integer; begin - Result := False; Action := nil; + Result := False; Link := FPDFLink_GetLinkAtPoint(Handle, X, Y); if Link <> nil then + begin Action := FPDFLink_GetAction(Link); - if Action <> nil then - Result := True; + if (Action <> nil) and (FPDFAction_GetType(Action) = PDFACTION_URI) then + Result := True; + end; - Uri := ''; 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 - // Get required ByteSize - 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 - Uri := UTF8ToString(Buf); - end; - end; + Result := Annotations.FindLink(Link); + if (Result <> nil) and (Result.LinkType = altUnsupported) then + Result := nil; + end + else + Result := nil; end; function TPdfPage.GetWebLinkCount: Integer; @@ -2533,6 +2706,43 @@ function TPdfPage.GetWebLinkRect(LinkIndex, RectIndex: Integer): TPdfRect; Result := TPdfRect.Empty; end; +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.GetMouseModifier(const Shift: TShiftState): Integer; begin Result := 0; @@ -2912,6 +3122,14 @@ function TPdfAttachmentList.Add(const Name: string): TPdfAttachment; 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; @@ -3334,6 +3552,97 @@ function TPdfAnnotationList.NewTextAnnotation(const Text: string; const R: TPdfR 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; + + +{ TPdfPageWebLinkInfo } + +constructor TPdfPageWebLinkInfo.Create(APage: TPdfPage); +begin + inherited Create; + FPage := APage; + GetPageWebLinks; +end; + +procedure TPdfPageWebLinkInfo.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 TPdfPageWebLinkInfo.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 TPdfPageWebLinkInfo.GetCount: Integer; +begin + Result := Length(FWebLinksRects); +end; + +function TPdfPageWebLinkInfo.GetRect(Index: Integer): TPdfRectArray; +begin + Result := FWebLinksRects[Index]; +end; + +function TPdfPageWebLinkInfo.GetURL(Index: Integer): string; +begin + Result := FPage.GetWebLinkURL(Index); +end; + +function TPdfPageWebLinkInfo.IsWebLinkAt(X, Y: Double): Boolean; +begin + Result := GetWebLinkIndex(X, Y) <> -1; +end; + +function TPdfPageWebLinkInfo.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; + { TPdfFormFieldList } constructor TPdfFormFieldList.Create(AAnnotations: TPdfAnnotationList); @@ -3371,17 +3680,63 @@ procedure TPdfFormFieldList.DestroyingItem(Item: TPdfFormField); 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; + + { 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(FHandle); + + 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(FLinkGotoDest); FreeAndNil(FFormField); if FHandle <> nil then begin @@ -3393,26 +3748,123 @@ destructor TPdfAnnotation.Destroy; inherited Destroy; end; -function TPdfAnnotation.IsFormField: Boolean; +function TPdfAnnotation.GetPdfLinkAction: FPDF_ACTION; +var + Link: FPDF_LINK; begin - case FPDFAnnot_GetSubtype(Handle) of - FPDF_ANNOT_WIDGET, - FPDF_ANNOT_XFAWIDGET: - Result := True; - else - Result := False; + 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 + Result := FPage.GetPdfActionFilePath(GetPdfLinkAction) + else + Result := ''; +end; + +function TPdfAnnotation.GetLinkGotoDestination(ARemoteDocument: TPdfDocument = nil): TPdfLinkGotoDestination; +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 + if FLinkGotoDest = nil then begin - if not IsFormField then - raise EPdfException.CreateRes(@RsPdfAnnotationNotAFormFieldError); - FFormField := TPdfFormField.Create(Self); + 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); + + FLinkGotoDest := TPdfLinkGotoDestination.Create( + PageIndex, + HasXVal <> 0, HasYVal <> 0, HasZoomVal <> 0, + X, Y, Zoom, + ViewKind, ViewParams + ); + end; + end; + end; + end; end; - Result := FFormField; + Result := FLinkGotoDest; end; { TPdfFormField } diff --git a/Source/PdfiumCtrl.pas b/Source/PdfiumCtrl.pas index fd302ec..39fec41 100644 --- a/Source/PdfiumCtrl.pas +++ b/Source/PdfiumCtrl.pas @@ -40,7 +40,8 @@ interface smZoom ); - TPdfControlLinkClickEvent = procedure(Sender: TObject; Url: string) of object; + TPdfControlWebLinkClickEvent = procedure(Sender: TObject; Url: string) of object; + TPdfControlAnnotationLinkClickEvent = procedure(Sender: TObject; Link: TPdfAnnotation) of object; TPdfControlRectArray = array of TRect; TPdfControlPdfRectArray = array of TPdfRect; @@ -72,7 +73,7 @@ TPdfControl = class(TCustomControl) FSelStopCharIndex: Integer; FMouseDownPt: TPoint; FCheckForTrippleClick: Boolean; - FWebLinksRects: array of TPdfControlPdfRectArray; + FWebLinkInfo: TPdfPageWebLinkInfo; FDrawOptions: TPdfPageRenderOptions; FScaleMode: TPdfControlScaleMode; FZoomPercentage: Integer; @@ -82,7 +83,8 @@ TPdfControl = class(TCustomControl) FHighlightText: string; FHighlightMatchCase: Boolean; FHighlightMatchWholeWord: Boolean; - FOnLinkClick: TPdfControlLinkClickEvent; + FOnWebLinkClick: TPdfControlWebLinkClickEvent; + FOnAnnotationLinkClick: TPdfControlAnnotationLinkClickEvent; FOnPageChange: TNotifyEvent; FOnPaint: TNotifyEvent; FFormOutputSelectedRects: TPdfRectArray; @@ -154,13 +156,14 @@ TPdfControl = class(TCustomControl) procedure WMChar(var Message: TWMChar); message WM_CHAR; procedure WMKillFocus(var Message: TWMKillFocus); message WM_KILLFOCUS; - procedure LinkClick(const Url: string); virtual; + function IsClickableLinkAt(X, Y: Integer): Boolean; + procedure WebLinkClick(const Url: string); virtual; + procedure AnnotationLinkClick(LinkAnnotation: TPdfAnnotation); virtual; procedure PageChange; virtual; procedure PageContentChanged(Closing: Boolean); procedure PageLayoutChanged; function IsPageValid: Boolean; function GetSelectionRects: TPdfControlRectArray; - function GetWebLinkIndex(X, Y: Integer): Integer; procedure DestroyWnd; override; property DrawX: Integer read FDrawX; @@ -205,8 +208,11 @@ TPdfControl = class(TCustomControl) procedure HightlightText(const SearchText: string; MatchCase, MatchWholeWord: Boolean); procedure ClearHighlightText; - function IsLinkAt(X, Y: Integer): Boolean; overload; - function IsLinkAt(X, Y: Integer; var Url: string): Boolean; overload; + 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; @@ -242,7 +248,12 @@ TPdfControl = class(TCustomControl) property PageShadowSize: Integer read FPageShadowSize write SetPageShadowSize default 4; property PageShadowPadding: Integer read FPageShadowPadding write SetPageShadowPadding default 44; - property OnLinkClick: TPdfControlLinkClickEvent read FOnLinkClick write FOnLinkClick; + { 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; property Align; @@ -1342,6 +1353,7 @@ procedure TPdfControl.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: In PagePt: TPdfPoint; Url: string; Page: TPdfPage; + LinkAnnotation: TPdfAnnotation; begin inherited MouseUp(Button, Shift, X, Y); @@ -1370,8 +1382,23 @@ procedure TPdfControl.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: In StopScrollTimer; if AllowUserTextSelection and not FFormFieldFocused then SetSelStopCharIndex(X, Y); - if not FSelectionActive and IsLinkAt(X, Y, Url) then - LinkClick(Url); + if not FSelectionActive then + begin + if Assigned(FOnAnnotationLinkClick) or Assigned(FOnWebLinkClick) then + begin + LinkAnnotation := GetAnnotationLinkAt(X, Y); + if LinkAnnotation <> nil then + begin + if Assigned(FonAnnotationLinkClick) then + AnnotationLinkClick(LinkAnnotation) + else if LinkAnnotation.LinkType = altURI then + WebLinkClick(LinkAnnotation.LinkUri); + end + // If we have a Link Annotation and a WebLink, then the link annotation is prefered + else if Assigned(FOnWebLinkClick) and IsWebLinkAt(X, Y, Url) then + WebLinkClick(Url); + end; + end; end; end; end; @@ -1445,7 +1472,7 @@ procedure TPdfControl.MouseMove(Shift: TShiftState; X, Y: Integer); if IsPageValid then begin PagePt := DeviceToPage(X, Y); - if Assigned(FOnLinkClick) and IsLinkAt(X, Y) then + if IsClickableLinkAt(X, Y) then NewCursor := crHandPoint else if CurrentPage.GetCharIndexAt(PagePt.X, PagePt.Y, 5, 5) >= 0 then NewCursor := crIBeam @@ -1464,7 +1491,7 @@ procedure TPdfControl.CMMouseleave(var Message: TMessage); begin if (Cursor = crIBeam) or (Cursor = crHandPoint) then begin - if AllowUserTextSelection or Assigned(FOnLinkClick) then + if AllowUserTextSelection or Assigned(FOnWebLinkClick) or Assigned(FOnAnnotationLinkClick) then Cursor := crDefault; end; inherited; @@ -1940,79 +1967,96 @@ 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 := TPdfPageWebLinkInfo.Create(Page); +end; + +function TPdfControl.IsClickableLinkAt(X, Y: Integer): Boolean; +begin + if Assigned(FOnWebLinkClick) and IsWebLinkAt(X, Y) then + Result := True + else if Assigned(FOnAnnotationLinkClick) and IsAnnotationLinkAt(X, Y) then + Result := True + // Fallback in case OnAnnotationLinkClick is not assigend but OnWebLinkClick is, then we use + // WebLinkClick for the URI-Action Links. + else if not Assigned(FOnAnnotationLinkClick) and Assigned(FOnWebLinkClick) and IsUriAnnotationLinkAt(X, Y) then + Result := True + else + Result := False; +end; + +function TPdfControl.IsWebLinkAt(X, Y: Integer): Boolean; +var + PdfPt: TPdfPoint; +begin + if (FWebLinkInfo <> nil) and IsPageValid then begin - LinkCount := Page.GetWebLinkCount; - SetLength(FWebLinksRects, LinkCount); - for LinkIndex := 0 to LinkCount - 1 do - begin - RectCount := Page.GetWebLinkRectCount(LinkIndex); - SetLength(FWebLinksRects[LinkIndex], RectCount); - for RectIndex := 0 to RectCount - 1 do - FWebLinksRects[LinkIndex][RectIndex] := Page.GetWebLinkRect(LinkIndex, RectIndex); - end; + 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: TPdfPoint; - Page: TPdfPage; + PdfPt: TPdfPoint; begin - Page := CurrentPage; - if Page <> nil then + Url := ''; + if (FWebLinkInfo <> nil) and IsPageValid then begin - Pt := DeviceToPage(X, 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; + PdfPt := DeviceToPage(X, Y); + Result := FWebLinkInfo.IsWebLinkAt(PdfPt.X, PdfPt.Y, Url); + end + else + Result := False; end; -function TPdfControl.IsLinkAt(X, Y: Integer): Boolean; +function TPdfControl.IsUriAnnotationLinkAt(X, Y: Integer): Boolean; var PdfPt: TPdfPoint; begin - Result := GetWebLinkIndex(X, Y) <> -1; - if not Result and IsPageValid then + if IsPageValid then begin - // Annotation Links cannot be found with the WebLink interface PdfPt := DeviceToPage(X, Y); - Result := CurrentPage.IsLinkAtPoint(PdfPt.X, PdfPt.Y); - end; + Result := CurrentPage.IsUriLinkAtPoint(PdfPt.X, PdfPt.Y); + end + else + Result := False; +end; + +function TPdfControl.IsAnnotationLinkAt(X, Y: Integer): Boolean; +begin + Result := GetAnnotationLinkAt(X, Y) <> nil; end; -function TPdfControl.IsLinkAt(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; - Url := ''; - if Result then - Url := CurrentPage.GetWebLinkURL(Index) - else if IsPageValid then + if IsPageValid then begin PdfPt := DeviceToPage(X, Y); - Result := CurrentPage.IsLinkAtPoint(PdfPt.X, PdfPt.Y, Url); - end; + Result := CurrentPage.GetLinkAtPoint(PdfPt.X, PdfPt.Y); + end + else + Result := nil; +end; + +procedure TPdfControl.WebLinkClick(const Url: string); +begin + if Assigned(FOnWebLinkClick) then + FOnWebLinkClick(Self, Url); end; -procedure TPdfControl.LinkClick(const Url: string); +procedure TPdfControl.AnnotationLinkClick(LinkAnnotation: TPdfAnnotation); begin - if Assigned(FOnLinkClick) then - FOnLinkClick(Self, Url); + if Assigned(FOnAnnotationLinkClick) then + FOnAnnotationLinkClick(Self, LinkAnnotation); end; procedure TPdfControl.UpdatePageDrawInfo; From 4670f005a7ade12c0356ec63d8362704cbb429b4 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Sun, 24 Dec 2023 04:10:47 +0100 Subject: [PATCH 40/59] TPdfDocument.LoadFromFile() got a new LoadOption (dloDefault) and uses this as default parameter. With dloDefault the FPDF_LoadDocument function is used to load the PDF. PDFium's FPDF_LoadDocument was fixed to handle large (2GB+) PDF files and now supports UTF8 for the filename. --- Source/PdfiumCore.pas | 169 +++++++++++++++++++++++++++--------------- Source/PdfiumCtrl.pas | 50 ++++++------- 2 files changed, 133 insertions(+), 86 deletions(-) diff --git a/Source/PdfiumCore.pas b/Source/PdfiumCore.pas index b40eb94..a57faea 100644 --- a/Source/PdfiumCore.pas +++ b/Source/PdfiumCore.pas @@ -101,6 +101,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) @@ -633,6 +634,8 @@ TCustomLoadDataRec = record {$IFDEF MSWINDOWS} FFileHandle: THandle; FFileMapping: THandle; + {$ELSE} + FFileStream: TFileStream; {$ENDIF MSWINDOWS} FBuffer: PByte; FBytes: TBytes; @@ -652,9 +655,10 @@ TCustomLoadDataRec = record FOnFormGetCurrentPage: TPdfFormGetCurrentPageEvent; FOnFormFieldFocus: TPdfFormFieldFocusEvent; - procedure InternLoadFromMem(Buffer: PByte; Size: NativeInt; const APassword: UTF8String); - procedure InternLoadFromCustom(ReadFunc: TPdfDocumentCustomReadProc; ASize: LongWord; - AParam: Pointer; const APassword: UTF8String); + 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; @@ -679,13 +683,13 @@ TCustomLoadDataRec = record constructor Create; destructor Destroy; override; - procedure LoadFromCustom(ReadFunc: TPdfDocumentCustomReadProc; ASize: LongWord; AParam: Pointer; const APassword: UTF8String = ''); - procedure LoadFromActiveStream(Stream: TStream; const APassword: UTF8String = ''); // Stream must not be released until the document is closed - procedure LoadFromActiveBuffer(Buffer: Pointer; Size: NativeInt; const APassword: UTF8String = ''); // Buffer must not be released until the document is closed - procedure LoadFromBytes(const ABytes: TBytes; const APassword: UTF8String = ''); overload; - procedure LoadFromBytes(const ABytes: TBytes; AIndex: NativeInt; ACount: NativeInt; const APassword: UTF8String = ''); overload; - procedure LoadFromStream(AStream: TStream; const APassword: UTF8String = ''); - procedure LoadFromFile(const AFileName: string; const APassword: UTF8String = ''; ALoadOption: 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); @@ -1408,6 +1412,8 @@ procedure TPdfDocument.Close; CloseHandle(FFileHandle); FFileHandle := INVALID_HANDLE_VALUE; end; + {$ELSE} + FreeAndNil(FFileStream); {$ENDIF MSWINDOWS} FFileName := ''; @@ -1418,7 +1424,7 @@ procedure TPdfDocument.Close; end; {$IFDEF MSWINDOWS} -function ReadFromActiveFile(Param: Pointer; Position: LongWord; Buffer: PByte; Size: LongWord): Boolean; +function ReadFromActiveFileHandle(Param: Pointer; Position: LongWord; Buffer: PByte; Size: LongWord): Boolean; var NumRead: DWORD; begin @@ -1432,39 +1438,42 @@ function ReadFromActiveFile(Param: Pointer; Position: LongWord; Buffer: PByte; S end; {$ENDIF MSWINDOWS} -procedure TPdfDocument.LoadFromFile(const AFileName: string; const APassword: UTF8String; ALoadOption: TPdfDocumentLoadOption); +procedure TPdfDocument.LoadFromFile(const FileName: string; const Password: UTF8String; LoadOption: TPdfDocumentLoadOption); +{$IFDEF MSWINDOWS} var - {$IFDEF MSWINDOWS} Size: Int64; Offset: NativeInt; NumRead: DWORD; LastError: DWORD; - {$ELSE} - Stream: TFileStream; - {$ENDIF MSWINDOWS} +{$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; {$IFDEF MSWINDOWS} - FFileHandle := CreateFileW(PWideChar(AFileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + 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 up to 2 GB (FX_FILESIZE in core/fxcrt/fx_system.h) + 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 ALoadOption = dloOnDemand then - ALoadOption := dloMMF; + if LoadOption = dloOnDemand then + LoadOption := dloMMF; {$ELSE} raise EPdfException.CreateResFmt(@RsFileTooLarge, [ExtractFileName(AFileName)]); {$ENDIF CPUX64} end; - case ALoadOption of + case LoadOption of dloMemory: begin if Size > 0 then @@ -1493,7 +1502,7 @@ procedure TPdfDocument.LoadFromFile(const AFileName: string; const APassword: UT FFileHandle := INVALID_HANDLE_VALUE; end; - InternLoadFromMem(FBuffer, Size, APassword); + InternLoadFromMem(FBuffer, Size, Password); end; end; @@ -1506,39 +1515,51 @@ procedure TPdfDocument.LoadFromFile(const AFileName: string; const APassword: UT 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; {$ELSE} - Stream := TFileStream.Create(AFileName, fmOpenRead or fmShareDenyWrite); + FFileStream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite); try - LoadFromStream(Stream, APassword); - finally - Stream.Free; + 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 := AFileName; + FFileName := FileName; end; -procedure TPdfDocument.LoadFromStream(AStream: TStream; const APassword: UTF8String); +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; @@ -1546,32 +1567,32 @@ procedure TPdfDocument.LoadFromStream(AStream: TStream; const APassword: UTF8Str end; end; -procedure TPdfDocument.LoadFromActiveBuffer(Buffer: Pointer; Size: NativeInt; const APassword: UTF8String); +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: UTF8String); +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: NativeInt; - const APassword: UTF8String); +procedure TPdfDocument.LoadFromBytes(const Bytes: TBytes; Index, Count: NativeInt; + const Password: UTF8String); var Len: NativeInt; begin Close; - Len := Length(ABytes); - if AIndex >= Len then - raise EPdfArgumentOutOfRange.CreateResFmt(@RsArgumentsOutOfRange, ['Index', AIndex]); - if AIndex + ACount > Len then - raise EPdfArgumentOutOfRange.CreateResFmt(@RsArgumentsOutOfRange, ['Count', ACount]); + 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; @@ -1585,19 +1606,19 @@ function ReadFromActiveStream(Param: Pointer; Position: LongWord; Buffer: PByte; Result := Size = 0; end; -procedure TPdfDocument.LoadFromActiveStream(Stream: TStream; const APassword: UTF8String); +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: UTF8String); +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; @@ -1608,32 +1629,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: UTF8String); +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(Pointer(APassword))); - DocumentLoaded; + FDocument := FPDF_LoadCustomDocument(@FCustomLoadData.FileAccess, PAnsiChar(Pointer(Password))); finally UnsupportedFeatureCurrentDocument := OldCurDoc; end; + DocumentLoaded; end; end; -procedure TPdfDocument.InternLoadFromMem(Buffer: PByte; Size: NativeInt; const APassword: UTF8String); +procedure TPdfDocument.InternLoadFromMem(Buffer: PByte; Size: NativeInt; const Password: UTF8String); var OldCurDoc: TPdfDocument; begin @@ -1642,7 +1663,7 @@ procedure TPdfDocument.InternLoadFromMem(Buffer: PByte; Size: NativeInt; const A OldCurDoc := UnsupportedFeatureCurrentDocument; try UnsupportedFeatureCurrentDocument := Self; - FDocument := FPDF_LoadMemDocument64(Buffer, Size, PAnsiChar(Pointer(APassword))); + FDocument := FPDF_LoadMemDocument64(Buffer, Size, PAnsiChar(Pointer(Password))); finally UnsupportedFeatureCurrentDocument := OldCurDoc; end; @@ -1650,6 +1671,24 @@ procedure TPdfDocument.InternLoadFromMem(Buffer: PByte; Size: NativeInt; const A 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; @@ -1776,6 +1815,8 @@ class function TPdfDocument.CreateNPagesOnOnePageDocument(Source: TPdfDocument; class function TPdfDocument.CreateNPagesOnOnePageDocument(Source: TPdfDocument; NewPageWidth, NewPageHeight: Double; NumPagesXAxis, NumPagesYAxis: Integer): TPdfDocument; +var + OldCurDoc: TPdfDocument; begin Result := TPdfDocument.Create; try @@ -1783,7 +1824,13 @@ class function TPdfDocument.CreateNPagesOnOnePageDocument(Source: TPdfDocument; Result.NewDocument else begin - Result.FDocument := FPDF_ImportNPagesToOne(Source.FDocument, NewPageWidth, NewPageHeight, NumPagesXAxis, NumPagesYAxis); + 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 diff --git a/Source/PdfiumCtrl.pas b/Source/PdfiumCtrl.pas index 39fec41..c77afde 100644 --- a/Source/PdfiumCtrl.pas +++ b/Source/PdfiumCtrl.pas @@ -177,13 +177,13 @@ TPdfControl = class(TCustomControl) { InvalidatePage forces the page to be rendered again and invalidates the control. } procedure InvalidatePage; - procedure LoadFromCustom(ReadFunc: TPdfDocumentCustomReadProc; ASize: LongWord; AParam: Pointer; const APassword: UTF8String = ''); - procedure LoadFromActiveStream(Stream: TStream; const APassword: UTF8String = ''); // Stream must not be released until the document is closed - procedure LoadFromActiveBuffer(Buffer: Pointer; Size: Int64; const APassword: UTF8String = ''); // Buffer must not be released until the document is closed - procedure LoadFromBytes(const ABytes: TBytes; const APassword: UTF8String = ''); 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: UTF8String = ''); overload; // The content of the Bytes array must not be changed until the document is closed - procedure LoadFromStream(AStream: TStream; const APassword: UTF8String = ''); - procedure LoadFromFile(const AFileName: string; const APassword: UTF8String = ''; ALoadOption: 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: 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; @@ -324,7 +324,7 @@ TPdfDocumentVclPrinter = class(TPdfDocumentPrinter) implementation uses - Math, Clipbrd, Character, Printers, PdfiumLib; + Math, Clipbrd, Character, Printers; const cScrollTimerId = 1; @@ -1024,67 +1024,67 @@ procedure TPdfControl.DocumentLoaded; PageContentChanged(False); end; -procedure TPdfControl.LoadFromCustom(ReadFunc: TPdfDocumentCustomReadProc; ASize: LongWord; - AParam: Pointer; const APassword: UTF8String); +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: UTF8String); +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: Int64; const APassword: UTF8String); +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: UTF8String); +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: UTF8String); +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: UTF8String); +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: UTF8String; - ALoadOption: TPdfDocumentLoadOption); +procedure TPdfControl.LoadFromFile(const FileName: string; const Password: UTF8String; + LoadOption: TPdfDocumentLoadOption); begin try - FDocument.LoadFromFile(AFileName, APassword, ALoadOption); + FDocument.LoadFromFile(FileName, Password, LoadOption); finally DocumentLoaded; end; From 26835423d2fdf5755aa6bcbce279c2f259e49f62 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Sun, 24 Dec 2023 13:23:20 +0100 Subject: [PATCH 41/59] - Added ExecuteNamedAction handler - Added OnPrintDocument event handler - Fix: Exception after printing --- Example/MainFrm.dfm | 2 -- Example/MainFrm.pas | 13 ++++++-- Source/PdfiumCore.pas | 73 ++++++++++++++++++++++++++++++++++--------- Source/PdfiumCtrl.pas | 48 ++++++++++++++++++++++++---- 4 files changed, 111 insertions(+), 25 deletions(-) diff --git a/Example/MainFrm.dfm b/Example/MainFrm.dfm index 41e7e45..5026fbd 100644 --- a/Example/MainFrm.dfm +++ b/Example/MainFrm.dfm @@ -34,8 +34,6 @@ object frmMain: TfrmMain Align = alTop BevelOuter = bvNone TabOrder = 1 - ExplicitLeft = 8 - ExplicitTop = 144 object btnAddAnnotation: TButton Left = 318 Top = 0 diff --git a/Example/MainFrm.pas b/Example/MainFrm.pas index 91bae58..3311441 100644 --- a/Example/MainFrm.pas +++ b/Example/MainFrm.pas @@ -41,6 +41,7 @@ TfrmMain = class(TForm) FCtrl: TPdfControl; procedure WebLinkClick(Sender: TObject; Url: string); procedure AnnotationLinkClick(Sender: TObject; LinkAnnotation: TPdfAnnotation); + procedure PrintDocument(Sender: TObject); procedure ListAttachments; public { Public-Deklarationen } @@ -59,6 +60,7 @@ 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'; @@ -76,6 +78,7 @@ procedure TfrmMain.FormCreate(Sender: TObject); //FCtrl.PageColor := RGB(255, 255, 200); FCtrl.OnWebLinkClick := WebLinkClick; FCtrl.OnAnnotationLinkClick := AnnotationLinkClick; + FCtrl.OnPrintDocument := PrintDocument; edtZoom.Value := FCtrl.ZoomPercentage; @@ -128,7 +131,7 @@ procedure TfrmMain.btnNextClick(Sender: TObject); procedure TfrmMain.btnHighlightClick(Sender: TObject); begin - FCtrl.HightlightText('Delphi 2010', False, False); + FCtrl.HightlightText('the', False, False); end; procedure TfrmMain.btnScaleClick(Sender: TObject); @@ -185,6 +188,11 @@ procedure TfrmMain.AnnotationLinkClick(Sender: TObject; LinkAnnotation: TPdfAnno 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; @@ -212,7 +220,8 @@ procedure TfrmMain.btnPrintClick(Sender: TObject); {var PdfPrinter: TPdfDocumentPrinter;} begin - TPdfDocumentVclPrinter.PrintDocument(FCtrl.Document, 'PDF Example Print Job'); + FCtrl.PrintDocument; // calls OnPrintDocument->PrintDocument + //TPdfDocumentVclPrinter.PrintDocument(FCtrl.Document, 'PDF Example Print Job'); { PrintDialog1.MinPage := 1; PrintDialog1.MaxPage := FCtrl.Document.PageCount; diff --git a/Source/PdfiumCore.pas b/Source/PdfiumCore.pas index a57faea..99f5b3d 100644 --- a/Source/PdfiumCore.pas +++ b/Source/PdfiumCore.pas @@ -75,6 +75,14 @@ TPdfRect = record 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. @@ -558,6 +566,7 @@ TPdfPage = class(TObject) TPdfFormOutputSelectedRectEvent = procedure(Document: TPdfDocument; Page: TPdfPage; const PageRect: TPdfRect) 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 @@ -650,10 +659,12 @@ TCustomLoadDataRec = record FFormFieldHighlightAlpha: Integer; FPrintHidesFormFieldHighlight: Boolean; FFormModified: Boolean; + FOnFormInvalidate: TPdfFormInvalidateEvent; FOnFormOutputSelectedRect: TPdfFormOutputSelectedRectEvent; FOnFormGetCurrentPage: TPdfFormGetCurrentPageEvent; FOnFormFieldFocus: TPdfFormFieldFocusEvent; + FOnExecuteNamedAction: TPdfExecuteNamedActionEvent; procedure InternLoadFromFile(const FileName: string; const Password: UTF8String); procedure InternLoadFromMem(Buffer: PByte; Size: NativeInt; const Password: UTF8String); @@ -744,6 +755,7 @@ TCustomLoadDataRec = record property OnFormOutputSelectedRect: TPdfFormOutputSelectedRectEvent read FOnFormOutputSelectedRect write FOnFormOutputSelectedRect; property OnFormGetCurrentPage: TPdfFormGetCurrentPageEvent read FOnFormGetCurrentPage write FOnFormGetCurrentPage; property OnFormFieldFocus: TPdfFormFieldFocusEvent read FOnFormFieldFocus write FOnFormFieldFocus; + property OnExecuteNamedAction: TPdfExecuteNamedActionEvent read FOnExecuteNamedAction write FOnExecuteNamedAction; end; TPdfDocumentPrinterStatusEvent = procedure(Sender: TObject; CurrentPageNum, PageCount: Integer) of object; @@ -1157,21 +1169,21 @@ function FFI_SetTimer(pThis: PFPDF_FORMFILLINFO; uElapse: Integer; lpTimerFunc: Timer: TFFITimer; begin // Find highest Id - 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; 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 @@ -1256,10 +1268,38 @@ 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 use check what form field type is under the mouse cursor in the - // MoveMove event. Chrome/Edge don't rely on SetCursor either. + // 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; @@ -1709,9 +1749,12 @@ 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 diff --git a/Source/PdfiumCtrl.pas b/Source/PdfiumCtrl.pas index c77afde..be51e25 100644 --- a/Source/PdfiumCtrl.pas +++ b/Source/PdfiumCtrl.pas @@ -83,10 +83,6 @@ TPdfControl = class(TCustomControl) FHighlightText: string; FHighlightMatchCase: Boolean; FHighlightMatchWholeWord: Boolean; - FOnWebLinkClick: TPdfControlWebLinkClickEvent; - FOnAnnotationLinkClick: TPdfControlAnnotationLinkClickEvent; - FOnPageChange: TNotifyEvent; - FOnPaint: TNotifyEvent; FFormOutputSelectedRects: TPdfRectArray; FFormFieldFocused: Boolean; FPageShadowSize: Integer; @@ -94,6 +90,12 @@ TPdfControl = class(TCustomControl) FPageShadowPadding: Integer; FPageBorderColor: TColor; + FOnWebLinkClick: TPdfControlWebLinkClickEvent; + FOnAnnotationLinkClick: TPdfControlAnnotationLinkClickEvent; + FOnPageChange: TNotifyEvent; + FOnPaint: TNotifyEvent; + FOnPrintDocument: TNotifyEvent; + procedure WMTimer(var Message: TWMTimer); message WM_TIMER; procedure WMVScroll(var Message: TWMVScroll); message WM_VSCROLL; procedure WMHScroll(var Message: TWMHScroll); message WM_HSCROLL; @@ -141,6 +143,8 @@ TPdfControl = class(TCustomControl) procedure FormOutputSelectedRect(Document: TPdfDocument; Page: TPdfPage; const PageRect: TPdfRect); procedure FormGetCurrentPage(Document: TPdfDocument; var Page: TPdfPage); procedure FormFieldFocus(Document: TPdfDocument; Value: PWideChar; ValueLen: Integer; FieldFocused: Boolean); + procedure ExecuteNamedAction(Document: TPdfDocument; NamedAction: TPdfNamedActionType); + procedure DrawAlphaSelection(DC: HDC; Page: TPdfPage; const ARects: TPdfRectArray); procedure DrawFormOutputSelectedRects(DC: HDC; Page: TPdfPage); protected @@ -176,6 +180,8 @@ TPdfControl = class(TCustomControl) { 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 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 @@ -255,6 +261,8 @@ TPdfControl = class(TCustomControl) 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; @@ -370,7 +378,7 @@ function TPdfDocumentVclPrinter.PrinterStartDoc(const AJobTitle: string): Boolea FBeginDocCalled := Printer.Printing; Result := FBeginDocCalled; end; - if Result then + 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. @@ -382,10 +390,10 @@ procedure TPdfDocumentVclPrinter.PrinterEndDoc; begin if Printer.Printing then begin + SetAbortProc(GetPrinterDC, @VclAbortProc); // restore default behavior if FBeginDocCalled then Printer.EndDoc; end; - SetAbortProc(GetPrinterDC, @VclAbortProc); // restore default behavior end; procedure TPdfDocumentVclPrinter.PrinterStartPage; @@ -500,6 +508,7 @@ constructor TPdfControl.Create(AOwner: TComponent); FDocument.OnFormOutputSelectedRect := FormOutputSelectedRect; FDocument.OnFormGetCurrentPage := FormGetCurrentPage; FDocument.OnFormFieldFocus := FormFieldFocus; + FDocument.OnExecuteNamedAction := ExecuteNamedAction; ParentDoubleBuffered := False; ParentBackground := False; @@ -908,6 +917,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 @@ -2533,5 +2553,21 @@ procedure TPdfControl.FormFieldFocus(Document: TPdfDocument; Value: PWideChar; 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. From ce6bf29edf0a744b8e592cbf103de38e6879ece8 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Sun, 24 Dec 2023 16:52:55 +0100 Subject: [PATCH 42/59] - Refactored Annotation Link and WebLink code - Added LinkOptions and automatic Annotation Link handling (default disabled except for "Goto") --- Example/MainFrm.pas | 48 ++---- Source/PdfiumCore.pas | 357 +++++++++++++++++++++++++----------------- Source/PdfiumCtrl.pas | 290 ++++++++++++++++++++++++++++++---- 3 files changed, 485 insertions(+), 210 deletions(-) diff --git a/Example/MainFrm.pas b/Example/MainFrm.pas index 3311441..55f41bc 100644 --- a/Example/MainFrm.pas +++ b/Example/MainFrm.pas @@ -40,7 +40,7 @@ TfrmMain = class(TForm) { Private-Deklarationen } FCtrl: TPdfControl; procedure WebLinkClick(Sender: TObject; Url: string); - procedure AnnotationLinkClick(Sender: TObject; LinkAnnotation: TPdfAnnotation); + procedure AnnotationLinkClick(Sender: TObject; LinkInfo: TPdfLinkInfo; var Handled: Boolean); procedure PrintDocument(Sender: TObject); procedure ListAttachments; public @@ -76,8 +76,9 @@ procedure TfrmMain.FormCreate(Sender: TObject); //FCtrl.PageShadowColor := clDkGray; FCtrl.ScaleMode := smFitWidth; //FCtrl.PageColor := RGB(255, 255, 200); - FCtrl.OnWebLinkClick := WebLinkClick; + FCtrl.OnWebLinkClick := WebLinkClick; // disabled due to loTreatWebLinkAsUriAnnotationLink + loAutoOpenURI FCtrl.OnAnnotationLinkClick := AnnotationLinkClick; + FCtrl.LinkOptions := FCtrl.LinkOptions - [loAutoOpenURI] {+ cPdfControlAllAutoLinkOptions}; FCtrl.OnPrintDocument := PrintDocument; edtZoom.Value := FCtrl.ZoomPercentage; @@ -148,43 +149,20 @@ procedure TfrmMain.WebLinkClick(Sender: TObject; Url: string); ShowMessage(Url); end; -procedure TfrmMain.AnnotationLinkClick(Sender: TObject; LinkAnnotation: TPdfAnnotation); -var - Dest: TPdfLinkGotoDestination; - X, Y{, Zoom}: Double; - Pt: TPoint; +procedure TfrmMain.AnnotationLinkClick(Sender: TObject; LinkInfo: TPdfLinkInfo; var Handled: Boolean); begin - case LinkAnnotation.LinkType of - altGoto: - begin - Dest := LinkAnnotation.GetLinkGotoDestination(); - FCtrl.PageIndex := Dest.PageIndex; - X := 0; - Y := 0; - //Zoom := 0; - if Dest.XValid then - X := Dest.X; - if Dest.YValid then - Y := Dest.Y; - {if Dest.ZoomValid then - Zoom := Dest.Zoom; - FCtrl.ZoomPercentage := Int(Zoom);} - - Pt := FCtrl.PageToDevice(X, Y); - FCtrl.ScrollContentTo(Pt.X, Pt.Y); - end; + Handled := True; + case LinkInfo.LinkType of + //altURI: + // ShowMessage('URL: ' + LinkAnnotation.LinkUri); - altRemoteGoto: - ShowMessage('Remote Goto: ' + LinkAnnotation.LinkFileName); - - altURI: - ShowMessage('URL: ' + LinkAnnotation.LinkUri); - - altLaunch: - ShowMessage('Launch: ' + LinkAnnotation.LinkFileName); + //altLaunch: + // ShowMessage('Launch: ' + LinkAnnotation.LinkFileName); altEmbeddedGoto: - ShowMessage('EmbeddedGoto: ' + LinkAnnotation.LinkUri); + ShowMessage('EmbeddedGoto: ' + LinkInfo.LinkUri); + else + Handled := False; end; end; diff --git a/Source/PdfiumCore.pas b/Source/PdfiumCore.pas index 99f5b3d..c160251 100644 --- a/Source/PdfiumCore.pas +++ b/Source/PdfiumCore.pas @@ -359,7 +359,6 @@ TPdfAnnotation = class(TObject) FSubType: FPDF_ANNOTATION_SUBTYPE; FLinkDest: FPDF_DEST; FLinkType: TPdfAnnotationLinkType; - FLinkGotoDest: TPdfLinkGotoDestination; function GetPdfLinkAction: FPDF_ACTION; function GetFormField: TPdfFormField; @@ -374,13 +373,14 @@ TPdfAnnotation = class(TObject) 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; - function GetLinkGotoDestination(ARemoteDocument: TPdfDocument = nil): TPdfLinkGotoDestination; property AnnotationRect: TPdfRect read GetAnnotationRect; property Handle: FPDF_ANNOTATION read FHandle; @@ -417,9 +417,30 @@ TPdfAnnotationList = class(TObject) property FormFields: TPdfFormFieldList read GetFormFields; end; - { TPdfPageWebLinkInfo caches all the WebLinks for one page. This makes the IsWebLinkAt() methods + 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. } - TPdfPageWebLinkInfo = class(TObject) + TPdfPageWebLinksInfo = class(TObject) private FPage: TPdfPage; FWebLinksRects: array of TPdfRectArray; @@ -3656,83 +3677,6 @@ function TPdfAnnotationList.FindLink(Link: FPDF_LINK): TPdfAnnotation; end; -{ TPdfPageWebLinkInfo } - -constructor TPdfPageWebLinkInfo.Create(APage: TPdfPage); -begin - inherited Create; - FPage := APage; - GetPageWebLinks; -end; - -procedure TPdfPageWebLinkInfo.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 TPdfPageWebLinkInfo.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 TPdfPageWebLinkInfo.GetCount: Integer; -begin - Result := Length(FWebLinksRects); -end; - -function TPdfPageWebLinkInfo.GetRect(Index: Integer): TPdfRectArray; -begin - Result := FWebLinksRects[Index]; -end; - -function TPdfPageWebLinkInfo.GetURL(Index: Integer): string; -begin - Result := FPage.GetWebLinkURL(Index); -end; - -function TPdfPageWebLinkInfo.IsWebLinkAt(X, Y: Double): Boolean; -begin - Result := GetWebLinkIndex(X, Y) <> -1; -end; - -function TPdfPageWebLinkInfo.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; - { TPdfFormFieldList } constructor TPdfFormFieldList.Create(AAnnotations: TPdfAnnotationList); @@ -3770,27 +3714,6 @@ procedure TPdfFormFieldList.DestroyingItem(Item: TPdfFormField); 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; - - { TPdfAnnotation } constructor TPdfAnnotation.Create(APage: TPdfPage; AHandle: FPDF_ANNOTATION); @@ -3826,7 +3749,6 @@ constructor TPdfAnnotation.Create(APage: TPdfPage; AHandle: FPDF_ANNOTATION); destructor TPdfAnnotation.Destroy; begin - FreeAndNil(FLinkGotoDest); FreeAndNil(FFormField); if FHandle <> nil then begin @@ -3888,13 +3810,13 @@ function TPdfAnnotation.GetLinkUri: string; function TPdfAnnotation.GetLinkFileName: string; begin - if LinkType in [altRemoteGoto, altLaunch, altEmbeddedGoto] then + 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(ARemoteDocument: TPdfDocument = nil): TPdfLinkGotoDestination; +function TPdfAnnotation.GetLinkGotoDestination(var LinkGotoDestination: TPdfLinkGotoDestination; ARemoteDocument: TPdfDocument): Boolean; var Action: FPDF_ACTION; Dest: FPDF_DEST; @@ -3906,55 +3828,54 @@ function TPdfAnnotation.GetLinkGotoDestination(ARemoteDocument: TPdfDocument = n NumViewParams: LongWord; ViewParams: TPdfFloatArray; begin - if FLinkGotoDest = nil then + Result := False; + + Action := GetPdfLinkAction; + if ((Action <> nil) or (FLinkDest <> nil)) and (LinkType in [altGoto, altRemoteGoto, altEmbeddedGoto]) then begin - Action := GetPdfLinkAction; - if ((Action <> nil) or (FLinkDest <> nil)) and (LinkType in [altGoto, altRemoteGoto, altEmbeddedGoto]) then + Doc := FPage.FDocument; + if LinkType = altRemoteGoto 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; + // 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; + 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); + // 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 + // Extract the information + if Dest <> nil then + begin + PageIndex := FPDFDest_GetDestPageIndex(Doc.Handle, Dest); + if PageIndex <> -1 then begin - PageIndex := FPDFDest_GetDestPageIndex(Doc.Handle, Dest); - if PageIndex <> -1 then + if FPDFDest_GetLocationInPage(Dest, HasXVal, HasYVal, HasZoomVal, X, Y, Zoom) <> 0 then begin - if FPDFDest_GetLocationInPage(Dest, HasXVal, HasYVal, HasZoomVal, X, Y, Zoom) <> 0 then - begin - SetLength(ViewParams, 4); // max. 4 params + SetLength(ViewParams, 4); // max. 4 params + NumViewParams := 4; + ViewKind := TPdfLinkGotoDestinationViewKind(FPDFDest_GetView(Dest, @NumViewParams, @ViewParams[0])); + if NumViewParams > 4 then // range check NumViewParams := 4; - ViewKind := TPdfLinkGotoDestinationViewKind(FPDFDest_GetView(Dest, @NumViewParams, @ViewParams[0])); - if NumViewParams > 4 then // range check - NumViewParams := 4; - SetLength(ViewParams, NumViewParams); - - FLinkGotoDest := TPdfLinkGotoDestination.Create( - PageIndex, - HasXVal <> 0, HasYVal <> 0, HasZoomVal <> 0, - X, Y, Zoom, - ViewKind, ViewParams - ); - end; + SetLength(ViewParams, NumViewParams); + + LinkGotoDestination := TPdfLinkGotoDestination.Create( + PageIndex, + HasXVal <> 0, HasYVal <> 0, HasZoomVal <> 0, + X, Y, Zoom, + ViewKind, ViewParams + ); + Result := True; end; end; end; end; - Result := FLinkGotoDest; end; { TPdfFormField } @@ -4215,6 +4136,158 @@ procedure TPdfFormField.SetChecked(const Value: Boolean); end; 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; + + { TPdfDocumentPrinter } constructor TPdfDocumentPrinter.Create; diff --git a/Source/PdfiumCtrl.pas b/Source/PdfiumCtrl.pas index be51e25..32af25f 100644 --- a/Source/PdfiumCtrl.pas +++ b/Source/PdfiumCtrl.pas @@ -27,10 +27,27 @@ interface {$IFDEF FPC} LCLType, PrintersDlgs, Win32Extra, {$ENDIF FPC} - Windows, Messages, Types, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, PdfiumCore; + Windows, Messages, ShellAPI, Types, SysUtils, Classes, 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 = [proAnnotations]; + cPdfControlDefaultLinkOptions = [loAutoGoto, loTreatWebLinkAsUriAnnotationLink, loAlwaysDetectWebAndUriLink]; + cPdfControlAllAutoLinkOptions = [loAutoGoto, loAutoRemoteGotoReplaceDocument, loAutoOpenURI, + loAutoLaunch, loAutoEmbeddedGotoReplaceDocument]; type TPdfControlScaleMode = ( @@ -41,7 +58,7 @@ interface ); TPdfControlWebLinkClickEvent = procedure(Sender: TObject; Url: string) of object; - TPdfControlAnnotationLinkClickEvent = procedure(Sender: TObject; Link: TPdfAnnotation) of object; + TPdfControlAnnotationLinkClickEvent = procedure(Sender: TObject; LinkInfo: TPdfLinkInfo; var Handled: Boolean) of object; TPdfControlRectArray = array of TRect; TPdfControlPdfRectArray = array of TPdfRect; @@ -73,12 +90,13 @@ TPdfControl = class(TCustomControl) FSelStopCharIndex: Integer; FMouseDownPt: TPoint; FCheckForTrippleClick: Boolean; - FWebLinkInfo: TPdfPageWebLinkInfo; + FWebLinkInfo: TPdfPageWebLinksInfo; FDrawOptions: TPdfPageRenderOptions; FScaleMode: TPdfControlScaleMode; FZoomPercentage: Integer; FPageColor: TColor; FScrollMousePos: TPoint; + FLinkOptions: TPdfControlLinkOptions; FHighlightTextRects: TPdfControlPdfRectArray; FHighlightText: string; FHighlightMatchCase: Boolean; @@ -138,6 +156,8 @@ TPdfControl = class(TCustomControl) 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); @@ -160,9 +180,10 @@ TPdfControl = class(TCustomControl) procedure WMChar(var Message: TWMChar); message WM_CHAR; procedure WMKillFocus(var Message: TWMKillFocus); message WM_KILLFOCUS; + function LinkHandlingNeeded: Boolean; function IsClickableLinkAt(X, Y: Integer): Boolean; procedure WebLinkClick(const Url: string); virtual; - procedure AnnotationLinkClick(LinkAnnotation: TPdfAnnotation); virtual; + procedure AnnotationLinkClick(LinkInfo: TPdfLinkInfo); virtual; procedure PageChange; virtual; procedure PageContentChanged(Closing: Boolean); procedure PageLayoutChanged; @@ -183,6 +204,7 @@ TPdfControl = class(TCustomControl) { 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 @@ -224,6 +246,7 @@ TPdfControl = class(TCustomControl) 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; @@ -248,6 +271,7 @@ TPdfControl = class(TCustomControl) 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; @@ -332,7 +356,7 @@ TPdfDocumentVclPrinter = class(TPdfDocumentPrinter) implementation uses - Math, Clipbrd, Character, Printers; + Math, Clipbrd, Character, Printers, StrUtils; const cScrollTimerId = 1; @@ -497,6 +521,7 @@ constructor TPdfControl.Create(AOwner: TComponent); FDrawOptions := cPdfControlDefaultDrawOptions; FScrollTimer := True; FBufferedPageDraw := True; + FLinkOptions := cPdfControlDefaultLinkOptions; FPageBorderColor := clNone; FPageShadowColor := clNone; @@ -504,11 +529,7 @@ constructor TPdfControl.Create(AOwner: TComponent); FPageShadowPadding := 44; FDocument := TPdfDocument.Create; - FDocument.OnFormInvalidate := FormInvalidate; - FDocument.OnFormOutputSelectedRect := FormOutputSelectedRect; - FDocument.OnFormGetCurrentPage := FormGetCurrentPage; - FDocument.OnFormFieldFocus := FormFieldFocus; - FDocument.OnExecuteNamedAction := ExecuteNamedAction; + InitDocument; ParentDoubleBuffered := False; ParentBackground := False; @@ -527,6 +548,15 @@ destructor TPdfControl.Destroy; 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; @@ -1044,6 +1074,17 @@ procedure TPdfControl.DocumentLoaded; PageContentChanged(False); end; +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 @@ -1374,6 +1415,7 @@ procedure TPdfControl.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: In Url: string; Page: TPdfPage; LinkAnnotation: TPdfAnnotation; + LinkInfo: TPdfLinkInfo; begin inherited MouseUp(Button, Shift, X, Y); @@ -1404,19 +1446,27 @@ procedure TPdfControl.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: In SetSelStopCharIndex(X, Y); if not FSelectionActive then begin - if Assigned(FOnAnnotationLinkClick) or Assigned(FOnWebLinkClick) then + 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 Assigned(FonAnnotationLinkClick) then - AnnotationLinkClick(LinkAnnotation) - else if LinkAnnotation.LinkType = altURI then - WebLinkClick(LinkAnnotation.LinkUri); - end - // If we have a Link Annotation and a WebLink, then the link annotation is prefered - else if Assigned(FOnWebLinkClick) and IsWebLinkAt(X, Y, Url) then - WebLinkClick(Url); + 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; @@ -1511,7 +1561,7 @@ procedure TPdfControl.CMMouseleave(var Message: TMessage); begin if (Cursor = crIBeam) or (Cursor = crHandPoint) then begin - if AllowUserTextSelection or Assigned(FOnWebLinkClick) or Assigned(FOnAnnotationLinkClick) then + if AllowUserTextSelection or Assigned(FOnWebLinkClick) or Assigned(FOnAnnotationLinkClick) or (LinkOptions <> []) then Cursor := crDefault; end; inherited; @@ -1992,21 +2042,60 @@ procedure TPdfControl.GetPageWebLinks; FreeAndNil(FWebLinkInfo); Page := CurrentPage; if Page <> nil then - FWebLinkInfo := TPdfPageWebLinkInfo.Create(Page); + 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 + // 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 - if Assigned(FOnWebLinkClick) and IsWebLinkAt(X, Y) then - Result := True - else if Assigned(FOnAnnotationLinkClick) and IsAnnotationLinkAt(X, Y) then - Result := True - // Fallback in case OnAnnotationLinkClick is not assigend but OnWebLinkClick is, then we use - // WebLinkClick for the URI-Action Links. - else if not Assigned(FOnAnnotationLinkClick) and Assigned(FOnWebLinkClick) and IsUriAnnotationLinkAt(X, Y) then - Result := True - else - Result := False; + Result := False; + if LinkHandlingNeeded then + begin + LinkAnnotation := GetAnnotationLinkAt(X, Y); + if LinkAnnotation <> nil then + begin + 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; @@ -2067,16 +2156,151 @@ function TPdfControl.GetAnnotationLinkAt(X, Y: Integer): TPdfAnnotation; Result := nil; end; +function TPdfControl.ShellOpenFileName(const FileName: string; Launch: Boolean): Boolean; +var + Info: TShellExecuteInfo; +begin + FillChar(Info, SizeOf(Info), 0); + Info.cbSize := SizeOf(Info); + if HandleAllocated then + Info.Wnd := Handle; + if Launch then + Info.lpVerb := nil + else + Info.lpVerb := 'open'; + Info.lpFile := PChar(FileName); + Info.lpDirectory := PChar(ExtractFileDir(Document.FileName)); + Info.nShow := SW_NORMAL; + Result := ShellExecuteEx(@Info); +end; + procedure TPdfControl.WebLinkClick(const Url: string); begin if Assigned(FOnWebLinkClick) then FOnWebLinkClick(Self, Url); end; -procedure TPdfControl.AnnotationLinkClick(LinkAnnotation: TPdfAnnotation); +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, LinkAnnotation); + 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; From e015854570831bdf862c37c0cfee1559afa523a7 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Sun, 24 Dec 2023 16:55:27 +0100 Subject: [PATCH 43/59] Fix Win32 compilation --- Source/PdfiumCore.pas | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/PdfiumCore.pas b/Source/PdfiumCore.pas index c160251..0bfd8dc 100644 --- a/Source/PdfiumCore.pas +++ b/Source/PdfiumCore.pas @@ -1530,7 +1530,7 @@ procedure TPdfDocument.LoadFromFile(const FileName: string; const Password: UTF8 if LoadOption = dloOnDemand then LoadOption := dloMMF; {$ELSE} - raise EPdfException.CreateResFmt(@RsFileTooLarge, [ExtractFileName(AFileName)]); + raise EPdfException.CreateResFmt(@RsFileTooLarge, [ExtractFileName(FileName)]); {$ENDIF CPUX64} end; From 00385a3e1a5938b6d1b6fe23e5b448309b6e0bf8 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Mon, 25 Dec 2023 11:45:51 +0100 Subject: [PATCH 44/59] Fixed #38 --- Source/PdfiumCore.pas | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/PdfiumCore.pas b/Source/PdfiumCore.pas index 0bfd8dc..6608571 100644 --- a/Source/PdfiumCore.pas +++ b/Source/PdfiumCore.pas @@ -3729,7 +3729,7 @@ constructor TPdfAnnotation.Create(APage: TPdfPage; AHandle: FPDF_ANNOTATION); case FSubType of FPDF_ANNOT_WIDGET, FPDF_ANNOT_XFAWIDGET: - FFormField := TPdfFormField.Create(FHandle); + FFormField := TPdfFormField.Create(Self); FPDF_ANNOT_LINK: begin From 84a64df810646565d0967cfdea870b0e5b0fe8b6 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Mon, 1 Jan 2024 13:20:13 +0100 Subject: [PATCH 45/59] FPC (Windows) compatibility --- Source/PdfiumCore.pas | 7 +++-- Source/PdfiumCtrl.pas | 66 +++++++++++++++---------------------------- 2 files changed, 28 insertions(+), 45 deletions(-) diff --git a/Source/PdfiumCore.pas b/Source/PdfiumCore.pas index 6608571..2f320b1 100644 --- a/Source/PdfiumCore.pas +++ b/Source/PdfiumCore.pas @@ -1073,11 +1073,14 @@ procedure FFI_OutputSelectedRect(pThis: PFPDF_FORMFILLINFO; page: FPDF_PAGE; lef end; {$IFDEF MSWINDOWS} -var - FFITimers: array of record +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; diff --git a/Source/PdfiumCtrl.pas b/Source/PdfiumCtrl.pas index 32af25f..bb4557f 100644 --- a/Source/PdfiumCtrl.pas +++ b/Source/PdfiumCtrl.pas @@ -60,7 +60,6 @@ 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 @@ -97,7 +96,7 @@ TPdfControl = class(TCustomControl) FPageColor: TColor; FScrollMousePos: TPoint; FLinkOptions: TPdfControlLinkOptions; - FHighlightTextRects: TPdfControlPdfRectArray; + FHighlightTextRects: TPdfRectArray; FHighlightText: string; FHighlightMatchCase: Boolean; FHighlightMatchWholeWord: Boolean; @@ -146,7 +145,7 @@ TPdfControl = class(TCustomControl) 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); @@ -165,7 +164,8 @@ TPdfControl = class(TCustomControl) procedure FormFieldFocus(Document: TPdfDocument; Value: PWideChar; ValueLen: Integer; FieldFocused: Boolean); procedure ExecuteNamedAction(Document: TPdfDocument; NamedAction: TPdfNamedActionType); - procedure DrawAlphaSelection(DC: HDC; Page: TPdfPage; const ARects: TPdfRectArray); + 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; @@ -356,7 +356,7 @@ TPdfDocumentVclPrinter = class(TPdfDocumentPrinter) implementation uses - Math, Clipbrd, Character, Printers, StrUtils; + Math, Clipbrd, Character, Printers; const cScrollTimerId = 1; @@ -586,7 +586,12 @@ procedure TPdfControl.WMEraseBkgnd(var Message: TWMEraseBkgnd); 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; @@ -595,13 +600,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; @@ -609,7 +618,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]); 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, @@ -643,37 +652,8 @@ procedure TPdfControl.DrawFormOutputSelectedRects(DC: HDC; Page: TPdfPage); end; procedure TPdfControl.DrawHighlightText(DC: HDC; Page: TPdfPage); -var - I: Integer; - R: TRect; - BmpDC: HDC; - SelBmp: TBitmap; - BlendFunc: TBlendFunction; begin - if FHighlightTextRects <> nil 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; - - 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; - end; + DrawAlphaRects(DC, Page, FHighlightTextRects, RGB(254, 142, 50)); end; procedure TPdfControl.DrawBorderAndShadow(DC: HDC); @@ -1694,7 +1674,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; @@ -2158,7 +2138,7 @@ function TPdfControl.GetAnnotationLinkAt(X, Y: Integer): TPdfAnnotation; function TPdfControl.ShellOpenFileName(const FileName: string; Launch: Boolean): Boolean; var - Info: TShellExecuteInfo; + Info: TShellExecuteInfoW; begin FillChar(Info, SizeOf(Info), 0); Info.cbSize := SizeOf(Info); @@ -2171,7 +2151,7 @@ function TPdfControl.ShellOpenFileName(const FileName: string; Launch: Boolean): Info.lpFile := PChar(FileName); Info.lpDirectory := PChar(ExtractFileDir(Document.FileName)); Info.nShow := SW_NORMAL; - Result := ShellExecuteEx(@Info); + Result := ShellExecuteExW(@Info); end; procedure TPdfControl.WebLinkClick(const Url: string); @@ -2697,7 +2677,7 @@ procedure TPdfControl.HightlightText(const SearchText: string; MatchCase, MatchW procedure TPdfControl.CalcHighlightTextRects; var - OldHighlightTextRects: TPdfControlPdfRectArray; + OldHighlightTextRects: TPdfRectArray; Page: TPdfPage; CharIndex, CharCount, I, Count: Integer; Num: Integer; From 669505d4baa6b4ddbc6e25d9527a21859c11733d Mon Sep 17 00:00:00 2001 From: DomenicoMammola Date: Mon, 15 Jan 2024 09:16:41 +0100 Subject: [PATCH 46/59] solved memory leak --- Source/PdfiumCtrl.pas | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/PdfiumCtrl.pas b/Source/PdfiumCtrl.pas index 32af25f..69b62f1 100644 --- a/Source/PdfiumCtrl.pas +++ b/Source/PdfiumCtrl.pas @@ -544,6 +544,7 @@ destructor TPdfControl.Destroy; begin if FPageBitmap <> 0 then DeleteObject(FPageBitmap); + FreeAndNil(FWebLinkInfo); FDocument.Free; inherited Destroy; end; From 7f7a1b84568feb697a180cb054016d89b593a397 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Mon, 15 Jan 2024 21:18:14 +0100 Subject: [PATCH 47/59] Update README.md --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 24ce23c..a29a823 100644 --- a/README.md +++ b/README.md @@ -15,14 +15,15 @@ chromium/6043 - 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 - 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) From af2e142cf256d3297baa837f5e1ecd95b2f0cfb6 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Sat, 10 Feb 2024 14:14:31 +0100 Subject: [PATCH 48/59] =?UTF-8?q?Fixed=20#40:=20Text=20selection=20with=20?= =?UTF-8?q?90=C2=B0=20clockwise=20and=20180=C2=B0=20rotation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Source/PdfiumCtrl.pas | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/Source/PdfiumCtrl.pas b/Source/PdfiumCtrl.pas index 1f2032b..a6978ea 100644 --- a/Source/PdfiumCtrl.pas +++ b/Source/PdfiumCtrl.pas @@ -151,7 +151,7 @@ TPdfControl = class(TCustomControl) procedure DrawSelection(DC: HDC; Page: TPdfPage); procedure DrawHighlightText(DC: HDC; Page: TPdfPage); procedure DrawBorderAndShadow(DC: HDC); - function InternPageToDevice(Page: TPdfPage; PageRect: TPdfRect): TRect; + function InternPageToDevice(Page: TPdfPage; PageRect: TPdfRect; ANormalize: Boolean): TRect; procedure SetZoomPercentage(Value: Integer); procedure DrawPage(DC: HDC; Page: TPdfPage; DirectDrawPage: Boolean); procedure CalcHighlightTextRects; @@ -619,7 +619,7 @@ procedure TPdfControl.DrawAlphaRects(DC: HDC; Page: TPdfPage; const Rects: TPdfR BmpDC := SelBmp.Canvas.Handle; for I := 0 to Count - 1 do begin - R := InternPageToDevice(Page, Rects[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, @@ -1290,9 +1290,26 @@ function TPdfControl.PageToDevice(PageRect: TPdfRect): TRect; 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; @@ -1640,7 +1657,7 @@ function TPdfControl.GetSelectionRects: TPdfControlRectArray; 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; @@ -1686,11 +1703,11 @@ procedure TPdfControl.InvalidatePdfRectDiffs(const OldRects, NewRects: TPdfRectA 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; @@ -2731,7 +2748,7 @@ procedure TPdfControl.FormInvalidate(Document: TPdfDocument; Page: TPdfPage; FFormOutputSelectedRects := nil; if HandleAllocated then begin - R := InternPageToDevice(Page, PageRect); + R := InternPageToDevice(Page, PageRect, True); InvalidateRect(Handle, @R, True); end; end; From b9487a55bdc0076767bd0802821cc108b118bb6a Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Sat, 3 Aug 2024 21:44:55 +0200 Subject: [PATCH 49/59] Updated to chromium/6611 --- README.md | 4 +- Source/PdfiumCore.pas | 15 +- Source/PdfiumCtrl.pas | 2 + Source/PdfiumLib.pas | 4081 ++++++++++++++++++++--------------------- 4 files changed, 2032 insertions(+), 2070 deletions(-) diff --git a/README.md b/README.md index a29a823..d537a65 100644 --- a/README.md +++ b/README.md @@ -4,10 +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/6043](https://github.com/bblanchon/pdfium-binaries/releases/tag/chromium%2F6043) +Binary release: [chromium/6611](https://github.com/bblanchon/pdfium-binaries/releases/tag/chromium%2F6611) ## Required pdfium.dll version -chromium/6043 +chromium/6611 ## Features - Multiple PDF load functions: diff --git a/Source/PdfiumCore.pas b/Source/PdfiumCore.pas index 2f320b1..89561cd 100644 --- a/Source/PdfiumCore.pas +++ b/Source/PdfiumCore.pas @@ -218,9 +218,11 @@ TPdfRect = record 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) @@ -1399,6 +1401,7 @@ function TPdfRect.PtIn(const Pt: TPdfPoint): Boolean; end; end; + { TPdfDocument } constructor TPdfDocument.Create; @@ -2225,6 +2228,7 @@ function TPdfDocument.FindPage(Page: FPDF_PAGE): TPdfPage; Result := nil; end; + { TPdfPage } constructor TPdfPage.Create(ADocument: TPdfDocument; APage: FPDF_PAGE); @@ -3121,13 +3125,15 @@ function TPdfPage.GetFormFields: TPdfFormFieldList; Result := Annotations.FormFields; end; + { _TPdfBitmapHideCtor } -procedure _TPdfBitmapHideCtor.Create; +constructor _TPdfBitmapHideCtor.Create; begin inherited Create; end; + { TPdfBitmap } constructor TPdfBitmap.Create(ABitmap: FPDF_BITMAP; AOwnsBitmap: Boolean); @@ -3194,6 +3200,7 @@ class function TPdfPoint.Empty: TPdfPoint; Result.Y := 0; end; + { TPdfAttachmentList } constructor TPdfAttachmentList.Create(ADocument: TPdfDocument); @@ -3244,6 +3251,7 @@ function TPdfAttachmentList.IndexOf(const Name: string): Integer; Result := -1; end; + { TPdfAttachment } function TPdfAttachment.GetName: string; @@ -3559,6 +3567,7 @@ function TPdfAttachment.GetContentAsString(Encoding: TEncoding): string; GetContent(Result, Encoding); end; + { TPdfAnnotationList } constructor TPdfAnnotationList.Create(APage: TPdfPage); @@ -3881,6 +3890,7 @@ function TPdfAnnotation.GetLinkGotoDestination(var LinkGotoDestination: TPdfLink end; end; + { TPdfFormField } constructor TPdfFormField.Create(AAnnotation: TPdfAnnotation); @@ -4213,6 +4223,7 @@ function TPdfLinkInfo.GetLinkGotoDestination(var LinkGotoDestination: TPdfLinkGo Result := False; end; + { TPdfPageWebLinksInfo } constructor TPdfPageWebLinksInfo.Create(APage: TPdfPage); diff --git a/Source/PdfiumCtrl.pas b/Source/PdfiumCtrl.pas index a6978ea..813fe79 100644 --- a/Source/PdfiumCtrl.pas +++ b/Source/PdfiumCtrl.pas @@ -388,6 +388,7 @@ function FastVclAbortProc(Prn: HDC; Error: Integer): Bool; stdcall; Result := not Printer.Aborted; end; + { TPdfDocumentVclPrinter } function TPdfDocumentVclPrinter.PrinterStartDoc(const AJobTitle: string): Boolean; @@ -504,6 +505,7 @@ class function TPdfDocumentVclPrinter.PrintDocument(ADocument: TPdfDocument; end; end; + { TPdfControl } constructor TPdfControl.Create(AOwner: TComponent); diff --git a/Source/PdfiumLib.pas b/Source/PdfiumLib.pas index 121dc71..c31ee4d 100644 --- a/Source/PdfiumLib.pas +++ b/Source/PdfiumLib.pas @@ -1,6 +1,6 @@ // Use DLLs (x64, x86) from https://github.com/bblanchon/pdfium-binaries // -// DLL Version: chromium/6043 +// DLL Version: chromium/6611 unit PdfiumLib; {$IFDEF FPC} @@ -15,7 +15,7 @@ {.$DEFINE DLLEXPORT} // stdcall in WIN32 instead of CDECL in WIN32 (The library switches between those from release to release) -{$DEFINE _SKIA_SUPPORT_} +{$DEFINE PDF_USE_SKIA} {$DEFINE PDF_ENABLE_XFA} {$DEFINE PDF_ENABLE_V8} @@ -126,6 +126,7 @@ __FPDF_PTRREC = record end; 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; @@ -497,88 +498,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; @@ -941,7 +933,7 @@ FPDF_COLORSCHEME = 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: @@ -953,7 +945,7 @@ FPDF_COLORSCHEME = record // None. var FPDF_RenderPageSkia: procedure(canvas: FPDF_SKIA_CANVAS; page: FPDF_PAGE; size_x, size_y: Integer); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -{$ENDIF _SKIA_SUPPORT_} +{$ENDIF PDF_USE_SKIA} // Function: FPDF_ClosePage // Close a loaded PDF page. @@ -1296,14 +1288,15 @@ FPDF_COLORSCHEME = 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}; @@ -1431,6 +1424,9 @@ FPDF_COLORSCHEME = record // 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} @@ -1621,26 +1617,28 @@ 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_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. The |page_object| will be +// automatically freed. var - FPDFPage_InsertObject: procedure(page: FPDF_PAGE; page_obj: FPDF_PAGEOBJECT); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + FPDFPage_InsertObject: procedure(page: FPDF_PAGE; page_object: FPDF_PAGEOBJECT); {$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|. // @@ -1678,13 +1676,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}; @@ -1722,6 +1720,21 @@ 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. // @@ -1733,6 +1746,11 @@ FPDF_IMAGEOBJ_METADATA = record // |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}; @@ -1750,7 +1768,7 @@ FPDF_IMAGEOBJ_METADATA = record // // Returns TRUE on success. var - FPDFPageObj_SetMatrix: function(path: FPDF_PAGEOBJECT; const matrix: PFS_MATRIX): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + FPDFPageObj_SetMatrix: function(page_object: FPDF_PAGEOBJECT; const matrix: PFS_MATRIX): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; // Transform all annotations in |page|. // @@ -1777,6 +1795,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|. // @@ -2537,18 +2564,16 @@ FPDF_IMAGEOBJ_METADATA = record FPDFText_SetCharcodes: function(text_object: FPDF_PAGEOBJECT; const charcodes: PUINT; 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. -// -// 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. +// into the document. Various font data structures, such as the ToUnicode data, +// are auto-generated based on the inputs. // -// 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}; @@ -2561,12 +2586,32 @@ 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. +// 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. +// +// 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 loaded font can be closed using FPDFFont_Close(). +// +// Returns NULL on failure. +var + 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}; + // Get the font size of a text object. // // text - handle to a text. @@ -2658,20 +2703,20 @@ FPDF_IMAGEOBJ_METADATA = record FPDFTextObj_GetFont: function(text: FPDF_PAGEOBJECT): FPDF_FONT; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; // Experimental API. -// Get the font name of a font. +// Get the family name of a font. // // 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 font name (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-8 encoding. // If |length| is less than the returned length, or |buffer| is NULL, |buffer| // will not be modified. var - FPDFFont_GetFontName: function(font: FPDF_FONT; buffer: PAnsiChar; length: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + FPDFFont_GetFamilyName: function(font: FPDF_FONT; buffer: PAnsiChar; length: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; // Experimental API. // Get the decoded data from the |font| object. @@ -3060,6 +3105,21 @@ 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. @@ -3157,22 +3217,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. @@ -3332,17 +3376,16 @@ 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. -// It returns all characters on the page, even those that are not +// 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(). @@ -3405,20 +3448,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; @@ -3649,24 +3692,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. @@ -3938,6 +3976,8 @@ IFSDK_PAUSE = 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}; @@ -4326,184 +4366,166 @@ IFSDK_PAUSE = 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. 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 + // Implementation Required: + // No + // Parameters: + // pThis - Pointer to the interface structure itself + // Return Value: + // None + // Comments: + // Called by PDFium during the final cleanup process. 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 + // 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 + // 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 + // 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 + // 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 + // 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 + // 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. @@ -4512,79 +4534,100 @@ 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. -//* +// 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. +// +// Call this with NULL to tell PDFium to stop using a previously set +// |FPDF_SYSFONTINFO|. 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_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: +// pFontInfo - 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}; @@ -4921,245 +4964,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 for embedder-specific data. Unused by PDFium, and despite - //* its name, can be any data the embedder desires, though traditionally - //* a 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; @@ -5173,21 +5195,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; @@ -5230,796 +5248,710 @@ FPDF_SYSTEMTIME = record type PFPDF_FORMFILLINFO = ^FPDF_FORMFILLINFO; FPDF_FORMFILLINFO = record - //* - //* 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 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 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. - //* + // 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 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. - //* + // 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: - //* 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. - //* + // 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; - //* 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; - //* - //* 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. - //* + // 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. - //* + // 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(). -//* 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. -//* +// 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 returned 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}; @@ -6036,21 +5968,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}; @@ -6061,429 +5991,382 @@ 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}; -//* -//* 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. -//* +// 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. -//* +// 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 - 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. -//* +// 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 (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. -//* +// 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 itself. -//* modifier - Mask of key flags (see fpdf_fwlevent.h for key -//* flag values). -//* 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, 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. -//* +// 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}; -//* 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. -//* +// 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. -//* +// 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}; -//* -//* 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. -//* +// 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. -//* +// 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_Redo -//* Make the current focussed 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. -//* +// 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. -//* +// 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. -//* +// 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}; @@ -6521,215 +6404,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_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}; @@ -6822,6 +6686,7 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; // Check if an annotation subtype is currently supported for creation. // Currently supported subtypes: // - circle +// - fileattachment // - freetext // - highlight // - ink @@ -7518,6 +7383,18 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; var FPDFAnnot_GetFontSize: function(hHandle: FPDF_FORMHANDLE; annot: FPDF_ANNOTATION; var value: Single): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// 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. @@ -7639,20 +7516,37 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; 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. -//* +// 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 FPDFCatalog_IsTagged: function(document: FPDF_DOCUMENT): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; @@ -7833,173 +7727,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}; @@ -8047,38 +7915,32 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; 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}; @@ -8090,7 +7952,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}; @@ -8121,7 +7985,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}; @@ -8227,6 +8096,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}; @@ -8304,9 +8177,29 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; // 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}; + // Experimental API. // Function: FPDF_StructElement_GetParent // Get the parent of the structure element. @@ -8340,7 +8233,10 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; // Comments: // 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. +// 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_StructElement_GetAttributeAtIndex: function(struct_element: FPDF_STRUCTELEMENT; index: Integer): FPDF_STRUCTELEMENT_ATTR; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; @@ -8375,94 +8271,132 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; 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. +// Get the type of an attribute in a structure element attribute map. // Parameters: -// struct_attribute - Handle to the struct element attribute. -// name - The attribute name. +// value - Handle to the value. // Return value: -// Returns the type of the value, or FPDF_OBJECT_UNKNOWN in case of -// failure. +// 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; name: FPDF_BYTESTRING): FPDF_OBJECT_TYPE; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + 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 by name as -// FPDF_BOOL. FPDF_StructElement_Attr_GetType() should have returned -// FPDF_OBJECT_BOOLEAN for this property. +// 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: -// struct_attribute - Handle to the struct element attribute. -// name - The attribute name. -// out_value - A pointer to variable that will receive the -// value. Not filled if false is returned. +// 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 name maps to a boolean value, FALSE otherwise. +// Returns TRUE if the attribute maps to a boolean value, FALSE +// otherwise. var - FPDF_StructElement_Attr_GetBooleanValue: function(struct_attribute: FPDF_STRUCTELEMENT_ATTR; name: FPDF_BYTESTRING; + 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 by name as -// float. FPDF_StructElement_Attr_GetType() should have returned -// FPDF_OBJECT_NUMBER for this property. +// 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: -// struct_attribute - Handle to the struct element attribute. -// name - The attribute name. -// out_value - A pointer to variable that will receive the -// value. Not filled if false is returned. +// 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 name maps to a number value, FALSE otherwise. +// Returns TRUE if the attribute maps to a number value, FALSE +// otherwise. var - FPDF_StructElement_Attr_GetNumberValue: function(struct_attribute: FPDF_STRUCTELEMENT_ATTR; name: FPDF_BYTESTRING; + 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 by name as -// string. FPDF_StructElement_Attr_GetType() should have returned -// FPDF_OBJECT_STRING or FPDF_OBJECT_NAME for this property. -// Parameters: -// struct_attribute - Handle to the struct element attribute. -// name - The attribute name. -// 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. +// 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 name maps to a string value, FALSE otherwise. +// Returns TRUE if the attribute maps to a string value, FALSE +// otherwise. var - FPDF_StructElement_Attr_GetStringValue: function(struct_attribute: FPDF_STRUCTELEMENT_ATTR; name: FPDF_BYTESTRING; - buffer: Pointer; buflen: LongWord; var out_buflen: LongWord): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + 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 by name as -// string. +// 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: -// struct_attribute - Handle to the struct element attribute. -// name - The attribute name. -// 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. +// value - Handle to the value. // Return value: -// Returns TRUE if the name maps to a string value, FALSE otherwise. +// The number of children, or -1 on error. var - FPDF_StructElement_Attr_GetBlobValue: function(struct_attribute: FPDF_STRUCTELEMENT_ATTR; name: FPDF_BYTESTRING; - buffer: Pointer; buflen: LongWord; var out_buflen: LongWord): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + 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 @@ -8483,6 +8417,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: +// 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}; @@ -8685,9 +8623,9 @@ TImportFuncRec = record {$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..427 + ImportFuncs: array[0..438 {$IFDEF MSWINDOWS } + 2 {$ENDIF} - {$IFDEF _SKIA_SUPPORT_} + 2 {$ENDIF} + {$IFDEF PDF_USE_SKIA } + 2 {$ENDIF} {$IFDEF PDF_ENABLE_V8 } + 3 {$ENDIF} {$IFDEF PDF_ENABLE_XFA} + 3 {$ENDIF} ] of TImportFuncRec = ( @@ -8725,9 +8663,9 @@ TImportFuncRec = record {$ENDIF MSWINDOWS} (P: @@FPDF_RenderPageBitmap; N: 'FPDF_RenderPageBitmap'), (P: @@FPDF_RenderPageBitmapWithMatrix; N: 'FPDF_RenderPageBitmapWithMatrix'), - {$IFDEF _SKIA_SUPPORT_} + {$IFDEF PDF_USE_SKIA} (P: @@FPDF_RenderPageSkia; N: 'FPDF_RenderPageSkia'; Quirk: True; Optional: True), - {$ENDIF _SKIA_SUPPORT_} + {$ENDIF PDF_USE_SKIA} (P: @@FPDF_ClosePage; N: 'FPDF_ClosePage'), (P: @@FPDF_CloseDocument; N: 'FPDF_CloseDocument'), (P: @@FPDF_DeviceToPage; N: 'FPDF_DeviceToPage'), @@ -8781,10 +8719,12 @@ TImportFuncRec = record (P: @@FPDFPageObj_HasTransparency; N: 'FPDFPageObj_HasTransparency'), (P: @@FPDFPageObj_GetType; N: 'FPDFPageObj_GetType'), (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'), @@ -8848,6 +8788,7 @@ TImportFuncRec = record (P: @@FPDFText_SetCharcodes; N: 'FPDFText_SetCharcodes'), (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'), @@ -8856,7 +8797,7 @@ TImportFuncRec = record (P: @@FPDFTextObj_GetText; N: 'FPDFTextObj_GetText'), (P: @@FPDFTextObj_GetRenderedBitmap; N: 'FPDFTextObj_GetRenderedBitmap'), (P: @@FPDFTextObj_GetFont; N: 'FPDFTextObj_GetFont'), - (P: @@FPDFFont_GetFontName; N: 'FPDFFont_GetFontName'), + (P: @@FPDFFont_GetFamilyName; N: 'FPDFFont_GetFamilyName'), (P: @@FPDFFont_GetFontData; N: 'FPDFFont_GetFontData'), (P: @@FPDFFont_GetIsEmbedded; N: 'FPDFFont_GetIsEmbedded'), (P: @@FPDFFont_GetFlags; N: 'FPDFFont_GetFlags'), @@ -8889,13 +8830,13 @@ TImportFuncRec = record (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_GetTextRenderMode; N: 'FPDFText_GetTextRenderMode'), (P: @@FPDFText_GetFillColor; N: 'FPDFText_GetFillColor'), (P: @@FPDFText_GetStrokeColor; N: 'FPDFText_GetStrokeColor'), (P: @@FPDFText_GetCharAngle; N: 'FPDFText_GetCharAngle'), @@ -8976,6 +8917,8 @@ TImportFuncRec = record // *** _FPDF_SYSFONTINFO_H_ *** (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'), @@ -9034,9 +8977,9 @@ TImportFuncRec = record (P: @@FPDF_SetFormFieldHighlightAlpha; N: 'FPDF_SetFormFieldHighlightAlpha'), (P: @@FPDF_RemoveFormFieldHighlight; N: 'FPDF_RemoveFormFieldHighlight'), (P: @@FPDF_FFLDraw; N: 'FPDF_FFLDraw'), - {$IFDEF _SKIA_SUPPORT_} + {$IFDEF PDF_USE_SKIA} (P: @@FPDF_FFLDrawSkia; N: 'FPDF_FFLDrawSkia'; Quirk: True; Optional: True), - {$ENDIF _SKIA_SUPPORT_} + {$ENDIF PDF_USE_SKIA} (P: @@FPDF_GetFormType; N: 'FPDF_GetFormType'), (P: @@FORM_SetIndexSelected; N: 'FORM_SetIndexSelected'), @@ -9096,6 +9039,7 @@ TImportFuncRec = record (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'), @@ -9106,6 +9050,8 @@ TImportFuncRec = record (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'), @@ -9161,6 +9107,7 @@ TImportFuncRec = record (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_IsChecked; N: 'FPDFAnnot_IsChecked'), (P: @@FPDFAnnot_SetFocusableSubtypes; N: 'FPDFAnnot_SetFocusableSubtypes'), @@ -9171,6 +9118,8 @@ TImportFuncRec = record (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'), {$IFDEF PDF_ENABLE_V8} // *** _FPDF_LIBS_H_ *** @@ -9221,12 +9170,12 @@ function PDF_USE_XFA: Boolean; function PDF_IsSkiaAvailable: Boolean; begin - {$IFDEF _SKIA_SUPPORT_} + {$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 _SKIA_SUPPORT_} + {$ENDIF PDF_USE_SKIA} end; procedure Init; @@ -9340,7 +9289,7 @@ procedure InitPDFiumEx(const DllFileName: string{$IFDEF PDF_ENABLE_V8}; const Re {$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 := 4; + LibraryConfig.version := 2; LibraryConfig.m_RendererType := FPDF_RENDERERTYPE_AGG; {if IsSkiaAvailable and SkiaRendererEnabled then LibraryConfig.m_RendererType := FPDF_RENDERERTYPE_SKIA;} From 571f1931cba330672e31e844522280368e381734 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Sat, 3 Aug 2024 23:09:26 +0200 Subject: [PATCH 50/59] * Fixed FPC (LCL) key events in form fields * PdfiumCore.pas can be compiled with FPC (LCL) for Linux --- Source/PdfiumCore.pas | 94 ++++++++++++++++++++++--------------------- Source/PdfiumCtrl.pas | 67 ++++++++++++++++-------------- 2 files changed, 84 insertions(+), 77 deletions(-) diff --git a/Source/PdfiumCore.pas b/Source/PdfiumCore.pas index 89561cd..3bd2ebe 100644 --- a/Source/PdfiumCore.pas +++ b/Source/PdfiumCore.pas @@ -20,7 +20,7 @@ interface {$IFDEF FPC} LCLType, {$ENDIF FPC} - ExtCtrls, + ExtCtrls, // for TTimer {$ENDIF MSWINDOWS} Types, SysUtils, Classes, Contnrs, PdfiumLib; @@ -484,8 +484,7 @@ 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; @@ -497,10 +496,19 @@ TPdfPage = class(TObject) 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 = []; PageBackground: TColorRef = $FFFFFF); + 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 = []); @@ -519,9 +527,9 @@ TPdfPage = class(TObject) 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; + 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; @@ -781,6 +789,7 @@ TCustomLoadDataRec = record property OnExecuteNamedAction: TPdfExecuteNamedActionEvent read FOnExecuteNamedAction write FOnExecuteNamedAction; end; + {$IFDEF MSWINDOWS} TPdfDocumentPrinterStatusEvent = procedure(Sender: TObject; CurrentPageNum, PageCount: Integer) of object; TPdfDocumentPrinter = class(TObject) @@ -827,6 +836,7 @@ TPdfDocumentPrinter = class(TObject) { OnPrintStatus is triggered after every printed page } property OnPrintStatus: TPdfDocumentPrinterStatusEvent read FOnPrintStatus write FOnPrintStatus; end; + {$ENDIF MSWINDOWS} function SetThreadPdfUnsupportedFeatureHandler(const Handler: TPdfUnsupportedFeatureHandler): TPdfUnsupportedFeatureHandler; @@ -1168,7 +1178,7 @@ procedure FFI_KillTimer(pThis: PFPDF_FORMFILLINFO; nTimerID: Integer); cdecl; end; end; end; -{$ELSE MSWINDOWS} +{$ELSE} type TFFITimer = class(TTimer) public @@ -1603,7 +1613,7 @@ procedure TPdfDocument.LoadFromFile(const FileName: string; const Password: UTF8 finally FreeAndNil(FFileStream); end; - end + end; dloOnDemand: LoadFromActiveStream(FFileStream, Password); end; @@ -2385,6 +2395,7 @@ class function TPdfPage.GetDrawFlags(const Options: TPdfPageRenderOptions): Inte Result := Result or FPDF_REVERSE_BYTE_ORDER; end; +{$IFDEF MSWINDOWS} procedure TPdfPage.Draw(DC: HDC; X, Y, Width, Height: Integer; Rotate: TPdfPageRotation; const Options: TPdfPageRenderOptions; PageBackground: TColorRef); var @@ -2396,7 +2407,6 @@ procedure TPdfPage.Draw(DC: HDC; X, Y, Width, Height: Integer; Rotate: TPdfPageR begin Open; - {$IFDEF MSWINDOWS} if proPrinting in Options then begin if IsValidForm and (FPDFPage_GetAnnotCount(FPage) > 0) then @@ -2410,13 +2420,11 @@ procedure TPdfPage.Draw(DC: HDC; X, Y, Width, Height: Integer; Rotate: TPdfPageR FPDF_RenderPage(DC, FPage, X, Y, Width, Height, Ord(Rotate), GetDrawFlags(Options)); Exit; end; - {$ENDIF MSWINDOWS} - 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; @@ -2425,11 +2433,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 - PdfBmp.FillRect(0, 0, Width, Height, $FF000000 or PageBackground); - 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; @@ -2444,6 +2451,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(0, 0, Width, Height, $FF000000 or PageBackground); + DrawToPdfBitmap(APdfBitmap, 0, 0, Width, Height, Rotate, Options); + DrawFormToPdfBitmap(APdfBitmap, 0, 0, Width, Height, Rotate, Options); +end; procedure TPdfPage.DrawToPdfBitmap(APdfBitmap: TPdfBitmap; X, Y, Width, Height: Integer; Rotate: TPdfPageRotation; const Options: TPdfPageRenderOptions); @@ -2861,7 +2877,7 @@ function TPdfPage.IsWebLinkAtPoint(X, Y: Double; var URL: string): Boolean; Result := False; end; -function TPdfPage.GetMouseModifier(const Shift: TShiftState): Integer; +function TPdfPage.ShiftStateToModifier(const Shift: TShiftState): Integer; begin Result := 0; if ssShift in Shift then @@ -2878,25 +2894,10 @@ function TPdfPage.GetMouseModifier(const Shift: TShiftState): Integer; Result := Result or FWL_EVENTFLAG_RightButtonDown; end; -function TPdfPage.GetKeyModifier(KeyData: LPARAM): Integer; -const - AltMask = $20000000; -begin - Result := 0; - {$IFDEF MSWINDOWS} - if GetKeyState(VK_SHIFT) < 0 then - Result := Result or FWL_EVENTFLAG_ShiftKey; - if GetKeyState(VK_CONTROL) < 0 then - Result := Result or FWL_EVENTFLAG_ControlKey; - {$ENDIF MSWINDOWS} - if KeyData and AltMask <> 0 then - Result := Result or FWL_EVENTFLAG_AltKey; -end; - function TPdfPage.FormEventFocus(const Shift: TShiftState; PageX, PageY: Double): Boolean; begin if IsValidForm then - Result := FORM_OnFocus(FDocument.FForm, FPage, GetMouseModifier(Shift), PageX, PageY) <> 0 + Result := FORM_OnFocus(FDocument.FForm, FPage, ShiftStateToModifier(Shift), PageX, PageY) <> 0 else Result := False; end; @@ -2916,7 +2917,7 @@ function TPdfPage.FormEventMouseWheel(const Shift: TShiftState; WheelDelta: Inte WheelX := WheelDelta else WheelY := WheelDelta; - Result := FORM_OnMouseWheel(FDocument.FForm, FPage, GetMouseModifier(Shift), @Pt, WheelX, WheelY) <> 0; + Result := FORM_OnMouseWheel(FDocument.FForm, FPage, ShiftStateToModifier(Shift), @Pt, WheelX, WheelY) <> 0; end else Result := False; @@ -2925,7 +2926,7 @@ function TPdfPage.FormEventMouseWheel(const Shift: TShiftState; WheelDelta: Inte 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; @@ -2933,7 +2934,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; @@ -2941,7 +2942,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; @@ -2949,7 +2950,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; @@ -2957,31 +2958,31 @@ 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; KeyData: LPARAM): Boolean; +function TPdfPage.FormEventKeyDown(KeyCode: Word; const Shift: TShiftState): Boolean; begin if IsValidForm then - Result := FORM_OnKeyDown(FDocument.FForm, FPage, KeyCode, GetKeyModifier(KeyData)) <> 0 + Result := FORM_OnKeyDown(FDocument.FForm, FPage, KeyCode, ShiftStateToModifier(Shift)) <> 0 else Result := False; end; -function TPdfPage.FormEventKeyUp(KeyCode: Word; KeyData: LPARAM): Boolean; +function TPdfPage.FormEventKeyUp(KeyCode: Word; const Shift: TShiftState): Boolean; begin if IsValidForm then - Result := FORM_OnKeyUp(FDocument.FForm, FPage, KeyCode, GetKeyModifier(KeyData)) <> 0 + Result := FORM_OnKeyUp(FDocument.FForm, FPage, KeyCode, ShiftStateToModifier(Shift)) <> 0 else Result := False; end; -function TPdfPage.FormEventKeyPress(Key: Word; KeyData: LPARAM): Boolean; +function TPdfPage.FormEventKeyPress(Key: Word; const Shift: TShiftState): Boolean; begin if IsValidForm then - Result := FORM_OnChar(FDocument.FForm, FPage, Key, GetKeyModifier(KeyData)) <> 0 + Result := FORM_OnChar(FDocument.FForm, FPage, Key, ShiftStateToModifier(Shift)) <> 0 else Result := False; end; @@ -4301,7 +4302,7 @@ function TPdfPageWebLinksInfo.IsWebLinkAt(X, Y: Double; var Url: string): Boolea Url := ''; end; - +{$IFDEF MSWINDOWS} { TPdfDocumentPrinter } constructor TPdfDocumentPrinter.Create; @@ -4496,6 +4497,7 @@ procedure TPdfDocumentPrinter.InternPrintPage(APage: TPdfPage; X, Y, Width, Heig prNormal, [proPrinting, proAnnotations] ); end; +{$ENDIF MSWINDOWS} initialization {$IFDEF FPC} diff --git a/Source/PdfiumCtrl.pas b/Source/PdfiumCtrl.pas index 813fe79..9842260 100644 --- a/Source/PdfiumCtrl.pas +++ b/Source/PdfiumCtrl.pas @@ -175,9 +175,9 @@ 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; function LinkHandlingNeeded: Boolean; @@ -1978,52 +1978,57 @@ procedure TPdfControl.KeyDown(var Key: Word; Shift: TShiftState); procedure TPdfControl.WMKeyDown(var Message: TWMKeyDown); var - ShiftState: TShiftState; + Shift: TShiftState; begin - if AllowFormEvents and IsPageValid and CurrentPage.FormEventKeyDown(Message.CharCode, Message.KeyData) then + if AllowFormEvents and IsPageValid 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 - ShiftState := KeyDataToShiftState(Message.KeyData); - if ShiftState = [ssCtrl] then - begin - case Message.CharCode of - Ord('C'), VK_INSERT: - CopyFormTextToClipboard; - Ord('X'): - CutFormTextToClipboard; - Ord('V'): - PasteFormTextFromClipboard; - end; - end - else if ShiftState = [ssShift] then + 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 - case Message.CharCode of - VK_INSERT: - PasteFormTextFromClipboard; - VK_DELETE: - CutFormTextToClipboard; + 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; + end; + Exit; end; - Exit; 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; From 94936644c5a83e83c304055667544bc2916dc7d9 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Mon, 18 Nov 2024 20:44:26 +0100 Subject: [PATCH 51/59] Fixes #47: Added AddHightlightText() method to allow multiple highlighted texts By using ClearHighlightText() followed by one or more AddHightlightText() calls one can add multiple highlighted texts. The HighlightText() method removes all highlighted texts and adds a new one to keep backward compatibility. --- Example/MainFrm.pas | 4 +- Source/PdfiumCtrl.pas | 114 +++++++++++++++++++++++++++++++++--------- 2 files changed, 92 insertions(+), 26 deletions(-) diff --git a/Example/MainFrm.pas b/Example/MainFrm.pas index 55f41bc..5c60dfa 100644 --- a/Example/MainFrm.pas +++ b/Example/MainFrm.pas @@ -132,7 +132,9 @@ procedure TfrmMain.btnNextClick(Sender: TObject); procedure TfrmMain.btnHighlightClick(Sender: TObject); begin - FCtrl.HightlightText('the', False, False); + FCtrl.ClearHighlightText; + FCtrl.AddHightlightText('the', False, True); + FCtrl.AddHightlightText('in', False, True); end; procedure TfrmMain.btnScaleClick(Sender: TObject); diff --git a/Source/PdfiumCtrl.pas b/Source/PdfiumCtrl.pas index 9842260..672e532 100644 --- a/Source/PdfiumCtrl.pas +++ b/Source/PdfiumCtrl.pas @@ -27,8 +27,8 @@ interface {$IFDEF FPC} LCLType, PrintersDlgs, Win32Extra, {$ENDIF FPC} - Windows, Messages, ShellAPI, Types, SysUtils, Classes, Graphics, Controls, Forms, - Dialogs, PdfiumCore; + Windows, Messages, ShellAPI, Types, SysUtils, Classes, Contnrs, Graphics, Controls, + Forms, Dialogs, PdfiumCore; type TPdfControlLinkOptionType = ( @@ -97,9 +97,7 @@ TPdfControl = class(TCustomControl) FScrollMousePos: TPoint; FLinkOptions: TPdfControlLinkOptions; FHighlightTextRects: TPdfRectArray; - FHighlightText: string; - FHighlightMatchCase: Boolean; - FHighlightMatchWholeWord: Boolean; + FHighlightTexts: TObjectList; FFormOutputSelectedRects: TPdfRectArray; FFormFieldFocused: Boolean; FPageShadowSize: Integer; @@ -233,7 +231,12 @@ 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; @@ -348,8 +351,8 @@ TPdfDocumentVclPrinter = class(TPdfDocumentPrinter) 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; + class function PrintDocument(ADocument: TPdfDocument; const AJobTitle: string; + AShowPrintDialog: Boolean = True; AllowPageRange: Boolean = True; AParentWnd: HWND = 0): Boolean; static; end; @@ -364,6 +367,21 @@ 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 {$IFDEF FPC} @@ -389,6 +407,23 @@ function FastVclAbortProc(Prn: HDC; Error: Integer): Bool; stdcall; 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; @@ -2694,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: TPdfRectArray; + HLTextInfo: THighlightTextInfo; Page: TPdfPage; - CharIndex, CharCount, I, Count: Integer; + CharIndex, CharCount, I, Count, TextsIndex: Integer; Num: Integer; begin OldHighlightTextRects := FHighlightTextRects; FHighlightTextRects := nil; - if (FHighlightText <> '') and IsPageValid 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; @@ -2741,7 +2805,7 @@ procedure TPdfControl.CalcHighlightTextRects; procedure TPdfControl.ClearHighlightText; begin - FHighlightText := ''; + FreeAndNil(FHighlightTexts); InvalidatePdfRectDiffs(FHighlightTextRects, nil); FHighlightTextRects := nil; end; From c0d3409afb82f6ba4e1ebce15ba168a854083f54 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Mon, 18 Nov 2024 20:51:31 +0100 Subject: [PATCH 52/59] Fix typos in comment --- Example/MainFrm.pas | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Example/MainFrm.pas b/Example/MainFrm.pas index 5c60dfa..c6c4f00 100644 --- a/Example/MainFrm.pas +++ b/Example/MainFrm.pas @@ -237,7 +237,7 @@ procedure TfrmMain.ListViewAttachmentsDblClick(Sender: TObject); procedure TfrmMain.btnAddAnnotationClick(Sender: TObject); begin - // Add a new annotation and make it persietent so that is can be shown and saved to a file. + // 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'); From 54507312e1d3e612c629db8e5302aa64b47d6a06 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Fri, 20 Jun 2025 12:52:29 +0200 Subject: [PATCH 53/59] * Updated to chromium/7242 / PDFium 139.0.7242.0 --- Example/MainFrm.pas | 1 + README.md | 4 +- Source/PdfiumCore.pas | 7 +- Source/PdfiumCtrl.pas | 2 +- Source/PdfiumLib.pas | 328 +++++++++++++++++++++++++++++------------- 5 files changed, 235 insertions(+), 107 deletions(-) diff --git a/Example/MainFrm.pas b/Example/MainFrm.pas index c6c4f00..74f0386 100644 --- a/Example/MainFrm.pas +++ b/Example/MainFrm.pas @@ -63,6 +63,7 @@ procedure TfrmMain.FormCreate(Sender: TObject); //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} diff --git a/README.md b/README.md index d537a65..3259e2d 100644 --- a/README.md +++ b/README.md @@ -4,10 +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/6611](https://github.com/bblanchon/pdfium-binaries/releases/tag/chromium%2F6611) +Binary release: [chromium/7242](https://github.com/bblanchon/pdfium-binaries/releases/tag/chromium%2F7242) ## Required pdfium.dll version -chromium/6611 +chromium/7242 / PDFium 139.0.7242.0 ## Features - Multiple PDF load functions: diff --git a/Source/PdfiumCore.pas b/Source/PdfiumCore.pas index 3bd2ebe..334748d 100644 --- a/Source/PdfiumCore.pas +++ b/Source/PdfiumCore.pas @@ -843,9 +843,6 @@ function SetThreadPdfUnsupportedFeatureHandler(const Handler: TPdfUnsupportedFea 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 @@ -996,9 +993,9 @@ procedure InitLib; if Initialized = 0 then begin if PDFiumDllFileName <> '' then - InitPDFiumEx(PDFiumDllFileName {$IF declared(FPDF_InitEmbeddedLibraries)}, PDFiumResDir{$IFEND}) + InitPDFiumEx(PDFiumDllFileName) else - InitPDFium(PDFiumDllDir {$IF declared(FPDF_InitEmbeddedLibraries)}, PDFiumResDir{$IFEND}); + InitPDFium(PDFiumDllDir); FSDK_SetUnSpObjProcessHandler(@UnsupportInfo); Initialized := 1; end; diff --git a/Source/PdfiumCtrl.pas b/Source/PdfiumCtrl.pas index 672e532..e06790f 100644 --- a/Source/PdfiumCtrl.pas +++ b/Source/PdfiumCtrl.pas @@ -1528,7 +1528,7 @@ procedure TPdfControl.MouseMove(Shift: TShiftState; X, Y: Integer); Proceed := False; case Page.HasFormFieldAtPoint(PagePt.X, PagePt.Y) of fftUnknown: - // Could be a annotation link with a URL + // Could be an annotation link with a URL Proceed := True; fftTextField: NewCursor := crIBeam; diff --git a/Source/PdfiumLib.pas b/Source/PdfiumLib.pas index c31ee4d..482ec7d 100644 --- a/Source/PdfiumLib.pas +++ b/Source/PdfiumLib.pas @@ -1,6 +1,6 @@ // Use DLLs (x64, x86) from https://github.com/bblanchon/pdfium-binaries // -// DLL Version: chromium/6611 +// DLL Version: chromium/7242 unit PdfiumLib; {$IFDEF FPC} @@ -734,6 +734,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}; @@ -748,6 +750,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}; @@ -759,6 +763,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}; @@ -772,6 +778,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}; @@ -875,10 +883,10 @@ FPDF_COLORSCHEME = 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 @@ -1075,11 +1083,16 @@ FPDF_COLORSCHEME = 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. + 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) @@ -1146,7 +1159,7 @@ FPDF_COLORSCHEME = 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. @@ -1157,7 +1170,7 @@ FPDF_COLORSCHEME = 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. @@ -1625,6 +1638,22 @@ FPDF_IMAGEOBJ_METADATA = record var FPDFPage_InsertObject: procedure(page: FPDF_PAGE; page_object: FPDF_PAGEOBJECT); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Insert |page_object| into |page| at the specified |index|. +// +// 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_InsertObjectAtIndex: function(page: FPDF_PAGE; page_object: FPDF_PAGEOBJECT; index: SIZE_T): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // Experimental API. // Remove |page_object| from |page|. // @@ -1703,6 +1732,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. @@ -1856,17 +1917,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|. @@ -1884,17 +1946,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. @@ -1928,18 +1991,18 @@ FPDF_IMAGEOBJ_METADATA = record // 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. @@ -1947,17 +2010,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 @@ -2006,7 +2070,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. @@ -2195,6 +2259,28 @@ FPDF_IMAGEOBJ_METADATA = record 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. @@ -2702,6 +2788,23 @@ FPDF_IMAGEOBJ_METADATA = record 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 + FPDFFont_GetBaseFontName: function(font: FPDF_FONT; buffer: PAnsiChar; length: SIZE_T): SIZE_T; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // Experimental API. // Get the family name of a font. // @@ -2716,7 +2819,7 @@ FPDF_IMAGEOBJ_METADATA = record // If |length| is less than the returned length, or |buffer| is NULL, |buffer| // will not be modified. var - FPDFFont_GetFamilyName: function(font: FPDF_FONT; buffer: PAnsiChar; 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. @@ -2872,6 +2975,20 @@ FPDF_IMAGEOBJ_METADATA = record var FPDFFormObj_GetObject: function(form_object: FPDF_PAGEOBJECT; index: LongWord): FPDF_PAGEOBJECT; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Experimental API. +// +// Remove |page_object| from |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_RemoveObject: function(form_object: FPDF_PAGEOBJECT; page_object: FPDF_PAGEOBJECT): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // *** _FPDF_PPO_H_ *** // Experimental API. @@ -4590,7 +4707,7 @@ FPDF_CharsetFontMap = record // Function: FPDF_SetSystemFontInfo // Set the system font info interface into PDFium // Parameters: -// pFontInfo - Pointer to a FPDF_SYSFONTINFO structure +// font_info - Pointer to a FPDF_SYSFONTINFO structure // Return Value: // None // Comments: @@ -4601,7 +4718,7 @@ FPDF_CharsetFontMap = record // Call this with NULL to tell PDFium to stop using a previously set // |FPDF_SYSFONTINFO|. var - FPDF_SetSystemFontInfo: procedure(pFontInfo: PFPDF_SYSFONTINFO); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + 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 @@ -4622,14 +4739,14 @@ FPDF_CharsetFontMap = record // Function: FPDF_FreeDefaultSystemFontInfo // Free a default system font info interface // Parameters: -// pFontInfo - Pointer to a FPDF_SYSFONTINFO structure +// 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_ *** @@ -6876,7 +6993,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. @@ -6891,7 +7008,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. @@ -7237,6 +7354,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 @@ -7383,6 +7512,24 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; 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 @@ -7550,6 +7697,16 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; var FPDFCatalog_IsTagged: function(document: FPDF_DOCUMENT): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// 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_SetLanguage: function(document: FPDF_DOCUMENT; language: FPDF_BYTESTRING): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // *** _FPDF_ATTACHMENT_H_ *** @@ -7704,6 +7861,20 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; 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_ *** @@ -8424,25 +8595,6 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; var FPDF_StructElement_GetMarkedContentIdAtIndex: function(struct_element: FPDF_STRUCTELEMENT; index: Integer): Integer; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; - -// *** _FPDF_LIBS_H_ *** - -{$IFDEF PDF_ENABLE_V8} - -// Function: FPDF_InitEmbeddedLibraries -// Initialize embedded libraries (v8, iuctl) included in pdfium -// Parameters: -// resourcePath - a path to v8 resources (snapshot_blob.bin, icudtl.dat, ...) -// Return value: -// None. -// Comments: -// This function must be called before calling FPDF_InitLibrary() -// if v8 suppport is enabled -var - FPDF_InitEmbeddedLibraries: procedure(const resourcePath: PAnsiChar); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; -{$ENDIF PDF_ENABLE_V8} - - // *** _FPDF_JAVASCRIPT_H_ *** // Experimental API. @@ -8541,8 +8693,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 @@ -8623,10 +8775,10 @@ TImportFuncRec = record {$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..438 + ImportFuncs: array[0..448 {$IFDEF MSWINDOWS } + 2 {$ENDIF} {$IFDEF PDF_USE_SKIA } + 2 {$ENDIF} - {$IFDEF PDF_ENABLE_V8 } + 3 {$ENDIF} + {$IFDEF PDF_ENABLE_V8 } + 2 {$ENDIF} {$IFDEF PDF_ENABLE_XFA} + 3 {$ENDIF} ] of TImportFuncRec = ( @@ -8710,6 +8862,7 @@ TImportFuncRec = record (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'), @@ -8718,6 +8871,8 @@ TImportFuncRec = record (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'), @@ -8752,6 +8907,7 @@ TImportFuncRec = record (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'), @@ -8797,6 +8953,7 @@ TImportFuncRec = record (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'), @@ -8811,6 +8968,7 @@ TImportFuncRec = record (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_ImportPagesByIndex; N: 'FPDF_ImportPagesByIndex'), @@ -8988,6 +9146,7 @@ TImportFuncRec = record // *** _FPDF_CATALOG_H_ *** (P: @@FPDFCatalog_IsTagged; N: 'FPDFCatalog_IsTagged'), + (P: @@FPDFCatalog_SetLanguage; N: 'FPDFCatalog_SetLanguage'), // *** _FPDF_ATTACHMENT_H_ *** (P: @@FPDFDoc_GetAttachmentCount; N: 'FPDFDoc_GetAttachmentCount'), @@ -9001,6 +9160,7 @@ TImportFuncRec = record (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'), @@ -9098,6 +9258,7 @@ TImportFuncRec = record (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'), @@ -9108,6 +9269,7 @@ TImportFuncRec = record (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'), @@ -9121,11 +9283,6 @@ TImportFuncRec = record (P: @@FPDFAnnot_GetFileAttachment; N: 'FPDFAnnot_GetFileAttachment'), (P: @@FPDFAnnot_AddFileAttachment; N: 'FPDFAnnot_AddFileAttachment'), - {$IFDEF PDF_ENABLE_V8} - // *** _FPDF_LIBS_H_ *** - (P: @@FPDF_InitEmbeddedLibraries; N: 'FPDF_InitEmbeddedLibraries'; Optional: True), - {$ENDIF PDF_ENABLE_V8} - // *** _FPDF_JAVASCRIPT_H_ *** (P: @@FPDFDoc_GetJavaScriptActionCount; N: 'FPDFDoc_GetJavaScriptActionCount'), (P: @@FPDFDoc_GetJavaScriptAction; N: 'FPDFDoc_GetJavaScriptAction'), @@ -9186,15 +9343,15 @@ 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; @@ -9258,33 +9415,6 @@ 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} - // 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); From 3ce2cc9382e217b72e8c501e715865363415a355 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Fri, 20 Jun 2025 23:30:19 +0200 Subject: [PATCH 54/59] Fix: TPdfPage.Draw ignored X and Y parameter --- Source/PdfiumCore.pas | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/PdfiumCore.pas b/Source/PdfiumCore.pas index 334748d..d52c03b 100644 --- a/Source/PdfiumCore.pas +++ b/Source/PdfiumCore.pas @@ -2453,9 +2453,9 @@ procedure TPdfPage.Draw(DC: HDC; X, Y, Width, Height: Integer; Rotate: TPdfPageR procedure TPdfPage.Draw(APdfBitmap: TPdfBitmap; X, Y, Width, Height: Integer; Rotate: TPdfPageRotation = prNormal; const Options: TPdfPageRenderOptions = []; PageBackground: TColorRef = $FFFFFF); begin - APdfBitmap.FillRect(0, 0, Width, Height, $FF000000 or PageBackground); - DrawToPdfBitmap(APdfBitmap, 0, 0, Width, Height, Rotate, Options); - DrawFormToPdfBitmap(APdfBitmap, 0, 0, Width, Height, Rotate, Options); + 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; From c3d5f5726765cbcb364466c3ebcef367874ae049 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Sommer=20Hoffmann?= Date: Wed, 21 Jan 2026 10:09:58 +0100 Subject: [PATCH 55/59] support 'FPDFAnnot_SetFormFieldFlags' API * added method 'TPdfFormField.SetFlags' for write-access to property 'Flags' * therefore inversed logic of 'TPdfFormField.GetFlags' (using 'or' instead of 'and') --- Source/PdfiumCore.pas | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/Source/PdfiumCore.pas b/Source/PdfiumCore.pas index d52c03b..1a74176 100644 --- a/Source/PdfiumCore.pas +++ b/Source/PdfiumCore.pas @@ -274,6 +274,7 @@ TPdfFormField = class(TObject) procedure SetValue(const Value: string); procedure SetChecked(const Value: Boolean); + procedure SetFlags(const Value: TPdfFormFieldFlags); protected constructor Create(AAnnotation: TPdfAnnotation); @@ -288,7 +289,7 @@ TPdfFormField = class(TObject) function SelectComboBoxOption(OptionIndex: Integer): Boolean; function SelectListBoxOption(OptionIndex: Integer; Selected: Boolean = True): Boolean; - property Flags: TPdfFormFieldFlags read GetFlags; + property Flags: TPdfFormFieldFlags read GetFlags write SetFlags; property ReadOnly: Boolean read GetReadOnly; property Name: string read GetName; property AlternateName: string read GetAlternateName; @@ -4147,6 +4148,37 @@ procedure TPdfFormField.SetChecked(const Value: Boolean); 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 } From b926ac48f06b6832d30ce2e0fc00c5310dd1ea67 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Wed, 21 Jan 2026 19:37:36 +0100 Subject: [PATCH 56/59] fix: Remove unused local variable --- Source/PdfiumLib.pas | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/PdfiumLib.pas b/Source/PdfiumLib.pas index 482ec7d..86f350a 100644 --- a/Source/PdfiumLib.pas +++ b/Source/PdfiumLib.pas @@ -9354,7 +9354,6 @@ procedure InitPDFium(const DllPath: string); procedure InitPDFiumEx(const DllFileName: string); var I: Integer; - Path: string; LibraryConfig: FPDF_LIBRARY_CONFIG; begin if PdfiumModule <> 0 then From 985e2a48dc85159745d62c5c05cf59b17093f30b Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Sat, 30 May 2026 11:08:30 +0200 Subject: [PATCH 57/59] fix: Mouse Cursor crIBeam vs. crDefault if text box is focused --- Source/PdfiumCtrl.pas | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/PdfiumCtrl.pas b/Source/PdfiumCtrl.pas index e06790f..4c4ab80 100644 --- a/Source/PdfiumCtrl.pas +++ b/Source/PdfiumCtrl.pas @@ -1543,9 +1543,9 @@ procedure TPdfControl.MouseMove(Shift: TShiftState; X, Y: Integer); end; end; - if AllowUserTextSelection and not FFormFieldFocused then + if AllowUserTextSelection then begin - if FMousePressed then + if FMousePressed and not FFormFieldFocused then begin // Auto scroll FScrollMousePos := Point(X, Y); From a7f8ac6d0fc6af273947b4003812c50362dacffd Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Sat, 30 May 2026 11:50:49 +0200 Subject: [PATCH 58/59] Updated to chromium/7857 / PDFium 150.0.7857.0 --- Source/PdfiumCore.pas | 4 + Source/PdfiumLib.pas | 219 +++++++++++++++++++++++++++++++++++------- 2 files changed, 186 insertions(+), 37 deletions(-) diff --git a/Source/PdfiumCore.pas b/Source/PdfiumCore.pas index 1a74176..5e0b1d9 100644 --- a/Source/PdfiumCore.pas +++ b/Source/PdfiumCore.pas @@ -2494,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; @@ -2535,6 +2537,8 @@ 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; diff --git a/Source/PdfiumLib.pas b/Source/PdfiumLib.pas index 86f350a..6096ec6 100644 --- a/Source/PdfiumLib.pas +++ b/Source/PdfiumLib.pas @@ -1,6 +1,6 @@ // Use DLLs (x64, x86) from https://github.com/bblanchon/pdfium-binaries // -// DLL Version: chromium/7242 +// DLL Version: chromium/7857 unit PdfiumLib; {$IFDEF FPC} @@ -271,6 +271,16 @@ FS_QUADPOINTSF = record // 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. PFPDF_LIBRARY_CONFIG = ^FPDF_LIBRARY_CONFIG; @@ -303,13 +313,26 @@ FPDF_LIBRARY_CONFIG = record // Version 4 - Experimental. - // Explicit specification of core renderer 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. + // 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 render library is not included in the build will similarly - // fail with an immediate crash. + // 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; @@ -1084,6 +1107,7 @@ FPDF_COLORSCHEME = record const // More DIB formats 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. @@ -1616,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}; @@ -1632,11 +1658,15 @@ FPDF_IMAGEOBJ_METADATA = record // Insert |page_object| into |page|. // -// page - handle to a page -// page_object - handle to a page object. The |page_object| will be -// automatically freed. +// 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: procedure(page: FPDF_PAGE; page_object: FPDF_PAGEOBJECT); {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + 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|. // @@ -1985,6 +2015,21 @@ 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. // @@ -2039,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 @@ -2633,7 +2694,8 @@ FPDF_IMAGEOBJ_METADATA = record // 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 FPDFText_SetText: function(text_object: FPDF_PAGEOBJECT; text: FPDF_WIDESTRING): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; @@ -2645,10 +2707,31 @@ FPDF_IMAGEOBJ_METADATA = record // charcodes - pointer to an array of charcodes to be added. // count - number of elements in |charcodes|. // -// Returns TRUE on success +// Returns TRUE on success. Fails if |text_object| or |charcodes| is null, or +// |count| is 0. var FPDFText_SetCharcodes: function(text_object: FPDF_PAGEOBJECT; const charcodes: PUINT; count: SIZE_T): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; +// Experimental API. +// Set the character positions for a text object. +// +// text_object - handle to the text object. +// positions - pointer to an array of character positions to be set. +// count - number of elements in |positions|. +// +// 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_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. Various font data structures, such as the ToUnicode data, // are auto-generated based on the inputs. @@ -3049,7 +3132,8 @@ FPDF_IMAGEOBJ_METADATA = record // |src_page_index|, for use in |dest_doc|. // // Returns a handle on success, or NULL on failure. Caller owns the newly -// created object. +// 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}; @@ -3098,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_ *** @@ -4488,14 +4581,17 @@ IFSDK_PAUSE = record 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 + // 1 and 2 // Implementation Required: // No // Parameters: @@ -4504,12 +4600,14 @@ FPDF_SYSFONTINFO = record // 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 + // 1 and 2 // Implementation Required: // No // Parameters: @@ -4559,7 +4657,7 @@ FPDF_SYSFONTINFO = record // Method: GetFont // Get a handle to a particular font by its internal ID // Interface Version: - // 1 + // 1 and 2 // Implementation Required: // Required if MapFont method is not implemented. // Return Value: @@ -4575,7 +4673,7 @@ FPDF_SYSFONTINFO = record // Method: GetFontData // Get font data from a font // Interface Version: - // 1 + // 1 and 2 // Implementation Required: // Yes // Parameters: @@ -4598,7 +4696,7 @@ FPDF_SYSFONTINFO = record // Method: GetFaceName // Get face name from a font handle // Interface Version: - // 1 + // 1 and 2 // Implementation Required: // No // Parameters: @@ -4615,7 +4713,7 @@ FPDF_SYSFONTINFO = record // Method: GetFontCharset // Get character set information for a font handle // Interface Version: - // 1 + // 1 and 2 // Implementation Required: // No // Parameters: @@ -4628,7 +4726,7 @@ FPDF_SYSFONTINFO = record // Method: DeleteFont // Delete a font handle // Interface Version: - // 1 + // 1 and 2 // Implementation Required: // Yes // Parameters: @@ -7697,6 +7795,28 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; var FPDFCatalog_IsTagged: function(document: FPDF_DOCUMENT): FPDF_BOOL; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + +// Experimental API. +// Gets the language of |document| from the catalog's /Lang entry. +// +// 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 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 + FPDFCatalog_GetLanguage: function(document: FPDF_DOCUMENT; buffer: PFPDF_WCHAR; buflen: LongWord): LongWord; {$IFDEF DLLEXPORT}stdcall{$ELSE}cdecl{$ENDIF}; + // Experimental API. // Sets the language of |document| to |language|. // @@ -7705,7 +7825,7 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; // // Returns TRUE on success. var - FPDFCatalog_SetLanguage: function(document: FPDF_DOCUMENT; language: FPDF_BYTESTRING): 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_ *** @@ -8202,6 +8322,26 @@ function IS_XFA_FORMFIELD(type_: Integer): Boolean; inline; 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: @@ -8775,7 +8915,7 @@ TImportFuncRec = record {$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..448 + ImportFuncs: array[0..453 {$IFDEF MSWINDOWS } + 2 {$ENDIF} {$IFDEF PDF_USE_SKIA } + 2 {$ENDIF} {$IFDEF PDF_ENABLE_V8 } + 2 {$ENDIF} @@ -8889,9 +9029,11 @@ TImportFuncRec = record (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'), @@ -8942,6 +9084,7 @@ TImportFuncRec = record (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'), @@ -9146,6 +9289,7 @@ TImportFuncRec = record // *** _FPDF_CATALOG_H_ *** (P: @@FPDFCatalog_IsTagged; N: 'FPDFCatalog_IsTagged'), + (P: @@FPDFCatalog_GetLanguage; N: 'FPDFCatalog_GetLanguage'), (P: @@FPDFCatalog_SetLanguage; N: 'FPDFCatalog_SetLanguage'), // *** _FPDF_ATTACHMENT_H_ *** @@ -9190,6 +9334,7 @@ TImportFuncRec = record (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'), From b27551760d817e719943d54eeeab7c01b38fcf11 Mon Sep 17 00:00:00 2001 From: Andreas Hausladen Date: Sat, 30 May 2026 16:33:57 +0200 Subject: [PATCH 59/59] Updated to chromium/7857 / PDFium 150.0.7857.0 --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3259e2d..d066727 100644 --- a/README.md +++ b/README.md @@ -4,10 +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/7242](https://github.com/bblanchon/pdfium-binaries/releases/tag/chromium%2F7242) +Binary release: [chromium/7857](https://github.com/bblanchon/pdfium-binaries/releases/tag/chromium%2F7857) ## Required pdfium.dll version -chromium/7242 / PDFium 139.0.7242.0 +chromium/7857 / PDFium 150.0.7857.0 ## Features - Multiple PDF load functions: