RFC 199

Suggestions for a Network Data-Tablet Graphics Protocol

πŸ“… published July 1971, from ietf

RFC 199: SUGGESTIONS FOR A NETWORK DATA-TABLET GRAPHICS PROTOCOL πŸŽ€

okay bestie, the title block first ✨ this is from the Network Working Group, written by T. Williams at SDC, with NIC number 7151, dated 15 July 1971 πŸ’€ it's so old and so iconic. The original doesn't list a category or status, and it doesn't say it obsoletes or updates anything, so there's no drama there 🫢

Disclaimer πŸŽ€

The work reported here was supported by the Advanced Research Projects Agency of the Department of Defense under Contract DAHC15-67-C-0149, ARPA Order No. 1327, Amendment No. 3, Program Code No. 1D30, and 1P10.

The views and conclusions in this document are the author's own. They shouldn't be read as necessarily representing the official policies, either expressed or implied, of the Advanced Research Projects Agency or the U. S. Government. 🫢

INTRODUCTION ✨

okay so the whole point of this doc is for SDC to drop their two cents into the ARPA Network crew's chat about a protocol for network graphics πŸ’¬ we care about two areas here: non-interactive graphics and data-tablet graphics, which is different from fully interactive graphics πŸ¦‹

non-interactive graphics is when people barely touch the display at all. think data retrieval systems that show info as charts, X-Y graphs, histograms, scatter plots, tabular displays, and stuff like that πŸ“Š every time you interact with the system, you get a brand new display. the displays don't have much structure, and you aren't really poking at the picture itself, maybe except for some light buttons πŸ’…

it's super important that non-interactive graphics stay simple to implement and use on the network πŸ“ so the vibe is: design the graphics protocol around non-interactive graphics first, then add the stuff interactive graphics needs as a super-set on top. that way the complicated interactive stuff doesn't end up messing with people who only want non-interactive graphics 😭 the alternative would be building a non-interactive subset out of a protocol that started out interactive, and that's the lowkey messy route we're avoiding πŸ™ˆ

also, the section of Request for Comment (RFC) 177 that describes actual display instructions is a good basis for a non-interactive graphics protocol 🌸 so the plan is: start with it, build a protocol for generating a picture, and then work out the organizational and structural info that interactive graphics needs later 🧚

DATA-TABLET GRAPHIC INPUTS πŸ¦‹

data-tablet graphics is our main focus πŸ’– there are lots of different data-tablet implementations, but they act similarly enough that we can treat them as one class ✨

so data-tablet input is a triple of info: X, Y, and Z 🌈 X is the distance along the abscissa, Y is the distance along the ordinate (both are usually measured to a precision of 1 in 1024), and Z is how far the stylus is above the writing plane. Z can be encoded in a bunch of ways, from a simple on/off binary to three or more values showing distances from right on the surface to several inches up. for what we need here, we're just gonna treat Z as a binary thing 🫢

input timing also changes depending on the tablet and how it's installed πŸ’… it can be:

  • single shot, where you get one coordinate point each time Z says the stylus is on the writing surface
  • asynchronous, where the tablet gets sampled on demand from the driving program or interface logic when certain conditions are met, like the pen moving a certain amount from the last sample, or the program being ready for another sample after some variable amount of processing
  • clocked synchronous, where a timing pulse is what asks for the sample

clock rates are all over the place too, from one or two samples per second up to nearly 5000 samples per second πŸ”₯ some clocks are fixed, and others get controlled by the program or by external switches.

ngl the data-tablet input is way more voluminous than a similar computer-generated image 😭 and the stream also has temporal info that is, in some cases, vital for processing the input correctly ⏰ so we have to find ways to build a data-tablet graphics protocol that's flexible enough for a wide range of data volumes, and that still works with the protocol for non-interactive display images πŸ‘‘

PROPOSED DATA-TABLET INPUT PROTOCOLS πŸ’…

