Package com.alssoftrd.utils

Source Code of com.alssoftrd.utils.ManageBitmaps

package com.alssoftrd.utils;

import com.alssoftrd.events.EventWakeUp;
import com.lixia.rdp.Bitmap;
import com.lixia.rdp.Cache;
import com.lixia.rdp.RasterOp;
import com.lixia.rdp.RdesktopException;
import com.lixia.rdp.orders.BoundsOrder;
import com.lixia.rdp.orders.Brush;
import com.lixia.rdp.orders.DestBltOrder;
import com.lixia.rdp.orders.LineOrder;
import com.lixia.rdp.orders.MemBltOrder;
import com.lixia.rdp.orders.PatBltOrder;
import com.lixia.rdp.orders.PolyLineOrder;
import com.lixia.rdp.orders.RectangleOrder;
import com.lixia.rdp.orders.ScreenBltOrder;
import com.lixia.rdp.orders.TriBltOrder;
import com.lixia.rdp.rdp5.ARDP5;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.image.MemoryImageSource;
import javax.swing.JPanel;

/**
* @author aluis
*/
public class ManageBitmaps extends javax.swing.JPanel {

//    static Logger logger = Logger.getLogger(ManageBitmaps.class);
    private RasterOp rop = null;

    public static final int ROP2_COPY = 0xc;

    private static final int ROP2_XOR = 0x6;

    private static final int ROP2_AND = 0x8;

    private static final int ROP2_NXOR = 0x9;

    private static final int ROP2_OR = 0xe;

    private static final int MIX_TRANSPARENT = 0;

    private static final int MIX_OPAQUE = 1;

    private static final int TEXT2_VERTICAL = 0x04;

    private static final int TEXT2_IMPLICIT_X = 0x20;

    private Cache cache = null;

    public int width = 0;

    public int height = 0;

    private int top = 0;

    private int left = 0;

    private int right = 0;

    private int bottom = 0;

    private final Dimension dimension;

    public ManageBitmaps(Cache cache) {
        super();
        rop = new RasterOp();
        this.cache = cache;
        this.width = RDPConnection.conf.width;
        this.height = RDPConnection.conf.height;
        this.right = RDPConnection.conf.width; // changed
        this.bottom = RDPConnection.conf.height; // changed
        dimension = new Dimension(width, height);
    }

    @Override
    public Dimension getMinimumSize() {
        return (dimension);
    }

    @Override
    public Dimension getPreferredSize() {
        return (dimension);
    }

    @Override
    public void paint(Graphics g) {
        update(g);
    }

    public void repaintAll(int x, int y, int width, int height) {
        this.repaint(x, y, width, height);
    }

    @Override
    public void update(Graphics g) {
        Rectangle r = g.getClipBounds();
        //Position.debugPrintf("update: x=%d, y=%d, width=%d, height=%d\n", r.x, r.y, r.width, r.height);
        int w = (r.width > RDPConnection.conf.width) ? RDPConnection.conf.width : r.width;
        int h = (r.height > RDPConnection.conf.height) ? RDPConnection.conf.height : r.height;
        super.paintComponent(g);
        Graphics2D tempg = (Graphics2D) g;

        //Draw BufferedImage
        try {
            tempg.drawImage(ARDP5.wi.getSubimage(r.x, r.y, w, h), r.x, r.y, null);
        } catch (Exception e) {
            //nothing to do
        }
    }

    /**
     * Reset clipping boundaries for canvas
     */
    public void resetClip() {
//        Graphics g = this.getGraphics();
//        Rectangle bounds = this.getBounds();
//        g.setClip(bounds.x, bounds.y, bounds.width, bounds.height);
        this.top = 0;
        this.left = 0;
        this.right = this.width - 1; // changed
        this.bottom = this.height - 1; // changed
    }

    /**
     * Set clipping boundaries for canvas, based on a bounds order
     *
     * @param bounds Order defining new boundaries
     */
    public void setClip(BoundsOrder bounds) {
//        Graphics g = this.getGraphics();
//        g.setClip(bounds.getLeft(), bounds.getTop(), bounds.getRight() - bounds.getLeft(), bounds.getBottom() - bounds.getTop());
        this.top = bounds.getTop();
        this.left = bounds.getLeft();
        this.right = bounds.getRight();
        this.bottom = bounds.getBottom();
    }

