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.0 KiB
205 lines
6.0 KiB
#include "pch.h"
|
|
|
|
#include "JSValueXaml.h"
|
|
|
|
#include "GroupView.h"
|
|
#if __has_include("GroupView.g.cpp")
|
|
#include "GroupView.g.cpp"
|
|
#endif
|
|
|
|
#include "SVGLength.h"
|
|
#include "Utils.h"
|
|
|
|
using namespace winrt;
|
|
using namespace Microsoft::Graphics::Canvas;
|
|
using namespace Microsoft::ReactNative;
|
|
|
|
namespace winrt::RNSVG::implementation {
|
|
void GroupView::UpdateProperties(IJSValueReader const &reader, bool forceUpdate, bool invalidate) {
|
|
const JSValueObject &propertyMap{JSValue::ReadObjectFrom(reader)};
|
|
|
|
auto const &parent{SvgParent().try_as<RNSVG::GroupView>()};
|
|
auto fontProp{RNSVG::FontProp::Unknown};
|
|
|
|
for (auto const &pair : propertyMap) {
|
|
auto const &propertyName{pair.first};
|
|
auto const &propertyValue{pair.second};
|
|
|
|
if (propertyName == "font") {
|
|
auto const &font{propertyValue.AsObject()};
|
|
|
|
// When any of the font props update, you don't get individual updates.
|
|
// Instead, you get a new JSValueObject with all font props set on the element.
|
|
// If a prop was removed, you will not get a null type - it just won't
|
|
// be part of the new prop object, so we will reset all font values.
|
|
if (forceUpdate) {
|
|
m_fontPropMap[RNSVG::FontProp::FontSize] = false;
|
|
m_fontPropMap[RNSVG::FontProp::FontFamily] = false;
|
|
m_fontPropMap[RNSVG::FontProp::FontWeight] = false;
|
|
}
|
|
|
|
for (auto const &item : m_fontPropMap) {
|
|
if (!item.second) {
|
|
switch (item.first) {
|
|
case RNSVG::FontProp::FontSize:
|
|
m_fontSize = parent ? parent.FontSize() : 12.0f;
|
|
break;
|
|
case RNSVG::FontProp::FontFamily:
|
|
m_fontFamily = parent ? parent.FontFamily() : L"Segoe UI";
|
|
break;
|
|
case RNSVG::FontProp::FontWeight:
|
|
m_fontWeight = L"auto";
|
|
break;
|
|
default:
|
|
throw hresult_error();
|
|
}
|
|
}
|
|
}
|
|
|
|
for (auto const &prop : font) {
|
|
auto const &key{prop.first};
|
|
auto const &value{prop.second};
|
|
|
|
if (key == "fontSize") {
|
|
fontProp = RNSVG::FontProp::FontSize;
|
|
if (forceUpdate || !m_fontPropMap[fontProp]) {
|
|
m_fontSize = value.AsSingle();
|
|
}
|
|
} else if (key == "fontFamily") {
|
|
fontProp = RNSVG::FontProp::FontFamily;
|
|
if (forceUpdate || !m_fontPropMap[fontProp]) {
|
|
m_fontFamily = to_hstring(value.AsString());
|
|
}
|
|
} else if (key == "fontWeight") {
|
|
fontProp = RNSVG::FontProp::FontWeight;
|
|
auto fontWeight{to_hstring(value.AsString())};
|
|
if (forceUpdate) {
|
|
m_fontWeight = fontWeight;
|
|
} else if (!m_fontPropMap[fontProp]) {
|
|
m_fontWeight = L"auto";
|
|
}
|
|
}
|
|
|
|
// forceUpdate = true means the property is being set on an element
|
|
// instead of being inherited from the parent.
|
|
if (forceUpdate && (fontProp != RNSVG::FontProp::Unknown)) {
|
|
// If the propertyValue is null, that means we reset the property
|
|
m_fontPropMap[fontProp] = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
__super::UpdateProperties(reader, forceUpdate, false);
|
|
|
|
for (auto const &child : Children()) {
|
|
child.UpdateProperties(reader, false, false);
|
|
}
|
|
|
|
if (invalidate && SvgParent()) {
|
|
SvgRoot().InvalidateCanvas();
|
|
}
|
|
}
|
|
|
|
void GroupView::CreateGeometry(UI::Xaml::CanvasControl const &canvas) {
|
|
auto const &resourceCreator{canvas.try_as<ICanvasResourceCreator>()};
|
|
std::vector<Geometry::CanvasGeometry> geometries;
|
|
for (auto const &child : Children()) {
|
|
if (!child.Geometry()) {
|
|
child.CreateGeometry(canvas);
|
|
}
|
|
geometries.push_back(child.Geometry());
|
|
}
|
|
|
|
Geometry(Geometry::CanvasGeometry::CreateGroup(resourceCreator, geometries, FillRule()));
|
|
}
|
|
|
|
void GroupView::SaveDefinition() {
|
|
__super::SaveDefinition();
|
|
|
|
for (auto const &child : Children()) {
|
|
child.SaveDefinition();
|
|
}
|
|
}
|
|
|
|
void GroupView::MergeProperties(RNSVG::RenderableView const &other) {
|
|
__super::MergeProperties(other);
|
|
|
|
for (auto const &child : Children()) {
|
|
child.MergeProperties(*this);
|
|
}
|
|
}
|
|
|
|
void GroupView::Render(UI::Xaml::CanvasControl const &canvas, CanvasDrawingSession const &session) {
|
|
auto const &transform{session.Transform()};
|
|
|
|
if (m_propSetMap[RNSVG::BaseProp::Matrix]) {
|
|
session.Transform(transform * SvgTransform());
|
|
}
|
|
|
|
auto const &clipPathGeometry{ClipPathGeometry()};
|
|
|
|
if (auto const &opacityLayer{clipPathGeometry ? session.CreateLayer(m_opacity, clipPathGeometry) : session.CreateLayer(m_opacity)}) {
|
|
if (Children().Size() == 0) {
|
|
__super::Render(canvas, session);
|
|
} else {
|
|
RenderGroup(canvas, session);
|
|
}
|
|
|
|
opacityLayer.Close();
|
|
}
|
|
session.Transform(transform);
|
|
}
|
|
|
|
void GroupView::RenderGroup(UI::Xaml::CanvasControl const &canvas, CanvasDrawingSession const &session) {
|
|
for (auto const &child : Children()) {
|
|
child.Render(canvas, session);
|
|
}
|
|
}
|
|
|
|
void GroupView::CreateResources(ICanvasResourceCreator const &resourceCreator, UI::CanvasCreateResourcesEventArgs const &args) {
|
|
for (auto const &child : Children()) {
|
|
child.CreateResources(resourceCreator, args);
|
|
}
|
|
}
|
|
|
|
void GroupView::Unload() {
|
|
for (auto const &child : Children()) {
|
|
child.Unload();
|
|
}
|
|
|
|
m_reactContext = nullptr;
|
|
m_fontPropMap.clear();
|
|
m_children.Clear();
|
|
|
|
__super::Unload();
|
|
}
|
|
|
|
winrt::RNSVG::IRenderable GroupView::HitTest(Windows::Foundation::Point const &point) {
|
|
RNSVG::IRenderable renderable{nullptr};
|
|
if (IsResponsible()) {
|
|
for (auto const &child : Children()) {
|
|
if (auto const &hit{child.HitTest(point)}) {
|
|
renderable = hit;
|
|
}
|
|
}
|
|
if (renderable && !renderable.IsResponsible()) {
|
|
renderable = *this;
|
|
} else if (!renderable){
|
|
if (!Geometry()) {
|
|
if (auto const &svgRoot{SvgRoot()}) {
|
|
CreateGeometry(svgRoot.Canvas());
|
|
}
|
|
}
|
|
if (Geometry()) {
|
|
auto const &bounds{Geometry().ComputeBounds()};
|
|
if (Windows::UI::Xaml::RectHelper::Contains(bounds, point)) {
|
|
renderable = *this;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return renderable;
|
|
}
|
|
} // namespace winrt::RNSVG::implementation
|