* rdr/Exception.h, rdr/FdInStream.cxx, rdr/FdInStream.h, rdr/FdOutStream.cxx, rdr/FdOutStream.h, rdr/FixedMemOutStream.h, rdr/InStream.cxx, rdr/InStream.h, rdr/MemInStream.h, rdr/MemOutStream.h, rdr/NullOutStream.cxx, rdr/NullOutStream.h, rdr/OutStream.h, rdr/ZlibInStream.cxx, rdr/ZlibInStream.h, rdr/ZlibOutStream.cxx, rdr/ZlibOutStream.h, rdr/types.h, zrle.cxx, zrleDecode.h, zrleEncode.h: remove original C++ ZRLE implementation. Its been ported to C. * NEWS: copy the existing ChangeLog to here and make this a more detailed ChangeLog.pull/1/head
parent
937b906f0d
commit
9edf7e56bb
@ -1,147 +1,13 @@
|
|||||||
Mark sent me patches to no longer need C++ for ZRLE encoding!
|
2003-09-11 Mark McLoughlin <mark@skynet.ie>
|
||||||
added --disable-cxx Option for configure
|
|
||||||
x11vnc changes from Karl Runge:
|
* rdr/Exception.h, rdr/FdInStream.cxx, rdr/FdInStream.h,
|
||||||
- Changed all those whimpy printf(...)'s into manly fprintf(stdxxx,...)'s.
|
rdr/FdOutStream.cxx, rdr/FdOutStream.h, rdr/FixedMemOutStream.h,
|
||||||
|
rdr/InStream.cxx, rdr/InStream.h, rdr/MemInStream.h,
|
||||||
- Added -q switch (quiet) to suppress printing all the debug-looking output.
|
rdr/MemOutStream.h, rdr/NullOutStream.cxx, rdr/NullOutStream.h,
|
||||||
|
rdr/OutStream.h, rdr/ZlibInStream.cxx, rdr/ZlibInStream.h,
|
||||||
- Added -bg switch to fork into background after everything is set up.
|
rdr/ZlibOutStream.cxx, rdr/ZlibOutStream.h, rdr/types.h,
|
||||||
(checks for LIBVNCSERVER_HAVE_FORK and LIBVNCSERVER_HAVE_SETSID)
|
zrle.cxx, zrleDecode.h, zrleEncode.h: remove original
|
||||||
|
C++ ZRLE implementation. Its been ported to C.
|
||||||
- Print this string out to stdout: 'PORT=XXXX' (usually XXXX = 5900).
|
|
||||||
Combining with -bg, easy to write a ssh/rsh wrapper with something like:
|
* NEWS: copy the existing ChangeLog to here and make
|
||||||
port=`ssh $host "x11vnc -bg .."` then run vncviewer based on $port output.
|
this a more detailed ChangeLog.
|
||||||
(tunneling the vnc traffic thru ssh a bit more messy, but doable)
|
|
||||||
|
|
||||||
- Quite a bit of code to be more careful when doing 8bpp indexed color, e.g.
|
|
||||||
not assuming NCOLORS is 256, handling 8bit TrueColor and Direct Color, etc
|
|
||||||
(I did all this probably in April, not quite clear in my mind now, but
|
|
||||||
I did test it out a fair amount on my old Sparcstation 20 wrt a user's
|
|
||||||
questions).
|
|
||||||
introduce rfbErr for Errors (Erik)
|
|
||||||
make rfbLog overridable (suggested by Erik)
|
|
||||||
don't reutrn on EINTR in WriteExact()/ReadExact() (suggested by Erik)
|
|
||||||
use AX_PREFIX_CONFIG_H to prefix constants in config.h to avoid
|
|
||||||
name clashes (also suggested by Erik)
|
|
||||||
transformed Bool, KeySym, Pixel to rfbBool, rfbKeySym, rfbPixel
|
|
||||||
(as suggested by Erik)
|
|
||||||
purged exit() calls (suggested by Erik)
|
|
||||||
fixed bug with maxRectsPerUpdate and Tight Encoding (these are incompatible)
|
|
||||||
checked sync with TightVNC 1.2.8:
|
|
||||||
viewonly/full passwords; if given a list, only the first is a full one
|
|
||||||
vncRandomBytes is a little more secure now
|
|
||||||
new weights for tight encoding
|
|
||||||
checked sync with RealVNC 3.3.7
|
|
||||||
introduced maxRectsPerUpdate
|
|
||||||
added first alpha version of LibVNCClient
|
|
||||||
added simple and simple15 example (really simple examples)
|
|
||||||
finally got around to fix configure in CVS
|
|
||||||
long standing http bug (.jar was sent twice) fixed by a friend of Karl named Mike
|
|
||||||
http options in cargs
|
|
||||||
when closing a client and no longer listening for new ones, don't crash
|
|
||||||
fixed a bug with ClientConnectionGone
|
|
||||||
endianness is checked at configure time
|
|
||||||
fixed a bug that prevented the first client from being closed
|
|
||||||
fixed that annoying "libvncserver-config --link" bug
|
|
||||||
make rfbReverseByte public (for rdp2vnc)
|
|
||||||
fixed compilation on OS X, IRIX, Solaris
|
|
||||||
install target for headers is now ${prefix}/include/rfb ("#include <rfb/rfb.h>")
|
|
||||||
renamed "sraRegion.h" to "rfbregion.h"
|
|
||||||
CARD{8,16,32} are more standard uint{8,16,32}_t now
|
|
||||||
fixed LinuxVNC colour handling
|
|
||||||
fixed a bug with pthreads where the connection was not closed
|
|
||||||
moved vncterm to main package (LinuxVNC included)
|
|
||||||
portability fixes (IRIX, OSX, Solaris)
|
|
||||||
more portable way to determine endianness and types of a given size
|
|
||||||
through autoconf based methods
|
|
||||||
0.5
|
|
||||||
rpm packaging through autoconf
|
|
||||||
autoconf'ed the whole package (including optional support for zlib,
|
|
||||||
pthreads and libjpeg as well as zrle/c++)
|
|
||||||
moved appropriate files to contrib/ and examples/ respectively
|
|
||||||
fixed long standing cargs bug (Justin "Zippy" Dearing)
|
|
||||||
Even better x11vnc from Karl J. Runge! (supports different kbd layouts of
|
|
||||||
client/server)
|
|
||||||
Better x11vnc from Karl J. Runge!
|
|
||||||
fixed severe bug (Const Kaplinsky)
|
|
||||||
got patch from Const Kaplisnky with CursorPosUpdate encoding and some Docs
|
|
||||||
sync'ed with newest RealVNC (ZRLE encoding)
|
|
||||||
a HTTP request for tunnelling was added (to fool strict web proxies)
|
|
||||||
sync'ed with TightVNC 1.2.5
|
|
||||||
0.4
|
|
||||||
support for NewFB from Const Kaplinsky
|
|
||||||
memory leaks squashed (localtime pseudo leak is still there :-)
|
|
||||||
small improvements for OSXvnc (still not working correctly)
|
|
||||||
synced with TightVNC 1.2.3
|
|
||||||
solaris compile cleanups
|
|
||||||
many x11vnc improvements
|
|
||||||
added backchannel, an encoding which needs special clients to pass
|
|
||||||
arbitrary data to the client
|
|
||||||
changes from Tim Jansen regarding multi threading and client blocking
|
|
||||||
as well as C++ compliancy
|
|
||||||
x11vnc can be controlled by starting again with special options if compiling
|
|
||||||
with LOCAL_CONTROL defined
|
|
||||||
0.3
|
|
||||||
added x11vnc, a x0rfbserver clone
|
|
||||||
regard deferUpdateTime in processEvents, if usec<0
|
|
||||||
initialize deferUpdateTime (memory "leak"!)
|
|
||||||
changed command line handling (arguments are parsed and then removed)
|
|
||||||
added very simple example: zippy
|
|
||||||
added rfbDrawLine, rfbDrawPixel
|
|
||||||
0.2
|
|
||||||
inserted a deferUpdate mechanism (X11 independent).
|
|
||||||
removed deletion of requestedRegion
|
|
||||||
added rfbLoadConsoleFont
|
|
||||||
fixed font colour handling.
|
|
||||||
added rfbSelectBox
|
|
||||||
added rfbDrawCharWithClip to allow for clipping and a background colour.
|
|
||||||
fixed font colours
|
|
||||||
added rfbFillRect
|
|
||||||
added IO function to check password.
|
|
||||||
rfbNewClient now sets the socket in the fd_set (for the select() call)
|
|
||||||
when compiling the library with HAVE_PTHREADS and an application
|
|
||||||
which includes "rfb.h" without, the structures got mixed up.
|
|
||||||
So, the pthreads section is now always at the end, and also
|
|
||||||
you get a linker error for rfbInitServer when using two different
|
|
||||||
pthread setups.
|
|
||||||
fixed two deadlocks: when setting a cursor and when using CopyRect
|
|
||||||
fixed CopyRect when copying modified regions (they lost the modified
|
|
||||||
property)
|
|
||||||
WIN32 target compiles and works for example :-)
|
|
||||||
fixed CopyRect (was using the wrong order of rectangles...)
|
|
||||||
should also work with pthreads, because copyrects are
|
|
||||||
always sent immediately (so that two consecutive copy rects
|
|
||||||
cannot conflict).
|
|
||||||
changed rfbUndrawCursor(rfbClientPtr) to (rfbScreenInfoPtr), because
|
|
||||||
this makes more sense!
|
|
||||||
flag backgroundLoop in rfbScreenInfo (if having pthreads)
|
|
||||||
CopyRect & CopyRegion were implemented.
|
|
||||||
if you use a rfbDoCopyR* function, it copies the data in the
|
|
||||||
framebuffer. If you prefer to do that yourself, use rfbScheduleCopyR*
|
|
||||||
instead; this doesn't modify the frameBuffer.
|
|
||||||
added flag to optionally not send XCursor updates, but only RichCursor,
|
|
||||||
or if that is not possible, fall back to server side cursor.
|
|
||||||
This is useful if your cursor has many nice colours.
|
|
||||||
fixed java viewer on server side:
|
|
||||||
SendCursorUpdate would send data even before the client pixel format
|
|
||||||
was set, but the java applet doesn't like the server's format.
|
|
||||||
fixed two pthread issues:
|
|
||||||
rfbSendFramebuffer was sent by a ProcessClientMessage function
|
|
||||||
(unprotected by updateMutex).
|
|
||||||
cursor coordinates were set without protection by cursorMutex
|
|
||||||
source is now equivalent to TridiaVNC 1.2.1
|
|
||||||
pthreads now work (use iterators!)
|
|
||||||
cursors are supported (rfbSetCursor automatically undraws cursor)
|
|
||||||
support for 3 bytes/pixel (slow!)
|
|
||||||
server side colourmap support
|
|
||||||
fixed rfbCloseClient not to close the connection (pthreads!)
|
|
||||||
this is done lazily (and with proper signalling).
|
|
||||||
cleaned up mac.c (from original OSXvnc); now compiles (untested!)
|
|
||||||
compiles cleanly on Linux, IRIX, BSD, Apple (Darwin)
|
|
||||||
fixed prototypes
|
|
||||||
0.1
|
|
||||||
rewrote API to use pseudo-methods instead of required functions.
|
|
||||||
lots of clean up.
|
|
||||||
Example can show symbols now.
|
|
||||||
All encodings
|
|
||||||
HTTP
|
|
||||||
|
@ -1,39 +1,147 @@
|
|||||||
Question: Why the *&!"/(§ did you change so many things in the API?
|
Mark sent me patches to no longer need C++ for ZRLE encoding!
|
||||||
Answer: It was necessary to make this library slightly less
|
added --disable-cxx Option for configure
|
||||||
painful to use with other libraries.
|
x11vnc changes from Karl Runge:
|
||||||
|
- Changed all those whimpy printf(...)'s into manly fprintf(stdxxx,...)'s.
|
||||||
|
|
||||||
Anyway, most changes are just search-and-replace:
|
- Added -q switch (quiet) to suppress printing all the debug-looking output.
|
||||||
|
|
||||||
#include "rfb.h" -> #include <rfb/rfb.h>
|
- Added -bg switch to fork into background after everything is set up.
|
||||||
CARD8 -> uint8_t
|
(checks for LIBVNCSERVER_HAVE_FORK and LIBVNCSERVER_HAVE_SETSID)
|
||||||
CARD16 -> uint16_t
|
|
||||||
CARD32 -> uint32_t
|
|
||||||
Pixel -> rfbPixel
|
|
||||||
KeySym -> rfbKeySym
|
|
||||||
Bool -> rfbBool
|
|
||||||
|
|
||||||
also, rfbUsage doesn't exit any longer, but returns FALSE
|
- Print this string out to stdout: 'PORT=XXXX' (usually XXXX = 5900).
|
||||||
|
Combining with -bg, easy to write a ssh/rsh wrapper with something like:
|
||||||
|
port=`ssh $host "x11vnc -bg .."` then run vncviewer based on $port output.
|
||||||
|
(tunneling the vnc traffic thru ssh a bit more messy, but doable)
|
||||||
|
|
||||||
If you used some constants defined in rfbconfig.h, you now
|
- Quite a bit of code to be more careful when doing 8bpp indexed color, e.g.
|
||||||
have to prefix LIBVNCSERVER_ to the constants.
|
not assuming NCOLORS is 256, handling 8bit TrueColor and Direct Color, etc
|
||||||
|
(I did all this probably in April, not quite clear in my mind now, but
|
||||||
Upcoming 0.6 release!
|
I did test it out a fair amount on my old Sparcstation 20 wrt a user's
|
||||||
|
questions).
|
||||||
lots of bugs fixed.
|
introduce rfbErr for Errors (Erik)
|
||||||
|
make rfbLog overridable (suggested by Erik)
|
||||||
|
don't reutrn on EINTR in WriteExact()/ReadExact() (suggested by Erik)
|
||||||
Version 5.0:
|
use AX_PREFIX_CONFIG_H to prefix constants in config.h to avoid
|
||||||
|
name clashes (also suggested by Erik)
|
||||||
The library just got autoconf && automake support as well as a real install
|
transformed Bool, KeySym, Pixel to rfbBool, rfbKeySym, rfbPixel
|
||||||
target!
|
(as suggested by Erik)
|
||||||
|
purged exit() calls (suggested by Erik)
|
||||||
x11vnc was much improved thanks to Karl Runge!
|
fixed bug with maxRectsPerUpdate and Tight Encoding (these are incompatible)
|
||||||
|
checked sync with TightVNC 1.2.8:
|
||||||
CursorPosUpdate encoding supported thanks to Const Kaplinsky!
|
viewonly/full passwords; if given a list, only the first is a full one
|
||||||
|
vncRandomBytes is a little more secure now
|
||||||
ZRLE encoding, if you have a c++ compiler!
|
new weights for tight encoding
|
||||||
|
checked sync with RealVNC 3.3.7
|
||||||
HTTP now optionally handles HTTP proxy functions to connect to the same
|
introduced maxRectsPerUpdate
|
||||||
server only.
|
added first alpha version of LibVNCClient
|
||||||
|
added simple and simple15 example (really simple examples)
|
||||||
Of course, a lot of bugs fixed since last release...
|
finally got around to fix configure in CVS
|
||||||
|
long standing http bug (.jar was sent twice) fixed by a friend of Karl named Mike
|
||||||
|
http options in cargs
|
||||||
|
when closing a client and no longer listening for new ones, don't crash
|
||||||
|
fixed a bug with ClientConnectionGone
|
||||||
|
endianness is checked at configure time
|
||||||
|
fixed a bug that prevented the first client from being closed
|
||||||
|
fixed that annoying "libvncserver-config --link" bug
|
||||||
|
make rfbReverseByte public (for rdp2vnc)
|
||||||
|
fixed compilation on OS X, IRIX, Solaris
|
||||||
|
install target for headers is now ${prefix}/include/rfb ("#include <rfb/rfb.h>")
|
||||||
|
renamed "sraRegion.h" to "rfbregion.h"
|
||||||
|
CARD{8,16,32} are more standard uint{8,16,32}_t now
|
||||||
|
fixed LinuxVNC colour handling
|
||||||
|
fixed a bug with pthreads where the connection was not closed
|
||||||
|
moved vncterm to main package (LinuxVNC included)
|
||||||
|
portability fixes (IRIX, OSX, Solaris)
|
||||||
|
more portable way to determine endianness and types of a given size
|
||||||
|
through autoconf based methods
|
||||||
|
0.5
|
||||||
|
rpm packaging through autoconf
|
||||||
|
autoconf'ed the whole package (including optional support for zlib,
|
||||||
|
pthreads and libjpeg as well as zrle/c++)
|
||||||
|
moved appropriate files to contrib/ and examples/ respectively
|
||||||
|
fixed long standing cargs bug (Justin "Zippy" Dearing)
|
||||||
|
Even better x11vnc from Karl J. Runge! (supports different kbd layouts of
|
||||||
|
client/server)
|
||||||
|
Better x11vnc from Karl J. Runge!
|
||||||
|
fixed severe bug (Const Kaplinsky)
|
||||||
|
got patch from Const Kaplisnky with CursorPosUpdate encoding and some Docs
|
||||||
|
sync'ed with newest RealVNC (ZRLE encoding)
|
||||||
|
a HTTP request for tunnelling was added (to fool strict web proxies)
|
||||||
|
sync'ed with TightVNC 1.2.5
|
||||||
|
0.4
|
||||||
|
support for NewFB from Const Kaplinsky
|
||||||
|
memory leaks squashed (localtime pseudo leak is still there :-)
|
||||||
|
small improvements for OSXvnc (still not working correctly)
|
||||||
|
synced with TightVNC 1.2.3
|
||||||
|
solaris compile cleanups
|
||||||
|
many x11vnc improvements
|
||||||
|
added backchannel, an encoding which needs special clients to pass
|
||||||
|
arbitrary data to the client
|
||||||
|
changes from Tim Jansen regarding multi threading and client blocking
|
||||||
|
as well as C++ compliancy
|
||||||
|
x11vnc can be controlled by starting again with special options if compiling
|
||||||
|
with LOCAL_CONTROL defined
|
||||||
|
0.3
|
||||||
|
added x11vnc, a x0rfbserver clone
|
||||||
|
regard deferUpdateTime in processEvents, if usec<0
|
||||||
|
initialize deferUpdateTime (memory "leak"!)
|
||||||
|
changed command line handling (arguments are parsed and then removed)
|
||||||
|
added very simple example: zippy
|
||||||
|
added rfbDrawLine, rfbDrawPixel
|
||||||
|
0.2
|
||||||
|
inserted a deferUpdate mechanism (X11 independent).
|
||||||
|
removed deletion of requestedRegion
|
||||||
|
added rfbLoadConsoleFont
|
||||||
|
fixed font colour handling.
|
||||||
|
added rfbSelectBox
|
||||||
|
added rfbDrawCharWithClip to allow for clipping and a background colour.
|
||||||
|
fixed font colours
|
||||||
|
added rfbFillRect
|
||||||
|
added IO function to check password.
|
||||||
|
rfbNewClient now sets the socket in the fd_set (for the select() call)
|
||||||
|
when compiling the library with HAVE_PTHREADS and an application
|
||||||
|
which includes "rfb.h" without, the structures got mixed up.
|
||||||
|
So, the pthreads section is now always at the end, and also
|
||||||
|
you get a linker error for rfbInitServer when using two different
|
||||||
|
pthread setups.
|
||||||
|
fixed two deadlocks: when setting a cursor and when using CopyRect
|
||||||
|
fixed CopyRect when copying modified regions (they lost the modified
|
||||||
|
property)
|
||||||
|
WIN32 target compiles and works for example :-)
|
||||||
|
fixed CopyRect (was using the wrong order of rectangles...)
|
||||||
|
should also work with pthreads, because copyrects are
|
||||||
|
always sent immediately (so that two consecutive copy rects
|
||||||
|
cannot conflict).
|
||||||
|
changed rfbUndrawCursor(rfbClientPtr) to (rfbScreenInfoPtr), because
|
||||||
|
this makes more sense!
|
||||||
|
flag backgroundLoop in rfbScreenInfo (if having pthreads)
|
||||||
|
CopyRect & CopyRegion were implemented.
|
||||||
|
if you use a rfbDoCopyR* function, it copies the data in the
|
||||||
|
framebuffer. If you prefer to do that yourself, use rfbScheduleCopyR*
|
||||||
|
instead; this doesn't modify the frameBuffer.
|
||||||
|
added flag to optionally not send XCursor updates, but only RichCursor,
|
||||||
|
or if that is not possible, fall back to server side cursor.
|
||||||
|
This is useful if your cursor has many nice colours.
|
||||||
|
fixed java viewer on server side:
|
||||||
|
SendCursorUpdate would send data even before the client pixel format
|
||||||
|
was set, but the java applet doesn't like the server's format.
|
||||||
|
fixed two pthread issues:
|
||||||
|
rfbSendFramebuffer was sent by a ProcessClientMessage function
|
||||||
|
(unprotected by updateMutex).
|
||||||
|
cursor coordinates were set without protection by cursorMutex
|
||||||
|
source is now equivalent to TridiaVNC 1.2.1
|
||||||
|
pthreads now work (use iterators!)
|
||||||
|
cursors are supported (rfbSetCursor automatically undraws cursor)
|
||||||
|
support for 3 bytes/pixel (slow!)
|
||||||
|
server side colourmap support
|
||||||
|
fixed rfbCloseClient not to close the connection (pthreads!)
|
||||||
|
this is done lazily (and with proper signalling).
|
||||||
|
cleaned up mac.c (from original OSXvnc); now compiles (untested!)
|
||||||
|
compiles cleanly on Linux, IRIX, BSD, Apple (Darwin)
|
||||||
|
fixed prototypes
|
||||||
|
0.1
|
||||||
|
rewrote API to use pseudo-methods instead of required functions.
|
||||||
|
lots of clean up.
|
||||||
|
Example can show symbols now.
|
||||||
|
All encodings
|
||||||
|
HTTP
|
||||||
|
@ -1,71 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// This is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation; either version 2 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This software is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this software; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
||||||
// USA.
|
|
||||||
|
|
||||||
#ifndef __RDR_EXCEPTION_H__
|
|
||||||
#define __RDR_EXCEPTION_H__
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
namespace rdr {
|
|
||||||
|
|
||||||
struct Exception {
|
|
||||||
enum { len = 256 };
|
|
||||||
char str_[len];
|
|
||||||
Exception(const char* s=0, const char* e="rdr::Exception") {
|
|
||||||
str_[0] = 0;
|
|
||||||
strncat(str_, e, len-1);
|
|
||||||
if (s) {
|
|
||||||
strncat(str_, ": ", len-1-strlen(str_));
|
|
||||||
strncat(str_, s, len-1-strlen(str_));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
virtual const char* str() const { return str_; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SystemException : public Exception {
|
|
||||||
int err;
|
|
||||||
SystemException(const char* s, int err_) : err(err_) {
|
|
||||||
str_[0] = 0;
|
|
||||||
strncat(str_, "rdr::SystemException: ", len-1);
|
|
||||||
strncat(str_, s, len-1-strlen(str_));
|
|
||||||
strncat(str_, ": ", len-1-strlen(str_));
|
|
||||||
strncat(str_, strerror(err), len-1-strlen(str_));
|
|
||||||
strncat(str_, " (", len-1-strlen(str_));
|
|
||||||
char buf[20];
|
|
||||||
sprintf(buf,"%d",err);
|
|
||||||
strncat(str_, buf, len-1-strlen(str_));
|
|
||||||
strncat(str_, ")", len-1-strlen(str_));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TimedOut : public Exception {
|
|
||||||
TimedOut(const char* s=0) : Exception(s,"rdr::TimedOut") {}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct EndOfStream : public Exception {
|
|
||||||
EndOfStream(const char* s=0) : Exception(s,"rdr::EndOfStream") {}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FrameException : public Exception {
|
|
||||||
FrameException(const char* s=0) : Exception(s,"rdr::FrameException") {}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,251 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// This is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation; either version 2 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This software is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this software; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
||||||
// USA.
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <winsock.h>
|
|
||||||
#include <sys/timeb.h>
|
|
||||||
#define read(s,b,l) recv(s,(char*)b,l,0)
|
|
||||||
#undef errno
|
|
||||||
#define errno WSAGetLastError()
|
|
||||||
#else
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// XXX should use autoconf HAVE_SYS_SELECT_H
|
|
||||||
#ifdef _AIX
|
|
||||||
#include <sys/select.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <rdr/FdInStream.h>
|
|
||||||
#include <rdr/Exception.h>
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
extern void rfbLog(const char *format, ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
using namespace rdr;
|
|
||||||
|
|
||||||
enum { DEFAULT_BUF_SIZE = 8192,
|
|
||||||
MIN_BULK_SIZE = 1024 };
|
|
||||||
|
|
||||||
FdInStream::FdInStream(int fd_, int timeout_, int bufSize_)
|
|
||||||
: fd(fd_), timeout(timeout_), blockCallback(0), blockCallbackArg(0),
|
|
||||||
timing(false), timeWaitedIn100us(5), timedKbits(0),
|
|
||||||
bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0)
|
|
||||||
{
|
|
||||||
ptr = end = start = new U8[bufSize];
|
|
||||||
}
|
|
||||||
|
|
||||||
FdInStream::FdInStream(int fd_, void (*blockCallback_)(void*),
|
|
||||||
void* blockCallbackArg_, int bufSize_)
|
|
||||||
: fd(fd_), timeout(0), blockCallback(blockCallback_),
|
|
||||||
blockCallbackArg(blockCallbackArg_),
|
|
||||||
timing(false), timeWaitedIn100us(5), timedKbits(0),
|
|
||||||
bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0)
|
|
||||||
{
|
|
||||||
ptr = end = start = new U8[bufSize];
|
|
||||||
}
|
|
||||||
|
|
||||||
FdInStream::~FdInStream()
|
|
||||||
{
|
|
||||||
delete [] start;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int FdInStream::pos()
|
|
||||||
{
|
|
||||||
return offset + ptr - start;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FdInStream::readBytes(void* data, int length)
|
|
||||||
{
|
|
||||||
if (length < MIN_BULK_SIZE) {
|
|
||||||
InStream::readBytes(data, length);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
U8* dataPtr = (U8*)data;
|
|
||||||
|
|
||||||
int n = end - ptr;
|
|
||||||
if (n > length) n = length;
|
|
||||||
|
|
||||||
memcpy(dataPtr, ptr, n);
|
|
||||||
dataPtr += n;
|
|
||||||
length -= n;
|
|
||||||
ptr += n;
|
|
||||||
|
|
||||||
while (length > 0) {
|
|
||||||
n = readWithTimeoutOrCallback(dataPtr, length);
|
|
||||||
dataPtr += n;
|
|
||||||
length -= n;
|
|
||||||
offset += n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int FdInStream::overrun(int itemSize, int nItems)
|
|
||||||
{
|
|
||||||
if (itemSize > bufSize)
|
|
||||||
throw Exception("FdInStream overrun: max itemSize exceeded");
|
|
||||||
|
|
||||||
if (end - ptr != 0)
|
|
||||||
memmove(start, ptr, end - ptr);
|
|
||||||
|
|
||||||
offset += ptr - start;
|
|
||||||
end -= ptr - start;
|
|
||||||
ptr = start;
|
|
||||||
|
|
||||||
while (end < start + itemSize) {
|
|
||||||
int n = readWithTimeoutOrCallback((U8*)end, start + bufSize - end);
|
|
||||||
end += n;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (itemSize * nItems > end - ptr)
|
|
||||||
nItems = (end - ptr) / itemSize;
|
|
||||||
|
|
||||||
return nItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
int FdInStream::checkReadable(int fd, int timeout)
|
|
||||||
{
|
|
||||||
while (true) {
|
|
||||||
fd_set rfds;
|
|
||||||
struct timeval tv;
|
|
||||||
|
|
||||||
tv.tv_sec = timeout / 1000;
|
|
||||||
tv.tv_usec = (timeout % 1000) * 1000;
|
|
||||||
|
|
||||||
FD_ZERO(&rfds);
|
|
||||||
FD_SET(fd, &rfds);
|
|
||||||
int n = select(fd+1, &rfds, 0, 0, &tv);
|
|
||||||
if (n != -1 || errno != EINTR)
|
|
||||||
return n;
|
|
||||||
rfbLog("select returned EINTR\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
static void gettimeofday(struct timeval* tv, void*)
|
|
||||||
{
|
|
||||||
LARGE_INTEGER counts, countsPerSec;
|
|
||||||
static double usecPerCount = 0.0;
|
|
||||||
|
|
||||||
if (QueryPerformanceCounter(&counts)) {
|
|
||||||
if (usecPerCount == 0.0) {
|
|
||||||
QueryPerformanceFrequency(&countsPerSec);
|
|
||||||
usecPerCount = 1000000.0 / countsPerSec.QuadPart;
|
|
||||||
}
|
|
||||||
|
|
||||||
LONGLONG usecs = (LONGLONG)(counts.QuadPart * usecPerCount);
|
|
||||||
tv->tv_usec = (long)(usecs % 1000000);
|
|
||||||
tv->tv_sec = (long)(usecs / 1000000);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
struct timeb tb;
|
|
||||||
ftime(&tb);
|
|
||||||
tv->tv_sec = tb.time;
|
|
||||||
tv->tv_usec = tb.millitm * 1000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int FdInStream::readWithTimeoutOrCallback(void* buf, int len)
|
|
||||||
{
|
|
||||||
struct timeval before, after;
|
|
||||||
if (timing)
|
|
||||||
gettimeofday(&before, 0);
|
|
||||||
|
|
||||||
int n = checkReadable(fd, timeout);
|
|
||||||
|
|
||||||
if (n < 0) throw SystemException("select",errno);
|
|
||||||
|
|
||||||
if (n == 0) {
|
|
||||||
if (timeout) throw TimedOut();
|
|
||||||
if (blockCallback) (*blockCallback)(blockCallbackArg);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
n = ::read(fd, buf, len);
|
|
||||||
if (n != -1 || errno != EINTR)
|
|
||||||
break;
|
|
||||||
rfbLog("read returned EINTR\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n < 0) throw SystemException("read",errno);
|
|
||||||
if (n == 0) throw EndOfStream();
|
|
||||||
|
|
||||||
if (timing) {
|
|
||||||
gettimeofday(&after, 0);
|
|
||||||
// rfbLog("%d.%06d\n",(after.tv_sec - before.tv_sec),
|
|
||||||
// (after.tv_usec - before.tv_usec));
|
|
||||||
int newTimeWaited = ((after.tv_sec - before.tv_sec) * 10000 +
|
|
||||||
(after.tv_usec - before.tv_usec) / 100);
|
|
||||||
int newKbits = n * 8 / 1000;
|
|
||||||
|
|
||||||
// if (newTimeWaited == 0) {
|
|
||||||
// rfbLog("new kbps infinite t %d k %d\n",
|
|
||||||
// newTimeWaited, newKbits);
|
|
||||||
// } else {
|
|
||||||
// rfbLog("new kbps %d t %d k %d\n",
|
|
||||||
// newKbits * 10000 / newTimeWaited, newTimeWaited, newKbits);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// limit rate to between 10kbit/s and 40Mbit/s
|
|
||||||
|
|
||||||
if (newTimeWaited > newKbits*1000) newTimeWaited = newKbits*1000;
|
|
||||||
if (newTimeWaited < newKbits/4) newTimeWaited = newKbits/4;
|
|
||||||
|
|
||||||
timeWaitedIn100us += newTimeWaited;
|
|
||||||
timedKbits += newKbits;
|
|
||||||
}
|
|
||||||
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FdInStream::startTiming()
|
|
||||||
{
|
|
||||||
timing = true;
|
|
||||||
|
|
||||||
// Carry over up to 1s worth of previous rate for smoothing.
|
|
||||||
|
|
||||||
if (timeWaitedIn100us > 10000) {
|
|
||||||
timedKbits = timedKbits * 10000 / timeWaitedIn100us;
|
|
||||||
timeWaitedIn100us = 10000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FdInStream::stopTiming()
|
|
||||||
{
|
|
||||||
timing = false;
|
|
||||||
if (timeWaitedIn100us < timedKbits/2)
|
|
||||||
timeWaitedIn100us = timedKbits/2; // upper limit 20Mbit/s
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int FdInStream::kbitsPerSecond()
|
|
||||||
{
|
|
||||||
// The following calculation will overflow 32-bit arithmetic if we have
|
|
||||||
// received more than about 50Mbytes (400Mbits) since we started timing, so
|
|
||||||
// it should be OK for a single RFB update.
|
|
||||||
|
|
||||||
return timedKbits * 10000 / timeWaitedIn100us;
|
|
||||||
}
|
|
@ -1,72 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// This is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation; either version 2 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This software is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this software; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
||||||
// USA.
|
|
||||||
|
|
||||||
//
|
|
||||||
// FdInStream streams from a file descriptor.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef __RDR_FDINSTREAM_H__
|
|
||||||
#define __RDR_FDINSTREAM_H__
|
|
||||||
|
|
||||||
#include <rdr/InStream.h>
|
|
||||||
|
|
||||||
namespace rdr {
|
|
||||||
|
|
||||||
class FdInStream : public InStream {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
FdInStream(int fd, int timeout=0, int bufSize=0);
|
|
||||||
FdInStream(int fd, void (*blockCallback)(void*), void* blockCallbackArg=0,
|
|
||||||
int bufSize=0);
|
|
||||||
virtual ~FdInStream();
|
|
||||||
|
|
||||||
int getFd() { return fd; }
|
|
||||||
int pos();
|
|
||||||
void readBytes(void* data, int length);
|
|
||||||
int bytesInBuf() { return end - ptr; }
|
|
||||||
|
|
||||||
void startTiming();
|
|
||||||
void stopTiming();
|
|
||||||
unsigned int kbitsPerSecond();
|
|
||||||
unsigned int timeWaited() { return timeWaitedIn100us; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
int overrun(int itemSize, int nItems);
|
|
||||||
|
|
||||||
private:
|
|
||||||
int checkReadable(int fd, int timeout);
|
|
||||||
int readWithTimeoutOrCallback(void* buf, int len);
|
|
||||||
|
|
||||||
int fd;
|
|
||||||
int timeout;
|
|
||||||
void (*blockCallback)(void*);
|
|
||||||
void* blockCallbackArg;
|
|
||||||
|
|
||||||
bool timing;
|
|
||||||
unsigned int timeWaitedIn100us;
|
|
||||||
unsigned int timedKbits;
|
|
||||||
|
|
||||||
int bufSize;
|
|
||||||
int offset;
|
|
||||||
U8* start;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // end of namespace rdr
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,113 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// This is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation; either version 2 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This software is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this software; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
||||||
// USA.
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <winsock.h>
|
|
||||||
#define write(s,b,l) send(s,(const char*)b,l,0)
|
|
||||||
#undef errno
|
|
||||||
#define errno WSAGetLastError()
|
|
||||||
#else
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <rdr/FdOutStream.h>
|
|
||||||
#include <rdr/Exception.h>
|
|
||||||
|
|
||||||
|
|
||||||
using namespace rdr;
|
|
||||||
|
|
||||||
enum { DEFAULT_BUF_SIZE = 16384,
|
|
||||||
MIN_BULK_SIZE = 1024 };
|
|
||||||
|
|
||||||
FdOutStream::FdOutStream(int fd_, int bufSize_)
|
|
||||||
: fd(fd_), bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0)
|
|
||||||
{
|
|
||||||
ptr = start = new U8[bufSize];
|
|
||||||
end = start + bufSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
FdOutStream::~FdOutStream()
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
flush();
|
|
||||||
} catch (Exception&) {
|
|
||||||
}
|
|
||||||
delete [] start;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void FdOutStream::writeBytes(const void* data, int length)
|
|
||||||
{
|
|
||||||
if (length < MIN_BULK_SIZE) {
|
|
||||||
OutStream::writeBytes(data, length);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const U8* dataPtr = (const U8*)data;
|
|
||||||
|
|
||||||
flush();
|
|
||||||
|
|
||||||
while (length > 0) {
|
|
||||||
int n = write(fd, dataPtr, length);
|
|
||||||
|
|
||||||
if (n < 0) throw SystemException("write",errno);
|
|
||||||
|
|
||||||
length -= n;
|
|
||||||
dataPtr += n;
|
|
||||||
offset += n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int FdOutStream::length()
|
|
||||||
{
|
|
||||||
return offset + ptr - start;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FdOutStream::flush()
|
|
||||||
{
|
|
||||||
U8* sentUpTo = start;
|
|
||||||
while (sentUpTo < ptr) {
|
|
||||||
int n = write(fd, (const void*) sentUpTo, ptr - sentUpTo);
|
|
||||||
|
|
||||||
if (n < 0) throw SystemException("write",errno);
|
|
||||||
|
|
||||||
sentUpTo += n;
|
|
||||||
offset += n;
|
|
||||||
}
|
|
||||||
|
|
||||||
ptr = start;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int FdOutStream::overrun(int itemSize, int nItems)
|
|
||||||
{
|
|
||||||
if (itemSize > bufSize)
|
|
||||||
throw Exception("FdOutStream overrun: max itemSize exceeded");
|
|
||||||
|
|
||||||
flush();
|
|
||||||
|
|
||||||
if (itemSize * nItems > end - ptr)
|
|
||||||
nItems = (end - ptr) / itemSize;
|
|
||||||
|
|
||||||
return nItems;
|
|
||||||
}
|
|
@ -1,53 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// This is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation; either version 2 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This software is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this software; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
||||||
// USA.
|
|
||||||
|
|
||||||
//
|
|
||||||
// FdOutStream streams to a file descriptor.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef __RDR_FDOUTSTREAM_H__
|
|
||||||
#define __RDR_FDOUTSTREAM_H__
|
|
||||||
|
|
||||||
#include <rdr/OutStream.h>
|
|
||||||
|
|
||||||
namespace rdr {
|
|
||||||
|
|
||||||
class FdOutStream : public OutStream {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
FdOutStream(int fd, int bufSize=0);
|
|
||||||
virtual ~FdOutStream();
|
|
||||||
|
|
||||||
int getFd() { return fd; }
|
|
||||||
|
|
||||||
void flush();
|
|
||||||
int length();
|
|
||||||
void writeBytes(const void* data, int length);
|
|
||||||
|
|
||||||
private:
|
|
||||||
int overrun(int itemSize, int nItems);
|
|
||||||
int fd;
|
|
||||||
int bufSize;
|
|
||||||
int offset;
|
|
||||||
U8* start;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,52 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// This is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation; either version 2 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This software is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this software; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
||||||
// USA.
|
|
||||||
|
|
||||||
//
|
|
||||||
// A FixedMemOutStream writes to a buffer of a fixed length.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef __RDR_FIXEDMEMOUTSTREAM_H__
|
|
||||||
#define __RDR_FIXEDMEMOUTSTREAM_H__
|
|
||||||
|
|
||||||
#include <rdr/OutStream.h>
|
|
||||||
#include <rdr/Exception.h>
|
|
||||||
|
|
||||||
namespace rdr {
|
|
||||||
|
|
||||||
class FixedMemOutStream : public OutStream {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
FixedMemOutStream(void* buf, int len) {
|
|
||||||
ptr = start = (U8*)buf;
|
|
||||||
end = start + len;
|
|
||||||
}
|
|
||||||
|
|
||||||
int length() { return ptr - start; }
|
|
||||||
void reposition(int pos) { ptr = start + pos; }
|
|
||||||
const void* data() { return (const void*)start; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
int overrun(int itemSize, int nItems) { throw EndOfStream(); }
|
|
||||||
U8* start;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,35 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// This is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation; either version 2 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This software is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this software; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
||||||
// USA.
|
|
||||||
|
|
||||||
#include <rdr/InStream.h>
|
|
||||||
#include <rdr/Exception.h>
|
|
||||||
|
|
||||||
using namespace rdr;
|
|
||||||
|
|
||||||
U32 InStream::maxStringLength = 65535;
|
|
||||||
|
|
||||||
char* InStream::readString()
|
|
||||||
{
|
|
||||||
U32 len = readU32();
|
|
||||||
if (len > maxStringLength)
|
|
||||||
throw Exception("InStream max string length exceeded");
|
|
||||||
char* str = new char[len+1];
|
|
||||||
readBytes(str, len);
|
|
||||||
str[len] = 0;
|
|
||||||
return str;
|
|
||||||
}
|
|
@ -1,143 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// This is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation; either version 2 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This software is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this software; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
||||||
// USA.
|
|
||||||
|
|
||||||
//
|
|
||||||
// rdr::InStream marshalls data from a buffer stored in RDR (RFB Data
|
|
||||||
// Representation).
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef __RDR_INSTREAM_H__
|
|
||||||
#define __RDR_INSTREAM_H__
|
|
||||||
|
|
||||||
#include <rdr/types.h>
|
|
||||||
#include <string.h> // for memcpy
|
|
||||||
|
|
||||||
namespace rdr {
|
|
||||||
|
|
||||||
class InStream {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
virtual ~InStream() {}
|
|
||||||
|
|
||||||
// check() ensures there is buffer data for at least one item of size
|
|
||||||
// itemSize bytes. Returns the number of items in the buffer (up to a
|
|
||||||
// maximum of nItems).
|
|
||||||
|
|
||||||
inline int check(int itemSize, int nItems=1)
|
|
||||||
{
|
|
||||||
if (ptr + itemSize * nItems > end) {
|
|
||||||
if (ptr + itemSize > end)
|
|
||||||
return overrun(itemSize, nItems);
|
|
||||||
|
|
||||||
nItems = (end - ptr) / itemSize;
|
|
||||||
}
|
|
||||||
return nItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
// readU/SN() methods read unsigned and signed N-bit integers.
|
|
||||||
|
|
||||||
inline U8 readU8() { check(1); return *ptr++; }
|
|
||||||
inline U16 readU16() { check(2); int b0 = *ptr++; int b1 = *ptr++;
|
|
||||||
return b0 << 8 | b1; }
|
|
||||||
inline U32 readU32() { check(4); int b0 = *ptr++; int b1 = *ptr++;
|
|
||||||
int b2 = *ptr++; int b3 = *ptr++;
|
|
||||||
return b0 << 24 | b1 << 16 | b2 << 8 | b3; }
|
|
||||||
|
|
||||||
inline S8 readS8() { return (S8) readU8(); }
|
|
||||||
inline S16 readS16() { return (S16)readU16(); }
|
|
||||||
inline S32 readS32() { return (S32)readU32(); }
|
|
||||||
|
|
||||||
// readString() reads a string - a U32 length followed by the data.
|
|
||||||
// Returns a null-terminated string - the caller should delete[] it
|
|
||||||
// afterwards.
|
|
||||||
|
|
||||||
char* readString();
|
|
||||||
|
|
||||||
// maxStringLength protects against allocating a huge buffer. Set it
|
|
||||||
// higher if you need longer strings.
|
|
||||||
|
|
||||||
static U32 maxStringLength;
|
|
||||||
|
|
||||||
inline void skip(int bytes) {
|
|
||||||
while (bytes > 0) {
|
|
||||||
int n = check(1, bytes);
|
|
||||||
ptr += n;
|
|
||||||
bytes -= n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// readBytes() reads an exact number of bytes.
|
|
||||||
|
|
||||||
virtual void readBytes(void* data, int length) {
|
|
||||||
U8* dataPtr = (U8*)data;
|
|
||||||
U8* dataEnd = dataPtr + length;
|
|
||||||
while (dataPtr < dataEnd) {
|
|
||||||
int n = check(1, dataEnd - dataPtr);
|
|
||||||
memcpy(dataPtr, ptr, n);
|
|
||||||
ptr += n;
|
|
||||||
dataPtr += n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// readOpaqueN() reads a quantity without byte-swapping.
|
|
||||||
|
|
||||||
inline U8 readOpaque8() { return readU8(); }
|
|
||||||
inline U16 readOpaque16() { check(2); U16 r; ((U8*)&r)[0] = *ptr++;
|
|
||||||
((U8*)&r)[1] = *ptr++; return r; }
|
|
||||||
inline U32 readOpaque32() { check(4); U32 r; ((U8*)&r)[0] = *ptr++;
|
|
||||||
((U8*)&r)[1] = *ptr++; ((U8*)&r)[2] = *ptr++;
|
|
||||||
((U8*)&r)[3] = *ptr++; return r; }
|
|
||||||
inline U32 readOpaque24A() { check(3); U32 r=0; ((U8*)&r)[0] = *ptr++;
|
|
||||||
((U8*)&r)[1] = *ptr++; ((U8*)&r)[2] = *ptr++;
|
|
||||||
return r; }
|
|
||||||
inline U32 readOpaque24B() { check(3); U32 r=0; ((U8*)&r)[1] = *ptr++;
|
|
||||||
((U8*)&r)[2] = *ptr++; ((U8*)&r)[3] = *ptr++;
|
|
||||||
return r; }
|
|
||||||
|
|
||||||
// pos() returns the position in the stream.
|
|
||||||
|
|
||||||
virtual int pos() = 0;
|
|
||||||
|
|
||||||
// getptr(), getend() and setptr() are "dirty" methods which allow you to
|
|
||||||
// manipulate the buffer directly. This is useful for a stream which is a
|
|
||||||
// wrapper around an underlying stream.
|
|
||||||
|
|
||||||
inline const U8* getptr() const { return ptr; }
|
|
||||||
inline const U8* getend() const { return end; }
|
|
||||||
inline void setptr(const U8* p) { ptr = p; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
// overrun() is implemented by a derived class to cope with buffer overrun.
|
|
||||||
// It ensures there are at least itemSize bytes of buffer data. Returns
|
|
||||||
// the number of items in the buffer (up to a maximum of nItems). itemSize
|
|
||||||
// is supposed to be "small" (a few bytes).
|
|
||||||
|
|
||||||
virtual int overrun(int itemSize, int nItems) = 0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
InStream() {}
|
|
||||||
const U8* ptr;
|
|
||||||
const U8* end;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,47 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// This is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation; either version 2 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This software is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this software; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
||||||
// USA.
|
|
||||||
|
|
||||||
#ifndef __RDR_MEMINSTREAM_H__
|
|
||||||
#define __RDR_MEMINSTREAM_H__
|
|
||||||
|
|
||||||
#include <rdr/InStream.h>
|
|
||||||
#include <rdr/Exception.h>
|
|
||||||
|
|
||||||
namespace rdr {
|
|
||||||
|
|
||||||
class MemInStream : public InStream {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
MemInStream(const void* data, int len) {
|
|
||||||
ptr = start = (const U8*)data;
|
|
||||||
end = start + len;
|
|
||||||
}
|
|
||||||
|
|
||||||
int pos() { return ptr - start; }
|
|
||||||
void reposition(int pos) { ptr = start + pos; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
int overrun(int itemSize, int nItems) { throw EndOfStream(); }
|
|
||||||
const U8* start;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,82 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// This is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation; either version 2 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This software is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this software; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
||||||
// USA.
|
|
||||||
|
|
||||||
//
|
|
||||||
// A MemOutStream grows as needed when data is written to it.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef __RDR_MEMOUTSTREAM_H__
|
|
||||||
#define __RDR_MEMOUTSTREAM_H__
|
|
||||||
|
|
||||||
#include <rdr/OutStream.h>
|
|
||||||
|
|
||||||
namespace rdr {
|
|
||||||
|
|
||||||
class MemOutStream : public OutStream {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
MemOutStream(int len=1024) {
|
|
||||||
start = ptr = new U8[len];
|
|
||||||
end = start + len;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~MemOutStream() {
|
|
||||||
delete [] start;
|
|
||||||
}
|
|
||||||
|
|
||||||
void writeBytes(const void* data, int length) {
|
|
||||||
check(length);
|
|
||||||
memcpy(ptr, data, length);
|
|
||||||
ptr += length;
|
|
||||||
}
|
|
||||||
|
|
||||||
int length() { return ptr - start; }
|
|
||||||
void clear() { ptr = start; };
|
|
||||||
void reposition(int pos) { ptr = start + pos; }
|
|
||||||
|
|
||||||
// data() returns a pointer to the buffer.
|
|
||||||
|
|
||||||
const void* data() { return (const void*)start; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
// overrun() either doubles the buffer or adds enough space for nItems of
|
|
||||||
// size itemSize bytes.
|
|
||||||
|
|
||||||
int overrun(int itemSize, int nItems) {
|
|
||||||
int len = ptr - start + itemSize * nItems;
|
|
||||||
if (len < (end - start) * 2)
|
|
||||||
len = (end - start) * 2;
|
|
||||||
|
|
||||||
U8* newStart = new U8[len];
|
|
||||||
memcpy(newStart, start, ptr - start);
|
|
||||||
ptr = newStart + (ptr - start);
|
|
||||||
delete [] start;
|
|
||||||
start = newStart;
|
|
||||||
end = newStart + len;
|
|
||||||
|
|
||||||
return nItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
U8* start;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,60 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// This is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation; either version 2 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This software is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this software; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
||||||
// USA.
|
|
||||||
|
|
||||||
#include <rdr/NullOutStream.h>
|
|
||||||
#include <rdr/Exception.h>
|
|
||||||
|
|
||||||
using namespace rdr;
|
|
||||||
|
|
||||||
static const int bufferSize = 1024;
|
|
||||||
|
|
||||||
NullOutStream::NullOutStream()
|
|
||||||
: offset(0)
|
|
||||||
{
|
|
||||||
start = ptr = new U8[bufferSize];
|
|
||||||
end = start + bufferSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
NullOutStream::~NullOutStream()
|
|
||||||
{
|
|
||||||
delete [] start;
|
|
||||||
}
|
|
||||||
|
|
||||||
int NullOutStream::length()
|
|
||||||
{
|
|
||||||
return offset + ptr - start;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NullOutStream::writeBytes(const void* data, int length)
|
|
||||||
{
|
|
||||||
offset += length;
|
|
||||||
}
|
|
||||||
|
|
||||||
int NullOutStream::overrun(int itemSize, int nItems)
|
|
||||||
{
|
|
||||||
if (itemSize > bufferSize)
|
|
||||||
throw Exception("NullOutStream overrun: max itemSize exceeded");
|
|
||||||
|
|
||||||
offset += ptr - start;
|
|
||||||
ptr = start;
|
|
||||||
|
|
||||||
if (itemSize * nItems > end - ptr)
|
|
||||||
nItems = (end - ptr) / itemSize;
|
|
||||||
|
|
||||||
return nItems;
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// This is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation; either version 2 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This software is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this software; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
||||||
// USA.
|
|
||||||
|
|
||||||
#ifndef __RDR_NULLOUTSTREAM_H__
|
|
||||||
#define __RDR_NULLOUTSTREAM_H__
|
|
||||||
|
|
||||||
#include <rdr/OutStream.h>
|
|
||||||
|
|
||||||
namespace rdr {
|
|
||||||
|
|
||||||
class NullOutStream : public OutStream {
|
|
||||||
|
|
||||||
public:
|
|
||||||
NullOutStream();
|
|
||||||
virtual ~NullOutStream();
|
|
||||||
int length();
|
|
||||||
void writeBytes(const void* data, int length);
|
|
||||||
|
|
||||||
private:
|
|
||||||
int overrun(int itemSize, int nItems);
|
|
||||||
int offset;
|
|
||||||
U8* start;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,152 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// This is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation; either version 2 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This software is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this software; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
||||||
// USA.
|
|
||||||
|
|
||||||
//
|
|
||||||
// rdr::OutStream marshalls data into a buffer stored in RDR (RFB Data
|
|
||||||
// Representation).
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef __RDR_OUTSTREAM_H__
|
|
||||||
#define __RDR_OUTSTREAM_H__
|
|
||||||
|
|
||||||
#include <rdr/types.h>
|
|
||||||
#include <string.h> // for memcpy
|
|
||||||
|
|
||||||
namespace rdr {
|
|
||||||
|
|
||||||
class OutStream {
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
OutStream() {}
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
virtual ~OutStream() {}
|
|
||||||
|
|
||||||
// check() ensures there is buffer space for at least one item of size
|
|
||||||
// itemSize bytes. Returns the number of items which fit (up to a maximum
|
|
||||||
// of nItems).
|
|
||||||
|
|
||||||
inline int check(int itemSize, int nItems=1)
|
|
||||||
{
|
|
||||||
if (ptr + itemSize * nItems > end) {
|
|
||||||
if (ptr + itemSize > end)
|
|
||||||
return overrun(itemSize, nItems);
|
|
||||||
|
|
||||||
nItems = (end - ptr) / itemSize;
|
|
||||||
}
|
|
||||||
return nItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
// writeU/SN() methods write unsigned and signed N-bit integers.
|
|
||||||
|
|
||||||
inline void writeU8( U8 u) { check(1); *ptr++ = u; }
|
|
||||||
inline void writeU16(U16 u) { check(2); *ptr++ = u >> 8; *ptr++ = (U8)u; }
|
|
||||||
inline void writeU32(U32 u) { check(4); *ptr++ = u >> 24; *ptr++ = u >> 16;
|
|
||||||
*ptr++ = u >> 8; *ptr++ = u; }
|
|
||||||
|
|
||||||
inline void writeS8( S8 s) { writeU8((U8)s); }
|
|
||||||
inline void writeS16(S16 s) { writeU16((U16)s); }
|
|
||||||
inline void writeS32(S32 s) { writeU32((U32)s); }
|
|
||||||
|
|
||||||
// writeString() writes a string - a U32 length followed by the data. The
|
|
||||||
// given string should be null-terminated (but the terminating null is not
|
|
||||||
// written to the stream).
|
|
||||||
|
|
||||||
inline void writeString(const char* str) {
|
|
||||||
U32 len = strlen(str);
|
|
||||||
writeU32(len);
|
|
||||||
writeBytes(str, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void pad(int bytes) {
|
|
||||||
while (bytes-- > 0) writeU8(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void skip(int bytes) {
|
|
||||||
while (bytes > 0) {
|
|
||||||
int n = check(1, bytes);
|
|
||||||
ptr += n;
|
|
||||||
bytes -= n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// writeBytes() writes an exact number of bytes.
|
|
||||||
|
|
||||||
virtual void writeBytes(const void* data, int length) {
|
|
||||||
const U8* dataPtr = (const U8*)data;
|
|
||||||
const U8* dataEnd = dataPtr + length;
|
|
||||||
while (dataPtr < dataEnd) {
|
|
||||||
int n = check(1, dataEnd - dataPtr);
|
|
||||||
memcpy(ptr, dataPtr, n);
|
|
||||||
ptr += n;
|
|
||||||
dataPtr += n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// writeOpaqueN() writes a quantity without byte-swapping.
|
|
||||||
|
|
||||||
inline void writeOpaque8( U8 u) { writeU8(u); }
|
|
||||||
inline void writeOpaque16(U16 u) { check(2); *ptr++ = ((U8*)&u)[0];
|
|
||||||
*ptr++ = ((U8*)&u)[1]; }
|
|
||||||
inline void writeOpaque32(U32 u) { check(4); *ptr++ = ((U8*)&u)[0];
|
|
||||||
*ptr++ = ((U8*)&u)[1];
|
|
||||||
*ptr++ = ((U8*)&u)[2];
|
|
||||||
*ptr++ = ((U8*)&u)[3]; }
|
|
||||||
inline void writeOpaque24A(U32 u) { check(3); *ptr++ = ((U8*)&u)[0];
|
|
||||||
*ptr++ = ((U8*)&u)[1];
|
|
||||||
*ptr++ = ((U8*)&u)[2]; }
|
|
||||||
inline void writeOpaque24B(U32 u) { check(3); *ptr++ = ((U8*)&u)[1];
|
|
||||||
*ptr++ = ((U8*)&u)[2];
|
|
||||||
*ptr++ = ((U8*)&u)[3]; }
|
|
||||||
|
|
||||||
// length() returns the length of the stream.
|
|
||||||
|
|
||||||
virtual int length() = 0;
|
|
||||||
|
|
||||||
// flush() requests that the stream be flushed.
|
|
||||||
|
|
||||||
virtual void flush() {}
|
|
||||||
|
|
||||||
// getptr(), getend() and setptr() are "dirty" methods which allow you to
|
|
||||||
// manipulate the buffer directly. This is useful for a stream which is a
|
|
||||||
// wrapper around an underlying stream.
|
|
||||||
|
|
||||||
inline U8* getptr() { return ptr; }
|
|
||||||
inline U8* getend() { return end; }
|
|
||||||
inline void setptr(U8* p) { ptr = p; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
// overrun() is implemented by a derived class to cope with buffer overrun.
|
|
||||||
// It ensures there are at least itemSize bytes of buffer space. Returns
|
|
||||||
// the number of items which fit (up to a maximum of nItems). itemSize is
|
|
||||||
// supposed to be "small" (a few bytes).
|
|
||||||
|
|
||||||
virtual int overrun(int itemSize, int nItems) = 0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
U8* ptr;
|
|
||||||
U8* end;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,121 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// This is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation; either version 2 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This software is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this software; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
||||||
// USA.
|
|
||||||
|
|
||||||
#include <rdr/ZlibInStream.h>
|
|
||||||
#include <rdr/Exception.h>
|
|
||||||
#include <zlib.h>
|
|
||||||
|
|
||||||
using namespace rdr;
|
|
||||||
|
|
||||||
enum { DEFAULT_BUF_SIZE = 16384 };
|
|
||||||
|
|
||||||
ZlibInStream::ZlibInStream(int bufSize_)
|
|
||||||
: underlying(0), bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0),
|
|
||||||
bytesIn(0)
|
|
||||||
{
|
|
||||||
zs = new z_stream;
|
|
||||||
zs->zalloc = Z_NULL;
|
|
||||||
zs->zfree = Z_NULL;
|
|
||||||
zs->opaque = Z_NULL;
|
|
||||||
zs->next_in = Z_NULL;
|
|
||||||
zs->avail_in = 0;
|
|
||||||
if (inflateInit(zs) != Z_OK) {
|
|
||||||
delete zs;
|
|
||||||
throw Exception("ZlibInStream: inflateInit failed");
|
|
||||||
}
|
|
||||||
ptr = end = start = new U8[bufSize];
|
|
||||||
}
|
|
||||||
|
|
||||||
ZlibInStream::~ZlibInStream()
|
|
||||||
{
|
|
||||||
delete [] start;
|
|
||||||
inflateEnd(zs);
|
|
||||||
delete zs;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ZlibInStream::setUnderlying(InStream* is, int bytesIn_)
|
|
||||||
{
|
|
||||||
underlying = is;
|
|
||||||
bytesIn = bytesIn_;
|
|
||||||
ptr = end = start;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ZlibInStream::pos()
|
|
||||||
{
|
|
||||||
return offset + ptr - start;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ZlibInStream::reset()
|
|
||||||
{
|
|
||||||
ptr = end = start;
|
|
||||||
if (!underlying) return;
|
|
||||||
|
|
||||||
while (bytesIn > 0) {
|
|
||||||
decompress();
|
|
||||||
end = start; // throw away any data
|
|
||||||
}
|
|
||||||
underlying = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ZlibInStream::overrun(int itemSize, int nItems)
|
|
||||||
{
|
|
||||||
if (itemSize > bufSize)
|
|
||||||
throw Exception("ZlibInStream overrun: max itemSize exceeded");
|
|
||||||
if (!underlying)
|
|
||||||
throw Exception("ZlibInStream overrun: no underlying stream");
|
|
||||||
|
|
||||||
if (end - ptr != 0)
|
|
||||||
memmove(start, ptr, end - ptr);
|
|
||||||
|
|
||||||
offset += ptr - start;
|
|
||||||
end -= ptr - start;
|
|
||||||
ptr = start;
|
|
||||||
|
|
||||||
while (end - ptr < itemSize) {
|
|
||||||
decompress();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (itemSize * nItems > end - ptr)
|
|
||||||
nItems = (end - ptr) / itemSize;
|
|
||||||
|
|
||||||
return nItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
// decompress() calls the decompressor once. Note that this won't necessarily
|
|
||||||
// generate any output data - it may just consume some input data.
|
|
||||||
|
|
||||||
void ZlibInStream::decompress()
|
|
||||||
{
|
|
||||||
zs->next_out = (U8*)end;
|
|
||||||
zs->avail_out = start + bufSize - end;
|
|
||||||
|
|
||||||
underlying->check(1);
|
|
||||||
zs->next_in = (U8*)underlying->getptr();
|
|
||||||
zs->avail_in = underlying->getend() - underlying->getptr();
|
|
||||||
if ((int)zs->avail_in > bytesIn)
|
|
||||||
zs->avail_in = bytesIn;
|
|
||||||
|
|
||||||
int rc = inflate(zs, Z_SYNC_FLUSH);
|
|
||||||
if (rc != Z_OK) {
|
|
||||||
throw Exception("ZlibInStream: inflate failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
bytesIn -= zs->next_in - underlying->getptr();
|
|
||||||
end = zs->next_out;
|
|
||||||
underlying->setptr(zs->next_in);
|
|
||||||
}
|
|
@ -1,59 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// This is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation; either version 2 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This software is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this software; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
||||||
// USA.
|
|
||||||
|
|
||||||
//
|
|
||||||
// ZlibInStream streams from a compressed data stream ("underlying"),
|
|
||||||
// decompressing with zlib on the fly.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef __RDR_ZLIBINSTREAM_H__
|
|
||||||
#define __RDR_ZLIBINSTREAM_H__
|
|
||||||
|
|
||||||
#include <rdr/InStream.h>
|
|
||||||
|
|
||||||
struct z_stream_s;
|
|
||||||
|
|
||||||
namespace rdr {
|
|
||||||
|
|
||||||
class ZlibInStream : public InStream {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
ZlibInStream(int bufSize=0);
|
|
||||||
virtual ~ZlibInStream();
|
|
||||||
|
|
||||||
void setUnderlying(InStream* is, int bytesIn);
|
|
||||||
void reset();
|
|
||||||
int pos();
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
int overrun(int itemSize, int nItems);
|
|
||||||
void decompress();
|
|
||||||
|
|
||||||
InStream* underlying;
|
|
||||||
int bufSize;
|
|
||||||
int offset;
|
|
||||||
z_stream_s* zs;
|
|
||||||
int bytesIn;
|
|
||||||
U8* start;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // end of namespace rdr
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,144 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// This is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation; either version 2 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This software is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this software; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
||||||
// USA.
|
|
||||||
|
|
||||||
#include <rdr/ZlibOutStream.h>
|
|
||||||
#include <rdr/Exception.h>
|
|
||||||
#include <zlib.h>
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
extern void rfbLog(const char *format, ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
using namespace rdr;
|
|
||||||
|
|
||||||
enum { DEFAULT_BUF_SIZE = 16384 };
|
|
||||||
|
|
||||||
ZlibOutStream::ZlibOutStream(OutStream* os, int bufSize_)
|
|
||||||
: underlying(os), bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0)
|
|
||||||
{
|
|
||||||
zs = new z_stream;
|
|
||||||
zs->zalloc = Z_NULL;
|
|
||||||
zs->zfree = Z_NULL;
|
|
||||||
zs->opaque = Z_NULL;
|
|
||||||
if (deflateInit(zs, Z_DEFAULT_COMPRESSION) != Z_OK) {
|
|
||||||
delete zs;
|
|
||||||
throw Exception("ZlibOutStream: deflateInit failed");
|
|
||||||
}
|
|
||||||
ptr = start = new U8[bufSize];
|
|
||||||
end = start + bufSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
ZlibOutStream::~ZlibOutStream()
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
flush();
|
|
||||||
} catch (Exception&) {
|
|
||||||
}
|
|
||||||
delete [] start;
|
|
||||||
deflateEnd(zs);
|
|
||||||
delete zs;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ZlibOutStream::setUnderlying(OutStream* os)
|
|
||||||
{
|
|
||||||
underlying = os;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ZlibOutStream::length()
|
|
||||||
{
|
|
||||||
return offset + ptr - start;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ZlibOutStream::flush()
|
|
||||||
{
|
|
||||||
zs->next_in = start;
|
|
||||||
zs->avail_in = ptr - start;
|
|
||||||
|
|
||||||
// rfbLog("zos flush: avail_in %d\n",zs->avail_in);
|
|
||||||
|
|
||||||
while (zs->avail_in != 0) {
|
|
||||||
|
|
||||||
do {
|
|
||||||
underlying->check(1);
|
|
||||||
zs->next_out = underlying->getptr();
|
|
||||||
zs->avail_out = underlying->getend() - underlying->getptr();
|
|
||||||
|
|
||||||
// rfbLog("zos flush: calling deflate, avail_in %d, avail_out %d\n",
|
|
||||||
// zs->avail_in,zs->avail_out);
|
|
||||||
int rc = deflate(zs, Z_SYNC_FLUSH);
|
|
||||||
if (rc != Z_OK) throw Exception("ZlibOutStream: deflate failed");
|
|
||||||
|
|
||||||
// rfbLog("zos flush: after deflate: %d bytes\n",
|
|
||||||
// zs->next_out-underlying->getptr());
|
|
||||||
|
|
||||||
underlying->setptr(zs->next_out);
|
|
||||||
} while (zs->avail_out == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
offset += ptr - start;
|
|
||||||
ptr = start;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ZlibOutStream::overrun(int itemSize, int nItems)
|
|
||||||
{
|
|
||||||
// rfbLog("ZlibOutStream overrun\n");
|
|
||||||
|
|
||||||
if (itemSize > bufSize)
|
|
||||||
throw Exception("ZlibOutStream overrun: max itemSize exceeded");
|
|
||||||
|
|
||||||
while (end - ptr < itemSize) {
|
|
||||||
zs->next_in = start;
|
|
||||||
zs->avail_in = ptr - start;
|
|
||||||
|
|
||||||
do {
|
|
||||||
underlying->check(1);
|
|
||||||
zs->next_out = underlying->getptr();
|
|
||||||
zs->avail_out = underlying->getend() - underlying->getptr();
|
|
||||||
|
|
||||||
// rfbLog("zos overrun: calling deflate, avail_in %d, avail_out %d\n",
|
|
||||||
// zs->avail_in,zs->avail_out);
|
|
||||||
|
|
||||||
int rc = deflate(zs, 0);
|
|
||||||
if (rc != Z_OK) throw Exception("ZlibOutStream: deflate failed");
|
|
||||||
|
|
||||||
// rfbLog("zos overrun: after deflate: %d bytes\n",
|
|
||||||
// zs->next_out-underlying->getptr());
|
|
||||||
|
|
||||||
underlying->setptr(zs->next_out);
|
|
||||||
} while (zs->avail_out == 0);
|
|
||||||
|
|
||||||
// output buffer not full
|
|
||||||
|
|
||||||
if (zs->avail_in == 0) {
|
|
||||||
offset += ptr - start;
|
|
||||||
ptr = start;
|
|
||||||
} else {
|
|
||||||
// but didn't consume all the data? try shifting what's left to the
|
|
||||||
// start of the buffer.
|
|
||||||
rfbLog("z out buf not full, but in data not consumed\n");
|
|
||||||
memmove(start, zs->next_in, ptr - zs->next_in);
|
|
||||||
offset += zs->next_in - start;
|
|
||||||
ptr -= zs->next_in - start;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (itemSize * nItems > end - ptr)
|
|
||||||
nItems = (end - ptr) / itemSize;
|
|
||||||
|
|
||||||
return nItems;
|
|
||||||
}
|
|
@ -1,57 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// This is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation; either version 2 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This software is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this software; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
||||||
// USA.
|
|
||||||
|
|
||||||
//
|
|
||||||
// ZlibOutStream streams to a compressed data stream (underlying), compressing
|
|
||||||
// with zlib on the fly.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef __RDR_ZLIBOUTSTREAM_H__
|
|
||||||
#define __RDR_ZLIBOUTSTREAM_H__
|
|
||||||
|
|
||||||
#include <rdr/OutStream.h>
|
|
||||||
|
|
||||||
struct z_stream_s;
|
|
||||||
|
|
||||||
namespace rdr {
|
|
||||||
|
|
||||||
class ZlibOutStream : public OutStream {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
ZlibOutStream(OutStream* os=0, int bufSize=0);
|
|
||||||
virtual ~ZlibOutStream();
|
|
||||||
|
|
||||||
void setUnderlying(OutStream* os);
|
|
||||||
void flush();
|
|
||||||
int length();
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
int overrun(int itemSize, int nItems);
|
|
||||||
|
|
||||||
OutStream* underlying;
|
|
||||||
int bufSize;
|
|
||||||
int offset;
|
|
||||||
z_stream_s* zs;
|
|
||||||
U8* start;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // end of namespace rdr
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,33 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// This is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation; either version 2 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This software is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this software; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
||||||
// USA.
|
|
||||||
|
|
||||||
#ifndef __RDR_TYPES_H__
|
|
||||||
#define __RDR_TYPES_H__
|
|
||||||
|
|
||||||
namespace rdr {
|
|
||||||
|
|
||||||
typedef unsigned char U8;
|
|
||||||
typedef unsigned short U16;
|
|
||||||
typedef unsigned int U32;
|
|
||||||
typedef signed char S8;
|
|
||||||
typedef signed short S16;
|
|
||||||
typedef signed int S32;
|
|
||||||
|
|
||||||
} // end of namespace rdr
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,179 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// This is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation; either version 2 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This software is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this software; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
||||||
// USA.
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// zrle.cc
|
|
||||||
//
|
|
||||||
// Routines to implement Zlib Run-length Encoding (ZRLE).
|
|
||||||
//
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include <rfb/rfb.h>
|
|
||||||
}
|
|
||||||
#include <rdr/MemOutStream.h>
|
|
||||||
#include <rdr/ZlibOutStream.h>
|
|
||||||
|
|
||||||
|
|
||||||
#define GET_IMAGE_INTO_BUF(tx,ty,tw,th,buf) \
|
|
||||||
char *fbptr = (cl->screen->frameBuffer \
|
|
||||||
+ (cl->screen->paddedWidthInBytes * ty) \
|
|
||||||
+ (tx * (cl->screen->bitsPerPixel / 8))); \
|
|
||||||
\
|
|
||||||
(*cl->translateFn)(cl->translateLookupTable, &cl->screen->rfbServerFormat,\
|
|
||||||
&cl->format, fbptr, (char*)buf, \
|
|
||||||
cl->screen->paddedWidthInBytes, tw, th);
|
|
||||||
|
|
||||||
#define EXTRA_ARGS , rfbClientPtr cl
|
|
||||||
|
|
||||||
#define BPP 8
|
|
||||||
#include <zrleEncode.h>
|
|
||||||
#undef BPP
|
|
||||||
#define BPP 16
|
|
||||||
#include <zrleEncode.h>
|
|
||||||
#undef BPP
|
|
||||||
#define BPP 32
|
|
||||||
#include <zrleEncode.h>
|
|
||||||
#define CPIXEL 24A
|
|
||||||
#include <zrleEncode.h>
|
|
||||||
#undef CPIXEL
|
|
||||||
#define CPIXEL 24B
|
|
||||||
#include <zrleEncode.h>
|
|
||||||
#undef CPIXEL
|
|
||||||
#undef BPP
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* zrleBeforeBuf contains pixel data in the client's format. It must be at
|
|
||||||
* least one pixel bigger than the largest tile of pixel data, since the
|
|
||||||
* ZRLE encoding algorithm writes to the position one past the end of the pixel
|
|
||||||
* data.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static char zrleBeforeBuf[rfbZRLETileWidth * rfbZRLETileHeight * 4 + 4];
|
|
||||||
|
|
||||||
static rdr::MemOutStream mos;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rfbSendRectEncodingZRLE - send a given rectangle using ZRLE encoding.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
rfbBool rfbSendRectEncodingZRLE(rfbClientPtr cl, int x, int y, int w, int h)
|
|
||||||
{
|
|
||||||
if (!cl->zrleData) cl->zrleData = new rdr::ZlibOutStream;
|
|
||||||
rdr::ZlibOutStream* zos = (rdr::ZlibOutStream*)cl->zrleData;
|
|
||||||
mos.clear();
|
|
||||||
|
|
||||||
switch (cl->format.bitsPerPixel) {
|
|
||||||
|
|
||||||
case 8:
|
|
||||||
zrleEncode8( x, y, w, h, &mos, zos, zrleBeforeBuf, cl);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 16:
|
|
||||||
zrleEncode16(x, y, w, h, &mos, zos, zrleBeforeBuf, cl);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 32:
|
|
||||||
bool fitsInLS3Bytes
|
|
||||||
= ((cl->format.redMax << cl->format.redShift) < (1<<24) &&
|
|
||||||
(cl->format.greenMax << cl->format.greenShift) < (1<<24) &&
|
|
||||||
(cl->format.blueMax << cl->format.blueShift) < (1<<24));
|
|
||||||
|
|
||||||
bool fitsInMS3Bytes = (cl->format.redShift > 7 &&
|
|
||||||
cl->format.greenShift > 7 &&
|
|
||||||
cl->format.blueShift > 7);
|
|
||||||
|
|
||||||
if ((fitsInLS3Bytes && !cl->format.bigEndian) ||
|
|
||||||
(fitsInMS3Bytes && cl->format.bigEndian))
|
|
||||||
{
|
|
||||||
zrleEncode24A(x, y, w, h, &mos, zos, zrleBeforeBuf, cl);
|
|
||||||
}
|
|
||||||
else if ((fitsInLS3Bytes && cl->format.bigEndian) ||
|
|
||||||
(fitsInMS3Bytes && !cl->format.bigEndian))
|
|
||||||
{
|
|
||||||
zrleEncode24B(x, y, w, h, &mos, zos, zrleBeforeBuf, cl);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
zrleEncode32(x, y, w, h, &mos, zos, zrleBeforeBuf, cl);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
cl->rfbRectanglesSent[rfbEncodingZRLE]++;
|
|
||||||
cl->rfbBytesSent[rfbEncodingZRLE] += (sz_rfbFramebufferUpdateRectHeader
|
|
||||||
+ sz_rfbZRLEHeader + mos.length());
|
|
||||||
|
|
||||||
if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbZRLEHeader
|
|
||||||
> UPDATE_BUF_SIZE)
|
|
||||||
{
|
|
||||||
if (!rfbSendUpdateBuf(cl))
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
rfbFramebufferUpdateRectHeader rect;
|
|
||||||
rect.r.x = Swap16IfLE(x);
|
|
||||||
rect.r.y = Swap16IfLE(y);
|
|
||||||
rect.r.w = Swap16IfLE(w);
|
|
||||||
rect.r.h = Swap16IfLE(h);
|
|
||||||
rect.encoding = Swap32IfLE(rfbEncodingZRLE);
|
|
||||||
|
|
||||||
memcpy(cl->updateBuf+cl->ublen, (char *)&rect,
|
|
||||||
sz_rfbFramebufferUpdateRectHeader);
|
|
||||||
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
|
|
||||||
|
|
||||||
rfbZRLEHeader hdr;
|
|
||||||
|
|
||||||
hdr.length = Swap32IfLE(mos.length());
|
|
||||||
|
|
||||||
memcpy(cl->updateBuf+cl->ublen, (char *)&hdr, sz_rfbZRLEHeader);
|
|
||||||
cl->ublen += sz_rfbZRLEHeader;
|
|
||||||
|
|
||||||
// copy into updateBuf and send from there. Maybe should send directly?
|
|
||||||
|
|
||||||
for (int i = 0; i < mos.length();) {
|
|
||||||
|
|
||||||
int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen;
|
|
||||||
|
|
||||||
if (i + bytesToCopy > mos.length()) {
|
|
||||||
bytesToCopy = mos.length() - i;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(cl->updateBuf+cl->ublen, (uint8_t*)mos.data() + i, bytesToCopy);
|
|
||||||
|
|
||||||
cl->ublen += bytesToCopy;
|
|
||||||
i += bytesToCopy;
|
|
||||||
|
|
||||||
if (cl->ublen == UPDATE_BUF_SIZE) {
|
|
||||||
if (!rfbSendUpdateBuf(cl))
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void FreeZrleData(rfbClientPtr cl)
|
|
||||||
{
|
|
||||||
delete (rdr::ZlibOutStream*)cl->zrleData;
|
|
||||||
}
|
|
||||||
|
|
@ -1,241 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// This is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation; either version 2 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This software is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this software; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
||||||
// USA.
|
|
||||||
|
|
||||||
//
|
|
||||||
// zrleDecode.h - zrle decoding function.
|
|
||||||
//
|
|
||||||
// Before including this file, you must define a number of CPP macros.
|
|
||||||
//
|
|
||||||
// BPP should be 8, 16 or 32 depending on the bits per pixel.
|
|
||||||
// FILL_RECT
|
|
||||||
// IMAGE_RECT
|
|
||||||
|
|
||||||
#include <rdr/ZlibInStream.h>
|
|
||||||
#include <rdr/InStream.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
using namespace rdr;
|
|
||||||
|
|
||||||
/* __RFB_CONCAT2 concatenates its two arguments. __RFB_CONCAT2E does the same
|
|
||||||
but also expands its arguments if they are macros */
|
|
||||||
|
|
||||||
#ifndef __RFB_CONCAT2E
|
|
||||||
#define __RFB_CONCAT2(a,b) a##b
|
|
||||||
#define __RFB_CONCAT2E(a,b) __RFB_CONCAT2(a,b)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CPIXEL
|
|
||||||
#define PIXEL_T __RFB_CONCAT2E(rdr::U,BPP)
|
|
||||||
#define READ_PIXEL __RFB_CONCAT2E(readOpaque,CPIXEL)
|
|
||||||
#define ZRLE_DECODE_BPP __RFB_CONCAT2E(zrleDecode,CPIXEL)
|
|
||||||
#else
|
|
||||||
#define PIXEL_T __RFB_CONCAT2E(rdr::U,BPP)
|
|
||||||
#define READ_PIXEL __RFB_CONCAT2E(readOpaque,BPP)
|
|
||||||
#define ZRLE_DECODE_BPP __RFB_CONCAT2E(zrleDecode,BPP)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void ZRLE_DECODE_BPP (int x, int y, int w, int h, rdr::InStream* is,
|
|
||||||
rdr::ZlibInStream* zis, PIXEL_T* buf)
|
|
||||||
{
|
|
||||||
int length = is->readU32();
|
|
||||||
zis->setUnderlying(is, length);
|
|
||||||
|
|
||||||
for (int ty = y; ty < y+h; ty += rfbZRLETileHeight) {
|
|
||||||
int th = rfbZRLETileHeight;
|
|
||||||
if (th > y+h-ty) th = y+h-ty;
|
|
||||||
for (int tx = x; tx < x+w; tx += rfbZRLETileWidth) {
|
|
||||||
int tw = rfbZRLETileWidth;
|
|
||||||
if (tw > x+w-tx) tw = x+w-tx;
|
|
||||||
|
|
||||||
int mode = zis->readU8();
|
|
||||||
bool rle = mode & 128;
|
|
||||||
int palSize = mode & 127;
|
|
||||||
PIXEL_T palette[128];
|
|
||||||
|
|
||||||
// fprintf(stderr,"rle %d palSize %d\n",rle,palSize);
|
|
||||||
|
|
||||||
for (int i = 0; i < palSize; i++) {
|
|
||||||
palette[i] = zis->READ_PIXEL();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (palSize == 1) {
|
|
||||||
PIXEL_T pix = palette[0];
|
|
||||||
FILL_RECT(tx,ty,tw,th,pix);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!rle) {
|
|
||||||
if (palSize == 0) {
|
|
||||||
|
|
||||||
// raw
|
|
||||||
|
|
||||||
#ifdef CPIXEL
|
|
||||||
for (PIXEL_T* ptr = buf; ptr < buf+tw*th; ptr++) {
|
|
||||||
*ptr = zis->READ_PIXEL();
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
zis->readBytes(buf, tw * th * (BPP / 8));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// packed pixels
|
|
||||||
int bppp = ((palSize > 16) ? 8 :
|
|
||||||
((palSize > 4) ? 4 : ((palSize > 2) ? 2 : 1)));
|
|
||||||
|
|
||||||
PIXEL_T* ptr = buf;
|
|
||||||
|
|
||||||
for (int i = 0; i < th; i++) {
|
|
||||||
PIXEL_T* eol = ptr + tw;
|
|
||||||
U8 byte = 0;
|
|
||||||
U8 nbits = 0;
|
|
||||||
|
|
||||||
while (ptr < eol) {
|
|
||||||
if (nbits == 0) {
|
|
||||||
byte = zis->readU8();
|
|
||||||
nbits = 8;
|
|
||||||
}
|
|
||||||
nbits -= bppp;
|
|
||||||
U8 index = (byte >> nbits) & ((1 << bppp) - 1) & 127;
|
|
||||||
*ptr++ = palette[index];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef FAVOUR_FILL_RECT
|
|
||||||
//fprintf(stderr,"copying data to screen %dx%d at %d,%d\n",tw,th,tx,ty);
|
|
||||||
IMAGE_RECT(tx,ty,tw,th,buf);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if (palSize == 0) {
|
|
||||||
|
|
||||||
// plain RLE
|
|
||||||
|
|
||||||
PIXEL_T* ptr = buf;
|
|
||||||
PIXEL_T* end = ptr + th * tw;
|
|
||||||
while (ptr < end) {
|
|
||||||
PIXEL_T pix = zis->READ_PIXEL();
|
|
||||||
int len = 1;
|
|
||||||
int b;
|
|
||||||
do {
|
|
||||||
b = zis->readU8();
|
|
||||||
len += b;
|
|
||||||
} while (b == 255);
|
|
||||||
|
|
||||||
assert(len <= end - ptr);
|
|
||||||
|
|
||||||
#ifdef FAVOUR_FILL_RECT
|
|
||||||
int i = ptr - buf;
|
|
||||||
ptr += len;
|
|
||||||
|
|
||||||
int runX = i % tw;
|
|
||||||
int runY = i / tw;
|
|
||||||
|
|
||||||
if (runX + len > tw) {
|
|
||||||
if (runX != 0) {
|
|
||||||
FILL_RECT(tx+runX, ty+runY, tw-runX, 1, pix);
|
|
||||||
len -= tw-runX;
|
|
||||||
runX = 0;
|
|
||||||
runY++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len > tw) {
|
|
||||||
FILL_RECT(tx, ty+runY, tw, len/tw, pix);
|
|
||||||
runY += len / tw;
|
|
||||||
len = len % tw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len != 0) {
|
|
||||||
FILL_RECT(tx+runX, ty+runY, len, 1, pix);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
while (len-- > 0) *ptr++ = pix;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// palette RLE
|
|
||||||
|
|
||||||
PIXEL_T* ptr = buf;
|
|
||||||
PIXEL_T* end = ptr + th * tw;
|
|
||||||
while (ptr < end) {
|
|
||||||
int index = zis->readU8();
|
|
||||||
int len = 1;
|
|
||||||
if (index & 128) {
|
|
||||||
int b;
|
|
||||||
do {
|
|
||||||
b = zis->readU8();
|
|
||||||
len += b;
|
|
||||||
} while (b == 255);
|
|
||||||
|
|
||||||
assert(len <= end - ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
index &= 127;
|
|
||||||
|
|
||||||
PIXEL_T pix = palette[index];
|
|
||||||
|
|
||||||
#ifdef FAVOUR_FILL_RECT
|
|
||||||
int i = ptr - buf;
|
|
||||||
ptr += len;
|
|
||||||
|
|
||||||
int runX = i % tw;
|
|
||||||
int runY = i / tw;
|
|
||||||
|
|
||||||
if (runX + len > tw) {
|
|
||||||
if (runX != 0) {
|
|
||||||
FILL_RECT(tx+runX, ty+runY, tw-runX, 1, pix);
|
|
||||||
len -= tw-runX;
|
|
||||||
runX = 0;
|
|
||||||
runY++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len > tw) {
|
|
||||||
FILL_RECT(tx, ty+runY, tw, len/tw, pix);
|
|
||||||
runY += len / tw;
|
|
||||||
len = len % tw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len != 0) {
|
|
||||||
FILL_RECT(tx+runX, ty+runY, len, 1, pix);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
while (len-- > 0) *ptr++ = pix;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef FAVOUR_FILL_RECT
|
|
||||||
//fprintf(stderr,"copying data to screen %dx%d at %d,%d\n",tw,th,tx,ty);
|
|
||||||
IMAGE_RECT(tx,ty,tw,th,buf);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
zis->reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef ZRLE_DECODE_BPP
|
|
||||||
#undef READ_PIXEL
|
|
||||||
#undef PIXEL_T
|
|
@ -1,310 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// This is free software; you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation; either version 2 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This software is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this software; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
||||||
// USA.
|
|
||||||
|
|
||||||
//
|
|
||||||
// zrleEncode.h - zrle encoding function.
|
|
||||||
//
|
|
||||||
// Before including this file, you must define a number of CPP macros.
|
|
||||||
//
|
|
||||||
// BPP should be 8, 16 or 32 depending on the bits per pixel.
|
|
||||||
// GET_IMAGE_INTO_BUF should be some code which gets a rectangle of pixel data
|
|
||||||
// into the given buffer. EXTRA_ARGS can be defined to pass any other
|
|
||||||
// arguments needed by GET_IMAGE_INTO_BUF.
|
|
||||||
//
|
|
||||||
// Note that the buf argument to ZRLE_ENCODE needs to be at least one pixel
|
|
||||||
// bigger than the largest tile of pixel data, since the ZRLE encoding
|
|
||||||
// algorithm writes to the position one past the end of the pixel data.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <rdr/OutStream.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
using namespace rdr;
|
|
||||||
|
|
||||||
/* __RFB_CONCAT2 concatenates its two arguments. __RFB_CONCAT2E does the same
|
|
||||||
but also expands its arguments if they are macros */
|
|
||||||
|
|
||||||
#ifndef __RFB_CONCAT2E
|
|
||||||
#define __RFB_CONCAT2(a,b) a##b
|
|
||||||
#define __RFB_CONCAT2E(a,b) __RFB_CONCAT2(a,b)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CPIXEL
|
|
||||||
#define PIXEL_T __RFB_CONCAT2E(rdr::U,BPP)
|
|
||||||
#define WRITE_PIXEL __RFB_CONCAT2E(writeOpaque,CPIXEL)
|
|
||||||
#define ZRLE_ENCODE __RFB_CONCAT2E(zrleEncode,CPIXEL)
|
|
||||||
#define ZRLE_ENCODE_TILE __RFB_CONCAT2E(zrleEncodeTile,CPIXEL)
|
|
||||||
#define BPPOUT 24
|
|
||||||
#else
|
|
||||||
#define PIXEL_T __RFB_CONCAT2E(rdr::U,BPP)
|
|
||||||
#define WRITE_PIXEL __RFB_CONCAT2E(writeOpaque,BPP)
|
|
||||||
#define ZRLE_ENCODE __RFB_CONCAT2E(zrleEncode,BPP)
|
|
||||||
#define ZRLE_ENCODE_TILE __RFB_CONCAT2E(zrleEncodeTile,BPP)
|
|
||||||
#define BPPOUT BPP
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef ZRLE_ONCE
|
|
||||||
#define ZRLE_ONCE
|
|
||||||
static const int bitsPerPackedPixel[] = {
|
|
||||||
0, 1, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
|
|
||||||
};
|
|
||||||
|
|
||||||
// The PaletteHelper class helps us build up the palette from pixel data by
|
|
||||||
// storing a reverse index using a simple hash-table
|
|
||||||
|
|
||||||
class PaletteHelper {
|
|
||||||
public:
|
|
||||||
enum { MAX_SIZE = 127 };
|
|
||||||
|
|
||||||
PaletteHelper()
|
|
||||||
{
|
|
||||||
memset(index, 255, sizeof(index));
|
|
||||||
size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int hash(rdr::U32 pix)
|
|
||||||
{
|
|
||||||
return (pix ^ (pix >> 17)) & 4095;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void insert(rdr::U32 pix)
|
|
||||||
{
|
|
||||||
if (size < MAX_SIZE) {
|
|
||||||
int i = hash(pix);
|
|
||||||
while (index[i] != 255 && key[i] != pix)
|
|
||||||
i++;
|
|
||||||
if (index[i] != 255) return;
|
|
||||||
|
|
||||||
index[i] = size;
|
|
||||||
key[i] = pix;
|
|
||||||
palette[size] = pix;
|
|
||||||
}
|
|
||||||
size++;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int lookup(rdr::U32 pix)
|
|
||||||
{
|
|
||||||
assert(size <= MAX_SIZE);
|
|
||||||
int i = hash(pix);
|
|
||||||
while (index[i] != 255 && key[i] != pix)
|
|
||||||
i++;
|
|
||||||
if (index[i] != 255) return index[i];
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
rdr::U32 palette[MAX_SIZE];
|
|
||||||
rdr::U8 index[4096+MAX_SIZE];
|
|
||||||
rdr::U32 key[4096+MAX_SIZE];
|
|
||||||
int size;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void ZRLE_ENCODE_TILE (PIXEL_T* data, int w, int h, rdr::OutStream* os);
|
|
||||||
|
|
||||||
void ZRLE_ENCODE (int x, int y, int w, int h, rdr::OutStream* os,
|
|
||||||
rdr::ZlibOutStream* zos, void* buf
|
|
||||||
EXTRA_ARGS
|
|
||||||
)
|
|
||||||
{
|
|
||||||
zos->setUnderlying(os);
|
|
||||||
|
|
||||||
for (int ty = y; ty < y+h; ty += rfbZRLETileHeight) {
|
|
||||||
int th = rfbZRLETileHeight;
|
|
||||||
if (th > y+h-ty) th = y+h-ty;
|
|
||||||
for (int tx = x; tx < x+w; tx += rfbZRLETileWidth) {
|
|
||||||
int tw = rfbZRLETileWidth;
|
|
||||||
if (tw > x+w-tx) tw = x+w-tx;
|
|
||||||
|
|
||||||
GET_IMAGE_INTO_BUF(tx,ty,tw,th,buf);
|
|
||||||
|
|
||||||
ZRLE_ENCODE_TILE((PIXEL_T*)buf, tw, th, zos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
zos->flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ZRLE_ENCODE_TILE (PIXEL_T* data, int w, int h, rdr::OutStream* os)
|
|
||||||
{
|
|
||||||
// First find the palette and the number of runs
|
|
||||||
|
|
||||||
PaletteHelper ph;
|
|
||||||
|
|
||||||
int runs = 0;
|
|
||||||
int singlePixels = 0;
|
|
||||||
|
|
||||||
PIXEL_T* ptr = data;
|
|
||||||
PIXEL_T* end = ptr + h * w;
|
|
||||||
*end = ~*(end-1); // one past the end is different so the while loop ends
|
|
||||||
|
|
||||||
while (ptr < end) {
|
|
||||||
PIXEL_T pix = *ptr;
|
|
||||||
if (*++ptr != pix) {
|
|
||||||
singlePixels++;
|
|
||||||
} else {
|
|
||||||
while (*++ptr == pix) ;
|
|
||||||
runs++;
|
|
||||||
}
|
|
||||||
ph.insert(pix);
|
|
||||||
}
|
|
||||||
|
|
||||||
//fprintf(stderr,"runs %d, single pixels %d, paletteSize %d\n",
|
|
||||||
// runs, singlePixels, ph.size);
|
|
||||||
|
|
||||||
// Solid tile is a special case
|
|
||||||
|
|
||||||
if (ph.size == 1) {
|
|
||||||
os->writeU8(1);
|
|
||||||
os->WRITE_PIXEL(ph.palette[0]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to work out whether to use RLE and/or a palette. We do this by
|
|
||||||
// estimating the number of bytes which will be generated and picking the
|
|
||||||
// method which results in the fewest bytes. Of course this may not result
|
|
||||||
// in the fewest bytes after compression...
|
|
||||||
|
|
||||||
bool useRle = false;
|
|
||||||
bool usePalette = false;
|
|
||||||
|
|
||||||
int estimatedBytes = w * h * (BPPOUT/8); // start assuming raw
|
|
||||||
|
|
||||||
int plainRleBytes = ((BPPOUT/8)+1) * (runs + singlePixels);
|
|
||||||
|
|
||||||
if (plainRleBytes < estimatedBytes) {
|
|
||||||
useRle = true;
|
|
||||||
estimatedBytes = plainRleBytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ph.size < 128) {
|
|
||||||
int paletteRleBytes = (BPPOUT/8) * ph.size + 2 * runs + singlePixels;
|
|
||||||
|
|
||||||
if (paletteRleBytes < estimatedBytes) {
|
|
||||||
useRle = true;
|
|
||||||
usePalette = true;
|
|
||||||
estimatedBytes = paletteRleBytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ph.size < 17) {
|
|
||||||
int packedBytes = ((BPPOUT/8) * ph.size +
|
|
||||||
w * h * bitsPerPackedPixel[ph.size-1] / 8);
|
|
||||||
|
|
||||||
if (packedBytes < estimatedBytes) {
|
|
||||||
useRle = false;
|
|
||||||
usePalette = true;
|
|
||||||
estimatedBytes = packedBytes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!usePalette) ph.size = 0;
|
|
||||||
|
|
||||||
os->writeU8((useRle ? 128 : 0) | ph.size);
|
|
||||||
|
|
||||||
for (int i = 0; i < ph.size; i++) {
|
|
||||||
os->WRITE_PIXEL(ph.palette[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (useRle) {
|
|
||||||
|
|
||||||
PIXEL_T* ptr = data;
|
|
||||||
PIXEL_T* end = ptr + w * h;
|
|
||||||
PIXEL_T* runStart;
|
|
||||||
PIXEL_T pix;
|
|
||||||
while (ptr < end) {
|
|
||||||
runStart = ptr;
|
|
||||||
pix = *ptr++;
|
|
||||||
while (*ptr == pix && ptr < end)
|
|
||||||
ptr++;
|
|
||||||
int len = ptr - runStart;
|
|
||||||
if (len <= 2 && usePalette) {
|
|
||||||
int index = ph.lookup(pix);
|
|
||||||
if (len == 2)
|
|
||||||
os->writeU8(index);
|
|
||||||
os->writeU8(index);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (usePalette) {
|
|
||||||
int index = ph.lookup(pix);
|
|
||||||
os->writeU8(index | 128);
|
|
||||||
} else {
|
|
||||||
os->WRITE_PIXEL(pix);
|
|
||||||
}
|
|
||||||
len -= 1;
|
|
||||||
while (len >= 255) {
|
|
||||||
os->writeU8(255);
|
|
||||||
len -= 255;
|
|
||||||
}
|
|
||||||
os->writeU8(len);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// no RLE
|
|
||||||
|
|
||||||
if (usePalette) {
|
|
||||||
|
|
||||||
// packed pixels
|
|
||||||
|
|
||||||
assert (ph.size < 17);
|
|
||||||
|
|
||||||
int bppp = bitsPerPackedPixel[ph.size-1];
|
|
||||||
|
|
||||||
PIXEL_T* ptr = data;
|
|
||||||
|
|
||||||
for (int i = 0; i < h; i++) {
|
|
||||||
U8 nbits = 0;
|
|
||||||
U8 byte = 0;
|
|
||||||
|
|
||||||
PIXEL_T* eol = ptr + w;
|
|
||||||
|
|
||||||
while (ptr < eol) {
|
|
||||||
PIXEL_T pix = *ptr++;
|
|
||||||
U8 index = ph.lookup(pix);
|
|
||||||
byte = (byte << bppp) | index;
|
|
||||||
nbits += bppp;
|
|
||||||
if (nbits >= 8) {
|
|
||||||
os->writeU8(byte);
|
|
||||||
nbits = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (nbits > 0) {
|
|
||||||
byte <<= 8 - nbits;
|
|
||||||
os->writeU8(byte);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// raw
|
|
||||||
|
|
||||||
#ifdef CPIXEL
|
|
||||||
for (PIXEL_T* ptr = data; ptr < data+w*h; ptr++) {
|
|
||||||
os->WRITE_PIXEL(*ptr);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
os->writeBytes(data, w*h*(BPP/8));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef PIXEL_T
|
|
||||||
#undef WRITE_PIXEL
|
|
||||||
#undef ZRLE_ENCODE
|
|
||||||
#undef ZRLE_ENCODE_TILE
|
|
||||||
#undef BPPOUT
|
|
Loading…
Reference in new issue