[poppler] 16 commits - qt4/src

Albert Astals Cid aacid at kemper.freedesktop.org
Thu Apr 12 11:43:37 PDT 2012


 qt4/src/poppler-annotation-helper.h  |   38 
 qt4/src/poppler-annotation-private.h |   60 
 qt4/src/poppler-annotation.cc        | 2888 ++++++++++++++++++++++++++++++-----
 qt4/src/poppler-annotation.h         |  306 ++-
 qt4/src/poppler-link.cc              |    2 
 qt4/src/poppler-page.cc              |  792 ---------
 qt4/src/poppler-ps-converter.cc      |   23 
 qt4/src/poppler-qt4.h                |   33 
 8 files changed, 2866 insertions(+), 1276 deletions(-)

New commits:
commit 9a10d31fca7f060f24bae9efe15662f02a9684ca
Author: Fabio D'Urso <fabiodurso at hotmail.it>
Date:   Thu Apr 12 20:31:23 2012 +0200

    qt4: Remove unimplemented revision setters from public API

diff --git a/qt4/src/poppler-annotation-private.h b/qt4/src/poppler-annotation-private.h
index ea4a88c..2ee7d77 100644
--- a/qt4/src/poppler-annotation-private.h
+++ b/qt4/src/poppler-annotation-private.h
@@ -44,6 +44,8 @@ class AnnotationPrivate : public QSharedData
         AnnotationPrivate();
         virtual ~AnnotationPrivate();
 
+        void addRevision(Annotation *ann, Annotation::RevScope scope, Annotation::RevType type);
+
         /* Returns an Annotation of the right subclass whose d_ptr points to
          * this AnnotationPrivate */
         virtual Annotation * makeAlias() = 0;
diff --git a/qt4/src/poppler-annotation.cc b/qt4/src/poppler-annotation.cc
index 37b7829..4d7cd84 100644
--- a/qt4/src/poppler-annotation.cc
+++ b/qt4/src/poppler-annotation.cc
@@ -126,6 +126,16 @@ AnnotationPrivate::AnnotationPrivate()
 {
 }
 
+void AnnotationPrivate::addRevision( Annotation *ann, Annotation::RevScope scope, Annotation::RevType type )
+{
+    /* Since ownership stays with the caller, create an alias of ann */
+    revisions.append( ann->d_ptr->makeAlias() );
+
+    /* Set revision properties */
+    revisionScope = scope;
+    revisionType = type;
+}
+
 AnnotationPrivate::~AnnotationPrivate()
 {
     // Delete all children revisions
@@ -173,8 +183,7 @@ void AnnotationPrivate::flushBaseAnnotationProperties()
     // Flush revisions
     foreach (Annotation *r, revisions)
     {
-        // addRevision creates a native Annot because pdfAnnot is set
-        q->addRevision(r, r->d_ptr->revisionScope, r->d_ptr->revisionType);
+        // TODO: Flush revision
         delete r; // Object is no longer needed
     }
 
@@ -748,6 +757,8 @@ Annotation::~Annotation()
 Annotation::Annotation( AnnotationPrivate &dd, const QDomNode &annNode )
     : d_ptr( &dd )
 {
+    Q_D( Annotation );
+
     window.width = window.height = 0;
 
     // get the [base] element of the annotation node
@@ -884,7 +895,7 @@ Annotation::Annotation( AnnotationPrivate &dd, const QDomNode &annNode )
         {
             RevScope scope = (RevScope)revElement.attribute( "revScope" ).toInt();
             RevType type = (RevType)revElement.attribute( "revType" ).toInt();
-            addRevision(reply, scope, type);
+            d->addRevision(reply, scope, type);
             delete reply;
         }
     }
@@ -1443,19 +1454,6 @@ Annotation::RevScope Annotation::revisionScope() const
     return Annotation::Root; // It's not a revision
 }
 
-void Annotation::setRevisionScope( Annotation::RevScope scope )
-{
-    Q_D( Annotation );
-
-    if (!d->pdfAnnot)
-    {
-        d->revisionScope = scope;
-        return;
-    }
-
-    // TODO: Set pdfAnnot
-}
-
 Annotation::RevType Annotation::revisionType() const
 {
     Q_D( const Annotation );
@@ -1489,19 +1487,6 @@ Annotation::RevType Annotation::revisionType() const
     return Annotation::None;
 }
 
-void Annotation::setRevisionType( Annotation::RevType type )
-{
-    Q_D( Annotation );
-
-    if (!d->pdfAnnot)
-    {
-        d->revisionType = type;
-        return;
-    }
-
-    // TODO: Set pdfAnnot
-}
-
 QList<Annotation*> Annotation::revisions() const
 {
     Q_D( const Annotation );
@@ -1518,25 +1503,6 @@ QList<Annotation*> Annotation::revisions() const
     return AnnotationPrivate::findAnnotations( d->pdfPage, d->parentDoc, d->pdfAnnot->getId() );
 }
 
-void Annotation::addRevision( Annotation *ann, RevScope scope, RevType type )
-{
-    Q_D( Annotation );
-
-    if (!d->pdfAnnot)
-    {
-        /* Since ownership stays with the caller, create an alias of ann */
-        d->revisions.append( ann->d_ptr->makeAlias() );
-    }
-    else
-    {
-        // TODO: Add annotation to page and set IRT
-    }
-
-    /* Set revision properties */
-    ann->setRevisionScope(scope);
-    ann->setRevisionType(type);
-}
-
 //END Annotation implementation
 
 
diff --git a/qt4/src/poppler-annotation.h b/qt4/src/poppler-annotation.h
index e0e98ee..b897603 100644
--- a/qt4/src/poppler-annotation.h
+++ b/qt4/src/poppler-annotation.h
@@ -279,19 +279,6 @@ class POPPLER_QT4_EXPORT Annotation
     void storeBaseAnnotationProperties( QDomNode & parentNode, QDomDocument & document ) const;
     Q_DECLARE_PRIVATE( Annotation )
     QExplicitlySharedDataPointer<AnnotationPrivate> d_ptr;
-
-    //BEGIN: To be made public when revision write support is implemented
-    void setRevisionType( RevType type );
-    void setRevisionScope( RevScope scope );
-    /**
-     * Adds a revision to this annotation. Scope and type are assigned to the
-     * newly added annotation.
-     *
-     * \note Ownership of the annotation object stays with the caller, who can
-     *       delete it at any time.
-     */
-    void addRevision( Annotation *ann, RevScope scope = Reply, RevType type = None );
-    //END
     /// \endcond
 
   private:
commit 0531329aeb8783c48f056929e6e81cebda33500f
Author: Albert Astals Cid <aacid at kde.org>
Date:   Thu Apr 12 20:07:13 2012 +0200

    [qt4] Mark the dummy stuff as deprecated

diff --git a/qt4/src/poppler-annotation.h b/qt4/src/poppler-annotation.h
index 9fe729e..e0e98ee 100644
--- a/qt4/src/poppler-annotation.h
+++ b/qt4/src/poppler-annotation.h
@@ -242,8 +242,8 @@ class POPPLER_QT4_EXPORT Annotation
     void setPopup( const Popup& popup );
 
     /// \cond PRIVATE
-    // This field is deprecated and not used any more.
-    struct { int width, height; } window; // Always set to zero
+    // This field is deprecated and not used any more. Use popup
+    Q_DECL_DEPRECATED struct { int width, height; } window; // Always set to zero
     /// \endcond
 
     /// \since 0.20
commit 67b7b2bdd0943680437d96349c3415aa40082cbb
Author: Albert Astals Cid <aacid at kde.org>
Date:   Thu Apr 12 20:06:52 2012 +0200

    [qt4] initialize the dummy members here too

diff --git a/qt4/src/poppler-annotation.cc b/qt4/src/poppler-annotation.cc
index dfe4e37..37b7829 100644
--- a/qt4/src/poppler-annotation.cc
+++ b/qt4/src/poppler-annotation.cc
@@ -1,5 +1,5 @@
 /* poppler-annotation.cc: qt interface to poppler
- * Copyright (C) 2006, 2009 Albert Astals Cid <aacid at kde.org>
+ * 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>
@@ -748,6 +748,8 @@ Annotation::~Annotation()
 Annotation::Annotation( AnnotationPrivate &dd, const QDomNode &annNode )
     : d_ptr( &dd )
 {
+    window.width = window.height = 0;
+
     // get the [base] element of the annotation node
     QDomElement e = AnnotationUtils::findChildElement( annNode, "base" );
     if ( e.isNull() )
commit bf171382afb6b50284c3855e3a1815a15ec34366
Author: Albert Astals Cid <aacid at kde.org>
Date:   Thu Apr 12 19:24:42 2012 +0200

    Add since markers

diff --git a/qt4/src/poppler-annotation.h b/qt4/src/poppler-annotation.h
index 779ce2d..9fe729e 100644
--- a/qt4/src/poppler-annotation.h
+++ b/qt4/src/poppler-annotation.h
@@ -1,5 +1,5 @@
 /* poppler-annotation.h: qt interface to poppler
- * Copyright (C) 2006-2008, Albert Astals Cid <aacid at kde.org>
+ * Copyright (C) 2006-2008, 2012 Albert Astals Cid <aacid at kde.org>
  * Copyright (C) 2006, 2008 Pino Toscano <pino at kde.org>
  * Copyright (C) 2007, Brad Hards <bradh at frogmouth.net>
  * Copyright (C) 2010, Philip Lorenz <lorenzph+freedesktop at gmail.com>
@@ -112,12 +112,12 @@ class POPPLER_QT4_EXPORT Annotation
     // 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, A_BASE = 0 };
+                   AMovie = 11, AScreen = 12 /** \since 0.20 */, A_BASE = 0 };
     enum Flag { Hidden = 1, FixedSize = 2, FixedRotation = 4, DenyPrint = 8,
                 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, Reply = 1, Group = 2, Delete = 4 };
+    enum RevScope { Root = 0 /** \since 0.20 */, Reply = 1, Group = 2, Delete = 4 };
     enum RevType { None = 1,  Marked = 2, Unmarked = 4,  Accepted = 8, Rejected = 16, Cancelled = 32, Completed = 64 };
 
     /**
@@ -633,6 +633,7 @@ class POPPLER_QT4_EXPORT LinkAnnotation : public Annotation
     // local enums
     enum HighlightMode { None, Invert, Outline, Push };
 
+    /** \since 0.20 */
     Link* linkDestination() const;
     void setLinkDestination( Link *link );
 
commit e36fd775394ee752c0f62f789359c72b52094975
Author: Albert Astals Cid <aacid at kde.org>
Date:   Thu Apr 12 18:58:29 2012 +0200

    Remove unneeded forward declaration

diff --git a/qt4/src/poppler-qt4.h b/qt4/src/poppler-qt4.h
index 84837c8..f314108 100644
--- a/qt4/src/poppler-qt4.h
+++ b/qt4/src/poppler-qt4.h
@@ -1,7 +1,7 @@
 /* poppler-qt.h: qt interface to poppler
  * Copyright (C) 2005, Net Integration Technologies, Inc.
  * Copyright (C) 2005, 2007, Brad Hards <bradh at frogmouth.net>
- * Copyright (C) 2005-2011, Albert Astals Cid <aacid at kde.org>
+ * Copyright (C) 2005-2012, Albert Astals Cid <aacid at kde.org>
  * Copyright (C) 2005, Stefan Kebekus <stefan.kebekus at math.uni-koeln.de>
  * Copyright (C) 2006-2011, Pino Toscano <pino at kde.org>
  * Copyright (C) 2009 Shawn Rutledge <shawn.t.rutledge at gmail.com>
@@ -44,7 +44,6 @@
 class EmbFile;
 class Sound;
 class AnnotMovie;
-class AnnotScreen;
 
 /**
    The %Poppler Qt4 binding.
commit c1aa4a8c0aa9d46757e3849776acac42731e02d1
Author: Fabio D'Urso <fabiodurso at hotmail.it>
Date:   Thu Apr 12 00:39:33 2012 +0200

    qt4: Annotation appearance invalidation
    
    Call Annot::invalidateAppearance every time the visual aspect is changed

diff --git a/qt4/src/poppler-annotation.cc b/qt4/src/poppler-annotation.cc
index 549fe23..dfe4e37 100644
--- a/qt4/src/poppler-annotation.cc
+++ b/qt4/src/poppler-annotation.cc
@@ -1063,6 +1063,7 @@ void Annotation::setContents( const QString &contents )
     GooString *s = QStringToUnicodeGooString(contents);
     d->pdfAnnot->setContents(s);
     delete s;
+    d->pdfAnnot->invalidateAppearance();
 }
 
 QString Annotation::uniqueName() const
@@ -1226,6 +1227,7 @@ void Annotation::setFlags( int flags )
     }
 
     d->pdfAnnot->setFlags(toPdfFlags( flags ));
+    d->pdfAnnot->invalidateAppearance();
 }
 
 QRectF Annotation::boundary() const
@@ -1251,6 +1253,7 @@ void Annotation::setBoundary( const QRectF &boundary )
 
     PDFRectangle rect = d->toPdfRectangle(boundary);
     d->pdfAnnot->setRect(&rect);
+    d->pdfAnnot->invalidateAppearance();
 }
 
 Annotation::Style Annotation::style() const
@@ -1331,6 +1334,7 @@ void Annotation::setStyle( const Annotation::Style& style )
     border->setHorizontalCorner( style.xCorners() );
     border->setVerticalCorner( style.yCorners() );
     d->pdfAnnot->setBorder(border);
+    d->pdfAnnot->invalidateAppearance();
 }
 
 Annotation::Popup Annotation::popup() const
@@ -1783,6 +1787,7 @@ void TextAnnotation::setTextIcon( const QString &icon )
         QByteArray encoded = icon.toLatin1();
         GooString s(encoded.constData());
         textann->setIcon(&s);
+        d->pdfAnnot->invalidateAppearance();
     }
 }
 
@@ -1830,6 +1835,7 @@ void TextAnnotation::setTextFont( const QFont &font )
     GooString * da = TextAnnotationPrivate::toAppearanceString(font);
     ftextann->setAppearanceString(da);
     delete da;
+    d->pdfAnnot->invalidateAppearance();
 }
 
 int TextAnnotation::inplaceAlign() const
@@ -1862,6 +1868,7 @@ void TextAnnotation::setInplaceAlign( int align )
     {
         AnnotFreeText * ftextann = static_cast<AnnotFreeText*>(d->pdfAnnot);
         ftextann->setQuadding((AnnotFreeText::AnnotFreeTextQuadding)align);
+        d->pdfAnnot->invalidateAppearance();
     }
 }
 
@@ -1930,6 +1937,7 @@ void TextAnnotation::setCalloutPoints( const QVector<QPointF> &points )
     if (count == 0)
     {
         ftextann->setCalloutLine(0);
+        d->pdfAnnot->invalidateAppearance();
         return;
     }
 
@@ -1959,6 +1967,7 @@ void TextAnnotation::setCalloutPoints( const QVector<QPointF> &points )
 
     ftextann->setCalloutLine(callout);
     delete callout;
+    d->pdfAnnot->invalidateAppearance();
 }
 
 TextAnnotation::InplaceIntent TextAnnotation::inplaceIntent() const
@@ -1991,6 +2000,7 @@ void TextAnnotation::setInplaceIntent( TextAnnotation::InplaceIntent intent )
     {
         AnnotFreeText * ftextann = static_cast<AnnotFreeText*>(d->pdfAnnot);
         ftextann->setIntent((AnnotFreeText::AnnotFreeTextIntent)intent);
+        d->pdfAnnot->invalidateAppearance();
     }
 }
 
@@ -2277,6 +2287,8 @@ void LineAnnotation::setLinePoints( const QLinkedList<QPointF> &points )
         polyann->setVertices(p);
         delete p;
     }
+
+    d->pdfAnnot->invalidateAppearance();
 }
 
 LineAnnotation::TermStyle LineAnnotation::lineStartStyle() const
@@ -2318,6 +2330,8 @@ void LineAnnotation::setLineStartStyle( LineAnnotation::TermStyle style )
         AnnotPolygon *polyann = static_cast<AnnotPolygon*>(d->pdfAnnot);
         polyann->setStartEndStyle((AnnotLineEndingStyle)style, polyann->getEndStyle());
     }
+
+    d->pdfAnnot->invalidateAppearance();
 }
 
 LineAnnotation::TermStyle LineAnnotation::lineEndStyle() const
@@ -2359,6 +2373,8 @@ void LineAnnotation::setLineEndStyle( LineAnnotation::TermStyle style )
         AnnotPolygon *polyann = static_cast<AnnotPolygon*>(d->pdfAnnot);
         polyann->setStartEndStyle(polyann->getStartStyle(), (AnnotLineEndingStyle)style);
     }
+
+    d->pdfAnnot->invalidateAppearance();
 }
 
 bool LineAnnotation::isLineClosed() const
@@ -2398,6 +2414,8 @@ void LineAnnotation::setLineClosed( bool closed )
             if (polyann->getIntent() == AnnotPolygon::polygonDimension)
                 polyann->setIntent( AnnotPolygon::polylineDimension );
         }
+
+        d->pdfAnnot->invalidateAppearance();
     }
 }
 
@@ -2446,6 +2464,8 @@ void LineAnnotation::setLineInnerColor( const QColor &color )
         AnnotPolygon *polyann = static_cast<AnnotPolygon*>(d->pdfAnnot);
         polyann->setInteriorColor(c);
     }
+
+    d->pdfAnnot->invalidateAppearance();
 }
 
 double LineAnnotation::lineLeadingForwardPoint() const
@@ -2478,6 +2498,7 @@ void LineAnnotation::setLineLeadingForwardPoint( double point )
     {
         AnnotLine *lineann = static_cast<AnnotLine*>(d->pdfAnnot);
         lineann->setLeaderLineLength(point);
+        d->pdfAnnot->invalidateAppearance();
     }
 }
 
@@ -2511,6 +2532,7 @@ void LineAnnotation::setLineLeadingBackPoint( double point )
     {
         AnnotLine *lineann = static_cast<AnnotLine*>(d->pdfAnnot);
         lineann->setLeaderLineExtension(point);
+        d->pdfAnnot->invalidateAppearance();
     }
 }
 
@@ -2544,6 +2566,7 @@ void LineAnnotation::setLineShowCaption( bool show )
     {
         AnnotLine *lineann = static_cast<AnnotLine*>(d->pdfAnnot);
         lineann->setCaption(show);
+        d->pdfAnnot->invalidateAppearance();
     }
 }
 
@@ -2600,6 +2623,8 @@ void LineAnnotation::setLineIntent( LineAnnotation::LineIntent intent )
                 polyann->setIntent( AnnotPolygon::polylineDimension );
         }
     }
+
+    d->pdfAnnot->invalidateAppearance();
 }
 
 
@@ -2737,6 +2762,8 @@ void GeomAnnotation::setGeomType( GeomAnnotation::GeomType type )
         geomann->setType(Annot::typeSquare);
     else // GeomAnnotation::InscribedCircle
         geomann->setType(Annot::typeCircle);
+
+    d->pdfAnnot->invalidateAppearance();
 }
 
 QColor GeomAnnotation::geomInnerColor() const
@@ -2762,6 +2789,7 @@ void GeomAnnotation::setGeomInnerColor( const QColor &color )
 
     AnnotGeometry * geomann = static_cast<AnnotGeometry*>(d->pdfAnnot);
     geomann->setInteriorColor(convertQColor( color ));
+    d->pdfAnnot->invalidateAppearance();
 }
 
 
@@ -3019,6 +3047,7 @@ void HighlightAnnotation::setHighlightType( HighlightAnnotation::HighlightType t
 
     AnnotTextMarkup * hlann = static_cast<AnnotTextMarkup*>(d->pdfAnnot);
     hlann->setType(HighlightAnnotationPrivate::toAnnotSubType( type ));
+    d->pdfAnnot->invalidateAppearance();
 }
 
 QList< HighlightAnnotation::Quad > HighlightAnnotation::highlightQuads() const
@@ -3046,6 +3075,7 @@ void HighlightAnnotation::setHighlightQuads( const QList< HighlightAnnotation::Q
     AnnotQuadrilaterals * quadrilaterals = d->toQuadrilaterals(quads);
     hlann->setQuadrilaterals(quadrilaterals);
     delete quadrilaterals;
+    d->pdfAnnot->invalidateAppearance();
 }
 
 
@@ -3171,6 +3201,7 @@ void StampAnnotation::setStampIconName( const QString &name )
     QByteArray encoded = name.toLatin1();
     GooString s(encoded.constData());
     stampann->setIcon(&s);
+    d->pdfAnnot->invalidateAppearance();
 }
 
 /** InkAnnotation [Annotation] */
@@ -3383,6 +3414,8 @@ void InkAnnotation::setInkPaths( const QList< QLinkedList<QPointF> > &paths )
     for (int i = 0; i < pathsNumber; ++i)
         delete annotpaths[i];
     delete[] annotpaths;
+
+    d->pdfAnnot->invalidateAppearance();
 }
 
 
@@ -3850,6 +3883,7 @@ void CaretAnnotation::setCaretSymbol( CaretAnnotation::CaretSymbol symbol )
 
     AnnotCaret * caretann = static_cast<AnnotCaret *>(d->pdfAnnot);
     caretann->setSymbol((AnnotCaret::AnnotCaretSymbol)symbol);
+    d->pdfAnnot->invalidateAppearance();
 }
 
 /** FileAttachmentAnnotation [Annotation] */
commit 4338ae354c66e4df8d7d70a156517e27b3b80539
Author: Fabio D'Urso <fabiodurso at hotmail.it>
Date:   Sun Mar 25 22:58:33 2012 +0200

    qt4: Added HideAnnotations option to PSConverter

diff --git a/qt4/src/poppler-ps-converter.cc b/qt4/src/poppler-ps-converter.cc
index 1df6b2c..63fb7b4 100644
--- a/qt4/src/poppler-ps-converter.cc
+++ b/qt4/src/poppler-ps-converter.cc
@@ -3,6 +3,7 @@
  * Copyright (C) 2008, Pino Toscano <pino at kde.org>
  * Copyright (C) 2010 Hib Eris <hib at hiberis.nl>
  * Copyright (C) 2011 Glad Deschrijver <glad.deschrijver at gmail.com>
+ * Copyright (C) 2012 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
@@ -178,6 +179,14 @@ void PSConverter::setPageConvertedCallback(void (* callback)(int page, void *pay
 	d->pageConvertedPayload = payload;
 }
 
+static GBool annotDisplayDecideCbk(Annot *annot, void *user_data)
+{
+	if (annot->getType() == Annot::typeWidget)
+		return gTrue; // Never hide forms
+	else
+		return *(GBool*)user_data;
+}
+
 bool PSConverter::convert()
 {
 	Q_D(PSConverter);
@@ -230,9 +239,21 @@ bool PSConverter::convert()
 	if (psOut->isOk())
 	{
 		GBool isPrinting = (d->opts & Printing) ? gTrue : gFalse;
+		GBool showAnnotations = (d->opts & HideAnnotations) ? gFalse : gTrue;
 		foreach(int page, d->pageList)
 		{
-			d->document->doc->displayPage(psOut, page, d->hDPI, d->vDPI, d->rotate, gFalse, gTrue, isPrinting);
+			d->document->doc->displayPage(psOut,
+			                              page,
+			                              d->hDPI,
+			                              d->vDPI,
+			                              d->rotate,
+			                              gFalse,
+			                              gTrue,
+			                              isPrinting,
+			                              NULL,
+			                              NULL,
+			                              annotDisplayDecideCbk,
+			                              &showAnnotations);
 			if (d->pageConvertedCallback)
 				(*d->pageConvertedCallback)(page, d->pageConvertedPayload);
 		}
diff --git a/qt4/src/poppler-qt4.h b/qt4/src/poppler-qt4.h
index 025ee8b..84837c8 100644
--- a/qt4/src/poppler-qt4.h
+++ b/qt4/src/poppler-qt4.h
@@ -1450,7 +1450,8 @@ height = dummy.height();
                 Printing = 0x00000001,              ///< The PS is generated for printing purposes
                 StrictMargins = 0x00000002,
                 ForceRasterization = 0x00000004,
-                PrintToEPS = 0x00000008             ///< Output EPS instead of PS \since 0.20
+                PrintToEPS = 0x00000008,            ///< Output EPS instead of PS \since 0.20
+                HideAnnotations = 0x00000010        ///< Don't print annotations \since 0.20
             };
             Q_DECLARE_FLAGS( PSOptions, PSOption )
 
commit e50993b3b47a759c93ccdeeaef289d6985b05bb1
Author: Fabio D'Urso <fabiodurso at hotmail.it>
Date:   Thu Mar 22 19:58:12 2012 +0100

    qt4: DOM annotation store - Black color is different than invalid color

diff --git a/qt4/src/poppler-annotation.cc b/qt4/src/poppler-annotation.cc
index 5a0ac48..549fe23 100644
--- a/qt4/src/poppler-annotation.cc
+++ b/qt4/src/poppler-annotation.cc
@@ -912,7 +912,7 @@ void Annotation::storeBaseAnnotationProperties( QDomNode & annNode, QDomDocument
     // store -other- attributes
     if ( flags() )
         e.setAttribute( "flags", flags() );
-    if ( s.color().isValid() && s.color() != Qt::black )
+    if ( s.color().isValid() )
         e.setAttribute( "color", s.color().name() );
     if ( s.opacity() != 1.0 )
         e.setAttribute( "opacity", QString::number( s.opacity() ) );
commit 4739a6a02097f110c37defdfa616351459902806
Author: Fabio D'Urso <fabiodurso at hotmail.it>
Date:   Mon Mar 19 19:17:33 2012 +0100

    qt4: Annotation removal

diff --git a/qt4/src/poppler-annotation-private.h b/qt4/src/poppler-annotation-private.h
index 1121b32..ea4a88c 100644
--- a/qt4/src/poppler-annotation-private.h
+++ b/qt4/src/poppler-annotation-private.h
@@ -94,6 +94,9 @@ class AnnotationPrivate : public QSharedData
         /* Add given annotation to given page */
         static void addAnnotationToPage(::Page *pdfPage, DocumentData *doc, const Annotation * ann);
 
+        /* Remove annotation from page and destroy ann */
+        static void removeAnnotationFromPage(::Page *pdfPage, const Annotation * ann);
+
         Ref pdfObjectReference() const;
 };
 
diff --git a/qt4/src/poppler-annotation.cc b/qt4/src/poppler-annotation.cc
index 360f949..5a0ac48 100644
--- a/qt4/src/poppler-annotation.cc
+++ b/qt4/src/poppler-annotation.cc
@@ -487,6 +487,35 @@ void AnnotationPrivate::addAnnotationToPage(::Page *pdfPage, DocumentData *doc,
     pdfPage->addAnnot(nativeAnnot);
 }
 
+void AnnotationPrivate::removeAnnotationFromPage(::Page *pdfPage, const Annotation * ann)
+{
+    if (ann->d_ptr->pdfAnnot == 0)
+    {
+        error(errIO, -1, "Annotation is not tied");
+        return;
+    }
+
+    if (ann->d_ptr->pdfPage != pdfPage)
+    {
+        error(errIO, -1, "Annotation doesn't belong to the specified page");
+        return;
+    }
+
+    // Remove popup window
+    AnnotMarkup *markupann = dynamic_cast<AnnotMarkup*>(ann->d_ptr->pdfAnnot);
+    if (markupann && markupann->getPopup())
+        pdfPage->removeAnnot(markupann->getPopup());
+
+    // Remove appearance streams (if any)
+    ann->d_ptr->pdfAnnot->invalidateAppearance();
+
+    // Remove annotation
+    pdfPage->removeAnnot(ann->d_ptr->pdfAnnot);
+
+    // Destroy object
+    delete ann;
+}
+
 class Annotation::Style::Private : public QSharedData
 {
   public:
diff --git a/qt4/src/poppler-page.cc b/qt4/src/poppler-page.cc
index e4a5f8b..6a16d03 100644
--- a/qt4/src/poppler-page.cc
+++ b/qt4/src/poppler-page.cc
@@ -581,6 +581,11 @@ void Page::addAnnotation( const Annotation *ann )
   AnnotationPrivate::addAnnotationToPage(m_page->page, m_page->parentDoc, ann);
 }
 
+void Page::removeAnnotation( const Annotation *ann )
+{
+  AnnotationPrivate::removeAnnotationFromPage(m_page->page, ann);
+}
+
 QList<FormField*> Page::formFields() const
 {
   QList<FormField*> fields;
diff --git a/qt4/src/poppler-qt4.h b/qt4/src/poppler-qt4.h
index 0fdfdb7..025ee8b 100644
--- a/qt4/src/poppler-qt4.h
+++ b/qt4/src/poppler-qt4.h
@@ -695,6 +695,14 @@ delete it;
 	void addAnnotation( const Annotation *ann );
 
 	/**
+	 Removes an annotation from the page and destroys the annotation object
+
+	 \note There mustn't be other Annotation objects pointing this annotation
+	 \since 0.20
+	*/
+	void removeAnnotation( const Annotation *ann );
+
+	/**
 	 Returns the form fields on the page
 	 The caller gets the ownership of the returned objects.
 
commit 25a64d69aaab61c8cf944107e649e19920244a2b
Author: Fabio D'Urso <fabiodurso at hotmail.it>
Date:   Tue Mar 20 01:46:07 2012 +0100

    qt4: TextAnnotation write support + basic textFont getter
    
    Also makes inplaceText a synoym for contents

diff --git a/qt4/src/poppler-annotation.cc b/qt4/src/poppler-annotation.cc
index 56f00e4..360f949 100644
--- a/qt4/src/poppler-annotation.cc
+++ b/qt4/src/poppler-annotation.cc
@@ -22,6 +22,7 @@
  */
 
 // qt/kde includes
+#include <QtCore/QRegExp>
 #include <QtCore/QtAlgorithms>
 #include <QtXml/QDomElement>
 #include <QtGui/QColor>
@@ -62,9 +63,8 @@ Annotation * AnnotationUtils::createAnnotation( const QDomElement & annElement )
     int typeNumber = annElement.attribute( "type" ).toInt();
     switch ( typeNumber )
     {
-        // Some annot types are commented because their creation is temporarly disabled
         case Annotation::AText:
-            //annotation = new TextAnnotation( annElement );
+            annotation = new TextAnnotation( annElement );
             break;
         case Annotation::ALine:
             annotation = new LineAnnotation( annElement );
@@ -1518,9 +1518,11 @@ class TextAnnotationPrivate : public AnnotationPrivate
         QString textIcon;
         QFont textFont;
         int inplaceAlign; // 0:left, 1:center, 2:right
-        QString inplaceText;  // overrides contents
         QVector<QPointF> inplaceCallout;
         TextAnnotation::InplaceIntent inplaceIntent;
+
+        // Helper
+        static GooString * toAppearanceString(const QFont &font);
 };
 
 TextAnnotationPrivate::TextAnnotationPrivate()
@@ -1535,9 +1537,45 @@ Annotation * TextAnnotationPrivate::makeAlias()
     return new TextAnnotation(*this);
 }
 
+GooString * TextAnnotationPrivate::toAppearanceString(const QFont &font)
+{
+    GooString * s = GooString::format("/Invalid_font {0:d} Tf", font.pointSize());
+    // TODO: Font family, style (bold, italic, ...) and pointSize as float
+    return s;
+}
+
 Annot* TextAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc)
 {
-    return 0; // Not implemented
+    // Setters are defined in the public class
+    TextAnnotation *q = static_cast<TextAnnotation*>( makeAlias() );
+
+    // Set page and contents
+    pdfPage = destPage;
+    parentDoc = doc;
+
+    // Set pdfAnnot
+    PDFRectangle rect = toPdfRectangle(boundary);
+    if (textType == TextAnnotation::Linked)
+    {
+        pdfAnnot = new AnnotText(destPage->getDoc(), &rect);
+    }
+    else
+    {
+        GooString * da = toAppearanceString(textFont);
+        pdfAnnot = new AnnotFreeText(destPage->getDoc(), &rect, da);
+        delete da;
+    }
+
+    // Set properties
+    flushBaseAnnotationProperties();
+    q->setTextIcon(textIcon);
+    q->setInplaceAlign(inplaceAlign);
+    q->setCalloutPoints(inplaceCallout);
+    q->setInplaceIntent(inplaceIntent);
+
+    delete q;
+
+    return pdfAnnot;
 }
 
 TextAnnotation::TextAnnotation( TextAnnotation::TextType type )
@@ -1710,7 +1748,13 @@ void TextAnnotation::setTextIcon( const QString &icon )
         return;
     }
 
-    // TODO: Set pdfAnnot
+    if (d->pdfAnnot->getType() == Annot::typeText)
+    {
+        AnnotText * textann = static_cast<AnnotText*>(d->pdfAnnot);
+        QByteArray encoded = icon.toLatin1();
+        GooString s(encoded.constData());
+        textann->setIcon(&s);
+    }
 }
 
 QFont TextAnnotation::textFont() const
@@ -1720,7 +1764,24 @@ QFont TextAnnotation::textFont() const
     if (!d->pdfAnnot)
         return d->textFont;
 
-    return QFont(); // TODO: AnnotFreeText::getAppearanceString
+    QFont font;
+
+    if (d->pdfAnnot->getType() == Annot::typeFreeText)
+    {
+        const AnnotFreeText * ftextann = static_cast<const AnnotFreeText*>(d->pdfAnnot);
+        const GooString * da = ftextann->getAppearanceString();
+        if (da)
+        {
+            // At the moment, only font size is parsed
+            QString style = QString::fromLatin1( da->getCString() );
+            QRegExp rx("(\\d+)(\\.\\d*)? Tf");
+            if (rx.indexIn(style) != -1)
+                font.setPointSize( rx.cap(1).toInt() );
+            // TODO: Other properties
+        }
+    }
+
+    return font;
 }
 
 void TextAnnotation::setTextFont( const QFont &font )
@@ -1733,7 +1794,13 @@ void TextAnnotation::setTextFont( const QFont &font )
         return;
     }
 
-    // TODO: Set pdfAnnot
+    if (d->pdfAnnot->getType() != Annot::typeFreeText)
+        return;
+
+    AnnotFreeText * ftextann = static_cast<AnnotFreeText*>(d->pdfAnnot);
+    GooString * da = TextAnnotationPrivate::toAppearanceString(font);
+    ftextann->setAppearanceString(da);
+    delete da;
 }
 
 int TextAnnotation::inplaceAlign() const
@@ -1762,40 +1829,21 @@ void TextAnnotation::setInplaceAlign( int align )
         return;
     }
 
-    // TODO: Set pdfAnnot
-}
-
-QString TextAnnotation::inplaceText() const
-{
-    Q_D( const TextAnnotation );
-
-    if (!d->pdfAnnot)
-        return d->inplaceText;
-
     if (d->pdfAnnot->getType() == Annot::typeFreeText)
     {
-        const AnnotFreeText * ftextann = static_cast<const AnnotFreeText*>(d->pdfAnnot);
-        QString tmpstring;
-        GooString *styleString = ftextann->getStyleString();
-
-        if (styleString)
-            return UnicodeParsedString( styleString );
+        AnnotFreeText * ftextann = static_cast<AnnotFreeText*>(d->pdfAnnot);
+        ftextann->setQuadding((AnnotFreeText::AnnotFreeTextQuadding)align);
     }
+}
 
-    return QString();
+QString TextAnnotation::inplaceText() const
+{
+    return contents();
 }
 
 void TextAnnotation::setInplaceText( const QString &text )
 {
-    Q_D( TextAnnotation );
-
-    if (!d->pdfAnnot)
-    {
-        d->inplaceText = text;
-        return;
-    }
-
-    // TODO: Set pdfAnnot
+    setContents(text);
 }
 
 QPointF TextAnnotation::calloutPoint( int id ) const
@@ -1844,7 +1892,44 @@ void TextAnnotation::setCalloutPoints( const QVector<QPointF> &points )
         return;
     }
 
