summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvisvgm/dvisvgm-1.9.1/src/BoundingBox.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/dvisvgm/dvisvgm-1.9.1/src/BoundingBox.cpp')
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-1.9.1/src/BoundingBox.cpp263
1 files changed, 263 insertions, 0 deletions
diff --git a/Build/source/texk/dvisvgm/dvisvgm-1.9.1/src/BoundingBox.cpp b/Build/source/texk/dvisvgm/dvisvgm-1.9.1/src/BoundingBox.cpp
new file mode 100644
index 00000000000..3fcde07ba5d
--- /dev/null
+++ b/Build/source/texk/dvisvgm/dvisvgm-1.9.1/src/BoundingBox.cpp
@@ -0,0 +1,263 @@
+/*************************************************************************
+** BoundingBox.cpp **
+** **
+** This file is part of dvisvgm -- the DVI to SVG converter **
+** Copyright (C) 2005-2015 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 **
+** published by the Free Software Foundation; either version 3 of **
+** the License, or (at your option) any later version. **
+** **
+** This program is distributed in the hope that it will be useful, but **
+** WITHOUT ANY WARRANTY; without even the implied warranty of **
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the **
+** GNU General Public License for more details. **
+** **
+** You should have received a copy of the GNU General Public License **
+** along with this program; if not, see <http://www.gnu.org/licenses/>. **
+*************************************************************************/
+
+#include <config.h>
+#include <algorithm>
+#include <sstream>
+#include <string>
+#include "BoundingBox.h"
+#include "Matrix.h"
+#include "XMLNode.h"
+#include "XMLString.h"
+
+using namespace std;
+
+
+BoundingBox::BoundingBox ()
+ : _ulx(0), _uly(0), _lrx(0), _lry(0), _valid(false), _locked(false)
+{
+}
+
+
+BoundingBox::BoundingBox (double ulxx, double ulyy, double lrxx, double lryy)
+ : _ulx(min(ulxx,lrxx)), _uly(min(ulyy,lryy)),
+ _lrx(max(ulxx,lrxx)), _lry(max(ulyy,lryy)),
+ _valid(true), _locked(false)
+{
+}
+
+
+BoundingBox::BoundingBox (const DPair &p1, const DPair &p2)
+ : _ulx(min(p1.x(), p2.x())), _uly(min(p1.y(), p2.y())),
+ _lrx(max(p1.x(), p2.x())), _lry(max(p1.y(), p2.y())),
+ _valid(true), _locked(false)
+{
+}
+
+
+BoundingBox::BoundingBox (const Length &ulxx, const Length &ulyy, const Length &lrxx, const Length &lryy)
+ : _ulx(min(ulxx.pt(),lrxx.pt())), _uly(min(ulyy.pt(),lryy.pt())),
+ _lrx(max(ulxx.pt(),lrxx.pt())), _lry(max(ulyy.pt(),lryy.pt())),
+ _valid(true), _locked(false)
+{
+}
+
+
+BoundingBox::BoundingBox (const string &boxstr)
+ : _ulx(0), _uly(0), _lrx(0), _lry(0), _valid(false), _locked(false)
+{
+ set(boxstr);
+}
+
+
+/** Removes leading and trailing whitespace from the given string. */
+static string& strip (string &str) {
+ size_t n=0;
+ while (n < str.length() && isspace(str[n]))
+ ++n;
+ str.erase(0, n);
+ n=str.length()-1;
+ while (n > 0 && isspace(str[n]))
+ --n;
+ str.erase(n+1);
+ return str;
+}
+
+
+/** Sets or modifies the bounding box. If 'boxstr' consists of 4 length values,
+ * they denote the absolute position of two diagonal corners of the box. In case
+ * of a single length value l the current box is enlarged by adding (-l,-l) the upper
+ * left and (l,l) to the lower right corner.
+ * @param[in] boxstr whitespace and/or comma separated string of lengths. */
+void BoundingBox::set (string boxstr) {
+ vector<Length> coord;
+ const size_t len = boxstr.length();
+ size_t l=0;
+ strip(boxstr);
+ string lenstr;
+ do {
+ while (l < len && isspace(boxstr[l]))
+ l++;
+ size_t r=l;
+ while (r < len && !isspace(boxstr[r]) && boxstr[r] != ',')
+ r++;
+ lenstr = boxstr.substr(l, r-l);
+ if (!lenstr.empty()) {
+ coord.push_back(Length(lenstr));
+ if (boxstr[r] == ',')
+ r++;
+ l = r;
+ }
+ } while (!lenstr.empty() && coord.size() < 4);
+
+ switch (coord.size()) {
+ case 1:
+ _ulx -= coord[0].pt();
+ _uly -= coord[0].pt();
+ _lrx += coord[0].pt();
+ _lry += coord[0].pt();
+ break;
+ case 2:
+ _ulx -= coord[0].pt();
+ _uly -= coord[1].pt();
+ _lrx += coord[0].pt();
+ _lry += coord[1].pt();
+ break;
+ case 4:
+ _ulx = min(coord[0].pt(), coord[2].pt());
+ _uly = min(coord[1].pt(), coord[3].pt());
+ _lrx = max(coord[0].pt(), coord[2].pt());
+ _lry = max(coord[1].pt(), coord[3].pt());
+ break;
+ default:
+ throw BoundingBoxException("1, 2 or 4 length parameters expected");
+ }
+ _valid = true;
+}
+
+
+/** Enlarges the box so that point (x,y) is enclosed. */
+void BoundingBox::embed (double x, double y) {
+ if (!_locked) {
+ if (_valid) {
+ if (x < _ulx)
+ _ulx = x;
+ else if (x > _lrx)
+ _lrx = x;
+ if (y < _uly)
+ _uly = y;
+ else if (y > _lry)
+ _lry = y;
+ }
+ else {
+ _ulx = _lrx = x;
+ _uly = _lry = y;
+ _valid = true;
+ }
+ }
+}
+
+
+/** Enlarges the box so that box bb is enclosed. */
+void BoundingBox::embed (const BoundingBox &bb) {
+ if (!_locked && bb._valid) {
+ if (_valid) {
+ embed(bb._ulx, bb._uly);
+ embed(bb._lrx, bb._lry);
+ }
+ else {
+ _ulx = bb._ulx;
+ _uly = bb._uly;
+ _lrx = bb._lrx;
+ _lry = bb._lry;
+ _valid = true;
+ }
+ }
+}
+
+
+void BoundingBox::embed (const DPair &c, double r) {
+ embed(BoundingBox(c.x()-r, c.y()-r, c.x()+r, c.y()+r));
+}
+
+
+void BoundingBox::expand (double m) {
+ if (!_locked) {
+ _ulx -= m;
+ _uly -= m;
+ _lrx += m;
+ _lry += m;
+ }
+}
+
+
+/** Intersects the current box with bbox and applies the result to *this.
+ * If both boxes are disjoint, *this is not altered.
+ * @param[in] bbox box to intersect with
+ * @return false if *this is locked or both boxes are disjoint */
+bool BoundingBox::intersect (const BoundingBox &bbox) {
+ if (_locked || _lrx < bbox._ulx || _lry < bbox._uly || _ulx > bbox._lrx || _uly > bbox._lry)
+ return false;
+ _ulx = max(_ulx, bbox._ulx);
+ _uly = max(_uly, bbox._uly);
+ _lrx = min(_lrx, bbox._lrx);
+ _lry = min(_lry, bbox._lry);
+ return true;
+}
+
+
+void BoundingBox::operator += (const BoundingBox &bb) {
+ if (!_locked) {
+ _ulx += bb._ulx;
+ _uly += bb._uly;
+ _lrx += bb._lrx;
+ _lry += bb._lry;
+ }
+}
+
+
+void BoundingBox::scale (double sx, double sy) {
+ if (!_locked) {
+ _ulx *= sx;
+ _lrx *= sx;
+ if (sx < 0) swap(_ulx, _lrx);
+ _uly *= sy;
+ _lry *= sy;
+ if (sy < 0) swap(_uly, _lry);
+ }
+}
+
+
+void BoundingBox::transform (const Matrix &tm) {
+ if (!_locked) {
+ DPair ul = tm * DPair(_lrx, _lry);
+ DPair lr = tm * DPair(_ulx, _uly);
+ DPair ll = tm * DPair(_ulx, _lry);
+ DPair ur = tm * DPair(_lrx, _uly);
+ _ulx = min(min(ul.x(), lr.x()), min(ur.x(), ll.x()));
+ _uly = min(min(ul.y(), lr.y()), min(ur.y(), ll.y()));
+ _lrx = max(max(ul.x(), lr.x()), max(ur.x(), ll.x()));
+ _lry = max(max(ul.y(), lr.y()), max(ur.y(), ll.y()));
+ }
+}
+
+
+string BoundingBox::toSVGViewBox () const {
+ ostringstream oss;
+ oss << XMLString(_ulx) << ' ' << XMLString(_uly) << ' ' << XMLString(width()) << ' ' << XMLString(height());
+ return oss.str();
+}
+
+
+ostream& BoundingBox::write (ostream &os) const {
+ return os << '(' << _ulx << ", " << _uly
+ << ", " << _lrx << ", " << _lry << ')';
+}
+
+
+XMLElementNode* BoundingBox::toSVGRect () const {
+ XMLElementNode *rect = new XMLElementNode("rect");
+ rect->addAttribute("x", minX());
+ rect->addAttribute("y", minY());
+ rect->addAttribute("width", width());
+ rect->addAttribute("height", height());
+ rect->addAttribute("fill", "none");
+ return rect;
+}