/* poppler-annotation.cc: qt interface to poppler
 * Copyright (C) 2006, 2009, 2012-2014 Albert Astals Cid <aacid@kde.org>
 * Copyright (C) 2006, 2008, 2010 Pino Toscano <pino@kde.org>
 * Copyright (C) 2012, Guillermo A. Amaral B. <gamaral@kde.org>
 * Copyright (C) 2012-2014 Fabio D'Urso <fabiodurso@hotmail.it>
 * Copyright (C) 2012, Tobias Koenig <tokoe@kdab.com>
 * Adapting code from
 *   Copyright (C) 2004 by Enrico Ros <eros.kde@email.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
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
 */

// qt/kde includes
#include <QtCore/QRegExp>
#include <QtCore/QtAlgorithms>
#include <QtXml/QDomElement>
#include <QtGui/QColor>
#include <QtGui/QTransform>

// local includes
#include "poppler-annotation.h"
#include "poppler-link.h"
#include "poppler-qt5.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>
#include <Link.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 {

//BEGIN AnnotationUtils implementation
Annotation * AnnotationUtils::createAnnotation( const QDomElement & annElement )
{
    // safety check on annotation element
    if ( !annElement.hasAttribute( "type" ) )
        return 0;

    // build annotation of given type
    Annotation * annotation = 0;
    int typeNumber = annElement.attribute( "type" ).toInt();
    switch ( typeNumber )
    {
        case Annotation::AText:
            annotation = new TextAnnotation( annElement );
            break;
        case Annotation::ALine:
            annotation = new LineAnnotation( annElement );
            break;
        case Annotation::AGeom:
            annotation = new GeomAnnotation( annElement );
            break;
        case Annotation::AHighlight:
            annotation = new HighlightAnnotation( annElement );
            break;
        case Annotation::AStamp:
            annotation = new StampAnnotation( annElement );
            break;
        case Annotation::AInk:
            annotation = new InkAnnotation( annElement );
            break;
        case Annotation::ACaret:
            annotation = new CaretAnnotation( annElement );
            break;
    }

    // return created annotation
    return annotation;
}

void AnnotationUtils::storeAnnotation( const Annotation * ann, QDomElement & annElement,
    QDomDocument & document )
{
    // save annotation's type as element's attribute
    annElement.setAttribute( "type", (uint)ann->subType() );

    // append all annotation data as children of this node
    ann->store( annElement, document );
}

QDomElement AnnotationUtils::findChildElement( const QDomNode & parentNode,
    const QString & name )
{
    // loop through the whole children and return a 'name' named element
    QDomNode subNode = parentNode.firstChild();
    while( subNode.isElement() )
    {
        QDomElement element = subNode.toElement();
        if ( element.tagName() == name )
            return element;
        subNode = subNode.nextSibling();
    }
    // if the name can't be found, return a dummy null element
    return QDomElement();
}
//END AnnotationUtils implementation


//BEGIN Annotation implementation
AnnotationPrivate::AnnotationPrivate()
    : flags( 0 ), revisionScope ( Annotation::Root ),
    revisionType ( Annotation::None ), pdfAnnot ( 0 ), pdfPage ( 0 ),
    parentDoc ( 0 )
{
}

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
    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();
}

/* 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)
    {
        // TODO: Flush revision
        delete r; // Object is no longer needed
    }

    delete q;

    // Clear some members to save memory
    author.clear();
    contents.clear();
    uniqueName.clear();
    revisions.clear();
}

// Returns matrix to convert from user space coords (oriented according to the
// specified rotation) to normalized coords
void AnnotationPrivate::fillNormalizationMTX(double MTX[6], int pageRotation) const
{
    Q_ASSERT ( pdfPage );

    // build a normalized transform matrix for this page at 100% scale
    GfxState * gfxState = new GfxState( 72.0, 72.0, pdfPage->getCropBox(), pageRotation, gTrue );
    double * gfxCTM = gfxState->getCTM();

    double w = pdfPage->getCropWidth();
    double h = pdfPage->getCropHeight();

    // Swap width and height if the page is rotated landscape or seascape
    if ( pageRotation == 90 || pageRotation == 270 )
    {
        double t = w;
        w = h;
        h = t;
    }

    for ( int i = 0; i < 6; i+=2 )
    {
        MTX[i] = gfxCTM[i] / w;
        MTX[i+1] = gfxCTM[i+1] / h;
    }
    delete gfxState;
}

// Returns matrix to convert from user space coords (i.e. those that are stored
// in the PDF file) to normalized coords (i.e. those that we expose to clients).
// This method also applies a rotation around the top-left corner if the
// FixedRotation flag is set.
void AnnotationPrivate::fillTransformationMTX(double MTX[6]) const
{
    Q_ASSERT ( pdfPage );
    Q_ASSERT ( pdfAnnot );

    const int pageRotate = pdfPage->getRotate();

    if ( pageRotate == 0 || ( pdfAnnot->getFlags() & Annot::flagNoRotate ) == 0 )
    {
        // Use the normalization matrix for this page's rotation
        fillNormalizationMTX( MTX, pageRotate );
    }
    else
    {
        // Clients expect coordinates relative to this page's rotation, but
        // FixedRotation annotations internally use unrotated coordinates:
        // construct matrix to both normalize and rotate coordinates using the
        // top-left corner as rotation pivot

        double MTXnorm[6];
        fillNormalizationMTX( MTXnorm, pageRotate );

        QTransform transform( MTXnorm[0], MTXnorm[1], MTXnorm[2],
                              MTXnorm[3], MTXnorm[4], MTXnorm[5] );
        transform.translate( +pdfAnnot->getXMin(), +pdfAnnot->getYMax() );
        transform.rotate( pageRotate );
        transform.translate( -pdfAnnot->getXMin(), -pdfAnnot->getYMax() );

        MTX[0] = transform.m11();
        MTX[1] = transform.m12();
        MTX[2] = transform.m21();
        MTX[3] = transform.m22();
        MTX[4] = transform.dx();
        MTX[5] = transform.dy();
    }
}

QRectF AnnotationPrivate::fromPdfRectangle(const PDFRectangle &r) const
{
    double swp, MTX[6];
    fillTransformationMTX(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) );
}

// This function converts a boundary QRectF in normalized coords to a
// PDFRectangle in user coords. If the FixedRotation flag is set, this function
// also applies a rotation around the top-left corner: it's the inverse of
// the transformation produced by fillTransformationMTX, but we can't use
// fillTransformationMTX here because it relies on the native annotation
// object's boundary rect to be already set up.
PDFRectangle AnnotationPrivate::boundaryToPdfRectangle(const QRectF &r, int flags) const
{
    Q_ASSERT ( pdfPage );

    const int pageRotate = pdfPage->getRotate();

    double MTX[6];
    fillNormalizationMTX( MTX, pageRotate );

    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;
    }

    const int rotationFixUp = ( flags & Annotation::FixedRotation ) ? pageRotate : 0;
    const double width = br_x - tl_x;
    const double height = br_y - tl_y;

    if ( rotationFixUp == 0 )
        return PDFRectangle(tl_x, tl_y, br_x, br_y);
    else if ( rotationFixUp == 90 )
        return PDFRectangle(tl_x, tl_y - width, tl_x + height, tl_y);
    else if ( rotationFixUp == 180 )
        return PDFRectangle(br_x, tl_y - height, br_x + width, tl_y);
    else // rotationFixUp == 270
        return PDFRectangle(br_x, br_y - width, br_x + height, br_y);
}

AnnotPath * AnnotationPrivate::toAnnotPath(const QLinkedList<QPointF> &list) const
{
    const int count = list.size();
    AnnotCoord **ac = (AnnotCoord **) gmallocn(count, sizeof(AnnotCoord*));

    double MTX[6];
    fillTransformationMTX(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, const QSet<Annotation::SubType> &subtypes, int parentID)
{
    Annots* annots = pdfPage->getAnnots();
    const uint numAnnotations = annots->getNumAnnots();
    if ( numAnnotations == 0 )
    {
        return QList<Annotation*>();
    }

    const bool wantTextAnnotations = subtypes.isEmpty() || subtypes.contains(Annotation::AText);
    const bool wantLineAnnotations = subtypes.isEmpty() || subtypes.contains(Annotation::ALine);
    const bool wantGeomAnnotations = subtypes.isEmpty() || subtypes.contains(Annotation::AGeom);
    const bool wantHighlightAnnotations = subtypes.isEmpty() || subtypes.contains(Annotation::AHighlight);
    const bool wantStampAnnotations = subtypes.isEmpty() || subtypes.contains(Annotation::AStamp);
    const bool wantInkAnnotations = subtypes.isEmpty() || subtypes.contains(Annotation::AInk);
    const bool wantLinkAnnotations = subtypes.isEmpty() || subtypes.contains(Annotation::ALink);
    const bool wantCaretAnnotations = subtypes.isEmpty() || subtypes.contains(Annotation::ACaret);
    const bool wantFileAttachmentAnnotations = subtypes.isEmpty() || subtypes.contains(Annotation::AFileAttachment);
    const bool wantSoundAnnotations = subtypes.isEmpty() || subtypes.contains(Annotation::ASound);
    const bool wantMovieAnnotations = subtypes.isEmpty() || subtypes.contains(Annotation::AMovie);
    const bool wantScreenAnnotations = subtypes.isEmpty() || subtypes.contains(Annotation::AScreen);
    const bool wantWidgetAnnotations = subtypes.isEmpty() || subtypes.contains(Annotation::AWidget);

    // 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 {0:ud} 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:
                if (!wantTextAnnotations)
                    continue;
                annotation = new TextAnnotation(TextAnnotation::Linked);
                break;
            case Annot::typeFreeText:
                if (!wantTextAnnotations)
                    continue;
                annotation = new TextAnnotation(TextAnnotation::InPlace);
                break;
            case Annot::typeLine:
                if (!wantLineAnnotations)
                    continue;
                annotation = new LineAnnotation(LineAnnotation::StraightLine);
                break;
            case Annot::typePolygon:
            case Annot::typePolyLine:
                if (!wantLineAnnotations)
                    continue;
                annotation = new LineAnnotation(LineAnnotation::Polyline);
                break;
            case Annot::typeSquare:
            case Annot::typeCircle:
                if (!wantGeomAnnotations)
                    continue;
                annotation = new GeomAnnotation();
                break;
            case Annot::typeHighlight:
            case Annot::typeUnderline:
            case Annot::typeSquiggly:
            case Annot::typeStrikeOut:
                if (!wantHighlightAnnotations)
                    continue;
                annotation = new HighlightAnnotation();
                break;
            case Annot::typeStamp:
                if (!wantStampAnnotations)
                    continue;
                annotation = new StampAnnotation();
                break;
            case Annot::typeInk:
                if (!wantInkAnnotations)
                    continue;
                annotation = new InkAnnotation();
                break;
            case Annot::typeLink: /* TODO: Move logic to getters */
            {
                if (!wantLinkAnnotations)
                    continue;
                // 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:
                if (!wantCaretAnnotations)
                    continue;
                annotation = new CaretAnnotation();
                break;
            case Annot::typeFileAttachment: /* TODO: Move logic to getters */
            {
                if (!wantFileAttachmentAnnotations)
                    continue;
                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 */
            {
                if (!wantSoundAnnotations)
                    continue;
                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 */
            {
                if (!wantMovieAnnotations)
                    continue;
                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:
            {
                if (!wantScreenAnnotations)
                    continue;
                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:
                if (!wantWidgetAnnotations)
                    continue;
                annotation = new WidgetAnnotation();
                break;
            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 {0:d} 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();
}

Link* AnnotationPrivate::additionalAction( Annotation::AdditionalActionType type ) const
{
    if ( pdfAnnot->getType() != Annot::typeScreen && pdfAnnot->getType() != Annot::typeWidget )
        return 0;

    Annot::AdditionalActionsType actionType = Annot::actionCursorEntering;
    switch ( type )
    {
        case Annotation::CursorEnteringAction: actionType = Annot::actionCursorEntering; break;
        case Annotation::CursorLeavingAction: actionType = Annot::actionCursorLeaving; break;
        case Annotation::MousePressedAction: actionType = Annot::actionMousePressed; break;
        case Annotation::MouseReleasedAction: actionType = Annot::actionMouseReleased; break;
        case Annotation::FocusInAction: actionType = Annot::actionFocusIn; break;
        case Annotation::FocusOutAction: actionType = Annot::actionFocusOut; break;
        case Annotation::PageOpeningAction: actionType = Annot::actionPageOpening; break;
        case Annotation::PageClosingAction: actionType = Annot::actionPageClosing; break;
        case Annotation::PageVisibleAction: actionType = Annot::actionPageVisible; break;
        case Annotation::PageInvisibleAction: actionType = Annot::actionPageInvisible; break;
    }

    ::LinkAction *linkAction = 0;
    if ( pdfAnnot->getType() == Annot::typeScreen )
        linkAction = static_cast<AnnotScreen*>( pdfAnnot )->getAdditionalAction( actionType );
    else
        linkAction = static_cast<AnnotWidget*>( pdfAnnot )->getAdditionalAction( actionType );

    Link *link = 0;

    if ( linkAction )
        link = PageData::convertLinkActionToLink( linkAction, parentDoc, QRectF() );

    return link;
}

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);
}

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 annotation
    pdfPage->removeAnnot(ann->d_ptr->pdfAnnot);

    // Destroy object
    delete ann;
}

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()
    : 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;
}

