merge
commit
5fbf46faf2
|
@ -157,6 +157,7 @@
|
||||||
<ClCompile Include="src\Renderer\VirtualTextureManager.cpp" />
|
<ClCompile Include="src\Renderer\VirtualTextureManager.cpp" />
|
||||||
<ClCompile Include="src\SvgParser.cpp" />
|
<ClCompile Include="src\SvgParser.cpp" />
|
||||||
<ClCompile Include="src\Editor\EditorWidgetComponent\StrokeStyleWidget.cpp" />
|
<ClCompile Include="src\Editor\EditorWidgetComponent\StrokeStyleWidget.cpp" />
|
||||||
|
<QtUic Include="EditorLayerInfoWidget.ui" />
|
||||||
<QtUic Include="EditorSettingWidget.ui" />
|
<QtUic Include="EditorSettingWidget.ui" />
|
||||||
<QtUic Include="EditorWidget.ui" />
|
<QtUic Include="EditorWidget.ui" />
|
||||||
<QtUic Include="EditorWidgetItem.ui" />
|
<QtUic Include="EditorWidgetItem.ui" />
|
||||||
|
|
|
@ -97,6 +97,9 @@
|
||||||
<QtUic Include="EditorSettingWidget.ui">
|
<QtUic Include="EditorSettingWidget.ui">
|
||||||
<Filter>Form Files</Filter>
|
<Filter>Form Files</Filter>
|
||||||
</QtUic>
|
</QtUic>
|
||||||
|
<QtUic Include="EditorLayerInfoWidget.ui">
|
||||||
|
<Filter>Form Files</Filter>
|
||||||
|
</QtUic>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="src\Editor\EditorWidgetItem.cpp">
|
<ClCompile Include="src\Editor\EditorWidgetItem.cpp">
|
||||||
|
@ -222,9 +225,6 @@
|
||||||
<ClCompile Include="src\NavigationBarWidget.cpp">
|
<ClCompile Include="src\NavigationBarWidget.cpp">
|
||||||
<Filter>Source Files\Editor</Filter>
|
<Filter>Source Files\Editor</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="src\Editor\EditorWidgetComponent\ColorPicker.cpp">
|
|
||||||
<Filter>Source Files\Editor</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\Editor\EditorWidget.cpp">
|
<ClCompile Include="src\Editor\EditorWidget.cpp">
|
||||||
<Filter>Source Files\Editor</Filter>
|
<Filter>Source Files\Editor</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -261,6 +261,9 @@
|
||||||
<ClCompile Include="src\Editor\DataManager\ProjectDataManager.cpp">
|
<ClCompile Include="src\Editor\DataManager\ProjectDataManager.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Editor\EditorWidgetComponent\ColorPicker.cpp">
|
||||||
|
<Filter>Source Files\Editor</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<QtMoc Include="src\Renderer\RendererGLWidget.h">
|
<QtMoc Include="src\Renderer\RendererGLWidget.h">
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>EditorLayerInfoWidget</class>
|
||||||
|
<widget class="QWidget" name="EditorLayerInfoWidget">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>333</width>
|
||||||
|
<height>321</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="widgetLayout">
|
||||||
|
<item row="0" column="0" colspan="2">
|
||||||
|
<widget class="QtMaterialTextField" name="name">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0" colspan="2">
|
||||||
|
<widget class="QtMaterialTextField" name="rotation">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QtMaterialTextField" name="offsetX">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QtMaterialTextField" name="offsetY">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QtMaterialTextField" name="scaleX">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QtMaterialTextField" name="scaleY">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QtMaterialCheckBox" name="flipX">
|
||||||
|
<property name="text">
|
||||||
|
<string>水平翻转</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1">
|
||||||
|
<widget class="QtMaterialCheckBox" name="flipY">
|
||||||
|
<property name="text">
|
||||||
|
<string>竖直翻转</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0" colspan="2">
|
||||||
|
<widget class="QListWidget" name="styleList"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>QtMaterialTextField</class>
|
||||||
|
<extends>QLineEdit</extends>
|
||||||
|
<header location="global">qtmaterialtextfield.h</header>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>QtMaterialCheckBox</class>
|
||||||
|
<extends>QCheckBox</extends>
|
||||||
|
<header location="global">qtmaterialcheckbox.h</header>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
|
@ -1132,12 +1132,6 @@ void main()
|
||||||
vec2 pTemp = path[pathIndex + 1];
|
vec2 pTemp = path[pathIndex + 1];
|
||||||
if (isinf(pTemp.x))
|
if (isinf(pTemp.x))
|
||||||
{
|
{
|
||||||
if(endType == 4)
|
|
||||||
{
|
|
||||||
//onVeryEnd = false;
|
|
||||||
tangentBeginNext = tangentFirstBegin;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
onVeryEnd = true;
|
onVeryEnd = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1150,8 +1144,17 @@ void main()
|
||||||
tangentBeginNext = normalize(pNext[0] - pNext[2]);
|
tangentBeginNext = normalize(pNext[0] - pNext[2]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(endType == 4)
|
||||||
|
{
|
||||||
|
//onVeryEnd = false;
|
||||||
|
tangentBeginNext = tangentFirstBegin;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
onVeryEnd = true;
|
onVeryEnd = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
float d = cubic_bezier_dis(localUV, p[0], p[1], p[2], p[3], true);
|
float d = cubic_bezier_dis(localUV, p[0], p[1], p[2], p[3], true);
|
||||||
if (d <= strokeWidth)
|
if (d <= strokeWidth)
|
||||||
|
@ -1199,7 +1202,7 @@ void main()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tangentEndLast = tangentEnd;
|
tangentEndLast = tangentEnd;
|
||||||
if(pathIndex == 0)
|
if(pathIndex == 4)
|
||||||
tangentFirstBegin = tangentBegin;
|
tangentFirstBegin = tangentBegin;
|
||||||
}
|
}
|
||||||
p3Last = p[3];
|
p3Last = p[3];
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <QInputDialog>
|
#include <QInputDialog>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
|
#include <QMessagebox>
|
||||||
|
|
||||||
ElementPoolWidget::ElementPoolWidget(QWidget* parent)
|
ElementPoolWidget::ElementPoolWidget(QWidget* parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
|
@ -125,7 +126,12 @@ void ElementPoolWidget::popMenu(const QPoint& pos)
|
||||||
{
|
{
|
||||||
menu->addAction(QString::fromLocal8Bit("添加元素(从svg导入)"), this, [this]() {
|
menu->addAction(QString::fromLocal8Bit("添加元素(从svg导入)"), this, [this]() {
|
||||||
QString filePath = QFileDialog::getOpenFileName(this, QString::fromLocal8Bit("打开文件"), "", "SVG Files (*.svg)");
|
QString filePath = QFileDialog::getOpenFileName(this, QString::fromLocal8Bit("打开文件"), "", "SVG Files (*.svg)");
|
||||||
|
filePath = filePath.trimmed();
|
||||||
QFileInfo fileInfo(filePath);
|
QFileInfo fileInfo(filePath);
|
||||||
|
if (!fileInfo.exists() || !fileInfo.isFile()) {
|
||||||
|
QMessageBox::warning(this, tr("Error"), QString::fromLocal8Bit("请选择Svg文件"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
QString fileName = fileInfo.fileName();
|
QString fileName = fileInfo.fileName();
|
||||||
qDebug() << fileName << " " << filePath;
|
qDebug() << fileName << " " << filePath;
|
||||||
this->elementManager->createSimpleElement(fileName, filePath);
|
this->elementManager->createSimpleElement(fileName, filePath);
|
||||||
|
|
|
@ -41,6 +41,7 @@ void PixelPath::addPath(const PixelPath& path)
|
||||||
QPainter painter(&pixmap);
|
QPainter painter(&pixmap);
|
||||||
painter.drawPixmap(0, 0, path.getPixmap());
|
painter.drawPixmap(0, 0, path.getPixmap());
|
||||||
this->painterPath.addPath(path.getPainterPath());
|
this->painterPath.addPath(path.getPainterPath());
|
||||||
|
this->originPath.addPath(path.originPath);
|
||||||
boundingRect = boundingRect.united(path.getBoundingRect());
|
boundingRect = boundingRect.united(path.getBoundingRect());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,6 +53,7 @@ void PixelPath::addPath(const QPainterPath& path)
|
||||||
painter.setPen(QPen(Qt::black,1));
|
painter.setPen(QPen(Qt::black,1));
|
||||||
painter.drawPath(path);
|
painter.drawPath(path);
|
||||||
this->painterPath.addPath(path);
|
this->painterPath.addPath(path);
|
||||||
|
this->originPath.addPath(path);
|
||||||
boundingRect = boundingRect.united(path.boundingRect());
|
boundingRect = boundingRect.united(path.boundingRect());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,6 +69,7 @@ void PixelPath::clear()
|
||||||
pixmap.fill(Qt::transparent);
|
pixmap.fill(Qt::transparent);
|
||||||
boundingRect = QRectF(0, 0, 0, 0);
|
boundingRect = QRectF(0, 0, 0, 0);
|
||||||
painterPath.clear();
|
painterPath.clear();
|
||||||
|
originPath.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
PixelPath PixelPath::trans(QTransform& mat)const
|
PixelPath PixelPath::trans(QTransform& mat)const
|
||||||
|
@ -78,6 +81,7 @@ PixelPath PixelPath::trans(QTransform& mat)const
|
||||||
painter.setTransform(mat);
|
painter.setTransform(mat);
|
||||||
painter.drawPixmap(0, 0, pixmap);
|
painter.drawPixmap(0, 0, pixmap);
|
||||||
result.painterPath.addPath(this->painterPath);
|
result.painterPath.addPath(this->painterPath);
|
||||||
|
result.originPath.addPath(this->painterPath);
|
||||||
result.painterPath = mat.map(result.painterPath);
|
result.painterPath = mat.map(result.painterPath);
|
||||||
result.boundingRect = result.painterPath.boundingRect();
|
result.boundingRect = result.painterPath.boundingRect();
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -10,7 +10,7 @@ class PixelPath
|
||||||
public:
|
public:
|
||||||
QRectF boundingRect;
|
QRectF boundingRect;
|
||||||
QPixmap pixmap;
|
QPixmap pixmap;
|
||||||
QPainterPath painterPath;
|
QPainterPath painterPath, originPath;
|
||||||
int w,h;
|
int w,h;
|
||||||
public:
|
public:
|
||||||
PixelPath(int w=16, int h= 16);
|
PixelPath(int w=16, int h= 16);
|
||||||
|
|
|
@ -51,7 +51,7 @@ void PreviewWindow::paintGL()
|
||||||
glClearColor(backgroundColor.redF(), backgroundColor.greenF(), backgroundColor.blueF(), backgroundColor.alphaF());
|
glClearColor(backgroundColor.redF(), backgroundColor.greenF(), backgroundColor.blueF(), backgroundColor.alphaF());
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
painter->begin(this);
|
painter->begin(this);
|
||||||
painter->setWindow(0, 0, logicalSize.width(), logicalSize.height());
|
painter->setWindow(0, 0, logicalSize.width() * devicePixelRatioF(), logicalSize.height() * devicePixelRatioF());
|
||||||
painter->setRenderHint(QPainter::Antialiasing);
|
painter->setRenderHint(QPainter::Antialiasing);
|
||||||
painter->setRenderHint(QPainter::HighQualityAntialiasing);
|
painter->setRenderHint(QPainter::HighQualityAntialiasing);
|
||||||
layerManager->paint(painter, this->size(), currentLayer);
|
layerManager->paint(painter, this->size(), currentLayer);
|
||||||
|
|
|
@ -79,34 +79,38 @@ FolderLayerWrapper* PaintingUtil::handleLayerWrapper(LayerWrapper* nowLayer, QTr
|
||||||
}
|
}
|
||||||
|
|
||||||
PixelPath pixelPath = nowLayer->getCache();
|
PixelPath pixelPath = nowLayer->getCache();
|
||||||
QPainterPath painterPath = pixelPath.getPainterPath();
|
QPainterPath painterPath = pixelPath.originPath;
|
||||||
QRectF bound = painterPath.boundingRect();
|
QRectF bound = painterPath.boundingRect();
|
||||||
//qDebug() << leafLayer<<"------" << painterPath;
|
//qDebug() << leafLayer<<"------" << painterPath;
|
||||||
// transform to -1£¬ 1
|
// transform to -1£¬ 1
|
||||||
QTransform trans;
|
QTransform trans;
|
||||||
double maxLen = std::max(bound.width(), bound.height());
|
double maxLen = std::max(bound.width(), bound.height()) * 1.00001;
|
||||||
qDebug() << maxLen << bound;
|
qDebug() << maxLen << bound;
|
||||||
trans.scale(1 / maxLen, 1 / maxLen);
|
trans.scale(1 / maxLen, 1 / maxLen);
|
||||||
trans.translate(-bound.center().x(), -bound.center().y());
|
trans.translate(-bound.center().x(), -bound.center().y());
|
||||||
|
|
||||||
painterPath = trans.map(painterPath);
|
painterPath = trans.map(painterPath);
|
||||||
shared_ptr<vector<vector<Renderer::Point> >> contour = std::make_shared<vector<vector<Renderer::Point> >>(PainterPathUtil::transformToLines(painterPath));
|
shared_ptr<vector<vector<Renderer::Point> >> contour = std::make_shared<vector<vector<Renderer::Point> >>(PainterPathUtil::transformToLines(painterPath));
|
||||||
QSize screenSize = QSize(1024, 1024);
|
QSize screenSize = QSize(1080, 1080);
|
||||||
|
|
||||||
ElementTransform elementTransform;
|
ElementTransform elementTransform;
|
||||||
transform = trans.inverted() * transform * QTransform::fromScale(2. / screenSize.width(), 2. / screenSize.height()) * QTransform::fromTranslate(-1, -1) * QTransform::fromScale(1, -1);
|
transform = trans.inverted() * transform * QTransform::fromScale(2. / screenSize.width(), 2. / screenSize.height()) * QTransform::fromTranslate(-1, -1) * QTransform::fromScale(1, -1);
|
||||||
|
|
||||||
auto baseStyles = leafLayer->styles.toBaseStyles();
|
auto baseStyles = leafLayer->styles.toBaseStyles();
|
||||||
Renderer::BaseElement element;
|
|
||||||
element.contour = contour;
|
|
||||||
for (auto& baseStyle : baseStyles) {
|
for (auto& baseStyle : baseStyles) {
|
||||||
double lineWidth = 0;
|
double lineWidth = 0;
|
||||||
|
|
||||||
|
std::shared_ptr<MaterialStyle> material;
|
||||||
|
|
||||||
if (baseStyle.material->type() == Renderer::MaterialStyleType::kStroke) {
|
if (baseStyle.material->type() == Renderer::MaterialStyleType::kStroke) {
|
||||||
auto material = std::static_pointer_cast<MaterialStyleStroke>(baseStyle.material);
|
std::shared_ptr copy = baseStyle.material->clone();
|
||||||
material->halfWidth /= maxLen;
|
std::static_pointer_cast<MaterialStyleStroke>(copy)->halfWidth /= maxLen;
|
||||||
lineWidth = material->halfWidth;
|
lineWidth = std::static_pointer_cast<MaterialStyleStroke>(copy)->halfWidth;
|
||||||
qDebug() << material->halfWidth;
|
material = copy;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
material = baseStyle.material;
|
||||||
QPainterPathStroker stroker;
|
QPainterPathStroker stroker;
|
||||||
stroker.setWidth(lineWidth * 2);
|
stroker.setWidth(lineWidth * 2);
|
||||||
stroker.setCapStyle(Qt::RoundCap);
|
stroker.setCapStyle(Qt::RoundCap);
|
||||||
|
@ -114,17 +118,14 @@ FolderLayerWrapper* PaintingUtil::handleLayerWrapper(LayerWrapper* nowLayer, QTr
|
||||||
QPainterPath strokePath = stroker.createStroke(painterPath);
|
QPainterPath strokePath = stroker.createStroke(painterPath);
|
||||||
auto rect = transform.map(strokePath).boundingRect();
|
auto rect = transform.map(strokePath).boundingRect();
|
||||||
elementTransform.bound = glm::vec4(rect.x(), rect.y(), rect.x() + rect.width(), rect.y() + rect.height());
|
elementTransform.bound = glm::vec4(rect.x(), rect.y(), rect.x() + rect.width(), rect.y() + rect.height());
|
||||||
qDebug() << elementTransform.bound.x << elementTransform.bound.y << elementTransform.bound.z << elementTransform.bound.z;
|
//qDebug() << elementTransform.bound.x << elementTransform.bound.y << elementTransform.bound.z << elementTransform.bound.z;
|
||||||
transform = transform.inverted();
|
transform = transform.inverted();
|
||||||
elementTransform.transform = glm::mat3x2(
|
elementTransform.transform = glm::mat3x2(
|
||||||
transform.m11(), transform.m12(), transform.m21(),
|
transform.m11(), transform.m12(), transform.m21(),
|
||||||
transform.m22(), transform.m31(), transform.m32()
|
transform.m22(), transform.m31(), transform.m32()
|
||||||
);
|
);
|
||||||
//qDebug() << transform;
|
|
||||||
elementTransform.zIndex = 0;
|
elementTransform.zIndex = 0;
|
||||||
|
painting.addElement(BaseElement{ contour, material }, elementTransform);
|
||||||
element.style = baseStyle.material;
|
|
||||||
painting.addElement(element, elementTransform);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "ElementRendererTest.h"
|
#include "ElementRendererTest.h"
|
||||||
#include "Renderer/Painting/ElementStyle.h"
|
#include "Renderer/Painting/ElementStyle.h"
|
||||||
#include "Renderer/Painting/MaterialStyleFill.h"
|
#include "Renderer/Painting/MaterialStyleFill.h"
|
||||||
|
#include "Editor/util/SvgFileLoader.h"
|
||||||
|
|
||||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||||
using namespace Renderer;
|
using namespace Renderer;
|
||||||
|
@ -203,6 +204,30 @@ namespace UnitTest
|
||||||
w.show();
|
w.show();
|
||||||
a.exec();
|
a.exec();
|
||||||
}
|
}
|
||||||
|
TEST_METHOD(TestBothSidesClosed)
|
||||||
|
{
|
||||||
|
QPainterPath closedPath;
|
||||||
|
SvgFileLoader().loadSvgFile("../../svg/4_L0.svg", closedPath);
|
||||||
|
closedPath = QTransform::fromScale(5, 5).map(closedPath);
|
||||||
|
QApplication a(argc, argv);
|
||||||
|
class StyleStrokeRadialGradient : public Renderer::ElementStyle
|
||||||
|
{
|
||||||
|
virtual std::vector<Renderer::BaseStyle> toBaseStyles() const override
|
||||||
|
{
|
||||||
|
std::map<float, Material> materialMap = {
|
||||||
|
{0.20, Material{QColor(255,255,255)}},
|
||||||
|
{0.60, Material{QColor(165,176,207)}},
|
||||||
|
{1.00, Material{QColor(58,64,151)}}
|
||||||
|
};
|
||||||
|
return { BaseStyle(std::make_shared<TransformStyle>(),
|
||||||
|
std::make_shared<MaterialStyleStroke>(20, StrokeType::kLeftSide, StrokeEndType::kClosed,
|
||||||
|
std::make_shared<StrokeRadialGradient>(materialMap, false))) };
|
||||||
|
}
|
||||||
|
} style;
|
||||||
|
TestGLWidget w(style, closedPath);
|
||||||
|
w.show();
|
||||||
|
a.exec();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_CLASS(ElementRendererStokeMaterialTest)
|
TEST_CLASS(ElementRendererStokeMaterialTest)
|
||||||
|
|
115
test.json
115
test.json
|
@ -3,7 +3,7 @@
|
||||||
"elements": [
|
"elements": [
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"include": "../svg/2.svg"
|
"include": "/svg/2.svg"
|
||||||
},
|
},
|
||||||
"name": "ababa",
|
"name": "ababa",
|
||||||
"type": "svg-file"
|
"type": "svg-file"
|
||||||
|
@ -17,10 +17,17 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"include": "../svg/0.svg"
|
"include": "/svg/0.svg"
|
||||||
},
|
},
|
||||||
"name": "ababa2",
|
"name": "ababa2",
|
||||||
"type": "svg-file"
|
"type": "svg-file"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"include": "/svg/4_L0.svg"
|
||||||
|
},
|
||||||
|
"name": "4_L0.svg",
|
||||||
|
"type": "svg-file"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"height": 1080,
|
"height": 1080,
|
||||||
|
@ -29,46 +36,22 @@
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"children": [
|
"children": [
|
||||||
{
|
|
||||||
"element": 0,
|
|
||||||
"is-folder": false,
|
|
||||||
"name": "Leaf1",
|
|
||||||
"styles": [
|
|
||||||
{
|
|
||||||
"enableEachSideIndependent": false,
|
|
||||||
"left": "AAAAQAEAIZwAf///qqr//w==",
|
|
||||||
"right": "AADgQAAACJw=",
|
|
||||||
"type": "stroke"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"transform": {
|
|
||||||
"offset": {
|
|
||||||
"x": 0,
|
|
||||||
"y": 0
|
|
||||||
},
|
|
||||||
"rotation": 0,
|
|
||||||
"scale": {
|
|
||||||
"x": 1,
|
|
||||||
"y": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"element": 0,
|
"element": 0,
|
||||||
"is-folder": false,
|
"is-folder": false,
|
||||||
"name": "Leaf2",
|
"name": "Leaf2",
|
||||||
"styles": [
|
"styles": [
|
||||||
{
|
{
|
||||||
"enableEachSideIndependent": false,
|
"enableEachSideIndependent": true,
|
||||||
"left": "AAAAQAEAIZwAf////1UA/w==",
|
"left": "AABAQAEAIZwAf///AFqe/w==",
|
||||||
"right": "AADgQAEACJwAf///AFqe/w==",
|
"right": "AABAQAAACJw=",
|
||||||
"type": "stroke"
|
"type": "stroke"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"transform": {
|
"transform": {
|
||||||
"offset": {
|
"offset": {
|
||||||
"x": 150,
|
"x": 501,
|
||||||
"y": 0
|
"y": -3
|
||||||
},
|
},
|
||||||
"rotation": 0,
|
"rotation": 0,
|
||||||
"scale": {
|
"scale": {
|
||||||
|
@ -83,8 +66,8 @@
|
||||||
"referenced-by": 1,
|
"referenced-by": 1,
|
||||||
"transform": {
|
"transform": {
|
||||||
"offset": {
|
"offset": {
|
||||||
"x": 50,
|
"x": 503,
|
||||||
"y": 50
|
"y": 36
|
||||||
},
|
},
|
||||||
"rotation": 0,
|
"rotation": 0,
|
||||||
"scale": {
|
"scale": {
|
||||||
|
@ -96,15 +79,73 @@
|
||||||
{
|
{
|
||||||
"element": 1,
|
"element": 1,
|
||||||
"is-folder": false,
|
"is-folder": false,
|
||||||
"name": "ReferencingGroupLayer",
|
"name": "子图层-2",
|
||||||
"styles": [
|
"styles": [
|
||||||
],
|
],
|
||||||
"transform": {
|
"transform": {
|
||||||
"offset": {
|
"offset": {
|
||||||
"x": 100,
|
"x": 1,
|
||||||
"y": 0
|
"y": 986
|
||||||
},
|
},
|
||||||
"rotation": 45,
|
"rotation": 0,
|
||||||
|
"scale": {
|
||||||
|
"x": 1,
|
||||||
|
"y": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"element": 1,
|
||||||
|
"is-folder": false,
|
||||||
|
"name": "子图层-3",
|
||||||
|
"styles": [
|
||||||
|
],
|
||||||
|
"transform": {
|
||||||
|
"offset": {
|
||||||
|
"x": -959,
|
||||||
|
"y": -5
|
||||||
|
},
|
||||||
|
"rotation": 0,
|
||||||
|
"scale": {
|
||||||
|
"x": 1,
|
||||||
|
"y": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"element": 1,
|
||||||
|
"is-folder": false,
|
||||||
|
"name": "子图层-4",
|
||||||
|
"styles": [
|
||||||
|
],
|
||||||
|
"transform": {
|
||||||
|
"offset": {
|
||||||
|
"x": -958,
|
||||||
|
"y": 980
|
||||||
|
},
|
||||||
|
"rotation": 0,
|
||||||
|
"scale": {
|
||||||
|
"x": 1,
|
||||||
|
"y": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"element": 3,
|
||||||
|
"is-folder": false,
|
||||||
|
"name": "子图层-5",
|
||||||
|
"styles": [
|
||||||
|
{
|
||||||
|
"material": "AH8A/wBanv8=",
|
||||||
|
"type": "fill"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"transform": {
|
||||||
|
"offset": {
|
||||||
|
"x": 473,
|
||||||
|
"y": 419
|
||||||
|
},
|
||||||
|
"rotation": 0,
|
||||||
"scale": {
|
"scale": {
|
||||||
"x": 1,
|
"x": 1,
|
||||||
"y": 1
|
"y": 1
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
# 图层删除
|
||||||
|
当删除一个节点时,该节点一定满足且只满足以下条件中的一条:
|
||||||
|
1. 是一个Leaf节点,引用了其他的Element;
|
||||||
|
2. 是一个Folder节点,没有GroupElement引用,没有引用任何其他节点(因为是Folder);
|
||||||
|
3. 是一个Folder节点,存在对应的GroupElement引用。
|
||||||
|
|
||||||
|
其中,对于第1条,由于Leaf节点被删除只影响其父亲Folder的属性,所以显然在删除Leaf节点时是绝对安全的。
|
||||||
|
|
||||||
|
对于第2条,对于其父亲Folder,其被删除只影响其父亲Folder的属性,所以不会影响其父亲;对于其孩子,有可能存在以下情况:
|
||||||
|
1. 孩子中不存在任何被引用的情况:删除安全;
|
||||||
|
2. 孩子中存在Folder节点被GroupElement引用,不安全,需要手动将情况转换为第1条后才可以删除。
|
||||||
|
|
||||||
|
对于第3条,必须首先手动解除其本身的引用,然后将转变为第2条。
|
||||||
|
|
||||||
|
# 图元删除
|
||||||
|
**显然**,无论是什么种类的图元,删除一个图元会影响到的元素只有引用它的图层,所以我们将SimpleElement与GroupElement合并成一种情况讨论。
|
||||||
|
|
||||||
|
当删除一个图元时,该图元一定满足且只满足以下条件中的一条:
|
||||||
|
1. 是一个GraphicElement,未被其他图层引用;
|
||||||
|
2. 是一个GraphicElement,被其他图层引用。
|
||||||
|
|
||||||
|
对于第1条,删除绝对安全。
|
||||||
|
|
||||||
|
对于第2条,将引用关系手动解除后,删除安全。
|
||||||
|
|
||||||
|
# 图层移动
|
||||||
|
## 条件分析
|
||||||
|
图层移动时,显然,被移动的节点只影响它本身及它的子图层,
|
||||||
|
移动的目标节点只影响它本身及它的父图层,那么:
|
||||||
|
|
||||||
|
(1) 被移动的图层一定满足且只满足以下条件中的一条:
|
||||||
|
1. 是一个Folder节点,无对应的GroupElement引用,子节点无引用GroupElement;
|
||||||
|
2. 是一个Folder节点,无对应的GroupElement引用,子节点存在引用GroupElement;
|
||||||
|
3. 是一个Folder节点,存在对应的GroupElement引用;
|
||||||
|
4. 是一个Leaf节点,引用了GroupElement;
|
||||||
|
5. 是一个Leaf节点,未引用GroupElement。
|
||||||
|
|
||||||
|
(2) 目标FolderLayer一定满足且只满足以下条件中的一条:
|
||||||
|
1. 自身无对应的GroupElement引用,无父节点有GroupElement引用;
|
||||||
|
2. 自身无对应的GroupElement引用,存在父节点有GroupElement引用;
|
||||||
|
3. 自身存在对应的GroupElement引用。
|
||||||
|
|
||||||
|
显然,以上条件的全组合可以覆盖所有情况。
|
||||||
|
由于:
|
||||||
|
- `(1) 1` 与 `(2) 中的任一条件`进行组合显然是绝对安全的;
|
||||||
|
- `(1) 3` 中自身提供的GroupElement并不会影响移动;
|
||||||
|
- `(1) 5` 与 `(2) 中的任一条件`进行组合显然是绝对安全的;
|
||||||
|
- `(1) 中的任一条件` 与 `(2) 1` 进行组合显然是绝对安全的。
|
||||||
|
|
||||||
|
所以接下来对于除去以上情况的所有组合情况进行讨论。
|
||||||
|
## 讨论证明
|
||||||
|
### `(1) 2` - `(2) 2`
|
||||||
|
当且仅当被移动的图层的子节点引用的GroupElement 与 目标图层父节点提供的GroupElement 相同时,移动不安全。
|
||||||
|
### `(1) 4` - `(2) 2`
|
||||||
|
当且仅当被移动的图层引用的GroupElement 与 目标图层父节点提供的 GroupElement 相同时,移动不安全。
|
||||||
|
### `(2) 3` 的特殊讨论
|
||||||
|
当且仅当自身提供的GroupElement 被 被移动图层或其子节点引用时,需要处理其自身情况,否则无视其自身提供的GroupElement,与 `(2) 1` 或 `(2) 2` 视为同情况处理。
|
||||||
|
|
||||||
|
## 结论
|
||||||
|
当且仅当被移动的图层或其子节点所引用的GroupElement 与 目标图层或其父节点所提供的GroupElement 相同时,移动不安全;其余情况均安全。
|
Loading…
Reference in New Issue