public (int, RectangleF) GetAdjustedFont(string graphicString, float containerWidth, float containerHeight, int maxFontSize, int minFontSize) { var sizeRect = new RectangleF(); for (int adjustedSize = maxFontSize; adjustedSize >= minFontSize; adjustedSize--) { var testFont = new Font(_dummyFont, adjustedSize); var renderOptions = new RendererOptions(testFont) { WrappingWidth = containerWidth }; // Test the string with the new size sizeRect = TextMeasurer.MeasureBounds(graphicString, renderOptions); float volume = sizeRect.Height * sizeRect.Width; if (volume < containerWidth * containerHeight) { // Good font, return it return(adjustedSize, sizeRect); } } return(minFontSize, sizeRect); }
public void TextFailsToRender() { var text = "2016-12-10"; // first make sure the text rectangle actually overlaps var destArea = new RectangleF(PointF.Empty, this.ActualImage.Size()); var textArea = TextMeasurer.MeasureBounds(text, new RendererOptions(Drawing.Roboto10, new Point(-10, 3))); Assert.IsTrue(destArea.IntersectsWith(textArea.AsRect())); // THIS SHOULD IDEALLY NOT THROW Assert.ThrowsException <ImageProcessingException>( () => this.ActualImage.Mutate( x => { x.DrawText(text, Drawing.Roboto10, Color.White, new PointF(-10, 3)); })); // but our custom safe method side steps the problem this.ActualImage.Mutate(x => { x.DrawTextSafe(text, Drawing.Roboto10, Color.White, new PointF(-10, 3)); }); this.ExpectedImage = Drawing.NewImage(100, 100, Color.Black); this.ExpectedImage.Mutate( x => x.DrawText("016-12-10", Drawing.Roboto10, Color.White, new PointF(-3.8232422f, 3))); // if we're on a system where Arial isn't installed, we fall back to roboto font, // thus we allow a slight tolerance on the image var tolerance = SystemFonts.TryFind(Drawing.Arial, out _) ? 0.0 : 1.5E-06; this.AssertImagesEqual(tolerance); }
public static void DrawEventLabel(this SpectralEvent @event, IImageProcessingContext graphics, EventRenderingOptions options) { if (!options.DrawLabel) { return; } var text = @event.Name; if (string.IsNullOrWhiteSpace(text)) { return; } var bounds = TextMeasurer.MeasureBounds(text, new RendererOptions(Roboto6)); var topLeft = options.Converters.GetPoint(@event); topLeft.Offset(0, -bounds.Height); graphics.DrawTextSafe( @event.Name, Roboto6, options.Label, topLeft); }
public static Font ScaleFont(Font font, string text, float targetWidth, float targetHeight) { var maxFontSize = font.Size; var minFontSize = 0f; while (maxFontSize - minFontSize > 0.1f) { var actual = TextMeasurer.MeasureBounds(text, new RendererOptions(font) { WrappingWidth = targetWidth }); if (actual.Height > targetHeight || actual.Width > targetWidth) { maxFontSize = font.Size; } else { minFontSize = font.Size; } font = new Font(font, (maxFontSize + minFontSize) / 2); } return(new Font(font, minFontSize)); }
public void TextFailsToRender() { var text = "2016-12-10"; // first make sure the text rectangle actually overlaps var destArea = new RectangleF(PointF.Empty, this.Actual.Size()); var textArea = TextMeasurer.MeasureBounds(text, new RendererOptions(Drawing.Arial10, new Point(-10, 3))); Assert.IsTrue(destArea.IntersectsWith(textArea.AsRect())); // THIS SHOULD IDEALLY NOT THROW Assert.ThrowsException <ImageProcessingException>( () => this.Actual.Mutate( x => { x.DrawText(text, Drawing.Arial10, Color.White, new PointF(-10, 3)); })); // but our custom safe method side steps the problem this.Actual.Mutate(x => { x.DrawTextSafe(text, Drawing.Arial10, Color.White, new PointF(-10, 3)); }); this.Expected = Drawing.NewImage(100, 100, Color.Black); this.Expected.Mutate( x => x.DrawText("016-12-10", Drawing.Arial10, Color.White, new PointF((float)(-10f + 4.741211f), 3))); this.AssertImagesEqual(); }
public void WhiteSpaceAtStartOfLineNotMeasured(string text, float width, float height) { Font font = CreateFont(text); FontRectangle size = TextMeasurer.MeasureBounds(text, new RendererOptions(font, 72 * font.EmSize)); Assert.Equal(height, size.Height, 2); Assert.Equal(width, size.Width, 2); }
public void TwoTabsAreDoubleWidthOfOneTab() { Font font = CreateFont("\t x"); var xWidth = TextMeasurer.MeasureBounds("x", new RendererOptions(font, (72 * font.EmSize))); var tabWidth = TextMeasurer.MeasureBounds("\t", new RendererOptions(font, (72 * font.EmSize))); var twoTabWidth = TextMeasurer.MeasureBounds("\t\t", new RendererOptions(font, (72 * font.EmSize))); Assert.Equal(twoTabWidth.Width, tabWidth.Width * 2, 2); }
public void TwoTabsAreDoubleWidthOfOneTabMinusXWidth() { var font = CreateFont("\t x"); SizeF xWidth = TextMeasurer.MeasureBounds("x", new RendererOptions(font, (72 * font.EmSize))).Size; SizeF tabWidth = TextMeasurer.MeasureBounds("\tx", new RendererOptions(font, (72 * font.EmSize))).Size; SizeF twoTabWidth = TextMeasurer.MeasureBounds("\t\tx", new RendererOptions(font, (72 * font.EmSize))).Size; Assert.Equal(twoTabWidth.Width - xWidth.Width, (tabWidth.Width - xWidth.Width) * 2, 2); }
public void ThrowsMeasuringWhitespace() { // wendy one returns wrong points for 'o' Font font = new FontCollection().Add(TestFonts.WendyOneFile).CreateFont(12); FontRectangle size = TextMeasurer.MeasureBounds(" ", new TextOptions(new Font(font, 30))); Assert.Equal(60, size.Width, 1); Assert.Equal(31.6, size.Height, 1); }
public void TwoTabsAreDoubleWidthOfOneTabMinusXWidth() { Font font = CreateFont("\t x"); FontRectangle xWidth = TextMeasurer.MeasureBounds("x", new RendererOptions(font, 72 * font.EmSize)); FontRectangle tabWidth = TextMeasurer.MeasureBounds("\tx", new RendererOptions(font, 72 * font.EmSize)); FontRectangle twoTabWidth = TextMeasurer.MeasureBounds("\t\tx", new RendererOptions(font, 72 * font.EmSize)); Assert.Equal(twoTabWidth.Width - xWidth.Width, (tabWidth.Width - xWidth.Width) * 2, 2); }
public void Rendering2TabsAtStartOfLineTooShort() { var font = CreateFont("\t x"); SizeF xWidth = TextMeasurer.MeasureBounds("x", new RendererOptions(font, (72 * font.EmSize))).Size; SizeF tabWidth = TextMeasurer.MeasureBounds("\t\t", new RendererOptions(font, (72 * font.EmSize))).Size; SizeF tabWithXWidth = TextMeasurer.MeasureBounds("\t\tx", new RendererOptions(font, (72 * font.EmSize))).Size; Assert.Equal(tabWidth.Width + xWidth.Width, tabWithXWidth.Width, 2); }
private RectangleF GetTextBounds(int wrapWidth, string text, Font font) { return(TextMeasurer.MeasureBounds(text, new RendererOptions(font) { HorizontalAlignment = HorizontalAlignment, VerticalAlignment = VerticalAlignment, WrappingWidth = wrapWidth })); }
public void Rendering2TabsAtStartOfLineTooShort() { Font font = CreateFont("\t x"); FontRectangle xWidth = TextMeasurer.MeasureBounds("x", new RendererOptions(font, 72 * font.EmSize)); FontRectangle tabWidth = TextMeasurer.MeasureBounds("\t\t", new RendererOptions(font, 72 * font.EmSize)); FontRectangle tabWithXWidth = TextMeasurer.MeasureBounds("\t\tx", new RendererOptions(font, 72 * font.EmSize)); Assert.Equal(tabWidth.Width + xWidth.Width, tabWithXWidth.Width, 2); }
public void TextWidthFroTabOnlyTextSouldBeSingleTabWidthMultipliedByTabCount(int tabCount) { Font font = CreateFont("\t x"); SizeF tabWidth = TextMeasurer.MeasureBounds("\t", new RendererOptions(font, (72 * font.EmSize))).Size; string tabString = "".PadRight(tabCount, '\t'); SizeF tabCountWidth = TextMeasurer.MeasureBounds(tabString, new RendererOptions(font, (72 * font.EmSize))).Size; Assert.Equal(tabWidth.Width * tabCount, tabCountWidth.Width, 2); }
public void RenderingTabAtStartOrLineTooShort() { Font font = CreateFont("\t x"); var xWidth = TextMeasurer.MeasureBounds("x", new RendererOptions(font, (72 * font.EmSize))); var tabWidth = TextMeasurer.MeasureBounds("\t", new RendererOptions(font, (72 * font.EmSize))); var doublTabWidth = TextMeasurer.MeasureBounds("\t\t", new RendererOptions(font, (72 * font.EmSize))); var tabWithXWidth = TextMeasurer.MeasureBounds("\tx", new RendererOptions(font, (72 * font.EmSize))); Assert.Equal(tabWidth.Width + xWidth.Width, tabWithXWidth.Width, 2); }
public void MeasureText(string text, float height, float width) { Font font = CreateFont(text); int scaleFactor = 72 * font.EmSize; // 72 * emSize means 1 point = 1px FontRectangle size = TextMeasurer.MeasureBounds(text, new RendererOptions(font, 72 * font.EmSize)); Assert.Equal(height, size.Height, 4); Assert.Equal(width, size.Width, 4); }
public void WhiteSpaceAtStartOfLineNotMeasured(string text, float width, float height) { Font font = CreateFont(text); FontRectangle size = TextMeasurer.MeasureBounds(text, new TextOptions(font) { Dpi = font.FontMetrics.ScaleFactor }); Assert.Equal(height, size.Height, 2); Assert.Equal(width, size.Width, 2); }
public void ThrowsMeasureingWhitespace() { // wendy one returns wrong points for 'o' Font font = new FontCollection().Install(TestFonts.WendyOneFile).CreateFont(12); var r = new GlyphRenderer(); var size = TextMeasurer.MeasureBounds(" ", new RendererOptions(new Font(font, 30), 72)); Assert.Equal(60, size.Width, 1); Assert.Equal(31.6, size.Height, 1); }
public static void DrawTextBoxes <TPixel>(Image <TPixel> image, Font font, IEnumerable <TextBox> boxes) where TPixel : struct, IPixel <TPixel> { image.Mutate(context => { foreach (var box in boxes) { var boxBounds = new RectangleF( x: (float)(image.Width * box.X / 100), y: (float)(image.Height * box.Y / 100), width: (float)(image.Width * box.Width / 100), height: (float)(image.Height * box.Height / 100) ); var scaledFont = ScaleFont(new Font(font, image.Height / 8), box.Text, boxBounds.Width - 2 * outlineSize, boxBounds.Height - 2 * outlineSize); var wrapWidth = ScaleWidth(scaledFont, box.Text, boxBounds.Width - 2 * outlineSize); var lineColor = ColorBuilder <TPixel> .FromRGBA(box.LineColor.R, box.LineColor.G, box.LineColor.B, box.LineColor.A); var fillColor = ColorBuilder <TPixel> .FromRGBA(box.FillColor.R, box.FillColor.G, box.FillColor.B, box.FillColor.A); var pen = Pens.Solid(lineColor, 3f); var brush = Brushes.Solid(fillColor); var textBounds = TextMeasurer.MeasureBounds(box.Text, new RendererOptions(scaledFont) { WrappingWidth = wrapWidth, HorizontalAlignment = ConvertHorizontalAlignment(box.Horizontal), }); var drawLocation = GetLocation(box, boxBounds, textBounds); // draw outline context.DrawText( new TextGraphicsOptions(true) { WrapTextWidth = wrapWidth, HorizontalAlignment = ConvertHorizontalAlignment(box.Horizontal), }, box.Text, scaledFont, pen, drawLocation); // draw fill context.DrawText(new TextGraphicsOptions(true) { WrapTextWidth = wrapWidth, HorizontalAlignment = ConvertHorizontalAlignment(box.Horizontal), }, box.Text, scaledFont, brush, drawLocation); } }); }
public void MeasureTextWordWrapping(string text, float height, float width) { Font font = CreateFont(text); int scaleFactor = 72 * font.EmSize; // 72 * emSize means 1 point = 1px SizeF size = TextMeasurer.MeasureBounds(text, new RendererOptions(font, 72 * font.EmSize) { WrappingWidth = 350 }).Size; Assert.Equal(width, size.Width, 4); Assert.Equal(height, size.Height, 4); }
public unsafe void MeasureTextWithSpan() { Font font = CreateFont("hello"); Span <char> text = stackalloc char[] { 'h', 'e', 'l', 'l', 'o' }; int scaleFactor = 72 * font.EmSize; // 72 * emSize means 1 point = 1px FontRectangle size = TextMeasurer.MeasureBounds(text, new RendererOptions(font, 72 * font.EmSize)); Assert.Equal(10, size.Height, 4); Assert.Equal(130, size.Width, 4); }
public void TabWidth0CausesBadTabRendering() { string text = "Hello\tworld"; Font font = CreateFont(text); var size = TextMeasurer.MeasureBounds(text, new RendererOptions(font, 72 * font.EmSize) { TabWidth = 0 }); // tab width of 0 should make tabs not render at all Assert.Equal(10, size.Height, 4); Assert.Equal(280, size.Width, 4); }
public MemoryStream SpoilerTxt(string spoil) { var fill = Brushes.Solid <Rgba32>(Rgba32.Black); var brush = Brushes.Solid <Rgba32>(Rgba32.White); RendererOptions op = new RendererOptions(_Spoiltxt); var text = WordWrap(spoil, 120); var tsize = TextMeasurer.MeasureBounds(text, op); int[] size = { Convert.ToInt32(tsize.Width) + 20, Convert.ToInt32(tsize.Height) + 20 }; var img2 = new Image <Rgba32>(size[0], size[1]); img2.DrawText(text, _Spoiltxt, brush, new PointF(0, 0), new TextGraphicsOptions(true)); img2.BackgroundColor(Rgba32.Black); var img1 = new Image <Rgba32>(img2.Width, img2.Height); _Spoil = _fonts.Find("Whitney-Bold").CreateFont(img2.Width * 0.064f); var rect = new Rectangle(0, 0, img2.Width, img2.Height); img1.BackgroundColor(Rgba32.Black, rect); img1.DrawText("Spoiler Warning" + "\r\n" + "(Mouse over to view)", _Spoil, brush, new PointF(0, 0), new TextGraphicsOptions(true) { WrapTextWidth = img1.Width - 20 }); MagickImage f1 = new MagickImage(img1.ToStream()); MagickImage f2 = new MagickImage(img2.ToStream()); MagickImage[] frames = { f1, f2 }; MemoryStream ms = new MemoryStream(); using (MagickImageCollection gif = new MagickImageCollection()) { gif.Add(f1); gif.Add(f2); for (int i = 0; i < gif.Count; i++) { gif[i].AnimationDelay = 50; gif[i].AnimationIterations = 1; } QuantizeSettings settings = new QuantizeSettings { Colors = 256, DitherMethod = DitherMethod.No }; gif.Quantize(settings); gif.Optimize(); gif.Write(ms, MagickFormat.Gif); ms.Position = 0; } return(ms); }
public void MakeSureWeAccountForKerning() { var text = "i1i1i1i1i1i1i1i1i1"; var textArea = TextMeasurer.MeasureBounds(text, new RendererOptions(Drawing.Roboto10, new Point(-70, 3))); this.ActualImage.Mutate(x => { x.DrawTextSafe(text, Drawing.Roboto10, Color.White, new PointF(-70, 3)); }); this.ExpectedImage = Drawing.NewImage(100, 100, Color.Black); this.ExpectedImage.Mutate( x => x.DrawText("i1", Drawing.Roboto10, Color.White, new PointF(-4.975585f, 3))); this.AssertImagesEqual(); }
public void MeasureTextWithKerning(string text, float height, float width, bool enableKerning) { var c = new FontCollection(); Font font = c.Install(TestFonts.SimpleFontFileData()).CreateFont(12); int scaleFactor = 72 * font.EmSize; // 72 * emSize means 1 point = 1px FontRectangle size = TextMeasurer.MeasureBounds(text, new RendererOptions(new Font(font, 1), 72 * font.EmSize) { ApplyKerning = enableKerning }); Assert.Equal(height, size.Height, 4); Assert.Equal(width, size.Width, 4); }
public void DrawProcessors_CompleteOverlap() { // complete overlap does NOT throw for text var textSize = TextMeasurer.MeasureBounds(TestText, new RendererOptions(TestFont)); Assert.IsTrue(textSize.Width < 50 && textSize.Height < 50); this.testImage.Mutate(Parallel, x => x.DrawText(TestText, TestFont, TestBrush, CompleteOverlap)); // complete overlap does NOT throw for images this.testImage.Mutate(Parallel, x => x.DrawImage(OverImage, (Point)CompleteOverlap, 1f)); // complete overlap does NOT throw for rects this.testImage.Mutate(Parallel, x => x.Draw(TestPen, new Rectangle((Point)CompleteOverlap, TestSize))); }
public void TextWidthFroTabOnlyTextSouldBeSingleTabWidthMultipliedByTabCountMinusX(int tabCount) { Font font = CreateFont("\t x"); SizeF xWidth = TextMeasurer.MeasureBounds("x", new RendererOptions(font, (72 * font.EmSize))).Size; SizeF tabWidth = TextMeasurer.MeasureBounds("\tx", new RendererOptions(font, (72 * font.EmSize))).Size; string tabString = "x".PadLeft(tabCount + 1, '\t'); SizeF tabCountWidth = TextMeasurer.MeasureBounds(tabString, new RendererOptions(font, (72 * font.EmSize))).Size; float singleTabWidth = tabWidth.Width - xWidth.Width; float finalTabWidth = tabCountWidth.Width - xWidth.Width; Assert.Equal(singleTabWidth * tabCount, finalTabWidth, 2); }
public void TabWidth0CausesBadTabRendering() { string text = "Hello\tworld"; Font font = CreateFont(text); FontRectangle size = TextMeasurer.MeasureBounds(text, new TextOptions(font) { Dpi = font.FontMetrics.ScaleFactor, TabWidth = 0 }); // tab width of 0 should make tabs not render at all Assert.Equal(10, size.Height, 4); Assert.Equal(280, size.Width, 4); }
public void TextWidthForTabOnlyTextShouldBeSingleTabWidthMultipliedByTabCount(int tabCount) { Font font = CreateFont("\t x"); FontRectangle tabWidth = TextMeasurer.MeasureBounds("\t", new TextOptions(font) { Dpi = font.FontMetrics.ScaleFactor }); string tabString = string.Empty.PadRight(tabCount, '\t'); FontRectangle tabCountWidth = TextMeasurer.MeasureBounds(tabString, new TextOptions(font) { Dpi = font.FontMetrics.ScaleFactor }); Assert.Equal(tabWidth.Width * tabCount, tabCountWidth.Width, 2); }
public Task <CommandResult> RunImageCommand(params string[] args) { Image <Rgba32> baseImage = Image.Load(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Assets", $"clippy.png")); try { IEnumerable <string> txtBase = args; if (characters.Contains(args[0].ToLowerInvariant())) { baseImage = ChangeImage(ref txtBase); } string txt = string.Join("\r\n\r\n", txtBase); RectangleF size = TextMeasurer.MeasureBounds(txt, new RendererOptions(font) { WrappingWidth = clippyTop.Width - 20 }); using (Image <Rgba32> textImage = new Image <Rgba32>(clippyTop.Width, (int)Math.Ceiling(size.Height + 5))) { textImage.Mutate(m => m .Fill(colour) .DrawLines(Rgba32.Black, 2, new PointF[] { new PointF(0, 0), new PointF(0, textImage.Height) }) .DrawLines(Rgba32.Black, 2, new PointF[] { new PointF(textImage.Width, 0), new PointF(textImage.Width, textImage.Height) }) .DrawText(txt, font, Rgba32.Black, new PointF(10, 0), new TextGraphicsOptions() { WrapTextWidth = clippyTop.Width - 20 })); Image <Rgba32> returnImage = new Image <Rgba32>(clippyTop.Width, clippyTop.Height + textImage.Height + clippyBottom.Height + baseImage.Height); returnImage.Mutate(m => m .Fill(Rgba32.Transparent) .DrawImage(clippyTop, 1, new Size(clippyTop.Width, clippyTop.Height), new Point(0, 0)) .DrawImage(textImage, 1, new Size(textImage.Width, textImage.Height), new Point(0, clippyTop.Height)) .DrawImage(clippyBottom, 1, new Size(clippyBottom.Width, clippyBottom.Height), new Point(0, clippyTop.Height + textImage.Height)) .DrawImage(baseImage, 1, new Size(baseImage.Width, baseImage.Height), new Point((clippyTop.Width - baseImage.Width) / 2, clippyTop.Height + textImage.Height + clippyBottom.Height))); return(Task.FromResult(returnImage.ToResult(Context))); } } finally { baseImage?.Dispose(); } }