Jump to content

TextMeasure with Kearning


RickG

Recommended Posts

Hi All,

 

Needing to measure resulting length of text of various font sizes to determine the longest line of text and the amount of kerning needs to be taken into account.

 

Given the following...

var tm10 = new FusionProTextMeasure;
tm10.pointSize = "10 pt";
tm10.kerning = "50";
tm10.CalculateTextExtent(dept);
wDept = tm10.textWidth;

...I would assume that changing the amount of kerning would change the textWidth result, but it does not.

 

I've tried it without the quotes and with % but nothing changes. I don't see a tracking attribute to use against TextMeasure.

 

Am I totally misunderstanding the purpose of TextMeasure?

Link to comment
Share on other sites

Kerning and tracking are not the same thing.

 

The kerning property of the FusionProTextMeasure object is a Boolean (true/false) setting, matching the check box on the Paragraph Formatting dialog, which determines whether kerning pairs in the font are honored when setting text, so that, for example, a capital "W" and "A" are set slightly closer together in certain fonts.

 

Tracking is a percentage by which ALL text is set more closely together (or farther apart), regardless of kerning. This setting is not available as a property of the FusionProTextMeasure object (nor in the Text Editor dialog); you need to invoke it with a <tracking> tag, like so:

var tm10 = new FusionProTextMeasure;
tm10.pointSize = "10 pt";
//tm10.kerning = true; // this is the default
tm10.CalculateTextExtent("<tracking newsize=150>" + dept);
wDept = tm10.textWidth;

Link to comment
Share on other sites

Thank you for the additional information Dan...

 

I did (finally) come across the information on the t/f value for the kerning after posting the thread and did move into the direction of using the tracking information within the CalculateTextExtent method. My approach was a little different, but I have since modified it to match your example.

 

The calculations appear to be working properly when I dump the information to the screen, but it doesn't appear to be applying properly in all cases...or rather the rendering of the text in the cell does not apply the same as the calculation expects it to.

 

Basically, here's what I'm trying to accomplish. I have a logo that needs address information to the right of it (this is my text frame which is the exact height of the logo). The left-most character of the longest line must be at a specific x-coordinate which is the x-coordinate of the text frame. The text (table) must be vertically aligned in the text frame and horizontally aligned in regards to the other text within the frame (table). The first line is 10pt and the remainder are 6pt.

 

So, I've made my text frame really wide, then I'm adding the table to the frame. Here is the core of the code...

 

var table = new FPTable;
//- Calculate text lengths
var tm          =   new FusionProTextMeasure;
tm.pointSize    =   "10 pt";
tm.CalculateTextExtent("<tracking newsize=50>" + dept);
wDept           =   tm.textWidth;

tm.pointSize    =   "6 pt";
tm.CalculateTextExtent("<tracking newsize=50>" + addr1);
wAddr1 = tm.textWidth;
tm.CalculateTextExtent("<tracking newsize=50>" + addr2);
wAddr2 = tm.textWidth;
tm.CalculateTextExtent("<tracking newsize=50>" + addr3);
wAddr3 = tm.textWidth;

//- Determine the longest field length and apply the value to the column
//-   Note: Math.max within FP only accepts 2 values whereas the true JS function allows for more
max01 = Math.max(wDept,wAddr1);
max02 = Math.max(wAddr2,wAddr3);
maxFieldLength = Math.max(max01,max02);
table.AddColumns(maxFieldLength);

var CellMargins = new FPTableMargins;
CellMargins.Top = 0;
CellMargins.Bottom = 0;
CellMargins.Left = 0;
CellMargins.Right = 0;

...and here is how I'm adding the text to the cells, ignore the fact that I'm omitting the lines where I tell it how many rows to add...

 

table.Rows[0].Cells[0].Content = "<span pointSize=10><tracking newsize=50>" + dept + "</tracking></span>";

This seems to be working okay but when using test data with even a small variety of dept names, there are instances where the dept is being wrapped into two lines and I'm not clear as to why.

 

Any thoughts/tips/tricks on this?

 

Thank you in advance...

 

Side Question, but related: I'm unable to find anything in the User/Tag/Rules manuals regarding using FPTable...can you point me in the direction of that information?

