private JmeCursor loadCursor(InputStream inStream) throws IOException {

        byte[] icoimages = new byte[0]; // new byte [0] facilitates read()

        if (isAni) {
            CursorLoader.CursorImageData ciDat = new CursorLoader.CursorImageData();
            int numIcons = 0;
            int jiffy = 0;
            // not using those but keeping references for now.
            int steps = 0;
            int width = 0;
            int height = 0;
            int flag = 0; // we don't use that.
            int[] rate = null;
            int[] animSeq = null;
            ArrayList<byte[]> icons;

            DataInput leIn = new LittleEndien(inStream);
            int riff = leIn.readInt();
            if (riff == 0x46464952) { // RIFF
                // read next int (file length), discarding it, we don't need that.
                leIn.readInt();

                int nextInt = 0;

                nextInt = getNext(leIn);
                if (nextInt == 0x4e4f4341) {
                    // We have ACON, we do nothing
//                    System.out.println("We have ACON. Next!");
                    nextInt = getNext(leIn);
                    while (nextInt >= 0) {
                        if (nextInt == 0x68696e61) {
//                            System.out.println("we have 'anih' header");
                            leIn.skipBytes(8); // internal struct length (always 36)
                            numIcons = leIn.readInt();
                            steps = leIn.readInt(); // number of blits for ani cycles
                            width = leIn.readInt();
                            height = leIn.readInt();
                            leIn.skipBytes(8);
                            jiffy = leIn.readInt();
                            flag = leIn.readInt();
                            nextInt = leIn.readInt();
                        } else if (nextInt == 0x65746172) { // found a 'rate' of animation
//                            System.out.println("we have 'rate'.");
                            // Fill rate here.
                            // Rate is synchronous with frames.
                            int length = leIn.readInt();
                            rate = new int[length / 4];
                            for (int i = 0; i < length / 4; i++) {
                                rate[i] = leIn.readInt();
                            }
                            nextInt = leIn.readInt();
                        } else if (nextInt == 0x20716573) { // found a 'seq ' of animation
//                            System.out.println("we have 'seq '.");
                            // Fill animation sequence here
                            int length = leIn.readInt();
                            animSeq = new int[length / 4];
                            for (int i = 0; i < length / 4; i++) {
                                animSeq[i] = leIn.readInt();
                            }
                            nextInt = leIn.readInt();
                        } else if (nextInt == 0x5453494c) { // Found a LIST
//                            System.out.println("we have 'LIST'.");
                            int length = leIn.readInt();
                            nextInt = leIn.readInt();
                            if (nextInt == 0x4f464e49) { // Got an INFO, skip its length
                                // this part consist  of Author, title, etc
                                leIn.skipBytes(length - 4);
//                                System.out.println(" Discarding INFO (skipped = " + skipped + ")");
                                nextInt = leIn.readInt();
                            } else if (nextInt == 0x6d617266) { // found a 'fram' for animation
//                                System.out.println("we have 'fram'.");
                                if (leIn.readInt() == 0x6e6f6369) { // we have 'icon'
                                    // We have an icon and from this point on
                                    // the rest is only icons.
                                    int icoLength = leIn.readInt();
                                    ciDat.numImages = numIcons;
                                    icons = new ArrayList<byte[]>(numIcons);
                                    for (int i = 0; i < numIcons; i++) {
                                        if (i > 0) {
                                            // skip 'icon' header and length as they are
                                            // known already and won't change.
                                            leIn.skipBytes(8);
                                        }
                                        byte[] data = new byte[icoLength];
                                        ((InputStream) leIn).read(data, 0, icoLength);
                                        // in case the header didn't have width or height
                                        // get it from first image.
                                        if (width == 0 || height == 0 && i == 1) {
                                            width = data[6];
                                            height = data[7];
                                        }
                                        icons.add(data);
                                    }
                                    // At this point we have the icons, the rates (either
                                    // through jiffy or rate array), the sequence (if
                                    // applicable) and the ani header info.
                                    // Put things together.
                                    ciDat.assembleCursor(icons, rate, animSeq, jiffy, steps, width, height);
                                    ciDat.completeCursor();
                                    nextInt = leIn.readInt();
                                    // if for some reason there's JUNK (nextInt > -1)
                                    // bail out.
                                    nextInt = nextInt > -1 ? -1 : nextInt;
                                }
                            }
                        }
                    }
                }
                return setJmeCursor(ciDat);

            } else if (riff == 0x58464952) {
                throw new IllegalArgumentException("Big-Endian RIFX is not supported. Sorry.");
            } else {
                throw new IllegalArgumentException("Unknown format.");
            }
        } else if (isCur || isIco) {
            DataInputStream in = new DataInputStream(inStream);
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            byte[] buffer = new byte[16384];
            int bytesRead;
            while ((bytesRead = in.read(buffer)) >= 0) {
                out.write(buffer, 0, bytesRead);
            }
            icoimages = out.toByteArray();
        }

        BufferedImage bi[] = parseICOImage(icoimages);
        int hotSpotX = 0;
        int hotSpotY = 0;
        CursorLoader.CursorImageData cid = new CursorLoader.CursorImageData(bi, 0, hotSpotX, hotSpotY, 0);
        if (isCur) {
            /*
             * Per http://msdn.microsoft.com/en-us/library/ms997538.aspx
             * every .cur file should provide hotspot coordinates.
             */
            hotSpotX = icoimages[FDE_OFFSET + 4]
                    + icoimages[FDE_OFFSET + 5] * 255;
            hotSpotY = icoimages[FDE_OFFSET + 6]
                    + icoimages[FDE_OFFSET + 7] * 255;
            cid.xHotSpot = hotSpotX;
            /*
             * Flip the Y-coordinate.
             */
            cid.yHotSpot = cid.height - 1 - hotSpotY;
        }
        cid.completeCursor();

        return setJmeCursor(cid);
    }
Loads and return a cursor file of one of the following format: .ani, .cur and .ico.
@param info The {@link AssetInfo} describing the cursor file.
@return A JmeCursor representation of the LWJGL's Cursor.
@throws IOException if the file is not found.
jme3-desktop/src/main/java/com/jme3/cursors/plugins/CursorLoader.java