    /**
     * Perform a dest blt
     *
     * @param destblt DestBltOrder describing the blit to be performed
     */
    public void drawDestBltOrder(DestBltOrder destblt) {
        int x = destblt.getX();
        int y = destblt.getY();

        if (x > this.right || y > this.bottom) {
            return; // off screen
        }
        int cx = destblt.getCX();
        int cy = destblt.getCY();

        int clipright = x + cx - 1;
        if (clipright > this.right) {
            clipright = this.right;
        }
        if (x < this.left) {
            x = this.left;
        }
        cx = clipright - x + 1;

        int clipbottom = y + cy - 1;
        if (clipbottom > this.bottom) {
            clipbottom = this.bottom;
        }
        if (y < this.top) {
            y = this.top;
        }
        cy = clipbottom - y + 1;
        rop.do_array(destblt.getOpcode(), ARDP5.wi, this.width, x, y, cx, cy, null, 0, 0, 0);
        // pinto de nuevo
        this.repaintAll(x, y, cx, cy);
        EventWakeUp.getInstance().imageSegmented(x, y, ARDP5.wi.getSubimage(x, y, cx, cy));
    }

    /**
     * Perform a pattern blit on the screen
     *
     * @param patblt PatBltOrder describing the blit to be performed
     */
    public void drawPatBltOrder(PatBltOrder patblt) {
        Brush brush = patblt.getBrush();
        int x = patblt.getX();
        int y = patblt.getY();

        if (x > this.right || y > this.bottom) {
            return; // off screen
        }
        int cx = patblt.getCX();
        int cy = patblt.getCY();
        int fgcolor = patblt.getForegroundColor();
        int bgcolor = patblt.getBackgroundColor();
        int opcode = patblt.getOpcode();

        patBltOrder(opcode, x, y, cx, cy, fgcolor, bgcolor, brush);
    }

    /**
     * Draw a pattern to the screen (pattern blit)
     *
     * @param opcode Code defining operation to be performed
     * @param x x coordinate for left of blit area
     * @param y y coordinate for top of blit area
     * @param cx Width of blit area
     * @param cy Height of blit area
     * @param fgcolor Foreground colour for pattern
     * @param bgcolor Background colour for pattern
     * @param brush Brush object defining pattern to be drawn
     */
    public void patBltOrder(int opcode, int x, int y, int cx, int cy, int fgcolor, int bgcolor, Brush brush) {
        // convert to 24-bit colour
        fgcolor = Bitmap.convertTo24(fgcolor);
        bgcolor = Bitmap.convertTo24(bgcolor);

        // Perform standard clipping checks, x-axis
        int clipright = x + cx - 1;
        if (clipright > this.right) {
            clipright = this.right;
        }
        if (x < this.left) {
            x = this.left;
        }
        cx = clipright - x + 1;

        // Perform standard clipping checks, y-axis
        int clipbottom = y + cy - 1;
        if (clipbottom > this.bottom) {
            clipbottom = this.bottom;
        }
        if (y < this.top) {
            y = this.top;
        }
        cy = clipbottom - y + 1;

        int i;
        int[] src;
        switch (brush.getStyle()) {
            case 0:
                src = new int[cx * cy];
                for (i = 0; i < src.length; i++) {
                    src[i] = fgcolor;
                }
                rop.do_array(opcode, ARDP5.wi, this.width, x, y, cx, cy, src, cx, 0, 0);
                // pinto de nuevo
                this.repaintAll(x, y, cx, cy);
                EventWakeUp.getInstance().imageSegmented(x, y, ARDP5.wi.getSubimage(x, y, cx, cy));
                break;
            case 2: // hatch
                System.out.println("hatch");
                break;
            case 3: // pattern
                int brushx = brush.getXOrigin();
                int brushy = brush.getYOrigin();
                byte[] pattern = brush.getPattern();
                byte[] ipattern = pattern;
                src = new int[cx * cy];
                int psrc = 0;
                for (i = 0; i < cy; i++) {
                    for (int j = 0; j < cx; j++) {
                        if ((ipattern[(i + brushy) % 8] & (0x01 << ((j + brushx) % 8))) == 0) {
                            src[psrc] = fgcolor;
                        } else {
                            src[psrc] = bgcolor;
                        }
                        psrc++;
                    }
                }
                rop.do_array(opcode, ARDP5.wi, this.width, x, y, cx, cy, src, cx, 0, 0);
                // pinto de nuevo
                this.repaintAll(x, y, cx, cy);
                EventWakeUp.getInstance().imageSegmented(x, y, ARDP5.wi.getSubimage(x, y, cx, cy));
                break;
            default:
//                logger.warn("Unsupported brush style " + brush.getStyle());
        }
    }

