实现通过json文件构造Painting

dev-LayerStyle
wuyize 2023-03-20 00:26:50 +08:00
parent b3bbf6c1be
commit b6e79ee6de
9 changed files with 255 additions and 155 deletions

View File

@ -206,11 +206,11 @@ bool LayerStyleContainer::dropStyle(const QString& styleName)
float LayerStyleContainer::boundingBoxAffectValue() const { float LayerStyleContainer::boundingBoxAffectValue() const {
float maxLineWidth = 0; float maxLineWidth = 0;
const auto strokeStyle = styles.at(StrokeElementLayerStyle::displayName()); const auto strokeStyle = styles.find(StrokeElementLayerStyle::displayName());
if (strokeStyle != nullptr) if (strokeStyle != styles.end())
{ {
if (const auto strokeElementLayerStyle = if (const auto strokeElementLayerStyle =
std::dynamic_pointer_cast<StrokeElementLayerStyle>(strokeStyle); std::dynamic_pointer_cast<StrokeElementLayerStyle>(strokeStyle->second);
strokeElementLayerStyle != nullptr) strokeElementLayerStyle != nullptr)
{ {
const auto& leftStyleStroke = strokeElementLayerStyle->strokePair.first; const auto& leftStyleStroke = strokeElementLayerStyle->strokePair.first;

View File

@ -5,7 +5,7 @@
#include <queue> #include <queue>
using Renderer::Painting; using Renderer::Painting;
using Renderer::Element; using Renderer::BaseElement;
using Renderer::ElementTransform; using Renderer::ElementTransform;
using glm::bvec2; using glm::bvec2;
using std::max; using std::max;
@ -17,161 +17,124 @@ using std::queue;
const double PaintingUtil::pi = acos(-1); const double PaintingUtil::pi = acos(-1);
struct LayerNode { struct LayerNode {
LayerWrapper* nowLayer; LayerWrapper* nowLayer;
QTransform transfrom; QTransform transfrom;
bvec2 flip;
}; };
QJsonObject PaintingUtil::readJsonFile(QString jsonFilePath) { QJsonObject PaintingUtil::readJsonFile(QString jsonFilePath) {
QFile jsonFile(jsonFilePath); QFile jsonFile(jsonFilePath);
jsonFile.open(QFile::ReadOnly); qDebug() << jsonFilePath;
QByteArray fileContent = jsonFile.readAll().trimmed(); jsonFile.open(QFile::ReadOnly);
jsonFile.close(); QByteArray fileContent = jsonFile.readAll().trimmed();
QJsonParseError jError; jsonFile.close();
QJsonDocument jsonDoc(QJsonDocument::fromJson(fileContent, &jError)); QJsonParseError jError;
return jsonDoc.object(); QJsonDocument jsonDoc(QJsonDocument::fromJson(fileContent, &jError));
return jsonDoc.object();
} }
Painting PaintingUtil::transfromToPainting(QString jsonFilePath) { Painting PaintingUtil::transfromToPainting(QString jsonFilePath) {
Painting painting; Painting painting;
glm::bvec2 flip(0, 0); glm::bvec2 flip(0, 0);
QJsonObject jsonObj = readJsonFile(jsonFilePath); QJsonObject jsonObj = readJsonFile(jsonFilePath);
qDebug() << jsonObj; qDebug() << jsonObj;
shared_ptr<ElementManager> elementManager = make_shared<ElementManager>(jsonObj, Renderer::ElementRenderer::instance()); shared_ptr<ElementManager> elementManager = make_shared<ElementManager>(jsonObj, Renderer::ElementRenderer::instance());
shared_ptr<LayerManager> layerManager = make_shared<LayerManager>(jsonObj, elementManager.get()); shared_ptr<LayerManager> layerManager = make_shared<LayerManager>(jsonObj, elementManager.get());
//qDebug() << elementManager->toJson(); //qDebug() << elementManager->toJson();
//qDebug() << layerManager->toJson(); //qDebug() << layerManager->toJson();
//qDebug() << ((SimpleElement*)((LeafLayerWrapper*)((FolderLayerWrapper*)((FolderLayerWrapper*)layerManager->getRoot())->children[0].get())->children[0].get())->wrappedElement)->painterPath; //qDebug() << ((SimpleElement*)((LeafLayerWrapper*)((FolderLayerWrapper*)((FolderLayerWrapper*)layerManager->getRoot())->children[0].get())->children[0].get())->wrappedElement)->painterPath;
//qDebug() << ((LeafLayerWrapper*)((FolderLayerWrapper*)((FolderLayerWrapper*)layerManager->getRoot())->children[0].get())->children[0].get())->getCache().painterPath; //qDebug() << ((LeafLayerWrapper*)((FolderLayerWrapper*)((FolderLayerWrapper*)layerManager->getRoot())->children[0].get())->children[0].get())->getCache().painterPath;
queue<LayerNode> layerQueue; //qDebug() << elementManager->toJson();
LayerWrapper* root = layerManager->getRoot(); //qDebug() << layerManager->toJson();
root->getCache(); //qDebug() << ((SimpleElement*)((LeafLayerWrapper*)((FolderLayerWrapper*)((FolderLayerWrapper*)layerManager->getRoot())->children[0].get())->children[0].get())->wrappedElement)->painterPath;
layerQueue.push({ root, root->property.transform, flip }); //qDebug() << ((LeafLayerWrapper*)((FolderLayerWrapper*)((FolderLayerWrapper*)layerManager->getRoot())->children[0].get())->children[0].get())->getCache().painterPath;
while (!layerQueue.empty()) { queue<LayerNode> layerQueue;
auto layerNode = layerQueue.front(); LayerWrapper* root = layerManager->getRoot();
layerQueue.pop(); root->getCache();
FolderLayerWrapper* nowLayer = handleLayerWrapper(layerNode.nowLayer, layerNode.transfrom, layerNode.flip, painting); //double maxLineWidth = getMaxLineWidth(root);
if (nowLayer != nullptr) { layerQueue.push({ root, root->property.transform });
for (auto sonLayer : nowLayer->children) { while (!layerQueue.empty()) {
layerQueue.push({ sonLayer.get(), layerNode.transfrom, layerNode.flip}); auto layerNode = layerQueue.front();
} layerQueue.pop();
} FolderLayerWrapper* nowLayer = handleLayerWrapper(layerNode.nowLayer, layerNode.transfrom, painting);
} if (nowLayer != nullptr) {
for (auto sonLayer : nowLayer->children) {
return painting; layerQueue.push({ sonLayer.get(), layerNode.transfrom });
}
}
}
return painting;
} }
FolderLayerWrapper* PaintingUtil::handleLayerWrapper(LayerWrapper* nowLayer, QTransform& transform, bvec2& flip, Painting& painting) { FolderLayerWrapper* PaintingUtil::handleLayerWrapper(LayerWrapper* nowLayer, QTransform& transform, Painting& painting) {
LeafLayerWrapper* leafLayer = dynamic_cast<LeafLayerWrapper*>(nowLayer); LeafLayerWrapper* leafLayer = dynamic_cast<LeafLayerWrapper*>(nowLayer);
flip ^= bvec2(nowLayer->property.flipHorizontally, nowLayer->property.flipVertically);
transform = nowLayer->property.transform * transform; transform = nowLayer->property.transform * transform;
if (leafLayer != nullptr) { if (leafLayer != nullptr) {
GroupElement* wrapperElement = dynamic_cast<GroupElement*>(leafLayer->wrappedElement); GroupElement* wrapperElement = dynamic_cast<GroupElement*>(leafLayer->wrappedElement);
if (wrapperElement != nullptr) { if (wrapperElement != nullptr) {
transform = wrapperElement->sourceLayer->property.transform * transform; transform = wrapperElement->sourceLayer->property.transform * transform;
return wrapperElement->sourceLayer; return wrapperElement->sourceLayer;
} }
PixelPath pixelPath = nowLayer->getCache(); PixelPath pixelPath = nowLayer->getCache();
QPainterPath painterPath = pixelPath.getPainterPath(); QPainterPath painterPath = pixelPath.getPainterPath();
QRectF bound = painterPath.boundingRect(); QRectF bound = painterPath.boundingRect();
//qDebug() << leafLayer<<"------" << painterPath; //qDebug() << leafLayer<<"------" << painterPath;
//qDebug() << transform; //qDebug() << transform;
Element element; // transform to initial painterPath
ElementTransform elementTrans; // transfrom to -1£¬ 1
element.ratio = bound.width() / bound.height(); QTransform trans;
// transform to initial painterPath double maxLen = std::max(bound.width(), bound.height());
// transfrom to -1£¬ 1 qDebug() << maxLen << bound;
QTransform trans; trans.scale(1 / maxLen, 1 / maxLen);
trans.scale(1 / bound.width(), 1 / bound.height()); trans.translate(-bound.center().x(), -bound.center().y());
trans.translate(-bound.center().x(), -bound.center().y());
qDebug() << trans.map(painterPath);
element.contour = std::make_shared<vector<vector<Renderer::Point> >>(PainterPathUtil::transformToLines(trans.map(painterPath)));
QSize screenSize = QSize(1024, 1024);
element.style = std::make_shared<Renderer::ElementStyleStrokeDemo>(0.06);
painterPath = transform.map(painterPath);
qDebug() << painterPath;
bound = painterPath.boundingRect();
qDebug() << bound;
// TODO ¸ÄÓþØÕó painterPath = trans.map(painterPath);
shared_ptr<vector<vector<Renderer::Point> >> contour = std::make_shared<vector<vector<Renderer::Point> >>(PainterPathUtil::transformToLines(painterPath));
QSize screenSize = QSize(1024, 1024);
/* elementTrans.center = glm::vec2( ElementTransform elementTransform;
(2 * bound.center().x() - screenSize.width()) / screenSize.width(), transform = trans.inverted() * transform * QTransform::fromScale(2. / screenSize.width(), 2. / screenSize.height()) * QTransform::fromTranslate(-1, -1) * QTransform::fromScale(1, -1);
(2 * bound.center().y() - screenSize.height()) / screenSize.height()
); auto baseStyles = leafLayer->styles.toBaseStyles();
qDebug() << elementTrans.center.x << elementTrans.center.y; Renderer::BaseElement element;
decomposeTransform(transform, elementTrans.rotation, elementTrans.scale); element.contour = contour;
elementTrans.scale = glm::vec2( for (auto baseStyle : baseStyles) {
bound.width() * 2 / screenSize.width(), double lineWidth = 0;
bound.height() * 2 / screenSize.height() if (baseStyle.material->type() == Renderer::MaterialStyleType::kStroke) {
); auto material = dynamic_cast<MaterialStyleStroke*>(baseStyle.material.get());
elementTrans.flip = glm::bvec2( material->halfWidth = material->halfWidth / maxLen;
nowLayer->property.flipHorizontally, lineWidth = material->halfWidth;
nowLayer->property.flipVertically qDebug() << material->halfWidth;
); }
qDebug() << elementTrans.scale.x << elementTrans.scale.y; QRectF rect = painterPath.boundingRect();
painting.addElement(element, elementTrans);*/ rect.setX(-lineWidth + rect.x());
return nullptr; rect.setY(-lineWidth + rect.y());
} rect.setWidth(lineWidth * 2 + rect.width());
rect.setHeight(lineWidth * 2 + rect.height());
FolderLayerWrapper* folderLayer = dynamic_cast<FolderLayerWrapper*>(nowLayer); QPainterPath path;
return folderLayer; path.addRect(rect);
} rect = transform.map(path).boundingRect();
void PaintingUtil::decomposeTransform(QTransform trans, float& angle, glm::vec2& scale) { elementTransform.bound = glm::vec4(rect.x(), rect.y(), rect.x() + rect.width(), rect.y() + rect.height());
//qDebug() << trans; qDebug() << elementTransform.bound.x << elementTransform.bound.y << elementTransform.bound.z << elementTransform.bound.z;
trans.setMatrix( transform = transform.inverted();
trans.m11(), trans.m12(), trans.m13(), elementTransform.transform = glm::mat3x2(
trans.m21(), trans.m22(), trans.m23(), transform.m11(), transform.m12(), transform.m21(),
0, 0, 1); transform.m22(), transform.m31(), transform.m32()
//qDebug() << trans.dx() << trans.dy(); );
int count = 0; qDebug() << transform;
double norm = 0, n = 0; elementTransform.zIndex = 0;
QTransform R = trans, Rit, Rnext;
do { element.style = baseStyle.material;
++count; painting.addElement(element, elementTransform);
Rit = R.transposed().inverted(); }
Rnext.setMatrix(
(R.m11() + Rit.m11()) / 2, return nullptr;
(R.m12() + Rit.m12()) / 2, }
(R.m13() + Rit.m13()) / 2,
(R.m21() + Rit.m21()) / 2, FolderLayerWrapper* folderLayer = dynamic_cast<FolderLayerWrapper*>(nowLayer);
(R.m22() + Rit.m22()) / 2, return folderLayer;
(R.m23() + Rit.m23()) / 2,
(R.m31() + Rit.m31()) / 2,
(R.m32() + Rit.m32()) / 2,
(R.m33() + Rit.m33()) / 2
);
norm = 0;
norm = max(norm,
fabs(R.m11() - Rnext.m11())
+ fabs(R.m12() - Rnext.m12())
+ fabs(R.m13() - Rnext.m13()));
norm = max(norm,
fabs(R.m21() - Rnext.m21())
+ fabs(R.m22() - Rnext.m22())
+ fabs(R.m23() - Rnext.m23()));
norm = max(norm,
fabs(R.m31() - Rnext.m31())
+ fabs(R.m32() - Rnext.m32())
+ fabs(R.m33() - Rnext.m33()));
R = Rnext;
} while (count < 100 && norm > 0.0001);
double cosValue = max(-1.0, min(R.m11(), 1.0));
double sinValue = max(-1.0, min(R.m12(), 1.0));
angle = acos(cosValue) * 180 / pi;
if (sinValue < 0) {
angle = 360 - angle;
}
qDebug() << angle;
//R = R.inverted() * trans;
//scale = glm::vec2(R.m11(), R.m22());
//qDebug() << scale.x << scale.y;
return;
} }

View File

@ -7,10 +7,9 @@ class PaintingUtil
private: private:
static const double pi; static const double pi;
static QJsonObject readJsonFile(QString jsonFilePath); static QJsonObject readJsonFile(QString jsonFilePath);
static FolderLayerWrapper* handleLayerWrapper(LayerWrapper* nowLayer, QTransform& transform, glm::bvec2& flip, Renderer::Painting& painting); static FolderLayerWrapper* handleLayerWrapper(LayerWrapper* nowLayer, QTransform& transform, Renderer::Painting& painting);
public: //static double getMaxLineWidth(LayerWrapper* root);
public:
static Renderer::Painting transfromToPainting(QString jsonFilePath); static Renderer::Painting transfromToPainting(QString jsonFilePath);
static void decomposeTransform(QTransform trans, float& angle, glm::vec2& scale);
}; };

View File

@ -21,4 +21,9 @@ void ::FluentMenu::paintEvent(QPaintEvent* event)
painter.drawRoundedRect(QRectF(shadowRadius - i, shadowRadius - i, width() - (shadowRadius - i) * 2, height() - (shadowRadius - i) * 2), borderRadius + i, borderRadius + i); painter.drawRoundedRect(QRectF(shadowRadius - i, shadowRadius - i, width() - (shadowRadius - i) * 2, height() - (shadowRadius - i) * 2), borderRadius + i, borderRadius + i);
} }
QMenu::paintEvent(event); QMenu::paintEvent(event);
} }
QAction* FluentMenu::exec(const QPoint& pos, QAction* at)
{
return QMenu::exec(parentWidget()->mapToGlobal(parentWidget()->mapFromGlobal(pos) + QPoint(-shadowRadius, -shadowRadius)), at);
}

