Fixed methods that return the system default fonts.
Added font tests.
This commit is contained in:
Lluis Sanchez 2013-03-28 17:39:45 +01:00
Родитель 66ebe9ceaa
Коммит 310581b5d0
7 изменённых файлов: 288 добавлений и 95 удалений

Просмотреть файл

@ -49,7 +49,7 @@ namespace Samples
var col1 = new Rectangle (); var col1 = new Rectangle ();
var col2 = new Rectangle (); var col2 = new Rectangle ();
var text = new TextLayout (ctx); var text = new TextLayout ();
text.Font = this.Font.WithSize (24); text.Font = this.Font.WithSize (24);
Console.WriteLine (text.Font.Size); Console.WriteLine (text.Font.Size);

222
Testing/Tests/FontTests.cs Normal file
Просмотреть файл

@ -0,0 +1,222 @@
//
// FontTests.cs
//
// Author:
// Lluis Sanchez <lluis@xamarin.com>
//
// Copyright (c) 2013 Xamarin Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using NUnit.Framework;
using Xwt.Drawing;
namespace Xwt
{
[TestFixture]
public class FontTests
{
[Test]
public void FromNameEmpty ()
{
var f = Font.FromName ("");
Assert.AreEqual (Font.SystemFont, f);
}
[Test]
public void WithFamily ()
{
var f1 = Font.SystemFont;
var f2 = f1.WithFamily ("Courier");
Assert.AreEqual ("Courier", f2.Family);
Assert.AreEqual (f1.Size, f2.Size);
Assert.AreEqual (f1.Stretch, f2.Stretch);
Assert.AreEqual (f1.Style, f2.Style);
Assert.AreEqual (f1.Weight, f2.Weight);
}
[Test]
public void WithSize ()
{
var f1 = Font.SystemFont;
var f2 = f1.WithSize (33);
Assert.AreEqual (f1.Family, f2.Family);
Assert.AreEqual (33d, f2.Size);
Assert.AreEqual (f1.Stretch, f2.Stretch);
Assert.AreEqual (f1.Style, f2.Style);
Assert.AreEqual (f1.Weight, f2.Weight);
}
[Test]
public void WithStretch ()
{
var f1 = Font.SystemFont;
var f2 = f1.WithStretch (FontStretch.Condensed);
Assert.AreEqual (f1.Family, f2.Family);
Assert.AreEqual (f1.Size, f2.Size);
Assert.AreEqual (FontStretch.Condensed, f2.Stretch);
Assert.AreEqual (f1.Style, f2.Style);
Assert.AreEqual (f1.Weight, f2.Weight);
}
[Test]
public void WithStyle ()
{
var f1 = Font.SystemFont;
var f2 = f1.WithStyle (FontStyle.Oblique);
Assert.AreEqual (f1.Family, f2.Family);
Assert.AreEqual (f1.Size, f2.Size);
Assert.AreEqual (f1.Stretch, f2.Stretch);
Assert.AreEqual (FontStyle.Oblique, f2.Style);
Assert.AreEqual (f1.Weight, f2.Weight);
}
[Test]
public void WithWeight ()
{
var f1 = Font.SystemFont;
var f2 = f1.WithWeight (FontWeight.Bold);
Assert.AreEqual (f1.Family, f2.Family);
Assert.AreEqual (f1.Size, f2.Size);
Assert.AreEqual (f1.Stretch, f2.Stretch);
Assert.AreEqual (f1.Style, f2.Style);
Assert.AreEqual (FontWeight.Bold, f2.Weight);
}
[Test]
public void FromNameOnlyFamily ()
{
var f = Font.FromName ("Arial");
Assert.AreEqual ("Arial", f.Family);
Assert.AreEqual (Font.SystemFont.Size, f.Size);
Assert.AreEqual (FontStretch.Normal, f.Stretch);
Assert.AreEqual (FontStyle.Normal, f.Style);
Assert.AreEqual (FontWeight.Normal, f.Weight);
}
[Test]
public void FromNameOnlySize ()
{
var f = Font.FromName ("33");
Assert.AreEqual (Font.SystemFont.Family, f.Family);
Assert.AreEqual (33d, f.Size);
Assert.AreEqual (FontStretch.Normal, f.Stretch);
Assert.AreEqual (FontStyle.Normal, f.Style);
Assert.AreEqual (FontWeight.Normal, f.Weight);
}
[Test]
public void FromNameOnlyFamilyAndSize ()
{
var f = Font.FromName ("Arial 33");
Assert.AreEqual ("Arial", f.Family);
Assert.AreEqual (33d, f.Size);
Assert.AreEqual (FontStretch.Normal, f.Stretch);
Assert.AreEqual (FontStyle.Normal, f.Style);
Assert.AreEqual (FontWeight.Normal, f.Weight);
}
[Test]
public void FromNameOnlyFamilyAndSizeWithFallbackSecondChoice ()
{
var f = Font.FromName ("Foobar, Arial, dummy, 33");
Assert.AreEqual ("Arial", f.Family);
Assert.AreEqual (33d, f.Size);
Assert.AreEqual (FontStretch.Normal, f.Stretch);
Assert.AreEqual (FontStyle.Normal, f.Style);
Assert.AreEqual (FontWeight.Normal, f.Weight);
}
[Test]
public void FromNameOnlyFamilyAndSizeWithFallbackFirstChoice ()
{
var f = Font.FromName ("Arial, Foobar, dummy 33");
Assert.AreEqual ("Arial", f.Family);
Assert.AreEqual (33d, f.Size);
Assert.AreEqual (FontStretch.Normal, f.Stretch);
Assert.AreEqual (FontStyle.Normal, f.Style);
Assert.AreEqual (FontWeight.Normal, f.Weight);
}
[Test]
public void FromNameOnlyFamilyAndSizeWithFallbackNoChoice ()
{
var f = Font.FromName ("Foobar, dummy 33");
Assert.AreEqual (Font.SystemFont.Family, f.Family);
Assert.AreEqual (33d, f.Size);
Assert.AreEqual (FontStretch.Normal, f.Stretch);
Assert.AreEqual (FontStyle.Normal, f.Style);
Assert.AreEqual (FontWeight.Normal, f.Weight);
}
[Test]
public void FromNameWithStyle ()
{
var f = Font.FromName ("Arial, dummy italic 33");
Assert.AreEqual ("Arial", f.Family);
Assert.AreEqual (33d, f.Size);
Assert.AreEqual (FontStretch.Normal, f.Stretch);
Assert.AreEqual (FontStyle.Italic, f.Style);
Assert.AreEqual (FontWeight.Normal, f.Weight);
}
[Test]
public void FromNameWithWeight ()
{
var f = Font.FromName ("Arial, dummy bold 33");
Assert.AreEqual ("Arial", f.Family);
Assert.AreEqual (33d, f.Size);
Assert.AreEqual (FontStretch.Normal, f.Stretch);
Assert.AreEqual (FontStyle.Normal, f.Style);
Assert.AreEqual (FontWeight.Bold, f.Weight);
}
[Test]
public void FromNameWithStretch ()
{
var f = Font.FromName ("Arial, dummy condensed 33");
Assert.AreEqual ("Arial", f.Family);
Assert.AreEqual (33d, f.Size);
Assert.AreEqual (FontStretch.Condensed, f.Stretch);
Assert.AreEqual (FontStyle.Normal, f.Style);
Assert.AreEqual (FontWeight.Normal, f.Weight);
}
[Test]
public void FromNameWithAllStyles ()
{
var f = Font.FromName ("Arial, dummy expanded Oblique Light 33");
Assert.AreEqual ("Arial", f.Family);
Assert.AreEqual (33d, f.Size);
Assert.AreEqual (FontStretch.Expanded, f.Stretch);
Assert.AreEqual (FontStyle.Oblique, f.Style);
Assert.AreEqual (FontWeight.Light, f.Weight);
}
[Test]
public void FontEquals ()
{
var f1 = Font.FromName ("Arial expanded Oblique Light 33");
var f2 = Font.FromName ("Arial expanded Oblique Light 33");
Assert.IsTrue (f1.Equals (f2));
}
}
}

