From f005d76468dc4c6a368b6f1f6eca69da25214e80 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jean-Philippe=20Bruy=C3=A8re?= Date: Wed, 24 Nov 2021 03:00:25 +0100 Subject: [PATCH] default Crow.CairoBackend ok --- Backends/CairoBackend/CairoBackend.csproj | 3 + Backends/CairoBackend/src/Context.cs | 523 +++++++------------ Backends/CairoBackend/src/DRMDevice.cs | 6 +- Backends/CairoBackend/src/Device.cs | 149 ++++-- Backends/CairoBackend/src/EGLDevice.cs | 2 +- Backends/CairoBackend/src/GLDevice.cs | 17 + Backends/CairoBackend/src/GLSurface.cs | 2 +- Backends/CairoBackend/src/GLXDevice.cs | 6 +- Backends/CairoBackend/src/Gradient.cs | 20 +- Backends/CairoBackend/src/LinearGradient.cs | 2 +- Backends/CairoBackend/src/Matrix.cs | 8 +- Backends/CairoBackend/src/MeshPattern.cs | 38 +- Backends/CairoBackend/src/NativeMethods.cs | 4 +- Backends/CairoBackend/src/Pattern.cs | 113 ++-- Backends/CairoBackend/src/Region.cs | 166 +++--- Backends/CairoBackend/src/SolidPattern.cs | 5 +- Backends/CairoBackend/src/Surface.cs | 5 +- Backends/CairoBackend/src/SurfacePattern.cs | 8 +- Backends/CairoBackend/src/WGLDevice.cs | 4 +- Backends/CairoBackend/src/Win32Surface.cs | 11 + Backends/CairoBackend/src/XcbSurface.cs | 2 +- Backends/CairoBackend/src/XlibSurface.cs | 2 +- Backends/CairoBackend/src/rsvg/SvgHandle.cs | 6 +- Backends/VkvgBackend/VkvgBackend.csproj | 21 +- Backends/VkvgBackend/src/Context.cs | 368 +++++++------ Backends/VkvgBackend/src/Device.cs | 68 ++- Backends/VkvgBackend/src/FontExtents.cs | 62 +++ Backends/VkvgBackend/src/Gradient.cs | 10 +- Backends/VkvgBackend/src/Matrix.cs | 2 +- Backends/VkvgBackend/src/NativeMethods.cs | 5 +- Backends/VkvgBackend/src/Pattern.cs | 12 +- Backends/VkvgBackend/src/{tmp => }/Region.cs | 77 +-- Backends/VkvgBackend/src/Surface.cs | 25 +- Backends/VkvgBackend/src/SvgHandle.cs | 42 +- Backends/VkvgBackend/src/TextExtents.cs | 60 +++ Backends/VkvgBackend/src/TextRun.cs | 14 +- Backends/VkvgBackend/src/tmp/FontOptions.cs | 74 --- Crow.sln | 7 + Crow/Crow.csproj | 21 +- Crow/src/Fill/BmpPicture.cs | 66 +-- Crow/src/Fill/Gradient.cs | 35 +- Crow/src/Fill/SvgPicture.cs | 46 +- Crow/src/Font.cs | 2 +- Crow/src/Interface.cs | 86 +-- Crow/src/LayoutingQueueItem.cs | 12 +- Crow/src/Widgets/ColorSlider.cs | 9 +- Crow/src/Widgets/HueSelector.cs | 7 +- Crow/src/Widgets/Image.cs | 5 +- Crow/src/Widgets/Label.cs | 4 +- Crow/src/Widgets/SaturationValueSelector.cs | 4 +- Crow/src/Widgets/Shape.cs | 8 +- Crow/src/Widgets/Widget.cs | 18 +- {Crow/src/Text => Drawing2D/src}/Encoding.cs | 8 +- Drawing2D/src/Enums.cs | 7 + Drawing2D/src/FontExtents.cs | 22 +- Drawing2D/src/IContext.cs | 74 ++- Drawing2D/src/IDevice.cs | 10 +- Drawing2D/src/IGradient.cs | 12 + Drawing2D/src/{Pattern.cs => IPattern.cs} | 2 + Drawing2D/src/IRegion.cs | 25 + Drawing2D/src/ISurface.cs | 1 + Drawing2D/src/ISvgHandle.cs | 14 + Drawing2D/src/TextExtents.cs | 33 +- Samples/ShowCase/ShowCase.cs | 2 +- Samples/common/src/Editor.cs | 4 +- Samples/common/src/SampleBase.cs | 1 + Samples/common/src/TestWidget.cs | 2 +- 67 files changed, 1185 insertions(+), 1304 deletions(-) create mode 100644 Backends/CairoBackend/src/GLDevice.cs create mode 100644 Backends/VkvgBackend/src/FontExtents.cs rename Backends/VkvgBackend/src/{tmp => }/Region.cs (82%) create mode 100644 Backends/VkvgBackend/src/TextExtents.cs delete mode 100644 Backends/VkvgBackend/src/tmp/FontOptions.cs rename {Crow/src/Text => Drawing2D/src}/Encoding.cs (90%) create mode 100644 Drawing2D/src/IGradient.cs rename Drawing2D/src/{Pattern.cs => IPattern.cs} (92%) create mode 100644 Drawing2D/src/IRegion.cs create mode 100644 Drawing2D/src/ISvgHandle.cs diff --git a/Backends/CairoBackend/CairoBackend.csproj b/Backends/CairoBackend/CairoBackend.csproj index dc9cb60a..bc11bc47 100644 --- a/Backends/CairoBackend/CairoBackend.csproj +++ b/Backends/CairoBackend/CairoBackend.csproj @@ -14,5 +14,8 @@ + + $(DefineConstants);STB_SHARP + diff --git a/Backends/CairoBackend/src/Context.cs b/Backends/CairoBackend/src/Context.cs index 965297be..a28c7b0c 100644 --- a/Backends/CairoBackend/src/Context.cs +++ b/Backends/CairoBackend/src/Context.cs @@ -139,52 +139,24 @@ namespace Crow.CairoBackend } } - public IntPtr Handle { - get { - return handle; - } - } + public IntPtr Handle => handle; public Operator Operator { - set { - NativeMethods.cairo_set_operator (handle, value); - } - - get { - return NativeMethods.cairo_get_operator (handle); - } + set => NativeMethods.cairo_set_operator (handle, value); + get => NativeMethods.cairo_get_operator (handle); } - public double Tolerance { - get { - return NativeMethods.cairo_get_tolerance (handle); - } - - set { - NativeMethods.cairo_set_tolerance (handle, value); - } + get => NativeMethods.cairo_get_tolerance (handle); + set => NativeMethods.cairo_set_tolerance (handle, value); } - public FillRule FillRule { - set { - NativeMethods.cairo_set_fill_rule (handle, value); - } - - get { - return NativeMethods.cairo_get_fill_rule (handle); - } + set => NativeMethods.cairo_set_fill_rule (handle, value); + get => NativeMethods.cairo_get_fill_rule (handle); } - public double LineWidth { - set { - NativeMethods.cairo_set_line_width (handle, value); - } - - get { - return NativeMethods.cairo_get_line_width (handle); - } + set => NativeMethods.cairo_set_line_width (handle, value); + get => NativeMethods.cairo_get_line_width (handle); } - public LineCap LineCap { set { NativeMethods.cairo_set_line_cap (handle, value); @@ -233,7 +205,7 @@ namespace Crow.CairoBackend public void SetSource (Pattern source) { - NativeMethods.cairo_set_source (handle, source.Handle); + NativeMethods.cairo_set_source (handle, source.handle); } public Pattern GetSource () @@ -265,63 +237,20 @@ namespace Crow.CairoBackend return NativeMethods.cairo_has_current_point (handle); } } - - [Obsolete ("Use GetTarget/SetTarget")] - public Surface Target { - set { - if (handle != IntPtr.Zero) - NativeMethods.cairo_destroy (handle); - - handle = NativeMethods.cairo_create (value.Handle); - } - - get { - return GetTarget (); - } - } - - public Surface GetTarget () - { - return Surface.Lookup (NativeMethods.cairo_get_target (handle), false); - } - + 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); } - - [Obsolete("Use GetScaledFont/SetScaledFont")] - public ScaledFont ScaledFont { - set { - SetScaledFont (value); - } - - get { - return GetScaledFont (); - } - } - public ScaledFont GetScaledFont () - { - return new ScaledFont (NativeMethods.cairo_get_scaled_font (handle), false); - } - + => new ScaledFont (NativeMethods.cairo_get_scaled_font (handle), false); public void SetScaledFont (ScaledFont font) - { - NativeMethods.cairo_set_scaled_font (handle, font.Handle); - } - - public uint ReferenceCount { - get { return NativeMethods.cairo_get_reference_count (handle); } - } - + => NativeMethods.cairo_set_scaled_font (handle, font.Handle); + public uint ReferenceCount => NativeMethods.cairo_get_reference_count (handle); public void SetSource (Color color) - { - NativeMethods.cairo_set_source_rgba (handle, color.R / 255.0, color.G / 255.0, color.B / 255.0, color.A / 255.0); - } - + => NativeMethods.cairo_set_source_rgba (handle, color.R / 255.0, color.G / 255.0, color.B / 255.0, color.A / 255.0); public void SetSource (double r, double g, double b) { NativeMethods.cairo_set_source_rgb (handle, r, g, b); @@ -348,168 +277,54 @@ namespace Crow.CairoBackend NativeMethods.cairo_set_source_surface (handle, source.Handle, 0, 0); } -#region Path methods - - public void NewPath () - { - NativeMethods.cairo_new_path (handle); - } - - public void NewSubPath () - { - NativeMethods.cairo_new_sub_path (handle); - } - - public void MoveTo (PointD p) - { - MoveTo (p.X, p.Y); - } - - public void MoveTo (double x, double y) - { - NativeMethods.cairo_move_to (handle, x, y); - } - - public void LineTo (PointD p) - { - LineTo (p.X, p.Y); - } - - public void LineTo (double x, double y) - { - NativeMethods.cairo_line_to (handle, x, y); - } - - public void CurveTo (PointD p1, PointD p2, PointD p3) - { - CurveTo (p1.X, p1.Y, p2.X, p2.Y, p3.X, p3.Y); - } - + #region Path methods + public void NewPath () => NativeMethods.cairo_new_path (handle); + public void NewSubPath () => NativeMethods.cairo_new_sub_path (handle); + public void MoveTo (PointD p) => MoveTo (p.X, p.Y); + public void MoveTo (double x, double y) => NativeMethods.cairo_move_to (handle, x, y); + public void LineTo (PointD p) => LineTo (p.X, p.Y); + public void LineTo (double x, double y) => NativeMethods.cairo_line_to (handle, x, y); + public void CurveTo (PointD p1, PointD p2, PointD p3) => CurveTo (p1.X, p1.Y, p2.X, p2.Y, p3.X, p3.Y); public void CurveTo (double x1, double y1, double x2, double y2, double x3, double y3) - { - NativeMethods.cairo_curve_to (handle, x1, y1, x2, y2, x3, y3); - } - - public void RelMoveTo (Distance d) - { - RelMoveTo (d.Dx, d.Dy); - } - - public void RelMoveTo (double dx, double dy) - { - NativeMethods.cairo_rel_move_to (handle, dx, dy); - } - - public void RelLineTo (Distance d) - { - RelLineTo (d.Dx, d.Dy); - } - - public void RelLineTo (double dx, double dy) - { - NativeMethods.cairo_rel_line_to (handle, dx, dy); - } - + => NativeMethods.cairo_curve_to (handle, x1, y1, x2, y2, x3, y3); + public void RelMoveTo (Distance d) => RelMoveTo (d.Dx, d.Dy); + public void RelMoveTo (double dx, double dy) => NativeMethods.cairo_rel_move_to (handle, dx, dy); + public void RelLineTo (Distance d) => RelLineTo (d.Dx, d.Dy); + public void RelLineTo (double dx, double dy) => NativeMethods.cairo_rel_line_to (handle, dx, dy); public void RelCurveTo (Distance d1, Distance d2, Distance d3) - { - RelCurveTo (d1.Dx, d1.Dy, d2.Dx, d2.Dy, d3.Dx, d3.Dy); - } - + => RelCurveTo (d1.Dx, d1.Dy, d2.Dx, d2.Dy, d3.Dx, d3.Dy); public void RelCurveTo (double dx1, double dy1, double dx2, double dy2, double dx3, double dy3) - { - NativeMethods.cairo_rel_curve_to (handle, dx1, dy1, dx2, dy2, dx3, dy3); - } - + => NativeMethods.cairo_rel_curve_to (handle, dx1, dy1, dx2, dy2, dx3, dy3); public void Arc (double xc, double yc, double radius, double angle1, double angle2) - { - NativeMethods.cairo_arc (handle, xc, yc, radius, angle1, angle2); - } + => NativeMethods.cairo_arc (handle, xc, yc, radius, angle1, angle2); public void Arc (PointD center, double radius, double angle1, double angle2) - { - NativeMethods.cairo_arc (handle, center.X, center.Y, radius, angle1, angle2); - } - + => NativeMethods.cairo_arc (handle, center.X, center.Y, radius, angle1, angle2); public void ArcNegative (double xc, double yc, double radius, double angle1, double angle2) - { - NativeMethods.cairo_arc_negative (handle, xc, yc, radius, angle1, angle2); - } + => NativeMethods.cairo_arc_negative (handle, xc, yc, radius, angle1, angle2); public void ArcNegative (PointD center, double radius, double angle1, double angle2) - { - NativeMethods.cairo_arc_negative (handle, center.X, center.Y, radius, angle1, angle2); - } - + => NativeMethods.cairo_arc_negative (handle, center.X, center.Y, radius, angle1, angle2); public void Rectangle (Rectangle rectangle) - { - Rectangle (rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height); - } + => Rectangle (rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height); public void Rectangle (RectangleD rectangle) - { - Rectangle (rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height); - } - + => Rectangle (rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height); public void Rectangle (PointD p, double width, double height) - { - Rectangle (p.X, p.Y, width, height); - } - + => Rectangle (p.X, p.Y, width, height); public void Rectangle (double x, double y, double width, double height) - { - NativeMethods.cairo_rectangle (handle, x, y, width, height); - } - - public void ClosePath () - { - NativeMethods.cairo_close_path (handle); - } - - public Path CopyPath () - { - return new Path (NativeMethods.cairo_copy_path (handle)); - } - - public Path CopyPathFlat () - { - return new Path (NativeMethods.cairo_copy_path_flat (handle)); - } - - public void AppendPath (Path path) - { - NativeMethods.cairo_append_path (handle, path.Handle); - } - -#endregion - -#region Painting Methods - public void Paint () - { - NativeMethods.cairo_paint (handle); - } - - public void PaintWithAlpha (double alpha) - { - NativeMethods.cairo_paint_with_alpha (handle, alpha); - } - - public void Mask (Pattern pattern) - { - NativeMethods.cairo_mask (handle, pattern.Handle); - } - + => NativeMethods.cairo_rectangle (handle, x, y, width, height); + public void ClosePath () => NativeMethods.cairo_close_path (handle); + public Path CopyPath () => new Path (NativeMethods.cairo_copy_path (handle)); + public Path CopyPathFlat () => new Path (NativeMethods.cairo_copy_path_flat (handle)); + public void AppendPath (Path path) => NativeMethods.cairo_append_path (handle, path.Handle); + #endregion + + #region Painting Methods + public void Paint () => NativeMethods.cairo_paint (handle); + 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); - } - - public void Stroke () - { - NativeMethods.cairo_stroke (handle); - } - - public void StrokePreserve () - { - NativeMethods.cairo_stroke_preserve (handle); - } - + => 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 () { double x1, y1, x2, y2; @@ -517,11 +332,8 @@ namespace Crow.CairoBackend return new Rectangle ((int)x1, (int)y1, (int)(x2 - x1), (int)(y2 - y1)); } - public void Fill () - { - NativeMethods.cairo_fill (handle); - } - + public void Fill () => NativeMethods.cairo_fill (handle); + public void FillPreserve () => NativeMethods.cairo_fill_preserve (handle); public Rectangle FillExtents () { double x1, y1, x2, y2; @@ -529,102 +341,36 @@ namespace Crow.CairoBackend return new Rectangle ((int)x1, (int)y1, (int)(x2 - x1), (int)(y2 - y1)); } - public void FillPreserve () - { - NativeMethods.cairo_fill_preserve (handle); - } - -#endregion - - public void Clip () - { - NativeMethods.cairo_clip (handle); - } - - public void ClipPreserve () - { - NativeMethods.cairo_clip_preserve (handle); - } - - public void ResetClip () - { - NativeMethods.cairo_reset_clip (handle); - } + #endregion - public bool InClip (double x, double y) - { - return NativeMethods.cairo_in_clip (handle, x, y); - } - public RectangleList GetClipRectangles (){ + public void Clip () => NativeMethods.cairo_clip (handle); + public void ClipPreserve () => NativeMethods.cairo_clip_preserve (handle); + public void ResetClip () => NativeMethods.cairo_reset_clip (handle); + public bool InClip (double x, double y) => NativeMethods.cairo_in_clip (handle, x, y); + /*public RectangleList GetClipRectangles (){ return (RectangleList)Marshal.PtrToStructure (NativeMethods.cairo_copy_clip_rectangle_list (handle), typeof(RectangleList)); - } + }*/ public void ClipExtendRectangle (){ double x1, y1, x2, y2; NativeMethods.cairo_clip_extents (handle, out x1, out y1, out x2, out y2); - NativeMethods.cairo_rectangle (handle, x1, y1, x2 - x1, y2 - y1); - } - public bool InStroke (double x, double y) - { - return NativeMethods.cairo_in_stroke (handle, x, y); - } - - public bool InFill (double x, double y) - { - return NativeMethods.cairo_in_fill (handle, x, y); - } - - public Pattern PopGroup () - { - return Pattern.Lookup (NativeMethods.cairo_pop_group (handle), true); - } - - public void PopGroupToSource () - { - NativeMethods.cairo_pop_group_to_source (handle); - } - - public void PushGroup () - { - NativeMethods.cairo_push_group (handle); - } - - public void PushGroup (Content content) - { - NativeMethods.cairo_push_group_with_content (handle, content); - } - - [Obsolete ("Use GetGroupTarget()")] - public Surface GroupTarget { - get { - return GetGroupTarget (); - } - } - + NativeMethods.cairo_rectangle (handle, x1, y1, x2 - x1, y2 - y1); + } + public bool InStroke (double x, double y) => NativeMethods.cairo_in_stroke (handle, x, y); + public bool InFill (double x, double y) => NativeMethods.cairo_in_fill (handle, x, y); + public Pattern PopGroup () => Pattern.Lookup (NativeMethods.cairo_pop_group (handle), true); + public void PopGroupToSource () => NativeMethods.cairo_pop_group_to_source (handle); + public void PushGroup () => NativeMethods.cairo_push_group (handle); + public void PushGroup (Content content) => NativeMethods.cairo_push_group_with_content (handle, content); public Surface GetGroupTarget () { IntPtr surface = NativeMethods.cairo_get_group_target (handle); return Surface.Lookup (surface, false); } - public void Rotate (double angle) - { - NativeMethods.cairo_rotate (handle, angle); - } - - public void Scale (double sx, double sy) - { - NativeMethods.cairo_scale (handle, sx, sy); - } - - public void Translate (double tx, double ty) - { - NativeMethods.cairo_translate (handle, tx, ty); - } - - public void Transform (Matrix m) - { - NativeMethods.cairo_transform (handle, m); - } + public void Rotate (double angle) => NativeMethods.cairo_rotate (handle, angle); + public void Scale (double sx, double sy) => NativeMethods.cairo_scale (handle, sx, sy); + public void Translate (double tx, double ty) => NativeMethods.cairo_translate (handle, tx, ty); + public void Transform (Matrix m) => NativeMethods.cairo_transform (handle, m); [Obsolete("Use UserToDevice instead")] public void TransformPoint (ref double x, ref double y) @@ -670,28 +416,12 @@ namespace Crow.CairoBackend NativeMethods.cairo_device_to_user_distance (handle, ref dx, ref dy); } - public Matrix Matrix { - set { - NativeMethods.cairo_set_matrix (handle, value); - } - - get { - Matrix m = new Matrix(); - NativeMethods.cairo_get_matrix (handle, m); - return m; - } - } - public void SetFontSize (double scale) { NativeMethods.cairo_set_font_size (handle, scale); } - public void IdentityMatrix () - { - NativeMethods.cairo_identity_matrix (handle); - } - + public void IdentityMatrix () => NativeMethods.cairo_identity_matrix (handle); public Matrix FontMatrix { get { Matrix m; @@ -853,18 +583,18 @@ namespace Crow.CairoBackend public void ShowText (ReadOnlySpan s, int tabSize) { int size = s.Length * 4 + 1; Span bytes = size > 512 ? new byte[size] : stackalloc byte[size]; - int encodedBytes = Text.Encoding.ToUtf8 (s, bytes, tabSize); + int encodedBytes = s.ToUtf8 (bytes, tabSize); bytes[encodedBytes] = 0; ShowText (bytes.Slice (0, encodedBytes + 1)); } public TextExtents TextExtents (ReadOnlySpan s, int tabSize) { - TextExtents (s, tabSize, out TextExtents extents); + TextExtents (s, tabSize, out TextExtents extents); return extents; } public void TextExtents (ReadOnlySpan s, int tabSize, out TextExtents extents) { int size = s.Length * 4 + 1; Span bytes = size > 512 ? new byte[size] : stackalloc byte[size]; - int encodedBytes = Text.Encoding.ToUtf8 (s, bytes, tabSize); + int encodedBytes = s.ToUtf8 (bytes, tabSize); bytes[encodedBytes] = 0; TextExtents (bytes.Slice (0, encodedBytes + 1), out extents); } @@ -887,5 +617,106 @@ namespace Crow.CairoBackend return extents; } + + public void Flush() + { + throw new NotImplementedException(); + } + + public void Clear() + { + throw new NotImplementedException(); + } + public void MoveTo(Point p) + { + throw new NotImplementedException(); + } + public void LineTo(Point p) + { + throw new NotImplementedException(); + } + +/* public void Arc(float xc, float yc, float radius, float a1, float a2) + { + throw new NotImplementedException(); + } + public void ArcNegative(float xc, float yc, float radius, float a1, float a2) + { + throw new NotImplementedException(); + } + + public void MoveTo(float x, float y) + { + throw new NotImplementedException(); + } + + public void RelMoveTo(float x, float y) + { + throw new NotImplementedException(); + } + + public void LineTo(float x, float y) + { + throw new NotImplementedException(); + } + public void RelLineTo(float x, float y) + { + throw new NotImplementedException(); + } + + public void CurveTo(float x1, float y1, float x2, float y2, float x3, float y3) + { + throw new NotImplementedException(); + } + + public void RelCurveTo(float x1, float y1, float x2, float y2, float x3, float y3) + { + throw new NotImplementedException(); + } + + public void Scale(float sx, float sy) + { + throw new NotImplementedException(); + } + + public void Translate(float dx, float dy) + { + throw new NotImplementedException(); + } + public void Rotate(float alpha) + { + throw new NotImplementedException(); + } + public void SetSource(float r, float g, float b, float a = 1) + { + throw new NotImplementedException(); + } + + public void SetSource(ISurface surf, float x = 0, float y = 0) + { + throw new NotImplementedException(); + } + + public void SetSourceSurface(ISurface surf, float x = 0, float y = 0) + { + throw new NotImplementedException(); + } +*/ + public void Translate(PointD p) + { + throw new NotImplementedException(); + } + public void RenderSvg(IntPtr svgNativeHandle, string subId = null) + { + throw new NotImplementedException(); + } + 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(ISurface surf, double x = 0, double y = 0) + => NativeMethods.cairo_set_source_surface (handle, surf.Handle, x, y); } } diff --git a/Backends/CairoBackend/src/DRMDevice.cs b/Backends/CairoBackend/src/DRMDevice.cs index 7bca9e6a..69009fc7 100644 --- a/Backends/CairoBackend/src/DRMDevice.cs +++ b/Backends/CairoBackend/src/DRMDevice.cs @@ -31,7 +31,7 @@ using System; namespace Crow.CairoBackend { - public class DRMDevice : Device + public class DRMDevice : CairoDevice { public DRMDevice () : base (NativeMethods.cairo_drm_device_default (), true) { @@ -44,10 +44,10 @@ namespace Crow.CairoBackend } public int FileDescriptor { - get { return NativeMethods.cairo_drm_device_get_fd (Handle); } + get { return NativeMethods.cairo_drm_device_get_fd (handle); } } - public void DeviceThrottle () { NativeMethods.cairo_drm_device_throttle (Handle);} + public void DeviceThrottle () { NativeMethods.cairo_drm_device_throttle (handle);} } } diff --git a/Backends/CairoBackend/src/Device.cs b/Backends/CairoBackend/src/Device.cs index 5191a23d..4cbb180f 100644 --- a/Backends/CairoBackend/src/Device.cs +++ b/Backends/CairoBackend/src/Device.cs @@ -28,33 +28,17 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; +using System.IO; +using System.Runtime.InteropServices; using Drawing2D; using Glfw; namespace Crow.CairoBackend { - public class Device : IDevice - { - IntPtr handle = IntPtr.Zero; - /// Global font rendering settings for Cairo - FontOptions FontRenderingOptions; - /// Global font rendering settings for Cairo - Antialias Antialias = Antialias.Subpixel; - - protected Device() - { - FontRenderingOptions = new FontOptions (); - FontRenderingOptions.Antialias = Antialias.Subpixel; - FontRenderingOptions.HintMetrics = HintMetrics.On; - FontRenderingOptions.HintStyle = HintStyle.Full; - FontRenderingOptions.SubpixelOrder = SubpixelOrder.Default; - } - - protected Device (IntPtr ptr) : this (ptr, true) - { - } - - protected Device (IntPtr handle, bool owner) + public abstract class CairoDevice : Device { + protected IntPtr handle = IntPtr.Zero; + public IntPtr Handle => handle; + protected CairoDevice (IntPtr handle, bool owner = true) { this.handle = handle; if (!owner) @@ -62,25 +46,11 @@ namespace Crow.CairoBackend if (CairoDebug.Enabled) CairoDebug.OnAllocated (handle); } - - ~Device () - { - Dispose (false); - } - - public IntPtr Handle { - get { - return handle; - } - } public string Status { get { return System.Runtime.InteropServices.Marshal.PtrToStringAuto(NativeMethods.cairo_status_to_string (NativeMethods.cairo_device_status (handle))); } } - public void SetThreadAware (bool value){ - NativeMethods.cairo_gl_device_set_thread_aware (handle, value ? 1 : 0); - } public Status Acquire() { return NativeMethods.cairo_device_acquire (handle); @@ -90,14 +60,10 @@ namespace Crow.CairoBackend NativeMethods.cairo_device_release (handle); } - public void Dispose () + protected override void Dispose (bool disposing) { - Dispose (true); - GC.SuppressFinalize (this); - } + base.Dispose (disposing); - protected virtual void Dispose (bool disposing) - { if (!disposing || CairoDebug.Enabled) CairoDebug.OnDisposed (handle, disposing); @@ -106,24 +72,46 @@ namespace Crow.CairoBackend NativeMethods.cairo_device_destroy (handle); - FontRenderingOptions.Dispose (); handle = IntPtr.Zero; } + } + public class Device : IDevice + { + /// Global font rendering settings for Cairo + FontOptions FontRenderingOptions; + /// Global font rendering settings for Cairo + Antialias Antialias = Antialias.Subpixel; - public void GetDpy(out int hdpy, out int vdpy) + public Device() { - throw new NotImplementedException(); + FontRenderingOptions = new FontOptions (); + FontRenderingOptions.Antialias = Antialias.Subpixel; + FontRenderingOptions.HintMetrics = HintMetrics.On; + FontRenderingOptions.HintStyle = HintStyle.Full; + FontRenderingOptions.SubpixelOrder = SubpixelOrder.Default; } - public void SetDpy(int hdpy, int vdpy) + ~Device () + { + Dispose (false); + } + + #region IDevice implementation + public void GetDpy(out int hdpy, out int vdpy) { throw new NotImplementedException(); } - public virtual ISurface CreateSurface(int width, int height) + public void SetDpy(int hdpy, int vdpy) { throw new NotImplementedException(); } + public IRegion CreateRegion () => new Region (); + public virtual ISurface CreateSurface(int width, int height) + => new ImageSurface (Format.ARGB32, width, height); + public virtual ISurface CreateSurface(byte[] data, int width, int height) + => new ImageSurface (data, Format.ARGB32, width, height, 4 * width); + public ISurface CreateSurface (IntPtr nativeWindoPointer, int width, int height) { switch (Environment.OSVersion.Platform) { case PlatformID.Unix: @@ -147,8 +135,73 @@ namespace Crow.CairoBackend Context gr = new Context (surf); gr.FontOptions = FontRenderingOptions; gr.Antialias = Antialias; - throw new NotImplementedException(); + return gr; + } + public byte[] LoadBitmap (Stream stream, out Size dimensions) { + byte[] image; +#if STB_SHARP + StbImageSharp.ImageResult stbi = StbImageSharp.ImageResult.FromStream (stream, StbImageSharp.ColorComponents.RedGreenBlueAlpha); + image = new byte[stbi.Data.Length]; + //rgba to argb for cairo. + for (int i = 0; i < stbi.Data.Length; i += 4) { + image[i] = stbi.Data[i + 2]; + image[i + 1] = stbi.Data[i + 1]; + image[i + 2] = stbi.Data[i]; + image[i + 3] = stbi.Data[i + 3]; + } + dimensions = new Size (stbi.Width, stbi.Height); +#else + using (StbImage stbi = new StbImage (stream)) { + image = new byte [stbi.Size]; + for (int i = 0; i < stbi.Size; i+=4) { + //rgba to argb for cairo. ???? looks like bgra to me. + image [i] = Marshal.ReadByte (stbi.Handle, i + 2); + image [i + 1] = Marshal.ReadByte (stbi.Handle, i + 1); + image [i + 2] = Marshal.ReadByte (stbi.Handle, i); + image [i + 3] = Marshal.ReadByte (stbi.Handle, i + 3); + } + dimensions = new Size (stbi.Width, stbi.Height); + } +#endif + return image; + } + public ISvgHandle LoadSvg(Stream stream) + { + using (BinaryReader sr = new BinaryReader (stream)) + return new SvgHandle (sr.ReadBytes ((int)stream.Length)); + } + + public ISvgHandle LoadSvg(string svgFragment) => + new SvgHandle (System.Text.Encoding.Unicode.GetBytes (svgFragment)); + + public IGradient CreateGradient (GradientType gradientType, Rectangle bounds) { + 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; + } + #endregion + + #region IDispose implementation + public void Dispose () + { + Dispose (true); + GC.SuppressFinalize (this); + } + + protected virtual void Dispose (bool disposing) + { + if (disposing) + FontRenderingOptions.Dispose (); } + #endregion } } diff --git a/Backends/CairoBackend/src/EGLDevice.cs b/Backends/CairoBackend/src/EGLDevice.cs index 1f73ef4f..5305298b 100644 --- a/Backends/CairoBackend/src/EGLDevice.cs +++ b/Backends/CairoBackend/src/EGLDevice.cs @@ -31,7 +31,7 @@ using System; namespace Crow.CairoBackend { - public class EGLDevice : Device + public class EGLDevice : GLDevice { public EGLDevice (IntPtr dpy, IntPtr gl_ctx) : base (NativeMethods.cairo_egl_device_create (dpy, gl_ctx), true) { diff --git a/Backends/CairoBackend/src/GLDevice.cs b/Backends/CairoBackend/src/GLDevice.cs new file mode 100644 index 00000000..c7992b74 --- /dev/null +++ b/Backends/CairoBackend/src/GLDevice.cs @@ -0,0 +1,17 @@ +// Copyright (c) 2021 Jean-Philippe Bruyère +// +// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) +using System; + +namespace Crow.CairoBackend +{ + public abstract class GLDevice : CairoDevice + { + protected GLDevice (IntPtr handle, bool owner = true) : base (handle, owner) {} + public void SetThreadAware (bool value) { + NativeMethods.cairo_gl_device_set_thread_aware (handle, value ? 1 : 0); + } + + } +} + diff --git a/Backends/CairoBackend/src/GLSurface.cs b/Backends/CairoBackend/src/GLSurface.cs index 117bd60f..ddbf0a4f 100644 --- a/Backends/CairoBackend/src/GLSurface.cs +++ b/Backends/CairoBackend/src/GLSurface.cs @@ -37,7 +37,7 @@ namespace Crow.CairoBackend { public GLSurface (IntPtr ptr, bool own) : base (ptr, own) {} - public GLSurface (Device device, Content content, uint tex, int width, int height) + public GLSurface (CairoDevice device, Content content, uint tex, int width, int height) : base (NativeMethods.cairo_gl_surface_create_for_texture (device.Handle, (uint)content, tex, width, height), true) {} diff --git a/Backends/CairoBackend/src/GLXDevice.cs b/Backends/CairoBackend/src/GLXDevice.cs index 8c080df5..4a788c99 100644 --- a/Backends/CairoBackend/src/GLXDevice.cs +++ b/Backends/CairoBackend/src/GLXDevice.cs @@ -31,18 +31,18 @@ using System; namespace Crow.CairoBackend { - public class GLXDevice : Device + public class GLXDevice : CairoDevice { public GLXDevice (IntPtr dpy, IntPtr gl_ctx) : base (NativeMethods.cairo_glx_device_create (dpy, gl_ctx), true) { } public IntPtr Display { - get { return NativeMethods.cairo_glx_device_get_display (Handle); } + get { return NativeMethods.cairo_glx_device_get_display (handle); } } public IntPtr Context { - get { return NativeMethods.cairo_glx_device_get_context (Handle); } + get { return NativeMethods.cairo_glx_device_get_context (handle); } } } } diff --git a/Backends/CairoBackend/src/Gradient.cs b/Backends/CairoBackend/src/Gradient.cs index 3dd0d9d2..74ac7d48 100644 --- a/Backends/CairoBackend/src/Gradient.cs +++ b/Backends/CairoBackend/src/Gradient.cs @@ -28,11 +28,11 @@ // using System; -using Color = Drawing2D.Color; +using Drawing2D; namespace Crow.CairoBackend { - public class Gradient : Pattern + public class Gradient : Pattern, IGradient { protected Gradient (IntPtr handle, bool owned) : base (handle, owned) { @@ -41,20 +41,20 @@ namespace Crow.CairoBackend { public int ColorStopCount { get { int cnt; - NativeMethods.cairo_pattern_get_color_stop_count (Handle, out cnt); + NativeMethods.cairo_pattern_get_color_stop_count (handle, out cnt); return cnt; } } - - public Status AddColorStop (double offset, Color c) - { - NativeMethods.cairo_pattern_add_color_stop_rgba (Handle, offset, c.R / 255.0, c.G / 255.0, c.B / 255.0, c.A / 255.0); - return Status; - } + #region IGradient implementation + public void AddColorStop (double offset, Color c) + => NativeMethods.cairo_pattern_add_color_stop_rgba (handle, offset, c.R / 255.0, c.G / 255.0, c.B / 255.0, c.A / 255.0); + public void AddColorStop(float offset, float r, float g, float b, float a = 1) + => NativeMethods.cairo_pattern_add_color_stop_rgba (handle, offset, r, g, b, a); + #endregion public Status AddColorStopRgb (double offset, Color c) { - NativeMethods.cairo_pattern_add_color_stop_rgb (Handle, offset, c.R / 255.0, c.G / 255.0 / 255.0, c.B / 255.0); + NativeMethods.cairo_pattern_add_color_stop_rgb (handle, offset, c.R / 255.0, c.G / 255.0 / 255.0, c.B / 255.0); return Status; } } diff --git a/Backends/CairoBackend/src/LinearGradient.cs b/Backends/CairoBackend/src/LinearGradient.cs index 32b83db2..49e423ed 100644 --- a/Backends/CairoBackend/src/LinearGradient.cs +++ b/Backends/CairoBackend/src/LinearGradient.cs @@ -48,7 +48,7 @@ namespace Crow.CairoBackend { double x0, y0, x1, y1; PointD[] points = new PointD [2]; - NativeMethods.cairo_pattern_get_linear_points (Handle, out x0, out y0, out x1, out y1); + NativeMethods.cairo_pattern_get_linear_points (handle, out x0, out y0, out x1, out y1); points[0] = new PointD (x0, y0); points[1] = new PointD (x1, y1); diff --git a/Backends/CairoBackend/src/Matrix.cs b/Backends/CairoBackend/src/Matrix.cs index b1925688..b565edcc 100644 --- a/Backends/CairoBackend/src/Matrix.cs +++ b/Backends/CairoBackend/src/Matrix.cs @@ -37,7 +37,7 @@ using System.Runtime.InteropServices; namespace Crow.CairoBackend { [StructLayout(LayoutKind.Sequential)] - public class Matrix //: ICloneable + public struct Matrix //: ICloneable { public double Xx; public double Yx; @@ -52,12 +52,6 @@ namespace Crow.CairoBackend { this.Xx = xx; this.Yx = yx; this.Xy = xy; this.Yy = yy; this.X0 = x0; this.Y0 = y0; } - - public Matrix () - { - this.InitIdentity (); - } - public bool IsIdentity () { return (this == new Matrix ()); diff --git a/Backends/CairoBackend/src/MeshPattern.cs b/Backends/CairoBackend/src/MeshPattern.cs index f2576705..39fdd2af 100644 --- a/Backends/CairoBackend/src/MeshPattern.cs +++ b/Backends/CairoBackend/src/MeshPattern.cs @@ -45,64 +45,64 @@ namespace Crow.CairoBackend { //no idea why this is here, the base one is identical, but we can't remove it now public new Extend Extend { - set { NativeMethods.cairo_pattern_set_extend (Handle, value); } - get { return NativeMethods.cairo_pattern_get_extend (Handle); } + set { NativeMethods.cairo_pattern_set_extend (handle, value); } + get { return NativeMethods.cairo_pattern_get_extend (handle); } } public Filter Filter { - set { NativeMethods.cairo_pattern_set_filter (Handle, value); } - get { return NativeMethods.cairo_pattern_get_filter (Handle); } + set { NativeMethods.cairo_pattern_set_filter (handle, value); } + get { return NativeMethods.cairo_pattern_get_filter (handle); } } public void BeginPatch(){ - NativeMethods.cairo_mesh_pattern_begin_patch (Handle); + NativeMethods.cairo_mesh_pattern_begin_patch (handle); } public void EndPatch(){ - NativeMethods.cairo_mesh_pattern_end_patch (Handle); + NativeMethods.cairo_mesh_pattern_end_patch (handle); } public void MoveTo(double x, double y){ - NativeMethods.cairo_mesh_pattern_move_to (Handle, x, y); + NativeMethods.cairo_mesh_pattern_move_to (handle, x, y); } public void MoveTo (PointD p) { - NativeMethods.cairo_mesh_pattern_move_to (Handle, p.X, p.Y); + NativeMethods.cairo_mesh_pattern_move_to (handle, p.X, p.Y); } public void LineTo(double x, double y){ - NativeMethods.cairo_mesh_pattern_line_to (Handle, x, y); + NativeMethods.cairo_mesh_pattern_line_to (handle, x, y); } public void LineTo (PointD p) { - NativeMethods.cairo_mesh_pattern_line_to (Handle, p.X, p.Y); + NativeMethods.cairo_mesh_pattern_line_to (handle, p.X, p.Y); } public void CurveTo(double x1, double y1, double x2, double y2, double x3, double y3) { - NativeMethods.cairo_mesh_pattern_curve_to (Handle, x1, y1, x2, y2, x3, y3); + NativeMethods.cairo_mesh_pattern_curve_to (handle, x1, y1, x2, y2, x3, y3); } public void SetControlPoint(uint point_num, double x, double y){ - NativeMethods.cairo_mesh_pattern_set_control_point (Handle, point_num, x, y); + NativeMethods.cairo_mesh_pattern_set_control_point (handle, point_num, x, y); } public void SetControlPoint (uint point_num, PointD p) { - NativeMethods.cairo_mesh_pattern_set_control_point (Handle, point_num, p.X, p.Y); + NativeMethods.cairo_mesh_pattern_set_control_point (handle, point_num, p.X, p.Y); } public void SetCornerColorRGB(uint corner_num, double r, double g, double b){ - NativeMethods.cairo_mesh_pattern_set_corner_color_rgb (Handle, corner_num, r, g, b); + NativeMethods.cairo_mesh_pattern_set_corner_color_rgb (handle, corner_num, r, g, b); } public void SetCornerColorRGBA(uint corner_num, double r, double g, double b, double a){ - NativeMethods.cairo_mesh_pattern_set_corner_color_rgba (Handle, corner_num, r, g, b, a); + NativeMethods.cairo_mesh_pattern_set_corner_color_rgba (handle, corner_num, r, g, b, a); } public void SetCornerColor (uint corner_num, Color c) { - NativeMethods.cairo_mesh_pattern_set_corner_color_rgba (Handle, corner_num, c.R, c.G, c.B, c.A); + NativeMethods.cairo_mesh_pattern_set_corner_color_rgba (handle, corner_num, c.R, c.G, c.B, c.A); } public uint PatchCount { get { uint count = 0; - NativeMethods.cairo_mesh_pattern_get_patch_count(Handle, out count); + NativeMethods.cairo_mesh_pattern_get_patch_count(handle, out count); return count; } } public Path GetPath(uint patch_num){ - return new Path(NativeMethods.cairo_mesh_pattern_get_path(Handle, patch_num)); + return new Path(NativeMethods.cairo_mesh_pattern_get_path(handle, patch_num)); } public PointD GetControlPoint(uint point_num, uint patch_num = 0) { - NativeMethods.cairo_mesh_pattern_get_control_point (Handle, patch_num, point_num, out double x, out double y); + NativeMethods.cairo_mesh_pattern_get_control_point (handle, patch_num, point_num, out double x, out double y); return new PointD (x, y); } public void GetCornerColorRGBA(){ diff --git a/Backends/CairoBackend/src/NativeMethods.cs b/Backends/CairoBackend/src/NativeMethods.cs index 27f61154..7b6053ac 100644 --- a/Backends/CairoBackend/src/NativeMethods.cs +++ b/Backends/CairoBackend/src/NativeMethods.cs @@ -233,7 +233,7 @@ namespace Crow.CairoBackend internal static extern double cairo_get_line_width (IntPtr cr); [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)] - internal static extern void cairo_get_matrix (IntPtr cr, Matrix matrix); + internal static extern void cairo_get_matrix (IntPtr cr, out Matrix matrix); [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)] internal static extern double cairo_get_miter_limit (IntPtr cr); @@ -723,7 +723,7 @@ namespace Crow.CairoBackend internal static extern void cairo_set_line_width (IntPtr cr, double width); [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)] - internal static extern void cairo_set_matrix (IntPtr cr, Matrix matrix); + internal static extern void cairo_set_matrix (IntPtr cr, ref Matrix matrix); [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)] internal static extern void cairo_set_miter_limit (IntPtr cr, double limit); diff --git a/Backends/CairoBackend/src/Pattern.cs b/Backends/CairoBackend/src/Pattern.cs index 545dda36..137f67fe 100644 --- a/Backends/CairoBackend/src/Pattern.cs +++ b/Backends/CairoBackend/src/Pattern.cs @@ -14,10 +14,10 @@ // 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 @@ -28,21 +28,19 @@ // using System; -using System.Collections; using Drawing2D; -namespace Crow.CairoBackend { - - public class Pattern : IDisposable +namespace Crow.CairoBackend +{ + public class Pattern : IPattern { - [Obsolete] - protected IntPtr pattern = IntPtr.Zero; - + internal IntPtr handle; + public IntPtr Handle => handle; public static Pattern Lookup (IntPtr pattern, bool owner) { if (pattern == IntPtr.Zero) return null; - + PatternType pt = NativeMethods.cairo_pattern_get_type (pattern); switch (pt) { case PatternType.Solid: @@ -58,98 +56,73 @@ namespace Crow.CairoBackend { } } - [Obsolete] - protected Pattern () - { - } - internal Pattern (IntPtr handle, bool owned) { - Handle = handle; + this.handle = handle; if (!owned) NativeMethods.cairo_pattern_reference (handle); if (CairoDebug.Enabled) CairoDebug.OnAllocated (handle); } - ~Pattern () - { - Dispose (false); - } - [Obsolete ("Use the SurfacePattern constructor")] public Pattern (Surface surface) : this ( NativeMethods.cairo_pattern_create_for_surface (surface.Handle), true) { } - + [Obsolete] protected void Reference () { - NativeMethods.cairo_pattern_reference (pattern); - } - - public void Dispose () - { - Dispose (true); - GC.SuppressFinalize (this); - } - - protected virtual void Dispose (bool disposing) - { - if (!disposing || CairoDebug.Enabled) - CairoDebug.OnDisposed (Handle, disposing); - - if (!disposing|| Handle == IntPtr.Zero) - return; - - NativeMethods.cairo_pattern_destroy (Handle); - Handle = IntPtr.Zero; + NativeMethods.cairo_pattern_reference (handle); } - [Obsolete ("Use Dispose()")] - public void Destroy () - { - Dispose (); - } - public Status Status - { - get { return NativeMethods.cairo_pattern_status (Handle); } - } - public Extend Extend - { - get { return NativeMethods.cairo_pattern_get_extend (Handle); } - set { NativeMethods.cairo_pattern_set_extend (Handle, value); } - } + public Status Status => NativeMethods.cairo_pattern_status (handle); public Matrix Matrix { - set { - NativeMethods.cairo_pattern_set_matrix (Handle, value); - } - + set => NativeMethods.cairo_pattern_set_matrix (handle, value); get { Matrix m = new Matrix (); - NativeMethods.cairo_pattern_get_matrix (Handle, m); + NativeMethods.cairo_pattern_get_matrix (handle, m); return m; } } -#pragma warning disable 612 - public IntPtr Handle { - get { return pattern; } - private set { pattern = value; } + public PatternType PatternType => NativeMethods.cairo_pattern_get_type (handle); + + #region IPattern implementation + public Extend Extend + { + get { return NativeMethods.cairo_pattern_get_extend (handle); } + set { NativeMethods.cairo_pattern_set_extend (handle, value); } + } + public Filter Filter { + get => NativeMethods.cairo_pattern_get_filter (handle); + set => NativeMethods.cairo_pattern_set_filter (handle, value); } -#pragma warning restore 612 + #endregion - [Obsolete] - public IntPtr Pointer { - get { return pattern; } + ~Pattern () + { + Dispose (false); } + public void Dispose () + { + Dispose (true); + GC.SuppressFinalize (this); + } + protected virtual void Dispose (bool disposing) + { + if (!disposing || CairoDebug.Enabled) + CairoDebug.OnDisposed (handle, disposing); + + if (!disposing|| handle == IntPtr.Zero) + return; - public PatternType PatternType { - get { return NativeMethods.cairo_pattern_get_type (Handle); } + NativeMethods.cairo_pattern_destroy (handle); + handle = IntPtr.Zero; } } } diff --git a/Backends/CairoBackend/src/Region.cs b/Backends/CairoBackend/src/Region.cs index 5466b121..139ebc8e 100644 --- a/Backends/CairoBackend/src/Region.cs +++ b/Backends/CairoBackend/src/Region.cs @@ -21,34 +21,25 @@ // using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; using Drawing2D; namespace Crow.CairoBackend { [StructLayout(LayoutKind.Sequential)] - public struct RectangleList { + struct RectangleList { public Status Status; public IntPtr Rectangles; public int NumRectangles; } - public enum RegionOverlap { - In, - Out, - Part, - } - public class Region : IDisposable { + public class Region : IRegion { IntPtr handle; - public IntPtr Handle { - get { return handle; } - } - - [Obsolete] - public Region (IntPtr handle) : this (handle, false) {} + #region CTOR public Region (IntPtr handle, bool owned) { this.handle = handle; @@ -57,148 +48,127 @@ namespace Crow.CairoBackend if (CairoDebug.Enabled) CairoDebug.OnAllocated (handle); } - public Region () : this (NativeMethods.cairo_region_create () , true) - { - } - - public Region (Rectangle rect) - { + {} + public Region (Rectangle rect) { handle = NativeMethods.cairo_region_create_rectangle (ref rect); } - - public Region (RectangleList rects) - { - handle = NativeMethods.cairo_region_create_rectangles (rects.Rectangles, rects.NumRectangles); - } - - public Region Copy () - { - return new Region (NativeMethods.cairo_region_copy (Handle), true); - } - - #region IDisposable - ~Region () - { - Dispose (false); - } - - public void Dispose () - { - Dispose (true); - GC.SuppressFinalize (this); - } - - protected virtual void Dispose (bool disposing) - { - if (!disposing || CairoDebug.Enabled) - CairoDebug.OnDisposed (handle, disposing); - - if (!disposing|| handle == IntPtr.Zero) - return; - - NativeMethods.cairo_region_destroy (Handle); - handle = IntPtr.Zero; - } #endregion - public override bool Equals (object obj) - { - return (obj is Region) && NativeMethods.cairo_region_equal (Handle, (obj as Region).Handle); - } + public Region Copy () => new Region (NativeMethods.cairo_region_copy (handle), true); - public override int GetHashCode () - { - return Handle.GetHashCode (); - } public Status Status { - get { return NativeMethods.cairo_region_status (Handle); } + get { return NativeMethods.cairo_region_status (handle); } } public Rectangle Extents { get { Rectangle result; - NativeMethods.cairo_region_get_extents (Handle, out result); + NativeMethods.cairo_region_get_extents (handle, out result); return result; } } - public int NumRectangles { - get { return NativeMethods.cairo_region_num_rectangles (Handle); } - } - - public Rectangle GetRectangle (int nth) - { - Rectangle val; - NativeMethods.cairo_region_get_rectangle (Handle, nth, out val); - return val; - } - - public bool IsEmpty { - get { return NativeMethods.cairo_region_is_empty (Handle); } - } - - public RegionOverlap Contains (Rectangle rectangle) - { - return NativeMethods.cairo_region_contains_rectangle (Handle, ref rectangle); - } - public bool Contains (int x, int y) { - return NativeMethods.cairo_region_contains_point (Handle, x, y); + return NativeMethods.cairo_region_contains_point (handle, x, y); } public void Translate (int dx, int dy) { - NativeMethods.cairo_region_translate (Handle, dx, dy); + NativeMethods.cairo_region_translate (handle, dx, dy); } public Status Subtract (Region other) { - return NativeMethods.cairo_region_subtract (Handle, other.Handle); + return NativeMethods.cairo_region_subtract (handle, other.handle); } public Status SubtractRectangle (Rectangle rectangle) { - return NativeMethods.cairo_region_subtract_rectangle (Handle, ref rectangle); + return NativeMethods.cairo_region_subtract_rectangle (handle, ref rectangle); } public Status Intersect (Region other) { - return NativeMethods.cairo_region_intersect (Handle, other.Handle); + return NativeMethods.cairo_region_intersect (handle, other.handle); } public Status IntersectRectangle (Rectangle rectangle) { - return NativeMethods.cairo_region_intersect_rectangle (Handle, ref rectangle); + return NativeMethods.cairo_region_intersect_rectangle (handle, ref rectangle); } public Status Union (Region other) { - return NativeMethods.cairo_region_union (Handle, other.Handle); + return NativeMethods.cairo_region_union (handle, other.handle); } - public Status UnionRectangle (Rectangle rectangle) - { - return NativeMethods.cairo_region_union_rectangle (Handle, ref rectangle); - } public Status Xor (Region other) { - return NativeMethods.cairo_region_xor (Handle, other.Handle); + return NativeMethods.cairo_region_xor (handle, other.handle); } public Status XorRectangle (Rectangle rectangle) { - return NativeMethods.cairo_region_xor_rectangle (Handle, ref rectangle); + return NativeMethods.cairo_region_xor_rectangle (handle, ref rectangle); + } + + #region IRegion implementation + public bool IsEmpty => NativeMethods.cairo_region_is_empty (handle); + public int NumRectangles => NativeMethods.cairo_region_num_rectangles (handle); + public Rectangle GetRectangle (int nth) + { + Rectangle val; + NativeMethods.cairo_region_get_rectangle (handle, nth, out val); + return val; } + public void UnionRectangle (Rectangle rectangle) + => NativeMethods.cairo_region_union_rectangle (handle, ref rectangle); + public bool OverlapOut (Rectangle rectangle) => Contains (rectangle) == RegionOverlap.Out; + public RegionOverlap Contains (Rectangle rectangle) + => NativeMethods.cairo_region_contains_rectangle (handle, ref rectangle); public void Reset () { if (IsEmpty) return; - NativeMethods.cairo_region_destroy (Handle); + NativeMethods.cairo_region_destroy (handle); handle = NativeMethods.cairo_region_create (); } - public bool OverlapOut (Rectangle rectangle) => Contains (rectangle) == RegionOverlap.Out; + + public bool Equals(IRegion other) + => other is Region r ? NativeMethods.cairo_region_equal (handle, r.handle) : false; + #endregion + + public override bool Equals (object obj) + => obj is Region r ? NativeMethods.cairo_region_equal (handle, r.handle) : false; + + public override int GetHashCode () => handle.GetHashCode (); + + #region IDisposable + ~Region () + { + Dispose (false); + } + + public void Dispose () + { + Dispose (true); + GC.SuppressFinalize (this); + } + + protected virtual void Dispose (bool disposing) + { + if (!disposing || CairoDebug.Enabled) + CairoDebug.OnDisposed (handle, disposing); + + if (!disposing|| handle == IntPtr.Zero) + return; + + NativeMethods.cairo_region_destroy (handle); + handle = IntPtr.Zero; + } + #endregion } } diff --git a/Backends/CairoBackend/src/SolidPattern.cs b/Backends/CairoBackend/src/SolidPattern.cs index 8d52fb01..65e86a01 100644 --- a/Backends/CairoBackend/src/SolidPattern.cs +++ b/Backends/CairoBackend/src/SolidPattern.cs @@ -28,7 +28,8 @@ // using System; -using Color = Drawing2D.Color; +using Drawing2D; + namespace Crow.CairoBackend { public class SolidPattern : Pattern @@ -63,7 +64,7 @@ namespace Crow.CairoBackend { public Color Color { get { double red, green, blue, alpha; - NativeMethods.cairo_pattern_get_rgba (Handle, out red, out green, out blue, out alpha); + NativeMethods.cairo_pattern_get_rgba (handle, out red, out green, out blue, out alpha); return new Color (red, green, blue, alpha); } } diff --git a/Backends/CairoBackend/src/Surface.cs b/Backends/CairoBackend/src/Surface.cs index b41af1a4..2d6fac10 100644 --- a/Backends/CairoBackend/src/Surface.cs +++ b/Backends/CairoBackend/src/Surface.cs @@ -34,14 +34,13 @@ // using System; -using System.Collections; using Drawing2D; namespace Crow.CairoBackend { public class Surface : ISurface { - IntPtr handle = IntPtr.Zero; + protected IntPtr handle = IntPtr.Zero; [Obsolete] protected Surface() @@ -144,7 +143,7 @@ namespace Crow.CairoBackend { NativeMethods.cairo_surface_destroy (handle); handle = IntPtr.Zero; } - public virtual void SetSize (int width, int height) { + public virtual void Resize (int width, int height) { } public Status Finish () diff --git a/Backends/CairoBackend/src/SurfacePattern.cs b/Backends/CairoBackend/src/SurfacePattern.cs index 7b06265f..83b98a8c 100644 --- a/Backends/CairoBackend/src/SurfacePattern.cs +++ b/Backends/CairoBackend/src/SurfacePattern.cs @@ -45,13 +45,13 @@ namespace Crow.CairoBackend { //no idea why this is here, the base one is identical, but we can't remove it now public new Extend Extend { - set { NativeMethods.cairo_pattern_set_extend (Handle, value); } - get { return NativeMethods.cairo_pattern_get_extend (Handle); } + set { NativeMethods.cairo_pattern_set_extend (handle, value); } + get { return NativeMethods.cairo_pattern_get_extend (handle); } } public Filter Filter { - set { NativeMethods.cairo_pattern_set_filter (Handle, value); } - get { return NativeMethods.cairo_pattern_get_filter (Handle); } + set { NativeMethods.cairo_pattern_set_filter (handle, value); } + get { return NativeMethods.cairo_pattern_get_filter (handle); } } } } diff --git a/Backends/CairoBackend/src/WGLDevice.cs b/Backends/CairoBackend/src/WGLDevice.cs index 18179948..4d7773e5 100644 --- a/Backends/CairoBackend/src/WGLDevice.cs +++ b/Backends/CairoBackend/src/WGLDevice.cs @@ -31,14 +31,14 @@ using System; namespace Crow.CairoBackend { - public class WGLDevice : Device + public class WGLDevice : GLDevice { public WGLDevice (IntPtr hglrc) : base (NativeMethods.cairo_wgl_device_create (hglrc), true) { } public IntPtr Context { - get { return NativeMethods.cairo_wgl_device_get_context (Handle); } + get { return NativeMethods.cairo_wgl_device_get_context (handle); } } } } diff --git a/Backends/CairoBackend/src/Win32Surface.cs b/Backends/CairoBackend/src/Win32Surface.cs index f620673e..a10a9cf2 100644 --- a/Backends/CairoBackend/src/Win32Surface.cs +++ b/Backends/CairoBackend/src/Win32Surface.cs @@ -32,6 +32,7 @@ namespace Crow.CairoBackend { public class Win32Surface : Surface { + IntPtr hdc; internal Win32Surface (IntPtr handle, bool owns) : base (handle, owns) { } @@ -39,6 +40,16 @@ namespace Crow.CairoBackend { public Win32Surface (IntPtr hdc) : base (NativeMethods.cairo_win32_surface_create (hdc), true) { + this.hdc = hdc; + } + public override void Resize(int width, int height) + { + if (hdc == IntPtr.Zero) + base.Resize (width, height); + else { + NativeMethods.cairo_surface_destroy (handle); + handle = NativeMethods.cairo_win32_surface_create (hdc); + } } } } diff --git a/Backends/CairoBackend/src/XcbSurface.cs b/Backends/CairoBackend/src/XcbSurface.cs index affc46f8..bb198a71 100644 --- a/Backends/CairoBackend/src/XcbSurface.cs +++ b/Backends/CairoBackend/src/XcbSurface.cs @@ -45,7 +45,7 @@ namespace Crow.CairoBackend { IntPtr ptr = NativeMethods.cairo_xcb_surface_create_for_bitmap (connection, bitmap, screen, width, height); return new XcbSurface (ptr, true); } - public override void SetSize (int width, int height) + public override void Resize (int width, int 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 602400e5..df4b2619 100644 --- a/Backends/CairoBackend/src/XlibSurface.cs +++ b/Backends/CairoBackend/src/XlibSurface.cs @@ -60,7 +60,7 @@ namespace Crow.CairoBackend { NativeMethods.cairo_xlib_surface_set_drawable (Handle, drawable, width, height); } - public override void SetSize (int width, int height) + public override void Resize (int width, int height) { NativeMethods.cairo_xlib_surface_set_size (Handle, width, height); } diff --git a/Backends/CairoBackend/src/rsvg/SvgHandle.cs b/Backends/CairoBackend/src/rsvg/SvgHandle.cs index 1622ecfa..6db657fd 100644 --- a/Backends/CairoBackend/src/rsvg/SvgHandle.cs +++ b/Backends/CairoBackend/src/rsvg/SvgHandle.cs @@ -6,7 +6,7 @@ using Drawing2D; namespace Crow.CairoBackend { - public sealed class SvgHandle : IDisposable { + public sealed class SvgHandle : ISvgHandle { const string lib = "rsvg-2.40"; public IntPtr Raw; @@ -58,10 +58,10 @@ namespace Crow.CairoBackend { public void SetDpiXY (double dpi_x, double dpi_y) => rsvg_handle_set_dpi_x_y (Raw, dpi_x, dpi_y); - public void Render(Context cr) => + public void Render(IContext cr) => rsvg_handle_render_cairo (Raw, cr == null ? IntPtr.Zero : cr.Handle); - public void Render (Context cr, string id) => + public void Render (IContext cr, string id) => rsvg_handle_render_cairo_sub (Raw, cr == null ? IntPtr.Zero : cr.Handle, id); [StructLayout(LayoutKind.Sequential)] diff --git a/Backends/VkvgBackend/VkvgBackend.csproj b/Backends/VkvgBackend/VkvgBackend.csproj index c14bad89..87455c68 100644 --- a/Backends/VkvgBackend/VkvgBackend.csproj +++ b/Backends/VkvgBackend/VkvgBackend.csproj @@ -1,16 +1,21 @@ - netcoreapp3.0 - false + netcoreapp3.0 + false - - - + + + - - - + + + + + + + $(DefineConstants);STB_SHARP + diff --git a/Backends/VkvgBackend/src/Context.cs b/Backends/VkvgBackend/src/Context.cs index 11f63de3..20a3cdaa 100644 --- a/Backends/VkvgBackend/src/Context.cs +++ b/Backends/VkvgBackend/src/Context.cs @@ -5,11 +5,11 @@ using System; using System.Text; using System.Linq; -using Crow; +using Drawing2D; -namespace Crow.Drawing +namespace Crow.VkvgBackend { - public class Context : IDisposable + public class Context : IContext { IntPtr handle = IntPtr.Zero; @@ -26,12 +26,6 @@ namespace Crow.Drawing public IntPtr Handle => handle; - public void AddReference() - { - NativeMethods.vkvg_reference(handle); - } - public uint References() => NativeMethods.vkvg_get_reference_count(handle); - public double LineWidth { get => NativeMethods.vkvg_get_line_width(handle); @@ -47,14 +41,6 @@ namespace Crow.Drawing get => NativeMethods.vkvg_get_line_cap(handle); set { NativeMethods.vkvg_set_line_cap(handle, value); } } - public uint FontSize - { - set { NativeMethods.vkvg_set_font_size(handle, value); } - } - public string FontFace - { - set { NativeMethods.vkvg_select_font_face(handle, value); } - } public Operator Operator { set { NativeMethods.vkvg_set_operator(handle, value); } @@ -65,36 +51,60 @@ namespace Crow.Drawing set { NativeMethods.vkvg_set_fill_rule(handle, value); } get { return NativeMethods.vkvg_get_fill_rule(handle); } } - public FontExtents FontExtents + public Drawing2D.FontExtents FontExtents { get { - FontExtents f_extents; - NativeMethods.vkvg_font_extents(handle, out f_extents); - return f_extents; + FontExtents e; + NativeMethods.vkvg_font_extents(handle, out e); + return new Drawing2D.FontExtents (e.Ascent, e.Descent, e.Height, e.MaxXAdvance, e.MaxYAdvance); } } public Antialias Antialias { set; get; } - public TextExtents TextExtents (ReadOnlySpan s, int tabSize = 4) { - TextExtents (s, tabSize, out TextExtents extents); - return extents; + 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 TextExtents (ReadOnlySpan s, int tabSize, out TextExtents extents) { - if (s.Length == 0) { - extents = default; - return; - } - int size = s.Length * 4 + 1; - Span bytes = size > 512 ? new byte[size] : stackalloc byte[size]; - int encodedBytes = Crow.Text.Encoding.ToUtf8 (s, bytes, tabSize); - bytes[encodedBytes] = 0; - TextExtents (bytes.Slice (0, encodedBytes + 1), out extents); + + public void Clear() => NativeMethods.vkvg_clear(handle); + + public void Clip() => NativeMethods.vkvg_clip(handle); + public void ClipPreserve() => NativeMethods.vkvg_clip_preserve(handle); + public void ResetClip() => NativeMethods.vkvg_reset_clip(handle); + + public void Save() => NativeMethods.vkvg_save(handle); + public void Restore() => NativeMethods.vkvg_restore(handle); + public void Flush() => NativeMethods.vkvg_flush(handle); + public void Paint() => NativeMethods.vkvg_paint(handle); + public void PaintWithAlpha (double alpha) => Paint(); + + 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 IntPtr Handle => handle; + + public void AddReference() + { + NativeMethods.vkvg_reference(handle); } - public void TextExtents (Span bytes, out TextExtents extents) { - NativeMethods.vkvg_text_extents (handle, ref bytes.GetPinnableReference (), out extents); + public uint References() => NativeMethods.vkvg_get_reference_count(handle); + + public string FontFace + { + set { NativeMethods.vkvg_select_font_face(handle, value); } } public Matrix Matrix { @@ -109,88 +119,128 @@ namespace Crow.Drawing NativeMethods.vkvg_set_matrix(handle, ref value); } } - 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 = Crow.Text.Encoding.ToUtf8 (s, bytes, tabSize); - bytes[encodedBytes] = 0; - ShowText (bytes.Slice (0, encodedBytes + 1)); + } - public void ShowText (Span bytes) { - NativeMethods.vkvg_show_text (handle, ref bytes.GetPinnableReference()); + public Rectangle StrokeExtents () => default; + public float[] Dashes + { + set + { + if (value == null) + NativeMethods.vkvg_set_dash(handle, null, 0, 0); + else + NativeMethods.vkvg_set_dash(handle, value, (uint)value.Length, 0); + } } - public void ShowText(TextRun textRun) + + public void PushGroup () { + + } + public void PopGroupToSource () { + + } + + public void SelectFontFace(string family, FontSlant slant, FontWeight weight) { - NativeMethods.vkvg_show_text_run(handle, textRun.Handle); + throw new NotImplementedException(); } - public void Save() +*/ + public void MoveTo(float x, float y) { - NativeMethods.vkvg_save(handle); + NativeMethods.vkvg_move_to(handle, x, y); } - public void Restore() + public void RelMoveTo(float x, float y) { - NativeMethods.vkvg_restore(handle); + NativeMethods.vkvg_rel_move_to(handle, x, y); } - public void Flush() + public void LineTo(float x, float y) { - NativeMethods.vkvg_flush(handle); + NativeMethods.vkvg_line_to(handle, x, y); } - public void Clear() + public void LineTo(Point p) { - NativeMethods.vkvg_clear(handle); + NativeMethods.vkvg_line_to(handle, p.X, p.Y); } - public void Paint() + public void LineTo(PointD p) { - NativeMethods.vkvg_paint(handle); + NativeMethods.vkvg_line_to(handle, (float)p.X, (float)p.Y); } - public void PaintWithAlpha (double alpha) => Paint(); - public void Arc(float xc, float yc, float radius, float a1, float a2) + public void RelLineTo(float x, float y) { - NativeMethods.vkvg_arc(handle, xc, yc, radius, a1, a2); + NativeMethods.vkvg_rel_line_to(handle, x, y); } - public void Arc(double xc, double yc, double radius, double a1, double a2) + public void CurveTo(float x1, float y1, float x2, float y2, float x3, float y3) { - NativeMethods.vkvg_arc(handle, (float)xc, (float)yc, (float)radius, (float)a1, (float)a2); + NativeMethods.vkvg_curve_to(handle, x1, y1, x2, y2, x3, y3); } - public void Arc (PointD center, double radius, double angle1, double angle2) + public void RelCurveTo(float x1, float y1, float x2, float y2, float x3, float y3) { - NativeMethods.vkvg_arc (handle, (float)center.X, (float)center.Y, (float)radius, (float)angle1, (float)angle2); + NativeMethods.vkvg_rel_curve_to(handle, x1, y1, x2, y2, x3, y3); } - public void ArcNegative (PointD center, double radius, double angle1, double angle2) + public void MoveTo(double x, double y) { - NativeMethods.vkvg_arc_negative (handle, (float)center.X, (float)center.Y, (float)radius, (float)angle1, (float)angle2); + NativeMethods.vkvg_move_to(handle, (float)x, (float)y); } - public void ArcNegative(float xc, float yc, float radius, float a1, float a2) + public void RelMoveTo(double x, double y) { - NativeMethods.vkvg_arc_negative(handle, xc, yc, radius, a1, a2); + NativeMethods.vkvg_rel_move_to(handle, (float)x, (float)y); } - public void Rectangle(float x, float y, float width, float height) + public void LineTo(double x, double y) { - NativeMethods.vkvg_rectangle(handle, x, y, width, height); + NativeMethods.vkvg_line_to(handle, (float)x, (float)y); } - public void Scale(float sx, float sy) + public void RelLineTo(double x, double y) { - NativeMethods.vkvg_scale(handle, sx, sy); + NativeMethods.vkvg_rel_line_to(handle, (float)x, (float)y); } - public void Translate(float dx, float dy) + public void RelCurveTo(double x1, double y1, double x2, double y2, double x3, double y3) { - NativeMethods.vkvg_translate(handle, dx, dy); + NativeMethods.vkvg_rel_curve_to(handle, (float)x1, (float)y1, (float)x2, (float)y2, (float)x3, (float)y3); } - public void Rotate(float alpha) + + public void SetSource(Pattern pat) { - NativeMethods.vkvg_rotate(handle, alpha); + NativeMethods.vkvg_set_source(handle, pat.Handle); } - public void ArcNegative(double xc, double yc, double radius, double a1, double a2) + public void SetSource(IPattern pat) { + if (pat is Pattern p) + NativeMethods.vkvg_set_source (handle, p.Handle); + } + public void SetSource (Color color) { - NativeMethods.vkvg_arc_negative(handle, (float)xc, (float)yc, (float)radius, (float)a1, (float)a2); + 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 Rectangle(double x, double y, double width, double height) + public void SetSource(ISurface surf, double x = 0, double y = 0) { - NativeMethods.vkvg_rectangle(handle, (float)x, (float)y, (float)width, (float)height); + NativeMethods.vkvg_set_source_surface(handle, surf.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); + } + + Matrix savedMat = Matrix.Identity; + 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); @@ -224,18 +274,6 @@ namespace Crow.Drawing { NativeMethods.vkvg_stroke_preserve(handle); } - public void Clip() - { - NativeMethods.vkvg_clip(handle); - } - public void ClipPreserve() - { - NativeMethods.vkvg_clip_preserve(handle); - } - public void ResetClip() - { - NativeMethods.vkvg_reset_clip(handle); - } public void NewPath() { NativeMethods.vkvg_new_path(handle); @@ -244,10 +282,6 @@ namespace Crow.Drawing { NativeMethods.vkvg_new_sub_path(handle); } - public void ClosePath() - { - NativeMethods.vkvg_close_path(handle); - } public void MoveTo(PointD p) { NativeMethods.vkvg_move_to(handle, (float)p.X, (float)p.Y); @@ -256,93 +290,29 @@ namespace Crow.Drawing { NativeMethods.vkvg_move_to(handle, p.X, p.Y); } - 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 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 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); - } - public void SetSource(Pattern pat) - { - NativeMethods.vkvg_set_source(handle, pat.Handle); - } - public void SetSource (Color color) + public void PopGroupToSource() { - 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(float r, float g, float b, float a = 1f) - { - NativeMethods.vkvg_set_source_rgba(handle, r, g, b, a); - } - 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); + throw new NotImplementedException(); } - public void SetSource(Surface surf, float x = 0f, float y = 0f) - { - NativeMethods.vkvg_set_source_surface(handle, surf.Handle, x, y); - } - public void SetSourceSurface(Surface surf, float x = 0f, float y = 0f) + + public void PushGroup() { - NativeMethods.vkvg_set_source_surface(handle, surf.Handle, x, y); + throw new NotImplementedException(); } - public void RenderSvg(IntPtr nsvgImage, string subId = null) + + 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) { - NativeMethods.vkvg_render_svg(handle, nsvgImage, subId); + throw new NotImplementedException(); } - public Crow.Rectangle StrokeExtents () => default; + internal static byte[] TerminateUtf8(string s) { // compute the byte count including the trailing \0 @@ -359,24 +329,49 @@ namespace Crow.Drawing NativeMethods.vkvg_set_dash(handle, floats, (uint)dashes.Length, (float)offset); } } - public float[] Dashes - { - set - { - if (value == null) - NativeMethods.vkvg_set_dash(handle, null, 0, 0); - else - NativeMethods.vkvg_set_dash(handle, value, (uint)value.Length, 0); + + public Drawing2D.TextExtents TextExtents (ReadOnlySpan s, int tabSize = 4) { + TextExtents (s, tabSize, out Drawing2D.TextExtents e); + return e; + } + public void TextExtents (ReadOnlySpan s, int tabSize, out Drawing2D.TextExtents extents) { + if (s.Length == 0) { + extents = default; + return; } + 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; + TextExtents (bytes.Slice (0, encodedBytes + 1), out extents); + } + public void TextExtents (Span bytes, out Drawing2D.TextExtents extents) { + NativeMethods.vkvg_text_extents (handle, ref bytes.GetPinnableReference (), out TextExtents e); + extents = new Drawing2D.TextExtents (e.XBearing, e.YBearing, e.Width, e.Height, e.XAdvance, e.YAdvance); + } + 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) { + NativeMethods.vkvg_show_text (handle, ref bytes.GetPinnableReference()); } + public void ShowText(TextRun textRun) + { + NativeMethods.vkvg_show_text_run(handle, textRun.Handle); + } - public void PushGroup () { + public Rectangle StrokeExtents() + { + throw new NotImplementedException(); } - public void PopGroupToSource () { - } #region IDisposable implementation public void Dispose() @@ -384,7 +379,6 @@ namespace Crow.Drawing Dispose(true); GC.SuppressFinalize(this); } - protected virtual void Dispose(bool disposing) { if (!disposing || handle == IntPtr.Zero) diff --git a/Backends/VkvgBackend/src/Device.cs b/Backends/VkvgBackend/src/Device.cs index 6ff0230c..c2bd40b2 100644 --- a/Backends/VkvgBackend/src/Device.cs +++ b/Backends/VkvgBackend/src/Device.cs @@ -1,12 +1,14 @@ -// Copyright (c) 2018-2020 Jean-Philippe Bruyère +// 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.IO; +using Drawing2D; -namespace Crow.Drawing +namespace Crow.VkvgBackend { - public class Device: IDisposable + public class Device: IDevice { IntPtr handle = IntPtr.Zero; @@ -22,13 +24,69 @@ namespace Crow.Drawing } #endregion - public void GetDpy (out int hdpy, out int vdpy) => NativeMethods.vkvg_device_get_dpy (handle, out hdpy, out vdpy); - public void SetDpy (int hdpy, int vdpy) => NativeMethods.vkvg_device_set_dpy (handle, hdpy, vdpy); public void AddReference () => NativeMethods.vkvg_device_reference (handle); public uint References () => NativeMethods.vkvg_device_get_reference_count (handle); public IntPtr Handle => handle; + #region IDevice implementation + public void GetDpy (out int hdpy, out int vdpy) => NativeMethods.vkvg_device_get_dpy (handle, out hdpy, out vdpy); + public void SetDpy (int hdpy, int vdpy) => NativeMethods.vkvg_device_set_dpy (handle, hdpy, vdpy); + + public IRegion CreateRegion() => new Region (); + + public ISurface CreateSurface(int width, int height) + { + throw new NotImplementedException(); + } + + public ISurface CreateSurface(byte[] data, int width, int height) + { + throw new NotImplementedException(); + } + public ISurface CreateSurface(IntPtr glfwWinHandle, int width, int height) + { + throw new NotImplementedException(); + } + public IContext CreateContext(ISurface surf) + { + throw new NotImplementedException(); + } + + public IGradient CreateGradient(GradientType gradientType, Rectangle bounds) + { + throw new NotImplementedException(); + } + public byte[] LoadBitmap (Stream stream, out Size dimensions) { + byte[] image; +#if STB_SHARP + StbImageSharp.ImageResult stbi = StbImageSharp.ImageResult.FromStream (stream, StbImageSharp.ColorComponents.RedGreenBlueAlpha); + image = new byte[stbi.Data.Length]; + + Array.Copy (stbi.Data, image, stbi.Data.Length); + dimensions = new Size (stbi.Width, stbi.Height); +#else + using (StbImage stbi = new StbImage (stream)) { + image = new byte [stbi.Size]; + Marshal.Copy (stbi.Handle, image, 0, stbi.Size); + dimensions = new Size (stbi.Width, stbi.Height); + } +#endif + return image; + } + + public ISvgHandle LoadSvg(Stream stream) + { + throw new NotImplementedException(); + } + + public ISvgHandle LoadSvg(string svgFragment) + { + throw new NotImplementedException(); + } + #endregion + + #region IDisposable implementation public void Dispose () { diff --git a/Backends/VkvgBackend/src/FontExtents.cs b/Backends/VkvgBackend/src/FontExtents.cs new file mode 100644 index 00000000..f5614c2f --- /dev/null +++ b/Backends/VkvgBackend/src/FontExtents.cs @@ -0,0 +1,62 @@ +// Copyright (c) 2018-2022 Jean-Philippe Bruyère +// +// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) +using System; +using System.Runtime.InteropServices; + +namespace Crow.VkvgBackend +{ + [StructLayout (LayoutKind.Sequential)] + internal struct FontExtents : IEquatable + { + float ascent; + float descent; + float height; + float maxXAdvance; + float maxYAdvance; + + public float Ascent { + get => ascent; + set { ascent = value; } + } + + public float Descent { + get => descent; + set { descent = value; } + } + + public float Height { + get => height; + set { height = value; } + } + + public float MaxXAdvance { + get => maxXAdvance; + set { maxXAdvance = value; } + } + + public float MaxYAdvance { + get => maxYAdvance; + set { maxYAdvance = value; } + } + + public FontExtents (float ascent, float descent, float height, float maxXAdvance, float maxYAdvance) + { + this.ascent = ascent; + this.descent = descent; + this.height = height; + this.maxXAdvance = maxXAdvance; + this.maxYAdvance = maxYAdvance; + } + + public override int GetHashCode () => HashCode.Combine (ascent, descent, height, maxXAdvance, maxYAdvance); + public override bool Equals (object obj) => obj is FontExtents fe ? Equals (fe) : false; + + public bool Equals(FontExtents other) => + ascent == other.ascent && descent == other.descent && height == other.height && + maxXAdvance == other.maxXAdvance && maxYAdvance == other.maxYAdvance; + + public static bool operator == (FontExtents extents, FontExtents other) => extents.Equals (other); + public static bool operator != (FontExtents extents, FontExtents other) => !extents.Equals (other); + } +} diff --git a/Backends/VkvgBackend/src/Gradient.cs b/Backends/VkvgBackend/src/Gradient.cs index 9f6bed2d..d2432d66 100644 --- a/Backends/VkvgBackend/src/Gradient.cs +++ b/Backends/VkvgBackend/src/Gradient.cs @@ -3,12 +3,14 @@ // This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) using System; -namespace Crow.Drawing +using Drawing2D; + +namespace Crow.VkvgBackend { - public class Gradient : Pattern - { + public class Gradient : Pattern, IGradient + { protected Gradient(IntPtr handle) : base (handle) { } - public void AddColorStop (double offset, Crow.Color c) + public void AddColorStop (double offset, Color c) => NativeMethods.vkvg_pattern_add_color_stop(handle, (float)offset, c.R / 255f, c.G / 255f, c.B / 255f, c.A / 255f); public void AddColorStop(float offset, float r, float g, float b, float a = 1f) => NativeMethods.vkvg_pattern_add_color_stop(handle, offset, r, g, b, a); diff --git a/Backends/VkvgBackend/src/Matrix.cs b/Backends/VkvgBackend/src/Matrix.cs index 2dc541ed..0907362e 100644 --- a/Backends/VkvgBackend/src/Matrix.cs +++ b/Backends/VkvgBackend/src/Matrix.cs @@ -3,7 +3,7 @@ // This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) using System; -namespace Crow.Drawing { +namespace Crow.VkvgBackend { public struct Matrix { float xx; float yx; float xy; float yy; diff --git a/Backends/VkvgBackend/src/NativeMethods.cs b/Backends/VkvgBackend/src/NativeMethods.cs index d96eab8f..fcaf4620 100644 --- a/Backends/VkvgBackend/src/NativeMethods.cs +++ b/Backends/VkvgBackend/src/NativeMethods.cs @@ -4,8 +4,9 @@ using System; using System.Runtime.InteropServices; +using Drawing2D; -namespace Crow.Drawing +namespace Crow.VkvgBackend { internal static class NativeMethods { @@ -142,6 +143,8 @@ namespace Crow.Drawing [DllImport (libvkvg, CallingConvention = CallingConvention.Cdecl)] internal static extern void vkvg_set_dash (IntPtr ctx, float[] dashes, uint dashCount, float offset); + [DllImport (libvkvg, CallingConvention = CallingConvention.Cdecl)] + internal static extern void vkvg_path_extents (IntPtr ctx, out float x1, out float y1, out float x2, out float y2); //void vkvg_set_dash (VkvgContext ctx, const float* dashes, uint32_t num_dashes, float offset); //void vkvg_get_dash (VkvgContext ctx, const float* dashes, uint32_t* num_dashes, float* offset diff --git a/Backends/VkvgBackend/src/Pattern.cs b/Backends/VkvgBackend/src/Pattern.cs index b25e26b2..6c2918f0 100644 --- a/Backends/VkvgBackend/src/Pattern.cs +++ b/Backends/VkvgBackend/src/Pattern.cs @@ -3,11 +3,14 @@ // This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) using System; -namespace Crow.Drawing +using Drawing2D; + +namespace Crow.VkvgBackend { - public class Pattern : IDisposable + public class Pattern : IPattern { protected IntPtr handle = IntPtr.Zero; + public IntPtr Handle => handle; #region CTORS & DTOR protected Pattern(IntPtr handle) @@ -39,17 +42,16 @@ namespace Crow.Drawing } public uint References() => NativeMethods.vkvg_pattern_get_reference_count(handle); - public IntPtr Handle => handle; public Extend Extend { + get => NativeMethods.vkvg_pattern_get_extend(handle); set { NativeMethods.vkvg_pattern_set_extend(handle, value); } - get { return NativeMethods.vkvg_pattern_get_extend(handle); } } public Filter Filter { + get => NativeMethods.vkvg_pattern_get_filter(handle); set { NativeMethods.vkvg_pattern_set_filter(handle, value); } - get { return NativeMethods.vkvg_pattern_get_filter(handle); } } #region IDisposable implementation diff --git a/Backends/VkvgBackend/src/tmp/Region.cs b/Backends/VkvgBackend/src/Region.cs similarity index 82% rename from Backends/VkvgBackend/src/tmp/Region.cs rename to Backends/VkvgBackend/src/Region.cs index 1821ae2b..b02eacf4 100644 --- a/Backends/VkvgBackend/src/tmp/Region.cs +++ b/Backends/VkvgBackend/src/Region.cs @@ -4,21 +4,16 @@ using System.Collections.Generic; using System; +using Drawing2D; +using System.Diagnostics.CodeAnalysis; - -namespace Crow { - public enum RegionOverlap { - In, - Out, - Part, - } - public class Region : IDisposable +namespace Crow.VkvgBackend { + public class Region : IRegion { + Rectangle _bounds; + bool boundsUpToDate = true; public List list = new List(); public int count => list.Count; - public int NumRectangles => list.Count; - public bool IsEmpty => list.Count == 0; - public Rectangle GetRectangle(int i) => list[i]; public void AddRectangle(Rectangle r) { @@ -29,12 +24,6 @@ namespace Crow { boundsUpToDate = false; } } - public void Reset() - { - list = new List(); - _bounds = default; - boundsUpToDate = true; - } public bool DoesNotContains(Rectangle r) { foreach (Rectangle rInList in list) @@ -42,13 +31,6 @@ namespace Crow { return false; return true; } - public bool OverlapOut (Rectangle r) { - foreach (Rectangle rInList in list) - if (rInList.Intersect(r)) - return false; - return true; - } - public bool intersect(Rectangle r) { foreach (Rectangle rInList in list) @@ -56,7 +38,7 @@ namespace Crow { return true; return false; } - public void stroke(Context ctx, Color c) + public void stroke(IContext ctx, Color c) { foreach (Rectangle r in list) ctx.Rectangle(r); @@ -66,7 +48,7 @@ namespace Crow { ctx.LineWidth = 2; ctx.Stroke (); } - public void clearAndClip(Context ctx) + public void clearAndClip(IContext ctx) { if (list.Count == 0) return; @@ -79,20 +61,13 @@ namespace Crow { ctx.Operator = Operator.Over; } - public void clip(Context ctx) + public void clip(IContext ctx) { foreach (Rectangle r in list) ctx.Rectangle(r); ctx.Clip(); } - public void UnionRectangle (Rectangle r) { - /*if (r == default) - System.Diagnostics.Debugger.Break ();*/ - AddRectangle (r); - } - Rectangle _bounds; - bool boundsUpToDate = true; public Rectangle Bounds { get { if (!boundsUpToDate) { @@ -108,7 +83,7 @@ namespace Crow { return _bounds; } } - public void clear(Context ctx) + public void clear(IContext ctx) { foreach (Rectangle r in list) ctx.Rectangle(r); @@ -116,6 +91,37 @@ namespace Crow { ctx.Fill(); ctx.Operator = Operator.Over; } + + #region IRegion implemenatation + public bool IsEmpty => list.Count == 0; + public int NumRectangles => list.Count; + public Rectangle GetRectangle(int i) => list[i]; + public void UnionRectangle (Rectangle r) { + /*if (r == default) + System.Diagnostics.Debugger.Break ();*/ + AddRectangle (r); + } + public bool OverlapOut (Rectangle r) { + foreach (Rectangle rInList in list) + if (rInList.Intersect(r)) + return false; + return true; + } + public RegionOverlap Contains(Rectangle rectangle) + { + throw new NotImplementedException(); + } + public void Reset() + { + list = new List(); + _bounds = default; + boundsUpToDate = true; + } + + public bool Equals([AllowNull] IRegion other) + => other is Region r ? Bounds.Equals (r.Bounds) : false; + #endregion + public override string ToString () { string tmp = ""; @@ -129,5 +135,6 @@ namespace Crow { { } + } } diff --git a/Backends/VkvgBackend/src/Surface.cs b/Backends/VkvgBackend/src/Surface.cs index dba19ca4..1c04b204 100644 --- a/Backends/VkvgBackend/src/Surface.cs +++ b/Backends/VkvgBackend/src/Surface.cs @@ -1,20 +1,22 @@ -// Copyright (c) 2018-2020 Jean-Philippe Bruyère +// 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 Drawing2D; -namespace Crow.Drawing +namespace Crow.VkvgBackend { - public class Surface: IDisposable - { + public class Surface: ISurface + { IntPtr handle = IntPtr.Zero; Device vkvgDev; + #region CTOR public Surface (Device device, int width, int height) { vkvgDev = device; - if (width <= 0 || height <= 0) + if (width <= 0 || height <= 0) handle = NativeMethods.vkvg_surface_create (device.Handle, 1, 1); else handle = NativeMethods.vkvg_surface_create (device.Handle, (uint)width, (uint)height); @@ -38,6 +40,7 @@ namespace Crow.Drawing { handle = NativeMethods.vkvg_surface_create (devHandle, (uint)width, (uint)heigth); } + #endregion ~Surface () { Dispose (false); @@ -51,12 +54,12 @@ namespace Crow.Drawing public void AddReference () => NativeMethods.vkvg_surface_reference (handle); public uint References () => NativeMethods.vkvg_surface_get_reference_count (handle); -// public Surface CreateSimilar (uint width, uint height) { -// return new Surface (handle, width, height); -// } -// public Surface CreateSimilar (int width, int height) { -// return new Surface (handle, (uint)width, (uint)height); -// } + public ISurface CreateSimilar(int width, int height) => new Surface (vkvgDev, width, height); + + public void Resize(int width, int height) + { + throw new NotImplementedException(); + } public void Flush () { //throw new NotImplementedException (); diff --git a/Backends/VkvgBackend/src/SvgHandle.cs b/Backends/VkvgBackend/src/SvgHandle.cs index d923d89f..376d0dbb 100644 --- a/Backends/VkvgBackend/src/SvgHandle.cs +++ b/Backends/VkvgBackend/src/SvgHandle.cs @@ -1,41 +1,43 @@ -//Copyright GPL2 -using System; +// Copyright (c) 2021 Jean-Philippe Bruyère +// +// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) -namespace Crow.Drawing { +using System; +using Drawing2D; +namespace Crow.VkvgBackend +{ + public sealed class SvgHandle : ISvgHandle { - public sealed class SvgHandle : IDisposable { + IntPtr handle; - public IntPtr Raw; - - public SvgHandle (Device dev, Span bytes) + public SvgHandle (Device dev, Span bytes) { /*int size = svgFragment.Length * 4 + 1; Span bytes = size > 512 ? new byte[size] : stackalloc byte[size]; int encodedBytes = Crow.Text.Encoding.ToUtf8 (svgFragment, bytes); bytes[encodedBytes] = 0;*/ - Raw = NativeMethods.nsvg_load (dev.Handle, ref bytes.GetPinnableReference()); + handle = NativeMethods.nsvg_load (dev.Handle, ref bytes.GetPinnableReference()); } public SvgHandle (Device dev, string file_name) - { - Raw = NativeMethods.nsvg_load_file (dev.Handle, file_name); + { + handle = NativeMethods.nsvg_load_file (dev.Handle, file_name); } - public void Render(Context cr) => - cr.RenderSvg (Raw); - - public void Render (Context cr, string id) => - cr.RenderSvg (Raw, id); - + public void Render(IContext cr) => + cr.RenderSvg (handle); + + public void Render (IContext cr, string id) => + cr.RenderSvg (handle, id); + public Size Dimensions { get { - NativeMethods.nsvg_get_size (Raw, out int w, out int h); + NativeMethods.nsvg_get_size (handle, out int w, out int h); return new Size (w, h); } } - - public void Dispose() { - NativeMethods.nsvg_destroy (Raw); + public void Dispose() { + NativeMethods.nsvg_destroy (handle); } } diff --git a/Backends/VkvgBackend/src/TextExtents.cs b/Backends/VkvgBackend/src/TextExtents.cs new file mode 100644 index 00000000..8afb7392 --- /dev/null +++ b/Backends/VkvgBackend/src/TextExtents.cs @@ -0,0 +1,60 @@ +// Copyright (c) 2018-2022 Jean-Philippe Bruyère +// +// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) + +using System; +using System.Runtime.InteropServices; + +namespace Crow.VkvgBackend +{ + [StructLayout (LayoutKind.Sequential)] + internal struct TextExtents : IEquatable + { + float xBearing; + float yBearing; + float width; + float height; + float xAdvance; + float yAdvance; + + public float XBearing { + get => xBearing; + set { xBearing = value; } + } + + public float YBearing { + get => yBearing; + set { yBearing = value; } + } + + public float Width { + get => width; + set { width = value; } + } + + public float Height { + get => height; + set { height = value; } + } + + public float XAdvance { + get => xAdvance; + set { xAdvance = value; } + } + + public float YAdvance { + get => yAdvance; + set { yAdvance = value; } + } + + public override int GetHashCode () => + HashCode.Combine (xBearing, yBearing, width, height, xAdvance, yAdvance); + public override bool Equals (object obj) => obj is TextExtents te ? Equals (te) : false; + + public bool Equals(TextExtents other) => + xBearing == other.xBearing && yBearing == other.yBearing && width == other.width && height == other.height && + xAdvance == other.xAdvance && yAdvance == other.yAdvance; + public static bool operator == (TextExtents extents, TextExtents other) => extents.Equals (other); + public static bool operator != (TextExtents extents, TextExtents other )=> !extents.Equals (other); + } +} diff --git a/Backends/VkvgBackend/src/TextRun.cs b/Backends/VkvgBackend/src/TextRun.cs index f4553692..94b94f56 100644 --- a/Backends/VkvgBackend/src/TextRun.cs +++ b/Backends/VkvgBackend/src/TextRun.cs @@ -1,9 +1,12 @@ -// Copyright (c) 2018-2020 Jean-Philippe Bruyère +// Copyright (c) 2018-2021 Jean-Philippe Bruyère // // This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) using System; -namespace Crow.Drawing { +using Drawing2D; + +namespace Crow.VkvgBackend +{ public class TextRun : IDisposable { IntPtr handle = IntPtr.Zero; @@ -28,11 +31,10 @@ namespace Crow.Drawing { public IntPtr Handle { get { return handle; } } - public TextExtents Extents { + public Drawing2D.TextExtents Extents { get { - TextExtents extents; - NativeMethods.vkvg_text_run_get_extents (handle, out extents); - return extents; + NativeMethods.vkvg_text_run_get_extents (handle, out TextExtents e); + return new Drawing2D.TextExtents (e.XBearing, e.YBearing, e.Width, e.Height, e.XAdvance, e.YAdvance); } } diff --git a/Backends/VkvgBackend/src/tmp/FontOptions.cs b/Backends/VkvgBackend/src/tmp/FontOptions.cs deleted file mode 100644 index 1d9764fb..00000000 --- a/Backends/VkvgBackend/src/tmp/FontOptions.cs +++ /dev/null @@ -1,74 +0,0 @@ -//from Mono.Cairo -//fake FontOptions - -using System; - -namespace Crow.Drawing -{ - public enum SubpixelOrder - { - Default, - Rgb, - Bgr, - Vrgb, - Vbgr, - } - public enum HintMetrics - { - Default, - Off, - On, - } - public enum HintStyle - { - Default, - None, - Slight, - Medium, - Full, - } - public class FontOptions : IDisposable - { - public FontOptions () { } - - - public FontOptions Copy () => default; - - - public IntPtr Handle { - get ; - } - - - public void Merge (FontOptions other) - { - } - - public void Dispose() {} - - public Antialias Antialias { - get ; - set ; - } - - public HintMetrics HintMetrics { - get ; - set ; - } - - public HintStyle HintStyle { - get ; - set ; - } - - public Status Status { - get ; - } - - public SubpixelOrder SubpixelOrder { - get ; - set ; - } - } -} - diff --git a/Crow.sln b/Crow.sln index e9e8fd86..470b92b3 100644 --- a/Crow.sln +++ b/Crow.sln @@ -27,6 +27,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Backends", "Backends", "{45 EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CairoBackend", "Backends\CairoBackend\CairoBackend.csproj", "{E06441A9-0CFD-45BB-9478-99D28CEB327F}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VkvgBackend", "Backends\VkvgBackend\VkvgBackend.csproj", "{34976828-80CF-4AC5-8C81-F66F635DC5FC}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -53,6 +55,10 @@ Global {E06441A9-0CFD-45BB-9478-99D28CEB327F}.Debug|Any CPU.Build.0 = Debug|Any CPU {E06441A9-0CFD-45BB-9478-99D28CEB327F}.Release|Any CPU.ActiveCfg = Release|Any CPU {E06441A9-0CFD-45BB-9478-99D28CEB327F}.Release|Any CPU.Build.0 = Release|Any CPU + {34976828-80CF-4AC5-8C81-F66F635DC5FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {34976828-80CF-4AC5-8C81-F66F635DC5FC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {34976828-80CF-4AC5-8C81-F66F635DC5FC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {34976828-80CF-4AC5-8C81-F66F635DC5FC}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -62,6 +68,7 @@ Global {56329D48-D382-4850-93DE-59C453894E8A} = {B2C7855A-2878-47FD-AD32-9A83DB4AB8C6} {18EBB41F-815E-4BF5-B80F-C9E2FAB2993A} = {B2C7855A-2878-47FD-AD32-9A83DB4AB8C6} {E06441A9-0CFD-45BB-9478-99D28CEB327F} = {451F5727-2A2E-4361-A41B-089429ADE8F9} + {34976828-80CF-4AC5-8C81-F66F635DC5FC} = {451F5727-2A2E-4361-A41B-089429ADE8F9} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {00D4E149-7131-49F4-BAAD-559AA961A78E} diff --git a/Crow/Crow.csproj b/Crow/Crow.csproj index ea3b3a02..ffe4e866 100644 --- a/Crow/Crow.csproj +++ b/Crow/Crow.csproj @@ -57,22 +57,9 @@ --> - - $(DefineConstants);VKVG - - - - - - - - - - - - + Crow.%(Filename)%(Extension) @@ -87,5 +74,11 @@ + + + + $(DefineConstants);STB_SHARP + + diff --git a/Crow/src/Fill/BmpPicture.cs b/Crow/src/Fill/BmpPicture.cs index 3f59c3d6..72cc36b8 100644 --- a/Crow/src/Fill/BmpPicture.cs +++ b/Crow/src/Fill/BmpPicture.cs @@ -40,51 +40,11 @@ namespace Crow return; } using (Stream stream = iFace.GetStreamFromPath (Path)) { - load (stream); - //loadBitmap (new System.Drawing.Bitmap (stream)); + image = iFace.Device.LoadBitmap (stream, out Size dimensions); + Dimensions = dimensions; iFace.sharedPictures[Path] = new sharedPicture (image, Dimensions); } } - void load (Stream stream) { -#if STB_SHARP - StbImageSharp.ImageResult stbi = StbImageSharp.ImageResult.FromStream (stream, StbImageSharp.ColorComponents.RedGreenBlueAlpha); - image = new byte[stbi.Data.Length]; - #if VKVG - Array.Copy (stbi.Data, image, stbi.Data.Length); - #else - //rgba to argb for cairo. - for (int i = 0; i < stbi.Data.Length; i += 4) { - image[i] = stbi.Data[i + 2]; - image[i + 1] = stbi.Data[i + 1]; - image[i + 2] = stbi.Data[i]; - image[i + 3] = stbi.Data[i + 3]; - } - #endif - Dimensions = new Size (stbi.Width, stbi.Height); -#else - using (StbImage stbi = new StbImage (stream)) { - image = new byte [stbi.Size]; - #if VKVG - Marshal.Copy (stbi.Handle, image, 0, stbi.Size); - #else - for (int i = 0; i < stbi.Size; i+=4) { - //rgba to argb for cairo. ???? looks like bgra to me. - image [i] = Marshal.ReadByte (stbi.Handle, i + 2); - image [i + 1] = Marshal.ReadByte (stbi.Handle, i + 1); - image [i + 2] = Marshal.ReadByte (stbi.Handle, i); - image [i + 3] = Marshal.ReadByte (stbi.Handle, i + 3); - } - #endif - Dimensions = new Size (stbi.Width, stbi.Height); - } -#endif - } - internal static sharedPicture CreateSharedPicture (Stream stream) { - BmpPicture pic = new BmpPicture (); - pic.load (stream); - return new sharedPicture (pic.image, pic.Dimensions); - } - //load image via System.Drawing.Bitmap, cairo load png only /*void loadBitmap (System.Drawing.Bitmap bitmap) @@ -157,12 +117,12 @@ namespace Crow if (image == null) load (iFace); - float widthRatio = 1f; - float heightRatio = 1f; + double widthRatio = 1; + double heightRatio = 1; if (Scaled){ - widthRatio = (float)rect.Width / Dimensions.Width; - heightRatio = (float)rect.Height / Dimensions.Height; + widthRatio = (double)rect.Width / Dimensions.Width; + heightRatio = (double)rect.Height / Dimensions.Height; } if (KeepProportions) { @@ -172,26 +132,18 @@ namespace Crow widthRatio = heightRatio; } - //gr.Save (); - - Matrix m = gr.Matrix; + gr.SaveTransformations (); gr.Translate (rect.Left,rect.Top); gr.Scale (widthRatio, heightRatio); gr.Translate ((rect.Width/widthRatio - Dimensions.Width)/2, (rect.Height/heightRatio - Dimensions.Height)/2); -#if VKVG - using (Surface imgSurf = new Surface (iFace.vkvgDevice, image, Dimensions.Width, Dimensions.Height)) -#else - using (Surface imgSurf = new ImageSurface (image, Format.Argb32, Dimensions.Width, Dimensions.Height, 4 * Dimensions.Width)) -#endif - { + using (ISurface imgSurf = iFace.Device.CreateSurface (image, Dimensions.Width, Dimensions.Height)) { gr.SetSource (imgSurf, 0,0); gr.Paint (); } - gr.Matrix = m; - //gr.Restore (); + gr.RestoreTransformations (); } } } diff --git a/Crow/src/Fill/Gradient.cs b/Crow/src/Fill/Gradient.cs index ba461518..d161eba8 100644 --- a/Crow/src/Fill/Gradient.cs +++ b/Crow/src/Fill/Gradient.cs @@ -12,13 +12,6 @@ namespace Crow { public class Gradient : Fill { - public enum Type - { - Vertical, - Horizontal, - Oblic, - Radial - } public class ColorStop { public double Offset; @@ -44,7 +37,7 @@ namespace Crow return new ColorStop (-1, Color.FromIml (parts [0])); } } - public Type GradientType = Type.Vertical; + public GradientType Type = GradientType.Vertical; // public double x0; // public double y0; // public double x1; @@ -52,30 +45,16 @@ namespace Crow // public double Radius1; // public double Radius2; public List Stops = new List(); - public Gradient(Type _type) + public Gradient(GradientType _type) { - GradientType = _type; + Type = _type; } #region implemented abstract members of Fill public override void SetAsSource (Interface iFace, IContext ctx, Rectangle bounds = default(Rectangle)) { - Crow.Drawing.Gradient grad = null; - switch (GradientType) { - case Type.Vertical: - grad = new LinearGradient (bounds.Left, bounds.Top, bounds.Left, bounds.Bottom); - break; - case Type.Horizontal: - grad = new LinearGradient (bounds.Left, bounds.Top, bounds.Right, bounds.Top); - break; - case Type.Oblic: - grad = new LinearGradient (bounds.Left, bounds.Top, bounds.Right, bounds.Bottom); - break; - case Type.Radial: - throw new NotImplementedException (); - } - + IGradient grad = iFace.Device.CreateGradient (Type, bounds); foreach (ColorStop cs in Stops) { if (cs == null) continue; @@ -98,13 +77,13 @@ namespace Crow switch (stops[0].Trim()) { case "vgradient": - tmp = new Gradient (Type.Vertical); + tmp = new Gradient (GradientType.Vertical); break; case "hgradient": - tmp = new Gradient (Type.Horizontal); + tmp = new Gradient (GradientType.Horizontal); break; case "ogradient": - tmp = new Gradient (Type.Oblic); + tmp = new Gradient (GradientType.Oblic); break; default: throw new Exception ("Unknown gradient type: " + stops [0]); diff --git a/Crow/src/Fill/SvgPicture.cs b/Crow/src/Fill/SvgPicture.cs index 0bd85f75..d562b342 100644 --- a/Crow/src/Fill/SvgPicture.cs +++ b/Crow/src/Fill/SvgPicture.cs @@ -15,7 +15,7 @@ namespace Crow /// public class SvgPicture : Picture { - SvgHandle hSVG; + ISvgHandle hSVG; #region CTOR /// @@ -33,37 +33,19 @@ namespace Crow { if (iFace.sharedPictures.ContainsKey (Path)) { sharedPicture sp = iFace.sharedPictures [Path]; - hSVG = (SvgHandle)sp.Data; + hSVG = (ISvgHandle)sp.Data; Dimensions = sp.Dims; return; } using (Stream stream = iFace.GetStreamFromPath (Path)) - load (iFace, stream); + hSVG = iFace.Device.LoadSvg (stream); + Dimensions = hSVG.Dimensions; iFace.sharedPictures [Path] = new sharedPicture (hSVG, Dimensions); } - void load (Interface iface, Stream stream) { - using (BinaryReader sr = new BinaryReader (stream)) { -#if VKVG - hSVG = new SvgHandle (iface.vkvgDevice, sr.ReadBytes ((int)stream.Length)); -#else - hSVG = new SvgHandle (sr.ReadBytes ((int)stream.Length)); -#endif - Dimensions = hSVG.Dimensions; - } - } - internal static sharedPicture CreateSharedPicture (Interface iface, Stream stream) { - SvgPicture pic = new SvgPicture (); - pic.load (iface, stream); - return new sharedPicture (pic.hSVG, pic.Dimensions); - } - public void LoadSvgFragment (Interface iface, string fragment) { -#if VKVG - hSVG = new SvgHandle (iface.vkvgDevice, System.Text.Encoding.Unicode.GetBytes(fragment)); -#else - hSVG = new SvgHandle (System.Text.Encoding.Unicode.GetBytes(fragment)); -#endif - Dimensions = new Size (hSVG.Dimensions.Width, hSVG.Dimensions.Height); + public void LoadSvgFragment (Interface iface, string fragment) { + hSVG = iface.Device.LoadSvg (fragment); + Dimensions = hSVG.Dimensions; } #region implemented abstract members of Fill @@ -88,12 +70,8 @@ namespace Crow widthRatio = heightRatio; } -#if VKVG - using (Surface tmp = new Surface (iFace.vkvgDevice, bounds.Width, bounds.Height)) { -#else - using (Surface tmp = new ImageSurface (Format.Argb32, bounds.Width, bounds.Height)) { -#endif - using (IContext gr = new Context (tmp)) { + using (ISurface tmp = iFace.Device.CreateSurface (bounds.Width, bounds.Height)) { + using (IContext gr = iFace.Device.CreateContext (tmp)) { gr.Translate (bounds.Left, bounds.Top); gr.Scale (widthRatio, heightRatio); gr.Translate ((bounds.Width/widthRatio - Dimensions.Width)/2, (bounds.Height/heightRatio - Dimensions.Height)/2); @@ -130,7 +108,7 @@ namespace Crow else widthRatio = heightRatio; } - + gr.Save (); gr.Translate (rect.Left,rect.Top); @@ -141,10 +119,10 @@ namespace Crow hSVG.Render (gr); else { string[] parts = subPart.Split (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); - foreach (string p in parts) + foreach (string p in parts) hSVG.Render (gr, "#" + subPart); } - + gr.Restore (); } } diff --git a/Crow/src/Font.cs b/Crow/src/Font.cs index acfe9760..e39f9125 100644 --- a/Crow/src/Font.cs +++ b/Crow/src/Font.cs @@ -3,7 +3,7 @@ // This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) using System; - +using Drawing2D; namespace Crow { diff --git a/Crow/src/Interface.cs b/Crow/src/Interface.cs index be1a203f..e0c00ede 100644 --- a/Crow/src/Interface.cs +++ b/Crow/src/Interface.cs @@ -197,11 +197,6 @@ namespace Crow PerformanceMeasure.InitMeasures (); -#if VKVG - //force single threaded interface for vkvg until multithreading in vkvg is ok - startUIThread = false; -#endif - if (startUIThread) { Thread t = new Thread (InterfaceThread) { IsBackground = true @@ -253,13 +248,11 @@ namespace Crow /// Create the VulkanContext with swapchain support. Override it to use another vulkan backend. /// #endif + static string backendDeviceTypeString = "Crow.CairoBackend.Device"; protected void initBackend (bool offscreen = false) { -#if VKVG - if (offscreen) - vkCtx = new OffscreenVulkanContext (this); - else - vkCtx = new VulkanContext (this, hWin, (uint)clientRectangle.Width, (uint)clientRectangle.Height); -#endif + + dev = new Crow.CairoBackend.Device (); + clipping = dev.CreateRegion (); } /// /// Create the main rendering surface. The default is a GLFW window with a cairo surface bound to it. @@ -279,12 +272,9 @@ namespace Crow registerGlfwCallbacks (); -#if VKVG initBackend (); - vkCtx.CreateSurface (clientRectangle.Width, clientRectangle.Height, ref surf); -#else -#endif + CreateMainSurface (ref clientRectangle); } /// /// ?? @@ -292,11 +282,7 @@ namespace Crow /// public void CreateMainSurface (ref Rectangle r) { surf?.Dispose(); -#if (VKVG) - vkCtx.CreateSurface (clientRectangle.Width, clientRectangle.Height, ref surf); -#else - surf = new ImageSurface (Format.ARGB32, r.Width, r.Height); -#endif + surf = Device.CreateSurface (hWin, r.Width, r.Height); } public IntPtr SurfacePointer { get { @@ -556,9 +542,7 @@ namespace Crow if (disposing) { disposeContextMenus (); -#if VKVG - vkCtx.Dispose (); -#endif + dev.Dispose (); } currentCursor?.Dispose (); @@ -735,7 +719,7 @@ namespace Crow /// Client rectangle in the host context protected Rectangle clientRectangle; /// Clipping rectangles on the root context - Region clipping = new Region(); + IRegion clipping; /// Main Cairo context //Context ctx; #endregion @@ -831,10 +815,13 @@ namespace Crow foreach (string pic in Directory.GetFiles (path, "*.*", SearchOption.AllDirectories)) { string resId = $"#{pic.Substring (path.Length + 1).Replace (Path.DirectorySeparatorChar, '.')}"; using (Stream s = new FileStream (pic, FileMode.Open, FileAccess.Read)) { - if (resId.EndsWith (".svg", StringComparison.OrdinalIgnoreCase)) - sharedPictures[resId] = SvgPicture.CreateSharedPicture (this, s); - else - sharedPictures[resId] = BmpPicture.CreateSharedPicture (s); + if (resId.EndsWith (".svg", StringComparison.OrdinalIgnoreCase)) { + ISvgHandle hSVG = Device.LoadSvg (s); + sharedPictures[resId] = new sharedPicture (hSVG, hSVG.Dimensions); + } else { + byte[] image = Device.LoadBitmap (s, out Size dimensions); + sharedPictures[resId] = new sharedPicture (image, dimensions); + } } } } @@ -1165,18 +1152,11 @@ namespace Crow if (!clipping.IsEmpty || shouldDrawTextCursor) { if (ctx == null) { - using (ctx = new Context (surf)) + using (ctx = Device.CreateContext (surf)) processDrawing (ctx); }else processDrawing (ctx); } - -#if VKVG - if (IsDirty) { - if (!vkCtx.render ()) - ProcessResize (new Rectangle (0,0,(int)vkCtx.width, (int)vkCtx.height)); - } -#endif } finally { PerformanceMeasure.End (PerformanceMeasure.Kind.Update); @@ -1187,13 +1167,6 @@ namespace Crow PerformanceMeasure.Notify (); } -#if VKVG - void resizeVulkanContext () { - - - - } -#endif /// Layouting loop, this is the first step of the udpate and process registered /// Layouting queue items. Failing LQI's are requeued in this cycle until MaxTry is reached which /// trigger an enqueue for the next Update Cycle @@ -1533,32 +1506,7 @@ namespace Crow public virtual void ProcessResize(Rectangle bounds){ lock (UpdateMutex) { clientRectangle = bounds; - -#if VKVG - vkCtx.CreateSurface (clientRectangle.Width, clientRectangle.Height, ref surf); -#else - switch (Environment.OSVersion.Platform) { - case PlatformID.MacOSX: - break; - case PlatformID.Unix: - surf.SetSize (clientRectangle.Width, clientRectangle.Height); - break; - case PlatformID.Win32NT: - case PlatformID.Win32S: - case PlatformID.Win32Windows: - if (ownWindow) { - surf.Dispose (); - IntPtr hWin32 = Glfw3.GetWin32Window (hWin); - IntPtr hdc = Glfw3.GetWin32DC (hWin32); - surf = new Win32Surface (hdc); - }else - surf.SetSize (clientRectangle.Width, clientRectangle.Height); - break; - case PlatformID.Xbox: - case PlatformID.WinCE: - throw new PlatformNotSupportedException ("Unable to create cairo surface."); - } -#endif + surf.Resize (clientRectangle.Width, clientRectangle.Height); foreach (Widget g in GraphicTree) g.RegisterForLayouting (LayoutingType.All); diff --git a/Crow/src/LayoutingQueueItem.cs b/Crow/src/LayoutingQueueItem.cs index a9a634c3..64549c08 100644 --- a/Crow/src/LayoutingQueueItem.cs +++ b/Crow/src/LayoutingQueueItem.cs @@ -48,7 +48,7 @@ namespace Crow #region CTOR public LayoutingQueueItem (LayoutingType _layoutType, ILayoutable _graphicObject) - { + { LayoutType = _layoutType; Layoutable = _graphicObject; Layoutable.RegisteredLayoutings |= LayoutType; @@ -75,7 +75,7 @@ namespace Crow if (!go.layoutMutex.TryEnterWriteLock (1)) { go.IFace.LayoutingQueue.Enqueue (this); -#if DEBUG_LOG +#if DEBUG_LOG result = Result.Requeued; #endif return; @@ -92,12 +92,12 @@ namespace Crow Slot = Layoutable.getSlot (); #endif LayoutingTries++; - + if (Layoutable.UpdateLayout (LayoutType)) { Layoutable.RequiredLayoutings &= (~LayoutType); - if (Layoutable.RequiredLayoutings == LayoutingType.None && go.IsDirty) + if (Layoutable.RequiredLayoutings == LayoutingType.None && go.IsDirty) go.IFace.EnqueueForRepaint (this); -#if DEBUG_LOG +#if DEBUG_LOG result = Result.Success; #endif } else { @@ -122,7 +122,7 @@ namespace Crow } #endif } -#if DEBUG_LOG +#if DEBUG_LOG NewSlot = Layoutable.getSlot(); #endif } finally { diff --git a/Crow/src/Widgets/ColorSlider.cs b/Crow/src/Widgets/ColorSlider.cs index 605212da..61bb951d 100644 --- a/Crow/src/Widgets/ColorSlider.cs +++ b/Crow/src/Widgets/ColorSlider.cs @@ -146,11 +146,8 @@ namespace Crow r.Height -= 4; r.Y += 2; - Gradient.Type gt = Gradient.Type.Horizontal; - if (Orientation == Orientation.Vertical) - gt = Gradient.Type.Vertical; - - Gradient grad = new Gradient (gt); + Gradient grad = new Gradient ( + Orientation == Orientation.Vertical ? GradientType.Vertical : GradientType.Horizontal); Color c = currentColor; switch (component) { @@ -193,8 +190,6 @@ namespace Crow CairoHelpers.CairoRectangle (gr, r, CornerRadius); gr.Fill (); - - r = ClientRectangle; switch (cursorType) { diff --git a/Crow/src/Widgets/HueSelector.cs b/Crow/src/Widgets/HueSelector.cs index 4b46ed54..d4d23f36 100644 --- a/Crow/src/Widgets/HueSelector.cs +++ b/Crow/src/Widgets/HueSelector.cs @@ -57,11 +57,8 @@ namespace Crow r.Height -= 4; r.Y += 2; - Gradient.Type gt = Gradient.Type.Horizontal; - if (Orientation == Orientation.Vertical) - gt = Gradient.Type.Vertical; - - Gradient grad = new Gradient (gt); + Gradient grad = new Gradient ( + Orientation == Orientation.Vertical ? GradientType.Vertical : GradientType.Horizontal); grad.Stops.Add (new Gradient.ColorStop (0, new Color (1, 0, 0, 1))); grad.Stops.Add (new Gradient.ColorStop (0.167, new Color (1, 1, 0, 1))); diff --git a/Crow/src/Widgets/Image.cs b/Crow/src/Widgets/Image.cs index 7bcc1d32..30908847 100644 --- a/Crow/src/Widgets/Image.cs +++ b/Crow/src/Widgets/Image.cs @@ -7,8 +7,7 @@ using System; using System.Xml.Serialization; using System.ComponentModel; using System.Diagnostics; - - +using Drawing2D; namespace Crow { @@ -188,6 +187,6 @@ namespace Crow gr.Operator = Operator.Over; } } - #endregion + #endregion } } diff --git a/Crow/src/Widgets/Label.cs b/Crow/src/Widgets/Label.cs index 3c3795c4..5ef09523 100644 --- a/Crow/src/Widgets/Label.cs +++ b/Crow/src/Widgets/Label.cs @@ -439,7 +439,7 @@ namespace Crow if (bytes.Length < size) bytes = size > 512 ? new byte[size] : stackalloc byte[size]; - encodedBytes = Crow.Text.Encoding.ToUtf8 (_text.GetLine (lines[i]), bytes); + encodedBytes = _text.GetLine (lines[i]).ToUtf8 (bytes); bytes[encodedBytes++] = 0; if (lines[i].LengthInPixel < 0) { @@ -592,7 +592,7 @@ namespace Crow Span bytes = stackalloc byte[5];//utf8 single char buffer + '\0' for (int i = 0; i < ls.Length; i++) { - int encodedBytes = Crow.Text.Encoding.ToUtf8 (curLine.Slice (i, 1), bytes); + int encodedBytes = curLine.Slice (i, 1).ToUtf8 (bytes); bytes[encodedBytes] = 0; gr.TextExtents (bytes, out te); diff --git a/Crow/src/Widgets/SaturationValueSelector.cs b/Crow/src/Widgets/SaturationValueSelector.cs index 7f0af78a..69ff67b9 100644 --- a/Crow/src/Widgets/SaturationValueSelector.cs +++ b/Crow/src/Widgets/SaturationValueSelector.cs @@ -55,13 +55,13 @@ namespace Crow gr.Fill (); } - Crow.Gradient grad = new Gradient (Gradient.Type.Horizontal); + Crow.Gradient grad = new Gradient (GradientType.Horizontal); grad.Stops.Add (new Gradient.ColorStop (0, new Color (1, 1, 1, 1))); grad.Stops.Add (new Gradient.ColorStop (1, new Color (1, 1, 1, 0))); grad.SetAsSource (IFace, gr, r); CairoHelpers.CairoRectangle (gr, r, CornerRadius); gr.Fill(); - grad = new Gradient (Gradient.Type.Vertical); + grad = new Gradient (GradientType.Vertical); grad.Stops.Add (new Gradient.ColorStop (0, new Color (0, 0, 0, 0))); grad.Stops.Add (new Gradient.ColorStop (1, new Color (0, 0, 0, 1))); grad.SetAsSource (IFace, gr, r); diff --git a/Crow/src/Widgets/Shape.cs b/Crow/src/Widgets/Shape.cs index fea5d1e3..efa8b45b 100644 --- a/Crow/src/Widgets/Shape.cs +++ b/Crow/src/Widgets/Shape.cs @@ -203,7 +203,7 @@ namespace Crow return; Rectangle cr = ClientRectangle; - double widthRatio = 1f, heightRatio = 1f; + double widthRatio = 1, heightRatio = 1; double w = (double)(contentSize.Width == 0 ? size.Width : contentSize.Width); double h = (double)(contentSize.Height == 0 ? size.Height : contentSize.Height); @@ -220,8 +220,7 @@ namespace Crow widthRatio = heightRatio; } - Matrix m = gr.Matrix; - //gr.Save (); + gr.SaveTransformations (); gr.Translate (cr.Left, cr.Top); gr.Scale (widthRatio, heightRatio); @@ -233,8 +232,7 @@ namespace Crow using (PathParser parser = new PathParser (path)) parser.Draw (gr); - //gr.Restore (); - gr.Matrix = m; + gr.RestoreTransformations (); } diff --git a/Crow/src/Widgets/Widget.cs b/Crow/src/Widgets/Widget.cs index 875fa1a7..57b65aab 100644 --- a/Crow/src/Widgets/Widget.cs +++ b/Crow/src/Widgets/Widget.cs @@ -198,7 +198,7 @@ namespace Crow /// are repeated at each cached levels of the tree with correspondig coordinate system. This is done /// in a dedicated step of the update between layouting and drawing. /// - public Region Clipping; + public IRegion Clipping; #region IValueChange implementation /// @@ -233,7 +233,6 @@ namespace Crow /// action. /// protected Widget () { - Clipping = new Region (); #if DEBUG_STATS TotalWidgetCreated++; #endif @@ -1169,6 +1168,7 @@ namespace Crow { DbgLogger.StartEvent (DbgEvtType.GOInitialization, this); + Clipping = IFace.Device.CreateRegion (); Type thisType = this.GetType (); if (!string.IsNullOrEmpty (style)) { @@ -1927,10 +1927,6 @@ namespace Crow } #endregion - protected void setFontForContext (IContext gr) { - - } - #region Rendering /// This is the common overridable drawing routine to create new widget protected virtual void onDraw(IContext gr) @@ -1958,14 +1954,8 @@ namespace Crow else if (LastPaintedSlot.Width != Slot.Width || LastPaintedSlot.Height != Slot.Height) bmp.SetSize (Slot.Width, Slot.Height);*/ bmp?.Dispose (); -#if (VKVG) - DbgLogger.StartEvent (DbgEvtType.GOCreateSurface, this); - bmp = new Surface (IFace.vkvgDevice, Slot.Width, Slot.Height); - DbgLogger.EndEvent (DbgEvtType.GOCreateSurface); - //bmp.Clear(); -#else - bmp = IFace.surf.CreateSimilar (Content.ColorAlpha, Slot.Width, Slot.Height); -#endif + bmp = IFace.Device.CreateSurface (Slot.Width, Slot.Height); + //bmp = new ImageSurface(Format.Argb32, Slot.Width, Slot.Height); DbgLogger.StartEvent (DbgEvtType.GOCreateContext, this); diff --git a/Crow/src/Text/Encoding.cs b/Drawing2D/src/Encoding.cs similarity index 90% rename from Crow/src/Text/Encoding.cs rename to Drawing2D/src/Encoding.cs index ac730650..8999623d 100644 --- a/Crow/src/Text/Encoding.cs +++ b/Drawing2D/src/Encoding.cs @@ -2,14 +2,12 @@ // // This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) using System; -using System.Collections.Generic; -using System.Text; -namespace Crow.Text +namespace Drawing2D { - public class Encoding + public static class Extensions { - public static int ToUtf8 (ReadOnlySpan source, Span buff, int tabWidth = 4) { + public static int ToUtf8 (this ReadOnlySpan source, Span buff, int tabWidth = 4) { int c = 0; int encodedBytes = 0; int encodedChar = 0; diff --git a/Drawing2D/src/Enums.cs b/Drawing2D/src/Enums.cs index b13f29af..12a6f035 100644 --- a/Drawing2D/src/Enums.cs +++ b/Drawing2D/src/Enums.cs @@ -72,6 +72,13 @@ namespace Drawing2D Mesh, RasterSource, } + public enum GradientType + { + Vertical, + Horizontal, + Oblic, + Radial + } public enum Operator { diff --git a/Drawing2D/src/FontExtents.cs b/Drawing2D/src/FontExtents.cs index 19532880..a28f3699 100644 --- a/Drawing2D/src/FontExtents.cs +++ b/Drawing2D/src/FontExtents.cs @@ -41,38 +41,38 @@ namespace Drawing2D [StructLayout (LayoutKind.Sequential)] public struct FontExtents : IEquatable { - float ascent; - float descent; - float height; - float maxXAdvance; - float maxYAdvance; + double ascent; + double descent; + double height; + double maxXAdvance; + double maxYAdvance; - public float Ascent { + public double Ascent { get => ascent; set { ascent = value; } } - public float Descent { + public double Descent { get => descent; set { descent = value; } } - public float Height { + public double Height { get => height; set { height = value; } } - public float MaxXAdvance { + public double MaxXAdvance { get => maxXAdvance; set { maxXAdvance = value; } } - public float MaxYAdvance { + public double MaxYAdvance { get => maxYAdvance; set { maxYAdvance = value; } } - public FontExtents (float ascent, float descent, float height, float maxXAdvance, float maxYAdvance) + public FontExtents (double ascent, double descent, double height, double maxXAdvance, double maxYAdvance) { this.ascent = ascent; this.descent = descent; diff --git a/Drawing2D/src/IContext.cs b/Drawing2D/src/IContext.cs index 9e080613..3c4f54f8 100644 --- a/Drawing2D/src/IContext.cs +++ b/Drawing2D/src/IContext.cs @@ -20,74 +20,66 @@ namespace Drawing2D FillRule FillRule { get; set; } FontExtents FontExtents { get; } Antialias Antialias { get; set; } + void SetDash (double [] dashes, double offset = 0); + TextExtents TextExtents (ReadOnlySpan s, int tabSize = 4); void TextExtents (ReadOnlySpan s, int tabSize, out TextExtents extents); void TextExtents (Span bytes, out TextExtents extents); - Matrix Matrix { get; set; } void ShowText (string text); void ShowText (ReadOnlySpan s, int tabSize = 4); void ShowText (Span bytes); + void Save(); void Restore(); - void Flush(); - void Clear(); - void Paint(); - void PaintWithAlpha (double alpha); - - void Arc(float xc, float yc, float radius, float a1, float a2); - void Arc(double xc, double yc, double radius, double a1, double a2); - void Arc (PointD center, double radius, double angle1, double angle2); - void ArcNegative (PointD center, double radius, double angle1, double angle2); - void ArcNegative(float xc, float yc, float radius, float a1, float a2); - void Rectangle(float x, float y, float width, float height); - void Scale(float sx, float sy); - void Translate(float dx, float dy); - void Rotate(float alpha); - void ArcNegative(double xc, double yc, double radius, double a1, double a2); - void Rectangle(double x, double y, double width, double height); + void SaveTransformations (); + void RestoreTransformations (); void Scale(double sx, double sy); void Translate(double dx, double dy); void Translate(PointD p); void Rotate(double alpha); - void Fill(); - void FillPreserve(); - void Stroke(); - void StrokePreserve(); - void Clip(); - void ClipPreserve(); - void ResetClip(); + + void Flush(); + void Clear(); + void NewPath(); void NewSubPath(); void ClosePath(); - void MoveTo(PointD p); + void Arc(double xc, double yc, double radius, double a1, double a2); + void Arc (PointD center, double radius, double angle1, double angle2); + void ArcNegative(double xc, double yc, double radius, double a1, double a2); + void ArcNegative (PointD center, double radius, double angle1, double angle2); void MoveTo(Point p); - void MoveTo(float x, float y); - void RelMoveTo(float x, float y); - void LineTo(float x, float y); - void LineTo(Point p); - void LineTo(PointD p); - void RelLineTo(float x, float y); - void CurveTo(float x1, float y1, float x2, float y2, float x3, float y3); - void RelCurveTo(float x1, float y1, float x2, float y2, float x3, float y3); + void MoveTo(PointD p); void MoveTo(double x, double y); void RelMoveTo(double x, double y); void LineTo(double x, double y); + void LineTo(Point p); + void LineTo(PointD p); void RelLineTo(double x, double y); void CurveTo(double x1, double y1, double x2, double y2, double x3, double y3); void RelCurveTo(double x1, double y1, double x2, double y2, double x3, double y3); + void Rectangle(double x, double y, double width, double height); + void Rectangle(Rectangle r); + + void Paint(); + void PaintWithAlpha (double alpha); + void Fill(); + void FillPreserve(); + Rectangle StrokeExtents (); + void Stroke(); + void StrokePreserve(); + void Clip(); + void ClipPreserve(); + void ResetClip(); + void SetSource(IPattern pat); void SetSource (Color color); - void SetSource(float r, float g, float b, float a = 1f); void SetSource(double r, double g, double b, double a = 1.0); - void SetSource(ISurface surf, float x = 0f, float y = 0f); - void SetSourceSurface(ISurface surf, float x = 0f, float y = 0f); + void SetSource(ISurface surf, double x = 0f, double y = 0f); void RenderSvg(IntPtr svgNativeHandle, string subId = null); - Rectangle StrokeExtents (); - void SetDash (double [] dashes, double offset = 0); - float[] Dashes { set; } - //void PushGroup (); - //void PopGroupToSource (); + void PushGroup (); + void PopGroupToSource (); } } diff --git a/Drawing2D/src/IDevice.cs b/Drawing2D/src/IDevice.cs index 02224894..891f8b2e 100644 --- a/Drawing2D/src/IDevice.cs +++ b/Drawing2D/src/IDevice.cs @@ -3,6 +3,7 @@ // This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) using System; +using System.IO; namespace Drawing2D { @@ -12,9 +13,16 @@ namespace Drawing2D void GetDpy (out int hdpy, out int vdpy); void SetDpy (int hdpy, int vdpy); + IRegion CreateRegion (); ISurface CreateSurface (int width, int height); - + ISurface CreateSurface (byte[] data, int width, int height); + ISurface CreateSurface (IntPtr glfwWinHandle, int width, int height); IContext CreateContext (ISurface surf); + //IPattern CreatePattern (PatternType patternType); + IGradient CreateGradient (GradientType gradientType, Rectangle bounds); + byte[] LoadBitmap (Stream stream, out Size dimensions); + ISvgHandle LoadSvg (Stream stream); + ISvgHandle LoadSvg (string svgFragment); } } diff --git a/Drawing2D/src/IGradient.cs b/Drawing2D/src/IGradient.cs new file mode 100644 index 00000000..6371c969 --- /dev/null +++ b/Drawing2D/src/IGradient.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2021 Jean-Philippe Bruyère +// +// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) + +namespace Drawing2D +{ + public interface IGradient : IPattern + { + void AddColorStop (double offset, Color c); + void AddColorStop(float offset, float r, float g, float b, float a = 1f); + } +} \ No newline at end of file diff --git a/Drawing2D/src/Pattern.cs b/Drawing2D/src/IPattern.cs similarity index 92% rename from Drawing2D/src/Pattern.cs rename to Drawing2D/src/IPattern.cs index f8c31438..5eb4ffcc 100644 --- a/Drawing2D/src/Pattern.cs +++ b/Drawing2D/src/IPattern.cs @@ -3,10 +3,12 @@ // This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) using System; + namespace Drawing2D { public interface IPattern : IDisposable { + IntPtr Handle { get; } Extend Extend { get; set; } Filter Filter { get; set; } } diff --git a/Drawing2D/src/IRegion.cs b/Drawing2D/src/IRegion.cs new file mode 100644 index 00000000..967f8733 --- /dev/null +++ b/Drawing2D/src/IRegion.cs @@ -0,0 +1,25 @@ +// Copyright (c) 2021 Bruyère Jean-Philippe jp_bruyere@hotmail.com +// +// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) + +using System; + +namespace Drawing2D +{ + public enum RegionOverlap { + In, + Out, + Part, + } + + public interface IRegion : IDisposable, IEquatable + { + bool IsEmpty { get; } + int NumRectangles { get; } + Rectangle GetRectangle (int nth); + void UnionRectangle (Rectangle r); + bool OverlapOut (Rectangle r); + RegionOverlap Contains (Rectangle rectangle); + void Reset (); + } +} diff --git a/Drawing2D/src/ISurface.cs b/Drawing2D/src/ISurface.cs index 37bb510c..e4940872 100644 --- a/Drawing2D/src/ISurface.cs +++ b/Drawing2D/src/ISurface.cs @@ -18,6 +18,7 @@ namespace Drawing2D void WriteTo (IntPtr bitmap); void Clear (); ISurface CreateSimilar (int width, int height); + void Resize (int width, int height); } } diff --git a/Drawing2D/src/ISvgHandle.cs b/Drawing2D/src/ISvgHandle.cs new file mode 100644 index 00000000..28d29ec9 --- /dev/null +++ b/Drawing2D/src/ISvgHandle.cs @@ -0,0 +1,14 @@ +//Copyright GPL2 +using System; +using System.Runtime.InteropServices; + +namespace Drawing2D { + + + public interface ISvgHandle : IDisposable { + void Render(IContext cr); + void Render (IContext cr, string id); + + Size Dimensions { get; } + } +} diff --git a/Drawing2D/src/TextExtents.cs b/Drawing2D/src/TextExtents.cs index 7d1939b7..ba99aece 100644 --- a/Drawing2D/src/TextExtents.cs +++ b/Drawing2D/src/TextExtents.cs @@ -10,39 +10,46 @@ namespace Drawing2D [StructLayout (LayoutKind.Sequential)] public struct TextExtents : IEquatable { - float xBearing; - float yBearing; - float width; - float height; - float xAdvance; - float yAdvance; - - public float XBearing { + double xBearing; + double yBearing; + double width; + double height; + double xAdvance; + double yAdvance; + public TextExtents (double xBearing, double yBearing, double width, double height, double xAdvance, double yAdvance) { + this.xBearing = xBearing; + this.yBearing = yBearing; + this.width = width; + this.height = height; + this.xAdvance = xAdvance; + this.yAdvance = yAdvance; + } + public double XBearing { get => xBearing; set { xBearing = value; } } - public float YBearing { + public double YBearing { get => yBearing; set { yBearing = value; } } - public float Width { + public double Width { get => width; set { width = value; } } - public float Height { + public double Height { get => height; set { height = value; } } - public float XAdvance { + public double XAdvance { get => xAdvance; set { xAdvance = value; } } - public float YAdvance { + public double YAdvance { get => yAdvance; set { yAdvance = value; } } diff --git a/Samples/ShowCase/ShowCase.cs b/Samples/ShowCase/ShowCase.cs index 4f3d79f8..9096ebe6 100644 --- a/Samples/ShowCase/ShowCase.cs +++ b/Samples/ShowCase/ShowCase.cs @@ -36,7 +36,7 @@ namespace ShowCase using (Showcase app = new Showcase ()) { app.WindowTitle = "C.R.O.W Showcase"; - app.SetWindowIcon ("#Crow.Icons.crow.png"); + //app.SetWindowIcon ("#Crow.Icons.crow.png"); //app.Theme = @"C:\Users\Jean-Philippe\source\Crow\Themes\TestTheme"; CurrentProgramInstance = app; //Interface.UPDATE_INTERVAL = 50; diff --git a/Samples/common/src/Editor.cs b/Samples/common/src/Editor.cs index 0de7af55..13e0f382 100644 --- a/Samples/common/src/Editor.cs +++ b/Samples/common/src/Editor.cs @@ -411,7 +411,7 @@ namespace Crow if (bytes.Length < size) bytes = size > 512 ? new byte[size] : stackalloc byte[size]; - int encodedBytes = Crow.Text.Encoding.ToUtf8 (buff, bytes); + int encodedBytes = buff.ToUtf8 (bytes); if (encodedBytes > 0) { bytes[encodedBytes++] = 0; @@ -456,7 +456,7 @@ namespace Crow if (bytes.Length < size) bytes = size > 512 ? new byte[size] : stackalloc byte[size]; - int encodedBytes = Crow.Text.Encoding.ToUtf8 (buff, bytes); + int encodedBytes = buff.ToUtf8 (bytes); gr.SetSource (SelectionBackground); gr.Rectangle (selRect); diff --git a/Samples/common/src/SampleBase.cs b/Samples/common/src/SampleBase.cs index 6d06dba4..2d773af4 100644 --- a/Samples/common/src/SampleBase.cs +++ b/Samples/common/src/SampleBase.cs @@ -12,6 +12,7 @@ using System.Threading; using System.Diagnostics; +using Drawing2D; namespace Samples { diff --git a/Samples/common/src/TestWidget.cs b/Samples/common/src/TestWidget.cs index 40970d80..e23a2361 100644 --- a/Samples/common/src/TestWidget.cs +++ b/Samples/common/src/TestWidget.cs @@ -1,6 +1,6 @@ //Tutorial using Crow; - +using Drawing2D; using Glfw; namespace TestWidget { -- 2.47.3