Recent

Author Topic: Canvas Text Justified left AND right.  (Read 18159 times)

cov

  • Full Member
  • ***
  • Posts: 241
Canvas Text Justified left AND right.
« on: June 12, 2013, 12:32:03 am »
Is there any simple way of justifying TCanvas.Text so that it fits within a Rectangle?

I know that TCanvas.TextRect will clip text if it exceeds the width of the Boundary rectangle.

Is there any way of increasing the width of text so that it is justified on the right as well as on the left?

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Canvas Text Justified left AND right.
« Reply #1 on: June 12, 2013, 09:55:23 am »
Here's one way to do it:
Code: [Select]
unit mainJustified;

{$mode objfpc}{$H+}

interface

uses
  Classes, Forms, Graphics, StdCtrls, types;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
var r: TRect;
    s: string = 'this string is long enough to test';
    sz: TSize;
    topLeft: integer = 30;
    ts: TTextStyle;
begin
  sz:= Canvas.TextExtent(s);
  r := Rect(topLeft, topLeft, topLeft+sz.cx, topLeft+sz.cy);
  ts.SingleLine:=True;
  ts.SystemFont:=True;
  Canvas.TextRect(r, 0, 0, s, ts);
  canvas.Frame(r);
end;

end.
                                     

Zoran

  • Hero Member
  • *****
  • Posts: 1829
    • http://wiki.lazarus.freepascal.org/User:Zoran
Re: Canvas Text Justified left AND right.
« Reply #2 on: June 12, 2013, 10:09:55 am »
Here's one way to do it:
Code: [Select]
unit mainJustified;

{$mode objfpc}{$H+}

interface

uses
  Classes, Forms, Graphics, StdCtrls, types;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
var r: TRect;
    s: string = 'this string is long enough to test';
    sz: TSize;
    topLeft: integer = 30;
    ts: TTextStyle;
begin
  sz:= Canvas.TextExtent(s);
  r := Rect(topLeft, topLeft, topLeft+sz.cx, topLeft+sz.cy);
  ts.SingleLine:=True;
  ts.SystemFont:=True;
  Canvas.TextRect(r, 0, 0, s, ts);
  canvas.Frame(r);
end;

end.
                                     

Howardpc, you are resizing the rectangle to make room for text.
I think that what cov wants is to justify the text to both left and right sides of the rectangle at the same time.

TextStyle record has Aligment field, but it seems that it can only be aligned to left, right or center, it lacks the "justified" possibility. :(

User137

  • Hero Member
  • *****
  • Posts: 1791
    • Nxpascal home
Re: Canvas Text Justified left AND right.
« Reply #3 on: June 12, 2013, 11:24:33 am »
1 odd solutions come to mind: Insert spaces between words 1 at the time, until adding 1 more space would make text be wider than rectangle.

This can be very slow solution, so try to make the space inserts "cached" somehow, not during drawing.
« Last Edit: June 12, 2013, 11:26:28 am by User137 »

cov

  • Full Member
  • ***
  • Posts: 241
Re: Canvas Text Justified left AND right.
« Reply #4 on: June 12, 2013, 12:27:22 pm »
I think that what cov wants is to justify the text to both left and right sides of the rectangle at the same time.

TextStyle record has Aligment field, but it seems that it can only be aligned to left, right or center, it lacks the "justified" possibility. :(

Correct, Zoran.

Okay, so there's no native implementation.

What I'm doing in the case of rotated text is writing the text onto a TBitmap and then transferring each bit onto the Image Canvas in it's rotated position.

It shouldn't take much to calculate a stretch factor which I can use when I write the pixel to the Image Canvas.

But that'll probably be for another day....


typo

  • Hero Member
  • *****
  • Posts: 3051
Re: Canvas Text Justified left AND right.
« Reply #6 on: June 13, 2013, 03:45:46 pm »
I have a package (it is attached) called ColumnLabel. On it you can not set Width (which is read only), but Columns, and no Height, but MaxLines. You can set Text property programmatically instead of setting by property editor and it can have LineEndings. It can have a NextLabel, on which the text can be splitted.

This justifies text.

typo

  • Hero Member
  • *****
  • Posts: 3051
Re: Canvas Text Justified left AND right.
« Reply #7 on: June 16, 2013, 03:04:31 pm »
The attached example justifies text on a canvas by wrapping the text and then adding spaces to every line in order to fit some rectangle width.

(Reposted)

exdatis

  • Hero Member
  • *****
  • Posts: 668
    • exdatis
Re: Canvas Text Justified left AND right.
« Reply #8 on: June 16, 2013, 03:06:19 pm »
Thank you very much, typo!
Regards

typo

  • Hero Member
  • *****
  • Posts: 3051
Re: Canvas Text Justified left AND right.
« Reply #9 on: June 23, 2013, 01:43:54 pm »
This file is a demo for a justified and hyphenated static text. (Attached.)

(It compiles without installation.)
« Last Edit: June 23, 2013, 01:45:46 pm by typo »

exdatis

  • Hero Member
  • *****
  • Posts: 668
    • exdatis
Re: Canvas Text Justified left AND right.
« Reply #10 on: June 23, 2013, 01:45:18 pm »
So, thanks again!
Regards

SassyPenguin

  • New Member
  • *
  • Posts: 49
Re: Canvas Text Justified left AND right.
« Reply #11 on: October 03, 2021, 05:16:49 pm »
Although this topic is over 8 years old, I think somebody might seeking for the same answer too...

I just came across this scenario where I need to align numbers in StringGrid during "DrawCell" event, hope this will give a hint on where to start.

Code: Pascal  [Select][+][-]
  1. procedure TForm1.StringGrid1DrawCell(Sender : TObject; aCol, aRow : Integer; aRect : TRect; aState : TGridDrawState);
  2. const
  3.   TopMargin = 2;
  4.   RightMargin = 4;
  5. var
  6.   s: string
  7.   TextHeight, TextWidth: integer;
  8. begin
  9.     s := 'This is a text sample';
  10.  
  11.    {aRect is the drawing RECT area given by StringGrid, or find a way to get the drawing RECT if using other components}
  12.  
  13.     txtWidth := StringGrid1.Canvas.TextWidth(s);
  14.     txtHeight := StringGrid1.Canvas.TextHeight(s);
  15.    
  16.    {Right and Center align the text to the cell}
  17.     StringGrid1.Canvas.TextRect(aRect, (aRect.Right - txtWidth) - RightMargin, (aRect.Bottom - txtHeight) - TopMargin,s);
  18.  
  19. end;
  20.  
« Last Edit: October 03, 2021, 05:22:03 pm by jamestien »
Lazarus 2.2.4 (Win11, Manjaro KDE, CachyOS KDE, Linux Mint)

 

TinyPortal © 2005-2018