RFC 493
GRAPHICS PROTOCOL
GRAPHICS PROTOCOL ๐
okay bestie, let's get into RFC 493 ๐ It's a Network Working Group doc, and the authors are J. Michener (MAC), I. Cotton (MITRE), K. Kelley (U. of Ill.), D. Liddle (Ownes Ill.), and E. Meyer (MAC). The NIC number is 15358, it references RFC 282 and RFC 258, and it obsoletes RFC 292 ๐ซถ The header doesn't list a category or a date, so I'm not making one up ๐
Introduction โจ
so this doc is basically the opinions and decisions from the second meeting of the Network Graphics Group, which happened at the Stanford Artificial Intelligence Laboratory in late November 1971 ๐ It describes part of a proposed Network Standard Graphics Protocol for sending graphics data over the ARPA network. The main focus is the stuff graphics info looks like when it goes from a source (like an application program in the "Serving Host") to a display package that outputs to a graphics console at the "Using Host." It's a sequence of 8-bit bytes, and it's called the graphics output byte stream ๐
this doc is meant to be a starting point for discussion and experiments over the network ๐ง It does not cover the form or content of graphics input (data going from the Using Host to the Serving Host), and it doesn't cover how the connection between the hosts gets set up either. The committee will eventually make a proposal for the input side, and the Connection Committee (of the Network Graphics Group) handles the connection stuff ๐ซถ
this RFC describes the commands in the protocol by what they'd do on the receiving end, aka the Using Host ๐ฆ Some kind of subroutine package would be super useful on the Serving Host for apps sending graphics data, but this RFC is not going to comment on that ๐คทโโ๏ธ
also, you might notice there's no way for the Using Host to report logical errors in the graphics output byte stream back to the Serving Host ๐ That kind of facility would have to be built into the graphics input byte stream, because it's tangled up with most of the problems around synchronizing independent hosts. Lowkey a whole mess ๐
Background ๐
bestie, go read RFC 282, "Graphics Meeting Report" by Mike Padlipsky. It gives you the framework around this whole network graphics conversation ๐ It's also worth checking out the model in RFC 285, "Network Graphics" by Donald Huff ๐
Levels and Ground Rules Pertaining Thereto ๐
okay so the functions in the graphics protocol get sorted into a bunch of levels, partly based on how hard they are to implement ๐ Any host that says it implements the functions of level N has to implement all the lower levels too. So sites are expected to build things up incrementally ๐ฐ Implementations keep getting better as they add more and more functions, and each one should be able to tell a remote site that's requesting a graphics exchange which level it's at โจ A nice side effect is that each site can decide its own priorities for putting programmers on graphics protocol work versus other projects ๐
the other thing is that implementing level N doesn't need any knowledge of level N+1 ๐ง So a site can implement a level knowing (pretty firmly) that changes at higher levels won't mess with the level it already built. The Network Graphics Group could decide to redefine a level that's already been firmed up, and that's not the plan, but ngl the protocol is experimental and might have to change ๐
one more ground rule: a stream of commands and data that's valid at level K has to produce "identical" results on any interpreter at level K or higher ๐ฅ What they mean is that as long as the commands and data only use strictly defined operations, you should get similar pictures. The stuff that isn't strictly defined yet includes character size, where a character sits relative to the beam, how control characters in text output affect the terminal, and what happens when the beam moves or a line gets drawn outside the logical screen boundary ๐ This rule is what keeps things upward compatible, so an app written with features from a low-numbered level still works at sites that have moved on to higher levels ๐ฆ And anything that's "left unspecified" in the detailed operations descriptions below has to be explicitly specified in any public description of an actual implementation โจ
we're about to describe the framework that every level shares ๐ซถ
Basic Data Forms ๐ฆ
okay, the Network Standard Graphics Protocol expresses everything as a sequence of 8-bit bytes ๐ A command is a command byte followed by zero or more arguments. The same command byte always takes the same number of arguments in the same form, and each argument's length can be fixed or variable depending on the argument ๐
there are two kinds of arguments. The simple one is a "value," which is an 8-bit integer ๐ The other is a "string," which is a count followed by that many 8-bit bytes โจ If the count is between 0 and 127, it's sent in a single byte. If it's between 128 and 2**15-1 (where ** means exponentiation), it's sent in two bytes, with the high-order bit of the first byte set to one ๐ธ The first byte carries the seven high-order bits of the number, and the second byte carries the eight low-order bits ๐ง A string is the only argument type that can vary in length ๐
So whenever a command has optional arguments, they get represented inside a string ๐
coordinate data caused a LOT of discussion at the second Network Graphics Group meeting ๐ญ They decided on a two-dimensional Logical Coordinate System, and each interpreter of the graphic command byte stream is responsible for mapping that onto physical device coordinates ๐ The logical coordinate data is in twos-complement notation, it's fractional, each edge of the screen has unit length, and the origin is the center of the screen on the output device ๐
the vertical and horizontal edges of the output device's screen line up with X = -1/2 or X = +1/2-e (and the same for Y), where e is a small positive number set by how precise the fractional data is ๐ฅ The points (-1/2, -1/2), (-1/2, 1/2-e), (1/2-e, -1/2), and (1/2-e, 1/2-e) are explicitly meant to be visible points at the corners of the logical screen โจ For a non-square display surface, the implementer can make their own call ๐คทโโ๏ธ So the Logical Coordinate System has points with coordinates going from -1/2 up to a little less than +1/2 ๐ฆ
coordinate commands come in different modes ๐ซถ In absolute mode, a position is given by its coordinates in the Logical Coordinate System. In relative mode, you specify the difference between the position's coordinates and the current position's coordinates ๐ So a coordinate datum that's an argument for an absolute mode operation should fall in the range -1/2 to +1/2-e, and one for a relative mode operation should fall in the range -1+e to +1-e ๐
people at the second Graphics Group Meeting were interested in eventually allowing a very large coordinate space, with many bits of precision in each fractional coordinate ๐ The plan is to let the length of each coordinate datum, in 8-bit bytes, be set as a mode โจ At the meeting, they decided two bytes per coordinate would be enough for now ๐ธ So e in the discussion above is 2**(-15), which is one in the least significant bit of a 15-bit plus sign fractional coordinate ๐ง
text data gets sent as an argument to various commands so it can be displayed on the output device ๐ Network ASCII is used to represent characters ๐ At the lowest levels of the protocol, there's only one character size, whatever is "normal" on the display device ๐ If the device has no "normal" size, 72 characters per line would be the desirable choice ๐ At higher levels, you can specify the size of each individual character ๐ฅ
also, at the lowest levels, control characters get passed along to the device so it can do the best it can with them ๐ญ BUT the consensus from the graphics meeting was that at some reasonably low (but non-zero) level, carriage return, line feed, and backspace should be interpreted to do the right thing ๐ โจ
Okay so at the second Network Graphics Group meeting ๐, everyone agreed there should be two sorts of picture subroutines ๐. The big difference between them is how hard they are to implement ๐ ๏ธ. The simpler one got called a subpicture, and the fancier one got called a subroutine. This author thinks those names don't carry enough meaning to keep the two straight, so they propose standardizing on "simple subroutine" and "full subpicture" instead ๐ฆ.
The only parameter a simple subpicture can take is the "current beam position" โจ. So if you call it more than once in a picture, the only thing that changes between calls is a translation based on where the beam was when you called it ๐ธ. Full subpictures, though? They take parameters that can cause scaling, rotation, reflection, or literally anything else we come up with ๐.
It's planned that a subpicture definition only needs to be sent once (per network connection) ๐, and a "new picture" operation won't delete it ๐ง. That means a changing picture can be split into parts based on static versus changing info, and only the parts that change need to be resent to redraw it ๐ซถ.
Traditionally, picture subroutines that depend only on the initial beam position have been limited to relative data mode drawing operations ๐. Since subpictures will probably be used to save static picture info, it's desirable to allow absolute data mode operations in simple subpictures ๐ .
Next question: what does absolute data mean in a full subpicture that takes both position and scale parameters? Is absolute data really absolute here? ๐ค This author believes the answer is this: a full subpicture is really a picture in its own right, so it has its own logical coordinate system, and its absolute data lives inside that system ๐. So "shifting and scaling" a full subpicture really means "scale the subpicture in its own coordinate system and shift the result as a whole" ๐.
So the main difference is that a full subpicture has its own logical coordinate system, while a simple subpicture uses the logical coordinate system of whoever calls it ๐. That's exactly why full subpictures are harder to implement than simple ones ๐ญ.
Another thing discussed at the meeting was a special data mode where a subpicture can display data at absolute positions on the screen, i.e., absolutely in the main (picture) program โจ. To do this, the meeting proposed special data modes for three operations: move beam invisibly, draw line, and display dot ๐ฆ. The idea was to bypass all rotation, scaling, and clipping functions tied to the current level of subpicture nesting until this mode gets cleared in a certain way ๐ซง. This same effect can be done more directly and more efficiently with two commands: one to save and one to re-establish the logical coordinate system for the current subpicture ๐. (Additionally, of course, the "save" operation would establish the initial, highest level, logical coordinate system.) ๐
Simple Subpicture Calls ๐ง
Besides the <identifier> of the subpicture being called, a simple subpicture call can specify two optional parameters ๐. The first is an <identifier> that's the "name" (in a sense described below) of this particular call ๐. The second is an absolute position on the calling page that the beam gets invisibly moved to before the subpicture is called ๐.
When (eventually) the viewer is allowed to interact by "picking" information displayed before them, and that information is part of a subpicture, the "name" of the subpicture call gets reported as part of the "graphic input" sent to the serving host ๐. If the picked information is within several levels of subpicture calls, the names of each call get reported in a way that shows their nesting ๐ช. (Note that just the name of the subpicture by itself isn't enough, since one subpicture may be displayed in several positions and the application may want to tell individual calls apart ๐.) If the identifier isn't specified, it defaults to the null string ๐ซถ. If the position (for the invisible move) isn't specified, the current beam position is used ๐ธ.
Which of these two parameters are present is encoded by two bits in a code byte that comes right before the parameters ๐ฅ. If both are present, they're always in the same order. This order, and the bits assigned to the two parameters, are specified in the detailed description of the Simple Instance command (and in the BNF in Appendix 1) ๐. Coming right before even the code byte, and right after the name of the subpicture being called, is a count of the data in the rest of the instance command โจ. That's included so you don't have to decode the code byte just to figure out the total length of any one Simple Instance operation ๐.
Windowing: Clipping, Blanking, or (?) ๐ช
Since we're on the topic of coordinate systems and subpictures, it might be good to touch on this: who (which end of the connection) is responsible for what, when a picture is potentially going to display beyond the edge of the virtual screen? ๐ฌ The consensus at the graphics meeting was that the interpreter of the graphics protocol (i.e., the using end) would not be held responsible for doing anything reasonable when a picture displays information beyond the edge of the screen (e.g., by relative moves and draws) ๐.
The interpreter must react properly to the next absolute data in the proper range, however ๐ . Various solutions to this situation in existing graphics systems include:
- clipping a line to display as much as is proper,
- blanking the whole of a line if any part is invisible, or
- discarding high order bits of the current position register, so that no invisible positions can be represented ("wraparound").
In addition to edge effects at the highest level, problems arise with respect to (full) subpictures ๐. It's nice to be able to select a rectangular portion of a subpicture to display as part of a subpicture call ๐. (See: Newman, Display procedures, Communications of the ACM, Volume 14, Number 10, October 1971, pp651-660). In accordance with the consensus of the meeting, which was to make this capability optional, this author merely hopes to include in the protocol a method of encoding this information, since his site a) can handle some such windowing, and b) hopes to provide a service facility to perform this function ๐ซถ.
Appendix 2 describes how to concatenate several levels of portions into a single rectangular test, as long as no rotations are involved ๐. It also outlines the problems related to rotations and portioning ๐.
Full Subpicture Calls โจ
okay so now we get to the fun part ๐ we can look at everything you can put in a full subpicture call, on top of the name of the subpicture being called (which, obvi, is required ๐).
All of the data below is optional ๐ซถ. A single code byte comes first, and one bit in that byte tells you whether a parameter is there (bit is one) or not (bit is zero). The parameters always show up in the same order, if they're present at all. You can see that order in the detailed description of the Full Instance command, and in the BNF in Appendix 1. Oh, and even before the code byte there's a <count> of the following bytes, including the code byte, so you always know the total length of any particular Full Instance operation ๐ง.
One parameter is an <identifier>, which lets you tell this particular call to a subpicture apart from every other call to that same subpicture ๐ฆ. We already covered this one under Simple Subpicture Calls.
Another parameter is a translation. This one is given by the absolute coordinates of the center of the subpicture's image (on the calling page). If you don't give one, it defaults to the beam position at the time of the call.
A rotation can be specified by giving a 16-bit fraction in the range 0 to .1111111111111111 (binary), inclusive. That fraction tells you what part of a full circle (2pi) the rotation is. The default angle of rotation is zero.
(Actually, the rotation representation works the same way if you think of it as a two's complement fraction from -1/2 to just less than +1/2. The same bit configurations encode the same rotation, because sine and cosine are periodic. For example, binary zero always represents 0, and 010000...0 denotes pi/2 in both schemes. 100...00 denotes 1/2 in one scheme and -1/2 in the other. Those correspond to rotations of +pi and -pi, which are identical rotations. ๐)
Also part of a full subpicture call is a rectangular portion of the called picture to be imaged on the calling picture. (See the previous section for a discussion of clipping ๐.) This rectangle is specified by its center and by one half of its total size in x and y. The rectangle consists of all points whose x coordinate differs from that of the center by no more than the specified x-size, and whose y coordinate satisfies a similar condition. The defaults put the center at the origin and give both the x half width and the y half width the value of +1/2. So the default includes the whole logical coordinate system of the called page. It also includes some points where one of the coordinates is +1/2, which, strictly speaking, lie "outside" the coordinate system. How this inconsistency gets resolved is left unspecified ๐คทโโ๏ธ.
Finally, you have to specify the scaling to be applied when working out the image, and there are a bunch of ways to do it. One way is a uniform magnification applied to the subpicture. To reach a wide range of magnifications, the author's opinion is that some form of scientific notation (i.e., floating point) will have to be used. If there's already a network standard floating point notation (which the author isn't aware of), it should be used. Failing that, the suggestion is that this notation consist of an 8-bit (two's complement) exponent followed by a 16-bit (two's complement) fractional part ๐ฅ.
Another form of scaling is to specify separate magnifications in x and in y, applied to the subpicture before any rotation is performed. A third option is to specify a rectangular area in the calling picture's coordinate system to be filled with the image of the subpicture. Since the center of the image is already specified by the translation, this image information only consists of half-edge size data. If none of the three scaling methods is chosen (and an affine transformation, see below, isn't given explicitly), a uniform magnification of unity (i.e., no scaling) is used. Heads up: the three forms of scaling tend to contradict each other, so only one of them should be used in any one call. What happens if self-contradictory information is given in these fields is left unspecified ๐.
Appendix 2 presents the math for transforming the subpicture's coordinate system into the calling picture's coordinate system. It shows that all the individual operations (scaling, rotating, and translating) can be represented as a single affine transformation, which consists of 6 values. It might be nice to let the serving program specify this transformation directly. So one possible parameter of a full subpicture call is six floating point numbers (in the form described under magnification, above) that get interpreted as an affine transformation. If the affine transformation has the following form:
/_ |x |y_/ = /_ x y_/ * / L11 L12 / + /_ T1 T2_/
/_ L21 L22 _/
then the values shall (arbitrarily) be sent in the following (columnar) order: L11, L21, L12, L22, T1, T2. This affine transformation should be invertible, meaning L11*L22 - L21*L12 should not be zero ๐ง .
Viewporting ๐ธ
Another topic from the meeting, which got referred to the protocol committee for a decision, was the ability to place the "top level" picture in some rectangle of the virtual screen. The default rectangle might be the full screen. Alternatively, it might be left up to the viewer to specify the default, via interaction with the graphics system at the Using Host. Viewporting generally allows more than one "top level" picture to be viewed at once. You'd want to see several pictures on the same screen when multiple users are working together, or when one user is interacting with a group of applications (on separate serving hosts). The author thinks the coordinate transformations for this feature are simpler than the ones for "full subpictures", since no rotations are involved, and that it would be part of the same mechanism in implementation. Specifically, just another affine transformation (see Appendix 2) would be added to the levels caused by full subpicture calls. All you need to do is keep track of viewport identifiers and their associated rectangles. Since there's very little extra work, the proposal is to include this feature at some high level of the protocol โจ.
Command Codes ๐ข
Each command in the graphics protocol gets assigned a non-negative value, which represents that command in the byte stream. The algorithm that matches values to commands is, it turns out, a super touchy subject ๐ญ. There are five or ten different criteria for a "best" algorithm, and each criterion has a different emphasis. This proposal cuts the Gordian knot by ordering the commands approximately by level and then just numbering them. If several closely related commands show up at the same level, some effort goes into encoding variations of meaning in bit configurations. Even if a later consideration causes a change in ordering to be proposed, this committee feels the numbering should not be altered. Until this matter is firmly settled, though, it's strongly advised that any implementation take into account the possibility of reassignment of command codes ๐จ.
Particular Proposal for Level 0 Protocol ๐ฏ
The proposal is to keep level 0 very simple. That way, implementation can be done quickly and experimenting with the protocol can begin. Another reason is that the least powerful host, and even programmable terminals, should be able to implement it. With that in mind, the "rule" was made that a command gets included only if its output is a function solely of the current command and the "beam position" current at the start of the command. Put differently, the interpreter for level 0 needs no internal storage for "modes" or pushdown stacks. With this restriction, the hope is that a very simple implementation will be possible for level 0. Someday, one could even build a hardware translator from level 0 code to one's own particular terminal's code ๐ค.
Note that in the opcode assignment for level 0, bits 4, 2, and 1 have special meaning for the move, line, and dot commands. Specifically, the 1 bit encodes absolute versus relative data mode, the 4 bit encodes whether any visible output occurs, and the 2 bit determines whether the visible output is a line or a dot ๐ฆ.
Level 0: Command Summary ๐
Here's the list of commands (and their syntax) in level zero. Detailed descriptions follow in the next section. Commands dealing with protocol may be added by the Connection Committee. (They currently request opcodes in the range 128 to 255.) (As described in Basic Data Forms, above, <x coordinate>, <y coordinate>, <x delta> and <y delta> are two-byte coordinate values, <string> is a count followed by <count> many bytes, and <value> is an eight bit number.)
Decimal Octal Binary Format
0 0 00000000 Null
1 1 00000001 Erase screen and reset beam
2 2 00000010 Move Absolute <x coordinate> <y coordinate>
3 3 00000011 Move Relative <x delta> <y delta>
4 4 00000100 Draw Absolute <x coordinate> <y coordinate>
5 5 00000101 Draw Relative <x delta> <y delta>
6 6 00000110 Dot Absolute <x coordinate> <y coordinate>
7 7 00000111 Dot relative <x delta> <y delta>
8 10 00001000 Text <string>
9 11 00001001 TextR <string>
10 12 00001010 End of Picture
11 13 00001011 Escape <value> <string>
Level 0: Command Descriptions ๐ง
0 Null Statement ("NULL"). This statement has no arguments, and no effect either. ๐
1 Erase screen and reset beam to origin ("ERASE"). This command indicates that a new picture is about to be drawn. It should always be (eventually) paired with a following End of Picture command ๐งน.
2 Move beam invisibly to absolute position ("MOVEA") <x coordinate> <y coordinate>. Nothing is drawn. The beam is positioned at the specified absolute x,y position ๐.
3 Move beam invisibly by relative amount ("MOVER") <x coordinate> <y coordinate>. Nothing is drawn. The beam is shifted by the specified amount in x and y ๐ถโโ๏ธ.
4 Draw line to absolute position ("DRAWA") <x coordinate> <y coordinate>. A line is drawn from the current beam position to the specified absolute x,y position โ๏ธ.
5 Draw line to relative position ("DRAWR") <x delta> <y delta>. A line is drawn from the current beam position to the position delta x and delta y away ๐.
6 Display a Dot at absolute position ("DOTA") <x coordinate> <y coordinate>. The beam is moved invisibly to absolute position x,y, and a dot is displayed there โญ.
7 Display a Dot at relative position ("DOTR") <x delta> <y delta>. The beam is moved invisibly by the specified amount in x and y, and a dot is displayed there ๐ซ.
8 Display text ("TEXT") <string>. At the current beam position, display some characters at the normal size for the device being operated. <string> consists of a <count> followed by <count> many characters. If there is no "normal size", choose the size so that seventy-two characters are displayed per line. The characters in
the characters in the string are coded in network ASCII, and all codes between 0 and 127 (decimal) inclusive are permitted โจ (at level zero, what happens to control characters is left unspecified ๐). Where the beam ends up after this command is left unspecified, except that another Display Text command right after it will append its text to the previous string ๐ฆ. (The TEXT command is discouraged, so use TextR instead ๐
.) The position of the first character relative to the initial beam position is left unspecified too ๐ธ.
9 โจ Display text and restore beam ("TEXTR") <string>.
Bestie, this one has main character energy ๐. At the current beam position, it displays a string of characters at the normal size for the device being operated, and then the beam goes right back to where it was before the command ๐ฆ. <string> is a <count> followed by count many characters ๐. If there is no "normal size", pick a size so that 72 characters are displayed per line ๐ (that's a LOT of text per line, iykyk). The characters are coded in network ASCII, and all codes between 0 and 127 (decimal) inclusive are permitted. At level zero, what happens to control characters is left unspecified, so they're on their own ๐. The position of the first character relative to the initial beam position is left unspecified ๐ง.
10 ๐ End of Picture ("ENDPIC").
This command marks the end of a new picture ๐ฌ. It MUST be paired with a preceding ERASE command ๐ฅ.
11 ๐
Escape to device specifics ("ESCDEV") <value> <string>.
Okay so if <value> is the code the Protocol Committee assigned to the device being operated ๐ซถ, then the eight-bit bytes in <string> get transmitted to the device without anyone examining them ๐. (<string> starts with a <count> telling you how many bytes there are.) Otherwise this command gets ignored ๐. If the device doesn't accept 8-bit information, the data has to be reformatted in some device-specific way ๐ง. For example, you could throw away the high-order bit for a seven-bit device, or gather 5 8-bit bytes into one 36-bit word and again discard the high-order bits, perhaps ๐. The action of the bytes in the string SHOULD leave alone (or at least restore) any hardware beam position registers in the device which the interpreter might conceivably depend on ๐ง .
This command really SHOULD NOT be used ๐, but it was included at level 0 so that specific applications can do mode setting and other device-specific manipulations โจ. For example, ARDS terminals MAY optionally have several independently addressable output scopes ๐ฅ๏ธ. The selection mechanism only changes state when a particular sequence of ASCII characters reaches the terminal. So ESCDEV would be used to select which scope(s) is/are to be affected by following commands ๐ฆ. (The current state is invisible to the graphics package at the Using Host.)
Further, suppose another make of terminal has a similar option, which responds to a different code sequence. That possibility is the motivation for conditionally ignoring the ESCDEV command based on the "<value>" specified ๐. Given that a particular application will only be used to output to either an ARDS or this second make (with the multiple scope option), the application could always send two ESCDEV commands: one applicable only to ARDS terminals, and the other applicable only to the second make ๐.
LEVEL 1 ๐
Set Line mode ("LINMOD") <value>.
This command sets the current line mode ๐๏ธ. The possible modes and the <value> that sets each are: solid (0), dashed (1), dotted (2), and others (3 or >). At the beginning of a new picture (i.e., after an Erase and Reset command), line mode is solid ๐. If a site doesn't have a certain mode readily available, it MAY a) simulate it in software, b) substitute another in its place (dashed for dotted, or vice versa) c) ignore it entirely ๐. What is provided SHOULD be clearly indicated in any public document ๐. It is strongly RECOMMENDED that at least solid and one other mode be provided ๐ซถ.
Set intensity ("SETINT") <value>.
This command sets the intensity of lines, dots and characters displayed following the command โจ. If <value> is 128 decimal, normal intensity SHOULD be set. If <value> is 255 decimal, brightest SHOULD be selected, and if it is 0, then the beam SHOULD be blanked ๐ฆ. Intermediate values SHOULD be mapped appropriately as the implementer sees fit. For instance, if brightest is the same as normal, all values from 128 through 255 SHOULD be mapped to normal ๐
. Information displayed between the start of a new picture (the ERASE command) and the first SETINT command appears at normal intensity ๐ธ.
Text out ("TEXTO") <string>.
Starting from the current beam position, this command displays the <string> (of network ASCII characters) formatted as if it were typed material, at the current intensity โจ๏ธ. <string> consists of a <count> followed by count many characters. Basically, text that runs past the right margin gets broken and repositioned at the left margin on the next line down ๐. Of the control characters, only carriage return, line feed, and backspace are REQUIRED to be interpreted properly ๐ฅ.
Subpicture header ("SUBHED") <identifier> <count> <header info>.
This command begins the definition of a subpicture named "<identifier>" ๐ง. The definition is terminated by a matching SUBEND command. It stays remembered until a new one is specified or until the graphics network connection breaks ๐. Note that <identifier> is a <string> made up solely of capital letters and numbers ๐ .
Subpicture definitions MAY be nested, and that's equivalent to transmitting the two definitions separately ๐ช. In other words, all subpicture names are globals and are "known" to all other subpictures ๐. If a subpicture definition hasn't been received before its use in a picture, the empty subpicture SHOULD be displayed in its place until a definition is received โณ.
A subpicture definition need not be transmitted as part of a picture (i.e., within an ERASE and END command pair). Honestly, all subpicture definitions might come before the main picture ๐.
Currently, the <count> will always be 1, which means only one byte of <header info> follows. At higher levels of the protocol, room for expansion may be required ๐ฑ. In the <header info>, the 80 hex bit will be set if this subpicture can be a simple subpicture, and the 40 hex bit will be set if the subpicture can be a full subpicture. (It's possible that one subpicture can be both ๐คฏ.)
Other information that may eventually be present in <header info> includes whether the current value of a certain mode or parameter SHOULD be saved on entry to, and restored on exit from, this subroutine whenever it's called ๐. These modes and parameters include: line mode, intensity, character size, and data length ๐.
Subpicture end ("SUBEND").
This command ends the definition of a subpicture ๐. Each SUBEND MUST match a preceding SUBHED command ๐ .
Simple instance ("INSTS") <identifier> <simple instance tail>
This command indicates that the subpicture <identifier> is to be called (instanced) ๐. At this level, level 1, no subpicture may call another. If one does, what happens is left unspecified ๐. Also, this MUST be a call to a simple subpicture. Thus the 80 hex bit of the single byte of <header info> MUST have been set in the SUBHED command which started the definition of <identifier> ๐. If the subpicture <identifier> has never been defined, the empty subpicture SHOULD be displayed in its place ๐ซฅ.
The <simple instance tail> begins with a count of the amount of information that follows, and this count MAY be zero ๐งฎ. If it's non-zero, the next byte is a code byte that gets interpreted to see what further information follows ๐งฉ. If the 80-hex bit is set, the next thing in the byte stream is an <identifier> (called "AS information") ๐ท๏ธ. This <identifier> is the name of this particular instance of the subpicture, as described under Simple Subpicture Calls ๐ญ. If the 40-hex bit is set, then next in the byte stream (following the AS information, if present) is an x,y position (in the calling picture's coordinate scheme) where the subpicture will be centered ๐ฏ. (This is called AT information.)
If AT information isn't specified, the current beam position is used as a default ๐. If AS information isn't specified, it defaults to the <string> containing zero characters ๐ซง. If neither the 40 hex nor the 80 hex bits are set, then neither the AT information not the AS information is present, and the code byte SHOULD be zero ๐. (Also, the length count had better be 1.)
Changes to levels 0 commands for level 1.
Okay, here's what changes ๐:
- TEXT and TEXTR -- Carriage return, line feed and backspace characters SHOULD definitely be interpreted whenever they appear in
<string>๐. The results of other control characters remain unspecified. The intensity of the characters SHALL be affected by the SETINT command โจ. - ERASE -- Normal intensity and solid line mode MUST be established at the start of a new picture ๐ธ.
- DRAWA and DRAWR -- Line mode and intensity SHALL be affected by the LINMOD and SETINT commands ๐จ.
- DOTA and DOTR -- Intensity SHALL be affected by the SETINT command ๐.
LEVEL 2 ๐
Mark ("MARK").
This command causes the current x,y beam position to be saved on a pushdown stack ๐. This pushdown stack MUST be separate from the subpicture call pushdown stack ๐ฅ.
Move to mark and pop ("MOVEMK").
This command sets the current beam position equal to the x,y position at the top of the "mark" pushdown stack ๐โโ๏ธ. If the stack is empty, the origin is used instead. Then the stack gets popped (unless it's already empty) ๐จ.
Draw to mark and pop ("DRAWMK").
If the "mark" pushdown stack isn't empty, this command draws a line (of the current line mode and intensity) from the current beam position to the x,y position at the top of the "mark" pushdown stack ๐๏ธ. It also sets the beam position to that value, and then the stack is popped ๐ซถ. If the stack is empty, the line is drawn to the origin and the beam position is set there too ๐ฏ.
Changes to level 0 and 1 for level 2.
- INTS -- arbitrary levels of simple subpictures MUST be supported ๐ช. (Note that recursive use of subpictures is not allowed: once recursion starts, it can never be stopped ๐.) The pushdown stack for subpicture calls MUST be kept separate from the "mark" pushdown stack ๐.
Level 3 โจ
okay bestie, this is where things get fancy ๐ The author's own little note says all rotational transformations should maybe be put at a higher level, like higher than viewport operations ๐ธ
Full Instance ("INSTF") <identifier> <full instance tail> ๐
this command says the subpicture <identifier> gets called (instanced) in a "full" way, as described in an explanatory section ๐ฆ For one thing, the 40 hex bit of the single byte of <header info> must have been set in the SUBHED command that started the definition of <identifier>. If <identifier> has never been defined, the empty subpicture (aka nothing) should be displayed in its place ๐
The <full instance tail> is like the <simple instance tail> from the INSTS command, but it carries more info ๐ Here's the list of what can be specified, plus the bit that marks whether each piece is there or not. Whatever pieces are present always show up in the byte stream in the order listed here. (All of them get explained more fully in Full Subpicture Calls, except the "AS information", which lives in Simple Subpicture Calls.)
Bit (hex) Information
80 As information --"name" of this particular instance.
Consists of an <identifier>.
40 Translation information -- Center of the subpicture's image
on the calling page. Consists of an <x coordinate> and a
<y coordinate>.
20 Rotation -- Fractional part of 2pi to rotate the image
counterclockwise. Consists of a 16-bit unsigned fraction.
10 Portion Information -- Rectangular part of subpicture which
is to be displayed. Consists of <x coordinate>,
<y coordinate>, <x delta>, and <y delta>.
8 Uniform Magnification -- Amount to scale the whole
subpicture. Consists of a floating point number (which
should not be zero).
4 Separate x and y magnification -- Separate scales for the x
and y axes of the subpicture. Consists of two floating
point numbers (neither of which should be zero).
2 Image Size -- How large a rectangle on the calling page is
the image to occupy. Consists of an <x delta> and a
<y delta> (neither of which should be zero).
1 Affine transformation -- The map from the called to the
calling coordinates system. Consists of six floating point
numbers.
Notes:
- At most one of the three bits: 8, 4, and 2, should be set.
- If the 1 bit is set, bits 2, 4, 8, 20, and 40, should not be set.
- If additional optional parameters are ever added to the full subpicture call, another code byte could follow all the above information. In that case, the
<count>part of the<full instance tail>would include this second code byte and any additional bytes of information.
Escape to top level coordinate system ("ESCTOP") ๐ฆ
okay so this one is the escape hatch ๐ช Until a RESLEV command is (subsequently) executed, all display commands (moves, draws, dots, and texts) shall operate as if they were issued by the top level (main) picture instead of the subpicture containing them. They get mapped to the screen using the map for the highest level โจ Subpicture calls made while ESCTOP is in effect are NOT affected by it, though. The transformations still get calculated like the command isn't even there ๐ค The calculated transformations just get ignored, and whatever the subpicture displays still looks like it's at the top level until a RESLEV nullifies ESCTOP mode. So a subpicture call made during ESCTOP acts as if a RESLEV ran right before the call, and an ESCTOP ran as the very first command of the subpicture. Similar stuff goes for returning from subpictures ๐
Resume current level coordinate system ("RESLEV") ๐
this one restores the logical coordinate system for the subpicture that's currently executing, in case ESCTOP had turned it off (see ESCTOP) ๐
Changes to levels 0, 1, and 2 for level 3
MARK: the saved beam position shall be in terms of the logical coordinate system, not the physical coordinate system ๐
TEXTR, TEXT, TEXTO: okay so a full subpicture is supposed to be transformed as a whole, like it's a picture in its own right. The author feels that means all beam movements related to characters should be affected too ๐ซถ That includes character size, tab, carriage return and line feed. Specifically, carriage return should set the beam to the left margin, meaning the left edge of the logical coordinate system of the called subpicture. The author admits all this may be very hard to pull off ๐ญ So what should happen is left unspecified for now, and comments from readers are particularly invited ๐
Level 4 ๐
(maybe viewpoint operations can be included in level 3, the author says ๐ธ)
Declare Viewport ("SETVW") <viewport id> <x coordinate> <y coordinate> <x delta> <y delta> ๐ช
this sets the viewport identified by <viewport id> to represent the given area of the logical screen โจ The x and y data are NOT physical screen coordinates, since that would bring in device dependencies. This command completely supersedes any previous declaration of the same viewport. If info is already displayed inside the viewport, this command moves that displayed info to its new position on the screen ๐ฆ
If the area specified goes past the limits of the graphics standard display screen, what happens is left unspecified ๐ Viewports don't have to be disjoint, which just means two viewports can show display info at the same point on the screen.
If <x delta> or <y delta> are negative, the viewport named should be deleted. All info displayed by it shall no longer appear ๐๏ธ
Because this command affects the top level picture, the author feels it should not occur as part of a picture or in a subpicture declaration.
Add subpicture to viewport ("ADDSVW") <identifier> <viewport id> ๐
the subpicture named <identifier> is displayed within the specified viewport, if it isn't already displayed there. (If it is, nothing is done.) The subpicture must be capable of being called via a full subpicture call. If the viewport has never been declared via a SETVW command, what happens is left unspecified ๐คทโโ๏ธ (Three possibilities are: nothing is displayed; the viewport defaults to the whole logical screen; or the human viewer is permitted by the Using Host to specify the viewport.) If the viewport is declared later, the subpicture shall be displayed in it. If the subpicture has never been declared, nothing is displayed for it. When and if it's declared later, the new definition is displayed in the viewport. More than one subpicture may be displayed in a single viewport at once ๐
Because this command affects the top level picture, the author feels it should not occur as part of a picture or in a subpicture declaration.
Clear viewport ("CLVW") <viewport id> ๐งน
all subpictures that were added with the ADDSVW command to the specified viewport get removed from it. So the specified viewport contributes nothing to what the human viewer sees ๐ (After a CLVW, the area of the viewport may not be blank, because other, non-cleared viewports might overlap it.)
Because this command affects the top level picture, the author feels it should not occur as part of a picture or in a subpicture declaration.
Changes to levels 0, 1, 2, and 3 for level 4
ERASE: all viewports are cleared (like in the CLVW command), but their declarations are remembered ๐ง
ENDPIC: this command partially loses its purpose ๐ข It no longer marks the end of all picture info to be presented to the user, since viewport operations may follow that amend or alter the picture. This job is partially taken over by the DELAY and NODELAY commands described below.
Level ? ๐ธ
Set Character Size ("SETCHS") <x delta> <y delta>.
until further notice, characters shall be displayed so that each one takes up approximately <x delta> and <y delta> in the appropriate coordinate direction in the current logical coordinate system ๐ Inter-character and inter-line spacing could be certain percentages (any ideas?) more than <x delta> and <y delta>, or they could be specified separately. Either way, only a "best effort" would be expected at a site ๐ซถ
Character size is always set back to normal (as defined by level 0 character size being normal) by the ERASE command. <x delta> and <y delta> should be positive, EXCEPT that if <x delta> is equal to zero, then <y delta> being negative, zero, or positive corresponds to a character size of "smaller than normal", "normal", or "larger than normal" ๐ How much smaller or larger than normal is left up to the site.
Changes to levels 0 and 1 for level ?
TEXTR, TEXT, and TEXTO: characters are to be displayed according to the current character size โ๏ธ
ERASE: must establish normal character size, with normal being the one for level 0 ๐งผ
Level ?' ๐ฆ
Set Data Length ("SETDLN") <value>.
until this mode is explicitly changed with another SETDLN, various data will consist of <value> number of bytes ๐ข <value> may be 1, 2, 3, or 4. The affected syntactic types (refer to Appendix 1) are: <coordinate>, <x coordinate>, <y coordinate>, <double coordinate>, <x delta>, <y delta>, <angle>, and the fractional part of a floating point number ๐ When a network connection is first established, the data length is two โจ
Level ?'' ๐
(these commands should probably be at the same level as viewport operations, if not earlier, the author says ๐)
Extensive Changes Follow ("DELAY").
this optional command is designed to eliminate futile effort on the part of the Using Host programs ๐ At some hosts and/or with some output devices (particularly storage tubes), a non-negligible amount of time may be needed to present an image to the human viewer. If extensive changes are going to be made, this command is used to stop the Using Host graphics package from updating the image after every change. A NODELAY command exits DELAY mode and causes the image to be prepared and presented to the viewer ๐ฌ
For example, the current picture may display four subpictures that are each going to be redefined. Without a DELAY command, the viewer would see successive stages of the change, each possibly involving a large amount of computation or transmission time ๐ตโ๐ซ
End of Extensive Changes ("NODELAY")
this optional command undoes the effect of the DELAY command ๐ซง
Appendix 1: BNF for the Graphics Protocol Byte Stream ๐
Key to below:
Non-terminals are represented in < >. Terminals which are keywords standing for particular eight-bit values are in capitals. Terminals whose meaning should be clear to the reader are in lower case. Note that "empty_string" means "zero bytes", not "a <string> whose <count> is zero."
<graphics output byte stream> ::= empty_string
| <picture> <graphics output byte stream>
| <subpicture declaration> <graphics output byte stream>
| <viewport operation> <graphics output byte stream>
| <transmission control stt> <graphics output byte stream>
<picture> ::= <new picture sst> <program stt group> <end picture stt>
4. Appendix 1 Grammar, Continued โจ
Okay so the grammar keeps going, and it's where all the pieces click together ๐งฉ Here's the rest, exactly as written, because every bracket matters.
<subpicture declaration> ::= <subpicture header stt> <program stt
group><subpicture end stt>
<viewport operation> ::= <declare viewport stt>
| <add subpicture to viewport stt>
| <clear viewport stt>
<transmission control stt> ::= <set data length stt>
| <extensive changes follow stt>
| <end of extensive changes stt>
<program stt group> ::= empty_string | <program stt <program stt group>
<program stt> ::= <picture control stt> | <display stt> |
<transmission control stt>
<picture control stt> ::= <escape to device stt>
| <escape to highest coordinate system stt>
| <restore coordinate system stt>
| <mark stt>
| <null stt>
| <line mode stt>
| <set intensity stt>
| <subpicture declaration>
| <simple instance stt>
| <full instance stt>
| <set character size stt>
<display stt> ::= <move absolute stt>
| <move relative stt>
| <draw absolute stt>
| <draw relative stt>
| <dot absolute stt>
| <dot relative stt>
| <move to mark and pop stt>
| <draw to mark and pop stt>
| <text and restore beam stt>
| <text stt>
| <text out stt>
<new picture stt> ::= ERASE
<end picture stt> ::= ENDPIC
<subpicture header stt> ::= SUBHED <identifier> count> <header info>
<header info> ::= 80-hex | 40-hex | C0-hex
<subpicture end stt> ::= SUBEND
<set viewport stt> ::= SETVW <viewport id> <x coordinate>
<y coordinate> <x delta> <y delta>
<add subpicture to viewport stt> ::= AADSVW <identifier> <viewport id>
<clear viewport stt> ::= CLVW <viewport id>
<extensive changes follow stt> ::= DELAY
<end of extensive changes stt> ::= NODELAY
<escape to device stt> ::= ESCDEV <device code> <string>
<escape to highest coordinate system stt> ::= ESCTOP
<restore coordinate system stt> ::= RESLEV
<null stt> ::= NULL
<mark stt> ::= MARK
<line mode stt> ::= LINMOD <value>
<set character size stt> ::= SETCHS <x delta> <y delta>
<set data length stt> ::= SETDLN <value>
<move absolute stt> ::= MOVEA <x coordinate> <y coordinate>
<move relative stt> ::= MOVER <x delta> <y delta>
<draw absolute stt> ::= DRAWA <x coordinate> <y coordinate>
<draw relative stt> ::= DRAWR <x delta> <y delta>
<dot absolute stt> ::= DOTA <x coordinate> <y coordinate>
<dot relative stt> ::= DOTR <x delta> <y delta>
<move to mark and pop stt> ::= MOVEMK
<draw to mark and pop stt> ::= DRAWMK
<text and restore beam stt> ::= TEXTR <string>
<text stt> ::= TEXT <string>
<text out stt> ::= TEXTO <string>
<simple instance stt> ::= INST <identifier> <simple instance tail>
<full instance stt> ::= INSTF <identifier> <full instance tail>
<simple instance tail> ::= eight_bits_of_binary_0
| <count> <tail code> <as clause> <at clause>
<tail code> ::= bit_pattern_indicating_what_clauses_follow
<full instance tail> ::= eight_bits_of_binary_0
| <count> <tail code> <as clause> <at clause>
<rotation clause> <portion clause>
<uniform magnification clause>
<separate magnification clause> <image size
clause> <complete transformation clause>
<as clause> ::= empty_string | <identifier>
<at clause> ::= empty_string | <x coordinate> <y coordinate>
<rotation clause> ::= empty_string | <angle>
<portion clause> ::= empty_string | <x coordinate> <y coordinate>
<x delta> <y delta>
<uniform magnification clause> ::= empty_string |floating point number>
<separate magnification clause> ::= empty_string |
<floating point number> <floating point number>
<image size clause> ::= empty_string | <x delta> <y delta>
<complete transformation clause> ::= empty_string | six_<floating point
number>'s
<angle> ::= 16-bit_non-negative_fractional_part_of_a_circle
<x coordinate> ::= <coordinate>
<y coordinate> ::= <coordinate>
<x delta> ::= <double coordinate>
<y delta> ::= <double coordinate>
<coordinate> ::= signed,_two_s-complement,_fraction_in_range
-1/2_to_less_than_+1/2
<double coordinate> ::= signed,_two_s_complement,_fraction,
range _strictly_between_-1_and_+1
<floating point number> ::= network_standard_floating_point
number_if_any
| 8-bit_two_s_complement_exponent_part and a
16-bit_two_s_complement_fraction_part <count>
::= 7-bit_non-negative_integer
| 15-bit_non-negative_integer_represented_in
"excess_2**15"_notation
<string> ::= <count> count_8-bit_bytes
<identifier> ::= <count> count_upper_case_letters_or_numbers
<viewport id> ::= <identifier>
<device code> ::= 8-bit_integer
<value> ::= 8-bit_integer
Appendix 2. Mathematical Formulae for Subpictures ๐งฎ
Transformations
Okay bestie, this appendix is the math behind subpictures, and it's giving linear algebra realness ๐ค Positions in a logical coordinate system get written as a row vector with two elements, like /_ x y_/. Vectors and matrices are wrapped in these funny brackets: /_ _/ ๐
A bunch of symbols show up in a full subpicture call to describe the transformation from one coordinate system to another. Here's the lineup:
Mx and My : magnifications in x and y to be applied before any
rotation.
They may be negative indicating reflection.
A: an angle of rotation in the range 0 to just less than 2pi.
/_ |cx |cy_/ : the center (in the calling picture) of the image of the
subpicture.
|sx |sy : the half-sizes, in the x and y directions, of the
image on the calling page in terms of the calling page's
coordinate system.
They may be negative to indicate reflection.
/_ x y_/ : a position on the called page.
/_ |x |y_/ : the position on the calling page corresponding to /_x y_/.
/_ Pcx Pcy_/ : The center of the portion of the called subpicture's
coordinate system which is to be mapped to the calling
page.
This defaults to /_ 0 0_/ if not specified.
Psx and Psy : The half-sizes in x and y of the portion of the
subpicture to be mapped. These both default to +1/2
in not specified.
Quick recap in my own words ๐ซถ
- Mx and My: magnifications in x and y, applied before any rotation. Negative means reflection ๐ช
- A: the rotation angle, from 0 up to just under 2pi ๐
- |cx |cy: the centre of the image, measured in the calling picture โจ
- |sx |sy: the half-sizes of the image on the calling page, in the calling page's coordinates. These can be negative too, for reflection ๐ฆ
- x y and |x |y: a position on the called page, and where it lands on the calling page ๐
- Pcx Pcy and Psx Psy: the centre and half-sizes of the portion of the called subpicture being mapped. Pcx and Pcy default to
/_ 0 0_/, and Psx and Psy default to +1/2 ๐
(If a uniform magnification is specified, set Mx and My equal to it and proceed below as if they were specified.)
If magnifications are specified, the following holds:
/_ |x |y_/ = (/_ x y_/ - /_ Pcx Pcy_>) * / Mx/Psx 0 / *
/_ 0 My/Psy_/
/ cos 0 sin 0 / * / 1/2 0 / + /_ |cx |cy_/
/_ -sin0 cos0_/ /_ 0 1/2_/
Or, put another way, here's the same thing in its expanded form:
1)
/_|x |y_/ = /_ x-Pcx y-Pcy_/ * / Mx cosA/2Psx Mx sinA/2Psx /
/_ -My sinA/2Psy My cosA/2Psy_/
+/_ |cx |cy_/
The factor of 1/2 is there for a reason, babe ๐ For example, (x-Pcx)/Psx goes from -1 to +1 for x values inside the portion (so |x-Pcx| <|Psx| ), but the image in the calling subpicture's coordinate system should only span -1/2 to +1/2. That's the whole trick โจ
If the image size is specified instead of the magnification, we have the following:
/_ |x |y_/ = (/_ x y_/ - /_Pcx Pcy_/) * / 1/Psx 0 / *
/_ 0 1/Psy _/
/ cosA sinA / * / |sx 0 / + /_ |cx |cy_/
/_ -sinA cosA _/ /_ 0 |sy _/
Same idea, just written another way:
2)
/_|x |y_/ = /_x-Pcx y-Pcy_/ * /|sx cosA/Psx |sy sinA/Psx /
/_-|sx sinA/Psy |sy cosA/Psy_/
+ /_|cx |cy_/
Expanding the parenthesized quantities in equations 1) and 2) gives us the following ๐
3a) /_|x |y_/ = /_x y_/ * /Mx cosA/2Psx Mx sinA/2Psx /
/_-My sinA/2Psy My cosA/2Psy_/
+ /_|cx-PcxMxcosA/2Psx+PcyMysinA/2Psy
|cy-PcxMxsinA/2Psx-PcyMycosA/2Psy _/
and
3b) /_|x |y_/ = /_x y_/ * /|sx cosA/Psx |sy sinA/Psx /
/_-|sx sinA/Psy |sy cosA/Psy_/
+ /_|cx-Pcx|sxcosA/Psx+Pcy|sxsinA/Psy
|cy-Pcy|sysinA/Psx-Pcy|sycosA/Psy_/
There are some super iconic substitutions you can make in 3a) and 3b) ๐ญ For example, if A=0 (no rotation), then we have:
4a) /_|x |y_/ = /_x y_/ * /Mx/2Psx 0 / + /_|cx-PcxMx/2Psx
|cy-PcyMy/2Psy_/
/_ 0 My/2Psy_/
4b) /_|x |y_/ = /_x y_/ * /|sx/Psx 0 / + /_|cx-Pcx|sx/Psx
|cy-Pcy|sy/Psy_/
/_ 0 |sy/Psy_/
Another one is if no portioning is done (Pcx=Pcy=0, Psx=Psy=1/2):
5a) /_|x |y_/ = /_ x y_/ * /Mx cosA Mx sinA / + /_|cx |cy_/
/_-My sinA My sinA_/
5b) /_|x |y_/ = /_ x y_/ * /2|sx cosA 2|sy sinA / + /_|cx |cy_/
/_-2|sx sinA 2|sx cosA_/
If in addition, 0=0, we have:
6a) /_|x |y_/ = /_ xMx+|cx yMy+|cy_/
6b) /_|x |y_/ = /_ x*2|sx+|cx y*2|sy+|cy_/
Of course, in every case, the transformation from /_x y_/ to /_|x |y_/ can be written in this form:
/_|x |y_/ = /_x y_/ * / 2 by 2 / + /_ translation _/
/_ matrix _/
In general, a transformation that combines a linear transformation with a translation is called an affine transformation ๐ธ
Transformations with Nested Levels
Here's where it gets lowkey brilliant ๐ง The combination of two affine transformations is itself an affine transformation. Like, if
/_|x |y_/ = /_x y_/ * / Mat1 / + /_ Tran1 _/
/_ _/
and
/_|x_ |y__/ = /_|x |y_/ * ( / Mat1 / * / Mat2 /)
/_ _/ /_ _/
+ (/_ Tran2 _/ + /_ Tran1 _/ * / Mat2 /)
/_ _/
then you can see the combo is just another affine transformation ๐
So if you have nested full subpicture calls, the data at any level only needs to be transformed once, by the single transformation that combines every step at each level of nesting. That's giving efficiency ๐
A new "grand combination" affine transformation should be computed whenever a full subpicture is called. You push down the current transformation first, then combine the current grand combination with the affine transformation for that particular subpicture call. Main character energy for sure ๐โจ
Portions with Nested Levels ๐
okay bestie, so as long as no rotations are involved (or only rotations in multiples of pi/2 ๐ธ), multiple levels of portions are easy to implement ๐ . for the next two paragraphs, let's assume no rotations other than whole multiples of pi/2 are involved โจ.
just like we keep track of a "grand combination" affine transformation, we can keep a grand combination of portions too ๐ฆ. at each level, here's the move: save a copy of the current grand portion, then use the inverse of the single level affine transformation (the one specified in the subpicture call) to figure out which rectangle of the called page corresponds to the current grand portion (on the calling page) ๐ง.
then there are a bunch of ways this rectangle can relate to the rectangle specified (or defaulted) in the subpicture call ๐. they may be disjoint (in which case this subpicture need not be called at all ๐). they may be equal (an easy case ๐). one may contain the other, or they may partially overlap. if there's any intersection at all, it'll be a rectangle, and that rectangle becomes the new grand combination portion ๐.
now the tea โ: with rotations other than multiples of pi/2, the inverse image of the rectangle is no longer in standard orientation (vertical and horizontal edges) ๐ญ. so its intersection with the portion specified on the subpicture call may have 3, 4, 5, 6, 7, or 8 edges (if it's non-empty) ๐ฅ. deeper levels can get even messier if they involve rotations too ๐. ngl there may be no conceptual difficulty (for some) in working with that, but it takes significantly more computation than the simple horizontal and vertical edge case ๐.
bestie, this protocol puts no recommendation on the table for rotations other than whole multiples of pi/2 with portions ๐ซถ. it does suggest that nested portions be handled as described above in the more straightforward case ๐.
[This RFC was put into machine readable form for entry] [into the online RFC archives by Helene Morin, Via Genie, 12/1999]
๐ฆ where this page comes from
- ietf: rfc493 1973-04
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms