$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r59296 - in branches/quickbook-1.5-spirit2: . detail
From: daniel_james_at_[hidden]
Date: 2010-01-27 17:01:10
Author: danieljames
Date: 2010-01-27 17:01:09 EST (Wed, 27 Jan 2010)
New Revision: 59296
URL: http://svn.boost.org/trac/boost/changeset/59296
Log:
Images.
Added:
   branches/quickbook-1.5-spirit2/phrase_image.cpp   (contents, props changed)
Text files modified: 
   branches/quickbook-1.5-spirit2/Jamfile.v2               |     1                                         
   branches/quickbook-1.5-spirit2/detail/actions.cpp       |   131 ----------------------------------------
   branches/quickbook-1.5-spirit2/detail/actions.hpp       |    19 -----                                   
   branches/quickbook-1.5-spirit2/detail/actions_class.cpp |     1                                         
   branches/quickbook-1.5-spirit2/detail/actions_class.hpp |     1                                         
   branches/quickbook-1.5-spirit2/phrase.cpp               |    37 ++++++++--                              
   branches/quickbook-1.5-spirit2/phrase.hpp               |    12 +++                                     
   7 files changed, 41 insertions(+), 161 deletions(-)
Modified: branches/quickbook-1.5-spirit2/Jamfile.v2
==============================================================================
--- branches/quickbook-1.5-spirit2/Jamfile.v2	(original)
+++ branches/quickbook-1.5-spirit2/Jamfile.v2	2010-01-27 17:01:09 EST (Wed, 27 Jan 2010)
@@ -29,6 +29,7 @@
     detail/markups.cpp
     phrase.cpp
     phrase_actions.cpp
+    phrase_image.cpp
     block.cpp
     doc_info.cpp
     detail/syntax_highlight.cpp
Modified: branches/quickbook-1.5-spirit2/detail/actions.cpp
==============================================================================
--- branches/quickbook-1.5-spirit2/detail/actions.cpp	(original)
+++ branches/quickbook-1.5-spirit2/detail/actions.cpp	2010-01-27 17:01:09 EST (Wed, 27 Jan 2010)
@@ -397,137 +397,6 @@
         detail::print_char(*x.begin(), phrase.get());
     }
 
