2
// Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
4
// This program is free software; you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation; either version 3 of the License, or
7
// (at your option) any later version.
9
// This program is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
// GNU General Public License for more details.
14
// You should have received a copy of the GNU General Public License
15
// along with this program; if not, write to the Free Software
16
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19
#include <boost/utility.hpp>
20
#include "PathParser.h"
22
#include <boost/bind.hpp>
28
UnivocalPath::startPoint() const
30
return _fill_type == FILL_LEFT ? _path->ap : _path->m_edges.back().ap;
34
UnivocalPath::endPoint() const
36
return _fill_type == FILL_LEFT ? _path->m_edges.back().ap : _path->ap;
39
PathParser::PathParser(const std::vector<path>& paths, size_t numstyles)
41
_num_styles(numstyles),
47
PathParser::run(const cxform& cx, const matrix& mat)
49
// Since we frequently remove an element from the front or the back, we use
50
// a double ended queue here.
51
typedef std::deque<UnivocalPath> UniPathList;
53
std::vector<UniPathList> unipathvec(_num_styles);
55
for (size_t i = 0; i < _paths.size(); ++i) {
57
if (_paths[i].is_empty()) {
61
int leftfill = _paths[i].getLeftFill();
63
unipathvec[leftfill-1].push_front(UnivocalPath(&_paths[i], UnivocalPath::FILL_LEFT));
66
int rightfill = _paths[i].getRightFill();
68
unipathvec[rightfill-1].push_front(UnivocalPath(&_paths[i], UnivocalPath::FILL_RIGHT));
72
for (size_t i = 0; i < _num_styles; ++i) {
74
start_shapes(i+1, cx);
75
UniPathList& path_list = unipathvec[i];
77
while (!path_list.empty()) {
80
reset_shape(path_list.front());
81
path_list.pop_front();
84
UniPathList::iterator it = emitConnecting(path_list);
86
if (it == path_list.end()) {
87
if (!closed_shape()) {
88
std::cout << "error: path not closed!" << std::endl;
89
_cur_endpoint = _shape_origin;
101
std::deque<UnivocalPath>::iterator
102
PathParser::emitConnecting(std::deque<UnivocalPath>& paths)
104
std::deque<UnivocalPath>::iterator it = paths.begin(),
108
if ((*it).startPoint() == _cur_endpoint) {
122
PathParser::append(const UnivocalPath& append_path)
124
const std::vector<Edge>& edges = append_path._path->m_edges;
126
if (append_path._fill_type == UnivocalPath::FILL_LEFT) {
128
std::for_each(edges.begin(), edges.end(), boost::bind(&PathParser::line_to,
132
for (std::vector<edge>::const_reverse_iterator prev = edges.rbegin(),
133
it = boost::next(prev), end = edges.rend(); it != end; ++it, ++prev) {
134
if ((*prev).isStraight()) {
137
line_to(Edge((*prev).cp, (*it).ap));
141
line_to(Edge(edges.front().cp, append_path.endPoint()));
144
_cur_endpoint = append_path.endPoint();
148
PathParser::line_to(const edge& curve)
150
if (curve.isStraight()) {
158
PathParser::start_shapes(int fill_style, const cxform& cx)
160
prepareFill(fill_style, cx);
164
PathParser::end_shapes(int fill_style)
166
terminateFill(fill_style);
170
PathParser::reset_shape(const UnivocalPath& append_path)
174
_shape_origin = append_path.startPoint();
176
moveTo(_shape_origin);
182
PathParser::closed_shape()
184
return _cur_endpoint == _shape_origin;