-    // TODO: Set pdfAnnot
+    if (d->pdfAnnot->getType() != Annot::typeFreeText)
+        return;
+
+    AnnotFreeText * ftextann = static_cast<AnnotFreeText*>(d->pdfAnnot);
+    const int count = points.size();
+
+    if (count == 0)
+    {
+        ftextann->setCalloutLine(0);
+        return;
+    }
+
+    if (count != 2 && count != 3)
+    {
+        error(errSyntaxError, -1, "Expected zero, two or three points for callout");
+        return;
+    }
+
+    AnnotCalloutLine *callout;
+    double x1, y1, x2, y2;
+    double MTX[6];
+    d->fillMTX(MTX);
+
+    XPDFReader::invTransform( MTX, points[0], x1, y1 );
+    XPDFReader::invTransform( MTX, points[1], x2, y2 );
+    if (count == 3)
+    {
+        double x3, y3;
+        XPDFReader::invTransform( MTX, points[2], x3, y3 );
+        callout = new AnnotCalloutMultiLine(x1, y1, x2, y2, x3, y3);
+    }
+    else
+    {
+        callout = new AnnotCalloutLine(x1, y1, x2, y2);
+    }
+
+    ftextann->setCalloutLine(callout);
+    delete callout;
 }
 
 TextAnnotation::InplaceIntent TextAnnotation::inplaceIntent() const
@@ -1873,7 +1958,11 @@ void TextAnnotation::setInplaceIntent( TextAnnotation::InplaceIntent intent )
         return;
     }
 
-    // TODO: Set pdfAnnot
+    if (d->pdfAnnot->getType() == Annot::typeFreeText)
+    {
+        AnnotFreeText * ftextann = static_cast<AnnotFreeText*>(d->pdfAnnot);
+        ftextann->setIntent((AnnotFreeText::AnnotFreeTextIntent)intent);
+    }
 }
 
 
commit a31a8118ba07aa7f90c69130476fb7d86f8614ad
Author: Fabio D'Urso <fabiodurso at hotmail.it>
Date:   Sun Mar 11 23:57:51 2012 +0100

    qt4: GeomAnnotation, InkAnnotation and CaretAnnotation write support

diff --git a/qt4/src/poppler-annotation.cc b/qt4/src/poppler-annotation.cc
index a93a291..56f00e4 100644
--- a/qt4/src/poppler-annotation.cc
+++ b/qt4/src/poppler-annotation.cc
@@ -70,7 +70,7 @@ Annotation * AnnotationUtils::createAnnotation( const QDomElement & annElement )
             annotation = new LineAnnotation( annElement );
             break;
         case Annotation::AGeom:
-            //annotation = new GeomAnnotation( annElement );
+            annotation = new GeomAnnotation( annElement );
             break;
         case Annotation::AHighlight:
             annotation = new HighlightAnnotation( annElement );
@@ -79,10 +79,10 @@ Annotation * AnnotationUtils::createAnnotation( const QDomElement & annElement )
             annotation = new StampAnnotation( annElement );
             break;
         case Annotation::AInk:
-            //annotation = new InkAnnotation( annElement );
+            annotation = new InkAnnotation( annElement );
             break;
         case Annotation::ACaret:
-            //annotation = new CaretAnnotation( annElement );
+            annotation = new CaretAnnotation( annElement );
             break;
     }
 
@@ -2510,7 +2510,29 @@ Annotation * GeomAnnotationPrivate::makeAlias()
 
 Annot* GeomAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc)
 {
-    return 0; // Not implemented
+    // Setters are defined in the public class
+    GeomAnnotation *q = static_cast<GeomAnnotation*>( makeAlias() );
+
+    // Set page and document
+    pdfPage = destPage;
+    parentDoc = doc;
+
+    Annot::AnnotSubtype type;
+    if (geomType == GeomAnnotation::InscribedSquare)
+        type = Annot::typeSquare;
+    else // GeomAnnotation::InscribedCircle
+        type = Annot::typeCircle;
+
+    // Set pdfAnnot
+    PDFRectangle rect = toPdfRectangle(boundary);
+    pdfAnnot = new AnnotGeometry(destPage->getDoc(), &rect, type);
+
+    // Set properties
+    flushBaseAnnotationProperties();
+    q->setGeomInnerColor(geomInnerColor);
+
+    delete q;
+    return pdfAnnot;
 }
 
 GeomAnnotation::GeomAnnotation()
@@ -2592,7 +2614,11 @@ void GeomAnnotation::setGeomType( GeomAnnotation::GeomType type )
         return;
     }
 
-    // TODO: Set pdfAnnot
+    AnnotGeometry * geomann = static_cast<AnnotGeometry*>(d->pdfAnnot);
+    if (type == GeomAnnotation::InscribedSquare)
+        geomann->setType(Annot::typeSquare);
+    else // GeomAnnotation::InscribedCircle
+        geomann->setType(Annot::typeCircle);
 }
 
 QColor GeomAnnotation::geomInnerColor() const
@@ -2616,7 +2642,8 @@ void GeomAnnotation::setGeomInnerColor( const QColor &color )
         return;
     }
 
-    // TODO: Set pdfAnnot
+    AnnotGeometry * geomann = static_cast<AnnotGeometry*>(d->pdfAnnot);
+    geomann->setInteriorColor(convertQColor( color ));
 }
 
 
@@ -3038,6 +3065,9 @@ class InkAnnotationPrivate : public AnnotationPrivate
 
         // data fields
         QList< QLinkedList<QPointF> > inkPaths;
+
+        // helper
+        AnnotPath **toAnnotPaths(const QList< QLinkedList<QPointF> > &inkPaths);
 };
 
 InkAnnotationPrivate::InkAnnotationPrivate()
@@ -3050,9 +3080,38 @@ Annotation * InkAnnotationPrivate::makeAlias()
     return new InkAnnotation(*this);
 }
 
+// Note: Caller is required to delete array elements and the array itself after use
+AnnotPath **InkAnnotationPrivate::toAnnotPaths(const QList< QLinkedList<QPointF> > &inkPaths)
+{
+    const int pathsNumber = inkPaths.size();
+    AnnotPath **res = new AnnotPath*[pathsNumber];
+    for (int i = 0; i < pathsNumber; ++i)
+        res[i] = toAnnotPath( inkPaths[i] );
+    return res;
+}
+
 Annot* InkAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc)
 {
-    return 0; // Not implemented
+    // 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;
+
+    // Set properties
+    flushBaseAnnotationProperties();
+
+    inkPaths.clear(); // Free up memory
+
+    return pdfAnnot;
 }
 
 InkAnnotation::InkAnnotation()
@@ -3198,7 +3257,14 @@ void InkAnnotation::setInkPaths( const QList< QLinkedList<QPointF> > &paths )
         return;
     }
 
-    // TODO: Set pdfAnnot
+    AnnotInk * inkann = static_cast<AnnotInk*>(d->pdfAnnot);
+    AnnotPath **annotpaths = d->toAnnotPaths(paths);
+    const int pathsNumber = paths.size();
+    inkann->setInkList(annotpaths, pathsNumber);
+
+    for (int i = 0; i < pathsNumber; ++i)
+        delete annotpaths[i];
+    delete[] annotpaths;
 }
 
 
@@ -3570,7 +3636,23 @@ Annotation * CaretAnnotationPrivate::makeAlias()
 
 Annot* CaretAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc)
 {
-    return 0; // Not implemented
+    // Setters are defined in the public class
+    CaretAnnotation *q = static_cast<CaretAnnotation*>( makeAlias() );
+
+    // Set page and document
+    pdfPage = destPage;
+    parentDoc = doc;
+
+    // Set pdfAnnot
+    PDFRectangle rect = toPdfRectangle(boundary);
+    pdfAnnot = new AnnotCaret(destPage->getDoc(), &rect);
+
+    // Set properties
+    flushBaseAnnotationProperties();
+    q->setCaretSymbol(symbol);
+
+    delete q;
+    return pdfAnnot;
 }
 
 CaretAnnotation::CaretAnnotation()
@@ -3648,7 +3730,8 @@ void CaretAnnotation::setCaretSymbol( CaretAnnotation::CaretSymbol symbol )
         return;
     }
 
-    // TODO: Set pdfAnnot
+    AnnotCaret * caretann = static_cast<AnnotCaret *>(d->pdfAnnot);
+    caretann->setSymbol((AnnotCaret::AnnotCaretSymbol)symbol);
 }
 
 /** FileAttachmentAnnotation [Annotation] */
diff --git a/qt4/src/poppler-annotation.h b/qt4/src/poppler-annotation.h
index dd64850..779ce2d 100644
--- a/qt4/src/poppler-annotation.h
+++ b/qt4/src/poppler-annotation.h
@@ -456,6 +456,7 @@ class POPPLER_QT4_EXPORT GeomAnnotation : public Annotation
   friend class AnnotationPrivate;
 
   public:
+    GeomAnnotation();
     virtual ~GeomAnnotation();
     virtual SubType subType() const;
 
@@ -469,7 +470,6 @@ class POPPLER_QT4_EXPORT GeomAnnotation : public Annotation
     void setGeomInnerColor( const QColor &color );
 
   private:
-    GeomAnnotation();
     GeomAnnotation( const QDomNode &node );
     GeomAnnotation( GeomAnnotationPrivate &dd );
     virtual void store( QDomNode &parentNode, QDomDocument &document ) const;
@@ -606,6 +606,7 @@ class POPPLER_QT4_EXPORT InkAnnotation : public Annotation
   friend class AnnotationPrivate;
 
   public:
+    InkAnnotation();
     virtual ~InkAnnotation();
     virtual SubType subType() const;
 
@@ -613,7 +614,6 @@ class POPPLER_QT4_EXPORT InkAnnotation : public Annotation
     void setInkPaths( const QList< QLinkedList<QPointF> > &paths );
 
   private:
-    InkAnnotation();
     InkAnnotation( const QDomNode &node );
     virtual void store( QDomNode &parentNode, QDomDocument &document ) const;
     InkAnnotation(InkAnnotationPrivate &dd);
@@ -662,6 +662,7 @@ class POPPLER_QT4_EXPORT CaretAnnotation : public Annotation
   friend class AnnotationPrivate;
 
   public:
+    CaretAnnotation();
     virtual ~CaretAnnotation();
     virtual SubType subType() const;
 
@@ -674,7 +675,6 @@ class POPPLER_QT4_EXPORT CaretAnnotation : public Annotation
     void setCaretSymbol( CaretSymbol symbol );
 
   private:
-    CaretAnnotation();
     CaretAnnotation( const QDomNode &node );
     CaretAnnotation( CaretAnnotationPrivate &dd );
     virtual void store( QDomNode &parentNode, QDomDocument &document ) const;
commit e4052b52002447772e24571fd13f0f22fd2bfb16
Author: Fabio D'Urso <fabiodurso at hotmail.it>
Date:   Sat Mar 10 17:48:56 2012 +0100

    qt4: HighlightAnnotation and StampAnnotation write support

diff --git a/qt4/src/poppler-annotation.cc b/qt4/src/poppler-annotation.cc
index bcc0ffa..a93a291 100644
--- a/qt4/src/poppler-annotation.cc
+++ b/qt4/src/poppler-annotation.cc
@@ -73,10 +73,10 @@ Annotation * AnnotationUtils::createAnnotation( const QDomElement & annElement )
             //annotation = new GeomAnnotation( annElement );
             break;
         case Annotation::AHighlight:
-            //annotation = new HighlightAnnotation( annElement );
+            annotation = new HighlightAnnotation( annElement );
             break;
         case Annotation::AStamp:
-            //annotation = new StampAnnotation( annElement );
+            annotation = new StampAnnotation( annElement );
             break;
         case Annotation::AInk:
             //annotation = new InkAnnotation( annElement );
@@ -2633,7 +2633,9 @@ class HighlightAnnotationPrivate : public AnnotationPrivate
         QList< HighlightAnnotation::Quad > highlightQuads; // not empty
 
         // helpers
+        static Annot::AnnotSubtype toAnnotSubType( HighlightAnnotation::HighlightType type );
         QList< HighlightAnnotation::Quad > fromQuadrilaterals(AnnotQuadrilaterals *quads) const;
+        AnnotQuadrilaterals * toQuadrilaterals(const QList< HighlightAnnotation::Quad > &quads) const;
 };
 
 HighlightAnnotationPrivate::HighlightAnnotationPrivate()
@@ -2646,6 +2648,21 @@ Annotation * HighlightAnnotationPrivate::makeAlias()
     return new HighlightAnnotation(*this);
 }
 
+Annot::AnnotSubtype HighlightAnnotationPrivate::toAnnotSubType( HighlightAnnotation::HighlightType type )
+{
+    switch (type)
+    {
+        default: // HighlightAnnotation::Highlight:
+            return Annot::typeHighlight;
+        case HighlightAnnotation::Underline:
+            return Annot::typeUnderline;
+        case HighlightAnnotation::Squiggly:
+            return Annot::typeSquiggly;
+        case HighlightAnnotation::StrikeOut:
+            return Annot::typeStrikeOut;
+    }
+}
+
 QList< HighlightAnnotation::Quad > HighlightAnnotationPrivate::fromQuadrilaterals(AnnotQuadrilaterals *hlquads) const
 {
     QList< HighlightAnnotation::Quad > quads;
@@ -2679,9 +2696,49 @@ QList< HighlightAnnotation::Quad > HighlightAnnotationPrivate::fromQuadrilateral
     return quads;
 }
 
+AnnotQuadrilaterals * HighlightAnnotationPrivate::toQuadrilaterals(const QList< HighlightAnnotation::Quad > &quads) const
+{
+    const int count = quads.size();
+    AnnotQuadrilaterals::AnnotQuadrilateral **ac =
+        (AnnotQuadrilaterals::AnnotQuadrilateral**)
+            gmallocn( count, sizeof(AnnotQuadrilaterals::AnnotQuadrilateral*) );
+
+    double MTX[6];
+    fillMTX(MTX);
+
+    int pos = 0;
+    foreach (const HighlightAnnotation::Quad &q, quads)
+    {
+        double x1, y1, x2, y2, x3, y3, x4, y4;
+        XPDFReader::invTransform( MTX, q.points[0], x1, y1 );
+        XPDFReader::invTransform( MTX, q.points[1], x2, y2 );
+        // Swap points 3 and 4 (see HighlightAnnotationPrivate::fromQuadrilaterals)
+        XPDFReader::invTransform( MTX, q.points[3], x3, y3 );
+        XPDFReader::invTransform( MTX, q.points[2], x4, y4 );
+        ac[pos++] = new AnnotQuadrilaterals::AnnotQuadrilateral(x1, y1, x2, y2, x3, y3, x4, y4);
+    }
+
+    return new AnnotQuadrilaterals(ac, count);
+}
+
 Annot* HighlightAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc)
 {
-    return 0; // Not implemented
+    // 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;
+
+    // Set properties
+    flushBaseAnnotationProperties();
+
+    highlightQuads.clear(); // Free up memory
+
+    return pdfAnnot;
 }
 
 HighlightAnnotation::HighlightAnnotation()
@@ -2815,7 +2872,8 @@ void HighlightAnnotation::setHighlightType( HighlightAnnotation::HighlightType t
         return;
     }
 
-    // TODO: Set pdfAnnot
+    AnnotTextMarkup * hlann = static_cast<AnnotTextMarkup*>(d->pdfAnnot);
+    hlann->setType(HighlightAnnotationPrivate::toAnnotSubType( type ));
 }
 
 QList< HighlightAnnotation::Quad > HighlightAnnotation::highlightQuads() const
@@ -2839,7 +2897,10 @@ void HighlightAnnotation::setHighlightQuads( const QList< HighlightAnnotation::Q
         return;
     }
 
-    // TODO: Set pdfAnnot
+    AnnotTextMarkup * hlann = static_cast<AnnotTextMarkup*>(d->pdfAnnot);
+    AnnotQuadrilaterals * quadrilaterals = d->toQuadrilaterals(quads);
+    hlann->setQuadrilaterals(quadrilaterals);
+    delete quadrilaterals;
 }
 
 
@@ -2867,7 +2928,25 @@ Annotation * StampAnnotationPrivate::makeAlias()
 
 Annot* StampAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc)
 {
-    return 0; // Not implemented
+    StampAnnotation *q = static_cast<StampAnnotation*>( makeAlias() );
+
+    // Set page and document
+    pdfPage = destPage;
+    parentDoc = doc;
+
+    // Set pdfAnnot
+    PDFRectangle rect = toPdfRectangle(boundary);
+    pdfAnnot = new AnnotStamp(destPage->getDoc(), &rect);
+
+    // Set properties
+    flushBaseAnnotationProperties();
+    q->setStampIconName(stampIconName);
+
+    delete q;
+
+    stampIconName.clear(); // Free up memory
+
+    return pdfAnnot;
 }
 
 StampAnnotation::StampAnnotation()
@@ -2943,7 +3022,10 @@ void StampAnnotation::setStampIconName( const QString &name )
         return;
     }
 
-    // TODO: Set pdfAnnot
+    AnnotStamp * stampann = static_cast<AnnotStamp*>(d->pdfAnnot);
+    QByteArray encoded = name.toLatin1();
+    GooString s(encoded.constData());
+    stampann->setIcon(&s);
 }
 
 /** InkAnnotation [Annotation] */
diff --git a/qt4/src/poppler-annotation.h b/qt4/src/poppler-annotation.h
index 64342bf..dd64850 100644
--- a/qt4/src/poppler-annotation.h
+++ b/qt4/src/poppler-annotation.h
@@ -488,6 +488,7 @@ class POPPLER_QT4_EXPORT HighlightAnnotation : public Annotation
   friend class AnnotationPrivate;
 
   public:
+    HighlightAnnotation();
     virtual ~HighlightAnnotation();
     virtual SubType subType() const;
 
@@ -536,7 +537,6 @@ class POPPLER_QT4_EXPORT HighlightAnnotation : public Annotation
     void setHighlightQuads( const QList< Quad > &quads );
 
   private:
-    HighlightAnnotation();
     HighlightAnnotation( const QDomNode &node );
     HighlightAnnotation( HighlightAnnotationPrivate &dd );
     virtual void store( QDomNode &parentNode, QDomDocument &document ) const;
@@ -555,6 +555,7 @@ class POPPLER_QT4_EXPORT StampAnnotation : public Annotation
   friend class AnnotationPrivate;
 
   public:
+    StampAnnotation();
     virtual ~StampAnnotation();
     virtual SubType subType() const;
 
@@ -587,7 +588,6 @@ class POPPLER_QT4_EXPORT StampAnnotation : public Annotation
     void setStampIconName( const QString &name );
 
   private:
-    StampAnnotation();
     StampAnnotation( const QDomNode &node );
     StampAnnotation( StampAnnotationPrivate &dd );
     virtual void store( QDomNode &parentNode, QDomDocument &document ) const;
commit b5e948b6130cdb04387a8244179337c7904dcd03
Author: Fabio D'Urso <fabiodurso at hotmail.it>
Date:   Wed Mar 14 17:44:50 2012 +0100

    qt4: Annotation insertion and LineAnnotation support
    
    This patch adds Page::addAnnotation to insert new annotations in a page.
    The only annotation type that can be added is LineAnnotation. Support for other
    types will be added in the next patches.

diff --git a/qt4/src/poppler-annotation-private.h b/qt4/src/poppler-annotation-private.h
index 24f5343..1121b32 100644
--- a/qt4/src/poppler-annotation-private.h
+++ b/qt4/src/poppler-annotation-private.h
@@ -21,6 +21,8 @@
 #ifndef _POPPLER_ANNOTATION_PRIVATE_H_
 #define _POPPLER_ANNOTATION_PRIVATE_H_
 
+#include <QtCore/QLinkedList>
+#include <QtCore/QPointF>
 #include <QtCore/QSharedDataPointer>
 
 #include "poppler-annotation.h"
@@ -28,6 +30,7 @@
 #include <Object.h>
 
 class Annot;
+class AnnotPath;
 class Page;
 class PDFRectangle;
 
@@ -69,19 +72,28 @@ class AnnotationPrivate : public QSharedData
          * the specified Annot object. All cached values are discarded */
         void tieToNativeAnnot(Annot *ann, ::Page *page, DocumentData *doc);
 
+        /* Creates a new Annot object on the specified page, flushes current
+         * values to that object and ties this Annotation to that object */
+        virtual Annot* createNativeAnnot(::Page *destPage, DocumentData *doc) = 0;
+
         /* Inited to 0 (i.e. untied annotation) */
         Annot *pdfAnnot;
         ::Page *pdfPage;
         DocumentData * parentDoc;
 
         /* The following helpers only work if pdfPage is set */
+        void flushBaseAnnotationProperties();
         void fillMTX(double MTX[6]) const;
         QRectF fromPdfRectangle(const PDFRectangle &r) const;
         PDFRectangle toPdfRectangle(const QRectF &r) const;
+        AnnotPath * toAnnotPath(const QLinkedList<QPointF> &l) const;
 
         /* Scan page for annotations, parentId=0 searches for root annotations */
         static QList<Annotation*> findAnnotations(::Page *pdfPage, DocumentData *doc, int parentId = 0);
 
+        /* Add given annotation to given page */
+        static void addAnnotationToPage(::Page *pdfPage, DocumentData *doc, const Annotation * ann);
+
         Ref pdfObjectReference() const;
 };
 
diff --git a/qt4/src/poppler-annotation.cc b/qt4/src/poppler-annotation.cc
index 3e7b361..bcc0ffa 100644
--- a/qt4/src/poppler-annotation.cc
+++ b/qt4/src/poppler-annotation.cc
@@ -67,7 +67,7 @@ Annotation * AnnotationUtils::createAnnotation( const QDomElement & annElement )
             //annotation = new TextAnnotation( annElement );
             break;
         case Annotation::ALine:
-            //annotation = new LineAnnotation( annElement );
+            annotation = new LineAnnotation( annElement );
             break;
         case Annotation::AGeom:
             //annotation = new GeomAnnotation( annElement );
@@ -151,6 +151,42 @@ void AnnotationPrivate::tieToNativeAnnot(Annot *ann, ::Page *page, Poppler::Docu
     pdfAnnot->incRefCnt();
 }
 
+/* This method is called when a new annotation is created, after pdfAnnot and
+ * pdfPage have been set */
+void AnnotationPrivate::flushBaseAnnotationProperties()
+{
+    Q_ASSERT ( pdfPage );
+
+    Annotation *q = makeAlias(); // Setters are defined in the public class
+
+    // Since pdfAnnot has been set, this calls will write in the Annot object
+    q->setAuthor(author);
+    q->setContents(contents);
+    q->setUniqueName(uniqueName);
+    q->setModificationDate(modDate);
+    q->setCreationDate(creationDate);
+    q->setFlags(flags);
+    //q->setBoundary(boundary); -- already set by subclass-specific code
+    q->setStyle(style);
+    q->setPopup(popup);
+
+    // Flush revisions
+    foreach (Annotation *r, revisions)
+    {
+        // addRevision creates a native Annot because pdfAnnot is set
+        q->addRevision(r, r->d_ptr->revisionScope, r->d_ptr->revisionType);
+        delete r; // Object is no longer needed
+    }
+
+    delete q;
+
+    // Clear some members to save memory
+    author.clear();
+    contents.clear();
+    uniqueName.clear();
+    revisions.clear();
+}
+
 void AnnotationPrivate::fillMTX(double MTX[6]) const
 {
     Q_ASSERT ( pdfPage );
@@ -223,6 +259,25 @@ PDFRectangle AnnotationPrivate::toPdfRectangle(const QRectF &r) const
     return PDFRectangle(tl_x, tl_y, br_x, br_y);
 }
 
+AnnotPath * AnnotationPrivate::toAnnotPath(const QLinkedList<QPointF> &list) const
+{
+    const int count = list.size();
+    AnnotCoord **ac = (AnnotCoord **) gmallocn(count, sizeof(AnnotCoord*));
+
+    double MTX[6];
+    fillMTX(MTX);
+
+    int pos = 0;
+    foreach (const QPointF &p, list)
+    {
+        double x, y;
+        XPDFReader::invTransform( MTX, p, x, y );
+        ac[pos++] = new AnnotCoord(x, y);
+    }
+
+    return new AnnotPath(ac, count);
+}
+
 QList<Annotation*> AnnotationPrivate::findAnnotations(::Page *pdfPage, DocumentData *doc, int parentID)
 {
     Annots* annots = pdfPage->getAnnots();
@@ -417,6 +472,21 @@ Ref AnnotationPrivate::pdfObjectReference() const
     return pdfAnnot->getRef();
 }
 
+void AnnotationPrivate::addAnnotationToPage(::Page *pdfPage, DocumentData *doc, const Annotation * ann)
+{
+    if (ann->d_ptr->pdfAnnot != 0)
+    {
+        error(errIO, -1, "Annotation is already tied");
+        return;
+    }
+
+    // Unimplemented annotations can't be created by the user because their ctor
+    // is private. Therefore, createNativeAnnot will never return 0
+    Annot *nativeAnnot = ann->d_ptr->createNativeAnnot(pdfPage, doc);
+    Q_ASSERT(nativeAnnot);
+    pdfPage->addAnnot(nativeAnnot);
+}
+
 class Annotation::Style::Private : public QSharedData
 {
   public:
@@ -1441,6 +1511,7 @@ class TextAnnotationPrivate : public AnnotationPrivate
     public:
         TextAnnotationPrivate();
         Annotation * makeAlias();
+        Annot* createNativeAnnot(::Page *destPage, DocumentData *doc);
 
         // data fields
         TextAnnotation::TextType textType;
@@ -1464,6 +1535,11 @@ Annotation * TextAnnotationPrivate::makeAlias()
     return new TextAnnotation(*this);
 }
 
+Annot* TextAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc)
+{
+    return 0; // Not implemented
+}
+
 TextAnnotation::TextAnnotation( TextAnnotation::TextType type )
     : Annotation( *new TextAnnotationPrivate() )
 {
@@ -1807,6 +1883,7 @@ class LineAnnotationPrivate : public AnnotationPrivate
     public:
         LineAnnotationPrivate();
         Annotation * makeAlias();
+        Annot* createNativeAnnot(::Page *destPage, DocumentData *doc);
 
         // data fields (note uses border for rendering style)
         QLinkedList<QPointF> linePoints;
@@ -1834,6 +1911,47 @@ Annotation * LineAnnotationPrivate::makeAlias()
     return new LineAnnotation(*this);
 }
 
+Annot* LineAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc)
+{
+    // Setters are defined in the public class
+    LineAnnotation *q = static_cast<LineAnnotation*>( makeAlias() );
+
+    // Set page and document
+    pdfPage = destPage;
+    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);
+    }
+    else
+    {
+        pdfAnnot = new AnnotPolygon(doc->doc, &rect,
+                lineClosed ? Annot::typePolygon : Annot::typePolyLine, path );
+    }
+    delete path;
+
+    // Set properties
+    flushBaseAnnotationProperties();
+    q->setLineStartStyle(lineStartStyle);
+    q->setLineEndStyle(lineEndStyle);
+    q->setLineInnerColor(lineInnerColor);
+    q->setLineLeadingForwardPoint(lineLeadingFwdPt);
+    q->setLineLeadingBackPoint(lineLeadingBackPt);
+    q->setLineShowCaption(lineShowCaption);
+    q->setLineIntent(lineIntent);
+
+    delete q;
+
+    linePoints.clear(); // Free up memory
+
+    return pdfAnnot;
+}
+
 LineAnnotation::LineAnnotation( LineAnnotation::LineType type )
     : Annotation( *new LineAnnotationPrivate() )
 {
@@ -2019,7 +2137,28 @@ void LineAnnotation::setLinePoints( const QLinkedList<QPointF> &points )
         return;
     }
 
-    // TODO: Set pdfAnnot
+    if (d->pdfAnnot->getType() == Annot::typeLine)
+    {
+        AnnotLine *lineann = static_cast<AnnotLine*>(d->pdfAnnot);
+        if (points.size() != 2)
+        {
+            error(errSyntaxError, -1, "Expected two points for a straight line");
+            return;
+        }
+        double x1, y1, x2, y2;
+        double MTX[6];
+        d->fillMTX(MTX);
+        XPDFReader::invTransform( MTX, points.first(), x1, y1 );
+        XPDFReader::invTransform( MTX, points.last(), x2, y2 );
+        lineann->setVertices(x1, y1, x2, y2);
+    }
+    else
+    {
+        AnnotPolygon *polyann = static_cast<AnnotPolygon*>(d->pdfAnnot);
+        AnnotPath * p = d->toAnnotPath(points);
+        polyann->setVertices(p);
+        delete p;
+    }
 }
 
 LineAnnotation::TermStyle LineAnnotation::lineStartStyle() const
@@ -2051,7 +2190,16 @@ void LineAnnotation::setLineStartStyle( LineAnnotation::TermStyle style )
         return;
     }
 
-    // TODO: Set pdfAnnot
+    if (d->pdfAnnot->getType() == Annot::typeLine)
+    {
+        AnnotLine *lineann = static_cast<AnnotLine*>(d->pdfAnnot);
+        lineann->setStartEndStyle((AnnotLineEndingStyle)style, lineann->getEndStyle());
+    }
+    else
+    {
+        AnnotPolygon *polyann = static_cast<AnnotPolygon*>(d->pdfAnnot);
+        polyann->setStartEndStyle((AnnotLineEndingStyle)style, polyann->getEndStyle());
+    }
 }
 
 LineAnnotation::TermStyle LineAnnotation::lineEndStyle() const
@@ -2083,7 +2231,16 @@ void LineAnnotation::setLineEndStyle( LineAnnotation::TermStyle style )
         return;
     }
 
-    // TODO: Set pdfAnnot
+    if (d->pdfAnnot->getType() == Annot::typeLine)
+    {
+        AnnotLine *lineann = static_cast<AnnotLine*>(d->pdfAnnot);
+        lineann->setStartEndStyle(lineann->getStartStyle(), (AnnotLineEndingStyle)style);
+    }
+    else
+    {
+        AnnotPolygon *polyann = static_cast<AnnotPolygon*>(d->pdfAnnot);
+        polyann->setStartEndStyle(polyann->getStartStyle(), (AnnotLineEndingStyle)style);
+    }
 }
 
 bool LineAnnotation::isLineClosed() const
@@ -2106,7 +2263,24 @@ void LineAnnotation::setLineClosed( bool closed )
         return;
     }
 
-    // TODO: Set pdfAnnot
+    if (d->pdfAnnot->getType() != Annot::typeLine)
+    {
+        AnnotPolygon *polyann = static_cast<AnnotPolygon*>(d->pdfAnnot);
+
+        // Set new subtype and switch intent if necessary
+        if (closed)
+        {
+            polyann->setType(Annot::typePolygon);
+            if (polyann->getIntent() == AnnotPolygon::polylineDimension)
+                polyann->setIntent( AnnotPolygon::polygonDimension );
+        }
+        else
+        {
+            polyann->setType(Annot::typePolyLine);
+            if (polyann->getIntent() == AnnotPolygon::polygonDimension)
+                polyann->setIntent( AnnotPolygon::polylineDimension );
+        }
+    }
 }
 
 QColor LineAnnotation::lineInnerColor() const
@@ -2142,7 +2316,18 @@ void LineAnnotation::setLineInnerColor( const QColor &color )
         return;
     }
 
-    // TODO: Set pdfAnnot
+    AnnotColor * c = convertQColor(color);
+
+    if (d->pdfAnnot->getType() == Annot::typeLine)
+    {
+        AnnotLine *lineann = static_cast<AnnotLine*>(d->pdfAnnot);
+        lineann->setInteriorColor(c);
+    }
+    else
+    {
+        AnnotPolygon *polyann = static_cast<AnnotPolygon*>(d->pdfAnnot);
+        polyann->setInteriorColor(c);
+    }
 }
 
 double LineAnnotation::lineLeadingForwardPoint() const
@@ -2171,7 +2356,11 @@ void LineAnnotation::setLineLeadingForwardPoint( double point )
         return;
     }
 
-    // TODO: Set pdfAnnot
+    if (d->pdfAnnot->getType() == Annot::typeLine)
+    {
+        AnnotLine *lineann = static_cast<AnnotLine*>(d->pdfAnnot);
+        lineann->setLeaderLineLength(point);
+    }
 }
 
 double LineAnnotation::lineLeadingBackPoint() const
@@ -2200,7 +2389,11 @@ void LineAnnotation::setLineLeadingBackPoint( double point )
         return;
     }
 
-    // TODO: Set pdfAnnot
+    if (d->pdfAnnot->getType() == Annot::typeLine)
+    {
+        AnnotLine *lineann = static_cast<AnnotLine*>(d->pdfAnnot);
+        lineann->setLeaderLineExtension(point);
+    }
 }
 
 bool LineAnnotation::lineShowCaption() const
@@ -2229,7 +2422,11 @@ void LineAnnotation::setLineShowCaption( bool show )
         return;
     }
 
-    // TODO: Set pdfAnnot
+    if (d->pdfAnnot->getType() == Annot::typeLine)
+    {
+        AnnotLine *lineann = static_cast<AnnotLine*>(d->pdfAnnot);
+        lineann->setCaption(show);
+    }
 }
 
 LineAnnotation::LineIntent LineAnnotation::lineIntent() const
@@ -2264,7 +2461,27 @@ void LineAnnotation::setLineIntent( LineAnnotation::LineIntent intent )
         return;
     }
 
-    // TODO: Set pdfAnnot
+    if ( intent == LineAnnotation::Unknown )
+        return; // Do not set (actually, it should clear the property)
+
+    if (d->pdfAnnot->getType() == Annot::typeLine)
+    {
+        AnnotLine * lineann = static_cast<AnnotLine*>(d->pdfAnnot);
+        lineann->setIntent((AnnotLine::AnnotLineIntent)( intent - 1 ));
+    }
+    else
+    {
+        AnnotPolygon * polyann = static_cast<AnnotPolygon*>(d->pdfAnnot);
+        if ( intent == LineAnnotation::PolygonCloud)
+            polyann->setIntent( AnnotPolygon::polygonCloud );
+        else // LineAnnotation::Dimension
+        {
+            if ( d->pdfAnnot->getType() == Annot::typePolygon )
+                polyann->setIntent( AnnotPolygon::polygonDimension );
+            else // Annot::typePolyLine
+                polyann->setIntent( AnnotPolygon::polylineDimension );
+        }
+    }
 }
 
 
@@ -2274,6 +2491,7 @@ class GeomAnnotationPrivate : public AnnotationPrivate
     public:
         GeomAnnotationPrivate();
         Annotation * makeAlias();
+        Annot* createNativeAnnot(::Page *destPage, DocumentData *doc);
 
         // data fields (note uses border for rendering style)
         GeomAnnotation::GeomType geomType;
@@ -2290,6 +2508,11 @@ Annotation * GeomAnnotationPrivate::makeAlias()
     return new GeomAnnotation(*this);
 }
 
+Annot* GeomAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc)
+{
+    return 0; // Not implemented
+}
+
 GeomAnnotation::GeomAnnotation()
     : Annotation( *new GeomAnnotationPrivate() )
 {}
@@ -2403,6 +2626,7 @@ class HighlightAnnotationPrivate : public AnnotationPrivate
     public:
         HighlightAnnotationPrivate();
         Annotation * makeAlias();
+        Annot* createNativeAnnot(::Page *destPage, DocumentData *doc);
 
         // data fields
         HighlightAnnotation::HighlightType highlightType;
@@ -2455,6 +2679,11 @@ QList< HighlightAnnotation::Quad > HighlightAnnotationPrivate::fromQuadrilateral
     return quads;
 }
 
+Annot* HighlightAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc)
+{
+    return 0; // Not implemented
+}
+
 HighlightAnnotation::HighlightAnnotation()
     : Annotation( *new HighlightAnnotationPrivate() )
 {}
@@ -2620,6 +2849,7 @@ class StampAnnotationPrivate : public AnnotationPrivate
     public:
         StampAnnotationPrivate();
         Annotation * makeAlias();
+        Annot* createNativeAnnot(::Page *destPage, DocumentData *doc);
 
         // data fields
         QString stampIconName;
@@ -2635,6 +2865,11 @@ Annotation * StampAnnotationPrivate::makeAlias()
     return new StampAnnotation(*this);
 }
 
+Annot* StampAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc)
+{
+    return 0; // Not implemented
+}
+
 StampAnnotation::StampAnnotation()
     : Annotation( *new StampAnnotationPrivate() )
 {}
@@ -2717,6 +2952,7 @@ class InkAnnotationPrivate : public AnnotationPrivate
     public:
         InkAnnotationPrivate();
         Annotation * makeAlias();
