From 81d68897daa033ef7a3a236639b0fda96358b351 Mon Sep 17 00:00:00 2001 From: David Sungaila Date: Thu, 12 Oct 2023 16:26:33 +0200 Subject: [PATCH 01/10] Remove NativeLibrary.Load from .NET (Core) builds --- .../PdfiumViewer/NativeMethods.Pdfium.cs | 78 ++++---- src/PDFtoImage/PdfiumViewer/NativeMethods.cs | 173 +++--------------- 2 files changed, 62 insertions(+), 189 deletions(-) diff --git a/src/PDFtoImage/PdfiumViewer/NativeMethods.Pdfium.cs b/src/PDFtoImage/PdfiumViewer/NativeMethods.Pdfium.cs index a77ae40e..fd38de93 100644 --- a/src/PDFtoImage/PdfiumViewer/NativeMethods.Pdfium.cs +++ b/src/PDFtoImage/PdfiumViewer/NativeMethods.Pdfium.cs @@ -343,120 +343,112 @@ private static int FPDF_GetBlock(IntPtr param, uint position, IntPtr buffer, uin } #endregion - private const string _dllName = -#if NET6_0_OR_GREATER - "libpdfium" -#else - "pdfium" -#endif - ; - private static class Imports { - [DllImport(_dllName, CallingConvention = CallingConvention.Cdecl)] + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] public static extern void FPDF_InitLibrary(); - [DllImport(_dllName, CallingConvention = CallingConvention.Cdecl)] + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] public static extern void FPDF_DestroyLibrary(); - [DllImport(_dllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public static extern IntPtr FPDF_LoadCustomDocument([MarshalAs(UnmanagedType.LPStruct)] FPDF_FILEACCESS access, string? password); - [DllImport(_dllName, CallingConvention = CallingConvention.Cdecl)] + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] public static extern void FPDF_CloseDocument(IntPtr document); - [DllImport(_dllName, CallingConvention = CallingConvention.Cdecl)] + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] public static extern int FPDF_GetPageCount(IntPtr document); - [DllImport(_dllName, CallingConvention = CallingConvention.Cdecl)] + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] public static extern uint FPDF_GetDocPermissions(IntPtr document); - [DllImport(_dllName, CallingConvention = CallingConvention.Cdecl)] + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr FPDFDOC_InitFormFillEnvironment(IntPtr document, FPDF_FORMFILLINFO formInfo); - [DllImport(_dllName, CallingConvention = CallingConvention.Cdecl)] + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] public static extern void FPDF_SetFormFieldHighlightColor(IntPtr hHandle, int fieldType, uint color); - [DllImport(_dllName, CallingConvention = CallingConvention.Cdecl)] + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] public static extern void FPDF_SetFormFieldHighlightAlpha(IntPtr hHandle, byte alpha); - [DllImport(_dllName, CallingConvention = CallingConvention.Cdecl)] + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] public static extern void FORM_DoDocumentJSAction(IntPtr hHandle); - [DllImport(_dllName, CallingConvention = CallingConvention.Cdecl)] + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] public static extern void FORM_DoDocumentOpenAction(IntPtr hHandle); - [DllImport(_dllName, CallingConvention = CallingConvention.Cdecl)] + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] public static extern void FPDFDOC_ExitFormFillEnvironment(IntPtr hHandle); - [DllImport(_dllName, CallingConvention = CallingConvention.Cdecl)] + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] public static extern void FORM_DoDocumentAAction(IntPtr hHandle, FPDFDOC_AACTION aaType); - [DllImport(_dllName, CallingConvention = CallingConvention.Cdecl)] + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr FPDF_LoadPage(IntPtr document, int page_index); - [DllImport(_dllName, CallingConvention = CallingConvention.Cdecl)] + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr FPDFText_LoadPage(IntPtr page); - [DllImport(_dllName, CallingConvention = CallingConvention.Cdecl)] + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] public static extern void FORM_OnAfterLoadPage(IntPtr page, IntPtr _form); - [DllImport(_dllName, CallingConvention = CallingConvention.Cdecl)] + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] public static extern void FORM_DoPageAAction(IntPtr page, IntPtr _form, FPDFPAGE_AACTION fPDFPAGE_AACTION); - [DllImport(_dllName, CallingConvention = CallingConvention.Cdecl)] + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] public static extern double FPDF_GetPageWidth(IntPtr page); - [DllImport(_dllName, CallingConvention = CallingConvention.Cdecl)] + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] public static extern double FPDF_GetPageHeight(IntPtr page); - [DllImport(_dllName, CallingConvention = CallingConvention.Cdecl)] + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] public static extern void FORM_OnBeforeClosePage(IntPtr page, IntPtr _form); - [DllImport(_dllName, CallingConvention = CallingConvention.Cdecl)] + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] public static extern void FPDFText_ClosePage(IntPtr text_page); - [DllImport(_dllName, CallingConvention = CallingConvention.Cdecl)] + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] public static extern void FPDF_ClosePage(IntPtr page); - [DllImport(_dllName, CallingConvention = CallingConvention.Cdecl)] + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] public static extern void FPDF_RenderPageBitmap(IntPtr bitmapHandle, IntPtr page, int start_x, int start_y, int size_x, int size_y, int rotate, FPDF flags); - [DllImport(_dllName, CallingConvention = CallingConvention.Cdecl)] + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] public static extern int FPDF_GetPageSizeByIndex(IntPtr document, int page_index, out double width, out double height); - [DllImport(_dllName, CallingConvention = CallingConvention.Cdecl)] + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr FPDFBitmap_CreateEx(int width, int height, int format, IntPtr first_scan, int stride); - [DllImport(_dllName, CallingConvention = CallingConvention.Cdecl)] + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] public static extern void FPDFBitmap_FillRect(IntPtr bitmapHandle, int left, int top, int width, int height, uint color); - [DllImport(_dllName, CallingConvention = CallingConvention.Cdecl)] + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] public static extern void FPDFBitmap_Destroy(IntPtr bitmapHandle); - [DllImport(_dllName, CallingConvention = CallingConvention.Cdecl)] + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] public static extern uint FPDFDest_GetDestPageIndex(IntPtr document, IntPtr dest); - [DllImport(_dllName, CallingConvention = CallingConvention.Cdecl)] + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr FPDFBookmark_GetFirstChild(IntPtr document, IntPtr bookmark); - [DllImport(_dllName, CallingConvention = CallingConvention.Cdecl)] + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr FPDFBookmark_GetNextSibling(IntPtr document, IntPtr bookmark); - [DllImport(_dllName, CallingConvention = CallingConvention.Cdecl)] + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] public static extern uint FPDFBookmark_GetTitle(IntPtr bookmark, byte[]? buffer, uint buflen); - [DllImport(_dllName, CallingConvention = CallingConvention.Cdecl)] + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr FPDFBookmark_GetDest(IntPtr document, IntPtr bookmark); - [DllImport(_dllName, CallingConvention = CallingConvention.Cdecl)] + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] public static extern uint FPDF_GetLastError(); #region Save/Edit APIs - [DllImport(_dllName, CallingConvention = CallingConvention.Cdecl)] + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] public static extern void FPDF_FFLDraw(IntPtr form, IntPtr bitmap, IntPtr page, int start_x, int start_y, int size_x, int size_y, int rotate, FPDF flags); - [DllImport(_dllName, CallingConvention = CallingConvention.Cdecl)] + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] public static extern void FPDF_RemoveFormFieldHighlight(IntPtr form); #endregion } diff --git a/src/PDFtoImage/PdfiumViewer/NativeMethods.cs b/src/PDFtoImage/PdfiumViewer/NativeMethods.cs index ce1ff557..b6d34524 100644 --- a/src/PDFtoImage/PdfiumViewer/NativeMethods.cs +++ b/src/PDFtoImage/PdfiumViewer/NativeMethods.cs @@ -10,46 +10,12 @@ internal static partial class NativeMethods { static NativeMethods() { - string? path = null; - try - { -#if NET7_0_OR_GREATER - string workingDirectory = Assembly.GetExecutingAssembly().Location; - if (string.IsNullOrWhiteSpace(workingDirectory)) - workingDirectory = Environment.ProcessPath!; - if (string.IsNullOrWhiteSpace(workingDirectory)) - workingDirectory = AppContext.BaseDirectory; -#elif NET6_0_OR_GREATER - var workingDirectory = Assembly.GetExecutingAssembly().GetName(false).CodeBase; - if (string.IsNullOrWhiteSpace(workingDirectory)) - workingDirectory = Environment.ProcessPath!; - if (string.IsNullOrWhiteSpace(workingDirectory)) - workingDirectory = AppContext.BaseDirectory; -#else - var workingDirectory = Assembly.GetExecutingAssembly().GetName(false).CodeBase; - if (string.IsNullOrWhiteSpace(workingDirectory)) - workingDirectory = Process.GetCurrentProcess().MainModule!.FileName!; - if (string.IsNullOrWhiteSpace(workingDirectory)) - workingDirectory = AppContext.BaseDirectory; -#endif - - path = Path.GetDirectoryName(new Uri(workingDirectory).LocalPath); - } - catch (Exception) { } - - LoadNativeLibrary(path); - } - - private static void LoadNativeLibrary(string? path = null) - { #if ANDROID || MONOANDROID LoadNativeLibraryAndroid(); -#elif NET6_0_OR_GREATER - LoadNativeLibraryNetCore(path); #elif NETFRAMEWORK - LoadNativeLibraryNetFX(path); + LoadNativeLibraryNetFX(); #else - throw new PlatformNotSupportedException("Unkown framework and/or platform."); + // .NET (Core) resolves the pdfium lib on its own #endif } @@ -69,105 +35,19 @@ private static void LoadNativeLibraryAndroid() Java.Lang.JavaSystem.LoadLibrary("pdfium"); } -#elif NET6_0_OR_GREATER - private static void LoadNativeLibraryNetCore(string? path) - { - if (path == null) - return; - - string runtimeIdentifier; - string pdfiumLibName; - - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - runtimeIdentifier = RuntimeInformation.ProcessArchitecture switch - { - Architecture.X86 => "win-x86", - Architecture.X64 => "win-x64", - Architecture.Arm64 => "win-arm64", - _ => throw new PlatformNotSupportedException("Only x86-64, x86 and arm64 are supported on Windows.") - }; - pdfiumLibName = "pdfium.dll"; - } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - runtimeIdentifier = RuntimeInformation.ProcessArchitecture switch - { - Architecture.X64 => "linux-x64", - Architecture.Arm => "linux-arm", - Architecture.Arm64 => "linux-arm64", - _ => throw new PlatformNotSupportedException("Only x86-64, arm and arm64 are supported on Linux.") - }; - pdfiumLibName = "libpdfium.so"; - } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - { - runtimeIdentifier = RuntimeInformation.ProcessArchitecture switch - { - Architecture.X64 => "osx-x64", - Architecture.Arm64 => "osx-arm64", - _ => throw new PlatformNotSupportedException("Only x86-64 and arm64 are supported on macOS.") - }; - pdfiumLibName = "libpdfium.dylib"; - } - else if (OperatingSystem.IsMacCatalyst()) - { - throw new NotSupportedException("Mac Catalyst is not supported."); - } - else if (OperatingSystem.IsIOS()) - { - throw new NotSupportedException("iOS and Mac Catalyst are not supported."); - } - else if (OperatingSystem.IsTvOS()) - { - throw new NotSupportedException("tvOS is not supported."); - } - else - { - throw new NotSupportedException("Only win-x86, win-x64, win-arm64, linux-x64, linux-arm, linux-arm64, osx-x64, and osx-arm64 are supported."); - } - - LoadLibrary(path, runtimeIdentifier, pdfiumLibName); - } -#endif - -#if !MONOANDROID && !ANDROID - private static string? _pdfiumLibPath; -#endif - -#if NET6_0_OR_GREATER && !ANDROID - private static void LoadLibrary(string path, string runtimeIdentifier, string pdfiumLibName) - { - if (File.Exists(Path.Combine(path, pdfiumLibName))) - { - // dotnet publish with a given runtime identifier (not portable) will put PDFium into the root folder - _pdfiumLibPath = Path.Combine(path, pdfiumLibName); - } - else - { - // in any other case there should be a runtimes folder - _pdfiumLibPath = Path.Combine(path, "runtimes", runtimeIdentifier, "native", pdfiumLibName); - } - - NativeLibrary.SetDllImportResolver(typeof(NativeMethods).Assembly, ImportResolver); - NativeLibrary.Load(_pdfiumLibPath, Assembly.GetExecutingAssembly(), default); - } - - private static IntPtr ImportResolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath) - { - if (_pdfiumLibPath != null && libraryName != null && libraryName.Contains("pdfium")) - return NativeLibrary.Load(_pdfiumLibPath, assembly, searchPath); - - return IntPtr.Zero; - } #elif NETFRAMEWORK - private static void LoadNativeLibraryNetFX(string? path) + private static void LoadNativeLibraryNetFX() { - if (path == null) - return; + var workingDirectory = Assembly.GetExecutingAssembly().GetName(false).CodeBase; + if (string.IsNullOrWhiteSpace(workingDirectory)) + workingDirectory = Process.GetCurrentProcess().MainModule!.FileName!; + if (string.IsNullOrWhiteSpace(workingDirectory)) + workingDirectory = AppContext.BaseDirectory; + + var path = Path.GetDirectoryName(new Uri(workingDirectory).LocalPath); string runtimeIdentifier; - + #if NET471_OR_GREATER runtimeIdentifier = RuntimeInformation.ProcessArchitecture switch { @@ -184,24 +64,25 @@ private static void LoadNativeLibraryNetFX(string? path) }; #endif - _pdfiumLibPath = Path.Combine(path, runtimeIdentifier, "pdfium.dll"); - LoadLibrary(_pdfiumLibPath); + var pdfiumLibPath = Path.Combine(path, runtimeIdentifier, "pdfium.dll"); + LoadLibrary(pdfiumLibPath); } - /// Loads the specified module into the address space of the calling process. - /// - /// The name of the module. This can be either a library module (a .dll file) or an executable module (an .exe file). The name specified is the file name of the module and is not related to the name stored in the library module itself, as specified by the LIBRARY keyword in the module-definition (.def) file. If the string specifies a full path, the function searches only that path for the module. If the string specifies a relative path or a module name without a path, the function uses a standard search strategy to find the module; for more information, see the Remarks. If the function cannot find the module, the function fails. When specifying a path, be sure to use backslashes (\\), not forward slashes (/). For more information about paths, see Naming a File or Directory. If the string specifies a module name without a path and the file name extension is omitted, the function appends the default library extension .dll to the module name. To prevent the function from appending .dll to the module name, include a trailing point character (.) in the module name string. - /// Read more on docs.microsoft.com. - /// - /// - /// If the function succeeds, the return value is a handle to the module. If the function fails, the return value is NULL. To get extended error information, call GetLastError. - /// - /// - /// Learn more about this API from docs.microsoft.com. - /// - [DllImport("Kernel32", ExactSpelling = true, EntryPoint = "LoadLibraryW", SetLastError = true)] + /// Loads the specified module into the address space of the calling process. (LoadLibraryW) + /// + /// The name of the module. This can be either a library module (a .dll file) or an executable module (an .exe file). If the specified module is an executable module, static imports are not loaded; instead, the module is loaded as if by LoadLibraryEx with the `DONT_RESOLVE_DLL_REFERENCES` flag. The name specified is the file name of the module and is not related to the name stored in the library module itself, as specified by the LIBRARY keyword in the module-definition (.def) file. If the string specifies a full path, the function searches only that path for the module. If the string specifies a relative path or a module name without a path, the function uses a standard search strategy to find the module; for more information, see the Remarks. If the function cannot find the module, the function fails. When specifying a path, be sure to use backslashes (\\), not forward slashes (/). For more information about paths, see Naming a File or Directory. If the string specifies a module name without a path and the file name extension is omitted, the function appends the default library extension ".DLL" to the module name. To prevent the function from appending ".DLL" to the module name, include a trailing point character (.) in the module name string. + /// Read more on docs.microsoft.com. + /// + /// + /// If the function succeeds, the return value is a handle to the module. If the function fails, the return value is NULL. To get extended error information, call GetLastError. + /// + /// + /// To enable or disable error messages displayed by the loader during DLL loads, use the SetErrorMode function. LoadLibrary can be used to load a library module into the address space of the process and return a handle that can be used in GetProcAddress to get the address of a DLL function. LoadLibrary can also be used to load other executable modules. For example, the function can specify an .exe file to get a handle that can be used in FindResource or LoadResource. However, do not use LoadLibrary to run an .exe file. Instead, use the CreateProcess function. If the specified module is a DLL that is not already loaded for the calling process, the system calls the DLL's DllMain function with the DLL_PROCESS_ATTACH value. If DllMain returns TRUE, LoadLibrary returns a handle to the module. If DllMain returns FALSE, the system unloads the DLL from the process address space and LoadLibrary returns NULL. It is not safe to call LoadLibrary from DllMain. For more information, see the Remarks section in DllMain. Module handles are not global or inheritable. A call to LoadLibrary by one process does not produce a handle that another process can use — for example, in calling GetProcAddress. The other process must make its own call to LoadLibrary for the module before calling GetProcAddress. If lpFileName does not include a path and there is more than one loaded module with the same base name and extension, the function returns a handle to the module that was loaded first. If no file name extension is specified in the lpFileName parameter, the default library extension .dll is appended. However, the file name string can include a trailing point character (.) to indicate that the module name has no extension. When no path is specified, the function searches for loaded modules whose base name matches the base name of the module to be loaded. If the name matches, the load succeeds. Otherwise, the function searches for the file. The first directory searched is the directory containing the image file used to create the calling process (for more information, see the CreateProcess function). Doing this allows private dynamic-link library (DLL) files associated with a process to be found without adding the process's installed directory to the PATH environment variable. If a relative path is specified, the entire relative path is appended to every token in the DLL search path list. To load a module from a relative path without searching any other path, use GetFullPathName to get a nonrelative path and call LoadLibrary with the nonrelative path. For more information on the DLL search order, see Dynamic-Link Library Search Order. The search path can be altered using the SetDllDirectory function. This solution is recommended instead of using SetCurrentDirectory or hard-coding the full path to the DLL. If a path is specified and there is a redirection file for the application, the function searches for the module in the application's directory. If the module exists in the application's directory, LoadLibrary ignores the specified path and loads the module from the application's directory. If the module does not exist in the application's directory, LoadLibrary loads the module from the specified directory. For more information, see Dynamic Link Library Redirection. If you call LoadLibrary with the name of an assembly without a path specification and the assembly is listed in the system compatible manifest, the call is automatically redirected to the side-by-side assembly. The system maintains a per-process reference count on all loaded modules. Calling LoadLibrary increments the reference count. Calling the FreeLibrary or FreeLibraryAndExitThread function decrements the reference count. The system unloads a module when its reference count reaches zero or when the process terminates (regardless of the reference count). Windows Server 2003 and Windows XP:  The Visual C++ compiler supports a syntax that enables you to declare thread-local variables: _declspec(thread). If you use this syntax in a DLL, you will not be able to load the DLL explicitly using LoadLibrary on versions of Windows prior to Windows Vista. If your DLL will be loaded explicitly, you must use the thread local storage functions instead of _declspec(thread). For an example, see Using Thread Local Storage in a Dynamic Link Library.

