Merge branch 'main' into dev-LayerStyle

dev-LayerStyle
ArgonarioD 2023-03-20 18:54:02 +08:00
commit 1ef08dc49e
12 changed files with 125 additions and 44 deletions

View File

@ -1093,6 +1093,7 @@ void main()
bool onVeryBegin = false; bool onVeryBegin = false;
bool onVeryEnd = false; bool onVeryEnd = false;
vec2 tangentEndLast; vec2 tangentEndLast;
vec2 tangentFirstBegin;
uint lastHitIndex = 0; uint lastHitIndex = 0;
bool lastHitElement = false; bool lastHitElement = false;
hitElement = false; hitElement = false;
@ -1108,7 +1109,19 @@ void main()
pBegin = path[++pathIndex]; pBegin = path[++pathIndex];
p3Last = pBegin; p3Last = pBegin;
p2Last = pBegin; p2Last = pBegin;
onVeryBegin = true; if(endType == 4)
{
//onVeryBegin = false;
vec2 lastP1 = path[pathSize-3];
vec2 lastP2 = path[pathSize-2];
vec2 lastP3 = path[pathSize-1];
if (lastP3 != lastP2)
tangentEndLast = normalize(lastP3 - lastP2);
else
tangentEndLast = normalize(lastP3 - lastP1);
}
else
onVeryBegin = true;
continue; continue;
} }
mat4x2 p = mat4x2(p3Last, pTemp, path[++pathIndex], path[++pathIndex]); mat4x2 p = mat4x2(p3Last, pTemp, path[++pathIndex], path[++pathIndex]);
@ -1119,7 +1132,13 @@ void main()
vec2 pTemp = path[pathIndex + 1]; vec2 pTemp = path[pathIndex + 1];
if (isinf(pTemp.x)) if (isinf(pTemp.x))
{ {
onVeryEnd = true; if(endType == 4)
{
//onVeryEnd = false;
tangentBeginNext = tangentFirstBegin;
}
else
onVeryEnd = true;
} }
else else
{ {
@ -1180,6 +1199,8 @@ void main()
} }
} }
tangentEndLast = tangentEnd; tangentEndLast = tangentEnd;
if(pathIndex == 0)
tangentFirstBegin = tangentBegin;
} }
p3Last = p[3]; p3Last = p[3];
p2Last = p[2]; p2Last = p[2];

View File

@ -13,8 +13,21 @@ LayerWrapper *LayerManager::getRoot() const
} }
void LayerManager::paint(QPainter *painter, QSize size,LayerWrapper* selecetedLayer) const void LayerManager::paint(QPainter *painter, QSize size,LayerWrapper* selecetedLayer) const
{ {
painter->save();
root->getCache(); root->getCache();
root->paint(painter); root->paint(painter);
painter->restore();
painter->save();
// painter->setBrush(QBrush(Qt::white));
//painter->setCompositionMode(QPainter::CompositionMode_Difference);
if (selecetedLayer != nullptr)
{
painter->setPen(QPen(Qt::gray, 2, Qt::DashLine));
selecetedLayer->paintVisualBounding(painter);
//painter->setPen(QPen(Qt::gray, 2, Qt::DashDotLine));
//selecetedLayer->paintVisualBounding(painter);
}
painter->restore();
} }
bool LayerManager::singleSelectedCheck() const bool LayerManager::singleSelectedCheck() const
{ {

View File

@ -284,7 +284,14 @@ int FolderLayerWrapper::getReferencedBy()const
void LayerWrapper::paint(QPainter* painter, QTransform transform, bool force) void LayerWrapper::paint(QPainter* painter, QTransform transform, bool force)
{ {
// if (this->selected)
// {
// painter->save();
//painter->setPen(QPen(Qt::red, 2));
//painter->setTransform(transform);
//painter->drawRect(this->cache.getBoundingRect());
//painter->restore();
// }
} }
void FolderLayerWrapper::paint(QPainter* painter, QTransform transform, bool force) void FolderLayerWrapper::paint(QPainter* painter, QTransform transform, bool force)
@ -429,3 +436,20 @@ bool LayerWrapper::canApplyStyles() const
{ {
return typeid(*this) == typeid(LeafLayerWrapper) && !referencingGroupElement(); return typeid(*this) == typeid(LeafLayerWrapper) && !referencingGroupElement();
} }
void LayerWrapper::paintVisualBounding(QPainter* painter) const
{
if (hidden)
return;
QTransform transform;
auto layer = this->parent;
while (layer != nullptr)
{
transform = transform * layer->property.transform;
layer = layer->parent;
}
painter->save();
painter->setTransform(transform);
painter->drawRect(cache.getBoundingRect());
painter->restore();
}

View File

@ -75,6 +75,7 @@ class LayerWrapper
virtual size_t referencedCount(bool excludeSelf = false) const; virtual size_t referencedCount(bool excludeSelf = false) const;
virtual bool deleteable(bool excludeSubTree = false) const; virtual bool deleteable(bool excludeSubTree = false) const;
virtual bool referencingGroupElement() const; virtual bool referencingGroupElement() const;
virtual void paintVisualBounding(QPainter* painter) const;
bool canApplyStyles() const; bool canApplyStyles() const;
}; };

