Skip to content
This repository has been archived by the owner on May 1, 2024. It is now read-only.

Xamarin.Forms Drawing Spec #2452

Closed
2 tasks done
jassmith opened this issue Apr 12, 2018 · 69 comments · Fixed by #9218 or #9264
Closed
2 tasks done

Xamarin.Forms Drawing Spec #2452

jassmith opened this issue Apr 12, 2018 · 69 comments · Fixed by #9218 or #9264
Labels
a/brushes a/shapes in-progress This issue has an associated pull request that may resolve it! m/high impact ⬛ t/enhancement ➕
Projects

Comments

@jassmith
Copy link

Xamarin.Forms Drawing Spec

Theming

To make MaterialShell work it not only needs a shell which appears to be material design, but all of its contents also should be material design. Today that means Custom Renderers. This is heavy and undesired from a user work perspective. Instead a better approach is required.

Simple drawing API sample

<Button x:Class="Local.MyButton">
  <Button.Template>
    <DrawingTemplate>
      <Drawing>
        <Grid>
          <RoundedRectangle Background="{x:Bind BackgroundColor}" />
          <Ellipse x:Name="TouchFeedback" Opacity="0" />
          <Text Content="{x:Bind Text}" />
        </Grid>
      </Drawing>
    </DrawingTemplate>
  </Button>
</Button>

View templates, at least for now, must be a DrawingTemplate. The first child of a DrawingTemplate is always a Drawing. Inside of a Drawing you may use Layouts and drawing primitives.

Drawing primitives may be x:named and looked up by name and manipulated in code behind as any other View. In effect a drawing primitive is simply a view who has no renderer but rather must be inside a Drawing in order to work. Drawing is limited to children it can support as all are collapsed into simple drawing commands.

Drawing primative objects may use a Brush type rather than a Color type for providing colors/backgrounds/etc.

When using a MaterialShell, all relevant controls will receive a default Template which themes them according to the Material design guidelines and unifies their look and feel across platform. This theme can be overridden at any layer of the hierarchy simply by blocking its propagation in resource dictionaries.

Once realized a Control may not have its Template changed as DrawingTemplated controls may at times require different renderers.

Types

DrawingTemplate

This is mostly a marker type. In the future we will eliminate the requirement that Templates be DrawingTemplates.

public class DrawingTemplate : ControlTemplate {}

Drawing

A View which has no renderer and is instead consumed by its parent view as a native drawing. Drawing is a very basic layout which can be measured but always sizes all of its children to the same size as itself when laid out.

public class Drawing : Layout<View> {}

New API for Drawing in View

public class View : VisualElement // new API only
{
  public ControlTemplate Template { get; set; }

  protected BindableObject GetTemplateChild(string childName);

  protected virtual void OnApplyTemplate ();
}

Brush

public class Brush : BindableObject
{
  public static readonly BindableProperty OpacityProperty;
  public double Opacity { get; set; }
}

SolidColorBrush

public class SolidColorBrush : Brush
{
  public static readonly BindableProperty ColorProperty;
  public Color Color { get; set; }
}

GradientBrush

public class LinearGradientBrush : Brush
{
  public static readonly BindableProperty GradientStopsProperty;
  [Content]
  public GradientStopCollection GradientStops { get; set; }
}

GradientStopCollection

public sealed class GradientStopCollection : IEnumerable<GradientStop>, IList<GradientStop>

GradientStop

public sealed class GradientStop : BindableObject
{
  public static readonly BindableProperty ColorProperty;
  public Color Color { get; set; }

  public static readonly BindableProperty OffsetProperty;
  public double Offset { get; set; }

  public static readonly BindableProperty StartPointProperty;
  public Point StartPoint { get; set; }

  public static readonly BindableProperty EndPointProperty;
  public Point EndPoint { get; set; }
}

Drawing Primitives

