mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-06-05 21:59:17 +02:00
Issue #118: Move compiler and draw space controller
This commit is contained in:
@@ -57,13 +57,19 @@ add_library(Pdf4QtLibWidgets SHARED
|
||||
sources/pdfwidgetformmanager.cpp
|
||||
sources/pdftexteditpseudowidget.cpp
|
||||
sources/pdftexteditpseudowidget.h
|
||||
sources/pdfdrawspacecontroller.cpp
|
||||
sources/pdfdrawspacecontroller.h
|
||||
sources/pdfcompiler.cpp
|
||||
sources/pdfcompiler.h
|
||||
sources/pdfdocumentdrawinterface.h
|
||||
sources/pdfwidgetsglobal.h
|
||||
)
|
||||
|
||||
include(GenerateExportHeader)
|
||||
|
||||
GENERATE_EXPORT_HEADER(Pdf4QtLibWidgets
|
||||
EXPORT_MACRO_NAME
|
||||
PDF4QTLIBCORESHARED_EXPORT
|
||||
PDF4QTLIBWIDGETSSHARED_EXPORT
|
||||
EXPORT_FILE_NAME "${CMAKE_BINARY_DIR}/${INSTALL_INCLUDEDIR}/pdf4qtlibwidgets_export.h")
|
||||
|
||||
if(PDF4QT_ENABLE_OPENGL)
|
||||
|
@@ -20,6 +20,7 @@
|
||||
#include "pdfdrawwidget.h"
|
||||
#include "pdfutils.h"
|
||||
#include "pdfcompiler.h"
|
||||
#include "pdfwidgetformmanager.h"
|
||||
#include "pdfdbgheap.h"
|
||||
|
||||
#include <QActionGroup>
|
||||
|
@@ -18,6 +18,7 @@
|
||||
#ifndef PDFADVANCEDTOOLS_H
|
||||
#define PDFADVANCEDTOOLS_H
|
||||
|
||||
#include "pdfwidgetsglobal.h"
|
||||
#include "pdfwidgettool.h"
|
||||
#include "pdfannotation.h"
|
||||
|
||||
@@ -29,7 +30,7 @@ namespace pdf
|
||||
/// Tool that creates 'sticky note' annotations. Multiple types of sticky
|
||||
/// notes are available, user can select a type of sticky note. When
|
||||
/// user select a point, popup window appears and user can enter a text.
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFCreateStickyNoteTool : public PDFWidgetTool
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFCreateStickyNoteTool : public PDFWidgetTool
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -52,7 +53,7 @@ private:
|
||||
TextAnnotationIcon m_icon;
|
||||
};
|
||||
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFCreateAnnotationTool : public PDFWidgetTool
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFCreateAnnotationTool : public PDFWidgetTool
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -69,7 +70,7 @@ protected:
|
||||
/// Tool that creates url link annotation. Multiple types of link highlights
|
||||
/// are available, user can select a link highlight. When link annotation
|
||||
/// is clicked, url address is triggered.
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFCreateHyperlinkTool : public PDFCreateAnnotationTool
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFCreateHyperlinkTool : public PDFCreateAnnotationTool
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -91,7 +92,7 @@ private:
|
||||
};
|
||||
|
||||
/// Tool that creates free text note without callout line.
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFCreateFreeTextTool : public PDFCreateAnnotationTool
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFCreateFreeTextTool : public PDFCreateAnnotationTool
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -109,7 +110,7 @@ private:
|
||||
};
|
||||
|
||||
/// Tool that creates line/polyline/polygon annotations.
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFCreateLineTypeTool : public PDFCreateAnnotationTool
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFCreateLineTypeTool : public PDFCreateAnnotationTool
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -160,7 +161,7 @@ private:
|
||||
};
|
||||
|
||||
/// Tool that creates ellipse annotation.
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFCreateEllipseTool : public PDFCreateAnnotationTool
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFCreateEllipseTool : public PDFCreateAnnotationTool
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -196,7 +197,7 @@ private:
|
||||
QColor m_fillColor;
|
||||
};
|
||||
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFCreateFreehandCurveTool : public PDFCreateAnnotationTool
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFCreateFreehandCurveTool : public PDFCreateAnnotationTool
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -234,7 +235,7 @@ private:
|
||||
|
||||
/// Tool that creates 'stamp' annotations. Multiple types of stamps
|
||||
/// are available, user can select a type of stamp (text).
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFCreateStampTool : public PDFWidgetTool
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFCreateStampTool : public PDFWidgetTool
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -267,7 +268,7 @@ private:
|
||||
};
|
||||
|
||||
/// Tool for highlighting of text in document
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFCreateHighlightTextTool : public PDFWidgetTool
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFCreateHighlightTextTool : public PDFWidgetTool
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -319,7 +320,7 @@ private:
|
||||
|
||||
/// Tool that creates redaction annotation from rectangle. Rectangle is not
|
||||
/// selected from the text, it is just any rectangle.
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFCreateRedactRectangleTool : public PDFCreateAnnotationTool
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFCreateRedactRectangleTool : public PDFCreateAnnotationTool
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -337,7 +338,7 @@ private:
|
||||
};
|
||||
|
||||
/// Tool for redaction of text in document. Creates redaction annotation from text selection.
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFCreateRedactTextTool : public PDFWidgetTool
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFCreateRedactTextTool : public PDFWidgetTool
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@@ -18,6 +18,7 @@
|
||||
#ifndef PDFCERTIFICATEMANAGERDIALOG_H
|
||||
#define PDFCERTIFICATEMANAGERDIALOG_H
|
||||
|
||||
#include "pdfwidgetsglobal.h"
|
||||
#include "pdfcertificatemanager.h"
|
||||
|
||||
#include <QDialog>
|
||||
@@ -33,7 +34,7 @@ class PDFCertificateManagerDialog;
|
||||
namespace pdf
|
||||
{
|
||||
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFCertificateManagerDialog : public QDialog
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFCertificateManagerDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
588
Pdf4QtLibWidgets/sources/pdfcompiler.cpp
Normal file
588
Pdf4QtLibWidgets/sources/pdfcompiler.cpp
Normal file
@@ -0,0 +1,588 @@
|
||||
// Copyright (C) 2019-2022 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT 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 Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include "pdfcompiler.h"
|
||||
#include "pdfcms.h"
|
||||
#include "pdfprogress.h"
|
||||
#include "pdfexecutionpolicy.h"
|
||||
#include "pdftextlayoutgenerator.h"
|
||||
#include "pdfdrawspacecontroller.h"
|
||||
#include "pdfdbgheap.h"
|
||||
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
|
||||
#include <execution>
|
||||
|
||||
namespace pdf
|
||||
{
|
||||
|
||||
PDFAsynchronousPageCompilerWorkerThread::PDFAsynchronousPageCompilerWorkerThread(PDFAsynchronousPageCompiler* parent) :
|
||||
QThread(parent),
|
||||
m_compiler(parent),
|
||||
m_mutex(&m_compiler->m_mutex),
|
||||
m_waitCondition(&m_compiler->m_waitCondition)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void PDFAsynchronousPageCompilerWorkerThread::run()
|
||||
{
|
||||
QMutexLocker locker(m_mutex);
|
||||
while (!isInterruptionRequested())
|
||||
{
|
||||
if (m_waitCondition->wait(locker.mutex(), QDeadlineTimer(QDeadlineTimer::Forever)))
|
||||
{
|
||||
while (!isInterruptionRequested())
|
||||
{
|
||||
std::vector<PDFAsynchronousPageCompiler::CompileTask> tasks;
|
||||
for (auto& task : m_compiler->m_tasks)
|
||||
{
|
||||
if (!task.second.finished)
|
||||
{
|
||||
tasks.push_back(task.second);
|
||||
}
|
||||
}
|
||||
|
||||
if (!tasks.empty())
|
||||
{
|
||||
locker.unlock();
|
||||
|
||||
// Perform page compilation
|
||||
auto proxy = m_compiler->getProxy();
|
||||
proxy->getFontCache()->setCacheShrinkEnabled(this, false);
|
||||
|
||||
auto compilePage = [this, proxy](PDFAsynchronousPageCompiler::CompileTask& task) -> PDFPrecompiledPage
|
||||
{
|
||||
PDFPrecompiledPage compiledPage;
|
||||
PDFCMSPointer cms = proxy->getCMSManager()->getCurrentCMS();
|
||||
PDFRenderer renderer(proxy->getDocument(), proxy->getFontCache(), cms.data(), proxy->getOptionalContentActivity(), proxy->getFeatures(), proxy->getMeshQualitySettings());
|
||||
renderer.setOperationControl(m_compiler);
|
||||
renderer.compile(&task.precompiledPage, task.pageIndex);
|
||||
task.finished = true;
|
||||
return compiledPage;
|
||||
};
|
||||
PDFExecutionPolicy::execute(PDFExecutionPolicy::Scope::Page, tasks.begin(), tasks.end(), compilePage);
|
||||
|
||||
proxy->getFontCache()->setCacheShrinkEnabled(this, true);
|
||||
|
||||
// Relock the mutex to write the tasks
|
||||
locker.relock();
|
||||
|
||||
// Now, write compiled pages
|
||||
bool isSomethingWritten = false;
|
||||
for (auto& task : tasks)
|
||||
{
|
||||
if (task.finished)
|
||||
{
|
||||
isSomethingWritten = true;
|
||||
m_compiler->m_tasks[task.pageIndex] = std::move(task);
|
||||
}
|
||||
}
|
||||
|
||||
if (isSomethingWritten)
|
||||
{
|
||||
// Why we are unlocking the mutex? Because
|
||||
// we do not want to emit signals with locked mutexes.
|
||||
// If direct connection is applied, this can lead to deadlock.
|
||||
locker.unlock();
|
||||
Q_EMIT pageCompiled();
|
||||
locker.relock();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PDFAsynchronousPageCompiler::PDFAsynchronousPageCompiler(PDFDrawWidgetProxy* proxy) :
|
||||
BaseClass(proxy),
|
||||
m_proxy(proxy)
|
||||
{
|
||||
m_cache.setMaxCost(128 * 1024 * 1024);
|
||||
}
|
||||
|
||||
PDFAsynchronousPageCompiler::~PDFAsynchronousPageCompiler()
|
||||
{
|
||||
stop(true);
|
||||
}
|
||||
|
||||
bool PDFAsynchronousPageCompiler::isOperationCancelled() const
|
||||
{
|
||||
return m_state == State::Stopping;
|
||||
}
|
||||
|
||||
void PDFAsynchronousPageCompiler::start()
|
||||
{
|
||||
switch (m_state)
|
||||
{
|
||||
case State::Inactive:
|
||||
{
|
||||
Q_ASSERT(!m_thread);
|
||||
m_state = State::Active;
|
||||
m_thread = new PDFAsynchronousPageCompilerWorkerThread(this);
|
||||
connect(m_thread, &PDFAsynchronousPageCompilerWorkerThread::pageCompiled, this, &PDFAsynchronousPageCompiler::onPageCompiled);
|
||||
m_thread->start();
|
||||
break;
|
||||
}
|
||||
|
||||
case State::Active:
|
||||
break; // We have nothing to do...
|
||||
|
||||
case State::Stopping:
|
||||
{
|
||||
// We shouldn't call this function while stopping!
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PDFAsynchronousPageCompiler::stop(bool clearCache)
|
||||
{
|
||||
switch (m_state)
|
||||
{
|
||||
case State::Inactive:
|
||||
{
|
||||
Q_ASSERT(!m_thread);
|
||||
break; // We have nothing to do...
|
||||
}
|
||||
|
||||
case State::Active:
|
||||
{
|
||||
// Stop the engine
|
||||
m_state = State::Stopping;
|
||||
|
||||
Q_ASSERT(m_thread);
|
||||
m_thread->requestInterruption();
|
||||
m_waitCondition.wakeAll();
|
||||
m_thread->wait();
|
||||
delete m_thread;
|
||||
m_thread = nullptr;
|
||||
|
||||
// It is safe to do not use mutex, because
|
||||
// we have ended the work thread.
|
||||
m_tasks.clear();
|
||||
|
||||
if (clearCache)
|
||||
{
|
||||
m_cache.clear();
|
||||
}
|
||||
|
||||
m_state = State::Inactive;
|
||||
break;
|
||||
}
|
||||
|
||||
case State::Stopping:
|
||||
{
|
||||
// We shouldn't call this function while stopping!
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PDFAsynchronousPageCompiler::reset()
|
||||
{
|
||||
stop(true);
|
||||
start();
|
||||
}
|
||||
|
||||
void PDFAsynchronousPageCompiler::setCacheLimit(int limit)
|
||||
{
|
||||
m_cache.setMaxCost(limit);
|
||||
}
|
||||
|
||||
const PDFPrecompiledPage* PDFAsynchronousPageCompiler::getCompiledPage(PDFInteger pageIndex, bool compile)
|
||||
{
|
||||
if (m_state != State::Active || !m_proxy->getDocument())
|
||||
{
|
||||
// Engine is not active, always return nullptr
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PDFPrecompiledPage* page = m_cache.object(pageIndex);
|
||||
|
||||
if (!page && compile)
|
||||
{
|
||||
QMutexLocker locker(&m_mutex);
|
||||
if (!m_tasks.count(pageIndex))
|
||||
{
|
||||
m_tasks.insert(std::make_pair(pageIndex, CompileTask(pageIndex)));
|
||||
m_waitCondition.wakeOne();
|
||||
}
|
||||
}
|
||||
|
||||
if (page)
|
||||
{
|
||||
page->markAccessed();
|
||||
}
|
||||
|
||||
return page;
|
||||
}
|
||||
|
||||
void PDFAsynchronousPageCompiler::smartClearCache(const int milisecondsLimit, const std::vector<PDFInteger>& activePages)
|
||||
{
|
||||
if (m_state != State::Active)
|
||||
{
|
||||
// Jakub Melka: Cache clearing can be done only in active state
|
||||
return;
|
||||
}
|
||||
|
||||
QMutexLocker locker(&m_mutex);
|
||||
|
||||
Q_ASSERT(std::is_sorted(activePages.cbegin(), activePages.cend()));
|
||||
|
||||
QList<PDFInteger> pageIndices = m_cache.keys();
|
||||
for (const PDFInteger pageIndex : pageIndices)
|
||||
{
|
||||
if (std::binary_search(activePages.cbegin(), activePages.cend(), pageIndex))
|
||||
{
|
||||
// We do not remove active page
|
||||
continue;
|
||||
}
|
||||
|
||||
const PDFPrecompiledPage* page = m_cache.object(pageIndex);
|
||||
if (page && page->hasExpired(milisecondsLimit))
|
||||
{
|
||||
m_cache.remove(pageIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PDFAsynchronousPageCompiler::onPageCompiled()
|
||||
{
|
||||
std::vector<PDFInteger> compiledPages;
|
||||
std::map<PDFInteger, PDFRenderError> errors;
|
||||
|
||||
{
|
||||
QMutexLocker locker(&m_mutex);
|
||||
|
||||
// Search all tasks for finished tasks
|
||||
for (auto it = m_tasks.begin(); it != m_tasks.end();)
|
||||
{
|
||||
CompileTask& task = it->second;
|
||||
if (task.finished)
|
||||
{
|
||||
if (m_state == State::Active)
|
||||
{
|
||||
// If we are in active state, try to store precompiled page
|
||||
PDFPrecompiledPage* page = new PDFPrecompiledPage(std::move(task.precompiledPage));
|
||||
page->markAccessed();
|
||||
qint64 memoryConsumptionEstimate = page->getMemoryConsumptionEstimate();
|
||||
if (m_cache.insert(it->first, page, memoryConsumptionEstimate))
|
||||
{
|
||||
compiledPages.push_back(it->first);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We can't insert page to the cache, because cache size is too small. We will
|
||||
// emit error string to inform the user, that cache is too small.
|
||||
QString message = PDFTranslationContext::tr("Precompiled page size is too high (%1 kB). Cache size is %2 kB. Increase the cache size!").arg(memoryConsumptionEstimate / 1024).arg(m_cache.maxCost() / 1024);
|
||||
errors[it->first] = PDFRenderError(RenderErrorType::Error, message);
|
||||
}
|
||||
}
|
||||
|
||||
it = m_tasks.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Just increment the counter
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& error : errors)
|
||||
{
|
||||
Q_EMIT renderingError(error.first, { error.second });
|
||||
}
|
||||
|
||||
if (!compiledPages.empty())
|
||||
{
|
||||
Q_ASSERT(std::is_sorted(compiledPages.cbegin(), compiledPages.cend()));
|
||||
Q_EMIT pageImageChanged(false, compiledPages);
|
||||
}
|
||||
}
|
||||
|
||||
PDFAsynchronousTextLayoutCompiler::PDFAsynchronousTextLayoutCompiler(PDFDrawWidgetProxy* proxy) :
|
||||
BaseClass(proxy),
|
||||
m_proxy(proxy),
|
||||
m_isRunning(false),
|
||||
m_cache(std::bind(&PDFAsynchronousTextLayoutCompiler::createTextLayout, this, std::placeholders::_1))
|
||||
{
|
||||
connect(&m_textLayoutCompileFutureWatcher, &QFutureWatcher<PDFTextLayoutStorage>::finished, this, &PDFAsynchronousTextLayoutCompiler::onTextLayoutCreated);
|
||||
}
|
||||
|
||||
void PDFAsynchronousTextLayoutCompiler::start()
|
||||
{
|
||||
switch (m_state)
|
||||
{
|
||||
case State::Inactive:
|
||||
{
|
||||
m_state = State::Active;
|
||||
break;
|
||||
}
|
||||
|
||||
case State::Active:
|
||||
break; // We have nothing to do...
|
||||
|
||||
case State::Stopping:
|
||||
{
|
||||
// We shouldn't call this function while stopping!
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PDFAsynchronousTextLayoutCompiler::stop(bool clearCache)
|
||||
{
|
||||
switch (m_state)
|
||||
{
|
||||
case State::Inactive:
|
||||
break; // We have nothing to do...
|
||||
|
||||
case State::Active:
|
||||
{
|
||||
// Stop the engine
|
||||
m_state = State::Stopping;
|
||||
m_textLayoutCompileFutureWatcher.waitForFinished();
|
||||
|
||||
if (clearCache)
|
||||
{
|
||||
m_textLayouts = std::nullopt;
|
||||
m_cache.clear();
|
||||
}
|
||||
|
||||
m_state = State::Inactive;
|
||||
break;
|
||||
}
|
||||
|
||||
case State::Stopping:
|
||||
{
|
||||
// We shouldn't call this function while stopping!
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PDFAsynchronousTextLayoutCompiler::reset()
|
||||
{
|
||||
stop(true);
|
||||
start();
|
||||
}
|
||||
|
||||
PDFTextLayout PDFAsynchronousTextLayoutCompiler::createTextLayout(PDFInteger pageIndex)
|
||||
{
|
||||
PDFTextLayout result;
|
||||
|
||||
if (isTextLayoutReady())
|
||||
{
|
||||
result = getTextLayout(pageIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_state != State::Active || !m_proxy->getDocument())
|
||||
{
|
||||
// Engine is not active, do not calculate layout
|
||||
return result;
|
||||
}
|
||||
|
||||
const PDFCatalog* catalog = m_proxy->getDocument()->getCatalog();
|
||||
if (pageIndex < 0 || pageIndex >= PDFInteger(catalog->getPageCount()))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!catalog->getPage(pageIndex))
|
||||
{
|
||||
// Invalid page index
|
||||
return result;
|
||||
}
|
||||
|
||||
const PDFPage* page = catalog->getPage(pageIndex);
|
||||
Q_ASSERT(page);
|
||||
|
||||
bool guard = false;
|
||||
m_proxy->getFontCache()->setCacheShrinkEnabled(&guard, false);
|
||||
|
||||
PDFCMSPointer cms = m_proxy->getCMSManager()->getCurrentCMS();
|
||||
PDFTextLayoutGenerator generator(m_proxy->getFeatures(), page, m_proxy->getDocument(), m_proxy->getFontCache(), cms.data(), m_proxy->getOptionalContentActivity(), QTransform(), m_proxy->getMeshQualitySettings());
|
||||
generator.processContents();
|
||||
result = generator.createTextLayout();
|
||||
m_proxy->getFontCache()->setCacheShrinkEnabled(&guard, true);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PDFTextLayout PDFAsynchronousTextLayoutCompiler::getTextLayout(PDFInteger pageIndex)
|
||||
{
|
||||
if (m_state != State::Active || !m_proxy->getDocument())
|
||||
{
|
||||
// Engine is not active, always return empty layout
|
||||
return PDFTextLayout();
|
||||
}
|
||||
|
||||
if (m_textLayouts)
|
||||
{
|
||||
return m_textLayouts->getTextLayout(pageIndex);
|
||||
}
|
||||
|
||||
return PDFTextLayout();
|
||||
}
|
||||
|
||||
PDFTextLayoutGetter PDFAsynchronousTextLayoutCompiler::getTextLayoutLazy(PDFInteger pageIndex)
|
||||
{
|
||||
return PDFTextLayoutGetter(&m_cache, pageIndex);
|
||||
}
|
||||
|
||||
PDFTextSelection PDFAsynchronousTextLayoutCompiler::getTextSelectionAll(QColor color) const
|
||||
{
|
||||
PDFTextSelection result;
|
||||
|
||||
if (m_textLayouts)
|
||||
{
|
||||
const PDFTextLayoutStorage& textLayouts = *m_textLayouts;
|
||||
|
||||
QMutex mutex;
|
||||
PDFIntegerRange<size_t> pageRange(0, textLayouts.getCount());
|
||||
auto selectPageText = [&mutex, &textLayouts, &result, color](PDFInteger pageIndex)
|
||||
{
|
||||
PDFTextLayout textLayout = textLayouts.getTextLayout(pageIndex);
|
||||
PDFTextSelectionItems items;
|
||||
|
||||
const PDFTextBlocks& blocks = textLayout.getTextBlocks();
|
||||
for (size_t blockId = 0, blockCount = blocks.size(); blockId < blockCount; ++blockId)
|
||||
{
|
||||
const PDFTextBlock& block = blocks[blockId];
|
||||
const PDFTextLines& lines = block.getLines();
|
||||
|
||||
if (!lines.empty())
|
||||
{
|
||||
const PDFTextLine& lastLine = lines.back();
|
||||
Q_ASSERT(!lastLine.getCharacters().empty());
|
||||
|
||||
PDFCharacterPointer ptrStart;
|
||||
ptrStart.pageIndex = pageIndex;
|
||||
ptrStart.blockIndex = blockId;
|
||||
ptrStart.lineIndex = 0;
|
||||
ptrStart.characterIndex = 0;
|
||||
|
||||
PDFCharacterPointer ptrEnd;
|
||||
ptrEnd.pageIndex = pageIndex;
|
||||
ptrEnd.blockIndex = blockId;
|
||||
ptrEnd.lineIndex = lines.size() - 1;
|
||||
ptrEnd.characterIndex = lastLine.getCharacters().size() - 1;
|
||||
|
||||
items.emplace_back(ptrStart, ptrEnd);
|
||||
}
|
||||
}
|
||||
|
||||
QMutexLocker lock(&mutex);
|
||||
result.addItems(qMove(items), color);
|
||||
};
|
||||
PDFExecutionPolicy::execute(PDFExecutionPolicy::Scope::Page, pageRange.begin(), pageRange.end(), selectPageText);
|
||||
}
|
||||
|
||||
result.build();
|
||||
return result;
|
||||
}
|
||||
|
||||
void PDFAsynchronousTextLayoutCompiler::makeTextLayout()
|
||||
{
|
||||
if (m_state != State::Active || !m_proxy->getDocument())
|
||||
{
|
||||
// Engine is not active, do not calculate layout
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_textLayouts.has_value())
|
||||
{
|
||||
// Value is computed already
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_isRunning)
|
||||
{
|
||||
// Text layout is already being processed
|
||||
return;
|
||||
}
|
||||
|
||||
// Jakub Melka: Mark, that we are running (test for future is not enough,
|
||||
// because future can finish before this function exits, for example)
|
||||
m_isRunning = true;
|
||||
|
||||
ProgressStartupInfo info;
|
||||
info.showDialog = true;
|
||||
info.text = tr("Indexing document contents...");
|
||||
|
||||
m_proxy->getFontCache()->setCacheShrinkEnabled(this, false);
|
||||
const PDFCatalog* catalog = m_proxy->getDocument()->getCatalog();
|
||||
m_proxy->getProgress()->start(catalog->getPageCount(), qMove(info));
|
||||
|
||||
PDFCMSPointer cms = m_proxy->getCMSManager()->getCurrentCMS();
|
||||
|
||||
auto createTextLayout = [this, cms, catalog]() -> PDFTextLayoutStorage
|
||||
{
|
||||
PDFTextLayoutStorage result(catalog->getPageCount());
|
||||
QMutex mutex;
|
||||
auto generateTextLayout = [this, &result, &mutex, cms, catalog](PDFInteger pageIndex)
|
||||
{
|
||||
if (!catalog->getPage(pageIndex))
|
||||
{
|
||||
// Invalid page index
|
||||
result.setTextLayout(pageIndex, PDFTextLayout(), &mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
const PDFPage* page = catalog->getPage(pageIndex);
|
||||
Q_ASSERT(page);
|
||||
|
||||
PDFTextLayoutGenerator generator(m_proxy->getFeatures(), page, m_proxy->getDocument(), m_proxy->getFontCache(), cms.data(), m_proxy->getOptionalContentActivity(), QTransform(), m_proxy->getMeshQualitySettings());
|
||||
generator.processContents();
|
||||
result.setTextLayout(pageIndex, generator.createTextLayout(), &mutex);
|
||||
m_proxy->getProgress()->step();
|
||||
};
|
||||
|
||||
auto pageRange = PDFIntegerRange<PDFInteger>(0, catalog->getPageCount());
|
||||
PDFExecutionPolicy::execute(PDFExecutionPolicy::Scope::Page, pageRange.begin(), pageRange.end(), generateTextLayout);
|
||||
return result;
|
||||
};
|
||||
|
||||
Q_ASSERT(!m_textLayoutCompileFuture.isRunning());
|
||||
m_textLayoutCompileFuture = QtConcurrent::run(createTextLayout);
|
||||
m_textLayoutCompileFutureWatcher.setFuture(m_textLayoutCompileFuture);
|
||||
}
|
||||
|
||||
void PDFAsynchronousTextLayoutCompiler::onTextLayoutCreated()
|
||||
{
|
||||
m_proxy->getFontCache()->setCacheShrinkEnabled(this, true);
|
||||
m_proxy->getProgress()->finish();
|
||||
m_cache.clear();
|
||||
|
||||
m_textLayouts = m_textLayoutCompileFuture.result();
|
||||
m_isRunning = false;
|
||||
Q_EMIT textLayoutChanged();
|
||||
}
|
||||
|
||||
} // namespace pdf
|
232
Pdf4QtLibWidgets/sources/pdfcompiler.h
Normal file
232
Pdf4QtLibWidgets/sources/pdfcompiler.h
Normal file
@@ -0,0 +1,232 @@
|
||||
// Copyright (C) 2019-2021 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT 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 Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef PDFCOMPILER_H
|
||||
#define PDFCOMPILER_H
|
||||
|
||||
#include "pdfwidgetsglobal.h"
|
||||
#include "pdfrenderer.h"
|
||||
#include "pdfpainter.h"
|
||||
#include "pdftextlayout.h"
|
||||
|
||||
#include <QCache>
|
||||
#include <QFuture>
|
||||
#include <QFutureWatcher>
|
||||
#include <QWaitCondition>
|
||||
|
||||
namespace pdf
|
||||
{
|
||||
class PDFDrawWidgetProxy;
|
||||
class PDFAsynchronousPageCompiler;
|
||||
|
||||
class PDFAsynchronousPageCompilerWorkerThread : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit PDFAsynchronousPageCompilerWorkerThread(PDFAsynchronousPageCompiler* parent);
|
||||
|
||||
signals:
|
||||
void pageCompiled();
|
||||
|
||||
protected:
|
||||
virtual void run() override;
|
||||
|
||||
private:
|
||||
PDFAsynchronousPageCompiler* m_compiler;
|
||||
QMutex* m_mutex;
|
||||
QWaitCondition* m_waitCondition;
|
||||
};
|
||||
|
||||
/// Asynchronous page compiler compiles pages asynchronously, and stores them in the
|
||||
/// cache. Cache size can be set. This object is designed to cooperate with
|
||||
/// draw widget proxy.
|
||||
class PDFAsynchronousPageCompiler : public QObject, public PDFOperationControl
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
using BaseClass = QObject;
|
||||
|
||||
public:
|
||||
explicit PDFAsynchronousPageCompiler(PDFDrawWidgetProxy* proxy);
|
||||
virtual ~PDFAsynchronousPageCompiler();
|
||||
|
||||
/// Starts the engine. Call this function only if the engine
|
||||
/// is stopped.
|
||||
void start();
|
||||
|
||||
/// Stops the engine and all underlying asynchronous tasks. Also
|
||||
/// clears the cache if needed. Call this function only if engine is active.
|
||||
/// Cache is cleared only, if \p clearCache parameter is being set to true.
|
||||
/// Set it to false, if "soft" document update occurs (this means change
|
||||
/// to the document, which doesn't modify page content in precompiled
|
||||
/// pages (graphic content / number of pages change).
|
||||
/// \param clearCache Clear cache
|
||||
void stop(bool clearCache);
|
||||
|
||||
/// Resets the engine - calls stop and then calls start.
|
||||
void reset();
|
||||
|
||||
/// Sets cache limit in bytes
|
||||
/// \param limit Cache limit [bytes]
|
||||
void setCacheLimit(int limit);
|
||||
|
||||
enum class State
|
||||
{
|
||||
Inactive,
|
||||
Active,
|
||||
Stopping
|
||||
};
|
||||
|
||||
/// Returns current state of compiler
|
||||
State getState() const { return m_state; }
|
||||
|
||||
/// Return proxy
|
||||
PDFDrawWidgetProxy* getProxy() const { return m_proxy; }
|
||||
|
||||
/// Tries to retrieve precompiled page from the cache. If page is not found,
|
||||
/// then nullptr is returned (no exception is thrown). If \p compile is set to true,
|
||||
/// and page is not found, and compiler is active, then new asynchronous compile
|
||||
/// task is performed.
|
||||
/// \param pageIndex Index of page
|
||||
/// \param compile Compile the page, if it is not found in the cache
|
||||
const PDFPrecompiledPage* getCompiledPage(PDFInteger pageIndex, bool compile);
|
||||
|
||||
/// Performs smart cache clear. Too old pages are removed from the cache,
|
||||
/// but only if these pages are not in active pages. Use this function to
|
||||
/// clear cache to avoid huge memory consumption.
|
||||
/// \param milisecondsLimit Pages with access time above this limit will be erased
|
||||
/// \param activePages Sorted vector of active pages, which should remain in cache
|
||||
void smartClearCache(const int milisecondsLimit, const std::vector<PDFInteger>& activePages);
|
||||
|
||||
/// Is operation being cancelled?
|
||||
virtual bool isOperationCancelled() const override;
|
||||
|
||||
signals:
|
||||
void pageImageChanged(bool all, const std::vector<pdf::PDFInteger>& pages);
|
||||
void renderingError(pdf::PDFInteger pageIndex, const QList<pdf::PDFRenderError>& errors);
|
||||
|
||||
private:
|
||||
friend class PDFAsynchronousPageCompilerWorkerThread;
|
||||
|
||||
void onPageCompiled();
|
||||
|
||||
struct CompileTask
|
||||
{
|
||||
CompileTask() = default;
|
||||
CompileTask(PDFInteger pageIndex) : pageIndex(pageIndex) { }
|
||||
|
||||
PDFInteger pageIndex = 0;
|
||||
bool finished = false;
|
||||
PDFPrecompiledPage precompiledPage;
|
||||
};
|
||||
|
||||
State m_state = State::Inactive;
|
||||
QMutex m_mutex;
|
||||
QWaitCondition m_waitCondition;
|
||||
PDFAsynchronousPageCompilerWorkerThread* m_thread = nullptr;
|
||||
|
||||
PDFDrawWidgetProxy* m_proxy;
|
||||
QCache<PDFInteger, PDFPrecompiledPage> m_cache;
|
||||
|
||||
/// This task is protected by mutex. Every access to this
|
||||
/// variable must be done with locked mutex.
|
||||
std::map<PDFInteger, CompileTask> m_tasks;
|
||||
};
|
||||
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFAsynchronousTextLayoutCompiler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
using BaseClass = QObject;
|
||||
|
||||
public:
|
||||
explicit PDFAsynchronousTextLayoutCompiler(PDFDrawWidgetProxy* proxy);
|
||||
|
||||
/// Starts the engine. Call this function only if the engine
|
||||
/// is stopped.
|
||||
void start();
|
||||
|
||||
/// Stops the engine and all underlying asynchronous tasks. Also
|
||||
/// clears the cache if parameter \p clearCache. Call this function
|
||||
/// only if engine is active. Clear cache should be set to false,
|
||||
/// only if "soft" document update appears (no text on page is being
|
||||
/// changed).
|
||||
/// \param clearCache Clear cache
|
||||
void stop(bool clearCache);
|
||||
|
||||
/// Resets the engine - calls stop and then calls start.
|
||||
void reset();
|
||||
|
||||
enum class State
|
||||
{
|
||||
Inactive,
|
||||
Active,
|
||||
Stopping
|
||||
};
|
||||
|
||||
/// Creates text layout of the page synchronously. If page index is invalid,
|
||||
/// then empty text layout is returned. Compiler must be active to get
|
||||
/// valid text layout.
|
||||
/// \param pageIndex Page index
|
||||
PDFTextLayout createTextLayout(PDFInteger pageIndex);
|
||||
|
||||
/// Returns text layout of the page. If page index is invalid,
|
||||
/// then empty text layout is returned.
|
||||
/// \param pageIndex Page index
|
||||
PDFTextLayout getTextLayout(PDFInteger pageIndex);
|
||||
|
||||
/// Returns getter for text layout of the page. If page index is invalid,
|
||||
/// then empty text layout getter is returned.
|
||||
/// \param pageIndex Page index
|
||||
PDFTextLayoutGetter getTextLayoutLazy(PDFInteger pageIndex);
|
||||
|
||||
/// Select all texts on all pages using \p color color.
|
||||
/// \param color Color to be used for text selection
|
||||
PDFTextSelection getTextSelectionAll(QColor color) const;
|
||||
|
||||
/// Create text layout for the document. Function is asynchronous,
|
||||
/// it returns immediately. After text layout is created, signal
|
||||
/// \p textLayoutChanged is emitted.
|
||||
void makeTextLayout();
|
||||
|
||||
/// Returns true, if text layout is ready
|
||||
bool isTextLayoutReady() const { return m_textLayouts.has_value(); }
|
||||
|
||||
/// Returns text layout storage (if it is ready), or nullptr
|
||||
const PDFTextLayoutStorage* getTextLayoutStorage() const { return isTextLayoutReady() ? &m_textLayouts.value() : nullptr; }
|
||||
|
||||
signals:
|
||||
void textLayoutChanged();
|
||||
|
||||
private:
|
||||
void onTextLayoutCreated();
|
||||
|
||||
PDFDrawWidgetProxy* m_proxy;
|
||||
State m_state = State::Inactive;
|
||||
bool m_isRunning;
|
||||
std::optional<PDFTextLayoutStorage> m_textLayouts;
|
||||
QFuture<PDFTextLayoutStorage> m_textLayoutCompileFuture;
|
||||
QFutureWatcher<PDFTextLayoutStorage> m_textLayoutCompileFutureWatcher;
|
||||
PDFTextLayoutCache m_cache;
|
||||
};
|
||||
|
||||
} // namespace pdf
|
||||
|
||||
#endif // PDFCOMPILER_H
|
@@ -18,6 +18,7 @@
|
||||
#ifndef PDFCREATECERTIFICATEDIALOG_H
|
||||
#define PDFCREATECERTIFICATEDIALOG_H
|
||||
|
||||
#include "pdfwidgetsglobal.h"
|
||||
#include "pdfcertificatemanager.h"
|
||||
|
||||
#include <QDialog>
|
||||
@@ -30,7 +31,7 @@ class PDFCreateCertificateDialog;
|
||||
namespace pdf
|
||||
{
|
||||
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFCreateCertificateDialog : public QDialog
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFCreateCertificateDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
148
Pdf4QtLibWidgets/sources/pdfdocumentdrawinterface.h
Normal file
148
Pdf4QtLibWidgets/sources/pdfdocumentdrawinterface.h
Normal file
@@ -0,0 +1,148 @@
|
||||
// Copyright (C) 2020-2021 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT 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 Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef PDFDOCUMENTDRAWINTERFACE_H
|
||||
#define PDFDOCUMENTDRAWINTERFACE_H
|
||||
|
||||
#include "pdfwidgetsglobal.h"
|
||||
#include "pdfglobal.h"
|
||||
#include "pdfexception.h"
|
||||
|
||||
#include <optional>
|
||||
|
||||
class QPainter;
|
||||
class QKeyEvent;
|
||||
class QMouseEvent;
|
||||
class QWheelEvent;
|
||||
|
||||
namespace pdf
|
||||
{
|
||||
class PDFPrecompiledPage;
|
||||
class PDFTextLayoutGetter;
|
||||
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT IDocumentDrawInterface
|
||||
{
|
||||
public:
|
||||
explicit inline IDocumentDrawInterface() = default;
|
||||
virtual ~IDocumentDrawInterface() = default;
|
||||
|
||||
/// Performs drawing of additional graphics onto the painter using precompiled page,
|
||||
/// optionally text layout and page point to device point matrix.
|
||||
/// \param painter Painter
|
||||
/// \param pageIndex Page index
|
||||
/// \param compiledPage Compiled page
|
||||
/// \param layoutGetter Layout getter
|
||||
/// \param pagePointToDevicePointMatrix Matrix mapping page space to device point space
|
||||
/// \param[out] errors Output parameter - rendering errors
|
||||
virtual void drawPage(QPainter* painter,
|
||||
pdf::PDFInteger pageIndex,
|
||||
const PDFPrecompiledPage* compiledPage,
|
||||
PDFTextLayoutGetter& layoutGetter,
|
||||
const QTransform& pagePointToDevicePointMatrix,
|
||||
QList<PDFRenderError>& errors) const;
|
||||
|
||||
/// Performs drawing of additional graphics after all pages are drawn onto the painter.
|
||||
/// \param painter Painter
|
||||
/// \param rect Draw rectangle (usually viewport rectangle of the pdf widget)
|
||||
virtual void drawPostRendering(QPainter* painter, QRect rect) const;
|
||||
};
|
||||
|
||||
/// Input interface for handling events. Implementations should react on these events,
|
||||
/// and set it to accepted, if they were consumed by the interface. Interface, which
|
||||
/// consumes mouse press event, should also consume mouse release event.
|
||||
class IDrawWidgetInputInterface
|
||||
{
|
||||
public:
|
||||
explicit inline IDrawWidgetInputInterface() = default;
|
||||
virtual ~IDrawWidgetInputInterface() = default;
|
||||
|
||||
enum InputPriority
|
||||
{
|
||||
ToolPriority = 10,
|
||||
FormPriority = 20,
|
||||
AnnotationPriority = 30,
|
||||
UserPriority = 40
|
||||
};
|
||||
|
||||
/// Handles shortcut override event. Accept this event, when you want given
|
||||
/// key sequence to be propagated to keyPressEvent.
|
||||
/// \param widget Widget
|
||||
/// \param event Event
|
||||
virtual void shortcutOverrideEvent(QWidget* widget, QKeyEvent* event) = 0;
|
||||
|
||||
/// Handles key press event from widget
|
||||
/// \param widget Widget
|
||||
/// \param event Event
|
||||
virtual void keyPressEvent(QWidget* widget, QKeyEvent* event) = 0;
|
||||
|
||||
/// Handles key release event from widget
|
||||
/// \param widget Widget
|
||||
/// \param event Event
|
||||
virtual void keyReleaseEvent(QWidget* widget, QKeyEvent* event) = 0;
|
||||
|
||||
/// Handles mouse press event from widget
|
||||
/// \param widget Widget
|
||||
/// \param event Event
|
||||
virtual void mousePressEvent(QWidget* widget, QMouseEvent* event) = 0;
|
||||
|
||||
/// Handles mouse double click event from widget
|
||||
/// \param widget Widget
|
||||
/// \param event Event
|
||||
virtual void mouseDoubleClickEvent(QWidget* widget, QMouseEvent* event) = 0;
|
||||
|
||||
/// Handles mouse release event from widget
|
||||
/// \param widget Widget
|
||||
/// \param event Event
|
||||
virtual void mouseReleaseEvent(QWidget* widget, QMouseEvent* event) = 0;
|
||||
|
||||
/// Handles mouse move event from widget
|
||||
/// \param widget Widget
|
||||
/// \param event Event
|
||||
virtual void mouseMoveEvent(QWidget* widget, QMouseEvent* event) = 0;
|
||||
|
||||
/// Handles mouse wheel event from widget
|
||||
/// \param widget Widget
|
||||
/// \param event Event
|
||||
virtual void wheelEvent(QWidget* widget, QWheelEvent* event) = 0;
|
||||
|
||||
/// Returns tooltip
|
||||
virtual QString getTooltip() const = 0;
|
||||
|
||||
/// Returns current cursor
|
||||
virtual const std::optional<QCursor>& getCursor() const = 0;
|
||||
|
||||
/// Returns input priority (interfaces with higher priority
|
||||
/// will get input events before interfaces with lower priority)
|
||||
virtual int getInputPriority() const = 0;
|
||||
|
||||
class Comparator
|
||||
{
|
||||
public:
|
||||
explicit constexpr inline Comparator() = default;
|
||||
|
||||
bool operator()(IDrawWidgetInputInterface* left, IDrawWidgetInputInterface* right) const
|
||||
{
|
||||
return std::make_pair(left->getInputPriority(), left) < std::make_pair(right->getInputPriority(), right);
|
||||
}
|
||||
};
|
||||
|
||||
static constexpr Comparator getComparator() { return Comparator(); }
|
||||
};
|
||||
|
||||
} // namespace pdf
|
||||
|
||||
#endif // PDFDOCUMENTDRAWINTERFACE_H
|
1613
Pdf4QtLibWidgets/sources/pdfdrawspacecontroller.cpp
Normal file
1613
Pdf4QtLibWidgets/sources/pdfdrawspacecontroller.cpp
Normal file
File diff suppressed because it is too large
Load Diff
553
Pdf4QtLibWidgets/sources/pdfdrawspacecontroller.h
Normal file
553
Pdf4QtLibWidgets/sources/pdfdrawspacecontroller.h
Normal file
@@ -0,0 +1,553 @@
|
||||
// Copyright (C) 2019-2021 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT 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 Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef PDFDRAWSPACECONTROLLER_H
|
||||
#define PDFDRAWSPACECONTROLLER_H
|
||||
|
||||
#include "pdfwidgetsglobal.h"
|
||||
#include "pdfglobal.h"
|
||||
#include "pdfdocument.h"
|
||||
#include "pdfrenderer.h"
|
||||
#include "pdffont.h"
|
||||
#include "pdfdocumentdrawinterface.h"
|
||||
#include "pdfwidgetsnapshot.h"
|
||||
|
||||
#include <QRectF>
|
||||
#include <QObject>
|
||||
#include <QMarginsF>
|
||||
|
||||
class QPainter;
|
||||
class QScrollBar;
|
||||
class QTimer;
|
||||
|
||||
namespace pdf
|
||||
{
|
||||
class PDFProgress;
|
||||
class PDFWidget;
|
||||
class PDFCMSManager;
|
||||
class PDFTextLayoutGetter;
|
||||
class PDFWidgetAnnotationManager;
|
||||
class PDFAsynchronousPageCompiler;
|
||||
class PDFAsynchronousTextLayoutCompiler;
|
||||
|
||||
/// This class controls draw space - page layout. Pages are divided into blocks
|
||||
/// each block can contain one or multiple pages. Units are in milimeters.
|
||||
/// Pages are layouted in zoom-independent mode.
|
||||
class PDFDrawSpaceController : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit PDFDrawSpaceController(QObject* parent);
|
||||
virtual ~PDFDrawSpaceController() override;
|
||||
|
||||
/// Sets the document and recalculates the draw space. Document can be nullptr,
|
||||
/// in that case, draw space is cleared. Optional content activity can be nullptr,
|
||||
/// in that case, no content is suppressed.
|
||||
/// \param document Document
|
||||
void setDocument(const PDFModifiedDocument& document);
|
||||
|
||||
/// Sets the page layout. Page layout can be one of the PDF's page layouts.
|
||||
/// \param pageLayout Page layout
|
||||
void setPageLayout(PageLayout pageLayout);
|
||||
|
||||
/// Returns the page layout
|
||||
PageLayout getPageLayout() const { return m_pageLayoutMode; }
|
||||
|
||||
/// Returns the block count
|
||||
size_t getBlockCount() const { return m_blockItems.size(); }
|
||||
|
||||
/// Return the bounding rectangle of the block. If block doesn't exist,
|
||||
/// then invalid rectangle is returned (no exception is thrown).
|
||||
/// \param blockIndex Index of the block
|
||||
QRectF getBlockBoundingRectangle(size_t blockIndex) const;
|
||||
|
||||
/// Represents layouted page. This structure contains index of the block, index of the
|
||||
/// page and page rectangle, in which the page is contained.
|
||||
struct LayoutItem
|
||||
{
|
||||
constexpr inline explicit LayoutItem() : blockIndex(-1), pageIndex(-1), groupIndex(-1) { }
|
||||
constexpr inline explicit LayoutItem(PDFInteger blockIndex, PDFInteger pageIndex, PDFInteger groupIndex, const QRectF& pageRectMM) :
|
||||
blockIndex(blockIndex), pageIndex(pageIndex), groupIndex(groupIndex), pageRectMM(pageRectMM) { }
|
||||
|
||||
bool operator ==(const LayoutItem&) const = default;
|
||||
|
||||
bool isValid() const { return pageIndex != -1; }
|
||||
|
||||
PDFInteger blockIndex;
|
||||
PDFInteger pageIndex;
|
||||
PDFInteger groupIndex; ///< Page group index
|
||||
QRectF pageRectMM;
|
||||
};
|
||||
|
||||
using LayoutItems = std::vector<LayoutItem>;
|
||||
|
||||
/// Returns the layout items for desired block. If block doesn't exist,
|
||||
/// then empty array is returned.
|
||||
/// \param blockIndex Index of the block
|
||||
LayoutItems getLayoutItems(size_t blockIndex) const;
|
||||
|
||||
/// Returns layout for single page. If page index is invalid,
|
||||
/// or page layout cannot be found, then invalid layout item is returned.
|
||||
/// \param pageIndex Page index
|
||||
LayoutItem getLayoutItemForPage(PDFInteger pageIndex) const;
|
||||
|
||||
/// Returns the document
|
||||
const PDFDocument* getDocument() const { return m_document; }
|
||||
|
||||
/// Returns the font cache
|
||||
const PDFFontCache* getFontCache() const { return &m_fontCache; }
|
||||
|
||||
/// Returns the font cache
|
||||
PDFFontCache* getFontCache() { return &m_fontCache; }
|
||||
|
||||
/// Returns optional content activity
|
||||
const PDFOptionalContentActivity* getOptionalContentActivity() const { return m_optionalContentActivity; }
|
||||
|
||||
/// Returns reference bounding box for correct calculation of zoom fit/fit vertical/fit horizontal.
|
||||
/// If zoom is set in a way to display this bounding box on a screen, then it is assured that
|
||||
/// any page on the screen will fit this bounding box, regardless of mode (single/two columns, etc.).
|
||||
QSizeF getReferenceBoundingBox() const;
|
||||
|
||||
/// Returns page rotation
|
||||
PageRotation getPageRotation() const { return m_pageRotation; }
|
||||
|
||||
/// Sets page rotation
|
||||
void setPageRotation(PageRotation pageRotation);
|
||||
|
||||
/// Set custom layout. Custom layout provides a way how to define
|
||||
/// custom page layout, including blocks. Block indices must be properly defined,
|
||||
/// that means block index must start by zero and must be continuous. If this
|
||||
/// criteria are not fulfilled, behaviour is undefined.
|
||||
void setCustomLayout(LayoutItems customLayoutItems);
|
||||
|
||||
/// Returns custom layout
|
||||
const LayoutItems& getCustomLayout() const { return m_customLayoutItems; }
|
||||
|
||||
signals:
|
||||
void drawSpaceChanged();
|
||||
void repaintNeeded();
|
||||
void pageImageChanged(bool all, const std::vector<PDFInteger>& pages);
|
||||
|
||||
private:
|
||||
/// Recalculates the draw space. Preserves setted page rotation.
|
||||
void recalculate();
|
||||
|
||||
/// Clears the draw space. Emits signal if desired.
|
||||
void clear(bool emitSignal);
|
||||
|
||||
/// Represents data for the single block. Contains block size in milimeters.
|
||||
struct LayoutBlock
|
||||
{
|
||||
constexpr inline explicit LayoutBlock() = default;
|
||||
constexpr inline explicit LayoutBlock(const QRectF& blockRectMM) : blockRectMM(blockRectMM) { }
|
||||
|
||||
QRectF blockRectMM;
|
||||
};
|
||||
|
||||
using BlockItems = std::vector<LayoutBlock>;
|
||||
|
||||
const PDFDocument* m_document;
|
||||
const PDFOptionalContentActivity* m_optionalContentActivity;
|
||||
|
||||
PageLayout m_pageLayoutMode;
|
||||
LayoutItems m_layoutItems;
|
||||
BlockItems m_blockItems;
|
||||
PDFReal m_verticalSpacingMM;
|
||||
PDFReal m_horizontalSpacingMM;
|
||||
PageRotation m_pageRotation;
|
||||
LayoutItems m_customLayoutItems;
|
||||
|
||||
/// Font cache
|
||||
PDFFontCache m_fontCache;
|
||||
};
|
||||
|
||||
/// This is a proxy class to draw space controller using widget. We have two spaces, pixel space
|
||||
/// (on the controlled widget) and device space (device is draw space controller).
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFDrawWidgetProxy : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit PDFDrawWidgetProxy(QObject* parent);
|
||||
virtual ~PDFDrawWidgetProxy() override;
|
||||
|
||||
/// Sets the document and updates the draw space. Document can be nullptr,
|
||||
/// in that case, draw space is cleared. Optional content activity can be nullptr,
|
||||
/// in that case, no content is suppressed.
|
||||
/// \param document Document
|
||||
void setDocument(const PDFModifiedDocument& document);
|
||||
|
||||
void init(PDFWidget* widget);
|
||||
|
||||
/// Updates the draw space area
|
||||
void update();
|
||||
|
||||
/// Creates page point to device point matrix for the given rectangle. It creates transformation
|
||||
/// from page's media box to the target rectangle.
|
||||
/// \param page Page, for which we want to create matrix
|
||||
/// \param rectangle Page rectangle, to which is page media box transformed
|
||||
QTransform createPagePointToDevicePointMatrix(const PDFPage* page, const QRectF& rectangle) const;
|
||||
|
||||
/// Draws the actually visible pages on the painter using the rectangle.
|
||||
/// Rectangle is space in the widget, which is used for painting the PDF.
|
||||
/// This function is using drawPages function to draw all pages. After that,
|
||||
/// custom drawing is performed.
|
||||
/// \sa drawPages
|
||||
/// \param painter Painter to paint the PDF pages
|
||||
/// \param rect Rectangle in which the content is painted
|
||||
void draw(QPainter* painter, QRect rect);
|
||||
|
||||
/// Draws the actually visible pages on the painter using the rectangle.
|
||||
/// Rectangle is space in the widget, which is used for painting the PDF.
|
||||
/// \param painter Painter to paint the PDF pages
|
||||
/// \param rect Rectangle in which the content is painted
|
||||
/// \param features Rendering features
|
||||
void drawPages(QPainter* painter, QRect rect, PDFRenderer::Features features);
|
||||
|
||||
/// Draws thumbnail image of the given size (so larger of the page size
|
||||
/// width or height equals to pixel size and the latter size is rescaled
|
||||
/// using the aspect ratio)
|
||||
/// \param pixelSize Pixel size
|
||||
QImage drawThumbnailImage(PDFInteger pageIndex, int pixelSize) const;
|
||||
|
||||
enum Operation
|
||||
{
|
||||
ZoomIn,
|
||||
ZoomOut,
|
||||
ZoomFit,
|
||||
ZoomFitWidth,
|
||||
ZoomFitHeight,
|
||||
NavigateDocumentStart,
|
||||
NavigateDocumentEnd,
|
||||
NavigateNextPage,
|
||||
NavigatePreviousPage,
|
||||
NavigateNextStep,
|
||||
NavigatePreviousStep,
|
||||
RotateRight,
|
||||
RotateLeft
|
||||
};
|
||||
|
||||
/// Performs the desired operation (for example navigation).
|
||||
/// \param operation Operation to be performed
|
||||
void performOperation(Operation operation);
|
||||
|
||||
/// Scrolls by pixels, if it is possible. If it is not possible to scroll,
|
||||
/// then nothing happens. Returns pixel offset, by which view camera was moved.
|
||||
/// \param offset Offset in pixels
|
||||
QPoint scrollByPixels(QPoint offset);
|
||||
|
||||
/// Sets the zoom. Tries to preserve current offsets (so the current visible
|
||||
/// area will be visible after the zoom).
|
||||
/// \param zoom New zoom
|
||||
void zoom(PDFReal zoom);
|
||||
|
||||
enum class ZoomHint
|
||||
{
|
||||
Fit,
|
||||
FitWidth,
|
||||
FitHeight
|
||||
};
|
||||
|
||||
/// Calculates zoom using given hint (i.e. to fill whole space, fill vertical,
|
||||
/// or fill horizontal).
|
||||
/// \param hint Zoom hint type
|
||||
PDFReal getZoomHint(ZoomHint hint) const;
|
||||
|
||||
/// Go to the specified page
|
||||
/// \param pageIndex Page to scroll to
|
||||
void goToPage(PDFInteger pageIndex);
|
||||
|
||||
/// Go to the specified page and ensures point on the page is visible
|
||||
/// \param pageIndex Page to scroll to
|
||||
/// \param ensureVisibleRect Rectangle on page, which should be visible
|
||||
void goToPageAndEnsureVisible(PDFInteger pageIndex, QRectF ensureVisibleRect);
|
||||
|
||||
/// Returns current zoom from widget space to device space. So, for example 2.00 corresponds to 200% zoom,
|
||||
/// and each 1 cm of widget area corresponds to 0.5 cm of the device space area.
|
||||
PDFReal getZoom() const { return m_zoom; }
|
||||
|
||||
/// Sets the page layout. Page layout can be one of the PDF's page layouts.
|
||||
/// \param pageLayout Page layout
|
||||
void setPageLayout(PageLayout pageLayout);
|
||||
|
||||
/// Sets custom page layout. If this function is used, page layout mode
|
||||
/// must be set to 'Custom'.
|
||||
/// \param layoutItems Layout items
|
||||
void setCustomPageLayout(PDFDrawSpaceController::LayoutItems layoutItems);
|
||||
|
||||
/// Returns the page layout
|
||||
PageLayout getPageLayout() const { return m_controller->getPageLayout(); }
|
||||
|
||||
/// Returns pages, which are intersecting rectangle (even partially)
|
||||
/// \param rect Rectangle to test
|
||||
std::vector<PDFInteger> getPagesIntersectingRect(QRect rect) const;
|
||||
|
||||
/// Returns sorted vector of page indices, which should remain in the cache
|
||||
std::vector<PDFInteger> getActivePages() const;
|
||||
|
||||
/// Returns page, under which is point. If no page is under the point,
|
||||
/// then -1 is returned. Point is in widget coordinates. If \p pagePoint
|
||||
/// is not nullptr, then point in page coordinate space is set here.
|
||||
/// \param point Point
|
||||
/// \param pagePoint Point in page coordinate system
|
||||
PDFInteger getPageUnderPoint(QPoint point, QPointF* pagePoint) const;
|
||||
|
||||
/// Returns bounding box of pages, which are intersecting rectangle (even partially)
|
||||
/// \param rect Rectangle to test
|
||||
QRect getPagesIntersectingRectBoundingBox(QRect rect) const;
|
||||
|
||||
/// Returns true, if we are in the block mode (multiple blocks with separate pages),
|
||||
/// or continuous mode (single block with continuous list of separated pages).
|
||||
bool isBlockMode() const;
|
||||
|
||||
/// Updates renderer (in current implementation, renderer for page thumbnails)
|
||||
/// using given parameters.
|
||||
/// \param useOpenGL Use OpenGL for rendering?
|
||||
/// \param surfaceFormat Surface format for OpenGL rendering
|
||||
void updateRenderer(bool useOpenGL, const QSurfaceFormat& surfaceFormat);
|
||||
|
||||
/// Prefetches (prerenders) pages after page with pageIndex, i.e., prepares
|
||||
/// for non-flickering scroll operation.
|
||||
void prefetchPages(PDFInteger pageIndex);
|
||||
|
||||
static constexpr PDFReal ZOOM_STEP = 1.2;
|
||||
|
||||
const PDFDocument* getDocument() const { return m_controller->getDocument(); }
|
||||
PDFFontCache* getFontCache() const { return m_controller->getFontCache(); }
|
||||
const PDFOptionalContentActivity* getOptionalContentActivity() const { return m_controller->getOptionalContentActivity(); }
|
||||
PDFRenderer::Features getFeatures() const;
|
||||
const PDFMeshQualitySettings& getMeshQualitySettings() const { return m_meshQualitySettings; }
|
||||
PDFAsynchronousPageCompiler* getCompiler() const { return m_compiler; }
|
||||
const PDFCMSManager* getCMSManager() const;
|
||||
PDFProgress* getProgress() const { return m_progress; }
|
||||
void setProgress(PDFProgress* progress) { m_progress = progress; }
|
||||
PDFAsynchronousTextLayoutCompiler* getTextLayoutCompiler() const { return m_textLayoutCompiler; }
|
||||
PDFWidget* getWidget() const { return m_widget; }
|
||||
bool isUsingOpenGL() const { return m_useOpenGL; }
|
||||
const QSurfaceFormat& getSurfaceFormat() const { return m_surfaceFormat; }
|
||||
PageRotation getPageRotation() const { return m_controller->getPageRotation(); }
|
||||
|
||||
void setFeatures(PDFRenderer::Features features);
|
||||
void setPreferredMeshResolutionRatio(PDFReal ratio);
|
||||
void setMinimalMeshResolutionRatio(PDFReal ratio);
|
||||
void setColorTolerance(PDFReal colorTolerance);
|
||||
|
||||
static constexpr PDFReal getMinZoom() { return MIN_ZOOM; }
|
||||
static constexpr PDFReal getMaxZoom() { return MAX_ZOOM; }
|
||||
|
||||
void registerDrawInterface(IDocumentDrawInterface* drawInterface) { m_drawInterfaces.insert(drawInterface); }
|
||||
void unregisterDrawInterface(IDocumentDrawInterface* drawInterface) { m_drawInterfaces.erase(drawInterface); }
|
||||
|
||||
/// Returns current paper color
|
||||
QColor getPaperColor();
|
||||
|
||||
/// Transforms pixels to device space
|
||||
/// \param pixel Value in pixels
|
||||
PDFReal transformPixelToDeviceSpace(PDFReal pixel) const { return pixel * m_pixelToDeviceSpaceUnit; }
|
||||
|
||||
/// Transforms value in device space to pixel value
|
||||
/// \param deviceSpaceValue Value in device space
|
||||
PDFReal transformDeviceSpaceToPixel(PDFReal deviceSpaceValue) const { return deviceSpaceValue * m_deviceSpaceUnitToPixel; }
|
||||
|
||||
/// Returns snapshot of current view area
|
||||
PDFWidgetSnapshot getSnapshot() const;
|
||||
|
||||
/// Sets page group transparency settings. All pages with a given group index
|
||||
/// will be displayed with this transparency settings.
|
||||
/// \param groupIndex Group index
|
||||
/// \param drawPaper Draw background paper
|
||||
/// \param transparency Page graphics transparency
|
||||
void setGroupTransparency(PDFInteger groupIndex, bool drawPaper = true, PDFReal transparency = 1.0);
|
||||
|
||||
PDFWidgetAnnotationManager* getAnnotationManager() const;
|
||||
|
||||
signals:
|
||||
void drawSpaceChanged();
|
||||
void pageLayoutChanged();
|
||||
void renderingError(pdf::PDFInteger pageIndex, const QList<pdf::PDFRenderError>& errors);
|
||||
void repaintNeeded();
|
||||
void pageImageChanged(bool all, const std::vector<PDFInteger>& pages);
|
||||
void textLayoutChanged();
|
||||
|
||||
private:
|
||||
struct LayoutItem
|
||||
{
|
||||
constexpr inline explicit LayoutItem() : pageIndex(-1), groupIndex(-1) { }
|
||||
constexpr inline explicit LayoutItem(PDFInteger pageIndex, PDFInteger groupIndex, const QRect& pageRect) :
|
||||
pageIndex(pageIndex), groupIndex(groupIndex), pageRect(pageRect) { }
|
||||
|
||||
|
||||
PDFInteger pageIndex;
|
||||
PDFInteger groupIndex; ///< Used to create group of pages (for transparency and overlay)
|
||||
QRect pageRect;
|
||||
};
|
||||
|
||||
struct Layout
|
||||
{
|
||||
inline void clear()
|
||||
{
|
||||
items.clear();
|
||||
blockRect = QRect();
|
||||
}
|
||||
|
||||
std::vector<LayoutItem> items;
|
||||
QRect blockRect;
|
||||
};
|
||||
|
||||
struct GroupInfo
|
||||
{
|
||||
bool operator==(const GroupInfo&) const = default;
|
||||
|
||||
bool drawPaper = true;
|
||||
PDFReal transparency = 1.0;
|
||||
};
|
||||
|
||||
static constexpr size_t INVALID_BLOCK_INDEX = std::numeric_limits<size_t>::max();
|
||||
|
||||
// Minimal/maximal zoom is from 8% to 6400 %, according to the PDF 1.7 Reference,
|
||||
// Appendix C.
|
||||
|
||||
static constexpr PDFReal MIN_ZOOM = 8.0 / 100.0;
|
||||
static constexpr PDFReal MAX_ZOOM = 6400.0 / 100.0;
|
||||
|
||||
static constexpr qint64 CACHE_CLEAR_TIMEOUT = 5000;
|
||||
static constexpr qint64 CACHE_PAGE_EXPIRATION_TIMEOUT = 30000;
|
||||
|
||||
/// Converts rectangle from device space to the pixel space
|
||||
QRectF fromDeviceSpace(const QRectF& rect) const;
|
||||
|
||||
void performPageCacheClear();
|
||||
|
||||
void onTextLayoutChanged();
|
||||
void onOptionalContentGroupStateChanged();
|
||||
void onColorManagementSystemChanged();
|
||||
void onHorizontalScrollbarValueChanged(int value);
|
||||
void onVerticalScrollbarValueChanged(int value);
|
||||
|
||||
void setHorizontalOffset(int value);
|
||||
void setVerticalOffset(int value);
|
||||
void setBlockIndex(int index);
|
||||
|
||||
void updateHorizontalScrollbarFromOffset();
|
||||
void updateVerticalScrollbarFromOffset();
|
||||
|
||||
GroupInfo getGroupInfo(int groupIndex) const;
|
||||
|
||||
template<typename T>
|
||||
struct Range
|
||||
{
|
||||
constexpr inline Range() : min(T()), max(T()) { }
|
||||
constexpr inline Range(T value) : min(value), max(value) { }
|
||||
constexpr inline Range(T min, T max) : min(min), max(max) { }
|
||||
|
||||
T min;
|
||||
T max;
|
||||
|
||||
constexpr inline T bound(T value) { return qBound(min, value, max); }
|
||||
};
|
||||
|
||||
static constexpr bool ENABLE_OPENGL_FOR_THUMBNAILS = false;
|
||||
|
||||
/// Flag, disables the update
|
||||
bool m_updateDisabled;
|
||||
|
||||
/// Current block (in the draw space controller)
|
||||
size_t m_currentBlock;
|
||||
|
||||
/// Number of pixels (fractional) per milimeter (unit is pixel/mm) of the screen,
|
||||
/// so, size of the area in milimeters can be computed as pixelCount * m_pixelPerMM [mm].
|
||||
PDFReal m_pixelPerMM;
|
||||
|
||||
/// Zoom from widget space to device space. So, for example 2.00 corresponds to 200% zoom,
|
||||
/// and each 1 cm of widget area corresponds to 0.5 cm of the device space area.
|
||||
PDFReal m_zoom;
|
||||
|
||||
/// Converts pixel to device space units (mm) using zoom
|
||||
PDFReal m_pixelToDeviceSpaceUnit;
|
||||
|
||||
/// Converts device space units (mm) to real pixels using zoom
|
||||
PDFReal m_deviceSpaceUnitToPixel;
|
||||
|
||||
/// Actual vertical offset of the draw space area in the widget (so block will be drawn
|
||||
/// with this vertical offset)
|
||||
PDFInteger m_verticalOffset;
|
||||
|
||||
/// Range of vertical offset
|
||||
Range<PDFInteger> m_verticalOffsetRange;
|
||||
|
||||
/// Actual horizontal offset of the draw space area in the widget (so block will be drawn
|
||||
/// with this horizontal offset)
|
||||
PDFInteger m_horizontalOffset;
|
||||
|
||||
/// Range for horizontal offset
|
||||
Range<PDFInteger> m_horizontalOffsetRange;
|
||||
|
||||
/// Draw space controller
|
||||
PDFDrawSpaceController* m_controller;
|
||||
|
||||
/// Controlled draw widget (proxy is for this widget)
|
||||
PDFWidget* m_widget;
|
||||
|
||||
/// Vertical scrollbar
|
||||
QScrollBar* m_verticalScrollbar;
|
||||
|
||||
/// Horizontal scrollbar
|
||||
QScrollBar* m_horizontalScrollbar;
|
||||
|
||||
/// Current page layout
|
||||
Layout m_layout;
|
||||
|
||||
/// Renderer features
|
||||
PDFRenderer::Features m_features;
|
||||
|
||||
/// Mesh quality settings
|
||||
PDFMeshQualitySettings m_meshQualitySettings;
|
||||
|
||||
/// Page compiler
|
||||
PDFAsynchronousPageCompiler* m_compiler;
|
||||
|
||||
/// Text layout compiler
|
||||
PDFAsynchronousTextLayoutCompiler* m_textLayoutCompiler;
|
||||
|
||||
/// Page image rasterizer for thumbnails
|
||||
PDFRasterizer* m_rasterizer;
|
||||
|
||||
/// Progress
|
||||
PDFProgress* m_progress;
|
||||
|
||||
/// Cache clear timer
|
||||
QTimer* m_cacheClearTimer;
|
||||
|
||||
/// Additional drawing interfaces
|
||||
std::set<IDocumentDrawInterface*> m_drawInterfaces;
|
||||
|
||||
/// Use OpenGL for rendering?
|
||||
bool m_useOpenGL;
|
||||
|
||||
/// Surface format for OpenGL
|
||||
QSurfaceFormat m_surfaceFormat;
|
||||
|
||||
/// Page group info for rendering. Group of pages
|
||||
/// can be rendered with transparency or without paper
|
||||
/// as overlay.
|
||||
std::map<PDFInteger, GroupInfo> m_groupInfos;
|
||||
};
|
||||
|
||||
} // namespace pdf
|
||||
|
||||
#endif // PDFDRAWSPACECONTROLLER_H
|
@@ -20,7 +20,8 @@
|
||||
#include "pdfcompiler.h"
|
||||
#include "pdfwidgettool.h"
|
||||
#include "pdfannotation.h"
|
||||
#include "pdfform.h"
|
||||
#include "pdfwidgetannotation.h"
|
||||
#include "pdfwidgetformmanager.h"
|
||||
#include "pdfdbgheap.h"
|
||||
|
||||
#include <QPainter>
|
||||
@@ -231,12 +232,12 @@ RendererEngine PDFWidget::getEffectiveRenderer(RendererEngine rendererEngine)
|
||||
return rendererEngine;
|
||||
}
|
||||
|
||||
PDFFormManager* PDFWidget::getFormManager() const
|
||||
PDFWidgetFormManager* PDFWidget::getFormManager() const
|
||||
{
|
||||
return m_formManager;
|
||||
}
|
||||
|
||||
void PDFWidget::setFormManager(PDFFormManager* formManager)
|
||||
void PDFWidget::setFormManager(PDFWidgetFormManager* formManager)
|
||||
{
|
||||
removeInputInterface(m_formManager);
|
||||
m_formManager = formManager;
|
||||
|
@@ -18,6 +18,7 @@
|
||||
#ifndef PDFDRAWWIDGET_H
|
||||
#define PDFDRAWWIDGET_H
|
||||
|
||||
#include "pdfwidgetsglobal.h"
|
||||
#include "pdfglobal.h"
|
||||
#include "pdfrenderer.h"
|
||||
|
||||
@@ -34,7 +35,7 @@ class PDFDocument;
|
||||
class PDFCMSManager;
|
||||
class PDFToolManager;
|
||||
class PDFDrawWidget;
|
||||
class PDFFormManager;
|
||||
class PDFWidgetFormManager;
|
||||
class PDFDrawWidgetProxy;
|
||||
class PDFModifiedDocument;
|
||||
class PDFWidgetAnnotationManager;
|
||||
@@ -54,7 +55,7 @@ public:
|
||||
virtual bool doEvent(QEvent* event) = 0;
|
||||
};
|
||||
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFWidget : public QWidget
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -102,8 +103,8 @@ public:
|
||||
void setToolManager(PDFToolManager* toolManager);
|
||||
void setAnnotationManager(PDFWidgetAnnotationManager* annotationManager);
|
||||
|
||||
PDFFormManager* getFormManager() const;
|
||||
void setFormManager(PDFFormManager* formManager);
|
||||
PDFWidgetFormManager* getFormManager() const;
|
||||
void setFormManager(PDFWidgetFormManager* formManager);
|
||||
|
||||
void removeInputInterface(IDrawWidgetInputInterface* inputInterface);
|
||||
void addInputInterface(IDrawWidgetInputInterface* inputInterface);
|
||||
@@ -123,7 +124,7 @@ private:
|
||||
const PDFCMSManager* m_cmsManager;
|
||||
PDFToolManager* m_toolManager;
|
||||
PDFWidgetAnnotationManager* m_annotationManager;
|
||||
PDFFormManager* m_formManager;
|
||||
PDFWidgetFormManager* m_formManager;
|
||||
IDrawWidget* m_drawWidget;
|
||||
QScrollBar* m_horizontalScrollBar;
|
||||
QScrollBar* m_verticalScrollBar;
|
||||
|
@@ -18,6 +18,7 @@
|
||||
#ifndef PDFITEMMODELS_H
|
||||
#define PDFITEMMODELS_H
|
||||
|
||||
#include "pdfwidgetsglobal.h"
|
||||
#include "pdfglobal.h"
|
||||
#include "pdfobject.h"
|
||||
|
||||
@@ -39,7 +40,7 @@ class PDFDrawWidgetProxy;
|
||||
class PDFDestination;
|
||||
|
||||
/// Represents tree item in the GUI tree
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFTreeItem
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFTreeItem
|
||||
{
|
||||
public:
|
||||
inline explicit PDFTreeItem() = default;
|
||||
@@ -89,7 +90,7 @@ private:
|
||||
/// Root of all tree item models. Reimplementations of this model
|
||||
/// must handle "soft" document updates, such as only annotations changed etc.
|
||||
/// Model should be rebuilded only, if it is neccessary.
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFTreeItemModel : public QAbstractItemModel
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFTreeItemModel : public QAbstractItemModel
|
||||
{
|
||||
public:
|
||||
explicit PDFTreeItemModel(QObject* parent);
|
||||
@@ -132,7 +133,7 @@ private:
|
||||
bool m_locked; ///< Node is locked (user can't change it)
|
||||
};
|
||||
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFOptionalContentTreeItemModel : public PDFTreeItemModel
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFOptionalContentTreeItemModel : public PDFTreeItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
@@ -167,7 +168,7 @@ private:
|
||||
QSharedPointer<PDFOutlineItem> m_outlineItem;
|
||||
};
|
||||
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFOutlineTreeItemModel : public PDFTreeItemModel
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFOutlineTreeItemModel : public PDFTreeItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
@@ -221,7 +222,7 @@ private:
|
||||
mutable QSharedPointer<PDFOutlineItem> m_dragDropItem;
|
||||
};
|
||||
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFSelectableOutlineTreeItemModel : public PDFOutlineTreeItemModel
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFSelectableOutlineTreeItemModel : public PDFOutlineTreeItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -264,7 +265,7 @@ private:
|
||||
std::unique_ptr<PDFFileSpecification> m_fileSpecification;
|
||||
};
|
||||
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFAttachmentsTreeItemModel : public PDFTreeItemModel
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFAttachmentsTreeItemModel : public PDFTreeItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
@@ -289,7 +290,7 @@ public:
|
||||
const PDFFileSpecification* getFileSpecification(const QModelIndex& index) const;
|
||||
};
|
||||
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFThumbnailsItemModel : public QAbstractItemModel
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFThumbnailsItemModel : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@@ -18,6 +18,7 @@
|
||||
#ifndef PDFPAGECONTENTEDITORSTYLESETTINGS_H
|
||||
#define PDFPAGECONTENTEDITORSTYLESETTINGS_H
|
||||
|
||||
#include "pdfwidgetsglobal.h"
|
||||
#include "pdfglobal.h"
|
||||
|
||||
#include <QPen>
|
||||
@@ -38,7 +39,7 @@ namespace pdf
|
||||
{
|
||||
class PDFPageContentElement;
|
||||
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFPageContentEditorStyleSettings : public QWidget
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFPageContentEditorStyleSettings : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@@ -18,6 +18,7 @@
|
||||
#ifndef PDFPAGECONTENTEDITORTOOLS_H
|
||||
#define PDFPAGECONTENTEDITORTOOLS_H
|
||||
|
||||
#include "pdfwidgetsglobal.h"
|
||||
#include "pdfwidgettool.h"
|
||||
|
||||
namespace pdf
|
||||
@@ -33,7 +34,7 @@ class PDFPageContentElementRectangle;
|
||||
class PDFPageContentElementFreehandCurve;
|
||||
class PDFTextEditPseudowidget;
|
||||
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFCreatePCElementTool : public PDFWidgetTool
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFCreatePCElementTool : public PDFWidgetTool
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
@@ -58,7 +59,7 @@ protected:
|
||||
};
|
||||
|
||||
/// Tool that creates rectangle element.
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFCreatePCElementRectangleTool : public PDFCreatePCElementTool
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFCreatePCElementRectangleTool : public PDFCreatePCElementTool
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -91,7 +92,7 @@ private:
|
||||
};
|
||||
|
||||
/// Tool that displays SVG image (or raster image)
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFCreatePCElementImageTool : public PDFCreatePCElementTool
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFCreatePCElementImageTool : public PDFCreatePCElementTool
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -131,7 +132,7 @@ private:
|
||||
};
|
||||
|
||||
/// Tool that creates line element.
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFCreatePCElementLineTool : public PDFCreatePCElementTool
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFCreatePCElementLineTool : public PDFCreatePCElementTool
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -167,7 +168,7 @@ private:
|
||||
};
|
||||
|
||||
/// Tool that creates dot element.
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFCreatePCElementDotTool : public PDFCreatePCElementTool
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFCreatePCElementDotTool : public PDFCreatePCElementTool
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -199,7 +200,7 @@ private:
|
||||
};
|
||||
|
||||
/// Tool that creates freehand curve element.
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFCreatePCElementFreehandCurveTool : public PDFCreatePCElementTool
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFCreatePCElementFreehandCurveTool : public PDFCreatePCElementTool
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -237,7 +238,7 @@ private:
|
||||
};
|
||||
|
||||
/// Tool that displays SVG image
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFCreatePCElementTextTool : public PDFCreatePCElementTool
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFCreatePCElementTextTool : public PDFCreatePCElementTool
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@@ -18,6 +18,7 @@
|
||||
#ifndef PDFPAGECONTENTEDITORWIDGET_H
|
||||
#define PDFPAGECONTENTEDITORWIDGET_H
|
||||
|
||||
#include "pdfwidgetsglobal.h"
|
||||
#include "pdfglobal.h"
|
||||
|
||||
#include <QDockWidget>
|
||||
@@ -38,7 +39,7 @@ class PDFPageContentScene;
|
||||
class PDFPageContentElement;
|
||||
class PDFPageContentEditorStyleSettings;
|
||||
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFPageContentEditorWidget : public QDockWidget
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFPageContentEditorWidget : public QDockWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@@ -18,6 +18,7 @@
|
||||
#ifndef PDFPAGECONTENTELEMENTS_H
|
||||
#define PDFPAGECONTENTELEMENTS_H
|
||||
|
||||
#include "pdfwidgetsglobal.h"
|
||||
#include "pdfdocumentdrawinterface.h"
|
||||
|
||||
#include <QPen>
|
||||
@@ -36,7 +37,7 @@ class PDFWidget;
|
||||
class PDFDocument;
|
||||
class PDFPageContentScene;
|
||||
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFPageContentElement
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFPageContentElement
|
||||
{
|
||||
public:
|
||||
explicit PDFPageContentElement() = default;
|
||||
@@ -117,7 +118,7 @@ protected:
|
||||
PDFInteger m_pageIndex = -1;
|
||||
};
|
||||
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFPageContentStyledElement : public PDFPageContentElement
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFPageContentStyledElement : public PDFPageContentElement
|
||||
{
|
||||
public:
|
||||
explicit PDFPageContentStyledElement() = default;
|
||||
@@ -134,7 +135,7 @@ protected:
|
||||
QBrush m_brush;
|
||||
};
|
||||
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFPageContentElementRectangle : public PDFPageContentStyledElement
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFPageContentElementRectangle : public PDFPageContentStyledElement
|
||||
{
|
||||
public:
|
||||
virtual ~PDFPageContentElementRectangle() = default;
|
||||
@@ -167,7 +168,7 @@ private:
|
||||
QRectF m_rectangle;
|
||||
};
|
||||
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFPageContentElementLine : public PDFPageContentStyledElement
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFPageContentElementLine : public PDFPageContentStyledElement
|
||||
{
|
||||
public:
|
||||
virtual ~PDFPageContentElementLine() = default;
|
||||
@@ -207,7 +208,7 @@ private:
|
||||
QLineF m_line;
|
||||
};
|
||||
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFPageContentElementDot : public PDFPageContentStyledElement
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFPageContentElementDot : public PDFPageContentStyledElement
|
||||
{
|
||||
public:
|
||||
virtual ~PDFPageContentElementDot() = default;
|
||||
@@ -236,7 +237,7 @@ private:
|
||||
QPointF m_point;
|
||||
};
|
||||
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFPageContentElementFreehandCurve : public PDFPageContentStyledElement
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFPageContentElementFreehandCurve : public PDFPageContentStyledElement
|
||||
{
|
||||
public:
|
||||
virtual ~PDFPageContentElementFreehandCurve() = default;
|
||||
@@ -270,7 +271,7 @@ private:
|
||||
QPainterPath m_curve;
|
||||
};
|
||||
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFPageContentImageElement : public PDFPageContentElement
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFPageContentImageElement : public PDFPageContentElement
|
||||
{
|
||||
public:
|
||||
PDFPageContentImageElement();
|
||||
@@ -306,7 +307,7 @@ private:
|
||||
std::unique_ptr<QSvgRenderer> m_renderer;
|
||||
};
|
||||
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFPageContentElementTextBox : public PDFPageContentStyledElement
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFPageContentElementTextBox : public PDFPageContentStyledElement
|
||||
{
|
||||
public:
|
||||
virtual ~PDFPageContentElementTextBox() = default;
|
||||
@@ -351,7 +352,7 @@ private:
|
||||
Qt::Alignment m_alignment = Qt::AlignCenter;
|
||||
};
|
||||
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFPageContentElementManipulator : public QObject
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFPageContentElementManipulator : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -463,7 +464,7 @@ private:
|
||||
QPointF m_lastUpdatedPoint;
|
||||
};
|
||||
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFPageContentScene : public QObject,
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFPageContentScene : public QObject,
|
||||
public IDocumentDrawInterface,
|
||||
public IDrawWidgetInputInterface
|
||||
{
|
||||
|
@@ -18,6 +18,7 @@
|
||||
#ifndef PDFRENDERINGERRORSWIDGET_H
|
||||
#define PDFRENDERINGERRORSWIDGET_H
|
||||
|
||||
#include "pdfwidgetsglobal.h"
|
||||
#include "pdfglobal.h"
|
||||
|
||||
#include <QDialog>
|
||||
|
@@ -18,6 +18,7 @@
|
||||
#ifndef PDFSELECTPAGESDIALOG_H
|
||||
#define PDFSELECTPAGESDIALOG_H
|
||||
|
||||
#include "pdfwidgetsglobal.h"
|
||||
#include "pdfutils.h"
|
||||
|
||||
#include <QDialog>
|
||||
|
@@ -21,7 +21,7 @@
|
||||
#include <QStyle>
|
||||
#include <QKeyEvent>
|
||||
#include <QMouseEvent>
|
||||
#include <QCoreApplication>
|
||||
#include <QApplication>
|
||||
#include <QClipboard>
|
||||
|
||||
namespace pdf
|
||||
@@ -35,7 +35,7 @@ PDFTextEditPseudowidget::PDFTextEditPseudowidget(PDFFormField::FieldFlags flags)
|
||||
m_maxTextLength(0)
|
||||
{
|
||||
m_textLayout.setCacheEnabled(true);
|
||||
m_passwordReplacementCharacter = QChar(QCoreApplication::style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter));
|
||||
m_passwordReplacementCharacter = QChar(QApplication::style()->styleHint(QStyle::SH_LineEdit_PasswordCharacter));
|
||||
}
|
||||
|
||||
void PDFTextEditPseudowidget::shortcutOverrideEvent(QWidget* widget, QKeyEvent* event)
|
||||
|
@@ -15,8 +15,10 @@
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include "pdfwidgetannotation.h"
|
||||
#include "pdfdrawwidget.h"
|
||||
#include "pdfwidgetutils.h"
|
||||
#include "pdfdrawspacecontroller.h"
|
||||
|
||||
#include <QMenu>
|
||||
#include <QDialog>
|
||||
@@ -510,4 +512,14 @@ void PDFWidgetAnnotationManager::createWidgetsForMarkupAnnotations(QWidget* pare
|
||||
parentWidget->setFixedSize(scrollArea->sizeHint());
|
||||
}
|
||||
|
||||
void PDFWidgetAnnotationManager::drawPage(QPainter* painter,
|
||||
PDFInteger pageIndex,
|
||||
const PDFPrecompiledPage* compiledPage,
|
||||
PDFTextLayoutGetter& layoutGetter,
|
||||
const QTransform& pagePointToDevicePointMatrix,
|
||||
QList<PDFRenderError>& errors) const
|
||||
{
|
||||
BaseClass::drawPage(painter, pageIndex, compiledPage, layoutGetter, pagePointToDevicePointMatrix, errors);
|
||||
}
|
||||
|
||||
} // namespace pdf
|
||||
|
@@ -15,7 +15,9 @@
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include "pdfwidgetsglobal.h"
|
||||
#include "pdfannotation.h"
|
||||
#include "pdfdocumentdrawinterface.h"
|
||||
|
||||
namespace pdf
|
||||
{
|
||||
@@ -24,7 +26,7 @@ class PDFDrawWidgetProxy;
|
||||
|
||||
/// Annotation manager for GUI rendering, it also manages annotations widgets
|
||||
/// for parent widget.
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFWidgetAnnotationManager : public PDFAnnotationManager, public IDrawWidgetInputInterface
|
||||
class PDF4QTLIBWIDGETSSHARED_EXPORT PDFWidgetAnnotationManager : public PDFAnnotationManager, public IDrawWidgetInputInterface, public IDocumentDrawInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -36,7 +38,6 @@ public:
|
||||
virtual ~PDFWidgetAnnotationManager() override;
|
||||
|
||||
virtual void setDocument(const PDFModifiedDocument& document) override;
|
||||
|
||||
virtual void shortcutOverrideEvent(QWidget* widget, QKeyEvent* event) override;
|
||||
virtual void keyPressEvent(QWidget* widget, QKeyEvent* event) override;
|
||||
virtual void keyReleaseEvent(QWidget* widget, QKeyEvent* event) override;
|
||||
@@ -46,6 +47,13 @@ public:
|
||||
virtual void mouseMoveEvent(QWidget* widget, QMouseEvent* event) override;
|
||||
virtual void wheelEvent(QWidget* widget, QWheelEvent* event) override;
|
||||
|
||||
virtual void drawPage(QPainter* painter,
|
||||
PDFInteger pageIndex,
|
||||
const PDFPrecompiledPage* compiledPage,
|
||||
PDFTextLayoutGetter& layoutGetter,
|
||||
const QTransform& pagePointToDevicePointMatrix,
|
||||
QList<PDFRenderError>& errors) const override;
|
||||
|
||||
/// Returns tooltip generated from annotation
|
||||
virtual QString getTooltip() const override { return m_tooltip; }
|
||||
|
||||
|
@@ -15,7 +15,9 @@
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include "pdfwidgetformmanager.h"
|
||||
#include "pdfdrawwidget.h"
|
||||
#include "pdfform.h"
|
||||
|
||||
#include <QKeyEvent>
|
||||
#include <QMouseEvent>
|
||||
|
@@ -16,6 +16,7 @@
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include "pdfform.h"
|
||||
#include "pdfdocumentdrawinterface.h"
|
||||
|
||||
namespace pdf
|
||||
{
|
||||
@@ -53,7 +54,7 @@ public:
|
||||
/// based on field value is drawn.
|
||||
/// \param parameters Parameters
|
||||
/// \param edit Draw editor or static contents
|
||||
virtual void draw(AnnotationDrawParameters& parameters, bool edit) const override;
|
||||
virtual void draw(AnnotationDrawParameters& parameters, bool edit) const;
|
||||
|
||||
protected:
|
||||
/// This function is called every time, the focus state changes
|
||||
|
35
Pdf4QtLibWidgets/sources/pdfwidgetsglobal.h
Normal file
35
Pdf4QtLibWidgets/sources/pdfwidgetsglobal.h
Normal file
@@ -0,0 +1,35 @@
|
||||
// Copyright (C) 2023 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT 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 Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef PDFWIDGETSGLOBAL_H
|
||||
#define PDFWIDGETSGLOBAL_H
|
||||
|
||||
#include <QtCore>
|
||||
#include <QtGlobal>
|
||||
|
||||
#include <pdf4qtlibwidgets_export.h>
|
||||
|
||||
#if !defined(PDF4QTLIBWIDGETSSHARED_EXPORT)
|
||||
#if defined(PDF4QTLIBWIDGETS_LIBRARY)
|
||||
# define PDF4QTLIBWIDGETSSHARED_EXPORT Q_DECL_EXPORT
|
||||
#else
|
||||
# define PDF4QTLIBWIDGETSSHARED_EXPORT Q_DECL_IMPORT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#endif // PDFWIDGETSGLOBAL_H
|
@@ -18,6 +18,7 @@
|
||||
#ifndef PDFWIDGETTOOL_H
|
||||
#define PDFWIDGETTOOL_H
|
||||
|
||||
#include "pdfwidgetsglobal.h"
|
||||
#include "pdfdrawspacecontroller.h"
|
||||
#include "pdftextlayout.h"
|
||||
#include "pdfsnapper.h"
|
||||
|
@@ -18,6 +18,7 @@
|
||||
#ifndef PDFWIDGETUTILS_H
|
||||
#define PDFWIDGETUTILS_H
|
||||
|
||||
#include "pdfwidgetsglobal.h"
|
||||
#include "pdfglobal.h"
|
||||
|
||||
#include <QIcon>
|
||||
|
Reference in New Issue
Block a user