UE5 Runtime PDF Writer with LibHaru

I won’t maintain PDFium please consider to use Pandores.

LibHaru Features

  • Windows Only
  • Create PDF Files (v1.7)
  • Add pages to created PDF
  • Load Standart Fonts
  • Load External Font (UTF-8 supported. We tested it with Turkish special characters.)
  • Add Text to created PDF (including line breaks and auto text wrap like pdfium)
  • Add images to created PDF
  • Add U3D based 3D models to created PDF
  • Draw line, rectangle, arc and circle on created PDF (line width and color supported)
  • Convert LibHaru PDF object to PDFium PDF object.

DEPENDENCIES
1- External Variables Plugins. We use it for 64 bit bytes array and font enumeration.

IMPORTANT
You have to convert your 3D models to U3D extension. There are comments about Meshlab but it can’t even convert 3Ds Max default Teapot on Ryzen 9 5900HX with 64 GB DDR4 RAM. So, I suggest you to use Aspose

As you know, Unreal has an official GLTF exporter. You can export your scene and convert it to U3D. But U3D is very primitive format. So, don’t expect to visualize realistic contents and I didn’t try animated contents.

Google Chrome and other basic PDF viewers can’t see 3D contents of PDF files. You have to use professional PDF tools like Adobe Acrobat Pro.

4 Likes

Hello!

Thank you very much for sharing this plugin.
Would it be possible to make it work with UE Ver. 5.0.3?
I would like to try it out, and possibly use it for a current project but I am on ver 5.0.3 and it looked like it couldn’t properly recognize the plugin, so that would be appreciated.

Regardless thank you for sharing your work and putting the time to make this!

Kashk.Master

This is our startup’s in house plugin and we want to share it for free. So, we support engine version only what our team currently use.

and right now it is 5.1
we will update it to 5.2 roughly one month later. So, we won’t support older versions.

If anyone wants older engine’s support, it is open source project and you can follow these steps.

  1. Create C++ project
  2. Create Blueprint function library plugin with same name.
  3. Copy “Source” folder.
  4. Right click your .uproject and click Generate Visual Studio Project Files
  5. Fix referance problems. (If you create a plugin with same name, I don’t think there will any problem)

All these steps are don’t require C++ knowledge at all. If there are any referance problem, Visual Studio will say that.

1 Like

Understandable. Thank you very much for sharing your work for free!
Might try doing that or just upgrade UE myself as well. Thanks for the Tip.
Hope your startup a bright and successful future if god wills it!

Again thank you very much for your time and sharing your work.

Kashk.master

1 Like

Hello there again,

Thanks for the instructions, couldn’t get it to work though,
I did follow another guide as well, but it gave me a error for “ExtendedVer”

Would appreciate a more detailed instruction if possible.

Regardless, thank you again for all the help you provided!

Kashk.master

1- That workflow is for running an “old” plugin on newer engine but your case is exact opposite. Running a “new” plugin on older engine. Unreal Engine itself doesn’t have this kind of backward compability support.

2- You have 2 option at this point.

2A- One of them is installing 5.1. After that,

  • Create a C++ project
  • Copy that plugin to Plugins folder.
  • Generate Visual Studio Project Files → Right click to your .uproject and you will see it.
  • Open your project.sln and press F5.

I assume that you installed Visual Studio 2022.
These steps will create necessary binary files and after that you can use it with your blueprint only projects. Just copy that plugin to every other project’s plugin folder.

2B- If you insist to use older engines, look at my previous comment. I updated it. But in short, you have to create a blueprint function library plugin with same name, copy source folder, generate vs project files and change referances according to errors. (This is general workflow for my plugin’s case you have to do it for 4 time because there are 4 different plugins.)

Hello there again!

I tried the instructions you gave,
1-Made a C++ Project
2-Created the BP function library Plugin with same name
3-Copied source folder from your plugin and replaced the one from the newly created plugin
4- But when I right click on the .uproject file it doesn’t show me the Generate VS Project Files

What am I doing wrong? Also I only need to do this for the Extended Var and Pdfium plugins right? since i don’t need the functions the other two offer for the project i am working on.

Thank you for your time and instructions!

Kashk.master

Did you install Visual Studio 2022 with C++ and Game Development modules (there are two option for UE. one of them is about UE support other one is UE installation. Just select UE support)

If you installed VS 2022, check this topic.

Other than that missing context menu item has nothing to do with either our plugins or any plugins at all. It is a problem of your UE installation and I can’t help you about your IT infastructure.
(Actually I didn’t do anything to get context menu item. I have Windows 11, just installed VS 2022 with necessary modules, Android Studio and UE from Epic Launcher. If I did something special, I would tell)

and as I understand you don’t use a special source code branch which sticked to an old version like oculus branch. (Even it uses 5.1)