There will be a need for a large number of drawing primitives with associated properties. This document does not attempt to define all of them, just note some of the obvious ones that will need to exist. The drawing primitive API is not intended to be a wholesale replacement for SkiaSharp. It is however intended to be agnostic to the usage of Skia or native drawing backends for the paltform.

A good path forward for Skia would be to add a SkiaDrawing element that would instruct the Drawing to be rendered via Skia. Skia could then render all the stock primitives as well as provide a Skia drawing element which allows for coded drawing.

Shape

namespace Xamarin.Forms.Shapes 
{
  public class Shape : View
  {
    public static readonly BindableProperty FillProperty;
    public Brush Fill { get; set; }

    public static readonly BindableProperty StrokeProperty;
    public Brush Stroke { get; set; }

    public static readonly BindableProperty StrokeThicknessProperty;
    public double StrokeThickness { get; set; }
  }
}

Line

namespace Xamarin.Forms.Shapes 
{
  public sealed class Line : Shape
  {
    public Point Start { get; set; }
    public Point End { get; set; }
  }
}

Ellipse

namespace Xamarin.Forms.Shapes 
{
  public sealed class Ellipse : Shape
  {
  }
}

Text

public sealed class Text : Shape 
{
  // All the same properties as Label more or less
}

Rectangle

namespace Xamarin.Forms.Shapes 
{
  public sealed class Rectangle : Shape
  {
    public CornerRadius CornerRadius { get; set; }
  }
}

BezierLine

This differs quite a bit from UWP, however this is capable of drawing an Bezier curved path/shape, as well as regular polygons and polylines.

namespace Xamarin.Forms.Shapes 
{
  public sealed class BezierLine : Shape
  {
    public IList<BezierPoint> Points { get; }
    public bool ShouldClose { get; set; }
  }
}

BezierPoint

namespace Xamarin.Forms.Shapes 
{
  public sealed class BezierPoint : Point
  {
    public Size LeftControlOffset { get; set; }
    public Size RightControlOffset { get; set; }
  }
}

TODO

  • Add API for drawing
  • Fill out brush API

Issues

Shapes

There is not currents a great way to draw just an arc. The mechanism in UWP for doing this is a bit... uhg just not fun.

There is also something to be said for the fact that Shapes are currently Views. This is to make sure they can be consumed by standard Layout's which is nice because the user does not need to learn new layouting mechanisms. The downside is drawing primitives only work in the context of a Drawing, but the compiler will not stop you from using them external to one. The counter case is to make Drawing specific layouts which currently seems to be the greater evil.

Ideally Layout would allow any child which implements some ILayoutable interface, of which View and and Drawing Primitives would implement. This would however be a breaking change, so at the moment it seems View is the only viable option.

Brush

ImageBrush is probably going to be needed. Research needs to be done to ensure that every platform can support ImageBrush everywhere brushes are used.

DrawingTemplate

There currently exists no mechanism in core to switch the renderer based on a property as this will require. That will need to be added. Ideally this should be more generic than a switch based on the Template.

@pauldipietro pauldipietro added this to New in Triage Apr 12, 2018
@jassmith jassmith removed this from New in Triage Apr 12, 2018
@jassmith jassmith mentioned this issue Apr 12, 2018
26 tasks
@MelbourneDeveloper
Copy link

MelbourneDeveloper commented Apr 13, 2018

@jassmith ,

This is a very good idea from a XAML standardization point of view, and will provide powerful functionality, However, I'd be careful going down this path. It will definitely contribute to the overall goal of moving Xamarin.Forms toward XAML Standard (https://github.com/Microsoft/xaml-standard). But, along with VisualStates, there's big question marks around how useful this will be in reality.

Graphical acceleration in these kinds of areas must be taken in to consideration. The lack of graphics acceleration is already an issue in some parts of the system like animations. My guess is that if Xamarin.Forms takes on the responsibility of rendering vector imaging, it will be subsequently removed from the underlying platform - and moved from GPU processing to CPU processing. This will be a massive performance hit in some cases. It's not that it shouldn't be done, but thought should be put in to whether or not the processing can be left at the GPU level instead of being moved to the CPU. Consumers of the XF library need to be made aware of what will run on native platform, and what will be rendered by the XF library.

