Browse Source

Merge remote-tracking branch 'origin/stable/0.10.x' into fixes/nullable-avalonia-native

pull/8035/head
Dan Walmsley 5 years ago
parent
commit
fa86e9b5ff
  1. 24
      Avalonia.sln
  2. 57
      src/Avalonia.Controls/DateTimePickers/DateTimePickerPanel.cs
  3. 4
      src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs
  4. 21
      src/Skia/Avalonia.Skia/FontManagerImpl.cs
  5. 123
      src/Skia/Avalonia.Skia/SKTypefaceCollection.cs
  6. 2
      src/Skia/Avalonia.Skia/SKTypefaceCollectionCache.cs

24
Avalonia.sln

@ -2003,6 +2003,30 @@ Global
{909A8CBD-7D0E-42FD-B841-022AD8925820}.Release|iPhone.Build.0 = Release|Any CPU {909A8CBD-7D0E-42FD-B841-022AD8925820}.Release|iPhone.Build.0 = Release|Any CPU
{909A8CBD-7D0E-42FD-B841-022AD8925820}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {909A8CBD-7D0E-42FD-B841-022AD8925820}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{909A8CBD-7D0E-42FD-B841-022AD8925820}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {909A8CBD-7D0E-42FD-B841-022AD8925820}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.AppStore|Any CPU.Build.0 = Debug|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.AppStore|iPhone.Build.0 = Debug|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.Debug|iPhone.Build.0 = Debug|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.Release|Any CPU.Build.0 = Release|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.Release|iPhone.ActiveCfg = Release|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.Release|iPhone.Build.0 = Release|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{11BE52AF-E2DD-4CF0-B19A-05285ACAF571}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU {11BE52AF-E2DD-4CF0-B19A-05285ACAF571}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
{11BE52AF-E2DD-4CF0-B19A-05285ACAF571}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU {11BE52AF-E2DD-4CF0-B19A-05285ACAF571}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
{11BE52AF-E2DD-4CF0-B19A-05285ACAF571}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU {11BE52AF-E2DD-4CF0-B19A-05285ACAF571}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU

57
src/Avalonia.Controls/DateTimePickers/DateTimePickerPanel.cs

