00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef GNASH_GEOMETRY_H
00020 #define GNASH_GEOMETRY_H
00021
00022 #include "dsodefs.h"
00023 #include "SWFMatrix.h"
00024 #include "SWFRect.h"
00025 #include "Point2d.h"
00026
00027 #include <vector>
00028 #include <cmath>
00029
00030
00031
00032 namespace gnash {
00033 class LineStyle;
00034 }
00035
00036 namespace gnash {
00037
00043 class Edge
00044 {
00045 public:
00046
00047
00048 point cp;
00049 point ap;
00050
00051 Edge()
00052 :
00053 cp(0, 0),
00054 ap(0, 0)
00055 {}
00056
00057 Edge(boost::int32_t cx, boost::int32_t cy, boost::int32_t ax,
00058 boost::int32_t ay)
00059 :
00060 cp(cx, cy),
00061 ap(ax, ay)
00062 {}
00063
00064 Edge(const Edge& from)
00065 :
00066 cp(from.cp),
00067 ap(from.ap)
00068 {}
00069
00070 Edge(const point& ncp, const point& nap)
00071 :
00072 cp(ncp),
00073 ap(nap)
00074 {}
00075
00076 bool straight() const
00077 {
00078 return cp == ap;
00079 }
00080
00082 void transform(const SWFMatrix& mat)
00083 {
00084 mat.transform(ap);
00085 mat.transform(cp);
00086 }
00087
00089 static double
00090 squareDistancePtSeg(const point& p, const point& A, const point& B)
00091 {
00092 boost::int32_t dx = B.x - A.x;
00093 boost::int32_t dy = B.y - A.y;
00094
00095 if ( dx == 0 && dy == 0 )
00096 {
00097 return p.squareDistance(A);
00098 }
00099
00100 boost::int32_t pdx = p.x - A.x;
00101 boost::int32_t pdy = p.y - A.y;
00102
00103 double u = (static_cast<double>(pdx) * dx + static_cast<double>(pdy) * dy ) /
00104 (static_cast<double>(dx)*dx + static_cast<double>(dy)*dy );
00105
00106 if (u <= 0)
00107 {
00108 return p.squareDistance(A);
00109 }
00110
00111 if (u >= 1)
00112 {
00113 return p.squareDistance(B);
00114 }
00115
00116 point px(A, B, u);
00117 return p.squareDistance(px);
00118 }
00119
00121 static double
00122 distancePtSeg(const point& pt, const point& A, const point& B)
00123 {
00124 double square = squareDistancePtSeg(pt, A, B);
00125 return std::sqrt(square);
00126 }
00127
00129
00136
00137 static point
00138 pointOnCurve(const point& A, const point& C, const point& B, float t)
00139 {
00140 point Q1(A, C, t);
00141 point Q2(C, B, t);
00142 point R(Q1, Q2, t);
00143
00144 return R;
00145 }
00146
00149
00156 static boost::int64_t squareDistancePtCurve(const point& A,
00157 const point& C,
00158 const point& B,
00159 const point& p, float t)
00160 {
00161 return p.squareDistance( pointOnCurve(A, C, B, t) );
00162 }
00163 };
00164
00165
00167 class DSOEXPORT Path
00168 {
00169 public:
00171 unsigned m_fill0;
00172
00174 unsigned m_fill1;
00175
00177 unsigned m_line;
00178
00180 point ap;
00181
00183 std::vector<Edge> m_edges;
00184
00189 bool m_new_shape;
00190
00192
00196 Path(bool newShape = false)
00197 :
00198 m_new_shape(newShape)
00199 {
00200 reset(0, 0, 0, 0, 0);
00201 }
00202
00203 Path(const Path& from)
00204 :
00205 m_fill0(from.m_fill0),
00206 m_fill1(from.m_fill1),
00207 m_line(from.m_line),
00208 ap(from.ap),
00209 m_edges(from.m_edges),
00210 m_new_shape(from.m_new_shape)
00211 {
00212 }
00213
00215
00236 Path(boost::int32_t ax, boost::int32_t ay,
00237 unsigned fill0, unsigned fill1, unsigned line,
00238 bool newShape)
00239 :
00240 m_new_shape(newShape)
00241 {
00242 reset(ax, ay, fill0, fill1, line);
00243 }
00244
00246
00258
00262 void reset(boost::int32_t ax, boost::int32_t ay,
00263 unsigned fill0, unsigned fill1, unsigned line)
00264
00265 {
00266 ap.x = ax;
00267 ap.y = ay;
00268 m_fill0 = fill0;
00269 m_fill1 = fill1;
00270 m_line = line;
00271
00272 m_edges.resize(0);
00273 assert(empty());
00274 }
00275
00277
00289 void
00290 expandBounds(SWFRect& r, unsigned int thickness, int swfVersion) const
00291 {
00292 const Path& p = *this;
00293 size_t nedges = m_edges.size();
00294
00295 if ( ! nedges ) return;
00296
00297 if (thickness)
00298 {
00299
00300
00301
00302 unsigned int radius = swfVersion < 8 ? thickness : thickness/2;
00303
00304 r.expand_to_circle(ap.x, ap.y, radius);
00305 for (unsigned int j = 0; j<nedges; j++)
00306 {
00307 r.expand_to_circle(m_edges[j].ap.x, m_edges[j].ap.y, radius);
00308 r.expand_to_circle(m_edges[j].cp.x, m_edges[j].cp.y, radius);
00309 }
00310 }
00311 else
00312 {
00313 r.expand_to_point(ap.x, ap.y);
00314 for (unsigned int j = 0; j<nedges; j++)
00315 {
00316 r.expand_to_point(m_edges[j].ap.x, p.m_edges[j].ap.y);
00317 r.expand_to_point(m_edges[j].cp.x, p.m_edges[j].cp.y);
00318 }
00319 }
00320 }
00321
00326
00328
00338 void
00339 drawLineTo(boost::int32_t dx, boost::int32_t dy)
00340 {
00341 m_edges.push_back(Edge(dx, dy, dx, dy));
00342 }
00343
00345
00361 void
00362 drawCurveTo(boost::int32_t cdx, boost::int32_t cdy, boost::int32_t adx, boost::int32_t ady)
00363 {
00364 m_edges.push_back(Edge(cdx, cdy, adx, ady));
00365 }
00366
00368 void clear()
00369 {
00370 m_edges.resize(0);
00371 m_fill0 = m_fill1 = m_line = 0;
00372 }
00373
00375
00376
00378 bool isClosed() const
00379 {
00380 if (m_edges.empty()) return true;
00381 return m_edges.back().ap == ap;
00382 }
00383
00385 void close()
00386 {
00387 if ( m_edges.empty() ) return;
00388
00389
00390 const Edge& lastedge = m_edges.back();
00391 if ( lastedge.ap != ap )
00392 {
00393 Edge newedge(ap, ap);
00394 m_edges.push_back(newedge);
00395 }
00396 }
00397
00401
00404 bool
00405 withinSquareDistance(const point& p, double dist) const
00406 {
00407 size_t nedges = m_edges.size();
00408
00409 if ( ! nedges ) return false;
00410
00411 point px(ap);
00412 for (size_t i=0; i<nedges; ++i)
00413 {
00414 const Edge& e = m_edges[i];
00415 point np(e.ap);
00416
00417 if (e.straight())
00418 {
00419 double d = Edge::squareDistancePtSeg(p, px, np);
00420 if ( d <= dist ) return true;
00421 }
00422 else
00423 {
00424
00425 const point& A = px;
00426 const point& C = e.cp;
00427 const point& B = e.ap;
00428
00429
00430
00431
00432
00433
00434
00435
00436 int segCount = 10;
00437 point p0(A.x, A.y);
00438 for (int i=1; i<=segCount; ++i)
00439 {
00440 float t1 = static_cast<float>(i) / segCount;
00441 point p1 = Edge::pointOnCurve(A, C, B, t1);
00442
00443
00444
00445 double d = Edge::squareDistancePtSeg(p, p0, p1);
00446 if ( d <= dist ) return true;
00447
00448 p0.setTo(p1.x, p1.y);
00449 }
00450 }
00451 px = np;
00452 }
00453
00454 return false;
00455 }
00456
00458 void transform(const SWFMatrix& mat)
00459 {
00460 mat.transform(ap);
00461 std::vector<Edge>::iterator it = m_edges.begin(), ie = m_edges.end();
00462 for(; it != ie; it++)
00463 {
00464 (*it).transform(mat);
00465 }
00466 }
00467
00469 void setNewShape()
00470 {
00471 m_new_shape=true;
00472 }
00473
00475 bool getNewShape() const
00476 {
00477 return m_new_shape;
00478 }
00479
00481 bool empty() const
00482 {
00483 return m_edges.empty();
00484 }
00485
00487
00495 void setLeftFill(unsigned f)
00496 {
00497 m_fill0 = f;
00498 }
00499
00500 unsigned getLeftFill() const
00501 {
00502 return m_fill0;
00503 }
00504
00506
00514 void setRightFill(unsigned f)
00515 {
00516 m_fill1 = f;
00517 }
00518
00519 unsigned getRightFill() const
00520 {
00521 return m_fill1;
00522 }
00523
00525
00533 void setLineStyle(unsigned i)
00534 {
00535 m_line = i;
00536 }
00537
00538 unsigned getLineStyle() const
00539 {
00540 return m_line;
00541 }
00542
00544 size_t size() const
00545 {
00546 return m_edges.size();
00547 }
00548
00550 Edge& operator[] (size_t n)
00551 {
00552 return m_edges[n];
00553 }
00554
00556 const Edge& operator[] (size_t n) const
00557 {
00558 return m_edges[n];
00559 }
00560
00562 bool isNewShape() const
00563 {
00564 return m_new_shape;
00565 }
00566
00567 };
00568
00569 namespace geometry
00570 {
00571
00572 bool pointTest(const std::vector<Path>& paths,
00573 const std::vector<LineStyle>& lineStyles, boost::int32_t x,
00574 boost::int32_t y, const SWFMatrix& wm);
00575
00576 }
00577
00578
00579 }
00580
00581 #endif // GNASH_GEOMETRY_H
00582
00583
00584
00585
00586
00587
00588
00589