Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 60 additions & 46 deletions 106 Source/OxyPlot.ImageSharp/ImageRenderContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@ namespace OxyPlot.ImageSharp
using System.Collections.Generic;
using System.IO;
using System.Linq;
using SixLabors.Fonts;
using SixLabors.Fonts.Exceptions;
using OxyPlot;
using SixLabors.ImageSharp;
using SixLabors.Fonts;
using SixLabors.ImageSharp.Drawing.Processing;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using SixLabors.Primitives;
using SixLabors.Shapes;
using SixLabors.ImageSharp.Drawing;
using SixLabors.ImageSharp.Processing.Processors;

/// <summary>
/// Provides an implementation of IRenderContext which draws to a <see cref="Image"/>.
Expand Down Expand Up @@ -180,13 +181,13 @@ public override void DrawText(ScreenPoint p, string text, OxyColor fill, string
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 actualDescent = this.Convert(actualFontSize * this.MilliPointsToNominalResolution(font.FontMetrics.Descender));
var offsetDescent = new PointF(actualDescent * -sin, actualDescent * cos);

var actualLineHeight = this.Convert(actualFontSize * this.MilliPointsToNominalResolution(font.LineHeight));
var actualLineHeight = this.Convert(actualFontSize * this.MilliPointsToNominalResolution(font.FontMetrics.LineHeight));
var offsetLineHeight = new PointF(actualLineHeight * -sin, actualLineHeight * cos);

var actualLineGap = this.Convert(actualFontSize * this.MilliPointsToNominalResolution(font.LineGap));
var actualLineGap = this.Convert(actualFontSize * this.MilliPointsToNominalResolution(font.FontMetrics.LineGap));
var offsetLineGap = new PointF(actualLineGap * -sin, actualLineGap * cos);

// find top of the whole text
Expand Down Expand Up @@ -219,7 +220,7 @@ public override void DrawText(ScreenPoint p, string text, OxyColor fill, string
{
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);
Expand All @@ -230,11 +231,13 @@ public override void DrawText(ScreenPoint p, string text, OxyColor fill, string
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)
var textPath = new PathBuilder().AddLine(0f, 0f, lineBoundsWidth, 0).Build();
var glyphsAtOrigin = TextBuilder.GenerateGlyphs(line, textPath, new TextOptions(font)
{
HorizontalAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Bottom, // sit on the line (baseline)
ApplyKerning = true,
Dpi = this.Dpi,
HorizontalAlignment = SixLabors.Fonts.HorizontalAlignment.Left,
VerticalAlignment = SixLabors.Fonts.VerticalAlignment.Bottom, // sit on the line (baseline)
KerningMode = KerningMode.Auto,
});

// translate and rotate into possition
Expand Down Expand Up @@ -295,7 +298,7 @@ public override void DrawImage(
src = RectangleF.FromLTRB(src.Left + (cropLeft / scale.Width), src.Top + (cropTop / scale.Height), src.Right - (cropRight / scale.Width), src.Bottom - (cropBottom / scale.Height));

var bytes = source.GetData();
var sourceImage = SixLabors.ImageSharp.Image.Load(bytes);
var sourceImage = Image.Load(bytes);

var resampler = interpolate ? KnownResamplers.Triangle : KnownResamplers.NearestNeighbor;

Expand Down Expand Up @@ -333,29 +336,10 @@ public override void DrawImage(
if (doPad)
{
img.Pad(srcRough.Width + 2, srcRough.Height + 2);
img.ApplyProcessor(new MirrorPadProcessor());
}
});

if (doPad)
{
sourceImage[0, 0] = sourceImage[1, 1];
sourceImage[sourceImage.Width - 1, 0] = sourceImage[sourceImage.Width - 2, 1];
sourceImage[0, sourceImage.Height - 1] = sourceImage[1, sourceImage.Height - 2];
sourceImage[sourceImage.Width - 1, sourceImage.Height - 1] = sourceImage[sourceImage.Width - 2, sourceImage.Height - 2];

for (int x = 1; x < sourceImage.Width - 1; x++)
{
sourceImage[x, 0] = sourceImage[x, 1];
sourceImage[x, sourceImage.Height - 1] = sourceImage[x, sourceImage.Height - 2];
}

for (int y = 1; y < sourceImage.Height - 1; y++)
{
sourceImage[0, y] = sourceImage[1, y];
sourceImage[sourceImage.Width - 1, y] = sourceImage[sourceImage.Width - 2, y];
}
}

sourceImage.Mutate(img =>
{
img.Transform(rescale, resampler);
Expand All @@ -365,7 +349,7 @@ public override void DrawImage(

this.Target.Mutate(img =>
{
img.DrawImage(sourceImage, new Point((int)dest.X, (int)dest.Y), new GraphicsOptions(interpolate, (float)opacity));
img.DrawImage(sourceImage, new Point((int)dest.X, (int)dest.Y), new GraphicsOptions() { Antialias = interpolate, BlendPercentage = (float)opacity });
});
}
catch (ImageProcessingException)
Expand Down Expand Up @@ -397,7 +381,7 @@ public override void DrawLine(IList<ScreenPoint> points, OxyColor stroke, double
? new Pen(ToRgba32(stroke), actualThickness, actualDashArray)
: new Pen(ToRgba32(stroke), actualThickness);
var actualPoints = this.GetActualPoints(points, thickness, edgeRenderingMode).ToArray();
var options = new GraphicsOptions(this.ShouldUseAntiAliasingForLine(edgeRenderingMode, points));
var options = this.CreateDrawingOptions(this.ShouldUseAntiAliasingForLine(edgeRenderingMode, points));

this.Target.Mutate(img =>
{
Expand All @@ -408,7 +392,10 @@ public override void DrawLine(IList<ScreenPoint> points, OxyColor stroke, double
/// <inheritdoc/>
public override void DrawPolygon(IList<ScreenPoint> points, OxyColor fill, OxyColor stroke, double thickness, EdgeRenderingMode edgeRenderingMode, double[] dashArray, LineJoin lineJoin)
{
if ((!fill.IsVisible() && !(stroke.IsVisible() || thickness <= 0)) || points.Count < 2)
var fillInvisible = !fill.IsVisible();
var strokeInvisible = !stroke.IsVisible() || thickness <= 0;

if ((fillInvisible && strokeInvisible) || points.Count < 2)
{
return;
}
Expand All @@ -418,18 +405,26 @@ public override void DrawPolygon(IList<ScreenPoint> points, OxyColor fill, OxyCo
? this.ConvertDashArray(dashArray, actualThickness)
: null;

var pen = actualDashArray != null
var pen = strokeInvisible ? null :
actualDashArray != null
? new Pen(ToRgba32(stroke), actualThickness, actualDashArray)
: new Pen(ToRgba32(stroke), actualThickness);
var actualPoints = this.GetActualPoints(points, thickness, edgeRenderingMode).ToArray();
var options = new GraphicsOptions(this.ShouldUseAntiAliasingForLine(edgeRenderingMode, points));
var options = this.CreateDrawingOptions(this.ShouldUseAntiAliasingForLine(edgeRenderingMode, points));

var brush = Brushes.Solid(ToRgba32(fill));
var brush = fillInvisible ? null : Brushes.Solid(ToRgba32(fill));

this.Target.Mutate(img =>
{
img.FillPolygon(options, brush, actualPoints);
img.DrawPolygon(options, pen, actualPoints);
if (brush != null)
{
img.FillPolygon(options, brush, actualPoints);
}

if (pen != null)
{
img.DrawPolygon(options, pen, actualPoints);
}
});
}

Expand Down Expand Up @@ -571,7 +566,7 @@ private FontFamily GetFamilyOrFallbackOrThrow(string fontFamily = null, bool all
FontFamily family;
try
{
family = SixLabors.Fonts.SystemFonts.Find(fontFamily);
family = SixLabors.Fonts.SystemFonts.Get(fontFamily);
}
catch (FontFamilyNotFoundException primaryEx)
{
Expand All @@ -582,7 +577,7 @@ private FontFamily GetFamilyOrFallbackOrThrow(string fontFamily = null, bool all

try
{
family = SixLabors.Fonts.SystemFonts.Find(FallbackFontFamily);
family = SystemFonts.Get(FallbackFontFamily);
}
catch (FontFamilyNotFoundException fallbackEx)
{
Expand Down Expand Up @@ -611,8 +606,8 @@ private OxySize MeasureTextLoose(string text, string fontFamily, double fontSize
var tight = this.MeasureTextTight(text, fontFamily, fontSize, fontWeight);
var width = tight.Width;

var lineHeight = actualFontSize * this.MilliPointsToNominalResolution(font.LineHeight);
var lineGap = actualFontSize * this.MilliPointsToNominalResolution(font.LineGap);
var lineHeight = actualFontSize * this.MilliPointsToNominalResolution(font.FontMetrics.LineHeight);
var lineGap = actualFontSize * this.MilliPointsToNominalResolution(font.FontMetrics.LineGap);
var lineCount = CountLines(text);

var height = (lineHeight * lineCount) + (lineGap * (lineCount - 1));
Expand All @@ -635,7 +630,7 @@ private OxySize MeasureTextTight(string text, string fontFamily, double fontSize
var font = this.GetFontOrThrow(fontFamily, fontSize, this.ToFontStyle(fontWeight));
var actualFontSize = this.NominalFontSizeToPoints(fontSize);

var result = TextMeasurer.Measure(text, new RendererOptions(font, this.Dpi));
var result = TextMeasurer.Measure(text, new TextOptions(font) { Dpi = this.Dpi });
return new OxySize(this.ConvertBack(result.Width), this.ConvertBack(result.Height));
}

Expand Down Expand Up @@ -819,5 +814,24 @@ private float GetActualThickness(double strokeThickness, EdgeRenderingMode edgeR

return scaledThickness;
}


/// <summary>
/// Creates a <see cref="DrawingOptions"/> object for the given options.
/// </summary>
/// <param name="antialised">A value indicating whether graphics should be antialised.</param>
/// <returns>A new <see cref="DrawingOptions"/></returns>
private DrawingOptions CreateDrawingOptions(bool antialised)
{
var options = new DrawingOptions()
{
GraphicsOptions = new GraphicsOptions()
{
Antialias = antialised
}
};

return options;
}
}
}
45 changes: 45 additions & 0 deletions 45 Source/OxyPlot.ImageSharp/MirrorPadProcessor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
namespace OxyPlot.ImageSharp
{
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing.Processors;

/// <summary>
/// Performs a 'mirror' (clamp) along the edge of the image, which is used to assist with drawing non-pixel aligned and interpolate images.
/// </summary>
internal class MirrorPadProcessor : IImageProcessor
{
private class MirrorPadImplementation<TPixel> : ImageProcessor<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{
public MirrorPadImplementation(Configuration configuration, Image<TPixel> source, Rectangle sourceRectangle)
: base(configuration, source, sourceRectangle)
{
}

protected override void OnFrameApply(ImageFrame<TPixel> source)
{
source[0, 0] = source[1, 1];
source[source.Width - 1, 0] = source[source.Width - 2, 1];
source[0, source.Height - 1] = source[1, source.Height - 2];
source[source.Width - 1, source.Height - 1] = source[source.Width - 2, source.Height - 2];

for (int x = 1; x < source.Width - 1; x++)
{
source[x, 0] = source[x, 1];
source[x, source.Height - 1] = source[x, source.Height - 2];
}

for (int y = 1; y < source.Height - 1; y++)
{
source[0, y] = source[1, y];
source[source.Width - 1, y] = source[source.Width - 2, y];
}
}
}

public IImageProcessor<TPixel> CreatePixelSpecificProcessor<TPixel>(Configuration configuration, Image<TPixel> source, Rectangle sourceRectangle) where TPixel : unmanaged, IPixel<TPixel>
{
return new MirrorPadImplementation<TPixel>(configuration, source, sourceRectangle);
}
}
}
7 changes: 3 additions & 4 deletions 7 Source/OxyPlot.ImageSharp/OxyPlot.ImageSharp.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<LangVersion>8</LangVersion>
<TargetFrameworks>netstandard1.3;netstandard2.0</TargetFrameworks>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<Description>OxyPlot is a plotting library for .NET. This is package is based on SixLabors.ImageSharp.</Description>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<Copyright>Copyright (c) 2014 OxyPlot contributors</Copyright>
Expand All @@ -20,9 +20,8 @@
<None Include="..\..\Icons\OxyPlot_128.png" Pack="true" PackagePath="\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="SixLabors.ImageSharp" Version="1.0.0-beta0007" />
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta0007" />
<PackageReference Include="SixLabors.Shapes.Text" Version="1.0.0-beta0009" />
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.3" />
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta15" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\OxyPlot\OxyPlot.csproj" />
Expand Down
Morty Proxy This is a proxified and sanitized view of the page, visit original site.