+ return Control::GetWidthForHeight(height) + padding.start + padding.end;
+ }
+}
+
+void ImageView::OnRelayout(const Vector2& size, RelayoutContainer& container)
+{
+ Control::OnRelayout(size, container);
+ if(mVisual)
+ {
+ Property::Map transformMap = Property::Map();
+
+ Extents padding = Self().GetProperty<Extents>(Toolkit::Control::Property::PADDING);
+
+ bool zeroPadding = (padding == Extents());
+
+ Vector2 naturalSize;
+ mVisual.GetNaturalSize(naturalSize);
+
+ Dali::LayoutDirection::Type layoutDirection = static_cast<Dali::LayoutDirection::Type>(
+ Self().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
+ if(Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection)
+ {
+ std::swap(padding.start, padding.end);
+ }
+
+ // remove padding from the size to know how much is left for the visual
+ Vector2 finalSize = size - Vector2(padding.start + padding.end, padding.top + padding.bottom);
+ Vector2 finalOffset = Vector2(padding.start, padding.top);
+
+ ApplyFittingMode(finalSize, naturalSize, finalOffset, zeroPadding, transformMap);
+
+ mVisual.SetTransformAndSize(transformMap, size);
+
+ // mVisual is not updated util the resource is ready in the case of visual replacement.
+ // in this case, the Property Map must be initialized so that the previous value is not reused.
+ // after mVisual is updated, the correct value will be reset.
+ Toolkit::Visual::Base visual = DevelControl::GetVisual(*this, Toolkit::ImageView::Property::IMAGE);
+ if(visual && visual != mVisual)
+ {
+ visual.SetTransformAndSize(Property::Map(), size);
+ }
+ }
+}
+
+void ImageView::OnCreateTransitions(std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& sourceProperties,
+ std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& destinationProperties,
+ Dali::Toolkit::Control source,
+ Dali::Toolkit::Control destination)
+{
+ // Retrieves image properties to be transitioned.
+ Dali::Property::Map imageSourcePropertyMap, imageDestinationPropertyMap;
+ MakeVisualTransition(imageSourcePropertyMap, imageDestinationPropertyMap, source, destination, Toolkit::ImageView::Property::IMAGE);
+ if(imageSourcePropertyMap.Count() > 0)
+ {
+ sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::ImageView::Property::IMAGE, imageSourcePropertyMap));
+ destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::ImageView::Property::IMAGE, imageDestinationPropertyMap));
+ }
+}
+
+void ImageView::OnUpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties)
+{
+ Toolkit::Visual::Base visual = DevelControl::GetVisual(*this, Toolkit::ImageView::Property::IMAGE);
+ if(visual)
+ {
+ Dali::Toolkit::Control handle(GetOwner());
+
+ for(auto&& data : properties)
+ {
+ if(data.first == Toolkit::ImageView::Property::IMAGE)
+ {
+ DevelControl::DoAction(handle, Toolkit::ImageView::Property::IMAGE, DevelVisual::Action::UPDATE_PROPERTY, data.second);
+ break;
+ }
+ }
+ }
+}
+
+void ImageView::OnResourceReady(Toolkit::Control control)
+{
+ // Visual ready so update visual attached to this ImageView, following call to RelayoutRequest will use this visual.
+ mVisual = DevelControl::GetVisual(*this, Toolkit::ImageView::Property::IMAGE);
+ // Signal that a Relayout may be needed
+}
+
+void ImageView::SetTransformMapForFittingMode(Vector2 finalSize, Vector2 naturalSize, Vector2 finalOffset, Visual::FittingMode fittingMode, Property::Map& transformMap)
+{
+ switch(fittingMode)
+ {
+ case Visual::FittingMode::FIT_KEEP_ASPECT_RATIO:
+ {
+ auto availableVisualSize = finalSize;
+
+ // scale to fit the padded area
+ finalSize = naturalSize * std::min((naturalSize.width ? (availableVisualSize.width / naturalSize.width) : 0),
+ (naturalSize.height ? (availableVisualSize.height / naturalSize.height) : 0));
+
+ // calculate final offset within the padded area
+ finalOffset += (availableVisualSize - finalSize) * .5f;
+
+ // populate the transform map
+ transformMap.Add(Toolkit::Visual::Transform::Property::OFFSET, finalOffset)
+ .Add(Toolkit::Visual::Transform::Property::SIZE, finalSize);
+ break;
+ }
+ case Visual::FittingMode::OVER_FIT_KEEP_ASPECT_RATIO:
+ {
+ mImageViewPixelAreaSetByFittingMode = true;
+ auto availableVisualSize = finalSize;
+ finalSize = naturalSize * std::max((naturalSize.width ? (availableVisualSize.width / naturalSize.width) : 0),
+ (naturalSize.height ? (availableVisualSize.height / naturalSize.height) : 0));
+
+ auto originalOffset = finalOffset;
+ finalOffset += (availableVisualSize - finalSize) * .5f;
+
+ float x = abs((availableVisualSize.width - finalSize.width) / finalSize.width) * .5f;
+ float y = abs((availableVisualSize.height - finalSize.height) / finalSize.height) * .5f;
+ float widthRatio = 1.f - abs((availableVisualSize.width - finalSize.width) / finalSize.width);
+ float heightRatio = 1.f - abs((availableVisualSize.height - finalSize.height) / finalSize.height);
+ Vector4 pixelArea = Vector4(x, y, widthRatio, heightRatio);
+ Self().SetProperty(Toolkit::ImageView::Property::PIXEL_AREA, pixelArea);
+
+ // populate the transform map
+ transformMap.Add(Toolkit::Visual::Transform::Property::OFFSET, originalOffset)
+ .Add(Toolkit::Visual::Transform::Property::SIZE, availableVisualSize);
+ break;
+ }
+ case Visual::FittingMode::CENTER:
+ {
+ auto availableVisualSize = finalSize;
+ if(availableVisualSize.width > naturalSize.width && availableVisualSize.height > naturalSize.height)
+ {
+ finalSize = naturalSize;
+ }
+ else
+ {
+ finalSize = naturalSize * std::min((naturalSize.width ? (availableVisualSize.width / naturalSize.width) : 0),
+ (naturalSize.height ? (availableVisualSize.height / naturalSize.height) : 0));
+ }
+
+ finalOffset += (availableVisualSize - finalSize) * .5f;
+
+ // populate the transform map
+ transformMap.Add(Toolkit::Visual::Transform::Property::OFFSET, finalOffset)
+ .Add(Toolkit::Visual::Transform::Property::SIZE, finalSize);
+ break;
+ }
+ case Visual::FittingMode::FILL:
+ {
+ transformMap.Add(Toolkit::Visual::Transform::Property::OFFSET, finalOffset)
+ .Add(Toolkit::Visual::Transform::Property::SIZE, finalSize);
+ break;
+ }
+ case Visual::FittingMode::FIT_WIDTH:
+ case Visual::FittingMode::FIT_HEIGHT:
+ {
+ // This FittingMode already converted
+ break;
+ }