    /**
     * Perform a screen blit
     *
     * @param screenblt ScreenBltOrder describing the blit to be performed
     */
    public void drawScreenBltOrder(ScreenBltOrder screenblt) {
        int x = screenblt.getX();
        int y = screenblt.getY();

        if (x > this.right || y > this.bottom) {
            return; // off screen
        }
        int cx = screenblt.getCX();
        int cy = screenblt.getCY();
        int srcx = screenblt.getSrcX();
        int srcy = screenblt.getSrcY();

        int clipright = x + cx - 1;
        if (clipright > this.right) {
            clipright = this.right;
        }
        if (x < this.left) {
            x = this.left;
        }
        cx = clipright - x + 1;

        int clipbottom = y + cy - 1;
        if (clipbottom > this.bottom) {
            clipbottom = this.bottom;
        }
        if (y < this.top) {
            y = this.top;
        }
        cy = clipbottom - y + 1;

        srcx += x - screenblt.getX();
        srcy += y - screenblt.getY();

        rop.do_array(screenblt.getOpcode(), ARDP5.wi, this.width, x, y, cx, cy, null, this.width, srcx, srcy);
        EventWakeUp.getInstance().imageSegmented(x, y, ARDP5.wi.getSubimage(x, y, cx, cy));
        // pinto de nuevo
        this.repaintAll(x, y, cx, cy);
    }

    /**
     * Draw a line to the screen
     *
     * @param line LineOrder describing line to be drawn
     */
    public void drawLineOrder(LineOrder line) {
        int x1 = line.getStartX();
        int y1 = line.getStartY();
        int x2 = line.getEndX();
        int y2 = line.getEndY();

        int fgcolor = line.getPen().getColor();

        int opcode = line.getOpcode() - 1;
        drawLine(x1, y1, x2, y2, fgcolor, opcode);
    }

    /**
     * Draw a line to the screen
     *
     * @param x1 x coordinate of start point of line
     * @param y1 y coordinate of start point of line
     * @param x2 x coordinate of end point of line
     * @param y2 y coordinate of end point of line
     * @param color colour of line
     * @param opcode Operation code defining operation to perform on pixels
     * within the line
     */
    public void drawLine(int x1, int y1, int x2, int y2, int color, int opcode) {
        // convert to 24-bit colour
        color = Bitmap.convertTo24(color);

        if (x1 == x2 || y1 == y2) {
            drawLineVerticalHorizontal(x1, y1, x2, y2, color, opcode);
            return;
        }

        int deltax = Math.abs(x2 - x1); // The difference between the x's
        int deltay = Math.abs(y2 - y1); // The difference between the y's
        int x = x1; // Start x off at the first pixel
        int y = y1; // Start y off at the first pixel
        int xinc1, xinc2, yinc1, yinc2;
        int num, den, numadd, numpixels;

        if (x2 >= x1) { // The x-values are increasing
            xinc1 = 1;
            xinc2 = 1;
        } else { // The x-values are decreasing
            xinc1 = -1;
            xinc2 = -1;
        }

        if (y2 >= y1) { // The y-values are increasing
            yinc1 = 1;
            yinc2 = 1;
        } else { // The y-values are decreasing
            yinc1 = -1;
            yinc2 = -1;
        }

        if (deltax >= deltay) { // There is at least one x-value for every
            // y-value
            xinc1 = 0; // Don't change the x when numerator >= denominator
            yinc2 = 0; // Don't change the y for every iteration
            den = deltax;
            num = deltax / 2;
            numadd = deltay;
            numpixels = deltax; // There are more x-values than y-values
        } else { // There is at least one y-value for every x-value
            xinc2 = 0; // Don't change the x for every iteration
            yinc1 = 0; // Don't change the y when numerator >= denominator
            den = deltay;
            num = deltay / 2;
            numadd = deltax;
            numpixels = deltay; // There are more y-values than x-values
        }

        for (int curpixel = 0; curpixel <= numpixels; curpixel++) {
            setPixel(opcode, x, y, color); // Draw the current pixel
            num += numadd; // Increase the numerator by the top of the fraction
            if (num >= den) { // Check if numerator >= denominator
                num -= den; // Calculate the new numerator value
                x += xinc1; // Change the x as appropriate
                y += yinc1; // Change the y as appropriate
            }
            x += xinc2; // Change the x as appropriate
            y += yinc2; // Change the y as appropriate
        }

        int x_min = x1 < x2 ? x1 : x2;
        int x_max = x1 > x2 ? x1 : x2;
        int y_min = y1 < y2 ? y1 : y2;
        int y_max = y1 > y2 ? y1 : y2;
        // pinto de nuevo
        this.repaintAll(x_min, y_min, x_max - x_min + 1, y_max - y_min + 1);
    }

