#1 Re: PDF Engine » PDF Info (title etc) not saved in PDF version >1.3 » 2023-12-29 11:18:59

Thank you very much for your attempt, and thanks to this I found out the problem.
I was using pdf.UseOptionalContent := true; after setting the Info data, and this will not work.
So the correct way to use it is setting the UseOptionalContent to true as first thing, then setting the Info data.

This is indeed documented in the code, so it was an overlook on my part, my mistake.
Thank you again.

#2 PDF Engine » PDF Info (title etc) not saved in PDF version >1.3 » 2023-12-28 12:26:02

padule
Replies: 2

If I put a custom title in the PDF Info, it works as long as the PDF version is 1.3.
Whenever I use a function that bumps the PDF version to >1.3 (eg. pdf.UseOptionalContent := true;) then the PDF Info is not saved anymore, and the title is lost.

Is this normal?

#3 Re: PDF Engine » Drawing dashed lines on VCLCanvas » 2023-09-08 10:20:35

rvk wrote:

BTW. Can you share your code to create your clipping example. I would like to throw it though the clipping fix to see if that works correctly (especially at the edges).

Sure, here is a simple example function (you can plug it into the example project I shared some time ago to test it with the various buttons for pdf, canvas, printer).

procedure Draw2(Handle:HDC);
var Graphics: TGPGraphics;
    Pen: TGPPen;
    Texture: TGPImage;
    path: TGPGraphicsPath;
    brush: TGPBrush;
begin
    Graphics:= TGPGraphics.Create(Handle);
    Pen:= TGPPen.Create(MakeColor(255,0,0,255),1);
    Pen.SetLineCap(LineCapRound,LineCapRound,DashCapRound);
    Texture:= TGPImage.Create('C:\texture.bmp');
    brush:= TGPTextureBrush.Create(Texture, MakeRect(0,0,Texture.GetWidth,Texture.GetHeight));

    //draw shape
    path:= TGPGraphicsPath.Create();
    path.AddLine(70,15,160,80);
    path.AddLine(160,80,20,185);
    path.AddLine(20,185,70,15);
    Graphics.FillPath(brush,path);
    Graphics.DrawPath(Pen,path);
    FreeAndNil(path);

    FreeAndNil(brush);
    FreeAndNil(Texture);
    FreeAndNil(Pen);
    FreeAndNil(Graphics);
end;

#4 Re: PDF Engine » Drawing dashed lines on VCLCanvas » 2023-09-08 09:14:41

I made an experiment with this.

We observed that the dashed lines are "simulated" by drawing many ellipses.
I think the problem is that the clipping doesn't work correctly. The stroke should be clipped to the boundaries of the ellipses, so that the resulting line is the correct width. As the clipping doesn't work the result is a fatter line.

So, here is my experiment: I draw a simple triangle with a texture inside, and it is not clipped on PDF via mormot.ui.pdf.
Again, the same code works correctly on canvas and on printer (the texture is clipped to the shape).

PlS9zsj.jpg

What do you think?

#5 Re: PDF Engine » Drawing dashed lines on VCLCanvas » 2023-09-06 19:00:17

I found this on stackoverflow, which shows the exact same problem with TMetaFile and dashed lines:
https://stackoverflow.com/questions/763 … ile-canvas

Unfortunately, no solution there.

#6 Re: PDF Engine » Drawing dashed lines on VCLCanvas » 2023-09-06 12:59:45

I still have one question though.

You confirmed that in the "print as pdf" file that I posted, the dashed line is still created as many segments (ellipses) and not as a real dashed line.
How does it display correctly then? What does it do differently?

#7 Re: PDF Engine » Drawing dashed lines on VCLCanvas » 2023-09-06 08:48:47

Hello rvk,

I think you are on the right track with this.
The MetaFile (emf) is just a list of GDI commands.
After a bit of googling, apparently, there is a different format (emf+) for GDI+, so here is where probably the incompatibility arises.
I had read that mormot.ui.pdf uses MetaFiles internally, but wasn't aware of the incompatibility.

So now I don't know what to do next hmm

#8 Re: PDF Engine » Drawing dashed lines on VCLCanvas » 2023-09-05 18:57:17

I really appreciate your efforts, did you look at the PDF I linked in the previous post? https://file.io/jwK2sU2v0k2J  (3Kb)

This was done with the same code just by printing on the Microsoft PDF printer.

In your previous post you were able to look into the PDF file internal commands, maybe you can look into this and see how it is done properly to achieve the correct result.

Since the printer canvas and the PDF file can handle the result well, the problem must be somewhere between the GDI and the way the mormot.ui.pdf library reads it.

#9 Re: PDF Engine » Drawing dashed lines on VCLCanvas » 2023-09-05 14:36:37

Here is the PDF created with the Microsoft PDF printer (correct with both solid and dashed line with width=1): https://file.io/jwK2sU2v0k2J  (3Kb)

rvk wrote:

So it seems that GDI itself translate the dashed line itself to many multiple fragments (and calls to LineTo).

Actually, I don't really care as long as the result is correct.

