[poppler] 11 commits - poppler/Annot.cc poppler/Annot.h poppler/Gfx.cc poppler/Gfx.h qt4/demos qt4/src qt5/demos qt5/src

Albert Astals Cid aacid at kemper.freedesktop.org
Sun Jun 30 12:10:50 PDT 2013


 poppler/Annot.cc                     |  119 ++++++++++++++--------------
 poppler/Annot.h                      |   14 +--
 poppler/Gfx.cc                       |   41 ++++++++-
 poppler/Gfx.h                        |    3 
 qt4/demos/navigationtoolbar.cpp      |   15 +++
 qt4/demos/navigationtoolbar.h        |    4 
 qt4/demos/pageview.cpp               |   24 +++++
 qt4/demos/pageview.h                 |    3 
 qt4/demos/viewer.cpp                 |    2 
 qt4/src/poppler-annotation-private.h |    7 -
 qt4/src/poppler-annotation.cc        |  147 +++++++++++++++++++++++++----------
 qt4/src/poppler-annotation.h         |  143 ++++++++++++++++++++++++++++++++--
 qt5/demos/navigationtoolbar.cpp      |   15 +++
 qt5/demos/navigationtoolbar.h        |    4 
 qt5/demos/pageview.cpp               |   24 +++++
 qt5/demos/pageview.h                 |    3 
 qt5/demos/viewer.cpp                 |    2 
 qt5/src/poppler-annotation-private.h |    7 -
 qt5/src/poppler-annotation.cc        |  147 +++++++++++++++++++++++++----------
 qt5/src/poppler-annotation.h         |  143 ++++++++++++++++++++++++++++++++--
 20 files changed, 696 insertions(+), 171 deletions(-)

New commits:
commit 19f8a88bba6022b8172477e6f52dfd36b2fc5e92
Author: Fabio D'Urso <fabiodurso at hotmail.it>
Date:   Thu Mar 7 00:20:15 2013 +0100

    qt5: Free some temporary memory in TextAnnotationPrivate::createNativeAnnot
    
    There's no need to keep this buffer around after it has been flushed

diff --git a/qt5/src/poppler-annotation.cc b/qt5/src/poppler-annotation.cc
index c32771e..baf0500 100644
--- a/qt5/src/poppler-annotation.cc
+++ b/qt5/src/poppler-annotation.cc
@@ -1684,6 +1684,8 @@ Annot* TextAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *
 
     delete q;
 
+    inplaceCallout.clear(); // Free up memory
+
     return pdfAnnot;
 }
 
commit 8bac4d1e43ce9a4c66fddc8430d7bed2d9aabba1
Author: Fabio D'Urso <fabiodurso at hotmail.it>
Date:   Tue Jun 25 20:09:00 2013 +0200

    qt5: Some documentation about annotations
    
    * Removed incorrect hint "Use uniqueName to test for Annotation
      equality": uniqueNames are optional and we don't actually guarantee
      uniqueness
    * Added "How to add annotations" and "FixedRotation flag specifics"
      sections in the Annotation class page
    * Added links from enum Annotation::SubType items to actual subclasses
    * Added documentation for annotation flags that are known to work
    * Added "see also" links between annotation flag and boundary
      setters/getters
    * Added warning on Annotation::setPopup to tell that it's currently not
      implemented

diff --git a/qt5/src/poppler-annotation.h b/qt5/src/poppler-annotation.h
index 19f6bd0..afdca33 100644
--- a/qt5/src/poppler-annotation.h
+++ b/qt5/src/poppler-annotation.h
@@ -5,7 +5,7 @@
  * Copyright (C) 2010, Philip Lorenz <lorenzph+freedesktop at gmail.com>
  * Copyright (C) 2012, Tobias Koenig <tokoe at kdab.com>
  * Copyright (C) 2012, Guillermo A. Amaral B. <gamaral at kde.org>
- * Copyright (C) 2012, Fabio D'Urso <fabiodurso at hotmail.it>
+ * Copyright (C) 2012, 2013 Fabio D'Urso <fabiodurso at hotmail.it>
  * Copyright (C) 2013, Anthony Granger <grangeranthony at gmail.com>
  * Adapting code from
  *   Copyright (C) 2004 by Enrico Ros <eros.kde at email.it>
@@ -102,7 +102,71 @@ class POPPLER_QT5_EXPORT AnnotationUtils
  * contained by a Page in the document.
  *
  * \warning Different Annotation objects might point to the same annotation.
- *          Use uniqueName to test for Annotation equality
+ *
+ * \section annotCreation How to add annotations
+ *
+ * Create an Annotation object of the desired subclass (for example
+ * TextAnnotation) and set its properties:
+ * @code
+ * Poppler::TextAnnotation* myann = new Poppler::TextAnnotation(Poppler::TextAnnotation::InPlace);
+ * myann->setBoundary(QRectF(0.1, 0.1, 0.2, 0.2)); // normalized coordinates: (0,0) is top-left, (1,1) is bottom-right
+ * myann->setContents("Hello, world!");
+ * @endcode
+ * \note Always set a boundary rectangle, or nothing will be shown!
+ *
+ * Obtain a pointer to the Page where you want to add the annotation (refer to
+ * \ref req for instructions) and add the annotation:
+ * @code
+ * Poppler::Page* mypage = ...;
+ * mypage->addAnnotation(myann);
+ * @endcode
+ *
+ * You can keep on editing the annotation after it has been added to the page:
+ * @code
+ * myann->setContents("World, hello!"); // Let's change text...
+ * myann->setAuthor("Your name here");  // ...and set an author too
+ * @endcode
+ *
+ * When you're done with editing the annotation, you must destroy the Annotation
+ * object:
+ * @code
+ * delete myann;
+ * @endcode
+ *
+ * Use the PDFConverter class to save the modified document.
+ *
+ * \section annotFixedRotation FixedRotation flag specifics
+ *
+ * According to the PDF specification, annotations whose
+ * Annotation::FixedRotation flag is set must always be shown in their original
+ * orientation, no matter what the current rendering rotation or the page's
+ * Page::orientation() values are. In comparison with regular annotations, such
+ * annotations should therefore be transformed by an extra rotation at rendering
+ * time to "undo" such context-related rotations, which is equal to
+ * <code>-(rendering_rotation + page_orientation)</code>. The rotation pivot
+ * is the top-left corner of the boundary rectangle.
+ *
+ * In practice, %Poppler's \ref Page::renderToImage only "unrotates" the
+ * page orientation, and does <b>not</b> unrotate the rendering rotation.
+ * This ensures consistent renderings at different Page::Rotation values:
+ * annotations are always positioned as if they were being positioned at the
+ * default page orientation.
+ *
+ * Just like regular annotations, %Poppler Qt4 exposes normalized coordinates
+ * relative to the page's default orientation. However, behind the scenes, the
+ * coordinate system is different and %Poppler transparently transforms each
+ * shape. If you never call either Annotation::setFlags or
+ * Annotation::setBoundary, you don't need to worry about this; but if you do
+ * call them, then you need to adhere to the following rules:
+ *  - Whenever you toggle the Annotation::FixedRotation flag, you <b>must</b>
+ *    set again the boundary rectangle first, and then you <b>must</b> set
+ *    again any other geometry-related property.
+ *  - Whenever you modify the boundary rectangle of an annotation whose
+ *    Annotation::FixedRotation flag is set, you <b>must</b> set again any other
+ *    geometry-related property.
+ *
+ * These two rules are necessary to make %Poppler's transparent coordinate
+ * conversion work properly.
  */
 class POPPLER_QT5_EXPORT Annotation
 {
@@ -112,12 +176,50 @@ class POPPLER_QT5_EXPORT Annotation
 
   public:
     // enum definitions
+    /**
+     * Annotation subclasses
+     *
+     * \sa subType()
+     */
     // WARNING!!! oKular uses that very same values so if you change them notify the author!
-    enum SubType { AText = 1, ALine = 2, AGeom = 3, AHighlight = 4, AStamp = 5,
-                   AInk = 6, ALink = 7, ACaret = 8, AFileAttachment = 9, ASound = 10,
-                   AMovie = 11, AScreen = 12 /** \since 0.20 */, AWidget = 13 /** \since 0.22 */, A_BASE = 0 };
-    enum Flag { Hidden = 1, FixedSize = 2, FixedRotation = 4, DenyPrint = 8,
-                DenyWrite = 16, DenyDelete = 32, ToggleHidingOnMouse = 64, External = 128 };
+    enum SubType
+    {
+        AText = 1,            ///< TextAnnotation
+        ALine = 2,            ///< LineAnnotation
+        AGeom = 3,            ///< GeomAnnotation
+        AHighlight = 4,       ///< HighlightAnnotation
+        AStamp = 5,           ///< StampAnnotation
+        AInk = 6,             ///< InkAnnotation
+        ALink = 7,            ///< LinkAnnotation
+        ACaret = 8,           ///< CaretAnnotation
+        AFileAttachment = 9,  ///< FileAttachmentAnnotation
+        ASound = 10,          ///< SoundAnnotation
+        AMovie = 11,          ///< MovieAnnotation
+        AScreen = 12,         ///< ScreenAnnotation \since 0.20
+        AWidget = 13,         ///< WidgetAnnotation \since 0.22
+        A_BASE = 0
+    };
+
+    /**
+     * Annotation flags
+     *
+     * They can be OR'd together (e.g. Annotation::FixedRotation | Annotation::DenyPrint).
+     *
+     * \sa flags(), setFlags(int)
+     */
+    // NOTE: Only flags that are known to work are documented
+    enum Flag
+    {
+        Hidden = 1,                ///< Do not display or print the annotation
+        FixedSize = 2,
+        FixedRotation = 4,         ///< Do not rotate the annotation according to page orientation and rendering rotation \warning Extra care is needed with this flag: see \ref annotFixedRotation
+        DenyPrint = 8,             ///< Do not print the annotation
+        DenyWrite = 16,
+        DenyDelete = 32,
+        ToggleHidingOnMouse = 64,
+        External = 128
+    };
+
     enum LineStyle { Solid = 1, Dashed = 2, Beveled = 4, Inset = 8, Underline = 16 };
     enum LineEffect { NoEffect = 1, Cloudy = 2};
     enum RevScope { Root = 0 /** \since 0.20 */, Reply = 1, Group = 2, Delete = 4 };
@@ -152,10 +254,35 @@ class POPPLER_QT5_EXPORT Annotation
     QDateTime creationDate() const;
     void setCreationDate( const QDateTime &date );
 
+    /**
+     * Returns this annotation's flags
+     *
+     * \sa Flag, setFlags(int)
+     */
     int flags() const;
+    /**
+     * Sets this annotation's flags
+     *
+     * \sa Flag, flags(), \ref annotFixedRotation
+     */
     void setFlags( int flags );
 
+    /**
+     * Returns this annotation's boundary rectangle in normalized coordinates
+     *
+     * \sa setBoundary(const QRectF&)
+     */
     QRectF boundary() const;
+    /**
+     * Sets this annotation's boundary rectangle
+     *
+     * The boundary rectangle is the smallest rectangle that contains the
+     * annotation.
+     *
+     * \warning This property is mandatory: you must always set this.
+     *
+     * \sa boundary(), \ref annotFixedRotation
+     */
     void setBoundary( const QRectF &boundary );
 
     /**
@@ -241,7 +368,7 @@ class POPPLER_QT5_EXPORT Annotation
 
     /// \since 0.20
     Popup popup() const;
-    /// \since 0.20
+    /// \warning Currently does nothing \since 0.20
     void setPopup( const Popup& popup );
 
     /// \since 0.20
commit 1d5fe3f20189fd3928121e954bcc8fa7278b39fb
Author: Fabio D'Urso <fabiodurso at hotmail.it>
Date:   Sat Mar 2 19:06:49 2013 +0100

    qt5: FixedRotation annotations' coordinate conversion
    
    FixedRotation(=flagNoRotate) annotations use a different coordinate
    system than regular annotations. This patch implements transparent
    conversion so that qt5 clients don't notice the difference.
    
    Important! When dealing with FixedRotation annotations, poppler-qt5
    clients will need to set geometry-related annotation properties in
    the following order:
     1) flags (because we need to know if this is a FixedRotation
        annotation or not)
     2) boundary (because we need to know what the topleft corner is,
        so that we can construct the conversion matrix)
     3) anything else
    
    This requirement will be documented in the next patch

diff --git a/qt5/src/poppler-annotation-private.h b/qt5/src/poppler-annotation-private.h
index 3bfb5da..c755eb3 100644
--- a/qt5/src/poppler-annotation-private.h
+++ b/qt5/src/poppler-annotation-private.h
@@ -1,7 +1,7 @@
 /* poppler-annotation-private.h: qt interface to poppler
  * Copyright (C) 2007, Pino Toscano <pino at kde.org>
  * Copyright (C) 2012, Tobias Koenig <tokoe at kdab.com>
- * Copyright (C) 2012, Fabio D'Urso <fabiodurso at hotmail.it>
+ * Copyright (C) 2012, 2013 Fabio D'Urso <fabiodurso at hotmail.it>
  * Copyright (C) 2012, Albert Astals Cid <aacid at kde.org>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -87,9 +87,10 @@ class AnnotationPrivate : public QSharedData
 
         /* The following helpers only work if pdfPage is set */
         void flushBaseAnnotationProperties();
-        void fillMTX(double MTX[6]) const;
+        void fillNormalizationMTX(double MTX[6], int pageRotation) const;
+        void fillTransformationMTX(double MTX[6]) const;
         QRectF fromPdfRectangle(const PDFRectangle &r) const;
-        PDFRectangle toPdfRectangle(const QRectF &r) const;
+        PDFRectangle boundaryToPdfRectangle(const QRectF &r, int flags) const;
         AnnotPath * toAnnotPath(const QLinkedList<QPointF> &l) const;
 
         /* Scan page for annotations, parentId=0 searches for root annotations */
diff --git a/qt5/src/poppler-annotation.cc b/qt5/src/poppler-annotation.cc
index 35cef49..c32771e 100644
--- a/qt5/src/poppler-annotation.cc
+++ b/qt5/src/poppler-annotation.cc
@@ -27,6 +27,7 @@
 #include <QtCore/QtAlgorithms>
 #include <QtXml/QDomElement>
 #include <QtGui/QColor>
+#include <QtGui/QTransform>
 
 // local includes
 #include "poppler-annotation.h"
@@ -198,19 +199,21 @@ void AnnotationPrivate::flushBaseAnnotationProperties()
     revisions.clear();
 }
 