QString Annotation::Popup::text() const
{
    return d->text;
}

void Annotation::Popup::setText( const QString &text )
{
    d->text = text;
}

Annotation::Annotation( AnnotationPrivate &dd )
    : d_ptr( &dd )
{
}

Annotation::~Annotation()
{
}

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" ) )
        setAuthor(e.attribute( "author" ));
    if ( e.hasAttribute( "contents" ) )
        setContents(e.attribute( "contents" ));
    if ( e.hasAttribute( "uniqueName" ) )
        setUniqueName(e.attribute( "uniqueName" ));
    if ( e.hasAttribute( "modifyDate" ) )
        setModificationDate(QDateTime::fromString( e.attribute( "modifyDate" ) ));
    if ( e.hasAttribute( "creationDate" ) )
        setCreationDate(QDateTime::fromString( e.attribute( "creationDate" ) ));

    // parse -other- attributes
    if ( e.hasAttribute( "flags" ) )
        setFlags(e.attribute( "flags" ).toInt());
    if ( e.hasAttribute( "color" ) )
        s.setColor(QColor( e.attribute( "color" ) ));
    if ( e.hasAttribute( "opacity" ) )
        s.setOpacity(e.attribute( "opacity" ).toDouble());

    // parse -the-subnodes- (describing Style, Window, Revision(s) structures)
    // Note: all subnodes if present must be 'attributes complete'
    QDomNode eSubNode = e.firstChild();
    while ( eSubNode.isElement() )
    {
        QDomElement ee = eSubNode.toElement();
        eSubNode = eSubNode.nextSibling();

        // parse boundary
        if ( ee.tagName() == "boundary" )
        {
            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" )
        {
            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" )
        {
            s.setLineEffect((LineEffect)ee.attribute( "effect" ).toInt());
            s.setEffectIntensity(ee.attribute( "intensity" ).toDouble());
        }
        // parse window if present
        else if ( ee.tagName() == "window" )
        {
            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" )
                    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() )
    {
        QDomElement revElement = revNode.toElement();
        if ( revElement.tagName() != "revision" )
            continue;

        Annotation *reply = AnnotationUtils::createAnnotation( revElement );

        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();
            d->addRevision(reply, scope, type);
            delete reply;
        }
    }
}

void Annotation::storeBaseAnnotationProperties( QDomNode & annNode, QDomDocument & document ) const
{
    // 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 ( !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 ( flags() )
        e.setAttribute( "flags", flags() );
    if ( s.color().isValid() )
        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)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
    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( 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 ( s.lineEffect() != NoEffect || s.effectIntensity() != 1.0 )
    {
        QDomElement peE = document.createElement( "penEffect" );
        e.appendChild( peE );
        peE.setAttribute( "effect", (int)s.lineEffect() );
        peE.setAttribute( "intensity", QString::number( s.effectIntensity() ) );
    }

    // Sub-Node-4 - window
    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", 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 ( !w.text().isEmpty() )
        {
            QDomElement escapedText = document.createElement( "text" );
            wE.appendChild( escapedText );
            QDomCDATASection textCData = document.createCDATASection( w.text() );
            escapedText.appendChild( textCData );
        }
    }

    const QList<Annotation*> revs = revisions();

    // create [revision] element of the annotation node (if any)
    if ( revs.isEmpty() )
        return;

    // add all revisions as children of revisions element
    foreach (const Annotation *rev, revs)
    {
        QDomElement r = document.createElement( "revision" );
        annNode.appendChild( r );
        // set element attributes
        r.setAttribute( "revScope", (int)rev->revisionScope() );
        r.setAttribute( "revType", (int)rev->revisionType() );
        // use revision as the annotation element, so fill it up
        AnnotationUtils::storeAnnotation( rev, r, document );
        delete rev;
    }
}

QString Annotation::author() const
{
    Q_D( const Annotation );

    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 );

    if (!d->pdfAnnot)
    {
        d->author = author;
        return;
    }

    AnnotMarkup *markupann = dynamic_cast<AnnotMarkup*>(d->pdfAnnot);
    if (markupann)
    {
        GooString *s = QStringToUnicodeGooString(author);
        markupann->setLabel(s);
        delete s;
    }
}

QString Annotation::contents() const
{
    Q_D( const Annotation );

    if (!d->pdfAnnot)
        return d->contents;

    return UnicodeParsedString( d->pdfAnnot->getContents() );
}

void Annotation::setContents( const QString &contents )
{
    Q_D( Annotation );

    if (!d->pdfAnnot)
    {
        d->contents = contents;
        return;
    }

    GooString *s = QStringToUnicodeGooString(contents);
    d->pdfAnnot->setContents(s);
    delete s;
}

QString Annotation::uniqueName() const
{
    Q_D( const Annotation );

    if (!d->pdfAnnot)
        return d->uniqueName;

    return UnicodeParsedString( d->pdfAnnot->getName() );
}

void Annotation::setUniqueName( const QString &uniqueName )
{
    Q_D( Annotation );

    if (!d->pdfAnnot)
    {
        d->uniqueName = uniqueName;
        return;
    }

    QByteArray ascii = uniqueName.toLatin1();
    GooString s(ascii.constData());
    d->pdfAnnot->setName(&s);
}

