Scalable text size to fit inputted font onto label

// Expert user has replied.
V Vince Quach 2 years 11 months ago
1708 2 0

Not sure if this is possible, but I'm writing a light Windows application in C# to generate labels based on what the user types in. It's meant to circumvent having to use ZDesigner to get the positioning and measurements in place every time the user wants to create a simple text label. I generated the ZPL for the template with a $(text) field in place of the content and whatever the user types replaces it.

The only issue I'm having is accounting for various user inputs of different string sizes. Is there a ZPL command to do this with? Font doesn't matter so if a specific font is required then that's okay too. The edge cases wouldn't be ridiculous where they type absurdly long text, but to account for differences in strings like "Sample 184 FAM CPG 11/20/21" vs "Samples 220-280 Yakima Yellow 11/20/21" where the former is slightly shorter than the latter, and hopefully you can get the idea of how the text can vary without being too unrelated. I know the ^FB command exists but it doesn't seem to scale the text size itself.

Please Register or Login to post a reply

2 Replies

S Steven Si

The ^FB doesn't scale the size. Instead, it wraps around the text into multi-lines within the box to accommodate the variable length of string. In ZPL, there is no auto scale. The font and the size are prespecified by the ^A command. You can change the font by issuing a new ^A command with new font and size. The best bet to accommodate the variable length of string is the ^FB.

W Ward Christensen

I had the same need - but just to calculate how long a string was.
I chose the font 0, scalable, and did my testing at a character size of 50.
I created a file of all characters, digits, and symbols, one per line strung out.
I printed, then edited the lines to include the number of each specific character necessary to have the same printed line length
From that, I created a table of character widths, and then I could PROGRAM to use that table with arbitrary input to determine the width of a string.
More calculations can be done then based upon these values to accommodate different ^A0 font sizes, such as lowering the font size to fit within a certain label width.
While what I'm giving is NOT a "solution", it is the _DATA TABLE_ that you need to write your own.
Sample of what I used - THIS WAS FOR DEVELOPMENT OF THE TABLE, NOT SOMETHING YOU HAVE TO DO:
^FO50,120^FDAAAAAAAAAAAAAAA^FS
^FO50,150^FDBBBBBBBBBBBBBBB^FS
^FO50,180^FDCCCCCCCCCCCCCCCC^FS
^FO50,210^FDDDDDDDDDDDDDDD^FS
^FO50,240^FDEEEEEEEEEEEEEEEEE^FS
^FO50,270^FDFFFFFFFFFFFFFFFFF^FS
^FO50,300^FDGGGGGGGGGGGGGGG^FS
^FO50,330^FDHHHHHHHHHHHHHH^FS
^FO50,360^FDIIIIIIIIIIIIIIIIIIIIIIIIIIIIII^FS
As you can obviously see and expect, "I" is a very narrow character, so it took 30 I's to make a line that printed the same width as 15 G's.
So in very rough and unlikely correct code you'd want to write a
zpl_string_length(char *msg);
subroutine which does this - well in my own programming language, the editor KEDIT
msg_wid = 0
do i = 1 to length(msg)
msg_wid = msg_wid + lookup_char_width(msg[i]);
end
return msg_wid

That didn't account for the FONT SIZE, only for the relative character widths. But it gives a number you can "fiddle with" to be the width you need, perhaps in 'mm'. The A0 font of A0hh[,ww] where ww defaults to hh if not specified, would be your "scale factor" for "width depending upon font size".

Here is the vital data, relative character widths of the ^A0 font
' '=117 '!'=113 '"'=183 '#'=183 '$'=183 '%'=366 '&'=235 ''"=113 '('=113 ')'=113 '*'=183 '+'=330
','=110 '-'=366 '.'=113 '/'=113 '0'=183 '1'=183 '2'=183 '3'=183 '4'=183 '5'=183 '6'=183 '7'=183
'8'=183 '9'=183 ':'=117 ';'=117 '<'=366 '='=366 '>'=366 '?'=165 '@'=330 'A'=220 'B'=220 'C'=206
'D'=235 'E'=194 'F'=194 'G'=220 'H'=235 'I'=110 'J'=173 'K'=220 'L'=183 'M'=300 'N'=235 'O'=220
'P'=220 'Q'=220 'R'=220 'S'=206 'T'=183 'U'=235 'V'=206 'W'=300 'X'=206 'Y'=206 'Z'=194 '['=113
'\'=192 ']'=113 '^'=192 '_'=194 '`'=113 'a'=173 'b'=194 'c'=173 'd'=194 'e'=183 'f'=106 'g'=194
'h'=194 'i'=100 'j'=100 'k'=173 'l'=100 'm'=300 'n'=194 'o'=183 'p'=194 'q'=194 'r'=126 's'=165
't'=106 'u'=194 'v'=173 'w'=253 'x'=173 'y'=173 'z'=150 '{'=194 '|'=194 '}'=194 '~'=192
If you want these formatted as an array initializer, if I'm remembering right, it would be 95 elements initialized to
[117,113,183,183,183,366,235,113,113,113,183,330,110,366,113,113,183,183,183,183,183,183,183,183,183,183,117,117,366,366,366,165,330,220,220,206,235,194,194,220,235,110,173,220,183,300,235,220,220,220,220,206,183,235,206,300,206,206,194,113,192,113,192,194,113,173,194,173,194,183,106,194,194,100,100,173,100,300,194,183,194,194,126,165,106,194,173,253,173,173,150,194,194,194,192]

**** NOTE **** When I printed my list of strings (AAAAA..) neither '^', '\', nor '~', printed, as they all have special interpretations. I COULD have swapped my escape chars for '^' and '~', so I could find their width, but since they're hard to print, I just don't print them.
I found the average char width to be 192, so set those to 192. NO OTHER CHARACTERS are 192 wide, so if you want a combination "zpl_string_length" and error detect, you could return a 0 (=error) if any 192 wide characters exist in the passed string.

Then there's the calculation you'll have to figure out - I can't remember how I came up with these numbers, but try this:
font_width = label_width *389 /zpl_string_length()
I don't recall how I came up with 389, but it worked for me.
I only did font size 50, so "somewhere there" you'd have to multiply by some factor * font_width.
____________
If you have any need for dense printing VERTICALLY, i.e. lines as close as they can be, the method would be to scan a string to see if it has any descenders, requiring the next line to start at a lower point than if it had no descenders.
I'd found there to be two descending distances in font ^A0
So you'd code something like this:
Small_descenders = '(),/;[\]Q{|}'
Small_descenders_fudge = 1.1
Full_descenders = 'gjpqy'
Full_descenders_fudge = 1.2
descender_fudge = 0
then scan the string for Small_descenders, and set the fudge to 1.1 if you find any,
THEN scan the string for Full_descenders, and set the fudge to 1.2 if you find any.
THEN you save the extra fudge to adjust the NEXT LINE's vertical starting point distance from the previous line, fudged by 1.1 or 1.2 times the "tight" spacing you may be computing.

I hope my "hacking" can help you.
Ward Christensen, inventor of "Xmodem" and inventor/programmer of the world's first BBS (Bulletin Board System)

CONTACT
Can’t find what you’re looking for?