Calculate Width of Scalable Font

I am using font 0 (zero) and cannot figure out how I can pre-determine whether a given font size and phrase will be too long for the badges that I am printing.

 

A good example can be seen here:

 

http://labelary.com/viewer.html?density=8&width=4&height=3&units=inches&index=0&zpl=%5EXA%0A%5EXA%0A%5ECF0%2C0%2C0%0A%5E…

 

Both words are 13 characters long and both have the same font size for height and width - but the "MASSACHUSETTS" line is too long.

 

Is there a way to calculate, ahead of time (meaning before I send the ZPL code to the printer) the total width of Zebra Font 0 with given text and font size?

Craig Anderson
I can't imagine I'm the only

I can't imagine I'm the only person who needs to do this?

Vote: 
Vote up!
Vote down!

Points: 0

You voted ‘up’


Anonymous (not verified)
Hi Craig,You are not, but we

Hi Craig,

You are not, but we don't really have a good answer for you.  Fonts are much more complicated than most people realize.  Determining the printed width of a string using a scaleable font essentially requires using a font engine to actually create the bitmap and size it.  I can see if we can get you more info on font 0 specifically, but you will essentially have to calculate the width character by character.  It would be easier to use a monospace scaleable font like "Courier New".  Unfortunately we only have monospcace bitmap fonts, which are not fully scalable by default on the printer. 

We do have a few essentially for free.  Let me know if you want one.  You can also convert several of the free Google fonts for use in our printers.

Vote: 
Vote up!
Vote down!

Points: 0

You voted ‘up’


Craig Anderson
Thanks for getting back to me

Thanks for getting back to me Robyn. The Internet basically has nothing on anything like this, so you're my last hope.

If you could get me more information on font 0 specifically, that would be great yes.

A prior developer that worked for a client of mine 15+ years ago, developed a solution that I'd like to run by you. I believe that it works similar to what you outlined - by calculating the width character by character. What I'm unsure of, however, is whether the base widths that he used are accurate (or where they even came from). A few quick example base widths:

  • !: 2602
  • #: 4228
  • 0: 4228
  • 1: 4228
  • 2: 4228
  • 3: 4228
  • A: 4879
  • G: 5204
  • ~: 8782
  • <: 87872

Does this look familiar to you at all?

For each character in the text to be printed, it takes the base width and divides it by 8782 (what appears to be the maximum character width) and then multiplies that by the desired font size. It then adds up all calculated character widths and sees if it will fit in the maximum width of the available printing area. If it doesn't fit, it starts the whole process over again, decrementing the desired font width by one.

It's not perfect, as I've found several scenarios where the calculation result is less than the maximum width - but the printed result ends up too long (and overlaps). If I use 770 for my maximum width instead of the actual 800 - it seems to work fine. But the whole solution feels held together with glue, and I don't love that I have no idea where those character widths came from.

Any insight on this solution, or another direction that I might go in, that you can provide would be greatly appreciated.

Vote: 
Vote up!
Vote down!

Points: 0

You voted ‘up’


Anonymous (not verified)
Hi Craig, Sorry, I don't

Hi Craig,

Sorry, I don't recognize the reference for those numbers.

I'll see what I can find, but until then, here are some articles you might find interesting:

Calculate Character Widths

Variable-width Fonts

Most of our printers print at 8 dots per mm.  ZPL takes font sizes in dots, not points.

Vote: 
Vote up!
Vote down!

Points: 0

You voted ‘up’


Craig Anderson
Were you able to find

Were you able to find anything?

Vote: 
Vote up!
Vote down!

Points: 0

You voted ‘up’


Craig Anderson
Checking in again, any luck?

Checking in again, any luck?

Vote: 
Vote up!
Vote down!

Points: 0

You voted ‘up’


Robert Wiley
I created a set of

I created a set of subroutines in VB.NET that calculates the length of a string for font 0. I printed all the characters out at 72 points and physically measured the distance each one occupies. These values are converted to printer dots for a 300 DPI printer and saved into a hash table similar to what you've described. The ASCII character code for each character is the key for the hash table.

The first VB.NET subroutine loads the hash table.

The second subroutine returns the length of a string in dots at a 72-point font size on a 300 DPI printer

The third subroutine returns a font size that is less than or equal to a given font size that will fit into a given area. It requires an array of text such as what would be placed into a field block (^FB)

