[Demo] Making PDF with table of contents using LLPDFLib

Demos, code samples. Only questions related to the existing topics are allowed here.
Post Reply
Sergey Tkachenko
Site Admin
Posts: 17746
Joined: Sat Aug 27, 2005 10:28 am
Contact:

[Demo] Making PDF with table of contents using LLPDFLib

Post by Sergey Tkachenko »

LLPDFLib is a free opensource Delphi component, https://github.com/sybrexsys/llPDFLib

TRichView already has a demo project showing how to use TRichView+LLPDFLib to create a PDF from RTF or RVF file.

We created an advanced version of this demo that supports a table of contents (TOC) in PDF:
LLPDFWithTOC.zip
(95.69 KiB) Downloaded 4349 times
A TOC is built using headings in documents (RTF, RVF, and we also added DocX).

You can see a checkbox "Build a table of contents":

LLPDFLib-TOC.png
LLPDFLib-TOC.png (55.93 KiB) Viewed 206089 times

If this checkbox is checked, and a file has headings, they are used to build TOC for PDF:

PDF-TOC.png
PDF-TOC.png (116.18 KiB) Viewed 206089 times

Ideas for improvements (not implemented in this demo):
  • allowing to specify the maximum level of headings used to build TOC (this demo uses all 6 levels of headings)
  • adding an option to ignore "Heading 1" (because many files have only a single "Heading 1" entry at the beginning, so it is useless)
edwinyzh
Posts: 104
Joined: Sun Jun 05, 2022 2:22 pm

Re: [Demo] Making PDF with table of contents using LLPDFLib

Post by edwinyzh »

Thanks for the great example.

How to ensure all images (including the large ones) to fit the width of the pdf pages? In practice I found large images exceed the right edge of the generated pdf...

Thanks.
Sergey Tkachenko
Site Admin
Posts: 17746
Joined: Sat Aug 27, 2005 10:28 am
Contact:

How to resize images to fit the page

Post by Sergey Tkachenko »

A solution that adjusts images in table cells would be too complicated, so the solution below is only for images inside the main document.

First, we need to calculate maximal possible image width.
This demo sets page size according to values specified in DocParameters property, so we can calculate this value in this way:

Code: Select all

function TfrmCustomMakePDF.GetMaxImageWidth: TRVStyleLength;
var
  rv: TCustomRichView;
begin
  rv := FDocument.MainDoc.RichView;
  // page width minus page margins
  Result := rv.Style.RVUnitsToUnits(
   rv.DocParameters.PageWidth
   - rv.DocParameters.LeftMargin - rv.DocParameters.RightMargin,
   rv.DocParameters.Units);
  // and minus internal margins
  dec(Result, rv.Style.StandardPixelsToUnits(rv.LeftMargin + rv.RightMargin));
end;
The returned value is measured in FDocument.MainDoc.RichView.Style.Units (like most sizes in TRichView documents)

Now, the code for adjusting images. It is large because it takes into account all possible values that affect maximal width (including border and spacing around images, indents of paragraphs and lists).
The code resizes large images proportionally.

Code: Select all

procedure TfrmCustomMakePDF.AdjustImages;
var
  rv: TCustomRichView;
  MaxWidth, ImgWidth, ImgHeight, ExtraWidth, BorderWidth, ImgPadding, ImgMargin: TRVStyleLength;
  i: Integer;
  ImgName: TRVUnicodeString;
  Gr: TGraphic;
  VAlign: TRVVAlign;
  ImgTag: TRVTag;
  ListItemNo, ListNo, ListLevel, ListStartFrom: Integer;
  ListReset: Boolean;
  ParaStyle: TParaInfo;
