#1 Re: mORMot 2 » mORMot PDF crossplatform » 2026-10-01 09:56:29

Arnaud, thanks for the detailed proposal. I left my comments in the gist.

#2 Re: mORMot 2 » mORMot PDF crossplatform » 2026-10-01 05:42:18

Hi Sven, hi Arnaud,

Sven, thank you, I gladly accept your offer, the PR as well as the further integration steps on your list. You know the trunk conventions far better than I do. I will review and test each step with Delphi 7, Delphi 2010, and FPC macOS and Linux. Thanks for spotting that mormot2.lpk shadows the fork's copy of mormot.lib.uniscribe.

The essential features are in now. If you both agree, I suggest a feature freeze until the migration into mORMot2 is done, so we don't work against each other.

Arnaud, agreed on mormot.lib.* and on no .inc files: the interfaces stay, and the FreeType and HarfBuzz imports move into their own mormot.lib.* units.

Splitting mormot.ui.pdf is welcome. A rough idea along the lines already inside the unit:

mormot.pdf.core: object model, writer, document, pages, metadata, PDF/A
mormot.pdf.font: TrueType, CMAP, font objects
mormot.pdf.canvas: drawing, text, tagged PDF
mormot.pdf.image: images, the only part needing the Graphics unit
mormot.pdf.crypt: encryption
mormot.pdf.emf: TPdfDocumentGdi, Windows only
on top: the TCanvas bridge, the report and its preview

This gives the VCL/LCL-free generator, and answers the HAS_UI_PDF question: only images, the bridge and the report need a UI framework, the Windows-only part gets its own flag. Part of it exists already; with Delphi on Linux and Android the unit builds without VCL, leaving out only the TBitmap image API. The exact boundaries will show during the work, since document, canvas and fonts reference each other. mormot.ui.pdf could stay as a thin unit of type aliases, so existing code keeps compiling.

TGDIPages as a TComponent felt right to me, but it must not break existing code. If replacing mormot.ui.report would do that, it could live next to it in the new folder, unless someone sees a more elegant way.

A PDF reader: yes, sounds interesting but challenging. A separate object model would be a good base for it. What scope do you have in mind: reading objects, metadata and attachments (e.g. the XML of a ZUGFeRD invoice), text extraction, or more?

Sven, on the invoice XML: as the author of an e-invoice library you are probably the best person to provide a sample invoice

Martin

#3 Re: mORMot 2 » mORMot PDF crossplatform » 2026-09-29 19:28:20

mORMot2 PDF Cross-Platform: from correct to usable, starting with the ZUGFeRD demo

Until now the work went into the output: one PDF, the same on Windows, Linux and macOS and from FPC, Delphi 7 and Delphi 2010, and valid. That means tagged PDF/UA-1 and PDF/A-3U, checked with veraPDF, PAC 2024 and Mustang. That goal is reached for all eight demos.

Along the way it became clear that the calls were too complicated, and the demos showed it. So the next phase is usability, and it started with zugferd_demo. It is now a plain TGDIPages report, and the page is read from the factur-x.xml it embeds.

From here on, no more drastic changes to the calls or the demos should be needed. The other demos will be simplified the same way, without changing the API.

Details are in the repo, docs/ROADMAP.md.

#4 Re: mORMot 2 » mORMot PDF crossplatform » 2026-09-28 10:48:10

mORMot2 PDF cross-platform: now on Delphi 2010 too

After Delphi 7, today it was Delphi 2010's turn, our first Unicode Delphi. Good news: the engine didn't need a single fix. All tests pass on Delphi 2010, Delphi 7 and FPC, all eight demos give the same PDFs as with Delphi 7, and PAC and veraPDF are happy.

It wasn't completely painless: my UTF-8 string constants got encoded twice, and that shook out a small bug in the XMP header. Fixed.

I can't test a current Delphi or Delphi for Linux myself because I don't have those compilers. If you do, I'd love to hear how it goes.

Details in the Github repo.

#5 Re: mORMot 2 » mORMot PDF crossplatform » 2026-09-27 22:06:59

A busy day on the PDF cross-platform port. The main news: the TCanvas bridge and TGDIPages now build on Delphi 7 too. All the console demos and the --export mode of the two GUI demos run there and produce the same PDFs as FPC, still passing PAC and veraPDF.