View File

@ -7,6 +7,7 @@ class FluentMenu : public QMenu
public: public:
explicit FluentMenu(QWidget* parent = nullptr); explicit FluentMenu(QWidget* parent = nullptr);
void paintEvent(QPaintEvent* event) override; void paintEvent(QPaintEvent* event) override;
QAction* exec(const QPoint& pos, QAction* at = nullptr);
int shadowRadius = 16; int shadowRadius = 16;
int borderRadius = 6; int borderRadius = 6;
int itemBorderRadius = 4; int itemBorderRadius = 4;

View File

@ -244,8 +244,9 @@ GLuint Renderer::Model::loadPainting(std::string path)
return iter->second; return iter->second;
Painting painting; Painting painting;
path = "../test.json";
if (auto file = QFileInfo(QString(path.c_str())); file.isFile()) if (auto file = QFileInfo(QString(path.c_str())); file.isFile())
painting = PaintingUtil::transfromToPainting(file.path()); painting = PaintingUtil::transfromToPainting(file.filePath());
else else
{ {
qDebug() << path.c_str() << "Not Found, Using Default Painting"; qDebug() << path.c_str() << "Not Found, Using Default Painting";

View File

@ -20,12 +20,12 @@ QVector4D BvhTree::Union(QVector4D a, QVector4D b) {
QVector4D BvhTree::merge(BvhPtr lp, BvhPtr rp) { QVector4D BvhTree::merge(BvhPtr lp, BvhPtr rp) {
QVector4D a = lp->bound, b = rp->bound; QVector4D a = lp->bound, b = rp->bound;
if (lp->isLeaf) { /*if (lp->isLeaf) {
a = BvhTreeData::boundWithRotation(a, lp->getRightSon()); a = BvhTreeData::boundWithRotation(a, lp->getRightSon());
} }
if (rp->isLeaf) { if (rp->isLeaf) {
b = BvhTreeData::boundWithRotation(b, rp->getRightSon()); b = BvhTreeData::boundWithRotation(b, rp->getRightSon());
} }*/
return Union(a, b); return Union(a, b);
} }

View File

@ -29,7 +29,7 @@ Renderer::RendererWidget::RendererWidget(QWidget* parent)
ui.openButton->setChecked(false); ui.openButton->setChecked(false);
}); });
QObject::connect(ui.openButton, &QPushButton::clicked, [&, menu]() { QObject::connect(ui.openButton, &QPushButton::clicked, [&, menu]() {
menu->exec(ui.openButton->mapToGlobal(QPoint(-menu->shadowRadius, ui.openButton->height() - menu->shadowRadius))); menu->exec(ui.openButton->mapToGlobal(QPoint(0, ui.openButton->height())));
}); });
QObject::connect(ui.horizontalSlider, &QSlider::valueChanged, QObject::connect(ui.horizontalSlider, &QSlider::valueChanged,

131
test.json Normal file
View File

@ -0,0 +1,131 @@
{
"background-color": "#ffffff",
"elements": [
{
"data": {
"include": "../svg/2.svg"
},
"name": "ababa",
"type": "svg-file"
},
{
"data": {
"reference-layer": "0.0"
},
"name": "ababa-group",
"type": "group"
},
{
"data": {
"include": "../svg/0.svg"
},
"name": "ababa2",
"type": "svg-file"
}
],
"height": 1080,
"project-name": "样例1",
"root-layer": {
"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,
"is-folder": false,
"name": "Leaf2",
"styles": [
{
"enableEachSideIndependent": false,
"left": "AAAAQAEAIZwAf////1UA/w==",
"right": "AADgQAAACJw=",
"type": "stroke"
}
],
"transform": {
"offset": {
"x": 150,
"y": 0
},
"rotation": 0,
"scale": {
"x": 1.5,
"y": 1.5
}
}
}
],
"is-folder": true,
"name": "GroupFolderExample",
"referenced-by": 1,
"transform": {
"offset": {
"x": 50,
"y": 50
},
"rotation": 0,
"scale": {
"x": 1,
"y": 1
}
}
},
{
"element": 1,
"is-folder": false,
"name": "ReferencingGroupLayer",
"styles": [
],
"transform": {
"offset": {
"x": 100,
"y": 0
},
"rotation": 45,
"scale": {
"x": 1,
"y": 1
}
}
}
],
"is-folder": true,
"name": "root",
"referenced-by": null,
"transform": {
"offset": {
"x": 0,
"y": 0
},
"rotation": 0,
"scale": {
"x": 1,
"y": 1
}
}
},
"width": 1080
}