~ubuntu-branches/ubuntu/karmic/gnash/karmic

1.1.9 by Alexander Sack
Import upstream version 0.8.4~~bzr9980
1
// 
2
//   Copyright (C) 2007, 2008 Free Software Foundation, Inc.
3
// 
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.
8
// 
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.
13
// 
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
17
18
19
20
21
#include "DynamicShape.h"
22
23
#include <algorithm>
24
25
26
namespace gnash {
27
28
DynamicShape::DynamicShape()
29
	:
30
	shape_character_def(),
31
	_currpath(0),
32
	_currfill(0),
33
	_currline(0),
34
	_x(0),
35
	_y(0),
36
	_changed(0)
37
{}
38
39
void
40
DynamicShape::clear()
41
{
42
	//clear_meshes();
43
	m_paths.clear();
44
	m_fill_styles.clear();
45
	m_line_styles.clear();
46
	m_bound.set_null();
47
	_currpath=0; // or would point to invalid memory
48
	_currfill = _currline = 0; // or would point to cleared m_fill_style and m_line_styles respectively
49
50
	// TODO: worth setting _changed=true ? 
51
}
52
53
void
54
DynamicShape::add_path(const path& pth)
55
{
56
	m_paths.push_back(pth);
57
	_currpath = &(m_paths.back());
58
	//compute_bound(&m_bound);
59
}
60
61
void
62
DynamicShape::endFill()
63
{
64
	// Close the path
65
	if ( _currpath ) _currpath->close();
66
67
	// Remove reference to the "current" path, as
68
	// next drawing will happen on a different one
69
	_currpath = NULL;
70
71
	// Remove fill information
72
	_currfill = 0;
73
74
	// TODO: should I also clear _currline ?
75
}
76
77
void
78
DynamicShape::beginFill(const rgba& color)
79
{
80
	// Add the new fill style and set as current
81
	fill_style style; style.setSolid(color);
82
83
	endFill();
84
85
	_currfill = add_fill_style(style);
86
	// TODO: how to know wheter the fill should be set
87
	//       as *left* or *right* fill ?
88
	//       A quick test shows that *left* always work fine !
89
	path newPath(_x, _y, _currfill, 0, _currline, true); // new fill start new subshapes
90
	add_path(newPath);
91
}
92
93
void
94
DynamicShape::beginLinearGradientFill(const std::vector<gradient_record>& grad, const matrix& mat)
95
{
96
	// Add the new fill style and set as current
97
	fill_style style; style.setLinearGradient(grad, mat);
98
99
	endFill();
100
101
	_currfill = add_fill_style(style);
102
	// TODO: how to know wheter the fill should be set
103
	//       as *left* or *right* fill ?
104
	//       A quick test shows that *left* always work fine !
105
	path newPath(_x, _y, _currfill, 0, _currline, true); // new fill start new subshapes
106
	add_path(newPath);
107
}
108
109
void
110
DynamicShape::beginRadialGradientFill(const std::vector<gradient_record>& grad, const matrix& mat)
111
{
112
	// Add the new fill style and set as current
113
	fill_style style; style.setRadialGradient(grad, mat);
114
115
	endFill();
116
117
	_currfill = add_fill_style(style);
118
	// TODO: how to know wheter the fill should be set
119
	//       as *left* or *right* fill ?
120
	//       A quick test shows that *left* always work fine !
121
	path newPath(_x, _y, _currfill, 0, _currline, true); // new fill start new subshapes
122
	add_path(newPath);
123
}
124
125
void
126
DynamicShape::startNewPath(bool newShape)
127
{
128
	// Close any pending filled path
129
	if ( _currpath && _currfill) _currpath->close();
130
131
	// The DrawingApiTest.swf file shows we should NOT
132
	// necessarely end the current fill when starting a new one.
133
	//endFill();
134
135
	// A quick test shows that *left* always work fine !
136
	// More than that, using a *right* fill seems to break the tests !
137
	path newPath(_x, _y, _currfill, 0, _currline, newShape);
138
	add_path(newPath);
139
}
140
141
void
142
DynamicShape::finalize()
143
{
144
	// Nothing to do if not changed
145
	if ( ! _changed ) return;
146
147
	// Close any pending filled path (_currpath should be last path)
148
	if ( _currpath && _currfill)
149
	{
150
		assert( ! m_paths.empty() );
151
		assert( _currpath == &(m_paths.back()) );
152
		_currpath->close();
153
	}
154
155
	// TODO: check consistency of fills and such !
156
157
	_changed = false;
158
}
159
160
void
161
DynamicShape::lineStyle(boost::uint16_t thickness, const rgba& color,
162
	bool vScale, bool hScale, bool pixelHinting, bool noClose,
163
	cap_style_e startCapStyle, cap_style_e endCapStyle,
164
	join_style_e joinStyle, float miterLimitFactor)
165
{
166
	line_style style(thickness, color, vScale, hScale, pixelHinting,
167
		noClose, startCapStyle, endCapStyle, joinStyle,
168
		miterLimitFactor);
169
170
	_currline = add_line_style(style);
171
	startNewPath(false); // don't make this the start of a new subshape (to verify)
172
}
173
174
void
175
DynamicShape::resetLineStyle()
176
{
177
	_currline = 0;
178
	startNewPath(false); // don't make this the start of a new subshape (to verify)
179
}
180
181
void
182
DynamicShape::moveTo(boost::int32_t x, boost::int32_t y)
183
{
184
	if ( x != _x || y != _y )
185
	{
186
		_x = x;
187
		_y = y;
188
189
		// TODO: close previous path if any and filled ?
190
		startNewPath(false); // don't make this the start of a new subshape (to verify)
191
	}
192
}
193
194
void
195
DynamicShape::lineTo(boost::int32_t x, boost::int32_t y, int swfVersion)
196
{
197
	if ( ! _currpath ) startNewPath(true); // first shape is always new (I hope this doesn't break anything)
198
	assert(_currpath);
199
200
	_currpath->drawLineTo(x, y);
201
202
	// Update bounds 
203
	unsigned thickness = _currline ? m_line_styles[_currline-1].getThickness() : 0;
204
	if ( _currpath->size() == 1 ) {
205
		_currpath->expandBounds(m_bound, thickness, swfVersion);
206
	} else {
207
		m_bound.expand_to_circle(x, y, swfVersion < 8 ? thickness : thickness/2.0);
208
	}
209
    
210
	// Update current pen position
211
	_x = x;
212
	_y = y;
213
214
	// Mark as changed
215
	changed();
216
}
217
218
void
219
DynamicShape::curveTo(boost::int32_t cx, boost::int32_t cy, 
220
                      boost::int32_t ax, boost::int32_t ay, int swfVersion)
221
{
222
	if ( ! _currpath ) startNewPath(true); // first shape is always new (I hope this doesn't break anything)
223
	assert(_currpath);
224
225
	_currpath->drawCurveTo(cx, cy, ax, ay);
226
227
	// Update bounds 
228
	unsigned thickness = _currline ? m_line_styles[_currline-1].getThickness() : 0;
229
	if ( _currpath->size() == 1 ) {
230
		_currpath->expandBounds(m_bound, thickness, swfVersion);
231
	} else {
232
		m_bound.expand_to_circle(ax, ay, swfVersion < 8 ? thickness : thickness/2.0);
233
		m_bound.expand_to_circle(cx, cy, swfVersion < 8 ? thickness : thickness/2.0);
234
	}
235
236
	// Update current pen position
237
	_x = ax;
238
	_y = ay;
239
240
	// Mark as changed
241
	changed();
242
}
243
244
size_t
245
DynamicShape::add_fill_style(const fill_style& stl)
246
{
247
	typedef FillStyleVect V;
248
	V& v=m_fill_styles;
249
250
	// TODO: check if the style is already in our list
251
	//       (needs operator== defined for fill_style)
252
	v.push_back(stl);
253
	return v.size(); // 1-based !
254
}
255
256
size_t
257
DynamicShape::add_line_style(const line_style& stl)
258
{
259
	typedef LineStyleVect V;
260
	V& v=m_line_styles;
261
262
	// TODO: check if the style is already in our list
263
	//       (needs operator== defined for line_style)
264
	v.push_back(stl);
265
	return v.size(); // 1-based !
266
}
267
	
268
}	// end namespace gnash
269
270
271
// Local Variables:
272
// mode: C++
273
// indent-tabs-mode: t
274
// End: