From a3d4977a3cb6d7e4ce4f9627842398e6ab25d9a8 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jean-Philippe=20Bruy=C3=A8re?= Date: Fri, 26 Nov 2021 13:18:02 +0100 Subject: [PATCH] skia backend wip, glfw win created in backends if null, wip --- Backends/CairoBackend/src/CairoBackendBase.cs | 7 +- Backends/CairoBackend/src/Context.cs | 116 +++------- Backends/CairoBackend/src/DefaultBackend.cs | 4 +- Backends/CairoBackend/src/EglBackend.cs | 24 +- Backends/CairoBackend/src/GLSurface.cs | 2 +- Backends/CairoBackend/src/ImageBackend.cs | 18 +- Backends/CairoBackend/src/ImageSurface.cs | 12 +- Backends/CairoBackend/src/PSSurface.cs | 8 +- Backends/CairoBackend/src/Pattern.cs | 3 +- Backends/CairoBackend/src/PdfSurface.cs | 2 +- Backends/CairoBackend/src/Surface.cs | 15 +- Backends/CairoBackend/src/SurfacePattern.cs | 2 +- Backends/CairoBackend/src/SvgSurface.cs | 2 +- Backends/CairoBackend/src/XcbSurface.cs | 2 +- Backends/CairoBackend/src/XlibSurface.cs | 18 +- Backends/CairoBackend/src/rsvg/SvgHandle.cs | 4 +- Backends/SkiaBackend/SkiaBackend.csproj | 5 +- Backends/SkiaBackend/src/Context.cs | 97 ++++---- Backends/SkiaBackend/src/DefaultBackend.cs | 4 +- Backends/SkiaBackend/src/Extensions.cs | 15 ++ Backends/SkiaBackend/src/Gradient.cs | 93 ++++++++ Backends/SkiaBackend/src/Surface.cs | 2 +- Backends/SkiaBackend/src/SvgHandle.cs | 52 +++++ Backends/SkiaBackend/src/VulkanBackend.cs | 50 +++- Backends/VkvgBackend/src/Context.cs | 219 +++++------------- Backends/VkvgBackend/src/DefaultBackend.cs | 24 +- Backends/VkvgBackend/src/Pattern.cs | 6 +- Backends/VkvgBackend/src/Surface.cs | 4 +- Backends/VkvgBackend/src/SvgHandle.cs | 10 +- Crow/Crow.csproj | 4 +- Crow/src/Interface.cs | 39 +--- Crow/src/Widgets/Widget.cs | 3 +- Drawing2D/src/IContext.cs | 4 +- Drawing2D/src/IPattern.cs | 1 - Drawing2D/src/ISurface.cs | 1 - Samples/PerfTests/Program.cs | 7 +- 36 files changed, 449 insertions(+), 430 deletions(-) create mode 100644 Backends/SkiaBackend/src/Extensions.cs create mode 100644 Backends/SkiaBackend/src/Gradient.cs create mode 100644 Backends/SkiaBackend/src/SvgHandle.cs diff --git a/Backends/CairoBackend/src/CairoBackendBase.cs b/Backends/CairoBackend/src/CairoBackendBase.cs index 535bb31d..1e1b2e82 100644 --- a/Backends/CairoBackend/src/CairoBackendBase.cs +++ b/Backends/CairoBackend/src/CairoBackendBase.cs @@ -6,7 +6,8 @@ using Glfw; namespace Crow.CairoBackend { public abstract class CairoBackendBase : IBackend { - protected ISurface surf; + protected IntPtr hWin; + protected Surface surf; /// Global font rendering settings for Cairo FontOptions FontRenderingOptions; /// Global font rendering settings for Cairo @@ -29,7 +30,7 @@ namespace Crow.CairoBackend public IRegion CreateRegion () => new Region (); public IContext CreateContext (ISurface surf) { - Context gr = new Context (surf); + Context gr = new Context (surf as Surface); gr.FontOptions = FontRenderingOptions; gr.Antialias = Antialias; return gr; @@ -102,7 +103,7 @@ namespace Crow.CairoBackend IContext ctx = existingContext; if (ctx == null) { disposeContextOnFlush = true; - ctx = new Context (MainSurface); + ctx = new Context (surf); } else disposeContextOnFlush = false; return ctx; diff --git a/Backends/CairoBackend/src/Context.cs b/Backends/CairoBackend/src/Context.cs index a4eac7a2..c15ecaa3 100644 --- a/Backends/CairoBackend/src/Context.cs +++ b/Backends/CairoBackend/src/Context.cs @@ -43,7 +43,7 @@ namespace Crow.CairoBackend { public class Context : IContext { - IntPtr handle = IntPtr.Zero; + internal IntPtr handle = IntPtr.Zero; static int native_glyph_size, c_compiler_long_size; @@ -75,12 +75,12 @@ namespace Crow.CairoBackend } } - public Context (ISurface surface) : this (NativeMethods.cairo_create (surface.Handle), true) + internal Context (Surface surface) : this (NativeMethods.cairo_create (surface.handle), true) { } - public Context (IntPtr handle, bool owner) + internal Context (IntPtr handle, bool owner) { this.handle = handle; if (!owner) @@ -90,7 +90,7 @@ namespace Crow.CairoBackend } [Obsolete] - public Context (IntPtr state) : this (state, true) + internal Context (IntPtr state) : this (state, true) { } @@ -144,8 +144,6 @@ namespace Crow.CairoBackend } } - public IntPtr Handle => handle; - public Operator Operator { set => NativeMethods.cairo_set_operator (handle, value); get => NativeMethods.cairo_get_operator (handle); @@ -163,71 +161,29 @@ namespace Crow.CairoBackend get => NativeMethods.cairo_get_line_width (handle); } public LineCap LineCap { - set { - NativeMethods.cairo_set_line_cap (handle, value); - } - - get { - return NativeMethods.cairo_get_line_cap (handle); - } + set => NativeMethods.cairo_set_line_cap (handle, value); + get => NativeMethods.cairo_get_line_cap (handle); } - public LineJoin LineJoin { - set { - NativeMethods.cairo_set_line_join (handle, value); - } - - get { - return NativeMethods.cairo_get_line_join (handle); - } + set => NativeMethods.cairo_set_line_join (handle, value); + get => NativeMethods.cairo_get_line_join (handle); } - - public void SetDash (double [] dashes, double offset = 0) - { - NativeMethods.cairo_set_dash (handle, dashes, dashes.Length, offset); - } - - [Obsolete("Use GetSource/SetSource")] - public Pattern Pattern { - set { - SetSource (value); - } - get { - return GetSource (); - } + public double MiterLimit { + set => NativeMethods.cairo_set_miter_limit (handle, value); + get => NativeMethods.cairo_get_miter_limit (handle); } - //This is obsolete because it wasn't obvious it needed to be disposed - [Obsolete("Use GetSource/SetSource")] - public Pattern Source { - set { - SetSource (value); - } - get { - return GetSource (); - } - } + public void SetDash (double [] dashes, double offset = 0) + => NativeMethods.cairo_set_dash (handle, dashes, dashes.Length, offset); public void SetSource (Pattern source) - { - NativeMethods.cairo_set_source (handle, source.handle); - } - + => NativeMethods.cairo_set_source (handle, source.handle); public Pattern GetSource () { var ptr = NativeMethods.cairo_get_source (handle); return Pattern.Lookup (ptr, false); } - public double MiterLimit { - set { - NativeMethods.cairo_set_miter_limit (handle, value); - } - - get { - return NativeMethods.cairo_get_miter_limit (handle); - } - } public PointD CurrentPoint { get { @@ -237,17 +193,13 @@ namespace Crow.CairoBackend } } - public bool HasCurrentPoint { - get { - return NativeMethods.cairo_has_current_point (handle); - } - } + public bool HasCurrentPoint => NativeMethods.cairo_has_current_point (handle); public Surface GetTarget () => Surface.Lookup (NativeMethods.cairo_get_target (handle), false); public void SetTarget (Surface target) { if (handle != IntPtr.Zero) NativeMethods.cairo_destroy (handle); - handle = NativeMethods.cairo_create (target.Handle); + handle = NativeMethods.cairo_create (target.handle); } public ScaledFont GetScaledFont () => new ScaledFont (NativeMethods.cairo_get_scaled_font (handle), false); @@ -269,17 +221,17 @@ namespace Crow.CairoBackend //[Obsolete ("Use SetSource method (with double parameters)")] public void SetSource (Surface source, int x = 0, int y = 0) { - NativeMethods.cairo_set_source_surface (handle, source.Handle, x, y); + NativeMethods.cairo_set_source_surface (handle, source.handle, x, y); } public void SetSource (Surface source, double x, double y) { - NativeMethods.cairo_set_source_surface (handle, source.Handle, x, y); + NativeMethods.cairo_set_source_surface (handle, source.handle, x, y); } public void SetSource (Surface source) { - NativeMethods.cairo_set_source_surface (handle, source.Handle, 0, 0); + NativeMethods.cairo_set_source_surface (handle, source.handle, 0, 0); } #region Path methods @@ -327,7 +279,7 @@ namespace Crow.CairoBackend public void PaintWithAlpha (double alpha) => NativeMethods.cairo_paint_with_alpha (handle, alpha); public void Mask (Pattern pattern) => NativeMethods.cairo_mask (handle, pattern.handle); public void MaskSurface (Surface surface, double surface_x, double surface_y) - => NativeMethods.cairo_mask_surface (handle, surface.Handle, surface_x, surface_y); + => NativeMethods.cairo_mask_surface (handle, surface.handle, surface_x, surface_y); public void Stroke () => NativeMethods.cairo_stroke (handle); public void StrokePreserve () => NativeMethods.cairo_stroke_preserve (handle); public Rectangle StrokeExtents () @@ -564,21 +516,11 @@ namespace Crow.CairoBackend } public void ShowText(string str) - { - NativeMethods.cairo_show_text (handle, TerminateUtf8 (str)); - } - - + => NativeMethods.cairo_show_text (handle, TerminateUtf8 (str)); public void TextPath(string str) - { - NativeMethods.cairo_text_path (handle, TerminateUtf8(str)); - } - + => NativeMethods.cairo_text_path (handle, TerminateUtf8(str)); public void TextPath(byte[] utf8) - { - NativeMethods.cairo_text_path (handle, TerminateUtf8(utf8)); - } - + => NativeMethods.cairo_text_path (handle, TerminateUtf8(utf8)); public TextExtents TextExtents(string s) { TextExtents extents; @@ -625,7 +567,7 @@ namespace Crow.CairoBackend public void Flush() { - throw new NotImplementedException(); + //throw new NotImplementedException(); } public void Clear() @@ -711,17 +653,15 @@ namespace Crow.CairoBackend { throw new NotImplementedException(); } - public void RenderSvg(IntPtr svgNativeHandle, string subId = null) - { - throw new NotImplementedException(); - } + public void RenderSvg(ISvgHandle svg, string subId = null) + => svg.Render (this, subId); Matrix savedMat; public void SaveTransformations() => NativeMethods.cairo_get_matrix (handle, out savedMat); public void RestoreTransformations() => NativeMethods.cairo_set_matrix (handle, ref savedMat); - public void SetSource(IPattern pat) => NativeMethods.cairo_set_source (handle, pat.Handle); + public void SetSource(IPattern pat) => NativeMethods.cairo_set_source (handle, (pat as Pattern).handle); public void SetSource(ISurface surf, double x = 0, double y = 0) - => NativeMethods.cairo_set_source_surface (handle, surf.Handle, x, y); + => NativeMethods.cairo_set_source_surface (handle, (surf as Surface).handle, x, y); } } diff --git a/Backends/CairoBackend/src/DefaultBackend.cs b/Backends/CairoBackend/src/DefaultBackend.cs index 2adb70a2..7f805063 100644 --- a/Backends/CairoBackend/src/DefaultBackend.cs +++ b/Backends/CairoBackend/src/DefaultBackend.cs @@ -9,8 +9,8 @@ namespace Crow.Backends /// /// backend surface width /// backend surface height - public DefaultBackend (IntPtr nativeWindoPointer, int width, int height) - : base (nativeWindoPointer, width, height) { } + public DefaultBackend (ref IntPtr nativeWindoPointer, out bool ownGlfwWinHandle, int width, int height) + : base (ref nativeWindoPointer, out ownGlfwWinHandle, width, height) { } public DefaultBackend (int width, int height) : base (width, height) { } diff --git a/Backends/CairoBackend/src/EglBackend.cs b/Backends/CairoBackend/src/EglBackend.cs index 51318a39..38f13a2e 100644 --- a/Backends/CairoBackend/src/EglBackend.cs +++ b/Backends/CairoBackend/src/EglBackend.cs @@ -6,15 +6,33 @@ using Glfw; namespace Crow.CairoBackend { public class EglBackend : CairoBackendBase { - IntPtr hWin; EGLDevice device; /// /// Create a new generic backend bound to the application surface /// /// backend surface width /// backend surface height - public EglBackend (IntPtr nativeWindoPointer, int width, int height) : base () { - hWin = nativeWindoPointer; + public EglBackend (ref IntPtr nativeWindoPointer, out bool ownGlfwWinHandle, int width, int height) : base () { + if (nativeWindoPointer == IntPtr.Zero) { + Glfw3.Init (); + Glfw3.WindowHint (WindowAttribute.ClientApi, Constants.OpenglEsApi); + Glfw3.WindowHint (WindowAttribute.ContextVersionMajor, 3); + Glfw3.WindowHint (WindowAttribute.ContextVersionMinor, 2); + Glfw3.WindowHint (WindowAttribute.ContextCreationApi, Constants.EglContextApi); + Glfw3.WindowHint (WindowAttribute.Resizable, 1); + Glfw3.WindowHint (WindowAttribute.Decorated, 1); + + hWin = Glfw3.CreateWindow (width, height, "win name", MonitorHandle.Zero, IntPtr.Zero); + if (hWin == IntPtr.Zero) + throw new Exception ("[GLFW3] Unable to create Window"); + + nativeWindoPointer = hWin; + ownGlfwWinHandle = true; + } else { + hWin = nativeWindoPointer; + ownGlfwWinHandle = false; + } + Glfw3.MakeContextCurrent (hWin); Glfw3.SwapInterval (0); diff --git a/Backends/CairoBackend/src/GLSurface.cs b/Backends/CairoBackend/src/GLSurface.cs index 20d5b525..4fa262cc 100644 --- a/Backends/CairoBackend/src/GLSurface.cs +++ b/Backends/CairoBackend/src/GLSurface.cs @@ -89,7 +89,7 @@ namespace Crow.CairoBackend { => NativeMethods.cairo_gl_surface_set_size(handle, width, height); public void SwapBuffers(){ - NativeMethods.cairo_gl_surface_swapbuffers (this.Handle); + NativeMethods.cairo_gl_surface_swapbuffers (this.handle); } } } diff --git a/Backends/CairoBackend/src/ImageBackend.cs b/Backends/CairoBackend/src/ImageBackend.cs index fa9b009e..0181451a 100644 --- a/Backends/CairoBackend/src/ImageBackend.cs +++ b/Backends/CairoBackend/src/ImageBackend.cs @@ -11,7 +11,23 @@ namespace Crow.CairoBackend /// /// backend surface width /// backend surface height - public ImageBackend (IntPtr nativeWindoPointer, int width, int height) : base () { + public ImageBackend (ref IntPtr nativeWindoPointer, out bool ownGlfwWinHandle, int width, int height) : base () { + if (nativeWindoPointer == IntPtr.Zero) { + Glfw3.Init (); + Glfw3.WindowHint (WindowAttribute.ClientApi, 0); + Glfw3.WindowHint (WindowAttribute.Resizable, 1); + Glfw3.WindowHint (WindowAttribute.Decorated, 1); + + hWin = Glfw3.CreateWindow (width, height, "win name", MonitorHandle.Zero, IntPtr.Zero); + if (hWin == IntPtr.Zero) + throw new Exception ("[GLFW3] Unable to create Window"); + + nativeWindoPointer = hWin; + ownGlfwWinHandle = true; + } else { + hWin = nativeWindoPointer; + ownGlfwWinHandle = false; + } switch (Environment.OSVersion.Platform) { case PlatformID.Unix: diff --git a/Backends/CairoBackend/src/ImageSurface.cs b/Backends/CairoBackend/src/ImageSurface.cs index c2e5dec9..2cfec61c 100644 --- a/Backends/CairoBackend/src/ImageSurface.cs +++ b/Backends/CairoBackend/src/ImageSurface.cs @@ -70,12 +70,12 @@ namespace Crow.CairoBackend { { } - public override int Width => NativeMethods.cairo_image_surface_get_width (Handle); - public override int Height => NativeMethods.cairo_image_surface_get_height (Handle); + public override int Width => NativeMethods.cairo_image_surface_get_width (handle); + public override int Height => NativeMethods.cairo_image_surface_get_height (handle); public byte[] Data { get { - IntPtr ptr = NativeMethods.cairo_image_surface_get_data (Handle); + IntPtr ptr = NativeMethods.cairo_image_surface_get_data (handle); int length = Height * Stride; byte[] data = new byte[length]; Marshal.Copy (ptr, data, 0, length); @@ -85,16 +85,16 @@ namespace Crow.CairoBackend { public IntPtr DataPtr { get { - return NativeMethods.cairo_image_surface_get_data (Handle); + return NativeMethods.cairo_image_surface_get_data (handle); } } public Format Format { - get { return NativeMethods.cairo_image_surface_get_format (Handle); } + get { return NativeMethods.cairo_image_surface_get_format (handle); } } public int Stride { - get { return NativeMethods.cairo_image_surface_get_stride (Handle); } + get { return NativeMethods.cairo_image_surface_get_stride (handle); } } } } diff --git a/Backends/CairoBackend/src/PSSurface.cs b/Backends/CairoBackend/src/PSSurface.cs index fadb1b2e..695b05de 100644 --- a/Backends/CairoBackend/src/PSSurface.cs +++ b/Backends/CairoBackend/src/PSSurface.cs @@ -43,22 +43,22 @@ namespace Crow.CairoBackend { public void BeginPageSetup () { - NativeMethods.cairo_ps_surface_dsc_begin_page_setup (Handle); + NativeMethods.cairo_ps_surface_dsc_begin_page_setup (handle); } public void BeginSetup () { - NativeMethods.cairo_ps_surface_dsc_begin_setup (Handle); + NativeMethods.cairo_ps_surface_dsc_begin_setup (handle); } public void DscComment (string comment) { - NativeMethods.cairo_ps_surface_dsc_comment (Handle, comment); + NativeMethods.cairo_ps_surface_dsc_comment (handle, comment); } public void SetSize (double width, double height) { - NativeMethods.cairo_ps_surface_set_size (Handle, width, height); + NativeMethods.cairo_ps_surface_set_size (handle, width, height); } } } diff --git a/Backends/CairoBackend/src/Pattern.cs b/Backends/CairoBackend/src/Pattern.cs index 137f67fe..3de491ec 100644 --- a/Backends/CairoBackend/src/Pattern.cs +++ b/Backends/CairoBackend/src/Pattern.cs @@ -35,7 +35,6 @@ namespace Crow.CairoBackend public class Pattern : IPattern { internal IntPtr handle; - public IntPtr Handle => handle; public static Pattern Lookup (IntPtr pattern, bool owner) { if (pattern == IntPtr.Zero) @@ -67,7 +66,7 @@ namespace Crow.CairoBackend [Obsolete ("Use the SurfacePattern constructor")] public Pattern (Surface surface) - : this ( NativeMethods.cairo_pattern_create_for_surface (surface.Handle), true) + : this ( NativeMethods.cairo_pattern_create_for_surface (surface.handle), true) { } diff --git a/Backends/CairoBackend/src/PdfSurface.cs b/Backends/CairoBackend/src/PdfSurface.cs index 676b596b..061eaa4f 100644 --- a/Backends/CairoBackend/src/PdfSurface.cs +++ b/Backends/CairoBackend/src/PdfSurface.cs @@ -43,7 +43,7 @@ namespace Crow.CairoBackend { public void SetSize (double width, double height) { - NativeMethods.cairo_pdf_surface_set_size (Handle, width, height); + NativeMethods.cairo_pdf_surface_set_size (handle, width, height); } } } diff --git a/Backends/CairoBackend/src/Surface.cs b/Backends/CairoBackend/src/Surface.cs index b09ff5e9..80435b5e 100644 --- a/Backends/CairoBackend/src/Surface.cs +++ b/Backends/CairoBackend/src/Surface.cs @@ -40,7 +40,7 @@ namespace Crow.CairoBackend { public class Surface : ISurface { - protected IntPtr handle = IntPtr.Zero; + internal IntPtr handle = IntPtr.Zero; protected Surface() { @@ -112,7 +112,7 @@ namespace Crow.CairoBackend { public ISurface CreateSimilar (int width, int height) { IntPtr p = NativeMethods.cairo_surface_create_similar ( - this.Handle, Content.ColorAlpha, width, height); + this.handle, Content.ColorAlpha, width, height); return Surface.Lookup(p, true); } @@ -156,22 +156,15 @@ namespace Crow.CairoBackend { public void MarkDirty () { - NativeMethods.cairo_surface_mark_dirty (Handle); + NativeMethods.cairo_surface_mark_dirty (handle); } public void MarkDirty (Rectangle rectangle) { - NativeMethods.cairo_surface_mark_dirty_rectangle (Handle, rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height); + NativeMethods.cairo_surface_mark_dirty_rectangle (handle, rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height); } public virtual int Width => NativeMethods.cairo_image_surface_get_width (handle); public virtual int Height => NativeMethods.cairo_image_surface_get_height (handle); - - public IntPtr Handle { - get { - return handle; - } - } - public PointD DeviceOffset { get { double x, y; diff --git a/Backends/CairoBackend/src/SurfacePattern.cs b/Backends/CairoBackend/src/SurfacePattern.cs index 83b98a8c..85a31348 100644 --- a/Backends/CairoBackend/src/SurfacePattern.cs +++ b/Backends/CairoBackend/src/SurfacePattern.cs @@ -39,7 +39,7 @@ namespace Crow.CairoBackend { } public SurfacePattern (Surface surface) - : base (NativeMethods.cairo_pattern_create_for_surface (surface.Handle), true) + : base (NativeMethods.cairo_pattern_create_for_surface (surface.handle), true) { } diff --git a/Backends/CairoBackend/src/SvgSurface.cs b/Backends/CairoBackend/src/SvgSurface.cs index 3eca6682..d6d53c33 100644 --- a/Backends/CairoBackend/src/SvgSurface.cs +++ b/Backends/CairoBackend/src/SvgSurface.cs @@ -43,7 +43,7 @@ namespace Crow.CairoBackend { public void RestrictToVersion (SvgVersion version) { - NativeMethods.cairo_svg_surface_restrict_to_version (Handle, version); + NativeMethods.cairo_svg_surface_restrict_to_version (handle, version); } } } diff --git a/Backends/CairoBackend/src/XcbSurface.cs b/Backends/CairoBackend/src/XcbSurface.cs index bb198a71..ed557d0c 100644 --- a/Backends/CairoBackend/src/XcbSurface.cs +++ b/Backends/CairoBackend/src/XcbSurface.cs @@ -47,7 +47,7 @@ namespace Crow.CairoBackend { } public override void Resize (int width, int height) { - NativeMethods.cairo_xcb_surface_set_size (Handle, width, height); + NativeMethods.cairo_xcb_surface_set_size (handle, width, height); } } } diff --git a/Backends/CairoBackend/src/XlibSurface.cs b/Backends/CairoBackend/src/XlibSurface.cs index df4b2619..6aea448b 100644 --- a/Backends/CairoBackend/src/XlibSurface.cs +++ b/Backends/CairoBackend/src/XlibSurface.cs @@ -57,21 +57,21 @@ namespace Crow.CairoBackend { public void SetDrawable (IntPtr drawable, int width, int height) { - NativeMethods.cairo_xlib_surface_set_drawable (Handle, drawable, width, height); + NativeMethods.cairo_xlib_surface_set_drawable (handle, drawable, width, height); } public override void Resize (int width, int height) { - NativeMethods.cairo_xlib_surface_set_size (Handle, width, height); + NativeMethods.cairo_xlib_surface_set_size (handle, width, height); } - public int Depth => NativeMethods.cairo_xlib_surface_get_depth (Handle); - public IntPtr Display => NativeMethods.cairo_xlib_surface_get_display (Handle); - public IntPtr Drawable => NativeMethods.cairo_xlib_surface_get_drawable (Handle); - public override int Width => NativeMethods.cairo_xlib_surface_get_width (Handle); - public override int Height => NativeMethods.cairo_xlib_surface_get_height (Handle); + public int Depth => NativeMethods.cairo_xlib_surface_get_depth (handle); + public IntPtr Display => NativeMethods.cairo_xlib_surface_get_display (handle); + public IntPtr Drawable => NativeMethods.cairo_xlib_surface_get_drawable (handle); + public override int Width => NativeMethods.cairo_xlib_surface_get_width (handle); + public override int Height => NativeMethods.cairo_xlib_surface_get_height (handle); - public IntPtr Screen => NativeMethods.cairo_xlib_surface_get_screen (Handle); - public IntPtr Visual=> NativeMethods.cairo_xlib_surface_get_visual (Handle); + public IntPtr Screen => NativeMethods.cairo_xlib_surface_get_screen (handle); + public IntPtr Visual=> NativeMethods.cairo_xlib_surface_get_visual (handle); } } diff --git a/Backends/CairoBackend/src/rsvg/SvgHandle.cs b/Backends/CairoBackend/src/rsvg/SvgHandle.cs index 6db657fd..e767ce3a 100644 --- a/Backends/CairoBackend/src/rsvg/SvgHandle.cs +++ b/Backends/CairoBackend/src/rsvg/SvgHandle.cs @@ -59,10 +59,10 @@ namespace Crow.CairoBackend { public void Render(IContext cr) => - rsvg_handle_render_cairo (Raw, cr == null ? IntPtr.Zero : cr.Handle); + rsvg_handle_render_cairo (Raw, cr == null ? IntPtr.Zero : (cr as Context).handle); public void Render (IContext cr, string id) => - rsvg_handle_render_cairo_sub (Raw, cr == null ? IntPtr.Zero : cr.Handle, id); + rsvg_handle_render_cairo_sub (Raw, cr == null ? IntPtr.Zero : (cr as Context).handle, id); [StructLayout(LayoutKind.Sequential)] struct DimensionData { diff --git a/Backends/SkiaBackend/SkiaBackend.csproj b/Backends/SkiaBackend/SkiaBackend.csproj index f86af042..4be73596 100644 --- a/Backends/SkiaBackend/SkiaBackend.csproj +++ b/Backends/SkiaBackend/SkiaBackend.csproj @@ -10,9 +10,10 @@ - + + - + diff --git a/Backends/SkiaBackend/src/Context.cs b/Backends/SkiaBackend/src/Context.cs index a4e34c33..837e715b 100644 --- a/Backends/SkiaBackend/src/Context.cs +++ b/Backends/SkiaBackend/src/Context.cs @@ -13,7 +13,7 @@ namespace Crow.SkiaBackend public class Context : IContext { VkSurface surf; - SKCanvas canvas; + internal SKCanvas canvas; SKPaint paint; SKPath path; FillRule fillRule = FillRule.NonZero; @@ -70,8 +70,10 @@ namespace Crow.SkiaBackend SKBlendMode.Darken, SKBlendMode.Lighten }; + internal Context (VkSurface surf) { + this.surf = surf; canvas = surf.Canvas; paint = new SKPaint (); } @@ -80,8 +82,6 @@ namespace Crow.SkiaBackend Dispose(false); } - public IntPtr Handle => throw new NotImplementedException(); - public double LineWidth { get => (float)paint.StrokeWidth; set => paint.StrokeWidth = (float)value; @@ -108,7 +108,7 @@ namespace Crow.SkiaBackend if (font == null) createDefaultFont (); paint.GetFontMetrics (out SKFontMetrics m); - return new FontExtents (m.Ascent, m.Descent, m.CapHeight, m.XMax, m.XHeight); + return new FontExtents (-m.Ascent, m.Descent, m.Descent - m.Ascent, m.MaxCharacterWidth, m.XHeight); } } public Antialias Antialias { @@ -254,10 +254,8 @@ namespace Crow.SkiaBackend MoveTo (dx + x, dx + y); } - public void RenderSvg(IntPtr svgNativeHandle, string subId = null) - { - //throw new NotImplementedException(); - } + public void RenderSvg(ISvgHandle svgHandle, string subId = null) + => svgHandle.Render (this, subId); public void ResetClip() { @@ -292,7 +290,6 @@ namespace Crow.SkiaBackend SKFontStyleWidth.Normal, (SKFontStyleSlant)slant)); updatePaintFont (); } - public void SetDash(double[] dashes, double offset = 0) { if (dashes == null || dashes.Length == 1) { @@ -301,7 +298,6 @@ namespace Crow.SkiaBackend } paint.PathEffect = SKPathEffect.CreateDash (dashes.Cast().ToArray(), (float)offset); } - public void SetFontSize(double scale) { if (font == null) @@ -309,50 +305,29 @@ namespace Crow.SkiaBackend font.Size = (float)scale; updatePaintFont (); } - public void SetSource(IPattern pat) { - throw new NotImplementedException(); + if (pat is Gradient gr) + paint.Shader = gr.shader; } - public void SetSource(Color color) { + paint.Shader = null; paint.Color = (UInt32)color; } - public void SetSource(double r, double g, double b, double a = 1) { - paint.Color = (UInt32)new Color (r, g, b, a); + paint.Shader = null; + paint.Color = (UInt32)new Color (a, r, g, b); } - + VkSurface sourceSurface; public void SetSource(ISurface surf, double x = 0, double y = 0) { - if (!(surf is Surface s)) - return; - canvas.DrawSurface (s.SkSurf, (float)x, (float)y); - } - - public void ShowText(string text) - { - ShowText (text.AsSpan ()); - } - - public void ShowText(ReadOnlySpan s, int tabSize = 4) - { - int size = s.Length * 4 + 1; - Span bytes = size > 512 ? new byte[size] : stackalloc byte[size]; - int encodedBytes = s.ToUtf8 (bytes, tabSize); - bytes[encodedBytes] = 0; - ShowText (bytes.Slice (0, encodedBytes + 1)); - } - - public void ShowText(Span bytes) - { - SKPoint origin = (path == null) ? SKPoint.Empty : path.LastPoint; - if (font == null) - createDefaultFont (); - SKTextBlob tb = SKTextBlob.Create (bytes, SKTextEncoding.Utf8, font, origin); - canvas.DrawText (tb, origin.X, origin.Y, paint); + VkSurface s = surf as VkSurface; + s.Flush(); + paint.Shader = SKShader.CreateImage(s.SkSurf.Snapshot(), + SKShaderTileMode.Clamp, SKShaderTileMode.Clamp, SKMatrix.CreateTranslation ((float)x, (float)y)); + //canvas.DrawSurface (s.SkSurf, (float)x, (float)y); } public void Stroke() @@ -361,12 +336,6 @@ namespace Crow.SkiaBackend path?.Dispose (); path = null; } - - public Rectangle StrokeExtents() - { - throw new NotImplementedException(); - } - public void StrokePreserve() { if (path == null) @@ -374,13 +343,16 @@ namespace Crow.SkiaBackend paint.IsStroke = true; canvas.DrawPath (path, paint); } + public Rectangle StrokeExtents() + { + throw new NotImplementedException(); + } public TextExtents TextExtents(ReadOnlySpan s, int tabSize = 4) { TextExtents (s, tabSize, out Drawing2D.TextExtents e); return e; } - public void TextExtents(ReadOnlySpan s, int tabSize, out TextExtents extents) { if (s.Length == 0) { @@ -393,22 +365,39 @@ namespace Crow.SkiaBackend bytes[encodedBytes] = 0; TextExtents (bytes.Slice (0, encodedBytes + 1), out extents); } - public void TextExtents(Span bytes, out TextExtents extents) { if (font == null) createDefaultFont (); paint.GetFontMetrics (out SKFontMetrics metrics); SKRect bounds = default; - paint.MeasureText (bytes, ref bounds); + paint.MeasureText (bytes.Slice (0, bytes.Length - 1), ref bounds); extents = new TextExtents (0,0,bounds.Width, bounds.Height, bounds.Width, bounds.Height); } - - public void Translate(double dx, double dy) + public void ShowText(string text) { - canvas.Translate ((float)dx, (float)dy); + ShowText (text.AsSpan ()); } + public void ShowText(ReadOnlySpan s, int tabSize = 4) + { + int size = s.Length * 4 + 1; + Span bytes = size > 512 ? new byte[size] : stackalloc byte[size]; + int encodedBytes = s.ToUtf8 (bytes, tabSize); + bytes[encodedBytes] = 0; + ShowText (bytes.Slice (0, encodedBytes + 1)); + } + public void ShowText(Span bytes) + { + SKPoint origin = (path == null) ? SKPoint.Empty : path.LastPoint; + if (font == null) + createDefaultFont (); + SKTextBlob tb = SKTextBlob.Create (bytes.Slice (0, bytes.Length - 1), SKTextEncoding.Utf8, font); + + canvas.DrawText (tb, origin.X, origin.Y, paint); + } + + public void Translate(double dx, double dy) => canvas.Translate ((float)dx, (float)dy); public void Translate(PointD p) => Translate (p.X, p.Y); diff --git a/Backends/SkiaBackend/src/DefaultBackend.cs b/Backends/SkiaBackend/src/DefaultBackend.cs index 6d0601ca..21f7e4da 100644 --- a/Backends/SkiaBackend/src/DefaultBackend.cs +++ b/Backends/SkiaBackend/src/DefaultBackend.cs @@ -9,8 +9,8 @@ namespace Crow.Backends { public class DefaultBackend : VulkanBackend { - public DefaultBackend (IntPtr nativeWindoPointer, int width, int height) - : base (nativeWindoPointer, width, height) {} + public DefaultBackend (ref IntPtr nativeWindoPointer, out bool ownGlfwWinHandle, int width, int height) + : base (ref nativeWindoPointer, out ownGlfwWinHandle, width, height) {} public DefaultBackend (int width, int height) : base (width, height) {} } diff --git a/Backends/SkiaBackend/src/Extensions.cs b/Backends/SkiaBackend/src/Extensions.cs new file mode 100644 index 00000000..2b27d31e --- /dev/null +++ b/Backends/SkiaBackend/src/Extensions.cs @@ -0,0 +1,15 @@ +// Copyright (c) 2018-2021 Jean-Philippe Bruyère +// +// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) + + +using Drawing2D; +using SkiaSharp; + +namespace Crow.SkiaBackend +{ + internal static class Extensions { + internal static SKColor ToSkiaColor (this Color c) + => new Color (c.A, c.R, c.G, c.B).Value; + } +} \ No newline at end of file diff --git a/Backends/SkiaBackend/src/Gradient.cs b/Backends/SkiaBackend/src/Gradient.cs new file mode 100644 index 00000000..c940e7d2 --- /dev/null +++ b/Backends/SkiaBackend/src/Gradient.cs @@ -0,0 +1,93 @@ +// Copyright (c) 2018-2021 Jean-Philippe Bruyère +// +// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) + +using System; +using System.Collections.Generic; +using Drawing2D; +using SkiaSharp; + +namespace Crow.SkiaBackend +{ + public abstract class Gradient : IGradient + { + internal SKShader shader; + protected SKPoint[] points; + protected List colorStops = new List (); + protected List offsets = new List(); + protected SKShaderTileMode tileMode = SKShaderTileMode.Clamp; + protected Filter filter = Filter.Fast; + protected Gradient (SKPoint p0, SKPoint p1) { + points = new SKPoint[] {p0, p1}; + } + ~Gradient() + { + Dispose(false); + } + public Extend Extend { + get => (Extend)tileMode; + set => tileMode = (SKShaderTileMode)value; + } + public Filter Filter { + get => throw new NotImplementedException(); + set => throw new NotImplementedException(); + } + + public void AddColorStop (double offset, Color c) { + shader?.Dispose(); + shader = null; + offsets.Add ((float)offset); + colorStops.Add (c.ToSkiaColor()); + } + public void AddColorStop(float offset, float r, float g, float b, float a = 1f) { + shader?.Dispose(); + shader = null; + offsets.Add ((float)offset); + colorStops.Add (new Color (a,r,g,b).Value); + } + internal abstract void Activate (); + + #region IDisposable implementation + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (!disposing) + return; + shader?.Dispose (); + } + #endregion + } + public class LinearGradient : Gradient { + public LinearGradient (float x0, float y0, float x1, float y1) + : base (new SKPoint (x0, y0), new SKPoint (x1, y1)) { } + + internal override void Activate() + { + if (shader != null) + return; + shader = SKShader.CreateLinearGradient (points[0], points[1], + colorStops.ToArray(), offsets.ToArray(), tileMode); + } + } + public class RadialGradient : Gradient { + float[] radiuses; + public RadialGradient ( float cx0, float cy0, float radius0, + float cx1, float cy1, float radius1) + : base (new SKPoint (cx0, cy0), new SKPoint (cx1, cy1)) { + radiuses = new float[] {radius0, radius1}; + } + + internal override void Activate() + { + if (shader != null) + return; + shader = SKShader.CreateRadialGradient (points[0], radiuses[0], + colorStops.ToArray(), offsets.ToArray(), tileMode); + } + } +} \ No newline at end of file diff --git a/Backends/SkiaBackend/src/Surface.cs b/Backends/SkiaBackend/src/Surface.cs index 31d84f21..843ae6bf 100644 --- a/Backends/SkiaBackend/src/Surface.cs +++ b/Backends/SkiaBackend/src/Surface.cs @@ -39,7 +39,7 @@ namespace Crow.SkiaBackend } }; rt = new GRBackendRenderTarget (width, height, (int)samples, imgInfo); - skSurf = SKSurface.Create (gr, rt, SKColorType.Rgba8888); + skSurf = SKSurface.Create (gr, rt, GRSurfaceOrigin.TopLeft, SKColorType.Rgba8888, SKColorSpace.CreateSrgb()); } ~VkSurface () { diff --git a/Backends/SkiaBackend/src/SvgHandle.cs b/Backends/SkiaBackend/src/SvgHandle.cs new file mode 100644 index 00000000..7cd354f0 --- /dev/null +++ b/Backends/SkiaBackend/src/SvgHandle.cs @@ -0,0 +1,52 @@ +// Copyright (c) 2021 Jean-Philippe Bruyère +// +// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) + +using System; +using System.IO; +using Drawing2D; +using SkiaSharp; +using Svg.Skia; + +namespace Crow.SkiaBackend +{ + public sealed class SvgHandle : ISvgHandle { + + SKSvg handle; + + SvgHandle () { + handle = new SKSvg (); + } + internal SvgHandle (string file_name) : this () + { + handle.Load (file_name); + } + internal SvgHandle (Stream stream) : this () + { + handle.Load (stream); + } + internal static SvgHandle FromFragment (string framgment) { + SvgHandle svg = new SvgHandle(); + svg.handle.FromSvg (framgment); + return svg; + } + + public void Render(IContext cr) + { + Context ctx = cr as Context; + ctx.canvas.DrawPicture (handle.Picture); + } + public void Render (IContext cr, string id) + { + Context ctx = cr as Context; + ctx.canvas.DrawPicture (handle.Picture); + } + public Size Dimensions + => new Size ((int)handle.Drawable.Bounds.Width, (int)handle.Drawable.Bounds.Height); + + public void Dispose() { + handle.Dispose (); + } + + } +} diff --git a/Backends/SkiaBackend/src/VulkanBackend.cs b/Backends/SkiaBackend/src/VulkanBackend.cs index 40882bfb..09069b77 100644 --- a/Backends/SkiaBackend/src/VulkanBackend.cs +++ b/Backends/SkiaBackend/src/VulkanBackend.cs @@ -51,7 +51,7 @@ namespace Crow.SkiaBackend Vk.vkGetDeviceProcAddr (device, n); } } - + #region CTOR /// /// Create a new offscreen backend, used in perfTests /// @@ -77,12 +77,28 @@ namespace Crow.SkiaBackend dev.Activate (enabledFeatures); } - public VulkanBackend (IntPtr nativeWindoPointer, int width, int height) : base () + public VulkanBackend (ref IntPtr nativeWindoPointer, out bool ownGlfwWinHandle, int width, int height) + : base () { - hWin = nativeWindoPointer; + if (nativeWindoPointer == IntPtr.Zero) { + Glfw3.Init (); + Glfw3.WindowHint (WindowAttribute.ClientApi, 0); + Glfw3.WindowHint (WindowAttribute.Resizable, 1); + Glfw3.WindowHint (WindowAttribute.Decorated, 1); + + hWin = Glfw3.CreateWindow (width, height, "win name", MonitorHandle.Zero, IntPtr.Zero); + if (hWin == IntPtr.Zero) + throw new Exception ("[GLFW3] Unable to create Window"); + + nativeWindoPointer = hWin; + ownGlfwWinHandle = true; + } else { + hWin = nativeWindoPointer; + ownGlfwWinHandle = false; + } SwapChain.IMAGES_USAGE = VkImageUsageFlags.ColorAttachment | VkImageUsageFlags.TransferDst; - SwapChain.PREFERED_FORMAT = VkFormat.B8g8r8a8Unorm; + SwapChain.PREFERED_FORMAT = VkFormat.B8g8r8a8Srgb; List instExts = new List (Glfw3.GetRequiredInstanceExtensions ()); #if DEBUG @@ -100,6 +116,7 @@ namespace Crow.SkiaBackend phy = phys[0]; VkPhysicalDeviceFeatures enabledFeatures = default; + dev = new vke.Device (phy); graphicQueue = new PresentQueue (dev, VkQueueFlags.Graphics, hSurf); @@ -137,19 +154,27 @@ namespace Crow.SkiaBackend { Dispose (false); } + #endregion public IContext CreateContext(ISurface surf) => new Context (surf as VkSurface); public IGradient CreateGradient(GradientType gradientType, Rectangle bounds) { - throw new NotImplementedException(); + switch (gradientType) { + case GradientType.Vertical: + return new LinearGradient (bounds.Left, bounds.Top, bounds.Left, bounds.Bottom); + case GradientType.Horizontal: + return new LinearGradient (bounds.Left, bounds.Top, bounds.Right, bounds.Top); + case GradientType.Oblic: + return new LinearGradient (bounds.Left, bounds.Top, bounds.Right, bounds.Bottom); + case GradientType.Radial: + throw new NotImplementedException (); + } + return null; } public IRegion CreateRegion () => new Crow.SkiaBackend.Region (); public ISurface CreateSurface(int width, int height) - { - return new VkSurface (dev, graphicQueue, gr, (int)width, (int)height, samples); - } - + => new VkSurface (dev, graphicQueue, gr, (int)width, (int)height, samples); public ISurface CreateSurface(byte[] data, int width, int height) { throw new NotImplementedException(); @@ -161,9 +186,7 @@ namespace Crow.SkiaBackend } public ISvgHandle LoadSvg(Stream stream) - { - throw new NotImplementedException(); - } + => new SvgHandle (stream); public ISvgHandle LoadSvg(string svgFragment) { @@ -197,6 +220,9 @@ namespace Crow.SkiaBackend } public void FlushUIFrame(IContext ctx) { + //surf.Canvas.Flush (); + surf.Flush(); + if (disposeContextOnFlush) ctx.Dispose (); clipping = null; diff --git a/Backends/VkvgBackend/src/Context.cs b/Backends/VkvgBackend/src/Context.cs index f303b09f..0e7c3be6 100644 --- a/Backends/VkvgBackend/src/Context.cs +++ b/Backends/VkvgBackend/src/Context.cs @@ -11,12 +11,11 @@ namespace Crow.VkvgBackend { public class Context : IContext { + internal IntPtr handle = IntPtr.Zero; - IntPtr handle = IntPtr.Zero; - - public Context (ISurface surf) + internal Context (Surface surf) { - handle = NativeMethods.vkvg_create(surf.Handle); + handle = NativeMethods.vkvg_create(surf.handle); this.FillRule = FillRule.NonZero; } ~Context() @@ -24,8 +23,6 @@ namespace Crow.VkvgBackend Dispose(false); } - public IntPtr Handle => handle; - public double LineWidth { get => NativeMethods.vkvg_get_line_width(handle); @@ -64,16 +61,6 @@ namespace Crow.VkvgBackend set; get; } - public void Arc(double xc, double yc, double radius, double a1, double a2) - => NativeMethods.vkvg_arc(handle, (float)xc, (float)yc, (float)radius, (float)a1, (float)a2); - public void Arc (PointD center, double radius, double angle1, double angle2) - => NativeMethods.vkvg_arc (handle, (float)center.X, (float)center.Y, (float)radius, (float)angle1, (float)angle2); - public void ArcNegative (PointD center, double radius, double angle1, double angle2) - => NativeMethods.vkvg_arc_negative (handle, (float)center.X, (float)center.Y, (float)radius, (float)angle1, (float)angle2); - public void ArcNegative(double xc, double yc, double radius, double a1, double a2) - { - NativeMethods.vkvg_arc_negative(handle, (float)xc, (float)yc, (float)radius, (float)a1, (float)a2); - } public void Clear() => NativeMethods.vkvg_clear(handle); @@ -90,10 +77,16 @@ namespace Crow.VkvgBackend public void SetFontSize (double size) => NativeMethods.vkvg_set_font_size(handle, (uint)size); public void ClosePath() => NativeMethods.vkvg_close_path (handle); - - public void CurveTo(double x1, double y1, double x2, double y2, double x3, double y3) - => NativeMethods.vkvg_curve_to (handle, (float)x1, (float)y1, (float)x2, (float)y2, (float)x3, (float)y3); - + public void NewPath() => NativeMethods.vkvg_new_path(handle); + public void NewSubPath() => NativeMethods.vkvg_new_sub_path(handle); + public void Arc(double xc, double yc, double radius, double a1, double a2) + => NativeMethods.vkvg_arc(handle, (float)xc, (float)yc, (float)radius, (float)a1, (float)a2); + public void Arc (PointD center, double radius, double angle1, double angle2) + => NativeMethods.vkvg_arc (handle, (float)center.X, (float)center.Y, (float)radius, (float)angle1, (float)angle2); + public void ArcNegative (PointD center, double radius, double angle1, double angle2) + => NativeMethods.vkvg_arc_negative (handle, (float)center.X, (float)center.Y, (float)radius, (float)angle1, (float)angle2); + public void ArcNegative(double xc, double yc, double radius, double a1, double a2) + => NativeMethods.vkvg_arc_negative(handle, (float)xc, (float)yc, (float)radius, (float)a1, (float)a2); /*public IntPtr Handle => handle; public void AddReference() @@ -146,166 +139,74 @@ namespace Crow.VkvgBackend throw new NotImplementedException(); } */ - public void MoveTo(float x, float y) - { - NativeMethods.vkvg_move_to(handle, x, y); - } - public void RelMoveTo(float x, float y) - { - NativeMethods.vkvg_rel_move_to(handle, x, y); - } - public void LineTo(float x, float y) - { - NativeMethods.vkvg_line_to(handle, x, y); - } - public void LineTo(Point p) - { - NativeMethods.vkvg_line_to(handle, p.X, p.Y); - } - public void LineTo(PointD p) - { - NativeMethods.vkvg_line_to(handle, (float)p.X, (float)p.Y); - } - public void RelLineTo(float x, float y) - { - NativeMethods.vkvg_rel_line_to(handle, x, y); - } - public void CurveTo(float x1, float y1, float x2, float y2, float x3, float y3) - { - NativeMethods.vkvg_curve_to(handle, x1, y1, x2, y2, x3, y3); - } - public void RelCurveTo(float x1, float y1, float x2, float y2, float x3, float y3) - { - NativeMethods.vkvg_rel_curve_to(handle, x1, y1, x2, y2, x3, y3); - } - - public void MoveTo(double x, double y) - { - NativeMethods.vkvg_move_to(handle, (float)x, (float)y); - } - public void RelMoveTo(double x, double y) - { - NativeMethods.vkvg_rel_move_to(handle, (float)x, (float)y); - } - public void LineTo(double x, double y) - { - NativeMethods.vkvg_line_to(handle, (float)x, (float)y); - } - public void RelLineTo(double x, double y) - { - NativeMethods.vkvg_rel_line_to(handle, (float)x, (float)y); - } + //public void MoveTo(float x, float y) => NativeMethods.vkvg_move_to(handle, x, y); + public void MoveTo(double x, double y) => NativeMethods.vkvg_move_to(handle, (float)x, (float)y); + public void MoveTo(Point p) => NativeMethods.vkvg_move_to(handle, p.X, p.Y); + public void MoveTo(PointD p) => NativeMethods.vkvg_move_to(handle, (float)p.X, (float)p.Y); + //public void RelMoveTo(float x, float y) => NativeMethods.vkvg_rel_move_to(handle, x, y); + //public void LineTo(float x, float y) => NativeMethods.vkvg_line_to(handle, x, y); + public void LineTo(Point p) => NativeMethods.vkvg_line_to(handle, p.X, p.Y); + public void LineTo(PointD p) => NativeMethods.vkvg_line_to(handle, (float)p.X, (float)p.Y); + public void LineTo(double x, double y) => NativeMethods.vkvg_line_to(handle, (float)x, (float)y); + //public void RelLineTo(float x, float y) => NativeMethods.vkvg_rel_line_to(handle, x, y); + /*public void CurveTo(float x1, float y1, float x2, float y2, float x3, float y3) + => NativeMethods.vkvg_curve_to(handle, x1, y1, x2, y2, x3, y3);*/ + public void CurveTo(double x1, double y1, double x2, double y2, double x3, double y3) + => NativeMethods.vkvg_curve_to (handle, (float)x1, (float)y1, (float)x2, (float)y2, (float)x3, (float)y3); + public void RelMoveTo(double x, double y) => NativeMethods.vkvg_rel_move_to(handle, (float)x, (float)y); + public void RelLineTo(double x, double y) => NativeMethods.vkvg_rel_line_to(handle, (float)x, (float)y); public void RelCurveTo(double x1, double y1, double x2, double y2, double x3, double y3) - { - NativeMethods.vkvg_rel_curve_to(handle, (float)x1, (float)y1, (float)x2, (float)y2, (float)x3, (float)y3); - } + => NativeMethods.vkvg_rel_curve_to(handle, (float)x1, (float)y1, (float)x2, (float)y2, (float)x3, (float)y3); + //public void RelCurveTo(float x1, float y1, float x2, float y2, float x3, float y3) + // => NativeMethods.vkvg_rel_curve_to(handle, x1, y1, x2, y2, x3, y3); + public void Rectangle(double x, double y, double width, double height) + => NativeMethods.vkvg_rectangle (handle, (float)x, (float)y, (float)width, (float)height); + public void Rectangle(Rectangle r) + => NativeMethods.vkvg_rectangle (handle, (float)r.X, (float)r.Y, (float)r.Width, (float)r.Height); + - public void SetSource(Pattern pat) - { - NativeMethods.vkvg_set_source(handle, pat.Handle); - } public void SetSource(IPattern pat) { if (pat is Pattern p) - NativeMethods.vkvg_set_source (handle, p.Handle); + NativeMethods.vkvg_set_source (handle, p.handle); } public void SetSource (Color color) { - NativeMethods.vkvg_set_source_rgba (handle, (float)(color.R / 255.0), (float)(color.G / 255.0), (float)(color.B / 255.0), (float)(color.A / 255.0)); + NativeMethods.vkvg_set_source_rgba (handle, + (float)(color.R / 255.0), (float)(color.G / 255.0), (float)(color.B / 255.0), (float)(color.A / 255.0)); } public void SetSource(ISurface surf, double x = 0, double y = 0) - { - NativeMethods.vkvg_set_source_surface(handle, surf.Handle, (float)x, (float)y); - } + => NativeMethods.vkvg_set_source_surface(handle, (surf as Surface).handle, (float)x, (float)y); public void SetSource(double r, double g, double b, double a = 1.0) - { - NativeMethods.vkvg_set_source_rgba(handle, (float)r, (float)g, (float)b, (float)a); - } - public void RenderSvg(IntPtr nsvgImage, string subId = null) - { - NativeMethods.vkvg_render_svg(handle, nsvgImage, subId); - } - + => NativeMethods.vkvg_set_source_rgba(handle, (float)r, (float)g, (float)b, (float)a); + public void RenderSvg(ISvgHandle nsvgImage, string subId = null) + => nsvgImage.Render (this, subId); Matrix savedMat = Matrix.Identity; - public void SaveTransformations() - { - NativeMethods.vkvg_get_matrix (handle, out savedMat); - } - - public void RestoreTransformations() - { - NativeMethods.vkvg_set_matrix (handle, ref savedMat); - } + public void SaveTransformations() => NativeMethods.vkvg_get_matrix (handle, out savedMat); + public void RestoreTransformations() => NativeMethods.vkvg_set_matrix (handle, ref savedMat); - Rectangle IContext.StrokeExtents() - { - throw new NotImplementedException(); - } - public void Scale(double sx, double sy) - { - NativeMethods.vkvg_scale(handle, (float)sx, (float)sy); - } - public void Translate(double dx, double dy) - { - NativeMethods.vkvg_translate(handle, (float)dx, (float)dy); - } - public void Translate(PointD p) - { - NativeMethods.vkvg_translate(handle, (float)p.X, (float)p.Y); - } - public void Rotate(double alpha) - { - NativeMethods.vkvg_rotate(handle, (float)alpha); - } + public void Scale(double sx, double sy) => NativeMethods.vkvg_scale(handle, (float)sx, (float)sy); + public void Translate(double dx, double dy) => NativeMethods.vkvg_translate(handle, (float)dx, (float)dy); + public void Translate(PointD p) => NativeMethods.vkvg_translate(handle, (float)p.X, (float)p.Y); + public void Rotate(double alpha) => NativeMethods.vkvg_rotate(handle, (float)alpha); - public void Fill() - { - NativeMethods.vkvg_fill(handle); - } - public void FillPreserve() - { - NativeMethods.vkvg_fill_preserve(handle); - } - public void Stroke() - { - NativeMethods.vkvg_stroke(handle); - } - public void StrokePreserve() - { - NativeMethods.vkvg_stroke_preserve(handle); - } - public void NewPath() - { - NativeMethods.vkvg_new_path(handle); - } - public void NewSubPath() - { - NativeMethods.vkvg_new_sub_path(handle); - } - public void MoveTo(PointD p) - { - NativeMethods.vkvg_move_to(handle, (float)p.X, (float)p.Y); - } - public void MoveTo(Point p) + public void Fill() => NativeMethods.vkvg_fill(handle); + public void FillPreserve() => NativeMethods.vkvg_fill_preserve(handle); + public void Stroke() => NativeMethods.vkvg_stroke(handle); + public void StrokePreserve() => NativeMethods.vkvg_stroke_preserve(handle); + public Rectangle StrokeExtents() { - NativeMethods.vkvg_move_to(handle, p.X, p.Y); + throw new NotImplementedException(); } - - public void PopGroupToSource() { throw new NotImplementedException(); } - public void PushGroup() { throw new NotImplementedException(); } - public void Rectangle(double x, double y, double width, double height) - => NativeMethods.vkvg_rectangle (handle, (float)x, (float)y, (float)width, (float)height); - public void Rectangle(Rectangle r) - => NativeMethods.vkvg_rectangle (handle, (float)r.X, (float)r.Y, (float)r.Width, (float)r.Height); public void SelectFontFace(string family, FontSlant slant, FontWeight weight) @@ -362,15 +263,9 @@ namespace Crow.VkvgBackend } public void ShowText(TextRun textRun) - { - NativeMethods.vkvg_show_text_run(handle, textRun.Handle); - } + => NativeMethods.vkvg_show_text_run(handle, textRun.Handle); - public Rectangle StrokeExtents() - { - throw new NotImplementedException(); - } #region IDisposable implementation diff --git a/Backends/VkvgBackend/src/DefaultBackend.cs b/Backends/VkvgBackend/src/DefaultBackend.cs index 68793806..ac7ff1db 100644 --- a/Backends/VkvgBackend/src/DefaultBackend.cs +++ b/Backends/VkvgBackend/src/DefaultBackend.cs @@ -63,9 +63,24 @@ namespace Crow.Backends surf = new VkvgBackend.Surface (vkvgDev, (int)width, (int)height); } - public DefaultBackend (IntPtr nativeWindoPointer, int width, int height) + public DefaultBackend (ref IntPtr nativeWindoPointer, out bool ownGlfwWinHandle, int width, int height) { - hWin = nativeWindoPointer; + if (nativeWindoPointer == IntPtr.Zero) { + Glfw3.Init (); + Glfw3.WindowHint (WindowAttribute.ClientApi, 0); + Glfw3.WindowHint (WindowAttribute.Resizable, 1); + Glfw3.WindowHint (WindowAttribute.Decorated, 1); + + hWin = Glfw3.CreateWindow (width, height, "win name", MonitorHandle.Zero, IntPtr.Zero); + if (hWin == IntPtr.Zero) + throw new Exception ("[GLFW3] Unable to create Window"); + + nativeWindoPointer = hWin; + ownGlfwWinHandle = true; + } else { + hWin = nativeWindoPointer; + ownGlfwWinHandle = false; + } SwapChain.IMAGES_USAGE = VkImageUsageFlags.ColorAttachment | VkImageUsageFlags.TransferDst; SwapChain.PREFERED_FORMAT = VkFormat.B8g8r8a8Unorm; @@ -113,6 +128,7 @@ namespace Crow.Backends vkvgDev = new Crow.VkvgBackend.Device ( instance.Handle, phy.Handle, dev.VkDev.Handle, graphicQueue.qFamIndex, samples); + vkvgDev.SetDpy (72,72); createMainSurface ((uint)width, (uint)height); } @@ -128,7 +144,7 @@ namespace Crow.Backends public IRegion CreateRegion () => new Crow.VkvgBackend.Region (); public IContext CreateContext (ISurface surf) { - Crow.VkvgBackend.Context gr = new Crow.VkvgBackend.Context (surf); + Crow.VkvgBackend.Context gr = new VkvgBackend.Context (surf as VkvgBackend.Surface); return gr; } //IPattern CreatePattern (PatternType patternType); @@ -188,7 +204,7 @@ namespace Crow.Backends IContext ctx = existingContext; if (ctx == null) { disposeContextOnFlush = true; - ctx = new VkvgBackend.Context (MainSurface); + ctx = new VkvgBackend.Context (surf); } else disposeContextOnFlush = false; diff --git a/Backends/VkvgBackend/src/Pattern.cs b/Backends/VkvgBackend/src/Pattern.cs index 6c2918f0..d324b2af 100644 --- a/Backends/VkvgBackend/src/Pattern.cs +++ b/Backends/VkvgBackend/src/Pattern.cs @@ -9,8 +9,7 @@ namespace Crow.VkvgBackend { public class Pattern : IPattern { - protected IntPtr handle = IntPtr.Zero; - public IntPtr Handle => handle; + internal IntPtr handle = IntPtr.Zero; #region CTORS & DTOR protected Pattern(IntPtr handle) @@ -27,7 +26,7 @@ namespace Crow.VkvgBackend } public Pattern(Surface surf) { - handle = NativeMethods.vkvg_pattern_create_for_surface(surf.Handle); + handle = NativeMethods.vkvg_pattern_create_for_surface(surf.handle); } ~Pattern() @@ -42,7 +41,6 @@ namespace Crow.VkvgBackend } public uint References() => NativeMethods.vkvg_pattern_get_reference_count(handle); - public Extend Extend { get => NativeMethods.vkvg_pattern_get_extend(handle); diff --git a/Backends/VkvgBackend/src/Surface.cs b/Backends/VkvgBackend/src/Surface.cs index b32feef6..e900478a 100644 --- a/Backends/VkvgBackend/src/Surface.cs +++ b/Backends/VkvgBackend/src/Surface.cs @@ -9,7 +9,7 @@ namespace Crow.VkvgBackend { public class Surface: ISurface { - IntPtr handle = IntPtr.Zero; + internal IntPtr handle = IntPtr.Zero; Device vkvgDev; #region CTOR @@ -45,8 +45,6 @@ namespace Crow.VkvgBackend { Dispose (false); } - - public IntPtr Handle => handle; public IntPtr VkImage => NativeMethods.vkvg_surface_get_vk_image (handle); public int Width => NativeMethods.vkvg_surface_get_width (handle); public int Height => NativeMethods.vkvg_surface_get_height (handle); diff --git a/Backends/VkvgBackend/src/SvgHandle.cs b/Backends/VkvgBackend/src/SvgHandle.cs index 376d0dbb..934483f5 100644 --- a/Backends/VkvgBackend/src/SvgHandle.cs +++ b/Backends/VkvgBackend/src/SvgHandle.cs @@ -9,8 +9,9 @@ namespace Crow.VkvgBackend { public sealed class SvgHandle : ISvgHandle { - IntPtr handle; + internal IntPtr handle; + #region CTOR public SvgHandle (Device dev, Span bytes) { /*int size = svgFragment.Length * 4 + 1; @@ -23,13 +24,12 @@ namespace Crow.VkvgBackend { handle = NativeMethods.nsvg_load_file (dev.Handle, file_name); } + #endregion public void Render(IContext cr) => - cr.RenderSvg (handle); - + NativeMethods.vkvg_render_svg((cr as Context).handle, handle, null); public void Render (IContext cr, string id) => - cr.RenderSvg (handle, id); - + NativeMethods.vkvg_render_svg((cr as Context).handle, handle, id); public Size Dimensions { get { NativeMethods.nsvg_get_size (handle, out int w, out int h); diff --git a/Crow/Crow.csproj b/Crow/Crow.csproj index f99c239d..eedb5404 100644 --- a/Crow/Crow.csproj +++ b/Crow/Crow.csproj @@ -74,8 +74,8 @@ - - + + diff --git a/Crow/src/Interface.cs b/Crow/src/Interface.cs index 8ad67291..9a1ab102 100644 --- a/Crow/src/Interface.cs +++ b/Crow/src/Interface.cs @@ -236,8 +236,7 @@ namespace Crow clientRectangle = new Rectangle (0, 0, width, height); SingleThreaded = singleThreaded; - if (createSurface) - initSurface (); + initBackend (); PerformanceMeasure.InitMeasures (); @@ -308,13 +307,16 @@ namespace Crow manage VkWindow instance. */ static Dictionary windows = new Dictionary (); /** GLFW window native pointer and current native handle for mouse cursor */ - IntPtr hWin; + protected IntPtr hWin; + /// + /// True if GLFW window has been created by the backend and should be disposed with the `Interface`, false otherwise. + /// + protected bool ownWindow; protected IBackend backend;//backend device /// Clipping rectangles on the root context protected IRegion clipping; static string backendDeviceTypeString = "Crow.CairoBackend.Device"; Cursor currentCursor; - bool ownWindow; /// /// If `true`, UI updates will be handle in the `Run()` method, so in the main thread of the application along with GLFW events polling. /// If `false`, A dedicated thread will be started for the UI updates. @@ -330,7 +332,7 @@ namespace Crow public IntPtr SurfacePointer { get { lock(UpdateMutex) - return MainSurface.Handle; + return IntPtr.Zero;// MainSurface.Handle; } } @@ -402,34 +404,9 @@ namespace Crow } protected virtual void initBackend () { - backend = new Crow.Backends.DefaultBackend (hWin, clientRectangle.Width, clientRectangle.Height); + backend = new Crow.Backends.DefaultBackend (ref hWin, out ownWindow, clientRectangle.Width, clientRectangle.Height); clipping = Backend.CreateRegion (); - } - /// - /// Create the main rendering surface. The default is a GLFW window with a cairo surface bound to it. - /// - protected void initSurface () - { - Glfw3.Init (); - - - Glfw3.WindowHint (WindowAttribute.ClientApi, 0); - /*Glfw3.WindowHint (WindowAttribute.ClientApi, Constants.OpenglEsApi); - Glfw3.WindowHint (WindowAttribute.ContextVersionMajor, 3); - Glfw3.WindowHint (WindowAttribute.ContextVersionMinor, 2); - Glfw3.WindowHint (WindowAttribute.ContextCreationApi, Constants.EglContextApi);*/ - - Glfw3.WindowHint (WindowAttribute.Resizable, 1); - Glfw3.WindowHint (WindowAttribute.Decorated, 1); - - hWin = Glfw3.CreateWindow (clientRectangle.Width, clientRectangle.Height, "win name", MonitorHandle.Zero, IntPtr.Zero); - if (hWin == IntPtr.Zero) - throw new Exception ("[GLFW3] Unable to create Window"); - ownWindow = true; - registerGlfwCallbacks (); - - initBackend (); } /// /// search for graphic object type in crow assembly, if not found, diff --git a/Crow/src/Widgets/Widget.cs b/Crow/src/Widgets/Widget.cs index 5d3e4c45..39ce20e5 100644 --- a/Crow/src/Widgets/Widget.cs +++ b/Crow/src/Widgets/Widget.cs @@ -1979,9 +1979,8 @@ namespace Crow } ctx.SetSource (bmp, rb.X, rb.Y); ctx.Paint (); -#if VKVG ctx.Flush (); -#endif + DbgLogger.EndEvent(DbgEvtType.GOPaintCache); } protected virtual void UpdateCache(IContext ctx){ diff --git a/Drawing2D/src/IContext.cs b/Drawing2D/src/IContext.cs index 3c4f54f8..e19f9738 100644 --- a/Drawing2D/src/IContext.cs +++ b/Drawing2D/src/IContext.cs @@ -9,8 +9,6 @@ namespace Drawing2D public interface IContext : IDisposable { - IntPtr Handle { get; } - double LineWidth { get; set; } LineJoin LineJoin { get; set; } LineCap LineCap { get; set; } @@ -76,7 +74,7 @@ namespace Drawing2D void SetSource (Color color); void SetSource(double r, double g, double b, double a = 1.0); void SetSource(ISurface surf, double x = 0f, double y = 0f); - void RenderSvg(IntPtr svgNativeHandle, string subId = null); + void RenderSvg(ISvgHandle svgHandle, string subId = null); void PushGroup (); void PopGroupToSource (); diff --git a/Drawing2D/src/IPattern.cs b/Drawing2D/src/IPattern.cs index 5eb4ffcc..9e94223a 100644 --- a/Drawing2D/src/IPattern.cs +++ b/Drawing2D/src/IPattern.cs @@ -8,7 +8,6 @@ namespace Drawing2D { public interface IPattern : IDisposable { - IntPtr Handle { get; } Extend Extend { get; set; } Filter Filter { get; set; } } diff --git a/Drawing2D/src/ISurface.cs b/Drawing2D/src/ISurface.cs index 7410a172..198f7539 100644 --- a/Drawing2D/src/ISurface.cs +++ b/Drawing2D/src/ISurface.cs @@ -8,7 +8,6 @@ namespace Drawing2D { public interface ISurface: IDisposable { - IntPtr Handle { get; } int Width { get; } int Height { get; } diff --git a/Samples/PerfTests/Program.cs b/Samples/PerfTests/Program.cs index d7797496..b4ec4bb1 100644 --- a/Samples/PerfTests/Program.cs +++ b/Samples/PerfTests/Program.cs @@ -141,10 +141,7 @@ namespace PerfTests writer.WriteLine ("Path;MinEllapsed;MaxEllapsed;MeanEllapsed;MedianEllapsed;sigmaEllapsed;MinMem;MaxMem;MeanMem;MedianMem;sigmaMem;MinAlloc;MaxAlloc;MeanAlloc;MedianAlloc;sigmaAlloc"); } - if (screenOutput) - initSurface (); - else - initBackend (); + initBackend (); initDictionaries (); loadStyling (); @@ -161,7 +158,7 @@ namespace PerfTests protected override void initBackend() { if (screenOutput) - backend = new Crow.Backends.DefaultBackend (WindowHandle, clientRectangle.Width, clientRectangle.Height); + backend = new Crow.Backends.DefaultBackend (ref hWin, out ownWindow, clientRectangle.Width, clientRectangle.Height); else backend = new Crow.Backends.DefaultBackend (clientRectangle.Width, clientRectangle.Height); -- 2.47.3