-void AnnotationPrivate::fillMTX(double MTX[6]) const
+// Returns matrix to convert from user space coords (oriented according to the
+// specified rotation) to normalized coords
+void AnnotationPrivate::fillNormalizationMTX(double MTX[6], int pageRotation) const
 {
     Q_ASSERT ( pdfPage );
 
     // build a normalized transform matrix for this page at 100% scale
-    GfxState * gfxState = new GfxState( 72.0, 72.0, pdfPage->getCropBox(), pdfPage->getRotate(), gTrue );
+    GfxState * gfxState = new GfxState( 72.0, 72.0, pdfPage->getCropBox(), pageRotation, gTrue );
     double * gfxCTM = gfxState->getCTM();
 
     double w = pdfPage->getCropWidth();
     double h = pdfPage->getCropHeight();
 
     // Swap width and height if the page is rotated landscape or seascape
-    if ( pdfPage->getRotate() == 90 || pdfPage->getRotate() == 270 )
+    if ( pageRotation == 90 || pageRotation == 270 )
     {
         double t = w;
         w = h;
@@ -225,10 +228,51 @@ void AnnotationPrivate::fillMTX(double MTX[6]) const
     delete gfxState;
 }
 
+// Returns matrix to convert from user space coords (i.e. those that are stored
+// in the PDF file) to normalized coords (i.e. those that we expose to clients).
+// This method also applies a rotation around the top-left corner if the
+// FixedRotation flag is set.
+void AnnotationPrivate::fillTransformationMTX(double MTX[6]) const
+{
+    Q_ASSERT ( pdfPage );
+    Q_ASSERT ( pdfAnnot );
+
+    const int pageRotate = pdfPage->getRotate();
+
+    if ( pageRotate == 0 || ( pdfAnnot->getFlags() & Annot::flagNoRotate ) == 0 )
+    {
+        // Use the normalization matrix for this page's rotation
+        fillNormalizationMTX( MTX, pageRotate );
+    }
+    else
+    {
+        // Clients expect coordinates relative to this page's rotation, but
+        // FixedRotation annotations internally use unrotated coordinates:
+        // construct matrix to both normalize and rotate coordinates using the
+        // top-left corner as rotation pivot
+
+        double MTXnorm[6];
+        fillNormalizationMTX( MTXnorm, pageRotate );
+
+        QTransform transform( MTXnorm[0], MTXnorm[1], MTXnorm[2],
+                              MTXnorm[3], MTXnorm[4], MTXnorm[5] );
+        transform.translate( +pdfAnnot->getXMin(), +pdfAnnot->getYMax() );
+        transform.rotate( pageRotate );
+        transform.translate( -pdfAnnot->getXMin(), -pdfAnnot->getYMax() );
+
+        MTX[0] = transform.m11();
+        MTX[1] = transform.m12();
+        MTX[2] = transform.m21();
+        MTX[3] = transform.m22();
+        MTX[4] = transform.dx();
+        MTX[5] = transform.dy();
+    }
+}
+
 QRectF AnnotationPrivate::fromPdfRectangle(const PDFRectangle &r) const
 {
     double swp, MTX[6];
-    fillMTX(MTX);
+    fillTransformationMTX(MTX);
 
     QPointF p1, p2;
     XPDFReader::transform( MTX, r.x1, r.y1, p1 );
@@ -256,10 +300,20 @@ QRectF AnnotationPrivate::fromPdfRectangle(const PDFRectangle &r) const
     return QRectF( QPointF(tl_x,tl_y) , QPointF(br_x,br_y) );
 }
 
-PDFRectangle AnnotationPrivate::toPdfRectangle(const QRectF &r) const
+// This function converts a boundary QRectF in normalized coords to a
+// PDFRectangle in user coords. If the FixedRotation flag is set, this function
+// also applies a rotation around the top-left corner: it's the inverse of
+// the transformation produced by fillTransformationMTX, but we can't use
+// fillTransformationMTX here because it relies on the native annotation
+// object's boundary rect to be already set up.
+PDFRectangle AnnotationPrivate::boundaryToPdfRectangle(const QRectF &r, int flags) const
 {
+    Q_ASSERT ( pdfPage );
+
+    const int pageRotate = pdfPage->getRotate();
+
     double MTX[6];
-    fillMTX(MTX);
+    fillNormalizationMTX( MTX, pageRotate );
 
     double tl_x, tl_y, br_x, br_y, swp;
     XPDFReader::invTransform( MTX, r.topLeft(), tl_x, tl_y );
@@ -279,7 +333,18 @@ PDFRectangle AnnotationPrivate::toPdfRectangle(const QRectF &r) const
         br_y = swp;
     }
 
-    return PDFRectangle(tl_x, tl_y, br_x, br_y);
+    const int rotationFixUp = ( flags & Annotation::FixedRotation ) ? pageRotate : 0;
+    const double width = br_x - tl_x;
+    const double height = br_y - tl_y;
+
+    if ( rotationFixUp == 0 )
+        return PDFRectangle(tl_x, tl_y, br_x, br_y);
+    else if ( rotationFixUp == 90 )
+        return PDFRectangle(tl_x, tl_y - width, tl_x + height, tl_y);
+    else if ( rotationFixUp == 180 )
+        return PDFRectangle(br_x, tl_y - height, br_x + width, tl_y);
+    else // rotationFixUp == 270
+        return PDFRectangle(br_x, br_y - width, br_x + height, br_y);
 }
 
 AnnotPath * AnnotationPrivate::toAnnotPath(const QLinkedList<QPointF> &list) const
@@ -288,7 +353,7 @@ AnnotPath * AnnotationPrivate::toAnnotPath(const QLinkedList<QPointF> &list) con
     AnnotCoord **ac = (AnnotCoord **) gmallocn(count, sizeof(AnnotCoord*));
 
     double MTX[6];
-    fillMTX(MTX);
+    fillTransformationMTX(MTX);
 
     int pos = 0;
     foreach (const QPointF &p, list)
@@ -1302,7 +1367,7 @@ void Annotation::setBoundary( const QRectF &boundary )
         return;
     }
 
-    PDFRectangle rect = d->toPdfRectangle(boundary);
+    PDFRectangle rect = d->boundaryToPdfRectangle( boundary, flags() );
     d->pdfAnnot->setRect(&rect);
     d->pdfAnnot->invalidateAppearance();
 }
@@ -1598,7 +1663,7 @@ Annot* TextAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *
     parentDoc = doc;
 
     // Set pdfAnnot