QDateTime Annotation::modificationDate() const
{
    Q_D( const Annotation );

    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 );

    if (!d->pdfAnnot)
    {
        d->modDate = date;
        return;
    }

#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
{
    Q_D( const Annotation );

    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 );

    if (!d->pdfAnnot)
    {
        d->creationDate = date;
        return;
    }

#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)
{
    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;
}

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 );

    if (!d->pdfAnnot)
        return d->flags;

    return fromPdfFlags( d->pdfAnnot->getFlags() );
}

void Annotation::setFlags( int flags )
{
    Q_D( Annotation );

    if (!d->pdfAnnot)
    {
        d->flags = flags;
        return;
    }

    d->pdfAnnot->setFlags(toPdfFlags( flags ));
}

QRectF Annotation::boundary() const
{
    Q_D( const Annotation );

    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 );

    if (!d->pdfAnnot)
    {
        d->boundary = boundary;
        return;
    }

    PDFRectangle rect = d->boundaryToPdfRectangle( boundary, flags() );
    d->pdfAnnot->setRect(&rect);
}

Annotation::Style Annotation::style() const
{
    Q_D( const Annotation );

    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 );

    if (!d->pdfAnnot)
    {
        d->style = style;
        return;
    }

    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
{
    Q_D( const Annotation );

    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 );

    if (!d->pdfAnnot)
    {
        d->popup = popup;
        return;
    }

#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
{
    Q_D( const Annotation );

    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
}

Annotation::RevType Annotation::revisionType() const
{
    Q_D( const Annotation );

    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;
}

QList<Annotation*> Annotation::revisions() const
{
    Q_D( const Annotation );

    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;
    }

    /* If the annotation doesn't live in a object on its own (eg bug51361), it
     * has no ref, therefore it can't have revisions */
    if ( !d->pdfAnnot->getHasRef() )
        return QList<Annotation*>();

    return AnnotationPrivate::findAnnotations( d->pdfPage, d->parentDoc, QSet<Annotation::SubType>(), d->pdfAnnot->getId() );
}

//END Annotation implementation


/** TextAnnotation [Annotation] */
class TextAnnotationPrivate : public AnnotationPrivate
{
    public:
        TextAnnotationPrivate();
        Annotation * makeAlias();
        Annot* createNativeAnnot(::Page *destPage, DocumentData *doc);

        // data fields
        TextAnnotation::TextType textType;
        QString textIcon;
        QFont textFont;
        int inplaceAlign; // 0:left, 1:center, 2:right
        QVector<QPointF> inplaceCallout;
        TextAnnotation::InplaceIntent inplaceIntent;

        // Helper
        static GooString * toAppearanceString(const QFont &font);
};

TextAnnotationPrivate::TextAnnotationPrivate()
    : AnnotationPrivate(), textType( TextAnnotation::Linked ),
    textIcon( "Note" ), inplaceAlign( 0 ),
    inplaceIntent( TextAnnotation::Unknown )
{
}

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)
{
    // 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 = boundaryToPdfRectangle(boundary, flags);
    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;

    inplaceCallout.clear(); // Free up memory

    return pdfAnnot;
}

TextAnnotation::TextAnnotation( TextAnnotation::TextType type )
    : Annotation( *new TextAnnotationPrivate() )
{
    setTextType( type );
}

TextAnnotation::TextAnnotation(TextAnnotationPrivate &dd)
    : Annotation( dd )
{}

TextAnnotation::TextAnnotation( const QDomNode & node )
    : Annotation( *new TextAnnotationPrivate, node )
{
    // loop through the whole children looking for a 'text' element
    QDomNode subNode = node.firstChild();
    while( subNode.isElement() )
    {
        QDomElement e = subNode.toElement();
        subNode = subNode.nextSibling();
        if ( e.tagName() != "text" )
            continue;

        // parse the attributes
        if ( e.hasAttribute( "type" ) )
            setTextType((TextAnnotation::TextType)e.attribute( "type" ).toInt());
        if ( e.hasAttribute( "icon" ) )
            setTextIcon(e.attribute( "icon" ));
        if ( e.hasAttribute( "font" ) )
        {
            QFont font;
            font.fromString( e.attribute( "font" ) );
            setTextFont(font);
        }
        if ( e.hasAttribute( "align" ) )
            setInplaceAlign(e.attribute( "align" ).toInt());
        if ( e.hasAttribute( "intent" ) )
            setInplaceIntent((TextAnnotation::InplaceIntent)e.attribute( "intent" ).toInt());

        // parse the subnodes
        QDomNode eSubNode = e.firstChild();
        while ( eSubNode.isElement() )
        {
            QDomElement ee = eSubNode.toElement();
            eSubNode = eSubNode.nextSibling();

            if ( ee.tagName() == "escapedText" )
            {
                setContents(ee.firstChild().toCDATASection().data());
            }
            else if ( ee.tagName() == "callout" )
            {
                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);
            }
        }

        // loading complete
        break;
    }
}

TextAnnotation::~TextAnnotation()
{
}

void TextAnnotation::store( QDomNode & node, QDomDocument & document ) const
{
    // store base annotation properties
    storeBaseAnnotationProperties( node, document );

    // create [text] element
    QDomElement textElement = document.createElement( "text" );
    node.appendChild( textElement );

    // store the optional attributes
    if ( textType() != Linked )
        textElement.setAttribute( "type", (int)textType() );
    if ( textIcon() != "Note" )
        textElement.setAttribute( "icon", textIcon() );
    if ( inplaceAlign() )
        textElement.setAttribute( "align", inplaceAlign() );
    if ( inplaceIntent() != Unknown )
        textElement.setAttribute( "intent", (int)inplaceIntent() );

    textElement.setAttribute( "font", textFont().toString() );

    // Sub-Node-1 - escapedText
    if ( !contents().isEmpty() )
    {
        QDomElement escapedText = document.createElement( "escapedText" );
        textElement.appendChild( escapedText );
        QDomCDATASection textCData = document.createCDATASection( contents() );
        escapedText.appendChild( textCData );
    }

    // Sub-Node-2 - callout
    if ( calloutPoint(0).x() != 0.0 )
    {
        QDomElement calloutElement = document.createElement( "callout" );
        textElement.appendChild( calloutElement );
        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() ) );
    }
}

Annotation::SubType TextAnnotation::subType() const
{
    return AText;
}

TextAnnotation::TextType TextAnnotation::textType() const
{
    Q_D( const TextAnnotation );

    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 );

    if (!d->pdfAnnot)
    {
        d->textType = type;
        return;
    }

    // Type cannot be changed if annotation is already tied
}

QString TextAnnotation::textIcon() const
{
    Q_D( const TextAnnotation );

    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 );

    if (!d->pdfAnnot)
    {
        d->textIcon = icon;
        return;
    }

    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
{
    Q_D( const TextAnnotation );

    if (!d->pdfAnnot)
        return d->textFont;

    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 )
{
    Q_D( TextAnnotation );

    if (!d->pdfAnnot)
    {
        d->textFont = font;
        return;
    }

    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
{
    Q_D( const TextAnnotation );

    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 );

    if (!d->pdfAnnot)
    {
        d->inplaceAlign = align;
        return;
    }

    if (d->pdfAnnot->getType() == Annot::typeFreeText)
    {
        AnnotFreeText * ftextann = static_cast<AnnotFreeText*>(d->pdfAnnot);
        ftextann->setQuadding((AnnotFreeText::AnnotFreeTextQuadding)align);
    }
}

QPointF TextAnnotation::calloutPoint( int id ) const
{
    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 );

    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->fillTransformationMTX(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::setCalloutPoints( const QVector<QPointF> &points )
{
    Q_D( TextAnnotation );
    if (!d->pdfAnnot)
    {
        d->inplaceCallout = points;
        return;
    }

    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->fillTransformationMTX(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
{
    Q_D( const TextAnnotation );

    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 );

    if (!d->pdfAnnot)
    {
        d->inplaceIntent = intent;
        return;
    }

    if (d->pdfAnnot->getType() == Annot::typeFreeText)
    {
        AnnotFreeText * ftextann = static_cast<AnnotFreeText*>(d->pdfAnnot);
        ftextann->setIntent((AnnotFreeText::AnnotFreeTextIntent)intent);
    }
}


/** LineAnnotation [Annotation] */
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;
        LineAnnotation::TermStyle lineStartStyle;
        LineAnnotation::TermStyle lineEndStyle;
        bool lineClosed : 1;  // (if true draw close shape)
        bool lineShowCaption : 1;
        LineAnnotation::LineType lineType;
        QColor lineInnerColor;
        double lineLeadingFwdPt;
        double lineLeadingBackPt;
        LineAnnotation::LineIntent lineIntent;
};

LineAnnotationPrivate::LineAnnotationPrivate()
    : AnnotationPrivate(), lineStartStyle( LineAnnotation::None ),
    lineEndStyle( LineAnnotation::None ), lineClosed( false ),
    lineShowCaption( false ), lineLeadingFwdPt( 0 ),
    lineLeadingBackPt( 0 ), lineIntent( LineAnnotation::Unknown )
{
}

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
    PDFRectangle rect = boundaryToPdfRectangle(boundary, flags);
    if (lineType == LineAnnotation::StraightLine)
    {
        pdfAnnot = new AnnotLine(doc->doc, &rect);
    }
    else
    {
        pdfAnnot = new AnnotPolygon(doc->doc, &rect,
                lineClosed ? Annot::typePolygon : Annot::typePolyLine );
    }

    // Set properties
    flushBaseAnnotationProperties();
    q->setLinePoints(linePoints);
    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() )
{
    setLineType(type);
}

