public void DecodeNextScanline()
{
int bits = 0, code = 0, isT = 0;
int current, entry, twoBits;
bool isWhite = true;
int bitOffset = 0;
// Initialize starting of the changing elements array
changingElemSize = 0;
// While scanline not complete
while (bitOffset < w) {
// Mark start of white run.
int runOffset = bitOffset;
while (isWhite && bitOffset < w) {
// White run
current = NextNBits(10);
entry = white[current];
// Get the 3 fields from the entry
isT = entry & 0x0001;
bits = (entry >> 1) & 0x0f;
if (bits == 12) { // Additional Make up code
// Get the next 2 bits
twoBits = NextLesserThan8Bits(2);
// Consolidate the 2 new bits and last 2 bits into 4 bits
current = ((current << 2) & 0x000c) | twoBits;
entry = additionalMakeup[current];
bits = (entry >> 1) & 0x07; // 3 bits 0000 0111
code = (entry >> 4) & 0x0fff; // 12 bits
bitOffset += code; // Skip white run
UpdatePointer(4 - bits);
} else if (bits == 0) { // ERROR
++fails;
// XXX return?
} else if (bits == 15) { // EOL
//
// Instead of throwing an exception, assume that the
// EOL was premature; emit a warning and return.
//
++fails;
return;
} else {
// 11 bits - 0000 0111 1111 1111 = 0x07ff
code = (entry >> 5) & 0x07ff;
bitOffset += code;
UpdatePointer(10 - bits);
if (isT == 0) {
isWhite = false;
currChangingElems[changingElemSize++] = bitOffset;
}
}
}
// Check whether this run completed one width
if (bitOffset == w) {
// If the white run has not been terminated then ensure that
// the next code word is a terminating code for a white run
// of length zero.
int runLength = bitOffset - runOffset;
if (isWhite
&& runLength != 0 && runLength % 64 == 0
&& NextNBits(8) != 0x35) {
++fails;
UpdatePointer(8);
}
break;
}
// Mark start of black run.
runOffset = bitOffset;
while (isWhite == false && bitOffset < w) {
// Black run
current = NextLesserThan8Bits(4);
entry = initBlack[current];
// Get the 3 fields from the entry
isT = entry & 0x0001;
bits = (entry >> 1) & 0x000f;
code = (entry >> 5) & 0x07ff;
if (code == 100) {
current = NextNBits(9);
entry = black[current];
// Get the 3 fields from the entry
isT = entry & 0x0001;
bits = (entry >> 1) & 0x000f;
code = (entry >> 5) & 0x07ff;
if (bits == 12) {
// Additional makeup codes
UpdatePointer(5);
current = NextLesserThan8Bits(4);
entry = additionalMakeup[current];
bits = (entry >> 1) & 0x07; // 3 bits 0000 0111
code = (entry >> 4) & 0x0fff; // 12 bits
SetToBlack(bitOffset, code);
bitOffset += code;
UpdatePointer(4 - bits);
} else if (bits == 15) {
//
// Instead of throwing an exception, assume that the
// EOL was premature; emit a warning and return.
//
++fails;
return;
} else {
SetToBlack(bitOffset, code);
bitOffset += code;
UpdatePointer(9 - bits);
if (isT == 0) {
isWhite = true;
currChangingElems[changingElemSize++] = bitOffset;
}
}
} else if (code == 200) {
// Is a Terminating code
current = NextLesserThan8Bits(2);
entry = twoBitBlack[current];
code = (entry >> 5) & 0x07ff;
bits = (entry >> 1) & 0x0f;
SetToBlack(bitOffset, code);
bitOffset += code;
UpdatePointer(2 - bits);
isWhite = true;
currChangingElems[changingElemSize++] = bitOffset;
} else {
// Is a Terminating code
SetToBlack(bitOffset, code);
bitOffset += code;
UpdatePointer(4 - bits);
isWhite = true;
currChangingElems[changingElemSize++] = bitOffset;
}
}
// Check whether this run completed one width
if (bitOffset == w) {
// If the black run has not been terminated then ensure that
// the next code word is a terminating code for a black run
// of length zero.
int runLength = bitOffset - runOffset;
if (!isWhite
&& runLength != 0 && runLength % 64 == 0
&& NextNBits(10) != 0x37) {
++fails;
UpdatePointer(10);
}
break;
}
}
currChangingElems[changingElemSize++] = bitOffset;
}