// This file is part of Extract PDFmark.
//
// Copyright (C) 2016, 2018 Masamichi Hosoda
//
// Extract PDFmark 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 3 of the License, or
// (at your option) any later version.
//
// Extract PDFmark 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 Extract PDFmark. If not, see <
http://www.gnu.org/licenses/>.
#include "config.h"
#include "poppler-core.hh"
#include <iostream>
#include <map>
#include <sstream>
#include <string>
#include <Link.h>
#include <PDFDoc.h>
#ifndef HAVE_POPPLER_CORE_IF
#include "destname-private.hh"
#endif
inline std::string goo_to_string (GooString *goo)
{
return std::string {
#ifdef HAS_GOOSTRING_C_STR
goo->c_str (),
#else
goo->getCString (),
#endif
static_cast<std::string::size_type>(goo->getLength ())};
}
inline void poppler_core::add_destname (GooString *name,
LinkDest *link_dest)
{
std::string str = goo_to_string (name);
add_destname (str, link_dest);
}
inline void poppler_core::add_destname (GooString *name)
{
std::string str = goo_to_string (name);
std::unique_ptr<LinkDest> link_dest {doc->findDest (name)};
add_destname (str, link_dest.get ());
}
inline void poppler_core::add_destname (const char *name)
{
GooString goo {name};
std::unique_ptr<LinkDest> link_dest {doc->findDest (&goo)};
add_destname (name, link_dest.get ());
}
inline void poppler_core::add_destname (const std::string &name,
LinkDest *link_dest)
{
if (link_dest)
{
name_map.insert (std::make_pair (name, *link_dest));
}
}
std::string poppler_core::build_destname (const std::string &name,
LinkDest *link_dest)
{
std::stringstream ss;
if (link_dest)
{
int pagenum;
if (link_dest->isPageRef ())
{
Ref page_ref = link_dest->getPageRef ();
pagenum = doc->findPage (page_ref.num, page_ref.gen);
}
else
{
pagenum = link_dest->getPageNum ();
}
switch (link_dest->getKind ())
{
case destXYZ:
ss
<< "[ /Dest " << encode_name (name)
<< " /Page " << pagenum
<< " /View [/XYZ " << link_dest->getLeft ()
<< " " << link_dest->getTop ()
<< " " << link_dest->getZoom ()
<< "] /DEST pdfmark" << std::endl;
break;
case destFit:
ss
<< "[ /Dest " << encode_name (name)
<< " /Page " << pagenum
<< " /View [/Fit] /DEST pdfmark" << std::endl;
break;
case destFitH:
ss
<< "[ /Dest " << encode_name (name)
<< " /Page " << pagenum
<< " /View [/FitH " << link_dest->getTop ()
<< "] /DEST pdfmark" << std::endl;
break;
case destFitV:
ss
<< "[ /Dest " << encode_name (name)
<< " /Page " << pagenum
<< " /View [/FitV " << link_dest->getLeft ()
<< "] /DEST pdfmark" << std::endl;
break;
case destFitR:
ss
<< "[ /Dest " << encode_name (name)
<< " /Page " << pagenum
<< " /View [/FitR " << link_dest->getLeft ()
<< " " << link_dest->getBottom ()
<< " " << link_dest->getRight ()
<< " " << link_dest->getTop ()
<< "] /DEST pdfmark" << std::endl;
break;
case destFitB:
ss
<< "[ /Dest " << encode_name (name)
<< " /Page " << pagenum
<< " /View [/FitB] /DEST pdfmark" << std::endl;
break;
case destFitBH:
ss
<< "[ /Dest " << encode_name (name)
<< " /Page " << pagenum
<< " /View [/FitBH " << link_dest->getTop ()
<< "] /DEST pdfmark" << std::endl;
break;
case destFitBV:
ss
<< "[ /Dest " << encode_name (name)
<< " /Page " << pagenum
<< " /View [/FitBV " << link_dest->getLeft ()
<< "] /DEST pdfmark" << std::endl;
break;
default:
ss << "% link_dest kind is unknown." << std::endl;
break;
}
}
else
{
ss << "% link_dest is null." << std::endl;
}
return ss.str ();
}
std::string poppler_core::build_destnames (void)
{
std::string str;
for (auto &elm: name_map)
{
str += build_destname (elm.first, &elm.second);
}
return str;
}
#ifdef HAVE_POPPLER_CORE_IF
// Use poppler-core interface
std::string poppler_core::destname (void)
{
Catalog *catalog = doc->getCatalog ();
name_map.clear ();
if (catalog && catalog->isOk ())
{
int len = catalog->numDestNameTree ();
for (int i=0; i<len; ++i)
{
add_destname (catalog->getDestNameTreeName (i),
catalog->getDestNameTreeDest (i));
}
len = catalog->numDests ();
for (int i=0; i<len; ++i)
{
add_destname (catalog->getDestsName (i),
catalog->getDestsDest (i));
}
}
else
std::cerr << "Catalog is not OK" << std::endl;
return build_destnames ();
}
#else // HAVE_POPPLER_CORE_IF
// Use poppler-core private access
std::string poppler_core::destname (void)
{
Catalog *catalog = doc->getCatalog ();
name_map.clear ();
if (catalog && catalog->isOk ())
{
NameTree *destnametree = get_destnametree (catalog);
if (destnametree)
{
int len = destnametree->numEntries ();
for (int i=0; i<len; ++i)
{
add_destname (destnametree->getName (i));
}
}
Object *obj = catalog->getDests ();
if (obj && obj->isDict ())
{
int len = obj->dictGetLength ();
for (int i=0; i<len; ++i)
{
add_destname (obj->dictGetKey (i));
}
}
}
else
std::cerr << "Catalog is not OK" << std::endl;
return build_destnames ();
}
#endif // HAVE_POPPLER_CORE_IF