+        Annot* createNativeAnnot(::Page *destPage, DocumentData *doc);
 
         // data fields
         QList< QLinkedList<QPointF> > inkPaths;
@@ -2732,6 +2968,11 @@ Annotation * InkAnnotationPrivate::makeAlias()
     return new InkAnnotation(*this);
 }
 
+Annot* InkAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc)
+{
+    return 0; // Not implemented
+}
+
 InkAnnotation::InkAnnotation()
     : Annotation( *new InkAnnotationPrivate() )
 {}
@@ -2886,6 +3127,7 @@ class LinkAnnotationPrivate : public AnnotationPrivate
         LinkAnnotationPrivate();
         ~LinkAnnotationPrivate();
         Annotation * makeAlias();
+        Annot* createNativeAnnot(::Page *destPage, DocumentData *doc);
 
         // data fields
         Link * linkDestination;
@@ -2908,6 +3150,11 @@ Annotation * LinkAnnotationPrivate::makeAlias()
     return new LinkAnnotation(*this);
 }
 
+Annot* LinkAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc)
+{
+    return 0; // Not implemented
+}
+
 LinkAnnotation::LinkAnnotation()
     : Annotation( *new LinkAnnotationPrivate() )
 {}
@@ -3202,6 +3449,7 @@ class CaretAnnotationPrivate : public AnnotationPrivate
     public:
         CaretAnnotationPrivate();
         Annotation * makeAlias();
+        Annot* createNativeAnnot(::Page *destPage, DocumentData *doc);
 
         // data fields
         CaretAnnotation::CaretSymbol symbol;
@@ -3238,6 +3486,11 @@ Annotation * CaretAnnotationPrivate::makeAlias()
     return new CaretAnnotation(*this);
 }
 
+Annot* CaretAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc)
+{
+    return 0; // Not implemented
+}
+
 CaretAnnotation::CaretAnnotation()
     : Annotation( *new CaretAnnotationPrivate() )
 {
@@ -3323,6 +3576,7 @@ class FileAttachmentAnnotationPrivate : public AnnotationPrivate
         FileAttachmentAnnotationPrivate();
         ~FileAttachmentAnnotationPrivate();
         Annotation * makeAlias();
+        Annot* createNativeAnnot(::Page *destPage, DocumentData *doc);
 
         // data fields
         QString icon;
@@ -3344,6 +3598,11 @@ Annotation * FileAttachmentAnnotationPrivate::makeAlias()
     return new FileAttachmentAnnotation(*this);
 }
 
+Annot* FileAttachmentAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc)
+{
+    return 0; // Not implemented
+}
+
 FileAttachmentAnnotation::FileAttachmentAnnotation()
     : Annotation( *new FileAttachmentAnnotationPrivate() )
 {
@@ -3421,6 +3680,7 @@ class SoundAnnotationPrivate : public AnnotationPrivate
         SoundAnnotationPrivate();
         ~SoundAnnotationPrivate();
         Annotation * makeAlias();
+        Annot* createNativeAnnot(::Page *destPage, DocumentData *doc);
 
         // data fields
         QString icon;
@@ -3442,6 +3702,11 @@ Annotation * SoundAnnotationPrivate::makeAlias()
     return new SoundAnnotation(*this);
 }
 
+Annot* SoundAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc)
+{
+    return 0; // Not implemented
+}
+
 SoundAnnotation::SoundAnnotation()
     : Annotation( *new SoundAnnotationPrivate() )
 {
@@ -3519,6 +3784,7 @@ class MovieAnnotationPrivate : public AnnotationPrivate
         MovieAnnotationPrivate();
         ~MovieAnnotationPrivate();
         Annotation * makeAlias();
+        Annot* createNativeAnnot(::Page *destPage, DocumentData *doc);
 
         // data fields
         MovieObject *movie;
@@ -3540,6 +3806,11 @@ Annotation * MovieAnnotationPrivate::makeAlias()
     return new MovieAnnotation(*this);
 }
 
+Annot* MovieAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc)
+{
+    return 0; // Not implemented
+}
+
 MovieAnnotation::MovieAnnotation()
     : Annotation( *new MovieAnnotationPrivate() )
 {
@@ -3617,6 +3888,7 @@ class ScreenAnnotationPrivate : public AnnotationPrivate
         ScreenAnnotationPrivate();
         ~ScreenAnnotationPrivate();
         Annotation * makeAlias();
+        Annot* createNativeAnnot(::Page *destPage, DocumentData *doc);
 
         // data fields
         LinkRendition *action;
@@ -3642,6 +3914,11 @@ Annotation * ScreenAnnotationPrivate::makeAlias()
     return new ScreenAnnotation(*this);
 }
 
+Annot* ScreenAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc)
+{
+    return 0; // Not implemented
+}
+
 ScreenAnnotation::ScreenAnnotation()
     : Annotation( *new ScreenAnnotationPrivate() )
 {
diff --git a/qt4/src/poppler-annotation.h b/qt4/src/poppler-annotation.h
index 6ab969e..64342bf 100644
--- a/qt4/src/poppler-annotation.h
+++ b/qt4/src/poppler-annotation.h
@@ -400,9 +400,12 @@ class POPPLER_QT4_EXPORT LineAnnotation : public Annotation
                      Butt, ROpenArrow, RClosedArrow, Slash };
     enum LineIntent { Unknown, Arrow, Dimension, PolygonCloud };
 
+    /// \since 0.20
+    LineAnnotation( LineType type );
     virtual ~LineAnnotation();
     virtual SubType subType() const;
 
+    /// \since 0.20
     LineType lineType() const;
 
     QLinkedList<QPointF> linePoints() const;
@@ -433,7 +436,6 @@ class POPPLER_QT4_EXPORT LineAnnotation : public Annotation
     void setLineIntent( LineIntent intent );
 
   private:
-    LineAnnotation( LineType type );
     LineAnnotation( const QDomNode &node );
     LineAnnotation( LineAnnotationPrivate &dd );
     virtual void store( QDomNode &parentNode, QDomDocument &document ) const;
diff --git a/qt4/src/poppler-page.cc b/qt4/src/poppler-page.cc
index 931d22e..e4a5f8b 100644
--- a/qt4/src/poppler-page.cc
+++ b/qt4/src/poppler-page.cc
@@ -576,6 +576,11 @@ QList<Annotation*> Page::annotations() const
   return AnnotationPrivate::findAnnotations(m_page->page, m_page->parentDoc);
 }
 
+void Page::addAnnotation( const Annotation *ann )
+{
+  AnnotationPrivate::addAnnotationToPage(m_page->page, m_page->parentDoc, ann);
+}
+
 QList<FormField*> Page::formFields() const
 {
   QList<FormField*> fields;
diff --git a/qt4/src/poppler-qt4.h b/qt4/src/poppler-qt4.h
index 62b2719..0fdfdb7 100644
--- a/qt4/src/poppler-qt4.h
+++ b/qt4/src/poppler-qt4.h
@@ -686,6 +686,15 @@ delete it;
 	QList<Annotation*> annotations() const;
 
 	/**
+	 Adds an annotation to the page
+
+	 \note Ownership of the annotation object stays with the caller, who can
+	       delete it at any time.
+	 \since 0.20
+	*/
+	void addAnnotation( const Annotation *ann );
+
+	/**
 	 Returns the form fields on the page
 	 The caller gets the ownership of the returned objects.
 
commit 20b4feec612448be8a800173ddadbf257657477e
Author: Fabio D'Urso <fabiodurso at hotmail.it>
Date:   Fri Mar 9 19:31:16 2012 +0100

    qt4: Basic setters to edit annotations

diff --git a/qt4/src/poppler-annotation-helper.h b/qt4/src/poppler-annotation-helper.h
index 5fc00a8..5f335c0 100644
--- a/qt4/src/poppler-annotation-helper.h
+++ b/qt4/src/poppler-annotation-helper.h
@@ -45,6 +45,7 @@ class XPDFReader
         static inline void lookupDate( Dict *, char *, QDateTime & dest );
         // transform from user coords to normalized ones using the matrix M
         static inline void transform( double * M, double x, double y, QPointF &res );
+        static inline void invTransform( double * M, const QPointF &p, double &x, double &y );
 };
 
 void XPDFReader::lookupName( Dict * dict, char * type, QString & dest )
@@ -178,6 +179,20 @@ void XPDFReader::transform( double * M, double x, double y, QPointF &res )
     res.setY( M[1] * x + M[3] * y + M[5] );
 }
 
+void XPDFReader::invTransform( double * M, const QPointF &p, double &x, double &y )
+{
+    const double det = M[0]*M[3] - M[1]*M[2];
+    Q_ASSERT(det != 0);
+
+    const double invM[4] = { M[3]/det, -M[1]/det, -M[2]/det, M[0]/det };
+    const double xt = p.x() - M[4];
+    const double yt = p.y() - M[5];
+
+    x = invM[0] * xt + invM[2] * yt;
+    y = invM[1] * xt + invM[3] * yt;
+}
+
 QColor convertAnnotColor( AnnotColor *color );
+AnnotColor* convertQColor( const QColor &color );
 
 }
diff --git a/qt4/src/poppler-annotation-private.h b/qt4/src/poppler-annotation-private.h
index 2485034..24f5343 100644
--- a/qt4/src/poppler-annotation-private.h
+++ b/qt4/src/poppler-annotation-private.h
@@ -77,6 +77,7 @@ class AnnotationPrivate : public QSharedData
         /* The following helpers only work if pdfPage is set */
         void fillMTX(double MTX[6]) const;
         QRectF fromPdfRectangle(const PDFRectangle &r) const;
+        PDFRectangle toPdfRectangle(const QRectF &r) const;
 
         /* Scan page for annotations, parentId=0 searches for root annotations */
         static QList<Annotation*> findAnnotations(::Page *pdfPage, DocumentData *doc, int parentId = 0);
diff --git a/qt4/src/poppler-annotation.cc b/qt4/src/poppler-annotation.cc
index c57475b..3e7b361 100644
--- a/qt4/src/poppler-annotation.cc
+++ b/qt4/src/poppler-annotation.cc
@@ -197,6 +197,32 @@ 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
+{
+    double MTX[6];
+    fillMTX(MTX);
+
+    double tl_x, tl_y, br_x, br_y, swp;
+    XPDFReader::invTransform( MTX, r.topLeft(), tl_x, tl_y );
+    XPDFReader::invTransform( MTX, r.bottomRight(), br_x, br_y );
+
+    if (tl_x > br_x)
+    {
+        swp = tl_x;
+        tl_x = br_x;
+        br_x = swp;
+    }
+
+    if (tl_y > br_y)
+    {
+        swp = tl_y;
+        tl_y = br_y;
+        br_y = swp;
+    }
+
+    return PDFRectangle(tl_x, tl_y, br_x, br_y);
+}
+
 QList<Annotation*> AnnotationPrivate::findAnnotations(::Page *pdfPage, DocumentData *doc, int parentID)
 {
     Annots* annots = pdfPage->getAnnots();
@@ -906,7 +932,13 @@ void Annotation::setAuthor( const QString &author )
         return;
     }
 
-    // TODO: Set pdfAnnot
+    AnnotMarkup *markupann = dynamic_cast<AnnotMarkup*>(d->pdfAnnot);
+    if (markupann)
+    {
+        GooString *s = QStringToUnicodeGooString(author);
+        markupann->setLabel(s);
+        delete s;
+    }
 }
 
 QString Annotation::contents() const
@@ -929,7 +961,9 @@ void Annotation::setContents( const QString &contents )
         return;
     }
 
-    // TODO: Set pdfAnnot
+    GooString *s = QStringToUnicodeGooString(contents);
+    d->pdfAnnot->setContents(s);
+    delete s;
 }
 
 QString Annotation::uniqueName() const
@@ -952,7 +986,9 @@ void Annotation::setUniqueName( const QString &uniqueName )
         return;
     }
 
-    // TODO: Set pdfAnnot
+    QByteArray ascii = uniqueName.toAscii();
+    GooString s(ascii.constData());
+    d->pdfAnnot->setName(&s);
 }
 
 QDateTime Annotation::modificationDate() const
@@ -978,7 +1014,15 @@ void Annotation::setModificationDate( const QDateTime &date )
         return;
     }
 
-    // TODO: Set pdfAnnot
+#if 0 // TODO: Conversion routine is broken
+    if (d->pdfAnnot)
+    {
+        time_t t = date.toTime_t();
+        GooString *s = timeToDateString(&t);
+        d->pdfAnnot->setModified(s);
+        delete s;
+    }
+#endif
 }
 
 QDateTime Annotation::creationDate() const
@@ -1006,7 +1050,16 @@ void Annotation::setCreationDate( const QDateTime &date )
         return;
     }
 
-    // TODO: Set pdfAnnot
+#if 0 // TODO: Conversion routine is broken
+    AnnotMarkup *markupann = dynamic_cast<AnnotMarkup*>(d->pdfAnnot);
+    if (markupann)
+    {
+        time_t t = date.toTime_t();
+        GooString *s = timeToDateString(&t);
+        markupann->setDate(s);
+        delete s;
+    }
+#endif
 }
 
 static int fromPdfFlags(int flags)
@@ -1031,6 +1084,28 @@ static int fromPdfFlags(int flags)
     return qtflags;
 }
 
+static int toPdfFlags(int qtflags)
+{
+    int flags = 0;
+
+    if ( qtflags & Annotation::Hidden )
+        flags |= Annot::flagHidden;
+    if ( qtflags & Annotation::FixedSize )
+        flags |= Annot::flagNoZoom;
+    if ( qtflags & Annotation::FixedRotation )
+        flags |= Annot::flagNoRotate;
+    if ( !( qtflags & Annotation::DenyPrint ) )
+        flags |= Annot::flagPrint;
+    if ( qtflags & Annotation::DenyWrite )
+        flags |= Annot::flagReadOnly;
+    if ( qtflags & Annotation::DenyDelete )
+        flags |= Annot::flagLocked;
+    if ( qtflags & Annotation::ToggleHidingOnMouse )
+        flags |= Annot::flagToggleNoView;
+
+    return flags;
+}
+
 int Annotation::flags() const
 {
     Q_D( const Annotation );
@@ -1051,7 +1126,7 @@ void Annotation::setFlags( int flags )
         return;
     }
 
-    // TODO: Set pdfAnnot
+    d->pdfAnnot->setFlags(toPdfFlags( flags ));
 }
 
 QRectF Annotation::boundary() const
@@ -1075,7 +1150,8 @@ void Annotation::setBoundary( const QRectF &boundary )
         return;
     }
 
-    // TODO: Set pdfAnnot
+    PDFRectangle rect = d->toPdfRectangle(boundary);
+    d->pdfAnnot->setRect(&rect);
 }
 
 Annotation::Style Annotation::style() const
@@ -1145,7 +1221,17 @@ void Annotation::setStyle( const Annotation::Style& style )
         return;
     }
 
-    // TODO: Set pdfAnnot
+    d->pdfAnnot->setColor(convertQColor( style.color() ));
+
+    AnnotMarkup *markupann = dynamic_cast<AnnotMarkup*>(d->pdfAnnot);
+    if (markupann)
+        markupann->setOpacity( style.opacity() );
+
+    AnnotBorderArray * border = new AnnotBorderArray();
+    border->setWidth( style.width() );
+    border->setHorizontalCorner( style.xCorners() );
+    border->setVerticalCorner( style.yCorners() );
+    d->pdfAnnot->setBorder(border);
 }
 
 Annotation::Popup Annotation::popup() const
@@ -1210,7 +1296,23 @@ void Annotation::setPopup( const Annotation::Popup& popup )
         return;
     }
 
-    // TODO: Set pdfAnnot
+#if 0 /* TODO: Remove old popup and add AnnotPopup to page */
+    AnnotMarkup *markupann = dynamic_cast<AnnotMarkup*>(d->pdfAnnot);
+    if (!markupann)
+        return;
+
+    // Create a new AnnotPopup and assign it to pdfAnnot
+    PDFRectangle rect = d->toPdfRectangle( popup.geometry() );
+    AnnotPopup * p = new AnnotPopup( d->pdfPage->getDoc(), &rect );
+    p->setOpen( !(popup.flags() & Annotation::Hidden) );
+    if (!popup.summary().isEmpty())
+    {
+        GooString *s = QStringToUnicodeGooString(popup.summary());
+        markupann->setLabel(s);
+        delete s;
+    }
+    markupann->setPopup(p);
+#endif
 }
 
 Annotation::RevScope Annotation::revisionScope() const
@@ -3613,6 +3715,14 @@ QColor convertAnnotColor( AnnotColor *color )
     }
     return newcolor;
 }
+
+AnnotColor* convertQColor( const QColor &c )
+{
+    if (!c.isValid() || c.alpha() == 0)
+        return new AnnotColor(); // Transparent
+    else
+        return new AnnotColor(c.redF(), c.greenF(), c.blueF());
+}
 //END utility annotation functions
 
 }
commit 0e8c35b59f0fba926b30c9a87823c92ae03bf116
Author: Fabio D'Urso <fabiodurso at hotmail.it>
Date:   Fri Mar 9 01:04:28 2012 +0100

    qt4: Changes to Annotation API (part 2/2)
    
    1) Moved annotation data retrieval logic to getters for types of annotations
    that will be made editable in next patches.
    Others (Link, FileAttachment, Sound, Movie and Screen) are still entirely filled
    at creation time.
    
    2) TextAnnotation's callout points setter now takes an array, not just
    individual points.
    
    3) AnnotationPrivate::pdfObjectReference replaced with a getter method that
    directly queries the tied Annot object (if any)

diff --git a/qt4/src/poppler-annotation-helper.h b/qt4/src/poppler-annotation-helper.h
index f5d17eb..5fc00a8 100644
--- a/qt4/src/poppler-annotation-helper.h
+++ b/qt4/src/poppler-annotation-helper.h
@@ -1,6 +1,7 @@
 /* poppler-annotation-helper.h: qt interface to poppler
  * Copyright (C) 2006, 2008, Albert Astals Cid <aacid at kde.org>
  * Copyright (C) 2008, Pino Toscano <pino at kde.org>
+ * Copyright (C) 2012, Fabio D'Urso <fabiodurso at hotmail.it>
  * Adapting code from
  *   Copyright (C) 2004 by Enrico Ros <eros.kde at email.it>
  *
@@ -21,6 +22,8 @@
 
 #include <QtCore/QDebug>
 
+#include <Object.h>
+
 class QColor;
 
 class AnnotColor;
@@ -175,34 +178,6 @@ void XPDFReader::transform( double * M, double x, double y, QPointF &res )
     res.setY( M[1] * x + M[3] * y + M[5] );
 }
 
-/** @short Helper classes for CROSSDEPS resolving and DS conversion. */
-struct ResolveRevision
-{
-    int           prevAnnotationID; // ID of the annotation to be reparended
-    int           nextAnnotationID; // (only needed for speeding up resolving)
-    Annotation *  nextAnnotation;   // annotation that will act as parent
-    Annotation::RevScope nextScope; // scope of revision (Reply)
-    Annotation::RevType  nextType;  // type of revision (None)
-};
-
-struct ResolveWindow
-{
-    AnnotPopup *  popup;            // the (maybe shared) window
-    Annotation *  annotation;       // annotation having the popup window
-};
-
-struct PostProcessText              // this handles a special pdf case conversion
-{
-    Annotation *  textAnnotation;   // a popup text annotation (not FreeText)
-    bool          opened;           // pdf property to convert to window flags
-};
-
-struct PopupWindow
-{
-    Annotation *  dummyAnnotation;  // window properties (in pdf as Annotation)
-    bool          shown;            // converted to Annotation::Hidden flag
-};
-
 QColor convertAnnotColor( AnnotColor *color );
 
 }
diff --git a/qt4/src/poppler-annotation-private.h b/qt4/src/poppler-annotation-private.h
index 7c63c7e..2485034 100644
--- a/qt4/src/poppler-annotation-private.h
+++ b/qt4/src/poppler-annotation-private.h
@@ -27,8 +27,13 @@
 
 #include <Object.h>
 
+class Annot;
+class Page;
+class PDFRectangle;
+
 namespace Poppler
 {
+class DocumentData;
 
 class AnnotationPrivate : public QSharedData
 {
@@ -60,7 +65,23 @@ class AnnotationPrivate : public QSharedData
         Annotation::RevType revisionType;
         QList<Annotation*> revisions;
 
-        Ref pdfObjectReference;
+        /* After this call, the Annotation object will behave like a wrapper for
+         * the specified Annot object. All cached values are discarded */
+        void tieToNativeAnnot(Annot *ann, ::Page *page, DocumentData *doc);
+
+        /* Inited to 0 (i.e. untied annotation) */
+        Annot *pdfAnnot;
+        ::Page *pdfPage;
+        DocumentData * parentDoc;
+
+        /* The following helpers only work if pdfPage is set */
+        void fillMTX(double MTX[6]) const;
+        QRectF fromPdfRectangle(const PDFRectangle &r) const;
+
+        /* Scan page for annotations, parentId=0 searches for root annotations */
+        static QList<Annotation*> findAnnotations(::Page *pdfPage, DocumentData *doc, int parentId = 0);
+
+        Ref pdfObjectReference() const;
 };
 
 }
diff --git a/qt4/src/poppler-annotation.cc b/qt4/src/poppler-annotation.cc
index b812737..c57475b 100644
--- a/qt4/src/poppler-annotation.cc
+++ b/qt4/src/poppler-annotation.cc
@@ -30,11 +30,23 @@
 #include "poppler-annotation.h"
 #include "poppler-link.h"
 #include "poppler-qt4.h"
+#include "poppler-annotation-helper.h"
 #include "poppler-annotation-private.h"
+#include "poppler-page-private.h"
+#include "poppler-private.h"
 
 // poppler includes
 #include <Page.h>
 #include <Annot.h>
+#include <Gfx.h>
+#include <Error.h>
+#include <FileSpec.h>
+
+/* Almost all getters directly query the underlying poppler annotation, with
+ * the exceptions of link, file attachment, sound, movie and screen annotations,
+ * Whose data retrieval logic has not been moved yet. Their getters return
+ * static data set at creation time by findAnnotations
+ */
 
 namespace Poppler {
 
@@ -108,15 +120,275 @@ QDomElement AnnotationUtils::findChildElement( const QDomNode & parentNode,
 
 //BEGIN Annotation implementation
 AnnotationPrivate::AnnotationPrivate()
-    : flags( 0 ), revisionScope ( Annotation::Root ), revisionType ( Annotation::None )
+    : flags( 0 ), revisionScope ( Annotation::Root ),
+    revisionType ( Annotation::None ), pdfAnnot ( 0 ), pdfPage ( 0 ),
+    parentDoc ( 0 )
 {
-    pdfObjectReference.num = pdfObjectReference.gen = -1;
 }
 
 AnnotationPrivate::~AnnotationPrivate()
 {
     // Delete all children revisions
     qDeleteAll( revisions );
+
+    // Release Annot object
+    if (pdfAnnot)
+        pdfAnnot->decRefCnt();
+}
+
+void AnnotationPrivate::tieToNativeAnnot(Annot *ann, ::Page *page, Poppler::DocumentData * doc)
+{
+    if (pdfAnnot)
+    {
+        error(errIO, -1, "Annotation is already tied");
+        return;
+    }
+
+    pdfAnnot = ann;
+    pdfPage = page;
+    parentDoc = doc;
+
+    pdfAnnot->incRefCnt();
+}
+
+void AnnotationPrivate::fillMTX(double MTX[6]) 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 );
+    double * gfxCTM = gfxState->getCTM();
+    for ( int i = 0; i < 6; i+=2 )
+    {
+        MTX[i] = gfxCTM[i] / pdfPage->getCropWidth();
+        MTX[i+1] = gfxCTM[i+1] / pdfPage->getCropHeight();
+    }
+    delete gfxState;
+}
+
+QRectF AnnotationPrivate::fromPdfRectangle(const PDFRectangle &r) const
+{
+    double swp, MTX[6];
+    fillMTX(MTX);
+
+    QPointF p1, p2;
+    XPDFReader::transform( MTX, r.x1, r.y1, p1 );
+    XPDFReader::transform( MTX, r.x2, r.y2, p2 );
+
+    double tl_x = p1.x();
+    double tl_y = p1.y();
+    double br_x = p2.x();
+    double br_y = p2.y();
+
+    if (tl_x > br_x)
+    {
+        swp = tl_x;
+        tl_x = br_x;
+        br_x = swp;
+    }
+
+    if (tl_y > br_y)
+    {
+        swp = tl_y;
+        tl_y = br_y;
+        br_y = swp;
+    }
+
+    return QRectF( QPointF(tl_x,tl_y) , QPointF(br_x,br_y) );
+}
+
+QList<Annotation*> AnnotationPrivate::findAnnotations(::Page *pdfPage, DocumentData *doc, int parentID)
+{
+    Annots* annots = pdfPage->getAnnots();
+    const uint numAnnotations = annots->getNumAnnots();
+    if ( numAnnotations == 0 )
+    {
+        return QList<Annotation*>();
+    }
+
+    // Create Annotation objects and tie to their native Annot
+    QList<Annotation*> res;
+    for ( uint j = 0; j < numAnnotations; j++ )
+    {
+        // get the j-th annotation
+        Annot * ann = annots->getAnnot( j );
+        if ( !ann )
+        {
+            error(errInternal, -1, "Annot %u is null", j);
+            continue;
+        }
+
+        // Check parent annotation
+        AnnotMarkup * markupann = dynamic_cast< AnnotMarkup * >( ann );
+        if (!markupann)
+        {
+            // Assume it's a root annotation, and skip if user didn't request it
+            if (parentID != 0)
+                continue;
+        }
+        else if (markupann->getInReplyToID() != parentID)
+            continue;
+
+        /* Create Annotation of the right subclass */
+        Annotation * annotation = 0;
+        Annot::AnnotSubtype subType = ann->getType();
+
+        switch ( subType )
+        {
+            case Annot::typeText:
+                annotation = new TextAnnotation(TextAnnotation::Linked);
+                break;
+            case Annot::typeFreeText:
+                annotation = new TextAnnotation(TextAnnotation::InPlace);
+                break;
+            case Annot::typeLine:
+                annotation = new LineAnnotation(LineAnnotation::StraightLine);
+                break;
+            case Annot::typePolygon:
+            case Annot::typePolyLine:
+                annotation = new LineAnnotation(LineAnnotation::Polyline);
+                break;
+            case Annot::typeSquare:
+            case Annot::typeCircle:
+                annotation = new GeomAnnotation();
+                break;
+            case Annot::typeHighlight:
+            case Annot::typeUnderline:
+            case Annot::typeSquiggly:
+            case Annot::typeStrikeOut:
+                annotation = new HighlightAnnotation();
+                break;
+            case Annot::typeStamp:
+                annotation = new StampAnnotation();
+                break;
+            case Annot::typeInk:
+                annotation = new InkAnnotation();
+                break;
+            case Annot::typeLink: /* TODO: Move logic to getters */
+            {
+                // parse Link params
+                AnnotLink * linkann = static_cast< AnnotLink * >( ann );
+                LinkAnnotation * l = new LinkAnnotation();
+                annotation = l;
+
+                // -> hlMode
+                l->setLinkHighlightMode( (LinkAnnotation::HighlightMode)linkann->getLinkEffect() );
+
+                // -> link region
+                // TODO
+
+                // reading link action
+                if ( linkann->getAction() )
+                {
+                    Link * popplerLink = PageData::convertLinkActionToLink( linkann->getAction(), doc, QRectF() );
+                    if ( popplerLink )
+                    {
+                        l->setLinkDestination( popplerLink );
+                    }
+                }
+                break;
+            }
+            case Annot::typeCaret:
+                annotation = new CaretAnnotation();
+                break;
+            case Annot::typeFileAttachment: /* TODO: Move logic to getters */
+            {
+                AnnotFileAttachment * attachann = static_cast< AnnotFileAttachment * >( ann );
+                FileAttachmentAnnotation * f = new FileAttachmentAnnotation();
+                annotation = f;
+                // -> fileIcon
+                f->setFileIconName( QString::fromLatin1( attachann->getName()->getCString() ) );
+                // -> embeddedFile
+                FileSpec *filespec = new FileSpec( attachann->getFile() );
+                f->setEmbeddedFile( new EmbeddedFile( *new EmbeddedFileData( filespec ) ) );
+                break;
+            }
+            case Annot::typeSound: /* TODO: Move logic to getters */
+            {
+                AnnotSound * soundann = static_cast< AnnotSound * >( ann );
+                SoundAnnotation * s = new SoundAnnotation();
+                annotation = s;
+
+                // -> soundIcon
+                s->setSoundIconName( QString::fromLatin1( soundann->getName()->getCString() ) );
+                // -> sound
+                s->setSound( new SoundObject( soundann->getSound() ) );
+                break;
+            }
+            case Annot::typeMovie: /* TODO: Move logic to getters */
+            {
+                AnnotMovie * movieann = static_cast< AnnotMovie * >( ann );
+                MovieAnnotation * m = new MovieAnnotation();
+                annotation = m;
+
+                // -> movie
+                MovieObject *movie = new MovieObject( movieann );
+                m->setMovie( movie );
+                // -> movieTitle
+                GooString * movietitle = movieann->getTitle();
+                if ( movietitle )
+                    m->setMovieTitle( QString::fromLatin1( movietitle->getCString() ) );
+                break;
+            }
+            case Annot::typeScreen:
+            {
+                AnnotScreen * screenann = static_cast< AnnotScreen * >( ann );
+                if (!screenann->getAction())
+                  continue;
+                ScreenAnnotation * s = new ScreenAnnotation();
+                annotation = s;
+
+                // -> screen
+                Link * popplerLink = PageData::convertLinkActionToLink( screenann->getAction(), doc, QRectF() );
+                s->setAction( static_cast<Poppler::LinkRendition *>(popplerLink) );
+
+                // -> screenTitle
+                GooString * screentitle = screenann->getTitle();
+                if ( screentitle )
+                    s->setScreenTitle( UnicodeParsedString( screentitle ) );
+                break;
+            }
+            case Annot::typePopup:
+                continue; // popups are parsed by Annotation's window() getter
+            case Annot::typeUnknown:
+                continue; // special case for ignoring unknown annotations
+            case Annot::typeWidget:
+                continue; // handled as forms or some other way
+            default:
+            {
+#define CASE_FOR_TYPE( thetype ) \
+                    case Annot::type ## thetype: \
+                        error(errUnimplemented, -1, "Annotation " #thetype " not supported"); \
+                        break;
+                switch ( subType )
+                {
+                    CASE_FOR_TYPE( PrinterMark )
+                    CASE_FOR_TYPE( TrapNet )
+                    CASE_FOR_TYPE( Watermark )
+                    CASE_FOR_TYPE( 3D )
+                    default: error(errUnimplemented, -1, "Annotation %u not supported", subType);
+                }
+                continue;
+#undef CASE_FOR_TYPE
+            }
+        }
+
+        annotation->d_ptr->tieToNativeAnnot(ann, pdfPage, doc);
+        res.append(annotation);
+    }
+
+    return res;
+}
+
+Ref AnnotationPrivate::pdfObjectReference() const
+{
+    if (pdfAnnot == 0)
+    {
+        const Ref invalid_ref = { -1, -1 };
+        return invalid_ref;
+    }
+
+    return pdfAnnot->getRef();
 }
 
 class Annotation::Style::Private : public QSharedData
@@ -616,160 +888,449 @@ void Annotation::storeBaseAnnotationProperties( QDomNode & annNode, QDomDocument
 QString Annotation::author() const
 {
     Q_D( const Annotation );
-    return d->author;
+
+    if (!d->pdfAnnot)
+        return d->author;
+
+    const AnnotMarkup *markupann = dynamic_cast<const AnnotMarkup*>(d->pdfAnnot);
+    return markupann ? UnicodeParsedString( markupann->getLabel() ) : QString();
 }
 
 void Annotation::setAuthor( const QString &author )
 {
     Q_D( Annotation );
-    d->author = author;
+
+    if (!d->pdfAnnot)
+    {
+        d->author = author;
+        return;
+    }
+
+    // TODO: Set pdfAnnot
 }
 
 QString Annotation::contents() const
 {
     Q_D( const Annotation );
-    return d->contents;
+
+    if (!d->pdfAnnot)
+        return d->contents;
+
+    return UnicodeParsedString( d->pdfAnnot->getContents() );
 }
 
 void Annotation::setContents( const QString &contents )
 {
     Q_D( Annotation );
-    d->contents = contents;
+
+    if (!d->pdfAnnot)
+    {
+        d->contents = contents;
+        return;
+    }
+
+    // TODO: Set pdfAnnot
 }
 
 QString Annotation::uniqueName() const
 {
     Q_D( const Annotation );
-    return d->uniqueName;
+
+    if (!d->pdfAnnot)
+        return d->uniqueName;
+
+    return UnicodeParsedString( d->pdfAnnot->getName() );
 }
 
 void Annotation::setUniqueName( const QString &uniqueName )
 {
     Q_D( Annotation );
-    d->uniqueName = uniqueName;
+
+    if (!d->pdfAnnot)
+    {
+        d->uniqueName = uniqueName;
+        return;
+    }
+
+    // TODO: Set pdfAnnot
 }
 
 QDateTime Annotation::modificationDate() const
 {
     Q_D( const Annotation );
-    return d->modDate;
+
+    if (!d->pdfAnnot)
+        return d->modDate;
+
+    if ( d->pdfAnnot->getModified() )
+        return convertDate( d->pdfAnnot->getModified()->getCString() );
+    else
+        return QDateTime();
 }
 
 void Annotation::setModificationDate( const QDateTime &date )
 {
     Q_D( Annotation );
-    d->modDate = date;
+
+    if (!d->pdfAnnot)
+    {
+        d->modDate = date;
+        return;
+    }
+
+    // TODO: Set pdfAnnot
 }
 
 QDateTime Annotation::creationDate() const
 {
     Q_D( const Annotation );
-    return d->creationDate;
+
+    if (!d->pdfAnnot)
+        return d->creationDate;
+
+    const AnnotMarkup *markupann = dynamic_cast<const AnnotMarkup*>(d->pdfAnnot);
+
+    if (markupann && markupann->getDate())
+        return convertDate( markupann->getDate()->getCString() );
+
+    return modificationDate();
 }
 
 void Annotation::setCreationDate( const QDateTime &date )
 {
     Q_D( Annotation );
-    d->creationDate = date;
+
+    if (!d->pdfAnnot)
+    {
+        d->creationDate = date;
+        return;
+    }
+
+    // TODO: Set pdfAnnot
+}
+
+static int fromPdfFlags(int flags)
+{
+    int qtflags = 0;
+
+    if ( flags & Annot::flagHidden )
+        qtflags |= Annotation::Hidden;
+    if ( flags & Annot::flagNoZoom )
+        qtflags |= Annotation::FixedSize;
+    if ( flags & Annot::flagNoRotate )
+        qtflags |= Annotation::FixedRotation;
+    if ( !( flags & Annot::flagPrint ) )
+        qtflags |= Annotation::DenyPrint;
+    if ( flags & Annot::flagReadOnly )
+        qtflags |= (Annotation::DenyWrite | Annotation::DenyDelete);
+    if ( flags & Annot::flagLocked )
+        qtflags |= Annotation::DenyDelete;
+    if ( flags & Annot::flagToggleNoView )
+        qtflags |= Annotation::ToggleHidingOnMouse;
+
+    return qtflags;
 }
 
 int Annotation::flags() const
 {
     Q_D( const Annotation );
-    return d->flags;
+
+    if (!d->pdfAnnot)
+        return d->flags;
+
+    return fromPdfFlags( d->pdfAnnot->getFlags() );
 }
 
 void Annotation::setFlags( int flags )
 {
     Q_D( Annotation );
-    d->flags = flags;
+
+    if (!d->pdfAnnot)
+    {
+        d->flags = flags;
+        return;
+    }
+
+    // TODO: Set pdfAnnot
 }
 
 QRectF Annotation::boundary() const
 {
     Q_D( const Annotation );
-    return d->boundary;
+
+    if (!d->pdfAnnot)
+        return d->boundary;
+
+    const PDFRectangle * rect = d->pdfAnnot->getRect();
+    return d->fromPdfRectangle( *rect );
 }
 
 void Annotation::setBoundary( const QRectF &boundary )
 {
     Q_D( Annotation );
-    d->boundary = boundary;
+
+    if (!d->pdfAnnot)
+    {
+        d->boundary = boundary;
+        return;
+    }
+
+    // TODO: Set pdfAnnot
 }
 
 Annotation::Style Annotation::style() const
 {
     Q_D( const Annotation );
-    return d->style;
+
+    if (!d->pdfAnnot)
+        return d->style;
+
+    Style s;
+    s.setColor(convertAnnotColor( d->pdfAnnot->getColor() ));
+
+    const AnnotMarkup *markupann = dynamic_cast<const AnnotMarkup*>(d->pdfAnnot);
+    if (markupann)
+        s.setOpacity( markupann->getOpacity() );
+
+    const AnnotBorder *border = d->pdfAnnot->getBorder();
+    if (border)
+    {
+        if ( border->getType() == AnnotBorder::typeArray )
+        {
+            const AnnotBorderArray *border_array = static_cast<const AnnotBorderArray*>(border);
+            s.setXCorners( border_array->getHorizontalCorner() );
+            s.setYCorners( border_array->getVerticalCorner() );
+        }
+
+        s.setWidth( border->getWidth() );
+        s.setLineStyle((Annotation::LineStyle)( 1 << border->getStyle() ));
+
+        const int dashArrLen = border->getDashLength();
+        const double* dashArrData = border->getDash();
+        QVector<double> dashArrVect( dashArrLen );
+        for (int i = 0; i < dashArrLen; ++i)
+            dashArrVect[i] = dashArrData[i];
+        s.setDashArray(dashArrVect);
+    }
+
+    AnnotBorderEffect *border_effect;
+    switch (d->pdfAnnot->getType())
+    {
+        case Annot::typeFreeText:
+            border_effect = static_cast<AnnotFreeText*>(d->pdfAnnot)->getBorderEffect();
+            break;
+        case Annot::typeSquare:
+        case Annot::typeCircle:
+            border_effect = static_cast<AnnotGeometry*>(d->pdfAnnot)->getBorderEffect();
+            break;
+        default:
+            border_effect = 0;
+    }
+    if (border_effect)
+    {
+        s.setLineEffect( (Annotation::LineEffect)border_effect->getEffectType() );
+        s.setEffectIntensity( border_effect->getIntensity() );
+    }
+
+    return s;
 }
 
 void Annotation::setStyle( const Annotation::Style& style )
 {
     Q_D( Annotation );
-    d->style = style;
+
+    if (!d->pdfAnnot)
+    {
+        d->style = style;
+        return;
+    }
+
+    // TODO: Set pdfAnnot
 }
 
 Annotation::Popup Annotation::popup() const
 {
     Q_D( const Annotation );
-    return d->popup;
+
+    if (!d->pdfAnnot)
+        return d->popup;
+
+    Popup w;
+    AnnotPopup *popup = 0;
+    int flags = -1; // Not initialized
+
+    const AnnotMarkup *markupann = dynamic_cast<const AnnotMarkup*>(d->pdfAnnot);
+    if (markupann)
+    {
+        popup = markupann->getPopup();
+        w.setSummary(UnicodeParsedString( markupann->getSubject() ));
+    }
+
+    if (popup)
+    {
+        flags = fromPdfFlags( popup->getFlags() ) & ( Annotation::Hidden |
+                Annotation::FixedSize | Annotation::FixedRotation );
+
+        if (!popup->getOpen())
+            flags |= Annotation::Hidden;
+
+        const PDFRectangle * rect = popup->getRect();
+        w.setGeometry( d->fromPdfRectangle( *rect ) );
+    }
+
+    if (d->pdfAnnot->getType() == Annot::typeText)
+    {
+        const AnnotText * textann = static_cast<const AnnotText*>(d->pdfAnnot);
+
+        // Text annotations default to same rect as annotation
+        if (flags == -1)
+        {
+            flags = 0;
+            w.setGeometry( boundary() );
+        }
+
+        // If text is not 'opened', force window hiding. if the window
+        // was parsed from popup, the flag should already be set
+        if ( !textann->getOpen() && flags != -1 )
+            flags |= Annotation::Hidden;
+    }
+
+    w.setFlags(flags);
+
+    return w;
 }
 
 void Annotation::setPopup( const Annotation::Popup& popup )
 {
     Q_D( Annotation );
-    d->popup = popup;
+
+    if (!d->pdfAnnot)
+    {
+        d->popup = popup;
+        return;
+    }
+
+    // TODO: Set pdfAnnot
 }
 
 Annotation::RevScope Annotation::revisionScope() const
 {
     Q_D( const Annotation );
-    return d->revisionScope;
+
+    if (!d->pdfAnnot)
+        return d->revisionScope;
+
+    const AnnotMarkup *markupann = dynamic_cast<const AnnotMarkup*>(d->pdfAnnot);
+
+    if (markupann && markupann->getInReplyToID() != 0)
+    {
+        switch (markupann->getReplyTo())
+        {
+            case AnnotMarkup::replyTypeR:
+                return Annotation::Reply;
+            case AnnotMarkup::replyTypeGroup:
+                return Annotation::Group;
+        }
+    }
+
+    return Annotation::Root; // It's not a revision
 }
 
 void Annotation::setRevisionScope( Annotation::RevScope scope )
 {
     Q_D( Annotation );
-    d->revisionScope = scope;
+
+    if (!d->pdfAnnot)
+    {
+        d->revisionScope = scope;
+        return;
+    }
+
+    // TODO: Set pdfAnnot
 }
 
 Annotation::RevType Annotation::revisionType() const
 {
     Q_D( const Annotation );
-    return d->revisionType;
+
+    if (!d->pdfAnnot)
+        return d->revisionType;
+
+    const AnnotText *textann = dynamic_cast<const AnnotText*>(d->pdfAnnot);
+
+    if (textann && textann->getInReplyToID() != 0)
+    {
+        switch (textann->getState())
+        {
+            case AnnotText::stateMarked:
+                return Annotation::Marked;
+            case AnnotText::stateUnmarked:
+                return Annotation::Unmarked;
+            case AnnotText::stateAccepted:
+                return Annotation::Accepted;
+            case AnnotText::stateRejected:
+                return Annotation::Rejected;
+            case AnnotText::stateCancelled:
+                return Annotation::Cancelled;
+            case AnnotText::stateCompleted:
+                return Annotation::Completed;
+            default:
+                break;
+        }
+    }
+
+    return Annotation::None;
 }
 
 void Annotation::setRevisionType( Annotation::RevType type )
 {
     Q_D( Annotation );
-    d->revisionType = type;
+
+    if (!d->pdfAnnot)
+    {
+        d->revisionType = type;
+        return;
+    }
+
+    // TODO: Set pdfAnnot
 }
 
 QList<Annotation*> Annotation::revisions() const
 {
     Q_D( const Annotation );
-    QList<Annotation*> res;
 
-    /* Return aliases, whose ownership goes to the caller */
-    foreach (Annotation *rev, d->revisions)
-        res.append( rev->d_ptr->makeAlias() );
+    if (!d->pdfAnnot)
+    {
+        /* Return aliases, whose ownership goes to the caller */
+        QList<Annotation*> res;
+        foreach (Annotation *rev, d->revisions)
+            res.append( rev->d_ptr->makeAlias() );
+        return res;
+    }
 
-    return res;
+    return AnnotationPrivate::findAnnotations( d->pdfPage, d->parentDoc, d->pdfAnnot->getId() );
 }
 
 void Annotation::addRevision( Annotation *ann, RevScope scope, RevType type )
 {
     Q_D( Annotation );
 
-    /* Since ownership stays with the caller, create an alias of ann */
-    d->revisions.append( ann->d_ptr->makeAlias() );
+    if (!d->pdfAnnot)
+    {
+        /* Since ownership stays with the caller, create an alias of ann */
+        d->revisions.append( ann->d_ptr->makeAlias() );
+    }
+    else
+    {
+        // TODO: Add annotation to page and set IRT
+    }
 
     /* Set revision properties */
     ann->setRevisionScope(scope);
     ann->setRevisionType(type);
 }
 
-//END AnnotationUtils implementation
+//END Annotation implementation
 
 
 /** TextAnnotation [Annotation] */
@@ -785,7 +1346,7 @@ class TextAnnotationPrivate : public AnnotationPrivate
         QFont textFont;
         int inplaceAlign; // 0:left, 1:center, 2:right
         QString inplaceText;  // overrides contents
-        QPointF inplaceCallout[3];
+        QVector<QPointF> inplaceCallout;
         TextAnnotation::InplaceIntent inplaceIntent;
 };
 
@@ -801,9 +1362,11 @@ Annotation * TextAnnotationPrivate::makeAlias()
     return new TextAnnotation(*this);
 }
 