Heads-up, there are breaking changes:
- preview and printing moved out of TGDIPages into their own unit (mormot.ui.reportpreview)
- TGDIPages takes RawUtf8 now, and GetReportFonts/GetExportFonts return RawUtf8
- the demo PDFs have new file names

Most code should compile as before, but please check the ROADMAP ("To Announce") before you update.

#6 Re: mORMot 2 » mORMot PDF crossplatform » 2026-09-25 11:04:11

ab wrote:

Perhaps it could be worth considering integrating it back to the mormot trunk sooner or later.

We could define a new "src/pdf" folder for the units, not any more in "src/ui".
The mormot.pdf.xxxx.pas unit names just show this pattern.
wink

This is exactly what I was hoping for. It finally gives me a chance to give something back to the project.

I wasn't sure whether PDF still had enough relevance in 2026, or whether my changes were good enough to be accepted upstream.

I've been so focused on tackling cross-platform challenges like fonts, different libraries, and tagged PDF support that I kind of lost sight of other areas, such as Delphi.

And yes, integrating it with mORMot2 is definitely the way forward.

#7 Re: mORMot 2 » mORMot PDF crossplatform » 2026-09-24 19:36:18

The engine now writes PDF/A-3U and PDF/UA-1 in one file.

The new example zugferd_demo builds a ZUGFeRD / Factur-X invoice (profile EN 16931): a tagged, accessible PDF with the invoice XML embedded. The invoice data is public KoSIT test data. The result passes veraPDF, the Mustang validator and PAC 2024 on Windows, Linux and macOS.

Feedback welcome, especially if you try it with your own validator or accounting software.

#8 Re: mORMot 2 » mORMot PDF crossplatform » 2026-09-22 19:15:34

Thanks for the question, it touches on something I've been thinking about as well.

Short answer: invoice generation itself is out of scope for this project, but PDF/A-3 with file attachments is something I will look into.

A few thoughts on your setup:

- If FastReport renders your invoices, the PDF comes from FastReport's own exporter. Since this PDF engine can't modify existing PDFs, you would need to render the layout with TGDIPages instead, or check whether FastReport itself supports PDF/A-3 attachments.

- This library could provide the generic container: PDF/A-3 with embedded files like Landrix XML invoice library, combined with the existing PDF/UA tagging.

I'll put PDF/A-3 with attachments on the roadmap as a future item and validate it. By the way, a real-world invoice layout would make an excellent test case.

#9 Re: mORMot 2 » mORMot PDF crossplatform » 2026-09-21 19:11:33

Besides the cross-platform support, creating accessible PDFs was a design goal. Since the European Accessibility Act came into force on 28 June 2025, accessibility is mandatory for many PDFs published online (and it has been required for public-sector bodies for even longer).

I've made a few adjustments so that most of the examples now pass an accessibility test, carried out with the German testing tool PAC. All demos except the Chinese and RTL ones now run through the tests without any errors.

#10 mORMot 2 » mORMot PDF crossplatform » 2026-09-12 07:48:02

mdoyle
Replies: 22

I’ve been a big fan of mORMot for a long time, and I’ve used the PDF engine extensively over the years. It’s a powerful library, and I really appreciate how much it can do.

Recently, with the move to Lazarus on macOS and Linux, I became especially interested in a cross-platform solution for PDF generation and reporting. That led me to build and refine a project that abstracts the platform-specific parts and works across those environments.

This is a very complex library, so I relied heavily on Claude to help with the porting and integration work. It has been extremely useful in navigating the complexity and getting the cross-platform pieces to fit together cleanly.

The project currently includes 6 example files that demonstrate the main use cases and APIs:

direct PDF generation,
TCanvas-style usage,
report generation,
markdown/export flow,
CJK support,
RTL/Arabic text handling.

You can find the project on https://github.com/martin-doyle/mORMot2 … ssPlatform.

I’d love to hear whether this kind of cross-platform mORMot PDF/reporting project is of interest to others in the community. If there is interest, I’d be happy to share more details and examples.

Martin

#11 Re: mORMot 2 » Using TCollection inTOrm » 2023-06-20 19:34:11

Works perfectly.

