The goal of the Solartech Formatted Message (SFM2) format is to allow people to create pages with specified font sizes, line breaks, etc. It is, necessarily, an alternative to MULTI (the NTCIP format), but it's not a direct competitor, in that it's not concerned with feature parity or compatibility.
Unlike SFM, SFM2 specifies a dynamic page, with animated built-in graphics and flashing lines.
SFM2 pages are encoded in unicode, with a 3-byte binary header. The first byte is a binary encoding of the number of lines in the page. The second and third bytes are a big-endian unsigned short indicating the size of the rest of the page in bytes (basically, something suitable to be read in by Java's DataInput.readUTF()).
SFM2 is a tagged language. For the sake of easy parsing and reduced storage space, tags will be special characters, mostly from the unused portion of the first unicode plane (historical ascii) which historically came from terminal types, and are consequently completely useless in our context. Tags are not just escape characters, though, they may begin an escape sequence. (The most obvious is the named font escape tag.)
Lines are terminated by newline characters ("\n", i.e. 0x000a). Since determining newlines means parsing the entire mesage (since the length of a font name could easily be 10), the number of lines in the page is encoded in the first byte. For simplicity of parsing, every line must be terminated with a newline, including the last. This is true even if the page is one line long.
Font tags switch the current font. All of the characters on a line are aligned to the same baseline; characters in larger fonts are simply taller. Lines which are either too tall or too long should simply be truncated.
If no font is specified via a tag, the default font is 7pxRoadSafety-normal.
There are a number of built-in graphics which an SFM2 message may specify. Built-in graphics take the place of the line which they are specified on, so if there is any text on that line, it is ignored. If there is more than one graphic specified on a line, it is undefined which one wins. Built-in graphics may be static or animated.
The built-in graphics are:
ID | Graphic |
0 | Left Static Arrow |
1 | Right Static Arrow |
2 | Left Animated Arrow |
3 | Right Animated Arrow |
4 | Left Animated Chevrons |
5 | Right Animated Chevrons |
Flashing may be specified for static images. If it is specified on a line with animated graphics, the flashing tag is ignored.
If the flashing tag is specified on a line, that entire line flashes. The flashing rate may be specified in deciseconds for on-time and off-time. If a flashing tag is specified on the same line as an animated graphic, the flashing tag is ignored.
The special escape characters are:
Escape Character | Name | Meaning |
0x0000 | Reserved | There's no good reason not to use 0x0000 as a tag, but given how often null is used as something special, it's probably best to avoid it. |
0x0001 | 1 Line | This tag switches the current font to 20pxRoadSafety |
0x0002 | 2 Line | This tag switches the current font to 11pxRoadSafety |
0x0003 | 3 Line | This tag switches the current font to 7pxRoadSafety-normal |
0x0004 | 3 Line Bold | This tag switches the current font to 7pxRoadSafety-bold |
0x0005 | 3 Line Narrow | This tag switches the current font to 7pxRoadSafety-narrow |
0x0006 | 3 Line Condensed | This tag switches the current font to 7pxRoadSafety-condensed |
0x0007 | 4 Line | This tag switches the current font to 5pxRoadSafety |
0x0008 | Specified Font | This tag is used to specify a font by name. Immediately following two (ascii) numerals indicating the length of the font name, followed by the name. This name is the full name of the font to use. |
0x000b | Builtin Graphic | This tag is used to specify a builtin graphic. Immediately following are two (ascii) numerals which gives the builtin ID (see above) |
0x000c | Flash | Causes the line it's found in to flash. Immediately followed by two ascii numerals, the first giving the on time and the second giving the off time, both in deciseconds minus one (that is, the real value is one greater than the numeral). |