Merge pull request #143 from microsoft/inlineData
Add support for image inline data
This commit is contained in:
Коммит
a77916b50e
9
USAGE.md
9
USAGE.md
|
@ -76,13 +76,20 @@ If you have questions about a scenario you don't see below, please [file an issu
|
|||
## Image
|
||||
|
||||
- For Image, note that you should specify its size so that RN reserves space for it, otherwise the image won't show.
|
||||
- Supports Bitmap images and SVG files.
|
||||
- Supports Bitmap images and SVG files URIs, as well as inline Base64-encoded data:
|
||||
|
||||
```jsx
|
||||
<Image source="https://microsoft.github.io/react-native-windows/img/homepage/cross-platform.png"
|
||||
width={200} height={100} />
|
||||
```
|
||||
|
||||
```jsx
|
||||
<Image
|
||||
source="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4gPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyOCAyOCIgZmlsbD0ibm9uZSI+PHBhdGggZD0iTTEzLjEyNSAwSDBWMTMuMTI1SDEzLjEyNVYwWiIgZmlsbD0iI0YyNTAyMiI+PC9wYXRoPjxwYXRoIGQ9Ik0yOCAwSDE0Ljg3NVYxMy4xMjVIMjhWMFoiIGZpbGw9IiM3RkJBMDAiPjwvcGF0aD48cGF0aCBkPSJNMTMuMTI1IDE0Ljg3NUgwVjI4SDEzLjEyNVYxNC44NzVaIiBmaWxsPSIjMDBBNEVGIj48L3BhdGg+PHBhdGggZD0iTTI4IDE0Ljg3NUgxNC44NzVWMjhIMjhWMTQuODc1WiIgZmlsbD0iI0ZGQjkwMCI+PC9wYXRoPjwvc3ZnPiA="
|
||||
width={80}
|
||||
height={80} />
|
||||
```
|
||||
|
||||
## ComboBox
|
||||
|
||||
```jsx
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"type": "patch",
|
||||
"comment": "Support SVG and PNG inline data",
|
||||
"packageName": "react-native-xaml",
|
||||
"email": "asklar@microsoft.com",
|
||||
"dependentChangeType": "patch"
|
||||
}
|
|
@ -19,9 +19,11 @@
|
|||
|
||||
#include "Styling.h"
|
||||
|
||||
#include <winrt/Windows.Storage.Streams.h>
|
||||
#include <winrt/Windows.Security.Cryptography.h>
|
||||
|
||||
namespace jsi = facebook::jsi;
|
||||
|
||||
using namespace winrt;
|
||||
using namespace winrt::Microsoft::ReactNative;
|
||||
|
||||
#define MAKE_GET_DP(type, prop) IsType<type>, []() { return type::prop(); }
|
||||
|
@ -323,4 +325,50 @@ void XamlMetadata::PopulateNativeProps(std::vector<std::string>& names, const wi
|
|||
auto cn = winrt::get_class_name(rea);
|
||||
auto trea = rea.try_as<xaml::Input::TappedRoutedEventArgs>();
|
||||
}
|
||||
}
|
||||
|
||||
winrt::IAsyncOperation<winrt::Windows::Storage::Streams::InMemoryRandomAccessStream> GetImageInlineDataAsync(const std::string& uri) {
|
||||
size_t start = uri.find(',');
|
||||
if (start == std::string::npos || start + 1 > uri.length())
|
||||
co_return nullptr;
|
||||
|
||||
try {
|
||||
co_await winrt::resume_background();
|
||||
|
||||
std::string_view base64String(uri.c_str() + start + 1, uri.length() - start - 1);
|
||||
auto buffer =
|
||||
winrt::Windows::Security::Cryptography::CryptographicBuffer::DecodeFromBase64String(winrt::to_hstring(base64String));
|
||||
|
||||
winrt::Windows::Storage::Streams::InMemoryRandomAccessStream memoryStream;
|
||||
auto b = memoryStream.CanWrite();
|
||||
co_await memoryStream.WriteAsync(buffer);
|
||||
memoryStream.Seek(0);
|
||||
|
||||
co_return memoryStream;
|
||||
}
|
||||
catch (winrt::hresult_error const&) {
|
||||
// Base64 decode failed
|
||||
}
|
||||
|
||||
co_return nullptr;
|
||||
}
|
||||
|
||||
winrt::fire_and_forget winrt::Microsoft::ReactNative::SetImageSourceForInlineData(std::string str, xaml::DependencyObject o, xaml::DependencyProperty dp) {
|
||||
// inline data
|
||||
const auto streamOp = GetImageInlineDataAsync(str);
|
||||
auto stream = co_await streamOp;
|
||||
|
||||
xaml::Media::ImageSource source{ nullptr };
|
||||
if (str.find("image/svg+xml;base64") != std::string::npos) {
|
||||
auto src = xaml::Media::Imaging::SvgImageSource();
|
||||
co_await src.SetSourceAsync(stream);
|
||||
source = src;
|
||||
}
|
||||
else if (str.find("image/png;base64") != std::string::npos) {
|
||||
auto src = xaml::Media::Imaging::BitmapImage();
|
||||
co_await src.SetSourceAsync(stream);
|
||||
source = src;
|
||||
}
|
||||
|
||||
o.SetValue(dp, source);
|
||||
}
|
|
@ -15,7 +15,6 @@
|
|||
#include "XamlObject.h"
|
||||
#include <Wrapper.h>
|
||||
|
||||
|
||||
using namespace xaml;
|
||||
using namespace xaml::Controls;
|
||||
using namespace winrt::Microsoft::ReactNative;
|
||||
|
@ -37,13 +36,55 @@ namespace winrt::Microsoft::ReactNative {
|
|||
value = xaml::Media::FontFamily(str);
|
||||
}
|
||||
|
||||
inline void ReadValue(JSValue const& jsValue, xaml::Media::ImageSource& value) noexcept {
|
||||
const auto uri = Uri{ winrt::to_hstring(jsValue.AsString()) };
|
||||
if (jsValue.AsJSString().ends_with(".svg")) {
|
||||
value = xaml::Media::Imaging::SvgImageSource {uri};
|
||||
winrt::fire_and_forget SetImageSourceForInlineData(std::string str, xaml::DependencyObject o, xaml::DependencyProperty dp);
|
||||
|
||||
enum class XamlPropType {
|
||||
Boolean,
|
||||
Int,
|
||||
Double,
|
||||
String,
|
||||
Object,
|
||||
Enum,
|
||||
};
|
||||
|
||||
template <typename T> bool IsType(const winrt::Windows::Foundation::IInspectable& i) { return i.try_as<T>() != nullptr; }
|
||||
|
||||
template<typename T, std::enable_if_t<std::is_enum<T>::value, int> = 0>
|
||||
void SetPropValue(const xaml::DependencyObject o, const xaml::DependencyProperty& prop, const winrt::Microsoft::ReactNative::JSValue& v, const winrt::Microsoft::ReactNative::IReactContext&) {
|
||||
auto valueEnum = MakeEnum<T>(v.AsInt32());
|
||||
o.SetValue(prop, valueEnum);
|
||||
}
|
||||
|
||||
template<typename T, std::enable_if_t<
|
||||
!std::is_enum<T>::value &&
|
||||
!std::is_same<winrt::hstring, T>::value &&
|
||||
!std::is_same<winrt::Windows::Foundation::IInspectable, T>::value &&
|
||||
!std::is_same<winrt::Windows::Foundation::Uri, T>::value &&
|
||||
!std::is_same<xaml::Media::ImageSource, T>::value
|
||||
, int> = 0>
|
||||
void SetPropValue(const xaml::DependencyObject& o, const xaml::DependencyProperty& prop, const winrt::Microsoft::ReactNative::JSValue& v, const winrt::Microsoft::ReactNative::IReactContext&) {
|
||||
auto b = v.To<T>();
|
||||
o.SetValue(prop, winrt::box_value(b));
|
||||
}
|
||||
|
||||
template<typename T, std::enable_if_t<
|
||||
std::is_same<xaml::Media::ImageSource, T>::value, int> = 0>
|
||||
void SetPropValue(const xaml::DependencyObject& o, const xaml::DependencyProperty& prop, const winrt::Microsoft::ReactNative::JSValue& v, const winrt::Microsoft::ReactNative::IReactContext&) {
|
||||
|
||||
const auto str = v.AsString();
|
||||
const auto uri = Uri{ winrt::to_hstring(str) };
|
||||
|
||||
xaml::Media::ImageSource value{ nullptr };
|
||||
if (uri.SchemeName() == L"data") {
|
||||
SetImageSourceForInlineData(str, o, prop);
|
||||
}
|
||||
else if (str.ends_with(".svg") || str.ends_with(".svgz")) {
|
||||
value = xaml::Media::Imaging::SvgImageSource{ uri };
|
||||
o.SetValue(prop, value);
|
||||
}
|
||||
else {
|
||||
value = xaml::Media::Imaging::BitmapImage{ uri };
|
||||
o.SetValue(prop, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,34 +98,6 @@ namespace winrt::Microsoft::ReactNative {
|
|||
}
|
||||
}
|
||||
|
||||
enum class XamlPropType {
|
||||
Boolean,
|
||||
Int,
|
||||
Double,
|
||||
String,
|
||||
Object,
|
||||
Enum,
|
||||
};
|
||||
|
||||
template <typename T> bool IsType(const winrt::Windows::Foundation::IInspectable& i) { return i.try_as<T>() != nullptr; }
|
||||
|
||||
template<typename T, std::enable_if_t<std::is_enum<T>::value, int> = 0>
|
||||
void SetPropValue(const xaml::DependencyObject o, const xaml::DependencyProperty& prop, const winrt::Microsoft::ReactNative::JSValue& v, const winrt::Microsoft::ReactNative::IReactContext&) {
|
||||
auto valueEnum = MakeEnum<T>(v.AsInt32());
|
||||
o.SetValue(prop, valueEnum);
|
||||
}
|
||||
|
||||
template<typename T, std::enable_if_t<
|
||||
!std::is_enum<T>::value &&
|
||||
!std::is_same<winrt::hstring, T>::value &&
|
||||
!std::is_same<winrt::Windows::Foundation::IInspectable, T>::value &&
|
||||
!std::is_same<winrt::Windows::Foundation::Uri, T>::value
|
||||
, int> = 0>
|
||||
void SetPropValue(const xaml::DependencyObject& o, const xaml::DependencyProperty& prop, const winrt::Microsoft::ReactNative::JSValue& v, const winrt::Microsoft::ReactNative::IReactContext&) {
|
||||
auto b = v.To<T>();
|
||||
o.SetValue(prop, winrt::box_value(b));
|
||||
}
|
||||
|
||||
|
||||
// MapStyle has a bug where it expects the property to be set as an IReference<MapStyle> always, and does not support IReference<uint32_t>
|
||||
template<typename T, std::enable_if_t<
|
||||
|
|
Загрузка…
Ссылка в новой задаче