2

I am trying to use Code128A.ttf font to generate barcodes. I have been using the same font for years in Windows 2000 and 2003 with Delphi. However, when I try to use the font now with C# and .NET 4.5 in Windows 8.x, all of the text characters seem to work, however, the start and stop code characters do not render the same as the Windows Character Map shows them.

For example: In the Character Map, \u008A shows a nice Code128 stop code barcode glyph in the Character Map. However, when Graphics.DrawString renders it, the character looks like the Š "Latin Capital S with caron". Similarly, the Code128 start code \u0087 is rendered by graphics.DrawString as the "Double Dagger" instead of its Character Map barcode glyph.

Failed Platform = Windows.Forms, C#, .NET 4.5, Visual Studio 2013, Windows 8.1 Last known working platform was = Delphi 6 (VCL)/Nevrona RAVE, Windows Server 2003

I'm hoping I'm just missing a setting or something simple.

void On_PrintPage(object sender, PrintPageEventArgs ppea)
{
    string sCodeAStart = "\u0087";  // Code128A.ttf's glyph for Start A 103
    string sStopCode = "\u008A";    // Code128A.ttf's glyph for StopCode 106
    int iCheckDigit = MyCheckSumFunction(103, "500014630");
    string sBarcode = sCodeAStart + "500014630" 
                      + ((char)iCheckDigit).ToString() + sStopCode;
    Font fontBarcode = new Font("Code128A", 24, FontStyle.Regular);
    ppea.Graphics.DrawString(sBarcode, fontBarcode, Brushes.Black, 100, 100);
}

Code128A.ttf Character Map with Stop Character selected. Code128A.ttf Character Map

DrawString Not Rendering Start and Stop Glyphs Properly DrawString Not Rendering Start and Stop Glyphs Properly

This is what it should look like

enter image description here

gridtrak
  • 731
  • 7
  • 20
  • Added an example code snippet. I tried things like `ppea.Graphics.TextRenderingHint = TextRenderingHint.SingleBitPerPixel;` but it only changes the appearance of the characters. Maybe the code page is the problem. I was only looking at the Character Map for the glyph's index in the font. I expected WYSIWYG like all the other fonts and the way it used to work. – gridtrak Sep 10 '15 at 02:49
  • I tested the Code128A.ttf font by pasting the "\u008A" character into NotePad and it worked fine. So the problem is definitely in the .NET Drawing implementation. I tried a half dozen of the `byte gdiCharSet` values for that `new Font(,,,)` parameter with no change. The problem is probably related to code page setup. How do I change the code page for the .NET graphics routines? How do I determine which code page will correctly render my Code128A font? – gridtrak Sep 10 '15 at 03:49
  • `System.Text.Encoding` provides the methods for manipulating the code page and encoding/decoding characters, bytes, strings, etc. After testing a few code pages, the only variance was between 7bit and 8bit. In 7bit code pages, the start and stop codes get converted to 7bits and end up as printed barcode characters - just not the correct characters! I do not think the code page is the issue; unless I just didn't figure out which one works. There are thousands of code pages, so trial and error is not going to work for me! – gridtrak Sep 10 '15 at 04:56
  • I discovered the problem is an encoding issue. `DrawString("‡...Š", ...)` WORKS! `DrawString("\u0087....\u008A", ...)` (and variations like \x0087 \u87 \x87) do not work. The answer to my question will be how to use the System.Text.Encoding routines to convert (char)135 to "‡". – gridtrak Sep 10 '15 at 15:06

3 Answers3

2

This is rather mysterious problem. The only real lead are the Unicode code-points, \u0087 and \u008A are control characters and have no glyph. If you run this code on a clean machine then you'll see them being rendered as rectangles. In other words, there is not a single font on such a machine that has a glyph for them.

What you get, Š and ‡ are not completely random, those are the glyphs for character codes 0x87 and 0x8A in code page 1252.

This is wildly strange behavior of course, Graphics.DrawString() is a pure Unicode function and never considers an 8-bit encoding like cp1252.

The only logical theory is that Windows decides to go looking for a glyph for these control characters. And your machine has another font that has these code-points defined. And, for some reason, it likes that font better than your barcode font.

So one thing you'll want to do is go chasing for that font and uninstall it. Should be easy enough to find with Charmap.exe. And in general suspect a dirty machine problem, there are registry keys that affect the font mapper that could have been tinkered with.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
1

I believe you need to use font something like this

PrivateFontCollection foo = new PrivateFontCollection();
foo.AddFontFile("code128.ttf");
// Some more code 
Font fontBarcode = new Font((System.Drawing.FontFamily)foo.Families[0], 24, fs);
g.DrawString(sBarcode, fontBarcode, System.Drawing.Brushes.Black, 100, 100);

It created a image like this

When Font was added with PrivateFontCollection

Whereas if I change the sCodeAStart and sStopCode to Hexa values like this

string sCodeAStart = "0x87"; 
string sStopCode = "0x8A";  

Than the output was like this When changed from Unicode to Hexa Values

I have tried to search for Code128A but could not found. So the code was written for Code128.ttf. Hope this helps

Mohit S
  • 13,723
  • 6
  • 34
  • 69
  • Thank you for your excellent example on how to import fonts on the fly. I still have the same bad results in my project. I am using the "c128att.ttf" Code128A font (version 1.0, Oct 6, 1992, Rivers Edge) from In my original question, I added an image for what a good Code128 barcode will look like. The second image you provided does not show a stop code (2331112 bar/space weights). This might just be due to which character/glyph the particular font file is using for the stop code. Which "Code128.ttf" are you using? – gridtrak Sep 10 '15 at 13:35
  • 1
    I am using a [Code128](http://www.dafont.com/code-128.font) font to create this program. You can use this. Or You can go for creating Barcode by using [Zen.Barcode](https://barcoderender.codeplex.com/) if in case you are just doing it for creating BarCode. – Mohit S Sep 11 '15 at 01:25
  • that'll just put the actual text around the barcode... for code "500014630" you'll just end up having a barcode containing "0x875000146300x8A" – Nyerguds Apr 18 '20 at 17:58
0

The answer is simple: The Character Map Unicode characters use the "U+####" index (bottom left of the Character Map application window), not the single byte character index.

The Unicode string for the start code in the Code128A is "\u2021"="‡" (which you type ALT+0135 to get using a US keyboard), NOT the legacy character index: "\u0087", "\x0087", (char)135, etc.

The problem was my code was based on legacy (char)### single byte character ordinals, however, DrawString handles its string as multi-byte characters (Unicode). The actual "\u2021" start and "\u0160" stop characters in the Code128A font I am using may be different in other barcode fonts.

In other words, my input string to Graphics.DrawString was not Unicode matching the font's character map. The result was good old Garbage In = Garbage Out!

gridtrak
  • 731
  • 7
  • 20