TOrmOrderBook = class(TOrm)
…
public
  procedure InternalCreate;override;
procedure TOrmOrderBook.InternalCreate;
begin
  inherited InternalCreate;
  FItems := TItemCollection.Create(TItem);
end;

Thanks a lot.

#12 Re: mORMot 2 » TRecordVersion doesn't work as expected » 2023-06-19 17:48:36

It looks like BatchAdd and BatchDelete update the Version field but BatchUpdate does not..

Please find the tests in https://gist.github.com/martin-doyle/00 … ceac4698fc.

#13 Re: mORMot 2 » Using TCollection inTOrm » 2023-06-19 17:45:01

mdoyle wrote:

In mORMot1 I used to use TCollection a lot as described in the documentation in 5.5.2.1.2.3. TPersistent/TCollection fields. This also worked in mORMot2 until commit 88742d0 several ORM raw optimizations.
As far as I can see the create constructors was changed to InternalCreate which does not call the overloaded Create constructor anymore.

Create with parameters and CreateAndFiilPrepare don’t work anymore. Any recommendations how to use TCollection and TPersistance from now on?

Please see the tests in https://gist.github.com/martin-doyle/6c … a26990e46e.

#14 Re: mORMot 2 » TRecordVersion doesn't work as expected » 2023-06-05 19:46:24

Sorry again. I apologize for the inconvenience.
I tested on Linux with FPC. For Windows {$apptype console} is missing. Updated the files again. Hope it works now. Thank you for taking care.

 Replication test suite
  ------------------------


1. Test suite

 1.1. Replication simple:
  - Test add: 45 assertions passed  46.93ms
  - Test update: 97 assertions passed  14.95ms
  - Test delete: 72 assertions passed  13.42ms
  Total failed: 0 / 214  - Replication simple PASSED  80.92ms

 1.2. Replication batch:
  - Test batch add: 4,011 assertions passed  42.88ms
!  - Test batch update: 10 / 7,038 FAILED  55.69ms
  - Test batch delete: 6,968 assertions passed  56.58ms
  Total failed: 10 / 18,017  - Replication batch FAILED  159.90ms

 1.3. Replication special:
  - Test add ten and delete first record: 77 assertions passed  12.38ms
!  - Test add ten and delete last record: 3 / 77 FAILED  11.63ms
!  - Test add one and delete record: 1 / 13 FAILED  11.41ms
  Total failed: 4 / 167  - Replication special FAILED  39.53ms


Generated with: Delphi 11.3 Alexandria 32 bit Win compiler

Time elapsed for all tests: 282.22ms
Performed 2023-06-05 21:33:25 by mdoyle on WIN11

Total assertions failed for all test suits:  14 / 18,398
! Some tests FAILED: please correct the code.

#15 Re: mORMot 2 » TRecordVersion doesn't work as expected » 2023-06-05 16:18:43

Sorry, you are right. It is the one which is created in test.orm.sqlite3.pas.
I updated the gist. Please check again https://gist.github.com/martin-doyle/00 … ceac4698fc.

#17 Re: mORMot 2 » TRecordVersion doesn't work as expected » 2023-06-03 14:54:47

Thank you for sending your example. That makes your question more clear.
I did some tests. It looks like that BatchUpdate does not update the Version field. This is a highly optimized function and focuses on the „simple fields“ and time fields only.
You could use Update instead. I know that Update is slower than BatchUpdate. But at least the Version field is updated correctly.

#18 Re: mORMot 2 » TRecordVersion doesn't work as expected » 2023-06-01 20:18:25

Not sure what you try to accomplish with the Version field. I use it for master slave replication without any issues. Never checked the numbers but the result of the replication.
It is difficult helping you with this fragment of code. Please provide a working example. But please follow the forum rules and do not copy long code directly into the forum.
I do not understand your batch approach. Please check the documentation 12.3. The batch process is pretty straightforward and works for me.

#19 Re: mORMot 2 » How to compile to aarch64 Linux ? » 2023-06-01 20:04:59

I have been using mORMot 2 on aarch64 for awhile without any issues. Runs on small devices like a Raspberry, a Mac M1 with a virtual machine or in the cloud. Please search the forum for arm or aarch64.
I have no experience with CodeTyphon. I use Lazarus/FreePascal compiling native or cross compiling from Linux x86_64. The mormot2tests run just fine.

