/* 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-2008, Albert Astals Cid <aacid@kde.org>
 * Copyright (C) 2005, Stefan Kebekus <stefan.kebekus@math.uni-koeln.de>
 * Copyright (C) 2006-2008, Pino Toscano <pino@kde.org>
 *
 * 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/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>
#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;
      // create link: no ext file, namedDest, object pointer
      popplerLink = new LinkGoto( linkArea, QString::null, LinkDestination( LinkDestinationData(g->getDest(), g->getNamedDest(), parentDoc ) ) );
    }
    break;

    case actionGoToR:
    {
      LinkGoToR * g = (LinkGoToR *) a;
      // copy link file
      const char * fileName = g->getFileName()->getCString();
      // ceate link: fileName, namedDest, object pointer
      popplerLink = new LinkGoto( linkArea, (QString)fileName, LinkDestination( LinkDestinationData(g->getDest(), g->getNamedDest(), parentDoc ) ) );
    }
    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;
}

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, 
            gTrue, gFalse, gFalse, gTrue, sCase, gFalse, &sLeft, &sTop, &sRight, &sBottom );

  delete textPage;

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


}