    /**
     * Helper function for drawLine, draws a horizontal or vertical line using a
     * much faster method than used for diagonal lines
     *
     * @param x1 x coordinate of start point of line
     * @param y1 y coordinate of start point of line
     * @param x2 x coordinate of end point of line
     * @param y2 y coordinate of end point of line
     * @param color colour of line
     * @param opcode Operation code defining operation to perform on pixels
     * within the line
     */
    public void drawLineVerticalHorizontal(int x1, int y1, int x2, int y2, int color, int opcode) {
        int pbackstore;
        int i;
        // only vertical or horizontal lines
        if (y1 == y2) { // HORIZONTAL
            if (y1 >= this.top && y1 <= this.bottom) { // visible
                if (x2 > x1) { // x inc, y1=y2
                    if (x1 < this.left) {
                        x1 = this.left;
                    }
                    if (x2 > this.right) {
                        x2 = this.right;
                    }
                    pbackstore = y1 * this.width + x1;
                    for (i = 0; i < x2 - x1; i++) {
                        rop.do_pixel(opcode, ARDP5.wi, x1 + i, y1, color);
                        pbackstore++;
                    }
                    repaint(x1, y1, x2 - x1 + 1, 1);
                    EventWakeUp.getInstance().imageSegmented(x1, y1, ARDP5.wi.getSubimage(x1, y1, x2 - x1 + 1, 1));
                } else { // x dec, y1=y2
                    if (x2 < this.left) {
                        x2 = this.left;
                    }
                    if (x1 > this.right) {
                        x1 = this.right;
                    }
                    pbackstore = y1 * this.width + x1;
                    for (i = 0; i < x1 - x2; i++) {
                        rop.do_pixel(opcode, ARDP5.wi, x2 + i, y1, color);
                        pbackstore--;
                    }
                    repaint(x2, y1, x1 - x2 + 1, 1);
                    EventWakeUp.getInstance().imageSegmented(x2, y1, ARDP5.wi.getSubimage(x2, y1, x1 - x2 + 1, 1));
                }
            }
        } else { // x1==x2 VERTICAL
            if (x1 >= this.left && x1 <= this.right) { // visible
                if (y2 > y1) { // x1=x2, y inc
                    if (y1 < this.top) {
                        y1 = this.top;
                    }
                    if (y2 > this.bottom) {
                        y2 = this.bottom;
                    }
                    pbackstore = y1 * this.width + x1;
                    for (i = 0; i < y2 - y1; i++) {
                        rop.do_pixel(opcode, ARDP5.wi, x1, y1 + i, color);
                        pbackstore += this.width;
                    }
                    repaint(x1, y1, 1, y2 - y1 + 1);
                    EventWakeUp.getInstance().imageSegmented(x1, y1, ARDP5.wi.getSubimage(x1, y1, 1, y2 - y1 + 1));
                } else { // x1=x2, y dec
                    if (y2 < this.top) {
                        y2 = this.top;
                    }
                    if (y1 > this.bottom) {
                        y1 = this.bottom;
                    }
                    pbackstore = y1 * this.width + x1;
                    for (i = 0; i < y1 - y2; i++) {
                        rop.do_pixel(opcode, ARDP5.wi, x1, y2 + i, color);
                        pbackstore -= this.width;
                    }
                    repaint(x1, y2, 1, y1 - y2 + 1);
                    EventWakeUp.getInstance().imageSegmented(x1, y2, ARDP5.wi.getSubimage(x1, y2, 1, y1 - y2 + 1));
                }
            }
        }
    }

