void CreateTextRuns(char[] textBuffer, List <CssRun> runlist, int startIndex, int appendLength) { //this may produce more than 1 css text run if (TextBreaker != null) { //use text break to parse more breakAtList.Clear(); TextBreaker.DoBreak(textBuffer, startIndex, appendLength, breakAtList); int j = breakAtList.Count; int pos = startIndex; for (int i = 0; i < j; ++i) { int sepAt = breakAtList[i]; runlist.Add( CssTextRun.CreateTextRun(pos, sepAt - pos)); pos = sepAt; } breakAtList.Clear(); //TextBreaker.DoBreak(textBuffer, startIndex, appendLength, bounds => //{ // //iterate new split // runlist.Add( // CssTextRun.CreateTextRun(startIndex + bounds.startIndex, bounds.length)); //}); } else { runlist.Add(CssTextRun.CreateTextRun(startIndex, appendLength)); } }
void AddToRunList(char[] textBuffer, List <CssRun> runlist, int startIndex, int appendLength, ref bool needICUSplitter) { if (needICUSplitter) { //use icu splitter //copy text buffer to icu *** var parts = Icu.BreakIterator.GetSplitBoundIter(Icu.BreakIterator.UBreakIteratorType.WORD, icuLocal, textBuffer, startIndex, appendLength); //iterate new split foreach (var bound in parts) { runlist.Add( CssTextRun.CreateTextRun(startIndex + bound.startIndex, bound.length)); } needICUSplitter = false;//reset } else { runlist.Add(CssTextRun.CreateTextRun(startIndex, appendLength)); } }
internal void ParseWordContent( char[] textBuffer, BoxSpec spec, bool isBlock, List <CssRun> runlistOutput, out bool hasSomeCharacter) { bool preserverLine = false; bool preserveWhiteSpace = false; var isblock = spec.CssDisplay == CssDisplay.Block; switch (spec.WhiteSpace) { case CssWhiteSpace.Pre: case CssWhiteSpace.PreWrap: //run and preserve whitespace preserveWhiteSpace = true; preserverLine = true; break; case CssWhiteSpace.PreLine: preserverLine = true; break; } //--------------------------------------- //1. check if has some text //-------------------------------------- hasSomeCharacter = false; //-------------------------------------- //just parse and preserve all whitespace //-------------------------------------- int startIndex = 0; int buffLength = textBuffer.Length; //whitespace and respect newline WordParsingState parsingState = WordParsingState.Init; int appendLength = 0; //-------------------------------------- //some text bool needFinerTextParser = false; for (int i = 0; i < buffLength; ++i) { char c0 = textBuffer[i]; if (c0 == '\r') { continue; } //---------------------------------------- //switch by state switch (parsingState) { case WordParsingState.Init: { if (char.IsWhiteSpace(c0)) { if (c0 == '\n') { if (preserverLine) { runlistOutput.Add(CssTextRun.CreateLineBreak()); appendLength = 0; //clear append length continue; } } parsingState = WordParsingState.Whitespace; //start collect whitespace startIndex = i; appendLength = 1; //start collect whitespace } else if (char.IsPunctuation(c0)) { parsingState = WordParsingState.Init; startIndex = i; appendLength = 1; //add single token runlistOutput.Add(CssTextRun.CreateTextRun(startIndex, appendLength)); } else { //character if (c0 > '~') { needFinerTextParser = true; } parsingState = WordParsingState.CharacterCollecting; startIndex = i; appendLength = 1; //start collect whitespace } } break; case WordParsingState.Whitespace: { if (char.IsWhiteSpace(c0)) { if (c0 == '\n') { if (preserverLine) { runlistOutput.Add(CssTextRun.CreateLineBreak()); appendLength = 0; //clear append length continue; } } if (appendLength == 0) { startIndex = i; } appendLength++; } else { runlistOutput.Add(CssTextRun.CreateWhitespace(preserveWhiteSpace ? appendLength : 1)); if (char.IsPunctuation(c0)) { parsingState = WordParsingState.Init; startIndex = i; appendLength = 1; //add single token runlistOutput.Add(CssTextRun.CreateTextRun(startIndex, appendLength)); } else { if (c0 > '~') { needFinerTextParser = true; } parsingState = WordParsingState.CharacterCollecting; startIndex = i; //start collect appendLength = 1; //start append length } } } break; case WordParsingState.CharacterCollecting: { bool isWhiteSpace; if ((isWhiteSpace = char.IsWhiteSpace(c0)) || char.IsPunctuation(c0)) { //flush collecting token if (needFinerTextParser && TextBreaker != null) { CreateTextRuns(textBuffer, runlistOutput, startIndex, appendLength); needFinerTextParser = false; //reset } else { runlistOutput.Add(CssTextRun.CreateTextRun(startIndex, appendLength)); } hasSomeCharacter = true; startIndex = i; //start collect appendLength = 1; //collect whitespace if (isWhiteSpace) { if (c0 == '\n') { if (preserverLine) { runlistOutput.Add(CssTextRun.CreateLineBreak()); appendLength = 0; //clear append length continue; } } parsingState = WordParsingState.Whitespace; } else { parsingState = WordParsingState.Init; runlistOutput.Add(CssTextRun.CreateTextRun(startIndex, appendLength)); } //---------------------------------------- } else { if (c0 > '~') { needFinerTextParser = true; } if (appendLength == 0) { startIndex = i; } appendLength++; } } break; } } //-------------------- if (appendLength > 0) { switch (parsingState) { case WordParsingState.Whitespace: { //last with whitespace if (preserveWhiteSpace) { runlistOutput.Add(CssTextRun.CreateWhitespace(appendLength)); } else { if (!isblock || (runlistOutput.Count > 0)) { runlistOutput.Add(CssTextRun.CreateWhitespace(1)); } } } break; case WordParsingState.CharacterCollecting: { if (needFinerTextParser && TextBreaker != null) { CreateTextRuns(textBuffer, runlistOutput, startIndex, appendLength); needFinerTextParser = false; //reset } else { runlistOutput.Add(CssTextRun.CreateTextRun(startIndex, appendLength)); } hasSomeCharacter = true; } break; } } }