diff options
Diffstat (limited to 'java/src/com/tigervnc/decoder/HextileDecoder.java')
-rw-r--r-- | java/src/com/tigervnc/decoder/HextileDecoder.java | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/java/src/com/tigervnc/decoder/HextileDecoder.java b/java/src/com/tigervnc/decoder/HextileDecoder.java new file mode 100644 index 00000000..da7e7781 --- /dev/null +++ b/java/src/com/tigervnc/decoder/HextileDecoder.java @@ -0,0 +1,228 @@ +package com.tightvnc.decoder; + +import com.tightvnc.decoder.common.Repaintable; +import com.tightvnc.vncviewer.RfbInputStream; +import java.awt.Color; +import java.awt.Graphics; +import java.io.IOException; + +// +// Class that used for decoding hextile encoded data. +// + +public class HextileDecoder extends RawDecoder { + + final static int EncodingHextile = 5; + + // Contstants used in the Hextile decoder + final static int + HextileRaw = 1, + HextileBackgroundSpecified = 2, + HextileForegroundSpecified = 4, + HextileAnySubrects = 8, + HextileSubrectsColoured = 16; + + public HextileDecoder(Graphics g, RfbInputStream is) { + super(g, is); + } + + public HextileDecoder(Graphics g, RfbInputStream is, int frameBufferW, + int frameBufferH) { + super(g, is, frameBufferW, frameBufferH); + } + + // + // Set private members methods + // + + public void setRepainableControl(Repaintable r) { + repainableControl = r; + } + + // + // Override handleRect method to decode Hextile encoded data insted of + // raw pixel data. + // + + public void handleRect(int x, int y, int w, int h) throws IOException, + Exception { + + // + // Write encoding ID to record output stream + // + + if (dos != null) { + dos.writeInt(HextileDecoder.EncodingHextile); + } + + hextile_bg = new Color(0); + hextile_fg = new Color(0); + + for (int ty = y; ty < y + h; ty += 16) { + int th = 16; + if (y + h - ty < 16) + th = y + h - ty; + + for (int tx = x; tx < x + w; tx += 16) { + int tw = 16; + if (x + w - tx < 16) + tw = x + w - tx; + + handleHextileSubrect(tx, ty, tw, th); + } + if (repainableControl != null) + repainableControl.scheduleRepaint(x, y, w, h); + } + if (repainableControl != null) + repainableControl.scheduleRepaint(x, y, w, h); + } + + // + // Handle one tile in the Hextile-encoded data. + // + + private void handleHextileSubrect(int tx, int ty, int tw, int th) + throws IOException, Exception { + + int subencoding = rfbis.readU8(); + + // + // Save decoded data to data output stream + // + + if (dos != null) { + dos.writeByte((byte)subencoding); + } + + // Is it a raw-encoded sub-rectangle? + if ((subencoding & HextileRaw) != 0) { + // + // Disable encoding id writting to record stream + // in super (RawDecoder) class, cause we write subencoding ID + // in this class (see code above). + // + + super.enableEncodingRecordWritting(false); + super.handleRect(tx, ty, tw, th); + super.handleUpdatedPixels(tx, ty, tw, th); + super.enableEncodingRecordWritting(true); + return; + } + + // Read and draw the background if specified. + byte[] cbuf = new byte[bytesPerPixel]; + if ((subencoding & HextileBackgroundSpecified) != 0) { + rfbis.readFully(cbuf); + if (bytesPerPixel == 1) { + hextile_bg = getColor256()[cbuf[0] & 0xFF]; + } else { + hextile_bg = new Color(cbuf[2] & 0xFF, cbuf[1] & 0xFF, cbuf[0] & 0xFF); + } + + // + // Save decoded data to data output stream + // + + if (dos != null) { + dos.write(cbuf); + } + } + graphics.setColor(hextile_bg); + graphics.fillRect(tx, ty, tw, th); + + // Read the foreground color if specified. + if ((subencoding & HextileForegroundSpecified) != 0) { + rfbis.readFully(cbuf); + if (bytesPerPixel == 1) { + hextile_fg = getColor256()[cbuf[0] & 0xFF]; + } else { + hextile_fg = new Color(cbuf[2] & 0xFF, cbuf[1] & 0xFF, cbuf[0] & 0xFF); + } + + // + // Save decoded data to data output stream + // + + if (dos != null) { + dos.write(cbuf); + } + } + + // Done with this tile if there is no sub-rectangles. + if ((subencoding & HextileAnySubrects) == 0) + return; + + int nSubrects = rfbis.readU8(); + int bufsize = nSubrects * 2; + if ((subencoding & HextileSubrectsColoured) != 0) { + bufsize += nSubrects * bytesPerPixel; + } + byte[] buf = new byte[bufsize]; + rfbis.readFully(buf); + + // + // Save decoded data to data output stream + // + + if (dos != null) { + dos.writeByte((byte)nSubrects); + dos.write(buf); + } + + int b1, b2, sx, sy, sw, sh; + int i = 0; + + if ((subencoding & HextileSubrectsColoured) == 0) { + + // Sub-rectangles are all of the same color. + graphics.setColor(hextile_fg); + for (int j = 0; j < nSubrects; j++) { + b1 = buf[i++] & 0xFF; + b2 = buf[i++] & 0xFF; + sx = tx + (b1 >> 4); + sy = ty + (b1 & 0xf); + sw = (b2 >> 4) + 1; + sh = (b2 & 0xf) + 1; + graphics.fillRect(sx, sy, sw, sh); + } + } else if (bytesPerPixel == 1) { + + // BGR233 (8-bit color) version for colored sub-rectangles. + for (int j = 0; j < nSubrects; j++) { + hextile_fg = getColor256()[buf[i++] & 0xFF]; + b1 = buf[i++] & 0xFF; + b2 = buf[i++] & 0xFF; + sx = tx + (b1 >> 4); + sy = ty + (b1 & 0xf); + sw = (b2 >> 4) + 1; + sh = (b2 & 0xf) + 1; + graphics.setColor(hextile_fg); + graphics.fillRect(sx, sy, sw, sh); + } + + } else { + + // Full-color (24-bit) version for colored sub-rectangles. + for (int j = 0; j < nSubrects; j++) { + hextile_fg = new Color(buf[i+2] & 0xFF, + buf[i+1] & 0xFF, + buf[i] & 0xFF); + i += 4; + b1 = buf[i++] & 0xFF; + b2 = buf[i++] & 0xFF; + sx = tx + (b1 >> 4); + sy = ty + (b1 & 0xf); + sw = (b2 >> 4) + 1; + sh = (b2 & 0xf) + 1; + graphics.setColor(hextile_fg); + graphics.fillRect(sx, sy, sw, sh); + } + + } + } + + // These colors should be kept between handleHextileSubrect() calls. + private Color hextile_bg, hextile_fg; + // Repaitable object + private Repaintable repainableControl = null; +} |