-    PDFRectangle rect = toPdfRectangle(boundary);
+    PDFRectangle rect = boundaryToPdfRectangle(boundary, flags);
     if (textType == TextAnnotation::Linked)
     {
         pdfAnnot = new AnnotText(destPage->getDoc(), &rect);
@@ -1909,7 +1974,7 @@ QVector<QPointF> TextAnnotation::calloutPoints() const
         return QVector<QPointF>();
 
     double MTX[6];
-    d->fillMTX(MTX);
+    d->fillTransformationMTX(MTX);
 
     const AnnotCalloutMultiLine * callout_v6 = dynamic_cast<const AnnotCalloutMultiLine*>(callout);
     QVector<QPointF> res(callout_v6 ? 3 : 2);
@@ -1951,7 +2016,7 @@ void TextAnnotation::setCalloutPoints( const QVector<QPointF> &points )
     AnnotCalloutLine *callout;
     double x1, y1, x2, y2;
     double MTX[6];
-    d->fillMTX(MTX);
+    d->fillTransformationMTX(MTX);
 
     XPDFReader::invTransform( MTX, points[0], x1, y1 );
     XPDFReader::invTransform( MTX, points[1], x2, y2 );
@@ -2050,7 +2115,7 @@ Annot* LineAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *
     parentDoc = doc;
 
     // Set pdfAnnot
-    PDFRectangle rect = toPdfRectangle(boundary);
+    PDFRectangle rect = boundaryToPdfRectangle(boundary, flags);
     if (lineType == LineAnnotation::StraightLine)
     {
         pdfAnnot = new AnnotLine(doc->doc, &rect);
@@ -2226,7 +2291,7 @@ QLinkedList<QPointF> LineAnnotation::linePoints() const
         return d->linePoints;
 
     double MTX[6];
-    d->fillMTX(MTX);
+    d->fillTransformationMTX(MTX);
 
     QLinkedList<QPointF> res;
     if (d->pdfAnnot->getType() == Annot::typeLine)
@@ -2274,7 +2339,7 @@ void LineAnnotation::setLinePoints( const QLinkedList<QPointF> &points )
         }
         double x1, y1, x2, y2;
         double MTX[6];
-        d->fillMTX(MTX);
+        d->fillTransformationMTX(MTX);
         XPDFReader::invTransform( MTX, points.first(), x1, y1 );
         XPDFReader::invTransform( MTX, points.last(), x2, y2 );
         lineann->setVertices(x1, y1, x2, y2);
@@ -2666,7 +2731,7 @@ Annot* GeomAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *
         type = Annot::typeCircle;
 
     // Set pdfAnnot
-    PDFRectangle rect = toPdfRectangle(boundary);
+    PDFRectangle rect = boundaryToPdfRectangle(boundary, flags);
     pdfAnnot = new AnnotGeometry(destPage->getDoc(), &rect, type);
 
     // Set properties
@@ -2844,7 +2909,7 @@ QList< HighlightAnnotation::Quad > HighlightAnnotationPrivate::fromQuadrilateral
     const int quadsCount = hlquads->getQuadrilateralsLength();
 
     double MTX[6];
-    fillMTX(MTX);
+    fillTransformationMTX(MTX);
 
     for (int q = 0; q < quadsCount; ++q)
     {
@@ -2876,7 +2941,7 @@ AnnotQuadrilaterals * HighlightAnnotationPrivate::toQuadrilaterals(const QList<
             gmallocn( count, sizeof(AnnotQuadrilaterals::AnnotQuadrilateral*) );
 
     double MTX[6];
-    fillMTX(MTX);
+    fillTransformationMTX(MTX);
 
     int pos = 0;
     foreach (const HighlightAnnotation::Quad &q, quads)
@@ -2903,7 +2968,7 @@ Annot* HighlightAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentD
     parentDoc = doc;
 
     // Set pdfAnnot
-    PDFRectangle rect = toPdfRectangle(boundary);
+    PDFRectangle rect = boundaryToPdfRectangle(boundary, flags);
     pdfAnnot = new AnnotTextMarkup(destPage->getDoc(), &rect, toAnnotSubType(highlightType));
 
     // Set properties
@@ -3113,7 +3178,7 @@ Annot* StampAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData
     parentDoc = doc;
 
     // Set pdfAnnot
-    PDFRectangle rect = toPdfRectangle(boundary);
+    PDFRectangle rect = boundaryToPdfRectangle(boundary, flags);
     pdfAnnot = new AnnotStamp(destPage->getDoc(), &rect);
 
     // Set properties
@@ -3252,7 +3317,7 @@ Annot* InkAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *d
     parentDoc = doc;
 
     // Set pdfAnnot
-    PDFRectangle rect = toPdfRectangle(boundary);
+    PDFRectangle rect = boundaryToPdfRectangle(boundary, flags);
     pdfAnnot = new AnnotInk(destPage->getDoc(), &rect);
 
     // Set properties
@@ -3377,7 +3442,7 @@ QList< QLinkedList<QPointF> > InkAnnotation::inkPaths() const
         return QList< QLinkedList<QPointF> >();
 
     double MTX[6];
-    d->fillMTX(MTX);
+    d->fillTransformationMTX(MTX);
 
     const int pathsNumber = inkann->getInkListLength();
     QList< QLinkedList<QPointF> > inkPaths;
@@ -3798,7 +3863,7 @@ Annot* CaretAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData
     parentDoc = doc;
 
     // Set pdfAnnot
-    PDFRectangle rect = toPdfRectangle(boundary);
+    PDFRectangle rect = boundaryToPdfRectangle(boundary, flags);
     pdfAnnot = new AnnotCaret(destPage->getDoc(), &rect);
 
     // Set properties
commit ab130c91492765f8be29ed112dd2e2e6f665641b
Author: Fabio D'Urso <fabiodurso at hotmail.it>
Date:   Sat Mar 2 00:55:58 2013 +0100

    core: Remove geometry-related arguments from annotation constructors
    
    Removed arguments from annotation constructors related to the geometry
    of the annotation. This change will make it easier to support creating
    annotations with flag NoRotate in the next patch (because no special
    cases will be needed: coordinate conversion code will be able to always
    assume that the underlying annotation object already exists).
    
    Data that used to be taken from these arguments is now replaced by dummy
    values, which can be modified using appropriate setter methods after
    the annotation object is created.
    
    Affected annotation types:
     - AnnotLine
     - AnnotTextMarkup
     - AnnotPolygon
     - AnnotInk

diff --git a/qt5/src/poppler-annotation.cc b/qt5/src/poppler-annotation.cc
index 956e028..35cef49 100644
--- a/qt5/src/poppler-annotation.cc
+++ b/qt5/src/poppler-annotation.cc
@@ -2,7 +2,7 @@
  * Copyright (C) 2006, 2009, 2012 Albert Astals Cid <aacid at kde.org>
  * Copyright (C) 2006, 2008, 2010 Pino Toscano <pino at kde.org>
  * Copyright (C) 2012, Guillermo A. Amaral B. <gamaral at kde.org>
- * Copyright (C) 2012, Fabio D'Urso <fabiodurso at hotmail.it>
+ * Copyright (C) 2012, 2013 Fabio D'Urso <fabiodurso at hotmail.it>
  * Copyright (C) 2012, Tobias Koenig <tokoe at kdab.com>
  * Adapting code from
  *   Copyright (C) 2004 by Enrico Ros <eros.kde at email.it>
@@ -2050,22 +2050,20 @@ Annot* LineAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *
     parentDoc = doc;
 
     // Set pdfAnnot
-    AnnotPath * path = toAnnotPath(linePoints);
     PDFRectangle rect = toPdfRectangle(boundary);
     if (lineType == LineAnnotation::StraightLine)
     {
-        PDFRectangle lrect(path->getX(0), path->getY(0), path->getX(1), path->getY(1));
-        pdfAnnot = new AnnotLine(doc->doc, &rect, &lrect);
+        pdfAnnot = new AnnotLine(doc->doc, &rect);
     }
     else
     {
         pdfAnnot = new AnnotPolygon(doc->doc, &rect,
-                lineClosed ? Annot::typePolygon : Annot::typePolyLine, path );
+                lineClosed ? Annot::typePolygon : Annot::typePolyLine );
     }
-    delete path;
 
     // Set properties
     flushBaseAnnotationProperties();
+    q->setLinePoints(linePoints);
     q->setLineStartStyle(lineStartStyle);
     q->setLineEndStyle(lineEndStyle);
     q->setLineInnerColor(lineInnerColor);
@@ -2897,21 +2895,25 @@ AnnotQuadrilaterals * HighlightAnnotationPrivate::toQuadrilaterals(const QList<
 
 Annot* HighlightAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc)
 {
+    // Setters are defined in the public class
+    HighlightAnnotation *q = static_cast<HighlightAnnotation*>( makeAlias() );
+
     // Set page and document
     pdfPage = destPage;
     parentDoc = doc;
 
     // Set pdfAnnot
     PDFRectangle rect = toPdfRectangle(boundary);
-    AnnotQuadrilaterals * quads = toQuadrilaterals(highlightQuads);
-    pdfAnnot = new AnnotTextMarkup(destPage->getDoc(), &rect, toAnnotSubType(highlightType), quads);
-    delete quads;
+    pdfAnnot = new AnnotTextMarkup(destPage->getDoc(), &rect, toAnnotSubType(highlightType));
 
     // Set properties
     flushBaseAnnotationProperties();
+    q->setHighlightQuads(highlightQuads);
 
     highlightQuads.clear(); // Free up memory
 
+    delete q;
+
     return pdfAnnot;
 }
 
@@ -3242,25 +3244,25 @@ AnnotPath **InkAnnotationPrivate::toAnnotPaths(const QList< QLinkedList<QPointF>
 
 Annot* InkAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc)
 {
+    // Setters are defined in the public class
+    InkAnnotation *q = static_cast<InkAnnotation*>( makeAlias() );
+
     // Set page and document
     pdfPage = destPage;
     parentDoc = doc;
 
     // Set pdfAnnot
     PDFRectangle rect = toPdfRectangle(boundary);
-    AnnotPath **paths = toAnnotPaths(inkPaths);
-    const int pathsNumber = inkPaths.size();
-    pdfAnnot = new AnnotInk(destPage->getDoc(), &rect, paths, pathsNumber);
-
-    for (int i = 0; i < pathsNumber; ++i)
-        delete paths[i];
-    delete[] paths;
+    pdfAnnot = new AnnotInk(destPage->getDoc(), &rect);
 
     // Set properties
     flushBaseAnnotationProperties();
+    q->setInkPaths(inkPaths);
 
     inkPaths.clear(); // Free up memory
 
+    delete q;
+
     return pdfAnnot;
 }
 
commit 35cfb6914e1be4c5eda2f355900b1a0a1fa69d19
Author: Fabio D'Urso <fabiodurso at hotmail.it>
Date:   Fri Feb 15 12:24:18 2013 +0100

    poppler_qt5viewer: Add combobox to select rotation

diff --git a/qt5/demos/navigationtoolbar.cpp b/qt5/demos/navigationtoolbar.cpp
index 4278aab..0b6c862 100644
--- a/qt5/demos/navigationtoolbar.cpp
+++ b/qt5/demos/navigationtoolbar.cpp
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2008-2009, Pino Toscano <pino at kde.org>
+ * Copyright (C) 2013, Fabio D'Urso <fabiodurso at hotmail.it>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -54,6 +55,15 @@ NavigationToolBar::NavigationToolBar(QWidget *parent)
     connect(m_zoomCombo, SIGNAL(currentIndexChanged(QString)), this, SLOT(slotZoomComboChanged(QString)));
     addWidget(m_zoomCombo);
 
+    m_rotationCombo = new QComboBox(this);
+    // NOTE: \302\260 = degree symbol
+    m_rotationCombo->addItem(trUtf8("0\302\260"));
+    m_rotationCombo->addItem(trUtf8("90\302\260"));
+    m_rotationCombo->addItem(trUtf8("180\302\260"));
+    m_rotationCombo->addItem(trUtf8("270\302\260"));
+    connect(m_rotationCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(slotRotationComboChanged(int)));
+    addWidget(m_rotationCombo);
+
     documentClosed();
 }
 
@@ -126,4 +136,9 @@ void NavigationToolBar::slotZoomComboChanged(const QString &_text)
     }
 }
 
+void NavigationToolBar::slotRotationComboChanged(int idx)
+{
+    emit rotationChanged(idx * 90);
+}
+
 #include "navigationtoolbar.moc"
diff --git a/qt5/demos/navigationtoolbar.h b/qt5/demos/navigationtoolbar.h
index 0bde376..e249adb 100644
--- a/qt5/demos/navigationtoolbar.h
+++ b/qt5/demos/navigationtoolbar.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2008-2009, Pino Toscano <pino at kde.org>
+ * Copyright (C) 2013, Fabio D'Urso <fabiodurso at hotmail.it>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -40,6 +41,7 @@ public:
 
 Q_SIGNALS:
     void zoomChanged(qreal value);
+    void rotationChanged(int rotation);
 
 private Q_SLOTS:
     void slotGoFirst();
@@ -48,6 +50,7 @@ private Q_SLOTS:
     void slotGoLast();
     void slotComboActivated(int index);
     void slotZoomComboChanged(const QString &text);
+    void slotRotationComboChanged(int idx);
 
 private:
     QAction *m_firstAct;
@@ -56,6 +59,7 @@ private:
     QAction *m_nextAct;
     QAction *m_lastAct;
     QComboBox *m_zoomCombo;
+    QComboBox *m_rotationCombo;
 };
 
 #endif
diff --git a/qt5/demos/pageview.cpp b/qt5/demos/pageview.cpp
index 0a74080..cb2731b 100644
--- a/qt5/demos/pageview.cpp
+++ b/qt5/demos/pageview.cpp
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2008-2009, Pino Toscano <pino at kde.org>
+ * Copyright (C) 2013, Fabio D'Urso <fabiodurso at hotmail.it>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -29,6 +30,7 @@
 PageView::PageView(QWidget *parent)
     : QScrollArea(parent)
     , m_zoom(1.0)
+    , m_rotation(0)
     , m_dpiX(QApplication::desktop()->physicalDpiX())
     , m_dpiY(QApplication::desktop()->physicalDpiY())
 {
@@ -56,7 +58,18 @@ void PageView::pageChanged(int page)
     Poppler::Page *popplerPage = document()->page(page);
     const double resX = m_dpiX * m_zoom;
     const double resY = m_dpiY * m_zoom;
-    QImage image = popplerPage->renderToImage(resX, resY);
+
+    Poppler::Page::Rotation rot;
+    if (m_rotation == 0)
+        rot = Poppler::Page::Rotate0;
+    else if (m_rotation == 90)
+        rot = Poppler::Page::Rotate90;
+    else if (m_rotation == 180)
+        rot = Poppler::Page::Rotate180;
+    else // m_rotation == 270
+        rot = Poppler::Page::Rotate270;
+
+    QImage image = popplerPage->renderToImage(resX, resY, -1, -1, -1, -1, rot);
     if (!image.isNull()) {
         m_imageLabel->resize(image.size());
         m_imageLabel->setPixmap(QPixmap::fromImage(image));
@@ -76,4 +89,13 @@ void PageView::slotZoomChanged(qreal value)
     reloadPage();
 }
 
+void PageView::slotRotationChanged(int value)
+{
+    m_rotation = value;
+    if (!document()) {
+        return;
+    }
+    reloadPage();
+}
+
 #include "pageview.moc"
diff --git a/qt5/demos/pageview.h b/qt5/demos/pageview.h
index 3030c84..95795a5 100644
--- a/qt5/demos/pageview.h
+++ b/qt5/demos/pageview.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2008-2009, Pino Toscano <pino at kde.org>
+ * Copyright (C) 2013, Fabio D'Urso <fabiodurso at hotmail.it>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -39,10 +40,12 @@ public:
 
 private Q_SLOTS:
     void slotZoomChanged(qreal value);
+    void slotRotationChanged(int value);
 
 private:
     QLabel *m_imageLabel;
     qreal m_zoom;
+    int m_rotation;
     int m_dpiX;
     int m_dpiY;
 };