Link to comment
Share on other sites

This seems to be working okay but when using test data with even a small variety of dept names, there are instances where the dept is being wrapped into two lines and I'm not clear as to why.

I appreciate the explanation of what you're trying to accomplish, and the code you posted, but it's almost impossible to troubleshoot without having the whole job and being able to actually run the rule and see the output. Could you collect it up?

 

It's probably that you're not specifying enough information to the FusionProTextMeasure object. You need to tell it everything about the text that's being typeset so that it can calculate accurately. The most obvious thing that's missing is the font name. The rule is calculating the size of the text based on the default font (Arial), but you're probably setting it in a different font. So at the very least I think you need to add this:

tm.font = "Your font name here";

You may need to set other properties as well; check the list in the Objects tab of the Building Blocks dialog.

 

Also, I assume that you're actually setting the text down with the same <tracking newsize=50> tags in the output, right?

 

Actually, what I would do here is create a Formatted Text Resource for each block of text that you're trying to measure, and a set of rules, each of which returns the content of one of the resources, with any other tagging (such as the <tracking newsize=50> tag), and then measure the results of those rules. Then when you set down the text to be output in the table, use the same rules, and you're guaranteed to be measuring exactly what you're setting in the output, even if you don't set the all properties of the FusionProTextMeasure object, because all the formatting is specified in the tags that the Formatted Text Resource generates.

 

The rules for each block of text should look something like this:

return '<tracking newsize=50>' + Resource("Addr1Resource").content;

And then your main rule can do measurements this:

tm.CalculateTextExtent(Rule("Addr1Rule"));

Side Question, but related: I'm unable to find anything in the User/Tag/Rules manuals regarding using FPTable...can you point me in the direction of that information?

Unfortunately there is currently no documentation on the FPTable object. However, there's a fairly comprehensive example in the Frodo Travel Tutorial which demonstrates most of the functionality.

 

Finally, I have to quibble with this:

//-   Note: Math.max within FP only accepts 2 values whereas the true JS function allows for more

That's not true. The Math.max function in FusionPro is the "true" JavaScript function. The expression "Math.max(1, 2, 3, 4)" returns 4 for me.

Link to comment
Share on other sites

Looks like we were posting at the same time when I sent up the example.

 

Thank you for the additional tips on the font...I'll try that out as well as checking out the Frodo Tutorial for additional guidance.

 

In regards to the quibble, that was a note to other developers in the team and not meant as a dig. When I first tried it with 4 values it did not appear to be working correctly which may have be a result of something I coded wrong while trying to figure this out. When it didn't work as expected I consulted the documentation in the Building Blocks --> Functions --> Math --> max which states "Math.max(number1, number2) Returns the greater of the two numbers". As it specifically states "two numbers", I assumed it was a limitation of the implementation of the function and made note of it in the code. My bad.

 

Thank you for all of your assistance with this.

Link to comment
Share on other sites

In regards to the quibble, that was a note to other developers in the team and not meant as a dig. When I first tried it with 4 values it did not appear to be working correctly which may have be a result of something I coded wrong while trying to figure this out. When it didn't work as expected I consulted the documentation in the Building Blocks --> Functions --> Math --> max which states "Math.max(number1, number2) Returns the greater of the two numbers". As it specifically states "two numbers", I assumed it was a limitation of the implementation of the function and made note of it in the code. My bad.

No problem. You're correct that the documentation in the Building Blocks is not completely accurate, so that's really our bad. We were trying to keep things a little simpler, since some users might be confused by the variable number of arguments. But it's really the same function you'll find in any other JavaScript engine, and it does work.

Link to comment
Share on other sites

Thanks for all of your help on this...

 

I put in a number of your suggestions and everything seems pretty happy now, not perfect, but very close. One of the key changes that seemed to have the most effect was how I was controlling/implementing the point size.

 

Originally I was doing something to this effect...

 

"<span pointSize=10><tracking newsize=50>" + dept + "</tracking></span>";

...in looking closer at the validation output, there appeared to be extra tagging in there so I changed it to this after RTFM...

 

