Jump to content
Gonda

vs.TextSize Bug/Error

Recommended Posts

Hey All,

 

So, I don't know if anyone has done a lot of drawing of text through python, but I think I've either found a bug or am completely misunderstanding how to vs.TextSize works.

 

I realize that text size changes relative to Layer Scale.  In my script have defined a scale factor to take this into account.  The problem that I seem to be running into, is that when the drawing is set to Millimeters for units, the smallest that I get the vs.TextSize function to draw is 1.  When I set the font size to less than 1, the text doesn't draw at all.  Now if I just drop a text object into the drawing, I can seemingly set the Font Size down to at least 0.01 Point via the OIP pulldown.  I may be wrong, but it appears as if the vs.TextSize function, even though it says it accepts non-integer values, appears as if it is applying a rounding function to the input before passing it to the actual drawing routine within VW.

 

Has anyone encountered this before or am I just overlooking something that is completely obvious?

 

Cheers,

-gonda

Share this post


Link to post

I can't replicate your problem here. 

 

Try a script with only 1 line

 

vs.TextSize(0.1)

 

Run the script and then enter some text. It should come out as 0.1 point.

 

Are you sure that you are passing a number and not text to the TextSize procedure?

 

I also checked SetTextSize and it accepts sizes less than 1 also. But it does need a ResetObject call after changing the font size.

Share this post


Link to post

Hey Pat,

 

So, I've done a little bit more digging and I think I've found the culprit.  It seems there's an issue with the vs.PushAttrs() and vs.PopAttrs() functions.  

 

Ex: (This seems to work just fine)

vs.PushAttrs()

vs.TextSize(0.4)

vs.CreateText("Test")

vs.PopAttrs()

 

Ex:  (This fails)

vs.TextSize(0.4)

vs.PushAttrs()

vs.PopAttrs()

vs.CreateText("test")

 

I'm guessing as part of the Push/Pop functions, there's either an integer cast or rounding happening which is why anything less than 0.5 seems to fail.

 

Cheers,

-gonda

Share this post


Link to post

Yep. According to the definition of PushAttrs   "Stores current attribute, tool, text, and constraint settings for later retrieval"

 

So when you Pop them back, the text size is being reset to value it was before you TextSize call.

 

If you example is really all you are doing, you don't need the Push/Pop at all. If you are only changing a couple of items, it might be easier to use variable to store them and then restore them yourself instead of using Pop.

Share this post


Link to post

Unfortunately, I was actually doing a lot more than in the example I posted...I omitted a lot of things for readability.  Hopefully this will get fixed in the next service pack.  For now I'll have to settle for writing code that is hard to read and maintin ;)

 

Cheers,

-gonda

Share this post


Link to post

It is never going to get fixed because it is doing exactly what it is supposed to do.  The generic text setting (size, font, justification, rotation etc) are saved by the PushAttrs command (as are the pen and fill settings) and restored by the PopAttrs command.

 

If you want to change settings in your script and leave them set that way, then you need to not use the PopAttrs command and save anything that you care about having still be the same after your script to restore manually.

Share this post


Link to post
48 minutes ago, Pat Stanford said:

If you want to change settings in your script and leave them set that way, then you need to not use the PopAttrs command and save anything that you care about having still be the same after your script to restore manually.

 

OR, change the text size outside the scope of the vs.PushAttrs / vs.PopAttrs commands.

 

Raymond

Share this post


Link to post

Unless your script is meant to change document defaults, I find you want to use as many of the handle-based calls as possible.  So instead of using TextSize() before creating text, use SetTextSize() on each newly created text block.  I'll usually write a function, taking a handle as its argument, to properly format each text block.

 

Also, remember that Python does define variables based on their initialization values, so if you're setting the text size by a variable, that could introduce rounding.

 

-Josh

Share this post


Link to post

Pat & MullinRJ:  It is broken.  If I set the text size, push and then pop, the text size should be what I set it at and this is not what is happening.  Unless the PushAttrs() function is also clearing everything it pushes, it is not doing what the documentation indicates nor.

 

JBenghiat:  I'll look into that.  It just seems that that is adding a lot more overhead and function calls since you're calling SetTextSize for every Text Block you create instead of just once.

 

-g

Share this post


Link to post

You are right that there is a bug, but I am pretty sure it is in PopAttrs, not in TextSize.

 

Run the attached script.  If you set the initial text size to 1pt the script will run fine and the GetPrefReal(57)  [which seems to return the text size in cm rather than in points or mm as I would expect] will return the same values before and after the Pop.

 

If you run the script with an initial value of 0.51 to 0.99, the AlrtDialog and the text will return a value that is equivalent to a point size of 1.

 