-TextAnnotation::TextAnnotation()
+TextAnnotation::TextAnnotation( TextAnnotation::TextType type )
     : Annotation( *new TextAnnotationPrivate() )
-{}
+{
+    setTextType( type );
+}
 
 TextAnnotation::TextAnnotation(TextAnnotationPrivate &dd)
     : Annotation( dd )
@@ -850,12 +1413,14 @@ TextAnnotation::TextAnnotation( const QDomNode & node )
             }
             else if ( ee.tagName() == "callout" )
             {
-                setCalloutPoint(0, QPointF(ee.attribute( "ax" ).toDouble(),
-                                           ee.attribute( "ay" ).toDouble()));
-                setCalloutPoint(1, QPointF(ee.attribute( "bx" ).toDouble(),
-                                           ee.attribute( "by" ).toDouble()));
-                setCalloutPoint(2, QPointF(ee.attribute( "cx" ).toDouble(),
-                                           ee.attribute( "cy" ).toDouble()));
+                QVector<QPointF> points(3);
+                points[0] = QPointF(ee.attribute( "ax" ).toDouble(),
+                                    ee.attribute( "ay" ).toDouble());
+                points[1] = QPointF(ee.attribute( "bx" ).toDouble(),
+                                    ee.attribute( "by" ).toDouble());
+                points[2] = QPointF(ee.attribute( "cx" ).toDouble(),
+                                    ee.attribute( "cy" ).toDouble());
+                setCalloutPoints(points);
             }
         }
 
@@ -920,91 +1485,217 @@ Annotation::SubType TextAnnotation::subType() const
 TextAnnotation::TextType TextAnnotation::textType() const
 {
     Q_D( const TextAnnotation );
-    return d->textType;
+
+    if (!d->pdfAnnot)
+        return d->textType;
+
+    return d->pdfAnnot->getType() == Annot::typeText ?
+        TextAnnotation::Linked : TextAnnotation::InPlace;
 }
 
 void TextAnnotation::setTextType( TextAnnotation::TextType type )
 {
     Q_D( TextAnnotation );
-    d->textType = type;
+
+    if (!d->pdfAnnot)
+    {
+        d->textType = type;
+        return;
+    }
+
+    // Type cannot be changed if annotation is already tied
 }
 
 QString TextAnnotation::textIcon() const
 {
     Q_D( const TextAnnotation );
-    return d->textIcon;
+
+    if (!d->pdfAnnot)
+        return d->textIcon;
+
+    if (d->pdfAnnot->getType() == Annot::typeText)
+    {
+        const AnnotText * textann = static_cast<const AnnotText*>(d->pdfAnnot);
+        return QString::fromLatin1( textann->getIcon()->getCString() );
+    }
+
+    return QString();
 }
 
 void TextAnnotation::setTextIcon( const QString &icon )
 {
     Q_D( TextAnnotation );
-    d->textIcon = icon;
+
+    if (!d->pdfAnnot)
+    {
+        d->textIcon = icon;
+        return;
+    }
+
+    // TODO: Set pdfAnnot
 }
 
 QFont TextAnnotation::textFont() const
 {
     Q_D( const TextAnnotation );
-    return d->textFont;
+
+    if (!d->pdfAnnot)
+        return d->textFont;
+
+    return QFont(); // TODO: AnnotFreeText::getAppearanceString
 }
 
 void TextAnnotation::setTextFont( const QFont &font )
 {
     Q_D( TextAnnotation );
-    d->textFont = font;
+
+    if (!d->pdfAnnot)
+    {
+        d->textFont = font;
+        return;
+    }
+
+    // TODO: Set pdfAnnot
 }
 
 int TextAnnotation::inplaceAlign() const
 {
     Q_D( const TextAnnotation );
-    return d->inplaceAlign;
+
+    if (!d->pdfAnnot)
+        return d->inplaceAlign;
+
+    if (d->pdfAnnot->getType() == Annot::typeFreeText)
+    {
+        const AnnotFreeText * ftextann = static_cast<const AnnotFreeText*>(d->pdfAnnot);
+        return ftextann->getQuadding();
+    }
+
+    return 0;
 }
 
 void TextAnnotation::setInplaceAlign( int align )
 {
     Q_D( TextAnnotation );
-    d->inplaceAlign = align;
+
+    if (!d->pdfAnnot)
+    {
+        d->inplaceAlign = align;
+        return;
+    }
+
+    // TODO: Set pdfAnnot
 }
 
 QString TextAnnotation::inplaceText() const
 {
     Q_D( const TextAnnotation );
-    return d->inplaceText;
+
+    if (!d->pdfAnnot)
+        return d->inplaceText;
+
+    if (d->pdfAnnot->getType() == Annot::typeFreeText)
+    {
+        const AnnotFreeText * ftextann = static_cast<const AnnotFreeText*>(d->pdfAnnot);
+        QString tmpstring;
+        GooString *styleString = ftextann->getStyleString();
+
+        if (styleString)
+            return UnicodeParsedString( styleString );
+    }
+
+    return QString();
 }
 
 void TextAnnotation::setInplaceText( const QString &text )
 {
     Q_D( TextAnnotation );
-    d->inplaceText = text;
+
+    if (!d->pdfAnnot)
+    {
+        d->inplaceText = text;
+        return;
+    }
+
+    // TODO: Set pdfAnnot
 }
 
 QPointF TextAnnotation::calloutPoint( int id ) const
 {
-    if ( id < 0 || id >= 3 )
+    const QVector<QPointF> points = calloutPoints();
+    if ( id < 0 || id >= points.size() )
         return QPointF();
+    else
+        return points[id];
+}
 
+QVector<QPointF> TextAnnotation::calloutPoints() const
+{
     Q_D( const TextAnnotation );
-    return d->inplaceCallout[id];
+
+    if (!d->pdfAnnot)
+        return d->inplaceCallout;
+
+    if (d->pdfAnnot->getType() == Annot::typeText)
+        return QVector<QPointF>();
+
+    const AnnotFreeText * ftextann = static_cast<const AnnotFreeText*>(d->pdfAnnot);
+    const AnnotCalloutLine *callout = ftextann->getCalloutLine();
+
+    if (!callout)
+        return QVector<QPointF>();
+
+    double MTX[6];
+    d->fillMTX(MTX);
+
+    const AnnotCalloutMultiLine * callout_v6 = dynamic_cast<const AnnotCalloutMultiLine*>(callout);
+    QVector<QPointF> res(callout_v6 ? 3 : 2);
+    XPDFReader::transform(MTX, callout->getX1(), callout->getY1(), res[0]);
+    XPDFReader::transform(MTX, callout->getX2(), callout->getY2(), res[1]);
+    if (callout_v6)
+        XPDFReader::transform(MTX, callout_v6->getX3(), callout_v6->getY3(), res[2]);
+    return res;
 }
 
-void TextAnnotation::setCalloutPoint( int id, const QPointF &point )
+void TextAnnotation::setCalloutPoints( const QVector<QPointF> &points )
 {
-    if ( id < 0 || id >= 3 )
+    Q_D( TextAnnotation );
+    if (!d->pdfAnnot)
+    {
+        d->inplaceCallout = points;
         return;
+    }
 
-    Q_D( TextAnnotation );
-    d->inplaceCallout[id] = point;
+    // TODO: Set pdfAnnot
 }
 
 TextAnnotation::InplaceIntent TextAnnotation::inplaceIntent() const
 {
     Q_D( const TextAnnotation );
-    return d->inplaceIntent;
+
+    if (!d->pdfAnnot)
+        return d->inplaceIntent;
+
+    if (d->pdfAnnot->getType() == Annot::typeFreeText)
+    {
+        const AnnotFreeText * ftextann = static_cast<const AnnotFreeText*>(d->pdfAnnot);
+        return (TextAnnotation::InplaceIntent)ftextann->getIntent();
+    }
+
+    return TextAnnotation::Unknown;
 }
 
 void TextAnnotation::setInplaceIntent( TextAnnotation::InplaceIntent intent )
 {
     Q_D( TextAnnotation );
-    d->inplaceIntent = intent;
+
+    if (d->pdfAnnot)
+    {
+        d->inplaceIntent = intent;
+        return;
+    }
+
+    // TODO: Set pdfAnnot
 }
 
 
@@ -1021,6 +1712,7 @@ class LineAnnotationPrivate : public AnnotationPrivate
         LineAnnotation::TermStyle lineEndStyle;
         bool lineClosed : 1;  // (if true draw close shape)
         bool lineShowCaption : 1;
+        LineAnnotation::LineType lineType;
         QColor lineInnerColor;
         double lineLeadingFwdPt;
         double lineLeadingBackPt;
@@ -1030,8 +1722,8 @@ class LineAnnotationPrivate : public AnnotationPrivate
 LineAnnotationPrivate::LineAnnotationPrivate()
     : AnnotationPrivate(), lineStartStyle( LineAnnotation::None ),
     lineEndStyle( LineAnnotation::None ), lineClosed( false ),
-    lineShowCaption( false ), lineLeadingFwdPt( 0 ), lineLeadingBackPt( 0 ),
-    lineIntent( LineAnnotation::Unknown )
+    lineShowCaption( false ), lineLeadingFwdPt( 0 ),
+    lineLeadingBackPt( 0 ), lineIntent( LineAnnotation::Unknown )
 {
 }
 
@@ -1040,9 +1732,11 @@ Annotation * LineAnnotationPrivate::makeAlias()
     return new LineAnnotation(*this);
 }
 
-LineAnnotation::LineAnnotation()
+LineAnnotation::LineAnnotation( LineAnnotation::LineType type )
     : Annotation( *new LineAnnotationPrivate() )
-{}
+{
+    setLineType(type);
+}
 
 LineAnnotation::LineAnnotation(LineAnnotationPrivate &dd)
     : Annotation( dd )
@@ -1093,6 +1787,7 @@ LineAnnotation::LineAnnotation( const QDomNode & node )
             points.append( p );
         }
         setLinePoints(points);
+        setLineType(points.size() == 2 ? StraightLine : Polyline);
 
         // loading complete
         break;
@@ -1152,112 +1847,322 @@ Annotation::SubType LineAnnotation::subType() const
     return ALine;
 }
 
+LineAnnotation::LineType LineAnnotation::lineType() const
+{
+    Q_D( const LineAnnotation );
+
+    if (!d->pdfAnnot)
+        return d->lineType;
+
+    return (d->pdfAnnot->getType() == Annot::typeLine) ?
+        LineAnnotation::StraightLine : LineAnnotation::Polyline;
+}
+
+void LineAnnotation::setLineType( LineAnnotation::LineType type )
+{
+    Q_D( LineAnnotation );
+
+    if (!d->pdfAnnot)
+    {
+        d->lineType = type;
+        return;
+    }
+
+    // Type cannot be changed if annotation is already tied
+}
+
 QLinkedList<QPointF> LineAnnotation::linePoints() const
 {
     Q_D( const LineAnnotation );
-    return d->linePoints;
+
+    if (!d->pdfAnnot)
+        return d->linePoints;
+
+    double MTX[6];
+    d->fillMTX(MTX);
+
+    QLinkedList<QPointF> res;
+    if (d->pdfAnnot->getType() == Annot::typeLine)
+    {
+        const AnnotLine * lineann = static_cast<const AnnotLine*>(d->pdfAnnot);
+        QPointF p;
+        XPDFReader::transform(MTX, lineann->getX1(), lineann->getY1(), p);
+        res.append(p);
+        XPDFReader::transform(MTX, lineann->getX2(), lineann->getY2(), p);
+        res.append(p);
+    }
+    else
+    {
+        const AnnotPolygon * polyann = static_cast<const AnnotPolygon*>(d->pdfAnnot);
+        const AnnotPath * vertices = polyann->getVertices();
+
+        for (int i = 0; i < vertices->getCoordsLength(); ++i)
+        {
+            QPointF p;
+            XPDFReader::transform(MTX, vertices->getX(i), vertices->getY(i), p);
+            res.append(p);
+        }
+    }
+
+    return res;
 }
 
 void LineAnnotation::setLinePoints( const QLinkedList<QPointF> &points )
 {
     Q_D( LineAnnotation );
-    d->linePoints = points;
+
+    if (!d->pdfAnnot)
+    {
+        d->linePoints = points;
+        return;
+    }
+
+    // TODO: Set pdfAnnot
 }
 
 LineAnnotation::TermStyle LineAnnotation::lineStartStyle() const
 {
     Q_D( const LineAnnotation );
-    return d->lineStartStyle;
+
+    if (!d->pdfAnnot)
+        return d->lineStartStyle;
+
+    if (d->pdfAnnot->getType() == Annot::typeLine)
+    {
+        const AnnotLine * lineann = static_cast<const AnnotLine*>(d->pdfAnnot);
+        return (LineAnnotation::TermStyle)lineann->getStartStyle();
+    }
+    else
+    {
+        const AnnotPolygon * polyann = static_cast<const AnnotPolygon*>(d->pdfAnnot);
+        return (LineAnnotation::TermStyle)polyann->getStartStyle();
+    }
 }
 
 void LineAnnotation::setLineStartStyle( LineAnnotation::TermStyle style )
 {
     Q_D( LineAnnotation );
-    d->lineStartStyle = style;
+
+    if (!d->pdfAnnot)
+    {
+        d->lineStartStyle = style;
+        return;
+    }
+
+    // TODO: Set pdfAnnot
 }
 
 LineAnnotation::TermStyle LineAnnotation::lineEndStyle() const
 {
     Q_D( const LineAnnotation );
-    return d->lineEndStyle;
+
+    if (!d->pdfAnnot)
+        return d->lineEndStyle;
+
+    if (d->pdfAnnot->getType() == Annot::typeLine)
+    {
+        const AnnotLine * lineann = static_cast<const AnnotLine*>(d->pdfAnnot);
+        return (LineAnnotation::TermStyle)lineann->getEndStyle();
+    }
+    else
+    {
+        const AnnotPolygon * polyann = static_cast<const AnnotPolygon*>(d->pdfAnnot);
+        return (LineAnnotation::TermStyle)polyann->getEndStyle();
+    }
 }
 
 void LineAnnotation::setLineEndStyle( LineAnnotation::TermStyle style )
 {
     Q_D( LineAnnotation );
-    d->lineEndStyle = style;
+
+    if (!d->pdfAnnot)
+    {
+        d->lineEndStyle = style;
+        return;
+    }
+
+    // TODO: Set pdfAnnot
 }
 
 bool LineAnnotation::isLineClosed() const
 {
     Q_D( const LineAnnotation );
-    return d->lineClosed;
+
+    if (!d->pdfAnnot)
+        return d->lineClosed;
+
+    return d->pdfAnnot->getType() == Annot::typePolygon;
 }
 
 void LineAnnotation::setLineClosed( bool closed )
 {
     Q_D( LineAnnotation );
-    d->lineClosed = closed;
+
+    if (!d->pdfAnnot)
+    {
+        d->lineClosed = closed;
+        return;
+    }
+
+    // TODO: Set pdfAnnot
 }
 
 QColor LineAnnotation::lineInnerColor() const
 {
     Q_D( const LineAnnotation );
-    return d->lineInnerColor;
+
+    if (!d->pdfAnnot)
+        return d->lineInnerColor;
+
+    AnnotColor * c;
+
+    if (d->pdfAnnot->getType() == Annot::typeLine)
+    {
+        const AnnotLine * lineann = static_cast<const AnnotLine*>(d->pdfAnnot);
+        c = lineann->getInteriorColor();
+    }
+    else
+    {
+        const AnnotPolygon * polyann = static_cast<const AnnotPolygon*>(d->pdfAnnot);
+        c = polyann->getInteriorColor();
+    }
+
+    return convertAnnotColor(c);
 }
 
 void LineAnnotation::setLineInnerColor( const QColor &color )
 {
     Q_D( LineAnnotation );
-    d->lineInnerColor = color;
+
+    if (!d->pdfAnnot)
+    {
+        d->lineInnerColor = color;
+        return;
+    }
+
+    // TODO: Set pdfAnnot
 }
 
 double LineAnnotation::lineLeadingForwardPoint() const
 {
     Q_D( const LineAnnotation );
-    return d->lineLeadingFwdPt;
+
+    if (!d->pdfAnnot)
+        return d->lineLeadingFwdPt;
+
+    if (d->pdfAnnot->getType() == Annot::typeLine)
+    {
+        const AnnotLine * lineann = static_cast<const AnnotLine*>(d->pdfAnnot);
+        return lineann->getLeaderLineLength();
+    }
+
+    return 0;
 }
 
 void LineAnnotation::setLineLeadingForwardPoint( double point )
 {
     Q_D( LineAnnotation );
-    d->lineLeadingFwdPt = point;
+
+    if (!d->pdfAnnot)
+    {
+        d->lineLeadingFwdPt = point;
+        return;
+    }
+
+    // TODO: Set pdfAnnot
 }
 
 double LineAnnotation::lineLeadingBackPoint() const
 {
     Q_D( const LineAnnotation );
-    return d->lineLeadingBackPt;
+
+    if (!d->pdfAnnot)
+        return d->lineLeadingBackPt;
+
+    if (d->pdfAnnot->getType() == Annot::typeLine)
+    {
+        const AnnotLine * lineann = static_cast<const AnnotLine*>(d->pdfAnnot);
+        return lineann->getLeaderLineExtension();
+    }
+
+    return 0;
 }
 
 void LineAnnotation::setLineLeadingBackPoint( double point )
 {
     Q_D( LineAnnotation );
-    d->lineLeadingBackPt = point;
+
+    if (!d->pdfAnnot)
+    {
+        d->lineLeadingBackPt = point;
+        return;
+    }
+
+    // TODO: Set pdfAnnot
 }
 
 bool LineAnnotation::lineShowCaption() const
 {
     Q_D( const LineAnnotation );
-    return d->lineShowCaption;
+
+    if (!d->pdfAnnot)
+        return d->lineShowCaption;
+
+    if (d->pdfAnnot->getType() == Annot::typeLine)
+    {
+        const AnnotLine * lineann = static_cast<const AnnotLine*>(d->pdfAnnot);
+        return lineann->getCaption();
+    }
+
+    return false;
 }
 
 void LineAnnotation::setLineShowCaption( bool show )
 {
     Q_D( LineAnnotation );
-    d->lineShowCaption = show;
+
+    if (!d->pdfAnnot)
+    {
+        d->lineShowCaption = show;
+        return;
+    }
+
+    // TODO: Set pdfAnnot
 }
 
 LineAnnotation::LineIntent LineAnnotation::lineIntent() const
 {
     Q_D( const LineAnnotation );
-    return d->lineIntent;
+
+    if (!d->pdfAnnot)
+        return d->lineIntent;
+
+    if (d->pdfAnnot->getType() == Annot::typeLine)
+    {
+        const AnnotLine * lineann = static_cast<const AnnotLine*>(d->pdfAnnot);
+        return (LineAnnotation::LineIntent)( lineann->getIntent() + 1 );
+    }
+    else
+    {
+        const AnnotPolygon * polyann = static_cast<const AnnotPolygon*>(d->pdfAnnot);
+        if ( polyann->getIntent() == AnnotPolygon::polygonCloud )
+            return LineAnnotation::PolygonCloud;
+        else // AnnotPolygon::polylineDimension, AnnotPolygon::polygonDimension
+            return LineAnnotation::Dimension;
+    }
 }
 
 void LineAnnotation::setLineIntent( LineAnnotation::LineIntent intent )
 {
     Q_D( LineAnnotation );
-    d->lineIntent = intent;
+
+    if (!d->pdfAnnot)
+    {
+        d->lineIntent = intent;
+        return;
+    }
+
+    // TODO: Set pdfAnnot
 }
 
 
@@ -1342,25 +2247,51 @@ Annotation::SubType GeomAnnotation::subType() const
 GeomAnnotation::GeomType GeomAnnotation::geomType() const
 {
     Q_D( const GeomAnnotation );
-    return d->geomType;
+
+    if (!d->pdfAnnot)
+        return d->geomType;
+
+    if (d->pdfAnnot->getType() == Annot::typeSquare)
+        return GeomAnnotation::InscribedSquare;
+    else // Annot::typeCircle
+        return GeomAnnotation::InscribedCircle;
 }
 
 void GeomAnnotation::setGeomType( GeomAnnotation::GeomType type )
 {
     Q_D( GeomAnnotation );
-    d->geomType = type;
+
+    if (!d->pdfAnnot)
+    {
+        d->geomType = type;
+        return;
+    }
+
+    // TODO: Set pdfAnnot
 }
 
 QColor GeomAnnotation::geomInnerColor() const
 {
     Q_D( const GeomAnnotation );
-    return d->geomInnerColor;
+
+    if (!d->pdfAnnot)
+        return d->geomInnerColor;
+
+    const AnnotGeometry * geomann = static_cast<const AnnotGeometry*>(d->pdfAnnot);
+    return convertAnnotColor( geomann->getInteriorColor() );
 }
 
 void GeomAnnotation::setGeomInnerColor( const QColor &color )
 {
     Q_D( GeomAnnotation );
-    d->geomInnerColor = color;
+
+    if (!d->pdfAnnot)
+    {
+        d->geomInnerColor = color;
+        return;
+    }
+
+    // TODO: Set pdfAnnot
 }
 
 
@@ -1374,6 +2305,9 @@ class HighlightAnnotationPrivate : public AnnotationPrivate
         // data fields
         HighlightAnnotation::HighlightType highlightType;
         QList< HighlightAnnotation::Quad > highlightQuads; // not empty
+
+        // helpers
+        QList< HighlightAnnotation::Quad > fromQuadrilaterals(AnnotQuadrilaterals *quads) const;
 };
 
 HighlightAnnotationPrivate::HighlightAnnotationPrivate()
@@ -1386,6 +2320,39 @@ Annotation * HighlightAnnotationPrivate::makeAlias()
     return new HighlightAnnotation(*this);
 }
 
+QList< HighlightAnnotation::Quad > HighlightAnnotationPrivate::fromQuadrilaterals(AnnotQuadrilaterals *hlquads) const
+{
+    QList< HighlightAnnotation::Quad > quads;
+
+    if ( !hlquads || !hlquads->getQuadrilateralsLength() )
+        return quads;
+    const int quadsCount = hlquads->getQuadrilateralsLength();
+
+    double MTX[6];
+    fillMTX(MTX);
+
+    for (int q = 0; q < quadsCount; ++q)
+    {
+        HighlightAnnotation::Quad quad;
+        XPDFReader::transform( MTX, hlquads->getX1( q ), hlquads->getY1( q ), quad.points[ 0 ] );
+        XPDFReader::transform( MTX, hlquads->getX2( q ), hlquads->getY2( q ), quad.points[ 1 ] );
+        XPDFReader::transform( MTX, hlquads->getX3( q ), hlquads->getY3( q ), quad.points[ 2 ] );
+        XPDFReader::transform( MTX, hlquads->getX4( q ), hlquads->getY4( q ), quad.points[ 3 ] );
+        // ### PDF1.6 specs says that point are in ccw order, but in fact
+        // points 3 and 4 are swapped in every PDF around!
+        QPointF tmpPoint = quad.points[ 2 ];
+        quad.points[ 2 ] = quad.points[ 3 ];
+        quad.points[ 3 ] = tmpPoint;
+        // initialize other properties and append quad
+        quad.capStart = true;       // unlinked quads are always capped
+        quad.capEnd = true;         // unlinked quads are always capped
+        quad.feather = 0.1;         // default feather
+        quads.append( quad );
+    }
+
+    return quads;
+}
+
 HighlightAnnotation::HighlightAnnotation()
     : Annotation( *new HighlightAnnotationPrivate() )
 {}
@@ -1491,25 +2458,57 @@ Annotation::SubType HighlightAnnotation::subType() const
 HighlightAnnotation::HighlightType HighlightAnnotation::highlightType() const
 {
     Q_D( const HighlightAnnotation );
-    return d->highlightType;
+
+    if (!d->pdfAnnot)
+        return d->highlightType;
+
+    Annot::AnnotSubtype subType = d->pdfAnnot->getType();
+
+    if ( subType == Annot::typeHighlight )
+        return HighlightAnnotation::Highlight;
+    else if ( subType == Annot::typeUnderline )
+        return HighlightAnnotation::Underline;
+    else if ( subType == Annot::typeSquiggly )
+        return HighlightAnnotation::Squiggly;
+    else // Annot::typeStrikeOut
+        return HighlightAnnotation::StrikeOut;
 }
 
 void HighlightAnnotation::setHighlightType( HighlightAnnotation::HighlightType type )
 {
     Q_D( HighlightAnnotation );
-    d->highlightType = type;
+
+    if (!d->pdfAnnot)
+    {
+        d->highlightType = type;
+        return;
+    }
+
+    // TODO: Set pdfAnnot
 }
 
 QList< HighlightAnnotation::Quad > HighlightAnnotation::highlightQuads() const
 {
     Q_D( const HighlightAnnotation );
-    return d->highlightQuads;
+
+    if (!d->pdfAnnot)
+        return d->highlightQuads;
+
+    const AnnotTextMarkup * hlann = static_cast<AnnotTextMarkup*>(d->pdfAnnot);
+    return d->fromQuadrilaterals( hlann->getQuadrilaterals() );
 }
 
 void HighlightAnnotation::setHighlightQuads( const QList< HighlightAnnotation::Quad > &quads )
 {
     Q_D( HighlightAnnotation );
-    d->highlightQuads = quads;
+
+    if (!d->pdfAnnot)
+    {
+        d->highlightQuads = quads;
+        return;
+    }
+
+    // TODO: Set pdfAnnot
 }
 
 
@@ -1589,13 +2588,25 @@ Annotation::SubType StampAnnotation::subType() const
 QString StampAnnotation::stampIconName() const
 {
     Q_D( const StampAnnotation );
-    return d->stampIconName;
+
+    if (!d->pdfAnnot)
+        return d->stampIconName;
+
+    const AnnotStamp * stampann = static_cast<const AnnotStamp*>(d->pdfAnnot);
+    return QString::fromLatin1( stampann->getIcon()->getCString() );
 }
 
 void StampAnnotation::setStampIconName( const QString &name )
 {
     Q_D( StampAnnotation );
-    d->stampIconName = name;
+
+    if (!d->pdfAnnot)
+    {
+        d->stampIconName = name;
+        return;
+    }
+
+    // TODO: Set pdfAnnot
 }
 
 /** InkAnnotation [Annotation] */
@@ -1718,14 +2729,51 @@ Annotation::SubType InkAnnotation::subType() const
 
 QList< QLinkedList<QPointF> > InkAnnotation::inkPaths() const
 {
-   Q_D( const InkAnnotation );
-   return d->inkPaths;
+    Q_D( const InkAnnotation );
+
+    if (!d->pdfAnnot)
+        return d->inkPaths;
+
+    const AnnotInk * inkann = static_cast<const AnnotInk *>(d->pdfAnnot);
+
+    const AnnotPath * const* paths = inkann->getInkList();
+    if ( !paths || !inkann->getInkListLength() )
+        return QList< QLinkedList<QPointF> >();
+
+    double MTX[6];
+    d->fillMTX(MTX);
+
+    const int pathsNumber = inkann->getInkListLength();
+    QList< QLinkedList<QPointF> > inkPaths;
+    for (int m = 0; m < pathsNumber; ++m)
+    {
+        // transform each path in a list of normalized points ..
+        QLinkedList<QPointF> localList;
+        const AnnotPath * path = paths[ m ];
+        const int pointsNumber = path ? path->getCoordsLength() : 0;
+        for (int n = 0; n < pointsNumber; ++n)
+        {
+            QPointF point;
+            XPDFReader::transform(MTX, path->getX(n), path->getY(n), point);
+            localList.append(point);
+        }
+        // ..and add it to the annotation
+        inkPaths.append( localList );
+    }
+    return inkPaths;
 }
 
 void InkAnnotation::setInkPaths( const QList< QLinkedList<QPointF> > &paths )
 {
-   Q_D( InkAnnotation );
-   d->inkPaths = paths;
+    Q_D( InkAnnotation );
+
+    if (!d->pdfAnnot)
+    {
+        d->inkPaths = paths;
+        return;
+    }
+
+    // TODO: Set pdfAnnot
 }
 
 
