Skip to content

[API Proposal]: public Viewbox.ComputeScaleFactor #9350

Open

Description

Background and motivation

Any code using the Stretch (and StretchDirection) property has to figure out how to scale the content respecting these properties, and how to undo the scaling when mapping coordinates back to the content. From built-in controls, this includes Image, MediaElement, Viewbox and DocumentPageView which all call a helper method to calculate the scaling.

It would be beneficial to other developers to be able to reuse the code for consistent results including corner cases (such as infinities and near-zero values).

API Proposal

namespace System.Windows.Controls;

public class Viewbox
{
-    internal static Size ComputeScaleFactor(Size availableSize, Size contentSize, Stretch stretch, StretchDirection stretchDirection);
+    public static Size ComputeScaleFactor(Size availableSize, Size contentSize, Stretch stretch, StretchDirection stretchDirection); 
}

API Usage

void Image_MouseLeftButtonDown(MouseButtonEventArgs e)
{
    Point point = e.GetPosition(this);
    Size stretchScale = ComputeScaleFactor(RenderSize, new Size(Source.Width, Source.Height), Stretch, StretchDirection);
    Point pixelPoint = new Point(point.X / stretchScale.Width, point.Y / stretchScale.Height); // click in image source coordinates
    ...
}     

Alternative Designs

The final scaling transform could be made available as a ScaleTransform instead. This would provide more robust solution with invertability and built-in ability to transform points and bounds, but with higher computational and memory costs. This could either be a new constructor, such as

public ScaleTransform(Size availableSize, Size contentSize, Stretch stretch, StretchDirection stretchDirection)

or a static method such as

public static ScaleTransform FromStretch(Size availableSize, Size contentSize, Stretch stretch, StretchDirection stretchDirection)

The Viewbox itself creates a ScaleTransform with the calculated values and uses it as a visual transform on the child.

Yet more alternatively, there could just be a TranslatePoint method somewhere (like UIElement or Viewbox), but that would have to calculate the scaling each time, which isn't great for usage in mouse move etc.

Risks

No existing API surface is changed or removed, so there shouldn't be breaking changes. The code to calculate the scaling already exists as an internal method.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    API suggestionEarly API idea and discussion, it is NOT ready for implementation

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions