📄 vnccanvas.java
字号:
} } } // Before requesting framebuffer update, check if the pixel // format should be changed. If it should, request full update // instead of an incremental one. if (viewer.options.eightBitColors != (bytesPixel == 1)) { setPixelFormat(); fullUpdateNeeded = true; } viewer.autoSelectEncodings(); rfb.writeFramebufferUpdateRequest(0, 0, rfb.framebufferWidth, rfb.framebufferHeight, !fullUpdateNeeded); break; case RfbProto.SetColourMapEntries: throw new Exception("Can't handle SetColourMapEntries message"); case RfbProto.Bell: Toolkit.getDefaultToolkit().beep(); break; case RfbProto.ServerCutText: String s = rfb.readServerCutText(); viewer.clipboard.setCutText(s); break; default: throw new Exception("Unknown RFB message type " + msgType); } } } // // Handle a raw rectangle. The second form with paint==false is used // by the Hextile decoder for raw-encoded tiles. // void handleRawRect(int x, int y, int w, int h) throws IOException { handleRawRect(x, y, w, h, true); } void handleRawRect(int x, int y, int w, int h, boolean paint) throws IOException { if (bytesPixel == 1) { for (int dy = y; dy < y + h; dy++) { rfb.readFully(pixels8, dy * rfb.framebufferWidth + x, w); if (rfb.rec != null) { rfb.rec.write(pixels8, dy * rfb.framebufferWidth + x, w); } } } else { byte[] buf = new byte[w * 4]; int i, offset; for (int dy = y; dy < y + h; dy++) { rfb.readFully(buf); if (rfb.rec != null) { rfb.rec.write(buf); } offset = dy * rfb.framebufferWidth + x; for (i = 0; i < w; i++) { pixels24[offset + i] = (buf[i * 4 + 2] & 0xFF) << 16 | (buf[i * 4 + 1] & 0xFF) << 8 | (buf[i * 4] & 0xFF); } } } handleUpdatedPixels(x, y, w, h); if (paint) scheduleRepaint(x, y, w, h); } // // Handle a CopyRect rectangle. // void handleCopyRect(int x, int y, int w, int h) throws IOException { rfb.readCopyRect(); memGraphics.copyArea(rfb.copyRectSrcX, rfb.copyRectSrcY, w, h, x - rfb.copyRectSrcX, y - rfb.copyRectSrcY); scheduleRepaint(x, y, w, h); } // // Handle an RRE-encoded rectangle. // void handleRRERect(int x, int y, int w, int h) throws IOException { int nSubrects = rfb.is.readInt(); byte[] bg_buf = new byte[bytesPixel]; rfb.readFully(bg_buf); Color pixel; if (bytesPixel == 1) { pixel = colors[bg_buf[0] & 0xFF]; } else { pixel = new Color(bg_buf[2] & 0xFF, bg_buf[1] & 0xFF, bg_buf[0] & 0xFF); } memGraphics.setColor(pixel); memGraphics.fillRect(x, y, w, h); byte[] buf = new byte[nSubrects * (bytesPixel + 8)]; rfb.readFully(buf); DataInputStream ds = new DataInputStream(new ByteArrayInputStream(buf)); if (rfb.rec != null) { rfb.rec.writeIntBE(nSubrects); rfb.rec.write(bg_buf); rfb.rec.write(buf); } int sx, sy, sw, sh; for (int j = 0; j < nSubrects; j++) { if (bytesPixel == 1) { pixel = colors[ds.readUnsignedByte()]; } else { ds.skip(4); pixel = new Color(buf[j*12+2] & 0xFF, buf[j*12+1] & 0xFF, buf[j*12] & 0xFF); } sx = x + ds.readUnsignedShort(); sy = y + ds.readUnsignedShort(); sw = ds.readUnsignedShort(); sh = ds.readUnsignedShort(); memGraphics.setColor(pixel); memGraphics.fillRect(sx, sy, sw, sh); } scheduleRepaint(x, y, w, h); } // // Handle a CoRRE-encoded rectangle. // void handleCoRRERect(int x, int y, int w, int h) throws IOException { int nSubrects = rfb.is.readInt(); byte[] bg_buf = new byte[bytesPixel]; rfb.readFully(bg_buf); Color pixel; if (bytesPixel == 1) { pixel = colors[bg_buf[0] & 0xFF]; } else { pixel = new Color(bg_buf[2] & 0xFF, bg_buf[1] & 0xFF, bg_buf[0] & 0xFF); } memGraphics.setColor(pixel); memGraphics.fillRect(x, y, w, h); byte[] buf = new byte[nSubrects * (bytesPixel + 4)]; rfb.readFully(buf); if (rfb.rec != null) { rfb.rec.writeIntBE(nSubrects); rfb.rec.write(bg_buf); rfb.rec.write(buf); } int sx, sy, sw, sh; int i = 0; for (int j = 0; j < nSubrects; j++) { if (bytesPixel == 1) { pixel = colors[buf[i++] & 0xFF]; } else { pixel = new Color(buf[i+2] & 0xFF, buf[i+1] & 0xFF, buf[i] & 0xFF); i += 4; } sx = x + (buf[i++] & 0xFF); sy = y + (buf[i++] & 0xFF); sw = buf[i++] & 0xFF; sh = buf[i++] & 0xFF; memGraphics.setColor(pixel); memGraphics.fillRect(sx, sy, sw, sh); } scheduleRepaint(x, y, w, h); } // // Handle a Hextile-encoded rectangle. // // These colors should be kept between handleHextileSubrect() calls. private Color hextile_bg, hextile_fg; void handleHextileRect(int x, int y, int w, int h) throws IOException { 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); } // Finished with a row of tiles, now let's show it. scheduleRepaint(x, y, w, h); } } // // Handle one tile in the Hextile-encoded data. // void handleHextileSubrect(int tx, int ty, int tw, int th) throws IOException { int subencoding = rfb.is.readUnsignedByte(); if (rfb.rec != null) { rfb.rec.writeByte(subencoding); } // Is it a raw-encoded sub-rectangle? if ((subencoding & rfb.HextileRaw) != 0) { handleRawRect(tx, ty, tw, th, false); return; } // Read and draw the background if specified. byte[] cbuf = new byte[bytesPixel]; if ((subencoding & rfb.HextileBackgroundSpecified) != 0) { rfb.readFully(cbuf); if (bytesPixel == 1) { hextile_bg = colors[cbuf[0] & 0xFF]; } else { hextile_bg = new Color(cbuf[2] & 0xFF, cbuf[1] & 0xFF, cbuf[0] & 0xFF); } if (rfb.rec != null) { rfb.rec.write(cbuf); } } memGraphics.setColor(hextile_bg); memGraphics.fillRect(tx, ty, tw, th); // Read the foreground color if specified. if ((subencoding & rfb.HextileForegroundSpecified) != 0) { rfb.readFully(cbuf); if (bytesPixel == 1) { hextile_fg = colors[cbuf[0] & 0xFF]; } else { hextile_fg = new Color(cbuf[2] & 0xFF, cbuf[1] & 0xFF, cbuf[0] & 0xFF); } if (rfb.rec != null) { rfb.rec.write(cbuf); } } // Done with this tile if there is no sub-rectangles. if ((subencoding & rfb.HextileAnySubrects) == 0) return; int nSubrects = rfb.is.readUnsignedByte(); int bufsize = nSubrects * 2; if ((subencoding & rfb.HextileSubrectsColoured) != 0) { bufsize += nSubrects * bytesPixel; } byte[] buf = new byte[bufsize]; rfb.readFully(buf); if (rfb.rec != null) { rfb.rec.writeByte(nSubrects); rfb.rec.write(buf); } int b1, b2, sx, sy, sw, sh; int i = 0; if ((subencoding & rfb.HextileSubrectsColoured) == 0) { // Sub-rectangles are all of the same color. memGraphics.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; memGraphics.fillRect(sx, sy, sw, sh); } } else if (bytesPixel == 1) { // BGR233 (8-bit color) version for colored sub-rectangles. for (int j = 0; j < nSubrects; j++) { hextile_fg = colors[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; memGraphics.setColor(hextile_fg); memGraphics.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; memGraphics.setColor(hextile_fg); memGraphics.fillRect(sx, sy, sw, sh); } } } // // Handle a ZRLE-encoded rectangle. // // FIXME: Currently, session recording is not fully supported for ZRLE. // void handleZRLERect(int x, int y, int w, int h) throws Exception { if (zrleInStream == null) zrleInStream = new ZlibInStream(); int nBytes = rfb.is.readInt(); if (nBytes > 64 * 1024 * 1024) throw new Exception("ZRLE decoder: illegal compressed data size"); if (zrleBuf == null || zrleBufLen < nBytes) { zrleBufLen = nBytes + 4096; zrleBuf = new byte[zrleBufLen]; } // FIXME: Do not wait for all the data before decompression. rfb.readFully(zrleBuf, 0, nBytes); if (rfb.rec != null) { if (rfb.recordFromBeginning) { rfb.rec.writeIntBE(nBytes); rfb.rec.write(zrleBuf, 0, nBytes); } else if (!zrleRecWarningShown) { System.out.println("Warning: ZRLE session can be recorded" + " only from the beginning"); System.out.println("Warning: Recorded file may be corrupted"); zrleRecWarningShown = true; } } zrleInStream.setUnderlying(new MemInStream(zrleBuf, 0, nBytes), nBytes); for (int ty = y; ty < y+h; ty += 64) { int th = Math.min(y+h-ty, 64); for (int tx = x; tx < x+w; tx += 64) { int tw = Math.min(x+w-tx, 64); int mode = zrleInStream.readU8(); boolean rle = (mode & 128) != 0; int palSize = mode & 127; int[] palette = new int[128]; readZrlePalette(palette, palSize); if (palSize == 1) { int pix = palette[0]; Color c = (bytesPixel == 1) ? colors[pix] : new Color(0xFF000000 | pix); memGraphics.setColor(c); memGraphics.fillRect(tx, ty, tw, th); continue; } if (!rle) { if (palSize == 0) { readZrleRawPixels(tw, th); } else { readZrlePackedPixels(tw, th, palette, palSize); } } else { if (palSize == 0) { readZrlePlainRLEPixels(tw, th); } else { readZrlePackedRLEPixels(tw, th, palette); } } handleUpdatedZrleTile(tx, ty, tw, th); } } zrleInStream.reset(); scheduleRepaint(x, y, w, h); } int readPixel(InStream is) throws Exception { int pix; if (bytesPixel == 1) { pix = is.readU8(); } else { int p1 = is.readU8(); int p2 = is.readU8(); int p3 = is.readU8(); pix = (p3 & 0xFF) << 16 | (p2 & 0xFF) << 8 | (p1 & 0xFF); } return pix; } void readPixels(InStream is, int[] dst, int count) throws Exception { int pix; if (bytesPixel == 1) { byte[] buf = new byte[count]; is.readBytes(buf, 0, count); for (int i = 0; i < count; i++) { dst[i] = (int)buf[i] & 0xFF; } } else { byte[] buf = new byte[count * 3]; is.readBytes(buf, 0, count * 3); for (int i = 0; i < count; i++) { dst[i] = ((buf[i*3+2] & 0xFF) << 16 | (buf[i*3+1] & 0xFF) << 8 | (buf[i*3] & 0xFF));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -