implement style-level opacity - closes #314

This commit is contained in:
Dane Springmeyer 2012-06-19 15:10:28 -04:00
parent 4e16618771
commit 48a543b5d5
6 changed files with 73 additions and 32 deletions

View file

@ -11,6 +11,8 @@ For a complete change history, see the git log.
Not yet released Not yet released
- Added style-level 'opacity' (#314)
- PostGIS: Added 'simplify_geometries' option - will trigger ST_Simplify on geometries before returning to Mapnik (#1179) - PostGIS: Added 'simplify_geometries' option - will trigger ST_Simplify on geometries before returning to Mapnik (#1179)
- Improved error feedback for invalid values passed to map.query_point - Improved error feedback for invalid values passed to map.query_point

View file

@ -51,7 +51,7 @@ typedef std::vector<rule*> rule_ptrs;
class MAPNIK_DECL feature_type_style class MAPNIK_DECL feature_type_style
{ {
private: private:
rules rules_; rules rules_;
filter_mode_e filter_mode_; filter_mode_e filter_mode_;
// image_filters // image_filters
std::vector<filter::filter_type> filters_; std::vector<filter::filter_type> filters_;
@ -63,6 +63,7 @@ private:
rule_ptrs if_rules_; rule_ptrs if_rules_;
rule_ptrs else_rules_; rule_ptrs else_rules_;
rule_ptrs also_rules_; rule_ptrs also_rules_;
float opacity_;
public: public:
feature_type_style(); feature_type_style();
@ -90,7 +91,9 @@ public:
// compositing // compositing
void set_comp_op(composite_mode_e comp_op); void set_comp_op(composite_mode_e comp_op);
boost::optional<composite_mode_e> comp_op() const; boost::optional<composite_mode_e> comp_op() const;
void set_opacity(float opacity);
float get_opacity() const;
~feature_type_style() {} ~feature_type_style() {}
private: private:

View file

@ -197,15 +197,25 @@ template <typename T>
void agg_renderer<T>::start_style_processing(feature_type_style const& st) void agg_renderer<T>::start_style_processing(feature_type_style const& st)
{ {
MAPNIK_LOG_DEBUG(agg_renderer) << "agg_renderer: Start processing style"; MAPNIK_LOG_DEBUG(agg_renderer) << "agg_renderer: Start processing style";
if (st.comp_op()) style_level_compositing_ = true; if (st.comp_op() || st.image_filters().size() > 0 || st.get_opacity() < 1)
else style_level_compositing_ = false; {
style_level_compositing_ = true;
}
else
{
style_level_compositing_ = false;
}
if (style_level_compositing_ || st.image_filters().size() > 0) if (style_level_compositing_)
{ {
if (!internal_buffer_) if (!internal_buffer_)
{
internal_buffer_ = boost::make_shared<buffer_type>(pixmap_.width(),pixmap_.height()); internal_buffer_ = boost::make_shared<buffer_type>(pixmap_.width(),pixmap_.height());
}
else else
{
internal_buffer_->set_background(color(0,0,0,0)); // fill with transparent colour internal_buffer_->set_background(color(0,0,0,0)); // fill with transparent colour
}
current_buffer_ = internal_buffer_.get(); current_buffer_ = internal_buffer_.get();
} }
else else
@ -217,33 +227,35 @@ void agg_renderer<T>::start_style_processing(feature_type_style const& st)
template <typename T> template <typename T>
void agg_renderer<T>::end_style_processing(feature_type_style const& st) void agg_renderer<T>::end_style_processing(feature_type_style const& st)
{ {
bool blend_from = false; if (style_level_compositing_)
if (st.image_filters().size() > 0)
{ {
blend_from = true; bool blend_from = false;
mapnik::filter::filter_visitor<image_32> visitor(*current_buffer_); if (st.image_filters().size() > 0)
BOOST_FOREACH(mapnik::filter::filter_type filter_tag, st.image_filters()) {
blend_from = true;
mapnik::filter::filter_visitor<image_32> visitor(*current_buffer_);
BOOST_FOREACH(mapnik::filter::filter_type filter_tag, st.image_filters())
{
boost::apply_visitor(visitor, filter_tag);
}
}
if (st.comp_op())
{
composite(pixmap_.data(),current_buffer_->data(), *st.comp_op(), st.get_opacity(), 0, 0, false);
}
else if (blend_from || st.get_opacity() < 1)
{
composite(pixmap_.data(),current_buffer_->data(), src_over, st.get_opacity(), 0, 0, false);
}
// apply any 'direct' image filters
mapnik::filter::filter_visitor<image_32> visitor(pixmap_);
BOOST_FOREACH(mapnik::filter::filter_type filter_tag, st.direct_image_filters())
{ {
boost::apply_visitor(visitor, filter_tag); boost::apply_visitor(visitor, filter_tag);
} }
} }
if (st.comp_op())
{
composite(pixmap_.data(),current_buffer_->data(), *st.comp_op(), 1.0f, 0, 0, false);
}
else if (blend_from)
{
composite(pixmap_.data(),current_buffer_->data(), src_over, 1.0f, 0, 0, false);
}
// apply any 'direct' image filters
mapnik::filter::filter_visitor<image_32> visitor(pixmap_);
BOOST_FOREACH(mapnik::filter::filter_type filter_tag, st.direct_image_filters())
{
boost::apply_visitor(visitor, filter_tag);
}
MAPNIK_LOG_DEBUG(agg_renderer) << "agg_renderer: End processing style"; MAPNIK_LOG_DEBUG(agg_renderer) << "agg_renderer: End processing style";
} }

View file

@ -38,7 +38,8 @@ feature_type_style::feature_type_style()
: filter_mode_(FILTER_ALL), : filter_mode_(FILTER_ALL),
filters_(), filters_(),
direct_filters_(), direct_filters_(),
scale_denom_validity_(-1) scale_denom_validity_(-1),
opacity_(1.0f)
{} {}
feature_type_style::feature_type_style(feature_type_style const& rhs, bool deep_copy) feature_type_style::feature_type_style(feature_type_style const& rhs, bool deep_copy)
@ -46,7 +47,8 @@ feature_type_style::feature_type_style(feature_type_style const& rhs, bool deep_
filters_(rhs.filters_), filters_(rhs.filters_),
direct_filters_(rhs.direct_filters_), direct_filters_(rhs.direct_filters_),
comp_op_(rhs.comp_op_), comp_op_(rhs.comp_op_),
scale_denom_validity_(-1) scale_denom_validity_(-1),
opacity_(rhs.opacity_)
{ {
if (!deep_copy) { if (!deep_copy) {
rules_ = rhs.rules_; rules_ = rhs.rules_;
@ -67,6 +69,7 @@ feature_type_style& feature_type_style::operator=(feature_type_style const& rhs)
direct_filters_ = rhs.direct_filters_; direct_filters_ = rhs.direct_filters_;
comp_op_ = rhs.comp_op_; comp_op_ = rhs.comp_op_;
scale_denom_validity_ = -1; scale_denom_validity_ = -1;
opacity_= rhs.opacity_;
return *this; return *this;
} }
@ -126,6 +129,16 @@ boost::optional<composite_mode_e> feature_type_style::comp_op() const
return comp_op_; return comp_op_;
} }
void feature_type_style::set_opacity(float opacity)
{
opacity_ = opacity;
}
float feature_type_style::get_opacity() const
{
return opacity_;
}
void feature_type_style::update_rule_cache(double scale_denom) void feature_type_style::update_rule_cache(double scale_denom)
{ {
if_rules_.clear(); if_rules_.clear();

View file

@ -433,8 +433,13 @@ void map_parser::parse_style(Map & map, xml_node const& sty)
} }
} }
// image filters optional<float> opacity = sty.get_opt_attr<float>("opacity");
if (opacity)
{
style.set_opacity(*opacity);
}
// image filters
mapnik::image_filter_grammar<std::string::const_iterator, mapnik::image_filter_grammar<std::string::const_iterator,
std::vector<mapnik::filter::filter_type> > filter_grammar; std::vector<mapnik::filter::filter_type> > filter_grammar;

View file

@ -518,7 +518,6 @@ void serialize_style( ptree & map_node, Map::const_style_iterator style_it, bool
{ {
feature_type_style const& style = style_it->second; feature_type_style const& style = style_it->second;
std::string const& name = style_it->first; std::string const& name = style_it->first;
filter_mode_e filter_mode = style.get_filter_mode();
ptree & style_node = map_node.push_back( ptree & style_node = map_node.push_back(
ptree::value_type("Style", ptree()))->second; ptree::value_type("Style", ptree()))->second;
@ -526,11 +525,18 @@ void serialize_style( ptree & map_node, Map::const_style_iterator style_it, bool
set_attr(style_node, "name", name); set_attr(style_node, "name", name);
feature_type_style dfl; feature_type_style dfl;
filter_mode_e filter_mode = style.get_filter_mode();
if (filter_mode != dfl.get_filter_mode() || explicit_defaults) if (filter_mode != dfl.get_filter_mode() || explicit_defaults)
{ {
set_attr(style_node, "filter-mode", filter_mode); set_attr(style_node, "filter-mode", filter_mode);
} }
double opacity = style.get_opacity();
if (opacity != dfl.get_opacity() || explicit_defaults)
{
set_attr(style_node, "opacity", opacity);
}
rules::const_iterator it = style.get_rules().begin(); rules::const_iterator it = style.get_rules().begin();
rules::const_iterator end = style.get_rules().end(); rules::const_iterator end = style.get_rules().end();
for (; it != end; ++it) for (; it != end; ++it)