From 98874f30c14d559662c0922f573cf9596cab4a58 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jean-Philippe=20Bruy=C3=A8re?= Date: Wed, 1 May 2019 00:36:26 +0200 Subject: [PATCH] text run and fill rule in vkvg, bitmaps, non-zero fill rule for clipping solve lots of problems --- Crow/Crow.csproj | 2 +- Crow/packages.config | 2 +- Crow/src/BmpPicture.cs | 83 ++++++++++++-------------------- Crow/src/Cairo/DrawingHelpers.cs | 1 + Crow/src/Gradient.cs | 46 +++++++++--------- Crow/src/Interface.cs | 8 ++- Crow/src/SvgPicture.cs | 4 +- Crow/src/vkvg/Context.cs | 9 +++- Crow/src/vkvg/Enums.cs | 4 ++ Crow/src/vkvg/NativeMethods.cs | 6 ++- Crow/src/vkvg/Pattern.cs | 3 ++ Crow/src/vkvg/TextRun.cs | 75 +++++++++++++++++++++++++++++ 12 files changed, 160 insertions(+), 83 deletions(-) create mode 100644 Crow/src/vkvg/TextRun.cs diff --git a/Crow/Crow.csproj b/Crow/Crow.csproj index 1fa7c438..ac334f25 100644 --- a/Crow/Crow.csproj +++ b/Crow/Crow.csproj @@ -53,7 +53,7 @@ - ..\..\packages\Vulkan.0.1.2.5-alpha\lib\netstandard2.0\VK.dll + ..\..\packages\Vulkan.0.1.2.6\lib\netstandard2.0\VK.dll diff --git a/Crow/packages.config b/Crow/packages.config index 16d6f60e..b38bd1a1 100644 --- a/Crow/packages.config +++ b/Crow/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/Crow/src/BmpPicture.cs b/Crow/src/BmpPicture.cs index 76cd3439..b4080428 100644 --- a/Crow/src/BmpPicture.cs +++ b/Crow/src/BmpPicture.cs @@ -36,7 +36,7 @@ namespace Crow /// public class BmpPicture : Picture { - byte[] image = null; + Surface imgSurface; #region CTOR /// @@ -49,46 +49,31 @@ namespace Crow /// /// image path, may be embedded public BmpPicture (string path) : base(path) - {} + { + Load (); + } #endregion /// /// load the image for rendering from the path given as argument /// /// image path, may be embedded void Load () - { - if (sharedResources.ContainsKey (Path)) { - sharedPicture sp = sharedResources [Path]; - image = (byte[])sp.Data; - Dimensions = sp.Dims; - return; - } - using (Stream stream = Interface.StaticGetStreamFromPath (Path)) { - //loadBitmap (new System.Drawing.Bitmap (stream)); - } - sharedResources [Path] = new sharedPicture (image, Dimensions); - } - - //load image via System.Drawing.Bitmap, cairo load png only - /*void loadBitmap (System.Drawing.Bitmap bitmap) { - if (bitmap == null) - return; - - System.Drawing.Imaging.BitmapData data = bitmap.LockBits - (new System.Drawing.Rectangle (0, 0, bitmap.Width, bitmap.Height), - System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); - - Dimensions = new Size (bitmap.Width, bitmap.Height); - - int stride = data.Stride; - int bitmapSize = Math.Abs (data.Stride) * bitmap.Height; - - image = new byte[bitmapSize]; - System.Runtime.InteropServices.Marshal.Copy (data.Scan0, image, 0, bitmapSize); + //if (sharedResources.ContainsKey (Path)) { + // sharedPicture sp = sharedResources [Path]; + // image = (byte[])sp.Data; + // Dimensions = sp.Dims; + // return; + //} - bitmap.UnlockBits (data); - }*/ + imgSurface = new Surface (Interface.CurrentInterface.dev, Path); + Dimensions.Width = imgSurface.Width; + Dimensions.Height = imgSurface.Height; + //using (Stream stream = Interface.StaticGetStreamFromPath (Path)) { + // loadBitmap (new System.Drawing.Bitmap (stream)); + //} + //sharedResources [Path] = new sharedPicture (image, Dimensions); + } #region implemented abstract members of Fill @@ -109,20 +94,16 @@ namespace Crow widthRatio = heightRatio; } - //using (ImageSurface tmp = new ImageSurface (Format.Argb32, bounds.Width, bounds.Height)) { - // using (Context gr = new Context (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); - - // using (ImageSurface imgSurf = new ImageSurface (image, Format.Argb32, - // Dimensions.Width, Dimensions.Height, 4 * Dimensions.Width)) { - // gr.SetSourceSurface (imgSurf, 0,0); - // gr.Paint (); - // } - // } - // ctx.SetSource (tmp); - //} + using (Surface tmp = new Surface (Interface.CurrentInterface.dev, bounds.Width, bounds.Height)) { + using (Context gr = new Context (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); + gr.SetSourceSurface (imgSurface, 0,0); + gr.Paint (); + } + ctx.SetSource (tmp); + } } #endregion @@ -155,12 +136,8 @@ namespace Crow gr.Translate (rect.Left,rect.Top); gr.Scale (widthRatio, heightRatio); gr.Translate ((rect.Width/widthRatio - Dimensions.Width)/2, (rect.Height/heightRatio - Dimensions.Height)/2); - - //using (Surface imgSurf = new Surface (. image, Format.Argb32, - // Dimensions.Width, Dimensions.Height, 4 * Dimensions.Width)) { - // gr.SetSourceSurface (imgSurf, 0,0); - // gr.Paint (); - //} + gr.SetSourceSurface (imgSurface, 0,0); + gr.Paint (); gr.Restore (); } } diff --git a/Crow/src/Cairo/DrawingHelpers.cs b/Crow/src/Cairo/DrawingHelpers.cs index 8fe7f62a..83bb10cc 100644 --- a/Crow/src/Cairo/DrawingHelpers.cs +++ b/Crow/src/Cairo/DrawingHelpers.cs @@ -91,6 +91,7 @@ namespace Crow { gr.LineTo(x + radius, y + height); gr.Arc(x + radius, y + height - radius, radius, Math.PI / 2, Math.PI); gr.ClosePath(); + gr.Restore(); } public static void StrokeRaisedRectangle(Context gr, Rectangle r, double width = 1) diff --git a/Crow/src/Gradient.cs b/Crow/src/Gradient.cs index 25f662ed..64bd30ef 100644 --- a/Crow/src/Gradient.cs +++ b/Crow/src/Gradient.cs @@ -39,6 +39,7 @@ namespace Crow Oblic, Radial } + public class ColorStop { public double Offset; @@ -64,6 +65,7 @@ namespace Crow return new ColorStop (-1, (Color)parts [0]); } } + public Gradient.Type GradientType = Type.Vertical; // public double x0; // public double y0; @@ -81,29 +83,29 @@ namespace Crow public override void SetAsSource (Context ctx, Rectangle bounds = default(Rectangle)) { - //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 (); - //} - - //foreach (ColorStop cs in Stops) { - // if (cs == null) - // continue; - // grad.AddColorStop (cs.Offset, cs.Color); - //} + Pattern grad = null; + switch (GradientType) { + case Type.Vertical: + grad = Pattern.CreateLinearGradient (bounds.Left, bounds.Top, bounds.Left, bounds.Bottom); + break; + case Type.Horizontal: + grad = Pattern.CreateLinearGradient (bounds.Left, bounds.Top, bounds.Right, bounds.Top); + break; + case Type.Oblic: + grad = Pattern.CreateLinearGradient (bounds.Left, bounds.Top, bounds.Right, bounds.Bottom); + break; + case Type.Radial: + throw new NotImplementedException (); + } + + foreach (ColorStop cs in Stops) { + if (cs == null) + continue; + grad.AddColorStop ((float)cs.Offset, cs.Color); + } - //ctx.SetSource (grad); - //grad.Dispose (); + ctx.SetSource (grad); + grad.Dispose (); } #endregion diff --git a/Crow/src/Interface.cs b/Crow/src/Interface.cs index 36b3d9c6..df364038 100644 --- a/Crow/src/Interface.cs +++ b/Crow/src/Interface.cs @@ -251,7 +251,7 @@ namespace Crow /// Each control need a ref to the root interface containing it, if not set in GraphicObject.currentInterface, /// the ref of this one will be stored in GraphicObject.currentInterface /// - protected static Interface CurrentInterface; + public static Interface CurrentInterface; Stopwatch lastClickTime = new Stopwatch(); internal Widget armedClick;//store widget with double click on first click internal MouseButtonEventArgs armedClickEventArgs; @@ -733,6 +733,7 @@ namespace Crow clippingMeasure.StopCycle(); #endif } + Color clippingStrokeColor = Color.Magenta.AdjustAlpha(0.8); /// Clipping Rectangles drive the drawing process. For compositing, each object under a clip rectangle should be /// repainted. If it contains also clip rectangles, its cache will be update, or if not cached a full redraw will take place void processDrawing(){ @@ -781,8 +782,11 @@ namespace Crow //} #if DEBUG_CLIP_RECTANGLE + clippingStrokeColor.R += 0.1f; + if (clippingStrokeColor.R > 1f) + clippingStrokeColor.R = 0; ctx.LineWidth = 1; - clipping.stroke (ctx, Color.Magenta.AdjustAlpha (0.5)); + clipping.stroke (ctx, clippingStrokeColor); ctx.Stroke (); #endif //clipping.stroke (ctx, new Color (1, 0, 0)); diff --git a/Crow/src/SvgPicture.cs b/Crow/src/SvgPicture.cs index cf7c39b0..96d42ac8 100644 --- a/Crow/src/SvgPicture.cs +++ b/Crow/src/SvgPicture.cs @@ -140,10 +140,10 @@ namespace Crow gr.Scale (widthRatio, heightRatio); gr.Translate (((float)rect.Width/widthRatio - Dimensions.Width)/2f, ((float)rect.Height/heightRatio - Dimensions.Height)/2f); - if (string.IsNullOrEmpty (subPart)) + /*if (string.IsNullOrEmpty (subPart)) hSVG.RenderCairo (gr); else - hSVG.RenderCairoSub (gr, "#" + subPart); + hSVG.RenderCairoSub (gr, "#" + subPart);*/ gr.Restore (); } diff --git a/Crow/src/vkvg/Context.cs b/Crow/src/vkvg/Context.cs index 0cf3195e..3186444f 100644 --- a/Crow/src/vkvg/Context.cs +++ b/Crow/src/vkvg/Context.cs @@ -63,6 +63,10 @@ namespace vkvg set { NativeMethods.vkvg_set_operator (handle, value); } get { return NativeMethods.vkvg_get_operator (handle); } } + public FillRule FillRule { + set { NativeMethods.vkvg_set_fill_rule (handle, value); } + get { return NativeMethods.vkvg_get_fill_rule (handle); } + } public FontExtents FontExtents { get { FontExtents f_extents; @@ -79,6 +83,9 @@ namespace vkvg public void ShowText (string txt) { NativeMethods.vkvg_show_text (handle, txt); } + public void ShowText (TextRun textRun) { + NativeMethods.vkvg_show_text_run (handle, textRun.Handle); + } public void Save () { NativeMethods.vkvg_save (handle); } @@ -232,7 +239,7 @@ namespace vkvg NativeMethods.vkvg_set_source_surface (handle, surf.Handle, x, y); } - private static byte[] TerminateUtf8(string s) + internal static byte[] TerminateUtf8(string s) { // compute the byte count including the trailing \0 var byteCount = Encoding.UTF8.GetMaxByteCount(s.Length + 1); diff --git a/Crow/src/vkvg/Enums.cs b/Crow/src/vkvg/Enums.cs index 44b0d087..f6fedd54 100644 --- a/Crow/src/vkvg/Enums.cs +++ b/Crow/src/vkvg/Enums.cs @@ -136,4 +136,8 @@ namespace vkvg { Round, Bevel } + public enum FillRule { + EvenOdd, + NonZero, + } } \ No newline at end of file diff --git a/Crow/src/vkvg/NativeMethods.cs b/Crow/src/vkvg/NativeMethods.cs index e598170d..7b6dfdf0 100644 --- a/Crow/src/vkvg/NativeMethods.cs +++ b/Crow/src/vkvg/NativeMethods.cs @@ -122,6 +122,10 @@ namespace vkvg internal static extern void vkvg_set_line_join (IntPtr ctx, LineJoin join); [DllImport (libvkvg, CallingConvention=CallingConvention.Cdecl)] internal static extern void vkvg_set_operator (IntPtr ctx, Operator op); + [DllImport (libvkvg, CallingConvention = CallingConvention.Cdecl)] + internal static extern FillRule vkvg_get_fill_rule (IntPtr ctx); + [DllImport (libvkvg, CallingConvention = CallingConvention.Cdecl)] + internal static extern void vkvg_set_fill_rule (IntPtr ctx, FillRule fr); [DllImport (libvkvg, CallingConvention=CallingConvention.Cdecl)] internal static extern Operator vkvg_get_operator (IntPtr ctx); [DllImport (libvkvg, CallingConvention=CallingConvention.Cdecl)] @@ -168,7 +172,7 @@ namespace vkvg [DllImport (libvkvg, CallingConvention=CallingConvention.Cdecl)] internal static extern void vkvg_show_text_run (IntPtr ctx, IntPtr textRun); [DllImport (libvkvg, CallingConvention=CallingConvention.Cdecl)] - internal static extern void vkvg_text_run_get_extents (IntPtr textRun); + internal static extern void vkvg_text_run_get_extents (IntPtr textRun, out TextExtents extents); #endregion #region Pattern diff --git a/Crow/src/vkvg/Pattern.cs b/Crow/src/vkvg/Pattern.cs index f6746ffb..096a7e5a 100644 --- a/Crow/src/vkvg/Pattern.cs +++ b/Crow/src/vkvg/Pattern.cs @@ -78,6 +78,9 @@ namespace vkvg { public void AddColorStop (float offset, float r, float g, float b, float a = 1f) { NativeMethods.vkvg_patter_add_color_stop (handle, offset, r, g, b, a); } + public void AddColorStop (float offset, Crow.Color c) { + NativeMethods.vkvg_patter_add_color_stop (Handle, offset, (float)c.R, (float)c.G, (float)c.B, (float)c.A); + } #region IDisposable implementation public void Dispose () { diff --git a/Crow/src/vkvg/TextRun.cs b/Crow/src/vkvg/TextRun.cs new file mode 100644 index 00000000..e748d7ff --- /dev/null +++ b/Crow/src/vkvg/TextRun.cs @@ -0,0 +1,75 @@ +// +// TextRun.cs +// +// Author: +// Jean-Philippe Bruyère +// +// Copyright (c) 2019 jp +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, 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 NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +namespace vkvg { + public class TextRun : IDisposable { + + IntPtr handle = IntPtr.Zero; + + #region CTORS & DTOR + protected TextRun(IntPtr handle) { + this.handle = handle; + } + public TextRun(string text) { + handle = NativeMethods.vkvg_text_run_create (handle, Context.TerminateUtf8(text)); + } + + ~TextRun() { + Dispose (false); + } + #endregion + + //public void AddReference () { + // NativeMethods.vkvg_pattern_reference (handle); + //} + //public uint References () => NativeMethods.vkvg_pattern_get_reference_count (handle); + + public IntPtr Handle { get { return handle; } } + + public TextExtents Extents { + get { + TextExtents extents; + NativeMethods.vkvg_text_run_get_extents (handle, out extents); + return extents; + } + } + + #region IDisposable implementation + public void Dispose () { + Dispose (true); + GC.SuppressFinalize (this); + } + + protected virtual void Dispose (bool disposing) { + if (!disposing || handle == IntPtr.Zero) + return; + + NativeMethods.vkvg_text_run_destroy (handle); + handle = IntPtr.Zero; + } + #endregion + } +} \ No newline at end of file -- 2.47.3