Olena-patches
  Threads by month 
                
            - ----- 2025 -----
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2024 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2023 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2022 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2021 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2020 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2019 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2018 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2017 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2016 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2015 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2014 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2013 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2012 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2011 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2010 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2009 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2008 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2007 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2006 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2005 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2004 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 
March 2011
- 7 participants
 - 277 discussions
 
                        
                            
                                
                            
                            last-svn-commit-788-gbe7296a	scribo/toolchain/internal/content_in_doc_functor.hh: Make OCR	step optional.
                        
                        
by Guillaume Lazzara 04 Mar '11
                    by Guillaume Lazzara 04 Mar '11
04 Mar '11
                    
                        ---
 scribo/ChangeLog                                   |    8 ++++++--
 .../toolchain/internal/content_in_doc_functor.hh   |   19 ++++++++++++-------
 2 files changed, 18 insertions(+), 9 deletions(-)
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index 7ae03ac..f870519 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,9 +1,13 @@
+2011-03-04  Guillaume Lazzara  <z(a)lrde.epita.fr>
+
+	* scribo/toolchain/internal/content_in_doc_functor.hh: Make OCR step optional.
+
 2011-03-03  Guillaume Lazzara  <z(a)lrde.epita.fr>
 
 	Compress image data in XML output.
 
-	* scribo/scribo/io/xml/internal/full_xml_visitor.hh,
-	* scribo/scribo/io/xml/load.hh: Here.
+	* scribo/io/xml/internal/full_xml_visitor.hh,
+	* scribo/io/xml/load.hh: Here.
 
 2011-03-03  Guillaume Lazzara  <z(a)lrde.epita.fr>
 
diff --git a/scribo/scribo/toolchain/internal/content_in_doc_functor.hh b/scribo/scribo/toolchain/internal/content_in_doc_functor.hh
index dcbb4f7..40f013c 100644
--- a/scribo/scribo/toolchain/internal/content_in_doc_functor.hh
+++ b/scribo/scribo/toolchain/internal/content_in_doc_functor.hh
@@ -111,6 +111,7 @@ namespace scribo
 	bool enable_denoising;
 	bool enable_line_seps;
 	bool enable_whitespace_seps;
+	bool enable_ocr;
 	bool enable_debug;
 	bool save_doc_as_xml;
 	scribo::io::xml::Format xml_format;
@@ -136,6 +137,7 @@ namespace scribo
 	: enable_denoising(true),
 	  enable_line_seps(true),
 	  enable_whitespace_seps(true),
+	  enable_ocr(true),
 	  enable_debug(false),
 	  save_doc_as_xml(false),
 	  xml_format(scribo::io::xml::PageExtended),
@@ -373,11 +375,14 @@ namespace scribo
 
 
 	// Text recognition
-	on_new_progress_label("Recognizing text");
-	scribo::text::recognition(lines, ocr_language.c_str());
+	if (enable_ocr)
+	{
+	  on_new_progress_label("Recognizing text");
 
-	on_progress();
+	  scribo::text::recognition(lines, ocr_language.c_str());
 
+	  on_progress();
+	}
 
 	// Link text lines
 	on_new_progress_label("Linking text lines");
@@ -390,7 +395,7 @@ namespace scribo
 	  image2d<value::rgb8> debug = data::convert(value::rgb8(), original_image);
 	  for_all_lines(l, lines)
 	  {
-	    if (! lines(l).is_valid() || lines(l).is_hidden() || lines(l).type() != line::Text)
+	    if (! lines(l).is_textline())
 	      continue;
 
 	    mln::draw::box(debug, lines(l).bbox(), literal::blue);
@@ -427,7 +432,7 @@ namespace scribo
 	  mln::util::array<accu::shape::bbox<point2d> > nbbox(llinks.nelements());
 	  for_all_lines(i, lines)
 	  {
-	    if (! lines(i).is_valid() || lines(i).is_hidden() || lines(i).type() != line::Text)
+	    if (! lines(i).is_textline())
 	      continue;
 
 	    mln::draw::box(debug, lines(i).bbox(), literal::red);
@@ -497,8 +502,8 @@ namespace scribo
       int
       content_in_doc_functor<I>::nsteps() const
       {
-	return 11 + enable_denoising + enable_line_seps
-	  + enable_whitespace_seps + save_doc_as_xml;
+	return 10 + enable_denoising + enable_line_seps
+	  + enable_whitespace_seps + enable_ocr + save_doc_as_xml;
       }
 
 
-- 
1.5.6.5
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    03 Mar '11
                    
                        	* scribo/scribo/io/xml/internal/full_xml_visitor.hh,
	* scribo/scribo/io/xml/load.hh: Here.
---
 scribo/ChangeLog                                  |    7 ++++
 scribo/scribo/io/xml/internal/full_xml_visitor.hh |   34 ++++++++++++++------
 scribo/scribo/io/xml/load.hh                      |   12 +++++--
 3 files changed, 39 insertions(+), 14 deletions(-)
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index 7c29163..7ae03ac 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,5 +1,12 @@
 2011-03-03  Guillaume Lazzara  <z(a)lrde.epita.fr>
 
+	Compress image data in XML output.
+
+	* scribo/scribo/io/xml/internal/full_xml_visitor.hh,
+	* scribo/scribo/io/xml/load.hh: Here.
+
+2011-03-03  Guillaume Lazzara  <z(a)lrde.epita.fr>
+
 	Small fixes in Scribo.
 
 	* scribo/convert/from_base64.hh: Remove guards HAVE_QT.
diff --git a/scribo/scribo/io/xml/internal/full_xml_visitor.hh b/scribo/scribo/io/xml/internal/full_xml_visitor.hh
index 9c5bd1d..2b09b3a 100644
--- a/scribo/scribo/io/xml/internal/full_xml_visitor.hh
+++ b/scribo/scribo/io/xml/internal/full_xml_visitor.hh
@@ -31,6 +31,9 @@
 /// XML serializer Visitor.
 
 # include <fstream>
+
+# include <QByteArray>
+
 # include <scribo/core/internal/doc_xml_serializer.hh>
 # include <scribo/core/document.hh>
 # include <scribo/core/component_set.hh>
@@ -40,11 +43,12 @@
 # include <scribo/core/line_links.hh>
 # include <scribo/core/line_info.hh>
 
-# include <scribo/convert/to_base64.hh>
-
 # include <scribo/io/xml/internal/print_box_coords.hh>
 # include <scribo/io/xml/internal/print_page_preambule.hh>
 
+// Compression level 0-9. 9 is the best but is slow.
+// 5 seems to be a good compromise.
+# define COMPRESSION_LEVEL 5
 
 namespace scribo
 {
@@ -273,15 +277,20 @@ namespace scribo
 		   << "\" width=\"" << lbl.domain().width() << "\">"
 		   << "<![CDATA[";
 
-	    util::array<unsigned char> lbl64;
-	    convert::to_base64(lbl, lbl64);
-	    output.write((const char *)lbl64.std_vector().data(),
-			 lbl64.nelements());
+	    // FIXME: Try to avoid that!
+	    border::resize(lbl, 0);
+	    QByteArray lbl64((const char *)lbl.buffer(),
+	    		     lbl.nelements() * sizeof(mln_value(L)));
+	    lbl64 = qCompress(lbl64, COMPRESSION_LEVEL);
+	    lbl64 = lbl64.toBase64();
+
+	    output.write(lbl64.data(), lbl64.size());
 
 	    output <<  "]]></labeled_image>" << std::endl;
 	  }
 
 	  // Save separators image
+	  if (comp_set.has_separators())
 	  {
 	    const mln_ch_value(L,bool)& seps = comp_set.separators();
 	    output << "<separators_image "
@@ -289,10 +298,13 @@ namespace scribo
 		   << "\" width=\"" << seps.domain().width() << "\">"
 		   << "<![CDATA[";
 
-	    util::array<unsigned char> seps64;
-	    convert::to_base64(seps, seps64);
-	    output.write((const char *)seps64.std_vector().data(),
-			 seps64.nelements());
+	    border::resize(seps, 0);
+	    QByteArray seps64((const char *)seps.buffer(),
+			      seps.nelements() * sizeof(bool));
+	    seps64 = qCompress(seps64, COMPRESSION_LEVEL);
+	    seps64 = seps64.toBase64();
+
+	    output.write(seps64.data(), seps64.size());
 
 	    output <<  "]]></separators_image>" << std::endl;
 	  }
@@ -453,4 +465,6 @@ namespace scribo
 
 } // end of namespace scribo
 
+# undef COMPRESSION_LEVEL
+
 #endif // SCRIBO_IO_XML_INTERNAL_FULL_XML_VISITOR_HH
diff --git a/scribo/scribo/io/xml/load.hh b/scribo/scribo/io/xml/load.hh
index e0f4548..8042c75 100644
--- a/scribo/scribo/io/xml/load.hh
+++ b/scribo/scribo/io/xml/load.hh
@@ -50,8 +50,6 @@
 # include <scribo/core/line_set.hh>
 # include <scribo/core/line_info.hh>
 
-# include <scribo/convert/from_base64.hh>
-
 namespace scribo
 {
 
@@ -405,13 +403,19 @@ namespace scribo
 	    {
 	      case LabeledImage:
 	      {
-		scribo::convert::from_base64(ch, comp_set_data->ima_);
+		QByteArray data = ch.toAscii();
+		data = QByteArray::fromBase64(data);
+		data = qUncompress(data);
+		memcpy((char *) comp_set_data->ima_.buffer(), data.data(), data.size());
 	      }
 	      break;
 
 	      case SeparatorsImage:
 	      {
-		scribo::convert::from_base64(ch, comp_set_data->separators_);
+		QByteArray data = ch.toAscii();
+		data = QByteArray::fromBase64(data);
+		data = qUncompress(data);
+		memcpy((char *) comp_set_data->separators_.buffer(), data.data(), data.size());
 	      }
 	      break;
 
-- 
1.5.6.5
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                        	* scribo/convert/from_base64.hh: Remove guards HAVE_QT.
	* scribo/core/document.hh: Initialize ImageMagick.
	* scribo/io/xml/internal/html_markups_replace.hh: Remove. Move code...
	* scribo/core/line_info.hh: ... here.
	* scribo/core/line_links.hh: Make use of is_textline method.
	* scribo/core/paragraph_info.hh: Add nlines method.
	* scribo/core/paragraph_set.hh: Add a construction routine using a
	line_set.
	* scribo/io/xml/internal/extended_page_xml_visitor.hh,
	* scribo/io/xml/internal/print_box_coords.hh,
	* scribo/io/xml/internal/print_page_preambule.hh,
	* src/primitive/extract/separators_nonvisible.cc: Fix includes.
	* scribo/io/xml/save.hh: Add a precondition.
	* scribo/text/extract_lines.hh,
	* src/debug/show_info_median_inter_characters.cc,
	* src/debug/show_info_x_height.cc,
	* src/debug/show_text_lines.cc: Fix label type.
---
 scribo/ChangeLog                                   |   30 ++++++
 scribo/scribo/convert/from_base64.hh               |    8 --
 scribo/scribo/core/document.hh                     |    1 +
 scribo/scribo/core/line_info.hh                    |   45 ++++++++-
 scribo/scribo/core/line_links.hh                   |    5 +-
 scribo/scribo/core/paragraph_info.hh               |    9 ++
 scribo/scribo/core/paragraph_set.hh                |   28 ++++++
 .../io/xml/internal/extended_page_xml_visitor.hh   |    2 -
 .../scribo/io/xml/internal/html_markups_replace.hh |   97 --------------------
 scribo/scribo/io/xml/internal/print_box_coords.hh  |    3 +
 .../scribo/io/xml/internal/print_page_preambule.hh |    5 +
 scribo/scribo/io/xml/save.hh                       |    2 +
 scribo/scribo/text/extract_lines.hh                |   16 ++--
 .../src/debug/show_info_median_inter_characters.cc |   12 +-
 scribo/src/debug/show_info_x_height.cc             |   12 +-
 scribo/src/debug/show_text_lines.cc                |    2 +-
 .../src/primitive/extract/separators_nonvisible.cc |    2 +-
 17 files changed, 143 insertions(+), 136 deletions(-)
 delete mode 100644 scribo/scribo/io/xml/internal/html_markups_replace.hh
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index 4eae5f8..7c29163 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,3 +1,33 @@
+2011-03-03  Guillaume Lazzara  <z(a)lrde.epita.fr>
+
+	Small fixes in Scribo.
+
+	* scribo/convert/from_base64.hh: Remove guards HAVE_QT.
+
+	* scribo/core/document.hh: Initialize ImageMagick.
+
+	* scribo/io/xml/internal/html_markups_replace.hh: Remove. Move code...
+	* scribo/core/line_info.hh: ... here.
+
+	* scribo/core/line_links.hh: Make use of is_textline method.
+
+	* scribo/core/paragraph_info.hh: Add nlines method.
+
+	* scribo/core/paragraph_set.hh: Add a construction routine using a
+	line_set.
+
+	* scribo/io/xml/internal/extended_page_xml_visitor.hh,
+	* scribo/io/xml/internal/print_box_coords.hh,
+	* scribo/io/xml/internal/print_page_preambule.hh,
+	* src/primitive/extract/separators_nonvisible.cc: Fix includes.
+
+	* scribo/io/xml/save.hh: Add a precondition.
+
+	* scribo/text/extract_lines.hh,
+	* src/debug/show_info_median_inter_characters.cc,
+	* src/debug/show_info_x_height.cc,
+	* src/debug/show_text_lines.cc: Fix label type.
+
 2011-03-02  Guillaume Lazzara  <z(a)lrde.epita.fr>
 
 	Regen mk files.
diff --git a/scribo/scribo/convert/from_base64.hh b/scribo/scribo/convert/from_base64.hh
index 8c14a0f..5eeeb53 100644
--- a/scribo/scribo/convert/from_base64.hh
+++ b/scribo/scribo/convert/from_base64.hh
@@ -82,13 +82,9 @@ namespace scribo
 		     Image<I>& output);
 
 
-# if defined HAVE_QT
-
     template <typename I>
     void from_base64(const QString& data64, Image<I>& output_);
 
-# endif // ! HAVE_QT
-
 
 # ifndef MLN_INCLUDE_ONLY
 
@@ -191,8 +187,6 @@ namespace scribo
     }
 
 
-# if defined HAVE_QT
-
     template <typename I>
     void
     from_base64(const QString& data64, Image<I>& output_)
@@ -205,8 +199,6 @@ namespace scribo
       trace::exiting("scribo::convert::to_base64");
     }
 
-# endif // ! HAVE_QT
-
 
 # endif // ! MLN_INCLUDE_ONLY
 
diff --git a/scribo/scribo/core/document.hh b/scribo/scribo/core/document.hh
index 372f0a4..689d0e3 100644
--- a/scribo/scribo/core/document.hh
+++ b/scribo/scribo/core/document.hh
@@ -160,6 +160,7 @@ namespace scribo
   void
   document<L>::open()
   {
+    Magick::InitializeMagick(0);
     mln::io::magick::load(image_, filename_);
   }
 
diff --git a/scribo/scribo/core/line_info.hh b/scribo/scribo/core/line_info.hh
index 33a1529..46ba720 100644
--- a/scribo/scribo/core/line_info.hh
+++ b/scribo/scribo/core/line_info.hh
@@ -35,9 +35,10 @@
 /// from the x_height and the baseline.
 ///
 /// \fixme The way the meanline and the baseline are computed is not
-/// optimal and does not work is the components are too high (because
+/// optimal and does not work if the components are too high (because
 /// of the median accumulator and int_u12 overflows).
 
+# include <map>
 
 # include <mln/core/alias/box2d.hh>
 # include <mln/core/alias/point2d.hh>
@@ -53,8 +54,6 @@
 # include <scribo/core/line_set.hh>
 # include <scribo/core/component_set.hh>
 
-# include <scribo/io/xml/internal/html_markups_replace.hh>
-
 # include <scribo/core/concept/serializable.hh>
 
 