@@ -2145,13 +3193,25 @@ Annotation::SubType CaretAnnotation::subType() const
 CaretAnnotation::CaretSymbol CaretAnnotation::caretSymbol() const
 {
     Q_D( const CaretAnnotation );
-    return d->symbol;
+
+    if (!d->pdfAnnot)
+        return d->symbol;
+
+    const AnnotCaret * caretann = static_cast<const AnnotCaret *>(d->pdfAnnot);
+    return (CaretAnnotation::CaretSymbol)caretann->getSymbol();
 }
 
 void CaretAnnotation::setCaretSymbol( CaretAnnotation::CaretSymbol symbol )
 {
     Q_D( CaretAnnotation );
-    d->symbol = symbol;
+
+    if (!d->pdfAnnot)
+    {
+        d->symbol = symbol;
+        return;
+    }
+
+    // TODO: Set pdfAnnot
 }
 
 /** FileAttachmentAnnotation [Annotation] */
diff --git a/qt4/src/poppler-annotation.h b/qt4/src/poppler-annotation.h
index b760702..6ab969e 100644
--- a/qt4/src/poppler-annotation.h
+++ b/qt4/src/poppler-annotation.h
@@ -106,7 +106,6 @@ class POPPLER_QT4_EXPORT Annotation
 {
   friend class AnnotationUtils;
   friend class LinkMovie;
-  friend class Page;
 
   public:
     // enum definitions
@@ -308,28 +307,23 @@ class POPPLER_QT4_EXPORT Annotation
  */
 class POPPLER_QT4_EXPORT TextAnnotation : public Annotation
 {
-  friend class Page;
   friend class AnnotationUtils;
+  friend class AnnotationPrivate;
 
   public:
-    virtual ~TextAnnotation();
-    virtual SubType subType() const;
-
     // local enums
     enum TextType { Linked, InPlace };
     enum InplaceIntent { Unknown, Callout, TypeWriter };
 
+    virtual ~TextAnnotation();
+    virtual SubType subType() const;
+
     /**
        The type of text annotation represented by this object
     */
     TextType textType() const;
 
     /**
-       Set the type of text annotation represented by this object
-    */
-    void setTextType( TextType type );
-
-    /**
        The name of the icon for this text annotation.
 
        Standard names for text annotation icons are:
@@ -370,16 +364,20 @@ class POPPLER_QT4_EXPORT TextAnnotation : public Annotation
     void setInplaceText( const QString &text );
 
     QPointF calloutPoint( int id ) const;
-    void setCalloutPoint( int id, const QPointF &point );
+    /// \since 0.20
+    QVector<QPointF> calloutPoints() const;
+    /// \since 0.20
+    void setCalloutPoints( const QVector<QPointF> &points );
 
     InplaceIntent inplaceIntent() const;
     void setInplaceIntent( InplaceIntent intent );
 
   private:
-    TextAnnotation();
+    TextAnnotation( TextType type );
     TextAnnotation( const QDomNode &node );
     TextAnnotation( TextAnnotationPrivate &dd );
     virtual void store( QDomNode &parentNode, QDomDocument &document ) const;
+    void setTextType( TextType type );
     Q_DECLARE_PRIVATE( TextAnnotation )
     Q_DISABLE_COPY( TextAnnotation )
 };
@@ -391,18 +389,22 @@ class POPPLER_QT4_EXPORT TextAnnotation : public Annotation
  */
 class POPPLER_QT4_EXPORT LineAnnotation : public Annotation
 {
-  friend class Page;
   friend class AnnotationUtils;
+  friend class AnnotationPrivate;
 
   public:
-    virtual ~LineAnnotation();
-    virtual SubType subType() const;
-
     // local enums
+    /// \since 0.20
+    enum LineType { StraightLine, Polyline };
     enum TermStyle { Square, Circle, Diamond, OpenArrow, ClosedArrow, None,
                      Butt, ROpenArrow, RClosedArrow, Slash };
     enum LineIntent { Unknown, Arrow, Dimension, PolygonCloud };
 
+    virtual ~LineAnnotation();
+    virtual SubType subType() const;
+
+    LineType lineType() const;
+
     QLinkedList<QPointF> linePoints() const;
     void setLinePoints( const QLinkedList<QPointF> &points );
 
@@ -431,10 +433,11 @@ class POPPLER_QT4_EXPORT LineAnnotation : public Annotation
     void setLineIntent( LineIntent intent );
 
   private:
-    LineAnnotation();
+    LineAnnotation( LineType type );
     LineAnnotation( const QDomNode &node );
     LineAnnotation( LineAnnotationPrivate &dd );
     virtual void store( QDomNode &parentNode, QDomDocument &document ) const;
+    void setLineType( LineType type );
     Q_DECLARE_PRIVATE( LineAnnotation )
     Q_DISABLE_COPY( LineAnnotation )
 };
@@ -447,8 +450,8 @@ class POPPLER_QT4_EXPORT LineAnnotation : public Annotation
  */
 class POPPLER_QT4_EXPORT GeomAnnotation : public Annotation
 {
-  friend class Page;
   friend class AnnotationUtils;
+  friend class AnnotationPrivate;
 
   public:
     virtual ~GeomAnnotation();
@@ -479,8 +482,8 @@ class POPPLER_QT4_EXPORT GeomAnnotation : public Annotation
  */
 class POPPLER_QT4_EXPORT HighlightAnnotation : public Annotation
 {
-  friend class Page;
   friend class AnnotationUtils;
+  friend class AnnotationPrivate;
 
   public:
     virtual ~HighlightAnnotation();
@@ -546,8 +549,8 @@ class POPPLER_QT4_EXPORT HighlightAnnotation : public Annotation
  */
 class POPPLER_QT4_EXPORT StampAnnotation : public Annotation
 {
-  friend class Page;
   friend class AnnotationUtils;
+  friend class AnnotationPrivate;
 
   public:
     virtual ~StampAnnotation();
@@ -597,8 +600,8 @@ class POPPLER_QT4_EXPORT StampAnnotation : public Annotation
  */
 class POPPLER_QT4_EXPORT InkAnnotation : public Annotation
 {
-  friend class Page;
   friend class AnnotationUtils;
+  friend class AnnotationPrivate;
 
   public:
     virtual ~InkAnnotation();
@@ -618,7 +621,8 @@ class POPPLER_QT4_EXPORT InkAnnotation : public Annotation
 
 class POPPLER_QT4_EXPORT LinkAnnotation : public Annotation
 {
-  friend class Page;
+  friend class AnnotationUtils;
+  friend class AnnotationPrivate;
 
   public:
     virtual ~LinkAnnotation();
@@ -652,8 +656,8 @@ class POPPLER_QT4_EXPORT LinkAnnotation : public Annotation
  */
 class POPPLER_QT4_EXPORT CaretAnnotation : public Annotation
 {
-  friend class Page;
   friend class AnnotationUtils;
+  friend class AnnotationPrivate;
 
   public:
     virtual ~CaretAnnotation();
@@ -685,7 +689,7 @@ class POPPLER_QT4_EXPORT CaretAnnotation : public Annotation
  */
 class POPPLER_QT4_EXPORT FileAttachmentAnnotation : public Annotation
 {
-  friend class Page;
+  friend class AnnotationPrivate;
 
   public:
     virtual ~FileAttachmentAnnotation();
@@ -729,7 +733,7 @@ class POPPLER_QT4_EXPORT FileAttachmentAnnotation : public Annotation
  */
 class POPPLER_QT4_EXPORT SoundAnnotation : public Annotation
 {
-  friend class Page;
+  friend class AnnotationPrivate;
 
   public:
     virtual ~SoundAnnotation();
@@ -773,7 +777,7 @@ class POPPLER_QT4_EXPORT SoundAnnotation : public Annotation
  */
 class POPPLER_QT4_EXPORT MovieAnnotation : public Annotation
 {
-  friend class Page;
+  friend class AnnotationPrivate;
 
   public:
     virtual ~MovieAnnotation();
@@ -817,7 +821,7 @@ class POPPLER_QT4_EXPORT MovieAnnotation : public Annotation
  */
 class POPPLER_QT4_EXPORT ScreenAnnotation : public Annotation
 {
-  friend class Page;
+  friend class AnnotationPrivate;
 
   public:
     virtual ~ScreenAnnotation();
diff --git a/qt4/src/poppler-link.cc b/qt4/src/poppler-link.cc
index 9ee01fe..a4bc55b 100644
--- a/qt4/src/poppler-link.cc
+++ b/qt4/src/poppler-link.cc
@@ -645,7 +645,7 @@ class LinkMoviePrivate : public LinkPrivate
 	bool LinkMovie::isReferencedAnnotation( const MovieAnnotation *annotation ) const
 	{
 		Q_D( const LinkMovie );
-		if ( d->annotationReference.num != -1 && d->annotationReference == annotation->d_ptr->pdfObjectReference )
+		if ( d->annotationReference.num != -1 && d->annotationReference == annotation->d_ptr->pdfObjectReference() )
 		{
 			return true;
 		}
diff --git a/qt4/src/poppler-page.cc b/qt4/src/poppler-page.cc
index 924c646..931d22e 100644
--- a/qt4/src/poppler-page.cc
+++ b/qt4/src/poppler-page.cc
@@ -44,7 +44,6 @@
 #include <TextOutputDev.h>
 #include <Annot.h>
 #include <Link.h>
-#include <FileSpec.h>
 #include <ArthurOutputDev.h>
 #include <Rendition.h>
 #if defined(HAVE_SPLASH)
@@ -56,7 +55,6 @@
 #include "poppler-page-transition-private.h"
 #include "poppler-page-private.h"
 #include "poppler-link-extractor-private.h"
-#include "poppler-annotation-helper.h"
 #include "poppler-annotation-private.h"
 #include "poppler-form.h"
 #include "poppler-media.h"
@@ -575,781 +573,7 @@ QList<Link*> Page::links() const
 
 QList<Annotation*> Page::annotations() const
 {
-    ::Page *pdfPage = m_page->page;
-    Annots* annots = pdfPage->getAnnots();
-    const uint numAnnotations = annots->getNumAnnots();
-    if ( numAnnotations == 0 )
-    {
-        return QList<Annotation*>();
-    }
-
-    // ID to Annotation/PopupWindow maps
-    QMap< int, Annotation * > annotationsMap;
-    QHash< AnnotPopup *, PopupWindow * > popupsMap;
-    // lists of Windows and Revisions that needs resolution
-    QLinkedList< ResolveRevision > resolveRevList;
-    QLinkedList< ResolveWindow > resolvePopList;
-    QLinkedList< PostProcessText > ppTextList;
-
-    // build a normalized transform matrix for this page at 100% scale
-    GfxState * gfxState = new GfxState( 72.0, 72.0, pdfPage->getCropBox(), pdfPage->getRotate(), gTrue );
-    double * gfxCTM = gfxState->getCTM();
-    double MTX[6];
-    for ( int i = 0; i < 6; i+=2 )
-    {
-        MTX[i] = gfxCTM[i] / pdfPage->getCropWidth();
-        MTX[i+1] = gfxCTM[i+1] / pdfPage->getCropHeight();
-    }
-    delete gfxState;
-
-    /** 1 - PARSE ALL ANNOTATIONS AND POPUPS FROM THE PAGE */
-    for ( uint j = 0; j < numAnnotations; j++ )
-    {
-        // get the j-th annotation
-        Annot * ann = annots->getAnnot( j );
-        if ( !ann )
-        {
-            qDebug() << "Annot" << j << "is null.";
-            continue;
-        }
-
-        Annotation * annotation = 0;
-        int annotID = ann->getId();
-        AnnotMarkup * markupann = dynamic_cast< AnnotMarkup * >( ann );
-        bool addToPage = true;      // Popup annots are added to custom queue
-
-        /** 1.1. GET Subtype */
-        Annot::AnnotSubtype subType = ann->getType();
-
-        /** 1.2. CREATE Annotation / PopupWindow and PARSE specific params */
-        switch ( subType )
-        {
-            case Annot::typeText:
-            {
-                // parse TextAnnotation params
-                AnnotText * textann = static_cast< AnnotText * >( ann );
-                TextAnnotation * t = new TextAnnotation();
-                annotation = t;
-                // -> textType
-                t->setTextType( TextAnnotation::Linked );
-                // -> textIcon
-                t->setTextIcon( QString::fromLatin1( textann->getIcon()->getCString() ) );
-                // request for postprocessing window geometry
-                PostProcessText request;
-                request.textAnnotation = t;
-                request.opened = textann->getOpen();
-                ppTextList.append( request );
-                break;
-            }
-            case Annot::typeFreeText:
-            {
-                // parse TextAnnotation params
-                AnnotFreeText * textann = static_cast< AnnotFreeText * >( ann );
-                TextAnnotation * t = new TextAnnotation();
-                annotation = t;
-                // -> textType
-                t->setTextType( TextAnnotation::InPlace );
-#if 0
-                // -> textFont
-                QString textFormat;
-                XPDFReader::lookupString( annotDict, "DA", textFormat );
-                // TODO, fill t->textFont using textFormat if not empty
-#endif
-                // -> inplaceAlign
-                t->setInplaceAlign( textann->getQuadding() );
-                // -> inplaceText (simple)
-                QString tmpstring;
-                GooString *styleString = textann->getStyleString();
-                if ( styleString )
-                    tmpstring = UnicodeParsedString( styleString );
-#if 0
-                // -> inplaceText (complex override)
-                XPDFReader::lookupString( annotDict, "RC", tmpstring );
-#endif
-                t->setInplaceText( tmpstring );
-                // -> inplaceCallout
-                AnnotCalloutLine *callout = textann->getCalloutLine();
-                if ( callout )
-                {
-                    QPointF tmppoint;
-                    XPDFReader::transform( MTX, callout->getX1(), callout->getY1(), tmppoint );
-                    t->setCalloutPoint( 0, tmppoint );
-                    XPDFReader::transform( MTX, callout->getX2(), callout->getY2(), tmppoint );
-                    t->setCalloutPoint( 1, tmppoint );
-                    if ( AnnotCalloutMultiLine * callout_v6 = dynamic_cast< AnnotCalloutMultiLine * >( callout ) )
-                    {
-                        XPDFReader::transform( MTX, callout_v6->getX3(), callout_v6->getY3(), tmppoint );
-                        t->setCalloutPoint( 2, tmppoint );
-                    }
-                }
-                // -> inplaceIntent
-                t->setInplaceIntent( (TextAnnotation::InplaceIntent)textann->getIntent() );
-                AnnotBorderEffect *border_effect = textann->getBorderEffect();
-                if ( border_effect )
-                {
-                    // -> style.effect
-                    t->d_ptr->style.setLineEffect( (Annotation::LineEffect)border_effect->getEffectType() );
-                    // -> style.effectIntensity
-                    t->d_ptr->style.setEffectIntensity( (int)border_effect->getIntensity() );
-                }
-                break;
-            }
-            case Annot::typeLine:
-            {
-                // parse LineAnnotation params
-                AnnotLine * lineann = static_cast< AnnotLine * >( ann );
-                LineAnnotation * l = new LineAnnotation();
-                annotation = l;
-
-                // -> linePoints
-                QLinkedList<QPointF> linePoints;
-                QPointF p;
-                XPDFReader::transform( MTX, lineann->getX1(), lineann->getY1(), p );
-                linePoints.push_back( p );
-                XPDFReader::transform( MTX, lineann->getX2(), lineann->getY2(), p );
-                linePoints.push_back( p );
-                l->setLinePoints( linePoints );
-                // -> lineStartStyle
-                l->setLineStartStyle( (LineAnnotation::TermStyle)lineann->getStartStyle() );
-                // -> lineEndStyle
-                l->setLineEndStyle( (LineAnnotation::TermStyle)lineann->getEndStyle() );
-                // -> lineClosed
-                l->setLineClosed( false );
-                // -> lineInnerColor
-                l->setLineInnerColor( convertAnnotColor( lineann->getInteriorColor() ) );
-                // -> lineLeadingFwdPt
-                l->setLineLeadingForwardPoint( lineann->getLeaderLineLength() );
-                // -> lineLeadingBackPt
-                l->setLineLeadingBackPoint( lineann->getLeaderLineExtension() );
-                // -> lineShowCaption
-                l->setLineShowCaption( lineann->getCaption() );
-                // -> lineIntent
-                l->setLineIntent( (LineAnnotation::LineIntent)( lineann->getIntent() + 1 ) );
-                break;
-            }
-            case Annot::typePolygon:
-            case Annot::typePolyLine:
-            {
-                // parse LineAnnotation params
-                AnnotPolygon * polyann = static_cast< AnnotPolygon * >( ann );
-                LineAnnotation * l = new LineAnnotation();
-                annotation = l;
-
-                // -> polyPoints
-                QLinkedList<QPointF> polyPoints;
-                AnnotPath * vertices = polyann->getVertices();
-                for ( int i = 0; i < vertices->getCoordsLength(); ++i )
-                {
-                    QPointF p;
-                    XPDFReader::transform( MTX, vertices->getX( i ), vertices->getY( i ), p );
-                    polyPoints.push_back( p );
-                }
-                l->setLinePoints( polyPoints );
-                // -> polyStartStyle
-                l->setLineStartStyle( (LineAnnotation::TermStyle)polyann->getStartStyle() );
-                // -> polyEndStyle
-                l->setLineEndStyle( (LineAnnotation::TermStyle)polyann->getEndStyle() );
-                // -> polyClosed
-                l->setLineClosed( subType == Annot::typePolygon );
-                // -> polyInnerColor
-                l->setLineInnerColor( convertAnnotColor( polyann->getInteriorColor() ) );
-                // -> polyIntent
-                switch ( polyann->getIntent() )
-                {
-                    case AnnotPolygon::polygonCloud:
-                        l->setLineIntent( LineAnnotation::PolygonCloud );
-                        break;
-                    case AnnotPolygon::polylineDimension:
-                    case AnnotPolygon::polygonDimension:
-                        l->setLineIntent( LineAnnotation::Dimension );
-                        break;
-                }
-                break;
-            }
-            case Annot::typeSquare:
-            case Annot::typeCircle:
-            {
-                // parse GeomAnnotation params
-                AnnotGeometry * geomann = static_cast< AnnotGeometry * >( ann );
-                GeomAnnotation * g = new GeomAnnotation();
-                annotation = g;
-
-                // -> highlightType
-                if ( subType == Annot::typeSquare )
-                    g->setGeomType( GeomAnnotation::InscribedSquare );
-                else if ( subType == Annot::typeCircle )
-                    g->setGeomType( GeomAnnotation::InscribedCircle );
-
-                // -> geomInnerColor
-                g->setGeomInnerColor( convertAnnotColor( geomann->getInteriorColor() ) );
-
-                AnnotBorderEffect *border_effect = geomann->getBorderEffect();
-                if ( border_effect )
-                {
-                    // -> style.effect
-                    g->d_ptr->style.setLineEffect( (Annotation::LineEffect)border_effect->getEffectType() );
-                    // -> style.effectIntensity
-                    g->d_ptr->style.setEffectIntensity( (int)border_effect->getIntensity() );
-                }
-
-                // TODO RD
-
-                break;
-            }
-            case Annot::typeHighlight:
-            case Annot::typeUnderline:
-            case Annot::typeSquiggly:
-            case Annot::typeStrikeOut:
-            {
-                AnnotTextMarkup * hlann = static_cast< AnnotTextMarkup * >( ann );
-                HighlightAnnotation * h = new HighlightAnnotation();
-                annotation = h;
-
-                // -> highlightType
-                if ( subType == Annot::typeHighlight )
-                    h->setHighlightType( HighlightAnnotation::Highlight );
-                else if ( subType == Annot::typeUnderline )
-                    h->setHighlightType( HighlightAnnotation::Underline );
-                else if ( subType == Annot::typeSquiggly )
-                    h->setHighlightType( HighlightAnnotation::Squiggly );
-                else if ( subType == Annot::typeStrikeOut )
-                    h->setHighlightType( HighlightAnnotation::StrikeOut );
-
-                // -> highlightQuads
-                AnnotQuadrilaterals *hlquads = hlann->getQuadrilaterals();
-                if ( !hlquads || !hlquads->getQuadrilateralsLength() )
-                {
-                    qDebug() << "Not enough quads for a Highlight annotation.";
-                    delete annotation;
-                    continue;
-                }
-                QList< HighlightAnnotation::Quad > quads;
-                const int quadsCount = hlquads->getQuadrilateralsLength();
-                for ( int q = 0; q < quadsCount; ++q )
-                {
-                    HighlightAnnotation::Quad quad;
-                    XPDFReader::transform( MTX, hlquads->getX1( q ), hlquads->getY1( q ), quad.points[ 0 ] );
-                    XPDFReader::transform( MTX, hlquads->getX2( q ), hlquads->getY2( q ), quad.points[ 1 ] );
-                    XPDFReader::transform( MTX, hlquads->getX3( q ), hlquads->getY3( q ), quad.points[ 2 ] );
-                    XPDFReader::transform( MTX, hlquads->getX4( q ), hlquads->getY4( q ), quad.points[ 3 ] );
-                    // ### PDF1.6 specs says that point are in ccw order, but in fact
-                    // points 3 and 4 are swapped in every PDF around!
-                    QPointF tmpPoint = quad.points[ 2 ];
-                    quad.points[ 2 ] = quad.points[ 3 ];
-                    quad.points[ 3 ] = tmpPoint;
-                    // initialize other properties and append quad
-                    quad.capStart = true;       // unlinked quads are always capped
-                    quad.capEnd = true;         // unlinked quads are always capped
-                    quad.feather = 0.1;         // default feather
-                    quads.append( quad );
-                }
-                h->setHighlightQuads( quads );
-                break;
-            }
-            case Annot::typeStamp:
-            {
-                AnnotStamp * stampann = static_cast< AnnotStamp * >( ann );
-                StampAnnotation * s = new StampAnnotation();
-                annotation = s;
-                // -> stampIcon
-                s->setStampIconName( QString::fromLatin1( stampann->getIcon()->getCString() ) );
-                break;
-            }
-            case Annot::typeInk:
-            {
-                // parse InkAnnotation params
-                AnnotInk * inkann = static_cast< AnnotInk * >( ann );
-                InkAnnotation * k = new InkAnnotation();
-                annotation = k;
-
-                // -> inkPaths
-                AnnotPath ** paths = inkann->getInkList();
-                if ( !paths || !inkann->getInkListLength() )
-                {
-                    qDebug() << "InkList not present for ink annot";
-                    delete annotation;
-                    continue;
-                }
-                QList< QLinkedList<QPointF> > inkPaths;
-                const int pathsNumber = inkann->getInkListLength();
-                for ( int m = 0; m < pathsNumber; m++ )
-                {
-                    // transform each path in a list of normalized points ..
-                    QLinkedList<QPointF> localList;
-                    AnnotPath * path = paths[ m ];
-                    const int pointsNumber = path ? path->getCoordsLength() : 0;
-                    for ( int n = 0; n < pointsNumber; ++n )
-                    {
-                        // get the x,y numbers for current point
-                        double x = path->getX( n );
-                        double y = path->getY( n );
-                        // add normalized point to localList
-                        QPointF np;
-                        XPDFReader::transform( MTX, x, y, np );
-                        localList.push_back( np );
-                    }
-                    // ..and add it to the annotation
-                    inkPaths.push_back( localList );
-                }
-                k->setInkPaths( inkPaths );
-                break;
-            }
-            case Annot::typePopup:
-            {
-                AnnotPopup * popupann = static_cast< AnnotPopup * >( ann );
-
-                // create PopupWindow and add it to the popupsMap
-                PopupWindow * popup = new PopupWindow();
-                popupsMap[ popupann ] = popup;
-                addToPage = false;
-
-                // get window specific properties if any
-                popup->shown = popupann->getOpen();
-                // no need to parse parent annotation id
-                //XPDFReader::lookupIntRef( annotDict, "Parent", popup->... );
-
-                // pretend it's a GeomAnnotation for getting other parameters
-                popup->dummyAnnotation = new GeomAnnotation();
-                annotation = popup->dummyAnnotation;
-
-                break;
-            }
-            case Annot::typeLink:
-            {
-                // parse Link params
-                AnnotLink * linkann = static_cast< AnnotLink * >( ann );
-                LinkAnnotation * l = new LinkAnnotation();
-                annotation = l;
-
-                // -> hlMode
-                l->setLinkHighlightMode( (LinkAnnotation::HighlightMode)linkann->getLinkEffect() );
-
-                // -> link region
-                // TODO
-
-                // reading link action
-                if ( linkann->getAction() )
-                {
-                    Link * popplerLink = m_page->convertLinkActionToLink( linkann->getAction(), QRectF() );
-                    if ( popplerLink )
-                    {
-                        l->setLinkDestination( popplerLink );
-                    }
-                }
-
-                break;
-            }
-            case Annot::typeCaret:
-            {
-                // parse CaretAnnotation params
-                AnnotCaret * caretann = static_cast< AnnotCaret * >( ann );
-                CaretAnnotation * c = new CaretAnnotation();
-                annotation = c;
-
-                // -> caretSymbol
-                c->setCaretSymbol( (CaretAnnotation::CaretSymbol)caretann->getSymbol() );
-
-                // TODO RD
-
-                break;
-            }
-            case Annot::typeFileAttachment:
-            {
-                AnnotFileAttachment * attachann = static_cast< AnnotFileAttachment * >( ann );
-                FileAttachmentAnnotation * f = new FileAttachmentAnnotation();
-                annotation = f;
-                // -> fileIcon
-                f->setFileIconName( QString::fromLatin1( attachann->getName()->getCString() ) );
-                // -> embeddedFile
-                FileSpec *filespec = new FileSpec( attachann->getFile() );
-                f->setEmbeddedFile( new EmbeddedFile( *new EmbeddedFileData( filespec ) ) );
-                break;
-            }
-            case Annot::typeSound:
-            {
-                AnnotSound * soundann = static_cast< AnnotSound * >( ann );
-                SoundAnnotation * s = new SoundAnnotation();
-                annotation = s;
-
-                // -> soundIcon
-                s->setSoundIconName( QString::fromLatin1( soundann->getName()->getCString() ) );
-                // -> sound
-                s->setSound( new SoundObject( soundann->getSound() ) );
-
-                break;
-            }
-            case Annot::typeMovie:
-            {
-                AnnotMovie * movieann = static_cast< AnnotMovie * >( ann );
-                MovieAnnotation * m = new MovieAnnotation();
-                annotation = m;
-
-                // -> movie
-                MovieObject *movie = new MovieObject( movieann );
-                m->setMovie( movie );
-                // -> movieTitle
-                GooString * movietitle = movieann->getTitle();
-                if ( movietitle )
-                {
-                    m->setMovieTitle( QString::fromLatin1( movietitle->getCString() ) );
-                }
-
-                break;
-            }
-            case Annot::typeScreen:
-            {
-                AnnotScreen * screenann = static_cast< AnnotScreen * >( ann );
-
-                if (!screenann->getAction())
-                  continue;
-
-                ScreenAnnotation * s = new ScreenAnnotation();
-                annotation = s;
-
-                // -> screen
-                s->setAction( static_cast<Poppler::LinkRendition *>(m_page->convertLinkActionToLink( screenann->getAction(), QRectF() ) ) );
-
-                // -> screenTitle
-                GooString * screentitle = screenann->getTitle();
-                if ( screentitle )
-                    s->setScreenTitle( UnicodeParsedString( screentitle ) );
-
-                break;
-            }
-            // special case for ignoring unknwon annotations
-            case Annot::typeUnknown:
-                continue;
-            // handled as forms or some other way
-            case Annot::typeWidget:
-                continue;
-            default:
-            {
-#define CASE_FOR_TYPE( thetype ) \
-                    case Annot::type ## thetype: \
-                        type = #thetype ; \
-                        break;
-                QByteArray type;
-                switch ( subType )
-                {
-                    CASE_FOR_TYPE( Screen )
-                    CASE_FOR_TYPE( PrinterMark )
-                    CASE_FOR_TYPE( TrapNet )
-                    CASE_FOR_TYPE( Watermark )
-                    CASE_FOR_TYPE( 3D )
-                    default: type = QByteArray::number( subType );
-                }
-                // MISSING: Widget, Screen, PrinterMark, TrapNet, Watermark, 3D
-                qDebug() << "Annotation" << type.constData() << "not supported.";
-                continue;
-#undef CASE_FOR_TYPE
-            }
-        }
-
-        /** 1.3. PARSE common parameters */
-        // -> boundary
-        PDFRectangle *boundary = ann->getRect();
-        // transform annotation rect to uniform coords
-        QPointF topLeft, bottomRight;
-        XPDFReader::transform( MTX, boundary->x1, boundary->y1, topLeft );
-        XPDFReader::transform( MTX, boundary->x2, boundary->y2, bottomRight );
-        QRectF boundaryRect;
-        boundaryRect.setTopLeft(topLeft);
-        boundaryRect.setBottomRight(bottomRight);
-        if ( boundaryRect.left() > boundaryRect.right() )
-        {
-            double aux = boundaryRect.left();
-            boundaryRect.setLeft( boundaryRect.right() );
-            boundaryRect.setRight(aux);
-        }
-        if ( boundaryRect.top() > boundaryRect.bottom() )
-        {
-            double aux = boundaryRect.top();
-            boundaryRect.setTop( boundaryRect.bottom() );
-            boundaryRect.setBottom(aux);
-           //annotation->rUnscaledWidth = (r[2] > r[0]) ? r[2] - r[0] : r[0] - r[2];
-           //annotation->rUnscaledHeight = (r[3] > r[1]) ? r[3] - r[1] : r[1] - r[3];
-        }
-        annotation->setBoundary( boundaryRect );
-        // -> PDF object reference
-        annotation->d_ptr->pdfObjectReference = ann->getRef();
-        // -> contents
-        annotation->setContents( UnicodeParsedString( ann->getContents() ) );
-        // -> uniqueName
-        annotation->setUniqueName( UnicodeParsedString( ann->getName() ) );
-        // -> modifyDate (and -> creationDate)
-        GooString *modDate = ann->getModified();
-        if ( modDate )
-        {
-            annotation->setModificationDate( convertDate( modDate->getCString() ) );
-        }
-        if ( annotation->creationDate().isNull() && !annotation->modificationDate().isNull() )
-            annotation->setCreationDate( annotation->modificationDate() );
-        // -> flags: set the external attribute since it's embedded on file
-        int annoflags = 0;
-        annoflags |= Annotation::External;
-        // -> flags
-        int flags = ann->getFlags();
-        if ( flags & Annot::flagHidden )
-            annoflags |= Annotation::Hidden;
-        if ( flags & Annot::flagNoZoom )
-            annoflags |= Annotation::FixedSize;
-        if ( flags & Annot::flagNoRotate )
-            annoflags |= Annotation::FixedRotation;
-        if ( !( flags & Annot::flagPrint ) )
-            annoflags |= Annotation::DenyPrint;
-        if ( flags & Annot::flagReadOnly )
-            annoflags |= (Annotation::DenyWrite | Annotation::DenyDelete);
-        if ( flags & Annot::flagLocked )
-            annoflags |= Annotation::DenyDelete;
-        if ( flags & Annot::flagToggleNoView )
-            annoflags |= Annotation::ToggleHidingOnMouse;
-        annotation->setFlags( annoflags );
-        // -> style
-        AnnotBorder *border = ann->getBorder();
-        if ( border )
-        {
-            if ( border->getType() == AnnotBorder::typeArray )
-            {
-                AnnotBorderArray * border_array = static_cast< AnnotBorderArray * >( border );
-                // -> style.xCorners
-                annotation->d_ptr->style.setXCorners(border_array->getHorizontalCorner());
-                // -> style.yCorners
-                annotation->d_ptr->style.setYCorners(border_array->getVerticalCorner());
-            }
-            // -> style.width
-            annotation->d_ptr->style.setWidth(border->getWidth());
-            // -> style.style
-            annotation->d_ptr->style.setLineStyle((Annotation::LineStyle)( 1 << border->getStyle() ));
-#if 0
-            // -> style.marks and style.spaces
-            // TODO
-            Object dashArray;
-            bsObj.getDict()->lookup( "D", &dashArray );
-            if ( dashArray.isArray() )
-            {
-                int dashMarks = 3;
-                int dashSpaces = 0;
-                Object intObj;
-                dashArray.arrayGet( 0, &intObj );
-                if ( intObj.isInt() )
-                    dashMarks = intObj.getInt();
-                intObj.free();
-                dashArray.arrayGet( 1, &intObj );
-                if ( intObj.isInt() )
-                    dashSpaces = intObj.getInt();
-                intObj.free();
-                annotation->style.marks = dashMarks;
-                annotation->style.spaces = dashSpaces;
-            }
-#endif
-        }
-        // -> style.color
-        annotation->d_ptr->style.setColor(convertAnnotColor( ann->getColor() ));
-
-        /** 1.4. PARSE markup { common, Popup, Revision } parameters */
-        if ( markupann )
-        {
-            // -> creationDate
-            GooString *createDate = markupann->getDate();
-            if ( createDate )
-            {
-                annotation->setCreationDate( convertDate( createDate->getCString() ) );
-            }
-            // -> style.opacity
-            annotation->d_ptr->style.setOpacity( markupann->getOpacity() );
-            // -> window.title and author
-            annotation->d_ptr->popup.setTitle(UnicodeParsedString( markupann->getLabel() ));
-            annotation->setAuthor( annotation->d_ptr->popup.title() );
-            // -> window.summary
-            annotation->d_ptr->popup.setSummary(UnicodeParsedString( markupann->getSubject() ));
-#if 0
-            // -> window.text
-            // TODO
-            XPDFReader::lookupString( annotDict, "RC", annotation->window.text );
-#endif
-
-            // if a popup is referenced, schedule for resolving it later
-            AnnotPopup *popup = markupann->getPopup();
-            if ( popup )
-            {
-                ResolveWindow request;
-                request.popup = popup;
-                request.annotation = annotation;
-                resolvePopList.append( request );
-            }
-
-            // if an older version is referenced, schedule for reparenting
-            int parentID = markupann->getInReplyToID();
-            if ( parentID )
-            {
-                ResolveRevision request;
-                request.nextAnnotation = annotation;
-                request.nextAnnotationID = annotID;
-                request.prevAnnotationID = parentID;
-
-                // -> request.nextScope
-                request.nextScope = Annotation::Reply;
-                switch ( markupann->getReplyTo() )
-                {
-                    case AnnotMarkup::replyTypeR:
-                        request.nextScope = Annotation::Reply;
-                        break;
-                    case AnnotMarkup::replyTypeGroup:
-                        request.nextScope = Annotation::Group;
-                        break;
-                }
-
-                // -> revision.type (StateModel is deduced from type, not parsed)
-                request.nextType = Annotation::None;
-                if ( subType == Annot::typeText )
-                {
-                    AnnotText * textann = static_cast< AnnotText * >( ann );
-                    switch ( textann->getState() )
-                    {
-                        case AnnotText::stateMarked:
-                            request.nextType = Annotation::Marked;
-                            break;
-                        case AnnotText::stateUnmarked:
-                            request.nextType = Annotation::Unmarked;
-                            break;
-                        case AnnotText::stateAccepted:
-                            request.nextType = Annotation::Accepted;
-                            break;
-                        case AnnotText::stateRejected:
-                            request.nextType = Annotation::Rejected;
-                            break;
-                        case AnnotText::stateCancelled:
-                            request.nextType = Annotation::Cancelled;
-                            break;
-                        case AnnotText::stateCompleted:
-                            request.nextType = Annotation::Completed;
-                            break;
-                        case AnnotText::stateNone:
-                        case AnnotText::stateUnknown:
-                            ;
-                    }
-                }
-
-                // schedule for later reparenting
-                resolveRevList.append( request );
-            }
-        }
-
-        /** 1.5. ADD ANNOTATION to the annotationsMap  */
-        if ( addToPage )
-        {
-            if ( annotationsMap.contains( annotID ) )
-                qDebug() << "Clash for annotations with ID:" << annotID;
-            annotationsMap[ annotID ] = annotation;
-        }
-    } // end Annotation/PopupWindow parsing loop
-
-    /** 2 - RESOLVE POPUPS (popup.* -> annotation.window) */
-    if ( !resolvePopList.isEmpty() && !popupsMap.isEmpty() )
-    {
-        QLinkedList< ResolveWindow >::iterator it = resolvePopList.begin(),
-                                              end = resolvePopList.end();
-        for ( ; it != end; ++it )
-        {
-            const ResolveWindow & request = *it;
-            if ( !popupsMap.contains( request.popup ) )
-                // warn aboud problems in popup resolving logic
-                qDebug() << "Cannot resolve popup"
-                          << request.popup << ".";
-            else
-            {
-                // set annotation's window properties taking ones from popup
-                PopupWindow * pop = popupsMap[ request.popup ];
-                Annotation * pa = pop->dummyAnnotation;
-                Annotation * ann = request.annotation;
-
-                // transfer properties to Annotation's window
-                int flags = pa->flags() & (Annotation::Hidden |
-                    Annotation::FixedSize | Annotation::FixedRotation);
-                if ( !pop->shown )
-                    flags |= Annotation::Hidden;
-                ann->d_ptr->popup.setFlags(flags);
-
-                QRectF geom;
-                geom.setLeft(pa->boundary().left());
-                geom.setTop(pa->boundary().top());
-                geom.setWidth( pa->boundary().right() - pa->boundary().left() );
-                geom.setHeight( pa->boundary().bottom() - pa->boundary().top() );
-                ann->d_ptr->popup.setGeometry(geom);
-            }
-        }
-
-        // clear data
-        QHash< AnnotPopup *, PopupWindow * >::Iterator dIt = popupsMap.begin(), dEnd = popupsMap.end();
-        for ( ; dIt != dEnd; ++dIt )
-        {
-            PopupWindow * p = dIt.value();
-            delete p->dummyAnnotation;
-            delete p;
-        }
-    }
-
-    /** 3 - RESOLVE REVISIONS (parent.revisions.append( children )) */
-    if ( !resolveRevList.isEmpty() )
-    {
-        // append children to parents
-        QVarLengthArray< int > excludeIDs( resolveRevList.count() );   // can't even reach this size
-        int excludeIndex = 0;                       // index in excludeIDs array
-        QLinkedList< ResolveRevision >::iterator it = resolveRevList.begin(), end = resolveRevList.end();
-        for ( ; it != end; ++it )
-        {
-            const ResolveRevision & request = *it;
-            int parentID = request.prevAnnotationID;
-            if ( !annotationsMap.contains( parentID ) )
-                // warn about problems in reparenting logic
-                qDebug() << "Cannot reparent annotation to"
-                          << parentID << ".";
-            else
-            {
-                // add annotation as a reply to the parent annotation
-                Annotation *curr = request.nextAnnotation;
-                annotationsMap[ parentID ]->addRevision( curr, request.nextScope, request.nextType );
-                delete curr;
-                // exclude child annotation from being rooted in page
-                excludeIDs[ excludeIndex++ ] = request.nextAnnotationID;
-            }
-        }
-
-        // prevent children from being attached to page as roots
-        for ( int i = 0; i < excludeIndex; i++ )
-            annotationsMap.remove( excludeIDs[ i ] );
-    }
-
-    /** 4 - POSTPROCESS TextAnnotations (when window geom is embedded) */
-    if ( !ppTextList.isEmpty() )
-    {
-        QLinkedList< PostProcessText >::const_iterator it = ppTextList.begin(), end = ppTextList.end();
-        for ( ; it != end; ++it )
-        {
-            const PostProcessText & request = *it;
-            Annotation * reqann = request.textAnnotation;
-            int flags = reqann->d_ptr->popup.flags();
-            // if not present, 'create' the window in-place over the annotation
-            if ( flags == -1 )
-            {
-                // initialize window geometry to annotation's one
-                QPointF tl = reqann->boundary().topLeft();
-                QSizeF size = reqann->boundary().size();
-                if (tl.x() < 0) tl.setX(0);
-                if (tl.y() < 0) tl.setY(0);
-                reqann->d_ptr->popup.setGeometry( QRectF (tl, size) );
-                flags = 0;
-            }
-            // (pdf) if text is not 'opened', force window hiding. if the window
-            // was parsed from popup, the flag should already be set
-            if ( !request.opened && flags != -1 )
-                flags |= Annotation::Hidden;
-            reqann->d_ptr->popup.setFlags( flags );
-        }
-    }
-
-    /** 5 - finally RETURN ANNOTATIONS */
-    return annotationsMap.values();
+  return AnnotationPrivate::findAnnotations(m_page->page, m_page->parentDoc);
 }
 
 QList<FormField*> Page::formFields() const
diff --git a/qt4/src/poppler-qt4.h b/qt4/src/poppler-qt4.h
index 0b10194..62b2719 100644
--- a/qt4/src/poppler-qt4.h
+++ b/qt4/src/poppler-qt4.h
@@ -310,7 +310,7 @@ delete it;
     */
     class POPPLER_QT4_EXPORT EmbeddedFile {
 	friend class DocumentData;
-	friend class Page;
+	friend class AnnotationPrivate;
     public:
 	/// \cond PRIVATE
 	EmbeddedFile(EmbFile *embfile);
@@ -1677,7 +1677,7 @@ height = dummy.height();
        \since 0.10
     */
     class POPPLER_QT4_EXPORT MovieObject {
-    friend class Page;
+    friend class AnnotationPrivate;
     public:
 	/**
 	   The play mode for playing the movie
commit 73b91207649a81740183e2288809d3b84b52f595
Author: Fabio D'Urso <fabiodurso at hotmail.it>
Date:   Wed Mar 7 17:05:50 2012 +0100

    qt4: Changes to Annotation API (part 1/2)
    
    This is part 1/2 of a change in annotation API. It breaks both source and binary
    compatibility.
    
    Note that, even though DOM methods are partially modified by this patch, their
    output is 100% backward compatible. Therefore code relying only on DOM methods
    (i.e. AnnotationUtils methods) will keep working.
    
    1) Style and Popup container classes
    
    Style and Popup (previously known as Window) properties are now wrapped in
    container classes. In both of them, private data is implicitly shared.
    The old Window structure is removed, but an undocumented window field is still
    exported to make Okular 4.8.0 compile. It must not be used.
    
    2) Revisions
    
    The Annotation::Revision structure was removed, because it added an extra layer
    of indirection that can be avoided. Now revision scope and type are stored
    directly in the target Annotation, and Annotation::revisions() returns a list
    of pointers to child annotations.
    
    3) All constructors are temporarily made private
    
    This patch hides all constructors from user code. Subsequent patches will
    restore them in the same patch as their type-specific creation support.
    
    4) Minor fixes
        - Popup size was incorrectly stored as an integer value, now it's part of
          a QRectF.
        - Typo: LinkAnnotation::linkDestionation() --> linkDestination
        - Dash array is now exported as QVector<doubles> instead of a marks/spaces
          integer pair
        - GeomAnnotation's geometricalPointWidth removed, because it was never
          referenced and it doesn't exist in PDF specs
    
    5) AnnotationPrivate data is now explicitly shared
    Annotation private data has been rearranged so that it's now possible to
    uniformly give ownership of all Annotation objects to the caller.
    Previously Page::annotations() did leave ownership to user, but
    Annotation::revisions() didn't. Now both of them give ownership to user.

diff --git a/qt4/src/poppler-annotation-private.h b/qt4/src/poppler-annotation-private.h
index 80e93d3..7c63c7e 100644
--- a/qt4/src/poppler-annotation-private.h
+++ b/qt4/src/poppler-annotation-private.h
@@ -1,6 +1,7 @@
 /* poppler-link-extractor-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>
  *
  * 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
@@ -20,6 +21,8 @@
 #ifndef _POPPLER_ANNOTATION_PRIVATE_H_
 #define _POPPLER_ANNOTATION_PRIVATE_H_
 
+#include <QtCore/QSharedDataPointer>
+
 #include "poppler-annotation.h"
 
 #include <Object.h>
@@ -27,12 +30,16 @@
 namespace Poppler
 {
 
-class AnnotationPrivate
+class AnnotationPrivate : public QSharedData
 {
     public:
         AnnotationPrivate();
         virtual ~AnnotationPrivate();
 
+        /* Returns an Annotation of the right subclass whose d_ptr points to
+         * this AnnotationPrivate */
+        virtual Annotation * makeAlias() = 0;
+
         /* properties: contents related */
         QString author;
         QString contents;
@@ -44,7 +51,15 @@ class AnnotationPrivate
         int flags;
         QRectF boundary;
 
-        QLinkedList< Annotation::Revision > revisions;
+        /* style and popup */
+        Annotation::Style style;
+        Annotation::Popup popup;
+
+        /* revisions */
+        Annotation::RevScope revisionScope;
+        Annotation::RevType revisionType;
+        QList<Annotation*> revisions;
+
         Ref pdfObjectReference;
 };
 
diff --git a/qt4/src/poppler-annotation.cc b/qt4/src/poppler-annotation.cc
index 3faef27..b812737 100644
--- a/qt4/src/poppler-annotation.cc
+++ b/qt4/src/poppler-annotation.cc
@@ -2,6 +2,7 @@
  * Copyright (C) 2006, 2009 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>
  * Adapting code from
  *   Copyright (C) 2004 by Enrico Ros <eros.kde at email.it>
  *
@@ -21,6 +22,7 @@
  */
 
 // qt/kde includes
+#include <QtCore/QtAlgorithms>
 #include <QtXml/QDomElement>
 #include <QtGui/QColor>
 
@@ -48,26 +50,27 @@ Annotation * AnnotationUtils::createAnnotation( const QDomElement & annElement )
     int typeNumber = annElement.attribute( "type" ).toInt();
     switch ( typeNumber )
     {
+        // Some annot types are commented because their creation is temporarly disabled
         case Annotation::AText:
-            annotation = new TextAnnotation( annElement );
+            //annotation = new TextAnnotation( annElement );
             break;
         case Annotation::ALine:
-            annotation = new LineAnnotation( annElement );
+            //annotation = new LineAnnotation( annElement );
             break;
         case Annotation::AGeom:
-            annotation = new GeomAnnotation( annElement );
+            //annotation = new GeomAnnotation( annElement );
             break;
         case Annotation::AHighlight:
-            annotation = new HighlightAnnotation( annElement );
+            //annotation = new HighlightAnnotation( annElement );
             break;
         case Annotation::AStamp:
-            annotation = new StampAnnotation( annElement );
+            //annotation = new StampAnnotation( annElement );
             break;
         case Annotation::AInk:
-            annotation = new InkAnnotation( annElement );
+            //annotation = new InkAnnotation( annElement );
             break;
         case Annotation::ACaret:
-            annotation = new CaretAnnotation( annElement );
+            //annotation = new CaretAnnotation( annElement );
             break;
     }
 
@@ -105,71 +108,276 @@ QDomElement AnnotationUtils::findChildElement( const QDomNode & parentNode,
 
 //BEGIN Annotation implementation
 AnnotationPrivate::AnnotationPrivate()
-    : flags( 0 )
+    : flags( 0 ), revisionScope ( Annotation::Root ), revisionType ( Annotation::None )
 {
     pdfObjectReference.num = pdfObjectReference.gen = -1;
 }
 
 AnnotationPrivate::~AnnotationPrivate()
 {
+    // Delete all children revisions
+    qDeleteAll( revisions );
 }
 
+class Annotation::Style::Private : public QSharedData
+{
+  public:
+    Private()
+        : opacity( 1.0 ), width( 1.0 ), lineStyle( Solid ), xCorners( 0.0 ),
+        yCorners( 0.0 ), lineEffect( NoEffect ), effectIntensity( 1.0 )
+        {
+            dashArray.resize(1);
+            dashArray[0] = 3;
+        }
+
+    QColor color;
+    double opacity;
+    double width;
+    Annotation::LineStyle lineStyle;
+    double xCorners;
+    double yCorners;
+    QVector<double> dashArray;
+    Annotation::LineEffect lineEffect;
+    double effectIntensity;
+};
 
 Annotation::Style::Style()
-    : opacity( 1.0 ), width( 1.0 ), style( Solid ), xCorners( 0.0 ),
-    yCorners( 0.0 ), marks( 3 ), spaces( 0 ), effect( NoEffect ),
-    effectIntensity( 1.0 ) {}
+    : d ( new Private )
+{
+}
+
+Annotation::Style::Style( const Style &other )
+    : d( other.d )
+{
+}
+
+Annotation::Style& Annotation::Style::operator=( const Style &other )
+{
+    if ( this != &other )
+        d = other.d;
+
+    return *this;
+}
+
+Annotation::Style::~Style()
+{
+}
+
+QColor Annotation::Style::color() const
+{
+    return d->color;
+}
+
+void Annotation::Style::setColor(const QColor &color)
+{
+    d->color = color;
+}
+
+double Annotation::Style::opacity() const
+{
+    return d->opacity;
+}
+
+void Annotation::Style::setOpacity(double opacity)
+{
+    d->opacity = opacity;
+}
+
+double Annotation::Style::width() const
+{
+    return d->width;
+}
+
+void Annotation::Style::setWidth(double width)
+{
+    d->width = width;
+}
+
+Annotation::LineStyle Annotation::Style::lineStyle() const
+{
+    return d->lineStyle;
+}
+
+void Annotation::Style::setLineStyle(Annotation::LineStyle style)
+{
+    d->lineStyle = style;
+}
+
+double Annotation::Style::xCorners() const
+{
+    return d->xCorners;
+}
+
+void Annotation::Style::setXCorners(double radius)
+{
+    d->xCorners = radius;
+}
+
+double Annotation::Style::yCorners() const
+{
+    return d->yCorners;
+}
+
+void Annotation::Style::setYCorners(double radius)
+{
+    d->yCorners = radius;
+}
+
+const QVector<double>& Annotation::Style::dashArray() const
+{
+    return d->dashArray;
+}
+
+void Annotation::Style::setDashArray(const QVector<double> &array)
+{
+    d->dashArray = array;
+}
+
+Annotation::LineEffect Annotation::Style::lineEffect() const
+{
+    return d->lineEffect;
+}
+
+void Annotation::Style::setLineEffect(Annotation::LineEffect effect)
+{
+    d->lineEffect = effect;
+}
+
+double Annotation::Style::effectIntensity() const
+{
+    return d->effectIntensity;
+}
+
+void Annotation::Style::setEffectIntensity(double intens)
+{
+    d->effectIntensity = intens;
+}
+
+class Annotation::Popup::Private : public QSharedData
+{
+  public:
+    Private()
+        : flags( -1 ) {}
+
+    int flags;
+    QRectF geometry;
+    QString title;
+    QString summary;
+    QString text;
+};
+
+Annotation::Popup::Popup()
+    : d ( new Private )
+{
+}
+
+Annotation::Popup::Popup( const Popup &other )
+    : d( other.d )
+{
+}
+
+Annotation::Popup& Annotation::Popup::operator=( const Popup &other )
+{
+    if ( this != &other )
+        d = other.d;
+
+    return *this;
+}
+
+Annotation::Popup::~Popup()
+{
+}
+
+int Annotation::Popup::flags() const
+{
+    return d->flags;
+}
+
+void Annotation::Popup::setFlags( int flags )
+{
+    d->flags = flags;
+}
+
+QRectF Annotation::Popup::geometry() const
+{
+    return d->geometry;
+}
+
+void Annotation::Popup::setGeometry( const QRectF &geom )
+{
+    d->geometry = geom;
+}
+
+QString Annotation::Popup::title() const
+{
+    return d->title;
+}
+
+void Annotation::Popup::setTitle( const QString &title )
+{
+    d->title = title;
+}
+
+QString Annotation::Popup::summary() const
+{
+    return d->summary;
+}
+
+void Annotation::Popup::setSummary( const QString &summary )
+{
+    d->summary = summary;
+}
 
-Annotation::Window::Window()
-    : flags( -1 ), width( 0 ), height( 0 ) {}
+QString Annotation::Popup::text() const
+{
+    return d->text;
+}
 
-Annotation::Revision::Revision()
-    : annotation( 0 ), scope( Reply ), type( None ) {}
+void Annotation::Popup::setText( const QString &text )
+{
+    d->text = text;
+}
 
 Annotation::Annotation( AnnotationPrivate &dd )
     : d_ptr( &dd )
 {
+    window.width = window.height = 0;
 }
 
 Annotation::~Annotation()
 {
-    Q_D( Annotation );
-    // delete all children revisions
-    QLinkedList< Annotation::Revision >::iterator it = d->revisions.begin(), end = d->revisions.end();
-    for ( ; it != end; ++it )
-        delete (*it).annotation;
-
-    delete d_ptr;
 }
 
 Annotation::Annotation( AnnotationPrivate &dd, const QDomNode &annNode )
     : d_ptr( &dd )
 {
-    Q_D( Annotation );
     // get the [base] element of the annotation node
     QDomElement e = AnnotationUtils::findChildElement( annNode, "base" );
     if ( e.isNull() )
         return;
 
+    Style s;
+    Popup w;
+
     // parse -contents- attributes
     if ( e.hasAttribute( "author" ) )
-        d->author = e.attribute( "author" );
+        setAuthor(e.attribute( "author" ));
     if ( e.hasAttribute( "contents" ) )
-        d->contents = e.attribute( "contents" );
+        setContents(e.attribute( "contents" ));
     if ( e.hasAttribute( "uniqueName" ) )
-        d->uniqueName = e.attribute( "uniqueName" );
+        setUniqueName(e.attribute( "uniqueName" ));
     if ( e.hasAttribute( "modifyDate" ) )
-        d->modDate = QDateTime::fromString( e.attribute( "modifyDate" ) );
+        setModificationDate(QDateTime::fromString( e.attribute( "modifyDate" ) ));
     if ( e.hasAttribute( "creationDate" ) )
-        d->creationDate = QDateTime::fromString( e.attribute( "creationDate" ) );
+        setCreationDate(QDateTime::fromString( e.attribute( "creationDate" ) ));
 
     // parse -other- attributes
     if ( e.hasAttribute( "flags" ) )
-        d->flags = e.attribute( "flags" ).toInt();
+        setFlags(e.attribute( "flags" ).toInt());
     if ( e.hasAttribute( "color" ) )
-        style.color = QColor( e.attribute( "color" ) );
+        s.setColor(QColor( e.attribute( "color" ) ));
     if ( e.hasAttribute( "opacity" ) )
-        style.opacity = e.attribute( "opacity" ).toDouble();
+        s.setOpacity(e.attribute( "opacity" ).toDouble());
 
     // parse -the-subnodes- (describing Style, Window, Revision(s) structures)
     // Note: all subnodes if present must be 'attributes complete'
@@ -182,48 +390,87 @@ Annotation::Annotation( AnnotationPrivate &dd, const QDomNode &annNode )
         // parse boundary
         if ( ee.tagName() == "boundary" )
         {
-            d->boundary.setLeft(ee.attribute( "l" ).toDouble());
-            d->boundary.setTop(ee.attribute( "t" ).toDouble());
-            d->boundary.setRight(ee.attribute( "r" ).toDouble());
-            d->boundary.setBottom(ee.attribute( "b" ).toDouble());
+            QRectF brect;
+            brect.setLeft(ee.attribute( "l" ).toDouble());
+            brect.setTop(ee.attribute( "t" ).toDouble());
+            brect.setRight(ee.attribute( "r" ).toDouble());
+            brect.setBottom(ee.attribute( "b" ).toDouble());
+            setBoundary(brect);
         }
         // parse penStyle if not default
         else if ( ee.tagName() == "penStyle" )
         {
-            style.width = ee.attribute( "width" ).toDouble();
-            style.style = (LineStyle)ee.attribute( "style" ).toInt();
-            style.xCorners = ee.attribute( "xcr" ).toDouble();
-            style.yCorners = ee.attribute( "ycr" ).toDouble();
-            style.marks = ee.attribute( "marks" ).toInt();
-            style.spaces = ee.attribute( "spaces" ).toInt();
+            s.setWidth(ee.attribute( "width" ).toDouble());
+            s.setLineStyle((LineStyle)ee.attribute( "style" ).toInt());
+            s.setXCorners(ee.attribute( "xcr" ).toDouble());
+            s.setYCorners(ee.attribute( "ycr" ).toDouble());
+
+            // Try to parse dash array (new format)
+            QVector<double> dashArray;
+
+            QDomNode eeSubNode = ee.firstChild();
+            while ( eeSubNode.isElement() )
+            {
+                QDomElement eee = eeSubNode.toElement();
+                eeSubNode = eeSubNode.nextSibling();
+
+                if ( eee.tagName() != "dashsegm" )
+                    continue;
+
+                dashArray.append(eee.attribute( "len" ).toDouble());
+            }
+
+            // If no segments were found use marks/spaces (old format)
+            if ( dashArray.size() == 0 )
+            {
+                dashArray.append(ee.attribute( "marks" ).toDouble());
+                dashArray.append(ee.attribute( "spaces" ).toDouble());
+            }
+
+            s.setDashArray(dashArray);
         }
         // parse effectStyle if not default
         else if ( ee.tagName() == "penEffect" )
         {
-            style.effect = (LineEffect)ee.attribute( "effect" ).toInt();
-            style.effectIntensity = ee.attribute( "intensity" ).toDouble();
+            s.setLineEffect((LineEffect)ee.attribute( "effect" ).toInt());
+            s.setEffectIntensity(ee.attribute( "intensity" ).toDouble());
         }
         // parse window if present
         else if ( ee.tagName() == "window" )
         {
-            window.flags = ee.attribute( "flags" ).toInt();
-            window.topLeft.setX(ee.attribute( "top" ).toDouble());
-            window.topLeft.setY(ee.attribute( "left" ).toDouble());
-            window.width = ee.attribute( "width" ).toInt();
-            window.height = ee.attribute( "height" ).toInt();
-            window.title = ee.attribute( "title" );
-            window.summary = ee.attribute( "summary" );
+            QRectF geom;
+            geom.setX(ee.attribute( "top" ).toDouble());
+            geom.setY(ee.attribute( "left" ).toDouble());
+
+            if (ee.hasAttribute("widthDouble"))
+                geom.setWidth(ee.attribute( "widthDouble" ).toDouble());
+            else
+                geom.setWidth(ee.attribute( "width" ).toDouble());
+
+            if (ee.hasAttribute("widthDouble"))
+                geom.setHeight(ee.attribute( "heightDouble" ).toDouble());
+            else
+                geom.setHeight(ee.attribute( "height" ).toDouble());
+
+            w.setGeometry(geom);
+
+            w.setFlags(ee.attribute( "flags" ).toInt());
+            w.setTitle(ee.attribute( "title" ));
+            w.setSummary(ee.attribute( "summary" ));
             // parse window subnodes
             QDomNode winNode = ee.firstChild();
             for ( ; winNode.isElement(); winNode = winNode.nextSibling() )
             {
                 QDomElement winElement = winNode.toElement();
                 if ( winElement.tagName() == "text" )
-                    window.text = winElement.firstChild().toCDATASection().data();
+                    w.setText(winElement.firstChild().toCDATASection().data());
             }
         }
     }
 
+    setStyle(s);  // assign parsed style
+    setPopup(w); // assign parsed window
+
     // get the [revisions] element of the annotation node
     QDomNode revNode = annNode.firstChild();
     for ( ; revNode.isElement(); revNode = revNode.nextSibling() )
@@ -232,116 +479,137 @@ Annotation::Annotation( AnnotationPrivate &dd, const QDomNode &annNode )
         if ( revElement.tagName() != "revision" )
             continue;
 
-        // compile the Revision structure crating annotation
-        Revision rev;
-        rev.scope = (RevScope)revElement.attribute( "revScope" ).toInt();
-        rev.type = (RevType)revElement.attribute( "revType" ).toInt();
-        rev.annotation = AnnotationUtils::createAnnotation( revElement );
+        Annotation *reply = AnnotationUtils::createAnnotation( revElement );
 
-        // if annotation is valid, add revision to internal list
-        if ( rev.annotation )
-            d->revisions.append( rev );
+        if (reply) // if annotation is valid, add as a revision of this annotation
+        {
+            RevScope scope = (RevScope)revElement.attribute( "revScope" ).toInt();
+            RevType type = (RevType)revElement.attribute( "revType" ).toInt();
+            addRevision(reply, scope, type);
+            delete reply;
+        }
     }
 }
 
-void Annotation::store( QDomNode & annNode, QDomDocument & document ) const
+void Annotation::storeBaseAnnotationProperties( QDomNode & annNode, QDomDocument & document ) const
 {
-    Q_D( const Annotation );
     // create [base] element of the annotation node
     QDomElement e = document.createElement( "base" );
     annNode.appendChild( e );
 
+    const Style s = style();
+    const Popup w = popup();
+
     // store -contents- attributes
-    if ( !d->author.isEmpty() )
-        e.setAttribute( "author", d->author );
-    if ( !d->contents.isEmpty() )
-        e.setAttribute( "contents", d->contents );
-    if ( !d->uniqueName.isEmpty() )
-        e.setAttribute( "uniqueName", d->uniqueName );
-    if ( d->modDate.isValid() )
-        e.setAttribute( "modifyDate", d->modDate.toString() );
-    if ( d->creationDate.isValid() )
-        e.setAttribute( "creationDate", d->creationDate.toString() );
+    if ( !author().isEmpty() )
+        e.setAttribute( "author", author() );
+    if ( !contents().isEmpty() )
+        e.setAttribute( "contents", contents() );
+    if ( !uniqueName().isEmpty() )
+        e.setAttribute( "uniqueName", uniqueName() );
+    if ( modificationDate().isValid() )
+        e.setAttribute( "modifyDate", modificationDate().toString() );
+    if ( creationDate().isValid() )
+        e.setAttribute( "creationDate", creationDate().toString() );
 
     // store -other- attributes
-    if ( d->flags )
-        e.setAttribute( "flags", d->flags );
-    if ( style.color.isValid() && style.color != Qt::black )
-        e.setAttribute( "color", style.color.name() );
-    if ( style.opacity != 1.0 )
-        e.setAttribute( "opacity", QString::number( style.opacity ) );
+    if ( flags() )
+        e.setAttribute( "flags", flags() );
+    if ( s.color().isValid() && s.color() != Qt::black )
+        e.setAttribute( "color", s.color().name() );
+    if ( s.opacity() != 1.0 )
+        e.setAttribute( "opacity", QString::number( s.opacity() ) );
 
     // Sub-Node-1 - boundary
+    const QRectF brect = boundary();
     QDomElement bE = document.createElement( "boundary" );
     e.appendChild( bE );
-    bE.setAttribute( "l", QString::number( (double)d->boundary.left() ) );
-    bE.setAttribute( "t", QString::number( (double)d->boundary.top() ) );
-    bE.setAttribute( "r", QString::number( (double)d->boundary.right() ) );
-    bE.setAttribute( "b", QString::number( (double)d->boundary.bottom() ) );
+    bE.setAttribute( "l", QString::number( (double)brect.left() ) );
+    bE.setAttribute( "t", QString::number( (double)brect.top() ) );
+    bE.setAttribute( "r", QString::number( (double)brect.right() ) );
+    bE.setAttribute( "b", QString::number( (double)brect.bottom() ) );
 
     // Sub-Node-2 - penStyle
-    if ( style.width != 1 || style.style != Solid || style.xCorners != 0 ||
-         style.yCorners != 0.0 || style.marks != 3 || style.spaces != 0 )
+    const QVector<double> dashArray = s.dashArray();
+    if ( s.width() != 1 || s.lineStyle() != Solid || s.xCorners() != 0 ||
+         s.yCorners() != 0.0 || dashArray.size() != 1 || dashArray[0] != 3 )
     {
         QDomElement psE = document.createElement( "penStyle" );
         e.appendChild( psE );
-        psE.setAttribute( "width", QString::number( style.width ) );
-        psE.setAttribute( "style", (int)style.style );
-        psE.setAttribute( "xcr", QString::number( style.xCorners ) );
-        psE.setAttribute( "ycr", QString::number( style.yCorners ) );
-        psE.setAttribute( "marks", style.marks );
-        psE.setAttribute( "spaces", style.spaces );
+        psE.setAttribute( "width", QString::number( s.width() ) );
+        psE.setAttribute( "style", (int)s.lineStyle() );
+        psE.setAttribute( "xcr", QString::number( s.xCorners() ) );
+        psE.setAttribute( "ycr", QString::number( s.yCorners() ) );
+
+        int marks = 3, spaces = 0; // Do not break code relying on marks/spaces
+        if (dashArray.size() != 0)
+            marks = (int)dashArray[0];
+        if (dashArray.size() > 1)
+            spaces = (int)dashArray[1];
+
+        psE.setAttribute( "marks", marks );
+        psE.setAttribute( "spaces", spaces );
+
+        foreach (double segm, dashArray)
+        {
+            QDomElement pattE = document.createElement( "dashsegm" );
+            pattE.setAttribute( "len", QString::number( segm ) );
+            psE.appendChild(pattE);
+        }
     }
 
     // Sub-Node-3 - penEffect
-    if ( style.effect != NoEffect || style.effectIntensity != 1.0 )
+    if ( s.lineEffect() != NoEffect || s.effectIntensity() != 1.0 )
     {
         QDomElement peE = document.createElement( "penEffect" );
         e.appendChild( peE );
-        peE.setAttribute( "effect", (int)style.effect );
-        peE.setAttribute( "intensity", QString::number( style.effectIntensity ) );
+        peE.setAttribute( "effect", (int)s.lineEffect() );
+        peE.setAttribute( "intensity", QString::number( s.effectIntensity() ) );
     }
 
     // Sub-Node-4 - window
-    if ( window.flags != -1 || !window.title.isEmpty() ||
-         !window.summary.isEmpty() || !window.text.isEmpty() )
+    if ( w.flags() != -1 || !w.title().isEmpty() || !w.summary().isEmpty() ||
+         !w.text().isEmpty() )
     {
         QDomElement wE = document.createElement( "window" );
+        const QRectF geom = w.geometry();
         e.appendChild( wE );
-        wE.setAttribute( "flags", window.flags );
-        wE.setAttribute( "top", QString::number( window.topLeft.x() ) );
-        wE.setAttribute( "left", QString::number( window.topLeft.y() ) );
-        wE.setAttribute( "width", window.width );
-        wE.setAttribute( "height", window.height );
-        wE.setAttribute( "title", window.title );
-        wE.setAttribute( "summary", window.summary );
+        wE.setAttribute( "flags", w.flags() );
+        wE.setAttribute( "top", QString::number( geom.x() ) );
+        wE.setAttribute( "left", QString::number( geom.y() ) );
+        wE.setAttribute( "width", (int)geom.width() );
+        wE.setAttribute( "height", (int)geom.height() );
+        wE.setAttribute( "widthDouble", QString::number( geom.width() ) );
+        wE.setAttribute( "heightDouble", QString::number( geom.height() ) );
+        wE.setAttribute( "title", w.title() );
+        wE.setAttribute( "summary", w.summary() );
         // store window.text as a subnode, because we need escaped data
-        if ( !window.text.isEmpty() )
+        if ( !w.text().isEmpty() )
         {
             QDomElement escapedText = document.createElement( "text" );
             wE.appendChild( escapedText );
-            QDomCDATASection textCData = document.createCDATASection( window.text );
+            QDomCDATASection textCData = document.createCDATASection( w.text() );
             escapedText.appendChild( textCData );
         }
     }
 
+    const QList<Annotation*> revs = revisions();
+
     // create [revision] element of the annotation node (if any)
-    if ( d->revisions.isEmpty() )
+    if ( revs.isEmpty() )
         return;
 
     // add all revisions as children of revisions element
-    QLinkedList< Revision >::const_iterator it = d->revisions.begin(), end = d->revisions.end();
-    for ( ; it != end; ++it )
+    foreach (const Annotation *rev, revs)
     {
-        // create revision element
-        const Revision & revision = *it;
         QDomElement r = document.createElement( "revision" );
         annNode.appendChild( r );
         // set element attributes
-        r.setAttribute( "revScope", (int)revision.scope );
-        r.setAttribute( "revType", (int)revision.type );
+        r.setAttribute( "revScope", (int)rev->revisionScope() );
+        r.setAttribute( "revType", (int)rev->revisionType() );
         // use revision as the annotation element, so fill it up
-        AnnotationUtils::storeAnnotation( revision.annotation, r, document );
+        AnnotationUtils::storeAnnotation( rev, r, document );
+        delete rev;
     }
 }
 
@@ -429,16 +697,76 @@ void Annotation::setBoundary( const QRectF &boundary )
     d->boundary = boundary;
 }
 
-QLinkedList< Annotation::Revision >& Annotation::revisions()
+Annotation::Style Annotation::style() const
+{
+    Q_D( const Annotation );
+    return d->style;
+}
+
+void Annotation::setStyle( const Annotation::Style& style )
 {
     Q_D( Annotation );
-    return d->revisions;
+    d->style = style;
 }
 
-const QLinkedList< Annotation::Revision >& Annotation::revisions() const
+Annotation::Popup Annotation::popup() const
 {
     Q_D( const Annotation );
-    return d->revisions;
+    return d->popup;
+}
+
+void Annotation::setPopup( const Annotation::Popup& popup )
+{
+    Q_D( Annotation );
+    d->popup = popup;
+}
+
+Annotation::RevScope Annotation::revisionScope() const
+{
+    Q_D( const Annotation );
+    return d->revisionScope;
+}
+
+void Annotation::setRevisionScope( Annotation::RevScope scope )
+{
+    Q_D( Annotation );
+    d->revisionScope = scope;
+}
+
+Annotation::RevType Annotation::revisionType() const
+{
+    Q_D( const Annotation );
+    return d->revisionType;
+}
+
+void Annotation::setRevisionType( Annotation::RevType type )
+{
+    Q_D( Annotation );
+    d->revisionType = type;
+}
+
+QList<Annotation*> Annotation::revisions() const
+{
+    Q_D( const Annotation );
+    QList<Annotation*> res;
+
+    /* Return aliases, whose ownership goes to the caller */
+    foreach (Annotation *rev, d->revisions)
+        res.append( rev->d_ptr->makeAlias() );
+
+    return res;
+}
+
+void Annotation::addRevision( Annotation *ann, RevScope scope, RevType type )
+{
+    Q_D( Annotation );
+
+    /* Since ownership stays with the caller, create an alias of ann */
+    d->revisions.append( ann->d_ptr->makeAlias() );
+
+    /* Set revision properties */
+    ann->setRevisionScope(scope);
+    ann->setRevisionType(type);
 }
 
 //END AnnotationUtils implementation
@@ -449,6 +777,7 @@ class TextAnnotationPrivate : public AnnotationPrivate
 {
     public:
         TextAnnotationPrivate();
+        Annotation * makeAlias();
 
         // data fields
         TextAnnotation::TextType textType;
@@ -467,15 +796,22 @@ TextAnnotationPrivate::TextAnnotationPrivate()
 {
 }
 
+Annotation * TextAnnotationPrivate::makeAlias()
+{
+    return new TextAnnotation(*this);
+}
+
 TextAnnotation::TextAnnotation()
     : Annotation( *new TextAnnotationPrivate() )
 {}
 
+TextAnnotation::TextAnnotation(TextAnnotationPrivate &dd)
+    : Annotation( dd )
+{}
+
 TextAnnotation::TextAnnotation( const QDomNode & node )
     : Annotation( *new TextAnnotationPrivate, node )
 {
-    Q_D( TextAnnotation );
-
     // loop through the whole children looking for a 'text' element
     QDomNode subNode = node.firstChild();
     while( subNode.isElement() )
@@ -487,15 +823,19 @@ TextAnnotation::TextAnnotation( const QDomNode & node )
 
         // parse the attributes
         if ( e.hasAttribute( "type" ) )
-            d->textType = (TextAnnotation::TextType)e.attribute( "type" ).toInt();
+            setTextType((TextAnnotation::TextType)e.attribute( "type" ).toInt());
         if ( e.hasAttribute( "icon" ) )
-            d->textIcon = e.attribute( "icon" );
+            setTextIcon(e.attribute( "icon" ));
         if ( e.hasAttribute( "font" ) )
-            d->textFont.fromString( e.attribute( "font" ) );
+        {
+            QFont font;
+            font.fromString( e.attribute( "font" ) );
+            setTextFont(font);
+        }
         if ( e.hasAttribute( "align" ) )
-            d->inplaceAlign = e.attribute( "align" ).toInt();
+            setInplaceAlign(e.attribute( "align" ).toInt());
         if ( e.hasAttribute( "intent" ) )
-            d->inplaceIntent = (TextAnnotation::InplaceIntent)e.attribute( "intent" ).toInt();
+            setInplaceIntent((TextAnnotation::InplaceIntent)e.attribute( "intent" ).toInt());
 
         // parse the subnodes
         QDomNode eSubNode = e.firstChild();
@@ -506,16 +846,16 @@ TextAnnotation::TextAnnotation( const QDomNode & node )
 
             if ( ee.tagName() == "escapedText" )
             {
-                d->inplaceText = ee.firstChild().toCDATASection().data();
+                setInplaceText(ee.firstChild().toCDATASection().data());
             }
             else if ( ee.tagName() == "callout" )
             {
-                d->inplaceCallout[0].setX(ee.attribute( "ax" ).toDouble());
-                d->inplaceCallout[0].setY(ee.attribute( "ay" ).toDouble());
-                d->inplaceCallout[1].setX(ee.attribute( "bx" ).toDouble());
-                d->inplaceCallout[1].setY(ee.attribute( "by" ).toDouble());
-                d->inplaceCallout[2].setX(ee.attribute( "cx" ).toDouble());
-                d->inplaceCallout[2].setY(ee.attribute( "cy" ).toDouble());
+                setCalloutPoint(0, QPointF(ee.attribute( "ax" ).toDouble(),
+                                           ee.attribute( "ay" ).toDouble()));
+                setCalloutPoint(1, QPointF(ee.attribute( "bx" ).toDouble(),
+                                           ee.attribute( "by" ).toDouble()));
+                setCalloutPoint(2, QPointF(ee.attribute( "cx" ).toDouble(),
+                                           ee.attribute( "cy" ).toDouble()));
             }
         }
 
@@ -530,47 +870,45 @@ TextAnnotation::~TextAnnotation()
 
 void TextAnnotation::store( QDomNode & node, QDomDocument & document ) const
 {
-    Q_D( const TextAnnotation );
-
-    // recurse to parent objects storing properties
-    Annotation::store( node, document );
+    // store base annotation properties
+    storeBaseAnnotationProperties( node, document );
 
     // create [text] element
     QDomElement textElement = document.createElement( "text" );
     node.appendChild( textElement );
 
     // store the optional attributes
-    if ( d->textType != Linked )
-        textElement.setAttribute( "type", (int)d->textType );
-    if ( d->textIcon != "Comment" )
-        textElement.setAttribute( "icon", d->textIcon );
-    if ( d->inplaceAlign )
-        textElement.setAttribute( "align", d->inplaceAlign );
-    if ( d->inplaceIntent != Unknown )
-        textElement.setAttribute( "intent", (int)d->inplaceIntent );
+    if ( textType() != Linked )
+        textElement.setAttribute( "type", (int)textType() );
+    if ( textIcon() != "Comment" )
+        textElement.setAttribute( "icon", textIcon() );
+    if ( inplaceAlign() )
+        textElement.setAttribute( "align", inplaceAlign() );
+    if ( inplaceIntent() != Unknown )
+        textElement.setAttribute( "intent", (int)inplaceIntent() );
 
-    textElement.setAttribute( "font", d->textFont.toString() );
+    textElement.setAttribute( "font", textFont().toString() );
 
     // Sub-Node-1 - escapedText
-    if ( !d->inplaceText.isEmpty() )
+    if ( !inplaceText().isEmpty() )
     {
         QDomElement escapedText = document.createElement( "escapedText" );
         textElement.appendChild( escapedText );
-        QDomCDATASection textCData = document.createCDATASection( d->inplaceText );
+        QDomCDATASection textCData = document.createCDATASection( inplaceText() );
         escapedText.appendChild( textCData );
     }
 
     // Sub-Node-2 - callout
-    if ( d->inplaceCallout[0].x() != 0.0 )
+    if ( calloutPoint(0).x() != 0.0 )
     {
         QDomElement calloutElement = document.createElement( "callout" );
         textElement.appendChild( calloutElement );
-        calloutElement.setAttribute( "ax", QString::number( d->inplaceCallout[0].x() ) );
-        calloutElement.setAttribute( "ay", QString::number( d->inplaceCallout[0].y() ) );
-        calloutElement.setAttribute( "bx", QString::number( d->inplaceCallout[1].x() ) );
-        calloutElement.setAttribute( "by", QString::number( d->inplaceCallout[1].y() ) );
-        calloutElement.setAttribute( "cx", QString::number( d->inplaceCallout[2].x() ) );
-        calloutElement.setAttribute( "cy", QString::number( d->inplaceCallout[2].y() ) );
+        calloutElement.setAttribute( "ax", QString::number( calloutPoint(0).x() ) );
+        calloutElement.setAttribute( "ay", QString::number( calloutPoint(0).y() ) );
+        calloutElement.setAttribute( "bx", QString::number( calloutPoint(1).x() ) );
+        calloutElement.setAttribute( "by", QString::number( calloutPoint(1).y() ) );
+        calloutElement.setAttribute( "cx", QString::number( calloutPoint(2).x() ) );
+        calloutElement.setAttribute( "cy", QString::number( calloutPoint(2).y() ) );
     }
 }
 
@@ -675,6 +1013,7 @@ class LineAnnotationPrivate : public AnnotationPrivate
 {
     public:
         LineAnnotationPrivate();
+        Annotation * makeAlias();
 
         // data fields (note uses border for rendering style)
         QLinkedList<QPointF> linePoints;
@@ -696,15 +1035,22 @@ LineAnnotationPrivate::LineAnnotationPrivate()
 {
 }
 
+Annotation * LineAnnotationPrivate::makeAlias()
+{
+    return new LineAnnotation(*this);
+}
+
 LineAnnotation::LineAnnotation()
     : Annotation( *new LineAnnotationPrivate() )
 {}
 
+LineAnnotation::LineAnnotation(LineAnnotationPrivate &dd)
+    : Annotation( dd )
+{}
+
 LineAnnotation::LineAnnotation( const QDomNode & node )
     : Annotation( *new LineAnnotationPrivate(), node )
 {
-    Q_D( LineAnnotation );
-
     // loop through the whole children looking for a 'line' element
     QDomNode subNode = node.firstChild();
     while( subNode.isElement() )
@@ -716,23 +1062,24 @@ LineAnnotation::LineAnnotation( const QDomNode & node )
 
         // parse the attributes
         if ( e.hasAttribute( "startStyle" ) )
-            d->lineStartStyle = (LineAnnotation::TermStyle)e.attribute( "startStyle" ).toInt();
+            setLineStartStyle((LineAnnotation::TermStyle)e.attribute( "startStyle" ).toInt());
         if ( e.hasAttribute( "endStyle" ) )
-            d->lineEndStyle = (LineAnnotation::TermStyle)e.attribute( "endStyle" ).toInt();
+            setLineEndStyle((LineAnnotation::TermStyle)e.attribute( "endStyle" ).toInt());
         if ( e.hasAttribute( "closed" ) )
-            d->lineClosed = e.attribute( "closed" ).toInt();
+            setLineClosed(e.attribute( "closed" ).toInt());
         if ( e.hasAttribute( "innerColor" ) )
-            d->lineInnerColor = QColor( e.attribute( "innerColor" ) );
+            setLineInnerColor(QColor( e.attribute( "innerColor" ) ));
         if ( e.hasAttribute( "leadFwd" ) )
-            d->lineLeadingFwdPt = e.attribute( "leadFwd" ).toDouble();
+            setLineLeadingForwardPoint(e.attribute( "leadFwd" ).toDouble());
         if ( e.hasAttribute( "leadBack" ) )
-            d->lineLeadingBackPt = e.attribute( "leadBack" ).toDouble();
+            setLineLeadingBackPoint(e.attribute( "leadBack" ).toDouble());
         if ( e.hasAttribute( "showCaption" ) )
-            d->lineShowCaption = e.attribute( "showCaption" ).toInt();
+            setLineShowCaption(e.attribute( "showCaption" ).toInt());
         if ( e.hasAttribute( "intent" ) )
-            d->lineIntent = (LineAnnotation::LineIntent)e.attribute( "intent" ).toInt();
+            setLineIntent((LineAnnotation::LineIntent)e.attribute( "intent" ).toInt());
 
         // parse all 'point' subnodes
+        QLinkedList<QPointF> points;
         QDomNode pointNode = e.firstChild();
         while ( pointNode.isElement() )
         {
@@ -743,8 +1090,9 @@ LineAnnotation::LineAnnotation( const QDomNode & node )
                 continue;
 
             QPointF p(pe.attribute( "x", "0.0" ).toDouble(), pe.attribute( "y", "0.0" ).toDouble());
-            d->linePoints.append( p );
+            points.append( p );
         }
+        setLinePoints(points);
 
         // loading complete
         break;
@@ -757,38 +1105,36 @@ LineAnnotation::~LineAnnotation()
 
 void LineAnnotation::store( QDomNode & node, QDomDocument & document ) const
 {
-    Q_D( const LineAnnotation );
-
-    // recurse to parent objects storing properties
-    Annotation::store( node, document );
+    // store base annotation properties
+    storeBaseAnnotationProperties( node, document );
 
     // create [line] element
     QDomElement lineElement = document.createElement( "line" );
     node.appendChild( lineElement );
 
     // store the attributes
-    if ( d->lineStartStyle != None )
-        lineElement.setAttribute( "startStyle", (int)d->lineStartStyle );
-    if ( d->lineEndStyle != None )
-        lineElement.setAttribute( "endStyle", (int)d->lineEndStyle );
-    if ( d->lineClosed )
-        lineElement.setAttribute( "closed", d->lineClosed );
-    if ( d->lineInnerColor.isValid() )
-        lineElement.setAttribute( "innerColor", d->lineInnerColor.name() );
-    if ( d->lineLeadingFwdPt != 0.0 )
-        lineElement.setAttribute( "leadFwd", QString::number( d->lineLeadingFwdPt ) );
-    if ( d->lineLeadingBackPt != 0.0 )
-        lineElement.setAttribute( "leadBack", QString::number( d->lineLeadingBackPt ) );
-    if ( d->lineShowCaption )
-        lineElement.setAttribute( "showCaption", d->lineShowCaption );
-    if ( d->lineIntent != Unknown )
-        lineElement.setAttribute( "intent", d->lineIntent );
+    if ( lineStartStyle() != None )
+        lineElement.setAttribute( "startStyle", (int)lineStartStyle() );
+    if ( lineEndStyle() != None )
+        lineElement.setAttribute( "endStyle", (int)lineEndStyle() );
+    if ( isLineClosed() )
+        lineElement.setAttribute( "closed", isLineClosed() );
+    if ( lineInnerColor().isValid() )
+        lineElement.setAttribute( "innerColor", lineInnerColor().name() );
+    if ( lineLeadingForwardPoint() != 0.0 )
+        lineElement.setAttribute( "leadFwd", QString::number( lineLeadingForwardPoint() ) );
+    if ( lineLeadingBackPoint() != 0.0 )
+        lineElement.setAttribute( "leadBack", QString::number( lineLeadingBackPoint() ) );
+    if ( lineShowCaption() )
+        lineElement.setAttribute( "showCaption", lineShowCaption() );
+    if ( lineIntent() != Unknown )
+        lineElement.setAttribute( "intent", lineIntent() );
 
     // append the list of points
-    int points = d->linePoints.count();
-    if ( points > 1 )
+    const QLinkedList<QPointF> points = linePoints();
+    if ( points.count() > 1 )
     {
-        QLinkedList<QPointF>::const_iterator it = d->linePoints.begin(), end = d->linePoints.end();
+        QLinkedList<QPointF>::const_iterator it = points.begin(), end = points.end();
         while ( it != end )
         {
             const QPointF & p = *it;
@@ -920,28 +1266,34 @@ class GeomAnnotationPrivate : public AnnotationPrivate
 {
     public:
         GeomAnnotationPrivate();
+        Annotation * makeAlias();
 
         // data fields (note uses border for rendering style)
         GeomAnnotation::GeomType geomType;
         QColor geomInnerColor;
-        int geomWidthPt;
 };
 
 GeomAnnotationPrivate::GeomAnnotationPrivate()
-    : AnnotationPrivate(), geomType( GeomAnnotation::InscribedSquare ),
-    geomWidthPt( 18 )
+    : AnnotationPrivate(), geomType( GeomAnnotation::InscribedSquare )
 {
 }
 
+Annotation * GeomAnnotationPrivate::makeAlias()
+{
+    return new GeomAnnotation(*this);
+}
+
 GeomAnnotation::GeomAnnotation()
     : Annotation( *new GeomAnnotationPrivate() )
 {}
 
+GeomAnnotation::GeomAnnotation(GeomAnnotationPrivate &dd)
+    : Annotation( dd )
+{}
+
 GeomAnnotation::GeomAnnotation( const QDomNode & node )
     : Annotation( *new GeomAnnotationPrivate(), node )
 {
-    Q_D( GeomAnnotation );
-
     // loop through the whole children looking for a 'geom' element
     QDomNode subNode = node.firstChild();
     while( subNode.isElement() )
@@ -953,11 +1305,9 @@ GeomAnnotation::GeomAnnotation( const QDomNode & node )
 
         // parse the attributes
         if ( e.hasAttribute( "type" ) )
-            d->geomType = (GeomAnnotation::GeomType)e.attribute( "type" ).toInt();
+            setGeomType((GeomAnnotation::GeomType)e.attribute( "type" ).toInt());
         if ( e.hasAttribute( "color" ) )
-            d->geomInnerColor = QColor( e.attribute( "color" ) );
-        if ( e.hasAttribute( "width" ) )
-            d->geomWidthPt = e.attribute( "width" ).toInt();
+            setGeomInnerColor(QColor( e.attribute( "color" ) ));
 
         // loading complete
         break;
@@ -970,22 +1320,18 @@ GeomAnnotation::~GeomAnnotation()
 
 void GeomAnnotation::store( QDomNode & node, QDomDocument & document ) const
 {
-    Q_D( const GeomAnnotation );
-
-    // recurse to parent objects storing properties
-    Annotation::store( node, document );
+    // store base annotation properties
+    storeBaseAnnotationProperties( node, document );
 
     // create [geom] element
     QDomElement geomElement = document.createElement( "geom" );
     node.appendChild( geomElement );
 
     // append the optional attributes
-    if ( d->geomType != InscribedSquare )
-        geomElement.setAttribute( "type", (int)d->geomType );
-    if ( d->geomInnerColor.isValid() )
-        geomElement.setAttribute( "color", d->geomInnerColor.name() );
-    if ( d->geomWidthPt != 18 )
-        geomElement.setAttribute( "width", d->geomWidthPt );
+    if ( geomType() != InscribedSquare )
+        geomElement.setAttribute( "type", (int)geomType() );
+    if ( geomInnerColor().isValid() )
+        geomElement.setAttribute( "color", geomInnerColor().name() );
 }
 
 Annotation::SubType GeomAnnotation::subType() const
@@ -1017,25 +1363,13 @@ void GeomAnnotation::setGeomInnerColor( const QColor &color )
     d->geomInnerColor = color;
 }
 
-int GeomAnnotation::geomPointWidth() const
-{
-    Q_D( const GeomAnnotation );
-    return d->geomWidthPt;
-}
-
-void GeomAnnotation::setGeomPointWidth( int width )
-{
-    Q_D( GeomAnnotation );
-    d->geomWidthPt = width;
-}
-
-
 
 /** HighlightAnnotation [Annotation] */
 class HighlightAnnotationPrivate : public AnnotationPrivate
 {
     public:
         HighlightAnnotationPrivate();
+        Annotation * makeAlias();
 
         // data fields
         HighlightAnnotation::HighlightType highlightType;
@@ -1047,15 +1381,22 @@ HighlightAnnotationPrivate::HighlightAnnotationPrivate()
 {
 }
 
+Annotation * HighlightAnnotationPrivate::makeAlias()
+{
+    return new HighlightAnnotation(*this);
+}
+
 HighlightAnnotation::HighlightAnnotation()
     : Annotation( *new HighlightAnnotationPrivate() )
 {}
 
+HighlightAnnotation::HighlightAnnotation(HighlightAnnotationPrivate &dd)
+    : Annotation( dd )
+{}
+
 HighlightAnnotation::HighlightAnnotation( const QDomNode & node )
     : Annotation( *new HighlightAnnotationPrivate(), node )
 {
-    Q_D( HighlightAnnotation );
-
     // loop through the whole children looking for a 'hl' element
     QDomNode subNode = node.firstChild();
     while( subNode.isElement() )
@@ -1067,9 +1408,10 @@ HighlightAnnotation::HighlightAnnotation( const QDomNode & node )
 
         // parse the attributes
         if ( e.hasAttribute( "type" ) )
-            d->highlightType = (HighlightAnnotation::HighlightType)e.attribute( "type" ).toInt();
+            setHighlightType((HighlightAnnotation::HighlightType)e.attribute( "type" ).toInt());
 
         // parse all 'quad' subnodes
+        QList<HighlightAnnotation::Quad> quads;
         QDomNode quadNode = e.firstChild();
         for ( ; quadNode.isElement(); quadNode = quadNode.nextSibling() )
         {
@@ -1089,8 +1431,9 @@ HighlightAnnotation::HighlightAnnotation( const QDomNode & node )
             q.capStart = qe.hasAttribute( "start" );
             q.capEnd = qe.hasAttribute( "end" );
             q.feather = qe.attribute( "feather", "0.1" ).toDouble();
-            d->highlightQuads.append( q );
+            quads.append( q );
         }
+        setHighlightQuads(quads);
 
         // loading complete
         break;
@@ -1103,22 +1446,22 @@ HighlightAnnotation::~HighlightAnnotation()
 
 void HighlightAnnotation::store( QDomNode & node, QDomDocument & document ) const
 {
-    Q_D( const HighlightAnnotation );
-
-    // recurse to parent objects storing properties
-    Annotation::store( node, document );
+    // store base annotation properties
+    storeBaseAnnotationProperties( node, document );
 
     // create [hl] element
     QDomElement hlElement = document.createElement( "hl" );
     node.appendChild( hlElement );
 
     // append the optional attributes
-    if ( d->highlightType != Highlight )
-        hlElement.setAttribute( "type", (int)d->highlightType );
-    if ( d->highlightQuads.count() < 1 )
+    if ( highlightType() != Highlight )
+        hlElement.setAttribute( "type", (int)highlightType() );
+
+    const QList<HighlightAnnotation::Quad> quads = highlightQuads();
+    if ( quads.count() < 1 )
         return;
     // append highlight quads, all children describe quads
-    QList< HighlightAnnotation::Quad >::const_iterator it = d->highlightQuads.begin(), end = d->highlightQuads.end();
+    QList< HighlightAnnotation::Quad >::const_iterator it = quads.begin(), end = quads.end();
     for ( ; it != end; ++it )
     {
         QDomElement quadElement = document.createElement( "quad" );
@@ -1175,6 +1518,7 @@ class StampAnnotationPrivate : public AnnotationPrivate
 {
     public:
         StampAnnotationPrivate();
+        Annotation * makeAlias();
 
         // data fields
         QString stampIconName;
@@ -1185,15 +1529,22 @@ StampAnnotationPrivate::StampAnnotationPrivate()
 {
 }
 
+Annotation * StampAnnotationPrivate::makeAlias()
+{
+    return new StampAnnotation(*this);
+}
+
 StampAnnotation::StampAnnotation()
     : Annotation( *new StampAnnotationPrivate() )
 {}
 
+StampAnnotation::StampAnnotation(StampAnnotationPrivate &dd)
+    : Annotation( dd )
+{}
+
 StampAnnotation::StampAnnotation( const QDomNode & node )
     : Annotation( *new StampAnnotationPrivate(), node )
 {
-   Q_D( StampAnnotation );
-
     // loop through the whole children looking for a 'stamp' element
     QDomNode subNode = node.firstChild();
     while( subNode.isElement() )
@@ -1205,7 +1556,7 @@ StampAnnotation::StampAnnotation( const QDomNode & node )
 
         // parse the attributes
         if ( e.hasAttribute( "icon" ) )
-            d->stampIconName = e.attribute( "icon" );
+            setStampIconName(e.attribute( "icon" ));
 
         // loading complete
         break;
@@ -1218,18 +1569,16 @@ StampAnnotation::~StampAnnotation()
 
 void StampAnnotation::store( QDomNode & node, QDomDocument & document ) const
 {
-   Q_D( const StampAnnotation );
-
-    // recurse to parent objects storing properties
-    Annotation::store( node, document );
+    // store base annotation properties
+    storeBaseAnnotationProperties( node, document );
 
     // create [stamp] element
     QDomElement stampElement = document.createElement( "stamp" );
     node.appendChild( stampElement );
 
     // append the optional attributes
-    if ( d->stampIconName != "Draft" )
-        stampElement.setAttribute( "icon", d->stampIconName );
+    if ( stampIconName() != "Draft" )
+        stampElement.setAttribute( "icon", stampIconName() );
 }
 
 Annotation::SubType StampAnnotation::subType() const
@@ -1254,6 +1603,7 @@ class InkAnnotationPrivate : public AnnotationPrivate
 {
     public:
         InkAnnotationPrivate();
+        Annotation * makeAlias();
 
         // data fields
         QList< QLinkedList<QPointF> > inkPaths;
@@ -1264,15 +1614,22 @@ InkAnnotationPrivate::InkAnnotationPrivate()
 {
 }
 
+Annotation * InkAnnotationPrivate::makeAlias()
+{
+    return new InkAnnotation(*this);
+}
+
 InkAnnotation::InkAnnotation()
     : Annotation( *new InkAnnotationPrivate() )
 {}
 
+InkAnnotation::InkAnnotation(InkAnnotationPrivate &dd)
+    : Annotation( dd )
+{}
+
 InkAnnotation::InkAnnotation( const QDomNode & node )
     : Annotation( *new InkAnnotationPrivate(), node )
 {
-    Q_D( InkAnnotation );
-
     // loop through the whole children looking for a 'ink' element
     QDomNode subNode = node.firstChild();
     while( subNode.isElement() )
@@ -1283,6 +1640,7 @@ InkAnnotation::InkAnnotation( const QDomNode & node )
             continue;
 
         // parse the 'path' subnodes
+        QList< QLinkedList<QPointF> > paths;
         QDomNode pathNode = e.firstChild();
         while ( pathNode.isElement() )
         {
@@ -1309,8 +1667,9 @@ InkAnnotation::InkAnnotation( const QDomNode & node )
 
             // add the path to the path list if it contains at least 2 nodes
             if ( path.count() >= 2 )
-                d->inkPaths.append( path );
+                paths.append( path );
         }
+        setInkPaths(paths);
 
         // loading complete
         break;
@@ -1323,19 +1682,18 @@ InkAnnotation::~InkAnnotation()
 
 void InkAnnotation::store( QDomNode & node, QDomDocument & document ) const
 {
-    Q_D( const InkAnnotation );
-
-    // recurse to parent objects storing properties
-    Annotation::store( node, document );
+    // store base annotation properties
+    storeBaseAnnotationProperties( node, document );
 
     // create [ink] element
     QDomElement inkElement = document.createElement( "ink" );
     node.appendChild( inkElement );
 
     // append the optional attributes
-    if ( d->inkPaths.count() < 1 )
+    const QList< QLinkedList<QPointF> > paths = inkPaths();
+    if ( paths.count() < 1 )
         return;
-    QList< QLinkedList<QPointF> >::const_iterator pIt = d->inkPaths.begin(), pEnd = d->inkPaths.end();
+    QList< QLinkedList<QPointF> >::const_iterator pIt = paths.begin(), pEnd = paths.end();
     for ( ; pIt != pEnd; ++pIt )
     {
         QDomElement pathElement = document.createElement( "path" );
@@ -1377,6 +1735,7 @@ class LinkAnnotationPrivate : public AnnotationPrivate
     public:
         LinkAnnotationPrivate();
         ~LinkAnnotationPrivate();
+        Annotation * makeAlias();
 
         // data fields
         Link * linkDestination;
@@ -1394,15 +1753,22 @@ LinkAnnotationPrivate::~LinkAnnotationPrivate()
     delete linkDestination;
 }
 
+Annotation * LinkAnnotationPrivate::makeAlias()
+{
+    return new LinkAnnotation(*this);
+}
+
 LinkAnnotation::LinkAnnotation()
     : Annotation( *new LinkAnnotationPrivate() )
 {}
 
+LinkAnnotation::LinkAnnotation(LinkAnnotationPrivate &dd)
+    : Annotation( dd )
+{}
+
 LinkAnnotation::LinkAnnotation( const QDomNode & node )
     : Annotation( *new LinkAnnotationPrivate(), node )
 {
-    Q_D( LinkAnnotation );
-
     // loop through the whole children looking for a 'link' element
     QDomNode subNode = node.firstChild();
     while( subNode.isElement() )
@@ -1414,7 +1780,7 @@ LinkAnnotation::LinkAnnotation( const QDomNode & node )
 
         // parse the attributes
         if ( e.hasAttribute( "hlmode" ) )
-            d->linkHLMode = (LinkAnnotation::HighlightMode)e.attribute( "hlmode" ).toInt();
+            setLinkHighlightMode((LinkAnnotation::HighlightMode)e.attribute( "hlmode" ).toInt());
 
         // parse all 'quad' subnodes
         QDomNode quadNode = e.firstChild();
@@ -1423,14 +1789,14 @@ LinkAnnotation::LinkAnnotation( const QDomNode & node )
             QDomElement qe = quadNode.toElement();
             if ( qe.tagName() == "quad" )
             {
-                d->linkRegion[0].setX(qe.attribute( "ax", "0.0" ).toDouble());
-                d->linkRegion[0].setY(qe.attribute( "ay", "0.0" ).toDouble());
-                d->linkRegion[1].setX(qe.attribute( "bx", "0.0" ).toDouble());
-                d->linkRegion[1].setY(qe.attribute( "by", "0.0" ).toDouble());
-                d->linkRegion[2].setX(qe.attribute( "cx", "0.0" ).toDouble());
-                d->linkRegion[2].setY(qe.attribute( "cy", "0.0" ).toDouble());
-                d->linkRegion[3].setX(qe.attribute( "dx", "0.0" ).toDouble());
-                d->linkRegion[3].setY(qe.attribute( "dy", "0.0" ).toDouble());
+                setLinkRegionPoint(0, QPointF(qe.attribute( "ax", "0.0" ).toDouble(),
+                                              qe.attribute( "ay", "0.0" ).toDouble()));
+                setLinkRegionPoint(1, QPointF(qe.attribute( "bx", "0.0" ).toDouble(),
+                                              qe.attribute( "by", "0.0" ).toDouble()));
+                setLinkRegionPoint(2, QPointF(qe.attribute( "cx", "0.0" ).toDouble(),
+                                              qe.attribute( "cy", "0.0" ).toDouble()));
+                setLinkRegionPoint(3, QPointF(qe.attribute( "dx", "0.0" ).toDouble(),
+                                              qe.attribute( "dy", "0.0" ).toDouble()));
             }
             else if ( qe.tagName() == "link" )
             {
@@ -1438,17 +1804,17 @@ LinkAnnotation::LinkAnnotation( const QDomNode & node )
                 if ( type == "GoTo" )
                 {
                     Poppler::LinkGoto * go = new Poppler::LinkGoto( QRect(), qe.attribute( "filename" ), LinkDestination( qe.attribute( "destination" ) ) );
-                    d->linkDestination = go;
+                    setLinkDestination(go);
                 }
                 else if ( type == "Exec" )
                 {
                     Poppler::LinkExecute * exec = new Poppler::LinkExecute( QRect(), qe.attribute( "filename" ), qe.attribute( "parameters" ) );
-                    d->linkDestination = exec;
+                    setLinkDestination(exec);
                 }
                 else if ( type == "Browse" )
                 {
                     Poppler::LinkBrowse * browse = new Poppler::LinkBrowse( QRect(), qe.attribute( "url" ) );
-                    d->linkDestination = browse;
+                    setLinkDestination(browse);
                 }
                 else if ( type == "Action" )
                 {
@@ -1486,14 +1852,14 @@ LinkAnnotation::LinkAnnotation( const QDomNode & node )
                     if (found)
                     {
                         Poppler::LinkAction * action = new Poppler::LinkAction( QRect(), act );
-                        d->linkDestination = action;
+                        setLinkDestination(action);
                     }
                 }
 #if 0
                 else if ( type == "Movie" )
                 {
                     Poppler::LinkMovie * movie = new Poppler::LinkMovie( QRect() );
-                    d->linkDestination = movie;
+                    setLinkDestination(movie);
                 }
 #endif
             }
@@ -1510,41 +1876,39 @@ LinkAnnotation::~LinkAnnotation()
 
 void LinkAnnotation::store( QDomNode & node, QDomDocument & document ) const
 {
-    Q_D( const LinkAnnotation );
-
-    // recurse to parent objects storing properties
-    Annotation::store( node, document );
+    // store base annotation properties
+    storeBaseAnnotationProperties( node, document );
 
     // create [hl] element
     QDomElement linkElement = document.createElement( "link" );
     node.appendChild( linkElement );
 
     // append the optional attributes
-    if ( d->linkHLMode != Invert )
-        linkElement.setAttribute( "hlmode", (int)d->linkHLMode );
+    if ( linkHighlightMode() != Invert )
+        linkElement.setAttribute( "hlmode", (int)linkHighlightMode() );
 
     // saving region
     QDomElement quadElement = document.createElement( "quad" );
     linkElement.appendChild( quadElement );
-    quadElement.setAttribute( "ax", QString::number( d->linkRegion[0].x() ) );
-    quadElement.setAttribute( "ay", QString::number( d->linkRegion[0].y() ) );
-    quadElement.setAttribute( "bx", QString::number( d->linkRegion[1].x() ) );
-    quadElement.setAttribute( "by", QString::number( d->linkRegion[1].y() ) );
-    quadElement.setAttribute( "cx", QString::number( d->linkRegion[2].x() ) );
-    quadElement.setAttribute( "cy", QString::number( d->linkRegion[2].y() ) );
-    quadElement.setAttribute( "dx", QString::number( d->linkRegion[3].x() ) );
-    quadElement.setAttribute( "dy", QString::number( d->linkRegion[3].y() ) );
+    quadElement.setAttribute( "ax", QString::number( linkRegionPoint(0).x() ) );
+    quadElement.setAttribute( "ay", QString::number( linkRegionPoint(0).y() ) );
+    quadElement.setAttribute( "bx", QString::number( linkRegionPoint(1).x() ) );
+    quadElement.setAttribute( "by", QString::number( linkRegionPoint(1).y() ) );
+    quadElement.setAttribute( "cx", QString::number( linkRegionPoint(2).x() ) );
+    quadElement.setAttribute( "cy", QString::number( linkRegionPoint(2).y() ) );
+    quadElement.setAttribute( "dx", QString::number( linkRegionPoint(3).x() ) );
+    quadElement.setAttribute( "dy", QString::number( linkRegionPoint(3).y() ) );
 
     // saving link
     QDomElement hyperlinkElement = document.createElement( "link" );
     linkElement.appendChild( hyperlinkElement );
-    if ( d->linkDestination )
+    if ( linkDestination() )
     {
-        switch( d->linkDestination->linkType() )
+        switch( linkDestination()->linkType() )
         {
             case Poppler::Link::Goto:
             {
-                Poppler::LinkGoto * go = static_cast< Poppler::LinkGoto * >( d->linkDestination );
+                Poppler::LinkGoto * go = static_cast< Poppler::LinkGoto * >( linkDestination() );
                 hyperlinkElement.setAttribute( "type", "GoTo" );
                 hyperlinkElement.setAttribute( "filename", go->fileName() );
                 hyperlinkElement.setAttribute( "destionation", go->destination().toString() );
@@ -1552,7 +1916,7 @@ void LinkAnnotation::store( QDomNode & node, QDomDocument & document ) const
             }
             case Poppler::Link::Execute:
             {
-                Poppler::LinkExecute * exec = static_cast< Poppler::LinkExecute * >( d->linkDestination );
+                Poppler::LinkExecute * exec = static_cast< Poppler::LinkExecute * >( linkDestination() );
                 hyperlinkElement.setAttribute( "type", "Exec" );
                 hyperlinkElement.setAttribute( "filename", exec->fileName() );
                 hyperlinkElement.setAttribute( "parameters", exec->parameters() );
@@ -1560,14 +1924,14 @@ void LinkAnnotation::store( QDomNode & node, QDomDocument & document ) const
             }
             case Poppler::Link::Browse:
             {
-                Poppler::LinkBrowse * browse = static_cast< Poppler::LinkBrowse * >( d->linkDestination );
+                Poppler::LinkBrowse * browse = static_cast< Poppler::LinkBrowse * >( linkDestination() );
                 hyperlinkElement.setAttribute( "type", "Browse" );
                 hyperlinkElement.setAttribute( "url", browse->url() );
                 break;
             }
             case Poppler::Link::Action:
             {
-                Poppler::LinkAction * action = static_cast< Poppler::LinkAction * >( d->linkDestination );
+                Poppler::LinkAction * action = static_cast< Poppler::LinkAction * >( linkDestination() );
                 hyperlinkElement.setAttribute( "type", "Action" );
                 switch ( action->actionType() )
                 {
@@ -1639,7 +2003,7 @@ Annotation::SubType LinkAnnotation::subType() const
     return ALink;
 }
 
-Link* LinkAnnotation::linkDestionation() const
+Link* LinkAnnotation::linkDestination() const
 {
     Q_D( const LinkAnnotation );
     return d->linkDestination;
@@ -1687,6 +2051,7 @@ class CaretAnnotationPrivate : public AnnotationPrivate
 {
     public:
         CaretAnnotationPrivate();
+        Annotation * makeAlias();
 
         // data fields
         CaretAnnotation::CaretSymbol symbol;
@@ -1718,16 +2083,24 @@ CaretAnnotationPrivate::CaretAnnotationPrivate()
 {
 }
 
+Annotation * CaretAnnotationPrivate::makeAlias()
+{
+    return new CaretAnnotation(*this);
+}
+
 CaretAnnotation::CaretAnnotation()
     : Annotation( *new CaretAnnotationPrivate() )
 {
 }
 
+CaretAnnotation::CaretAnnotation(CaretAnnotationPrivate &dd)
+    : Annotation( dd )
+{
+}
+
 CaretAnnotation::CaretAnnotation( const QDomNode & node )
     : Annotation( *new CaretAnnotationPrivate(), node )
 {
-    Q_D( CaretAnnotation );
-
     // loop through the whole children looking for a 'caret' element
     QDomNode subNode = node.firstChild();
     while( subNode.isElement() )
@@ -1739,7 +2112,7 @@ CaretAnnotation::CaretAnnotation( const QDomNode & node )
 
         // parse the attributes
         if ( e.hasAttribute( "symbol" ) )
-            d->symbol = caretSymbolFromString( e.attribute( "symbol" ) );
+            setCaretSymbol(caretSymbolFromString( e.attribute( "symbol" ) ));
 
         // loading complete
         break;
@@ -1752,18 +2125,16 @@ CaretAnnotation::~CaretAnnotation()
 
 void CaretAnnotation::store( QDomNode & node, QDomDocument & document ) const
 {
-    Q_D( const CaretAnnotation );
-
-    // recurse to parent objects storing properties
-    Annotation::store( node, document );
+    // store base annotation properties
+    storeBaseAnnotationProperties( node, document );
 
     // create [caret] element
     QDomElement caretElement = document.createElement( "caret" );
     node.appendChild( caretElement );
 
     // append the optional attributes
-    if ( d->symbol != CaretAnnotation::None )
-        caretElement.setAttribute( "symbol", caretSymbolToString( d->symbol ) );
+    if ( caretSymbol() != CaretAnnotation::None )
+        caretElement.setAttribute( "symbol", caretSymbolToString( caretSymbol() ) );
 }
 
 Annotation::SubType CaretAnnotation::subType() const
@@ -1789,6 +2160,7 @@ class FileAttachmentAnnotationPrivate : public AnnotationPrivate
     public:
         FileAttachmentAnnotationPrivate();
         ~FileAttachmentAnnotationPrivate();
+        Annotation * makeAlias();
 
         // data fields
         QString icon;
@@ -1805,11 +2177,21 @@ FileAttachmentAnnotationPrivate::~FileAttachmentAnnotationPrivate()
     delete embfile;
 }
 
+Annotation * FileAttachmentAnnotationPrivate::makeAlias()
+{
+    return new FileAttachmentAnnotation(*this);
+}
+
 FileAttachmentAnnotation::FileAttachmentAnnotation()
     : Annotation( *new FileAttachmentAnnotationPrivate() )
 {
 }
 
+FileAttachmentAnnotation::FileAttachmentAnnotation(FileAttachmentAnnotationPrivate &dd)
+    : Annotation( dd )
+{
+}
+
 FileAttachmentAnnotation::FileAttachmentAnnotation( const QDomNode & node )
     : Annotation( *new FileAttachmentAnnotationPrivate(), node )
 {
@@ -1833,8 +2215,8 @@ FileAttachmentAnnotation::~FileAttachmentAnnotation()
 
 void FileAttachmentAnnotation::store( QDomNode & node, QDomDocument & document ) const
 {
-    // recurse to parent objects storing properties
-    Annotation::store( node, document );
+    // store base annotation properties
+    storeBaseAnnotationProperties( node, document );
 
     // create [fileattachment] element
     QDomElement fileAttachmentElement = document.createElement( "fileattachment" );
@@ -1876,6 +2258,7 @@ class SoundAnnotationPrivate : public AnnotationPrivate
     public:
         SoundAnnotationPrivate();
         ~SoundAnnotationPrivate();
+        Annotation * makeAlias();
 
         // data fields
         QString icon;
@@ -1892,11 +2275,21 @@ SoundAnnotationPrivate::~SoundAnnotationPrivate()
     delete sound;
 }
 
+Annotation * SoundAnnotationPrivate::makeAlias()
+{
+    return new SoundAnnotation(*this);
+}
+
 SoundAnnotation::SoundAnnotation()
     : Annotation( *new SoundAnnotationPrivate() )
 {
 }
 
+SoundAnnotation::SoundAnnotation(SoundAnnotationPrivate &dd)
+    : Annotation( dd )
+{
+}
+
 SoundAnnotation::SoundAnnotation( const QDomNode & node )
     : Annotation( *new SoundAnnotationPrivate(), node )
 {
@@ -1920,8 +2313,8 @@ SoundAnnotation::~SoundAnnotation()
 
 void SoundAnnotation::store( QDomNode & node, QDomDocument & document ) const
 {
-    // recurse to parent objects storing properties
-    Annotation::store( node, document );
+    // store base annotation properties
+    storeBaseAnnotationProperties( node, document );
 
     // create [sound] element
     QDomElement soundElement = document.createElement( "sound" );
@@ -1963,6 +2356,7 @@ class MovieAnnotationPrivate : public AnnotationPrivate
     public:
         MovieAnnotationPrivate();
         ~MovieAnnotationPrivate();
+        Annotation * makeAlias();
 
         // data fields
         MovieObject *movie;
@@ -1979,11 +2373,21 @@ MovieAnnotationPrivate::~MovieAnnotationPrivate()
     delete movie;
 }
 
+Annotation * MovieAnnotationPrivate::makeAlias()
+{
+    return new MovieAnnotation(*this);
+}
+
 MovieAnnotation::MovieAnnotation()
     : Annotation( *new MovieAnnotationPrivate() )
 {
 }
 
+MovieAnnotation::MovieAnnotation(MovieAnnotationPrivate &dd)
+    : Annotation( dd )
+{
+}
+
 MovieAnnotation::MovieAnnotation( const QDomNode & node )
     : Annotation( *new MovieAnnotationPrivate(), node )
 {
@@ -2007,8 +2411,8 @@ MovieAnnotation::~MovieAnnotation()
 
 void MovieAnnotation::store( QDomNode & node, QDomDocument & document ) const
 {
-    // recurse to parent objects storing properties
-    Annotation::store( node, document );
+    // store base annotation properties
+    storeBaseAnnotationProperties( node, document );
 
     // create [movie] element
     QDomElement movieElement = document.createElement( "movie" );
@@ -2050,6 +2454,7 @@ class ScreenAnnotationPrivate : public AnnotationPrivate
     public:
         ScreenAnnotationPrivate();
         ~ScreenAnnotationPrivate();
+        Annotation * makeAlias();
 
         // data fields
         LinkRendition *action;
@@ -2066,6 +2471,15 @@ ScreenAnnotationPrivate::~ScreenAnnotationPrivate()
     delete action;
 }
 
+ScreenAnnotation::ScreenAnnotation(ScreenAnnotationPrivate &dd)
+    : Annotation( dd )
+{}
+
+Annotation * ScreenAnnotationPrivate::makeAlias()
+{
+    return new ScreenAnnotation(*this);
+}
+
 ScreenAnnotation::ScreenAnnotation()
     : Annotation( *new ScreenAnnotationPrivate() )
 {
@@ -2075,6 +2489,16 @@ ScreenAnnotation::~ScreenAnnotation()
 {
 }
 
+void ScreenAnnotation::store( QDomNode & node, QDomDocument & document ) const
+{
+    // store base annotation properties
+    storeBaseAnnotationProperties( node, document );
+
+    // create [screen] element
+    QDomElement screenElement = document.createElement( "screen" );
+    node.appendChild( screenElement );
+}
+
 Annotation::SubType ScreenAnnotation::subType() const
 {
     return AScreen;
diff --git a/qt4/src/poppler-annotation.h b/qt4/src/poppler-annotation.h
index 7700c7a..b760702 100644
--- a/qt4/src/poppler-annotation.h
+++ b/qt4/src/poppler-annotation.h
@@ -5,6 +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>
  * Adapting code from
  *   Copyright (C) 2004 by Enrico Ros <eros.kde at email.it>
  *
@@ -27,10 +28,12 @@
 #define _POPPLER_ANNOTATION_H_
 
 #include <QtCore/QDateTime>
+#include <QtCore/QSharedDataPointer>
 #include <QtCore/QLinkedList>
 #include <QtCore/QList>
 #include <QtCore/QPointF>
 #include <QtCore/QRectF>
+#include <QtCore/QVector>
 #include <QtGui/QColor>
 #include <QtGui/QFont>
 #include <QtXml/QDomDocument>
@@ -57,6 +60,7 @@ class Link;
 class SoundObject;
 class MovieObject;
 class LinkRendition;
+class Page;
 
 /**
  * \short Helper class for (recursive) Annotation retrieval/storage.
@@ -94,9 +98,13 @@ class POPPLER_QT4_EXPORT AnnotationUtils
  *
  * An Annotation is an object (text note, highlight, sound, popup window, ..)
  * contained by a Page in the document.
+ *
+ * \warning Different Annotation objects might point to the same annotation.
+ *          Use uniqueName to test for Annotation equality
  */
 class POPPLER_QT4_EXPORT Annotation
 {
+  friend class AnnotationUtils;
   friend class LinkMovie;
   friend class Page;
 
@@ -110,7 +118,7 @@ class POPPLER_QT4_EXPORT 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 { Reply = 1, Group = 2, Delete = 4 };
+    enum RevScope { Root = 0, Reply = 1, Group = 2, Delete = 4 };
     enum RevType { None = 1,  Marked = 2, Unmarked = 4,  Accepted = 8, Rejected = 16, Cancelled = 32, Completed = 64 };
 
     /**
@@ -148,67 +156,117 @@ class POPPLER_QT4_EXPORT Annotation
     QRectF boundary() const;
     void setBoundary( const QRectF &boundary );
 
-    struct POPPLER_QT4_EXPORT Style
+    /**
+     * \short Container class for Annotation style information
+     *
+     * \since 0.20
+     */
+    class POPPLER_QT4_EXPORT Style
     {
+      public:
+        Style();
+        Style( const Style &other );
+        Style& operator=( const Style &other );
+        ~Style();
+
         // appearance properties
-        QColor          color;              // black
-        double          opacity;            // 1.0
+        QColor color() const;                     // black
+        void setColor(const QColor &color);
+        double opacity() const;                   // 1.0
+        void setOpacity(double opacity);
+
         // pen properties
-        double          width;              // 1.0
-        LineStyle       style;              // LineStyle::Solid
-        double          xCorners;           // 0.0
-        double          yCorners;           // 0.0
-        int             marks;              // 3
-        int             spaces;             // 0
+        double width() const;                     // 1.0
+        void setWidth(double width);
+        LineStyle lineStyle() const;              // LineStyle::Solid
+        void setLineStyle(LineStyle style);
+        double xCorners() const;                  // 0.0
+        void setXCorners(double radius);
+        double yCorners() const;                  // 0.0
+        void setYCorners(double radius);
+        const QVector<double>& dashArray() const; // [ 3 ]
+        void setDashArray(const QVector<double> &array);
+
         // pen effects
-        LineEffect      effect;             // LineEffect::NoEffect
-        double          effectIntensity;    // 1.0
-        // default initializer
-        Style();
-    }               style;
+        LineEffect lineEffect() const;            // LineEffect::NoEffect
+        void setLineEffect(LineEffect effect);
+        double effectIntensity() const;           // 1.0
+        void setEffectIntensity(double intens);
+
+      private:
+        class Private;
+        QSharedDataPointer<Private> d;
+    };
+
+    /// \since 0.20
+    Style style() const;
+    /// \since 0.20
+    void setStyle( const Style& style );
 
-    /* properties: popup window */
-    struct POPPLER_QT4_EXPORT Window
+    /**
+     * \short Container class for Annotation pop-up window information
+     *
+     * \since 0.20
+     */
+    class POPPLER_QT4_EXPORT Popup
     {
+      public:
+        Popup();
+        Popup( const Popup &other );
+        Popup& operator=( const Popup &other );
+        ~Popup();
+
         // window state (Hidden, FixedRotation, Deny* flags allowed)
-        int             flags;              // -1 (never initialized) -> 0 (if inited and shown)
+        int flags() const;       // -1 (never initialized) -> 0 (if inited and shown)
+        void setFlags( int flags );
+
         // geometric properties
-        QPointF         topLeft;            // no default, inited to boundary.topLeft
-        int             width;              // no default
-        int             height;             // no default
+        QRectF geometry() const; // no default
+        void setGeometry( const QRectF &geom );
+
         // window contens/override properties
-        QString         title;              // '' text in the titlebar (overrides author)
-        QString         summary;            // '' short description (displayed if not empty)
-        QString         text;               // '' text for the window (overrides annot->contents)
-        // default initializer
-        Window();
-    }               window;
-
-    /* properties: versioning */
-    struct POPPLER_QT4_EXPORT Revision
-    {
-        // child revision
-        Annotation *    annotation;         // not null
-        // scope and type of revision
-        RevScope        scope;              // Reply
-        RevType         type;               // None
-        // default initializer
-        Revision();
+        QString title() const;   // '' text in the titlebar (overrides author)
+        void setTitle( const QString &title );
+        QString summary() const; // '' short description (displayed if not empty)
+        void setSummary( const QString &summary );
+        QString text() const;    // '' text for the window (overrides annot->contents)
+        void setText( const QString &text );
+
+      private:
+        class Private;
+        QSharedDataPointer<Private> d;
     };
 
-    QLinkedList< Revision >& revisions();
-    const QLinkedList< Revision >& revisions() const;
+    /// \since 0.20
+    Popup popup() const;
+    /// \since 0.20
+    void setPopup( const Popup& popup );
+
+    /// \cond PRIVATE
+    // This field is deprecated and not used any more.
+    struct { int width, height; } window; // Always set to zero
+    /// \endcond
+
+    /// \since 0.20
+    RevScope revisionScope() const; // Root
+
+    /// \since 0.20
+    RevType revisionType() const;   // None
 
-    // methods: query annotation's type for runtime type identification
     /**
-     * The type of the annotation.
+     * Returns the revisions of this annotation
+     *
+     * \note The caller owns the returned annotations and they should
+     *       be deleted when no longer required.
+     *
+     * \since 0.20
      */
-    virtual SubType subType() const = 0;
+    QList<Annotation*> revisions() const;
 
     /**
-     * Save this annotation as a child of \p parentNode.
+     * The type of the annotation.
      */
-    virtual void store( QDomNode & parentNode, QDomDocument & document ) const;
+    virtual SubType subType() const = 0;
 
     /**
      * Destructor.
@@ -219,11 +277,26 @@ class POPPLER_QT4_EXPORT Annotation
     /// \cond PRIVATE
     Annotation( AnnotationPrivate &dd );
     Annotation( AnnotationPrivate &dd, const QDomNode &description );
+    void storeBaseAnnotationProperties( QDomNode & parentNode, QDomDocument & document ) const;
     Q_DECLARE_PRIVATE( Annotation )
-    AnnotationPrivate *d_ptr;
+    QExplicitlySharedDataPointer<AnnotationPrivate> d_ptr;
+
+    //BEGIN: To be made public when revision write support is implemented
+    void setRevisionType( RevType type );
+    void setRevisionScope( RevScope scope );
+    /**
+     * Adds a revision to this annotation. Scope and type are assigned to the
+     * newly added annotation.
+     *
+     * \note Ownership of the annotation object stays with the caller, who can
+     *       delete it at any time.
+     */
+    void addRevision( Annotation *ann, RevScope scope = Reply, RevType type = None );
+    //END
     /// \endcond
 
   private:
+    virtual void store( QDomNode & parentNode, QDomDocument & document ) const = 0;
     Q_DISABLE_COPY( Annotation )
 };
 
@@ -235,11 +308,11 @@ class POPPLER_QT4_EXPORT Annotation
  */
 class POPPLER_QT4_EXPORT TextAnnotation : public Annotation
 {
+  friend class Page;
+  friend class AnnotationUtils;
+
   public:
-    TextAnnotation();
-    TextAnnotation( const QDomNode &node );
     virtual ~TextAnnotation();
-    virtual void store( QDomNode &parentNode, QDomDocument &document ) const;
     virtual SubType subType() const;
 
     // local enums
@@ -283,7 +356,17 @@ class POPPLER_QT4_EXPORT TextAnnotation : public Annotation
     int inplaceAlign() const;
     void setInplaceAlign( int align );
 
+    /**
+       Synonym for contents()
+
+       \deprecated Use contents() instead
+    */
     QString inplaceText() const;
+    /**
+       Synonym for setContents()
+
+       \deprecated Use setContents() instead
+    */
     void setInplaceText( const QString &text );
 
     QPointF calloutPoint( int id ) const;
@@ -293,6 +376,10 @@ class POPPLER_QT4_EXPORT TextAnnotation : public Annotation
     void setInplaceIntent( InplaceIntent intent );
 
   private:
+    TextAnnotation();
+    TextAnnotation( const QDomNode &node );
+    TextAnnotation( TextAnnotationPrivate &dd );
+    virtual void store( QDomNode &parentNode, QDomDocument &document ) const;
     Q_DECLARE_PRIVATE( TextAnnotation )
     Q_DISABLE_COPY( TextAnnotation )
 };
@@ -304,11 +391,11 @@ class POPPLER_QT4_EXPORT TextAnnotation : public Annotation
  */
 class POPPLER_QT4_EXPORT LineAnnotation : public Annotation
 {
+  friend class Page;
+  friend class AnnotationUtils;
+
   public:
-    LineAnnotation();
-    LineAnnotation( const QDomNode &node );
     virtual ~LineAnnotation();
-    virtual void store( QDomNode &parentNode, QDomDocument &document ) const;
     virtual SubType subType() const;
 
     // local enums
@@ -344,6 +431,10 @@ class POPPLER_QT4_EXPORT LineAnnotation : public Annotation
     void setLineIntent( LineIntent intent );
 
   private:
+    LineAnnotation();
+    LineAnnotation( const QDomNode &node );
+    LineAnnotation( LineAnnotationPrivate &dd );
+    virtual void store( QDomNode &parentNode, QDomDocument &document ) const;
     Q_DECLARE_PRIVATE( LineAnnotation )
     Q_DISABLE_COPY( LineAnnotation )
 };
@@ -356,11 +447,11 @@ class POPPLER_QT4_EXPORT LineAnnotation : public Annotation
  */
 class POPPLER_QT4_EXPORT GeomAnnotation : public Annotation
 {
+  friend class Page;
+  friend class AnnotationUtils;
+
   public:
-    GeomAnnotation();
-    GeomAnnotation( const QDomNode &node );
     virtual ~GeomAnnotation();
-    virtual void store( QDomNode &parentNode, QDomDocument &document ) const;
     virtual SubType subType() const;
 
     // common enums
@@ -372,10 +463,11 @@ class POPPLER_QT4_EXPORT GeomAnnotation : public Annotation
     QColor geomInnerColor() const;
     void setGeomInnerColor( const QColor &color );
 
-    int geomPointWidth() const;
-    void setGeomPointWidth( int width );
-
   private:
+    GeomAnnotation();
+    GeomAnnotation( const QDomNode &node );
+    GeomAnnotation( GeomAnnotationPrivate &dd );
+    virtual void store( QDomNode &parentNode, QDomDocument &document ) const;
     Q_DECLARE_PRIVATE( GeomAnnotation )
     Q_DISABLE_COPY( GeomAnnotation )
 };
@@ -387,11 +479,11 @@ class POPPLER_QT4_EXPORT GeomAnnotation : public Annotation
  */
 class POPPLER_QT4_EXPORT HighlightAnnotation : public Annotation
 {
+  friend class Page;
+  friend class AnnotationUtils;
+
   public:
-    HighlightAnnotation();
-    HighlightAnnotation( const QDomNode &node );
     virtual ~HighlightAnnotation();
-    virtual void store( QDomNode &parentNode, QDomDocument &document ) const;
     virtual SubType subType() const;
 
     /**
@@ -439,6 +531,10 @@ class POPPLER_QT4_EXPORT HighlightAnnotation : public Annotation
     void setHighlightQuads( const QList< Quad > &quads );
 
   private:
+    HighlightAnnotation();
+    HighlightAnnotation( const QDomNode &node );
+    HighlightAnnotation( HighlightAnnotationPrivate &dd );
+    virtual void store( QDomNode &parentNode, QDomDocument &document ) const;
     Q_DECLARE_PRIVATE( HighlightAnnotation )
     Q_DISABLE_COPY( HighlightAnnotation )
 };
@@ -450,11 +546,11 @@ class POPPLER_QT4_EXPORT HighlightAnnotation : public Annotation
  */
 class POPPLER_QT4_EXPORT StampAnnotation : public Annotation
 {
+  friend class Page;
+  friend class AnnotationUtils;
+
   public:
-    StampAnnotation();
-    StampAnnotation( const QDomNode &node );
     virtual ~StampAnnotation();
-    virtual void store( QDomNode &parentNode, QDomDocument &document ) const;
     virtual SubType subType() const;
 
     /**
@@ -486,6 +582,10 @@ class POPPLER_QT4_EXPORT StampAnnotation : public Annotation
     void setStampIconName( const QString &name );
 
   private:
+    StampAnnotation();
+    StampAnnotation( const QDomNode &node );
+    StampAnnotation( StampAnnotationPrivate &dd );
+    virtual void store( QDomNode &parentNode, QDomDocument &document ) const;
     Q_DECLARE_PRIVATE( StampAnnotation )
     Q_DISABLE_COPY( StampAnnotation )
 };
@@ -497,34 +597,37 @@ class POPPLER_QT4_EXPORT StampAnnotation : public Annotation
  */
 class POPPLER_QT4_EXPORT InkAnnotation : public Annotation
 {
+  friend class Page;
+  friend class AnnotationUtils;
+
   public:
-    InkAnnotation();
-    InkAnnotation( const QDomNode &node );
     virtual ~InkAnnotation();
-    virtual void store( QDomNode &parentNode, QDomDocument &document ) const;
     virtual SubType subType() const;
 
     QList< QLinkedList<QPointF> > inkPaths() const;
     void setInkPaths( const QList< QLinkedList<QPointF> > &paths );
 
   private:
+    InkAnnotation();
+    InkAnnotation( const QDomNode &node );
+    virtual void store( QDomNode &parentNode, QDomDocument &document ) const;
+    InkAnnotation(InkAnnotationPrivate &dd);
     Q_DECLARE_PRIVATE( InkAnnotation )
     Q_DISABLE_COPY( InkAnnotation )
 };
 
 class POPPLER_QT4_EXPORT LinkAnnotation : public Annotation
 {
+  friend class Page;
+
   public:
-    LinkAnnotation();
-    LinkAnnotation( const QDomNode &node );
     virtual ~LinkAnnotation();
-    virtual void store( QDomNode &parentNode, QDomDocument &document ) const;
     virtual SubType subType() const;
 
     // local enums
     enum HighlightMode { None, Invert, Outline, Push };
 
-    Link* linkDestionation() const;
+    Link* linkDestination() const;
     void setLinkDestination( Link *link );
 
     HighlightMode linkHighlightMode() const;
@@ -534,6 +637,10 @@ class POPPLER_QT4_EXPORT LinkAnnotation : public Annotation
     void setLinkRegionPoint( int id, const QPointF &point );
 
   private:
+    LinkAnnotation();
+    LinkAnnotation( const QDomNode &node );
+    LinkAnnotation( LinkAnnotationPrivate &dd );
+    virtual void store( QDomNode &parentNode, QDomDocument &document ) const;
     Q_DECLARE_PRIVATE( LinkAnnotation )
     Q_DISABLE_COPY( LinkAnnotation )
 };
@@ -545,11 +652,11 @@ class POPPLER_QT4_EXPORT LinkAnnotation : public Annotation
  */
 class POPPLER_QT4_EXPORT CaretAnnotation : public Annotation
 {
+  friend class Page;
+  friend class AnnotationUtils;
+
   public:
-    CaretAnnotation();
-    CaretAnnotation( const QDomNode &node );
     virtual ~CaretAnnotation();
-    virtual void store( QDomNode &parentNode, QDomDocument &document ) const;
     virtual SubType subType() const;
 
     /**
@@ -561,6 +668,10 @@ class POPPLER_QT4_EXPORT CaretAnnotation : public Annotation
     void setCaretSymbol( CaretSymbol symbol );
 
   private:
+    CaretAnnotation();
+    CaretAnnotation( const QDomNode &node );
+    CaretAnnotation( CaretAnnotationPrivate &dd );
+    virtual void store( QDomNode &parentNode, QDomDocument &document ) const;
     Q_DECLARE_PRIVATE( CaretAnnotation )
     Q_DISABLE_COPY( CaretAnnotation )
 };
@@ -574,11 +685,10 @@ class POPPLER_QT4_EXPORT CaretAnnotation : public Annotation
  */
 class POPPLER_QT4_EXPORT FileAttachmentAnnotation : public Annotation
 {
+  friend class Page;
+
   public:
-    FileAttachmentAnnotation();
-    FileAttachmentAnnotation( const QDomNode &node );
     virtual ~FileAttachmentAnnotation();
-    virtual void store( QDomNode &parentNode, QDomDocument &document ) const;
     virtual SubType subType() const;
 
     /**
@@ -602,6 +712,10 @@ class POPPLER_QT4_EXPORT FileAttachmentAnnotation : public Annotation
     void setEmbeddedFile( EmbeddedFile *ef );
 
   private:
+    FileAttachmentAnnotation();
+    FileAttachmentAnnotation( const QDomNode &node );
+    FileAttachmentAnnotation( FileAttachmentAnnotationPrivate &dd );
+    virtual void store( QDomNode &parentNode, QDomDocument &document ) const;
     Q_DECLARE_PRIVATE( FileAttachmentAnnotation )
     Q_DISABLE_COPY( FileAttachmentAnnotation )
 };
@@ -615,11 +729,10 @@ class POPPLER_QT4_EXPORT FileAttachmentAnnotation : public Annotation
  */
 class POPPLER_QT4_EXPORT SoundAnnotation : public Annotation
 {
+  friend class Page;
+
   public:
-    SoundAnnotation();
-    SoundAnnotation( const QDomNode &node );
     virtual ~SoundAnnotation();
-    virtual void store( QDomNode &parentNode, QDomDocument &document ) const;
     virtual SubType subType() const;
 
     /**
@@ -643,6 +756,10 @@ class POPPLER_QT4_EXPORT SoundAnnotation : public Annotation
     void setSound( SoundObject *ef );
 
   private:
+    SoundAnnotation();
+    SoundAnnotation( const QDomNode &node );
+    SoundAnnotation( SoundAnnotationPrivate &dd );
+    virtual void store( QDomNode &parentNode, QDomDocument &document ) const;
     Q_DECLARE_PRIVATE( SoundAnnotation )
     Q_DISABLE_COPY( SoundAnnotation )
 };
@@ -656,11 +773,10 @@ class POPPLER_QT4_EXPORT SoundAnnotation : public Annotation
  */
 class POPPLER_QT4_EXPORT MovieAnnotation : public Annotation
 {
+  friend class Page;
+
   public:
-    MovieAnnotation();
-    MovieAnnotation( const QDomNode &node );
     virtual ~MovieAnnotation();
-    virtual void store( QDomNode &parentNode, QDomDocument &document ) const;
     virtual SubType subType() const;
 
     /**
@@ -684,6 +800,10 @@ class POPPLER_QT4_EXPORT MovieAnnotation : public Annotation
     void setMovieTitle( const QString &title );
 
   private:
+    MovieAnnotation();
+    MovieAnnotation( const QDomNode &node );
+    MovieAnnotation( MovieAnnotationPrivate &dd );
+    virtual void store( QDomNode &parentNode, QDomDocument &document ) const;
     Q_DECLARE_PRIVATE( MovieAnnotation )
     Q_DISABLE_COPY( MovieAnnotation )
 };
@@ -697,8 +817,9 @@ class POPPLER_QT4_EXPORT MovieAnnotation : public Annotation
  */
 class POPPLER_QT4_EXPORT ScreenAnnotation : public Annotation
 {
+  friend class Page;
+
   public:
-    ScreenAnnotation();
     virtual ~ScreenAnnotation();
 
     virtual SubType subType() const;
@@ -726,6 +847,9 @@ class POPPLER_QT4_EXPORT ScreenAnnotation : public Annotation
     void setScreenTitle( const QString &title );
 
   private:
+    ScreenAnnotation();
+    ScreenAnnotation( ScreenAnnotationPrivate &dd );
+    virtual void store( QDomNode &parentNode, QDomDocument &document ) const; // stub
     Q_DECLARE_PRIVATE( ScreenAnnotation )
     Q_DISABLE_COPY( ScreenAnnotation )
 };
diff --git a/qt4/src/poppler-page.cc b/qt4/src/poppler-page.cc
index 44a117b..924c646 100644
--- a/qt4/src/poppler-page.cc
+++ b/qt4/src/poppler-page.cc
@@ -11,6 +11,7 @@
  * Copyright (C) 2010 Matthias Fauconneau <matthias.fauconneau at gmail.com>
  * Copyright (C) 2010 Hib Eris <hib at hiberis.nl>
  * Copyright (C) 2012 Tobias Koenig <tokoe at kdab.com>
+ * Copyright (C) 2012 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
@@ -62,17 +63,6 @@
 
 namespace Poppler {
 
-class DummyAnnotation : public Annotation
-{
-    public:
-        DummyAnnotation()
-            : Annotation( *new AnnotationPrivate() )
-        {
-        }
-
-        virtual SubType subType() const { return A_BASE; }
-};
-
 Link* PageData::convertLinkActionToLink(::LinkAction * a, const QRectF &linkArea)
 {
     return convertLinkActionToLink(a, parentDoc, linkArea);
@@ -698,9 +688,9 @@ QList<Annotation*> Page::annotations() const
                 if ( border_effect )
                 {
                     // -> style.effect
-                    t->style.effect = (Annotation::LineEffect)border_effect->getEffectType();
+                    t->d_ptr->style.setLineEffect( (Annotation::LineEffect)border_effect->getEffectType() );
                     // -> style.effectIntensity
-                    t->style.effectIntensity = (int)border_effect->getIntensity();
+                    t->d_ptr->style.setEffectIntensity( (int)border_effect->getIntensity() );
                 }
                 break;
             }
@@ -797,9 +787,9 @@ QList<Annotation*> Page::annotations() const
                 if ( border_effect )
                 {
                     // -> style.effect
-                    g->style.effect = (Annotation::LineEffect)border_effect->getEffectType();
+                    g->d_ptr->style.setLineEffect( (Annotation::LineEffect)border_effect->getEffectType() );
                     // -> style.effectIntensity
-                    g->style.effectIntensity = (int)border_effect->getIntensity();
+                    g->d_ptr->style.setEffectIntensity( (int)border_effect->getIntensity() );
                 }
 
                 // TODO RD
@@ -918,8 +908,8 @@ QList<Annotation*> Page::annotations() const
                 // no need to parse parent annotation id
                 //XPDFReader::lookupIntRef( annotDict, "Parent", popup->... );
 
-                // use the 'dummy annotation' for getting other parameters
-                popup->dummyAnnotation = new DummyAnnotation();
+                // pretend it's a GeomAnnotation for getting other parameters
+                popup->dummyAnnotation = new GeomAnnotation();
                 annotation = popup->dummyAnnotation;
 
                 break;
@@ -1122,14 +1112,14 @@ QList<Annotation*> Page::annotations() const
             {
                 AnnotBorderArray * border_array = static_cast< AnnotBorderArray * >( border );
                 // -> style.xCorners
-                annotation->style.xCorners = border_array->getHorizontalCorner();
+                annotation->d_ptr->style.setXCorners(border_array->getHorizontalCorner());
                 // -> style.yCorners
-                annotation->style.yCorners = border_array->getVerticalCorner();
+                annotation->d_ptr->style.setYCorners(border_array->getVerticalCorner());
             }
             // -> style.width
-            annotation->style.width = border->getWidth();
+            annotation->d_ptr->style.setWidth(border->getWidth());
             // -> style.style
-            annotation->style.style = (Annotation::LineStyle)( 1 << border->getStyle() );
+            annotation->d_ptr->style.setLineStyle((Annotation::LineStyle)( 1 << border->getStyle() ));
 #if 0
             // -> style.marks and style.spaces
             // TODO
@@ -1154,7 +1144,7 @@ QList<Annotation*> Page::annotations() const
 #endif
         }
         // -> style.color
-        annotation->style.color = convertAnnotColor( ann->getColor() );
+        annotation->d_ptr->style.setColor(convertAnnotColor( ann->getColor() ));
 
         /** 1.4. PARSE markup { common, Popup, Revision } parameters */
         if ( markupann )
@@ -1166,12 +1156,12 @@ QList<Annotation*> Page::annotations() const
                 annotation->setCreationDate( convertDate( createDate->getCString() ) );
             }
             // -> style.opacity
-            annotation->style.opacity = markupann->getOpacity();
+            annotation->d_ptr->style.setOpacity( markupann->getOpacity() );
             // -> window.title and author
-            annotation->window.title = UnicodeParsedString( markupann->getLabel() );
-            annotation->setAuthor( annotation->window.title );
+            annotation->d_ptr->popup.setTitle(UnicodeParsedString( markupann->getLabel() ));
+            annotation->setAuthor( annotation->d_ptr->popup.title() );
             // -> window.summary
-            annotation->window.summary = UnicodeParsedString( markupann->getSubject() );
+            annotation->d_ptr->popup.setSummary(UnicodeParsedString( markupann->getSubject() ));
 #if 0
             // -> window.text
             // TODO
@@ -1271,17 +1261,21 @@ QList<Annotation*> Page::annotations() const
                 // set annotation's window properties taking ones from popup
                 PopupWindow * pop = popupsMap[ request.popup ];
                 Annotation * pa = pop->dummyAnnotation;
-                Annotation::Window & w = request.annotation->window;
+                Annotation * ann = request.annotation;
 
                 // transfer properties to Annotation's window
-                w.flags = pa->flags() & (Annotation::Hidden |
+                int flags = pa->flags() & (Annotation::Hidden |
                     Annotation::FixedSize | Annotation::FixedRotation);
                 if ( !pop->shown )
-                    w.flags |= Annotation::Hidden;
-                w.topLeft.setX(pa->boundary().left());
-                w.topLeft.setY(pa->boundary().top());
-                w.width = (int)( pa->boundary().right() - pa->boundary().left() );
-                w.height = (int)( pa->boundary().bottom() - pa->boundary().top() );
+                    flags |= Annotation::Hidden;
+                ann->d_ptr->popup.setFlags(flags);
+
+                QRectF geom;
+                geom.setLeft(pa->boundary().left());
+                geom.setTop(pa->boundary().top());
+                geom.setWidth( pa->boundary().right() - pa->boundary().left() );
+                geom.setHeight( pa->boundary().bottom() - pa->boundary().top() );
+                ann->d_ptr->popup.setGeometry(geom);
             }
         }
 
@@ -1312,12 +1306,10 @@ QList<Annotation*> Page::annotations() const
                           << parentID << ".";
             else
             {
-                // compile and add a Revision structure to the parent annotation
-                Annotation::Revision childRevision;
-                childRevision.annotation = request.nextAnnotation;
-                childRevision.scope = request.nextScope;
-                childRevision.type = request.nextType;
-                annotationsMap[ parentID ]->revisions().append( childRevision );
+                // add annotation as a reply to the parent annotation
+                Annotation *curr = request.nextAnnotation;
+                annotationsMap[ parentID ]->addRevision( curr, request.nextScope, request.nextType );
+                delete curr;
                 // exclude child annotation from being rooted in page
                 excludeIDs[ excludeIndex++ ] = request.nextAnnotationID;
             }
@@ -1335,22 +1327,24 @@ QList<Annotation*> Page::annotations() const
         for ( ; it != end; ++it )
         {
             const PostProcessText & request = *it;
-            Annotation::Window & window = request.textAnnotation->window;
+            Annotation * reqann = request.textAnnotation;
+            int flags = reqann->d_ptr->popup.flags();
             // if not present, 'create' the window in-place over the annotation
-            if ( window.flags == -1 )
+            if ( flags == -1 )
             {
-                window.flags = 0;
-                QRectF geom = request.textAnnotation->boundary();
                 // initialize window geometry to annotation's one
-                window.width = (int)( geom.right() - geom.left() );
-                window.height = (int)( geom.bottom() - geom.top() );
-                window.topLeft.setX( geom.left() > 0.0 ? geom.left() : 0.0 );
-                window.topLeft.setY( geom.top() > 0.0 ? geom.top() : 0.0 );
+                QPointF tl = reqann->boundary().topLeft();
+                QSizeF size = reqann->boundary().size();
+                if (tl.x() < 0) tl.setX(0);
+                if (tl.y() < 0) tl.setY(0);
+                reqann->d_ptr->popup.setGeometry( QRectF (tl, size) );
+                flags = 0;
             }
             // (pdf) if text is not 'opened', force window hiding. if the window
             // was parsed from popup, the flag should already be set
-            if ( !request.opened && window.flags != -1 )
-                window.flags |= Annotation::Hidden;
+            if ( !request.opened && flags != -1 )
+                flags |= Annotation::Hidden;
+            reqann->d_ptr->popup.setFlags( flags );
         }
     }
 
diff --git a/qt4/src/poppler-qt4.h b/qt4/src/poppler-qt4.h
index f721f92..0b10194 100644
--- a/qt4/src/poppler-qt4.h
+++ b/qt4/src/poppler-qt4.h
@@ -10,6 +10,7 @@
  * Copyright (C) 2011 Andreas Hartmetz <ahartmetz at gmail.com>
  * Copyright (C) 2011 Glad Deschrijver <glad.deschrijver at gmail.com>
  * Copyright (C) 2012, Guillermo A. Amaral B. <gamaral at kde.org>
+ * Copyright (C) 2012, 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
@@ -676,6 +677,11 @@ delete it;
 	
 	/**
 	 Returns the annotations of the page
+
+	 \note If you call this method twice, you get different objects
+	       pointing to the same annotations (see Annotation).
+	       The caller owns the returned objects and they should be deleted
+	       when no longer required.
 	*/
 	QList<Annotation*> annotations() const;
 


More information about the poppler mailing list