Security Remarks

Do not use the SearchPath function to retrieve a path to a DLL for a subsequent LoadLibrary call. The SearchPath function uses a different search order than LoadLibrary and it does not use safe process search mode unless this is explicitly enabled by calling SetSearchPathMode with BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE. Therefore, SearchPath is likely to first search the user’s current working directory for the specified DLL. If an attacker has copied a malicious version of a DLL into the current working directory, the path retrieved by SearchPath will point to the malicious DLL, which LoadLibrary will then load. Do not make assumptions about the operating system version based on a LoadLibrary call that searches for a DLL. If the application is running in an environment where the DLL is legitimately not present but a malicious version of the DLL is in the search path, the malicious version of the DLL may be loaded. Instead, use the recommended techniques described in Getting the System Version.
+ /// Read more on docs.microsoft.com. + ///
+ [DllImport("kernel32.dll", ExactSpelling = true, EntryPoint = "LoadLibraryW", SetLastError = true)] [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] private static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPWStr)] string lpLibFileName); #endif } -} +} \ No newline at end of file From d3b6b1320c593634509970950c3e38f8c3c82286 Mon Sep 17 00:00:00 2001 From: David Sungaila Date: Thu, 12 Oct 2023 17:35:39 +0200 Subject: [PATCH 02/10] Use LibraryImport for .NET 7 and newer; fix WebConverter project --- .../PdfiumViewer/NativeMethods.Pdfium.cs | 1112 +++++++++-------- src/WebConverter/WebConverter.csproj | 2 +- src/WebConverter/{libpdfium.a => pdfium.a} | Bin 3 files changed, 612 insertions(+), 502 deletions(-) rename src/WebConverter/{libpdfium.a => pdfium.a} (100%) diff --git a/src/PDFtoImage/PdfiumViewer/NativeMethods.Pdfium.cs b/src/PDFtoImage/PdfiumViewer/NativeMethods.Pdfium.cs index fd38de93..4cb320c3 100644 --- a/src/PDFtoImage/PdfiumViewer/NativeMethods.Pdfium.cs +++ b/src/PDFtoImage/PdfiumViewer/NativeMethods.Pdfium.cs @@ -5,317 +5,307 @@ namespace PDFtoImage.PdfiumViewer { -#pragma warning disable SYSLIB1054 // LibraryImportAttribute cannot substitute most of the following DllImportAttributes - internal static partial class NativeMethods - { - // Interned strings are cached over AppDomains. This means that when we - // lock on this string, we actually lock over AppDomain's. The Pdfium - // library is not thread safe, and this way of locking - // guarantees that we don't access the Pdfium library from different - // threads, even when there are multiple AppDomain's in play. - private static readonly string LockString = string.Intern("e362349b-001d-4cb2-bf55-a71606a3e36f"); - - public static void FPDF_InitLibrary() - { - lock (LockString) - { - Imports.FPDF_InitLibrary(); - } - } - - public static void FPDF_DestroyLibrary() - { - lock (LockString) - { - Imports.FPDF_DestroyLibrary(); - } - } - - public static void FPDF_CloseDocument(IntPtr document) - { - lock (LockString) - { - Imports.FPDF_CloseDocument(document); - } - } - - public static int FPDF_GetPageCount(IntPtr document) - { - lock (LockString) - { - return Imports.FPDF_GetPageCount(document); - } - } - - public static uint FPDF_GetDocPermissions(IntPtr document) - { - lock (LockString) - { - return Imports.FPDF_GetDocPermissions(document); - } - } - - public static IntPtr FPDFDOC_InitFormFillEnvironment(IntPtr document, FPDF_FORMFILLINFO formInfo) - { - lock (LockString) - { - return Imports.FPDFDOC_InitFormFillEnvironment(document, formInfo); - } - } - - public static void FPDF_SetFormFieldHighlightColor(IntPtr hHandle, int fieldType, uint color) - { - lock (LockString) - { - Imports.FPDF_SetFormFieldHighlightColor(hHandle, fieldType, color); - } - } - - public static void FPDF_SetFormFieldHighlightAlpha(IntPtr hHandle, byte alpha) - { - lock (LockString) - { - Imports.FPDF_SetFormFieldHighlightAlpha(hHandle, alpha); - } - } - - public static void FORM_DoDocumentJSAction(IntPtr hHandle) - { - lock (LockString) - { - Imports.FORM_DoDocumentJSAction(hHandle); - } - } - - public static void FORM_DoDocumentOpenAction(IntPtr hHandle) - { - lock (LockString) - { - Imports.FORM_DoDocumentOpenAction(hHandle); - } - } - - public static void FPDFDOC_ExitFormFillEnvironment(IntPtr hHandle) - { - lock (LockString) - { - Imports.FPDFDOC_ExitFormFillEnvironment(hHandle); - } - } - - public static void FORM_DoDocumentAAction(IntPtr hHandle, FPDFDOC_AACTION aaType) - { - lock (LockString) - { - Imports.FORM_DoDocumentAAction(hHandle, aaType); - } - } - - public static IntPtr FPDF_LoadPage(IntPtr document, int page_index) - { - lock (LockString) - { - return Imports.FPDF_LoadPage(document, page_index); - } - } - - public static IntPtr FPDFText_LoadPage(IntPtr page) - { - lock (LockString) - { - return Imports.FPDFText_LoadPage(page); - } - } - - public static void FORM_OnAfterLoadPage(IntPtr page, IntPtr _form) - { - lock (LockString) - { - Imports.FORM_OnAfterLoadPage(page, _form); - } - } - - public static void FORM_DoPageAAction(IntPtr page, IntPtr _form, FPDFPAGE_AACTION fPDFPAGE_AACTION) - { - lock (LockString) - { - Imports.FORM_DoPageAAction(page, _form, fPDFPAGE_AACTION); - } - } - - public static double FPDF_GetPageWidth(IntPtr page) - { - lock (LockString) - { - return Imports.FPDF_GetPageWidth(page); - } - } - - public static double FPDF_GetPageHeight(IntPtr page) - { - lock (LockString) - { - return Imports.FPDF_GetPageHeight(page); - } - } - - public static void FORM_OnBeforeClosePage(IntPtr page, IntPtr _form) - { - lock (LockString) - { - Imports.FORM_OnBeforeClosePage(page, _form); - } - } - - public static void FPDFText_ClosePage(IntPtr text_page) - { - lock (LockString) - { - Imports.FPDFText_ClosePage(text_page); - } - } - - public static void FPDF_ClosePage(IntPtr page) - { - lock (LockString) - { - Imports.FPDF_ClosePage(page); - } - } - - public static void FPDF_RenderPageBitmap(IntPtr bitmapHandle, IntPtr page, int start_x, int start_y, int size_x, int size_y, int rotate, FPDF flags) - { - lock (LockString) - { - Imports.FPDF_RenderPageBitmap(bitmapHandle, page, start_x, start_y, size_x, size_y, rotate, flags); - } - } - - public static int FPDF_GetPageSizeByIndex(IntPtr document, int page_index, out double width, out double height) - { - lock (LockString) - { - return Imports.FPDF_GetPageSizeByIndex(document, page_index, out width, out height); - } - } - - public static IntPtr FPDFBitmap_CreateEx(int width, int height, int format, IntPtr first_scan, int stride) - { - lock (LockString) - { - return Imports.FPDFBitmap_CreateEx(width, height, format, first_scan, stride); - } - } - - public static void FPDFBitmap_FillRect(IntPtr bitmapHandle, int left, int top, int width, int height, uint color) - { - lock (LockString) - { - Imports.FPDFBitmap_FillRect(bitmapHandle, left, top, width, height, color); - } - } - - public static void FPDFBitmap_Destroy(IntPtr bitmapHandle) - { - lock (LockString) - { - Imports.FPDFBitmap_Destroy(bitmapHandle); - } - } - - public static uint FPDFDest_GetDestPageIndex(IntPtr document, IntPtr dest) - { - lock (LockString) - { - return Imports.FPDFDest_GetDestPageIndex(document, dest); - } - } - - public static IntPtr FPDF_BookmarkGetFirstChild(IntPtr document, IntPtr bookmark) - { - lock (LockString) - return Imports.FPDFBookmark_GetFirstChild(document, bookmark); - } - - public static IntPtr FPDF_BookmarkGetNextSibling(IntPtr document, IntPtr bookmark) - { - lock (LockString) - return Imports.FPDFBookmark_GetNextSibling(document, bookmark); - } - - public static uint FPDF_BookmarkGetTitle(IntPtr bookmark, byte[]? buffer, uint buflen) - { - lock (LockString) - return Imports.FPDFBookmark_GetTitle(bookmark, buffer, buflen); - } - - public static IntPtr FPDF_BookmarkGetDest(IntPtr document, IntPtr bookmark) - { - lock (LockString) - return Imports.FPDFBookmark_GetDest(document, bookmark); - } - - /// - /// Opens a document using a .NET Stream. Allows opening huge - /// PDFs without loading them into memory first. - /// - /// The input Stream. Don't dispose prior to closing the pdf. - /// Password, if the PDF is protected. Can be null. - /// Retrieves an IntPtr to the COM object for the Stream. The caller must release this with Marshal.Release prior to Disposing the Stream. - /// An IntPtr to the FPDF_DOCUMENT object. - - public static +#pragma warning disable CA2101 // Specify marshalling for P/Invoke string arguments +#pragma warning disable SYSLIB1054 // Use LibraryImportAttribute instead of DllImportAttribute to generate p/invoke marshalling code at compile time. + internal static partial class NativeMethods + { + // Interned strings are cached over AppDomains. This means that when we + // lock on this string, we actually lock over AppDomain's. The Pdfium + // library is not thread safe, and this way of locking + // guarantees that we don't access the Pdfium library from different + // threads, even when there are multiple AppDomain's in play. + private static readonly string LockString = string.Intern("e362349b-001d-4cb2-bf55-a71606a3e36f"); + + public static void FPDF_InitLibrary() + { + lock (LockString) + { + Imports.FPDF_InitLibrary(); + } + } + + public static void FPDF_DestroyLibrary() + { + lock (LockString) + { + Imports.FPDF_DestroyLibrary(); + } + } + + public static void FPDF_CloseDocument(IntPtr document) + { + lock (LockString) + { + Imports.FPDF_CloseDocument(document); + } + } + + public static int FPDF_GetPageCount(IntPtr document) + { + lock (LockString) + { + return Imports.FPDF_GetPageCount(document); + } + } + + public static uint FPDF_GetDocPermissions(IntPtr document) + { + lock (LockString) + { + return Imports.FPDF_GetDocPermissions(document); + } + } + + public static IntPtr FPDFDOC_InitFormFillEnvironment(IntPtr document, FPDF_FORMFILLINFO formInfo) + { + lock (LockString) + { + return Imports.FPDFDOC_InitFormFillEnvironment(document, formInfo); + } + } + + public static void FPDF_SetFormFieldHighlightColor(IntPtr hHandle, int fieldType, uint color) + { + lock (LockString) + { + Imports.FPDF_SetFormFieldHighlightColor(hHandle, fieldType, color); + } + } + + public static void FPDF_SetFormFieldHighlightAlpha(IntPtr hHandle, byte alpha) + { + lock (LockString) + { + Imports.FPDF_SetFormFieldHighlightAlpha(hHandle, alpha); + } + } + + public static void FORM_DoDocumentJSAction(IntPtr hHandle) + { + lock (LockString) + { + Imports.FORM_DoDocumentJSAction(hHandle); + } + } + + public static void FORM_DoDocumentOpenAction(IntPtr hHandle) + { + lock (LockString) + { + Imports.FORM_DoDocumentOpenAction(hHandle); + } + } + + public static void FORM_DoDocumentAAction(IntPtr hHandle, FPDFDOC_AACTION aaType) + { + lock (LockString) + { + Imports.FORM_DoDocumentAAction(hHandle, aaType); + } + } + + public static IntPtr FPDF_LoadPage(IntPtr document, int page_index) + { + lock (LockString) + { + return Imports.FPDF_LoadPage(document, page_index); + } + } + + public static IntPtr FPDFText_LoadPage(IntPtr page) + { + lock (LockString) + { + return Imports.FPDFText_LoadPage(page); + } + } + + public static void FORM_OnAfterLoadPage(IntPtr page, IntPtr _form) + { + lock (LockString) + { + Imports.FORM_OnAfterLoadPage(page, _form); + } + } + + public static void FORM_DoPageAAction(IntPtr page, IntPtr _form, FPDFPAGE_AACTION fPDFPAGE_AACTION) + { + lock (LockString) + { + Imports.FORM_DoPageAAction(page, _form, fPDFPAGE_AACTION); + } + } + + public static double FPDF_GetPageWidth(IntPtr page) + { + lock (LockString) + { + return Imports.FPDF_GetPageWidth(page); + } + } + + public static double FPDF_GetPageHeight(IntPtr page) + { + lock (LockString) + { + return Imports.FPDF_GetPageHeight(page); + } + } + + public static void FORM_OnBeforeClosePage(IntPtr page, IntPtr _form) + { + lock (LockString) + { + Imports.FORM_OnBeforeClosePage(page, _form); + } + } + + public static void FPDFText_ClosePage(IntPtr text_page) + { + lock (LockString) + { + Imports.FPDFText_ClosePage(text_page); + } + } + + public static void FPDF_ClosePage(IntPtr page) + { + lock (LockString) + { + Imports.FPDF_ClosePage(page); + } + } + + public static void FPDF_RenderPageBitmap(IntPtr bitmapHandle, IntPtr page, int start_x, int start_y, int size_x, int size_y, int rotate, FPDF flags) + { + lock (LockString) + { + Imports.FPDF_RenderPageBitmap(bitmapHandle, page, start_x, start_y, size_x, size_y, rotate, flags); + } + } + + public static int FPDF_GetPageSizeByIndex(IntPtr document, int page_index, out double width, out double height) + { + lock (LockString) + { + return Imports.FPDF_GetPageSizeByIndex(document, page_index, out width, out height); + } + } + + public static IntPtr FPDFBitmap_CreateEx(int width, int height, int format, IntPtr first_scan, int stride) + { + lock (LockString) + { + return Imports.FPDFBitmap_CreateEx(width, height, format, first_scan, stride); + } + } + + public static void FPDFBitmap_FillRect(IntPtr bitmapHandle, int left, int top, int width, int height, uint color) + { + lock (LockString) + { + Imports.FPDFBitmap_FillRect(bitmapHandle, left, top, width, height, color); + } + } + + public static void FPDFBitmap_Destroy(IntPtr bitmapHandle) + { + lock (LockString) + { + Imports.FPDFBitmap_Destroy(bitmapHandle); + } + } + + public static uint FPDFDest_GetDestPageIndex(IntPtr document, IntPtr dest) + { + lock (LockString) + { + return Imports.FPDFDest_GetDestPageIndex(document, dest); + } + } + + public static IntPtr FPDF_BookmarkGetFirstChild(IntPtr document, IntPtr bookmark) + { + lock (LockString) + return Imports.FPDFBookmark_GetFirstChild(document, bookmark); + } + + public static IntPtr FPDF_BookmarkGetNextSibling(IntPtr document, IntPtr bookmark) + { + lock (LockString) + return Imports.FPDFBookmark_GetNextSibling(document, bookmark); + } + + public static uint FPDF_BookmarkGetTitle(IntPtr bookmark, byte[]? buffer, uint buflen) + { + lock (LockString) + return Imports.FPDFBookmark_GetTitle(bookmark, buffer, buflen); + } + + public static IntPtr FPDF_BookmarkGetDest(IntPtr document, IntPtr bookmark) + { + lock (LockString) + return Imports.FPDFBookmark_GetDest(document, bookmark); + } + + /// + /// Opens a document using a .NET Stream. Allows opening huge + /// PDFs without loading them into memory first. + /// + /// The input Stream. Don't dispose prior to closing the pdf. + /// Password, if the PDF is protected. Can be null. + /// Retrieves an IntPtr to the COM object for the Stream. The caller must release this with Marshal.Release prior to Disposing the Stream. + /// An IntPtr to the FPDF_DOCUMENT object. + + public static #if NET6_0_OR_GREATER - unsafe + unsafe #endif - IntPtr FPDF_LoadCustomDocument(Stream input, string? password, int id) - { + IntPtr FPDF_LoadCustomDocument(Stream input, string? password, int id) + { #if NET6_0_OR_GREATER - delegate* unmanaged[Cdecl] getBlock = &FPDF_GetBlock; + delegate* unmanaged[Cdecl] getBlock = &FPDF_GetBlock; #else var getBlock = Marshal.GetFunctionPointerForDelegate(_getBlockDelegate); #endif - var access = new FPDF_FILEACCESS - { - m_FileLen = (uint)input.Length, - m_GetBlock = getBlock, - m_Param = (IntPtr)id - }; - - lock (LockString) - { - return Imports.FPDF_LoadCustomDocument(access, password); - } - } - - public static FPDF_ERR FPDF_GetLastError() - { - lock (LockString) - { - return (FPDF_ERR)Imports.FPDF_GetLastError(); - } - } - - #region Save / Edit Methods - public static void FPDF_FFLDraw(IntPtr form, IntPtr bitmap, IntPtr page, int start_x, int start_y, int size_x, int size_y, int rotate, FPDF flags) - { - lock (LockString) - { - Imports.FPDF_FFLDraw(form, bitmap, page, start_x, start_y, size_x, size_y, rotate, flags); - } - } - - public static void FPDF_RemoveFormFieldHighlight(IntPtr form) - { - lock (LockString) - { - Imports.FPDF_RemoveFormFieldHighlight(form); - } - } - #endregion - - #region Custom Load/Save Logic + var access = new FPDF_FILEACCESS + { + m_FileLen = (uint)input.Length, + m_GetBlock = getBlock, + m_Param = (IntPtr)id + }; + + lock (LockString) + { + return Imports.FPDF_LoadCustomDocument(access, password); + } + } + + public static FPDF_ERR FPDF_GetLastError() + { + lock (LockString) + { + return (FPDF_ERR)Imports.FPDF_GetLastError(); + } + } + + public static void FPDF_FFLDraw(IntPtr form, IntPtr bitmap, IntPtr page, int start_x, int start_y, int size_x, int size_y, int rotate, FPDF flags) + { + lock (LockString) + { + Imports.FPDF_FFLDraw(form, bitmap, page, start_x, start_y, size_x, size_y, rotate, flags); + } + } + + public static void FPDF_RemoveFormFieldHighlight(IntPtr form) + { + lock (LockString) + { + Imports.FPDF_RemoveFormFieldHighlight(form); + } + } + #if !NET6_0_OR_GREATER [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate int FPDF_GetBlockDelegate(IntPtr param, uint position, IntPtr buffer, uint size); @@ -324,289 +314,409 @@ public static void FPDF_RemoveFormFieldHighlight(IntPtr form) #endif #if NET6_0_OR_GREATER - [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] + [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] #endif - private static int FPDF_GetBlock(IntPtr param, uint position, IntPtr buffer, uint size) - { - var stream = StreamManager.Get(checked((int)param)); - if (stream == null) - return 0; - byte[] managedBuffer = new byte[size]; + private static int FPDF_GetBlock(IntPtr param, uint position, IntPtr buffer, uint size) + { + var stream = StreamManager.Get(checked((int)param)); + if (stream == null) + return 0; + byte[] managedBuffer = new byte[size]; + + stream.Position = position; + int read = stream.Read(managedBuffer, 0, (int)size); + if (read != size) + return 0; + + Marshal.Copy(managedBuffer, 0, buffer, (int)size); + return 1; + } + + private static partial class Imports + { +#if NET7_0_OR_GREATER + [LibraryImport("pdfium")] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + public static partial void FPDF_InitLibrary(); + + [LibraryImport("pdfium")] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + public static partial void FPDF_DestroyLibrary(); + + [LibraryImport("pdfium")] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + public static partial void FPDF_CloseDocument(IntPtr document); + + [LibraryImport("pdfium")] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + public static partial int FPDF_GetPageCount(IntPtr document); + + [LibraryImport("pdfium")] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + public static partial uint FPDF_GetDocPermissions(IntPtr document); + + [LibraryImport("pdfium")] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + public static partial void FPDF_SetFormFieldHighlightColor(IntPtr hHandle, int fieldType, uint color); + + [LibraryImport("pdfium")] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + public static partial void FPDF_SetFormFieldHighlightAlpha(IntPtr hHandle, byte alpha); + + [LibraryImport("pdfium")] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + public static partial void FORM_DoDocumentJSAction(IntPtr hHandle); + + [LibraryImport("pdfium")] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + public static partial void FORM_DoDocumentOpenAction(IntPtr hHandle); + + [LibraryImport("pdfium")] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + public static partial void FORM_DoDocumentAAction(IntPtr hHandle, FPDFDOC_AACTION aaType); + + [LibraryImport("pdfium")] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + public static partial IntPtr FPDF_LoadPage(IntPtr document, int page_index); + + [LibraryImport("pdfium")] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + public static partial IntPtr FPDFText_LoadPage(IntPtr page); + + [LibraryImport("pdfium")] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + public static partial void FORM_OnAfterLoadPage(IntPtr page, IntPtr _form); + + [LibraryImport("pdfium")] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + public static partial void FORM_DoPageAAction(IntPtr page, IntPtr _form, FPDFPAGE_AACTION fPDFPAGE_AACTION); + + [LibraryImport("pdfium")] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + public static partial double FPDF_GetPageWidth(IntPtr page); + + [LibraryImport("pdfium")] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + public static partial double FPDF_GetPageHeight(IntPtr page); + + [LibraryImport("pdfium")] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + public static partial void FORM_OnBeforeClosePage(IntPtr page, IntPtr _form); + + [LibraryImport("pdfium")] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + public static partial void FPDFText_ClosePage(IntPtr text_page); + + [LibraryImport("pdfium")] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + public static partial void FPDF_ClosePage(IntPtr page); + + [LibraryImport("pdfium")] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + public static partial void FPDF_RenderPageBitmap(IntPtr bitmapHandle, IntPtr page, int start_x, int start_y, int size_x, int size_y, int rotate, FPDF flags); + + [LibraryImport("pdfium")] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + public static partial int FPDF_GetPageSizeByIndex(IntPtr document, int page_index, out double width, out double height); + + [LibraryImport("pdfium")] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + public static partial IntPtr FPDFBitmap_CreateEx(int width, int height, int format, IntPtr first_scan, int stride); + + [LibraryImport("pdfium")] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + public static partial void FPDFBitmap_FillRect(IntPtr bitmapHandle, int left, int top, int width, int height, uint color); + + [LibraryImport("pdfium")] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + public static partial void FPDFBitmap_Destroy(IntPtr bitmapHandle); + + [LibraryImport("pdfium")] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + public static partial uint FPDFDest_GetDestPageIndex(IntPtr document, IntPtr dest); + + [LibraryImport("pdfium")] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + public static partial IntPtr FPDFBookmark_GetFirstChild(IntPtr document, IntPtr bookmark); + + [LibraryImport("pdfium")] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + public static partial IntPtr FPDFBookmark_GetNextSibling(IntPtr document, IntPtr bookmark); - stream.Position = position; - int read = stream.Read(managedBuffer, 0, (int)size); - if (read != size) - return 0; + [LibraryImport("pdfium")] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + public static partial uint FPDFBookmark_GetTitle(IntPtr bookmark, byte[]? buffer, uint buflen); - Marshal.Copy(managedBuffer, 0, buffer, (int)size); - return 1; - } - #endregion + [LibraryImport("pdfium")] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + public static partial IntPtr FPDFBookmark_GetDest(IntPtr document, IntPtr bookmark); - private static class Imports - { - [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] - public static extern void FPDF_InitLibrary(); + [LibraryImport("pdfium")] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + public static partial uint FPDF_GetLastError(); - [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] - public static extern void FPDF_DestroyLibrary(); + [LibraryImport("pdfium")] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + public static partial void FPDF_FFLDraw(IntPtr form, IntPtr bitmap, IntPtr page, int start_x, int start_y, int size_x, int size_y, int rotate, FPDF flags); - [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] - public static extern IntPtr FPDF_LoadCustomDocument([MarshalAs(UnmanagedType.LPStruct)] FPDF_FILEACCESS access, string? password); + [LibraryImport("pdfium")] + [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] + public static partial void FPDF_RemoveFormFieldHighlight(IntPtr form); +#else + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] + public static extern void FPDF_InitLibrary(); - [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] - public static extern void FPDF_CloseDocument(IntPtr document); + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] + public static extern void FPDF_DestroyLibrary(); - [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] - public static extern int FPDF_GetPageCount(IntPtr document); + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] + public static extern void FPDF_CloseDocument(IntPtr document); - [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] - public static extern uint FPDF_GetDocPermissions(IntPtr document); + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] + public static extern int FPDF_GetPageCount(IntPtr document); - [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] - public static extern IntPtr FPDFDOC_InitFormFillEnvironment(IntPtr document, FPDF_FORMFILLINFO formInfo); + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] + public static extern uint FPDF_GetDocPermissions(IntPtr document); - [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] - public static extern void FPDF_SetFormFieldHighlightColor(IntPtr hHandle, int fieldType, uint color); + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] + public static extern void FPDF_SetFormFieldHighlightColor(IntPtr hHandle, int fieldType, uint color); - [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] - public static extern void FPDF_SetFormFieldHighlightAlpha(IntPtr hHandle, byte alpha); + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] + public static extern void FPDF_SetFormFieldHighlightAlpha(IntPtr hHandle, byte alpha); - [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] - public static extern void FORM_DoDocumentJSAction(IntPtr hHandle); + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] + public static extern void FORM_DoDocumentJSAction(IntPtr hHandle); - [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] - public static extern void FORM_DoDocumentOpenAction(IntPtr hHandle); + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] + public static extern void FORM_DoDocumentOpenAction(IntPtr hHandle); - [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] - public static extern void FPDFDOC_ExitFormFillEnvironment(IntPtr hHandle); + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] + public static extern void FORM_DoDocumentAAction(IntPtr hHandle, FPDFDOC_AACTION aaType); - [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] - public static extern void FORM_DoDocumentAAction(IntPtr hHandle, FPDFDOC_AACTION aaType); + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr FPDF_LoadPage(IntPtr document, int page_index); - [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] - public static extern IntPtr FPDF_LoadPage(IntPtr document, int page_index); + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr FPDFText_LoadPage(IntPtr page); - [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] - public static extern IntPtr FPDFText_LoadPage(IntPtr page); + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] + public static extern void FORM_OnAfterLoadPage(IntPtr page, IntPtr _form); - [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] - public static extern void FORM_OnAfterLoadPage(IntPtr page, IntPtr _form); + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] + public static extern void FORM_DoPageAAction(IntPtr page, IntPtr _form, FPDFPAGE_AACTION fPDFPAGE_AACTION); - [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] - public static extern void FORM_DoPageAAction(IntPtr page, IntPtr _form, FPDFPAGE_AACTION fPDFPAGE_AACTION); + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] + public static extern double FPDF_GetPageWidth(IntPtr page); - [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] - public static extern double FPDF_GetPageWidth(IntPtr page); + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] + public static extern double FPDF_GetPageHeight(IntPtr page); - [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] - public static extern double FPDF_GetPageHeight(IntPtr page); + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] + public static extern void FORM_OnBeforeClosePage(IntPtr page, IntPtr _form); - [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] - public static extern void FORM_OnBeforeClosePage(IntPtr page, IntPtr _form); + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] + public static extern void FPDFText_ClosePage(IntPtr text_page); - [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] - public static extern void FPDFText_ClosePage(IntPtr text_page); + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] + public static extern void FPDF_ClosePage(IntPtr page); - [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] - public static extern void FPDF_ClosePage(IntPtr page); + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] + public static extern void FPDF_RenderPageBitmap(IntPtr bitmapHandle, IntPtr page, int start_x, int start_y, int size_x, int size_y, int rotate, FPDF flags); - [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] - public static extern void FPDF_RenderPageBitmap(IntPtr bitmapHandle, IntPtr page, int start_x, int start_y, int size_x, int size_y, int rotate, FPDF flags); + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] + public static extern int FPDF_GetPageSizeByIndex(IntPtr document, int page_index, out double width, out double height); - [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] - public static extern int FPDF_GetPageSizeByIndex(IntPtr document, int page_index, out double width, out double height); + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr FPDFBitmap_CreateEx(int width, int height, int format, IntPtr first_scan, int stride); - [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] - public static extern IntPtr FPDFBitmap_CreateEx(int width, int height, int format, IntPtr first_scan, int stride); + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] + public static extern void FPDFBitmap_FillRect(IntPtr bitmapHandle, int left, int top, int width, int height, uint color); - [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] - public static extern void FPDFBitmap_FillRect(IntPtr bitmapHandle, int left, int top, int width, int height, uint color); + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] + public static extern void FPDFBitmap_Destroy(IntPtr bitmapHandle); - [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] - public static extern void FPDFBitmap_Destroy(IntPtr bitmapHandle); + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] + public static extern uint FPDFDest_GetDestPageIndex(IntPtr document, IntPtr dest); - [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] - public static extern uint FPDFDest_GetDestPageIndex(IntPtr document, IntPtr dest); + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr FPDFBookmark_GetFirstChild(IntPtr document, IntPtr bookmark); - [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] - public static extern IntPtr FPDFBookmark_GetFirstChild(IntPtr document, IntPtr bookmark); + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr FPDFBookmark_GetNextSibling(IntPtr document, IntPtr bookmark); - [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] - public static extern IntPtr FPDFBookmark_GetNextSibling(IntPtr document, IntPtr bookmark); + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] + public static extern uint FPDFBookmark_GetTitle(IntPtr bookmark, byte[]? buffer, uint buflen); - [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] - public static extern uint FPDFBookmark_GetTitle(IntPtr bookmark, byte[]? buffer, uint buflen); + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr FPDFBookmark_GetDest(IntPtr document, IntPtr bookmark); - [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] - public static extern IntPtr FPDFBookmark_GetDest(IntPtr document, IntPtr bookmark); + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] + public static extern uint FPDF_GetLastError(); - [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] - public static extern uint FPDF_GetLastError(); + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] + public static extern void FPDF_FFLDraw(IntPtr form, IntPtr bitmap, IntPtr page, int start_x, int start_y, int size_x, int size_y, int rotate, FPDF flags); - #region Save/Edit APIs - [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] - public static extern void FPDF_FFLDraw(IntPtr form, IntPtr bitmap, IntPtr page, int start_x, int start_y, int size_x, int size_y, int rotate, FPDF flags); + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] + public static extern void FPDF_RemoveFormFieldHighlight(IntPtr form); +#endif - [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] - public static extern void FPDF_RemoveFormFieldHighlight(IntPtr form); - #endregion - } + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + public static extern IntPtr FPDF_LoadCustomDocument(FPDF_FILEACCESS access, string? password); - [StructLayout(LayoutKind.Sequential)] - public class FPDF_FORMFILLINFO - { - public int version; + [DllImport("pdfium", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr FPDFDOC_InitFormFillEnvironment(IntPtr document, FPDF_FORMFILLINFO formInfo); + } - private readonly IntPtr Release; + [StructLayout(LayoutKind.Sequential)] + public class FPDF_FORMFILLINFO + { + public int version; - private readonly IntPtr FFI_Invalidate; + private readonly IntPtr Release; - private readonly IntPtr FFI_OutputSelectedRect; + private readonly IntPtr FFI_Invalidate; - private readonly IntPtr FFI_SetCursor; + private readonly IntPtr FFI_OutputSelectedRect; - private readonly IntPtr FFI_SetTimer; + private readonly IntPtr FFI_SetCursor; - private readonly IntPtr FFI_KillTimer; + private readonly IntPtr FFI_SetTimer; - private readonly IntPtr FFI_GetLocalTime; + private readonly IntPtr FFI_KillTimer; - private readonly IntPtr FFI_OnChange; + private readonly IntPtr FFI_GetLocalTime; - private readonly IntPtr FFI_GetPage; + private readonly IntPtr FFI_OnChange; - private readonly IntPtr FFI_GetCurrentPage; + private readonly IntPtr FFI_GetPage; - private readonly IntPtr FFI_GetRotation; + private readonly IntPtr FFI_GetCurrentPage; - private readonly IntPtr FFI_ExecuteNamedAction; + private readonly IntPtr FFI_GetRotation; - private readonly IntPtr FFI_SetTextFieldFocus; + private readonly IntPtr FFI_ExecuteNamedAction; - private readonly IntPtr FFI_DoURIAction; + private readonly IntPtr FFI_SetTextFieldFocus; - private readonly IntPtr FFI_DoGoToAction; + private readonly IntPtr FFI_DoURIAction; - private readonly IntPtr m_pJsPlatform; + private readonly IntPtr FFI_DoGoToAction; - // XFA support i.e. version 2 + private readonly IntPtr m_pJsPlatform; - private readonly IntPtr FFI_DisplayCaret; + private readonly IntPtr FFI_DisplayCaret; - private readonly IntPtr FFI_GetCurrentPageIndex; + private readonly IntPtr FFI_GetCurrentPageIndex; - private readonly IntPtr FFI_SetCurrentPage; + private readonly IntPtr FFI_SetCurrentPage; - private readonly IntPtr FFI_GotoURL; + private readonly IntPtr FFI_GotoURL; - private readonly IntPtr FFI_GetPageViewRect; + private readonly IntPtr FFI_GetPageViewRect; - private readonly IntPtr FFI_PageEvent; + private readonly IntPtr FFI_PageEvent; - private readonly IntPtr FFI_PopupMenu; + private readonly IntPtr FFI_PopupMenu; - private readonly IntPtr FFI_OpenFile; + private readonly IntPtr FFI_OpenFile; - private readonly IntPtr FFI_EmailTo; + private readonly IntPtr FFI_EmailTo; - private readonly IntPtr FFI_UploadTo; + private readonly IntPtr FFI_UploadTo; - private readonly IntPtr FFI_GetPlatform; + private readonly IntPtr FFI_GetPlatform; - private readonly IntPtr FFI_GetLanguage; + private readonly IntPtr FFI_GetLanguage; - private readonly IntPtr FFI_DownloadFromURL; + private readonly IntPtr FFI_DownloadFromURL; - private readonly IntPtr FFI_PostRequestURL; + private readonly IntPtr FFI_PostRequestURL; - private readonly IntPtr FFI_PutRequestURL; - } + private readonly IntPtr FFI_PutRequestURL; + } - public enum FPDFDOC_AACTION - { - WC = 0x10, - WS = 0x11, - DS = 0x12, - WP = 0x13, - DP = 0x14 - } + public enum FPDFDOC_AACTION + { + WC = 0x10, + WS = 0x11, + DS = 0x12, + WP = 0x13, + DP = 0x14 + } - public enum FPDFPAGE_AACTION - { - OPEN = 0, - CLOSE = 1 - } + public enum FPDFPAGE_AACTION + { + OPEN = 0, + CLOSE = 1 + } - [Flags] - public enum FPDF - { - ANNOT = 0x01, - LCD_TEXT = 0x02, - NO_NATIVETEXT = 0x04, - GRAYSCALE = 0x08, - DEBUG_INFO = 0x80, - NO_CATCH = 0x100, - RENDER_LIMITEDIMAGECACHE = 0x200, - RENDER_FORCEHALFTONE = 0x400, - PRINTING = 0x800, - REVERSE_BYTE_ORDER = 0x10 - } + [Flags] + public enum FPDF + { + ANNOT = 0x01, + LCD_TEXT = 0x02, + NO_NATIVETEXT = 0x04, + GRAYSCALE = 0x08, + DEBUG_INFO = 0x80, + NO_CATCH = 0x100, + RENDER_LIMITEDIMAGECACHE = 0x200, + RENDER_FORCEHALFTONE = 0x400, + PRINTING = 0x800, + REVERSE_BYTE_ORDER = 0x10 + } - public enum FPDF_ERR : uint - { - /// - /// No error. - /// - SUCCESS = 0, + public enum FPDF_ERR : uint + { + /// + /// No error. + /// + SUCCESS = 0, - /// - /// Unknown error. - /// - UNKNOWN = 1, + /// + /// Unknown error. + /// + UNKNOWN = 1, - /// - /// File not found or could not be opened. - /// - FILE = 2, + /// + /// File not found or could not be opened. + /// + FILE = 2, - /// - /// File not in PDF format or corrupted. - /// - FORMAT = 3, + /// + /// File not in PDF format or corrupted. + /// + FORMAT = 3, - /// - /// Password required or incorrect password. - /// - PASSWORD = 4, + /// + /// Password required or incorrect password. + /// + PASSWORD = 4, - /// - /// Unsupported security scheme. - /// - SECURITY = 5, + /// + /// Unsupported security scheme. + /// + SECURITY = 5, - /// - /// Page not found or content error. - /// - PAGE = 6 - } + /// + /// Page not found or content error. + /// + PAGE = 6 + } - #region Save/Edit Structs and Flags - [StructLayout(LayoutKind.Sequential)] - public + [StructLayout(LayoutKind.Sequential)] + public #if NET6_0_OR_GREATER - unsafe + unsafe #endif - class FPDF_FILEACCESS - { - public uint m_FileLen; + class FPDF_FILEACCESS + { + public uint m_FileLen; #if NET6_0_OR_GREATER - public delegate* unmanaged[Cdecl] m_GetBlock; + public delegate* unmanaged[Cdecl] m_GetBlock; #else public IntPtr m_GetBlock; #endif - public IntPtr m_Param; - } - #endregion - } + public IntPtr m_Param; + } + } } \ No newline at end of file diff --git a/src/WebConverter/WebConverter.csproj b/src/WebConverter/WebConverter.csproj index f1aa840a..d618c702 100644 --- a/src/WebConverter/WebConverter.csproj +++ b/src/WebConverter/WebConverter.csproj @@ -52,7 +52,7 @@ - + diff --git a/src/WebConverter/libpdfium.a b/src/WebConverter/pdfium.a similarity index 100% rename from src/WebConverter/libpdfium.a rename to src/WebConverter/pdfium.a From 9367d0abf1a2d0659a5e00d84a907745a30ebf29 Mon Sep 17 00:00:00 2001 From: David Sungaila Date: Thu, 12 Oct 2023 20:11:44 +0200 Subject: [PATCH 03/10] Removed Java.Lang.JavaSystem.LoadLibrary for Android; added test projects --- src/Console/Console.csproj | 2 +- .../AspNetCore/AspNetCore.csproj | 25 + src/FrameworkTests/AspNetCore/Program.cs | 35 + .../AspNetCore/Properties/launchSettings.json | 37 + .../AspNetCore/appsettings.Development.json | 8 + .../AspNetCore/appsettings.json | 9 + .../AspNetCore/wwwroot/SocialPreview.pdf | Bin 0 -> 28704 bytes src/FrameworkTests/MauiApp/App.xaml | 15 + src/FrameworkTests/MauiApp/App.xaml.cs | 12 + src/FrameworkTests/MauiApp/AppShell.xaml | 14 + src/FrameworkTests/MauiApp/AppShell.xaml.cs | 10 + src/FrameworkTests/MauiApp/MainPage.xaml | 37 + src/FrameworkTests/MauiApp/MainPage.xaml.cs | 28 + src/FrameworkTests/MauiApp/MauiApp.csproj | 59 + src/FrameworkTests/MauiApp/MauiProgram.cs | 25 + .../Platforms/Android/AndroidManifest.xml | 6 + .../MauiApp/Platforms/Android/MainActivity.cs | 11 + .../Platforms/Android/MainApplication.cs | 16 + .../Android/Resources/values/colors.xml | 6 + .../Platforms/MacCatalyst/AppDelegate.cs | 10 + .../MauiApp/Platforms/MacCatalyst/Info.plist | 30 + .../MauiApp/Platforms/MacCatalyst/Program.cs | 16 + .../MauiApp/Platforms/Tizen/Main.cs | 17 + .../Platforms/Tizen/tizen-manifest.xml | 15 + .../MauiApp/Platforms/Windows/App.xaml | 6 + .../MauiApp/Platforms/Windows/App.xaml.cs | 24 + .../Platforms/Windows/Package.appxmanifest | 46 + .../MauiApp/Platforms/Windows/app.manifest | 15 + .../MauiApp/Platforms/iOS/AppDelegate.cs | 10 + .../MauiApp/Platforms/iOS/Info.plist | 32 + .../MauiApp/Platforms/iOS/Program.cs | 16 + .../MauiApp/Properties/launchSettings.json | 8 + .../MauiApp/Resources/AppIcon/appicon.svg | 4 + .../MauiApp/Resources/AppIcon/appiconfg.svg | 8 + .../Resources/Fonts/OpenSans-Regular.ttf | Bin 0 -> 107276 bytes .../Resources/Fonts/OpenSans-Semibold.ttf | Bin 0 -> 111164 bytes .../MauiApp/Resources/Images/dotnet_bot.svg | 93 + .../MauiApp/Resources/Raw/AboutAssets.txt | 15 + .../MauiApp/Resources/Raw/SocialPreview.pdf | Bin 0 -> 28704 bytes .../MauiApp/Resources/Splash/splash.svg | 8 + .../MauiApp/Resources/Styles/Colors.xaml | 44 + .../MauiApp/Resources/Styles/Styles.xaml | 405 + .../MonoAndroid/Assets/AboutAssets.txt | 19 + .../MonoAndroid/MainActivity.cs | 77 + .../MonoAndroid/MonoAndroid.csproj | 133 + .../Properties/AndroidManifest.xml | 6 + .../MonoAndroid/Properties/AssemblyInfo.cs | 26 + .../MonoAndroid/Resources/AboutResources.txt | 44 + .../Resources/Resource.designer.cs | 9205 +++++++++++++++++ .../Resources/layout/activity_main.xml | 32 + .../Resources/layout/content_main.xml | 16 + .../MonoAndroid/Resources/menu/menu_main.xml | 9 + .../mipmap-anydpi-v26/ic_launcher.xml | 5 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 + .../Resources/mipmap-hdpi/ic_launcher.png | Bin 0 -> 1634 bytes .../mipmap-hdpi/ic_launcher_foreground.png | Bin 0 -> 1441 bytes .../mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 3552 bytes .../Resources/mipmap-mdpi/ic_launcher.png | Bin 0 -> 1362 bytes .../mipmap-mdpi/ic_launcher_foreground.png | Bin 0 -> 958 bytes .../mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 2413 bytes .../Resources/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 2307 bytes .../mipmap-xhdpi/ic_launcher_foreground.png | Bin 0 -> 2056 bytes .../mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 4858 bytes .../Resources/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 3871 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 0 -> 3403 bytes .../mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 8001 bytes .../Resources/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 5016 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 0 -> 4889 bytes .../mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 10893 bytes .../MonoAndroid/Resources/values/colors.xml | 6 + .../MonoAndroid/Resources/values/dimens.xml | 3 + .../values/ic_launcher_background.xml | 4 + .../MonoAndroid/Resources/values/strings.xml | 4 + .../MonoAndroid/Resources/values/styles.xml | 20 + src/PDFtoImage.sln | 37 + src/PDFtoImage/PDFtoImage.csproj | 6 +- src/PDFtoImage/PdfiumViewer/NativeMethods.cs | 24 +- src/PDFtoImage/PdfiumViewer/PdfFile.cs | 13 + src/WebConverter/WebConverter.csproj | 2 +- 79 files changed, 10847 insertions(+), 26 deletions(-) create mode 100644 src/FrameworkTests/AspNetCore/AspNetCore.csproj create mode 100644 src/FrameworkTests/AspNetCore/Program.cs create mode 100644 src/FrameworkTests/AspNetCore/Properties/launchSettings.json create mode 100644 src/FrameworkTests/AspNetCore/appsettings.Development.json create mode 100644 src/FrameworkTests/AspNetCore/appsettings.json create mode 100644 src/FrameworkTests/AspNetCore/wwwroot/SocialPreview.pdf create mode 100644 src/FrameworkTests/MauiApp/App.xaml create mode 100644 src/FrameworkTests/MauiApp/App.xaml.cs create mode 100644 src/FrameworkTests/MauiApp/AppShell.xaml create mode 100644 src/FrameworkTests/MauiApp/AppShell.xaml.cs create mode 100644 src/FrameworkTests/MauiApp/MainPage.xaml create mode 100644 src/FrameworkTests/MauiApp/MainPage.xaml.cs create mode 100644 src/FrameworkTests/MauiApp/MauiApp.csproj create mode 100644 src/FrameworkTests/MauiApp/MauiProgram.cs create mode 100644 src/FrameworkTests/MauiApp/Platforms/Android/AndroidManifest.xml create mode 100644 src/FrameworkTests/MauiApp/Platforms/Android/MainActivity.cs create mode 100644 src/FrameworkTests/MauiApp/Platforms/Android/MainApplication.cs create mode 100644 src/FrameworkTests/MauiApp/Platforms/Android/Resources/values/colors.xml create mode 100644 src/FrameworkTests/MauiApp/Platforms/MacCatalyst/AppDelegate.cs create mode 100644 src/FrameworkTests/MauiApp/Platforms/MacCatalyst/Info.plist create mode 100644 src/FrameworkTests/MauiApp/Platforms/MacCatalyst/Program.cs create mode 100644 src/FrameworkTests/MauiApp/Platforms/Tizen/Main.cs create mode 100644 src/FrameworkTests/MauiApp/Platforms/Tizen/tizen-manifest.xml create mode 100644 src/FrameworkTests/MauiApp/Platforms/Windows/App.xaml create mode 100644 src/FrameworkTests/MauiApp/Platforms/Windows/App.xaml.cs create mode 100644 src/FrameworkTests/MauiApp/Platforms/Windows/Package.appxmanifest create mode 100644 src/FrameworkTests/MauiApp/Platforms/Windows/app.manifest create mode 100644 src/FrameworkTests/MauiApp/Platforms/iOS/AppDelegate.cs create mode 100644 src/FrameworkTests/MauiApp/Platforms/iOS/Info.plist create mode 100644 src/FrameworkTests/MauiApp/Platforms/iOS/Program.cs create mode 100644 src/FrameworkTests/MauiApp/Properties/launchSettings.json create mode 100644 src/FrameworkTests/MauiApp/Resources/AppIcon/appicon.svg create mode 100644 src/FrameworkTests/MauiApp/Resources/AppIcon/appiconfg.svg create mode 100644 src/FrameworkTests/MauiApp/Resources/Fonts/OpenSans-Regular.ttf create mode 100644 src/FrameworkTests/MauiApp/Resources/Fonts/OpenSans-Semibold.ttf create mode 100644 src/FrameworkTests/MauiApp/Resources/Images/dotnet_bot.svg create mode 100644 src/FrameworkTests/MauiApp/Resources/Raw/AboutAssets.txt create mode 100644 src/FrameworkTests/MauiApp/Resources/Raw/SocialPreview.pdf create mode 100644 src/FrameworkTests/MauiApp/Resources/Splash/splash.svg create mode 100644 src/FrameworkTests/MauiApp/Resources/Styles/Colors.xaml create mode 100644 src/FrameworkTests/MauiApp/Resources/Styles/Styles.xaml create mode 100644 src/FrameworkTests/MonoAndroid/Assets/AboutAssets.txt create mode 100644 src/FrameworkTests/MonoAndroid/MainActivity.cs create mode 100644 src/FrameworkTests/MonoAndroid/MonoAndroid.csproj create mode 100644 src/FrameworkTests/MonoAndroid/Properties/AndroidManifest.xml create mode 100644 src/FrameworkTests/MonoAndroid/Properties/AssemblyInfo.cs create mode 100644 src/FrameworkTests/MonoAndroid/Resources/AboutResources.txt create mode 100644 src/FrameworkTests/MonoAndroid/Resources/Resource.designer.cs create mode 100644 src/FrameworkTests/MonoAndroid/Resources/layout/activity_main.xml create mode 100644 src/FrameworkTests/MonoAndroid/Resources/layout/content_main.xml create mode 100644 src/FrameworkTests/MonoAndroid/Resources/menu/menu_main.xml create mode 100644 src/FrameworkTests/MonoAndroid/Resources/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 src/FrameworkTests/MonoAndroid/Resources/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 src/FrameworkTests/MonoAndroid/Resources/mipmap-hdpi/ic_launcher.png create mode 100644 src/FrameworkTests/MonoAndroid/Resources/mipmap-hdpi/ic_launcher_foreground.png create mode 100644 src/FrameworkTests/MonoAndroid/Resources/mipmap-hdpi/ic_launcher_round.png create mode 100644 src/FrameworkTests/MonoAndroid/Resources/mipmap-mdpi/ic_launcher.png create mode 100644 src/FrameworkTests/MonoAndroid/Resources/mipmap-mdpi/ic_launcher_foreground.png create mode 100644 src/FrameworkTests/MonoAndroid/Resources/mipmap-mdpi/ic_launcher_round.png create mode 100644 src/FrameworkTests/MonoAndroid/Resources/mipmap-xhdpi/ic_launcher.png create mode 100644 src/FrameworkTests/MonoAndroid/Resources/mipmap-xhdpi/ic_launcher_foreground.png create mode 100644 src/FrameworkTests/MonoAndroid/Resources/mipmap-xhdpi/ic_launcher_round.png create mode 100644 src/FrameworkTests/MonoAndroid/Resources/mipmap-xxhdpi/ic_launcher.png create mode 100644 src/FrameworkTests/MonoAndroid/Resources/mipmap-xxhdpi/ic_launcher_foreground.png create mode 100644 src/FrameworkTests/MonoAndroid/Resources/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 src/FrameworkTests/MonoAndroid/Resources/mipmap-xxxhdpi/ic_launcher.png create mode 100644 src/FrameworkTests/MonoAndroid/Resources/mipmap-xxxhdpi/ic_launcher_foreground.png create mode 100644 src/FrameworkTests/MonoAndroid/Resources/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 src/FrameworkTests/MonoAndroid/Resources/values/colors.xml create mode 100644 src/FrameworkTests/MonoAndroid/Resources/values/dimens.xml create mode 100644 src/FrameworkTests/MonoAndroid/Resources/values/ic_launcher_background.xml create mode 100644 src/FrameworkTests/MonoAndroid/Resources/values/strings.xml create mode 100644 src/FrameworkTests/MonoAndroid/Resources/values/styles.xml diff --git a/src/Console/Console.csproj b/src/Console/Console.csproj index 5cf1137b..5f421d3e 100644 --- a/src/Console/Console.csproj +++ b/src/Console/Console.csproj @@ -7,7 +7,7 @@ PDFtoImage.Console PDFtoImage.Console PDFtoImage.Console.Program - 2.4.2 + 2.5.0 Debug;Release;ReleaseSigned diff --git a/src/FrameworkTests/AspNetCore/AspNetCore.csproj b/src/FrameworkTests/AspNetCore/AspNetCore.csproj new file mode 100644 index 00000000..9ef4ebb5 --- /dev/null +++ b/src/FrameworkTests/AspNetCore/AspNetCore.csproj @@ -0,0 +1,25 @@ + + + + net7.0 + enable + enable + PDFtoImage.FrameworkTests.AspNetCore + PDFtoImage.FrameworkTests.AspNetCore + + + + + + + + + + + + + Always + + + + \ No newline at end of file diff --git a/src/FrameworkTests/AspNetCore/Program.cs b/src/FrameworkTests/AspNetCore/Program.cs new file mode 100644 index 00000000..3b1268bb --- /dev/null +++ b/src/FrameworkTests/AspNetCore/Program.cs @@ -0,0 +1,35 @@ +namespace PDFtoImage.FrameworkTests.AspNetCore +{ + public class Program + { + private static IWebHostEnvironment? _hostingEnvironment; + + public static void Main(string[] args) + { + var builder = WebApplication.CreateBuilder(args); + var app = builder.Build(); + + _hostingEnvironment = app.Services.GetService(); + + app.MapGet("/", GetOutput); + + app.Run(); + } + + private static string GetOutput() + { + try + { + using var input = new FileStream(Path.Combine(_hostingEnvironment!.WebRootPath, "SocialPreview.pdf"), FileMode.Open, FileAccess.Read); + + using var bitmap = PDFtoImage.Conversion.ToImage(input); + + return $"SocialPreview.pdf size: {bitmap.Width}x{bitmap.Height}"; + } + catch (Exception ex) + { + return ex.ToString(); + } + } + } +} \ No newline at end of file diff --git a/src/FrameworkTests/AspNetCore/Properties/launchSettings.json b/src/FrameworkTests/AspNetCore/Properties/launchSettings.json new file mode 100644 index 00000000..1b1caecb --- /dev/null +++ b/src/FrameworkTests/AspNetCore/Properties/launchSettings.json @@ -0,0 +1,37 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:23307", + "sslPort": 44323 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "http://localhost:5005", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "https://localhost:7074;http://localhost:5005", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/src/FrameworkTests/AspNetCore/appsettings.Development.json b/src/FrameworkTests/AspNetCore/appsettings.Development.json new file mode 100644 index 00000000..0c208ae9 --- /dev/null +++ b/src/FrameworkTests/AspNetCore/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/src/FrameworkTests/AspNetCore/appsettings.json b/src/FrameworkTests/AspNetCore/appsettings.json new file mode 100644 index 00000000..10f68b8c --- /dev/null +++ b/src/FrameworkTests/AspNetCore/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/src/FrameworkTests/AspNetCore/wwwroot/SocialPreview.pdf b/src/FrameworkTests/AspNetCore/wwwroot/SocialPreview.pdf new file mode 100644 index 0000000000000000000000000000000000000000..09c5ab2dcb5e1c93754ad2767e5784993285a6e6 GIT binary patch literal 28704 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 NgvH9Lps9%Ue*i+d*kk|z literal 0 HcmV?d00001 diff --git a/src/FrameworkTests/MauiApp/App.xaml b/src/FrameworkTests/MauiApp/App.xaml new file mode 100644 index 00000000..66a5b30c --- /dev/null +++ b/src/FrameworkTests/MauiApp/App.xaml @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/src/FrameworkTests/MauiApp/App.xaml.cs b/src/FrameworkTests/MauiApp/App.xaml.cs new file mode 100644 index 00000000..cc3657b2 --- /dev/null +++ b/src/FrameworkTests/MauiApp/App.xaml.cs @@ -0,0 +1,12 @@ +namespace PDFtoImage.FrameworkTests.MauiApp +{ + public partial class App : Application + { + public App() + { + InitializeComponent(); + + MainPage = new AppShell(); + } + } +} \ No newline at end of file diff --git a/src/FrameworkTests/MauiApp/AppShell.xaml b/src/FrameworkTests/MauiApp/AppShell.xaml new file mode 100644 index 00000000..afe07697 --- /dev/null +++ b/src/FrameworkTests/MauiApp/AppShell.xaml @@ -0,0 +1,14 @@ + + + + + + diff --git a/src/FrameworkTests/MauiApp/AppShell.xaml.cs b/src/FrameworkTests/MauiApp/AppShell.xaml.cs new file mode 100644 index 00000000..a2fa8066 --- /dev/null +++ b/src/FrameworkTests/MauiApp/AppShell.xaml.cs @@ -0,0 +1,10 @@ +namespace PDFtoImage.FrameworkTests.MauiApp +{ + public partial class AppShell : Shell + { + public AppShell() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/src/FrameworkTests/MauiApp/MainPage.xaml b/src/FrameworkTests/MauiApp/MainPage.xaml new file mode 100644 index 00000000..ffdb6166 --- /dev/null +++ b/src/FrameworkTests/MauiApp/MainPage.xaml @@ -0,0 +1,37 @@ + + + + + + + + +