Recent

Author Topic: Laz mupdf (SumatraPDF loader): Now rendering for 32Bit and 64Bit compile  (Read 1262 times)

Boleeman

  • Hero Member
  • *****
  • Posts: 879
Rendering OK but only for 32bit Lazarus compile and the old v2.2 32bit libmupdf.dll.
See later replies.

Hi All

I found some Lazarus source code to view a pdf file with freepascal bindings from mupdf located at:

https://github.com/blestan/lazmupdf

(Blestan Tabakov is a member of the Lazarus forum but has not been active since 2018. The MuPDF lib header port to FPC source code was written in 2013 )

That source contains a compiled libmupdf.dll (from SumatraPDF: http://code.google.com/p/sumatrapdf/ ) to do the pdf viewing.

It uses a ruler component from:

https://github.com/blestan/PureCode


I installed the ruler component but when compiling the source from the  test folder I have:

uses
   BGRAView

and    PaintBox1: TBGRAView;

which does not make sense as it should be PaintBox1: TPaintBox;

The source code is quite old, so what should that TBGRAView component be ? (Possibly something TBgrabmp related)

Code: Pascal  [Select][+][-]
  1. unit main_test;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, FileUtil, BGRAView, Forms, Controls, Graphics, Dialogs,
  9.   ExtCtrls, StdCtrls, Buttons, ComCtrls, Ruler, types, BGRABitmap, BCTypes,libmupdf;
  10.  
  11. type
  12.  
  13.   { TPreviewForm }
  14.  
  15.   TPreviewForm = class(TForm)
  16.     HRuler: TRuler;
  17.     ImageList1: TImageList;
  18.     OpenDialog1: TOpenDialog;
  19.     PaintBox1: TBGRAView;
  20.     Panel1: TPanel;
  21.     Panel2: TPanel;
  22.     SpeedButton1: TSpeedButton;
  23.     ToolBar1: TToolBar;
  24.     ToolButton1: TToolButton;
  25.     ToolButton2: TToolButton;
  26.     ToolButton3: TToolButton;
  27.     ToolButton4: TToolButton;
  28.     ToolButton5: TToolButton;
  29.     HScrollBar: TScrollBar;
  30.     VRuler: TRuler;
  31.     VScrollBar: TScrollBar;
  32.     procedure FormCreate(Sender: TObject);
  33.     procedure FormDestroy(Sender: TObject);
  34.     procedure FormShow(Sender: TObject);
  35.     procedure PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,Y: Integer);
  36.     procedure PaintBox1MouseWheel(Sender: TObject; Shift: TShiftState;WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
  37.     procedure PaintBox1Redraw(Sender: TObject; Bitmap: TBGRABitmap);
  38.     procedure HScrollBarScroll(Sender: TObject; ScrollCode: TScrollCode; var ScrollPos: Integer);
  39.     procedure ToolButton1Click(Sender: TObject);
  40.     procedure ToolButton4Click(Sender: TObject);
  41.     procedure ToolButton5Click(Sender: TObject);
  42.     procedure VScrollBarScroll(Sender: TObject; ScrollCode: TScrollCode; var ScrollPos: Integer);
  43.   private
  44.     FPNum: Integer;
  45.     FPCount: Integer;
  46.  
  47.     FDoc: fz_document;
  48.     FCTX: fz_context;
  49.     FPage: fz_Page;
  50.  
  51.     procedure GotoPage(N: Integer);
  52.   public
  53.     { public declarations }
  54.   end;
  55.  
  56. var
  57.   PreviewForm: TPreviewForm;
  58.  
  59. implementation
  60.  
  61. {$R *.lfm}
  62.  
  63.  
  64. { TPreviewForm }
  65.  
  66. procedure TPreviewForm.PaintBox1Redraw(Sender: TObject; Bitmap: TBGRABitmap);
  67. var
  68.       w,h: integer;
  69.       b: fz_bbox;
  70.       ctm: fz_matrix;
  71.  
  72.       pix:fz_pixmap;
  73.       dev: fz_device;
  74.  
  75.       oldc: TCursor;
  76.   begin
  77.    if (FPNum<0) or (FPNum>=FPCount) then exit;
  78.    try
  79.      oldc:=Screen.Cursor;
  80.      Screen.Cursor:=crHourGlass;
  81.  
  82.  
  83.      with ctm do
  84.       begin
  85.         a:=96/72;b:=0;c:=0;d:=96/72;e:=0;f:=0;
  86.       end;
  87.  
  88.      with b do
  89.       begin
  90.         x0:=0; y0:=0; x1:=PaintBox1.PageWidth; y1:=PaintBox1.PageHeight;
  91.       end;
  92.  
  93.  
  94.      pix:=fz_new_pixmap_with_bbox_and_data(FCTX,fz_find_device_colorspace(FCTX,'DeviceBGR'),b,PaintBox1.Bitmap.Data);
  95.  
  96.      dev:=fz_new_draw_device(FCTX,pix);
  97.  
  98.      fz_run_page(FDoc,FPage,dev,ctm,nil);
  99.  
  100.  
  101.      PaintBox1.Bitmap.VerticalFlip;
  102.  
  103.    finally
  104.      fz_free_device(dev);
  105.      fz_drop_pixmap(FCTX,pix);
  106.      Screen.Cursor:=oldC;
  107.    end;
  108. end;
  109.  
  110. procedure TPreviewForm.HScrollBarScroll(Sender: TObject;
  111.   ScrollCode: TScrollCode; var ScrollPos: Integer);
  112. begin
  113.  HRuler.ZeroOffset:=-ScrollPos-HRuler.Left;
  114.  PaintBox1.SetOrigin(-ScrollPos,PaintBox1.OriginY);
  115. end;
  116.  
  117. procedure TPreviewForm.GotoPage(N: Integer);
  118. var  r: fz_rectangle;
  119.      m: fz_matrix;
  120.      w,h,xo,yo: Integer;
  121. begin
  122.  if (N<0) or (N>=FPCount) then exit;
  123.  if FPage<>nil then fz_free_page(FDoc,FPage);
  124.  FPage:=fz_load_page(FDOC,N);
  125.  r:=fz_bound_page(FDoc,FPage);
  126.  
  127.  with m do
  128.       begin
  129.         a:=96/72;b:=0;c:=0;d:=96/72;e:=0;f:=0;
  130.       end;
  131.  
  132. // fz_transform_rect(r,m);
  133.  w:=round((r.x1-r.x0)*96/72);
  134.  h:=round((r.y1-r.y0)*96/72);
  135.  
  136.  PaintBox1.SetPageSize(w,h);
  137.  PaintBox1.RedrawBitmapContent;
  138.  
  139.  xo:=(PaintBox1.Width-PaintBox1.Bitmap.Width) div 2;
  140.  yo:=(PaintBox1.Height-PaintBox1.Bitmap.Height) div 2;
  141.  
  142.  PaintBox1.Caption:=IntToSTr(N);
  143.  PaintBox1.SetOrigin(xo,yo);
  144.  
  145.  HRuler.ZeroOffset:=xo;
  146.  
  147.  with HScrollBar do
  148.    begin
  149.      PageSize:=w;
  150.      Min:=-w;
  151.      Max:=2*w;
  152.      SmallChange:=1;
  153.      LargeChange:=w div 2;
  154.      Position:=0;
  155.    end;
  156.  
  157.   with VScrollBar do
  158.    begin
  159.      Min:=VRuler.Scale(-h);
  160.      Max:=VRuler.Scale(h*2);
  161.      PageSize:=VRuler.Scale(h);
  162.      SmallChange:=VRuler.Scale(1);
  163.      LargeChange:=VRuler.Scale(10);
  164.      VRuler.ZeroOffset:=yo;
  165.      Position:=yo;
  166.    end;
  167.  FPNum:=N;
  168. end;
  169.  
  170. procedure TPreviewForm.ToolButton1Click(Sender: TObject);
  171. begin
  172.   if not OpenDialog1.Execute  then exit;
  173.  
  174.   if FCTX=nil then FCTX:=fz_new_context(nil,nil,0);
  175.   if FDoc<>nil then fz_close_document(FDOC);
  176.   FDoc:=fz_open_document(FCTX,PChar(OpenDialog1.FileName));
  177.   FPNum:=0;
  178.   FPCount:=fz_count_pages(FDoc);
  179.   GotoPage(0);
  180. end;
  181.  
  182. procedure TPreviewForm.ToolButton4Click(Sender: TObject);
  183. begin
  184.   GotoPage(FPNum-1);
  185. end;
  186.  
  187. procedure TPreviewForm.ToolButton5Click(Sender: TObject);
  188. begin
  189.   GotoPage(FPNum+1);
  190. end;
  191.  
  192. procedure TPreviewForm.VScrollBarScroll(Sender: TObject;
  193.   ScrollCode: TScrollCode; var ScrollPos: Integer);
  194. begin
  195.  VRuler.ZeroOffset:=-ScrollPos;
  196.  PaintBox1.SetOrigin(PaintBox1.OriginX,-ScrollPos);
  197. end;
  198.  
  199.  
  200. procedure TPreviewForm.FormCreate(Sender: TObject);
  201. begin
  202.  FCTX:=nil;
  203.  FDoc:=nil;
  204.  FPage:=nil;
  205.  VRuler.ZeroOffset:=0;
  206.  HRuler.ZeroOffset:=0;
  207. end;
  208.  
  209. procedure TPreviewForm.FormDestroy(Sender: TObject);
  210. begin
  211.   if FPage<>nil then fz_free_page(FDoc,FPage);
  212.   if FDoc<>nil then fz_close_document(FDoc);
  213.   if FCTX<>nil then fz_free_context(FCTX);
  214. end;
  215.  
  216. procedure TPreviewForm.FormShow(Sender: TObject);
  217. begin
  218. end;
  219.  
  220. procedure TPreviewForm.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState;
  221.   X, Y: Integer);
  222. begin
  223.   Panel1.Caption:=Format('%d:%d',[x-PaintBox1.OriginX,y-PaintBox1.OriginY]);
  224.   Panel1.Repaint;
  225. end;
  226.  
  227. procedure TPreviewForm.PaintBox1MouseWheel(Sender: TObject; Shift: TShiftState;
  228.   WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
  229. begin
  230.   with VScrollBar do
  231.    begin
  232.      Position:=Position - WheelDelta;
  233.      VRuler.ZeroOffset:=-Position;
  234.      PaintBox1.SetOrigin(PaintBox1.OriginX,-Position);
  235.    end;
  236. end;
  237.  
  238. end.
  239.  


« Last Edit: April 08, 2025, 12:37:08 am by Boleeman »

Boleeman

  • Hero Member
  • *****
  • Posts: 879
Re: Compiling lazmupdf: Lazarus compile problems TBGRAView component ?
« Reply #1 on: March 22, 2025, 12:51:49 pm »
After much stuffing about, I roughly recreated the GUI (anchors are not set up)

Sort of have it rendering the pdf but it is rotated/reflected.

Missing the images from the Imagelist (which I assume are load, previous, next)

Also the toolbar is covering the top ruler.

Get the dll from the github page: https://github.com/blestan/lazmupdf

« Last Edit: March 22, 2025, 12:53:59 pm by Boleeman »

Boleeman

  • Hero Member
  • *****
  • Posts: 879
Re: Compiling lazmupdf: Lazarus compile problems TBGRAView component ?
« Reply #2 on: March 22, 2025, 01:28:54 pm »
Now loading and rendering the pdf OK.

Added the missing images to the Imagelist.

Also fixed the orientation of the rendered pdf.

Still need to anchor and adjust things a bit.


The bottom part of the rendered pdf is still covering the scrollbar and the top ruler is covered by the toolbar.

Yay, the main parts are working.

« Last Edit: March 22, 2025, 03:10:35 pm by Boleeman »

domasz

  • Hero Member
  • *****
  • Posts: 573
Re: Laz mupdf (SumatraPDF loader): Now rendering YAY !
« Reply #3 on: March 27, 2025, 03:38:54 pm »
Very interesting. Are you still working on it?

Boleeman

  • Hero Member
  • *****
  • Posts: 879
Re: Laz mupdf (SumatraPDF loader): Now rendering YAY !
« Reply #4 on: April 04, 2025, 09:38:38 am »
Apologies domasz.
I took a break on working on it and just did some initial investigative stuff.

I turns out that, in my attempt,  this Sumatra pdf reading library works for 32bits, using the old v2.2 libmupdf.dll from the Github site.

The latest 64bit libmupdf.dll does not work with a Lazarus 64bit compile.

Not sure if Tomxe could possibly help out, as he is really good at connecting dll's with Lazarus codes ?



« Last Edit: April 04, 2025, 09:42:37 am by Boleeman »

TRon

  • Hero Member
  • *****
  • Posts: 4292
Re: Laz mupdf (SumatraPDF loader): Now rendering YAY !
« Reply #5 on: April 04, 2025, 10:57:26 am »
The latest 64bit libmupdf.dll does not work with a Lazarus 64bit compile.
What version would that be exactly ? No windows, so no idea what you got from where :)

