Recent

Author Topic: [SOVLED]Curved text in Lazreport  (Read 412 times)

Petrus Vorster

  • Full Member
  • ***
  • Posts: 248
[SOVLED]Curved text in Lazreport
« on: June 05, 2026, 01:02:24 pm »
Hi All

I made a tool that outputs a lot of individual slips to  a receipt printer using Lazreport.
Each one has a barcode and a qr code.
As red tape would want it in bureaucracy, it still need a valid datestamp before it can be send out, and that takes a lot of unnecessary time.

I can make an image that resembles a rubberstamp, but the wording differs from outlet to outlet and that needs to come from my settings file. The red tape team is fine if i can make it look exactly like the real thing.
As luck would have it, its a round stamp and the wording follows the curve of the stamp. (Outlet name & Town and date in the center)

Before i head off in unreasonable long venture, could anyone tell me if its possible to make text curve to fit a circle and then put that on a lazreport on-the-go or is it simpler to just go and rubberstamp the batch?

If its too crazy, then I will just tell them its impossible to do.

Any thoughts will be welcome.

-Peter
« Last Edit: June 06, 2026, 10:16:48 am by Petrus Vorster »

paweld

  • Hero Member
  • *****
  • Posts: 1676
Re: Curved text in Lazreport
« Reply #1 on: June 05, 2026, 02:06:29 pm »
Try BGRABitmap - sample attached.
Best regards / Pozdrawiam
paweld

VisualLab

  • Hero Member
  • *****
  • Posts: 742
Re: Curved text in Lazreport
« Reply #2 on: June 05, 2026, 07:13:06 pm »
Try BGRABitmap - sample attached.

Do I also need LazReport to open and compile this project?

paweld

  • Hero Member
  • *****
  • Posts: 1676
Re: Curved text in Lazreport
« Reply #3 on: June 05, 2026, 09:37:27 pm »
Quote from: VisualLab
Do I also need LazReport to open and compile this project?
Yes. LazReports, LazBarcode and BGRABitmap

The code responsible for drawing the bitmap:
Code: Pascal  [Select][+][-]
  1. uses
  2.   BGRABitmap, BGRABitmapTypes, BGRAPath;
  3.  
  4. procedure TForm1.GenerateStamp(var ms: TMemoryStream);
  5. var
  6.   bmp: TBGRABitmap;
  7.   path: TBGRAPath;
  8. begin
  9.   ms.Clear;
  10.  
  11.   bmp := TBGRABitmap.Create(200, 200);
  12.   bmp.FontHeight := 24;
  13.   bmp.FontAntialias := True;
  14.   bmp.EllipseAntialias(bmp.Width/2, bmp.Height/2, 90, 90, clRed, 2);
  15.   bmp.EllipseAntialias(bmp.Width/2, bmp.Height/2, 56, 56, clRed, 2);
  16.  
  17.   path := TBGRAPath.Create;
  18.   path.arc(bmp.Width/2, bmp.Height/2, 88, Pi, 0, False);
  19.   bmp.TextOutCurved(path, 'POST OFFICE', clRed, taCenter, 0);
  20.   path.Free;
  21.  
  22.   bmp.TextOut(bmp.Width/2 - 80, bmp.Height/2, '★', clRed);
  23.   bmp.TextOut(bmp.Width/2 + 60, bmp.Height/2, '★', clRed);
  24.  
  25.   path := TBGRAPath.Create;
  26.   path.arc(bmp.Width/2, bmp.Height/2 - 36, 90, Pi, 0, True);
  27.   bmp.TextOutCurved(path, 'POLAND', clRed, taCenter, 0);
  28.   path.Free;
  29.  
  30.   bmp.FontHeight := 16;
  31.   bmp.TextRect(Rect(bmp.Width div 2 - 50, bmp.Height div 2 - 20, bmp.Width div 2 + 50, bmp.Height div 2 + 20),
  32.     FormatDateTime('yyyy-mm-dd', Now), taCenter, tlCenter, clRed);
  33.  
  34.   bmp.SaveToStreamAsPng(ms);
  35.   ms.Position := 0;
  36.  
  37.   bmp.Free;
  38. end;

Edit: or another sample:
Code: Pascal  [Select][+][-]
  1. uses
  2.   BGRABitmap, BGRABitmapTypes, BGRAPath, BGRAGradientScanner
  3.  
  4. procedure TForm1.Button1Click(Sender: TObject);
  5. var
  6.   bmp: TBGRABitmap;
  7.   path: TBGRAPath;
  8.   scan: IBGRAScanner;
  9.   ms: TMemoryStream;
  10. begin
  11.   bmp := TBGRABitmap.Create(Width, Height);
  12.   bmp.FontHeight := 24;
  13.   bmp.FontAntialias := True;
  14.  
  15.   scan := TBGRAGradientScanner.Create(clLime, clBlue, gtLinear, PointF(0, 0), PointF(700, 0));
  16.   path := TBGRAPath.Create;
  17.   path.bezierCurve(PointF(50, 200), PointF(300, 100), PointF(550, 300), PointF(800, 200));
  18.   bmp.TextOutCurved(path, 'Sample text on a curve with various characters Aź うこДб 风暴 😀👋', scan, taCenter, 0);
  19.   path.Free;
  20.  
  21.   ms := TMemoryStream.Create;
  22.   bmp.SaveToStreamAsPng(ms);
  23.   ms.Position := 0;
  24.   Image1.Picture.LoadFromStream(ms);
  25.   ms.Free;
  26.  
  27.   bmp.Free;
  28. end;
