blob: 1e4ef0933f1daed5d64d7245e4103679c8f050a8 [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
15 // Contstants used in the Hextile decoder
16 final static int
17 HextileRaw = 1,
18 HextileBackgroundSpecified = 2,
19 HextileForegroundSpecified = 4,
20 HextileAnySubrects = 8,
21 HextileSubrectsColoured = 16;
22
23 public HextileDecoder(Graphics g, RfbInputStream is) {
24 super(g, is);
25 }
26
27 public HextileDecoder(Graphics g, RfbInputStream is, int frameBufferW,
28 int frameBufferH) {
29 super(g, is, frameBufferW, frameBufferH);
30 }
enikey1b758b72008-12-19 06:24:06 +000031
enikeyeb246ca2008-12-19 06:43:25 +000032 //
33 // Set private members methods
34 //
35
36 public void setRepainableControl(Repaintable r) {
37 repainableControl = r;
38 }
39
enikey018dd5d2008-12-19 07:27:01 +000040 //
41 // Override handleRect method to decode Hextile encoded data insted of
42 // raw pixel data.
43 //
44
45 public void handleRect(int x, int y, int w, int h) throws IOException,
46 Exception {
47 hextile_bg = new Color(0);
48 hextile_fg = new Color(0);
49
50 for (int ty = y; ty < y + h; ty += 16) {
51 int th = 16;
52 if (y + h - ty < 16)
53 th = y + h - ty;
54
55 for (int tx = x; tx < x + w; tx += 16) {
56 int tw = 16;
57 if (x + w - tx < 16)
58 tw = x + w - tx;
59
60 handleHextileSubrect(tx, ty, tw, th);
61 }
62 if (repainableControl != null)
63 repainableControl.scheduleRepaint(x, y, w, h);
64 }
65 if (repainableControl != null)
66 repainableControl.scheduleRepaint(x, y, w, h);
67 }
68
69 //
70 // Handle one tile in the Hextile-encoded data.
71 //
72
73 private void handleHextileSubrect(int tx, int ty, int tw, int th)
74 throws IOException, Exception {
75
76 int subencoding = rfbis.readU8();
77
78 //
enikey8beb7782008-12-24 04:37:56 +000079 // Save decoded data to data output stream
enikey018dd5d2008-12-19 07:27:01 +000080 //
81
enikey8beb7782008-12-24 04:37:56 +000082 if (dos != null) {
83 dos.writeByte((byte)subencoding);
enikey018dd5d2008-12-19 07:27:01 +000084 }
85
86 // Is it a raw-encoded sub-rectangle?
87 if ((subencoding & HextileRaw) != 0) {
88 //handleRawRect(tx, ty, tw, th, false);
89 super.handleRect(tx, ty, tw, th);
90 super.handleUpdatedPixels(tx, ty, tw, th);
91 return;
92 }
93
94 // Read and draw the background if specified.
95 byte[] cbuf = new byte[bytesPerPixel];
96 if ((subencoding & HextileBackgroundSpecified) != 0) {
97 rfbis.readFully(cbuf);
98 if (bytesPerPixel == 1) {
99 hextile_bg = getColor256()[cbuf[0] & 0xFF];
100 } else {
101 hextile_bg = new Color(cbuf[2] & 0xFF, cbuf[1] & 0xFF, cbuf[0] & 0xFF);
102 }
103
104 //
enikey8beb7782008-12-24 04:37:56 +0000105 // Save decoded data to data output stream
enikey018dd5d2008-12-19 07:27:01 +0000106 //
107
enikey8beb7782008-12-24 04:37:56 +0000108 if (dos != null) {
109 dos.write(cbuf);
enikey018dd5d2008-12-19 07:27:01 +0000110 }
111 }
112 graphics.setColor(hextile_bg);
113 graphics.fillRect(tx, ty, tw, th);
114
115 // Read the foreground color if specified.
116 if ((subencoding & HextileForegroundSpecified) != 0) {
117 rfbis.readFully(cbuf);
118 if (bytesPerPixel == 1) {
119 hextile_fg = getColor256()[cbuf[0] & 0xFF];
120 } else {
121 hextile_fg = new Color(cbuf[2] & 0xFF, cbuf[1] & 0xFF, cbuf[0] & 0xFF);
122 }
123
124 //
enikey8beb7782008-12-24 04:37:56 +0000125 // Save decoded data to data output stream
enikey018dd5d2008-12-19 07:27:01 +0000126 //
127
enikey8beb7782008-12-24 04:37:56 +0000128 if (dos != null) {
129 dos.write(cbuf);
enikey018dd5d2008-12-19 07:27:01 +0000130 }
131 }
132
133 // Done with this tile if there is no sub-rectangles.
134 if ((subencoding & HextileAnySubrects) == 0)
135 return;
136
137 int nSubrects = rfbis.readU8();
138 int bufsize = nSubrects * 2;
139 if ((subencoding & HextileSubrectsColoured) != 0) {
140 bufsize += nSubrects * bytesPerPixel;
141 }
142 byte[] buf = new byte[bufsize];
143 rfbis.readFully(buf);
144
145 //
enikey8beb7782008-12-24 04:37:56 +0000146 // Save decoded data to data output stream
enikey018dd5d2008-12-19 07:27:01 +0000147 //
148
enikey8beb7782008-12-24 04:37:56 +0000149 if (dos != null) {
150 dos.writeByte((byte)nSubrects);
151 dos.write(buf);
enikey018dd5d2008-12-19 07:27:01 +0000152 }
153
154 int b1, b2, sx, sy, sw, sh;
155 int i = 0;
156
157 if ((subencoding & HextileSubrectsColoured) == 0) {
158
159 // Sub-rectangles are all of the same color.
160 graphics.setColor(hextile_fg);
161 for (int j = 0; j < nSubrects; j++) {
162 b1 = buf[i++] & 0xFF;
163 b2 = buf[i++] & 0xFF;
164 sx = tx + (b1 >> 4);
165 sy = ty + (b1 & 0xf);
166 sw = (b2 >> 4) + 1;
167 sh = (b2 & 0xf) + 1;
168 graphics.fillRect(sx, sy, sw, sh);
169 }
170 } else if (bytesPerPixel == 1) {
171
172 // BGR233 (8-bit color) version for colored sub-rectangles.
173 for (int j = 0; j < nSubrects; j++) {
174 hextile_fg = getColor256()[buf[i++] & 0xFF];
175 b1 = buf[i++] & 0xFF;
176 b2 = buf[i++] & 0xFF;
177 sx = tx + (b1 >> 4);
178 sy = ty + (b1 & 0xf);
179 sw = (b2 >> 4) + 1;
180 sh = (b2 & 0xf) + 1;
181 graphics.setColor(hextile_fg);
182 graphics.fillRect(sx, sy, sw, sh);
183 }
184
185 } else {
186
187 // Full-color (24-bit) version for colored sub-rectangles.
188 for (int j = 0; j < nSubrects; j++) {
189 hextile_fg = new Color(buf[i+2] & 0xFF,
190 buf[i+1] & 0xFF,
191 buf[i] & 0xFF);
192 i += 4;
193 b1 = buf[i++] & 0xFF;
194 b2 = buf[i++] & 0xFF;
195 sx = tx + (b1 >> 4);
196 sy = ty + (b1 & 0xf);
197 sw = (b2 >> 4) + 1;
198 sh = (b2 & 0xf) + 1;
199 graphics.setColor(hextile_fg);
200 graphics.fillRect(sx, sy, sw, sh);
201 }
202
203 }
204 }
205
enikeyeb246ca2008-12-19 06:43:25 +0000206 // These colors should be kept between handleHextileSubrect() calls.
207 private Color hextile_bg, hextile_fg;
208 // Repaitable object
209 private Repaintable repainableControl = null;
enikey1b758b72008-12-19 06:24:06 +0000210}