If I want to have a look then I would have to go the (original) source: https://github.com/ArtifexSoftware/mupdf (but there are only tags and the right tag would be required to match the one used for creating the DLL version).
Today is tomorrow's yesterday.

paweld

  • Hero Member
  • *****
  • Posts: 1354
Best regards / Pozdrawiam
paweld

Boleeman

  • Hero Member
  • *****
  • Posts: 879
Re: Laz mupdf (SumatraPDF loader): Now rendering on for 32Bit compile
« Reply #7 on: April 07, 2025, 01:58:05 am »
TRon I was referring to the C++ compiled dlls from https://github.com/sumatrapdfreader/sumatrapdf



Thanks Paweld for that web page link on compiling the dll.

I attach the working muPDF 1.17 64Bit Lazarus source below.


I also came across some interesting pdf libraries:

https://github.com/sybrexsys/llPDFLib

and

https://github.com/sybrexsys/VersyPDF                (this has Delphi bindings)

Might be nice to have VersyPDF working with Lazarus?


Here are some features of VersyPDF:

VersyPDF features
    Can read, write, and edit PDF documents
    Reading/writing a PDF document from/to memory buffer or a file on a disk.
    Creating new text, vector art and images.
    Quick image embedding for TIFF, JPEG, PNG, and BMP.
    Supporting Type1 and TrueType font embedding for accurate text reproduction.
    Supporting Unicode text and standard PDF encodings.
    Dynamic font subsetting that results in reducing file size.
    Full control over text positioning and character spacing.
    Supporting all PDF color spaces and advanced pre-press options.
    Full control over content positioning and all graphical attributes available in PDF.
    Reuse of resources such as images, fonts and color spaces through object sharing resulting in obtaining smaller and more efficient documents.
    Supporting explicit and named destinations. Named destinations allow for changes in the document not invalidating existing bookmarks.
    Extensive bookmark creation and API editing.
    Working with threads.
    Applying security to new documents.
    Linearization (Fast Web View).
    Compression of the output PDF documents.
    Inserting or appending new content in existing pages.
    Rotating pages.
    JBIG2, CCITT Fax, Flate/PNG, JPEG/DCT compression.
    Supporting for Standard PDF security handler (40, 128 bit RC4 and 128 and 256 AES encryption).
    Unused object removal. This option helps you to create smaller files.
    Filling in PDF Forms.
    Reading PDF form fields values.
    Creating new form fields.
    Splitting pages.
    Merging and appending pages.
    Supporting Digital Signature.
    Supporting many actions.
    Supporting many annotations.
    Parsing EMF images.


