2
* rfb_protocol.cpp - class rfbConnection, an implementation of the RFB-protocol, used by VNC servers
5
* Copyright (c) 2004-2005 Tobias Doerffel <tobias@doerffel.de>
7
* This program is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU General Public
9
* License as published by the Free Software Foundation; either
10
* version 2 of the License, or (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* General Public License for more details.
17
* You should have received a copy of the GNU General Public
18
* License along with this program (see COPYING); if not, write to the
19
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20
* Boston, MA 02111-1307, USA.
35
#ifdef HAVE_NETINET_TCP_H
36
#include <netinet/tcp.h>
41
#ifdef HAVE_SYS_SOCKET_H
42
#include <sys/socket.h>
47
#include <qfileinfo.h>
48
#include <qmessagebox.h>
50
#if QT_VERSION >= 0x030200
51
#include <qsplashscreen.h>
54
#include "rfb_connection.h"
55
#include "system_environment.h"
56
#include "qimage_manips.h"
57
#include "rsa_crypt_lib.h"
61
#include "rfb_connection.moc"
66
const char * RFBP_VERSION_FORMAT = "RFB %03d.%03d\n";
67
//const int MAX_READ_RETRIES = 1024;
70
const s_rfb_pixel_format rfbConnection::s_localDisplayFormat =
82
0, 0 // only for padding
87
#ifdef RSA_CRYPT_AVAILABLE
88
RSA * rfbConnection::s_privateKey = NULL;
92
void rfbConnection::initializeAuthentication( void )
94
#ifdef RSA_CRYPT_AVAILABLE
95
if( italc::ensureConfigPathExists() == FALSE )
97
qFatal( "Could not read/write or create directory " + QString( ITALC_CONFIG_PATH ) + "! For running iTALC, make sure you have "
98
"write-access to your home-directory and to " + QString( ITALC_CONFIG_PATH ) + " (if already existing)." );
100
const QString PRIV_KEY_FILE = QDir::home().absPath() + "/"+ITALC_CONFIG_PATH+"/id_rsa";
101
const QString PUB_KEY_FILE = PRIV_KEY_FILE + ".public";
103
s_privateKey = readPrivateKey( PRIV_KEY_FILE );
104
if( s_privateKey == NULL )
106
// generate 1024bit RSA-key and save it
107
s_privateKey = rsaGeneratePrivateKey( 1024 );
108
writePrivateKey( s_privateKey, PRIV_KEY_FILE );
110
// derive public key from private key and save it
111
RSA * pub_key = publicKeyFromPrivateKey( s_privateKey );
112
writePublicKey( pub_key, PUB_KEY_FILE );
114
#if QT_VERSION >= 0x030200
115
if( splashScreen != NULL )
117
splashScreen->hide();
120
QMessageBox::information( NULL, tr( "New key-pair generated" ), tr( "No authentication-keys were found or your old ones "
121
"contained errors, so a new key-pair has been "
122
"generated.\nPlease ask your administrator for "
123
"distributing your public key. Otherwise you won't "
124
"be able to access clients." ), QMessageBox::Ok );
133
rfbConnection::rfbConnection( const QString & _host_ip ) :
135
m_connected( FALSE ),
136
m_hostIP( _host_ip ),
138
m_gotInvitationResult( FALSE ),
139
m_invitationOk( FALSE ),
142
m_scaledClientScreen(),
143
m_destImgSize( 640, 480 ),
144
m_bufOutPtr( m_buf ),
148
m_zlibStreamActive[0] = m_zlibStreamActive[1] = m_zlibStreamActive[2] = m_zlibStreamActive[3] = FALSE;
155
// copy ctor for using data frome existing connection
156
rfbConnection::rfbConnection( const rfbConnection & _rc ) :
158
m_connected( FALSE ),
159
m_hostIP( _rc.m_hostIP ),
161
m_gotInvitationResult( FALSE ),
162
m_invitationOk( FALSE ),
165
m_scaledClientScreen(),
166
m_destImgSize( 640, 480 ),
167
m_bufOutPtr( m_buf ),
170
m_zlibStreamActive[0] = m_zlibStreamActive[1] = m_zlibStreamActive[2] = m_zlibStreamActive[3] = FALSE;
176
rfbConnection::~rfbConnection()
184
bool rfbConnection::openConnection( void )
188
if( systemEnvironment::hostAvailable( m_hostIP ) == FALSE )
194
if( !stringToIPAddr( m_hostIP.ascii(), &host ) )
196
printf( "Couldn't convert '%s' to host address\n", m_hostIP.ascii() );
200
m_sock = connectToTCPAddr( host, VNC_SERVER_PORT_OFFSET );
204
//printf("Unable to connect to VNC server on client %s\n", m_hostIP.ascii());
208
if( fcntl( m_sock, F_SETFL, O_NONBLOCK ) < 0 )
210
printf( "Error while setting non-blocking\n" );
215
char protocol_version[13];
217
Q_UINT32 auth_scheme, reason_len;
219
s_rfb_client_init_msg ci;
221
if( !readFromServer( protocol_version, RFBP_VERSION_MESSAGE_LEN ) )
226
protocol_version[RFBP_VERSION_MESSAGE_LEN] = 0;
228
if( sscanf( protocol_version, RFBP_VERSION_FORMAT, &major, &minor ) != 2 )
230
printf( "Not a valid VNC server\n" );
234
//printf ("VNC server supports protocol version %d.%d (viewer %d.%d)\n", major, minor, RFBP_MAJOR_VERSION, RFBP_MINOR_VERSION);
236
//major = RFBP_MAJOR_VERSION;
237
//minor = RFBP_MINOR_VERSION;
239
//sprintf (protocol_version, protocol_version, major, minor);
241
if( !writeToServer( protocol_version, RFBP_VERSION_MESSAGE_LEN ) )
247
if( !readFromServer( (char *)&auth_scheme, sizeof( Q_UINT32 ) ) )
252
auth_scheme = Swap32IfLE( auth_scheme );
254
switch( auth_scheme )
256
case RFB_CONNECTION_FAILED:
257
if( !readFromServer( (char *)&reason_len, sizeof( Q_UINT32 ) ) )
261
reason_len = Swap32IfLE( reason_len );
263
reason = new char[reason_len];
265
if( readFromServer( reason, reason_len ) )
267
printf( "VNC connection failed: %.*s\n", (int) reason_len, reason );
272
case RFB_NO_AUTHENTICATION:
273
//printf ("No authentication needed\n");
275
#ifdef RSA_CRYPT_AVAILABLE
276
case RFB_VNC_CHALL_RESP_AUTHENTICATION:
278
// send user-name to server (server has to encrypt data with the appropriate key)
279
s_rfb_authentication ra;
280
QString user_name = getenv( "USER" );
282
ra.user_name_len = Swap16IfLE( user_name.length()+1 );
283
if( !writeToServer( (const char*) &ra, sizeof( ra ) ) )
285
if( !writeToServer( user_name.ascii(), user_name.length()+1 ) )
288
// challenge-response-authentication
289
int ecs = RSA_size( s_privateKey );
290
char * encrypted_challenge = new char[ecs];
291
if( !readFromServer( encrypted_challenge, ecs ) )
296
char * decrypted_response = new char[DEFAULT_CHALLENGE_SIZE];
298
int bytes = RSA_private_decrypt( ecs, (unsigned char *)encrypted_challenge, (unsigned char *)decrypted_response, s_privateKey, RSA_PKCS1_PADDING );
299
// TODO: add error handling if bytes != DEFAULT_CHALLENGE_SIZE
301
if( !writeToServer( decrypted_response, DEFAULT_CHALLENGE_SIZE ) )
305
delete[] encrypted_challenge;
306
delete[] decrypted_response;
307
Q_UINT32 auth_result;
308
if( !readFromServer( (char *)& auth_result, 4 ) )
312
auth_result = Swap32IfLE( auth_result );
313
switch( auth_result )
316
//printf( "VNC authentication succeeded\n" );
318
case RFB_AUTH_FAILED:
319
printf( "VNC authentication failed\n" );
321
case RFB_AUTH_TOO_MANY:
322
printf( "VNC authentication failed - too many tries\n" );
325
printf( "Unknown VNC authentication result: %d\n", (int) auth_result );
332
printf( "Unknown authentication scheme from VNC server: %d\n",(int) auth_scheme );
338
if( !writeToServer( (char *) &ci, sizeof( ci ) ) )
343
if( !readFromServer( (char *)&m_si, sizeof( m_si ) ) )
348
m_si.framebuffer_width = Swap16IfLE( m_si.framebuffer_width );
349
m_si.framebuffer_height = Swap16IfLE( m_si.framebuffer_height );
350
m_si.format.red_max = Swap16IfLE( m_si.format.red_max );
351
m_si.format.green_max = Swap16IfLE( m_si.format.green_max );
352
m_si.format.blue_max = Swap16IfLE( m_si.format.blue_max );
353
m_si.name_length = Swap32IfLE( m_si.name_length );
355
char desktop_name[m_si.name_length+1];
357
if( !readFromServer( desktop_name, m_si.name_length ) )
362
//desktop_name[m_si.name_length] = 0;
364
//printf ("Desktop name: \"%s\"\n",desktop_name);
365
//printf ("Connected to VNC server, using protocol version %d.%d\n", RFBP_MAJOR_VERSION, RFBP_MINOR_VERSION);
367
//printf(stderr,"VNC server default format:\n");
368
//PrintPixelFormat(&m_si.format);
370
s_rfb_set_pixel_format_msg spf;
372
spf.type = RFB_SET_PIXEL_FORMAT;
373
spf.format = s_localDisplayFormat;
374
spf.format.red_max = Swap16IfLE(spf.format.red_max);
375
spf.format.green_max = Swap16IfLE(spf.format.green_max);
376
spf.format.blue_max = Swap16IfLE(spf.format.blue_max);
378
if( !writeToServer( (char *) &spf, sizeof( s_rfb_set_pixel_format_msg ) ) )
384
char m_buf[sizeof(s_rfb_set_pixel_format_msg) + MAX_ENCODINGS * sizeof(Q_UINT32)];
385
s_rfb_set_encodings_msg * se = (s_rfb_set_encodings_msg *) m_buf;
386
se->type = RFB_SET_ENCODINGS;
389
Q_UINT32 * encs = (Q_UINT32 *)(&m_buf[sizeof(s_rfb_set_encodings_msg)]);
391
encs[se->n_encodings++] = Swap32IfLE( RFB_ENCODING_TIGHT );
392
encs[se->n_encodings++] = Swap32IfLE( RFB_ENCODING_CORRE );
393
encs[se->n_encodings++] = Swap32IfLE( RFB_ENCODIG_RRE );
394
encs[se->n_encodings++] = Swap32IfLE( RFB_ENCODING_COPYRECT );
397
encs[se->n_encodings++] = Swap32IfLE( RFB_ENCODING_COMPRESS_LEVEL_0+4 );
399
encs[se->n_encodings++] = Swap32IfLE( RFB_ENCODING_QUALITY_LEVEL_0+4 );
402
//encs[se->n_encodings++] = Swap32IfLE(RFB_ENCODING_LAST_RECT);
405
unsigned int len = sizeof( s_rfb_set_encodings_msg ) + se->n_encodings * sizeof( Q_UINT32 );
407
se->n_encodings = Swap16IfLE( se->n_encodings );
409
if( !writeToServer( m_buf, len ) )
414
//printf ("Pixel-format and encodings sucessfully setup...\n");
416
m_clientScreen = QImage( m_si.framebuffer_width, m_si.framebuffer_height, s_localDisplayFormat.depth );
418
sendFramebufferUpdateRequest();
429
void rfbConnection::closeConnection( void )
434
m_zlibStreamActive[0] = m_zlibStreamActive[1] = m_zlibStreamActive[2] = m_zlibStreamActive[3] = FALSE;
451
bool rfbConnection::resetConnection( const QString & _new_host_ip )
455
if( _new_host_ip != "" )
456
m_hostIP = _new_host_ip;
458
return( openConnection() );
464
bool rfbConnection::dataFromServer( void )
469
tv.tv_usec = 10000; // timeout = 10ms*/
470
tv.tv_sec = 1; // timeout = 1 s
473
FD_SET( m_sock, &fds );
474
if( select( m_sock+1, &fds, NULL, NULL, &tv ) <= 0 )
485
bool rfbConnection::readFromServer( char * _out, unsigned int _n )
487
if( _n <= m_buffered )
489
memcpy( _out, m_bufOutPtr, _n );
497
memcpy( _out, m_bufOutPtr, m_buffered );
507
if( _n <= INTERNAL_READ_BUF_SIZE )
509
while( m_buffered < _n )
511
int i = read( m_sock, m_buf+m_buffered, INTERNAL_READ_BUF_SIZE-m_buffered );
516
if( ( errno == EWOULDBLOCK || errno == EAGAIN )/* && ++retries < MAX_READ_RETRIES*/ )
518
//QApplication::eventLoop()->processEvents (QEventLoop::AllEvents, MAX_EVENT_PROC_TIME);
523
printf( "readFromServer: read(...) failed\n" );
530
printf( "VNC server closed connection\n" );
538
memcpy( _out, m_bufOutPtr, _n );
546
int i = read( m_sock, _out, _n );
551
if( ( errno == EWOULDBLOCK || errno == EAGAIN )/* && ++retries < MAX_READ_RETRIES*/ )
553
//QApplication::eventLoop()->processEvents (QEventLoop::AllEvents, MAX_EVENT_PROC_TIME);
558
printf( "readFromServer: read(...) failed\n" );
565
printf( "VNC server closed connection\n" );
581
bool rfbConnection::writeToServer( const char * _buf, unsigned int _n )
586
int j = write( m_sock, _buf + i, _n - i );
589
printf( "error while writing!\n" );
592
if( errno == EWOULDBLOCK || errno == EAGAIN )
596
FD_SET( m_sock, &fds );
597
if( select( m_sock+1, NULL, &fds, NULL, NULL ) <= 0 )
599
printf( "writeToServer: select(..) failed\n" );
607
printf( "writeToServer: write(..) failed (j < 0)\n" );
614
printf( "writeToServer: write(..) failed (j == 0)\n" );
628
long rfbConnection::readCompactLen( void )
632
if( !readFromServer( (char *)&b, sizeof( b ) ) )
637
long len = (int)b & 0x7F;
640
if( !readFromServer( (char *)&b, sizeof( b ) ) )
644
len |= ((int)b & 0x7F) << 7;
647
if( !readFromServer( (char *)&b, 1 ) )
651
len |= ((int)b & 0xFF) << 14;
661
bool rfbConnection::sendFramebufferUpdateRequest( void )
663
return( sendFramebufferUpdateRequest( 0, 0, m_si.framebuffer_width, m_si.framebuffer_height, FALSE ) );
669
bool rfbConnection::sendIncrementalFramebufferUpdateRequest( void )
671
return( sendFramebufferUpdateRequest( 0, 0, m_si.framebuffer_width, m_si.framebuffer_height, TRUE ) );
677
bool rfbConnection::sendFramebufferUpdateRequest( Q_UINT16 _x, Q_UINT16 _y, Q_UINT16 _w, Q_UINT16 _h, bool _incremental )
679
s_rfb_framebuffer_update_request_msg fur;
681
fur.type = RFB_FRAMEBUFFER_UPDATE_REQUEST;
682
fur.incremental = (_incremental == TRUE)? 1 : 0;
683
fur.x = Swap16IfLE( _x );
684
fur.y = Swap16IfLE( _y );
685
fur.w = Swap16IfLE( _w );
686
fur.h = Swap16IfLE( _h );
688
return( writeToServer( (char *) &fur, sizeof( fur ) ) );
694
bool rfbConnection::sendPointerEvent( Q_UINT16 _x, Q_UINT16 _y, Q_UINT16 _button_mask )
696
s_rfb_pointer_event_msg pe;
698
pe.type = RFB_POINTER_EVENT;
699
pe.button_mask = _button_mask;
700
//if (_x < 0) _x = 0;
701
//if (_y < 0) _y = 0;
702
pe.x = Swap16IfLE( _x );
703
pe.y = Swap16IfLE( _y );
705
return( writeToServer( (char *) &pe, sizeof( pe ) ) );
711
bool rfbConnection::sendKeyEvent( Q_UINT32 key, bool down )
713
s_rfb_key_event_msg ke;
715
ke.type = RFB_KEY_EVENT;
716
ke.down = (down == TRUE)? 1 : 0;
717
ke.key = Swap32IfLE( key );
719
return( writeToServer( (char *) &ke, sizeof( ke ) ) );
725
bool rfbConnection::sendGetUserRequest( void )
732
s_rfb_get_user_msg gu;
733
gu.cmd = RFB_ITALC_TO_SERVER_REQUEST;
734
gu.italc_cmd = ITALC_GET_USER;
736
return( writeToServer( (char *) &gu, sizeof( gu ) ) );
742
bool rfbConnection::execCmds( const QString & _cmd )
749
s_rfb_exec_cmds_msg ec;
750
ec.cmd = RFB_ITALC_TO_SERVER_REQUEST;
751
ec.italc_cmd = ITALC_EXEC_CMDS;
752
ec.cmd_len = Swap16IfLE( _cmd.length()+1 );
754
if( !writeToServer( (char *) &ec, sizeof( ec ) ) )
756
printf( "Could not send ITALC_EXEC_CMDS-request to client\n" );
760
return( writeToServer( _cmd.ascii(), _cmd.length()+1 ) );
766
bool rfbConnection::startDemo( const QString & _master_ip, bool _full_screen )
773
s_rfb_start_demo_msg sd;
774
sd.cmd = RFB_ITALC_TO_SERVER_REQUEST;
775
sd.italc_cmd = ITALC_START_DEMO;
776
sd.fullscreen = (_full_screen)? !0 : 0;
777
sd.demo_master_ip_len = Swap16IfLE( _master_ip.length()+1 );
778
if( !writeToServer( (char *) &sd, sizeof( sd ) ) )
780
printf( "Could not send ITALC_START_DEMO-request to client\n" );
784
return( writeToServer( _master_ip.ascii(), _master_ip.length()+1 ) );
790
bool rfbConnection::stopDemo( void )
797
s_rfb_stop_demo_msg sd;
798
sd.cmd = RFB_ITALC_TO_SERVER_REQUEST;
799
sd.italc_cmd = ITALC_STOP_DEMO;
801
return( writeToServer( (char *) &sd, sizeof( sd ) ) );
807
bool rfbConnection::lockDisplay( void )
814
s_rfb_lock_display_msg ld;
815
ld.cmd = RFB_ITALC_TO_SERVER_REQUEST;
816
ld.italc_cmd = ITALC_LOCK_DISPLAY;
818
return( writeToServer( (char *) &ld, sizeof( ld ) ) );
824
bool rfbConnection::unlockDisplay( void )
829
s_rfb_unlock_display_msg ud;
830
ud.cmd = RFB_ITALC_TO_SERVER_REQUEST;
831
ud.italc_cmd = ITALC_UNLOCK_DISPLAY;
833
return( writeToServer( (char *) &ud, sizeof( ud ) ) );
839
bool rfbConnection::sendMessage( const QString & _msg )
846
s_rfb_send_msg_msg sm;
847
sm.cmd = RFB_ITALC_TO_SERVER_REQUEST;
848
sm.italc_cmd = ITALC_SEND_MSG;
849
sm.msg_len = Swap16IfLE( _msg.length()+1 );
851
if( !writeToServer( (char *) &sm, sizeof( sm ) ) )
853
printf( "Could not send ITALC_SEND_MSG-request to client\n" );
857
return( writeToServer( _msg.ascii(), _msg.length()+1 ) );
863
bool rfbConnection::postFile( const QString & _fname )
866
if (!connected() || QFileInfo(_fname).exists() == FALSE || QFileInfo(_fname).isReadable() == FALSE)
869
Q_UINT32 fsize = QFileInfo(_fname).size();
873
QString realFileName = QFileInfo(_fname).fileName();
875
s_rfb_post_file_msg pf;
876
pf.cmd = RFB_ITALC_TO_SERVER_REQUEST;
877
pf.italc_cmd = ITALC_POST_FILE_REQ;
878
pf.fname_len = Swap16IfLE(realFileName.length()+1);
879
pf.fsize = Swap32IfLE(fsize);
881
if (!writeToServer((char *) &pf, sizeof(pf))) {
882
printf ("Could not send ITALC_POST_FILE_REQ-request to client\n");
886
if (!writeToServer(realFileName.ascii(), realFileName.length()+1)) {
887
printf ("Could not send file-name to client\n");
892
f.open (IO_ReadOnly);
893
Q_UINT32 processed = 0;
895
while (processed < fsize) {
896
const int BUF_SIZE = 1024;
897
char m_buffer[BUF_SIZE];
898
Q_LONG read = f.readBlock (m_buffer, BUF_SIZE);
900
if (!writeToServer(m_buffer, read)) {
901
printf ("Could not send file-content to client (%d of %d bytes already sent)\n", (int) processed, (int) fsize);
905
} else if (read < 0) {
906
printf ("An error occured while reading file (%d of %d bytes already sent)\n", (int) processed, (int) fsize);
909
usleep(25); // avoid m_buffer-overflow in client's TCP/IP-m_buffer...
919
bool rfbConnection::getFile( const QString & _nfilter )
924
s_rfb_get_file_msg gf;
925
gf.cmd = RFB_ITALC_TO_SERVER_REQUEST;
926
gf.italc_cmd = ITALC_GET_FILE;
927
gf.fmask_len = Swap16IfLE(_nfilter.length()+1);
929
if (!writeToServer((char *) &gf, sizeof(gf))) {
930
printf ("Could not send ITALC_GET_FILE-request to client\n");
934
return (writeToServer(_nfilter.ascii(), _nfilter.length()+1));
941
bool rfbConnection::inviteForSupport( const QString & _user_name )
948
s_rfb_invite_support_msg is;
949
is.cmd = RFB_ITALC_TO_SERVER_REQUEST;
950
is.italc_cmd = ITALC_INVITE_SUPPORT;
951
is.uname_len = Swap16IfLE( _user_name.length()+1 );
953
if( !writeToServer( (char *) &is, sizeof( is ) ) )
955
printf( "Could not send ITALC_INVITE_SUPPORT-request to client\n" );
959
if( !writeToServer( _user_name.ascii(), _user_name.length()+1 ) )
961
printf( "Could not write user-name to client\n" );
965
m_gotInvitationResult = FALSE;
966
m_invitationOk = FALSE;
968
while( m_gotInvitationResult == FALSE && handleServerMessages( FALSE ) == TRUE )
972
// return result, if error occured while handling server-messages, m_invitationOk is untouched -> FALSE
973
return( m_invitationOk );
979
bool rfbConnection::handleServerMessages( bool _send_screen_update )
981
u_rfb_server_to_client_msg msg;
983
while( dataFromServer() == TRUE )
986
if( !readFromServer( (char *) &msg, sizeof( Q_UINT8 ) ) )
988
printf( "Reading of message-type failed\n" );
994
case RFB_SET_COLORMAP_ENTRIES:
995
printf( "Got signal for setting colormap entries. Ignoring.\n" );
998
case RFB_FRAMEBUFFER_UPDATE:
1000
if( !readFromServer( ( (char *)&msg.fu ) + 1, sizeof( s_rfb_framebuffer_update_msg )- 1 ) )
1005
msg.fu.n_rects = Swap16IfLE( msg.fu.n_rects );
1007
s_rfb_framebuffer_update_rect_header rect;
1008
for( Q_UINT16 i = 0; i < msg.fu.n_rects; i++ )
1010
if( !readFromServer( (char *)&rect, sizeof( s_rfb_framebuffer_update_rect_header ) ) )
1015
rect.r.x = Swap16IfLE( rect.r.x );
1016
rect.r.y = Swap16IfLE( rect.r.y );
1017
rect.r.w = Swap16IfLE( rect.r.w );
1018
rect.r.h = Swap16IfLE( rect.r.h );
1020
rect.encoding = Swap32IfLE( rect.encoding );
1021
if( rect.encoding == RFB_ENCODING_LAST_RECT )
1026
if( ( rect.r.x + rect.r.w > m_si.framebuffer_width ) ||
1027
( rect.r.y + rect.r.h > m_si.framebuffer_height ) )
1029
printf( "Rect too large: %dx%d at (%d, %d)\n", rect.r.w, rect.r.h, rect.r.x, rect.r.y );
1033
if( ( rect.r.h * rect.r.w ) == 0 )
1035
printf( "Zero size rect - ignoring\n" );
1039
switch( rect.encoding )
1041
case RFB_ENCODIG_RAW:
1043
Q_UINT16 bytes_per_line = rect.r.w * (s_localDisplayFormat.bits_per_pixel/8);
1044
Q_UINT16 lines_to_read = (Q_UINT16) (BUFFER_SIZE / bytes_per_line);
1045
while( rect.r.h > 0 )
1047
if( lines_to_read > rect.r.h )
1049
lines_to_read = rect.r.h;
1051
if( !readFromServer( m_buffer, bytes_per_line * lines_to_read ) )
1055
QRgb * src = (QRgb *) m_buffer;
1056
Q_UINT16 x2 = rect.r.x+rect.r.w;
1057
for( Q_UINT16 y = 0; y < lines_to_read; y++ )
1059
QRgb * dest = (QRgb *)m_clientScreen.scanLine( rect.r.y+y );
1060
for( Q_UINT16 x = rect.r.x; x < x2; ++x )
1066
rect.r.h -= lines_to_read;
1067
rect.r.y += lines_to_read;
1071
case RFB_ENCODING_COPYRECT:
1074
if( !readFromServer( (char *) &cr, sizeof( s_rfb_copy_rect ) ) )
1078
cr.src_x = Swap16IfLE( cr.src_x );
1079
cr.src_y = Swap16IfLE( cr.src_y );
1081
copyExistingRect( m_clientScreen, cr.src_x, cr.src_y, rect.r.w, rect.r.h, rect.r.x, rect.r.y );
1082
printf( "copy rect - should not occur!!\n" );
1085
case RFB_ENCODIG_RRE:
1087
if( !handleRRE( rect.r.x, rect.r.y, rect.r.w, rect.r.h ) )
1093
case RFB_ENCODING_CORRE:
1095
if( !handleCoRRE( rect.r.x, rect.r.y, rect.r.w, rect.r.h ) )
1103
case RFB_ENCODING_TIGHT:
1105
if( !handleTight( rect.r.x, rect.r.y, rect.r.w, rect.r.h ) )
1114
printf( "Unknown rect encoding %d\n", (int) rect.encoding );
1119
if( m_destImgSize.width() > 0 && m_destImgSize.height() > 0 )
1121
// first create temporary image whose size matches destination-image-size
1122
QImage temporary_image = QImage( m_destImgSize, s_localDisplayFormat.depth );
1123
// now scale the image and store the output to temporary_image
1124
fastScaleImage( m_clientScreen, temporary_image );
1125
// now copy temporary_image to scaled client-screen
1127
m_scaledClientScreen = temporary_image;
1133
// FIXME: bell-action
1136
case RFB_SERVER_CUT_TEXT:
1138
if( !readFromServer( ( (char *) &msg ) + 1, sizeof( s_rfb_server_cut_text_msg ) - 1 ) )
1142
msg.sct.length = Swap32IfLE( msg.sct.length );
1143
char server_cut_text[msg.sct.length+1];
1144
if( !readFromServer( server_cut_text, msg.sct.length ) )
1148
//server_cut_text[msg.sct.length] = 0;
1149
//printf ("Server-Cut-Text: %s\n", server_cut_text);
1153
case RFB_SERVER_TO_ITALC_RESPONSE:
1155
s_rfb_server_response sr;
1156
if( !readFromServer( (char *) &sr.italc_cmd, sizeof( sr.italc_cmd ) ) )
1162
case ITALC_POST_USER:
1164
if( !readFromServer( ( (char *) &sr ) + 2, sizeof( s_rfb_post_user_msg )-2 ) )
1168
sr.post_user_msg.user_name_len = Swap16IfLE( sr.post_user_msg.user_name_len );
1169
char * user_name = new char[sr.post_user_msg.user_name_len];
1170
if( !readFromServer( user_name, sr.post_user_msg.user_name_len ) )
1179
case ITALC_INVITATION_RESULT:
1181
if( !readFromServer( ( (char *) &sr ) + 2, sizeof( s_rfb_invitation_result_msg ) - 2 ) )
1185
m_invitationOk = sr.invitation_result_msg.inv_accepted;
1186
m_gotInvitationResult = TRUE;
1189
/* case ITALC_POST_FILE_RESP: {
1190
if (!readFromServer(((char *) &sr)+2, sizeof(s_rfb_post_file_msg)-2))
1192
sr.post_file_msg.fname_len = Swap16IfLE(sr.post_file_msg.fname_len);
1193
sr.post_file_msg.fsize = Swap32IfLE(sr.post_file_msg.fsize);
1194
char * file_name = new char[sr.post_file_msg.fname_len];
1195
if (!readFromServer(file_name, sr.post_file_msg.fname_len)) {
1199
system ("mkdir -p ~/collected_files/"+m_user);
1200
int fd = open(QString(getenv("HOME"))+"/collected_files/"+m_user+"/"+QFileInfo(file_name).fileName(), O_CREAT|O_WRONLY, 0666);
1201
Q_UINT32 total_bytes = sr.post_file_msg.fsize;
1202
Q_UINT32 bytes_done = 0;
1203
while (bytes_done < total_bytes) {
1204
char m_buffer[BUFFER_SIZE];
1205
Q_UINT32 bytes_todo = BUFFER_SIZE;
1206
if (total_bytes - bytes_done < bytes_todo)
1207
bytes_todo = total_bytes - bytes_done;
1208
if (!readFromServer(m_buffer, bytes_todo)) {
1214
write(fd, m_buffer, bytes_todo);
1215
bytes_done += bytes_todo;
1222
printf( "Unknown server response %d\n", (int) sr.cmd );
1229
printf( "Unknown message type %d from VNC server. Closing connection. Will re-open it later.\n", msg.type );
1234
} // end while( ... )
1237
if( _send_screen_update )
1239
if( !sendIncrementalFramebufferUpdateRequest() )
1256
// ========================================================================================================================
1257
// functions for network-IO
1258
// ========================================================================================================================
1261
int rfbConnection::connectToTCPAddr( in_addr_t _host, int _port )
1263
struct sockaddr_in addr;
1266
addr.sin_family = AF_INET;
1267
addr.sin_port = htons(_port);
1268
addr.sin_addr.s_addr = _host;
1269
int m_sock = socket(AF_INET, SOCK_STREAM, 0);
1272
printf( "connectToTCPAdress: socket(...) failed\n" );
1276
if( ::connect( m_sock, ( struct sockaddr * )&addr, sizeof( addr ) ) < 0 )
1278
//printf ("connectToTCPAdress: connect(...) failed\n");
1283
if( setsockopt( m_sock, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof( one ) ) < 0 )
1285
printf( "connectToTCPAdress: setsockopt(...) failed\n" );
1298
bool rfbConnection::stringToIPAddr( const QString & _host, in_addr_t * _addr )
1302
*_addr = 0; // local
1306
*_addr = inet_addr( _host.ascii() );
1308
if( *_addr != (in_addr_t) -1 )
1313
struct hostent * hp = gethostbyname( _host.ascii() );
1317
*_addr = *(in_addr_t *)hp->h_addr;
1327
// ========================================================================================================================
1328
// functions for decoding rects
1329
// ========================================================================================================================
1332
bool rfbConnection::handleCoRRE( Q_UINT16 rx, Q_UINT16 ry, Q_UINT16 rw, Q_UINT16 rh )
1334
s_rfb_RRE_header hdr;
1336
if( !readFromServer( (char *) &hdr, sizeof( s_rfb_RRE_header ) ) )
1341
hdr.n_subrects = Swap32IfLE( hdr.n_subrects );
1344
if( !readFromServer( (char *) &pix, sizeof( pix ) ) )
1349
fillRect( m_clientScreen, rx, ry, rw, rh, pix );
1351
if( !readFromServer( m_buffer, hdr.n_subrects * ( sizeof( s_rfb_CoRRE_rectangle ) + sizeof( Q_UINT32 ) ) ) )
1356
Q_UINT8 * ptr = (Q_UINT8 *) m_buffer;
1358
for( Q_UINT32 i = 0; i < hdr.n_subrects; i++ )
1360
pix = *(QRgb *) ptr;
1361
ptr += sizeof( pix );
1366
fillRect( m_clientScreen, rx+x, ry+y, w, h, pix );
1374
bool rfbConnection::handleRRE( Q_UINT16, Q_UINT16, Q_UINT16, Q_UINT16 )
1376
printf ("Fatal: Got RRE-encoded rect. Can't decode.\n");
1383
#define TIGHT_MIN_TO_COMPRESS 12
1386
#define RGB_TO_PIXEL(r,g,b) \
1387
(((Q_UINT32)(r) & s_localDisplayFormat.red_max) << s_localDisplayFormat.red_shift | \
1388
((Q_UINT32)(g) & s_localDisplayFormat.green_max) << s_localDisplayFormat.green_shift | \
1389
((Q_UINT32)(b) & s_localDisplayFormat.blue_max) << s_localDisplayFormat.blue_shift)
1393
// type declarations
1395
typedef void (rfbConnection:: *filterPtr) (Q_UINT16, Q_UINT32 *);
1401
bool rfbConnection::handleTight( Q_UINT16 rx, Q_UINT16 ry, Q_UINT16 rw, Q_UINT16 rh )
1406
if( !readFromServer( (char *) &comp_ctl, 1 ) )
1411
// Flush zlib streams if we are told by the server to do so.
1412
for( Q_UINT8 stream_id = 0; stream_id < 4; stream_id++ )
1414
if( ( comp_ctl & 1 ) && m_zlibStreamActive[stream_id] )
1416
if( inflateEnd( &m_zlibStream[stream_id] ) != Z_OK && m_zlibStream[stream_id].msg != NULL )
1418
printf( "inflateEnd: %s\n", m_zlibStream[stream_id].msg );
1420
m_zlibStreamActive[stream_id] = FALSE;
1425
// Handle solid rectangles.
1426
if( comp_ctl == RFB_TIGHT_FILL )
1428
if( !readFromServer( (char*)&fill_color, sizeof( fill_color ) ) )
1432
fillRect( m_clientScreen, rx, ry, rw, rh, fill_color );
1436
if( comp_ctl == RFB_TIGHT_JPEG )
1439
return( decompressJpegRect( rx, ry, rw, rh ) );
1446
// Quit on unsupported subencoding value.
1447
if( comp_ctl > RFB_TIGHT_MAX_SUBENCODING )
1449
printf( "Tight encoding: bad subencoding value received.\n" );
1453
// Here primary compression mode handling begins.
1454
// Data was processed with optional filter + zlib compression.
1455
filterPtr filter_function;
1458
// First, we should identify a filter to use.
1459
if( ( comp_ctl & RFB_TIGHT_EXPLICIT_FILTER ) != 0 )
1462
if( !readFromServer( (char*) &filter_id, 1 ) )
1469
case RFB_TIGHT_FILTER_COPY:
1470
filter_function = &rfbConnection::filterCopy;
1471
bits_pixel = initFilterCopy( rw, rh );
1473
case RFB_TIGHT_FILTER_PALETTE:
1474
filter_function = &rfbConnection::filterPalette;
1475
bits_pixel = initFilterPalette( rw, rh );
1477
case RFB_TIGHT_FILTER_GRADIENT:
1478
filter_function = &rfbConnection::filterGradient;
1479
bits_pixel = initFilterGradient( rw, rh );
1482
printf( "Tight encoding: unknown filter code received.\n" );
1488
filter_function = &rfbConnection::filterCopy;
1489
bits_pixel = initFilterCopy( rw, rh );
1491
if( bits_pixel == 0 )
1493
printf( "Tight encoding: error receiving palette.\n" );
1498
// Determine if the data should be decompressed or just copied.
1499
Q_UINT16 row_size = ( rw * bits_pixel + 7 ) / 8;
1500
if( rh * row_size < TIGHT_MIN_TO_COMPRESS )
1502
if( !readFromServer( (char*)m_buffer, rh * row_size ) )
1507
QRgb * buffer2 = (QRgb *) &m_buffer[TIGHT_MIN_TO_COMPRESS * 4];
1508
( this->*( filter_function ) )( rh, (Q_UINT32 *)buffer2 );
1509
copyRect( m_clientScreen, rx, ry, rw, rh, buffer2 );
1513
// Read the length (1..3 bytes) of compressed data following.
1514
int compressed_len = (int)readCompactLen();
1515
if( compressed_len <= 0 )
1517
printf( "Incorrect data received from the server.\n" );
1522
// Now let's initialize compression stream if needed. */
1523
Q_UINT8 stream_id = comp_ctl & 0x03;
1524
z_streamp zs = &m_zlibStream[stream_id];
1525
if( !m_zlibStreamActive[stream_id] )
1527
zs->zalloc = Z_NULL;
1529
zs->opaque = Z_NULL;
1530
int err = inflateInit( zs );
1533
if( zs->msg != NULL )
1535
printf( "InflateInit error: %s.\n", zs->msg );
1539
m_zlibStreamActive[stream_id] = TRUE;
1543
// Read, decode and draw actual pixel data in a loop. */
1544
int buffer_size = BUFFER_SIZE * bits_pixel / ( bits_pixel+32 ) & 0xFFFFFFFC;
1545
if( row_size > buffer_size )
1547
// Should be impossible when BUFFER_SIZE >= 16384
1548
printf( "Internal error: incorrect m_buffer size.\n" );
1551
QRgb * buffer2 = (QRgb *) &m_buffer[buffer_size];
1554
Q_UINT16 rows_processed = 0;
1555
int extra_bytes = 0;
1558
while( compressed_len > 0 )
1560
if( compressed_len > ZLIB_BUFFER_SIZE )
1562
portion_len = ZLIB_BUFFER_SIZE;
1566
portion_len = compressed_len;
1569
if( !readFromServer( (char*)m_zlibBuffer, portion_len ) )
1574
compressed_len -= portion_len;
1576
zs->next_in = (Bytef *)m_zlibBuffer;
1577
zs->avail_in = portion_len;
1581
zs->next_out = (Bytef *) &m_buffer[extra_bytes];
1582
zs->avail_out = buffer_size - extra_bytes;
1584
int err = inflate(zs, Z_SYNC_FLUSH);
1585
if( err == Z_BUF_ERROR ) // Input exhausted -- no problem.
1589
if( err != Z_OK && err != Z_STREAM_END )
1591
if( zs->msg != NULL )
1593
printf( "Inflate error: %s.\n", zs->msg );
1597
printf( "Inflate error: %d.\n", err );
1602
Q_UINT16 num_rows = (Q_UINT16)( ( buffer_size - zs->avail_out ) / (int)row_size );
1604
( this->*( filter_function ) )( num_rows, (Q_UINT32 *)buffer2 );
1605
extra_bytes = buffer_size - zs->avail_out - num_rows * row_size;
1606
if( extra_bytes > 0 )
1608
memcpy( m_buffer, &m_buffer[num_rows * row_size], extra_bytes );
1611
copyRect( m_clientScreen, rx, ry+rows_processed, rw, num_rows, buffer2 );
1612
rows_processed += num_rows;
1614
while( zs->avail_out == 0 );
1617
if( rows_processed != rh )
1619
printf( "Incorrect number of scan lines after decompression.\n" );
1628
/*----------------------------------------------------------------------------
1634
Q_UINT8 rfbConnection::initFilterCopy( Q_UINT16 rw, Q_UINT16/* rh*/ )
1644
void rfbConnection::filterCopy( Q_UINT16 num_rows, Q_UINT32 * dst )
1646
memcpy( dst, m_buffer, num_rows * m_rectWidth * sizeof( Q_UINT32 ) );
1652
Q_UINT8 rfbConnection::initFilterGradient( Q_UINT16 rw, Q_UINT16/* rh*/ )
1655
memset( m_tightPrevRow, 0, rw * 3 * sizeof( Q_UINT16 ) );
1657
return( sizeof( QRgb ) );
1663
void rfbConnection::filterGradient( Q_UINT16 num_rows, Q_UINT32 * dst )
1665
Q_UINT32 * src = (Q_UINT32 *) m_buffer;
1666
Q_UINT16 * that_row = (Q_UINT16 *) m_tightPrevRow;
1667
Q_UINT16 this_row[2048*3];
1669
Q_UINT16 max[3] = { s_localDisplayFormat.red_max, s_localDisplayFormat.green_max, s_localDisplayFormat.blue_max } ;
1670
Q_UINT8 shift[3] = { s_localDisplayFormat.red_shift, s_localDisplayFormat.green_shift, s_localDisplayFormat.blue_shift } ;
1674
for( Q_UINT16 y = 0; y < num_rows; y++ )
1676
// First pixel in a row
1677
for( Q_UINT8 c = 0; c < 3; c++ )
1679
pix[c] = (Q_UINT16)((src[y*m_rectWidth] >> shift[c]) + that_row[c] & max[c]);
1680
this_row[c] = pix[c];
1682
dst[y*m_rectWidth] = RGB_TO_PIXEL(pix[0], pix[1], pix[2]);
1683
// Remaining pixels of a row
1684
for( Q_UINT16 x = 1; x < m_rectWidth; x++ )
1686
for( Q_UINT8 c = 0; c < 3; c++ )
1688
est[c] = (Q_INT16)that_row[x*3+c] + (Q_INT16)pix[c] - (Q_INT16)that_row[(x-1)*3+c];
1689
if( est[c] > (Q_INT16)max[c] )
1691
est[c] = (Q_INT16)max[c];
1693
else if( est[c] < 0 )
1697
pix[c] = (Q_UINT16)((src[y*m_rectWidth+x] >> shift[c]) + est[c] & max[c]);
1698
this_row[x*3+c] = pix[c];
1700
dst[y*m_rectWidth+x] = RGB_TO_PIXEL( pix[0], pix[1], pix[2] );
1702
memcpy( that_row, this_row, m_rectWidth * 3 * sizeof( Q_UINT16 ) );
1709
Q_UINT8 rfbConnection::initFilterPalette( Q_UINT16 rw, Q_UINT16/* rh*/ )
1715
if( !readFromServer( (char*)&num_colors, sizeof( num_colors ) ) )
1720
m_rectColors = (Q_UINT16) num_colors;
1721
if( ++m_rectColors < 2 )
1726
if( !readFromServer( (char*)&m_tightPalette, m_rectColors * sizeof( Q_UINT32 ) ) )
1731
return( ( m_rectColors == 2 ) ? 1 : 8 );
1737
void rfbConnection::filterPalette( Q_UINT16 num_rows, Q_UINT32 * dst )
1739
Q_UINT8 * src = (Q_UINT8 *)m_buffer;
1740
Q_UINT32 * palette = (Q_UINT32 *) m_tightPalette;
1742
if( m_rectColors == 2 )
1744
const Q_UINT16 w = (m_rectWidth + 7) / 8;
1745
for( Q_UINT16 y = 0; y < num_rows; y++ )
1747
const Q_UINT32 base = y*m_rectWidth;
1748
for( Q_UINT16 x = 0; x < m_rectWidth/8; x++ )
1750
for( Q_INT8 b = 7; b >= 0; b-- )
1752
dst[base+x*8+7-b] = palette[src[y*w+x] >> b & 1];
1755
for( Q_INT8 b = 7; b >= 8 - m_rectWidth % 8; b-- )
1757
dst[base+m_rectWidth+7-b] = palette[src[y*w+m_rectWidth/8] >> b & 1];
1763
for( Q_UINT16 y = 0; y < num_rows; y++ )
1765
const Q_UINT32 base = y*m_rectWidth;
1766
for( Q_UINT16 x = 0; x < m_rectWidth; x++ )
1768
dst[base+x] = palette[(int)src[base+x]];
1776
/*----------------------------------------------------------------------------
1778
* JPEG decompression.
1783
void jpegInitSource( jpeglib::j_decompress_ptr )
1790
jpeglib::boolean jpegFillInputBuffer( jpeglib::j_decompress_ptr )
1792
printf( "ERROR: jpegFillInputBuffer(...) called (not implemented, because it should not be needed\n" );
1799
void jpegSkipInputData( jpeglib::j_decompress_ptr, long )
1801
printf( "ERROR: jpegSkipInputData(...) called (not implemented, because it should not be needed\n" );
1807
void jpegTermSource( jpeglib::j_decompress_ptr )
1813
using jpeglib::jpeg_decompress_struct;
1815
bool rfbConnection::decompressJpegRect( Q_UINT16 x, Q_UINT16 y, Q_UINT16 w, Q_UINT16 h )
1817
int compressed_len = (int) readCompactLen();
1818
if( compressed_len <= 0 )
1820
printf( "Incorrect data received from the server.\n" );
1824
Q_UINT8 compressed_data[compressed_len];
1826
if( !readFromServer( (char*)compressed_data, compressed_len ) )
1831
struct jpeglib::jpeg_error_mgr jerr;
1832
struct jpeglib::jpeg_decompress_struct cinfo;
1833
cinfo.err = jpeglib::jpeg_std_error( &jerr );
1834
jpeglib::jpeg_create_decompress( &cinfo );
1836
//jpegSetSrcManager (&cinfo, compressed_data, compressed_len);
1837
m_jpegSrcManager.init_source = jpegInitSource;
1838
m_jpegSrcManager.fill_input_buffer = jpegFillInputBuffer;
1839
m_jpegSrcManager.skip_input_data = jpegSkipInputData;
1840
m_jpegSrcManager.resync_to_restart = jpeglib::jpeg_resync_to_restart;
1841
m_jpegSrcManager.term_source = jpegTermSource;
1842
m_jpegSrcManager.next_input_byte = (jpeglib::JOCTET *) compressed_data;
1843
m_jpegSrcManager.bytes_in_buffer = (size_t) compressed_len;
1845
cinfo.src = &m_jpegSrcManager;
1848
jpeglib::jpeg_read_header( &cinfo, TRUE );
1849
cinfo.out_color_space = jpeglib::JCS_RGB;
1851
jpeglib::jpeg_start_decompress( &cinfo );
1852
if( cinfo.output_width != w || cinfo.output_height != h || cinfo.output_components != 3 )
1854
printf( "Tight Encoding: Wrong JPEG data received.\n" );
1855
jpeglib::jpeg_destroy_decompress( &cinfo );
1859
jpeglib::JSAMPROW row_pointer[1];
1860
row_pointer[0] = (jpeglib::JSAMPROW) m_buffer;
1862
while( cinfo.output_scanline < cinfo.output_height )
1864
jpeglib::jpeg_read_scanlines( &cinfo, row_pointer, 1 );
1865
Q_UINT32 * pixel_ptr = (Q_UINT32 *) &m_buffer[BUFFER_SIZE / 2];
1866
for( Q_UINT16 dx = 0; dx < w; dx++ )
1868
*pixel_ptr++ = RGB_TO_PIXEL( m_buffer[dx*3], m_buffer[dx*3+1], m_buffer[dx*3+2] );
1870
copyRect( m_clientScreen, x, y+dy, w, 1, (QRgb *) &m_buffer[BUFFER_SIZE / 2] );
1874
jpeglib::jpeg_finish_decompress( &cinfo );
1876
jpeglib::jpeg_destroy_decompress( &cinfo );
1881
#endif /* LIBJPEG */
1890
// this is an optimized version of Qt's smoothScale... the adventage is, that I could remove all code, dealing with
1891
// alpha-layers. The second thing is, that this code will be optimized for use on CPU with MMX and SSE. The Qt libraries
1892
// are per default compiled for i586 only...
1893
void fastScaleImage( const QImage & src, QImage & dst )
1895
QRgb * xelrow = NULL;
1896
QRgb * tempxelrow = NULL;
1897
Q_UINT16 rowswritten = 0;
1898
const uchar maxval = 255;
1900
Q_UINT16 cols = src.width();
1901
Q_UINT16 rows = src.height();
1902
Q_UINT16 newcols = dst.width();
1903
Q_UINT16 newrows = dst.height();
1915
Q_UINT16 fac = 4096;
1916
while( cols * fac > 4096 )
1921
HALFSCALE = fac * cols / 2;
1924
long sxscale = (long)( (double) newcols / (double) cols * SCALE );
1925
long syscale = (long)( (double) newrows / (double) rows * SCALE );
1927
if( newrows != rows ) // shortcut Y scaling if possible
1928
tempxelrow = new QRgb[cols];
1930
long * rs = new long[cols];
1931
long * gs = new long[cols];
1932
long * bs = new long[cols];
1933
Q_UINT16 rowsread = 0;
1934
register long fracrowleft = syscale;
1935
register Q_UINT16 needtoreadrow = 1;
1937
for( Q_UINT16 col = 0; col < cols; ++col )
1939
rs[col] = gs[col] = bs[col] = HALFSCALE;
1942
register long fracrowtofill = SCALE;
1944
register QRgb * nxP;
1946
for( Q_UINT16 row = 0; row < newrows; ++row )
1948
// First scale Y from xelrow into tempxelrow.
1949
if( newrows == rows )
1951
// shortcut Y scaling if possible
1952
tempxelrow = xelrow = (QRgb*)src.scanLine( rowsread++ );
1956
while( fracrowleft < fracrowtofill )
1958
if( needtoreadrow && rowsread < rows )
1960
xelrow = (QRgb*)src.scanLine( rowsread++ );
1963
for( Q_UINT16 col = 0; col < cols; ++col, ++xP )
1965
rs[col] += fracrowleft * qRed( *xP );
1966
gs[col] += fracrowleft * qGreen( *xP );
1967
bs[col] += fracrowleft * qBlue( *xP );
1969
fracrowtofill -= fracrowleft;
1970
fracrowleft = syscale;
1973
// Now fracrowleft is >= fracrowtofill, so we can produce a row.
1974
if( needtoreadrow && rowsread < rows )
1976
xelrow = (QRgb*)src.scanLine( rowsread++ );
1981
for( Q_UINT16 col = 0; col < cols; ++col, ++xP, ++nxP )
1983
register long r, g, b;
1984
r = rs[col] + fracrowtofill * qRed( *xP );
1985
g = gs[col] + fracrowtofill * qGreen( *xP );
1986
b = bs[col] + fracrowtofill * qBlue( *xP );
2006
*nxP = qRgb( (int)r, (int)g, (int)b );
2007
rs[col] = gs[col] = bs[col] = HALFSCALE;
2009
fracrowleft -= fracrowtofill;
2010
if( fracrowleft == 0 )
2012
fracrowleft = syscale;
2015
fracrowtofill = SCALE;
2018
// Now scale X from tempxelrow into dst and write it out.
2019
if( newcols == cols )
2021
// shortcut X scaling if possible
2022
memcpy( dst.scanLine(rowswritten++), tempxelrow, newcols*4 );
2026
register long r, g, b;
2027
register long fraccoltofill, fraccolleft = 0;
2028
register Q_UINT16 needcol;
2030
nxP = (QRgb*)dst.scanLine( rowswritten++ );
2031
fraccoltofill = SCALE;
2032
r = g = b = HALFSCALE;
2035
for( Q_UINT16 col = 0; col < cols; ++col, ++xP )
2037
fraccolleft = sxscale;
2038
while( fraccolleft >= fraccoltofill )
2043
r = g = b = HALFSCALE;
2045
r += fraccoltofill * qRed( *xP );
2046
g += fraccoltofill * qGreen( *xP );
2047
b += fraccoltofill * qBlue( *xP );
2067
*nxP = qRgb( (int)r, (int)g, (int)b );
2068
fraccolleft -= fraccoltofill;
2069
fraccoltofill = SCALE;
2072
if( fraccolleft > 0 )
2077
r = g = b = HALFSCALE;
2080
r += fraccolleft * qRed( *xP );
2081
g += fraccolleft * qGreen( *xP );
2082
b += fraccolleft * qBlue( *xP );
2083
fraccoltofill -= fraccolleft;
2086
if( fraccoltofill > 0 )
2089
r += fraccoltofill * qRed( *xP );
2090
g += fraccoltofill * qGreen( *xP );
2091
b += fraccoltofill * qBlue( *xP );
2113
*nxP = qRgb( (int)r, (int)g, (int)b );
2118
if( newrows != rows && tempxelrow )// Robust, tempxelrow might be 0 one day
2120
delete[] tempxelrow;
2122
if( rs ) // Robust, rs might be 0 one day
2126
if( gs ) // Robust, gs might be 0 one day
2130
if( bs ) // Robust, bs might be 0 one day