图元预览改为懒加载;添加帧缓存;修改图元预览渲染机制;固定渲染倍率*

dev-wuyize
karlis 2023-03-22 19:58:17 +08:00
parent 7e0e07292f
commit beee94ebe0
11 changed files with 121 additions and 44 deletions

View File

@ -84,7 +84,7 @@ void EditorWidget::initFileMenu()
auto* item = dynamic_cast<EditorWidgetItem*>(this->tabWidget->currentWidget());
if (item != nullptr)
{
//item->save();
item->save();
}
});
connect(actionSaveAs, &QAction::triggered, this, [this] {

View File

@ -25,9 +25,9 @@ EditorWidgetItem::EditorWidgetItem(QString filePath,QWidget *parent) : QWidget(p
qDebug() << elementInfoDisplayWidget;
auto centralRefresh = [this]() {
layerInfoDisplayWidget->refresh();
elementInfoDisplayWidget->refresh();
treeWidget->refresh();
previewWindow->refresh();
elementInfoDisplayWidget->lazyRefresh();
};
connect(previewWindow, &PreviewWindow::triggerCentralRefresh, centralRefresh);
connect(layerInfoDisplayWidget, &InfoDisplayWidget::triggerCentralRefresh, centralRefresh);

View File

@ -4,6 +4,7 @@
#include <QFileDialog>
#include <QDialogButtonBox>
#include <QMessagebox>
#include <QTimer>
ElementPoolWidget::ElementPoolWidget(QWidget* parent)
: QWidget(parent)
@ -38,10 +39,15 @@ void ElementPoolWidget::setElementList(std::vector<GraphicElement*> elements) {
pictureList->clear();
this->elements = elements;
for (int index = 0; index < elements.size(); index++) {
QListWidgetItem* pItem = new QListWidgetItem(
elements[index]->getPreview(QSize(iconWidth - 25, iconHeight - 25)),
elements[index]->name);
QListWidgetItem* pItem = new QListWidgetItem(elements[index]->name);
QPainter* painter = new QPainter();
QImage* image = new QImage(QSize(iconWidth - 12, iconHeight - 12), QImage::Format_ARGB32);
image->fill(Qt::transparent);
pItem->setIcon(QIcon(QPixmap::fromImage(*image)));
pItem->setSizeHint(QSize(iconWidth, iconHeight));
painter->begin(image);
elements[index]->paintPreview(painter);
painter->end();
pictureList->insertItem(index, pItem);
}
if(elements.size() > 0)
@ -66,15 +72,47 @@ void ElementPoolWidget::setElementManager(ElementManager* element)
this->setElementList(this->elementManager->elements);
}
void ElementPoolWidget::lazyRefresh()
{
if (!refreshWait) {
refreshWait = true;
QTimer::singleShot(1000, this, SLOT(refresh()));
}
}
void ElementPoolWidget::refresh() {
this->setElementList(this->elementManager->elements);
// update();
refreshWait = false;
if (elementManager != nullptr)
{
for (int i = 0; i < elements.size(); i++)
{
QListWidgetItem* pItem = pictureList->item(i);
if (pItem == nullptr)
{
pItem = new QListWidgetItem(elements[i]->name);
pictureList->insertItem(i, pItem);
}
QPainter* painter = new QPainter();
QImage* image = new QImage(QSize(iconWidth - 12, iconHeight - 12), QImage::Format_ARGB32);
image->fill(Qt::transparent);
painter->begin(image);
elements[i]->paintPreview(painter);
painter->end();
pItem->setIcon(QIcon(QPixmap::fromImage(*image)));
pItem->setData(Qt::UserRole, QVariant::fromValue(image));
pItem->setSizeHint(QSize(iconWidth, iconHeight));
pictureList->insertItem(i, pItem);
}
}
}
void ElementPoolWidget::refreshPicture(GraphicElement* element) {
for (int i = 0; i < elements.size(); i++) {
if (element == elements[i]) {
pictureList->item(i)->setIcon(elements[i]->getPreview(QSize(iconWidth - 25, iconHeight - 25)));
QPainter* painter = new QPainter();
painter->begin(pictureList->item(i)->data(Qt::UserRole).value<QImage*>());
elements[i]->paintPreview(painter);
painter->end();
// update();
return;
}
@ -84,7 +122,10 @@ void ElementPoolWidget::refreshPicture(GraphicElement* element) {
void ElementPoolWidget::refreshPictureByIndex(int index) {
if (index >= 0 && index < elements.size())
{
pictureList->item(index)->setIcon(elements[index]->getPreview(QSize(iconWidth - 25, iconHeight - 25)));
QPainter* painter = new QPainter();
painter->begin(pictureList->item(index)->data(Qt::UserRole).value<QImage*>());
elements[index]->paintPreview(painter);
painter->end();
// update();
}
}
@ -118,7 +159,6 @@ void ElementPoolWidget::popMenu(const QPoint& pos)
});
menu->addAction(QString::fromLocal8Bit("ɾ³ý"), this, [this, currentElement]() {
this->elementManager->removeElement(currentElement);
emit triggerCentralRefresh();
});
menu->actions().last()->setDisabled(currentElement->referencedCount > 0);
}

View File

@ -14,6 +14,7 @@ private:
QListWidget* pictureList;
int iconWidth, iconHeight;
ElementManager* elementManager;
bool refreshWait = false;
public:
int currentIndex = -1;
@ -22,6 +23,7 @@ public:
void setElementManager(ElementManager* element);
~ElementPoolWidget();
void enableEdit();
void lazyRefresh();
signals:
void elementSelected(GraphicElement* element);

View File

@ -45,7 +45,6 @@ void GroupElement::setSourceLayer(FolderLayerWrapper* sourceLayer)
PixelPath GroupElement::getPaintObject() const
{
if (sourceLayer != nullptr) {
sourceLayer->refresh();
return sourceLayer->getCache();
}
else
@ -113,8 +112,9 @@ void SimpleElement::paint(QPainter* painter, QTransform transform, const LayerSt
maxScale = std::max(fabs(transform.m11() / cos(angle)), fabs(transform.m22() / cos(angle)));
else
maxScale = std::max(fabs(transform.m12() / sin(angle)), fabs(transform.m21() / sin(angle)));
double pixelRatio = maxScale * QGuiApplication::primaryScreen()->devicePixelRatio();
if (painterPath == painterPathPrev && styles.getHash() == stylesHashValue && pixelRatio == pixelRatioPrev)
//double pixelRatio = maxScale * QGuiApplication::primaryScreen()->devicePixelRatio();
double pixelRatio = 5;
if (painterPath == painterPathPrev && styles.getHash() == stylesHashValue && fabs(pixelRatio - pixelRatioPrev) < 1e-3)
{
transform.translate(movPrev.x(), movPrev.y());
painter->setTransform(transform.scale(1 / pixelRatio, 1 / pixelRatio));
@ -153,31 +153,26 @@ bool GroupElement::isClosed() const
}
QPixmap SimpleElement::getPreview(QSize size)
void SimpleElement::paintPreview(QPainter* painter)
{
QPixmap result(size + QSize(5, 5));
QPainter painter(&result);
painter.setRenderHint(QPainter::Antialiasing);
painter.setRenderHint(QPainter::SmoothPixmapTransform);
painter.scale(size.width() / painterPath.boundingRect().width(), size.height() / painterPath.boundingRect().height());
painter.drawPath(painterPath);
return result;
painter->save();
painter->setWindow(painterPath.boundingRect().x() - 5, painterPath.boundingRect().y() - 5, (painterPath.boundingRect().width() + 10) * QGuiApplication::primaryScreen()->devicePixelRatio(), (painterPath.boundingRect().height() + 10) * QGuiApplication::primaryScreen()->devicePixelRatio());
painter->drawPath(painterPath);
painter->restore();
}
QPixmap GroupElement::getPreview(QSize size)
void GroupElement::paintPreview(QPainter* painter)
{
painter->save();
auto cache = sourceLayer->getCache();
QPixmap result(QSize(1024, 1024));
QPainter painter(&result);
painter.setRenderHint(QPainter::Antialiasing);
painter.setRenderHint(QPainter::SmoothPixmapTransform);
sourceLayer->paint(&painter, QTransform(), true);
painter.end();
QRect rect(cache.getBoundingRect().toRect());
rect.setTopLeft(rect.topLeft() - QPoint(5, 5));
rect.setBottomRight(rect.bottomRight() + QPoint(5, 5));
result = result.copy(rect);
return result.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
painter->setRenderHint(QPainter::Antialiasing, true);
painter->setRenderHint(QPainter::SmoothPixmapTransform, true);
painter->setWindow(cache.getBoundingRect().toRect().x() - 5, cache.getBoundingRect().toRect().y() - 5, (cache.getBoundingRect().toRect().width() + 10) * QGuiApplication::primaryScreen()->devicePixelRatio(), (cache.getBoundingRect().toRect().height() + 10) * QGuiApplication::primaryScreen()->devicePixelRatio());
//painter->translate(-cache.getBoundingRect().toRect().x() - 5, -cache.getBoundingRect().toRect().y() - 5);
//double maxScale = std::max(cache.getBoundingRect().toRect().width() + 10, cache.getBoundingRect().toRect().height() + 10) * QGuiApplication::primaryScreen()->devicePixelRatio();
//painter->scale(1 / maxScale, 1/ maxScale);
sourceLayer->paint(painter, QTransform(), true);
painter->restore();
}
void GroupElement::collectReachable(std::set<LayerWrapper*>& set) const

View File

@ -20,6 +20,7 @@ class ComposedPainterPath;
class GraphicElement
{
public:
bool needRefresh = true;
size_t referencedCount = 0;
Renderer::ElementRenderer *renderer;
QString name = "";
@ -35,7 +36,7 @@ public:
virtual PixelPath getPaintObject(const LayerStyleContainer& styles) const = 0;
virtual void paint(QPainter* painter, QTransform transform, const LayerStyleContainer& styles) = 0;
virtual bool isClosed() const = 0;
virtual QPixmap getPreview(QSize size) = 0;
virtual void paintPreview(QPainter* painter) = 0;
};
@ -59,7 +60,7 @@ public:
PixelPath getPaintObject(const LayerStyleContainer& styles) const override;
void paint(QPainter* painter, QTransform transform, const LayerStyleContainer& styles) override;
bool isClosed() const override;
QPixmap getPreview(QSize size) override;
void paintPreview(QPainter* painter) override;
};
class GroupElement : public GraphicElement
@ -77,10 +78,12 @@ public:
void setSourceLayer(FolderLayerWrapper* sourceLayer);
void paint(QPainter* painter, QTransform transform, const LayerStyleContainer& styles) override;
bool isClosed() const override;
QPixmap getPreview(QSize size) override;
void paintPreview(QPainter* painter) override;
void collectReachable(std::set<LayerWrapper*>& set) const;
};
Q_DECLARE_METATYPE(GraphicElement*)
//******************************** BitmapPath ********************************//
//using std::vector;

View File

@ -14,6 +14,7 @@ LayerWrapper *LayerManager::getRoot() const
void LayerManager::paint(QPainter *painter, QSize size,LayerWrapper* selecetedLayer) const
{
painter->save();
root->markNeedRefresh();
root->getCache();
root->paint(painter);
painter->restore();

View File

@ -25,10 +25,10 @@ FolderLayerWrapper*LayerWrapper::getParent() const
PixelPath LayerWrapper::getCache(LayerWrapper* selectedLayer)
{
this->refresh(selectedLayer);
if (selectedLayer == this)
if (needRefresh)
{
this->cache.highLight();
this->refresh(selectedLayer);
needRefresh = false;
}
return cache;
}
@ -460,4 +460,16 @@ void LayerWrapper::paintVisualBounding(QPainter* painter) const
painter->setTransform(transform);
painter->drawRect(cache.getBoundingRect());
painter->restore();
}
void LayerWrapper::markNeedRefresh()
{
this->needRefresh = true;
}
void FolderLayerWrapper::markNeedRefresh()
{
LayerWrapper::markNeedRefresh();
for (auto& child : children)
child->markNeedRefresh();
}

View File

@ -35,6 +35,7 @@ class LayerWrapper
PixelPath cache;
public:
bool needRefresh = true;
QTreeWidgetItem* qTreeWidgetItem;
bool selected;
bool hidden;
@ -77,6 +78,7 @@ class LayerWrapper
virtual bool referencingGroupElement() const;
virtual void paintVisualBounding(QPainter* painter) const;
bool canApplyStyles() const;
virtual void markNeedRefresh();
};
class FolderLayerWrapper : public LayerWrapper
@ -104,6 +106,7 @@ class FolderLayerWrapper : public LayerWrapper
void refreshTreeItem() override;
size_t referencedCount(bool excludeSelf = false) const override;
bool deleteable(bool excludeSubTree = false) const override;
void markNeedRefresh() override;
};
class LeafLayerWrapper : public LayerWrapper

View File

@ -21,37 +21,51 @@ InfoDisplayWidget::InfoDisplayWidget(QWidget* parent) :QWidget(parent)
ui.rotation->setLabel(("旋转角度"));
ui.scaleX->setLabel(("水平缩放"));
ui.scaleY->setLabel(("垂直缩放"));
ui.rotation->setValidator(new QIntValidator(-10000, 10000, this));
ui.rotation->setValidator(new QDoubleValidator(-10000, 10000, 6, this));
ui.styleList->setDisabled(true);
connect(ui.rotation, &QLineEdit::textChanged, [=](QString content) {
if (fabs(content.toDouble() - this->displayLayer->property.rotation) < 1e-6)
return;
this->displayLayer->property.rotation = content.toDouble();
emit triggerCentralRefresh();
});
ui.offsetX->setValidator(new QIntValidator(-10000, 10000, this));
ui.offsetX->setValidator(new QDoubleValidator(-10000, 10000, 2, this));
connect(ui.offsetX, &QLineEdit::textChanged, [=](QString content) {
if (fabs(content.toDouble() - this->displayLayer->property.offset.x()) < 1e-6)
return;
this->displayLayer->property.offset = { content.toDouble(), this->displayLayer->property.offset.y() };
emit triggerCentralRefresh();
});
ui.offsetY->setValidator(new QIntValidator(-10000, 10000, this));
ui.offsetY->setValidator(new QDoubleValidator(-10000, 10000, 2, this));
connect(ui.offsetY, &QLineEdit::textChanged, [=](QString content) {
if (fabs(content.toDouble() - this->displayLayer->property.offset.y()) < 1e-6)
return;
this->displayLayer->property.offset = { this->displayLayer->property.offset.x(), content.toDouble() };
emit triggerCentralRefresh();
});
ui.scaleX->setValidator(new QDoubleValidator(0, 1000, 4, this));
ui.scaleX->setValidator(new QDoubleValidator(0, 10000, 6, this));
connect(ui.scaleX, &QLineEdit::textChanged, [=](QString content) {
if (fabs(content.toDouble() - this->displayLayer->property.scale.x()) < 1e-6)
return;
this->displayLayer->property.scale = { content.toDouble(), this->displayLayer->property.scale.y() };
emit triggerCentralRefresh();
});
ui.scaleY->setValidator(new QDoubleValidator(0, 1000, 4, this));
ui.scaleY->setValidator(new QDoubleValidator(0, 10000, 6, this));
connect(ui.scaleY, &QLineEdit::textChanged, [=](QString content) {
if (fabs(content.toDouble() - this->displayLayer->property.scale.y()) < 1e-6)
return;
this->displayLayer->property.scale = { this->displayLayer->property.scale.x(), content.toDouble() };
emit triggerCentralRefresh();
});
connect(ui.flipX, &QtMaterialCheckBox::toggled, [=](bool state) {
if (state == this->displayLayer->property.flipX)
return;
this->displayLayer->property.flipX = state;
emit triggerCentralRefresh();
});
connect(ui.flipY, &QtMaterialCheckBox::toggled, [=](bool state) {
if (state == this->displayLayer->property.flipY)
return;
this->displayLayer->property.flipY = state;
emit triggerCentralRefresh();
});

View File

@ -239,6 +239,7 @@ QAction* LayerTreeWidget::getPromoteUpAction()
auto layer = pair.first;
auto parent = pair.second;
this->moveLayer(layer, parent);
this->setCurrentItem(layer->qTreeWidgetItem);
});
optionList.append(option);
}
@ -255,6 +256,11 @@ QAction* LayerTreeWidget::getPromoteDownAction()
std::vector<FolderLayerWrapper*> layers;
auto layer = this->selectedItem->data(0, Qt::UserRole).value<LayerWrapper*>();
auto parent = layer->getParent();
if (parent == nullptr)
{
action->setEnabled(false);
return action;
}
for (auto child : parent->children)
{
if (child.get() == layer || typeid(*child) != typeid(FolderLayerWrapper))
@ -278,6 +284,7 @@ QAction* LayerTreeWidget::getPromoteDownAction()
auto layer = pair.first;
auto parent = pair.second;
this->moveLayer(layer, parent);
this->setCurrentItem(layer->qTreeWidgetItem);
});
optionList.append(option);
}