Hello,
I’m failing simple math right now. I want to draw a text with TextShape at a 45 degree angle. But I need the Xojo.Rect surrounding the TextShape. How can I do that?
Hello,
I’m failing simple math right now. I want to draw a text with TextShape at a 45 degree angle. But I need the Xojo.Rect surrounding the TextShape. How can I do that?
Why not use a Rectshape and put both in a group2D to rotate them together?
Else you will need to calculate the coordinates of the rotated rect corners and draw it as a polygon.
-karen
Thanks, Karen. Can you please post sample code? I’m not familiar with the Shape2D classes. It would be an advantage if I knew the dimensions of the rectangle before drawing, because I like to output the rectangle centered on a page.
Martin, I posted a routine that finds the minimum bounding rectangle for rotated text, in answer to one of your earlier queries, a couple of years ago. It was in the thread about drawing fan charts.
I did all of that and more yers ago but don’t have teh code handy. Read the docs on the 2D classes.
Group2D’s can be positioned by their center point, so centering the whole thing is not an issue
-karen
example xojo 2019r3.1
but it is not perfect because textheight return same height for “Hello” “jy”
i made a feature request because TextShape did not have a Width,Height
[code]Sub Paint(g As Graphics, areas() As REALbasic.Rect) Handles Paint
Var r As New RectShape
r.FillColor = Color.White
r.BorderWidth = 2
r.BorderOpacity = 100
r.BorderColor = Color.Black
r.Width = g.Width
r.Height = g.Height
Var l As Double = Sqrt(g.Widthg.Width + g.Heightg.Height)
Var t As New TextShape
t.HorizontalAlignment = TextShape.Alignment.Center
t.VerticalAlignment = TextShape.Alignment.Center
t.FontSize = 10
t.x = 0
t.y = 0
t.Value = “Hello”
t.Rotation = -ATan2(g.Height,g.Width) ’ -45.0 * 22/7/180
While TextShapeWidth(g,t) < (l - TextShapeHeight(g,t))
t.FontSize = t.FontSize + 0.5
Wend
While TextShapeHeight(g,t) > Min(g.Width,g.Height)
t.FontSize = t.FontSize - 0.5
Wend
g.DrawObject r,g.Width / 2.0, g.Height / 2.0
g.DrawObject t,g.Width / 2.0, g.Height / 2.0
End Sub
[/code]
helpers
[code]Public Function TextShapeWidth(g as Graphics, t as TextShape) as Double
g.FontName = t.FontName
g.FontSize = t.FontSize
g.FontUnit = t.FontUnit
Return g.TextWidth(t.Value)
End Function
Public Function TextShapeHeight(g as Graphics, t as TextShape) as Double
g.FontName = t.FontName
g.FontSize = t.FontSize
g.FontUnit = t.FontUnit
Return g.TextHeight
End Function
[/code]
I’ll have to retract that statement. After reviewing that thread, I see that the bounding box issue was secondary to the main discussion, and I never did post the code. So, here it is now:
Public Function StringPic(Txt As String,font as string, fontsize as integer, fclr as color, bold as boolean, italic as boolean,underline as boolean,rot As Integer) as Picture
'Returns a picture of a rotated string in the smallest bounding box
' Note that angle of rotation, rot, is in integer degrees and is
' counterclockwise from positive x-axis.
dim bbW,bbH,x0,y0,r,quadrant As integer
dim w,h,w1,w2,h1,h2,a As Double
Dim pTest as new Picture(1,1)
dim s As new StringShape
dim rt as new RectShape
Const pi=3.14159265358979
Const radianConversion=-pi/180
s.TextFont=font
s.Bold=bold
s.Italic=italic
s.Underline=underline
s.TextSize=fontsize
s.Text=Txt
s.Border=50
s.BorderWidth=2
s.FillColor=fclr
s.BorderColor=&c000000
s.HorizontalAlignment = StringShape.Alignment.Left
s.VerticalAlignment = StringShape.Alignment.Top
'Test picture pTest is used for measuring string width and height
pTest.Graphics.TextFont = s.TextFont
pTest.Graphics.TextSize = s.TextSize
pTest.Graphics.TextUnit = s.TextUnit
pTest.Graphics.Bold=bold
pTest.Graphics.Italic=italic
pTest.Graphics.Underline=underline
'Get the width and Height of the unrotated text
w = pTest.Graphics.StringWidth(s.Text)
h = pTest.Graphics.StringHeight(s.Text,10000)
s.Rotation=rot*radianConversion
'Set mask parameters
rt.Width=w
rt.Height=h
rt.Rotation=rot*radianConversion
rt.FillColor=&cffffff
'Rotation angle may be in range -360 to +360
'So, normalize it to the range 0..359 degrees
r=rot
while r<0
r=r+360
wend
r=r mod 360
'Get quadrant 1..4 of angle
quadrant=1+r\\90
'Get the angle within the quadrant
r=r mod 90
'Convert rotation angle to radians and calculate
'principal parameters of rotated text
a=-r*radianConversion
h1=h*cos(a)+0.5
h2=w*sin(a)+0.5
w1=h*sin(a)+0.5
w2=w*cos(a)+0.5
'Calculate bounding box width and height bbW & bbH
' and text origin x0, y0 from principal dimensions
select case quadrant
case 1
bbW=w1+w2
bbH=h1+h2
x0=w1
y0=bbH
case 2
bbW=h1+h2
bbH=w1+w2
y0=w2
x0=bbW
case 3
bbW=w1+w2
bbH=h1+h2
x0=w2
y0=0
case 4
bbW=h1+h2
bbH=w1+w2
x0=0
y0=w1
end select
'Create an exactly sized bounding box for the text
dim sPic As new Picture(bbW,bbH)
'and draw the text in it
sPic.Graphics.DrawObject(s,x0,y0)
'Note that the exact centre of the text will always be at the exact
' centre of the bounding box. This makes it easy to position.
Return sPic
End Function
Note that the variables bbW and bbH are the width and height of the bounding box.
Hi everyone,
thanks for your messages. I have now written myself a method that will serve my purpose. I don’t even need a surrounding rectangle anymore, which I only wanted to use for positioning the rotated text within a graphics object. This was a wrong/unnecessary approach. The following code prints any text centered.
[code]Sub DrawRotatedText(g As Graphics, txt As String, degree As Double)
Const pi = 3.14159265358979
Const radianConversion = -pi / 180
Var shape As New TextShape
shape.Bold = g.Bold
shape.FillColor = g.DrawingColor
shape.FontName = g.FontName
shape.FontSize = g.FontSize
shape.FontUnit = g.FontUnit
shape.Italic = g.Italic
shape.Underline = g.Underline
shape.Value = txt
shape.VerticalAlignment = TextShape.Alignment.Center
Var group As New Group2D
group.AddObject(shape)
group.X = g.Width / 2
group.Y = g.Height / 2
group.Rotation = degree * radianConversion
g.DrawObject(group)
End Sub[/code]
Canvas Paint-Event:
Sub Paint(g As Graphics, areas() As REALbasic.Rect)
g.FontSize = 72
g.FontName = "Arial"
DrawRotatedText(g, "Hello World", 45)
End Sub