in source/uwp/Renderer/lib/AdaptiveImageRenderer.cpp [49:272]
winrt::UIElement XamlBuilder::BuildImage(winrt::IAdaptiveCardElement const& adaptiveCardElement,
winrt::AdaptiveRenderContext const& renderContext,
winrt::AdaptiveRenderArgs const& renderArgs)
{
auto adaptiveImage = adaptiveCardElement.as<winrt::AdaptiveImage>();
auto hostConfig = renderContext.HostConfig();
auto url = adaptiveImage.Url();
auto imageUrl = GetUrlFromString(hostConfig, url);
if (imageUrl == nullptr)
{
renderContext.AddWarning(winrt::WarningStatusCode::AssetLoadFailed, L"Image not found");
return nullptr;
}
uint32_t pixelWidth = adaptiveImage.PixelWidth();
uint32_t pixelHeight = adaptiveImage.PixelHeight();
bool hasExplicitMeasurements = (pixelWidth || pixelHeight);
bool isAspectRatioNeeded = (pixelWidth && pixelHeight);
// Get the image's size and style
winrt::ImageSize size = winrt::ImageSize::None;
if (!hasExplicitMeasurements)
{
size = adaptiveImage.Size();
}
if (size == winrt::ImageSize::None && !hasExplicitMeasurements)
{
size = hostConfig.Image().ImageSize();
}
auto imageStyle = adaptiveImage.Style();
auto resourceResolvers = renderContext.ResourceResolvers();
auto backgroundColor = adaptiveImage.BackgroundColor();
auto isVisible = adaptiveCardElement.IsVisible();
winrt::FrameworkElement frameworkElement{nullptr};
if (imageStyle == winrt::ImageStyle::Person)
{
winrt::Ellipse ellipse{};
winrt::Ellipse backgroundEllipse{};
winrt::Stretch imageStretch = (isAspectRatioNeeded) ? winrt::Stretch::Fill : winrt::Stretch::UniformToFill;
auto parentElement = renderArgs.ParentElement();
auto ellipseAsShape = ellipse.as<winrt::Shape>();
auto backgrondEllipseAsShape = backgroundEllipse.as<winrt::Shape>();
SetImageOnUIElement(imageUrl, ellipse, resourceResolvers, (size == winrt::ImageSize::Auto), parentElement, ellipseAsShape, isVisible, imageStretch);
if (size == winrt::ImageSize::None || size == winrt::ImageSize::Stretch || size == winrt::ImageSize::Auto || hasExplicitMeasurements)
{
ellipse.Stretch(imageStretch);
backgroundEllipse.Stretch(imageStretch);
}
else
{
// Set the stretch for the ellipse - this is different to the stretch used for the image brush
// above. This will force the ellipse to conform to fit within the confines of its parent.
ellipse.Stretch(winrt::Stretch::UniformToFill);
backgroundEllipse.Stretch(winrt::Stretch::UniformToFill);
}
if (!backgroundColor.empty())
{
// Fill the background ellipse with solid color brush
auto color = GetColorFromString(HStringToUTF8(backgroundColor));
backgroundEllipse.Fill(winrt::SolidColorBrush{color});
// Create a grid to contain the background color ellipse and the image ellipse
winrt::Grid imageGrid{};
::AdaptiveCards::Rendering::Uwp::XamlHelpers::AppendXamlElementToPanel(backgroundEllipse, imageGrid);
::AdaptiveCards::Rendering::Uwp::XamlHelpers::AppendXamlElementToPanel(ellipse, imageGrid);
frameworkElement = imageGrid;
}
else
{
frameworkElement = ellipse;
}
}
else
{
winrt::Image xamlImage{};
if (!backgroundColor.empty())
{
// Create a surrounding border with solid color background to contain the image
winrt::Border border{};
auto color = GetColorFromString(HStringToUTF8(backgroundColor));
border.Background(winrt::SolidColorBrush{color});
border.Child(xamlImage);
frameworkElement = border;
}
else
{
frameworkElement = xamlImage;
}
if (isAspectRatioNeeded)
{
xamlImage.Stretch(winrt::Stretch::Fill);
}
auto parentElement = renderArgs.ParentElement();
SetImageOnUIElement(imageUrl, xamlImage, resourceResolvers, (size == winrt::ImageSize::Auto), parentElement, frameworkElement, isVisible);
}
auto sizeOptions = hostConfig.ImageSizes();
if (hasExplicitMeasurements)
{
if (pixelWidth)
{
if (imageStyle == winrt::ImageStyle::Person)
{
frameworkElement.Width(pixelWidth);
}
else
{
frameworkElement.MaxWidth(pixelWidth);
}
}
if (pixelHeight)
{
if (imageStyle == winrt::ImageStyle::Person)
{
frameworkElement.Height(pixelHeight);
}
else
{
frameworkElement.MaxHeight(pixelHeight);
}
}
}
else
{
if (size == winrt::ImageSize::Small || size == winrt::ImageSize::Medium || size == winrt::ImageSize::Large)
{
uint32_t imageSize;
switch (size)
{
case winrt::ImageSize::Small:
{
imageSize = sizeOptions.Small();
break;
}
case winrt::ImageSize::Medium:
{
imageSize = sizeOptions.Medium();
break;
}
case winrt::ImageSize::Large:
{
imageSize = sizeOptions.Large();
break;
}
default:
{
throw winrt::hresult_error(E_UNEXPECTED);
}
}
frameworkElement.MaxWidth(imageSize);
// We don't want to set a max height on the person ellipse as ellipses do not understand preserving
// aspect ratio when constrained on both axes.
if (imageStyle != winrt::ImageStyle::Person)
{
frameworkElement.MaxHeight(imageSize);
}
}
}
auto adaptiveHorizontalAlignmentReference = adaptiveImage.HorizontalAlignment();
// If the image doesn't have horizontal alignment set, check the render context for a parent value
if (adaptiveHorizontalAlignmentReference == nullptr)
{
adaptiveHorizontalAlignmentReference = renderContext.HorizontalContentAlignment();
}
auto adaptiveHorizontalAlignment = GetValueFromRef(adaptiveHorizontalAlignmentReference, winrt::HAlignment::Left);
switch (adaptiveHorizontalAlignment)
{
case winrt::HAlignment::Left:
frameworkElement.HorizontalAlignment(winrt::HorizontalAlignment::Left);
break;
case winrt::HAlignment::Right:
frameworkElement.HorizontalAlignment(winrt::HorizontalAlignment::Right);
break;
case winrt::HAlignment::Center:
frameworkElement.HorizontalAlignment(winrt::HorizontalAlignment::Center);
break;
}
frameworkElement.VerticalAlignment(winrt::VerticalAlignment::Top);
::AdaptiveCards::Rendering::Uwp::XamlHelpers::SetStyleFromResourceDictionary(renderContext, L"Adaptive.Image", frameworkElement);
auto selectAction = adaptiveImage.SelectAction();
winrt::hstring altText = adaptiveImage.AltText();
winrt::AutomationProperties::SetName(frameworkElement, altText);
return ActionHelpers::HandleSelectAction(adaptiveCardElement,
selectAction,
renderContext,
frameworkElement,
::AdaptiveCards::Rendering::Uwp::XamlHelpers::SupportsInteractivity(hostConfig),
true);
}