0001: ///////////////////////////////////////////////////////////////////////////////
0002: //
0003: // This program is free software; you can redistribute it and/or modify
0004: // it under the terms of the GNU General Public License and GNU Library
0005: // General Public License as published by the Free Software Foundation;
0006: // either version 2, or (at your option) any later version.
0007: //
0008: // This program is distributed in the hope that it will be useful,
0009: // but WITHOUT ANY WARRANTY; without even the implied warranty of
0010: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0011: // GNU General Public License and GNU Library General Public License
0012: // for more details.
0013: //
0014: // You should have received a copy of the GNU General Public License
0015: // and GNU Library General Public License along with this program; if
0016: // not, write to the Free Software Foundation, 675 Mass Ave, Cambridge,
0017: // MA 02139, USA.
0018: //
0019: ///////////////////////////////////////////////////////////////////////////////
0020:
0021: package org.rdesktop.server.rdp;
0022:
0023: import java.io.IOException;
0024: import java.awt.image.IndexColorModel;
0025:
0026: import org.rdesktop.server.rdp.orders.*;
0027:
0028: public class RdpOrders {
0029: /* RDP_BMPCACHE2_ORDER */
0030: private static final int ID_MASK = 0x0007;
0031: private static final int MODE_MASK = 0x0038;
0032: private static final int SQUARE = 0x0080;
0033: private static final int PERSIST = 0x0100;
0034: private static final int FLAG_51_UNKNOWN = 0x0800;
0035: private static final int MODE_SHIFT = 3;
0036: private static final int LONG_FORMAT = 0x80;
0037: private static final int BUFSIZE_MASK = 0x3FFF; /* or 0x1FFF? */
0038: private static final int RDP_ORDER_STANDARD = 0x01;
0039: private static final int RDP_ORDER_SECONDARY = 0x02;
0040: private static final int RDP_ORDER_BOUNDS = 0x04;
0041: private static final int RDP_ORDER_CHANGE = 0x08;
0042: private static final int RDP_ORDER_DELTA = 0x10;
0043: private static final int RDP_ORDER_LASTBOUNDS = 0x20;
0044: private static final int RDP_ORDER_SMALL = 0x40;
0045: private static final int RDP_ORDER_TINY = 0x80;
0046:
0047: /* standard order types */
0048: private static final int RDP_ORDER_DESTBLT = 0;
0049: private static final int RDP_ORDER_PATBLT = 1;
0050: private static final int RDP_ORDER_SCREENBLT = 2;
0051: private static final int RDP_ORDER_LINE = 9;
0052: private static final int RDP_ORDER_RECT = 10;
0053: private static final int RDP_ORDER_DESKSAVE = 11;
0054: private static final int RDP_ORDER_MEMBLT = 13;
0055: private static final int RDP_ORDER_TRIBLT = 14;
0056: private static final int RDP_ORDER_POLYLINE = 22;
0057: private static final int RDP_ORDER_TEXT2 = 27;
0058: private int rect_colour;
0059:
0060: /* secondary order types */
0061: private static final int RDP_ORDER_RAW_BMPCACHE = 0;
0062: private static final int RDP_ORDER_COLCACHE = 1;
0063: private static final int RDP_ORDER_BMPCACHE = 2;
0064: private static final int RDP_ORDER_FONTCACHE = 3;
0065: private static final int RDP_ORDER_RAW_BMPCACHE2 = 4;
0066: private static final int RDP_ORDER_BMPCACHE2 = 5;
0067: private static final int MIX_TRANSPARENT = 0;
0068: private static final int MIX_OPAQUE = 1;
0069: private static final int TEXT2_VERTICAL = 0x04;
0070: private static final int TEXT2_IMPLICIT_X = 0x20;
0071:
0072: private RdpOrderState m_os;
0073: private RdpCache m_cache = null;
0074: private RdpAbstractDesktopCanvas m_surface;
0075:
0076: private static int setCoordinate(RdpPacket data, int coordinate,
0077: boolean delta) {
0078: byte change = 0;
0079:
0080: if (delta == true) {
0081: change = (byte) data.get8();
0082: coordinate += (int) change;
0083: return coordinate;
0084: } else {
0085: coordinate = data.getLittleEndian16();
0086: return coordinate;
0087: }
0088: }
0089:
0090: private static int setColor(RdpPacket data) {
0091: int color = 0;
0092: int i = 0;
0093:
0094: i = data.get8();
0095: color = i;
0096: i = data.get8();
0097: color |= i << 8;
0098: i = data.get8();
0099: color |= i << 16;
0100:
0101: return color;
0102: }
0103:
0104: private static boolean parsePen(RdpPacket data, Pen pen, int present) {
0105: if ((present & 0x01) != 0) {
0106: pen.setStyle(data.get8());
0107: }
0108:
0109: if ((present & 0x02) != 0) {
0110: pen.setWidth(data.get8());
0111: }
0112:
0113: if ((present & 0x04) != 0) {
0114: pen.setColor(setColor(data));
0115: }
0116:
0117: return true;
0118: }
0119:
0120: public RdpOrders() {
0121: m_os = new RdpOrderState();
0122: m_surface = null;
0123: }
0124:
0125: private int ROP2_S(int rop3) {
0126: return (rop3 & 0x0f);
0127: }
0128:
0129: private int ROP2_P(int rop3) {
0130: return ((rop3 & 0x3) | ((rop3 & 0x30) >> 2));
0131: }
0132:
0133: private int inPresent(RdpPacket data, int flags, int size) {
0134: int present = 0;
0135: int bits = 0;
0136: int i = 0;
0137:
0138: if ((flags & RDP_ORDER_SMALL) != 0) {
0139: size--;
0140: }
0141:
0142: if ((flags & RDP_ORDER_TINY) != 0) {
0143: if (size < 2) {
0144: size = 0;
0145: } else {
0146: size -= 2;
0147: }
0148: }
0149:
0150: for (i = 0; i < size; i++) {
0151: bits = data.get8();
0152: present |= (bits << (i * 8));
0153: }
0154:
0155: return present;
0156: }
0157:
0158: private void processSecondaryOrders(RdpPacket data)
0159: throws RdpOrderException, RdpDesktopException {
0160: int length = 0;
0161: int type = 0;
0162: int flags = 0;
0163: int next_order = 0;
0164:
0165: length = data.getLittleEndian16();
0166: flags = data.getLittleEndian16();
0167: type = data.get8();
0168:
0169: next_order = data.getPosition() + length + 7;
0170:
0171: switch (type) {
0172: case RDP_ORDER_RAW_BMPCACHE: {
0173: processRawBitmapCache(data);
0174: break;
0175: }
0176: case RDP_ORDER_COLCACHE: {
0177: processColorCache(data);
0178: break;
0179: }
0180: case RDP_ORDER_BMPCACHE: {
0181: processBitmapCache(data);
0182: break;
0183: }
0184: case RDP_ORDER_FONTCACHE: {
0185: processFontCache(data);
0186: break;
0187: }
0188: case RDP_ORDER_RAW_BMPCACHE2: {
0189: try {
0190: process_bmpcache2(data, flags, false);
0191: } catch (IOException e) {
0192: throw new RdpDesktopException(e.getMessage());
0193: }
0194:
0195: break;
0196: }
0197: case RDP_ORDER_BMPCACHE2: {
0198: try {
0199: process_bmpcache2(data, flags, true);
0200: } catch (IOException e) {
0201: throw new RdpDesktopException(e.getMessage());
0202: }
0203:
0204: break;
0205: }
0206: default: {
0207: }
0208: }
0209:
0210: data.setPosition(next_order);
0211: }
0212:
0213: private void processRawBitmapCache(RdpPacket data)
0214: throws RdpDesktopException {
0215: int cache_id = data.get8();
0216: data.incrementPosition(1); // pad
0217: int width = data.get8();
0218: int height = data.get8();
0219: int bpp = data.get8();
0220: int Bpp = (bpp + 7) / 8;
0221: int bufsize = data.getLittleEndian16();
0222: int cache_idx = data.getLittleEndian16();
0223: int pdata = data.getPosition();
0224: data.incrementPosition(bufsize);
0225:
0226: byte[] inverted = new byte[width * height * Bpp];
0227: int pinverted = (height - 1) * (width * Bpp);
0228: for (int y = 0; y < height; y++) {
0229: data.copyToByteArray(inverted, pinverted, pdata, width
0230: * Bpp);
0231: pinverted -= width * Bpp;
0232: pdata += width * Bpp;
0233: }
0234:
0235: m_cache.putBitmap(cache_id, cache_idx, new RdpBitmap(RdpBitmap
0236: .convertImage(inverted, Bpp), width, height, 0, 0), 0);
0237: }
0238:
0239: private void processColorCache(RdpPacket data)
0240: throws RdpDesktopException {
0241: byte[] palette = null;
0242:
0243: byte[] red = null;
0244: byte[] green = null;
0245: byte[] blue = null;
0246: int j = 0;
0247:
0248: int cache_id = data.get8();
0249: int n_colors = data.getLittleEndian16(); // Number of Colors in Palette
0250:
0251: palette = new byte[n_colors * 4];
0252: red = new byte[n_colors];
0253: green = new byte[n_colors];
0254: blue = new byte[n_colors];
0255: data.copyToByteArray(palette, 0, data.getPosition(),
0256: palette.length);
0257: data.incrementPosition(palette.length);
0258:
0259: for (int i = 0; i < n_colors; i++) {
0260: blue[i] = palette[j];
0261: green[i] = palette[j + 1];
0262: red[i] = palette[j + 2];
0263: j += 4;
0264: }
0265:
0266: IndexColorModel cm = new IndexColorModel(8, n_colors, red,
0267: green, blue);
0268: m_cache.put_colourmap(cache_id, cm);
0269: }
0270:
0271: private void processBitmapCache(RdpPacket data)
0272: throws RdpDesktopException {
0273: int pad1;
0274: int bufsize, pad2, row_size, final_size, size;
0275: bufsize = pad2 = row_size = final_size = size = 0;
0276:
0277: int cache_id = data.get8();
0278: pad1 = data.get8(); // pad
0279: int width = data.get8();
0280: int height = data.get8();
0281: int bpp = data.get8();
0282: int Bpp = (bpp + 7) / 8;
0283: bufsize = data.getLittleEndian16(); // bufsize
0284: int cache_idx = data.getLittleEndian16();
0285:
0286: if (RdpOptions.use_rdp5 == true) {
0287: pad2 = data.getLittleEndian16();
0288: size = data.getLittleEndian16();
0289: row_size = data.getLittleEndian16();
0290: final_size = data.getLittleEndian16();
0291: } else {
0292: data.incrementPosition(2);
0293: size = data.getLittleEndian16();
0294: row_size = data.getLittleEndian16();
0295: final_size = data.getLittleEndian16();
0296: }
0297:
0298: if (Bpp == 1) {
0299: byte[] pixel = RdpBitmap.decompress(width, height, size,
0300: data, Bpp);
0301: if (pixel != null) {
0302: m_cache.putBitmap(cache_id, cache_idx, new RdpBitmap(
0303: RdpBitmap.convertImage(pixel, Bpp), width,
0304: height, 0, 0), 0);
0305: }
0306: } else {
0307: int[] pixel = RdpBitmap.decompressInt(width, height, size,
0308: data, Bpp);
0309: if (pixel != null) {
0310: m_cache.putBitmap(cache_id, cache_idx, new RdpBitmap(
0311: pixel, width, height, 0, 0), 0);
0312: }
0313: }
0314: }
0315:
0316: private void process_bmpcache2(RdpPacket data, int flags,
0317: boolean compressed) throws RdpDesktopException, IOException {
0318: int y;
0319: byte[] bmpdata, bitmap_id;
0320: int cache_idx, bufsize;
0321: int cache_id, cache_idx_low, width, height, Bpp;
0322:
0323: RdpBitmap bitmap;
0324:
0325: bitmap_id = new byte[8]; /* prevent compiler warning */
0326: cache_id = flags & ID_MASK;
0327: Bpp = ((flags & MODE_MASK) >> MODE_SHIFT) - 2;
0328: Bpp = RdpOptions.Bpp;
0329:
0330: if ((flags & SQUARE) != 0) {
0331: width = data.get8();
0332: height = width;
0333: } else {
0334: width = data.get8();
0335: height = data.get8();
0336: }
0337:
0338: bufsize = data.getBigEndian16();
0339: bufsize &= BUFSIZE_MASK;
0340: cache_idx = data.get8();
0341:
0342: if ((cache_idx & LONG_FORMAT) != 0) {
0343: cache_idx_low = data.get8();
0344: cache_idx = ((cache_idx ^ LONG_FORMAT) << 8)
0345: + cache_idx_low;
0346: }
0347:
0348: bmpdata = new byte[width * height * Bpp];
0349: int[] bmpdataInt = new int[width * height];
0350:
0351: if (compressed == true) {
0352: if (Bpp == 1) {
0353: bmpdataInt = RdpBitmap.convertImage(RdpBitmap
0354: .decompress(width, height, bufsize, data, Bpp),
0355: Bpp);
0356: } else {
0357: bmpdataInt = RdpBitmap.decompressInt(width, height,
0358: bufsize, data, Bpp);
0359: }
0360:
0361: if (bmpdataInt == null) {
0362: return;
0363: }
0364:
0365: bitmap = new RdpBitmap(bmpdataInt, width, height, 0, 0);
0366: } else {
0367: for (y = 0; y < height; y++) {
0368: data.copyToByteArray(bmpdata, y * (width * Bpp),
0369: (height - y - 1) * (width * Bpp), width * Bpp);
0370: }
0371:
0372: bitmap = new RdpBitmap(
0373: RdpBitmap.convertImage(bmpdata, Bpp), width,
0374: height, 0, 0);
0375: }
0376:
0377: if (bitmap != null) {
0378: m_cache.putBitmap(cache_id, cache_idx, bitmap, 0);
0379: }
0380: }
0381:
0382: private void processFontCache(RdpPacket data)
0383: throws RdpDesktopException {
0384: int datasize = 0;
0385: int font = 0, nglyphs = 0;
0386: int character = 0, offset = 0, baseline = 0, width = 0, height = 0;
0387: byte[] fontdata = null;
0388:
0389: RdpGlyph glyph = null;
0390:
0391: font = data.get8();
0392: nglyphs = data.get8();
0393:
0394: for (int i = 0; i < nglyphs; i++) {
0395: character = data.getLittleEndian16();
0396: offset = data.getLittleEndian16();
0397: baseline = data.getLittleEndian16();
0398: width = data.getLittleEndian16();
0399: height = data.getLittleEndian16();
0400: datasize = (height * ((width + 7) / 8) + 3) & ~3;
0401: fontdata = new byte[datasize];
0402:
0403: data.copyToByteArray(fontdata, 0, data.getPosition(),
0404: datasize);
0405: data.incrementPosition(datasize);
0406: glyph = new RdpGlyph(font, character, offset, baseline,
0407: width, height, fontdata);
0408: m_cache.putFont(glyph);
0409: }
0410: }
0411:
0412: private void processDestBlt(RdpPacket data, DestBltOrder destblt,
0413: int present, boolean delta) {
0414: if ((present & 0x01) != 0) {
0415: destblt.setX(setCoordinate(data, destblt.getX(), delta));
0416: }
0417:
0418: if ((present & 0x02) != 0) {
0419: destblt.setY(setCoordinate(data, destblt.getY(), delta));
0420: }
0421:
0422: if ((present & 0x04) != 0) {
0423: destblt.setCX(setCoordinate(data, destblt.getCX(), delta));
0424: }
0425:
0426: if ((present & 0x08) != 0) {
0427: destblt.setCY(setCoordinate(data, destblt.getCY(), delta));
0428: }
0429:
0430: if ((present & 0x10) != 0) {
0431: destblt.setOpcode(ROP2_S(data.get8()));
0432: }
0433:
0434: m_surface.drawDestBltOrder(destblt);
0435: }
0436:
0437: private void parseBrush(RdpPacket data, Brush brush, int present) {
0438: if ((present & 0x01) != 0) {
0439: brush.setXOrigin(data.get8());
0440: }
0441:
0442: if ((present & 0x02) != 0) {
0443: brush.setXOrigin(data.get8());
0444: }
0445:
0446: if ((present & 0x04) != 0) {
0447: brush.setStyle(data.get8());
0448: }
0449:
0450: byte[] pat = brush.getPattern();
0451: if ((present & 0x08) != 0) {
0452: pat[0] = (byte) data.get8();
0453: }
0454:
0455: if ((present & 0x10) != 0) {
0456: for (int i = 1; i < 8; i++) {
0457: pat[i] = (byte) data.get8();
0458: }
0459: }
0460:
0461: brush.setPattern(pat);
0462: }
0463:
0464: private void processPatBlt(RdpPacket data, PatBltOrder patblt,
0465: int present, boolean delta) {
0466: if ((present & 0x01) != 0) {
0467: patblt.setX(setCoordinate(data, patblt.getX(), delta));
0468: }
0469:
0470: if ((present & 0x02) != 0) {
0471: patblt.setY(setCoordinate(data, patblt.getY(), delta));
0472: }
0473:
0474: if ((present & 0x04) != 0) {
0475: patblt.setCX(setCoordinate(data, patblt.getCX(), delta));
0476: }
0477:
0478: if ((present & 0x08) != 0) {
0479: patblt.setCY(setCoordinate(data, patblt.getCY(), delta));
0480: }
0481:
0482: if ((present & 0x10) != 0) {
0483: patblt.setOpcode(ROP2_P(data.get8()));
0484: }
0485:
0486: if ((present & 0x20) != 0) {
0487: patblt.setBackgroundColor(setColor(data));
0488: }
0489:
0490: if ((present & 0x40) != 0) {
0491: patblt.setForegroundColor(setColor(data));
0492: }
0493:
0494: parseBrush(data, patblt.getBrush(), present >> 7);
0495: m_surface.drawPatBltOrder(patblt);
0496: }
0497:
0498: private void processScreenBlt(RdpPacket data,
0499: ScreenBltOrder screenblt, int present, boolean delta) {
0500: if ((present & 0x01) != 0) {
0501: screenblt
0502: .setX(setCoordinate(data, screenblt.getX(), delta));
0503: }
0504:
0505: if ((present & 0x02) != 0) {
0506: screenblt
0507: .setY(setCoordinate(data, screenblt.getY(), delta));
0508: }
0509:
0510: if ((present & 0x04) != 0) {
0511: screenblt.setCX(setCoordinate(data, screenblt.getCX(),
0512: delta));
0513: }
0514:
0515: if ((present & 0x08) != 0) {
0516: screenblt.setCY(setCoordinate(data, screenblt.getCY(),
0517: delta));
0518: }
0519:
0520: if ((present & 0x10) != 0) {
0521: screenblt.setOpcode(ROP2_S(data.get8()));
0522: }
0523:
0524: if ((present & 0x20) != 0) {
0525: screenblt.setSrcX(setCoordinate(data, screenblt.getSrcX(),
0526: delta));
0527: }
0528:
0529: if ((present & 0x40) != 0) {
0530: screenblt.setSrcY(setCoordinate(data, screenblt.getSrcY(),
0531: delta));
0532: }
0533:
0534: m_surface.drawScreenBltOrder(screenblt);
0535: }
0536:
0537: private void processLine(RdpPacket data, LineOrder line,
0538: int present, boolean delta) {
0539: if ((present & 0x01) != 0) {
0540: line.setMixmode(data.getLittleEndian16());
0541: }
0542:
0543: if ((present & 0x02) != 0) {
0544: line
0545: .setStartX(setCoordinate(data, line.getStartX(),
0546: delta));
0547: }
0548:
0549: if ((present & 0x04) != 0) {
0550: line
0551: .setStartY(setCoordinate(data, line.getStartY(),
0552: delta));
0553: }
0554:
0555: if ((present & 0x08) != 0) {
0556: line.setEndX(setCoordinate(data, line.getEndX(), delta));
0557: }
0558:
0559: if ((present & 0x10) != 0) {
0560: line.setEndY(setCoordinate(data, line.getEndY(), delta));
0561: }
0562:
0563: if ((present & 0x20) != 0) {
0564: line.setBackgroundColor(setColor(data));
0565: }
0566:
0567: if ((present & 0x40) != 0) {
0568: line.setOpcode(data.get8());
0569: }
0570:
0571: parsePen(data, line.getPen(), present >> 7);
0572:
0573: if (line.getOpcode() < 0x01 || line.getOpcode() > 0x10) {
0574: return;
0575: }
0576:
0577: m_surface.drawLineOrder(line);
0578: }
0579:
0580: private void processRectangle(RdpPacket data, RectangleOrder rect,
0581: int present, boolean delta) {
0582: if ((present & 0x01) != 0) {
0583: rect.setX(setCoordinate(data, rect.getX(), delta));
0584: }
0585:
0586: if ((present & 0x02) != 0) {
0587: rect.setY(setCoordinate(data, rect.getY(), delta));
0588: }
0589:
0590: if ((present & 0x04) != 0) {
0591: rect.setCX(setCoordinate(data, rect.getCX(), delta));
0592: }
0593:
0594: if ((present & 0x08) != 0) {
0595: rect.setCY(setCoordinate(data, rect.getCY(), delta));
0596: }
0597:
0598: if ((present & 0x10) != 0) {
0599: rect_colour = (rect_colour & 0xffffff00) | data.get8();
0600: }
0601:
0602: if ((present & 0x20) != 0) {
0603: rect_colour = (rect_colour & 0xffff00ff)
0604: | (data.get8() << 8);
0605: }
0606:
0607: if ((present & 0x40) != 0) {
0608: rect_colour = (rect_colour & 0xff00ffff)
0609: | (data.get8() << 16);
0610: }
0611:
0612: rect.setColor(rect_colour);
0613: m_surface.drawRectangleOrder(rect);
0614: }
0615:
0616: private void processDeskSave(RdpPacket data,
0617: DeskSaveOrder desksave, int present, boolean delta)
0618: throws RdpDesktopException {
0619: int width = 0, height = 0;
0620:
0621: if ((present & 0x01) != 0) {
0622: desksave.setOffset(data.getLittleEndian32());
0623: }
0624:
0625: if ((present & 0x02) != 0) {
0626: desksave.setLeft(setCoordinate(data, desksave.getLeft(),
0627: delta));
0628: }
0629:
0630: if ((present & 0x04) != 0) {
0631: desksave.setTop(setCoordinate(data, desksave.getTop(),
0632: delta));
0633: }
0634:
0635: if ((present & 0x08) != 0) {
0636: desksave.setRight(setCoordinate(data, desksave.getRight(),
0637: delta));
0638: }
0639:
0640: if ((present & 0x10) != 0) {
0641: desksave.setBottom(setCoordinate(data,
0642: desksave.getBottom(), delta));
0643: }
0644:
0645: if ((present & 0x20) != 0) {
0646: desksave.setAction(data.get8());
0647: }
0648:
0649: width = desksave.getRight() - desksave.getLeft() + 1;
0650: height = desksave.getBottom() - desksave.getTop() + 1;
0651:
0652: if (desksave.getAction() == 0) {
0653: int[] pixel = m_surface.getImage(desksave.getLeft(),
0654: desksave.getTop(), width, height);
0655: m_cache.putDesktop((int) desksave.getOffset(), width,
0656: height, pixel);
0657: } else {
0658: int[] pixel = m_cache.getDesktopInt((int) desksave
0659: .getOffset(), width, height);
0660: m_surface.putImage(desksave.getLeft(), desksave.getTop(),
0661: width, height, pixel);
0662: }
0663: }
0664:
0665: private void processMemBlt(RdpPacket data, MemBltOrder memblt,
0666: int present, boolean delta) {
0667: if ((present & 0x01) != 0) {
0668: memblt.setCacheID(data.get8());
0669: memblt.setColorTable(data.get8());
0670: }
0671:
0672: if ((present & 0x02) != 0) {
0673: memblt.setX(setCoordinate(data, memblt.getX(), delta));
0674: }
0675:
0676: if ((present & 0x04) != 0) {
0677: memblt.setY(setCoordinate(data, memblt.getY(), delta));
0678: }
0679:
0680: if ((present & 0x08) != 0) {
0681: memblt.setCX(setCoordinate(data, memblt.getCX(), delta));
0682: }
0683:
0684: if ((present & 0x10) != 0) {
0685: memblt.setCY(setCoordinate(data, memblt.getCY(), delta));
0686: }
0687:
0688: if ((present & 0x20) != 0) {
0689: memblt.setOpcode(ROP2_S(data.get8()));
0690: }
0691:
0692: if ((present & 0x40) != 0) {
0693: memblt
0694: .setSrcX(setCoordinate(data, memblt.getSrcX(),
0695: delta));
0696: }
0697:
0698: if ((present & 0x80) != 0) {
0699: memblt
0700: .setSrcY(setCoordinate(data, memblt.getSrcY(),
0701: delta));
0702: }
0703:
0704: if ((present & 0x0100) != 0) {
0705: memblt.setCacheIDX(data.getLittleEndian16());
0706: }
0707:
0708: m_surface.drawMemBltOrder(memblt);
0709: }
0710:
0711: private void processTriBlt(RdpPacket data, TriBltOrder triblt,
0712: int present, boolean delta) {
0713: if ((present & 0x01) != 0) {
0714: triblt.setCacheID(data.get8());
0715: triblt.setColorTable(data.get8());
0716: }
0717:
0718: if ((present & 0x02) != 0) {
0719: triblt.setX(setCoordinate(data, triblt.getX(), delta));
0720: }
0721:
0722: if ((present & 0x04) != 0) {
0723: triblt.setY(setCoordinate(data, triblt.getY(), delta));
0724: }
0725:
0726: if ((present & 0x08) != 0) {
0727: triblt.setCX(setCoordinate(data, triblt.getCX(), delta));
0728: }
0729:
0730: if ((present & 0x10) != 0) {
0731: triblt.setCY(setCoordinate(data, triblt.getCY(), delta));
0732: }
0733:
0734: if ((present & 0x20) != 0) {
0735: triblt.setOpcode(ROP2_S(data.get8()));
0736: }
0737:
0738: if ((present & 0x40) != 0) {
0739: triblt
0740: .setSrcX(setCoordinate(data, triblt.getSrcX(),
0741: delta));
0742: }
0743:
0744: if ((present & 0x80) != 0) {
0745: triblt
0746: .setSrcY(setCoordinate(data, triblt.getSrcY(),
0747: delta));
0748: }
0749:
0750: if ((present & 0x0100) != 0) {
0751: triblt.setBackgroundColor(setColor(data));
0752: }
0753:
0754: if ((present & 0x0200) != 0) {
0755: triblt.setForegroundColor(setColor(data));
0756: }
0757:
0758: parseBrush(data, triblt.getBrush(), present >> 10);
0759:
0760: if ((present & 0x8000) != 0) {
0761: triblt.setCacheIDX(data.getLittleEndian16());
0762: }
0763:
0764: if ((present & 0x10000) != 0) {
0765: triblt.setUnknown(data.getLittleEndian16());
0766: }
0767:
0768: m_surface.drawTriBltOrder(triblt);
0769: }
0770:
0771: private void processPolyLine(RdpPacket data,
0772: PolyLineOrder polyline, int present, boolean delta) {
0773: if ((present & 0x01) != 0) {
0774: polyline.setX(setCoordinate(data, polyline.getX(), delta));
0775: }
0776:
0777: if ((present & 0x02) != 0) {
0778: polyline.setY(setCoordinate(data, polyline.getY(), delta));
0779: }
0780:
0781: if ((present & 0x04) != 0) {
0782: polyline.setOpcode(data.get8());
0783: }
0784:
0785: if ((present & 0x10) != 0) {
0786: polyline.setForegroundColor(setColor(data));
0787: }
0788:
0789: if ((present & 0x20) != 0) {
0790: polyline.setLines(data.get8());
0791: }
0792:
0793: if ((present & 0x40) != 0) {
0794: int datasize = data.get8();
0795: polyline.setDataSize(datasize);
0796: byte[] databytes = new byte[datasize];
0797: for (int i = 0; i < datasize; i++) {
0798: databytes[i] = (byte) data.get8();
0799: }
0800:
0801: polyline.setData(databytes);
0802: }
0803:
0804: m_surface.drawPolyLineOrder(polyline);
0805: }
0806:
0807: private void processText2(RdpPacket data, Text2Order text2,
0808: int present, boolean delta) throws RdpDesktopException {
0809: if ((present & 0x000001) != 0) {
0810: text2.setFont(data.get8());
0811: }
0812:
0813: if ((present & 0x000002) != 0) {
0814: text2.setFlags(data.get8());
0815: }
0816:
0817: if ((present & 0x000004) != 0) {
0818: text2.setOpcode(data.get8());
0819: }
0820:
0821: if ((present & 0x000008) != 0) {
0822: text2.setMixmode(data.get8());
0823: }
0824:
0825: if ((present & 0x000010) != 0) {
0826: text2.setForegroundColor(setColor(data));
0827: }
0828:
0829: if ((present & 0x000020) != 0) {
0830: text2.setBackgroundColor(setColor(data));
0831: }
0832:
0833: if ((present & 0x000040) != 0) {
0834: text2.setClipLeft(data.getLittleEndian16());
0835: }
0836:
0837: if ((present & 0x000080) != 0) {
0838: text2.setClipTop(data.getLittleEndian16());
0839: }
0840:
0841: if ((present & 0x000100) != 0) {
0842: text2.setClipRight(data.getLittleEndian16());
0843: }
0844:
0845: if ((present & 0x000200) != 0) {
0846: text2.setClipBottom(data.getLittleEndian16());
0847: }
0848:
0849: if ((present & 0x000400) != 0) {
0850: text2.setBoxLeft(data.getLittleEndian16());
0851: }
0852:
0853: if ((present & 0x000800) != 0) {
0854: text2.setBoxTop(data.getLittleEndian16());
0855: }
0856:
0857: if ((present & 0x001000) != 0) {
0858: text2.setBoxRight(data.getLittleEndian16());
0859: }
0860:
0861: if ((present & 0x002000) != 0) {
0862: text2.setBoxBottom(data.getLittleEndian16());
0863: }
0864:
0865: if ((present & 0x004000) != 0) {
0866: data.incrementPosition(1);
0867: }
0868:
0869: if ((present & 0x008000) != 0) {
0870: data.incrementPosition(1);
0871: }
0872:
0873: if ((present & 0x010000) != 0) {
0874: data.incrementPosition(1);
0875: }
0876:
0877: if ((present & 0x020000) != 0) {
0878: data.incrementPosition(4);
0879: }
0880:
0881: if ((present & 0x040000) != 0) {
0882: data.incrementPosition(4);
0883: }
0884:
0885: if ((present & 0x080000) != 0) {
0886: text2.setX(data.getLittleEndian16());
0887: }
0888:
0889: if ((present & 0x100000) != 0) {
0890: text2.setY(data.getLittleEndian16());
0891: }
0892:
0893: if ((present & 0x200000) != 0) {
0894: text2.setLength(data.get8());
0895:
0896: byte[] text = new byte[text2.getLength()];
0897: data.copyToByteArray(text, 0, data.getPosition(),
0898: text.length);
0899: data.incrementPosition(text.length);
0900: text2.setText(text);
0901: }
0902:
0903: drawText(text2, text2.getClipRight() - text2.getClipLeft(),
0904: text2.getClipBottom() - text2.getClipTop(), text2
0905: .getBoxRight()
0906: - text2.getBoxLeft(), text2.getBoxBottom()
0907: - text2.getBoxTop());
0908: }
0909:
0910: private void parseBounds(RdpPacket data, BoundsOrder bounds)
0911: throws RdpOrderException {
0912: int present = 0;
0913:
0914: present = data.get8();
0915:
0916: if ((present & 1) != 0) {
0917: bounds
0918: .setLeft(setCoordinate(data, bounds.getLeft(),
0919: false));
0920: } else if ((present & 16) != 0) {
0921: bounds.setLeft(setCoordinate(data, bounds.getLeft(), true));
0922: }
0923:
0924: if ((present & 2) != 0) {
0925: bounds.setTop(setCoordinate(data, bounds.getTop(), false));
0926: } else if ((present & 32) != 0) {
0927: bounds.setTop(setCoordinate(data, bounds.getTop(), true));
0928: }
0929:
0930: if ((present & 4) != 0) {
0931: bounds.setRight(setCoordinate(data, bounds.getRight(),
0932: false));
0933: } else if ((present & 64) != 0) {
0934: bounds
0935: .setRight(setCoordinate(data, bounds.getRight(),
0936: true));
0937: }
0938:
0939: if ((present & 8) != 0) {
0940: bounds.setBottom(setCoordinate(data, bounds.getBottom(),
0941: false));
0942: } else if ((present & 128) != 0) {
0943: bounds.setBottom(setCoordinate(data, bounds.getBottom(),
0944: true));
0945: }
0946:
0947: if (data.getPosition() > data.getEnd()) {
0948: throw new RdpOrderException("Too far!");
0949: }
0950: }
0951:
0952: private int twosComplement16(int val) {
0953: return ((val & 0x8000) != 0) ? -((~val & 0xFFFF) + 1) : val;
0954: }
0955:
0956: private void drawText(Text2Order text2, int clipcx, int clipcy,
0957: int boxcx, int boxcy) throws RdpDesktopException {
0958: byte[] text = text2.getText();
0959: int length = text2.getLength();
0960: int x = text2.getX();
0961: int y = text2.getY();
0962: int offset = 0;
0963: int ptext = 0;
0964:
0965: RdpGlyph glyph = null;
0966: RdpDataBlob entry = null;
0967:
0968: if (boxcx > 1) {
0969: m_surface.fillRectangle(text2.getBoxLeft(), text2
0970: .getBoxTop(), boxcx, boxcy, text2
0971: .getBackgroundColor());
0972: } else if (text2.getMixmode() == MIX_OPAQUE) {
0973: m_surface.fillRectangle(text2.getClipLeft(), text2
0974: .getClipTop(), clipcx, clipcy, text2
0975: .getBackgroundColor());
0976: }
0977:
0978: for (int i = 0; i < length;) {
0979: switch (text[ptext + i] & 0x000000ff) {
0980: case 0xff: {
0981: if (i + 2 < length) {
0982: byte[] data = new byte[text[ptext + i + 2] & 0x000000ff];
0983: System.arraycopy(text, ptext, data, 0, text[ptext
0984: + i + 2] & 0x000000ff);
0985: RdpDataBlob db = new RdpDataBlob(
0986: text[ptext + i + 2] & 0x000000ff, data);
0987: m_cache.putText(text[ptext + i + 1] & 0x000000ff,
0988: db);
0989: } else {
0990: throw new RdpDesktopException();
0991: }
0992:
0993: length -= i + 3;
0994: ptext = i + 3;
0995: i = 0;
0996: break;
0997: }
0998: case 0xfe: {
0999: entry = m_cache
1000: .getText(text[ptext + i + 1] & 0x000000ff);
1001: if (entry != null) {
1002: if ((entry.getData()[1] == 0)
1003: && ((text2.getFlags() & TEXT2_IMPLICIT_X) == 0)) {
1004: if ((text2.getFlags() & 0x04) != 0) {
1005: y += text[ptext + i + 2] & 0x000000ff;
1006: } else {
1007: x += text[ptext + i + 2] & 0x000000ff;
1008: }
1009: }
1010: }
1011:
1012: if (i + 2 < length) {
1013: i += 3;
1014: } else {
1015: i += 2;
1016: }
1017:
1018: length -= i;
1019: ptext = i;
1020: i = 0;
1021:
1022: byte[] data = entry.getData();
1023: for (int j = 0; j < entry.getSize(); j++) {
1024: glyph = m_cache.getFont(text2.getFont(),
1025: data[j] & 0x000000ff);
1026:
1027: if ((text2.getFlags() & TEXT2_IMPLICIT_X) == 0) {
1028: offset = data[++j] & 0x000000ff;
1029: if ((offset & 0x80) != 0) {
1030: if ((text2.getFlags() & TEXT2_VERTICAL) != 0) {
1031: int var = twosComplement16((data[j + 1] & 0xff)
1032: | ((data[j + 2] & 0xff) << 8));
1033: y += var;
1034: j += 2;
1035: } else {
1036: int var = twosComplement16((data[j + 1] & 0xff)
1037: | ((data[j + 2] & 0xff) << 8));
1038: x += var;
1039: j += 2;
1040: }
1041: } else {
1042: if ((text2.getFlags() & TEXT2_VERTICAL) != 0) {
1043: y += offset;
1044: } else {
1045: x += offset;
1046: }
1047: }
1048: }
1049:
1050: if (glyph != null) {
1051: m_surface.drawGlyph(text2.getMixmode(), x
1052: + (short) glyph.getOffset(), y
1053: + (short) glyph.getBaseLine(), glyph
1054: .getWidth(), glyph.getHeight(), glyph
1055: .getFontData(), text2
1056: .getBackgroundColor(), text2
1057: .getForegroundColor());
1058:
1059: if ((text2.getFlags() & TEXT2_IMPLICIT_X) != 0) {
1060: x += glyph.getWidth();
1061: }
1062: }
1063: }
1064:
1065: break;
1066: }
1067: default: {
1068: glyph = m_cache.getFont(text2.getFont(),
1069: text[ptext + i] & 0x000000ff);
1070:
1071: if ((text2.getFlags() & TEXT2_IMPLICIT_X) == 0) {
1072: offset = text[ptext + (++i)] & 0x000000ff;
1073: if ((offset & 0x80) != 0) {
1074: if ((text2.getFlags() & TEXT2_VERTICAL) != 0) {
1075: int var = twosComplement16((text[ptext + i
1076: + 1] & 0x000000ff)
1077: | ((text[ptext + i + 2] & 0x000000ff) << 8));
1078: y += var;
1079: i += 2;
1080: } else {
1081: int var = twosComplement16((text[ptext + i
1082: + 1] & 0x000000ff)
1083: | ((text[ptext + i + 2] & 0x000000ff) << 8));
1084: x += var;
1085: i += 2;
1086: }
1087: } else {
1088: if ((text2.getFlags() & TEXT2_VERTICAL) != 0) {
1089: y += offset;
1090: } else {
1091: x += offset;
1092: }
1093: }
1094: }
1095:
1096: if (glyph != null) {
1097: m_surface.drawGlyph(text2.getMixmode(), x
1098: + (short) glyph.getOffset(), y
1099: + (short) glyph.getBaseLine(), glyph
1100: .getWidth(), glyph.getHeight(), glyph
1101: .getFontData(), text2.getBackgroundColor(),
1102: text2.getForegroundColor());
1103:
1104: if ((text2.getFlags() & TEXT2_IMPLICIT_X) != 0) {
1105: x += glyph.getWidth();
1106: }
1107: }
1108:
1109: i++;
1110: break;
1111: }
1112: }
1113: }
1114: }
1115:
1116: public void resetOrderState() {
1117: m_os.reset();
1118: m_os.setOrderType(RDP_ORDER_PATBLT);
1119: }
1120:
1121: public void registerCache(RdpCache cache) {
1122: m_cache = cache;
1123: }
1124:
1125: public void registerDrawingSurface(RdpAbstractDesktopCanvas surface) {
1126: m_surface = surface;
1127: m_surface.registerCache(m_cache);
1128: }
1129:
1130: public void processOrders(RdpPacket data, int next_packet,
1131: int n_orders) throws RdpOrderException, RdpDesktopException {
1132: int present = 0;
1133: int order_type = 0;
1134: int order_flags = 0;
1135: int size = 0;
1136: int processed = 0;
1137: boolean delta;
1138:
1139: while (processed < n_orders) {
1140: order_flags = data.get8();
1141:
1142: if ((order_flags & RDP_ORDER_STANDARD) == 0) {
1143: throw new RdpOrderException("Order parsing failed!");
1144: }
1145:
1146: if ((order_flags & RDP_ORDER_SECONDARY) != 0) {
1147: processSecondaryOrders(data);
1148: } else {
1149: if ((order_flags & RDP_ORDER_CHANGE) != 0) {
1150: m_os.setOrderType(data.get8());
1151: }
1152:
1153: switch (m_os.getOrderType()) {
1154: case RDP_ORDER_TRIBLT:
1155: case RDP_ORDER_TEXT2: {
1156: size = 3;
1157: break;
1158: }
1159: case RDP_ORDER_PATBLT:
1160: case RDP_ORDER_MEMBLT:
1161: case RDP_ORDER_LINE: {
1162: size = 2;
1163: break;
1164: }
1165: default: {
1166: size = 1;
1167: }
1168: }
1169:
1170: present = inPresent(data, order_flags, size);
1171:
1172: if ((order_flags & RDP_ORDER_BOUNDS) != 0) {
1173: if ((order_flags & RDP_ORDER_LASTBOUNDS) == 0) {
1174: parseBounds(data, m_os.getBounds());
1175: }
1176:
1177: m_surface.setClip(m_os.getBounds());
1178: }
1179:
1180: delta = ((order_flags & RDP_ORDER_DELTA) != 0);
1181:
1182: switch (m_os.getOrderType()) {
1183: case RDP_ORDER_DESTBLT: {
1184: processDestBlt(data, m_os.getDestBlt(), present,
1185: delta);
1186: break;
1187: }
1188: case RDP_ORDER_PATBLT: {
1189: processPatBlt(data, m_os.getPatBlt(), present,
1190: delta);
1191: break;
1192: }
1193: case RDP_ORDER_SCREENBLT: {
1194: processScreenBlt(data, m_os.getScreenBlt(),
1195: present, delta);
1196: break;
1197: }
1198: case RDP_ORDER_LINE: {
1199: processLine(data, m_os.getLine(), present, delta);
1200: break;
1201: }
1202: case RDP_ORDER_RECT: {
1203: processRectangle(data, m_os.getRectangle(),
1204: present, delta);
1205: break;
1206: }
1207: case RDP_ORDER_DESKSAVE: {
1208: processDeskSave(data, m_os.getDeskSave(), present,
1209: delta);
1210: break;
1211: }
1212: case RDP_ORDER_MEMBLT: {
1213: processMemBlt(data, m_os.getMemBlt(), present,
1214: delta);
1215: break;
1216: }
1217: case RDP_ORDER_TRIBLT: {
1218: processTriBlt(data, m_os.getTriBlt(), present,
1219: delta);
1220: break;
1221: }
1222: case RDP_ORDER_POLYLINE: {
1223: processPolyLine(data, m_os.getPolyLine(), present,
1224: delta);
1225: break;
1226: }
1227: case RDP_ORDER_TEXT2: {
1228: processText2(data, m_os.getText2(), present, delta);
1229: break;
1230: }
1231: default: {
1232: return;
1233: }
1234: }
1235:
1236: if ((order_flags & RDP_ORDER_BOUNDS) != 0) {
1237: m_surface.resetClip();
1238: }
1239: }
1240:
1241: processed++;
1242: }
1243:
1244: if (data.getPosition() != next_packet) {
1245: throw new RdpOrderException("End not reached!");
1246: }
1247: }
1248: }
|