    /**
     * Perform an operation on a pixel in the backstore
     *
     * @param opcode ID of operation to perform
     * @param x x coordinate of pixel
     * @param y y coordinate of pixel
     * @param color Colour value to be used in operation
     */
    public void setPixel(int opcode, int x, int y, int color) {
        int Bpp = RDPConnection.conf.Bpp;
        // correction for 24-bit colour
        if (Bpp == 3) {
            color = ((color & 0xFF) << 16) | (color & 0xFF00) | ((color & 0xFF0000) >> 16);
        }
        if ((x < this.left) || (x > this.right) || (y < this.top) || (y > this.bottom)) { // Clip
        } else {
            rop.do_pixel(opcode, ARDP5.wi, x, y, color);
        }
    }

    /**
     * Draw a rectangle to the screen
     *
     * @param rect RectangleOrder defining the rectangle to be drawn
     */
    public void drawRectangleOrder(RectangleOrder rect) {
        fillRectangle(rect.getX(), rect.getY(), rect.getCX(), rect.getCY(), rect.getColor());
    }

    /**
     * Draw a filled rectangle to the screen
     *
     * @param x x coordinate (left) of rectangle
     * @param y y coordinate (top) of rectangle
     * @param cx Width of rectangle
     * @param cy Height of rectangle
     * @param color Colour of rectangle
     */
    public void fillRectangle(int x, int y, int cx, int cy, int color) {
        // clip here instead
        if (x > this.right || y > this.bottom) {
            return; // off screen
        }
        int Bpp = RDPConnection.conf.Bpp;

        // convert to 24-bit colour
        color = Bitmap.convertTo24(color);

        // correction for 24-bit colour
        if (Bpp == 3) {
            color = ((color & 0xFF) << 16) | (color & 0xFF00)
                    | ((color & 0xFF0000) >> 16);
        }

        // Perform standard clipping checks, x-axis
        int clipright = x + cx - 1;
        if (clipright > this.right) {
            clipright = this.right;
        }
        if (x < this.left) {
            x = this.left;
        }
        cx = clipright - x + 1;

        // Perform standard clipping checks, y-axis
        int clipbottom = y + cy - 1;
        if (clipbottom > this.bottom) {
            clipbottom = this.bottom;
        }
        if (y < this.top) {
            y = this.top;
        }
        cy = clipbottom - y + 1;

        // construct rectangle as integer array, filled with color
        int[] rect = new int[cx * cy];
        for (int i = 0; i < rect.length; i++) {
            rect[i] = color;
        }
        // draw rectangle to backstore
        ARDP5.wi.setRGB(x, y, cx, cy, rect, 0, cx);
        this.repaintAll(x, y, cx, cy); // seems to be faster than Graphics.fillRect
        EventWakeUp.getInstance().imageSegmented(x, y, ARDP5.wi.getSubimage(x, y, cx, cy));
    }

    /**
     * Perform a memory blit
     *
     * @param memblt MemBltOrder describing the blit to be performed
     */
    public void drawMemBltOrder(MemBltOrder memblt) {
        int x = memblt.getX();
        int y = memblt.getY();

        if (x > this.right || y > this.bottom) {
            return; // off screen
        }
        int cx = memblt.getCX();
        int cy = memblt.getCY();
        int srcx = memblt.getSrcX();
        int srcy = memblt.getSrcY();

        // Perform standard clipping checks, x-axis
        int clipright = x + cx - 1;
        if (clipright > this.right) {
            clipright = this.right;
        }
        if (x < this.left) {
            x = this.left;
        }
        cx = clipright - x + 1;

        // Perform standard clipping checks, y-axis
        int clipbottom = y + cy - 1;
        if (clipbottom > this.bottom) {
            clipbottom = this.bottom;
        }
        if (y < this.top) {
            y = this.top;
        }
        cy = clipbottom - y + 1;

        srcx += x - memblt.getX();
        srcy += y - memblt.getY();

        try {
            Bitmap bitmap = cache.getBitmap(memblt.getCacheID(), memblt.getCacheIDX());
            rop.do_array(memblt.getOpcode(), ARDP5.wi, this.width, x, y, cx, cy, bitmap.getBitmapData(), bitmap.getWidth(), srcx, srcy);
            EventWakeUp.getInstance().imageSegmented(x, y, ARDP5.wi.getSubimage(x, y, cx, cy));
            this.repaintAll(x, y, cx, cy);
        } catch (RdesktopException e) {
        }
    }

