Rendering options

This commit is contained in:
Jakub Melka
2019-07-06 15:55:37 +02:00
parent 584211bf36
commit 9ed17fc8ca
11 changed files with 241 additions and 24 deletions

View File

@@ -347,7 +347,8 @@ PDFDrawWidgetProxy::PDFDrawWidgetProxy(QObject* parent) :
m_controller(nullptr),
m_widget(nullptr),
m_horizontalScrollbar(nullptr),
m_verticalScrollbar(nullptr)
m_verticalScrollbar(nullptr),
m_features(PDFRenderer::Antialiasing | PDFRenderer::TextAntialiasing)
{
m_controller = new PDFDrawSpaceController(this);
connect(m_controller, &PDFDrawSpaceController::drawSpaceChanged, this, &PDFDrawWidgetProxy::update);
@@ -549,7 +550,7 @@ void PDFDrawWidgetProxy::draw(QPainter* painter, QRect rect)
// Clear the page space by white color
painter->fillRect(placedRect, Qt::white);
PDFRenderer renderer(m_controller->getDocument(), m_controller->getFontCache(), m_controller->getOptionalContentActivity());
PDFRenderer renderer(m_controller->getDocument(), m_controller->getFontCache(), m_controller->getOptionalContentActivity(), m_features);
QList<PDFRenderError> errors = renderer.render(painter, placedRect, item.pageIndex);
if (!errors.empty())
@@ -810,4 +811,18 @@ void PDFDrawWidgetProxy::updateVerticalScrollbarFromOffset()
}
}
PDFRenderer::Features PDFDrawWidgetProxy::getFeatures() const
{
return m_features;
}
void PDFDrawWidgetProxy::setFeatures(PDFRenderer::Features features)
{
if (m_features != features)
{
m_features = features;
emit repaintNeeded();
}
}
} // namespace pdf

View File

@@ -213,6 +213,9 @@ public:
static constexpr PDFReal ZOOM_STEP = 1.2;
PDFRenderer::Features getFeatures() const;
void setFeatures(PDFRenderer::Features features);
signals:
void drawSpaceChanged();
void pageLayoutChanged();
@@ -326,6 +329,9 @@ private:
/// Current page layout
Layout m_layout;
/// Renderer features
PDFRenderer::Features m_features;
};
} // namespace pdf

View File