There's also the question of balance between native drawing and cross platform drawing differences. Text is an important point. Should text be rendered the same on all platforms? I.e. should font rendering be passed over to XF to do so as to create uniformity over all platforms? Perhaps. But, I don't feel like that should be the overall project for XF. People subconsciously detect small visual details. The details might be in an animation or so on. Even a small departure from the norm on a given platform can make the user feel uncomfortable. So, it's not necessarily a good idea that all drawing be made uniform. Avalonia is certainly going down that path, but that's a totally separate case, and that's a point of difference between Avalonia and Xamarin Forms.

Also, one more comment is that care should be taken to make sure any primitive types are named the same, and are aligned as closely as possible to other platforms like UWP, and WPF so as to be inline with XAML Standard.

@davidortinau , do you have thoughts on this?

@ChaseFlorell
Copy link

One of the great features in material design is the Ripple. Do you expect to support this?
Overall I think this is fantastic!

@rogihee
Copy link
Contributor

rogihee commented Apr 13, 2018

I really like this direction. For iOS I was using native view cells using the native elements (i, > options), but the more I apply custom theming I find myself just mimicking a bit the native cells and going more for a nice looking/working theme that is fluent and consistent for the app but not per se native apart from details. I think that if the appropriate underlying rendering library is used GPU will not be a problem, read Skia. The same thing powering Flutter.

Perhaps it's a seperate issue, but it would be nice to make SVG a first class citizen of Forms at the same time. Enabling neat effects such as animated tinting for an image button upon press for example.

My opinion is that in the end you want powerful, rich, native looking (not per se native!) controls that are easy to program with consistent behavior cross-platform, with the odd exception to accomodate a native quirk of a platform. E.g. a ripple effect for Android.

@samhouts samhouts added this to Backlog in Enhancements Apr 13, 2018
@jassmith
Copy link
Author

@ChaseFlorell as a matter of fact I do. The idea being that you can x:Name things in the template and then dig them out using FindByName. Once you have the native element you can apply animations to it like anything else, however there will likely be a special way to get an animation callback. I'm still working out those exact details. With Skia doing to drawing this can easily hit 60FPS on android and even without Skia you can hit 60FPS on the other platforms.

@rogihee SVG really isn't a shipping format sorry :/ I don't want to be responsible for trying to render SVG consistently cross platforms. When are they going to add hinting to SVG's anyway...

@MelbourneDeveloper
Copy link

@jassmith , will this us hardware graphics acceleration?

@RichiCoder1
Copy link

Coming from Qt's QML, would love to see this. Combined with a few obvious builtin controls, can conver a lot of ground.

Maybe a bit premature or worth another issue , but what's the accessibility/testability story plan for controls built ground up with this?

@jassmith
Copy link
Author

@RichiCoder1 a11y is certainly something that will need to be properly worked out. Ideally a Text element would automatically set most of the required properties for simple controls.

@juepiezhongren
Copy link

is this the feature for xf 4.0?

@jassmith
Copy link
Author

3.0 series

@juepiezhongren
Copy link

@jassmith there is nothing about draw and shell in roadmap

@jassmith
Copy link
Author

AFAIK the public roadmap does not include anything that has no been scheduled fully

@juepiezhongren
Copy link

will all these preview in 2018?@jassmith

@davidortinau
Copy link
Contributor

@juepiezhongren we have not committed to doing these proposals. They are presented here for open discussion on their merits, deficiencies, etc.

I take it from your interest that these specs are interesting to you. Would you share some specific examples of where you see them helping you when building apps with Xamarin.Forms? What problems do you see this solving? What opportunities do you see them opening up for you?