-    void image_action::operator()(iterator position, std::string image_fileref,
-            std::multimap<std::string, std::string> input_attributes) const
-    {
-        std::map<std::string, std::string> attributes(
-            input_attributes.begin(), input_attributes.end());
-        
-        if(attributes.size() != input_attributes.size()) {
-            boost::spirit::classic::file_position const pos = position.get_position();
-            
-            std::map<std::string, std::string> duplicates;
-            std::set_difference(
-                input_attributes.begin(), input_attributes.end(),
-                attributes.begin(), attributes.end(),
-                std::inserter(duplicates, duplicates.end()));
-            
-            for(std::map<std::string, std::string>::iterator
-                begin = duplicates.begin(), end = duplicates.end();
-                begin != end; ++begin)
-            {
-                detail::outerr(pos.file,pos.line)
-                    << "Duplicate image attribute: "
-                    << begin->first
-                    << std::endl;
-                ++error_count;
-            }
-        }
-    
-        fs::path const img_path(image_fileref);
-        
-        attribute_map::iterator it = attributes.find("alt");
-        std::string alt_text = it != attributes.end() ? it->second : fs::basename(img_path);
-        attributes.erase("alt");
-
-        attributes.insert(attribute_map::value_type("fileref", image_fileref));
-
-        if(fs::extension(img_path) == ".svg")
-        {
-           //
-           // SVG's need special handling:
-           //
-           // 1) We must set the "format" attribute, otherwise
-           //    HTML generation produces code that will not display
-           //    the image at all.
-           // 2) We need to set the "contentwidth" and "contentdepth"
-           //    attributes, otherwise the image will be displayed inside
-           //    a tiny box with scrollbars (Firefox), or else cropped to
-           //    fit in a tiny box (IE7).
-           //
-           attributes.insert(attribute_map::value_type("format", "SVG"));
-           //
-           // Image paths are relative to the html subdirectory:
-           // TODO: This only works when you're running in the correct directory.
-           // Support 'boost:' directories? Include paths?
-           //
-           fs::path img;
-           if(img_path.root_path().empty())
-              img = "html" / img_path;  // relative path
-           else
-              img = img_path;   // absolute path
-           //
-           // Now load the SVG file:
-           //
-           std::string svg_text;
-           fs::ifstream fs(img);
-           char c;
-           while(fs.get(c) && fs.good())
-              svg_text.push_back(c);
-           //
-           // Extract the svg header from the file:
-           //
-           std::string::size_type a, b;
-           a = svg_text.find("<svg");
-           b = svg_text.find('>', a);
-           svg_text = (a == std::string::npos) ? "" : svg_text.substr(a, b - a);
-           //
-           // Now locate the "width" and "height" attributes
-           // and borrow their values:
-           //
-           a = svg_text.find("width");
-           a = svg_text.find('=', a);
-           a = svg_text.find('\"', a);
-           b = svg_text.find('\"', a + 1);
-           if(a != std::string::npos)
-           {
-              attributes.insert(attribute_map::value_type("contentwidth",
-                std::string(svg_text.begin() + a + 1, svg_text.begin() + b)));
-           }
-           a = svg_text.find("height");
-           a = svg_text.find('=', a);
-           a = svg_text.find('\"', a);
-           b = svg_text.find('\"', a + 1);
-           if(a != std::string::npos)
-           {
-              attributes.insert(attribute_map::value_type("contentdepth",
-                std::string(svg_text.begin() + a + 1, svg_text.begin() + b)));
-           }
-        }
-
-        phrase << "<inlinemediaobject>";
-
-        phrase << "<imageobject><imagedata";
-        
-        for(attribute_map::const_iterator
-            attr_first = attributes.begin(), attr_last  = attributes.end();
-            attr_first != attr_last; ++attr_first)
-        {
-            phrase << " " << attr_first->first << "=\"";
-
-            for(std::string::const_iterator
-                first = attr_first->second.begin(),
-                last  = attr_first->second.end();
-                first != last; ++first)
-            {
-                if (*first == '\\' && ++first == last) break;
-                detail::print_char(*first, phrase.get());
-            }
-
-            phrase << "\"";
-        }
-
-        phrase << "></imagedata></imageobject>";
-
-        // Also add a textobject -- use the basename of the image file.
-        // This will mean we get "alt" attributes of the HTML img.
-        phrase << "<textobject><phrase>";
-        detail::print_string(alt_text, phrase.get());
-        phrase << "</phrase></textobject>";
-
-        phrase << "</inlinemediaobject>";
-    }
-
     void macro_identifier_action::operator()(iterator_range x, unused_type, unused_type) const
     {
         actions.macro_id.assign(x.begin(), x.end());
Modified: branches/quickbook-1.5-spirit2/detail/actions.hpp
==============================================================================
--- branches/quickbook-1.5-spirit2/detail/actions.hpp	(original)
+++ branches/quickbook-1.5-spirit2/detail/actions.hpp	2010-01-27 17:01:09 EST (Wed, 27 Jan 2010)
@@ -376,25 +376,6 @@
         collector& phrase;
     };
     
