Browse Source

Fixed `Path_Tick_Scaled`, `Path_Tick_Scaled_Stroke_8px` and `Path_Expander_With_Border` for Skia

pull/398/head
Nikita Tsukanov 10 years ago
parent
commit
a74e9b3ff7
  1. 16
      src/Skia/Perspex.Skia/DrawingContextImpl.cs
  2. 35
      src/Skia/Perspex.Skia/MethodTable.cs
  3. 59
      src/Skia/Perspex.Skia/PerspexHandleHolder.cs
  4. 40
      src/Skia/Perspex.Skia/StreamGeometryImpl.cs
  5. 12
      tests/Perspex.RenderTests/Shapes/PathTests.cs

16
src/Skia/Perspex.Skia/DrawingContextImpl.cs

@ -37,18 +37,13 @@ namespace Perspex.Skia
public void DrawGeometry(Brush brush, Pen pen, Geometry geometry)
{
var impl = ((StreamGeometryImpl) geometry.PlatformImpl);
var oldTransform = Transform;
if (!impl.Transform.IsIdentity)
Transform = impl.Transform*Transform;
var size = geometry.Bounds.Size;
using(var fill = brush!=null?CreateBrush(brush, size):null)
using (var stroke = pen?.Brush != null ? CreateBrush(pen, size) : null)
{
MethodTable.Instance.DrawGeometry(Handle, impl.Path.Handle, fill != null ? fill.Brush : null,
MethodTable.Instance.DrawGeometry(Handle, impl.EffectivePath, fill != null ? fill.Brush : null,
stroke != null ? stroke.Brush : null, impl.FillRule == FillRule.EvenOdd);
}
Transform = oldTransform;
}
unsafe NativeBrushContainer CreateBrush(Brush brush, Size targetSize)
@ -196,14 +191,7 @@ namespace Perspex.Skia
if(_currentTransform == value)
return;
_currentTransform = value;
_fmatrix[0] = (float)value.M11;
_fmatrix[1] = (float)value.M21;
_fmatrix[2] = (float)value.M31;
_fmatrix[3] = (float)value.M12;
_fmatrix[4] = (float)value.M22;
_fmatrix[5] = (float)value.M32;
MethodTable.Instance.SetTransform(Handle, _fmatrix);
MethodTable.Instance.SetTransform(Handle, value);
}
}
}

35
src/Skia/Perspex.Skia/MethodTable.cs

@ -47,9 +47,9 @@ namespace Perspex.Skia
public _PopClip PopClip;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void _SetTransform(IntPtr ctx, float[] matrix6);
public delegate void _SetTransform(IntPtr ctx, void* matrix6);
public _SetTransform SetTransform;
public _SetTransform SetTransformNative;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void _DrawLine(IntPtr ctx, void* brush, float x1, float y1, float x2, float y2);
@ -66,6 +66,11 @@ namespace Perspex.Skia
public _DisposePath DisposePath;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate IntPtr _TransformPath(IntPtr path, void* matrix6);
public _TransformPath TransformPathNative;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void _DrawGeometry(IntPtr ctx, IntPtr path, void* fill, void* stroke, bool useEvenOdd);
@ -185,10 +190,34 @@ namespace Perspex.Skia
typeof (_RebuildFormattedText),
typeof (_DestroyFormattedText),
typeof (_DrawFormattedText),
typeof (_SetOption)
typeof (_SetOption),
typeof (_TransformPath)
};
void ConvertMatrix(Matrix value, float* target)
{
target[0] = (float)value.M11;
target[1] = (float)value.M21;
target[2] = (float)value.M31;
target[3] = (float)value.M12;
target[4] = (float)value.M22;
target[5] = (float)value.M32;
}
public unsafe IntPtr TransformPath(IntPtr path, Matrix matrix)
{
var tmp = stackalloc float[6];
ConvertMatrix(matrix, tmp);
return TransformPathNative(path, tmp);
}
public unsafe void SetTransform(IntPtr ctx, Matrix matrix)
{
var tmp = stackalloc float[6];
ConvertMatrix(matrix, tmp);
SetTransformNative(ctx, tmp);
}
protected MethodTable(IntPtr methodTable)
{

59
src/Skia/Perspex.Skia/PerspexHandleHolder.cs

@ -44,4 +44,63 @@ namespace Perspex.Skia
Dispose();
}
}
class RefCountable<T> : IDisposable where T : PerspexHandleHolder
{
class Shared
{
public readonly T Target;
private int _refCount = 1;
public Shared(T target)
{
Target = target;
}
public void AddRef() => _refCount++;
public void Release()
{
_refCount--;
if (_refCount <= 0)
Target.Dispose();
}
}
public bool IsDisposed => _shared == null;
private Shared _shared;
public void CheckDisposed()
{
if (IsDisposed)
throw new ObjectDisposedException(GetType().FullName);
}
public IntPtr Handle
{
get
{
CheckDisposed();
return _shared.Target.Handle;
}
}
public RefCountable(T handle)
{
_shared = new Shared(handle);
}
public RefCountable(RefCountable<T> other)
{
other._shared.Target.CheckDisposed();
other._shared.AddRef();
_shared = other._shared;
}
public RefCountable<T> Clone() => new RefCountable<T>(this);
public void Dispose()
{
_shared?.Release();
_shared = null;
}
}
}