Any real-world examples and stories you can share would be tremendously useful in helping us validate that this could be providing real value.

As always, anyone can feel free to email me if preferred. david.ortinau@microsoft.com

@timahrentlov
Copy link

timahrentlov commented Apr 24, 2018

The biggest problem for me is the "we can't do that with the Forms framework" reply that I have to give to potential customers and UX/UI. It discredits the framework and I only get so many chances with a customer.

Forms lack a compositional paradigm where we pr. project can build the UI using UI primitives. This applies to navigation, animations (incl. stuff like hero-animations), UI elements and gestures.

Will this suggestion give us such platform-neutral compositional UI primitives?

@opcodewriter
Copy link

@timahrentlov We need to see discuss and see exactly what those limitations are and the reason of those limitations. But honestly I don't even dare to think or look that far. The issue I see with Xamarin Forms is from a much simpler perspective: it still remains a project with very limited development resources. It's unrealistic or useless to discuss what it could be done, when in fact there's no actual enough power and fuel. I don't see the point. Is maybe Xamarin secretly still hoping some individuals from the OSS community will start working and fixing things? Don't get me wrong, I respect the time and effort Xamarin has put into Xamarin Forms.

@juepiezhongren
Copy link

@davidortinau
cross platform is hard to make out chracteristic visual design, unique button appearance, unique placeholder disappearing effect etc r really avoid our apps being identical. For example, mac's notice fading, with a slight explosion, is realy easy to impress its customers. Why we love wpf a lot that day, one reason i shall mention, is control template, where we enjoy paths so much for our uniqueness, like cornered hexagon button. We want xf bring these to cross platform client devs.

@opcodewriter
Copy link

@juepiezhongren if you're looking for that kind of UI customization, I don't think there's any cross-platform framework which can do that. And about WPF: it's a bad idea to mix WPF with mobile.

@juepiezhongren
Copy link

my team is using react native too, where so many jsers contribute a lot, where after 3 months we concluded that it's not productive at all. For xf, it is with drawbacks, with bugs, but basically it is solid solution, eps x.native makes all native api valid. What lacks is only ubi apperance, cusidering flutter' recent mafness. Besides, with shell, flutter shall be useless, without something like flutter.ios, flutter shall be like rn with native api limitless suffering.

@juepiezhongren
Copy link

@opcodewriter
we use skiasharp rather frequently, making special control, its performance is satisfying

@juepiezhongren
Copy link

@jassmith have u considered to port materialShell to wasm by using webgl, for skia, maybe it is too big to download

@jassmith
Copy link
Author

jassmith commented Apr 25, 2018

correct we dont want to take a hard dep on any third party libs for the default drawing API. <SkiaDrawing> could do that

@juepiezhongren
Copy link

with xamarin.mono and shell in wasm, any alpha product will cause a dotnet renaissance in china, where hatred against dotnet is too much prevailing

@juepiezhongren
Copy link

@jassmith any good news about this issue?

@ChaseFlorell
Copy link

what news are you looking for @juepiezhongren? At this point it's a Spec posted to invoke discussion.

@wuxueqicai
Copy link

Any news about this?

@legistek
Copy link
Contributor

Also wondering if this is still likely to happen. I'm very much in the camp of wanting a lookless cross-platform UI framework and this seems to be the best way to achieve that.

@charlesroddie
Copy link

@legistek You can use SkiaSharp for lookless cross-platform drawing. What are the advantages of a Xamarin.Forms-specific one in your mind?

@legistek
Copy link
Contributor

There's a bit more to a UI framework than drawing.

@charlesroddie
Copy link

But this thread is discussing a drawing framework not a UI framework...

@legistek
Copy link
Contributor

I thought it was discussing a drawing framework for Xamarin Forms.

@charlesroddie
Copy link

charlesroddie commented Nov 25, 2019

SkiaSharp is a drawing framework for Xamarin Forms. The fact it also works on other .Net UI platforms is surely an advantage not a disadvantage.