#20 Re: mORMot 2 » Using TCollection inTOrm » 2023-05-28 07:01:57

The same happens when using one of the Create functions with paramters.

Order := TOrmOrderBook.Create(TestClient.Orm, 'OrderNo = ?', ['Order1']);

The work around is currently using the Retrieve function like

Order := TOrmOrderBook.Create;
  try
    TestClient.Orm.Retrieve('OrderNo = ?', [], ['Order1'], Order); 

I updated the tests in https://gist.github.com/martin-doyle/6c … a26990e46e.

By the way, I like the idea of embedding detail data within the record (sharding). Would be interesting to know what other people use, just schemaless TDocVariant?

#21 Re: mORMot 2 » Using TCollection inTOrm » 2023-05-24 17:05:37

Thanks Thomas, that keeps me working.
I was only able finding the right commit and spot. This fix helps a lot.

#22 mORMot 2 » Using TCollection inTOrm » 2023-05-23 19:21:00

mdoyle
Replies: 9

In mORMot1 I used to use TCollection a lot as described in the documentation in 5.5.2.1.2.3. TPersistent/TCollection fields. This also worked in mORMot2 until commit 88742d0 several ORM raw optimizations.

As far as I can see the create constructor was changed to InternalCreate which does not call the overloaded Create constructor anymore.
So the TCollection is not created anymore, is null and can't be set when getting data from the database.

constructor TSQLRecordPeopleObject.Create;
begin
  inherited;
  fPersistent := TCollTst.Create;
  fUTF8 := TRawUTF8List.Create;
end;

Please find a test example in https://gist.github.com/martin-doyle/a4 … 18facfad6c.

Is TCollection still supported and what is the recommended way of using it?

#23 Re: mORMot 1 » Variant Error running mORMot tests on Debian 11 » 2022-07-10 09:58:33

Interesting that it happened right after the os upgrade. I reinstalled FPC and everything works fine. Just in case somebody else runs into the same issue.
Thanks a lot and sorry for the confusion.

#24 mORMot 1 » Variant Error running mORMot tests on Debian 11 » 2022-07-09 10:31:31

mdoyle
Replies: 3

Just updated from Debian 10 Buster to Debian11 Bullseye. Some variant tests fail using the underscore syntax.

Example TTestCoreProcess._TDocVariant => CheckDoc line 4229 Check(variant(Doc)._(0) = 'John');
Error message TDocVariant.DispInvoke: invalid (1) call
mormot.core.variants.pas lines 3430 and 3533

#25 Re: mORMot 1 » mORMot 2 ORM Performance » 2022-02-19 08:25:05

Great news. And yes it works on aarch64 as well giving similar good numbers.

#26 Re: mORMot 1 » mORMot2 on ARM » 2022-02-13 09:13:46

I kept testing on MacOS aarch64.

First, I compiled the newest sqlite3 3.37.2 and the installation worked without any problem. Then I thought, maybe compiling the static libraries works as well. I could compile armv8.c from the res directory. This made building the mormot2 package possible.
Compiling the sqlite3 library was a little trickier. I had to patch the amalgamation file on Linux since „sed“ works a little different on MacOS.

To make a long story short, I could compile and run the mormot tests with static libraries.
I had to disable a couple of tests which froze but it is a good start. https://gist.github.com/martin-doyle/0f … e9dacdc252

A first issue I found was a segmentation fault when creating the BloomFilter. ln(fFalsePositivePercent / 100) crashes. ln(0.01) works just fine. I created a little fpc test program in order to see if it is a fpc, type whatever issue. But no problem here - ln seems to work as expected but behaves strangely within the Create method of Bloomfilter.

#27 Re: mORMot 1 » mORMot2 on ARM » 2022-02-08 11:04:23

„4x generic aes sha crc aarch64 cpu“ on Linux.
„8x MacBookPro18,3 (aarch64)“ on MacOS. I just started some tests with the external sqlite 3.36.0 library. Would be interesting to do tests with the static libraries.

#28 Re: mORMot 1 » mORMot2 on ARM » 2022-02-06 19:05:57

Oops. My VM had only 2 cores with 4 GB RAM.
For 4 cores and 8GB it looks like this https://gist.github.com/martin-doyle/e0 … 22075e6de0.


