mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-02-05 20:03:40 +01:00
Fixing bugs - annotation rendering
This commit is contained in:
parent
0b2d94d115
commit
e124ae9135
@ -21,6 +21,7 @@
|
||||
#include "pdfpainter.h"
|
||||
#include "pdfdrawspacecontroller.h"
|
||||
#include "pdfcms.h"
|
||||
#include "pdfwidgetutils.h"
|
||||
|
||||
namespace pdf
|
||||
{
|
||||
@ -766,7 +767,7 @@ void PDFAnnotationManager::drawPage(QPainter* painter,
|
||||
const PDFPage* page = m_document->getCatalog()->getPage(pageIndex);
|
||||
Q_ASSERT(page);
|
||||
|
||||
const PDFRenderer::Features features = m_proxy->getFeatures();
|
||||
PDFRenderer::Features features = m_proxy->getFeatures();
|
||||
PDFFontCache* fontCache = m_proxy->getFontCache();
|
||||
const PDFCMSPointer cms = m_proxy->getCMSManager()->getCurrentCMS();
|
||||
const PDFOptionalContentActivity* optionalActivity = m_proxy->getOptionalContentActivity();
|
||||
@ -775,6 +776,14 @@ void PDFAnnotationManager::drawPage(QPainter* painter,
|
||||
|
||||
for (PageAnnotation& annotation : annotations.annotations)
|
||||
{
|
||||
const PDFAnnotation::Flags annotationFlags = annotation.annotation->getFlags();
|
||||
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
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
PDFObject appearanceStreamObject = m_document->getObject(getAppearanceStream(annotation));
|
||||
if (!appearanceStreamObject.isStream())
|
||||
{
|
||||
@ -801,7 +810,7 @@ void PDFAnnotationManager::drawPage(QPainter* painter,
|
||||
|
||||
// "Unrotate" user coordinate space, if NoRotate flag is set
|
||||
QMatrix userSpaceToDeviceSpace = pagePointToDevicePointMatrix;
|
||||
if (annotation.annotation->getFlags().testFlag(PDFAnnotation::NoRotate))
|
||||
if (annotationFlags.testFlag(PDFAnnotation::NoRotate))
|
||||
{
|
||||
PDFReal rotationAngle = 0.0;
|
||||
switch (page->getPageRotation())
|
||||
@ -837,6 +846,23 @@ void PDFAnnotationManager::drawPage(QPainter* painter,
|
||||
userSpaceToDeviceSpace = finalMatrix * userSpaceToDeviceSpace;
|
||||
}
|
||||
|
||||
if (annotationFlags.testFlag(PDFAnnotation::NoZoom))
|
||||
{
|
||||
// Jakub Melka: we must adjust annotation rectangle to disable zoom. We calculate
|
||||
// inverse zoom as square root of absolute value of determinant of scale matrix.
|
||||
// Determinant corresponds approximately to zoom squared, and if we will have
|
||||
// unrotated matrix, and both axes are scaled by same value, then determinant will
|
||||
// be exactly zoom squared. Also, we will adjust to target device logical DPI,
|
||||
// if we, for example are using 4K, or 8K monitors.
|
||||
qreal zoom = 1.0 / qSqrt(qAbs(pagePointToDevicePointMatrix.determinant()));
|
||||
zoom = PDFWidgetUtils::scaleDPI_x(painter->device(), zoom);
|
||||
|
||||
QRectF unzoomedRect(annotationRectangle.bottomLeft(), annotationRectangle.size() * zoom);
|
||||
unzoomedRect.translate(0, -unzoomedRect.height());
|
||||
annotationRectangle = unzoomedRect;
|
||||
features.setFlag(PDFRenderer::ClipToCropBox, false);
|
||||
}
|
||||
|
||||
// Jakub Melka: perform algorithm 8.1, defined in PDF 1.7 reference,
|
||||
// chapter 8.4.4 Appearance streams.
|
||||
|
||||
@ -844,11 +870,12 @@ void PDFAnnotationManager::drawPage(QPainter* painter,
|
||||
QRectF transformedAppearanceBox = formMatrix.mapRect(formBoundingBox);
|
||||
|
||||
// Step 2) - calculate matrix A, which maps from form space to annotation space
|
||||
// Matrix A transforms from form space to transformed appearance box space
|
||||
const PDFReal scaleX = transformedAppearanceBox.width() / formBoundingBox.width();
|
||||
const PDFReal scaleY = transformedAppearanceBox.height() / formBoundingBox.height();
|
||||
const PDFReal translateX = annotationRectangle.left() - formBoundingBox.left() * scaleX;
|
||||
const PDFReal translateY = annotationRectangle.bottom() - formBoundingBox.bottom() * scaleY;
|
||||
// Matrix A transforms from transformed appearance box space to the
|
||||
// annotation rectangle.
|
||||
const PDFReal scaleX = annotationRectangle.width() / transformedAppearanceBox.width();
|
||||
const PDFReal scaleY = annotationRectangle.height() / transformedAppearanceBox.height();
|
||||
const PDFReal translateX = annotationRectangle.left() - transformedAppearanceBox.left() * scaleX;
|
||||
const PDFReal translateY = annotationRectangle.bottom() - transformedAppearanceBox.bottom() * scaleY;
|
||||
QMatrix A(scaleX, 0.0, 0.0, scaleY, translateX, translateY);
|
||||
|
||||
// Step 3) - compute final matrix AA
|
||||
@ -919,4 +946,14 @@ PDFAnnotationManager::PageAnnotations& PDFAnnotationManager::getPageAnnotations(
|
||||
return it->second;
|
||||
}
|
||||
|
||||
PDFAnnotationManager::Target PDFAnnotationManager::getTarget() const
|
||||
{
|
||||
return m_target;
|
||||
}
|
||||
|
||||
void PDFAnnotationManager::setTarget(Target target)
|
||||
{
|
||||
m_target = target;
|
||||
}
|
||||
|
||||
} // namespace pdf
|
||||
|
@ -1036,6 +1036,13 @@ private:
|
||||
using BaseClass = QObject;
|
||||
|
||||
public:
|
||||
|
||||
enum class Target
|
||||
{
|
||||
View,
|
||||
Print
|
||||
};
|
||||
|
||||
explicit PDFAnnotationManager(PDFDrawWidgetProxy* proxy, QObject* parent);
|
||||
virtual ~PDFAnnotationManager() override;
|
||||
|
||||
@ -1047,6 +1054,9 @@ public:
|
||||
|
||||
void setDocument(const PDFDocument* document);
|
||||
|
||||
Target getTarget() const;
|
||||
void setTarget(Target target);
|
||||
|
||||
private:
|
||||
struct PageAnnotation
|
||||
{
|
||||
@ -1074,6 +1084,7 @@ private:
|
||||
const PDFDocument* m_document;
|
||||
PDFDrawWidgetProxy* m_proxy;
|
||||
mutable std::map<PDFInteger, PageAnnotations> m_pageAnnotations;
|
||||
Target m_target = Target::View;
|
||||
};
|
||||
|
||||
} // namespace pdf
|
||||
|
@ -50,6 +50,13 @@ int PDFWidgetUtils::scaleDPI_x(QPaintDevice* device, int unscaledSize)
|
||||
return (logicalDPI_x / defaultDPI_x) * unscaledSize;
|
||||
}
|
||||
|
||||
PDFReal PDFWidgetUtils::scaleDPI_x(QPaintDevice* device, PDFReal unscaledSize)
|
||||
{
|
||||
const double logicalDPI_x = device->logicalDpiX();
|
||||
const double defaultDPI_x = qt_default_dpi_x();
|
||||
return (logicalDPI_x / defaultDPI_x) * unscaledSize;
|
||||
}
|
||||
|
||||
void PDFWidgetUtils::scaleWidget(QWidget* widget, QSize unscaledSize)
|
||||
{
|
||||
const double logicalDPI_x = widget->logicalDpiX();
|
||||
|
@ -37,6 +37,10 @@ public:
|
||||
/// \param device Paint device to obtain logical DPI for scaling
|
||||
static int scaleDPI_x(QPaintDevice* device, int unscaledSize);
|
||||
|
||||
/// Scale horizontal DPI value
|
||||
/// \param device Paint device to obtain logical DPI for scaling
|
||||
static PDFReal scaleDPI_x(QPaintDevice* device, PDFReal unscaledSize);
|
||||
|
||||
/// Scales widget based on DPI
|
||||
/// \param widget Widget to be scaled
|
||||
/// \param unscaledSize Unscaled size of the widget
|
||||
|
Loading…
x
Reference in New Issue
Block a user