-    struct image_action
-    {
-        template <typename Arg1, typename Arg2, typename Arg3 = void>
-        struct result {typedef void type; };
-    
-        // Handles inline images
-
-        image_action(collector& phrase, int& error_count)
-        : phrase(phrase)
-        , error_count(error_count) {}
-
-        void operator()(iterator, std::string,
-            std::multimap<std::string, std::string>
-                = std::multimap<std::string, std::string>()) const;
-
-        collector& phrase;
-        int& error_count;
-    };
-
     struct markup_action
     {
         template <typename T = void> struct result { typedef void type; };
Modified: branches/quickbook-1.5-spirit2/detail/actions_class.cpp
==============================================================================
--- branches/quickbook-1.5-spirit2/detail/actions_class.cpp	(original)
+++ branches/quickbook-1.5-spirit2/detail/actions_class.cpp	2010-01-27 17:01:09 EST (Wed, 27 Jan 2010)
@@ -94,7 +94,6 @@
         , tip(out, temp_para, tip_pre, tip_post)
         , plain_char(phrase)
         , raw_char(phrase)
-        , image(phrase, error_count)
         , cond_phrase_pre(phrase, conditions, macro)
         , cond_phrase_post(phrase, conditions, macro)
 
Modified: branches/quickbook-1.5-spirit2/detail/actions_class.hpp
==============================================================================
--- branches/quickbook-1.5-spirit2/detail/actions_class.hpp	(original)
+++ branches/quickbook-1.5-spirit2/detail/actions_class.hpp	2010-01-27 17:01:09 EST (Wed, 27 Jan 2010)
@@ -117,7 +117,6 @@
         phrase_action           warning, caution, important, note, tip;
         plain_char_action       plain_char;
         raw_char_action         raw_char;
-        image_action            image;
         cond_phrase_action_pre  cond_phrase_pre;
         cond_phrase_action_post cond_phrase_post;
 
Modified: branches/quickbook-1.5-spirit2/phrase.cpp
==============================================================================
--- branches/quickbook-1.5-spirit2/phrase.cpp	(original)
+++ branches/quickbook-1.5-spirit2/phrase.cpp	2010-01-27 17:01:09 EST (Wed, 27 Jan 2010)
@@ -37,11 +37,26 @@
     (std::string, content)
 )
 