diff --git a/qt5/demos/viewer.cpp b/qt5/demos/viewer.cpp
index 2a29509..a95d7f3 100644
--- a/qt5/demos/viewer.cpp
+++ b/qt5/demos/viewer.cpp
@@ -2,6 +2,7 @@
  * Copyright (C) 2008-2009, Pino Toscano <pino at kde.org>
  * Copyright (C) 2008, Albert Astals Cid <aacid at kde.org>
  * Copyright (C) 2009, Shawn Rutledge <shawn.t.rutledge at gmail.com>
+ * Copyright (C) 2013, Fabio D'Urso <fabiodurso at hotmail.it>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -148,6 +149,7 @@ PdfViewer::PdfViewer()
     }
 
     connect(navbar, SIGNAL(zoomChanged(qreal)), view, SLOT(slotZoomChanged(qreal)));
+    connect(navbar, SIGNAL(rotationChanged(int)), view, SLOT(slotRotationChanged(int)));
 
     // activate AA by default
     m_settingsTextAAAct->setChecked(true);
commit de2a93c0bc6e92a95c687796f59780c998b90ca4
Author: Fabio D'Urso <fabiodurso at hotmail.it>
Date:   Thu Mar 7 00:20:15 2013 +0100

    qt4: Free some temporary memory in TextAnnotationPrivate::createNativeAnnot
    
    There's no need to keep this buffer around after it has been flushed

diff --git a/qt4/src/poppler-annotation.cc b/qt4/src/poppler-annotation.cc
index f8a20d1..3edcbdb 100644
--- a/qt4/src/poppler-annotation.cc
+++ b/qt4/src/poppler-annotation.cc
@@ -1687,6 +1687,8 @@ Annot* TextAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *
 
     delete q;
 
+    inplaceCallout.clear(); // Free up memory
+
     return pdfAnnot;
 }
 
commit 738b0b4fedaa2b2b28ea1c11622dfd880180d1c9
Author: Fabio D'Urso <fabiodurso at hotmail.it>
Date:   Thu Mar 7 20:50:52 2013 +0100

    qt4: Some documentation about annotations
    
    * Removed incorrect hint "Use uniqueName to test for Annotation
      equality": uniqueNames are optional and we don't actually guarantee
      uniqueness
    * Added "How to add annotations" and "FixedRotation flag specifics"
      sections in the Annotation class page
    * Added links from enum Annotation::SubType items to actual subclasses
    * Added documentation for annotation flags that are known to work
    * Added "see also" links between annotation flag and boundary
      setters/getters
    * Added warning on Annotation::setPopup to tell that it's currently not
      implemented

diff --git a/qt4/src/poppler-annotation.h b/qt4/src/poppler-annotation.h
index 9208ca7..03f5e26 100644
--- a/qt4/src/poppler-annotation.h
+++ b/qt4/src/poppler-annotation.h
@@ -5,7 +5,7 @@
  * Copyright (C) 2010, Philip Lorenz <lorenzph+freedesktop at gmail.com>
  * Copyright (C) 2012, Tobias Koenig <tokoe at kdab.com>
  * Copyright (C) 2012, Guillermo A. Amaral B. <gamaral at kde.org>
- * Copyright (C) 2012, Fabio D'Urso <fabiodurso at hotmail.it>
+ * Copyright (C) 2012, 2013 Fabio D'Urso <fabiodurso at hotmail.it>
  * Adapting code from
  *   Copyright (C) 2004 by Enrico Ros <eros.kde at email.it>
  *
@@ -101,7 +101,71 @@ class POPPLER_QT4_EXPORT AnnotationUtils
  * contained by a Page in the document.
  *
  * \warning Different Annotation objects might point to the same annotation.
- *          Use uniqueName to test for Annotation equality
+ *
+ * \section annotCreation How to add annotations
+ *
+ * Create an Annotation object of the desired subclass (for example
+ * TextAnnotation) and set its properties:
+ * @code
+ * Poppler::TextAnnotation* myann = new Poppler::TextAnnotation(Poppler::TextAnnotation::InPlace);
+ * myann->setBoundary(QRectF(0.1, 0.1, 0.2, 0.2)); // normalized coordinates: (0,0) is top-left, (1,1) is bottom-right
+ * myann->setContents("Hello, world!");
+ * @endcode
+ * \note Always set a boundary rectangle, or nothing will be shown!
+ *
+ * Obtain a pointer to the Page where you want to add the annotation (refer to
+ * \ref req for instructions) and add the annotation:
+ * @code
+ * Poppler::Page* mypage = ...;
+ * mypage->addAnnotation(myann);
+ * @endcode
+ *
+ * You can keep on editing the annotation after it has been added to the page:
+ * @code
+ * myann->setContents("World, hello!"); // Let's change text...
+ * myann->setAuthor("Your name here");  // ...and set an author too
+ * @endcode
+ *
+ * When you're done with editing the annotation, you must destroy the Annotation
+ * object:
+ * @code
+ * delete myann;
+ * @endcode
+ *
+ * Use the PDFConverter class to save the modified document.
+ *
+ * \section annotFixedRotation FixedRotation flag specifics
+ *
+ * According to the PDF specification, annotations whose
+ * Annotation::FixedRotation flag is set must always be shown in their original
+ * orientation, no matter what the current rendering rotation or the page's
+ * Page::orientation() values are. In comparison with regular annotations, such
+ * annotations should therefore be transformed by an extra rotation at rendering
+ * time to "undo" such context-related rotations, which is equal to
+ * <code>-(rendering_rotation + page_orientation)</code>. The rotation pivot
+ * is the top-left corner of the boundary rectangle.
+ *
+ * In practice, %Poppler's \ref Page::renderToImage only "unrotates" the
+ * page orientation, and does <b>not</b> unrotate the rendering rotation.
+ * This ensures consistent renderings at different Page::Rotation values:
+ * annotations are always positioned as if they were being positioned at the
+ * default page orientation.
+ *
+ * Just like regular annotations, %Poppler Qt4 exposes normalized coordinates
+ * relative to the page's default orientation. However, behind the scenes, the
+ * coordinate system is different and %Poppler transparently transforms each
+ * shape. If you never call either Annotation::setFlags or
+ * Annotation::setBoundary, you don't need to worry about this; but if you do
+ * call them, then you need to adhere to the following rules:
+ *  - Whenever you toggle the Annotation::FixedRotation flag, you <b>must</b>
+ *    set again the boundary rectangle first, and then you <b>must</b> set
+ *    again any other geometry-related property.
+ *  - Whenever you modify the boundary rectangle of an annotation whose
+ *    Annotation::FixedRotation flag is set, you <b>must</b> set again any other
+ *    geometry-related property.
+ *
+ * These two rules are necessary to make %Poppler's transparent coordinate
+ * conversion work properly.
  */
 class POPPLER_QT4_EXPORT Annotation
 {
@@ -111,12 +175,50 @@ class POPPLER_QT4_EXPORT Annotation
 
   public:
     // enum definitions
+    /**
+     * Annotation subclasses
+     *
+     * \sa subType()
+     */
     // WARNING!!! oKular uses that very same values so if you change them notify the author!
-    enum SubType { AText = 1, ALine = 2, AGeom = 3, AHighlight = 4, AStamp = 5,
-                   AInk = 6, ALink = 7, ACaret = 8, AFileAttachment = 9, ASound = 10,
-                   AMovie = 11, AScreen = 12 /** \since 0.20 */, AWidget = 13 /** \since 0.22 */, A_BASE = 0 };
-    enum Flag { Hidden = 1, FixedSize = 2, FixedRotation = 4, DenyPrint = 8,
-                DenyWrite = 16, DenyDelete = 32, ToggleHidingOnMouse = 64, External = 128 };
+    enum SubType
+    {
+        AText = 1,            ///< TextAnnotation
+        ALine = 2,            ///< LineAnnotation
+        AGeom = 3,            ///< GeomAnnotation
+        AHighlight = 4,       ///< HighlightAnnotation
+        AStamp = 5,           ///< StampAnnotation
+        AInk = 6,             ///< InkAnnotation
+        ALink = 7,            ///< LinkAnnotation
+        ACaret = 8,           ///< CaretAnnotation
+        AFileAttachment = 9,  ///< FileAttachmentAnnotation
+        ASound = 10,          ///< SoundAnnotation
+        AMovie = 11,          ///< MovieAnnotation
+        AScreen = 12,         ///< ScreenAnnotation \since 0.20
+        AWidget = 13,         ///< WidgetAnnotation \since 0.22
+        A_BASE = 0
+    };
+
+    /**
+     * Annotation flags
+     *
+     * They can be OR'd together (e.g. Annotation::FixedRotation | Annotation::DenyPrint).
+     *
+     * \sa flags(), setFlags(int)
+     */
+    // NOTE: Only flags that are known to work are documented
+    enum Flag
+    {
+        Hidden = 1,                ///< Do not display or print the annotation
+        FixedSize = 2,
+        FixedRotation = 4,         ///< Do not rotate the annotation according to page orientation and rendering rotation \warning Extra care is needed with this flag: see \ref annotFixedRotation
+        DenyPrint = 8,             ///< Do not print the annotation
+        DenyWrite = 16,
+        DenyDelete = 32,
+        ToggleHidingOnMouse = 64,
+        External = 128
+    };
+
     enum LineStyle { Solid = 1, Dashed = 2, Beveled = 4, Inset = 8, Underline = 16 };
     enum LineEffect { NoEffect = 1, Cloudy = 2};
     enum RevScope { Root = 0 /** \since 0.20 */, Reply = 1, Group = 2, Delete = 4 };
@@ -151,10 +253,35 @@ class POPPLER_QT4_EXPORT Annotation
     QDateTime creationDate() const;
     void setCreationDate( const QDateTime &date );
 
+    /**
+     * Returns this annotation's flags
+     *
+     * \sa Flag, setFlags(int)
+     */
     int flags() const;
+    /**
+     * Sets this annotation's flags
+     *
+     * \sa Flag, flags(), \ref annotFixedRotation
+     */
     void setFlags( int flags );
 
+    /**
+     * Returns this annotation's boundary rectangle in normalized coordinates
+     *
+     * \sa setBoundary(const QRectF&)
+     */
     QRectF boundary() const;
+    /**
+     * Sets this annotation's boundary rectangle
+     *
+     * The boundary rectangle is the smallest rectangle that contains the
+     * annotation.
+     *
+     * \warning This property is mandatory: you must always set this.
+     *
+     * \sa boundary(), \ref annotFixedRotation
+     */
     void setBoundary( const QRectF &boundary );
 
     /**
@@ -240,7 +367,7 @@ class POPPLER_QT4_EXPORT Annotation
 
     /// \since 0.20
     Popup popup() const;
-    /// \since 0.20
+    /// \warning Currently does nothing \since 0.20
     void setPopup( const Popup& popup );
 
     /// \cond PRIVATE
commit cf950a2b7e8278e70719c67b441b0d324ffd0399
Author: Fabio D'Urso <fabiodurso at hotmail.it>
Date:   Sat Mar 2 19:06:49 2013 +0100

    qt4: FixedRotation annotations' coordinate conversion
    
    FixedRotation(=flagNoRotate) annotations use a different coordinate
    system than regular annotations. This patch implements transparent
    conversion so that qt4 clients don't notice the difference.
    
    Important! When dealing with FixedRotation annotations, poppler-qt4
    clients will need to set geometry-related annotation properties in
    the following order:
     1) flags (because we need to know if this is a FixedRotation
        annotation or not)
     2) boundary (because we need to know what the topleft corner is,
        so that we can construct the conversion matrix)
     3) anything else
    
    This requirement will be documented in the next patch

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 1fb8feb..99d40a6 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -1520,6 +1520,14 @@ double Annot::getYMin() {
   return rect->y1;
 }
 
+double Annot::getXMax() {
+  return rect->x2;
+}
+
+double Annot::getYMax() {
+  return rect->y2;
+}
+
 void Annot::readArrayNum(Object *pdfArray, int key, double *value) {
   Object valueObject;
 
diff --git a/poppler/Annot.h b/poppler/Annot.h
index 3d3b0f6..af29eb2 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -553,6 +553,8 @@ public:
 
   double getXMin();
   double getYMin();
+  double getXMax();
+  double getYMax();
 
   double getFontSize() { return fontSize; }
 
diff --git a/qt4/src/poppler-annotation-private.h b/qt4/src/poppler-annotation-private.h
index 3bfb5da..c755eb3 100644
--- a/qt4/src/poppler-annotation-private.h
+++ b/qt4/src/poppler-annotation-private.h
@@ -1,7 +1,7 @@
 /* poppler-annotation-private.h: qt interface to poppler
  * Copyright (C) 2007, Pino Toscano <pino at kde.org>
  * Copyright (C) 2012, Tobias Koenig <tokoe at kdab.com>
- * Copyright (C) 2012, Fabio D'Urso <fabiodurso at hotmail.it>
+ * Copyright (C) 2012, 2013 Fabio D'Urso <fabiodurso at hotmail.it>
  * Copyright (C) 2012, Albert Astals Cid <aacid at kde.org>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -87,9 +87,10 @@ class AnnotationPrivate : public QSharedData
 
         /* The following helpers only work if pdfPage is set */
         void flushBaseAnnotationProperties();
-        void fillMTX(double MTX[6]) const;
+        void fillNormalizationMTX(double MTX[6], int pageRotation) const;
+        void fillTransformationMTX(double MTX[6]) const;
         QRectF fromPdfRectangle(const PDFRectangle &r) const;
-        PDFRectangle toPdfRectangle(const QRectF &r) const;
+        PDFRectangle boundaryToPdfRectangle(const QRectF &r, int flags) const;
         AnnotPath * toAnnotPath(const QLinkedList<QPointF> &l) const;
 
         /* Scan page for annotations, parentId=0 searches for root annotations */
diff --git a/qt4/src/poppler-annotation.cc b/qt4/src/poppler-annotation.cc
index 173861e..f8a20d1 100644
--- a/qt4/src/poppler-annotation.cc
+++ b/qt4/src/poppler-annotation.cc
@@ -27,6 +27,7 @@
 #include <QtCore/QtAlgorithms>
 #include <QtXml/QDomElement>
 #include <QtGui/QColor>
+#include <QtGui/QTransform>
 
 // local includes
 #include "poppler-annotation.h"
@@ -198,19 +199,21 @@ void AnnotationPrivate::flushBaseAnnotationProperties()
     revisions.clear();
 }
 