These features sound really interesting.
« Last Edit: April 07, 2025, 03:49:29 am by Boleeman »

Tomxe

  • New Member
  • *
  • Posts: 42
Re: Laz mupdf (SumatraPDF loader): Now rendering on for 32Bit compile
« Reply #8 on: April 07, 2025, 08:08:35 am »
https://github.com/sybrexsys/VersyPDF           

It's licensed under GNU Affero General Public License which means you need to publish source code of the whole application when you use VersyPDF. You can buy a commercial license to use VersyPDF in a commercial product but I doubt it's affordable.
MuPDF is a better library.

Boleeman

  • Hero Member
  • *****
  • Posts: 879
Re: Laz mupdf (SumatraPDF loader): Now rendering on for 32Bit compile
« Reply #9 on: April 07, 2025, 08:20:00 am »
Ok. I just wanted to make a not for profit pdf editor with VersyPDF.

Anyhow, will stick with the free MuPDF.

Thanks Tomxe.

Tomxe

  • New Member
  • *
  • Posts: 42
Re: Laz mupdf (SumatraPDF loader): Now rendering on for 32Bit compile
« Reply #10 on: April 07, 2025, 10:29:36 am »
Such double licenses in reality are selected because the authors think:
- we want to make money selling commercial licensens
- we want to gain popularity so we make this open source
- thanks to open source people will help us find and fix bugs for free
- if we don't make enough money we might one day stop offering this as open source and just stick to commercial licenses

 

TinyPortal © 2005-2018