
* scribo/scribo/core/component_info.hh: Remove useless line_id. * scribo/scribo/core/line_set.hh, * scribo/scribo/core/component_set.hh: Add new constructors. * scribo/scribo/core/document.hh: Store line separators. * scribo/scribo/core/line_info.hh: Share attributes and add new constructors. (is_textline): New method. * scribo/scribo/core/line_links.hh: Do not allocate useless data. * scribo/scribo/core/paragraph_info.hh (operator<<): New. * scribo/scribo/core/paragraph_set.hh: Share attributes and add new constructors. --- scribo/ChangeLog | 22 ++ scribo/scribo/core/component_info.hh | 17 +-- scribo/scribo/core/component_set.hh | 65 +++++-- scribo/scribo/core/document.hh | 48 +++++- scribo/scribo/core/line_info.hh | 367 ++++++++++++++++++---------------- scribo/scribo/core/line_links.hh | 2 +- scribo/scribo/core/line_set.hh | 29 +++- scribo/scribo/core/paragraph_info.hh | 10 + scribo/scribo/core/paragraph_set.hh | 84 +++++++- 9 files changed, 425 insertions(+), 219 deletions(-) diff --git a/scribo/ChangeLog b/scribo/ChangeLog index e08f2fd..ab028c3 100644 --- a/scribo/ChangeLog +++ b/scribo/ChangeLog @@ -1,5 +1,27 @@ 2011-02-17 Guillaume Lazzara <z@lrde.epita.fr> + Various changes in scribo core structures. + + * scribo/scribo/core/component_info.hh: Remove useless line_id. + + * scribo/scribo/core/line_set.hh, + * scribo/scribo/core/component_set.hh: Add new constructors. + + * scribo/scribo/core/document.hh: Store line separators. + + * scribo/scribo/core/line_info.hh: Share attributes and add new + constructors. + (is_textline): New method. + + * scribo/scribo/core/line_links.hh: Do not allocate useless data. + + * scribo/scribo/core/paragraph_info.hh (operator<<): New. + + * scribo/scribo/core/paragraph_set.hh: Share attributes and add new + constructors. + +2011-02-17 Guillaume Lazzara <z@lrde.epita.fr> + Rename files in Scribo. * scribo/primitive/extract/elements.hh, diff --git a/scribo/scribo/core/component_info.hh b/scribo/scribo/core/component_info.hh index 4ed6db7..1b03318 100644 --- a/scribo/scribo/core/component_info.hh +++ b/scribo/scribo/core/component_info.hh @@ -47,7 +47,6 @@ namespace scribo class component_info { typedef mln::util::object_id<scribo::ComponentId, unsigned> component_id_t; - typedef mln::util::object_id<scribo::LineId, unsigned> line_id_t; public: component_info(); @@ -69,9 +68,6 @@ namespace scribo component::Type type() const; void update_type(component::Type type); - // The line it is rattached to. 0 means an invalid line. - line_id_t line_id() const; - bool is_valid() const; private: @@ -82,8 +78,6 @@ namespace scribo component::Tag tag_; component::Type type_; - - line_id_t line_id_; }; @@ -109,7 +103,7 @@ namespace scribo const mln::point2d& mass_center, unsigned card) : id_(id), bbox_(bbox), mass_center_(mass_center), card_(card), - tag_(component::None), type_(component::Undefined), line_id_(0) + tag_(component::None), type_(component::Undefined) { } @@ -179,14 +173,6 @@ namespace scribo inline - component_info::line_id_t - component_info::line_id() const - { - return line_id_; - } - - - inline bool component_info::is_valid() const { @@ -204,7 +190,6 @@ namespace scribo << ", mass_center=" << info.mass_center() << ", card=" << info.card() << ", tag=" << info.tag() - << ", line_id=" << info.line_id() << ")" << std::endl; } diff --git a/scribo/scribo/core/component_set.hh b/scribo/scribo/core/component_set.hh index 103826f..7ddcf16 100644 --- a/scribo/scribo/core/component_set.hh +++ b/scribo/scribo/core/component_set.hh @@ -1,5 +1,5 @@ -// Copyright (C) 2009, 2010 EPITA Research and Development Laboratory -// (LRDE) +// Copyright (C) 2009, 2010, 2011 EPITA Research and Development +// Laboratory (LRDE) // // This file is part of Olena. // @@ -55,6 +55,8 @@ # include <mln/core/routine/duplicate.hh> +# include <mln/value/next.hh> + # include <scribo/core/macros.hh> # include <scribo/core/component_info.hh> @@ -95,6 +97,8 @@ namespace scribo void fill_infos(const mln::util::array<pair_data_t>& attribs); + // Useful while constructing incrementaly (XML loading). + void soft_init(const mln_value(L) ncomps); L ima_; mln_value(L) ncomps_; @@ -128,6 +132,9 @@ namespace scribo /// Constructor without argument. component_set(); + // Constructor from internal data. + component_set(const mln::util::tracked_ptr<data_t>& data); + /// Constructor from an image \p ima and the number of labels \p ncomps. component_set(const L& ima, const mln_value(L)& ncomps); @@ -348,6 +355,19 @@ namespace scribo } + template <typename L> + inline + void + component_set_data<L>::soft_init(const mln_value(L) ncomps) + { + mln_precondition(infos_.nelements() == 0); + + ncomps_ = ncomps; + infos_.reserve(ncomps_); + infos_.append(component_info()); // Component 0, i.e. the background. + } + + } // end of namespace mln::internal @@ -361,6 +381,13 @@ namespace scribo template <typename L> inline + component_set<L>::component_set(const mln::util::tracked_ptr<data_t>& data) + { + data_ = data; + } + + template <typename L> + inline component_set<L>::component_set(const L& ima, const mln_value(L)& ncomps) { data_ = new internal::component_set_data<L>(ima, ncomps); @@ -400,7 +427,7 @@ namespace scribo const component_info& component_set<L>::info(const mln_value(L)& id) const { - return this->data_->infos_[id]; + return data_->infos_[id]; } template <typename L> @@ -408,7 +435,7 @@ namespace scribo component_info& component_set<L>::info(const mln_value(L)& id) { - return this->data_->infos_[id]; + return data_->infos_[id]; } // template <typename L> @@ -416,7 +443,7 @@ namespace scribo // const component_info& // component_set<L>::operator()(const mln_value(L)& id) const // { -// return this->data_->infos_[id]; +// return data_->infos_[id]; // } // template <typename L> @@ -424,7 +451,7 @@ namespace scribo // component_info& // component_set<L>::operator()(const mln_value(L)& id) // { -// return this->data_->infos_[id]; +// return data_->infos_[id]; // } template <typename L> @@ -432,7 +459,7 @@ namespace scribo const component_info& component_set<L>::operator()(const component_id_t& id) const { - return this->data_->infos_[id]; + return data_->infos_[id]; } template <typename L> @@ -440,7 +467,7 @@ namespace scribo component_info& component_set<L>::operator()(const component_id_t& id) { - return this->data_->infos_[id]; + return data_->infos_[id]; } @@ -476,7 +503,7 @@ namespace scribo const L& component_set<L>::labeled_image() const { - return this->data_->ima_; + return data_->ima_; } @@ -485,7 +512,7 @@ namespace scribo bool component_set<L>::is_valid() const { - return this->data_->ima_.is_valid(); + return data_ != 0 && data_->ima_.is_valid(); } @@ -503,7 +530,7 @@ namespace scribo L& component_set<L>::labeled_image_() { - return this->data_->ima_; + return data_->ima_; } @@ -512,7 +539,7 @@ namespace scribo mln_concrete(L) component_set<L>::valid_comps_image_() const { - mln::util::array<bool> f(mln::value::next(this->data_->ncomps_)); + mln::util::array<bool> f(mln::value::next(data_->ncomps_)); f(0) = true; for_all_comps(c, (*this)) @@ -520,8 +547,8 @@ namespace scribo mln_value(L) new_ncomps; mln_concrete(L) - output = mln::labeling::relabel(this->data_->ima_, - this->data_->ncomps_, + output = mln::labeling::relabel(data_->ima_, + data_->ncomps_, new_ncomps, f); @@ -534,7 +561,7 @@ namespace scribo bool component_set<L>::has_separators() const { - return this->data_->separators_.is_valid(); + return data_->separators_.is_valid(); } @@ -544,9 +571,9 @@ namespace scribo component_set<L>::add_separators(const mln_ch_value(L, bool)& ima) { if (! has_separators()) - this->data_->separators_ = ima; + data_->separators_ = ima; else - mln::logical::or_inplace(this->data_->separators_, ima); + mln::logical::or_inplace(data_->separators_, ima); } @@ -555,7 +582,7 @@ namespace scribo const mln_ch_value(L, bool)& component_set<L>::separators() const { - return this->data_->separators_; + return data_->separators_; } @@ -564,7 +591,7 @@ namespace scribo void component_set<L>::clear_separators() { - this->data_->separators_.destroy(); + data_->separators_.destroy(); } diff --git a/scribo/scribo/core/document.hh b/scribo/scribo/core/document.hh index f112410..e5ac825 100644 --- a/scribo/scribo/core/document.hh +++ b/scribo/scribo/core/document.hh @@ -91,16 +91,24 @@ namespace scribo const component_set<L>& whitespace_seps_comps() const; void set_whitespace_separators(const image2d<bool>& whitespace_seps); + bool has_line_seps() const; + const mln::image2d<bool>& line_seps() const; + const component_set<L>& line_seps_comps() const; + void set_line_separators(const image2d<bool>& line_seps); + + private: const char *filename_; mln::image2d<mln::value::rgb8> image_; - line_set<L> lines_; paragraph_set<L> parset_; component_set<L> elements_; mln::image2d<bool> whitespace_seps_; component_set<L> whitespace_seps_comps_; + + mln::image2d<bool> line_seps_; + component_set<L> line_seps_comps_; }; @@ -201,7 +209,6 @@ namespace scribo return parset_.lines(); } - template <typename L> const paragraph_set<L>& document<L>::paragraphs() const @@ -294,6 +301,43 @@ namespace scribo } + template <typename L> + bool + document<L>::has_line_seps() const + { + return line_seps_.is_valid(); + } + + + template <typename L> + const mln::image2d<bool>& + document<L>::line_seps() const + { + return line_seps_; + } + + + template <typename L> + const component_set<L>& + document<L>::line_seps_comps() const + { + return line_seps_comps_; + } + + + template <typename L> + void + document<L>::set_line_separators(const image2d<bool>& line_seps) + { + line_seps_ = line_seps; + + mln_value(L) ncomps; + line_seps_comps_ = primitive::extract::components(line_seps, + mln::c8(), ncomps); + } + + + # endif // ! MLN_INCLUDE_ONLY diff --git a/scribo/scribo/core/line_info.hh b/scribo/scribo/core/line_info.hh index 54a5094..c82160a 100644 --- a/scribo/scribo/core/line_info.hh +++ b/scribo/scribo/core/line_info.hh @@ -58,12 +58,76 @@ namespace scribo // Forward declarations. template <typename L> class line_set; + template <typename L> class line_info; typedef mln::util::object_id<scribo::LineId, unsigned> line_id_t; + + namespace internal + { + /// Data structure for \c scribo::line_info<I>. + template <typename L> + struct line_info_data + { + line_info_data(); + line_info_data(const line_set<L>& holder, + const mln::util::array<component_id_t>& comps); + + + bool hidden_; + line::Tag tag_; + mln::box2d bbox_; + mln::box2d ebbox_; + mln::util::array<component_id_t> components_; + + // Values relative to the line bbox. + int baseline_; + int meanline_; + + // Values relative to the baseline. + unsigned x_height_; + int d_height_; + int a_height_; + + // Character related stats. + unsigned char_space_; + unsigned char_width_; + + // Words related stats. + unsigned word_space_; + + // Reading direction + line::ReadingDirection reading_direction_; + + // Line type + line::Type type_; + + // Is this line in reverse video? + bool reverse_video_; + + // Text orientation + float orientation_; + + // Text reading orientation + float reading_orientation_; + + bool indented_; + + std::string text_; + + // Line set holding this element. + line_set<L> holder_; + + }; + + } // end of namespace scribo::internal + + + template <typename L> class line_info { + typedef internal::line_info_data<L> data_t; typedef mln::util::object_id<scribo::ComponentId, unsigned> component_id_t; typedef mln::util::object_id<scribo::LineId, unsigned> line_id_t; @@ -74,6 +138,8 @@ namespace scribo line_info(); + line_info(const line_id_t& id, data_t* data); + line_info(const line_set<L>& holder, const line_id_t& id, const mln::util::array<component_id_t>& comps); @@ -134,9 +200,10 @@ namespace scribo const std::string& text() const; void update_text(const std::string& str); - bool is_valid() const; + bool is_textline() const; + /// Hidden status. /// /// When a line is hidden, it should not be used in routines @@ -180,6 +247,9 @@ namespace scribo /// Returns the delta used to compute the extended bbox. int delta_of_line() const; + /// Update the extended bbox. + void update_ebbox(); + private: // Members void copy_data(const line_info<L>& other); @@ -189,81 +259,59 @@ namespace scribo /// Update bbox and ebbox_ attributes. void update_bbox_and_ebox(line_info<L>& other); - /// Update the extended bbox. - void update_ebbox(); - mln::box2d merged_ebbox(const scribo::line_info<L>& info_l, const scribo::line_info<L>& info); void update_components_type(component::Type type); private: // Attributes - // WARNING: NEVER FORGET TO UPDATE COPY CONSTRUCTOR REDEFINITION!!!! - line_id_t id_; - bool hidden_; - line::Tag tag_; - mln::box2d bbox_; - mln::box2d ebbox_; - mln::util::array<component_id_t> components_; - - // Values relative to the line bbox. - int baseline_; - int meanline_; - - // Values relative to the baseline. - unsigned x_height_; - int d_height_; - int a_height_; - - // WARNING: NEVER FORGET TO UPDATE COPY CONSTRUCTOR REDEFINITION!!!! - - // Character related stats. - unsigned char_space_; - unsigned char_width_; - - // Words related stats. - unsigned word_space_; - - // Reading direction - line::ReadingDirection reading_direction_; - - // Line type - line::Type type_; + mln::util::tracked_ptr<data_t> data_; + }; - // Is this line in reverse video? - bool reverse_video_; - // Text orientation - float orientation_; + template <typename L> + std::ostream& + operator<<(std::ostream& ostr, const line_info<L>& info); - // Text reading orientation - float reading_orientation_; - bool indented_; +# ifndef MLN_INCLUDE_ONLY - std::string text_; + namespace internal + { - // Line set holding this element. - line_set<L> holder_; + template <typename L> + line_info_data<L>::line_info_data() + { + hidden_ = false; + } - // WARNING: NEVER FORGET TO UPDATE COPY CONSTRUCTOR REDEFINITION!!!! - }; + template <typename L> + line_info_data<L>::line_info_data(const line_set<L>& holder, + const mln::util::array<component_id_t>& comps) + : hidden_(false), tag_(line::None), components_(comps), + type_(line::Undefined), holder_(holder) + { + // FIXME: set valid information for these attributes in + // force_stats_update. + word_space_ = 0; + reading_direction_ = line::LeftToRight; + reverse_video_ = false; - template <typename L> - std::ostream& - operator<<(std::ostream& ostr, const line_info<L>& info); + orientation_ = 0.; + reading_orientation_ = 0.; + indented_ = false; + } -# ifndef MLN_INCLUDE_ONLY + } // end of namespace scribo::internal template <typename L> line_info<L>::line_info() - : id_(0), hidden_(false) + : id_(0) { - } template <typename L> @@ -275,47 +323,24 @@ namespace scribo if (! is_valid()) id_ = other.id(); - hidden_ = other.hidden_; - - tag_ = other.tag(); - bbox_ = other.bbox(); - ebbox_ = other.ebbox(); - components_ = other.components(); - - baseline_ = other.baseline(); - meanline_ = other.meanline(); - - x_height_ = other.x_height(); - d_height_ = other.d_height(); - a_height_ = other.a_height(); - - char_space_ = other.char_space(); - char_width_ = other.char_width(); - - word_space_ = other.word_space(); - - reading_direction_ = other.reading_direction(); - - type_ = other.type(); - - reverse_video_ = other.reverse_video(); - - orientation_ = other.orientation(); - - reading_orientation_ = other.reading_orientation(); - - indented_ = other.indented(); + data_ = other.data_; + } - text_ = other.text(); - holder_ = other.holder(); + template <typename L> + inline + line_info<L>::line_info(const line_id_t& id, data_t *data) + : id_(id), data_(data) + { } + template <typename L> inline line_info<L>::line_info(const line_info<L>& other) - : id_(0), hidden_(false) + : id_(0) { + //data_->hidden_ = false; copy_data(other); } @@ -357,22 +382,10 @@ namespace scribo line_info<L>::line_info(const line_set<L>& holder, const line_id_t& id, const mln::util::array<component_id_t>& comps) - : id_(id), hidden_(false), tag_(line::None), components_(comps), - type_(line::Undefined), holder_(holder) + : id_(id) { - + data_ = new data_t(holder, comps); force_stats_update(); - - // FIXME: set valid information for these attributes in - // force_stats_update. - word_space_ = 0; - reading_direction_ = line::LeftToRight; - reverse_video_ = false; - - orientation_ = 0.; - reading_orientation_ = 0.; - - indented_ = false; } @@ -397,7 +410,7 @@ namespace scribo line::Tag line_info<L>::tag() const { - return tag_; + return data_->tag_; } @@ -405,7 +418,7 @@ namespace scribo void line_info<L>::update_tag(line::Tag tag) { - tag_ = tag; + data_->tag_ = tag; } @@ -413,14 +426,14 @@ namespace scribo const mln::box2d& line_info<L>::bbox() const { - return bbox_; + return data_->bbox_; } template <typename L> const mln::box2d& line_info<L>::ebbox() const { - return ebbox_; + return data_->ebbox_; } @@ -428,14 +441,14 @@ namespace scribo const mln::util::array<typename line_info<L>::component_id_t>& line_info<L>::components() const { - return components_; + return data_->components_; } template <typename L> unsigned line_info<L>::card() const { - return components_.size(); + return data_->components_.size(); } @@ -443,7 +456,7 @@ namespace scribo int line_info<L>::baseline() const { - return baseline_; + return data_->baseline_; } @@ -451,7 +464,7 @@ namespace scribo int line_info<L>::meanline() const { - return meanline_; + return data_->meanline_; } @@ -459,7 +472,7 @@ namespace scribo int line_info<L>::ascent() const { - return baseline_ - a_height() + 1; + return data_->baseline_ - a_height() + 1; } @@ -467,7 +480,7 @@ namespace scribo int line_info<L>::descent() const { - return baseline_ - d_height(); + return data_->baseline_ - d_height(); } @@ -475,7 +488,7 @@ namespace scribo unsigned line_info<L>::x_height() const { - return x_height_; + return data_->x_height_; } @@ -483,7 +496,7 @@ namespace scribo int line_info<L>::d_height() const { - return d_height_; + return data_->d_height_; } @@ -491,7 +504,7 @@ namespace scribo int line_info<L>::a_height() const { - return a_height_; + return data_->a_height_; } @@ -499,7 +512,7 @@ namespace scribo unsigned line_info<L>::char_space() const { - return char_space_; + return data_->char_space_; } @@ -507,7 +520,7 @@ namespace scribo unsigned line_info<L>::char_width() const { - return char_width_; + return data_->char_width_; } @@ -515,7 +528,7 @@ namespace scribo unsigned line_info<L>::word_space() const { - return word_space_; + return data_->word_space_; } @@ -523,14 +536,14 @@ namespace scribo line::ReadingDirection line_info<L>::reading_direction() const { - return reading_direction_; + return data_->reading_direction_; } template <typename L> line::Type line_info<L>::type() const { - return type_; + return data_->type_; } @@ -538,10 +551,10 @@ namespace scribo void line_info<L>::update_components_type(component::Type type) { - for_all_elements(i, components_) + for_all_elements(i, data_->components_) { - unsigned c = components_[i]; - holder_.components_()(c).update_type(type); + unsigned c = data_->components_[i]; + data_->holder_.components_()(c).update_type(type); } } @@ -550,7 +563,7 @@ namespace scribo void line_info<L>::update_type(line::Type type) { - type_ = type; + data_->type_ = type; // Some line types may involve updating components type as well. if (type == line::Punctuation) @@ -564,7 +577,7 @@ namespace scribo bool line_info<L>::reverse_video() const { - return reverse_video_; + return data_->reverse_video_; } @@ -572,7 +585,7 @@ namespace scribo float line_info<L>::orientation() const { - return orientation_; + return data_->orientation_; } @@ -580,7 +593,7 @@ namespace scribo float line_info<L>::reading_orientation() const { - return reading_orientation_; + return data_->reading_orientation_; } @@ -588,21 +601,21 @@ namespace scribo bool line_info<L>::indented() const { - return indented_; + return data_->indented_; } template <typename L> bool line_info<L>::has_text() const { - return !text_.empty(); + return !data_->text_.empty(); } template <typename L> const std::string& line_info<L>::text() const { - return text_; + return data_->text_; } @@ -610,7 +623,7 @@ namespace scribo void line_info<L>::update_text(const std::string& str) { - text_ = str; + data_->text_ = str; } @@ -624,9 +637,19 @@ namespace scribo template <typename L> bool + line_info<L>::is_textline() const + { + return is_valid() + && !is_hidden() + && type() == line::Text; + } + + + template <typename L> + bool line_info<L>::is_hidden() const { - return hidden_; + return data_->hidden_; } @@ -634,7 +657,7 @@ namespace scribo void line_info<L>::set_hidden(bool b) { - hidden_ = b; + data_->hidden_ = b; } @@ -665,8 +688,8 @@ namespace scribo void line_info<L>::update_ebbox() { - int A = a_height_ - x_height_; - int D = - d_height_; + int A = data_->a_height_ - data_->x_height_; + int D = - data_->d_height_; if (A <= 2 && D > 2) A = D; if (D <= 2 && A > 2) @@ -674,10 +697,12 @@ namespace scribo int delta = delta_of_line(); - ebbox_ = mln::make::box2d(meanline_ - A, bbox().pmin().col() - delta, - baseline_ + D, bbox().pmax().col() + delta); + data_->ebbox_ = mln::make::box2d(data_->meanline_ - A, + bbox().pmin().col() - delta, + data_->baseline_ + D, + bbox().pmax().col() + delta); - ebbox_.crop_wrt(holder_.components().labeled_image().domain()); + data_->ebbox_.crop_wrt(data_->holder_.components().labeled_image().domain()); } @@ -729,20 +754,20 @@ namespace scribo // Adjusting ebboxes with the highest delta and merging ebboxes. int d_delta = other.delta_of_line() - this->delta_of_line(); if (d_delta < 0) // other.delta_of_line() < this->delta_of_line() - ebbox_.merge(enlarge(other.ebbox(), - d_delta)); + data_->ebbox_.merge(enlarge(other.ebbox(), - d_delta)); else { - mln::box2d b = ebbox_; - ebbox_ = other.bbox(); - ebbox_.merge(enlarge(b, d_delta)); + mln::box2d b = data_->ebbox_; + data_->ebbox_ = other.bbox(); + data_->ebbox_.merge(enlarge(b, d_delta)); } - ebbox_.crop_wrt(holder_.components().labeled_image().domain()); + data_->ebbox_.crop_wrt(data_->holder_.components().labeled_image().domain()); } else // /other/ IS NOT a text line. { - ebbox_.merge(other.ebbox()); - ebbox_.merge(merged_ebbox(*this, other)); + data_->ebbox_.merge(other.ebbox()); + data_->ebbox_.merge(merged_ebbox(*this, other)); } } else // /this/ is NOT a text line @@ -755,15 +780,15 @@ namespace scribo } update_type(line::Text); - ebbox_.merge(other.ebbox()); - ebbox_.merge(merged_ebbox(other, *this)); + data_->ebbox_.merge(other.ebbox()); + data_->ebbox_.merge(merged_ebbox(other, *this)); } // Merging bboxes. - bbox_.merge(other.bbox()); + data_->bbox_.merge(other.bbox()); // Make sure the ebbox is included in the image domain. - ebbox_.crop_wrt(holder_.components().labeled_image().domain()); + data_->ebbox_.crop_wrt(data_->holder_.components().labeled_image().domain()); } @@ -771,14 +796,14 @@ namespace scribo void line_info<L>::fast_merge(line_info<L>& other, bool hide) { - tag_ = line::Needs_Precise_Stats_Update; + data_->tag_ = line::Needs_Precise_Stats_Update; other.update_tag(line::Merged); other.set_hidden(hide); // Update bbox and ebbox update_bbox_and_ebox(other); - components_.append(other.components()); + data_->components_.append(other.components()); } @@ -795,7 +820,7 @@ namespace scribo line_info<L>::force_stats_update() { typedef mln_site(L) P; - const component_set<L>& comp_set = holder_.components(); + const component_set<L>& comp_set = data_->holder_.components(); // Init. typedef mln::value::int_u<12> median_data_t; @@ -814,21 +839,21 @@ namespace scribo // Workaround to avoid overflow with int_u<12> in median accumulators. // // FIXME: not optimal... - for_all_elements(i, components_) + for_all_elements(i, data_->components_) { - unsigned c = components_(i); + unsigned c = data_->components_(i); // Ignore punctuation for stats computation but not for bbox // computation. - if (holder_.components()(c).type() == component::Punctuation) + if (data_->holder_.components()(c).type() == component::Punctuation) continue; ref_line = mln::math::min(comp_set(c).bbox().pmin().row(), ref_line); } - for_all_elements(i, components_) + for_all_elements(i, data_->components_) { - unsigned c = components_(i); + unsigned c = data_->components_(i); const mln::box2d& bb = comp_set(c).bbox(); @@ -837,7 +862,7 @@ namespace scribo // Ignore punctuation for stats computation but not for bbox // computation. - if (holder_.components()(c).type() == component::Punctuation) + if (data_->holder_.components()(c).type() == component::Punctuation) continue; @@ -853,11 +878,11 @@ namespace scribo // (right link) (left link) // Space between characters. - if (holder_.links()(c) != c) + if (data_->holder_.links()(c) != c) { int space = bb.pmin().col() - - comp_set(holder_.links()(c)).bbox().pmax().col() - 1; + - comp_set(data_->holder_.links()(c)).bbox().pmax().col() - 1; // -- Ignore overlapped characters. if (space > 0) @@ -884,31 +909,31 @@ namespace scribo // Finalization { - tag_ = line::None; - bbox_ = bbox.to_result(); + data_->tag_ = line::None; + data_->bbox_ = bbox.to_result(); // Char space if (char_space.card() < 2) - char_space_ = 0; + data_->char_space_ = 0; else - char_space_ = char_space.to_result(); + data_->char_space_ = char_space.to_result(); // Char width if (card() == 2) - char_width_ = (comp_set(components_[0]).bbox().width() - + comp_set(components_[1]).bbox().width()) / 2; + data_->char_width_ = (comp_set(data_->components_[0]).bbox().width() + + comp_set(data_->components_[1]).bbox().width()) / 2; else - char_width_ = char_width.to_result(); + data_->char_width_ = char_width.to_result(); mln::def::coord absolute_baseline_r = baseline.to_result() + ref_line, absolute_meanline_r = meanline.to_result() + ref_line; - baseline_ = absolute_baseline_r; - meanline_ = absolute_meanline_r; - x_height_ = baseline_ - meanline_ + 1; - d_height_ = baseline_ - bbox.to_result().pmax().row(); - a_height_ = baseline_ - bbox.to_result().pmin().row() + 1; + data_->baseline_ = absolute_baseline_r; + data_->meanline_ = absolute_meanline_r; + data_->x_height_ = data_->baseline_ - data_->meanline_ + 1; + data_->d_height_ = data_->baseline_ - bbox.to_result().pmax().row(); + data_->a_height_ = data_->baseline_ - bbox.to_result().pmin().row() + 1; //FIXME // @@ -929,7 +954,7 @@ namespace scribo const line_set<L>& line_info<L>::holder() const { - return holder_; + return data_->holder_; } diff --git a/scribo/scribo/core/line_links.hh b/scribo/scribo/core/line_links.hh index 85c45e8..de62158 100644 --- a/scribo/scribo/core/line_links.hh +++ b/scribo/scribo/core/line_links.hh @@ -139,8 +139,8 @@ namespace scribo template <typename L> line_links<L>::line_links() + : data_(0) { - data_ = new data_t(); } diff --git a/scribo/scribo/core/line_set.hh b/scribo/scribo/core/line_set.hh index 29795b2..bfa9240 100644 --- a/scribo/scribo/core/line_set.hh +++ b/scribo/scribo/core/line_set.hh @@ -99,6 +99,10 @@ namespace scribo /// Constructor from object groups. line_set(const object_groups<L>& groups); + + /// Constructor useful for delayed construction (loading from file). + line_set(const object_groups<L>& groups, + const mln::util::array<line_info<L> >& line_data); /// @} /// Compute line stats and fill the underlying information. @@ -155,8 +159,14 @@ namespace scribo /// @} + /// Return false if it is not initialized (built with the default + /// constructor). bool is_valid() const; + + void update_line_data_(const mln::util::array<line_info<L> >& line_data); + + private: /// Duplicate the underlying image and create a new line_set. void init_(const line_set<L>& model); @@ -233,6 +243,15 @@ namespace scribo template <typename L> + inline + line_set<L>::line_set(const object_groups<L>& groups, + const mln::util::array<line_info<L> >& line_data) + { + data_ = new internal::line_set_data<L>(line_data, groups); + } + + + template <typename L> void line_set<L>::compute_lines(const object_groups<L>& groups) { @@ -396,7 +415,15 @@ namespace scribo bool line_set<L>::is_valid() const { - return data_->links_.is_valid() && data_->groups_.is_valid(); + return data_ && data_->groups_.is_valid(); + } + + template <typename L> + inline + void + line_set<L>::update_line_data_(const mln::util::array<line_info<L> >& line_data) + { + data_->infos_ = line_data; } template <typename L> diff --git a/scribo/scribo/core/paragraph_info.hh b/scribo/scribo/core/paragraph_info.hh index a8c623a..17f847f 100644 --- a/scribo/scribo/core/paragraph_info.hh +++ b/scribo/scribo/core/paragraph_info.hh @@ -113,6 +113,16 @@ namespace scribo } + template <typename L> + std::ostream& + operator<<(std::ostream& ostr, const paragraph_info<L>& info) + { + return ostr << "paragraph_info(" + << "line_ids=" << info.line_ids() + << ", bbox=" << info.bbox() + << ")" << std::endl; + } + # endif // ! MLN_INCLUDE_ONLY } // end of namespace scribo diff --git a/scribo/scribo/core/paragraph_set.hh b/scribo/scribo/core/paragraph_set.hh index 355eaa9..6597189 100644 --- a/scribo/scribo/core/paragraph_set.hh +++ b/scribo/scribo/core/paragraph_set.hh @@ -36,6 +36,25 @@ namespace scribo { + namespace internal + { + + /// Data structure for \c scribo::paragraph_set<I>. + template <typename L> + struct paragraph_set_data + { + paragraph_set_data(); + paragraph_set_data(const line_links<L>& llines, unsigned npars); + + mln::util::array<paragraph_info<L> > pars_; + line_set<L> lines_; + line_links<L> links_; + }; + + } // end of namespace scribo::internal + + + /*! \brief Paragraph container. Paragraph ids start from 1. @@ -46,6 +65,7 @@ namespace scribo { public: paragraph_set(); + paragraph_set(internal::paragraph_set_data<L>* data); paragraph_set(const line_links<L>& llinks, unsigned npars); unsigned nelements() const; @@ -57,9 +77,10 @@ namespace scribo const line_set<L>& lines() const; + const line_links<L>& links() const; + private: - mln::util::array<paragraph_info<L> > pars_; - line_set<L> lines_; + mln::util::tracked_ptr< internal::paragraph_set_data<L> > data_; }; @@ -77,37 +98,72 @@ namespace scribo # ifndef MLN_INCLUDE_ONLY + // paragraph_set_data<L> > + + namespace internal + { + + // data< paragraph_set<L> > + + + template <typename L> + inline + paragraph_set_data<L>::paragraph_set_data() + { + } + + + template <typename L> + inline + paragraph_set_data<L>::paragraph_set_data(const line_links<L>& llinks, unsigned npars) + : pars_(npars + 1, paragraph_info<L>(llinks)), links_(llinks) + { + lines_ = llinks.lines(); + } + + } // end of namespace mln::internal + + template <typename L> paragraph_set<L>::paragraph_set() + : data_(0) { } template <typename L> + paragraph_set<L>::paragraph_set(internal::paragraph_set_data<L>* data) + { + data_ = data; + } + + template <typename L> paragraph_set<L>::paragraph_set(const line_links<L>& llinks, unsigned npars) - : pars_(npars + 1, paragraph_info<L>(llinks)) { - lines_ = llinks.lines(); + data_ = new internal::paragraph_set_data<L>(llinks, npars); } template <typename L> unsigned paragraph_set<L>::nelements() const { - return pars_.nelements() - 1; + mln_precondition(data_ != 0); + return data_->pars_.nelements() - 1; } template <typename L> paragraph_info<L>& paragraph_set<L>::operator()(unsigned i) { - return pars_[i]; + mln_precondition(data_ != 0); + return data_->pars_[i]; } template <typename L> const paragraph_info<L>& paragraph_set<L>::operator()(unsigned i) const { - return pars_[i]; + mln_precondition(data_ != 0); + return data_->pars_[i]; } @@ -115,7 +171,7 @@ namespace scribo bool paragraph_set<L>::is_valid() const { - return !pars_.is_empty(); + return data_ && !data_->pars_.is_empty(); } @@ -123,7 +179,17 @@ namespace scribo const line_set<L>& paragraph_set<L>::lines() const { - return lines_; + mln_precondition(data_ != 0); + return data_->lines_; + } + + + template <typename L> + const line_links<L>& + paragraph_set<L>::links() const + { + mln_precondition(data_ != 0); + return data_->links_; } -- 1.5.6.5