-void AnnotationPrivate::fillMTX(double MTX[6]) const
+// Returns matrix to convert from user space coords (oriented according to the
+// specified rotation) to normalized coords
+void AnnotationPrivate::fillNormalizationMTX(double MTX[6], int pageRotation) const
 {
     Q_ASSERT ( pdfPage );
 
     // build a normalized transform matrix for this page at 100% scale
-    GfxState * gfxState = new GfxState( 72.0, 72.0, pdfPage->getCropBox(), pdfPage->getRotate(), gTrue );
+    GfxState * gfxState = new GfxState( 72.0, 72.0, pdfPage->getCropBox(), pageRotation, gTrue );
     double * gfxCTM = gfxState->getCTM();
 
     double w = pdfPage->getCropWidth();
     double h = pdfPage->getCropHeight();
 
     // Swap width and height if the page is rotated landscape or seascape
-    if ( pdfPage->getRotate() == 90 || pdfPage->getRotate() == 270 )
+    if ( pageRotation == 90 || pageRotation == 270 )
     {
         double t = w;
         w = h;
@@ -225,10 +228,51 @@ void AnnotationPrivate::fillMTX(double MTX[6]) const
     delete gfxState;
 }
 
+// Returns matrix to convert from user space coords (i.e. those that are stored
+// in the PDF file) to normalized coords (i.e. those that we expose to clients).
+// This method also applies a rotation around the top-left corner if the
+// FixedRotation flag is set.
+void AnnotationPrivate::fillTransformationMTX(double MTX[6]) const
+{
+    Q_ASSERT ( pdfPage );
+    Q_ASSERT ( pdfAnnot );
+
+    const int pageRotate = pdfPage->getRotate();
+
+    if ( pageRotate == 0 || ( pdfAnnot->getFlags() & Annot::flagNoRotate ) == 0 )
+    {
+        // Use the normalization matrix for this page's rotation
+        fillNormalizationMTX( MTX, pageRotate );
+    }
+    else
+    {
+        // Clients expect coordinates relative to this page's rotation, but
+        // FixedRotation annotations internally use unrotated coordinates:
+        // construct matrix to both normalize and rotate coordinates using the
+        // top-left corner as rotation pivot
+
+        double MTXnorm[6];
+        fillNormalizationMTX( MTXnorm, pageRotate );
+
+        QTransform transform( MTXnorm[0], MTXnorm[1], MTXnorm[2],
+                              MTXnorm[3], MTXnorm[4], MTXnorm[5] );
+        transform.translate( +pdfAnnot->getXMin(), +pdfAnnot->getYMax() );
+        transform.rotate( pageRotate );
+        transform.translate( -pdfAnnot->getXMin(), -pdfAnnot->getYMax() );
+
+        MTX[0] = transform.m11();
+        MTX[1] = transform.m12();
+        MTX[2] = transform.m21();
+        MTX[3] = transform.m22();
+        MTX[4] = transform.dx();
+        MTX[5] = transform.dy();
+    }
+}
+
 QRectF AnnotationPrivate::fromPdfRectangle(const PDFRectangle &r) const
 {
     double swp, MTX[6];
-    fillMTX(MTX);
+    fillTransformationMTX(MTX);
 
     QPointF p1, p2;
     XPDFReader::transform( MTX, r.x1, r.y1, p1 );
@@ -256,10 +300,20 @@ QRectF AnnotationPrivate::fromPdfRectangle(const PDFRectangle &r) const
     return QRectF( QPointF(tl_x,tl_y) , QPointF(br_x,br_y) );
 }
 
-PDFRectangle AnnotationPrivate::toPdfRectangle(const QRectF &r) const
+// This function converts a boundary QRectF in normalized coords to a
+// PDFRectangle in user coords. If the FixedRotation flag is set, this function
+// also applies a rotation around the top-left corner: it's the inverse of
+// the transformation produced by fillTransformationMTX, but we can't use
+// fillTransformationMTX here because it relies on the native annotation
+// object's boundary rect to be already set up.
+PDFRectangle AnnotationPrivate::boundaryToPdfRectangle(const QRectF &r, int flags) const
 {
+    Q_ASSERT ( pdfPage );
+
+    const int pageRotate = pdfPage->getRotate();
+
     double MTX[6];
-    fillMTX(MTX);
+    fillNormalizationMTX( MTX, pageRotate );
 
     double tl_x, tl_y, br_x, br_y, swp;
     XPDFReader::invTransform( MTX, r.topLeft(), tl_x, tl_y );
@@ -279,7 +333,18 @@ PDFRectangle AnnotationPrivate::toPdfRectangle(const QRectF &r) const
         br_y = swp;
     }
 
-    return PDFRectangle(tl_x, tl_y, br_x, br_y);
+    const int rotationFixUp = ( flags & Annotation::FixedRotation ) ? pageRotate : 0;
+    const double width = br_x - tl_x;
+    const double height = br_y - tl_y;
+
+    if ( rotationFixUp == 0 )
+        return PDFRectangle(tl_x, tl_y, br_x, br_y);
+    else if ( rotationFixUp == 90 )
+        return PDFRectangle(tl_x, tl_y - width, tl_x + height, tl_y);
+    else if ( rotationFixUp == 180 )
+        return PDFRectangle(br_x, tl_y - height, br_x + width, tl_y);
+    else // rotationFixUp == 270
+        return PDFRectangle(br_x, br_y - width, br_x + height, br_y);
 }
 
 AnnotPath * AnnotationPrivate::toAnnotPath(const QLinkedList<QPointF> &list) const
@@ -288,7 +353,7 @@ AnnotPath * AnnotationPrivate::toAnnotPath(const QLinkedList<QPointF> &list) con
     AnnotCoord **ac = (AnnotCoord **) gmallocn(count, sizeof(AnnotCoord*));
 
     double MTX[6];
-    fillMTX(MTX);
+    fillTransformationMTX(MTX);
 
     int pos = 0;
     foreach (const QPointF &p, list)
@@ -1305,7 +1370,7 @@ void Annotation::setBoundary( const QRectF &boundary )
         return;
     }
 
-    PDFRectangle rect = d->toPdfRectangle(boundary);
+    PDFRectangle rect = d->boundaryToPdfRectangle( boundary, flags() );
     d->pdfAnnot->setRect(&rect);
     d->pdfAnnot->invalidateAppearance();
 }
@@ -1601,7 +1666,7 @@ Annot* TextAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *
     parentDoc = doc;
 
     // Set pdfAnnot