@@ -1866,6 +1866,23 @@ void PDFPageContentProcessor::operatorPaintXObject(PDFPageContentProcessor::PDFO
{
if (m_xobjectDictionary)
{
// According to the specification, XObjects are skipped entirely, as no operator was invoked.
if (m_xobjectDictionary->hasKey("OC"))
{
const PDFObject& object = m_xobjectDictionary->get("OC");
if (object.isReference())
{
if (isContentSuppressedByOC(object.getReference()))
{
return;
}
}
else
{
throw PDFRendererException(RenderErrorType::Error, PDFTranslationContext::tr("Reference to optional content expected."));
}
}
const PDFObject& object = m_document->getObject(m_xobjectDictionary->get(name.name));
if (object.isStream())
{
@@ -1969,8 +1986,6 @@ void PDFPageContentProcessor::operatorMarkedContentBegin(PDFOperandName name)
void PDFPageContentProcessor::operatorMarkedContentBeginWithProperties(PDFOperandName name, PDFObject properties)
{
// TODO: Handle optional content of images/forms
// Handle the optional content
if (name.name == "OC")
{

View File

@@ -406,6 +406,10 @@ protected:
/// Returns true, if graphic content is suppressed
bool isContentSuppressed() const;
/// Computes visibility of OCG/OCMD - returns false, if it is not suppressed,
/// or true, if it is suppressed.
virtual bool isContentSuppressedByOC(PDFObjectReference ocgOrOcmd);
private:
/// Initializes the resources dictionaries
void initDictionaries(const PDFObject& resourcesObject);
@@ -665,10 +669,6 @@ private:
/// Read object from operand stack
PDFObject readObjectFromOperandStack(size_t startPosition) const;
/// Computes visibility of OCG/OCMD - returns false, if it is not suppressed,
/// or true, if it is suppressed.
bool isContentSuppressedByOC(PDFObjectReference ocgOrOcmd);
const PDFPage* m_page;
const PDFDocument* m_document;
const PDFFontCache* m_fontCache;

View File

@@ -81,8 +81,6 @@ void PDFPainter::performPathPainting(const QPainterPath& path, bool stroke, bool
m_painter->setBrush(Qt::NoBrush);
}
m_painter->setRenderHint(QPainter::Antialiasing, m_features.testFlag(PDFRenderer::Antialiasing));
Q_ASSERT(path.fillRule() == fillRule);
m_painter->drawPath(path);
}
@@ -162,6 +160,16 @@ void PDFPainter::performRestoreGraphicState(ProcessOrder order)
}
}
bool PDFPainter::isContentSuppressedByOC(PDFObjectReference ocgOrOcmd)
{
if (m_features.testFlag(PDFRenderer::IgnoreOptionalContent))
{
return false;
}
return PDFPageContentProcessor::isContentSuppressedByOC(ocgOrOcmd);
}
QPen PDFPainter::getCurrentPenImpl() const
{
const PDFPageContentProcessorState* graphicState = getGraphicState();

View File

@@ -57,6 +57,7 @@ protected:
virtual void performUpdateGraphicsState(const PDFPageContentProcessorState& state) override;
virtual void performSaveGraphicState(ProcessOrder order) override;
virtual void performRestoreGraphicState(ProcessOrder order) override;
virtual bool isContentSuppressedByOC(PDFObjectReference ocgOrOcmd) override;
private:
/// Returns current pen

View File

@@ -22,11 +22,11 @@
namespace pdf
{
PDFRenderer::PDFRenderer(const PDFDocument* document, const PDFFontCache* fontCache, const PDFOptionalContentActivity* optionalContentActivity) :
PDFRenderer::PDFRenderer(const PDFDocument* document, const PDFFontCache* fontCache, const PDFOptionalContentActivity* optionalContentActivity, Features features) :
m_document(document),
m_fontCache(fontCache),
m_optionalContentActivity(optionalContentActivity),
m_features(Antialiasing | TextAntialiasing)
m_features(features)
{
Q_ASSERT(document);
}

View File

@@ -32,17 +32,19 @@ class PDFOptionalContentActivity;
class PDFRenderer
{
public:
explicit PDFRenderer(const PDFDocument* document, const PDFFontCache* fontCache, const PDFOptionalContentActivity* optionalContentActivity);
enum Feature
{
Antialiasing = 0x0001, ///< Antialiasing for lines, shapes, etc.
TextAntialiasing = 0x0002, ///< Antialiasing for drawing text
SmoothImages = 0x0004 ///< Adjust images to the device space using smooth transformation (slower, but better performance quality)
Antialiasing = 0x0001, ///< Antialiasing for lines, shapes, etc.
TextAntialiasing = 0x0002, ///< Antialiasing for drawing text
SmoothImages = 0x0004, ///< Adjust images to the device space using smooth transformation (slower, but better image quality)
IgnoreOptionalContent = 0x0008, ///< Ignore optional content (so all is drawn ignoring settings of optional content)
};
Q_DECLARE_FLAGS(Features, Feature)
explicit PDFRenderer(const PDFDocument* document, const PDFFontCache* fontCache, const PDFOptionalContentActivity* optionalContentActivity, Features features);
/// Paints desired page onto the painter. Page is painted in the rectangle using best-fit method.
/// If the page doesn't exist, then error is returned. No exception is thrown. Rendering errors
/// are reported and returned in the error list. If no error occured, empty list is returned.
@@ -56,6 +58,9 @@ public:
/// Rendering errors are reported and returned in the error list. If no error occured, empty list is returned.
QList<PDFRenderError> render(QPainter* painter, const QMatrix& matrix, size_t pageIndex) const;
/// Returns default renderer features
static constexpr Features getDefaultFeatures() { return Antialiasing | TextAntialiasing; }
private:
const PDFDocument* m_document;
const PDFFontCache* m_fontCache;