/// <summary> /// Add something to the line. Return true if we should keep trying to add more. (That is, all of the current thing fit, /// and there is still room left; this routine is not responsible to determine whether there IS anything else to add.) /// If there is not yet anything in the line, this routine MUST add something; otherwise, it is allowed to fail, /// returning false without changing anything. /// </summary> private bool AddSomethingToLine() { m_currentRenderRun = m_renderRuns[m_renderRunIndex]; Box boxToAdd = m_currentRenderRun.Box; if (boxToAdd != null) { // The current run works out to a single box; add it if it fits. Add it anyway if the line // is currently empty. boxToAdd.Layout(m_layoutInfo); if (m_currentLine.FirstBox != null && boxToAdd.Width > m_spaceLeftOnCurrentLine) { return(false); } m_spaceLeftOnCurrentLine -= boxToAdd.Width; AddBoxToLine(boxToAdd, LgEndSegmentType.kestOkayBreak); // always OK to break after non-string. boxToAdd.Container = m_para; m_ichRendered = m_currentRenderRun.RenderLim; m_renderRunIndex++; } else { // current run is not a simple box. Make a text box out of part or all of it, or possibly also subsequent // runs that are not boxes and use the same renderer. IRenderEngine renderer = m_layoutInfo.GetRenderer(m_currentRenderRun.Ws); // If our text source doesn't yet know about the writing system factory, make sure it does. if (m_para.Source.GetWsFactory() == null) { m_para.Source.SetWsFactory(renderer.WritingSystemFactory); } int ichRunLim = GetLimitOfRunWithSameRenderer(renderer, m_renderRunIndex); ILgSegment seg; int dichLim, dxWidth; LgEndSegmentType est; bool mustGetSomeSeg = m_currentLine.FirstBox == null; var twsh = GetNextTwsh(); renderer.FindBreakPoint(m_layoutInfo.VwGraphics, m_para.Source, null, m_ichRendered, ichRunLim, ichRunLim, false, mustGetSomeSeg, m_spaceLeftOnCurrentLine, (mustGetSomeSeg ? LgLineBreak.klbClipBreak : LgLineBreak.klbWordBreak), m_currentLine.FirstBox == null ? LgLineBreak.klbClipBreak : LgLineBreak.klbWordBreak, twsh, false, out seg, out dichLim, out dxWidth, out est, null); if (est == LgEndSegmentType.kestNothingFit && twsh != LgTrailingWsHandling.ktwshAll) { // Nothing of the one we were trying for, try for the other. twsh = GetNextTwsh(); renderer.FindBreakPoint(m_layoutInfo.VwGraphics, m_para.Source, null, m_ichRendered, ichRunLim, ichRunLim, false, mustGetSomeSeg, m_spaceLeftOnCurrentLine, (mustGetSomeSeg ? LgLineBreak.klbClipBreak : LgLineBreak.klbWordBreak), m_currentLine.FirstBox == null ? LgLineBreak.klbClipBreak : LgLineBreak.klbWordBreak, twsh, false, out seg, out dichLim, out dxWidth, out est, null); } switch (est) { case LgEndSegmentType.kestNoMore: case LgEndSegmentType.kestOkayBreak: case LgEndSegmentType.kestMoreLines: case LgEndSegmentType.kestWsBreak: case LgEndSegmentType.kestMoreWhtsp: boxToAdd = new StringBox(m_para.Style, seg, m_ichRendered); boxToAdd.Layout(m_layoutInfo); m_spaceLeftOnCurrentLine -= boxToAdd.Width; m_ichRendered += dichLim; boxToAdd.Container = m_para; // If we get NoMore, we should also check, because it might really be a ws break at the end // of the run. if (est == LgEndSegmentType.kestNoMore && ichRunLim < m_para.Source.Length && ichRunLim > 0 && WsInSource(ichRunLim - 1, m_para.Source) != WsInSource(ichRunLim, m_para.Source)) { // The renderer failed to detect it because not told to look further in the source, // but there is in fact a writing system break. // However, if the next character is a box, we want to treat it as a definitely good break. if (m_para.Source.IsThereABoxAt(ichRunLim)) { est = LgEndSegmentType.kestOkayBreak; } else { est = LgEndSegmentType.kestWsBreak; } } AddBoxToLine(boxToAdd, est); m_renderRunIndex = AdvanceRenderRunIndexToIch(m_ichRendered, m_renderRunIndex); // We want to return true if more could be put on this line. // Of the cases that take this branch, NoMore means no more input at all, so we can't add any more; // MoreLines means this line is full. So for both of those we return false. OkayBreak allows us to try // to put more segments on this line, as does ws break, and moreWhtsp. return(est == LgEndSegmentType.kestOkayBreak || est == LgEndSegmentType.kestWsBreak || est == LgEndSegmentType.kestMoreWhtsp); case LgEndSegmentType.kestNothingFit: Debug.Assert(m_currentLine.FirstBox != null, "Making segment must not return kestNothingFit if line contains nothing"); return(false); //case LgEndSegmentType.kestHardBreak: // if() // return true; default: Debug.Assert(false); break; } } return(true); }