diff --git a/src/HTMLRenderer/StateTracker.h b/src/HTMLRenderer/StateTracker.h index b7ab404..35a38d8 100644 --- a/src/HTMLRenderer/StateTracker.h +++ b/src/HTMLRenderer/StateTracker.h @@ -7,44 +7,84 @@ * Copyright (C) 2013 Lu Wang */ -#ifndef STATE_TRACKER_H__ -#define STATE_TRACKER_H__ +#ifndef STATETRACKER_H__ +#define STATETRACKER_H__ + +#include #include - namespace pdf2htmlEX { -class StateTrackerBase +template class StateTracker {}; + +template +class StateTracker { public: - virtual ~StateTracker(void); + // values no father than eps are treated as equal + StateTracker(const char * css_class_prefix, double eps) + : css_class_prefix(css_class_prefix) + , eps(eps) + , changed(false) + , imp(static_cast(this)) + { } // usually called at the beginning of a page - virtual void reset(void) = 0; - /* - * update() is called when PDF updates the state - * check_state() is called when we really need the new state - * - * There could be a number of calls to update() between 2 consecutive calls to check_state() - * So usually we just mark as changed in update, and actually retrive from the state in check_state() - */ - virtual void update(GfxState * state) = 0; - /* - * return if state has been updated - * - * if force is true, do check the state if there is no update() called before - * useful for updateAll - */ - virtual bool check_state(GfxState * state, bool force) = 0; + void reset(void) { imp->reset(); } - long long get_id() const { return id; } + // is called when PDF updates the state + void update(GfxState * state) { changed = true; } + /* + * retrive the new state if update() is called recently, or force == true + * return if the state has been indeed changed + */ + bool sync(GfxState * state, bool force)| { + if(!(changed || force)) + return false; -protected: - long long id; // For CSS classe + changed = false; + + double new_value = imp->get_value(state); + if(equal(new_value, value)) + return false; + + install(new_value); + return true; + } + + + long long install(double new_value) { + value = new_value; + + auto iter = value_map.lower_bound(new_value - eps); + if((iter != value_map.end()) && (abs(iter->first - value) <= eps)) { + actual_value = iter->first; + return iter->second; + } + + actual_value = new_value; + long long new_id = map.size(); + map.insert(make_pair(new_value, new_id)); + + imp->create(new_id, new_value); + + return new_id; + } +private: + const char * css_class_prefix; + const double eps; + bool changed; + Imp * imp; + + + long long id; + double value; // the value we are tracking + double actual_value; // the value we actually exported to HTML + std::map value_map; }; } // namespace pdf2htmlEX -#endif //STATE_TRACKER_H__ +#endif //STATETRACKER_H__ diff --git a/src/HTMLRenderer/state.cc b/src/HTMLRenderer/state.cc index 9aec231..4542c0e 100644 --- a/src/HTMLRenderer/state.cc +++ b/src/HTMLRenderer/state.cc @@ -168,9 +168,9 @@ void HTMLRenderer::check_state_change(GfxState * state) if(!(new_font_info->id == cur_font_info->id)) { - // Currently Type 3 font are shown hidden in HTML, with default fonts (at viewers' machine) - // The width of the text displayed is likely to be wrong + // The width of the type 3 font text, if shown, is likely to be wrong // So we will create separate (absolute positioned) blocks for them, such that it won't affect other text + // TODO: consider the font matrix and estimate the metrics if(new_font_info->is_type3 || cur_font_info->is_type3) { new_line_state = max(new_line_state, NLS_DIV);