2.2.2.2.1.1.2 Primary Drawing Order (PRIMARY_DRAWING_ORDER)

The PRIMARY_DRAWING_ORDER structure encapsulates a primary drawing order. All primary drawing orders employ special field encoding to reduce the number of bytes sent on the wire. Field encoding maintains a copy of the most recent field values that were used in each primary drawing order, in addition to common state information such as the last bounding rectangle used across all orders and the last order type. Only the fields that have changed are sent on the wire. This implies that all the fields in a primary drawing order are optional, their presence being denoted by the controlFlags and fieldFlags fields.


0


1


2


3


4


5


6


7


8


9

1
0


1


2


3


4


5


6


7


8


9

2
0


1


2


3


4


5


6


7


8


9

3
0


1

controlFlags

orderType (optional)

fieldFlags (variable)

...

bounds (variable)

...

primaryOrderData (variable)

...

controlFlags (1 byte): An 8-bit, unsigned integer. A control byte that identifies the class of the drawing order and describes the fields that are included in the order and the type of coordinates being used. This field MUST contain a combination of the following flags.

Value

Meaning

TS_STANDARD

0x01

Indicates that the order is a primary drawing order. This flag MUST be set.

TS_BOUNDS

0x04

Indicates that the order has a bounding rectangle.

TS_TYPE_CHANGE

0x08

Indicates that the order type has changed and that the orderType field is present.

TS_DELTA_COORDINATES

0x10

Indicates that all of the Coord-type fields in the order (see section 2.2.2.2.1.1.1.1) are specified as 1-byte signed deltas from their previous values.

TS_ZERO_BOUNDS_DELTAS

0x20

Indicates that the previous bounding rectangle MUST be used, as the bounds have not changed (this implies that the bounds field is not present). This flag is only applicable if the TS_BOUNDS (0x04) flag is set.

TS_ZERO_FIELD_BYTE_BIT0

0x40

Used in conjunction with the TS_ZERO_FIELD_BYTE_BIT1 (0x80) flag to form a 2-bit count (so maximum of 3) of the number of field flag bytes (present in the fieldFlags field) that are zero and not present, counted from the end of the set of field flag bytes. This flag is the least significant bit of the count.

TS_ZERO_FIELD_BYTE_BIT1

0x80

Used in conjunction with the TS_ZERO_FIELD_BYTE_BIT0 (0x40) flag to form a 2-bit count (so maximum of 3) of the number of field flag bytes (present in the fieldFlags field) that are zero and not present, counted from the end of the set of field flag bytes. This flag is the most significant bit of the count.

For the use of the TS_ZERO_FIELD_BYTE_BIT0 (0x40) and TS_ZERO_FIELD_BYTE_BIT1 (0x80) flags, see the fieldFlags field.

orderType (1 byte): An 8-bit, unsigned integer. An optional identifier describing the type of primary drawing order. The initial value for the orderType agreed on by both the server and client is TS_ENC_PATBLT_ORDER (0x01) for the PatBlt primary drawing order.

Value

Meaning

TS_ENC_DSTBLT_ORDER

0x00

DstBlt (section 2.2.2.2.1.1.2.1) Primary Drawing Order.

TS_ENC_PATBLT_ORDER

0x01

PatBlt (section 2.2.2.2.1.1.2.3) Primary Drawing Order.

TS_ENC_SCRBLT_ORDER

0x02

ScrBlt (section 2.2.2.2.1.1.2.7) Primary Drawing Order.

TS_ENC_DRAWNINEGRID_ORDER

0x07

DrawNineGrid (section 2.2.2.2.1.1.2.21) Primary Drawing Order.

TS_ENC_MULTI_DRAWNINEGRID_ORDER

0x08

MultiDrawNineGrid (section 2.2.2.2.1.1.2.22) Primary Drawing Order.

TS_ENC_LINETO_ORDER

0x09

LineTo (section 2.2.2.2.1.1.2.11) Primary Drawing Order.

TS_ENC_OPAQUERECT_ORDER

0x0A

OpaqueRect (section 2.2.2.2.1.1.2.5) Primary Drawing Order.

TS_ENC_SAVEBITMAP_ORDER

0x0B

SaveBitmap (section 2.2.2.2.1.1.2.12) Primary Drawing Order.

TS_ENC_MEMBLT_ORDER

0x0D

MemBlt (section 2.2.2.2.1.1.2.9) Primary Drawing Order.

TS_ENC_MEM3BLT_ORDER

0x0E

Mem3Blt (section 2.2.2.2.1.1.2.10) Primary Drawing Order.

TS_ENC_MULTIDSTBLT_ORDER

0x0F

MultiDstBlt (section 2.2.2.2.1.1.2.2) Primary Drawing Order.

TS_ENC_MULTIPATBLT_ORDER

0x10

MultiPatBlt (section 2.2.2.2.1.1.2.4) Primary Drawing Order.

TS_ENC_MULTISCRBLT_ORDER

0x11

MultiScrBlt (section 2.2.2.2.1.1.2.8) Primary Drawing Order.

TS_ENC_MULTIOPAQUERECT_ORDER

0x12

MultiOpaqueRect (section 2.2.2.2.1.1.2.6) Primary Drawing Order.

TS_ENC_FAST_INDEX_ORDER

0x13

FastIndex (section 2.2.2.2.1.1.2.14) Primary Drawing Order.

TS_ENC_POLYGON_SC_ORDER

0x14

PolygonSC (section 2.2.2.2.1.1.2.16) Primary Drawing Order.

TS_ENC_POLYGON_CB_ORDER

0x15

PolygonCB (section 2.2.2.2.1.1.2.17) Primary Drawing Order.

