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