You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
205 lines
6.2 KiB
205 lines
6.2 KiB
#include "pch.h"
|
|
|
|
#include "SvgView.h"
|
|
#if __has_include("SvgView.g.cpp")
|
|
#include "SvgView.g.cpp"
|
|
#endif
|
|
|
|
#include <winrt/Windows.Graphics.Display.h>
|
|
|
|
#include "GroupView.h"
|
|
#include "Utils.h"
|
|
|
|
using namespace winrt;
|
|
using namespace Microsoft::Graphics::Canvas;
|
|
using namespace Microsoft::ReactNative;
|
|
using namespace Windows::Graphics::Display;
|
|
|
|
namespace winrt::RNSVG::implementation {
|
|
SvgView::SvgView(IReactContext const &context) : m_reactContext(context) {
|
|
m_scale = static_cast<float>(DisplayInformation::GetForCurrentView().ResolutionScale()) / 100;
|
|
|
|
m_canvasDrawRevoker = m_canvas.Draw(winrt::auto_revoke, {get_weak(), &SvgView::Canvas_Draw});
|
|
m_canvasCreateResourcesRevoker = m_canvas.CreateResources(winrt::auto_revoke, {get_weak(), &SvgView::Canvas_CreateResources});
|
|
m_canvasSizeChangedRevoker = m_canvas.SizeChanged(winrt::auto_revoke, {get_weak(), &SvgView::Canvas_SizeChanged});
|
|
m_panelUnloadedRevoker = Unloaded(winrt::auto_revoke, {get_weak(), &SvgView::Panel_Unloaded});
|
|
|
|
Children().Append(m_canvas);
|
|
}
|
|
|
|
void SvgView::SvgParent(Windows::UI::Xaml::FrameworkElement const &value) {
|
|
if (value) {
|
|
m_canvasDrawRevoker.revoke();
|
|
m_canvasCreateResourcesRevoker.revoke();
|
|
m_canvasSizeChangedRevoker.revoke();
|
|
m_panelUnloadedRevoker.revoke();
|
|
m_canvas.RemoveFromVisualTree();
|
|
m_canvas = nullptr;
|
|
m_parent = value;
|
|
}
|
|
}
|
|
|
|
void SvgView::UpdateProperties(IJSValueReader const &reader, bool forceUpdate, bool invalidate) {
|
|
// If forceUpdate is false, that means this is a nested Svg
|
|
// and we're inheriting props. Pass those along to the group.
|
|
if (!forceUpdate && m_group) {
|
|
m_group.UpdateProperties(reader, forceUpdate, invalidate);
|
|
} else {
|
|
auto const &propertyMap{JSValueObject::ReadFrom(reader)};
|
|
|
|
for (auto const &pair : propertyMap) {
|
|
auto const &propertyName{pair.first};
|
|
auto const &propertyValue{pair.second};
|
|
|
|
if (propertyName == "name") {
|
|
if (m_parent && m_group) {
|
|
m_group.SvgRoot().Templates().Remove(m_id);
|
|
}
|
|
m_id = to_hstring(Utils::JSValueAsString(propertyValue));
|
|
if (m_parent) {
|
|
SaveDefinition();
|
|
}
|
|
} else if (propertyName == "width") {
|
|
m_width = SVGLength::From(propertyValue);
|
|
} else if (propertyName == "height") {
|
|
m_height = SVGLength::From(propertyValue);
|
|
} else if (propertyName == "bbWidth") {
|
|
m_bbWidth = SVGLength::From(propertyValue);
|
|
Width(m_bbWidth.Value());
|
|
} else if (propertyName == "bbHeight") {
|
|
m_bbHeight = SVGLength::From(propertyValue);
|
|
Height(m_bbHeight.Value());
|
|
} else if (propertyName == "vbWidth") {
|
|
m_vbWidth = Utils::JSValueAsFloat(propertyValue);
|
|
} else if (propertyName == "vbHeight") {
|
|
m_vbHeight = Utils::JSValueAsFloat(propertyValue);
|
|
} else if (propertyName == "minX") {
|
|
m_minX = Utils::JSValueAsFloat(propertyValue);
|
|
} else if (propertyName == "minY") {
|
|
m_minY = Utils::JSValueAsFloat(propertyValue);
|
|
} else if (propertyName == "align") {
|
|
m_align = Utils::JSValueAsString(propertyValue);
|
|
} else if (propertyName == "meetOrSlice") {
|
|
m_meetOrSlice = Utils::GetMeetOrSlice(propertyValue);
|
|
} else if (propertyName == "color") {
|
|
m_currentColor = Utils::JSValueAsColor(propertyValue);
|
|
} else if (propertyName == "responsible") {
|
|
m_isResponsible = propertyValue.AsBoolean();
|
|
}
|
|
}
|
|
|
|
InvalidateCanvas();
|
|
}
|
|
}
|
|
|
|
void SvgView::SaveDefinition() {
|
|
if (m_id != L"" && m_group) {
|
|
m_group.SvgRoot().Templates().Insert(m_id, *this);
|
|
m_group.SaveDefinition();
|
|
}
|
|
}
|
|
|
|
void SvgView::MergeProperties(RNSVG::RenderableView const &other) {
|
|
if (m_group) {
|
|
m_group.MergeProperties(other);
|
|
}
|
|
}
|
|
|
|
Size SvgView::MeasureOverride(Size availableSize) {
|
|
for (auto const &child : Children()) {
|
|
child.Measure(availableSize);
|
|
}
|
|
return availableSize;
|
|
}
|
|
|
|
Size SvgView::ArrangeOverride(Size finalSize) {
|
|
for (auto const &child : Children()) {
|
|
child.Arrange({0, 0, finalSize.Width, finalSize.Height});
|
|
}
|
|
return finalSize;
|
|
}
|
|
|
|
void SvgView::Render(UI::Xaml::CanvasControl const & canvas, CanvasDrawingSession const & session) {
|
|
if (m_align != "") {
|
|
Rect vbRect{m_minX * m_scale, m_minY * m_scale, m_vbWidth * m_scale, m_vbHeight * m_scale};
|
|
float width{static_cast<float>(canvas.ActualWidth())};
|
|
float height{static_cast<float>(canvas.ActualHeight())};
|
|
bool nested{m_parent};
|
|
|
|
if (nested) {
|
|
width = Utils::GetAbsoluteLength(m_bbWidth, width);
|
|
height = Utils::GetAbsoluteLength(m_bbHeight, height);
|
|
}
|
|
|
|
Rect elRect{0, 0, width, height};
|
|
|
|
session.Transform(Utils::GetViewBoxTransform(vbRect, elRect, m_align, m_meetOrSlice));
|
|
}
|
|
|
|
if (m_group) {
|
|
m_group.SaveDefinition();
|
|
m_group.Render(canvas, session);
|
|
}
|
|
}
|
|
|
|
void SvgView::Canvas_Draw(UI::Xaml::CanvasControl const &sender, UI::Xaml::CanvasDrawEventArgs const &args) {
|
|
if (!m_hasRendered) {
|
|
m_hasRendered = true;
|
|
}
|
|
|
|
m_brushes.Clear();
|
|
m_templates.Clear();
|
|
|
|
Render(sender, args.DrawingSession());
|
|
}
|
|
|
|
void SvgView::CreateResources(ICanvasResourceCreator const &resourceCreator, UI::CanvasCreateResourcesEventArgs const &args) {
|
|
if (m_group) {
|
|
m_group.CreateResources(resourceCreator, args);
|
|
}
|
|
}
|
|
|
|
void SvgView::CreateGeometry(UI::Xaml::CanvasControl const& canvas) {
|
|
if (m_group) {
|
|
m_group.CreateGeometry(canvas);
|
|
}
|
|
}
|
|
|
|
void SvgView::Canvas_CreateResources(UI::Xaml::CanvasControl const &sender, UI::CanvasCreateResourcesEventArgs const &args) {
|
|
CreateResources(sender, args);
|
|
}
|
|
|
|
void SvgView::Canvas_SizeChanged(
|
|
IInspectable const & /*sender*/,
|
|
Windows::UI::Xaml::SizeChangedEventArgs const & /*args*/) {
|
|
// sender.Invalidate();
|
|
}
|
|
|
|
void SvgView::Panel_Unloaded(IInspectable const &sender, Windows::UI::Xaml::RoutedEventArgs const & /*args*/) {
|
|
if (auto const &svgView{sender.try_as<RNSVG::SvgView>()}) {
|
|
svgView.Unload();
|
|
}
|
|
}
|
|
|
|
void SvgView::Unload() {
|
|
m_reactContext = nullptr;
|
|
m_templates.Clear();
|
|
m_brushes.Clear();
|
|
|
|
if (m_group) {
|
|
m_group.Unload();
|
|
}
|
|
|
|
if (m_canvas) {
|
|
m_canvas.RemoveFromVisualTree();
|
|
m_canvas = nullptr;
|
|
}
|
|
}
|
|
|
|
void SvgView::InvalidateCanvas() {
|
|
if (m_hasRendered) {
|
|
m_canvas.Invalidate();
|
|
}
|
|
}
|
|
} // namespace winrt::RNSVG::implementation
|