diff options
author | Karl Berry <karl@freefriends.org> | 2019-01-25 23:20:32 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2019-01-25 23:20:32 +0000 |
commit | dbb07a7a7359963676891de548723b36785eff79 (patch) | |
tree | e46b8d2cb0e53954b3cb06cab0d9bae28606a9e3 /Build/source/texk/dvisvgm/dvisvgm-src/src/PsSpecialHandler.cpp | |
parent | 0c9aa4f80b0f44658e8ba13f2261a2386e99c774 (diff) |
dvisvgm 2.6.2
git-svn-id: svn://tug.org/texlive/trunk@49819 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/dvisvgm/dvisvgm-src/src/PsSpecialHandler.cpp')
-rw-r--r-- | Build/source/texk/dvisvgm/dvisvgm-src/src/PsSpecialHandler.cpp | 126 |
1 files changed, 70 insertions, 56 deletions
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/PsSpecialHandler.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/PsSpecialHandler.cpp index 167ab0bc393..e383f4c5806 100644 --- a/Build/source/texk/dvisvgm/dvisvgm-src/src/PsSpecialHandler.cpp +++ b/Build/source/texk/dvisvgm/dvisvgm-src/src/PsSpecialHandler.cpp @@ -2,7 +2,7 @@ ** PsSpecialHandler.cpp ** ** ** ** This file is part of dvisvgm -- a fast DVI to SVG converter ** -** Copyright (C) 2005-2018 Martin Gieseking <martin.gieseking@uos.de> ** +** Copyright (C) 2005-2019 Martin Gieseking <martin.gieseking@uos.de> ** ** ** ** This program is free software; you can redistribute it and/or ** ** modify it under the terms of the GNU General Public License as ** @@ -545,7 +545,7 @@ static string css_blendmode_name (int mode) { * @param[in] p not used */ void PsSpecialHandler::stroke (vector<double> &p) { _path.removeRedundantCommands(); - if ((_path.empty() && !_clipStack.clippathLoaded()) || !_actions) + if ((_path.empty() && !_clipStack.prependedPath()) || !_actions) return; BoundingBox bbox; @@ -554,8 +554,8 @@ void PsSpecialHandler::stroke (vector<double> &p) { if (!_xmlnode) bbox.transform(_actions->getMatrix()); } - if (_clipStack.clippathLoaded() && _clipStack.top()) - _path.prepend(*_clipStack.top()); + if (_clipStack.prependedPath()) + _path.prepend(*_clipStack.prependedPath()); unique_ptr<XMLElementNode> path; Pair<double> point; if (_path.isDot(point)) { // zero-length path? @@ -606,13 +606,13 @@ void PsSpecialHandler::stroke (vector<double> &p) { path->addAttribute("stroke-dashoffset", _dashoffset); } } - if (path && _clipStack.top()) { + if (path && _clipStack.path()) { // assign clipping path and clip bounding box path->addAttribute("clip-path", XMLString("url(#clip")+XMLString(_clipStack.topID())+")"); BoundingBox clipbox; - _clipStack.top()->computeBBox(clipbox); + _clipStack.path()->computeBBox(clipbox); bbox.intersect(clipbox); - _clipStack.setClippathLoaded(false); + _clipStack.removePrependedPath(); } if (_xmlnode) _xmlnode->append(std::move(path)); @@ -629,7 +629,7 @@ void PsSpecialHandler::stroke (vector<double> &p) { * @param[in] evenodd true: use even-odd fill algorithm, false: use nonzero fill algorithm */ void PsSpecialHandler::fill (vector<double> &p, bool evenodd) { _path.removeRedundantCommands(); - if ((_path.empty() && !_clipStack.clippathLoaded()) || !_actions) + if ((_path.empty() && !_clipStack.prependedPath()) || !_actions) return; // compute bounding box @@ -640,8 +640,8 @@ void PsSpecialHandler::fill (vector<double> &p, bool evenodd) { if (!_xmlnode) bbox.transform(_actions->getMatrix()); } - if (_clipStack.clippathLoaded() && _clipStack.top()) - _path.prepend(*_clipStack.top()); + if (_clipStack.prependedPath()) + _path.prepend(*_clipStack.prependedPath()); ostringstream oss; _path.writeSVG(oss, SVGTree::RELATIVE_PATH_CMDS); @@ -651,13 +651,13 @@ void PsSpecialHandler::fill (vector<double> &p, bool evenodd) { path->addAttribute("fill", XMLString("url(#")+_pattern->svgID()+")"); else if (_actions->getColor() != Color::BLACK || _savenode) path->addAttribute("fill", _actions->getColor().svgColorString()); - if (_clipStack.top()) { + if (_clipStack.path()) { // assign clipping path and clip bounding box path->addAttribute("clip-path", XMLString("url(#clip")+XMLString(_clipStack.topID())+")"); BoundingBox clipbox; - _clipStack.top()->computeBBox(clipbox); + _clipStack.path()->computeBBox(clipbox); bbox.intersect(clipbox); - _clipStack.setClippathLoaded(false); + _clipStack.removePrependedPath(); } if (evenodd) // SVG default fill rule is "nonzero" algorithm path->addAttribute("fill-rule", "evenodd"); @@ -779,10 +779,8 @@ void PsSpecialHandler::initclip (vector<double> &) { /** Assigns the current clipping path to the graphics path. */ void PsSpecialHandler::clippath (std::vector<double>&) { - if (!_clipStack.empty()) { - _clipStack.setClippathLoaded(true); - _path.clear(); - } + if (!_clipStack.empty()) + _clipStack.setPrependedPath(); } @@ -802,7 +800,7 @@ void PsSpecialHandler::clip (vector<double>&, bool evenodd) { * computed by intersecting the current one with the given path. * @param[in] path path used to restrict the clipping region * @param[in] evenodd true: use even-odd fill algorithm, false: use nonzero fill algorithm */ -void PsSpecialHandler::clip (Path &path, bool evenodd) { +void PsSpecialHandler::clip (Path path, bool evenodd) { // when this method is called, _path contains the clipping path if (path.empty() || !_actions) return; @@ -812,37 +810,41 @@ void PsSpecialHandler::clip (Path &path, bool evenodd) { if (!_actions->getMatrix().isIdentity()) path.transform(_actions->getMatrix()); + if (_clipStack.prependedPath()) + path.prepend(*_clipStack.prependedPath()); int oldID = _clipStack.topID(); ostringstream oss; + bool pathReplaced; if (!COMPUTE_CLIPPATHS_INTERSECTIONS || oldID < 1) { - _clipStack.replace(path); + pathReplaced = _clipStack.replace(path); path.writeSVG(oss, SVGTree::RELATIVE_PATH_CMDS); } else { // compute the intersection of the current clipping path with the current graphics path - const Path *oldPath = _clipStack.top(); + const Path *oldPath = _clipStack.path(); Path intersectedPath(windingRule); PathClipper clipper; clipper.intersect(*oldPath, path, intersectedPath); - _clipStack.replace(intersectedPath); + pathReplaced = _clipStack.replace(intersectedPath); intersectedPath.writeSVG(oss, SVGTree::RELATIVE_PATH_CMDS); } - - auto pathElem = util::make_unique<XMLElementNode>("path"); - pathElem->addAttribute("d", oss.str()); - if (evenodd) - pathElem->addAttribute("clip-rule", "evenodd"); - - int newID = _clipStack.topID(); - auto clipElem = util::make_unique<XMLElementNode>("clipPath"); - clipElem->addAttribute("id", XMLString("clip")+XMLString(newID)); - if (!COMPUTE_CLIPPATHS_INTERSECTIONS && oldID) - clipElem->addAttribute("clip-path", XMLString("url(#clip")+XMLString(oldID)+")"); - - clipElem->append(std::move(pathElem)); - _actions->appendToDefs(std::move(clipElem)); + if (pathReplaced) { + auto pathElem = util::make_unique<XMLElementNode>("path"); + pathElem->addAttribute("d", oss.str()); + if (evenodd) + pathElem->addAttribute("clip-rule", "evenodd"); + + int newID = _clipStack.topID(); + auto clipElem = util::make_unique<XMLElementNode>("clipPath"); + clipElem->addAttribute("id", XMLString("clip")+XMLString(newID)); + if (!COMPUTE_CLIPPATHS_INTERSECTIONS && oldID) + clipElem->addAttribute("clip-path", XMLString("url(#clip")+XMLString(oldID)+")"); + + clipElem->append(std::move(pathElem)); + _actions->appendToDefs(std::move(clipElem)); + } } @@ -1068,13 +1070,12 @@ void PsSpecialHandler::processLatticeTriangularPatchMesh (ColorSpace colorSpace, } -/** Clears current path */ +/** Clears current path. */ void PsSpecialHandler::newpath (vector<double> &p) { - bool drawing = (p[0] > 0); - if (!drawing || !_clipStack.clippathLoaded()) { - _path.clear(); - _clipStack.setClippathLoaded(false); - } + bool calledByNewpathOp = (p[0] > 0); + if (calledByNewpathOp) // function triggered by PS operator 'newpath'? + _clipStack.removePrependedPath(); + _path.clear(); } @@ -1123,7 +1124,7 @@ void PsSpecialHandler::rotate (vector<double> &p) { void PsSpecialHandler::setgray (vector<double> &p) { - _pattern = 0; + _pattern = nullptr; _currentcolor.setGray(p[0]); if (_actions) _actions->setColor(_currentcolor); @@ -1131,7 +1132,7 @@ void PsSpecialHandler::setgray (vector<double> &p) { void PsSpecialHandler::setrgbcolor (vector<double> &p) { - _pattern= 0; + _pattern= nullptr; _currentcolor.setRGB(p[0], p[1], p[2]); if (_actions) _actions->setColor(_currentcolor); @@ -1139,7 +1140,7 @@ void PsSpecialHandler::setrgbcolor (vector<double> &p) { void PsSpecialHandler::setcmykcolor (vector<double> &p) { - _pattern = 0; + _pattern = nullptr; _currentcolor.setCMYK(p[0], p[1], p[2], p[3]); if (_actions) _actions->setColor(_currentcolor); @@ -1147,7 +1148,7 @@ void PsSpecialHandler::setcmykcolor (vector<double> &p) { void PsSpecialHandler::sethsbcolor (vector<double> &p) { - _pattern = 0; + _pattern = nullptr; _currentcolor.setHSB(p[0], p[1], p[2]); if (_actions) _actions->setColor(_currentcolor); @@ -1179,10 +1180,14 @@ void PsSpecialHandler::ClippingStack::pushEmptyPath () { void PsSpecialHandler::ClippingStack::push (const Path &path, int saveID) { + shared_ptr<Path> prependedPath; + if (!_stack.empty()) + prependedPath = _stack.top().prependedPath; if (path.empty()) _stack.emplace(Entry(saveID)); else _stack.emplace(Entry(path, ++_maxID, saveID)); + _stack.top().prependedPath = prependedPath; } @@ -1218,21 +1223,20 @@ void PsSpecialHandler::ClippingStack::pop (int saveID, bool grestoreall) { /** Returns a pointer to the path on top of the stack, or 0 if the stack is empty. */ -const PsSpecialHandler::Path* PsSpecialHandler::ClippingStack::top () const { +const PsSpecialHandler::Path* PsSpecialHandler::ClippingStack::path () const { return _stack.empty() ? nullptr : _stack.top().path.get(); } -/** Returns true if the clipping path was loaded into the graphics path (via PS operator 'clippath') */ -bool PsSpecialHandler::ClippingStack::clippathLoaded () const { - return !_stack.empty() && _stack.top().cpathLoaded; +/** Returns a pointer to the path on top of the stack, or 0 if the stack is empty. */ +const PsSpecialHandler::Path* PsSpecialHandler::ClippingStack::prependedPath () const { + return _stack.empty() ? nullptr : _stack.top().prependedPath.get(); } -void PsSpecialHandler::ClippingStack::setClippathLoaded (bool loaded) { - if (_stack.empty()) - return; - _stack.top().cpathLoaded = loaded; +void PsSpecialHandler::ClippingStack::removePrependedPath () { + if (!_stack.empty()) + _stack.top().prependedPath = nullptr; } @@ -1243,15 +1247,19 @@ void PsSpecialHandler::ClippingStack::clear() { } -/** Replaces the top element by a new one. - * @param[in] path new path to be on top of the stack */ -void PsSpecialHandler::ClippingStack::replace (const Path &path) { +/** Replaces the top path by a new one. + * @param[in] path new path to put on the stack + * @return true if the new path differs from the previous one */ +bool PsSpecialHandler::ClippingStack::replace (const Path &path) { if (_stack.empty()) push(path, -1); + else if (_stack.top().path && path == *_stack.top().path) + return false; else { _stack.top().path = make_shared<Path>(path); _stack.top().pathID = ++_maxID; } + return true; } @@ -1262,6 +1270,12 @@ void PsSpecialHandler::ClippingStack::dup (int saveID) { } +void PsSpecialHandler::ClippingStack::setPrependedPath () { + if (!_stack.empty()) + _stack.top().prependedPath = _stack.top().path; +} + + vector<const char*> PsSpecialHandler::prefixes() const { vector<const char*> pfx { "header=", // read and execute PS header file prior to the following PS statements |