"<p><z newsize=10><tracking newsize=50>" + dept;

...and that cleared up a few different issues. All in all, the project is in much better shape now and will open a new thread for any nit-picking issues so this one doesn't become a nightmare.

 

For the sake of the user community, here is the cleaned up code...could probably use a little more tuning, but its in good shape overall...

 

//- In order to correctly calculate the width of the fields with tracking and pointSize,
//-   applied correctlym we need to define the display attributes first
dispDept    =   "<p><z newsize=10><tracking newsize=50>" + dept;
dispAddr1   =   "<tracking newsize=50>" + addr1;
dispAddr2   =   "<tracking newsize=50>" + addr2;
dispAddr3   =   "<tracking newsize=50>" + addr3;

//- Calculate text lengths
var tm          =   new FusionProTextMeasure;
tm.font         =   "Weiss-ExtraBold";
tm.pointSize    =   "10 pt";
tm.CalculateTextExtent(dispDept);
wDept           =   tm.textWidth;

tm.pointSize    =   "6 pt";
tm.CalculateTextExtent(dispAddr1);
wAddr1 = tm.textWidth;
tm.CalculateTextExtent(dispAddr2);
wAddr2 = tm.textWidth;
tm.CalculateTextExtent(dispAddr3);
wAddr3 = tm.textWidth;

//- Determine the longest field length and apply the value to the column
maxFieldLength = Math.max(wDept,wAddr1,wAddr2,wAddr3);

//- Init the table and add the column
var table = new FPTable;
table.AddColumns(maxFieldLength);

//- Determine the number of rows needed
rowCount = 4
if (Len(Trim(addr2)) > 0)
{
   rowCount = 5;
}
table.AddRows(rowCount);

//- Set the table margins
var CellMargins = new FPTableMargins;
CellMargins.Top = 0;
CellMargins.Bottom = 0;
CellMargins.Left = 0;
CellMargins.Right = 0;

//- NOTE: Un-comment SetBorders lines for troubleshooting
//- Department
//table.Rows[0].Cells[0].SetBorders("Thin","Black","Top","Bottom","Left","Right");
table.Rows[0].Cells[0].Margins = CellMargins;
table.Rows[0].Cells[0].VAlign = "middle";
table.Rows[0].Cells[0].Content = dispDept;

//- Blank Line
//table.Rows[1].Cells[0].SetBorders("Thin","Black","Top","Bottom","Left","Right");
table.Rows[1].Cells[0].Margins = CellMargins;
table.Rows[1].Cells[0].VAlign = "middle";
table.Rows[1].Cells[0].Content = "<z newsize=6><tracking newsize=50> </tracking>";

//- Address 1 
//table.Rows[2].Cells[0].SetBorders("Thin","Black","Top","Bottom","Left","Right");
table.Rows[2].Cells[0].Margins = CellMargins;
table.Rows[2].Cells[0].VAlign = "middle";
table.Rows[2].Cells[0].Content = dispAddr1;

//- If the calculated row count is 5, that means there is an address2...
if (rowCount == 5)
{
   //- Address 2
   //table.Rows[3].Cells[0].SetBorders("Thin","Black","Top","Bottom","Left","Right");
   table.Rows[3].Cells[0].Margins = CellMargins;
   table.Rows[3].Cells[0].VAlign = "middle";
   table.Rows[3].Cells[0].Content = dispAddr2;

   //- Address 3 (city, state, zip)
   //table.Rows[4].Cells[0].SetBorders("Thin","Black","Top","Bottom","Left","Right");
   table.Rows[4].Cells[0].Margins = CellMargins;
   table.Rows[4].Cells[0].VAlign = "middle";
   table.Rows[4].Cells[0].Content = dispAddr3;
}
else
{
   //- Address 3 (city, state, zip)
   //table.Rows[3].Cells[0].SetBorders("Thin","Black","Top","Bottom","Left","Right");
   table.Rows[3].Cells[0].Margins = CellMargins;
   table.Rows[3].Cells[0].VAlign = "middle";
   table.Rows[3].Cells[0].Content = dispAddr3;
}

return table.MakeTags();

Thanks again Dan for all of your help!

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...