[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] /srv/bzr/gnash/trunk r10236: Further reduce the libcore/p
From: |
Benjamin Wolsey |
Subject: |
[Gnash-commit] /srv/bzr/gnash/trunk r10236: Further reduce the libcore/parser directory. |
Date: |
Fri, 07 Nov 2008 10:10:54 +0100 |
User-agent: |
Bazaar (1.5) |
------------------------------------------------------------
revno: 10236
committer: Benjamin Wolsey <address@hidden>
branch nick: trunk
timestamp: Fri 2008-11-07 10:10:54 +0100
message:
Further reduce the libcore/parser directory.
added:
libcore/swf/VideoFrameTag.cpp
libcore/swf/VideoFrameTag.h
renamed:
libcore/parser/video_stream_def.cpp => libcore/swf/DefineVideoStreamTag.cpp
libcore/parser/video_stream_def.h => libcore/swf/DefineVideoStreamTag.h
libcore/video_stream_instance.cpp => libcore/Video.cpp
libcore/video_stream_instance.h => libcore/Video.h
modified:
libcore/Makefile.am
libcore/asobj/ClassHierarchy.cpp
libcore/asobj/Global.cpp
libcore/asobj/NetStream_as.h
libcore/impl.cpp
libcore/parser/Makefile.am
libcore/parser/morph2_character_def.cpp
libcore/parser/morph2_character_def.h
libcore/parser/shape_character_def.cpp
libcore/parser/shape_character_def.h
libcore/swf/tag_loaders.cpp
libcore/swf/DefineVideoStreamTag.cpp
libcore/swf/DefineVideoStreamTag.h
libcore/Video.cpp
libcore/Video.h
------------------------------------------------------------
revno: 10229.1.11
committer: Benjamin Wolsey <address@hidden>
branch nick: work
timestamp: Thu 2008-11-06 22:10:36 +0100
message:
Clean up shape_character_def so it's almost readable. Drop the debugging
stuff, which almost certainly doesn't work any more.
modified:
libcore/parser/shape_character_def.cpp
------------------------------------------------------------
revno: 10229.1.12
committer: Benjamin Wolsey <address@hidden>
branch nick: work
timestamp: Thu 2008-11-06 23:57:43 +0100
message:
Split video stream parsing into DefineVideoStreamTag and VideoFrameTag.
Push the
data in the frame tags to the DefineVideoStreamTag on parsing.
Drop things from shape_character_def that aren't immediately useful. They
can easily be retrieved if necessary.
added:
libcore/swf/VideoFrameTag.cpp
libcore/swf/VideoFrameTag.h
renamed:
libcore/parser/video_stream_def.cpp =>
libcore/swf/DefineVideoStreamTag.cpp
libcore/parser/video_stream_def.h => libcore/swf/DefineVideoStreamTag.h
modified:
libcore/Makefile.am
libcore/impl.cpp
libcore/parser/Makefile.am
libcore/parser/shape_character_def.cpp
libcore/parser/shape_character_def.h
libcore/swf/tag_loaders.cpp
libcore/video_stream_instance.cpp
libcore/video_stream_instance.h
libcore/swf/DefineVideoStreamTag.cpp
libcore/swf/DefineVideoStreamTag.h
------------------------------------------------------------
revno: 10229.1.13
committer: Benjamin Wolsey <address@hidden>
branch nick: work
timestamp: Fri 2008-11-07 00:06:02 +0100
message:
Rename video_stream_instance to Video.
renamed:
libcore/video_stream_instance.cpp => libcore/Video.cpp
libcore/video_stream_instance.h => libcore/Video.h
modified:
libcore/Makefile.am
libcore/asobj/ClassHierarchy.cpp
libcore/asobj/Global.cpp
libcore/asobj/NetStream_as.h
libcore/swf/DefineVideoStreamTag.cpp
libcore/Video.cpp
libcore/Video.h
------------------------------------------------------------
revno: 10229.1.14
committer: Benjamin Wolsey <address@hidden>
branch nick: work
timestamp: Fri 2008-11-07 00:21:13 +0100
message:
Use std::fill_n instead of memset.
modified:
libcore/swf/VideoFrameTag.cpp
------------------------------------------------------------
revno: 10229.1.15
committer: Benjamin Wolsey <address@hidden>
branch nick: work
timestamp: Fri 2008-11-07 09:37:30 +0100
message:
Separate shape and morph parsing / definition classes properly.
modified:
libcore/parser/morph2_character_def.cpp
libcore/parser/morph2_character_def.h
libcore/parser/shape_character_def.h
=== modified file 'libcore/Makefile.am'
--- a/libcore/Makefile.am 2008-11-06 11:56:50 +0000
+++ b/libcore/Makefile.am 2008-11-06 23:06:02 +0000
@@ -82,6 +82,8 @@
rect.cpp \
MovieClip.cpp \
swf/TagLoadersTable.cpp \
+ swf/DefineVideoStreamTag.cpp \
+ swf/VideoFrameTag.cpp \
swf/tag_loaders.cpp \
swf/DefineFontAlignZonesTag.cpp \
swf/DefineEditTextTag.cpp \
@@ -91,7 +93,7 @@
swf/StartSoundTag.cpp \
swf/StreamSoundBlockTag.cpp \
swf_function.cpp \
- video_stream_instance.cpp \
+ Video.cpp \
StreamProvider.cpp \
array.cpp \
Button.cpp \
@@ -175,6 +177,8 @@
swf.h \
swf/TagLoadersTable.h \
swf/tag_loaders.h \
+ swf/VideoFrameTag.h \
+ swf/DefineVideoStreamTag.h \
swf/ControlTag.h \
swf/DefineFontAlignZonesTag.h \
swf/CSMTextSettingsTag.h \
@@ -194,7 +198,7 @@
text.h \
timers.h \
RGBA.h \
- video_stream_instance.h \
+ Video.h \
$(NULL)
libgnashcore_la_LIBADD = \
=== renamed file 'libcore/video_stream_instance.cpp' => 'libcore/Video.cpp'
--- a/libcore/video_stream_instance.cpp 2008-10-27 16:05:13 +0000
+++ b/libcore/Video.cpp 2008-11-06 23:06:02 +0000
@@ -1,4 +1,4 @@
-// video_stream_instance.cpp: Draw individual video frames, for Gnash.
+// Video.cpp: Draw individual video frames, for Gnash.
//
// Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
//
@@ -19,8 +19,8 @@
#include "MovieClip.h"
-#include "video_stream_instance.h"
-#include "video_stream_def.h"
+#include "Video.h"
+#include "DefineVideoStreamTag.h"
#include "fn_call.h"
#include "as_value.h"
#include "NetStream_as.h"
@@ -114,7 +114,7 @@
static as_value
video_attach(const fn_call& fn)
{
- boost::intrusive_ptr<video_stream_instance> video =
ensureType<video_stream_instance>(fn.this_ptr);
+ boost::intrusive_ptr<Video> video = ensureType<Video>(fn.this_ptr);
if (fn.nargs < 1)
{
@@ -153,14 +153,14 @@
// I'm not sure We can rely on the def and parent values being accepted
as NULL
// Not till we add some testing...
- boost::intrusive_ptr<character> obj = new video_stream_instance(NULL,
NULL, -1);
+ boost::intrusive_ptr<character> obj = new Video(NULL, NULL, -1);
obj->setDynamic();
return as_value(obj.get()); // will keep alive
}
/*private*/
void
-video_stream_instance::initializeDecoder()
+Video::initializeDecoder()
{
media::MediaHandler* mh = media::MediaHandler::get();
@@ -188,7 +188,7 @@
}
}
-video_stream_instance::video_stream_instance(video_stream_definition* def,
+Video::Video(SWF::DefineVideoStreamTag* def,
character* parent, int id)
:
character(parent, id),
@@ -199,7 +199,7 @@
_lastDecodedVideoFrameNum(-1),
_lastDecodedVideoFrame()
{
- //log_debug("video_stream_instance %p ctor", (void*)this);
+ //log_debug("Video %p ctor", (void*)this);
if ( m_def )
{
@@ -211,12 +211,12 @@
set_prototype(getVideoInterface(*this));
}
-video_stream_instance::~video_stream_instance()
+Video::~Video()
{
}
void
-video_stream_instance::display()
+Video::display()
{
// if m_def is NULL we've been constructed by 'new Video', in this
// case I think display() would never be invoked on us...
@@ -235,7 +235,7 @@
}
GnashImage*
-video_stream_instance::getVideoFrame()
+Video::getVideoFrame()
{
@@ -323,7 +323,7 @@
}
void
-video_stream_instance::stagePlacementCallback()
+Video::stagePlacementCallback()
{
saveOriginalTarget(); // for softref
@@ -333,7 +333,7 @@
void
-video_stream_instance::advance()
+Video::advance()
{
if (_ns) {
//_ns->advance();
@@ -342,7 +342,7 @@
}
void
-video_stream_instance::add_invalidated_bounds(InvalidatedRanges& ranges,
+Video::add_invalidated_bounds(InvalidatedRanges& ranges,
bool force)
{
if (!force && !m_invalidated) return; // no need to redraw
@@ -362,7 +362,7 @@
}
void
-video_stream_instance::setStream(boost::intrusive_ptr<NetStream_as> ns)
+Video::setStream(boost::intrusive_ptr<NetStream_as> ns)
{
_ns = ns;
_ns->setInvalidatedVideo(this);
@@ -389,7 +389,7 @@
}
rect
-video_stream_instance::getBounds() const
+Video::getBounds() const
{
if (_embeddedStream) return m_def->get_bound();
@@ -400,7 +400,7 @@
#ifdef GNASH_USE_GC
void
-video_stream_instance::markReachableResources() const
+Video::markReachableResources() const
{
if ( _ns ) _ns->setReachable();
=== renamed file 'libcore/video_stream_instance.h' => 'libcore/Video.h'
--- a/libcore/video_stream_instance.h 2008-10-27 16:05:13 +0000
+++ b/libcore/Video.h 2008-11-06 23:06:02 +0000
@@ -21,12 +21,17 @@
#define GNASH_VIDEO_STREAM_INSTANCE_H
#include "character.h" // for inheritance
-#include "video_stream_def.h"
-#include "snappingrange.h"
// Forward declarations
namespace gnash {
class NetStream_as;
+ class GnashImage;
+ namespace SWF {
+ class DefineVideoStreamTag;
+ }
+ namespace media {
+ class VideoDecoder;
+ }
}
namespace gnash {
@@ -37,17 +42,17 @@
/// embedded into the SWF itself or loaded from the
/// network using an associated NetStream object.
///
-class video_stream_instance : public character
+class Video : public character
{
public:
- boost::intrusive_ptr<video_stream_definition> m_def;
+ boost::intrusive_ptr<SWF::DefineVideoStreamTag> m_def;
- video_stream_instance(video_stream_definition* def,
- character* parent, int id);
+ Video(SWF::DefineVideoStreamTag* def, character* parent,
+ int id);
- ~video_stream_instance();
+ ~Video();
virtual bool pointInShape(boost::int32_t x, boost::int32_t y) const
{
=== modified file 'libcore/asobj/ClassHierarchy.cpp'
--- a/libcore/asobj/ClassHierarchy.cpp 2008-11-05 10:02:06 +0000
+++ b/libcore/asobj/ClassHierarchy.cpp 2008-11-06 23:06:02 +0000
@@ -52,7 +52,7 @@
#include "System_as.h"
#include "TextSnapshot_as.h"
#include "TextFormat.h"
-#include "video_stream_instance.h"
+#include "Video.h"
#include "extension.h"
#include "VM.h"
#include "timers.h"
=== modified file 'libcore/asobj/Global.cpp'
--- a/libcore/asobj/Global.cpp 2008-11-05 10:02:06 +0000
+++ b/libcore/asobj/Global.cpp 2008-11-06 23:06:02 +0000
@@ -58,7 +58,7 @@
#include "System_as.h"
#include "TextFormat.h"
#include "TextSnapshot_as.h"
-#include "video_stream_instance.h"
+#include "Video.h"
#include "extension.h"
#include "VM.h"
#include "timers.h"
=== modified file 'libcore/asobj/NetStream_as.h'
--- a/libcore/asobj/NetStream_as.h 2008-11-04 01:14:26 +0000
+++ b/libcore/asobj/NetStream_as.h 2008-11-06 23:06:02 +0000
@@ -29,7 +29,6 @@
#include "smart_ptr.h" // GNASH_USE_GC
#include "impl.h"
-#include "video_stream_instance.h"
#include "NetConnection.h"
#include "MediaParser.h"
#include "as_function.h" // for visibility of destructor by intrusive_ptr
=== modified file 'libcore/impl.cpp'
--- a/libcore/impl.cpp 2008-11-06 11:56:50 +0000
+++ b/libcore/impl.cpp 2008-11-06 22:57:43 +0000
@@ -47,6 +47,8 @@
#include "SetBackgroundColorTag.h"
#include "StartSoundTag.h"
#include "StreamSoundBlockTag.h"
+#include "DefineVideoStreamTag.h"
+#include "VideoFrameTag.h"
#include "swf/tag_loaders.h" // for all tag loaders..
#include "RunInfo.h"
#ifdef GNASH_USE_GC
@@ -166,8 +168,10 @@
register_tag_loader(SWF::INITACTION, DoInitActionTag::doInitActionLoader);
// 59
- register_tag_loader(SWF::DEFINEVIDEOSTREAM, define_video_loader); // 60
- register_tag_loader(SWF::VIDEOFRAME, video_loader); // 61
+ // 60
+ register_tag_loader(SWF::DEFINEVIDEOSTREAM, DefineVideoStreamTag::loader);
+ // 61
+ register_tag_loader(SWF::VIDEOFRAME, VideoFrameTag::loader);
// 62, DEFINEFONTINFO2 is done above.
// We're not an authoring tool.
=== modified file 'libcore/parser/Makefile.am'
--- a/libcore/parser/Makefile.am 2008-11-06 11:56:50 +0000
+++ b/libcore/parser/Makefile.am 2008-11-06 22:57:43 +0000
@@ -57,8 +57,7 @@
morph2_character_def.cpp \
shape_character_def.cpp \
sound_definition.cpp \
- sprite_definition.cpp \
- video_stream_def.cpp
+ sprite_definition.cpp
noinst_HEADERS = \
abc_block.h \
@@ -74,8 +73,7 @@
Namespace.h \
shape_character_def.h \
sound_definition.h \
- sprite_definition.h \
- video_stream_def.h
+ sprite_definition.h
libgnashparser_la_LIBADD = \
$(top_builddir)/libamf/libgnashamf.la \
=== modified file 'libcore/parser/morph2_character_def.cpp'
--- a/libcore/parser/morph2_character_def.cpp 2008-10-30 13:15:12 +0000
+++ b/libcore/parser/morph2_character_def.cpp 2008-11-07 08:37:30 +0000
@@ -97,200 +97,212 @@
};
- morph2_character_def::morph2_character_def():
- m_last_ratio(-1.0f)
- { /* Markus: No delete??? */
- m_shape1 = new shape_character_def();
- m_shape2 = new shape_character_def();
- }
-
-
- morph2_character_def::~morph2_character_def()
- {
- }
-
- void morph2_character_def::display(character* inst)
- {
+morph2_character_def::morph2_character_def():
+ m_last_ratio(-1.0f)
+{ /* Markus: No delete??? */
+ m_shape1 = new shape_character_def();
+ m_shape2 = new shape_character_def();
+}
+
+
+morph2_character_def::~morph2_character_def()
+{
+}
+
+void morph2_character_def::display(character* inst)
+{
// GNASH_REPORT_FUNCTION;
- unsigned int i = 0;
- float ratio = inst->get_ratio() / 65535.0;
- // bounds
- rect new_bound;
- new_bound.set_lerp(m_shape1->get_bound(),
m_shape2->get_bound(), ratio);
- set_bound(new_bound);
-
- // fill styles
- for (; i < m_fill_styles.size(); i++)
- {
- fill_style& fs = m_fill_styles[i];
-
- const fill_style& fs1 = m_shape1->get_fill_styles()[i];
- const fill_style& fs2 = m_shape2->get_fill_styles()[i];
-
- fs.set_lerp(fs1, fs2, ratio);
- }
-
- // line styles
- for (i=0; i < m_line_styles.size(); i++)
- {
- line_style& ls = m_line_styles[i];
-
- const line_style& ls1 = m_shape1->get_line_styles()[i];
- const line_style& ls2 = m_shape2->get_line_styles()[i];
-
- ls.set_lerp(ls1, ls2, ratio);
- }
-
- // This is used for cases in which number
- // of paths in start shape and end shape are not
- // the same.
- path empty_path;
- edge empty_edge;
-
- // shape
- unsigned int k=0, n=0;
- const std::vector<path>& paths1 = m_shape1->get_paths();
- const std::vector<path>& paths2 = m_shape2->get_paths();
- for (i=0; i < m_paths.size(); i++)
- {
- path& p = m_paths[i];
- const path& p1 = i < paths1.size() ? paths1[i] :
empty_path;
- const path& p2 = n < paths2.size() ? paths2[n] :
empty_path;
-
- float new_ax = utility::flerp(p1.ap.x, p2.ap.x, ratio);
- float new_ay = utility::flerp(p1.ap.y, p2.ap.y, ratio);
-
- p.reset ( new_ax, new_ay, p1.getLeftFill(),
p2.getRightFill(), p1.getLineStyle() );
-
- // edges;
- size_t len = p1.size();
- p.m_edges.resize(len);
-
- for (size_t j=0; j < p.size(); j++)
- {
- edge& e = p[j];
- const edge& e1 = j < p1.size() ? p1[j] :
empty_edge;
- const edge& e2 = k < p2.size() ? p2[k] :
empty_edge;
-
- e.cp.x =
static_cast<int>(utility::flerp(e1.cp.x, e2.cp.x, ratio));
- e.cp.y =
static_cast<int>(utility::flerp(e1.cp.y, e2.cp.y, ratio));
- e.ap.x =
static_cast<int>(utility::flerp(e1.ap.x, e2.ap.x, ratio));
- e.ap.y =
static_cast<int>(utility::flerp(e1.ap.y, e2.ap.y, ratio));
- k++;
- if (p2.size() <= k)
- {
- k=0; n++;
- }
- }
- }
+ unsigned int i = 0;
+ float ratio = inst->get_ratio() / 65535.0;
+ // bounds
+ rect new_bound;
+ new_bound.set_lerp(m_shape1->get_bound(), m_shape2->get_bound(), ratio);
+ set_bound(new_bound);
+
+ // fill styles
+ for (; i < m_fill_styles.size(); i++)
+ {
+ fill_style& fs = m_fill_styles[i];
+
+ const fill_style& fs1 = m_shape1->get_fill_styles()[i];
+ const fill_style& fs2 = m_shape2->get_fill_styles()[i];
+
+ fs.set_lerp(fs1, fs2, ratio);
+ }
+
+ // line styles
+ for (i=0; i < m_line_styles.size(); i++)
+ {
+ line_style& ls = m_line_styles[i];
+
+ const line_style& ls1 = m_shape1->get_line_styles()[i];
+ const line_style& ls2 = m_shape2->get_line_styles()[i];
+
+ ls.set_lerp(ls1, ls2, ratio);
+ }
+
+ // This is used for cases in which number
+ // of paths in start shape and end shape are not
+ // the same.
+ path empty_path;
+ edge empty_edge;
+
+ // shape
+ unsigned int k=0, n=0;
+ const std::vector<path>& paths1 = m_shape1->get_paths();
+ const std::vector<path>& paths2 = m_shape2->get_paths();
+ for (i=0; i < m_paths.size(); i++)
+ {
+ path& p = m_paths[i];
+ const path& p1 = i < paths1.size() ? paths1[i] : empty_path;
+ const path& p2 = n < paths2.size() ? paths2[n] : empty_path;
+
+ float new_ax = utility::flerp(p1.ap.x, p2.ap.x, ratio);
+ float new_ay = utility::flerp(p1.ap.y, p2.ap.y, ratio);
+
+ p.reset(new_ax, new_ay, p1.getLeftFill(),
+ p2.getRightFill(), p1.getLineStyle());
+
+ // edges;
+ size_t len = p1.size();
+ p.m_edges.resize(len);
+
+ for (size_t j=0; j < p.size(); j++)
+ {
+ edge& e = p[j];
+ const edge& e1 = j < p1.size() ? p1[j] : empty_edge;
+ const edge& e2 = k < p2.size() ? p2[k] : empty_edge;
+
+ e.cp.x = static_cast<int>(utility::flerp(e1.cp.x, e2.cp.x, ratio));
+ e.cp.y = static_cast<int>(utility::flerp(e1.cp.y, e2.cp.y, ratio));
+ e.ap.x = static_cast<int>(utility::flerp(e1.ap.x, e2.ap.x, ratio));
+ e.ap.y = static_cast<int>(utility::flerp(e1.ap.y, e2.ap.y, ratio));
+ k++;
+ if (p2.size() <= k)
+ {
+ k=0; n++;
+ }
+ }
+ }
// display
- {
- gnash::render::draw_shape_character(this, inst);
- }
-
- }
-
-
- void morph2_character_def::read(SWFStream& in, int tag_type,
movie_definition& md)
- {
- assert(tag_type == SWF::DEFINEMORPHSHAPE
- || tag_type == SWF::DEFINEMORPHSHAPE2
- || tag_type == SWF::DEFINEMORPHSHAPE2_);
-
- rect bound1, bound2;
- bound1.read(in);
- bound2.read(in);
-
- if (tag_type == SWF::DEFINEMORPHSHAPE2 || tag_type ==
SWF::DEFINEMORPHSHAPE2_)
- {
- // TODO: Use these values.
- rect inner_bound1, inner_bound2;
- inner_bound1.read(in);
- inner_bound2.read(in);
- // This should be used -- first 6 bits reserved, then
'non-scaling' stroke,
- // then 'scaling' stroke -- these can be used to optimize
morphing.
-
- in.ensureBytes(1);
- static_cast<void>(in.read_u8());
- }
-
- in.ensureBytes(4);
- offset = in.read_u32();
-
- // Next line will throw ParserException on malformed SWF
- fill_style_count = in.read_variable_count();
- int i;
- fill_style fs1, fs2;
- for (i = 0; i < fill_style_count; ++i)
- {
- fs1.read(in, tag_type, md, &fs2);
- m_shape1->m_fill_styles.push_back(fs1);
- m_shape2->m_fill_styles.push_back(fs2);
- }
-
- line_style_count = in.read_variable_count();
- line_style ls1, ls2;
- for (i = 0; i < line_style_count; ++i)
- {
- ls1.read_morph(in, tag_type, md, &ls2);
- m_shape1->m_line_styles.push_back(ls1);
- m_shape2->m_line_styles.push_back(ls2);
- }
-
- m_shape1->read(in, tag_type, false, md);
- in.align();
- m_shape2->read(in, tag_type, false, md);
-
- // Set bounds as read in *this* tags rather then
- // the one computed from shape_character_def parser
- // (does it make sense ?)
- m_shape1->set_bound(bound1);
- m_shape2->set_bound(bound2);
-
- assert(m_shape1->m_fill_styles.size() ==
m_shape2->m_fill_styles.size());
- assert(m_shape1->m_line_styles.size() ==
m_shape2->m_line_styles.size());
-
- // setup array size
- m_fill_styles.resize(m_shape1->m_fill_styles.size());
- unsigned int k;
- for (k = 0; k < m_fill_styles.size(); k++)
- {
- fill_style& fs = m_fill_styles[k];
- fill_style& fs1 = m_shape1->m_fill_styles[k];
- fs.m_gradients.resize(fs1.m_gradients.size());
- }
-
- m_line_styles.resize(m_shape1->m_line_styles.size());
- m_paths.resize(m_shape1->m_paths.size());
-
- unsigned edges_count1 =
PathList::computeNumberOfEdges(m_shape1->m_paths);
- unsigned edges_count2 =
PathList::computeNumberOfEdges(m_shape2->m_paths);
-
- IF_VERBOSE_PARSE(
- log_parse("morph: "
- "startShape(paths:%d, edges:%u), "
- "endShape(paths:%d, edges:%u)",
- m_shape1->m_paths.size(), edges_count1,
- m_shape2->m_paths.size(), edges_count2);
- );
-
- IF_VERBOSE_MALFORMED_SWF(
- // It is perfectly legal to have a different number of patsh,
- // edges count should be the same instead
- if ( edges_count1 != edges_count2 )
- {
- log_swferror(_("Different number of edges "
- "in start (%u) and end (%u) shapes "
- "of a morph"),
- edges_count1, edges_count1);
- }
-
- );
-
- }
+{
+gnash::render::draw_shape_character(this, inst);
+}
+
+}
+
+
+void morph2_character_def::read(SWFStream& in, int tag_type,
+ movie_definition& md)
+{
+ assert(tag_type == SWF::DEFINEMORPHSHAPE
+ || tag_type == SWF::DEFINEMORPHSHAPE2
+ || tag_type == SWF::DEFINEMORPHSHAPE2_);
+
+ rect bound1, bound2;
+ bound1.read(in);
+ bound2.read(in);
+
+ if (tag_type == SWF::DEFINEMORPHSHAPE2 ||
+ tag_type == SWF::DEFINEMORPHSHAPE2_)
+ {
+ // TODO: Use these values.
+ rect inner_bound1, inner_bound2;
+ inner_bound1.read(in);
+ inner_bound2.read(in);
+ // This should be used -- first 6 bits reserved, then
+ // 'non-scaling' stroke, then 'scaling' stroke -- these can be
+ // used to optimize morphing.
+
+ in.ensureBytes(1);
+ static_cast<void>(in.read_u8());
+ }
+
+ in.ensureBytes(4);
+ offset = in.read_u32();
+
+ // Next line will throw ParserException on malformed SWF
+ fill_style_count = in.read_variable_count();
+ int i;
+ fill_style fs1, fs2;
+ for (i = 0; i < fill_style_count; ++i)
+ {
+ fs1.read(in, tag_type, md, &fs2);
+ m_shape1->addFillStyle(fs1);
+ m_shape2->addFillStyle(fs2);
+ }
+
+ line_style_count = in.read_variable_count();
+ line_style ls1, ls2;
+ for (i = 0; i < line_style_count; ++i)
+ {
+ ls1.read_morph(in, tag_type, md, &ls2);
+ m_shape1->addLineStyle(ls1);
+ m_shape2->addLineStyle(ls2);
+ }
+
+ m_shape1->read(in, tag_type, false, md);
+ in.align();
+ m_shape2->read(in, tag_type, false, md);
+
+ // Set bounds as read in *this* tags rather then
+ // the one computed from shape_character_def parser
+ // (does it make sense ?)
+ m_shape1->set_bound(bound1);
+ m_shape2->set_bound(bound2);
+
+ const shape_character_def::FillStyleVect& s1Fills =
+ m_shape1->get_fill_styles();
+
+ const shape_character_def::LineStyleVect& s1Lines =
+ m_shape1->get_line_styles();
+
+ assert(s1Fills.size() == m_shape2->get_fill_styles().size());
+ assert(s1Lines.size() == m_shape2->get_line_styles().size());
+
+ // setup array size
+ m_fill_styles.resize(s1Fills.size());
+ unsigned int k;
+ for (k = 0; k < m_fill_styles.size(); k++)
+ {
+ fill_style& fs = m_fill_styles[k];
+ const fill_style& fs1 = s1Fills[k];
+ fs.m_gradients.resize(fs1.m_gradients.size());
+ }
+
+ m_line_styles.resize(s1Lines.size());
+ m_paths.resize(m_shape1->get_paths().size());
+
+ unsigned edges_count1 = PathList::computeNumberOfEdges(
+ m_shape1->get_paths());
+ unsigned edges_count2 = PathList::computeNumberOfEdges(
+ m_shape2->get_paths());
+
+ IF_VERBOSE_PARSE(
+ log_parse("morph: "
+ "startShape(paths:%d, edges:%u), "
+ "endShape(paths:%d, edges:%u)",
+ m_shape1->get_paths().size(), edges_count1,
+ m_shape2->get_paths().size(), edges_count2);
+ );
+
+ IF_VERBOSE_MALFORMED_SWF(
+ // It is perfectly legal to have a different number of paths,
+ // edges count should be the same instead
+ if ( edges_count1 != edges_count2 )
+ {
+ log_swferror(_("Different number of edges "
+ "in start (%u) and end (%u) shapes "
+ "of a morph"),
+ edges_count1, edges_count1);
+ }
+
+ );
+
+}
}
// Local Variables:
=== modified file 'libcore/parser/morph2_character_def.h'
--- a/libcore/parser/morph2_character_def.h 2008-10-30 13:15:12 +0000
+++ b/libcore/parser/morph2_character_def.h 2008-11-07 08:37:30 +0000
@@ -49,8 +49,8 @@
/// invalidated area when rendering morphs
virtual const rect& get_bound() const
{
- m_bound.expand_to_rect(m_shape1->m_bound);
- m_bound.expand_to_rect(m_shape2->m_bound);
+ m_bound.expand_to_rect(m_shape1->get_bound());
+ m_bound.expand_to_rect(m_shape2->get_bound());
return m_bound;
}
=== modified file 'libcore/parser/shape_character_def.cpp'
--- a/libcore/parser/shape_character_def.cpp 2008-10-30 13:15:12 +0000
+++ b/libcore/parser/shape_character_def.cpp 2008-11-06 22:57:43 +0000
@@ -38,12 +38,6 @@
// and compare them with the bounds encoded in the SWF
//#define GNASH_DEBUG_SHAPE_BOUNDS 1
-//#define DEBUG_DISPLAY_SHAPE_PATHS // won't probably work anymore (Udo)
-#ifdef DEBUG_DISPLAY_SHAPE_PATHS
-// For debugging only!
-bool gnash_debug_show_paths = false;
-#endif // DEBUG_DISPLAY_SHAPE_PATHS
-
namespace gnash
{
@@ -78,10 +72,10 @@
}
}
+// Read line styles and push them onto the back of the given array.
static void
read_line_styles(std::vector<line_style>& styles, SWFStream& in, int tag_type,
movie_definition& md)
-// Read line styles and push them onto the back of the given array.
{
in.ensureBytes(1);
int line_style_count = in.read_u8();
@@ -174,7 +168,8 @@
int num_line_bits = (num_bits & 0x0F);
IF_VERBOSE_PARSE(
- log_parse(_(" shape_character_def read: nfillbits = %d, nlinebits =
%d"), num_fill_bits, num_line_bits);
+ log_parse(_(" shape_character_def read: nfillbits = %d, "
+ "nlinebits = %d"), num_fill_bits, num_line_bits);
);
if ( !num_fill_bits && !num_line_bits )
@@ -193,9 +188,11 @@
/// Pretty ugly... till next bug report.
///
///
- if (tag_type == SWF::DEFINEFONT || tag_type == SWF::DEFINEFONT2 ||
tag_type == SWF::DEFINEFONT3)
+ if (tag_type == SWF::DEFINEFONT || tag_type == SWF::DEFINEFONT2 ||
+ tag_type == SWF::DEFINEFONT3)
{
- log_debug("Skipping glyph read, being fill and line bits zero. SWF
tag is %d.", tag_type);
+ log_debug("Skipping glyph read, being fill and line bits zero. "
+ "SWF tag is %d.", tag_type);
return;
}
}
@@ -255,11 +252,11 @@
current_path.ap.x = x;
current_path.ap.y = y;
- #if SHAPE_LOG
+#if SHAPE_LOG
IF_VERBOSE_PARSE(
log_parse(_(" shape_character read: moveto %d %d"), x, y);
);
- #endif
+#endif
}
if ((flags & flagFillStyle0Change) && num_fill_bits > 0)
{
@@ -278,12 +275,14 @@
style += fill_base;
}
- if ( tag_type == SWF::DEFINEFONT || tag_type ==
SWF::DEFINEFONT2 )
+ if (tag_type == SWF::DEFINEFONT || tag_type ==
SWF::DEFINEFONT2)
{
if ( style > 1 ) // 0:hide 1:renderer
{
IF_VERBOSE_MALFORMED_SWF(
- log_swferror(_("Invalid fill style %d in
fillStyle0Change record for font tag (0 or 1 valid). Set to 0."), style);
+ log_swferror(_("Invalid fill style %d in "
+ "fillStyle0Change record for font tag "
+ "(0 or 1 valid). Set to 0."), style);
);
style = 0;
}
@@ -294,18 +293,21 @@
if ( style > m_fill_styles.size() )
{
IF_VERBOSE_MALFORMED_SWF(
- log_swferror(_("Invalid fill style %d in
fillStyle0Change record - %d defined. Set to 0."), style, m_fill_styles.size());
- );
+ log_swferror(_("Invalid fill style %d in "
+ "fillStyle0Change record - %d defined. "
+ "Set to 0."), style,
m_fill_styles.size());
+ );
style = 0;
}
}
current_path.setLeftFill(style);
- #if SHAPE_LOG
+#if SHAPE_LOG
IF_VERBOSE_PARSE(
- log_parse(_(" shape_character read: fill0 (left) = %d"),
current_path.getLeftFill());
+ log_parse(_(" shape_character read: fill0 (left) = %d"),
+ current_path.getLeftFill());
);
- #endif
+#endif
}
if ((flags & flagFillStyle1Change) && num_fill_bits > 0)
{
@@ -324,12 +326,14 @@
style += fill_base;
}
- if ( tag_type == SWF::DEFINEFONT || tag_type ==
SWF::DEFINEFONT2 )
+ if (tag_type == SWF::DEFINEFONT || tag_type ==
SWF::DEFINEFONT2)
{
if ( style > 1 ) // 0:hide 1:renderer
{
IF_VERBOSE_MALFORMED_SWF(
- log_swferror(_("Invalid fill style %d in
fillStyle1Change record for font tag (0 or 1 valid). Set to 0."), style);
+ log_swferror(_("Invalid fill style %d in "
+ "fillStyle1Change record for font tag "
+ "(0 or 1 valid). Set to 0."), style);
);
style = 0;
}
@@ -340,17 +344,20 @@
if ( style > m_fill_styles.size() )
{
IF_VERBOSE_MALFORMED_SWF(
- log_swferror(_("Invalid fill style %d in
fillStyle1Change record - %d defined. Set to 0."), style, m_fill_styles.size());
+ log_swferror(_("Invalid fill style %d in "
+ "fillStyle1Change record - %d defined. "
+ "Set to 0."), style, m_fill_styles.size());
);
style = 0;
}
}
current_path.setRightFill(style);
- #if SHAPE_LOG
+#if SHAPE_LOG
IF_VERBOSE_PARSE (
- log_parse(_(" shape_character read: fill1 (right) = %d"),
current_path.getRightFill());
+ log_parse(_(" shape_character read: fill1 (right) = %d"),
+ current_path.getRightFill());
);
- #endif
+#endif
}
if ((flags & flagLineStyleChange) && num_line_bits > 0)
{
@@ -368,12 +375,14 @@
{
style += line_base;
}
- if ( tag_type == SWF::DEFINEFONT || tag_type ==
SWF::DEFINEFONT2 )
+ if (tag_type == SWF::DEFINEFONT || tag_type ==
SWF::DEFINEFONT2)
{
if ( style > 1 ) // 0:hide 1:renderer
{
IF_VERBOSE_MALFORMED_SWF(
- log_swferror(_("Invalid line style %d in
lineStyleChange record for font tag (0 or 1 valid). Set to 0."), style);
+ log_swferror(_("Invalid line style %d in "
+ "lineStyleChange record for font tag "
+ "(0 or 1 valid). Set to 0."), style);
);
style = 0;
}
@@ -384,24 +393,28 @@
if ( style > m_line_styles.size() )
{
IF_VERBOSE_MALFORMED_SWF(
- log_swferror(_("Invalid fill style %d in
lineStyleChange record - %d defined. Set to 0."), style, m_line_styles.size());
+ log_swferror(_("Invalid fill style %d in "
+ "lineStyleChange record - %d defined. "
+ "Set to 0."), style, m_line_styles.size());
);
style = 0;
}
}
current_path.setLineStyle(style);
- #if SHAPE_LOG
- IF_VERBOSE_PARSE (
- log_parse(_(" shape_character_read: line = %d"),
current_path.getLineStyle());
+#if SHAPE_LOG
+ IF_VERBOSE_PARSE(
+ log_parse(_(" shape_character_read: line = %d"),
+ current_path.getLineStyle());
)
- #endif
+#endif
}
if (flags & flagHasNewStyles)
{
if (!with_style)
{
IF_VERBOSE_MALFORMED_SWF(
- log_swferror("Unexpected HasNewStyle flag in tag %d
shape record", tag_type);
+ log_swferror("Unexpected HasNewStyle flag in tag "
+ "%d shape record", tag_type);
);
continue;
}
@@ -448,11 +461,12 @@
int ax = cx + in.read_sint(num_bits);
int ay = cy + in.read_sint(num_bits);
- #if SHAPE_LOG
+#if SHAPE_LOG
IF_VERBOSE_PARSE (
- log_parse(_(" shape_character read: curved edge = %d %d
- %d %d - %d %d"), x, y, cx, cy, ax, ay);
+ log_parse(_(" shape_character read: curved edge = "
+ "%d %d - %d %d - %d %d"), x, y, cx, cy, ax, ay);
);
- #endif
+#endif
current_path.m_edges.push_back(edge(cx, cy, ax, ay));
x = ax;
y = ay;
@@ -489,12 +503,14 @@
}
}
- #if SHAPE_LOG
+#if SHAPE_LOG
IF_VERBOSE_PARSE (
- log_parse(_(" shape_character_read: straight edge = %d
%d - %d %d"), x, y, x + dx, y + dy);
+ log_parse(_(" shape_character_read: straight edge = "
+ "%d %d - %d %d"), x, y, x + dx, y + dy);
);
- #endif
- current_path.m_edges.push_back(edge(x + dx, y + dy, x + dx, y
+ dy));
+#endif
+ current_path.m_edges.push_back(edge(x + dx, y + dy,
+ x + dx, y + dy));
x += dx;
y += dy;
}
@@ -507,527 +523,367 @@
// the bounds as edges are parsed.
compute_bound(&m_bound, m.get_version());
}
- #ifdef GNASH_DEBUG_SHAPE_BOUNDS
+#ifdef GNASH_DEBUG_SHAPE_BOUNDS
else
{
rect computedBounds;
compute_bound(&computedBounds, m->get_version());
if ( computedBounds != m_bounds )
{
- log_debug("Shape character read for tag %d contained embedded
bounds %s, while we computed bounds %s",
- tag_type, m_bound.toString().c_str(),
computedBounds.toString().c_str());
+ log_debug("Shape character read for tag %d contained embedded "
+ "bounds %s, while we computed bounds %s",
+ tag_type, m_bound, computedBounds);
}
}
- #endif // GNASH_DEBUG_SHAPE_BOUNDS
+#endif
}
- void shape_character_def::display(character* inst)
+void shape_character_def::display(character* inst)
+{
// Draw the shape using our own inherent styles.
- {
- gnash::render::draw_shape_character(this, inst);
- }
-
-#ifdef DEBUG_DISPLAY_SHAPE_PATHS
-
-#include "ogl.h"
-
- static void point_normalize(point* p)
- {
- float mag2 = p->x * p->x + p->y * p->y;
- if (mag2 < 1e-9f)
- {
- p->x = 1;
- p->y = 0;
- }
-
- float inv_mag = 1.0f / sqrtf(mag2);
- p->x *= inv_mag;
- p->y *= inv_mag;
- }
-
- static void show_fill_number(const point& p, int fill_number)
- {
- // We're inside a glBegin(GL_LINES)
-
- // Eh, let's do it in binary, least sig four bits...
- float x = p.x;
- float y = p.y;
-
- int mask = 8;
- while (mask)
- {
- if (mask & fill_number)
- {
- // Vert line --> 1.
- glVertex2f(x, y - 40.0f);
- glVertex2f(x, y + 40.0f);
- }
- else
- {
- // Rectangle --> 0.
- glVertex2f(x - 10.0f, y - 40.0f);
- glVertex2f(x + 10.0f, y - 40.0f);
-
- glVertex2f(x + 10.0f, y - 40.0f);
- glVertex2f(x + 10.0f, y + 40.0f);
-
- glVertex2f(x - 10.0f, y + 40.0f);
- glVertex2f(x + 10.0f, y + 40.0f);
-
- glVertex2f(x - 10.0f, y - 40.0f);
- glVertex2f(x - 10.0f, y + 40.0f);
- }
- x += 40.0f;
- mask >>= 1;
- }
- }
-
- static void debug_display_shape_paths(
- const SWFMatrix& mat,
- float /* object_space_max_error */,
- const std::vector<path>& paths,
- const std::vector<fill_style>& /* fill_styles */,
- const std::vector<line_style>& /* line_styles */)
- {
- for (unsigned int i = 0; i < paths.size(); i++)
- {
- const path& p = paths[i];
-
- if (p.getLeftFill() == 0 && p.getRightFill() == 0)
- {
- continue;
- }
-
- gnash::render::setMatrix(mat);
-
- // Color the line according to which side has
- // fills.
- if (p.getLeftFill() == 0) glColor4f(1, 0, 0, 0.5);
- else if (p.getRightFill() == 0) glColor4f(0, 1, 0, 0.5);
- else glColor4f(0, 0, 1, 0.5);
-
- // Offset according to which loop we are.
- float offset_x = (i & 1) * 80.0f;
- float offset_y = ((i & 2) >> 1) * 80.0f;
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glTranslatef(offset_x, offset_y, 0.f);
-
- point pt;
-
- glBegin(GL_LINE_STRIP);
-
- mat.transform(&pt, point(p.ap.x, p.ap.y));
- glVertex2f(pt.x, pt.y);
-
- for (unsigned int j = 0; j < p.m_edges.size(); j++)
- {
- mat.transform(&pt, point(p.m_edges[j].cp.x,
p.m_edges[j].cp.y));
- glVertex2f(pt.x, pt.y);
- mat.transform(&pt, point(p.m_edges[j].ap.x,
p.m_edges[j].ap.y));
- glVertex2f(pt.x, pt.y);
- }
-
- glEnd();
-
- // Draw arrowheads.
- point dir, right, p0, p1;
- glBegin(GL_LINES);
- {
- for (unsigned int j = 0; j < p.m_edges.size(); j++)
- {
- mat.transform(&p0, point(p.m_edges[j].cp.x,
p.m_edges[j].cp.y));
- mat.transform(&p1, point(p.m_edges[j].ap.x,
p.m_edges[j].ap.y));
- dir = point(p1.x - p0.x, p1.y - p0.y);
- point_normalize(&dir);
- right = point(-dir.y, dir.x); // perpendicular
-
- const float ARROW_MAG = 60.f; // TWIPS?
- if (p.getLeftFill() != 0)
- {
- glColor4f(0, 1, 0, 0.5);
- glVertex2f(p0.x,
- p0.y);
- glVertex2f(p0.x - dir.x * ARROW_MAG - right.x *
ARROW_MAG,
- p0.y - dir.y * ARROW_MAG - right.y * ARROW_MAG);
-
- show_fill_number(point(p0.x - right.x * ARROW_MAG * 4,
- p0.y - right.y * ARROW_MAG * 4),
- p.getLeftFill());
- }
- if (p.getRightFill() != 0)
- {
- glColor4f(1, 0, 0, 0.5);
- glVertex2f(p0.x,
- p0.y);
- glVertex2f(p0.x - dir.x * ARROW_MAG + right.x *
ARROW_MAG,
- p0.y - dir.y * ARROW_MAG + right.y * ARROW_MAG);
-
- show_fill_number(point(p0.x + right.x * ARROW_MAG * 4,
- p0.y + right.y * ARROW_MAG * 4),
- p.getRightFill());
- }
- }
- }
- glEnd();
-
- glPopMatrix();
- }
- }
-#endif // DEBUG_DISPLAY_SHAPE_PATHS
-
- void shape_character_def::display(
- const SWFMatrix& mat,
- const cxform& cx,
- const std::vector<fill_style>& fill_styles,
- const std::vector<line_style>& line_styles) const
- {
- shape_character_def* this_non_const =
const_cast<shape_character_def*>(this);
-
- render_handler* renderer = get_render_handler();
-
- renderer->draw_shape_character(this_non_const, mat, cx, fill_styles,
- line_styles);
- }
-
- // TODO: this should be moved to libgeometry or something
- int curve_x_crossings(float x0, float y0, float x1, float y1,
- float cx, float cy, float y, float &cross1, float &cross2)
- // Finds the quadratic bezier curve crossings with the line Y.
- // The function can have zero, one or two solutions (cross1, cross2). The
- // return value of the function is the number of solutions.
- // x0, y0 = start point of the curve
- // x1, y1 = end point of the curve (anchor, aka ax|ay)
- // cx, cy = control point of the curve
- // If there are two crossings, cross1 is the nearest to x0|y0 on the curve.
- {
- int count=0;
-
- // check if any crossings possible
- if ( ((y0 < y) && (y1 < y) && (cy < y))
- || ((y0 > y) && (y1 > y) && (cy > y)) )
- {
- // all above or below -- no possibility of crossing
- return 0;
- }
-
- // Quadratic bezier is:
- //
- // p = (1-t)^2 * a0 + 2t(1-t) * c + t^2 * a1
- //
- // We need to solve for x at y.
-
- // Use the quadratic formula.
-
- // Numerical Recipes suggests this variation:
- // q = -0.5 [b +sgn(b) sqrt(b^2 - 4ac)]
- // x1 = q/a; x2 = c/q;
-
- float A = y1 + y0 - 2 * cy;
- float B = 2 * (cy - y0);
- float C = y0 - y;
-
- float rad = B * B - 4 * A * C;
-
- if (rad < 0)
- {
- return 0;
+ gnash::render::draw_shape_character(this, inst);
+}
+
+void shape_character_def::display(const SWFMatrix& mat, const cxform& cx,
+ const std::vector<fill_style>& fill_styles,
+ const std::vector<line_style>& line_styles) const
+{
+ shape_character_def* this_non_const =
+ const_cast<shape_character_def*>(this);
+
+ render_handler* renderer = get_render_handler();
+
+ renderer->draw_shape_character(this_non_const, mat, cx, fill_styles,
+ line_styles);
+}
+
+// TODO: this should be moved to libgeometry or something
+// Finds the quadratic bezier curve crossings with the line Y.
+// The function can have zero, one or two solutions (cross1, cross2). The
+// return value of the function is the number of solutions.
+// x0, y0 = start point of the curve
+// x1, y1 = end point of the curve (anchor, aka ax|ay)
+// cx, cy = control point of the curve
+// If there are two crossings, cross1 is the nearest to x0|y0 on the curve.
+int curve_x_crossings(float x0, float y0, float x1, float y1,
+ float cx, float cy, float y, float &cross1, float &cross2)
+{
+ int count=0;
+
+ // check if any crossings possible
+ if ( ((y0 < y) && (y1 < y) && (cy < y))
+ || ((y0 > y) && (y1 > y) && (cy > y)) )
+ {
+ // all above or below -- no possibility of crossing
+ return 0;
+ }
+
+ // Quadratic bezier is:
+ //
+ // p = (1-t)^2 * a0 + 2t(1-t) * c + t^2 * a1
+ //
+ // We need to solve for x at y.
+
+ // Use the quadratic formula.
+
+ // Numerical Recipes suggests this variation:
+ // q = -0.5 [b +sgn(b) sqrt(b^2 - 4ac)]
+ // x1 = q/a; x2 = c/q;
+
+ float A = y1 + y0 - 2 * cy;
+ float B = 2 * (cy - y0);
+ float C = y0 - y;
+
+ float rad = B * B - 4 * A * C;
+
+ if (rad < 0)
+ {
+ return 0;
+ }
+ else
+ {
+ float q;
+ float sqrt_rad = sqrtf(rad);
+ if (B < 0)
+ {
+ q = -0.5f * (B - sqrt_rad);
}
else
{
- float q;
- float sqrt_rad = sqrtf(rad);
- if (B < 0)
- {
- q = -0.5f * (B - sqrt_rad);
- }
- else
- {
- q = -0.5f * (B + sqrt_rad);
- }
-
- // The old-school way.
- // float t0 = (-B + sqrt_rad) / (2 * A);
- // float t1 = (-B - sqrt_rad) / (2 * A);
-
- if (q != 0)
- {
- float t1 = C / q;
- if (t1 >= 0 && t1 < 1)
- {
- float x_at_t1 =
- x0 + 2 * (cx - x0) * t1 + (x1 + x0 - 2 * cx) * t1 * t1;
-
- count++;
- assert(count==1);
- cross1 = x_at_t1; // order is important!
- }
- }
-
- if (A != 0)
- {
- float t0 = q / A;
- if (t0 >= 0 && t0 < 1)
- {
- float x_at_t0 =
- x0 + 2 * (cx - x0) * t0 + (x1 + x0 - 2 * cx) * t0 * t0;
-
- count++;
- if (count==2)
- cross2 = x_at_t0; // order is important!
- else
- cross1 = x_at_t0;
- }
- }
-
- }
-
- return count;
- }
-
- bool shape_character_def::point_test_local(boost::int32_t x,
boost::int32_t y, SWFMatrix& wm)
- {
- /*
- Principle:
- For the fill of the shape, we project a ray from the test point to the
left
- side of the shape counting all crossings. When a line or curve segment
is
- crossed we add 1 if the left fill style is set. Regardless of the left
fill
- style we subtract 1 from the counter then the right fill style is set.
- This is true when the line goes in downward direction. If it goes
upward,
- the fill styles are reversed.
-
- The final counter value reveals if the point is inside the shape (and
depends
- on filling rule, see below).
- This method should not depend on subshapes and work for some malformed
- shapes situations:
- - wrong fill side (eg. left side set for a clockwise drawen rectangle)
- - intersecting paths
- */
- point pt(x, y);
-
- bool even_odd = true; // later we will need non-zero for glyphs...
(TODO)
-
- // FIXME: if the shape contains non-scaled strokes
- // we can't rely on boundary itself for a quick
- // way out. Bounds supposedly already include
- // thickness, so we might keep a flag telling us
- // whether *non_scaled* strokes are present
- // and if not still use the boundary check.
- // NOTE: just skipping this test breaks a corner-case
- // in DrawingApiTest (kind of a fill-leakage making
- // the collision detection find you inside a self-crossing
- // shape).
- //
- if (m_bound.point_test(x, y) == false)
- {
- return false;
- }
-
- unsigned npaths = m_paths.size();
- int counter = 0;
-
- // browse all paths
- for (unsigned pno=0; pno<npaths; pno++)
- {
- const path& pth = m_paths[pno];
- unsigned nedges = pth.m_edges.size();
-
- float next_pen_x = pth.ap.x;
- float next_pen_y = pth.ap.y;
- float pen_x, pen_y;
-
- if (pth.m_new_shape)
- {
- if ( ( even_odd && (counter % 2) != 0) ||
- (!even_odd && (counter != 0)) )
- {
- // the point is inside the previous subshape, so exit now
- return true;
- }
-
- counter=0;
- }
- if (pth.empty())
- continue;
-
- // If the path has a line style, check for strokes there
- if (pth.m_line != 0 )
- {
- assert(m_line_styles.size() >= pth.m_line);
- line_style& ls = m_line_styles[pth.m_line-1];
- double thickness = ls.getThickness();
- if (! thickness )
- {
- thickness = 20; // at least ONE PIXEL thick.
- }
- else if ( (!ls.scaleThicknessVertically()) &&
(!ls.scaleThicknessHorizontally()) )
- {
- // TODO: pass the SWFMatrix to withinSquareDistance
instead ?
- double xScale = wm.get_x_scale();
- double yScale = wm.get_y_scale();
- //log_debug("thickness:%d, xScale:%g, yScale:%g",
thickness, xScale, yScale);
- thickness *= std::max(xScale, yScale);
- //log_debug("after scaling, thickness:%d", thickness);
- }
- else if ( ls.scaleThicknessVertically() !=
ls.scaleThicknessHorizontally() )
- {
- LOG_ONCE( log_unimpl("Collision detection for
unidirectionally scaled strokes") );
- }
-
- double dist = thickness / 2.0;
- double sqdist = dist * dist;
- if (pth.withinSquareDistance(pt, sqdist))
- return true;
- }
-
- // browse all edges of the path
- for (unsigned eno=0; eno<nedges; eno++)
- {
- const edge& edg = pth.m_edges[eno];
- pen_x = next_pen_x;
- pen_y = next_pen_y;
- next_pen_x = edg.ap.x;
- next_pen_y = edg.ap.y;
-
- float cross1, cross2;
- int dir1, dir2 = 0; // +1 = downward, -1 = upward
- int crosscount = 0;
-
- if (edg.is_straight())
- {
- // ignore horizontal lines
- if (edg.ap.y == pen_y) // TODO: better check for small
difference?
- {
- continue;
- }
- // does this line cross the Y coordinate?
- if ( ((pen_y <= y) && (edg.ap.y >= y))
- || ((pen_y >= y) && (edg.ap.y <= y)) )
- {
-
- // calculate X crossing
- cross1 = pen_x + (edg.ap.x - pen_x) *
- (y - pen_y) / (edg.ap.y - pen_y);
-
- if (pen_y > edg.ap.y)
- dir1 = -1; // upward
- else
- dir1 = +1; // downward
-
- crosscount = 1;
- }
- else
- {
- // no crossing found
- crosscount = 0;
- }
- }
- else
- {
- // ==> curve case
- crosscount = curve_x_crossings(pen_x, pen_y, edg.ap.x,
edg.ap.y,
- edg.cp.x, edg.cp.y, y, cross1, cross2);
- dir1 = pen_y > y ? -1 : +1;
- dir2 = dir1 * (-1); // second crossing always in opposite
dir.
- } // curve
-
- // ==> we have now:
- // - one (cross1) or two (cross1, cross2) ray crossings (X
coordinate)
- // - dir1/dir2 tells the direction of the crossing
- // (+1 = downward, -1 = upward)
- // - crosscount tells the number of crossings
-
- // need at least one crossing
- if (crosscount == 0)
+ q = -0.5f * (B + sqrt_rad);
+ }
+
+ // The old-school way.
+ // float t0 = (-B + sqrt_rad) / (2 * A);
+ // float t1 = (-B - sqrt_rad) / (2 * A);
+
+ if (q != 0)
+ {
+ float t1 = C / q;
+ if (t1 >= 0 && t1 < 1)
+ {
+ float x_at_t1 =
+ x0 + 2 * (cx - x0) * t1 + (x1 + x0 - 2 * cx) * t1 * t1;
+
+ count++;
+ assert(count==1);
+ cross1 = x_at_t1; // order is important!
+ }
+ }
+
+ if (A != 0)
+ {
+ float t0 = q / A;
+ if (t0 >= 0 && t0 < 1)
+ {
+ float x_at_t0 =
+ x0 + 2 * (cx - x0) * t0 + (x1 + x0 - 2 * cx) * t0 * t0;
+
+ count++;
+ // order is important!
+ if (count == 2) cross2 = x_at_t0;
+ else cross1 = x_at_t0;
+ }
+ }
+
+ }
+
+ return count;
+}
+
+bool shape_character_def::point_test_local(boost::int32_t x,
+ boost::int32_t y, SWFMatrix& wm)
+{
+ /*
+ Principle:
+ For the fill of the shape, we project a ray from the test point to the left
+ side of the shape counting all crossings. When a line or curve segment is
+ crossed we add 1 if the left fill style is set. Regardless of the left fill
+ style we subtract 1 from the counter then the right fill style is set.
+ This is true when the line goes in downward direction. If it goes upward,
+ the fill styles are reversed.
+
+ The final counter value reveals if the point is inside the shape (and
+ depends on filling rule, see below).
+ This method should not depend on subshapes and work for some malformed
+ shapes situations:
+ - wrong fill side (eg. left side set for a clockwise drawen rectangle)
+ - intersecting paths
+ */
+ point pt(x, y);
+
+ // later we will need non-zero for glyphs... (TODO)
+ bool even_odd = true;
+
+ // FIXME: if the shape contains non-scaled strokes
+ // we can't rely on boundary itself for a quick
+ // way out. Bounds supposedly already include
+ // thickness, so we might keep a flag telling us
+ // whether *non_scaled* strokes are present
+ // and if not still use the boundary check.
+ // NOTE: just skipping this test breaks a corner-case
+ // in DrawingApiTest (kind of a fill-leakage making
+ // the collision detection find you inside a self-crossing
+ // shape).
+ //
+ if (m_bound.point_test(x, y) == false)
+ {
+ return false;
+ }
+
+ unsigned npaths = m_paths.size();
+ int counter = 0;
+
+ // browse all paths
+ for (unsigned pno=0; pno<npaths; pno++)
+ {
+ const path& pth = m_paths[pno];
+ unsigned nedges = pth.m_edges.size();
+
+ float next_pen_x = pth.ap.x;
+ float next_pen_y = pth.ap.y;
+ float pen_x, pen_y;
+
+ if (pth.m_new_shape)
+ {
+ if ( ( even_odd && (counter % 2) != 0) ||
+ (!even_odd && (counter != 0)) )
+ {
+ // the point is inside the previous subshape, so exit now
+ return true;
+ }
+
+ counter=0;
+ }
+ if (pth.empty()) continue;
+
+ // If the path has a line style, check for strokes there
+ if (pth.m_line != 0 )
+ {
+ assert(m_line_styles.size() >= pth.m_line);
+ line_style& ls = m_line_styles[pth.m_line-1];
+ double thickness = ls.getThickness();
+ if (! thickness )
+ {
+ thickness = 20; // at least ONE PIXEL thick.
+ }
+ else if ((!ls.scaleThicknessVertically()) &&
+ (!ls.scaleThicknessHorizontally()) )
+ {
+ // TODO: pass the SWFMatrix to withinSquareDistance instead ?
+ double xScale = wm.get_x_scale();
+ double yScale = wm.get_y_scale();
+ //log_debug("thickness:%d, xScale:%g, yScale:%g", thickness, xScale,
yScale);
+ thickness *= std::max(xScale, yScale);
+ //log_debug("after scaling, thickness:%d", thickness);
+ }
+ else if (ls.scaleThicknessVertically() !=
+ ls.scaleThicknessHorizontally())
+ {
+ LOG_ONCE( log_unimpl("Collision detection for "
+ "unidirectionally scaled strokes") );
+ }
+
+ double dist = thickness / 2.0;
+ double sqdist = dist * dist;
+ if (pth.withinSquareDistance(pt, sqdist))
+ return true;
+ }
+
+ // browse all edges of the path
+ for (unsigned eno=0; eno<nedges; eno++)
+ {
+ const edge& edg = pth.m_edges[eno];
+ pen_x = next_pen_x;
+ pen_y = next_pen_y;
+ next_pen_x = edg.ap.x;
+ next_pen_y = edg.ap.y;
+
+ float cross1, cross2;
+ int dir1, dir2 = 0; // +1 = downward, -1 = upward
+ int crosscount = 0;
+
+ if (edg.is_straight())
+ {
+ // ignore horizontal lines
+ // TODO: better check for small difference?
+ if (edg.ap.y == pen_y)
{
continue;
}
-
- bool touched=false;
-
- // check first crossing
- if (cross1 <= x)
- {
- if (pth.m_fill0 > 0) counter += dir1;
- if (pth.m_fill1 > 0) counter -= dir1;
-
- touched = true;
- }
-
- // check optional second crossing (only possible with curves)
- if ( (crosscount > 1) && (cross2 <= x) )
- {
- if (pth.m_fill0 > 0) counter += dir2;
- if (pth.m_fill1 > 0) counter -= dir2;
-
- touched = true;
- }
-
- }// for edge
- } // for path
-
- return ( (even_odd && (counter % 2) != 0) ||
- (!even_odd && (counter != 0)) );
- }
-
- // Find the bounds of this shape, and store them in the given rectangle.
- void shape_character_def::compute_bound(rect* r, int swfVersion) const
+ // does this line cross the Y coordinate?
+ if ( ((pen_y <= y) && (edg.ap.y >= y))
+ || ((pen_y >= y) && (edg.ap.y <= y)) )
+ {
+
+ // calculate X crossing
+ cross1 = pen_x + (edg.ap.x - pen_x) *
+ (y - pen_y) / (edg.ap.y - pen_y);
+
+ if (pen_y > edg.ap.y)
+ dir1 = -1; // upward
+ else
+ dir1 = +1; // downward
+
+ crosscount = 1;
+ }
+ else
+ {
+ // no crossing found
+ crosscount = 0;
+ }
+ }
+ else
+ {
+ // ==> curve case
+ crosscount = curve_x_crossings(pen_x, pen_y, edg.ap.x,
edg.ap.y,
+ edg.cp.x, edg.cp.y, y, cross1, cross2);
+ dir1 = pen_y > y ? -1 : +1;
+ dir2 = dir1 * (-1); // second crossing always in opposite dir.
+ } // curve
+
+ // ==> we have now:
+ // - one (cross1) or two (cross1, cross2) ray crossings (X
+ // coordinate)
+ // - dir1/dir2 tells the direction of the crossing
+ // (+1 = downward, -1 = upward)
+ // - crosscount tells the number of crossings
+
+ // need at least one crossing
+ if (crosscount == 0)
+ {
+ continue;
+ }
+
+ bool touched = false;
+
+ // check first crossing
+ if (cross1 <= x)
+ {
+ if (pth.m_fill0 > 0) counter += dir1;
+ if (pth.m_fill1 > 0) counter -= dir1;
+
+ touched = true;
+ }
+
+ // check optional second crossing (only possible with curves)
+ if ( (crosscount > 1) && (cross2 <= x) )
+ {
+ if (pth.m_fill0 > 0) counter += dir2;
+ if (pth.m_fill1 > 0) counter -= dir2;
+
+ touched = true;
+ }
+
+ }// for edge
+ } // for path
+
+ return ( (even_odd && (counter % 2) != 0) ||
+ (!even_odd && (counter != 0)) );
+}
+
+// Find the bounds of this shape, and store them in the given rectangle.
+void
+shape_character_def::compute_bound(rect* r, int swfVersion) const
+{
+ r->set_null();
+
+ for (unsigned int i = 0; i < m_paths.size(); i++)
{
- r->set_null();
+ const path& p = m_paths[i];
- for (unsigned int i = 0; i < m_paths.size(); i++)
+ unsigned thickness = 0;
+ if ( p.m_line )
{
- const path& p = m_paths[i];
-
- unsigned thickness = 0;
- if ( p.m_line )
- {
- // For glyph shapes m_line is allowed to be 1
- // while no defined line styles are allowed.
- if ( m_line_styles.empty() )
- {
- // This is either a Glyph, for which m_line==1 is valid
- // or a bug in the parser, which we have no way to
- // check at this time
- assert(p.m_line == 1);
- }
- else
- {
- thickness = m_line_styles[p.m_line-1].getThickness();
- }
- }
- p.expandBounds(*r, thickness, swfVersion);
+ // For glyph shapes m_line is allowed to be 1
+ // while no defined line styles are allowed.
+ if ( m_line_styles.empty() )
+ {
+ // This is either a Glyph, for which m_line==1 is valid
+ // or a bug in the parser, which we have no way to
+ // check at this time
+ assert(p.m_line == 1);
+ }
+ else
+ {
+ thickness = m_line_styles[p.m_line-1].getThickness();
+ }
}
+ p.expandBounds(*r, thickness, swfVersion);
}
+}
#ifdef GNASH_USE_GC
- void shape_character_def::markReachableResources() const
- {
- assert(isReachable());
- for (FillStyleVect::const_iterator i=m_fill_styles.begin(),
e=m_fill_styles.end();
- i != e; ++i)
- {
- i->markReachableResources();
- }
- }
-#endif // GNASH_USE_GC
-
- size_t shape_character_def::numPaths() const
- {
- return m_paths.size();
- }
-
- size_t shape_character_def::numEdges() const
- {
- typedef std::vector<path> PathList;
-
- size_t count = 0;
- for (PathList::const_iterator i=m_paths.begin(), ie=m_paths.end();
i!=ie; ++i)
- {
- count += i->size();
- }
- return count;
- }
+void shape_character_def::markReachableResources() const
+{
+ assert(isReachable());
+ for (FillStyleVect::const_iterator i=m_fill_styles.begin(),
+ e=m_fill_styles.end(); i != e; ++i)
+ {
+ i->markReachableResources();
+ }
+}
+#endif
} // end namespace gnash
=== modified file 'libcore/parser/shape_character_def.h'
--- a/libcore/parser/shape_character_def.h 2008-10-30 13:15:12 +0000
+++ b/libcore/parser/shape_character_def.h 2008-11-07 08:37:30 +0000
@@ -49,7 +49,8 @@
/// Incoming coords are local coords (twips).
/// The SWFMatrix will be used for lines with non-scalable strokes.
///
- virtual bool point_test_local(boost::int32_t x, boost::int32_t y,
SWFMatrix& wm);
+ virtual bool point_test_local(boost::int32_t x, boost::int32_t y,
+ SWFMatrix& wm);
/// \brief
/// Read a shape definition as included in DEFINEFONT*,
@@ -73,12 +74,10 @@
/// The movie definition corresponding to the SWF we/re parsing.
/// This is used to resolve bitmap characters for fill styles, never
/// used if with_style is false.
- ///
- void read(SWFStream& in, int tag_type, bool with_style, movie_definition&
m);
+ void read(SWFStream& in, int tag_type, bool with_style,
+ movie_definition& m);
- void display(
- const SWFMatrix& mat,
- const cxform& cx,
+ void display(const SWFMatrix& mat, const cxform& cx,
const std::vector<fill_style>& fill_styles,
const std::vector<line_style>& line_styles) const;
@@ -86,7 +85,7 @@
const rect& get_bound() const { return m_bound; }
/// Compute bounds by looking at the component paths
- void compute_bound(rect* r, int swfVersion) const;
+ void compute_bound(rect* r, int swfVersion) const;
const FillStyleVect& get_fill_styles() const { return m_fill_styles; }
const LineStyleVect& get_line_styles() const { return m_line_styles; }
@@ -94,15 +93,20 @@
const std::vector<path>& get_paths() const { return m_paths; }
// morph uses this
- void set_bound(const rect& r) { m_bound = r; /* should do some
verifying */ }
-
- size_t numEdges() const;
-
- size_t numPaths() const;
+ // Should this be verified?
+ void set_bound(const rect& r) { m_bound = r; }
+
+ // Morph uses this.
+ void addFillStyle(const fill_style& fs) {
+ m_fill_styles.push_back(fs);
+ }
+
+ void addLineStyle(const line_style& fs) {
+ m_line_styles.push_back(fs);
+ }
protected:
- friend class morph2_character_def;
#ifdef GNASH_USE_GC
/// Mark reachable resources (for the GC)
//
=== renamed file 'libcore/parser/video_stream_def.cpp' =>
'libcore/swf/DefineVideoStreamTag.cpp'
--- a/libcore/parser/video_stream_def.cpp 2008-09-06 07:35:31 +0000
+++ b/libcore/swf/DefineVideoStreamTag.cpp 2008-11-06 23:06:02 +0000
@@ -17,29 +17,26 @@
//
-#include "video_stream_def.h"
-#include "video_stream_instance.h"
-#include "render.h"
-#include "BitsReader.h"
-//#include "MediaHandler.h"
+#include "DefineVideoStreamTag.h"
+#include "Video.h"
#include "MediaParser.h" // for VideoInfo
#include "VideoDecoder.h"
#include "SWFStream.h" // for read()
-
-#include <boost/bind.hpp>
-
+#include "movie_definition.h"
namespace gnash {
+namespace SWF {
-video_stream_definition::video_stream_definition(boost::uint16_t char_id)
+DefineVideoStreamTag::DefineVideoStreamTag(SWFStream& in, boost::uint16_t
char_id)
:
m_char_id(char_id),
_width(0),
_height(0)
{
+ read(in);
}
-video_stream_definition::~video_stream_definition()
+DefineVideoStreamTag::~DefineVideoStreamTag()
{
std::for_each(_video_frames.begin(), _video_frames.end(),
boost::checked_deleter<media::EncodedVideoFrame>());
@@ -47,11 +44,24 @@
void
-video_stream_definition::readDefineVideoStream(SWFStream& in, SWF::tag_type
tag, movie_definition& /*m*/)
-{
- // Character ID has been read already, and was loaded in the constructor
-
- assert(tag == SWF::DEFINEVIDEOSTREAM);
+DefineVideoStreamTag::loader(SWFStream& in, SWF::tag_type tag,
+ movie_definition& m, const RunInfo& /*r*/)
+{
+ assert(tag == SWF::DEFINEVIDEOSTREAM); // 60
+
+ in.ensureBytes(2);
+ boost::uint16_t id = in.read_u16();
+
+ std::auto_ptr<DefineVideoStreamTag> vs(new DefineVideoStreamTag(in, id));
+
+ m.add_character(id, vs.release());
+
+}
+
+void
+DefineVideoStreamTag::read(SWFStream& in)
+{
+
assert(!_videoInfo.get()); // allowed to be called only once
//m_start_frame = m->get_loading_frame();
@@ -83,50 +93,23 @@
return;
}
- _videoInfo.reset( new media::VideoInfo(m_codec_id, _width, _height, 0
/*framerate*/, 0 /*duration*/, media::FLASH /*typei*/) );
+ _videoInfo.reset(new media::VideoInfo(m_codec_id, _width, _height,
+ 0 /*framerate*/, 0 /*duration*/, media::FLASH /*typei*/));
}
void
-video_stream_definition::readDefineVideoFrame(SWFStream& in, SWF::tag_type
tag, movie_definition& /*m*/)
+DefineVideoStreamTag::addVideoFrameTag(
+ std::auto_ptr<media::EncodedVideoFrame> frame)
{
- // Character ID has been read already, and was loaded in the constructor
-
- assert(tag == SWF::VIDEOFRAME);
-
- // TODO: skip if there's no MediaHandler registered ?
-
- in.ensureBytes(2);
- unsigned int frameNum = in.read_u16();
-
- const unsigned int dataLength = in.get_tag_end_position() - in.tell();
-
- boost::uint8_t* buffer = new uint8_t[dataLength + 8]; // FIXME: catch
bad_alloc
-
- const size_t bytesRead = in.read(reinterpret_cast<char*>(buffer),
dataLength);
-
- if (bytesRead < dataLength)
- {
- throw ParserException(_("Could not read enough bytes when parsing "
- "VideoFrame tag. Perhaps we reached the "
- "end of the stream!"));
- }
-
- memset(buffer + bytesRead, 0, 8);
-
- using namespace media;
-
- EncodedVideoFrame* frame = new EncodedVideoFrame(buffer, dataLength,
frameNum);
-
boost::mutex::scoped_lock lock(_video_mutex);
- _video_frames.push_back(frame);
+ _video_frames.push_back(frame.release());
}
-
character*
-video_stream_definition::create_character_instance(character* parent, int id)
+DefineVideoStreamTag::create_character_instance(character* parent, int id)
{
- character* ch = new video_stream_instance(this, parent, id);
+ character* ch = new Video(this, parent, id);
return ch;
}
@@ -137,13 +120,14 @@
}
void
-video_stream_definition::getEncodedFrameSlice(boost::uint32_t from,
boost::uint32_t to, EmbedFrameVec& ret)
+DefineVideoStreamTag::getEncodedFrameSlice(boost::uint32_t from,
+ boost::uint32_t to, EmbeddedFrames& ret)
{
assert(from<=to);
boost::mutex::scoped_lock lock(_video_mutex);
- EmbedFrameVec::iterator it=_video_frames.begin(),
itEnd=_video_frames.end();
+ EmbeddedFrames::iterator it=_video_frames.begin(),
itEnd=_video_frames.end();
for (; it!=itEnd; ++it)
{
media::EncodedVideoFrame* frame = *it;
@@ -165,6 +149,6 @@
}
-
+} // namespace SWF
} // namespace gnash
=== renamed file 'libcore/parser/video_stream_def.h' =>
'libcore/swf/DefineVideoStreamTag.h'
--- a/libcore/parser/video_stream_def.h 2008-10-27 16:05:13 +0000
+++ b/libcore/swf/DefineVideoStreamTag.h 2008-11-06 22:57:43 +0000
@@ -17,40 +17,38 @@
//
-#ifndef GNASH_VIDEO_STREAM_DEF_H
-#define GNASH_VIDEO_STREAM_DEF_H
+#ifndef GNASH_SWF_DEFINEVIDEOSTREAMTAG_H
+#define GNASH_SWF_DEFINEVIDEOSTREAMTAG_H
#ifdef HAVE_CONFIG_H
#include "gnashconfig.h"
#endif
#include "character_def.h"
-#include "movie_definition.h"
#include "swf.h"
#include "rect.h" // for composition
-#include "ControlTag.h"
-#include "VideoDecoder.h"
#include "MediaParser.h" // for videoFrameType and videoCodecType enums
-#include "GnashImage.h"
-
#include <boost/shared_array.hpp>
-#include <boost/shared_ptr.hpp>
#include <boost/thread/mutex.hpp>
#include <memory> // for auto_ptr
-namespace gnash {
-
// Forward declarations
-class SWFStream;
+namespace gnash {
+ class movie_definition;
+ class SWFStream;
+ class RunInfo;
+}
+namespace gnash {
/// Class used to store data for the undecoded embedded video frames.
/// Contains the data, the data size and the type of the frame
class VideoData {
public:
- VideoData(boost::shared_array<boost::uint8_t> data, boost::uint32_t
size, media::videoFrameType ft)
+ VideoData(boost::shared_array<boost::uint8_t> data, boost::uint32_t
size,
+ media::videoFrameType ft)
:
videoData(data),
dataSize(size),
@@ -67,20 +65,21 @@
media::videoFrameType frameType;
};
-class video_stream_definition : public character_def
+namespace SWF {
+
+class DefineVideoStreamTag : public character_def
{
public:
/// Construct a video stream definition with given ID
//
- /// NOTE: for dynamically created definitions (ActionScript Video class
instances)
- /// you can use an id of -1. See character_def constructor, as
that's the
- /// one which will eventually get passed the id.
- ///
- video_stream_definition(boost::uint16_t char_id);
-
- ~video_stream_definition();
-
+ /// NOTE: for dynamically created definitions (ActionScript Video class
+ /// instances) you can use an id of -1. See character_def
+ /// constructor, as that's the one which will eventually get passed
+ /// the id.
+ DefineVideoStreamTag(SWFStream& in, boost::uint16_t id);
+
+ ~DefineVideoStreamTag();
character* create_character_instance(character* parent, int id);
@@ -91,17 +90,19 @@
/// This function is allowed to be called only *once* for each
/// instance of this class.
///
- void readDefineVideoStream(SWFStream& in, SWF::tag_type tag,
movie_definition& m);
+ static void loader(SWFStream& in, SWF::tag_type tag, movie_definition&
m,
+ const RunInfo& r);
+
/// Read tag SWF::VIDEOFRAME
//
- /// The character_id (used to find this instance in the character's
dictionary)
- /// is assumed to have been already read.
+ /// The character_id (used to find this instance in the character's
+ /// dictionary) is assumed to have been already read.
///
/// This function is allowed to be called zero or more times, as long
/// as readDefineVideoStream was read before.
- ///
- void readDefineVideoFrame(SWFStream& in, SWF::tag_type tag,
movie_definition& m);
+ void readDefineVideoFrame(SWFStream& in, SWF::tag_type tag,
+ movie_definition& m);
/// Return local video bounds in twips
const rect& get_bound() const
@@ -135,9 +136,13 @@
void getEncodedFrameSlice(boost::uint32_t from, boost::uint32_t to,
std::vector<media::EncodedVideoFrame*>& ret);
+
+ void addVideoFrameTag(std::auto_ptr<media::EncodedVideoFrame> frame);
private:
+ void read(SWFStream& in);
+
/// Id of this character definition, set by constructor.
///
/// The id is currently set to -1 when the definition is actually
@@ -175,17 +180,17 @@
/// Bounds of the video, as read from the DEFINEVIDEOSTREAM tag.
rect m_bound;
- /// The undecoded video frames and its size, using the swf-frame number
as key
+ /// The undecoded video frames and its size, using the swf-frame number
+ /// as key
//
/// Elements of this vector are owned by this instance, and will be
deleted
/// at instance destruction time.
///
- typedef std::vector<media::EncodedVideoFrame*> EmbedFrameVec;
+ typedef std::vector<media::EncodedVideoFrame*> EmbeddedFrames;
boost::mutex _video_mutex;
-
- EmbedFrameVec _video_frames;
+ EmbeddedFrames _video_frames;
/// Width of the video
boost::uint32_t _width;
@@ -195,13 +200,14 @@
/// Info about embedded video
//
- /// TODO: drop _width/_height/m_codec_id leaving all in this member
instead ?
- ///
+ /// TODO: drop _width/_height/m_codec_id leaving all in this member
+ /// instead ?
std::auto_ptr<media::VideoInfo> _videoInfo;
};
-} // end namespace gnash
+} // namespace SWF
+} // namespace gnash
#endif // GNASH_VIDEO_STREAM_DEF_H
=== added file 'libcore/swf/VideoFrameTag.cpp'
--- a/libcore/swf/VideoFrameTag.cpp 1970-01-01 00:00:00 +0000
+++ b/libcore/swf/VideoFrameTag.cpp 2008-11-06 23:21:13 +0000
@@ -0,0 +1,93 @@
+//
+// Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+#include "DefineVideoStreamTag.h"
+#include "VideoFrameTag.h"
+#include "VideoDecoder.h"
+#include "SWFStream.h" // for read()
+#include "movie_definition.h"
+#include "utility.h"
+
+#include <algorithm>
+
+namespace gnash {
+namespace SWF {
+
+
+void
+VideoFrameTag::loader(SWFStream& in, SWF::tag_type tag, movie_definition& m,
+ const RunInfo& /*r*/)
+{
+ assert(tag == SWF::VIDEOFRAME);
+
+ in.ensureBytes(2);
+ boost::uint16_t character_id = in.read_u16();
+ character_def* chdef = m.get_character_def(character_id);
+
+ if (!chdef)
+ {
+ IF_VERBOSE_MALFORMED_SWF(
+ log_swferror(_("VideoFrame tag refers to unknown video "
+ "stream id %d"), character_id);
+ );
+ return;
+ }
+
+ DefineVideoStreamTag* vs = dynamic_cast<DefineVideoStreamTag*> (chdef);
+ if (!vs)
+ {
+ IF_VERBOSE_MALFORMED_SWF(
+ log_swferror(_("VideoFrame tag refers to a non-video character "
+ "%d (%s)"), character_id, typeName(*chdef));
+ );
+ return;
+ }
+
+ // TODO: skip if there's no MediaHandler registered ?
+
+ in.ensureBytes(2);
+ unsigned int frameNum = in.read_u16();
+
+ const unsigned int dataLength = in.get_tag_end_position() - in.tell();
+
+ // FIXME: catch bad_alloc
+ boost::uint8_t* buffer = new uint8_t[dataLength + 8];
+
+ const size_t bytesRead = in.read(reinterpret_cast<char*>(buffer),
+ dataLength);
+
+ if (bytesRead < dataLength)
+ {
+ throw ParserException(_("Could not read enough bytes when parsing "
+ "VideoFrame tag. Perhaps we reached the "
+ "end of the stream!"));
+ }
+
+ std::fill_n(buffer + bytesRead, 8, 0);
+
+ using namespace media;
+
+ std::auto_ptr<EncodedVideoFrame> frame(
+ new EncodedVideoFrame(buffer, dataLength, frameNum));
+
+ vs->addVideoFrameTag(frame);
+}
+
+} // namespace SWF
+} // namespace gnash
+
=== added file 'libcore/swf/VideoFrameTag.h'
--- a/libcore/swf/VideoFrameTag.h 1970-01-01 00:00:00 +0000
+++ b/libcore/swf/VideoFrameTag.h 2008-11-06 22:57:43 +0000
@@ -0,0 +1,64 @@
+//
+// Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+//
+
+#ifndef GNASH_SWF_VIDEOFRAMETAG_H
+#define GNASH_SWF_VIDEOFRAMETAG_H
+
+#ifdef HAVE_CONFIG_H
+#include "gnashconfig.h"
+#endif
+
+#include "character_def.h"
+#include "movie_definition.h"
+#include "swf.h"
+#include "rect.h" // for composition
+#include "ControlTag.h"
+#include "VideoDecoder.h"
+
+#include <memory> // for auto_ptr
+
+namespace gnash {
+ // Forward declarations
+ class SWFStream;
+}
+
+namespace gnash {
+namespace SWF {
+
+class VideoFrameTag
+{
+public:
+
+ /// Read tag SWF::VIDEOFRAME
+ //
+ /// The character_id (used to find this instance in the character's
+ /// dictionary) is assumed to have been already read.
+ ///
+ /// This function is allowed to be called zero or more times, as long
+ /// as a DefineVideoStreamTag was read before.
+ static void loader(SWFStream& in, SWF::tag_type tag, movie_definition&
m,
+ const RunInfo& r);
+
+};
+
+} // namespace SWF
+} // namespace gnash
+
+
+#endif // GNASH_VIDEO_STREAM_DEF_H
=== modified file 'libcore/swf/tag_loaders.cpp'
--- a/libcore/swf/tag_loaders.cpp 2008-11-06 11:56:50 +0000
+++ b/libcore/swf/tag_loaders.cpp 2008-11-06 22:57:43 +0000
@@ -52,7 +52,7 @@
#include "text_character_def.h"
#include "URL.h"
#include "GnashException.h"
-#include "video_stream_def.h"
+#include "swf/DefineVideoStreamTag.h"
#include "sound_definition.h"
#include "abc_block.h"
#include "SoundInfo.h"
@@ -1442,54 +1442,6 @@
m.set_loading_sound_stream_id(handler_id);
}
-void
-define_video_loader(SWFStream& in, tag_type tag, movie_definition& m,
- const RunInfo& /*r*/)
-{
- assert(tag == SWF::DEFINEVIDEOSTREAM); // 60
-
- in.ensureBytes(2);
- boost::uint16_t character_id = in.read_u16();
-
- std::auto_ptr<video_stream_definition> chdef (
- new video_stream_definition(character_id));
-
- chdef->readDefineVideoStream(in, tag, m);
-
- m.add_character(character_id, chdef.release());
-
-}
-
-void
-video_loader(SWFStream& in, tag_type tag, movie_definition& m,
- const RunInfo& /*r*/)
-{
- assert(tag == SWF::VIDEOFRAME); // 61
-
- in.ensureBytes(2);
- boost::uint16_t character_id = in.read_u16();
- character_def* chdef = m.get_character_def(character_id);
-
- if (!chdef)
- {
- IF_VERBOSE_MALFORMED_SWF(
- log_swferror(_("VideoFrame tag refers to unknown video stream id %d"),
character_id);
- );
- return;
- }
-
- // TODO: add a character_def::cast_to_video_def ?
- video_stream_definition* vdef = dynamic_cast<video_stream_definition*>
(chdef);
- if ( ! vdef )
- {
- IF_VERBOSE_MALFORMED_SWF(
- log_swferror(_("VideoFrame tag refers to a non-video character %d
(%s)"), character_id, typeName(*chdef));
- );
- return;
- }
-
- vdef->readDefineVideoFrame(in, tag, m);
-}
void
file_attributes_loader(SWFStream& in, tag_type tag, movie_definition& /*m*/,
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Gnash-commit] /srv/bzr/gnash/trunk r10236: Further reduce the libcore/parser directory.,
Benjamin Wolsey <=