uwp-xamlwin2d

why the overlap rectangle drawn in CanvasRenderTarget were visible in win2d?


what i have tried is? my XAML code:

 <Canvas x:Name="can">

 </Canvas>

my c# code:

   private void Page_Loaded(object sender, RoutedEventArgs e)
    {
        CanvasVirtualControl canvasVirtual = new CanvasVirtualControl();
        canvasVirtual.Width = 1500;
        canvasVirtual.Height = 800;
        canvasVirtual.RegionsInvalidated += CanvasVirtual_RegionsInvalidated;
       //canvasVirtual.Invalidate();
        can.Children.Add(canvasVirtual);
    }

    private void CanvasVirtual_RegionsInvalidated(CanvasVirtualControl sender, CanvasRegionsInvalidatedEventArgs args)
    {
        CanvasRenderTarget Offscreen = new CanvasRenderTarget(CanvasDevice.GetSharedDevice(), (float)args.InvalidatedRegions[0].Width, (float)args.InvalidatedRegions[0].Height, 96);
        using (CanvasDrawingSession session = Offscreen.CreateDrawingSession())
        {
            CanvasRenderTarget mouseOverOffscreen = new CanvasRenderTarget(CanvasDevice.GetSharedDevice(), 300, 300, 96);
            CanvasDrawingSession session1;
            using (session1 = mouseOverOffscreen.CreateDrawingSession())
            {
                session1.DrawRectangle(new Rect(0, 0, 300, 300), new Color { A = 255, R = 0, G = 255, B = 0 }, 2);
            }
            session.DrawImage(mouseOverOffscreen, new Rect(100, 100, 300, 300));
            CanvasRenderTarget seleOverOffscreen = new CanvasRenderTarget(CanvasDevice.GetSharedDevice(), 300, 300, 96);
            CanvasDrawingSession session2;
            using (session2 = seleOverOffscreen.CreateDrawingSession())
            {
                session2.DrawRectangle(new Rect(0, 0, 300, 300), new Color { A = 255, R = 255, G = 0, B = 0 }, 2);
            }
            session.DrawImage(seleOverOffscreen, new Rect(200, 200, 300, 300));
        }
        

        using (CanvasDrawingSession session = sender.CreateDrawingSession(new Rect((float)args.InvalidatedRegions[0].X, (float)args.InvalidatedRegions[0].Y, (float)args.InvalidatedRegions[0].Width, (float)args.InvalidatedRegions[0].Height)))
        {
            session.DrawImage(Offscreen);
        }
    }

i'm trying to draw two intersecting rectangle in canvasVirtualControl,using canvasRenderTarget.The rectangles images are created by canvasRenderTarget.This two images are drawed in an offscreen and this offscreen is later used to draw in CanvasVirtualControl.

My problem was ,while drawing two intersecting rectangles(i.e,overlap),the result will be like this. enter image description here

I need to erase the rectangle area where it is overlapped,how can i do this?Example,like the below image,

enter image description here


Solution

  • This involves the calculation of paths in Win2D. CanvasGeometry is provided in Win2D for the combined calculation of graphics, which can meet your needs:

    We need to create two CanvasGeometry as two rectangles:

    var Rect1 = CanvasGeometry.CreateRectangle(sender, 100, 100, 300, 300);
    var Rect2 = CanvasGeometry.CreateRectangle(sender, 0, 0, 300, 300);
    

    Through the CanvasGeometry.CombineWith method, we can calculate the combined area:

    var combineGeo = Rect2.CombineWith(Rect1, Matrix3x2.CreateTranslation(Vector2.Zero), CanvasGeometryCombine.Union);
    

    The next step is to draw:

    private void CanvasVirtual_RegionsInvalidated(CanvasVirtualControl sender, CanvasRegionsInvalidatedEventArgs args)
    {
        CanvasRenderTarget Offscreen = new CanvasRenderTarget(CanvasDevice.GetSharedDevice(), (float)args.InvalidatedRegions[0].Width, (float)args.InvalidatedRegions[0].Height, 96);
        using (CanvasDrawingSession session = Offscreen.CreateDrawingSession())
        {
            CanvasRenderTarget mouseOverOffscreen = new CanvasRenderTarget(CanvasDevice.GetSharedDevice(), 300, 300, 96);
            CanvasDrawingSession session1;
            var Rect1 = CanvasGeometry.CreateRectangle(sender, 100, 100, 300, 300);
            var Rect2 = CanvasGeometry.CreateRectangle(sender, 0, 0, 300, 300);
            var combineGeo = Rect2.CombineWith(Rect1, Matrix3x2.CreateTranslation(Vector2.Zero), CanvasGeometryCombine.Union);
            using (session1 = mouseOverOffscreen.CreateDrawingSession())
            {
                session1.DrawGeometry(combineGeo, new Color { A = 255, R = 0, G = 255, B = 0 }, 2);
            }
            session.DrawImage(mouseOverOffscreen, new Rect(100, 100, 300, 300));
            CanvasRenderTarget seleOverOffscreen = new CanvasRenderTarget(CanvasDevice.GetSharedDevice(), 300, 300, 96);
            CanvasDrawingSession session2;
            using (session2 = seleOverOffscreen.CreateDrawingSession())
            {
                session2.DrawGeometry(Rect2, new Color { A = 255, R = 255, G = 0, B = 0 }, 2);
            }
            session.DrawImage(seleOverOffscreen, new Rect(200, 200, 300, 300));
        }
    
    
        using (CanvasDrawingSession session = sender.CreateDrawingSession(new Rect((float)args.InvalidatedRegions[0].X, (float)args.InvalidatedRegions[0].Y, (float)args.InvalidatedRegions[0].Width, (float)args.InvalidatedRegions[0].Height)))
        {
            session.DrawImage(Offscreen);
        }
    }
    

    The rendered result will be displayed as overlapping rectangles that eliminate the internal intersecting boundaries (the effect is slightly different from your expected effect in layer).