From ba0dd9e89100c1bb7d04d488f13852e10f990b0d Mon Sep 17 00:00:00 2001 From: Jakub Melka Date: Sat, 22 Jun 2024 17:43:41 +0200 Subject: [PATCH] Editor plugin: Style of text and paths --- .../EditorPlugin/editorplugin.cpp | 14 +- Pdf4QtLibCore/sources/pdffont.cpp | 3 +- .../sources/pdfpagecontentprocessor.h | 2 +- ...pdfpagecontenteditorediteditemsettings.cpp | 258 ++++++++++++++++++ .../pdfpagecontenteditorediteditemsettings.h | 40 ++- .../pdfpagecontenteditorediteditemsettings.ui | 87 ++++++ 6 files changed, 400 insertions(+), 4 deletions(-) diff --git a/Pdf4QtEditorPlugins/EditorPlugin/editorplugin.cpp b/Pdf4QtEditorPlugins/EditorPlugin/editorplugin.cpp index fc92439..93dd4f9 100644 --- a/Pdf4QtEditorPlugins/EditorPlugin/editorplugin.cpp +++ b/Pdf4QtEditorPlugins/EditorPlugin/editorplugin.cpp @@ -49,6 +49,10 @@ EditorPlugin::EditorPlugin() : m_scene.setIsPageContentDrawSuppressed(true); } +// TODO: When text is edited, old text remains +// TODO: Color of the text is unchanged +// TODO: Moznost nastavit fill / stroke bool + void EditorPlugin::setWidget(pdf::PDFWidget* widget) { Q_ASSERT(!m_widget); @@ -189,7 +193,14 @@ bool EditorPlugin::save() { pdf::PDFTemporaryValueChange guard(&m_isSaving, true); - if (QMessageBox::question(m_dataExchangeInterface->getMainWindow(), tr("Confirm Changes"), tr("The changes to the page content will be written to the document. Do you want to continue?"), QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) + auto answer = QMessageBox::question(m_dataExchangeInterface->getMainWindow(), tr("Confirm Changes"), tr("The changes to the page content will be written to the document. Do you want to continue?"), QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, QMessageBox::Cancel); + + if (answer == QMessageBox::Cancel) + { + return false; + } + + if (answer == QMessageBox::Yes) { pdf::PDFDocumentModifier modifier(m_document); @@ -590,6 +601,7 @@ void EditorPlugin::onSetActive(bool active) if (!active && !save()) { updateActions(); + m_actions[Activate]->setChecked(true); return; } diff --git a/Pdf4QtLibCore/sources/pdffont.cpp b/Pdf4QtLibCore/sources/pdffont.cpp index 01c2953..164e711 100644 --- a/Pdf4QtLibCore/sources/pdffont.cpp +++ b/Pdf4QtLibCore/sources/pdffont.cpp @@ -1985,7 +1985,8 @@ PDFEncodedText PDFSimpleFont::encodeText(const QString& text) const bool isFound = false; for (size_t i = 0; i < encodingTable->size(); ++i) { - if (unicode == (*encodingTable)[static_cast(i)]) + if (unicode == (*encodingTable)[static_cast(i)] && + m_glyphIndices[i] != GID()) { isFound = true; converted = static_cast(i); diff --git a/Pdf4QtLibCore/sources/pdfpagecontentprocessor.h b/Pdf4QtLibCore/sources/pdfpagecontentprocessor.h index 6964059..aa0a4a7 100644 --- a/Pdf4QtLibCore/sources/pdfpagecontentprocessor.h +++ b/Pdf4QtLibCore/sources/pdfpagecontentprocessor.h @@ -98,7 +98,7 @@ struct PDFOverprintMode /// Represents graphic state of the PDF (holding current graphic state parameters). /// Please see PDF Reference 1.7, Chapter 4.3 "Graphic State" -class PDFPageContentProcessorState +class PDF4QTLIBCORESHARED_EXPORT PDFPageContentProcessorState { public: explicit PDFPageContentProcessorState(); diff --git a/Pdf4QtLibWidgets/sources/pdfpagecontenteditorediteditemsettings.cpp b/Pdf4QtLibWidgets/sources/pdfpagecontenteditorediteditemsettings.cpp index 76f90d7..7cd1cc7 100644 --- a/Pdf4QtLibWidgets/sources/pdfpagecontenteditorediteditemsettings.cpp +++ b/Pdf4QtLibWidgets/sources/pdfpagecontenteditorediteditemsettings.cpp @@ -27,6 +27,7 @@ #include #include #include +#include namespace pdf { @@ -37,6 +38,48 @@ PDFPageContentEditorEditedItemSettings::PDFPageContentEditorEditedItemSettings(Q { ui->setupUi(this); connect(ui->loadImageButton, &QPushButton::clicked, this, &PDFPageContentEditorEditedItemSettings::selectImage); + + for (const QString& colorName : QColor::colorNames()) + { + QColor color(colorName); + QIcon icon = getIconForColor(color); + + ui->penColorCombo->addItem(icon, colorName, color); + ui->brushColorCombo->addItem(icon, colorName, color); + } + + ui->penStyleCombo->addItem(tr("None"), int(Qt::NoPen)); + ui->penStyleCombo->addItem(tr("Solid"), int(Qt::SolidLine)); + ui->penStyleCombo->addItem(tr("Dashed"), int(Qt::DashLine)); + ui->penStyleCombo->addItem(tr("Dotted"), int(Qt::DotLine)); + ui->penStyleCombo->addItem(tr("Dash-dot"), int(Qt::DashDotLine)); + ui->penStyleCombo->addItem(tr("Dash-dot-dot"), int(Qt::DashDotDotLine)); + + ui->brushStyleCombo->addItem(tr("None"), int(Qt::NoBrush)); + ui->brushStyleCombo->addItem(tr("Solid"), int(Qt::SolidPattern)); + + connect(ui->selectPenColorButton, &QToolButton::clicked, this, &PDFPageContentEditorEditedItemSettings::onSelectPenColorButtonClicked); + connect(ui->selectBrushColorButton, &QToolButton::clicked, this, &PDFPageContentEditorEditedItemSettings::onSelectBrushColorButtonClicked); + connect(ui->penWidthEdit, QOverload::of(&QDoubleSpinBox::valueChanged), this, &PDFPageContentEditorEditedItemSettings::onPenWidthChanged); + connect(ui->penStyleCombo, QOverload::of(&QComboBox::currentIndexChanged), this, &PDFPageContentEditorEditedItemSettings::onPenStyleChanged); + connect(ui->brushStyleCombo, QOverload::of(&QComboBox::currentIndexChanged), this, &PDFPageContentEditorEditedItemSettings::onBrushStyleChanged); + connect(ui->penColorCombo->lineEdit(), &QLineEdit::editingFinished, this, &PDFPageContentEditorEditedItemSettings::onPenColorComboTextChanged); + connect(ui->penColorCombo, QOverload::of(&QComboBox::currentIndexChanged), this, &PDFPageContentEditorEditedItemSettings::onPenColorComboIndexChanged); + connect(ui->brushColorCombo->lineEdit(), &QLineEdit::editingFinished, this, &PDFPageContentEditorEditedItemSettings::onBrushColorComboTextChanged); + connect(ui->brushColorCombo, QOverload::of(&QComboBox::currentIndexChanged), this, &PDFPageContentEditorEditedItemSettings::onBrushColorComboIndexChanged); +} + +QIcon PDFPageContentEditorEditedItemSettings::getIconForColor(QColor color) const +{ + QIcon icon; + + QSize iconSize = PDFWidgetUtils::scaleDPI(this, QSize(16, 16)); + + QPixmap pixmap(iconSize.width(), iconSize.height()); + pixmap.fill(color); + icon.addPixmap(pixmap); + + return icon; } PDFPageContentEditorEditedItemSettings::~PDFPageContentEditorEditedItemSettings() @@ -67,6 +110,11 @@ void PDFPageContentEditorEditedItemSettings::loadFromElement(PDFPageContentEleme ui->plainTextEdit->setPlainText(text); } + if (editedElement->getElement()->asText() || editedElement->getElement()->asPath()) + { + ui->tabWidget->addTab(ui->styleTab, tr("Style")); + } + QTransform matrix = editedElement->getElement()->getTransform(); PDFTransformationDecomposition decomposedTransformation = PDFPainterHelper::decomposeTransform(matrix); @@ -78,6 +126,101 @@ void PDFPageContentEditorEditedItemSettings::loadFromElement(PDFPageContentEleme ui->translateInYEdit->setValue(decomposedTransformation.translateY); ui->tabWidget->addTab(ui->transformationTab, tr("Transformation")); + + // Style + const PDFEditedPageContentElement* element = editedElement->getElement(); + + StyleFeatures features = None; + + if (element->asPath()) + { + features.setFlag(Pen); + features.setFlag(PenColor); + features.setFlag(Brush); + } + + if (element->asText()) + { + features.setFlag(PenColor); + } + + const bool hasPen = features.testFlag(Pen); + const bool hasPenColor = features.testFlag(PenColor); + const bool hasBrush = features.testFlag(Brush); + + ui->penWidthEdit->setEnabled(hasPen); + ui->penWidthLabel->setEnabled(hasPen); + + ui->penStyleCombo->setEnabled(hasPen); + ui->penStyleLabel->setEnabled(hasPen); + + ui->penColorCombo->setEnabled(hasPenColor); + ui->penColorLabel->setEnabled(hasPenColor); + ui->selectPenColorButton->setEnabled(hasPenColor); + + ui->brushStyleLabel->setEnabled(hasBrush); + ui->brushStyleCombo->setEnabled(hasBrush); + + ui->brushColorCombo->setEnabled(hasBrush); + ui->brushColorLabel->setEnabled(hasBrush); + ui->selectBrushColorButton->setEnabled(hasBrush); + + const PDFPageContentProcessorState& graphicState = element->getState(); + + QPen pen = pdf::PDFPainterHelper::createPenFromState(&graphicState, graphicState.getAlphaStroking()); + QBrush brush = pdf::PDFPainterHelper::createBrushFromState(&graphicState, graphicState.getAlphaFilling()); + + setPen(pen, true); + setBrush(brush, true); +} + +void PDFPageContentEditorEditedItemSettings::setPen(const QPen& pen, bool forceUpdate) +{ + if (m_pen != pen || forceUpdate) + { + m_pen = pen; + ui->penWidthEdit->setValue(pen.widthF()); + ui->penStyleCombo->setCurrentIndex(ui->penStyleCombo->findData(int(pen.style()))); + setColorToComboBox(ui->penColorCombo, pen.color()); + } +} + +void PDFPageContentEditorEditedItemSettings::setBrush(const QBrush& brush, bool forceUpdate) +{ + if (m_brush != brush || forceUpdate) + { + m_brush = brush; + ui->brushStyleCombo->setCurrentIndex(ui->brushStyleCombo->findData(int(brush.style()))); + setColorToComboBox(ui->brushColorCombo, brush.color()); + } +} + +void PDFPageContentEditorEditedItemSettings::setColorToComboBox(QComboBox* comboBox, QColor color) +{ + if (!color.isValid()) + { + return; + } + + QString name = color.name(QColor::HexArgb); + + int index = comboBox->findData(color, Qt::UserRole, Qt::MatchExactly); + + if (index == -1) + { + // Jakub Melka: try to find text (color name) + index = comboBox->findText(name); + } + + if (index != -1) + { + comboBox->setCurrentIndex(index); + } + else + { + comboBox->addItem(getIconForColor(color), name, color); + comboBox->setCurrentIndex(comboBox->count() - 1); + } } void PDFPageContentEditorEditedItemSettings::saveToElement(PDFPageContentElementEdited* editedElement) @@ -103,6 +246,16 @@ void PDFPageContentEditorEditedItemSettings::saveToElement(PDFPageContentElement QTransform transform = PDFPainterHelper::composeTransform(decomposedTransformation); editedElement->getElement()->setTransform(transform); + + if (editedElement->getElement()->asText() || editedElement->getElement()->asPath()) + { + PDFPageContentProcessorState graphicState = editedElement->getElement()->getState(); + + PDFPainterHelper::applyPenToGraphicState(&graphicState, m_pen); + PDFPainterHelper::applyBrushToGraphicState(&graphicState, m_brush); + + editedElement->getElement()->setState(graphicState); + } } static int PDF_gcd(int a, int b) @@ -185,4 +338,109 @@ void PDFPageContentEditorEditedItemSettings::selectImage() } } +void PDFPageContentEditorEditedItemSettings::setPenColor(QColor color) +{ + if (color.isValid()) + { + m_pen.setColor(color); + setColorToComboBox(ui->penColorCombo, color); + } +} + +void PDFPageContentEditorEditedItemSettings::onSelectPenColorButtonClicked() +{ + QColor color = QColorDialog::getColor(m_pen.color(), this, tr("Select Color for Pen"), QColorDialog::ShowAlphaChannel); + setPenColor(color); +} + +void PDFPageContentEditorEditedItemSettings::setBrushColor(QColor color) +{ + if (color.isValid() && m_brush.color() != color) + { + m_brush.setColor(color); + setColorToComboBox(ui->brushColorCombo, color); + } +} + +const QBrush& PDFPageContentEditorEditedItemSettings::getBrush() const +{ + return m_brush; +} + +const QPen& PDFPageContentEditorEditedItemSettings::getPen() const +{ + return m_pen; +} + +void PDFPageContentEditorEditedItemSettings::onSelectBrushColorButtonClicked() +{ + QColor color = QColorDialog::getColor(m_pen.color(), this, tr("Select Color for Brush"), QColorDialog::ShowAlphaChannel); + setBrushColor(color); +} + +void PDFPageContentEditorEditedItemSettings::onPenWidthChanged(double value) +{ + m_pen.setWidthF(value); +} + +void PDFPageContentEditorEditedItemSettings::onPenStyleChanged() +{ + Qt::PenStyle penStyle = static_cast(ui->penStyleCombo->currentData().toInt()); + m_pen.setStyle(penStyle); +} + +void PDFPageContentEditorEditedItemSettings::onBrushStyleChanged() +{ + Qt::BrushStyle brushStyle = static_cast(ui->brushStyleCombo->currentData().toInt()); + m_brush.setStyle(brushStyle); +} + +void PDFPageContentEditorEditedItemSettings::onPenColorComboTextChanged() +{ + QColor color(ui->penColorCombo->currentText()); + if (color.isValid()) + { + setColorToComboBox(ui->penColorCombo, color); + m_pen.setColor(color); + } + else if (ui->penColorCombo->currentIndex() != -1) + { + ui->penColorCombo->setEditText(ui->penColorCombo->itemText(ui->penColorCombo->currentIndex())); + } +} + +void PDFPageContentEditorEditedItemSettings::onPenColorComboIndexChanged() +{ + const int index = ui->penColorCombo->currentIndex(); + QColor color = ui->penColorCombo->itemData(index, Qt::UserRole).value(); + if (color.isValid() && m_pen.color() != color) + { + m_pen.setColor(color); + } +} + +void PDFPageContentEditorEditedItemSettings::onBrushColorComboTextChanged() +{ + QColor color(ui->brushColorCombo->currentText()); + if (color.isValid()) + { + setColorToComboBox(ui->brushColorCombo, color); + m_brush.setColor(color); + } + else if (ui->brushColorCombo->currentIndex() != -1) + { + ui->brushColorCombo->setEditText(ui->brushColorCombo->itemText(ui->brushColorCombo->currentIndex())); + } +} + +void PDFPageContentEditorEditedItemSettings::onBrushColorComboIndexChanged() +{ + const int index = ui->brushColorCombo->currentIndex(); + QColor color = ui->brushColorCombo->itemData(index, Qt::UserRole).value(); + if (color.isValid()) + { + m_brush.setColor(color); + } +} + } // namespace pdf diff --git a/Pdf4QtLibWidgets/sources/pdfpagecontenteditorediteditemsettings.h b/Pdf4QtLibWidgets/sources/pdfpagecontenteditorediteditemsettings.h index c978df8..f81d134 100644 --- a/Pdf4QtLibWidgets/sources/pdfpagecontenteditorediteditemsettings.h +++ b/Pdf4QtLibWidgets/sources/pdfpagecontenteditorediteditemsettings.h @@ -19,8 +19,13 @@ #define PDFPAGECONTENTEDITOREDITEDITEMSETTINGS_H #include +#include +#include -namespace Ui { +class QComboBox; + +namespace Ui +{ class PDFPageContentEditorEditedItemSettings; } @@ -39,12 +44,45 @@ public: void loadFromElement(PDFPageContentElementEdited* editedElement); void saveToElement(PDFPageContentElementEdited* editedElement); + void setPen(const QPen& pen, bool forceUpdate); + void setBrush(const QBrush& brush, bool forceUpdate); + + const QPen& getPen() const; + const QBrush& getBrush() const; + private: + void onSelectPenColorButtonClicked(); + void onSelectBrushColorButtonClicked(); + void onPenWidthChanged(double value); + void onPenStyleChanged(); + void onBrushStyleChanged(); + void onPenColorComboTextChanged(); + void onPenColorComboIndexChanged(); + void onBrushColorComboTextChanged(); + void onBrushColorComboIndexChanged(); + void setImage(QImage image); void selectImage(); + enum StyleFeature + { + None = 0, + Pen = 1 << 0, + PenColor = 1 << 1, + Brush = 1 << 2 + }; + Q_DECLARE_FLAGS(StyleFeatures, StyleFeature) + + void setColorToComboBox(QComboBox* comboBox, QColor color); + QIcon getIconForColor(QColor color) const; + + void setPenColor(QColor color); + void setBrushColor(QColor color); + Ui::PDFPageContentEditorEditedItemSettings* ui; QImage m_image; + QPen m_pen; + QBrush m_brush; }; } // namespace pdf diff --git a/Pdf4QtLibWidgets/sources/pdfpagecontenteditorediteditemsettings.ui b/Pdf4QtLibWidgets/sources/pdfpagecontenteditorediteditemsettings.ui index 33c21b0..8e86601 100644 --- a/Pdf4QtLibWidgets/sources/pdfpagecontenteditorediteditemsettings.ui +++ b/Pdf4QtLibWidgets/sources/pdfpagecontenteditorediteditemsettings.ui @@ -138,6 +138,93 @@ Style + + + + + true + + + + + + + Pen Style + + + + + + + + + + Brush Color + + + + + + + ... + + + + + + + ... + + + + + + + + + + Pen Width + + + + + + + Brush Style + + + + + + + Pen Color + + + + + + + + + + true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + +