Stringshape rotation

Given a string of font size FS, drawn at x,y

Is there a reliable method for turning that into a stringshape which, when drawn, rotates the string clockwise around the bottom left corner of the string?

I’m struggling to do this because stringshapes rotate around their centre point.
And if I get the position correct for one value of FS, as soon as I use another font size, the Y position is incorrect.
I’ve spent days on it and cannot get it to be reliable

Im happy with the rotation angle for 90 degrees, and eventually wouldnt mind using other angles. But right now its the starting location that is eluding me.

To avoid doing the math yourself, you could try making it part of a Group2D and then rotate the Group2D.

-Karen

I hear you.
But that would rotate ‘everything’ and my needs are
99% normal drawing commands, plus a few rotated text items.

I can rotate the text. I just cannot predict where it will end up on the page.

I do this (g is the target graphics instance):

'Note this code is an excerpt, the actual code is part of a class which determines the rotation and scaling

Dim Ss As New StringShape
Dim TempX1 As Double
Dim TempY1 As Double
Dim WidHere As Double
Dim WidNew As Double

Ss.FillColor = g.DrawingColor
Ss.TextFont = g.TextFont
Ss.TextSize = g.TextSize
Ss.Bold = g.Bold
Ss.Underline = g.Underline
Ss.Italic = g.Italic

Ss.HorizontalAlignment = StringShape.Alignment.Center
Ss.VerticalAlignment = StringShape.Alignment.Center

Ss.Text = Astr 'The string I'm drawing

Ss.Rotation=Rotation * -.0174533 'Rotate 270 degrees to the left 

Select Case Self.TxtAlignment
  
Case kJustLeft
  
  If Rotation=0 Then 'Upright
    
    Ss.x=TempX1-((AvailWid/2)-(WidHere/2))
    Ss.y=TempY1
    
  ElseIf Rotation=90 Then 'Rotated Left
    
    Ss.x=TempX1
    Ss.y=TempY1+((AvailWid-WidHere)/2)
    
  ElseIf Rotation=270 Then 'Rotated Right
    
    Ss.x=TempX1
    Ss.y=TempY1-((AvailWid-WidHere)/2)
    
  End If
  
Case kJustCtr
  
  Ss.x=TempX1
  Ss.y=TempY1
  
Case kJustRight
  
  If Rotation=0 Then 'Upright
    
    Ss.x=TempX1+((AvailWid-WidHere)/2)
    
    If WidNew>0 Then
      Ss.x=Ss.x+((WidHere-WidNew)/2)
    End If
    
    Ss.y=TempY1
    
  ElseIf Rotation=90 Then 'Rotated Left
    
    Ss.x=TempX1
    Ss.y=TempY1-((AvailWid-WidHere)/2)
    
  ElseIf Rotation=270 Then 'Rotated right
    
    Ss.x=TempX1
    Ss.y=TempY1+((AvailWid-WidHere)/2)
    
  End If
  
End Select

g.DrawObject(Ss)

Just noticed that my snippet left out a crucial part:

WidHere=g.StringWidth(Astr)

If WidHere=0 Then
WidHere=Ceil(g.StringWidth(Astr))
End If

Interesting… What are AvailWid and Availhere doing/coming from?

centre justification is the default, isnt it?
If so,
Ss.x=TempX1
Ss.y=TempY1

does rotate the text but places it ‘somewhere’ rather than ‘rotated about the corner’

This is what I am after: (the red dot shows my assumed point of centre for rotating)
image

I’ll experiment with your code (thank you), but at first glance I’m not sure we are there yet…

Not done much with string shape but the following code i’ve just hacked together might help.
NOTE. mAngle_ is an Integer containing the angle in degrees

  Const kPi = 3.14159265358979323846264338327950288
  
  'the draw x & y position
  Const kX = 150
  Const kY = 150
  
  
  'create a dummy shape
  Dim s As New StringShape
  s.Text = "Hello"
  s.TextFont = "System"
  s.TextSize = 50
  
  
  'create a picture so that we can measure the text
  Dim p As New Picture(1, 1, 32)
  p.Graphics.TextFont = s.TextFont
  p.Graphics.TextSize = s.TextSize
  
  
  'calculate half the width as string shape rotates from the centre
  Dim halfWidth As Double
  halfWidth = p.Graphics.StringWidth(s.Text) / 2
  
  
  'offset the string shape so that it draws the same way as Graphics.DrawString
  'not needed but i used this for testing
  s.Y = p.Graphics.TextAscent
  s.X = halfWidth
  
  
  'draw the string shape at 0 degrees
  s.FillColor = RGB(0, 0,  0)
  g.DrawObject(s, kX, kY)
  
  
  'draw the text using DrawString at the same position
  'not needed but i used this for testing
  g.TextFont = s.TextFont
  g.TextSize = s.TextSize
  g.ForeColor = RGB(255, 0,  0)
  g.DrawString(s.Text, kX, kY + p.Graphics.TextAscent)
  
  
  'calculate the rotation offset
  Dim offsetX, offsetY As Double
  Dim theRadians As Double
  Dim theCosine, theSine As Double
  Dim rotatedX, rotatedY As Double
  
  theRadians = (2 * kPi * Self.mAngle_) / 360
  
  theCosine = Cos(theRadians)
  theSine = Sin(theRadians)
  
  offsetX = halfWidth 'move the horizontal rotation point from the centre to the left (* -1 should move it to the right)
  offsetY = 0 'don't move the vertical rotation point (p.Graphics.TextAscent should move it to the top)
  
  rotatedX = (offsetX * theCosine) - (offsetY * theSine)
  rotatedY = (offsetX * theSine) + (offsetY * theCosine)
  
  
  'draw the rotated string shape
  s.Rotation = theRadians
  s.FillColor = RGB(192, 192, 192)

  g.DrawObject(s, kX - offsetX + rotatedX, kY - offsetY + rotatedY)

I’m drawing on Avery labels on a page, so AvailWid is g.width of the whole page, WidHere is the space available within each label.

For what you’re doing, you probably want to use the Rotation=270 code.

This does require some mind-twisting gymnastics. I worked it out by drawing a letter on a 3x5 index card set on top of a piece of paper, writing down the coordinates of the card, then rotated the card the direction I wanted and figured out its new coordinates. Compared the “before” and “after” to see what the difference was, then wrote code to match.

1 Like