mirror of
https://github.com/pdf2htmlEX/pdf2htmlEX.git
synced 2024-10-06 12:01:39 +00:00
[experimental], styling change within a line
This commit is contained in:
parent
ad6d6a31a0
commit
dc0fd477d8
@ -8,7 +8,6 @@
|
|||||||
#ifndef HTMLRENDERER_H_
|
#ifndef HTMLRENDERER_H_
|
||||||
#define HTMLRENDERER_H_
|
#define HTMLRENDERER_H_
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -164,7 +163,8 @@ class HTMLRenderer : public OutputDev
|
|||||||
////////////////////////////////////////////////////
|
////////////////////////////////////////////////////
|
||||||
void check_state_change(GfxState * state);
|
void check_state_change(GfxState * state);
|
||||||
void reset_state_track();
|
void reset_state_track();
|
||||||
void close_cur_line();
|
void prepare_line(); // close current span or div if necessary, according to new_line_status
|
||||||
|
void close_line();
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////
|
////////////////////////////////////////////////////
|
||||||
@ -182,13 +182,15 @@ class HTMLRenderer : public OutputDev
|
|||||||
////////////////////////////////////////////////////
|
////////////////////////////////////////////////////
|
||||||
// states
|
// states
|
||||||
////////////////////////////////////////////////////
|
////////////////////////////////////////////////////
|
||||||
// if we have a pending opened line
|
//line status
|
||||||
|
//indicating the status for current line & next line
|
||||||
|
//see comments: meaning for current line || meaning for next line
|
||||||
enum class LineStatus
|
enum class LineStatus
|
||||||
{
|
{
|
||||||
CLOSED,
|
NONE, // no line is opened (last <div> is closed) || stay with the same style
|
||||||
SPAN,
|
SPAN, // there's a pending opening <span> (within a pending opening <div>) || open a new <span> if possible, otherwise a new <div>
|
||||||
DIV
|
DIV // there's a pending opening <div> (but no <span>) || has to open a new <div>
|
||||||
} line_status;
|
} line_status, new_line_status;
|
||||||
|
|
||||||
// The order is according to the appearance in check_state_change
|
// The order is according to the appearance in check_state_change
|
||||||
// any state changed
|
// any state changed
|
||||||
|
@ -19,7 +19,7 @@ using boost::filesystem::remove;
|
|||||||
using boost::filesystem::filesystem_error;
|
using boost::filesystem::filesystem_error;
|
||||||
|
|
||||||
HTMLRenderer::HTMLRenderer(const Param * param)
|
HTMLRenderer::HTMLRenderer(const Param * param)
|
||||||
:line_status(LineStatus::CLOSED)
|
:line_status(LineStatus::NONE)
|
||||||
,image_count(0)
|
,image_count(0)
|
||||||
,param(param)
|
,param(param)
|
||||||
,dest_dir(param->dest_dir)
|
,dest_dir(param->dest_dir)
|
||||||
@ -142,7 +142,7 @@ void HTMLRenderer::startPage(int pageNum, GfxState *state)
|
|||||||
this->pageWidth = state->getPageWidth();
|
this->pageWidth = state->getPageWidth();
|
||||||
this->pageHeight = state->getPageHeight();
|
this->pageHeight = state->getPageHeight();
|
||||||
|
|
||||||
assert(line_status == LineStatus::CLOSED);
|
assert(line_status == LineStatus::NONE);
|
||||||
|
|
||||||
html_fout << format("<div id=\"p%|1$x|\" class=\"p\" style=\"width:%2%px;height:%3%px;") % pageNum % pageWidth % pageHeight;
|
html_fout << format("<div id=\"p%|1$x|\" class=\"p\" style=\"width:%2%px;height:%3%px;") % pageNum % pageWidth % pageHeight;
|
||||||
|
|
||||||
@ -186,7 +186,7 @@ void HTMLRenderer::startPage(int pageNum, GfxState *state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void HTMLRenderer::endPage() {
|
void HTMLRenderer::endPage() {
|
||||||
close_cur_line();
|
close_line();
|
||||||
// close page
|
// close page
|
||||||
html_fout << "</div>" << endl;
|
html_fout << "</div>" << endl;
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ void HTMLRenderer::drawImage(GfxState * state, Object * ref, Stream * str, int w
|
|||||||
img_stream->close();
|
img_stream->close();
|
||||||
delete img_stream;
|
delete img_stream;
|
||||||
|
|
||||||
close_cur_line();
|
close_line();
|
||||||
|
|
||||||
double * ctm = state->getCTM();
|
double * ctm = state->getCTM();
|
||||||
ctm[4] = ctm[5] = 0.0;
|
ctm[4] = ctm[5] = 0.0;
|
||||||
|
@ -7,10 +7,13 @@
|
|||||||
* 2012.08.14
|
* 2012.08.14
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include "HTMLRenderer.h"
|
#include "HTMLRenderer.h"
|
||||||
#include "namespace.h"
|
#include "namespace.h"
|
||||||
|
|
||||||
|
using std::max;
|
||||||
|
|
||||||
void HTMLRenderer::updateAll(GfxState * state)
|
void HTMLRenderer::updateAll(GfxState * state)
|
||||||
{
|
{
|
||||||
all_changed = true;
|
all_changed = true;
|
||||||
@ -63,10 +66,13 @@ void HTMLRenderer::updateFillColor(GfxState * state)
|
|||||||
}
|
}
|
||||||
void HTMLRenderer::check_state_change(GfxState * state)
|
void HTMLRenderer::check_state_change(GfxState * state)
|
||||||
{
|
{
|
||||||
|
//TODO:
|
||||||
|
// close <span> but not <div>, to use the first style of the line
|
||||||
|
|
||||||
// DEPENDENCY WARNING
|
// DEPENDENCY WARNING
|
||||||
// don't adjust the order of state checking
|
// don't adjust the order of state checking
|
||||||
|
|
||||||
bool close_line = false;
|
new_line_status = LineStatus::NONE;
|
||||||
|
|
||||||
bool need_recheck_position = false;
|
bool need_recheck_position = false;
|
||||||
bool need_rescale_font = false;
|
bool need_rescale_font = false;
|
||||||
@ -97,7 +103,7 @@ void HTMLRenderer::check_state_change(GfxState * state)
|
|||||||
// should draw_scale be updated, we'll close the line anyway
|
// should draw_scale be updated, we'll close the line anyway
|
||||||
if(!(abs((cur_ty + cur_rise) - draw_ty) * draw_scale < param->v_eps))
|
if(!(abs((cur_ty + cur_rise) - draw_ty) * draw_scale < param->v_eps))
|
||||||
{
|
{
|
||||||
close_line = true;
|
new_line_status = max(new_line_status, LineStatus::DIV);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,7 +114,7 @@ void HTMLRenderer::check_state_change(GfxState * state)
|
|||||||
|
|
||||||
if(!(new_fn_id == cur_fn_id))
|
if(!(new_fn_id == cur_fn_id))
|
||||||
{
|
{
|
||||||
close_line = true;
|
new_line_status = max(new_line_status, LineStatus::SPAN);
|
||||||
cur_fn_id = new_fn_id;
|
cur_fn_id = new_fn_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,13 +173,13 @@ void HTMLRenderer::check_state_change(GfxState * state)
|
|||||||
|
|
||||||
if(!(_equal(new_draw_font_size, draw_font_size)))
|
if(!(_equal(new_draw_font_size, draw_font_size)))
|
||||||
{
|
{
|
||||||
close_line = true;
|
new_line_status = max(new_line_status, LineStatus::SPAN);
|
||||||
draw_font_size = new_draw_font_size;
|
draw_font_size = new_draw_font_size;
|
||||||
cur_fs_id = install_font_size(draw_font_size);
|
cur_fs_id = install_font_size(draw_font_size);
|
||||||
}
|
}
|
||||||
if(!(_tm_equal(new_draw_ctm, draw_ctm)))
|
if(!(_tm_equal(new_draw_ctm, draw_ctm)))
|
||||||
{
|
{
|
||||||
close_line = true;
|
new_line_status = max(new_line_status, LineStatus::DIV);
|
||||||
memcpy(draw_ctm, new_draw_ctm, sizeof(draw_ctm));
|
memcpy(draw_ctm, new_draw_ctm, sizeof(draw_ctm));
|
||||||
cur_tm_id = install_transform_matrix(draw_ctm);
|
cur_tm_id = install_transform_matrix(draw_ctm);
|
||||||
}
|
}
|
||||||
@ -186,7 +192,7 @@ void HTMLRenderer::check_state_change(GfxState * state)
|
|||||||
double new_letter_space = state->getCharSpace();
|
double new_letter_space = state->getCharSpace();
|
||||||
if(!_equal(cur_letter_space, new_letter_space))
|
if(!_equal(cur_letter_space, new_letter_space))
|
||||||
{
|
{
|
||||||
close_line = true;
|
new_line_status = max(new_line_status, LineStatus::SPAN);
|
||||||
cur_letter_space = new_letter_space;
|
cur_letter_space = new_letter_space;
|
||||||
cur_ls_id = install_letter_space(cur_letter_space * draw_scale);
|
cur_ls_id = install_letter_space(cur_letter_space * draw_scale);
|
||||||
}
|
}
|
||||||
@ -199,14 +205,12 @@ void HTMLRenderer::check_state_change(GfxState * state)
|
|||||||
double new_word_space = state->getWordSpace();
|
double new_word_space = state->getWordSpace();
|
||||||
if(!_equal(cur_word_space, new_word_space))
|
if(!_equal(cur_word_space, new_word_space))
|
||||||
{
|
{
|
||||||
close_line = true;
|
new_line_status = max(new_line_status, LineStatus::SPAN);
|
||||||
cur_word_space = new_word_space;
|
cur_word_space = new_word_space;
|
||||||
cur_ws_id = install_word_space(cur_word_space * draw_scale);
|
cur_ws_id = install_word_space(cur_word_space * draw_scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO, we may use nested span if only color is changed
|
|
||||||
|
|
||||||
// color
|
// color
|
||||||
if(all_changed || color_changed)
|
if(all_changed || color_changed)
|
||||||
{
|
{
|
||||||
@ -214,17 +218,103 @@ void HTMLRenderer::check_state_change(GfxState * state)
|
|||||||
state->getFillRGB(&new_color);
|
state->getFillRGB(&new_color);
|
||||||
if(!((new_color.r == cur_color.r) && (new_color.g == cur_color.g) && (new_color.b == cur_color.b)))
|
if(!((new_color.r == cur_color.r) && (new_color.g == cur_color.g) && (new_color.b == cur_color.b)))
|
||||||
{
|
{
|
||||||
close_line = true;
|
new_line_status = max(new_line_status, LineStatus::SPAN);
|
||||||
cur_color = new_color;
|
cur_color = new_color;
|
||||||
cur_color_id = install_color(&new_color);
|
cur_color_id = install_color(&new_color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prepare_line();
|
||||||
|
|
||||||
|
// TODO: move the following to prepare_line ??
|
||||||
|
if(line_status == LineStatus::NONE)
|
||||||
|
{
|
||||||
|
new_line_status = LineStatus::DIV;
|
||||||
|
|
||||||
|
//resync position
|
||||||
|
draw_ty = cur_ty + cur_rise;
|
||||||
|
draw_tx = cur_tx;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(new_line_status != LineStatus::DIV);
|
||||||
|
|
||||||
|
// horizontal position
|
||||||
|
// try to merge with the last line if possible
|
||||||
|
double target = (cur_tx - draw_tx) * draw_scale;
|
||||||
|
if(abs(target) < param->h_eps)
|
||||||
|
{
|
||||||
|
// ignore it
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// don't close a pending span here, keep the styling
|
||||||
|
|
||||||
|
if(target > param->h_eps)
|
||||||
|
{
|
||||||
|
double w;
|
||||||
|
auto wid = install_whitespace(target, w);
|
||||||
|
html_fout << format("<span class=\"_ _%|1$x|\"> </span>") % wid;
|
||||||
|
draw_tx += w / draw_scale;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// shift left
|
||||||
|
// TODO, create a class for this
|
||||||
|
html_fout << format("<span style=\"margin-left:%1%px\"></span>") % target;
|
||||||
|
draw_tx += target / draw_scale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(new_line_status != LineStatus::NONE)
|
||||||
|
{
|
||||||
|
// have to open a new tag
|
||||||
|
|
||||||
|
if(new_line_status == LineStatus::SPAN)
|
||||||
|
{
|
||||||
|
html_fout << "<span class=\"";
|
||||||
|
}
|
||||||
|
else if (new_line_status == LineStatus::DIV)
|
||||||
|
{
|
||||||
|
// TODO: recheck descent/ascent
|
||||||
|
double x,y; // in user space
|
||||||
|
state->transform(state->getCurX(), state->getCurY(), &x, &y);
|
||||||
|
|
||||||
|
html_fout << format("<div style=\"bottom:%1%px;top:%2%px;left:%3%px;\" class=\"l ")
|
||||||
|
% (y + state->getFont()->getDescent() * draw_font_size)
|
||||||
|
% (pageHeight - y - state->getFont()->getAscent() * draw_font_size)
|
||||||
|
% x;
|
||||||
|
|
||||||
|
// "t0" is the id_matrix
|
||||||
|
if(cur_tm_id != 0)
|
||||||
|
html_fout << format("t%|1$x| ") % cur_tm_id;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(false && "Bad value of new_line_status");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: only show changed styles for <span>
|
||||||
|
html_fout << format("f%|1$x| s%|2$x| c%|3$x|") % cur_fn_id % cur_fs_id % cur_color_id;
|
||||||
|
|
||||||
|
|
||||||
|
if(cur_ls_id != 0)
|
||||||
|
html_fout << format(" l%|1$x|") % cur_ls_id;
|
||||||
|
|
||||||
|
if(cur_ws_id != 0)
|
||||||
|
html_fout << format(" w%|1$x|") % cur_ws_id;
|
||||||
|
|
||||||
|
html_fout << "\">";
|
||||||
|
|
||||||
|
line_status = new_line_status;
|
||||||
|
}
|
||||||
|
|
||||||
reset_state_track();
|
reset_state_track();
|
||||||
|
|
||||||
if(close_line)
|
|
||||||
close_cur_line();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTMLRenderer::reset_state_track()
|
void HTMLRenderer::reset_state_track()
|
||||||
{
|
{
|
||||||
all_changed = false;
|
all_changed = false;
|
||||||
@ -242,24 +332,32 @@ void HTMLRenderer::reset_state_track()
|
|||||||
|
|
||||||
color_changed = false;
|
color_changed = false;
|
||||||
}
|
}
|
||||||
void HTMLRenderer::close_cur_line()
|
void HTMLRenderer::prepare_line()
|
||||||
{
|
{
|
||||||
switch(line_status)
|
if((line_status == LineStatus::NONE) || (new_line_status == LineStatus::NONE))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(new_line_status == LineStatus::DIV)
|
||||||
{
|
{
|
||||||
case LineStatus::SPAN:
|
close_line();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(new_line_status == LineStatus::SPAN);
|
||||||
|
if(line_status == LineStatus::SPAN)
|
||||||
html_fout << "</span>";
|
html_fout << "</span>";
|
||||||
// fall through
|
else
|
||||||
case LineStatus::DIV:
|
assert(line_status == LineStatus::DIV);
|
||||||
html_fout << "</div>" << endl;
|
// don't change line_status
|
||||||
line_status = LineStatus::CLOSED;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LineStatus::CLOSED:
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
draw_ty = cur_ty + cur_rise;
|
|
||||||
draw_tx = cur_tx;
|
|
||||||
}
|
}
|
||||||
|
void HTMLRenderer::close_line()
|
||||||
|
{
|
||||||
|
if(line_status == LineStatus::SPAN)
|
||||||
|
html_fout << "</span>";
|
||||||
|
else
|
||||||
|
assert(line_status == LineStatus::DIV);
|
||||||
|
|
||||||
|
html_fout << "</div>";
|
||||||
|
line_status = LineStatus::NONE;
|
||||||
|
}
|
||||||
|
@ -156,80 +156,6 @@ void HTMLRenderer::drawString(GfxState * state, GooString * s)
|
|||||||
// see if the line has to be closed due to state change
|
// see if the line has to be closed due to state change
|
||||||
check_state_change(state);
|
check_state_change(state);
|
||||||
|
|
||||||
// if the line is still open, try to merge with it
|
|
||||||
if(line_status != LineStatus::CLOSED)
|
|
||||||
{
|
|
||||||
double target = (cur_tx - draw_tx) * draw_scale;
|
|
||||||
if(abs(target) < param->h_eps)
|
|
||||||
{
|
|
||||||
// ignore it
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// don't close a pending span here, keep the styling
|
|
||||||
|
|
||||||
if(target > param->h_eps)
|
|
||||||
{
|
|
||||||
double w;
|
|
||||||
auto wid = install_whitespace(target, w);
|
|
||||||
html_fout << format("<span class=\"_ _%|1$x|\"> </span>") % wid;
|
|
||||||
draw_tx += w / draw_scale;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// shift left
|
|
||||||
// TODO, create a class for this
|
|
||||||
html_fout << format("<span style=\"margin-left:%1%px\"></span>") % target;
|
|
||||||
draw_tx += target / draw_scale;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// have to open a new line
|
|
||||||
|
|
||||||
// classes
|
|
||||||
html_fout << "<div class=\"l "
|
|
||||||
<< format("f%|1$x| s%|2$x| c%|3$x|") % cur_fn_id % cur_fs_id % cur_color_id;
|
|
||||||
|
|
||||||
// "t0" is the id_matrix
|
|
||||||
if(cur_tm_id != 0)
|
|
||||||
html_fout << format(" t%|1$x|") % cur_tm_id;
|
|
||||||
|
|
||||||
if(cur_ls_id != 0)
|
|
||||||
html_fout << format(" l%|1$x|") % cur_ls_id;
|
|
||||||
|
|
||||||
if(cur_ws_id != 0)
|
|
||||||
html_fout << format(" w%|1$x|") % cur_ws_id;
|
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
double x,y; // in user space
|
|
||||||
state->transform(state->getCurX(), state->getCurY(), &x, &y);
|
|
||||||
// TODO: recheck descent/ascent
|
|
||||||
html_fout << "\" style=\""
|
|
||||||
<< "bottom:" << (y + state->getFont()->getDescent() * draw_font_size) << "px;"
|
|
||||||
<< "top:" << (pageHeight - y - state->getFont()->getAscent() * draw_font_size) << "px;"
|
|
||||||
<< "left:" << x << "px;"
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
//debug
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
html_fout << "\"";
|
|
||||||
double x,y;
|
|
||||||
state->transform(state->getCurX(), state->getCurY(), &x, &y);
|
|
||||||
html_fout << format("data-lx=\"%5%\" data-ly=\"%6%\" data-draw-x=\"%7%\" data-draw-y=\"%8%\" data-drawscale=\"%4%\" data-x=\"%1%\" data-y=\"%2%\" data-hs=\"%3%")
|
|
||||||
%x%y%(state->getHorizScaling())%draw_scale%state->getLineX()%state->getLineY()%draw_tx%draw_ty;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
html_fout << "\">";
|
|
||||||
|
|
||||||
line_status = LineStatus::DIV;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now ready to output
|
// Now ready to output
|
||||||
// get the unicodes
|
// get the unicodes
|
||||||
char *p = s->getCString();
|
char *p = s->getCString();
|
||||||
|
Loading…
Reference in New Issue
Block a user