Hope this helps in some way. I have looked for a better solution but haven't had any luck at all. The data in the hash table isn't perfect but it's worked out very well for my needs.

My VB.NET code follow:

Public gintHash(125) As Integer

Sub LoadHash()

        gintHash(32) = 305

        gintHash(33) = 287

        gintHash(34) = 471

        gintHash(35) = 471

        gintHash(36) = 471

        gintHash(37) = 890

        gintHash(38) = 598

        gintHash(39) = 287

        gintHash(40) = 293

        gintHash(41) = 293

        gintHash(42) = 471

        gintHash(43) = 847

        gintHash(44) = 325

        gintHash(45) = 1500

        gintHash(46) = 293

        gintHash(47) = 293

        gintHash(48) = 480

        gintHash(49) = 480

        gintHash(50) = 480

        gintHash(51) = 480

        gintHash(52) = 480

        gintHash(53) = 480

        gintHash(54) = 480

        gintHash(55) = 480

        gintHash(56) = 480

        gintHash(57) = 480

        gintHash(58) = 293

        gintHash(59) = 293

        gintHash(60) = 986

        gintHash(61) = 890

        gintHash(62) = 986

        gintHash(63) = 432

        gintHash(64) = 890

        gintHash(65) = 547

        gintHash(66) = 547

        gintHash(67) = 527

        gintHash(68) = 585

        gintHash(69) = 489

        gintHash(70) = 515

        gintHash(71) = 585

        gintHash(72) = 598

        gintHash(73) = 267

        gintHash(74) = 432

        gintHash(75) = 547

        gintHash(76) = 471

        gintHash(77) = 742

        gintHash(78) = 598

        gintHash(79) = 560

        gintHash(80) = 547

        gintHash(81) = 560

        gintHash(82) = 585

        gintHash(83) = 522

        gintHash(84) = 489

        gintHash(85) = 598

        gintHash(86) = 522

        gintHash(87) = 795

        gintHash(88) = 547

        gintHash(89) = 547

        gintHash(90) = 489

        gintHash(92) = 293

        gintHash(97) = 452

        gintHash(98) = 489

        gintHash(99) = 432

        gintHash(100) = 489

        gintHash(101) = 470

        gintHash(102) = 274

        gintHash(103) = 489

        gintHash(104) = 489

        gintHash(105) = 254

        gintHash(106) = 254

        gintHash(107) = 432

        gintHash(108) = 254

        gintHash(109) = 742

        gintHash(110) = 489

        gintHash(111) = 471

        gintHash(112) = 489

        gintHash(113) = 489

        gintHash(114) = 325

        gintHash(115) = 420

        gintHash(116) = 267

        gintHash(117) = 489

        gintHash(118) = 432

        gintHash(119) = 657

        gintHash(120) = 432

        gintHash(121) = 432

        gintHash(122) = 381

        gintHash(123) = 489

        gintHash(124) = 489

        gintHash(125) = 489

End Sub

Function intStringLen(strText As String) As Integer

        Dim intI As Integer

        Dim intLength As Integer = 0

        Dim intChrCode As Integer

        Dim intTotalLength As Integer

        ' function returns the total length of the string in printer dots for a font of 72 points (300 dots)

        Try

            If strText = "" Then Return 0

            intTotalLength = Len(strText)

            For intI = 1 To intTotalLength

                intChrCode = Asc(Mid(strText, intI, 1))

                Select Case intChrCode

                    Case 32 To 125

                        intLength += gintHash(intChrCode)

                    Case Else

                        intLength += 833

                End Select

            Next 'intI

            Return intLength

        Catch ex As Exception

            'Catch errors here

        End Try

        Return intLength

End Function

Function strFontWidth(strTextArray() As String, intPrintArea As Integer, StrCurrentFontWidth As String) As String

        Dim intBase As Integer

        Dim intLength As Integer

        Dim intMaxLength As Integer = 0

        Dim intCurrentFontWidth As Integer

        Dim intJ As Integer

        Dim intMinBound As Integer

        Dim intMaxBound As Integer

        ' Function returns the largest font width that will fit in a given print area that is no larger than the current font width

        Try

            intBase = intPrintArea  * 1000    'print area in printer dots * thousandths of an inch

            intCurrentFontWidth = Val(StrCurrentFontWidth)

            intMinBound = LBound(strTextArray)

            intMaxBound = UBound(strTextArray)

            For intJ = intMinBound To intMaxBound

                intLength = intStringLen(strTextArray(intJ))

                If intLength > intMaxLength Then

                    intMaxLength = intLength

                End If

            Next

            intLength = intBase \ intMaxLength

            If intLength > intCurrentFontWidth Then intLength = intCurrentFontWidth

            Return Trim(Str(intLength))

        Catch ex As Exception

            'Catch errors here

        End Try

        Return Trim(Str(intLength))

