blob: 7052ff41e5ddfdd6337ede2004679e5a61ecddf3 [file] [log] [blame]
Adam Tkacf53e62a2009-03-13 13:20:26 +00001package com.tigervnc.decoder;
enikey1b758b72008-12-19 06:24:06 +00002
Adam Tkacf53e62a2009-03-13 13:20:26 +00003import com.tigervnc.decoder.common.Repaintable;
4import com.tigervnc.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 {
enikey2f0294e2008-12-24 08:18:54 +000049
50 //
51 // Write encoding ID to record output stream
52 //
53
54 if (dos != null) {
55 dos.writeInt(HextileDecoder.EncodingHextile);
56 }
57
enikey018dd5d2008-12-19 07:27:01 +000058 hextile_bg = new Color(0);
59 hextile_fg = new Color(0);
60
61 for (int ty = y; ty < y + h; ty += 16) {
62 int th = 16;
63 if (y + h - ty < 16)
64 th = y + h - ty;
65
66 for (int tx = x; tx < x + w; tx += 16) {
67 int tw = 16;
68 if (x + w - tx < 16)
69 tw = x + w - tx;
70
71 handleHextileSubrect(tx, ty, tw, th);
72 }
73 if (repainableControl != null)
74 repainableControl.scheduleRepaint(x, y, w, h);
75 }
76 if (repainableControl != null)
77 repainableControl.scheduleRepaint(x, y, w, h);
78 }
79
80 //
81 // Handle one tile in the Hextile-encoded data.
82 //
83
84 private void handleHextileSubrect(int tx, int ty, int tw, int th)
85 throws IOException, Exception {
86
87 int subencoding = rfbis.readU8();
88
89 //
enikey8beb7782008-12-24 04:37:56 +000090 // Save decoded data to data output stream
enikey018dd5d2008-12-19 07:27:01 +000091 //
92
enikey8beb7782008-12-24 04:37:56 +000093 if (dos != null) {
94 dos.writeByte((byte)subencoding);
enikey018dd5d2008-12-19 07:27:01 +000095 }
96
97 // Is it a raw-encoded sub-rectangle?
98 if ((subencoding & HextileRaw) != 0) {
enikey2f0294e2008-12-24 08:18:54 +000099 //
100 // Disable encoding id writting to record stream
101 // in super (RawDecoder) class, cause we write subencoding ID
102 // in this class (see code above).
103 //
104
105 super.enableEncodingRecordWritting(false);
enikey018dd5d2008-12-19 07:27:01 +0000106 super.handleRect(tx, ty, tw, th);
107 super.handleUpdatedPixels(tx, ty, tw, th);
enikey2f0294e2008-12-24 08:18:54 +0000108 super.enableEncodingRecordWritting(true);
enikey018dd5d2008-12-19 07:27:01 +0000109 return;
110 }
111
112 // Read and draw the background if specified.
113 byte[] cbuf = new byte[bytesPerPixel];
114 if ((subencoding & HextileBackgroundSpecified) != 0) {
115 rfbis.readFully(cbuf);
116 if (bytesPerPixel == 1) {
117 hextile_bg = getColor256()[cbuf[0] & 0xFF];
118 } else {
119 hextile_bg = new Color(cbuf[2] & 0xFF, cbuf[1] & 0xFF, cbuf[0] & 0xFF);
120 }
121
122 //
enikey8beb7782008-12-24 04:37:56 +0000123 // Save decoded data to data output stream
enikey018dd5d2008-12-19 07:27:01 +0000124 //
125
enikey8beb7782008-12-24 04:37:56 +0000126 if (dos != null) {
127 dos.write(cbuf);
enikey018dd5d2008-12-19 07:27:01 +0000128 }
129 }
130 graphics.setColor(hextile_bg);
131 graphics.fillRect(tx, ty, tw, th);
132
133 // Read the foreground color if specified.
134 if ((subencoding & HextileForegroundSpecified) != 0) {
135 rfbis.readFully(cbuf);
136 if (bytesPerPixel == 1) {
137 hextile_fg = getColor256()[cbuf[0] & 0xFF];
138 } else {
139 hextile_fg = new Color(cbuf[2] & 0xFF, cbuf[1] & 0xFF, cbuf[0] & 0xFF);
140 }
141
142 //
enikey8beb7782008-12-24 04:37:56 +0000143 // Save decoded data to data output stream
enikey018dd5d2008-12-19 07:27:01 +0000144 //
145
enikey8beb7782008-12-24 04:37:56 +0000146 if (dos != null) {
147 dos.write(cbuf);
enikey018dd5d2008-12-19 07:27:01 +0000148 }
149 }
150
151 // Done with this tile if there is no sub-rectangles.
152 if ((subencoding & HextileAnySubrects) == 0)
153 return;
154
155 int nSubrects = rfbis.readU8();
156 int bufsize = nSubrects * 2;
157 if ((subencoding & HextileSubrectsColoured) != 0) {
158 bufsize += nSubrects * bytesPerPixel;
159 }
160 byte[] buf = new byte[bufsize];
161 rfbis.readFully(buf);
162
163 //
enikey8beb7782008-12-24 04:37:56 +0000164 // Save decoded data to data output stream
enikey018dd5d2008-12-19 07:27:01 +0000165 //
166
enikey8beb7782008-12-24 04:37:56 +0000167 if (dos != null) {
168 dos.writeByte((byte)nSubrects);
169 dos.write(buf);
enikey018dd5d2008-12-19 07:27:01 +0000170 }
171
172 int b1, b2, sx, sy, sw, sh;
173 int i = 0;
174
175 if ((subencoding & HextileSubrectsColoured) == 0) {
176
177 // Sub-rectangles are all of the same color.
178 graphics.setColor(hextile_fg);
179 for (int j = 0; j < nSubrects; j++) {
180 b1 = buf[i++] & 0xFF;
181 b2 = buf[i++] & 0xFF;
182 sx = tx + (b1 >> 4);
183 sy = ty + (b1 & 0xf);
184 sw = (b2 >> 4) + 1;
185 sh = (b2 & 0xf) + 1;
186 graphics.fillRect(sx, sy, sw, sh);
187 }
188 } else if (bytesPerPixel == 1) {
189
190 // BGR233 (8-bit color) version for colored sub-rectangles.
191 for (int j = 0; j < nSubrects; j++) {
192 hextile_fg = getColor256()[buf[i++] & 0xFF];
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 } else {
204
205 // Full-color (24-bit) version for colored sub-rectangles.
206 for (int j = 0; j < nSubrects; j++) {
207 hextile_fg = new Color(buf[i+2] & 0xFF,
208 buf[i+1] & 0xFF,
209 buf[i] & 0xFF);
210 i += 4;
211 b1 = buf[i++] & 0xFF;
212 b2 = buf[i++] & 0xFF;
213 sx = tx + (b1 >> 4);
214 sy = ty + (b1 & 0xf);
215 sw = (b2 >> 4) + 1;
216 sh = (b2 & 0xf) + 1;
217 graphics.setColor(hextile_fg);
218 graphics.fillRect(sx, sy, sw, sh);
219 }
220
221 }
222 }
223
enikeyeb246ca2008-12-19 06:43:25 +0000224 // These colors should be kept between handleHextileSubrect() calls.
225 private Color hextile_bg, hextile_fg;
226 // Repaitable object
227 private Repaintable repainableControl = null;
enikey1b758b72008-12-19 06:24:06 +0000228}