LineAnnotation::LineAnnotation(LineAnnotationPrivate &dd)
    : Annotation( dd )
{}

LineAnnotation::LineAnnotation( const QDomNode & node )
    : Annotation( *new LineAnnotationPrivate(), node )
{
    // loop through the whole children looking for a 'line' element
    QDomNode subNode = node.firstChild();
    while( subNode.isElement() )
    {
        QDomElement e = subNode.toElement();
        subNode = subNode.nextSibling();
        if ( e.tagName() != "line" )
            continue;

        // parse the attributes
        if ( e.hasAttribute( "startStyle" ) )
            setLineStartStyle((LineAnnotation::TermStyle)e.attribute( "startStyle" ).toInt());
        if ( e.hasAttribute( "endStyle" ) )
            setLineEndStyle((LineAnnotation::TermStyle)e.attribute( "endStyle" ).toInt());
        if ( e.hasAttribute( "closed" ) )
            setLineClosed(e.attribute( "closed" ).toInt());
        if ( e.hasAttribute( "innerColor" ) )
            setLineInnerColor(QColor( e.attribute( "innerColor" ) ));
        if ( e.hasAttribute( "leadFwd" ) )
            setLineLeadingForwardPoint(e.attribute( "leadFwd" ).toDouble());
        if ( e.hasAttribute( "leadBack" ) )
            setLineLeadingBackPoint(e.attribute( "leadBack" ).toDouble());
        if ( e.hasAttribute( "showCaption" ) )
            setLineShowCaption(e.attribute( "showCaption" ).toInt());
        if ( e.hasAttribute( "intent" ) )
            setLineIntent((LineAnnotation::LineIntent)e.attribute( "intent" ).toInt());

        // parse all 'point' subnodes
        QLinkedList<QPointF> points;
        QDomNode pointNode = e.firstChild();
        while ( pointNode.isElement() )
        {
            QDomElement pe = pointNode.toElement();
            pointNode = pointNode.nextSibling();

            if ( pe.tagName() != "point" )
                continue;

            QPointF p(pe.attribute( "x", "0.0" ).toDouble(), pe.attribute( "y", "0.0" ).toDouble());
            points.append( p );
        }
        setLinePoints(points);
        setLineType(points.size() == 2 ? StraightLine : Polyline);

        // loading complete
        break;
    }
}

LineAnnotation::~LineAnnotation()
{
}

void LineAnnotation::store( QDomNode & node, QDomDocument & document ) const
{
    // store base annotation properties
    storeBaseAnnotationProperties( node, document );

    // create [line] element
    QDomElement lineElement = document.createElement( "line" );
    node.appendChild( lineElement );

    // store the attributes
    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
    const QLinkedList<QPointF> points = linePoints();
    if ( points.count() > 1 )
    {
        QLinkedList<QPointF>::const_iterator it = points.begin(), end = points.end();
        while ( it != end )
        {
            const QPointF & p = *it;
            QDomElement pElement = document.createElement( "point" );
            lineElement.appendChild( pElement );
            pElement.setAttribute( "x", QString::number( p.x() ) );
            pElement.setAttribute( "y", QString::number( p.y() ) );
            ++it;
        }
    }
}

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 );

    if (!d->pdfAnnot)
        return d->linePoints;

    double MTX[6];
    d->fillTransformationMTX(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 );

    if (!d->pdfAnnot)
    {
        d->linePoints = points;
        return;
    }

    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->fillTransformationMTX(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
{
    Q_D( const LineAnnotation );

    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 );

    if (!d->pdfAnnot)
    {
        d->lineStartStyle = style;
        return;
    }

    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
{
    Q_D( const LineAnnotation );

    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 );

    if (!d->pdfAnnot)
    {
        d->lineEndStyle = style;
        return;
    }

    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
{
    Q_D( const LineAnnotation );

    if (!d->pdfAnnot)
        return d->lineClosed;

    return d->pdfAnnot->getType() == Annot::typePolygon;
}

void LineAnnotation::setLineClosed( bool closed )
{
    Q_D( LineAnnotation );

    if (!d->pdfAnnot)
    {
        d->lineClosed = closed;
        return;
    }

    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
{
    Q_D( const LineAnnotation );

    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 );

    if (!d->pdfAnnot)
    {
        d->lineInnerColor = color;
        return;
    }

    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
{
    Q_D( const LineAnnotation );

    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 );

    if (!d->pdfAnnot)
    {
        d->lineLeadingFwdPt = point;
        return;
    }

    if (d->pdfAnnot->getType() == Annot::typeLine)
    {
        AnnotLine *lineann = static_cast<AnnotLine*>(d->pdfAnnot);
        lineann->setLeaderLineLength(point);
    }
}

double LineAnnotation::lineLeadingBackPoint() const
{
    Q_D( const LineAnnotation );

    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 );

    if (!d->pdfAnnot)
    {
        d->lineLeadingBackPt = point;
        return;
    }

    if (d->pdfAnnot->getType() == Annot::typeLine)
    {
        AnnotLine *lineann = static_cast<AnnotLine*>(d->pdfAnnot);
        lineann->setLeaderLineExtension(point);
    }
}

bool LineAnnotation::lineShowCaption() const
{
    Q_D( const LineAnnotation );

    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 );

    if (!d->pdfAnnot)
    {
        d->lineShowCaption = show;
        return;
    }

    if (d->pdfAnnot->getType() == Annot::typeLine)
    {
        AnnotLine *lineann = static_cast<AnnotLine*>(d->pdfAnnot);
        lineann->setCaption(show);
    }
}

LineAnnotation::LineIntent LineAnnotation::lineIntent() const
{
    Q_D( const LineAnnotation );

    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 );

    if (!d->pdfAnnot)
    {
        d->lineIntent = intent;
        return;
    }

    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 );
        }
    }
}


/** GeomAnnotation [Annotation] */
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;
        QColor geomInnerColor;
};

GeomAnnotationPrivate::GeomAnnotationPrivate()
    : AnnotationPrivate(), geomType( GeomAnnotation::InscribedSquare )
{
}

Annotation * GeomAnnotationPrivate::makeAlias()
{
    return new GeomAnnotation(*this);
}

Annot* GeomAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc)
{
    // 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 = boundaryToPdfRectangle(boundary, flags);
    pdfAnnot = new AnnotGeometry(destPage->getDoc(), &rect, type);

    // Set properties
    flushBaseAnnotationProperties();
    q->setGeomInnerColor(geomInnerColor);

    delete q;
    return pdfAnnot;
}

GeomAnnotation::GeomAnnotation()
    : Annotation( *new GeomAnnotationPrivate() )
{}

GeomAnnotation::GeomAnnotation(GeomAnnotationPrivate &dd)
    : Annotation( dd )
{}

GeomAnnotation::GeomAnnotation( const QDomNode & node )
    : Annotation( *new GeomAnnotationPrivate(), node )
{
    // loop through the whole children looking for a 'geom' element
    QDomNode subNode = node.firstChild();
    while( subNode.isElement() )
    {
        QDomElement e = subNode.toElement();
        subNode = subNode.nextSibling();
        if ( e.tagName() != "geom" )
            continue;

        // parse the attributes
        if ( e.hasAttribute( "type" ) )
            setGeomType((GeomAnnotation::GeomType)e.attribute( "type" ).toInt());
        if ( e.hasAttribute( "color" ) )
            setGeomInnerColor(QColor( e.attribute( "color" ) ));

        // loading complete
        break;
    }
}

GeomAnnotation::~GeomAnnotation()
{
}

void GeomAnnotation::store( QDomNode & node, QDomDocument & document ) const
{
    // store base annotation properties
    storeBaseAnnotationProperties( node, document );

    // create [geom] element
    QDomElement geomElement = document.createElement( "geom" );
    node.appendChild( geomElement );

    // append the optional attributes
    if ( geomType() != InscribedSquare )
        geomElement.setAttribute( "type", (int)geomType() );
    if ( geomInnerColor().isValid() )
        geomElement.setAttribute( "color", geomInnerColor().name() );
}

Annotation::SubType GeomAnnotation::subType() const
{
    return AGeom;
}

GeomAnnotation::GeomType GeomAnnotation::geomType() const
{
    Q_D( const GeomAnnotation );

    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 );

    if (!d->pdfAnnot)
    {
        d->geomType = type;
        return;
    }

    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
{
    Q_D( const GeomAnnotation );

    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 );

    if (!d->pdfAnnot)
    {
        d->geomInnerColor = color;
        return;
    }

    AnnotGeometry * geomann = static_cast<AnnotGeometry*>(d->pdfAnnot);
    geomann->setInteriorColor(convertQColor( color ));
}


/** HighlightAnnotation [Annotation] */
class HighlightAnnotationPrivate : public AnnotationPrivate
{
    public:
        HighlightAnnotationPrivate();
        Annotation * makeAlias();
        Annot* createNativeAnnot(::Page *destPage, DocumentData *doc);