begin
  MaxWidth := GetMaxImageWidth;
  rv := FDocument.MainDoc.RichView;
  for i := 0 to rv.ItemCount - 1 do
    if rv.GetItem(i) is TRVGraphicItemInfo then
    begin
      rv.GetPictureInfo(i, ImgName, Gr, VAlign, ImgTag);
      // getting image width (resized or original)
      rv.GetItemExtraIntProperty(i, rvepImageWidth, Integer(ImgWidth));
      if ImgWidth <= 0 then
        ImgWidth := rv.Style.StandardPixelsToUnits(Gr.Width);
      // getting extra item width (border and spacing)
      rv.GetItemExtraIntProperty(i, rvepBorderWidth, Integer(BorderWidth));
      rv.GetItemExtraIntProperty(i, rvepSpacing, Integer(ImgPadding));
      rv.GetItemExtraIntProperty(i, rvepOuterHSpacing, Integer(ImgMargin));
      ExtraWidth := (BorderWidth + ImgPadding + ImgMargin) * 2;

      ParaStyle := rv.Style.ParaStyles[rv.GetItemPara(i)];
      ListItemNo := rv.GetListMarkerInfo(i, ListNo, ListLevel, ListStartFrom, ListReset);
      if (ListItemNo >= 0) and (ListNo >= 0) then
      begin
        // adding indents of list to extra width
        inc(ExtraWidth,
          rv.Style.ListStyles[ListNo].Levels[ListLevel].LeftIndent +
          Max(rv.Style.ListStyles[ListNo].Levels[ListLevel].LeftIndent, 0));
        if rv.RVData.GetParaBiDiMode(rv.GetItemPara(ListItemNo)) = rvbdRightToLeft then
          inc(ExtraWidth, ParaStyle.LeftIndent)
        else
          inc(ExtraWidth, ParaStyle.RightIndent);
      end
      else
      begin
        // adding indents of paragraph to extra width
        inc(ExtraWidth,
          ParaStyle.LeftIndent + ParaStyle.RightIndent + Max(ParaStyle.FirstIndent, 0));
      end;
      // resizing image, if necessary
      if ImgWidth + ExtraWidth > MaxWidth then
      begin
        rv.GetItemExtraIntProperty(i, rvepImageHeight, Integer(ImgHeight));
        if ImgHeight <= 0 then
          ImgHeight := rv.Style.StandardPixelsToUnits(Gr.Height);
        rv.SetItemExtraIntProperty(i, rvepImageWidth, MaxWidth - ExtraWidth);
        rv.SetItemExtraIntProperty(i, rvepImageHeight,
          MulDiv(ImgHeight, MaxWidth - ExtraWidth, ImgWidth));
      end;
    end;
end;
Call this code after opening the file and before formatting the document, i.e. just after the case that calls LoadRVF/LoadRTF/LoadDocX.
edwinyzh
Posts: 104
Joined: Sun Jun 05, 2022 2:22 pm

Re: [Demo] Making PDF with table of contents using LLPDFLib

Post by edwinyzh »

Hi Sergey,

2022-12-18 update: Tested and it works.

Great! Thank you! I'll try it soon
DanielM
Posts: 4
Joined: Thu Mar 27, 2025 5:31 pm

Re: [Demo] Making PDF with table of contents using LLPDFLib

Post by DanielM »

Hi,

I tried the demo LLPDFWithTOC.zip for converting RVF to PDF, for RTF and Docx it works fine, but for RVF it doesn't. The RVF loads with a strange page setting, it has a smaller editable area than the actual one set.(footer, header and margins).

I also tried with the file ...\TRichView\ScaleRichView\Demos\Delphi\ActionTestTabs\readme.rvf with the same result...

Do you have any idea how to solve the problem?
Sergey Tkachenko
Site Admin
Posts: 17746
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Re: [Demo] Making PDF with table of contents using LLPDFLib

Post by Sergey Tkachenko »

Please send me an example of a problematic RVF file.
DanielM
Posts: 4
Joined: Thu Mar 27, 2025 5:31 pm

Re: [Demo] Making PDF with table of contents using LLPDFLib

Post by DanielM »

When Load a RVF File look like this:
Load_RVF_File.png
Load_RVF_File.png (96.63 KiB) Viewed 79540 times
When load a Docx file look like this:
Load_Docx_File.png
Load_Docx_File.png (56.37 KiB) Viewed 79540 times

When I open any RVF file, the border is not set correctly. It can also be seen in the pictures.
Sergey Tkachenko
Site Admin
Posts: 17746
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Re: [Demo] Making PDF with table of contents using LLPDFLib

Post by Sergey Tkachenko »

Was this PDF created in ScaleRichView?
There are two kinds of margins in RVF documents: page margins + document margins.
Page margins are like in RTF and DocX.
Document margins are like <body> margins in HTML (they do not exist in RTF and DocX files).
In the current version, ScaleRichView saves document margins equal to page margins, and this demo (which uses both these kinds of margins for RVF) will show double margins. If you need, I'll explain how to turn off document margins.
DanielM
Posts: 4
Joined: Thu Mar 27, 2025 5:31 pm

Re: [Demo] Making PDF with table of contents using LLPDFLib

Post by DanielM »

Hi,

Yes, pls, if you can put some demo will be nice.

Tnx.
DanielM
Posts: 4
Joined: Thu Mar 27, 2025 5:31 pm

Re: [Demo] Making PDF with table of contents using LLPDFLib

Post by DanielM »

Actually I would like to be able to export from TScaleRichView to PDF, RTF, Docx and definitely RVF. I would also like to be able to convert from RVF, RTF and Docx without having visual components, I saw that you posted a demo that converts RTF to PDF with non-visual components.
Sergey Tkachenko
Site Admin
Posts: 17746
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Re: [Demo] Making PDF with table of contents using LLPDFLib

Post by Sergey Tkachenko »

If you want to export from TSRichViewEdit, you should not use this demo.
This demo uses TRVPrint for pagination, and it may be different from pagination made by ScaleRichView, and does not provide WYSIWYG.

ScaleRichView+LLPDFLib demo is included in ScaleRichView installation.
See the folder <TRichView Dir>\ScaleRichView\Demos\Delphi\ThirdParty\MakePDF\Version4\
Post Reply