@ -1,7 +1,11 @@
using System; using System;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using Avalonia.Controls.Presenters;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Input.GestureRecognizers;
using Avalonia.Interactivity;
using Avalonia.Media;
using Avalonia.VisualTree; using Avalonia.VisualTree;
namespace Avalonia.Controls.Primitives namespace Avalonia.Controls.Primitives
@ -58,18 +62,18 @@ namespace Avalonia.Controls.Primitives
private Vector _offset; private Vector _offset;
private bool _hasInit; private bool _hasInit;
private bool _suppressUpdateOffset; private bool _suppressUpdateOffset;
private ListBoxItem _pressedItem; private ScrollContentPresenter? _parentScroller;
public DateTimePickerPanel() public DateTimePickerPanel()
{ {
FormatDate = DateTime.Now; FormatDate = DateTime.Now;
AddHandler(ListBoxItem.PointerPressedEvent, OnItemPointerDown, Avalonia.Interactivity.RoutingStrategies.Bubble); AddHandler(TappedEvent, OnItemTapped, RoutingStrategies.Bubble);
AddHandler(ListBoxItem.PointerReleasedEvent, OnItemPointerUp, Avalonia.Interactivity.RoutingStrategies.Bubble);
} }
static DateTimePickerPanel() static DateTimePickerPanel()
{ {
FocusableProperty.OverrideDefaultValue<DateTimePickerPanel>(true); FocusableProperty.OverrideDefaultValue<DateTimePickerPanel>(true);
BackgroundProperty.OverrideDefaultValue<DateTimePickerPanel>(Brushes.Transparent);
AffectsMeasure<DateTimePickerPanel>(ItemHeightProperty); AffectsMeasure<DateTimePickerPanel>(ItemHeightProperty);
} }
@ -254,6 +258,8 @@ namespace Avalonia.Controls.Primitives
_suppressUpdateOffset = true; _suppressUpdateOffset = true;
SelectedValue = (int)newSel * Increment + MinimumValue; SelectedValue = (int)newSel * Increment + MinimumValue;
_suppressUpdateOffset = false; _suppressUpdateOffset = false;
System.Diagnostics.Debug.WriteLine($"Offset: {_offset} ItemHeight: {ItemHeight}");
} }
} }
@ -269,7 +275,7 @@ namespace Avalonia.Controls.Primitives
public Size Extent => _extent; public Size Extent => _extent;
public Size Viewport => new Size(0, ItemHeight); public Size Viewport => Bounds.Size;
public event EventHandler ScrollInvalidated; public event EventHandler ScrollInvalidated;
@ -340,6 +346,20 @@ namespace Avalonia.Controls.Primitives
return finalSize; return finalSize;
} }
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnAttachedToVisualTree(e);
_parentScroller = this.GetVisualParent() as ScrollContentPresenter;
_parentScroller?.AddHandler(Gestures.ScrollGestureEndedEvent, OnScrollGestureEnded);
}
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnDetachedFromVisualTree(e);
_parentScroller?.RemoveHandler(Gestures.ScrollGestureEndedEvent, OnScrollGestureEnded);
_parentScroller = null;
}
protected override void OnKeyDown(KeyEventArgs e) protected override void OnKeyDown(KeyEventArgs e)
{ {
switch (e.Key) switch (e.Key)
@ -523,22 +543,13 @@ namespace Avalonia.Controls.Primitives
return newValue; return newValue;
} }
private void OnItemPointerDown(object sender, PointerPressedEventArgs e) private void OnItemTapped(object sender, TappedEventArgs e)
{ {
if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed) if (e.Source is IVisual source &&
GetItemFromSource(source) is ListBoxItem listBoxItem &&
listBoxItem.Tag is int tag)
{ {
_pressedItem = GetItemFromSource((IVisual)e.Source); SelectedValue = tag;
e.Handled = true;
}
}
private void OnItemPointerUp(object sender, PointerReleasedEventArgs e)
{
if (e.GetCurrentPoint(this).Properties.PointerUpdateKind == PointerUpdateKind.LeftButtonReleased &&
_pressedItem != null)
{
SelectedValue = (int)GetItemFromSource((IVisual)e.Source).Tag;
_pressedItem = null;
e.Handled = true; e.Handled = true;
} }
} }
@ -562,5 +573,15 @@ namespace Avalonia.Controls.Primitives
{ {
ScrollInvalidated?.Invoke(this, e); ScrollInvalidated?.Invoke(this, e);
} }
private void OnScrollGestureEnded(object? sender, ScrollGestureEndedEventArgs e)
{
var snapY = Math.Round(Offset.Y / ItemHeight) * ItemHeight;
if (snapY != Offset.Y)
{
Offset = Offset.WithY(snapY);
}
}
} }
} }

4
src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs

@ -371,7 +371,7 @@ namespace Avalonia.Controls.Presenters
{ {
var logicalUnits = delta.Y / logicalScrollItemSize.Y; var logicalUnits = delta.Y / logicalScrollItemSize.Y;
delta = delta.WithY(delta.Y - logicalUnits * logicalScrollItemSize.Y); delta = delta.WithY(delta.Y - logicalUnits * logicalScrollItemSize.Y);
dy = logicalUnits * scrollable!.ScrollSize.Height; dy = logicalUnits;
} }
else else
dy = delta.Y; dy = delta.Y;
@ -389,7 +389,7 @@ namespace Avalonia.Controls.Presenters
{ {
var logicalUnits = delta.X / logicalScrollItemSize.X; var logicalUnits = delta.X / logicalScrollItemSize.X;
delta = delta.WithX(delta.X - logicalUnits * logicalScrollItemSize.X); delta = delta.WithX(delta.X - logicalUnits * logicalScrollItemSize.X);
dx = logicalUnits * scrollable!.ScrollSize.Width; dx = logicalUnits;
} }
else else
dx = delta.X; dx = delta.X;

