SourceForge: dvisvgm/dvisvgm: changeset 357:39d380bdca39
PS handler: replace zero-length paths by dots
authorMartin Gieseking <mgieseki@users.sourceforge.net>
Fri Nov 06 21:00:58 2009 +0100 (2 weeks ago)
changeset 35739d380bdca39
parent 356c871faefbd2c
child 358742dc459a53e
PS handler: replace zero-length paths by dots
src/GraphicPath.h
src/PsSpecialHandler.cpp
     1.1 --- a/src/GraphicPath.h	Thu Oct 29 08:17:00 2009 +0100
     1.2 +++ b/src/GraphicPath.h	Fri Nov 06 21:00:58 2009 +0100
     1.3 @@ -25,8 +25,8 @@
     1.4  #include <ostream>
     1.5  #include <vector>
     1.6  #include "BoundingBox.h"
     1.7 +#include "Matrix.h"
     1.8  #include "Pair.h"
     1.9 -#include "Matrix.h"
    1.10  
    1.11  
    1.12  template <typename T>
    1.13 @@ -85,6 +85,7 @@
    1.14  		virtual void scubicto (const Point &p1, const Point &p2) {}
    1.15  		virtual void cubicto (const Point &p1, const Point &p2, const Point &p3) {}
    1.16  		virtual void closepath () {}
    1.17 +		virtual bool quit () {return false;}
    1.18  	};
    1.19  
    1.20  	typedef typename std::vector<Command>::iterator Iterator;
    1.21 @@ -171,6 +172,22 @@
    1.22  			iterate(actions, false);
    1.23  		}
    1.24  
    1.25 +		bool isDot (Point &p) const {
    1.26 +			struct DotActions : Actions {
    1.27 +				DotActions () : differs(false) {}
    1.28 +				void moveto (const Point &p) {point = p;}
    1.29 +				void lineto (const Point &p) {differs = (p != point);}
    1.30 +				void conicto (const Point &p1, const Point &p2) {differs = (point != p1 || point != p2);}
    1.31 +				void cubicto (const Point &p1, const Point &p2, const Point &p3) {differs = (point != p1 || point != p2 || point != p3);}
    1.32 +				bool quit () {return differs;}
    1.33 +				Point point;
    1.34 +				bool differs;
    1.35 +			} actions;
    1.36 +			iterate(actions, false);
    1.37 +			p = actions.point;
    1.38 +			return !actions.differs;
    1.39 +		}
    1.40 +
    1.41  		void transform (const Matrix &matrix) {
    1.42  			FORALL(_commands, Iterator, it)
    1.43  				it->transform(matrix);
    1.44 @@ -189,7 +206,7 @@
    1.45  	Point fp; // first point of current path
    1.46  	Point cp; // current point
    1.47  	Point pstore[2];
    1.48 -	FORALL(_commands, ConstIterator, it) {
    1.49 +	for (ConstIterator it=_commands.begin(); it != _commands.end() && !actions.quit(); ++it) {
    1.50  		const Point *params = it->params;
    1.51  		switch (it->type) {
    1.52  			case Command::MOVETO:
     2.1 --- a/src/PsSpecialHandler.cpp	Thu Oct 29 08:17:00 2009 +0100
     2.2 +++ b/src/PsSpecialHandler.cpp	Fri Nov 06 21:00:58 2009 +0100
     2.3 @@ -290,30 +290,58 @@
     2.4  		ScalingMatrix scale(pt, pt);
     2.5  		_path.transform(scale);
     2.6  
     2.7 -		// compute bounding box
     2.8 +		XMLElementNode *path=0;
     2.9  		BoundingBox bbox;
    2.10 -		_path.computeBBox(bbox);
    2.11 -		bbox.expand(_linewidth/2);
    2.12 -		if (!_actions->getMatrix().isIdentity()) {
    2.13 -			_path.transform(_actions->getMatrix());
    2.14 -			if (!_xmlnode)
    2.15 -				bbox.transform(_actions->getMatrix());
    2.16 +		Pair<double> point;
    2.17 +		if (_path.isDot(point)) {  // zero-length path?
    2.18 +			if (_linecap == 1) {     // round line ends?  => draw dot
    2.19 +				double x = point.x();
    2.20 +				double y = point.y();
    2.21 +				double r = _linewidth/2.0;
    2.22 +				path = new XMLElementNode("circle");
    2.23 +				path->addAttribute("cx", XMLString(x));
    2.24 +				path->addAttribute("cy", XMLString(y));
    2.25 +				path->addAttribute("r", XMLString(r));
    2.26 +				path->addAttribute("fill", _actions->getColor().rgbString());
    2.27 +				bbox = BoundingBox(x-r, y-r, x+r, y+r);
    2.28 +			}
    2.29  		}
    2.30 +		else {
    2.31 +			// compute bounding box
    2.32 +			_path.computeBBox(bbox);
    2.33 +			bbox.expand(_linewidth/2);
    2.34 +			if (!_actions->getMatrix().isIdentity()) {
    2.35 +				_path.transform(_actions->getMatrix());
    2.36 +				if (!_xmlnode)
    2.37 +					bbox.transform(_actions->getMatrix());
    2.38 +			}
    2.39  
    2.40 -		ostringstream oss;
    2.41 -		_path.writeSVG(oss);
    2.42 -		XMLElementNode *path = new XMLElementNode("path");
    2.43 -		path->addAttribute("d", oss.str());
    2.44 -		path->addAttribute("stroke", _actions->getColor().rgbString());
    2.45 -		path->addAttribute("fill", "none");
    2.46 -		if (_linewidth != 1)
    2.47 -			path->addAttribute("stroke-width", XMLString(_linewidth));
    2.48 -		if (_miterlimit != 4)
    2.49 -			path->addAttribute("stroke-miterlimit", XMLString(_miterlimit));
    2.50 -		if (_linecap > 0)     // default value is "butt", no need to set it explicitely
    2.51 -			path->addAttribute("stroke-linecap", XMLString(_linecap == 1 ? "round" : "square"));
    2.52 -		if (_linejoin > 0)    // default value is "miter", no need to set it explicitely
    2.53 -			path->addAttribute("stroke-linejoin", XMLString(_linecap == 1 ? "round" : "bevel"));
    2.54 +			ostringstream oss;
    2.55 +			_path.writeSVG(oss);
    2.56 +			path = new XMLElementNode("path");
    2.57 +			path->addAttribute("d", oss.str());
    2.58 +			path->addAttribute("stroke", _actions->getColor().rgbString());
    2.59 +			path->addAttribute("fill", "none");
    2.60 +			if (_linewidth != 1)
    2.61 +				path->addAttribute("stroke-width", XMLString(_linewidth));
    2.62 +			if (_miterlimit != 4)
    2.63 +				path->addAttribute("stroke-miterlimit", XMLString(_miterlimit));
    2.64 +			if (_linecap > 0)     // default value is "butt", no need to set it explicitely
    2.65 +				path->addAttribute("stroke-linecap", XMLString(_linecap == 1 ? "round" : "square"));
    2.66 +			if (_linejoin > 0)    // default value is "miter", no need to set it explicitely
    2.67 +				path->addAttribute("stroke-linejoin", XMLString(_linecap == 1 ? "round" : "bevel"));
    2.68 +			if (_dashpattern.size() > 0) {
    2.69 +				ostringstream oss;
    2.70 +				for (size_t i=0; i < _dashpattern.size(); i++) {
    2.71 +					if (i > 0)
    2.72 +						oss << ',';
    2.73 +					oss << _dashpattern[i];
    2.74 +				}
    2.75 +				path->addAttribute("stroke-dasharray", oss.str());
    2.76 +				if (_dashoffset != 0)
    2.77 +					path->addAttribute("stroke-dashoffset", _dashoffset);
    2.78 +			}
    2.79 +		}
    2.80  		if (_clipStack.top()) {
    2.81  			// assign clipping path and clip bounding box
    2.82  			path->addAttribute("clip-path", XMLString("url(#clip")+XMLString(_clipStack.topID())+XMLString(")"));
    2.83 @@ -321,17 +349,7 @@
    2.84  			_clipStack.top()->computeBBox(clipbox);
    2.85  			bbox.intersect(clipbox);
    2.86  		}
    2.87 -		if (_dashpattern.size() > 0) {
    2.88 -			ostringstream oss;
    2.89 -			for (size_t i=0; i < _dashpattern.size(); i++) {
    2.90 -				if (i > 0)
    2.91 -					oss << ',';
    2.92 -				oss << _dashpattern[i];
    2.93 -			}
    2.94 -			path->addAttribute("stroke-dasharray", oss.str());
    2.95 -			if (_dashoffset != 0)
    2.96 -				path->addAttribute("stroke-dashoffset", _dashoffset);
    2.97 -		}
    2.98 +
    2.99  		if (_xmlnode)
   2.100  			_xmlnode->append(path);
   2.101  		else {