okay the range here is wild πŸŽ€ data-tablet input could be a single point (like when something's just being pointed at) or literally thousands of bytes for a hand-drawn picture or a line of text ✍️ a lot of the time, the raw input gets preprocessed before it reaches the main processing program. that preprocessing can include smoothing algorithms, filtering for thinning or redundancy removal, detecting operator actions (like uniquely marking each time the pen goes down on the writing surface and comes back up), and maybe other, more exotic stuff like corner detection or fitting straight-line segments 🧠 but most of those fancier processes won't be included in the protocol, since they're usually unique to a particular investigator and their research πŸ™ˆ

so a data-tablet graphic protocol should let the sender specify, and the receiver tell apart, at least four types of data-tablet input 🌸

  1. Single-shot data
  2. Unpreprocessed (raw) asynchronous data
  3. Unpreprocessed (raw) synchronous data
  4. Preprocessed data

we'll define formats for the first three, then talk through the fourth in detail before defining its format πŸ¦‹

okay now the bit-saving trick 🀏 data-tablet info should be sent in incremental form: a first point, then the difference between each point and the one before it 🧚 to get rid of trailing zeros that might be needed for compatibility with the standard network graphics screen, there's a scale factor that all the increments should get multiplied by before use ✨

Single-Shot Data Input Format πŸ’–

Byte 0:   Data tablet input op code

Byte 1:   Type, 0 = single shot

Byte 2-3: X - Coordinate

Byte 4-5: Y - Coordinate

      8          8            16             16
+----------+----------+---------------+---------------+
| Op code  |     0    |   X - coord.  |    Y coord.   |
+----------+----------+---------------+---------------+
      0          1         2     3         4     5

in the next formats, we're assuming each "stroke" of the pen gets sent as one entity πŸ–ŠοΈ a stroke is the data generated (and processed) from when Z says the stylus is on the writing surface until it's lifted off 🫢

Unpreprocessed (Raw) Asynchronous Data Input Format 🌊

Byte 0:     Data tablet input op code

Byte 1:     Type, 1 = raw asynchronous

Byte 2:     Flags

Byte 3:     Scale of deltas

Byte 4-5:   Number of points

Byte 6-7:   1st X-coordinate

Byte 8-9:   1st Y-coordinate

Byte 10:    delta X1

Byte 11:    delta Y1

        .
        .
        .

Byte 2n+10: delta Xn

Byte 2n+11: delta Yn


 8   8    8     8      16      16      16     8     8        8     8
+--+---+-----+-----+---.---+---.---+---.---+-----+-----+  +-----+-----+
|Op| 1 |Flags|Scale|  N.o  |   .   |   .   |delta|delta|..|delta|delta|
|  |   |     |     |poi.nts| X0.   | Y0.   | X1  | Y2  |  | Xn  | Yn  |
+--+---+-----+-----+-------+-------+-------+-----+-----+  +-----+-----+
 0   1    2     3    4   5   6   7   8   9   10     11     2n+10 2n+11

Unpreprocessed (Raw) Synchronous Data Input Format ⏱️

Byte 0:     Data tablet input op code

Byte 1:     Type, 2 = raw synchronous

Byte 2:     Flags

Byte 3:     Scale of deltas

Byte 4:     Sampling rate to the nearest 100 usec

Byte 5-6:   Number of points

Byte 7-8:   1st X-coordinate

Byte 9-10:  1st Y-coordinate

Byte 11:    delta X1
                    (sign magnitude code)
Byte 12:    delta Y1
        .
        .
        .

Byte 2n+11: delta Xn

Byte 2n+12: delta Yn

 8  8   8     8    8     16      16    16    8     8        8     8
+--+-+-----+-----+----+---.---+---.-+---.-+-----+-----+  +-----+-----+
|Op|2|Flags|Scale|Rate|  N.o  | X0. | Y0. |delta|delta|..|delta|delta|
|  | |     |     |    |poi.nts|   . |   . | X1  | Y1  |  | Xn  | Yn  |
+--+-+-----+-----+----+----------+--+-----+-----+-----+  +-----+-----+
 0  1   2     3    4    5   6  7  8  9  10   11   12      2n+11 2n+12

PREPROCESSED-DATA INPUT FORMAT ✨

okay so before raw tablet data even gets sent off to the program asking for it, there are a bunch of processing steps that can be applied to it 🧼 like, when the tablet is "noisy" or jittery (so relatable 😭), various smoothing algorithms may be applied. The most common one is some form of weighted, clumped, or moving average. At SDC we've settled on an 8-point moving average whenever smoothing is desirable πŸ’…

another super common move is "thinning" (aka filtering) to clear out unnecessary or redundant data points πŸ—‘οΈ depending on what the data is for, filter "windows" can come in all kinds of geometries (square, rectangular, diamond, circular, the whole squad πŸ”·β­•), and the filter may be single or double windowed. SDC currently uses a single square window filter on all tablet input 🟦 the window size is a variable and may be set to zero, which basically switches the filter off πŸ™ˆ

Logic time 🧠 the filter may be described as:

   Take (X,Y) if |Xp - X| >= w or |Yp - Y| >= w is true

where (X,Y) is the current data point, (Xp,Yp) is the previously accepted data point (the one that passed the filter, or the very first point of the stroke), and w is the window size.

Picture it like this πŸ–ΌοΈ

         ---- +-------------+-----
          ^   |             |  ^
          |   |             |  |
              |             |  W
          2W  |  Xp, Yp   __|__v__
              |             |
          |   |             |
          v   |             |
         -----+-------------+
              | <-- 2W -->  |

Any point inside the square gets rejected 🚫, and any point on the boundary or beyond it gets accepted and becomes (Xp,Yp) πŸ‘‘

Here's where it gets extra πŸ€“ our character recognition algorithms need to be able to estimate the velocity along the path of the stroke. So on top of saving the X,Y coordinates that pass the filter (smoothing, if it's done, comes before filtering and runs on the raw points), we also count and store the number of rejected points between the saved ones πŸ”’ since the data-tablet input is synchronous, the count times the sampling rate divided into the distance between adjacent points is a sufficient approximation for our purposes πŸ“ and our character generator also needs the rectangle surrounding a stroke (defined by the minimum and maximum values of X and Y in the stroke) πŸ“¦ which is super easy to generate during preprocessing ✨