« Last Edit: June 06, 2026, 07:59:17 am by paweld »
Best regards / Pozdrawiam
paweld

Petrus Vorster

  • Full Member
  • ***
  • Posts: 248
Re: Curved text in Lazreport
« Reply #4 on: June 06, 2026, 10:16:21 am »
Hi Paweld!

Good to hear from you!
Wow, that is amazing.

I thought it was going to be pages upon pages of work.
I would never have managed this on my own!

Great stuff!

-Peter

Petrus Vorster

  • Full Member
  • ***
  • Posts: 248
Re: [SOVLED]Curved text in Lazreport
« Reply #5 on: June 06, 2026, 10:22:25 am »
This is a darn good example.

Thank you very much!

-Peter

Petrus Vorster

  • Full Member
  • ***
  • Posts: 248
Re: [SOVLED]Curved text in Lazreport
« Reply #6 on: June 06, 2026, 10:33:38 am »
Geez, it even scales according to the size of the BMP on the report.
Now, i have the entire slip rotated in the length of the receipt, so i will need to rotate that BMP by 45 degrees.
I suppose that has to be done in the code before placing it?

Thanks mate, you are indeed brilliant.

-Peter

paweld

  • Hero Member
  • *****
  • Posts: 1676
Re: [SOVLED]Curved text in Lazreport
« Reply #7 on: June 06, 2026, 11:00:52 am »
Hi Petrus,
It's nice to hear from you, too.
You can either draw everything at the correct angle right away, or you'll need to use BGRATransform (simpler):
Code: Pascal  [Select][+][-]
  1. uses
  2.   BGRABitmap, BGRABitmapTypes, BGRAPath,
  3.   BGRATransform;
  4.  
  5. procedure TForm1.Button1Click(Sender: TObject);
  6. var
  7.   bmp, bmptmp: TBGRABitmap;
  8.   path: TBGRAPath;
  9.   ms: TMemoryStream;
  10.   bmptranform: TBGRAAffineBitmapTransform;
  11. begin
  12.   bmp := TBGRABitmap.Create(200, 200);
  13.   bmp.FontHeight := 24;
  14.   bmp.FontAntialias := True;
  15.   bmp.EllipseAntialias(bmp.Width/2, bmp.Height/2, 90, 90, clRed, 2);
  16.   bmp.EllipseAntialias(bmp.Width/2, bmp.Height/2, 56, 56, clRed, 2);
  17.  
  18.   path := TBGRAPath.Create;
  19.   path.arc(bmp.Width/2, bmp.Height/2, 88, Pi, 0, False);
  20.   bmp.TextOutCurved(path, 'POST OFFICE', clRed, taCenter, 0);
  21.   path.Free;
  22.  
  23.   bmp.TextOut(bmp.Width/2 - 80, bmp.Height/2, '★', clRed);
  24.   bmp.TextOut(bmp.Width/2 + 60, bmp.Height/2, '★', clRed);
  25.  
  26.   path := TBGRAPath.Create;
  27.   path.arc(bmp.Width/2, bmp.Height/2 - 36, 90, Pi, 0, True);
  28.   bmp.TextOutCurved(path, 'POLAND', clRed, taCenter, 0);
  29.   path.Free;
  30.  
  31.   bmp.FontHeight := 16;
  32.   bmp.TextRect(Rect(bmp.Width div 2 - 50, bmp.Height div 2 - 20, bmp.Width div 2 + 50, bmp.Height div 2 + 20),
  33.     FormatDateTime('yyyy-mm-dd', Now), taCenter, tlCenter, clRed);
  34.  
  35.   //rotate
  36.   bmptmp := TBGRABitmap.Create(bmp.Width, bmp.Height, BGRAPixelTransparent);
  37.   bmptranform := TBGRAAffineBitmapTransform.Create(bmp);
  38.   bmptranform.Translate(-bmp.Width div 2, -bmp.Height div 2);
  39.   bmptranform.RotateDeg(45); //<-- angle
  40.   bmptranform.Translate(bmp.Width div 2, bmp.Height div 2);
  41.   bmptmp.Fill(bmptranform);
  42.   bmptranform.Free;
  43.   bmp.Assign(bmptmp);
  44.   bmptmp.Free;
  45.  
  46.   ms := TMemoryStream.Create;
  47.   bmp.SaveToStreamAsPng(ms);
  48.   ms.Position := 0;
  49.   Image1.Picture.LoadFromStream(ms);
  50.   ms.Free;
  51.  
  52.   bmp.Free;
  53. end;
Best regards / Pozdrawiam
paweld

 

TinyPortal © 2005-2018