TS_ENC_POLYLINE_ORDER

0x16

Polyline (section 2.2.2.2.1.1.2.18) Primary Drawing Order.

TS_ENC_FAST_GLYPH_ORDER

0x18

FastGlyph (section 2.2.2.2.1.1.2.15) Primary Drawing Order.

TS_ENC_ELLIPSE_SC_ORDER

0x19

EllipseSC (section 2.2.2.2.1.1.2.19) Primary Drawing Order.

TS_ENC_ELLIPSE_CB_ORDER

0x1A

EllipseCB (section 2.2.2.2.1.1.2.20) Primary Drawing Order.

TS_ENC_INDEX_ORDER

0x1B

GlyphIndex (section 2.2.2.2.1.1.2.13) Primary Drawing Order.

fieldFlags (variable): A variable-length, 1-byte to 3-byte field. The optional fieldFlags field is used to indicate the presence of an order field in the encoded fields portion of the packet (represented by the primaryOrderData field). Each bit in the fieldFlags field functions as a flag and indicates if a particular order field is present.

The number of bytes used to represent the field flags will vary based on the maximum number of fields that a primary drawing order can hold. For any given drawing order, the size (in bytes) of the fieldFlags field MUST be computed with the following formula.

 ceil(((numberOfOrderFields) + 1) / 8)

The maximum number of allowed fields is 23, which corresponds to three field flags bytes. The "+ 1" in the equation indicates that for seven fields there is one field flags byte; however, for eight fields, there are 2 bytes. (This drives some of the specialized orders in RDP where a special case can be used to reduce the number of fields below 7 or 15, thereby reducing the number of field flags bytes sent.)

The individual field flags bytes are arranged in little-endian order; the low order byte is first. The order of the flags proceeds from 0x01 (the least significant bit), which corresponds to the first field in the order, 0x02 the second field in the order, 0x04 the third field in the order, and so on.

The presence of the fieldFlags field is also governed by the controlFlags field ZERO_FIELD_BYTE_BIT0 (0x40) and ZERO_FIELD_BYTE_BIT1 (0x80) flags (known as the "zero flags"). These flags are used as a 2-bit count of the number of field flags bytes that are zero and not present, counted from the end of the set of flag bytes.

Relationship between zero flags and the number of flag field bytes sent on the wire

Figure 1: Relationship between zero flags and the number of flag field bytes sent on the wire

For example, assume that a given order has nine fields. Hence, there can be up to two bytes in the fieldFlags field. Assume further that the fieldFlags field has the field-encoding bytes {0x20, 0x00}. In this case, there is 1 zero byte (counting from the end backward); thus, the controlFlags field contains the ZERO_FIELD_BYTE_BIT0 flag (0x40), and the order is sent on the wire with a fieldFlags value of 0x20.

bounds (variable): A variable-length, 1-byte to 9-byte field. The presence of the optional bounds field is governed by the TS_BOUNDS (0x04) flag in the controlFlags field, which indicates that the order MUST have a bounding region applied. If the controlFlags field TS_ZERO_BOUNDS_DELTAS (0x20) flag is also set, the previous bounding rectangle MUST be used, as the bounds have not changed (this implies that the bounds field is not present). Otherwise, the bounds are encoded as an encoding description byte followed by one or more encoded bounds (written in the order: left, top, right, bottom). The description byte MUST contain a TS_BOUND_XXX or TS_BOUND_DELTA_XXX flag to describe each of the encoded bounds that are present.

Flag

Meaning

TS_BOUND_LEFT

0x01

Indicates that the left bound is present and encoded as a 2-byte, little-endian ordered value.

TS_BOUND_TOP

0x02

Indicates that the top bound is present and encoded as a 2-byte, little-endian ordered value.

TS_BOUND_RIGHT

0x04

Indicates that the right bound is present and encoded as a 2-byte, little-endian ordered value.

TS_BOUND_BOTTOM

0x08

Indicates that the bottom bound is present and encoded as a 2-byte, little-endian ordered value.

TS_BOUND_DELTA_LEFT

0x10

Indicates that the left bound is present and encoded as a 1-byte signed value used as an offset (-128 to 127) from the previous value.

TS_BOUND_DELTA_TOP

0x20

Indicates that the top bound is present and encoded as a 1-byte signed value used as an offset (-128 to 127) from the previous value.

TS_BOUND_DELTA_RIGHT

0x40

Indicates that the right bound is present and encoded as a 1-byte, signed value used as an offset (-128 to 127) from the previous value.

TS_BOUND_DELTA_BOTTOM

0x80

Indicates that the bottom bound is present and encoded as a 1-byte, signed value used as an offset (-128 to 127) from the previous value.

If for a given component a TS_BOUND_XXX or TS_BOUND_DELTA_XXX flag is not present, the component value is the same as the last one used, and no value is included in the encoded bounds. If both the TS_BOUND_XXX and TS_BOUND_DELTA_XXX flags are present, the TS_BOUND_XXX flag is ignored. Hence, to avoid parsing errors, only one flag MUST be used to describe the format of a given encoded bound.

The initial value for the bounds agreed on by both the server and client is the following zero rectangle.

 (left, top, right, bottom) = (0, 0, 0, 0)

primaryOrderData (variable): A variable-length byte field. The primaryOrderData field contains the encoded order field values whose presence is governed by the fieldFlags field. The encoded fields, if present, MUST be encoded in the same order as the order description (see sections 2.2.2.2.1.1.2.1 through 2.2.2.2.1.1.2.22). If a field is not present, its value is the same as the last value sent for that order. The initial values for all fields are zero.