Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
@@ -0,0 +1,226 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#include "pws_rfb_protocol.h"
|
||||
|
||||
// see https://vncdotool.readthedocs.io/en/0.8.0/rfbproto.html
|
||||
namespace ProjectionWorkstation
|
||||
{
|
||||
|
||||
namespace RfbProtocol
|
||||
{
|
||||
namespace STC
|
||||
{
|
||||
static constexpr int s_bytePerPixel = 4;
|
||||
|
||||
enum HextileSubEncoding : uint8_t
|
||||
{
|
||||
Raw = 0x01,
|
||||
BackgroundSpecified = 0x02,
|
||||
ForegroundSpecified = 0x04,
|
||||
AnySubrects = 0x08,
|
||||
SubrectsColoured = 0x10,
|
||||
};
|
||||
|
||||
static inline int highNibble(uint8_t b)
|
||||
{
|
||||
return b >> 4;
|
||||
}
|
||||
static inline int lowNibble(uint8_t b)
|
||||
{
|
||||
return b & 0x0f;
|
||||
}
|
||||
|
||||
static inline bool testBit(uint8_t bit, HextileSubEncoding enc)
|
||||
{
|
||||
return (bit & enc) == enc;
|
||||
}
|
||||
|
||||
static inline uint32_t swap(uint32_t in)
|
||||
{
|
||||
// compiler: bswap $eax ...
|
||||
uint32_t out = 0;
|
||||
out |= ((in >> 24) & 0x000000ff);
|
||||
out |= ((in >> 8) & 0x0000ff00);
|
||||
out |= ((in << 8) & 0x00ff0000);
|
||||
out |= ((in << 24) & 0xff000000);
|
||||
return out;
|
||||
}
|
||||
|
||||
static inline void fillHextileRect(RfbRectangle &rect, int xOfs, int yOfs, int w, int h, uint32_t col)
|
||||
{
|
||||
uint32_t *dst = reinterpret_cast<uint32_t *>(rect.pixelData.data());
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
Q_ASSERT(x + xOfs < rect.xpos + rect.width);
|
||||
Q_ASSERT(y + yOfs < rect.ypos + rect.height);
|
||||
dst[rect.width * (y + yOfs) + (x + xOfs)] = col;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void copyHextileRect(RfbRectangle &rect, int xOfs, int yOfs, int w, int h, const QByteArray &srcBa)
|
||||
{
|
||||
uint32_t *dst = reinterpret_cast<uint32_t *>(rect.pixelData.data());
|
||||
const uint32_t *src = reinterpret_cast<const uint32_t *>(srcBa.data());
|
||||
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
Q_ASSERT(x + xOfs < rect.xpos + rect.width);
|
||||
Q_ASSERT(y + yOfs < rect.ypos + rect.height);
|
||||
dst[rect.width * (y + yOfs) + (x + xOfs)] = src[w * y + x];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool decodeHextile(RfbRectangle &rect, QDataStream &ds)
|
||||
{
|
||||
uint32_t bg = 0;
|
||||
uint32_t fg = 0;
|
||||
|
||||
for (int yRect = rect.ypos; yRect < rect.ypos + rect.height; yRect += 16)
|
||||
{
|
||||
for (int xRect = rect.xpos; xRect < rect.xpos + rect.width; xRect += 16)
|
||||
{
|
||||
int w = 16;
|
||||
int h = 16;
|
||||
if (rect.xpos + rect.width - xRect < 16)
|
||||
w = rect.xpos + rect.width - xRect;
|
||||
if (rect.ypos + rect.height - yRect < 16)
|
||||
h = rect.ypos + rect.height - yRect;
|
||||
|
||||
const int x = xRect - rect.xpos;
|
||||
const int y = yRect - rect.ypos;
|
||||
|
||||
uint8_t subencoding = 0;
|
||||
ds >> subencoding;
|
||||
if (ds.status() != QDataStream::Ok)
|
||||
return false;
|
||||
|
||||
if (testBit(subencoding, HextileSubEncoding::Raw))
|
||||
{
|
||||
QByteArray buf(w * h * s_bytePerPixel, Qt::Uninitialized);
|
||||
ds.readRawData(buf.data(), buf.size());
|
||||
if (ds.status() != QDataStream::Ok)
|
||||
return false;
|
||||
copyHextileRect(rect, x, y, w, h, buf);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (testBit(subencoding, HextileSubEncoding::BackgroundSpecified))
|
||||
{
|
||||
ds >> bg;
|
||||
bg = swap(bg);
|
||||
if (ds.status() != QDataStream::Ok)
|
||||
return false;
|
||||
}
|
||||
|
||||
fillHextileRect(rect, x, y, w, h, bg);
|
||||
|
||||
if (testBit(subencoding, HextileSubEncoding::ForegroundSpecified))
|
||||
{
|
||||
ds >> fg;
|
||||
fg = swap(fg);
|
||||
if (ds.status() != QDataStream::Ok)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!testBit(subencoding, HextileSubEncoding::AnySubrects))
|
||||
continue;
|
||||
|
||||
uint8_t nSubrects;
|
||||
ds >> nSubrects;
|
||||
if (ds.status() != QDataStream::Ok)
|
||||
return false;
|
||||
|
||||
if (testBit(subencoding, HextileSubEncoding::SubrectsColoured))
|
||||
{
|
||||
uint8_t xy = 0;
|
||||
uint8_t wh = 0;
|
||||
for (int i = 0; i < nSubrects; i++)
|
||||
{
|
||||
ds >> fg >> xy >> wh;
|
||||
fg = swap(fg);
|
||||
if (ds.status() != QDataStream::Ok)
|
||||
return false;
|
||||
int xOfs = highNibble(xy);
|
||||
int yOfs = lowNibble(xy);
|
||||
int wOfs = highNibble(wh) + 1;
|
||||
int hOfs = lowNibble(wh) + 1;
|
||||
fillHextileRect(rect, x + xOfs, y + yOfs, wOfs, hOfs, fg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t xy = 0;
|
||||
uint8_t wh = 0;
|
||||
for (int i = 0; i < nSubrects; i++)
|
||||
{
|
||||
ds >> xy >> wh;
|
||||
if (ds.status() != QDataStream::Ok)
|
||||
return false;
|
||||
int xOfs = highNibble(xy);
|
||||
int yOfs = lowNibble(xy);
|
||||
int wOfs = highNibble(wh) + 1;
|
||||
int hOfs = lowNibble(wh) + 1;
|
||||
fillHextileRect(rect, x + xOfs, y + yOfs, wOfs, hOfs, fg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void RfbFramebufferUpdate::fillDataFromStream(QDataStream &ds)
|
||||
{
|
||||
quint8 padding;
|
||||
ds >> padding;
|
||||
if (ds.status() != QDataStream::Ok)
|
||||
return;
|
||||
|
||||
quint16 numberOfRectangles;
|
||||
ds >> numberOfRectangles;
|
||||
if (ds.status() != QDataStream::Ok)
|
||||
return;
|
||||
|
||||
RfbRectangle rect;
|
||||
for (int count = 0; count < numberOfRectangles; ++count)
|
||||
{
|
||||
ds >> rect.xpos >> rect.ypos >> rect.width >> rect.height >> rect.encoding;
|
||||
if (ds.status() != QDataStream::Ok)
|
||||
return;
|
||||
|
||||
const int calculatedPixelData = rect.width * rect.height * s_bytePerPixel;
|
||||
if (calculatedPixelData <= 0)
|
||||
continue;
|
||||
rect.pixelData.resize(calculatedPixelData);
|
||||
if (rect.encoding == RAW_ENCODING)
|
||||
{
|
||||
ds.readRawData(rect.pixelData.data(), calculatedPixelData);
|
||||
if (ds.status() != QDataStream::Ok)
|
||||
return;
|
||||
m_rectangles.append(rect);
|
||||
}
|
||||
else if (rect.encoding == HEXTILE_ENCODING)
|
||||
{
|
||||
decodeHextile(rect, ds);
|
||||
if (ds.status() != QDataStream::Ok)
|
||||
return;
|
||||
m_rectangles.append(rect);
|
||||
}
|
||||
else if (rect.encoding == LAST_RECT_PSEUDO_ENCODING)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace STC
|
||||
} // namespace RfbProtocol
|
||||
} // namespace ProjectionWorkstation
|
||||
Reference in new issue
Block a user