cat /proc/cpuinfo does not give any information about the cpu details only some cryptic numbers. sysctl -a machdep.cpu only works on the macOS terminal. Let me further check.

#29 Re: mORMot 1 » mORMot2 on ARM » 2022-02-06 16:50:35

Wow. AAALLL green now.

Total assertions failed for all test suits:  0 / 71,390,226
! All tests passed successfully.

https://gist.Github.com/martin-doyle/a8 … 7985572920.

#30 Re: mORMot 1 » mORMot2 on ARM » 2022-02-06 08:40:06

I ran the tests several times. Please find the numbers here https://gist.github.com/martin-doyle/8b … c7d68cfd7c.

The failed tests starting at 2.1 ORM Core seem to have the same root cause. The InMemory storage reading existing data - i.e. TTestOrmCore._TRestServerFullMemory line 299 - fails due to duplicate entries. TRestStorageInMemory.LoadFromBinariy loads all entries correctly but in ComputeStateAfterLoad it seems that the PtrInt dup variable is not set in/after fValues.Hasher.ForceReHash(@dup).

#31 Re: mORMot 1 » mORMot2 on ARM » 2022-02-05 16:30:27

Please find the output from the tests on gist https://gist.github.com/martin-doyle/44 … 99bc915c56. Might be also interesting to see the numbers.

#32 Re: mORMot 1 » mORMot2 on ARM » 2022-02-05 10:54:44

OK. I checked again my setup. FPC is available for aarch64 only since version 3.2.2.
First I cross compiled from FPC 3.2.0  Debian X64 to aarch64 and I did not get the above error messages. All Variant tests were fine.
Second I reinstalled FPC fixes-3.2 and Lazarus fixes-2.2 on Debian aarch64 with FPCUPdeluxe 2.2.0h. The installed versions are now FPC 3.2.3-582-gdba65567f1 and Lazarus 2.2.0-64-gff329cf453. And guess what, no Variant test issues anymore.
There are a few tests left which fail and I will keep checking. Thanks ab and Alfred for the great job.

#33 Re: mORMot 1 » mORMot2 on ARM » 2022-02-03 20:58:59

As far as I can see the only issue with aarch64 is TDocVariant. All tests with TDocVariantData like AddValue fail. The tests with variants are fine. I do not know what to do at the moment since Step into AddValue already causes an error message -> log message TSysVariant {Message: TDocVariant.DispInvoke: invalid (1) call“} [Main] at 696618 … variants.pas (3490) variants (3597) variants (8938).

#34 mORMot 1 » mORMot2 on ARM » 2022-01-29 16:54:44

mdoyle
Replies: 46

I am wondering if ARM will be a focus target for mORMot2 in the future. Linux aarch64 is supported but I believe it is not as maintained as the x64 platform. I do not know if the Oracle cloud is still used in the current development. When running the tests there are a couple of errors.
ARM is a hot topic for Apple and Windows 11 is also available for ARM now.
I have a new Mac M1 and I got FPC and Lazarus running on MacOS which is pretty cool. A client application with ORM and HTTP already works. Next I will test a server app with external sqlite3 libs since there are no arm static files other than for Linux. So, if this interesting I would be happy to help testing and building.

Martin

#35 mORMot 1 » mORMot2 examples » 2021-02-27 07:45:51

mdoyle
Replies: 5

Good morning,

I really like the new design of mORMot2 and I assume it will increase the already breathtaking speed of development. It is just an amazing piece of software.
As others mentioned, the transition from mORMot1 is not that easy. So I started a couple of examples in my fork of the project.

https://github.com/martin-doyle/mORMot2 … rtin-doyle

The goals I want to accomplish are the following:

- Get the examples running with PUREMORMOT2 definition (done)
- The examples should work in Delphi 7 and FPC on Windows and Debian Linux (X86_64 server and client, ARM64 server only) (done, not yet tested on ARM64)
- Make the same use case work for different technical approaches like ORM, method based and interfaced based services (started, probably not yet correct)
- Create a best practice starting point for different scenarios like a standalone client only application, local network client server, client server on the internet. (open)

Any feedback is welcome.

Martin

Board footer

Powered by FluxBB