blob: 9c053095f161bbd79baade3cb9923121a327a05f [file] [log] [blame]
enikey1b758b72008-12-19 06:24:06 +00001package com.tightvnc.decoder;
2
enikeyeb246ca2008-12-19 06:43:25 +00003import com.tightvnc.decoder.common.Repaintable;
enikeyd734f102008-12-19 06:28:08 +00004import com.tightvnc.vncviewer.RfbInputStream;
enikeyeb246ca2008-12-19 06:43:25 +00005import java.awt.Color;
enikeyd734f102008-12-19 06:28:08 +00006import java.awt.Graphics;
enikey018dd5d2008-12-19 07:27:01 +00007import java.io.IOException;
enikeyd734f102008-12-19 06:28:08 +00008
enikeyeb246ca2008-12-19 06:43:25 +00009//
10// Class that used for decoding hextile encoded data.
11//
12
enikeyd734f102008-12-19 06:28:08 +000013public class HextileDecoder extends RawDecoder {
14
enikey6558a302008-12-24 05:14:30 +000015 final static int EncodingHextile = 5;
16
enikeyd734f102008-12-19 06:28:08 +000017 // Contstants used in the Hextile decoder
18 final static int
19 HextileRaw = 1,
20 HextileBackgroundSpecified = 2,
21 HextileForegroundSpecified = 4,
22 HextileAnySubrects = 8,
23 HextileSubrectsColoured = 16;
24
25 public HextileDecoder(Graphics g, RfbInputStream is) {
26 super(g, is);
27 }
28
29 public HextileDecoder(Graphics g, RfbInputStream is, int frameBufferW,
30 int frameBufferH) {
31 super(g, is, frameBufferW, frameBufferH);
32 }
enikey1b758b72008-12-19 06:24:06 +000033
enikeyeb246ca2008-12-19 06:43:25 +000034 //
35 // Set private members methods
36 //
37
38 public void setRepainableControl(Repaintable r) {
39 repainableControl = r;
40 }
41
enikey018dd5d2008-12-19 07:27:01 +000042 //
43 // Override handleRect method to decode Hextile encoded data insted of
44 // raw pixel data.
45 //
46
47 public void handleRect(int x, int y, int w, int h) throws IOException,
48 Exception {
49 hextile_bg = new Color(0);
50 hextile_fg = new Color(0);
51
52 for (int ty = y; ty < y + h; ty += 16) {
53 int th = 16;
54 if (y + h - ty < 16)
55 th = y + h - ty;
56
57 for (int tx = x; tx < x + w; tx += 16) {
58 int tw = 16;
59 if (x + w - tx < 16)
60 tw = x + w - tx;
61
62 handleHextileSubrect(tx, ty, tw, th);
63 }
64 if (repainableControl != null)
65 repainableControl.scheduleRepaint(x, y, w, h);
66 }
67 if (repainableControl != null)
68 repainableControl.scheduleRepaint(x, y, w, h);
69 }
70
71 //
72 // Handle one tile in the Hextile-encoded data.
73 //
74
75 private void handleHextileSubrect(int tx, int ty, int tw, int th)
76 throws IOException, Exception {
77
78 int subencoding = rfbis.readU8();
79
80 //
enikey8beb7782008-12-24 04:37:56 +000081 // Save decoded data to data output stream
enikey018dd5d2008-12-19 07:27:01 +000082 //
83
enikey8beb7782008-12-24 04:37:56 +000084 if (dos != null) {
85 dos.writeByte((byte)subencoding);
enikey018dd5d2008-12-19 07:27:01 +000086 }
87
88 // Is it a raw-encoded sub-rectangle?
89 if ((subencoding & HextileRaw) != 0) {
90 //handleRawRect(tx, ty, tw, th, false);
91 super.handleRect(tx, ty, tw, th);
92 super.handleUpdatedPixels(tx, ty, tw, th);
93 return;
94 }
95
96 // Read and draw the background if specified.
97 byte[] cbuf = new byte[bytesPerPixel];
98 if ((subencoding & HextileBackgroundSpecified) != 0) {
99 rfbis.readFully(cbuf);
100 if (bytesPerPixel == 1) {
101 hextile_bg = getColor256()[cbuf[0] & 0xFF];
102 } else {
103 hextile_bg = new Color(cbuf[2] & 0xFF, cbuf[1] & 0xFF, cbuf[0] & 0xFF);
104 }
105
106 //
enikey8beb7782008-12-24 04:37:56 +0000107 // Save decoded data to data output stream
enikey018dd5d2008-12-19 07:27:01 +0000108 //
109
enikey8beb7782008-12-24 04:37:56 +0000110 if (dos != null) {
111 dos.write(cbuf);
enikey018dd5d2008-12-19 07:27:01 +0000112 }
113 }
114 graphics.setColor(hextile_bg);
115 graphics.fillRect(tx, ty, tw, th);
116
117 // Read the foreground color if specified.
118 if ((subencoding & HextileForegroundSpecified) != 0) {
119 rfbis.readFully(cbuf);
120 if (bytesPerPixel == 1) {
121 hextile_fg = getColor256()[cbuf[0] & 0xFF];
122 } else {
123 hextile_fg = new Color(cbuf[2] & 0xFF, cbuf[1] & 0xFF, cbuf[0] & 0xFF);
124 }
125
126 //
enikey8beb7782008-12-24 04:37:56 +0000127 // Save decoded data to data output stream
enikey018dd5d2008-12-19 07:27:01 +0000128 //
129
enikey8beb7782008-12-24 04:37:56 +0000130 if (dos != null) {
131 dos.write(cbuf);
enikey018dd5d2008-12-19 07:27:01 +0000132 }
133 }
134
135 // Done with this tile if there is no sub-rectangles.
136 if ((subencoding & HextileAnySubrects) == 0)
137 return;
138
139 int nSubrects = rfbis.readU8();
140 int bufsize = nSubrects * 2;
141 if ((subencoding & HextileSubrectsColoured) != 0) {
142 bufsize += nSubrects * bytesPerPixel;
143 }
144 byte[] buf = new byte[bufsize];
145 rfbis.readFully(buf);
146
147 //
enikey8beb7782008-12-24 04:37:56 +0000148 // Save decoded data to data output stream
enikey018dd5d2008-12-19 07:27:01 +0000149 //
150
enikey8beb7782008-12-24 04:37:56 +0000151 if (dos != null) {
152 dos.writeByte((byte)nSubrects);
153 dos.write(buf);
enikey018dd5d2008-12-19 07:27:01 +0000154 }
155
156 int b1, b2, sx, sy, sw, sh;
157 int i = 0;
158
159 if ((subencoding & HextileSubrectsColoured) == 0) {
160
161 // Sub-rectangles are all of the same color.
162 graphics.setColor(hextile_fg);
163 for (int j = 0; j < nSubrects; j++) {
164 b1 = buf[i++] & 0xFF;
165 b2 = buf[i++] & 0xFF;
166 sx = tx + (b1 >> 4);
167 sy = ty + (b1 & 0xf);
168 sw = (b2 >> 4) + 1;
169 sh = (b2 & 0xf) + 1;
170 graphics.fillRect(sx, sy, sw, sh);
171 }
172 } else if (bytesPerPixel == 1) {
173
174 // BGR233 (8-bit color) version for colored sub-rectangles.
175 for (int j = 0; j < nSubrects; j++) {
176 hextile_fg = getColor256()[buf[i++] & 0xFF];
177 b1 = buf[i++] & 0xFF;
178 b2 = buf[i++] & 0xFF;
179 sx = tx + (b1 >> 4);
180 sy = ty + (b1 & 0xf);
181 sw = (b2 >> 4) + 1;
182 sh = (b2 & 0xf) + 1;
183 graphics.setColor(hextile_fg);
184 graphics.fillRect(sx, sy, sw, sh);
185 }
186
187 } else {
188
189 // Full-color (24-bit) version for colored sub-rectangles.
190 for (int j = 0; j < nSubrects; j++) {
191 hextile_fg = new Color(buf[i+2] & 0xFF,
192 buf[i+1] & 0xFF,
193 buf[i] & 0xFF);
194 i += 4;
195 b1 = buf[i++] & 0xFF;
196 b2 = buf[i++] & 0xFF;
197 sx = tx + (b1 >> 4);
198 sy = ty + (b1 & 0xf);
199 sw = (b2 >> 4) + 1;
200 sh = (b2 & 0xf) + 1;
201 graphics.setColor(hextile_fg);
202 graphics.fillRect(sx, sy, sw, sh);
203 }
204
205 }
206 }
207
enikeyeb246ca2008-12-19 06:43:25 +0000208 // These colors should be kept between handleHextileSubrect() calls.
209 private Color hextile_bg, hextile_fg;
210 // Repaitable object
211 private Repaintable repainableControl = null;
enikey1b758b72008-12-19 06:24:06 +0000212}