        // data fields
        HighlightAnnotation::HighlightType highlightType;
        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()
    : AnnotationPrivate(), highlightType( HighlightAnnotation::Highlight )
{
}

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;

    if ( !hlquads || !hlquads->getQuadrilateralsLength() )
        return quads;
    const int quadsCount = hlquads->getQuadrilateralsLength();

    double MTX[6];
    fillTransformationMTX(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;
}

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];
    fillTransformationMTX(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)
{
    // Setters are defined in the public class
    HighlightAnnotation *q = static_cast<HighlightAnnotation*>( makeAlias() );

    // Set page and document
    pdfPage = destPage;
    parentDoc = doc;

    // Set pdfAnnot
    PDFRectangle rect = boundaryToPdfRectangle(boundary, flags);
    pdfAnnot = new AnnotTextMarkup(destPage->getDoc(), &rect, toAnnotSubType(highlightType));

    // Set properties
    flushBaseAnnotationProperties();
    q->setHighlightQuads(highlightQuads);

    highlightQuads.clear(); // Free up memory

    delete q;

    return pdfAnnot;
}

HighlightAnnotation::HighlightAnnotation()
    : Annotation( *new HighlightAnnotationPrivate() )
{}

HighlightAnnotation::HighlightAnnotation(HighlightAnnotationPrivate &dd)
    : Annotation( dd )
{}

HighlightAnnotation::HighlightAnnotation( const QDomNode & node )
    : Annotation( *new HighlightAnnotationPrivate(), node )
{
    // loop through the whole children looking for a 'hl' element
    QDomNode subNode = node.firstChild();
    while( subNode.isElement() )
    {
        QDomElement e = subNode.toElement();
        subNode = subNode.nextSibling();
        if ( e.tagName() != "hl" )
            continue;

        // parse the attributes
        if ( e.hasAttribute( "type" ) )
            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() )
        {
            QDomElement qe = quadNode.toElement();
            if ( qe.tagName() != "quad" )
                continue;

            Quad q;
            q.points[0].setX(qe.attribute( "ax", "0.0" ).toDouble());
            q.points[0].setY(qe.attribute( "ay", "0.0" ).toDouble());
            q.points[1].setX(qe.attribute( "bx", "0.0" ).toDouble());
            q.points[1].setY(qe.attribute( "by", "0.0" ).toDouble());
            q.points[2].setX(qe.attribute( "cx", "0.0" ).toDouble());
            q.points[2].setY(qe.attribute( "cy", "0.0" ).toDouble());
            q.points[3].setX(qe.attribute( "dx", "0.0" ).toDouble());
            q.points[3].setY(qe.attribute( "dy", "0.0" ).toDouble());
            q.capStart = qe.hasAttribute( "start" );
            q.capEnd = qe.hasAttribute( "end" );
            q.feather = qe.attribute( "feather", "0.1" ).toDouble();
            quads.append( q );
        }
        setHighlightQuads(quads);

        // loading complete
        break;
    }
}

HighlightAnnotation::~HighlightAnnotation()
{
}

void HighlightAnnotation::store( QDomNode & node, QDomDocument & document ) const
{
    // store base annotation properties
    storeBaseAnnotationProperties( node, document );

    // create [hl] element
    QDomElement hlElement = document.createElement( "hl" );
    node.appendChild( hlElement );

    // append the optional attributes
    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 = quads.begin(), end = quads.end();
    for ( ; it != end; ++it )
    {
        QDomElement quadElement = document.createElement( "quad" );
        hlElement.appendChild( quadElement );
        const Quad & q = *it;
        quadElement.setAttribute( "ax", QString::number( q.points[0].x() ) );
        quadElement.setAttribute( "ay", QString::number( q.points[0].y() ) );
        quadElement.setAttribute( "bx", QString::number( q.points[1].x() ) );
        quadElement.setAttribute( "by", QString::number( q.points[1].y() ) );
        quadElement.setAttribute( "cx", QString::number( q.points[2].x() ) );
        quadElement.setAttribute( "cy", QString::number( q.points[2].y() ) );
        quadElement.setAttribute( "dx", QString::number( q.points[3].x() ) );
        quadElement.setAttribute( "dy", QString::number( q.points[3].y() ) );
        if ( q.capStart )
            quadElement.setAttribute( "start", 1 );
        if ( q.capEnd )
            quadElement.setAttribute( "end", 1 );
        quadElement.setAttribute( "feather", QString::number( q.feather ) );
    }
}

Annotation::SubType HighlightAnnotation::subType() const
{
    return AHighlight;
}

HighlightAnnotation::HighlightType HighlightAnnotation::highlightType() const
{
    Q_D( const HighlightAnnotation );

    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 );

    if (!d->pdfAnnot)
    {
        d->highlightType = type;
        return;
    }

    AnnotTextMarkup * hlann = static_cast<AnnotTextMarkup*>(d->pdfAnnot);
    hlann->setType(HighlightAnnotationPrivate::toAnnotSubType( type ));
}

QList< HighlightAnnotation::Quad > HighlightAnnotation::highlightQuads() const
{
    Q_D( const HighlightAnnotation );

    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 );

    if (!d->pdfAnnot)
    {
        d->highlightQuads = quads;
        return;
    }

    AnnotTextMarkup * hlann = static_cast<AnnotTextMarkup*>(d->pdfAnnot);
    AnnotQuadrilaterals * quadrilaterals = d->toQuadrilaterals(quads);
    hlann->setQuadrilaterals(quadrilaterals);
    delete quadrilaterals;
}


/** StampAnnotation [Annotation] */
class StampAnnotationPrivate : public AnnotationPrivate
{
    public:
        StampAnnotationPrivate();
        Annotation * makeAlias();
        Annot* createNativeAnnot(::Page *destPage, DocumentData *doc);

        // data fields
        QString stampIconName;
};

StampAnnotationPrivate::StampAnnotationPrivate()
    : AnnotationPrivate(), stampIconName( "Draft" )
{
}

Annotation * StampAnnotationPrivate::makeAlias()
{
    return new StampAnnotation(*this);
}

Annot* StampAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc)
{
    StampAnnotation *q = static_cast<StampAnnotation*>( makeAlias() );

    // Set page and document
    pdfPage = destPage;
    parentDoc = doc;

    // Set pdfAnnot
    PDFRectangle rect = boundaryToPdfRectangle(boundary, flags);
    pdfAnnot = new AnnotStamp(destPage->getDoc(), &rect);

    // Set properties
    flushBaseAnnotationProperties();
    q->setStampIconName(stampIconName);

    delete q;

    stampIconName.clear(); // Free up memory

    return pdfAnnot;
}

StampAnnotation::StampAnnotation()
    : Annotation( *new StampAnnotationPrivate() )
{}

StampAnnotation::StampAnnotation(StampAnnotationPrivate &dd)
    : Annotation( dd )
{}

StampAnnotation::StampAnnotation( const QDomNode & node )
    : Annotation( *new StampAnnotationPrivate(), node )
{
    // loop through the whole children looking for a 'stamp' element
    QDomNode subNode = node.firstChild();
    while( subNode.isElement() )
    {
        QDomElement e = subNode.toElement();
        subNode = subNode.nextSibling();
        if ( e.tagName() != "stamp" )
            continue;

        // parse the attributes
        if ( e.hasAttribute( "icon" ) )
            setStampIconName(e.attribute( "icon" ));

        // loading complete
        break;
    }
}

StampAnnotation::~StampAnnotation()
{
}

void StampAnnotation::store( QDomNode & node, QDomDocument & document ) const
{
    // store base annotation properties
    storeBaseAnnotationProperties( node, document );

    // create [stamp] element
    QDomElement stampElement = document.createElement( "stamp" );
    node.appendChild( stampElement );

    // append the optional attributes
    if ( stampIconName() != "Draft" )
        stampElement.setAttribute( "icon", stampIconName() );
}

Annotation::SubType StampAnnotation::subType() const
{
    return AStamp;
}

QString StampAnnotation::stampIconName() const
{
    Q_D( const StampAnnotation );

    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 );

    if (!d->pdfAnnot)
    {
        d->stampIconName = name;
        return;
    }

    AnnotStamp * stampann = static_cast<AnnotStamp*>(d->pdfAnnot);
    QByteArray encoded = name.toLatin1();
    GooString s(encoded.constData());
    stampann->setIcon(&s);
}

/** InkAnnotation [Annotation] */
class InkAnnotationPrivate : public AnnotationPrivate
{
    public:
        InkAnnotationPrivate();
        Annotation * makeAlias();
        Annot* createNativeAnnot(::Page *destPage, DocumentData *doc);

        // data fields
        QList< QLinkedList<QPointF> > inkPaths;

        // helper
        AnnotPath **toAnnotPaths(const QList< QLinkedList<QPointF> > &inkPaths);
};

InkAnnotationPrivate::InkAnnotationPrivate()
    : AnnotationPrivate()
{
}

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)
{
    // Setters are defined in the public class
    InkAnnotation *q = static_cast<InkAnnotation*>( makeAlias() );

    // Set page and document
    pdfPage = destPage;
    parentDoc = doc;

    // Set pdfAnnot
    PDFRectangle rect = boundaryToPdfRectangle(boundary, flags);
    pdfAnnot = new AnnotInk(destPage->getDoc(), &rect);

    // Set properties
    flushBaseAnnotationProperties();
    q->setInkPaths(inkPaths);

    inkPaths.clear(); // Free up memory

    delete q;

    return pdfAnnot;
}

