qpdfviewsb/sources/psmodel.cpp

326 lines
8.1 KiB
C++

/*
Copyright 2013 Alexander Volkov
Copyright 2013 Adam Reichold
This file is part of qpdfview.
qpdfview 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 2 of the License, or
(at your option) any later version.
qpdfview 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 qpdfview. If not, see <http://www.gnu.org/licenses/>.
*/
#include "psmodel.h"
#include <QFile>
#include <QFormLayout>
#include <qmath.h>
#include <QSettings>
#include <QSpinBox>
#include <libspectre/spectre-document.h>
namespace
{
using namespace qpdfview;
using namespace qpdfview::Model;
namespace Defaults
{
const int graphicsAntialiasBits = 4;
const int textAntialiasBits = 2;
} // Defaults
} // anonymous
namespace qpdfview
{
namespace Model
{
PsPage::PsPage(QMutex* mutex, SpectrePage* page, SpectreRenderContext* renderContext) :
m_mutex(mutex),
m_page(page),
m_renderContext(renderContext)
{
}
PsPage::~PsPage()
{
spectre_page_free(m_page);
m_page = 0;
}
QSizeF PsPage::size() const
{
QMutexLocker mutexLocker(m_mutex);
int w;
int h;
spectre_page_get_size(m_page, &w, &h);
return QSizeF(w, h);
}
QImage PsPage::render(qreal horizontalResolution, qreal verticalResolution, Rotation rotation, QRect boundingRect) const
{
QMutexLocker mutexLocker(m_mutex);
double xscale;
double yscale;
switch(rotation)
{
default:
case RotateBy0:
case RotateBy180:
xscale = horizontalResolution / 72.0;
yscale = verticalResolution / 72.0;
break;
case RotateBy90:
case RotateBy270:
xscale = verticalResolution / 72.0;
yscale = horizontalResolution / 72.0;
break;
}
spectre_render_context_set_scale(m_renderContext, xscale, yscale);
switch(rotation)
{
default:
case RotateBy0:
spectre_render_context_set_rotation(m_renderContext, 0);
break;
case RotateBy90:
spectre_render_context_set_rotation(m_renderContext, 90);
break;
case RotateBy180:
spectre_render_context_set_rotation(m_renderContext, 180);
break;
case RotateBy270:
spectre_render_context_set_rotation(m_renderContext, 270);
break;
}
int w;
int h;
spectre_page_get_size(m_page, &w, &h);
w = qRound(w * xscale);
h = qRound(h * yscale);
if(rotation == RotateBy90 || rotation == RotateBy270)
{
qSwap(w, h);
}
unsigned char* pageData = 0;
int rowLength = 0;
spectre_page_render(m_page, m_renderContext, &pageData, &rowLength);
if (spectre_page_status(m_page) != SPECTRE_STATUS_SUCCESS)
{
free(pageData);
pageData = 0;
return QImage();
}
QImage auxiliaryImage(pageData, rowLength / 4, h, QImage::Format_RGB32);
QImage image(boundingRect.isNull() ? auxiliaryImage.copy(0, 0, w, h) : auxiliaryImage.copy(boundingRect));
free(pageData);
pageData = 0;
return image;
}
PsDocument::PsDocument(SpectreDocument* document, SpectreRenderContext* renderContext) :
m_mutex(),
m_document(document),
m_renderContext(renderContext)
{
}
PsDocument::~PsDocument()
{
spectre_render_context_free(m_renderContext);
m_renderContext = 0;
spectre_document_free(m_document);
m_document = 0;
}
int PsDocument::numberOfPages() const
{
QMutexLocker mutexLocker(&m_mutex);
return spectre_document_get_n_pages(m_document);
}
Page* PsDocument::page(int index) const
{
QMutexLocker mutexLocker(&m_mutex);
if(SpectrePage* page = spectre_document_get_page(m_document, index))
{
return new PsPage(&m_mutex, page, m_renderContext);
}
return 0;
}
QStringList PsDocument::saveFilter() const
{
QMutexLocker mutexLocker(&m_mutex);
if(spectre_document_is_eps(m_document))
{
return QStringList() << QLatin1String("Encapsulated PostScript (*.eps)");
}
else
{
return QStringList() << QLatin1String("PostScript (*.ps)");
}
}
bool PsDocument::canSave() const
{
return true;
}
bool PsDocument::save(const QString& filePath, bool withChanges) const
{
Q_UNUSED(withChanges)
QMutexLocker mutexLocker(&m_mutex);
spectre_document_save(m_document, QFile::encodeName(filePath));
return spectre_document_status(m_document) == SPECTRE_STATUS_SUCCESS;
}
bool PsDocument::canBePrintedUsingCUPS() const
{
return true;
}
Properties PsDocument::properties() const
{
Properties properties;
QMutexLocker mutexLocker(&m_mutex);
const QString title = QString::fromLocal8Bit(spectre_document_get_title(m_document));
const QString createdFor = QString::fromLocal8Bit(spectre_document_get_for(m_document));
const QString creator = QString::fromLocal8Bit(spectre_document_get_creator(m_document));
const QString creationDate = QString::fromLocal8Bit(spectre_document_get_creation_date(m_document));
const QString format = QString::fromLocal8Bit(spectre_document_get_format(m_document));
const QString languageLevel = QString::number(spectre_document_get_language_level(m_document));
properties.push_back(qMakePair(tr("Title"), title));
properties.push_back(qMakePair(tr("Created for"), createdFor));
properties.push_back(qMakePair(tr("Creator"), creator));
properties.push_back(qMakePair(tr("Creation date"), creationDate));
properties.push_back(qMakePair(tr("Format"), format));
properties.push_back(qMakePair(tr("Language level"), languageLevel));
return properties;
}
} // Model
PsSettingsWidget::PsSettingsWidget(QSettings* settings, QWidget* parent) : SettingsWidget(parent),
m_settings(settings)
{
m_layout = new QFormLayout(this);
// graphics antialias bits
m_graphicsAntialiasBitsSpinBox = new QSpinBox(this);
m_graphicsAntialiasBitsSpinBox->setRange(1, 4);
m_graphicsAntialiasBitsSpinBox->setValue(m_settings->value("graphicsAntialiasBits", Defaults::graphicsAntialiasBits).toInt());
m_layout->addRow(tr("Graphics antialias bits:"), m_graphicsAntialiasBitsSpinBox);
// text antialias bits
m_textAntialiasBitsSpinBox = new QSpinBox(this);
m_textAntialiasBitsSpinBox->setRange(1, 2);
m_textAntialiasBitsSpinBox->setValue(m_settings->value("textAntialiasBits", Defaults::textAntialiasBits).toInt());
m_layout->addRow(tr("Text antialias bits:"), m_textAntialiasBitsSpinBox);
}
void PsSettingsWidget::accept()
{
m_settings->setValue("graphicsAntialiasBits", m_graphicsAntialiasBitsSpinBox->value());
m_settings->setValue("textAntialiasBits", m_textAntialiasBitsSpinBox->value());
}
void PsSettingsWidget::reset()
{
m_graphicsAntialiasBitsSpinBox->setValue(Defaults::graphicsAntialiasBits);
m_textAntialiasBitsSpinBox->setValue(Defaults::textAntialiasBits);
}
PsPlugin::PsPlugin(QObject* parent) : QObject(parent)
{
setObjectName("PsPlugin");
m_settings = new QSettings("qpdfview", "ps-plugin", this);
}
Model::Document* PsPlugin::loadDocument(const QString& filePath) const
{
SpectreDocument* document = spectre_document_new();
spectre_document_load(document, QFile::encodeName(filePath));
if (spectre_document_status(document) != SPECTRE_STATUS_SUCCESS)
{
spectre_document_free(document);
return 0;
}
SpectreRenderContext* renderContext = spectre_render_context_new();
spectre_render_context_set_antialias_bits(renderContext,
m_settings->value("graphicsAntialiasBits", Defaults::graphicsAntialiasBits).toInt(),
m_settings->value("textAntialiasBits", Defaults::textAntialiasBits).toInt());
return new Model::PsDocument(document, renderContext);
}
SettingsWidget* PsPlugin::createSettingsWidget(QWidget* parent) const
{
return new PsSettingsWidget(m_settings, parent);
}
} // qpdfview
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
Q_EXPORT_PLUGIN2(qpdfview_ps, qpdfview::PsPlugin)
#endif // QT_VERSION