/// <summary> /// Draws the text. /// </summary> /// <param name="p">The position.</param> /// <param name="text">The text.</param> /// <param name="fill">The fill color.</param> /// <param name="fontFamily">The font family.</param> /// <param name="fontSize">Size of the font.</param> /// <param name="fontWeight">The font weight.</param> /// <param name="rotate">The rotation angle.</param> /// <param name="halign">The horizontal alignment.</param> /// <param name="valign">The vertical alignment.</param> /// <param name="maxSize">The maximum size of the text.</param> public void DrawText( ScreenPoint p, string text, OxyColor fill, string fontFamily, double fontSize, double fontWeight, double rotate, OxyPlot.HorizontalAlignment halign, OxyPlot.VerticalAlignment valign, OxySize?maxSize) { var tb = new TextBlock { Text = text, Foreground = new SolidColorBrush(fill.ToColor()) }; // tb.SetValue(TextOptions.TextHintingModeProperty, TextHintingMode.Animated); if (fontFamily != null) { tb.FontFamily = new FontFamily(fontFamily); } if (fontSize > 0) { tb.FontSize = fontSize; } tb.FontWeight = GetFontWeight(fontWeight); tb.Measure(new Size(1000, 1000)); var size = new Size(tb.ActualWidth, tb.ActualHeight); if (maxSize != null) { if (size.Width > maxSize.Value.Width) { size.Width = maxSize.Value.Width; } if (size.Height > maxSize.Value.Height) { size.Height = maxSize.Value.Height; } tb.Clip = new RectangleGeometry { Rect = new Rect(0, 0, size.Width, size.Height) }; } double dx = 0; if (halign == OxyPlot.HorizontalAlignment.Center) { dx = -size.Width / 2; } if (halign == OxyPlot.HorizontalAlignment.Right) { dx = -size.Width; } double dy = 0; if (valign == OxyPlot.VerticalAlignment.Middle) { dy = -size.Height / 2; } if (valign == OxyPlot.VerticalAlignment.Bottom) { dy = -size.Height; } var transform = new TransformGroup(); transform.Children.Add(new TranslateTransform { X = (int)dx, Y = (int)dy }); if (!rotate.Equals(0)) { transform.Children.Add(new RotateTransform { Angle = rotate }); } transform.Children.Add(new TranslateTransform { X = (int)p.X, Y = (int)p.Y }); tb.RenderTransform = transform; this.ApplyTooltip(tb); if (this.clip) { // add a clipping container that is not rotated var c = new Canvas(); c.Children.Add(tb); this.Add(c); } else { this.Add(tb); } }
/// <summary> /// The draw text. /// </summary> /// <param name="p">The p.</param> /// <param name="text">The text.</param> /// <param name="fill">The fill.</param> /// <param name="fontFamily">The font family.</param> /// <param name="fontSize">The font size.</param> /// <param name="fontWeight">The font weight.</param> /// <param name="rotate">The rotate.</param> /// <param name="halign">The horizontal alignment.</param> /// <param name="valign">The vertical alignment.</param> /// <param name="maxSize">The maximum size of the text.</param> public void DrawText( ScreenPoint p, string text, OxyColor fill, string fontFamily, double fontSize, double fontWeight, double rotate, OxyPlot.HorizontalAlignment halign, OxyPlot.VerticalAlignment valign, OxySize?maxSize) { if (fill.IsInvisible() || string.IsNullOrEmpty(text)) { return; } var tb = new TextBlock { Text = text, Foreground = fill.ToBrush() }; // tb.SetValue(TextOptions.TextHintingModeProperty, TextHintingMode.Animated); if (fontFamily != null) { tb.FontFamily = new FontFamily(fontFamily); } if (fontSize > 0) { tb.FontSize = fontSize; } tb.FontWeight = GetFontWeight(fontWeight); tb.Measure(new Size(1000, 1000)); double dx = 0; if (halign == OxyPlot.HorizontalAlignment.Center) { dx = -tb.ActualWidth / 2; } if (halign == OxyPlot.HorizontalAlignment.Right) { dx = -tb.ActualWidth; } double dy = 0; if (valign == OxyPlot.VerticalAlignment.Middle) { dy = -tb.ActualHeight / 2; } if (valign == OxyPlot.VerticalAlignment.Bottom) { dy = -tb.ActualHeight; } var transform = new TransformGroup(); transform.Children.Add(new TranslateTransform { X = (int)dx, Y = (int)dy }); if (!rotate.Equals(0.0)) { transform.Children.Add(new RotateTransform { Angle = rotate }); } transform.Children.Add(new TranslateTransform { X = (int)p.X, Y = (int)p.Y }); tb.RenderTransform = transform; if (this.clip.HasValue) { // add a clipping container that is not rotated var c = new Canvas(); c.Children.Add(tb); this.Add(c); } else { this.Add(tb); } }
/// <inheritdoc/> public override void DrawText(ScreenPoint p, string text, OxyColor fill, string fontFamily = null, double fontSize = 10, double fontWeight = 400, double rotation = 0, OxyPlot.HorizontalAlignment horizontalAlignment = OxyPlot.HorizontalAlignment.Left, OxyPlot.VerticalAlignment verticalAlignment = OxyPlot.VerticalAlignment.Top, OxySize?maxSize = null) { if (text == null || !fill.IsVisible()) { return; } var font = this.GetFontOrThrow(fontFamily, fontSize, this.ToFontStyle(fontWeight)); var actualFontSize = this.NominalFontSizeToPoints(fontSize); var outputX = this.Convert(p.X); var outputY = this.Convert(p.Y); var outputPosition = new PointF(outputX, outputY); var cos = (float)Math.Cos(rotation * Math.PI / 180.0); var sin = (float)Math.Sin(rotation * Math.PI / 180.0); // measure bounds of the whole text (we only need the height) var bounds = this.MeasureTextLoose(text, fontFamily, fontSize, fontWeight); var boundsHeight = this.Convert(bounds.Height); var offsetHeight = new PointF(boundsHeight * -sin, boundsHeight * cos); // determine the font metrids for this font size at 96 DPI var actualDescent = this.Convert(actualFontSize * this.MilliPointsToNominalResolution(font.Descender)); var offsetDescent = new PointF(actualDescent * -sin, actualDescent * cos); var actualLineHeight = this.Convert(actualFontSize * this.MilliPointsToNominalResolution(font.LineHeight)); var offsetLineHeight = new PointF(actualLineHeight * -sin, actualLineHeight * cos); var actualLineGap = this.Convert(actualFontSize * this.MilliPointsToNominalResolution(font.LineGap)); var offsetLineGap = new PointF(actualLineGap * -sin, actualLineGap * cos); // find top of the whole text var deltaY = verticalAlignment switch { OxyPlot.VerticalAlignment.Top => 1.0f, OxyPlot.VerticalAlignment.Middle => 0.5f, OxyPlot.VerticalAlignment.Bottom => 0.0f, _ => throw new ArgumentOutOfRangeException(nameof(verticalAlignment)), }; // this is the top of the top line var topPosition = outputPosition + (offsetHeight * deltaY) - offsetHeight; // need this later var deltaX = horizontalAlignment switch { OxyPlot.HorizontalAlignment.Left => - 0.0f, OxyPlot.HorizontalAlignment.Center => - 0.5f, OxyPlot.HorizontalAlignment.Right => - 1.0f, _ => throw new ArgumentOutOfRangeException(nameof(horizontalAlignment)), }; var lines = StringHelper.SplitLines(text); for (int li = 0; li < lines.Length; li++) { var line = lines[li]; if (string.IsNullOrWhiteSpace(line)) { continue; } // measure bounds of just the line (we only need the width) var lineBounds = this.MeasureTextLoose(line, fontFamily, fontSize, fontWeight); var lineBoundsWidth = this.Convert(lineBounds.Width); var offsetLineWidth = new PointF(lineBoundsWidth * cos, lineBoundsWidth * sin); // find the left baseline position var lineTop = topPosition + (offsetLineGap * li) + (offsetLineHeight * li); var lineBaseLineLeft = lineTop + offsetLineWidth * deltaX + offsetLineHeight + offsetDescent; // this seems to produce consistent and correct results, but we have to rotate it manually, so render it at the origin for simplicity var glyphsAtOrigin = TextBuilder.GenerateGlyphs(line, new PointF(0f, 0f), new RendererOptions(font, this.Dpi, this.Dpi) { HorizontalAlignment = HorizontalAlignment.Left, VerticalAlignment = VerticalAlignment.Bottom, // sit on the line (baseline) ApplyKerning = true, }); // translate and rotate into possition var transform = Matrix3x2Extensions.CreateRotationDegrees((float)rotation); transform.Translation = lineBaseLineLeft; var glyphs = glyphsAtOrigin.Transform(transform); // draw the glyphs this.Target.Mutate(img => { img.Fill(ToRgba32(fill), glyphs); }); } }
public void DrawText(ScreenPoint p, string text, OxyColor fill, string fontFamily = null, double fontSize = 10, double fontWeight = 500, double rotate = 0, OxyPlot.HorizontalAlignment halign = HorizontalAlignment.Left, VerticalAlignment valign = VerticalAlignment.Top, OxySize?maxSize = new OxySize?()) { using (var paint = new Paint()) { paint.AntiAlias = true; paint.TextSize = (float)fontSize; paint.Color = fill.ToColor(); var bounds = new Rect(); paint.GetTextBounds(text, 0, text.Length, bounds); float dx = 0; if (halign == HorizontalAlignment.Center) { dx = -bounds.Width() / 2; } if (halign == HorizontalAlignment.Right) { dx = -bounds.Width(); } float dy = 0; if (valign == VerticalAlignment.Middle) { dy = +bounds.Height() / 2; } if (valign == VerticalAlignment.Top) { dy = bounds.Height(); } canvas.Save(); canvas.Translate(dx, dy); canvas.Rotate((float)rotate); canvas.Translate((float)p.X, (float)p.Y); canvas.DrawText(text, 0, 0, paint); canvas.Restore(); } }
/// <summary> /// Draws text. /// </summary> /// <param name="p">The position.</param> /// <param name="text">The text.</param> /// <param name="fill">The text color.</param> /// <param name="fontFamily">The font family.</param> /// <param name="fontSize">Size of the font (in device independent units, 1/96 inch).</param> /// <param name="fontWeight">The font weight.</param> /// <param name="rotate">The rotation angle.</param> /// <param name="halign">The horizontal alignment.</param> /// <param name="valign">The vertical alignment.</param> /// <param name="maxSize">The maximum size of the text (in device independent units, 1/96 inch).</param> public void DrawText( ScreenPoint p, string text, OxyColor fill, string fontFamily, double fontSize, double fontWeight, double rotate, HorizontalAlignment halign, VerticalAlignment valign, OxySize?maxSize) { var tb = this.CreateAndAdd <TextBlock>(); tb.Text = text; tb.Foreground = this.GetCachedBrush(fill); if (fontFamily != null) { tb.FontFamily = this.GetCachedFontFamily(fontFamily); } if (fontSize > 0) { tb.FontSize = fontSize; } if (fontWeight > 0) { tb.FontWeight = GetFontWeight(fontWeight); } #if !NET35 TextOptions.SetTextFormattingMode(tb, this.TextFormattingMode); #endif double dx = 0; double dy = 0; if (maxSize != null || halign != HorizontalAlignment.Left || valign != VerticalAlignment.Top) { tb.Measure(new Size(1000, 1000)); var size = tb.DesiredSize; if (maxSize != null) { if (size.Width > maxSize.Value.Width + 1e-3) { size.Width = Math.Max(maxSize.Value.Width, 0); } if (size.Height > maxSize.Value.Height + 1e-3) { size.Height = Math.Max(maxSize.Value.Height, 0); } tb.Width = size.Width; tb.Height = size.Height; } if (halign == HorizontalAlignment.Center) { dx = -size.Width / 2; } if (halign == HorizontalAlignment.Right) { dx = -size.Width; } if (valign == VerticalAlignment.Middle) { dy = -size.Height / 2; } if (valign == VerticalAlignment.Bottom) { dy = -size.Height; } } var transform = new TransformGroup(); transform.Children.Add(new TranslateTransform(dx, dy)); if (Math.Abs(rotate) > double.Epsilon) { transform.Children.Add(new RotateTransform(rotate)); } transform.Children.Add(new TranslateTransform(p.X, p.Y)); tb.RenderTransform = transform; if (tb.Clip != null) { tb.Clip.Transform = tb.RenderTransform.Inverse as Transform; } #if !NET35 tb.SetValue(RenderOptions.ClearTypeHintProperty, ClearTypeHint.Enabled); #endif }
/// <summary> /// Draws text. /// </summary> /// <param name="p">The position.</param> /// <param name="text">The text.</param> /// <param name="fill">The text color.</param> /// <param name="fontFamily">The font family.</param> /// <param name="fontSize">Size of the font (in device independent units, 1/96 inch).</param> /// <param name="fontWeight">The font weight.</param> /// <param name="rotate">The rotation angle.</param> /// <param name="halign">The horizontal alignment.</param> /// <param name="valign">The vertical alignment.</param> /// <param name="maxSize">The maximum size of the text (in device independent units, 1/96 inch).</param> public void DrawText( ScreenPoint p, string text, OxyColor fill, string fontFamily, double fontSize, double fontWeight, double rotate, HorizontalAlignment halign, VerticalAlignment valign, OxySize?maxSize) { var tb = CreateAndAdd <TextBlock>(); tb.Text = text; tb.Foreground = GetCachedBrush(fill); if (fontFamily != null) { tb.FontFamily = fontFamily; } if (fontSize > 0) { tb.FontSize = fontSize; } if (fontWeight > 0) { tb.FontWeight = GetFontWeight(fontWeight); } double dx = 0; double dy = 0; if (maxSize != null || halign != HorizontalAlignment.Left || valign != VerticalAlignment.Top) { tb.Measure(new Size(1000, 1000)); var size = tb.DesiredSize; if (maxSize != null) { if (size.Width > maxSize.Value.Width + 1e-3) { size = size.WithWidth(Math.Max(maxSize.Value.Width, 0)); } if (size.Height > maxSize.Value.Height + 1e-3) { size = size.WithHeight(Math.Max(maxSize.Value.Height, 0)); } tb.Width = size.Width; tb.Height = size.Height; } if (halign == HorizontalAlignment.Center) { dx = -size.Width / 2; } if (halign == HorizontalAlignment.Right) { dx = -size.Width; } if (valign == VerticalAlignment.Middle) { dy = -size.Height / 2; } if (valign == VerticalAlignment.Bottom) { dy = -size.Height; } } var transform = new TransformGroup(); transform.Children.Add(new TranslateTransform(dx, dy)); if (Math.Abs(rotate) > double.Epsilon) { transform.Children.Add(new RotateTransform(rotate)); } transform.Children.Add(new TranslateTransform(p.X, p.Y)); tb.RenderTransform = transform; if (tb.Clip != null) { tb.Clip.Transform = new MatrixTransform(tb.RenderTransform.Value.Invert()); } }
/// <inheritdoc/> public override void DrawText(ScreenPoint p, string text, OxyColor fill, string fontFamily = null, double fontSize = 10, double fontWeight = 400, double rotation = 0, OxyPlot.HorizontalAlignment horizontalAlignment = OxyPlot.HorizontalAlignment.Left, OxyPlot.VerticalAlignment verticalAlignment = OxyPlot.VerticalAlignment.Top, OxySize?maxSize = null) { var font = GetFontOrThrow(fontFamily, fontSize, FontStyle.Regular); float outputX = (float)p.X; float outputY = (float)p.Y; var bounds = MeasureText(text, fontFamily, fontSize, fontWeight); switch (horizontalAlignment) { case OxyPlot.HorizontalAlignment.Center: outputX = (float)(outputX - bounds.Width / 2.0); break; case OxyPlot.HorizontalAlignment.Right: outputX = (float)(outputX - bounds.Width); break; } switch (verticalAlignment) { case OxyPlot.VerticalAlignment.Bottom: outputY = (float)(outputY - bounds.Height); break; case OxyPlot.VerticalAlignment.Middle: outputY = (float)(outputY - bounds.Height / 2.0); break; } var outputPosition = new PointF(outputX, outputY); image.Mutate(img => { img.DrawText(text, font, new Rgba32(fill.R, fill.G, fill.B, fill.A), outputPosition); }); }
/// <summary> /// Draws the text. /// </summary> /// <param name="p">The position.</param> /// <param name="text">The text.</param> /// <param name="fill">The fill color.</param> /// <param name="fontFamily">The font family.</param> /// <param name="fontSize">Size of the font.</param> /// <param name="fontWeight">The font weight.</param> /// <param name="rotate">The rotation angle.</param> /// <param name="halign">The horizontal alignment.</param> /// <param name="valign">The vertical alignment.</param> /// <param name="maxSize">The maximum size of the text.</param> public void DrawText( ScreenPoint p, string text, OxyColor fill, string fontFamily, double fontSize, double fontWeight, double rotate, OxyPlot.HorizontalAlignment halign, OxyPlot.VerticalAlignment valign, OxySize?maxSize) { if (string.IsNullOrWhiteSpace(fontFamily)) { fontFamily = "Arial"; } if (text == null) { text = string.Empty; } var format = new TextFormat(this.dwtFactory, fontFamily, GetFontWeight(fontWeight), FontStyle.Normal, FontStretch.Normal, (float)fontSize); var maxWidth = 1000f; var maxHeight = 1000f; if (maxSize != null) { maxHeight = (float)maxSize.Value.Height; maxWidth = (float)maxSize.Value.Width; } var layout = new TextLayout(this.dwtFactory, text, format, maxWidth, maxHeight); var size = new Size2F(layout.Metrics.Width, layout.Metrics.Height); if (maxSize != null) { if (size.Width > maxSize.Value.Width) { size.Width = (float)maxSize.Value.Width; } if (size.Height > maxSize.Value.Height) { size.Height = (float)maxSize.Value.Height; } } float dx = 0; if (halign == OxyPlot.HorizontalAlignment.Center) { dx = -size.Width / 2; } if (halign == OxyPlot.HorizontalAlignment.Right) { dx = -size.Width; } float dy = 0; if (valign == OxyPlot.VerticalAlignment.Middle) { dy = -size.Height / 2; } if (valign == OxyPlot.VerticalAlignment.Bottom) { dy = -size.Height; } this.renderUnits.Add(new TextRenderUnit(layout, this.GetBrush(fill), Matrix3x2.Translation(dx, dy) * Matrix3x2.Rotation((float)rotate) * Matrix3x2.Translation(p.ToVector2()))); format.Dispose(); }
/// <summary> /// Draws the text. /// </summary> /// <param name="p">The position.</param> /// <param name="text">The text.</param> /// <param name="fill">The fill color.</param> /// <param name="fontFamily">The font family.</param> /// <param name="fontSize">Size of the font.</param> /// <param name="fontWeight">The font weight.</param> /// <param name="rotate">The rotation angle.</param> /// <param name="halign">The horizontal alignment.</param> /// <param name="valign">The vertical alignment.</param> /// <param name="maxSize">The maximum size of the text.</param> public void DrawText( ScreenPoint p, string text, OxyColor fill, string fontFamily, double fontSize, double fontWeight, double rotate, HorizontalAlignment halign, VerticalAlignment valign, OxySize? maxSize) { var tb = new TextBlock { Text = text, Foreground = this.GetCachedBrush(fill) }; if (fontFamily != null) { tb.FontFamily = new FontFamily(fontFamily); } if (fontSize > 0) { tb.FontSize = fontSize; } if (fontWeight > 0) { tb.FontWeight = GetFontWeight(fontWeight); } double dx = 0; double dy = 0; if (maxSize != null || halign != HorizontalAlignment.Left || valign != VerticalAlignment.Top) { tb.Measure(new Size(1000, 1000)); var size = tb.DesiredSize; if (maxSize != null) { if (size.Width > maxSize.Value.Width) { size.Width = Math.Max(maxSize.Value.Width, 0); } if (size.Height > maxSize.Value.Height) { size.Height = Math.Max(maxSize.Value.Height, 0); } tb.Width = size.Width; tb.Height = size.Height; } if (halign == HorizontalAlignment.Center) { dx = -size.Width / 2; } if (halign == HorizontalAlignment.Right) { dx = -size.Width; } if (valign == VerticalAlignment.Middle) { dy = -size.Height / 2; } if (valign == VerticalAlignment.Bottom) { dy = -size.Height; } } var transform = new TransformGroup(); transform.Children.Add(new TranslateTransform(dx, dy)); if (Math.Abs(rotate) > double.Epsilon) { transform.Children.Add(new RotateTransform(rotate)); } transform.Children.Add(new TranslateTransform(p.X, p.Y)); tb.RenderTransform = transform; tb.SetValue(RenderOptions.ClearTypeHintProperty, ClearTypeHint.Enabled); this.ApplyTooltip(tb); if (this.clip.HasValue) { // add a clipping container that is not rotated var c = new Canvas(); c.Children.Add(tb); this.Add(c); } else { this.Add(tb); } }
/// <summary> /// Draws the text. /// </summary> /// <param name="p">The position.</param> /// <param name="text">The text.</param> /// <param name="fill">The fill color.</param> /// <param name="fontFamily">The font family.</param> /// <param name="fontSize">Size of the font.</param> /// <param name="fontWeight">The font weight.</param> /// <param name="rotate">The rotation angle.</param> /// <param name="halign">The horizontal alignment.</param> /// <param name="valign">The vertical alignment.</param> /// <param name="maxSize">The maximum size of the text.</param> public void DrawText( ScreenPoint p, string text, OxyColor fill, string fontFamily, double fontSize, double fontWeight, double rotate, HorizontalAlignment halign, VerticalAlignment valign, OxySize?maxSize) { var tb = new TextBlock { Text = text, Foreground = this.GetCachedBrush(fill) }; if (fontFamily != null) { tb.FontFamily = new FontFamily(fontFamily); } if (fontSize > 0) { tb.FontSize = fontSize; } if (fontWeight > 0) { tb.FontWeight = GetFontWeight(fontWeight); } double dx = 0; double dy = 0; if (maxSize != null || halign != HorizontalAlignment.Left || valign != VerticalAlignment.Top) { tb.Measure(new Size(1000, 1000)); var size = tb.DesiredSize; if (maxSize != null) { if (size.Width > maxSize.Value.Width) { size.Width = Math.Max(maxSize.Value.Width, 0); } if (size.Height > maxSize.Value.Height) { size.Height = Math.Max(maxSize.Value.Height, 0); } tb.Width = size.Width; tb.Height = size.Height; } if (halign == HorizontalAlignment.Center) { dx = -size.Width / 2; } if (halign == HorizontalAlignment.Right) { dx = -size.Width; } if (valign == VerticalAlignment.Middle) { dy = -size.Height / 2; } if (valign == VerticalAlignment.Bottom) { dy = -size.Height; } } var transform = new TransformGroup(); transform.Children.Add(new TranslateTransform(dx, dy)); if (Math.Abs(rotate) > double.Epsilon) { transform.Children.Add(new RotateTransform(rotate)); } transform.Children.Add(new TranslateTransform(p.X, p.Y)); tb.RenderTransform = transform; tb.SetValue(RenderOptions.ClearTypeHintProperty, ClearTypeHint.Enabled); this.ApplyTooltip(tb); if (this.clip.HasValue) { // add a clipping container that is not rotated var c = new Canvas(); c.Children.Add(tb); this.Add(c); } else { this.Add(tb); } }