-    PDFRectangle rect = toPdfRectangle(boundary);
+    PDFRectangle rect = boundaryToPdfRectangle(boundary, flags);
     if (textType == TextAnnotation::Linked)
     {
         pdfAnnot = new AnnotText(destPage->getDoc(), &rect);
@@ -1922,7 +1987,7 @@ QVector<QPointF> TextAnnotation::calloutPoints() const
         return QVector<QPointF>();
 
     double MTX[6];
-    d->fillMTX(MTX);
+    d->fillTransformationMTX(MTX);
 
     const AnnotCalloutMultiLine * callout_v6 = dynamic_cast<const AnnotCalloutMultiLine*>(callout);
     QVector<QPointF> res(callout_v6 ? 3 : 2);
@@ -1964,7 +2029,7 @@ void TextAnnotation::setCalloutPoints( const QVector<QPointF> &points )
     AnnotCalloutLine *callout;
     double x1, y1, x2, y2;
     double MTX[6];
-    d->fillMTX(MTX);
+    d->fillTransformationMTX(MTX);
 
     XPDFReader::invTransform( MTX, points[0], x1, y1 );
     XPDFReader::invTransform( MTX, points[1], x2, y2 );
@@ -2063,7 +2128,7 @@ Annot* LineAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *
     parentDoc = doc;
 
     // Set pdfAnnot
-    PDFRectangle rect = toPdfRectangle(boundary);
+    PDFRectangle rect = boundaryToPdfRectangle(boundary, flags);
     if (lineType == LineAnnotation::StraightLine)
     {
         pdfAnnot = new AnnotLine(doc->doc, &rect);
@@ -2239,7 +2304,7 @@ QLinkedList<QPointF> LineAnnotation::linePoints() const
         return d->linePoints;
 
     double MTX[6];
-    d->fillMTX(MTX);
+    d->fillTransformationMTX(MTX);
 
     QLinkedList<QPointF> res;
     if (d->pdfAnnot->getType() == Annot::typeLine)
@@ -2287,7 +2352,7 @@ void LineAnnotation::setLinePoints( const QLinkedList<QPointF> &points )
         }
         double x1, y1, x2, y2;
         double MTX[6];
-        d->fillMTX(MTX);
+        d->fillTransformationMTX(MTX);
         XPDFReader::invTransform( MTX, points.first(), x1, y1 );
         XPDFReader::invTransform( MTX, points.last(), x2, y2 );
         lineann->setVertices(x1, y1, x2, y2);
@@ -2679,7 +2744,7 @@ Annot* GeomAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *
         type = Annot::typeCircle;
 
     // Set pdfAnnot
-    PDFRectangle rect = toPdfRectangle(boundary);
+    PDFRectangle rect = boundaryToPdfRectangle(boundary, flags);
     pdfAnnot = new AnnotGeometry(destPage->getDoc(), &rect, type);
 
     // Set properties
@@ -2857,7 +2922,7 @@ QList< HighlightAnnotation::Quad > HighlightAnnotationPrivate::fromQuadrilateral
     const int quadsCount = hlquads->getQuadrilateralsLength();
 
     double MTX[6];
-    fillMTX(MTX);
+    fillTransformationMTX(MTX);
 
     for (int q = 0; q < quadsCount; ++q)
     {
@@ -2889,7 +2954,7 @@ AnnotQuadrilaterals * HighlightAnnotationPrivate::toQuadrilaterals(const QList<
             gmallocn( count, sizeof(AnnotQuadrilaterals::AnnotQuadrilateral*) );
 
     double MTX[6];
-    fillMTX(MTX);
+    fillTransformationMTX(MTX);
 
     int pos = 0;
     foreach (const HighlightAnnotation::Quad &q, quads)
@@ -2916,7 +2981,7 @@ Annot* HighlightAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentD
     parentDoc = doc;
 
     // Set pdfAnnot
-    PDFRectangle rect = toPdfRectangle(boundary);
+    PDFRectangle rect = boundaryToPdfRectangle(boundary, flags);
     pdfAnnot = new AnnotTextMarkup(destPage->getDoc(), &rect, toAnnotSubType(highlightType));
 
     // Set properties
@@ -3126,7 +3191,7 @@ Annot* StampAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData
     parentDoc = doc;
 
     // Set pdfAnnot
-    PDFRectangle rect = toPdfRectangle(boundary);
+    PDFRectangle rect = boundaryToPdfRectangle(boundary, flags);
     pdfAnnot = new AnnotStamp(destPage->getDoc(), &rect);
 
     // Set properties
@@ -3265,7 +3330,7 @@ Annot* InkAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *d
     parentDoc = doc;
 
     // Set pdfAnnot
-    PDFRectangle rect = toPdfRectangle(boundary);
+    PDFRectangle rect = boundaryToPdfRectangle(boundary, flags);
     pdfAnnot = new AnnotInk(destPage->getDoc(), &rect);
 
     // Set properties
@@ -3390,7 +3455,7 @@ QList< QLinkedList<QPointF> > InkAnnotation::inkPaths() const
         return QList< QLinkedList<QPointF> >();
 
     double MTX[6];
-    d->fillMTX(MTX);
+    d->fillTransformationMTX(MTX);
 
     const int pathsNumber = inkann->getInkListLength();
     QList< QLinkedList<QPointF> > inkPaths;
@@ -3811,7 +3876,7 @@ Annot* CaretAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData
     parentDoc = doc;
 
     // Set pdfAnnot
-    PDFRectangle rect = toPdfRectangle(boundary);
+    PDFRectangle rect = boundaryToPdfRectangle(boundary, flags);
     pdfAnnot = new AnnotCaret(destPage->getDoc(), &rect);
 
     // Set properties
commit 4b13085568df09d8b75099f6a5438f025a028fd5
Author: Fabio D'Urso <fabiodurso at hotmail.it>
Date:   Sat Mar 2 00:55:58 2013 +0100

    core: Remove geometry-related arguments from annotation constructors
    
    Removed arguments from annotation constructors related to the geometry
    of the annotation. This change will make it easier to support creating
    annotations with flag NoRotate in the next patch (because no special
    cases will be needed: coordinate conversion code will be able to always
    assume that the underlying annotation object already exists).
    
    Data that used to be taken from these arguments is now replaced by dummy
    values, which can be modified using appropriate setter methods after
    the annotation object is created.
    
    Affected annotation types:
     - AnnotLine
     - AnnotTextMarkup
     - AnnotPolygon
     - AnnotInk

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 8c77edc..1fb8feb 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -3019,21 +3019,13 @@ Object *AnnotFreeText::getAppearanceResDict(Object *dest) {
 // AnnotLine
 //------------------------------------------------------------------------
 
-AnnotLine::AnnotLine(PDFDoc *docA, PDFRectangle *rect, PDFRectangle *lRect) :
+AnnotLine::AnnotLine(PDFDoc *docA, PDFRectangle *rect) :
     AnnotMarkup(docA, rect) {
   Object obj1;
 
   type = typeLine;
   annotObj.dictSet ("Subtype", obj1.initName ("Line"));
 
-  Object obj2, obj3;
-  obj2.initArray (doc->getXRef());
-  obj2.arrayAdd (obj3.initReal (lRect->x1));
-  obj2.arrayAdd (obj3.initReal (lRect->y1));
-  obj2.arrayAdd (obj3.initReal (lRect->x2));
-  obj2.arrayAdd (obj3.initReal (lRect->y2));
-  annotObj.dictSet ("L", &obj2);
-
   initialize (docA, annotObj.getDict());
 }
 
@@ -3498,8 +3490,7 @@ Object *AnnotLine::getAppearanceResDict(Object *dest) {
 //------------------------------------------------------------------------
 // AnnotTextMarkup
 //------------------------------------------------------------------------
-AnnotTextMarkup::AnnotTextMarkup(PDFDoc *docA, PDFRectangle *rect, AnnotSubtype subType,
-				 AnnotQuadrilaterals *quadPoints) :
+AnnotTextMarkup::AnnotTextMarkup(PDFDoc *docA, PDFRectangle *rect, AnnotSubtype subType) :
     AnnotMarkup(docA, rect) {
   Object obj1;
 
@@ -3520,22 +3511,12 @@ AnnotTextMarkup::AnnotTextMarkup(PDFDoc *docA, PDFRectangle *rect, AnnotSubtype
       assert (0 && "Invalid subtype for AnnotTextMarkup\n");
   }
 
-  Object obj2;
+  // Store dummy quadrilateral with null coordinates
+  Object obj2, obj3;
   obj2.initArray (doc->getXRef());
-
-  for (int i = 0; i < quadPoints->getQuadrilateralsLength(); ++i) {
-    Object obj3;
-
-    obj2.arrayAdd (obj3.initReal (quadPoints->getX1(i)));
-    obj2.arrayAdd (obj3.initReal (quadPoints->getY1(i)));
-    obj2.arrayAdd (obj3.initReal (quadPoints->getX2(i)));
-    obj2.arrayAdd (obj3.initReal (quadPoints->getY2(i)));
-    obj2.arrayAdd (obj3.initReal (quadPoints->getX3(i)));
-    obj2.arrayAdd (obj3.initReal (quadPoints->getY3(i)));
-    obj2.arrayAdd (obj3.initReal (quadPoints->getX4(i)));
-    obj2.arrayAdd (obj3.initReal (quadPoints->getY4(i)));
+  for (int i = 0; i < 4*2; ++i) {
+    obj2.arrayAdd (obj3.initReal (0));
   }
-
   annotObj.dictSet ("QuadPoints", &obj2);
 
   initialize(docA, annotObj.getDict());
@@ -5566,7 +5547,7 @@ void AnnotGeometry::draw(Gfx *gfx, GBool printing) {
 //------------------------------------------------------------------------
 // AnnotPolygon
 //------------------------------------------------------------------------
-AnnotPolygon::AnnotPolygon(PDFDoc *docA, PDFRectangle *rect, AnnotSubtype subType, AnnotPath *path) :
+AnnotPolygon::AnnotPolygon(PDFDoc *docA, PDFRectangle *rect, AnnotSubtype subType) :
     AnnotMarkup(docA, rect) {
   Object obj1;
 
@@ -5581,16 +5562,11 @@ AnnotPolygon::AnnotPolygon(PDFDoc *docA, PDFRectangle *rect, AnnotSubtype subTyp
       assert (0 && "Invalid subtype for AnnotGeometry\n");
   }
 
-  Object obj2;
+  // Store dummy path with one null vertex only
+  Object obj2, obj3;
   obj2.initArray (doc->getXRef());
-
-  for (int i = 0; i < path->getCoordsLength(); ++i) {
-    Object obj3;
-
-    obj2.arrayAdd (obj3.initReal (path->getX(i)));
-    obj2.arrayAdd (obj3.initReal (path->getY(i)));
-  }
-
+  obj2.arrayAdd (obj3.initReal (0));
+  obj2.arrayAdd (obj3.initReal (0));
   annotObj.dictSet ("Vertices", &obj2);
 
   initialize(docA, annotObj.getDict());
@@ -5911,7 +5887,7 @@ void AnnotCaret::setSymbol(AnnotCaretSymbol new_symbol) {
 //------------------------------------------------------------------------
 // AnnotInk
 //------------------------------------------------------------------------
-AnnotInk::AnnotInk(PDFDoc *docA, PDFRectangle *rect, AnnotPath **paths, int n_paths) :
+AnnotInk::AnnotInk(PDFDoc *docA, PDFRectangle *rect) :
     AnnotMarkup(docA, rect) {
   Object obj1;
 
@@ -5919,10 +5895,12 @@ AnnotInk::AnnotInk(PDFDoc *docA, PDFRectangle *rect, AnnotPath **paths, int n_pa
 
   annotObj.dictSet ("Subtype", obj1.initName ("Ink"));
 
-  Object obj2;
+  // Store dummy path with one null vertex only
+  Object obj2, obj3, obj4;
   obj2.initArray (doc->getXRef());
-  writeInkList(paths, n_paths, obj2.getArray());
-
+  obj2.arrayAdd (obj3.initArray (doc->getXRef()));
+  obj3.arrayAdd (obj4.initReal (0));
+  obj3.arrayAdd (obj4.initReal (0));
   annotObj.dictSet ("InkList", &obj2);
 
   initialize(docA, annotObj.getDict());
diff --git a/poppler/Annot.h b/poppler/Annot.h
index ca94429..3d3b0f6 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -960,7 +960,7 @@ public:
     captionPosTop     // Top
   };
 
-  AnnotLine(PDFDoc *docA, PDFRectangle *rect, PDFRectangle *lRect);
+  AnnotLine(PDFDoc *docA, PDFRectangle *rect);
   AnnotLine(PDFDoc *docA, Dict *dict, Object *obj);
   ~AnnotLine();
 
@@ -1025,8 +1025,7 @@ protected:
 class AnnotTextMarkup: public AnnotMarkup {
 public:
 
-  AnnotTextMarkup(PDFDoc *docA, PDFRectangle *rect, AnnotSubtype subType,
-		  AnnotQuadrilaterals *quadPoints);
+  AnnotTextMarkup(PDFDoc *docA, PDFRectangle *rect, AnnotSubtype subType);
   AnnotTextMarkup(PDFDoc *docA, Dict *dict, Object *obj);
   virtual ~AnnotTextMarkup();
 
@@ -1112,7 +1111,7 @@ public:
     polygonDimension   // PolygonDimension
   };
 
-  AnnotPolygon(PDFDoc *docA, PDFRectangle *rect, AnnotSubtype subType, AnnotPath *path);
+  AnnotPolygon(PDFDoc *docA, PDFRectangle *rect, AnnotSubtype subType);
   AnnotPolygon(PDFDoc *docA, Dict *dict, Object *obj);
   ~AnnotPolygon();
 
@@ -1187,7 +1186,7 @@ private:
 class AnnotInk: public AnnotMarkup {
 public:
 
-  AnnotInk(PDFDoc *docA, PDFRectangle *rect, AnnotPath **paths, int n_paths);
+  AnnotInk(PDFDoc *docA, PDFRectangle *rect);
   AnnotInk(PDFDoc *docA, Dict *dict, Object *obj);
   ~AnnotInk();
 
diff --git a/qt4/src/poppler-annotation.cc b/qt4/src/poppler-annotation.cc
index 5ecea80..173861e 100644
--- a/qt4/src/poppler-annotation.cc
+++ b/qt4/src/poppler-annotation.cc
@@ -2,7 +2,7 @@
  * Copyright (C) 2006, 2009, 2012 Albert Astals Cid <aacid at kde.org>
  * Copyright (C) 2006, 2008, 2010 Pino Toscano <pino at kde.org>
  * Copyright (C) 2012, Guillermo A. Amaral B. <gamaral at kde.org>
- * Copyright (C) 2012, Fabio D'Urso <fabiodurso at hotmail.it>
+ * Copyright (C) 2012, 2013 Fabio D'Urso <fabiodurso at hotmail.it>
  * Copyright (C) 2012, Tobias Koenig <tokoe at kdab.com>
  * Adapting code from
  *   Copyright (C) 2004 by Enrico Ros <eros.kde at email.it>
@@ -2063,22 +2063,20 @@ Annot* LineAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *
     parentDoc = doc;
 
     // Set pdfAnnot
-    AnnotPath * path = toAnnotPath(linePoints);
     PDFRectangle rect = toPdfRectangle(boundary);
     if (lineType == LineAnnotation::StraightLine)
     {
-        PDFRectangle lrect(path->getX(0), path->getY(0), path->getX(1), path->getY(1));
-        pdfAnnot = new AnnotLine(doc->doc, &rect, &lrect);
+        pdfAnnot = new AnnotLine(doc->doc, &rect);
     }
     else
     {
         pdfAnnot = new AnnotPolygon(doc->doc, &rect,
-                lineClosed ? Annot::typePolygon : Annot::typePolyLine, path );
+                lineClosed ? Annot::typePolygon : Annot::typePolyLine );
     }
-    delete path;
 
     // Set properties
     flushBaseAnnotationProperties();
+    q->setLinePoints(linePoints);
     q->setLineStartStyle(lineStartStyle);
     q->setLineEndStyle(lineEndStyle);
     q->setLineInnerColor(lineInnerColor);
@@ -2910,21 +2908,25 @@ AnnotQuadrilaterals * HighlightAnnotationPrivate::toQuadrilaterals(const QList<
 
 Annot* HighlightAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc)
 {
+    // Setters are defined in the public class
+    HighlightAnnotation *q = static_cast<HighlightAnnotation*>( makeAlias() );
+
     // Set page and document
     pdfPage = destPage;
     parentDoc = doc;
 
     // Set pdfAnnot
     PDFRectangle rect = toPdfRectangle(boundary);
-    AnnotQuadrilaterals * quads = toQuadrilaterals(highlightQuads);
-    pdfAnnot = new AnnotTextMarkup(destPage->getDoc(), &rect, toAnnotSubType(highlightType), quads);
-    delete quads;
+    pdfAnnot = new AnnotTextMarkup(destPage->getDoc(), &rect, toAnnotSubType(highlightType));
 
     // Set properties
     flushBaseAnnotationProperties();
+    q->setHighlightQuads(highlightQuads);
 
     highlightQuads.clear(); // Free up memory
 
+    delete q;
+
     return pdfAnnot;
 }
 
@@ -3255,25 +3257,25 @@ AnnotPath **InkAnnotationPrivate::toAnnotPaths(const QList< QLinkedList<QPointF>
 
 Annot* InkAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc)
 {
+    // Setters are defined in the public class
+    InkAnnotation *q = static_cast<InkAnnotation*>( makeAlias() );
+
     // Set page and document
     pdfPage = destPage;
     parentDoc = doc;
 
     // Set pdfAnnot
     PDFRectangle rect = toPdfRectangle(boundary);
-    AnnotPath **paths = toAnnotPaths(inkPaths);
-    const int pathsNumber = inkPaths.size();
-    pdfAnnot = new AnnotInk(destPage->getDoc(), &rect, paths, pathsNumber);
-
-    for (int i = 0; i < pathsNumber; ++i)
-        delete paths[i];
-    delete[] paths;
+    pdfAnnot = new AnnotInk(destPage->getDoc(), &rect);
 
     // Set properties
     flushBaseAnnotationProperties();
+    q->setInkPaths(inkPaths);
 
     inkPaths.clear(); // Free up memory
 
+    delete q;
+
     return pdfAnnot;
 }
 
commit 5923cfb5f7e3a0703de17e21f4952f92a44f3c14
Author: Fabio D'Urso <fabiodurso at hotmail.it>
Date:   Fri Feb 15 12:24:18 2013 +0100

    poppler_qt4viewer: Add combobox to select rotation

diff --git a/qt4/demos/navigationtoolbar.cpp b/qt4/demos/navigationtoolbar.cpp
index e9ebafa..79dd418 100644
--- a/qt4/demos/navigationtoolbar.cpp
+++ b/qt4/demos/navigationtoolbar.cpp
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2008-2009, Pino Toscano <pino at kde.org>
+ * Copyright (C) 2013, Fabio D'Urso <fabiodurso at hotmail.it>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -54,6 +55,15 @@ NavigationToolBar::NavigationToolBar(QWidget *parent)
     connect(m_zoomCombo, SIGNAL(currentIndexChanged(QString)), this, SLOT(slotZoomComboChanged(QString)));
     addWidget(m_zoomCombo);
 
+    m_rotationCombo = new QComboBox(this);
+    // NOTE: \302\260 = degree symbol
+    m_rotationCombo->addItem(trUtf8("0\302\260"));
+    m_rotationCombo->addItem(trUtf8("90\302\260"));
+    m_rotationCombo->addItem(trUtf8("180\302\260"));
+    m_rotationCombo->addItem(trUtf8("270\302\260"));
+    connect(m_rotationCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(slotRotationComboChanged(int)));
+    addWidget(m_rotationCombo);
+
     documentClosed();
 }
 
@@ -126,4 +136,9 @@ void NavigationToolBar::slotZoomComboChanged(const QString &_text)
     }
 }
 
+void NavigationToolBar::slotRotationComboChanged(int idx)
+{
+    emit rotationChanged(idx * 90);
+}
+
 #include "navigationtoolbar.moc"
diff --git a/qt4/demos/navigationtoolbar.h b/qt4/demos/navigationtoolbar.h
index 3469f01..d7dbd5d 100644
--- a/qt4/demos/navigationtoolbar.h
+++ b/qt4/demos/navigationtoolbar.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2008-2009, Pino Toscano <pino at kde.org>
+ * Copyright (C) 2013, Fabio D'Urso <fabiodurso at hotmail.it>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -40,6 +41,7 @@ public:
 
 Q_SIGNALS:
     void zoomChanged(qreal value);
+    void rotationChanged(int rotation);
 
 private Q_SLOTS:
     void slotGoFirst();
@@ -48,6 +50,7 @@ private Q_SLOTS:
     void slotGoLast();
     void slotComboActivated(int index);
     void slotZoomComboChanged(const QString &text);
+    void slotRotationComboChanged(int idx);
 
 private:
     QAction *m_firstAct;
@@ -56,6 +59,7 @@ private:
     QAction *m_nextAct;
     QAction *m_lastAct;
     QComboBox *m_zoomCombo;
+    QComboBox *m_rotationCombo;
 };
 
 #endif
diff --git a/qt4/demos/pageview.cpp b/qt4/demos/pageview.cpp
index 734dacb..0dfa5e9 100644
--- a/qt4/demos/pageview.cpp
+++ b/qt4/demos/pageview.cpp
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2008-2009, Pino Toscano <pino at kde.org>
+ * Copyright (C) 2013, Fabio D'Urso <fabiodurso at hotmail.it>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -29,6 +30,7 @@
 PageView::PageView(QWidget *parent)
     : QScrollArea(parent)
     , m_zoom(1.0)
+    , m_rotation(0)
     , m_dpiX(QApplication::desktop()->physicalDpiX())
     , m_dpiY(QApplication::desktop()->physicalDpiY())
 {
@@ -56,7 +58,18 @@ void PageView::pageChanged(int page)
     Poppler::Page *popplerPage = document()->page(page);
     const double resX = m_dpiX * m_zoom;
     const double resY = m_dpiY * m_zoom;
-    QImage image = popplerPage->renderToImage(resX, resY);
+
+    Poppler::Page::Rotation rot;
+    if (m_rotation == 0)
+        rot = Poppler::Page::Rotate0;
+    else if (m_rotation == 90)
+        rot = Poppler::Page::Rotate90;
+    else if (m_rotation == 180)
+        rot = Poppler::Page::Rotate180;
+    else // m_rotation == 270
+        rot = Poppler::Page::Rotate270;
+
+    QImage image = popplerPage->renderToImage(resX, resY, -1, -1, -1, -1, rot);
     if (!image.isNull()) {
         m_imageLabel->resize(image.size());
         m_imageLabel->setPixmap(QPixmap::fromImage(image));
@@ -76,4 +89,13 @@ void PageView::slotZoomChanged(qreal value)
     reloadPage();
 }
 
+void PageView::slotRotationChanged(int value)
+{
+    m_rotation = value;
+    if (!document()) {
+        return;
+    }
+    reloadPage();
+}
+
 #include "pageview.moc"
diff --git a/qt4/demos/pageview.h b/qt4/demos/pageview.h
index 2f7ad61..2406502 100644
--- a/qt4/demos/pageview.h
+++ b/qt4/demos/pageview.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2008-2009, Pino Toscano <pino at kde.org>
+ * Copyright (C) 2013, Fabio D'Urso <fabiodurso at hotmail.it>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -39,10 +40,12 @@ public:
 
 private Q_SLOTS:
     void slotZoomChanged(qreal value);
+    void slotRotationChanged(int value);
 
 private:
     QLabel *m_imageLabel;
     qreal m_zoom;
+    int m_rotation;
     int m_dpiX;
     int m_dpiY;
 };
diff --git a/qt4/demos/viewer.cpp b/qt4/demos/viewer.cpp
index 0201eea..c34af23 100644
--- a/qt4/demos/viewer.cpp
+++ b/qt4/demos/viewer.cpp
@@ -2,6 +2,7 @@
  * Copyright (C) 2008-2009, Pino Toscano <pino at kde.org>
  * Copyright (C) 2008, Albert Astals Cid <aacid at kde.org>
  * Copyright (C) 2009, Shawn Rutledge <shawn.t.rutledge at gmail.com>
+ * Copyright (C) 2013, Fabio D'Urso <fabiodurso at hotmail.it>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -148,6 +149,7 @@ PdfViewer::PdfViewer()
     }
 
     connect(navbar, SIGNAL(zoomChanged(qreal)), view, SLOT(slotZoomChanged(qreal)));
+    connect(navbar, SIGNAL(rotationChanged(int)), view, SLOT(slotRotationChanged(int)));
 
     // activate AA by default
     m_settingsTextAAAct->setChecked(true);
commit 74ea15cc454f31b772e71b3525b71045dbfa5527
Author: Fabio D'Urso <fabiodurso at hotmail.it>
Date:   Tue Jun 25 19:56:20 2013 +0200

    core: Support for rendering annotations with flagNoRotate
    
    Gfx::drawAnnot now makes a counter-rotation if flagNoRotate is set

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 791a645..8c77edc 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -24,7 +24,7 @@
 // Copyright (C) 2008 Hugo Mercier <hmercier31 at gmail.com>
 // Copyright (C) 2009 Ilya Gorenbein <igorenbein at finjan.com>
 // Copyright (C) 2011, 2013 José Aliste <jaliste at src.gnome.org>
-// Copyright (C) 2012 Fabio D'Urso <fabiodurso at hotmail.it>
+// Copyright (C) 2012, 2013 Fabio D'Urso <fabiodurso at hotmail.it>
 // Copyright (C) 2012, 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
 // Copyright (C) 2012 Tobias Koenig <tokoe at kdab.com>
 // Copyright (C) 2013 Peter Breitenlohner <peb at mppmu.mpg.de>
@@ -1780,6 +1780,18 @@ GBool Annot::isVisible(GBool printing) {
   return gTrue;
 }
 
+int Annot::getRotation() const
+{
+  Page *pageobj = doc->getPage(page);
+  assert(pageobj != NULL);
+
+  if (flags & flagNoRotate) {
+    return (360 - pageobj->getRotate()) % 360;
+  } else {
+    return 0;
+  }
+}
+
 void Annot::draw(Gfx *gfx, GBool printing) {
   Object obj;
 
@@ -1790,7 +1802,7 @@ void Annot::draw(Gfx *gfx, GBool printing) {
   // draw the appearance stream
   appearance.fetch(gfx->getXRef(), &obj);
   gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
-      rect->x1, rect->y1, rect->x2, rect->y2);
+      rect->x1, rect->y1, rect->x2, rect->y2, getRotation());
   obj.free();
 }
 
@@ -2457,10 +2469,11 @@ void AnnotText::draw(Gfx *gfx, GBool printing) {
   if (appearBBox) {
     gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
                    appearBBox->getPageXMin(), appearBBox->getPageYMin(),
-                   appearBBox->getPageXMax(), appearBBox->getPageYMax());
+                   appearBBox->getPageXMax(), appearBBox->getPageYMax(),
+                   getRotation());
   } else {
     gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
-                   rect->x1, rect->y1, rect->x2, rect->y2);
+                   rect->x1, rect->y1, rect->x2, rect->y2, getRotation());
   }
   obj.free();
 }
@@ -2555,7 +2568,7 @@ void AnnotLink::draw(Gfx *gfx, GBool printing) {
   // draw the appearance stream
   appearance.fetch(gfx->getXRef(), &obj);
   gfx->drawAnnot(&obj, border, color,
-		 rect->x1, rect->y1, rect->x2, rect->y2);
+		 rect->x1, rect->y1, rect->x2, rect->y2, getRotation());
   obj.free();
 }
 
