Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use element applies referenced viewBox scaling. FontManager created. #414

Merged
merged 3 commits into from
Feb 4, 2019
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ Tests/**/*.suo
*.trx
Source/TestResults/
Source/.vs
/Source/Svg.sln.DotSettings.user
49 changes: 49 additions & 0 deletions Source/Document Structure/SvgUse.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace Svg
Expand Down Expand Up @@ -79,6 +80,21 @@ public virtual SvgUnit Y
set { this.Attributes["y"] = value; }
}


[SvgAttribute("width")]
public virtual SvgUnit Width
{
get { return this.Attributes.GetAttribute<SvgUnit>("width"); }
set { this.Attributes["width"] = value; }
}

[SvgAttribute("height")]
public virtual SvgUnit Height
{
get { return this.Attributes.GetAttribute<SvgUnit>("height"); }
set { this.Attributes["height"] = value; }
}

/// <summary>
/// Applies the required transforms to <see cref="ISvgRenderer"/>.
/// </summary>
Expand All @@ -99,6 +115,8 @@ public SvgUse()
{
this.X = 0;
this.Y = 0;
this.Width = 0;
this.Height = 0;
}

public override System.Drawing.Drawing2D.GraphicsPath Path(ISvgRenderer renderer)
Expand All @@ -107,15 +125,33 @@ public override System.Drawing.Drawing2D.GraphicsPath Path(ISvgRenderer renderer
return (element != null && !this.HasRecursiveReference()) ? element.Path(renderer) : null;
}

/// <summary>
/// Gets an <see cref="SvgPoint"/> representing the top left point of the rectangle.
/// </summary>
public SvgPoint Location
{
get { return new SvgPoint(X, Y); }
}

/// <summary>
/// Gets the bounds of the element.
/// </summary>
/// <value>The bounds.</value>
public override System.Drawing.RectangleF Bounds
{
get
{
var ew = this.Width.ToDeviceValue(null, UnitRenderingType.Horizontal, this);
var eh = this.Height.ToDeviceValue(null, UnitRenderingType.Vertical, this);
if (ew > 0 && eh > 0)
return TransformedBounds(new RectangleF(this.Location.ToDeviceValue(null, this),
new SizeF(ew, eh)));
var element = this.OwnerDocument.IdManager.GetElementById(this.ReferencedElement) as SvgVisualElement;
if (element != null)
{
return element.Bounds;
}

return new System.Drawing.RectangleF();
}
}
Expand All @@ -131,6 +167,19 @@ protected override void Render(ISvgRenderer renderer)
var element = this.OwnerDocument.IdManager.GetElementById(this.ReferencedElement) as SvgVisualElement;
if (element != null)
{
var ew = Width.ToDeviceValue(renderer, UnitRenderingType.Horizontal, this);
var eh = Height.ToDeviceValue(renderer, UnitRenderingType.Vertical, this);
if (ew > 0 && eh > 0)
{
var viewBox = element.Attributes.GetAttribute<SvgViewBox>("viewBox");
if (viewBox!=SvgViewBox.Empty && Math.Abs(ew - viewBox.Width) > float.Epsilon && Math.Abs(eh - viewBox.Height) > float.Epsilon)
{
var sw = ew / viewBox.Width;
var sh = eh / viewBox.Height;
renderer.ScaleTransform(sw, sh, MatrixOrder.Prepend);
}
}

mrbean-bremen marked this conversation as resolved.
Show resolved Hide resolved
var origParent = element.Parent;
element._parent = this;
// as the new parent may have other styles that are inherited,
Expand Down
1 change: 1 addition & 0 deletions Source/Svg.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@
<Compile Include="Rendering\ISvgRenderer.cs" />
<Compile Include="Rendering\SvgRendering.cs" />
<Compile Include="SvgElementStyle.cs" />
<Compile Include="SvgFontManager.cs" />
<Compile Include="SvgNodeReader.cs" />
<Compile Include="Css\CssQuery.cs" />
<Compile Include="Css\SvgElementOps.cs" />
Expand Down
11 changes: 3 additions & 8 deletions Source/SvgElementStyle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -434,8 +434,6 @@ public static object ValidateFontFamily(string fontFamilyList, SvgDocument doc)
{
// Split font family list on "," and then trim start and end spaces and quotes.
var fontParts = (fontFamilyList ?? string.Empty).Split(new[] { ',' }).Select(fontName => fontName.Trim(new[] { '"', ' ', '\'' }));
var families = System.Drawing.FontFamily.Families;
Func<FontFamily, bool> getFamily;
FontFamily family;
IEnumerable<SvgFontFace> sFaces;

Expand All @@ -444,13 +442,10 @@ public static object ValidateFontFamily(string fontFamilyList, SvgDocument doc)
foreach (var f in fontParts)
{
if (doc != null && doc.FontDefns().TryGetValue(f, out sFaces)) return sFaces;

getFamily = new Func<FontFamily, bool>(ff => string.Equals(ff.Name, f, StringComparison.OrdinalIgnoreCase));
family = families.FirstOrDefault(getFamily);
family = SvgFontManager.FindFont(f);
if (family != null) return family;
family = PrivateFonts.Families.FirstOrDefault(getFamily);
family = PrivateFonts.Families.FirstOrDefault(ff => string.Equals(ff.Name, f, StringComparison.OrdinalIgnoreCase));
if (family != null) return family;

switch (f.ToLower())
{
case "serif":
Expand All @@ -466,4 +461,4 @@ public static object ValidateFontFamily(string fontFamilyList, SvgDocument doc)
return System.Drawing.FontFamily.GenericSansSerif;
}
}
}
}
58 changes: 58 additions & 0 deletions Source/SvgFontManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Text;
using System.IO;
using System.Linq;

