Files
quickbook/phrase_image.cpp
Daniel James a8dfaf1852 Separate actions and state.
[SVN r59563]
2010-02-07 09:12:02 +00:00

119 lines
4.4 KiB
C++

/*=============================================================================
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 <boost/filesystem/convenience.hpp>
#include <boost/filesystem/fstream.hpp>
#include "phrase.hpp"
#include "gen_types.hpp"
#include "actions.hpp"
#include "state.hpp"
#include "utils.hpp"
namespace quickbook
{
namespace fs = boost::filesystem;
image2 process(quickbook::actions& actions, image const& x)
{
typedef image2::attribute_map attribute_map;
typedef attribute_map::value_type attribute;
attribute_map 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.state_.error_count;
}
}
fs::path const img_path(x.image_filename);
attributes.insert(attribute("fileref", x.image_filename));
// Note: If there is already an alt attribute this is a no-op.
attributes.insert(attribute("alt", fs::basename(img_path)));
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("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("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("contentdepth",
std::string(svg_text.begin() + a + 1, svg_text.begin() + b)));
}
}
return image2(attributes);
}
}