#10 Re: PDF Engine » Drawing dashed lines on VCLCanvas » 2023-09-05 14:03:25

rvk wrote:

Hi, a non-expert here... wink

Thank you for taking your time to look into this


rvk wrote:

I'm not sure if this is a PDF thing.
(if you create plain PDF with only vector line is it possible to create a 1pixel dashed line?)

In my small example program, you can use the print button to print on PDF using a PDF printer (eg. change 'My Printer' with 'Microsoft Print on PDF', included in Windows).
The resulting PDF of the print will be perfect (both lines with width=1), so it is not a limitation of the PDF format, it must be something in the mormot pdf library.

#11 Re: PDF Engine » Drawing dashed lines on VCLCanvas » 2023-09-05 10:33:10

ab wrote:

...in a way incompatible with what the PDF library can handle.

Yes, that's what I thought.

Now for the steps going forward.

Since everything seems to be working, except this, I am inclined to think that it could be fixed.
Do you think there are some intrinsic limitations within the pdf library itself which makes this impossible at the moment?

If you think it can be fixed, it would be helpful if you could point me roughly to the code where this is handled and I'll see if I can fix it myself.

#12 Re: PDF Engine » Drawing dashed lines on VCLCanvas » 2023-09-04 12:08:39

Hello,

I prepared a stand-alone sample code, as requested.
Please note that the code is minimalist (no "try finally", error checking etc) for the sake of the example.

Here is the main function that does the drawing.
It does not use any external library, except mormot.ui.pdf.
It draws two lines, one solid line for reference, one dashed line. Both lines are drawn with a width=1 but the dashed line is wider on PDF.

uses mormot.ui.pdf, Winapi.GDIPAPI, Winapi.GDIPOBJ;

procedure Draw(Handle:HDC);
const Dashed: array [0..1] of Single = (5,4);
var Graphics: TGPGraphics;
    Pen: TGPPen;
    path: TGPGraphicsPath;
begin
    Graphics:= TGPGraphics.Create(Handle);
    Pen:= TGPPen.Create(MakeColor(255,0,0,255),1);
    Pen.SetLineCap(LineCapRound,LineCapRound,DashCapRound);

    //normal line
    path:= TGPGraphicsPath.Create();
    path.AddLine(30,500,40,40);
    path.AddLine(40,40,300,50);
    Graphics.DrawPath(Pen,path);
    FreeAndNil(path);

    //dashed line
    Pen.SetColor(MakeColor(255,0,255,0));
    Pen.SetDashPattern(@Dashed,2);
    path:= TGPGraphicsPath.Create();
    path.AddLine(50,500,60,60);
    path.AddLine(60,60,300,70);
    Graphics.DrawPath(Pen,path);
    FreeAndNil(path);

    FreeAndNil(Pen);
    FreeAndNil(Graphics);
end;

You can then call the drawing function like this, to save on PDF:

procedure DrawOnPdf;
var pdf: TPdfDocumentGDI;
begin
    pdf:= TPdfDocumentGDI.Create;
    pdf.AddPage;
    Draw(pdf.VclCanvas.Handle);
    pdf.SaveToFile('C:\test.pdf');
end;

If you want to check, you can also draw on a form canvas, or even print the drawing (add Vcl.Printers in the uses) like this.
Both on the form and on printer, the drawing is correct (both lines have same width).

procedure DrawOnForm;
begin
    Draw(Form1.Canvas.Handle);
end;

procedure DrawOnPrinter;
begin
    Printer.PrinterIndex:= Printer.Printers.IndexOf('My Printer');
    Printer.BeginDoc;
    Draw(Printer.Canvas.Handle);
    Printer.EndDoc;
end;

I also created a small self-contained project demonstrating the above, with a form and three buttons to perform the three types of drawing (form, pdf, print).
You can download it here: https://file.io/pTvvnrYbisxY  (54Kb).

Thank you.

#13 Re: PDF Engine » Drawing dashed lines on VCLCanvas » 2023-08-29 14:32:26

ab wrote:

I don't know which library you are using for GDI+ rendering,

The Delphi Winapi.GDPIAPI, which is just a wrapper for the original Microsoft's gdiplus.dll library.


ab wrote:

usually it uses bitmap rendering over the VCL/GDI canvas handle.
So you loose most of the PDF vector benefits.

As you can see from the screenshots I added above, I can zoom into the pdf without any quality loss, so it is vector it seems.


ab wrote:

My guess is that it is more a problem of your GDI+ library, or how you use it, than a mormot.ui.pdf issue.
Or at least some confusion between how GDI, GDI+ and PDF are implemented and do interact.

This same code is used to draw on screen, on PDF and even on a printer, just by feeding it a different canvas handle.
The drawing is correct on screen and on printer, but wrong on PDF. It works even if I use a PDF printer, like Bullzip etc.

This is the only thing I found so far that doesn't work with the mormot.ui.pdf.


ab wrote:

A fully stand-alone and reproducible sample code could help.

I will try that, thank you.

#14 Re: PDF Engine » Drawing dashed lines on VCLCanvas » 2023-08-29 14:17:35

rvk wrote:

