public byte[] GetLevels(int[] linebreaks)
{
// Note that since the previous processing has removed all
// P, S, and WS values from resultTypes, the values referred to
// in these rules are the initial types, before any processing
// has been applied (including processing of overrides).
//
// This example implementation has reinserted explicit format codes
// and BN, in order that the levels array correspond to the
// initial text. Their final placement is not normative.
// These codes are treated like WS in this implementation,
// so they don't interrupt sequences of WS.
ValidateLineBreaks(linebreaks, textLength);
byte[] result = new byte[resultLevels.Length];
for (int k = 0; k < resultLevels.Length; ++k)
result[k] = (byte)resultLevels[k];
// don't worry about linebreaks since if there is a break within
// a series of WS values preceeding S, the linebreak itself
// causes the reset.
for (int i = 0; i < result.Length; ++i) {
sbyte t = initialTypes[i];
if (t == B || t == S) {
// Rule L1, clauses one and two.
result[i] = (byte)paragraphEmbeddingLevel;
// Rule L1, clause three.
for (int j = i - 1; j >= 0; --j) {
if (IsWhitespace(initialTypes[j])) { // including format codes
result[j] = (byte)paragraphEmbeddingLevel;
} else {
break;
}
}
}
}
// Rule L1, clause four.
int start = 0;
for (int i = 0; i < linebreaks.Length; ++i) {
int limit = linebreaks[i];
for (int j = limit - 1; j >= start; --j) {
if (IsWhitespace(initialTypes[j])) { // including format codes
result[j] = (byte)paragraphEmbeddingLevel;
} else {
break;
}
}
start = limit;
}
return result;
}