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
diff --git a/src/HTMLRenderer/link.cc b/src/HTMLRenderer/link.cc
index 510baaa..225f7ac 100644
--- a/src/HTMLRenderer/link.cc
+++ b/src/HTMLRenderer/link.cc
@@ -193,7 +193,7 @@ void HTMLRenderer::processLink(AnnotLink * al)
if(!dest_str.empty())
{
- f_pages.fs << "
";
}
+ transform_matrix_manager.install(default_ctm);
f_pages.fs << "(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(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);
}
}
diff --git a/src/util/StateManager.h b/src/util/StateManager.h
index e210ae1..f15459a 100644
--- a/src/util/StateManager.h
+++ b/src/util/StateManager.h
@@ -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 value_map;
};
+// Be careful about the mixed usage of Matrix and const double *
+template
+class StateManager
+{
+public:
+ StateManager()
+ : imp(static_cast(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 value_map;
+};
+
+/////////////////////////////////////
+// Specific state managers
+
class FontSizeManager : public StateManager
{
public:
@@ -154,6 +234,39 @@ public:
void dump_value(std::ostream & out, double value) { out << "left:" << round(value) << "px;"; }
};
+class TransformMatrixManager : public StateManager
+{
+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__
diff --git a/src/util/misc.h b/src/util/misc.h
index 3500bf7..19ce66e 100644
--- a/src/util/misc.h
+++ b/src/util/misc.h
@@ -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