Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <blockquote> <p>I assume this is because the text will rotate around the rectangle's TopLeft position</p> </blockquote> <p>No, the rotation is centered around the current origin of the canvas. By default, that is coordinate <code>0, 0</code>, but could be altered by the currently set deformation matrix. The typical way to go is: choose a rotation center, move the origin to that center, rotate, move back to the changed origin, and then draw. See <code>TControl.MatrixChanged</code> for reference. But there are many other ways.</p> <p>Hereby an example of how to paint text from the lower left to the upper right within a form:</p> <p><img src="https://i.stack.imgur.com/rXHKj.png" alt="enter image description here"></p> <pre><code>procedure TForm1.FormPaint(Sender: TObject; Canvas: TCanvas; const ARect: TRectF); var Angle: Single; R: TRectF; S: String; H: Single; Matrix: TMatrix; begin Canvas.Fill.Color := TAlphaColors.Black; Angle := -ArcTan2(ClientHeight, ClientWidth); R := ClientRect; S := 'Text from bottom-left...'; H := Canvas.TextHeight(S); Matrix := CreateRotationMatrix(Angle); Matrix.m31 := Sin(Angle) * (ClientHeight - H); Matrix.m32 := ClientHeight * (1 - Cos(Angle)); Canvas.SetMatrix(Matrix); Canvas.FillText(R, S, False, 1, [], TTextAlign.taLeading, TTextAlign.taTrailing); S := '...to top-right'; Matrix.m31 := ClientWidth * (1 - Cos(Angle)) + Sin(Angle) * H; Matrix.m32 := -Sin(Angle) * ClientWidth; Canvas.SetMatrix(Matrix); Canvas.FillText(R, S, False, 1, [], TTextAlign.taTrailing, TTextAlign.taLeading); end; </code></pre> <h3>Update:</h3> <p>This code does not yet take an already shifted origin into account.</p> <p>In response to your comment, the following code draws text from coordinate <code>50, 100</code> down, 90° rotated around that point, using the method explained above, on a PaintBox which is arbitrarily positioned on the form.</p> <pre><code>procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas); const S = 'Hello World'; var R: TRectF; OriginalMatrix: TMatrix; ShiftMatrix: TMatrix; RotationMatrix: TMatrix; ShiftBackMatrix: TMatrix; Matrix: TMatrix; begin PaintBox1.Canvas.Fill.Color := TAlphaColors.Black; R.Right := 50; R.Bottom := 100; R.Left := R.Right - 5000; R.Top := R.Bottom - 5000; OriginalMatrix := PaintBox1.Canvas.Matrix; ShiftMatrix := IdentityMatrix; ShiftMatrix.m31 := -R.Right; ShiftMatrix.m32 := -R.Bottom; RotationMatrix := CreateRotationMatrix(DegToRad(-90)); ShiftBackMatrix := IdentityMatrix; ShiftBackMatrix.m31 := R.Right; ShiftBackMatrix.m32 := R.Bottom; Matrix := MatrixMultiply(RotationMatrix, ShiftBackMatrix); Matrix := MatrixMultiply(ShiftMatrix, Matrix); Matrix := MatrixMultiply(Matrix, OriginalMatrix); PaintBox1.Canvas.SetMatrix(Matrix); PaintBox1.Canvas.FillText(R, S, False, 1, [], TTextAlign.taTrailing, TTextAlign.taTrailing); PaintBox1.Canvas.SetMatrix(OriginalMatrix); end; </code></pre> <p>Which can be reduced to:</p> <pre><code>procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas); const S = 'Hello World'; var R: TRectF; SaveMatrix: TMatrix; Matrix: TMatrix; begin PaintBox1.Canvas.Fill.Color := TAlphaColors.Black; R := RectF(-Canvas.TextWidth(S), -Canvas.TextHeight(S), 0, 0); SaveMatrix := PaintBox1.Canvas.Matrix; Matrix := CreateRotationMatrix(DegToRad(-90)); Matrix.m31 := 50; Matrix.m32 := 100; PaintBox1.Canvas.MultyMatrix(Matrix); PaintBox1.Canvas.FillText(R, S, False, 1, [], TTextAlign.taTrailing, TTextAlign.taTrailing); PaintBox1.Canvas.SetMatrix(SaveMatrix); end; </code></pre> <p>Which in turn evolves into this general routine:</p> <pre><code>procedure DrawRotatedText(Canvas: TCanvas; const P: TPointF; RadAngle: Single; const S: String; HTextAlign, VTextAlign: TTextAlign); var W: Single; H: Single; R: TRectF; SaveMatrix: TMatrix; Matrix: TMatrix; begin W := Canvas.TextWidth(S); H := Canvas.TextHeight(S); case HTextAlign of TTextAlign.taCenter: R.Left := -W / 2; TTextAlign.taLeading: R.Left := 0; TTextAlign.taTrailing: R.Left := -W; end; R.Width := W; case VTextAlign of TTextAlign.taCenter: R.Top := -H / 2; TTextAlign.taLeading: R.Top := 0; TTextAlign.taTrailing: R.Top := -H; end; R.Height := H; SaveMatrix := Canvas.Matrix; Matrix := CreateRotationMatrix(RadAngle); Matrix.m31 := P.X; Matrix.m32 := P.Y; Canvas.MultyMatrix(Matrix); Canvas.FillText(R, S, False, 1, [], HTextAlign, VTextAlign); Canvas.SetMatrix(SaveMatrix); end; procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas); begin PaintBox1.Canvas.Fill.Color := TAlphaColors.Black; DrawRotatedText(PaintBox1.Canvas, PointF(50, 100), DegToRad(-90), 'Hello world', TTextAlign.taTrailing, TTextAlign.taTrailing); end; </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload