/* poppler-page.cc: qt interface to poppler
 * Copyright (C) 2005, Net Integration Technologies, Inc.
 * Copyright (C) 2005, Brad Hards <bradh@frogmouth.net>
 * Copyright (C) 2005-2009, Albert Astals Cid <aacid@kde.org>
 * Copyright (C) 2005, Stefan Kebekus <stefan.kebekus@math.uni-koeln.de>
 * Copyright (C) 2006-2009, Pino Toscano <pino@kde.org>
 * Copyright (C) 2008 Carlos Garcia Campos <carlosgc@gnome.org>
 * Copyright (C) 2009 Shawn Rutledge <shawn.t.rutledge@gmail.com>
 *
 * 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.
 */

#include <poppler-qt4.h>

#include <QtCore/QHash>
#include <QtCore/QMap>
#include <QtCore/QVarLengthArray>
#include <QtGui/QImage>
#include <QtGui/QPainter>

#include <config.h>
#include <PDFDoc.h>
#include <Catalog.h>
#include <Form.h>
#include <ErrorCodes.h>
#include <TextOutputDev.h>
#include <Annot.h>
#include <Link.h>
#if defined(HAVE_SPLASH)
#include <SplashOutputDev.h>
#include <splash/SplashBitmap.h>
#include <ArthurOutputDev.h>
#endif

#include "poppler-private.h"
#include "poppler-page-transition-private.h"
#include "poppler-page-private.h"
#include "poppler-link-extractor-private.h"
#include "poppler-annotation-helper.h"
#include "poppler-annotation-private.h"
#include "poppler-form.h"

namespace Poppler {

class DummyAnnotation : public Annotation
{
    public:
        DummyAnnotation()
            : Annotation( *new AnnotationPrivate() )
        {
        }

        virtual SubType subType() const { return A_BASE; }
};

Link* PageData::convertLinkActionToLink(::LinkAction * a, const QRectF &linkArea)
{
    return convertLinkActionToLink(a, parentDoc, linkArea);
}

Link* PageData::convertLinkActionToLink(::LinkAction * a, DocumentData *parentDoc, const QRectF &linkArea)
{
  if ( !a )
    return NULL;

  Link * popplerLink = NULL;
  switch ( a->getKind() )
  {
    case actionGoTo:
    {
      LinkGoTo * g = (LinkGoTo *) a;
      const LinkDestinationData ldd( g->getDest(), g->getNamedDest(), parentDoc, false );
      // create link: no ext file, namedDest, object pointer
      popplerLink = new LinkGoto( linkArea, QString::null, LinkDestination( ldd ) );
    }
    break;

    case actionGoToR:
    {
      LinkGoToR * g = (LinkGoToR *) a;
      // copy link file
      const QString fileName = UnicodeParsedString( g->getFileName() );
      const LinkDestinationData ldd( g->getDest(), g->getNamedDest(), parentDoc, !fileName.isEmpty() );
      // ceate link: fileName, namedDest, object pointer
      popplerLink = new LinkGoto( linkArea, fileName, LinkDestination( ldd ) );
    }
    break;

    case actionLaunch:
    {
      LinkLaunch * e = (LinkLaunch *)a;
      GooString * p = e->getParams();
      popplerLink = new LinkExecute( linkArea, e->getFileName()->getCString(), p ? p->getCString() : 0 );
    }
    break;

    case actionNamed:
    {
      const char * name = ((LinkNamed *)a)->getName()->getCString();
      if ( !strcmp( name, "NextPage" ) )
        popplerLink = new LinkAction( linkArea, LinkAction::PageNext );
      else if ( !strcmp( name, "PrevPage" ) )
        popplerLink = new LinkAction( linkArea, LinkAction::PagePrev );
      else if ( !strcmp( name, "FirstPage" ) )
        popplerLink = new LinkAction( linkArea, LinkAction::PageFirst );
      else if ( !strcmp( name, "LastPage" ) )
        popplerLink = new LinkAction( linkArea, LinkAction::PageLast );
      else if ( !strcmp( name, "GoBack" ) )
        popplerLink = new LinkAction( linkArea, LinkAction::HistoryBack );
      else if ( !strcmp( name, "GoForward" ) )
        popplerLink = new LinkAction( linkArea, LinkAction::HistoryForward );
      else if ( !strcmp( name, "Quit" ) )
        popplerLink = new LinkAction( linkArea, LinkAction::Quit );
      else if ( !strcmp( name, "GoToPage" ) )
        popplerLink = new LinkAction( linkArea, LinkAction::GoToPage );
      else if ( !strcmp( name, "Find" ) )
        popplerLink = new LinkAction( linkArea, LinkAction::Find );
      else if ( !strcmp( name, "FullScreen" ) )
        popplerLink = new LinkAction( linkArea, LinkAction::Presentation );
      else if ( !strcmp( name, "Close" ) )
      {
        // acroread closes the document always, doesnt care whether 
        // its presentation mode or not
        // popplerLink = new LinkAction( linkArea, LinkAction::EndPresentation );
        popplerLink = new LinkAction( linkArea, LinkAction::Close );
      }
      else
      {
        // TODO
      }
    }
    break;

    case actionURI:
    {
      popplerLink = new LinkBrowse( linkArea, ((LinkURI *)a)->getURI()->getCString() );
    }
    break;

    case actionSound:
    {
      ::LinkSound *ls = (::LinkSound *)a;
      popplerLink = new LinkSound( linkArea, ls->getVolume(), ls->getSynchronous(), ls->getRepeat(), ls->getMix(), new SoundObject( ls->getSound() ) );
    }
    break;

    case actionJavaScript:
    {
      ::LinkJavaScript *ljs = (::LinkJavaScript *)a;
      popplerLink = new LinkJavaScript( linkArea, UnicodeParsedString(ljs->getScript()) );
    }
    break;

    case actionMovie:
/*      TODO this (Movie link)
          m_type = Movie;
          LinkMovie * m = (LinkMovie *) a;
          // copy Movie parameters (2 IDs and a const char *)
          Ref * r = m->getAnnotRef();
          m_refNum = r->num;
          m_refGen = r->gen;
          copyString( m_uri, m->getTitle()->getCString() );
*/  break;

    case actionUnknown:
    break;
  }

  return popplerLink;
}


Page::Page(DocumentData *doc, int index) {
  m_page = new PageData();
  m_page->index = index;
  m_page->parentDoc = doc;
  m_page->page = doc->doc->getCatalog()->getPage(m_page->index + 1);
  m_page->transition = 0;
}

Page::~Page()
{
  delete m_page->transition;
  delete m_page;
}

QImage Page::renderToImage(double xres, double yres, int x, int y, int w, int h, Rotation rotate) const
{
  int rotation = (int)rotate * 90;
  QImage img;
  switch(m_page->parentDoc->m_backend)
  {
    case Poppler::Document::SplashBackend:
    {
#if defined(HAVE_SPLASH)
      SplashOutputDev *splash_output = static_cast<SplashOutputDev *>(m_page->parentDoc->getOutputDev());

      m_page->parentDoc->doc->displayPageSlice(splash_output, m_page->index + 1, xres, yres,
						 rotation, false, true, false, x, y, w, h);

      SplashBitmap *bitmap = splash_output->getBitmap();
      int bw = bitmap->getWidth();
      int bh = bitmap->getHeight();

      SplashColorPtr dataPtr = splash_output->getBitmap()->getDataPtr();

      if (QSysInfo::BigEndian == QSysInfo::ByteOrder)
      {
        uchar c;
        int count = bw * bh * 4;
        for (int k = 0; k < count; k += 4)
        {
          c = dataPtr[k];
          dataPtr[k] = dataPtr[k+3];
          dataPtr[k+3] = c;

          c = dataPtr[k+1];
          dataPtr[k+1] = dataPtr[k+2];
          dataPtr[k+2] = c;
        }
      }

      // construct a qimage SHARING the raw bitmap data in memory
      QImage tmpimg( dataPtr, bw, bh, QImage::Format_ARGB32 );
      img = tmpimg.copy();
      // unload underlying xpdf bitmap
      splash_output->startPage( 0, NULL );
#endif
      break;
    }
    case Poppler::Document::ArthurBackend:
    {
#if defined(HAVE_SPLASH)
      QSize size = pageSize();
      QImage tmpimg(w == -1 ? qRound( size.width() * xres / 72.0 ) : w, h == -1 ? qRound( size.height() * yres / 72.0 ) : h, QImage::Format_ARGB32);

      QPainter painter(&tmpimg);
      if (m_page->parentDoc->m_hints & Document::Antialiasing)
          painter.setRenderHint(QPainter::Antialiasing);
      if (m_page->parentDoc->m_hints & Document::TextAntialiasing)
          painter.setRenderHint(QPainter::TextAntialiasing);
      painter.save();
      painter.translate(x == -1 ? 0 : -x, y == -1 ? 0 : -y);
      ArthurOutputDev arthur_output(&painter);
      arthur_output.startDoc(m_page->parentDoc->doc->getXRef());
      m_page->parentDoc->doc->displayPageSlice(&arthur_output,
						 m_page->index + 1,
						 xres,
						 yres,
						 rotation,
						 false,
						 true,
						 false,
						 x,
						 y,
						 w,
						 h);
      painter.restore();
      painter.end();
      img = tmpimg;
#endif
      break;
    }
  }

  return img;
}

QImage Page::thumbnail() const
{
  unsigned char* data = 0;
  int w = 0;
  int h = 0;
  int rowstride = 0;
  GBool r = m_page->page->loadThumb(&data, &w, &h, &rowstride);
  QImage ret;
  if (r)
  {
    // first construct a temporary image with the data got,
    // then force a copy of it so we can free the raw thumbnail data
    ret = QImage(data, w, h, rowstride, QImage::Format_RGB888).copy();
    gfree(data);
  }
  return ret;
}

QString Page::text(const QRectF &r) const
{
  TextOutputDev *output_dev;
  GooString *s;
  PDFRectangle *rect;
  QString result;
  
  output_dev = new TextOutputDev(0, gFalse, gFalse, gFalse);
  m_page->parentDoc->doc->displayPageSlice(output_dev, m_page->index + 1, 72, 72,
      0, false, true, false, -1, -1, -1, -1);
  if (r.isNull())
  {
    rect = m_page->page->getCropBox();
    s = output_dev->getText(rect->x1, rect->y1, rect->x2, rect->y2);
  }
  else
  {
    s = output_dev->getText(r.left(), r.top(), r.right(), r.bottom());
  }

  result = QString::fromUtf8(s->getCString());

  delete output_dev;
  delete s;
  return result;
}

bool Page::search(const QString &text, QRectF &rect, SearchDirection direction, SearchMode caseSensitive, Rotation rotate) const
{
  const QChar * str = text.unicode();
  int len = text.length();
  QVector<Unicode> u(len);
  for (int i = 0; i < len; ++i) u[i] = str[i].unicode();

  GBool sCase;
  if (caseSensitive == CaseSensitive) sCase = gTrue;
  else sCase = gFalse;

  bool found = false;
  double sLeft, sTop, sRight, sBottom;
  sLeft = rect.left();
  sTop = rect.top();
  sRight = rect.right();
  sBottom = rect.bottom();

  int rotation = (int)rotate * 90;

  // fetch ourselves a textpage
  TextOutputDev td(NULL, gTrue, gFalse, gFalse);
  m_page->parentDoc->doc->displayPage( &td, m_page->index + 1, 72, 72, rotation, false, true, false );
  TextPage *textPage=td.takeText();

  if (direction == FromTop)
    found = textPage->findText( u.data(), len, 
            gTrue, gTrue, gFalse, gFalse, sCase, gFalse, &sLeft, &sTop, &sRight, &sBottom );
  else if ( direction == NextResult )
    found = textPage->findText( u.data(), len, 
            gFalse, gTrue, gTrue, gFalse, sCase, gFalse, &sLeft, &sTop, &sRight, &sBottom );
  else if ( direction == PreviousResult )
    found = textPage->findText( u.data(), len, 
            gFalse, gTrue, gTrue, gFalse, sCase, gTrue, &sLeft, &sTop, &sRight, &sBottom );

  textPage->decRefCnt();

  rect.setLeft( sLeft );
  rect.setTop( sTop );
  rect.setRight( sRight );
  rect.setBottom( sBottom );

  return found;
}

QList<TextBox*> Page::textList(Rotation rotate) const
{
  TextOutputDev *output_dev;
  
  QList<TextBox*> output_list;
  
  output_dev = new TextOutputDev(0, gFalse, gFalse, gFalse);
  
  int rotation = (int)rotate * 90;

  m_page->parentDoc->doc->displayPageSlice(output_dev, m_page->index + 1, 72, 72,
      rotation, false, false, false, -1, -1, -1, -1);

  TextWordList *word_list = output_dev->makeWordList();
  
  if (!word_list) {
    delete output_dev;
    return output_list;
  }
  
  QHash<TextWord *, TextBox*> wordBoxMap;
  
  for (int i = 0; i < word_list->getLength(); i++) {
    TextWord *word = word_list->get(i);
    GooString *gooWord = word->getText();
    QString string = QString::fromUtf8(gooWord->getCString());
    delete gooWord;
    double xMin, yMin, xMax, yMax;
    word->getBBox(&xMin, &yMin, &xMax, &yMax);
    
    TextBox* text_box = new TextBox(string, QRectF(xMin, yMin, xMax-xMin, yMax-yMin));
    text_box->m_data->hasSpaceAfter = word->hasSpaceAfter() == gTrue;
    text_box->m_data->charBBoxes.reserve(word->getLength());
    for (int j = 0; j < word->getLength(); ++j)
    {
        word->getCharBBox(j, &xMin, &yMin, &xMax, &yMax);
        text_box->m_data->charBBoxes.append(QRectF(xMin, yMin, xMax-xMin, yMax-yMin));
    }
    
    wordBoxMap.insert(word, text_box);
    
    output_list.append(text_box);
  }
  
  for (int i = 0; i < word_list->getLength(); i++) {
    TextWord *word = word_list->get(i);
    TextBox* text_box = wordBoxMap.value(word);
    text_box->m_data->nextWord = wordBoxMap.value(word->nextWord());
  }
  
  delete word_list;
  delete output_dev;
  
  return output_list;
}

PageTransition *Page::transition() const
{
  if (!m_page->transition) {
    Object o;
    PageTransitionParams params;
    params.dictObj = m_page->page->getTrans(&o);
    if (params.dictObj->isDict()) m_page->transition = new PageTransition(params);
    o.free();
  }
  return m_page->transition;
}

Link *Page::action( PageAction act ) const
{
  if ( act == Page::Opening || act == Page::Closing )
  {
    Object o;
    m_page->page->getActions(&o);
    if (!o.isDict())
    {
      o.free();
      return 0;
    }
    Dict *dict = o.getDict();
    Object o2;
    const char *key = act == Page::Opening ? "O" : "C";
    dict->lookup((char*)key, &o2);
    ::LinkAction *lact = ::LinkAction::parseAction(&o2, m_page->parentDoc->doc->getCatalog()->getBaseURI() );
    o2.free();
    o.free();
    Link *popplerLink = NULL;
    if (lact != NULL)
    {
      popplerLink = m_page->convertLinkActionToLink(lact, QRectF());
      delete lact;
    }
    return popplerLink;
  }
  return 0;
}

QSizeF Page::pageSizeF() const
{
  Page::Orientation orient = orientation();
  if ( ( Page::Landscape == orient ) || (Page::Seascape == orient ) ) {
      return QSizeF( m_page->page->getCropHeight(), m_page->page->getCropWidth() );
  } else {
    return QSizeF( m_page->page->getCropWidth(), m_page->page->getCropHeight() );
  }
}

QSize Page::pageSize() const
{
  return pageSizeF().toSize();
}

Page::Orientation Page::orientation() const
{
  const int rotation = m_page->page->getRotate();
  switch (rotation) {
  case 90:
    return Page::Landscape;
    break;
  case 180:
    return Page::UpsideDown;
    break;
  case 270:
    return Page::Seascape;
    break;
  default:
    return Page::Portrait;
  }
}

void Page::defaultCTM(double *CTM, double dpiX, double dpiY, int rotate, bool upsideDown)
{
  m_page->page->getDefaultCTM(CTM, dpiX, dpiY, rotate, gFalse, upsideDown);
}

QList<Link*> Page::links() const
{
  LinkExtractorOutputDev link_dev(m_page);
  m_page->parentDoc->doc->processLinks(&link_dev, m_page->index + 1);
  QList<Link*> popplerLinks = link_dev.links();

  return popplerLinks;
}

QList<Annotation*> Page::annotations() const
{
    ::Page *pdfPage = m_page->page;
    Annots* annots = pdfPage->getAnnots(m_page->parentDoc->doc->getCatalog());
    const uint numAnnotations = annots->getNumAnnots();
    if ( numAnnotations == 0 )
    {
        delete annots;
        return QList<Annotation*>();
    }

    // ID to Annotation/PopupWindow maps
    QMap< int, Annotation * > annotationsMap;
    QHash< AnnotPopup *, PopupWindow * > popupsMap;
    // lists of Windows and Revisions that needs resolution
    QLinkedList< ResolveRevision > resolveRevList;
    QLinkedList< ResolveWindow > resolvePopList;
    QLinkedList< PostProcessText > ppTextList;

    // build a normalized transform matrix for this page at 100% scale
    GfxState * gfxState = new GfxState( 72.0, 72.0, pdfPage->getCropBox(), pdfPage->getRotate(), gTrue );
    double * gfxCTM = gfxState->getCTM();
    double MTX[6];
    for ( int i = 0; i < 6; i+=2 )
    {
        MTX[i] = gfxCTM[i] / pdfPage->getCropWidth();
        MTX[i+1] = gfxCTM[i+1] / pdfPage->getCropHeight();
    }
    delete gfxState;

    /** 1 - PARSE ALL ANNOTATIONS AND POPUPS FROM THE PAGE */
    for ( uint j = 0; j < numAnnotations; j++ )
    {
        // get the j-th annotation
        Annot * ann = annots->getAnnot( j );
        if ( !ann )
        {
            qDebug() << "Annot" << j << "is null.";
            continue;
        }

        Annotation * annotation = 0;
        int annotID = ann->getId();
        AnnotMarkup * markupann = dynamic_cast< AnnotMarkup * >( ann );
        bool addToPage = true;      // Popup annots are added to custom queue

        /** 1.1. GET Subtype */
        Annot::AnnotSubtype subType = ann->getType();

        /** 1.2. CREATE Annotation / PopupWindow and PARSE specific params */
        switch ( subType )
        {
            case Annot::typeText:
            {
                // parse TextAnnotation params
                AnnotText * textann = static_cast< AnnotText * >( ann );
                TextAnnotation * t = new TextAnnotation();
                annotation = t;
                // -> textType
                t->setTextType( TextAnnotation::Linked );
                // -> textIcon
                t->setTextIcon( QString::fromLatin1( textann->getIcon()->getCString() ) );
                // request for postprocessing window geometry
                PostProcessText request;
                request.textAnnotation = t;
                request.opened = textann->getOpen();
                ppTextList.append( request );
                break;
            }
            case Annot::typeFreeText:
            {
                // parse TextAnnotation params
                AnnotFreeText * textann = static_cast< AnnotFreeText * >( ann );
                TextAnnotation * t = new TextAnnotation();
                annotation = t;
                // -> textType
                t->setTextType( TextAnnotation::InPlace );
#if 0
                // -> textFont
                QString textFormat;
                XPDFReader::lookupString( annotDict, "DA", textFormat );
                // TODO, fill t->textFont using textFormat if not empty
#endif
                // -> inplaceAlign
                t->setInplaceAlign( textann->getQuadding() );
                // -> inplaceText (simple)
                QString tmpstring;
                GooString *styleString = textann->getStyleString();
                if ( styleString )
                    tmpstring = UnicodeParsedString( styleString );
#if 0
                // -> inplaceText (complex override)
                XPDFReader::lookupString( annotDict, "RC", tmpstring );
#endif
                t->setInplaceText( tmpstring );
                // -> inplaceCallout
                AnnotCalloutLine *callout = textann->getCalloutLine();
                if ( callout )
                {
                    QPointF tmppoint;
                    XPDFReader::transform( MTX, callout->getX1(), callout->getY1(), tmppoint );
                    t->setCalloutPoint( 0, tmppoint );
                    XPDFReader::transform( MTX, callout->getX2(), callout->getY2(), tmppoint );
                    t->setCalloutPoint( 1, tmppoint );
                    if ( AnnotCalloutMultiLine * callout_v6 = dynamic_cast< AnnotCalloutMultiLine * >( callout ) )
                    {
                        XPDFReader::transform( MTX, callout_v6->getX3(), callout_v6->getY3(), tmppoint );
                        t->setCalloutPoint( 2, tmppoint );
                    }
                }
                // -> inplaceIntent
                t->setInplaceIntent( (TextAnnotation::InplaceIntent)textann->getIntent() );
                AnnotBorderEffect *border_effect = textann->getBorderEffect();
                if ( border_effect )
                {
                    // -> style.effect
                    t->style.effect = (Annotation::LineEffect)border_effect->getEffectType();
                    // -> style.effectIntensity
                    t->style.effectIntensity = (int)border_effect->getIntensity();
                }
                break;
            }
            case Annot::typeLine:
            {
                // parse LineAnnotation params
                AnnotLine * lineann = static_cast< AnnotLine * >( ann );
                LineAnnotation * l = new LineAnnotation();
                annotation = l;

                // -> linePoints
                QLinkedList<QPointF> linePoints;
                QPointF p;
                XPDFReader::transform( MTX, lineann->getX1(), lineann->getY1(), p );
                linePoints.push_back( p );
                XPDFReader::transform( MTX, lineann->getX2(), lineann->getY2(), p );
                linePoints.push_back( p );
                l->setLinePoints( linePoints );
                // -> lineStartStyle
                l->setLineStartStyle( (LineAnnotation::TermStyle)lineann->getStartStyle() );
                // -> lineEndStyle
                l->setLineEndStyle( (LineAnnotation::TermStyle)lineann->getEndStyle() );
                // -> lineClosed
                l->setLineClosed( false );
                // -> lineInnerColor
                l->setLineInnerColor( convertAnnotColor( lineann->getInteriorColor() ) );
                // -> lineLeadingFwdPt
                l->setLineLeadingForwardPoint( lineann->getLeaderLineLength() );
                // -> lineLeadingBackPt
                l->setLineLeadingBackPoint( lineann->getLeaderLineExtension() );
                // -> lineShowCaption
                l->setLineShowCaption( lineann->getCaption() );
                // -> lineIntent
                l->setLineIntent( (LineAnnotation::LineIntent)( lineann->getIntent() + 1 ) );
                break;
            }
            case Annot::typePolygon:
            case Annot::typePolyLine:
            {
                // parse LineAnnotation params
                AnnotPolygon * polyann = static_cast< AnnotPolygon * >( ann );
                LineAnnotation * l = new LineAnnotation();
                annotation = l;

                // -> polyPoints
                QLinkedList<QPointF> polyPoints;
                AnnotPath * vertices = polyann->getVertices();
                for ( int i = 0; i < vertices->getCoordsLength(); ++i )
                {
                    QPointF p;
                    XPDFReader::transform( MTX, vertices->getX( i ), vertices->getY( i ), p );
                    polyPoints.push_back( p );
                }
                l->setLinePoints( polyPoints );
                // -> polyStartStyle
                l->setLineStartStyle( (LineAnnotation::TermStyle)polyann->getStartStyle() );
                // -> polyEndStyle
                l->setLineEndStyle( (LineAnnotation::TermStyle)polyann->getEndStyle() );
                // -> polyClosed
                l->setLineClosed( subType == Annot::typePolygon );
                // -> polyInnerColor
                l->setLineInnerColor( convertAnnotColor( polyann->getInteriorColor() ) );
                // -> polyIntent
                switch ( polyann->getIntent() )
                {
                    case AnnotPolygon::polygonCloud:
                        l->setLineIntent( LineAnnotation::PolygonCloud );
                        break;
                    case AnnotPolygon::polylineDimension:
                    case AnnotPolygon::polygonDimension:
                        l->setLineIntent( LineAnnotation::Dimension );
                        break;
                }
                break;
            }
            case Annot::typeSquare:
            case Annot::typeCircle:
            {
                // parse GeomAnnotation params
                AnnotGeometry * geomann = static_cast< AnnotGeometry * >( ann );
                GeomAnnotation * g = new GeomAnnotation();
                annotation = g;

                // -> highlightType
                if ( subType == Annot::typeSquare )
                    g->setGeomType( GeomAnnotation::InscribedSquare );
                else if ( subType == Annot::typeCircle )
                    g->setGeomType( GeomAnnotation::InscribedCircle );

                // -> geomInnerColor
                g->setGeomInnerColor( convertAnnotColor( geomann->getInteriorColor() ) );

                AnnotBorderEffect *border_effect = geomann->getBorderEffect();
                if ( border_effect )
                {
                    // -> style.effect
                    g->style.effect = (Annotation::LineEffect)border_effect->getEffectType();
                    // -> style.effectIntensity
                    g->style.effectIntensity = (int)border_effect->getIntensity();
                }

                // TODO RD

                break;
            }
            case Annot::typeHighlight:
            case Annot::typeUnderline:
            case Annot::typeSquiggly:
            case Annot::typeStrikeOut:
            {
                AnnotTextMarkup * hlann = static_cast< AnnotTextMarkup * >( ann );
                HighlightAnnotation * h = new HighlightAnnotation();
                annotation = h;

                // -> highlightType
                if ( subType == Annot::typeHighlight )
                    h->setHighlightType( HighlightAnnotation::Highlight );
                else if ( subType == Annot::typeUnderline )
                    h->setHighlightType( HighlightAnnotation::Underline );
                else if ( subType == Annot::typeSquiggly )
                    h->setHighlightType( HighlightAnnotation::Squiggly );
                else if ( subType == Annot::typeStrikeOut )
                    h->setHighlightType( HighlightAnnotation::StrikeOut );

                // -> highlightQuads
                AnnotQuadrilaterals *hlquads = hlann->getQuadrilaterals();
                if ( !hlquads || !hlquads->getQuadrilateralsLength() )
                {
                    qDebug() << "Not enough quads for a Highlight annotation.";
                    delete annotation;
                    continue;
                }
                QList< HighlightAnnotation::Quad > quads;
                const int quadsCount = hlquads->getQuadrilateralsLength();
                for ( int q = 0; q < quadsCount; ++q )
                {
                    HighlightAnnotation::Quad quad;
                    XPDFReader::transform( MTX, hlquads->getX1( q ), hlquads->getY1( q ), quad.points[ 0 ] );
                    XPDFReader::transform( MTX, hlquads->getX2( q ), hlquads->getY2( q ), quad.points[ 1 ] );
                    XPDFReader::transform( MTX, hlquads->getX3( q ), hlquads->getY3( q ), quad.points[ 2 ] );
                    XPDFReader::transform( MTX, hlquads->getX4( q ), hlquads->getY4( q ), quad.points[ 3 ] );
                    // ### PDF1.6 specs says that point are in ccw order, but in fact
                    // points 3 and 4 are swapped in every PDF around!
                    QPointF tmpPoint = quad.points[ 2 ];
                    quad.points[ 2 ] = quad.points[ 3 ];
                    quad.points[ 3 ] = tmpPoint;
                    // initialize other properties and append quad
                    quad.capStart = true;       // unlinked quads are always capped
                    quad.capEnd = true;         // unlinked quads are always capped
                    quad.feather = 0.1;         // default feather
                    quads.append( quad );
                }
                h->setHighlightQuads( quads );
                break;
            }
            case Annot::typeStamp:
            {
                AnnotStamp * stampann = static_cast< AnnotStamp * >( ann );
                StampAnnotation * s = new StampAnnotation();
                annotation = s;
                // -> stampIcon
                s->setStampIconName( QString::fromLatin1( stampann->getIcon()->getCString() ) );
                break;
            }
            case Annot::typeInk:
            {
                // parse InkAnnotation params
                AnnotInk * inkann = static_cast< AnnotInk * >( ann );
                InkAnnotation * k = new InkAnnotation();
                annotation = k;

                // -> inkPaths
                AnnotPath ** paths = inkann->getInkList();
                if ( !paths || !inkann->getInkListLength() )
                {
                    qDebug() << "InkList not present for ink annot";
                    delete annotation;
                    continue;
                }
                QList< QLinkedList<QPointF> > inkPaths;
                const int pathsNumber = inkann->getInkListLength();
                for ( int m = 0; m < pathsNumber; m++ )
                {
                    // transform each path in a list of normalized points ..
                    QLinkedList<QPointF> localList;
                    AnnotPath * path = paths[ m ];
                    const int pointsNumber = path ? path->getCoordsLength() : 0;
                    for ( int n = 0; n < pointsNumber; ++n )
                    {
                        // get the x,y numbers for current point
                        double x = path->getX( n );
                        double y = path->getY( n );
                        // add normalized point to localList
                        QPointF np;
                        XPDFReader::transform( MTX, x, y, np );
                        localList.push_back( np );
                    }
                    // ..and add it to the annotation
                    inkPaths.push_back( localList );
                }
                k->setInkPaths( inkPaths );
                break;
            }
            case Annot::typePopup:
            {
                AnnotPopup * popupann = static_cast< AnnotPopup * >( ann );

                // create PopupWindow and add it to the popupsMap
                PopupWindow * popup = new PopupWindow();
                popupsMap[ popupann ] = popup;
                addToPage = false;

                // get window specific properties if any
                popup->shown = popupann->getOpen();
                // no need to parse parent annotation id
                //XPDFReader::lookupIntRef( annotDict, "Parent", popup->... );

                // use the 'dummy annotation' for getting other parameters
                popup->dummyAnnotation = new DummyAnnotation();
                annotation = popup->dummyAnnotation;

                break;
            }
            case Annot::typeLink:
            {
                // parse Link params
                AnnotLink * linkann = static_cast< AnnotLink * >( ann );
                LinkAnnotation * l = new LinkAnnotation();
                annotation = l;

                // -> hlMode
                l->setLinkHighlightMode( (LinkAnnotation::HighlightMode)linkann->getLinkEffect() );

                // -> link region
                // TODO

                // reading link action
                if ( !linkann->getDest()->isNull() )
                {
                    ::LinkAction *act = ::LinkAction::parseDest( linkann->getDest() );
                    Link * popplerLink = m_page->convertLinkActionToLink( act, QRectF() );
                    delete act;
                    if ( popplerLink )
                    {
                        l->setLinkDestination( popplerLink );
                    }
                }

                break;
            }
            case Annot::typeCaret:
            {
                // parse CaretAnnotation params
                AnnotCaret * caretann = static_cast< AnnotCaret * >( ann );
                CaretAnnotation * c = new CaretAnnotation();
                annotation = c;

                // -> caretSymbol
                c->setCaretSymbol( (CaretAnnotation::CaretSymbol)caretann->getSymbol() );

                // TODO RD

                break;
            }
            case Annot::typeFileAttachment:
            {
                AnnotFileAttachment * attachann = static_cast< AnnotFileAttachment * >( ann );
                FileAttachmentAnnotation * f = new FileAttachmentAnnotation();
                annotation = f;
                // -> fileIcon
                f->setFileIconName( QString::fromLatin1( attachann->getName()->getCString() ) );
                // -> embeddedFile
                EmbFile *embfile = new EmbFile( attachann->getFile(), attachann->getContents() );
                f->setEmbeddedFile( new EmbeddedFile( embfile ) );
                break;
            }
            case Annot::typeSound:
            {
                AnnotSound * soundann = static_cast< AnnotSound * >( ann );
                SoundAnnotation * s = new SoundAnnotation();
                annotation = s;

                // -> soundIcon
                s->setSoundIconName( QString::fromLatin1( soundann->getName()->getCString() ) );
                // -> sound
                s->setSound( new SoundObject( soundann->getSound() ) );

                break;
            }
            case Annot::typeMovie:
            {
                AnnotMovie * movieann = static_cast< AnnotMovie * >( ann );
                MovieAnnotation * m = new MovieAnnotation();
                annotation = m;

                // -> movie
                MovieObject *movie = new MovieObject( movieann );
                m->setMovie( movie );
                // -> movieTitle
                GooString * movietitle = movieann->getTitle();
                if ( movietitle )
                {
                    m->setMovieTitle( QString::fromLatin1( movietitle->getCString() ) );
                }

                break;
            }
            // special case for ignoring unknwon annotations
            case Annot::typeUnknown:
                continue;
            default:
            {
#define CASE_FOR_TYPE( thetype ) \
                    case Annot::type ## thetype: \
                        type = #thetype ; \
                        break;
                QByteArray type;
                switch ( subType )
                {
                    CASE_FOR_TYPE( Widget )
                    CASE_FOR_TYPE( Screen )
                    CASE_FOR_TYPE( PrinterMark )
                    CASE_FOR_TYPE( TrapNet )
                    CASE_FOR_TYPE( Watermark )
                    CASE_FOR_TYPE( 3D )
                    default: type = QByteArray::number( subType );
                }
                // MISSING: Widget, Screen, PrinterMark, TrapNet, Watermark, 3D
                qDebug() << "Annotation" << type.constData() << "not supported.";
                continue;
#undef CASE_FOR_TYPE
            }
        }

        /** 1.3. PARSE common parameters */
        // -> boundary
        PDFRectangle *boundary = ann->getRect();
        // transform annotation rect to uniform coords
        QPointF topLeft, bottomRight;
        XPDFReader::transform( MTX, boundary->x1, boundary->y1, topLeft );
        XPDFReader::transform( MTX, boundary->x2, boundary->y2, bottomRight );
        QRectF boundaryRect;
        boundaryRect.setTopLeft(topLeft);
        boundaryRect.setBottomRight(bottomRight);
        if ( boundaryRect.left() > boundaryRect.right() )
        {
            double aux = boundaryRect.left();
            boundaryRect.setLeft( boundaryRect.right() );
            boundaryRect.setRight(aux);
        }
        if ( boundaryRect.top() > boundaryRect.bottom() )
        {
            double aux = boundaryRect.top();
            boundaryRect.setTop( boundaryRect.bottom() );
            boundaryRect.setBottom(aux);
           //annotation->rUnscaledWidth = (r[2] > r[0]) ? r[2] - r[0] : r[0] - r[2];
           //annotation->rUnscaledHeight = (r[3] > r[1]) ? r[3] - r[1] : r[1] - r[3];
        }
        annotation->setBoundary( boundaryRect );
        // -> contents
        annotation->setContents( UnicodeParsedString( ann->getContents() ) );
        // -> uniqueName
        annotation->setUniqueName( UnicodeParsedString( ann->getName() ) );
        // -> modifyDate (and -> creationDate)
        GooString *modDate = ann->getModified();
        if ( modDate )
        {
            annotation->setModificationDate( convertDate( modDate->getCString() ) );
        }
        if ( annotation->creationDate().isNull() && !annotation->modificationDate().isNull() )
            annotation->setCreationDate( annotation->modificationDate() );
        // -> flags: set the external attribute since it's embedded on file
        int annoflags = 0;
        annoflags |= Annotation::External;
        // -> flags
        int flags = ann->getFlags();
        if ( flags & Annot::flagHidden )
            annoflags |= Annotation::Hidden;
        if ( flags & Annot::flagNoZoom )
            annoflags |= Annotation::FixedSize;
        if ( flags & Annot::flagNoRotate )
            annoflags |= Annotation::FixedRotation;
        if ( !( flags & Annot::flagPrint ) )
            annoflags |= Annotation::DenyPrint;
        if ( flags & Annot::flagReadOnly )
            annoflags |= (Annotation::DenyWrite | Annotation::DenyDelete);
        if ( flags & Annot::flagLocked )
            annoflags |= Annotation::DenyDelete;
        if ( flags & Annot::flagToggleNoView )
            annoflags |= Annotation::ToggleHidingOnMouse;
        annotation->setFlags( annoflags );
        // -> style
        AnnotBorder *border = ann->getBorder();
        if ( border )
        {
            if ( border->getType() == AnnotBorder::typeArray )
            {
                AnnotBorderArray * border_array = static_cast< AnnotBorderArray * >( border );
                // -> style.xCorners
                annotation->style.xCorners = border_array->getHorizontalCorner();
                // -> style.yCorners
                annotation->style.yCorners = border_array->getVerticalCorner();
            }
            // -> style.width
            annotation->style.width = border->getWidth();
            // -> style.style
            annotation->style.style = (Annotation::LineStyle)( 1 << border->getStyle() );
#if 0
            // -> style.marks and style.spaces
            // TODO
            Object dashArray;
            bsObj.getDict()->lookup( "D", &dashArray );
            if ( dashArray.isArray() )
            {
                int dashMarks = 3;
                int dashSpaces = 0;
                Object intObj;
                dashArray.arrayGet( 0, &intObj );
                if ( intObj.isInt() )
                    dashMarks = intObj.getInt();
                intObj.free();
                dashArray.arrayGet( 1, &intObj );
                if ( intObj.isInt() )
                    dashSpaces = intObj.getInt();
                intObj.free();
                annotation->style.marks = dashMarks;
                annotation->style.spaces = dashSpaces;
            }
#endif
        }
        // -> style.color
        annotation->style.color = convertAnnotColor( ann->getColor() );

        /** 1.4. PARSE markup { common, Popup, Revision } parameters */
        if ( markupann )
        {
            // -> creationDate
            GooString *createDate = markupann->getDate();
            if ( createDate )
            {
                annotation->setCreationDate( convertDate( createDate->getCString() ) );
            }
            // -> style.opacity
            annotation->style.opacity = markupann->getOpacity();
            // -> window.title and author
            annotation->window.title = UnicodeParsedString( markupann->getLabel() );
            annotation->setAuthor( annotation->window.title );
            // -> window.summary
            annotation->window.summary = UnicodeParsedString( markupann->getSubject() );
#if 0
            // -> window.text
            // TODO
            XPDFReader::lookupString( annotDict, "RC", annotation->window.text );
#endif

            // if a popup is referenced, schedule for resolving it later
            AnnotPopup *popup = markupann->getPopup();
            if ( popup )
            {
                ResolveWindow request;
                request.popup = popup;
                request.annotation = annotation;
                resolvePopList.append( request );
            }

            // if an older version is referenced, schedule for reparenting
            int parentID = markupann->getInReplyToID();
            if ( parentID )
            {
                ResolveRevision request;
                request.nextAnnotation = annotation;
                request.nextAnnotationID = annotID;
                request.prevAnnotationID = parentID;

                // -> request.nextScope
                request.nextScope = Annotation::Reply;
                switch ( markupann->getReplyTo() )
                {
                    case AnnotMarkup::replyTypeR:
                        request.nextScope = Annotation::Reply;
                        break;
                    case AnnotMarkup::replyTypeGroup:
                        request.nextScope = Annotation::Group;
                        break;
                }

                // -> revision.type (StateModel is deduced from type, not parsed)
                request.nextType = Annotation::None;
                if ( subType == Annot::typeText )
                {
                    AnnotText * textann = static_cast< AnnotText * >( ann );
                    switch ( textann->getState() )
                    {
                        case AnnotText::stateMarked:
                            request.nextType = Annotation::Marked;
                            break;
                        case AnnotText::stateUnmarked:
                            request.nextType = Annotation::Unmarked;
                            break;
                        case AnnotText::stateAccepted:
                            request.nextType = Annotation::Accepted;
                            break;
                        case AnnotText::stateRejected:
                            request.nextType = Annotation::Rejected;
                            break;
                        case AnnotText::stateCancelled:
                            request.nextType = Annotation::Cancelled;
                            break;
                        case AnnotText::stateCompleted:
                            request.nextType = Annotation::Completed;
                            break;
                        case AnnotText::stateNone:
                        case AnnotText::stateUnknown:
                            ;
                    }
                }

                // schedule for later reparenting
                resolveRevList.append( request );
            }
        }

        /** 1.5. ADD ANNOTATION to the annotationsMap  */
        if ( addToPage )
        {
            if ( annotationsMap.contains( annotID ) )
                qDebug() << "Clash for annotations with ID:" << annotID;
            annotationsMap[ annotID ] = annotation;
        }
    } // end Annotation/PopupWindow parsing loop

    /** 2 - RESOLVE POPUPS (popup.* -> annotation.window) */
    if ( !resolvePopList.isEmpty() && !popupsMap.isEmpty() )
    {
        QLinkedList< ResolveWindow >::iterator it = resolvePopList.begin(),
                                              end = resolvePopList.end();
        for ( ; it != end; ++it )
        {
            const ResolveWindow & request = *it;
            if ( !popupsMap.contains( request.popup ) )
                // warn aboud problems in popup resolving logic
                qDebug() << "Cannot resolve popup"
                          << request.popup << ".";
            else
            {
                // set annotation's window properties taking ones from popup
                PopupWindow * pop = popupsMap[ request.popup ];
                Annotation * pa = pop->dummyAnnotation;
                Annotation::Window & w = request.annotation->window;

                // transfer properties to Annotation's window
                w.flags = pa->flags() & (Annotation::Hidden |
                    Annotation::FixedSize | Annotation::FixedRotation);
                if ( !pop->shown )
                    w.flags |= Annotation::Hidden;
                w.topLeft.setX(pa->boundary().left());
                w.topLeft.setY(pa->boundary().top());
                w.width = (int)( pa->boundary().right() - pa->boundary().left() );
                w.height = (int)( pa->boundary().bottom() - pa->boundary().top() );
            }
        }

        // clear data
        QHash< AnnotPopup *, PopupWindow * >::Iterator dIt = popupsMap.begin(), dEnd = popupsMap.end();
        for ( ; dIt != dEnd; ++dIt )
        {
            PopupWindow * p = dIt.value();
            delete p->dummyAnnotation;
            delete p;
        }
    }

    /** 3 - RESOLVE REVISIONS (parent.revisions.append( children )) */
    if ( !resolveRevList.isEmpty() )
    {
        // append children to parents
        QVarLengthArray< int > excludeIDs( resolveRevList.count() );   // can't even reach this size
        int excludeIndex = 0;                       // index in excludeIDs array
        QLinkedList< ResolveRevision >::iterator it = resolveRevList.begin(), end = resolveRevList.end();
        for ( ; it != end; ++it )
        {
            const ResolveRevision & request = *it;
            int parentID = request.prevAnnotationID;
            if ( !annotationsMap.contains( parentID ) )
                // warn about problems in reparenting logic
                qDebug() << "Cannot reparent annotation to"
                          << parentID << ".";
            else
            {
                // compile and add a Revision structure to the parent annotation
                Annotation::Revision childRevision;
                childRevision.annotation = request.nextAnnotation;
                childRevision.scope = request.nextScope;
                childRevision.type = request.nextType;
                annotationsMap[ parentID ]->revisions().append( childRevision );
                // exclude child annotation from being rooted in page
                excludeIDs[ excludeIndex++ ] = request.nextAnnotationID;
            }
        }

        // prevent children from being attached to page as roots
        for ( int i = 0; i < excludeIndex; i++ )
            annotationsMap.remove( excludeIDs[ i ] );
    }

    /** 4 - POSTPROCESS TextAnnotations (when window geom is embedded) */
    if ( !ppTextList.isEmpty() )
    {
        QLinkedList< PostProcessText >::const_iterator it = ppTextList.begin(), end = ppTextList.end();
        for ( ; it != end; ++it )
        {
            const PostProcessText & request = *it;
            Annotation::Window & window = request.textAnnotation->window;
            // if not present, 'create' the window in-place over the annotation
            if ( window.flags == -1 )
            {
                window.flags = 0;
                QRectF geom = request.textAnnotation->boundary();
                // initialize window geometry to annotation's one
                window.width = (int)( geom.right() - geom.left() );
                window.height = (int)( geom.bottom() - geom.top() );
                window.topLeft.setX( geom.left() > 0.0 ? geom.left() : 0.0 );
                window.topLeft.setY( geom.top() > 0.0 ? geom.top() : 0.0 );
            }
            // (pdf) if text is not 'opened', force window hiding. if the window
            // was parsed from popup, the flag should already be set
            if ( !request.opened && window.flags != -1 )
                window.flags |= Annotation::Hidden;
        }
    }

    delete annots;
    /** 5 - finally RETURN ANNOTATIONS */
    return annotationsMap.values();
}

QList<FormField*> Page::formFields() const
{
  QList<FormField*> fields;
  ::Page *p = m_page->page;
  ::FormPageWidgets * form = p->getPageWidgets();
  int formcount = form->getNumWidgets();
  for (int i = 0; i < formcount; ++i)
  {
    ::FormWidget *fm = form->getWidget(i);
    FormField * ff = NULL;
    switch (fm->getType())
    {
      case formButton:
      {
        ff = new FormFieldButton(m_page->parentDoc, p, static_cast<FormWidgetButton*>(fm));
      }
      break;

      case formText:
      {
        ff = new FormFieldText(m_page->parentDoc, p, static_cast<FormWidgetText*>(fm));
      }
      break;

      case formChoice:
      {
        ff = new FormFieldChoice(m_page->parentDoc, p, static_cast<FormWidgetChoice*>(fm));
      }
      break;

      default: ;
    }

    if (ff)
      fields.append(ff);
  }

  return fields;
}

double Page::duration() const
{
  return m_page->page->getDuration();
}

QString Page::label() const
{
  GooString goo;
  if (!m_page->parentDoc->doc->getCatalog()->indexToLabel(m_page->index, &goo))
    return QString();

  return QString(goo.getCString());
}


}
