public void DrawBoxModel(TextGeometry textGeometry, Rect rect, StyleRuleSet style) { GetBoxes(rect, style, out var borderBoxRect, out var paddingBoxRect, out var contentBoxRect); this.DrawBackground(style, paddingBoxRect); //Content //Content-box if (contentBoxRect.TopLeft.X < contentBoxRect.TopRight.X)//content should not be visible when contentBoxRect.TopLeft.X > contentBoxRect.TopRight.X { if (textGeometry != null) { //var textSize = style.CalcSize(text); /*HACK Don't check text size because the size calculated by Typography is not accurate. */ /*if (textSize.Height < contentBoxRect.Height && textSize.Width < contentBoxRect.Width)*/ { this.DrawText(textGeometry, contentBoxRect, style); } } } this.DrawBorder(style, borderBoxRect, paddingBoxRect); this.DrawOutline(style, borderBoxRect); this.DrawDebug(paddingBoxRect, contentBoxRect); }
public void DrawTextPrimitive(TextMesh textMesh, TextGeometry textGeometry, Rect rect, StyleRuleSet style, Vector offset) { this.SetTextMesh(textMesh); this.DrawText(textGeometry, rect, style); this.SetTextMesh(null); }
/// <summary> /// 开始绘制 /// </summary> /// <param name="gs"></param> private void A_DrawStartEvent(ActionEventArgs gs) { TextGeometry tg = (gs.Geometry2D as TextGeometry); var md = KernelProperty.MMToPix(tg.FontSize); Vector2D nv = Vector2D.Create(tg.Central.X, tg.Central.Y - md / 2); this.Tip.SetText("|", nv, 0); }
public void DrawOneTextNodeAtPosition() { Node node = new Node(1); var primitive = new TextGeometry("AAA"); node.Geometry = primitive; node.Rect.X = 50; node.Rect.Y = 30; Util.DrawNodeToImage(out var imageRawBytes, node, 150, 60); Util.CheckExpectedImage(imageRawBytes, 150, 60, @"Rendering\images\NodeFacts.Draw.DrawOneTextNodeAtPosition.png"); }
public void DrawOneTextNode() { Node node = new Node(1); var primitive = new TextGeometry("ImGUI立即"); node.Geometry = primitive; node.Rect.X = 1; node.Rect.Y = 1; Util.DrawNodeToImage(out var imageRawBytes, node, 100, 30); Util.CheckExpectedImage(imageRawBytes, 100, 30, @"Rendering\images\NodeFacts.Draw.DrawOneTextNode.png"); }
public void UpdateATextNode() { Node node = new Node(1); var primitive = new TextGeometry("Before"); node.Geometry = primitive; { primitive.Text = "Before"; Util.DrawNodeToImage(out var imageRawBytes, node, 100, 30); Util.CheckExpectedImage(imageRawBytes, 100, 30, @"Rendering\images\NodeFacts.Draw.UpdateATextNode.Before.png"); } { primitive.Text = "After"; Util.DrawNodeToImage(out var imageRawBytes, node, 100, 30); Util.CheckExpectedImage(imageRawBytes, 100, 30, @"Rendering\images\NodeFacts.Draw.UpdateATextNode.After.png"); } }
public void TestSerialization() { var text = new TextGeometry { FontFamily = "Consolas", FontStyle = FontStyle.Normal, FontWeight = FontWeight.Bold, FontDecoration = FontDecoration.Underlined, BaseLineLeft = new Point(2,3), Content = "Hello!", FontHeight = 5, Rotation = 90, }; var writer = new StringWriter(); _serializer.Serialize(writer, text); var reader = new StringReader(writer.ToString()); Assert.AreEqual(text, _serializer.Deserialize(reader)); }
private bool CheckTextPrimitive(TextGeometry geometry, StyleRuleSet style) { do { if (geometry.TextChanged) { geometry.TextChanged = false; break; } double fontSize = style.FontSize; if (!MathEx.AmostEqual(geometry.FontSize, fontSize)) { break; } string fontFamily = style.FontFamily; if (geometry.FontFamily != fontFamily) { break; } FontStyle fontStyle = style.FontStyle; if (geometry.FontStyle != fontStyle) { break; } FontWeight fontWeight = style.FontWeight; if (geometry.FontWeight != fontWeight) { break; } return(false); } while (false); return(true); }
public void DrawTwoTextNode() { var nodes = new List <Node>(); { Node node = new Node(1); nodes.Add(node); var primitive = new TextGeometry("AAA"); node.Geometry = primitive; node.Rect.X = 1; node.Rect.Y = 1; } { Node node = new Node(1); nodes.Add(node); var primitive = new TextGeometry("B"); node.Geometry = primitive; node.Rect.X = 1; node.Rect.Y = 40; } Util.DrawNodesToImage(out var imageRawBytes, nodes, 100, 70); Util.CheckExpectedImage(imageRawBytes, 100, 70, @"Rendering\images\NodeFacts.Draw.DrawTwoTextNode.png"); }
protected override IEnumerable <CGeometry> MeasureOverride( double entireWidth, double remainWidth) { var family = FontFamily; var size = FontSize; var style = FontStyle; var weight = FontWeight; var foreground = Foreground; var background = Background; var underline = IsUnderline; var strikethrough = IsStrikethrough; var infos = new List <TextGeometry>(); var fmt = Measure(Size.Infinity, family, size, style, weight, TextWrapping.Wrap); if (String.IsNullOrEmpty(Text)) { fmt.Text = "Ty"; infos.Add(new TextGeometry( 0, fmt.Bounds.Height, false, this, "", fmt)); return(infos); } string[] txtChips = Regex.Split(Text, "\r\n|\r|\n"); Tuple <string, bool>[] txtChipsWithLineBreak = txtChips.Select((t, i) => Tuple.Create(t, i < txtChips.Length - 1)).ToArray(); foreach (Tuple <string, bool> txtChipEntry in txtChipsWithLineBreak) { string txtChip = txtChipEntry.Item1; bool lineBreak = txtChipEntry.Item2; if (string.IsNullOrEmpty(txtChip)) { // linebreak; fmt.Text = "Ty"; infos.Add(TextGeometry.NewLine(fmt)); continue; } /* * It is hacking-resolution for 'line breaking rules'. * * TODO 後で、英訳する。 * * Avalonia(9.11)のFormattedTextでは、 * 矩形範囲に単一のスタイルで文字描画したときの改行位置しか計算できません。 * * そのため、 既に適当な文字を入力した後に、追加で別の文言を描画しようとした時、 * 以下のどちらの理由で改行が発生したか判断ができません。 * * 理由1.余白が小さすぎるため改行が行われた * 理由2.描画領域が狭く(あるいは単語が長すぎるため)無理やり改行が行われた * * 先頭にスペースを入れて改行位置を計算させることで、 * 理由1でも理由2でも先頭で改行が行われるようにしています。 * (この場合、スペース1文字を追加したために理由1に該当してしまう可能性がありますが、 * スペースの横幅は小さいため、不自然には見えないと期待しています) */ string lineTxt = txtChip; if (entireWidth != remainWidth) { fmt.Text = " " + lineTxt; fmt.Constraint = new Size(remainWidth, Double.PositiveInfinity); FormattedTextLine[] lines = fmt.GetLines().ToArray(); FormattedTextLine firstLine = lines[0]; string firstLineTxt = fmt.Text.Substring(0, firstLine.Length); if (lines.Length == 1) { if (remainWidth < fmt.Bounds.Width) { // 指定条件を無視された場合(横幅が狭すぎる)は強制的に改行 infos.Add(TextGeometry.NewLine(fmt)); remainWidth = entireWidth; } else { // 1行しか無い場合は、余計なスペースを排除して寸法情報生成 fmt.Text = lineTxt; infos.Add(new TextGeometry( fmt.Bounds.Width, fmt.Bounds.Height, lineBreak, this, lineTxt, fmt)); remainWidth -= fmt.Bounds.Width; continue; } } else { int secondLineSep = -1; if (firstLineTxt == " ") { // check exists of CJK character. var secondLineLen = lines[1].Length; var secondLineTxt = lineTxt.Substring(0, secondLineLen); secondLineSep = secondLineTxt.Length - 1; for (; secondLineSep >= 1; --secondLineSep) { if (secondLineTxt[secondLineSep].IsCJK()) { break; } } } if (secondLineSep > 0) { fmt.Text = lineTxt.Substring(0, secondLineSep); infos.Add(new TextGeometry( fmt.Bounds.Width, fmt.Bounds.Height, true, this, fmt.Text, fmt)); remainWidth = entireWidth; lineTxt = lineTxt.Substring(secondLineSep); } else if (firstLineTxt == " ") { infos.Add(TextGeometry.NewLine()); remainWidth = entireWidth; } else { firstLineTxt = firstLineTxt.Substring(1); fmt.Text = firstLineTxt; infos.Add(new TextGeometry( fmt.Bounds.Width, fmt.Bounds.Height, true, this, firstLineTxt, fmt)); remainWidth = entireWidth; lineTxt = lineTxt.Substring(firstLineTxt.Length); } } } fmt.Text = lineTxt; fmt.Constraint = new Size(entireWidth, Double.PositiveInfinity); int lineOffset = 0; FormattedTextLine[] ftlines = fmt.GetLines().ToArray(); for (int idx = 0; idx < ftlines.Length; ++idx) { FormattedTextLine line = ftlines[idx]; string chip = lineTxt.Substring(lineOffset, line.Length); fmt.Text = chip; double txtWid = fmt.Bounds.Width; infos.Add(new TextGeometry( txtWid, line.Height, lineBreak || idx < ftlines.Length - 1, this, chip, fmt)); lineOffset += line.Length; } remainWidth = entireWidth - infos.Last().Width; } return(infos); }
protected override IEnumerable <CGeometry> MeasureOverride( double entireWidth, double remainWidth) { if (Image is null) { if (Task.Status == TaskStatus.RanToCompletion || Task.Status == TaskStatus.Faulted || Task.Status == TaskStatus.Canceled) { Image = Task.IsFaulted ? WhenError : Task.Result ?? WhenError; } else { Image = new WriteableBitmap( new PixelSize(1, 1), new Vector(96, 96), PixelFormat.Rgb565, AlphaFormat.Premul); Thread.MemoryBarrier(); System.Threading.Tasks.Task.Run(() => { Task.Wait(); Image = Task.IsFaulted ? WhenError : Task.Result ?? WhenError; Dispatcher.UIThread.InvokeAsync(RequestMeasure); }); } } double imageWidth = Image.Size.Width; double imageHeight = Image.Size.Height; if (RelativeWidth.HasValue) { var aspect = imageHeight / imageWidth; imageWidth = RelativeWidth.Value * entireWidth; imageHeight = aspect * imageWidth; } if (LayoutWidth.HasValue) { imageWidth = LayoutWidth.Value; } if (LayoutHeight.HasValue) { imageHeight = LayoutHeight.Value; } if (imageWidth > remainWidth) { if (entireWidth != remainWidth) { yield return(TextGeometry.NewLine()); } if (FittingWhenProtrude && imageWidth > entireWidth) { var aspect = imageHeight / imageWidth; imageWidth = entireWidth; imageHeight = aspect * imageWidth; } } yield return(new BitmapGeometry(Image, imageWidth, imageHeight, TextVerticalAlignment)); }
/// <summary> /// Draw a text Geometry and merge the result to the text mesh. /// </summary> /// <param name="geometry"></param> /// <param name="rect"></param> /// <param name="style"></param> public void DrawText(TextGeometry geometry, Rect rect, StyleRuleSet style) { //check if we need to rebuild the glyph data of this text Geometry var needRebuild = this.CheckTextPrimitive(geometry, style); var fontFamily = style.FontFamily; var fontSize = style.FontSize; var fontColor = style.FontColor; //build text mesh if (needRebuild) { geometry.Glyphs.Clear(); geometry.Offsets.Clear(); geometry.FontSize = fontSize; geometry.FontFamily = fontFamily; geometry.FontStyle = style.FontStyle; geometry.FontWeight = style.FontWeight; var fontStretch = FontStretch.Normal; var fontStyle = style.FontStyle; var fontWeight = style.FontWeight; var textAlignment = (TextAlignment)style.Get <int>(GUIStyleName.TextAlignment);//TODO apply text alignment var textContext = new OSImplentation.TypographyTextContext(geometry.Text, fontFamily, fontSize, fontStretch, fontStyle, fontWeight, (int)rect.Size.Width, (int)rect.Size.Height, textAlignment); textContext.Build(rect.Location); geometry.Offsets.AddRange(textContext.GlyphOffsets); foreach (var character in geometry.Text) { Typography.OpenFont.Glyph glyph = OSImplentation.TypographyTextContext.LookUpGlyph(fontFamily, character); Typography.OpenFont.GlyphLoader.Read(glyph, out var polygons, out var bezierSegments); var glyphData = GlyphCache.Default.GetGlyph(character, fontFamily, fontStyle, fontWeight); if (glyphData == null) { glyphData = GlyphCache.Default.AddGlyph(character, fontFamily, fontStyle, fontWeight, polygons, bezierSegments); } Debug.Assert(glyphData != null); geometry.Glyphs.Add(glyphData); } } //FIXME Should each text segment consume a draw call? NO! //add a new draw command DrawCommand cmd = new DrawCommand(); cmd.ClipRect = Rect.Big; cmd.TextureData = null; this.TextMesh.Commands.Add(cmd); var oldIndexBufferCount = this.TextMesh.IndexBuffer.Count; var scale = OSImplentation.TypographyTextContext.GetScale(fontFamily, fontSize); int index = -1; // get glyph data from typeface foreach (var character in geometry.Text) { index++; var glyphData = geometry.Glyphs[index]; Vector glyphOffset = geometry.Offsets[index]; this.TextMesh.Append((Vector)rect.Location + geometry.Offset, glyphData, glyphOffset, scale, fontColor, false); } var newIndexBufferCount = this.TextMesh.IndexBuffer.Count; // Update command var command = this.TextMesh.Commands[this.TextMesh.Commands.Count - 1]; command.ElemCount += newIndexBufferCount - oldIndexBufferCount; this.TextMesh.Commands[this.TextMesh.Commands.Count - 1] = command; }
public void Dispose() { ShapeGeometry?.Dispose(); TextGeometry?.Dispose(); }
/// <summary> /// Initializes a new instance of <see cref="TextBuilder"/> with the provided <see cref="ITextLayoutMeasure"/>. /// </summary> public TextBuilder(ITextLayoutMeasure textLayoutMeasure) { _geometry = new TextGeometry(textLayoutMeasure); }
/// <summary> /// Initializes a new instance of <see cref="TextBuilder"/>. /// </summary> public TextBuilder() { _geometry = new TextGeometry(); }
/// <summary> /// 解析指定的XML对象 /// </summary> /// <param name="messageXML"></param> private void ParseXML(XmlReader xmlReader) { Geometry2D shape = null; switch (xmlReader.Name) { case "ArcGeometry": shape = new ArcGeometry(); break; case "BeamGeometry": shape = new BeamGeometry(); break; case "CircleGeometry": shape = new CircleGeometry(); break; case "CSectionGeometry": shape = new CSectionGeometry(); break; case "EllipseGeometry": shape = new EllipseGeometry(); break; case "FloorGeometry": shape = new FloorGeometry(); break; case "LineGeometry": shape = new LineGeometry(); break; case "MeasureGeometry": shape = new MeasureGeometry(); break; case "MemberGeometry": shape = new MemberGeometry(); break; case "OSBGeometry": shape = new OSBGeometry(); break; case "PointGeometry": shape = new PointGeometry(); break; case "PolygonGeometry": shape = new PolygonGeometry(); break; case "PolylineGeometry": shape = new PolylineGeometry(); break; case "RectangleGeometry": shape = new RectangleGeometry(); break; case "SteelBeamGeometry": shape = new SteelBeamGeometry(); break; case "TextGeometry": shape = new TextGeometry(); break; case "WallGeometry": shape = new WallGeometry(); break; } if (shape != null) { //将信息写入数据流中 shape.ReadXML(xmlReader); //将图形添加都界面上 this.drawingKernel.AddShape(shape); } }