protected override void DrawText(float z) { Rect absRect = GetVisibleTextArea(); Rect clipRect = absRect.GetIntersection(this.PixelRect); SimpleFont textFont = this.Font; // textColors.SetAlpha(EffectiveAlpha); Vector3 drawPos = new Vector3(); drawPos.x = absRect.Left; drawPos.y = absRect.Top; drawPos.z = z; // int debug_count = 0; foreach (TextChunk chunk in textChunks) { // find the intersection of chunks and lines foreach (TextRange line in lines) { if (line.end <= chunk.range.start) // this line comes before the chunk - skip it continue; else if (line.start >= chunk.range.end) // this line comes after the chunk, so we must be done // with the chunk. break; // some portion of this line is in this chunk int start = line.start > chunk.range.start ? line.start : chunk.range.start; int end = line.end > chunk.range.end ? chunk.range.end : line.end; if (end <= start) continue; TextRange range = new TextRange(start, end); PointF pt = font.GetOffset(text, lines, range.start, horzFormat, vertFormat, absRect.Width, absRect.Height, true); drawPos.x = absRect.Left + pt.X; drawPos.y = absRect.Top + pt.Y; DrawText(text, start, end - start, drawPos, clipRect, chunk.style); // debug_count++; } } // log.DebugFormat("Wrote {0} lines", debug_count); }
/// <summary> /// Given a text range for a line with possible trailing whitespace, /// return a text range where the trailing whitespace has been trimmed. /// </summary> /// <param name="range"></param> /// <param name="text"></param> /// <returns></returns> private static TextRange Trim(TextRange range, string text) { int end = range.end; while (end > range.start && Char.IsWhiteSpace(text, end - 1)) end--; range.end = end; return range; }
public static List<TextRange> GetWrappedLines(SimpleFont font, List<TextRange> hardWrappedLines, string text, float width, bool nonSpaceWrap) { List<TextRange> lines = new List<TextRange>(); foreach (TextRange range in hardWrappedLines) { // Does the whole line fit? if (font.GetTextExtent(text, range.start, range.Length) < width) { lines.Add(range); } else { int start = range.start; // loop for adding multiple lines for the one hard-break line while (start < range.end) { float curWidth = 0; TextRange curLine = new TextRange(); curLine.start = start; // loop for adding words to the line while (start < range.end) { int wordEndIndex = 0; int chunkEndIndex = 0; // this method should get words. // bounds.start will be the start of the word // bounds.end will be after the end of the word with whitespace trimmed. // chunkEndIndex is after the end of the word including trailing whitespace. TextUtil.GetWordBounds(text, start, range.end, out wordEndIndex, out chunkEndIndex); float wordWidth = font.GetTextExtent(text, start, wordEndIndex - start); if (curWidth + wordWidth < width) { // include the word curLine.end = wordEndIndex; curWidth += wordWidth; // include the trailing space curWidth += font.GetTextExtent(text, wordEndIndex, chunkEndIndex - wordEndIndex); start = chunkEndIndex; } else if (nonSpaceWrap && start == curLine.start) { // FIXME - the one word didn't fit on this line -- deal with non-space wrap Debug.Assert(false, "Still need to handle lines that don't break"); } else if (start == curLine.start) { // We don't do non-space wrap, but the first word doesn't fit.. // We will have to pretend it does, so that we can make progress. // include the word curLine.end = wordEndIndex; curWidth += wordWidth; // include the trailing space curWidth += font.GetTextExtent(text, wordEndIndex, chunkEndIndex - wordEndIndex); start = chunkEndIndex; } else { // the word doesn't fit on this line, so I'm through with this line curLine.end = start; break; } } lines.Add(curLine); } } } //Trace.TraceInformation("GetWrappedLines():"); //foreach (TextRange range in lines) // Trace.TraceInformation(" '{0}'", text.Substring(range.start, range.end - range.start)); return lines; }
/// <summary> /// Break the text up based on hard line breaks. /// </summary> /// <param name="text"></param> /// <returns></returns> public static List<TextRange> GetLines(string text) { List<TextRange> lines = new List<TextRange>(); int cur = 0; while (cur < text.Length) { TextRange range = new TextRange(); range.start = cur; int eol = text.IndexOf('\n', range.start); if (eol == -1) { range.end = text.Length; cur = text.Length; } else { range.end = eol; cur = eol + 1; } lines.Add(range); } return lines; }
protected float GetTextStartOffset(string text, TextRange line, HorizontalTextFormat format, float width, bool leftToRight) { float baseX = 0; switch (format) { case HorizontalTextFormat.Left: case HorizontalTextFormat.WordWrapLeft: if (!leftToRight) baseX += GetTextExtent(text, line.start, line.Length); break; case HorizontalTextFormat.Right: case HorizontalTextFormat.WordWrapRight: baseX = width; if (leftToRight) baseX -= GetTextExtent(text, line.start, line.Length); break; case HorizontalTextFormat.Centered: case HorizontalTextFormat.WordWrapCentered: if (leftToRight) baseX = (float)Math.Floor((width - GetTextExtent(text, line.start, line.Length)) * 0.5f); else baseX = width - (float)Math.Floor((width - GetTextExtent(text, line.start, line.Length)) * 0.5f); break; default: throw new NotImplementedException(string.Format("Unknown text format option '{0}'", format)); } return baseX; }
public TextChunk(TextRange range, TextStyle style) { this.range = range; this.style = style; }