InkAnnotation::InkAnnotation()
    : Annotation( *new InkAnnotationPrivate() )
{}

InkAnnotation::InkAnnotation(InkAnnotationPrivate &dd)
    : Annotation( dd )
{}

InkAnnotation::InkAnnotation( const QDomNode & node )
    : Annotation( *new InkAnnotationPrivate(), node )
{
    // loop through the whole children looking for a 'ink' element
    QDomNode subNode = node.firstChild();
    while( subNode.isElement() )
    {
        QDomElement e = subNode.toElement();
        subNode = subNode.nextSibling();
        if ( e.tagName() != "ink" )
            continue;

        // parse the 'path' subnodes
        QList< QLinkedList<QPointF> > paths;
        QDomNode pathNode = e.firstChild();
        while ( pathNode.isElement() )
        {
            QDomElement pathElement = pathNode.toElement();
            pathNode = pathNode.nextSibling();

            if ( pathElement.tagName() != "path" )
                continue;

            // build each path parsing 'point' subnodes
            QLinkedList<QPointF> path;
            QDomNode pointNode = pathElement.firstChild();
            while ( pointNode.isElement() )
            {
                QDomElement pointElement = pointNode.toElement();
                pointNode = pointNode.nextSibling();

                if ( pointElement.tagName() != "point" )
                    continue;

                QPointF p(pointElement.attribute( "x", "0.0" ).toDouble(), pointElement.attribute( "y", "0.0" ).toDouble());
                path.append( p );
            }

            // add the path to the path list if it contains at least 2 nodes
            if ( path.count() >= 2 )
                paths.append( path );
        }
        setInkPaths(paths);

        // loading complete
        break;
    }
}

InkAnnotation::~InkAnnotation()
{
}

void InkAnnotation::store( QDomNode & node, QDomDocument & document ) const
{
    // store base annotation properties
    storeBaseAnnotationProperties( node, document );

    // create [ink] element
    QDomElement inkElement = document.createElement( "ink" );
    node.appendChild( inkElement );

    // append the optional attributes
    const QList< QLinkedList<QPointF> > paths = inkPaths();
    if ( paths.count() < 1 )
        return;
    QList< QLinkedList<QPointF> >::const_iterator pIt = paths.begin(), pEnd = paths.end();
    for ( ; pIt != pEnd; ++pIt )
    {
        QDomElement pathElement = document.createElement( "path" );
        inkElement.appendChild( pathElement );
        const QLinkedList<QPointF> & path = *pIt;
        QLinkedList<QPointF>::const_iterator iIt = path.begin(), iEnd = path.end();
        for ( ; iIt != iEnd; ++iIt )
        {
            const QPointF & point = *iIt;
            QDomElement pointElement = document.createElement( "point" );
            pathElement.appendChild( pointElement );
            pointElement.setAttribute( "x", QString::number( point.x() ) );
            pointElement.setAttribute( "y", QString::number( point.y() ) );
        }
    }
}

Annotation::SubType InkAnnotation::subType() const
{
    return AInk;
}

QList< QLinkedList<QPointF> > InkAnnotation::inkPaths() const
{
    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->fillTransformationMTX(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 );

    if (!d->pdfAnnot)
    {
        d->inkPaths = paths;
        return;
    }

    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;
}


/** LinkAnnotation [Annotation] */
class LinkAnnotationPrivate : public AnnotationPrivate
{
    public:
        LinkAnnotationPrivate();
        ~LinkAnnotationPrivate();
        Annotation * makeAlias();
        Annot* createNativeAnnot(::Page *destPage, DocumentData *doc);

        // data fields
        Link * linkDestination;
        LinkAnnotation::HighlightMode linkHLMode;
        QPointF linkRegion[4];
};

LinkAnnotationPrivate::LinkAnnotationPrivate()
    : AnnotationPrivate(), linkDestination( 0 ), linkHLMode( LinkAnnotation::Invert )
{
}

LinkAnnotationPrivate::~LinkAnnotationPrivate()
{
    delete linkDestination;
}

Annotation * LinkAnnotationPrivate::makeAlias()
{
    return new LinkAnnotation(*this);
}

Annot* LinkAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc)
{
    return 0; // Not implemented
}

LinkAnnotation::LinkAnnotation()
    : Annotation( *new LinkAnnotationPrivate() )
{}

LinkAnnotation::LinkAnnotation(LinkAnnotationPrivate &dd)
    : Annotation( dd )
{}

