public PdfLine ProcessLine(float leftX, float width, int alignment, int runDirection, int arabicOptions)
{
ArabicOptions = arabicOptions;
Save();
var isRtl = (runDirection == PdfWriter.RUN_DIRECTION_RTL);
if (CurrentChar >= TotalTextLength)
{
var hasText = GetParagraph(runDirection);
if (!hasText)
{
return(null);
}
if (TotalTextLength == 0)
{
var ar = new ArrayList();
var ckx = new PdfChunk("", DetailChunks[0]);
ar.Add(ckx);
return(new PdfLine(0, 0, 0, alignment, true, ar, isRtl));
}
}
var originalWidth = width;
var lastSplit = -1;
if (CurrentChar != 0)
{
CurrentChar = TrimLeftEx(CurrentChar, TotalTextLength - 1);
}
var oldCurrentChar = CurrentChar;
var uniC = 0;
PdfChunk ck = null;
float charWidth = 0;
PdfChunk lastValidChunk = null;
var splitChar = false;
var surrogate = false;
for (; CurrentChar < TotalTextLength; ++CurrentChar)
{
ck = DetailChunks[CurrentChar];
surrogate = Utilities.IsSurrogatePair(Text, CurrentChar);
if (surrogate)
{
uniC = ck.GetUnicodeEquivalent(Utilities.ConvertToUtf32(Text, CurrentChar));
}
else
{
uniC = ck.GetUnicodeEquivalent(Text[CurrentChar]);
}
if (PdfChunk.NoPrint(uniC))
{
continue;
}
if (surrogate)
{
charWidth = ck.GetCharWidth(uniC);
}
else
{
charWidth = ck.GetCharWidth(Text[CurrentChar]);
}
splitChar = ck.IsExtSplitCharacter(oldCurrentChar, CurrentChar, TotalTextLength, Text, DetailChunks);
if (splitChar && char.IsWhiteSpace((char)uniC))
{
lastSplit = CurrentChar;
}
if (width - charWidth < 0)
{
break;
}
if (splitChar)
{
lastSplit = CurrentChar;
}
width -= charWidth;
lastValidChunk = ck;
if (surrogate)
{
++CurrentChar;
}
if (ck.IsTab())
{
var tab = (object[])ck.GetAttribute(Chunk.TAB);
var tabPosition = (float)tab[1];
var newLine = (bool)tab[2];
if (newLine && tabPosition < originalWidth - width)
{
return(new PdfLine(0, originalWidth, width, alignment, true, CreateArrayOfPdfChunks(oldCurrentChar, CurrentChar - 1), isRtl));
}
DetailChunks[CurrentChar].AdjustLeft(leftX);
width = originalWidth - tabPosition;
}
}
if (lastValidChunk == null)
{
// not even a single char fit; must output the first char
++CurrentChar;
if (surrogate)
{
++CurrentChar;
}
return(new PdfLine(0, originalWidth, 0, alignment, false, CreateArrayOfPdfChunks(CurrentChar - 1, CurrentChar - 1), isRtl));
}
if (CurrentChar >= TotalTextLength)
{
// there was more line than text
return(new PdfLine(0, originalWidth, width, alignment, true, CreateArrayOfPdfChunks(oldCurrentChar, TotalTextLength - 1), isRtl));
}
var newCurrentChar = TrimRightEx(oldCurrentChar, CurrentChar - 1);
if (newCurrentChar < oldCurrentChar)
{
// only WS
return(new PdfLine(0, originalWidth, width, alignment, false, CreateArrayOfPdfChunks(oldCurrentChar, CurrentChar - 1), isRtl));
}
if (newCurrentChar == CurrentChar - 1)
{ // middle of word
var he = (IHyphenationEvent)lastValidChunk.GetAttribute(Chunk.HYPHENATION);
if (he != null)
{
var word = GetWord(oldCurrentChar, newCurrentChar);
if (word != null)
{
var testWidth = width + GetWidth(word[0], CurrentChar - 1);
var pre = he.GetHyphenatedWordPre(new string(Text, word[0], word[1] - word[0]), lastValidChunk.Font.Font, lastValidChunk.Font.Size, testWidth);
var post = he.HyphenatedWordPost;
if (pre.Length > 0)
{
var extra = new PdfChunk(pre, lastValidChunk);
CurrentChar = word[1] - post.Length;
return(new PdfLine(0, originalWidth, testWidth - lastValidChunk.Font.Width(pre), alignment, false, CreateArrayOfPdfChunks(oldCurrentChar, word[0] - 1, extra), isRtl));
}
}
}
}
if (lastSplit == -1 || lastSplit >= newCurrentChar)
{
// no split point or split point ahead of end
return(new PdfLine(0, originalWidth, width + GetWidth(newCurrentChar + 1, CurrentChar - 1), alignment, false, CreateArrayOfPdfChunks(oldCurrentChar, newCurrentChar), isRtl));
}
// standard split
CurrentChar = lastSplit + 1;
newCurrentChar = TrimRightEx(oldCurrentChar, lastSplit);
if (newCurrentChar < oldCurrentChar)
{
// only WS again
newCurrentChar = CurrentChar - 1;
}
return(new PdfLine(0, originalWidth, originalWidth - GetWidth(oldCurrentChar, newCurrentChar), alignment, false, CreateArrayOfPdfChunks(oldCurrentChar, newCurrentChar), isRtl));
}