Also, to begin with, you might want to check if this line doesn't produce a GetLastStatus <> Ok error:
(and what error it does produce, since the problem is that you get a solid line)

There is no error there.
The solid line in the screenshot is an example for reference (correct), the problem is with the dashed line which, despite using width=1 the same as the solid line, it is drawn much bigger.

#15 Re: PDF Engine » Drawing dashed lines on VCLCanvas » 2023-08-29 12:37:03

Hello,

Thank you for taking the time to look into this.
Maybe I should have mentioned that I use GDI+ to draw on the VCLCanvas. It works really fine, except for this problem with dotted lines.

I have a function I use to set the pen property values:

procedure TDrawDriver.SetPen(Color:TGPColor;Width:Single;Dash:TDashType);
begin
    //Pen is a TGPPen
    Pen.SetColor(Color);
    Pen.SetWidth(Width);
    Pen.SetLineCap(LineCapRound,LineCapRound,DashCapRound);
    //Dash is an array eg. (5,3,5,3) for a dash
    Pen.SetDashPattern(@Dash,4);
    if Pen.GetLastStatus<>Ok then Pen.SetDashStyle(DashStyleSolid);
end;

Then the actual drawing is done like this (simplified):

procedure TDrawDriver.DrawLine(line:TLine);
var path: TGPGraphicsPath;
     i: integer;
begin
    SetPen(line.Color,line.Width,line.Dash);
    path:= TGPGraphicsPath.Create();
    for i:=0 to line.Points.Count-2 do begin
        path.AddLine(line.Points[i].X,line.Points[i].Y,line.Points[i+1].X,line.Points[i+1].Y);
    end;

    //Graphics is a TGPGraphics created like:
    //Graphics:= TGPGraphics.Create(pdf.VclCanvas.Handle);
    Graphics.DrawPath(Pen,path);
    FreeAndNil(path);
end;

Here is the result. Both lines are width=1. The solid line is correct, the dashed line is drawn much bigger.

JaAxoQ5.png

I also noticed that the line cap doesn't work correctly with dashed lines, just magnifying the corner here. The line cap was set as round.

bhuENjX.png

Any idea?
Thank you.

#16 PDF Engine » Drawing dashed lines on VCLCanvas » 2023-08-28 14:21:58

padule
Replies: 37

Hello everyone,

Drawing a simple dashed line using the VCLCanvas will always draw the line at a specific line width, regardless of the width I set the pen to.
Drawing non-dotted lines works fine.

I passed half a day browsing through the source code (mormot.ui.pdf) trying to find the culprit, but I could not find it, I guess I don't yet have a good enough knowledge of the internals.

Any idea what could cause this?
Thank you.

#18 Re: PDF Engine » VCLCanvas and Optional Content (layers) » 2023-07-25 12:23:16

Hello again ab,

Regarding the latest commit above, I spotted a bug that doesn't mark the end of the optional content.

The GdiComment for pgcEndMarkContent has a size of 1 (just the identifier) while in the EnumEMFFunc for the EMR_GDICOMMENT checks the data size to be >1, thus failing in case of the pgcEndMarkContent. (mortmot.ui.pdf.pas ~line 10939)

I hope my explanation is clear, if you need further info let me know.

#19 Re: PDF Engine » VCLCanvas and Optional Content (layers) » 2023-07-21 09:06:40

Thank you ab, I'll give a look at the framework then.

#20 Re: PDF Engine » VCLCanvas and Optional Content (layers) » 2023-07-20 17:58:13

Looks great *thumbs up*.

About mormot.ui.pdf.pas, can it be used standalone? Otherwise I will port the modifications to SynPDF.

#21 Re: PDF Engine » VCLCanvas and Optional Content (layers) » 2023-07-20 15:26:10

Since the CreateOptionalContentGroup is a method of the TPdfDocument class I thought it was global to the document and not local to the page.
If every page has its own layers then it is not useful for my project, even though I am pretty sure the PDF specification supports layers that span through multiple pages.

#22 Re: PDF Engine » VCLCanvas and Optional Content (layers) » 2023-07-20 14:50:00

Hello ab, I gave a look, interesting solution.
Am I wrong or it creates a new group at each call? I would much prefer to pass the TPdfOptionalContentGroup object that references the group, maybe saving in the comment the pdf group object id instead of the title.

#23 Re: PDF Engine » VCLCanvas and Optional Content (layers) » 2023-07-19 17:37:16

Thank you for your prompt reply, and for pointing out a possible solution.
I specifically need this for a project, so if I don't find an alternative I will probably try to implement it in SynPDF myself some time in the next months.
If so, I will contribute with a pull request.
Thank you.

#24 PDF Engine » VCLCanvas and Optional Content (layers) » 2023-07-19 13:57:53

padule
Replies: 14

Hello everyone,

I can't seem to find a way to use optional content (layers) when drawing with VCLCanvas.

All content drawn in VCLCanvas is always saved outside any optional content, regardless of the use of BeginMarkedContent/EndMarkedContent.

Am I missing anything? Any pointer on the correct way to use it?

Thanks,
Regards,
Padule

Board footer

Powered by FluxBB