40
src/Skia/Perspex.Skia/StreamGeometryImpl.cs

@ -41,7 +41,11 @@ namespace Perspex.Skia
class StreamGeometryImpl : IStreamGeometryImpl
{
public SkPath Path;
RefCountable<SkPath> _path;
RefCountable<SkPath> _transformedPath;
private Matrix _transform = Matrix.Identity;
public IntPtr EffectivePath => (_transformedPath ?? _path).Handle;
public Rect GetRenderBounds(double strokeThickness)
{
@ -51,11 +55,35 @@ namespace Perspex.Skia
public Rect Bounds { get; private set; }
public Matrix Transform { get; set; } = Matrix.Identity;
public Matrix Transform
{
get { return _transform; }
set
{
if(_transform == value)
return;
_transform = value;
ApplyTransform();
}
}
void ApplyTransform()
{
if(_path == null)
return;
if (_transformedPath != null)
{
_transformedPath.Dispose();
_transformedPath = null;
}
if (!_transform.IsIdentity)
_transformedPath =
new RefCountable<SkPath>(new SkPath(MethodTable.Instance.TransformPath(_path.Handle, Transform)));
}
public IStreamGeometryImpl Clone()
{
return new StreamGeometryImpl() {Path = Path, Transform = Transform, Bounds = Bounds};
return new StreamGeometryImpl {_path = _path?.Clone(), _transformedPath = _transformedPath?.Clone(), _transform = Transform, Bounds = Bounds};
}
public IStreamGeometryContextImpl Open()
@ -77,7 +105,11 @@ namespace Perspex.Skia
{
var arr = _elements.ToArray();
SkRect rc;
_geometryImpl.Path = new SkPath(MethodTable.Instance.CreatePath(arr, arr.Length, out rc));
_geometryImpl._path?.Dispose();
_geometryImpl._path =
new RefCountable<SkPath>(new SkPath(MethodTable.Instance.CreatePath(arr, arr.Length, out rc)));
_geometryImpl.ApplyTransform();
_geometryImpl.Bounds = rc.ToRect();
}

12
tests/Perspex.RenderTests/Shapes/PathTests.cs

@ -46,11 +46,7 @@ namespace Perspex.Direct2D1.RenderTests.Shapes
CompareImages();
}
#if PERSPEX_SKIA
[Fact(Skip = "FIXME")]
#else
[Fact]
#endif
public void Path_Tick_Scaled()
{
Decorator target = new Decorator
@ -73,11 +69,7 @@ namespace Perspex.Direct2D1.RenderTests.Shapes
CompareImages();
}
#if PERSPEX_SKIA
[Fact(Skip = "FIXME")]
#else
[Fact]
#endif
public void Path_Tick_Scaled_Stroke_8px()
{
Decorator target = new Decorator
@ -100,11 +92,7 @@ namespace Perspex.Direct2D1.RenderTests.Shapes
CompareImages();
}
#if PERSPEX_SKIA
[Fact(Skip = "FIXME")]
#else
[Fact]
#endif
public void Path_Expander_With_Border()
{
Decorator target = new Decorator

Loading…
Cancel
Save