View File

@ -78,7 +78,8 @@ 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.boundingRect = mat.mapRect(boundingRect); result.painterPath = mat.map(result.painterPath);
result.boundingRect = result.painterPath.boundingRect();
return result; return result;
} }

View File

@ -1,4 +1,5 @@
#include "PreviewWindow.h" #include "PreviewWindow.h"
#include <QApplication>
PreviewWindow::PreviewWindow(QWidget *parent) : QOpenGLWidget(parent) PreviewWindow::PreviewWindow(QWidget *parent) : QOpenGLWidget(parent)
{ {
@ -84,7 +85,17 @@ void PreviewWindow::mouseMoveEvent(QMouseEvent* event)
int dx = event->x() - m_lastPos.x(); int dx = event->x() - m_lastPos.x();
int dy = event->y() - m_lastPos.y(); int dy = event->y() - m_lastPos.y();
if (currentLayer != nullptr) { if (currentLayer != nullptr) {
if (event->buttons() & Qt::LeftButton) { if (QApplication::keyboardModifiers() == Qt::ControlModifier && (event->buttons() & Qt::LeftButton))
{
currentLayer->property.scale.setX(std::max(0.0, currentLayer->property.scale.x() + dx / 50.0));
currentLayer->property.scale.setY(std::max(0.0, currentLayer->property.scale.y() + dy / 50.0));
}
else if (QApplication::keyboardModifiers() == (Qt::ControlModifier | Qt::ShiftModifier) && (event->buttons() & Qt::LeftButton))
{
currentLayer->property.scale.setX(std::max(0.0, currentLayer->property.scale.x() * (1.0 + dx / 50.0)));
currentLayer->property.scale.setY(std::max(0.0, currentLayer->property.scale.y() * (1.0 + dx / 50.0)));
}
else if (event->buttons() & Qt::LeftButton) {
// 如果按下的是左键,那么平移图形 // 如果按下的是左键,那么平移图形
currentLayer->property.offset.setX(currentLayer->property.offset.x() + dx); currentLayer->property.offset.setX(currentLayer->property.offset.x() + dx);
currentLayer->property.offset.setY(currentLayer->property.offset.y() + dy); currentLayer->property.offset.setY(currentLayer->property.offset.y() + dy);

View File

@ -83,9 +83,7 @@ FolderLayerWrapper* PaintingUtil::handleLayerWrapper(LayerWrapper* nowLayer, QTr
QPainterPath painterPath = pixelPath.getPainterPath(); QPainterPath painterPath = pixelPath.getPainterPath();
QRectF bound = painterPath.boundingRect(); QRectF bound = painterPath.boundingRect();
//qDebug() << leafLayer<<"------" << painterPath; //qDebug() << leafLayer<<"------" << painterPath;
//qDebug() << transform; // transform to -1£¬ 1
// transform to initial painterPath
// transfrom to -1£¬ 1
QTransform trans; QTransform trans;
double maxLen = std::max(bound.width(), bound.height()); double maxLen = std::max(bound.width(), bound.height());
qDebug() << maxLen << bound; qDebug() << maxLen << bound;
@ -102,22 +100,19 @@ FolderLayerWrapper* PaintingUtil::handleLayerWrapper(LayerWrapper* nowLayer, QTr
auto baseStyles = leafLayer->styles.toBaseStyles(); auto baseStyles = leafLayer->styles.toBaseStyles();
Renderer::BaseElement element; Renderer::BaseElement element;
element.contour = contour; element.contour = contour;
for (auto baseStyle : baseStyles) { for (auto& baseStyle : baseStyles) {
double lineWidth = 0; double lineWidth = 0;
if (baseStyle.material->type() == Renderer::MaterialStyleType::kStroke) { if (baseStyle.material->type() == Renderer::MaterialStyleType::kStroke) {
auto material = dynamic_cast<MaterialStyleStroke*>(baseStyle.material.get()); auto material = std::static_pointer_cast<MaterialStyleStroke>(baseStyle.material);
material->halfWidth = material->halfWidth / maxLen; material->halfWidth /= maxLen;
lineWidth = material->halfWidth; lineWidth = material->halfWidth;
qDebug() << material->halfWidth; qDebug() << material->halfWidth;
} }
QRectF rect = painterPath.boundingRect(); QPainterPathStroker stroker;
rect.setX(-lineWidth + rect.x()); stroker.setWidth(lineWidth);
rect.setY(-lineWidth + rect.y()); stroker.setCapStyle(Qt::RoundCap);
rect.setWidth(lineWidth * 2 + rect.width()); QPainterPath strokePath = stroker.createStroke(painterPath);
rect.setHeight(lineWidth * 2 + rect.height()); auto rect = transform.map(strokePath).boundingRect();
QPainterPath path;
path.addRect(rect);
rect = transform.map(path).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();
@ -125,7 +120,7 @@ FolderLayerWrapper* PaintingUtil::handleLayerWrapper(LayerWrapper* nowLayer, QTr
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; //qDebug() << transform;
elementTransform.zIndex = 0; elementTransform.zIndex = 0;
element.style = baseStyle.material; element.style = baseStyle.material;

View File

@ -1,5 +1,6 @@
#include "MaterialStyleStroke.h" #include "MaterialStyleStroke.h"
#include <QDebug> #include <QDebug>
#include <array>
using namespace Renderer; using namespace Renderer;
@ -117,4 +118,10 @@ float Renderer::MaterialStyleStroke::getHalfWidth() const
return halfWidth; return halfWidth;
} }
#define endTypeBoxLabel(start, end) QStringLiteral(start##" -> "##end)
const std::array<std::pair<QString, StrokeEndType>, 4> Renderer::MaterialStyleStroke::strokeEndTypeNames = {
std::pair{endTypeBoxLabel("Բͷ", "Բͷ"), StrokeEndType::kRound},
std::pair{endTypeBoxLabel("ƽͷ", "Բͷ"), StrokeEndType::kFlatRound},
std::pair{endTypeBoxLabel("Բͷ", "ƽͷ"), StrokeEndType::kRoundFlat},
std::pair{endTypeBoxLabel("ƽͷ", "ƽͷ"), StrokeEndType::kFlat}
};

View File

@ -43,7 +43,7 @@ namespace Renderer
}; };
enum class StrokeType { kBothSides = 2, kLeftSide = 1, kRightSide = 0 }; enum class StrokeType { kBothSides = 2, kLeftSide = 1, kRightSide = 0 };
enum class StrokeEndType { kRound = 0b00, kFlat = 0b11, kRoundFlat = 0b10, kFlatRound = 0b01 }; enum class StrokeEndType { kRound = 0b00, kFlat = 0b11, kRoundFlat = 0b10, kFlatRound = 0b01, kClosed = 0b100/*用于封闭图形*/ };
class MaterialStyleStroke : public MaterialStyle class MaterialStyleStroke : public MaterialStyle
{ {
@ -59,5 +59,6 @@ namespace Renderer
StrokeType strokeType; StrokeType strokeType;
StrokeEndType endType; StrokeEndType endType;
std::shared_ptr<MaterialStroke> materialStroke; std::shared_ptr<MaterialStroke> materialStroke;
static const std::array<std::pair<QString, StrokeEndType>, 4> strokeEndTypeNames;
}; };
} }

View File

@ -42,17 +42,38 @@ namespace UnitTest
{ {
virtual std::vector<Renderer::BaseStyle> toBaseStyles() const override virtual std::vector<Renderer::BaseStyle> toBaseStyles() const override
{ {
return { BaseStyle(std::make_shared<TransformStyle>(), return { BaseStyle(std::make_shared<TransformStyle>(),
std::make_shared<MaterialStyleFill>( std::make_shared<MaterialStyleFill>(std::make_shared<FillPlain>(Material(QColor(255,255,0))))) };
std::make_shared<FillPlain>(Material(QColor(255,255,0))))) }; }
} style;
TestGLWidget w(style, path);
w.show();
a.exec();
}
TEST_METHOD(TestFillPlainAndStrokeRadialGradient)
{
QApplication a(argc, argv);
class Style : 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<MaterialStyleFill>(
std::make_shared<FillPlain>(Material(QColor(255,255,0))))),
BaseStyle(std::make_shared<TransformStyle>(),
std::make_shared<MaterialStyleStroke>(10, StrokeType::kBothSides, StrokeEndType::kRound,
std::make_shared<StrokeRadialGradient>(materialMap, false))) };
} }
} style; } style;
TestGLWidget w(style, path); TestGLWidget w(style, path);
w.show(); w.show();
a.exec(); a.exec();
} }
}; };
TEST_CLASS(ElementRendererStokeTypeTest) TEST_CLASS(ElementRendererStokeTypeTest)

View File

@ -122,20 +122,6 @@ namespace UnitTest
}; };
TEST_CLASS(PaintingUtilTest) TEST_CLASS(PaintingUtilTest)
{ {
TEST_METHOD(TransfromTest)
{
qInstallMessageHandler(messageHandler);
QPainterPath path;
path.addRect(0, 0, 20, 20);
QTransform trans;
qDebug() << path.boundingRect();
//qDebug() << trans;
//qDebug() << acos(-0.707107);
glm::vec2 scale;
float rotate;
PaintingUtil::decomposeTransform(trans, rotate, scale);
qDebug() << rotate;
qDebug() << scale.x << scale.y;
}
}; };
} }

View File

@ -59,7 +59,7 @@
"name": "Leaf2", "name": "Leaf2",
"styles": [ "styles": [
{ {
"enableEachSideIndependent": false, "enableEachSideIndependent": true,
"left": "AAAAQAEAIZwAf////1UA/w==", "left": "AAAAQAEAIZwAf////1UA/w==",
"right": "AADgQAAACJw=", "right": "AADgQAAACJw=",
"type": "stroke" "type": "stroke"