internal Size MeasureText(GUIState state, string text) { var measureContext = TextMeshUtil.GetTextContext(text, new Size(4096, 4096), this, state); var actualSize = measureContext.Measure(); return(actualSize); }
private static void MoveCaretCallBack(InputTextContext textBox) { var g = Form.current.uiContext; var rect = textBox.Rect; var style = GUIStyle.Basic; ITextContext textContext = TextMeshUtil.GetTextContext(textBox.Text, rect.Size, style, GUIState.Normal); var contentRect = style.GetContentRect(rect); var mousePos = Mouse.Instance.Position; var offsetOfTextRect = contentRect.TopLeft; uint caretIndex; bool isInside; caretIndex = textContext.XyToIndex( (float)(mousePos.X - offsetOfTextRect.X), (float)(mousePos.Y - offsetOfTextRect.Y), out isInside); textBox.SelectIndex = textBox.CaretIndex = caretIndex; }
public static void DrawTextBox(Rect rect, int id, string text, InputTextContext context, GUIState state) { GUIContext g = Form.current.uiContext; WindowManager w = g.WindowManager; Window window = w.CurrentWindow; var d = window.DrawList; var style = GUIStyle.Basic; // draw text, selection and caret var contentRect = style.GetContentRect(rect); d.PushClipRect(contentRect, true); if (g.ActiveId == id) { //Calculate positions and sizes var textContext = TextMeshUtil.GetTextContext(context.Text, rect.Size, style, GUIState.Normal); var offsetOfTextRect = contentRect.TopLeft; float pointX, pointY; float caretHeight; textContext.IndexToXY(context.CaretIndex, false, out pointX, out pointY, out caretHeight); var caretTopPoint = new Point(pointX, pointY); var caretBottomPoint = new Point(pointX, pointY + caretHeight); caretTopPoint.Offset(offsetOfTextRect.X, offsetOfTextRect.Y); caretBottomPoint.Offset(offsetOfTextRect.X, offsetOfTextRect.Y); byte caretAlpha = context.CaretAlpha; // Check if the caret is outside the rect. If so, move the text so the caret is always shown. FIXME this should be done in TextBoxBehaviour var caretX = caretTopPoint.X; if (caretX < contentRect.X || caretX > contentRect.Right) { var offsetX = -(caretX - contentRect.Width - rect.X); contentRect.Offset(offsetX, 0); caretTopPoint.Offset(offsetX, 0); caretBottomPoint.Offset(offsetX, 0); } //Draw text d.DrawText(contentRect, context.Text, style, GUIState.Normal); //Draw selection rect /* * Note: Design * * left bound right bound * ↓ ↓ * | A-----------------+ * | |CONTENT_CONTENT_C| => Line 1 => rect1 * +------B | * |ONTENT_CONTENT_CONTENT_C| => Line 2 (represents inner lines) => rect2 * | C------+ * |ONTENT_CONTENT_CO| => Line 3 => rect3 * +-----------------D * * left bound = l * right bound = r */ if (context.SelectIndex != context.CaretIndex) { float selectPointX, selectPointY; textContext.IndexToXY(context.SelectIndex, false, out selectPointX, out selectPointY, out float dummyHeight); var selectTopPoint = new Point(selectPointX, selectPointY); var selectBottomPoint = new Point(selectPointX, selectPointY + caretHeight); selectTopPoint.Offset(offsetOfTextRect.X, offsetOfTextRect.Y); selectBottomPoint.Offset(offsetOfTextRect.X, offsetOfTextRect.Y); var delta = Math.Abs(selectTopPoint.Y - caretTopPoint.Y); if (delta < caretHeight) // single line { var selectionRect = new Rect( new Point(pointX, pointY), new Point(selectPointX, selectPointY + caretHeight)); selectionRect.Offset(offsetOfTextRect.X, offsetOfTextRect.Y); d.AddRectFilled(selectionRect.Min, selectionRect.Max, Color.Argb(100, 10, 102, 214)); } else//mutiple line { var l = contentRect.Left; var r = contentRect.Right; Point A; Point B; Point C; Point D; if (selectTopPoint.Y > caretTopPoint.Y) { A = caretTopPoint; B = caretBottomPoint; C = selectTopPoint; D = selectBottomPoint; } else { A = selectTopPoint; B = selectBottomPoint; C = caretTopPoint; D = caretBottomPoint; } // Line 1 var rect1 = new Rect(A, r - A.X, caretHeight); d.AddRectFilled(rect1, Color.Argb(100, 10, 102, 214), 12); d.AddRect(rect1.Min, rect1.Max, Color.White, 12, 15, 2); // Line 2 var rect2 = new Rect(new Point(l, B.Y), new Point(r, C.Y)); if (rect2.Height > 0.5 * caretHeight)//TODO There should more a more reasonable way to detect this: If it only has two lines, we don't draw the inner rectangle. { d.AddRectFilled(rect2, Color.Argb(100, 10, 102, 214), 12); d.AddRect(rect2.Min, rect2.Max, Color.White, 12, 15, 2); } // Line 3 var rect3 = new Rect(new Point(l, C.Y), D); d.AddRectFilled(rect3, Color.Argb(100, 10, 102, 214), 12); d.AddRect(rect3.Min, rect3.Max, Color.White, 12, 15, 2); } } //Draw caret d.PathMoveTo(caretTopPoint); d.PathLineTo(caretBottomPoint); d.PathStroke(Color.Argb(caretAlpha, 0, 0, 0), false, 2); } else { d.DrawText(contentRect, text, style, GUIState.Normal); } d.PopClipRect(); // draw the box { d.AddRect(rect.Min, rect.Max, style.GetBorderColor(state)); } }
public static void DrawTextBox(Node node, int id, string text, InputTextContext context, GUIState state) { GUIContext g = Form.current.uiContext; Rect rect = node.Rect; var d = node.RenderOpen(); var style = node.RuleSet; // draw text, selection and caret var contentRect = node.ContentRect; // clip text rendering to content-box //d.PushClip(contentRect); if (g.ActiveId == id) { //Calculate positions and sizes var textContext = TextMeshUtil.GetTextContext(context.Text, rect.Size, style, GUIState.Normal); var offsetOfTextRect = contentRect.TopLeft; float pointX, pointY; float caretHeight; textContext.IndexToXY(context.CaretIndex, false, out pointX, out pointY, out caretHeight); var caretTopPoint = new Point(pointX, pointY); var caretBottomPoint = new Point(pointX, pointY + caretHeight); caretTopPoint.Offset(offsetOfTextRect.X, offsetOfTextRect.Y); caretBottomPoint.Offset(offsetOfTextRect.X, offsetOfTextRect.Y); byte caretAlpha = context.CaretAlpha; // Check if the caret is outside the rect. If so, move the text so the caret is always shown. FIXME this should be done in TextBoxBehaviour var caretX = caretTopPoint.X; if (caretX < contentRect.X || caretX > contentRect.Right) { var offsetX = -(caretX - contentRect.Width - rect.X); contentRect.Offset(offsetX, 0); caretTopPoint.Offset(offsetX, 0); caretBottomPoint.Offset(offsetX, 0); } //Draw text d.DrawText(style, context.Text, contentRect); //Draw selection rect /* * Note: Design * * left bound right bound * ↓ ↓ * | A-----------------+ * | |CONTENT_CONTENT_C| => Line 1 => rect1 * +------B | * |ONTENT_CONTENT_CONTENT_C| => Line 2 (represents inner lines) => rect2 * | C------+ * |ONTENT_CONTENT_CO| => Line 3 => rect3 * +-----------------D * * left bound = l * right bound = r */ if (context.SelectIndex != context.CaretIndex) { float selectPointX, selectPointY; textContext.IndexToXY(context.SelectIndex, false, out selectPointX, out selectPointY, out float dummyHeight); var selectTopPoint = new Point(selectPointX, selectPointY); var selectBottomPoint = new Point(selectPointX, selectPointY + caretHeight); selectTopPoint.Offset(offsetOfTextRect.X, offsetOfTextRect.Y); selectBottomPoint.Offset(offsetOfTextRect.X, offsetOfTextRect.Y); var delta = Math.Abs(selectTopPoint.Y - caretTopPoint.Y); if (delta < caretHeight) // single line { var selectionRect = new Rect( new Point(pointX, pointY), new Point(selectPointX, selectPointY + caretHeight)); selectionRect.Offset(offsetOfTextRect.X, offsetOfTextRect.Y); d.DrawRectangle(new Brush(Color.Argb(100, 10, 102, 214)), null, selectionRect); } else//multiple lines { var l = contentRect.Left; var r = contentRect.Right; Point A; Point B; Point C; Point D; if (selectTopPoint.Y > caretTopPoint.Y) { A = caretTopPoint; B = caretBottomPoint; C = selectTopPoint; D = selectBottomPoint; } else { A = selectTopPoint; B = selectBottomPoint; C = caretTopPoint; D = caretBottomPoint; } // Line 1 var rect1 = new Rect(A, r - A.X, caretHeight); d.DrawRectangle(new Brush(Color.Argb(100, 10, 102, 214)), null, rect1); d.DrawRectangle(null, new Pen(Color.White, 2), rect1); // Line 2 var rect2 = new Rect(new Point(l, B.Y), new Point(r, C.Y)); if (rect2.Height > 0.5 * caretHeight)//TODO There should more a more reasonable way to detect this: If it only has two lines, we don't draw the inner rectangle. { d.DrawRectangle(new Brush(Color.Argb(100, 10, 102, 214)), null, rect2); d.DrawRectangle(null, new Pen(Color.White, 2), rect2); } // Line 3 var rect3 = new Rect(new Point(l, C.Y), D); d.DrawRectangle(new Brush(Color.Argb(100, 10, 102, 214)), null, rect3); d.DrawRectangle(null, new Pen(Color.White, 2), rect3); } } //Draw caret d.DrawLine(new Pen(Color.Argb(caretAlpha, 0, 0, 0), 2), caretTopPoint, caretBottomPoint); } else { d.DrawText(style, text, contentRect); } //d.Pop(); d.Close(); }
/// <summary> /// Append a text mesh to this drawlist /// </summary> public void AddText(Rect rect, string text, GUIStyle style, GUIState state) { if (GetCurrentClipRect().IsEmpty) { return; } AddTextDrawCommand(); var textMesh = this.TextMesh; var oldIndexBufferCount = textMesh.IndexBuffer.Count; string fontFamily = style.FontFamily; double fontSize = style.FontSize; Color fontColor = style.FontColor; // get offset and scale from text layout var scale = OSImplentation.TypographyTextContext.GetScale(fontFamily, fontSize); var textContext = TextMeshUtil.GetTextContext(text, rect.Size, style, state) as OSImplentation.TypographyTextContext; var glyphOffsets = textContext.GlyphOffsets; int index = -1; // get glyph data from typeface FontStyle fontStyle = style.FontStyle; FontWeight fontWeight = style.FontWeight; foreach (var character in text) { index++; if (char.IsWhiteSpace(character)) { continue; } var glyphData = GlyphCache.Default.GetGlyph(character, fontFamily, fontStyle, fontWeight); if (glyphData == null) { Typography.OpenFont.Glyph glyph = OSImplentation.TypographyTextContext.LookUpGlyph(fontFamily, character); var polygons = new List <List <Point> >(); var bezierSegments = new List <(Point, Point, Point)>(); Typography.OpenFont.GlyphLoader.Read(glyph, out polygons, out bezierSegments); GlyphCache.Default.AddGlyph(character, fontFamily, fontStyle, fontWeight, polygons, bezierSegments); glyphData = GlyphCache.Default.GetGlyph(character, fontFamily, fontStyle, fontWeight); Debug.Assert(glyphData != null); } // append to drawlist Vector glyphOffset = glyphOffsets[index]; var positionOffset = (Vector)rect.TopLeft; this.TextMesh.Append(positionOffset, glyphData, glyphOffset, scale, fontColor, false); } var newIndexBufferCount = textMesh.IndexBuffer.Count; // Update command var command = textMesh.Commands[textMesh.Commands.Count - 1]; command.ElemCount += newIndexBufferCount - oldIndexBufferCount; textMesh.Commands[textMesh.Commands.Count - 1] = command; // TODO refactor this }