1 // bounds.h
2 // this file is part of Context Free
3 // ---------------------
4 // Copyright (C) 2006-2007 Mark Lentczner - markl@glyphic.com
5 // Copyright (C) 2006-2013 John Horigan - john@glyphic.com
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License
9 // as published by the Free Software Foundation; either version 2
10 // of the License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 //
21 // John Horigan can be contacted at john@glyphic.com or at
22 // John Horigan, 1209 Villa St., Mountain View, CA 94041-1123, USA
23 //
24 // Mark Lentczner can be contacted at markl@glyphic.com or at
25 // Mark Lentczner, 1209 Villa St., Mountain View, CA 94041-1123, USA
26 //
27 //
28 
29 
30 #ifndef INCLUDE_BOUNDS_H
31 #define INCLUDE_BOUNDS_H
32 
33 #include "agg2/agg_path_storage.h"
34 #include <limits>
35 #include <cmath>
36 
37 namespace agg { struct trans_affine; }
38 namespace AST {
39     class ASTpathCommand;
40     struct CommandInfo;
41 }
42 class pathIterator;
43 
44 class Bounds {
45     public:
Bounds()46         Bounds() : mMin_X(std::numeric_limits<double>::infinity()) {}
47 
48         Bounds(const agg::trans_affine& trans, pathIterator& helper,
49                double scale, const AST::CommandInfo& attr);
50                 // set bounds to be the bounds of this shape, transformed
51 
valid()52         bool valid() const { return std::isfinite(mMin_X) && std::isfinite(mMax_X) &&
53                                     std::isfinite(mMin_Y) && std::isfinite(mMax_Y); }
invalidate()54         void invalidate() { mMin_X = std::numeric_limits<double>::infinity(); }
55 
56         Bounds dilate(double dilation) const;
57 
merge(const Bounds & b)58         void merge(const Bounds& b)
59             // merge the other bounds into this bounds
60         {
61             if (valid() && b.valid()) {
62                 if (b.mMin_X < mMin_X) mMin_X = b.mMin_X;
63                 if (b.mMax_X > mMax_X) mMax_X = b.mMax_X;
64                 if (b.mMin_Y < mMin_Y) mMin_Y = b.mMin_Y;
65                 if (b.mMax_Y > mMax_Y) mMax_Y = b.mMax_Y;
66             } else if (b.valid()) {
67                 *this = b;
68             }
69         }
70 
merge(double x,double y)71         void merge(double x, double y)
72         // merge a point into this bounds
73         {
74             if (valid()) {
75                 if (x < mMin_X) mMin_X = x;
76                 if (x > mMax_X) mMax_X = x;
77                 if (y < mMin_Y) mMin_Y = y;
78                 if (y > mMax_Y) mMax_Y = y;
79             } else {
80                 mMin_X = mMax_X = x;
81                 mMin_Y = mMax_Y = y;
82             }
83         }
84 
merge(const agg::point_d & p)85         void merge(const agg::point_d& p) { merge(p.x, p.y); }
86         // merge a point into this bounds
87 
88         Bounds operator+(const Bounds& other) const
89         { Bounds t(*this); t.merge(other); return t; }
90 
91         Bounds& operator+=(const Bounds& other)
92         { merge(other); return *this; }
93 
94         Bounds operator+(const agg::point_d& p) const
95         { Bounds t(*this); t.merge(p); return t; }
96 
97         Bounds& operator+=(const agg::point_d& p)
98         { merge(p); return *this; }
99 
100         Bounds interpolate(const Bounds& other, double alpha) const;
101         // compute the interpolation between this bounds and the other
102         // an alpha of 0.0 has no effect, an alpha of 1.0 give the other
103         Bounds slewCenter(const Bounds& other, double alpha) const;
104         // compute a new bounds who's center is slewed alpha of the way
105         // toward the other center, yet incorporates all of the current
106         // bounds
107 
108         double computeScale(int& width, int& height, double borderX, double borderY,
109                             bool modify = false, agg::trans_affine* trans = nullptr,
110                             bool exact = false) const;
111         // Computes the scale factor of fitting this bounds into a canvas
112         // of the given width and height, with the provided fixed border.
113         // If modify is true, width and height are reset to the scaled size.
114         // If trans isn't null, it is set to the needed transformation.
115         // If exact is true then the diensions are not bumped to preserve parity.
116 
117         void gather(const Bounds& other, double weight);
118 
119         void update(const agg::trans_affine& trns, pathIterator& helper,
120                     double scale, const AST::CommandInfo& attr);
121 
overlaps(const Bounds & other)122         bool overlaps(const Bounds& other) const
123         {
124             return !(other.mMin_X > mMax_X || other.mMax_X < mMin_X ||
125                      other.mMin_Y > mMax_Y || other.mMax_Y < mMin_Y);
126 
127         }
128 
129         double  mMin_X, mMin_Y, mMax_X, mMax_Y;
130 };
131 
132 #endif // INCLUDE_BOUNDS_H
133