Просмотреть файл

@ -64,6 +64,7 @@
<Compile Include="DrawingTests.cs" /> <Compile Include="DrawingTests.cs" />
<Compile Include="ReferenceImageVerifierDialog.cs" /> <Compile Include="ReferenceImageVerifierDialog.cs" />
<Compile Include="ReferenceImageManager.cs" /> <Compile Include="ReferenceImageManager.cs" />
<Compile Include="FontTests.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="Test.csproj" /> <None Include="Test.csproj" />

Просмотреть файл

@ -31,6 +31,7 @@ using Xwt.Drawing;
using System.Globalization; using System.Globalization;
using System.Reflection; using System.Reflection;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
namespace Xwt.GtkBackend namespace Xwt.GtkBackend
{ {
@ -38,67 +39,18 @@ namespace Xwt.GtkBackend
{ {
public override object GetSystemDefaultFont () public override object GetSystemDefaultFont ()
{ {
if (Platform.IsMac || Platform.IsWindows) { var la = new Gtk.Label ("");
Xwt.Drawing.Font font = null; return la.Style.FontDescription;
GtkEngine.NativeToolkit.Invoke (delegate {
font = Xwt.Drawing.Font.SystemFont;
});
return Create (font.Family, font.Size, FontStyle.Normal, FontWeight.Normal, FontStretch.Normal);
}
return null;
}
public override object GetSystemDefaultMonospaceFont ()
{
if (Platform.IsMac || Platform.IsWindows) {
Xwt.Drawing.Font font = null;
GtkEngine.NativeToolkit.Invoke (delegate {
font = Xwt.Drawing.Font.SystemMonospaceFont;
});
return Create (font.Family, font.Size, FontStyle.Normal, FontWeight.Normal, FontStretch.Normal);
}
return null;
}
public override object GetSystemDefaultSansSerifFont ()
{
if (Platform.IsMac || Platform.IsWindows) {
Xwt.Drawing.Font font = null;
GtkEngine.NativeToolkit.Invoke (delegate {
font = Xwt.Drawing.Font.SystemSansSerifFont;
});
return Create (font.Family, font.Size, FontStyle.Normal, FontWeight.Normal, FontStretch.Normal);
}
return null;
}
public override object GetSystemDefaultSerifFont ()
{
if (Platform.IsMac || Platform.IsWindows) {
Xwt.Drawing.Font font = null;
GtkEngine.NativeToolkit.Invoke (delegate {
font = Xwt.Drawing.Font.SystemSerifFont;
});
return Create (font.Family, font.Size, FontStyle.Normal, FontWeight.Normal, FontStretch.Normal);
}
return null;
} }
public override IEnumerable<string> GetInstalledFonts () public override IEnumerable<string> GetInstalledFonts ()
{ {
if (Platform.IsMac || Platform.IsWindows) { return Gdk.PangoHelper.ContextGet ().FontMap.Families.Select (f => f.Name);
IEnumerable<string> fonts = null;
GtkEngine.NativeToolkit.Invoke (delegate {
fonts = Xwt.Drawing.Font.AvailableFontFamilies;
});
return fonts;
}
return new string[0];
} }
public override object Create (string fontName, double size, FontStyle style, FontWeight weight, FontStretch stretch) public override object Create (string fontName, double size, FontStyle style, FontWeight weight, FontStretch stretch)
{ {
return FontDescription.FromString (fontName + " " + size.ToString (CultureInfo.InvariantCulture)); return FontDescription.FromString (fontName + ", " + style + " " + weight + " " + stretch + " " + size.ToString (CultureInfo.InvariantCulture));
} }
#region IFontBackendHandler implementation #region IFontBackendHandler implementation

Просмотреть файл

@ -33,31 +33,11 @@ namespace Xwt.GtkBackend
{ {
public class GtkEngine: ToolkitEngineBackend public class GtkEngine: ToolkitEngineBackend
{ {
static Toolkit nativeToolkit;
public override void InitializeApplication () public override void InitializeApplication ()
{ {
Gtk.Application.Init (); Gtk.Application.Init ();
} }
public static Toolkit NativeToolkit {
get {
if (nativeToolkit == null) {
if (Platform.IsMac) {
if (!Toolkit.TryLoad (ToolkitType.XamMac, out nativeToolkit)) {
if (!Toolkit.TryLoad (ToolkitType.Cocoa, out nativeToolkit)) {
throw new InvalidOperationException ("Mac backend not found");
}
}
} else if (Platform.IsWindows) {
if (!Toolkit.TryLoad (ToolkitType.Wpf, out nativeToolkit))
throw new InvalidOperationException ("Windows backend not found");
}
}
return nativeToolkit;
}
}
public override void InitializeBackends () public override void InitializeBackends ()
{ {
RegisterBackend<ICustomWidgetBackend, CustomWidgetBackend> (); RegisterBackend<ICustomWidgetBackend, CustomWidgetBackend> ();

Просмотреть файл

@ -112,7 +112,16 @@ namespace Xwt.Backends
public abstract IEnumerable<string> GetInstalledFonts (); public abstract IEnumerable<string> GetInstalledFonts ();
/// <summary>
/// Creates a new font. Returns null if the font family is not available in the system
/// </summary>
/// <param name="fontName">Font family name</param>
/// <param name="size">Size in points</param>
/// <param name="style">Style</param>
/// <param name="weight">Weight</param>
/// <param name="stretch">Stretch</param>
public abstract object Create (string fontName, double size, FontStyle style, FontWeight weight, FontStretch stretch); public abstract object Create (string fontName, double size, FontStyle style, FontWeight weight, FontStretch stretch);
public abstract object Copy (object handle); public abstract object Copy (object handle);
public abstract object SetSize (object handle, double size); public abstract object SetSize (object handle, double size);

Просмотреть файл

@ -73,14 +73,12 @@ namespace Xwt.Drawing
/// decimal number (size in points). Any one of the options may be absent. If FAMILY-LIST is absent, the default /// decimal number (size in points). Any one of the options may be absent. If FAMILY-LIST is absent, the default
/// font family will be used. If STYLE-OPTIONS is missing, then all style options will be set to the default values. /// font family will be used. If STYLE-OPTIONS is missing, then all style options will be set to the default values.
/// If SIZE is missing, the size in the resulting font description will be set to the default font size. /// If SIZE is missing, the size in the resulting font description will be set to the default font size.
/// If the font doesn't exist, it returns the system font.
/// </remarks> /// </remarks>
public static Font FromName (string name) public static Font FromName (string name)
{ {
var toolkit = Toolkit.CurrentEngine; var toolkit = Toolkit.CurrentEngine;
var handler = toolkit.FontBackendHandler; var handler = toolkit.FontBackendHandler;
string[] parts = name.Split (new char[] {' '}, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length < 2)
throw new ArgumentException ("Font family name or size not specified");
double size = -1; double size = -1;
FontStyle style = FontStyle.Normal; FontStyle style = FontStyle.Normal;
@ -95,39 +93,50 @@ namespace Xwt.Drawing
FontWeight fw; FontWeight fw;
FontStretch fs; FontStretch fs;
double siz; double siz;
if (Enum.TryParse<FontStyle> (token, out st) && st != FontStyle.Normal) if (double.TryParse (token, out siz)) // Try parsing the number first, since Enum.TryParse can also parse numbers
style = st;
else if (Enum.TryParse<FontWeight> (token, out fw) && fw != FontWeight.Normal)
weight = fw;
else if (Enum.TryParse<FontStretch> (token, out fs) && fs != FontStretch.Normal)
stretch = fs;
else if (double.TryParse (token, out siz) && size != -1)
size = siz; size = siz;
else if (Enum.TryParse<FontStyle> (token, true, out st) && st != FontStyle.Normal)
style = st;
else if (Enum.TryParse<FontWeight> (token, true, out fw) && fw != FontWeight.Normal)
weight = fw;
else if (Enum.TryParse<FontStretch> (token, true, out fs) && fs != FontStretch.Normal)
stretch = fs;
else if (token.Length > 0) else if (token.Length > 0)
break; break;
lasti = i;
if (i <= 0) if (i <= 0)
break; break;
lasti = i;
i = name.LastIndexOf (' ', i - 1); i = name.LastIndexOf (' ', i - 1);
} while (true); } while (true);
string fname = GetSupportedFont (name.Substring (0, lasti)); string fname = lasti > 0 ? name.Substring (0, lasti) : string.Empty;
if (fname.Length == 0) fname = fname.Length > 0 ? GetSupportedFont (fname) : Font.SystemFont.Family;
fname = SystemFont.Family;
if (size == -1) if (size == -1)
size = SystemFont.Size; size = SystemFont.Size;
return new Font (handler.Create (fname, size, style, weight, stretch), toolkit); var fb = handler.Create (fname, size, style, weight, stretch);
if (fb != null)
return new Font (fb, toolkit);
else
return Font.SystemFont;
} }
static string GetSupportedFont (string fontNames) static string GetSupportedFont (string fontNames)
{ {
int i = fontNames.IndexOf (',');
if (i == -1)
return fontNames.Trim ();
LoadInstalledFonts (); LoadInstalledFonts ();
int i = fontNames.IndexOf (',');
if (i == -1) {
var f = fontNames.Trim ();
if (installedFonts.Contains (f))
return f;
else
return GetDefaultFont (f);
}
string[] names = fontNames.Split (new char[] {','}, StringSplitOptions.RemoveEmptyEntries); string[] names = fontNames.Split (new char[] {','}, StringSplitOptions.RemoveEmptyEntries);
if (names.Length == 0) if (names.Length == 0)
throw new ArgumentException ("Font family name not provided"); throw new ArgumentException ("Font family name not provided");
@ -137,10 +146,16 @@ namespace Xwt.Drawing
if (installedFonts.Contains (n)) if (installedFonts.Contains (n))
return n; return n;
} }
return names[0].Trim (); return GetDefaultFont (fontNames.Trim (' ',','));
} }
static HashSet<string> installedFonts = new HashSet<string> (); static string GetDefaultFont (string unknownFont)
{
Console.WriteLine ("Font '" + unknownFont + "' not available in the system. Using '" + Font.SystemFont.Family + "' instead");
return Font.SystemFont.Family;
}
static HashSet<string> installedFonts;
static ReadOnlyCollection<string> installedFontsArray; static ReadOnlyCollection<string> installedFontsArray;
@ -262,6 +277,20 @@ namespace Xwt.Drawing
sb.Append (' ').Append (Size.ToString (CultureInfo.InvariantCulture)); sb.Append (' ').Append (Size.ToString (CultureInfo.InvariantCulture));
return sb.ToString (); return sb.ToString ();
} }
public override bool Equals (object obj)
{
var other = obj as Font;
if (other == null)
return false;
return Family == other.Family && Style == other.Style && Weight == other.Weight && Stretch == other.Stretch && Size == other.Size;
}
public override int GetHashCode ()
{
return ToString().GetHashCode ();
}
} }
public enum FontStyle public enum FontStyle