public IEnumerable <TextLine> DivideTextItemsIntoLines(float availableWidth, float availableHeight) { var queue = new Queue <ITextBlockItem>(RenderingQueue); var currentItemIndex = CurrentElementIndex; var currentHeight = 0f; while (queue.Any()) { var line = GetNextLine(); if (!line.Elements.Any()) { yield break; } if (currentHeight + line.LineHeight > availableHeight + Size.Epsilon) { yield break; } currentHeight += line.LineHeight; yield return(line); } TextLine GetNextLine() { var currentWidth = 0f; var currentLineElements = new List <TextLineElement>(); while (true) { if (!queue.Any()) { break; } var currentElement = queue.Peek(); var measurementRequest = new TextMeasurementRequest { Canvas = Canvas, PageContext = PageContext, StartIndex = currentItemIndex, AvailableWidth = availableWidth - currentWidth, IsFirstElementInBlock = currentElement == Items.First(), IsFirstElementInLine = !currentLineElements.Any() }; var measurementResponse = currentElement.Measure(measurementRequest); if (measurementResponse == null) { break; } currentLineElements.Add(new TextLineElement { Item = currentElement, Measurement = measurementResponse }); currentWidth += measurementResponse.Width; currentItemIndex = measurementResponse.NextIndex; if (!measurementResponse.IsLast) { break; } currentItemIndex = 0; queue.Dequeue(); } return(TextLine.From(currentLineElements)); } }