~ubuntu-branches/ubuntu/saucy/gnash/saucy-proposed

« back to all changes in this revision

Viewing changes to libcore/swf/ShapeRecord.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Sindhudweep Narayan Sarkar
  • Date: 2009-10-07 00:06:10 UTC
  • mfrom: (1.1.12 upstream)
  • Revision ID: james.westby@ubuntu.com-20091007000610-mj9rwqe774gizn1j
Tags: 0.8.6-0ubuntu1
new upstream release 0.8.6 (LP: #435897)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//   Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
 
2
// 
 
3
// This program is free software; you can redistribute it and/or modify
 
4
// it under the terms of the GNU General Public License as published by
 
5
// the Free Software Foundation; either version 3 of the License, or
 
6
// (at your option) any later version.
 
7
// 
 
8
// This program is distributed in the hope that it will be useful,
 
9
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
// GNU General Public License for more details.
 
12
// 
 
13
// You should have received a copy of the GNU General Public License
 
14
// along with this program; if not, write to the Free Software
 
15
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
16
 
 
17
 
 
18
#include "ShapeRecord.h"
 
19
#include "SWF.h"
 
20
#include "SWFStream.h"
 
21
#include "movie_definition.h"
 
22
#include "fill_style.h"
 
23
#include "Geometry.h"
 
24
#include "GnashNumeric.h"
 
25
#include "RunResources.h"
 
26
 
 
27
#include <vector>
 
28
 
 
29
namespace gnash {
 
30
namespace SWF {
 
31
 
 
32
// Forward declarations
 
33
namespace {
 
34
    void readFillStyles(ShapeRecord::FillStyles& styles, SWFStream& in,
 
35
        SWF::TagType tag, movie_definition& md, const RunResources& r);
 
36
    void readLineStyles(ShapeRecord::LineStyles& styles, SWFStream& in,
 
37
        SWF::TagType tag, movie_definition& md, const RunResources& r);
 
38
    void computeBounds(rect& bounds, const ShapeRecord::Paths& paths,
 
39
        const ShapeRecord::LineStyles& lineStyles, int swfVersion);
 
40
}
 
41
 
 
42
// Functors for path and style manipulation.
 
43
namespace {
 
44
 
 
45
template<typename T>
 
46
class Lerp
 
47
{
 
48
public:
 
49
    Lerp(typename T::const_iterator style1, typename T::const_iterator style2,
 
50
            const double ratio)
 
51
        :
 
52
        _style1(style1),
 
53
        _style2(style2),
 
54
        _ratio(ratio)
 
55
    {}
 
56
 
 
57
    void operator()(typename T::value_type& st)
 
58
    {
 
59
        st.set_lerp(*_style1, *_style2, _ratio);
 
60
        ++_style1, ++_style2;
 
61
    }
 
62
 
 
63
private:
 
64
    typename T::const_iterator _style1;
 
65
    typename T::const_iterator _style2;
 
66
    const double _ratio;
 
67
};
 
68
 
 
69
// Facilities for working with list of paths.
 
70
class PathList
 
71
{
 
72
    typedef SWF::ShapeRecord::Paths Paths;
 
73
public:
 
74
 
 
75
    PathList(const Paths& paths)
 
76
        :
 
77
        _paths(paths),
 
78
        _currpath(0),
 
79
        _curredge(0),
 
80
        _nedges(computeNumberOfEdges(_paths))
 
81
    {}
 
82
 
 
83
    /// Return number of edges in the path list
 
84
    size_t size() const
 
85
    {
 
86
        return _nedges;
 
87
    }
 
88
 
 
89
    /// Get next edge in the path list.
 
90
    //
 
91
    /// After last edge in the list has been fetched,
 
92
    /// next call to this function will return first
 
93
    /// edge again.
 
94
    ///
 
95
    const Edge& getNextEdge()
 
96
    {
 
97
        const Edge& ret = _paths[_currpath][_curredge];
 
98
        if ( ++_curredge >= _paths[_currpath].size() )
 
99
        {
 
100
            if ( ++_currpath >= _paths.size() )
 
101
            {
 
102
                // this is not really needed,
 
103
                // but it's simpler to do so that
 
104
                // to make next call fail or abort..
 
105
                _currpath = 0;
 
106
                _curredge = 0;
 
107
            }
 
108
        }
 
109
        return ret;
 
110
    }
 
111
 
 
112
    /// Compute total number of edges
 
113
    static size_t computeNumberOfEdges(const Paths& paths)
 
114
    {
 
115
        size_t count=0;
 
116
        for (Paths::const_iterator i = paths.begin(), e = paths.end();
 
117
                i != e; ++i) {
 
118
 
 
119
            count += i->size();
 
120
        }
 
121
        return count;
 
122
    }
 
123
 
 
124
private:
 
125
 
 
126
    const Paths& _paths;
 
127
 
 
128
    size_t _currpath;
 
129
 
 
130
    size_t _curredge;
 
131
 
 
132
    size_t _nedges;
 
133
 
 
134
};
 
135
 
 
136
} // anonymous namespace
 
137
 
 
138
 
 
139
ShapeRecord::ShapeRecord(SWFStream& in, SWF::TagType tag, movie_definition& m,
 
140
        const RunResources& r)
 
141
{
 
142
    read(in, tag, m, r);
 
143
}
 
144
 
 
145
void
 
146
ShapeRecord::setLerp(const ShapeRecord& a, const ShapeRecord& b,
 
147
        const double ratio)
 
148
{
 
149
 
 
150
    // Update current bounds.
 
151
    _bounds.set_lerp(a.getBounds(), b.getBounds(), ratio);
 
152
 
 
153
    // fill styles
 
154
    const FillStyles::const_iterator fs1 = a.fillStyles().begin();
 
155
    const FillStyles::const_iterator fs2 = b.fillStyles().begin();
 
156
 
 
157
    std::for_each(_fillStyles.begin(), _fillStyles.end(),
 
158
            Lerp<FillStyles>(fs1, fs2, ratio));
 
159
 
 
160
    // line styles
 
161
    const LineStyles::const_iterator ls1 = a.lineStyles().begin();
 
162
    const LineStyles::const_iterator ls2 = b.lineStyles().begin();
 
163
 
 
164
    std::for_each(_lineStyles.begin(), _lineStyles.end(),
 
165
            Lerp<LineStyles>(ls1, ls2, ratio));
 
166
 
 
167
    // This is used for cases in which number
 
168
    // of paths in start shape and end shape are not
 
169
    // the same.
 
170
    const Path empty_path;
 
171
    const Edge empty_edge;
 
172
 
 
173
    // shape
 
174
    const Paths& paths1 = a.paths();
 
175
    const Paths& paths2 = b.paths();
 
176
    for (size_t i = 0, k = 0, n = 0; i < _paths.size(); i++)
 
177
    {
 
178
        Path& p = _paths[i];
 
179
        const Path& p1 = i < paths1.size() ? paths1[i] : empty_path;
 
180
        const Path& p2 = n < paths2.size() ? paths2[n] : empty_path;
 
181
 
 
182
        const float new_ax = flerp(p1.ap.x, p2.ap.x, ratio);
 
183
        const float new_ay = flerp(p1.ap.y, p2.ap.y, ratio);
 
184
 
 
185
        p.reset(new_ax, new_ay, p1.getLeftFill(),
 
186
                p2.getRightFill(), p1.getLineStyle());
 
187
 
 
188
        //  edges;
 
189
        const size_t len = p1.size();
 
190
        p.m_edges.resize(len);
 
191
 
 
192
        for (size_t j=0; j < p.size(); j++)
 
193
        {
 
194
            Edge& e = p[j];
 
195
            const Edge& e1 = j < p1.size() ? p1[j] : empty_edge;
 
196
 
 
197
            const Edge& e2 = k < p2.size() ? p2[k] : empty_edge;
 
198
 
 
199
            e.cp.x = static_cast<int>(flerp(e1.cp.x, e2.cp.x, ratio));
 
200
            e.cp.y = static_cast<int>(flerp(e1.cp.y, e2.cp.y, ratio));
 
201
            e.ap.x = static_cast<int>(flerp(e1.ap.x, e2.ap.x, ratio));
 
202
            e.ap.y = static_cast<int>(flerp(e1.ap.y, e2.ap.y, ratio));
 
203
            ++k;
 
204
 
 
205
            if (p2.size() <= k) {
 
206
                k = 0;
 
207
                ++n;
 
208
            }
 
209
        }
 
210
    }
 
211
 
 
212
}
 
213
 
 
214
void
 
215
ShapeRecord::read(SWFStream& in, SWF::TagType tag, movie_definition& m,
 
216
        const RunResources& r)
 
217
{
 
218
 
 
219
    /// TODO: is this correct?
 
220
    const bool styleInfo = (tag == SWF::DEFINESHAPE ||
 
221
                            tag == SWF::DEFINESHAPE2 ||
 
222
                            tag == SWF::DEFINESHAPE3 ||
 
223
                            tag == SWF::DEFINESHAPE4 ||
 
224
                            tag == SWF::DEFINESHAPE4_);
 
225
 
 
226
    if (styleInfo)
 
227
    {
 
228
        _bounds.read(in);
 
229
    
 
230
        IF_VERBOSE_PARSE(
 
231
            std::string b = _bounds.toString();
 
232
            log_parse(_("  bound rect: %s"), b);
 
233
        );
 
234
    
 
235
        // TODO: Store and use these. Unfinished.
 
236
        if (tag == SWF::DEFINESHAPE4 || tag == SWF::DEFINESHAPE4_)
 
237
        {
 
238
            rect tbound;
 
239
            tbound.read(in);
 
240
            in.ensureBytes(1);
 
241
            static_cast<void>(in.read_u8());
 
242
            LOG_ONCE(log_unimpl("DEFINESHAPE4 edge boundaries and scales"));
 
243
        }
 
244
    
 
245
        readFillStyles(_fillStyles, in, tag, m, r);
 
246
        readLineStyles(_lineStyles, in, tag, m, r);
 
247
    }
 
248
 
 
249
    if (tag == SWF::DEFINEFONT || tag == SWF::DEFINEFONT2 )
 
250
    {
 
251
        assert(!styleInfo);
 
252
    }
 
253
    
 
254
    // Use read_u8 to force alignment.
 
255
    in.ensureBytes(1);
 
256
    boost::uint8_t num_bits = in.read_u8();
 
257
    int num_fill_bits = (num_bits & 0xF0) >> 4;
 
258
    int num_line_bits = (num_bits & 0x0F);
 
259
    
 
260
    IF_VERBOSE_PARSE(
 
261
        log_parse(_("  ShapeRecord(%s): fillbits %d, linebits %d"),
 
262
            tag, num_fill_bits, num_line_bits);
 
263
    );
 
264
    
 
265
    if ( !num_fill_bits && !num_line_bits )
 
266
    {
 
267
        /// When reading font glyphs it happens to read 1 byte
 
268
        /// past end boundary of a glyph due to fill/line bits being
 
269
        /// zero.
 
270
        ///
 
271
        /// Generally returning here seems to break morphs:
 
272
        ///  http://savannah.gnu.org/bugs/?21747
 
273
        /// And other normal shapes:
 
274
        ///  http://savannah.gnu.org/bugs/?21923
 
275
        ///  http://savannah.gnu.org/bugs/?22000
 
276
        ///
 
277
        /// So for now we only return if NOT reading a morph shape.
 
278
        /// Pretty ugly... till next bug report.
 
279
        ///
 
280
        ///
 
281
        if (tag == SWF::DEFINEFONT || tag == SWF::DEFINEFONT2 || 
 
282
                tag == SWF::DEFINEFONT3)
 
283
        {
 
284
            log_debug("Skipping glyph read, being fill and line bits zero. "
 
285
                    "SWF tag is %d.", tag);
 
286
            return;
 
287
        }
 
288
    }
 
289
    
 
290
    // These are state variables that keep the
 
291
    // current position & style of the shape
 
292
    // outline, and vary as we read the edge data.
 
293
    //
 
294
    // At the moment we just store each edge with
 
295
    // the full necessary info to render it, which
 
296
    // is simple but not optimally efficient.
 
297
    int fill_base = 0;
 
298
    int line_base = 0;
 
299
    int   x = 0, y = 0;
 
300
    Path  current_path;
 
301
 
 
302
#define SHAPE_LOG 0
 
303
    
 
304
    // SHAPERECORDS
 
305
    for (;;)
 
306
    {
 
307
        in.ensureBits(1);
 
308
        bool isEdgeRecord = in.read_bit();
 
309
        if (!isEdgeRecord)
 
310
        {
 
311
            // Parse the record.
 
312
            in.ensureBits(5);
 
313
            int flags = in.read_uint(5);
 
314
            if (flags == SHAPE_END)
 
315
            {  
 
316
                // Store the current path if any.
 
317
                if (! current_path.empty())
 
318
                {
 
319
                    _paths.push_back(current_path);
 
320
                    current_path.m_edges.resize(0);
 
321
                }
 
322
                break;
 
323
            }
 
324
            if (flags & SHAPE_MOVE)
 
325
            {  
 
326
                // Store the current path if any, and prepare a fresh one.
 
327
                if (! current_path.empty())
 
328
                {
 
329
                    _paths.push_back(current_path);
 
330
                    current_path.m_edges.resize(0);
 
331
                }
 
332
                in.ensureBits(5);
 
333
                int num_move_bits = in.read_uint(5);
 
334
                in.ensureBits(2 * num_move_bits);
 
335
                int move_x = in.read_sint(num_move_bits);
 
336
                int move_y = in.read_sint(num_move_bits);
 
337
    
 
338
                x = move_x;
 
339
                y = move_y;
 
340
    
 
341
                // Set the beginning of the path.
 
342
                current_path.ap.x = x;
 
343
                current_path.ap.y = y;
 
344
    
 
345
#if SHAPE_LOG
 
346
                IF_VERBOSE_PARSE(
 
347
                    log_parse(_("  Shape read: moveto %d %d"), x, y);
 
348
                );
 
349
#endif
 
350
            }
 
351
            if ((flags & SHAPE_FILLSTYLE0_CHANGE) && num_fill_bits > 0)
 
352
            {
 
353
                // fill_style_0_change = 1;
 
354
                if (! current_path.empty())
 
355
                {
 
356
                    _paths.push_back(current_path);
 
357
                    current_path.m_edges.resize(0);
 
358
                    current_path.ap.x = x;
 
359
                    current_path.ap.y = y;
 
360
                }
 
361
                in.ensureBits(num_fill_bits);
 
362
                unsigned style = in.read_uint(num_fill_bits);
 
363
                if (style > 0)
 
364
                {
 
365
                    style += fill_base;
 
366
                }
 
367
    
 
368
                if (tag == SWF::DEFINEFONT || tag == SWF::DEFINEFONT2)
 
369
                {
 
370
                    if ( style > 1 )          // 0:hide 1:renderer
 
371
                    {
 
372
                        IF_VERBOSE_MALFORMED_SWF(
 
373
                             log_swferror(_("Invalid fill style %d in "
 
374
                                     "fillStyle0Change record for font tag "
 
375
                                     "(0 or 1 valid). Set to 0."), style);
 
376
                        );
 
377
                        style = 0;
 
378
                    }
 
379
                }
 
380
                else
 
381
                {
 
382
                    // 1-based index
 
383
                    if ( style > _fillStyles.size() )
 
384
                    {
 
385
                        IF_VERBOSE_MALFORMED_SWF(
 
386
                             log_swferror(_("Invalid fill style %d in "
 
387
                                     "fillStyle0Change record - %d defined. "
 
388
                                     "Set to 0."), style, _fillStyles.size());
 
389
                        );
 
390
                        style = 0;
 
391
                    }
 
392
                }
 
393
    
 
394
                current_path.setLeftFill(style);
 
395
#if SHAPE_LOG
 
396
                IF_VERBOSE_PARSE(
 
397
                     log_parse(_("  Shape read: fill0 (left) = %d"),
 
398
                         current_path.getLeftFill());
 
399
                );
 
400
#endif
 
401
            }
 
402
            if ((flags & SHAPE_FILLSTYLE1_CHANGE) && num_fill_bits > 0)
 
403
            {
 
404
                // fill_style_1_change = 1;
 
405
                if (! current_path.empty())
 
406
                {
 
407
                    _paths.push_back(current_path);
 
408
                    current_path.m_edges.resize(0);
 
409
                    current_path.ap.x = x;
 
410
                    current_path.ap.y = y;
 
411
                }
 
412
                in.ensureBits(num_fill_bits);
 
413
                unsigned style = in.read_uint(num_fill_bits);
 
414
                if (style > 0)
 
415
                {
 
416
                    style += fill_base;
 
417
                }
 
418
    
 
419
                if (tag == SWF::DEFINEFONT || tag == SWF::DEFINEFONT2)
 
420
                {
 
421
                    if ( style > 1 )          // 0:hide 1:renderer
 
422
                    {
 
423
                        IF_VERBOSE_MALFORMED_SWF(
 
424
                             log_swferror(_("Invalid fill style %d in "
 
425
                                     "fillStyle1Change record for font tag "
 
426
                                     "(0 or 1 valid). Set to 0."), style);
 
427
                        );
 
428
                        style = 0;
 
429
                    }
 
430
                }
 
431
                else
 
432
                {
 
433
                    // 1-based index
 
434
                    if ( style > _fillStyles.size() )
 
435
                    {
 
436
                        IF_VERBOSE_MALFORMED_SWF(
 
437
                            log_swferror(_("Invalid fill style %d in "
 
438
                                    "fillStyle1Change record - %d defined. "
 
439
                                    "Set to 0."), style, _fillStyles.size());
 
440
                        );
 
441
                        style = 0;
 
442
                    }
 
443
                }
 
444
                current_path.setRightFill(style);
 
445
#if SHAPE_LOG
 
446
                IF_VERBOSE_PARSE (
 
447
                    log_parse(_("  Shape read: fill1 (right) = %d"),
 
448
                        current_path.getRightFill());
 
449
                );
 
450
#endif
 
451
            }
 
452
            if ((flags & SHAPE_LINESTYLE_CHANGE) && num_line_bits > 0)
 
453
            {
 
454
                // line_style_change = 1;
 
455
                if (! current_path.empty())
 
456
                {
 
457
                    _paths.push_back(current_path);
 
458
                    current_path.m_edges.resize(0);
 
459
                    current_path.ap.x = x;
 
460
                    current_path.ap.y = y;
 
461
                }
 
462
                in.ensureBits(num_line_bits);
 
463
                unsigned style = in.read_uint(num_line_bits);
 
464
                if (style > 0)
 
465
                {
 
466
                    style += line_base;
 
467
                }
 
468
                if (tag == SWF::DEFINEFONT || tag == SWF::DEFINEFONT2)
 
469
                {
 
470
                    if ( style > 1 )          // 0:hide 1:renderer
 
471
                    {
 
472
                        IF_VERBOSE_MALFORMED_SWF(
 
473
                            log_swferror(_("Invalid line style %d in "
 
474
                                    "lineStyleChange record for font tag "
 
475
                                    "(0 or 1 valid). Set to 0."), style);
 
476
                        );
 
477
                        style = 0;
 
478
                    }
 
479
                }
 
480
                else {
 
481
                    // 1-based index
 
482
                    if (style > _lineStyles.size()) {
 
483
                        IF_VERBOSE_MALFORMED_SWF(
 
484
                            log_swferror(_("Invalid fill style %d in "
 
485
                                    "lineStyleChange record - %d defined. "
 
486
                                    "Set to 0."), style, _lineStyles.size());
 
487
                        );
 
488
                        style = 0;
 
489
                    }
 
490
                }
 
491
                current_path.setLineStyle(style);
 
492
#if SHAPE_LOG
 
493
                IF_VERBOSE_PARSE(
 
494
                    log_parse(_("ShapeRecord: line %d"), 
 
495
                        current_path.getLineStyle());
 
496
                )
 
497
#endif
 
498
            }
 
499
            if (flags & SHAPE_HAS_NEW_STYLES)
 
500
            {
 
501
                if (!styleInfo)
 
502
                {
 
503
                    IF_VERBOSE_MALFORMED_SWF(
 
504
                         log_swferror("Unexpected HasNewStyle flag in tag "
 
505
                             "%d shape record", tag);
 
506
                    );
 
507
                    continue;
 
508
                }
 
509
                IF_VERBOSE_PARSE (
 
510
                    log_parse(_("ShapeRecord: more fill styles"));
 
511
                );
 
512
    
 
513
                // Store the current path if any.
 
514
                if (! current_path.empty())
 
515
                {
 
516
                    _paths.push_back(current_path);
 
517
                    current_path.clear();
 
518
                }
 
519
    
 
520
                // Tack on an empty path signalling a new shape.
 
521
                // @@ need better understanding of whether this is correct??!?!!
 
522
                // @@ i.e., we should just start a whole new shape here, right?
 
523
                _paths.push_back(Path());
 
524
                _paths.back().m_new_shape = true;
 
525
    
 
526
                fill_base = _fillStyles.size();
 
527
                line_base = _lineStyles.size();
 
528
                readFillStyles(_fillStyles, in, tag, m, r);
 
529
                readLineStyles(_lineStyles, in, tag, m, r);
 
530
    
 
531
                in.ensureBits(8);
 
532
                num_fill_bits = in.read_uint(4);
 
533
                num_line_bits = in.read_uint(4);
 
534
            }
 
535
        }
 
536
        else
 
537
        {
 
538
            // EDGERECORD
 
539
            in.ensureBits(1);
 
540
            bool edge_flag = in.read_bit();
 
541
            if (edge_flag == 0)
 
542
            {
 
543
                in.ensureBits(4);
 
544
                int num_bits = 2 + in.read_uint(4);
 
545
                // curved edge
 
546
                in.ensureBits(4 * num_bits);
 
547
                int cx = x + in.read_sint(num_bits);
 
548
                int cy = y + in.read_sint(num_bits);
 
549
                int ax = cx + in.read_sint(num_bits);
 
550
                int ay = cy + in.read_sint(num_bits);
 
551
    
 
552
#if SHAPE_LOG
 
553
                IF_VERBOSE_PARSE (
 
554
                    log_parse(_("ShapeRecord: curved edge "
 
555
                            "%d %d - %d %d - %d %d"), x, y, cx, cy, ax, ay);
 
556
                );
 
557
#endif
 
558
                current_path.m_edges.push_back(Edge(cx, cy, ax, ay));
 
559
                x = ax;
 
560
                y = ay;
 
561
            }
 
562
            else
 
563
            {
 
564
                // straight edge
 
565
                in.ensureBits(5);
 
566
                int num_bits = 2 + in.read_uint(4);
 
567
                bool  line_flag = in.read_bit();
 
568
                int dx = 0, dy = 0;
 
569
                if (line_flag)
 
570
                {
 
571
                    // General line.
 
572
                    in.ensureBits(2 * num_bits);
 
573
                    dx = in.read_sint(num_bits);
 
574
                    dy = in.read_sint(num_bits);
 
575
                }
 
576
                else
 
577
                {
 
578
                    in.ensureBits(1);
 
579
                    bool vert_flag = in.read_bit();
 
580
                    if (vert_flag == 0)
 
581
                    {
 
582
                        // Horizontal line.
 
583
                        in.ensureBits(num_bits);
 
584
                        dx = in.read_sint(num_bits);
 
585
                    }
 
586
                    else
 
587
                    {
 
588
                        // Vertical line.
 
589
                        in.ensureBits(num_bits);
 
590
                        dy = in.read_sint(num_bits);
 
591
                    }
 
592
                }
 
593
    
 
594
#if SHAPE_LOG
 
595
                IF_VERBOSE_PARSE (
 
596
                     log_parse(_("ShapeRecord: straight edge "
 
597
                             "%d %d - %d %d"), x, y, x + dx, y + dy);
 
598
                );
 
599
#endif
 
600
                current_path.m_edges.push_back(Edge(x + dx, y + dy,
 
601
                            x + dx, y + dy));
 
602
                x += dx;
 
603
                y += dy;
 
604
            }
 
605
        }
 
606
    }
 
607
    
 
608
    if (!styleInfo)
 
609
    {
 
610
        // TODO: performance would be improved by computing
 
611
        //       the bounds as edges are parsed.
 
612
        computeBounds(_bounds, _paths, _lineStyles, m.get_version());
 
613
    }
 
614
#ifdef GNASH_DEBUG_SHAPE_BOUNDS
 
615
    else
 
616
    {
 
617
        rect computedBounds;
 
618
        computeBounds(computedBounds, _paths, _lineStyles, m->get_version());
 
619
        if ( computedBounds != m_bounds )
 
620
        {
 
621
            log_debug("Shape object read for tag %d contained embedded "
 
622
                    "bounds %s, while we computed bounds %s",
 
623
                    tag, m_bound, computedBounds);
 
624
        }
 
625
    }
 
626
#endif
 
627
}
 
628
 
 
629
namespace {
 
630
 
 
631
// Read fill styles, and push them onto the given style array.
 
632
void
 
633
readFillStyles(ShapeRecord::FillStyles& styles, SWFStream& in,
 
634
                 SWF::TagType tag, movie_definition& m, const RunResources& r)
 
635
{
 
636
    in.ensureBytes(1);
 
637
    boost::uint16_t fill_style_count = in.read_u8();
 
638
    if (tag != SWF::DEFINESHAPE)
 
639
    {
 
640
        if (fill_style_count == 0xFF)
 
641
        {
 
642
            in.ensureBytes(2);
 
643
            fill_style_count = in.read_u16();
 
644
        }
 
645
    }
 
646
 
 
647
    IF_VERBOSE_PARSE (
 
648
        log_parse(_("  readFillStyles: count = %u"), fill_style_count);
 
649
    );
 
650
 
 
651
    // Read the styles.
 
652
    styles.reserve(styles.size()+fill_style_count);
 
653
    for (boost::uint16_t i = 0; i < fill_style_count; ++i) {
 
654
        // TODO: add a fill_style constructor directly reading from stream
 
655
        fill_style fs;
 
656
        fs.read(in, tag, m, r);
 
657
        styles.push_back(fs);
 
658
    }
 
659
}
 
660
 
 
661
// Read line styles and push them onto the back of the given array.
 
662
void
 
663
readLineStyles(ShapeRecord::LineStyles& styles, SWFStream& in,
 
664
        SWF::TagType tag, movie_definition& md, const RunResources& r)
 
665
{
 
666
    in.ensureBytes(1);
 
667
    int line_style_count = in.read_u8();
 
668
 
 
669
    IF_VERBOSE_PARSE(
 
670
        log_parse(_("  readLineStyles: count = %d"), line_style_count);
 
671
    );
 
672
 
 
673
    if (line_style_count == 0xFF)
 
674
    {
 
675
        in.ensureBytes(2);
 
676
        line_style_count = in.read_u16();
 
677
        IF_VERBOSE_PARSE(
 
678
            log_parse(_("  readLineStyles: count2 = %d"), line_style_count);
 
679
        );
 
680
    }
 
681
 
 
682
    // Read the styles.
 
683
    for (int i = 0; i < line_style_count; i++)
 
684
    {
 
685
        styles.resize(styles.size() + 1);
 
686
        styles.back().read(in, tag, md, r);
 
687
    }
 
688
}
 
689
 
 
690
// Find the bounds of this shape, and store them in the given rectangle.
 
691
void
 
692
computeBounds(rect& bounds, const ShapeRecord::Paths& paths,
 
693
        const ShapeRecord::LineStyles& lineStyles, int swfVersion)
 
694
{
 
695
    bounds.set_null();
 
696
 
 
697
    for (unsigned int i = 0; i < paths.size(); i++)
 
698
    {
 
699
        const Path& p = paths[i];
 
700
 
 
701
        unsigned thickness = 0;
 
702
        if ( p.m_line )
 
703
        {
 
704
            // For glyph shapes m_line is allowed to be 1
 
705
            // while no defined line styles are allowed.
 
706
            if (lineStyles.empty()) {
 
707
                // This is either a Glyph, for which m_line==1 is valid
 
708
                // or a bug in the parser, which we have no way to
 
709
                // check at this time
 
710
                assert(p.m_line == 1);
 
711
            }
 
712
            else
 
713
            {
 
714
                thickness = lineStyles[p.m_line-1].getThickness();
 
715
            }
 
716
        }
 
717
        p.expandBounds(bounds, thickness, swfVersion);
 
718
    }
 
719
}
 
720
 
 
721
 
 
722
} // anonymous namespace
 
723
 
 
724
} // namespace SWF
 
725
} // namespace gnash
 
726