diff options
| author | Tavmjong Bah <tavmjong@free.fr> | 2011-11-29 11:27:10 +0000 |
|---|---|---|
| committer | tavmjong-free <tavmjong@free.fr> | 2011-11-29 11:27:10 +0000 |
| commit | 771029025214cffd0bc9783656c29e08ad208743 (patch) | |
| tree | f8571540680f4aa0138798f87222263df20c278a | |
| parent | preferences read out: when no unit is specified, assume it is in the requeste... (diff) | |
| download | inkscape-771029025214cffd0bc9783656c29e08ad208743.tar.gz inkscape-771029025214cffd0bc9783656c29e08ad208743.zip | |
Add possibility to check validity of attributes and usefulness of properties.
This code adds the ability to check for every elment in an SVG document if its
attributes are valid and the styling properties are useful. Options under the
SVG Output section of the Inkscape Preferences dialog control what should
be checked when, and what actions should be taken if invalid attributes
or non-useful properties are found.
(bzr r10753)
| -rw-r--r-- | CMakeLists.txt | 1 | ||||
| -rw-r--r-- | build-lx.xml | 3 | ||||
| -rw-r--r-- | configure.ac | 1 | ||||
| -rw-r--r-- | share/Makefile.am | 3 | ||||
| -rw-r--r-- | share/attributes/Makefile.am | 10 | ||||
| -rw-r--r-- | share/attributes/README | 15 | ||||
| -rw-r--r-- | share/attributes/css_defaults | 124 | ||||
| -rw-r--r-- | share/attributes/cssprops | 124 | ||||
| -rwxr-xr-x | share/attributes/genMapDataCSS.pl | 201 | ||||
| -rwxr-xr-x | share/attributes/genMapDataSVG.pl | 104 | ||||
| -rw-r--r-- | share/attributes/svgprops | 552 | ||||
| -rw-r--r-- | src/Makefile_insert | 3 | ||||
| -rw-r--r-- | src/attribute-rel-css.cpp | 195 | ||||
| -rw-r--r-- | src/attribute-rel-css.h | 66 | ||||
| -rw-r--r-- | src/attribute-rel-svg.cpp | 120 | ||||
| -rw-r--r-- | src/attribute-rel-svg.h | 49 | ||||
| -rw-r--r-- | src/attribute-rel-util.cpp | 312 | ||||
| -rw-r--r-- | src/attribute-rel-util.h | 87 | ||||
| -rw-r--r-- | src/path-prefix.h | 4 | ||||
| -rw-r--r-- | src/preferences-skeleton.h | 18 | ||||
| -rw-r--r-- | src/sp-object.cpp | 27 | ||||
| -rw-r--r-- | src/ui/dialog/inkscape-preferences.cpp | 36 | ||||
| -rw-r--r-- | src/ui/dialog/inkscape-preferences.h | 11 | ||||
| -rw-r--r-- | src/xml/repr-io.cpp | 23 | ||||
| -rw-r--r-- | src/xml/simple-node.cpp | 60 |
25 files changed, 2139 insertions, 10 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index eb7878124..b6b983af0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -121,6 +121,7 @@ if(UNIX) install( DIRECTORY + ${CMAKE_SOURCE_DIR}/share/attributes ${CMAKE_SOURCE_DIR}/share/clipart ${CMAKE_SOURCE_DIR}/share/examples ${CMAKE_SOURCE_DIR}/share/extensions diff --git a/build-lx.xml b/build-lx.xml index 307bbb2d8..4dd3c7b90 100644 --- a/build-lx.xml +++ b/build-lx.xml @@ -459,6 +459,9 @@ <copy file="README" todir="${dist}"/> <copy file="TRANSLATORS" todir="${dist}"/> <copy todir="${datadir}/inkscape"> + <fileset dir="share/attributes"> <exclude name=".*\.am"/> </fileset> + </copy> + <copy todir="${datadir}/inkscape"> <fileset dir="share/clipart"> <exclude name=".*\.am"/> </fileset> </copy> <copy todir="${datadir}/inkscape"> diff --git a/configure.ac b/configure.ac index e10fa82ef..05e310ddd 100644 --- a/configure.ac +++ b/configure.ac @@ -972,6 +972,7 @@ src/2geom/makefile doc/Makefile po/Makefile.in share/Makefile +share/attributes/Makefile share/clipart/Makefile share/examples/Makefile share/extensions/Makefile diff --git a/share/Makefile.am b/share/Makefile.am index ec42d761f..abc1608c7 100644 --- a/share/Makefile.am +++ b/share/Makefile.am @@ -1,4 +1,5 @@ -SUBDIRS = clipart \ +SUBDIRS = attributes \ + clipart \ examples \ extensions \ filters \ diff --git a/share/attributes/Makefile.am b/share/attributes/Makefile.am new file mode 100644 index 000000000..9834c5b14 --- /dev/null +++ b/share/attributes/Makefile.am @@ -0,0 +1,10 @@ + +attributesdir = $(datadir)/inkscape/attributes + +attributes_DATA = \ + svgprops \ + cssprops \ + css_defaults \ + README + +EXTRA_DIST = $(attributes_DATA) diff --git a/share/attributes/README b/share/attributes/README new file mode 100644 index 000000000..a58ebb859 --- /dev/null +++ b/share/attributes/README @@ -0,0 +1,15 @@ +This directory contains data for XML attribute checking, CSS property +checking, and CSS defaults checking. + +svgprops - Mapping of valid attributes for elements in svg namespace + +cssprops - Mapping of valid CSS properties to svg elements + +css_defaults - Mapping of CSS properties to default values and inheritance. + +genMapData* - PERL script files that create the data files from the +Attribute and CSS Properties appendices of the SVG 1.1 2nd Edtion +specification located at http://www.w3.org/TR/SVG/ + +The data files are loaded at runtime. The default location is +'inkscape_data_dir/attributes'. They can be user customized. diff --git a/share/attributes/css_defaults b/share/attributes/css_defaults new file mode 100644 index 000000000..7308a8f0c --- /dev/null +++ b/share/attributes/css_defaults @@ -0,0 +1,124 @@ +"alignment-baseline" - "auto" - "no" + +"baseline-shift" - "baseline" - "no" + +"clip" - "auto" - "no" + +"clip-path" - "none" - "no" + +"clip-rule" - "nonzero" - "yes" + +"color" - "NO_DEFAULT" - "yes" + +"color-interpolation" - "sRGB" - "yes" + +"color-interpolation-filters" - "linearRGB" - "yes" + +"color-profile" - "auto" - "yes" + +"color-rendering" - "auto" - "yes" + +"cursor" - "auto" - "yes" + +"direction" - "ltr" - "yes" + +"display" - "inline" - "no" + +"dominant-baseline" - "auto" - "no" + +"enable-background" - "accumulate" - "no" + +"fill" - "black" - "yes" + +"fill-opacity" - "1" - "yes" + +"fill-rule" - "nonzero" - "yes" + +"filter" - "none" - "no" + +"flood-color" - "black" - "no" + +"flood-opacity" - "1" - "no" + +"font" - "NO_DEFAULT" - "yes" + +"font-family" - "NO_DEFAULT" - "yes" + +"font-size" - "medium" - "yes, the computed value is inherited" + +"font-size-adjust" - "none" - "yes" + +"font-stretch" - "normal" - "yes" + +"font-style" - "normal" - "yes" + +"font-variant" - "normal" - "yes" + +"font-weight" - "normal" - "yes" + +"glyph-orientation-horizontal" - "0deg" - "yes" + +"glyph-orientation-vertical" - "auto" - "yes" + +"image-rendering" - "auto" - "yes" + +"kerning" - "auto" - "yes" + +"letter-spacing" - "normal" - "yes" + +"lighting-color" - "white" - "no" + +"line-height" - "NO DEFAULT" - "no" + +"marker" - "none" - "yes" + +"marker-end" - "none" - "yes" + +"marker-mid" - "none" - "yes" + +"marker-start" - "none" - "yes" + +"mask" - "none" - "no" + +"opacity" - "1" - "no" + +"overflow" - "hidden" - "no" + +"pointer-events" - "visiblePainted" - "yes" + +"shape-rendering" - "auto" - "yes" + +"stop-color" - "black" - "no" + +"stop-opacity" - "1" - "no" + +"stroke" - "none" - "yes" + +"stroke-dasharray" - "none" - "yes" + +"stroke-dashoffset" - "0" - "yes" + +"stroke-linecap" - "butt" - "yes" + +"stroke-linejoin" - "miter" - "yes" + +"stroke-miterlimit" - "4" - "yes" + +"stroke-opacity" - "1" - "yes" + +"stroke-width" - "1" - "yes" + +"text-anchor" - "start" - "yes" + +"text-decoration" - "NO_DEFAULT" - "no" + +"text-rendering" - "auto" - "yes" + +"unicode-bidi" - "normal" - "no" + +"visibility" - "visible" - "yes" + +"word-spacing" - "normal" - "yes" + +"writing-mode" - "lr-tb" - "yes" + diff --git a/share/attributes/cssprops b/share/attributes/cssprops new file mode 100644 index 000000000..7eeb70fe3 --- /dev/null +++ b/share/attributes/cssprops @@ -0,0 +1,124 @@ +"alignment-baseline" - "tspan","tref","altGlyph","textPath" + +"baseline-shift" - "tspan","tref","altGlyph","textPath" + +"clip" - "svg","symbol","foreignObject","pattern","marker" + +"clip-path" - "a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use","circle","ellipse","image","line","path","polygon","polyline","rect","text","use" + +"clip-rule" - "circle","ellipse","image","line","path","polygon","polyline","rect","text","use","clip-path","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"color" - "altGlyph","textPath","text","tref","tspan","path","rect","circle","ellipse","line","polyline","polygon","stop","feFlood","feDiffuseLighting","feSpecularLighting","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"color-interpolation" - "a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use","circle","ellipse","image","line","path","polygon","polyline","rect","text","use","animateColor" + +"color-interpolation-filters" - "feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feFlood","feGaussianBlur","feImage","feMerge","feMorphology","feOffset","feSpecularLighting","feTile","feTurbulence","filter","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"color-profile" - "image","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"color-rendering" - "a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use","circle","ellipse","image","line","path","polygon","polyline","rect","text","use","animateColor" + +"cursor" - "a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use","circle","ellipse","image","line","path","polygon","polyline","rect","text","use" + +"direction" - "altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"display" - "svg","g","switch","a","foreignObject","text","tspan","tref","altGlyph","textPath","circle","ellipse","image","line","path","polygon","polyline","rect","text","use" + +"dominant-baseline" - "altGlyph","textPath","text","tref","tspan" + +"enable-background" - "a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"fill" - "path","rect","circle","ellipse","line","polyline","polygon","altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"fill-opacity" - "path","rect","circle","ellipse","line","polyline","polygon","altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"fill-rule" - "path","rect","circle","ellipse","line","polyline","polygon","altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"filter" - "a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use","circle","ellipse","image","line","path","polygon","polyline","rect","text","use" + +"flood-color" - "feFlood" + +"flood-opacity" - "feFlood" + +"font" - "altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"font-family" - "altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"font-size" - "altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"font-size-adjust" - "altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"font-stretch" - "altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"font-style" - "altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"font-variant" - "altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"font-weight" - "altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"glyph-orientation-horizontal" - "altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"glyph-orientation-vertical" - "altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"image-rendering" - "pattern","image","feImage","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"kerning" - "altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"letter-spacing" - "altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"lighting-color" - "feDiffuseLighting","feSpecularLighting" + +"line-height" - "text" + +"marker" - "path","line","polyline","polygon","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"marker-end" - "path","line","polyline","polygon","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"marker-mid" - "path","line","polyline","polygon","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"marker-start" - "path","line","polyline","polygon","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"mask" - "a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use","circle","ellipse","image","line","path","polygon","polyline","rect","text","use" + +"opacity" - "a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use","circle","ellipse","image","line","path","polygon","polyline","rect","text","use" + +"overflow" - "svg","symbol","foreignObject","pattern","marker" + +"pointer-events" - "circle","ellipse","image","line","path","polygon","polyline","rect","text","use","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"shape-rendering" - "path","rect","circle","ellipse","line","polyline","polygon","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"stop-color" - "stop" + +"stop-opacity" - "stop" + +"stroke" - "path","rect","circle","ellipse","line","polyline","polygon","altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"stroke-dasharray" - "path","rect","circle","ellipse","line","polyline","polygon","altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"stroke-dashoffset" - "path","rect","circle","ellipse","line","polyline","polygon","altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"stroke-linecap" - "path","rect","circle","ellipse","line","polyline","polygon","altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"stroke-linejoin" - "path","rect","circle","ellipse","line","polyline","polygon","altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"stroke-miterlimit" - "path","rect","circle","ellipse","line","polyline","polygon","altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"stroke-opacity" - "path","rect","circle","ellipse","line","polyline","polygon","altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"stroke-width" - "path","rect","circle","ellipse","line","polyline","polygon","altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"text-anchor" - "altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"text-decoration" - "altGlyph","textPath","text","tref","tspan" + +"text-rendering" - "text","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"unicode-bidi" - "altGlyph","textPath","text","tref","tspan" + +"visibility" - "text","tspan","tref","altGlyph","textPath","a","circle","ellipse","image","line","path","polygon","polyline","rect","text","use","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"word-spacing" - "altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + +"writing-mode" - "text","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","use" + diff --git a/share/attributes/genMapDataCSS.pl b/share/attributes/genMapDataCSS.pl new file mode 100755 index 000000000..498ce8bbe --- /dev/null +++ b/share/attributes/genMapDataCSS.pl @@ -0,0 +1,201 @@ +#!/usr/bin/env perl + +# Purpose: To extract the css_defaults and cssprops data from the +# SVG 1.1 2nd Ed specification file propidx.html. The file can be found at: +# +# http://www.w3.org/TR/SVG/propidx.html +# +# A number of adjustments must be made after parsing the HTML file. + +# Author: Tavmjong Bah +# Rewrite of script by Abhishek + +use strict; +use warnings; +use HTML::TokeParser; + +# Groups of elements defined in spec. +# Note "use" is not a container element but it acts like one! +my @container_elements = ("a", "defs", "glyph", "g", "marker", "mask", "missing-glyph", "pattern", "svg", "switch", "symbol", "use"); +my @graphics_elements = ("circle", "ellipse", "image", "line", "path", "polygon", "polyline", "rect", "text", "use"); +my @filter_primitives = ("feBlend", "feColorMatrix", "feComponentTransfer", "feComposite", "feConvolveMatrix", + "feDiffuseLighting", "feDisplacementMap", "feFlood", "feGaussianBlur", "feImage", + "feMerge", "feMorphology", "feOffset", "feSpecularLighting", "feTile", "feTurbulence" ); +my @text_content_elements = ("altGlyph", "textPath", "text", "tref", "tspan"); +my @shapes = ("path", "rect", "circle", "ellipse", "line", "polyline", "polygon"); +my @viewport = ("svg", "symbol", "foreignObject" ); + +my $p= HTML::TokeParser->new('propidx.html') or die "Can't open file: $!"; + +my %properties; +my $property; + +# Loop over tokens +while( my $t = $p->get_token ) { + + # Look for <tr> (start token with value 'tr'). + if( $t->[0] eq 'S' and lc $t->[1] eq 'tr') { + + print "---------\n"; + + my $column = 0; + while( $t = $p->get_token ) { + + # Keep track of column + if( $t->[0] eq 'S' and lc $t->[1] eq 'td') { + $column++; + $t = $p->get_token; # Skip to next token + } + + if( $column == 1 and $t->[0] eq 'S' and lc $t->[1] =~ 'span') { + # First column is always property name, defined inside <span>. + # print " span ${$t->[2]}{'class'}\n"; + # if( ${$t->[2]}{'class'} =~ 'prop-name' ) { + # print " $t->[4]\n"; + # } $property =~ s/\‘//; + + $t = $p->get_token; + $property = $t->[1]; + $property =~ s/‘//; # Opening single quote + $property =~ s/’//; # Closing single quote + print "Property: $property\n"; + } + + if( $column == 3 and $t->[0] eq 'T') { + # Third column is default value (simple text). + my $default = $t->[1]; + $properties{ $property }->{default} = $default; + print " Default: $default\n"; + } + + if( $column == 4 and $t->[0] eq 'S' ) { + # Fourth column is "Applies to" + if( lc $t->[1] eq 'span' && ${$t->[2]}{'class'} =~ 'element-name' ) { + $t = $p->get_token; + my $element = $t->[1]; + $element =~ s/‘//; # Opening single quote + $element =~ s/’//; # Closing single quote + print " Elements: $element\n"; + push @{$properties{ $property }->{elements}}, $element; + } elsif ( lc $t->[1] eq 'a' ) { + my $text = $p->get_trimmed_text; + if( $text ne "" ) { + print " Text ->$text<-\n"; + if( $text =~ "container" ) { + print " Adding container elements\n"; + push @{$properties{ $property }->{elements}}, @container_elements; + $properties{ $property }->{addedContainers} = 1; + } + if( $text =~ "text" ) { + print " Adding text content elements\n"; + push @{$properties{ $property }->{elements}}, @text_content_elements; + } + if( $text =~ "graphics" ) { + print " Adding graphics elements\n"; + push @{$properties{ $property }->{elements}}, @graphics_elements; + } + if( $text =~ "primitives" ) { + print " Adding filter primitive elements\n"; + push @{$properties{ $property }->{elements}}, @filter_primitives; + } + if( $text =~ "shape" ) { + print " Adding shape elements\n"; + push @{$properties{ $property }->{elements}}, @shapes; + } + if( $text =~ "viewport" ) { + print " Adding viewport elements\n"; + push @{$properties{ $property }->{elements}}, @viewport; + } + } + } else { + print " Not Elements: $t->[1]\n"; + } + } + + if( $column == 5 and $t->[0] eq 'T') { + # Fifth column is inherit value (simple text). + my $inherit = $t->[1]; + $properties{ $property }->{inherit} = $inherit; + print " Inherit: $inherit\n"; + } + + if( $t->[0] eq 'E' and lc $t->[1] eq 'tr') { + last; + } + + } + } + +} + +# Adjustments +$properties{ "alignment-baseline" }->{default} = "auto"; +$properties{ "color" }->{default} = "NO_DEFAULT"; # Depends on user agent. +$properties{ "font" }->{default} = "NO_DEFAULT"; # See individual font properties. +$properties{ "font-family" }->{default} = "NO_DEFAULT"; +$properties{ "marker" }->{default} = "none"; # Same as marker-start, etc. +$properties{ "overflow" }->{default} = "hidden"; # On all but outermost <svg>, user agent style sheet sets this to hidden. + +# This is the safest thing to do.... +$properties{ "text-decoration" }->{default} = "NO_DEFAULT"; +$properties{ "text-decoration" }->{inherit} = "no"; + +# +push @{$properties{ "color" }->{elements}}, @text_content_elements; +push @{$properties{ "color" }->{elements}}, @shapes; +push @{$properties{ "color" }->{elements}}, "stop", "feFlood", "feDiffuseLighting", "feSpecularLighting"; + +push @{$properties{ "color-interpolation-filters" }->{elements}}, "filter"; + +@{$properties{ "clip-rule" }->{elements}} = @graphics_elements; +push @{$properties{ "clip-rule" }->{elements}}, "clip-path"; # Can inherit + +push @{$properties{ "display" }->{elements}}, @graphics_elements; + +push @{$properties{ "image-rendering" }->{elements}}, "pattern", "image", "feImage"; + +push @{$properties{ "visibility" }->{elements}}, @graphics_elements; + + +$properties{ "marker-end" }->{default} = $properties{ "marker-start" }->{default}; +$properties{ "marker-mid" }->{default} = $properties{ "marker-start" }->{default}; +$properties{ "marker-end" }->{inherit} = $properties{ "marker-start" }->{inherit}; +$properties{ "marker-mid" }->{inherit} = $properties{ "marker-start" }->{inherit}; +@{$properties{ "marker-end" }->{elements}} = @{$properties{ "marker-start" }->{elements}}; +@{$properties{ "marker-mid" }->{elements}} = @{$properties{ "marker-start" }->{elements}}; + + +# Inkscape uses CSS property 'line-height' even though this is not part of SVG spec. +push @{$properties{ "line-height" }->{elements}}, "text"; +$properties{ "line-height" }->{default} = "NO DEFAULT"; +$properties{ "line-height" }->{inherit} = "no"; + +# Output + +open( DEFAULTS, ">css_defaults_new" ) or die "Couldn't open output"; +open( ELEMENTS, ">cssprops_new" ) or die "Couldn't open output"; + +for $property ( sort keys %properties ) { + print "$property:\t$properties{ $property }->{default}\t$properties{ $property }->{inherit}\n"; + # Must add container elements to all properties that are inherited. + if( $properties{ $property }->{inherit} =~ "yes" ) { + # But not if they have already been added + if( !defined $properties{ $property }->{addedContainers} ) { + push @{$properties{ $property }->{elements}}, @container_elements; + } + } + print " @{ $properties{ $property }->{elements}}\n"; + + print DEFAULTS "\"$property\" - \"$properties{ $property }->{default}\" - \"$properties{ $property }->{inherit}\"\n\n"; + print ELEMENTS "\"$property\" - "; + my $first = 0; + foreach (@{$properties{ $property }->{elements}}) { + if( $first != 0 ) { + print ELEMENTS ","; + } + $first = 1; + print ELEMENTS "\"$_\""; + } + print ELEMENTS "\n\n"; +} + diff --git a/share/attributes/genMapDataSVG.pl b/share/attributes/genMapDataSVG.pl new file mode 100755 index 000000000..89908033b --- /dev/null +++ b/share/attributes/genMapDataSVG.pl @@ -0,0 +1,104 @@ +#!/usr/bin/env perl + +# Purpose: To extract the svgprops data from the +# SVG 1.1 2nd Ed specification file attindex.html. The file can be found at: +# +# http://www.w3.org/TR/SVG/attindex.html +# +# Note cssprops must be generated first to pickup "Presentation Attributes". + +# Author: Tavmjong Bah +# Rewrite of script by Abhishek + +use strict; +use warnings; +use HTML::TokeParser; + +my $p= HTML::TokeParser->new('attindex.html') or die "Can't open file: $!"; + +my %attributes; +my $attribute; + +# Loop over tokens +while( my $t = $p->get_token ) { + + # Look for <tr> (start token with value 'tr'). + if( $t->[0] eq 'S' and lc $t->[1] eq 'tr') { + + print "---------\n"; + + my $column = 0; + while( $t = $p->get_token ) { + + # Keep track of column + if( $t->[0] eq 'S' and lc $t->[1] eq 'td') { + $column++; + $t = $p->get_token; # Skip to next token + } + + if( $column == 1 and $t->[0] eq 'S' and lc $t->[1] =~ 'span') { + # First column is always attribute name, defined inside <span>. + $t = $p->get_token; + $attribute = $t->[1]; + $attribute =~ s/‘//; # Opening single quote + $attribute =~ s/’//; # Closing single quote + print "Attribute: $attribute\n"; + } + + if( $column == 2 and $t->[0] eq 'S') { + # Second column is list of elements, each inside its own span. + if( lc $t->[1] eq 'span' && ${$t->[2]}{'class'} =~ 'element-name' ) { + $t = $p->get_token; + my $element = $t->[1]; + $element =~ s/‘//; # Opening single quote + $element =~ s/’//; # Closing single quote + print " Elements: $element\n"; + push @{$attributes{ $attribute }->{elements}}, $element; + } else { +# print " Not Elements: $t->[1]\n"; + } + } + + if( $t->[0] eq 'E' and lc $t->[1] eq 'tr') { + last; + } + + } + } + + # Stop if we get to presentation attributes + if( $t->[0] eq 'S' and lc $t->[1] eq 'h2') { + $t = $p->get_token; + if( $t->[1] =~ /Presentation/ ) { + print "Found: $t->[1], quiting.\n"; + last; + } + } +} + +# Output + +open( ELEMENTS, ">svgprops_new" ) or die "Couldn't open output"; + +for $attribute ( sort keys %attributes ) { + + print ELEMENTS "\"$attribute\" - "; + my $first = 0; + foreach (@{$attributes{ $attribute }->{elements}}) { + if( $first != 0 ) { + print ELEMENTS ","; + } + $first = 1; + print ELEMENTS "\"$_\""; + } + print ELEMENTS "\n\n"; +} + +# Copy cssprops verbatim. For every CSS property there is a +# corresponding "Presentation Attribute". + +open( PROPERTIES, "cssprops" ) or die "Couldn't open $!"; + +while( <PROPERTIES> ) { + print ELEMENTS; +} diff --git a/share/attributes/svgprops b/share/attributes/svgprops new file mode 100644 index 000000000..53b3fd8b0 --- /dev/null +++ b/share/attributes/svgprops @@ -0,0 +1,552 @@ +"accent-height" - "font-face" + +"accumulate" - "animate","animateColor","animateMotion","animateTransform" + +"additive" - "animate","animateColor","animateMotion","animateTransform" + +"alphabetic" - "font-face" + +"amplitude" - "feFuncA","feFuncB","feFuncG","feFuncR" + +"arabic-form" - "glyph" + +"ascent" - "font-face" + +"attributeName" - "animate","animateColor","animateTransform","set" + +"attributeType" - "animate","animateColor","animateTransform","set" + +"azimuth" - "feDistantLight" + +"baseFrequency" - "feTurbulence" + +"baseProfile" - "svg" + +"bbox" - "font-face" + +"begin" - "animate","animateColor","animateMotion","animateTransform","set" + +"bias" - "feConvolveMatrix" + +"by" - "animate","animateColor","animateMotion","animateTransform" + +"calcMode" - "animate","animateColor","animateMotion","animateTransform" + +"cap-height" - "font-face" + +"class" - "a","altGlyph","circle","clipPath","defs","desc","ellipse","feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feFlood","feGaussianBlur","feImage","feMerge","feMorphology","feOffset","feSpecularLighting","feTile","feTurbulence","filter","font","foreignObject","g","glyph","glyphRef","image","line","linearGradient","marker","mask","missing-glyph","path","pattern","polygon","polyline","radialGradient","rect","stop","svg","switch","symbol","text","textPath","title","tref","tspan","use" + +"clipPathUnits" - "clipPath" + +"contentScriptType" - "svg" + +"contentStyleType" - "svg" + +"cx" - "circle","ellipse","radialGradient" + +"cy" - "circle","ellipse","radialGradient" + +"d" - "path","glyph","missing-glyph" + +"descent" - "font-face" + +"diffuseConstant" - "feDiffuseLighting" + +"divisor" - "feConvolveMatrix" + +"dur" - "animate","animateColor","animateMotion","animateTransform","set" + +"dx" - "altGlyph","feOffset","glyphRef","text","tref","tspan" + +"dy" - "altGlyph","feOffset","glyphRef","text","tref","tspan" + +"edgeMode" - "feConvolveMatrix" + +"elevation" - "feDistantLight" + +"end" - "animate","animateColor","animateMotion","animateTransform","set" + +"exponent" - "feFuncA","feFuncB","feFuncG","feFuncR" + +"externalResourcesRequired" - "a","altGlyph","animate","animateColor","animateMotion","animateTransform","circle","clipPath","cursor","defs","ellipse","feImage","filter","font","foreignObject","g","image","line","linearGradient","marker","mask","mpath","path","pattern","polygon","polyline","radialGradient","rect","script","set","svg","switch","symbol","text","textPath","tref","tspan","use","view" + +"fill" - "animate","animateColor","animateMotion","animateTransform","set" + +"filterRes" - "filter" + +"filterUnits" - "filter" + +"font-family" - "font-face" + +"font-size" - "font-face" + +"font-stretch" - "font-face" + +"font-style" - "font-face" + +"font-variant" - "font-face" + +"font-weight" - "font-face" + +"format" - "altGlyph","glyphRef" + +"from" - "animate","animateColor","animateMotion","animateTransform" + +"fx" - "radialGradient" + +"fy" - "radialGradient" + +"g1" - "hkern","vkern" + +"g2" - "hkern","vkern" + +"glyph-name" - "glyph" + +"glyphRef" - "altGlyph","glyphRef" + +"gradientTransform" - "linearGradient","radialGradient" + +"gradientUnits" - "linearGradient","radialGradient" + +"hanging" - "font-face" + +"height" - "filter","foreignObject","image","pattern","rect","svg","use","feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feFlood","feGaussianBlur","feImage","feMerge","feMorphology","feOffset","feSpecularLighting","feTile","feTurbulence","mask" + +"horiz-adv-x" - "font","glyph","missing-glyph" + +"horiz-origin-x" - "font" + +"horiz-origin-y" - "font" + +"id" - "a","altGlyph","altGlyphDef","altGlyphItem","animate","animateColor","animateMotion","animateTransform","circle","clipPath","color-profile","cursor","defs","desc","ellipse","feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feDistantLight","feFlood","feFuncA","feFuncB","feFuncG","feFuncR","feGaussianBlur","feImage","feMerge","feMergeNode","feMorphology","feOffset","fePointLight","feSpecularLighting","feSpotLight","feTile","feTurbulence","filter","font","font-face","font-face-format","font-face-name","font-face-src","font-face-uri","foreignObject","g","glyph","glyphRef","hkern","image","line","linearGradient","marker","mask","metadata","missing-glyph","mpath","path","pattern","polygon","polyline","radialGradient","rect","script","set","stop","style","svg","switch","symbol","text","textPath","title","tref","tspan","use","view","vkern" + +"ideographic" - "font-face" + +"in" - "feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feGaussianBlur","feMorphology","feOffset","feSpecularLighting","feTile" + +"in2" - "feBlend","feComposite","feDisplacementMap" + +"intercept" - "feFuncA","feFuncB","feFuncG","feFuncR" + +"k" - "hkern","vkern" + +"k1" - "feComposite" + +"k2" - "feComposite" + +"k3" - "feComposite" + +"k4" - "feComposite" + +"kernelMatrix" - "feConvolveMatrix" + +"kernelUnitLength" - "feConvolveMatrix","feDiffuseLighting","feSpecularLighting" + +"keyPoints" - "animateMotion" + +"keySplines" - "animate","animateColor","animateMotion","animateTransform" + +"keyTimes" - "animate","animateColor","animateMotion","animateTransform" + +"lang" - "glyph" + +"lengthAdjust" - "text","textPath","tref","tspan" + +"limitingConeAngle" - "feSpotLight" + +"local" - "color-profile" + +"markerHeight" - "marker" + +"markerUnits" - "marker" + +"markerWidth" - "marker" + +"maskContentUnits" - "mask" + +"maskUnits" - "mask" + +"mathematical" - "font-face" + +"max" - "animate","animateColor","animateMotion","animateTransform","set" + +"media" - "style" + +"method" - "textPath" + +"min" - "animate","animateColor","animateMotion","animateTransform","set" + +"mode" - "feBlend" + +"name" - "color-profile","font-face-name" + +"numOctaves" - "feTurbulence" + +"offset" - "stop","feFuncA","feFuncB","feFuncG","feFuncR" + +"onabort" - "svg" + +"onactivate" - "a","altGlyph","circle","defs","ellipse","foreignObject","g","image","line","path","polygon","polyline","rect","svg","switch","symbol","text","textPath","tref","tspan","use" + +"onbegin" - "animate","animateColor","animateMotion","animateTransform","set" + +"onclick" - "a","altGlyph","circle","defs","ellipse","foreignObject","g","image","line","path","polygon","polyline","rect","svg","switch","symbol","text","textPath","tref","tspan","use" + +"onend" - "animate","animateColor","animateMotion","animateTransform","set" + +"onerror" - "svg" + +"onfocusin" - "a","altGlyph","circle","defs","ellipse","foreignObject","g","image","line","path","polygon","polyline","rect","svg","switch","symbol","text","textPath","tref","tspan","use" + +"onfocusout" - "a","altGlyph","circle","defs","ellipse","foreignObject","g","image","line","path","polygon","polyline","rect","svg","switch","symbol","text","textPath","tref","tspan","use" + +"onload" - "a","altGlyph","circle","defs","ellipse","foreignObject","g","image","line","path","polygon","polyline","rect","svg","switch","symbol","text","textPath","tref","tspan","use","animate","animateColor","animateMotion","animateTransform","set" + +"onmousedown" - "a","altGlyph","circle","defs","ellipse","foreignObject","g","image","line","path","polygon","polyline","rect","svg","switch","symbol","text","textPath","tref","tspan","use" + +"onmousemove" - "a","altGlyph","circle","defs","ellipse","foreignObject","g","image","line","path","polygon","polyline","rect","svg","switch","symbol","text","textPath","tref","tspan","use" + +"onmouseout" - "a","altGlyph","circle","defs","ellipse","foreignObject","g","image","line","path","polygon","polyline","rect","svg","switch","symbol","text","textPath","tref","tspan","use" + +"onmouseover" - "a","altGlyph","circle","defs","ellipse","foreignObject","g","image","line","path","polygon","polyline","rect","svg","switch","symbol","text","textPath","tref","tspan","use" + +"onmouseup" - "a","altGlyph","circle","defs","ellipse","foreignObject","g","image","line","path","polygon","polyline","rect","svg","switch","symbol","text","textPath","tref","tspan","use" + +"onrepeat" - "animate","animateColor","animateMotion","animateTransform","set" + +"onresize" - "svg" + +"onscroll" - "svg" + +"onunload" - "svg" + +"onzoom" - "svg" + +"operator" - "feComposite","feMorphology" + +"order" - "feConvolveMatrix" + +"orient" - "marker" + +"orientation" - "glyph" + +"origin" - "animateMotion" + +"overline-position" - "font-face" + +"overline-thickness" - "font-face" + +"panose-1" - "font-face" + +"path" - "animateMotion" + +"pathLength" - "path" + +"patternContentUnits" - "pattern" + +"patternTransform" - "pattern" + +"patternUnits" - "pattern" + +"points" - "polygon","polyline" + +"pointsAtX" - "feSpotLight" + +"pointsAtY" - "feSpotLight" + +"pointsAtZ" - "feSpotLight" + +"preserveAlpha" - "feConvolveMatrix" + +"preserveAspectRatio" - "feImage","image","marker","pattern","svg","symbol","view" + +"primitiveUnits" - "filter" + +"r" - "circle","radialGradient" + +"radius" - "feMorphology" + +"refX" - "marker" + +"refY" - "marker" + +"rendering-intent" - "color-profile" + +"repeatCount" - "animate","animateColor","animateMotion","animateTransform","set" + +"repeatDur" - "animate","animateColor","animateMotion","animateTransform","set" + +"requiredExtensions" - "a","altGlyph","animate","animateColor","animateMotion","animateTransform","circle","clipPath","cursor","defs","ellipse","foreignObject","g","image","line","mask","path","pattern","polygon","polyline","rect","set","svg","switch","text","textPath","tref","tspan","use" + +"requiredFeatures" - "a","altGlyph","animate","animateColor","animateMotion","animateTransform","circle","clipPath","cursor","defs","ellipse","foreignObject","g","image","line","mask","path","pattern","polygon","polyline","rect","set","svg","switch","text","textPath","tref","tspan","use" + +"restart" - "animate","animateColor","animateMotion","animateTransform","set" + +"result" - "feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feFlood","feGaussianBlur","feImage","feMerge","feMorphology","feOffset","feSpecularLighting","feTile","feTurbulence" + +"rotate" - "altGlyph","animateMotion","text","tref","tspan" + +"rx" - "ellipse","rect" + +"ry" - "ellipse","rect" + +"scale" - "feDisplacementMap" + +"seed" - "feTurbulence" + +"slope" - "font-face","feFuncA","feFuncB","feFuncG","feFuncR" + +"spacing" - "textPath" + +"specularConstant" - "feSpecularLighting" + +"specularExponent" - "feSpecularLighting","feSpotLight" + +"spreadMethod" - "linearGradient","radialGradient" + +"startOffset" - "textPath" + +"stdDeviation" - "feGaussianBlur" + +"stemh" - "font-face" + +"stemv" - "font-face" + +"stitchTiles" - "feTurbulence" + +"strikethrough-position" - "font-face" + +"strikethrough-thickness" - "font-face" + +"string" - "font-face-format" + +"style" - "a","altGlyph","circle","clipPath","defs","desc","ellipse","feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feFlood","feGaussianBlur","feImage","feMerge","feMorphology","feOffset","feSpecularLighting","feTile","feTurbulence","filter","font","foreignObject","g","glyph","glyphRef","image","line","linearGradient","marker","mask","missing-glyph","path","pattern","polygon","polyline","radialGradient","rect","stop","svg","switch","symbol","text","textPath","title","tref","tspan","use" + +"surfaceScale" - "feDiffuseLighting","feSpecularLighting" + +"systemLanguage" - "a","altGlyph","animate","animateColor","animateMotion","animateTransform","circle","clipPath","cursor","defs","ellipse","foreignObject","g","image","line","mask","path","pattern","polygon","polyline","rect","set","svg","switch","text","textPath","tref","tspan","use" + +"tableValues" - "feFuncA","feFuncB","feFuncG","feFuncR" + +"target" - "a" + +"targetX" - "feConvolveMatrix" + +"targetY" - "feConvolveMatrix" + +"textLength" - "text","textPath","tref","tspan" + +"title" - "style" + +"to" - "set","animate","animateColor","animateMotion","animateTransform" + +"transform" - "a","circle","clipPath","defs","ellipse","foreignObject","g","image","line","path","polygon","polyline","rect","switch","text","use" + +"type" - "animateTransform","feColorMatrix","feTurbulence","script","style","feFuncA","feFuncB","feFuncG","feFuncR" + +"u1" - "hkern","vkern" + +"u2" - "hkern","vkern" + +"underline-position" - "font-face" + +"underline-thickness" - "font-face" + +"unicode" - "glyph" + +"unicode-range" - "font-face" + +"units-per-em" - "font-face" + +"v-alphabetic" - "font-face" + +"v-hanging" - "font-face" + +"v-ideographic" - "font-face" + +"v-mathematical" - "font-face" + +"values" - "feColorMatrix","animate","animateColor","animateMotion","animateTransform" + +"version" - "svg" + +"vert-adv-y" - "font","glyph","missing-glyph" + +"vert-origin-x" - "font","glyph","missing-glyph" + +"vert-origin-y" - "font","glyph","missing-glyph" + +"viewBox" - "marker","pattern","svg","symbol","view" + +"viewTarget" - "view" + +"width" - "filter","foreignObject","image","pattern","rect","svg","use","feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feFlood","feGaussianBlur","feImage","feMerge","feMorphology","feOffset","feSpecularLighting","feTile","feTurbulence","mask" + +"widths" - "font-face" + +"x" - "altGlyph","cursor","fePointLight","feSpotLight","filter","foreignObject","glyphRef","image","pattern","rect","svg","text","use","feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feFlood","feGaussianBlur","feImage","feMerge","feMorphology","feOffset","feSpecularLighting","feTile","feTurbulence","mask","tref","tspan" + +"x-height" - "font-face" + +"x1" - "line","linearGradient" + +"x2" - "line","linearGradient" + +"xChannelSelector" - "feDisplacementMap" + +"xlink:actuate" - "a","altGlyph","animate","animateColor","animateMotion","animateTransform","color-profile","cursor","feImage","filter","font-face-uri","glyphRef","image","mpath","pattern","script","set","use" + +"xlink:arcrole" - "a","altGlyph","animate","animateColor","animateMotion","animateTransform","color-profile","cursor","feImage","filter","font-face-uri","glyphRef","image","linearGradient","mpath","pattern","radialGradient","script","set","textPath","tref","use" + +"xlink:href" - "a","altGlyph","color-profile","cursor","feImage","filter","font-face-uri","glyphRef","image","linearGradient","mpath","pattern","radialGradient","script","textPath","use","animate","animateColor","animateMotion","animateTransform","set","tref" + +"xlink:role" - "a","altGlyph","animate","animateColor","animateMotion","animateTransform","color-profile","cursor","feImage","filter","font-face-uri","glyphRef","image","linearGradient","mpath","pattern","radialGradient","script","set","textPath","tref","use" + +"xlink:show" - "a","altGlyph","animate","animateColor","animateMotion","animateTransform","color-profile","cursor","feImage","filter","font-face-uri","glyphRef","image","mpath","pattern","script","set","use" + +"xlink:title" - "a","altGlyph","animate","animateColor","animateMotion","animateTransform","color-profile","cursor","feImage","filter","font-face-uri","glyphRef","image","linearGradient","mpath","pattern","radialGradient","script","set","textPath","tref","use" + +"xlink:type" - "a","altGlyph","animate","animateColor","animateMotion","animateTransform","color-profile","cursor","feImage","filter","font-face-uri","glyphRef","image","linearGradient","mpath","pattern","radialGradient","script","set","textPath","tref","use" + +"xml:base" - "a","altGlyph","altGlyphDef","altGlyphItem","animate","animateColor","animateMotion","animateTransform","circle","clipPath","color-profile","cursor","defs","desc","ellipse","feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feDistantLight","feFlood","feFuncA","feFuncB","feFuncG","feFuncR","feGaussianBlur","feImage","feMerge","feMergeNode","feMorphology","feOffset","fePointLight","feSpecularLighting","feSpotLight","feTile","feTurbulence","filter","font","font-face","font-face-format","font-face-name","font-face-src","font-face-uri","foreignObject","g","glyph","glyphRef","hkern","image","line","linearGradient","marker","mask","metadata","missing-glyph","mpath","path","pattern","polygon","polyline","radialGradient","rect","script","set","stop","style","svg","switch","symbol","text","textPath","title","tref","tspan","use","view","vkern" + +"xml:lang" - "a","altGlyph","altGlyphDef","altGlyphItem","animate","animateColor","animateMotion","animateTransform","circle","clipPath","color-profile","cursor","defs","desc","ellipse","feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feDistantLight","feFlood","feFuncA","feFuncB","feFuncG","feFuncR","feGaussianBlur","feImage","feMerge","feMergeNode","feMorphology","feOffset","fePointLight","feSpecularLighting","feSpotLight","feTile","feTurbulence","filter","font","font-face","font-face-format","font-face-name","font-face-src","font-face-uri","foreignObject","g","glyph","glyphRef","hkern","image","line","linearGradient","marker","mask","metadata","missing-glyph","mpath","path","pattern","polygon","polyline","radialGradient","rect","script","set","stop","style","svg","switch","symbol","text","textPath","title","tref","tspan","use","view","vkern" + +"xml:space" - "a","altGlyph","altGlyphDef","altGlyphItem","animate","animateColor","animateMotion","animateTransform","circle","clipPath","color-profile","cursor","defs","desc","ellipse","feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feDistantLight","feFlood","feFuncA","feFuncB","feFuncG","feFuncR","feGaussianBlur","feImage","feMerge","feMergeNode","feMorphology","feOffset","fePointLight","feSpecularLighting","feSpotLight","feTile","feTurbulence","filter","font","font-face","font-face-format","font-face-name","font-face-src","font-face-uri","foreignObject","g","glyph","glyphRef","hkern","image","line","linearGradient","marker","mask","metadata","missing-glyph","mpath","path","pattern","polygon","polyline","radialGradient","rect","script","set","stop","style","svg","switch","symbol","text","textPath","title","tref","tspan","use","view","vkern" + +"y" - "altGlyph","cursor","fePointLight","feSpotLight","filter","foreignObject","glyphRef","image","pattern","rect","svg","text","use","feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feFlood","feGaussianBlur","feImage","feMerge","feMorphology","feOffset","feSpecularLighting","feTile","feTurbulence","mask","tref","tspan" + +"y1" - "line","linearGradient" + +"y2" - "line","linearGradient" + +"yChannelSelector" - "feDisplacementMap" + +"z" - "fePointLight","feSpotLight" + +"zoomAndPan" - "svg","view" + +"alignment-baseline" - "tspan","tref","altGlyph","textPath" + +"baseline-shift" - "tspan","tref","altGlyph","textPath" + +"clip" - "svg","symbol","foreignObject","pattern","marker" + +"clip-path" - "a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","circle","ellipse","image","line","path","polygon","polyline","rect","text","use" + +"clip-rule" - "circle","ellipse","image","line","path","polygon","polyline","rect","text","use","clip-path","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"color" - "altGlyph","textPath","text","tref","tspan","path","rect","circle","ellipse","line","polyline","polygon","stop","feFlood","feDiffuseLighting","feSpecularLighting","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"color-interpolation" - "a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","circle","ellipse","image","line","path","polygon","polyline","rect","text","use","animateColor" + +"color-interpolation-filters" - "feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feFlood","feGaussianBlur","feImage","feMerge","feMorphology","feOffset","feSpecularLighting","feTile","feTurbulence","filter","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"color-profile" - "image","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"color-rendering" - "a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","circle","ellipse","image","line","path","polygon","polyline","rect","text","use","animateColor" + +"cursor" - "a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","circle","ellipse","image","line","path","polygon","polyline","rect","text","use" + +"direction" - "altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"display" - "svg","g","switch","a","foreignObject","text","tspan","tref","altGlyph","textPath","circle","ellipse","image","line","path","polygon","polyline","rect","text","use" + +"dominant-baseline" - "altGlyph","textPath","text","tref","tspan" + +"enable-background" - "a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"fill" - "path","rect","circle","ellipse","line","polyline","polygon","altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"fill-opacity" - "path","rect","circle","ellipse","line","polyline","polygon","altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"fill-rule" - "path","rect","circle","ellipse","line","polyline","polygon","altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"filter" - "a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","circle","ellipse","image","line","path","polygon","polyline","rect","text","use" + +"flood-color" - "feFlood" + +"flood-opacity" - "feFlood" + +"font" - "altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"font-family" - "altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"font-size" - "altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"font-size-adjust" - "altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"font-stretch" - "altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"font-style" - "altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"font-variant" - "altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"font-weight" - "altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"glyph-orientation-horizontal" - "altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"glyph-orientation-vertical" - "altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"image-rendering" - "pattern","image","feImage","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"kerning" - "altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"letter-spacing" - "altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"lighting-color" - "feDiffuseLighting","feSpecularLighting" + +"line-height" - "text" + +"marker" - "path","line","polyline","polygon","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"marker-end" - "path","line","polyline","polygon","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"marker-mid" - "path","line","polyline","polygon","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"marker-start" - "path","line","polyline","polygon","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"mask" - "a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","circle","ellipse","image","line","path","polygon","polyline","rect","text","use" + +"opacity" - "a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol","circle","ellipse","image","line","path","polygon","polyline","rect","text","use" + +"overflow" - "svg","symbol","foreignObject","pattern","marker" + +"pointer-events" - "circle","ellipse","image","line","path","polygon","polyline","rect","text","use","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"shape-rendering" - "path","rect","circle","ellipse","line","polyline","polygon","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"stop-color" - "stop" + +"stop-opacity" - "stop" + +"stroke" - "path","rect","circle","ellipse","line","polyline","polygon","altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"stroke-dasharray" - "path","rect","circle","ellipse","line","polyline","polygon","altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"stroke-dashoffset" - "path","rect","circle","ellipse","line","polyline","polygon","altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"stroke-linecap" - "path","rect","circle","ellipse","line","polyline","polygon","altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"stroke-linejoin" - "path","rect","circle","ellipse","line","polyline","polygon","altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"stroke-miterlimit" - "path","rect","circle","ellipse","line","polyline","polygon","altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"stroke-opacity" - "path","rect","circle","ellipse","line","polyline","polygon","altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"stroke-width" - "path","rect","circle","ellipse","line","polyline","polygon","altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"text-anchor" - "altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"text-decoration" - "altGlyph","textPath","text","tref","tspan" + +"text-rendering" - "text","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"unicode-bidi" - "altGlyph","textPath","text","tref","tspan" + +"visibility" - "text","tspan","tref","altGlyph","textPath","a","circle","ellipse","image","line","path","polygon","polyline","rect","text","use","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"word-spacing" - "altGlyph","textPath","text","tref","tspan","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + +"writing-mode" - "text","a","defs","glyph","g","marker","mask","missing-glyph","pattern","svg","switch","symbol" + diff --git a/src/Makefile_insert b/src/Makefile_insert index 2cb689740..c649b26b1 100644 --- a/src/Makefile_insert +++ b/src/Makefile_insert @@ -6,6 +6,9 @@ ink_common_sources += \ approx-equal.h remove-last.h \ arc-context.cpp arc-context.h \ attributes.cpp attributes.h \ + attribute-rel-svg.cpp attribute-rel-svg.h \ + attribute-rel-css.cpp attribute-rel-css.h \ + attribute-rel-util.cpp attribute-rel-util.h \ axis-manip.cpp axis-manip.h \ bad-uri-exception.h \ box3d-context.cpp box3d-context.h \ diff --git a/src/attribute-rel-css.cpp b/src/attribute-rel-css.cpp new file mode 100644 index 000000000..b014aeb77 --- /dev/null +++ b/src/attribute-rel-css.cpp @@ -0,0 +1,195 @@ +/* + * attribute-rel-css.cpp + * + * Created on: Jul 25, 2011 + * Author: abhishek + */ + +/** \class SPAttributeRelCSS + * + * SPAttributeRelCSS class stores the mapping of element->style_properties + * relationship and provides a static function to access that + * mapping indirectly(only reading). + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <fstream> +#include <sstream> +#include <string> +#include <iostream> + +#include "attribute-rel-css.h" + +#include "path-prefix.h" +#include "preferences.h" + +SPAttributeRelCSS * SPAttributeRelCSS::instance = NULL; + +/* + * This function checks whether an element -> CSS property pair + * is allowed or not + */ +bool SPAttributeRelCSS::findIfValid(Glib::ustring property, Glib::ustring element) +{ + if (SPAttributeRelCSS::instance == NULL) { + SPAttributeRelCSS::instance = new SPAttributeRelCSS(); + } + + // Strip of "svg:" from the element's name + Glib::ustring temp = element; + if ( temp.find("svg:") != std::string::npos ) { + temp.erase( temp.find("svg:"), 4 ); + } + + // Don't check for properties with -, role, aria etc. to allow for more accessbility + // FixMe: Name space list should be created when file read in. + if (property[0] == '-' + || property.substr(0,4) == "role" + || property.substr(0,4) == "aria" + || property.substr(0,5) == "xmlns" + || property.substr(0,8) == "inkscape:" + || property.substr(0,9) == "sodipodi:" + || property.substr(0,4) == "rdf:" + || property.substr(0,3) == "cc:" + || (SPAttributeRelCSS::instance->propertiesOfElements[temp].find(property) + != SPAttributeRelCSS::instance->propertiesOfElements[temp].end()) ) { + return true; + } else { + //g_warning( "Invalid attribute: %s used on <%s>", property.c_str(), element.c_str() ); + return false; + } +} + +/* + * This function checks whether an CSS property -> default value + * pair is allowed or not + */ +bool SPAttributeRelCSS::findIfDefault(Glib::ustring property, Glib::ustring value) +{ + if (SPAttributeRelCSS::instance == NULL) { + SPAttributeRelCSS::instance = new SPAttributeRelCSS(); + } + + if( instance->defaultValuesOfProps[property] == value) { + return true; + } else { + return false; + } +} + +/* + * Check if property can be inherited. + */ +bool SPAttributeRelCSS::findIfInherit(Glib::ustring property) +{ + if (SPAttributeRelCSS::instance == NULL) { + SPAttributeRelCSS::instance = new SPAttributeRelCSS(); + } + + return instance->inheritProps[property]; +} + +/* + * Check if attribute is a property. + */ +bool SPAttributeRelCSS::findIfProperty(Glib::ustring property) +{ + if (SPAttributeRelCSS::instance == NULL) { + SPAttributeRelCSS::instance = new SPAttributeRelCSS(); + } + + return ( instance->defaultValuesOfProps.find( property ) + != instance->defaultValuesOfProps.end() ); +} + +SPAttributeRelCSS::SPAttributeRelCSS() +{ + // Read data from standard path + std::string filepath = INKSCAPE_ATTRRELDIR; + filepath += "/cssprops"; + + // Try and load data from filepath + if (!readDataFromFileIn(filepath, SPAttributeRelCSS::prop_element_pair)) { + // Set default preference for CSS property checking to ignore + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setInt("/options/svgoutput/incorrect_style_properties", 3); + } + + // Read data from standard path + filepath = INKSCAPE_ATTRRELDIR; + filepath += "/css_defaults"; + + // Try and load data from filepath + if (!readDataFromFileIn(filepath, SPAttributeRelCSS::prop_defValue_pair)) { + // Set default preference for CSS defaults checking to ignore + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setInt("/options/svgoutput/style_defaults", 3); + } +} + +bool SPAttributeRelCSS::readDataFromFileIn(Glib::ustring fileName, storageType type) +{ + std::fstream file; + file.open(fileName.c_str(), std::ios::in); + + if (!file.is_open()) { + // Display warning for file not open + g_warning("Could not open the data file for CSS attribute-element map construction: %s", fileName.c_str()); + file.close(); + return false; + } + + while (!file.eof()) { + std::stringstream ss; + std::string s; + + std::getline(file,s,'"'); + std::getline(file,s,'"'); + if (s.size() > 0 && s[0] != '\n') { + std::string prop = s; + getline(file,s); + ss << s; + + // Load data to structure that holds element -> set of CSS props + if (type == SPAttributeRelCSS::prop_element_pair) { + while (std::getline(ss,s,'"')) { + std::string element; + std::getline(ss,s,'"'); + element = s; + propertiesOfElements[element].insert(prop); + } + // Load data to structure that holds CSS prop -> default value + } else if (type == SPAttributeRelCSS::prop_defValue_pair) { + std::string value; + std::getline(ss,s,'"'); + std::getline(ss,s,'"'); + value = s; + defaultValuesOfProps[prop] = value; + std::getline(ss,s,'"'); + std::getline(ss,s,'"'); + gboolean inherit = false; + if ( s.find( "yes" ) != std::string::npos ) { + inherit = true; + } + inheritProps[prop] = inherit; + } + } + } + + file.close(); + return true; +} + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/attribute-rel-css.h b/src/attribute-rel-css.h new file mode 100644 index 000000000..b5077f8a0 --- /dev/null +++ b/src/attribute-rel-css.h @@ -0,0 +1,66 @@ +#ifndef __SP_ATTRIBUTE_REL_CSS_H__ +#define __SP_ATTRIBUTE_REL_CSS_H__ + +/* + * attribute-rel-css.h + * + * Created on: Jul 25, 2011 + * Author: abhishek + */ + +#include <string> +#include <map> +#include <set> +#include <glibmm/ustring.h> + +// This data structure stores the valid (element -> set of CSS properties) pair +typedef std::map<Glib::ustring, std::set<Glib::ustring> > hashList; + +/* + * Utility class that helps check whether a given element -> CSS property is + * valid or not and whether the value assumed by a CSS property has a default + * value. + */ +class SPAttributeRelCSS { +public: + static bool findIfValid(Glib::ustring property, Glib::ustring element); + static bool findIfDefault(Glib::ustring property, Glib::ustring value); + static bool findIfInherit(Glib::ustring property); + static bool findIfProperty(Glib::ustring property); + +private: + SPAttributeRelCSS(); + SPAttributeRelCSS(const SPAttributeRelCSS&); + SPAttributeRelCSS& operator= (const SPAttributeRelCSS&); + +private: + /* + * Allows checking whether data loading is to be done for element -> CSS properties + * or CSS property -> default value. + */ + enum storageType { + prop_element_pair, + prop_defValue_pair + }; + static SPAttributeRelCSS *instance; + hashList propertiesOfElements; + + // Data structure to store CSS property and default value pair + std::map<Glib::ustring, Glib::ustring> defaultValuesOfProps; + std::map<Glib::ustring, gboolean> inheritProps; + bool readDataFromFileIn(Glib::ustring fileName, storageType type); +}; + + +#endif /* __SP_ATTRIBUTE_REL_CSS_H__ */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/attribute-rel-svg.cpp b/src/attribute-rel-svg.cpp new file mode 100644 index 000000000..3f5ce9395 --- /dev/null +++ b/src/attribute-rel-svg.cpp @@ -0,0 +1,120 @@ +/* + * attribute-rel-svg.cpp + * + * Created on: Jul 25, 2011 + * Author: abhishek + */ + +/** \class SPAttributeRelSVG + * + * SPAttributeRelSVG class stores the mapping of element->attribute + * relationship and provides a static function to access that + * mapping indirectly(only reading). + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <fstream> +#include <sstream> +#include <string> + +#include "attribute-rel-svg.h" + +#include "path-prefix.h" +#include "preferences.h" + +SPAttributeRelSVG * SPAttributeRelSVG::instance = NULL; + +/* + * This functions checks whether an element -> attribute pair is allowed or not + */ +bool SPAttributeRelSVG::findIfValid(Glib::ustring attribute, Glib::ustring element) +{ + if (SPAttributeRelSVG::instance == NULL) { + SPAttributeRelSVG::instance = new SPAttributeRelSVG(); + } + + // Strip of "svg:" from the element's name + Glib::ustring temp = element; + if ( temp.find("svg:") != std::string::npos ) { + temp.erase( temp.find("svg:"), 4 ); + } + + // Check for attributes with -, role, aria etc. to allow for more accessbility + if (attribute[0] == '-' + || attribute.substr(0,4) == "role" + || attribute.substr(0,4) == "aria" + || attribute.substr(0,5) == "xmlns" + || attribute.substr(0,9) == "inkscape:" + || attribute.substr(0,9) == "sodipodi:" + || attribute.substr(0,4) == "rdf:" + || attribute.substr(0,3) == "cc:" + || (SPAttributeRelSVG::instance->attributesOfElements[temp].find(attribute) + != SPAttributeRelSVG::instance->attributesOfElements[temp].end()) ) { + return true; + } else { + //g_warning( "Invalid attribute: %s used on <%s>", attribute.c_str(), element.c_str() ); + return false; + } +} + +/* + * One timer singleton constructor, to load the element -> attributes data + * into memory. + */ +SPAttributeRelSVG::SPAttributeRelSVG() +{ + std::fstream f; + + // Read data from standard path + std::string filepath = INKSCAPE_ATTRRELDIR; + filepath += "/svgprops"; + + f.open(filepath.c_str(), std::ios::in); + + if (!f.is_open()) { + // Set the default preference of attribute checking to ignore + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setInt("/options/svgoutput/incorrect_attributes", 3); + + // Display warning for file not open + g_warning("Could not open the data file for XML attribute-element map construction: %s", filepath.c_str()); + f.close(); + return ; + } + + while (!f.eof()){ + std::stringstream ss; + std::string s; + + std::getline(f,s,'"'); + std::getline(f,s,'"'); + if(s.size() > 0 && s[0] != '\n'){ + std::string prop = s; + getline(f,s); + ss << s; + + while(std::getline(ss,s,'"')){ + std::string element; + std::getline(ss,s,'"'); + element = s; + attributesOfElements[element].insert(prop); + } + } + } + + f.close(); +} + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/attribute-rel-svg.h b/src/attribute-rel-svg.h new file mode 100644 index 000000000..f0ba314b6 --- /dev/null +++ b/src/attribute-rel-svg.h @@ -0,0 +1,49 @@ +#ifndef __SP_ATTRIBUTE_REL_SVG_H__ +#define __SP_ATTRIBUTE_REL_SVG_H__ + +/* + * attribute-rel-svg.h + * + * Created on: Jul 25, 2011 + * Author: abhishek + */ + +#include <string> +#include <map> +#include <set> +#include <glibmm/ustring.h> + +// This data structure stores the valid (element -> set of attributes) pair +typedef std::map<Glib::ustring, std::set<Glib::ustring> > hashList; + +/* + * Utility class to check whether a combination of element and attribute + * is valid or not. + */ +class SPAttributeRelSVG { +public: + static bool findIfValid(Glib::ustring attribute, Glib::ustring element); + +private: + SPAttributeRelSVG(); + SPAttributeRelSVG(const SPAttributeRelSVG&); + SPAttributeRelSVG& operator= (const SPAttributeRelSVG&); + +private: + static SPAttributeRelSVG *instance; + hashList attributesOfElements; +}; + + +#endif /* __SP_ATTRIBUTE_REL_SVG_H__ */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/attribute-rel-util.cpp b/src/attribute-rel-util.cpp new file mode 100644 index 000000000..9104e26c1 --- /dev/null +++ b/src/attribute-rel-util.cpp @@ -0,0 +1,312 @@ +/* + * attribute-rel-util.h + * + * Created on: Sep 8, 2011 + * Author: tavmjong + */ + +/** + * Utility functions for cleaning SVG tree of unneeded attributes and style properties. + */ + +#include <fstream> +#include <sstream> +#include <string> +#include <iostream> + +#include "preferences.h" + +#include "xml/attribute-record.h" + +#include "attribute-rel-css.h" +#include "attribute-rel-svg.h" + +#include "attribute-rel-util.h" + +using Inkscape::XML::Node; +using Inkscape::XML::AttributeRecord; +using Inkscape::Util::List; + +/** + * Get preferences + */ +unsigned int sp_attribute_clean_get_prefs() { + + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + unsigned int flags = 0; + if( prefs->getBool("/options/svgoutput/incorrect_attributes_warn") ) flags += SP_ATTR_CLEAN_ATTR_WARN; + if( prefs->getBool("/options/svgoutput/incorrect_attributes_remove") ) flags += SP_ATTR_CLEAN_ATTR_REMOVE; + if( prefs->getBool("/options/svgoutput/incorrect_style_properties_warn") ) flags += SP_ATTR_CLEAN_STYLE_WARN; + if( prefs->getBool("/options/svgoutput/incorrect_style_properties_remove" ) ) flags += SP_ATTR_CLEAN_STYLE_REMOVE; + if( prefs->getBool("/options/svgoutput/style_defaults_warn") ) flags += SP_ATTR_CLEAN_DEFAULT_WARN; + if( prefs->getBool("/options/svgoutput/style_defaults_remove") ) flags += SP_ATTR_CLEAN_DEFAULT_REMOVE; + + return flags; +} + +/** + * Remove or warn about inappropriate attributes and useless stype properties. + * repr: the root node in a document or any other node. + */ +void sp_attribute_clean_tree(Node *repr) { + + g_return_if_fail (repr != NULL); + + unsigned int flags = sp_attribute_clean_get_prefs(); + + if( flags ) { + sp_attribute_clean_recursive( repr, flags ); + } +} + +/** + * Clean recursively over all elements. + */ +void sp_attribute_clean_recursive(Node *repr, unsigned int flags) { + + g_return_if_fail (repr != NULL); + + if( repr->type() == Inkscape::XML::ELEMENT_NODE ) { + Glib::ustring element = repr->name(); + + // Only clean elements in svg namespace + if( element.substr(0,4) == "svg:" ) { + sp_attribute_clean_element(repr, flags ); + } + } + + for(Node *child=sp_repr_children( repr ) ; child ; child = sp_repr_next( child ) ) { + sp_attribute_clean_recursive( child, flags ); + } +} + +/** + * Clean attributes on an element + */ +void sp_attribute_clean_element(Node *repr, unsigned int flags) { + + g_return_if_fail (repr != NULL); + g_return_if_fail (repr->type() == Inkscape::XML::ELEMENT_NODE); + + Glib::ustring element = repr->name(); + Glib::ustring id = (repr->attribute( "id" )==NULL ? "" : repr->attribute( "id" )); + + // Clean style: this attribute is unique in that normally we want to change it and not simply + // delete it. + sp_attribute_clean_style(repr, flags ); + + // Clean attributes + List<AttributeRecord const> attributes = repr->attributeList(); + + std::set<Glib::ustring> attributesToDelete; + for ( List<AttributeRecord const> iter = attributes ; iter ; ++iter ) { + + Glib::ustring attribute = g_quark_to_string(iter->key); + //Glib::ustring value = (const char*)iter->value; + + bool is_useful = sp_attribute_check_attribute( element, id, attribute, flags & SP_ATTR_CLEAN_ATTR_WARN ); + if( !is_useful ) { + attributesToDelete.insert( attribute ); + } + } + + // Do actual deleting (done after so as not to perturb List iterator). + for( std::set<Glib::ustring>::const_iterator iter_d = attributesToDelete.begin(); + iter_d != attributesToDelete.end(); ++iter_d ) { + repr->setAttribute( (*iter_d).c_str(), NULL, false ); + } +} + + +/** + * Clean CSS style on an element. + */ +void sp_attribute_clean_style(Node *repr, unsigned int flags) { + + g_return_if_fail (repr != NULL); + g_return_if_fail (repr->type() == Inkscape::XML::ELEMENT_NODE); + + // Find element's style + SPCSSAttr *css = sp_repr_css_attr( repr, "style" ); + + sp_attribute_clean_style(repr, css, flags); + + // g_warning( "sp_repr_write_stream_element(): Final style:" ); + //sp_repr_css_print( css ); + + // Convert css node's properties data to string and set repr node's attribute "style" to that string. + // sp_repr_css_set( repr, css, "style"); // Don't use as it will cause loop. + gchar *value = sp_repr_css_write_string(css); + repr->setAttribute("style", value); + if (value) g_free (value); + + sp_repr_css_attr_unref( css ); +} + + +/** + * Clean CSS style on an element. + */ +gchar * sp_attribute_clean_style(Node *repr, gchar const *string, unsigned int flags) { + + g_return_val_if_fail (repr != NULL, NULL); + g_return_val_if_fail (repr->type() == Inkscape::XML::ELEMENT_NODE, NULL); + + SPCSSAttr *css = sp_repr_css_attr_new(); + sp_repr_css_attr_add_from_string( css, string ); + sp_attribute_clean_style(repr, css, flags); + gchar* string_cleaned = sp_repr_css_write_string( css ); + + sp_repr_css_attr_unref( css ); + + return string_cleaned; +} + + +/** + * Clean CSS style on an element. + * + * 1. Is a style property appropriate on the given element? + * e.g, font-size is useless on <svg:rect> + * 2. Is the value of the style property useful? + * Is it the same as the parent and it inherits? + * Is it the default value (and the property on the parent is not set or does not inherit)? + */ +void sp_attribute_clean_style(Node* repr, SPCSSAttr *css, unsigned int flags) { + + g_return_if_fail (repr != NULL); + g_return_if_fail (css != NULL); + + Glib::ustring element = repr->name(); + Glib::ustring id = (repr->attribute( "id" )==NULL ? "" : repr->attribute( "id" )); + + // Find parent's style, including properties that are inherited. + // Note, a node may not have a parent if it has not yet been added to tree. + SPCSSAttr *css_parent = NULL; + if( repr->parent() ) css_parent = sp_repr_css_attr_inherited( repr->parent(), "style" ); + + // Loop over all properties in "style" node, keeping track of which to delete. + std::set<Glib::ustring> toDelete; + for ( List<AttributeRecord const> iter = css->attributeList() ; iter ; ++iter ) { + + gchar const * property = g_quark_to_string(iter->key); + gchar const * value = iter->value; + + // Check if a property is applicable to an element (i.e. is font-family useful for a <rect>?). + if( !SPAttributeRelCSS::findIfValid( property, element ) ) { + if( flags & SP_ATTR_CLEAN_STYLE_WARN ) { + g_warning( "<%s id=\"%s\">: CSS Style property: \"%s\" is inappropriate.", + element.c_str(), id.c_str(), property ); + } + if( flags & SP_ATTR_CLEAN_STYLE_REMOVE ) { + toDelete.insert(property); + } + continue; + } + + // Find parent value for same property (property) + gchar const * property_p = NULL; + gchar const * value_p = NULL; + if( css_parent != NULL ) { + for ( List<AttributeRecord const> iter_p = css_parent->attributeList() ; iter_p ; ++iter_p ) { + + property_p = g_quark_to_string(iter_p->key); + + if( !g_strcmp0( property, property_p ) ) { + value_p = iter_p->value; + break; + } + } + } + + // If parent has same property value and property is inherited, mark for deletion. + if ( !g_strcmp0( value, value_p ) && SPAttributeRelCSS::findIfInherit( property ) ) { + + if ( flags & SP_ATTR_CLEAN_DEFAULT_WARN ) { + g_warning( "<%s id=\"%s\">: CSS Style property: \"%s\" has same value as parent (%s).", + element.c_str(), id.c_str(), property, value ); + } + if ( flags & SP_ATTR_CLEAN_DEFAULT_REMOVE ) { + toDelete.insert( property ); + } + continue; + } + + // If property value is same as default and the parent value not set or property is not inherited, + // mark for deletion. + if ( SPAttributeRelCSS::findIfDefault( property, value ) && + ( (css_parent != NULL && value_p == NULL) || !SPAttributeRelCSS::findIfInherit( property ) ) ) { + + if ( flags & SP_ATTR_CLEAN_DEFAULT_WARN ) { + g_warning( "<%s id=\"%s\">: CSS Style property: \"%s\" with default value (%s) not needed.", + element.c_str(), id.c_str(), property, value ); + } + if ( flags & SP_ATTR_CLEAN_DEFAULT_REMOVE ) { + toDelete.insert( property ); + } + continue; + } + + } // End loop over style properties + + // Delete unneeded style properties. Do this at the end so as to not perturb List iterator. + for( std::set<Glib::ustring>::const_iterator iter_d = toDelete.begin(); iter_d != toDelete.end(); ++iter_d ) { + sp_repr_css_set_property( css, (*iter_d).c_str(), NULL ); + } + +} + +/** + * Check one attribute on an element + */ +bool sp_attribute_check_attribute(Glib::ustring element, Glib::ustring id, Glib::ustring attribute, bool warn) { + + bool is_useful = true; + + if( SPAttributeRelCSS::findIfProperty( attribute ) ) { + + // First check if it is a presentation attribute. Presentation attributes can be applied to + // any element. At the moment, we are only going to check if it is a possibly useful + // attribute. Note, we don't explicitely check against the list of elements where presentation + // attributes are allowed (See SVG1.1 spec, Appendix M.2). + if( !SPAttributeRelCSS::findIfValid( attribute, element ) ) { + + // Non-useful presentation attribute on SVG <element> + if( warn ) { + g_warning( "<%s id=\"%s\">: Non-useful presentation attribute: \"%s\" found.", + element.c_str(), + id.c_str(), + attribute.c_str() ); + } + is_useful = false; + } + + } else { + + // Second check if it is a valid attribute + if ( !SPAttributeRelSVG::findIfValid( attribute, element ) ) { + + // Invalid attribute on SVG <element> + if( warn ) { + g_warning( "<%s id=\"%s\">: Invalid attribute: \"%s\" found.", + element.c_str(), + id.c_str(), + attribute.c_str() ); + } + is_useful = false; + } + } + + return is_useful; +} + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/attribute-rel-util.h b/src/attribute-rel-util.h new file mode 100644 index 000000000..d9d270a13 --- /dev/null +++ b/src/attribute-rel-util.h @@ -0,0 +1,87 @@ +#ifndef __SP_ATTRIBUTE_REL_UTIL_H__ +#define __SP_ATTRIBUTE_REL_UTIL_H__ + +/* + * attribute-rel-util.h + * + * Created on: Sep 8, 2011 + * Author: tavmjong + */ + +#include "glibmm/ustring.h" +#include "xml/node.h" +#include "xml/sp-css-attr.h" + +using Inkscape::XML::Node; + +/** + * Utility functions for cleaning XML tree. + */ + +/** + * Enum for preferences + */ +enum SPAttrClean { + SP_ATTR_CLEAN_ATTR_WARN = 1, + SP_ATTR_CLEAN_ATTR_REMOVE = 2, + SP_ATTR_CLEAN_STYLE_WARN = 4, + SP_ATTR_CLEAN_STYLE_REMOVE = 8, + SP_ATTR_CLEAN_DEFAULT_WARN = 16, + SP_ATTR_CLEAN_DEFAULT_REMOVE = 32 +}; + +/** + * Get preferences + */ +unsigned int sp_attribute_clean_get_prefs(); + +/** + * Remove or warn about inappropriate attributes and useless style properties. + * repr: the root node in a document or any other node. + */ +void sp_attribute_clean_tree(Node *repr); + +/** + * Recursively clean. + * repr: the root node in a document or any other node. + * pref_attr, pref_style, pref_defaults: ignore, delete, or warn. + */ +void sp_attribute_clean_recursive(Node *repr, unsigned int flags); + +/** + * Clean one element (attributes and style properties). + */ +void sp_attribute_clean_element(Node *repr, unsigned int flags); + +/** + * Clean style properties for one element. + */ +void sp_attribute_clean_style(Node *repr, unsigned int flags); + +/** + * Clean style properties for one style string. + */ +gchar* sp_attribute_clean_style(Node *repr, gchar const *string, unsigned int flags); + +/** + * Clean style properties for one CSS. + */ +void sp_attribute_clean_style(Node* repr, SPCSSAttr *css, unsigned int flags); + +/** + * Check one attribute on an element + */ +bool sp_attribute_check_attribute(Glib::ustring element, Glib::ustring id, Glib::ustring attribute, bool warn); + +#endif /* __SP_ATTRIBUTE_REL_UTIL_H__ */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/path-prefix.h b/src/path-prefix.h index b2ff6ff88..193801532 100644 --- a/src/path-prefix.h +++ b/src/path-prefix.h @@ -22,6 +22,7 @@ extern "C" { #ifdef ENABLE_BINRELOC # define INKSCAPE_APPICONDIR BR_DATADIR( "/pixmaps" ) +# define INKSCAPE_ATTRRELDIR BR_DATADIR( "/inkscape/attributes" ) # define INKSCAPE_BINDDIR BR_DATADIR( "/inkscape/bind" ) # define INKSCAPE_EXAMPLESDIR BR_DATADIR( "/inkscape/examples" ) # define INKSCAPE_EXTENSIONDIR BR_DATADIR( "/inkscape/extensions" ) @@ -43,6 +44,7 @@ extern "C" { #else # ifdef WIN32 # define INKSCAPE_APPICONDIR WIN32_DATADIR("pixmaps") +# define INKSCAPE_ATTRRELDIR WIN32_DATADIR "share\\attributes" # define INKSCAPE_BINDDIR WIN32_DATADIR("share\\bind") # define INKSCAPE_EXAMPLESDIR WIN32_DATADIR("share\\examples") # define INKSCAPE_EXTENSIONDIR WIN32_DATADIR("share\\extensions") @@ -63,6 +65,7 @@ extern "C" { # define CREATE_PATTERNSDIR WIN32_DATADIR("create\\patterns\\vector") # elif defined ENABLE_OSX_APP_LOCATIONS # define INKSCAPE_APPICONDIR "Contents/Resources/pixmaps" +# define INKSCAPE_ATTRRELDIR "Contents/Resources/attributes" # define INKSCAPE_BINDDIR "Contents/Resources/bind" # define INKSCAPE_EXAMPLESDIR "Contents/Resources/examples" # define INKSCAPE_EXTENSIONDIR "Contents/Resources/extensions" @@ -83,6 +86,7 @@ extern "C" { # define CREATE_PATTERNSDIR "/Library/Application Support/create/patterns/vector" # else # define INKSCAPE_APPICONDIR INKSCAPE_DATADIR "/pixmaps" +# define INKSCAPE_ATTRRELDIR INKSCAPE_DATADIR "/inkscape/attributes" # define INKSCAPE_BINDDIR INKSCAPE_DATADIR "/inkscape/bind" # define INKSCAPE_EXAMPLESDIR INKSCAPE_DATADIR "/inkscape/examples" # define INKSCAPE_EXTENSIONDIR INKSCAPE_DATADIR "/inkscape/extensions" diff --git a/src/preferences-skeleton.h b/src/preferences-skeleton.h index 70193bf96..b4f1e12cc 100644 --- a/src/preferences-skeleton.h +++ b/src/preferences-skeleton.h @@ -315,7 +315,23 @@ static char const preferences_skeleton[] = " images=\"4278190335\"" //ff0000ff " clips=\"16711935\"" // 00ff00ff " masks=\"65535\"/>\n" // 0x0000ffff -" <group id=\"svgoutput\" usenamedcolors=\"0\" numericprecision=\"8\" minimumexponent=\"-8\" inlineattrs=\"0\" indent=\"2\" allowrelativecoordinates=\"1\" forcerepeatcommands=\"0\"/>\n" +" <group id=\"svgoutput\" " +" usenamedcolors=\"0\" " +" numericprecision=\"8\" " +" minimumexponent=\"-8\" " +" inlineattrs=\"0\" " +" indent=\"2\" " +" allowrelativecoordinates=\"1\" " +" forcerepeatcommands=\"0\" " +" incorrect_attributes_warn=\"1\" " +" incorrect_attributes_remove=\"0\" " +" incorrect_style_properties_warn=\"1\" " +" incorrect_style_properties_remove=\"0\" " +" style_defaults_warn=\"1\" " +" style_defaults_remove=\"0\" " +" check_on_reading=\"0\" " +" check_on_editing=\"0\" " +" check_on_writing=\"0\"/>\n" " <group id=\"forkgradientvectors\" value=\"1\"/>\n" " <group id=\"iconrender\" named_nodelay=\"0\"/>\n" " <group id=\"autosave\" enable=\"0\" interval=\"10\" path=\"\" max=\"10\"/>\n" diff --git a/src/sp-object.cpp b/src/sp-object.cpp index d746e278d..bf85d074e 100644 --- a/src/sp-object.cpp +++ b/src/sp-object.cpp @@ -20,8 +20,10 @@ #include "helper/sp-marshal.h" #include "xml/node-event-vector.h" #include "attributes.h" +#include "attribute-rel-util.h" #include "color-profile.h" #include "document.h" +#include "preferences.h" #include "style.h" #include "sp-object-repr.h" #include "sp-paint-server.h" @@ -1021,8 +1023,31 @@ Inkscape::XML::Node * SPObject::sp_object_private_write(SPObject *object, Inksca SPStyle const *const obj_style = object->style; if (obj_style) { gchar *s = sp_style_write_string(obj_style, SP_STYLE_FLAG_IFSET); - repr->setAttribute("style", ( *s ? s : NULL )); + + // Check for valid attributes. This may be time consuming. + // It is useful, though, for debugging Inkscape code. + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + if( prefs->getBool("/options/svgoutput/check_on_editing") ) { + + unsigned int flags = sp_attribute_clean_get_prefs(); + gchar *s_cleaned = sp_attribute_clean_style( repr, s, flags ); + + // g_warning("SPObject::sp_object_private_write: %s", object->getId() ); + // g_warning(" old: :%s:", repr->attribute("style") ); + // g_warning(" new: :%s:", s ); + // g_warning(" cleaned: :%s:", s_cleaned ); + + g_free( s ); + s = s_cleaned; + } + + if( s == NULL || strcmp(s,"") == 0 ) { + repr->setAttribute("style", NULL); + } else { + repr->setAttribute("style", s); + } g_free(s); + } else { /** \todo I'm not sure what to do in this case. Bug #1165868 * suggests that it can arise, but the submitter doesn't know diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp index 6d28e8c88..cb4d2b755 100644 --- a/src/ui/dialog/inkscape-preferences.cpp +++ b/src/ui/dialog/inkscape-preferences.cpp @@ -1124,6 +1124,42 @@ void InkscapePreferences::initPageSVGOutput() _svgoutput_minimumexponent.init("/options/svgoutput/minimumexponent", -32.0, -1, 1.0, 2.0, -8.0, true, false); _page_svgoutput.add_line( false, _("Minimum exponent:"), _svgoutput_minimumexponent, "", _("The smallest number written to SVG is 10 to the power of this exponent; anything smaller is written as zero"), false); + /* Code to add controls for attribute checking options */ + + /* Add incorrect style properties options */ + _page_svgoutput.add_group_header( _("Improper Attributes Actions")); + + _svgoutput_attrwarn.init( _("Print warnings"), "/options/svgoutput/incorrect_attributes_warn", true); + _page_svgoutput.add_line( false, "", _svgoutput_attrwarn, "", _("Print warning if invalid or non-useful attributes found. Database files located in inkscape_data_dir/attributes."), false); + _svgoutput_attrremove.init( _("Remove attributes"), "/options/svgoutput/incorrect_attributes_remove", false); + _page_svgoutput.add_line( false, "", _svgoutput_attrremove, "", _("Delete invalid or non-useful attributes from element tag."), false); + + /* Add incorrect style properties options */ + _page_svgoutput.add_group_header( _("Inappropriate Style Properties Actions")); + + _svgoutput_stylepropwarn.init( _("Print warnings"), "/options/svgoutput/incorrect_style_properties_warn", true); + _page_svgoutput.add_line( false, "", _svgoutput_stylepropwarn, "", _("Print warning if inappropriate style properties found (i.e. 'font-family' set on a <rect>). Database files located in inkscape_data_dir/attributes."), false); + _svgoutput_stylepropremove.init( _("Remove style properties"), "/options/svgoutput/incorrect_style_properties_remove", false); + _page_svgoutput.add_line( false, "", _svgoutput_stylepropremove, "", _("Delete inappropriate style properties."), false); + + /* Add default or inherited style properties options */ + _page_svgoutput.add_group_header( _("Non-useful Style Properties Actions")); + + _svgoutput_styledefaultswarn.init( _("Print warnings"), "/options/svgoutput/style_defaults_warn", true); + _page_svgoutput.add_line( false, "", _svgoutput_styledefaultswarn, "", _("Print warning if redundant style properties found (i.e. if a property has the default value and a different value is not inherited or if value is the same as would be inherited). Database files located in inkscape_data_dir/attributes."), false); + _svgoutput_styledefaultsremove.init( _("Remove style properties"), "/options/svgoutput/style_defaults_remove", false); + _page_svgoutput.add_line( false, "", _svgoutput_styledefaultsremove, "", _("Delete redundant style properties."), false); + + _page_svgoutput.add_group_header( _("Check Attributes and Style Properties on:")); + + _svgoutput_check_reading.init( _("Reading"), "/options/svgoutput/check_on_reading", false); + _page_svgoutput.add_line( false, "", _svgoutput_check_reading, "", _("Check attributes and style properties on reading in SVG files (including those internal to Inkscape which will slow down startup)."), false); + _svgoutput_check_editing.init( _("Editing"), "/options/svgoutput/check_on_editing", false); + _page_svgoutput.add_line( false, "", _svgoutput_check_editing, "", _("Check attributes and style properties while editing SVG files (may slow down Inkscape, mostly useful for debugging)."), false); + _svgoutput_check_writing.init( _("Writing"), "/options/svgoutput/check_on_writing", true); + _page_svgoutput.add_line( false, "", _svgoutput_check_writing, "", _("Check attributes and style properties on writing out SVG files."), false); + + this->AddPage(_page_svgoutput, _("SVG output"), PREFS_PAGE_SVGOUTPUT); } diff --git a/src/ui/dialog/inkscape-preferences.h b/src/ui/dialog/inkscape-preferences.h index d783a2df1..a72b74203 100644 --- a/src/ui/dialog/inkscape-preferences.h +++ b/src/ui/dialog/inkscape-preferences.h @@ -358,6 +358,17 @@ protected: UI::Widget::PrefCheckButton _svgoutput_allowrelativecoordinates; UI::Widget::PrefCheckButton _svgoutput_forcerepeatcommands; + // Attribute Checking controls for SVG Output page: + UI::Widget::PrefCheckButton _svgoutput_attrwarn; + UI::Widget::PrefCheckButton _svgoutput_attrremove; + UI::Widget::PrefCheckButton _svgoutput_stylepropwarn; + UI::Widget::PrefCheckButton _svgoutput_stylepropremove; + UI::Widget::PrefCheckButton _svgoutput_styledefaultswarn; + UI::Widget::PrefCheckButton _svgoutput_styledefaultsremove; + UI::Widget::PrefCheckButton _svgoutput_check_reading; + UI::Widget::PrefCheckButton _svgoutput_check_editing; + UI::Widget::PrefCheckButton _svgoutput_check_writing; + UI::Widget::PrefEntryButtonHBox _importexport_ocal_url; UI::Widget::PrefEntry _importexport_ocal_username; UI::Widget::PrefEntry _importexport_ocal_password; diff --git a/src/xml/repr-io.cpp b/src/xml/repr-io.cpp index 365415488..39eb2637a 100644 --- a/src/xml/repr-io.cpp +++ b/src/xml/repr-io.cpp @@ -33,6 +33,8 @@ #include "extension/extension.h" +#include "attribute-rel-util.h" + #include "preferences.h" using Inkscape::IO::Writer; @@ -256,6 +258,7 @@ int XmlSource::close() Document * sp_repr_read_file (const gchar * filename, const gchar *default_ns) { + // g_warning( "Reading file: %s", filename ); xmlDocPtr doc = 0; Document * rdoc = 0; @@ -446,6 +449,18 @@ sp_repr_do_read (xmlDocPtr doc, const gchar *default_ns) promote_to_namespace(root, INKSCAPE_EXTENSION_NS_NC); } } + + + // Clean unnecessary attributes and style properties from SVG documents. (Controlled by + // preferences.) Note: internal Inkscape svg files will also be cleaned (filters.svg, + // icons.svg). How can one tell if a file is internal? + if ( !strcmp(root->name(), "svg:svg" ) ) { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + bool clean = prefs->getBool("/options/svgoutput/check_on_reading"); + if( clean ) { + sp_attribute_clean_tree( root ); + } + } } g_hash_table_destroy (prefix_map); @@ -806,6 +821,12 @@ sp_repr_write_stream_root_element(Node *repr, Writer &out, using Inkscape::Util::ptr_shared; g_assert(repr != NULL); + + // Clean unnecessary attributes and stype properties. (Controlled by preferences.) + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + bool clean = prefs->getBool("/options/svgoutput/check_on_writing"); + if (clean) sp_attribute_clean_tree( repr ); + Glib::QueryQuark xml_prefix=g_quark_from_static_string("xml"); NSMap ns_map; @@ -928,7 +949,7 @@ void sp_repr_write_stream_element( Node * repr, Writer & out, add_whitespace = false; } - + // THIS DOESN'T APPEAR TO DO ANYTHING. Can it be commented out or deleted? { GQuark const href_key = g_quark_from_static_string("xlink:href"); GQuark const absref_key = g_quark_from_static_string("sodipodi:absref"); diff --git a/src/xml/simple-node.cpp b/src/xml/simple-node.cpp index 792706a18..44ddba237 100644 --- a/src/xml/simple-node.cpp +++ b/src/xml/simple-node.cpp @@ -1,6 +1,5 @@ -/** - * @file - * Garbage collected XML node implementation. +/** @file + * @brief Garbage collected XML node implementation */ /* Copyright 2003-2005 MenTaLguY <mental@rydia.net> * Copyright 2003 Nathan Hurst @@ -17,8 +16,11 @@ #include <cstring> #include <string> + #include <glib/gstrfuncs.h> +#include "preferences.h" + #include "xml/node.h" #include "xml/simple-node.h" #include "xml/node-event-vector.h" @@ -29,6 +31,8 @@ #include "util/share.h" #include "util/format.h" +#include "attribute-rel-util.h" + namespace Inkscape { namespace XML { @@ -312,6 +316,47 @@ SimpleNode::setAttribute(gchar const *name, gchar const *value, bool const /*is_ { g_return_if_fail(name && *name); + // Check usefulness of attributes on elements in the svg namespace, optionally don't add them to tree. + Glib::ustring element = g_quark_to_string(_name); + //g_warning("setAttribute: %s: %s: %s", element.c_str(), name, value); + + gchar* cleaned_value = g_strdup( value ); + + // Only check elements in SVG name space and don't block setting attribute to NULL. + if( element.substr(0,4) == "svg:" && value != NULL) { + + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + if( prefs->getBool("/options/svgoutput/check_on_editing") ) { + + gchar const *id_char = attribute("id"); + Glib::ustring id = (id_char == NULL ? "" : id_char ); + unsigned int flags = sp_attribute_clean_get_prefs(); + bool attr_warn = flags & SP_ATTR_CLEAN_ATTR_WARN; + bool attr_remove = flags & SP_ATTR_CLEAN_ATTR_REMOVE; + + // Check attributes + if( (attr_warn || attr_remove) && value != NULL ) { + bool is_useful = sp_attribute_check_attribute( element, id, name, attr_warn ); + if( !is_useful && attr_remove ) { + g_free( cleaned_value ); + return; // Don't add to tree. + } + } + + // Check style properties -- Note: if element is not yet inserted into + // tree (and thus has no parent), default values will not be tested. + if( !strcmp( name, "style" ) && (flags >= SP_ATTR_CLEAN_STYLE_WARN) ) { + g_free( cleaned_value ); + cleaned_value = sp_attribute_clean_style( this, value, flags ); + // if( g_strcmp0( value, cleaned_value ) ) { + // g_warning( "SimpleNode::setAttribute: %s", id.c_str() ); + // g_warning( " original: %s", value); + // g_warning( " cleaned: %s", cleaned_value); + // } + } + } + } + GQuark const key = g_quark_from_string(name); MutableList<AttributeRecord> ref; @@ -322,14 +367,13 @@ SimpleNode::setAttribute(gchar const *name, gchar const *value, bool const /*is_ } ref = existing; } - Debug::EventTracker<> tracker; ptr_shared<char> old_value=( existing ? existing->value : ptr_shared<char>() ); ptr_shared<char> new_value=ptr_shared<char>(); - if (value) { - new_value = share_string(value); + if (cleaned_value) { + new_value = share_string(cleaned_value); tracker.set<DebugSetAttribute>(*this, key, new_value); if (!existing) { if (ref) { @@ -355,7 +399,11 @@ SimpleNode::setAttribute(gchar const *name, gchar const *value, bool const /*is_ if ( new_value != old_value && (!old_value || !new_value || strcmp(old_value, new_value))) { _document->logger()->notifyAttributeChanged(*this, key, old_value, new_value); _observers.notifyAttributeChanged(*this, key, old_value, new_value); + //g_warning( "setAttribute notified: %s: %s: %s: %s", name, element.c_str(), old_value, new_value ); } + + g_free( cleaned_value ); + } void SimpleNode::addChild(Node *generic_child, Node *generic_ref) { |
