mirror of
https://github.com/pdf2htmlEX/pdf2htmlEX.git
synced 2024-12-22 04:50:09 +00:00
precise link dest
This commit is contained in:
parent
a3a67d48ae
commit
e8d09a0115
@ -127,6 +127,7 @@ add_executable(pdf2htmlEX
|
||||
src/HTMLRenderer/export.cc
|
||||
src/HTMLRenderer/text.cc
|
||||
src/HTMLRenderer/image.cc
|
||||
src/HTMLRenderer/link.cc
|
||||
src/include/namespace.h
|
||||
src/HTMLRenderer/LineBuffer.cc
|
||||
src/include/ffw.h
|
||||
|
@ -54,4 +54,9 @@ span {
|
||||
.i {
|
||||
position:absolute;
|
||||
}
|
||||
.j {
|
||||
display:none;
|
||||
}
|
||||
.a {
|
||||
}
|
||||
/* Base CSS END */
|
||||
|
@ -12,10 +12,28 @@
|
||||
|
||||
var pdf2htmlEX = (function(){
|
||||
var EPS = 1e-6;
|
||||
var Page = function(page, box, visible) {
|
||||
this.p = page;
|
||||
this.b = box;
|
||||
this.v = visible;
|
||||
var invert = function(ctm) {
|
||||
var det = ctm[0] * ctm[3] - ctm[1] * ctm[2];
|
||||
var ictm = new Array();
|
||||
ictm[0] = ctm[3] / det;
|
||||
ictm[1] = -ctm[1] / det;
|
||||
ictm[2] = -ctm[2] / det;
|
||||
ictm[3] = ctm[0] / det;
|
||||
ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) / det;
|
||||
ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) / det;
|
||||
return ictm;
|
||||
};
|
||||
var transform = function(ctm, pos) {
|
||||
return [ctm[0] * pos[0] + ctm[2] * pos[1] + ctm[4]
|
||||
,ctm[1] * pos[0] + ctm[3] * pos[1] + ctm[5]];
|
||||
};
|
||||
var Page = function(page) {
|
||||
if(page == undefined) return undefined;
|
||||
|
||||
this.p = $(page);
|
||||
this.n = parseInt(this.p.attr('data-page-no'), 16);
|
||||
this.b = $('.b', this.p);
|
||||
|
||||
/*
|
||||
* scale ratios
|
||||
*
|
||||
@ -23,23 +41,22 @@ var pdf2htmlEX = (function(){
|
||||
* set_r : last set
|
||||
* cur_r : currently using
|
||||
*/
|
||||
this.default_r = this.set_r = this.cur_r = page.height() / box.height();
|
||||
this.default_r = this.set_r = this.cur_r = this.p.height() / this.b.height();
|
||||
|
||||
this.data = JSON.parse($($('.j', this.p)[0]).attr('data-data'));
|
||||
|
||||
this.ctm = this.data.ctm;
|
||||
this.ictm = invert(this.ctm);
|
||||
};
|
||||
Page.prototype.hide = function(){
|
||||
if(this.v) {
|
||||
this.v = false;
|
||||
this.b.hide();
|
||||
}
|
||||
this.b.hide();
|
||||
};
|
||||
Page.prototype.show = function(){
|
||||
if(Math.abs(this.set_r - this.cur_r) > EPS) {
|
||||
this.cur_r = this.set_r;
|
||||
this.b.css('transform', 'scale('+this.cur_r.toFixed(3)+')');
|
||||
}
|
||||
if(!(this.v)) {
|
||||
this.v = true;
|
||||
this.b.show();
|
||||
}
|
||||
this.b.show();
|
||||
};
|
||||
Page.prototype.rescale = function(ratio, is_relative) {
|
||||
if(ratio == 0) {
|
||||
@ -55,7 +72,11 @@ var pdf2htmlEX = (function(){
|
||||
|
||||
this.p.height(this.b.height() * this.set_r);
|
||||
this.p.width(this.b.width() * this.set_r);
|
||||
|
||||
};
|
||||
Page.prototype.is_visible = function() {
|
||||
var p = this.p;
|
||||
var off = p.position();
|
||||
return !((off.top + p.height() < 0) || (off.top > p.offsetParent().height()));
|
||||
};
|
||||
|
||||
return {
|
||||
@ -73,13 +94,14 @@ var pdf2htmlEX = (function(){
|
||||
},
|
||||
|
||||
init_after_loading_content : function() {
|
||||
this.container = $("#pdf-main");
|
||||
this.container = $('#pdf-main');
|
||||
|
||||
var new_pages = new Array();
|
||||
var pl= $(".p", this.container);
|
||||
var pbl = $(".b", this.container);
|
||||
var pl= $('.p', this.container);
|
||||
/* don't use for(..in..) */
|
||||
for(var i = 0, l = pl.length; i < l; ++i) {
|
||||
new_pages.push(new Page($(pl[i]), $(pbl[i]), false));
|
||||
var p = new Page(pl[i]);
|
||||
new_pages[p.n] = p;
|
||||
}
|
||||
this.pages = new_pages;
|
||||
|
||||
@ -87,6 +109,8 @@ var pdf2htmlEX = (function(){
|
||||
this.container.scroll(function(){ _.schedule_render(); });
|
||||
|
||||
//this.zoom_fixer();
|
||||
|
||||
this.container.on('click', '.a', this, this.annot_link_handler);
|
||||
|
||||
this.render();
|
||||
},
|
||||
@ -95,7 +119,7 @@ var pdf2htmlEX = (function(){
|
||||
this.init_before_loading_content();
|
||||
|
||||
var _ = this;
|
||||
$(document).ready(function(){_.init_after_loading_content();});
|
||||
$(function(){_.init_after_loading_content();});
|
||||
|
||||
return this;
|
||||
},
|
||||
@ -103,47 +127,31 @@ var pdf2htmlEX = (function(){
|
||||
pre_hide_pages : function() {
|
||||
/* pages might have not been loaded yet, so add a CSS rule */
|
||||
var s = '.b{display:none;}';
|
||||
var n = document.createElement("style");
|
||||
n.type = "text/css";
|
||||
var n = document.createElement('style');
|
||||
n.type = 'text/css';
|
||||
if (n.styleSheet) {
|
||||
n.styleSheet.cssText = s;
|
||||
} else {
|
||||
n.appendChild(document.createTextNode(s));
|
||||
}
|
||||
document.getElementsByTagName("head")[0].appendChild(n);
|
||||
document.getElementsByTagName('head')[0].appendChild(n);
|
||||
},
|
||||
|
||||
hide_pages : function() {
|
||||
var pl = this.pages;
|
||||
for(var i = 0, l = pl.length; i < l; ++i)
|
||||
for(var i in pl)
|
||||
pl[i].hide();
|
||||
},
|
||||
|
||||
render : function () {
|
||||
/* hide (positional) invisible pages */
|
||||
var pl = this.pages;
|
||||
var l = pl.length;
|
||||
var ch = this.container.height();
|
||||
|
||||
var i;
|
||||
for(i = 0; i < l; ++i) {
|
||||
for(var i in pl) {
|
||||
var p = pl[i];
|
||||
|
||||
if(p.p.position().top + p.p.height() >= 0) break;
|
||||
if(i > 0) pl[i-1].hide();
|
||||
}
|
||||
|
||||
if((i > 0) && (i < l)) pl[i-1].show();
|
||||
|
||||
for(; i < l; ++i) {
|
||||
var p = pl[i];
|
||||
p.show();
|
||||
|
||||
if(p.p.position().top > ch) break;
|
||||
}
|
||||
|
||||
for(++i; i < l; ++i) {
|
||||
pl[i].hide();
|
||||
if(p.is_visible())
|
||||
p.show();
|
||||
else
|
||||
p.hide();
|
||||
}
|
||||
},
|
||||
|
||||
@ -199,13 +207,57 @@ var pdf2htmlEX = (function(){
|
||||
|
||||
rescale : function (ratio, is_relative) {
|
||||
var pl = this.pages;
|
||||
for(var i = 0, l = pl.length; i < l; ++i) {
|
||||
for(var i in pl) {
|
||||
pl[i].rescale(ratio, is_relative);
|
||||
}
|
||||
|
||||
this.schedule_render();
|
||||
},
|
||||
|
||||
__last_member__ : 'no comma' /*,*/
|
||||
get_containing_page : function(obj) {
|
||||
/* get the page obj containing obj */
|
||||
return this.pages[(new Page(obj.closest('.p')[0])).n];
|
||||
},
|
||||
|
||||
annot_link_handler : function (e) {
|
||||
var _ = e.data;
|
||||
var t = $(e.currentTarget);
|
||||
var cur_page = _.get_containing_page(t);
|
||||
if(cur_page == undefined) return;
|
||||
|
||||
var off = cur_page.p.position();
|
||||
var cur_pos = transform(cur_page.ictm, [-off.left, cur_page.p.height()+off.top]);
|
||||
|
||||
var detail_str = t.attr('data-dest-detail');
|
||||
if(detail_str == undefined) return;
|
||||
|
||||
var ok = false;
|
||||
var detail= JSON.parse(detail_str);
|
||||
var target_page = _.pages[detail[0]];
|
||||
if(target_page == undefined) return;
|
||||
|
||||
switch(detail[1]) {
|
||||
case 'XYZ':
|
||||
var pos = [(detail[2] == null) ? cur_pos[0] : detail[2]
|
||||
,(detail[3] == null) ? cur_pos[1] : detail[3]];
|
||||
pos = transform(cur_page.ctm, pos);
|
||||
|
||||
console.log(pos);
|
||||
|
||||
var off = target_page.p.position();
|
||||
|
||||
console.log(off);
|
||||
|
||||
_.container.scrollLeft(_.container.scrollLeft()+off.left+pos[0]);
|
||||
_.container.scrollTop(_.container.scrollTop()+off.top+target_page.p.height()-pos[1]);
|
||||
ok = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(ok)
|
||||
e.preventDefault();
|
||||
}, __last_member__ : 'no comma' /*,*/
|
||||
}.init();
|
||||
})();
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* general.cc
|
||||
*
|
||||
* Hanlding general stuffs
|
||||
* Handling general stuffs
|
||||
*
|
||||
* by WangLu
|
||||
* 2012.08.14
|
||||
@ -12,7 +12,6 @@
|
||||
#include <cmath>
|
||||
|
||||
#include <splash/SplashBitmap.h>
|
||||
#include <Link.h>
|
||||
|
||||
#include "HTMLRenderer.h"
|
||||
#include "BackgroundRenderer.h"
|
||||
@ -155,7 +154,8 @@ void HTMLRenderer::startPage(int pageNum, GfxState *state)
|
||||
assert((!line_opened) && "Open line in startPage detected!");
|
||||
|
||||
html_fout
|
||||
<< "<div id=\"p" << pageNum << "\" class=\"p\" style=\"width:"
|
||||
<< "<div id=\"p" << pageNum << "\" data-page-no=\"" << pageNum
|
||||
<< "\" class=\"p\" style=\"width:"
|
||||
<< (pageWidth) << "px;height:"
|
||||
<< (pageHeight) << "px;\">"
|
||||
<< "<div class=\"b\" style=\"width:"
|
||||
@ -226,170 +226,29 @@ void HTMLRenderer::endPage() {
|
||||
// process links before the page is closed
|
||||
cur_doc->processLinks(this, pageNum);
|
||||
|
||||
// close box
|
||||
html_fout << "</div>";
|
||||
|
||||
// dump info for js
|
||||
// TODO: create a function for this
|
||||
// BE CAREFUL WITH ESCAPES
|
||||
html_fout << "<div class=\"j\" data-data='{";
|
||||
|
||||
//default CTM
|
||||
html_fout << "\"ctm\":[";
|
||||
for(int i = 0; i < 6; ++i)
|
||||
{
|
||||
if(i > 0) html_fout << ",";
|
||||
html_fout << _round(default_ctm[i]);
|
||||
}
|
||||
html_fout << "]";
|
||||
|
||||
html_fout << "}'></div>";
|
||||
|
||||
// close page
|
||||
html_fout << "</div></div>" << endl;
|
||||
html_fout << "</div>" << endl;
|
||||
}
|
||||
|
||||
/*
|
||||
* Based on pdftohtml from poppler
|
||||
* TODO: CSS for link rectangles
|
||||
*/
|
||||
void HTMLRenderer::processLink(AnnotLink * al)
|
||||
{
|
||||
std::string dest_str;
|
||||
auto action = al->getAction();
|
||||
if(action)
|
||||
{
|
||||
auto kind = action->getKind();
|
||||
switch(kind)
|
||||
{
|
||||
case actionGoTo:
|
||||
{
|
||||
auto catalog = cur_doc->getCatalog();
|
||||
auto * real_action = dynamic_cast<LinkGoTo*>(action);
|
||||
LinkDest * dest = nullptr;
|
||||
if(auto _ = real_action->getDest())
|
||||
dest = _->copy();
|
||||
else if (auto _ = real_action->getNamedDest())
|
||||
dest = catalog->findDest(_);
|
||||
if(dest)
|
||||
{
|
||||
int pageno = 0;
|
||||
if(dest->isPageRef())
|
||||
{
|
||||
auto pageref = dest->getPageRef();
|
||||
pageno = catalog->findPage(pageref.num, pageref.gen);
|
||||
}
|
||||
else
|
||||
{
|
||||
pageno = dest->getPageNum();
|
||||
}
|
||||
|
||||
delete dest;
|
||||
|
||||
if(pageno > 0)
|
||||
dest_str = (char*)str_fmt("#p%x", pageno);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case actionGoToR:
|
||||
{
|
||||
cerr << "TODO: actionGoToR is not implemented." << endl;
|
||||
}
|
||||
break;
|
||||
case actionURI:
|
||||
{
|
||||
auto * real_action = dynamic_cast<LinkURI*>(action);
|
||||
dest_str = real_action->getURI()->getCString();
|
||||
}
|
||||
break;
|
||||
case actionLaunch:
|
||||
{
|
||||
cerr << "TODO: actionLaunch is not implemented." << endl;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
cerr << "Warning: unknown annotation type: " << kind << endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(dest_str != "")
|
||||
{
|
||||
html_fout << "<a href=\"" << dest_str << "\">";
|
||||
}
|
||||
|
||||
html_fout << "<div style=\"";
|
||||
|
||||
double width = 0;
|
||||
auto * border = al->getBorder();
|
||||
if(border)
|
||||
{
|
||||
width = border->getWidth() * (param->zoom);
|
||||
if(width > 0)
|
||||
{
|
||||
html_fout << "border-width:" << _round(width) << "px;";
|
||||
auto style = border->getStyle();
|
||||
switch(style)
|
||||
{
|
||||
case AnnotBorder::borderSolid:
|
||||
html_fout << "border-style:solid;";
|
||||
break;
|
||||
case AnnotBorder::borderDashed:
|
||||
html_fout << "border-style:dashed;";
|
||||
break;
|
||||
case AnnotBorder::borderBeveled:
|
||||
html_fout << "border-style:outset;";
|
||||
break;
|
||||
case AnnotBorder::borderInset:
|
||||
html_fout << "border-style:inset;";
|
||||
break;
|
||||
case AnnotBorder::borderUnderlined:
|
||||
html_fout << "border-style:none;border-bottom-style:solid;";
|
||||
break;
|
||||
default:
|
||||
cerr << "Warning:Unknown annotation border style: " << style << endl;
|
||||
html_fout << "border-style:solid;";
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
html_fout << "border-color:rgb("
|
||||
<< dec << (int)dblToByte(r) << "," << (int)dblToByte(g) << "," << (int)dblToByte(b) << hex
|
||||
<< ");";
|
||||
}
|
||||
else
|
||||
{
|
||||
html_fout << "border-style:none;";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
html_fout << "border-style:none;";
|
||||
}
|
||||
|
||||
// fix for IE
|
||||
html_fout << "background-color:rgba(255,255,255,0.000001);";
|
||||
|
||||
double x1,x2,y1,y2;
|
||||
al->getRect(&x1, &y1, &x2, &y2);
|
||||
|
||||
x1 = default_ctm[0] * x1 + default_ctm[2] * y1 + default_ctm[4];
|
||||
y1 = default_ctm[1] * x1 + default_ctm[3] * y1 + default_ctm[5];
|
||||
x2 = default_ctm[0] * x2 + default_ctm[2] * y2 + default_ctm[4];
|
||||
y2 = default_ctm[1] * x2 + default_ctm[3] * y2 + default_ctm[5];
|
||||
|
||||
// TODO: check overlap when x2-x1-width<0 or y2-y1-width<0
|
||||
html_fout << "position:absolute;"
|
||||
<< "left:" << _round(x1 - width/2) << "px;"
|
||||
<< "bottom:" << _round(y1 - width/2) << "px;"
|
||||
<< "width:" << _round(x2-x1-width) << "px;"
|
||||
<< "height:" << _round(y2-y1-width) << "px;";
|
||||
|
||||
html_fout << "background-color:rgb(0,0,0,0);";
|
||||
|
||||
html_fout << "\"></div>";
|
||||
|
||||
if(dest_str != "")
|
||||
{
|
||||
html_fout << "</a>";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void HTMLRenderer::pre_process()
|
||||
{
|
||||
// we may output utf8 characters, so always use binary
|
||||
|
334
src/HTMLRenderer/link.cc
Normal file
334
src/HTMLRenderer/link.cc
Normal file
@ -0,0 +1,334 @@
|
||||
/*
|
||||
* link.cc
|
||||
*
|
||||
* Handling links
|
||||
*
|
||||
* by WangLu
|
||||
* 2012.09.25
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
#include <HTMLRenderer.h>
|
||||
#include <Link.h>
|
||||
|
||||
#include "namespace.h"
|
||||
|
||||
namespace pdf2htmlEX {
|
||||
|
||||
using std::ostringstream;
|
||||
using std::min;
|
||||
using std::max;
|
||||
|
||||
static void _transform(const double * ctm, double & x, double & y)
|
||||
{
|
||||
double xx = x, yy = y;
|
||||
x = ctm[0] * xx + ctm[2] * yy + ctm[4];
|
||||
y = ctm[1] * xx + ctm[3] * yy + ctm[5];
|
||||
}
|
||||
|
||||
static void _get_transformed_rect(AnnotLink * link, const double * ctm, double & x1, double & y1, double & x2, double & y2)
|
||||
{
|
||||
double _x1, _x2, _y1, _y2;
|
||||
link->getRect(&_x1, &_y1, &_x2, &_y2);
|
||||
|
||||
_transform(ctm, _x1, _y1);
|
||||
_transform(ctm, _x2, _y2);
|
||||
|
||||
x1 = min(_x1, _x2);
|
||||
x2 = max(_x1, _x2);
|
||||
y1 = min(_y1, _y2);
|
||||
y2 = max(_y1, _y2);
|
||||
}
|
||||
|
||||
/*
|
||||
* In PDF, edges of the rectangle are in the middle of the borders
|
||||
* In HTML, edges are completely outside the rectangle
|
||||
*/
|
||||
static void _fix_border_width(double & x1, double & y1, double & x2, double & y2,
|
||||
double border_width, double & border_top_bottom_width, double & border_left_right_width)
|
||||
{
|
||||
double w = x2 - x1;
|
||||
if(w > border_width)
|
||||
{
|
||||
x1 += border_width / 2;
|
||||
x2 -= border_width / 2;
|
||||
border_left_right_width = border_width;
|
||||
}
|
||||
else
|
||||
{
|
||||
x1 += w / 2;
|
||||
x2 -= w / 2;
|
||||
border_left_right_width = border_width + w/2;
|
||||
}
|
||||
double h = y2 - y1;
|
||||
if(h > border_width)
|
||||
{
|
||||
y1 += border_width / 2;
|
||||
y2 -= border_width / 2;
|
||||
border_top_bottom_width = border_width;
|
||||
}
|
||||
else
|
||||
{
|
||||
y1 += h / 2;
|
||||
y2 -= h / 2;
|
||||
border_top_bottom_width = border_width + h/2;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The detailed rectangle area of the link destination
|
||||
* Will be parsed and performed by Javascript
|
||||
*/
|
||||
static string get_dest_detail_str(int pageno, LinkDest * dest)
|
||||
{
|
||||
ostringstream sout;
|
||||
// dec
|
||||
sout << "[" << pageno;
|
||||
|
||||
if(dest)
|
||||
{
|
||||
switch(dest->getKind())
|
||||
{
|
||||
case destXYZ:
|
||||
{
|
||||
sout << ",\"XYZ\",";
|
||||
if(dest->getChangeLeft())
|
||||
sout << (dest->getLeft());
|
||||
else
|
||||
sout << "null";
|
||||
sout << ",";
|
||||
if(dest->getChangeTop())
|
||||
sout << (dest->getTop());
|
||||
else
|
||||
sout << "null";
|
||||
sout << ",";
|
||||
if(dest->getChangeZoom())
|
||||
sout << (dest->getZoom());
|
||||
else
|
||||
sout << "null";
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
sout << "]";
|
||||
|
||||
return sout.str();
|
||||
}
|
||||
|
||||
/*
|
||||
* Based on pdftohtml from poppler
|
||||
* TODO: CSS for link rectangles
|
||||
*/
|
||||
void HTMLRenderer::processLink(AnnotLink * al)
|
||||
{
|
||||
std::string dest_str, dest_detail_str;
|
||||
auto action = al->getAction();
|
||||
if(action)
|
||||
{
|
||||
auto kind = action->getKind();
|
||||
switch(kind)
|
||||
{
|
||||
case actionGoTo:
|
||||
{
|
||||
auto catalog = cur_doc->getCatalog();
|
||||
auto * real_action = dynamic_cast<LinkGoTo*>(action);
|
||||
LinkDest * dest = nullptr;
|
||||
if(auto _ = real_action->getDest())
|
||||
dest = _->copy();
|
||||
else if (auto _ = real_action->getNamedDest())
|
||||
dest = catalog->findDest(_);
|
||||
if(dest)
|
||||
{
|
||||
int pageno = 0;
|
||||
if(dest->isPageRef())
|
||||
{
|
||||
auto pageref = dest->getPageRef();
|
||||
pageno = catalog->findPage(pageref.num, pageref.gen);
|
||||
}
|
||||
else
|
||||
{
|
||||
pageno = dest->getPageNum();
|
||||
}
|
||||
|
||||
if(pageno > 0)
|
||||
{
|
||||
dest_str = (char*)str_fmt("#p%x", pageno);
|
||||
dest_detail_str = get_dest_detail_str(pageno, dest);
|
||||
}
|
||||
|
||||
delete dest;
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
case actionGoToR:
|
||||
{
|
||||
cerr << "TODO: actionGoToR is not implemented." << endl;
|
||||
}
|
||||
break;
|
||||
case actionURI:
|
||||
{
|
||||
auto * real_action = dynamic_cast<LinkURI*>(action);
|
||||
dest_str = real_action->getURI()->getCString();
|
||||
}
|
||||
break;
|
||||
case actionLaunch:
|
||||
{
|
||||
cerr << "TODO: actionLaunch is not implemented." << endl;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
cerr << "Warning: unknown annotation type: " << kind << endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(dest_str != "")
|
||||
{
|
||||
html_fout << "<a class=\"a\" href=\"" << dest_str << "\"";
|
||||
|
||||
if(dest_detail_str != "")
|
||||
html_fout << " data-dest-detail='" << dest_detail_str << "'";
|
||||
|
||||
html_fout << ">";
|
||||
}
|
||||
|
||||
html_fout << "<div style=\"";
|
||||
|
||||
double x1, y1, x2, y2;
|
||||
_get_transformed_rect(al, default_ctm, x1, y1, x2, y2);
|
||||
|
||||
double border_width = 0;
|
||||
double border_top_bottom_width = 0;
|
||||
double border_left_right_width = 0;
|
||||
auto * border = al->getBorder();
|
||||
if(border)
|
||||
{
|
||||
border_width = border->getWidth() * (param->zoom);
|
||||
if(border_width > 0)
|
||||
{
|
||||
{
|
||||
_fix_border_width(x1, y1, x2, y1,
|
||||
border_width, border_top_bottom_width, border_left_right_width);
|
||||
if(abs(border_top_bottom_width - border_left_right_width) < EPS)
|
||||
html_fout << "border-width:" << _round(border_top_bottom_width) << "px;";
|
||||
else
|
||||
html_fout << "border-width:" << _round(border_top_bottom_width) << "px " << _round(border_left_right_width) << "px;";
|
||||
}
|
||||
auto style = border->getStyle();
|
||||
switch(style)
|
||||
{
|
||||
case AnnotBorder::borderSolid:
|
||||
html_fout << "border-style:solid;";
|
||||
break;
|
||||
case AnnotBorder::borderDashed:
|
||||
html_fout << "border-style:dashed;";
|
||||
break;
|
||||
case AnnotBorder::borderBeveled:
|
||||
html_fout << "border-style:outset;";
|
||||
break;
|
||||
case AnnotBorder::borderInset:
|
||||
html_fout << "border-style:inset;";
|
||||
break;
|
||||
case AnnotBorder::borderUnderlined:
|
||||
html_fout << "border-style:none;border-bottom-style:solid;";
|
||||
break;
|
||||
default:
|
||||
cerr << "Warning:Unknown annotation border style: " << style << endl;
|
||||
html_fout << "border-style:solid;";
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
html_fout << "border-color:rgb("
|
||||
<< dec << (int)dblToByte(r) << "," << (int)dblToByte(g) << "," << (int)dblToByte(b) << hex
|
||||
<< ");";
|
||||
}
|
||||
else
|
||||
{
|
||||
html_fout << "border-style:none;";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
html_fout << "border-style:none;";
|
||||
}
|
||||
|
||||
|
||||
html_fout << "position:absolute;"
|
||||
<< "left:" << _round(x1- border_left_right_width) << "px;"
|
||||
<< "bottom:" << _round(y1 - border_top_bottom_width) << "px;"
|
||||
<< "width:" << _round(x2-x1) << "px;"
|
||||
<< "height:" << _round(y2-y1) << "px;";
|
||||
|
||||
// fix for IE
|
||||
html_fout << "background-color:rgba(255,255,255,0.000001);";
|
||||
|
||||
html_fout << "\"></div>";
|
||||
|
||||
if(dest_str != "")
|
||||
{
|
||||
html_fout << "</a>";
|
||||
}
|
||||
}
|
||||
|
||||
}// namespace pdf2htmlEX
|
@ -33,11 +33,13 @@
|
||||
*
|
||||
* CSS classes
|
||||
*
|
||||
* b - page Box
|
||||
* p - Page
|
||||
* l - Line
|
||||
* _ - white space
|
||||
* a - Annot link
|
||||
* b - page Box
|
||||
* l - Line
|
||||
* i - Image
|
||||
* j - Js data
|
||||
* p - Page
|
||||
*
|
||||
* Reusable CSS classes
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user