@@ -287,6 +286,42 @@ namespace scribo
   namespace internal
   {
 
+    // INTERNAL TOOLS
+
+    static inline std::map<char, std::string> init_map()
+    {
+      std::map<char, std::string> html_map;
+      html_map['\"'] = """;
+      html_map['<'] = "<";
+      html_map['>'] = ">";
+      html_map['&'] = "&";
+      return html_map;
+    }
+
+
+    inline
+    std::string
+    html_markups_replace(const std::string& input)
+    {
+      static std::map<char, std::string> map = init_map();
+
+      std::string output = input;
+      for (unsigned i = 0; i < input.size(); ++i)
+      {
+	std::map<char, std::string>::iterator it = map.find(output.at(i));
+	if (it != map.end())
+	{
+	  output.replace(i, 1, it->second);
+	  i += it->second.size() - 1;
+	}
+      }
+      return output;
+    }
+
+
+
+    // LINE INFO DATA
+
     template <typename L>
     line_info_data<L>::line_info_data()
     {
@@ -641,7 +676,7 @@ namespace scribo
   line_info<L>::update_text(const std::string& str)
   {
     data_->text_ = str;
-    data_->html_text_ = scribo::io::xml::internal::html_markups_replace(str);
+    data_->html_text_ = scribo::internal::html_markups_replace(str);
   }
 
 
@@ -869,6 +904,8 @@ namespace scribo
       ref_line = mln::math::min(comp_set(c).bbox().pmin().row(), ref_line);
     }
 
+    // FIXME: compute font color!
+
     for_all_elements(i, data_->components_)
     {
       unsigned c = data_->components_(i);
diff --git a/scribo/scribo/core/line_links.hh b/scribo/scribo/core/line_links.hh
index fdd09a5..ab36a73 100644
--- a/scribo/scribo/core/line_links.hh
+++ b/scribo/scribo/core/line_links.hh
@@ -215,9 +215,8 @@ namespace scribo
   line_links<L>::init()
   {
     for (unsigned i = 0; i < nelements(); ++i)
-      if (! data_->lines_(i).is_valid()
-	  || data_->lines_(i).is_hidden()
-	  || data_->lines_(i).type() != line::Text)
+      if (!data_->lines_(i).is_valid()
+	  || !data_->lines_(i).is_textline())
       {
 	data_->line_to_link_(i) = 0;
       }
diff --git a/scribo/scribo/core/paragraph_info.hh b/scribo/scribo/core/paragraph_info.hh
index 17f847f..f4b1309 100644
--- a/scribo/scribo/core/paragraph_info.hh
+++ b/scribo/scribo/core/paragraph_info.hh
@@ -52,6 +52,8 @@ namespace scribo
 
     const mln::util::array<line_id_t>& line_ids() const;
 
+    unsigned nlines() const;
+
     bool is_valid() const;
 
   private:
@@ -106,6 +108,13 @@ namespace scribo
   }
 
   template <typename L>
+  unsigned
+  paragraph_info<L>::nlines() const
+  {
+    return line_ids_.nelements();
+  }
+
+  template <typename L>
   bool
   paragraph_info<L>::is_valid() const
   {
diff --git a/scribo/scribo/core/paragraph_set.hh b/scribo/scribo/core/paragraph_set.hh
index 5451069..f081472 100644
--- a/scribo/scribo/core/paragraph_set.hh
+++ b/scribo/scribo/core/paragraph_set.hh
@@ -215,6 +215,7 @@ namespace scribo
     } // end of namespace scribo::make::internal
 
 
+    // FIXME: move that code into paragraph_set constructor?
     template <typename L>
     scribo::paragraph_set<L>
     paragraph(const line_links<L>& llinks)
@@ -241,6 +242,33 @@ namespace scribo
       return parset;
     }
 
+
+    // FIXME: move that code into paragraph_set constructor?
+    template <typename L>
+    scribo::paragraph_set<L>
+    paragraph(const scribo::line_set<L>& lines)
+    {
+      line_links<L> links(lines);
+      links.init();
+
+      unsigned npars;
+      mln::fun::i2v::array<unsigned>
+	par_ids = mln::make::relabelfun(links.line_to_link(),
+					links.nelements() - 1, npars);
+      paragraph_set<L> parset(links, npars);
+
+      for_all_links(l, links)
+	if (links(l))
+	{
+	  value::int_u16 par_id = par_ids(l);
+	  parset(par_id).add_line(lines(l));
+	}
+
+      return parset;
+    }
+
+
+
   } // end of namespace scribo::make
 
 
diff --git a/scribo/scribo/io/xml/internal/extended_page_xml_visitor.hh b/scribo/scribo/io/xml/internal/extended_page_xml_visitor.hh
index 5d8a672..4da0755 100644
--- a/scribo/scribo/io/xml/internal/extended_page_xml_visitor.hh
+++ b/scribo/scribo/io/xml/internal/extended_page_xml_visitor.hh
@@ -40,8 +40,6 @@
 # include <scribo/core/line_links.hh>
 # include <scribo/core/line_info.hh>
 
-# include <scribo/convert/to_base64.hh>
-
 # include <scribo/io/xml/internal/print_box_coords.hh>
 # include <scribo/io/xml/internal/print_page_preambule.hh>
 
diff --git a/scribo/scribo/io/xml/internal/html_markups_replace.hh b/scribo/scribo/io/xml/internal/html_markups_replace.hh
deleted file mode 100644
index 76f8107..0000000
--- a/scribo/scribo/io/xml/internal/html_markups_replace.hh
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE)
-//
-// This file is part of Olena.
-//
-// Olena is free software: you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation, version 2 of the License.
-//
-// Olena is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Olena.  If not, see <http://www.gnu.org/licenses/>.
-//
-// As a special exception, you may use this file as part of a free
-// software project without restriction.  Specifically, if other files
-// instantiate templates or use macros or inline functions from this
-// file, or you compile this file and link it with other files to produce
-// an executable, this file does not by itself cause the resulting
-// executable to be covered by the GNU General Public License.  This
-// exception does not however invalidate any other reasons why the
-// executable file might be covered by the GNU General Public License.
-
-#ifndef SCRIBO_IO_XML_INTERNAL_HTML_MARKUPS_REPLACE_HH
-# define SCRIBO_IO_XML_INTERNAL_HTML_MARKUPS_REPLACE_HH
-
-/// \file
-///
-/// \brief Replace HTML markups characters by their corresponding
-/// markups.
-
-
-namespace scribo
-{
-
-  namespace io
-  {
-
-    namespace xml
-    {
-
-      namespace internal
-      {
-
-        /*! \brief Replace HTML markups characters by their corresponding
-	  markups.
-	*/
-	inline
-	std::string
-	html_markups_replace(std::string& input);
-
-
-# ifndef MLN_INCLUDE_ONLY
-
-	static inline std::map<char, std::string> init_map()
-	{
-	  std::map<char, std::string> html_map;
-	  html_map['\"'] = """;
-	  html_map['<'] = "<";
-	  html_map['>'] = ">";
-	  html_map['&'] = "&";
-	  return html_map;
-	}
-
-
-	inline
-	std::string
-	html_markups_replace(const std::string& input)
-	{
-	  static std::map<char, std::string> map = init_map();
-
-	  std::string output = input;
-	  for (unsigned i = 0; i < input.size(); ++i)
-	  {
-	    std::map<char, std::string>::iterator it = map.find(output.at(i));
-	    if (it != map.end())
-	    {
-	      output.replace(i, 1, it->second);
-	      i += it->second.size() - 1;
-	    }
-	  }
-	  return output;
-	}
-
-# endif // ! MLN_INCLUDE_ONLY
-
-      } // end of namespace scribo::io::xml::internal
-
-    } // end of namespace scribo::io::xml
-
-  } // end of namespace scribo::io
-
-} // end of namespace scribo
-
-#endif // ! SCRIBO_IO_XML_INTERNAL_HTML_MARKUPS_REPLACE_HH
diff --git a/scribo/scribo/io/xml/internal/print_box_coords.hh b/scribo/scribo/io/xml/internal/print_box_coords.hh
index d3aeedf..ad84709 100644
--- a/scribo/scribo/io/xml/internal/print_box_coords.hh
+++ b/scribo/scribo/io/xml/internal/print_box_coords.hh
@@ -30,6 +30,7 @@
 ///
 /// \brief Prints box2d coordinates to XML data.
 
+# include <fstream>
 # include <mln/core/alias/box2d.hh>
 
 namespace scribo
@@ -44,6 +45,8 @@ namespace scribo
       namespace internal
       {
 
+	using namespace mln;
+
         /*! \brief Prints box2d coordinates to XML data.
 	 */
 	void
diff --git a/scribo/scribo/io/xml/internal/print_page_preambule.hh b/scribo/scribo/io/xml/internal/print_page_preambule.hh
index b5ae891..3ee29be 100644
--- a/scribo/scribo/io/xml/internal/print_page_preambule.hh
+++ b/scribo/scribo/io/xml/internal/print_page_preambule.hh
@@ -30,7 +30,9 @@
 ///
 /// \brief Print PAGE XML format preambule.
 
+# include <fstream>
 # include <mln/core/alias/box2d.hh>
+# include <scribo/core/document.hh>
 
 namespace scribo
 {
@@ -44,6 +46,9 @@ namespace scribo
       namespace internal
       {
 
+	using namespace mln;
+
+
         /// \brief Print PAGE XML format preambule.
 	template <typename L>
 	void print_PAGE_preambule(std::ofstream& output,
diff --git a/scribo/scribo/io/xml/save.hh b/scribo/scribo/io/xml/save.hh
index 30579d0..7428e5d 100644
--- a/scribo/scribo/io/xml/save.hh
+++ b/scribo/scribo/io/xml/save.hh
@@ -121,6 +121,8 @@ namespace scribo
       {
 	trace::entering("scribo::io::xml::save");
 
+	mln_precondition(doc.is_open());
+
 	// Open file
 	std::ofstream output(output_name.c_str());
 	if (! output)
diff --git a/scribo/scribo/text/extract_lines.hh b/scribo/scribo/text/extract_lines.hh
index b81cb79..9949d09 100644
--- a/scribo/scribo/text/extract_lines.hh
+++ b/scribo/scribo/text/extract_lines.hh
@@ -33,8 +33,8 @@
 
 
 # include <mln/core/concept/image.hh>
-# include <mln/value/int_u16.hh>
 
+# include <scribo/core/def/lbl_type.hh>
 # include <scribo/core/line_set.hh>
 
 # include <scribo/primitive/extract/components.hh>
@@ -71,13 +71,13 @@ namespace scribo
     ** \return A set of lines.
     */
     template <typename I, typename N>
-    line_set<mln_ch_value(I,value::int_u16)>
+    line_set<mln_ch_value(I,scribo::def::lbl_type)>
     extract_lines(const Image<I>& input_, const Neighborhood<N>& nbh_,
 		  const mln_ch_value(I,bool)& separators);
 
     /// \overload
     template <typename I, typename N>
-    line_set<mln_ch_value(I,value::int_u16)>
+    line_set<mln_ch_value(I,scribo::def::lbl_type)>
     extract_lines(const Image<I>& input, const Neighborhood<N>& nbh);
 
 
@@ -85,7 +85,7 @@ namespace scribo
 
 
     template <typename I, typename N>
-    line_set<mln_ch_value(I,value::int_u16)>
+    line_set<mln_ch_value(I,scribo::def::lbl_type)>
     extract_lines(const Image<I>& input, const Neighborhood<N>& nbh)
     {
       mln_ch_value(I,bool) seps;
@@ -94,7 +94,7 @@ namespace scribo
 
 
     template <typename I, typename N>
-    line_set<mln_ch_value(I,value::int_u16)>
+    line_set<mln_ch_value(I,scribo::def::lbl_type)>
     extract_lines(const Image<I>& input_, const Neighborhood<N>& nbh_,
 		  const mln_ch_value(I,bool)& separators)
     {
@@ -107,10 +107,10 @@ namespace scribo
       mln_precondition(nbh.is_valid());
 
       /// Finding comps.
-      typedef mln_ch_value(I,value::int_u16) L;
-      value::int_u16 ncomps;
+      typedef mln_ch_value(I,scribo::def::lbl_type) L;
+      scribo::def::lbl_type ncomps;
       component_set<L>
-	comps = scribo::primitive::extract::components(input, c8(), ncomps);
+	comps = scribo::primitive::extract::components(input, nbh, ncomps);
 
       /// First filtering.
       comps = scribo::filter::components_small(comps, 3);
diff --git a/scribo/src/debug/show_info_median_inter_characters.cc b/scribo/src/debug/show_info_median_inter_characters.cc
index b55079d..2ba240e 100644
--- a/scribo/src/debug/show_info_median_inter_characters.cc
+++ b/scribo/src/debug/show_info_median_inter_characters.cc
@@ -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.
 //
@@ -35,7 +35,7 @@
 #include <mln/io/ppm/save.hh>
 
 #include <mln/value/rgb8.hh>
-#include <mln/value/label_16.hh>
+#include <mln/value/int_u16.hh>
 
 #include <mln/draw/box.hh>
 #include <mln/draw/line.hh>
@@ -71,14 +71,14 @@ int main(int argc, char* argv[])
 
 
   image2d<bool> input;
-  io::pbm::load(input, argv[1]);
+  mln::io::pbm::load(input, argv[1]);
 
-  typedef image2d<value::label_16> L;
+  typedef image2d<scribo::def::lbl_type> L;
 
   line_set<L> line = scribo::text::extract_lines(input, c8());
 
   image2d<value::rgb8> output = scribo::debug::char_space_image(input, line);
-  io::ppm::save(output, argv[2]);
+  mln::io::ppm::save(output, argv[2]);
 
   trace::exiting("main");
 }
diff --git a/scribo/src/debug/show_info_x_height.cc b/scribo/src/debug/show_info_x_height.cc
index e5ff8d2..2997230 100644
--- a/scribo/src/debug/show_info_x_height.cc
+++ b/scribo/src/debug/show_info_x_height.cc
@@ -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.
 //
@@ -35,8 +35,8 @@
 #include <mln/io/ppm/save.hh>
 
 #include <mln/value/rgb8.hh>
-#include <mln/value/label_16.hh>
 
+#include <scribo/core/def/lbl_type.hh>
 #include <scribo/text/extract_lines.hh>
 #include <scribo/debug/line_info_image.hh>
 #include <scribo/debug/usage.hh>
@@ -66,14 +66,14 @@ int main(int argc, char* argv[])
 
 
   image2d<bool> input;
-  io::pbm::load(input, argv[1]);
+  mln::io::pbm::load(input, argv[1]);
 
-  typedef image2d<value::label_16> L;
+  typedef image2d<scribo::def::lbl_type> L;
 
   line_set<L> line = scribo::text::extract_lines(input, c8());
 
   image2d<value::rgb8> output = scribo::debug::line_info_image(input, line);
-  io::ppm::save(output, argv[2]);
+  mln::io::ppm::save(output, argv[2]);
 
   trace::exiting("main");
 }
diff --git a/scribo/src/debug/show_text_lines.cc b/scribo/src/debug/show_text_lines.cc
index a031072..368f375 100644
--- a/scribo/src/debug/show_text_lines.cc
+++ b/scribo/src/debug/show_text_lines.cc
@@ -77,7 +77,7 @@ int main(int argc, char* argv[])
   util::timer t;
   t.start();
 
-  typedef image2d<value::int_u16> L;
+  typedef image2d<scribo::def::lbl_type> L;
   line_set<L> lines = text::extract_lines(input, c8(), input_seps);
 
   t.stop();
diff --git a/scribo/src/primitive/extract/separators_nonvisible.cc b/scribo/src/primitive/extract/separators_nonvisible.cc
index 82d4787..d50cc73 100644
--- a/scribo/src/primitive/extract/separators_nonvisible.cc
+++ b/scribo/src/primitive/extract/separators_nonvisible.cc
@@ -27,7 +27,7 @@
 #include <mln/io/pbm/all.hh>
 #include <mln/data/convert.hh>
 
-#include <scribo/primitive/extract/separators_nonvisible2.hh>
+#include <scribo/primitive/extract/separators_nonvisible.hh>
 #include <scribo/debug/usage.hh>
 
 const char *args_desc[][2] =
-- 
1.5.6.5
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                        
                            
                                
                            
                            last-svn-commit-11-gd91174e 2011-03-02 edwin	carlinet <carlinet@lrde.epita.fr>
                        
                        
by edwin carlinet 02 Mar '11
                    by edwin carlinet 02 Mar '11
02 Mar '11
                    
                        Add traits so that dump images of unspecified types can be load and save.
	* milena/mln/trait/value/kind.hh,
	* milena/mln/trait/value_.hh: Add "unknown" name for default types.
---
 milena/ChangeLog               |    7 +++++++
 milena/mln/trait/value/kind.hh |    2 +-
 milena/mln/trait/value_.hh     |    8 ++++++++
 3 files changed, 16 insertions(+), 1 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 9065378..0fafe4a 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,4 +1,11 @@
 2011-03-02  edwin carlinet  <carlinet(a)lrde.epita.fr>
+
+Add traits so that dump images of unspecified types can be load and save.
+
+	* milena/mln/trait/value/kind.hh,
+	* milena/mln/trait/value_.hh: Add "unknown" name for default types.
+
+2011-03-02  edwin carlinet  <carlinet(a)lrde.epita.fr>
 Minor updates to make things compile.
 
 	* milena/mln/core/alias/dpoint2d.hh: add typedef dpoint2df.
diff --git a/milena/mln/trait/value/kind.hh b/milena/mln/trait/value/kind.hh
index a92e631..5f75ab6 100644
--- a/milena/mln/trait/value/kind.hh
+++ b/milena/mln/trait/value/kind.hh
@@ -58,7 +58,7 @@ namespace mln
 	// FIXME: Why not?
 	// label       logic
 	//   \         /     \  
-	//    \   nary_logic   \  
+	//    \   nary_logic g  \  
 	//     \     /   \       \  
 	//     binary   ternary  fuzzy
 	*/
diff --git a/milena/mln/trait/value_.hh b/milena/mln/trait/value_.hh
index 404b204..b33d216 100644
--- a/milena/mln/trait/value_.hh
+++ b/milena/mln/trait/value_.hh
@@ -137,6 +137,14 @@ namespace mln
        * typedef ? comp_1;
        * ...
        */
+
+      // FIXME: hack to allow dumping/loading non-native type.
+      static const char* name()
+      {
+	static std::string s = std::string("unknown");
+	return s.c_str();
+      }
+
     };
 
 
-- 
1.5.6.5
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    02 Mar '11
                    
                        This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Olena, a generic and efficient image processing platform".
The branch features/maxtree has been updated
       via  d91174e2154461f742686aab47be527903b32387 (commit)
      from  6d6177abe961a13bd88357c8701f631267e44a98 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
d91174e 2011-03-02  edwin carlinet  <carlinet(a)lrde.epita.fr>
-----------------------------------------------------------------------
Summary of changes:
 milena/ChangeLog               |    7 +++++++
 milena/mln/trait/value/kind.hh |    2 +-
 milena/mln/trait/value_.hh     |    8 ++++++++
 3 files changed, 16 insertions(+), 1 deletions(-)
hooks/post-receive
-- 
Olena, a generic and efficient image processing platform
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    02 Mar '11
                    
                        This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Olena, a generic and efficient image processing platform".
The branch features/maxtree has been updated
       via  6d6177abe961a13bd88357c8701f631267e44a98 (commit)
      from  81466eb3026e78a9f6c89a9555028a6ff1488b14 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
6d6177a 2011-03-02  edwin carlinet  <carlinet(a)lrde.epita.fr>
-----------------------------------------------------------------------
Summary of changes:
 milena/ChangeLog                         |   11 ++++
 milena/mln/core/alias/dpoint2d.hh        |    1 +
 milena/mln/core/image/attribute_image.hh |    2 +-
 milena/mln/morpho/tree/leaf_last.hh      |    4 +-
 milena/mln/util/ctree/ctree.hh           |    8 ++-
 milena/mln/util/ctree/node.hh            |   90 +++++++++++++++---------------
 6 files changed, 68 insertions(+), 48 deletions(-)
hooks/post-receive
-- 
Olena, a generic and efficient image processing platform
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                        
                            
                                
                            
                            last-svn-commit-10-g6d6177a 2011-03-02 edwin carlinet <carlinet@lrde.epita.fr> Minor updates to make things compile.
                        
                        
by edwin carlinet 02 Mar '11
                    by edwin carlinet 02 Mar '11
02 Mar '11
                    
                        	* milena/mln/core/alias/dpoint2d.hh: add typedef dpoint2df.
	* milena/mln/core/image/attribute_image.hh: add explicit
	constructor.
	* milena/mln/morpho/tree/leaf_last.hh: energy minimization instead
	of maximization.
	* milena/mln/util/ctree/ctree.hh: bug fix.
	* milena/mln/util/ctree/node.hh: put operators outside namespace.
---
 milena/ChangeLog                         |   11 ++++
 milena/mln/core/alias/dpoint2d.hh        |    1 +
 milena/mln/core/image/attribute_image.hh |    2 +-
 milena/mln/morpho/tree/leaf_last.hh      |    4 +-
 milena/mln/util/ctree/ctree.hh           |    8 ++-
 milena/mln/util/ctree/node.hh            |   90 +++++++++++++++---------------
 6 files changed, 68 insertions(+), 48 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index d07d036..9065378 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,14 @@
+2011-03-02  edwin carlinet  <carlinet(a)lrde.epita.fr>
+Minor updates to make things compile.
+
+	* milena/mln/core/alias/dpoint2d.hh: add typedef dpoint2df.
+	* milena/mln/core/image/attribute_image.hh: add explicit
+	constructor.
+	* milena/mln/morpho/tree/leaf_last.hh: energy minimization instead
+	of maximization.
+	* milena/mln/util/ctree/ctree.hh: bug fix.
+	* milena/mln/util/ctree/node.hh: put operators outside namespace.
+
 2010-05-21  edwin carlinet  <carlinet(a)lrde.epita.fr>
 
 	Add MLN_WO_GLOBAL_VARS directive that prevents globals vars to be
diff --git a/milena/mln/core/alias/dpoint2d.hh b/milena/mln/core/alias/dpoint2d.hh
index 1120154..cf07423 100644
--- a/milena/mln/core/alias/dpoint2d.hh
+++ b/milena/mln/core/alias/dpoint2d.hh
@@ -43,6 +43,7 @@ namespace mln
   /// grid with integer coordinates.
   typedef dpoint<mln::grid::square, mln::def::coord> dpoint2d;
 
+  typedef dpoint<mln::grid::square, mln::def::coordf> dpoint2df;
 
 } // end of namespace mln
 
diff --git a/milena/mln/core/image/attribute_image.hh b/milena/mln/core/image/attribute_image.hh
index 1331a6f..cc2d760 100644
--- a/milena/mln/core/image/attribute_image.hh
+++ b/milena/mln/core/image/attribute_image.hh
@@ -160,7 +160,7 @@ namespace mln
     /// Constructor without argument.
     attribute_image();
     /// Allocate an attribute image respecting the size of the tree.
-    attribute_image(const Tree<T>& tree);
+    explicit attribute_image(const Tree<T>& tree);
     /// \}
 
     /// Initialize an empty image.
diff --git a/milena/mln/morpho/tree/leaf_last.hh b/milena/mln/morpho/tree/leaf_last.hh
index 2f283d5..07ad8a1 100644
--- a/milena/mln/morpho/tree/leaf_last.hh
+++ b/milena/mln/morpho/tree/leaf_last.hh
@@ -61,7 +61,7 @@ namespace mln
 
 	  bool operator() (const node_t& lhs, const node_t& rhs)
 	  {
-	    return f_(lhs)  > f_(rhs);
+	    return f_(lhs)  < f_(rhs);
 	  }
 
 	private:
@@ -77,6 +77,8 @@ namespace mln
         typedef typename T::node_t node_t;
 
         p_array<node_t> sorted_sites = convert::to_p_array(ima);
+	mln_invariant(sorted_sites.nsites() == ima.nsites());
+
         std::vector<node_t>& hook = sorted_sites.hook_std_vector_();
 	std::sort(hook.begin(), hook.end(), internal::less_<T, V> (ima));
 
diff --git a/milena/mln/util/ctree/ctree.hh b/milena/mln/util/ctree/ctree.hh
index e1c7148..39e7170 100644
--- a/milena/mln/util/ctree/ctree.hh
+++ b/milena/mln/util/ctree/ctree.hh
@@ -39,9 +39,11 @@
 # include <mln/core/concept/site_set.hh>
 # include <mln/util/ctree/internal/tree_base.hh>
 # include <mln/util/array.hh>
+# include <mln/data/fill.hh>
 # include <mln/core/image/attribute_image.hh>
 # include <algorithm>
 
+
 # define mln_node(T) typename T::node_t
 
 namespace mln
@@ -101,7 +103,7 @@ namespace mln
       std::vector<unsigned>	length_;
       std::vector<mln_value(I)> values_;
 
-      const mln_domain(I)&	domain_;
+      mln_domain(I)		domain_;
       int			nnodes;
     };
 
@@ -244,10 +246,13 @@ namespace mln
 	/// Equivalent to desc(tree.node_at(i)).nsites().
 	unsigned length_at_(index_t i) const;
 	unsigned& length_at_(index_t i);
+
 	rvalue f_at_(index_t i) const;
 	lvalue f_at_(index_t i);
+
 	index_t parent_at_(index_t i) const;
 	index_t& parent_at_(index_t i);
+
 	index_t node_at_(const psite& p) const;
 	index_t& node_at_(const psite& p);
 	/// \}
@@ -342,6 +347,7 @@ namespace mln
 	this->data_ = new mln::internal::data< ctree<I> >(f);
 
 	initialize(this->data_->map_, f);
+	this->data_->domain_ = f.domain();
 	this->data_->parent_.resize(nnodes);
 	this->data_->length_.resize(nnodes);
 	this->data_->values_.resize(nnodes);
diff --git a/milena/mln/util/ctree/node.hh b/milena/mln/util/ctree/node.hh
index ebdc955..8bfc356 100644
--- a/milena/mln/util/ctree/node.hh
+++ b/milena/mln/util/ctree/node.hh
@@ -47,8 +47,8 @@ namespace mln
   {
     namespace ctree
     {
-       template <typename T>
-       class node;
+      template <typename T>
+      class node;
     }
 
   }
@@ -119,26 +119,26 @@ namespace mln
 	int		idx_;
       };
 
-      /*
-      ** Operators.
-      */
-      template <typename T>
-      bool
-      operator== (const node<T>& n1, const node<T>& n2);
+    } // end of namespace mln::util::ctree
 
