pdf2htmlEX/pdf2htmlEX/src/HTMLRenderer/link.cc

320 lines
8.8 KiB
C++
Raw Normal View History

2012-09-25 11:29:59 +00:00
/*
* link.cc
*
* Handling links
*
* by WangLu
* 2012.09.25
*/
#include <iostream>
#include <sstream>
#include <algorithm>
#include <Link.h>
2012-11-29 09:28:05 +00:00
#include "HTMLRenderer.h"
#include "util/namespace.h"
2012-11-29 10:16:05 +00:00
#include "util/math.h"
2012-11-29 10:28:07 +00:00
#include "util/misc.h"
2013-02-15 05:07:00 +00:00
#include "util/encoding.h"
2013-02-27 18:52:00 +00:00
#include "util/css_const.h"
2012-09-25 11:29:59 +00:00
namespace pdf2htmlEX {
using std::ostringstream;
using std::min;
using std::max;
2012-11-29 10:28:07 +00:00
using std::cerr;
using std::endl;
2012-09-25 11:29:59 +00:00
/*
* The detailed rectangle area of the link destination
* Will be parsed and performed by Javascript
2013-01-28 13:01:02 +00:00
* The string will be put into a HTML attribute, surrounded by single quotes
* So pay attention to the characters used here
2012-09-25 11:29:59 +00:00
*/
static string get_linkdest_detail_str(
LinkDest * dest, // borrow the caller's std::unique_ptr
Catalog * catalog,
int & pageno
)
2012-09-25 11:29:59 +00:00
{
2013-01-28 10:31:02 +00:00
pageno = 0;
if(dest->isPageRef())
{
auto pageref = dest->getPageRef();
pageno = catalog->findPage(pageref);
2013-01-28 10:31:02 +00:00
}
else
{
pageno = dest->getPageNum();
}
if(pageno <= 0)
{
return "";
}
2012-09-25 11:29:59 +00:00
ostringstream sout;
// dec
sout << "[" << pageno;
New master (#2) * Show header in font map files * fix a usage of unique_ptr with array * Added '--quiet' argument to hide progress messages (resolves #503) * Revert cout messages to cerr (see #622) * bump version * fix build; fix some coverity warnings * Many bug fixes and improvements, including: - Incorporated latest Cairo files from cairo-0.15.2 - Moved build to out-of-source - Added clean script - Rewritten correct_text_visibility option to improve accuracy - Transparent characters drawn on background layer - Improved bad unicode detection * Many bug fixes and improvements, including: - Incorporated latest Cairo files from cairo-0.15.2 - Moved build to out-of-source - Added clean script - Rewritten correct_text_visibility option to improve accuracy - Transparent characters drawn on background layer - Improved bad unicode detection * Rationlise DPI to single number. Implement actual_dpi - clamp maximum background image size in cases of huge PDF pages * DPI fixes - increase DPI when partially covered text to covered-text-dpi Add font-style italic for oblique fonts Reduce char bbox for occlusion tests * Don't shrink bbox - not required if zoom=25 used * Ignore occlusion from stroke/fill with opacity < 0.5 Better compute char bbox for occlusion Use 10% inset for char bbox for occlusion Back out adding font-weight: bold to potentially bold fonts Fix bug to ensure CID ascent/descent matches subfont values * Removed zero char logging * Remove forced italic - missing italic is due to fontforge bug which needs fixing * Typos fixed, readme updated * Typos * Increase maximum background image width Fix private use range to avoid stupid mobile safari switching to emoji font * included -pthread switch to link included 3rdparty poppler files. * Updated files from poppler 0.59.0 and adjusted includes. * Support updated "Object" class from poppler 0.59.0
2018-01-10 19:31:38 +00:00
switch(dest->getKind())
2012-09-25 11:29:59 +00:00
{
New master (#2) * Show header in font map files * fix a usage of unique_ptr with array * Added '--quiet' argument to hide progress messages (resolves #503) * Revert cout messages to cerr (see #622) * bump version * fix build; fix some coverity warnings * Many bug fixes and improvements, including: - Incorporated latest Cairo files from cairo-0.15.2 - Moved build to out-of-source - Added clean script - Rewritten correct_text_visibility option to improve accuracy - Transparent characters drawn on background layer - Improved bad unicode detection * Many bug fixes and improvements, including: - Incorporated latest Cairo files from cairo-0.15.2 - Moved build to out-of-source - Added clean script - Rewritten correct_text_visibility option to improve accuracy - Transparent characters drawn on background layer - Improved bad unicode detection * Rationlise DPI to single number. Implement actual_dpi - clamp maximum background image size in cases of huge PDF pages * DPI fixes - increase DPI when partially covered text to covered-text-dpi Add font-style italic for oblique fonts Reduce char bbox for occlusion tests * Don't shrink bbox - not required if zoom=25 used * Ignore occlusion from stroke/fill with opacity < 0.5 Better compute char bbox for occlusion Use 10% inset for char bbox for occlusion Back out adding font-weight: bold to potentially bold fonts Fix bug to ensure CID ascent/descent matches subfont values * Removed zero char logging * Remove forced italic - missing italic is due to fontforge bug which needs fixing * Typos fixed, readme updated * Typos * Increase maximum background image width Fix private use range to avoid stupid mobile safari switching to emoji font * included -pthread switch to link included 3rdparty poppler files. * Updated files from poppler 0.59.0 and adjusted includes. * Support updated "Object" class from poppler 0.59.0
2018-01-10 19:31:38 +00:00
case destXYZ:
{
sout << ",\"XYZ\",";
2012-09-25 11:29:59 +00:00
if(dest->getChangeLeft())
sout << (dest->getLeft());
else
sout << "null";
New master (#2) * Show header in font map files * fix a usage of unique_ptr with array * Added '--quiet' argument to hide progress messages (resolves #503) * Revert cout messages to cerr (see #622) * bump version * fix build; fix some coverity warnings * Many bug fixes and improvements, including: - Incorporated latest Cairo files from cairo-0.15.2 - Moved build to out-of-source - Added clean script - Rewritten correct_text_visibility option to improve accuracy - Transparent characters drawn on background layer - Improved bad unicode detection * Many bug fixes and improvements, including: - Incorporated latest Cairo files from cairo-0.15.2 - Moved build to out-of-source - Added clean script - Rewritten correct_text_visibility option to improve accuracy - Transparent characters drawn on background layer - Improved bad unicode detection * Rationlise DPI to single number. Implement actual_dpi - clamp maximum background image size in cases of huge PDF pages * DPI fixes - increase DPI when partially covered text to covered-text-dpi Add font-style italic for oblique fonts Reduce char bbox for occlusion tests * Don't shrink bbox - not required if zoom=25 used * Ignore occlusion from stroke/fill with opacity < 0.5 Better compute char bbox for occlusion Use 10% inset for char bbox for occlusion Back out adding font-weight: bold to potentially bold fonts Fix bug to ensure CID ascent/descent matches subfont values * Removed zero char logging * Remove forced italic - missing italic is due to fontforge bug which needs fixing * Typos fixed, readme updated * Typos * Increase maximum background image width Fix private use range to avoid stupid mobile safari switching to emoji font * included -pthread switch to link included 3rdparty poppler files. * Updated files from poppler 0.59.0 and adjusted includes. * Support updated "Object" class from poppler 0.59.0
2018-01-10 19:31:38 +00:00
sout << ",";
2012-09-25 11:29:59 +00:00
if(dest->getChangeTop())
sout << (dest->getTop());
else
sout << "null";
New master (#2) * Show header in font map files * fix a usage of unique_ptr with array * Added '--quiet' argument to hide progress messages (resolves #503) * Revert cout messages to cerr (see #622) * bump version * fix build; fix some coverity warnings * Many bug fixes and improvements, including: - Incorporated latest Cairo files from cairo-0.15.2 - Moved build to out-of-source - Added clean script - Rewritten correct_text_visibility option to improve accuracy - Transparent characters drawn on background layer - Improved bad unicode detection * Many bug fixes and improvements, including: - Incorporated latest Cairo files from cairo-0.15.2 - Moved build to out-of-source - Added clean script - Rewritten correct_text_visibility option to improve accuracy - Transparent characters drawn on background layer - Improved bad unicode detection * Rationlise DPI to single number. Implement actual_dpi - clamp maximum background image size in cases of huge PDF pages * DPI fixes - increase DPI when partially covered text to covered-text-dpi Add font-style italic for oblique fonts Reduce char bbox for occlusion tests * Don't shrink bbox - not required if zoom=25 used * Ignore occlusion from stroke/fill with opacity < 0.5 Better compute char bbox for occlusion Use 10% inset for char bbox for occlusion Back out adding font-weight: bold to potentially bold fonts Fix bug to ensure CID ascent/descent matches subfont values * Removed zero char logging * Remove forced italic - missing italic is due to fontforge bug which needs fixing * Typos fixed, readme updated * Typos * Increase maximum background image width Fix private use range to avoid stupid mobile safari switching to emoji font * included -pthread switch to link included 3rdparty poppler files. * Updated files from poppler 0.59.0 and adjusted includes. * Support updated "Object" class from poppler 0.59.0
2018-01-10 19:31:38 +00:00
sout << ",";
if(dest->getChangeZoom())
sout << (dest->getZoom());
2012-09-25 11:29:59 +00:00
else
sout << "null";
New master (#2) * Show header in font map files * fix a usage of unique_ptr with array * Added '--quiet' argument to hide progress messages (resolves #503) * Revert cout messages to cerr (see #622) * bump version * fix build; fix some coverity warnings * Many bug fixes and improvements, including: - Incorporated latest Cairo files from cairo-0.15.2 - Moved build to out-of-source - Added clean script - Rewritten correct_text_visibility option to improve accuracy - Transparent characters drawn on background layer - Improved bad unicode detection * Many bug fixes and improvements, including: - Incorporated latest Cairo files from cairo-0.15.2 - Moved build to out-of-source - Added clean script - Rewritten correct_text_visibility option to improve accuracy - Transparent characters drawn on background layer - Improved bad unicode detection * Rationlise DPI to single number. Implement actual_dpi - clamp maximum background image size in cases of huge PDF pages * DPI fixes - increase DPI when partially covered text to covered-text-dpi Add font-style italic for oblique fonts Reduce char bbox for occlusion tests * Don't shrink bbox - not required if zoom=25 used * Ignore occlusion from stroke/fill with opacity < 0.5 Better compute char bbox for occlusion Use 10% inset for char bbox for occlusion Back out adding font-weight: bold to potentially bold fonts Fix bug to ensure CID ascent/descent matches subfont values * Removed zero char logging * Remove forced italic - missing italic is due to fontforge bug which needs fixing * Typos fixed, readme updated * Typos * Increase maximum background image width Fix private use range to avoid stupid mobile safari switching to emoji font * included -pthread switch to link included 3rdparty poppler files. * Updated files from poppler 0.59.0 and adjusted includes. * Support updated "Object" class from poppler 0.59.0
2018-01-10 19:31:38 +00:00
}
break;
case destFit:
sout << ",\"Fit\"";
break;
case destFitH:
sout << ",\"FitH\",";
if(dest->getChangeTop())
sout << (dest->getTop());
else
sout << "null";
break;
case destFitV:
sout << ",\"FitV\",";
if(dest->getChangeLeft())
sout << (dest->getLeft());
else
sout << "null";
break;
case destFitR:
sout << ",\"FitR\","
<< (dest->getLeft()) << ","
<< (dest->getBottom()) << ","
<< (dest->getRight()) << ","
<< (dest->getTop());
break;
case destFitB:
sout << ",\"FitB\"";
break;
case destFitBH:
sout << ",\"FitBH\",";
if(dest->getChangeTop())
sout << (dest->getTop());
else
sout << "null";
break;
case destFitBV:
sout << ",\"FitBV\",";
if(dest->getChangeLeft())
sout << (dest->getLeft());
else
sout << "null";
break;
default:
break;
2012-09-25 11:29:59 +00:00
}
sout << "]";
return sout.str();
}
2013-01-28 13:01:02 +00:00
string HTMLRenderer::get_linkaction_str(
const LinkAction * action,
string & detail
)
2012-09-25 11:29:59 +00:00
{
2013-01-28 13:01:02 +00:00
string dest_str;
detail = "";
2012-09-25 11:29:59 +00:00
if(action)
{
auto kind = action->getKind();
switch(kind)
{
case actionGoTo:
{
auto * real_action =
dynamic_cast<const LinkGoTo*>(action);
std::unique_ptr<LinkDest> dest = nullptr;
2012-09-25 11:29:59 +00:00
if(auto _ = real_action->getDest())
2023-12-18 10:39:47 +00:00
dest = std::make_unique<LinkDest>(*_);
2012-09-25 11:29:59 +00:00
else if (auto _ = real_action->getNamedDest())
2013-01-28 10:31:02 +00:00
dest = cur_catalog->findDest(_);
2012-09-25 11:29:59 +00:00
if(dest)
{
int pageno = 0;
detail = get_linkdest_detail_str(
dest.get(), cur_catalog, pageno
);
2012-09-25 11:29:59 +00:00
if(pageno > 0)
{
dest_str = (char*)str_fmt(
"#%s%x", CSS::PAGE_FRAME_CN, pageno
);
2012-09-25 11:29:59 +00:00
}
dest.reset();
2012-09-25 11:29:59 +00:00
}
}
break;
case actionGoToR:
{
cerr << "TODO: actionGoToR is not implemented." << endl;
}
break;
case actionURI:
{
auto * real_action = dynamic_cast<const LinkURI*>(action);
New master (#2) * Show header in font map files * fix a usage of unique_ptr with array * Added '--quiet' argument to hide progress messages (resolves #503) * Revert cout messages to cerr (see #622) * bump version * fix build; fix some coverity warnings * Many bug fixes and improvements, including: - Incorporated latest Cairo files from cairo-0.15.2 - Moved build to out-of-source - Added clean script - Rewritten correct_text_visibility option to improve accuracy - Transparent characters drawn on background layer - Improved bad unicode detection * Many bug fixes and improvements, including: - Incorporated latest Cairo files from cairo-0.15.2 - Moved build to out-of-source - Added clean script - Rewritten correct_text_visibility option to improve accuracy - Transparent characters drawn on background layer - Improved bad unicode detection * Rationlise DPI to single number. Implement actual_dpi - clamp maximum background image size in cases of huge PDF pages * DPI fixes - increase DPI when partially covered text to covered-text-dpi Add font-style italic for oblique fonts Reduce char bbox for occlusion tests * Don't shrink bbox - not required if zoom=25 used * Ignore occlusion from stroke/fill with opacity < 0.5 Better compute char bbox for occlusion Use 10% inset for char bbox for occlusion Back out adding font-weight: bold to potentially bold fonts Fix bug to ensure CID ascent/descent matches subfont values * Removed zero char logging * Remove forced italic - missing italic is due to fontforge bug which needs fixing * Typos fixed, readme updated * Typos * Increase maximum background image width Fix private use range to avoid stupid mobile safari switching to emoji font * included -pthread switch to link included 3rdparty poppler files. * Updated files from poppler 0.59.0 and adjusted includes. * Support updated "Object" class from poppler 0.59.0
2018-01-10 19:31:38 +00:00
assert(real_action != nullptr);
dest_str = real_action->getURI();
2012-09-25 11:29:59 +00:00
}
break;
case actionLaunch:
{
cerr << "TODO: actionLaunch is not implemented." << endl;
}
break;
default:
cerr << "Warning: unknown annotation type: " << kind << endl;
break;
}
}
2013-01-28 13:01:02 +00:00
return dest_str;
}
/*
* Based on pdftohtml from poppler
* TODO: share rectangle draw with css-draw
*/
void HTMLRenderer::processLink(AnnotLink * al)
{
string dest_detail_str;
string dest_str = get_linkaction_str(al->getAction(), dest_detail_str);
2013-01-28 10:31:02 +00:00
if(!dest_str.empty())
2012-09-25 11:29:59 +00:00
{
2013-06-09 14:19:12 +00:00
(*f_curpage) << "<a class=\"" << CSS::LINK_CN << "\" href=\"";
2013-10-18 08:31:59 +00:00
writeAttribute((*f_curpage), dest_str);
2013-06-09 14:19:12 +00:00
(*f_curpage) << "\"";
2012-09-25 11:29:59 +00:00
2013-01-28 10:31:02 +00:00
if(!dest_detail_str.empty())
2013-06-09 14:19:12 +00:00
(*f_curpage) << " data-dest-detail='" << dest_detail_str << "'";
2012-09-25 11:29:59 +00:00
2013-06-09 14:19:12 +00:00
(*f_curpage) << ">";
2012-09-25 11:29:59 +00:00
}
2013-06-09 14:19:12 +00:00
(*f_curpage) << "<div class=\"" << CSS::CSS_DRAW_CN << ' ' << CSS::TRANSFORM_MATRIX_CN
<< all_manager.transform_matrix.install(default_ctm)
2012-10-01 17:59:04 +00:00
<< "\" style=\"";
2012-09-25 11:29:59 +00:00
2012-10-01 17:59:04 +00:00
double x,y,w,h;
2012-09-25 11:29:59 +00:00
double x1, y1, x2, y2;
2012-10-01 17:59:04 +00:00
al->getRect(&x1, &y1, &x2, &y2);
2012-10-02 18:19:40 +00:00
x = min<double>(x1, x2);
y = min<double>(y1, y2);
w = max<double>(x1, x2) - x;
h = max<double>(y1, y2) - y;
2012-09-25 11:29:59 +00:00
double border_width = 0;
double border_top_bottom_width = 0;
double border_left_right_width = 0;
auto * border = al->getBorder();
if(border)
{
2012-10-02 06:19:20 +00:00
border_width = border->getWidth();
2012-09-25 11:29:59 +00:00
if(border_width > 0)
{
{
2012-10-01 20:06:38 +00:00
css_fix_rectangle_border_width(x1, y1, x2, y2, border_width,
2012-10-01 17:59:04 +00:00
x, y, w, h,
border_top_bottom_width, border_left_right_width);
2014-06-24 08:31:33 +00:00
if(std::abs(border_top_bottom_width - border_left_right_width) < EPS)
2013-06-09 14:19:12 +00:00
(*f_curpage) << "border-width:" << round(border_top_bottom_width) << "px;";
2012-09-25 11:29:59 +00:00
else
2013-06-09 14:19:12 +00:00
(*f_curpage) << "border-width:" << round(border_top_bottom_width) << "px " << round(border_left_right_width) << "px;";
2012-09-25 11:29:59 +00:00
}
auto style = border->getStyle();
switch(style)
{
case AnnotBorder::borderSolid:
2013-06-09 14:19:12 +00:00
(*f_curpage) << "border-style:solid;";
2012-09-25 11:29:59 +00:00
break;
case AnnotBorder::borderDashed:
2013-06-09 14:19:12 +00:00
(*f_curpage) << "border-style:dashed;";
2012-09-25 11:29:59 +00:00
break;
case AnnotBorder::borderBeveled:
2013-06-09 14:19:12 +00:00
(*f_curpage) << "border-style:outset;";
2012-09-25 11:29:59 +00:00
break;
case AnnotBorder::borderInset:
2013-06-09 14:19:12 +00:00
(*f_curpage) << "border-style:inset;";
2012-09-25 11:29:59 +00:00
break;
case AnnotBorder::borderUnderlined:
2013-06-09 14:19:12 +00:00
(*f_curpage) << "border-style:none;border-bottom-style:solid;";
2012-09-25 11:29:59 +00:00
break;
default:
cerr << "Warning:Unknown annotation border style: " << style << endl;
2013-06-09 14:19:12 +00:00
(*f_curpage) << "border-style:solid;";
2012-09-25 11:29:59 +00:00
}
auto color = al->getColor();
double r,g,b;
if(color && (color->getSpace() == AnnotColor::colorRGB))
{
const double * v = color->getValues();
r = v[0];
g = v[1];
b = v[2];
}
else
{
r = g = b = 0;
}
2013-06-09 14:19:12 +00:00
(*f_curpage) << "border-color:rgb("
2012-09-25 11:29:59 +00:00
<< dec << (int)dblToByte(r) << "," << (int)dblToByte(g) << "," << (int)dblToByte(b) << hex
<< ");";
}
else
{
2013-06-09 14:19:12 +00:00
(*f_curpage) << "border-style:none;";
2012-09-25 11:29:59 +00:00
}
}
else
{
2013-06-09 14:19:12 +00:00
(*f_curpage) << "border-style:none;";
2012-09-25 11:29:59 +00:00
}
2012-11-29 10:16:05 +00:00
tm_transform(default_ctm, x, y);
2012-09-25 11:29:59 +00:00
2013-06-09 14:19:12 +00:00
(*f_curpage) << "position:absolute;"
2012-11-29 10:16:05 +00:00
<< "left:" << round(x) << "px;"
<< "bottom:" << round(y) << "px;"
<< "width:" << round(w) << "px;"
<< "height:" << round(h) << "px;";
2012-09-25 11:29:59 +00:00
// fix for IE
2013-06-09 14:19:12 +00:00
(*f_curpage) << "background-color:rgba(255,255,255,0.000001);";
2012-09-25 11:29:59 +00:00
2013-06-09 14:19:12 +00:00
(*f_curpage) << "\"></div>";
2012-09-25 11:29:59 +00:00
if(dest_str != "")
{
2013-06-09 14:19:12 +00:00
(*f_curpage) << "</a>";
2012-09-25 11:29:59 +00:00
}
}
}// namespace pdf2htmlEX