public override bool Compose(DrawContext dc, Style c, int availWidth, out ItemMetrics im, bool suppressWhitespace, out ITextLayout next) { TextItemMetrics metrics = new TextItemMetrics(this); im = metrics; this.style = c; next = null; // TODO: L: optimise Size sz = dc.Graphics.MeasureText(" "); spaceWidth = sz.Width; height = sz.Height; width = 0; // get the font ascent ascent = c.FontAscent; if (textNode.NodeType == XmlNodeType.SignificantWhitespace) { // special case, simply set to single space width and return width = sz.Width; len = textNode.Value.Length; metrics.CanBreakBefore = true; metrics.CanBreakAfter = true; return(true); } int startSpaceCount = GetStartSpaceCount(); if (startSpaceCount > 0 && suppressWhitespace) { TrimStart(startSpaceCount); startSpaceCount = 0; } if (startSpaceCount > 1) { TrimStart(startSpaceCount - 1); startSpaceCount = 1; } len = startSpaceCount; if (start + len == textNode.Value.Length) { // this is pure whitespace width = sz.Width; return(true); } metrics.CanBreakBefore = startSpaceCount > 0; bool hasMoreContent = true; bool firstWord = true; bool fit = false; int endSpaceCount = 0; int finalWidth = startSpaceCount * spaceWidth; int splitLen = 0; int splitWidth = 0; bool needNewline = false; // bool newline=false; while (hasMoreContent) { int testLen; int tesc; hasMoreContent = IncludeNextWord(out testLen, out tesc); string segString = textNode.Value.Substring(start + len, testLen - len - tesc); string testString = ProcessText(segString); int segWidth = dc.Graphics.MeasureText(testString).Width; int testWidth = finalWidth + segWidth; // string testString=ProcessText(textNode.Value.Substring(start, testLen-tesc)); // int testWidth=dc.Graphics.MeasureText(testString).Width; fit = testWidth < availWidth; if (fit || firstWord) { // either it fits or it has to fit because this is the first word metrics.AddSegment(start + len, testLen - len, segWidth); splitLen = len; len = testLen; splitWidth = finalWidth; endSpaceCount = tesc; finalWidth = testWidth + (endSpaceCount > 0 ? spaceWidth : 0); if (!fit && firstWord) { needNewline = true; } if (!fit || endSpaceCount > 1) { break; } } else { break; } firstWord = false; } // this is handled by custom class // if ( style.Pre && newline ) // bi.ForceBreakAfter=true; Debug.Assert(len > 0, "Must have laid out something!"); // at this point we have these possibilities: // everything fit - fit == true, nothing to do, return true // not everything fit - fit == false, get next, return false // and cannot split - oldLen=-1, return false // and can split - oldLen > 0, ConfigureSplitInfo, return true metrics.CanBreakAfter = endSpaceCount > 0; width = finalWidth; if (splitLen > 0) { canSplit = true; splitIndex = splitLen; splitLeftWidth = splitWidth; splitRightWidth = finalWidth - splitWidth; } if (start + len < textNode.Value.Length) { next = GetNextFragment(); } if (endSpaceCount > 1) { TrimEnd(endSpaceCount - 1); endSpaceCount = 1; } return(!needNewline); }
public override bool Compose(DrawContext dc, Style c, int availWidth, out ItemMetrics im, bool suppressWhitespace, out ITextLayout next) { TextItemMetrics metrics=new TextItemMetrics(this); im=metrics; this.style=c; next=null; // TODO: L: optimise Size sz=dc.Graphics.MeasureText(" "); spaceWidth=sz.Width; height=sz.Height; width=0; // get the font ascent ascent=c.FontAscent; if ( textNode.NodeType == XmlNodeType.SignificantWhitespace ) { // special case, simply set to single space width and return width=sz.Width; len=textNode.Value.Length; metrics.CanBreakBefore=true; metrics.CanBreakAfter=true; return true; } int startSpaceCount=GetStartSpaceCount(); if ( startSpaceCount > 0 && suppressWhitespace ) { TrimStart(startSpaceCount); startSpaceCount=0; } if ( startSpaceCount > 1 ) { TrimStart(startSpaceCount - 1); startSpaceCount=1; } len=startSpaceCount; if ( start+len == textNode.Value.Length ) { // this is pure whitespace width=sz.Width; return true; } metrics.CanBreakBefore=startSpaceCount > 0; bool hasMoreContent=true; bool firstWord=true; bool fit=false; int endSpaceCount=0; int finalWidth=startSpaceCount * spaceWidth; int splitLen=0; int splitWidth=0; bool needNewline=false; // bool newline=false; while ( hasMoreContent ) { int testLen; int tesc; hasMoreContent=IncludeNextWord(out testLen, out tesc); string segString=textNode.Value.Substring(start+len, testLen-len-tesc); string testString=ProcessText(segString); int segWidth=dc.Graphics.MeasureText(testString).Width; int testWidth=finalWidth+segWidth; // string testString=ProcessText(textNode.Value.Substring(start, testLen-tesc)); // int testWidth=dc.Graphics.MeasureText(testString).Width; fit=testWidth < availWidth; if ( fit || firstWord ) { // either it fits or it has to fit because this is the first word metrics.AddSegment(start+len, testLen-len, segWidth); splitLen=len; len=testLen; splitWidth=finalWidth; endSpaceCount=tesc; finalWidth=testWidth + (endSpaceCount > 0 ? spaceWidth : 0); if ( !fit && firstWord ) needNewline=true; if ( !fit || endSpaceCount > 1 ) break; } else break; firstWord=false; } // this is handled by custom class // if ( style.Pre && newline ) // bi.ForceBreakAfter=true; Debug.Assert(len > 0, "Must have laid out something!"); // at this point we have these possibilities: // everything fit - fit == true, nothing to do, return true // not everything fit - fit == false, get next, return false // and cannot split - oldLen=-1, return false // and can split - oldLen > 0, ConfigureSplitInfo, return true metrics.CanBreakAfter=endSpaceCount > 0; width=finalWidth; if ( splitLen > 0 ) { canSplit=true; splitIndex=splitLen; splitLeftWidth=splitWidth; splitRightWidth=finalWidth-splitWidth; } if ( start+len < textNode.Value.Length ) next=GetNextFragment(); if ( endSpaceCount > 1 ) { TrimEnd(endSpaceCount - 1); endSpaceCount=1; } return !needNewline; }