From 4858f12d9b67766c0185f0f45545690aa1818aaa Mon Sep 17 00:00:00 2001 From: Lu Wang Date: Tue, 5 Feb 2013 13:57:11 +0800 Subject: [PATCH] letter_space_tracker --- src/HTMLRenderer/HTMLRenderer.h | 7 +- src/HTMLRenderer/TextLineBuffer.cc | 2 +- src/HTMLRenderer/export.cc | 5 -- src/HTMLRenderer/general.cc | 5 ++ src/HTMLRenderer/install.cc | 12 ---- src/HTMLRenderer/state.cc | 16 ++--- src/HTMLRenderer/text.cc | 1 + src/{HTMLRenderer => util}/StateTracker.h | 85 +++++++++-------------- 8 files changed, 47 insertions(+), 86 deletions(-) rename src/{HTMLRenderer => util}/StateTracker.h (59%) diff --git a/src/HTMLRenderer/HTMLRenderer.h b/src/HTMLRenderer/HTMLRenderer.h index b70f6db..aa9c5d0 100644 --- a/src/HTMLRenderer/HTMLRenderer.h +++ b/src/HTMLRenderer/HTMLRenderer.h @@ -30,6 +30,7 @@ #include "util/StringFormatter.h" #include "util/TmpFiles.h" #include "util/misc.h" +#include "util/StateTracker.h" /* * Naming Convention @@ -197,7 +198,6 @@ class HTMLRenderer : public OutputDev long long install_font_size(double font_size); long long install_transform_matrix(const double * tm); - long long install_letter_space(double letter_space); long long install_word_space(double word_space); long long install_fill_color(const GfxRGB * rgb); long long install_stroke_color(const GfxRGB * rgb); @@ -219,7 +219,6 @@ class HTMLRenderer : public OutputDev void export_font_size(long long fs_id, double font_size); void export_transform_matrix(long long tm_id, const double * tm); - void export_letter_space(long long ls_id, double letter_space); void export_word_space(long long ws_id, double word_space); void export_fill_color(long long color_id, const GfxRGB * rgb); void export_stroke_color(long long color_id, const GfxRGB * rgb); @@ -334,9 +333,8 @@ class HTMLRenderer : public OutputDev double cur_text_tm[6]; // unscaled // letter spacing - long long cur_ls_id; - double cur_letter_space; bool letter_space_changed; + LetterSpaceTracker letter_space_tracker; // word spacing long long cur_ws_id; @@ -399,7 +397,6 @@ class HTMLRenderer : public OutputDev std::unordered_map font_name_map; std::map font_size_map; std::map transform_matrix_map; - std::map letter_space_map; std::map word_space_map; std::unordered_map fill_color_map, stroke_color_map; std::map whitespace_map; diff --git a/src/HTMLRenderer/TextLineBuffer.cc b/src/HTMLRenderer/TextLineBuffer.cc index e85f088..d4308c0 100644 --- a/src/HTMLRenderer/TextLineBuffer.cc +++ b/src/HTMLRenderer/TextLineBuffer.cc @@ -189,7 +189,7 @@ void HTMLRenderer::TextLineBuffer::set_state (State & state) state.ids[State::FONT_SIZE_ID] = renderer->cur_fs_id; state.ids[State::FILL_COLOR_ID] = renderer->cur_fill_color_id; state.ids[State::STROKE_COLOR_ID] = renderer->cur_stroke_color_id; - state.ids[State::LETTER_SPACE_ID] = renderer->cur_ls_id; + state.ids[State::LETTER_SPACE_ID] = renderer->letter_space_tracker.get_id(); state.ids[State::WORD_SPACE_ID] = renderer->cur_ws_id; state.ids[State::RISE_ID] = renderer->cur_rise_id; diff --git a/src/HTMLRenderer/export.cc b/src/HTMLRenderer/export.cc index 292a3a6..6347d3d 100644 --- a/src/HTMLRenderer/export.cc +++ b/src/HTMLRenderer/export.cc @@ -168,11 +168,6 @@ void HTMLRenderer::export_transform_matrix (long long tm_id, const double * tm) f_css.fs << "}" << endl; } -void HTMLRenderer::export_letter_space (long long ls_id, double letter_space) -{ - f_css.fs << ".l" << ls_id << "{letter-spacing:" << round(letter_space) << "px;}" << endl; -} - void HTMLRenderer::export_word_space (long long ws_id, double word_space) { f_css.fs << ".w" << ws_id << "{word-spacing:" << round(word_space) << "px;}" << endl; diff --git a/src/HTMLRenderer/general.cc b/src/HTMLRenderer/general.cc index fcc03ba..299947d 100644 --- a/src/HTMLRenderer/general.cc +++ b/src/HTMLRenderer/general.cc @@ -55,6 +55,8 @@ HTMLRenderer::HTMLRenderer(const Param * param) cur_mapping = new int32_t [0x10000]; cur_mapping2 = new char* [0x100]; width_list = new int [0x10000]; + + letter_space_tracker.set_param("l", EPS); } HTMLRenderer::~HTMLRenderer() @@ -331,6 +333,9 @@ void HTMLRenderer::pre_process(PDFDoc * doc) void HTMLRenderer::post_process() { + // dump css + letter_space_tracker.dump_css(f_css.fs); + // close files f_outline.fs.close(); f_pages.fs.close(); diff --git a/src/HTMLRenderer/install.cc b/src/HTMLRenderer/install.cc index 8a62aa5..51aaf74 100644 --- a/src/HTMLRenderer/install.cc +++ b/src/HTMLRenderer/install.cc @@ -240,18 +240,6 @@ long long HTMLRenderer::install_transform_matrix(const double * tm) return new_tm_id; } -long long HTMLRenderer::install_letter_space(double letter_space) -{ - auto iter = letter_space_map.lower_bound(letter_space - EPS); - if((iter != letter_space_map.end()) && (equal(iter->first, letter_space))) - return iter->second; - - long long new_ls_id = letter_space_map.size(); - letter_space_map.insert(make_pair(letter_space, new_ls_id)); - export_letter_space(new_ls_id, letter_space); - return new_ls_id; -} - long long HTMLRenderer::install_word_space(double word_space) { auto iter = word_space_map.lower_bound(word_space - EPS); diff --git a/src/HTMLRenderer/state.cc b/src/HTMLRenderer/state.cc index 3ff5632..87c1c79 100644 --- a/src/HTMLRenderer/state.cc +++ b/src/HTMLRenderer/state.cc @@ -104,8 +104,9 @@ void HTMLRenderer::reset_state() memcpy(draw_text_tm, ID_MATRIX, sizeof(draw_text_tm)); cur_ttm_id = install_transform_matrix(draw_text_tm); - cur_letter_space = cur_word_space = 0; - cur_ls_id = install_letter_space(cur_letter_space); + letter_space_tracker.reset(); + + cur_word_space = 0; cur_ws_id = install_word_space(cur_word_space); cur_fill_color.r = cur_fill_color.g = cur_fill_color.b = 0; @@ -339,15 +340,10 @@ void HTMLRenderer::check_state_change(GfxState * state) // letter space // depends: draw_text_scale - if(all_changed || letter_space_changed || draw_text_scale_changed) + if((all_changed || letter_space_changed || draw_text_scale_changed) + && (letter_space_tracker.install(state->getCharSpace() * draw_text_scale))) { - double new_letter_space = state->getCharSpace(); - if(!equal(cur_letter_space, new_letter_space)) - { - new_line_state = max(new_line_state, NLS_SPAN); - cur_letter_space = new_letter_space; - cur_ls_id = install_letter_space(cur_letter_space * draw_text_scale); - } + new_line_state = max(new_line_state, NLS_SPAN); } // word space diff --git a/src/HTMLRenderer/text.cc b/src/HTMLRenderer/text.cc index a4cf58f..126c29c 100644 --- a/src/HTMLRenderer/text.cc +++ b/src/HTMLRenderer/text.cc @@ -504,6 +504,7 @@ void HTMLRenderer::drawString(GfxState * state, GooString * s) return; auto font = state->getFont(); + double cur_letter_space = state->getCharSpace(); // Writing mode fonts and Type 3 fonts are rendered as images // I don't find a way to display writing mode fonts in HTML except for one div for each character, which is too costly diff --git a/src/HTMLRenderer/StateTracker.h b/src/util/StateTracker.h similarity index 59% rename from src/HTMLRenderer/StateTracker.h rename to src/util/StateTracker.h index 7dfe6fd..dea5582 100644 --- a/src/HTMLRenderer/StateTracker.h +++ b/src/util/StateTracker.h @@ -13,7 +13,7 @@ #include #include -#include +#include "util/math.h" namespace pdf2htmlEX { @@ -25,8 +25,7 @@ class StateTracker public: StateTracker() : eps(0) - , changed(false) - , imp(static_cast(this)) + , imp(static_cast(this)) { reset(); } @@ -38,49 +37,26 @@ public: } // usually called at the beginning of a page - void reset(void) { value = imp->default_value(); } + void reset(void) { + value = imp->default_value(); + _install(value); + } - // 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 + * install new_value if changed (equal() should be faster than map::lower_bound) * return if the state has been indeed changed */ - bool sync(GfxState * state, bool force) { - if(!(changed || force)) - return false; - - changed = false; - - double new_value = imp->get_value(state); + bool install(double new_value) { if(equal(new_value, value)) return false; - - install(new_value); - return true; + return _install(new_value); } - + + long long get_id (void) const { return id; } double get_actual_value (void) const { return actual_value; } - - 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)); - - return new_id; - } void dump_css(std::ostream & out) { - for(auto iter = map.begin(); iter != map.end(); ++iter) + for(auto iter = value_map.begin(); iter != value_map.end(); ++iter) { out << "." << css_class_name << iter->second << "{"; imp->dump_value(out, iter->first); @@ -89,9 +65,26 @@ public: } protected: + // this version of install does not check if value has been updated + bool _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; + id = iter->second; + return false; + } + + actual_value = new_value; + id = value_map.size(); + value_map.insert(std::make_pair(new_value, id)); + return true; + } + const char * css_class_name; double eps; - bool changed; Imp * imp; long long id; @@ -105,8 +98,7 @@ class FontSizeTracker : public StateTracker public: double default_value(void) { return 0; } double get_value(GfxState * state) { return state->getFontSize(); } - void dump_value(std::ostream & out, double value) { out "font-size:" << round(value) << "px;"; } - } + void dump_value(std::ostream & out, double value) { out << "font-size:" << round(value) << "px;"; } }; class LetterSpaceTracker : public StateTracker @@ -114,22 +106,9 @@ class LetterSpaceTracker : public StateTracker public: double default_value(void) { return 0; } double get_value(GfxState * state) { return state->getCharSpace(); } - void dump_value(std::ostream & out, double value) { out "font-size:" << round(value) << "px;"; } - } + void dump_value(std::ostream & out, double value) { out << "letter-spacing:" << round(value) << "px;"; } }; - - - std::map transform_matrix_map; - std::map letter_space_map; - std::map word_space_map; - std::unordered_map fill_color_map, stroke_color_map; - std::map whitespace_map; - std::map rise_map; - std::map height_map; - std::map left_map; - - } // namespace pdf2htmlEX #endif //STATETRACKER_H__