1
0
mirror of https://github.com/pdf2htmlEX/pdf2htmlEX.git synced 2024-12-22 04:50:09 +00:00

transform matrix manager

This commit is contained in:
Lu Wang 2013-02-05 20:27:29 +08:00
parent 6c33d431c6
commit 8e24776124
8 changed files with 138 additions and 95 deletions

View File

@ -164,7 +164,6 @@ class HTMLRenderer : public OutputDev
void install_base_font(GfxFont * font, GfxFontLoc * font_loc, FontInfo & info);
void install_external_font (GfxFont * font, FontInfo & info);
long long install_transform_matrix(const double * tm);
long long install_fill_color(const GfxRGB * rgb);
long long install_stroke_color(const GfxRGB * rgb);
@ -179,7 +178,6 @@ class HTMLRenderer : public OutputDev
void export_remote_default_font(long long fn_id);
void export_local_font(const FontInfo & info, GfxFont * font, const std::string & original_font_name, const std::string & cssfont);
void export_transform_matrix(long long tm_id, const double * tm);
void export_fill_color(long long color_id, const GfxRGB * rgb);
void export_stroke_color(long long color_id, const GfxRGB * rgb);
@ -277,7 +275,6 @@ class HTMLRenderer : public OutputDev
// cur_font_size is as in GfxState,
// font_size_manager saves the final font size used in HTML
double cur_font_size;
FontSizeManager font_size_manager;
// transform matrix
long long cur_ttm_id;
@ -292,11 +289,7 @@ class HTMLRenderer : public OutputDev
// letter spacing
bool letter_space_changed;
LetterSpaceManager letter_space_manager;
// word spacing
bool word_space_changed;
WordSpaceManager word_space_manager;
// fill color
long long cur_fill_color_id;
@ -309,22 +302,24 @@ class HTMLRenderer : public OutputDev
GfxRGB cur_stroke_color;
bool cur_has_stroke;
bool stroke_color_changed;
// rise
bool rise_changed;
RiseManager rise_manager;
// managers store values actually used in HTML (i.e. scaled)
FontSizeManager font_size_manager;
LetterSpaceManager letter_space_manager;
WordSpaceManager word_space_manager;
RiseManager rise_manager;
WhitespaceManager whitespace_manager;
HeightManager height_manager;
LeftManager left_manager;
TransformMatrixManager transform_matrix_manager;
// optimize for web
// we try to render the final font size directly
// to reduce the effect of ctm as much as possible
// draw_text_tm is cur_text_tm scaled by 1/draw_text_scale,
// the actual tm used is `real tm in PDF` scaled by 1/draw_text_scale,
// so everything redenered should be multiplied by draw_text_scale
double draw_text_tm[6];
double draw_text_scale;
// the position of next char, in text coords
@ -354,7 +349,6 @@ class HTMLRenderer : public OutputDev
////////////////////////////////////////////////////
std::unordered_map<long long, FontInfo> font_name_map;
std::map<Matrix, long long, Matrix_less> transform_matrix_map;
std::unordered_map<GfxRGB, long long, GfxRGB_hash, GfxRGB_equal> fill_color_map, stroke_color_map;
const Param * param;

View File

