Adding a framework to generate code for fonts.
- Work in progress to add a framework generating bitmap fonts.main
rodzic
3c46483bcb
commit
0018e4e9db
|
@ -0,0 +1,67 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#include "ApplicationController.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
ApplicationController *ApplicationController::_instance = nullptr;
|
||||||
|
|
||||||
|
|
||||||
|
ApplicationController::ApplicationController(QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
{
|
||||||
|
_instance = this;
|
||||||
|
|
||||||
|
// Start as soon the main loop is running.
|
||||||
|
QMetaObject::invokeMethod(this, &ApplicationController::start, Qt::QueuedConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QFont ApplicationController::monospaceFont() const
|
||||||
|
{
|
||||||
|
QFont monospaceFont;
|
||||||
|
#ifdef Q_OS_WIN32
|
||||||
|
monospaceFont = QFont("Consolas", 12);
|
||||||
|
#else
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
monospaceFont = QFont("Menlo", 12);
|
||||||
|
#else
|
||||||
|
monospaceFont = QFont("Lucida Console", 12);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
return monospaceFont;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ApplicationController::start()
|
||||||
|
{
|
||||||
|
_mainWindow = new MainWindow();
|
||||||
|
_mainWindow->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ApplicationController *ApplicationController::instance()
|
||||||
|
{
|
||||||
|
return _instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ApplicationController* gApp()
|
||||||
|
{
|
||||||
|
return ApplicationController::instance();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include "MainWindow.hpp"
|
||||||
|
|
||||||
|
#include <QtCore/QObject>
|
||||||
|
|
||||||
|
|
||||||
|
/// The application controller
|
||||||
|
///
|
||||||
|
class ApplicationController : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// ctor
|
||||||
|
///
|
||||||
|
explicit ApplicationController(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Get the default monospaced font.
|
||||||
|
///
|
||||||
|
QFont monospaceFont() const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Get the global instance.
|
||||||
|
///
|
||||||
|
static ApplicationController* instance();
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// Start the application.
|
||||||
|
///
|
||||||
|
Q_SLOT void start();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static ApplicationController *_instance; ///< The controller instance.
|
||||||
|
MainWindow *_mainWindow; ///< The main window.
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
ApplicationController* gApp();
|
|
@ -0,0 +1,29 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#include "BitmapConverter.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
BitmapConverter::BitmapConverter(const QString &displayName)
|
||||||
|
: Converter(displayName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Converter::Mode BitmapConverter::mode() const
|
||||||
|
{
|
||||||
|
return Mode::Bitmap;
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include "Converter.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
/// The base class for all bitmap converters.
|
||||||
|
///
|
||||||
|
class BitmapConverter : public Converter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// ctor
|
||||||
|
///
|
||||||
|
BitmapConverter(const QString &displayName);
|
||||||
|
|
||||||
|
public: // implement Converter
|
||||||
|
Mode mode() const override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Generate the code from the given image.
|
||||||
|
///
|
||||||
|
/// @param image The image to convert.
|
||||||
|
/// @param parameter A map with parameters passed to this converter.
|
||||||
|
/// @return The generated code.
|
||||||
|
///
|
||||||
|
virtual QString generateCode(const QImage &image, const QVariantMap ¶meter) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
|
@ -17,16 +17,19 @@
|
||||||
#include "BitmapPanel.hpp"
|
#include "BitmapPanel.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#include "ApplicationController.hpp"
|
||||||
#include "Converter.hpp"
|
#include "Converter.hpp"
|
||||||
#include "BitmapPreview.hpp"
|
#include "BitmapPreview.hpp"
|
||||||
|
|
||||||
#include <QComboBox>
|
#include <QtWidgets/QComboBox>
|
||||||
#include <QLabel>
|
#include <QtWidgets/QLabel>
|
||||||
#include <QScrollArea>
|
#include <QtWidgets/QScrollArea>
|
||||||
#include <QVBoxLayout>
|
#include <QtWidgets/QVBoxLayout>
|
||||||
|
#include <QtWidgets/QPushButton>
|
||||||
|
|
||||||
|
|
||||||
BitmapPanel::BitmapPanel(QWidget *parent) : QWidget(parent)
|
BitmapPanel::BitmapPanel(QWidget *parent)
|
||||||
|
: QWidget(parent), _converter(nullptr)
|
||||||
{
|
{
|
||||||
initializeUi();
|
initializeUi();
|
||||||
}
|
}
|
||||||
|
@ -35,16 +38,49 @@ BitmapPanel::BitmapPanel(QWidget *parent) : QWidget(parent)
|
||||||
void BitmapPanel::setImage(const QImage &image)
|
void BitmapPanel::setImage(const QImage &image)
|
||||||
{
|
{
|
||||||
_bitmapPreview->setImage(image);
|
_bitmapPreview->setImage(image);
|
||||||
|
_bitmapPreview->setFixedSize(_bitmapPreview->sizeHint());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void BitmapPanel::setConverter(const Converter *converter)
|
void BitmapPanel::setConverter(const Converter *converter)
|
||||||
{
|
{
|
||||||
_bitmapPreview->setConverter(converter);
|
if (_converter != converter) {
|
||||||
|
_converter = converter;
|
||||||
|
_bitmapPreview->setConverter(converter);
|
||||||
|
_bitmapPreview->setFixedSize(_bitmapPreview->sizeHint());
|
||||||
|
_characterSelector->setVisible(_converter->mode() == Converter::Mode::Font);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BitmapPanel::setCharacters(const QString &characters)
|
||||||
|
{
|
||||||
|
if (_characters != characters) {
|
||||||
|
_characters = characters;
|
||||||
|
_characterSelector->clear();
|
||||||
|
for (int i = 0; i < characters.size(); ++i) {
|
||||||
|
const auto c = _characters.at(i);
|
||||||
|
_characterSelector->addItem(QString("%1: %2 0x%3").arg(i, 3, 10, QChar('0'))
|
||||||
|
.arg(QString(c)).arg(c.unicode(), 4, 16, QChar('0')), c);
|
||||||
|
}
|
||||||
|
_characterSelector->setCurrentIndex(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BitmapPanel::setParameter(const QVariantMap ¶meter)
|
||||||
|
{
|
||||||
|
_bitmapPreview->setParameter(parameter);
|
||||||
_bitmapPreview->setFixedSize(_bitmapPreview->sizeHint());
|
_bitmapPreview->setFixedSize(_bitmapPreview->sizeHint());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QChar BitmapPanel::selectedCharacter() const
|
||||||
|
{
|
||||||
|
return _characterSelector->currentData().toChar();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void BitmapPanel::initializeUi()
|
void BitmapPanel::initializeUi()
|
||||||
{
|
{
|
||||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||||
|
@ -72,6 +108,35 @@ void BitmapPanel::initializeUi()
|
||||||
auto previewSettingsLayout = new QHBoxLayout(previewSettingsPanel);
|
auto previewSettingsLayout = new QHBoxLayout(previewSettingsPanel);
|
||||||
previewSettingsLayout->setContentsMargins(0, 0, 0, 0);
|
previewSettingsLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
previewSettingsLayout->setSpacing(4);
|
previewSettingsLayout->setSpacing(4);
|
||||||
|
|
||||||
|
_fontConversionTools = new QFrame();
|
||||||
|
auto fontConversionLayout = new QHBoxLayout(_fontConversionTools);
|
||||||
|
fontConversionLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
fontConversionLayout->setSpacing(2);
|
||||||
|
previewSettingsLayout->addWidget(_fontConversionTools);
|
||||||
|
|
||||||
|
auto previousCharButton = new QPushButton("<");
|
||||||
|
fontConversionLayout->addWidget(previousCharButton);
|
||||||
|
_characterSelector = new QComboBox();
|
||||||
|
_characterSelector->setFont(gApp()->monospaceFont());
|
||||||
|
fontConversionLayout->addWidget(_characterSelector);
|
||||||
|
auto nextCharButton = new QPushButton(">");
|
||||||
|
fontConversionLayout->addWidget(nextCharButton);
|
||||||
|
connect(_characterSelector, &QComboBox::currentIndexChanged, [=]{
|
||||||
|
Q_EMIT selectedCharacterChanged(_characterSelector->currentData().toChar());
|
||||||
|
});
|
||||||
|
connect(previousCharButton, &QPushButton::clicked, [=]{
|
||||||
|
auto currentIndex = _characterSelector->currentIndex();
|
||||||
|
if (currentIndex > 0) {
|
||||||
|
_characterSelector->setCurrentIndex(currentIndex - 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
connect(nextCharButton, &QPushButton::clicked, [=]{
|
||||||
|
auto currentIndex = _characterSelector->currentIndex();
|
||||||
|
if (currentIndex < (_characterSelector->count()-1)) {
|
||||||
|
_characterSelector->setCurrentIndex(currentIndex + 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
previewSettingsLayout->addStretch();
|
previewSettingsLayout->addStretch();
|
||||||
previewSettingsLayout->addWidget(new QLabel(tr("Overlay Mode:")));
|
previewSettingsLayout->addWidget(new QLabel(tr("Overlay Mode:")));
|
||||||
_overlaySelector = new QComboBox();
|
_overlaySelector = new QComboBox();
|
||||||
|
|
|
@ -23,13 +23,18 @@
|
||||||
class BitmapPreview;
|
class BitmapPreview;
|
||||||
class Converter;
|
class Converter;
|
||||||
class QComboBox;
|
class QComboBox;
|
||||||
|
class QFrame;
|
||||||
|
|
||||||
|
|
||||||
|
/// A panel with the scrollable bitmap preview.
|
||||||
|
///
|
||||||
class BitmapPanel : public QWidget
|
class BitmapPanel : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/// Create the panel.
|
||||||
|
///
|
||||||
explicit BitmapPanel(QWidget *parent = nullptr);
|
explicit BitmapPanel(QWidget *parent = nullptr);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -41,11 +46,34 @@ public:
|
||||||
///
|
///
|
||||||
void setConverter(const Converter *converter);
|
void setConverter(const Converter *converter);
|
||||||
|
|
||||||
private:
|
/// Set the current character set.
|
||||||
void initializeUi();
|
///
|
||||||
|
void setCharacters(const QString &characters);
|
||||||
|
|
||||||
|
/// Set the current parameter.
|
||||||
|
///
|
||||||
|
void setParameter(const QVariantMap ¶meter);
|
||||||
|
|
||||||
|
/// Get the current selected character
|
||||||
|
///
|
||||||
|
QChar selectedCharacter() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/// Initialize all UI elements.
|
||||||
|
///
|
||||||
|
void initializeUi();
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
/// Emitted if the selected character changes.
|
||||||
|
///
|
||||||
|
void selectedCharacterChanged(QChar c);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const Converter *_converter; ///< The current converter.
|
||||||
|
QString _characters; ///< The list of characters to convert.
|
||||||
BitmapPreview *_bitmapPreview; ///< The bitmap preview;
|
BitmapPreview *_bitmapPreview; ///< The bitmap preview;
|
||||||
|
QFrame *_fontConversionTools; ///< The area with tools for font conversion.
|
||||||
|
QComboBox *_characterSelector; ///< The selector for a single character.
|
||||||
QComboBox *_overlaySelector; ///< The selector for the overlays.
|
QComboBox *_overlaySelector; ///< The selector for the overlays.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -48,9 +48,7 @@ void BitmapPreview::setImage(const QImage &image)
|
||||||
if (_image != image) {
|
if (_image != image) {
|
||||||
_image = image;
|
_image = image;
|
||||||
_pixmap = QPixmap::fromImage(image);
|
_pixmap = QPixmap::fromImage(image);
|
||||||
if (_converter != nullptr) {
|
updateGeneratedSize();
|
||||||
setGeneratedSize(_converter->generatedSize(_image.size()));
|
|
||||||
}
|
|
||||||
recalculate();
|
recalculate();
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
@ -80,9 +78,18 @@ void BitmapPreview::setConverter(const Converter *converter)
|
||||||
{
|
{
|
||||||
if (_converter != converter) {
|
if (_converter != converter) {
|
||||||
_converter = converter;
|
_converter = converter;
|
||||||
if (_converter != nullptr) {
|
updateGeneratedSize();
|
||||||
setGeneratedSize(_converter->generatedSize(_image.size()));
|
update();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BitmapPreview::setParameter(const QVariantMap ¶meter)
|
||||||
|
{
|
||||||
|
if (_parameter != parameter) {
|
||||||
|
_parameter = parameter;
|
||||||
|
updateGeneratedSize();
|
||||||
|
recalculate();
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,7 +125,7 @@ void BitmapPreview::paintEvent(QPaintEvent *pe)
|
||||||
p.setOpacity(1.0);
|
p.setOpacity(1.0);
|
||||||
p.translate(x, y);
|
p.translate(x, y);
|
||||||
OverlayPainter op(&p, pe->rect(), _displayFactor, _pixmap.size(), _generatedSize);
|
OverlayPainter op(&p, pe->rect(), _displayFactor, _pixmap.size(), _generatedSize);
|
||||||
_converter->paintOverlay(op, _overlayMode, _image);
|
_converter->paintOverlay(op, _overlayMode, _image, _parameter);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
p.setPen(Qt::white);
|
p.setPen(Qt::white);
|
||||||
|
@ -134,6 +141,16 @@ void BitmapPreview::resizeEvent(QResizeEvent *e)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BitmapPreview::updateGeneratedSize()
|
||||||
|
{
|
||||||
|
if (_converter != nullptr && _converter->mode() == Converter::Mode::Bitmap) {
|
||||||
|
setGeneratedSize(_converter->generatedSize(_image.size(), _parameter));
|
||||||
|
} else {
|
||||||
|
setGeneratedSize(_image.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void BitmapPreview::recalculate()
|
void BitmapPreview::recalculate()
|
||||||
{
|
{
|
||||||
if (_pixmap.isNull()) {
|
if (_pixmap.isNull()) {
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include <QtWidgets/QWidget>
|
#include <QtWidgets/QWidget>
|
||||||
#include <QtGui/QImage>
|
#include <QtGui/QImage>
|
||||||
#include <QtGui/QPixmap>
|
#include <QtGui/QPixmap>
|
||||||
|
#include <QtCore/QVariantMap>
|
||||||
|
|
||||||
|
|
||||||
class Converter;
|
class Converter;
|
||||||
|
@ -49,6 +50,10 @@ public:
|
||||||
///
|
///
|
||||||
void setConverter(const Converter *converter);
|
void setConverter(const Converter *converter);
|
||||||
|
|
||||||
|
/// Set the current parameter.
|
||||||
|
///
|
||||||
|
void setParameter(const QVariantMap ¶meter);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QSize sizeHint() const override;
|
QSize sizeHint() const override;
|
||||||
QSize minimumSizeHint() const override;
|
QSize minimumSizeHint() const override;
|
||||||
|
@ -58,6 +63,10 @@ protected: // QWidget interface
|
||||||
void resizeEvent(QResizeEvent *event) override;
|
void resizeEvent(QResizeEvent *event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/// update the generated size
|
||||||
|
///
|
||||||
|
void updateGeneratedSize();
|
||||||
|
|
||||||
/// Recalculate all sizes
|
/// Recalculate all sizes
|
||||||
///
|
///
|
||||||
void recalculate();
|
void recalculate();
|
||||||
|
@ -74,5 +83,6 @@ private:
|
||||||
QSize _minimumSize; ///< The preferred size of this widget.
|
QSize _minimumSize; ///< The preferred size of this widget.
|
||||||
OverlayMode _overlayMode; ///< The overlay mode.
|
OverlayMode _overlayMode; ///< The overlay mode.
|
||||||
const Converter *_converter; ///< The current converter.
|
const Converter *_converter; ///< The current converter.
|
||||||
|
QVariantMap _parameter; ///< The current set of parameter.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -29,12 +29,18 @@ QString Converter::displayName() const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QSize Converter::generatedSize(const QSize &imageSize) const
|
QSize Converter::generatedSize(const QSize &imageSize, const QVariantMap&) const
|
||||||
{
|
{
|
||||||
return imageSize;
|
return imageSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ParameterDefinitionPtr Converter::createParameterDefinition() const
|
||||||
|
{
|
||||||
|
return ParameterDefinition::create();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
LegendDataPtr Converter::legendData(OverlayMode) const
|
LegendDataPtr Converter::legendData(OverlayMode) const
|
||||||
{
|
{
|
||||||
auto ld = LegendData::create();
|
auto ld = LegendData::create();
|
||||||
|
@ -43,7 +49,7 @@ LegendDataPtr Converter::legendData(OverlayMode) const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Converter::paintOverlay(OverlayPainter &op, OverlayMode, const QImage&) const
|
void Converter::paintOverlay(OverlayPainter &op, OverlayMode, const QImage&, const QVariantMap&) const
|
||||||
{
|
{
|
||||||
op.drawPixelOutline(op.imageRect(), colorBitmapSizeOriginal, 1, 2);
|
op.drawPixelOutline(op.imageRect(), colorBitmapSizeOriginal, 1, 2);
|
||||||
if (op.generatedSize().isValid() && !op.generatedSize().isEmpty()) {
|
if (op.generatedSize().isValid() && !op.generatedSize().isEmpty()) {
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "LegendData.hpp"
|
#include "LegendData.hpp"
|
||||||
#include "OverlayPainter.hpp"
|
#include "OverlayPainter.hpp"
|
||||||
#include "OverlayMode.hpp"
|
#include "OverlayMode.hpp"
|
||||||
|
#include "ParameterDefinition.hpp"
|
||||||
|
|
||||||
#include <QtGui/QImage>
|
#include <QtGui/QImage>
|
||||||
#include <QtCore/QObject>
|
#include <QtCore/QObject>
|
||||||
|
@ -30,10 +31,17 @@
|
||||||
///
|
///
|
||||||
class Converter
|
class Converter
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
enum class Mode {
|
||||||
|
Bitmap,
|
||||||
|
Font
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Create a new converter.
|
/// Create a new converter.
|
||||||
///
|
///
|
||||||
/// @param displayName The name displayed in the UI for this coonverter.
|
/// @param displayName The name displayed in the UI for this coonverter.
|
||||||
|
/// @param mode The converter mode.
|
||||||
///
|
///
|
||||||
Converter(const QString &displayName);
|
Converter(const QString &displayName);
|
||||||
|
|
||||||
|
@ -46,21 +54,21 @@ public:
|
||||||
///
|
///
|
||||||
QString displayName() const;
|
QString displayName() const;
|
||||||
|
|
||||||
|
/// Get the mode for this converter.
|
||||||
|
///
|
||||||
|
virtual Mode mode() const = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Return the size of the generated bitmap data.
|
/// Return the size of the generated bitmap data.
|
||||||
///
|
///
|
||||||
/// @param imageSize The size of the image.
|
/// @param imageSize The size of the image.
|
||||||
/// @return The size of the generated bitmap data.
|
/// @return The size of the generated bitmap data.
|
||||||
///
|
///
|
||||||
virtual QSize generatedSize(const QSize &imageSize) const;
|
virtual QSize generatedSize(const QSize &imageSize, const QVariantMap ¶meter) const;
|
||||||
|
|
||||||
/// Generate the code from the given image.
|
/// Create the parameter definition for the converter.
|
||||||
///
|
///
|
||||||
/// @param image The image to convert.
|
virtual ParameterDefinitionPtr createParameterDefinition() const;
|
||||||
/// @param parameter A map with parameters passed to this converter.
|
|
||||||
/// @return The generated code.
|
|
||||||
///
|
|
||||||
virtual QString generateCode(const QImage &image, const QVariantMap ¶meter) const = 0;
|
|
||||||
|
|
||||||
/// Return a legend for the bitmap preview.
|
/// Return a legend for the bitmap preview.
|
||||||
///
|
///
|
||||||
|
@ -71,8 +79,9 @@ public:
|
||||||
/// @param p The painter.
|
/// @param p The painter.
|
||||||
/// @param mode The overlay mode (never `None`).
|
/// @param mode The overlay mode (never `None`).
|
||||||
/// @param image The image.
|
/// @param image The image.
|
||||||
|
/// @param parameter The current set of parameter.
|
||||||
///
|
///
|
||||||
virtual void paintOverlay(OverlayPainter &p, OverlayMode mode, const QImage &image) const;
|
virtual void paintOverlay(OverlayPainter &p, OverlayMode mode, const QImage &image, const QVariantMap ¶meter) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// The color for the image frame.
|
/// The color for the image frame.
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
|
|
||||||
ConverterFramebuf::ConverterFramebuf(const QString &displayName)
|
ConverterFramebuf::ConverterFramebuf(const QString &displayName)
|
||||||
: Converter(displayName)
|
: BitmapConverter(displayName)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,12 +17,12 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
#include "Converter.hpp"
|
#include "BitmapConverter.hpp"
|
||||||
|
|
||||||
|
|
||||||
/// Base class of framebuf converters.
|
/// Base class of framebuf converters.
|
||||||
///
|
///
|
||||||
class ConverterFramebuf : public Converter
|
class ConverterFramebuf : public BitmapConverter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ConverterFramebuf(const QString &displayName);
|
ConverterFramebuf(const QString &displayName);
|
||||||
|
|
|
@ -25,124 +25,29 @@ ConverterFramebufMono::ConverterFramebufMono(
|
||||||
int unitSize)
|
int unitSize)
|
||||||
:
|
:
|
||||||
ConverterFramebuf(displayName),
|
ConverterFramebuf(displayName),
|
||||||
_unitOrientation(unitOrientation),
|
MonoTools(unitOrientation, bitDirection, unitSize)
|
||||||
_bitDirection(bitDirection),
|
|
||||||
_unitSize(unitSize)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QSize ConverterFramebufMono::generatedSize(const QSize &imageSize) const
|
QSize ConverterFramebufMono::generatedSize(const QSize &imageSize, const QVariantMap ¶meter) const
|
||||||
{
|
{
|
||||||
if (_unitOrientation == UnitOrientation::Vertical) {
|
return monoGeneratedSize(imageSize, parameter);
|
||||||
if ((imageSize.height() % _unitSize) != 0) {
|
|
||||||
return QSize(imageSize.width(), ((imageSize.height()/_unitSize)+1)*_unitSize);
|
|
||||||
} else {
|
|
||||||
return imageSize;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if ((imageSize.width() % _unitSize) != 0) {
|
|
||||||
return QSize(((imageSize.width()/_unitSize)+1)*_unitSize, imageSize.height());
|
|
||||||
} else {
|
|
||||||
return imageSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LegendDataPtr ConverterFramebufMono::legendData(OverlayMode mode) const
|
LegendDataPtr ConverterFramebufMono::legendData(OverlayMode mode) const
|
||||||
{
|
{
|
||||||
auto data = ConverterFramebuf::legendData(mode);
|
auto data = ConverterFramebuf::legendData(mode);
|
||||||
if (mode == OverlayMode::BitAssigments) {
|
addMonoLegendData(data, mode);
|
||||||
data->addEntry(colorBitAssignment1, colorBitAssignment2, QObject::tr("Bit Assignment"));
|
|
||||||
} else {
|
|
||||||
data->addEntry(colorPixelInterpretation, QObject::tr("Pixel Interpretation"));
|
|
||||||
}
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ConverterFramebufMono::paintOverlay(OverlayPainter &p, OverlayMode mode, const QImage &image) const
|
void ConverterFramebufMono::paintOverlay(OverlayPainter &p, OverlayMode mode, const QImage &image, const QVariantMap ¶meter) const
|
||||||
{
|
{
|
||||||
ConverterFramebuf::paintOverlay(p, mode, image);
|
ConverterFramebuf::paintOverlay(p, mode, image, parameter);
|
||||||
if (mode == OverlayMode::BitAssigments) {
|
monoPaintOverlay(p, mode, image, parameter);
|
||||||
const auto bitL = (_bitDirection == BitDirection::LSB ? "0" : QString::number(_unitSize-1));
|
|
||||||
const auto bitH = (_bitDirection == BitDirection::LSB ? QString::number(_unitSize-1) : "0");
|
|
||||||
bool colorFlag = false;
|
|
||||||
if (_unitOrientation == UnitOrientation::Vertical) {
|
|
||||||
for (int y = 0; y < p.imageSize().height(); y += _unitSize) {
|
|
||||||
for (int x = 0; x < p.imageSize().width(); ++x) {
|
|
||||||
QRect rect(x, y, 1, _unitSize);
|
|
||||||
if (p.arePixelUpdated(rect)) {
|
|
||||||
const auto color = colorFlag ? colorBitAssignment1 : colorBitAssignment2;
|
|
||||||
p.drawPixelOutline(rect, color, 1);
|
|
||||||
p.drawPixelText(QRect(x, y, 1, 1), color, bitL);
|
|
||||||
p.drawPixelText(QRect(x, y+_unitSize-1, 1, 1), color, bitH);
|
|
||||||
}
|
|
||||||
colorFlag = !colorFlag;
|
|
||||||
}
|
|
||||||
if (p.imageSize().width() % 2 == 0) {
|
|
||||||
colorFlag = !colorFlag;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (int y = 0; y < p.imageSize().height(); ++y) {
|
|
||||||
for (int x = 0; x < p.imageSize().width(); x += _unitSize) {
|
|
||||||
QRect rect(x, y, _unitSize, 1);
|
|
||||||
if (p.arePixelUpdated(rect)) {
|
|
||||||
const auto color = colorFlag ? colorBitAssignment1 : colorBitAssignment2;
|
|
||||||
p.drawPixelOutline(rect, color, 1);
|
|
||||||
p.drawPixelText(QRect(x, y, 1, 1), color, bitH);
|
|
||||||
p.drawPixelText(QRect(x+_unitSize-1, y, 1, 1), color, bitL);
|
|
||||||
}
|
|
||||||
colorFlag = !colorFlag;
|
|
||||||
}
|
|
||||||
if ((p.imageSize().width()/_unitSize) % 2 == 0) {
|
|
||||||
colorFlag = !colorFlag;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (mode == OverlayMode::PixelInterpretation) {
|
|
||||||
for (int y = 0; y < p.generatedSize().height(); ++y) {
|
|
||||||
for (int x = 0; x < p.generatedSize().width(); ++x) {
|
|
||||||
auto text = (getPixel(x, y, image) ? "1" : "0");
|
|
||||||
const QRect rect(x, y, 1, 1);
|
|
||||||
if (p.arePixelUpdated(rect)) {
|
|
||||||
p.drawPixelText(rect, colorPixelInterpretation, text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool ConverterFramebufMono::getPixel(int x, int y, const QImage &image)
|
|
||||||
{
|
|
||||||
if (x < 0 || y < 0 || x >= image.width() || y >= image.height()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
auto color = image.pixelColor(x, y);
|
|
||||||
float h, s, l, a;
|
|
||||||
color.getHslF(&h, &s, &l, &a);
|
|
||||||
if (a < 0.5) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return l < 0.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t ConverterFramebufMono::readUnit(int x, int y, int dx, int dy, int count, const QImage &image)
|
|
||||||
{
|
|
||||||
uint32_t result = 0;
|
|
||||||
for (int i = 0; i < count; ++i) {
|
|
||||||
result <<= 1;
|
|
||||||
if (getPixel(x, y, image)) {
|
|
||||||
result |= 0b1;
|
|
||||||
}
|
|
||||||
x += dx;
|
|
||||||
y += dy;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -17,24 +17,14 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include "MonoTools.hpp"
|
||||||
#include "ConverterFramebuf.hpp"
|
#include "ConverterFramebuf.hpp"
|
||||||
|
|
||||||
|
|
||||||
/// The base class of all mono converters
|
/// The base class of all mono converters
|
||||||
///
|
///
|
||||||
class ConverterFramebufMono : public ConverterFramebuf
|
class ConverterFramebufMono : public ConverterFramebuf, public MonoTools
|
||||||
{
|
{
|
||||||
protected:
|
|
||||||
enum class UnitOrientation {
|
|
||||||
Horizontal,
|
|
||||||
Vertical
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class BitDirection {
|
|
||||||
LSB,
|
|
||||||
MSB
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Create a new mono converter.
|
/// Create a new mono converter.
|
||||||
///
|
///
|
||||||
|
@ -49,30 +39,8 @@ public:
|
||||||
int unitSize);
|
int unitSize);
|
||||||
|
|
||||||
public: // Converter interface
|
public: // Converter interface
|
||||||
QSize generatedSize(const QSize &imageSize) const override;
|
QSize generatedSize(const QSize &imageSize, const QVariantMap ¶meter) const override;
|
||||||
LegendDataPtr legendData(OverlayMode mode) const override;
|
LegendDataPtr legendData(OverlayMode mode) const override;
|
||||||
void paintOverlay(OverlayPainter &p, OverlayMode mode, const QImage &image) const override;
|
void paintOverlay(OverlayPainter &p, OverlayMode mode, const QImage &image, const QVariantMap ¶meter) const override;
|
||||||
|
|
||||||
protected:
|
|
||||||
/// Interpret a single pixel.
|
|
||||||
///
|
|
||||||
/// Returns `false` if the pixel is out of bounds.
|
|
||||||
///
|
|
||||||
static bool getPixel(int x, int y, const QImage &image);
|
|
||||||
|
|
||||||
/// Read a single unit.
|
|
||||||
///
|
|
||||||
static uint32_t readUnit(int x, int y, int dx, int dy, int count, const QImage &image);
|
|
||||||
|
|
||||||
/// The colors for the bit assignments
|
|
||||||
///
|
|
||||||
static constexpr QColor colorBitAssignment1 = QColor(240, 40, 40);
|
|
||||||
static constexpr QColor colorBitAssignment2 = QColor(240, 80, 80);
|
|
||||||
static constexpr QColor colorPixelInterpretation = QColor(240, 240, 40);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
UnitOrientation _unitOrientation; ///< The unit orientatioon.
|
|
||||||
BitDirection _bitDirection; ///< The bit direction.
|
|
||||||
int _unitSize; ///< The number of bits per unit.
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ ConverterFramebufMonoHLSB::ConverterFramebufMonoHLSB()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QString ConverterFramebufMonoHLSB::generateCode(const QImage &image, const QVariantMap&) const
|
QString ConverterFramebufMonoHLSB::generateCode(const QImage &image, const QVariantMap ¶meter) const
|
||||||
{
|
{
|
||||||
QByteArray data;
|
QByteArray data;
|
||||||
for (int y = 0; y < image.height(); ++y) {
|
for (int y = 0; y < image.height(); ++y) {
|
||||||
|
@ -34,5 +34,5 @@ QString ConverterFramebufMonoHLSB::generateCode(const QImage &image, const QVari
|
||||||
data.append(static_cast<uint8_t>(readUnit(x, y, 1, 0, 8, image)));
|
data.append(static_cast<uint8_t>(readUnit(x, y, 1, 0, 8, image)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return createCode(data, generatedSize(image.size()), "MONO_HLSB");
|
return createCode(data, generatedSize(image.size(), parameter), "MONO_HLSB");
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ ConverterFramebufMonoHMSB::ConverterFramebufMonoHMSB()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QString ConverterFramebufMonoHMSB::generateCode(const QImage &image, const QVariantMap&) const
|
QString ConverterFramebufMonoHMSB::generateCode(const QImage &image, const QVariantMap ¶meter) const
|
||||||
{
|
{
|
||||||
QByteArray data;
|
QByteArray data;
|
||||||
for (int y = 0; y < image.height(); ++y) {
|
for (int y = 0; y < image.height(); ++y) {
|
||||||
|
@ -31,6 +31,6 @@ QString ConverterFramebufMonoHMSB::generateCode(const QImage &image, const QVari
|
||||||
data.append(static_cast<uint8_t>(readUnit(x+7, y, -1, 0, 8, image)));
|
data.append(static_cast<uint8_t>(readUnit(x+7, y, -1, 0, 8, image)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return createCode(data, generatedSize(image.size()), "MONO_HMSB");
|
return createCode(data, generatedSize(image.size(), parameter), "MONO_HMSB");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ ConverterFramebufMonoVLSB::ConverterFramebufMonoVLSB()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QString ConverterFramebufMonoVLSB::generateCode(const QImage &image, const QVariantMap&) const
|
QString ConverterFramebufMonoVLSB::generateCode(const QImage &image, const QVariantMap ¶meter) const
|
||||||
{
|
{
|
||||||
QByteArray data;
|
QByteArray data;
|
||||||
for (int y = 0; y < image.height(); y += 8) {
|
for (int y = 0; y < image.height(); y += 8) {
|
||||||
|
@ -31,6 +31,6 @@ QString ConverterFramebufMonoVLSB::generateCode(const QImage &image, const QVari
|
||||||
data.append(static_cast<uint8_t>(readUnit(x, y+7, 0, -1, 8, image)));
|
data.append(static_cast<uint8_t>(readUnit(x, y+7, 0, -1, 8, image)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return createCode(data, generatedSize(image.size()), "MONO_VLSB");
|
return createCode(data, generatedSize(image.size(), parameter), "MONO_VLSB");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,149 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#include "FontConverter.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
FontConverter::FontConverter(const QString &displayName)
|
||||||
|
: Converter(displayName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Converter::Mode FontConverter::mode() const
|
||||||
|
{
|
||||||
|
return Mode::Font;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ParameterDefinitionPtr FontConverter::createParameterDefinition() const
|
||||||
|
{
|
||||||
|
auto pd = Converter::createParameterDefinition();
|
||||||
|
pd->addIntegerSize("maximumSize", QObject::tr("Maximum Size"),
|
||||||
|
QSize(12, 16), QSize(8, 8), QSize(256, 256));
|
||||||
|
pd->addIntegerPosition("charOffset", QObject::tr("Char Offset"),
|
||||||
|
QPoint(0, 0), QPoint(-256, -256), QPoint(256, 256));
|
||||||
|
pd->addCheckbox("convertMono", QObject::tr("Convert to Mono"), false);
|
||||||
|
pd->addInteger("convertMonoThreshold", QObject::tr("Conversion Threshold"), 128, 0, 255);
|
||||||
|
pd->addCheckbox("preferBitmapFont", QObject::tr("Prefer Bitmap Font"), false);
|
||||||
|
pd->addCheckbox("noAntialiasFont", QObject::tr("No Antialias Font"), false);
|
||||||
|
pd->addCheckbox("trimLeft", QObject::tr("Trim Left Side"), true);
|
||||||
|
pd->addCheckbox("trimRight", QObject::tr("Trim Right Side"), true);
|
||||||
|
pd->addCheckbox("invertFont", QObject::tr("Invert the Font"), false);
|
||||||
|
return pd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QImage FontConverter::generateImage(const QFont &font, QChar c, const QVariantMap ¶meter) const
|
||||||
|
{
|
||||||
|
auto maximumSize = parameter["maximumSize"].toSize();
|
||||||
|
if (!maximumSize.isValid() || maximumSize.isNull()) {
|
||||||
|
maximumSize = QSize(8, 8);
|
||||||
|
}
|
||||||
|
const auto charOffset = parameter["charOffset"].toPoint();
|
||||||
|
QImage result(maximumSize, QImage::Format_ARGB32_Premultiplied);
|
||||||
|
result.setDevicePixelRatio(1.0);
|
||||||
|
QPainter p;
|
||||||
|
p.begin(&result);
|
||||||
|
p.fillRect(result.rect(), Qt::white);
|
||||||
|
p.setRenderHint(QPainter::TextAntialiasing, false);
|
||||||
|
auto fontForDrawing = font;
|
||||||
|
int fontStyleStrategy = 0;
|
||||||
|
if (parameter["preferBitmapFont"].toBool()) {
|
||||||
|
fontStyleStrategy |= QFont::PreferBitmap;
|
||||||
|
}
|
||||||
|
if (parameter["noAntialiasFont"].toBool()) {
|
||||||
|
fontStyleStrategy |= QFont::NoAntialias;
|
||||||
|
}
|
||||||
|
fontStyleStrategy |= QFont::NoSubpixelAntialias;
|
||||||
|
fontForDrawing.setStyleStrategy(static_cast<QFont::StyleStrategy>(fontStyleStrategy));
|
||||||
|
QFontMetrics fontMetrics(fontForDrawing);
|
||||||
|
auto charBoundingRect = fontMetrics.boundingRect(c);
|
||||||
|
// Make sure the first pixel is in the bitmap, draw baseline at ascent.
|
||||||
|
QPoint targetPoint(-charBoundingRect.left(), fontMetrics.ascent());
|
||||||
|
targetPoint += charOffset;
|
||||||
|
p.setFont(fontForDrawing);
|
||||||
|
p.drawText(targetPoint, QString(c));
|
||||||
|
p.end();
|
||||||
|
// Postprocess the font.
|
||||||
|
const auto threshold = static_cast<unsigned int>(parameter["convertMonoThreshold"].toInt());
|
||||||
|
if (parameter["convertMono"].toBool()) {
|
||||||
|
for (int x = 0; x < result.width(); ++x) {
|
||||||
|
for (int y = 0; y < result.height(); ++y) {
|
||||||
|
const auto pixel = result.pixel(x, y);
|
||||||
|
if ((pixel & 0xff) <= threshold) {
|
||||||
|
result.setPixel(x, y, qRgb(0, 0, 0));
|
||||||
|
} else {
|
||||||
|
result.setPixel(x, y, qRgb(255, 255, 255));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Trim the font.
|
||||||
|
const auto trimLeft = parameter["trimLeft"].toBool();
|
||||||
|
const auto trimRight = parameter["trimRight"].toBool();
|
||||||
|
if (trimLeft || trimRight) {
|
||||||
|
auto resultRect = result.rect();
|
||||||
|
int leftTrim = 0;
|
||||||
|
int rightTrim = 0;
|
||||||
|
if (trimLeft) {
|
||||||
|
for (int x = 0; x < result.width(); ++x) {
|
||||||
|
bool hasPixelSet = false;
|
||||||
|
for (int y = 0; y < result.height(); ++y) {
|
||||||
|
const auto pixel = result.pixel(x, y);
|
||||||
|
if ((pixel & 0xff) <= threshold) {
|
||||||
|
hasPixelSet = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hasPixelSet) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
leftTrim += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (trimRight) {
|
||||||
|
for (int x = result.width()-1; x >= 0; --x) {
|
||||||
|
bool hasPixelSet = false;
|
||||||
|
for (int y = 0; y < result.width(); ++y) {
|
||||||
|
const auto pixel = result.pixel(x, y);
|
||||||
|
if ((pixel & 0xff) <= threshold) {
|
||||||
|
hasPixelSet = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hasPixelSet) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rightTrim += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((resultRect.width() - leftTrim - rightTrim) <= 0) {
|
||||||
|
// The font image is empty, use one pixel line.
|
||||||
|
resultRect.setWidth(1);
|
||||||
|
} else {
|
||||||
|
resultRect = resultRect.marginsRemoved(QMargins(leftTrim, 0, rightTrim, 0));
|
||||||
|
}
|
||||||
|
if (resultRect != result.rect()) {
|
||||||
|
result = result.copy(resultRect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Invert the font.
|
||||||
|
if (parameter["invertFont"].toBool()) {
|
||||||
|
result.invertPixels();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include "Converter.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
/// The base class for all font converters.
|
||||||
|
///
|
||||||
|
class FontConverter : public Converter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// ctor
|
||||||
|
///
|
||||||
|
FontConverter(const QString &displayName);
|
||||||
|
|
||||||
|
public: // implement Converter
|
||||||
|
Mode mode() const override;
|
||||||
|
ParameterDefinitionPtr createParameterDefinition() const override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Create a bitmap for a given character.
|
||||||
|
///
|
||||||
|
/// This method should return the given character in exact the size and format it will
|
||||||
|
/// be converted as bitmap.
|
||||||
|
///
|
||||||
|
/// @param font The font for the character.
|
||||||
|
/// @param c The character to convert.
|
||||||
|
/// @param parameter The current map of parameters.
|
||||||
|
///
|
||||||
|
virtual QImage generateImage(const QFont &font, QChar c, const QVariantMap ¶meter) const;
|
||||||
|
|
||||||
|
/// Generate the code from the given font.
|
||||||
|
///
|
||||||
|
/// The string with all characters to convert is passed as parameter 'characters'.
|
||||||
|
///
|
||||||
|
/// @param font The font to convert.
|
||||||
|
/// @param parameter A map with parameters passed to this converter.
|
||||||
|
/// @return The generated code.
|
||||||
|
///
|
||||||
|
virtual QString generateCode(const QFont &font, const QVariantMap ¶meter) const = 0;
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#include "FontConverterFramebufMono.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
FontConverterFramebufMono::FontConverterFramebufMono()
|
||||||
|
:
|
||||||
|
FontConverter("MicroPython Font Mono VLSB"),
|
||||||
|
MonoTools(UnitOrientation::Vertical, BitDirection::LSB, 8)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QSize FontConverterFramebufMono::generatedSize(const QSize &imageSize, const QVariantMap ¶meter) const
|
||||||
|
{
|
||||||
|
return monoGeneratedSize(imageSize, parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString FontConverterFramebufMono::generateCode(const QFont&, const QVariantMap&) const
|
||||||
|
{
|
||||||
|
return "The generated format is not decided yet.";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LegendDataPtr FontConverterFramebufMono::legendData(OverlayMode mode) const
|
||||||
|
{
|
||||||
|
auto data = FontConverter::legendData(mode);
|
||||||
|
addMonoLegendData(data, mode);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FontConverterFramebufMono::paintOverlay(OverlayPainter &p, OverlayMode mode, const QImage &image, const QVariantMap ¶meter) const
|
||||||
|
{
|
||||||
|
FontConverter::paintOverlay(p, mode, image, parameter);
|
||||||
|
monoPaintOverlay(p, mode, image, parameter);
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include "FontConverter.hpp"
|
||||||
|
#include "MonoTools.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
/// A simple converter to create mono bitmap fonts.
|
||||||
|
///
|
||||||
|
class FontConverterFramebufMono : public FontConverter, public MonoTools
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// ctor
|
||||||
|
///
|
||||||
|
FontConverterFramebufMono();
|
||||||
|
|
||||||
|
public: // implement FontConverter
|
||||||
|
QSize generatedSize(const QSize &imageSize, const QVariantMap ¶meter) const override;
|
||||||
|
QString generateCode(const QFont &font, const QVariantMap ¶meter) const override;
|
||||||
|
LegendDataPtr legendData(OverlayMode mode) const override;
|
||||||
|
void paintOverlay(OverlayPainter &p, OverlayMode mode, const QImage &image, const QVariantMap ¶meter) const override;
|
||||||
|
};
|
||||||
|
|
334
MainWindow.cpp
334
MainWindow.cpp
|
@ -17,10 +17,12 @@
|
||||||
#include "MainWindow.hpp"
|
#include "MainWindow.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#include "ApplicationController.hpp"
|
||||||
#include "BitmapPanel.hpp"
|
#include "BitmapPanel.hpp"
|
||||||
#include "ConverterFramebufMonoVLSB.hpp"
|
#include "ConverterFramebufMonoVLSB.hpp"
|
||||||
#include "ConverterFramebufMonoHLSB.hpp"
|
#include "ConverterFramebufMonoHLSB.hpp"
|
||||||
#include "ConverterFramebufMonoHMSB.hpp"
|
#include "ConverterFramebufMonoHMSB.hpp"
|
||||||
|
#include "FontConverterFramebufMono.hpp"
|
||||||
|
|
||||||
#include <QtCore/QSettings>
|
#include <QtCore/QSettings>
|
||||||
#include <QtGui/QAction>
|
#include <QtGui/QAction>
|
||||||
|
@ -37,6 +39,11 @@
|
||||||
#include <QtWidgets/QPlainTextEdit>
|
#include <QtWidgets/QPlainTextEdit>
|
||||||
#include <QtWidgets/QScrollArea>
|
#include <QtWidgets/QScrollArea>
|
||||||
#include <QtWidgets/QSplitter>
|
#include <QtWidgets/QSplitter>
|
||||||
|
#include <QtWidgets/QFontComboBox>
|
||||||
|
#include <QtWidgets/QLineEdit>
|
||||||
|
#include <QtWidgets/QFormLayout>
|
||||||
|
#include <QtWidgets/QSpinBox>
|
||||||
|
#include <QtWidgets/QHBoxLayout>
|
||||||
#include <QtGui/QDesktopServices>
|
#include <QtGui/QDesktopServices>
|
||||||
|
|
||||||
|
|
||||||
|
@ -47,6 +54,9 @@ MainWindow::MainWindow(QWidget *parent)
|
||||||
initializeUi();
|
initializeUi();
|
||||||
initializeMenu();
|
initializeMenu();
|
||||||
loadSettings();
|
loadSettings();
|
||||||
|
onFormatChanged();
|
||||||
|
onFontChanged();
|
||||||
|
onCharactersChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,13 +70,16 @@ void MainWindow::initializeConverterList()
|
||||||
_converterList.append(new ConverterFramebufMonoVLSB());
|
_converterList.append(new ConverterFramebufMonoVLSB());
|
||||||
_converterList.append(new ConverterFramebufMonoHMSB());
|
_converterList.append(new ConverterFramebufMonoHMSB());
|
||||||
_converterList.append(new ConverterFramebufMonoHLSB());
|
_converterList.append(new ConverterFramebufMonoHLSB());
|
||||||
|
_converterList.append(new FontConverterFramebufMono());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MainWindow::initializeUi()
|
void MainWindow::initializeUi()
|
||||||
{
|
{
|
||||||
|
const int cFixedWidth = 400;
|
||||||
|
|
||||||
setMinimumSize(800, 600);
|
setMinimumSize(800, 600);
|
||||||
setWindowTitle(tr("Micropython Bitmap Tool - V%1 - Lucky Resistor").arg(qApp->applicationVersion()));
|
setWindowTitle(tr("MicroPython Bitmap Tool - V%1 - Lucky Resistor").arg(qApp->applicationVersion()));
|
||||||
|
|
||||||
auto centralWidget = new QWidget();
|
auto centralWidget = new QWidget();
|
||||||
centralWidget->setObjectName("CentralWidget");
|
centralWidget->setObjectName("CentralWidget");
|
||||||
|
@ -83,15 +96,16 @@ void MainWindow::initializeUi()
|
||||||
settingsLayout->setSpacing(4);
|
settingsLayout->setSpacing(4);
|
||||||
|
|
||||||
auto logo = new QLabel();
|
auto logo = new QLabel();
|
||||||
logo->setFixedSize(300, 250);
|
logo->setFixedSize(cFixedWidth, 100);
|
||||||
logo->setPixmap(QPixmap(":/images/AppLogo.png"));
|
logo->setPixmap(QPixmap(":/images/AppLogo.png"));
|
||||||
|
logo->setAlignment(Qt::AlignCenter);
|
||||||
settingsLayout->addWidget(logo);
|
settingsLayout->addWidget(logo);
|
||||||
auto versionLabel = new QLabel(tr("<b>Version %1</b>").arg(qApp->applicationVersion()));
|
auto versionLabel = new QLabel(tr("<b>Version %1</b>").arg(qApp->applicationVersion()));
|
||||||
versionLabel->setAlignment(Qt::AlignCenter);
|
versionLabel->setAlignment(Qt::AlignCenter);
|
||||||
settingsLayout->addWidget(versionLabel);
|
settingsLayout->addWidget(versionLabel);
|
||||||
settingsLayout->addSpacing(16);
|
settingsLayout->addSpacing(16);
|
||||||
|
|
||||||
settingsLayout->addWidget(new QLabel(tr("Generated Format:")));
|
settingsLayout->addWidget(new QLabel(tr("<b>Generated Format:</b>")));
|
||||||
_formatSelector = new QComboBox();
|
_formatSelector = new QComboBox();
|
||||||
for (auto converter : _converterList) {
|
for (auto converter : _converterList) {
|
||||||
_formatSelector->addItem(converter->displayName());
|
_formatSelector->addItem(converter->displayName());
|
||||||
|
@ -99,20 +113,96 @@ void MainWindow::initializeUi()
|
||||||
_formatSelector->setCurrentIndex(0);
|
_formatSelector->setCurrentIndex(0);
|
||||||
settingsLayout->addWidget(_formatSelector);
|
settingsLayout->addWidget(_formatSelector);
|
||||||
|
|
||||||
settingsLayout->addStretch();
|
settingsLayout->addWidget(new QLabel(tr("<b>Parameters:</b>")));
|
||||||
|
|
||||||
settingsLayout->addWidget(new QLabel(tr("<b>Loaded Bitmap Info:</b>")));
|
auto parameterScroll = new QScrollArea();
|
||||||
|
parameterScroll->setObjectName("ParameterScrollArea");
|
||||||
|
_parameterFrame = new QFrame();
|
||||||
|
_parameterFrame->setObjectName("ParameterFrame");
|
||||||
|
_parameterFrame->setFixedWidth(cFixedWidth);
|
||||||
|
_parameterLayout = new QFormLayout(_parameterFrame);
|
||||||
|
_parameterLayout->setContentsMargins(8, 8, 8, 8);
|
||||||
|
parameterScroll->setWidget(_parameterFrame);
|
||||||
|
parameterScroll->setWidgetResizable(true);
|
||||||
|
parameterScroll->setFixedWidth(cFixedWidth);
|
||||||
|
parameterScroll->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
|
||||||
|
//parameterScroll->setBackgroundRole(QPalette::Window);
|
||||||
|
settingsLayout->addWidget(parameterScroll);
|
||||||
|
|
||||||
|
_bitmapConverterFrame = new QFrame();
|
||||||
|
auto bitmapConverterLayout = new QVBoxLayout(_bitmapConverterFrame);
|
||||||
|
bitmapConverterLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
bitmapConverterLayout->setSpacing(4);
|
||||||
|
settingsLayout->addWidget(_bitmapConverterFrame);
|
||||||
|
|
||||||
|
bitmapConverterLayout->addWidget(new QLabel(tr("<b>Loaded Bitmap Info:</b>")));
|
||||||
_bitmapInfo = new QLabel(tr("No Bitmap Loaded"));
|
_bitmapInfo = new QLabel(tr("No Bitmap Loaded"));
|
||||||
_bitmapInfo->setObjectName("BitmapInfo");
|
_bitmapInfo->setObjectName("BitmapInfo");
|
||||||
_bitmapInfo->setMinimumHeight(200);
|
_bitmapInfo->setMinimumHeight(100);
|
||||||
_bitmapInfo->setAlignment(Qt::AlignTop|Qt::AlignLeft);
|
_bitmapInfo->setAlignment(Qt::AlignTop|Qt::AlignLeft);
|
||||||
settingsLayout->addWidget(_bitmapInfo);
|
bitmapConverterLayout->addWidget(_bitmapInfo);
|
||||||
|
|
||||||
auto loadButton = new QPushButton();
|
auto loadButton = new QPushButton();
|
||||||
loadButton->setText(tr("Load Bitmap"));
|
loadButton->setText(tr("Load Bitmap"));
|
||||||
settingsLayout->addWidget(loadButton);
|
bitmapConverterLayout->addWidget(loadButton);
|
||||||
connect(loadButton, &QPushButton::clicked, this, &MainWindow::onLoadBitmap);
|
connect(loadButton, &QPushButton::clicked, this, &MainWindow::onLoadBitmap);
|
||||||
|
|
||||||
|
_fontConverterFrame = new QFrame();
|
||||||
|
auto fontConverterLayout = new QVBoxLayout(_fontConverterFrame);
|
||||||
|
fontConverterLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
fontConverterLayout->setSpacing(4);
|
||||||
|
settingsLayout->addWidget(_fontConverterFrame);
|
||||||
|
|
||||||
|
fontConverterLayout->addWidget(new QLabel(tr("<b>Selected Font Info:</b>")));
|
||||||
|
_fontInfo = new QLabel(tr("No Font Seleccted"));
|
||||||
|
_fontInfo->setObjectName("FontInfo");
|
||||||
|
_fontInfo->setMinimumHeight(100);
|
||||||
|
_fontInfo->setAlignment(Qt::AlignTop|Qt::AlignLeft);
|
||||||
|
fontConverterLayout->addWidget(_fontInfo);
|
||||||
|
|
||||||
|
fontConverterLayout->addWidget(new QLabel(tr("<b>Selected Font:</b>")));
|
||||||
|
_fontSelector = new QFontComboBox();
|
||||||
|
fontConverterLayout->addWidget(_fontSelector);
|
||||||
|
auto fontDetailsLayout = new QHBoxLayout();
|
||||||
|
fontDetailsLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
fontDetailsLayout->setSpacing(4);
|
||||||
|
fontConverterLayout->addLayout(fontDetailsLayout);
|
||||||
|
_fontWeightSelector = new QComboBox();
|
||||||
|
_fontWeightSelector->addItem(tr("Thin"), static_cast<int>(QFont::Thin));
|
||||||
|
_fontWeightSelector->addItem(tr("Extra Light"), static_cast<int>(QFont::ExtraLight));
|
||||||
|
_fontWeightSelector->addItem(tr("Light"), static_cast<int>(QFont::Light));
|
||||||
|
_fontWeightSelector->addItem(tr("Normal"), static_cast<int>(QFont::Normal));
|
||||||
|
_fontWeightSelector->addItem(tr("Medium"), static_cast<int>(QFont::Medium));
|
||||||
|
_fontWeightSelector->addItem(tr("Demi Bold"), static_cast<int>(QFont::DemiBold));
|
||||||
|
_fontWeightSelector->addItem(tr("Bold"), static_cast<int>(QFont::Bold));
|
||||||
|
_fontWeightSelector->addItem(tr("Extra Bold"), static_cast<int>(QFont::ExtraBold));
|
||||||
|
_fontWeightSelector->addItem(tr("Black"), static_cast<int>(QFont::Black));
|
||||||
|
_fontWeightSelector->setCurrentIndex(3);
|
||||||
|
_fontSizeSelector = new QSpinBox();
|
||||||
|
_fontSizeSelector->setRange(4, 200);
|
||||||
|
_fontSizeSelector->setValue(12);
|
||||||
|
_fontHinting = new QComboBox();
|
||||||
|
_fontHinting->addItem(tr("Default"), static_cast<int>(QFont::PreferDefaultHinting));
|
||||||
|
_fontHinting->addItem(tr("None"), static_cast<int>(QFont::PreferNoHinting));
|
||||||
|
_fontHinting->addItem(tr("Vertical"), static_cast<int>(QFont::PreferVerticalHinting));
|
||||||
|
_fontHinting->addItem(tr("Full"), static_cast<int>(QFont::PreferFullHinting));
|
||||||
|
_fontHinting->setCurrentIndex(0);
|
||||||
|
fontDetailsLayout->addWidget(new QLabel(tr("Size:")));
|
||||||
|
fontDetailsLayout->addWidget(_fontSizeSelector);
|
||||||
|
fontDetailsLayout->addWidget(new QLabel(tr("Weight:")));
|
||||||
|
fontDetailsLayout->addWidget(_fontWeightSelector);
|
||||||
|
fontDetailsLayout->addWidget(new QLabel(tr("Hinting:")));
|
||||||
|
fontDetailsLayout->addWidget(_fontHinting);
|
||||||
|
fontConverterLayout->addWidget(new QLabel(tr("Characters to convert:")));
|
||||||
|
_fontCharacters = new QPlainTextEdit();
|
||||||
|
_fontCharacters->setFixedHeight(100);
|
||||||
|
_fontCharacters->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum);
|
||||||
|
_fontCharacters->setWordWrapMode(QTextOption::WrapAnywhere);
|
||||||
|
_fontCharacters->setPlainText("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,:;!?()+-=\"'<>");
|
||||||
|
_fontCharacters->setReadOnly(true);
|
||||||
|
fontConverterLayout->addWidget(_fontCharacters);
|
||||||
|
connect(_fontCharacters, &QPlainTextEdit::textChanged, this, &MainWindow::onCharactersChanged);
|
||||||
|
|
||||||
auto previewSplittter = new QSplitter(Qt::Vertical);
|
auto previewSplittter = new QSplitter(Qt::Vertical);
|
||||||
previewSplittter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
previewSplittter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||||
previewSplittter->setChildrenCollapsible(false);
|
previewSplittter->setChildrenCollapsible(false);
|
||||||
|
@ -133,15 +223,9 @@ void MainWindow::initializeUi()
|
||||||
_codePreview->setWordWrapMode(QTextOption::NoWrap);
|
_codePreview->setWordWrapMode(QTextOption::NoWrap);
|
||||||
codeLayout->addWidget(_codePreview);
|
codeLayout->addWidget(_codePreview);
|
||||||
|
|
||||||
#ifdef Q_OS_WIN32
|
const auto monospaceFont = gApp()->monospaceFont();
|
||||||
_codePreview->setFont(QFont("Consolas", 12));
|
_codePreview->setFont(monospaceFont);
|
||||||
#else
|
_fontCharacters->setFont(monospaceFont);
|
||||||
#ifdef Q_OS_MAC
|
|
||||||
_codePreview->setFont(QFont("Menlo", 12));
|
|
||||||
#else
|
|
||||||
_codePreview->setFont(QFont("Lucida Console", 12));
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
auto codeActions = new QFrame();
|
auto codeActions = new QFrame();
|
||||||
auto codeActionsLayout = new QHBoxLayout(codeActions);
|
auto codeActionsLayout = new QHBoxLayout(codeActions);
|
||||||
|
@ -161,11 +245,12 @@ void MainWindow::initializeUi()
|
||||||
previewSplittter->setStretchFactor(0, 4);
|
previewSplittter->setStretchFactor(0, 4);
|
||||||
previewSplittter->setStretchFactor(1, 1);
|
previewSplittter->setStretchFactor(1, 1);
|
||||||
|
|
||||||
connect(_formatSelector, &QComboBox::currentIndexChanged, [=]{
|
connect(_formatSelector, &QComboBox::currentIndexChanged, this, &MainWindow::onFormatChanged);
|
||||||
_bitmapPanel->setConverter(selectedConverter());
|
connect(_fontSelector, &QFontComboBox::currentFontChanged, this, &MainWindow::onFontChanged);
|
||||||
updateBitmapInfo();
|
connect(_fontSizeSelector, &QSpinBox::valueChanged, this, &MainWindow::onFontChanged);
|
||||||
updateCode();
|
connect(_fontWeightSelector, &QComboBox::currentIndexChanged, this, &MainWindow::onFontChanged);
|
||||||
});
|
connect(_fontHinting, &QComboBox::currentIndexChanged, this, &MainWindow::onFontChanged);
|
||||||
|
connect(_bitmapPanel, &BitmapPanel::selectedCharacterChanged, this, &MainWindow::onSelectedCharacterChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -229,6 +314,18 @@ void MainWindow::loadSettings()
|
||||||
restoreGeometry(settings.value("mainWindow.geometry").toByteArray());
|
restoreGeometry(settings.value("mainWindow.geometry").toByteArray());
|
||||||
restoreState(settings.value("mainWindow.state").toByteArray());
|
restoreState(settings.value("mainWindow.state").toByteArray());
|
||||||
_formatSelector->setCurrentIndex(settings.value("format.index").toInt(0));
|
_formatSelector->setCurrentIndex(settings.value("format.index").toInt(0));
|
||||||
|
_currentFont = QFont(settings.value("font.family", "Arial").toString());
|
||||||
|
_currentFont.setPixelSize(settings.value("font.size", 12).toInt());
|
||||||
|
_currentFont.setWeight(static_cast<QFont::Weight>(settings.value("font.weight", 500).toInt()));
|
||||||
|
_fontSelector->setCurrentFont(_currentFont);
|
||||||
|
_fontSizeSelector->setValue(_currentFont.pixelSize());
|
||||||
|
const int index = _fontWeightSelector->findData(static_cast<int>(_currentFont.weight()));
|
||||||
|
if (index >= 0) {
|
||||||
|
_fontWeightSelector->setCurrentIndex(index);
|
||||||
|
} else {
|
||||||
|
_fontWeightSelector->setCurrentIndex(3); // normal
|
||||||
|
}
|
||||||
|
_fontHinting->setCurrentIndex(settings.value("font.hinting", 0).toInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -238,6 +335,10 @@ void MainWindow::saveSettings()
|
||||||
settings.setValue("mainWindow.geometry", saveGeometry());
|
settings.setValue("mainWindow.geometry", saveGeometry());
|
||||||
settings.setValue("mainWindow.state", saveState());
|
settings.setValue("mainWindow.state", saveState());
|
||||||
settings.setValue("format.index", _formatSelector->currentIndex());
|
settings.setValue("format.index", _formatSelector->currentIndex());
|
||||||
|
settings.setValue("font.family", _currentFont.family());
|
||||||
|
settings.setValue("font.size", _currentFont.pixelSize());
|
||||||
|
settings.setValue("font.weight", static_cast<int>(_currentFont.weight()));
|
||||||
|
settings.setValue("font.hinting", _fontHinting->currentIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -251,42 +352,120 @@ Converter *MainWindow::selectedConverter() const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MainWindow::updateBitmapInfo()
|
void MainWindow::updateInfoBox()
|
||||||
{
|
{
|
||||||
QString text;
|
QString text;
|
||||||
QTextStream ts(&text);
|
QTextStream ts(&text);
|
||||||
ts << "<p>";
|
if (selectedConverter()->mode() == Converter::Mode::Bitmap) {
|
||||||
ts << "Bitmap Size: " << _currentImage.width() << "x" << _currentImage.height() << "<br>";
|
ts << "<p>";
|
||||||
ts << "Bit Depth: " << _currentImage.depth() << "<br>";
|
ts << "Bitmap Size: " << _currentImage.width() << "x" << _currentImage.height() << "<br>";
|
||||||
ts << "Color Format: ";
|
ts << "Bit Depth: " << _currentImage.depth() << "<br>";
|
||||||
switch (_currentImage.pixelFormat().colorModel()) {
|
ts << "Color Format: ";
|
||||||
case QPixelFormat::RGB: ts << "RGB"; break;
|
switch (_currentImage.pixelFormat().colorModel()) {
|
||||||
case QPixelFormat::BGR: ts << "BGR"; break;
|
case QPixelFormat::RGB: ts << "RGB"; break;
|
||||||
case QPixelFormat::Indexed: ts << "Indexed"; break;
|
case QPixelFormat::BGR: ts << "BGR"; break;
|
||||||
case QPixelFormat::Grayscale: ts << "Grayscale"; break;
|
case QPixelFormat::Indexed: ts << "Indexed"; break;
|
||||||
case QPixelFormat::CMYK: ts << "CMYK"; break;
|
case QPixelFormat::Grayscale: ts << "Grayscale"; break;
|
||||||
case QPixelFormat::HSL: ts << "HSL"; break;
|
case QPixelFormat::CMYK: ts << "CMYK"; break;
|
||||||
case QPixelFormat::HSV: ts << "HSV"; break;
|
case QPixelFormat::HSL: ts << "HSL"; break;
|
||||||
case QPixelFormat::YUV: ts << "YUV"; break;
|
case QPixelFormat::HSV: ts << "HSV"; break;
|
||||||
case QPixelFormat::Alpha: ts << "Alpha"; break;
|
case QPixelFormat::YUV: ts << "YUV"; break;
|
||||||
|
case QPixelFormat::Alpha: ts << "Alpha"; break;
|
||||||
|
}
|
||||||
|
ts << "<br>";
|
||||||
|
const auto gs = selectedConverter()->generatedSize(_currentImage.size(), createParameterMap());
|
||||||
|
ts << "Generated Size: " << gs.width() << "x" << gs.height() << "</p>";
|
||||||
|
_bitmapInfo->setText(text);
|
||||||
|
} else {
|
||||||
|
ts << "<p>";
|
||||||
|
ts << "Family: " << _currentFont.family() << "<br>";
|
||||||
|
ts << "Weight: ";
|
||||||
|
switch (_currentFont.weight()) {
|
||||||
|
case QFont::Thin: ts << tr("Thin"); break;
|
||||||
|
case QFont::ExtraLight: ts << tr("Extra Light"); break;
|
||||||
|
case QFont::Light: ts << tr("Light"); break;
|
||||||
|
case QFont::Normal: ts << tr("Normal"); break;
|
||||||
|
case QFont::Medium: ts << tr("Medium"); break;
|
||||||
|
case QFont::DemiBold: ts << tr("Demi Bold"); break;
|
||||||
|
case QFont::Bold: ts << tr("Bold"); break;
|
||||||
|
case QFont::ExtraBold: ts << tr("Extra Bold"); break;
|
||||||
|
case QFont::Black: ts << tr("Black"); break;
|
||||||
|
}
|
||||||
|
ts << "<br>";
|
||||||
|
ts << "Pixel Size: " << _currentFont.pixelSize() << "<br>";
|
||||||
|
ts << "</p>";
|
||||||
|
_fontInfo->setText(text);
|
||||||
}
|
}
|
||||||
ts << "<br>";
|
|
||||||
const auto gs = selectedConverter()->generatedSize(_currentImage.size());
|
|
||||||
ts << "Generated Size: " << gs.width() << "x" << gs.height() << "</p>";
|
|
||||||
_bitmapInfo->setText(text);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MainWindow::updateCode()
|
void MainWindow::updateCode()
|
||||||
{
|
{
|
||||||
QString code;
|
QString code;
|
||||||
if (!_currentImage.isNull()) {
|
if (selectedConverter()->mode() == Converter::Mode::Bitmap) {
|
||||||
code = selectedConverter()->generateCode(_currentImage, QVariantMap());
|
auto bitmapConverter = static_cast<BitmapConverter*>(selectedConverter());
|
||||||
|
if (!_currentImage.isNull()) {
|
||||||
|
code = bitmapConverter->generateCode(_currentImage, QVariantMap());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
auto fontConverter = static_cast<FontConverter*>(selectedConverter());
|
||||||
|
code = fontConverter->generateCode(_currentFont, createParameterMap());
|
||||||
}
|
}
|
||||||
_codePreview->setPlainText(code);
|
_codePreview->setPlainText(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MainWindow::updateParameters()
|
||||||
|
{
|
||||||
|
auto converter = selectedConverter();
|
||||||
|
if (converter == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace the current parameter definition.
|
||||||
|
_displayedParameters = converter->createParameterDefinition();
|
||||||
|
// Remove the previous UI
|
||||||
|
while (_parameterLayout->count() > 0) {
|
||||||
|
auto item = _parameterLayout->takeAt(0);
|
||||||
|
delete item;
|
||||||
|
}
|
||||||
|
for (auto w : _parameterFrame->findChildren<QWidget*>()) {
|
||||||
|
w->deleteLater();
|
||||||
|
}
|
||||||
|
// Build the new parameter UI.
|
||||||
|
if (_displayedParameters->parameterList().isEmpty()) {
|
||||||
|
auto label = new QLabel();
|
||||||
|
label->setText(tr("No Parameters"));
|
||||||
|
_parameterLayout->addWidget(label);
|
||||||
|
} else {
|
||||||
|
for (const auto ¶meter : _displayedParameters->parameterList()) {
|
||||||
|
auto pw = parameterFactory.createWidget(parameter);
|
||||||
|
pw->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
||||||
|
pw->setObjectName(parameter->identifier());
|
||||||
|
_parameterLayout->addRow(parameter->label() + ":", pw);
|
||||||
|
connect(pw, &ParameterWidget::valueChanged, this, &MainWindow::onParameterChanged);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto stretchItem = new QWidget();
|
||||||
|
stretchItem->setFixedWidth(10);
|
||||||
|
stretchItem->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
|
||||||
|
_parameterLayout->addRow(stretchItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QVariantMap MainWindow::createParameterMap() const
|
||||||
|
{
|
||||||
|
QVariantMap result;
|
||||||
|
result["characters"] = _fontCharacters->toPlainText();
|
||||||
|
result["font"] = _currentFont;
|
||||||
|
result["char"] = _bitmapPanel->selectedCharacter();
|
||||||
|
for (auto pw : _parameterFrame->findChildren<ParameterWidget*>()) {
|
||||||
|
result[pw->objectName()] = pw->value();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void MainWindow::onLoadBitmap()
|
void MainWindow::onLoadBitmap()
|
||||||
{
|
{
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
|
@ -320,11 +499,78 @@ void MainWindow::onLoadBitmap()
|
||||||
_currentImage = newImage;
|
_currentImage = newImage;
|
||||||
_bitmapPanel->setImage(newImage);
|
_bitmapPanel->setImage(newImage);
|
||||||
_bitmapPanel->setConverter(selectedConverter());
|
_bitmapPanel->setConverter(selectedConverter());
|
||||||
updateBitmapInfo();
|
updateInfoBox();
|
||||||
updateCode();
|
updateCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MainWindow::onFormatChanged()
|
||||||
|
{
|
||||||
|
const auto converter = selectedConverter();
|
||||||
|
_bitmapPanel->setConverter(converter);
|
||||||
|
if (converter->mode() == Converter::Mode::Bitmap) {
|
||||||
|
_bitmapConverterFrame->setVisible(true);
|
||||||
|
_fontConverterFrame->setVisible(false);
|
||||||
|
} else {
|
||||||
|
_bitmapConverterFrame->setVisible(false);
|
||||||
|
_fontConverterFrame->setVisible(true);
|
||||||
|
}
|
||||||
|
updateParameters();
|
||||||
|
updateInfoBox();
|
||||||
|
updateCode();
|
||||||
|
_bitmapPanel->setParameter(createParameterMap());
|
||||||
|
onSelectedCharacterChanged(_bitmapPanel->selectedCharacter());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MainWindow::onFontChanged()
|
||||||
|
{
|
||||||
|
_currentFont = _fontSelector->currentFont();
|
||||||
|
_currentFont.setWeight(static_cast<QFont::Weight>(_fontWeightSelector->currentData().toInt()));
|
||||||
|
_currentFont.setPixelSize(_fontSizeSelector->value());
|
||||||
|
const auto hintingPreferences = static_cast<QFont::HintingPreference>(_fontHinting->currentData().toInt());
|
||||||
|
_currentFont.setHintingPreference(hintingPreferences);
|
||||||
|
updateInfoBox();
|
||||||
|
updateCode();
|
||||||
|
_bitmapPanel->setParameter(createParameterMap());
|
||||||
|
onSelectedCharacterChanged(_bitmapPanel->selectedCharacter());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MainWindow::onCharactersChanged()
|
||||||
|
{
|
||||||
|
auto characters = _fontCharacters->toPlainText();
|
||||||
|
_bitmapPanel->setCharacters(characters);
|
||||||
|
_bitmapPanel->setConverter(selectedConverter());
|
||||||
|
_bitmapPanel->setParameter(createParameterMap());
|
||||||
|
onSelectedCharacterChanged(_bitmapPanel->selectedCharacter());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MainWindow::onSelectedCharacterChanged(QChar c)
|
||||||
|
{
|
||||||
|
auto converter = selectedConverter();
|
||||||
|
if (converter == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (converter->mode() == Converter::Mode::Font) {
|
||||||
|
auto fontConverter = static_cast<const FontConverter*>(converter);
|
||||||
|
auto newImage = fontConverter->generateImage(_currentFont, c, createParameterMap());
|
||||||
|
_currentImage = newImage;
|
||||||
|
_bitmapPanel->setImage(newImage);
|
||||||
|
_bitmapPanel->setConverter(selectedConverter());
|
||||||
|
_bitmapPanel->setParameter(createParameterMap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MainWindow::onParameterChanged()
|
||||||
|
{
|
||||||
|
_bitmapPanel->setParameter(createParameterMap());
|
||||||
|
onSelectedCharacterChanged(_bitmapPanel->selectedCharacter());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void MainWindow::closeEvent(QCloseEvent *event)
|
void MainWindow::closeEvent(QCloseEvent *event)
|
||||||
{
|
{
|
||||||
saveSettings();
|
saveSettings();
|
||||||
|
|
|
@ -17,6 +17,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include "ParameterDefinition.hpp"
|
||||||
|
#include "ParameterFactory.hpp"
|
||||||
|
|
||||||
|
#include <QtCore/QVariantMap>
|
||||||
#include <QtWidgets/QMainWindow>
|
#include <QtWidgets/QMainWindow>
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,6 +29,11 @@ class QPlainTextEdit;
|
||||||
class QComboBox;
|
class QComboBox;
|
||||||
class QLabel;
|
class QLabel;
|
||||||
class BitmapPanel;
|
class BitmapPanel;
|
||||||
|
class QFrame;
|
||||||
|
class QFontComboBox;
|
||||||
|
class QLineEdit;
|
||||||
|
class QSpinBox;
|
||||||
|
class QFormLayout;
|
||||||
|
|
||||||
|
|
||||||
/// The main widnow
|
/// The main widnow
|
||||||
|
@ -64,26 +73,73 @@ private:
|
||||||
|
|
||||||
/// Update the bitmap info.
|
/// Update the bitmap info.
|
||||||
///
|
///
|
||||||
void updateBitmapInfo();
|
void updateInfoBox();
|
||||||
|
|
||||||
/// Update the code.
|
/// Update the code.
|
||||||
///
|
///
|
||||||
void updateCode();
|
void updateCode();
|
||||||
|
|
||||||
|
/// Update the parameter frame for the current converter.
|
||||||
|
///
|
||||||
|
void updateParameters();
|
||||||
|
|
||||||
|
/// Get the current parameters
|
||||||
|
///
|
||||||
|
QVariantMap createParameterMap() const;
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
/// Load a bitmap.
|
/// Load a bitmap.
|
||||||
///
|
///
|
||||||
void onLoadBitmap();
|
void onLoadBitmap();
|
||||||
|
|
||||||
|
/// After a new converter is selected.
|
||||||
|
///
|
||||||
|
void onFormatChanged();
|
||||||
|
|
||||||
|
/// After a new font is selected.
|
||||||
|
///
|
||||||
|
void onFontChanged();
|
||||||
|
|
||||||
|
/// After the character list has changed
|
||||||
|
///
|
||||||
|
void onCharactersChanged();
|
||||||
|
|
||||||
|
/// If the selected character changed
|
||||||
|
///
|
||||||
|
void onSelectedCharacterChanged(QChar c);
|
||||||
|
|
||||||
|
/// After a parameter has changed.
|
||||||
|
///
|
||||||
|
void onParameterChanged();
|
||||||
|
|
||||||
protected: // Implement QWidget
|
protected: // Implement QWidget
|
||||||
void closeEvent(QCloseEvent *event) override;
|
void closeEvent(QCloseEvent *event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
ParameterFactory parameterFactory; ///< The parameter factory.
|
||||||
|
|
||||||
QComboBox *_formatSelector; ///< The format selector.
|
QComboBox *_formatSelector; ///< The format selector.
|
||||||
QPlainTextEdit *_codePreview; ///< The generated code.
|
QPlainTextEdit *_codePreview; ///< The generated code.
|
||||||
BitmapPanel *_bitmapPanel; ///< The bitmap panel.
|
BitmapPanel *_bitmapPanel; ///< The bitmap panel.
|
||||||
QImage _currentImage; ///< The current loaded image
|
|
||||||
|
QFrame *_parameterFrame; ///< The frame with the parameters.
|
||||||
|
QFormLayout *_parameterLayout; ///< The parameter layout.
|
||||||
|
ParameterDefinitionPtr _displayedParameters; ///< The currently displayed parameters.
|
||||||
|
|
||||||
|
QImage _currentImage; ///< The current loaded image for bitmap converters.
|
||||||
|
QFont _currentFont; ///< The currently selected font for font converters.
|
||||||
|
|
||||||
|
QFrame *_bitmapConverterFrame; ///< The frame for bitmap converters.
|
||||||
QLabel *_bitmapInfo; ///< The label with the image info.
|
QLabel *_bitmapInfo; ///< The label with the image info.
|
||||||
|
|
||||||
|
QFrame *_fontConverterFrame; ///< The frame for font converters.
|
||||||
|
QLabel *_fontInfo; ///< The label with the font info.
|
||||||
|
QFontComboBox *_fontSelector; ///< The combo box to select a new font.
|
||||||
|
QComboBox *_fontWeightSelector; ///< The selector for the font weight.
|
||||||
|
QSpinBox *_fontSizeSelector; ///< The selector for the used font size.
|
||||||
|
QComboBox *_fontHinting; ///< The hinting settings for the font.
|
||||||
|
QPlainTextEdit *_fontCharacters; ///< The characters of the font to be converted.
|
||||||
|
|
||||||
QList<Converter*> _converterList; ///< A list of available converters.
|
QList<Converter*> _converterList; ///< A list of available converters.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ QT += core gui
|
||||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||||
|
|
||||||
CONFIG += c++17
|
CONFIG += c++17
|
||||||
|
CONFIG += sdk_no_version_check
|
||||||
|
|
||||||
TARGET = "MicroPythonBitmapTool"
|
TARGET = "MicroPythonBitmapTool"
|
||||||
|
|
||||||
|
@ -11,6 +12,8 @@ TARGET = "MicroPythonBitmapTool"
|
||||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
|
ApplicationController.cpp \
|
||||||
|
BitmapConverter.cpp \
|
||||||
BitmapPanel.cpp \
|
BitmapPanel.cpp \
|
||||||
BitmapPreview.cpp \
|
BitmapPreview.cpp \
|
||||||
Converter.cpp \
|
Converter.cpp \
|
||||||
|
@ -19,13 +22,22 @@ SOURCES += \
|
||||||
ConverterFramebufMonoHLSB.cpp \
|
ConverterFramebufMonoHLSB.cpp \
|
||||||
ConverterFramebufMonoHMSB.cpp \
|
ConverterFramebufMonoHMSB.cpp \
|
||||||
ConverterFramebufMonoVLSB.cpp \
|
ConverterFramebufMonoVLSB.cpp \
|
||||||
|
FontConverter.cpp \
|
||||||
|
FontConverterFramebufMono.cpp \
|
||||||
LegendData.cpp \
|
LegendData.cpp \
|
||||||
LegendEntry.cpp \
|
LegendEntry.cpp \
|
||||||
|
MonoTools.cpp \
|
||||||
OverlayPainter.cpp \
|
OverlayPainter.cpp \
|
||||||
|
ParameterDefinition.cpp \
|
||||||
|
ParameterEntry.cpp \
|
||||||
|
ParameterFactory.cpp \
|
||||||
|
ParameterWidget.cpp \
|
||||||
main.cpp \
|
main.cpp \
|
||||||
MainWindow.cpp
|
MainWindow.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
|
ApplicationController.hpp \
|
||||||
|
BitmapConverter.hpp \
|
||||||
BitmapPanel.hpp \
|
BitmapPanel.hpp \
|
||||||
BitmapPreview.hpp \
|
BitmapPreview.hpp \
|
||||||
Converter.hpp \
|
Converter.hpp \
|
||||||
|
@ -34,11 +46,19 @@ HEADERS += \
|
||||||
ConverterFramebufMonoHLSB.hpp \
|
ConverterFramebufMonoHLSB.hpp \
|
||||||
ConverterFramebufMonoHMSB.hpp \
|
ConverterFramebufMonoHMSB.hpp \
|
||||||
ConverterFramebufMonoVLSB.hpp \
|
ConverterFramebufMonoVLSB.hpp \
|
||||||
|
FontConverter.hpp \
|
||||||
|
FontConverterFramebufMono.hpp \
|
||||||
LegendData.hpp \
|
LegendData.hpp \
|
||||||
LegendEntry.hpp \
|
LegendEntry.hpp \
|
||||||
MainWindow.hpp \
|
MainWindow.hpp \
|
||||||
|
MonoTools.hpp \
|
||||||
OverlayMode.hpp \
|
OverlayMode.hpp \
|
||||||
OverlayPainter.hpp
|
OverlayPainter.hpp \
|
||||||
|
ParameterDefinition.hpp \
|
||||||
|
ParameterEntry.hpp \
|
||||||
|
ParameterFactory.hpp \
|
||||||
|
ParameterType.hpp \
|
||||||
|
ParameterWidget.hpp
|
||||||
|
|
||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
data/data.qrc
|
data/data.qrc
|
||||||
|
|
|
@ -0,0 +1,134 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#include "MonoTools.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
MonoTools::MonoTools(MonoTools::UnitOrientation unitOrientation, MonoTools::BitDirection bitDirection, int unitSize)
|
||||||
|
: _unitOrientation(unitOrientation), _bitDirection(bitDirection), _unitSize(unitSize)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MonoTools::addMonoLegendData(LegendDataPtr data, OverlayMode mode) const
|
||||||
|
{
|
||||||
|
if (mode == OverlayMode::BitAssigments) {
|
||||||
|
data->addEntry(colorBitAssignment1, colorBitAssignment2, QObject::tr("Bit Assignment"));
|
||||||
|
} else {
|
||||||
|
data->addEntry(colorPixelInterpretation, QObject::tr("Pixel Interpretation"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QSize MonoTools::monoGeneratedSize(const QSize &imageSize, const QVariantMap&) const
|
||||||
|
{
|
||||||
|
if (_unitOrientation == UnitOrientation::Vertical) {
|
||||||
|
if ((imageSize.height() % _unitSize) != 0) {
|
||||||
|
return QSize(imageSize.width(), ((imageSize.height()/_unitSize)+1)*_unitSize);
|
||||||
|
} else {
|
||||||
|
return imageSize;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ((imageSize.width() % _unitSize) != 0) {
|
||||||
|
return QSize(((imageSize.width()/_unitSize)+1)*_unitSize, imageSize.height());
|
||||||
|
} else {
|
||||||
|
return imageSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MonoTools::monoPaintOverlay(OverlayPainter &p, OverlayMode mode, const QImage &image, const QVariantMap&) const
|
||||||
|
{
|
||||||
|
if (mode == OverlayMode::BitAssigments) {
|
||||||
|
const auto bitL = (_bitDirection == BitDirection::LSB ? "0" : QString::number(_unitSize-1));
|
||||||
|
const auto bitH = (_bitDirection == BitDirection::LSB ? QString::number(_unitSize-1) : "0");
|
||||||
|
bool colorFlag = false;
|
||||||
|
if (_unitOrientation == UnitOrientation::Vertical) {
|
||||||
|
for (int y = 0; y < p.imageSize().height(); y += _unitSize) {
|
||||||
|
for (int x = 0; x < p.imageSize().width(); ++x) {
|
||||||
|
QRect rect(x, y, 1, _unitSize);
|
||||||
|
if (p.arePixelUpdated(rect)) {
|
||||||
|
const auto color = colorFlag ? colorBitAssignment1 : colorBitAssignment2;
|
||||||
|
p.drawPixelOutline(rect, color, 1);
|
||||||
|
p.drawPixelText(QRect(x, y, 1, 1), color, bitL);
|
||||||
|
p.drawPixelText(QRect(x, y+_unitSize-1, 1, 1), color, bitH);
|
||||||
|
}
|
||||||
|
colorFlag = !colorFlag;
|
||||||
|
}
|
||||||
|
if (p.imageSize().width() % 2 == 0) {
|
||||||
|
colorFlag = !colorFlag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int y = 0; y < p.imageSize().height(); ++y) {
|
||||||
|
for (int x = 0; x < p.imageSize().width(); x += _unitSize) {
|
||||||
|
QRect rect(x, y, _unitSize, 1);
|
||||||
|
if (p.arePixelUpdated(rect)) {
|
||||||
|
const auto color = colorFlag ? colorBitAssignment1 : colorBitAssignment2;
|
||||||
|
p.drawPixelOutline(rect, color, 1);
|
||||||
|
p.drawPixelText(QRect(x, y, 1, 1), color, bitH);
|
||||||
|
p.drawPixelText(QRect(x+_unitSize-1, y, 1, 1), color, bitL);
|
||||||
|
}
|
||||||
|
colorFlag = !colorFlag;
|
||||||
|
}
|
||||||
|
if ((p.imageSize().width()/_unitSize) % 2 == 0) {
|
||||||
|
colorFlag = !colorFlag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (mode == OverlayMode::PixelInterpretation) {
|
||||||
|
for (int y = 0; y < p.generatedSize().height(); ++y) {
|
||||||
|
for (int x = 0; x < p.generatedSize().width(); ++x) {
|
||||||
|
auto text = (getPixel(x, y, image) ? "1" : "0");
|
||||||
|
const QRect rect(x, y, 1, 1);
|
||||||
|
if (p.arePixelUpdated(rect)) {
|
||||||
|
p.drawPixelText(rect, colorPixelInterpretation, text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool MonoTools::getPixel(int x, int y, const QImage &image)
|
||||||
|
{
|
||||||
|
if (x < 0 || y < 0 || x >= image.width() || y >= image.height()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto color = image.pixelColor(x, y);
|
||||||
|
float h, s, l, a;
|
||||||
|
color.getHslF(&h, &s, &l, &a);
|
||||||
|
if (a < 0.5) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return l < 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t MonoTools::readUnit(int x, int y, int dx, int dy, int count, const QImage &image)
|
||||||
|
{
|
||||||
|
uint32_t result = 0;
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
result <<= 1;
|
||||||
|
if (getPixel(x, y, image)) {
|
||||||
|
result |= 0b1;
|
||||||
|
}
|
||||||
|
x += dx;
|
||||||
|
y += dy;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include "LegendData.hpp"
|
||||||
|
#include "OverlayPainter.hpp"
|
||||||
|
#include "OverlayMode.hpp"
|
||||||
|
#include "ParameterDefinition.hpp"
|
||||||
|
|
||||||
|
#include <QtGui/QColor>
|
||||||
|
#include <QtGui/QImage>
|
||||||
|
|
||||||
|
|
||||||
|
class MonoTools
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class UnitOrientation {
|
||||||
|
Horizontal,
|
||||||
|
Vertical
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class BitDirection {
|
||||||
|
LSB,
|
||||||
|
MSB
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// ctor
|
||||||
|
///
|
||||||
|
MonoTools(UnitOrientation unitOrientation,
|
||||||
|
BitDirection bitDirection,
|
||||||
|
int unitSize);
|
||||||
|
|
||||||
|
/// Legend data for mono conversion
|
||||||
|
///
|
||||||
|
void addMonoLegendData(LegendDataPtr data, OverlayMode mode) const;
|
||||||
|
|
||||||
|
/// The generated size for mono conversion.
|
||||||
|
///
|
||||||
|
QSize monoGeneratedSize(const QSize &imageSize, const QVariantMap ¶meter) const;
|
||||||
|
|
||||||
|
/// Paint overlay for mono data.
|
||||||
|
///
|
||||||
|
void monoPaintOverlay(OverlayPainter &p, OverlayMode mode, const QImage &image, const QVariantMap ¶meter) const;
|
||||||
|
|
||||||
|
/// Interpret a single pixel.
|
||||||
|
///
|
||||||
|
/// Returns `false` if the pixel is out of bounds.
|
||||||
|
///
|
||||||
|
static bool getPixel(int x, int y, const QImage &image);
|
||||||
|
|
||||||
|
/// Read a single unit.
|
||||||
|
///
|
||||||
|
static uint32_t readUnit(int x, int y, int dx, int dy, int count, const QImage &image);
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// The colors for the bit assignments
|
||||||
|
///
|
||||||
|
static constexpr QColor colorBitAssignment1 = QColor(240, 40, 40);
|
||||||
|
static constexpr QColor colorBitAssignment2 = QColor(240, 80, 80);
|
||||||
|
static constexpr QColor colorPixelInterpretation = QColor(240, 240, 40);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
UnitOrientation _unitOrientation; ///< The unit orientatioon.
|
||||||
|
BitDirection _bitDirection; ///< The bit direction.
|
||||||
|
int _unitSize; ///< The number of bits per unit.
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#include "ParameterDefinition.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
ParameterDefinitionPtr ParameterDefinition::create()
|
||||||
|
{
|
||||||
|
return ParameterDefinitionPtr(new ParameterDefinition());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ParameterDefinition::addCheckbox(
|
||||||
|
const QString &identifier,
|
||||||
|
const QString &label,
|
||||||
|
bool defaultValue)
|
||||||
|
{
|
||||||
|
QVariantMap settings;
|
||||||
|
settings["default"] = defaultValue;
|
||||||
|
_parameterList.append(ParameterEntry::create(
|
||||||
|
ParameterType::Checkbox, identifier, label, settings));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ParameterDefinition::addInteger(
|
||||||
|
const QString &identifier,
|
||||||
|
const QString &label,
|
||||||
|
int defaultValue,
|
||||||
|
int minimum,
|
||||||
|
int maximum)
|
||||||
|
{
|
||||||
|
QVariantMap settings;
|
||||||
|
settings["default"] = defaultValue;
|
||||||
|
settings["minimum"] = minimum;
|
||||||
|
settings["maximum"] = maximum;
|
||||||
|
_parameterList.append(ParameterEntry::create(ParameterType::IntegerValue, identifier, label, settings));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ParameterDefinition::addIntegerSize(const QString &identifier, const QString &label, QSize defaultValue, QSize minimum, QSize maximum)
|
||||||
|
{
|
||||||
|
QVariantMap settings;
|
||||||
|
settings["default"] = defaultValue;
|
||||||
|
settings["minimum"] = minimum;
|
||||||
|
settings["maximum"] = maximum;
|
||||||
|
_parameterList.append(ParameterEntry::create(ParameterType::IntegerSize, identifier, label, settings));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ParameterDefinition::addIntegerPosition(const QString &identifier, const QString &label, QPoint defaultValue, QPoint minimum, QPoint maximum)
|
||||||
|
{
|
||||||
|
QVariantMap settings;
|
||||||
|
settings["default"] = defaultValue;
|
||||||
|
settings["minimum"] = minimum;
|
||||||
|
settings["maximum"] = maximum;
|
||||||
|
_parameterList.append(ParameterEntry::create(ParameterType::IntegerPosition, identifier, label, settings));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const ParameterDefinition::ParameterList &ParameterDefinition::parameterList() const
|
||||||
|
{
|
||||||
|
return _parameterList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ParameterDefinition::ParameterDefinition()
|
||||||
|
{
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include "ParameterEntry.hpp"
|
||||||
|
|
||||||
|
#include <QtCore/QSharedPointer>
|
||||||
|
#include <QtCore/QSize>
|
||||||
|
#include <QtCore/QPoint>
|
||||||
|
|
||||||
|
|
||||||
|
class ParameterDefinition;
|
||||||
|
using ParameterDefinitionPtr = QSharedPointer<ParameterDefinition>;
|
||||||
|
using ParameterDefinitionPtrConst = QSharedPointer<const ParameterDefinition>;
|
||||||
|
|
||||||
|
|
||||||
|
/// The definition of parameters, returned by a converter.
|
||||||
|
///
|
||||||
|
class ParameterDefinition
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// A parameter list.
|
||||||
|
///
|
||||||
|
using ParameterList = QList<ParameterEntryPtr>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Create a new parameter definition.
|
||||||
|
///
|
||||||
|
static ParameterDefinitionPtr create();
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Add a checkbox parameter.
|
||||||
|
///
|
||||||
|
void addCheckbox(const QString &identifier, const QString &label, bool defaultValue);
|
||||||
|
|
||||||
|
/// Add an integer parameter.
|
||||||
|
///
|
||||||
|
void addInteger(const QString &identifier, const QString &label, int defaultValue, int minimum, int maximum);
|
||||||
|
|
||||||
|
/// Add an integer size parameter.
|
||||||
|
///
|
||||||
|
void addIntegerSize(const QString &identifier, const QString &label, QSize defaultValue, QSize minimum, QSize maximum);
|
||||||
|
|
||||||
|
/// Add an integer position parameter.
|
||||||
|
///
|
||||||
|
void addIntegerPosition(const QString &identifier, const QString &label, QPoint defaultValue, QPoint minimum, QPoint maximum);
|
||||||
|
|
||||||
|
/// Get the parameter list.
|
||||||
|
///
|
||||||
|
const ParameterList& parameterList() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ParameterDefinition();
|
||||||
|
|
||||||
|
private:
|
||||||
|
ParameterList _parameterList; ///< The list with all parameters.
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#include "ParameterEntry.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
ParameterEntryPtr ParameterEntry::create(
|
||||||
|
ParameterType type,
|
||||||
|
const QString &identifier,
|
||||||
|
const QString &label,
|
||||||
|
const QVariantMap &settings)
|
||||||
|
{
|
||||||
|
return ParameterEntryPtr(new ParameterEntry(type, identifier, label, settings));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ParameterType ParameterEntry::type() const
|
||||||
|
{
|
||||||
|
return _type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString ParameterEntry::identifier() const
|
||||||
|
{
|
||||||
|
return _identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString ParameterEntry::label() const
|
||||||
|
{
|
||||||
|
return _label;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QVariantMap ParameterEntry::settings() const
|
||||||
|
{
|
||||||
|
return _settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ParameterEntry::ParameterEntry(
|
||||||
|
ParameterType type,
|
||||||
|
const QString &identifier,
|
||||||
|
const QString &label,
|
||||||
|
const QVariantMap &settings)
|
||||||
|
:
|
||||||
|
_type(type),
|
||||||
|
_identifier(identifier),
|
||||||
|
_label(label),
|
||||||
|
_settings(settings)
|
||||||
|
{
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include "ParameterType.hpp"
|
||||||
|
|
||||||
|
#include <QtCore/QString>
|
||||||
|
#include <QtCore/QVariantMap>
|
||||||
|
#include <QtCore/QSharedPointer>
|
||||||
|
|
||||||
|
|
||||||
|
class ParameterEntry;
|
||||||
|
using ParameterEntryPtr = QSharedPointer<ParameterEntry>;
|
||||||
|
|
||||||
|
|
||||||
|
/// One entry in the parameter definition.
|
||||||
|
///
|
||||||
|
class ParameterEntry
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static ParameterEntryPtr create(
|
||||||
|
ParameterType type,
|
||||||
|
const QString &identifier,
|
||||||
|
const QString &label,
|
||||||
|
const QVariantMap &settings);
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// The parameter type.
|
||||||
|
///
|
||||||
|
ParameterType type() const;
|
||||||
|
|
||||||
|
/// The identifier of the parameter.
|
||||||
|
///
|
||||||
|
QString identifier() const;
|
||||||
|
|
||||||
|
/// The label for the parameter.
|
||||||
|
///
|
||||||
|
QString label() const;
|
||||||
|
|
||||||
|
/// Settings for the parameter.
|
||||||
|
///
|
||||||
|
QVariantMap settings() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// Create a new raw paremeter entry.
|
||||||
|
///
|
||||||
|
ParameterEntry(
|
||||||
|
ParameterType type,
|
||||||
|
const QString &identifier,
|
||||||
|
const QString &label,
|
||||||
|
const QVariantMap &settings);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ParameterType _type;
|
||||||
|
QString _identifier;
|
||||||
|
QString _label;
|
||||||
|
QVariantMap _settings;
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#include "ParameterFactory.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
ParameterFactory::ParameterFactory()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ParameterWidget *ParameterFactory::createWidget(const ParameterEntryPtr ¶meter) const
|
||||||
|
{
|
||||||
|
switch (parameter->type()) {
|
||||||
|
case ParameterType::Checkbox:
|
||||||
|
return new CheckBoxParameter(parameter);
|
||||||
|
case ParameterType::IntegerValue:
|
||||||
|
return new IntegerParameter(parameter);
|
||||||
|
case ParameterType::IntegerSize:
|
||||||
|
return new IntegerSizeParameter(parameter);
|
||||||
|
case ParameterType::IntegerPosition:
|
||||||
|
return new IntegerPositionParameter(parameter);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include "ParameterWidget.hpp"
|
||||||
|
|
||||||
|
#include <QtWidgets/QWidget>
|
||||||
|
|
||||||
|
|
||||||
|
/// A factory to handle the generic parameters.
|
||||||
|
///
|
||||||
|
class ParameterFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ParameterFactory();
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Create the widget for to edit a parameter.
|
||||||
|
///
|
||||||
|
ParameterWidget *createWidget(const ParameterEntryPtr ¶meter) const;
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
/// The parameter type.
|
||||||
|
///
|
||||||
|
enum class ParameterType {
|
||||||
|
Checkbox, ///< A boolean parameter
|
||||||
|
IntegerValue, ///< An integer value.
|
||||||
|
IntegerSize, ///< A size value
|
||||||
|
IntegerPosition, ///< A position value.
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,173 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#include "ParameterWidget.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#include <QtWidgets/QHBoxLayout>
|
||||||
|
#include <QtWidgets/QSpinBox>
|
||||||
|
#include <QtWidgets/QCheckBox>
|
||||||
|
#include <QtWidgets/QLabel>
|
||||||
|
|
||||||
|
|
||||||
|
ParameterWidget::ParameterWidget(const ParameterEntryPtr ¶meter, QWidget *parent)
|
||||||
|
: QWidget(parent), _currentValue(parameter->settings()["default"])
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CheckBoxParameter::CheckBoxParameter(const ParameterEntryPtr ¶meter, QWidget *parent)
|
||||||
|
: ParameterWidget(parameter, parent)
|
||||||
|
{
|
||||||
|
auto mainLayout = new QHBoxLayout(this);
|
||||||
|
mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
mainLayout->setSpacing(2);
|
||||||
|
_value = new QCheckBox();
|
||||||
|
mainLayout->addWidget(_value);
|
||||||
|
_value->setChecked(_currentValue.toBool());
|
||||||
|
connect(_value, &QCheckBox::toggled, this, &CheckBoxParameter::valueChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QVariant CheckBoxParameter::value() const
|
||||||
|
{
|
||||||
|
return static_cast<bool>(_value->isChecked());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CheckBoxParameter::setValue(const QVariant &value)
|
||||||
|
{
|
||||||
|
if (value != _currentValue) {
|
||||||
|
_currentValue = value;
|
||||||
|
_value->setChecked(value.toBool());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IntegerParameter::IntegerParameter(const ParameterEntryPtr ¶meter, QWidget *parent)
|
||||||
|
: ParameterWidget(parameter, parent)
|
||||||
|
{
|
||||||
|
auto mainLayout = new QHBoxLayout(this);
|
||||||
|
mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
mainLayout->setSpacing(2);
|
||||||
|
_value = new QSpinBox();
|
||||||
|
_value->setRange(
|
||||||
|
parameter->settings()["minimum"].toInt(),
|
||||||
|
parameter->settings()["maximum"].toInt()
|
||||||
|
);
|
||||||
|
mainLayout->addWidget(_value);
|
||||||
|
_value->setValue(_currentValue.toInt());
|
||||||
|
connect(_value, &QSpinBox::valueChanged, this, &CheckBoxParameter::valueChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QVariant IntegerParameter::value() const
|
||||||
|
{
|
||||||
|
return _value->value();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void IntegerParameter::setValue(const QVariant &value)
|
||||||
|
{
|
||||||
|
if (value != _currentValue) {
|
||||||
|
_value->setValue(value.toInt());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IntegerSizeParameter::IntegerSizeParameter(const ParameterEntryPtr ¶meter, QWidget *parent)
|
||||||
|
: ParameterWidget(parameter, parent)
|
||||||
|
{
|
||||||
|
auto mainLayout = new QHBoxLayout(this);
|
||||||
|
mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
mainLayout->setSpacing(2);
|
||||||
|
mainLayout->addWidget(new QLabel(tr("W:")));
|
||||||
|
_a = new QSpinBox();
|
||||||
|
_a->setRange(
|
||||||
|
parameter->settings()["minimum"].toSize().width(),
|
||||||
|
parameter->settings()["maximum"].toSize().width()
|
||||||
|
);
|
||||||
|
mainLayout->addWidget(_a);
|
||||||
|
_a->setValue(_currentValue.toSize().width());
|
||||||
|
connect(_a, &QSpinBox::valueChanged, this, &CheckBoxParameter::valueChanged);
|
||||||
|
mainLayout->addWidget(new QLabel(tr("H:")));
|
||||||
|
_b = new QSpinBox();
|
||||||
|
_b->setRange(
|
||||||
|
parameter->settings()["minimum"].toSize().height(),
|
||||||
|
parameter->settings()["maximum"].toSize().height()
|
||||||
|
);
|
||||||
|
mainLayout->addWidget(_b);
|
||||||
|
_b->setValue(_currentValue.toSize().height());
|
||||||
|
connect(_b, &QSpinBox::valueChanged, this, &CheckBoxParameter::valueChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QVariant IntegerSizeParameter::value() const
|
||||||
|
{
|
||||||
|
return QSize(_a->value(), _b->value());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void IntegerSizeParameter::setValue(const QVariant &value)
|
||||||
|
{
|
||||||
|
if (_currentValue != value) {
|
||||||
|
_a->setValue(value.toSize().width());
|
||||||
|
_b->setValue(value.toSize().height());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IntegerPositionParameter::IntegerPositionParameter(const ParameterEntryPtr ¶meter, QWidget *parent)
|
||||||
|
: ParameterWidget(parameter, parent)
|
||||||
|
{
|
||||||
|
auto mainLayout = new QHBoxLayout(this);
|
||||||
|
mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
mainLayout->setSpacing(2);
|
||||||
|
mainLayout->addWidget(new QLabel(tr("X:")));
|
||||||
|
_a = new QSpinBox();
|
||||||
|
_a->setRange(
|
||||||
|
parameter->settings()["minimum"].toPoint().x(),
|
||||||
|
parameter->settings()["maximum"].toPoint().x()
|
||||||
|
);
|
||||||
|
mainLayout->addWidget(_a);
|
||||||
|
_a->setValue(_currentValue.toPoint().x());
|
||||||
|
connect(_a, &QSpinBox::valueChanged, this, &CheckBoxParameter::valueChanged);
|
||||||
|
mainLayout->addWidget(new QLabel(tr("Y:")));
|
||||||
|
_b = new QSpinBox();
|
||||||
|
_b->setRange(
|
||||||
|
parameter->settings()["minimum"].toPoint().y(),
|
||||||
|
parameter->settings()["maximum"].toPoint().y()
|
||||||
|
);
|
||||||
|
mainLayout->addWidget(_b);
|
||||||
|
_b->setValue(_currentValue.toPoint().y());
|
||||||
|
connect(_b, &QSpinBox::valueChanged, this, &CheckBoxParameter::valueChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QVariant IntegerPositionParameter::value() const
|
||||||
|
{
|
||||||
|
return QPoint(_a->value(), _b->value());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void IntegerPositionParameter::setValue(const QVariant &value)
|
||||||
|
{
|
||||||
|
if (_currentValue != value) {
|
||||||
|
_a->setValue(value.toPoint().x());
|
||||||
|
_b->setValue(value.toPoint().y());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
//
|
||||||
|
// (c)2021 by Lucky Resistor. https://luckyresistor.me/
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include "ParameterEntry.hpp"
|
||||||
|
|
||||||
|
#include <QtWidgets/QWidget>
|
||||||
|
|
||||||
|
|
||||||
|
class QCheckBox;
|
||||||
|
class QSpinBox;
|
||||||
|
|
||||||
|
|
||||||
|
/// The base class of all parameter widgets.
|
||||||
|
///
|
||||||
|
class ParameterWidget : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Create the widget.
|
||||||
|
///
|
||||||
|
ParameterWidget(const ParameterEntryPtr ¶meter, QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
/// Get the current value for the widget.
|
||||||
|
///
|
||||||
|
virtual QVariant value() const = 0;
|
||||||
|
|
||||||
|
/// Set the value for this widget.
|
||||||
|
///
|
||||||
|
virtual void setValue(const QVariant &value) = 0;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
/// Emitted if the value for this parameter changes.
|
||||||
|
///
|
||||||
|
void valueChanged();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QVariant _currentValue; ///< Buffer to limit signals.
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class CheckBoxParameter : public ParameterWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
CheckBoxParameter(const ParameterEntryPtr ¶meter, QWidget *parent = nullptr);
|
||||||
|
QVariant value() const override;
|
||||||
|
void setValue(const QVariant &value) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QCheckBox *_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class IntegerParameter : public ParameterWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
IntegerParameter(const ParameterEntryPtr ¶meter, QWidget *parent = nullptr);
|
||||||
|
QVariant value() const override;
|
||||||
|
void setValue(const QVariant &value) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QSpinBox *_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class IntegerSizeParameter : public ParameterWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
IntegerSizeParameter(const ParameterEntryPtr ¶meter, QWidget *parent = nullptr);
|
||||||
|
QVariant value() const override;
|
||||||
|
void setValue(const QVariant &value) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QSpinBox *_a;
|
||||||
|
QSpinBox *_b;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class IntegerPositionParameter : public ParameterWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
IntegerPositionParameter(const ParameterEntryPtr ¶meter, QWidget *parent = nullptr);
|
||||||
|
QVariant value() const override;
|
||||||
|
void setValue(const QVariant &value) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QSpinBox *_a;
|
||||||
|
QSpinBox *_b;
|
||||||
|
};
|
||||||
|
|
BIN
data/AppLogo.png
BIN
data/AppLogo.png
Plik binarny nie jest wyświetlany.
Przed Szerokość: | Wysokość: | Rozmiar: 8.6 KiB Po Szerokość: | Wysokość: | Rozmiar: 4.8 KiB |
Plik binarny nie jest wyświetlany.
Przed Szerokość: | Wysokość: | Rozmiar: 19 KiB Po Szerokość: | Wysokość: | Rozmiar: 9.5 KiB |
Plik binarny nie jest wyświetlany.
Przed Szerokość: | Wysokość: | Rozmiar: 30 KiB Po Szerokość: | Wysokość: | Rozmiar: 14 KiB |
|
@ -14,8 +14,16 @@
|
||||||
color: #f8f8f8;
|
color: #f8f8f8;
|
||||||
}
|
}
|
||||||
|
|
||||||
#BitmapInfo {
|
#BitmapInfo, #FontInfo {
|
||||||
border: 1px solid rgba(0,0,0,0.25);
|
border: 1px solid rgba(0,0,0,0.25);
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
margin: 0px 0px 16px 0px;
|
margin: 0px 0px 16px 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ParameterScrollArea {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ParameterFrame {
|
||||||
|
background-color: #616875;
|
||||||
|
}
|
||||||
|
|
10
main.cpp
10
main.cpp
|
@ -14,16 +14,19 @@
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
//
|
//
|
||||||
#include "MainWindow.hpp"
|
|
||||||
|
|
||||||
|
#include "ApplicationController.hpp"
|
||||||
|
|
||||||
#include <QtWidgets/QApplication>
|
#include <QtWidgets/QApplication>
|
||||||
#include <QtCore/QFile>
|
#include <QtCore/QFile>
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
QApplication a(argc, argv);
|
QApplication a(argc, argv);
|
||||||
a.setApplicationName("MicroPython Bitmap Tool");
|
a.setApplicationName("MicroPython Bitmap Tool");
|
||||||
a.setApplicationVersion("1.0.1");
|
a.setApplicationVersion("1.2.0");
|
||||||
a.setApplicationDisplayName("MicroPython Bitmap Tool");
|
a.setApplicationDisplayName("MicroPython Bitmap Tool");
|
||||||
a.setOrganizationDomain("luckyresistor.me");
|
a.setOrganizationDomain("luckyresistor.me");
|
||||||
a.setOrganizationName("Lucky Resistoor");
|
a.setOrganizationName("Lucky Resistoor");
|
||||||
|
@ -32,7 +35,6 @@ int main(int argc, char *argv[])
|
||||||
a.setStyleSheet(QString::fromUtf8(styleSheet.readAll()));
|
a.setStyleSheet(QString::fromUtf8(styleSheet.readAll()));
|
||||||
styleSheet.close();
|
styleSheet.close();
|
||||||
|
|
||||||
MainWindow w;
|
ApplicationController app;
|
||||||
w.show();
|
|
||||||
return a.exec();
|
return a.exec();
|
||||||
}
|
}
|
||||||
|
|
Ładowanie…
Reference in New Issue