Now, assuming other Network nodes wanted to use SDC's tablet graphic software (the character recognizer especially πŸ‘€), they'd have to know what preprocessing, if any, was done to the input data before it was sent πŸ€” so our suggested format for this type of tablet data is:

      Byte 0:     Data tablet op code

      Byte 1:     Type, 3 = preprocessed

      Byte 2:     Flags

      Byte 3:     Scale of deltas

      Byte 4:     Sampling rate if synchronous (as indicated by flag)

      Byte 5:     Window Size

      Byte 6-7:   Number of Points

      Byte 8-9:   1st X-coordinate

      Byte 10-11: 1st Y-coordinate

      Byte 12-13: Minimum value of X in the stroke

      Byte 14-15: Minimum value of Y in the stroke

      Byte 16-17: Minimum value of X in the stroke

      Byte 18-19: Minimum value of Y in the stroke
Heads up πŸ‘€ as printed, both Byte 16-17 and Byte 18-19 are labelled "Minimum value", so I've kept every label exactly as it is.

From there it splits into two forms, depending on another flag πŸŒ€

        Counts included         and       Counts deleted

        Byte 20:       delta X1           Byte 20:         delta X1

        Byte 21:       delta Y1           Byte 21:         delta Y1

        Byte 22:       rejected point count1

        Byte 3n+20:    delta Xn           Byte 2n+20:      delta Xn

        Byte 3n+21:    delta Xn           Byte 2n+21:      delta Yn

        Byte 3n+22:    RPCn

Here's the counts-included layout πŸŽ€

8  8   8     8     8     8      16    16   16   16    16    16    16
--+-+-----+-----+-----+------+------+----+----+-----+-----+-----+-----+
  |3|Flags|Scale|Rate |Window|  #   | X0  | Y0 |Xmin|Ymin |Xmax |Ymax |
  | |     |     |     | Size |points|     |    |    |     |     |     |
--+-+-----+-----+-----+------+------+----+----+-----+-----+-----+-----+
 0 1   2     3     4     5     6  7  8 9 10 11 12 13 14 15 16 17 18 19


  8     8     8        8     8     8
-----+-----+-----+-//-----+-----+-----+
delta|delta| RCP1| //delta|delta| RCPn|
X1   |Y1   |     |    Xn  | Yn  |     |
-----+-----+-----+-//-----+-----+-----+
 20    21    22       20     21    22

                       Counts Included

And here's the counts-deleted version πŸ¦‹

8  8   8     8     8     8      16    16   16   16    16    16    16
--+-+-----+-----+-----+------+------+----+----+-----+-----+-----+-----+
Op|3|Flags|Scale|Rate |Window|  #   | X0 | Y0 |Xmin |Ymin |Xmax |Ymax |
  | |     |     |     | Size |points|    |    |     |     |     |     |
--+-+-----+-----+-----+------+------+----+----+-----+-----+-----+-----+
 0 1   2     3     4     5     6  7  8 9 10 11 12 13 14 15 16 17 18 19


  8     8     8        8     8
-----+-----+-----+   +-----+-----+
delta|delta|delta|...|delta|delta|
X1   |Y1   |  X2 |   |Xn   |Yn   |
-----+-----+-----+   +-----+-----+
 20    21    22       2n+20 2n+21

                       Counts deleted

The flags in this format don't just tell you whether the data is synchronous and whether the counts are there 🚩 they may also be used to indicate whether or not the data was smoothed and the type of filtering. Main-character flag energy πŸ’œ


CHARACTER SETS AND CHARACTER GENERATION ⌨️

Our character recognition work affects the proposed protocols in one other area: character sets and character generation πŸ”€ Figure 1 shows the displayable characters that are presently available. We have planned extensions that will bring the set to 192 characters, and the availability and use of our and others' extended character sets must be provided for in the protocol 🌸

The character-set problem, though, is the easy one 😀 when you're dealing with hand-printed input, the computer-generated output has to hold onto the geometry of the user's input, at least temporarily ✍️ that means being able to generate characters in a huge range of sizes, with variable aspect ratios (sizes for X and Y specified independently). Since that isn't an available hardware function, all of our characters are program generated πŸ–₯️ right now we specify character size and ratios as X and Y multipliers applied to a character prototype. The prototype is built on a 5" x 7" grid (extended if needed to handle the long tails on p's, q's, etc.), where the grid-line spacing is 2^-10 times the screen size. The big takeaway: network transmission must be capable of specifying those types of characteristics when needed 🫢

So we propose a message format that specifies:

  • Character code
  • Character position
  • Character height and width

Side note πŸ‘€ we'd rather the character origin be the left-hand baseline point instead of the center. The center is ill-defined unless the character space includes vertical extensions in both directions, and it's also hard to use variable spacing to justify characters of unequal width (an aesthetic consideration that matters on some displays) πŸ’…

Figure 1: SDC EXTENDED CHARACTER SET (see PDF file) πŸŽ€


Endnote πŸ“

Subscript notation is inline. See the PDF file for a complete view of this document. πŸ’–

         [This RFC was put into machine readable form for entry]
         [into the online RFC archives by Lorrie Shiota, 10/01]
πŸ“¦ where this page comes from