You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

HextileDecoder.java 5.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
  2. * Copyright (C) 2019 Brian P. Hinz
  3. *
  4. * This is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This software is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this software; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
  17. * USA.
  18. */
  19. package com.tigervnc.rfb;
  20. import java.awt.image.*;
  21. import java.nio.*;
  22. import java.util.Arrays;
  23. import com.tigervnc.rdr.*;
  24. public class HextileDecoder extends Decoder {
  25. public static final int hextileRaw = (1 << 0);
  26. public static final int hextileBgSpecified = (1 << 1);
  27. public static final int hextileFgSpecified = (1 << 2);
  28. public static final int hextileAnySubrects = (1 << 3);
  29. public static final int hextileSubrectsColoured = (1 << 4);
  30. public HextileDecoder() { super(DecoderFlags.DecoderPlain); }
  31. public void readRect(Rect r, InStream is,
  32. ServerParams server, OutStream os)
  33. {
  34. Rect t = new Rect();
  35. int bytesPerPixel;
  36. bytesPerPixel = server.pf().bpp/8;
  37. for (t.tl.y = r.tl.y; t.tl.y < r.br.y; t.tl.y += 16) {
  38. t.br.y = Math.min(r.br.y, t.tl.y + 16);
  39. for (t.tl.x = r.tl.x; t.tl.x < r.br.x; t.tl.x += 16) {
  40. int tileType;
  41. t.br.x = Math.min(r.br.x, t.tl.x + 16);
  42. tileType = is.readU8();
  43. os.writeU8(tileType);
  44. if ((tileType & hextileRaw) != 0) {
  45. os.copyBytes(is, t.area() * bytesPerPixel);
  46. continue;
  47. }
  48. if ((tileType & hextileBgSpecified) != 0)
  49. os.copyBytes(is, bytesPerPixel);
  50. if ((tileType & hextileFgSpecified) != 0)
  51. os.copyBytes(is, bytesPerPixel);
  52. if ((tileType & hextileAnySubrects) != 0) {
  53. int nSubrects;
  54. nSubrects = is.readU8();
  55. os.writeU8(nSubrects);
  56. if ((tileType & hextileSubrectsColoured) != 0)
  57. os.copyBytes(is, nSubrects * (bytesPerPixel + 2));
  58. else
  59. os.copyBytes(is, nSubrects * 2);
  60. }
  61. }
  62. }
  63. }
  64. public void decodeRect(Rect r, Object buffer,
  65. int buflen, ServerParams server,
  66. ModifiablePixelBuffer pb)
  67. {
  68. MemInStream is = new MemInStream((byte[])buffer, 0, buflen);
  69. PixelFormat pf = server.pf();
  70. switch (pf.bpp) {
  71. case 8: hextileDecode8(r, is, pf, pb); break;
  72. case 16: hextileDecode16(r, is, pf, pb); break;
  73. case 32: hextileDecode32(r, is, pf, pb); break;
  74. }
  75. }
  76. private void hextileDecode8(Rect r, InStream is,
  77. PixelFormat pf,
  78. ModifiablePixelBuffer pb)
  79. {
  80. HEXTILE_DECODE(r, is, pf, pb);
  81. }
  82. private void hextileDecode16(Rect r, InStream is,
  83. PixelFormat pf,
  84. ModifiablePixelBuffer pb)
  85. {
  86. HEXTILE_DECODE(r, is, pf, pb);
  87. }
  88. private void hextileDecode32(Rect r, InStream is,
  89. PixelFormat pf,
  90. ModifiablePixelBuffer pb)
  91. {
  92. HEXTILE_DECODE(r, is, pf, pb);
  93. }
  94. private static ByteBuffer READ_PIXEL(InStream is, PixelFormat pf) {
  95. switch (pf.bpp) {
  96. case 8:
  97. return ByteBuffer.allocate(1).put(0, (byte)is.readOpaque8());
  98. case 16:
  99. return ByteBuffer.allocate(2).putShort(0, (short)is.readOpaque16());
  100. default:
  101. return ByteBuffer.allocate(4).putInt(0, is.readOpaque32());
  102. }
  103. }
  104. private void HEXTILE_DECODE(Rect r, InStream is,
  105. PixelFormat pf,
  106. ModifiablePixelBuffer pb)
  107. {
  108. Rect t = new Rect();
  109. ByteBuffer bg = ByteBuffer.allocate(pf.bpp/8);
  110. ByteBuffer fg = ByteBuffer.allocate(pf.bpp/8);
  111. ByteBuffer buf = ByteBuffer.allocate(16 * 16 * pf.bpp/8);
  112. for (t.tl.y = r.tl.y; t.tl.y < r.br.y; t.tl.y += 16) {
  113. t.br.y = Math.min(r.br.y, t.tl.y + 16);
  114. for (t.tl.x = r.tl.x; t.tl.x < r.br.x; t.tl.x += 16) {
  115. t.br.x = Math.min(r.br.x, t.tl.x + 16);
  116. int tileType = is.readU8();
  117. if ((tileType & hextileRaw) != 0) {
  118. is.readBytes(buf.duplicate(), t.area() * (pf.bpp/8));
  119. pb.imageRect(pf, t, buf.array());
  120. continue;
  121. }
  122. if ((tileType & hextileBgSpecified) != 0)
  123. bg = READ_PIXEL(is, pf);
  124. int len = t.area();
  125. ByteBuffer ptr = buf.duplicate();
  126. while (len-- > 0) ptr.put(bg.array());
  127. if ((tileType & hextileFgSpecified) != 0)
  128. fg = READ_PIXEL(is, pf);
  129. if ((tileType & hextileAnySubrects) != 0) {
  130. int nSubrects = is.readU8();
  131. for (int i = 0; i < nSubrects; i++) {
  132. if ((tileType & hextileSubrectsColoured) != 0)
  133. fg = READ_PIXEL(is, pf);
  134. int xy = is.readU8();
  135. int wh = is.readU8();
  136. int x = ((xy >> 4) & 15);
  137. int y = (xy & 15);
  138. int w = ((wh >> 4) & 15) + 1;
  139. int h = (wh & 15) + 1;
  140. if (x + w > 16 || y + h > 16) {
  141. throw new Exception("HEXTILE_DECODE: Hextile out of bounds");
  142. }
  143. ptr = buf.duplicate();
  144. ptr.position((y * t.width() + x)*pf.bpp/8);
  145. int rowAdd = (t.width() - w)*pf.bpp/8;
  146. while (h-- > 0) {
  147. len = w;
  148. while (len-- > 0) ptr.put(fg.array());
  149. if (h > 0) ptr.position(ptr.position()+rowAdd);
  150. }
  151. }
  152. }
  153. pb.imageRect(pf, t, buf.array());
  154. }
  155. }
  156. }
  157. }