-      template <typename T>
-      bool
-      operator!= (const node<T>& n1, const node<T>& n2);
+  } // end of namespace mln::util
 
-      /// Test if the node \p n1 is a descendant of \p n2
-      ///
-      template <typename T>
-      bool
-      operator< (const node<T>& n1, const node<T>& n2);
+  /*
+  ** Operators.
+  */
+  template <typename T>
+  bool
+  operator== (const util::ctree::node<T>& n1, const util::ctree::node<T>& n2);
 
-    } // end of namespace mln::util::ctree
+  template <typename T>
+  bool
+  operator!= (const util::ctree::node<T>& n1, const util::ctree::node<T>& n2);
 
-  } // end of namespace mln::util
+  /// Test if the node \p n1 is a descendant of \p n2
+  ///
+  template <typename T>
+  bool
+  operator< (const util::ctree::node<T>& n1, const util::ctree::node<T>& n2);
 
  
   namespace internal
@@ -260,36 +260,36 @@ namespace mln
 	return tree_ != 0 && tree_->is_valid();
       }
 
-      /*
-      ** Operators
-      */
-      template <typename T>
-      inline
-      bool
-      operator== (const node<T>& n1, const node<T>& n2)
-      {
-	return n1.index() == n2.index();
-      }
+    } // end of namespace mln::util::ctree
 
-      template <typename T>
-      inline
-      bool
-      operator!= (const node<T>& n1, const node<T>& n2)
-      {
-	return n1.index() != n2.index();
-      }
+  } // end of namespace mln::util
 
-      template <typename T>
-      inline
-      bool
-      operator< (const node<T>& n1, const node<T>& n2)
-      {
-	return n1.index() > n2.index();
-      }
+  /*
+  ** Operators
+  */
+  template <typename T>
+  inline
+  bool
+  operator== (const util::ctree::node<T>& n1, const util::ctree::node<T>& n2)
+  {
+    return n1.index() == n2.index();
+  }
 
-    } // end of namespace mln::util::ctree
+  template <typename T>
+  inline
+  bool
+  operator!= (const util::ctree::node<T>& n1, const util::ctree::node<T>& n2)
+  {
+    return n1.index() != n2.index();
+  }
 
-  } // end of namespace mln::util
+  template <typename T>
+  inline
+  bool
+  operator< (const util::ctree::node<T>& n1, const util::ctree::node<T>& n2)
+  {
+    return n1.index() > n2.index();
+  }
 
   namespace internal
   {
@@ -322,7 +322,7 @@ namespace mln
       return exact_().get_subject().tree();
     }
 
-   /*------------------------------------------`
+    /*------------------------------------------`
     | subject_impl<       util::ctree::node<T> |
     \-----------------------------------------*/
 
-- 
1.5.6.5
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                        	* scribo/headers.mk,
	* scribo/tests/unit_test/unit-tests.mk: Regen.
	* scribo/tests/unit_test/cond_tests_qt: Add scribo/io/xml/load.hh.
---
 scribo/ChangeLog                     |    9 +++++++++
 scribo/headers.mk                    |   13 ++++++++++++-
 scribo/tests/unit_test/cond_tests_qt |    1 +
 scribo/tests/unit_test/unit-tests.mk |   30 +++++++++++++++++++++++++++---
 4 files changed, 49 insertions(+), 4 deletions(-)
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index bbd0cf2..4eae5f8 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,3 +1,12 @@
+2011-03-02  Guillaume Lazzara  <z(a)lrde.epita.fr>
+
+	Regen mk files.
+
+	* scribo/headers.mk,
+	* scribo/tests/unit_test/unit-tests.mk: Regen.
+
+	* scribo/tests/unit_test/cond_tests_qt: Add scribo/io/xml/load.hh.
+
 2011-03-01  Guillaume Lazzara  <z(a)lrde.epita.fr>
 
 	* scribo/primitive/extract/non_text.hh: Remove debug.
diff --git a/scribo/headers.mk b/scribo/headers.mk
index 7603f8a..0b21a3f 100644
--- a/scribo/headers.mk
+++ b/scribo/headers.mk
@@ -14,17 +14,22 @@ scribo/binarization/sauvola_ms.hh \
 scribo/binarization/sauvola_ms_split.hh \
 scribo/binarization/sauvola_threshold_image.hh \
 scribo/canvas/integral_browsing.hh \
+scribo/convert/from_base64.hh \
 scribo/convert/from_qimage.hh \
+scribo/convert/to_base64.hh \
 scribo/core/all.hh \
 scribo/core/central_sites.hh \
 scribo/core/component_info.hh \
 scribo/core/component_set.hh \
 scribo/core/concept/dmax_functor.hh \
 scribo/core/concept/link_functor.hh \
+scribo/core/concept/serializable.hh \
+scribo/core/concept/serialize_visitor.hh \
 scribo/core/def/lbl_type.hh \
 scribo/core/document.hh \
 scribo/core/erase_objects.hh \
 scribo/core/init_integral_image.hh \
+scribo/core/internal/doc_xml_serializer.hh \
 scribo/core/line_info.hh \
 scribo/core/line_links.hh \
 scribo/core/line_set.hh \
@@ -93,6 +98,12 @@ scribo/fun/v2b/label_to_bool.hh \
 scribo/fun/v2b/objects_large_filter.hh \
 scribo/fun/v2b/objects_small_filter.hh \
 scribo/io/text_boxes/save.hh \
+scribo/io/xml/internal/extended_page_xml_visitor.hh \
+scribo/io/xml/internal/full_xml_visitor.hh \
+scribo/io/xml/internal/page_xml_visitor.hh \
+scribo/io/xml/internal/print_box_coords.hh \
+scribo/io/xml/internal/print_page_preambule.hh \
+scribo/io/xml/load.hh \
 scribo/io/xml/save.hh \
 scribo/make/all.hh \
 scribo/make/debug_filename.hh \
@@ -115,7 +126,6 @@ scribo/primitive/extract/all.hh \
 scribo/primitive/extract/canvas.hh \
 scribo/primitive/extract/cells.hh \
 scribo/primitive/extract/components.hh \
-scribo/primitive/extract/elements.hh \
 scribo/primitive/extract/horizontal_separators.hh \
 scribo/primitive/extract/lines_discontinued.hh \
 scribo/primitive/extract/lines_h_discontinued.hh \
@@ -130,6 +140,7 @@ scribo/primitive/extract/lines_v_pattern.hh \
 scribo/primitive/extract/lines_v_single.hh \
 scribo/primitive/extract/lines_v_thick.hh \
 scribo/primitive/extract/lines_v_thick_and_single.hh \
+scribo/primitive/extract/non_text.hh \
 scribo/primitive/extract/separators.hh \
 scribo/primitive/extract/separators_nonvisible.hh \
 scribo/primitive/extract/vertical_separators.hh \
diff --git a/scribo/tests/unit_test/cond_tests_qt b/scribo/tests/unit_test/cond_tests_qt
index 5428215..577f9e6 100644
--- a/scribo/tests/unit_test/cond_tests_qt
+++ b/scribo/tests/unit_test/cond_tests_qt
@@ -1 +1,2 @@
 scribo/convert/from_qimage.hh
+scribo/io/xml/load.hh
diff --git a/scribo/tests/unit_test/unit-tests.mk b/scribo/tests/unit_test/unit-tests.mk
index 6a8f29d..71b0b5b 100644
--- a/scribo/tests/unit_test/unit-tests.mk
+++ b/scribo/tests/unit_test/unit-tests.mk
@@ -19,11 +19,15 @@ endif HAVE_MAGICKXX
 # Starting a conditional unit test list.
 if HAVE_QT
 check_PROGRAMS +=  \
