From b0ac5ff1ce42e9da80a2afa58b972eabe471d907 Mon Sep 17 00:00:00 2001 From: Somya Sharma Date: Wed, 17 Apr 2024 16:56:59 -0700 Subject: [PATCH 1/5] Support svg xml data --- .../lib/AdaptiveImageRenderer.cpp | 27 ++++++++++++++----- source/uwp/SharedRenderer/lib/Util.cpp | 10 +++++++ source/uwp/SharedRenderer/lib/Util.h | 2 ++ 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/source/uwp/SharedRenderer/lib/AdaptiveImageRenderer.cpp b/source/uwp/SharedRenderer/lib/AdaptiveImageRenderer.cpp index b1576d387e..a4e92d6fc4 100644 --- a/source/uwp/SharedRenderer/lib/AdaptiveImageRenderer.cpp +++ b/source/uwp/SharedRenderer/lib/AdaptiveImageRenderer.cpp @@ -9,6 +9,7 @@ #include "AdaptiveBase64Util.h" #include "AdaptiveCardGetResourceStreamArgs.h" #include +#include "Util.h" #include "WholeItemsPanel.h" namespace winrt::AdaptiveCards::Rendering::Xaml_Rendering::implementation @@ -356,14 +357,23 @@ namespace AdaptiveCards::Rendering::Xaml_Rendering if (schemeName == L"data") { - // Decode base 64 string - winrt::hstring dataPath = imageUrl.Path(); - std::string data = AdaptiveBase64Util::ExtractDataFromUri(HStringToUTF8(dataPath)); - std::vector decodedData = AdaptiveBase64Util::Decode(data); - winrt::DataWriter dataWriter{winrt::InMemoryRandomAccessStream{}}; - dataWriter.WriteBytes(std::vector{decodedData.begin(), decodedData.end()}); + auto foundBase64 = HStringToUTF8(imageUrl.Path()).find("base64"); + if (!(foundBase64 == std::string::npos)) + { + // Decode base 64 string + winrt::hstring dataPath = imageUrl.Path(); + std::string data = AdaptiveBase64Util::ExtractDataFromUri(HStringToUTF8(dataPath)); + std::vector decodedData = AdaptiveBase64Util::Decode(data); + dataWriter.WriteBytes(std::vector{decodedData.begin(), decodedData.end()}); + } + else + { + // ... string + std::string data = ExtractSvgDataFromUri(imageUrl); + dataWriter.WriteBytes(std::vector{data.begin(), data.end()}); + } auto image = CreateImageSource(imgProperties.isImageSvg); @@ -428,6 +438,11 @@ namespace AdaptiveCards::Rendering::Xaml_Rendering strongThis->SetSvgUriSource(strongImageSource, imageUrl); } } + else if (status == winrt::AsyncStatus::Error) + { + // Handle error + winrt::hresult error = operation.ErrorCode(); + } } }); } diff --git a/source/uwp/SharedRenderer/lib/Util.cpp b/source/uwp/SharedRenderer/lib/Util.cpp index 9a012648e7..555b518b6e 100644 --- a/source/uwp/SharedRenderer/lib/Util.cpp +++ b/source/uwp/SharedRenderer/lib/Util.cpp @@ -643,3 +643,13 @@ namespace AdaptiveCards::Rendering::Xaml_Rendering registration->Set(L"Action.Execute", winrt::make()); } } + +std::string ExtractSvgDataFromUri(winrt::Windows::Foundation::Uri const& imageUrl) +{ + winrt::Windows::Foundation::Uri uriObj(imageUrl); + winrt::hstring unescapedUri = uriObj.UnescapeComponent(uriObj.AbsoluteUri()); + std::string dataUri = HStringToUTF8(unescapedUri); + size_t comaPosition = dataUri.find_first_of(","); + std::string data = dataUri.substr(comaPosition + 1); + return data; +} diff --git a/source/uwp/SharedRenderer/lib/Util.h b/source/uwp/SharedRenderer/lib/Util.h index 9f17f891f6..f013476f38 100644 --- a/source/uwp/SharedRenderer/lib/Util.h +++ b/source/uwp/SharedRenderer/lib/Util.h @@ -223,3 +223,5 @@ namespace AdaptiveCards::Rendering::Xaml_Rendering void RegisterDefaultActionRenderers(winrt::implementation::AdaptiveActionRendererRegistration* registration); } + +std::string ExtractSvgDataFromUri(winrt::Windows::Foundation::Uri const& imageUrl); From dc2cbc7a11825613753c111000b1cb970ba7c8c6 Mon Sep 17 00:00:00 2001 From: Somya Sharma Date: Wed, 17 Apr 2024 17:35:24 -0700 Subject: [PATCH 2/5] Clean up extraction --- source/uwp/SharedRenderer/lib/AdaptiveImageRenderer.cpp | 4 ++-- source/uwp/SharedRenderer/lib/Util.cpp | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/source/uwp/SharedRenderer/lib/AdaptiveImageRenderer.cpp b/source/uwp/SharedRenderer/lib/AdaptiveImageRenderer.cpp index a4e92d6fc4..9d3c224a96 100644 --- a/source/uwp/SharedRenderer/lib/AdaptiveImageRenderer.cpp +++ b/source/uwp/SharedRenderer/lib/AdaptiveImageRenderer.cpp @@ -360,7 +360,7 @@ namespace AdaptiveCards::Rendering::Xaml_Rendering winrt::DataWriter dataWriter{winrt::InMemoryRandomAccessStream{}}; auto foundBase64 = HStringToUTF8(imageUrl.Path()).find("base64"); - if (!(foundBase64 == std::string::npos)) + if (foundBase64 != std::string::npos) { // Decode base 64 string winrt::hstring dataPath = imageUrl.Path(); @@ -370,7 +370,7 @@ namespace AdaptiveCards::Rendering::Xaml_Rendering } else { - // ... string + // Extract ... string std::string data = ExtractSvgDataFromUri(imageUrl); dataWriter.WriteBytes(std::vector{data.begin(), data.end()}); } diff --git a/source/uwp/SharedRenderer/lib/Util.cpp b/source/uwp/SharedRenderer/lib/Util.cpp index 555b518b6e..f8af698534 100644 --- a/source/uwp/SharedRenderer/lib/Util.cpp +++ b/source/uwp/SharedRenderer/lib/Util.cpp @@ -649,7 +649,11 @@ std::string ExtractSvgDataFromUri(winrt::Windows::Foundation::Uri const& imageUr winrt::Windows::Foundation::Uri uriObj(imageUrl); winrt::hstring unescapedUri = uriObj.UnescapeComponent(uriObj.AbsoluteUri()); std::string dataUri = HStringToUTF8(unescapedUri); - size_t comaPosition = dataUri.find_first_of(","); - std::string data = dataUri.substr(comaPosition + 1); + size_t svgPosition = dataUri.find(" Date: Thu, 18 Apr 2024 14:58:15 -0700 Subject: [PATCH 3/5] Updated image svg sample --- samples/v1.5/Tests/Image.Svg.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/samples/v1.5/Tests/Image.Svg.json b/samples/v1.5/Tests/Image.Svg.json index 2b79c89ff4..8764012062 100644 --- a/samples/v1.5/Tests/Image.Svg.json +++ b/samples/v1.5/Tests/Image.Svg.json @@ -60,6 +60,11 @@ "backgroundColor": "#eeeeee", "style": "person", "url": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSJhdXRvIiAgaGVpZ2h0PSJhdXRvIiB2aWV3Qm94PSIwIDAgNzAwLjAwMDAxIDI5NC40MjI1OCI+IAo8c3R5bGU+CiAgCiAgLnRlc3QgewogICAgYW5pbWF0aW9uOiBmYWRlIDNzIGluZmluaXRlIGFsdGVybmF0ZTsgCiAgICAKICB9CiAgCiAgQGtleWZyYW1lcyBmYWRlIHsKICAgIAogICAgZnJvbSB7CiAgICAgIG9wYWNpdHk6IDAKICAgIH0KICAgIAogICAgdG8gewogICAgICAKICAgICAgb3BhY2l0eToxCiAgICB9CiAgICAKICB9CiAgCiAgPC9zdHlsZT4KICAKICA8cGF0aCBjbGFzcz0idGVzdCIgZD0iTTYwMi4yIDEyOC42Yy0xMS43IDIuNy00Mi42IDQuMi00Mi42IDQuMmwtMy44IDEyLjJzMTUuMy0xLjMgMjYuNS0uMmMwIDAgMy42LS4zIDQgNCAuMiA0LjQtLjMgOS0uMyA5cy0uMyAyLjctNCAzLjRjLTQuMy43LTMzLjMgMi0zMy4zIDJMNTQ0IDE3OXMtMS43IDMuNiAyLjIgMi42YzMuNi0xIDM0LTYuOCAzOC02IDQuMiAxIDkgNi44IDcuNiAxMi0xLjYgNi4zLTMyIDI1LjctNTAuNCAyNC40IDAgMC05LjcuNi0xNy44LTEyLjUtNy44LTEyLjUgMi43LTM2IDIuNy0zNnMtNC43LTExLTEuMi0xNWMwIDAgMi0xLjcgOC0yLjJsNy41LTE1LjRzLTguNS41LTEzLjUtNS43Yy00LjYtNi01LTguNi0xLjQtMTAuMiAzLjgtMiAzOS04LjMgNjMuMi03LjUgMCAwIDguNS0xIDE2IDEzLjcgMCAwIDMuNCA2LTIuNiA3LjRNNTExIDE4Ny44Yy0zIDcuMy0xMS4zIDE1LTIxLjMgMTAuMy0xMC4yLTQuOC0yNi4zLTM3LjYtMjYuMy0zNy42cy02LTEyLjItNy4yLTExLjhjMCAwLTEuMy0yLjQtMiAxMS0xIDEzLjMuMiAzOS4yLTUuMyA0My4zLTUgNC0xMSAyLjMtMTQuNC0yLjQtMi44LTQuNy00LTE2LTIuNC0zNS43IDEuOC0xOS43IDYuMy00MC43IDEyLTQ3LjIgNi02LjYgMTAuOC0xLjggMTIuNiAwIDAgMCA3LjcgNyAyMC43IDI3LjdsMi4yIDMuOHMxMS44IDE5LjcgMTMgMTkuNmMwIDAgMSAxIDEuOC4yIDEuMi0uMy44LTYuNy44LTYuN1M0OTMgMTQxIDQ4MiAxMDVjMCAwLTEuNi00LjYtLjUtOSAxLTQgNS4zLTIgNS4zLTJzMTYuNiA4IDI0LjcgMzVjOCAyNyAyLjYgNTEuNS0uNCA1OC44TTQyOS42IDExOC41Yy0xLjYgMi44LTIuMyA2LjctOS4yIDcuOCAwIDAtNjcgNC43LTcwLjMgOS40IDAgMC0yLjIgMi44IDEuNCAzLjUgMy44LjggMTkgMi44IDI2LjIgMy4yIDcuOCAwIDM0IC4yIDQzLjYgMTIgMCAwIDUuNSA1LjYgNS4zIDE4LjMtLjIgMTMtMi41IDE3LjYtNy42IDIyLjMtNS4zIDQuNC01MC43IDI0LjgtODAtNi40IDAgMC0xMy40LTE1IDQuNy0yNi40IDAgMCAxMy04IDQ2LjMgMS4zIDAgMCAxMCAzLjYgOS42IDcuMy0uNiA0LTguMyA4LTE5LjUgNy44LTEwLjgtLjMtMTguOC01LjUtMTcuMi00LjYgMS41LjUtMTEuNy02LjQtMTUuOC0xLjctNCA0LjQtMyA3IDEgOS43IDEwIDUuOCA0OS4zIDMuNyA2MS05LjQgMCAwIDQuNy01LjMtMi40LTkuNi03LTQtMjcuNC02LjUtMzUuMy02LjgtNy41LS40LTM1LjYgMC0zOS44LTcuMyAwIDAtNC01LjIuNC0xOS40IDQuNi0xNSAzNy4zLTIwLjggNTEuNS0yMiAwIDAgMzktMS42IDQ2LjMgNi40IDAgMCAxIDEuOC0uMiA0LjVNMzE5IDIwNi40Yy00LjcgMy41LTE0LjcgMi0xNy42LTItMi44LTMuNS0zLjgtMTcuMy0zLjMtMzkgLjctMjIuMiAxLTQ5LjQgNi01My44IDUtNC4zIDgtLjUgMTAgMi40IDIgMyA0LjYgNi4zIDUgMTMuMi42IDcgMi4zIDQzIDIuMyA0M3MyLjIgMzIuOC0yLjMgMzYuMk0zMjkgODkuNGMtMTMuOCA0LjctMjMuMiAzLjItMzEuMi0uMy0zLjUgNi4zLTUuNiA4LjItOC4yIDguNi00IC40LTcuNS02LTgtOC0uOC0xLjUtMi43LTQuMi0uNC0xMC4zLTcuOC03LTguNC0xNi40LTctMjIuNyAxLjgtNy40IDE1LTM1LjIgNTUtMzguNSAwIDAgMTkuNi0xLjQgMjMgOWguNnMxOSAwIDE4LjYgMTdjMCAxNy0yMSAzOC4yLTQyLjQgNDUuNW0xNy44LTQ4LjdjLTEyLjYgMi0zMiAxOC44LTQxLjMgMzIuNyAxNC4zIDIuNiAzOS4zIDEuNiA1MC41LTIxIDAgMCA1LjMtMTQuMi05LjItMTEuN20tNTUuMyAxMWMtNCA2LjUtNC4yIDEwLjQtMi4zIDEzIDQuNy03IDEzLTE4IDI1LjUtMjYuNi05LjYgMS0xNy43IDUtMjMuMiAxMy42TTYzMi4yIDIwNS43Yy05LjIgMjIuNi0xNyA0NS41LTIxLjUgNzkuOCAwIDAtMSA2LjctNi41IDQuNS01LjUtMi0xNC41LTExLTE2LjUtMjMuNy0yLTE2LjYgNS40LTQ0LjYgMjAuNS03Ni44LTQuNC03LTcuNS0xNy40LTUtMzIgMCAwIDQtMjcgMzEtNTEuNCAwIDAgMy4yLTIuNyA1LTEuOCAyLjIgMSAxLjMgOS42LS41IDE0LTEuNiA0LjItMTMuNiAyNS0xMy42IDI1cy03LjUgMTQuMi01LjQgMjUuM2MxNC4yLTIxLjggNDYuNS02NiA2Ni41LTUyIDEyLjcgOSAxMi43IDM4IDMuMiA1NC44LTcuNSAxMy4zLTI4LjcgNDAuOC01NyAzNC40bTQxLjYtNjhjLTcuNCA4LTIwLjYgMjMuMi0zMSA0My44IDExLTEuMiAyMS43LTcuMyAyNS0xMC40IDUuMy00LjcgMTcuNS0xNy40IDE1LjYtMzQuMiAwIDAtMS4yLTguOC05LjYuOE0yMjYgMjE3LjVjLTM1LjQgMTAuOC02OC44IDUuOC04NyAxLS41IDcuNC0xLjMgMTAuNS0yLjUgMTEuNy0xLjQgMS42LTEzIDguMi0xOS40LTEuMi0yLjgtNC41LTQuMi0xMi42LTUtMjAtNDEtMTguNi02MC00Ni02MC42LTQ3LTEtMS0xMC4zLTEwLjctMS0yMi43IDguNy0xMC44IDM3LjUtMjEuNyA2My4zLTI2IDEtMjIgMy40LTM5IDYuNS00Ni41IDMuNy05IDguNC0xIDEyLjYgNSAzLjQgNC41IDUuNSAyMy44IDUuNyAzOS4yIDE2LjgtLjggMjcgLjQgNDUuNyA0IDI0LjYgNC4yIDQxIDE2LjggMzkuNyAzMS0xLjIgMTQtMTQgMTkuOC0xOSAyMC4yLTUgLjQtMTMtMy4zLTEzLTMuMy01LjYtMi42LS41LTUgNi03LjggNy4yLTMuNSA1LjYtNyA1LjYtNy0yLjYtOC0zNC41LTEzLjMtNjYuMi0xMy4zIDAgMTcuNS43IDQ2LjUgMS4yIDYzLjQgMjIuMiA0LjIgMzguOCAzLjMgMzguOCAzLjNzODEtMi4zIDgzLjMtNTRjMi41LTUxLjgtODEtMTAxLjQtMTQyLjUtMTE3QzU2LjggMTQuNCAyMiAyNS44IDE5IDI3LjNjLTMuMyAxLjYtLjMgMi4yLS4zIDIuMlMyMiAzMCAyOCAzMmM2IDIgMS4yIDUgMS4yIDVDMTguNyA0MC42IDcgMzguNSA0LjcgMzMuN2MtMi4zLTQuNyAxLjUtOSA2LTE1LjMgNC4yLTYuNSA5LTYuMyA5LTYuMyA3Ni0yNi41IDE2OC44IDIxIDE2OC44IDIxIDg2LjggNDMuOCAxMDEuNiA5NS4zIDEwMCAxMTUuMy0xLjQgMTkuNy05IDUzLTYyLjUgNjkuMk01OSAxNDZjLTguNiA0LTIuNiAxMC40LTIuNiAxMC40IDE2LjIgMTcuMyAzNiAyOC4yIDU1IDM1IDIuMi0zMCAyLTQwLjcgMi01NS44Qzg0IDEzNy42IDY3IDE0Mi40IDU5IDE0NiIvPiA8L3N2Zz4=" + }, + { + "type": "Image", + "url": "data:image/svg+xml;utf8, ", + "size": "medium" } ] } From 32a2b5bebf4aa32ad9f7672d3ac055789db6b560 Mon Sep 17 00:00:00 2001 From: Somya Sharma Date: Fri, 19 Apr 2024 11:48:57 -0700 Subject: [PATCH 4/5] Additional check for svg --- source/uwp/SharedRenderer/lib/AdaptiveImageRenderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/uwp/SharedRenderer/lib/AdaptiveImageRenderer.cpp b/source/uwp/SharedRenderer/lib/AdaptiveImageRenderer.cpp index 9d3c224a96..5bbc9706f5 100644 --- a/source/uwp/SharedRenderer/lib/AdaptiveImageRenderer.cpp +++ b/source/uwp/SharedRenderer/lib/AdaptiveImageRenderer.cpp @@ -368,7 +368,7 @@ namespace AdaptiveCards::Rendering::Xaml_Rendering std::vector decodedData = AdaptiveBase64Util::Decode(data); dataWriter.WriteBytes(std::vector{decodedData.begin(), decodedData.end()}); } - else + else if (imgProperties.isImageSvg) { // Extract ... string std::string data = ExtractSvgDataFromUri(imageUrl); From 41f226e9c159b1aa71d4c735ea1c762ac9dff40b Mon Sep 17 00:00:00 2001 From: Somya Sharma Date: Mon, 22 Apr 2024 17:43:09 -0700 Subject: [PATCH 5/5] PR feedback --- source/uwp/SharedRenderer/lib/AdaptiveImageRenderer.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/source/uwp/SharedRenderer/lib/AdaptiveImageRenderer.cpp b/source/uwp/SharedRenderer/lib/AdaptiveImageRenderer.cpp index 5bbc9706f5..d7277deb6c 100644 --- a/source/uwp/SharedRenderer/lib/AdaptiveImageRenderer.cpp +++ b/source/uwp/SharedRenderer/lib/AdaptiveImageRenderer.cpp @@ -358,13 +358,12 @@ namespace AdaptiveCards::Rendering::Xaml_Rendering if (schemeName == L"data") { winrt::DataWriter dataWriter{winrt::InMemoryRandomAccessStream{}}; - - auto foundBase64 = HStringToUTF8(imageUrl.Path()).find("base64"); + auto imagePath = HStringToUTF8(imageUrl.Path()); + auto foundBase64 = imagePath.find("base64"); if (foundBase64 != std::string::npos) { // Decode base 64 string - winrt::hstring dataPath = imageUrl.Path(); - std::string data = AdaptiveBase64Util::ExtractDataFromUri(HStringToUTF8(dataPath)); + std::string data = AdaptiveBase64Util::ExtractDataFromUri(imagePath); std::vector decodedData = AdaptiveBase64Util::Decode(data); dataWriter.WriteBytes(std::vector{decodedData.begin(), decodedData.end()}); }