private static int[] ComputeReordering(sbyte[] levels)
{
int lineLength = levels.Length;
int[] result = new int[lineLength];
// initialize order
for (int i = 0; i < lineLength; ++i) {
result[i] = i;
}
// locate highest level found on line.
// Note the rules say text, but no reordering across line bounds is performed,
// so this is sufficient.
sbyte highestLevel = 0;
sbyte lowestOddLevel = 63;
for (int i = 0; i < lineLength; ++i) {
sbyte level = levels[i];
if (level > highestLevel) {
highestLevel = level;
}
if (((level & 1) != 0) && level < lowestOddLevel) {
lowestOddLevel = level;
}
}
for (int level = highestLevel; level >= lowestOddLevel; --level) {
for (int i = 0; i < lineLength; ++i) {
if (levels[i] >= level) {
// find range of text at or above this level
int start = i;
int limit = i + 1;
while (limit < lineLength && levels[limit] >= level) {
++limit;
}
// reverse run
for (int j = start, k = limit - 1; j < k; ++j, --k) {
int temp = result[j];
result[j] = result[k];
result[k] = temp;
}
// skip to end of level run
i = limit;
}
}
}
return result;
}