Files
ShotRDP/grdp/protocol/pdu/orders.go
2025-02-20 12:31:02 +08:00

1237 lines
26 KiB
Go

package pdu
import (
"bytes"
"errors"
"fmt"
"io"
"ShotRDP/grdp/core"
"ShotRDP/grdp/glog"
)
type ControlFlag uint8
const (
TS_STANDARD = 0x01
TS_SECONDARY = 0x02
TS_BOUNDS = 0x04
TS_TYPE_CHANGE = 0x08
TS_DELTA_COORDINATES = 0x10
TS_ZERO_BOUNDS_DELTAS = 0x20
TS_ZERO_FIELD_BYTE_BIT0 = 0x40
TS_ZERO_FIELD_BYTE_BIT1 = 0x80
)
type PrimaryOrderType uint8
const (
ORDER_TYPE_DSTBLT = 0x00 //0
ORDER_TYPE_PATBLT = 0x01 //1
ORDER_TYPE_SCRBLT = 0x02 //2
//ORDER_TYPE_DRAWNINEGRID = 0x07 //7
//ORDER_TYPE_MULTI_DRAWNINEGRID = 0x08 //8
ORDER_TYPE_LINETO = 0x09 //9
ORDER_TYPE_OPAQUERECT = 0x0A //10
ORDER_TYPE_SAVEBITMAP = 0x0B //11
ORDER_TYPE_MEMBLT = 0x0D //13
ORDER_TYPE_MEM3BLT = 0x0E //14
//ORDER_TYPE_MULTIDSTBLT = 0x0F //15
//ORDER_TYPE_MULTIPATBLT = 0x10 //16
//ORDER_TYPE_MULTISCRBLT = 0x11 //17
//ORDER_TYPE_MULTIOPAQUERECT = 0x12 //18
//ORDER_TYPE_FAST_INDEX = 0x13 //19
ORDER_TYPE_POLYGON_SC = 0x14 //20
ORDER_TYPE_POLYGON_CB = 0x15 //21
ORDER_TYPE_POLYLINE = 0x16 //22
//ORDER_TYPE_FAST_GLYPH = 0x18 //24
ORDER_TYPE_ELLIPSE_SC = 0x19 //25
ORDER_TYPE_ELLIPSE_CB = 0x1A //26
ORDER_TYPE_TEXT2 = 0x1B //27
)
type SecondaryOrderType uint8
const (
ORDER_TYPE_BITMAP_UNCOMPRESSED = 0x00
ORDER_TYPE_CACHE_COLOR_TABLE = 0x01
ORDER_TYPE_CACHE_BITMAP_COMPRESSED = 0x02
ORDER_TYPE_CACHE_GLYPH = 0x03
ORDER_TYPE_BITMAP_UNCOMPRESSED_V2 = 0x04
ORDER_TYPE_BITMAP_COMPRESSED_V2 = 0x05
ORDER_TYPE_CACHE_BRUSH = 0x07
ORDER_TYPE_BITMAP_COMPRESSED_V3 = 0x08
)
func (s SecondaryOrderType) String() string {
name := "Unknown"
switch s {
case ORDER_TYPE_BITMAP_UNCOMPRESSED:
name = "Cache Bitmap"
case ORDER_TYPE_CACHE_COLOR_TABLE:
name = "Cache Color Table"
case ORDER_TYPE_CACHE_BITMAP_COMPRESSED:
name = "Cache Bitmap (Compressed)"
case ORDER_TYPE_CACHE_GLYPH:
name = "Cache Glyph"
case ORDER_TYPE_BITMAP_UNCOMPRESSED_V2:
name = "Cache Bitmap V2"
case ORDER_TYPE_BITMAP_COMPRESSED_V2:
name = "Cache Bitmap V2 (Compressed)"
case ORDER_TYPE_CACHE_BRUSH:
name = "Cache Brush"
case ORDER_TYPE_BITMAP_COMPRESSED_V3:
name = "Cache Bitmap V3"
}
return fmt.Sprintf("[0x%02d] %s", s, name)
}
/* Alternate Secondary Drawing Orders */
const (
ORDER_TYPE_SWITCH_SURFACE = 0x00
ORDER_TYPE_CREATE_OFFSCREEN_BITMAP = 0x01
ORDER_TYPE_STREAM_BITMAP_FIRST = 0x02
ORDER_TYPE_STREAM_BITMAP_NEXT = 0x03
ORDER_TYPE_CREATE_NINE_GRID_BITMAP = 0x04
ORDER_TYPE_GDIPLUS_FIRST = 0x05
ORDER_TYPE_GDIPLUS_NEXT = 0x06
ORDER_TYPE_GDIPLUS_END = 0x07
ORDER_TYPE_GDIPLUS_CACHE_FIRST = 0x08
ORDER_TYPE_GDIPLUS_CACHE_NEXT = 0x09
ORDER_TYPE_GDIPLUS_CACHE_END = 0x0A
ORDER_TYPE_WINDOW = 0x0B
ORDER_TYPE_COMPDESK_FIRST = 0x0C
ORDER_TYPE_FRAME_MARKER = 0x0D
)
const (
GLYPH_FRAGMENT_NOP = 0x00
GLYPH_FRAGMENT_USE = 0xFE
GLYPH_FRAGMENT_ADD = 0xFF
CBR2_HEIGHT_SAME_AS_WIDTH = 0x01
CBR2_PERSISTENT_KEY_PRESENT = 0x02
CBR2_NO_BITMAP_COMPRESSION_HDR = 0x08
CBR2_DO_NOT_CACHE = 0x10
)
const (
ORDER_PRIMARY = iota
ORDER_SECONDARY
ORDER_ALTSEC
)
type OrderPdu struct {
ControlFlags uint8
Type int
Altsec *Altsec
Primary *Primary
Secondary *Secondary
}
func (o *OrderPdu) HasBounds() bool {
return o.ControlFlags&TS_BOUNDS != 0
}
type Altsec struct {
}
type Secondary struct {
}
type Primary struct {
Bounds Bounds
Data PrimaryOrder
}
type FastPathOrdersPDU struct {
NumberOrders uint16
OrderPdus []OrderPdu
}
func (*FastPathOrdersPDU) FastPathUpdateType() uint8 {
return FASTPATH_UPDATETYPE_ORDERS
}
func (f *FastPathOrdersPDU) Unpack(r io.Reader) error {
f.NumberOrders, _ = core.ReadUint16LE(r)
//glog.Info("NumberOrders:", f.NumberOrders)
for i := 0; i < int(f.NumberOrders); i++ {
var o OrderPdu
o.ControlFlags, _ = core.ReadUInt8(r)
if o.ControlFlags&TS_STANDARD == 0 {
//glog.Info("Altsec order")
o.processAltsecOrder(r)
o.Type = ORDER_ALTSEC
//return errors.New("Not support")
} else if o.ControlFlags&TS_SECONDARY != 0 {
//glog.Info("Secondary order")
o.processSecondaryOrder(r)
o.Type = ORDER_SECONDARY
} else {
//glog.Info("Primary order")
o.processPrimaryOrder(r)
o.Type = ORDER_PRIMARY
}
if f.OrderPdus == nil {
f.OrderPdus = make([]OrderPdu, 0, f.NumberOrders)
}
f.OrderPdus = append(f.OrderPdus, o)
}
return nil
}
func (o *OrderPdu) processAltsecOrder(r io.Reader) error {
orderType := o.ControlFlags >> 2
//glog.Info("Altsec:", orderType)
switch orderType {
case ORDER_TYPE_SWITCH_SURFACE:
case ORDER_TYPE_CREATE_OFFSCREEN_BITMAP:
case ORDER_TYPE_STREAM_BITMAP_FIRST:
case ORDER_TYPE_STREAM_BITMAP_NEXT:
case ORDER_TYPE_CREATE_NINE_GRID_BITMAP:
case ORDER_TYPE_GDIPLUS_FIRST:
case ORDER_TYPE_GDIPLUS_NEXT:
case ORDER_TYPE_GDIPLUS_END:
case ORDER_TYPE_GDIPLUS_CACHE_FIRST:
case ORDER_TYPE_GDIPLUS_CACHE_NEXT:
case ORDER_TYPE_GDIPLUS_CACHE_END:
case ORDER_TYPE_WINDOW:
case ORDER_TYPE_COMPDESK_FIRST:
case ORDER_TYPE_FRAME_MARKER:
core.ReadUInt32LE(r)
}
return nil
}
func (o *OrderPdu) processSecondaryOrder(r io.Reader) error {
var sec Secondary
length, _ := core.ReadUint16LE(r)
flags, _ := core.ReadUint16LE(r)
orderType, _ := core.ReadUInt8(r)
glog.Info("Secondary:", SecondaryOrderType(orderType))
b, _ := core.ReadBytes(int(length)+13-6, r)
r0 := bytes.NewReader(b)
switch orderType {
case ORDER_TYPE_BITMAP_UNCOMPRESSED:
fallthrough
case ORDER_TYPE_CACHE_BITMAP_COMPRESSED:
compressed := (orderType == ORDER_TYPE_CACHE_BITMAP_COMPRESSED)
sec.updateCacheBitmapOrder(r0, compressed, flags)
case ORDER_TYPE_BITMAP_UNCOMPRESSED_V2:
fallthrough
case ORDER_TYPE_BITMAP_COMPRESSED_V2:
compressed := (orderType == ORDER_TYPE_BITMAP_COMPRESSED_V2)
sec.updateCacheBitmapV2Order(r0, compressed, flags)
case ORDER_TYPE_BITMAP_COMPRESSED_V3:
sec.updateCacheBitmapV3Order(r0, flags)
case ORDER_TYPE_CACHE_COLOR_TABLE:
sec.updateCacheColorTableOrder(r0, flags)
case ORDER_TYPE_CACHE_GLYPH:
sec.updateCacheGlyphOrder(r0, flags)
case ORDER_TYPE_CACHE_BRUSH:
sec.updateCacheBrushOrder(r0, flags)
default:
glog.Debugf("Unsupport order type 0x%x", orderType)
}
return nil
}
func (b *Bounds) updateBounds(r io.Reader) {
present, _ := core.ReadUInt8(r)
if present&1 != 0 {
readOrderCoord(r, &b.left, false)
} else if present&16 != 0 {
readOrderCoord(r, &b.left, true)
}
if present&2 != 0 {
readOrderCoord(r, &b.top, false)
} else if present&32 != 0 {
readOrderCoord(r, &b.top, true)
}
if present&4 != 0 {
readOrderCoord(r, &b.right, false)
} else if present&64 != 0 {
readOrderCoord(r, &b.right, true)
}
if present&8 != 0 {
readOrderCoord(r, &b.bottom, false)
} else if present&128 != 0 {
readOrderCoord(r, &b.bottom, true)
}
}
type PrimaryOrder interface {
Type() int
Unpack(io.Reader, uint32, bool) error
}
var (
orderType uint8
bounds Bounds
)
func (o *OrderPdu) processPrimaryOrder(r io.Reader) error {
o.Primary = &Primary{}
if o.ControlFlags&TS_TYPE_CHANGE != 0 {
orderType, _ = core.ReadUInt8(r)
}
size := 1
switch orderType {
case ORDER_TYPE_MEM3BLT, ORDER_TYPE_TEXT2:
size = 3
case ORDER_TYPE_PATBLT, ORDER_TYPE_MEMBLT, ORDER_TYPE_LINETO, ORDER_TYPE_POLYGON_CB, ORDER_TYPE_ELLIPSE_CB:
size = 2
}
if o.ControlFlags&TS_ZERO_FIELD_BYTE_BIT0 != 0 {
size--
}
if o.ControlFlags&TS_ZERO_FIELD_BYTE_BIT1 != 0 {
if size < 2 {
size = 0
} else {
size -= 2
}
}
var present uint32
for i := 0; i < size; i++ {
bits, _ := core.ReadUInt8(r)
present |= uint32(bits) << (i * 8)
}
if o.ControlFlags&TS_BOUNDS != 0 {
if o.ControlFlags&TS_ZERO_BOUNDS_DELTAS == 0 {
bounds.updateBounds(r)
}
//glog.Infof("updateBounds")
o.Primary.Bounds = bounds
}
delta := o.ControlFlags&TS_DELTA_COORDINATES != 0
//glog.Infof("present=%d,delta=%v", present, delta)
var p PrimaryOrder
switch orderType {
case ORDER_TYPE_DSTBLT:
p = &Dstblt{}
case ORDER_TYPE_PATBLT:
p = &Patblt{}
case ORDER_TYPE_SCRBLT:
p = &Scrblt{}
//case ORDER_TYPE_DRAWNINEGRID:
//case ORDER_TYPE_MULTI_DRAWNINEGRID:
case ORDER_TYPE_LINETO:
p = &LineTo{}
case ORDER_TYPE_OPAQUERECT:
p = &OpaqueRect{}
case ORDER_TYPE_SAVEBITMAP:
p = &SaveBitmap{}
case ORDER_TYPE_MEMBLT:
p = &Memblt{}
case ORDER_TYPE_MEM3BLT:
p = &Mem3blt{}
//case ORDER_TYPE_MULTIDSTBLT:
//case ORDER_TYPE_MULTIPATBLT:
//case ORDER_TYPE_MULTISCRBLT:
//case ORDER_TYPE_MULTIOPAQUERECT:
//case ORDER_TYPE_FAST_INDEX:
case ORDER_TYPE_POLYGON_SC:
p = &PolygonSc{}
case ORDER_TYPE_POLYGON_CB:
p = &PolygonCb{}
case ORDER_TYPE_POLYLINE:
p = &Polyline{}
//case ORDER_TYPE_FAST_GLYPH:
case ORDER_TYPE_ELLIPSE_SC:
p = &EllipeSc{}
case ORDER_TYPE_ELLIPSE_CB:
p = &EllipeCb{}
case ORDER_TYPE_TEXT2:
p = &GlayphIndex{}
default:
glog.Error("Not Support order type:", orderType)
return errors.New("Not Support order type")
}
if p != nil {
if err := p.Unpack(r, present, delta); err != nil {
return err
}
}
o.Primary.Data = p
return nil
}
func readOrderCoord(r io.Reader, coord *int32, delta bool) {
if delta {
change, _ := core.ReadUInt8(r)
*coord += int32(int8(change))
} else {
change, _ := core.ReadUint16LE(r)
*coord = int32(int16(change))
}
}
type Dstblt struct {
x int32
y int32
cx int32
cy int32
opcode uint8
}
func (d *Dstblt) Type() int {
return ORDER_TYPE_DSTBLT
}
func (d *Dstblt) Unpack(r io.Reader, present uint32, delta bool) error {
glog.Infof("Dstblt Order")
if present&0x01 != 0 {
readOrderCoord(r, &d.x, delta)
}
if present&0x02 != 0 {
readOrderCoord(r, &d.y, delta)
}
if present&0x04 != 0 {
readOrderCoord(r, &d.cx, delta)
}
if present&0x08 != 0 {
readOrderCoord(r, &d.cy, delta)
}
if present&0x10 != 0 {
d.opcode, _ = core.ReadUInt8(r)
}
return nil
}
type Patblt struct {
x int32
y int32
cx int32
cy int32
opcode uint8
bgcolour [4]uint8
fgcolour [4]uint8
brush Brush
}
func (d *Patblt) Type() int {
return ORDER_TYPE_PATBLT
}
func (d *Patblt) Unpack(r io.Reader, present uint32, delta bool) error {
glog.Infof("Patblt Order")
if present&0x01 != 0 {
readOrderCoord(r, &d.x, delta)
}
if present&0x02 != 0 {
readOrderCoord(r, &d.y, delta)
}
if present&0x04 != 0 {
readOrderCoord(r, &d.cx, delta)
}
if present&0x08 != 0 {
readOrderCoord(r, &d.cy, delta)
}
if present&0x10 != 0 {
d.opcode, _ = core.ReadUInt8(r)
}
if present&0x0020 != 0 {
b, g, r, a := updateReadColorRef(r)
d.bgcolour[0], d.bgcolour[1], d.bgcolour[2], d.bgcolour[3] = b, g, r, a
}
if present&0x0040 != 0 {
b, g, r, a := updateReadColorRef(r)
d.fgcolour[0], d.fgcolour[1], d.fgcolour[2], d.fgcolour[3] = b, g, r, a
}
d.brush.updateBrush(r, present>>7)
return nil
}
type Brush struct {
X uint8
Y uint8
Style uint8
Hatch uint8
Data []byte
}
func (b *Brush) updateBrush(r io.Reader, present uint32) {
if present&1 != 0 {
b.X, _ = core.ReadUInt8(r)
}
if present&2 != 0 {
b.Y, _ = core.ReadUInt8(r)
}
if present&4 != 0 {
b.Style, _ = core.ReadUInt8(r)
}
if present&8 != 0 {
b.Hatch, _ = core.ReadUInt8(r)
}
if present&16 != 0 {
data, _ := core.ReadBytes(7, r)
b.Data = make([]byte, 0, 8)
b.Data = append(b.Data, b.Hatch)
b.Data = append(b.Data, data...)
}
}
type Scrblt struct {
X int32
Y int32
Cx int32
Cy int32
Opcode uint8
Srcx int32
Srcy int32
}
func (d *Scrblt) Type() int {
return ORDER_TYPE_SCRBLT
}
var d Scrblt
func (d1 *Scrblt) Unpack(r io.Reader, present uint32, delta bool) error {
glog.Infof("Scrblt Order")
if present&0x0001 != 0 {
readOrderCoord(r, &d.X, delta)
}
if present&0x0002 != 0 {
readOrderCoord(r, &d.Y, delta)
}
if present&0x0004 != 0 {
readOrderCoord(r, &d.Cx, delta)
}
if present&0x0008 != 0 {
readOrderCoord(r, &d.Cy, delta)
}
if present&0x0010 != 0 {
d.Opcode, _ = core.ReadUInt8(r)
}
if present&0x0020 != 0 {
readOrderCoord(r, &d.Srcx, delta)
}
if present&0x0040 != 0 {
readOrderCoord(r, &d.Srcy, delta)
}
*d1 = d
return nil
}
type LineTo struct {
Mixmode uint16
Startx int32
Starty int32
Endx int32
Endy int32
Bgcolour [4]uint8
Opcode uint8
Pen Pen
}
func (d *LineTo) Type() int {
return ORDER_TYPE_LINETO
}
func (d *LineTo) Unpack(r io.Reader, present uint32, delta bool) error {
glog.Infof("LineTo Order")
if present&0x0001 != 0 {
d.Mixmode, _ = core.ReadUint16LE(r)
}
if present&0x0002 != 0 {
readOrderCoord(r, &d.Startx, delta)
}
if present&0x0004 != 0 {
readOrderCoord(r, &d.Starty, delta)
}
if present&0x008 != 0 {
readOrderCoord(r, &d.Endx, delta)
}
if present&0x0010 != 0 {
readOrderCoord(r, &d.Endy, delta)
}
if present&0x0020 != 0 {
b, g, r, a := updateReadColorRef(r)
d.Bgcolour[0], d.Bgcolour[1], d.Bgcolour[2], d.Bgcolour[3] = b, g, r, a
}
if present&0x0040 != 0 {
d.Opcode, _ = core.ReadUInt8(r)
}
d.Pen.updatePen(r, present>>7)
return nil
}
type Pen struct {
Style uint8
Width uint8
Colour [4]uint8
}
func (d *Pen) updatePen(r io.Reader, present uint32) {
if present&1 != 0 {
d.Style, _ = core.ReadUInt8(r)
}
if present&2 != 0 {
d.Width, _ = core.ReadUInt8(r)
}
if present&4 != 0 {
b, g, r, a := updateReadColorRef(r)
d.Colour[0], d.Colour[1], d.Colour[2], d.Colour[3] = b, g, r, a
}
}
type OpaqueRect struct {
X int32
Y int32
Cx int32
Cy int32
Colour [4]uint8
}
func (d *OpaqueRect) Type() int {
return ORDER_TYPE_OPAQUERECT
}
func (d *OpaqueRect) Unpack(r io.Reader, present uint32, delta bool) error {
glog.Infof("OpaqueRect Order")
if present&0x0001 != 0 {
readOrderCoord(r, &d.X, delta)
}
if present&0x0002 != 0 {
readOrderCoord(r, &d.Y, delta)
}
if present&0x0004 != 0 {
readOrderCoord(r, &d.Cx, delta)
}
if present&0x0008 != 0 {
readOrderCoord(r, &d.Cy, delta)
}
if present&0x0010 != 0 {
i, _ := core.ReadUInt8(r)
d.Colour[0] = i
}
if present&0x0020 != 0 {
i, _ := core.ReadUInt8(r)
d.Colour[1] = i
}
if present&0x0040 != 0 {
i, _ := core.ReadUInt8(r)
d.Colour[2] = i
}
return nil
}
type SaveBitmap struct {
Offset uint32
Left int32
Top int32
Right int32
Bottom int32
action uint8
}
func (d *SaveBitmap) Type() int {
return ORDER_TYPE_SAVEBITMAP
}
func (d *SaveBitmap) Unpack(r io.Reader, present uint32, delta bool) error {
if present&0x0001 != 0 {
d.Offset, _ = core.ReadUInt32LE(r)
}
if present&0x0002 != 0 {
readOrderCoord(r, &d.Left, delta)
}
if present&0x0004 != 0 {
readOrderCoord(r, &d.Top, delta)
}
if present&0x0008 != 0 {
readOrderCoord(r, &d.Right, delta)
}
if present&0x0010 != 0 {
readOrderCoord(r, &d.Bottom, delta)
}
if present&0x0020 != 0 {
d.action, _ = core.ReadUInt8(r)
}
return nil
}
type Memblt struct {
ColourTable uint8
CacheId uint8
X int32
Y int32
Cx int32
Cy int32
Opcode uint8
Srcx int32
Srcy int32
CacheIdx uint16
}
func (d *Memblt) Type() int {
return ORDER_TYPE_MEMBLT
}
func (d *Memblt) Unpack(r io.Reader, present uint32, delta bool) error {
if present&0x0001 != 0 {
d.CacheId, _ = core.ReadUInt8(r)
d.ColourTable, _ = core.ReadUInt8(r)
}
if present&0x0002 != 0 {
readOrderCoord(r, &d.X, delta)
}
if present&0x0004 != 0 {
readOrderCoord(r, &d.Y, delta)
}
if present&0x0008 != 0 {
readOrderCoord(r, &d.Cx, delta)
}
if present&0x0010 != 0 {
readOrderCoord(r, &d.Cy, delta)
}
if present&0x0020 != 0 {
d.Opcode, _ = core.ReadUInt8(r)
}
if present&0x0040 != 0 {
readOrderCoord(r, &d.Srcx, delta)
}
if present&0x0080 != 0 {
readOrderCoord(r, &d.Srcy, delta)
}
if present&0x0100 != 0 {
d.CacheIdx, _ = core.ReadUint16LE(r)
}
return nil
}
type Mem3blt struct {
ColourTable uint8
CacheId uint8
X int32
Y int32
Cx int32
Cy int32
Opcode uint8
Srcx int32
Srcy int32
Bgcolour [4]uint8
Fgcolour [4]uint8
Brush Brush
CacheIdx uint16
}
func (d *Mem3blt) Type() int {
return ORDER_TYPE_MEM3BLT
}
func (d *Mem3blt) Unpack(r io.Reader, present uint32, delta bool) error {
if present&0x000001 != 0 {
d.CacheId, _ = core.ReadUInt8(r)
d.ColourTable, _ = core.ReadUInt8(r)
}
if present&0x000002 != 0 {
readOrderCoord(r, &d.X, delta)
}
if present&0x000004 != 0 {
readOrderCoord(r, &d.Y, delta)
}
if present&0x000008 != 0 {
readOrderCoord(r, &d.Cx, delta)
}
if present&0x000010 != 0 {
readOrderCoord(r, &d.Cy, delta)
}
if present&0x000020 != 0 {
d.Opcode, _ = core.ReadUInt8(r)
}
if present&0x000040 != 0 {
readOrderCoord(r, &d.Srcx, delta)
}
if present&0x000080 != 0 {
readOrderCoord(r, &d.Srcy, delta)
}
if present&0x000100 != 0 {
b, g, r, a := updateReadColorRef(r)
d.Bgcolour[0], d.Bgcolour[1], d.Bgcolour[2], d.Bgcolour[3] = b, g, r, a
}
if present&0x000200 != 0 {
b, g, r, a := updateReadColorRef(r)
d.Fgcolour[0], d.Fgcolour[1], d.Fgcolour[2], d.Fgcolour[3] = b, g, r, a
}
d.Brush.updateBrush(r, present>>10)
if present&0x008000 != 0 {
d.CacheIdx, _ = core.ReadUint16LE(r)
}
if present&0x010000 != 0 {
core.ReadUint16LE(r)
}
return nil
}
type PolygonSc struct {
X int32
Y int32
Opcode uint8
Fillmode uint8
Fgcolour [4]uint8
Npoints uint8
Points []Point
}
type Point struct {
X int32
Y int32
}
func (d *PolygonSc) Type() int {
return ORDER_TYPE_POLYGON_SC
}
func (d *PolygonSc) Unpack(r io.Reader, present uint32, delta bool) error {
if present&0x0001 != 0 {
readOrderCoord(r, &d.X, delta)
}
if present&0x0002 != 0 {
readOrderCoord(r, &d.Y, delta)
}
if present&0x0004 != 0 {
d.Opcode, _ = core.ReadUInt8(r)
}
if present&0x0008 != 0 {
d.Fillmode, _ = core.ReadUInt8(r)
}
if present&0x0010 != 0 {
b, g, r, a := updateReadColorRef(r)
d.Fgcolour[0], d.Fgcolour[1], d.Fgcolour[2], d.Fgcolour[3] = b, g, r, a
}
if present&0x0020 != 0 {
d.Npoints, _ = core.ReadUInt8(r)
d.Points = make([]Point, 0, d.Npoints+1)
}
if present&0x0040 != 0 {
size, _ := core.ReadUInt8(r)
data, _ := core.ReadBytes(int(size), r)
d.Points = append(d.Points, Point{d.X, d.Y})
var flags uint8
r = bytes.NewReader(data)
for i := 1; i <= int(d.Npoints); i++ {
var p Point
if (i-1)%4 == 0 {
flags, _ = core.ReadUInt8(r)
}
if (^flags)&0x80 != 0 {
p.X = parseDelta(r)
}
if (^flags)&0x40 != 0 {
p.Y = parseDelta(r)
}
flags <<= 2
}
}
return nil
}
func parseDelta(r io.Reader) (v int32) {
b, _ := core.ReadUInt8(r)
if b&0x40 != 0 {
v = int32(b) | (^0x3F)
} else {
v = int32(b & 0x3F)
}
if b&0x80 != 0 {
b, _ := core.ReadUInt8(r)
v = (v << 8) | int32(b)
}
return
}
type PolygonCb struct {
}
func (d *PolygonCb) Type() int {
return ORDER_TYPE_POLYGON_CB
}
func (d *PolygonCb) Unpack(r io.Reader, present uint32, delta bool) error {
return nil
}
type Polyline struct {
}
func (d *Polyline) Type() int {
return ORDER_TYPE_POLYLINE
}
func (d *Polyline) Unpack(r io.Reader, present uint32, delta bool) error {
return nil
}
type EllipeSc struct {
}
func (d *EllipeSc) Type() int {
return ORDER_TYPE_ELLIPSE_SC
}
func (d *EllipeSc) Unpack(r io.Reader, present uint32, delta bool) error {
return nil
}
type EllipeCb struct {
}
func (d *EllipeCb) Type() int {
return ORDER_TYPE_ELLIPSE_CB
}
func (d *EllipeCb) Unpack(r io.Reader, present uint32, delta bool) error {
return nil
}
type GlayphIndex struct {
}
func (d *GlayphIndex) Type() int {
return ORDER_TYPE_TEXT2
}
func (d *GlayphIndex) Unpack(r io.Reader, present uint32, delta bool) error {
return nil
}
/*Secondary*/
func (s *Secondary) updateCacheBitmapOrder(r io.Reader, compressed bool, flags uint16) {
var cb CacheBitmapOrder
cb.cacheId, _ = core.ReadUInt8(r)
core.ReadUInt8(r)
cb.bitmapWidth, _ = core.ReadUInt8(r)
cb.bitmapHeight, _ = core.ReadUInt8(r)
cb.bitmapBpp, _ = core.ReadUInt8(r)
bitmapLength, _ := core.ReadUint16LE(r)
cb.cacheIndex, _ = core.ReadUint16LE(r)
var bitmapComprHdr []byte
if compressed {
if (flags & NO_BITMAP_COMPRESSION_HDR) == 0 {
bitmapComprHdr, _ = core.ReadBytes(8, r)
bitmapLength -= 8
}
}
cb.bitmapComprHdr = bitmapComprHdr
cb.bitmapDataStream, _ = core.ReadBytes(int(bitmapLength), r)
cb.bitmapLength = bitmapLength
}
type CacheBitmapOrder struct {
cacheId uint8
bitmapBpp uint8
bitmapWidth uint8
bitmapHeight uint8
bitmapLength uint16
cacheIndex uint16
bitmapComprHdr []byte
bitmapDataStream []byte
}
func getCbV2Bpp(bpp uint32) (b uint32) {
switch bpp {
case 3:
b = 8
case 4:
b = 16
case 5:
b = 24
case 6:
b = 32
default:
b = 0
}
return
}
type CacheBitmapV2Order struct {
cacheId uint32
flags uint32
key1 uint32
key2 uint32
bitmapBpp uint32
bitmapWidth uint8
bitmapHeight uint8
bitmapLength uint16
cacheIndex uint32
compressed bool
cbCompFirstRowSize uint16
cbCompMainBodySize uint16
cbScanWidth uint16
cbUncompressedSize uint16
bitmapDataStream []byte
}
func (s *Secondary) updateCacheBitmapV2Order(r io.Reader, compressed bool, flags uint16) {
var cb CacheBitmapV2Order
cb.cacheId = uint32(flags) & 0x0003
cb.flags = (uint32(flags) & 0xFF80) >> 7
bitsPerPixelId := (uint32(flags) & 0x0078) >> 3
cb.bitmapBpp = getCbV2Bpp(bitsPerPixelId)
if cb.flags&CBR2_PERSISTENT_KEY_PRESENT != 0 {
cb.key1, _ = core.ReadUInt32LE(r)
cb.key2, _ = core.ReadUInt32LE(r)
}
if cb.flags&CBR2_HEIGHT_SAME_AS_WIDTH != 0 {
cb.bitmapWidth, _ = core.ReadUInt8(r)
cb.bitmapHeight = cb.bitmapWidth
} else {
cb.bitmapWidth, _ = core.ReadUInt8(r)
cb.bitmapHeight, _ = core.ReadUInt8(r)
}
bitmapLength, _ := core.ReadUint16LE(r)
cacheIndex, _ := core.ReadUInt8(r)
if cb.flags&CBR2_DO_NOT_CACHE != 0 {
cb.cacheIndex = 0x7FFF
} else {
cb.cacheIndex = uint32(cacheIndex)
}
if compressed {
if cb.flags&CBR2_NO_BITMAP_COMPRESSION_HDR == 0 {
cb.cbCompFirstRowSize, _ = core.ReadUint16LE(r)
cb.cbCompMainBodySize, _ = core.ReadUint16LE(r)
cb.cbScanWidth, _ = core.ReadUint16LE(r)
cb.cbUncompressedSize, _ = core.ReadUint16LE(r)
bitmapLength = cb.cbCompMainBodySize
}
}
cb.bitmapDataStream, _ = core.ReadBytes(int(bitmapLength), r)
cb.bitmapLength = bitmapLength
cb.compressed = compressed
}
type CacheBitmapV3Order struct {
cacheId uint32
bpp uint32
flags uint32
cacheIndex uint16
key1 uint32
key2 uint32
bitmapData BitmapDataEx
}
type BitmapDataEx struct {
bpp uint8
codecID uint8
width uint16
height uint16
length uint32
data []byte
}
func (s *Secondary) updateCacheBitmapV3Order(r io.Reader, flags uint16) {
var cb CacheBitmapV3Order
cb.cacheId = uint32(flags) & 0x00000003
cb.flags = (uint32(flags) & 0x0000FF80) >> 7
bitsPerPixelId := (uint32(flags) & 0x00000078) >> 3
cb.bpp = getCbV2Bpp(bitsPerPixelId)
cacheIndex, _ := core.ReadUint16LE(r)
cb.cacheIndex = cacheIndex
cb.key1, _ = core.ReadUInt32LE(r)
cb.key2, _ = core.ReadUInt32LE(r)
bitmapData := &cb.bitmapData
bitmapData.bpp, _ = core.ReadUInt8(r)
core.ReadUInt8(r)
core.ReadUInt8(r)
bitmapData.codecID, _ = core.ReadUInt8(r)
bitmapData.width, _ = core.ReadUint16LE(r)
bitmapData.height, _ = core.ReadUint16LE(r)
new_len, _ := core.ReadUInt32LE(r)
bitmapData.data, _ = core.ReadBytes(int(new_len), r)
bitmapData.length = new_len
}
type CacheColorTableOrder struct {
cacheIndex uint8
numberColors uint16
colorTable [256 * 4]uint8
}
func (s *Secondary) updateCacheColorTableOrder(r io.Reader, flags uint16) {
var cb CacheColorTableOrder
cb.cacheIndex, _ = core.ReadUInt8(r)
cb.numberColors, _ = core.ReadUint16LE(r)
if cb.numberColors != 256 {
/* This field MUST be set to 256 */
return
}
for i := 0; i < int(cb.numberColors)*4; i++ {
cb.colorTable[i], cb.colorTable[i+1], cb.colorTable[i+2], cb.colorTable[i+3] = updateReadColorRef(r)
}
}
func updateReadColorRef(r io.Reader) (uint8, uint8, uint8, uint8) {
blue, _ := core.ReadUInt8(r)
green, _ := core.ReadUInt8(r)
red, _ := core.ReadUInt8(r)
core.ReadUInt8(r)
return blue, green, red, 255
}
type CacheGlyphOrder struct {
cacheId uint8
nglyphs uint8
glyphs []CacheGlyph
}
type CacheGlyph struct {
character uint16
offset uint16
baseline uint16
width uint16
height uint16
datasize int
data []uint8
}
func (s *Secondary) updateCacheGlyphOrder(r io.Reader, flags uint16) {
var cb CacheGlyphOrder
cb.cacheId, _ = core.ReadUInt8(r)
cb.nglyphs, _ = core.ReadUInt8(r)
cb.glyphs = make([]CacheGlyph, 0, cb.nglyphs)
for i := 0; i < int(cb.nglyphs); i++ {
var c CacheGlyph
c.character, _ = core.ReadUint16LE(r)
c.offset, _ = core.ReadUint16LE(r)
c.baseline, _ = core.ReadUint16LE(r)
c.width, _ = core.ReadUint16LE(r)
c.height, _ = core.ReadUint16LE(r)
c.datasize = int(c.height*((c.width+7)/8)+3) & ^3
c.data, _ = core.ReadBytes(c.datasize, r)
cb.glyphs = append(cb.glyphs, c)
}
}
type CacheBrushOrder struct {
index uint8
bpp uint8
cx uint8
cy uint8
style uint8
length uint8
data []uint8
}
func (s *Secondary) updateCacheBrushOrder(r io.Reader, flags uint16) {
var cb CacheBrushOrder
cb.index, _ = core.ReadUInt8(r)
cb.bpp, _ = core.ReadUInt8(r)
cb.cx, _ = core.ReadUInt8(r)
cb.cy, _ = core.ReadUInt8(r)
cb.style, _ = core.ReadUInt8(r)
cb.length, _ = core.ReadUInt8(r)
if cb.cx == 8 && cb.cy == 8 {
if cb.bpp == 1 {
for i := 7; i >= 0; i-- {
cb.data[i], _ = core.ReadUInt8(r)
}
} else {
bpp := int(cb.bpp) - 2
if int(cb.length) == 16+4*bpp {
/* compressed brush */
data, _ := core.ReadBytes(int(cb.length), r)
cb.data = update_decompress_brush(data, bpp)
} else {
/* uncompressed brush */
scanline := 8 * 8 * bpp
cb.data, _ = core.ReadBytes(scanline, r)
}
}
}
}
func update_decompress_brush(in []uint8, bpp int) []uint8 {
var pal_index, in_index, shift int
pal := in[16:]
out := make([]uint8, 8*8*bpp)
/* read it bottom up */
for y := 7; y >= 0; y-- {
/* 2 bytes per row */
x := 0
for do2 := 0; do2 < 2; do2++ {
/* 4 pixels per byte */
shift = 6
for shift >= 0 {
pal_index = int((in[in_index] >> shift) & 3)
/* size of palette entries depends on bpp */
for i := 0; i < bpp; i++ {
out[(y*8+x)*bpp+i] = pal[pal_index*bpp+i]
}
x++
shift -= 2
}
in_index++
}
}
return out
}
/*Primary*/
type Bounds struct {
left int32
top int32
right int32
bottom int32
}
type OrderInfo struct {
controlFlags uint32
orderType uint32
fieldFlags uint32
boundsFlags uint32
bounds Bounds
deltaCoordinates bool
}