LinkAnnotation::LinkAnnotation( const QDomNode & node )
    : Annotation( *new LinkAnnotationPrivate(), node )
{
    // loop through the whole children looking for a 'link' element
    QDomNode subNode = node.firstChild();
    while( subNode.isElement() )
    {
        QDomElement e = subNode.toElement();
        subNode = subNode.nextSibling();
        if ( e.tagName() != "link" )
            continue;

        // parse the attributes
        if ( e.hasAttribute( "hlmode" ) )
            setLinkHighlightMode((LinkAnnotation::HighlightMode)e.attribute( "hlmode" ).toInt());

        // parse all 'quad' subnodes
        QDomNode quadNode = e.firstChild();
        for ( ; quadNode.isElement(); quadNode = quadNode.nextSibling() )
        {
            QDomElement qe = quadNode.toElement();
            if ( qe.tagName() == "quad" )
            {
                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" )
            {
                QString type = qe.attribute( "type" );
                if ( type == "GoTo" )
                {
                    Poppler::LinkGoto * go = new Poppler::LinkGoto( QRect(), qe.attribute( "filename" ), LinkDestination( qe.attribute( "destination" ) ) );
                    setLinkDestination(go);
                }
                else if ( type == "Exec" )
                {
                    Poppler::LinkExecute * exec = new Poppler::LinkExecute( QRect(), qe.attribute( "filename" ), qe.attribute( "parameters" ) );
                    setLinkDestination(exec);
                }
                else if ( type == "Browse" )
                {
                    Poppler::LinkBrowse * browse = new Poppler::LinkBrowse( QRect(), qe.attribute( "url" ) );
                    setLinkDestination(browse);
                }
                else if ( type == "Action" )
                {
                    Poppler::LinkAction::ActionType act;
                    QString actString = qe.attribute( "action" );
                    bool found = true;
                    if ( actString == "PageFirst" )
                        act = Poppler::LinkAction::PageFirst;
                    else if ( actString == "PagePrev" )
                        act = Poppler::LinkAction::PagePrev;
                    else if ( actString == "PageNext" )
                        act = Poppler::LinkAction::PageNext;
                    else if ( actString == "PageLast" )
                        act = Poppler::LinkAction::PageLast;
                    else if ( actString == "HistoryBack" )
                        act = Poppler::LinkAction::HistoryBack;
                    else if ( actString == "HistoryForward" )
                        act = Poppler::LinkAction::HistoryForward;
                    else if ( actString == "Quit" )
                        act = Poppler::LinkAction::Quit;
                    else if ( actString == "Presentation" )
                        act = Poppler::LinkAction::Presentation;
                    else if ( actString == "EndPresentation" )
                        act = Poppler::LinkAction::EndPresentation;
                    else if ( actString == "Find" )
                        act = Poppler::LinkAction::Find;
                    else if ( actString == "GoToPage" )
                        act = Poppler::LinkAction::GoToPage;
                    else if ( actString == "Close" )
                        act = Poppler::LinkAction::Close;
                    else if ( actString == "Print" )
                        act = Poppler::LinkAction::Print;
                    else
                        found = false;
                    if (found)
                    {
                        Poppler::LinkAction * action = new Poppler::LinkAction( QRect(), act );
                        setLinkDestination(action);
                    }
                }
#if 0
                else if ( type == "Movie" )
                {
                    Poppler::LinkMovie * movie = new Poppler::LinkMovie( QRect() );
                    setLinkDestination(movie);
                }
#endif
            }
        }

        // loading complete
        break;
    }
}

LinkAnnotation::~LinkAnnotation()
{
}

void LinkAnnotation::store( QDomNode & node, QDomDocument & document ) const
{
    // store base annotation properties
    storeBaseAnnotationProperties( node, document );

    // create [hl] element
    QDomElement linkElement = document.createElement( "link" );
    node.appendChild( linkElement );

    // append the optional attributes
    if ( linkHighlightMode() != Invert )
        linkElement.setAttribute( "hlmode", (int)linkHighlightMode() );

    // saving region
    QDomElement quadElement = document.createElement( "quad" );
    linkElement.appendChild( quadElement );
    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 ( linkDestination() )
    {
        switch( linkDestination()->linkType() )
        {
            case Poppler::Link::Goto:
            {
                Poppler::LinkGoto * go = static_cast< Poppler::LinkGoto * >( linkDestination() );
                hyperlinkElement.setAttribute( "type", "GoTo" );
                hyperlinkElement.setAttribute( "filename", go->fileName() );
                hyperlinkElement.setAttribute( "destionation", go->destination().toString() ); // TODO remove for poppler 0.28
                hyperlinkElement.setAttribute( "destination", go->destination().toString() );
                break;
            }
            case Poppler::Link::Execute:
            {
                Poppler::LinkExecute * exec = static_cast< Poppler::LinkExecute * >( linkDestination() );
                hyperlinkElement.setAttribute( "type", "Exec" );
                hyperlinkElement.setAttribute( "filename", exec->fileName() );
                hyperlinkElement.setAttribute( "parameters", exec->parameters() );
                break;
            }
            case Poppler::Link::Browse:
            {
                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 * >( linkDestination() );
                hyperlinkElement.setAttribute( "type", "Action" );
                switch ( action->actionType() )
                {
                    case Poppler::LinkAction::PageFirst:
                        hyperlinkElement.setAttribute( "action", "PageFirst" );
                        break;
                    case Poppler::LinkAction::PagePrev:
                        hyperlinkElement.setAttribute( "action", "PagePrev" );
                        break;
                    case Poppler::LinkAction::PageNext:
                        hyperlinkElement.setAttribute( "action", "PageNext" );
                        break;
                    case Poppler::LinkAction::PageLast:
                        hyperlinkElement.setAttribute( "action", "PageLast" );
                        break;
                    case Poppler::LinkAction::HistoryBack:
                        hyperlinkElement.setAttribute( "action", "HistoryBack" );
                        break;
                    case Poppler::LinkAction::HistoryForward:
                        hyperlinkElement.setAttribute( "action", "HistoryForward" );
                        break;
                    case Poppler::LinkAction::Quit:
                        hyperlinkElement.setAttribute( "action", "Quit" );
                        break;
                    case Poppler::LinkAction::Presentation:
                        hyperlinkElement.setAttribute( "action", "Presentation" );
                        break;
                    case Poppler::LinkAction::EndPresentation:
                        hyperlinkElement.setAttribute( "action", "EndPresentation" );
                        break;
                    case Poppler::LinkAction::Find:
                        hyperlinkElement.setAttribute( "action", "Find" );
                        break;
                    case Poppler::LinkAction::GoToPage:
                        hyperlinkElement.setAttribute( "action", "GoToPage" );
                        break;
                    case Poppler::LinkAction::Close:
                        hyperlinkElement.setAttribute( "action", "Close" );
                        break;
                    case Poppler::LinkAction::Print:
                        hyperlinkElement.setAttribute( "action", "Print" );
                        break;
                }
                break;
            }
            case Poppler::Link::Movie:
            {
                hyperlinkElement.setAttribute( "type", "Movie" );
                break;
            }
            case Poppler::Link::Rendition:
            {
                hyperlinkElement.setAttribute( "type", "Rendition" );
                break;
            }
            case Poppler::Link::Sound:
            {
                // FIXME: implement me
                break;
            }
            case Poppler::Link::None:
                break;
        }
    }
}

Annotation::SubType LinkAnnotation::subType() const
{
    return ALink;
}

Link* LinkAnnotation::linkDestination() const
{
    Q_D( const LinkAnnotation );
    return d->linkDestination;
}

void LinkAnnotation::setLinkDestination( Link *link )
{
    Q_D( LinkAnnotation );
    delete d->linkDestination;
    d->linkDestination = link;
}

LinkAnnotation::HighlightMode LinkAnnotation::linkHighlightMode() const
{
    Q_D( const LinkAnnotation );
    return d->linkHLMode;
}

void LinkAnnotation::setLinkHighlightMode( LinkAnnotation::HighlightMode mode )
{
    Q_D( LinkAnnotation );
    d->linkHLMode = mode;
}

QPointF LinkAnnotation::linkRegionPoint( int id ) const
{
    if ( id < 0 || id >= 4 )
        return QPointF();

    Q_D( const LinkAnnotation );
    return d->linkRegion[id];
}

void LinkAnnotation::setLinkRegionPoint( int id, const QPointF &point )
{
    if ( id < 0 || id >= 4 )
        return;

    Q_D( LinkAnnotation );
    d->linkRegion[id] = point;
}

/** CaretAnnotation [Annotation] */
class CaretAnnotationPrivate : public AnnotationPrivate
{
    public:
        CaretAnnotationPrivate();
        Annotation * makeAlias();
        Annot* createNativeAnnot(::Page *destPage, DocumentData *doc);

        // data fields
        CaretAnnotation::CaretSymbol symbol;
};

static QString caretSymbolToString( CaretAnnotation::CaretSymbol symbol )
{
    switch ( symbol )
    {
        case CaretAnnotation::None:
            return QString::fromLatin1( "None" );
        case CaretAnnotation::P:
            return QString::fromLatin1( "P" );
    }
    return QString();
}

static CaretAnnotation::CaretSymbol caretSymbolFromString( const QString &symbol )
{
    if ( symbol == QLatin1String( "None" ) )
        return CaretAnnotation::None;
    else if ( symbol == QLatin1String( "P" ) )
        return CaretAnnotation::P;
    return CaretAnnotation::None;
}

CaretAnnotationPrivate::CaretAnnotationPrivate()
    : AnnotationPrivate(), symbol( CaretAnnotation::None )
{
}

Annotation * CaretAnnotationPrivate::makeAlias()
{
    return new CaretAnnotation(*this);
}

Annot* CaretAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc)
{
    // 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 = boundaryToPdfRectangle(boundary, flags);
    pdfAnnot = new AnnotCaret(destPage->getDoc(), &rect);

    // Set properties
    flushBaseAnnotationProperties();
    q->setCaretSymbol(symbol);

    delete q;
    return pdfAnnot;
}

CaretAnnotation::CaretAnnotation()
    : Annotation( *new CaretAnnotationPrivate() )
{
}

CaretAnnotation::CaretAnnotation(CaretAnnotationPrivate &dd)
    : Annotation( dd )
{
}

CaretAnnotation::CaretAnnotation( const QDomNode & node )
    : Annotation( *new CaretAnnotationPrivate(), node )
{
    // loop through the whole children looking for a 'caret' element
    QDomNode subNode = node.firstChild();
    while( subNode.isElement() )
    {
        QDomElement e = subNode.toElement();
        subNode = subNode.nextSibling();
        if ( e.tagName() != "caret" )
            continue;

        // parse the attributes
        if ( e.hasAttribute( "symbol" ) )
            setCaretSymbol(caretSymbolFromString( e.attribute( "symbol" ) ));

        // loading complete
        break;
    }
}

CaretAnnotation::~CaretAnnotation()
{
}

void CaretAnnotation::store( QDomNode & node, QDomDocument & document ) const
{
    // store base annotation properties
    storeBaseAnnotationProperties( node, document );

    // create [caret] element
    QDomElement caretElement = document.createElement( "caret" );
    node.appendChild( caretElement );

    // append the optional attributes
    if ( caretSymbol() != CaretAnnotation::None )
        caretElement.setAttribute( "symbol", caretSymbolToString( caretSymbol() ) );
}

Annotation::SubType CaretAnnotation::subType() const
{
    return ACaret;
}

CaretAnnotation::CaretSymbol CaretAnnotation::caretSymbol() const
{
    Q_D( const CaretAnnotation );

    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 );

    if (!d->pdfAnnot)
    {
        d->symbol = symbol;
        return;
    }

    AnnotCaret * caretann = static_cast<AnnotCaret *>(d->pdfAnnot);
    caretann->setSymbol((AnnotCaret::AnnotCaretSymbol)symbol);
}

/** FileAttachmentAnnotation [Annotation] */
class FileAttachmentAnnotationPrivate : public AnnotationPrivate
{
    public:
        FileAttachmentAnnotationPrivate();
        ~FileAttachmentAnnotationPrivate();
        Annotation * makeAlias();
        Annot* createNativeAnnot(::Page *destPage, DocumentData *doc);

        // data fields
        QString icon;
        EmbeddedFile *embfile;
};

FileAttachmentAnnotationPrivate::FileAttachmentAnnotationPrivate()
    : AnnotationPrivate(), icon( "PushPin" ), embfile( 0 )
{
}

FileAttachmentAnnotationPrivate::~FileAttachmentAnnotationPrivate()
{
    delete embfile;
}

Annotation * FileAttachmentAnnotationPrivate::makeAlias()
{
    return new FileAttachmentAnnotation(*this);
}

Annot* FileAttachmentAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc)
{
    return 0; // Not implemented
}

FileAttachmentAnnotation::FileAttachmentAnnotation()
    : Annotation( *new FileAttachmentAnnotationPrivate() )
{
}

FileAttachmentAnnotation::FileAttachmentAnnotation(FileAttachmentAnnotationPrivate &dd)
    : Annotation( dd )
{
}

FileAttachmentAnnotation::FileAttachmentAnnotation( const QDomNode & node )
    : Annotation( *new FileAttachmentAnnotationPrivate(), node )
{
    // loop through the whole children looking for a 'fileattachment' element
    QDomNode subNode = node.firstChild();
    while( subNode.isElement() )
    {
        QDomElement e = subNode.toElement();
        subNode = subNode.nextSibling();
        if ( e.tagName() != "fileattachment" )
            continue;

        // loading complete
        break;
    }
}

FileAttachmentAnnotation::~FileAttachmentAnnotation()
{
}

void FileAttachmentAnnotation::store( QDomNode & node, QDomDocument & document ) const
{
    // store base annotation properties
    storeBaseAnnotationProperties( node, document );

    // create [fileattachment] element
    QDomElement fileAttachmentElement = document.createElement( "fileattachment" );
    node.appendChild( fileAttachmentElement );
}

Annotation::SubType FileAttachmentAnnotation::subType() const
{
    return AFileAttachment;
}

