10 February 2025
The little Python script I wrote last night was able to open the ‘occident’ file of Hershey font descriptions and then import them into a list of lines. I then iterated over the list, line by line, extracting the character number, the number of vertices as well as the left- and right-hand extents of each of the characters, then write them to the console.
I added some more analysis to the script to get a better feel for the data. Each line can be a different length, as each character can have as many or as few strokes defined as it needs. The number of vertices should give me a clue to the actual length of the line. Since each vertex, which I’m just remembering includes the character extent pair as the first vertex, is exactly two bytes long, and the line header is fixed at 8 bytes, the formula:
vertices * 2 + 8
gives us the expected length of the line. This is the case except for these character numbers:
Actual Calculated
Number Vertices Width Length Length
------ -------- ------------- ------ ----------
2,331 3 <-13,20>=[33] 214 14
3,258 4 <-10,11>=[21] 216 16
3,313 28 <-16,16>=[32] 264 64
3,323 43 <-16,17>=[33] 294 94
3,502 10 <-12,12>=[24] 228 28
3,508 12 <-12,12>=[24] 232 32
3,511 15 <-12,12>=[24] 238 38
3,513 7 <-14,14>=[28] 222 22
3,518 8 <-12,12>=[24] 224 24
And I see a pattern. Looking at the original data for character number 2,331, we have this very long line:
2331103EfNSOUQVSVUUVSVQUOSNQNOONPMSMVNYP[S\V\Y[[Y\W]T]P\MZJXIUHRHOIMJKLIOHSHXI]KaMcPeTfYf]e`cba RKLJNIRIXJ\L`NbQdUeYe]d_cba RPOTO ROPUP RNQVQ RNRVR RNSVS ROTUT RPUTU RaLaNcNcLaL RbLbN RaMcM RaVaXcXcVaV RbVbX RaWcW
It very clearly declares that there are 103 vertices, but my conversion resulted in a 3, so I’m obviously not pointing to the right segment of the string when extracting that value, missing out on the hundreds digit, for the very small number of characters that have over 100 vertices.
And that’s what it was. I incorrectly specified the ‘slice’ parameters of the vertex segment of the string. I am not very good at the Pythoning yet, but I am getting better.
So now I have some faith in the internal consistency of the data preserved lo these many years. Now I can move on to actually extracting the coordinate pairs from each string, knowing the exact moment that I should stop.
More Python trial and error has produced a working model that will output the coordinate pairs for each character, along with the ‘pen up’ commands.
Now I need to translate that into a series of simple commands that I can send to the OLED device via the serial link and have them drawn on the screen to visualize the characters.
I needed to install PySerial as a module so that Python can talk to the serial port:
python3 -m pip install pyserial
It installed pyserial-3.5.
The serial port available via the WCH-LinkE is found in the /dev folder as:
/dev/cu.usbmodemC0F98F0645CF2
I’ve got a good start on the Python script. It’s pushing out the coordinates both to the console and the serial port. I re-formatted the coding going out the serial port into ‘move to’ commands and ‘draw to’ commands. ‘Move to’ just updates the coordinates and ‘draw to’ actually draws the vector between the points.
As an intermediate stage, I was totally faking it by just drawing the endpoints of the vectors, and you could tell the overall shape of the character that way. I already had the point() function working, so that was an easy step. Adapting Bresenham’s line algorithm to the code was also staight-forward. It’s a delightful thought experiment and has been around longer than I have.
There are still some edge cases that bring them whole thing to its knees, such as character 907 and its -41 y-coordinate. I had added a +32 offset to the data points for serial transmission as a single byte, but that just didn’t work for our friend number 907. But I’ve seen enough of the characters drawn on the target OLED now to be sure that I want to go ahead and build these into the project.