How parsed values are passed to context¶
To find out how value of the SVG attribute will be passed to context, following algorithm should be applied:
- If attribute tag is included in passthrough_attributes sequence, then its value will be passed by Value Events Policy as a string.
- If for this element and attribute
traits::attribute_type<ElementTag, AttributeTag>::typeistag::type::string, then value will also be passed by Value Events Policy as a string. - Otherwise type of the attribute should be found in its description in SVG Specification.
- Attribute values of type <path data> (e.g. d attribute of path element) are described in Path section.
- Attribute values of type <transform list> (e.g. transform attribute) are described in Transform section.
- All others are passed through Value Events Policy.
Value Events Policy¶
Value Events Policy Concept¶
Value Events Policy is a class, containing static set methods, that receives reference to
context object as a first argument, attribute tag as a second and a source tag as a third.
Source tag is one of two types: tag::source::css and tag::source::attribute (they have common base tag::source::any).
Source tag shows where value comes from – CSS value in style attribute or from separate SVG/XML attribute.
Number and types of other parameters depends on an attribute type.
structvalue_events_policy { staticvoidset(Context&context,AttributeTagtag,SourceTagsource,ValueType1const&value1); staticvoidset(Context&context,AttributeTagtag,SourceTagsource,ValueType1const&value1,ValueType2const&value2); /*...*/ };
policy::value_events::forward_to_method used by default forward calls to set methods of context object:
template<classContext> structforward_to_method { template<classAttributeTag,class...Args> staticvoidset(Context&context,AttributeTagtag,tag::source::anyconst&,Args...args) { context.set(tag,args...); } };
Note
Source tag is dropped by default Value Events Policy, because default
Attribute Traversal Policy processes only one value of the same property,
even if both are provided (css_hides_presentation_attribute = true).
Note
Default Value Events Policy doesn’t pass tag::value::inherit values of properties and presentation attributes,
that are inherited (see policy::value_events::skip_inherit).
inherit value for such attributes is equivalent to its absence.
Example of default Value Events Policy usage:
#include<svgpp/svgpp.hpp> usingnamespacesvgpp; structContext { voidset(tag::attribute::amplitude,doublevalue) { std::cout<<value<<"\n"; } }; voidfunc() { Contextcontext; value_parser<tag::type::number>::parse(tag::attribute::amplitude(),context,std::string("3.14"),tag::source::attribute()); }
Example of own Value Events Policy implementation.
Created policy::value_events::default_policy template class specialization
for our context type (let it be boost::optional<double> in our example):
namespacesvgpp{namespacepolicy{namespacevalue_events { template<> structdefault_policy<boost::optional<double>> { template<classAttributeTag> staticvoidset(boost::optional<double>&context,AttributeTagtag,tag::source::any,doublevalue) { context=value; } }; }}} voidfunc() { boost::optional<double>context; value_parser<tag::type::number>::parse(tag::attribute::amplitude(),context,std::string("3.14"),tag::source::attribute()); if(context) std::cout<<*context<<"\n"; }
- Literal Values
If literal is one of attribute possible values, then this value will cause call with tag from
tag::valuenamespace. Example of attributes that may have literal values:gradientUnits="userSpaceOnUse | objectBoundingBox" clip-path="<funciri> | none | inherit"
gradientUnits is limited to two literal values. clip-path, besides none and inherit literal values may get values of <FuncIRI> type.
Example of context implementation, that receives values of gradientUnits attributes:
classGradientContext { public: GradientContext() :m_gradientUnitsUserSpace(false) {} voidset(tag::attribute::gradientUnits,tag::value::userSpaceOnUse) { m_gradientUnitsUserSpace=true; } voidset(tag::attribute::gradientUnits,tag::value::objectBoundingBox) { m_gradientUnitsUserSpace=false; } private: boolm_gradientUnitsUserSpace; };
- <length> or <coordinate>
- Is passed as single argument, whose type is set by Length Factory (by default
double). - <IRI> or <FuncIRI>
- See IRI.
- <integer>
- Single argument of
inttype is used. - <number> or <opacity-value>
- Is passed as single argument of number_type_ (by default
double).
<percentage>
- <color>
- Is passed as single argument, whose type is set by Color Factory
(by default 8 bit per channel RGB packed in
int). - <color> [<icccolor>]
If <icccolor> isn’t set, then it is passed as single argument, whose type is set by Color Factory. Otherwise, second argument is added, whose type is set by ICC Color Factory. Example:
structContext { voidset(tag::attribute::flood_color,intrgb); voidset(tag::attribute::flood_color,intrgb,tag::skip_icc_color); voidset(tag::attribute::flood_color,tag::value::currentColor); voidset(tag::attribute::flood_color,tag::value::inherit); };
- <angle>
- Is passed as single argument, whose type and value are set by Angle Factory
(by default
doublevalue in degrees). - <number-optional-number>
- Is passed as one or two arguments of number_type_ type (by default
double). - <list-of-numbers>, <list-of-lengths> or <list-of-points>
Is passed as single argument of unspecified type, which is model of Boost Single Pass Range.
- range items have type:
- number_type_ (by default
double) in case of <list-of-numbers>; - that is set by Length Factory in case of <list-of-lengths>;
std::pair<number_type, number_type>(by defaultstd::pair<double, double>) in case of <list-of-points>.
- number_type_ (by default
Example:
structContext { template<classRange> voidset(tag::attribute::kernelMatrix,Rangeconst&range) { for(typenameboost::range_iterator<Range>::typeit=boost::begin(range),end=boost::end(range); it!=end;++it) std::cout<<*it; } };
Note
If template function can’t be used (e.g. it is virtual function), then Boost any_range can be used as range type instead:
typedefboost::any_range<double,boost::single_pass_traversal_tag,doubleconst&,std::ptrdiff_t>Range;
- <shape>
- Is passed as 5 arguments - first is tag
tag::value::rect, others are of number_type_ type (by defaultdouble):(tag::value::rect(), top, right, bottom, left). - viewBox attribute
- Is passed as 4 arguments of number_type_ type (by default
double):(x, y, width, height). - bbox attribute
- Is passed as 4 arguments of number_type_ type (by default
double):(lo_x, lo_y, hi_x, hi_y). - preserveAspectRatio attribute
- Depending on value is passed as:
(bool defer, tag::value::none)(bool defer, AlignT align, MeetOrSliceT meetOrSlice)Type
AlignTis one oftag::value::xMinYMin,tag::value::xMidYMin,tag::value::xMaxYMin,tag::value::xMinYMid,tag::value::xMidYMid,tag::value::xMaxYMid,tag::value::xMinYMax,tag::value::xMidYMax,tag::value::xMaxYMax. TypeMeetOrSliceTistag::value::meetortag::value::slice.
- text-decoration property
none and inherit values are passed as Literal Values. Other values are passed as 8 arguments, 4 of which is of type
bool, each of them preceded with tag, describing argument meaning. Boolean parameters takestruevalue if corresponding text decoration is set in property:structContext { voidset(tag::attribute::text_decoration,tag::value::none); voidset(tag::attribute::text_decoration,tag::value::inherit); voidset(tag::attribute::text_decoration, tag::value::underline,boolunderline, tag::value::overline,booloverline, tag::value::line_through,boolline_through, tag::value::blink,boolblink); };
- enable-background property
- accumulate, new and inherit values are passed as Literal Values.
Values as new <x> <y> <width> <height> are passed as 5 arguments, first of them is tag,
other have type number_type_ (by default
double):(tag::value::new_(), x, y, width, height). - <paint>
Possible combinations of argument types:
- (
tag::value::inherit) - (
tag::value::none) - (
tag::value::currentColor) - (<color>)
- (<color>, <icccolor>)
- (<iri>,
tag::value::none) - (<iri>,
tag::value::currentColor) - (<iri>, <color>)
- (<iri>, <color>, <icccolor>)
Which types corresponds to <color> and <icccolor> is described above.
If IRI Policy
policy::iri::distinguish_localis used, then number of methods with <iri> is doubled:- (
tag::value::inherit) - (
tag::value::none) - (
tag::value::currentColor) - (<color>)
- (<color>, <icccolor>)
- (<iri>,
tag::value::none) - (
tag::iri_fragment, <iri fragment>,tag::value::none) - (<iri>,
tag::value::currentColor) - (
tag::iri_fragment, <iri fragment>,tag::value::currentColor) - (<iri>, <color>)
- (
tag::iri_fragment, <iri fragment>, <color>) - (<iri>, <color>, <icccolor>)
- (
tag::iri_fragment, <iri fragment>, <color>, <icccolor>)
Example:
typedefboost::variant<tag::value::none,tag::value::currentColor,int/* rgba */>SolidPaint; structIRIPaint { IRIPaint( std::stringconst&fragment, boost::optional<SolidPaint>const&fallback=boost::optional<SolidPaint>()); }; typedefboost::variant<SolidPaint,IRIPaint>Paint; template<classAttributeTag> classPaintContext { public: voidset(AttributeTag,tag::value::none) { m_paint=tag::value::none(); } voidset(AttributeTag,tag::value::currentColor) { m_paint=tag::value::currentColor(); } voidset(AttributeTag,intcolor,tag::skip_icc_color=tag::skip_icc_color()) { m_paint=color; } template<classIRI> voidset(AttributeTagtag,IRIconst&iri) { throwstd::runtime_error("Non-local references aren't supported"); } template<classIRI> voidset(AttributeTagtag,tag::iri_fragment,IRIconst&fragment) { m_paint=IRIPaint(std::string(boost::begin(fragment),boost::end(fragment))); } template<classIRI> voidset(AttributeTagtag,IRIconst&,tag::value::noneval) { // Ignore non-local IRI, fallback to second option set(tag,val); } template<classIRI> voidset(AttributeTagtag,tag::iri_fragment,IRIconst&fragment,tag::value::noneval) { m_paint=IRIPaint(std::string(boost::begin(fragment),boost::end(fragment)),boost::optional<SolidPaint>(val)); } template<classIRI> voidset(AttributeTagtag,IRIconst&,tag::value::currentColorval) { // Ignore non-local IRI, fallback to second option set(tag,val); } template<classIRI> voidset(AttributeTagtag,tag::iri_fragment,IRIconst&fragment,tag::value::currentColorval) { m_paint=IRIPaint(std::string(boost::begin(fragment),boost::end(fragment)),boost::optional<SolidPaint>(val)); } template<classIRI> voidset(AttributeTagtag,IRIconst&,agg::rgba8val,tag::skip_icc_color=tag::skip_icc_color()) { // Ignore non-local IRI, fallback to second option set(tag,val); } template<classIRI> voidset(AttributeTagtag,tag::iri_fragment,IRIconst&fragment,intval,tag::skip_icc_color=tag::skip_icc_color()) { m_paint=IRIPaint(std::string(boost::begin(fragment),boost::end(fragment)),boost::optional<SolidPaint>(val)); } private: Paintm_paint; };
- (