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 {