    /**
     * Perform a tri blit on the screen
     *
     * @param triblt TriBltOrder describing the blit
     */
    public void drawTriBltOrder(TriBltOrder triblt) {
        int x = triblt.getX();
        int y = triblt.getY();

        if (x > this.right || y > this.bottom) {
            return; // off screen
        }
        int cx = triblt.getCX();
        int cy = triblt.getCY();
        int srcx = triblt.getSrcX();
        int srcy = triblt.getSrcY();
        int fgcolor = triblt.getForegroundColor();
        int bgcolor = triblt.getBackgroundColor();
        Brush brush = triblt.getBrush();

        // convert to 24-bit colour
        fgcolor = Bitmap.convertTo24(fgcolor);
        bgcolor = Bitmap.convertTo24(bgcolor);

        // Perform standard clipping checks, x-axis
        int clipright = x + cx - 1;
        if (clipright > this.right) {
            clipright = this.right;
        }
        if (x < this.left) {
            x = this.left;
        }
        cx = clipright - x + 1;

        // Perform standard clipping checks, y-axis
        int clipbottom = y + cy - 1;
        if (clipbottom > this.bottom) {
            clipbottom = this.bottom;
        }
        if (y < this.top) {
            y = this.top;
        }
        cy = clipbottom - y + 1;

        try {
            Bitmap bitmap = cache.getBitmap(triblt.getCacheID(), triblt.getCacheIDX());
            switch (triblt.getOpcode()) {
                case 0x69: // PDSxxn
                    rop.do_array(ROP2_XOR, ARDP5.wi, this.width, x, y, cx, cy, bitmap.getBitmapData(), bitmap.getWidth(), srcx, srcy);
                    patBltOrder(ROP2_NXOR, x, y, cx, cy, fgcolor, bgcolor, brush);
                    EventWakeUp.getInstance().imageSegmented(x, y, ARDP5.wi.getSubimage(x, y, cx, cy));
                    break;
                case 0xb8: // PSDPxax
                    patBltOrder(ROP2_XOR, x, y, cx, cy, fgcolor, bgcolor, brush);
                    rop.do_array(ROP2_AND, ARDP5.wi, this.width, x, y, cx, cy, bitmap.getBitmapData(), bitmap.getWidth(), srcx, srcy);
                    patBltOrder(ROP2_XOR, x, y, cx, cy, fgcolor, bgcolor, brush);
                    EventWakeUp.getInstance().imageSegmented(x, y, ARDP5.wi.getSubimage(x, y, cx, cy));
                    break;
                case 0xc0: // PSa
                    rop.do_array(ROP2_COPY, ARDP5.wi, this.width, x, y, cx, cy, bitmap.getBitmapData(), bitmap.getWidth(), srcx, srcy);
                    patBltOrder(ROP2_AND, x, y, cx, cy, fgcolor, bgcolor, brush);
                    EventWakeUp.getInstance().imageSegmented(x, y, ARDP5.wi.getSubimage(x, y, cx, cy));
                    break;
                default:
//                    logger.warn("Unimplemented Triblt opcode:" + triblt.getOpcode());
                    rop.do_array(ROP2_COPY, ARDP5.wi, this.width, x, y, cx, cy, bitmap.getBitmapData(), bitmap.getWidth(), srcx, srcy);
            }
        } catch (RdesktopException e) {
        }
    }

    /**
     * Draw a multi-point set of lines to the screen
     *
     * @param polyline PolyLineOrder describing the set of lines to draw
     */
    public void drawPolyLineOrder(PolyLineOrder polyline) {
        int x = polyline.getX();
        int y = polyline.getY();
        int fgcolor = polyline.getForegroundColor();
        int datasize = polyline.getDataSize();
        byte[] databytes = polyline.getData();
        int lines = polyline.getLines();

        // convert to 24-bit colour
        fgcolor = Bitmap.convertTo24(fgcolor);

        // hack - data as single element byte array so can pass by ref to
        // parse_delta
        // see http://www.rgagnon.com/javadetails/java-0035.html
        int[] data = new int[1];
        data[0] = ((lines - 1) / 4) + 1;
        int flags = 0;
        int index = 0;

        int opcode = polyline.getOpcode() - 1;

        for (int line = 0; (line < lines) && (data[0] < datasize); line++) {
            int xfrom = x;
            int yfrom = y;

            if (line % 4 == 0) {
                flags = databytes[index++];
            }
            if ((flags & 0xc0) == 0) {
                flags |= 0xc0; /* none = both */

            }
            if ((flags & 0x40) != 0) {
                x += parse_delta(databytes, data);
            }
            if ((flags & 0x80) != 0) {
                y += parse_delta(databytes, data);
            }
            drawLine(xfrom, yfrom, x, y, fgcolor, opcode);
            flags <<= 2;
        }
    }