If you run the script with an initial value of less that 0.5, the AlrtDialog will show the text size as zero and the script will crash.

 

The PopAttrs seems to be pulling the value back as an integer.

 

The problem could be with the PushAttrs, I don't have enough visibility into what is actually saved to be able to say for certain.

 

Again, if you want to use TextSize, don't use the PopAttrs command. Even if it is more work to save all the parameters yourself.

 

@MullinRJ, if you agree with my diagnosis, can you submit the bug on this?  I am completely underwater and shouldn't have taken the time to figure this much out.

 

Pat

Share this post


Link to post

And here is the script that I forgot to attach yesterday :-(

 

Procedure Test;

Var    R1:Real;
    S1:String;

Begin
    TextSize(0.51);
    R1:=GetPrefReal(57);
    CreateText(Concat('Before Push. The actual value is: ',R1) );
    PushAttrs;
    MoveTo(0,-1");
    R1:=GetPrefReal(57);
    CreateText(Concat('After Push. The actual value is: ',R1));
    MoveTo(0,-2");
    TextSize(10);
    R1:=GetPrefReal(57);
    CreateText(Concat('This is 10 point. But the returned value is: ',R1));
    PopAttrs;
    MoveTo(0,-3");
    R1:=GetPrefReal(57);
    AlrtDialog(Concat(R1));
    CreateText(Concat('This should be 0.1 point. But the actual value is: ',R1) );
End;

Run(Test);

Share this post


Link to post

Pat, I agree. PushAtrrs/PopAttrs is broken for saving and restoring the document text size, but I do not know whether the PUSH or the POP is to blame, or possibly both. When the PUSH/POP scope is exited, the saved document text size is rounded to the closest integer POINT value before it is reapplied. I wonder if it is being saved as an INTEGER type instead of a REAL.

 

Here's the script I used to show how the text size changes before, during, and after the Push/Pop commands. It is in Vectorscript, but I suspect the Python calls will fail equally. I will test before I submit it.

PROCEDURE TestPushPopTextSize;
{ Show how text size is Pushed and Popped. }
{ 05 May 2017 - Raymond J Mullin }
VAR
	TxtSz, InitTxtSz :Real;		{ text size variables }
	
	function DocTxtSize :Real;
	{ return the Document Text Size in POINTS }
	Const
		mmpp =  25.4 / 72;	{ mm per Point  = 0.3527777... }
	Begin
		DocTxtSize := GetPrefReal(57) / mmpp;
	End;	{ DocTxtSize }


BEGIN
	{ save initial document text size }
	InitTxtSz := DocTxtSize;
	AlrtDialog(concat('Initial Document Txt Size ', InitTxtSz));
	
	{ let user change the size }
	TxtSz := RealDialog('Your Text Size Please:', concat(InitTxtSz));
	if not DiDCancel then begin
		PushAttrs;
			{ show text size AFTER PushAttrs }
			AlrtDialog(concat('Pushed Text Size before change ', DocTxtSize));

			{ change to User's size inside Push/Pop }
			TextSize(TxtSz);

			{ show text size AFTER PushAttrs }
			AlrtDialog(concat('Text Size after change ', DocTxtSize));

		PopAttrs;
		{ show text size AFTER PopAttrs }
		AlrtDialog(concat('Popped Text Size ', DocTxtSize));
	end;	{ if }

	{ restore initial document text size }
	TextSize(InitTxtSz);
	AlrtDialog(concat('Restored Text Size ', DocTxtSize));
END;
Run(TestPushPopTextSize);

 

This script restores the Document Text Size manually before it exits. The same technique can be applied as a workaround for anyone wanting PushAtrrs/PopAttrs to work as it should before it gets fixed.

 

I will submit this as a bug along with this script. 

 

For anyone who is interested, GetPrefReal(57) returns the text size in mm. To convert this to POINTS, divide the return value by 0.3527777777777. TextSize() takes POINTS as its argument. 

 

Raymond

Share this post


Link to post

A pleasant update:

I just received an email regarding the bug report I submitted 4 days ago – this issue has been fixed and should soon be available at a store near you.

 

Thank you VWI. Your efforts do not go unnoticed. And Pat, thanks for grabbing the bull by the horns. If you had not have had to dismount mid-ride, you'd be spreading the good word here.

 

Raymond

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

 

7150 Riverwood Drive, Columbia, Maryland 21046, USA   |   Contact Us:   410-290-5114

 

© 2018 Vectorworks, Inc. All Rights Reserved. Vectorworks, Inc. is part of the Nemetschek Group.

×