-scribo_convert_from_qimage
+scribo_convert_from_qimage \
+scribo_io_xml_load
 
 scribo_convert_from_qimage_CPPFLAGS= ${QT_CPPFLAGS}  ${AM_CPPFLAGS}
 scribo_convert_from_qimage_LDFLAGS= ${QT_LDFLAGS}  ${AM_LDFLAGS}
 scribo_convert_from_qimage_SOURCES = scribo_convert_from_qimage.cc
+scribo_io_xml_load_CPPFLAGS= ${QT_CPPFLAGS}  ${AM_CPPFLAGS}
+scribo_io_xml_load_LDFLAGS= ${QT_LDFLAGS}  ${AM_LDFLAGS}
+scribo_io_xml_load_SOURCES = scribo_io_xml_load.cc
 endif HAVE_QT
 
 # Starting a conditional unit test list.
@@ -79,16 +83,21 @@ scribo_binarization_sauvola_ms \
 scribo_binarization_sauvola_ms_split \
 scribo_binarization_sauvola_threshold_image \
 scribo_canvas_integral_browsing \
+scribo_convert_from_base64 \
+scribo_convert_to_base64 \
 scribo_core_all \
 scribo_core_central_sites \
 scribo_core_component_info \
 scribo_core_component_set \
 scribo_core_concept_dmax_functor \
 scribo_core_concept_link_functor \
+scribo_core_concept_serializable \
+scribo_core_concept_serialize_visitor \
 scribo_core_def_lbl_type \
 scribo_core_document \
 scribo_core_erase_objects \
 scribo_core_init_integral_image \
+scribo_core_internal_doc_xml_serializer \
 scribo_core_line_info \
 scribo_core_line_links \
 scribo_core_line_set \
@@ -157,6 +166,11 @@ scribo_fun_v2b_label_to_bool \
 scribo_fun_v2b_objects_large_filter \
 scribo_fun_v2b_objects_small_filter \
 scribo_io_text_boxes_save \
+scribo_io_xml_internal_extended_page_xml_visitor \
+scribo_io_xml_internal_full_xml_visitor \
+scribo_io_xml_internal_page_xml_visitor \
+scribo_io_xml_internal_print_box_coords \
+scribo_io_xml_internal_print_page_preambule \
 scribo_io_xml_save \
 scribo_make_all \
 scribo_make_debug_filename \
@@ -179,7 +193,6 @@ scribo_primitive_extract_all \
 scribo_primitive_extract_canvas \
 scribo_primitive_extract_cells \
 scribo_primitive_extract_components \
-scribo_primitive_extract_elements \
 scribo_primitive_extract_horizontal_separators \
 scribo_primitive_extract_lines_discontinued \
 scribo_primitive_extract_lines_h_discontinued \
@@ -194,6 +207,7 @@ scribo_primitive_extract_lines_v_pattern \
 scribo_primitive_extract_lines_v_single \
 scribo_primitive_extract_lines_v_thick \
 scribo_primitive_extract_lines_v_thick_and_single \
+scribo_primitive_extract_non_text \
 scribo_primitive_extract_separators \
 scribo_primitive_extract_separators_nonvisible \
 scribo_primitive_extract_vertical_separators \
@@ -286,16 +300,21 @@ scribo_binarization_sauvola_ms_SOURCES = scribo_binarization_sauvola_ms.cc
 scribo_binarization_sauvola_ms_split_SOURCES = scribo_binarization_sauvola_ms_split.cc
 scribo_binarization_sauvola_threshold_image_SOURCES = scribo_binarization_sauvola_threshold_image.cc
 scribo_canvas_integral_browsing_SOURCES = scribo_canvas_integral_browsing.cc
+scribo_convert_from_base64_SOURCES = scribo_convert_from_base64.cc
+scribo_convert_to_base64_SOURCES = scribo_convert_to_base64.cc
 scribo_core_all_SOURCES = scribo_core_all.cc
 scribo_core_central_sites_SOURCES = scribo_core_central_sites.cc
 scribo_core_component_info_SOURCES = scribo_core_component_info.cc
 scribo_core_component_set_SOURCES = scribo_core_component_set.cc
 scribo_core_concept_dmax_functor_SOURCES = scribo_core_concept_dmax_functor.cc
 scribo_core_concept_link_functor_SOURCES = scribo_core_concept_link_functor.cc
+scribo_core_concept_serializable_SOURCES = scribo_core_concept_serializable.cc
+scribo_core_concept_serialize_visitor_SOURCES = scribo_core_concept_serialize_visitor.cc
 scribo_core_def_lbl_type_SOURCES = scribo_core_def_lbl_type.cc
 scribo_core_document_SOURCES = scribo_core_document.cc
 scribo_core_erase_objects_SOURCES = scribo_core_erase_objects.cc
 scribo_core_init_integral_image_SOURCES = scribo_core_init_integral_image.cc
+scribo_core_internal_doc_xml_serializer_SOURCES = scribo_core_internal_doc_xml_serializer.cc
 scribo_core_line_info_SOURCES = scribo_core_line_info.cc
 scribo_core_line_links_SOURCES = scribo_core_line_links.cc
 scribo_core_line_set_SOURCES = scribo_core_line_set.cc
@@ -364,6 +383,11 @@ scribo_fun_v2b_label_to_bool_SOURCES = scribo_fun_v2b_label_to_bool.cc
 scribo_fun_v2b_objects_large_filter_SOURCES = scribo_fun_v2b_objects_large_filter.cc
 scribo_fun_v2b_objects_small_filter_SOURCES = scribo_fun_v2b_objects_small_filter.cc
 scribo_io_text_boxes_save_SOURCES = scribo_io_text_boxes_save.cc
+scribo_io_xml_internal_extended_page_xml_visitor_SOURCES = scribo_io_xml_internal_extended_page_xml_visitor.cc
+scribo_io_xml_internal_full_xml_visitor_SOURCES = scribo_io_xml_internal_full_xml_visitor.cc
+scribo_io_xml_internal_page_xml_visitor_SOURCES = scribo_io_xml_internal_page_xml_visitor.cc
+scribo_io_xml_internal_print_box_coords_SOURCES = scribo_io_xml_internal_print_box_coords.cc
+scribo_io_xml_internal_print_page_preambule_SOURCES = scribo_io_xml_internal_print_page_preambule.cc
 scribo_io_xml_save_SOURCES = scribo_io_xml_save.cc
 scribo_make_all_SOURCES = scribo_make_all.cc
 scribo_make_debug_filename_SOURCES = scribo_make_debug_filename.cc
@@ -386,7 +410,6 @@ scribo_primitive_extract_all_SOURCES = scribo_primitive_extract_all.cc
 scribo_primitive_extract_canvas_SOURCES = scribo_primitive_extract_canvas.cc
 scribo_primitive_extract_cells_SOURCES = scribo_primitive_extract_cells.cc
 scribo_primitive_extract_components_SOURCES = scribo_primitive_extract_components.cc
-scribo_primitive_extract_elements_SOURCES = scribo_primitive_extract_elements.cc
 scribo_primitive_extract_horizontal_separators_SOURCES = scribo_primitive_extract_horizontal_separators.cc
 scribo_primitive_extract_lines_discontinued_SOURCES = scribo_primitive_extract_lines_discontinued.cc
 scribo_primitive_extract_lines_h_discontinued_SOURCES = scribo_primitive_extract_lines_h_discontinued.cc
@@ -401,6 +424,7 @@ scribo_primitive_extract_lines_v_pattern_SOURCES = scribo_primitive_extract_line
 scribo_primitive_extract_lines_v_single_SOURCES = scribo_primitive_extract_lines_v_single.cc
 scribo_primitive_extract_lines_v_thick_SOURCES = scribo_primitive_extract_lines_v_thick.cc
 scribo_primitive_extract_lines_v_thick_and_single_SOURCES = scribo_primitive_extract_lines_v_thick_and_single.cc
+scribo_primitive_extract_non_text_SOURCES = scribo_primitive_extract_non_text.cc
 scribo_primitive_extract_separators_SOURCES = scribo_primitive_extract_separators.cc
 scribo_primitive_extract_separators_nonvisible_SOURCES = scribo_primitive_extract_separators_nonvisible.cc
 scribo_primitive_extract_vertical_separators_SOURCES = scribo_primitive_extract_vertical_separators.cc
-- 
1.5.6.5
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                        
                            
                                
                            
                            last-svn-commit-784-gf4cad33	scribo/primitive/extract/non_text.hh: Remove debug.
                        
                        
by Guillaume Lazzara 01 Mar '11
                    by Guillaume Lazzara 01 Mar '11
01 Mar '11
                    
                        ---
 scribo/ChangeLog                            |    4 ++++
 scribo/scribo/primitive/extract/non_text.hh |   21 ---------------------
 2 files changed, 4 insertions(+), 21 deletions(-)
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index 4a9dcbf..bbd0cf2 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,5 +1,9 @@
 2011-03-01  Guillaume Lazzara  <z(a)lrde.epita.fr>
 
+	* scribo/primitive/extract/non_text.hh: Remove debug.
+
+2011-03-01  Guillaume Lazzara  <z(a)lrde.epita.fr>
+
 	Add new debug tools.
 
 	* scribo/src/debug/Makefile.am: New targets.
diff --git a/scribo/scribo/primitive/extract/non_text.hh b/scribo/scribo/primitive/extract/non_text.hh
index a017f1f..8528782 100644
--- a/scribo/scribo/primitive/extract/non_text.hh
+++ b/scribo/scribo/primitive/extract/non_text.hh
@@ -58,10 +58,6 @@
 # include <mln/clustering/kmean_rgb.hh>
 # include <mln/fun/v2v/rgb8_to_rgbn.hh>
 