@legistek
Copy link
Contributor

And as was said in the OP, SkiaSharp could well be the underlying drawing engine on the individual platforms but the idea of this proposal is to add an abstraction layer and support drawing through XAML with all its benefits, the most notable one being data binding. What you call unnecessary complexity I call elegant.

This was referenced Jan 13, 2020
@samhouts samhouts added the in-progress This issue has an associated pull request that may resolve it! label Jan 15, 2020
@samhouts samhouts added this to In Progress in v4.6.0 Jan 15, 2020
This was referenced Jan 15, 2020
@samhouts samhouts removed this from Discussion Required in Enhancements Feb 7, 2020
@samhouts samhouts added this to In Progress in vCurrent (4.8.0) Apr 16, 2020
@samhouts samhouts removed this from In Progress in v4.6.0 Apr 16, 2020
@samhouts samhouts removed this from In Progress in vCurrent (4.8.0) May 11, 2020
@legistek
Copy link
Contributor

Is this still alive and/or will it be rolled into MAUI?

@samhouts
Copy link
Member

@legistek https://github.com/xamarin/Xamarin.Forms/wiki/Feature-Roadmap lists Shapes, Paths, and Brushes as on the roadmap for Xamarin.Forms 4.7.0.

@legistek
Copy link
Contributor

Wonderful news! Thanks!

samhouts pushed a commit that referenced this issue Jun 9, 2020
* Added Path definition in Core (Shapes)
Implemented Path in Android and iOS

* Fixed Android build errors

* Fixed UWP Build

* Fixed WPF Build

* Implemented PathRenderer on UWP

* Added unit tests

* Fixed namespaces conflicts in Platform projects

* Changes to fix the build errors

* Implemented Path Transformations in Android and iOS

* Fixed Build error in WPF and UWP

* Implemented Path Transformations in UWP

* Fixed iOS Build error

* Changes to fix the Build (Path namespace conflict)

* More changes to fix the build error

* Fixed Windows Build errors

* Fixed Path size issue on UWP

* Added Shapes_Experimental flag

* Updated path sample

* Updated Android ShapeRenderer size logic

* Added Shape Aspect sample in Core Gallery

* Added more Shapes samples

* Updated UWP PathRenderer size logic

* Updated droid and iOS pathRenderer size logic (same behavior in all the platforms)

* Updated UWP ShapeRenderer

* Implemented Path in WPF Backend

* Fixed build error

* Initial Clip implementation in WPF and UWP (work in progress)

* Added Path implementation on macOS

* Added Clip implementation in Android, iOS and macOS

* Fixed broken unit tests

* Notify the change of Geometry if any of the child properties changed

* Added new sample clipping different views

* Fixed flipped shape issue on macOS

* Added support to Clip using EllipseGeometry, LineGeometry and RectangleGeometry in UWP

* Changed Shape class to be abstract

* Moved Shapes to Xamarin.Forms.Shapes in Android, iOS and macOS

* Moved Shapes to Xamarin.Forms.Shapes namespace in Windows (UWP and WPF)

* Fixed wrong property in LineGeometry

* Fixed build error

* Added Clip Performance sample in Core Gallery

* Update Matrix.cs

* Update RectangleGeometry.cs

* Update Xamarin.Forms.Platform.macOS.csproj

* Some duplicate classes

* Update PointCollectionTests.cs

* Update ImageButtonRenderer.cs

* Update Xamarin.Forms.Platform.iOS.csproj

* Update Xamarin.Forms.Platform.iOS.csproj

* Fixed tabs error

Co-authored-by: Samantha Houts <samhouts@users.noreply.github.com>

fixes #2452 (partially)
fixes #9178
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
a/brushes a/shapes in-progress This issue has an associated pull request that may resolve it! m/high impact ⬛ t/enhancement ➕
Projects
No open projects
Sprint 138
  
To do
Development

Successfully merging a pull request may close this issue.