End Function

Vote: 
Vote up!
Vote down!

Points: 0

You voted ‘up’


Craig Anderson
First, thanks for replying

First, thanks for replying here. It's nice, if nothing else, to know that I'm not the only person who struggles with this problem.

You said that you printed all the characters at 72 points and physically measured them - sorry if this is a dumb question, but what did you use for measurement?

Vote: 
Vote up!
Vote down!

Points: 0

You voted ‘up’


Robert Wiley
I measured them with a small

I measured them with a small steel ruler. At 72 points (300 printer dots) the characters were large enough to measure fairly close. Granted my process wasn't perfectly accurate and I have not accounted for the variable kerning between various characters but it seems to be within about +-5%. I use these routines to fit text on a lot of labels and to place a registered trademark symbol at the end of different lines of text. In areas where maximum font size is critical I usually drop the font size by a dot or decrease the print area by 5%.

Vote: 
Vote up!
Vote down!

Points: 0

You voted ‘up’


Duong Geraldo
You can find a solution on

You can find a solution on https://studenterra.com/, I've always asked for help there.

Vote: 
Vote up!
Vote down!

Points: 0

You voted ‘up’


Anonymous Anonymous
Same issue here!

I have the same issue.
Is it possible to extract the Font0 from the Printer or download it somewhere from the Internet?
If that is possible, I could read chracter widths from the font file itself and create a function to calculate text wide (and so it would be possible to calculate text size which fits whole text on the label).
Printing and measuring every character manually is not an option as we are using a wide range of chracters (not only a-Z).

Vote: 
Vote up!
Vote down!

Points: 0

You voted ‘up’


Robin West
CG Triumverate Bold

Font 0 is essentially the truetype font by Monospace called CG Triumverate Bold.

Vote: 
Vote up!
Vote down!

Points: 0

You voted ‘up’


George Tziros
I would also like to unload

I would also like to unload the 0 scaleable font from a Zebra printer so that i can include it in the ZPL code using the ~DS command.

Is this possible?
Is the default 0 scaleble font one of the FNT files on the Z drive on the printer?

Thanks

Vote: 
Vote up!
Vote down!

Points: 0

You voted ‘up’


Robin West
Override the designation

Hi George, There is a way to get the effect without actually removing font 0.  It is one of the fonts on the Z drive and there is no way for users to delete it.  You can download your font and override the font designation though and get the functionality. Download it normally using it's standard name so you can find it or even have multiple fonts loaded.  Then use the ^CW command to change the font designation to '0'.  You can verify if it worked by pulling a directory listing, the new font should have a '0' preceding the name in the listing.

Vote: 
Vote up!
Vote down!

Points: 0

You voted ‘up’


George Tziros
Thanks Robin, What I'm trying

Thanks Robin, What I'm trying to do is give our customers a virtual printer. This is for testing only where a physical printer is not available. i.e. For testing at home!
To recreate an exact duplicate of the printed label I need the 0 font off the printer and then I can include it in the ZPL for printing to the screen. If that is possible?
Thanks

Vote: 
Vote up!
Vote down!

Points: 0

You voted ‘up’


Robin West
Sorry

Hi George, I'm afraid not. Using the CG font is the closest you are going to get.
Fonts are licenced and heavily copyright controlled. You might be fine with a personal use app, but Zebra is held liable if you download the font from our printer, regardless of what you use it for.

Vote: 
Vote up!
Vote down!

Points: 0

You voted ‘up’


George Tziros
OK I understand thanks.

OK I understand thanks.
What did you mean by the CG font is the closest i could get?

Thanks

Vote: 
Vote up!
Vote down!

Points: 0

You voted ‘up’


Robin West
CG Triumvirate Bold

Sorry, I posted a previous comment in this thread to someone else.  The font 0 is pretty much the Monotype font called CG Triumvirate™ Bold.

Vote: 
Vote up!
Vote down!

Points: 0

You voted ‘up’


Log in to post comments