Even if you have an old plugin, you have to update your engine in the future in any case. (Running an old plugin/blueprint in newer engine is easier for UE) Maybe this is the time ? Don’t fear ! You can do it ! You have to power, yaay !

As I say before, I can help about “our plugin’s” problem. For example, a crash after correct installation, a deprecation warning, a package problem or a wrong result but I can’t help you about your current problem.

Hi,

I recently tried to make the Pdfium into my project and I cannot make it load properly. Do you know why? May I ask why you gave up on Pdfium and used the Pandores?

Here is the problem shortcut:

Here is my file hierarchy:
image

Here is my build.cs:

Here is how I include and use the code in the file:

And here is the error it shows when loading till 75%:

Where did I do wrong? Thanks for your reply.

Actually I didn’t give up on my project.
I had a problem about PDF save system and no one but Pandores (not even PDFium user group. They even said “we wouldn’t give help about third party integrations.” I mean this is Unreal Engine. If C++ had gain some popularity over other high level languages at latest years, it was about UE) helped me about it.

(If PDF file has big images or external fonts, callback function triggers multiple times and you have to append a global byte array with it. I didn’t understand that trick at first. It has to be global because it is C type function pointer callback. So, there is no support for lambda capture and also there is no void pointer as callback context.)

So, I promised him to buy his plugin, close my open source project and give him an access to my source code in their help’s return. (I didn’t want to be his competitor and I have some extra features for parsing. Btw. Pandores already published their plugin before I asked for help and give access to my source code.)

Right now, my implementation works perfectly as renderer, parser and writer on both Windows & Android platforms and I am using it on my projects.

You know we develope and share source codes for money, help request or at least some ratings. I didn’t seek money but some help and rating would be good. I couldn’t get any and for this reason, I closed it as promised.

//

For your problem, you have to learn DLL delayed load.

First add this to your build.cs / PrivateDependencyModuleNames
“Projects”,

After that

**Public/MergePDF.h**

class FMergePDFModule : public IModuleInterface
{
public:

	/** IModuleInterface implementation */
	virtual void StartupModule() override;
	virtual void ShutdownModule() override;

#ifdef _WIN64
	void* PDFium_Handle;
#endif
};

**Private/MergePDF.cpp**

#include "Interfaces/IPluginManager.h"

void FMergePDFModule ::StartupModule()
{
#ifdef _WIN64
	const FString BasePluginDir = IPluginManager::Get().FindPlugin("MergePDF")->GetBaseDir();
	const FString DLL_Path = FPaths::Combine(*BasePluginDir, TEXT("Source/MergePDF/ThirdParty/pdfium/Windows/lib/pdfium.dll"));
	PDFium_Handle = FPlatformProcess::GetDllHandle(*DLL_Path);

        // you have to edit that DLL_Path according to your DLL location.

	if (PDFium_Handle != nullptr)
	{
		UE_LOG(LogTemp, Log, TEXT("pdfium.dll loaded successfully!"));
	}

	else
	{
		UE_LOG(LogTemp, Fatal, TEXT("pdfium.dll failed to load!"));
	}
#endif
}
1 Like

Thanks for such a quick reply.

I understand now, I’ll learn how to delay load DLL. Thank you very much.

1 Like

I just downloaded this and upgraded it to 5.3 and it’s working very well, this plugin is a life saver, thanks :pray:

1 Like

Hi, could you please aid me in my quest to build a PDF 1:1 from a UMG? I need to export this widget below into a PDF File and i’m having trouble with adding texts, i’m using the same font and size for UMG and PDF and i’m trying to position my text in the middle of the PDF.

Problem is that i’m getting the correct size of the string in pixels but when i pass it into PDF the size gets bigger then the string.

Some configs and debug i’ve made:

  • Both UMG and PDF have a page size of 595x842 so the translation of positions should be 1:1
  • I’m using GetDesiredSize in TextBox to get the string size in px i’ve drawn a box at the UMG and this function is giving me the correct px size for the string.
  • In my PDF image below 1 is half of page size 2 is half of string size and 3 is the string size in px that was passed to the PDF. I’m using Draw Line function to draw those debug lines.

UMG BP which i need to export:

My progress so far:

So, i’m sure that i’m passing the correct size to the PDF but somehow the translation is not 1:1. Should i use 2480x3508 for PDF which is A4 Print size in pixels and translate positions using % relation between sizes? I’m really lost here and i hope you can have some insights on this.

I’ve found that if i multiply the GetDesiresSize by 0.75 before doing any position operations it’ll give me the expected result, this is probably due to some conversion that is needed to create the PDF file and perhaps if i wasn’t using 595x842 in both UMG and PDF this value would be different tho.

1 Like