namespace Svg
{
/// <summary>
/// Manages access to <see cref="SystemFonts"/> and any privately loaded fonts.
/// When a font is requested in the render process, if the font is not found as an embedded SvgFont, the render
/// process will SvgFontManager.FindFont method.
/// </summary>

public static class SvgFontManager
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please add a description what this does and how it is used (along the lines you put in the comments in this PR already)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

complete.

{
private static readonly Dictionary<string, FontFamily> SystemFonts;
public static Func<string, FontFamily> FontLoaderCallback;
static SvgFontManager()
{
SystemFonts = FontFamily.Families.ToDictionary(ff => ff.Name.ToLower());
}

/// <summary>
/// Loads a font from the given path.
/// </summary>
/// <param name="path">A <see cref="string"/> containing the full path to the font file.</param>
/// <returns>An <see cref="FontFamily"/> of the loaded font.</returns>
public static FontFamily LoadFontFamily(string path)
{
var pfc = new PrivateFontCollection();
var fp = Path.GetFullPath(path);
pfc.AddFontFile(fp);
return pfc.Families.Length == 0 ? null : pfc.Families[0];
}

/// <summary>
/// This method searches a dictionary of fonts (pre loaded with the system fonts). If a
/// font can't be found and a callback has been provided - then the callback should perform
/// any validation and return a font (or null if not found/error).
/// Where a font can't be located it is the responsibility of the caller to perform any
/// exception handling.
/// </summary>
/// <param name="name">A <see cref="string"/> containing the FamilyName of the font.</param>
/// <returns>An <see cref="FontFamily"/> of the loaded font or null is not located.</returns>
public static FontFamily FindFont(string name)
{
if (name == null) return null;
FontFamily ff = null;
if (SystemFonts.TryGetValue(name.ToLower(), out ff)) return ff;
if (FontLoaderCallback == null) return null;
var ff2 = FontLoaderCallback(name);
SystemFonts.Add(name.ToLower(), ff2);
return ff2;
}
}
}