Gnash  0.8.11dev
Geometry.h
Go to the documentation of this file.
1 //
2 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
3 // Free Software Foundation, Inc
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 //
19 
20 #ifndef GNASH_GEOMETRY_H
21 #define GNASH_GEOMETRY_H
22 
23 #include "dsodefs.h"
24 #include "SWFMatrix.h"
25 #include "SWFRect.h"
26 #include "Point2d.h"
27 
28 #include <vector> // for path composition
29 #include <cmath> // sqrt
30 
31 
32 // Forward declarations
33 namespace gnash {
34  class LineStyle;
35 }
36 
37 namespace gnash {
38 
44 class Edge
45 {
46 public:
47 
48  // Quadratic bezier: point = p0 * t^2 + p1 * 2t(1-t) + p2 * (1-t)^2
49  point cp; // control point, TWIPS
50  point ap; // anchor point, TWIPS
51 
52  constexpr Edge()
53  :
54  cp(0, 0),
55  ap(0, 0)
56  {}
57 
58  constexpr Edge(std::int32_t cx, std::int32_t cy, std::int32_t ax,
59  std::int32_t ay)
60  :
61  cp(cx, cy),
62  ap(ax, ay)
63  {}
64 
65  constexpr Edge(const Edge& from)
66  :
67  cp(from.cp),
68  ap(from.ap)
69  {}
70 
71  constexpr Edge(const point& ncp, const point& nap)
72  :
73  cp(ncp),
74  ap(nap)
75  {}
76 
77  bool straight() const
78  {
79  return cp == ap;
80  }
81 
83  void transform(const SWFMatrix& mat)
84  {
85  mat.transform(ap);
86  mat.transform(cp);
87  }
88 
90  static double
91  squareDistancePtSeg(const point& p, const point& A, const point& B)
92  {
93  std::int32_t dx = B.x - A.x;
94  std::int32_t dy = B.y - A.y;
95 
96  if ( dx == 0 && dy == 0 )
97  {
98  return p.squareDistance(A);
99  }
100 
101  std::int32_t pdx = p.x - A.x;
102  std::int32_t pdy = p.y - A.y;
103 
104  double u = (static_cast<double>(pdx) * dx + static_cast<double>(pdy) * dy ) /
105  (static_cast<double>(dx)*dx + static_cast<double>(dy)*dy );
106 
107  if (u <= 0)
108  {
109  return p.squareDistance(A);
110  }
111 
112  if (u >= 1)
113  {
114  return p.squareDistance(B);
115  }
116 
117  point px(A, B, u); // FIXME: this interpolation introduce a precision loss (point is int-based)
118  return p.squareDistance(px);
119  }
120 
122  static double
123  distancePtSeg(const point& pt, const point& A, const point& B)
124  {
125  const double square = squareDistancePtSeg(pt, A, B);
126  return std::sqrt(square);
127  }
128 
130  //
136  static point
137  pointOnCurve(const point& A, const point& C, const point& B, float t)
138  {
139  point Q1(A, C, t);
140  point Q2(C, B, t);
141  point R(Q1, Q2, t);
142 
143  return R;
144  }
145 
148  //
155  static std::int64_t squareDistancePtCurve(const point& A,
156  const point& C,
157  const point& B,
158  const point& p, float t)
159  {
160  return p.squareDistance( pointOnCurve(A, C, B, t) );
161  }
162 };
163 
164 
167 {
168 public:
170  unsigned m_fill0;
171 
173  unsigned m_fill1;
174 
176  unsigned m_line;
177 
180 
182  std::vector<Edge> m_edges;
183 
188 
190  //
192  {
193  reset(0, 0, 0, 0, 0);
194  }
195 
196  Path(const Path& from)
197  :
198  m_fill0(from.m_fill0),
199  m_fill1(from.m_fill1),
200  m_line(from.m_line),
201  ap(from.ap),
202  m_edges(from.m_edges)
203  {
204  }
205 
207  //
225  Path(std::int32_t ax, std::int32_t ay,
226  unsigned fill0, unsigned fill1, unsigned line)
227  {
228  reset(ax, ay, fill0, fill1, line);
229  }
230 
232  //
244  //
248  void reset(std::int32_t ax, std::int32_t ay,
249  unsigned fill0, unsigned fill1, unsigned line)
250  // Reset all our members to the given values, and clear our edge list.
251  {
252  ap.x = ax;
253  ap.y = ay;
254  m_fill0 = fill0;
255  m_fill1 = fill1;
256  m_line = line;
257 
258  m_edges.resize(0);
259  assert(empty());
260  }
261 
263  //
275  void
276  expandBounds(SWFRect& r, unsigned int thickness, int swfVersion) const
277  {
278  const Path& p = *this;
279  size_t nedges = m_edges.size();
280 
281  if ( ! nedges ) return; // this path adds nothing
282 
283  if (thickness)
284  {
285  // NOTE: Half of thickness would be enough (and correct) for
286  // radius, but that would not match how Flash calculates the
287  // bounds using the drawing API.
288  unsigned int radius = swfVersion < 8 ? thickness : thickness/2;
289 
290  r.expand_to_circle(ap.x, ap.y, radius);
291  for (unsigned int j = 0; j<nedges; j++)
292  {
293  r.expand_to_circle(m_edges[j].ap.x, m_edges[j].ap.y, radius);
294  r.expand_to_circle(m_edges[j].cp.x, m_edges[j].cp.y, radius);
295  }
296  }
297  else
298  {
299  r.expand_to_point(ap.x, ap.y);
300  for (unsigned int j = 0; j<nedges; j++)
301  {
302  r.expand_to_point(m_edges[j].ap.x, p.m_edges[j].ap.y);
303  r.expand_to_point(m_edges[j].cp.x, p.m_edges[j].cp.y);
304  }
305  }
306  }
307 
312 
314  //
324  void
325  drawLineTo(std::int32_t dx, std::int32_t dy)
326  {
327  m_edges.emplace_back(dx, dy, dx, dy);
328  }
329 
331  //
347  void
348  drawCurveTo(std::int32_t cdx, std::int32_t cdy, std::int32_t adx, std::int32_t ady)
349  {
350  m_edges.emplace_back(cdx, cdy, adx, ady);
351  }
352 
354  void clear()
355  {
356  m_edges.resize(0);
357  m_fill0 = m_fill1 = m_line = 0;
358  }
359 
361 
362 
364  bool isClosed() const
365  {
366  if (m_edges.empty()) return true;
367  return m_edges.back().ap == ap;
368  }
369 
371  void close()
372  {
373  if ( m_edges.empty() ) return;
374 
375  // Close it with a straight edge if needed
376  const Edge& lastedge = m_edges.back();
377  if ( lastedge.ap != ap )
378  {
379  m_edges.emplace_back(ap, ap);
380  }
381  }
382 
386  //
389  bool
390  withinSquareDistance(const point& p, double dist) const
391  {
392  size_t nedges = m_edges.size();
393 
394  if ( ! nedges ) return false;
395 
396  point px(ap);
397  for (size_t i=0; i<nedges; ++i)
398  {
399  const Edge& e = m_edges[i];
400  point np(e.ap);
401 
402  if (e.straight())
403  {
404  double d = Edge::squareDistancePtSeg(p, px, np);
405  if ( d <= dist ) return true;
406  }
407  else
408  {
409 
410  const point& A = px;
411  const point& C = e.cp;
412  const point& B = e.ap;
413 
414  // Approximate the curve to segCount segments
415  // and compute distance of query point from each
416  // segment.
417  //
418  // TODO: find an apprpriate value for segCount based
419  // on rendering scale ?
420  //
421  int segCount = 10;
422  point p0(A.x, A.y);
423  for (int i=1; i<=segCount; ++i)
424  {
425  float t1 = static_cast<float>(i) / segCount;
426  point p1 = Edge::pointOnCurve(A, C, B, t1);
427 
428  // distance from point and segment being an approximation
429  // of the curve
430  double d = Edge::squareDistancePtSeg(p, p0, p1);
431  if ( d <= dist ) return true;
432 
433  p0.setTo(p1.x, p1.y);
434  }
435  }
436  px = np;
437  }
438 
439  return false;
440  }
441 
443  void transform(const SWFMatrix& mat)
444  {
445  mat.transform(ap);
446  std::vector<Edge>::iterator it = m_edges.begin(), ie = m_edges.end();
447  for(; it != ie; ++it)
448  {
449  (*it).transform(mat);
450  }
451  }
452 
454  bool empty() const
455  {
456  return m_edges.empty();
457  }
458 
460  //
468  void setLeftFill(unsigned f)
469  {
470  m_fill0 = f;
471  }
472 
473  unsigned getLeftFill() const
474  {
475  return m_fill0;
476  }
477 
479  //
487  void setRightFill(unsigned f)
488  {
489  m_fill1 = f;
490  }
491 
492  unsigned getRightFill() const
493  {
494  return m_fill1;
495  }
496 
498  //
506  void setLineStyle(unsigned i)
507  {
508  m_line = i;
509  }
510 
511  unsigned getLineStyle() const
512  {
513  return m_line;
514  }
515 
517  size_t size() const
518  {
519  return m_edges.size();
520  }
521 
523  Edge& operator[] (size_t n)
524  {
525  return m_edges[n];
526  }
527 
529  const Edge& operator[] (size_t n) const
530  {
531  return m_edges[n];
532  }
533 }; // end of class Path
534 
535 namespace geometry
536 {
537 
538 bool pointTest(const std::vector<Path>& paths,
539  const std::vector<LineStyle>& lineStyles, std::int32_t x,
540  std::int32_t y, const SWFMatrix& wm);
541 
542 } // namespace geometry
543 
544 
545 } // namespace gnash
546 
547 #endif // GNASH_GEOMETRY_H
548 
549 
550 // Local Variables:
551 // mode: C++
552 // c-basic-offset: 8
553 // tab-width: 8
554 // indent-tabs-mode: t
555 // End:
static double squareDistancePtSeg(const point &p, const point &A, const point &B)
Return squared distance between point pt and segment A-B.
Definition: Geometry.h:91
bool empty() const
Return true if this path contains no edges.
Definition: Geometry.h:454
Definition: GnashKey.h:150
Path(const Path &from)
Definition: Geometry.h:196
unsigned getRightFill() const
Definition: Geometry.h:492
void transform(const SWFMatrix &mat)
Transform the edge according to the given SWFMatrix.
Definition: Geometry.h:83
void transform(geometry::Point2d &p) const
Transform a given point by our SWFMatrix.
Definition: SWFMatrix.cpp:99
Definition: SWFMatrix.h:53
Definition: GnashKey.h:114
Definition: GnashKey.h:167
point cp
Definition: Geometry.h:49
constexpr Edge()
Definition: Geometry.h:52
Anonymous namespace for callbacks, local functions, event handlers etc.
Definition: dbus_ext.cpp:40
Point2d & setTo(const std::int32_t cx, const std::int32_t cy)
Set coordinates to given values.
Definition: Point2d.h:79
constexpr Edge(std::int32_t cx, std::int32_t cy, std::int32_t ax, std::int32_t ay)
Definition: Geometry.h:58
bool pointTest(const std::vector< Path > &paths, const std::vector< LineStyle > &lineStyles, std::int32_t x, std::int32_t y, const SWFMatrix &wm)
Definition: Geometry.cpp:125
2D Point class
Definition: Point2d.h:38
Definition: GnashKey.h:152
void transform(const SWFMatrix &mat)
Transform all path coordinates according to the given SWFMatrix.
Definition: Geometry.h:443
void expand_to_point(std::int32_t x, std::int32_t y)
Expand this rectangle to enclose the given point.
Definition: SWFRect.h:171
Definition: GnashKey.h:115
bool isClosed() const
Returns true if the last and the first point of the path match.
Definition: Geometry.h:364
Definition: GnashKey.h:156
static double distancePtSeg(const point &pt, const point &A, const point &B)
Return distance between point pt and segment A-B.
Definition: Geometry.h:123
unsigned getLineStyle() const
Definition: Geometry.h:511
Definition: GnashKey.h:160
Definition: GnashKey.h:164
void setLeftFill(unsigned f)
Set the fill to use on the left side.
Definition: Geometry.h:468
Definition: GnashKey.h:166
unsigned m_fill1
Right fill style index (1-based)
Definition: Geometry.h:173
constexpr Edge(const Edge &from)
Definition: Geometry.h:65
std::int32_t y
The y coordinate.
Definition: Point2d.h:46
static point pointOnCurve(const point &A, const point &C, const point &B, float t)
Find point of the quadratic curve defined by points A,C,B.
Definition: Geometry.h:137
A subset of a shape, a series of edges sharing a single set of styles.
Definition: Geometry.h:166
unsigned m_fill0
Left fill style index (1-based)
Definition: Geometry.h:170
std::vector< Edge > m_edges
Edges forming the path.
Definition: Geometry.h:182
unsigned getLeftFill() const
Definition: Geometry.h:473
std::int32_t x
Definition: BitmapData_as.cpp:434
bool withinSquareDistance(const point &p, double dist) const
Return true if the given point is within the given squared distance from this path edges...
Definition: Geometry.h:390
Definition: GnashKey.h:130
#define DSOEXPORT
Definition: dsodefs.h:55
void setLineStyle(unsigned i)
Set the line style to use for this path.
Definition: Geometry.h:506
std::int32_t x
The x coordinate.
Definition: Point2d.h:43
static std::int64_t squareDistancePtCurve(const point &A, const point &C, const point &B, const point &p, float t)
Definition: Geometry.h:155
unsigned m_line
Line style index (1-based)
Definition: Geometry.h:176
constexpr Edge(const point &ncp, const point &nap)
Definition: Geometry.h:71
bool straight() const
Definition: Geometry.h:77
std::int32_t y
Definition: BitmapData_as.cpp:435
void expandBounds(SWFRect &r, unsigned int thickness, int swfVersion) const
Expand given SWFRect to include bounds of this path.
Definition: Geometry.h:276
Rectangle class, see swf defined rectangle record.
Definition: SWFRect.h:44
void reset(std::int32_t ax, std::int32_t ay, unsigned fill0, unsigned fill1, unsigned line)
Re-initialize a path, maintaining the "new shape" flag untouched.
Definition: Geometry.h:248
Definition: GnashKey.h:162
Definition: GnashKey.h:155
Definition: GnashKey.h:151
void drawCurveTo(std::int32_t cdx, std::int32_t cdy, std::int32_t adx, std::int32_t ady)
Draw a curve.
Definition: Geometry.h:348
Defines an edge with a control point and an anchor point.
Definition: Geometry.h:44
void expand_to_circle(std::int32_t x, std::int32_t y, std::int32_t radius)
Expand this rectangle to enclose the given circle.
Definition: SWFRect.h:186
void clear()
Remove all edges and reset style infomation.
Definition: Geometry.h:354
point ap
Definition: Geometry.h:50
Definition: GnashKey.h:113
point ap
Start point of the path.
Definition: Geometry.h:179
size_t size() const
Return the number of edges in this path.
Definition: Geometry.h:517
Path()
Default constructor.
Definition: Geometry.h:191
static std::int64_t squareDistance(const Point2d &p0, const Point2d &p1)
Return square distance between two given points.
Definition: Point2d.h:103
void close()
Close this path with a straight line, if not already closed.
Definition: Geometry.h:371
void setRightFill(unsigned f)
Set the fill to use on the left side.
Definition: Geometry.h:487
Path(std::int32_t ax, std::int32_t ay, unsigned fill0, unsigned fill1, unsigned line)
Initialize a path.
Definition: Geometry.h:225
void drawLineTo(std::int32_t dx, std::int32_t dy)
Draw a straight line.
Definition: Geometry.h:325