Subversion Repositories display

Rev

Rev 335 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 * Copyright (C) 2014 Steve Ratcliffe
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 or
 * version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

package test.files;

import uk.me.parabola.imgfmt.app.ImgFileReader;

/**
 * Read a direction from NOD 1.
 *
 * This is moderately complex. You can have a single direction in a byte or two 4 bit directions.
 * If the first haveNet bit is 1 then you have the 2 4 bit directions, otherwise a single 8 bit.
 *
 * When you read a direction and you have packed 4 bit directions then every other read just uses
 * the other half of the byte that was read and saved before.
 *
 * When the haveNet bit is zero, then the sign bit is used to indicate if the current direction value
 * should be used or a new one. When there are a sequence of haveNet==false arcs, then the first
 * one that also has sign==true will read the next direction.
 *
 * So there may be several haveNet==false,sign==false followed by one or more haveNet==false,sign=true arcs.
 * The first set will all have the same direction and the second set will have the next direction.
 *
 * @author Steve Ratcliffe
 */

public class DirectionReader {

        private final ImgFileReader reader;
        private boolean haveDir;
        private boolean largeDir;
        private byte savedDir;
        private boolean lastSign;

        public DirectionReader(ImgFileReader reader) {
                this.reader = reader;
        }

        public int fetchDirection(boolean first, boolean hasNet, boolean sign) {
                if (first) {
                        haveDir = false;
                        largeDir = !hasNet;
                }

                int direction;
                if (first || hasNet || (sign != lastSign)) {
                        direction = fetchDirection();
                } else {
                        direction = currentDirection(largeDir);
                }

                lastSign = sign;
                return direction;
        }

        private int fetchDirection() {
                if (largeDir) {
                        savedDir = reader.get();
                        return savedDir;
                }
                if (haveDir) {
                        haveDir = false;
                        int dir = (savedDir & 0xf0);
                        return dir;
                } else {
                        savedDir = reader.get();
                        haveDir = true;
                        int dir = (savedDir & 0xf) << 4;
                        return dir;
                }
        }

        private int currentDirection(boolean largeDir) {
                if (largeDir)
                        return savedDir;
                return haveDir ? ((savedDir & 0xf) << 4) : (savedDir & 0xf0);
        }
}