QString FileAttachmentAnnotation::fileIconName() const
{
    Q_D( const FileAttachmentAnnotation );
    return d->icon;
}

void FileAttachmentAnnotation::setFileIconName( const QString &icon )
{
    Q_D( FileAttachmentAnnotation );
    d->icon = icon;
}

EmbeddedFile* FileAttachmentAnnotation::embeddedFile() const
{
    Q_D( const FileAttachmentAnnotation );
    return d->embfile;
}

void FileAttachmentAnnotation::setEmbeddedFile( EmbeddedFile *ef )
{
    Q_D( FileAttachmentAnnotation );
    d->embfile = ef;
}

/** SoundAnnotation [Annotation] */
class SoundAnnotationPrivate : public AnnotationPrivate
{
    public:
        SoundAnnotationPrivate();
        ~SoundAnnotationPrivate();
        Annotation * makeAlias();
        Annot* createNativeAnnot(::Page *destPage, DocumentData *doc);

        // data fields
        QString icon;
        SoundObject *sound;
};

SoundAnnotationPrivate::SoundAnnotationPrivate()
    : AnnotationPrivate(), icon( "Speaker" ), sound( 0 )
{
}

SoundAnnotationPrivate::~SoundAnnotationPrivate()
{
    delete sound;
}

Annotation * SoundAnnotationPrivate::makeAlias()
{
    return new SoundAnnotation(*this);
}

Annot* SoundAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc)
{
    return 0; // Not implemented
}

SoundAnnotation::SoundAnnotation()
    : Annotation( *new SoundAnnotationPrivate() )
{
}

SoundAnnotation::SoundAnnotation(SoundAnnotationPrivate &dd)
    : Annotation( dd )
{
}

SoundAnnotation::SoundAnnotation( const QDomNode & node )
    : Annotation( *new SoundAnnotationPrivate(), node )
{
    // loop through the whole children looking for a 'sound' element
    QDomNode subNode = node.firstChild();
    while( subNode.isElement() )
    {
        QDomElement e = subNode.toElement();
        subNode = subNode.nextSibling();
        if ( e.tagName() != "sound" )
            continue;

        // loading complete
        break;
    }
}

SoundAnnotation::~SoundAnnotation()
{
}

void SoundAnnotation::store( QDomNode & node, QDomDocument & document ) const
{
    // store base annotation properties
    storeBaseAnnotationProperties( node, document );

    // create [sound] element
    QDomElement soundElement = document.createElement( "sound" );
    node.appendChild( soundElement );
}

Annotation::SubType SoundAnnotation::subType() const
{
    return ASound;
}

QString SoundAnnotation::soundIconName() const
{
    Q_D( const SoundAnnotation );
    return d->icon;
}

void SoundAnnotation::setSoundIconName( const QString &icon )
{
    Q_D( SoundAnnotation );
    d->icon = icon;
}

SoundObject* SoundAnnotation::sound() const
{
    Q_D( const SoundAnnotation );
    return d->sound;
}

void SoundAnnotation::setSound( SoundObject *s )
{
    Q_D( SoundAnnotation );
    d->sound = s;
}

/** MovieAnnotation [Annotation] */
class MovieAnnotationPrivate : public AnnotationPrivate
{
    public:
        MovieAnnotationPrivate();
        ~MovieAnnotationPrivate();
        Annotation * makeAlias();
        Annot* createNativeAnnot(::Page *destPage, DocumentData *doc);

        // data fields
        MovieObject *movie;
        QString title;
};

MovieAnnotationPrivate::MovieAnnotationPrivate()
    : AnnotationPrivate(), movie( 0 )
{
}

MovieAnnotationPrivate::~MovieAnnotationPrivate()
{
    delete movie;
}

Annotation * MovieAnnotationPrivate::makeAlias()
{
    return new MovieAnnotation(*this);
}

Annot* MovieAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc)
{
    return 0; // Not implemented
}

MovieAnnotation::MovieAnnotation()
    : Annotation( *new MovieAnnotationPrivate() )
{
}

MovieAnnotation::MovieAnnotation(MovieAnnotationPrivate &dd)
    : Annotation( dd )
{
}

MovieAnnotation::MovieAnnotation( const QDomNode & node )
    : Annotation( *new MovieAnnotationPrivate(), node )
{
    // loop through the whole children looking for a 'movie' element
    QDomNode subNode = node.firstChild();
    while( subNode.isElement() )
    {
        QDomElement e = subNode.toElement();
        subNode = subNode.nextSibling();
        if ( e.tagName() != "movie" )
            continue;

        // loading complete
        break;
    }
}

MovieAnnotation::~MovieAnnotation()
{
}

void MovieAnnotation::store( QDomNode & node, QDomDocument & document ) const
{
    // store base annotation properties
    storeBaseAnnotationProperties( node, document );

    // create [movie] element
    QDomElement movieElement = document.createElement( "movie" );
    node.appendChild( movieElement );
}

Annotation::SubType MovieAnnotation::subType() const
{
    return AMovie;
}

MovieObject* MovieAnnotation::movie() const
{
    Q_D( const MovieAnnotation );
    return d->movie;
}

void MovieAnnotation::setMovie( MovieObject *movie )
{
    Q_D( MovieAnnotation );
    d->movie = movie;
}

QString MovieAnnotation::movieTitle() const
{
    Q_D( const MovieAnnotation );
    return d->title;
}

void MovieAnnotation::setMovieTitle( const QString &title )
{
    Q_D( MovieAnnotation );
    d->title = title;
}

/** ScreenAnnotation [Annotation] */
class ScreenAnnotationPrivate : public AnnotationPrivate
{
    public:
        ScreenAnnotationPrivate();
        ~ScreenAnnotationPrivate();
        Annotation * makeAlias();
        Annot* createNativeAnnot(::Page *destPage, DocumentData *doc);

        // data fields
        LinkRendition *action;
        QString title;
};

ScreenAnnotationPrivate::ScreenAnnotationPrivate()
    : AnnotationPrivate(), action( 0 )
{
}

ScreenAnnotationPrivate::~ScreenAnnotationPrivate()
{
    delete action;
}

ScreenAnnotation::ScreenAnnotation(ScreenAnnotationPrivate &dd)
    : Annotation( dd )
{}

Annotation * ScreenAnnotationPrivate::makeAlias()
{
    return new ScreenAnnotation(*this);
}

Annot* ScreenAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc)
{
    return 0; // Not implemented
}

ScreenAnnotation::ScreenAnnotation()
    : Annotation( *new ScreenAnnotationPrivate() )
{
}

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;
}

LinkRendition* ScreenAnnotation::action() const
{
    Q_D( const ScreenAnnotation );
    return d->action;
}

void ScreenAnnotation::setAction( LinkRendition *action )
{
    Q_D( ScreenAnnotation );
    d->action = action;
}

QString ScreenAnnotation::screenTitle() const
{
    Q_D( const ScreenAnnotation );
    return d->title;
}

void ScreenAnnotation::setScreenTitle( const QString &title )
{
    Q_D( ScreenAnnotation );
    d->title = title;
}

Link* ScreenAnnotation::additionalAction( AdditionalActionType type ) const
{
    Q_D( const ScreenAnnotation );
    return d->additionalAction( type );
}

/** WidgetAnnotation [Annotation] */
class WidgetAnnotationPrivate : public AnnotationPrivate
{
    public:
        Annotation * makeAlias();
        Annot* createNativeAnnot(::Page *destPage, DocumentData *doc);
};

Annotation * WidgetAnnotationPrivate::makeAlias()
{
    return new WidgetAnnotation(*this);
}

Annot* WidgetAnnotationPrivate::createNativeAnnot(::Page *destPage, DocumentData *doc)
{
    return 0; // Not implemented
}

WidgetAnnotation::WidgetAnnotation(WidgetAnnotationPrivate &dd)
    : Annotation( dd )
{}

WidgetAnnotation::WidgetAnnotation()
    : Annotation( *new WidgetAnnotationPrivate() )
{
}

WidgetAnnotation::~WidgetAnnotation()
{
}

void WidgetAnnotation::store( QDomNode & node, QDomDocument & document ) const
{
    // store base annotation properties
    storeBaseAnnotationProperties( node, document );

    // create [widget] element
    QDomElement widgetElement = document.createElement( "widget" );
    node.appendChild( widgetElement );
}

Annotation::SubType WidgetAnnotation::subType() const
{
    return AWidget;
}

Link* WidgetAnnotation::additionalAction( AdditionalActionType type ) const
{
    Q_D( const WidgetAnnotation );
    return d->additionalAction( type );
}

//BEGIN utility annotation functions
QColor convertAnnotColor( AnnotColor *color )
{
    if ( !color )
        return QColor();

    QColor newcolor;
    const double *color_data = color->getValues();
    switch ( color->getSpace() )
    {
        case AnnotColor::colorTransparent: // = 0,
            newcolor = Qt::transparent;
            break;
        case AnnotColor::colorGray: // = 1,
            newcolor.setRgbF( color_data[0], color_data[0], color_data[0] );
            break;
        case AnnotColor::colorRGB: // = 3,
            newcolor.setRgbF( color_data[0], color_data[1], color_data[2] );
            break;
        case AnnotColor::colorCMYK: // = 4
            newcolor.setCmykF( color_data[0], color_data[1], color_data[2], color_data[3] );
            break;
    }
    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

}
