Refactoring of annotation drawing

This commit is contained in:
Jakub Melka
2020-05-24 18:42:11 +02:00
parent 81f27e87ac
commit 00e141129a
2 changed files with 257 additions and 139 deletions

View File

@ -1084,30 +1084,48 @@ void PDFAnnotationManager::drawPage(QPainter* painter,
Q_ASSERT(m_cmsManager);
Q_ASSERT(m_optionalActivity);
int fontCacheLock = 0;
const PDFCMSPointer cms = m_cmsManager->getCurrentCMS();
m_fontCache->setCacheShrinkEnabled(this, false);
m_fontCache->setCacheShrinkEnabled(&fontCacheLock, false);
const PageAnnotation* annotationDrawnByEditor = nullptr;
for (const PageAnnotation& annotation : annotations.annotations)
{
try
{
const PDFAnnotation::Flags annotationFlags = annotation.annotation->getEffectiveFlags();
if (annotationFlags.testFlag(PDFAnnotation::Hidden) || // Annotation is completely hidden
(m_target == Target::Print && !annotationFlags.testFlag(PDFAnnotation::Print)) || // Target is print and annotation is marked as not printed
(m_target == Target::View && annotationFlags.testFlag(PDFAnnotation::NoView)) || // Target is view, and annotation is disabled for screen
annotation.annotation->isReplyTo()) // Annotation is reply to another annotation, display just the first annotation
// If annotation draw is not enabled, then skip it
if (!isAnnotationDrawEnabled(annotation))
{
continue;
}
const PDFFormFieldWidgetEditor* editor = nullptr;
const bool isWidget = annotation.annotation->getType() == AnnotationType::Widget;
if (isWidget && m_formManager)
if (isAnnotationDrawnByEditor(annotation))
{
editor = m_formManager->getEditor(m_formManager->getFormFieldForWidget(annotation.annotation->getSelfReference()));
Q_ASSERT(!annotationDrawnByEditor);
annotationDrawnByEditor = &annotation;
continue;
}
const bool isEditorDrawEnabled = editor && editor->isEditorDrawEnabled();
drawAnnotation(annotation, pagePointToDevicePointMatrix, page, cms.data(), false, errors, painter);
}
if (annotationDrawnByEditor)
{
drawAnnotation(*annotationDrawnByEditor, pagePointToDevicePointMatrix, page, cms.data(), true, errors, painter);
}
m_fontCache->setCacheShrinkEnabled(&fontCacheLock, true);
}
}
void PDFAnnotationManager::drawAnnotation(const PageAnnotation& annotation,
const QMatrix& pagePointToDevicePointMatrix,
const PDFPage* page,
const PDFCMS* cms,
bool isEditorDrawEnabled,
QList<PDFRenderError>& errors,
QPainter* painter) const
{
try
{
PDFObject appearanceStreamObject = m_document->getObject(getAppearanceStream(annotation));
if (!appearanceStreamObject.isStream() || isEditorDrawEnabled)
{
@ -1116,10 +1134,64 @@ void PDFAnnotationManager::drawPage(QPainter* painter,
// We do not draw annotation, if it is not ignored and annotation
// has reference to optional content.
drawAnnotationDirect(annotation, pagePointToDevicePointMatrix, page, cms, isEditorDrawEnabled, painter);
}
else
{
drawAnnotationUsingAppearanceStream(annotation, appearanceStreamObject, pagePointToDevicePointMatrix, page, cms, painter);
}
}
catch (PDFException exception)
{
errors.push_back(PDFRenderError(RenderErrorType::Error, exception.getMessage()));
}
catch (PDFRendererException exception)
{
errors.push_back(exception.getError());
}
}
bool PDFAnnotationManager::isAnnotationDrawEnabled(const PageAnnotation& annotation) const
{
const PDFAnnotation::Flags annotationFlags = annotation.annotation->getEffectiveFlags();
return !(annotationFlags.testFlag(PDFAnnotation::Hidden) || // Annotation is completely hidden
(m_target == Target::Print && !annotationFlags.testFlag(PDFAnnotation::Print)) || // Target is print and annotation is marked as not printed
(m_target == Target::View && annotationFlags.testFlag(PDFAnnotation::NoView)) || // Target is view, and annotation is disabled for screen
annotation.annotation->isReplyTo()); // Annotation is reply to another annotation, display just the first annotation
}
bool PDFAnnotationManager::isAnnotationDrawnByEditor(const PageAnnotation& annotation) const
{
if (!m_formManager)
{
return false;
}
const PDFFormFieldWidgetEditor* editor = nullptr;
if (annotation.annotation->getType() == AnnotationType::Widget)
{
editor = m_formManager->getEditor(m_formManager->getFormFieldForWidget(annotation.annotation->getSelfReference()));
return editor && editor->isEditorDrawEnabled();
}
return false;
}
void PDFAnnotationManager::drawAnnotationDirect(const PageAnnotation& annotation,
const QMatrix& pagePointToDevicePointMatrix,
const PDFPage* page,
const PDFCMS* cms,
bool isEditorDrawEnabled,
QPainter* painter) const
{
if (!m_features.testFlag(PDFRenderer::IgnoreOptionalContent) &&
annotation.annotation->getOptionalContent().isValid())
{
continue;
PDFPainter pdfPainter(painter, m_features, pagePointToDevicePointMatrix, page, m_document, m_fontCache, cms, m_optionalActivity, m_meshQualitySettings);
if (pdfPainter.isContentSuppressedByOC(annotation.annotation->getOptionalContent()))
{
return;
}
}
QRectF annotationRectangle = annotation.annotation->getRectangle();
@ -1149,13 +1221,20 @@ void PDFAnnotationManager::drawPage(QPainter* painter,
PDFPainterStateGuard guard(painter);
drawWidgetAnnotationHighlight(annotationRectangle, annotation.annotation.get(), painter, pagePointToDevicePointMatrix);
}
continue;
}
void PDFAnnotationManager::drawAnnotationUsingAppearanceStream(const PageAnnotation& annotation,
const PDFObject& appearanceStreamObject,
const QMatrix& pagePointToDevicePointMatrix,
const PDFPage* page,
const PDFCMS* cms,
QPainter* painter) const
{
PDFDocumentDataLoaderDecorator loader(m_document);
const PDFStream* formStream = appearanceStreamObject.getStream();
const PDFDictionary* formDictionary = formStream->getDictionary();
const PDFAnnotation::Flags annotationFlags = annotation.annotation->getEffectiveFlags();
QRectF annotationRectangle = annotation.annotation->getRectangle();
QRectF formBoundingBox = loader.readRectangle(formDictionary->get("BBox"), QRectF());
QMatrix formMatrix = loader.readMatrixFromDictionary(formDictionary, "Matrix", QMatrix());
@ -1166,11 +1245,12 @@ void PDFAnnotationManager::drawPage(QPainter* painter,
if (formBoundingBox.isEmpty() || annotationRectangle.isEmpty())
{
// Form bounding box is empty
continue;
return;
}
QMatrix userSpaceToDeviceSpace = prepareTransformations(pagePointToDevicePointMatrix, painter->device(), annotationFlags, page, annotationRectangle);
PDFRenderer::Features features = m_features;
if (annotationFlags.testFlag(PDFAnnotation::NoZoom))
{
features.setFlag(PDFRenderer::ClipToCropBox, false);
@ -1199,7 +1279,7 @@ void PDFAnnotationManager::drawPage(QPainter* painter,
// Draw annotation
{
PDFPainterStateGuard guard(painter);
PDFPainter pdfPainter(painter, features, userSpaceToDeviceSpace, page, m_document, m_fontCache, cms.get(), m_optionalActivity, m_meshQualitySettings);
PDFPainter pdfPainter(painter, features, userSpaceToDeviceSpace, page, m_document, m_fontCache, cms, m_optionalActivity, m_meshQualitySettings);
pdfPainter.initializeProcessor();
// Jakub Melka: we must check, that we do not display annotation disabled by optional content
@ -1222,21 +1302,6 @@ void PDFAnnotationManager::drawPage(QPainter* painter,
drawWidgetAnnotationHighlight(annotationRectangle, annotation.annotation.get(), painter, userSpaceToDeviceSpace);
}
}
catch (PDFException exception)
{
errors.push_back(PDFRenderError(RenderErrorType::Error, exception.getMessage()));
continue;
}
catch (PDFRendererException exception)
{
errors.push_back(exception.getError());
continue;
}
}
m_fontCache->setCacheShrinkEnabled(this, true);
}
}
void PDFAnnotationManager::setDocument(const PDFModifiedDocument& document)
{

View File

@ -1400,6 +1400,59 @@ protected:
QPainter* painter,
QMatrix userSpaceToDeviceSpace) const;
/// Returns true, if given annotation should be drawn
/// \param annotation Annotation
bool isAnnotationDrawEnabled(const PageAnnotation& annotation) const;
/// Returns true, if annotation is drawn by editor (from form widget)
/// \param annotation Annotation
bool isAnnotationDrawnByEditor(const PageAnnotation& annotation) const;
/// Draws annotation
/// \param pageAnnotation Page annotation
/// \param pagePointToDevicePointMatrix Page point to device point matrix
/// \param page Page
/// \param cms Color management system
/// \param isEditorDrawEnabled Is editor draw enabled?
/// \param errors Errors list (where draw errors are stored)
/// \param painter Painter
void drawAnnotation(const PageAnnotation& annotation,
const QMatrix& pagePointToDevicePointMatrix,
const PDFPage* page,
const PDFCMS* cms,
bool isEditorDrawEnabled,
QList<PDFRenderError>& errors,
QPainter* painter) const;
/// Draws annotation by direct drawing, not using annotation's
/// appearance stream.
/// \param pageAnnotation Page annotation
/// \param pagePointToDevicePointMatrix Page point to device point matrix
/// \param page Page
/// \param cms Color management system
/// \param isEditorDrawEnabled Is annotation drawn by form widget editor?
/// \param painter Painter
void drawAnnotationDirect(const PageAnnotation& annotation,
const QMatrix& pagePointToDevicePointMatrix,
const PDFPage* page,
const PDFCMS* cms,
bool isEditorDrawEnabled,
QPainter* painter) const;
/// Draws annotation using annotation's appearance stream.
/// \param pageAnnotation Page annotation
/// \param appearanceStreamObject Object with appearance stream
/// \param pagePointToDevicePointMatrix Page point to device point matrix
/// \param page Page
/// \param cms Color management system
/// \param painter Painter
void drawAnnotationUsingAppearanceStream(const PageAnnotation& annotation,
const PDFObject& appearanceStreamObject,
const QMatrix& pagePointToDevicePointMatrix,
const PDFPage* page,
const PDFCMS* cms,
QPainter* painter) const;
const PDFDocument* m_document;
PDFFontCache* m_fontCache;