Skip to content

Commit

Permalink
Merge pull request AvaloniaUI#3202 from Gillibald/feature/GlyphRun
Browse files Browse the repository at this point in the history
GlyphRun support
  • Loading branch information
Gillibald authored Dec 6, 2019
2 parents c4708e2 + 7901f6f commit 70e6f06
Show file tree
Hide file tree
Showing 29 changed files with 1,405 additions and 7 deletions.
4 changes: 2 additions & 2 deletions build/HarfBuzzSharp.props
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<PackageReference Include="HarfBuzzSharp" Version="2.6.1-rc.153" />
<PackageReference Condition="'$(IncludeLinuxSkia)' == 'true'" Include="HarfBuzzSharp.NativeAssets.Linux" Version="2.6.1-rc.153" />
<PackageReference Include="HarfBuzzSharp" Version="2.6.1" />
<PackageReference Condition="'$(IncludeLinuxSkia)' == 'true'" Include="HarfBuzzSharp.NativeAssets.Linux" Version="2.6.1" />
</ItemGroup>
</Project>
4 changes: 2 additions & 2 deletions build/SkiaSharp.props
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<PackageReference Include="SkiaSharp" Version="1.68.1-rc.153" />
<PackageReference Condition="'$(IncludeLinuxSkia)' == 'true'" Include="SkiaSharp.NativeAssets.Linux" Version="1.68.1-rc.153" />
<PackageReference Include="SkiaSharp" Version="1.68.1" />
<PackageReference Condition="'$(IncludeLinuxSkia)' == 'true'" Include="SkiaSharp.NativeAssets.Linux" Version="1.68.1" />
</ItemGroup>
</Project>
3 changes: 3 additions & 0 deletions samples/RenderDemo/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
<TabItem Header="RenderTargetBitmap">
<pages:RenderTargetBitmapPage/>
</TabItem>
<TabItem Header="GlyphRun">
<pages:GlyphRunPage/>
</TabItem>
</TabControl>
</DockPanel>
</Window>
14 changes: 14 additions & 0 deletions samples/RenderDemo/Pages/GlyphRunPage.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="RenderDemo.Pages.GlyphRunPage">
<Border
Background="White">
<DrawingPresenter
x:Name="drawingPresenter"
Stretch="None">
</DrawingPresenter>
</Border>
</UserControl>
80 changes: 80 additions & 0 deletions samples/RenderDemo/Pages/GlyphRunPage.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.Threading;

namespace RenderDemo.Pages
{
public class GlyphRunPage : UserControl
{
private DrawingPresenter _drawingPresenter;
private GlyphTypeface _glyphTypeface = Typeface.Default.GlyphTypeface;
private readonly Random _rand = new Random();
private ushort[] _glyphIndices = new ushort[1];
private float _fontSize = 20;
private int _direction = 10;

public GlyphRunPage()
{
this.InitializeComponent();
}

private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);

_drawingPresenter = this.FindControl<DrawingPresenter>("drawingPresenter");

DispatcherTimer.Run(() =>
{
UpdateGlyphRun();
return true;
}, TimeSpan.FromSeconds(1));
}

private void UpdateGlyphRun()
{
var c = (uint)_rand.Next(65, 90);

if (_fontSize + _direction > 200)
{
_direction = -10;
}

if (_fontSize + _direction < 20)
{
_direction = 10;
}

_fontSize += _direction;

_glyphIndices[0] = _glyphTypeface.GetGlyph(c);

var scale = (double)_fontSize / _glyphTypeface.DesignEmHeight;

var drawingGroup = new DrawingGroup();

var glyphRunDrawing = new GlyphRunDrawing
{
Foreground = Brushes.Black,
GlyphRun = new GlyphRun(_glyphTypeface, _fontSize, _glyphIndices),
BaselineOrigin = new Point(0, -_glyphTypeface.Ascent * scale)
};

drawingGroup.Children.Add(glyphRunDrawing);

var geometryDrawing = new GeometryDrawing
{
Pen = new Pen(Brushes.Black),
Geometry = new RectangleGeometry { Rect = glyphRunDrawing.GlyphRun.Bounds }
};

drawingGroup.Children.Add(geometryDrawing);

_drawingPresenter.Drawing = drawingGroup;
}
}
}
68 changes: 68 additions & 0 deletions src/Avalonia.Visuals/Media/CharacterHit.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.

using System;

namespace Avalonia.Media
{
/// <summary>
/// Represents information about a character hit within a glyph run.
/// </summary>
/// <remarks>
/// The CharacterHit structure provides information about the index of the first
/// character that got hit as well as information about leading or trailing edge.
/// </remarks>
public readonly struct CharacterHit : IEquatable<CharacterHit>
{
/// <summary>
/// Initializes a new instance of the <see cref="CharacterHit"/> structure.
/// </summary>
/// <param name="firstCharacterIndex">Index of the first character that got hit.</param>
/// <param name="trailingLength">In the case of a leading edge, this value is 0. In the case of a trailing edge,
/// this value is the number of code points until the next valid caret position.</param>
public CharacterHit(int firstCharacterIndex, int trailingLength = 0)
{
FirstCharacterIndex = firstCharacterIndex;

TrailingLength = trailingLength;
}

/// <summary>
/// Gets the index of the first character that got hit.
/// </summary>
public int FirstCharacterIndex { get; }

/// <summary>
/// Gets the trailing length value for the character that got hit.
/// </summary>
public int TrailingLength { get; }

public bool Equals(CharacterHit other)
{
return FirstCharacterIndex == other.FirstCharacterIndex && TrailingLength == other.TrailingLength;
}

public override bool Equals(object obj)
{
return obj is CharacterHit other && Equals(other);
}

public override int GetHashCode()
{
unchecked
{
return FirstCharacterIndex * 397 ^ TrailingLength;
}
}

public static bool operator ==(CharacterHit left, CharacterHit right)
{
return left.Equals(right);
}

public static bool operator !=(CharacterHit left, CharacterHit right)
{
return !left.Equals(right);
}
}
}
16 changes: 16 additions & 0 deletions src/Avalonia.Visuals/Media/DrawingContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,22 @@ public void DrawText(IBrush foreground, Point origin, FormattedText text)
}
}

/// <summary>
/// Draws a glyph run.
/// </summary>
/// <param name="foreground">The foreground brush.</param>
/// <param name="glyphRun">The glyph run.</param>
/// <param name="baselineOrigin">The baseline origin of the glyph run.</param>
public void DrawGlyphRun(IBrush foreground, GlyphRun glyphRun, Point baselineOrigin)
{
Contract.Requires<ArgumentNullException>(glyphRun != null);

if (foreground != null)
{
PlatformImpl.DrawGlyphRun(foreground, glyphRun, baselineOrigin);
}
}

/// <summary>
/// Draws a filled rectangle.
/// </summary>
Expand Down
Loading

0 comments on commit 70e6f06

Please sign in to comment.