@ -372,7 +372,10 @@ void HTMLRenderer::css_draw_rectangle(double x, double y, double w, double h, co
}
}
f_pages.fs << "<div class=\"Cd t" << install_transform_matrix(new_tm) << "\" style=\"";
transform_matrix_manager.install(new_tm);
f_pages.fs << "<div class=\"" << CSS::CSS_DRAW_CN
<< ' ' << CSS::TRANSFORM_MATRIX_CN << transform_matrix_manager.get_id()
<< "\" style=\"";
if(line_color)
{

View File

@ -130,39 +130,6 @@ void HTMLRenderer::export_local_font(const FontInfo & info, GfxFont * font, cons
f_css.fs << "}" << endl;
}
void HTMLRenderer::export_transform_matrix (long long tm_id, const double * tm)
{
f_css.fs << ".t" << tm_id << "{";
// always ignore tm[4] and tm[5] because
// we have already shifted the origin
// TODO: recognize common matices
if(tm_equal(tm, ID_MATRIX, 4))
{
auto prefixes = {"", "-ms-", "-moz-", "-webkit-", "-o-"};
for(auto iter = prefixes.begin(); iter != prefixes.end(); ++iter)
f_css.fs << *iter << "transform:none;";
}
else
{
auto prefixes = {"", "-ms-", "-moz-", "-webkit-", "-o-"};
for(auto iter = prefixes.begin(); iter != prefixes.end(); ++iter)
{
// PDF use a different coordinate system from Web
f_css.fs << *iter << "transform:matrix("
<< round(tm[0]) << ','
<< round(-tm[1]) << ','
<< round(-tm[2]) << ','
<< round(tm[3]) << ',';
f_css.fs << "0,0);";
}
}
f_css.fs << "}" << endl;
}
void HTMLRenderer::export_fill_color (long long color_id, const GfxRGB * rgb)
{
f_css.fs << ".c" << color_id << "{color:" << *rgb << ";}" << endl;

View File

@ -212,21 +212,6 @@ void HTMLRenderer::install_external_font(GfxFont * font, FontInfo & info)
export_local_font(info, font, fontname, "");
}
long long HTMLRenderer::install_transform_matrix(const double * tm)
{
Matrix m;
memcpy(m.m, tm, sizeof(m.m));
auto iter = transform_matrix_map.lower_bound(m);
if((iter != transform_matrix_map.end()) && (tm_equal(m.m, iter->first.m, 4)))
return iter->second;
long long new_tm_id = transform_matrix_map.size();
transform_matrix_map.insert(make_pair(m, new_tm_id));
export_transform_matrix(new_tm_id, tm);
return new_tm_id;
}
long long HTMLRenderer::install_fill_color(const GfxRGB * rgb)
{
// transparent

View File

@ -193,7 +193,7 @@ void HTMLRenderer::processLink(AnnotLink * al)
if(!dest_str.empty())
{
f_pages.fs << "<a class=\"" << CSS::LINE_CN << "\" href=\"" << dest_str << "\"";
f_pages.fs << "<a class=\"" << CSS::LINK_CN << "\" href=\"" << dest_str << "\"";
if(!dest_detail_str.empty())
f_pages.fs << " data-dest-detail='" << dest_detail_str << "'";
@ -201,8 +201,9 @@ void HTMLRenderer::processLink(AnnotLink * al)
f_pages.fs << ">";
}
transform_matrix_manager.install(default_ctm);
f_pages.fs << "<div class=\"" << CSS::CSS_DRAW_CN << ' ' << CSS::TRANSFORM_MATRIX_CN
<< install_transform_matrix(default_ctm)
<< transform_matrix_manager.get_id()
<< "\" style=\"";
double x,y,w,h;

View File

@ -102,9 +102,8 @@ void HTMLRenderer::reset_state()
font_size_manager.reset();
memcpy(cur_text_tm, ID_MATRIX, sizeof(cur_text_tm));
memcpy(draw_text_tm, ID_MATRIX, sizeof(draw_text_tm));
cur_ttm_id = install_transform_matrix(draw_text_tm);
transform_matrix_manager.reset();
letter_space_manager .reset();
word_space_manager .reset();
@ -269,11 +268,9 @@ void HTMLRenderer::check_state_change(GfxState * state)
{
new_line_state = max<NewLineState>(new_line_state, NLS_SPAN);
}
if(!(tm_equal(new_draw_text_tm, draw_text_tm, 4)))
if(transform_matrix_manager.install(new_draw_text_tm))
{
new_line_state = max<NewLineState>(new_line_state, NLS_DIV);
memcpy(draw_text_tm, new_draw_text_tm, sizeof(draw_text_tm));
cur_ttm_id = install_transform_matrix(draw_text_tm);
}
}

View File

@ -37,8 +37,7 @@ public:
// usually called at the beginning of a page
void reset(void) {
value = imp->default_value();
_install(value);
_install(imp->default_value());
}
/*
@ -79,9 +78,8 @@ protected:
return false;
}
actual_value = new_value;
id = value_map.size();
value_map.insert(std::make_pair(new_value, id));
actual_value = value_map.insert(std::make_pair(new_value, id)).first->first;
return true;
}
@ -94,6 +92,88 @@ protected:
std::map<double, long long> value_map;
};
// Be careful about the mixed usage of Matrix and const double *
template <class Imp>
class StateManager<Matrix, Imp>
{
public:
StateManager()
: imp(static_cast<Imp*>(this))
{ }
void reset(void) {
_install(imp->default_value());
}
// return if changed
bool install(const double * new_value) {
// For a transform matrix m
// m[4] & m[5] have been taken care of
if(tm_equal(new_value, value.m, 4))
return false;
_install(new_value);
return true;
}
long long get_id (void) const { return id; }
const Matrix & get_value (void) const { return value; }
const Matrix & get_actual_value (void) const { return *actual_value; }
void dump_css(std::ostream & out) {
for(auto iter = value_map.begin(); iter != value_map.end(); ++iter)
{
out << "." << imp->get_css_class_name() << iter->second << "{";
imp->dump_value(out, iter->first);
out << "}" << std::endl;
}
}
protected:
// return if a new entry has been created
bool _install(const double * new_value) {
memcpy(value.m, new_value, sizeof(value.m));
auto iter = value_map.lower_bound(value);
if((iter != value_map.end()) && (tm_equal(value.m, iter->first.m, 4)))
{
actual_value = &(iter->first);
id = iter->second;
return false;
}
id = value_map.size();
actual_value = &(value_map.insert(std::make_pair(value, id)).first->first);
return true;
}
Imp * imp;
long long id;
Matrix value;
const Matrix * actual_value;
class Matrix_less
{
public:
bool operator () (const Matrix & m1, const Matrix & m2) const
{
// Note that we only care about the first 4 elements
for(int i = 0; i < 4; ++i)
{
if(m1.m[i] < m2.m[i] - EPS)
return true;
if(m1.m[i] > m2.m[i] + EPS)
return false;
}
return false;
}
};
std::map<Matrix, long long, Matrix_less> value_map;
};
/////////////////////////////////////
// Specific state managers
class FontSizeManager : public StateManager<double, FontSizeManager>
{
public:
@ -154,6 +234,39 @@ public:
void dump_value(std::ostream & out, double value) { out << "left:" << round(value) << "px;"; }
};
class TransformMatrixManager : public StateManager<Matrix, TransformMatrixManager>
{
public:
static const char * get_css_class_name (void) { return CSS::TRANSFORM_MATRIX_CN; }
const double * default_value(void) { return ID_MATRIX; }
void dump_value(std::ostream & out, const Matrix & matrix) {
// always ignore tm[4] and tm[5] because
// we have already shifted the origin
// TODO: recognize common matices
const auto & m = matrix.m;
if(tm_equal(m, ID_MATRIX, 4))
{
auto prefixes = {"", "-ms-", "-moz-", "-webkit-", "-o-"};
for(auto iter = prefixes.begin(); iter != prefixes.end(); ++iter)
out << *iter << "transform:none;";
}
else
{
auto prefixes = {"", "-ms-", "-moz-", "-webkit-", "-o-"};
for(auto iter = prefixes.begin(); iter != prefixes.end(); ++iter)
{
// PDF use a different coordinate system from Web
out << *iter << "transform:matrix("
<< round(m[0]) << ','
<< round(-m[1]) << ','
<< round(-m[2]) << ','
<< round(m[3]) << ',';
out << "0,0);";
}
}
}
};
} // namespace pdf2htmlEX
#endif //STATEMANAGER_H__

View File

@ -55,23 +55,6 @@ public:
}
};
class Matrix_less
{
public:
bool operator () (const Matrix & m1, const Matrix & m2) const
{
// Note that we only care about the first 4 elements
for(int i = 0; i < 4; ++i)
{
if(m1.m[i] < m2.m[i] - EPS)
return true;
if(m1.m[i] > m2.m[i] + EPS)
return false;
}
return false;
}
};
} // namespace pdf2htmlEX