    /**
     * Parse a delta co-ordinate in polyline order form
     *
     * @param buffer
     * @param offset
     * @return
     */
    static int parse_delta(byte[] buffer, int[] offset) {
        int value = buffer[offset[0]++] & 0xff;
        int two_byte = value & 0x80;

        if ((value & 0x40) != 0) /* sign bit */ {
            value |= ~0x3f;
        } else {
            value &= 0x3f;
        }
        if (two_byte != 0) {
            value = (value << 8) | (buffer[offset[0]++] & 0xff);
        }
        return value;
    }

    /**
     * Draw a single glyph to the screen
     *
     * @param mixmode 0 for transparent background, specified colour for
     * background otherwide
     * @param x x coordinate on screen at which to draw glyph
     * @param y y coordinate on screen at which to draw glyph
     * @param cx Width of clipping area for glyph
     * @param cy Height of clipping area for glyph
     * @param data Set of values defining glyph's pattern
     * @param bgcolor Background colour for glyph pattern
     * @param fgcolor Foreground colour for glyph pattern
     */
    public void drawGlyph(int mixmode, int x, int y, int cx, int cy, byte[] data, int bgcolor, int fgcolor) {
        int pdata;
        int index = 0x80;

        int bytes_per_row = (cx - 1) / 8 + 1;
        int newx, newy, newcx, newcy;

        int Bpp = RDPConnection.conf.Bpp;

        // convert to 24-bit colour
        fgcolor = Bitmap.convertTo24(fgcolor);
        bgcolor = Bitmap.convertTo24(bgcolor);

        // correction for 24-bit colour
        if (Bpp == 3) {
            fgcolor = ((fgcolor & 0xFF) << 16) | (fgcolor & 0xFF00) | ((fgcolor & 0xFF0000) >> 16);
            bgcolor = ((bgcolor & 0xFF) << 16) | (bgcolor & 0xFF00) | ((bgcolor & 0xFF0000) >> 16);
        }

        // clip here instead
        if (x > this.right || y > this.bottom) {
            return; // off screen
        }
        int clipright = x + cx - 1;
        if (clipright > this.right) {
            clipright = this.right;
        }
        if (x < this.left) {
            newx = this.left;
        } else {
            newx = x;
        }
        newcx = clipright - x + 1; // not clipright - newx - 1

        int clipbottom = y + cy - 1;
        if (clipbottom > this.bottom) {
            clipbottom = this.bottom;
        }
        if (y < this.top) {
            newy = this.top;
        } else {
            newy = y;
        }

        newcy = clipbottom - newy + 1;

        int pbackstore = (newy * this.width) + x;
        pdata = bytes_per_row * (newy - y); // offset y, but not x

        if (mixmode == MIX_TRANSPARENT) { // FillStippled
            for (int i = 0; i < newcy; i++) {
                for (int j = 0; j < newcx; j++) {
                    if (index == 0) { // next row
                        pdata++;
                        index = 0x80;
                    }
                    if ((data[pdata] & index) != 0) {
                        if ((x + j >= newx) && (newx + j > 0) && (newy + i > 0)) {
                            ARDP5.wi.setRGB(newx + j, newy + i, fgcolor);
                        }
                    }
                    index >>= 1;
                }
                pdata++;
                index = 0x80;
                pbackstore += this.width;
                if (pdata == data.length) {
                    pdata = 0;
                }
            }
        } else { // FillOpaqueStippled
            for (int i = 0; i < newcy; i++) {
                for (int j = 0; j < newcx; j++) {
                    if (index == 0) { // next row
                        pdata++;
                        index = 0x80;
                    }
                    if (x + j >= newx) {
                        if ((x + j > 0) && (y + i > 0)) {
                            if ((data[pdata] & index) != 0) {
                                ARDP5.wi.setRGB(x + j, y + i, fgcolor);
                            } else {
                                ARDP5.wi.setRGB(x + j, y + i, bgcolor);
                            }
                        }
                    }
                    index >>= 1;
                }
                pdata++;
                index = 0x80;
                pbackstore += this.width;
                if (pdata == data.length) {
                    pdata = 0;
                }
            }
        }
        this.repaintAll(newx, newy, newcx, newcy);
        if (newx > 0 && newy > 0 && newcx > 0 && newcy > 0 && newx < ARDP5.wi.getWidth() && newy < ARDP5.wi.getHeight() && newcx < ARDP5.wi.getWidth() && newcy < ARDP5.wi.getHeight()) {
            EventWakeUp.getInstance().imageSegmented(x, y, ARDP5.wi.getSubimage(newx, newy, newcx, newcy));
        }
    }