@@ -2989,7 +3002,7 @@ void AnnotFreeText::draw(Gfx *gfx, GBool printing) {
   // draw the appearance stream
   appearance.fetch(gfx->getXRef(), &obj);
   gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
-                 rect->x1, rect->y1, rect->x2, rect->y2);
+                 rect->x1, rect->y1, rect->x2, rect->y2, getRotation());
   obj.free();
 }
 
@@ -3464,10 +3477,11 @@ void AnnotLine::draw(Gfx *gfx, GBool printing) {
   if (appearBBox) {
     gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
                    appearBBox->getPageXMin(), appearBBox->getPageYMin(),
-                   appearBBox->getPageXMax(), appearBBox->getPageYMax());
+                   appearBBox->getPageXMax(), appearBBox->getPageYMax(),
+                   getRotation());
   } else {
     gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
-                   rect->x1, rect->y1, rect->x2, rect->y2);
+                   rect->x1, rect->y1, rect->x2, rect->y2, getRotation());
   }
   obj.free();
 }
@@ -3778,10 +3792,11 @@ void AnnotTextMarkup::draw(Gfx *gfx, GBool printing) {
   if (appearBBox) {
     gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
                    appearBBox->getPageXMin(), appearBBox->getPageYMin(),
-                   appearBBox->getPageXMax(), appearBBox->getPageYMax());
+                   appearBBox->getPageXMax(), appearBBox->getPageYMax(),
+                   getRotation());
   } else {
     gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
-                   rect->x1, rect->y1, rect->x2, rect->y2);
+                   rect->x1, rect->y1, rect->x2, rect->y2, getRotation());
   }
   obj.free();
 }