-# include <mln/util/timer.hh>
-
-# include <mln/io/pbm/save.hh>
-
 namespace scribo
 {
 
@@ -139,16 +135,9 @@ namespace scribo
 	  image2d<t_rgb5>
 	    img_rgb5 = mln::data::transform(doc.image(), t_rgb8_to_rgb5());
 
-	  // DEBUG
-	  io::pbm::save(content, "text_area.pbm");
-
-	  mln::util::timer t;
-	  t.start();
 	  img_lbl8 =
 	    mln::clustering::kmean_rgb<double,5>((img_rgb5 | pw::value(content)), 3, 10, 10).unmorph_();
 	  data::fill((img_lbl8 | !pw::value(content)).rw(), 0u);
-	  t.stop();
-	  std::cout << t << std::endl;
 
 	  mln::util::array<unsigned>
 	    card = mln::labeling::compute(accu::math::count<value::label_8>(),
@@ -178,19 +167,9 @@ namespace scribo
 	  data::fill(elts, false);
 	  data::fill((elts | (pw::value(img_lbl8) != pw::cst(0))).rw(), true);
 
-	  // DEBUG
-	  data::fill((elts | (pw::value(doc.line_seps()) != pw::cst(0))).rw(),
-		     false);
-	  // END OF DEBUG
-
-
 	  scribo::def::lbl_type nlabels;
 	  elts = filter::components_small(elts, c8(), nlabels, 40);
 
-	  // DEBUG
-	  io::pbm::save(elts, "elements.pbm");
-	  // END OF DEBUG
-
 	  output = primitive::extract::components(elts, c8(), nlabels);
 	}
 
-- 
1.5.6.5
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    01 Mar '11
                    
                        	* scribo/core/component_info.hh,
	* scribo/core/component_set.hh,
	* scribo/core/document.hh,
	* scribo/core/line_info.hh,
	* scribo/core/line_links.hh,
	* scribo/core/object_groups.hh,
	* scribo/core/object_links.hh,
	* scribo/core/paragraph_set.hh: Make these classes serializable.
	* scribo/core/concept/serializable.hh,
	* scribo/core/concept/serialize_visitor.hh: New concepts.
	* scribo/core/internal/doc_xml_serializer.hh: New. Base
	implementation.
	* scribo/io/xml/internal/extended_page_xml_visitor.hh,
	* scribo/io/xml/internal/full_xml_visitor.hh,
	* scribo/io/xml/internal/page_xml_visitor.hh: New. Visitors
	producing different XML outputs.
	* scribo/io/xml/internal/html_markups_replace.hh,
	* scribo/io/xml/internal/print_box_coords.hh,
	* scribo/io/xml/internal/print_page_preambule.hh: New. Tools for
	XML output.
	* scribo/io/xml/save.hh: Make use of visitors.
	* scribo/toolchain/internal/content_in_doc_functor.hh: Set default
	XML output type.
	* src/content_in_doc.cc: Produce several XML output.
---
 scribo/ChangeLog                                   |   38 ++
 scribo/demo/viewer/runner.cc                       |    5 +-
 scribo/scribo/core/component_info.hh               |    3 +-
 scribo/scribo/core/component_set.hh                |    7 +-
 scribo/scribo/core/concept/serializable.hh         |   64 +++
 scribo/scribo/core/concept/serialize_visitor.hh    |   49 +++
 scribo/scribo/core/document.hh                     |    8 +-
 scribo/scribo/core/internal/doc_xml_serializer.hh  |  140 ++++++
 scribo/scribo/core/line_info.hh                    |   21 +-
 scribo/scribo/core/line_links.hh                   |    3 +-
 scribo/scribo/core/object_groups.hh                |    4 +-
 scribo/scribo/core/object_links.hh                 |    8 +-
 scribo/scribo/core/paragraph_set.hh                |    4 +-
 .../io/xml/internal/extended_page_xml_visitor.hh   |  283 ++++++++++++
 scribo/scribo/io/xml/internal/full_xml_visitor.hh  |  456 ++++++++++++++++++++
 .../scribo/io/xml/internal/html_markups_replace.hh |   97 +++++
 scribo/scribo/io/xml/internal/page_xml_visitor.hh  |  222 ++++++++++
 scribo/scribo/io/xml/internal/print_box_coords.hh  |   92 ++++
 .../scribo/io/xml/internal/print_page_preambule.hh |   95 ++++
 scribo/scribo/io/xml/save.hh                       |  388 +++--------------
 .../toolchain/internal/content_in_doc_functor.hh   |    9 +-
 scribo/src/content_in_doc.cc                       |    4 +-
 22 files changed, 1660 insertions(+), 340 deletions(-)
 create mode 100644 scribo/scribo/core/concept/serializable.hh
 create mode 100644 scribo/scribo/core/concept/serialize_visitor.hh
 create mode 100644 scribo/scribo/core/internal/doc_xml_serializer.hh
 create mode 100644 scribo/scribo/io/xml/internal/extended_page_xml_visitor.hh
 create mode 100644 scribo/scribo/io/xml/internal/full_xml_visitor.hh
 create mode 100644 scribo/scribo/io/xml/internal/html_markups_replace.hh
 create mode 100644 scribo/scribo/io/xml/internal/page_xml_visitor.hh
 create mode 100644 scribo/scribo/io/xml/internal/print_box_coords.hh
 create mode 100644 scribo/scribo/io/xml/internal/print_page_preambule.hh
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index 330338a..6571137 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,5 +1,43 @@
 2011-03-01  Guillaume Lazzara  <z(a)lrde.epita.fr>
 
+	Make XML output more flexible.
+
+	* scribo/core/component_info.hh,
+	* scribo/core/component_set.hh,
+	* scribo/core/document.hh,
+	* scribo/core/line_info.hh,
+	* scribo/core/line_links.hh,
+	* scribo/core/object_groups.hh,
+	* scribo/core/object_links.hh,
+	* scribo/core/paragraph_set.hh: Make these classes serializable.
+
+	* scribo/core/concept/serializable.hh,
+	* scribo/core/concept/serialize_visitor.hh: New concepts.
+
+	* scribo/core/internal/doc_xml_serializer.hh: New. Base
+	implementation.
+
+	* scribo/io/xml/internal/extended_page_xml_visitor.hh,
+	* scribo/io/xml/internal/full_xml_visitor.hh,
+	* scribo/io/xml/internal/page_xml_visitor.hh: New. Visitors
+	producing different XML outputs.
+
+	* scribo/io/xml/internal/html_markups_replace.hh,
+	* scribo/io/xml/internal/print_box_coords.hh,
+	* scribo/io/xml/internal/print_page_preambule.hh: New. Tools for
+	XML output.
+
+	* scribo/io/xml/save.hh: Make use of visitors.
+
+	* scribo/toolchain/internal/content_in_doc_functor.hh: Set default
+	XML output type.
+
+	* src/content_in_doc.cc: Produce several XML output.
+
+	* demo/viewer/runner.cc: Update call to io::xml::save.
+
+2011-03-01  Guillaume Lazzara  <z(a)lrde.epita.fr>
+
 	Set component type during component extraction.
 
 	* scribo/core/component_info.hh,
diff --git a/scribo/demo/viewer/runner.cc b/scribo/demo/viewer/runner.cc
index 86ff5dc..a3cc883 100644
--- a/scribo/demo/viewer/runner.cc
+++ b/scribo/demo/viewer/runner.cc
@@ -1,4 +1,5 @@
-// Copyright (C) 2010 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2010, 2011 EPITA Research and Development Laboratory
+// (LRDE)
 //
 // This file is part of Olena.
 //
@@ -156,7 +157,7 @@ void runner::process(const image2d<value::rgb8>& original_ima,
   f.enable_whitespace_seps = (find_seps == defs::Whitespaces
 			      || find_seps == defs::LinesAndWhitespaces);
 
-  f.allow_xml_extensions = true;
+  f.xml_format = scribo::io::xml::PageExtended;
 
 
   f.save_doc_as_xml = true;
diff --git a/scribo/scribo/core/component_info.hh b/scribo/scribo/core/component_info.hh
index 6fc73f8..f825aee 100644
--- a/scribo/scribo/core/component_info.hh
+++ b/scribo/scribo/core/component_info.hh
@@ -36,6 +36,7 @@
 # include <mln/core/alias/point2d.hh>
 # include <mln/util/object_id.hh>
 
+# include <scribo/core/concept/serializable.hh>
 # include <scribo/core/tag/component.hh>
 # include <scribo/core/tag/line.hh>
 
@@ -44,7 +45,7 @@ namespace scribo
 
   typedef mln::util::object_id<scribo::ComponentId, unsigned> component_id_t;
 
-  class component_info
+  class component_info : public Serializable<component_info>
   {
     typedef mln::util::object_id<scribo::ComponentId, unsigned> component_id_t;
 
diff --git a/scribo/scribo/core/component_set.hh b/scribo/scribo/core/component_set.hh
index 442e8d6..a63ed6c 100644
--- a/scribo/scribo/core/component_set.hh
+++ b/scribo/scribo/core/component_set.hh
@@ -30,6 +30,10 @@
 /// \file
 ///
 /// \brief Definition of a component set.
+///
+/// \fixme component_set should always set a component type in order
+/// to be fully supported by visitors.
+
 
 # include <mln/core/concept/site_set.hh>
 # include <mln/core/concept/function.hh>
@@ -59,6 +63,7 @@
 
 # include <scribo/core/macros.hh>
 # include <scribo/core/component_info.hh>
+# include <scribo/core/concept/serializable.hh>
 
 
 namespace scribo
@@ -115,7 +120,7 @@ namespace scribo
 
 
   template <typename L>
-  class component_set
+  class component_set : public Serializable<component_set<L> >
   {
     typedef mln::accu::shape::bbox<mln_site(L)> bbox_accu_t;
     typedef mln::accu::center<mln_site(L)> center_accu_t;
diff --git a/scribo/scribo/core/concept/serializable.hh b/scribo/scribo/core/concept/serializable.hh
new file mode 100644
index 0000000..6e661a6
--- /dev/null
+++ b/scribo/scribo/core/concept/serializable.hh
@@ -0,0 +1,64 @@
+// Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena.  If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction.  Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License.  This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef SCRIBO_CORE_CONCEPT_SERIALIZABLE_HH
+# define SCRIBO_CORE_CONCEPT_SERIALIZABLE_HH
+
+/// \file
+///
+/// Concept for serializer visitors.
+
+# include <mln/core/concept/object.hh>
+# include <scribo/core/concept/serialize_visitor.hh>
+
+namespace scribo
+{
+
+  /// \brief Link functor concept.
+  template <typename E>
+  class Serializable : public mln::Object<E>
+  {
+  public:
+    template <typename E2>
+    void accept(const SerializeVisitor<E2>& visitor) const;
+  };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+  template <typename E>
+  template <typename E2>
+  void
+  Serializable<E>::accept(const SerializeVisitor<E2>& visitor) const
+  {
+    exact(visitor).visit(exact(*this));
+  }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+
+} // end of namespace scribo
+
+#endif // SCRIBO_CORE_CONCEPT_SERIALIZABLE_HH
diff --git a/scribo/scribo/core/concept/serialize_visitor.hh b/scribo/scribo/core/concept/serialize_visitor.hh
new file mode 100644
index 0000000..e5e598f
--- /dev/null
+++ b/scribo/scribo/core/concept/serialize_visitor.hh
@@ -0,0 +1,49 @@
+// Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena.  If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction.  Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License.  This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef SCRIBO_CORE_CONCEPT_SERIALIZE_VISITOR_HH
+# define SCRIBO_CORE_CONCEPT_SERIALIZE_VISITOR_HH
+
+/// \file
+///
+/// Concept for serializer visitors.
+
+# include <mln/core/concept/object.hh>
+
+namespace scribo
+{
+
+  /// \brief Link functor concept.
+  template <typename E>
+  class SerializeVisitor : public mln::Object<E>
+  {
+  public:
+    // void visit(..);
+  };
+
+
+} // end of namespace scribo
+
+#endif // SCRIBO_CORE_CONCEPT_SERIALIZE_VISITOR_HH
diff --git a/scribo/scribo/core/document.hh b/scribo/scribo/core/document.hh
index ef0869e..372f0a4 100644
--- a/scribo/scribo/core/document.hh
+++ b/scribo/scribo/core/document.hh
@@ -40,13 +40,15 @@
 # include <scribo/core/line_set.hh>
 # include <scribo/core/paragraph_set.hh>
 
+# include <scribo/core/concept/serializable.hh>
+
 # include <scribo/primitive/extract/components.hh>
 
 namespace scribo
 {
 
   template <typename L>
-  struct document
+  struct document : public Serializable<document<L> >
   {
   public:
 
@@ -98,7 +100,7 @@ namespace scribo
 
 
   private:
-    const char *filename_;
+    std::string filename_;
     mln::image2d<mln::value::rgb8> image_;
 
     paragraph_set<L> parset_;
@@ -142,7 +144,7 @@ namespace scribo
   const char *
   document<L>::filename() const
   {
-    return filename_;
+    return filename_.c_str();
   }
 
 
diff --git a/scribo/scribo/core/internal/doc_xml_serializer.hh b/scribo/scribo/core/internal/doc_xml_serializer.hh
new file mode 100644
index 0000000..b64c9d4
--- /dev/null
+++ b/scribo/scribo/core/internal/doc_xml_serializer.hh
@@ -0,0 +1,140 @@
+// Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena.  If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction.  Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License.  This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef SCRIBO_CORE_INTERNAL_DOC_XML_SERIALIZER_HH
+# define SCRIBO_CORE_INTERNAL_DOC_XML_SERIALIZER_HH
+
+/// \file
+///
+/// Concept for serializer visitors.
+
+# include <scribo/core/concept/serialize_visitor.hh>
+
+# include <scribo/core/document.hh>
+# include <scribo/core/component_set.hh>
+# include <scribo/core/component_info.hh>
+# include <scribo/core/paragraph_set.hh>
+# include <scribo/core/object_groups.hh>
+# include <scribo/core/object_links.hh>
+# include <scribo/core/line_links.hh>
+# include <scribo/core/line_info.hh>
+
+namespace scribo
+{
+
+  /// \brief Link functor concept.
+  template <typename E>
+  class doc_xml_serializer : public SerializeVisitor<E>
+  {
+  public:
+    // Visit overloads
+    template <typename L>
+    void visit(const document<L>& doc) const;
+
+    template <typename L>
+    void visit(const line_links<L>& llinks) const;
+
+    template <typename L>
+    void visit(const object_groups<L>& groups) const;
+
+    template <typename L>
+    void visit(const object_links<L>& links) const;
+
+    template <typename L>
+    void visit(const component_set<L>& comp_set) const;
+
+    void visit(const component_info& info) const;
+
+    template <typename L>
+    void visit(const paragraph_set<L>& parset) const;
+
+    template <typename L>
+    void visit(const line_info<L>& line) const;
+  };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+  template <typename E>
+  template <typename L>
+  void
+  doc_xml_serializer<E>::visit(const document<L>& doc) const
+  {
+  }
+
+  template <typename E>
+  template <typename L>
+  void
+  doc_xml_serializer<E>::visit(const line_links<L>& llinks) const
+  {
+  }
+
+  template <typename E>
+  template <typename L>
+  void
+  doc_xml_serializer<E>::visit(const object_groups<L>& groups) const
+  {
+  }
+
+  template <typename E>
+  template <typename L>
+  void
+  doc_xml_serializer<E>::visit(const object_links<L>& links) const
+  {
+  }
+
+  template <typename E>
+  template <typename L>
+  void
+  doc_xml_serializer<E>::visit(const component_set<L>& comp_set) const
+  {
+  }
+
+  template <typename E>
+  void
+  doc_xml_serializer<E>::visit(const component_info& info) const
+  {
+  }
+
+  template <typename E>
+  template <typename L>
+  void
+  doc_xml_serializer<E>::visit(const paragraph_set<L>& parset) const
+  {
+  }
+
+  template <typename E>
+  template <typename L>
+  void
+  doc_xml_serializer<E>::visit(const line_info<L>& line) const
+  {
+  }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+
+} // end of namespace scribo
+
+#endif // SCRIBO_CORE_INTERNAL_DOC_XML_SERIALIZER_HH
diff --git a/scribo/scribo/core/line_info.hh b/scribo/scribo/core/line_info.hh
index c82160a..33a1529 100644
--- a/scribo/scribo/core/line_info.hh
+++ b/scribo/scribo/core/line_info.hh
@@ -53,6 +53,11 @@
 # include <scribo/core/line_set.hh>
 # include <scribo/core/component_set.hh>
 
+# include <scribo/io/xml/internal/html_markups_replace.hh>
+
+# include <scribo/core/concept/serializable.hh>
+
+
 namespace scribo
 {
 
@@ -114,6 +119,7 @@ namespace scribo
       bool indented_;
 
       std::string text_;
+      std::string html_text_;
 
       // Line set holding this element.
       line_set<L> holder_;
@@ -125,7 +131,7 @@ namespace scribo
 
 
   template <typename L>
-  class line_info
+  class line_info : public Serializable<line_info<L> >
   {
     typedef internal::line_info_data<L> data_t;
     typedef mln::util::object_id<scribo::ComponentId, unsigned> component_id_t;
@@ -198,6 +204,7 @@ namespace scribo
 
     bool has_text() const;
     const std::string& text() const;
+    const std::string& html_text() const;
     void update_text(const std::string& str);
 
     bool is_valid() const;
@@ -604,6 +611,7 @@ namespace scribo
     return data_->indented_;
   }
 
+
   template <typename L>
   bool
   line_info<L>::has_text() const
@@ -611,6 +619,7 @@ namespace scribo
     return !data_->text_.empty();
   }
 
+
   template <typename L>
   const std::string&
   line_info<L>::text() const
@@ -620,10 +629,19 @@ namespace scribo
 
 
   template <typename L>
+  const std::string&
+  line_info<L>::html_text() const
+  {
+    return data_->html_text_;
+  }
+
+
+  template <typename L>
   void
   line_info<L>::update_text(const std::string& str)
   {
     data_->text_ = str;
+    data_->html_text_ = scribo::io::xml::internal::html_markups_replace(str);
   }
 
 
@@ -987,6 +1005,7 @@ namespace scribo
 		<< ", indented=" << info.indented()
 		<< ", hidden=" << info.is_hidden()
 		<< ", text=" << info.text()
+		<< ", html_text=" << info.html_text()
 		<< ")" << std::endl;
   }
 
diff --git a/scribo/scribo/core/line_links.hh b/scribo/scribo/core/line_links.hh
index de62158..fdd09a5 100644
--- a/scribo/scribo/core/line_links.hh
+++ b/scribo/scribo/core/line_links.hh
@@ -34,6 +34,7 @@
 # include <mln/util/array.hh>
 # include <mln/util/tracked_ptr.hh>
 
+# include <scribo/core/concept/serializable.hh>
 # include <scribo/core/line_set.hh>
 
 
@@ -69,7 +70,7 @@ namespace scribo
   /// \brief Line group representation.
   //
   template <typename L>
-  class line_links
+  class line_links : public Serializable<line_links<L> >
   {
     typedef internal::line_links_data<L> data_t;
 
diff --git a/scribo/scribo/core/object_groups.hh b/scribo/scribo/core/object_groups.hh
index 9d9fb25..bbfaf6e 100644
--- a/scribo/scribo/core/object_groups.hh
+++ b/scribo/scribo/core/object_groups.hh
@@ -36,6 +36,8 @@
 # include <scribo/core/object_links.hh>
 # include <scribo/core/component_set.hh>
 
+# include <scribo/core/concept/serializable.hh>
+
 namespace scribo
 {
 
@@ -69,7 +71,7 @@ namespace scribo
   /// \brief Object group representation.
   //
   template <typename L>
-  class object_groups
+  class object_groups : public Serializable<object_groups<L> >
   {
     typedef internal::object_groups_data<L> data_t;
 
diff --git a/scribo/scribo/core/object_links.hh b/scribo/scribo/core/object_links.hh
index af7dc38..2c2eea1 100644
--- a/scribo/scribo/core/object_links.hh
+++ b/scribo/scribo/core/object_links.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.
 //
@@ -37,6 +37,8 @@
 
 # include <scribo/core/component_set.hh>
 
+# include <scribo/core/concept/serializable.hh>
+
 
 namespace scribo
 {
@@ -70,7 +72,7 @@ namespace scribo
   /// \brief Object group representation.
   //
   template <typename L>
-  class object_links
+  class object_links : public Serializable<object_links<L> >
   {
     typedef internal::object_links_data<L> data_t;
 
diff --git a/scribo/scribo/core/paragraph_set.hh b/scribo/scribo/core/paragraph_set.hh
index 6597189..5451069 100644
--- a/scribo/scribo/core/paragraph_set.hh
+++ b/scribo/scribo/core/paragraph_set.hh
@@ -33,6 +33,8 @@
 # include <scribo/core/line_set.hh>
 # include <scribo/core/paragraph_info.hh>
 
+# include <scribo/core/concept/serializable.hh>
+
 namespace scribo
 {
 
@@ -61,7 +63,7 @@ namespace scribo
 
    */
   template <typename L>
-  class paragraph_set
+  class paragraph_set : public Serializable<paragraph_set<L> >
   {
   public:
     paragraph_set();
diff --git a/scribo/scribo/io/xml/internal/extended_page_xml_visitor.hh b/scribo/scribo/io/xml/internal/extended_page_xml_visitor.hh
new file mode 100644
index 0000000..5d8a672
--- /dev/null
+++ b/scribo/scribo/io/xml/internal/extended_page_xml_visitor.hh
@@ -0,0 +1,283 @@
+// Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena.  If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction.  Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License.  This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef SCRIBO_IO_XML_INTERNAL_EXTENDED_PAGE_XML_VISITOR_HH
+# define SCRIBO_IO_XML_INTERNAL_EXTENDED_PAGE_XML_VISITOR_HH
+
+/// \file
+///
+/// Extended XML PAGE format serializer Visitor.
+
+# include <fstream>
+# include <scribo/core/internal/doc_xml_serializer.hh>
+# include <scribo/core/document.hh>
+# include <scribo/core/component_set.hh>
+# include <scribo/core/paragraph_set.hh>
+# include <scribo/core/object_groups.hh>
+# include <scribo/core/object_links.hh>
+# include <scribo/core/line_links.hh>
+# include <scribo/core/line_info.hh>
+
+# include <scribo/convert/to_base64.hh>
+
+# include <scribo/io/xml/internal/print_box_coords.hh>
+# include <scribo/io/xml/internal/print_page_preambule.hh>
+
+
+namespace scribo
+{
+
+  namespace io
+  {
+
+    namespace xml
+    {
+
+      namespace internal
+      {
+
+
+	class extended_page_xml_visitor : public doc_xml_serializer<extended_page_xml_visitor>
+	{
+	public:
+	  // Constructor
+	  extended_page_xml_visitor(std::ofstream& out);
+
+	  // Visit overloads
+	  template <typename L>
+	  void visit(const document<L>& doc) const;
+
+	  template <typename L>
+	  void visit(const component_set<L>& comp_set) const;
+
+	  void visit(const component_info& info) const;
+
+	  template <typename L>
+	  void visit(const paragraph_set<L>& parset) const;
+
+	  template <typename L>
+	  void visit(const line_info<L>& line) const;
+
+	private: // Attributes
+	  std::ofstream& output;
+	};
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+	inline
+	extended_page_xml_visitor::extended_page_xml_visitor(std::ofstream& out)
+	  : output(out)
+	{
+	}
+
+
+
+	/// Document
+	//
+	template <typename L>
+	void
+	extended_page_xml_visitor::visit(const document<L>& doc) const
+ 	{
+	  // Preambule
+	  print_PAGE_preambule(output, doc, false);
+
+	  // Text
+	  if (doc.has_text())
+	    doc.paragraphs().accept(*this);
+
+
+	  // Page elements (Pictures, ...)
+	  if (doc.has_elements())
+	    doc.elements().accept(*this);
+
+	  // Whitespace seraparators
+	  if (doc.has_whitespace_seps())
+	    doc.whitespace_seps_comps().accept(*this);
+
+	  output << "  </page>" << std::endl;
+	  output << "</pcGts>" << std::endl;
+
+	}
+
+	/// Component Set
+	//
+	template <typename L>
+	void
+	extended_page_xml_visitor::visit(const component_set<L>& comp_set) const
+	{
+	  for_all_comps(c, comp_set)
+	    if (comp_set(c).is_valid())
+	      comp_set(c).accept(*this);
+	}
+
+
+	/// Component_info
+	//
+	inline
+	void
+	extended_page_xml_visitor::visit(const component_info& info) const
+	{
+	  switch (info.type())
+	  {
+	    case component::WhitespaceSeparator:
+	    {
+	      output << "    <whitespace_separator_region id=\"wss"
+		     << info.id()
+		     << "\">" << std::endl;
+
+	      internal::print_box_coords(output, info.bbox(), "      ");
+
+	      output << "    </whitespace_separator_region>" << std::endl;
+	      break;
+	    }
+
+	    case component::LineSeparator:
+	    {
+	      output << "    <separator_region id=\"sr" << info.id()
+		     << "\" sep_orientation=\"0.000000\" "
+		     << " sep_colour=\"Black\" "
+		     << " sep_bgcolour=\"White\">" << std::endl;
+
+	      internal::print_box_coords(output, info.bbox(), "      ");
+
+	      output << "    </separator_region>" << std::endl;
+	      break;
+	    }
+
+
+	    default:
+	    case component::Image:
+	    {
+	      output << "    <image_region id=\"ir" << info.id()
+		     << "\" img_colour_type=\"24_Bit_Colour\""
+		     << " img_orientation=\"0.000000\" "
+		     << " img_emb_text=\"No\" "
+		     << " img_bgcolour=\"White\">" << std::endl;
+
+	      internal::print_box_coords(output, info.bbox(), "      ");
+
+	      output << "    </image_region>" << std::endl;
+	      break;
+	    }
+	  }
+	}
+
+
+	/// Paragraph Set
+	//
+	template <typename L>
+	void
+	extended_page_xml_visitor::visit(const paragraph_set<L>& parset) const
+	{
+	  const line_set<L>& lines = parset.lines();
+
+	  for_all_paragraphs(p, parset)
+	  {
+	    const mln::util::array<line_id_t>& line_ids = parset(p).line_ids();
+
+	    // FIXME: compute that information on the whole paragraph
+	    // and use them here.
+	    line_id_t fid = line_ids(0);
+	    output << "    <text_region id=\"" << p
+		   << "\" txt_orientation=\"" << lines(fid).orientation()
+		   << "\" txt_reading_orientation=\"" << lines(fid).reading_orientation()
+		   << "\" txt_reading_direction=\"" << lines(fid).reading_direction()
+		   << "\" txt_text_type=\"" << lines(fid).type()
+		   << "\" txt_reverse_video=\"" << (lines(fid).reverse_video() ? "true" : "false")
+		   << "\" txt_indented=\"" << (lines(fid).indented() ? "true" : "false")
+		   << "\" kerning=\"" << lines(fid).char_space();
+
+	    // EXTENSIONS - Not officially supported
+	    output << "\" baseline=\"" << lines(fid).baseline()
+		   << "\" meanline=\"" << lines(fid).meanline()
+		   << "\" x_height=\"" << lines(fid).x_height()
+		   << "\" d_height=\"" << lines(fid).d_height()
+		   << "\" a_height=\"" << lines(fid).a_height()
+		   << "\" char_width=\"" << lines(fid).char_width();
+	    // End of EXTENSIONS
+	    output << "\">"
+		   << std::endl;
+
+	    internal::print_box_coords(output, parset(p).bbox(), "      ");
+
+	    // EXTENSIONS - Not officially supported
+	    for_all_paragraph_lines(lid, line_ids)
+	    {
+	      line_id_t l = line_ids(lid);
+	      lines(l).accept(*this);
+	    }
+	    // End of EXTENSIONS
+
+	    output << "    </text_region>" << std::endl;
+	  }
+	}
+
+
+	template <typename L>
+	void
+	extended_page_xml_visitor::visit(const line_info<L>& line) const
+	{
+	  if (line.has_text())
+	  {
+	    output << "        <line text=\"" << line.html_text() << "\" ";
+	  }
+	  else
+	    output << "        <line " << std::endl;
+
+	  output << "id=\"" << line.id()
+		 << "\" txt_orientation=\"" << line.orientation()
+		 << "\" txt_reading_orientation=\"" << line.reading_orientation()
+		 << "\" txt_reading_direction=\"" << line.reading_direction()
+		 << "\" txt_text_type=\"" << line.type()
+		 << "\" txt_reverse_video=\"" << (line.reverse_video() ? "true" : "false")
+		 << "\" txt_indented=\"" << (line.indented() ? "true" : "false")
+		 << "\" kerning=\"" << line.char_space()
+		 << "\" baseline=\"" << line.baseline()
+		 << "\" meanline=\"" << line.meanline()
+		 << "\" x_height=\"" << line.x_height()
+		 << "\" d_height=\"" << line.d_height()
+		 << "\" a_height=\"" << line.a_height()
+		 << "\" char_width=\"" << line.char_width()
+		 << "\">" << std::endl;
+
+	  internal::print_box_coords(output, line.bbox(), "          ");
+
+	  output << "        </line>" << std::endl;
+	}
+
+#endif // MLN_INCLUDE_ONLY
+
+      } // end of namespace scribo::io::xml::internal
+
+    } // end of namespace scribo::io::xml
+
+  } // end of namespace scribo::io
+
+} // end of namespace scribo
+
+#endif // SCRIBO_IO_XML_INTERNAL_EXTENDED_PAGE_XML_VISITOR_HH
diff --git a/scribo/scribo/io/xml/internal/full_xml_visitor.hh b/scribo/scribo/io/xml/internal/full_xml_visitor.hh
new file mode 100644
index 0000000..9c5bd1d
--- /dev/null
+++ b/scribo/scribo/io/xml/internal/full_xml_visitor.hh
@@ -0,0 +1,456 @@
+// Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena.  If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction.  Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License.  This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef SCRIBO_IO_XML_INTERNAL_FULL_XML_VISITOR_HH
+# define SCRIBO_IO_XML_INTERNAL_FULL_XML_VISITOR_HH
+
+/// \file
+///
+/// XML serializer Visitor.
+
+# include <fstream>
+# include <scribo/core/internal/doc_xml_serializer.hh>
+# include <scribo/core/document.hh>
+# include <scribo/core/component_set.hh>
+# include <scribo/core/paragraph_set.hh>
+# include <scribo/core/object_groups.hh>
+# include <scribo/core/object_links.hh>
+# include <scribo/core/line_links.hh>
+# include <scribo/core/line_info.hh>
+
+# include <scribo/convert/to_base64.hh>
+
+# include <scribo/io/xml/internal/print_box_coords.hh>
+# include <scribo/io/xml/internal/print_page_preambule.hh>
+
+
+namespace scribo
+{
+
+  namespace io
+  {
+
+    namespace xml
+    {
+
+      namespace internal
+      {
+
+
+	class full_xml_visitor : public doc_xml_serializer<full_xml_visitor>
+	{
+	public:
+	  // Constructor
+	  full_xml_visitor(std::ofstream& out);
+
+	  // Visit overloads
+	  template <typename L>
+	  void visit(const document<L>& doc) const;
+
+	  template <typename L>
+	  void visit(const line_links<L>& llinks) const;
+
+	  template <typename L>
+	  void visit(const object_groups<L>& groups) const;
+
+	  template <typename L>
+	  void visit(const object_links<L>& links) const;
+
+	  template <typename L>
+	  void visit(const component_set<L>& comp_set) const;
+
+	  void visit(const component_info& info) const;
+
+	  template <typename L>
+	  void visit(const paragraph_set<L>& parset) const;
+
+	  template <typename L>
+	  void visit(const line_info<L>& line) const;
+
+	private: // Attributes
+	  std::ofstream& output;
+	};
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+	inline
+	full_xml_visitor::full_xml_visitor(std::ofstream& out)
+	  : output(out)
+	{
+	}
+
+
+
+	/// Document
+	//
+	template <typename L>
+	void
+	full_xml_visitor::visit(const document<L>& doc) const
+	{
+	  print_PAGE_preambule(output, doc, false);
+
+	  // Text
+	  if (doc.has_text())
+	  {
+	    const line_set<L>& lines = doc.lines();
+
+	    // Save component/link/group information (Extension)
+	    {
+	      // Component set
+	      lines.components().accept(*this);
+
+	      // Object link
+	      lines.links().accept(*this);
+
+	      // Object group
+	      lines.groups().accept(*this);
+	    }
+	    // End of EXTENSIONS
+
+	    const paragraph_set<L>& parset = doc.paragraphs();
+
+	    // Save paragraphs related information (Extension)
+	    {
+	      // General text information
+	      output << "    <text_data nlines=\"" << lines.nelements() << "\" "
+		   << " nparagraphs=\"" << parset.nelements() << "\" />" << std::endl;
+
+	      // line_links
+	      parset.links().accept(*this);
+	    }
+
+	    // Paragraph and lines
+	    parset.accept(*this);
+	  }
+
+
+	  // Page elements (Pictures, ...)
+	  if (doc.has_elements())
+	  {
+	    const component_set<L>& elts = doc.elements();
+	    for_all_comps(e, elts)
+	      if (elts(e).is_valid())
+		elts(e).accept(*this);
+	  }
+
+
+	  // line seraparators
+	  if (doc.has_line_seps())
+	  {
+	    const component_set<L>&
+	      line_seps_comps = doc.line_seps_comps();
+
+	    for_all_comps(c, line_seps_comps)
+	      line_seps_comps(c).accept(*this);
+	  }
+
+
+	  // Whitespace seraparators
+	  if (doc.has_whitespace_seps())
+	  {
+	    const component_set<L>&
+	      whitespace_seps_comps = doc.whitespace_seps_comps();
+
+	    for_all_comps(c, whitespace_seps_comps)
+	      whitespace_seps_comps(c).accept(*this);
+	  }
+
+	  output << "  </page>" << std::endl;
+	  output << "</pcGts>" << std::endl;
+
+	}
+
+
+	/// Line Links
+	//
+	template <typename L>
+	void
+	full_xml_visitor::visit(const line_links<L>& llinks) const
+	{
+	  output << "      <line_links>" << std::endl;
+	  for_all_links(l, llinks)
+	  {
+	    output << "      <line_link"
+		   << " from=\"" << l
+		   << "\" to=\"" << llinks(l)
+		   << "\"/>" << std::endl;
+	  }
+	  output << "      </line_links>" << std::endl;
+	}
+
+
+	/// Object Groups
+        //
+	template <typename L>
+	void
+	full_xml_visitor::visit(const object_groups<L>& groups) const
+	{
+	  output << "      <object_groups>" << std::endl;
+	  for_all_groups(g, groups)
+	  {
+	    output << "      <group "
+		 << " object_id=\"" << g
+		 << "\" group_id=\"" << groups(g)
+		 << "\"/>" << std::endl;
+	  }
+	  output << "      </object_groups>" << std::endl;
+	}
+
+
+	/// Object Links
+	//
+	template <typename L>
+	void
+	full_xml_visitor::visit(const object_links<L>& links) const
+	{
+	  output << "      <object_links>" << std::endl;
+	  for_all_links(l, links)
+	  {
+	    output << "      <link"
+		   << " from=\"" << l
+		   << "\" to=\"" << links(l)
+		   << "\"/>" << std::endl;
+	  }
+	  output << "      </object_links>" << std::endl;
+	}
+
+
+	/// Component Set
+	//
+	template <typename L>
+	void
+	full_xml_visitor::visit(const component_set<L>& comp_set) const
+	{
+	  output << "    <component_set nelements=\"" << comp_set.nelements()
+		 << "\">" << std::endl;
+	  for_all_comps(c, comp_set)
+	  {
+	    output << "      <component_info"
+		   << " id=\"" << comp_set(c).id()
+		   << "\" mass_center_x=\"" << comp_set(c).mass_center().col()
+		   << "\" mass_center_y=\"" << comp_set(c).mass_center().row()
+		   << "\" card=\"" <<  comp_set(c).card()
+		   << "\" tag=\"" <<  comp_set(c).tag()
+		   << "\" type=\"" <<  comp_set(c).type()
+		   << "\" pmin_x=\"" << comp_set(c).bbox().pmin().col()
+		   << "\" pmin_y=\"" << comp_set(c).bbox().pmin().row()
+		   << "\" pmax_x=\"" << comp_set(c).bbox().pmax().col()
+		   << "\" pmax_y=\"" << comp_set(c).bbox().pmax().row()
+		   << "\"/>" << std::endl;
+	  }
+
+
+	  // Save labeled image
+	  {
+	    const L& lbl = comp_set.labeled_image();
+	    output << "<labeled_image "
+		   << " height=\"" << lbl.domain().height()
+		   << "\" width=\"" << lbl.domain().width() << "\">"
+		   << "<![CDATA[";
+
+	    util::array<unsigned char> lbl64;
+	    convert::to_base64(lbl, lbl64);
+	    output.write((const char *)lbl64.std_vector().data(),
+			 lbl64.nelements());
+
+	    output <<  "]]></labeled_image>" << std::endl;
+	  }
+
+	  // Save separators image
+	  {
+	    const mln_ch_value(L,bool)& seps = comp_set.separators();
+	    output << "<separators_image "
+		   << " height=\"" << seps.domain().height()
+		   << "\" width=\"" << seps.domain().width() << "\">"
+		   << "<![CDATA[";
+
+	    util::array<unsigned char> seps64;
+	    convert::to_base64(seps, seps64);
+	    output.write((const char *)seps64.std_vector().data(),
+			 seps64.nelements());
+
+	    output <<  "]]></separators_image>" << std::endl;
+	  }
+
+	  output << "</component_set>" << std::endl;
+	}
+
+
+	/// Component_info
+	//
+	inline
+	void
+	full_xml_visitor::visit(const component_info& info) const
+	{
+	  switch (info.type())
+	  {
+	    case component::WhitespaceSeparator:
+	    {
+	      output << "    <whitespace_separator_region id=\"wss"
+		     << info.id()
+		     << "\">" << std::endl;
+
+	      internal::print_box_coords(output, info.bbox(), "      ");
+
+	      output << "    </whitespace_separator_region>" << std::endl;
+	      break;
+	    }
+
+	    case component::LineSeparator:
+	    {
+	      output << "    <separator_region id=\"sr" << info.id()
+		     << "\" sep_orientation=\"0.000000\" "
+		     << " sep_colour=\"Black\" "
+		     << " sep_bgcolour=\"White\">" << std::endl;
+
+	      internal::print_box_coords(output, info.bbox(), "      ");
+
+	      output << "    </separator_region>" << std::endl;
+	      break;
+	    }
+
+
+	    default:
+	    case component::Image:
+	    {
+	      output << "    <image_region id=\"ir" << info.id()
+		     << "\" img_colour_type=\"24_Bit_Colour\""
+		     << " img_orientation=\"0.000000\" "
+		     << " img_emb_text=\"No\" "
+		     << " img_bgcolour=\"White\">" << std::endl;
+
+	      internal::print_box_coords(output, info.bbox(), "      ");
+
+	      output << "    </image_region>" << std::endl;
+	      break;
+	    }
+	  }
+	}
+
+	/// Paragraph Set
+	//
+	template <typename L>
+	void
+	full_xml_visitor::visit(const paragraph_set<L>& parset) const
+	{
+	  const line_set<L>& lines = parset.lines();
+
+	  for_all_paragraphs(p, parset)
+	  {
+	    const mln::util::array<line_id_t>& line_ids = parset(p).line_ids();
+
+	    // FIXME: compute that information on the whole paragraph
+	    // and use them here.
+	    line_id_t fid = line_ids(0);
+	    output << "    <text_region id=\"" << p
+		   << "\" txt_orientation=\"" << lines(fid).orientation()
+		   << "\" txt_reading_orientation=\"" << lines(fid).reading_orientation()
+		   << "\" txt_reading_direction=\"" << lines(fid).reading_direction()
+		   << "\" txt_text_type=\"" << lines(fid).type()
+		   << "\" txt_reverse_video=\"" << (lines(fid).reverse_video() ? "true" : "false")
+		   << "\" txt_indented=\"" << (lines(fid).indented() ? "true" : "false")
+		   << "\" kerning=\"" << lines(fid).char_space();
+
+	    // EXTENSIONS - Not officially supported
+	    output << "\" baseline=\"" << lines(fid).baseline()
+		   << "\" meanline=\"" << lines(fid).meanline()
+		   << "\" x_height=\"" << lines(fid).x_height()
+		   << "\" d_height=\"" << lines(fid).d_height()
+		   << "\" a_height=\"" << lines(fid).a_height()
+		   << "\" char_width=\"" << lines(fid).char_width();
+	    // End of EXTENSIONS
+	    output << "\">"
+		   << std::endl;
+
+	    internal::print_box_coords(output, parset(p).bbox(), "      ");
+
+
+	    // EXTENSIONS - Not officially supported
+	    for_all_paragraph_lines(lid, line_ids)
+	    {
+	      line_id_t l = line_ids(lid);
+
+	      lines(l).accept(*this);
+	    }
+
+	    output << "    </text_region>" << std::endl;
+	  }
+	}
+
+
+	template <typename L>
+	void
+	full_xml_visitor::visit(const line_info<L>& line) const
+	{
+	  if (line.has_text())
+	  {
+	    output << "        <line text=\"" << line.html_text() << "\" ";
+	  }
+	  else
+	    output << "        <line " << std::endl;
+
+	  output << "id=\"" << line.id()
+		 << "\" txt_orientation=\"" << line.orientation()
+		 << "\" txt_reading_orientation=\"" << line.reading_orientation()
+		 << "\" txt_reading_direction=\"" << line.reading_direction()
+		 << "\" txt_text_type=\"" << line.type()
+		 << "\" txt_reverse_video=\"" << (line.reverse_video() ? "true" : "false")
+		 << "\" txt_indented=\"" << (line.indented() ? "true" : "false")
+		 << "\" kerning=\"" << line.char_space()
+		 << "\" baseline=\"" << line.baseline()
+		 << "\" meanline=\"" << line.meanline()
+		 << "\" x_height=\"" << line.x_height()
+		 << "\" d_height=\"" << line.d_height()
+		 << "\" a_height=\"" << line.a_height()
+		 << "\" char_width=\"" << line.char_width()
+		 << "\">" << std::endl;
+
+	  internal::print_box_coords(output, line.bbox(), "          ");
+
+	  output << "          <compid_list>" << std::endl;
+
+	  for_all_line_comps(c, line.components())
+	    output << "            <compid value=\""
+		   << line.components()(c) << "\" />" << std::endl;
+
+	  output << "          </compid_list>" << std::endl;
+
+	  output << "        </line>" << std::endl;
+	}
+
+#endif // MLN_INCLUDE_ONLY
+
+      } // end of namespace scribo::io::xml::internal
+
+    } // end of namespace scribo::io::xml
+
+  } // end of namespace scribo::io
+
+} // end of namespace scribo
+
+#endif // SCRIBO_IO_XML_INTERNAL_FULL_XML_VISITOR_HH
diff --git a/scribo/scribo/io/xml/internal/html_markups_replace.hh b/scribo/scribo/io/xml/internal/html_markups_replace.hh
new file mode 100644
index 0000000..76f8107
--- /dev/null
+++ b/scribo/scribo/io/xml/internal/html_markups_replace.hh
@@ -0,0 +1,97 @@
+// Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena.  If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction.  Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License.  This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef SCRIBO_IO_XML_INTERNAL_HTML_MARKUPS_REPLACE_HH
+# define SCRIBO_IO_XML_INTERNAL_HTML_MARKUPS_REPLACE_HH
+
+/// \file
+///
+/// \brief Replace HTML markups characters by their corresponding
+/// markups.
+
+
+namespace scribo
+{
+
+  namespace io
+  {
+
+    namespace xml
+    {
+
+      namespace internal
+      {
+
+        /*! \brief Replace HTML markups characters by their corresponding
+	  markups.
+	*/
+	inline
+	std::string
+	html_markups_replace(std::string& input);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+	static inline std::map<char, std::string> init_map()
+	{
+	  std::map<char, std::string> html_map;
+	  html_map['\"'] = """;
+	  html_map['<'] = "<";
+	  html_map['>'] = ">";
+	  html_map['&'] = "&";
+	  return html_map;
+	}
+
+
+	inline
+	std::string
+	html_markups_replace(const std::string& input)
+	{
+	  static std::map<char, std::string> map = init_map();
+
+	  std::string output = input;
+	  for (unsigned i = 0; i < input.size(); ++i)
+	  {
+	    std::map<char, std::string>::iterator it = map.find(output.at(i));
+	    if (it != map.end())
+	    {
+	      output.replace(i, 1, it->second);
+	      i += it->second.size() - 1;
+	    }
+	  }
+	  return output;
+	}
+
+# endif // ! MLN_INCLUDE_ONLY
+
+      } // end of namespace scribo::io::xml::internal
+
+    } // end of namespace scribo::io::xml
+
+  } // end of namespace scribo::io
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_IO_XML_INTERNAL_HTML_MARKUPS_REPLACE_HH
diff --git a/scribo/scribo/io/xml/internal/page_xml_visitor.hh b/scribo/scribo/io/xml/internal/page_xml_visitor.hh
new file mode 100644
index 0000000..52d8f12
--- /dev/null
+++ b/scribo/scribo/io/xml/internal/page_xml_visitor.hh
@@ -0,0 +1,222 @@
+// Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena.  If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction.  Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License.  This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef SCRIBO_IO_XML_INTERNAL_PAGE_XML_VISITOR_HH
+# define SCRIBO_IO_XML_INTERNAL_PAGE_XML_VISITOR_HH
+
+/// \file
+///
+/// PAGE format XML serializer Visitor.
+
+# include <fstream>
+
+# include <scribo/core/internal/doc_xml_serializer.hh>
+# include <scribo/convert/to_base64.hh>
+
+# include <scribo/io/xml/internal/print_box_coords.hh>
+# include <scribo/io/xml/internal/print_page_preambule.hh>
+
+
+namespace scribo
+{
+
+  namespace io
+  {
+
+    namespace xml
+    {
+
+      namespace internal
+      {
+
+	/*! \brief Save document information as XML.
+
+	  We use a XML Schema part of the PAGE (Page Analysis and Ground
+	  truth Elements) image representation framework.
+
+	  This schema was used in the Page Segmentation COMPetition
+	  (PSCOMP) for ICDAR 2009.
+
+	  Its XSD file is located here:
+	  http://schema.primaresearch.org/PAGE/gts/pagecontent/2009-03-16/pagecontent…
+
+	*/
+	class page_xml_visitor : public doc_xml_serializer<page_xml_visitor>
+	{
+	public:
+	  // Constructor
+	  page_xml_visitor(std::ofstream& out);
+
+	  // Visit overloads
+	  template <typename L>
+	  void visit(const document<L>& doc) const;
+
+	  template <typename L>
+	  void visit(const component_set<L>& comp_set) const;
+
+	  void visit(const component_info& info) const;
+
+	  template <typename L>
+	  void visit(const paragraph_set<L>& parset) const;
+
+	private: // Attributes
+	  std::ofstream& output;
+	};
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+	inline
+	page_xml_visitor::page_xml_visitor(std::ofstream& out)
+	  : output(out)
+	{
+	}
+
+
+
+	/// Document
+	//
+	template <typename L>
+	void
+	page_xml_visitor::visit(const document<L>& doc) const
+	{
+	  // Preambule
+	  print_PAGE_preambule(output, doc, true);
+
+	  // Text
+	  if (doc.has_text())
+	    doc.paragraphs().accept(*this);
+
+	  // Page elements (Pictures, ...)
+	  if (doc.has_elements())
+	    doc.elements().accept(*this);
+
+	  // line seraparators
+	  if (doc.has_line_seps())
+	    doc.line_seps_comps().accept(*this);
+
+	  output << "  </page>" << std::endl;
+	  output << "</pcGts>" << std::endl;
+	}
+
+
+	/// Component Set
+	//
+	template <typename L>
+	void
+	page_xml_visitor::visit(const component_set<L>& comp_set) const
+	{
+	  for_all_comps(c, comp_set)
+	    if (comp_set(c).is_valid())
+	      comp_set(c).accept(*this);
+	}
+
+
+	/// Component_info
+	//
+	inline
+	void
+	page_xml_visitor::visit(const component_info& info) const
+	{
+	  switch (info.type())
+	  {
+	    case component::LineSeparator:
+	    {
+	      output << "    <separator_region id=\"sr" << info.id()
+		     << "\" sep_orientation=\"0.000000\" "
+		     << " sep_colour=\"Black\" "
+		     << " sep_bgcolour=\"White\">" << std::endl;
+
+	      internal::print_box_coords(output, info.bbox(), "      ");
+
+	      output << "    </separator_region>" << std::endl;
+	      break;
+	    }
+
+
+	    default:
+	    case component::Image:
+	    {
+	      output << "    <image_region id=\"ir" << info.id()
+		     << "\" img_colour_type=\"24_Bit_Colour\""
+		     << " img_orientation=\"0.000000\" "
+		     << " img_emb_text=\"No\" "
+		     << " img_bgcolour=\"White\">" << std::endl;
+
+	      internal::print_box_coords(output, info.bbox(), "      ");
+
+	      output << "    </image_region>" << std::endl;
+	      break;
+	    }
+	  }
+	}
+
+
+	/// Paragraph Set
+	//
+	template <typename L>
+	void
+	page_xml_visitor::visit(const paragraph_set<L>& parset) const
+	{
+	  const line_set<L>& lines = parset.lines();
+
+	  for_all_paragraphs(p, parset)
+	  {
+	    const mln::util::array<line_id_t>& line_ids = parset(p).line_ids();
+
+	    // FIXME: compute that information on the whole paragraph
+	    // and use them here.
+	    line_id_t fid = line_ids(0);
+	    output << "    <text_region id=\"" << p
+		   << "\" txt_orientation=\"" << lines(fid).orientation()
+		   << "\" txt_reading_orientation=\"" << lines(fid).reading_orientation()
+		   << "\" txt_reading_direction=\"" << lines(fid).reading_direction()
+		   << "\" txt_text_type=\"" << lines(fid).type()
+		   << "\" txt_reverse_video=\"" << (lines(fid).reverse_video() ? "true" : "false")
+		   << "\" txt_indented=\"" << (lines(fid).indented() ? "true" : "false")
+		   << "\" kerning=\"" << lines(fid).char_space()
+		   << "\">"
+		   << std::endl;
+
+	    internal::print_box_coords(output, parset(p).bbox(), "      ");
+
+	    output << "    </text_region>" << std::endl;
+	  }
+	}
+
+
+#endif // MLN_INCLUDE_ONLY
+
+      } // end of namespace scribo::io::xml::internal
+
+    } // end of namespace scribo::io::xml
+
+  } // end of namespace scribo::io
+
+} // end of namespace scribo
+
+#endif // SCRIBO_IO_XML_INTERNAL_PAGE_XML_VISITOR_HH
diff --git a/scribo/scribo/io/xml/internal/print_box_coords.hh b/scribo/scribo/io/xml/internal/print_box_coords.hh
new file mode 100644
index 0000000..d3aeedf
--- /dev/null
+++ b/scribo/scribo/io/xml/internal/print_box_coords.hh
@@ -0,0 +1,92 @@
+// Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena.  If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction.  Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License.  This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef SCRIBO_IO_XML_INTERNAL_PRINT_BOX_COORDS_HH
+# define SCRIBO_IO_XML_INTERNAL_PRINT_BOX_COORDS_HH
+
+/// \file
+///
+/// \brief Prints box2d coordinates to XML data.
+
+# include <mln/core/alias/box2d.hh>
+
+namespace scribo
+{
+
+  namespace io
+  {
+
+    namespace xml
+    {
+
+      namespace internal
+      {
+
+        /*! \brief Prints box2d coordinates to XML data.
+	 */
+	void
+	print_box_coords(std::ofstream& ostr, const box2d& b,
+			 const char *space);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+	inline
+	void
+	print_box_coords(std::ofstream& ostr, const box2d& b,
+			 const char *space)
+	{
+	  std::string sc = space;
+	  std::string sp = sc + "  ";
+	  ostr << sc << "<coords>" << std::endl
+	       << sp << "<point x=\"" << b.pmin().col()
+	       << "\" y=\"" << b.pmin().row() << "\"/>"
+	       << std::endl
+	       << sp << "<point x=\"" << b.pmax().col()
+	       << "\" y=\"" << b.pmin().row() << "\"/>"
+	       << std::endl
+	       << sp << "<point x=\"" << b.pmax().col()
+	       << "\" y=\"" << b.pmax().row() << "\"/>"
+	       << std::endl
+	       << sp << "<point x=\"" << b.pmin().col()
+	       << "\" y=\"" << b.pmax().row() << "\"/>"
+	       << std::endl
+	       << sc << "</coords>" << std::endl;
+
+	}
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+      } // end of namespace scribo::io::xml::internal
+
+    } // end of namespace scribo::io::xml
+
+  } // end of namespace scribo::io
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_IO_XML_INTERNAL_PRINT_BOX_COORDS_HH
diff --git a/scribo/scribo/io/xml/internal/print_page_preambule.hh b/scribo/scribo/io/xml/internal/print_page_preambule.hh
new file mode 100644
index 0000000..b5ae891
--- /dev/null
+++ b/scribo/scribo/io/xml/internal/print_page_preambule.hh
@@ -0,0 +1,95 @@
+// Copyright (C) 2011 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena.  If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction.  Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License.  This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef SCRIBO_IO_XML_INTERNAL_PRINT_PAGE_PREAMBULE_HH
+# define SCRIBO_IO_XML_INTERNAL_PRINT_PAGE_PREAMBULE_HH
+
+/// \file
+///
+/// \brief Print PAGE XML format preambule.
+
+# include <mln/core/alias/box2d.hh>
+
+namespace scribo
+{
+
+  namespace io
+  {
+
+    namespace xml
+    {
+
+      namespace internal
+      {
+
+        /// \brief Print PAGE XML format preambule.
+	template <typename L>
+	void print_PAGE_preambule(std::ofstream& output,
+				  const document<L>& doc,
+				  bool with_validation);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+	template <typename L>
+	void print_PAGE_preambule(std::ofstream& output,
+				  const document<L>& doc,
+				  bool with_validation)
+	{
+	  output << "<?xml version=\"1.0\"?>" << std::endl;
+
+	  if (with_validation)
+	    output << "<pcGts xmlns=\"http://schema.primaresearch.org/PAGE/gts/pagecontent/2009-03-16\" "
+		   << "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
+		   << "xsi:schemaLocation=\"http://schema.primaresearch.org/PAGE/gts/pagecontent/2009-03-16 "
+		   << "http://schema.primaresearch.org/PAGE/gts/pagecontent/2009-03-16/pagecontent…" "
+		   << "pcGtsId=\"" << doc.filename() << "\">" << std::endl;
+	  else
+	    output << "<pcGts>" << std::endl;
+
+	  output << "  <pcMetadata>" << std::endl;
+	  output << "    <pcCreator>LRDE</pcCreator>" << std::endl;
+	  output << "    <pcCreated/>" << std::endl;
+	  output << "    <pcLastChange/>" << std::endl;
+	  output << "    <pcComments>Generated by Scribo from Olena.</pcComments>" << std::endl;
+	  output << "  </pcMetadata>" << std::endl;
+
+	  output << "  <page image_filename=\"" << doc.filename()
+		 << "\" image_width=\"" << doc.width()
+		 << "\" image_height=\"" << doc.height()
+		 << "\">" << std::endl;
+	}
+
+# endif // ! MLN_INCLUDE_ONLY
+
+      } // end of namespace scribo::io::xml::internal
+
+    } // end of namespace scribo::io::xml
+
+  } // end of namespace scribo::io
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_IO_XML_INTERNAL_PRINT_PAGE_PREAMBULE_HH
diff --git a/scribo/scribo/io/xml/save.hh b/scribo/scribo/io/xml/save.hh
index 7011e87..30579d0 100644
--- a/scribo/scribo/io/xml/save.hh
+++ b/scribo/scribo/io/xml/save.hh
@@ -38,7 +38,11 @@
 # include <map>
 
 # include <scribo/core/document.hh>
-# include <scribo/core/line_set.hh>
+
+# include <scribo/io/xml/internal/full_xml_visitor.hh>
+# include <scribo/io/xml/internal/extended_page_xml_visitor.hh>
+# include <scribo/io/xml/internal/page_xml_visitor.hh>
+
 
 namespace scribo
 {
@@ -49,360 +53,104 @@ namespace scribo
     namespace xml
     {
 
-      /*! \brief Save document information as XML.
+      /*! \brief Supported XML formats
+
+	Page : PRima PAGE format. Used in ICDAR 2009.
 
-	We use a XML Schema part of the PAGE (Page Analysis and Ground
-	truth Elements) image representation framework.
+	PageExtended : Enriched PRima PAGE format with scribo data.
+
+	Full : Enriched PRima PAGE format with scribo data. This
+	       format can be reloaded in Scribo.
+       */
+      enum Format
+      {
+	Page,
+	PageExtended,
+	Full
+	//Hocr
+      };
 
-	This schema was used in the Page Segmentation COMPetition
-	(PSCOMP) for ICDAR 2009.
 
-	Its XSD file is located here:
-	http://schema.primaresearch.org/PAGE/gts/pagecontent/2009-03-16/pagecontent…
+      /*! \brief Save document information as XML.
 
       */
       template <typename L>
       void
-      save(const document<L>& doc,
-	   const std::string& output_name,
-	   bool allow_extensions);
+      save(const document<L>& doc, const std::string& output_name,
+	   Format format);
 
 
 # ifndef MLN_INCLUDE_ONLY
 
+
       namespace internal
       {
 
-	inline
-	std::string&
-	html_markups_replace(std::string& input,
-			     std::map<char, std::string>& map)
-	{
-	  for (unsigned i = 0; i < input.size(); ++i)
-	  {
-	    std::map<char, std::string>::iterator it = map.find(input.at(i));
-	    if (it != map.end())
-	    {
-	      input.replace(i, 1, it->second);
-	      i += it->second.size() - 1;
-	    }
-	  }
-	  return input;
-	}
-
-
-	inline
-	void print_box_coords(std::ofstream& ostr, const box2d& b,
-			      const char *space)
+	template <typename L>
+	void save_page(const document<L>& doc, std::ofstream& output)
 	{
-	  std::string sc = space;
-	  std::string sp = sc + "  ";
-	  ostr << sc << "<coords>" << std::endl
-	       << sp << "<point x=\"" << b.pmin().col()
-	       << "\" y=\"" << b.pmin().row() << "\"/>"
-	       << std::endl
-	       << sp << "<point x=\"" << b.pmax().col()
-	       << "\" y=\"" << b.pmin().row() << "\"/>"
-	       << std::endl
-	       << sp << "<point x=\"" << b.pmax().col()
-	       << "\" y=\"" << b.pmax().row() << "\"/>"
-	       << std::endl
-	       << sp << "<point x=\"" << b.pmin().col()
-	       << "\" y=\"" << b.pmax().row() << "\"/>"
-	       << std::endl
-	       << sc << "</coords>" << std::endl;
-
+	  scribo::io::xml::internal::page_xml_visitor f(output);
+	  doc.accept(f);
 	}
 
-
-
 	template <typename L>
-	void
-	save(const document<L>& doc,
-	     const std::string& output_name)
+	void save_page_extended(const document<L>& doc, std::ofstream& output)
 	{
-	  trace::entering("scribo::io::xml:save_text_lines");
-
-	  std::ofstream file(output_name.c_str());
-	  if (! file)
-	  {
-	    std::cerr << "error: cannot open file '" << doc.filename() << "'!";
-	    abort();
-	  }
-
-	  std::map<char, std::string> html_map;
-	  html_map['\"'] = """;
-	  html_map['<'] = "<";
-	  html_map['>'] = ">";
-	  html_map['&'] = "&";
-
-	  file << "<?xml version=\"1.0\"?>" << std::endl;
-	  file << "<pcGts xmlns=\"http://schema.primaresearch.org/PAGE/gts/pagecontent/2009-03-16\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://schema.primaresearch.org/PAGE/gts/pagecontent/2009-03-16 http://schema.primaresearch.org/PAGE/gts/pagecontent/2009-03-16/pagecontent…" pcGtsId=\"" << doc.filename() << "\">" << std::endl;
-
-	  file << "  <pcMetadata>" << std::endl;
-	  file << "    <pcCreator>LRDE</pcCreator>" << std::endl;
-	  file << "    <pcCreated/>" << std::endl;
-	  file << "    <pcLastChange/>" << std::endl;
-	  file << "    <pcComments>Generated by Scribo from Olena.</pcComments>" << std::endl;
-	  file << "  </pcMetadata>" << std::endl;
-
-	  file << "  <page image_filename=\"" << doc.filename()
-	       << "\" image_width=\"" << doc.width()
-	       << "\" image_height=\"" << doc.height()
-	       << "\">" << std::endl;
-
-	  // Text
-	  if (doc.has_text())
-	  {
-	    const line_set<L>& lines = doc.lines();
-	    const paragraph_set<L>& parset = doc.paragraphs();
-
-	    for_all_paragraphs(p, parset)
-	    {
-	      const mln::util::array<line_id_t>& line_ids = parset(p).line_ids();
-
-	      // FIXME: compute that information on the whole paragraph
-	      // and use them here.
-	      line_id_t fid = line_ids(0);
-	      file << "    <text_region id=\"" << p
-		   << "\" txt_orientation=\"" << lines(fid).orientation()
-		   << "\" txt_reading_orientation=\"" << lines(fid).reading_orientation()
-		   << "\" txt_reading_direction=\"" << lines(fid).reading_direction()
-		   << "\" txt_text_type=\"" << lines(fid).type()
-		   << "\" txt_reverse_video=\"" << (lines(fid).reverse_video() ? "true" : "false")
-		   << "\" txt_indented=\"" << (lines(fid).indented() ? "true" : "false")
-		   << "\" kerning=\"" << lines(fid).char_space()
-		   << "\">"
-		   << std::endl;
-
-	      internal::print_box_coords(file, parset(p).bbox(), "      ");
-
-	      file << "    </text_region>" << std::endl;
-	    }
-	  }
-
-	  // Page elements (Pictures, ...)
-	  if (doc.has_elements())
-	  {
-	    const component_set<L>& elts = doc.elements();
-	    for_all_comps(e, elts)
-	      if (elts(e).is_valid())
-	      {
-		file << "    <image_region id=\"ir" << elts(e).id()
-		     << "\" img_colour_type=\"24_Bit_Colour\""
-		     << " img_orientation=\"0.000000\" "
-		     << " img_emb_text=\"No\" "
-		     << " img_bgcolour=\"White\">" << std::endl;
-
-		internal::print_box_coords(file, elts(e).bbox(), "      ");
-
-		file << "    </image_region>" << std::endl;
-	      }
-	  }
-
-
-	  file << "  </page>" << std::endl;
-	  file << "</pcGts>" << std::endl;
-
-	  trace::exiting("scribo::io::xml::save_text_lines");
+	  scribo::io::xml::internal::extended_page_xml_visitor f(output);
+	  doc.accept(f);
 	}
 
-
-
-
 	template <typename L>
-	void
-	save_extended(const document<L>& doc,
-		      const std::string& output_name)
+	void save_full(const document<L>& doc, std::ofstream& output)
 	{
-	  trace::entering("scribo::io::xml:save_text_lines");
-
-	  std::ofstream file(output_name.c_str());
-	  if (! file)
-	  {
-	    std::cerr << "error: cannot open file '" << doc.filename() << "'!";
-	    abort();
-	  }
-
-	  std::map<char, std::string> html_map;
-	  html_map['\"'] = """;
-	  html_map['<'] = "<";
-	  html_map['>'] = ">";
-	  html_map['&'] = "&";
-
-	  file << "<?xml version=\"1.0\"?>" << std::endl;
-	  file << "<pcGts>" << std::endl;
-
-	  file << "  <pcMetadata>" << std::endl;
-	  file << "    <pcCreator>LRDE</pcCreator>" << std::endl;
-	  file << "    <pcCreated/>" << std::endl;
-	  file << "    <pcLastChange/>" << std::endl;
-	  file << "    <pcComments>Generated by Scribo from Olena.</pcComments>" << std::endl;
-	  file << "  </pcMetadata>" << std::endl;
-
-	  file << "  <page image_filename=\"" << doc.filename()
-	       << "\" image_width=\"" << doc.width()
-	       << "\" image_height=\"" << doc.height()
-	       << "\">" << std::endl;
-
-	  // Text
-	  if (doc.has_text())
-	  {
-	    const line_set<L>& lines = doc.lines();
-	    const paragraph_set<L>& parset = doc.paragraphs();
-
-	    for_all_paragraphs(p, parset)
-	    {
-	      const mln::util::array<line_id_t>& line_ids = parset(p).line_ids();
-
-	      // FIXME: compute that information on the whole paragraph
-	      // and use them here.
-	      line_id_t fid = line_ids(0);
-	      file << "    <text_region id=\"" << p
-		   << "\" txt_orientation=\"" << lines(fid).orientation()
-		   << "\" txt_reading_orientation=\"" << lines(fid).reading_orientation()
-		   << "\" txt_reading_direction=\"" << lines(fid).reading_direction()
-		   << "\" txt_text_type=\"" << lines(fid).type()
-		   << "\" txt_reverse_video=\"" << (lines(fid).reverse_video() ? "true" : "false")
-		   << "\" txt_indented=\"" << (lines(fid).indented() ? "true" : "false")
-		   << "\" kerning=\"" << lines(fid).char_space();
-
-	      // EXTENSIONS - Not officially supported
-	      file << "\" baseline=\"" << lines(fid).baseline()
-		   << "\" meanline=\"" << lines(fid).meanline()
-		   << "\" x_height=\"" << lines(fid).x_height()
-		   << "\" d_height=\"" << lines(fid).d_height()
-		   << "\" a_height=\"" << lines(fid).a_height()
-		   << "\" char_width=\"" << lines(fid).char_width();
-	      // End of EXTENSIONS
-	      file << "\">"
-		   << std::endl;
-
-	      internal::print_box_coords(file, parset(p).bbox(), "      ");
-
-
-	      // EXTENSIONS - Not officially supported
-	      for_all_paragraph_lines(lid, line_ids)
-	      {
-		line_id_t l = line_ids(lid);
-
-		if (lines(l).has_text())
-		{
-		  std::string tmp = lines(l).text();
-		  tmp = internal::html_markups_replace(tmp, html_map);
-
-		  file << "        <line text=\"" << tmp << "\" ";
-		}
-		else
-		  file << "        <line " << std::endl;
-
-		file << "id=\"" << lines(l).id()
-		     << "\" txt_orientation=\"" << lines(l).orientation()
-		     << "\" txt_reading_orientation=\"" << lines(l).reading_orientation()
-		     << "\" txt_reading_direction=\"" << lines(l).reading_direction()
-		     << "\" txt_text_type=\"" << lines(l).type()
-		     << "\" txt_reverse_video=\"" << (lines(l).reverse_video() ? "true" : "false")
-		     << "\" txt_indented=\"" << (lines(l).indented() ? "true" : "false")
-		     << "\" kerning=\"" << lines(l).char_space()
-		     << "\" baseline=\"" << lines(l).baseline()
-		     << "\" meanline=\"" << lines(l).meanline()
-		     << "\" x_height=\"" << lines(l).x_height()
-		     << "\" d_height=\"" << lines(l).d_height()
-		     << "\" a_height=\"" << lines(l).a_height()
-		     << "\" char_width=\"" << lines(l).char_width()
-		     << "\">" << std::endl;
-
-		internal::print_box_coords(file, lines(l).bbox(), "          ");
-
-		file << "        </line>" << std::endl;
-	      }
-
-	      file << "    </text_region>" << std::endl;
-	    }
-	  }
-	  // End of EXTENSIONS
-
-	  // Page elements (Pictures, ...)
-	  if (doc.has_elements())
-	  {
-	    const component_set<L>& elts = doc.elements();
-	    for_all_comps(e, elts)
-	      if (elts(e).is_valid())
-	      {
-		switch (elts(e).type())
-		{
-		  case component::Separator:
-		  {
-		    file << "    <separator_region id=\"sr" << elts(e).id()
-			 << "\" sep_orientation=\"0.000000\" "
-			 << " sep_colour=\"Black\" "
-			 << " sep_bgcolour=\"White\">" << std::endl;
-
-		    internal::print_box_coords(file, elts(e).bbox(), "      ");
-
-		    file << "    </separator_region>" << std::endl;
-		    break;
-		    break;
-		  }
-
-		  default:
-		  case component::Image:
-		  {
-		    file << "    <image_region id=\"ir" << elts(e).id()
-			 << "\" img_colour_type=\"24_Bit_Colour\""
-			 << " img_orientation=\"0.000000\" "
-			 << " img_emb_text=\"No\" "
-			 << " img_bgcolour=\"White\">" << std::endl;
-
-		    internal::print_box_coords(file, elts(e).bbox(), "      ");
-
-		    file << "    </image_region>" << std::endl;
-		    break;
-		  }
-		}
-	      }
-	  }
-
-
-	  // Whitespace seraparators
-	  if (doc.has_whitespace_seps())
-	  {
-	    const component_set<L>&
-	      whitespace_seps_comps = doc.whitespace_seps_comps();
-
-	    for_all_comps(c, whitespace_seps_comps)
-	    {
-	      file << "    <whitespace_separator_region id=\"wss"
-		   << whitespace_seps_comps(c).id()
-		   << "\">" << std::endl;
-
-	      internal::print_box_coords(file, whitespace_seps_comps(c).bbox(), "      ");
-
-	      file << "    </whitespace_separator_region>" << std::endl;
-	    }
-	  }
-
-	  file << "  </page>" << std::endl;
-	  file << "</pcGts>" << std::endl;
-
-	  trace::exiting("scribo::io::xml::save_text_lines");
+	  scribo::io::xml::internal::full_xml_visitor f(output);
+	  doc.accept(f);
 	}
 
       } // end of namespace scribo::io::xml::internal
 
 
+
       // FACADE
 
       template <typename L>
       void
       save(const document<L>& doc,
 	   const std::string& output_name,
-	   bool allow_extensions)
+	   Format format)
       {
-	if (allow_extensions)
-	  internal::save_extended(doc, output_name);
-	else
-	  internal::save(doc, output_name);
+	trace::entering("scribo::io::xml::save");
+
+	// Open file
+	std::ofstream output(output_name.c_str());
+	if (! output)
+	{
+	  std::cerr << "scribo::io::xml::save - ERROR: cannot open file '"
+		    << doc.filename() << "'!";
+	  return;
+	}
+
+	// Choose saving method.
+	switch (format)
+	{
+	  case Page:
+	    internal::save_page(doc, output);
+	    break;
+
+	  case PageExtended:
+	    internal::save_page_extended(doc, output);
+	    break;
+
+	  case Full:
+	    internal::save_full(doc, output);
+	    break;
+
+	  default:
+	    trace::warning("scribo::io::xml::save - Invalid XML format! Skip saving...");
+	}
+
+	output.close();
+	trace::exiting("scribo::io::xml::save");
       }
 
 
diff --git a/scribo/scribo/toolchain/internal/content_in_doc_functor.hh b/scribo/scribo/toolchain/internal/content_in_doc_functor.hh
index 48098ba..dcbb4f7 100644
--- a/scribo/scribo/toolchain/internal/content_in_doc_functor.hh
+++ b/scribo/scribo/toolchain/internal/content_in_doc_functor.hh
@@ -36,7 +36,6 @@
 
 # include <scribo/primitive/extract/non_text.hh>
 # include <scribo/primitive/extract/components.hh>
-//# include <scribo/primitive/extract/vertical_separators.hh>
 # include <scribo/primitive/extract/separators.hh>
 # include <scribo/primitive/extract/separators_nonvisible.hh>
 
@@ -114,7 +113,7 @@ namespace scribo
 	bool enable_whitespace_seps;
 	bool enable_debug;
 	bool save_doc_as_xml;
-	bool allow_xml_extensions;
+	scribo::io::xml::Format xml_format;
 
 	//============
 	// Parameters
@@ -139,7 +138,7 @@ namespace scribo
 	  enable_whitespace_seps(true),
 	  enable_debug(false),
 	  save_doc_as_xml(false),
-	  allow_xml_extensions(true),
+	  xml_format(scribo::io::xml::PageExtended),
 	  ocr_language("eng"),
 	  output_file("/tmp/foo.xml"),
 	  doc(doc_filename)
@@ -189,7 +188,7 @@ namespace scribo
 	  // Whitespace separators
 	  on_new_progress_label("Find whitespace separators...");
 
-	  whitespaces = primitive::extract::separators_nonvisible(processed_image);
+	  whitespaces = primitive::extract::separators_nonvisible(input_cleaned);
 
 	  on_progress();
 	}
@@ -483,7 +482,7 @@ namespace scribo
 	{
 	  on_new_progress_label("Saving results");
 
-	  scribo::io::xml::save(doc, output_file, allow_xml_extensions);
+	  scribo::io::xml::save(doc, output_file, xml_format);
 	  on_xml_saved();
 
 	  on_progress();
diff --git a/scribo/src/content_in_doc.cc b/scribo/src/content_in_doc.cc
index 9748b28..d8d4e52 100644
--- a/scribo/src/content_in_doc.cc
+++ b/scribo/src/content_in_doc.cc
@@ -172,7 +172,9 @@ int main(int argc, char* argv[])
 					    debug);
 
   // Saving results
-  scribo::io::xml::save(doc, argv[2], true);
+  scribo::io::xml::save(doc, argv[2], scribo::io::xml::PageExtended);
+  scribo::io::xml::save(doc, "page.xml", scribo::io::xml::Page);
+  scribo::io::xml::save(doc, "full.xml", scribo::io::xml::Full);
 
   trace::exiting("main");
 }
-- 
1.5.6.5
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0