-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Image] Implement 'center' and 'repeat' resizeModes #2581
[Image] Implement 'center' and 'repeat' resizeModes #2581
Conversation
vnext/ReactUWP/Views/cppwinrt/react.uwp.image.ReactImageBrush.g.h
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🕐
{ | ||
bool effectToSurfaceBrushSwitch{ | ||
ResizeMode() != ResizeMode::Repeat && | ||
!CompositionBrush().try_as<winrt::CompositionSurfaceBrush>() }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
!CompositionBrush().try_aswinrt::CompositionSurfaceBrush() [](start = 8, length = 60)
This check feels a bit awkward - we're looking to see if we have an effect brush set, yes? In this case can you check for a non-null m_effectBrush instead? Alternatively, consider refactoring this into a "HasEffectBrush()" helper function #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm caching the effect brush in case they have some kind of mechanism to switch an image's resizeMode at runtime, so we can't just check to see if it's not null. What I want to know is if the current composition brush is not a CompositionSurfaceBrush (because that's when we would want to switch brushes). I've added a "UsingSurfaceBrush()" helper function. #Closed
ResizeMode() != ResizeMode::Repeat && | ||
!CompositionBrush().try_as<winrt::CompositionSurfaceBrush>() }; | ||
|
||
bool surfaceToEffectBrushSwitch{ ResizeMode() == ResizeMode::Repeat }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bool surfaceToEffectBrushSwitch{ ResizeMode() == ResizeMode::Repeat }; [](start = 6, length = 70)
This seems to be missing a bit of logic (I think it should also check for a null m_effectBrush). #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The effect brush is created and/or retrieved just before the call to this method and the GetOrCreateEffectBrush call is also gated by the same logic (ResizeMode == Repeat).
All other modes use the SurfaceBrush, so we always have to switch brushes if ResizeMode has been set to Repeat. #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the explanation. Reading through this a bit more carefully, I see where I got confused - this function isn't really checking to see if we need to switch brushes as it might already be set to the appropriate brush. It looks like you could remove ShouldSwitchCompositionBrush() altogether, and set the CompositionBrush to what you've already got in compositionBrush. As it stands the code is somewhat confusing.
In reply to: 293640055 [](ancestors = 293640055)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does check if we need to switch brushes. It's basically just preventing an unnecessary CompositionBrush set when we are switching between two resizeModes that use a CompositionSurfaceBrush (center, contain, cover, stretch). In those cases all we need to do is update CompositionSurfaceBrush.Stretch which is what we do right after we get the SurfaceBrush.
I think the most human way of expressing this is in the negative (i.e. when do we NOT want to switch brushes), so maybe this is more readable?
bool ReactImageBrush::ShouldSwitchCompositionBrush()
{
// The only scenario where we do not want to switch brushes is if:
// 1. We're not switching to the EffectBrush (Repeat is the only resizeMode that uses the EffectBrush) and
// 2. We're already using the SurfaceBrush
return !(ResizeMode() != ResizeMode::Repeat && UsingSurfaceBrush())
}
In reply to: 294010205 [](ancestors = 294010205,293640055)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this example run-through will help illustrate the point I'm trying to make:
- App sets ResizeMode to Repeat => ShouldSwitchCompositionBrush returns true, because ResizeMode() == Repeat.
- A little bit later, the size of the element changes and we set the AvailableSize. => ShouldSwitchCompositionBrush again returns true, even though we already have the effect brush set.
I would have expected the function to only return true if we actually need to set a new brush into CompositionBrush().
If I'm reading the code correctly, everything that leads up to the "should switch brushes" check is computing the brush that we should set. Assuming I've got this correct, why can't you just query the current CompositionBrush() and compare to the one you're about to set, and only set if they are different? #Resolved
…eact-native-windows into image-bordereffect
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ImageSource source{ reactImage->Source() }; | ||
|
||
EmitImageEvent(m_wkReactInstance.lock(), reactImage.as<winrt::Canvas>(), succeeded ? "topLoad" : "topError", source); | ||
EmitImageEvent(m_wkReactInstance.lock(), reactImage.as<winrt::Canvas>(), "topLoadEnd", source); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as mentioned over chat, we want to change these to fire only when subscribed to, which will require having a shadownode to store if onLoad/etc have been set. #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh i thought maybe these were firing more than before your change (for non-http) but that doesn't appear to be the case, future fix...
In reply to: 294093989 [](ancestors = 294093989)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
}; | ||
|
||
HRESULT GetNamedPropertyMappingImpl( | ||
_In_count_(mappingCount) const NamedProperty* namedProperties, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should that be _In_count(namedPropertyCount)? #Resolved
#include <winrt/Windows.Foundation.h> | ||
#include <winrt/Windows.UI.h> | ||
|
||
#define CATCH_RETURN \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like this (and probably the DECLARE macros below?) should be in a separate header. #Resolved
return image; | ||
auto reactImage{ ReactImage::Create() }; | ||
|
||
reactImage->OnLoadEnd([=](const auto&, const bool& succeeded) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are a lot of good reasons to avoid default lambda captures entirely. Consider making this an explicit capture of [this, reactImage] (tag is unused?)
Check out F.54, for example. #Resolved
} | ||
} | ||
catch (winrt::hresult_error const&) | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this fire the load end event?
(like above when the memory stream fails?) #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking forward to trying out these changes
🚀
} | ||
|
||
// Only switch CompositionBrush if we are switching to/from ResizeMode::Repeat | ||
if (ShouldSwitchCompositionBrush()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this check be made before creating surfaceBrush and compositionBrush? #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was a bad name. The code above determines the correct brush we need to use. This should just check to see if it is different than what we're currently using and set it if that's the case.
In reply to: 294561221 [](ancestors = 294561221)
#2111
ImageViewManager:
ReactImage:
ReactImageBrush:
BorderEffect:
Microsoft Reviewers: Open in CodeFlow