@@ -5045,7 +5060,7 @@ void AnnotWidget::draw(Gfx *gfx, GBool printing) {
     delete dict;
   }
   gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
-		 rect->x1, rect->y1, rect->x2, rect->y2);
+		 rect->x1, rect->y1, rect->x2, rect->y2, getRotation());
   if (addDingbatsResource) {
     gfx->popResources();
   }
@@ -5201,7 +5216,7 @@ void AnnotMovie::draw(Gfx *gfx, GBool printing) {
   // draw the appearance stream
   appearance.fetch(gfx->getXRef(), &obj);
   gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
-		 rect->x1, rect->y1, rect->x2, rect->y2);
+		 rect->x1, rect->y1, rect->x2, rect->y2, getRotation());
   obj.free();
 }
 
@@ -5544,7 +5559,7 @@ void AnnotGeometry::draw(Gfx *gfx, GBool printing) {
   // draw the appearance stream
   appearance.fetch(gfx->getXRef(), &obj);
   gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
-		 rect->x1, rect->y1, rect->x2, rect->y2);
+		 rect->x1, rect->y1, rect->x2, rect->y2, getRotation());
   obj.free();
 }
 
@@ -5831,10 +5846,11 @@ void AnnotPolygon::draw(Gfx *gfx, GBool printing) {
   if (appearBBox) {
     gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
                    appearBBox->getPageXMin(), appearBBox->getPageYMin(),
-                   appearBBox->getPageXMax(), appearBBox->getPageYMax());
+                   appearBBox->getPageXMax(), appearBBox->getPageYMax(),
+                   getRotation());
   } else {
     gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
-                   rect->x1, rect->y1, rect->x2, rect->y2);
+                   rect->x1, rect->y1, rect->x2, rect->y2, getRotation());
   }
   obj.free();
 }
@@ -6044,10 +6060,11 @@ void AnnotInk::draw(Gfx *gfx, GBool printing) {
   if (appearBBox) {
     gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
                    appearBBox->getPageXMin(), appearBBox->getPageYMin(),
-                   appearBBox->getPageXMax(), appearBBox->getPageYMax());
+                   appearBBox->getPageXMax(), appearBBox->getPageYMax(),
+                   getRotation());
   } else {
     gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
-                   rect->x1, rect->y1, rect->x2, rect->y2);
+                   rect->x1, rect->y1, rect->x2, rect->y2, getRotation());
   }
   obj.free();
 }
@@ -6264,7 +6281,7 @@ void AnnotFileAttachment::draw(Gfx *gfx, GBool printing) {
   // draw the appearance stream
   appearance.fetch(gfx->getXRef(), &obj);
   gfx->drawAnnot(&obj, border, color,
-		 rect->x1, rect->y1, rect->x2, rect->y2);
+		 rect->x1, rect->y1, rect->x2, rect->y2, getRotation());
   obj.free();
 }
 
@@ -6426,7 +6443,7 @@ void AnnotSound::draw(Gfx *gfx, GBool printing) {
   // draw the appearance stream
   appearance.fetch(gfx->getXRef(), &obj);
   gfx->drawAnnot(&obj, border, color,
-		 rect->x1, rect->y1, rect->x2, rect->y2);
+		 rect->x1, rect->y1, rect->x2, rect->y2, getRotation());
   obj.free();
 }
 
diff --git a/poppler/Annot.h b/poppler/Annot.h
index 7be2114..ca94429 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -22,7 +22,7 @@
 // Copyright (C) 2008 Pino Toscano <pino at kde.org>
 // Copyright (C) 2008 Tomas Are Haavet <tomasare at gmail.com>
 // Copyright (C) 2009-2011, 2013 Albert Astals Cid <aacid at kde.org>
-// Copyright (C) 2012 Fabio D'Urso <fabiodurso at hotmail.it>
+// Copyright (C) 2012, 2013 Fabio D'Urso <fabiodurso at hotmail.it>
 // Copyright (C) 2012 Tobias Koenig <tokoe at kdab.com>
 // Copyright (C) 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
 //
@@ -624,6 +624,7 @@ protected:
   void createResourcesDict(const char *formName, Object *formStream, const char *stateName,
 			   double opacity, const char *blendMode, Object *resDict);
   GBool isVisible(GBool printing);
+  int getRotation() const;
 
   // Updates the field key of the annotation dictionary
   // and sets M to the current time
diff --git a/poppler/Gfx.cc b/poppler/Gfx.cc
index c609292..f2971d6 100644
--- a/poppler/Gfx.cc
+++ b/poppler/Gfx.cc
@@ -35,7 +35,7 @@
 // Copyright (C) 2010 Christian Feuersänger <cfeuersaenger at googlemail.com>
 // Copyright (C) 2011 Axel Strübing <axel.struebing at freenet.de>
 // Copyright (C) 2012 Even Rouault <even.rouault at mines-paris.org>
-// Copyright (C) 2012 Fabio D'Urso <fabiodurso at hotmail.it>
+// Copyright (C) 2012, 2013 Fabio D'Urso <fabiodurso at hotmail.it>
 // Copyright (C) 2012 Lu Wang <coolwanglu at gmail.com>
 //
 // To see a description of the changes please see the Changelog file that
@@ -62,6 +62,7 @@
 #include "Object.h"
 #include "PDFDoc.h"
 #include "Array.h"
+#include "Annot.h"
 #include "Dict.h"
 #include "Stream.h"
 #include "Lexer.h"
@@ -5131,8 +5132,20 @@ void Gfx::opMarkPoint(Object args[], int numArgs) {
 // misc
 //------------------------------------------------------------------------
 
+struct GfxStackStateSaver {
+  GfxStackStateSaver(Gfx *gfx) : gfx(gfx) {
+    gfx->saveState();
+  }
+
+  ~GfxStackStateSaver() {
+    gfx->restoreState();
+  }
+
+  Gfx * const gfx;
+};
+
 void Gfx::drawAnnot(Object *str, AnnotBorder *border, AnnotColor *aColor,
-		    double xMin, double yMin, double xMax, double yMax) {
+		    double xMin, double yMin, double xMax, double yMax, int rotate) {
   Dict *dict, *resDict;
   Object matrixObj, bboxObj, resObj, obj1;
   double formXMin, formYMin, formXMax, formYMax;
@@ -5153,6 +5166,28 @@ void Gfx::drawAnnot(Object *str, AnnotBorder *border, AnnotColor *aColor,
     return;
   }
 
+  // saves gfx state and automatically restores it on return
+  GfxStackStateSaver stackStateSaver(this);
+
+  // Rotation around the topleft corner (for the NoRotate flag)
+  if (rotate != 0) {
+    const double angle_rad = rotate * M_PI / 180;
+    const double c = cos(angle_rad);
+    const double s = sin(angle_rad);
+
+    // (xMin, yMax) is the pivot
+    const double unrotateMTX[6] = {
+        +c, -s,
+        +s, +c,
+        -c*xMin - s*yMax + xMin, -c*yMax + s*xMin + yMax
+    };
+
+    state->concatCTM(unrotateMTX[0], unrotateMTX[1], unrotateMTX[2],
+                     unrotateMTX[3], unrotateMTX[4], unrotateMTX[5]);
+    out->updateCTM(state, unrotateMTX[0], unrotateMTX[1], unrotateMTX[2],
+                          unrotateMTX[3], unrotateMTX[4], unrotateMTX[5]);
+  }
+
   // draw the appearance stream (if there is one)
   if (str->isStream()) {
 
@@ -5276,7 +5311,6 @@ void Gfx::drawAnnot(Object *str, AnnotBorder *border, AnnotColor *aColor,
 
   // draw the border
   if (border && border->getWidth() > 0) {
-    saveState();
     if (state->getStrokeColorSpace()->getMode() != csDeviceRGB) {
       state->setStrokePattern(NULL);
       state->setStrokeColorSpace(new GfxDeviceRGBColorSpace());
@@ -5315,7 +5349,6 @@ void Gfx::drawAnnot(Object *str, AnnotBorder *border, AnnotColor *aColor,
       state->closePath();
     }
     out->stroke(state);
-    restoreState();
   }
 }
 
diff --git a/poppler/Gfx.h b/poppler/Gfx.h
index 4107e8a..aba3b7e 100644
--- a/poppler/Gfx.h
+++ b/poppler/Gfx.h
@@ -21,6 +21,7 @@
 // Copyright (C) 2009, 2010, 2012, 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
 // Copyright (C) 2010 David Benjamin <davidben at mit.edu>
 // Copyright (C) 2010 Christian Feuersänger <cfeuersaenger at googlemail.com>
+// Copyright (C) 2013 Fabio D'Urso <fabiodurso at hotmail.it>
 //
 // To see a description of the changes please see the Changelog file that
 // came with your tarball or type make ChangeLog if you are building from git
@@ -166,7 +167,7 @@ public:
   // Display an annotation, given its appearance (a Form XObject),
   // border style, and bounding box (in default user space).
   void drawAnnot(Object *str, AnnotBorder *border, AnnotColor *aColor,
-		 double xMin, double yMin, double xMax, double yMax);
+		 double xMin, double yMin, double xMax, double yMax, int rotate);
 
   // Save graphics state.
   void saveState();


More information about the poppler mailing list