# Change Text size based on string length to stay on 1 line

## Recommended Posts

lets say i make a text box that is 3" long but i want whatever text i type to dynamically size itself to always be on 1 line. using vs.SetTextSize() how would i go from deciding the point size based on the text length and the text box size.

Oh my... I've started doing some research into how pts compare to inches and they math hurts my head... Lol I've got a good working formula if all the characters are the same size but that's never gonna happen...

If the point size is uniform through the entire block, the scaling formula is quite easy to achieve a known length. If you have mixed character sizes throughout the block, and potentially mixed font faces, you will have to build a dynamic array of each character and store its size and fontID, calculate the scale factor needed to change the block length to the desired size, then scale each character individually to achieve the overall desired length. Doable, but tedious.

And who said HS algebra class was a waste of time?

Raymond

How about calculating the ratio of the existing size of the bounding box to the desired size and using that ratio to scale the text size.

It seems to work both up and down on my quick test.

This script is intended to be run on a selected text block on the active layer. It will work best on a layer at 1:1 scale.

Sorry, Vectorscript, not Python.

```Procedure Test;
Var X1,Y1,X2,Y2, W1, R1, T1, T2		:Real;
H1							:Handle;

BEGIN
H1:=FSActLayer;
GetBBox(H1,X1,Y1, X2,Y2);
W1:=(X2-X1);

R1:=(3"/W1);
T1:=GetTextSize(H1,1);
T2:=(T1*R1);
SetTextSize(H1, 0, Len(GetText(H1)), T2);
ResetObject(H1);
End;

Run(Test);```

And yes, the above script does assume that the entire block is the same font.

Thats edge case @MullinRJ to you and me. 😉

Good catch Raymond.

Posted (edited)

OK, not as hard as I originally imagined. You just have to scale each character's size by the same amount, and the scale factor is the (existing text length) / (unwrapped text length). Then use a loop to get each characters's size and scale each one to a new size. The secret sauce is knowing how to set the TextWrap and TightFill attributes. The rest is easy peasy.

```PROCEDURE xxx;
{ Scale a wrapped text block to fit in the same box on one line. }
{ 2 Jun 2022 - Raymond Mullin }
VAR
H :Handle;
I :Integer;
TxtBoxW, TxtWid, SF, ChSz :Real;
BEGIN
H := FSActLayer;
TxtBoxW := GetTextWidth(H);			{ target size }
SetTextWrap(H, False);				{ clear Text Wrap }
SetObjectVariableBoo(H, 684, False);		{ clear Tight Fill }
TxtWid := GetTextWidth(H);			{ full length of text }
SF := TxtBoxW / TxtWid;				{ scale factor }

for I := 0 to GetTextLength(H) do begin
ChSz := GetTextSize(H, I);		{ individual character size }
SetTextSize(H, I, 1, ChSz * SF);	{ new character size }
end;		{ for }
SysBeep;
END;
Run(xxx);```

Like Pat, I leave it to you to Pythonize it.

Raymond

Edited by MullinRJ

For some unknown reason, to me at least, when processing a text block with 3 or more point sizes, the above procedure gets very close to achieving the proper text length after scaling, but not the exact length. It's slightly long. I did achieve acceptable perfection by repeating the process of scaling a second time.

If you need more input on how to do this, write back.

Raymond

Here is the Python Version!

i also added a check so it doesn't go larger then the vertical box i want the text to be in. might a little messy but it works for my specific scenario thanks for the help @MullinRJ and @Pat Stanford

```    max_size = 1 ### points (determed by trial and error lol)
text_box_width = 2.8 ### inches
string1 = "Super Long Fixture Name"

vs.CreateText(str(f"{string1}"))
last = vs.LNewObj()

vs.SetTextJust(last, 1)
vs.SetTextWidth(last, text_box_width)
vs.HMove(last, 1.01, -0.2)

textwidth = vs.GetTextWidth(last)
vs.SetTextWrap(last, False)
vs.SetObjectVariableBoolean(last, 684, False)
textwidth_new = vs.GetTextWidth(last)
sf = textwidth / textwidth_new

for i in range(vs.GetTextLength(last)):
ChSz = vs.GetTextSize(last, i)
if ChSz * sf > max_size:
vs.SetTextSize(last, i, 1, max_size)
else:
vs.SetTextSize(last, i, 1, ChSz * sf)```

## Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

×   Pasted as rich text.   Restore formatting

Only 75 emoji are allowed.

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×

• KBASE
• #### MARIONETTE

×
• Create New...