diff options
author | Pierre Ossman <ossman@cendio.se> | 2014-07-07 14:27:04 +0200 |
---|---|---|
committer | Pierre Ossman <ossman@cendio.se> | 2014-07-07 14:27:04 +0200 |
commit | 0aa3157cf6bf2a5d20a8a84515d2ee5c15faef65 (patch) | |
tree | 659c6081230675758edcfb66a394fc1aa3e1bacb | |
parent | 1338c0dc2d79235cd0380a1f11a7558548929a82 (diff) | |
parent | 5ad4d06006e96b1c7ff663ffcd5e406e06bae1c2 (diff) | |
download | tigervnc-0aa3157cf6bf2a5d20a8a84515d2ee5c15faef65.tar.gz tigervnc-0aa3157cf6bf2a5d20a8a84515d2ee5c15faef65.zip |
Merge branch 'cleanup' of https://github.com/CendioOssman/tigervnc
112 files changed, 763 insertions, 4856 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 2593a64b..c8de79f7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -378,18 +378,10 @@ else() set(CMAKE_EXTRA_INCLUDE_FILES sys/socket.h) endif() check_function_exists(inet_aton HAVE_INET_ATON) -check_function_exists(inet_ntop HAVE_INET_NTOP) check_function_exists(getaddrinfo HAVE_GETADDRINFO) -check_type_size(socklen_t SOCKLEN_T) set(CMAKE_EXTRA_INCLUDE_FILES) set(CMAKE_REQUIRED_LIBRARIES) -# Check for the newer standard string functions -check_function_exists(snprintf HAVE_SNPRINTF) -check_function_exists(strcasecmp HAVE_STRCASECMP) -check_function_exists(strncasecmp HAVE_STRNCASECMP) -check_function_exists(vsnprintf HAVE_VSNPRINTF) - # Generate config.h and make sure the source finds it configure_file(config.h.in config.h) add_definitions(-DHAVE_CONFIG_H) diff --git a/common/network/TcpSocket.cxx b/common/network/TcpSocket.cxx index e494a112..d9e9376a 100644 --- a/common/network/TcpSocket.cxx +++ b/common/network/TcpSocket.cxx @@ -43,7 +43,6 @@ #include <stdlib.h> #include <network/TcpSocket.h> -#include <os/net.h> #include <rfb/util.h> #include <rfb/LogWriter.h> diff --git a/common/os/CMakeLists.txt b/common/os/CMakeLists.txt index 39d5c106..fd3794dc 100644 --- a/common/os/CMakeLists.txt +++ b/common/os/CMakeLists.txt @@ -1,8 +1,6 @@ include_directories(${CMAKE_SOURCE_DIR}/common) add_library(os STATIC - print.c - net.c w32tiger.c os.cxx tls.cxx) diff --git a/common/os/net.c b/common/os/net.c deleted file mode 100644 index 7bad36c9..00000000 --- a/common/os/net.c +++ /dev/null @@ -1,53 +0,0 @@ -/* Copyright (C) 2008 TightVNC Team. 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. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdlib.h> -#include <string.h> - -#ifdef WIN32 -#include <winsock2.h> -#include <ws2tcpip.h> -#else -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#endif - -#include <os/net.h> - - -#ifndef HAVE_INET_NTOP -const char *tight_inet_ntop(int af, const void *src, char *dst, - socklen_t size) { - char *tempstr; - - /* Catch bugs - we should not use IPv6 if we don't have inet_ntop */ - if (af != AF_INET) - abort(); - - /* inet_ntoa never fails */ - tempstr = inet_ntoa(*(struct in_addr *)(src)); - memcpy(dst, tempstr, strlen(tempstr) + 1); - - return dst; -} -#endif diff --git a/common/os/net.h b/common/os/net.h deleted file mode 100644 index bd8b21cc..00000000 --- a/common/os/net.h +++ /dev/null @@ -1,50 +0,0 @@ -/* Copyright (C) 2008 TightVNC Team. 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 OS_NET_H -#define OS_NET_H - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef HAVE_SOCKLEN_T -typedef int socklen_t; -#endif - -/* IPv6 support on server side - we have to have all those functions */ -#if defined(HAVE_INET_NTOP) -#define HAVE_IPV6 -#endif - -/* IPv4-only stub implementation */ -#ifndef HAVE_INET_NTOP -const char *tight_inet_ntop(int af, const void *src, - char *dst, socklen_t size); -#define inet_ntop tight_inet_ntop -#endif - -#ifdef __cplusplus -}; -#endif - -#endif /* OS_NET_H */ diff --git a/common/os/print.c b/common/os/print.c deleted file mode 100644 index 4be22035..00000000 --- a/common/os/print.c +++ /dev/null @@ -1,104 +0,0 @@ -/* Copyright (C) 2008 TightVNC Team. 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. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <os/print.h> - -#include <stdarg.h> -#include <stdlib.h> -#include <string.h> - -#ifndef HAVE_VSNPRINTF -size_t internal_memcpy(char *dest, const char *src, size_t destsize, - size_t srcsize) { - size_t copied; - - copied = ((destsize) < (srcsize)) ? (destsize) : (srcsize); - memcpy(dest, src, copied); - - return copied; -} - -int tight_vsnprintf(char *str, size_t n, const char *format, va_list ap) { - int written = 0; - int tmpint, len; - char buf[64]; /* Is it enough? */ - char *tmpstr; - - if (format == NULL || n < 1) - return 0; - - while (*format != '\0' && written < n - 1) { - if (*format != '%') { - if (written < n) { - str[written++] = *format++; - continue; - } else - break; - } - - format++; - switch (*format) { - case '\0': - str[written++] = '%'; - continue; - case 'd': - tmpint = va_arg(ap, int); - sprintf(buf, "%d", tmpint); - len = strlen(buf); - written += internal_memcpy (&str[written], buf, - len, n - written); - break; - case 's': - tmpstr = va_arg(ap, char *); - len = strlen(tmpstr); - written += internal_memcpy (&str[written], - tmpstr, len, - n - written); - break; - /* Catch unimplemented stuff */ - default: - fprintf(stderr, "Unimplemented format: %c\n", - *format); - abort(); - } - format++; - } - - str[written] = '\0'; - - return written; -} -#endif /* HAVE_VSNPRINTF */ - -#ifndef HAVE_SNPRINTF -int tight_snprintf(char *str, size_t n, const char *format, ...) { - va_list ap; - int written; - - va_start(ap, format); - written = vsnprintf(str, n, format, ap); - va_end(ap); - - return written; -} -#endif /* HAVE_SNPRINTF */ - diff --git a/common/os/print.h b/common/os/print.h deleted file mode 100644 index 442dd642..00000000 --- a/common/os/print.h +++ /dev/null @@ -1,57 +0,0 @@ -/* Copyright (C) 2008 TightVNC Team. 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 OS_PRINT_H -#define OS_PRINT_H - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdarg.h> -#include <stdio.h> -#include <sys/types.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef HAVE_VSNPRINTF -/* NOTE: - * - * This is only very limited implementation for our internal purposes. It - * doesn't conform to C99/POSIX - * - limited conversion specifiers - * - returns written number of characters instead of number what would be - * written - */ -int tight_vsnprintf(char *str, size_t n, const char *format, va_list ap); -#define vsnprintf tight_vsnprintf -#endif - -#ifndef HAVE_SNPRINTF -/* Inherits tight_vsnprintf limitations if vsnprintf is not present */ -int tight_snprintf(char *str, size_t n, const char *format, ...); -#define snprintf tight_snprintf -#endif - -#ifdef __cplusplus -}; -#endif - -#endif /* OS_PRINT_H */ diff --git a/common/os/w32tiger.h b/common/os/w32tiger.h index 5e0c5de2..d09994f2 100644 --- a/common/os/w32tiger.h +++ b/common/os/w32tiger.h @@ -28,6 +28,11 @@ #include <wininet.h> +/* Windows has different names for these */ +#define strcasecmp _stricmp +#define strncasecmp _strnicmp + + /* MSLLHOOKSTRUCT structure*/ #ifndef LLMHF_INJECTED #define LLMHF_INJECTED 0x00000001 diff --git a/common/rdr/Exception.cxx b/common/rdr/Exception.cxx index fd40582f..d70cd9fc 100644 --- a/common/rdr/Exception.cxx +++ b/common/rdr/Exception.cxx @@ -22,6 +22,9 @@ #include <config.h> #endif +#include <stdio.h> +#include <stdarg.h> + #include <rdr/Exception.h> #include <rdr/TLSException.h> #ifdef _WIN32 @@ -30,8 +33,6 @@ #include <windows.h> #endif -#include <os/print.h> - #include <string.h> #ifdef HAVE_GNUTLS diff --git a/common/rdr/ZlibOutStream.cxx b/common/rdr/ZlibOutStream.cxx index 260bd1a4..9d9f8ba1 100644 --- a/common/rdr/ZlibOutStream.cxx +++ b/common/rdr/ZlibOutStream.cxx @@ -17,9 +17,10 @@ * USA. */ +#include <stdio.h> + #include <rdr/ZlibOutStream.h> #include <rdr/Exception.h> -#include <os/print.h> #include <zlib.h> diff --git a/common/rdr/msvcwarning.h b/common/rdr/msvcwarning.h deleted file mode 100644 index bea8d3f4..00000000 --- a/common/rdr/msvcwarning.h +++ /dev/null @@ -1,26 +0,0 @@ -/* Copyright (C) 2002-2005 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. - */ - -// Trim out extraneous cruft from windows.h includes -#define WIN32_LEAN_AND_MEAN - -// Force all Windows NT-specific APIs to be visible -#define _WIN32_WINNT 0xffff - -#pragma warning( disable : 4800 ) // forcing bool 'true' or 'false' -#pragma warning( disable : 4786 ) // truncating debug information to 255 chars
\ No newline at end of file diff --git a/common/rfb/CMakeLists.txt b/common/rfb/CMakeLists.txt index 27e3caa5..0300105a 100644 --- a/common/rfb/CMakeLists.txt +++ b/common/rfb/CMakeLists.txt @@ -52,7 +52,6 @@ set(RFB_SOURCES SSecurityStack.cxx SSecurityVncAuth.cxx SSecurityVeNCrypt.cxx - ScaledPixelBuffer.cxx ScaleFilters.cxx Timer.cxx TightDecoder.cxx diff --git a/common/rfb/CMsgHandler.h b/common/rfb/CMsgHandler.h index d69d4f21..d7ffd65b 100644 --- a/common/rfb/CMsgHandler.h +++ b/common/rfb/CMsgHandler.h @@ -71,8 +71,8 @@ namespace rfb { virtual void imageRect(const Rect& r, void* pixels) = 0; virtual void copyRect(const Rect& r, int srcX, int srcY) = 0; - virtual rdr::U8* getRawPixelsRW(const Rect& r, int* stride) = 0; - virtual void releaseRawPixels(const Rect& r) = 0; + virtual rdr::U8* getRawBufferRW(const Rect& r, int* stride) = 0; + virtual void releaseRawBuffer(const Rect& r) = 0; virtual const PixelFormat &getPreferredPF(void) = 0; diff --git a/common/rfb/CMsgWriter.cxx b/common/rfb/CMsgWriter.cxx index ddc25ff7..9ee7a02f 100644 --- a/common/rfb/CMsgWriter.cxx +++ b/common/rfb/CMsgWriter.cxx @@ -18,6 +18,7 @@ #include <stdio.h> #include <rdr/OutStream.h> #include <rfb/msgTypes.h> +#include <rfb/encodings.h> #include <rfb/PixelFormat.h> #include <rfb/Rect.h> #include <rfb/ConnParams.h> @@ -113,9 +114,9 @@ void CMsgWriter::writeSetEncodings(int preferredEncoding, bool useCopyRect) } } - if (cp->customCompressLevel && cp->compressLevel >= 0 && cp->compressLevel <= 9) + if (cp->compressLevel >= 0 && cp->compressLevel <= 9) encodings[nEncodings++] = pseudoEncodingCompressLevel0 + cp->compressLevel; - if (!cp->noJpeg && cp->qualityLevel >= 0 && cp->qualityLevel <= 9) + if (cp->qualityLevel >= 0 && cp->qualityLevel <= 9) encodings[nEncodings++] = pseudoEncodingQualityLevel0 + cp->qualityLevel; writeSetEncodings(nEncodings, encodings); diff --git a/common/rfb/CSecurityTLS.cxx b/common/rfb/CSecurityTLS.cxx index 59fd5067..a8abeeb0 100644 --- a/common/rfb/CSecurityTLS.cxx +++ b/common/rfb/CSecurityTLS.cxx @@ -42,7 +42,6 @@ #include <rdr/TLSInStream.h> #include <rdr/TLSOutStream.h> #include <os/os.h> -#include <os/print.h> #include <os/tls.h> #include <gnutls/x509.h> diff --git a/common/rfb/ComparingUpdateTracker.cxx b/common/rfb/ComparingUpdateTracker.cxx index 1c2bd383..8d4311a1 100644 --- a/common/rfb/ComparingUpdateTracker.cxx +++ b/common/rfb/ComparingUpdateTracker.cxx @@ -53,7 +53,7 @@ bool ComparingUpdateTracker::compare() for (int y=0; y<fb->height(); y+=BLOCK_SIZE) { Rect pos(0, y, fb->width(), __rfbmin(fb->height(), y+BLOCK_SIZE)); int srcStride; - const rdr::U8* srcData = fb->getPixelsR(pos, &srcStride); + const rdr::U8* srcData = fb->getBuffer(pos, &srcStride); oldFb.imageRect(pos, srcData, srcStride); } @@ -106,7 +106,7 @@ void ComparingUpdateTracker::compareRect(const Rect& r, Region* newChanged) int bytesPerPixel = fb->getPF().bpp/8; int oldStride; - rdr::U8* oldData = oldFb.getPixelsRW(r, &oldStride); + rdr::U8* oldData = oldFb.getBufferRW(r, &oldStride); int oldStrideBytes = oldStride * bytesPerPixel; std::vector<Rect> changedBlocks; @@ -116,7 +116,7 @@ void ComparingUpdateTracker::compareRect(const Rect& r, Region* newChanged) // Get a strip of the source buffer Rect pos(r.tl.x, blockTop, r.br.x, __rfbmin(r.br.y, blockTop+BLOCK_SIZE)); int fbStride; - const rdr::U8* newBlockPtr = fb->getPixelsR(pos, &fbStride); + const rdr::U8* newBlockPtr = fb->getBuffer(pos, &fbStride); int newStrideBytes = fbStride * bytesPerPixel; rdr::U8* oldBlockPtr = oldData; diff --git a/common/rfb/Configuration.cxx b/common/rfb/Configuration.cxx index 414b18f7..d7005221 100644 --- a/common/rfb/Configuration.cxx +++ b/common/rfb/Configuration.cxx @@ -22,10 +22,6 @@ #include <stdlib.h> #include <ctype.h> #include <string.h> -#ifdef WIN32 -#define strcasecmp _stricmp -#define strncasecmp _strnicmp -#endif #include <rfb/util.h> #include <rfb/Configuration.h> diff --git a/common/rfb/ConnParams.cxx b/common/rfb/ConnParams.cxx index ed747523..6fd6668e 100644 --- a/common/rfb/ConnParams.cxx +++ b/common/rfb/ConnParams.cxx @@ -1,5 +1,6 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. * Copyright (C) 2011 D. R. Commander. All Rights Reserved. + * Copyright 2014 Pierre Ossman for Cendio AB * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,10 +36,8 @@ ConnParams::ConnParams() supportsDesktopRename(false), supportsLastRect(false), supportsSetDesktopSize(false), supportsFence(false), supportsContinuousUpdates(false), - customCompressLevel(false), compressLevel(2), - noJpeg(false), qualityLevel(-1), fineQualityLevel(-1), - subsampling(SUBSAMP_UNDEFINED), - name_(0), nEncodings_(0), encodings_(0), + compressLevel(2), qualityLevel(-1), fineQualityLevel(-1), + subsampling(subsampleUndefined), name_(0), currentEncoding_(encodingRaw), verStrPos(0) { setName(""); @@ -47,7 +46,6 @@ ConnParams::ConnParams() ConnParams::~ConnParams() { delete [] name_; - delete [] encodings_; } bool ConnParams::readVersion(rdr::InStream* is, bool* done) @@ -90,69 +88,80 @@ void ConnParams::setName(const char* name) void ConnParams::setEncodings(int nEncodings, const rdr::S32* encodings) { - if (nEncodings > nEncodings_) { - delete [] encodings_; - encodings_ = new rdr::S32[nEncodings]; - } - nEncodings_ = nEncodings; useCopyRect = false; supportsLocalCursor = false; supportsDesktopResize = false; supportsExtendedDesktopSize = false; supportsLocalXCursor = false; supportsLastRect = false; - customCompressLevel = false; compressLevel = -1; - noJpeg = true; qualityLevel = -1; fineQualityLevel = -1; - subsampling = SUBSAMP_UNDEFINED; + subsampling = subsampleUndefined; currentEncoding_ = encodingRaw; for (int i = nEncodings-1; i >= 0; i--) { - encodings_[i] = encodings[i]; - - if (encodings[i] == encodingCopyRect) + switch (encodings[i]) { + case encodingCopyRect: useCopyRect = true; - else if (encodings[i] == pseudoEncodingCursor) + break; + case pseudoEncodingCursor: supportsLocalCursor = true; - else if (encodings[i] == pseudoEncodingXCursor) + break; + case pseudoEncodingXCursor: supportsLocalXCursor = true; - else if (encodings[i] == pseudoEncodingDesktopSize) + break; + case pseudoEncodingDesktopSize: supportsDesktopResize = true; - else if (encodings[i] == pseudoEncodingExtendedDesktopSize) + break; + case pseudoEncodingExtendedDesktopSize: supportsExtendedDesktopSize = true; - else if (encodings[i] == pseudoEncodingDesktopName) + break; + case pseudoEncodingDesktopName: supportsDesktopRename = true; - else if (encodings[i] == pseudoEncodingLastRect) + break; + case pseudoEncodingLastRect: supportsLastRect = true; - else if (encodings[i] == pseudoEncodingFence) + break; + case pseudoEncodingFence: supportsFence = true; - else if (encodings[i] == pseudoEncodingContinuousUpdates) + break; + case pseudoEncodingContinuousUpdates: supportsContinuousUpdates = true; - else if (encodings[i] >= pseudoEncodingCompressLevel0 && - encodings[i] <= pseudoEncodingCompressLevel9) { - customCompressLevel = true; + break; + case pseudoEncodingSubsamp1X: + subsampling = subsampleNone; + break; + case pseudoEncodingSubsampGray: + subsampling = subsampleGray; + break; + case pseudoEncodingSubsamp2X: + subsampling = subsample2X; + break; + case pseudoEncodingSubsamp4X: + subsampling = subsample4X; + break; + case pseudoEncodingSubsamp8X: + subsampling = subsample8X; + break; + case pseudoEncodingSubsamp16X: + subsampling = subsample16X; + break; + } + + if (encodings[i] >= pseudoEncodingCompressLevel0 && + encodings[i] <= pseudoEncodingCompressLevel9) compressLevel = encodings[i] - pseudoEncodingCompressLevel0; - } else if (encodings[i] >= pseudoEncodingQualityLevel0 && - encodings[i] <= pseudoEncodingQualityLevel9) { - noJpeg = false; + + if (encodings[i] >= pseudoEncodingQualityLevel0 && + encodings[i] <= pseudoEncodingQualityLevel9) qualityLevel = encodings[i] - pseudoEncodingQualityLevel0; - } else if (Encoder::supported(encodings[i])) - currentEncoding_ = encodings[i]; - } - // If the TurboVNC fine quality/subsampling encodings exist, let them - // override the coarse TightVNC quality level - for (int i = nEncodings-1; i >= 0; i--) { - if (encodings[i] >= pseudoEncodingFineQualityLevel0 + 1 && - encodings[i] <= pseudoEncodingFineQualityLevel100) { - noJpeg = false; + if (encodings[i] >= pseudoEncodingFineQualityLevel0 && + encodings[i] <= pseudoEncodingFineQualityLevel100) fineQualityLevel = encodings[i] - pseudoEncodingFineQualityLevel0; - } else if (encodings[i] >= pseudoEncodingSubsamp1X && - encodings[i] <= pseudoEncodingSubsampGray) { - noJpeg = false; - subsampling = (JPEG_SUBSAMP)(encodings[i] - pseudoEncodingSubsamp1X); - } + + if (Encoder::supported(encodings[i])) + currentEncoding_ = encodings[i]; } } diff --git a/common/rfb/ConnParams.h b/common/rfb/ConnParams.h index fa0fe022..43267ffd 100644 --- a/common/rfb/ConnParams.h +++ b/common/rfb/ConnParams.h @@ -1,4 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * Copyright 2014 Pierre Ossman for Cendio AB * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,12 +26,19 @@ #include <rdr/types.h> #include <rfb/PixelFormat.h> #include <rfb/ScreenSet.h> -#include <rfb/JpegCompressor.h> namespace rdr { class InStream; } namespace rfb { + const int subsampleUndefined = -1; + const int subsampleNone = 0; + const int subsampleGray = 1; + const int subsample2X = 2; + const int subsample4X = 3; + const int subsample8X = 4; + const int subsample16X = 5; + class ConnParams { public: ConnParams(); @@ -67,9 +75,9 @@ namespace rfb { void setName(const char* name); rdr::S32 currentEncoding() { return currentEncoding_; } - int nEncodings() { return nEncodings_; } - const rdr::S32* encodings() { return encodings_; } + void setEncodings(int nEncodings, const rdr::S32* encodings); + bool useCopyRect; bool supportsLocalCursor; @@ -83,19 +91,15 @@ namespace rfb { bool supportsFence; bool supportsContinuousUpdates; - bool customCompressLevel; int compressLevel; - bool noJpeg; int qualityLevel; int fineQualityLevel; - JPEG_SUBSAMP subsampling; + int subsampling; private: PixelFormat pf_; char* name_; - int nEncodings_; - rdr::S32* encodings_; int currentEncoding_; char verStr[13]; int verStrPos; diff --git a/common/rfb/Decoder.cxx b/common/rfb/Decoder.cxx index 193b61c0..e201821f 100644 --- a/common/rfb/Decoder.cxx +++ b/common/rfb/Decoder.cxx @@ -1,4 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * Copyright 2014 Pierre Ossman for Cendio AB * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,7 +17,7 @@ * USA. */ #include <stdio.h> -#include <rfb/Exception.h> +#include <rfb/encodings.h> #include <rfb/Decoder.h> #include <rfb/RawDecoder.h> #include <rfb/RREDecoder.h> @@ -30,41 +31,34 @@ Decoder::~Decoder() { } -DecoderCreateFnType Decoder::createFns[encodingMax+1] = { 0 }; - bool Decoder::supported(int encoding) { - return encoding >= 0 && encoding <= encodingMax && createFns[encoding]; + switch (encoding) { + case encodingRaw: + case encodingRRE: + case encodingHextile: + case encodingZRLE: + case encodingTight: + return true; + default: + return false; + } } Decoder* Decoder::createDecoder(int encoding, CMsgReader* reader) { - if (supported(encoding)) - return (*createFns[encoding])(reader); - return 0; -} - -void Decoder::registerDecoder(int encoding, - DecoderCreateFnType createFn) -{ - if (encoding > encodingMax) - throw Exception("Decoder::registerDecoder: encoding out of range"); - - if (createFns[encoding]) - fprintf(stderr,"Replacing existing decoder for encoding %s (%d)\n", - encodingName(encoding), encoding); - createFns[encoding] = createFn; -} - -int DecoderInit::count = 0; - -DecoderInit::DecoderInit() -{ - if (count++ != 0) return; - - Decoder::registerDecoder(encodingRaw, RawDecoder::create); - Decoder::registerDecoder(encodingRRE, RREDecoder::create); - Decoder::registerDecoder(encodingHextile, HextileDecoder::create); - Decoder::registerDecoder(encodingZRLE, ZRLEDecoder::create); - Decoder::registerDecoder(encodingTight, TightDecoder::create); + switch (encoding) { + case encodingRaw: + return new RawDecoder(reader); + case encodingRRE: + return new RREDecoder(reader); + case encodingHextile: + return new HextileDecoder(reader); + case encodingZRLE: + return new ZRLEDecoder(reader); + case encodingTight: + return new TightDecoder(reader); + default: + return NULL; + } } diff --git a/common/rfb/Decoder.h b/common/rfb/Decoder.h index 50aee82f..025d63f5 100644 --- a/common/rfb/Decoder.h +++ b/common/rfb/Decoder.h @@ -1,4 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * Copyright 2014 Pierre Ossman for Cendio AB * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,13 +20,10 @@ #define __RFB_DECODER_H__ #include <rfb/Rect.h> -#include <rfb/encodings.h> namespace rfb { class CMsgReader; class CMsgHandler; - class Decoder; - typedef Decoder* (*DecoderCreateFnType)(CMsgReader*); class Decoder { public: @@ -34,19 +32,7 @@ namespace rfb { static bool supported(int encoding); static Decoder* createDecoder(int encoding, CMsgReader* reader); - static void registerDecoder(int encoding, - DecoderCreateFnType createFn); - private: - static DecoderCreateFnType createFns[encodingMax+1]; }; - - class DecoderInit { - static int count; - public: - DecoderInit(); - }; - - static DecoderInit decoderInitObj; } #endif diff --git a/common/rfb/Encoder.cxx b/common/rfb/Encoder.cxx index 5de75430..1733c8ec 100644 --- a/common/rfb/Encoder.cxx +++ b/common/rfb/Encoder.cxx @@ -1,4 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * Copyright 2014 Pierre Ossman for Cendio AB * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,6 +17,7 @@ * USA. */ #include <stdio.h> +#include <rfb/encodings.h> #include <rfb/Exception.h> #include <rfb/Encoder.h> #include <rfb/RawEncoder.h> @@ -30,48 +32,34 @@ Encoder::~Encoder() { } -EncoderCreateFnType Encoder::createFns[encodingMax+1] = { 0 }; - bool Encoder::supported(int encoding) { - return encoding >= 0 && encoding <= encodingMax && createFns[encoding]; + switch (encoding) { + case encodingRaw: + case encodingRRE: + case encodingHextile: + case encodingZRLE: + case encodingTight: + return true; + default: + return false; + } } Encoder* Encoder::createEncoder(int encoding, SMsgWriter* writer) { - if (supported(encoding)) - return (*createFns[encoding])(writer); - return 0; -} - -void Encoder::registerEncoder(int encoding, - EncoderCreateFnType createFn) -{ - if (encoding > encodingMax) - throw Exception("Encoder::registerEncoder: encoding out of range"); - - if (createFns[encoding]) - fprintf(stderr,"Replacing existing encoder for encoding %s (%d)\n", - encodingName(encoding), encoding); - createFns[encoding] = createFn; -} - -void Encoder::unregisterEncoder(int encoding) -{ - if (encoding > encodingMax) - throw Exception("Encoder::unregisterEncoder: encoding out of range"); - createFns[encoding] = 0; -} - -int EncoderInit::count = 0; - -EncoderInit::EncoderInit() -{ - if (count++ != 0) return; - - Encoder::registerEncoder(encodingRaw, RawEncoder::create); - Encoder::registerEncoder(encodingRRE, RREEncoder::create); - Encoder::registerEncoder(encodingHextile, HextileEncoder::create); - Encoder::registerEncoder(encodingZRLE, ZRLEEncoder::create); - Encoder::registerEncoder(encodingTight, TightEncoder::create); + switch (encoding) { + case encodingRaw: + return new RawEncoder(writer); + case encodingRRE: + return new RREEncoder(writer); + case encodingHextile: + return new HextileEncoder(writer); + case encodingZRLE: + return new ZRLEEncoder(writer); + case encodingTight: + return new TightEncoder(writer); + default: + return NULL; + } } diff --git a/common/rfb/Encoder.h b/common/rfb/Encoder.h index da2c5c09..26d57963 100644 --- a/common/rfb/Encoder.h +++ b/common/rfb/Encoder.h @@ -1,5 +1,6 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. * Copyright (C) 2011 D. R. Commander. All Rights Reserved. + * Copyright 2014 Pierre Ossman for Cendio AB * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,15 +21,11 @@ #define __RFB_ENCODER_H__ #include <rfb/Rect.h> -#include <rfb/encodings.h> #include <rfb/TransImageGetter.h> -#include <rfb/JpegCompressor.h> namespace rfb { class SMsgWriter; - class Encoder; - class ImageGetter; - typedef Encoder* (*EncoderCreateFnType)(SMsgWriter*); + class TransImageGetter; class Encoder { public: @@ -36,7 +33,7 @@ namespace rfb { virtual void setCompressLevel(int level) {}; virtual void setQualityLevel(int level) {}; - virtual void setFineQualityLevel(int quality, JPEG_SUBSAMP subsampling) {}; + virtual void setFineQualityLevel(int quality, int subsampling) {}; virtual int getNumRects(const Rect &r) { return 1; } // writeRect() tries to write the given rectangle. If it is unable to @@ -47,20 +44,7 @@ namespace rfb { static bool supported(int encoding); static Encoder* createEncoder(int encoding, SMsgWriter* writer); - static void registerEncoder(int encoding, - EncoderCreateFnType createFn); - static void unregisterEncoder(int encoding); - private: - static EncoderCreateFnType createFns[encodingMax+1]; }; - - class EncoderInit { - static int count; - public: - EncoderInit(); - }; - - static EncoderInit encoderInitObj; } #endif diff --git a/common/rfb/HTTPServer.cxx b/common/rfb/HTTPServer.cxx index 94f06090..f50722ab 100644 --- a/common/rfb/HTTPServer.cxx +++ b/common/rfb/HTTPServer.cxx @@ -21,10 +21,6 @@ #include <rfb/util.h> #include <rdr/MemOutStream.h> -#ifdef WIN32 -#define strcasecmp _stricmp -#endif - using namespace rfb; using namespace rdr; diff --git a/common/rfb/HextileDecoder.cxx b/common/rfb/HextileDecoder.cxx index e817c732..ae612676 100644 --- a/common/rfb/HextileDecoder.cxx +++ b/common/rfb/HextileDecoder.cxx @@ -34,11 +34,6 @@ using namespace rfb; #include <rfb/hextileDecode.h> #undef BPP -Decoder* HextileDecoder::create(CMsgReader* reader) -{ - return new HextileDecoder(reader); -} - HextileDecoder::HextileDecoder(CMsgReader* reader_) : reader(reader_) { } diff --git a/common/rfb/HextileDecoder.h b/common/rfb/HextileDecoder.h index e7dd3d58..95a7f8a4 100644 --- a/common/rfb/HextileDecoder.h +++ b/common/rfb/HextileDecoder.h @@ -24,11 +24,10 @@ namespace rfb { class HextileDecoder : public Decoder { public: - static Decoder* create(CMsgReader* reader); - virtual void readRect(const Rect& r, CMsgHandler* handler); + HextileDecoder(CMsgReader* reader); virtual ~HextileDecoder(); + virtual void readRect(const Rect& r, CMsgHandler* handler); private: - HextileDecoder(CMsgReader* reader); CMsgReader* reader; }; } diff --git a/common/rfb/HextileEncoder.cxx b/common/rfb/HextileEncoder.cxx index 73f1f575..0907bab8 100644 --- a/common/rfb/HextileEncoder.cxx +++ b/common/rfb/HextileEncoder.cxx @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ -#include <rfb/ImageGetter.h> +#include <rfb/TransImageGetter.h> #include <rfb/encodings.h> #include <rfb/SMsgWriter.h> #include <rfb/HextileEncoder.h> @@ -45,11 +45,6 @@ BoolParameter improvedHextile("ImprovedHextile", #include <rfb/hextileEncodeBetter.h> #undef BPP -Encoder* HextileEncoder::create(SMsgWriter* writer) -{ - return new HextileEncoder(writer); -} - HextileEncoder::HextileEncoder(SMsgWriter* writer_) : writer(writer_) { } diff --git a/common/rfb/HextileEncoder.h b/common/rfb/HextileEncoder.h index 6b89643d..0c475a8e 100644 --- a/common/rfb/HextileEncoder.h +++ b/common/rfb/HextileEncoder.h @@ -24,11 +24,10 @@ namespace rfb { class HextileEncoder : public Encoder { public: - static Encoder* create(SMsgWriter* writer); - virtual bool writeRect(const Rect& r, TransImageGetter* ig, Rect* actual); + HextileEncoder(SMsgWriter* writer); virtual ~HextileEncoder(); + virtual bool writeRect(const Rect& r, TransImageGetter* ig, Rect* actual); private: - HextileEncoder(SMsgWriter* writer); SMsgWriter* writer; }; } diff --git a/common/rfb/JpegCompressor.cxx b/common/rfb/JpegCompressor.cxx index b3c5f7c4..c19af34e 100644 --- a/common/rfb/JpegCompressor.cxx +++ b/common/rfb/JpegCompressor.cxx @@ -1,5 +1,6 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. * Copyright (C) 2011 D. R. Commander. All Rights Reserved. + * Copyright 2014 Pierre Ossman for Cendio AB * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,7 +22,7 @@ #include <rdr/Exception.h> #include <rfb/Rect.h> #include <rfb/PixelFormat.h> -#include <os/print.h> +#include <rfb/ConnParams.h> #include <stdio.h> extern "C" { @@ -32,6 +33,15 @@ extern "C" { using namespace rfb; // +// Special formats that libjpeg can have optimised code paths for +// + +static const PixelFormat pfRGBX(32, 24, false, true, 255, 255, 255, 0, 8, 16); +static const PixelFormat pfBGRX(32, 24, false, true, 255, 255, 255, 16, 8, 0); +static const PixelFormat pfXRGB(32, 24, false, true, 255, 255, 255, 8, 16, 24); +static const PixelFormat pfXBGR(32, 24, false, true, 255, 255, 255, 24, 16, 8); + +// // Error manager implmentation for the JPEG library // @@ -141,8 +151,8 @@ JpegCompressor::~JpegCompressor(void) delete cinfo; } -void JpegCompressor::compress(const rdr::U8 *buf, int pitch, const Rect& r, - const PixelFormat& pf, int quality, JPEG_SUBSAMP subsamp) +void JpegCompressor::compress(const rdr::U8 *buf, int stride, const Rect& r, + const PixelFormat& pf, int quality, int subsamp) { int w = r.width(); int h = r.height(); @@ -165,62 +175,58 @@ void JpegCompressor::compress(const rdr::U8 *buf, int pitch, const Rect& r, pixelsize = 3; #ifdef JCS_EXTENSIONS - // Try to have libjpeg read directly from our native format - if(pf.is888()) { - int redShift, greenShift, blueShift; - - if(pf.bigEndian) { - redShift = 24 - pf.redShift; - greenShift = 24 - pf.greenShift; - blueShift = 24 - pf.blueShift; - } else { - redShift = pf.redShift; - greenShift = pf.greenShift; - blueShift = pf.blueShift; - } - - if(redShift == 0 && greenShift == 8 && blueShift == 16) - cinfo->in_color_space = JCS_EXT_RGBX; - if(redShift == 16 && greenShift == 8 && blueShift == 0) - cinfo->in_color_space = JCS_EXT_BGRX; - if(redShift == 24 && greenShift == 16 && blueShift == 8) - cinfo->in_color_space = JCS_EXT_XBGR; - if(redShift == 8 && greenShift == 16 && blueShift == 24) - cinfo->in_color_space = JCS_EXT_XRGB; - - if (cinfo->in_color_space != JCS_RGB) { - srcBuf = (rdr::U8 *)buf; - pixelsize = 4; - } + // Try to have libjpeg output directly to our native format + // libjpeg can only handle some "standard" formats + if (pfRGBX.equal(pf)) + cinfo->in_color_space = JCS_EXT_RGBX; + else if (pfBGRX.equal(pf)) + cinfo->in_color_space = JCS_EXT_BGRX; + else if (pfXRGB.equal(pf)) + cinfo->in_color_space = JCS_EXT_XRGB; + else if (pfXBGR.equal(pf)) + cinfo->in_color_space = JCS_EXT_XBGR; + + if (cinfo->in_color_space != JCS_RGB) { + srcBuf = (rdr::U8 *)buf; + pixelsize = 4; } #endif - if (pitch == 0) pitch = w * pf.bpp / 8; + if (stride == 0) + stride = w; if (cinfo->in_color_space == JCS_RGB) { srcBuf = new rdr::U8[w * h * pixelsize]; srcBufIsTemp = true; - pf.rgbFromBuffer(srcBuf, (const rdr::U8 *)buf, w, pitch, h); - pitch = w * pixelsize; + pf.rgbFromBuffer(srcBuf, (const rdr::U8 *)buf, w, stride, h); + stride = w; } cinfo->input_components = pixelsize; jpeg_set_defaults(cinfo); - jpeg_set_quality(cinfo, quality, TRUE); - if(quality >= 96) cinfo->dct_method = JDCT_ISLOW; - else cinfo->dct_method = JDCT_FASTEST; + + if (quality >= 1 && quality <= 100) { + jpeg_set_quality(cinfo, quality, TRUE); + if (quality >= 96) + cinfo->dct_method = JDCT_ISLOW; + else + cinfo->dct_method = JDCT_FASTEST; + } switch (subsamp) { - case SUBSAMP_420: + case subsample16X: + case subsample8X: + // FIXME (fall through) + case subsample4X: cinfo->comp_info[0].h_samp_factor = 2; cinfo->comp_info[0].v_samp_factor = 2; break; - case SUBSAMP_422: + case subsample2X: cinfo->comp_info[0].h_samp_factor = 2; cinfo->comp_info[0].v_samp_factor = 1; break; - case SUBSAMP_GRAY: + case subsampleGray: jpeg_set_colorspace(cinfo, JCS_GRAYSCALE); default: cinfo->comp_info[0].h_samp_factor = 1; @@ -229,7 +235,7 @@ void JpegCompressor::compress(const rdr::U8 *buf, int pitch, const Rect& r, rowPointer = new JSAMPROW[h]; for (int dy = 0; dy < h; dy++) - rowPointer[dy] = (JSAMPROW)(&srcBuf[dy * pitch]); + rowPointer[dy] = (JSAMPROW)(&srcBuf[dy * stride * pixelsize]); jpeg_start_compress(cinfo, TRUE); while (cinfo->next_scanline < cinfo->image_height) diff --git a/common/rfb/JpegCompressor.h b/common/rfb/JpegCompressor.h index d50e5871..8fbb7a9e 100644 --- a/common/rfb/JpegCompressor.h +++ b/common/rfb/JpegCompressor.h @@ -36,14 +36,6 @@ struct JPEG_DEST_MGR; namespace rfb { - enum JPEG_SUBSAMP { - SUBSAMP_UNDEFINED = -1, - SUBSAMP_NONE = 0, - SUBSAMP_420, - SUBSAMP_422, - SUBSAMP_GRAY - }; - class JpegCompressor : public rdr::MemOutStream { public: @@ -51,8 +43,7 @@ namespace rfb { JpegCompressor(int bufferLen = 128*1024); virtual ~JpegCompressor(); - void compress(const rdr::U8 *, int, const Rect&, const PixelFormat&, int, - JPEG_SUBSAMP); + void compress(const rdr::U8 *, int, const Rect&, const PixelFormat&, int, int); void writeBytes(const void*, int); diff --git a/common/rfb/JpegDecompressor.cxx b/common/rfb/JpegDecompressor.cxx index 503c030f..ca1ad226 100644 --- a/common/rfb/JpegDecompressor.cxx +++ b/common/rfb/JpegDecompressor.cxx @@ -1,6 +1,7 @@ /* Copyright (C) 2000-2003 Constantin Kaplinsky. All Rights Reserved. * Copyright (C) 2004-2005 Cendio AB. All rights reserved. * Copyright (C) 2011 D. R. Commander. All Rights Reserved. + * Copyright 2014 Pierre Ossman for Cendio AB * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,7 +23,6 @@ #include <rdr/Exception.h> #include <rfb/Rect.h> #include <rfb/PixelFormat.h> -#include <os/print.h> #include <stdio.h> extern "C" { @@ -33,6 +33,14 @@ extern "C" { using namespace rfb; +// +// Special formats that libjpeg can have optimised code paths for +// + +static const PixelFormat pfRGBX(32, 24, false, true, 255, 255, 255, 0, 8, 16); +static const PixelFormat pfBGRX(32, 24, false, true, 255, 255, 255, 16, 8, 0); +static const PixelFormat pfXRGB(32, 24, false, true, 255, 255, 255, 8, 16, 24); +static const PixelFormat pfXBGR(32, 24, false, true, 255, 255, 255, 24, 16, 8); // // Error manager implmentation for the JPEG library @@ -139,12 +147,12 @@ JpegDecompressor::~JpegDecompressor(void) } void JpegDecompressor::decompress(const rdr::U8 *jpegBuf, int jpegBufLen, - rdr::U8 *buf, int pitch, const Rect& r, const PixelFormat& pf) + rdr::U8 *buf, int stride, const Rect& r, const PixelFormat& pf) { int w = r.width(); int h = r.height(); int pixelsize; - int dstBufPitch; + int dstBufStride; rdr::U8 *dstBuf = NULL; bool dstBufIsTemp = false; JSAMPROW *rowPointer = NULL; @@ -163,50 +171,37 @@ void JpegDecompressor::decompress(const rdr::U8 *jpegBuf, int jpegBufLen, jpeg_read_header(dinfo, TRUE); dinfo->out_color_space = JCS_RGB; pixelsize = 3; - if (pitch == 0) pitch = w * pf.bpp / 8; - dstBufPitch = pitch; + if (stride == 0) + stride = w; + dstBufStride = stride; #ifdef JCS_EXTENSIONS // Try to have libjpeg output directly to our native format - if (pf.is888()) { - int redShift, greenShift, blueShift; - - if(pf.bigEndian) { - redShift = 24 - pf.redShift; - greenShift = 24 - pf.greenShift; - blueShift = 24 - pf.blueShift; - } else { - redShift = pf.redShift; - greenShift = pf.greenShift; - blueShift = pf.blueShift; - } - - // libjpeg can only handle some "standard" formats - if(redShift == 0 && greenShift == 8 && blueShift == 16) - dinfo->out_color_space = JCS_EXT_RGBX; - if(redShift == 16 && greenShift == 8 && blueShift == 0) - dinfo->out_color_space = JCS_EXT_BGRX; - if(redShift == 24 && greenShift == 16 && blueShift == 8) - dinfo->out_color_space = JCS_EXT_XBGR; - if(redShift == 8 && greenShift == 16 && blueShift == 24) - dinfo->out_color_space = JCS_EXT_XRGB; - - if (dinfo->out_color_space != JCS_RGB) { - dstBuf = (rdr::U8 *)buf; - pixelsize = 4; - } + // libjpeg can only handle some "standard" formats + if (pfRGBX.equal(pf)) + dinfo->out_color_space = JCS_EXT_RGBX; + else if (pfBGRX.equal(pf)) + dinfo->out_color_space = JCS_EXT_BGRX; + else if (pfXRGB.equal(pf)) + dinfo->out_color_space = JCS_EXT_XRGB; + else if (pfXBGR.equal(pf)) + dinfo->out_color_space = JCS_EXT_XBGR; + + if (dinfo->out_color_space != JCS_RGB) { + dstBuf = (rdr::U8 *)buf; + pixelsize = 4; } #endif if (dinfo->out_color_space == JCS_RGB) { dstBuf = new rdr::U8[w * h * pixelsize]; dstBufIsTemp = true; - dstBufPitch = w * pixelsize; + dstBufStride = w; } rowPointer = new JSAMPROW[h]; for (int dy = 0; dy < h; dy++) - rowPointer[dy] = (JSAMPROW)(&dstBuf[dy * dstBufPitch]); + rowPointer[dy] = (JSAMPROW)(&dstBuf[dy * dstBufStride * pixelsize]); jpeg_start_decompress(dinfo); @@ -225,7 +220,7 @@ void JpegDecompressor::decompress(const rdr::U8 *jpegBuf, int jpegBufLen, } if (dinfo->out_color_space == JCS_RGB) - pf.bufferFromRGB((rdr::U8*)buf, dstBuf, w, pitch, h); + pf.bufferFromRGB((rdr::U8*)buf, dstBuf, w, stride, h); jpeg_finish_decompress(dinfo); diff --git a/common/rfb/LogWriter.cxx b/common/rfb/LogWriter.cxx index c6461d14..37a9d1ce 100644 --- a/common/rfb/LogWriter.cxx +++ b/common/rfb/LogWriter.cxx @@ -19,9 +19,6 @@ // -=- LogWriter.cxx - client-side logging interface #include <string.h> -#ifdef WIN32 -#define strcasecmp _stricmp -#endif #include <rfb/LogWriter.h> #include <rfb/Configuration.h> diff --git a/common/rfb/Logger.cxx b/common/rfb/Logger.cxx index 451cee25..3daf2486 100644 --- a/common/rfb/Logger.cxx +++ b/common/rfb/Logger.cxx @@ -21,11 +21,7 @@ #include <stdarg.h> #include <stdio.h> #include <string.h> -#ifdef WIN32 -#define strcasecmp _stricmp -#endif -#include <os/print.h> #include <rfb/Logger.h> #include <rfb/LogWriter.h> #include <rfb/util.h> diff --git a/common/rfb/PixelBuffer.cxx b/common/rfb/PixelBuffer.cxx index 60957a25..9d151b97 100644 --- a/common/rfb/PixelBuffer.cxx +++ b/common/rfb/PixelBuffer.cxx @@ -48,7 +48,7 @@ ColourMap* PixelBuffer::getColourMap() const {return colourmap;} void PixelBuffer::getImage(void* imageBuf, const Rect& r, int outStride) { int inStride; - const U8* data = getPixelsR(r, &inStride); + const U8* data = getBuffer(r, &inStride); // We assume that the specified rectangle is pre-clipped to the buffer int bytesPerPixel = format.bpp/8; int inBytesPerRow = inStride * bytesPerPixel; @@ -64,19 +64,6 @@ PixelBuffer::getImage(void* imageBuf, const Rect& r, int outStride) { } } -/* *** -Pixel PixelBuffer::getPixel(const Point& p) { - int stride; - Rect r = Rect(p.x, p.y, p.x+1, p.y+1); - switch(format.bpp) { - case 8: return *((rdr::U8*)getDataAt(r, &stride)); - case 16: return *((rdr::U16*)getDataAt(r, &stride)); - case 32: return *((rdr::U32*)getDataAt(r, &stride)); - default: return 0; - }; -} -*/ - static void fillRect8(U8 *buf, int stride, const Rect& r, Pixel pix) { @@ -167,7 +154,7 @@ void FullFramePixelBuffer::setPF(const PixelFormat &pf) { int FullFramePixelBuffer::getStride() const { return width(); } -rdr::U8* FullFramePixelBuffer::getPixelsRW(const Rect& r, int* stride) +rdr::U8* FullFramePixelBuffer::getBufferRW(const Rect& r, int* stride) { *stride = getStride(); return &data[(r.tl.x + (r.tl.y * *stride)) * format.bpp/8]; @@ -176,14 +163,14 @@ rdr::U8* FullFramePixelBuffer::getPixelsRW(const Rect& r, int* stride) void FullFramePixelBuffer::fillRect(const Rect& r, Pixel pix) { int stride; - U8 *buf = getPixelsRW(r, &stride); + U8 *buf = getBufferRW(r, &stride); fillRectFn(buf, stride, r, pix); } void FullFramePixelBuffer::imageRect(const Rect& r, const void* pixels, int srcStride) { int bytesPerPixel = getPF().bpp/8; int destStride; - U8* dest = getPixelsRW(r, &destStride); + U8* dest = getBufferRW(r, &destStride); int bytesPerDestRow = bytesPerPixel * destStride; if (!srcStride) srcStride = r.width(); int bytesPerSrcRow = bytesPerPixel * srcStride; @@ -201,7 +188,7 @@ void FullFramePixelBuffer::maskRect(const Rect& r, const void* pixels, const voi Rect cr = getRect().intersect(r); if (cr.is_empty()) return; int stride; - U8* data = getPixelsRW(cr, &stride); + U8* data = getBufferRW(cr, &stride); U8* mask = (U8*) mask_; int w = cr.width(); int h = cr.height(); @@ -239,7 +226,7 @@ void FullFramePixelBuffer::maskRect(const Rect& r, Pixel pixel, const void* mask Rect cr = getRect().intersect(r); if (cr.is_empty()) return; int stride; - U8* data = getPixelsRW(cr, &stride); + U8* data = getBufferRW(cr, &stride); U8* mask = (U8*) mask_; int w = cr.width(); int h = cr.height(); @@ -299,7 +286,7 @@ void FullFramePixelBuffer::copyRect(const Rect &rect, const Point &move_by_delta if (srect.is_empty()) return; - data = getPixelsRW(getRect(), &stride); + data = getBufferRW(getRect(), &stride); bytesPerPixel = getPF().bpp/8; bytesPerRow = stride * bytesPerPixel; bytesPerMemCpy = drect.width() * bytesPerPixel; diff --git a/common/rfb/PixelBuffer.h b/common/rfb/PixelBuffer.h index e870622e..5c4f9666 100644 --- a/common/rfb/PixelBuffer.h +++ b/common/rfb/PixelBuffer.h @@ -70,18 +70,14 @@ namespace rfb { // Get a pointer into the buffer // The pointer is to the top-left pixel of the specified Rect. // The buffer stride (in pixels) is returned. - virtual const rdr::U8* getPixelsR(const Rect& r, int* stride) = 0; - virtual rdr::U8* getPixelsRW(const Rect& r, int* stride) = 0; + virtual const rdr::U8* getBuffer(const Rect& r, int* stride) = 0; + virtual rdr::U8* getBufferRW(const Rect& r, int* stride) = 0; // Get pixel data for a given part of the buffer // Data is copied into the supplied buffer, with the specified // stride. virtual void getImage(void* imageBuf, const Rect& r, int stride=0); - // Get the data at (x,y) as a Pixel. - // VERY INEFFICIENT!!! - // *** Pixel getPixel(const Point& p); - /////////////////////////////////////////////// // Framebuffer update methods // @@ -115,10 +111,10 @@ namespace rfb { virtual int getStride() const; // Get a pointer to specified pixel data - rdr::U8* getPixelsRW(const Rect& r, int* stride); - virtual const rdr::U8* getPixelsR(const Rect& r, int* stride) { - return getPixelsRW(r, stride); + virtual const rdr::U8* getBuffer(const Rect& r, int* stride) { + return getBufferRW(r, stride); } + virtual rdr::U8* getBufferRW(const Rect& r, int* stride); /////////////////////////////////////////////// // Basic rendering operations diff --git a/common/rfb/PixelFormat.cxx b/common/rfb/PixelFormat.cxx index a2e94960..b11f8836 100644 --- a/common/rfb/PixelFormat.cxx +++ b/common/rfb/PixelFormat.cxx @@ -1,6 +1,6 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2009 Pierre Ossman for Cendio AB * Copyright (C) 2011 D. R. Commander. All Rights Reserved. + * Copyright 2009-2014 Pierre Ossman for Cendio AB * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,6 +22,7 @@ #include <string.h> #include <rdr/InStream.h> #include <rdr/OutStream.h> +#include <rfb/Exception.h> #include <rfb/PixelFormat.h> #include <rfb/util.h> @@ -37,11 +38,7 @@ PixelFormat::PixelFormat(int b, int d, bool e, bool t, redMax(rm), greenMax(gm), blueMax(bm), redShift(rs), greenShift(gs), blueShift(bs) { - assert((bpp == 8) || (bpp == 16) || (bpp == 32)); - assert(depth <= bpp); - assert((redMax & (redMax + 1)) == 0); - assert((greenMax & (greenMax + 1)) == 0); - assert((blueMax & (blueMax + 1)) == 0); + assert(isSane()); updateState(); } @@ -82,6 +79,9 @@ void PixelFormat::read(rdr::InStream* is) blueShift = is->readU8(); is->skip(3); + if (!isSane()) + throw Exception("invalid pixel format"); + updateState(); } @@ -132,160 +132,58 @@ bool PixelFormat::isLittleEndian(void) const } -Pixel PixelFormat::pixelFromRGB(rdr::U16 red, rdr::U16 green, rdr::U16 blue, - ColourMap* cm) const +void PixelFormat::bufferFromRGB(rdr::U8 *dst, const rdr::U8* src, + int pixels, ColourMap* cm) const { - if (trueColour) { - rdr::U32 r = ((rdr::U32)red * redMax + 32767) / 65535; - rdr::U32 g = ((rdr::U32)green * greenMax + 32767) / 65535; - rdr::U32 b = ((rdr::U32)blue * blueMax + 32767) / 65535; - - return (r << redShift) | (g << greenShift) | (b << blueShift); - } else if (cm) { - // Try to find the closest pixel by Cartesian distance - int colours = 1 << depth; - int diff = 256 * 256 * 4; - int col = 0; - for (int i=0; i<colours; i++) { - int r, g, b; - cm->lookup(i, &r, &g, &b); - int rd = (r-red) >> 8; - int gd = (g-green) >> 8; - int bd = (b-blue) >> 8; - int d = rd*rd + gd*gd + bd*bd; - if (d < diff) { - col = i; - diff = d; - } - } - return col; - } - // XXX just return 0 for colour map? - return 0; + bufferFromRGB(dst, src, pixels, pixels, 1, cm); } - -Pixel PixelFormat::pixelFromRGB(rdr::U8 red, rdr::U8 green, rdr::U8 blue, - ColourMap* cm) const -{ - if (trueColour) { - rdr::U32 r = ((rdr::U32)red * redMax + 127) / 255; - rdr::U32 g = ((rdr::U32)green * greenMax + 127) / 255; - rdr::U32 b = ((rdr::U32)blue * blueMax + 127) / 255; - - return (r << redShift) | (g << greenShift) | (b << blueShift); - } - - return pixelFromRGB((rdr::U16)(red << 8), (rdr::U16)(green << 8), - (rdr::U16)(blue << 8), cm); -} - - void PixelFormat::bufferFromRGB(rdr::U8 *dst, const rdr::U8* src, - int pixels, ColourMap* cm) const + int w, int stride, int h, ColourMap* cm) const { if (is888()) { // Optimised common case - rdr::U8 *r, *g, *b; + rdr::U8 *r, *g, *b, *x; if (bigEndian) { r = dst + (24 - redShift)/8; g = dst + (24 - greenShift)/8; b = dst + (24 - blueShift)/8; + x = dst + (24 - (48 - redShift - greenShift - blueShift))/8; } else { r = dst + redShift/8; g = dst + greenShift/8; b = dst + blueShift/8; + x = dst + (48 - redShift - greenShift - blueShift)/8; } - while (pixels--) { - *r = *(src++); - *g = *(src++); - *b = *(src++); - r += 4; - g += 4; - b += 4; - } - } else { - // Generic code - Pixel p; - rdr::U8 r, g, b; - - while (pixels--) { - r = *(src++); - g = *(src++); - b = *(src++); - - p = pixelFromRGB(r, g, b, cm); - - bufferFromPixel(dst, p); - dst += bpp/8; - } - } -} - -#define trueColorBufferFromRGB(BPP) { \ - rdr::U8 r, g, b; \ - int dstPad = pitch - w * BPP / 8; \ - while (h > 0) { \ - rdr::U8 *dstEndOfRow = (rdr::U8 *)dst + w * BPP / 8; \ - while (dst < dstEndOfRow) { \ - r = *(src++); \ - g = *(src++); \ - b = *(src++); \ - *(rdr::U##BPP *)dst = (((r * redMax + 127) / 255) << redShift) \ - | (((g * greenMax + 127) / 255) << greenShift) \ - | (((b * blueMax + 127) / 255) << blueShift); \ - dst += BPP / 8; \ - } \ - dst += dstPad; \ - h--; \ - } \ -} - -void PixelFormat::bufferFromRGB(rdr::U8 *dst, const rdr::U8* src, - int w, int pitch, int h, ColourMap* cm) const -{ - if (is888()) { - // Optimised common case - int rindex, gindex, bindex; - - if (bigEndian) { - rindex = (24 - redShift)/8; - gindex = (24 - greenShift)/8; - bindex = (24 - blueShift)/8; - } else { - rindex = redShift/8; - gindex = greenShift/8; - bindex = blueShift/8; - } - - int dstPad = pitch - w * 4; - while (h > 0) { - rdr::U8 *dstEndOfRow = (rdr::U8 *)dst + w * 4; - while (dst < dstEndOfRow) { - dst[rindex] = *(src++); - dst[gindex] = *(src++); - dst[bindex] = *(src++); - dst += 4; + int dstPad = (stride - w) * 4; + while (h--) { + int w_ = w; + while (w_--) { + *r = *(src++); + *g = *(src++); + *b = *(src++); + *x = 0; + r += 4; + g += 4; + b += 4; + x += 4; } - dst += dstPad; - h--; + r += dstPad; + g += dstPad; + b += dstPad; + x += dstPad; } - } else if (!cm && bpp == 16) { - trueColorBufferFromRGB(16); - } else if (!cm && bpp == 8) { - trueColorBufferFromRGB(8); } else { // Generic code - Pixel p; - rdr::U8 r, g, b; - int pixelSize = bpp/8; - - int dstPad = pitch - w * pixelSize; - while (h > 0) { - rdr::U8 *dstEndOfRow = (rdr::U8 *)dst + w * pixelSize; - while (dst < dstEndOfRow) { + int dstPad = (stride - w) * 4; + while (h--) { + int w_ = w; + while (w_--) { + Pixel p; + rdr::U8 r, g, b; + r = *(src++); g = *(src++); b = *(src++); @@ -293,10 +191,9 @@ void PixelFormat::bufferFromRGB(rdr::U8 *dst, const rdr::U8* src, p = pixelFromRGB(r, g, b, cm); bufferFromPixel(dst, p); - dst += pixelSize; + dst += bpp/8; } dst += dstPad; - h--; } } } @@ -314,24 +211,14 @@ void PixelFormat::rgbFromPixel(Pixel p, ColourMap* cm, Colour* rgb) const } -void PixelFormat::rgbFromBuffer(rdr::U16* dst, const rdr::U8* src, int pixels, ColourMap* cm) const +void PixelFormat::rgbFromBuffer(rdr::U8* dst, const rdr::U8* src, int pixels, ColourMap* cm) const { - Pixel p; - rdr::U16 r, g, b; - - while (pixels--) { - p = pixelFromBuffer(src); - src += bpp/8; - - rgbFromPixel(p, cm, &r, &g, &b); - *(dst++) = r; - *(dst++) = g; - *(dst++) = b; - } + rgbFromBuffer(dst, src, pixels, pixels, 1, cm); } -void PixelFormat::rgbFromBuffer(rdr::U8* dst, const rdr::U8* src, int pixels, ColourMap* cm) const +void PixelFormat::rgbFromBuffer(rdr::U8* dst, const rdr::U8* src, + int w, int stride, int h, ColourMap* cm) const { if (is888()) { // Optimised common case @@ -347,81 +234,40 @@ void PixelFormat::rgbFromBuffer(rdr::U8* dst, const rdr::U8* src, int pixels, Co b = src + blueShift/8; } - while (pixels--) { - *(dst++) = *r; - *(dst++) = *g; - *(dst++) = *b; - r += 4; - g += 4; - b += 4; - } - } else { - // Generic code - Pixel p; - rdr::U8 r, g, b; - - while (pixels--) { - p = pixelFromBuffer(src); - src += bpp/8; - - rgbFromPixel(p, cm, &r, &g, &b); - *(dst++) = r; - *(dst++) = g; - *(dst++) = b; - } - } -} - - -void PixelFormat::rgbFromBuffer(rdr::U8* dst, const rdr::U8* src, - int w, int pitch, int h, ColourMap* cm) const -{ - if (is888()) { - // Optimised common case - int rindex, gindex, bindex; - - if (bigEndian) { - rindex = (24 - redShift)/8; - gindex = (24 - greenShift)/8; - bindex = (24 - blueShift)/8; - } else { - rindex = redShift/8; - gindex = greenShift/8; - bindex = blueShift/8; - } - - int srcPad = pitch - w * 4; - while (h > 0) { - rdr::U8 *srcEndOfRow = (rdr::U8 *)src + w * 4; - while (src < srcEndOfRow) { - *(dst++) = src[rindex]; - *(dst++) = src[gindex]; - *(dst++) = src[bindex]; - src += 4; + int srcPad = (stride - w) * 4; + while (h--) { + int w_ = w; + while (w_--) { + *(dst++) = *r; + *(dst++) = *g; + *(dst++) = *b; + r += 4; + g += 4; + b += 4; } - src += srcPad; - h--; + r += srcPad; + g += srcPad; + b += srcPad; } } else { // Generic code - Pixel p; - rdr::U8 r, g, b; - int pixelSize = bpp/8; - - int srcPad = pitch - w * pixelSize; - while (h > 0) { - rdr::U8 *srcEndOfRow = (rdr::U8 *)src + w * pixelSize; - while (src < srcEndOfRow) { + int srcPad = (stride - w) * bpp/8; + while (h--) { + int w_ = w; + while (w_--) { + Pixel p; + rdr::U8 r, g, b; + p = pixelFromBuffer(src); rgbFromPixel(p, cm, &r, &g, &b); + *(dst++) = r; *(dst++) = g; *(dst++) = b; - src += pixelSize; + src += bpp/8; } src += srcPad; - h--; } } } @@ -531,6 +377,8 @@ bool PixelFormat::parse(const char* str) return false; } + assert(isSane()); + updateState(); return true; @@ -565,19 +413,72 @@ static int bits(rdr::U16 value) void PixelFormat::updateState(void) { - int redBits, greenBits, blueBits; int endianTest = 1; redBits = bits(redMax); greenBits = bits(greenMax); blueBits = bits(blueMax); - redConvShift = 16 - redBits; - greenConvShift = 16 - greenBits; - blueConvShift = 16 - blueBits; + maxBits = redBits; + if (greenBits > maxBits) + maxBits = greenBits; + if (blueBits > maxBits) + maxBits = blueBits; + + minBits = redBits; + if (greenBits < minBits) + minBits = greenBits; + if (blueBits < minBits) + minBits = blueBits; if (((*(char*)&endianTest) == 0) != bigEndian) endianMismatch = true; else endianMismatch = false; } + +bool PixelFormat::isSane(void) +{ + int totalBits; + + if ((bpp != 8) && (bpp != 16) && (bpp != 32)) + return false; + if (depth > bpp) + return false; + + if (!trueColour && (depth != 8)) + return false; + + if (trueColour) { + if ((redMax & (redMax + 1)) != 0) + return false; + if ((greenMax & (greenMax + 1)) != 0) + return false; + if ((blueMax & (blueMax + 1)) != 0) + return false; + + /* + * We don't allow individual channels > 8 bits in order to keep our + * conversions simple. + */ + if (redMax >= (1 << 8)) + return false; + if (greenMax >= (1 << 8)) + return false; + if (blueMax >= (1 << 8)) + return false; + + totalBits = bits(redMax) + bits(greenMax) + bits(blueMax); + if (totalBits > bpp) + return false; + + if (((redMax << redShift) & (greenMax << greenShift)) != 0) + return false; + if (((redMax << redShift) & (blueMax << blueShift)) != 0) + return false; + if (((greenMax << greenShift) & (blueMax << blueShift)) != 0) + return false; + } + + return true; +} diff --git a/common/rfb/PixelFormat.h b/common/rfb/PixelFormat.h index 88e80f4c..a8408ddd 100644 --- a/common/rfb/PixelFormat.h +++ b/common/rfb/PixelFormat.h @@ -1,5 +1,6 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. * Copyright (C) 2011 D. R. Commander. All Rights Reserved. + * Copyright 2009-2014 Pierre Ossman for Cendio AB * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,7 +19,16 @@ */ // // PixelFormat - structure to represent a pixel format. Also has useful -// methods for reading & writing to streams, etc. +// methods for reading & writing to streams, etc. Conversion to and from +// other formats are also handled by this class. We have three different +// representations that we refer to: +// +// a) Pixels - Unsigned native integers in the format specified by this +// PixelFormat object. +// b) Buffer - Same thing as pixels, but in the appropriate byte stream +// format. This involves endian conversion and padding. +// c) RGB - A byte stream of 8 bit red, green and blue elements, in that +// order. // #ifndef __RFB_PIXELFORMAT_H__ @@ -49,20 +59,19 @@ namespace rfb { inline Pixel pixelFromBuffer(const rdr::U8* buffer) const; inline void bufferFromPixel(rdr::U8* buffer, Pixel pixel) const; - Pixel pixelFromRGB(rdr::U16 red, rdr::U16 green, rdr::U16 blue, ColourMap* cm=0) const; - Pixel pixelFromRGB(rdr::U8 red, rdr::U8 green, rdr::U8 blue, ColourMap* cm=0) const; + inline Pixel pixelFromRGB(rdr::U16 red, rdr::U16 green, rdr::U16 blue, ColourMap* cm=0) const; + inline Pixel pixelFromRGB(rdr::U8 red, rdr::U8 green, rdr::U8 blue, ColourMap* cm=0) const; void bufferFromRGB(rdr::U8 *dst, const rdr::U8* src, int pixels, ColourMap* cm=0) const; - void bufferFromRGB(rdr::U8 *dst, const rdr::U8* src, int w, int pitch, + void bufferFromRGB(rdr::U8 *dst, const rdr::U8* src, int w, int stride, int h, ColourMap* cm=0) const; void rgbFromPixel(Pixel pix, ColourMap* cm, Colour* rgb) const; inline void rgbFromPixel(Pixel pix, ColourMap* cm, rdr::U16 *r, rdr::U16 *g, rdr::U16 *b) const; inline void rgbFromPixel(Pixel pix, ColourMap* cm, rdr::U8 *r, rdr::U8 *g, rdr::U8 *b) const; - void rgbFromBuffer(rdr::U16* dst, const rdr::U8* src, int pixels, ColourMap* cm=0) const; void rgbFromBuffer(rdr::U8* dst, const rdr::U8* src, int pixels, ColourMap* cm=0) const; - void rgbFromBuffer(rdr::U8* dst, const rdr::U8* src, int w, int pitch, + void rgbFromBuffer(rdr::U8* dst, const rdr::U8* src, int w, int stride, int h, ColourMap* cm=0) const; void print(char* str, int len) const; @@ -70,6 +79,7 @@ namespace rfb { protected: void updateState(void); + bool isSane(void); public: int bpp; @@ -87,9 +97,9 @@ namespace rfb { int blueShift; protected: - int redConvShift; - int greenConvShift; - int blueConvShift; + /* Pre-computed values to keep algorithms simple */ + int redBits, greenBits, blueBits; + int maxBits, minBits; bool endianMismatch; }; } diff --git a/common/rfb/PixelFormat.inl b/common/rfb/PixelFormat.inl index 90d8e6da..547fae5d 100644 --- a/common/rfb/PixelFormat.inl +++ b/common/rfb/PixelFormat.inl @@ -1,4 +1,4 @@ -/* Copyright 2009 Pierre Ossman for Cendio AB +/* Copyright 2009-2014 Pierre Ossman for Cendio AB * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -75,13 +75,83 @@ inline void PixelFormat::bufferFromPixel(rdr::U8* buffer, Pixel p) const } -inline void PixelFormat::rgbFromPixel(Pixel p, ColourMap* cm, rdr::U16 *r, rdr::U16 *g, rdr::U16 *b) const +inline Pixel PixelFormat::pixelFromRGB(rdr::U16 red, rdr::U16 green, rdr::U16 blue, ColourMap* cm) const { if (trueColour) { + Pixel p; + /* We don't need to mask since we shift out unwanted bits */ - *r = (p >> redShift) << redConvShift; - *g = (p >> greenShift) << greenConvShift; - *b = (p >> blueShift) << blueConvShift; + p = ((Pixel)red >> (16 - redBits)) << redShift; + p |= ((Pixel)green >> (16 - greenBits)) << greenShift; + p |= ((Pixel)blue >> (16 - blueBits)) << blueShift; + } else if (cm) { + // Try to find the closest pixel by Cartesian distance + int colours = 1 << depth; + int diff = 256 * 256 * 4; + int col = 0; + for (int i=0; i<colours; i++) { + int r, g, b; + cm->lookup(i, &r, &g, &b); + int rd = (r-red) >> 8; + int gd = (g-green) >> 8; + int bd = (b-blue) >> 8; + int d = rd*rd + gd*gd + bd*bd; + if (d < diff) { + col = i; + diff = d; + } + } + return col; + } else { + // XXX just return 0 for colour map? + return 0; + } +} + + +inline Pixel PixelFormat::pixelFromRGB(rdr::U8 red, rdr::U8 green, rdr::U8 blue, ColourMap* cm) const +{ + if (trueColour) { + Pixel p; + + p = ((Pixel)red >> (8 - redBits)) << redShift; + p |= ((Pixel)green >> (8 - greenBits)) << greenShift; + p |= ((Pixel)blue >> (8 - blueBits)) << blueShift; + + return p; + } else { + return pixelFromRGB((rdr::U16)(red << 8 | red), + (rdr::U16)(green << 8 | green), + (rdr::U16)(blue << 8 | blue), cm); + } +} + + +inline void PixelFormat::rgbFromPixel(Pixel p, ColourMap* cm, rdr::U16 *r, rdr::U16 *g, rdr::U16 *b) const +{ + if (trueColour) { + int mb, rb, gb, bb; + + /* Bit replication is much cheaper than multiplication and division */ + + mb = minBits; + rb = redBits; + gb = greenBits; + bb = blueBits; + + *r = (p >> redShift) << (16 - rb); + *g = (p >> greenShift) << (16 - gb); + *b = (p >> blueShift) << (16 - bb); + + while (mb < 16) { + *r = *r | (*r >> rb); + *g = *g | (*g >> gb); + *b = *b | (*b >> bb); + mb <<= 1; + rb <<= 1; + gb <<= 1; + bb <<= 1; + } } else if (cm) { int ir, ig, ib; cm->lookup(p, &ir, &ig, &ib); @@ -100,9 +170,28 @@ inline void PixelFormat::rgbFromPixel(Pixel p, ColourMap* cm, rdr::U16 *r, rdr:: inline void PixelFormat::rgbFromPixel(Pixel p, ColourMap* cm, rdr::U8 *r, rdr::U8 *g, rdr::U8 *b) const { if (trueColour) { - *r = (p >> redShift) << (redConvShift - 8); - *g = (p >> greenShift) << (greenConvShift - 8); - *b = (p >> blueShift) << (blueConvShift - 8); + int mb, rb, gb, bb; + + /* Bit replication is much cheaper than multiplication and division */ + + mb = minBits; + rb = redBits; + gb = greenBits; + bb = blueBits; + + *r = (p >> redShift) << (8 - rb); + *g = (p >> greenShift) << (8 - gb); + *b = (p >> blueShift) << (8 - bb); + + while (mb < 8) { + *r = *r | (*r >> rb); + *g = *g | (*g >> gb); + *b = *b | (*b >> bb); + mb <<= 1; + rb <<= 1; + gb <<= 1; + bb <<= 1; + } } else { rdr::U16 r2, g2, b2; diff --git a/common/rfb/RREDecoder.cxx b/common/rfb/RREDecoder.cxx index da56ee7c..b81a4a82 100644 --- a/common/rfb/RREDecoder.cxx +++ b/common/rfb/RREDecoder.cxx @@ -34,11 +34,6 @@ using namespace rfb; #include <rfb/rreDecode.h> #undef BPP -Decoder* RREDecoder::create(CMsgReader* reader) -{ - return new RREDecoder(reader); -} - RREDecoder::RREDecoder(CMsgReader* reader_) : reader(reader_) { } diff --git a/common/rfb/RREDecoder.h b/common/rfb/RREDecoder.h index 2309f754..98abf982 100644 --- a/common/rfb/RREDecoder.h +++ b/common/rfb/RREDecoder.h @@ -24,11 +24,10 @@ namespace rfb { class RREDecoder : public Decoder { public: - static Decoder* create(CMsgReader* reader); - virtual void readRect(const Rect& r, CMsgHandler* handler); + RREDecoder(CMsgReader* reader); virtual ~RREDecoder(); + virtual void readRect(const Rect& r, CMsgHandler* handler); private: - RREDecoder(CMsgReader* reader); CMsgReader* reader; }; } diff --git a/common/rfb/RREEncoder.cxx b/common/rfb/RREEncoder.cxx index 1b86986f..36d46955 100644 --- a/common/rfb/RREEncoder.cxx +++ b/common/rfb/RREEncoder.cxx @@ -16,7 +16,7 @@ * USA. */ #include <rdr/OutStream.h> -#include <rfb/ImageGetter.h> +#include <rfb/TransImageGetter.h> #include <rfb/encodings.h> #include <rfb/SMsgWriter.h> #include <rfb/RREEncoder.h> @@ -33,11 +33,6 @@ using namespace rfb; #include <rfb/rreEncode.h> #undef BPP -Encoder* RREEncoder::create(SMsgWriter* writer) -{ - return new RREEncoder(writer); -} - RREEncoder::RREEncoder(SMsgWriter* writer_) : writer(writer_) { } diff --git a/common/rfb/RREEncoder.h b/common/rfb/RREEncoder.h index 6178d57f..f7d576eb 100644 --- a/common/rfb/RREEncoder.h +++ b/common/rfb/RREEncoder.h @@ -25,11 +25,10 @@ namespace rfb { class RREEncoder : public Encoder { public: - static Encoder* create(SMsgWriter* writer); - virtual bool writeRect(const Rect& r, TransImageGetter* ig, Rect* actual); + RREEncoder(SMsgWriter* writer); virtual ~RREEncoder(); + virtual bool writeRect(const Rect& r, TransImageGetter* ig, Rect* actual); private: - RREEncoder(SMsgWriter* writer); SMsgWriter* writer; rdr::MemOutStream mos; }; diff --git a/common/rfb/RawDecoder.cxx b/common/rfb/RawDecoder.cxx index 57cb37bc..5fd3b7c1 100644 --- a/common/rfb/RawDecoder.cxx +++ b/common/rfb/RawDecoder.cxx @@ -22,11 +22,6 @@ using namespace rfb; -Decoder* RawDecoder::create(CMsgReader* reader) -{ - return new RawDecoder(reader); -} - RawDecoder::RawDecoder(CMsgReader* reader_) : reader(reader_) { } diff --git a/common/rfb/RawDecoder.h b/common/rfb/RawDecoder.h index 9fdbb220..e09cca2d 100644 --- a/common/rfb/RawDecoder.h +++ b/common/rfb/RawDecoder.h @@ -24,11 +24,10 @@ namespace rfb { class RawDecoder : public Decoder { public: - static Decoder* create(CMsgReader* reader); - virtual void readRect(const Rect& r, CMsgHandler* handler); + RawDecoder(CMsgReader* reader); virtual ~RawDecoder(); + virtual void readRect(const Rect& r, CMsgHandler* handler); private: - RawDecoder(CMsgReader* reader); CMsgReader* reader; }; } diff --git a/common/rfb/RawEncoder.cxx b/common/rfb/RawEncoder.cxx index 5612cb8d..4b8de6ba 100644 --- a/common/rfb/RawEncoder.cxx +++ b/common/rfb/RawEncoder.cxx @@ -16,18 +16,13 @@ * USA. */ #include <rdr/OutStream.h> -#include <rfb/ImageGetter.h> +#include <rfb/TransImageGetter.h> #include <rfb/encodings.h> #include <rfb/SMsgWriter.h> #include <rfb/RawEncoder.h> using namespace rfb; -Encoder* RawEncoder::create(SMsgWriter* writer) -{ - return new RawEncoder(writer); -} - RawEncoder::RawEncoder(SMsgWriter* writer_) : writer(writer_) { } diff --git a/common/rfb/RawEncoder.h b/common/rfb/RawEncoder.h index 34dba0b5..22d45dbf 100644 --- a/common/rfb/RawEncoder.h +++ b/common/rfb/RawEncoder.h @@ -24,11 +24,10 @@ namespace rfb { class RawEncoder : public Encoder { public: - static Encoder* create(SMsgWriter* writer); - virtual bool writeRect(const Rect& r, TransImageGetter* ig, Rect* actual); + RawEncoder(SMsgWriter* writer); virtual ~RawEncoder(); + virtual bool writeRect(const Rect& r, TransImageGetter* ig, Rect* actual); private: - RawEncoder(SMsgWriter* writer); SMsgWriter* writer; }; } diff --git a/common/rfb/SMsgWriter.cxx b/common/rfb/SMsgWriter.cxx index f47f3eeb..509ffbf5 100644 --- a/common/rfb/SMsgWriter.cxx +++ b/common/rfb/SMsgWriter.cxx @@ -122,18 +122,6 @@ bool SMsgWriter::needFakeUpdate() return false; } -// FIXME: This functions is not used because it incorrectly computes -// the number of rectangles if the Tight encoder is used. -/* -void SMsgWriter::writeFramebufferUpdate(const UpdateInfo& ui, ImageGetter* ig, - Region* updatedRegion) -{ - writeFramebufferUpdateStart(ui.numRects()); - writeRects(ui, ig, updatedRegion); - writeFramebufferUpdateEnd(); -} -*/ - bool SMsgWriter::needNoDataUpdate() { return false; diff --git a/common/rfb/SMsgWriter.h b/common/rfb/SMsgWriter.h index 3933b38c..edf29447 100644 --- a/common/rfb/SMsgWriter.h +++ b/common/rfb/SMsgWriter.h @@ -109,18 +109,6 @@ namespace rfb { // order to flush out pseudo-rectangles to the client. virtual bool needFakeUpdate(); - // writeFramebufferUpdate() writes a framebuffer update using the given - // UpdateInfo and ImageGetter. On a V3 writer this may have - // pseudo-rectangles for setDesktopSize and setCursor added to it, and so - // may invoke writeSetCursorCallback(). - // - // FIXME: This function is not used because it incorrectly computes - // the number of rectangles if the Tight encoder is used. - /* - virtual void writeFramebufferUpdate(const UpdateInfo& ui, ImageGetter* ig, - Region* updatedRegion); - */ - // needNoDataUpdate() returns true when an update without any // framebuffer changes need to be sent (using writeNoDataUpdate()). // Commonly this is an update that modifies the size of the framebuffer diff --git a/common/rfb/ScaleFilters.cxx b/common/rfb/ScaleFilters.cxx index 07f3db85..3e414d90 100644 --- a/common/rfb/ScaleFilters.cxx +++ b/common/rfb/ScaleFilters.cxx @@ -23,10 +23,6 @@ #include <rfb/Rect.h> #include <rfb/ScaleFilters.h> -#ifdef _WIN32 -#define strcasecmp _stricmp -#endif - using namespace rfb; // diff --git a/common/rfb/ScaledPixelBuffer.cxx b/common/rfb/ScaledPixelBuffer.cxx deleted file mode 100644 index dc6096d7..00000000 --- a/common/rfb/ScaledPixelBuffer.cxx +++ /dev/null @@ -1,225 +0,0 @@ -/* Copyright (C) 2005 TightVNC Team. 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. - */ - -// -=- ScaledPixelBuffer.cxx - -#include <rfb/Exception.h> -#include <rfb/ScaledPixelBuffer.h> - -#include <math.h> -#include <memory.h> -#include <stdlib.h> - -using namespace rdr; -using namespace rfb; - -ScaledPixelBuffer::ScaledPixelBuffer(U8 **src_data_, int src_width_, - int src_height_, int scale_, PixelFormat pf_) - : scale(scale_), scale_ratio_x(1), scale_ratio_y(1), scaleFilterID(scaleFilterBilinear), - xWeightTabs(0), yWeightTabs(0), raccum(0), gaccum(0), baccum(0), scaled_data(0) { - - setSourceBuffer(src_data_, src_width_, src_height_); - setPF(pf_); -} - -ScaledPixelBuffer::ScaledPixelBuffer() - : src_width(0), src_height(0), scaled_width(0), scaled_height(0), scale(100), - scale_ratio_x(1), scale_ratio_y(1), scaleFilterID(scaleFilterBilinear), - xWeightTabs(0), yWeightTabs(0), raccum(0), gaccum(0), baccum(0), - src_data(0), scaled_data(0) { - memset(&pf, 0, sizeof(pf)); -} - -ScaledPixelBuffer::~ScaledPixelBuffer() { - freeWeightTabs(); - if (raccum) delete [] raccum; - if (gaccum) delete [] gaccum; - if (baccum) delete [] baccum; -} - -void ScaledPixelBuffer::freeWeightTabs() { - if (xWeightTabs) { - for (int i = 0; i < scaled_width; i++) delete [] xWeightTabs[i].weight; - delete [] xWeightTabs; - xWeightTabs = 0; - } - if (yWeightTabs) { - for (int i = 0; i < scaled_height; i++) delete [] yWeightTabs[i].weight; - delete [] yWeightTabs; - yWeightTabs = 0; - } -} - -void ScaledPixelBuffer::recreateRowAccum() { - if (raccum) delete [] raccum; - if (gaccum) delete [] gaccum; - if (baccum) delete [] baccum; - raccum = new int[src_width]; - gaccum = new int[src_width]; - baccum = new int[src_width]; -} - -void ScaledPixelBuffer::setSourceBuffer(U8 **src_data_, int w, int h) { - if (w > 0 && h > 0 && src_data_ != NULL) { - freeWeightTabs(); - src_data = src_data_; - src_width = w; - src_height = h; - recreateRowAccum(); - calculateScaledBufferSize(); - scaleFilters.makeWeightTabs(scaleFilterID, src_width, scaled_width, &xWeightTabs); - scaleFilters.makeWeightTabs(scaleFilterID, src_height, scaled_height, &yWeightTabs); - } -} - -void ScaledPixelBuffer::setPF(const PixelFormat &pf_) { - ///if (pf_.depth != 24) throw rfb::UnsupportedPixelFormatException(); - pf = pf_; -} - -void ScaledPixelBuffer::setScale(int scale_) { - if (scale != scale_ && scale_ > 0) { - scale = scale_; - freeWeightTabs(); - calculateScaledBufferSize(); - scaleFilters.makeWeightTabs(scaleFilterID, src_width, scaled_width, &xWeightTabs); - scaleFilters.makeWeightTabs(scaleFilterID, src_height, scaled_height, &yWeightTabs); - } -} - -void ScaledPixelBuffer::setScaleFilter(unsigned int scaleFilterID_) { - if (scaleFilterID == scaleFilterID_ || scaleFilterID_ > scaleFilterMaxNumber) return; - - scaleFilterID = scaleFilterID_; - - if (src_width && src_height && scaled_width && scaled_height) { - freeWeightTabs(); - scaleFilters.makeWeightTabs(scaleFilterID, src_width, scaled_width, &xWeightTabs); - scaleFilters.makeWeightTabs(scaleFilterID, src_height, scaled_height, &yWeightTabs); - if (scale != 100 && pf.depth > 0 && scaled_data) scaleRect(Rect(0, 0, src_width, src_height)); - } -} - -inline U32 ScaledPixelBuffer::getSourcePixel(int x, int y) { - int bytes_per_pixel = pf.bpp / 8; - U8 *ptr = &(*src_data)[(x + y*src_width)*bytes_per_pixel]; - if (bytes_per_pixel == 1) { - return *ptr; - } else if (bytes_per_pixel == 2) { - int b0 = *ptr++; int b1 = *ptr; - return b1 << 8 | b0; - } else if (bytes_per_pixel == 4) { - int b0 = *ptr++; int b1 = *ptr++; - int b2 = *ptr++; int b3 = *ptr; - return b3 << 24 | b2 << 16 | b1 << 8 | b0; - } else { - return 0; - } -} - -void ScaledPixelBuffer::scaleRect(const Rect& rect) { - Rect changed_rect; - U8 *ptr, *ptrs, *px, *pxs; - U16 r, g, b; - int red, green, blue; - short *xweight, *yweight, weight; - - // Calculate the changed pixel rect in the scaled image - changed_rect = calculateScaleBoundary(rect); - - int bytesPerSrcPixel = pf.bpp / 8; - int bytesPerSrcRow = src_width * bytesPerSrcPixel; - int bytesPerScaledRow = scaled_width * 4; - - int bytesPerAccumRow = src_width * sizeof(int); - - ptrs = &(*scaled_data)[(changed_rect.tl.x + changed_rect.tl.y*scaled_width) * 4]; - for (int y = changed_rect.tl.y; y < changed_rect.br.y; y++) { - ptr = ptrs; - yweight = yWeightTabs[y].weight; - - // Clear the color accumulators - memset(raccum, 0, bytesPerAccumRow); - memset(gaccum, 0, bytesPerAccumRow); - memset(baccum, 0, bytesPerAccumRow); - - // Make the convolution the source image with scale filter weights - // by y axis and save results to the color accumulators. - pxs = &(*src_data)[(xWeightTabs[changed_rect.tl.x].i0 + yWeightTabs[y].i0*src_width) * bytesPerSrcPixel]; - for (int ys = yWeightTabs[y].i0; ys < yWeightTabs[y].i1; ys++) { - px = pxs; - for (int xs = xWeightTabs[changed_rect.tl.x].i0; xs < xWeightTabs[changed_rect.br.x-1].i1; xs++) { - pf.rgbFromPixel(*((U32*)px), NULL, &r, &g, &b); - weight = *yweight; - raccum[xs] += (int)(weight) * r; - gaccum[xs] += (int)(weight) * g; - baccum[xs] += (int)(weight) * b; - px += bytesPerSrcPixel; - } - yweight++; - pxs += bytesPerSrcRow; - } - - // Make the convolution the color accumulators with scale filter weights - // by x axis and save results to the scaled image. - for (int x = changed_rect.tl.x; x < changed_rect.br.x; x++) { - // Init the sum of colors with (1 << (shift-1)) for rounding. - red = green = blue = 1 << (FINALSHIFT-1); - xweight = xWeightTabs[x].weight; - for (int xs = xWeightTabs[x].i0; xs < xWeightTabs[x].i1; xs++) { - weight = *xweight; - red += (int)(weight) * (raccum[xs] >> BITS_OF_CHANEL); - green += (int)(weight) * (gaccum[xs] >> BITS_OF_CHANEL); - blue += (int)(weight) * (baccum[xs] >> BITS_OF_CHANEL); - xweight++; - } - *ptr++ = U8(blue >> FINALSHIFT); - *ptr++ = U8(green >> FINALSHIFT); - *ptr++ = U8(red >> FINALSHIFT); - ptr++; - } - ptrs += bytesPerScaledRow; - } -} - -Rect ScaledPixelBuffer::calculateScaleBoundary(const Rect& r) { - int x_start, y_start, x_end, y_end; - double translate_x = 0.5*scale_ratio_x - 0.5; - double translate_y = 0.5*scale_ratio_y - 0.5; - double sourceXScale = __rfbmax(1.0, 1.0/scale_ratio_x); - double sourceYScale = __rfbmax(1.0, 1.0/scale_ratio_y); - double sourceXRadius = __rfbmax(0.5, sourceXScale*scaleFilters[scaleFilterID].radius); - double sourceYRadius = __rfbmax(0.5, sourceYScale*scaleFilters[scaleFilterID].radius); - x_start = (int)ceil(scale_ratio_x*(r.tl.x-sourceXRadius) + translate_x + SCALE_ERROR); - y_start = (int)ceil(scale_ratio_y*(r.tl.y-sourceYRadius) + translate_y + SCALE_ERROR); - x_end = (int)floor(scale_ratio_x*((r.br.x-1)+sourceXRadius) + translate_x - SCALE_ERROR) + 1; - y_end = (int)floor(scale_ratio_y*((r.br.y-1)+sourceXRadius) + translate_y - SCALE_ERROR) + 1; - if (x_start < 0) x_start = 0; - if (y_start < 0) y_start = 0; - if (x_end > scaled_width) x_end = scaled_width; - if (y_end > scaled_height) y_end = scaled_height; - return Rect(x_start, y_start, x_end, y_end); -} - -void ScaledPixelBuffer::calculateScaledBufferSize() { - double scale_ratio = (double)scale / 100; - scaled_width = (int)ceil(src_width * scale_ratio); - scaled_height = (int)ceil(src_height * scale_ratio); - scale_ratio_x = (double)scaled_width / src_width; - scale_ratio_y = (double)scaled_height / src_height; -} diff --git a/common/rfb/ScaledPixelBuffer.h b/common/rfb/ScaledPixelBuffer.h deleted file mode 100644 index 453ab78c..00000000 --- a/common/rfb/ScaledPixelBuffer.h +++ /dev/null @@ -1,128 +0,0 @@ -/* Copyright (C) 2005 TightVNC Team. 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. - */ - -// -=- ScaledPixelBuffer.h -// -// The ScaledPixelBuffer class allows to scale the image data -// from the source buffer to destination buffer using bilinear -// interpolation. - -#ifndef __RFB_SCALEDPIXELBUFFER_H__ -#define __RFB_SCALEDPIXELBUFFER_H__ - -#include <rdr/types.h> -#include <rdr/Exception.h> -#include <rfb/Rect.h> -#include <rfb/PixelFormat.h> -#include <rfb/ScaleFilters.h> - -using namespace rdr; - -namespace rfb { - - struct UnsupportedPixelFormatException : public Exception { - UnsupportedPixelFormatException(const char* s="Now supported only true colour pixel data in the scaling mode.") - : Exception(s) {} - }; - - class ScaledPixelBuffer { - public: - ScaledPixelBuffer(U8 **data, int width, int height, int scale, PixelFormat pf); - ScaledPixelBuffer(); - virtual ~ScaledPixelBuffer(); - - // Get width, height, number of pixels and scale - int width() const { return scaled_width; } - int height() const { return scaled_height; } - int getSrcWidth() const { return src_width; } - int getSrcHeight() const { return src_height; } - int area() const { return scaled_width * scaled_height; } - int getScale() const { return scale; } - double getScaleRatioX() const { return scale_ratio_x; } - double getScaleRatioY() const { return scale_ratio_y; } - - // Pixel manipulation routines - inline U32 getSourcePixel(int x, int y); - - // Get rectangle encompassing this buffer - // Top-left of rectangle is either at (0,0), or the specified point. - Rect getRect() const { return Rect(0, 0, scaled_width, scaled_height); } - Rect getRect(const Point& pos) const { - return Rect(pos, pos.translate(Point(scaled_width, scaled_height))); - } - - // Set the new source buffer and its parameters - void setSourceBuffer(U8 **src_data, int w, int h); - - void setScaledBuffer(U8 **scaled_data_) { - scaled_data = scaled_data_; - }; - - // Set the new pixel format - void setPF(const PixelFormat &pf); - - // Set the new scale, in percent - virtual void setScale(int scale); - - // Set/get the scale method - virtual void setScaleFilter(unsigned int scaleFilterID); - unsigned int getScaleFilterID() const { return scaleFilterID; } - - // Scale rect from the source image buffer to the destination buffer - // using the current interpolation method - virtual void scaleRect(const Rect& r); - - // Calculate the scaled image rectangle which depend on the source - // image rectangle. - Rect calculateScaleBoundary(const Rect& r); - - protected: - - // Calculate the scaled buffer size depending on the source buffer - // parameters (width, height, pixel format) - virtual void calculateScaledBufferSize(); - - // Free the weight tabs for x and y - virtual void freeWeightTabs(); - - // Recreates the row accumulators. - virtual void recreateRowAccum(); - - - int src_width; - int src_height; - int scaled_width; - int scaled_height; - int scale; - double scale_ratio_x; - double scale_ratio_y; - PixelFormat pf; - unsigned int scaleFilterID; - ScaleFilters scaleFilters; - SFilterWeightTab *xWeightTabs; - SFilterWeightTab *yWeightTabs; - int *raccum; - int *gaccum; - int *baccum; - U8 **src_data; - U8 **scaled_data; - }; - -}; - -#endif diff --git a/common/rfb/Security.cxx b/common/rfb/Security.cxx index 238f3351..62ea50e6 100644 --- a/common/rfb/Security.cxx +++ b/common/rfb/Security.cxx @@ -24,9 +24,6 @@ #include <assert.h> #include <stdlib.h> #include <string.h> -#ifdef _WIN32 -#define strcasecmp _stricmp -#endif #include <rfb/CSecurityNone.h> #include <rfb/CSecurityStack.h> #include <rfb/CSecurityVeNCrypt.h> diff --git a/common/rfb/TightDecoder.cxx b/common/rfb/TightDecoder.cxx index b3d174a3..d4ee877f 100644 --- a/common/rfb/TightDecoder.cxx +++ b/common/rfb/TightDecoder.cxx @@ -37,11 +37,6 @@ using namespace rfb; #include <rfb/tightDecode.h> #undef BPP -Decoder* TightDecoder::create(CMsgReader* reader) -{ - return new TightDecoder(reader); -} - TightDecoder::TightDecoder(CMsgReader* reader_) : reader(reader_) { } diff --git a/common/rfb/TightDecoder.h b/common/rfb/TightDecoder.h index 5cdf873b..8200d2b8 100644 --- a/common/rfb/TightDecoder.h +++ b/common/rfb/TightDecoder.h @@ -28,9 +28,9 @@ namespace rfb { class TightDecoder : public Decoder { public: - static Decoder* create(CMsgReader* reader); - virtual void readRect(const Rect& r, CMsgHandler* handler); + TightDecoder(CMsgReader* reader); virtual ~TightDecoder(); + virtual void readRect(const Rect& r, CMsgHandler* handler); private: void tightDecode8(const Rect& r); @@ -54,8 +54,6 @@ namespace rfb { void directFillRect16(const Rect& r, Pixel pix); void directFillRect32(const Rect& r, Pixel pix); - TightDecoder(CMsgReader* reader); - CMsgReader* reader; CMsgHandler* handler; rdr::InStream* is; diff --git a/common/rfb/TightEncoder.cxx b/common/rfb/TightEncoder.cxx index 9be4581e..733365e0 100644 --- a/common/rfb/TightEncoder.cxx +++ b/common/rfb/TightEncoder.cxx @@ -17,6 +17,7 @@ * USA. */ #include <rdr/OutStream.h> +#include <rfb/TransImageGetter.h> #include <rfb/encodings.h> #include <rfb/ConnParams.h> #include <rfb/SMsgWriter.h> @@ -63,16 +64,16 @@ using namespace rfb; // 0 = JPEG quality 15, 4:2:0 subsampling (ratio ~= 100:1) const TIGHT_CONF TightEncoder::conf[10] = { - { 65536, 2048, 6, 0, 0, 0, 4, 24, 15, SUBSAMP_420 }, // 0 - { 65536, 2048, 6, 1, 1, 1, 8, 24, 29, SUBSAMP_420 }, // 1 - { 65536, 2048, 8, 3, 3, 2, 24, 96, 41, SUBSAMP_420 }, // 2 - { 65536, 2048, 12, 5, 5, 2, 32, 96, 42, SUBSAMP_422 }, // 3 - { 65536, 2048, 12, 6, 7, 3, 32, 96, 62, SUBSAMP_422 }, // 4 - { 65536, 2048, 12, 7, 8, 4, 32, 96, 77, SUBSAMP_422 }, // 5 - { 65536, 2048, 16, 7, 8, 5, 32, 96, 79, SUBSAMP_NONE }, // 6 - { 65536, 2048, 16, 8, 9, 6, 64, 96, 86, SUBSAMP_NONE }, // 7 - { 65536, 2048, 24, 9, 9, 7, 64, 96, 92, SUBSAMP_NONE }, // 8 - { 65536, 2048, 32, 9, 9, 9, 96, 96,100, SUBSAMP_NONE } // 9 + { 65536, 2048, 6, 0, 0, 0, 4, 24, 15, subsample4X }, // 0 + { 65536, 2048, 6, 1, 1, 1, 8, 24, 29, subsample4X }, // 1 + { 65536, 2048, 8, 3, 3, 2, 24, 96, 41, subsample4X }, // 2 + { 65536, 2048, 12, 5, 5, 2, 32, 96, 42, subsample2X }, // 3 + { 65536, 2048, 12, 6, 7, 3, 32, 96, 62, subsample2X }, // 4 + { 65536, 2048, 12, 7, 8, 4, 32, 96, 77, subsample2X }, // 5 + { 65536, 2048, 16, 7, 8, 5, 32, 96, 79, subsampleNone }, // 6 + { 65536, 2048, 16, 8, 9, 6, 64, 96, 86, subsampleNone }, // 7 + { 65536, 2048, 24, 9, 9, 7, 64, 96, 92, subsampleNone }, // 8 + { 65536, 2048, 32, 9, 9, 9, 96, 96,100, subsampleNone } // 9 }; const int TightEncoder::defaultCompressLevel = 2; @@ -91,11 +92,6 @@ const int TightEncoder::defaultCompressLevel = 2; #include <rfb/tightEncode.h> #undef BPP -Encoder* TightEncoder::create(SMsgWriter* writer) -{ - return new TightEncoder(writer); -} - TightEncoder::TightEncoder(SMsgWriter* writer_) : writer(writer_) { setCompressLevel(defaultCompressLevel); @@ -122,18 +118,14 @@ void TightEncoder::setQualityLevel(int level) jpegSubsampling = conf[level].jpegSubsampling; } else { jpegQuality = -1; - jpegSubsampling = SUBSAMP_UNDEFINED; + jpegSubsampling = subsampleUndefined; } } -void TightEncoder::setFineQualityLevel(int quality, JPEG_SUBSAMP subsampling) +void TightEncoder::setFineQualityLevel(int quality, int subsampling) { - if (quality >= 1 && quality <= 100) { - jpegQuality = quality; - } - if (subsampling >= SUBSAMP_NONE && subsampling <= SUBSAMP_GRAY) { - jpegSubsampling = subsampling; - } + jpegQuality = quality; + jpegSubsampling = subsampling; } bool TightEncoder::checkSolidTile(Rect& r, rdr::U32* colorPtr, @@ -345,7 +337,7 @@ bool TightEncoder::writeRect(const Rect& _r, TransImageGetter* _ig, sr.setXYWH(dx, dy, dw, dh); if (checkSolidTile(sr, &colorValue, false)) { - if (jpegSubsampling == SUBSAMP_GRAY && jpegQuality != -1) { + if (jpegSubsampling == subsampleGray && jpegQuality != -1) { Colour rgb; serverpf.rgbFromPixel(colorValue, NULL, &rgb); rdr::U32 lum = ((257 * rgb.r) + (504 * rgb.g) + (98 * rgb.b) diff --git a/common/rfb/TightEncoder.h b/common/rfb/TightEncoder.h index 4fff0832..3632539d 100644 --- a/common/rfb/TightEncoder.h +++ b/common/rfb/TightEncoder.h @@ -21,8 +21,8 @@ #include <rdr/MemOutStream.h> #include <rdr/ZlibOutStream.h> -#include <rfb/TransImageGetter.h> #include <rfb/Encoder.h> +#include <rfb/JpegCompressor.h> // FIXME: Check if specifying extern "C" is really necessary. #include <stdio.h> @@ -32,6 +32,8 @@ extern "C" { namespace rfb { + class TransImageGetter; + struct TIGHT_CONF { unsigned int maxRectSize, maxRectWidth; unsigned int monoMinRectSize; @@ -39,7 +41,7 @@ namespace rfb { int idxMaxColorsDivisor; int palMaxColorsWithJPEG; int jpegQuality; - JPEG_SUBSAMP jpegSubsampling; + int jpegSubsampling; }; // @@ -77,16 +79,16 @@ namespace rfb { class TightEncoder : public Encoder { public: - static Encoder* create(SMsgWriter* writer); + TightEncoder(SMsgWriter* writer); + virtual ~TightEncoder(); + virtual void setCompressLevel(int level); virtual void setQualityLevel(int level); - virtual void setFineQualityLevel(int quality, JPEG_SUBSAMP subsampling); + virtual void setFineQualityLevel(int quality, int subsampling); virtual int getNumRects(const Rect &r); virtual bool writeRect(const Rect& r, TransImageGetter* ig, Rect* actual); - virtual ~TightEncoder(); private: - TightEncoder(SMsgWriter* writer); bool checkSolidTile(Rect& r, rdr::U32* colorPtr, bool needSameColor); void extendSolidArea(const Rect& r, rdr::U32 colorValue, Rect& er); void findBestSolidArea(Rect& r, rdr::U32 colorValue, Rect& bestr); @@ -157,7 +159,7 @@ namespace rfb { const TIGHT_CONF* pconf; int jpegQuality; - JPEG_SUBSAMP jpegSubsampling; + int jpegSubsampling; }; } diff --git a/common/rfb/TransImageGetter.cxx b/common/rfb/TransImageGetter.cxx index c1add1ce..3900d065 100644 --- a/common/rfb/TransImageGetter.cxx +++ b/common/rfb/TransImageGetter.cxx @@ -56,18 +56,18 @@ void TransImageGetter::setColourMapEntries(int firstCol, int nCols) PixelTransformer::setColourMapEntries(firstCol, nCols); } -const rdr::U8 *TransImageGetter::getRawPixelsR(const Rect &r, int *stride) +const rdr::U8 *TransImageGetter::getRawBufferR(const Rect &r, int *stride) { if (!offset.equals(Point(0, 0))) - return pb->getPixelsR(r.translate(offset.negate()), stride); + return pb->getBuffer(r.translate(offset.negate()), stride); else - return pb->getPixelsR(r, stride); + return pb->getBuffer(r, stride); } void TransImageGetter::getImage(void* outPtr, const Rect& r, int outStride) { int inStride; - const rdr::U8* inPtr = pb->getPixelsR(r.translate(offset.negate()), &inStride); + const rdr::U8* inPtr = pb->getBuffer(r.translate(offset.negate()), &inStride); if (!outStride) outStride = r.width(); diff --git a/common/rfb/TransImageGetter.h b/common/rfb/TransImageGetter.h index f2b35b45..b241b83c 100644 --- a/common/rfb/TransImageGetter.h +++ b/common/rfb/TransImageGetter.h @@ -72,11 +72,11 @@ namespace rfb { // padding will be outStride-r.width() pixels). void getImage(void* outPtr, const Rect& r, int outStride=0); - // getRawPixelsR() gets the given rectangle of data directly from the + // getRawBufferR() gets the given rectangle of data directly from the // underlying PixelBuffer, bypassing the translation logic. Only use // this when doing something that's independent of the client's pixel // format. - const rdr::U8 *getRawPixelsR(const Rect &r, int *stride); + const rdr::U8 *getRawBufferR(const Rect &r, int *stride); // setPixelBuffer() changes the pixel buffer to be used. The new pixel // buffer MUST have the same pixel format as the old one - if not you diff --git a/common/rfb/ZRLEDecoder.cxx b/common/rfb/ZRLEDecoder.cxx index aba7fc9f..111e2de6 100644 --- a/common/rfb/ZRLEDecoder.cxx +++ b/common/rfb/ZRLEDecoder.cxx @@ -40,11 +40,6 @@ using namespace rfb; #undef CPIXEL #undef BPP -Decoder* ZRLEDecoder::create(CMsgReader* reader) -{ - return new ZRLEDecoder(reader); -} - ZRLEDecoder::ZRLEDecoder(CMsgReader* reader_) : reader(reader_) { } diff --git a/common/rfb/ZRLEDecoder.h b/common/rfb/ZRLEDecoder.h index fe96c737..2128ab91 100644 --- a/common/rfb/ZRLEDecoder.h +++ b/common/rfb/ZRLEDecoder.h @@ -25,11 +25,10 @@ namespace rfb { class ZRLEDecoder : public Decoder { public: - static Decoder* create(CMsgReader* reader); - virtual void readRect(const Rect& r, CMsgHandler* handler); + ZRLEDecoder(CMsgReader* reader); virtual ~ZRLEDecoder(); + virtual void readRect(const Rect& r, CMsgHandler* handler); private: - ZRLEDecoder(CMsgReader* reader); CMsgReader* reader; rdr::ZlibInStream zis; }; diff --git a/common/rfb/ZRLEEncoder.cxx b/common/rfb/ZRLEEncoder.cxx index a83d79f3..e70706b5 100644 --- a/common/rfb/ZRLEEncoder.cxx +++ b/common/rfb/ZRLEEncoder.cxx @@ -17,7 +17,7 @@ */ #include <rdr/OutStream.h> #include <rfb/Exception.h> -#include <rfb/ImageGetter.h> +#include <rfb/TransImageGetter.h> #include <rfb/encodings.h> #include <rfb/ConnParams.h> #include <rfb/SMsgWriter.h> @@ -26,9 +26,6 @@ using namespace rfb; -rdr::MemOutStream* ZRLEEncoder::sharedMos = 0; -int ZRLEEncoder::maxLen = 4097 * 1024; // enough for width 16384 32-bit pixels - IntParameter zlibLevel("ZlibLevel","Zlib compression level",-1); #define EXTRA_ARGS ImageGetter* ig @@ -49,39 +46,28 @@ IntParameter zlibLevel("ZlibLevel","Zlib compression level",-1); #undef CPIXEL #undef BPP -Encoder* ZRLEEncoder::create(SMsgWriter* writer) -{ - return new ZRLEEncoder(writer); -} - ZRLEEncoder::ZRLEEncoder(SMsgWriter* writer_) - : writer(writer_), zos(0,0,zlibLevel) + : writer(writer_), zos(0,0,zlibLevel), mos(129*1024) { - if (sharedMos) - mos = sharedMos; - else - mos = new rdr::MemOutStream(129*1024); } ZRLEEncoder::~ZRLEEncoder() { - if (!sharedMos) - delete mos; } bool ZRLEEncoder::writeRect(const Rect& r, TransImageGetter* ig, Rect* actual) { rdr::U8* imageBuf = writer->getImageBuf(64 * 64 * 4 + 4); - mos->clear(); + mos.clear(); bool wroteAll = true; *actual = r; switch (writer->bpp()) { case 8: - wroteAll = zrleEncode8(r, mos, &zos, imageBuf, maxLen, actual, ig); + wroteAll = zrleEncode8(r, &mos, &zos, imageBuf, actual, ig); break; case 16: - wroteAll = zrleEncode16(r, mos, &zos, imageBuf, maxLen, actual, ig); + wroteAll = zrleEncode16(r, &mos, &zos, imageBuf, actual, ig); break; case 32: { @@ -94,16 +80,16 @@ bool ZRLEEncoder::writeRect(const Rect& r, TransImageGetter* ig, Rect* actual) if ((fitsInLS3Bytes && pf.isLittleEndian()) || (fitsInMS3Bytes && pf.isBigEndian())) { - wroteAll = zrleEncode24A(r, mos, &zos, imageBuf, maxLen, actual, ig); + wroteAll = zrleEncode24A(r, &mos, &zos, imageBuf, actual, ig); } else if ((fitsInLS3Bytes && pf.isBigEndian()) || (fitsInMS3Bytes && pf.isLittleEndian())) { - wroteAll = zrleEncode24B(r, mos, &zos, imageBuf, maxLen, actual, ig); + wroteAll = zrleEncode24B(r, &mos, &zos, imageBuf, actual, ig); } else { - wroteAll = zrleEncode32(r, mos, &zos, imageBuf, maxLen, actual, ig); + wroteAll = zrleEncode32(r, &mos, &zos, imageBuf, actual, ig); } break; } @@ -111,8 +97,8 @@ bool ZRLEEncoder::writeRect(const Rect& r, TransImageGetter* ig, Rect* actual) writer->startRect(*actual, encodingZRLE); rdr::OutStream* os = writer->getOutStream(); - os->writeU32(mos->length()); - os->writeBytes(mos->data(), mos->length()); + os->writeU32(mos.length()); + os->writeBytes(mos.data(), mos.length()); writer->endRect(); return wroteAll; } diff --git a/common/rfb/ZRLEEncoder.h b/common/rfb/ZRLEEncoder.h index 3a0f52a9..e3517c13 100644 --- a/common/rfb/ZRLEEncoder.h +++ b/common/rfb/ZRLEEncoder.h @@ -26,29 +26,13 @@ namespace rfb { class ZRLEEncoder : public Encoder { public: - static Encoder* create(SMsgWriter* writer); - virtual bool writeRect(const Rect& r, TransImageGetter* ig, Rect* actual); + ZRLEEncoder(SMsgWriter* writer); virtual ~ZRLEEncoder(); - - // setMaxLen() sets the maximum size in bytes of any ZRLE rectangle. This - // can be used to stop the MemOutStream from growing too large. The value - // must be large enough to allow for at least one row of ZRLE tiles. So - // for example for a screen width of 2048 32-bit pixels this is 2K*4*64 = - // 512Kbytes plus a bit of overhead (the overhead is about 1/16 of the - // width, in this example about 128 bytes). - static void setMaxLen(int m) { maxLen = m; } - - // setSharedMos() sets a MemOutStream to be shared amongst all - // ZRLEEncoders. Should be called before any ZRLEEncoders are created. - static void setSharedMos(rdr::MemOutStream* mos_) { sharedMos = mos_; } - + virtual bool writeRect(const Rect& r, TransImageGetter* ig, Rect* actual); private: - ZRLEEncoder(SMsgWriter* writer); SMsgWriter* writer; rdr::ZlibOutStream zos; - rdr::MemOutStream* mos; - static rdr::MemOutStream* sharedMos; - static int maxLen; + rdr::MemOutStream mos; }; } #endif diff --git a/common/rfb/encodings.cxx b/common/rfb/encodings.cxx index 97f547bf..190e0324 100644 --- a/common/rfb/encodings.cxx +++ b/common/rfb/encodings.cxx @@ -16,9 +16,6 @@ * USA. */ #include <string.h> -#ifdef _WIN32 -#define strcasecmp _stricmp -#endif #include <rfb/encodings.h> #include <rfb/util.h> diff --git a/common/rfb/hextileDecode.h b/common/rfb/hextileDecode.h index 77befc7d..7aa04d91 100644 --- a/common/rfb/hextileDecode.h +++ b/common/rfb/hextileDecode.h @@ -69,13 +69,9 @@ void HEXTILE_DECODE (const Rect& r, rdr::InStream* is, PIXEL_T* buf if (tileType & hextileBgSpecified) bg = is->READ_PIXEL(); -#ifdef FAVOUR_FILL_RECT - FILL_RECT(t, bg); -#else int len = t.area(); PIXEL_T* ptr = (PIXEL_T*)buf; while (len-- > 0) *ptr++ = bg; -#endif if (tileType & hextileFgSpecified) fg = is->READ_PIXEL(); @@ -91,14 +87,6 @@ void HEXTILE_DECODE (const Rect& r, rdr::InStream* is, PIXEL_T* buf int xy = is->readU8(); int wh = is->readU8(); -#ifdef FAVOUR_FILL_RECT - Rect s; - s.tl.x = t.tl.x + ((xy >> 4) & 15); - s.tl.y = t.tl.y + (xy & 15); - s.br.x = s.tl.x + ((wh >> 4) & 15) + 1; - s.br.y = s.tl.y + (wh & 15) + 1; - FILL_RECT(s, fg); -#else int x = ((xy >> 4) & 15); int y = (xy & 15); int w = ((wh >> 4) & 15) + 1; @@ -110,12 +98,9 @@ void HEXTILE_DECODE (const Rect& r, rdr::InStream* is, PIXEL_T* buf while (len-- > 0) *ptr++ = fg; ptr += rowAdd; } -#endif } } -#ifndef FAVOUR_FILL_RECT IMAGE_RECT(t, buf); -#endif } } } diff --git a/common/rfb/tightDecode.h b/common/rfb/tightDecode.h index e9f5f6ba..06c84775 100644 --- a/common/rfb/tightDecode.h +++ b/common/rfb/tightDecode.h @@ -156,7 +156,7 @@ void TIGHT_DECODE (const Rect& r) PIXEL_T *buf; int stride = r.width(); - if (directDecode) buf = (PIXEL_T *)handler->getRawPixelsRW(r, &stride); + if (directDecode) buf = (PIXEL_T *)handler->getRawBufferRW(r, &stride); else buf = (PIXEL_T *)reader->getImageBuf(r.area()); if (palSize == 0) { @@ -228,7 +228,7 @@ void TIGHT_DECODE (const Rect& r) } } - if (directDecode) handler->releaseRawPixels(r); + if (directDecode) handler->releaseRawBuffer(r); else IMAGE_RECT(r, buf); delete [] netbuf; @@ -256,10 +256,9 @@ DECOMPRESS_JPEG_RECT(const Rect& r) // We always use direct decoding with JPEG images int stride; - rdr::U8 *buf = handler->getRawPixelsRW(r, &stride); - jd.decompress(netbuf, compressedLen, buf, stride * clientpf.bpp / 8, r, - clientpf); - handler->releaseRawPixels(r); + rdr::U8 *buf = handler->getRawBufferRW(r, &stride); + jd.decompress(netbuf, compressedLen, buf, stride, r, clientpf); + handler->releaseRawBuffer(r); delete [] netbuf; } diff --git a/common/rfb/tightEncode.h b/common/rfb/tightEncode.h index 8f900b58..c121b7aa 100644 --- a/common/rfb/tightEncode.h +++ b/common/rfb/tightEncode.h @@ -191,9 +191,9 @@ void TIGHT_ENCODE (const Rect& r, rdr::OutStream *os, bool forceSolid) { int stride; rdr::U32 solidColor; - const PIXEL_T *rawPixels = (const PIXEL_T *)ig->getRawPixelsR(r, &stride); + const PIXEL_T *rawPixels = (const PIXEL_T *)ig->getRawBufferR(r, &stride); PIXEL_T *pixels = NULL; - bool grayScaleJPEG = (jpegSubsampling == SUBSAMP_GRAY && jpegQuality != -1); + bool grayScaleJPEG = (jpegSubsampling == subsampleGray && jpegQuality != -1); #if (BPP == 32) // Check if it's necessary to pack 24-bit pixels, and @@ -412,7 +412,7 @@ void ENCODE_JPEG_RECT (PIXEL_T *buf, int stride, const Rect& r, rdr::OutStream *os) { jc.clear(); - jc.compress((rdr::U8 *)buf, stride * clientpf.bpp / 8, r, clientpf, + jc.compress((rdr::U8 *)buf, stride, r, clientpf, jpegQuality, jpegSubsampling); os->writeU8(0x09 << 4); os->writeCompactLength(jc.length()); @@ -540,12 +540,7 @@ void FAST_FILL_PALETTE (const PIXEL_T *data, int stride, const Rect& r) *dataend = &data[stride * h]; bool willTransform = ig->willTransform(); - if (willTransform) { - mask = serverpf.redMax << serverpf.redShift; - mask |= serverpf.greenMax << serverpf.greenShift; - mask |= serverpf.blueMax << serverpf.blueShift; - } - else mask = ~0; + serverpf.bufferFromPixel((rdr::U8*)&mask, ~0); c0 = data[0] & mask; n0 = 0; @@ -650,7 +645,7 @@ bool CHECK_SOLID_TILE(Rect& r, rdr::U32 *colorPtr, bool needSameColor) int w = r.width(), h = r.height(); int stride = w; - buf = (const PIXEL_T *)ig->getRawPixelsR(r, &stride); + buf = (const PIXEL_T *)ig->getRawBufferR(r, &stride); colorValue = *buf; if (needSameColor && (rdr::U32)colorValue != *colorPtr) diff --git a/common/rfb/util.cxx b/common/rfb/util.cxx index 2709f2cc..a41ad96a 100644 --- a/common/rfb/util.cxx +++ b/common/rfb/util.cxx @@ -38,97 +38,6 @@ #include <rfb/util.h> -// Provide strcasecmp() and/or strncasecmp() if absent on this system. - -#ifndef WIN32 -#if !defined(HAVE_STRCASECMP) || !defined(HAVE_STRNCASECMP) - -extern "C" { - -/* - * This array is designed for mapping upper and lower case letter - * together for a case independent comparison. The mappings are - * based upon ascii character sequences. - */ -static unsigned char s_charmap[] = { - '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', - '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', - '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', - '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', - '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', - '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', - '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', - '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', - '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', - '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', - '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', - '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', - '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', - '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', - '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', - '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', - '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', - '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', - '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', - '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', - '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', - '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', - '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', - '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', - '\300', '\341', '\342', '\343', '\344', '\345', '\346', '\347', - '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', - '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', - '\370', '\371', '\372', '\333', '\334', '\335', '\336', '\337', - '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', - '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', - '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', - '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377', -}; - -#ifndef HAVE_STRCASECMP -int -strcasecmp(const char *s1, const char *s2) -{ - unsigned char u1, u2; - - for (;;) { - u1 = (unsigned char) *s1++; - u2 = (unsigned char) *s2++; - if (s_charmap[u1] != s_charmap[u2]) { - return s_charmap[u1] - s_charmap[u2]; - } - if (u1 == '\0') { - return 0; - } - } -} -#endif // !defined(HAVE_STRCASECMP) - -#ifndef HAVE_STRNCASECMP -int -strncasecmp(const char *s1, const char *s2, size_t n) -{ - unsigned char u1, u2; - - for (; n != 0; --n) { - u1 = (unsigned char) *s1++; - u2 = (unsigned char) *s2++; - if (s_charmap[u1] != s_charmap[u2]) { - return s_charmap[u1] - s_charmap[u2]; - } - if (u1 == '\0') { - return 0; - } - } - return 0; -} -#endif // !defined(HAVE_STRNCASECMP) - -} // extern "C" - -#endif // !defined(HAVE_STRCASECMP) || !defined(HAVE_STRNCASECMP) -#endif // defined(WIN32) - namespace rfb { char* strDup(const char* s) { diff --git a/common/rfb/util.h b/common/rfb/util.h index 7d90a6b2..13dbe68e 100644 --- a/common/rfb/util.h +++ b/common/rfb/util.h @@ -104,17 +104,4 @@ namespace rfb { #define __rfbmin(a,b) (((a) < (b)) ? (a) : (b)) #endif -// Declare strcasecmp() and/or strncasecmp() if absent on this system. - -#if !defined(WIN32) && !defined(HAVE_STRCASECMP) -extern "C" { - int strcasecmp(const char *s1, const char *s2); -} -#endif -#if !defined(WIN32) && !defined(HAVE_STRNCASECMP) -extern "C" { - int strncasecmp(const char *s1, const char *s2, size_t n); -} -#endif - #endif diff --git a/common/rfb/zrleDecode.h b/common/rfb/zrleDecode.h index 8f6f7927..d26d4d3e 100644 --- a/common/rfb/zrleDecode.h +++ b/common/rfb/zrleDecode.h @@ -121,12 +121,6 @@ void ZRLE_DECODE (const Rect& r, rdr::InStream* is, } } -#ifdef FAVOUR_FILL_RECT - //fprintf(stderr,"copying data to screen %dx%d at %d,%d\n", - //t.width(),t.height(),t.tl.x,t.tl.y); - IMAGE_RECT(t,buf); -#endif - } else { if (palSize == 0) { @@ -149,36 +143,7 @@ void ZRLE_DECODE (const Rect& r, rdr::InStream* is, throw Exception ("ZRLE decode error"); } -#ifdef FAVOUR_FILL_RECT - int i = ptr - buf; - ptr += len; - - int runX = i % t.width(); - int runY = i / t.width(); - - if (runX + len > t.width()) { - if (runX != 0) { - FILL_RECT(Rect(t.tl.x+runX, t.tl.y+runY, t.width()-runX, 1), - pix); - len -= t.width()-runX; - runX = 0; - runY++; - } - - if (len > t.width()) { - FILL_RECT(Rect(t.tl.x, t.tl.y+runY, t.width(), len/t.width()), - pix); - runY += len / t.width(); - len = len % t.width(); - } - } - - if (len != 0) { - FILL_RECT(Rect(t.tl.x+runX, t.tl.y+runY, len, 1), pix); - } -#else while (len-- > 0) *ptr++ = pix; -#endif } } else { @@ -207,45 +172,14 @@ void ZRLE_DECODE (const Rect& r, rdr::InStream* is, PIXEL_T pix = palette[index]; -#ifdef FAVOUR_FILL_RECT - int i = ptr - buf; - ptr += len; - - int runX = i % t.width(); - int runY = i / t.width(); - - if (runX + len > t.width()) { - if (runX != 0) { - FILL_RECT(Rect(t.tl.x+runX, t.tl.y+runY, t.width()-runX, 1), - pix); - len -= t.width()-runX; - runX = 0; - runY++; - } - - if (len > t.width()) { - FILL_RECT(Rect(t.tl.x, t.tl.y+runY, t.width(), len/t.width()), - pix); - runY += len / t.width(); - len = len % t.width(); - } - } - - if (len != 0) { - FILL_RECT(Rect(t.tl.x+runX, t.tl.y+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", //t.width(),t.height(),t.tl.x,t.tl.y); IMAGE_RECT(t,buf); -#endif } } diff --git a/common/rfb/zrleEncode.h b/common/rfb/zrleEncode.h index 9b7263b3..0c622b88 100644 --- a/common/rfb/zrleEncode.h +++ b/common/rfb/zrleEncode.h @@ -115,7 +115,7 @@ public: void ZRLE_ENCODE_TILE (PIXEL_T* data, int w, int h, rdr::OutStream* os); bool ZRLE_ENCODE (const Rect& r, rdr::OutStream* os, - rdr::ZlibOutStream* zos, void* buf, int maxLen, Rect* actual + rdr::ZlibOutStream* zos, void* buf, Rect* actual #ifdef EXTRA_ARGS , EXTRA_ARGS #endif @@ -132,7 +132,8 @@ bool ZRLE_ENCODE (const Rect& r, rdr::OutStream* os, t.br.y = __rfbmin(r.br.y, t.tl.y + 64); - if (os->length() + worstCaseLine > maxLen) { + // enough for width 16384 32-bit pixels + if (os->length() + worstCaseLine > 4097 * 1024) { if (t.tl.y == r.tl.y) throw Exception("ZRLE: not enough space for first line?"); actual->tl = r.tl; diff --git a/config.h.in b/config.h.in index ec2aed90..0c9e71a5 100644 --- a/config.h.in +++ b/config.h.in @@ -1,14 +1,8 @@ #define PACKAGE_NAME "@CMAKE_PROJECT_NAME@" #define PACKAGE_VERSION "@VERSION@" -#cmakedefine HAVE_SOCKLEN_T #cmakedefine HAVE_INET_ATON -#cmakedefine HAVE_INET_NTOP #cmakedefine HAVE_GETADDRINFO -#cmakedefine HAVE_SNPRINTF -#cmakedefine HAVE_STRCASECMP -#cmakedefine HAVE_STRNCASECMP -#cmakedefine HAVE_VSNPRINTF #cmakedefine HAVE_GNUTLS_SET_GLOBAL_ERRNO #cmakedefine HAVE_GNUTLS_SET_ERRNO #cmakedefine HAVE_GNUTLS_X509_CRT_PRINT diff --git a/unix/tx/CMakeLists.txt b/unix/tx/CMakeLists.txt index ab46f03c..67976150 100644 --- a/unix/tx/CMakeLists.txt +++ b/unix/tx/CMakeLists.txt @@ -4,10 +4,6 @@ include_directories(${CMAKE_SOURCE_DIR}/common) include_directories(${CMAKE_SOURCE_DIR}/common/rfb) add_library(tx STATIC - TXWindow.cxx - TXScrollbar.cxx - TXViewport.cxx - TXImage.cxx - TXMenu.cxx) + TXWindow.cxx) target_link_libraries(tx ${X11_LIBRARIES}) diff --git a/unix/tx/TXEntry.h b/unix/tx/TXEntry.h deleted file mode 100644 index 1785a5f5..00000000 --- a/unix/tx/TXEntry.h +++ /dev/null @@ -1,191 +0,0 @@ -/* Copyright (C) 2002-2005 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. - */ -// -// TXEntry.h -// -// A TXEntry allows you to enter a single line of text in a window. The entry -// must be tall enough to contain a line of text - if not then it will be -// resized appropriately. If the passwd argument to the constructor is true, -// then the text in the entry will be replaced by asterisks on the screen. -// - -#ifndef __TXENTRY_H__ -#define __TXENTRY_H__ - -#include "TXWindow.h" -#include <X11/keysym.h> - -#ifndef XK_ISO_Left_Tab -#define XK_ISO_Left_Tab 0xFE20 -#endif -#ifndef XK_KP_Delete -#define XK_KP_Delete 0xFF9F -#endif - -// TXEntryCallback's entryCallback() method is called when one of three special -// key presses have happened: Enter/Return, forward tab, or backward tab. -class TXEntry; -class TXEntryCallback { -public: - enum Detail { ENTER, NEXT_FOCUS, PREV_FOCUS }; - virtual void entryCallback(TXEntry* entry, Detail detail, Time time)=0; -}; - - -class TXEntry : public TXWindow, public TXEventHandler { -public: - - TXEntry(Display* dpy_, TXEntryCallback* cb_=0, - TXWindow* parent_=0, bool passwd_=false, int w=1, int h=1) - : TXWindow(dpy_, w, h, parent_), cb(cb_), - passwd(passwd_), disabled_(false), gotFocus(false) - { - setEventHandler(this); - gc = XCreateGC(dpy, win(), 0, 0); - addEventMask(ExposureMask | KeyPressMask | FocusChangeMask - | ButtonPressMask); - text[0] = 0; - int textHeight = (defaultFS->ascent + defaultFS->descent); - int newHeight = __rfbmax(height(), textHeight + yPad*2 + bevel*2); - if (height() < newHeight) { - resize(width(), newHeight); - } - } - - virtual ~TXEntry() { - XFreeGC(dpy, gc); - // overwrite memory used to store password - not critical, but can avoid - // accidental exposure of a password in uninitialised memory. - if (passwd) - memset(text, 0, maxLen); - } - - // getText() gets the text in the entry. - const char* getText() { return text; } - - // setText() sets the text in the entry. - void setText(const char* text_) { - strncpy(text, text_, maxLen-1); - text[maxLen-1] = 0; - paint(); - } - - // disabled() sets or queries the disabled state of the entry. A disabled - // entry cannot have text entered into it. - void disabled(bool b) { disabled_ = b; paint(); } - bool disabled() { return disabled_; } - -private: - void paint() { - if (disabled_) - drawBevel(gc, 0, 0, width(), height(), bevel, disabledBg,darkBg,lightBg); - else - drawBevel(gc, 0, 0, width(), height(), bevel, enabledBg, darkBg,lightBg); - char* str = text; - char stars[maxLen]; - if (passwd) { - int i; - for (i = 0; i < (int)strlen(text); i++) stars[i] = '*'; - stars[i] = 0; - str = stars; - } - int tw = XTextWidth(defaultFS, str, strlen(str)); - int startx = bevel + xPad; - if (startx + tw > width() - 2*bevel) { - startx = width() - 2*bevel - tw; - } - XDrawString(dpy, win(), defaultGC, startx, - (height() + defaultFS->ascent - defaultFS->descent) / 2, - str, strlen(str)); - if (!disabled_ && gotFocus) - XDrawLine(dpy, win(), defaultGC, startx+tw, - (height() - defaultFS->ascent - defaultFS->descent) / 2, - startx+tw, - (height() + defaultFS->ascent + defaultFS->descent) / 2); - } - - virtual void handleEvent(TXWindow* w, XEvent* ev) { - switch (ev->type) { - case Expose: - paint(); - break; - - case FocusIn: - gotFocus = true; - paint(); - break; - - case FocusOut: - gotFocus = false; - paint(); - break; - - case ButtonPress: - if (!disabled_) - XSetInputFocus(dpy, win(), RevertToParent, ev->xbutton.time); - break; - - case KeyPress: - { - if (disabled_ || !gotFocus) break; - KeySym keysym; - XComposeStatus compose; - char buf[10]; - int count = XLookupString(&ev->xkey, buf, 10, &keysym, &compose); - if (count >= 1 && buf[0] >= ' ' && buf[0] <= '~') { - if (strlen(text) + count >= maxLen) { - XBell(dpy, 0); - } else { - strncat(text, buf, count); - paint(); - } - } else if (keysym == XK_BackSpace || keysym == XK_Delete || - keysym == XK_KP_Delete) { - if (strlen(text) > 0) { - text[strlen(text)-1] = 0; - paint(); - } - } else if (keysym == XK_Return || keysym == XK_KP_Enter || - keysym == XK_Linefeed) { - if (cb) cb->entryCallback(this, TXEntryCallback::ENTER, - ev->xkey.time); - } else if ((keysym == XK_Tab || keysym == XK_KP_Tab) - && !(ev->xkey.state & ShiftMask)) - { - if (cb) cb->entryCallback(this, TXEntryCallback::NEXT_FOCUS, - ev->xkey.time); - } else if (((keysym == XK_Tab || keysym == XK_KP_Tab) - && (ev->xkey.state & ShiftMask)) - || keysym == XK_ISO_Left_Tab) - { - if (cb) cb->entryCallback(this, TXEntryCallback::PREV_FOCUS, - ev->xkey.time); - } - } - } - } - GC gc; - enum { maxLen = 256 }; - char text[maxLen]; - TXEntryCallback* cb; - bool passwd; - bool disabled_; - bool gotFocus; -}; - -#endif diff --git a/unix/tx/TXImage.cxx b/unix/tx/TXImage.cxx deleted file mode 100644 index db20d6f3..00000000 --- a/unix/tx/TXImage.cxx +++ /dev/null @@ -1,361 +0,0 @@ -/* Copyright (C) 2002-2005 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. - */ -// -// TXImage.cxx -// - - -#include <stdio.h> -#include <stdlib.h> -#include <strings.h> -#include <sys/types.h> -#include <sys/ipc.h> -#include <sys/shm.h> -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <list> -#include <rfb/TransImageGetter.h> -#include <rfb/Exception.h> -#include <rfb/LogWriter.h> -#include "TXWindow.h" -#include "TXImage.h" - -using namespace rfb; - -static rfb::LogWriter vlog("TXImage"); - -TXImage::TXImage(Display* d, int width, int height, Visual* vis_, int depth_) - : xim(0), dpy(d), vis(vis_), depth(depth_), tig(0), cube(0) -{ -#ifdef HAVE_MITSHM - shminfo = 0; -#endif - width_ = width; - height_ = height; - for (int i = 0; i < 256; i++) - colourMap[i].r = colourMap[i].g = colourMap[i].b = 0; - - if (!vis) - vis = DefaultVisual(dpy,DefaultScreen(dpy)); - if (!depth) - depth = DefaultDepth(dpy,DefaultScreen(dpy)); - - createXImage(); - getNativePixelFormat(vis, depth); - colourmap = this; - format.bpp = 0; // just make it different to any valid format, so that... - setPF(nativePF); // ...setPF() always works -} - -TXImage::~TXImage() -{ - if (data != (rdr::U8*)xim->data) delete [] data; - destroyXImage(); - delete tig; - delete cube; -} - -void TXImage::resize(int w, int h) -{ - if (w == width() && h == height()) return; - - int oldStrideBytes = getStride() * (format.bpp/8); - int rowsToCopy = __rfbmin(h, height()); - int bytesPerRow = __rfbmin(w, width()) * (format.bpp/8); - rdr::U8* oldData = 0; - bool allocData = false; - - if (data != (rdr::U8*)xim->data) { - oldData = (rdr::U8*)data; - allocData = true; - } else { - oldData = new rdr::U8[xim->bytes_per_line * height()]; - memcpy(oldData, xim->data, xim->bytes_per_line * height()); - } - - destroyXImage(); - width_ = w; - height_ = h; - createXImage(); - - if (allocData) - data = new rdr::U8[width() * height() * (format.bpp/8)]; - else - data = (rdr::U8*)xim->data; - - int newStrideBytes = getStride() * (format.bpp/8); - for (int i = 0; i < rowsToCopy; i++) - memcpy((rdr::U8*)data + newStrideBytes * i, oldData + oldStrideBytes * i, - bytesPerRow); - delete [] oldData; -} - -void TXImage::setPF(const PixelFormat& newPF) -{ - if (newPF.equal(format)) return; - format = newPF; - - if (data != (rdr::U8*)xim->data) delete [] data; - delete tig; - tig = 0; - - if (format.equal(nativePF) && format.trueColour) { - data = (rdr::U8*)xim->data; - } else { - data = new rdr::U8[width() * height() * (format.bpp/8)]; - tig = new TransImageGetter(); - tig->init(this, nativePF, 0, cube); - } -} - -int TXImage::getStride() const -{ - if (data == (rdr::U8*)xim->data) - return xim->bytes_per_line / (xim->bits_per_pixel / 8); - else - return width(); -} - -void TXImage::put(Window win, GC gc, const rfb::Rect& r) -{ - if (r.is_empty()) return; - int x = r.tl.x; - int y = r.tl.y; - int w = r.width(); - int h = r.height(); - if (data != (rdr::U8*)xim->data) { - rdr::U8* ximDataStart = ((rdr::U8*)xim->data + y * xim->bytes_per_line - + x * (xim->bits_per_pixel / 8)); - tig->getImage(ximDataStart, r, - xim->bytes_per_line / (xim->bits_per_pixel / 8)); - } -#ifdef HAVE_MITSHM - if (usingShm()) { - XShmPutImage(dpy, win, gc, xim, x, y, x, y, w, h, False); - return; - } -#endif - XPutImage(dpy, win, gc, xim, x, y, x, y, w, h); -} - -void TXImage::setColourMapEntries(int firstColour, int nColours, rdr::U16* rgbs) -{ - for (int i = 0; i < nColours; i++) { - colourMap[firstColour+i].r = rgbs[i*3]; - colourMap[firstColour+i].g = rgbs[i*3+1]; - colourMap[firstColour+i].b = rgbs[i*3+2]; - } -} - -void TXImage::updateColourMap() -{ - if (tig != 0) - tig->setColourMapEntries(0, 0); -} - -void TXImage::lookup(int index, int* r, int* g, int* b) -{ - *r = colourMap[index].r; - *g = colourMap[index].g; - *b = colourMap[index].b; -} - -#ifdef HAVE_MITSHM -static bool caughtError = false; - -static int XShmAttachErrorHandler(Display *dpy, XErrorEvent *error) -{ - caughtError = true; - return 0; -} - -class TXImageCleanup { -public: - std::list<TXImage*> images; - ~TXImageCleanup() { - while (!images.empty()) - delete images.front(); - } -}; - -static TXImageCleanup imageCleanup; -#endif - -void TXImage::createXImage() -{ -#ifdef HAVE_MITSHM - int major, minor; - Bool pixmaps; - - if (XShmQueryVersion(dpy, &major, &minor, &pixmaps)) { - shminfo = new XShmSegmentInfo; - - xim = XShmCreateImage(dpy, vis, depth, ZPixmap, - 0, shminfo, width(), height()); - - if (xim) { - shminfo->shmid = shmget(IPC_PRIVATE, - xim->bytes_per_line * xim->height, - IPC_CREAT|0777); - - if (shminfo->shmid != -1) { - shminfo->shmaddr = xim->data = (char*)shmat(shminfo->shmid, 0, 0); - - if (shminfo->shmaddr != (char *)-1) { - - shminfo->readOnly = False; - - XErrorHandler oldHdlr = XSetErrorHandler(XShmAttachErrorHandler); - XShmAttach(dpy, shminfo); - XSync(dpy, False); - XSetErrorHandler(oldHdlr); - - if (!caughtError) { - vlog.debug("Using shared memory XImage"); - imageCleanup.images.push_back(this); - return; - } - - shmdt(shminfo->shmaddr); - } else { - vlog.error("shmat failed"); - perror("shmat"); - } - - shmctl(shminfo->shmid, IPC_RMID, 0); - } else { - vlog.error("shmget failed"); - perror("shmget"); - } - - XDestroyImage(xim); - xim = 0; - } else { - vlog.error("XShmCreateImage failed"); - } - - delete shminfo; - shminfo = 0; - } -#endif - - xim = XCreateImage(dpy, vis, depth, ZPixmap, - 0, 0, width(), height(), BitmapPad(dpy), 0); - - xim->data = (char*)malloc(xim->bytes_per_line * xim->height); - if (!xim->data) { - vlog.error("malloc failed"); - exit(1); - } -} - -void TXImage::destroyXImage() -{ -#ifdef HAVE_MITSHM - if (shminfo) { - vlog.debug("Freeing shared memory XImage"); - shmdt(shminfo->shmaddr); - shmctl(shminfo->shmid, IPC_RMID, 0); - delete shminfo; - shminfo = 0; - imageCleanup.images.remove(this); - } -#endif - // XDestroyImage() will free(xim->data) if appropriate - if (xim) XDestroyImage(xim); - xim = 0; -} - - -static bool supportedBPP(int bpp) { - return (bpp == 8 || bpp == 16 || bpp == 32); -} - -static int depth2bpp(Display* dpy, int depth) -{ - int nformats; - XPixmapFormatValues* format = XListPixmapFormats(dpy, &nformats); - - int i; - for (i = 0; i < nformats; i++) - if (format[i].depth == depth) break; - - if (i == nformats || !supportedBPP(format[i].bits_per_pixel)) - throw rfb::Exception("Error: couldn't find suitable pixmap format"); - - int bpp = format[i].bits_per_pixel; - XFree(format); - return bpp; -} - -void TXImage::getNativePixelFormat(Visual* vis, int depth) -{ - int bpp; - int trueColour, bigEndian; - int redShift, greenShift, blueShift; - int redMax, greenMax, blueMax; - - cube = 0; - - bpp = depth2bpp(dpy, depth); - bigEndian = (ImageByteOrder(dpy) == MSBFirst); - trueColour = (vis->c_class == TrueColor); - - vlog.info("Using default colormap and visual, %sdepth %d.", - (vis->c_class == TrueColor) ? "TrueColor, " : - ((vis->c_class == PseudoColor) ? "PseudoColor, " : ""), - depth); - - redShift = ffs(vis->red_mask) - 1; - greenShift = ffs(vis->green_mask) - 1; - blueShift = ffs(vis->blue_mask) - 1; - redMax = vis->red_mask >> redShift; - greenMax = vis->green_mask >> greenShift; - blueMax = vis->blue_mask >> blueShift; - - nativePF = PixelFormat(bpp, depth, bigEndian, trueColour, - redMax, greenMax, blueMax, - redShift, greenShift, blueShift); - - if (!trueColour) { - XColor xc[256]; - cube = new rfb::ColourCube(6,6,6); - int r; - for (r = 0; r < cube->nRed; r++) { - for (int g = 0; g < cube->nGreen; g++) { - for (int b = 0; b < cube->nBlue; b++) { - int i = (r * cube->nGreen + g) * cube->nBlue + b; - xc[i].red = r * 65535 / (cube->nRed-1); - xc[i].green = g * 65535 / (cube->nGreen-1); - xc[i].blue = b * 65535 / (cube->nBlue-1); - } - } - } - - TXWindow::getColours(dpy, xc, cube->size()); - - for (r = 0; r < cube->nRed; r++) { - for (int g = 0; g < cube->nGreen; g++) { - for (int b = 0; b < cube->nBlue; b++) { - int i = (r * cube->nGreen + g) * cube->nBlue + b; - cube->set(r, g, b, xc[i].pixel); - } - } - } - } -} diff --git a/unix/tx/TXImage.h b/unix/tx/TXImage.h deleted file mode 100644 index 055bd22d..00000000 --- a/unix/tx/TXImage.h +++ /dev/null @@ -1,97 +0,0 @@ -/* Copyright (C) 2002-2005 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. - */ -// -// TXImage.h -// -// A TXImage represents a rectangular off-screen image in any RFB pixel format. -// By default it will use the "native" pixel format for the screen, which will -// be an 8-bit colourmap unless the X display is TrueColor. The pixel format -// can be changed via the setPF() method. The pixel data is accessible via the -// data member inherited from FullFramePixelBuffer, or can be set via the -// fillRect(), imageRect(), copyRect() and maskRect() methods, also inherited -// from PixelBuffer. A rectangle of the image can be drawn into an X Window -// via the put() method. If using a colourmap, the setColourMapEntries() and -// updateColourMap() methods must be called to set up the colourmap as -// appropriate. - - -#ifndef __TXIMAGE_H__ -#define __TXIMAGE_H__ - -#include <X11/Xlib.h> -#include <rfb/PixelBuffer.h> -#include <rfb/ColourMap.h> -#include <rfb/ColourCube.h> -#ifdef HAVE_MITSHM -#include <X11/extensions/XShm.h> -#endif - -namespace rfb { class TransImageGetter; } - -class TXImage : public rfb::FullFramePixelBuffer, public rfb::ColourMap { -public: - TXImage(Display* dpy, int width, int height, Visual* vis=0, int depth=0); - ~TXImage(); - - // resize() resizes the image, preserving the image data where possible. - void resize(int w, int h); - - // put causes the given rectangle to be drawn onto the given window. - void put(Window win, GC gc, const rfb::Rect& r); - - // setColourMapEntries() changes some of the entries in the colourmap. - // However these settings won't take effect until updateColourMap() is - // called. This is because recalculating the internal translation table can - // be expensive. - void setColourMapEntries(int firstColour, int nColours, rdr::U16* rgbs); - void updateColourMap(); - -#ifdef HAVE_MITSHM - bool usingShm() { return shminfo; } -#else - bool usingShm() { return 0; } -#endif - - // PixelBuffer methods - // width(), height(), getPF() etc are inherited from PixelBuffer - virtual void setPF(const rfb::PixelFormat& pf); - virtual int getStride() const; - -private: - - // ColourMap method - virtual void lookup(int index, int* r, int* g, int* b); - - void createXImage(); - void destroyXImage(); - void getNativePixelFormat(Visual* vis, int depth); - - XImage* xim; - Display* dpy; - Visual* vis; - int depth; -#ifdef HAVE_MITSHM - XShmSegmentInfo* shminfo; -#endif - rfb::TransImageGetter* tig; - rfb::Colour colourMap[256]; - rfb::PixelFormat nativePF; - rfb::ColourCube* cube; -}; - -#endif diff --git a/unix/tx/TXMenu.cxx b/unix/tx/TXMenu.cxx deleted file mode 100644 index 92712f55..00000000 --- a/unix/tx/TXMenu.cxx +++ /dev/null @@ -1,186 +0,0 @@ -/* Copyright (C) 2002-2005 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. - */ -// -// TXMenu.cxx -// - -#include "TXMenu.h" -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <assert.h> -#include <rfb/util.h> -#include <X11/keysym.h> - -TXMenu::TXMenu(Display* dpy_, TXMenuCallback* cb_, int w, int h, - TXWindow* parent_) - : TXWindow(dpy_, w, h, parent_), cb(cb_), nEntries(0), - highlight(-1) -{ - setEventHandler(this); - gc = XCreateGC(dpy, win(), 0, 0); - addEventMask(ExposureMask | ButtonPressMask | ButtonReleaseMask | - PointerMotionMask | EnterWindowMask | LeaveWindowMask); -} - -TXMenu::~TXMenu() -{ - XFreeGC(dpy, gc); - for (int i = 0; i < nEntries; i++) - delete [] text[i]; -} - -inline int TXMenu::entryHeight(int i) -{ - if (text[i]) - return defaultFS->ascent + defaultFS->descent + bevel*2 + yPad*2; - else - return yPad*2 + 1; -} - -void TXMenu::addEntry(const char* text_, long id_) -{ - assert(nEntries < maxEntries); - text[nEntries] = rfb::strDup(text_); - checked[nEntries] = false; - id[nEntries++] = id_; - int tw = 0; - if (text_) - tw = XTextWidth(defaultFS, text_, strlen(text_)); - int newWidth = width(); - if (tw + bevel*2 + xPad*5 + tickSize > width()) - newWidth = tw + bevel*2 + xPad*5 + tickSize; - int newHeight = 0; - for (int i = 0; i < nEntries; i++) - newHeight += entryHeight(i); - resize(newWidth, newHeight); -} - -void TXMenu::check(long id_, bool checked_) -{ - for (int i = 0; i < nEntries; i++) { - if (id[i] == id_) { - checked[i] = checked_; - break; - } - } -} - -void TXMenu::paint() -{ - int y = 0; - for (int i = 0; i < nEntries; i++) { - if (text[i]) { - if (i == highlight) - drawBevel(gc, 0, y, width(), entryHeight(i), bevel, - defaultBg, darkBg, lightBg); - else - XClearArea(dpy, win(), 0, y, width(), entryHeight(i), false); - if (checked[i]) - XCopyPlane(dpy, tick, win(), defaultGC, 0, 0, tickSize, tickSize, - bevel + xPad, - y + bevel + yPad + defaultFS->ascent - tickSize, 1); - - XDrawImageString(dpy, win(), defaultGC, bevel + xPad*2 + tickSize, - y + bevel + yPad + defaultFS->ascent, - text[i], strlen(text[i])); - } else { - XDrawLine(dpy, win(), defaultGC, bevel + xPad, y + entryHeight(i) / 2, - width() - bevel - xPad, y + entryHeight(i) / 2); - } - y += entryHeight(i); - } -} - -void TXMenu::handleEvent(TXWindow* w, XEvent* ev) -{ - switch (ev->type) { - case Expose: - paint(); - break; - - case ButtonRelease: - { - int y = ev->xmotion.y; - int entryY = 0; - for (int i = 0; i < nEntries; i++) { - if (y >= entryY && y <= entryY + entryHeight(i)) { - if (cb && text[i]) - cb->menuSelect(id[i], this); - break; - } - entryY += entryHeight(i); - } - highlight = -1; - paint(); - break; - } - - case ButtonPress: - case MotionNotify: - { - int y = ev->xmotion.y; - int entryY = 0; - for (int i = 0; i < nEntries; i++) { - if (y >= entryY && y <= entryY + entryHeight(i)) { - if (highlight != i) { - highlight = i; - paint(); - } - break; - } - entryY += entryHeight(i); - } - break; - } - - case KeyPress: - { - KeySym ks; - char str[256]; - XLookupString(&ev->xkey, str, 256, &ks, NULL); - if (ks == XK_Escape) { - highlight = -1; - unmap(); - } else if (ks == XK_Down || ks == XK_Up) { - if (nEntries < 1) break; - if (highlight < 0) - highlight = (ks == XK_Down ? nEntries-1 : 0); - int start = highlight; - int inc = (ks == XK_Down ? 1 : nEntries-1); - do { - highlight = (highlight + inc) % nEntries; - } while (highlight != start && !text[highlight]); - paint(); - } else if (ks == XK_space || ks == XK_KP_Space || - ks == XK_Return || ks == XK_KP_Enter) { - if (cb && highlight >= 0 && text[highlight]) - cb->menuSelect(id[highlight], this); - highlight = -1; - paint(); - } - break; - } - - case EnterNotify: - case LeaveNotify: - highlight = -1; - paint(); - break; - } -} diff --git a/unix/tx/TXMenu.h b/unix/tx/TXMenu.h deleted file mode 100644 index d0245ee9..00000000 --- a/unix/tx/TXMenu.h +++ /dev/null @@ -1,67 +0,0 @@ -/* Copyright (C) 2002-2005 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. - */ -// -// TXMenu.h -// -// A TXMenu consists of multiple entries which can be added one at a time. -// Each entry consists of some text, and has an associated integer identifier. -// A callback is made when a menu entry is selected. -// - -#ifndef __TXMENU_H__ -#define __TXMENU_H__ - -#include "TXWindow.h" - -// TXMenuCallback's menuSelect() method is called when a particular menu entry -// is selected. The id argument identifies the menu entry. -class TXMenu; -class TXMenuCallback { -public: - virtual void menuSelect(long id, TXMenu* menu)=0; -}; - -class TXMenu : public TXWindow, public TXEventHandler { -public: - TXMenu(Display* dpy_, TXMenuCallback* cb=0, int width=1, int height=1, - TXWindow* parent_=0); - virtual ~TXMenu(); - - // addEntry() adds an entry to the end of the menu with the given text and - // identifier. - void addEntry(const char* text, long id); - - // check() sets whether the given menu entry should have a tick next to it. - void check(long id, bool checked); - -private: - int entryHeight(int i); - virtual void handleEvent(TXWindow* w, XEvent* ev); - void paint(); - - GC gc; - TXMenuCallback* cb; - enum { maxEntries = 64 }; - char* text[maxEntries]; - long id[maxEntries]; - bool checked[maxEntries]; - int nEntries; - int highlight; -}; - -#endif diff --git a/unix/tx/TXMsgBox.h b/unix/tx/TXMsgBox.h deleted file mode 100644 index ff84e6ae..00000000 --- a/unix/tx/TXMsgBox.h +++ /dev/null @@ -1,112 +0,0 @@ -/* Copyright (C) 2002-2005 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. - */ -// -// TXMsgBox.h -// -// A TXMsgBox is a specialised pop-up dialog window, designed to present -// the user with a small amount of textual information, and potentially to -// obtain their response. -// TXMsgBoxes are always modal, and may have an Ok button, Ok+Cancel buttons, -// or Yes+No buttons. -// The MsgBox helper function creates a TXMsgBox on the fly, runs it, and -// returns the result. -// - -#ifndef __TXMSGBOX_H__ -#define __TXMSGBOX_H__ - -#include "TXDialog.h" -#include "TXLabel.h" -#include "TXButton.h" - -enum TXMsgBoxFlags { - MB_OK = 0, - MB_OKCANCEL = 1, - MB_YESNO = 4, - MB_ICONERROR = 0x10, - MB_ICONQUESTION = 0x20, - MB_ICONWARNING = 0x30, - MB_ICONINFORMATION = 0x40, - MB_DEFBUTTON1 = 0, - MB_DEFBUTTON2 = 0x100 -}; - -class TXMsgBox : public TXDialog, public TXButtonCallback { -public: - TXMsgBox(Display* dpy, const char* text, unsigned int flags, const char* title=0) - : TXDialog(dpy, 1, 1, "Message", true), - textLabel(dpy, "", this), - okButton(dpy, "OK", this, this, 60), - cancelButton(dpy, "Cancel", this, this, 60) - { - textLabel.xPad = 8; - textLabel.move(0, yPad*4); - textLabel.setText(text); - resize(textLabel.width(), - textLabel.height() + okButton.height() + yPad*12); - - switch (flags & 0x30) { - case MB_ICONERROR: - toplevel("Error", this); break; - case MB_ICONQUESTION: - toplevel("Question", this); break; - case MB_ICONWARNING: - toplevel("Warning", this); break; - case MB_ICONINFORMATION: - toplevel("Information", this); break; - default: - if (title) - toplevel(title, this); - break; - }; - - switch (flags & 0x7) { - default: - okButton.move((width() - okButton.width()) / 2, - height() - yPad*4 - okButton.height()); - cancelButton.unmap(); - break; - case MB_OKCANCEL: - case MB_YESNO: - - okButton.move(((width()/2) - okButton.width()) / 2, - height() - yPad*4 - okButton.height()); - cancelButton.move(((width()*3/2) - cancelButton.width()) / 2, - height() - yPad*4 - cancelButton.height()); - if ((flags & 0x7) == MB_YESNO) { - okButton.setText("Yes"); - cancelButton.setText("No"); - } - break; - }; - - setBorderWidth(1); - } - - virtual void buttonActivate(TXButton* b) { - ok = (b == &okButton); - done = true; - unmap(); - } - - TXLabel textLabel; - TXButton okButton; - TXButton cancelButton; -}; - -#endif diff --git a/unix/tx/TXScrollbar.cxx b/unix/tx/TXScrollbar.cxx deleted file mode 100644 index 47e124c3..00000000 --- a/unix/tx/TXScrollbar.cxx +++ /dev/null @@ -1,119 +0,0 @@ -/* Copyright (C) 2002-2005 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. - */ -// -// TXScrollbar.cxx -// - -#include "TXScrollbar.h" -#include <stdio.h> -#include <assert.h> - -TXScrollbar::TXScrollbar(Display* dpy_, int width, int height, bool vert, - TXScrollbarCallback* cb_, TXWindow* parent_) - : TXWindow(dpy_, width, height, parent_), cb(cb_), vertical(vert), - clickedInThumb(false) -{ - setEventHandler(this); - gc = XCreateGC(dpy, win(), 0, 0); - addEventMask(ExposureMask | ButtonPressMask | ButtonReleaseMask | - ButtonMotionMask); - setBg(scrollbarBg); - limit[0] = len[0] = limit[1] = len[1] = 1; - start[0] = start[1] = 0; -} - -TXScrollbar::~TXScrollbar() -{ - XFreeGC(dpy, gc); -} - -void TXScrollbar::set(int limit_, int start_, int len_, bool vert) -{ - assert(limit_ > 0 && len_ >= 0 && len_ <= limit_); - - if (start_ < 0) start_ = 0; - if (start_ > limit_ - len_) start_ = limit_ - len_; - - if (limit[vert] != limit_ || start[vert] != start_ || len[vert] != len_) { - limit[vert] = limit_; - start[vert] = start_; - len[vert] = len_; - paint(); - } -} - -void TXScrollbar::paint() -{ - int x = scaleToBarX(start[0]); - int y = scaleToBarY(start[1]); - int w = scaleToBarX(len[0]); - int h = scaleToBarY(len[1]); - if (y > 0) XClearArea(dpy, win(), 0, 0, 0, y, false); - if (x > 0) XClearArea(dpy, win(), 0, y, x, y+h, false); - XClearArea(dpy, win(), x+w, y, 0, y+h, false); - XClearArea(dpy, win(), 0, y+h, 0, 0, false); - drawBevel(gc, x, y, w, h, bevel, defaultBg, lightBg, darkBg); -} - -void TXScrollbar::handleEvent(TXWindow* w, XEvent* ev) -{ - switch (ev->type) { - case Expose: - paint(); - break; - - case ButtonPress: - { - xDown = ev->xbutton.x; - yDown = ev->xbutton.y; - xStart = start[0]; - yStart = start[1]; - bool clickedInThumbX = false; - if (xDown < scaleToBarX(start[0])) { - set(limit[0], start[0] - len[0], len[0], false); - } else if (xDown >= scaleToBarX(start[0]+len[0])) { - set(limit[0], start[0] + len[0], len[0], false); - } else { - clickedInThumbX = true; - } - bool clickedInThumbY = false; - if (yDown < scaleToBarY(start[1])) { - set(limit[1], start[1] - len[1], len[1], true); - } else if (yDown >= scaleToBarY(start[1]+len[1])) { - set(limit[1], start[1] + len[1], len[1], true); - } else { - clickedInThumbY = true; - } - clickedInThumb = clickedInThumbX && clickedInThumbY; - if (cb) cb->scrollbarPos(start[0], start[1], this); - } - break; - - case ButtonRelease: - case MotionNotify: - while (XCheckTypedWindowEvent(dpy, win(), MotionNotify, ev)); - if (clickedInThumb) { - int dx = ev->xmotion.x - xDown; - int dy = ev->xmotion.y - yDown; - set(limit[0], xStart + barToScaleX(dx), len[0], false); - set(limit[1], yStart + barToScaleY(dy), len[1], true); - if (cb) cb->scrollbarPos(start[0], start[1], this); - } - break; - } -} diff --git a/unix/tx/TXScrollbar.h b/unix/tx/TXScrollbar.h deleted file mode 100644 index 87fec3d8..00000000 --- a/unix/tx/TXScrollbar.h +++ /dev/null @@ -1,82 +0,0 @@ -/* Copyright (C) 2002-2005 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. - */ -// -// TXScrollbar.h -// -// A TXScrollbar represents a range of values starting at start, of length len, -// between zero and limit. The vertical argument to the constructor says -// whether the scrollbar is horizontal or vertical. -// -// In fact it can represent a range in each dimension but usually one of the -// dimensions is fixed, according to the vertical flag (for a vertical -// scrollbar, the horizontal dimension is fixed, and vice-versa). -// -// The TXScrollbarCallback argument is an object which will be notified when -// the user has attempted to move the scrollbar. The x and y arguments to the -// scrollbarPos() method give the start values in the respective dimensions. -// They are guaranteed to be between 0 and limit-len. -// - -#ifndef __TXSCROLLBAR_H__ -#define __TXSCROLLBAR_H__ - -#include "TXWindow.h" - -class TXScrollbarCallback; - -class TXScrollbar : public TXWindow, public TXEventHandler { -public: - TXScrollbar(Display* dpy_, int width=1, int height=1, bool vertical=false, - TXScrollbarCallback* cb=0, TXWindow* parent_=0); - virtual ~TXScrollbar(); - - // set() sets the limit, start and length of the range represented by the - // scrollbar. The values of limit and len passed in must be valid - // (i.e. limit > 0 and 0 <= len <= limit). Values of start are clipped to - // the range 0 to limit-len. - void set(int limit, int start, int len) { set(limit, start, len, vertical); } - - // set() with an extra argument vert can be used to represent a range in both - // dimensions simultaneously. - void set(int limit, int start, int len, bool vert); - - virtual void handleEvent(TXWindow* w, XEvent* ev); - -private: - int scaleToBarX(int x) { return (x * width() + limit[0]/2) / limit[0]; } - int scaleToBarY(int y) { return (y * height() + limit[1]/2) / limit[1]; } - int barToScaleX(int x) { return (x * limit[0] + width()/2) / width(); } - int barToScaleY(int y) { return (y * limit[1] + height()/2) / height(); } - void paint(); - - GC gc; - TXScrollbarCallback* cb; - int limit[2]; - int start[2]; - int len[2]; - int xDown, yDown; - int xStart, yStart; - bool vertical; - bool clickedInThumb; -}; - -class TXScrollbarCallback { -public: - virtual void scrollbarPos(int x, int y, TXScrollbar* sb)=0; -}; -#endif diff --git a/unix/tx/TXViewport.cxx b/unix/tx/TXViewport.cxx deleted file mode 100644 index 60648933..00000000 --- a/unix/tx/TXViewport.cxx +++ /dev/null @@ -1,189 +0,0 @@ -/* Copyright (C) 2002-2005 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. - */ -// -// TXViewport.cxx -// - -#include "TXViewport.h" -#include <stdio.h> - -TXViewport::TXViewport(Display* dpy_, int w, int h, TXWindow* parent_) - : TXWindow(dpy_, w, h, parent_), child(0), hScrollbar(0), - vScrollbar(0), scrollbarSize(15), xOff(0), yOff(0), bumpScrollTimer(this), - bumpScroll(false), needXScrollbar(false), needYScrollbar(false), - bumpScrollX(0), bumpScrollY(0) -{ - clipper = new TXWindow(dpy, width()-scrollbarSize, height()-scrollbarSize, - this); - clipper->setBg(black); - hScrollbar = new TXScrollbar(dpy, width()-scrollbarSize, scrollbarSize, - false, this, this); - vScrollbar = new TXScrollbar(dpy, scrollbarSize, height()-scrollbarSize, - true, this, this); -} - -TXViewport::~TXViewport() -{ - delete clipper; - delete hScrollbar; - delete vScrollbar; -} - -void TXViewport::setChild(TXWindow* child_) -{ - child = child_; - XReparentWindow(dpy, child->win(), clipper->win(), 0, 0); - xOff = yOff = 0; - child->map(); - resizeNotify(); -} - -bool TXViewport::setOffset(int x, int y) -{ - if (clipper->width() >= child->width()) { - x = (clipper->width() - child->width()) / 2; - } else { - if (x > 0) x = 0; - if (x + child->width() < clipper->width()) - x = clipper->width() - child->width(); - } - - if (clipper->height() >= child->height()) { - y = (clipper->height() - child->height()) / 2; - } else { - if (y > 0) y = 0; - if (y + child->height() < clipper->height()) - y = clipper->height() - child->height(); - } - - if (x != xOff || y != yOff) { - xOff = x; - yOff = y; - child->move(xOff, yOff); - return true; - } - - return false; -} - -void TXViewport::setBumpScroll(bool b) -{ - bumpScroll = b; - resizeNotify(); -} - -// Note: bumpScrollEvent() only works if the viewport is positioned at 0,0 and -// is the same width and height as the screen. -bool TXViewport::bumpScrollEvent(XMotionEvent* ev) -{ - if (!bumpScroll) return false; - int bumpScrollPixels = 20; - bumpScrollX = bumpScrollY = 0; - - if (ev->x_root == width()-1) bumpScrollX = -bumpScrollPixels; - else if (ev->x_root == 0) bumpScrollX = bumpScrollPixels; - if (ev->y_root == height()-1) bumpScrollY = -bumpScrollPixels; - else if (ev->y_root == 0) bumpScrollY = bumpScrollPixels; - - if (bumpScrollX || bumpScrollY) { - if (bumpScrollTimer.isStarted()) return true; - if (setOffset(xOff + bumpScrollX, yOff + bumpScrollY)) { - bumpScrollTimer.start(25); - return true; - } - } - - bumpScrollTimer.stop(); - return false; -} - -bool TXViewport::handleTimeout(rfb::Timer* timer) { - return setOffset(xOff + bumpScrollX, yOff + bumpScrollY); -} - -void TXViewport::resizeNotify() -{ - int winMaxWidth, winMaxHeight; - - winMaxWidth = child->width(); - winMaxHeight = child->height(); - - needXScrollbar = false; - needYScrollbar = false; - if (!bumpScroll && height() > scrollbarSize && width() > scrollbarSize) { - needXScrollbar = (width() < child->width()); - needYScrollbar = (height() < child->height()); - // Adding an horizontal scrollbar occupies space, which might cause the - // need to add a vertical scrollbar, and vice-versa. These additional - // checks should solve this problem - if (needXScrollbar && (height() - scrollbarSize < child->height())) - needYScrollbar = true; - if (needYScrollbar && (width() - scrollbarSize < child->width())) - needXScrollbar = true; - } - - if (needXScrollbar) - winMaxHeight += scrollbarSize; - if (needYScrollbar) - winMaxWidth += scrollbarSize; - setMaxSize(winMaxWidth, winMaxHeight); - - if (needXScrollbar && needYScrollbar) { - clipper->resize(width()-scrollbarSize, height()-scrollbarSize); - hScrollbar->map(); - vScrollbar->map(); - } else if (needXScrollbar) { - clipper->resize(width(), height()-scrollbarSize); - hScrollbar->map(); - vScrollbar->unmap(); - } else if (needYScrollbar) { - clipper->resize(width()-scrollbarSize, height()); - hScrollbar->unmap(); - vScrollbar->map(); - } else { - clipper->resize(width(), height()); - hScrollbar->unmap(); - vScrollbar->unmap(); - } - - setOffset(xOff, yOff); - - if (needXScrollbar) { - hScrollbar->move(0, height()-scrollbarSize); - hScrollbar->resize(width()-scrollbarSize, scrollbarSize); - hScrollbar->set(child->width(), -xOff, width()-scrollbarSize); - } - - if (needYScrollbar) { - vScrollbar->move(width()-scrollbarSize, 0); - vScrollbar->resize(scrollbarSize, height()-scrollbarSize); - vScrollbar->set(child->height(), -yOff, height()-scrollbarSize); - } -} - -void TXViewport::scrollbarPos(int x, int y, TXScrollbar* sb) -{ - if (sb == hScrollbar) { - x = -x; - y = yOff; - } else { - x = xOff; - y = -y; - } - setOffset(x, y); -} diff --git a/unix/tx/TXViewport.h b/unix/tx/TXViewport.h deleted file mode 100644 index 823d67af..00000000 --- a/unix/tx/TXViewport.h +++ /dev/null @@ -1,78 +0,0 @@ -/* Copyright (C) 2002-2005 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. - */ -// -// TXViewport.h -// -// A TXViewport allows a large window to be viewed by adding scrollbars to the -// right and bottom if necessary. It also has a bump-scroll mode where there -// are no scrollbars, and scrolling is achieved by bumping up against the edge -// of the screen instead. Note that this only works when the viewport fills -// the entire screen. If the child window is smaller than the viewport, it is -// always positioned centrally in the viewport. - -#ifndef __TXVIEWPORT_H__ -#define __TXVIEWPORT_H__ - -#include <rfb/Timer.h> -#include "TXWindow.h" -#include "TXScrollbar.h" - -class TXViewport : public TXWindow, public TXScrollbarCallback, - public rfb::Timer::Callback { -public: - TXViewport(Display* dpy_, int width, int height, TXWindow* parent_=0); - virtual ~TXViewport(); - - // setChild() sets the child window which is to be viewed in the viewport. - void setChild(TXWindow* child_); - - // setOffset() sets the position of the child in the viewport. Note that the - // offsets are negative. For example when the offset is (-100,-30), position - // (100,30) in the child window is at the top-left of the viewport. The - // offsets given are clipped to keep the child window filling the viewport - // (except where the child window is smaller than the viewport, in which case - // it is always positioned centrally in the viewport). It returns true if - // the child was repositioned. - bool setOffset(int x, int y); - - // setBumpScroll() puts the viewport in bump-scroll mode. - void setBumpScroll(bool b); - - // bumpScrollEvent() can be called with a MotionNotify event which may - // potentially be against the edge of the screen. It returns true if the - // event was used for bump-scrolling, false if it should be processed - // normally. - bool bumpScrollEvent(XMotionEvent* ev); - -private: - virtual void resizeNotify(); - virtual void scrollbarPos(int x, int y, TXScrollbar* sb); - virtual bool handleTimeout(rfb::Timer* timer); - TXWindow* clipper; - TXWindow* child; - TXScrollbar* hScrollbar; - TXScrollbar* vScrollbar; - const int scrollbarSize; - int xOff, yOff; - rfb::Timer bumpScrollTimer; - bool bumpScroll; - bool needXScrollbar; - bool needYScrollbar; - int bumpScrollX, bumpScrollY; -}; -#endif diff --git a/unix/x0vncserver/XPixelBuffer.cxx b/unix/x0vncserver/XPixelBuffer.cxx index f691c576..aa52620a 100644 --- a/unix/x0vncserver/XPixelBuffer.cxx +++ b/unix/x0vncserver/XPixelBuffer.cxx @@ -1,4 +1,5 @@ /* Copyright (C) 2007-2008 Constantin Kaplinsky. All Rights Reserved. + * Copyright 2014 Pierre Ossman for Cendio AB * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -38,16 +39,16 @@ XPixelBuffer::XPixelBuffer(Display *dpy, ImageFactory &factory, m_stride(0) { // Fill in the PixelFormat structure of the parent class. - format.bpp = m_image->xim->bits_per_pixel; - format.depth = m_image->xim->depth; - format.bigEndian = (m_image->xim->byte_order == MSBFirst); - format.trueColour = m_image->isTrueColor(); - format.redShift = ffs(m_image->xim->red_mask) - 1; - format.greenShift = ffs(m_image->xim->green_mask) - 1; - format.blueShift = ffs(m_image->xim->blue_mask) - 1; - format.redMax = m_image->xim->red_mask >> format.redShift; - format.greenMax = m_image->xim->green_mask >> format.greenShift; - format.blueMax = m_image->xim->blue_mask >> format.blueShift; + format = PixelFormat(m_image->xim->bits_per_pixel, + m_image->xim->depth, + (m_image->xim->byte_order == MSBFirst), + m_image->isTrueColor(), + m_image->xim->red_mask >> (ffs(m_image->xim->red_mask) - 1), + m_image->xim->green_mask >> (ffs(m_image->xim->green_mask) - 1), + m_image->xim->blue_mask >> (ffs(m_image->xim->blue_mask) - 1), + ffs(m_image->xim->red_mask) - 1, + ffs(m_image->xim->green_mask) - 1, + ffs(m_image->xim->blue_mask) - 1); // Set up the remaining data of the parent class. width_ = rect.width(); diff --git a/vncviewer/CConn.cxx b/vncviewer/CConn.cxx index f97b0f4c..789cf09e 100644 --- a/vncviewer/CConn.cxx +++ b/vncviewer/CConn.cxx @@ -44,6 +44,7 @@ #include "CConn.h" #include "OptionsDialog.h" +#include "DesktopWindow.h" #include "i18n.h" #include "parameters.h" #include "vncviewer.h" @@ -88,11 +89,15 @@ CConn::CConn(const char* vncServerName, network::Socket* socket=NULL) cp.supportsExtendedDesktopSize = true; cp.supportsDesktopRename = true; - cp.customCompressLevel = customCompressLevel; - cp.compressLevel = compressLevel; + if (customCompressLevel) + cp.compressLevel = compressLevel; + else + cp.compressLevel = -1; - cp.noJpeg = noJpeg; - cp.qualityLevel = qualityLevel; + if (!noJpeg) + cp.qualityLevel = qualityLevel; + else + cp.qualityLevel = -1; if(sock == NULL) { try { @@ -394,14 +399,17 @@ void CConn::fillRect(const rfb::Rect& r, rfb::Pixel p) { desktop->fillRect(r,p); } + void CConn::imageRect(const rfb::Rect& r, void* p) { desktop->imageRect(r,p); } + void CConn::copyRect(const rfb::Rect& r, int sx, int sy) { desktop->copyRect(r,sx,sy); } + void CConn::setCursor(int width, int height, const Point& hotspot, void* data, void* mask) { @@ -443,10 +451,10 @@ void CConn::fence(rdr::U32 flags, unsigned len, const char data[]) } } -rdr::U8* CConn::getRawPixelsRW(const rfb::Rect& r, int* stride) { - return desktop->getPixelsRW(r, stride); +rdr::U8* CConn::getRawBufferRW(const rfb::Rect& r, int* stride) { + return desktop->getBufferRW(r, stride); } -void CConn::releaseRawPixels(const rfb::Rect& r) { +void CConn::releaseRawBuffer(const rfb::Rect& r) { desktop->damageRect(r); } @@ -615,16 +623,19 @@ void CConn::handleOptions(void *data) if (encNum != -1) self->currentEncoding = encNum; - - self->cp.qualityLevel = qualityLevel; } self->cp.supportsLocalCursor = true; - self->cp.customCompressLevel = customCompressLevel; - self->cp.compressLevel = compressLevel; + if (customCompressLevel) + self->cp.compressLevel = compressLevel; + else + self->cp.compressLevel = -1; - self->cp.noJpeg = noJpeg; + if (!noJpeg && !autoSelect) + self->cp.qualityLevel = qualityLevel; + else + self->cp.qualityLevel = -1; self->encodingChange = true; diff --git a/vncviewer/CConn.h b/vncviewer/CConn.h index 24fbbab4..286a09ed 100644 --- a/vncviewer/CConn.h +++ b/vncviewer/CConn.h @@ -20,10 +20,12 @@ #ifndef __CCONN_H__ #define __CCONN_H__ +#include <FL/Fl.H> + #include <rfb/CConnection.h> #include <network/Socket.h> -#include "DesktopWindow.h" +class DesktopWindow; class CConn : public rfb::CConnection, public rdr::FdInStreamBlockCallback @@ -67,8 +69,8 @@ public: void imageRect(const rfb::Rect& r, void* p); void copyRect(const rfb::Rect& r, int sx, int sy); - rdr::U8* getRawPixelsRW(const rfb::Rect& r, int* stride); - void releaseRawPixels(const rfb::Rect& r); + rdr::U8* getRawBufferRW(const rfb::Rect& r, int* stride); + void releaseRawBuffer(const rfb::Rect& r); const rfb::PixelFormat &getPreferredPF() { return fullColourPF; } diff --git a/vncviewer/DesktopWindow.cxx b/vncviewer/DesktopWindow.cxx index 40d08ae2..2a2f8734 100644 --- a/vncviewer/DesktopWindow.cxx +++ b/vncviewer/DesktopWindow.cxx @@ -34,7 +34,9 @@ #include "parameters.h" #include "vncviewer.h" #include "CConn.h" +#include "Viewport.h" +#include <FL/Fl.H> #include <FL/Fl_Scroll.H> #include <FL/x.H> @@ -220,6 +222,26 @@ void DesktopWindow::setColourMapEntries(int firstColour, int nColours, viewport->setColourMapEntries(firstColour, nColours, rgbs); } +void DesktopWindow::fillRect(const rfb::Rect& r, rfb::Pixel pix) { + viewport->fillRect(r, pix); +} + +void DesktopWindow::imageRect(const rfb::Rect& r, void* pixels) { + viewport->imageRect(r, pixels); +} + +void DesktopWindow::copyRect(const rfb::Rect& r, int srcX, int srcY) { + viewport->copyRect(r, srcX, srcY); +} + +rdr::U8* DesktopWindow::getBufferRW(const rfb::Rect& r, int* stride) { + return viewport->getBufferRW(r, stride); +} + +void DesktopWindow::damageRect(const rfb::Rect& r) { + viewport->damageRect(r); +} + // Copy the areas of the framebuffer that have been changed (damaged) // to the displayed window. diff --git a/vncviewer/DesktopWindow.h b/vncviewer/DesktopWindow.h index 78d9bf79..06f25f55 100644 --- a/vncviewer/DesktopWindow.h +++ b/vncviewer/DesktopWindow.h @@ -23,13 +23,13 @@ #include <map> #include <rfb/Rect.h> +#include <rfb/Pixel.h> -#include "Viewport.h" - -#include <FL/Fl.H> #include <FL/Fl_Window.H> class CConn; +class Viewport; + class Fl_Scroll; class DesktopWindow : public Fl_Window { @@ -52,22 +52,12 @@ public: void setColourMapEntries(int firstColour, int nColours, rdr::U16* rgbs); - void fillRect(const rfb::Rect& r, rfb::Pixel pix) { - viewport->fillRect(r, pix); - } - void imageRect(const rfb::Rect& r, void* pixels) { - viewport->imageRect(r, pixels); - } - void copyRect(const rfb::Rect& r, int srcX, int srcY) { - viewport->copyRect(r, srcX, srcY); - } - - rdr::U8* getPixelsRW(const rfb::Rect& r, int* stride) { - return viewport->getPixelsRW(r, stride); - } - void damageRect(const rfb::Rect& r) { - viewport->damageRect(r); - } + void fillRect(const rfb::Rect& r, rfb::Pixel pix); + void imageRect(const rfb::Rect& r, void* pixels); + void copyRect(const rfb::Rect& r, int srcX, int srcY); + + rdr::U8* getBufferRW(const rfb::Rect& r, int* stride); + void damageRect(const rfb::Rect& r); void resizeFramebuffer(int new_w, int new_h); diff --git a/vncviewer/OptionsDialog.cxx b/vncviewer/OptionsDialog.cxx index df9f3554..e21f2dd3 100644 --- a/vncviewer/OptionsDialog.cxx +++ b/vncviewer/OptionsDialog.cxx @@ -41,7 +41,11 @@ #include <FL/Fl_Tabs.H> #include <FL/Fl_Button.H> +#include <FL/Fl_Check_Button.H> #include <FL/Fl_Return_Button.H> +#include <FL/Fl_Round_Button.H> +#include <FL/Fl_Int_Input.H> +#include <FL/Fl_Choice.H> using namespace std; using namespace rdr; diff --git a/vncviewer/OptionsDialog.h b/vncviewer/OptionsDialog.h index b3ac0156..a6b504e9 100644 --- a/vncviewer/OptionsDialog.h +++ b/vncviewer/OptionsDialog.h @@ -22,11 +22,14 @@ #include <map> #include <FL/Fl_Window.H> -#include <FL/Fl_Group.H> -#include <FL/Fl_Check_Button.H> -#include <FL/Fl_Round_Button.H> -#include <FL/Fl_Int_Input.H> -#include <FL/Fl_Choice.H> + +class Fl_Widget; +class Fl_Group; +class Fl_Check_Button; +class Fl_Round_Button; +class Fl_Input; +class Fl_Int_Input; +class Fl_Choice; typedef void (OptionsCallback)(void*); diff --git a/vncviewer/ServerDialog.h b/vncviewer/ServerDialog.h index e023659c..7926849a 100644 --- a/vncviewer/ServerDialog.h +++ b/vncviewer/ServerDialog.h @@ -20,8 +20,9 @@ #define __SERVERDIALOG_H__ #include <FL/Fl_Window.H> -#include <FL/Fl_Input.H> -#include <FL/Fl_File_Chooser.H> + +class Fl_Widget; +class Fl_Input; class ServerDialog : public Fl_Window { protected: diff --git a/vncviewer/Viewport.cxx b/vncviewer/Viewport.cxx index 4b8a85b0..0ac76024 100644 --- a/vncviewer/Viewport.cxx +++ b/vncviewer/Viewport.cxx @@ -27,6 +27,7 @@ #include <rfb/CMsgWriter.h> #include <rfb/LogWriter.h> +#include <rfb/PixelTransformer.h> // FLTK can pull in the X11 headers on some systems #ifndef XK_VoidSymbol @@ -42,6 +43,7 @@ #include "Viewport.h" #include "CConn.h" #include "OptionsDialog.h" +#include "DesktopWindow.h" #include "i18n.h" #include "fltk_layout.h" #include "parameters.h" @@ -49,9 +51,25 @@ #include "menukey.h" #include "vncviewer.h" +#if defined(WIN32) +#include "Win32PixelBuffer.h" +#elif defined(__APPLE__) +#include "OSXPixelBuffer.h" +#else +#include "X11PixelBuffer.h" +#endif + +// We also have a generic version of the above, using pure FLTK: +// +// #include "PlatformPixelBuffer.h" +// + #include <FL/fl_draw.H> #include <FL/fl_ask.H> +#include <FL/Fl_Menu.H> +#include <FL/Fl_Menu_Button.H> + #ifdef WIN32 #include "win32.h" #endif @@ -209,6 +227,48 @@ void Viewport::updateWindow() damage.clear(); } +void Viewport::fillRect(const rfb::Rect& r, rfb::Pixel pix) { + if (pixelTrans) { + rfb::Pixel pix2; + if (colourMapChange) + commitColourMap(); + pixelTrans->translatePixels(&pix, &pix2, 1); + pix = pix2; + } + + frameBuffer->fillRect(r, pix); + damageRect(r); +} + +void Viewport::imageRect(const rfb::Rect& r, void* pixels) { + if (pixelTrans) { + if (colourMapChange) + commitColourMap(); + pixelTrans->translateRect(pixels, r.width(), + rfb::Rect(0, 0, r.width(), r.height()), + frameBuffer->data, frameBuffer->getStride(), + r.tl); + } else { + frameBuffer->imageRect(r, pixels); + } + damageRect(r); +} + +void Viewport::copyRect(const rfb::Rect& r, int srcX, int srcY) { + frameBuffer->copyRect(r, rfb::Point(r.tl.x-srcX, r.tl.y-srcY)); + damageRect(r); +} + +rdr::U8* Viewport::getBufferRW(const rfb::Rect& r, int* stride) { + return frameBuffer->getBufferRW(r, stride); +} + +void Viewport::damageRect(const rfb::Rect& r) { + damage.assign_union(rfb::Region(r)); + if (!Fl::has_timeout(handleUpdateTimeout, this)) + Fl::add_timeout(0.500, handleUpdateTimeout, this); +}; + #ifdef HAVE_FLTK_CURSOR static const char * dotcursor_xpm[] = { "5 5 2 1", @@ -931,7 +991,7 @@ void Viewport::popupContextMenu() // Back to our proper mouse pointer. #ifdef HAVE_FLTK_CURSOR - if (Fl::belowmouse() == this) + if ((Fl::belowmouse() == this) && cursor) window()->cursor(cursor, cursorHotspot.x, cursorHotspot.y); #endif diff --git a/vncviewer/Viewport.h b/vncviewer/Viewport.h index c66c19a0..e83a14ba 100644 --- a/vncviewer/Viewport.h +++ b/vncviewer/Viewport.h @@ -22,31 +22,19 @@ #include <map> -#include <FL/Fl.H> #include <FL/Fl_Widget.H> -#include <FL/Fl_Menu_Button.H> -#include <FL/Fl_RGB_Image.H> -#include <rfb/Rect.h> #include <rfb/Region.h> -#include <rfb/Timer.h> -#include <rfb/PixelBuffer.h> -#include <rfb/PixelTransformer.h> - -#if defined(WIN32) -#include "Win32PixelBuffer.h" -#elif defined(__APPLE__) -#include "OSXPixelBuffer.h" -#else -#include "X11PixelBuffer.h" -#endif +#include <rfb/Pixel.h> +#include <rfb/ColourMap.h> + +class Fl_Menu_Button; +class Fl_RGB_Image; -// We also have a generic version of the above, using pure FLTK: -// -// #include "PlatformPixelBuffer.h" -// +namespace rfb { class PixelTransformer; } class CConn; +class PlatformPixelBuffer; class Viewport : public Fl_Widget { public: @@ -63,49 +51,16 @@ public: void updateWindow(); // Methods forwarded from CConn - void setName(const char *name); void setColourMapEntries(int firstColour, int nColours, rdr::U16* rgbs); - void fillRect(const rfb::Rect& r, rfb::Pixel pix) { - if (pixelTrans) { - rfb::Pixel pix2; - if (colourMapChange) - commitColourMap(); - pixelTrans->translatePixels(&pix, &pix2, 1); - pix = pix2; - } - - frameBuffer->fillRect(r, pix); - damageRect(r); - } - void imageRect(const rfb::Rect& r, void* pixels) { - if (pixelTrans) { - if (colourMapChange) - commitColourMap(); - pixelTrans->translateRect(pixels, r.width(), - rfb::Rect(0, 0, r.width(), r.height()), - frameBuffer->data, frameBuffer->getStride(), - r.tl); - } else { - frameBuffer->imageRect(r, pixels); - } - damageRect(r); - } - void copyRect(const rfb::Rect& r, int srcX, int srcY) { - frameBuffer->copyRect(r, rfb::Point(r.tl.x-srcX, r.tl.y-srcY)); - damageRect(r); - } - - rdr::U8* getPixelsRW(const rfb::Rect& r, int* stride) { - return frameBuffer->getPixelsRW(r, stride); - } - - void damageRect(const rfb::Rect& r) { - damage.assign_union(rfb::Region(r)); - if (!Fl::has_timeout(handleUpdateTimeout, this)) - Fl::add_timeout(0.500, handleUpdateTimeout, this); - }; + void fillRect(const rfb::Rect& r, rfb::Pixel pix); + void imageRect(const rfb::Rect& r, void* pixels); + void copyRect(const rfb::Rect& r, int srcX, int srcY); + + rdr::U8* getBufferRW(const rfb::Rect& r, int* stride); + + void damageRect(const rfb::Rect& r); void setCursor(int width, int height, const rfb::Point& hotspot, void* data, void* mask); diff --git a/vncviewer/Win32PixelBuffer.h b/vncviewer/Win32PixelBuffer.h index ae2b71ac..7d91e09d 100644 --- a/vncviewer/Win32PixelBuffer.h +++ b/vncviewer/Win32PixelBuffer.h @@ -19,6 +19,8 @@ #ifndef __WIN32PIXELBUFFER_H__ #define __WIN32PIXELBUFFER_H__ +#include <windows.h> + #include <rfb/PixelBuffer.h> class PlatformPixelBuffer: public rfb::FullFramePixelBuffer { diff --git a/win/rfb_win32/CKeyboard.cxx b/win/rfb_win32/CKeyboard.cxx deleted file mode 100644 index 408e483a..00000000 --- a/win/rfb_win32/CKeyboard.cxx +++ /dev/null @@ -1,285 +0,0 @@ -/* Copyright (C) 2002-2005 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 <map> - -#define XK_MISCELLANY -#define XK_LATIN1 -#define XK_CURRENCY -#include <rfb/keysymdef.h> - -#include <rfb_win32/CKeyboard.h> -#include <rfb/LogWriter.h> -#include <rfb_win32/OSVersion.h> -#include "keymap.h" - -using namespace rfb; - -static LogWriter vlog("CKeyboard"); - - -// Client-side RFB keyboard event sythesis - -class CKeymapper { - -public: - CKeymapper() - { - for (unsigned int i = 0; i < sizeof(keymap) / sizeof(keymap_t); i++) { - int extendedVkey = keymap[i].vk + (keymap[i].extended ? 256 : 0); - if (keysymMap.find(extendedVkey) == keysymMap.end()) { - keysymMap[extendedVkey] = keymap[i].keysym; - } - } - } - - // lookup() tries to find a match for vkey with the extended flag. We check - // first for an exact match including the extended flag, then try without the - // extended flag. - rdr::U32 lookup(int extendedVkey) { - - // There's no real definition of the meaning of - // VK_SEPARATOR/XK_KP_Separator or VK_DECIMAL/XK_KP_Decimal. As - // http://blogs.msdn.com/michkap/archive/2006/09/13/752377.aspx - // puts it: "As for what is actually assigned to VK_DECIMAL, that - // is something that for every keyboard is either defined in a - // standard or decided by the person/people who submitted the - // keyboard layout. It may match the locale's preferences or it - // may not". In a VNC context, we are considering a SEPARATOR to - // be a comma and a DECIMAL to be a dot. - if (extendedVkey == VK_DECIMAL || extendedVkey == VK_SEPARATOR) { - char buf[4]; - if (!GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, (LPTSTR) buf, - sizeof(buf) / sizeof(TCHAR))) { - vlog.debug("failed to retrieve LOCALE_SDECIMAL"); - } else { - switch (buf[0]) { - case ',': - extendedVkey = VK_SEPARATOR; - break; - case '.': - extendedVkey = VK_DECIMAL; - break; - } - } - } - - if (keysymMap.find(extendedVkey) != keysymMap.end()) - return keysymMap[extendedVkey]; - if (keysymMap.find(extendedVkey ^ 256) != keysymMap.end()) - return keysymMap[extendedVkey ^ 256]; - return 0; - } - -private: - std::map<int,rdr::U32> keysymMap; -} ckeymapper; - - -class ModifierKeyReleaser { -public: - ModifierKeyReleaser(InputHandler* writer_, int vkCode, bool extended) - : writer(writer_), extendedVkey(vkCode + (extended ? 256 : 0)), - keysym(0) - {} - void release(std::map<int,rdr::U32>* downKeysym) { - if (downKeysym->find(extendedVkey) != downKeysym->end()) { - keysym = (*downKeysym)[extendedVkey]; - vlog.debug("fake release extendedVkey 0x%x, keysym 0x%x", - extendedVkey, keysym); - writer->keyEvent(keysym, false); - } - } - ~ModifierKeyReleaser() { - if (keysym) { - vlog.debug("fake press extendedVkey 0x%x, keysym 0x%x", - extendedVkey, keysym); - writer->keyEvent(keysym, true); - } - } - InputHandler* writer; - int extendedVkey; - rdr::U32 keysym; -}; - -// IS_PRINTABLE_LATIN1 tests if a character is either a printable latin1 -// character, or 128, which is the Euro symbol on Windows. -#define IS_PRINTABLE_LATIN1(c) (((c) >= 32 && (c) <= 126) || (c) == 128 || \ - ((c) >= 160 && (c) <= 255)) - -void win32::CKeyboard::keyEvent(InputHandler* writer, rdr::U8 vkey, - rdr::U32 flags, bool down) -{ - bool extended = (flags & 0x1000000); - int extendedVkey = vkey + (extended ? 256 : 0); - - // If it's a release, just release whichever keysym corresponded to the same - // key being pressed, regardless of how it would be interpreted in the - // current keyboard state. - if (!down) { - releaseKey(writer, extendedVkey); - return; - } - - // We should always pass every down event to ToAscii() otherwise it can get - // out of sync. - - // XXX should we pass CapsLock, ScrollLock or NumLock to ToAscii - they - // actually alter the lock state on the keyboard? - - BYTE keystate[256]; - GetKeyboardState(keystate); - rdr::U8 chars[2]; - - int nchars = ToAscii(vkey, 0, keystate, (WORD*)&chars, 0); - - // See if it's in the Windows VK code -> X keysym map. We do this before - // looking at the result of ToAscii so that e.g. we recognise that it's - // XK_KP_Add rather than '+'. - - rdr::U32 keysym = ckeymapper.lookup(extendedVkey); - if (keysym) { - vlog.debug("mapped key: extendedVkey 0x%x", extendedVkey); - pressKey(writer, extendedVkey, keysym); - return; - } - - if (nchars < 0) { - // Dead key - the next call to ToAscii() will give us either the accented - // character or two characters. - vlog.debug("ToAscii dead key (1): extendedVkey 0x%x", extendedVkey); - return; - } - - if (nchars > 0 && IS_PRINTABLE_LATIN1(chars[0])) { - // Got a printable latin1 character. We must release Control and Alt - // (AltGr) if they were both pressed, so that the latin1 character is seen - // without them by the VNC server. - ModifierKeyReleaser lctrl(writer, VK_CONTROL, 0); - ModifierKeyReleaser rctrl(writer, VK_CONTROL, 1); - ModifierKeyReleaser lalt(writer, VK_MENU, 0); - ModifierKeyReleaser ralt(writer, VK_MENU, 1); - - if ((keystate[VK_CONTROL] & 0x80) && (keystate[VK_MENU] & 0x80)) { - lctrl.release(&downKeysym); - rctrl.release(&downKeysym); - lalt.release(&downKeysym); - ralt.release(&downKeysym); - } - - for (int i = 0; i < nchars; i++) { - vlog.debug("ToAscii key (1): extendedVkey 0x%x", extendedVkey); - if (chars[i] == 128) { // special hack for euro! - pressKey(writer, extendedVkey, XK_EuroSign); - } else { - pressKey(writer, extendedVkey, chars[i]); - } - } - return; - } - - // Either no chars were generated, or something outside the printable - // character range. Try ToAscii() without the Control and Alt keys down to - // see if that yields an ordinary character. - - keystate[VK_CONTROL] = keystate[VK_LCONTROL] = keystate[VK_RCONTROL] = 0; - keystate[VK_MENU] = keystate[VK_LMENU] = keystate[VK_RMENU] = 0; - - nchars = ToAscii(vkey, 0, keystate, (WORD*)&chars, 0); - - if (nchars < 0) { - // So it would be a dead key if neither control nor alt were pressed. - // However, we know that at least one of control and alt must be pressed. - // We can't leave it at this stage otherwise the next call to ToAscii() - // with a valid character will get wrongly interpreted in the context of - // this bogus dead key. Working on the assumption that a dead key followed - // by space usually returns the dead character itself, try calling ToAscii - // with VK_SPACE. - vlog.debug("ToAscii dead key (2): extendedVkey 0x%x", extendedVkey); - nchars = ToAscii(VK_SPACE, 0, keystate, (WORD*)&chars, 0); - if (nchars < 0) { - vlog.debug("ToAscii dead key (3): extendedVkey 0x%x - giving up!", - extendedVkey); - return; - } - } - - if (nchars > 0 && IS_PRINTABLE_LATIN1(chars[0])) { - for (int i = 0; i < nchars; i++) { - vlog.debug("ToAscii key (2) (no ctrl/alt): extendedVkey 0x%x", - extendedVkey); - if (chars[i] == 128) { // special hack for euro! - pressKey(writer, extendedVkey, XK_EuroSign); - } else { - pressKey(writer, extendedVkey, chars[i]); - } - } - return; - } - - vlog.debug("no chars regardless of control and alt: extendedVkey 0x%x", - extendedVkey); -} - -// releaseAllKeys() - write key release events to the server for all keys -// that are currently regarded as being down. -void win32::CKeyboard::releaseAllKeys(InputHandler* writer) { - std::map<int,rdr::U32>::iterator i, next_i; - for (i=downKeysym.begin(); i!=downKeysym.end(); i=next_i) { - next_i = i; next_i++; - writer->keyEvent((*i).second, false); - downKeysym.erase(i); - } -} - -// releaseKey() - write a key up event to the server, but only if we've -// actually sent a key down event for the given key. The key up event always -// contains the same keysym we used in the key down event, regardless of what -// it would look up as using the current keyboard state. -void win32::CKeyboard::releaseKey(InputHandler* writer, int extendedVkey) -{ - if (downKeysym.find(extendedVkey) != downKeysym.end()) { - vlog.debug("release extendedVkey 0x%x, keysym 0x%x", - extendedVkey, downKeysym[extendedVkey]); - writer->keyEvent(downKeysym[extendedVkey], false); - downKeysym.erase(extendedVkey); - } -} - -// pressKey() - write a key down event to the server, and record which keysym -// was sent as corresponding to the given extendedVkey. The only tricky bit is -// that if we are trying to press an extendedVkey which is already marked as -// down but with a different keysym, then we need to release the old keysym -// first. This can happen in two cases: (a) when a single key press results in -// more than one character, and (b) when shift is released while another key is -// autorepeating. -void win32::CKeyboard::pressKey(InputHandler* writer, int extendedVkey, - rdr::U32 keysym) -{ - if (downKeysym.find(extendedVkey) != downKeysym.end()) { - if (downKeysym[extendedVkey] != keysym) { - vlog.debug("release extendedVkey 0x%x, keysym 0x%x", - extendedVkey, downKeysym[extendedVkey]); - writer->keyEvent(downKeysym[extendedVkey], false); - } - } - vlog.debug("press extendedVkey 0x%x, keysym 0x%x", - extendedVkey, keysym); - writer->keyEvent(keysym, true); - downKeysym[extendedVkey] = keysym; -} diff --git a/win/rfb_win32/CKeyboard.h b/win/rfb_win32/CKeyboard.h deleted file mode 100644 index bce886d8..00000000 --- a/win/rfb_win32/CKeyboard.h +++ /dev/null @@ -1,50 +0,0 @@ -/* Copyright (C) 2002-2005 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. - */ - -// -=- CKeyboard.h -// -// Client-side keyboard handling for Win32 - -#ifndef __RFB_WIN32_CKEYBOARD_H__ -#define __RFB_WIN32_CKEYBOARD_H__ - -#include <rfb/InputHandler.h> -#include <map> - -namespace rfb { - - namespace win32 { - - class CKeyboard { - public: - void keyEvent(InputHandler* writer, rdr::U8 vkey, rdr::U32 flags, - bool down); - void releaseAllKeys(InputHandler* writer); - const std::map<int,rdr::U32>& pressedKeys() const {return downKeysym;}; - bool keyPressed(int k) const {return downKeysym.find(k)!=downKeysym.end();} - private: - void releaseKey(InputHandler* writer, int extendedVkey); - void pressKey(InputHandler* writer, int extendedVkey, rdr::U32 keysym); - std::map<int,rdr::U32> downKeysym; - }; - - }; // win32 - -}; // rfb - -#endif // __RFB_WIN32_CKEYBOARD_H__ diff --git a/win/rfb_win32/CMakeLists.txt b/win/rfb_win32/CMakeLists.txt index 83d7f1c6..99d52779 100644 --- a/win/rfb_win32/CMakeLists.txt +++ b/win/rfb_win32/CMakeLists.txt @@ -1,8 +1,6 @@ set(RFB_WIN32_SOURCES AboutDialog.cxx - CKeyboard.cxx Clipboard.cxx - CPointer.cxx CurrentUser.cxx DeviceContext.cxx DeviceFrameBuffer.cxx @@ -12,14 +10,11 @@ set(RFB_WIN32_SOURCES EventManager.cxx LaunchProcess.cxx ListViewControl.cxx - LowLevelKeyEvents.cxx MonitorInfo.cxx MsgWindow.cxx OSVersion.cxx - ProgressControl.cxx RegConfig.cxx Registry.cxx - ScaledDIBSectionBuffer.cxx SecurityPage.cxx SDisplayCorePolling.cxx SDisplayCoreWMHooks.cxx @@ -30,7 +25,6 @@ set(RFB_WIN32_SOURCES SocketManager.cxx TCharArray.cxx Threading.cxx - ToolBar.cxx TsSessions.cxx Win32Util.cxx WMCursor.cxx diff --git a/win/rfb_win32/CPointer.cxx b/win/rfb_win32/CPointer.cxx deleted file mode 100644 index eda6e388..00000000 --- a/win/rfb_win32/CPointer.cxx +++ /dev/null @@ -1,186 +0,0 @@ -/* Copyright (C) 2002-2005 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 <windows.h> -#include <rfb/LogWriter.h> -#include <rfb_win32/CPointer.h> - -using namespace rfb; -using namespace win32; - -static LogWriter vlog("CPointer"); - - -CPointer::CPointer() : currButtonMask(0), intervalQueued(false), threeEmulating(false) { -} - -CPointer::~CPointer() { - intervalTimer.stop(); - threeTimer.stop(); -} - - -void CPointer::pointerEvent(InputHandler* writer, const Point& pos, int buttonMask) { - // - // - Duplicate Event Filtering - // - - bool maskChanged = buttonMask != currButtonMask; - bool posChanged = !pos.equals(currPos); - if (!(posChanged || maskChanged)) - return; - - // Pass on the event to the event-interval handler - threePointerEvent(writer, pos, buttonMask); - - // Save the position and mask - currPos = pos; - currButtonMask = buttonMask; -} - - -inline int _abs(int x) {return x>0 ? x : -x;} - -int emulate3Mask(int buttonMask) { - // - Release left & right and press middle - vlog.debug("emulate3: active"); - buttonMask &= ~5; - buttonMask |= 2; - return buttonMask; -} - -void CPointer::threePointerEvent(InputHandler* writer, const Point& pos, int buttonMask) { - // - // - 3-Button Mouse Emulation - // - - if (emulate3) { - - bool leftChanged = (buttonMask & 1) != (currButtonMask & 1); - bool rightChanged = (buttonMask & 4) != (currButtonMask & 4); - - if (leftChanged || rightChanged) { - // - One of left or right have changed - - if ((buttonMask & 5) == 1 || (buttonMask & 5) == 4) { - // - One is up, one is down. Start a timer, so that if it - // expires then we know we should actually send this event - vlog.debug("emulate3: start timer"); - threeTimer.start(100); - threePos = pos; - threeMask = buttonMask; - return; - - } else if (threeTimer.isActive()) { - // - Both are up or both are down, and we were timing for an emulation event - // Stop the timer and flush the stored event - vlog.debug("emulate3: stop timer (state)"); - threeTimer.stop(); - if (threeEmulating == ((buttonMask & 5) == 5)) - intervalPointerEvent(writer, threePos, threeMask); - else - threeEmulating = ((buttonMask & 5) == 5); - } - - } else { - - if (threeTimer.isActive()) { - // - We are timing for an emulation event - - if (_abs(threePos.x - pos.x) > 4 || _abs(threePos.y - pos.y) > 4) { - // If the mouse has moved too far since the button-change event then flush - vlog.debug("emulate3: stop timer (moved)"); - threeTimer.stop(); - intervalPointerEvent(writer, threePos, threeMask); - - } else { - // Otherwise, we ignore the new event - return; - } - } - - } - - // - If neither left nor right are down, stop emulating - if ((buttonMask & 5) == 0) - threeEmulating = false; - - // - If emulating, release left & right and press middle - if (threeEmulating) - buttonMask = emulate3Mask(buttonMask); - - } - - // - Let the event pass through to the next stage of processing - intervalPointerEvent(writer, pos, buttonMask); -} - -void CPointer::intervalPointerEvent(InputHandler* writer, const Point& pos, int buttonMask) { - // - // - Pointer Event Interval - // - vlog.write(101, "ptrEvent: %d,%d (%lx)", pos.x, pos.y, buttonMask); - - // Send the event immediately if we haven't sent one for a while - bool sendNow = !intervalTimer.isActive(); - - if (intervalMask != buttonMask) { - // If the buttons have changed then flush queued events and send now - sendNow = true; - if (intervalQueued) - writer->pointerEvent(intervalPos, intervalMask); - intervalQueued = false; - } - - if (!sendNow) { - // If we're not sending now then just queue the event - intervalQueued = true; - intervalPos = pos; - intervalMask = buttonMask; - } else { - // Start the interval timer if required, and send the event - intervalQueued = false; - intervalMask = buttonMask; - if (pointerEventInterval) - intervalTimer.start(pointerEventInterval); - writer->pointerEvent(pos, buttonMask); - } -} - -void CPointer::handleTimer(InputHandler* writer, int timerId) { - if (timerId == intervalTimer.getId()) { - // Pointer interval has expired - send any queued events - if (intervalQueued) { - writer->pointerEvent(intervalPos, intervalMask); - intervalQueued = false; - } else { - intervalTimer.stop(); - } - - } else if (timerId == threeTimer.getId()) { - // 3-Button emulation timer has expired - send what we've got - vlog.debug("emulate3: timeout"); - threeTimer.stop(); - - // If emulating, release left & right and press middle - if (threeEmulating) - threeMask = emulate3Mask(threeMask); - - intervalPointerEvent(writer, threePos, threeMask); - } -} diff --git a/win/rfb_win32/CPointer.h b/win/rfb_win32/CPointer.h deleted file mode 100644 index b5916010..00000000 --- a/win/rfb_win32/CPointer.h +++ /dev/null @@ -1,74 +0,0 @@ -/* Copyright (C) 2002-2005 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. - */ - -// -=- CPointer.h -// -// Client-side pointer event handling for Win32 - -#ifndef __RFB_WIN32_CPOINTER_H__ -#define __RFB_WIN32_CPOINTER_H__ - -#include <rdr/Exception.h> -#include <rfb/Configuration.h> -#include <rfb/InputHandler.h> -#include <rfb/Rect.h> -#include <rfb_win32/IntervalTimer.h> - -namespace rfb { - - namespace win32 { - - class CPointer { - public: - CPointer(); - ~CPointer(); - - void pointerEvent(InputHandler* writer, const Point& pos, int buttonMask); - void handleTimer(InputHandler* writer, int timerId); - - void setHWND(HWND w) {intervalTimer.setHWND(w); threeTimer.setHWND(w);} - void setIntervalTimerId(int id) {intervalTimer.setId(id);} - void set3ButtonTimerId(int id) {threeTimer.setId(id);} - - void enableEmulate3(bool enable) {emulate3 = enable;} - void enableInterval(int millis) {pointerEventInterval = millis;} - private: - Point currPos; - int currButtonMask; - - bool emulate3; - int pointerEventInterval; - - void intervalPointerEvent(InputHandler* writer, const Point& pos, int buttonMask); - IntervalTimer intervalTimer; - bool intervalQueued; - Point intervalPos; - int intervalMask; - - void threePointerEvent(InputHandler* writer, const Point& pos, int buttonMask); - IntervalTimer threeTimer; - Point threePos; - int threeMask; - bool threeEmulating; - }; - - }; // win32 - -}; // rfb - -#endif // __RFB_WIN32_CPOINTER_H__ diff --git a/win/rfb_win32/DIBSectionBuffer.cxx b/win/rfb_win32/DIBSectionBuffer.cxx index 3c2f5096..0c266b00 100644 --- a/win/rfb_win32/DIBSectionBuffer.cxx +++ b/win/rfb_win32/DIBSectionBuffer.cxx @@ -1,4 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * Copyright 2014 Pierre Ossman for Cendio AB * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -55,9 +56,11 @@ void DIBSectionBuffer::setPF(const PixelFormat& pf) { if ((pf.bpp <= 8) && pf.trueColour) { vlog.info("creating %d-bit TrueColour palette", pf.depth); for (int i=0; i < (1<<(pf.depth)); i++) { - palette[i].b = ((((i >> pf.blueShift) & pf.blueMax) * 65535) + pf.blueMax/2) / pf.blueMax; - palette[i].g = ((((i >> pf.greenShift) & pf.greenMax) * 65535) + pf.greenMax/2) / pf.greenMax; - palette[i].r = ((((i >> pf.redShift) & pf.redMax) * 65535) + pf.redMax/2) / pf.redMax; + rdr::U16 r, g, b; + pf.rgbFromPixel(i, NULL, &r, &g, &b); + palette[i].r = r; + palette[i].g = g; + palette[i].b = b; } refreshPalette(); } @@ -110,9 +113,9 @@ void DIBSectionBuffer::recreateBuffer() { bi.bmiHeader.biWidth = width_; bi.bmiHeader.biHeight = -height_; bi.bmiHeader.biCompression = (format.bpp > 8) ? BI_BITFIELDS : BI_RGB; - bi.mask.red = format.redMax << format.redShift; - bi.mask.green = format.greenMax << format.greenShift; - bi.mask.blue = format.blueMax << format.blueShift; + bi.mask.red = format.pixelFromRGB((rdr::U16)~0, 0, 0); + bi.mask.green = format.pixelFromRGB(0, (rdr::U16)~0, 0); + bi.mask.blue = format.pixelFromRGB(0, 0, (rdr::U16)~0); // Create a DIBSection to draw into if (device) @@ -160,6 +163,11 @@ void DIBSectionBuffer::recreateBuffer() { } if (new_bitmap) { + int bpp, depth; + bool trueColour; + int redMax, greenMax, blueMax; + int redShift, greenShift, blueShift; + // Set up the new bitmap bitmap = new_bitmap; data = new_data; @@ -180,30 +188,34 @@ void DIBSectionBuffer::recreateBuffer() { } // Calculate the PixelFormat for the DIB - format.bigEndian = 0; - format.bpp = format.depth = ds.dsBm.bmBitsPixel; - format.trueColour = format.trueColour || format.bpp > 8; - if (format.bpp > 8) { + bpp = depth = ds.dsBm.bmBitsPixel; + trueColour = format.trueColour || format.bpp > 8; + if (trueColour) { // Get the truecolour format used by the DIBSection - initMaxAndShift(ds.dsBitfields[0], &format.redMax, &format.redShift); - initMaxAndShift(ds.dsBitfields[1], &format.greenMax, &format.greenShift); - initMaxAndShift(ds.dsBitfields[2], &format.blueMax, &format.blueShift); + initMaxAndShift(ds.dsBitfields[0], &redMax, &redShift); + initMaxAndShift(ds.dsBitfields[1], &greenMax, &greenShift); + initMaxAndShift(ds.dsBitfields[2], &blueMax, &blueShift); // Calculate the effective depth - format.depth = 0; + depth = 0; Pixel bits = ds.dsBitfields[0] | ds.dsBitfields[1] | ds.dsBitfields[2]; while (bits) { - format.depth++; + depth++; bits = bits >> 1; } - if (format.depth > format.bpp) + if (depth > bpp) throw Exception("Bad DIBSection format (depth exceeds bpp)"); - } else { + } + + format = PixelFormat(bpp, depth, false, trueColour, + redMax, greenMax, blueMax, + redShift, greenShift, blueShift); + + if (!trueColour) { // Set the DIBSection's palette refreshPalette(); } - } } diff --git a/win/rfb_win32/DeviceContext.cxx b/win/rfb_win32/DeviceContext.cxx index 3b97e446..26721a60 100644 --- a/win/rfb_win32/DeviceContext.cxx +++ b/win/rfb_win32/DeviceContext.cxx @@ -1,4 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * Copyright 2014 Pierre Ossman for Cendio AB * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,7 +34,11 @@ PixelFormat DeviceContext::getPF() const { } PixelFormat DeviceContext::getPF(HDC dc) { - PixelFormat format; + bool trueColour, bigEndian; + int bpp, depth; + int redMax, greenMax, blueMax; + int redShift, greenShift, blueShift; + CompatibleBitmap bitmap(dc, 1, 1); // -=- Get the bitmap format information @@ -49,11 +54,11 @@ PixelFormat DeviceContext::getPF(HDC dc) { } // Set the initial format information - format.trueColour = bi.bmiHeader.biBitCount > 8; - format.bigEndian = 0; - format.bpp = bi.bmiHeader.biBitCount; + trueColour = bi.bmiHeader.biBitCount > 8; + bigEndian = 0; + bpp = bi.bmiHeader.biBitCount; - if (format.trueColour) { + if (trueColour) { DWORD rMask=0, gMask=0, bMask=0; // Which true colour format is the DIB section using? @@ -92,44 +97,42 @@ PixelFormat DeviceContext::getPF(HDC dc) { }; // Convert the data we just retrieved - initMaxAndShift(rMask, &format.redMax, &format.redShift); - initMaxAndShift(gMask, &format.greenMax, &format.greenShift); - initMaxAndShift(bMask, &format.blueMax, &format.blueShift); + initMaxAndShift(rMask, &redMax, &redShift); + initMaxAndShift(gMask, &greenMax, &greenShift); + initMaxAndShift(bMask, &blueMax, &blueShift); // Calculate the depth from the colour shifts - format.depth = 0; + depth = 0; Pixel bits = rMask | gMask | bMask; while (bits) { - format.depth++; + depth++; bits = bits >> 1; } // Check that the depth & bpp are valid - if (format.depth > format.bpp) { + if (depth > bpp) { vlog.error("depth exceeds bits per pixel!"); - format.bpp = format.depth; + bpp = depth; } // Correct the bits-per-pixel to something we're happy with - if (format.bpp <= 16) - format.bpp = 16; - else if (format.bpp <= 32) - format.bpp = 32; + if (bpp <= 16) + bpp = 16; + else if (bpp <= 32) + bpp = 32; } else { // Palettised format - depth reflects number of colours, // but bits-per-pixel is ALWAYS 8 - format.depth = format.bpp; - if (format.bpp < 8) - format.bpp = 8; - vlog.info("%d-colour palettised", 1<<format.depth); + depth = bpp; + if (bpp < 8) + bpp = 8; + vlog.info("%d-colour palettised", 1<<depth); } - // Use 10 arguments constructor to trigger PixelFormat::updateState() - return PixelFormat(format.bpp, format.depth, - format.bigEndian, format.trueColour, - format.redMax, format.greenMax, format.blueMax, - format.redShift, format.greenShift, format.blueShift); + return PixelFormat(bpp, depth, bigEndian, trueColour, + redMax, greenMax, blueMax, + redShift, greenShift, blueShift); } Rect DeviceContext::getClipBox() const { diff --git a/win/rfb_win32/LogicalPalette.h b/win/rfb_win32/LogicalPalette.h deleted file mode 100644 index 204f1081..00000000 --- a/win/rfb_win32/LogicalPalette.h +++ /dev/null @@ -1,90 +0,0 @@ -/* Copyright (C) 2002-2005 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 __RFB_WIN32_LOGPALETTE_H__ -#define __RFB_WIN32_LOGPALETTE_H__ - -#include <windows.h> -#include <rdr/Exception.h> - -namespace rfb { - namespace win32 { - - class LogicalPalette { - public: - LogicalPalette() { - BYTE buf[sizeof(LOGPALETTE)+256*sizeof(PALETTEENTRY)]; - LOGPALETTE* logpal = (LOGPALETTE*)buf; - logpal->palVersion = 0x300; - logpal->palNumEntries = 256; - for (int i=0; i<256;i++) { - logpal->palPalEntry[i].peRed = 0; - logpal->palPalEntry[i].peGreen = 0; - logpal->palPalEntry[i].peBlue = 0; - logpal->palPalEntry[i].peFlags = 0; - } - palette = CreatePalette(logpal); - if (!palette) - throw rdr::SystemException("failed to CreatePalette", GetLastError()); - } - ~LogicalPalette() { - if (palette && !DeleteObject(palette)) - throw rdr::SystemException("del palette failed", GetLastError()); - } - void setEntries(int start, int count, const Colour* cols) { - if (numEntries < count) { - ResizePalette(palette, start+count); - numEntries = start+count; - } - PALETTEENTRY* logpal = new PALETTEENTRY[count]; - for (int i=0; i<count; i++) { - logpal[i].peRed = cols[i].r >> 8; - logpal[i].peGreen = cols[i].g >> 8; - logpal[i].peBlue = cols[i].b >> 8; - logpal[i].peFlags = 0; - } - UnrealizeObject(palette); - SetPaletteEntries(palette, start, count, logpal); - delete [] logpal; - } - HPALETTE getHandle() {return palette;} - protected: - HPALETTE palette; - int numEntries; - }; - - class PaletteSelector { - public: - PaletteSelector(HDC dc, HPALETTE pal) : device(dc), redrawRequired(false) { - oldPal = SelectPalette(dc, pal, FALSE); - redrawRequired = RealizePalette(dc) > 0; - } - ~PaletteSelector() { - if (oldPal) SelectPalette(device, oldPal, TRUE); - } - bool isRedrawRequired() {return redrawRequired;} - protected: - HPALETTE oldPal; - HDC device; - bool redrawRequired; - }; - - }; -}; - -#endif diff --git a/win/rfb_win32/LowLevelKeyEvents.cxx b/win/rfb_win32/LowLevelKeyEvents.cxx deleted file mode 100644 index e80ebedc..00000000 --- a/win/rfb_win32/LowLevelKeyEvents.cxx +++ /dev/null @@ -1,96 +0,0 @@ -/* Copyright (C) 2002-2005 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 <windows.h> -#include <rfb_win32/LowLevelKeyEvents.h> -#include <rfb/Threading.h> -#include <rfb/LogWriter.h> -#include <list> - -using namespace rfb; -using namespace win32; - -static LogWriter vlog("LowLevelKeyEvents"); - - -HHOOK hook = 0; -std::list<HWND> windows; -Mutex windowLock; - - -static bool filterKeyEvent(int vkCode) { - switch (vkCode) { - case VK_LWIN: - case VK_RWIN: - case VK_SNAPSHOT: - return true; - case VK_TAB: - if (GetAsyncKeyState(VK_MENU) & 0x8000) - return true; - case VK_ESCAPE: - if (GetAsyncKeyState(VK_MENU) & 0x8000) - return true; - if (GetAsyncKeyState(VK_CONTROL) & 0x8000) - return true; - } - return false; -} - -LRESULT CALLBACK LowLevelKeyEventProc(int nCode, - WPARAM wParam, - LPARAM lParam) { - if (nCode >= 0) { - Lock l(windowLock); - HWND foreground = GetForegroundWindow(); - std::list<HWND>::iterator i; - for (i=windows.begin(); i!=windows.end(); i++) { - if (*i == foreground) { - UINT msgType = wParam; - KBDLLHOOKSTRUCT* msgInfo = (KBDLLHOOKSTRUCT*)lParam; - if (filterKeyEvent(msgInfo->vkCode)) { - vlog.debug("filtered event %lx(%lu) %lu", msgInfo->vkCode, msgInfo->vkCode, msgType); - PostMessage(*i, wParam, msgInfo->vkCode, (msgInfo->scanCode & 0xff) << 16); - return 1; - } - } - } - } - return CallNextHookEx(hook, nCode, wParam, lParam); -} - - -bool rfb::win32::enableLowLevelKeyEvents(HWND hwnd) { -// *** return false; // *** THIS CODE IS EXPERIMENTAL, SO DISABLED BY DEFAULT! - Lock l(windowLock); - if (windows.empty() && !hook) - hook = SetWindowsHookEx(WH_KEYBOARD_LL, &LowLevelKeyEventProc, GetModuleHandle(0), 0); - if (hook) - windows.push_back(hwnd); - vlog.debug("enable %p -> %s", hwnd, hook ? "success" : "failure"); - return hook != 0; -} - -void rfb::win32::disableLowLevelKeyEvents(HWND hwnd) { - vlog.debug("disable %p", hwnd); - Lock l(windowLock); - windows.remove(hwnd); - if (windows.empty() && hook) { - UnhookWindowsHookEx(hook); - hook = 0; - } -} diff --git a/win/rfb_win32/LowLevelKeyEvents.h b/win/rfb_win32/LowLevelKeyEvents.h deleted file mode 100644 index 40d2ecfa..00000000 --- a/win/rfb_win32/LowLevelKeyEvents.h +++ /dev/null @@ -1,49 +0,0 @@ -/* Copyright (C) 2002-2005 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. - */ - -// -=- LowLevelKeyEvents.h -// -// This interface allows keyboard events destined for a particular window -// to be intercepted early in the keyboard message queue and posted directly -// to the window. This is used to avoid having the operating system process -// keys such as VK_LWIN, VK_RWIN, etc. -// - -#ifndef __RFB_WIN32_LOW_LEVEL_KEY_EVENTS_H__ -#define __RFB_WIN32_LOW_LEVEL_KEY_EVENTS_H__ - -namespace rfb { - - namespace win32 { - - // enableLowLevelKeyEvents - // Specifies that keyboard events destined for the specified window should - // be posted directly to the window, rather than being passed via the normal - // Windows keyboard message queue. - bool enableLowLevelKeyEvents(HWND hwnd); - - // disableLowLevelKeyEvents - // Causes the specified window to revert to the normal Windows keyboard - // event processing mechanism. - void disableLowLevelKeyEvents(HWND hwnd); - - }; - -}; - -#endif // __RFB_WIN32_LOW_LEVEL_KEY_EVENTS_H__ diff --git a/win/rfb_win32/ProgressControl.cxx b/win/rfb_win32/ProgressControl.cxx deleted file mode 100644 index 5533317b..00000000 --- a/win/rfb_win32/ProgressControl.cxx +++ /dev/null @@ -1,97 +0,0 @@ -/* Copyright (C) 2005 TightVNC Team. 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. - * - * - * - */ - -// -=- ProgressControl.cxx - -#include <rfb_win32/ProgressControl.h> - -using namespace rfb; -using namespace rfb::win32; - -#define MAX_RANGE 0xFFFF - -ProgressControl::ProgressControl(HWND hwndProgress) -{ - m_hwndProgress = hwndProgress; - - m_dw64MaxValue = 0; - m_dw64CurrentValue = 0; -} - -ProgressControl::~ProgressControl() -{ -} - -bool -ProgressControl::init(DWORD64 maxValue, DWORD64 position) -{ - if (m_dw64CurrentValue > m_dw64MaxValue) return false; - - m_dw64CurrentValue = position; - m_dw64MaxValue = maxValue; - - if (!SendMessage(m_hwndProgress, PBM_SETRANGE, (WPARAM) 0, MAKELPARAM(0, MAX_RANGE))) - return false; - - return true; -} - -bool -ProgressControl::clear() -{ - m_dw64CurrentValue = 0; - return show(); -} - -bool -ProgressControl::increase(DWORD64 value) -{ - if ((m_dw64MaxValue - m_dw64CurrentValue) > value) { - m_dw64CurrentValue += value; - } else { - m_dw64CurrentValue = m_dw64MaxValue; - } - return show(); -} - -bool -ProgressControl::show() -{ - DWORD curPos; - if (m_dw64MaxValue != 0) { - curPos = (DWORD) ((m_dw64CurrentValue * MAX_RANGE) / m_dw64MaxValue); - } else { - curPos = 0; - } - - if (!SendMessage(m_hwndProgress, PBM_SETPOS, (WPARAM) curPos, (LPARAM) 0)) - return false; - - return true; -} - -int -ProgressControl::getCurrentPercent() -{ - if (m_dw64MaxValue == 0) return 0; - - return ((int) ((m_dw64CurrentValue * 100) / m_dw64MaxValue)); -} diff --git a/win/rfb_win32/ProgressControl.h b/win/rfb_win32/ProgressControl.h deleted file mode 100644 index 094c7657..00000000 --- a/win/rfb_win32/ProgressControl.h +++ /dev/null @@ -1,56 +0,0 @@ -/* Copyright (C) 2005 TightVNC Team. 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. - * - * - * - */ - -// -=- ProgressControl.h - -#ifndef __RFB_WIN32_PROGRESSCONTROL_H__ -#define __RFB_WIN32_PROGRESSCONTROL_H__ - -#include <windows.h> -#include <commctrl.h> - -namespace rfb { - namespace win32 { - class ProgressControl - { - public: - ProgressControl(HWND hwndProgress); - ~ProgressControl(); - - bool init(DWORD64 maxValue, DWORD64 position); - - bool increase(DWORD64 value); - bool clear(); - - int getCurrentPercent(); - - private: - HWND m_hwndProgress; - - DWORD64 m_dw64MaxValue; - DWORD64 m_dw64CurrentValue; - - bool show(); - }; - } -} - -#endif // __RFB_WIN32_PROGRESSCONTROL_H__ diff --git a/win/rfb_win32/ScaledDIBSectionBuffer.cxx b/win/rfb_win32/ScaledDIBSectionBuffer.cxx deleted file mode 100644 index 752cd784..00000000 --- a/win/rfb_win32/ScaledDIBSectionBuffer.cxx +++ /dev/null @@ -1,195 +0,0 @@ -/* Copyright (C) 2006 TightVNC Team. 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. - * - * - * - */ - -// -=- ScaledDIBSectionBuffer.cxx - -#include <math.h> - -#include <rfb_win32/ScaledDIBSectionBuffer.h> - -using namespace rfb; -using namespace win32; - -const PixelFormat RGB24(32, 24, 0, 1, 255, 255, 255, 16, 8, 0); - -ScaledDIBSectionBuffer::ScaledDIBSectionBuffer(HWND window) - : DIBSectionBuffer(window), src_buffer(0), scaling(false) { - scaled_data = &data; -} - -ScaledDIBSectionBuffer::~ScaledDIBSectionBuffer() { - if (src_buffer) delete src_buffer; -} - -void ScaledDIBSectionBuffer::setScale(int scale_) { - if (scale == scale_ || scale_ <= 0) return; - if (!(getPixelFormat().trueColour) && scale_ != 100) throw rfb::UnsupportedPixelFormatException(); - ScaledPixelBuffer::setScale(scale_); - if (scale == 100) scaling = false; - else scaling = true; - recreateBuffers(); -} - -void ScaledDIBSectionBuffer::setPF(const PixelFormat &pf_) { - if (memcmp(&(ScaledPixelBuffer::pf), &pf_, sizeof(pf_)) == 0) return; - - if (!pf_.trueColour && isScaling()) throw rfb::UnsupportedPixelFormatException(); - - pf = pf_; - if (scaling) { - if (src_buffer) { - src_buffer->setPF(pf); - } else { - src_buffer = new ManagedPixelBuffer(pf, src_width, src_height); - src_data = &(src_buffer->data); - } - if (memcmp(&(DIBSectionBuffer::getPF()), &RGB24, sizeof(PixelFormat)) != 0) { - DIBSectionBuffer::setPF(RGB24); - } - } else { - DIBSectionBuffer::setPF(pf); - pf = format; - } -} - -void ScaledDIBSectionBuffer::setSize(int src_width_, int src_height_) { - if (src_width == src_width_ && src_height == src_height_) return; - src_width = src_width_; - src_height = src_height_; - - // FIXME: - // Calculate the scale weight tabs must be in the ScalePixelBuffer class - recreateRowAccum(); - freeWeightTabs(); - calculateScaledBufferSize(); - scaleFilters.makeWeightTabs(scaleFilterID, src_width, scaled_width, &xWeightTabs); - scaleFilters.makeWeightTabs(scaleFilterID, src_height, scaled_height, &yWeightTabs); - - recreateBuffers(); -} - -void ScaledDIBSectionBuffer::setScaleWindowSize(int width, int height) { - if (scaled_width == width && scaled_height == height) return; - - freeWeightTabs(); - - scaled_width = width_ = width; - scaled_height = height_ = height; - - if (scaled_width == src_width && scaled_height == src_height) scaling = false; - else scaling = true; - scale_ratio_x = (double)scaled_width / src_width; - scale_ratio_y = (double)scaled_height / src_height; - scale = (int)(scale_ratio_x * 100); - - // FIXME: - // Calculate the scale weight tabs must be in the ScalePixelBuffer class - scaleFilters.makeWeightTabs(scaleFilterID, src_width, scaled_width, &xWeightTabs); - scaleFilters.makeWeightTabs(scaleFilterID, src_height, scaled_height, &yWeightTabs); - - recreateBuffers(); -} - -void ScaledDIBSectionBuffer::recreateScaledBuffer() { - if (scaling && memcmp(&(DIBSectionBuffer::getPF()), &RGB24, sizeof(PixelFormat)) != 0) { - DIBSectionBuffer::setPF(RGB24); - } else if (!scaling && (memcmp(&(DIBSectionBuffer::getPF()), &pf, sizeof(PixelFormat)) != 0)){ - DIBSectionBuffer::setPF(pf); - } else { - DIBSectionBuffer::recreateBuffer(); - } -} - -void ScaledDIBSectionBuffer::recreateBuffers() { - // Recreate the source pixel buffer - if (src_width && src_height && pf.depth > 0) { - if (scaling) { - if (src_buffer) { - if (src_buffer->width() != src_width || src_buffer->width() != src_height) - src_buffer->setSize(src_width, src_height); - } else { - src_buffer = new ManagedPixelBuffer(pf, src_width, src_height); - src_data = &(src_buffer->data); - if (data) memcpy(src_buffer->data, data, src_width * src_height * (getPF().bpp/8)); - } - } - } - // Recreate the scaled pixel buffer - recreateScaledBuffer(); - if (scaling && src_buffer && data) scaleRect(Rect(0, 0, src_width, src_height)); - else if (!scaling && src_buffer) { - if (src_buffer->data && data) memcpy(data, src_buffer->data, src_buffer->area() * (getPF().bpp/8)); - delete src_buffer; - src_buffer = 0; - src_data = 0; - } -} - -void ScaledDIBSectionBuffer::calculateScaledBufferSize() { - ScaledPixelBuffer::calculateScaledBufferSize(); - width_ = scaled_width; - height_ = scaled_height; -} - -void ScaledDIBSectionBuffer::fillRect(const Rect &dest, Pixel pix) { - if (scaling) { - src_buffer->fillRect(dest, pix); - scaleRect(dest); - } else { - DIBSectionBuffer::fillRect(dest, pix); - } -} - -void ScaledDIBSectionBuffer::imageRect(const Rect &dest, const void* pixels, int stride) { - if (scaling) { - src_buffer->imageRect(dest, pixels, stride); - scaleRect(dest); - } else { - DIBSectionBuffer::imageRect(dest, pixels, stride); - } -} - -void ScaledDIBSectionBuffer::copyRect(const Rect &dest, const Point &move_by_delta) { - if (scaling) { - src_buffer->copyRect(dest, move_by_delta); - scaleRect(dest); - } else { - DIBSectionBuffer::copyRect(dest, move_by_delta); - } -} - -void ScaledDIBSectionBuffer::maskRect(const Rect& r, const void* pixels, const void* mask_) { - if (scaling) { - src_buffer->maskRect(r, pixels, mask_); - scaleRect(r); - } else { - DIBSectionBuffer::maskRect(r, pixels, mask_); - } -} - -void ScaledDIBSectionBuffer::maskRect(const Rect& r, Pixel pixel, const void* mask_) { - if (scaling) { - src_buffer->maskRect(r, pixel, mask_); - scaleRect(r); - } else { - DIBSectionBuffer::maskRect(r, pixel, mask_); - } -} diff --git a/win/rfb_win32/ScaledDIBSectionBuffer.h b/win/rfb_win32/ScaledDIBSectionBuffer.h deleted file mode 100644 index 420a97ab..00000000 --- a/win/rfb_win32/ScaledDIBSectionBuffer.h +++ /dev/null @@ -1,85 +0,0 @@ -/* Copyright (C) 2006 TightVNC Team. 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. - * - * - * - */ - -// -=- ScaledDIBSectionBuffer.h - -#ifndef __RFB_WIN32_SCALED_DIB_SECTION_BUFFER_H__ -#define __RFB_WIN32_SCALED_DIB_SECTION_BUFFER_H__ - -#include <rfb/ScaledPixelBuffer.h> - -#include <rfb_win32/DIBSectionBuffer.h> - -namespace rfb { - - namespace win32 { - - // - // -=- ScaledDIBSectionBuffer - // - - class ScaledDIBSectionBuffer : public ScaledPixelBuffer, public DIBSectionBuffer { - public: - ScaledDIBSectionBuffer(HWND window); - virtual ~ScaledDIBSectionBuffer(); - - int width() const { return scaled_width; } - int height() const { return scaled_height; } - int area() const { return scaled_width * scaled_height; } - bool isScaling() const { return scaling; } - - virtual void setPF(const PixelFormat &pf); - virtual const PixelFormat& getPixelFormat() const { return pf; } - virtual const PixelFormat& getScaledPixelFormat() const { return getPF(); } - virtual void setSize(int w, int h); - virtual void setScale(int scale); - virtual void setScaleWindowSize(int width, int height); - - virtual void calculateScaledBufferSize(); - - Rect getRect() const { return ScaledPixelBuffer::getRect(); } - Rect getRect(const Point& pos) const { return ScaledPixelBuffer::getRect(pos); } - - // -=- Overrides basic rendering operations of - // FullFramePixelBuffer class - - virtual void fillRect(const Rect &dest, Pixel pix); - virtual void imageRect(const Rect &dest, const void* pixels, int stride=0); - virtual void copyRect(const Rect &dest, const Point &move_by_delta); - virtual void maskRect(const Rect& r, const void* pixels, const void* mask_); - virtual void maskRect(const Rect& r, Pixel pixel, const void* mask_); - - protected: - virtual void recreateScaledBuffer(); - virtual void recreateBuffers(); - virtual void recreateBuffer() { - recreateScaledBuffer(); - }; - - ManagedPixelBuffer *src_buffer; - bool scaling; - }; - - }; - -}; - -#endif // __RFB_WIN32_SCALED_DIB_SECTION_BUFFER_H__ diff --git a/win/rfb_win32/ToolBar.cxx b/win/rfb_win32/ToolBar.cxx deleted file mode 100644 index 1bbba30a..00000000 --- a/win/rfb_win32/ToolBar.cxx +++ /dev/null @@ -1,222 +0,0 @@ -/* Copyright (C) 2004 TightVNC Team. 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. - */ - -// -=- ToolBar control class. - -#include "ToolBar.h" - -using namespace rfb::win32; - -ToolBar::ToolBar() : hwndToolBar(0), tbID(-1) { - INITCOMMONCONTROLSEX icex; - - // Ensure that the common control DLL is loaded - icex.dwSize = sizeof(INITCOMMONCONTROLSEX); - icex.dwICC = ICC_BAR_CLASSES; - InitCommonControlsEx(&icex); -} - -ToolBar::~ToolBar() { - DestroyWindow(getHandle()); -} - -bool ToolBar::create(int _tbID, HWND _parentHwnd, DWORD dwStyle) { - parentHwnd = _parentHwnd; - dwStyle |= WS_CHILD; - - // Create the ToolBar window - hwndToolBar = CreateWindowEx(0, TOOLBARCLASSNAME, 0, dwStyle, - 0, 0, 25, 25, parentHwnd, (HMENU)_tbID, GetModuleHandle(0), 0); - - if (hwndToolBar) { - tbID = _tbID; - - // It's required for backward compatibility - SendMessage(hwndToolBar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0); - } - return (hwndToolBar ? true : false); -}; - -int ToolBar::addBitmap(int nButtons, UINT bitmapID) { - assert(nButtons > 0); - TBADDBITMAP resBitmap; - resBitmap.hInst = GetModuleHandle(0); - resBitmap.nID = bitmapID; - return SendMessage(getHandle(), TB_ADDBITMAP, nButtons, (LPARAM)&resBitmap); -} - -int ToolBar::addSystemBitmap(UINT stdBitmapID) { - TBADDBITMAP resBitmap; - resBitmap.hInst = HINST_COMMCTRL; - resBitmap.nID = stdBitmapID; - return SendMessage(getHandle(), TB_ADDBITMAP, 0, (LPARAM)&resBitmap); -} - -bool ToolBar::setBitmapSize(int width, int height) { - int result = SendMessage(getHandle(), TB_SETBITMAPSIZE, - 0, MAKELONG(width, height)); - return (result ? true : false); -} - -bool ToolBar::addButton(int iBitmap, int idCommand, BYTE state, BYTE style, UINT dwData, int iString) { - TBBUTTON tbb; - tbb.iBitmap = iBitmap; - tbb.idCommand = idCommand; - tbb.fsState = state; - tbb.fsStyle = style; - tbb.dwData = dwData; - tbb.iString = iString; - - int result = SendMessage(getHandle(), TB_ADDBUTTONS, 1, (LPARAM)&tbb); - if (result) { - SendMessage(getHandle(), TB_AUTOSIZE, 0, 0); - } - return (result ? true : false); -} - -bool ToolBar::addNButton(int nButtons, LPTBBUTTON tbb) { - assert(nButtons > 0); - assert(tbb > 0); - int result = SendMessage(getHandle(), TB_ADDBUTTONS, nButtons, (LPARAM)tbb); - if (result) { - SendMessage(getHandle(), TB_AUTOSIZE, 0, 0); - } - return (result ? true : false); -} - -bool ToolBar::deleteButton(int indexButton) { - assert(indexButton >= 0); - int result = SendMessage(getHandle(), TB_DELETEBUTTON, indexButton, 0); - - if (result) { - SendMessage(getHandle(), TB_AUTOSIZE, 0, 0); - } - return (result ? true : false); -} - -bool ToolBar::insertButton(int indexButton, LPTBBUTTON tbb) { - assert(indexButton >= 0); - assert(tbb > 0); - int result = SendMessage(getHandle(), TB_INSERTBUTTON, - indexButton, (LPARAM)tbb); - - if (result) { - SendMessage(getHandle(), TB_AUTOSIZE, 0, 0); - } - return (result ? true : false); -} - -int ToolBar::getButtonInfo(int idButton, TBBUTTONINFO *btnInfo) { - assert(idButton >= 0); - assert(btnInfo > 0); - return SendMessage(getHandle(), TB_GETBUTTONINFO, idButton, (LPARAM)btnInfo); -} - -int ToolBar::getButtonsHeight() { - return HIWORD(SendMessage(getHandle(), TB_GETBUTTONSIZE, 0, 0)); -} - -int ToolBar::getButtonsWidth() { - return LOWORD(SendMessage(getHandle(), TB_GETBUTTONSIZE, 0, 0)); -} - -bool ToolBar::setButtonInfo(int idButton, TBBUTTONINFO* btnInfo) { - assert(idButton >= 0); - assert(btnInfo > 0); - int result = SendMessage(getHandle(), TB_SETBUTTONINFO, - idButton, (LPARAM)(LPTBBUTTONINFO)btnInfo); - return (result ? true : false); -} - -bool ToolBar::checkButton(int idButton, bool check) { - assert(idButton >= 0); - int result = SendMessage(getHandle(), TB_CHECKBUTTON, - idButton, MAKELONG(check, 0)); - return (result ? true : false); -} - -bool ToolBar::enableButton(int idButton, bool enable) { - assert(idButton >= 0); - int result = SendMessage(getHandle(), TB_ENABLEBUTTON, - idButton, MAKELONG(enable, 0)); - return (result ? true : false); -} - -bool ToolBar::pressButton(int idButton, bool press) { - assert(idButton >= 0); - int result = SendMessage(getHandle(), TB_PRESSBUTTON, - idButton, MAKELONG(press, 0)); - return (result ? true : false); -} - -bool ToolBar::getButtonRect(int nIndex, LPRECT buttonRect) { - int result = SendMessage(getHandle(), TB_GETITEMRECT, - nIndex, (LPARAM)buttonRect); - return (result ? true : false); -} - -bool ToolBar::setButtonSize(int width, int height) { - assert(width > 0); - assert(height > 0); - int result = SendMessage(getHandle(), TB_SETBUTTONSIZE, - 0, MAKELONG(width, height)); - if (result) { - SendMessage(getHandle(), TB_AUTOSIZE, 0, 0); - return true; - } - return false; -} - -void ToolBar::autoSize() { - DWORD style = SendMessage(getHandle(), TB_GETSTYLE, 0, 0); - if (style & CCS_NORESIZE) { - RECT r, btnRect; - GetClientRect(parentHwnd, &r); - getButtonRect(0, &btnRect); - int height = getButtonsHeight() + btnRect.top * 2 + 2; - SetWindowPos(getHandle(), HWND_TOP, 0, 0, r.right - r.left, height, - SWP_NOMOVE); - } else { - SendMessage(getHandle(), TB_AUTOSIZE, 0, 0); - } -} - -int ToolBar::getHeight() { - RECT r; - GetWindowRect(getHandle(), &r); - return r.bottom - r.top; -} - -int ToolBar::getTotalWidth() { - SIZE size; - SendMessage(getHandle(), TB_GETMAXSIZE, 0, (LPARAM)(LPSIZE)&size); - return size.cx; -} - -void ToolBar::show() { - ShowWindow(getHandle(), SW_SHOW); -} - -void ToolBar::hide() { - ShowWindow(getHandle(), SW_HIDE); -} - -bool ToolBar::isVisible() { - DWORD style = GetWindowLong(getHandle(), GWL_STYLE); - return (bool)(style & WS_VISIBLE); -} diff --git a/win/rfb_win32/ToolBar.h b/win/rfb_win32/ToolBar.h deleted file mode 100644 index f256c999..00000000 --- a/win/rfb_win32/ToolBar.h +++ /dev/null @@ -1,136 +0,0 @@ -/* Copyright (C) 2004 TightVNC Team. 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. - */ - -// -=- ToolBar control class. - -#include <windows.h> -#include <commctrl.h> -#include <assert.h> - -namespace rfb { - - namespace win32 { - - class ToolBar { - public: - ToolBar(); - virtual ~ToolBar(); - - // create() creates a windows toolbar. dwStyle is a combination of - // the toolbar control and button styles. It returns TRUE if successful, - // or FALSE otherwise. - bool create(int tbID, HWND parentHwnd, - DWORD dwStyle = WS_CHILD | WS_VISIBLE | TBSTYLE_FLAT); - - // -=- Button images operations - - // addBitmap() adds one or more images from resources to - // the list of button images available for a toolbar. - // Returns the index of the first new image if successful, - // or -1 otherwise. - int addBitmap(int nButtons, UINT bitmapID); - - // addSystemBitmap() adds the system-defined button bitmaps to the list - // of the toolbar button specifying by stdBitmapID. Returns the index of - // the first new image if successful, or -1 otherwise. - int addSystemBitmap(UINT stdBitmapID); - - // setBitmapSize() sets the size of the bitmapped images to be added - // to a toolbar. It returns TRUE if successful, or FALSE otherwise. - // You must call it before addBitmap(). - bool setBitmapSize(int width, int height); - - // -=- Button operations - - // addButton() adds one button. - bool addButton(int iBitmap, int idCommand, BYTE state=TBSTATE_ENABLED, - BYTE style=TBSTYLE_BUTTON, UINT dwData=0, int iString=0); - - // addNButton() adds nButtons buttons to a toolbar. - bool addNButton(int nButtons, LPTBBUTTON tbb); - - // deleteButton() removes a button from the toolbar. - bool deleteButton(int nIndex); - - // insertButton() inserts a button in a toolbar control by index. - bool insertButton(int nIndex, LPTBBUTTON tbb); - - // getButtonInfo() retrieves extended information about a toolbar's - // button. It returns index of the button if successful, or -1 otherwise. - int getButtonInfo(int idButton, TBBUTTONINFO *btnInfo); - - // getButtonsHeight() retrieves the height of the toolbar buttons. - int getButtonsHeight(); - - // getButtonsWidth() retrieves the width of the toolbar buttons. - int getButtonsWidth(); - - // setButtonInfo() sets the information for an existing button - // in a toolbar. - bool setButtonInfo(int idButton, TBBUTTONINFO* ptbbi); - - // checkButton() checks or unchecks a given button in a toolbar control. - bool checkButton(int idButton, bool check); - - // enableButton() enables or disables the specified button - // in the toolbar. - bool enableButton(int idButton, bool enable); - - // pressButton() presses or releases the specified button in the toolbar. - bool pressButton(int idButton, bool press); - - // getButtonRect() gets the bounding rectangle of a button in a toolbar. - bool getButtonRect(int nIndex, LPRECT buttonRect); - - // setButtonSize() sets the size of the buttons to be added to a toolbar. - // Button size must be largen the button bitmap. - bool setButtonSize(int width, int height); - - // -=- ToolBar operations - - // autoSize() resizes the toolbar window. - void autoSize(); - - // getHandle() returns handle to a toolbar window. - HWND getHandle() { return hwndToolBar; } - - // getHeight() returns the toolbar window height. - int getHeight(); - - // getTotalWidth() returns the total size of all buttons and - // separators in the toolbar. - int getTotalWidth(); - - // show() displays the toolbar window. - void show(); - - // hide() hides the toolbar window. - void hide(); - - // isVisible() check the toolbar window on visible. - bool isVisible(); - - protected: - HWND hwndToolBar; - HWND parentHwnd; - int tbID; - }; - - }; // win32 - -}; // rfb diff --git a/win/vncconfig/vncconfig.cxx b/win/vncconfig/vncconfig.cxx index 535febbe..16bf1727 100644 --- a/win/vncconfig/vncconfig.cxx +++ b/win/vncconfig/vncconfig.cxx @@ -19,9 +19,6 @@ #include <windows.h> #include <commctrl.h> #include <string.h> -#ifdef WIN32 -#define strcasecmp _stricmp -#endif #include "resource.h" #include <rfb/Logger_stdio.h> diff --git a/win/winvnc/JavaViewer.cxx b/win/winvnc/JavaViewer.cxx index e1cb6e5f..c9631229 100644 --- a/win/winvnc/JavaViewer.cxx +++ b/win/winvnc/JavaViewer.cxx @@ -25,8 +25,6 @@ #include <windows.h> -#define strcasecmp _stricmp - using namespace winvnc; using namespace rfb; diff --git a/win/winvnc/winvnc.cxx b/win/winvnc/winvnc.cxx index 4aa5dcb6..17b3a91c 100644 --- a/win/winvnc/winvnc.cxx +++ b/win/winvnc/winvnc.cxx @@ -19,9 +19,6 @@ // -=- VNC Server 4.0 for Windows (WinVNC4) #include <string.h> -#ifdef WIN32 -#define strcasecmp _stricmp -#endif #include <winvnc/VNCServerWin32.h> #include <winvnc/VNCServerService.h> |