1 /**************************************************************************/ 2 /* */ 3 /* Copyright (c) 2001, 2010 NoMachine, http://www.nomachine.com/. */ 4 /* */ 5 /* NXCOMP, NX protocol compression and NX extensions to this software */ 6 /* are copyright of NoMachine. Redistribution and use of the present */ 7 /* software is allowed according to terms specified in the file LICENSE */ 8 /* which comes in the source distribution. */ 9 /* */ 10 /* Check http://www.nomachine.com/licensing.html for applicability. */ 11 /* */ 12 /* NX and NoMachine are trademarks of Medialogic S.p.A. */ 13 /* */ 14 /* All rights reserved. */ 15 /* */ 16 /**************************************************************************/ 17 18 // 19 // Include the template for 20 // this message class. 21 // 22 23 #include "RenderCompositeGlyphsCompat.h" 24 25 // 26 // Set the verbosity level. 27 // 28 29 #define PANIC 30 #define WARNING 31 #undef TEST 32 #undef DEBUG 33 34 #include MESSAGE_TAGS 35 36 // 37 // Message handling methods. 38 // 39 40 MESSAGE_BEGIN_ENCODE_SIZE 41 { 42 ClientCache *clientCache = (ClientCache *) channelCache; 43 44 // 45 // The offset points 8 bytes after 46 // the beginning of the data part. 47 // 48 49 #ifdef DEBUG 50 *logofs << name() << ": Encoding value " 51 << ((size - (MESSAGE_OFFSET - 8)) >> 2) 52 << ".\n" << logofs_flush; 53 #endif 54 55 encodeBuffer.encodeCachedValue((size - (MESSAGE_OFFSET - 8)) >> 2, 16, 56 clientCache -> renderLengthCache, 5); 57 58 #ifdef TEST 59 *logofs << name() << ": Encoded size with value " 60 << size << ".\n" << logofs_flush; 61 #endif 62 } 63 MESSAGE_END_ENCODE_SIZE 64 65 MESSAGE_BEGIN_DECODE_SIZE 66 { 67 ClientCache *clientCache = (ClientCache *) channelCache; 68 69 decodeBuffer.decodeCachedValue(size, 16, 70 clientCache -> renderLengthCache, 5); 71 72 #ifdef DEBUG 73 *logofs << name() << ": Decoded value " << size 74 << ".\n" << logofs_flush; 75 #endif 76 77 size = (MESSAGE_OFFSET - 8) + (size << 2); 78 79 buffer = writeBuffer -> addMessage(size); 80 81 #ifdef TEST 82 *logofs << name() << ": Decoded size with value " 83 << size << ".\n" << logofs_flush; 84 #endif 85 } 86 MESSAGE_END_DECODE_SIZE 87 88 MESSAGE_BEGIN_ENCODE_MESSAGE 89 { 90 ClientCache *clientCache = (ClientCache *) channelCache; 91 92 encodeBuffer.encodeCachedValue(*(buffer + 4), 8, 93 clientCache -> renderOpCache); 94 95 encodeBuffer.encodeXidValue(GetULONG(buffer + 8, bigEndian), 96 clientCache -> renderSrcPictureCache); 97 98 encodeBuffer.encodeXidValue(GetULONG(buffer + 12, bigEndian), 99 clientCache -> renderSrcPictureCache); 100 101 encodeBuffer.encodeCachedValue(GetULONG(buffer + 16, bigEndian), 32, 102 clientCache -> renderFormatCache); 103 104 encodeBuffer.encodeCachedValue(GetULONG(buffer + 20, bigEndian), 29, 105 clientCache -> renderGlyphSetCache); 106 107 encodeBuffer.encodeDiffCachedValue(GetUINT(buffer + 24, bigEndian), 108 clientCache -> renderLastX, 16, 109 clientCache -> renderXCache, 11); 110 111 encodeBuffer.encodeDiffCachedValue(GetUINT(buffer + 26, bigEndian), 112 clientCache -> renderLastY, 16, 113 clientCache -> renderYCache, 11); 114 115 // 116 // Try to save as many bits as possible by 117 // encoding the information about the first 118 // set of glyphs. 119 // 120 121 if (size >= MESSAGE_OFFSET) 122 { 123 unsigned int numGlyphs = *(buffer + 28); 124 125 encodeBuffer.encodeCachedValue(numGlyphs, 8, 126 clientCache -> renderNumGlyphsCache); 127 128 encodeBuffer.encodeCachedValue(GetUINT(buffer + 32, bigEndian), 16, 129 clientCache -> renderWidthCache, 11); 130 131 encodeBuffer.encodeCachedValue(GetUINT(buffer + 34, bigEndian), 16, 132 clientCache -> renderHeightCache, 11); 133 134 // 135 // Only manage the first set of glyphs, 136 // that is in most cases the only one. 137 // 138 139 switch (*(buffer + 1)) 140 { 141 case X_RenderCompositeGlyphs8: 142 { 143 if (numGlyphs & 0x03) 144 { 145 memset((unsigned char *) buffer + MESSAGE_OFFSET + numGlyphs, '\0', 146 RoundUp4(numGlyphs) - numGlyphs); 147 } 148 149 break; 150 } 151 case X_RenderCompositeGlyphs16: 152 { 153 if (numGlyphs & 0x01) 154 { 155 memset((unsigned char *) buffer + MESSAGE_OFFSET + (numGlyphs * 2), '\0', 156 RoundUp4(numGlyphs * 2) - numGlyphs * 2); 157 } 158 159 break; 160 } 161 } 162 163 #ifdef TEST 164 if (*(buffer + (size - 1)) != '\0') 165 { 166 *logofs << name() << ": WARNING! Final byte is non-zero with size " 167 << size << " and " << (unsigned int) *(buffer + 28) 168 << " glyphs.\n" << logofs_flush; 169 } 170 else 171 { 172 *logofs << name() << ": Final byte is zero with size " 173 << size << " and " << (unsigned int) *(buffer + 28) 174 << " glyphs.\n" << logofs_flush; 175 } 176 #endif 177 } 178 179 #ifdef TEST 180 *logofs << name() << ": Encoded message. Type is " 181 << (unsigned int) *(buffer + 1) << " size is " 182 << size << ".\n" << logofs_flush; 183 #endif 184 } 185 MESSAGE_END_ENCODE_MESSAGE 186 187 MESSAGE_BEGIN_DECODE_MESSAGE 188 { 189 ClientCache *clientCache = (ClientCache *) channelCache; 190 191 unsigned int value; 192 193 *(buffer + 1) = type; 194 195 decodeBuffer.decodeCachedValue(*(buffer + 4), 8, 196 clientCache -> renderOpCache); 197 198 decodeBuffer.decodeXidValue(value, 199 clientCache -> renderSrcPictureCache); 200 201 PutULONG(value, buffer + 8, bigEndian); 202 203 decodeBuffer.decodeXidValue(value, 204 clientCache -> renderSrcPictureCache); 205 206 PutULONG(value, buffer + 12, bigEndian); 207 208 decodeBuffer.decodeCachedValue(value, 32, 209 clientCache -> renderFormatCache); 210 211 PutULONG(value, buffer + 16, bigEndian); 212 213 decodeBuffer.decodeCachedValue(value, 29, 214 clientCache -> renderGlyphSetCache); 215 216 PutULONG(value, buffer + 20, bigEndian); 217 218 decodeBuffer.decodeDiffCachedValue(value, 219 clientCache -> renderLastX, 16, 220 clientCache -> renderXCache, 11); 221 222 PutUINT(clientCache -> renderLastX, buffer + 24, bigEndian); 223 224 decodeBuffer.decodeDiffCachedValue(value, 225 clientCache -> renderLastY, 16, 226 clientCache -> renderYCache, 11); 227 228 PutUINT(clientCache -> renderLastY, buffer + 26, bigEndian); 229 230 if (size >= MESSAGE_OFFSET) 231 { 232 decodeBuffer.decodeCachedValue(value, 8, 233 clientCache -> renderNumGlyphsCache); 234 235 *(buffer + 28) = value; 236 237 decodeBuffer.decodeCachedValue(value, 16, 238 clientCache -> renderWidthCache, 11); 239 240 PutUINT(value, buffer + 32, bigEndian); 241 242 decodeBuffer.decodeCachedValue(value, 16, 243 clientCache -> renderHeightCache, 11); 244 245 PutUINT(value, buffer + 34, bigEndian); 246 } 247 248 #ifdef TEST 249 *logofs << name() << ": Decoded message. Type is " 250 << (unsigned int) type << " size is " << size 251 << ".\n" << logofs_flush; 252 #endif 253 } 254 MESSAGE_END_DECODE_MESSAGE 255 256 MESSAGE_BEGIN_ENCODE_DATA 257 { 258 ClientCache *clientCache = (ClientCache *) channelCache; 259 260 unsigned int value; 261 262 switch (*(buffer + 1)) 263 { 264 case X_RenderCompositeGlyphs8: 265 { 266 clientCache -> renderTextCompressor.reset(); 267 268 const unsigned char *next = buffer + MESSAGE_OFFSET; 269 270 for (unsigned int i = MESSAGE_OFFSET; i < size; i++) 271 { 272 #ifdef DEBUG 273 *logofs << name() << ": Encoding char with i = " << i 274 << ".\n" << logofs_flush; 275 #endif 276 277 clientCache -> renderTextCompressor. 278 encodeChar(*next++, encodeBuffer); 279 } 280 281 break; 282 } 283 case X_RenderCompositeGlyphs16: 284 { 285 for (unsigned int i = MESSAGE_OFFSET; i < size; i += 2) 286 { 287 value = GetUINT(buffer + i, bigEndian); 288 289 #ifdef DEBUG 290 *logofs << name() << ": Encoding short with i = " << i 291 << ".\n" << logofs_flush; 292 #endif 293 294 encodeBuffer.encodeCachedValue(value, 16, 295 *clientCache -> renderCompositeGlyphsDataCache[clientCache -> 296 renderLastCompositeGlyphsData]); 297 298 clientCache -> renderLastCompositeGlyphsData = value % 16; 299 } 300 301 break; 302 } 303 default: 304 { 305 for (unsigned int i = MESSAGE_OFFSET; i < size; i += 4) 306 { 307 value = GetULONG(buffer + i, bigEndian); 308 309 #ifdef DEBUG 310 *logofs << name() << ": Encoding long with i = " << i 311 << ".\n" << logofs_flush; 312 #endif 313 314 encodeBuffer.encodeCachedValue(value, 32, 315 *clientCache -> renderCompositeGlyphsDataCache[clientCache -> 316 renderLastCompositeGlyphsData]); 317 318 clientCache -> renderLastCompositeGlyphsData = value % 16; 319 } 320 321 break; 322 } 323 } 324 325 #ifdef TEST 326 *logofs << name() << ": Encoded " << size - MESSAGE_OFFSET 327 << " bytes of data.\n" << logofs_flush; 328 #endif 329 } 330 MESSAGE_END_ENCODE_DATA 331 332 MESSAGE_BEGIN_DECODE_DATA 333 { 334 ClientCache *clientCache = (ClientCache *) channelCache; 335 336 unsigned int value; 337 338 switch (*(buffer + 1)) 339 { 340 case X_RenderCompositeGlyphs8: 341 { 342 clientCache -> renderTextCompressor.reset(); 343 344 unsigned char *next = buffer + MESSAGE_OFFSET; 345 346 for (unsigned int i = MESSAGE_OFFSET; i < size; i++) 347 { 348 #ifdef DEBUG 349 *logofs << name() << ": Decoding char with i = " << i 350 << ".\n" << logofs_flush; 351 #endif 352 353 *next++ = clientCache -> renderTextCompressor. 354 decodeChar(decodeBuffer); 355 } 356 357 break; 358 } 359 case X_RenderCompositeGlyphs16: 360 { 361 for (unsigned int i = MESSAGE_OFFSET; i < size; i += 2) 362 { 363 #ifdef DEBUG 364 *logofs << name() << ": Decoding short with i = " << i 365 << ".\n" << logofs_flush; 366 #endif 367 368 decodeBuffer.decodeCachedValue(value, 16, 369 *clientCache -> renderCompositeGlyphsDataCache[clientCache -> 370 renderLastCompositeGlyphsData]); 371 372 PutUINT(value, buffer + i, bigEndian); 373 374 clientCache -> renderLastCompositeGlyphsData = value % 16; 375 } 376 377 break; 378 } 379 default: 380 { 381 for (unsigned int i = MESSAGE_OFFSET; i < size; i += 4) 382 { 383 #ifdef DEBUG 384 *logofs << name() << ": Decoding long with i = " << i 385 << ".\n" << logofs_flush; 386 #endif 387 388 decodeBuffer.decodeCachedValue(value, 32, 389 *clientCache -> renderCompositeGlyphsDataCache[clientCache -> 390 renderLastCompositeGlyphsData]); 391 392 PutULONG(value, buffer + i, bigEndian); 393 394 clientCache -> renderLastCompositeGlyphsData = value % 16; 395 } 396 397 break; 398 } 399 } 400 401 #ifdef TEST 402 *logofs << name() << ": Decoded " << size - MESSAGE_OFFSET 403 << " bytes of data.\n" << logofs_flush; 404 #endif 405 } 406 MESSAGE_END_DECODE_DATA 407 408 MESSAGE_BEGIN_PARSE_IDENTITY 409 { 410 RenderExtensionMessage *renderExtension = (RenderExtensionMessage *) message; 411 412 renderExtension -> data.composite_glyphs_compat.type = *(buffer + 1); 413 renderExtension -> data.composite_glyphs_compat.op = *(buffer + 4); 414 415 renderExtension -> data.composite_glyphs_compat.src_id = GetULONG(buffer + 8, bigEndian); 416 renderExtension -> data.composite_glyphs_compat.dst_id = GetULONG(buffer + 12, bigEndian); 417 418 renderExtension -> data.composite_glyphs_compat.format = GetULONG(buffer + 16, bigEndian); 419 renderExtension -> data.composite_glyphs_compat.set_id = GetULONG(buffer + 20, bigEndian); 420 421 renderExtension -> data.composite_glyphs_compat.src_x = GetUINT(buffer + 24, bigEndian); 422 renderExtension -> data.composite_glyphs_compat.src_y = GetUINT(buffer + 26, bigEndian); 423 424 if (size >= MESSAGE_OFFSET) 425 { 426 renderExtension -> data.composite_glyphs_compat.num_elm = *(buffer + 28); 427 428 renderExtension -> data.composite_glyphs_compat.delta_x = GetUINT(buffer + 32, bigEndian); 429 renderExtension -> data.composite_glyphs_compat.delta_y = GetUINT(buffer + 34, bigEndian); 430 } 431 432 #ifdef TEST 433 *logofs << name() << ": Parsed identity. Type is " 434 << (unsigned int) renderExtension -> data.composite_glyphs_compat.type 435 << " size is " << renderExtension -> size_ << " identity size " 436 << renderExtension -> i_size_ << ".\n" 437 << logofs_flush; 438 #endif 439 } 440 MESSAGE_END_PARSE_IDENTITY 441 442 MESSAGE_BEGIN_UNPARSE_IDENTITY 443 { 444 RenderExtensionMessage *renderExtension = (RenderExtensionMessage *) message; 445 446 *(buffer + 1) = renderExtension -> data.composite_glyphs_compat.type; 447 *(buffer + 4) = renderExtension -> data.composite_glyphs_compat.op; 448 449 PutULONG(renderExtension -> data.composite_glyphs_compat.src_id, buffer + 8, bigEndian); 450 PutULONG(renderExtension -> data.composite_glyphs_compat.dst_id, buffer + 12, bigEndian); 451 452 PutULONG(renderExtension -> data.composite_glyphs_compat.format, buffer + 16, bigEndian); 453 PutULONG(renderExtension -> data.composite_glyphs_compat.set_id, buffer + 20, bigEndian); 454 455 PutUINT(renderExtension -> data.composite_glyphs_compat.src_x, buffer + 24, bigEndian); 456 PutUINT(renderExtension -> data.composite_glyphs_compat.src_y, buffer + 26, bigEndian); 457 458 if (size >= MESSAGE_OFFSET) 459 { 460 *(buffer + 28) = renderExtension -> data.composite_glyphs_compat.num_elm; 461 462 PutUINT(renderExtension -> data.composite_glyphs_compat.delta_x, buffer + 32, bigEndian); 463 PutUINT(renderExtension -> data.composite_glyphs_compat.delta_y, buffer + 34, bigEndian); 464 465 #ifdef DEBUG 466 *logofs << name() << ": Len is " << (unsigned int) *(buffer + 28) 467 << " delta X is " << GetUINT(buffer + 32, bigEndian) 468 << " delta Y is " << GetUINT(buffer + 34, bigEndian) 469 << ".\n" << logofs_flush; 470 471 *logofs << name() << ": Pad 1 is " << (unsigned int) *(buffer + 29) 472 << " pad 2 and 3 are " << GetUINT(buffer + 30, bigEndian) 473 << ".\n" << logofs_flush; 474 #endif 475 } 476 477 #ifdef TEST 478 *logofs << name() << ": Unparsed identity. Type is " 479 << (unsigned int) renderExtension -> data.composite_glyphs_compat.type 480 << " size is " << renderExtension -> size_ << " identity size " 481 << renderExtension -> i_size_ << ".\n" << ".\n" 482 << logofs_flush; 483 #endif 484 } 485 MESSAGE_END_UNPARSE_IDENTITY 486 487 MESSAGE_BEGIN_IDENTITY_CHECKSUM 488 { 489 // 490 // Include minor opcode, size and 491 // the composite operator in the 492 // identity. 493 // 494 495 md5_append(md5_state, buffer + 1, 4); 496 497 // 498 // Include the format and the source 499 // x and y fields. 500 // 501 502 md5_append(md5_state, buffer + 16, 4); 503 md5_append(md5_state, buffer + 24, 4); 504 505 // 506 // Include the number of glyphs. 507 // 508 509 if (size >= MESSAGE_OFFSET) 510 { 511 md5_append(md5_state, buffer + 28, 1); 512 } 513 } 514 MESSAGE_END_IDENTITY_CHECKSUM 515 516 MESSAGE_BEGIN_ENCODE_UPDATE 517 { 518 RenderExtensionMessage *renderExtension = (RenderExtensionMessage *) message; 519 RenderExtensionMessage *cachedRenderExtension = (RenderExtensionMessage *) cachedMessage; 520 521 ClientCache *clientCache = (ClientCache *) channelCache; 522 523 encodeBuffer.encodeXidValue(renderExtension -> data.composite_glyphs_compat.src_id, 524 clientCache -> renderSrcPictureCache); 525 526 cachedRenderExtension -> data.composite_glyphs_compat.src_id = 527 renderExtension -> data.composite_glyphs_compat.src_id; 528 529 encodeBuffer.encodeXidValue(renderExtension -> data.composite_glyphs_compat.dst_id, 530 clientCache -> renderSrcPictureCache); 531 532 cachedRenderExtension -> data.composite_glyphs_compat.dst_id = 533 renderExtension -> data.composite_glyphs_compat.dst_id; 534 535 encodeBuffer.encodeCachedValue(renderExtension -> data.composite_glyphs_compat.set_id, 29, 536 clientCache -> renderGlyphSetCache); 537 538 cachedRenderExtension -> data.composite_glyphs_compat.set_id = 539 renderExtension -> data.composite_glyphs_compat.set_id; 540 541 if (renderExtension -> size_ >= MESSAGE_OFFSET) 542 { 543 encodeBuffer.encodeCachedValue(renderExtension -> data.composite_glyphs_compat.delta_x, 16, 544 clientCache -> renderWidthCache, 11); 545 546 cachedRenderExtension -> data.composite_glyphs_compat.delta_x = 547 renderExtension -> data.composite_glyphs_compat.delta_x; 548 549 encodeBuffer.encodeCachedValue(renderExtension -> data.composite_glyphs_compat.delta_y, 16, 550 clientCache -> renderHeightCache, 11); 551 552 cachedRenderExtension -> data.composite_glyphs_compat.delta_y = 553 renderExtension -> data.composite_glyphs_compat.delta_y; 554 } 555 556 #ifdef TEST 557 *logofs << name() << ": Encoded update. Type is " 558 << (unsigned int) renderExtension -> data.composite_glyphs_compat.type 559 << " size is " << renderExtension -> size_ << ".\n" 560 << logofs_flush; 561 #endif 562 } 563 MESSAGE_END_ENCODE_UPDATE 564 565 MESSAGE_BEGIN_DECODE_UPDATE 566 { 567 RenderExtensionMessage *renderExtension = (RenderExtensionMessage *) message; 568 569 ClientCache *clientCache = (ClientCache *) channelCache; 570 571 decodeBuffer.decodeXidValue(renderExtension -> data.composite_glyphs_compat.src_id, 572 clientCache -> renderSrcPictureCache); 573 574 decodeBuffer.decodeXidValue(renderExtension -> data.composite_glyphs_compat.dst_id, 575 clientCache -> renderSrcPictureCache); 576 577 decodeBuffer.decodeCachedValue(renderExtension -> data.composite_glyphs_compat.set_id, 29, 578 clientCache -> renderGlyphSetCache); 579 580 if (renderExtension -> size_ >= MESSAGE_OFFSET) 581 { 582 unsigned int value; 583 584 decodeBuffer.decodeCachedValue(value, 16, 585 clientCache -> renderWidthCache, 11); 586 587 renderExtension -> data.composite_glyphs_compat.delta_x = value; 588 589 decodeBuffer.decodeCachedValue(value, 16, 590 clientCache -> renderHeightCache, 11); 591 592 renderExtension -> data.composite_glyphs_compat.delta_y = value; 593 } 594 595 #ifdef TEST 596 *logofs << name() << ": Decoded update. Type is " 597 << (unsigned int) renderExtension -> data.composite_glyphs_compat.type 598 << " size is " << renderExtension -> size_ << ".\n" 599 << logofs_flush; 600 #endif 601 } 602 MESSAGE_END_DECODE_UPDATE 603