+BOOST_FUSION_ADAPT_STRUCT(
+    quickbook::image,
+    (quickbook::file_position, position)
+    (std::string, image_filename)
+    (quickbook::image::attribute_map, attributes)
+)
+
 namespace quickbook
 {
     namespace qi = boost::spirit::qi;
     namespace ph = boost::phoenix;
     
+    struct get_position_impl
+    {
+        template <typename Context>
+        void operator()(iterator_range& it, Context& c, unused_type x) const {
+            qi::_val(it, c, x) = it.begin().get_position();
+        }
+    } get_position;
+    
     struct phrase_grammar::rules
     {
         rules(quickbook::actions& actions, bool& no_eols);
@@ -60,14 +75,16 @@
                         brackets_1_4, template_inner_arg_1_5, brackets_1_5
                         ;
 
+        qi::rule<iterator, file_position()> position;
+
         qi::rule<iterator, std::string()> template_arg_1_4, template_arg_1_5;
         qi::rule<iterator, std::vector<std::string>() > template_args;
 
         qi::rule<iterator, std::string()> phrase_attr;
 
-        qi::rule<iterator> image, image_1_4, image_1_5;
+        qi::rule<iterator, quickbook::image()> image, image_1_4, image_1_5;
         qi::rule<iterator, std::string()> image_filename, image_attribute_key, image_attribute_value;
-        qi::rule<iterator, std::multimap<std::string, std::string>()> image_attributes;
+        qi::rule<iterator, quickbook::image::attribute_map()> image_attributes;
         qi::rule<iterator, std::pair<std::string, std::string>()> image_attribute;
         
         qi::rule<iterator, boost::iterator_range<iterator>(char)> simple_markup;
@@ -254,7 +271,7 @@
         phrase_markup =
                 '['
             >>  (   cond_phrase
-                |   image
+                |   image                           [actions.process]
                 |   url                             [actions.process]
                 |   link                            [actions.process]
                 |   anchor
@@ -298,22 +315,22 @@
             (qi::eps(qbk_since(105u)) >> image_1_5) |
             (qi::eps(qbk_before(105u)) >> image_1_4);
         
-        image_1_4 = (
-                qi::raw['$']
+        image_1_4 =
+                position
+            >>  '$'
             >>  blank
             >>  *(qi::char_ - phrase_end)
             >>  &qi::lit(']')
-            ) [ph::bind(actions.image, ph::begin(qi::_1), as_string(qi::_2))]
             ;
         
-        image_1_5 = (
-                qi::raw['$']
+        image_1_5 =
+                position
+            >>  '$'
             >>  blank
             >>  image_filename
             >>  hard_space
             >>  image_attributes
             >>  &qi::lit(']')
-            ) [ph::bind(actions.image, ph::begin(qi::_1), qi::_2, qi::_3)]
             ;
 
         image_filename = qi::raw[
@@ -417,6 +434,8 @@
                 qi::lit("footnote")                 [actions.footnote_pre]
             >>  blank >> phrase                     [actions.footnote_post]
             ;
+
+         position = qi::raw[qi::eps] [get_position];
     }
 
     struct simple_phrase_grammar::rules
Modified: branches/quickbook-1.5-spirit2/phrase.hpp
==============================================================================
--- branches/quickbook-1.5-spirit2/phrase.hpp	(original)
+++ branches/quickbook-1.5-spirit2/phrase.hpp	2010-01-27 17:01:09 EST (Wed, 27 Jan 2010)
@@ -11,11 +11,14 @@
 #define BOOST_SPIRIT_QUICKBOOK_PHRASE_HPP
 
 #include <string>
+#include <map>
+#include <boost/spirit/include/classic_position_iterator.hpp>
 
 namespace quickbook
 {
     // TODO: Add to a forward header somewhere.
     class actions;
+    typedef boost::spirit::classic::file_position file_position;
 
     struct source_mode {
         source_mode() {}
@@ -39,9 +42,18 @@
         std::string destination;
         std::string content;
     };
+    
+    struct image {
+        typedef std::multimap<std::string, std::string> attribute_map;
+    
+        file_position position;
+        std::string image_filename;
+        attribute_map attributes;
+    };
 
     void process(quickbook::actions& actions, source_mode const& s);
     void process(quickbook::actions& actions, link const& x);
+    void process(quickbook::actions& actions, image const& x);
 }
 
 #endif // BOOST_SPIRIT_QUICKBOOK_PHRASE_HPP
Added: branches/quickbook-1.5-spirit2/phrase_image.cpp
==============================================================================
--- (empty file)
+++ branches/quickbook-1.5-spirit2/phrase_image.cpp	2010-01-27 17:01:09 EST (Wed, 27 Jan 2010)
@@ -0,0 +1,147 @@
+/*=============================================================================
+    Copyright (c) 2002 2004 2006 Joel de Guzman
+    Copyright (c) 2004 Eric Niebler
+    http://spirit.sourceforge.net/
+
+    Use, modification and distribution is subject to the Boost Software
+    License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+    http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#include "./phrase.hpp"
+#include "./detail/actions_class.hpp"
+#include <boost/filesystem/convenience.hpp>
+#include <boost/filesystem/fstream.hpp>
+
+namespace quickbook
+{
+    namespace fs = boost::filesystem;
+
+    void process(quickbook::actions& actions, image const& x)
+    {
+        std::map<std::string, std::string> attributes(
+            x.attributes.begin(), x.attributes.end());
+        
+        if(attributes.size() != x.attributes.size()) {
+            std::map<std::string, std::string> duplicates;
+            std::set_difference(
+                x.attributes.begin(), x.attributes.end(),
+                attributes.begin(), attributes.end(),
+                std::inserter(duplicates, duplicates.end()));
+            
+            for(std::map<std::string, std::string>::iterator
+                begin = duplicates.begin(), end = duplicates.end();
+                begin != end; ++begin)
+            {
+                detail::outerr(x.position.file, x.position.line)
+                    << "Duplicate image attribute: "
+                    << begin->first
+                    << std::endl;
+                ++actions.error_count;
+            }
+        }
+    
+        fs::path const img_path(x.image_filename);
+        
+        attribute_map::iterator it = attributes.find("alt");
+        std::string alt_text = it != attributes.end() ? it->second : fs::basename(img_path);
+        attributes.erase("alt");
+
+        attributes.insert(attribute_map::value_type("fileref", x.image_filename));
+
+        if(fs::extension(img_path) == ".svg")
+        {
+           //
+           // SVG's need special handling:
+           //
+           // 1) We must set the "format" attribute, otherwise
+           //    HTML generation produces code that will not display
+           //    the image at all.
+           // 2) We need to set the "contentwidth" and "contentdepth"
+           //    attributes, otherwise the image will be displayed inside
+           //    a tiny box with scrollbars (Firefox), or else cropped to
+           //    fit in a tiny box (IE7).
+           //
+           attributes.insert(attribute_map::value_type("format", "SVG"));
+           //
+           // Image paths are relative to the html subdirectory:
+           // TODO: This only works when you're running in the correct directory.
+           // Support 'boost:' directories? Include paths?
+           //
+           fs::path img;
+           if(img_path.root_path().empty())
+              img = "html" / img_path;  // relative path
+           else
+              img = img_path;   // absolute path
+           //
+           // Now load the SVG file:
+           //
+           std::string svg_text;
+           fs::ifstream fs(img);
+           char c;
+           while(fs.get(c) && fs.good())
+              svg_text.push_back(c);
+           //
+           // Extract the svg header from the file:
+           //
+           std::string::size_type a, b;
+           a = svg_text.find("<svg");
+           b = svg_text.find('>', a);
+           svg_text = (a == std::string::npos) ? "" : svg_text.substr(a, b - a);
+           //
+           // Now locate the "width" and "height" attributes
+           // and borrow their values:
+           //
+           a = svg_text.find("width");
+           a = svg_text.find('=', a);
+           a = svg_text.find('\"', a);
+           b = svg_text.find('\"', a + 1);
+           if(a != std::string::npos)
+           {
+              attributes.insert(attribute_map::value_type("contentwidth",
+                std::string(svg_text.begin() + a + 1, svg_text.begin() + b)));
+           }
+           a = svg_text.find("height");
+           a = svg_text.find('=', a);
+           a = svg_text.find('\"', a);
+           b = svg_text.find('\"', a + 1);
+           if(a != std::string::npos)
+           {
+              attributes.insert(attribute_map::value_type("contentdepth",
+                std::string(svg_text.begin() + a + 1, svg_text.begin() + b)));
+           }
+        }
+
+        actions.phrase << "<inlinemediaobject>";
+
+        actions.phrase << "<imageobject><imagedata";
+        
+        for(attribute_map::const_iterator
+            attr_first = attributes.begin(), attr_last  = attributes.end();
+            attr_first != attr_last; ++attr_first)
+        {
+            actions.phrase << " " << attr_first->first << "=\"";
+
+            for(std::string::const_iterator
+                first = attr_first->second.begin(),
+                last  = attr_first->second.end();
+                first != last; ++first)
+            {
+                if (*first == '\\' && ++first == last) break;
+                detail::print_char(*first, actions.phrase.get());
+            }
+
+            actions.phrase << "\"";
+        }
+
+        actions.phrase << "></imagedata></imageobject>";
+
+        // Also add a textobject -- use the basename of the image file.
+        // This will mean we get "alt" attributes of the HTML img.
+        actions.phrase << "<textobject><phrase>";
+        detail::print_string(alt_text, actions.phrase.get());
+        actions.phrase << "</phrase></textobject>";
+
+        actions.phrase << "</inlinemediaobject>";
+    }
+}
\ No newline at end of file