21
src/Skia/Avalonia.Skia/FontManagerImpl.cs

@ -29,8 +29,7 @@ namespace Avalonia.Skia
[ThreadStatic] private static string[] t_languageTagBuffer; [ThreadStatic] private static string[] t_languageTagBuffer;
public bool TryMatchCharacter(int codepoint, FontStyle fontStyle, public bool TryMatchCharacter(int codepoint, FontStyle fontStyle,
FontWeight fontWeight, FontWeight fontWeight, FontFamily fontFamily, CultureInfo culture, out Typeface fontKey)
FontFamily fontFamily, CultureInfo culture, out Typeface fontKey)
{ {
SKFontStyle skFontStyle; SKFontStyle skFontStyle;
@ -109,15 +108,20 @@ namespace Avalonia.Skia
if (typeface.FontFamily.Key == null) if (typeface.FontFamily.Key == null)
{ {
var defaultName = SKTypeface.Default.FamilyName; var defaultName = SKTypeface.Default.FamilyName;
var fontStyle = new SKFontStyle((SKFontStyleWeight)typeface.Weight, SKFontStyleWidth.Normal, (SKFontStyleSlant)typeface.Style);
var fontStyle = new SKFontStyle((SKFontStyleWeight)typeface.Weight, SKFontStyleWidth.Normal,
(SKFontStyleSlant)typeface.Style);
foreach (var familyName in typeface.FontFamily.FamilyNames) foreach (var familyName in typeface.FontFamily.FamilyNames)
{ {
if(familyName == FontFamily.DefaultFontFamilyName)
{
continue;
}
skTypeface = _skFontManager.MatchFamily(familyName, fontStyle); skTypeface = _skFontManager.MatchFamily(familyName, fontStyle);
if (skTypeface is null if (skTypeface is null || defaultName.Equals(skTypeface.FamilyName, StringComparison.Ordinal))
|| (!skTypeface.FamilyName.Equals(familyName, StringComparison.Ordinal)
&& defaultName.Equals(skTypeface.FamilyName, StringComparison.Ordinal)))
{ {
continue; continue;
} }
@ -125,7 +129,10 @@ namespace Avalonia.Skia
break; break;
} }
skTypeface ??= _skFontManager.MatchTypeface(SKTypeface.Default, fontStyle); // MatchTypeface can return "null" if matched typeface wasn't found for the style
// Fallback to the default typeface and styles instead.
skTypeface ??= _skFontManager.MatchTypeface(SKTypeface.Default, fontStyle)
?? SKTypeface.Default;
} }
else else
{ {

123
src/Skia/Avalonia.Skia/SKTypefaceCollection.cs

@ -1,6 +1,4 @@
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using Avalonia.Media; using Avalonia.Media;
using SkiaSharp; using SkiaSharp;
@ -18,48 +16,131 @@ namespace Avalonia.Skia
public SKTypeface Get(Typeface typeface) public SKTypeface Get(Typeface typeface)
{ {
return GetNearestMatch(_typefaces, typeface); return GetNearestMatch(typeface);
} }
private static SKTypeface GetNearestMatch(IDictionary<Typeface, SKTypeface> typefaces, Typeface key) private SKTypeface GetNearestMatch(Typeface key)
{ {
if (typefaces.TryGetValue(key, out var typeface)) if (_typefaces.Count == 0)
{ {
return typeface; return null;
} }
var initialWeight = (int)key.Weight; if (_typefaces.TryGetValue(key, out var typeface))
{
return typeface;
}
if(key.Style != FontStyle.Normal)
{
key = new Typeface(key.FontFamily, FontStyle.Normal, key.Weight);
}
if(TryFindWeightFallback(key, out typeface))
{
return typeface;
}
//Nothing was found so we try some regular typeface.
if (_typefaces.TryGetValue(new Typeface(key.FontFamily), out typeface))
{
return typeface;
}
SKTypeface skTypeface = null;
foreach(var pair in _typefaces)
{
skTypeface = pair.Value;
if (skTypeface.FamilyName.Contains(key.FontFamily.Name))
{
return skTypeface;
}
}
return skTypeface;
}
private bool TryFindWeightFallback(Typeface key, out SKTypeface typeface)
{
typeface = null;
var weight = (int)key.Weight; var weight = (int)key.Weight;
weight -= weight % 50; // make sure we start at a full weight //If the target weight given is between 400 and 500 inclusive
if (weight >= 400 && weight <= 500)
{
//Look for available weights between the target and 500, in ascending order.
for (var i = 0; weight + i <= 500; i += 50)
{
if (_typefaces.TryGetValue(new Typeface(key.FontFamily, key.Style, (FontWeight)(weight + i)), out typeface))
{
return true;
}
}
for (var i = 0; i < 2; i++) //If no match is found, look for available weights less than the target, in descending order.
for (var i = 0; weight - i >= 100; i += 50)
{
if (_typefaces.TryGetValue(new Typeface(key.FontFamily, key.Style, (FontWeight)(weight - i)), out typeface))
{
return true;
}
}
//If no match is found, look for available weights greater than 500, in ascending order.
for (var i = 0; weight + i <= 900; i += 50)
{
if (_typefaces.TryGetValue(new Typeface(key.FontFamily, key.Style, (FontWeight)(weight + i)), out typeface))
{
return true;
}
}
}
//If a weight less than 400 is given, look for available weights less than the target, in descending order.
if (weight < 400)
{ {
for (var j = 0; j < initialWeight; j += 50) for (var i = 0; weight - i >= 100; i += 50)
{
if (_typefaces.TryGetValue(new Typeface(key.FontFamily, key.Style, (FontWeight)(weight - i)), out typeface))
{
return true;
}
}
//If no match is found, look for available weights less than the target, in descending order.
for (var i = 0; weight + i <= 900; i += 50)
{ {
if (weight - j >= 100) if (_typefaces.TryGetValue(new Typeface(key.FontFamily, key.Style, (FontWeight)(weight + i)), out typeface))
{ {
if (typefaces.TryGetValue(new Typeface(key.FontFamily, (FontStyle)i, (FontWeight)(weight - j)), out typeface)) return true;
{
return typeface;
}
} }
}
}
if (weight + j > 900) //If a weight greater than 500 is given, look for available weights greater than the target, in ascending order.
if (weight > 500)
{
for (var i = 0; weight + i <= 900; i += 50)
{
if (_typefaces.TryGetValue(new Typeface(key.FontFamily, key.Style, (FontWeight)(weight + i)), out typeface))
{ {
continue; return true;
} }
}
if (typefaces.TryGetValue(new Typeface(key.FontFamily, (FontStyle)i, (FontWeight)(weight + j)), out typeface)) //If no match is found, look for available weights less than the target, in descending order.
for (var i = 0; weight - i >= 100; i += 50)
{
if (_typefaces.TryGetValue(new Typeface(key.FontFamily, key.Style, (FontWeight)(weight - i)), out typeface))
{ {
return typeface; return true;
} }
} }
} }
//Nothing was found so we try to get a regular typeface. return false;
return typefaces.TryGetValue(new Typeface(key.FontFamily), out typeface) ? typeface : null;
} }
} }
} }

2
src/Skia/Avalonia.Skia/SKTypefaceCollectionCache.cs

@ -51,7 +51,7 @@ namespace Avalonia.Skia
if (typeface == null) if (typeface == null)
throw new InvalidOperationException("Typeface could not be loaded."); throw new InvalidOperationException("Typeface could not be loaded.");
if (typeface.FamilyName != fontFamily.Name) if (!typeface.FamilyName.Contains(fontFamily.Name))
{ {
continue; continue;
} }

Loading…
Cancel
Save