2 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
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.
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.
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
20 #include <boost/utility.hpp>
21 #include "PathParser.h"
23 #include <boost/bind.hpp>
30 UnivocalPath::startPoint() const
32 return _fill_type
== FILL_LEFT
? _path
->ap
: _path
->m_edges
.back().ap
;
36 UnivocalPath::endPoint() const
38 return _fill_type
== FILL_LEFT
? _path
->m_edges
.back().ap
: _path
->ap
;
41 PathParser::PathParser(const std::vector
<Path
>& paths
, size_t numstyles
)
43 _num_styles(numstyles
),
49 PathParser::run(const SWFCxForm
& cx
, const SWFMatrix
& /*mat*/)
51 // Since we frequently remove an element from the front or the back, we use
52 // a double ended queue here.
53 typedef std::deque
<UnivocalPath
> UniPathList
;
55 std::vector
<UniPathList
> unipathvec(_num_styles
);
57 for (size_t i
= 0; i
< _paths
.size(); ++i
) {
59 if (_paths
[i
].empty()) {
63 int leftfill
= _paths
[i
].getLeftFill();
65 unipathvec
[leftfill
-1].push_front(UnivocalPath(&_paths
[i
], UnivocalPath::FILL_LEFT
));
68 int rightfill
= _paths
[i
].getRightFill();
70 unipathvec
[rightfill
-1].push_front(UnivocalPath(&_paths
[i
], UnivocalPath::FILL_RIGHT
));
74 for (size_t i
= 0; i
< _num_styles
; ++i
) {
76 start_shapes(i
+1, cx
);
77 UniPathList
& path_list
= unipathvec
[i
];
79 while (!path_list
.empty()) {
82 reset_shape(path_list
.front());
83 path_list
.pop_front();
86 UniPathList::iterator it
= emitConnecting(path_list
);
88 if (it
== path_list
.end()) {
89 if (!closed_shape()) {
90 log_error("path not closed!");
91 _cur_endpoint
= _shape_origin
;
103 std::deque
<UnivocalPath
>::iterator
104 PathParser::emitConnecting(std::deque
<UnivocalPath
>& paths
)
106 std::deque
<UnivocalPath
>::iterator it
= paths
.begin(),
110 if ((*it
).startPoint() == _cur_endpoint
) {
124 PathParser::append(const UnivocalPath
& append_path
)
126 const std::vector
<Edge
>& edges
= append_path
._path
->m_edges
;
128 if (append_path
._fill_type
== UnivocalPath::FILL_LEFT
) {
130 std::for_each(edges
.begin(), edges
.end(), boost::bind(&PathParser::line_to
,
134 for (std::vector
<Edge
>::const_reverse_iterator prev
= edges
.rbegin(),
135 it
= boost::next(prev
), end
= edges
.rend(); it
!= end
; ++it
, ++prev
) {
136 if ((*prev
).straight()) {
139 line_to(Edge((*prev
).cp
, (*it
).ap
));
143 line_to(Edge(edges
.front().cp
, append_path
.endPoint()));
146 _cur_endpoint
= append_path
.endPoint();
150 PathParser::line_to(const Edge
& curve
)
152 if (curve
.straight()) {
160 PathParser::start_shapes(int fill_style
, const SWFCxForm
& cx
)
162 prepareFill(fill_style
, cx
);
166 PathParser::end_shapes(int fill_style
)
168 terminateFill(fill_style
);
172 PathParser::reset_shape(const UnivocalPath
& append_path
)
176 _shape_origin
= append_path
.startPoint();
178 moveTo(_shape_origin
);
184 PathParser::closed_shape()
186 return _cur_endpoint
== _shape_origin
;