    /**
     * Retrieve an image from the backstore, as integer pixel information
     *
     * @param x x coordinate of image to retrieve
     * @param y y coordinage of image to retrieve
     * @param cx width of image to retrieve
     * @param cy height of image to retrieve
     * @return Requested area of backstore, as an array of integer pixel colours
     */
    public int[] getImage(int x, int y, int cx, int cy) {
        int[] data = ARDP5.wi.getRGB(x, y, cx, cy, null, 0, cx);
        return data;
    }

    /**
     * Draw an image (from an integer array of colour data) to the backstore,
     * also calls repaint to draw image to canvas
     *
     * @param x x coordinate at which to draw image
     * @param y y coordinate at which to draw image
     * @param cx Width of drawn image (clips, does not scale)
     * @param cy Height of drawn image (clips, does not scale)
     * @param data Image to draw, represented as an array of integer pixel
     * colours
     */
    public void putImage(int x, int y, int cx, int cy, int[] data) {
        ARDP5.wi.setRGBNoConversion(x, y, cx, cy, data, 0, cx);
    }

    /**
     * Create an AWT Cursor object
     *
     * @param x
     * @param y
     * @param w
     * @param h
     * @param andmask
     * @param xormask
     * @param cache_idx
     * @return Created Cursor
     */
    public Cursor createCursor(int x, int y, int w, int h, byte[] andmask, byte[] xormask, int cache_idx) {
        int pxormask = 0;
        int pandmask = 0;
        Point p = new Point(x, y);
        int size = w * h;
        int scanline = w / 8;
        int offset;
        byte[] mask = new byte[size];
        int[] cursor = new int[size];
        int pcursor, pmask;

        offset = size;

        for (int i = 0; i < h; i++) {
            offset -= w;
            pmask = offset;
            for (int j = 0; j < scanline; j++) {
                for (int bit = 0x80; bit > 0; bit >>= 1) {
                    if ((andmask[pandmask] & bit) != 0) {
                        mask[pmask] = 0;
                    } else {
                        mask[pmask] = 1;
                    }
                    pmask++;
                }
                pandmask++;
            }
        }

        offset = size;
        pcursor = 0;

        for (int i = 0; i < h; i++) {
            offset -= w;
            pcursor = offset;
            for (int j = 0; j < w; j++) {
                cursor[pcursor] = ((xormask[pxormask + 2] << 16) & 0x00ff0000)
                        | ((xormask[pxormask + 1] << 8) & 0x0000ff00)
                        | (xormask[pxormask] & 0x000000ff);
                pxormask += 3;
                pcursor++;
            }

        }

        offset = size;
        pmask = 0;
        pcursor = 0;
        pxormask = 0;

        for (int i = 0; i < h; i++) {
            for (int j = 0; j < w; j++) {
                if ((mask[pmask] == 0) && (cursor[pcursor] != 0)) {
                    cursor[pcursor] = ~(cursor[pcursor]);
                    cursor[pcursor] |= 0xff000000;
                } else if ((mask[pmask] == 1) || (cursor[pcursor] != 0)) {
                    cursor[pcursor] |= 0xff000000;
                }
                pcursor++;
                pmask++;
            }
        }
        JPanel jp = new JPanel();
        Image wincursor = jp.createImage(new MemoryImageSource(w, h, cursor, 0, w));
        return createCustomCursor(wincursor, p, "", cache_idx);
    }

    /**
     * Create an AWT Cursor from an image
     *
     * @param wincursor
     * @param p
     * @param s
     * @param cache_idx
     * @return Generated Cursor object
     */
    protected Cursor createCustomCursor(Image wincursor, Point p, String s, int cache_idx) {
        if (cache_idx == 1) {
            return Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR);
        }
        return Cursor.getDefaultCursor();
    }

}
TOP

Related Classes of com.alssoftrd.utils.ManageBitmaps

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.