/// <summary> /// Draws a text /// </summary> /// <param name="text">The text which will be drawn.</param> /// <param name="position">The drawing location on screen.</param> /// <param name="color">A color mask.</param> /// <param name="layerDepth">A depth of the layer of this string.</param> public void DrawString(SpriteFontBase font, string text, Vector2 position, Color color, float layerDepth = 0.0f) { font.DrawText(_renderer, text, position, CrossEngineStuff.MultiplyColor(color, Opacity), layerDepth); }
private void RenderSelection(RenderContext context) { var bounds = ActualBounds; if (string.IsNullOrEmpty(Text) || Selection == null) { return; } var selectStart = Math.Min(SelectStart, SelectEnd); var selectEnd = Math.Max(SelectStart, SelectEnd); if (selectStart >= selectEnd) { return; } var startGlyph = _formattedText.GetGlyphInfoByIndex(selectStart); if (startGlyph == null) { return; } var lineIndex = startGlyph.TextLine.LineIndex; var i = selectStart; while (true) { startGlyph = _formattedText.GetGlyphInfoByIndex(i); var startPosition = GetRenderPositionByIndex(i); if (selectEnd < i + startGlyph.TextLine.Count) { var endPosition = GetRenderPositionByIndex(selectEnd); context.Draw(Selection, new Rectangle(startPosition.X - _internalScrolling.X, startPosition.Y - _internalScrolling.Y, endPosition.X - startPosition.X, CrossEngineStuff.LineSpacing(_formattedText.Font))); break; } context.Draw(Selection, new Rectangle(startPosition.X - _internalScrolling.X, startPosition.Y - _internalScrolling.Y, bounds.Left + startGlyph.TextLine.Size.X - startPosition.X, CrossEngineStuff.LineSpacing(_formattedText.Font))); ++lineIndex; if (lineIndex >= _formattedText.Strings.Length) { break; } i = 0; for (var k = 0; k < lineIndex; ++k) { i += _formattedText.Strings[k].Count; } } }
private void UpdateScrolling() { var p = GetRenderPositionByIndex(CursorPosition); if (p == _lastCursorPosition) { return; } var asScrollViewer = Parent as ScrollViewer; Point sz, maximum; var bounds = ActualBounds; if (asScrollViewer != null) { asScrollViewer.UpdateLayout(); sz = new Point(asScrollViewer.Bounds.Width, asScrollViewer.Bounds.Height); maximum = asScrollViewer.ScrollMaximum; } else { sz = new Point(Bounds.Width, Bounds.Height); maximum = new Point(_formattedText.Size.X + CursorWidth - sz.X, _formattedText.Size.Y - sz.Y); if (maximum.X < 0) { maximum.X = 0; } if (maximum.Y < 0) { maximum.Y = 0; } } if (maximum == Point.Zero) { _internalScrolling = Point.Zero; _lastCursorPosition = p; return; } p.X -= bounds.X; p.Y -= bounds.Y; var lineHeight = CrossEngineStuff.LineSpacing(_formattedText.Font); Point sp; if (asScrollViewer != null) { sp = asScrollViewer.ScrollPosition; } else { sp = _internalScrolling; } if (p.Y < sp.Y) { sp.Y = p.Y; } else if (p.Y + lineHeight > sp.Y + sz.Y) { sp.Y = p.Y + lineHeight - sz.Y; } if (p.X < sp.X) { sp.X = p.X; } else if (p.X + CursorWidth > sp.X + sz.X) { sp.X = p.X + CursorWidth - sz.X; } if (asScrollViewer != null) { asScrollViewer.ScrollPosition = sp; } else { if (sp.X < 0) { sp.X = 0; } if (sp.X > maximum.X) { sp.X = maximum.X; } if (sp.Y < 0) { sp.Y = 0; } if (sp.Y > maximum.Y) { sp.Y = maximum.Y; } _internalScrolling = sp; } _lastCursorPosition = p; }
internal ChunkInfo LayoutRow(int startIndex, int?width, bool parseCommands) { var r = new ChunkInfo { StartIndex = startIndex, LineEnd = true }; if (string.IsNullOrEmpty(_text)) { return(r); } _stringBuilder.Clear(); int? lastBreakPosition = null; Point?lastBreakMeasure = null; for (var i = r.StartIndex; i < _text.Length; ++i) { var c = _text[i]; if (SupportsCommands && c == '\\') { if (i < _text.Length - 2 && _text[i + 1] == 'c' && _text[i + 2] == '{') { // Find end var startPos = i + 3; var j = _text.IndexOf('}', startPos); if (j != -1) { // Found if (i > r.StartIndex) { // Break right here, as next chunk has another color r.LineEnd = false; return(r); } if (parseCommands) { r.Color = _text.Substring(startPos, j - startPos).FromName(); } r.StartIndex = j + 1; i = j; continue; } } } _stringBuilder.Append(c); var sz = Point.Zero; if (c != '\n') { var v = Font.MeasureString(_stringBuilder); sz = new Point((int)v.X, (int)v.Y); } else { sz = new Point(r.X + NewLineWidth, Math.Max(r.Y, CrossEngineStuff.LineSpacing(_font))); // Break right here ++r.CharsCount; r.X = sz.X; r.Y = sz.Y; break; } if (width != null && sz.X > width.Value) { if (lastBreakPosition != null) { r.CharsCount = lastBreakPosition.Value - r.StartIndex; } if (lastBreakMeasure != null) { r.X = lastBreakMeasure.Value.X; r.Y = lastBreakMeasure.Value.Y; } break; } if (char.IsWhiteSpace(c)) { lastBreakPosition = i + 1; lastBreakMeasure = sz; } ++r.CharsCount; r.X = sz.X; r.Y = sz.Y; } return(r); }
public void Render(RenderContext context) { if (!Visible) { return; } UpdateLayout(); var view = Rectangle.Intersect(context.View, Bounds); if (view.Width == 0 || view.Height == 0) { return; } var batch = context.Batch; var oldScissorRectangle = CrossEngineStuff.GetScissor(); if (ClipToBounds && !MyraEnvironment.DisableClipping) { var newScissorRectangle = Rectangle.Intersect(oldScissorRectangle, view); if (newScissorRectangle.IsEmpty) { return; } context.Flush(); CrossEngineStuff.SetScissor(newScissorRectangle); } var oldOpacity = context.Opacity; context.Opacity *= Opacity; // Background var background = GetCurrentBackground(); if (background != null) { context.Draw(background, Bounds); } var oldView = context.View; context.View = view; InternalRender(context); context.View = oldView; // Border var border = GetCurrentBorder(); if (border != null) { context.Draw(border, Bounds); } if (MyraEnvironment.DrawWidgetsFrames) { batch.DrawRectangle(Bounds, Color.LightGreen); } if (MyraEnvironment.DrawKeyboardFocusedWidgetFrame && IsKeyboardFocused) { batch.DrawRectangle(Bounds, Color.Red); } if (MyraEnvironment.DrawMouseWheelFocusedWidgetFrame && IsMouseWheelFocused) { batch.DrawRectangle(Bounds, Color.Yellow); } if (ClipToBounds && !MyraEnvironment.DisableClipping) { context.Flush(); CrossEngineStuff.SetScissor(oldScissorRectangle); } context.Opacity = oldOpacity; }
public void Render(RenderContext context) { if (!Visible) { return; } UpdateLayout(); var view = Rectangle.Intersect(context.View, Bounds); if (view.Width == 0 || view.Height == 0) { return; } var batch = context.Batch; var oldScissorRectangle = CrossEngineStuff.GetScissor(); if (ClipToBounds && !MyraEnvironment.DisableClipping) { var newScissorRectangle = Rectangle.Intersect(oldScissorRectangle, view); if (newScissorRectangle.IsEmpty) { return; } context.Flush(); CrossEngineStuff.SetScissor(newScissorRectangle); } var oldOpacity = context.Opacity; var oldView = context.View; context.Opacity *= Opacity; context.View = view; BeforeRender?.Invoke(context); // Background var background = GetCurrentBackground(); if (background != null) { context.Draw(background, BackgroundBounds); } // Borders var border = GetCurrentBorder(); if (border != null) { var borderBounds = BorderBounds; if (BorderThickness.Left > 0) { context.Draw(border, new Rectangle(borderBounds.X, borderBounds.Y, BorderThickness.Left, borderBounds.Height)); } if (BorderThickness.Top > 0) { context.Draw(border, new Rectangle(borderBounds.X, borderBounds.Y, borderBounds.Width, BorderThickness.Top)); } if (BorderThickness.Right > 0) { context.Draw(border, new Rectangle(borderBounds.Right - BorderThickness.Right, borderBounds.Y, BorderThickness.Right, borderBounds.Height)); } if (BorderThickness.Bottom > 0) { context.Draw(border, new Rectangle(borderBounds.X, borderBounds.Bottom - BorderThickness.Bottom, borderBounds.Width, BorderThickness.Bottom)); } } InternalRender(context); AfterRender?.Invoke(context); // Restore context settings context.View = oldView; context.Opacity = oldOpacity; // Optional debug rendering if (MyraEnvironment.DrawWidgetsFrames) { batch.DrawRectangle(Bounds, Color.LightGreen); } if (MyraEnvironment.DrawKeyboardFocusedWidgetFrame && IsKeyboardFocused) { batch.DrawRectangle(Bounds, Color.Red); } if (MyraEnvironment.DrawMouseWheelFocusedWidgetFrame && IsMouseWheelFocused) { batch.DrawRectangle(Bounds, Color.Yellow); } if (ClipToBounds && !MyraEnvironment.DisableClipping) { // Restore scissor context.Flush(); CrossEngineStuff.SetScissor(oldScissorRectangle); } }
public override void InternalRender(RenderContext context) { if (_formattedText.Font == null) { return; } var bounds = ActualBounds; if (Selection != null && !string.IsNullOrEmpty(Text)) { var selectStart = Math.Min(SelectStart, SelectEnd); var selectEnd = Math.Max(SelectStart, SelectEnd); if (selectStart < selectEnd) { // Debug.WriteLine("{0} - {1}", selectStart, selectEnd); var startGlyph = _formattedText.GetGlyphInfoByIndex(selectStart); var lineIndex = startGlyph.TextLine.LineIndex; var i = selectStart; while (true) { startGlyph = _formattedText.GetGlyphInfoByIndex(i); var startPosition = GetRenderPositionByIndex(i); if (selectEnd < i + startGlyph.TextLine.Count) { var endPosition = GetRenderPositionByIndex(selectEnd); context.Draw(Selection, new Rectangle(startPosition.X - _internalScrolling.X, startPosition.Y - _internalScrolling.Y, endPosition.X - startPosition.X, CrossEngineStuff.LineSpacing(_formattedText.Font))); break; } context.Draw(Selection, new Rectangle(startPosition.X - _internalScrolling.X, startPosition.Y - _internalScrolling.Y, bounds.Left + startGlyph.TextLine.Size.X - startPosition.X, CrossEngineStuff.LineSpacing(_formattedText.Font))); ++lineIndex; if (lineIndex >= _formattedText.Strings.Length) { break; } i = 0; for (var k = 0; k < lineIndex; ++k) { i += _formattedText.Strings[k].Count; } } } } var textColor = TextColor; if (!Enabled && DisabledTextColor != null) { textColor = DisabledTextColor.Value; } else if (IsKeyboardFocused && FocusedTextColor != null) { textColor = FocusedTextColor.Value; } var centeredBounds = LayoutUtils.Align(new Point(bounds.Width, bounds.Height), _formattedText.Size, HorizontalAlignment.Left, TextVerticalAlignment); centeredBounds.Offset(bounds.Location); var p = new Point(centeredBounds.Location.X - _internalScrolling.X, centeredBounds.Location.Y - _internalScrolling.Y); _formattedText.Draw(context.Batch, p, context.View, textColor, context.Opacity); if (!IsKeyboardFocused) { // Skip cursor rendering if the widget doesnt have the focus return; } var now = DateTime.Now; if ((now - _lastBlinkStamp).TotalMilliseconds >= BlinkIntervalInMs) { _cursorOn = !_cursorOn; _lastBlinkStamp = now; } if (Enabled && _cursorOn && Cursor != null) { p = GetRenderPositionByIndex(CursorPosition); p.X -= _internalScrolling.X; p.Y -= _internalScrolling.Y; context.Draw(Cursor, new Rectangle(p.X, p.Y, Cursor.Size.X, CrossEngineStuff.LineSpacing(_formattedText.Font))); } }
public override void InternalRender(RenderContext context) { if (_formattedText.Font == null) { return; } var bounds = ActualBounds; RenderSelection(context); var textColor = TextColor; var opacity = context.Opacity; if (HintTextEnabled) { opacity *= 0.5f; } else if (!Enabled && DisabledTextColor != null) { textColor = DisabledTextColor.Value; } else if (IsKeyboardFocused && FocusedTextColor != null) { textColor = FocusedTextColor.Value; } var centeredBounds = LayoutUtils.Align(new Point(bounds.Width, bounds.Height), _formattedText.Size, HorizontalAlignment.Left, TextVerticalAlignment); centeredBounds.Offset(bounds.Location); var p = new Point(centeredBounds.Location.X - _internalScrolling.X, centeredBounds.Location.Y - _internalScrolling.Y); _formattedText.Draw(context.Batch, TextAlign.Left, bounds, context.View, textColor, false, opacity); if (!IsKeyboardFocused) { // Skip cursor rendering if the widget doesnt have the focus return; } var now = DateTime.Now; if ((now - _lastBlinkStamp).TotalMilliseconds >= BlinkIntervalInMs) { _cursorOn = !_cursorOn; _lastBlinkStamp = now; } if (Enabled && _cursorOn && Cursor != null) { p = GetRenderPositionByIndex(CursorPosition); p.X -= _internalScrolling.X; p.Y -= _internalScrolling.Y; context.Draw(Cursor, new Rectangle(p.X, p.Y, Cursor.Size.X, CrossEngineStuff.LineSpacing(_formattedText.Font))); } }
private void RenderSelection(RenderContext context) { var bounds = ActualBounds; if (string.IsNullOrEmpty(Text) || Selection == null) { return; } var selectStart = Math.Min(SelectStart, SelectEnd); var selectEnd = Math.Max(SelectStart, SelectEnd); if (selectStart >= selectEnd) { return; } var startGlyph = _formattedText.GetGlyphInfoByIndex(selectStart); if (startGlyph == null) { return; } var lineIndex = startGlyph.TextChunk.LineIndex; var i = selectStart; var lineHeight = CrossEngineStuff.LineSpacing(_formattedText.Font); while (true) { startGlyph = _formattedText.GetGlyphInfoByIndex(i); var startPosition = GetRenderPositionByIndex(i); var line = _formattedText.Lines[startGlyph.TextChunk.LineIndex]; if (selectEnd < line.TextStartIndex + line.Count) { var endPosition = GetRenderPositionByIndex(selectEnd); context.Draw(Selection, new Rectangle(startPosition.X - _internalScrolling.X, startPosition.Y - _internalScrolling.Y, endPosition.X - startPosition.X, lineHeight)); break; } context.Draw(Selection, new Rectangle(startPosition.X - _internalScrolling.X, startPosition.Y - _internalScrolling.Y, bounds.Left + startGlyph.TextChunk.Size.X - startPosition.X, lineHeight)); ++lineIndex; if (lineIndex >= _formattedText.Lines.Count) { break; } i = _formattedText.Lines[lineIndex].TextStartIndex; } }
public Point Measure(int?width) { var result = Point.Zero; var key = GetMeasureKey(width); if (_measures.TryGetValue(key, out result)) { return(result); } if (!string.IsNullOrEmpty(_text)) { var i = 0; var y = 0; var remainingWidth = width; var lineWidth = 0; while (i < _text.Length) { var chunkInfo = LayoutRow(i, remainingWidth, false); if (i == chunkInfo.StartIndex && chunkInfo.CharsCount == 0) { break; } lineWidth += chunkInfo.X; i = chunkInfo.StartIndex + chunkInfo.CharsCount; if (remainingWidth.HasValue) { remainingWidth = remainingWidth.Value - chunkInfo.X; } if (chunkInfo.LineEnd) { if (lineWidth > result.X) { result.X = lineWidth; } lineWidth = 0; remainingWidth = width; y += chunkInfo.Y; y += _verticalSpacing; } } result.Y = y; } if (result.Y == 0) { result.Y = CrossEngineStuff.LineSpacing(_font); } _measures[key] = result; return(result); }
internal void Update() { if (!_dirty) { return; } if (!string.IsNullOrEmpty(_text)) { var sz = _spriteFont.MeasureString(_text); _size = new Point((int)sz.X, (int)sz.Y); #if MONOGAME var fontGlyphs = _spriteFont.GetGlyphs(); var offset = Vector2.Zero; var firstGlyphOfLine = true; for (var i = 0; i < _text.Length; ++i) { SpriteFont.Glyph g; fontGlyphs.TryGetValue(_text[i], out g); // The first character on a line might have a negative left side bearing. // In this scenario, SpriteBatch/SpriteFont normally offset the text to the right, // so that text does not hang off the left side of its rectangle. if (firstGlyphOfLine) { offset.X = Math.Max(g.LeftSideBearing, 0); firstGlyphOfLine = false; } else { offset.X += _spriteFont.Spacing + g.LeftSideBearing; } var p = offset; p += g.Cropping.Location.ToVector2(); var result = new Rectangle((int)p.X, (int)p.Y, (int)(g.Width + g.RightSideBearing), g.BoundsInTexture.Height); _glyphs[i].Bounds = result; offset.X += g.Width + g.RightSideBearing; } #else var offset = Vector2.Zero; for (var i = 0; i < _text.Length; ++i) { Vector2 v = _spriteFont.MeasureString(_text[i].ToString()); var result = new Rectangle((int)offset.X, (int)offset.Y, (int)v.X, (int)v.Y); _glyphs[i].Bounds = result; offset.X += v.X; } #endif } else { _size = new Point(0, CrossEngineStuff.LineSpacing(_spriteFont)); } _dirty = false; }
internal TextEditRow LayoutRow(int startIndex, int?width) { var r = new TextEditRow(); if (string.IsNullOrEmpty(_text)) { return(r); } _stringBuilder.Clear(); int? lastBreakPosition = null; Vector2?lastBreakMeasure = null; for (var i = startIndex; i < _text.Length; ++i) { var c = _displayText[i]; _stringBuilder.Append(c); Vector2 sz = Vector2.Zero; if (c != '\n') { sz = Font.MeasureString(_stringBuilder); } else { sz = new Vector2(r.x1 + NewLineWidth, Math.Max(r.ymax, CrossEngineStuff.LineSpacing(_font))); } if (width != null && c == '\n') { // Break right here ++r.num_chars; r.x1 = sz.X; r.ymax = sz.Y; r.baseline_y_delta = sz.Y; break; } if (width != null && sz.X > width.Value) { if (lastBreakPosition != null) { r.num_chars = lastBreakPosition.Value - startIndex; } if (lastBreakMeasure != null) { r.x1 = lastBreakMeasure.Value.X; r.ymax = lastBreakMeasure.Value.Y; r.baseline_y_delta = lastBreakMeasure.Value.Y; } break; } if (char.IsWhiteSpace(c)) { lastBreakPosition = i + 1; lastBreakMeasure = sz; } ++r.num_chars; r.x1 = sz.X; r.ymax = sz.Y; r.baseline_y_delta = sz.Y; } return(r); }