diff --git a/source/uwp/SharedRenderer/lib/AdaptiveImageRenderer.cpp b/source/uwp/SharedRenderer/lib/AdaptiveImageRenderer.cpp index 871dfb96f2..e39b3c66a1 100644 --- a/source/uwp/SharedRenderer/lib/AdaptiveImageRenderer.cpp +++ b/source/uwp/SharedRenderer/lib/AdaptiveImageRenderer.cpp @@ -36,7 +36,7 @@ namespace winrt::AdaptiveCards::Rendering::Xaml_Rendering::implementation namespace AdaptiveCards::Rendering::Xaml_Rendering { - auto inline GetDispatcher(winrt::SvgImageSource const &imageSource) + auto inline GetDispatcher(winrt::ImageSource const &imageSource) { #ifdef USE_WINUI3 return imageSource.DispatcherQueue(); @@ -289,74 +289,78 @@ namespace AdaptiveCards::Rendering::Xaml_Rendering adaptiveCardElement, selectAction, renderContext, frameworkElement, XamlHelpers::SupportsInteractivity(hostConfig), true); } - template - winrt::ImageSource XamlBuilder::SetImageOnUIElement(winrt::Uri const& imageUrl, - winrt::AdaptiveCardResourceResolvers const& resolvers, - ImageProperties const& imgProperties) + winrt::Windows::Foundation::Size XamlBuilder::ParseSizeOfSVGImageFromXmlString(winrt::hstring const& content) { - bool mustHideElement = true; + // Parse the size from the XamlDocument as XML + winrt::XmlDocument xmlDoc; - // Get the image url scheme - winrt::hstring schemeName = imageUrl.SchemeName(); + xmlDoc.LoadXml(content); - // Get the resolver for the image - if (resolvers) + if (xmlDoc) { - auto resolver = resolvers.Get(schemeName); - // If we have a resolver - if (resolver) + auto rootElement = xmlDoc.DocumentElement(); + + // Root element must be an SVG + if (rootElement.NodeName() == L"svg") { - // Create a Image to hold the image data. We use BitmapImage & SvgImageSource in order to allow - // the tracker to subscribe to the ImageLoaded/Failed events - auto image = CreateImageSource(imgProperties.isImageSvg); + auto heightAttribute = rootElement.GetAttribute(L"height"); + auto widthAttribute = rootElement.GetAttribute(L"width"); - if (!m_enableXamlImageHandling && (m_listeners.size() != 0)) + double height{0.0}; + double width{0.0}; + + if (!heightAttribute.empty()) { - if (!imgProperties.isImageSvg) - { - image.as().CreateOptions(winrt::BitmapCreateOptions::None); - } - this->m_imageLoadTracker->TrackImage(image); + height = TryHStringToDouble(heightAttribute).value_or(0.0); } - // Create the arguments to pass to the resolver - auto args = winrt::make(imageUrl); + if (!widthAttribute.empty()) + { + width = TryHStringToDouble(widthAttribute).value_or(0.0); + } - // And call the resolver to get the image stream - auto getResourceStreamOperation = resolver.GetResourceStreamAsync(args); + return {static_cast(width), static_cast(height)}; + } + } - getResourceStreamOperation.Completed( - [this, weakThis = this->get_weak(), image, imgProperties]( - auto const& operation, auto status) -> void - { - if (status == winrt::AsyncStatus::Completed) - { - if (auto strongThis = weakThis.get()) - { - auto randomAccessStream = operation.GetResults(); - if (!randomAccessStream) - { - this->m_imageLoadTracker->MarkFailedLoadImage(image); - return; - } - strongThis->HandleAccessStreamForImageSource(imgProperties, randomAccessStream, image); - } - } - else - { - if (auto strongThis = weakThis.get()) - { - // Question: should we only mark as a failed image if (!m_enableXamlImageHandling && (m_listeners.size() != 0)) - this->m_imageLoadTracker->MarkFailedLoadImage(image); - } - } - }); - return image; + return {}; + } + + winrt::IAsyncOperation XamlBuilder::ParseSizeOfSVGImageFromStreamAsync(winrt::IRandomAccessStream const stream) + { + auto inputStream = stream.GetInputStreamAt(0); + auto dataReader = winrt::DataReader(inputStream); + + // Load the data from the stream + uint32_t numBytesLoaded = co_await dataReader.LoadAsync(static_cast(stream.Size())); + + // Read the data as a string + winrt::hstring svgString = dataReader.ReadString(numBytesLoaded); + + co_return ParseSizeOfSVGImageFromXmlString(svgString); + } + + winrt::IAsyncOperation XamlBuilder::ResolveToStreamAsync(winrt::Uri const imageUrl, + winrt::AdaptiveCardResourceResolvers const resolvers, bool const isImageSvg) + { + const auto weakThis = get_weak(); + const auto schemeName = imageUrl.SchemeName(); + + if (resolvers) + { + auto resolver = resolvers.Get(schemeName); + // If we have a resolver + if (resolver) + { + auto args = winrt::make(imageUrl); + auto stream = co_await resolver.GetResourceStreamAsync(args); + co_return stream; } } if (schemeName == L"data") { + co_await winrt::resume_background(); winrt::DataWriter dataWriter{winrt::InMemoryRandomAccessStream{}}; auto imagePath = HStringToUTF8(imageUrl.Path()); auto foundBase64 = imagePath.find("base64"); @@ -367,314 +371,219 @@ namespace AdaptiveCards::Rendering::Xaml_Rendering std::vector decodedData = AdaptiveBase64Util::Decode(data); dataWriter.WriteBytes(std::vector{decodedData.begin(), decodedData.end()}); } - else if (imgProperties.isImageSvg) + else if (isImageSvg) { // Extract ... string std::string data = ExtractSvgDataFromUri(imageUrl); dataWriter.WriteBytes(std::vector{data.begin(), data.end()}); } - auto image = CreateImageSource(imgProperties.isImageSvg); + auto storeOp = dataWriter.StoreAsync(); - if (!imgProperties.isImageSvg) + if (const auto strongThis = weakThis.get()) { - image.as().CreateOptions(winrt::BitmapCreateOptions::IgnoreImageCache); - } - m_imageLoadTracker->TrackImage(image); + strongThis->m_writeAsyncOperations.push_back(storeOp); - auto streamWriteOperation = dataWriter.StoreAsync(); + co_await storeOp; - streamWriteOperation.Completed( - [weakThis = this->get_weak(), dataWriter, image, imgProperties]( - auto const& /*operation*/, auto status) -> void - { - if (status == winrt::AsyncStatus::Completed) - { - if (auto strongThis = weakThis.get()) - { - if (const auto stream = dataWriter.DetachStream().try_as()) - { - stream.Seek(0); - strongThis->HandleAccessStreamForImageSource(imgProperties, stream, image); - } - } - } - }); - m_writeAsyncOperations.push_back(streamWriteOperation); - mustHideElement = false; - return image; + auto stream = dataWriter.DetachStream().try_as(); + stream.Seek(0); + + co_return stream; + } } // Otherwise, no resolver... - if ((m_enableXamlImageHandling) || (m_listeners.size() == 0)) + if (auto strongThis = weakThis.get()) { - // If we've been explicitly told to let Xaml handle the image loading, or there are - // no listeners waiting on the image load callbacks, use Xaml to load the images - auto image = CreateImageSource(imgProperties.isImageSvg); - - if (imgProperties.isImageSvg) - { - winrt::HttpClient httpClient; - auto getOperation = httpClient.GetAsync(imageUrl); - - getOperation.Completed([weakThis = this->get_weak(), - weakImageSource = winrt::make_weak(image.as()), - imageUrl](auto const& operation, auto status) - { - if (status == winrt::AsyncStatus::Completed) - { - winrt::HttpResponseMessage response = operation.GetResults(); - - if (response.IsSuccessStatusCode()) - { - auto readOperation = response.Content().ReadAsStringAsync(); - - readOperation.Completed([weakThis, weakImageSource, imageUrl](auto const& operation, auto status) - { - auto strongThis = weakThis.get(); - auto strongImageSource = weakImageSource.get(); - - if (strongThis && strongImageSource) - { - if (status == winrt::AsyncStatus::Completed) - { - // Read SVG xml - winrt::XmlDocument xmlDoc; - xmlDoc.LoadXml(operation.GetResults()); - auto success = strongThis->ParseXmlForHeightAndWidth(xmlDoc, strongImageSource); - if (success) - { - // Now that we've parsed the height and width successfully, we can set the image source - strongThis->SetSvgUriSource(strongImageSource, imageUrl); - } - } - } - }); - } - } - }); - } - else + if (!(strongThis->m_enableXamlImageHandling) && (strongThis->m_listeners.size() == 0)) { - image.as().UriSource(imageUrl); + winrt::HttpBaseProtocolFilter httpBaseProtocolFilter{}; + httpBaseProtocolFilter.AllowUI(false); + winrt::HttpClient httpClient{httpBaseProtocolFilter}; + auto getStreamOperation = httpClient.GetInputStreamAsync(imageUrl); + strongThis->m_getStreamOperations.push_back(getStreamOperation); + co_await getStreamOperation; + + auto imageStream = getStreamOperation.GetResults(); + winrt::InMemoryRandomAccessStream randomAccessStream{}; + auto copyStreamOperation = winrt::RandomAccessStream::CopyAsync(imageStream, randomAccessStream); + strongThis->m_copyStreamOperations.push_back(copyStreamOperation); + co_await copyStreamOperation; + co_return randomAccessStream; } - - SetImageSource(imgProperties.uiElement, image, imgProperties.stretch); - - // Issue #8126 - if (imgProperties.isAutoSize) - { - SetAutoSize(imgProperties.uiElement, - imgProperties.parentElement, - imgProperties.imageContainer, - imgProperties.isVisible, - true /* imageFiresOpenEvent */); - } - - return image; - } - else - { - return PopulateImageFromUrlAsync(imageUrl, imgProperties); } - } - winrt::ImageSource XamlBuilder::CreateImageSource(bool isImageSvg) - { - if (isImageSvg) - { - winrt::SvgImageSource svgImageSource{}; - return svgImageSource; - } - else - { - winrt::BitmapImage bitmapImage{}; - return bitmapImage; - } + co_return {}; } - // Issue #8127 template - winrt::ImageSource XamlBuilder::PopulateImageFromUrlAsync(winrt::Uri const& imageUrl, - ImageProperties const& imgProperties) + winrt::fire_and_forget XamlBuilder::ResolveImageAsync(winrt::Uri const uri, + winrt::AdaptiveCardResourceResolvers const resolvers, + winrt::ImageSource imageSource, + ImageProperties const properties) { - winrt::HttpBaseProtocolFilter httpBaseProtocolFilter{}; - httpBaseProtocolFilter.AllowUI(false); - - winrt::HttpClient httpClient{httpBaseProtocolFilter}; + auto isAutoSize{properties.isAutoSize}; + auto isSVG{properties.isImageSvg}; + auto weakThis{get_weak()}; + auto weakImageSource{winrt::make_weak(imageSource)}; + auto weakFrameworkElement = winrt::make_weak(properties.uiElement); - // Create an ImageSource to hold the image data. We use BitmapImage & SvgImageSource in order to allow - // the tracker to subscribe to the ImageLoaded/Failed events - auto image = CreateImageSource(imgProperties.isImageSvg); - this->m_imageLoadTracker->TrackImage(image); - - if (!imgProperties.isImageSvg) + try { - image.as().CreateOptions(winrt::BitmapCreateOptions::None); - } - - auto getStreamOperation = httpClient.GetInputStreamAsync(imageUrl); - getStreamOperation.Completed( - [this, weakThis = this->get_weak(), imgProperties, image]( - auto const& operation, auto status) -> void + // if image loading is handled by Xaml, we set this to true; + auto imageFiresOpenEvent{true}; + // we can not do any works until stream is resolved + auto stream = co_await ResolveToStreamAsync(uri, resolvers, isSVG); + if (auto strongImageSource = weakImageSource.get()) { - if (status == winrt::AsyncStatus::Completed) + if (stream) { - if (auto strongThis = weakThis.get()) + imageFiresOpenEvent = false; + + // the big differences between SVG and non-SVG images are: + // 1. SVG size needs to be parsed from its data source + // 2. SVG images need to be rasterized to a specific size + if (isSVG) { - auto imageStream = operation.GetResults(); - winrt::InMemoryRandomAccessStream randomAccessStream{}; - auto copyStreamOperation = winrt::RandomAccessStream::CopyAsync(imageStream, randomAccessStream); + auto sizeParseOp{ParseSizeOfSVGImageFromStreamAsync(stream)}; + // as size is being parsed, we can switch to the UI thread to set the source + co_await wil::resume_foreground(GetDispatcher(strongImageSource)); + auto svgImageSource = strongImageSource.as(); - m_copyStreamOperations.push_back(copyStreamOperation); + if (!isAutoSize) + { + auto size = co_await sizeParseOp; + svgImageSource.RasterizePixelHeight(size.Height); + svgImageSource.RasterizePixelWidth(size.Width); + } - copyStreamOperation.Completed( - [randomAccessStream, weakThis, imgProperties, image]( - auto const& /*operation*/, auto status) - { - if (status == winrt::AsyncStatus::Completed) - { - randomAccessStream.Seek(0); - if (auto strongThis = weakThis.get()) - { - strongThis->HandleAccessStreamForImageSource( - imgProperties, randomAccessStream, image); - } - } - }); + co_await svgImageSource.SetSourceAsync(stream); + } + else + { + co_await wil::resume_foreground(GetDispatcher(strongImageSource)); + auto bitmapImage = strongImageSource.as(); + co_await bitmapImage.SetSourceAsync(stream); } } - }); - m_getStreamOperations.push_back(getStreamOperation); - - return image; - } - - template - void XamlBuilder::HandleAccessStreamForImageSource(ImageProperties const& imgProperties, - TStream const& stream, - winrt::ImageSource const& imageSource) - { - SetImageSource(imgProperties.uiElement, imageSource, imgProperties.stretch); - - if (imgProperties.isImageSvg) - { - // If we have an SVG, we need to try to parse for the image size before setting the image source - auto streamSize = stream.Size(); - auto inputStream = stream.GetInputStreamAt(0); - auto streamDataReader = winrt::DataReader(inputStream); - auto loadDataReaderOperation = streamDataReader.LoadAsync((uint32_t)streamSize); - - loadDataReaderOperation.Completed( - [weakThis = this->get_weak(), streamDataReader, streamRef = winrt::make_weak(stream), - imageSourceRef = winrt::make_weak(imageSource.as()), imgProperties]( - auto const& result, auto status) -> void + else { - auto strongThis = weakThis.get(); - auto strongImageSource = imageSourceRef.get(); - auto strongStream = streamRef.get(); - - if (strongThis && strongImageSource && strongStream) + // Use Xaml to load the images + if (auto strongThis = weakThis.get()) { - if (status == winrt::AsyncStatus::Completed) + if ((strongThis->m_enableXamlImageHandling) || (strongThis->m_listeners.size() == 0)) { - auto bytes = result.GetResults(); - - try + // If we've been explicitly told to let Xaml handle the image loading, or there are + // no listeners waiting on the image load callbacks, use Xaml to load the images + if (isSVG) { - auto svgText = streamDataReader.ReadString(bytes); - - if (!svgText.empty()) - { - auto svgDocument = winrt::XmlDocument(); - svgDocument.LoadXml(svgText); - - auto success = strongThis->ParseXmlForHeightAndWidth(svgDocument, strongImageSource); - - if (success) - { - // Now that we've parsed the size, we can set the image source - strongThis->SetSvgImageSourceAsync(strongImageSource, strongStream, imgProperties); - } - } + winrt::HttpClient httpClient; + auto getOperation = co_await httpClient.GetAsync(uri); + auto readOperation = co_await getOperation.Content().ReadAsStringAsync(); + auto size{ParseSizeOfSVGImageFromXmlString(readOperation)}; + co_await wil::resume_foreground(GetDispatcher(strongImageSource)); + auto svgImageSource = strongImageSource.as(); + svgImageSource.RasterizePixelHeight(size.Height); + svgImageSource.RasterizePixelWidth(size.Width); + svgImageSource.UriSource(uri); } - catch (winrt::hresult_error) + else { - // There was an error reading the streamDataReader or loading the xml + co_await wil::resume_foreground(GetDispatcher(strongImageSource)); + strongImageSource.as().UriSource(uri); } } } - }); - } - else - { - auto setSourceAction = imageSource.as().SetSourceAsync(stream); + } - setSourceAction.Completed([weakThis = this->get_weak(), imgProperties]( - auto const& /*operation*/, auto status) + if (auto strongThis = weakThis.get(); isAutoSize) { - if (status == winrt::AsyncStatus::Completed && imgProperties.isAutoSize) - { - if (auto strongThis = weakThis.get()) - { - strongThis->SetAutoSize(imgProperties.uiElement, - imgProperties.parentElement, - imgProperties.imageContainer, - imgProperties.isVisible, - false /* imageFiresOpenEvent */); - } - } - }); + strongThis->SetAutoSize( + properties.uiElement, + properties.parentElement, + properties.imageContainer, + properties.isVisible, + imageFiresOpenEvent); + } + } + } + catch (...) + { + // Handle error + if (auto strongThis = weakThis.get()) + { + strongThis->m_imageLoadTracker->MarkFailedLoadImage(imageSource); + } } } - winrt::fire_and_forget XamlBuilder::SetSvgUriSource(winrt::SvgImageSource const imageSource, - winrt::Uri const uri) + void XamlBuilder::ConfigureImageSource(winrt::Uri const& imageUrl, + winrt::AdaptiveCardResourceResolvers const& resolvers, + winrt::ImageSource const& imageSource, + bool isImageSvg) { - co_await wil::resume_foreground(GetDispatcher(imageSource)); - imageSource.UriSource(uri); + winrt::hstring schemeName = imageUrl.SchemeName(); + auto hasResolver = resolvers && resolvers.Get(schemeName) != nullptr; + auto externalHandling = !(m_enableXamlImageHandling || (m_listeners.size() == 0)); + auto schemeNameIsData = schemeName == L"data"; + + if (!isImageSvg) + { + if ((hasResolver || !schemeNameIsData) && externalHandling) + { + imageSource.as().CreateOptions(winrt::BitmapCreateOptions::None); + } + else if (schemeNameIsData) + { + imageSource.as().CreateOptions(winrt::BitmapCreateOptions::IgnoreImageCache); + } + } + + if ((hasResolver && externalHandling) || schemeNameIsData) + { + m_imageLoadTracker->TrackImage(imageSource); + } } - template - winrt::IAsyncAction XamlBuilder::SetSvgImageSourceAsync(winrt::SvgImageSource const imageSource, - TStream const stream, - ImageProperties const imgProperties) + template + winrt::ImageSource XamlBuilder::SetImageOnUIElement(winrt::Uri const& imageUrl, + winrt::AdaptiveCardResourceResolvers const& resolvers, + ImageProperties const& imgProperties) { - auto weakThis = this->get_weak(); + auto imageSource = CreateImageSource(imgProperties.isImageSvg); - co_await wil::resume_foreground(GetDispatcher(imageSource)); - auto setSourceOperation = imageSource.SetSourceAsync(stream); + SetImageSourceToFrameworkElement(imgProperties.uiElement, imageSource, imgProperties.stretch); - setSourceOperation.Completed( - [weakThis, imgProperties]( - auto const& operation, auto status) - { - auto loadStatus = operation.GetResults(); - if (status == winrt::AsyncStatus::Completed && loadStatus == winrt::SvgImageSourceLoadStatus::Success) - { - if (auto strongThis = weakThis.get()) - { - if (imgProperties.isAutoSize) - { - strongThis->SetAutoSize(imgProperties.uiElement, - imgProperties.parentElement, - imgProperties.imageContainer, - imgProperties.isVisible, - false /* imageFiresOpenEvent */); - } - } - } - }); + ConfigureImageSource(imageUrl, resolvers, imageSource, imgProperties.isImageSvg); + + ResolveImageAsync(imageUrl, resolvers, imageSource, imgProperties); + + return imageSource; + } + + winrt::ImageSource XamlBuilder::CreateImageSource(bool isImageSvg) + { + if (isImageSvg) + { + winrt::SvgImageSource svgImageSource{}; + return svgImageSource; + } + else + { + winrt::BitmapImage bitmapImage{}; + return bitmapImage; + } } template - void XamlBuilder::SetImageSource(TDest const& destination, winrt::ImageSource const& imageSource, winrt::Stretch /*stretch*/) + void XamlBuilder::SetImageSourceToFrameworkElement(TDest const& destination, winrt::ImageSource const& imageSource, winrt::Stretch /*stretch*/) { destination.Source(imageSource); }; template <> - void XamlBuilder::SetImageSource(winrt::Ellipse const& destination, winrt::ImageSource const& imageSource, winrt::Stretch stretch) + void XamlBuilder::SetImageSourceToFrameworkElement(winrt::Ellipse const& destination, winrt::ImageSource const& imageSource, winrt::Stretch stretch) { winrt::ImageBrush imageBrush{}; imageBrush.ImageSource(imageSource); @@ -705,9 +614,6 @@ namespace AdaptiveCards::Rendering::Xaml_Rendering // If the image hasn't loaded yet if (imageFiresOpenEvent) { - // Collapse the Ellipse while the image loads, so that resizing is not noticeable - ellipse.Visibility(winrt::Visibility::Collapsed); - // Handle ImageOpened event so we can check the imageSource's size to determine if it fits in its parent // Take a weak reference to the parent to avoid circular references (Parent->Ellipse->ImageBrush->Lambda->(Parent)) auto weakParent = winrt::make_weak(parentElement); @@ -789,84 +695,7 @@ namespace AdaptiveCards::Rendering::Xaml_Rendering auto foundSvg = url.find("svg"); return !(foundSvg == std::string::npos); } - - bool XamlBuilder::ParseXmlForHeightAndWidth(winrt::XmlDocument const& xmlDoc, - winrt::SvgImageSource const& imageSource) - { - if (xmlDoc) - { - auto rootElement = xmlDoc.DocumentElement(); - - // Root element must be an SVG - if (winrt::operator==(rootElement.NodeName(), L"svg")) - { - auto height = rootElement.GetAttribute(L"height"); - auto width = rootElement.GetAttribute(L"width"); - - // We only need to set height or width, not both (fixes aspect ratio for person style) - bool isHeightSet = false; - - if (!height.empty()) - { - if (auto heightAsDouble = TryHStringToDouble(height)) - { - SetRasterizedPixelHeightAsync(imageSource, heightAsDouble.value()); - isHeightSet = true; - } - } - - if (!width.empty()) - { - if (auto widthAsDouble = TryHStringToDouble(width)) - { - SetRasterizedPixelWidthAsync(imageSource, widthAsDouble.value(), isHeightSet); - } - } - - return true; - } - } - return false; - } - - winrt::fire_and_forget XamlBuilder::SetRasterizedPixelHeightAsync(winrt::SvgImageSource const imageSource, - double const imageSize, - bool const dropIfUnset) - { - co_await wil::resume_foreground(GetDispatcher(imageSource)); - auto currentSize = imageSource.RasterizePixelHeight(); - bool sizeIsUnset = isinf(currentSize); - - // If the size has already been set explicitly, we need to update it with the correct value - // Ex: If `size: small`, the rasterize pixel size will be 40x40 at this point. - // If the actual image is 100x100, we cannot leave it as 100x40 and must set both height and width - bool dropHeight = sizeIsUnset && dropIfUnset; - - if (!dropHeight) - { - imageSource.RasterizePixelHeight(imageSize); - } - } - - winrt::fire_and_forget XamlBuilder::SetRasterizedPixelWidthAsync(winrt::SvgImageSource const imageSource, - double const imageSize, - bool const dropIfUnset) - { - co_await wil::resume_foreground(GetDispatcher(imageSource)); - auto currentSize = imageSource.RasterizePixelWidth(); - bool sizeIsUnset = isinf(currentSize); - - // If the size has already been set explicitly, we need to update it with the correct value - // Ex: If `size: small`, the rasterize pixel size will be 40x40 at this point. - // If the actual image is 100x100, we cannot leave it as 100x40 and must set both height and width - bool dropWidth = sizeIsUnset && dropIfUnset; - - if (!dropWidth) - { - imageSource.RasterizePixelWidth(imageSize); - } - } - + void XamlBuilder::SetRasterizedPixelHeight(winrt::ImageSource const& imageSource, double const& imageSize) { if (auto image = imageSource.try_as()) { diff --git a/source/uwp/SharedRenderer/lib/XamlBuilder.h b/source/uwp/SharedRenderer/lib/XamlBuilder.h index 0a65717491..a7075f9326 100644 --- a/source/uwp/SharedRenderer/lib/XamlBuilder.h +++ b/source/uwp/SharedRenderer/lib/XamlBuilder.h @@ -88,7 +88,7 @@ namespace AdaptiveCards::Rendering::Xaml_Rendering bool imageFiresOpenEvent); template - void SetImageSource(TDest const& destination, winrt::ImageSource const& imageSource, winrt::Stretch stretch = winrt::Stretch::UniformToFill); + void SetImageSourceToFrameworkElement(TDest const& destination, winrt::ImageSource const& imageSource, winrt::Stretch stretch = winrt::Stretch::UniformToFill); template winrt::ImageSource SetImageOnUIElement(winrt::Uri const& imageUrl, @@ -97,41 +97,32 @@ namespace AdaptiveCards::Rendering::Xaml_Rendering winrt::ImageSource CreateImageSource(bool isImageSvg); - template - winrt::ImageSource PopulateImageFromUrlAsync(winrt::Uri const& imageUrl, - ImageProperties const& imgProperties); + winrt::Windows::Foundation::Size XamlBuilder::ParseSizeOfSVGImageFromXmlString(winrt::hstring const& content); + + winrt::IAsyncOperation XamlBuilder::ParseSizeOfSVGImageFromStreamAsync(winrt::IRandomAccessStream const stream); - template - void HandleAccessStreamForImageSource(ImageProperties const& imgProperties, - TStream const& stream, - winrt::ImageSource const& imageSource); + winrt::IAsyncOperation XamlBuilder::ResolveToStreamAsync( + winrt::Uri const uri, winrt::AdaptiveCardResourceResolvers const resolvers, bool const isImageSvg); - winrt::fire_and_forget SetSvgUriSource(winrt::SvgImageSource const imageSourceRef, - winrt::Uri const uriRef); + void ConfigureImageSource(winrt::Uri const& imageUrl, + winrt::AdaptiveCardResourceResolvers const& resolvers, + winrt::ImageSource const& imageSource, + bool isImageSvg); - template - winrt::IAsyncAction SetSvgImageSourceAsync(winrt::SvgImageSource const imageSourceRef, - TStream const streamRef, - ImageProperties const imgProperties); + template + winrt::fire_and_forget ResolveImageAsync( + winrt::Uri const uri, + winrt::AdaptiveCardResourceResolvers const resolvers, + winrt::ImageSource imageSource, + ImageProperties const properties); boolean IsSvgImage(std::string url); void FireAllImagesLoaded(); void FireImagesLoadingHadError(); - bool ParseXmlForHeightAndWidth(winrt::XmlDocument const& xmlDoc, - winrt::SvgImageSource const& imageSourceRef); - - winrt::fire_and_forget SetRasterizedPixelHeightAsync(winrt::SvgImageSource const imageSourceRef, - double const imageSize, - bool const dropIfUnset = false); - winrt::fire_and_forget SetRasterizedPixelWidthAsync(winrt::SvgImageSource const imageSourceRef, - double const imageSize, - bool const dropIfUnset = false); - void SetRasterizedPixelHeight(winrt::ImageSource const& imageSource, double const& imageSize); void SetRasterizedPixelWidth(winrt::ImageSource const& imageSource, double const& imageSize); - static void ShouldFallback(winrt::IAdaptiveCardElement const& element, winrt::IAdaptiveElementRenderer const& elementRenderer, winrt::AdaptiveRenderArgs const& renderArgs,