void UpdateCache(ref CachedRenderString cache, string fontName, float size, string text, bool underline, TextAlignment alignment) { if (cache == null) { cache = new DirectWriteCachedText() { FontName = fontName, FontSize = size, Text = text, Underline = underline, Alignment = alignment }; } if (cache is not DirectWriteCachedText pc) { throw new ArgumentException("cache"); } if (pc.quads == null || pc.Update(fontName, text, size, underline, alignment)) { using (var layout = new TextLayout(dwFactory, text, GetFormat(fontName, ConvertSize(size)), float.MaxValue, float.MaxValue)) { layout.TextAlignment = CastAlignment(alignment); layout.SetDrawingEffect(new ColorDrawingEffect(Color4.White, new TextShadow()), new TextRange(0, text.Length)); layout.Draw(Renderer, 0, 0); pc.quads = Renderer.Quads.ToArray(); Renderer.Quads = new List <DrawQuad>(); var metrics = layout.Metrics; pc.size = new Point((int)metrics.WidthIncludingTrailingWhitespace, (int)metrics.Height); } } }
public async Task TextLayout_Basic() { // Skip test on OSX: text rendering is subtly different. if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { return; } var t = new TextLayout( "Avalonia!", new Typeface(TestFontFamily), 24, Brushes.Black); var target = new Border { Width = 200, Height = 200, Background = Brushes.White, Child = new DrawnControl(c => { var textRect = t.Bounds; var bounds = new Rect(0, 0, 200, 200); var rect = bounds.CenterRect(textRect); c.DrawRectangle(Brushes.Yellow, null, rect); t.Draw(c, rect.Position); }), }; await RenderToFile(target); CompareImages(); }
public void Draw() { if (rectEnabled) { renderer.brush2d.Color = rectColor; renderer.rtv2d.FillRectangle(rect, renderer.brush2d); } float x = hookViewport ? pos.X + renderer.GetViewport.X : pos.X; float y = hookViewport ? pos.Y + renderer.GetViewport.Y : pos.Y; renderer.brush2d.Color = color; if (renderer.msgToSurf[OSDMessage.Type.Subtitles] == name) { y -= renderer.SubsPosition; //renderer.rtv2d.DrawTextLayout(new RawVector2(x, y), layout, renderer.brush2d); try { // Draw outline layout.Draw(renderer.outlineRenderer, x, y); } catch (Exception) { // Fallback in failure (will happen if custom effect were applied) renderer.rtv2d.DrawTextLayout(new RawVector2(x, y), layout, renderer.brush2d); } } else { renderer.rtv2d.DrawTextLayout(new RawVector2(x, y), layout, renderer.brush2d); } }
public void Draw() { if (rectEnabled) { renderer.brush2d.Color = rectColor; renderer.rtv2d.FillRectangle(rect, renderer.brush2d); } float x = hookViewport ? pos.X + renderer.GetViewport.X : pos.X; float y = hookViewport ? pos.Y + renderer.GetViewport.Y : pos.Y; renderer.brush2d.Color = color; // Outline: For better performance maybe should create new fonts with outline if (renderer.msgToSurf[OSDMessage.Type.Subtitles] == name) { y -= renderer.SubsPosition; renderer.rtv2d.DrawTextLayout(new RawVector2(x, y), layout, renderer.brush2d); layout.Draw(renderer.outlineRenderer, x, y); } else { renderer.rtv2d.DrawTextLayout(new RawVector2(x, y), layout, renderer.brush2d); } }
public override void DrawStringBaseline(string fontName, float size, string text, float x, float y, float start_x, Color4 color, bool underline = false, TextShadow shadow = default) { using (var layout = new TextLayout(dwFactory, text, GetFormat(fontName, ConvertSize(size)), float.MaxValue, float.MaxValue)) { var indent = (x - start_x); if (Math.Abs(indent) > 0.001f) { layout.SetInlineObject(new Indent(indent), new TextRange(0, 0)); } layout.SetDrawingEffect(new ColorDrawingEffect(color, shadow), new TextRange(0, text.Length)); layout.Draw(Renderer, 0, 0); foreach (var q in Renderer.Quads) { var d = q.Destination; d.X += (int)start_x; d.Y += (int)y; if (q.Texture == null) { render2d.FillRectangle(d, q.Color); } else { render2d.Draw(q.Texture, q.Source, d, q.Color); } } Renderer.Quads = new List <DrawQuad>(); } }
public static void DrawTextLayout( RenderTarget renderTarget, Vector2 origin, TextLayout textLayout, Brush defaultForegroundBrush, DrawTextOptions options = DrawTextOptions.None) { if (options.HasFlag(DrawTextOptions.Clip)) { renderTarget.PushAxisAlignedClip(new global::SharpDX.RectangleF(origin.X, origin.Y, textLayout.MaxWidth, textLayout.MaxHeight), renderTarget.AntialiasMode); using (var renderer = new CustomBrushTextRenderer(renderTarget, defaultForegroundBrush, options.HasFlag(DrawTextOptions.NoSnap))) textLayout.Draw(renderer, origin.X, origin.Y); renderTarget.PopAxisAlignedClip(); } else { using (var renderer = new CustomBrushTextRenderer(renderTarget, defaultForegroundBrush, options.HasFlag(DrawTextOptions.NoSnap))) textLayout.Draw(renderer, origin.X, origin.Y); } }
public override void Render(DrawingContext context) { var background = Background; if (background != null) { context.FillRectangle(background, new Rect(Bounds.Size)); } var padding = Padding; if (TextLayout != null) { _textWidth = TextLayout.Size.Width; _textHeight = TextLayout.Size.Height; var constraints = Bounds.Deflate(Padding); var constraintsWidth = constraints.Width; //让文字不要在宽度合适的时候滚动 _isConstrained = _textWidth > constraintsWidth + 1; if (_isConstrained & !_waiting) { _animate = true; var tOffset = padding.Left - _offset; _offsets[0] = tOffset; _offsets[1] = tOffset + _textWidth + TextGap; _offsets[2] = tOffset + (_textWidth + TextGap) * 2; foreach (var offset in _offsets) { var nR = new Rect(offset, padding.Top, _textWidth, _textHeight); var nC = new Rect(0, padding.Top, constraintsWidth, constraints.Height); if (nC.Intersects(nR)) { using (context.PushPostTransform(Matrix.CreateTranslation(offset, padding.Top))) //TextLayout.Draw(context, new Point(Padding.Left, Padding.Top)); TextLayout.Draw(context); } } } else { _animate = false; using (context.PushPostTransform(Matrix.CreateTranslation(padding.Left, padding.Top))) //TextLayout.Draw(context, new Point(Padding.Left, Padding.Top)); TextLayout.Draw(context); } } }
private void DrawCharacter(string character, bool stretched, TextLayout layout) { if (!_drawingOutline) { DeviceContext.DrawTextLayout(_baselineOrigin, layout, _whiteBrush); } else { layout.Draw(_outlineRenderer, _baselineOrigin.X, _baselineOrigin.Y); } _widths[_idxCurrent] = Measure(character, layout, stretched); _idxCurrent++; }
public override void Render(DrawingContext context) { var background = Background; if (background != null) { context.FillRectangle(background, new Rect(Bounds.Size)); } var padding = Padding; if (TextLayout != null) { _textWidth = TextLayout.Bounds.Width; _textHeight = TextLayout.Bounds.Height; var constraints = this.Bounds.Deflate(Padding); var constraintsWidth = constraints.Width; _isConstrained = _textWidth >= constraintsWidth; if (_isConstrained & !_waiting) { _animate = true; var tOffset = padding.Left - _offset; _offsets[0] = tOffset; _offsets[1] = tOffset + _textWidth + this.TextGap; _offsets[2] = tOffset + (_textWidth + this.TextGap) * 2; foreach (var offset in _offsets) { var nR = new Rect(offset, padding.Top, _textWidth, _textHeight); var nC = new Rect(0, padding.Top, constraintsWidth, constraints.Height); if (nC.Intersects(nR)) { TextLayout.Draw(context.PlatformImpl, new Point(offset, padding.Top)); } } } else { _animate = false; TextLayout.Draw(context.PlatformImpl, new Point(padding.Left, padding.Top)); } } }
public async Task TextLayout_Rotated() { // Skip test on OSX: text rendering is subtly different. if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { return; } var t = new TextLayout( "Avalonia!", new Typeface(TestFontFamily), 24, Brushes.Black); var target = new Border { Width = 200, Height = 200, Background = Brushes.White, Child = new DrawnControl(c => { var textRect = t.Bounds; var bounds = new Rect(0, 0, 200, 200); var rect = bounds.CenterRect(textRect); var rotate = Matrix.CreateTranslation(-100, -100) * Matrix.CreateRotation(MathUtilities.Deg2Rad(90)) * Matrix.CreateTranslation(100, 100); using var transform = c.PushPreTransform(rotate); c.DrawRectangle(Brushes.Yellow, null, rect); t.Draw(c, rect.Position); }), }; await RenderToFile(target); CompareImages(); }
internal override void Draw() { base.Draw(); lock (Locker) { if (_textLayout == null) { UpdateTextLayout(); } Debug.Assert(_textLayout != null, "_textLayout != null"); if (_textRenderer.OutlineBrush.Opacity > 0) { _textRenderer.Location = RenderRect.Location; _textLayout.Draw(_textRenderer, 0, 0); } else { Renderer.Context2D.DrawTextLayout(RenderRect.Location, _textLayout, _textRenderer.FillBrush, DrawTextOptions.EnableColorFont); } } }
protected override DX11VertexGeometry GetGeom(DX11RenderContext device, int slice) { if (d2dFactory == null) { d2dFactory = new D2DFactory(); dwFactory = new DWriteFactory(SharpDX.DirectWrite.FactoryType.Shared); } TextFormat fmt = new TextFormat(dwFactory, this.FFontInput[slice].Name, FFontSize[slice]); TextLayout tl = new TextLayout(dwFactory, FText[slice], fmt, 0.0f, 32.0f); tl.WordWrapping = WordWrapping.NoWrap; tl.TextAlignment = FHAlignment[slice]; tl.ParagraphAlignment = FVAlignment[slice]; OutlineRenderer renderer = new OutlineRenderer(d2dFactory); Extruder ex = new Extruder(d2dFactory); tl.Draw(renderer, 0.0f, 0.0f); var outlinedGeometry = renderer.GetGeometry(); ex.GetVertices(outlinedGeometry, vertexList, this.FExtrude[slice]); outlinedGeometry.Dispose(); Vector3 min = new Vector3(float.MaxValue); Vector3 max = new Vector3(float.MinValue); for (int i = 0; i < vertexList.Count; i++) { Pos3Norm3VertexSDX pn = vertexList[i]; min.X = pn.Position.X < min.X ? pn.Position.X : min.X; min.Y = pn.Position.Y < min.Y ? pn.Position.Y : min.Y; min.Z = pn.Position.Z < min.Z ? pn.Position.Z : min.Z; max.X = pn.Position.X > max.X ? pn.Position.X : max.X; max.Y = pn.Position.Y > max.Y ? pn.Position.Y : max.Y; max.Z = pn.Position.Z > max.Z ? pn.Position.Z : max.Z; } SlimDX.DataStream ds = new SlimDX.DataStream(vertexList.Count * Pos3Norm3VertexSDX.VertexSize, true, true); ds.Position = 0; for (int i = 0; i < vertexList.Count; i++) { ds.Write(vertexList[i]); } ds.Position = 0; var vbuffer = new SlimDX.Direct3D11.Buffer(device.Device, ds, new SlimDX.Direct3D11.BufferDescription() { BindFlags = SlimDX.Direct3D11.BindFlags.VertexBuffer, CpuAccessFlags = SlimDX.Direct3D11.CpuAccessFlags.None, OptionFlags = SlimDX.Direct3D11.ResourceOptionFlags.None, SizeInBytes = (int)ds.Length, Usage = SlimDX.Direct3D11.ResourceUsage.Default }); ds.Dispose(); DX11VertexGeometry vg = new DX11VertexGeometry(device); vg.InputLayout = Pos3Norm3VertexSDX.Layout; vg.Topology = SlimDX.Direct3D11.PrimitiveTopology.TriangleList; vg.VertexBuffer = vbuffer; vg.VertexSize = Pos3Norm3VertexSDX.VertexSize; vg.VerticesCount = vertexList.Count; vg.HasBoundingBox = true; vg.BoundingBox = new SlimDX.BoundingBox(new SlimDX.Vector3(min.X, min.Y, min.Z), new SlimDX.Vector3(max.X, max.Y, max.Z)); renderer.Dispose(); fmt.Dispose(); tl.Dispose(); return(vg); }
public override void Render() { TextLayout.Draw(textRenderer, AbsolutePosition.X, AbsolutePosition.Y); }
public static DX11VertexGeometry Text3d(DX11RenderContext device, string text, string fontName, float fontSize, float extrude, TextAlignment textAlignment, ParagraphAlignment paragraphAlignment) { //Dictionary<DX11RenderContext, DX11VertexGeometry> deviceDict = null; //if (TextGeometryCache.TryGetValue(text, out deviceDict)) //{ // DX11VertexGeometry geom; // if(deviceDict.TryGetValue(device, out geom)) // { // return geom; // } //} if (d2dFactory == null) { d2dFactory = new D2DFactory(); dwFactory = new DWriteFactory(SharpDX.DirectWrite.FactoryType.Shared); } TextFormat fmt = new TextFormat(dwFactory, fontName, fontSize); TextLayout tl = new TextLayout(dwFactory, text, fmt, 0.0f, .0f); tl.WordWrapping = WordWrapping.NoWrap; tl.TextAlignment = (SharpDX.DirectWrite.TextAlignment)textAlignment; tl.ParagraphAlignment = (SharpDX.DirectWrite.ParagraphAlignment)paragraphAlignment; OutlineRenderer renderer = new OutlineRenderer(d2dFactory); Extruder ex = new Extruder(d2dFactory); tl.Draw(renderer, 0.0f, 0.0f); var geo = renderer.GetGeometry(); var result = ex.GetVertices(geo, extrude).ToArray(); renderer.Dispose(); geo.Dispose(); fmt.Dispose(); tl.Dispose(); Vector3 min = new Vector3(float.MaxValue); Vector3 max = new Vector3(float.MinValue); foreach (var pn in result) { min.X = pn.Position.X < min.X ? pn.Position.X : min.X; min.Y = pn.Position.Y < min.Y ? pn.Position.Y : min.Y; min.Z = pn.Position.Z < min.Z ? pn.Position.Z : min.Z; max.X = pn.Position.X > max.X ? pn.Position.X : max.X; max.Y = pn.Position.Y > max.Y ? pn.Position.Y : max.Y; max.Z = pn.Position.Z > max.Z ? pn.Position.Z : max.Z; } SlimDX.DataStream ds = new SlimDX.DataStream(result.Length * Pos3Norm3VertexSDX.VertexSize, true, true); ds.Position = 0; ds.WriteRange(result); ds.Position = 0; var vbuffer = new SlimDX.Direct3D11.Buffer(device.Device, ds, new SlimDX.Direct3D11.BufferDescription() { BindFlags = SlimDX.Direct3D11.BindFlags.VertexBuffer, CpuAccessFlags = SlimDX.Direct3D11.CpuAccessFlags.None, OptionFlags = SlimDX.Direct3D11.ResourceOptionFlags.None, SizeInBytes = (int)ds.Length, Usage = SlimDX.Direct3D11.ResourceUsage.Default, }); ds.Dispose(); DX11VertexGeometry vg = new DX11VertexGeometry(device); vg.InputLayout = Pos3Norm3VertexSDX.Layout; vg.Topology = SlimDX.Direct3D11.PrimitiveTopology.TriangleList; vg.VertexBuffer = vbuffer; vg.VertexSize = Pos3Norm3VertexSDX.VertexSize; vg.VerticesCount = result.Length; vg.HasBoundingBox = true; vg.BoundingBox = new SlimDX.BoundingBox(new SlimDX.Vector3(min.X, min.Y, min.Z), new SlimDX.Vector3(max.X, max.Y, max.Z)); //if(deviceDict != null) //{ // deviceDict[device] = vg; //} //else //{ // deviceDict = new Dictionary<DX11RenderContext, DX11VertexGeometry>(); // deviceDict[device] = vg; // TextGeometryCache[text] = deviceDict; //} return(vg); }
protected override void OnRender(WindowRenderTarget renderTarget) { PointF origin = new PointF(0, 0); _textLayout.Draw(_customRenderer, origin.X, origin.Y); }
static void Main(string[] args) { mainForm = new RenderForm("Advanced Text rendering demo"); d2dFactory = new D2DFactory(); dwFactory = new DWriteFactory(SharpDX.DirectWrite.FactoryType.Shared); textRenderer = new CustomColorRenderer(); CreateResources(); var bgcolor = new Color4(0.1f, 0.1f, 0.1f, 1.0f); //This is the offset where we start our text layout Vector2 offset = new Vector2(202.0f, 250.0f); textFormat = new TextFormat(dwFactory, "Arial", FontWeight.Regular, FontStyle.Normal, 16.0f); textLayout = new TextLayout(dwFactory, introText, textFormat, 300.0f, 200.0f); //Apply various modifications to text textLayout.SetUnderline(true, new TextRange(0, 5)); textLayout.SetDrawingEffect(greenBrush, new TextRange(10, 20)); textLayout.SetFontSize(24.0f, new TextRange(6, 4)); textLayout.SetFontFamilyName("Comic Sans MS", new TextRange(11, 7)); //Measure full layout var textSize = textLayout.Metrics; fullTextBackground = new RectangleF(textSize.Left + offset.X, textSize.Top + offset.Y, textSize.Width, textSize.Height); //Measure text to apply background to var metrics = textLayout.HitTestTextRange(53, 4, 0.0f, 0.0f)[0]; textRegionRect = new RectangleF(metrics.Left + offset.X, metrics.Top + offset.Y, metrics.Width, metrics.Height); //Assign render target and brush to our custom renderer textRenderer.AssignResources(renderTarget, defaultBrush); RenderLoop.Run(mainForm, () => { renderTarget.BeginDraw(); renderTarget.Clear(bgcolor); renderTarget.FillRectangle(fullTextBackground, backgroundBrush); renderTarget.FillRectangle(textRegionRect, redBrush); textLayout.Draw(textRenderer, offset.X, offset.Y); try { renderTarget.EndDraw(); } catch { CreateResources(); } }); d2dFactory.Dispose(); dwFactory.Dispose(); renderTarget.Dispose(); }